accelerate 1.1.1.0 → 1.4.0.0
raw patch · 518 files changed
Files
- CHANGELOG.md +132/−6
- Data/Array/Accelerate.hs +0/−534
- Data/Array/Accelerate/AST.hs +0/−1893
- Data/Array/Accelerate/Analysis/Hash.hs +0/−506
- Data/Array/Accelerate/Analysis/Hash/TH.hs +0/−30
- Data/Array/Accelerate/Analysis/Match.hs +0/−934
- Data/Array/Accelerate/Analysis/Shape.hs +0/−124
- Data/Array/Accelerate/Analysis/Stencil.hs +0/−91
- Data/Array/Accelerate/Analysis/Type.hs +0/−204
- Data/Array/Accelerate/Array/Data.hs +0/−810
- Data/Array/Accelerate/Array/Lifted.hs +0/−283
- Data/Array/Accelerate/Array/Remote.hs +0/−26
- Data/Array/Accelerate/Array/Remote/Class.hs +0/−81
- Data/Array/Accelerate/Array/Remote/LRU.hs +0/−405
- Data/Array/Accelerate/Array/Remote/Nursery.hs +0/−127
- Data/Array/Accelerate/Array/Remote/Table.hs +0/−469
- Data/Array/Accelerate/Array/Representation.hs +0/−235
- Data/Array/Accelerate/Array/Sugar.hs +0/−1294
- Data/Array/Accelerate/Array/Unique.hs +0/−98
- Data/Array/Accelerate/Async.hs +0/−103
- Data/Array/Accelerate/Classes.hs +0/−52
- Data/Array/Accelerate/Classes/Bounded.hs +0/−214
- Data/Array/Accelerate/Classes/Enum.hs +0/−71
- Data/Array/Accelerate/Classes/Eq.hs +0/−304
- Data/Array/Accelerate/Classes/Floating.hs +0/−123
- Data/Array/Accelerate/Classes/Fractional.hs +0/−55
- Data/Array/Accelerate/Classes/FromIntegral.hs +0/−86
- Data/Array/Accelerate/Classes/Integral.hs +0/−204
- Data/Array/Accelerate/Classes/Num.hs +0/−245
- Data/Array/Accelerate/Classes/Ord.hs +0/−493
- Data/Array/Accelerate/Classes/Real.hs +0/−41
- Data/Array/Accelerate/Classes/RealFloat.hs +0/−328
- Data/Array/Accelerate/Classes/RealFrac.hs +0/−166
- Data/Array/Accelerate/Classes/ToFloating.hs +0/−82
- Data/Array/Accelerate/Data/Bits.hs +0/−806
- Data/Array/Accelerate/Data/Complex.hs +0/−202
- Data/Array/Accelerate/Data/Fold.hs +0/−155
- Data/Array/Accelerate/Data/Monoid.hs +0/−172
- Data/Array/Accelerate/Debug.hs +0/−120
- Data/Array/Accelerate/Debug/Flags.hs +0/−343
- Data/Array/Accelerate/Debug/Monitoring.hs +0/−459
- Data/Array/Accelerate/Debug/Stats.hs +0/−210
- Data/Array/Accelerate/Debug/Timed.hs +0/−134
- Data/Array/Accelerate/Debug/Trace.hs +0/−137
- Data/Array/Accelerate/Error.hs +0/−165
- Data/Array/Accelerate/FullList.hs +0/−119
- Data/Array/Accelerate/Interpreter.hs +0/−1875
- Data/Array/Accelerate/Language.hs +0/−1373
- Data/Array/Accelerate/Lifetime.hs +0/−161
- Data/Array/Accelerate/Lift.hs +0/−747
- Data/Array/Accelerate/Prelude.hs +0/−2113
- Data/Array/Accelerate/Pretty.hs +0/−93
- Data/Array/Accelerate/Pretty/Graphviz.hs +0/−557
- Data/Array/Accelerate/Pretty/Graphviz/Monad.hs +0/−74
- Data/Array/Accelerate/Pretty/Graphviz/Type.hs +0/−154
- Data/Array/Accelerate/Pretty/Print.hs +0/−620
- Data/Array/Accelerate/Product.hs +0/−177
- Data/Array/Accelerate/Smart.hs +0/−2129
- Data/Array/Accelerate/Trafo.hs +0/−242
- Data/Array/Accelerate/Trafo/Algebra.hs +0/−740
- Data/Array/Accelerate/Trafo/Base.hs +0/−405
- Data/Array/Accelerate/Trafo/Fusion.hs +0/−1559
- Data/Array/Accelerate/Trafo/Rewrite.hs +0/−152
- Data/Array/Accelerate/Trafo/Sharing.hs +0/−2919
- Data/Array/Accelerate/Trafo/Shrink.hs +0/−481
- Data/Array/Accelerate/Trafo/Simplify.hs +0/−701
- Data/Array/Accelerate/Trafo/Substitution.hs +0/−597
- Data/Array/Accelerate/Type.hs +0/−712
- Data/Atomic.hs +0/−60
- LICENSE +3/−3
- README.md +95/−32
- Setup.hs +139/−1
- accelerate.cabal +520/−157
- app/Main.hs +23/−0
- cbits/align.h +24/−0
- cbits/atomic.c +31/−3
- cbits/clock.c +145/−0
- cbits/flags.c +428/−0
- cbits/flags.h +52/−0
- cbits/getopt.h +80/−0
- cbits/getopt_long.c +642/−0
- cbits/monitoring.c +137/−0
- cbits/tracy/capture/CMakeLists.txt +28/−0
- cbits/tracy/capture/src/capture.cpp +364/−0
- cbits/tracy/cmake/CPM.cmake +1269/−0
- cbits/tracy/cmake/ECMFindModuleHelpers.cmake +300/−0
- cbits/tracy/cmake/FindWaylandScanner.cmake +170/−0
- cbits/tracy/cmake/config.cmake +62/−0
- cbits/tracy/cmake/gl3w-extra-symbols.patch +12/−0
- cbits/tracy/cmake/imgui-emscripten.patch +14/−0
- cbits/tracy/cmake/imgui-loader.patch +56/−0
- cbits/tracy/cmake/ppqsort-nodebug.patch +14/−0
- cbits/tracy/cmake/server.cmake +35/−0
- cbits/tracy/cmake/vendor.cmake +193/−0
- cbits/tracy/cmake/version.cmake +24/−0
- cbits/tracy/dtl/Diff.hpp +706/−0
- cbits/tracy/dtl/Diff3.hpp +245/−0
- cbits/tracy/dtl/Lcs.hpp +55/−0
- cbits/tracy/dtl/Sequence.hpp +65/−0
- cbits/tracy/dtl/Ses.hpp +132/−0
- cbits/tracy/dtl/dtl.hpp +47/−0
- cbits/tracy/dtl/functors.hpp +151/−0
- cbits/tracy/dtl/variables.hpp +142/−0
- cbits/tracy/getopt/getopt.c +239/−0
- cbits/tracy/getopt/getopt.h +59/−0
- cbits/tracy/profiler/CMakeLists.txt +233/−0
- cbits/tracy/profiler/src/Backend.hpp +34/−0
- cbits/tracy/profiler/src/BackendEmscripten.cpp +341/−0
- cbits/tracy/profiler/src/BackendGlfw.cpp +216/−0
- cbits/tracy/profiler/src/BackendWayland.cpp +1319/−0
- cbits/tracy/profiler/src/ConnectionHistory.cpp +87/−0
- cbits/tracy/profiler/src/ConnectionHistory.hpp +32/−0
- cbits/tracy/profiler/src/Filters.cpp +87/−0
- cbits/tracy/profiler/src/Filters.hpp +28/−0
- cbits/tracy/profiler/src/Fonts.cpp +59/−0
- cbits/tracy/profiler/src/Fonts.hpp +12/−0
- cbits/tracy/profiler/src/HttpRequest.cpp +134/−0
- cbits/tracy/profiler/src/HttpRequest.hpp +8/−0
- cbits/tracy/profiler/src/ImGuiContext.cpp +20/−0
- cbits/tracy/profiler/src/ImGuiContext.hpp +16/−0
- cbits/tracy/profiler/src/IsElevated.cpp +41/−0
- cbits/tracy/profiler/src/IsElevated.hpp +6/−0
- cbits/tracy/profiler/src/ResolvService.cpp +65/−0
- cbits/tracy/profiler/src/ResolvService.hpp +38/−0
- cbits/tracy/profiler/src/RunQueue.cpp +31/−0
- cbits/tracy/profiler/src/RunQueue.hpp +23/−0
- cbits/tracy/profiler/src/WindowPosition.cpp +48/−0
- cbits/tracy/profiler/src/WindowPosition.hpp +20/−0
- cbits/tracy/profiler/src/font/DroidSans.hpp +2821/−0
- cbits/tracy/profiler/src/font/FiraCodeRetina.hpp +3995/−0
- cbits/tracy/profiler/src/font/FontAwesomeSolid.hpp +12368/−0
- cbits/tracy/profiler/src/icon.hpp +25/−0
- cbits/tracy/profiler/src/ini.c +274/−0
- cbits/tracy/profiler/src/ini.h +28/−0
- cbits/tracy/profiler/src/main.cpp +1591/−0
- cbits/tracy/profiler/src/profiler/IconsFontAwesome6.h +1400/−0
- cbits/tracy/profiler/src/profiler/TracyAchievementData.cpp +202/−0
- cbits/tracy/profiler/src/profiler/TracyAchievements.cpp +225/−0
- cbits/tracy/profiler/src/profiler/TracyAchievements.hpp +82/−0
- cbits/tracy/profiler/src/profiler/TracyBadVersion.cpp +124/−0
- cbits/tracy/profiler/src/profiler/TracyBadVersion.hpp +39/−0
- cbits/tracy/profiler/src/profiler/TracyBuzzAnim.hpp +50/−0
- cbits/tracy/profiler/src/profiler/TracyColor.cpp +36/−0
- cbits/tracy/profiler/src/profiler/TracyColor.hpp +57/−0
- cbits/tracy/profiler/src/profiler/TracyConfig.hpp +29/−0
- cbits/tracy/profiler/src/profiler/TracyDecayValue.hpp +48/−0
- cbits/tracy/profiler/src/profiler/TracyEventDebug.cpp +361/−0
- cbits/tracy/profiler/src/profiler/TracyEventDebug.hpp +10/−0
- cbits/tracy/profiler/src/profiler/TracyFileselector.cpp +126/−0
- cbits/tracy/profiler/src/profiler/TracyFileselector.hpp +18/−0
- cbits/tracy/profiler/src/profiler/TracyFilesystem.cpp +19/−0
- cbits/tracy/profiler/src/profiler/TracyFilesystem.hpp +23/−0
- cbits/tracy/profiler/src/profiler/TracyImGui.cpp +130/−0
- cbits/tracy/profiler/src/profiler/TracyImGui.hpp +278/−0
- cbits/tracy/profiler/src/profiler/TracyLockHelpers.hpp +28/−0
- cbits/tracy/profiler/src/profiler/TracyMicroArchitecture.cpp too large to diff
- cbits/tracy/profiler/src/profiler/TracyMicroArchitecture.hpp +46/−0
- cbits/tracy/profiler/src/profiler/TracyMouse.cpp +90/−0
- cbits/tracy/profiler/src/profiler/TracyMouse.hpp +21/−0
- cbits/tracy/profiler/src/profiler/TracyProtoHistory.cpp +31/−0
- cbits/tracy/profiler/src/profiler/TracyProtoHistory.hpp +20/−0
- cbits/tracy/profiler/src/profiler/TracySourceContents.cpp +106/−0
- cbits/tracy/profiler/src/profiler/TracySourceContents.hpp +51/−0
- cbits/tracy/profiler/src/profiler/TracySourceTokenizer.cpp +421/−0
- cbits/tracy/profiler/src/profiler/TracySourceTokenizer.hpp +72/−0
- cbits/tracy/profiler/src/profiler/TracySourceView.cpp +5753/−0
- cbits/tracy/profiler/src/profiler/TracySourceView.hpp +305/−0
- cbits/tracy/profiler/src/profiler/TracyStorage.cpp +211/−0
- cbits/tracy/profiler/src/profiler/TracyStorage.hpp +14/−0
- cbits/tracy/profiler/src/profiler/TracyTexture.cpp +187/−0
- cbits/tracy/profiler/src/profiler/TracyTexture.hpp +19/−0
- cbits/tracy/profiler/src/profiler/TracyTimelineContext.hpp +23/−0
- cbits/tracy/profiler/src/profiler/TracyTimelineController.cpp +177/−0
- cbits/tracy/profiler/src/profiler/TracyTimelineController.hpp +71/−0
- cbits/tracy/profiler/src/profiler/TracyTimelineDraw.hpp +105/−0
- cbits/tracy/profiler/src/profiler/TracyTimelineItem.cpp +168/−0
- cbits/tracy/profiler/src/profiler/TracyTimelineItem.hpp +77/−0
- cbits/tracy/profiler/src/profiler/TracyTimelineItemCpuData.cpp +259/−0
- cbits/tracy/profiler/src/profiler/TracyTimelineItemCpuData.hpp +47/−0
- cbits/tracy/profiler/src/profiler/TracyTimelineItemGpu.cpp +198/−0
- cbits/tracy/profiler/src/profiler/TracyTimelineItemGpu.hpp +40/−0
- cbits/tracy/profiler/src/profiler/TracyTimelineItemPlot.cpp +252/−0
- cbits/tracy/profiler/src/profiler/TracyTimelineItemPlot.hpp +44/−0
- cbits/tracy/profiler/src/profiler/TracyTimelineItemThread.cpp +1046/−0
- cbits/tracy/profiler/src/profiler/TracyTimelineItemThread.hpp +67/−0
- cbits/tracy/profiler/src/profiler/TracyUserData.cpp +389/−0
- cbits/tracy/profiler/src/profiler/TracyUserData.hpp +55/−0
- cbits/tracy/profiler/src/profiler/TracyUtility.cpp +190/−0
- cbits/tracy/profiler/src/profiler/TracyUtility.hpp +34/−0
- cbits/tracy/profiler/src/profiler/TracyView.cpp +1465/−0
- cbits/tracy/profiler/src/profiler/TracyView.hpp +943/−0
- cbits/tracy/profiler/src/profiler/TracyViewData.hpp +82/−0
- cbits/tracy/profiler/src/profiler/TracyView_Annotations.cpp +158/−0
- cbits/tracy/profiler/src/profiler/TracyView_Callstack.cpp +578/−0
- cbits/tracy/profiler/src/profiler/TracyView_Compare.cpp +1331/−0
- cbits/tracy/profiler/src/profiler/TracyView_ConnectionState.cpp +249/−0
- cbits/tracy/profiler/src/profiler/TracyView_ContextSwitch.cpp +632/−0
- cbits/tracy/profiler/src/profiler/TracyView_CpuData.cpp +889/−0
- cbits/tracy/profiler/src/profiler/TracyView_FindZone.cpp +2036/−0
- cbits/tracy/profiler/src/profiler/TracyView_FlameGraph.cpp +967/−0
- cbits/tracy/profiler/src/profiler/TracyView_FrameOverview.cpp +452/−0
- cbits/tracy/profiler/src/profiler/TracyView_FrameTimeline.cpp +336/−0
- cbits/tracy/profiler/src/profiler/TracyView_FrameTree.cpp +875/−0
- cbits/tracy/profiler/src/profiler/TracyView_GpuTimeline.cpp +368/−0
- cbits/tracy/profiler/src/profiler/TracyView_Locks.cpp +660/−0
- cbits/tracy/profiler/src/profiler/TracyView_Memory.cpp +931/−0
- cbits/tracy/profiler/src/profiler/TracyView_Messages.cpp +336/−0
- cbits/tracy/profiler/src/profiler/TracyView_Navigation.cpp +152/−0
- cbits/tracy/profiler/src/profiler/TracyView_NotificationArea.cpp +272/−0
- cbits/tracy/profiler/src/profiler/TracyView_Options.cpp +829/−0
- cbits/tracy/profiler/src/profiler/TracyView_Playback.cpp +218/−0
- cbits/tracy/profiler/src/profiler/TracyView_Plots.cpp +386/−0
- cbits/tracy/profiler/src/profiler/TracyView_Ranges.cpp +178/−0
- cbits/tracy/profiler/src/profiler/TracyView_Samples.cpp +1275/−0
- cbits/tracy/profiler/src/profiler/TracyView_Statistics.cpp +986/−0
- cbits/tracy/profiler/src/profiler/TracyView_Timeline.cpp +561/−0
- cbits/tracy/profiler/src/profiler/TracyView_TraceInfo.cpp +978/−0
- cbits/tracy/profiler/src/profiler/TracyView_Utility.cpp +936/−0
- cbits/tracy/profiler/src/profiler/TracyView_ZoneInfo.cpp +2052/−0
- cbits/tracy/profiler/src/profiler/TracyView_ZoneTimeline.cpp +617/−0
- cbits/tracy/profiler/src/profiler/TracyWeb.cpp +33/−0
- cbits/tracy/profiler/src/profiler/TracyWeb.hpp +11/−0
- cbits/tracy/profiler/src/stb_image.h +7985/−0
- cbits/tracy/profiler/src/stb_image_resize.h +2634/−0
- cbits/tracy/profiler/src/winmain.cpp +48/−0
- cbits/tracy/profiler/src/winmainArchDiscovery.cpp +22/−0
- cbits/tracy/profiler/src/zigzag01.hpp +10/−0
- cbits/tracy/profiler/src/zigzag02.hpp +10/−0
- cbits/tracy/profiler/src/zigzag04.hpp +11/−0
- cbits/tracy/profiler/src/zigzag08.hpp +11/−0
- cbits/tracy/profiler/src/zigzag16.hpp +12/−0
- cbits/tracy/profiler/src/zigzag32.hpp +13/−0
- cbits/tracy/public/TracyClient.cpp +61/−0
- cbits/tracy/public/client/TracyAlloc.cpp +43/−0
- cbits/tracy/public/client/TracyArmCpuTable.hpp +419/−0
- cbits/tracy/public/client/TracyCallstack.cpp +1420/−0
- cbits/tracy/public/client/TracyCallstack.h +35/−0
- cbits/tracy/public/client/TracyCallstack.hpp +155/−0
- cbits/tracy/public/client/TracyCpuid.hpp +12/−0
- cbits/tracy/public/client/TracyDebug.hpp +11/−0
- cbits/tracy/public/client/TracyDxt1.cpp +644/−0
- cbits/tracy/public/client/TracyDxt1.hpp +11/−0
- cbits/tracy/public/client/TracyFastVector.hpp +118/−0
- cbits/tracy/public/client/TracyKCore.cpp +121/−0
- cbits/tracy/public/client/TracyKCore.hpp +37/−0
- cbits/tracy/public/client/TracyLock.hpp +546/−0
- cbits/tracy/public/client/TracyOverride.cpp +26/−0
- cbits/tracy/public/client/TracyProfiler.cpp +5007/−0
- cbits/tracy/public/client/TracyProfiler.hpp +1089/−0
- cbits/tracy/public/client/TracyRingBuffer.hpp +141/−0
- cbits/tracy/public/client/TracyScoped.hpp +201/−0
- cbits/tracy/public/client/TracyStringHelpers.hpp +41/−0
- cbits/tracy/public/client/TracySysPower.cpp +164/−0
- cbits/tracy/public/client/TracySysPower.hpp +44/−0
- cbits/tracy/public/client/TracySysTime.cpp +108/−0
- cbits/tracy/public/client/TracySysTime.hpp +36/−0
- cbits/tracy/public/client/TracySysTrace.cpp +1646/−0
- cbits/tracy/public/client/TracySysTrace.hpp +28/−0
- cbits/tracy/public/client/TracyThread.hpp +90/−0
- cbits/tracy/public/client/tracy_SPSCQueue.h +148/−0
- cbits/tracy/public/client/tracy_concurrentqueue.h +1441/−0
- cbits/tracy/public/client/tracy_rpmalloc.cpp +3519/−0
- cbits/tracy/public/client/tracy_rpmalloc.hpp +363/−0
- cbits/tracy/public/common/TracyAlign.hpp +27/−0
- cbits/tracy/public/common/TracyAlloc.hpp +72/−0
- cbits/tracy/public/common/TracyApi.h +16/−0
- cbits/tracy/public/common/TracyColor.hpp +690/−0
- cbits/tracy/public/common/TracyForceInline.hpp +20/−0
- cbits/tracy/public/common/TracyMutex.hpp +24/−0
- cbits/tracy/public/common/TracyProtocol.hpp +169/−0
- cbits/tracy/public/common/TracyQueue.hpp +926/−0
- cbits/tracy/public/common/TracySocket.cpp +752/−0
- cbits/tracy/public/common/TracySocket.hpp +155/−0
- cbits/tracy/public/common/TracyStackFrames.cpp +122/−0
- cbits/tracy/public/common/TracyStackFrames.hpp +22/−0
- cbits/tracy/public/common/TracySystem.cpp +349/−0
- cbits/tracy/public/common/TracySystem.hpp +43/−0
- cbits/tracy/public/common/TracyUwp.hpp +11/−0
- cbits/tracy/public/common/TracyVersion.hpp +14/−0
- cbits/tracy/public/common/TracyYield.hpp +28/−0
- cbits/tracy/public/common/tracy_lz4.cpp +2720/−0
- cbits/tracy/public/common/tracy_lz4.hpp +847/−0
- cbits/tracy/public/common/tracy_lz4hc.cpp +1636/−0
- cbits/tracy/public/common/tracy_lz4hc.hpp +405/−0
- cbits/tracy/public/libbacktrace/alloc.cpp +174/−0
- cbits/tracy/public/libbacktrace/backtrace.hpp +186/−0
- cbits/tracy/public/libbacktrace/config.h +26/−0
- cbits/tracy/public/libbacktrace/dwarf.cpp +4455/−0
- cbits/tracy/public/libbacktrace/elf.cpp +7605/−0
- cbits/tracy/public/libbacktrace/fileline.cpp +412/−0
- cbits/tracy/public/libbacktrace/filenames.hpp +52/−0
- cbits/tracy/public/libbacktrace/internal.hpp +435/−0
- cbits/tracy/public/libbacktrace/macho.cpp +1367/−0
- cbits/tracy/public/libbacktrace/mmapio.cpp +115/−0
- cbits/tracy/public/libbacktrace/posix.cpp +109/−0
- cbits/tracy/public/libbacktrace/sort.cpp +113/−0
- cbits/tracy/public/libbacktrace/state.cpp +76/−0
- cbits/tracy/public/tracy/Tracy.hpp +254/−0
- cbits/tracy/public/tracy/TracyC.h +384/−0
- cbits/tracy/public/tracy/TracyCUDA.hpp +1325/−0
- cbits/tracy/public/tracy/TracyD3D11.hpp +466/−0
- cbits/tracy/public/tracy/TracyD3D12.hpp +500/−0
- cbits/tracy/public/tracy/TracyLua.hpp +486/−0
- cbits/tracy/public/tracy/TracyOpenCL.hpp +414/−0
- cbits/tracy/public/tracy/TracyOpenGL.hpp +325/−0
- cbits/tracy/public/tracy/TracyVulkan.hpp +741/−0
- cbits/tracy/server/TracyCharUtil.hpp +76/−0
- cbits/tracy/server/TracyEvent.hpp +921/−0
- cbits/tracy/server/TracyFileHeader.hpp +22/−0
- cbits/tracy/server/TracyFileMeta.hpp +18/−0
- cbits/tracy/server/TracyFileRead.hpp +600/−0
- cbits/tracy/server/TracyFileWrite.hpp +303/−0
- cbits/tracy/server/TracyMemory.cpp +8/−0
- cbits/tracy/server/TracyMemory.hpp +14/−0
- cbits/tracy/server/TracyMmap.cpp +38/−0
- cbits/tracy/server/TracyMmap.hpp +19/−0
- cbits/tracy/server/TracyPopcnt.hpp +40/−0
- cbits/tracy/server/TracyPrint.cpp +464/−0
- cbits/tracy/server/TracyPrint.hpp +152/−0
- cbits/tracy/server/TracyShortPtr.hpp +82/−0
- cbits/tracy/server/TracySlab.hpp +159/−0
- cbits/tracy/server/TracySort.hpp +10/−0
- cbits/tracy/server/TracySortedVector.hpp +127/−0
- cbits/tracy/server/TracyStringDiscovery.hpp +88/−0
- cbits/tracy/server/TracySysUtil.cpp +43/−0
- cbits/tracy/server/TracySysUtil.hpp +13/−0
- cbits/tracy/server/TracyTaskDispatch.cpp +88/−0
- cbits/tracy/server/TracyTaskDispatch.hpp +40/−0
- cbits/tracy/server/TracyTextureCompression.cpp +211/−0
- cbits/tracy/server/TracyTextureCompression.hpp +64/−0
- cbits/tracy/server/TracyThreadCompress.cpp +72/−0
- cbits/tracy/server/TracyThreadCompress.hpp +61/−0
- cbits/tracy/server/TracyVarArray.hpp +97/−0
- cbits/tracy/server/TracyVector.hpp +357/−0
- cbits/tracy/server/TracyWorker.cpp +8681/−0
- cbits/tracy/server/TracyWorker.hpp +1112/−0
- cbits/tracy/server/tracy_pdqsort.h +524/−0
- cbits/tracy/server/tracy_robin_hood.h +2538/−0
- cbits/tracy/server/tracy_xxhash.h +6773/−0
- cbits/xkcp/KeccakHash.c +81/−0
- cbits/xkcp/KeccakHash.h +125/−0
- cbits/xkcp/KeccakP-1600-64.macros +748/−0
- cbits/xkcp/KeccakP-1600-SnP.h +54/−0
- cbits/xkcp/KeccakP-1600-opt64-config.h +6/−0
- cbits/xkcp/KeccakP-1600-opt64.c +565/−0
- cbits/xkcp/KeccakP-1600-unrolling.macros +305/−0
- cbits/xkcp/KeccakSponge.c +111/−0
- cbits/xkcp/KeccakSponge.h +76/−0
- cbits/xkcp/KeccakSponge.inc +314/−0
- cbits/xkcp/SimpleFIPS202.c +48/−0
- cbits/xkcp/SimpleFIPS202.h +79/−0
- cbits/xkcp/SnP-Relaned.h +141/−0
- cbits/xkcp/align.h +33/−0
- cbits/xkcp/brg_endian.h +143/−0
- cbits/xkcp/config.h +5/−0
- cbits/xkcp/test.c +10/−0
- images/accelerate-logo-text-v.png binary
- images/fusion_example_1.png binary
- images/fusion_example_2.png binary
- images/fusion_example_3.png binary
- src/Crypto/Hash/XKCP.hs +184/−0
- src/Data/Array/Accelerate.hs +691/−0
- src/Data/Array/Accelerate/AST.hs +1457/−0
- src/Data/Array/Accelerate/AST/Environment.hs +91/−0
- src/Data/Array/Accelerate/AST/Idx.hs +119/−0
- src/Data/Array/Accelerate/AST/LeftHandSide.hs +67/−0
- src/Data/Array/Accelerate/AST/Var.hs +44/−0
- src/Data/Array/Accelerate/Analysis/Hash.hs +506/−0
- src/Data/Array/Accelerate/Analysis/Hash/TH.hs +30/−0
- src/Data/Array/Accelerate/Analysis/Match.hs +917/−0
- src/Data/Array/Accelerate/Array/Data.hs +408/−0
- src/Data/Array/Accelerate/Array/Remote.hs +25/−0
- src/Data/Array/Accelerate/Array/Remote/Class.hs +74/−0
- src/Data/Array/Accelerate/Array/Remote/LRU.hs +450/−0
- src/Data/Array/Accelerate/Array/Remote/Nursery.hs +122/−0
- src/Data/Array/Accelerate/Array/Remote/Table.hs +430/−0
- src/Data/Array/Accelerate/Array/Unique.hs +135/−0
- src/Data/Array/Accelerate/Async.hs +111/−0
- src/Data/Array/Accelerate/Classes/Bounded.hs +154/−0
- src/Data/Array/Accelerate/Classes/Enum.hs +195/−0
- src/Data/Array/Accelerate/Classes/Eq.hs +217/−0
- src/Data/Array/Accelerate/Classes/Floating.hs +145/−0
- src/Data/Array/Accelerate/Classes/Fractional.hs +72/−0
- src/Data/Array/Accelerate/Classes/FromIntegral.hs +85/−0
- src/Data/Array/Accelerate/Classes/Integral.hs +207/−0
- src/Data/Array/Accelerate/Classes/Num.hs +275/−0
- src/Data/Array/Accelerate/Classes/Ord.hs +249/−0
- src/Data/Array/Accelerate/Classes/Rational.hs +98/−0
- src/Data/Array/Accelerate/Classes/Real.hs +48/−0
- src/Data/Array/Accelerate/Classes/RealFloat.hs +411/−0
- src/Data/Array/Accelerate/Classes/RealFloat.hs-boot +67/−0
- src/Data/Array/Accelerate/Classes/RealFrac.hs +278/−0
- src/Data/Array/Accelerate/Classes/RealFrac.hs-boot +43/−0
- src/Data/Array/Accelerate/Classes/ToFloating.hs +80/−0
- src/Data/Array/Accelerate/Control/Monad.hs +221/−0
- src/Data/Array/Accelerate/Data/Bits.hs +830/−0
- src/Data/Array/Accelerate/Data/Complex.hs +366/−0
- src/Data/Array/Accelerate/Data/Either.hs +142/−0
- src/Data/Array/Accelerate/Data/Fold.hs +162/−0
- src/Data/Array/Accelerate/Data/Functor.hs +95/−0
- src/Data/Array/Accelerate/Data/Maybe.hs +145/−0
- src/Data/Array/Accelerate/Data/Monoid.hs +195/−0
- src/Data/Array/Accelerate/Data/Ratio.hs +141/−0
- src/Data/Array/Accelerate/Data/Semigroup.hs +171/−0
- src/Data/Array/Accelerate/Debug/Internal.hs +77/−0
- src/Data/Array/Accelerate/Debug/Internal/Clock.hs +42/−0
- src/Data/Array/Accelerate/Debug/Internal/Flags.hs +246/−0
- src/Data/Array/Accelerate/Debug/Internal/Graph.hs +72/−0
- src/Data/Array/Accelerate/Debug/Internal/Profile.hs +189/−0
- src/Data/Array/Accelerate/Debug/Internal/Stats.hs +253/−0
- src/Data/Array/Accelerate/Debug/Internal/Timed.hs +140/−0
- src/Data/Array/Accelerate/Debug/Internal/Trace.hs +183/−0
- src/Data/Array/Accelerate/Debug/Internal/Tracy.hs +176/−0
- src/Data/Array/Accelerate/Debug/Trace.hs +90/−0
- src/Data/Array/Accelerate/Error.hs +154/−0
- src/Data/Array/Accelerate/Interpreter.hs +1869/−0
- src/Data/Array/Accelerate/Language.hs +1517/−0
- src/Data/Array/Accelerate/Lifetime.hs +156/−0
- src/Data/Array/Accelerate/Lift.hs +358/−0
- src/Data/Array/Accelerate/Orphans.hs +52/−0
- src/Data/Array/Accelerate/Pattern.hs +308/−0
- src/Data/Array/Accelerate/Pattern/Bool.hs +26/−0
- src/Data/Array/Accelerate/Pattern/Either.hs +26/−0
- src/Data/Array/Accelerate/Pattern/Maybe.hs +26/−0
- src/Data/Array/Accelerate/Pattern/Ordering.hs +26/−0
- src/Data/Array/Accelerate/Pattern/TH.hs +450/−0
- src/Data/Array/Accelerate/Prelude.hs +2631/−0
- src/Data/Array/Accelerate/Pretty.hs +202/−0
- src/Data/Array/Accelerate/Pretty/Graphviz.hs +540/−0
- src/Data/Array/Accelerate/Pretty/Graphviz/Monad.hs +74/−0
- src/Data/Array/Accelerate/Pretty/Graphviz/Type.hs +154/−0
- src/Data/Array/Accelerate/Pretty/Print.hs +775/−0
- src/Data/Array/Accelerate/Representation/Array.hs +323/−0
- src/Data/Array/Accelerate/Representation/Elt.hs +160/−0
- src/Data/Array/Accelerate/Representation/Shape.hs +197/−0
- src/Data/Array/Accelerate/Representation/Slice.hs +112/−0
- src/Data/Array/Accelerate/Representation/Stencil.hs +161/−0
- src/Data/Array/Accelerate/Representation/Tag.hs +68/−0
- src/Data/Array/Accelerate/Representation/Type.hs +126/−0
- src/Data/Array/Accelerate/Representation/Vec.hs +95/−0
- src/Data/Array/Accelerate/Smart.hs +1398/−0
- src/Data/Array/Accelerate/Sugar/Array.hs +321/−0
- src/Data/Array/Accelerate/Sugar/Elt.hs +471/−0
- src/Data/Array/Accelerate/Sugar/Foreign.hs +38/−0
- src/Data/Array/Accelerate/Sugar/Shape.hs +379/−0
- src/Data/Array/Accelerate/Sugar/Vec.hs +40/−0
- src/Data/Array/Accelerate/Test/NoFib.hs +67/−0
- src/Data/Array/Accelerate/Test/NoFib/Base.hs +149/−0
- src/Data/Array/Accelerate/Test/NoFib/Config.hs +172/−0
- src/Data/Array/Accelerate/Test/NoFib/Imaginary.hs +37/−0
- src/Data/Array/Accelerate/Test/NoFib/Imaginary/DotP.hs +83/−0
- src/Data/Array/Accelerate/Test/NoFib/Imaginary/SASUM.hs +79/−0
- src/Data/Array/Accelerate/Test/NoFib/Imaginary/SAXPY.hs +88/−0
- src/Data/Array/Accelerate/Test/NoFib/Issues.hs +106/−0
- src/Data/Array/Accelerate/Test/NoFib/Issues/Issue102.hs +71/−0
- src/Data/Array/Accelerate/Test/NoFib/Issues/Issue114.hs +85/−0
- src/Data/Array/Accelerate/Test/NoFib/Issues/Issue119.hs +183/−0
- src/Data/Array/Accelerate/Test/NoFib/Issues/Issue123.hs +39/−0
- src/Data/Array/Accelerate/Test/NoFib/Issues/Issue137.hs +56/−0
- src/Data/Array/Accelerate/Test/NoFib/Issues/Issue168.hs +70/−0
- src/Data/Array/Accelerate/Test/NoFib/Issues/Issue184.hs +67/−0
- src/Data/Array/Accelerate/Test/NoFib/Issues/Issue185.hs +149/−0
- src/Data/Array/Accelerate/Test/NoFib/Issues/Issue187.hs +57/−0
- src/Data/Array/Accelerate/Test/NoFib/Issues/Issue228.hs +68/−0
- src/Data/Array/Accelerate/Test/NoFib/Issues/Issue255.hs +105/−0
- src/Data/Array/Accelerate/Test/NoFib/Issues/Issue264.hs +148/−0
- src/Data/Array/Accelerate/Test/NoFib/Issues/Issue287.hs +102/−0
- src/Data/Array/Accelerate/Test/NoFib/Issues/Issue288.hs +38/−0
- src/Data/Array/Accelerate/Test/NoFib/Issues/Issue362.hs +62/−0
- src/Data/Array/Accelerate/Test/NoFib/Issues/Issue364.hs +99/−0
- src/Data/Array/Accelerate/Test/NoFib/Issues/Issue407.hs +57/−0
- src/Data/Array/Accelerate/Test/NoFib/Issues/Issue409.hs +61/−0
- src/Data/Array/Accelerate/Test/NoFib/Issues/Issue427.hs +89/−0
- src/Data/Array/Accelerate/Test/NoFib/Issues/Issue436.hs +59/−0
- src/Data/Array/Accelerate/Test/NoFib/Issues/Issue437.hs +90/−0
- src/Data/Array/Accelerate/Test/NoFib/Issues/Issue439.hs +37/−0
- src/Data/Array/Accelerate/Test/NoFib/Issues/Issue517.hs +45/−0
- src/Data/Array/Accelerate/Test/NoFib/Issues/Issue551.hs +83/−0
- src/Data/Array/Accelerate/Test/NoFib/Issues/Issue93.hs +38/−0
- src/Data/Array/Accelerate/Test/NoFib/Misc.hs +28/−0
- src/Data/Array/Accelerate/Test/NoFib/Misc/Cache.hs +73/−0
- src/Data/Array/Accelerate/Test/NoFib/Misc/Scanl1.hs +39/−0
- src/Data/Array/Accelerate/Test/NoFib/Prelude.hs +69/−0
- src/Data/Array/Accelerate/Test/NoFib/Prelude/Backpermute.hs +166/−0
- src/Data/Array/Accelerate/Test/NoFib/Prelude/Filter.hs +137/−0
- src/Data/Array/Accelerate/Test/NoFib/Prelude/Fold.hs +325/−0
- src/Data/Array/Accelerate/Test/NoFib/Prelude/Map.hs +485/−0
- src/Data/Array/Accelerate/Test/NoFib/Prelude/Permute.hs +180/−0
- src/Data/Array/Accelerate/Test/NoFib/Prelude/SIMD.hs +243/−0
- src/Data/Array/Accelerate/Test/NoFib/Prelude/Scan.hs +947/−0
- src/Data/Array/Accelerate/Test/NoFib/Prelude/Stencil.hs +670/−0
- src/Data/Array/Accelerate/Test/NoFib/Prelude/ZipWith.hs +630/−0
- src/Data/Array/Accelerate/Test/NoFib/Sharing.hs +334/−0
- src/Data/Array/Accelerate/Test/NoFib/Spectral.hs +37/−0
- src/Data/Array/Accelerate/Test/NoFib/Spectral/BlackScholes.hs +131/−0
- src/Data/Array/Accelerate/Test/NoFib/Spectral/RadixSort.hs +187/−0
- src/Data/Array/Accelerate/Test/NoFib/Spectral/SMVM.hs +92/−0
- src/Data/Array/Accelerate/Test/Similar.hs +191/−0
- src/Data/Array/Accelerate/Trafo.hs +142/−0
- src/Data/Array/Accelerate/Trafo/Algebra.hs +744/−0
- src/Data/Array/Accelerate/Trafo/Config.hs +37/−0
- src/Data/Array/Accelerate/Trafo/Delayed.hs +126/−0
- src/Data/Array/Accelerate/Trafo/Environment.hs +163/−0
- src/Data/Array/Accelerate/Trafo/Fusion.hs +1770/−0
- src/Data/Array/Accelerate/Trafo/LetSplit.hs +77/−0
- src/Data/Array/Accelerate/Trafo/Sharing.hs +3161/−0
- src/Data/Array/Accelerate/Trafo/Shrink.hs +651/−0
- src/Data/Array/Accelerate/Trafo/Simplify.hs +686/−0
- src/Data/Array/Accelerate/Trafo/Substitution.hs +807/−0
- src/Data/Array/Accelerate/Trafo/Var.hs +79/−0
- src/Data/Array/Accelerate/Type.hs +520/−0
- src/Data/Array/Accelerate/Unsafe.hs +52/−0
- src/Data/Atomic.hs +101/−0
- src/Data/BitSet.hs +163/−0
- src/Data/Primitive/Vec.hs +289/−0
- src/Language/Haskell/TH/Extra.hs +92/−0
- test/doctest/Main.hs +23/−0
- test/nofib/Main.hs +24/−0
CHANGELOG.md view
@@ -6,14 +6,127 @@ project adheres to the [Haskell Package Versioning Policy (PVP)](https://pvp.haskell.org) +## [1.4.0.0] -- 2026-03-30+### Added+ * Compatibility with GHC 9.12 and Cabal 3.16+ * Support for profiling with [Tracy](https://github.com/wolfpld/tracy) in `accelerate-llvm-native` (enable the `tracy` Cabal flag on `accelerate`) ([#503](https://github.com/AccelerateHS/accelerate/pull/503))+ * Passing `+ACC -dverbose` makes `show` output of `Acc` terms print the hash+ of the kernel, to make cross-referencing against compiled code and+ execution information easier ([#478](https://github.com/AccelerateHS/accelerate/pull/478))+ * Debugging functions in module `Data.Array.Accelerate.Debug.Trace` ([#485](https://github.com/AccelerateHS/accelerate/pull/485))+ * A `Monad` class, and export `Functor` and `Either` from `Data.Array.Accelerate` ([#488](https://github.com/AccelerateHS/accelerate/pull/488)) +### Fixed+ * Graphviz graph generation of `-ddump-dot` and `-ddump-simpl-dot` ([#384](https://github.com/AccelerateHS/accelerate/issues/384))+ * `+ACC` argument parsing ([#539](https://github.com/AccelerateHS/accelerate/pull/539))+ * Removed dependency on lens ([#493](https://github.com/AccelerateHS/accelerate/pull/493))+ * And various other things!++### Contributors++Special thanks to those who contributed patches as part of this release:++ * Ivo Gabe de Wolff (@ivogabe)+ * David van Balen (@dpvanbalen)+ * Tom Smeding (@tomsmeding)+ * Trevor L. McDonell (@tmcdonell)+ * Maksymilian Demitraszek (@MaksymilianDemitraszek)+ * Laurent René de Cotret (@LaurentRDC)+ * Robbert van der Helm (@robbert-vdh)+ * Mirek Kratochvil (@exaexa)+++## [1.3.0.0] - 2020-08-26+### Added+ * Instances of `Elt` are now derivable via `Generic` for simple (Haskell'98)+ product _and_ sum data types.+ * Pattern synonyms for manipulating custom product and sum types can now be+ created; see `Pattern`, `mkPattern`+ * Added pattern synonyms for accessing tuples and indices, as an alternative+ to `lift` and `unlift`.+ * Support for pattern matching in the embedded language; see `match`++### Changed+ * The `stencil` functions now support fusion. Note however that the source+ (delayed) array will be evaluated at _every_ access to the stencil pattern;+ if the delayed function is expensive, you may wish to explicitly `compute`+ the source array first, matching the old behaviour.+ * Removed `Slice` constraint from some indexing operations+ * Improve fusion for `zipWith*` ([#453](https://github.com/AccelerateHS/accelerate/pull/453))+ * The indexing function to `permute` now returns a `Maybe` type ([#87](https://github.com/AccelerateHS/accelerate/issues/87))++ * (internal) Visible type applications are used instead of `Proxy` types+ * (internal) `EltR` is now a class-associated type of `Elt`+ * (internal) `GArrayData` has been simplified+ * (internal) SIMD representation has been improved and generalised+ * (internal) Internal refactoring ([#449](https://github.com/AccelerateHS/accelerate/pull/449), [#455](https://github.com/AccelerateHS/accelerate/pull/455), [#457](https://github.com/AccelerateHS/accelerate/pull/457), [#460](https://github.com/AccelerateHS/accelerate/pull/460))++ * Probably many others I have forgotten about++### Removed+ * Drop support for GHC-7.10 .. 8.4.++### Contributors++Special thanks to those who contributed patches as part of this release:++ * Trevor L. McDonell (@tmcdonell)+ * Joshua Meredith (@JoshMeredith)+ * Ivo Gabe de Wolff (@ivogabe)+ * David van Balen (@dpvanbalen)+ * Jaro Reinders (@noughtmare)+ * Alex Lang (@alang9)+ * Paul Wilson (@status_failed)+ * @lennonhill+ * Travis Whitaker (@TravisWhitaker)+ * Roger Bosman (@rogerbosman)+ * Robbert van der Helm (@robbert-vdh)+ * Sam (@sam-340453)+ * Lars van den Haak (@sakehl)+ * Rinat Striungis (@Haskell-mouse)+ * Viktor Kronvall (@considerate)+ * Tom Smeding (@tomsmeding)+ * Ryan Scott (@RyanGlScott)+++## [1.2.0.1] - 2018-10-06+### Fixed+ * Build fix for ghc-8.6++## [1.2.0.0] - 2018-04-03+### Changed+ * Internal debugging/RTS options handling has been changed. Compiling this package now implies that backends are also compiled in debug mode (no need to set the `-fdebug` cabal flag for those packages as well).+ * Complex numbers are stored in the C-style array-of-struct representation.+ * Improve numeric handling of complex numbers.+ * Coercions (`bitcast`) now occur between the underlying representation types+ * Front-end performance improvements++### Added+ * Support for half-precision floating-point numbers.+ * Support for struct-of-array-of-struct representations. Currently this is limited to fields of 2,3,4,8, or 16-elements wide.+ * Add equivalents for `Data.Functor`, `Data.Semigroup` (ghc-8+)+ * Add instances and helper functions for `Maybe` and `Either` types+ * Add rank generalised versions of `take`, `drop`, `head`, `tail`, `init`, `slit`, `reverse` and `transpose`.+ * Implement counters and reporting for `-ddump-gc-stats`++### Contributors++Special thanks to those who contributed patches as part of this release:++ * Trevor L. McDonell (@tmcdonell)+ * Ryan Scott (@ryanglscott)+ * Rinat Striungis (@Haskell-mouse)++ ## [1.1.1.0] - 2017-09-26 ### Changed * Improve and colourise the pretty-printer + ## [1.1.0.0] - 2017-09-21 ### Added- * Additional EKG monitoring hooks ([#340])+ * Additional EKG monitoring hooks ([#340](https://github.com/AccelerateHS/accelerate/issues/340))+ * Operations from `RealFloat` ### Changed@@ -27,18 +140,22 @@ to out-of-bounds indices. ### Fixed- * [#390]: Wrong number of arguments in printf+ * [#390](https://github.com/AccelerateHS/accelerate/issues/390): Wrong number of arguments in printf + ## [1.0.0.0] - 2017-03-31 * Many API and internal changes * Bug fixes and other enhancements + ## [0.15.1.0] * Fix type of `allocateArray` + ## [0.15.0.0] * Bug fixes and performance improvements. + ## [0.14.0.0] * New iteration constructs. * Additional Prelude-like functions.@@ -46,6 +163,7 @@ * Concurrent kernel execution in the CUDA backend. * Bug fixes. + ## [0.13.0.0] * New array fusion optimisation. * New foreign function interface for array and scalar expressions.@@ -53,23 +171,27 @@ * New example programs. * Bug fixes and performance improvements. + ## [0.12.0.0] * Full sharing recovery in scalar expressions and array computations. * Two new example applications in package `accelerate-examples` (both including a graphical frontend):- * A real-time Canny edge detection + * A real-time Canny edge detection * An interactive fluid flow simulator * Bug fixes. + ## [0.11.0.0] * New Prelude-like functions `zip*`, `unzip*`, `fill`, `enumFrom*`, `tail`, `init`, `drop`, `take`, `slit`, `gather*`, `scatter*`, and `shapeSize`. * New simplified AST (in package `accelerate-backend-kit`) for backend writers who want to avoid the complexities of the type-safe AST. + ## [0.10.0.0] * Complete sharing recovery for scalar expressions (but currently disabled by default). * Also bug fixes in array sharing recovery and a few new convenience functions. + ## [0.9.0.0] * Streaming computations * Precompilation@@ -79,18 +201,25 @@ * Conversions to other array formats * Bug fixes + ## 0.8.1.0 * Bug fixes and some performance tweaks. + ## 0.8.0.0 * More collective operations supported by the CUDA backend: `replicate`, `slice` and `foldSeg`. Frontend and interpreter support for `stencil`. * Bug fixes. + ## [0.7.1.0] * Initial release of the CUDA backend +[next]: https://github.com/AccelerateHS/accelerate/compare/v1.3.0.0...HEAD+[1.3.0.0]: https://github.com/AccelerateHS/accelerate/compare/v1.2.0.1...v1.3.0.0+[1.2.0.1]: https://github.com/AccelerateHS/accelerate/compare/v1.2.0.0...v1.2.0.1+[1.2.0.0]: https://github.com/AccelerateHS/accelerate/compare/v1.1.0.0...v1.2.0.0 [1.1.1.0]: https://github.com/AccelerateHS/accelerate/compare/v1.1.0.0...v1.1.1.0 [1.1.0.0]: https://github.com/AccelerateHS/accelerate/compare/1.0.0.0...v1.1.0.0 [1.0.0.0]: https://github.com/AccelerateHS/accelerate/compare/0.15.1.0...1.0.0.0@@ -103,7 +232,4 @@ [0.10.0.0]: https://github.com/AccelerateHS/accelerate/compare/0.9.0.0...0.10.0.0 [0.9.0.0]: https://github.com/AccelerateHS/accelerate/compare/0_8_1_0...0.9.0.0 [0.7.1.0]: https://github.com/AccelerateHS/accelerate/compare/0_6_0_0...0_7_1_0--[#340]: https://github.com/AccelerateHS/accelerate/issues/340-[#390]: https://github.com/AccelerateHS/accelerate/issues/390
− Data/Array/Accelerate.hs
@@ -1,534 +0,0 @@--- |--- Module : Data.Array.Accelerate--- Copyright : [2008..2017] Manuel M T Chakravarty, Gabriele Keller--- [2009..2017] Trevor L. McDonell--- [2013..2017] Robert Clifton-Everest--- [2014..2014] Frederik M. Madsen--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)------ @Data.Array.Accelerate@ defines an embedded language of array computations--- for high-performance computing in Haskell. Computations on multi-dimensional,--- regular arrays are expressed in the form of parameterised collective--- operations such as maps, reductions, and permutations. These computations are--- online compiled and can be executed on a range of architectures.------ [/Abstract interface:/]------ The types representing array computations are only exported abstractly;--- client code can generate array computations and submit them for execution,--- but it cannot inspect these computations. This is to allow for more--- flexibility for future extensions of this library.------ [/Stratified language:/]------ Accelerate distinguishes the types of collective operations 'Acc' from the--- type of scalar operations 'Exp' to achieve a stratified language. Collective--- operations comprise many scalar computations that are executed in parallel,--- but scalar computations /can not/ contain collective operations. This--- separation excludes /nested, irregular/ data-parallelism statically; instead,--- Accelerate is limited to /flat data-parallelism/ involving only regular,--- multi-dimensional arrays.------ [/Optimisations:/]------ Accelerate uses a number of scalar and array optimisations, including--- /array fusion/, in order to improve the performance of programs. Fusing--- a program entails combining successive traversals (loops) over an array into--- a single traversal, which reduces memory traffic and eliminates intermediate--- arrays.------ [/Code execution:/]------ Several backends are available which can be used to evaluate accelerate--- programs:------ * "Data.Array.Accelerate.Interpreter": simple interpreter in Haskell as a--- reference implementation defining the semantics of the Accelerate language------ * <http://hackage.haskell.org/package/accelerate-llvm-native accelerate-llvm-native>:--- implementation supporting parallel execution on multicore CPUs (e.g. x86).------ * <http://hackage.haskell.org/package/accelerate-llvm-ptx accelerate-llvm-ptx>:--- implementation supporting parallel execution on CUDA-capable NVIDIA GPUs.------ [/Examples:/]------ * The <http://hackage.haskell.org/package/accelerate-examples accelerate-examples>--- package demonstrates a range of computational kernels and several complete--- applications:------ - Implementation of the <https://en.wikipedia.org/wiki/Canny_edge_detector canny edge detector>--- - Interactive <https://en.wikipedia.org/wiki/Mandelbrot_set Mandelbrot set> generator--- - <https://en.wikipedia.org/wiki/N-body N-body simulation> of gravitational attraction between large bodies--- - Implementation of the <https://en.wikipedia.org/wiki/Pagerank PageRank> algorithm--- - A simple, real-time, interactive <https://en.wikipedia.org/wiki/Ray_tracing ray tracer>.--- - A particle based simulation of stable fluid flows--- - A cellular automaton simulation--- - A "password recovery" tool, for dictionary attacks on MD5 hashes.------ <<http://i.imgur.com/5Tbsp1j.jpg accelerate-mandelbrot>>--- <<http://i.imgur.com/7ohhKm9.jpg accelerate-ray>>------ * <http://hackage.haskell.org/package/lulesh-accelerate lulesh-accelerate>--- is an implementation of the Livermore Unstructured Lagrangian Explicit--- Shock Hydrodynamics (LULESH) application. LULESH is representative of--- typical hydrodynamics codes, although simplified and hard-coded to solve--- the Sedov blast problem on an unstructured hexahedron mesh.------ - For more information on LULESH: <https://codesign.llnl.gov/lulesh.php>.------ <<https://codesign.llnl.gov/images/sedov-3d-LLNL.png>>------ [/Additional components:/]------ * <https://hackage.haskell.org/package/accelerate-io accelerate-io>: Fast--- conversion between Accelerate arrays and other formats (e.g. Repa, Vector).------ * <https://hackage.haskell.org/package/accelerate-fft accelerate-fft>: Fast--- Fourier transform, with FFI bindings to optimised implementations.------ * <https://hackage.haskell.org/package/accelerate-blas accelerate-blas>: BLAS--- and LAPACK operations, with FFI bindings to optimised implementations.------ * <https://hackage.haskell.org/package/accelerate-bignum accelerate-bignum>:--- Fixed-width large integer arithmetic.------ * <https://hackage.haskell.org/package/colour-accelerate colour-accelerate>:--- Colour representations in Accelerate (RGB, sRGB, HSV, and HSL).------ * <https://hackage.haskell.org/package/gloss-accelerate gloss-accelerate>:--- Generate <https://hackage.haskell.org/package/gloss gloss> pictures from--- Accelerate.------ * <https://hackage.haskell.org/package/gloss-raster-accelerate gloss-raster-accelerate>:--- Parallel rendering of raster images and animations.------ * <https://hackage.haskell.org/package/lens-accelerate lens-accelerate>:--- <https://hackage.haskell.org/package/lens Lens> operators for Accelerate--- types.------ * <https://hackage.haskell.org/package/linear-accelerate linear-accelerate>:--- <https://hackage.haskell.org/package/linear Linear> vector space types for--- Accelerate.------ * <https://hackage.haskell.org/package/mwc-random-accelerate mwc-random-accelerate>:--- Generate Accelerate arrays filled with high-quality pseudorandom numbers.------ [/Contact:/]------ * Mailing list for both use and development discussion:------ * <mailto:accelerate-haskell@googlegroups.com>--- * http://groups.google.com/group/accelerate-haskell------ * Bug reports: https://github.com/AccelerateHS/accelerate/issues------ * Maintainers:------ * Trevor L. McDonell: <mailto:tmcdonell@cse.unsw.edu.au>--- * Manuel M T Chakravarty: <mailto:chak@cse.unsw.edu.au>------ [/Tip:/]------ Accelerate tends to stress GHC's garbage collector, so it helps to increase--- the default GC allocation sizes. This can be done when running an executable--- by specifying RTS options on the command line, for example:------ > ./foo +RTS -A64M -n2M -RTS------ You can make these settings the default by adding the following @ghc-options@--- to your @.cabal@ file or similar:------ > ghc-options: -with-rtsopts=-n2M -with-rtsopts=-A64M------ To specify RTS options you will also need to compile your program with @-rtsopts@.-----module Data.Array.Accelerate (-- -- * The /Accelerate/ Array Language- -- ** Embedded array computations- Acc,-- -- *** Arrays- Array, Arrays, Scalar, Vector, Segments,-- -- *** Array elements- Elt,-- -- *** Array shapes & indices- -- $shapes_and_indices- --- Z(..), (:.)(..),- DIM0, DIM1, DIM2, DIM3, DIM4, DIM5, DIM6, DIM7, DIM8, DIM9,- Shape, Slice(..), All(..), Any(..),- -- Split(..), Divide(..), Division(..),-- -- ** Array access- -- *** Element indexing- (!), (!!), the,-- -- *** Shape information- null, length, shape, size, shapeSize,-- -- ** Construction- -- *** Introduction- use, unit,-- -- *** Initialisation- generate, fill,-- -- *** Enumeration- enumFromN, enumFromStepN,-- -- *** Concatenation- (++),-- -- ** Composition- -- *** Flow control- (?|), acond, awhile,- IfThenElse(..),-- -- *** Controlling execution- (>->),- compute,-- -- ** Element-wise operations- -- *** Indexing- indexed,-- -- *** Mapping- map, imap,-- -- *** Zipping- zipWith, zipWith3, zipWith4, zipWith5, zipWith6, zipWith7, zipWith8, zipWith9,- izipWith, izipWith3, izipWith4, izipWith5, izipWith6, izipWith7, izipWith8, izipWith9,- zip, zip3, zip4, zip5, zip6, zip7, zip8, zip9,-- -- *** Unzipping- unzip, unzip3, unzip4, unzip5, unzip6, unzip7, unzip8, unzip9,-- -- ** Modifying Arrays- -- *** Shape manipulation- reshape, flatten,-- -- *** Replication- replicate,-- -- *** Extracting sub-arrays- slice,- init, tail, take, drop, slit,-- -- *** Permutations- -- **** Forward permutation (scatter)- permute,- ignore,- scatter,-- -- **** Backward permutation (gather)- backpermute,- gather,-- -- **** Specialised permutations- reverse, transpose,-- -- *** Filtering- filter,-- -- ** Folding- fold, fold1, foldAll, fold1All,-- -- *** Segmented reductions- foldSeg, fold1Seg,-- -- *** Specialised reductions- all, any, and, or, sum, product, minimum, maximum,-- -- ** Scans (prefix sums)- scanl, scanl1, scanl', scanr, scanr1, scanr',- prescanl, postscanl, prescanr, postscanr,-- -- *** Segmented scans- scanlSeg, scanl1Seg, scanl'Seg, prescanlSeg, postscanlSeg,- scanrSeg, scanr1Seg, scanr'Seg, prescanrSeg, postscanrSeg,-- -- ** Stencils- stencil, stencil2,-- -- *** Stencil specification- Stencil, Boundary,- clamp, mirror, wrap, function,-- -- *** Common stencil patterns- Stencil3, Stencil5, Stencil7, Stencil9,- Stencil3x3, Stencil5x3, Stencil3x5, Stencil5x5,- Stencil3x3x3, Stencil5x3x3, Stencil3x5x3, Stencil3x3x5, Stencil5x5x3, Stencil5x3x5,- Stencil3x5x5, Stencil5x5x5,-- -- -- ** Sequence operations- -- collect,-- -- -- ** Sequence producers- -- streamIn, toSeq, generateSeq,-- -- -- ** Sequence transducers- -- mapSeq, zipWithSeq, scanSeq,-- -- -- ** Sequence consumers- -- foldSeq, foldSeqFlatten, fromSeq, fromSeqElems, fromSeqShapes,- -- toSeqInner, toSeqOuter2, toSeqOuter3,-- -- ---------------------------------------------------------------------------- -- * The /Accelerate/ Expression Language- -- ** Scalar data types- Exp,-- -- ** Type classes- -- *** Basic type classes- Eq(..),- Ord(..),- -- Enum, -- vacuous- Bounded, minBound, maxBound,-- -- *** Numeric type classes- Num, (+), (-), (*), negate, abs, signum, fromInteger,- -- Real, -- vacuous- Integral, quot, rem, div, mod, quotRem, divMod,- Fractional, (/), recip, fromRational,- Floating, pi, sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh, exp, sqrt, log, (**), logBase,- RealFrac(..), div', mod', divMod',- RealFloat(..),-- -- *** Numeric conversion classes- FromIntegral(..),- ToFloating(..),-- -- ** Lifting and Unlifting- -- $lifting_and_unlifting- --- Lift(..), Unlift(..),- lift1, lift2, lift3,- ilift1, ilift2, ilift3,-- -- ** Scalar operations- -- *** Introduction- constant,-- -- *** Tuples- fst, afst, snd, asnd, curry, uncurry,-- -- *** Flow control- (?), caseof, cond, while, iterate,-- -- *** Scalar reduction- sfoldl,-- -- *** Logical operations- (&&), (||), not,-- -- *** Numeric operations- subtract, even, odd, gcd, lcm, (^), (^^),-- -- *** Shape manipulation- index0, index1, unindex1, index2, unindex2, index3, unindex3,- indexHead, indexTail,- toIndex, fromIndex,- intersect,-- -- *** Conversions- ord, chr, boolToInt, bitcast,-- -- ---------------------------------------------------------------------------- -- * Foreign Function Interface (FFI)- foreignAcc,- foreignExp,-- -- ---------------------------------------------------------------------------- -- * Plain arrays- -- ** Operations- arrayRank, arrayShape, arraySize, indexArray,-- -- ** Getting data in- -- $getting_data_in-- -- *** Function- fromFunction,-- -- *** Lists- fromList, toList,-- -- ---------------------------------------------------------------------------- -- * Prelude re-exports- (.), ($), error, undefined, const,-- -- ---------------------------------------------------------------------------- -- Types- Int, Int8, Int16, Int32, Int64,- Word, Word8, Word16, Word32, Word64,- Float, Double,- Bool(..), Char,-- CFloat, CDouble,- CShort, CUShort, CInt, CUInt, CLong, CULong, CLLong, CULLong,- CChar, CSChar, CUChar,-- -- | Avoid using these in your own functions wherever possible.- IsScalar, IsNum, IsBounded, IsIntegral, IsFloating, IsNonNum,--) where---- friends-import Data.Array.Accelerate.Array.Sugar hiding ( (!), rank, shape, size, toIndex, fromIndex, intersect, ignore )-import Data.Array.Accelerate.Classes-import Data.Array.Accelerate.Language-import Data.Array.Accelerate.Prelude-import Data.Array.Accelerate.Trafo () -- show instances-import Data.Array.Accelerate.Type-import qualified Data.Array.Accelerate.Array.Sugar as S---- re-exported from D.A.A.Classes.Num but not found (GHC<8 bug)-import Prelude ( (.), ($), undefined, error, const, fromInteger )----- Renamings--- --------------- FIXME: these all need to go into a separate module for separate importing!---- rename as '(!)' is already used by the EDSL for indexing---- | Array indexing in plain Haskell code.----indexArray :: Array sh e -> sh -> e-indexArray = (S.!)---- | Rank of an array.----arrayRank :: Shape sh => sh -> Int-arrayRank = S.rank---- |Array shape in plain Haskell code.----arrayShape :: Shape sh => Array sh e -> sh-arrayShape = S.shape--- rename as 'shape' is already used by the EDSL to query an array's shape---- | Total number of elements in an array of the given 'Shape'.----arraySize :: Shape sh => sh -> Int-arraySize = S.size---- Named documentation chunks--- ------------------------------ $shapes_and_indices------ Operations in Accelerate take the form of collective operations over arrays--- of the type @'Array' sh e@. Much like the--- <https://hackage.haskell.org/package/repa repa> library, arrays in Accelerate--- are parameterised by a type /sh/ which determines the dimensionality of the--- array and the type of each index, as well as the type of each element of the--- array /e/.------ Shape types, and multidimensional array indices, are built like lists--- (technically; a heterogeneous snoc-list) using 'Z' and (':.'):------ > data Z = Z--- > data tail :. head = tail :. head------ Here, the constructor 'Z' corresponds to a shape with zero dimension (or--- a 'Scalar' array, with one element) and is used to mark the end of the list.--- The constructor (':.') adds additional dimensions to the shape on the--- /right/. For example:------ > Z :. Int------ is the type of the shape of a one-dimensional array ('Vector') indexed by an--- 'Int', while:------ > Z :. Int :. Int------ is the type of the shape of a two-dimensional array (a matrix) indexed by an--- 'Int' in each dimension.------ This style is used to construct both the /type/ and /value/ of the shape. For--- example, to define the shape of a vector of ten elements:------ > sh :: Z :. Int--- > sh = Z :. 10------ Note that the right-most index is the /innermost/ dimension. This is the--- fastest-varying index, and corresponds to the elements of the array which are--- adjacent in memory.------- $lifting_and_unlifting------ A value of type 'Int' is a plain Haskell value (unlifted), whereas an @Exp--- Int@ is a /lifted/ value, that is, an integer lifted into the domain of--- embedded expressions (an abstract syntax tree in disguise). Both 'Acc' and--- 'Exp' are /surface types/ into which values may be lifted. Lifting plain--- array and scalar surface types is equivalent to 'use' and 'constant'--- respectively.------ In general an @Exp Int@ cannot be unlifted into an 'Int', because the actual--- number will not be available until a later stage of execution (e.g. during--- GPU execution, when 'run' is called). Similarly an @Acc array@ can not be--- unlifted to a vanilla 'array'; you should instead 'run' the expression with--- a specific backend to evaluate it.------ Lifting and unlifting are also used to pack and unpack an expression into and--- out of constructors such as tuples, respectively. Those expressions, at--- runtime, will become tuple dereferences. For example:------ >>> let sh = constant (Z :. 4 :. 10) :: Exp DIM2--- >>> let Z :. x :. y = unlift sh :: Z :. Exp Int :. Exp Int--- >>> let t = lift (x,y) :: Exp (Int, Int)------ >>> let r = scanl' f z xs :: (Acc (Vector Int), Acc (Scalar Int))--- >>> let r' = lift r :: Acc (Vector Int, Scalar Int)------ [/Note:/]------ Use of 'lift' and 'unlift' is probably the most common source of type errors--- when using Accelerate. GHC is not very good at determining the type the--- [un]lifted expression should have, so it is often necessary to add an--- explicit type signature.------ For example, in the following GHC will complain that it can not determine the--- type of 'y', even though we might expect that to be obvious (or for it to not--- care):------ > fst :: (Elt a, Elt b) => Exp (a,b) -> Exp a--- > fst t = let (x,y) = unlift t in x------ The fix is to instead add an explicit type signature. Note that this requires--- the @ScopedTypeVariables@ extension and to bring the type variables @a@ and--- @b@ into scope with @forall@:------ > fst :: forall a b. (Elt a, Elt b) => Exp (a,b) -> Exp a--- > fst t = let (x,y) = unlift t :: (Exp a, Exp b)--- > in x------- $getting_data_in--- #getting_data_in#------ We often need to generate or read data into an 'Array' so that it can be used--- in Accelerate. The base @accelerate@ library includes basic conversions--- routines, but for additional functionality see the--- <http://hackage.haskell.org/package/accelerate-io accelerate-io> package,--- which includes conversions between:------ * <https://hackage.haskell.org/package/repa repa>: another Haskell library for high-performance parallel arrays--- * <https://hackage.haskell.org/package/vector vector>: efficient boxed and unboxed one-dimensional arrays--- * <https://hackage.haskell.org/package/array array>: immutable arrays--- * <https://hackage.haskell.org/package/bmp BMP>: uncompressed BMP image files--- * <https://hackage.haskell.org/package/bytestring bytestring> compact, immutable binary data--- * As well as copying data directly from raw 'Foreign.Ptr.Ptr's----
− Data/Array/Accelerate/AST.hs
@@ -1,1893 +0,0 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE TypeSynonymInstances #-}-{-# OPTIONS_HADDOCK hide #-}--- |--- Module : Data.Array.Accelerate.AST--- Copyright : [2008..2017] Manuel M T Chakravarty, Gabriele Keller--- [2009..2017] Trevor L. McDonell--- [2010..2011] Ben Lever--- [2013..2017] Robert Clifton-Everest--- [2014..2014] Frederik M. Madsen--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)------ /Scalar versus collective operations/------ The embedded array processing language is a two-level language. It--- combines a language of scalar expressions and functions with a language of--- collective array operations. Scalar expressions are used to compute--- arguments for collective operations and scalar functions are used to--- parametrise higher-order, collective array operations. The two-level--- structure, in particular, ensures that collective operations cannot be--- parametrised with collective operations; hence, we are following a flat--- data-parallel model. The collective operations manipulate--- multi-dimensional arrays whose shape is explicitly tracked in their types.--- In fact, collective operations cannot produce any values other than--- multi-dimensional arrays; when they yield a scalar, this is in the form of--- a 0-dimensional, singleton array. Similarly, scalar expression can -as--- their name indicates- only produce tuples of scalar, but not arrays.------ There are, however, two expression forms that take arrays as arguments. As--- a result scalar and array expressions are recursively dependent. As we--- cannot and don't want to compute arrays in the middle of scalar--- computations, array computations will always be hoisted out of scalar--- expressions. So that this is always possible, these array expressions may--- not contain any free scalar variables. To express that condition in the--- type structure, we use separate environments for scalar and array variables.------ /Programs/------ Collective array programs comprise closed expressions of array operations.--- There is no explicit sharing in the initial AST form, but sharing is--- introduced subsequently by common subexpression elimination and floating--- of array computations.------ /Functions/------ The array expression language is first-order and only provides limited--- control structures to ensure that it can be efficiently executed on--- compute-acceleration hardware, such as GPUs. To restrict functions to--- first-order, we separate function abstraction from the main expression--- type. Functions are represented using de Bruijn indices.------ /Parametric and ad-hoc polymorphism/------ The array language features paramatric polymophism (e.g., pairing and--- projections) as well as ad-hoc polymorphism (e.g., arithmetic operations).--- All ad-hoc polymorphic constructs include reified dictionaries (c.f.,--- module 'Types'). Reified dictionaries also ensure that constants--- (constructor 'Const') are representable on compute acceleration hardware.------ The AST contains both reified dictionaries and type class constraints.--- Type classes are used for array-related functionality that is uniformly--- available for all supported types. In contrast, reified dictionaries are--- used for functionality that is only available for certain types, such as--- arithmetic operations.-----module Data.Array.Accelerate.AST (-- -- * Typed de Bruijn indices- Idx(..), idxToInt, tupleIdxToInt,-- -- * Valuation environment- Val(..), ValElt(..), prj, prjElt,-- -- * Accelerated array expressions- PreOpenAfun(..), OpenAfun, PreAfun, Afun, PreOpenAcc(..), OpenAcc(..), Acc,- PreBoundary(..), Boundary, Stencil(..), StencilR(..),-- -- * Accelerated sequences- -- PreOpenSeq(..), Seq,- -- Producer(..), Consumer(..),-- -- * Scalar expressions- PreOpenFun(..), OpenFun, PreFun, Fun, PreOpenExp(..), OpenExp, PreExp, Exp, PrimConst(..),- PrimFun(..),-- -- NFData- NFDataAcc,- rnfPreOpenAfun, rnfPreOpenAcc, rnfPreOpenFun, rnfPreOpenExp,-- -- TemplateHaskell- LiftAcc,- liftIdx, liftTupleIdx, liftArrays,- liftConst, liftSliceIndex, liftPrimConst, liftPrimFun,- liftPreOpenAfun, liftPreOpenAcc, liftPreOpenFun, liftPreOpenExp,-- -- debugging- showPreAccOp, showPreExpOp,--) where----standard library-import Control.DeepSeq-import Data.List-import Data.Typeable-import Foreign.ForeignPtr-import Foreign.Marshal-import Foreign.Ptr-import Foreign.Storable-import GHC.Ptr ( Ptr(..) )-import System.IO.Unsafe-import Language.Haskell.TH ( Q, TExp )-import qualified Language.Haskell.TH as TH-import qualified Language.Haskell.TH.Syntax as TH-#if __GLASGOW_HASKELL__ <= 708-import Instances.TH.Lift () -- Int8, Int16...-#endif---- friends-import Data.Array.Accelerate.Array.Data-import Data.Array.Accelerate.Array.Representation ( SliceIndex(..), size )-import Data.Array.Accelerate.Array.Sugar hiding ( size )-import Data.Array.Accelerate.Array.Unique-import Data.Array.Accelerate.Product-import Data.Array.Accelerate.Type-#if __GLASGOW_HASKELL__ < 800-import Data.Array.Accelerate.Error-#endif----- Typed de Bruijn indices--- --------------------------- De Bruijn variable index projecting a specific type from a type--- environment. Type environments are nested pairs (..((), t1), t2, ..., tn).----data Idx env t where- ZeroIdx :: Idx (env, t) t- SuccIdx :: Idx env t -> Idx (env, s) t---- de Bruijn Index to Int conversion----idxToInt :: Idx env t -> Int-idxToInt ZeroIdx = 0-idxToInt (SuccIdx idx) = 1 + idxToInt idx--tupleIdxToInt :: TupleIdx tup e -> Int-tupleIdxToInt ZeroTupIdx = 0-tupleIdxToInt (SuccTupIdx idx) = 1 + tupleIdxToInt idx----- Environments--- ---------------- Valuation for an environment----data Val env where- Empty :: Val ()- Push :: Val env -> t -> Val (env, t)--deriving instance Typeable Val---- Valuation for an environment of array elements----data ValElt env where- EmptyElt :: ValElt ()- PushElt :: Elt t- => ValElt env -> EltRepr t -> ValElt (env, t)---- Projection of a value from a valuation using a de Bruijn index----prj :: Idx env t -> Val env -> t-prj ZeroIdx (Push _ v) = v-prj (SuccIdx idx) (Push val _) = prj idx val-#if __GLASGOW_HASKELL__ < 800-prj _ _ = $internalError "prj" "inconsistent valuation"-#endif---- Projection of a value from a valuation of array elements using a de Bruijn index----prjElt :: Idx env t -> ValElt env -> t-prjElt ZeroIdx (PushElt _ v) = toElt v-prjElt (SuccIdx idx) (PushElt val _) = prjElt idx val-#if __GLASGOW_HASKELL__ < 800-prjElt _ _ = $internalError "prjElt" "inconsistent valuation"-#endif---- Array expressions--- --------------------- |Function abstraction over parametrised array computations----data PreOpenAfun acc aenv t where- Abody :: Arrays t => acc aenv t -> PreOpenAfun acc aenv t- Alam :: Arrays a => PreOpenAfun acc (aenv, a) t -> PreOpenAfun acc aenv (a -> t)---- Function abstraction over vanilla open array computations----type OpenAfun = PreOpenAfun OpenAcc---- |Parametrised array-computation function without free array variables----type PreAfun acc = PreOpenAfun acc ()---- |Vanilla array-computation function without free array variables----type Afun = OpenAfun ()---- Vanilla open array computations----newtype OpenAcc aenv t = OpenAcc (PreOpenAcc OpenAcc aenv t)---- |Closed array expression aka an array program----type Acc = OpenAcc ()--deriving instance Typeable PreOpenAcc-deriving instance Typeable OpenAcc----- |Collective array computations parametrised over array variables--- represented with de Bruijn indices.------ * Scalar functions and expressions embedded in well-formed array--- computations cannot contain free scalar variable indices. The latter--- cannot be bound in array computations, and hence, cannot appear in any--- well-formed program.------ * The let-form is used to represent the sharing discovered by common--- subexpression elimination as well as to control evaluation order. (We--- need to hoist array expressions out of scalar expressions - they occur in--- scalar indexing and in determining an arrays shape.)------ The data type is parameterised over the surface types (not the representation--- type).------ We use a non-recursive variant parametrised over the recursive closure, to facilitate attribute--- calculation in the backend.----data PreOpenAcc acc aenv a where-- -- Local binding to represent sharing and demand explicitly; this is an- -- eager(!) binding- Alet :: (Arrays bndArrs, Arrays bodyArrs)- => acc aenv bndArrs -- bound expression- -> acc (aenv, bndArrs) bodyArrs -- the bound expression scope- -> PreOpenAcc acc aenv bodyArrs-- -- Variable bound by a 'Let', represented by a de Bruijn index- Avar :: Arrays arrs- => Idx aenv arrs- -> PreOpenAcc acc aenv arrs-- -- Tuples of arrays- Atuple :: (Arrays arrs, IsAtuple arrs)- => Atuple (acc aenv) (TupleRepr arrs)- -> PreOpenAcc acc aenv arrs-- Aprj :: (Arrays arrs, IsAtuple arrs, Arrays a)- => TupleIdx (TupleRepr arrs) a- -> acc aenv arrs- -> PreOpenAcc acc aenv a-- -- Array-function application.- --- -- The array function is not closed at the core level because we need access- -- to free variables introduced by 'run1' style evaluators. See Issue#95.- --- Apply :: (Arrays arrs1, Arrays arrs2)- => PreOpenAfun acc aenv (arrs1 -> arrs2)- -> acc aenv arrs1- -> PreOpenAcc acc aenv arrs2-- -- Apply a backend-specific foreign function to an array, with a pure- -- Accelerate version for use with other backends. The functions must be- -- closed.- Aforeign :: (Arrays as, Arrays bs, Foreign asm)- => asm (as -> bs) -- The foreign function for a given backend- -> PreAfun acc (as -> bs) -- Fallback implementation(s)- -> acc aenv as -- Arguments to the function- -> PreOpenAcc acc aenv bs-- -- If-then-else for array-level computations- Acond :: Arrays arrs- => PreExp acc aenv Bool- -> acc aenv arrs- -> acc aenv arrs- -> PreOpenAcc acc aenv arrs-- -- Value-recursion for array-level computations- Awhile :: Arrays arrs- => PreOpenAfun acc aenv (arrs -> Scalar Bool) -- continue iteration while true- -> PreOpenAfun acc aenv (arrs -> arrs) -- function to iterate- -> acc aenv arrs -- initial value- -> PreOpenAcc acc aenv arrs--- -- Array inlet (triggers async host->device transfer if necessary)- Use :: Arrays arrs- => ArrRepr arrs- -> PreOpenAcc acc aenv arrs-- -- Capture a scalar (or a tuple of scalars) in a singleton array- Unit :: Elt e- => PreExp acc aenv e- -> PreOpenAcc acc aenv (Scalar e)-- -- Change the shape of an array without altering its contents- -- > precondition: size dim == size dim'- Reshape :: (Shape sh, Shape sh', Elt e)- => PreExp acc aenv sh -- new shape- -> acc aenv (Array sh' e) -- array to be reshaped- -> PreOpenAcc acc aenv (Array sh e)-- -- Construct a new array by applying a function to each index.- Generate :: (Shape sh, Elt e)- => PreExp acc aenv sh -- output shape- -> PreFun acc aenv (sh -> e) -- representation function- -> PreOpenAcc acc aenv (Array sh e)-- -- Hybrid map/backpermute, where we separate the index and value- -- transformations.- Transform :: (Elt a, Elt b, Shape sh, Shape sh')- => PreExp acc aenv sh' -- dimension of the result- -> PreFun acc aenv (sh' -> sh) -- index permutation function- -> PreFun acc aenv (a -> b) -- function to apply at each element- -> acc aenv (Array sh a) -- source array- -> PreOpenAcc acc aenv (Array sh' b)-- -- Replicate an array across one or more dimensions as given by the first- -- argument- Replicate :: (Shape sh, Shape sl, Elt slix, Elt e)- => SliceIndex (EltRepr slix) -- slice type specification- (EltRepr sl)- co- (EltRepr sh)- -> PreExp acc aenv slix -- slice value specification- -> acc aenv (Array sl e) -- data to be replicated- -> PreOpenAcc acc aenv (Array sh e)-- -- Index a sub-array out of an array; i.e., the dimensions not indexed are- -- returned whole- Slice :: (Shape sh, Shape sl, Elt slix, Elt e)- => SliceIndex (EltRepr slix) -- slice type specification- (EltRepr sl)- co- (EltRepr sh)- -> acc aenv (Array sh e) -- array to be indexed- -> PreExp acc aenv slix -- slice value specification- -> PreOpenAcc acc aenv (Array sl e)-- -- Apply the given unary function to all elements of the given array- Map :: (Shape sh, Elt e, Elt e')- => PreFun acc aenv (e -> e')- -> acc aenv (Array sh e)- -> PreOpenAcc acc aenv (Array sh e')-- -- Apply a given binary function pairwise to all elements of the given arrays.- -- The length of the result is the length of the shorter of the two argument- -- arrays.- ZipWith :: (Shape sh, Elt e1, Elt e2, Elt e3)- => PreFun acc aenv (e1 -> e2 -> e3)- -> acc aenv (Array sh e1)- -> acc aenv (Array sh e2)- -> PreOpenAcc acc aenv (Array sh e3)-- -- Fold along the innermost dimension of an array with a given /associative/ function.- Fold :: (Shape sh, Elt e)- => PreFun acc aenv (e -> e -> e) -- combination function- -> PreExp acc aenv e -- default value- -> acc aenv (Array (sh:.Int) e) -- folded array- -> PreOpenAcc acc aenv (Array sh e)-- -- 'Fold' without a default value- Fold1 :: (Shape sh, Elt e)- => PreFun acc aenv (e -> e -> e) -- combination function- -> acc aenv (Array (sh:.Int) e) -- folded array- -> PreOpenAcc acc aenv (Array sh e)-- -- Segmented fold along the innermost dimension of an array with a given /associative/ function- FoldSeg :: (Shape sh, Elt e, Elt i, IsIntegral i)- => PreFun acc aenv (e -> e -> e) -- combination function- -> PreExp acc aenv e -- default value- -> acc aenv (Array (sh:.Int) e) -- folded array- -> acc aenv (Segments i) -- segment descriptor- -> PreOpenAcc acc aenv (Array (sh:.Int) e)-- -- 'FoldSeg' without a default value- Fold1Seg :: (Shape sh, Elt e, Elt i, IsIntegral i)- => PreFun acc aenv (e -> e -> e) -- combination function- -> acc aenv (Array (sh:.Int) e) -- folded array- -> acc aenv (Segments i) -- segment descriptor- -> PreOpenAcc acc aenv (Array (sh:.Int) e)-- -- Left-to-right Haskell-style scan of a linear array with a given *associative*- -- function and an initial element (which does not need to be the neutral of the- -- associative operations)- Scanl :: (Shape sh, Elt e)- => PreFun acc aenv (e -> e -> e) -- combination function- -> PreExp acc aenv e -- initial value- -> acc aenv (Array (sh:.Int) e)- -> PreOpenAcc acc aenv (Array (sh:.Int) e)- -- FIXME: Make the scans rank-polymorphic?-- -- Like 'Scan', but produces a rightmost fold value and an array with the same length as the input- -- array (the fold value would be the rightmost element in a Haskell-style scan)- Scanl' :: (Shape sh, Elt e)- => PreFun acc aenv (e -> e -> e) -- combination function- -> PreExp acc aenv e -- initial value- -> acc aenv (Array (sh:.Int) e)- -> PreOpenAcc acc aenv (Array (sh:.Int) e, Array sh e)-- -- Haskell-style scan without an initial value- Scanl1 :: (Shape sh, Elt e)- => PreFun acc aenv (e -> e -> e) -- combination function- -> acc aenv (Array (sh:.Int) e)- -> PreOpenAcc acc aenv (Array (sh:.Int) e)-- -- Right-to-left version of 'Scanl'- Scanr :: (Shape sh, Elt e)- => PreFun acc aenv (e -> e -> e) -- combination function- -> PreExp acc aenv e -- initial value- -> acc aenv (Array (sh:.Int) e)- -> PreOpenAcc acc aenv (Array (sh:.Int) e)-- -- Right-to-left version of 'Scanl\''- Scanr' :: (Shape sh, Elt e)- => PreFun acc aenv (e -> e -> e) -- combination function- -> PreExp acc aenv e -- initial value- -> acc aenv (Array (sh:.Int) e)- -> PreOpenAcc acc aenv (Array (sh:.Int) e, Array sh e)-- -- Right-to-left version of 'Scanl1'- Scanr1 :: (Shape sh, Elt e)- => PreFun acc aenv (e -> e -> e) -- combination function- -> acc aenv (Array (sh:.Int) e)- -> PreOpenAcc acc aenv (Array (sh:.Int) e)-- -- Generalised forward permutation is characterised by a permutation function- -- that determines for each element of the source array where it should go in- -- the output. The permutation can be between arrays of varying shape and- -- dimensionality.- --- -- Other characteristics of the permutation function 'f':- --- -- 1. 'f' is a partial function: if it evaluates to the magic value 'ignore'- -- (i.e. a tuple of -1 values) then those elements of the domain are- -- dropped.- --- -- 2. 'f' is not surjective: positions in the target array need not be- -- picked up by the permutation function, so the target array must first- -- be initialised from an array of default values.- --- -- 3. 'f' is not injective: distinct elements of the domain may map to the- -- same position in the target array. In this case the combination- -- function is used to combine elements, which needs to be /associative/- -- and /commutative/.- --- Permute :: (Shape sh, Shape sh', Elt e)- => PreFun acc aenv (e -> e -> e) -- combination function- -> acc aenv (Array sh' e) -- default values- -> PreFun acc aenv (sh -> sh') -- permutation function- -> acc aenv (Array sh e) -- source array- -> PreOpenAcc acc aenv (Array sh' e)-- -- Generalised multi-dimensional backwards permutation; the permutation can- -- be between arrays of varying shape; the permutation function must be total- Backpermute :: (Shape sh, Shape sh', Elt e)- => PreExp acc aenv sh' -- dimensions of the result- -> PreFun acc aenv (sh' -> sh) -- permutation function- -> acc aenv (Array sh e) -- source array- -> PreOpenAcc acc aenv (Array sh' e)-- -- Map a stencil over an array. In contrast to 'map', the domain of a stencil function is an- -- entire /neighbourhood/ of each array element.- Stencil :: (Elt e, Elt e', Stencil sh e stencil)- => PreFun acc aenv (stencil -> e') -- stencil function- -> PreBoundary acc aenv (Array sh e) -- boundary condition- -> acc aenv (Array sh e) -- source array- -> PreOpenAcc acc aenv (Array sh e')-- -- Map a binary stencil over an array.- Stencil2 :: (Elt a, Elt b, Elt c, Stencil sh a stencil1, Stencil sh b stencil2)- => PreFun acc aenv (stencil1 -> stencil2 -> c) -- stencil function- -> PreBoundary acc aenv (Array sh a) -- boundary condition #1- -> acc aenv (Array sh a) -- source array #1- -> PreBoundary acc aenv (Array sh b) -- boundary condition #2- -> acc aenv (Array sh b) -- source array #2- -> PreOpenAcc acc aenv (Array sh c)-- -- A sequence of operations.- -- Collect :: Arrays arrs- -- => PreOpenSeq acc aenv () arrs- -- -> PreOpenAcc acc aenv arrs--{---data PreOpenSeq acc aenv senv arrs where- Producer :: Arrays a- => Producer acc aenv senv a- -> PreOpenSeq acc aenv (senv, a) arrs- -> PreOpenSeq acc aenv senv arrs-- Consumer :: Arrays arrs- => Consumer acc aenv senv arrs- -> PreOpenSeq acc aenv senv arrs-- Reify :: Arrays arrs- => Idx senv arrs- -> PreOpenSeq acc aenv senv [arrs]--data Producer acc aenv senv a where- -- Convert the given Haskell-list of arrays to a sequence.- StreamIn :: Arrays a- => [a]- -> Producer acc aenv senv a-- -- Convert the given array to a sequence.- ToSeq :: (Elt slix, Shape sl, Shape sh, Elt e)- => SliceIndex (EltRepr slix)- (EltRepr sl)- co- (EltRepr sh)- -> proxy slix- -> acc aenv (Array sh e)- -> Producer acc aenv senv (Array sl e)-- -- Apply the given the given function to all elements of the given- -- sequence.- MapSeq :: (Arrays a, Arrays b)- => PreOpenAfun acc aenv (a -> b)- -> Idx senv a- -> Producer acc aenv senv b-- -- Apply the given the given function to all elements of the given- -- sequence.- ChunkedMapSeq :: (Arrays a, Arrays b)- => PreOpenAfun acc aenv (Vector' a -> Vector' b)- -> Idx senv a- -> Producer acc aenv senv b-- -- Apply a given binary function pairwise to all elements of the- -- given sequences.- ZipWithSeq :: (Arrays a, Arrays b, Arrays c)- => PreOpenAfun acc aenv (a -> b -> c)- -> Idx senv a- -> Idx senv b- -> Producer acc aenv senv c-- -- ScanSeq (+) a0 x. Scan a sequence x by combining each element- -- using the given binary operation (+). (+) must be associative:- --- -- Forall a b c. (a + b) + c = a + (b + c),- --- -- and a0 must be the identity element for (+):- --- -- Forall a. a0 + a = a = a + a0.- --- ScanSeq :: Elt e- => PreFun acc aenv (e -> e -> e)- -> PreExp acc aenv e- -> Idx senv (Scalar e)- -> Producer acc aenv senv (Scalar e)--data Consumer acc aenv senv a where-- -- FoldSeq (+) a0 x. Fold a sequence x by combining each element- -- using the given binary operation (+). (+) must be associative:- --- -- Forall a b c. (a + b) + c = a + (b + c),- --- -- and a0 must be the identity element for (+):- --- -- Forall a. a0 + a = a = a + a0.- --- FoldSeq :: Elt a- => PreFun acc aenv (a -> a -> a)- -> PreExp acc aenv a- -> Idx senv (Scalar a)- -> Consumer acc aenv senv (Scalar a)-- -- FoldSeqFlatten f a0 x. A specialized version of FoldSeqAct where- -- reduction with the companion operator corresponds to- -- flattening. f must be semi-associative, with vecotor append (++)- -- as the companion operator:- --- -- Forall b sh1 a1 sh2 a2.- -- f (f b sh1 a1) sh2 a2 = f b (sh1 ++ sh2) (a1 ++ a2).- --- -- It is common to ignore the shape vectors, yielding the usual- -- semi-associativity law:- --- -- f b a _ = b + a,- --- -- for some (+) satisfying:- --- -- Forall b a1 a2. (b + a1) + a2 = b + (a1 ++ a2).- --- FoldSeqFlatten :: (Arrays a, Shape sh, Elt e)- => PreOpenAfun acc aenv (a -> Vector sh -> Vector e -> a)- -> acc aenv a- -> Idx senv (Array sh e)- -> Consumer acc aenv senv a-- Stuple :: (Arrays a, IsAtuple a)- => Atuple (Consumer acc aenv senv) (TupleRepr a)- -> Consumer acc aenv senv a---- |Closed sequence computation----type Seq = PreOpenSeq OpenAcc () ()---}----- | Vanilla stencil boundary condition----type Boundary = PreBoundary OpenAcc---- | Boundary condition specification for stencil operations----data PreBoundary (acc :: * -> * -> *) aenv t where- -- Clamp coordinates to the extent of the array- Clamp :: PreBoundary acc aenv t-- -- Mirror coordinates beyond the array extent- Mirror :: PreBoundary acc aenv t-- -- Wrap coordinates around on each dimension- Wrap :: PreBoundary acc aenv t-- -- Use a constant value for outlying coordinates- Constant :: Elt e- => EltRepr e- -> PreBoundary acc aenv (Array sh e)-- -- Apply the given function to outlying coordinates- Function :: (Shape sh, Elt e)- => PreFun acc aenv (sh -> e)- -> PreBoundary acc aenv (Array sh e)----- | Operations on stencils----class (Shape sh, Elt e, IsTuple stencil, Elt stencil) => Stencil sh e stencil where- stencil :: StencilR sh e stencil---- | GADT reifying the 'Stencil' class----data StencilR sh e pat where- StencilRunit3 :: Elt e => StencilR DIM1 e (e,e,e)- StencilRunit5 :: Elt e => StencilR DIM1 e (e,e,e,e,e)- StencilRunit7 :: Elt e => StencilR DIM1 e (e,e,e,e,e,e,e)- StencilRunit9 :: Elt e => StencilR DIM1 e (e,e,e,e,e,e,e,e,e)-- StencilRtup3 :: (Shape sh, Elt e)- => StencilR sh e pat1- -> StencilR sh e pat2- -> StencilR sh e pat3- -> StencilR (sh:.Int) e (pat1,pat2,pat3)-- StencilRtup5 :: (Shape sh, Elt e)- => StencilR sh e pat1- -> StencilR sh e pat2- -> StencilR sh e pat3- -> StencilR sh e pat4- -> StencilR sh e pat5- -> StencilR (sh:.Int) e (pat1,pat2,pat3,pat4,pat5)-- StencilRtup7 :: (Shape sh, Elt e)- => StencilR sh e pat1- -> StencilR sh e pat2- -> StencilR sh e pat3- -> StencilR sh e pat4- -> StencilR sh e pat5- -> StencilR sh e pat6- -> StencilR sh e pat7- -> StencilR (sh:.Int) e (pat1,pat2,pat3,pat4,pat5,pat6,pat7)-- StencilRtup9 :: (Shape sh, Elt e)- => StencilR sh e pat1- -> StencilR sh e pat2- -> StencilR sh e pat3- -> StencilR sh e pat4- -> StencilR sh e pat5- -> StencilR sh e pat6- -> StencilR sh e pat7- -> StencilR sh e pat8- -> StencilR sh e pat9- -> StencilR (sh:.Int) e (pat1,pat2,pat3,pat4,pat5,pat6,pat7,pat8,pat9)----- Note: [Stencil reification class]------ We cannot start with 'DIM0'. The 'IsTuple stencil' superclass would at--- 'DIM0' imply that the types of individual array elements are in 'IsTuple'.--- (That would only possible if we could have (degenerate) 1-tuple, but we can't--- as we can't distinguish between a 1-tuple of a pair and a simple pair.)--- Hence, we need to start from 'DIM1' and use 'sh:.Int:.Int' in the recursive--- case (to avoid overlapping instances).---- DIM1-instance Elt e => Stencil DIM1 e (e, e, e) where- stencil = StencilRunit3--instance Elt e => Stencil DIM1 e (e, e, e, e, e) where- stencil = StencilRunit5--instance Elt e => Stencil DIM1 e (e, e, e, e, e, e, e) where- stencil = StencilRunit7--instance Elt e => Stencil DIM1 e (e, e, e, e, e, e, e, e, e) where- stencil = StencilRunit9---- DIM(n+1), where n>1-instance (Stencil (sh:.Int) a row1,- Stencil (sh:.Int) a row2,- Stencil (sh:.Int) a row3) => Stencil (sh:.Int:.Int) a (row1, row2, row3) where- stencil = StencilRtup3 stencil stencil stencil--instance (Stencil (sh:.Int) a row1,- Stencil (sh:.Int) a row2,- Stencil (sh:.Int) a row3,- Stencil (sh:.Int) a row4,- Stencil (sh:.Int) a row5) => Stencil (sh:.Int:.Int) a (row1, row2, row3, row4, row5) where- stencil = StencilRtup5 stencil stencil stencil stencil stencil--instance (Stencil (sh:.Int) a row1,- Stencil (sh:.Int) a row2,- Stencil (sh:.Int) a row3,- Stencil (sh:.Int) a row4,- Stencil (sh:.Int) a row5,- Stencil (sh:.Int) a row6,- Stencil (sh:.Int) a row7)- => Stencil (sh:.Int:.Int) a (row1, row2, row3, row4, row5, row6, row7) where- stencil = StencilRtup7 stencil stencil stencil stencil stencil stencil stencil--instance (Stencil (sh:.Int) a row1,- Stencil (sh:.Int) a row2,- Stencil (sh:.Int) a row3,- Stencil (sh:.Int) a row4,- Stencil (sh:.Int) a row5,- Stencil (sh:.Int) a row6,- Stencil (sh:.Int) a row7,- Stencil (sh:.Int) a row8,- Stencil (sh:.Int) a row9)- => Stencil (sh:.Int:.Int) a (row1, row2, row3, row4, row5, row6, row7, row8, row9) where- stencil = StencilRtup9 stencil stencil stencil stencil stencil stencil stencil stencil stencil----- Embedded expressions--- ------------------------ |Parametrised open function abstraction----data PreOpenFun (acc :: * -> * -> *) env aenv t where- Body :: Elt t => PreOpenExp acc env aenv t -> PreOpenFun acc env aenv t- Lam :: Elt a => PreOpenFun acc (env, a) aenv t -> PreOpenFun acc env aenv (a -> t)---- |Vanilla open function abstraction----type OpenFun = PreOpenFun OpenAcc---- |Parametrised function without free scalar variables----type PreFun acc = PreOpenFun acc ()---- |Vanilla function without free scalar variables----type Fun = OpenFun ()---- |Vanilla open expression----type OpenExp = PreOpenExp OpenAcc---- |Parametrised expression without free scalar variables----type PreExp acc = PreOpenExp acc ()---- |Vanilla expression without free scalar variables----type Exp = OpenExp ()---- |Parametrised open expressions using de Bruijn indices for variables ranging over tuples--- of scalars and arrays of tuples. All code, except Cond, is evaluated eagerly. N-tuples are--- represented as nested pairs.------ The data type is parametrised over the surface types (not the representation type).----data PreOpenExp (acc :: * -> * -> *) env aenv t where-- -- Local binding of a scalar expression- Let :: (Elt bnd_t, Elt body_t)- => PreOpenExp acc env aenv bnd_t- -> PreOpenExp acc (env, bnd_t) aenv body_t- -> PreOpenExp acc env aenv body_t-- -- Variable index, ranging only over tuples or scalars- Var :: Elt t- => Idx env t- -> PreOpenExp acc env aenv t-- -- Apply a backend-specific foreign function- Foreign :: (Foreign asm, Elt x, Elt y)- => asm (x -> y)- -> PreFun acc () (x -> y)- -> PreOpenExp acc env aenv x- -> PreOpenExp acc env aenv y-- -- Constant values- Const :: Elt t- => EltRepr t- -> PreOpenExp acc env aenv t-- -- Tuples- Tuple :: (Elt t, IsTuple t)- => Tuple (PreOpenExp acc env aenv) (TupleRepr t)- -> PreOpenExp acc env aenv t-- Prj :: (Elt t, IsTuple t, Elt e)- => TupleIdx (TupleRepr t) e- -> PreOpenExp acc env aenv t- -> PreOpenExp acc env aenv e-- -- Array indices & shapes- IndexNil :: PreOpenExp acc env aenv Z-- IndexCons :: (Slice sl, Elt a)- => PreOpenExp acc env aenv sl- -> PreOpenExp acc env aenv a- -> PreOpenExp acc env aenv (sl:.a)-- IndexHead :: (Slice sl, Elt a)- => PreOpenExp acc env aenv (sl:.a)- -> PreOpenExp acc env aenv a-- IndexTail :: (Slice sl, Elt a)- => PreOpenExp acc env aenv (sl:.a)- -> PreOpenExp acc env aenv sl-- IndexAny :: Shape sh- => PreOpenExp acc env aenv (Any sh)-- IndexSlice :: (Shape sh, Shape sl, Elt slix)- => SliceIndex (EltRepr slix) (EltRepr sl) co (EltRepr sh)- -> PreOpenExp acc env aenv slix- -> PreOpenExp acc env aenv sh- -> PreOpenExp acc env aenv sl-- IndexFull :: (Shape sh, Shape sl, Elt slix)- => SliceIndex (EltRepr slix) (EltRepr sl) co (EltRepr sh)- -> PreOpenExp acc env aenv slix- -> PreOpenExp acc env aenv sl- -> PreOpenExp acc env aenv sh-- -- Shape and index conversion- ToIndex :: Shape sh- => PreOpenExp acc env aenv sh -- shape of the array- -> PreOpenExp acc env aenv sh -- index into the array- -> PreOpenExp acc env aenv Int-- FromIndex :: Shape sh- => PreOpenExp acc env aenv sh -- shape of the array- -> PreOpenExp acc env aenv Int -- index into linear representation- -> PreOpenExp acc env aenv sh-- -- Conditional expression (non-strict in 2nd and 3rd argument)- Cond :: Elt t- => PreOpenExp acc env aenv Bool- -> PreOpenExp acc env aenv t- -> PreOpenExp acc env aenv t- -> PreOpenExp acc env aenv t-- -- Value recursion- While :: Elt a- => PreOpenFun acc env aenv (a -> Bool) -- continue while true- -> PreOpenFun acc env aenv (a -> a) -- function to iterate- -> PreOpenExp acc env aenv a -- initial value- -> PreOpenExp acc env aenv a-- -- Primitive constants- PrimConst :: Elt t- => PrimConst t- -> PreOpenExp acc env aenv t-- -- Primitive scalar operations- PrimApp :: (Elt a, Elt r)- => PrimFun (a -> r)- -> PreOpenExp acc env aenv a- -> PreOpenExp acc env aenv r-- -- Project a single scalar from an array.- -- The array expression can not contain any free scalar variables.- Index :: (Shape dim, Elt t)- => acc aenv (Array dim t)- -> PreOpenExp acc env aenv dim- -> PreOpenExp acc env aenv t-- LinearIndex :: (Shape dim, Elt t)- => acc aenv (Array dim t)- -> PreOpenExp acc env aenv Int- -> PreOpenExp acc env aenv t-- -- Array shape.- -- The array expression can not contain any free scalar variables.- Shape :: (Shape dim, Elt e)- => acc aenv (Array dim e)- -> PreOpenExp acc env aenv dim-- -- Number of elements of an array given its shape- ShapeSize :: Shape dim- => PreOpenExp acc env aenv dim- -> PreOpenExp acc env aenv Int-- -- Intersection of two shapes- Intersect :: Shape dim- => PreOpenExp acc env aenv dim- -> PreOpenExp acc env aenv dim- -> PreOpenExp acc env aenv dim-- -- Union of two shapes- Union :: Shape dim- => PreOpenExp acc env aenv dim- -> PreOpenExp acc env aenv dim- -> PreOpenExp acc env aenv dim----- |Primitive constant values----data PrimConst ty where-- -- constants from Bounded- PrimMinBound :: BoundedType a -> PrimConst a- PrimMaxBound :: BoundedType a -> PrimConst a-- -- constant from Floating- PrimPi :: FloatingType a -> PrimConst a---- |Primitive scalar operations----data PrimFun sig where-- -- operators from Num- PrimAdd :: NumType a -> PrimFun ((a, a) -> a)- PrimSub :: NumType a -> PrimFun ((a, a) -> a)- PrimMul :: NumType a -> PrimFun ((a, a) -> a)- PrimNeg :: NumType a -> PrimFun (a -> a)- PrimAbs :: NumType a -> PrimFun (a -> a)- PrimSig :: NumType a -> PrimFun (a -> a)-- -- operators from Integral- PrimQuot :: IntegralType a -> PrimFun ((a, a) -> a)- PrimRem :: IntegralType a -> PrimFun ((a, a) -> a)- PrimQuotRem :: IntegralType a -> PrimFun ((a, a) -> (a, a))- PrimIDiv :: IntegralType a -> PrimFun ((a, a) -> a)- PrimMod :: IntegralType a -> PrimFun ((a, a) -> a)- PrimDivMod :: IntegralType a -> PrimFun ((a, a) -> (a, a))-- -- operators from Bits & FiniteBits- PrimBAnd :: IntegralType a -> PrimFun ((a, a) -> a)- PrimBOr :: IntegralType a -> PrimFun ((a, a) -> a)- PrimBXor :: IntegralType a -> PrimFun ((a, a) -> a)- PrimBNot :: IntegralType a -> PrimFun (a -> a)- PrimBShiftL :: IntegralType a -> PrimFun ((a, Int) -> a)- PrimBShiftR :: IntegralType a -> PrimFun ((a, Int) -> a)- PrimBRotateL :: IntegralType a -> PrimFun ((a, Int) -> a)- PrimBRotateR :: IntegralType a -> PrimFun ((a, Int) -> a)- PrimPopCount :: IntegralType a -> PrimFun (a -> Int)- PrimCountLeadingZeros :: IntegralType a -> PrimFun (a -> Int)- PrimCountTrailingZeros :: IntegralType a -> PrimFun (a -> Int)-- -- operators from Fractional and Floating- PrimFDiv :: FloatingType a -> PrimFun ((a, a) -> a)- PrimRecip :: FloatingType a -> PrimFun (a -> a)- PrimSin :: FloatingType a -> PrimFun (a -> a)- PrimCos :: FloatingType a -> PrimFun (a -> a)- PrimTan :: FloatingType a -> PrimFun (a -> a)- PrimAsin :: FloatingType a -> PrimFun (a -> a)- PrimAcos :: FloatingType a -> PrimFun (a -> a)- PrimAtan :: FloatingType a -> PrimFun (a -> a)- PrimSinh :: FloatingType a -> PrimFun (a -> a)- PrimCosh :: FloatingType a -> PrimFun (a -> a)- PrimTanh :: FloatingType a -> PrimFun (a -> a)- PrimAsinh :: FloatingType a -> PrimFun (a -> a)- PrimAcosh :: FloatingType a -> PrimFun (a -> a)- PrimAtanh :: FloatingType a -> PrimFun (a -> a)- PrimExpFloating :: FloatingType a -> PrimFun (a -> a)- PrimSqrt :: FloatingType a -> PrimFun (a -> a)- PrimLog :: FloatingType a -> PrimFun (a -> a)- PrimFPow :: FloatingType a -> PrimFun ((a, a) -> a)- PrimLogBase :: FloatingType a -> PrimFun ((a, a) -> a)-- -- FIXME: add missing operations from RealFrac & RealFloat-- -- operators from RealFrac- PrimTruncate :: FloatingType a -> IntegralType b -> PrimFun (a -> b)- PrimRound :: FloatingType a -> IntegralType b -> PrimFun (a -> b)- PrimFloor :: FloatingType a -> IntegralType b -> PrimFun (a -> b)- PrimCeiling :: FloatingType a -> IntegralType b -> PrimFun (a -> b)- -- PrimProperFraction :: FloatingType a -> IntegralType b -> PrimFun (a -> (b, a))-- -- operators from RealFloat- PrimAtan2 :: FloatingType a -> PrimFun ((a, a) -> a)- PrimIsNaN :: FloatingType a -> PrimFun (a -> Bool)- PrimIsInfinite :: FloatingType a -> PrimFun (a -> Bool)- -- PrimFloatRadix :: FloatingType a -> PrimFun (a -> Int) -- Integer?- -- PrimFloatDigits :: FloatingType a -> PrimFun (a -> Int)- -- PrimFloatRange :: FloatingType a -> PrimFun (a -> (Int, Int))- -- PrimDecodeFloat :: FloatingType a -> PrimFun (a -> (Int, Int)) -- Integer?- -- PrimEncodeFloat :: FloatingType a -> PrimFun ((Int, Int) -> a) -- Integer?- -- PrimExponent :: FloatingType a -> PrimFun (a -> Int)- -- PrimSignificand :: FloatingType a -> PrimFun (a -> a)- -- PrimScaleFloat :: FloatingType a -> PrimFun ((Int, a) -> a)- -- PrimIsDenormalized :: FloatingType a -> PrimFun (a -> Bool)- -- PrimIsNegativeZero :: FloatingType a -> PrimFun (a -> Bool)- -- PrimIsIEEE :: FloatingType a -> PrimFun (a -> Bool)-- -- relational and equality operators- PrimLt :: ScalarType a -> PrimFun ((a, a) -> Bool)- PrimGt :: ScalarType a -> PrimFun ((a, a) -> Bool)- PrimLtEq :: ScalarType a -> PrimFun ((a, a) -> Bool)- PrimGtEq :: ScalarType a -> PrimFun ((a, a) -> Bool)- PrimEq :: ScalarType a -> PrimFun ((a, a) -> Bool)- PrimNEq :: ScalarType a -> PrimFun ((a, a) -> Bool)- PrimMax :: ScalarType a -> PrimFun ((a, a) -> a )- PrimMin :: ScalarType a -> PrimFun ((a, a) -> a )-- -- logical operators- PrimLAnd :: PrimFun ((Bool, Bool) -> Bool)- PrimLOr :: PrimFun ((Bool, Bool) -> Bool)- PrimLNot :: PrimFun (Bool -> Bool)-- -- character conversions- -- FIXME: use IntegralType?- PrimOrd :: PrimFun (Char -> Int)- PrimChr :: PrimFun (Int -> Char)-- -- boolean conversion- PrimBoolToInt :: PrimFun (Bool -> Int)-- -- general conversion between types- PrimFromIntegral :: IntegralType a -> NumType b -> PrimFun (a -> b)- PrimToFloating :: NumType a -> FloatingType b -> PrimFun (a -> b)-- -- reinterpret the bits of a value as a different type- -- (the two types must have the same bit size)- PrimCoerce :: ScalarType a -> ScalarType b -> PrimFun (a -> b)-- -- FIXME: Conversions between various integer types: should we have overloaded- -- functions like 'toInt'? (or 'fromEnum' for enums?)-- -- FIXME: What do we want to do about Enum? 'succ' and 'pred' are only- -- moderately useful without user-defined enumerations, but we want the range- -- constructs for arrays (but that's not scalar primitives)----- NFData instances--- ================--instance NFData (OpenAfun aenv f) where- rnf = rnfOpenAfun--instance NFData (OpenAcc aenv t) where- rnf = rnfOpenAcc---- instance NFData (Seq t) where--- rnf = rnfPreOpenSeq rnfOpenAcc--instance NFData (OpenExp env aenv t) where- rnf = rnfPreOpenExp rnfOpenAcc--instance NFData (OpenFun env aenv t) where- rnf = rnfPreOpenFun rnfOpenAcc----- Array expressions--- -------------------type NFDataAcc acc = forall aenv t. acc aenv t -> ()--rnfIdx :: Idx env t -> ()-rnfIdx ZeroIdx = ()-rnfIdx (SuccIdx ix) = rnfIdx ix--rnfTupleIdx :: TupleIdx t e -> ()-rnfTupleIdx ZeroTupIdx = ()-rnfTupleIdx (SuccTupIdx tix) = rnfTupleIdx tix--rnfOpenAfun :: OpenAfun aenv t -> ()-rnfOpenAfun = rnfPreOpenAfun rnfOpenAcc--rnfOpenAcc :: OpenAcc aenv t -> ()-rnfOpenAcc (OpenAcc pacc) = rnfPreOpenAcc rnfOpenAcc pacc--rnfPreOpenAfun :: NFDataAcc acc -> PreOpenAfun acc aenv t -> ()-rnfPreOpenAfun rnfA (Abody b) = rnfA b-rnfPreOpenAfun rnfA (Alam f) = rnfPreOpenAfun rnfA f--rnfPreOpenAcc :: forall acc aenv t. NFDataAcc acc -> PreOpenAcc acc aenv t -> ()-rnfPreOpenAcc rnfA pacc =- let- rnfAF :: PreOpenAfun acc aenv' t' -> ()- rnfAF = rnfPreOpenAfun rnfA-- rnfE :: PreOpenExp acc env' aenv' t' -> ()- rnfE = rnfPreOpenExp rnfA-- rnfF :: PreOpenFun acc env' aenv' t' -> ()- rnfF = rnfPreOpenFun rnfA-- -- rnfS :: PreOpenSeq acc aenv' senv' t' -> ()- -- rnfS = rnfPreOpenSeq rnfA-- rnfB :: PreBoundary acc aenv' (Array sh e) -> ()- rnfB = rnfBoundary rnfA- in- case pacc of- Alet bnd body -> rnfA bnd `seq` rnfA body- Avar ix -> rnfIdx ix- Atuple atup -> rnfAtuple rnfA atup- Aprj tix a -> rnfTupleIdx tix `seq` rnfA a- Apply afun acc -> rnfAF afun `seq` rnfA acc- Aforeign asm afun a -> rnf (strForeign asm) `seq` rnfAF afun `seq` rnfA a- Acond p a1 a2 -> rnfE p `seq` rnfA a1 `seq` rnfA a2- Awhile p f a -> rnfAF p `seq` rnfAF f `seq` rnfA a- Use arrs -> rnfArrays (arrays (undefined::t)) arrs- Unit x -> rnfE x- Reshape sh a -> rnfE sh `seq` rnfA a- Generate sh f -> rnfE sh `seq` rnfF f- Transform sh p f a -> rnfE sh `seq` rnfF p `seq` rnfF f `seq` rnfA a- Replicate slice sh a -> rnfSliceIndex slice `seq` rnfE sh `seq` rnfA a- Slice slice a sh -> rnfSliceIndex slice `seq` rnfE sh `seq` rnfA a- Map f a -> rnfF f `seq` rnfA a- ZipWith f a1 a2 -> rnfF f `seq` rnfA a1 `seq` rnfA a2- Fold f z a -> rnfF f `seq` rnfE z `seq` rnfA a- Fold1 f a -> rnfF f `seq` rnfA a- FoldSeg f z a s -> rnfF f `seq` rnfE z `seq` rnfA a `seq` rnfA s- Fold1Seg f a s -> rnfF f `seq` rnfA a `seq` rnfA s- Scanl f z a -> rnfF f `seq` rnfE z `seq` rnfA a- Scanl1 f a -> rnfF f `seq` rnfA a- Scanl' f z a -> rnfF f `seq` rnfE z `seq` rnfA a- Scanr f z a -> rnfF f `seq` rnfE z `seq` rnfA a- Scanr1 f a -> rnfF f `seq` rnfA a- Scanr' f z a -> rnfF f `seq` rnfE z `seq` rnfA a- Permute f d p a -> rnfF f `seq` rnfA d `seq` rnfF p `seq` rnfA a- Backpermute sh f a -> rnfE sh `seq` rnfF f `seq` rnfA a- Stencil f b a -> rnfF f `seq` rnfB b `seq` rnfA a- Stencil2 f b1 a1 b2 a2 -> rnfF f `seq` rnfB b1 `seq` rnfB b2 `seq` rnfA a1 `seq` rnfA a2- -- Collect s -> rnfS s---rnfAtuple :: NFDataAcc acc -> Atuple (acc aenv) t -> ()-rnfAtuple _ NilAtup = ()-rnfAtuple rnfA (SnocAtup tup a) = rnfAtuple rnfA tup `seq` rnfA a--rnfArrays :: ArraysR arrs -> arrs -> ()-rnfArrays ArraysRunit () = ()-rnfArrays ArraysRarray arr = rnf arr-rnfArrays (ArraysRpair ar1 ar2) (a1,a2) = rnfArrays ar1 a1 `seq` rnfArrays ar2 a2--rnfBoundary :: forall acc aenv sh e. NFDataAcc acc -> PreBoundary acc aenv (Array sh e) -> ()-rnfBoundary _ Clamp = ()-rnfBoundary _ Mirror = ()-rnfBoundary _ Wrap = ()-rnfBoundary _ (Constant c) = rnfConst (eltType (undefined::e)) c-rnfBoundary rnfA (Function f) = rnfPreOpenFun rnfA f---{----- Sequence expressions--- ----------------------rnfPreOpenSeq :: forall acc aenv senv t. NFDataAcc acc -> PreOpenSeq acc aenv senv t -> ()-rnfPreOpenSeq rnfA topSeq =- let- rnfS :: PreOpenSeq acc aenv' senv' t' -> ()- rnfS = rnfPreOpenSeq rnfA-- rnfP :: Producer acc aenv' senv' t' -> ()- rnfP = rnfSeqProducer rnfA-- rnfC :: Consumer acc aenv' senv' t' -> ()- rnfC = rnfSeqConsumer rnfA- in- case topSeq of- Producer p s -> rnfP p `seq` rnfS s- Consumer c -> rnfC c- Reify ix -> rnfIdx ix--rnfSeqProducer :: forall acc aenv senv t. NFDataAcc acc -> Producer acc aenv senv t -> ()-rnfSeqProducer rnfA topSeq =- let- rnfArrs :: forall a. Arrays a => [a] -> ()- rnfArrs [] = ()- rnfArrs (a:as) = rnfArrays (arrays (undefined::a)) (fromArr a) `seq` rnfArrs as-- rnfAF :: PreOpenAfun acc aenv' t' -> ()- rnfAF = rnfPreOpenAfun rnfA-- rnfF :: PreOpenFun acc env' aenv' t' -> ()- rnfF = rnfPreOpenFun rnfA-- rnfE :: PreOpenExp acc env' aenv' t' -> ()- rnfE = rnfPreOpenExp rnfA- in- case topSeq of- StreamIn as -> rnfArrs as- ToSeq slice _ a -> rnfSliceIndex slice `seq` rnfA a- MapSeq f ix -> rnfAF f `seq` rnfIdx ix- ChunkedMapSeq f ix -> rnfAF f `seq` rnfIdx ix- ZipWithSeq f ix1 ix2 -> rnfAF f `seq` rnfIdx ix1 `seq` rnfIdx ix2- ScanSeq f z ix -> rnfF f `seq` rnfE z `seq` rnfIdx ix--rnfSeqConsumer :: forall acc aenv senv t. NFDataAcc acc -> Consumer acc aenv senv t -> ()-rnfSeqConsumer rnfA topSeq =- let- rnfAF :: PreOpenAfun acc aenv' t' -> ()- rnfAF = rnfPreOpenAfun rnfA-- rnfF :: PreOpenFun acc env' aenv' t' -> ()- rnfF = rnfPreOpenFun rnfA-- rnfE :: PreOpenExp acc env' aenv' t' -> ()- rnfE = rnfPreOpenExp rnfA- in- case topSeq of- FoldSeq f z ix -> rnfF f `seq` rnfE z `seq` rnfIdx ix- FoldSeqFlatten f a ix -> rnfAF f `seq` rnfA a `seq` rnfIdx ix- Stuple stup -> rnfStuple rnfA stup--rnfStuple :: NFDataAcc acc -> Atuple (Consumer acc aenv senv) t -> ()-rnfStuple _ NilAtup = ()-rnfStuple rnfA (SnocAtup tup c) = rnfStuple rnfA tup `seq` rnfSeqConsumer rnfA c---}---- Scalar expressions--- --------------------rnfPreOpenFun :: NFDataAcc acc -> PreOpenFun acc env aenv t -> ()-rnfPreOpenFun rnfA (Body b) = rnfPreOpenExp rnfA b-rnfPreOpenFun rnfA (Lam f) = rnfPreOpenFun rnfA f--rnfPreOpenExp :: forall acc env aenv t. NFDataAcc acc -> PreOpenExp acc env aenv t -> ()-rnfPreOpenExp rnfA topExp =- let- rnfF :: PreOpenFun acc env' aenv' t' -> ()- rnfF = rnfPreOpenFun rnfA-- rnfE :: PreOpenExp acc env' aenv' t' -> ()- rnfE = rnfPreOpenExp rnfA- in- case topExp of- Let bnd body -> rnfE bnd `seq` rnfE body- Var ix -> rnfIdx ix- Foreign asm f x -> rnf (strForeign asm) `seq` rnfF f `seq` rnfE x- Const t -> rnfConst (eltType (undefined::t)) t- Tuple t -> rnfTuple rnfA t- Prj ix e -> rnfTupleIdx ix `seq` rnfE e- IndexNil -> ()- IndexCons sh sz -> rnfE sh `seq` rnfE sz- IndexHead sh -> rnfE sh- IndexTail sh -> rnfE sh- IndexAny -> ()- IndexSlice slice slix sh -> rnfSliceIndex slice `seq` rnfE slix `seq` rnfE sh- IndexFull slice slix sl -> rnfSliceIndex slice `seq` rnfE slix `seq` rnfE sl- ToIndex sh ix -> rnfE sh `seq` rnfE ix- FromIndex sh ix -> rnfE sh `seq` rnfE ix- Cond p e1 e2 -> rnfE p `seq` rnfE e1 `seq` rnfE e2- While p f x -> rnfF p `seq` rnfF f `seq` rnfE x- PrimConst c -> rnfPrimConst c- PrimApp f x -> rnfPrimFun f `seq` rnfE x- Index a ix -> rnfA a `seq` rnfE ix- LinearIndex a ix -> rnfA a `seq` rnfE ix- Shape a -> rnfA a- ShapeSize sh -> rnfE sh- Intersect sh1 sh2 -> rnfE sh1 `seq` rnfE sh2- Union sh1 sh2 -> rnfE sh1 `seq` rnfE sh2--rnfTuple :: NFDataAcc acc -> Tuple (PreOpenExp acc env aenv) t -> ()-rnfTuple _ NilTup = ()-rnfTuple rnfA (SnocTup t e) = rnfTuple rnfA t `seq` rnfPreOpenExp rnfA e--rnfConst :: TupleType t -> t -> ()-rnfConst UnitTuple () = ()-rnfConst (SingleTuple t) !_ = rnfScalarType t -- scalars should have (nf == whnf)-rnfConst (PairTuple ta tb) (a,b) = rnfConst ta a `seq` rnfConst tb b--rnfPrimConst :: PrimConst c -> ()-rnfPrimConst (PrimMinBound t) = rnfBoundedType t-rnfPrimConst (PrimMaxBound t) = rnfBoundedType t-rnfPrimConst (PrimPi t) = rnfFloatingType t--rnfPrimFun :: PrimFun f -> ()-rnfPrimFun (PrimAdd t) = rnfNumType t-rnfPrimFun (PrimSub t) = rnfNumType t-rnfPrimFun (PrimMul t) = rnfNumType t-rnfPrimFun (PrimNeg t) = rnfNumType t-rnfPrimFun (PrimAbs t) = rnfNumType t-rnfPrimFun (PrimSig t) = rnfNumType t-rnfPrimFun (PrimQuot t) = rnfIntegralType t-rnfPrimFun (PrimRem t) = rnfIntegralType t-rnfPrimFun (PrimQuotRem t) = rnfIntegralType t-rnfPrimFun (PrimIDiv t) = rnfIntegralType t-rnfPrimFun (PrimMod t) = rnfIntegralType t-rnfPrimFun (PrimDivMod t) = rnfIntegralType t-rnfPrimFun (PrimBAnd t) = rnfIntegralType t-rnfPrimFun (PrimBOr t) = rnfIntegralType t-rnfPrimFun (PrimBXor t) = rnfIntegralType t-rnfPrimFun (PrimBNot t) = rnfIntegralType t-rnfPrimFun (PrimBShiftL t) = rnfIntegralType t-rnfPrimFun (PrimBShiftR t) = rnfIntegralType t-rnfPrimFun (PrimBRotateL t) = rnfIntegralType t-rnfPrimFun (PrimBRotateR t) = rnfIntegralType t-rnfPrimFun (PrimPopCount t) = rnfIntegralType t-rnfPrimFun (PrimCountLeadingZeros t) = rnfIntegralType t-rnfPrimFun (PrimCountTrailingZeros t) = rnfIntegralType t-rnfPrimFun (PrimFDiv t) = rnfFloatingType t-rnfPrimFun (PrimRecip t) = rnfFloatingType t-rnfPrimFun (PrimSin t) = rnfFloatingType t-rnfPrimFun (PrimCos t) = rnfFloatingType t-rnfPrimFun (PrimTan t) = rnfFloatingType t-rnfPrimFun (PrimAsin t) = rnfFloatingType t-rnfPrimFun (PrimAcos t) = rnfFloatingType t-rnfPrimFun (PrimAtan t) = rnfFloatingType t-rnfPrimFun (PrimSinh t) = rnfFloatingType t-rnfPrimFun (PrimCosh t) = rnfFloatingType t-rnfPrimFun (PrimTanh t) = rnfFloatingType t-rnfPrimFun (PrimAsinh t) = rnfFloatingType t-rnfPrimFun (PrimAcosh t) = rnfFloatingType t-rnfPrimFun (PrimAtanh t) = rnfFloatingType t-rnfPrimFun (PrimExpFloating t) = rnfFloatingType t-rnfPrimFun (PrimSqrt t) = rnfFloatingType t-rnfPrimFun (PrimLog t) = rnfFloatingType t-rnfPrimFun (PrimFPow t) = rnfFloatingType t-rnfPrimFun (PrimLogBase t) = rnfFloatingType t-rnfPrimFun (PrimTruncate f i) = rnfFloatingType f `seq` rnfIntegralType i-rnfPrimFun (PrimRound f i) = rnfFloatingType f `seq` rnfIntegralType i-rnfPrimFun (PrimFloor f i) = rnfFloatingType f `seq` rnfIntegralType i-rnfPrimFun (PrimCeiling f i) = rnfFloatingType f `seq` rnfIntegralType i-rnfPrimFun (PrimIsNaN t) = rnfFloatingType t-rnfPrimFun (PrimIsInfinite t) = rnfFloatingType t-rnfPrimFun (PrimAtan2 t) = rnfFloatingType t-rnfPrimFun (PrimLt t) = rnfScalarType t-rnfPrimFun (PrimGt t) = rnfScalarType t-rnfPrimFun (PrimLtEq t) = rnfScalarType t-rnfPrimFun (PrimGtEq t) = rnfScalarType t-rnfPrimFun (PrimEq t) = rnfScalarType t-rnfPrimFun (PrimNEq t) = rnfScalarType t-rnfPrimFun (PrimMax t) = rnfScalarType t-rnfPrimFun (PrimMin t) = rnfScalarType t-rnfPrimFun PrimLAnd = ()-rnfPrimFun PrimLOr = ()-rnfPrimFun PrimLNot = ()-rnfPrimFun PrimOrd = ()-rnfPrimFun PrimChr = ()-rnfPrimFun PrimBoolToInt = ()-rnfPrimFun (PrimFromIntegral i n) = rnfIntegralType i `seq` rnfNumType n-rnfPrimFun (PrimToFloating n f) = rnfNumType n `seq` rnfFloatingType f-rnfPrimFun (PrimCoerce a b) = rnfScalarType a `seq` rnfScalarType b--rnfSliceIndex :: SliceIndex ix slice co sh -> ()-rnfSliceIndex SliceNil = ()-rnfSliceIndex (SliceAll sh) = rnfSliceIndex sh-rnfSliceIndex (SliceFixed sh) = rnfSliceIndex sh--rnfScalarType :: ScalarType t -> ()-rnfScalarType (NumScalarType t) = rnfNumType t-rnfScalarType (NonNumScalarType t) = rnfNonNumType t--rnfBoundedType :: BoundedType t -> ()-rnfBoundedType (IntegralBoundedType t) = rnfIntegralType t-rnfBoundedType (NonNumBoundedType t) = rnfNonNumType t--rnfNumType :: NumType t -> ()-rnfNumType (IntegralNumType t) = rnfIntegralType t-rnfNumType (FloatingNumType t) = rnfFloatingType t--rnfNonNumType :: NonNumType t -> ()-rnfNonNumType (TypeBool NonNumDict) = ()-rnfNonNumType (TypeChar NonNumDict) = ()-rnfNonNumType (TypeCChar NonNumDict) = ()-rnfNonNumType (TypeCSChar NonNumDict) = ()-rnfNonNumType (TypeCUChar NonNumDict) = ()--rnfIntegralType :: IntegralType t -> ()-rnfIntegralType (TypeInt IntegralDict) = ()-rnfIntegralType (TypeInt8 IntegralDict) = ()-rnfIntegralType (TypeInt16 IntegralDict) = ()-rnfIntegralType (TypeInt32 IntegralDict) = ()-rnfIntegralType (TypeInt64 IntegralDict) = ()-rnfIntegralType (TypeWord IntegralDict) = ()-rnfIntegralType (TypeWord8 IntegralDict) = ()-rnfIntegralType (TypeWord16 IntegralDict) = ()-rnfIntegralType (TypeWord32 IntegralDict) = ()-rnfIntegralType (TypeWord64 IntegralDict) = ()-rnfIntegralType (TypeCShort IntegralDict) = ()-rnfIntegralType (TypeCUShort IntegralDict) = ()-rnfIntegralType (TypeCInt IntegralDict) = ()-rnfIntegralType (TypeCUInt IntegralDict) = ()-rnfIntegralType (TypeCLong IntegralDict) = ()-rnfIntegralType (TypeCULong IntegralDict) = ()-rnfIntegralType (TypeCLLong IntegralDict) = ()-rnfIntegralType (TypeCULLong IntegralDict) = ()--rnfFloatingType :: FloatingType t -> ()-rnfFloatingType (TypeFloat FloatingDict) = ()-rnfFloatingType (TypeDouble FloatingDict) = ()-rnfFloatingType (TypeCFloat FloatingDict) = ()-rnfFloatingType (TypeCDouble FloatingDict) = ()----- Template Haskell--- ================--type LiftAcc acc = forall aenv a. acc aenv a -> Q (TExp (acc aenv a))--liftIdx :: Idx env t -> Q (TExp (Idx env t))-liftIdx ZeroIdx = [|| ZeroIdx ||]-liftIdx (SuccIdx ix) = [|| SuccIdx $$(liftIdx ix) ||]--liftTupleIdx :: TupleIdx t e -> Q (TExp (TupleIdx t e))-liftTupleIdx ZeroTupIdx = [|| ZeroTupIdx ||]-liftTupleIdx (SuccTupIdx tix) = [|| SuccTupIdx $$(liftTupleIdx tix) ||]---liftPreOpenAfun :: LiftAcc acc -> PreOpenAfun acc aenv t -> Q (TExp (PreOpenAfun acc aenv t))-liftPreOpenAfun liftA (Alam f) = [|| Alam $$(liftPreOpenAfun liftA f) ||]-liftPreOpenAfun liftA (Abody b) = [|| Abody $$(liftA b) ||]--liftPreOpenAcc- :: forall acc aenv a.- LiftAcc acc- -> PreOpenAcc acc aenv a- -> Q (TExp (PreOpenAcc acc aenv a))-liftPreOpenAcc liftA pacc =- let- liftE :: PreOpenExp acc env aenv t -> Q (TExp (PreOpenExp acc env aenv t))- liftE = liftPreOpenExp liftA-- liftF :: PreOpenFun acc env aenv t -> Q (TExp (PreOpenFun acc env aenv t))- liftF = liftPreOpenFun liftA-- liftAF :: PreOpenAfun acc aenv f -> Q (TExp (PreOpenAfun acc aenv f))- liftAF = liftPreOpenAfun liftA-- liftB :: PreBoundary acc aenv (Array sh e) -> Q (TExp (PreBoundary acc aenv (Array sh e)))- liftB = liftBoundary liftA-- liftAtuple :: Atuple (acc aenv) t -> Q (TExp (Atuple (acc aenv) t))- liftAtuple NilAtup = [|| NilAtup ||]- liftAtuple (SnocAtup tup a) = [|| SnocAtup $$(liftAtuple tup) $$(liftA a) ||]- in- case pacc of- Alet bnd body -> [|| Alet $$(liftA bnd) $$(liftA body) ||]- Avar ix -> [|| Avar $$(liftIdx ix) ||]- Atuple tup -> [|| Atuple $$(liftAtuple tup) ||]- Aprj tix a -> [|| Aprj $$(liftTupleIdx tix) $$(liftA a) ||]- Apply f a -> [|| Apply $$(liftAF f) $$(liftA a) ||]- Aforeign asm f a -> [|| Aforeign $$(liftForeign asm) $$(liftPreOpenAfun liftA f) $$(liftA a) ||]- Acond p t e -> [|| Acond $$(liftE p) $$(liftA t) $$(liftA e) ||]- Awhile p f a -> [|| Awhile $$(liftAF p) $$(liftAF f) $$(liftA a) ||]- Use a -> [|| Use $$(liftArrays (arrays (undefined::a)) a) ||]- Unit e -> [|| Unit $$(liftE e) ||]- Reshape sh a -> [|| Reshape $$(liftE sh) $$(liftA a) ||]- Generate sh f -> [|| Generate $$(liftE sh) $$(liftF f) ||]- Transform sh p f a -> [|| Transform $$(liftE sh) $$(liftF p) $$(liftF f) $$(liftA a) ||]- Replicate slix sl a -> [|| Replicate $$(liftSliceIndex slix) $$(liftE sl) $$(liftA a) ||]- Slice slix a sh -> [|| Slice $$(liftSliceIndex slix) $$(liftA a) $$(liftE sh) ||]- Map f a -> [|| Map $$(liftF f) $$(liftA a) ||]- ZipWith f a b -> [|| ZipWith $$(liftF f) $$(liftA a) $$(liftA b) ||]- Fold f z a -> [|| Fold $$(liftF f) $$(liftE z) $$(liftA a) ||]- Fold1 f a -> [|| Fold1 $$(liftF f) $$(liftA a) ||]- FoldSeg f z a s -> [|| FoldSeg $$(liftF f) $$(liftE z) $$(liftA a) $$(liftA s) ||]- Fold1Seg f a s -> [|| Fold1Seg $$(liftF f) $$(liftA a) $$(liftA s) ||]- Scanl f z a -> [|| Scanl $$(liftF f) $$(liftE z) $$(liftA a) ||]- Scanl1 f a -> [|| Scanl1 $$(liftF f) $$(liftA a) ||]- Scanl' f z a -> [|| Scanl' $$(liftF f) $$(liftE z) $$(liftA a) ||]- Scanr f z a -> [|| Scanr $$(liftF f) $$(liftE z) $$(liftA a) ||]- Scanr1 f a -> [|| Scanr1 $$(liftF f) $$(liftA a) ||]- Scanr' f z a -> [|| Scanr' $$(liftF f) $$(liftE z) $$(liftA a) ||]- Permute f d p a -> [|| Permute $$(liftF f) $$(liftA d) $$(liftF p) $$(liftA a) ||]- Backpermute sh p a -> [|| Backpermute $$(liftE sh) $$(liftF p) $$(liftA a) ||]- Stencil f b a -> [|| Stencil $$(liftF f) $$(liftB b) $$(liftA a) ||]- Stencil2 f b1 a1 b2 a2 -> [|| Stencil2 $$(liftF f) $$(liftB b1) $$(liftA a1) $$(liftB b2) $$(liftA a2) ||]---liftPreOpenFun- :: LiftAcc acc- -> PreOpenFun acc env aenv t- -> Q (TExp (PreOpenFun acc env aenv t))-liftPreOpenFun liftA (Lam f) = [|| Lam $$(liftPreOpenFun liftA f) ||]-liftPreOpenFun liftA (Body b) = [|| Body $$(liftPreOpenExp liftA b) ||]--liftPreOpenExp- :: forall acc env aenv t.- LiftAcc acc- -> PreOpenExp acc env aenv t- -> Q (TExp (PreOpenExp acc env aenv t))-liftPreOpenExp liftA pexp =- let- liftE :: PreOpenExp acc env aenv e -> Q (TExp (PreOpenExp acc env aenv e))- liftE = liftPreOpenExp liftA-- liftF :: PreOpenFun acc env aenv f -> Q (TExp (PreOpenFun acc env aenv f))- liftF = liftPreOpenFun liftA-- liftT :: Tuple (PreOpenExp acc env aenv) e -> Q (TExp (Tuple (PreOpenExp acc env aenv) e))- liftT NilTup = [|| NilTup ||]- liftT (SnocTup tup e) = [|| SnocTup $$(liftT tup) $$(liftE e) ||]- in- case pexp of- Let bnd body -> [|| Let $$(liftPreOpenExp liftA bnd) $$(liftPreOpenExp liftA body) ||]- Var ix -> [|| Var $$(liftIdx ix) ||]- Foreign asm f x -> [|| Foreign $$(liftForeign asm) $$(liftPreOpenFun liftA f) $$(liftE x) ||]- Const c -> [|| Const $$(liftConst (eltType (undefined::t)) c) ||]- Tuple tup -> [|| Tuple $$(liftT tup) ||]- Prj tix e -> [|| Prj $$(liftTupleIdx tix) $$(liftE e) ||]- IndexNil -> [|| IndexNil ||]- IndexCons sh sz -> [|| IndexCons $$(liftE sh) $$(liftE sz) ||]- IndexHead sh -> [|| IndexHead $$(liftE sh) ||]- IndexTail sh -> [|| IndexTail $$(liftE sh) ||]- IndexAny -> [|| IndexAny ||]- IndexSlice slice slix sh -> [|| IndexSlice $$(liftSliceIndex slice) $$(liftE slix) $$(liftE sh) ||]- IndexFull slice slix sl -> [|| IndexFull $$(liftSliceIndex slice) $$(liftE slix) $$(liftE sl) ||]- ToIndex sh ix -> [|| ToIndex $$(liftE sh) $$(liftE ix) ||]- FromIndex sh ix -> [|| FromIndex $$(liftE sh) $$(liftE ix) ||]- Cond p t e -> [|| Cond $$(liftE p) $$(liftE t) $$(liftE e) ||]- While p f x -> [|| While $$(liftF p) $$(liftF f) $$(liftE x) ||]- PrimConst t -> [|| PrimConst $$(liftPrimConst t) ||]- PrimApp f x -> [|| PrimApp $$(liftPrimFun f) $$(liftE x) ||]- Index a ix -> [|| Index $$(liftA a) $$(liftE ix) ||]- LinearIndex a ix -> [|| LinearIndex $$(liftA a) $$(liftE ix) ||]- Shape a -> [|| Shape $$(liftA a) ||]- ShapeSize ix -> [|| ShapeSize $$(liftE ix) ||]- Intersect sh1 sh2 -> [|| Intersect $$(liftE sh1) $$(liftE sh2) ||]- Union sh1 sh2 -> [|| Union $$(liftE sh1) $$(liftE sh2) ||]---liftArrays :: ArraysR arr -> arr -> Q (TExp arr)-liftArrays ArraysRunit () = [|| () ||]-liftArrays ArraysRarray arr = [|| $$(liftArray arr) ||]-liftArrays (ArraysRpair r1 r2) (a1,a2) = [|| ($$(liftArrays r1 a1), $$(liftArrays r2 a2)) ||]--liftArray :: forall sh e. Array sh e -> Q (TExp (Array sh e))-liftArray (Array sh adata) =- [|| Array $$(liftConst (eltType (undefined::sh)) sh) $$(go arrayElt adata) ||] `sigE` typeRepToType (typeOf (undefined::Array sh e))- where- sz :: Int- sz = size sh-- sigE :: Q (TExp t) -> Q TH.Type -> Q (TExp t)- sigE e t = TH.unsafeTExpCoerce $ TH.sigE (TH.unTypeQ e) t-- typeRepToType :: TypeRep -> Q TH.Type- typeRepToType trep = do- let (con, args) = splitTyConApp trep- name = TH.Name (TH.OccName (tyConName con)) (TH.NameG TH.TcClsName (TH.PkgName (tyConPackage con)) (TH.ModName (tyConModule con)))- --- appsT x [] = x- appsT x (y:xs) = appsT (TH.AppT x y) xs- --- resultArgs <- mapM typeRepToType args- return (appsT (TH.ConT name) resultArgs)-- -- TODO: make sure that the resulting array is 16-byte aligned...- arr :: forall a. (ArrayElt a, Storable a) => UniqueArray a -> Q (TExp (UniqueArray a))- arr ua = do- bytes <- TH.runIO $ peekArray (sizeOf (undefined::a) * sz) (castPtr (unsafeUniqueArrayPtr ua) :: Ptr Word8)- [|| unsafePerformIO $ do- fp <- newForeignPtr_ $$( TH.unsafeTExpCoerce [| Ptr $(TH.litE (TH.StringPrimL bytes)) |] )- ua' <- newUniqueArray (castForeignPtr fp)- return ua'- ||]-- go :: ArrayEltR e' -> ArrayData e' -> Q (TExp (ArrayData e'))- go ArrayEltRunit AD_Unit = [|| AD_Unit ||]- go ArrayEltRint (AD_Int ua) = [|| AD_Int $$(arr ua) ||]- go ArrayEltRint8 (AD_Int8 ua) = [|| AD_Int8 $$(arr ua) ||]- go ArrayEltRint16 (AD_Int16 ua) = [|| AD_Int16 $$(arr ua) ||]- go ArrayEltRint32 (AD_Int32 ua) = [|| AD_Int32 $$(arr ua) ||]- go ArrayEltRint64 (AD_Int64 ua) = [|| AD_Int64 $$(arr ua) ||]- go ArrayEltRword (AD_Word ua) = [|| AD_Word $$(arr ua) ||]- go ArrayEltRword8 (AD_Word8 ua) = [|| AD_Word8 $$(arr ua) ||]- go ArrayEltRword16 (AD_Word16 ua) = [|| AD_Word16 $$(arr ua) ||]- go ArrayEltRword32 (AD_Word32 ua) = [|| AD_Word32 $$(arr ua) ||]- go ArrayEltRword64 (AD_Word64 ua) = [|| AD_Word64 $$(arr ua) ||]- go ArrayEltRcshort (AD_CShort ua) = [|| AD_CShort $$(arr ua) ||]- go ArrayEltRcushort (AD_CUShort ua) = [|| AD_CUShort $$(arr ua) ||]- go ArrayEltRcint (AD_CInt ua) = [|| AD_CInt $$(arr ua) ||]- go ArrayEltRcuint (AD_CUInt ua) = [|| AD_CUInt $$(arr ua) ||]- go ArrayEltRclong (AD_CLong ua) = [|| AD_CLong $$(arr ua) ||]- go ArrayEltRculong (AD_CULong ua) = [|| AD_CULong $$(arr ua) ||]- go ArrayEltRcllong (AD_CLLong ua) = [|| AD_CLLong $$(arr ua) ||]- go ArrayEltRcullong (AD_CULLong ua) = [|| AD_CULLong $$(arr ua) ||]- go ArrayEltRfloat (AD_Float ua) = [|| AD_Float $$(arr ua) ||]- go ArrayEltRdouble (AD_Double ua) = [|| AD_Double $$(arr ua) ||]- go ArrayEltRcfloat (AD_CFloat ua) = [|| AD_CFloat $$(arr ua) ||]- go ArrayEltRcdouble (AD_CDouble ua) = [|| AD_CDouble $$(arr ua) ||]- go ArrayEltRbool (AD_Bool ua) = [|| AD_Bool $$(arr ua) ||]- go ArrayEltRchar (AD_Char ua) = [|| AD_Char $$(arr ua) ||]- go ArrayEltRcchar (AD_CChar ua) = [|| AD_CChar $$(arr ua) ||]- go ArrayEltRcschar (AD_CSChar ua) = [|| AD_CSChar $$(arr ua) ||]- go ArrayEltRcuchar (AD_CUChar ua) = [|| AD_CUChar $$(arr ua) ||]- go (ArrayEltRpair r1 r2) (AD_Pair a1 a2) = [|| AD_Pair $$(go r1 a1) $$(go r2 a2) ||]---liftBoundary- :: forall acc aenv sh e.- LiftAcc acc- -> PreBoundary acc aenv (Array sh e)- -> Q (TExp (PreBoundary acc aenv (Array sh e)))-liftBoundary _ Clamp = [|| Clamp ||]-liftBoundary _ Mirror = [|| Mirror ||]-liftBoundary _ Wrap = [|| Wrap ||]-liftBoundary _ (Constant v) = [|| Constant $$(liftConst (eltType (undefined::e)) v) ||]-liftBoundary liftA (Function f) = [|| Function $$(liftPreOpenFun liftA f) ||]--liftSliceIndex :: SliceIndex ix slice coSlice sliceDim -> Q (TExp (SliceIndex ix slice coSlice sliceDim))-liftSliceIndex SliceNil = [|| SliceNil ||]-liftSliceIndex (SliceAll rest) = [|| SliceAll $$(liftSliceIndex rest) ||]-liftSliceIndex (SliceFixed rest) = [|| SliceFixed $$(liftSliceIndex rest) ||]--liftPrimConst :: PrimConst c -> Q (TExp (PrimConst c))-liftPrimConst (PrimMinBound t) = [|| PrimMinBound $$(liftBoundedType t) ||]-liftPrimConst (PrimMaxBound t) = [|| PrimMaxBound $$(liftBoundedType t) ||]-liftPrimConst (PrimPi t) = [|| PrimPi $$(liftFloatingType t) ||]--liftPrimFun :: PrimFun f -> Q (TExp (PrimFun f))-liftPrimFun (PrimAdd t) = [|| PrimAdd $$(liftNumType t) ||]-liftPrimFun (PrimSub t) = [|| PrimSub $$(liftNumType t) ||]-liftPrimFun (PrimMul t) = [|| PrimMul $$(liftNumType t) ||]-liftPrimFun (PrimNeg t) = [|| PrimNeg $$(liftNumType t) ||]-liftPrimFun (PrimAbs t) = [|| PrimAbs $$(liftNumType t) ||]-liftPrimFun (PrimSig t) = [|| PrimSig $$(liftNumType t) ||]-liftPrimFun (PrimQuot t) = [|| PrimQuot $$(liftIntegralType t) ||]-liftPrimFun (PrimRem t) = [|| PrimRem $$(liftIntegralType t) ||]-liftPrimFun (PrimQuotRem t) = [|| PrimQuotRem $$(liftIntegralType t) ||]-liftPrimFun (PrimIDiv t) = [|| PrimIDiv $$(liftIntegralType t) ||]-liftPrimFun (PrimMod t) = [|| PrimMod $$(liftIntegralType t) ||]-liftPrimFun (PrimDivMod t) = [|| PrimDivMod $$(liftIntegralType t) ||]-liftPrimFun (PrimBAnd t) = [|| PrimBAnd $$(liftIntegralType t) ||]-liftPrimFun (PrimBOr t) = [|| PrimBOr $$(liftIntegralType t) ||]-liftPrimFun (PrimBXor t) = [|| PrimBXor $$(liftIntegralType t) ||]-liftPrimFun (PrimBNot t) = [|| PrimBNot $$(liftIntegralType t) ||]-liftPrimFun (PrimBShiftL t) = [|| PrimBShiftL $$(liftIntegralType t) ||]-liftPrimFun (PrimBShiftR t) = [|| PrimBShiftR $$(liftIntegralType t) ||]-liftPrimFun (PrimBRotateL t) = [|| PrimBRotateL $$(liftIntegralType t) ||]-liftPrimFun (PrimBRotateR t) = [|| PrimBRotateR $$(liftIntegralType t) ||]-liftPrimFun (PrimPopCount t) = [|| PrimPopCount $$(liftIntegralType t) ||]-liftPrimFun (PrimCountLeadingZeros t) = [|| PrimCountLeadingZeros $$(liftIntegralType t) ||]-liftPrimFun (PrimCountTrailingZeros t) = [|| PrimCountTrailingZeros $$(liftIntegralType t) ||]-liftPrimFun (PrimFDiv t) = [|| PrimFDiv $$(liftFloatingType t) ||]-liftPrimFun (PrimRecip t) = [|| PrimRecip $$(liftFloatingType t) ||]-liftPrimFun (PrimSin t) = [|| PrimSin $$(liftFloatingType t) ||]-liftPrimFun (PrimCos t) = [|| PrimCos $$(liftFloatingType t) ||]-liftPrimFun (PrimTan t) = [|| PrimTan $$(liftFloatingType t) ||]-liftPrimFun (PrimAsin t) = [|| PrimAsin $$(liftFloatingType t) ||]-liftPrimFun (PrimAcos t) = [|| PrimAcos $$(liftFloatingType t) ||]-liftPrimFun (PrimAtan t) = [|| PrimAtan $$(liftFloatingType t) ||]-liftPrimFun (PrimSinh t) = [|| PrimSinh $$(liftFloatingType t) ||]-liftPrimFun (PrimCosh t) = [|| PrimCosh $$(liftFloatingType t) ||]-liftPrimFun (PrimTanh t) = [|| PrimTanh $$(liftFloatingType t) ||]-liftPrimFun (PrimAsinh t) = [|| PrimAsinh $$(liftFloatingType t) ||]-liftPrimFun (PrimAcosh t) = [|| PrimAcosh $$(liftFloatingType t) ||]-liftPrimFun (PrimAtanh t) = [|| PrimAtanh $$(liftFloatingType t) ||]-liftPrimFun (PrimExpFloating t) = [|| PrimExpFloating $$(liftFloatingType t) ||]-liftPrimFun (PrimSqrt t) = [|| PrimSqrt $$(liftFloatingType t) ||]-liftPrimFun (PrimLog t) = [|| PrimLog $$(liftFloatingType t) ||]-liftPrimFun (PrimFPow t) = [|| PrimFPow $$(liftFloatingType t) ||]-liftPrimFun (PrimLogBase t) = [|| PrimLogBase $$(liftFloatingType t) ||]-liftPrimFun (PrimTruncate ta tb) = [|| PrimTruncate $$(liftFloatingType ta) $$(liftIntegralType tb) ||]-liftPrimFun (PrimRound ta tb) = [|| PrimRound $$(liftFloatingType ta) $$(liftIntegralType tb) ||]-liftPrimFun (PrimFloor ta tb) = [|| PrimFloor $$(liftFloatingType ta) $$(liftIntegralType tb) ||]-liftPrimFun (PrimCeiling ta tb) = [|| PrimCeiling $$(liftFloatingType ta) $$(liftIntegralType tb) ||]-liftPrimFun (PrimIsNaN t) = [|| PrimIsNaN $$(liftFloatingType t) ||]-liftPrimFun (PrimIsInfinite t) = [|| PrimIsInfinite $$(liftFloatingType t) ||]-liftPrimFun (PrimAtan2 t) = [|| PrimAtan2 $$(liftFloatingType t) ||]-liftPrimFun (PrimLt t) = [|| PrimLt $$(liftScalarType t) ||]-liftPrimFun (PrimGt t) = [|| PrimGt $$(liftScalarType t) ||]-liftPrimFun (PrimLtEq t) = [|| PrimLtEq $$(liftScalarType t) ||]-liftPrimFun (PrimGtEq t) = [|| PrimGtEq $$(liftScalarType t) ||]-liftPrimFun (PrimEq t) = [|| PrimEq $$(liftScalarType t) ||]-liftPrimFun (PrimNEq t) = [|| PrimNEq $$(liftScalarType t) ||]-liftPrimFun (PrimMax t) = [|| PrimMax $$(liftScalarType t) ||]-liftPrimFun (PrimMin t) = [|| PrimMin $$(liftScalarType t) ||]-liftPrimFun PrimLAnd = [|| PrimLAnd ||]-liftPrimFun PrimLOr = [|| PrimLOr ||]-liftPrimFun PrimLNot = [|| PrimLNot ||]-liftPrimFun PrimOrd = [|| PrimOrd ||]-liftPrimFun PrimChr = [|| PrimChr ||]-liftPrimFun PrimBoolToInt = [|| PrimBoolToInt ||]-liftPrimFun (PrimFromIntegral ta tb) = [|| PrimFromIntegral $$(liftIntegralType ta) $$(liftNumType tb) ||]-liftPrimFun (PrimToFloating ta tb) = [|| PrimToFloating $$(liftNumType ta) $$(liftFloatingType tb) ||]-liftPrimFun (PrimCoerce ta tb) = [|| PrimCoerce $$(liftScalarType ta) $$(liftScalarType tb) ||]---liftConst :: TupleType t -> t -> Q (TExp t)-liftConst UnitTuple () = [|| () ||]-liftConst (SingleTuple t) x = [|| $$(liftScalar t x) ||]-liftConst (PairTuple ta tb) (a,b) = [|| ($$(liftConst ta a), $$(liftConst tb b)) ||]--liftScalar :: ScalarType t -> t -> Q (TExp t)-liftScalar (NumScalarType t) x = liftNum t x-liftScalar (NonNumScalarType t) x = liftNonNum t x--liftNum :: NumType t -> t -> Q (TExp t)-liftNum (IntegralNumType t) x = liftIntegral t x-liftNum (FloatingNumType t) x = liftFloating t x--liftNonNum :: NonNumType t -> t -> Q (TExp t)-liftNonNum TypeBool{} x = [|| x ||]-liftNonNum TypeChar{} x = [|| x ||]-liftNonNum TypeCChar{} x = return (TH.TExp (TH.LitE (TH.IntegerL (toInteger x))))-liftNonNum TypeCSChar{} x = return (TH.TExp (TH.LitE (TH.IntegerL (toInteger x))))-liftNonNum TypeCUChar{} x = return (TH.TExp (TH.LitE (TH.IntegerL (toInteger x))))--liftIntegral :: IntegralType t -> t -> Q (TExp t)-liftIntegral TypeInt{} x = [|| x ||]-liftIntegral TypeInt8{} x = [|| x ||]-liftIntegral TypeInt16{} x = [|| x ||]-liftIntegral TypeInt32{} x = [|| x ||]-liftIntegral TypeInt64{} x = [|| x ||]-#if __GLASGOW_HASKELL__ >= 710-liftIntegral TypeWord{} x = [|| x ||]-#else-liftIntegral TypeWord{} x = return (TH.TExp (TH.LitE (TH.IntegerL (toInteger x))))-#endif-liftIntegral TypeWord8{} x = [|| x ||]-liftIntegral TypeWord16{} x = [|| x ||]-liftIntegral TypeWord32{} x = [|| x ||]-liftIntegral TypeWord64{} x = [|| x ||]-liftIntegral TypeCShort{} x = return (TH.TExp (TH.LitE (TH.IntegerL (toInteger x))))-liftIntegral TypeCUShort{} x = return (TH.TExp (TH.LitE (TH.IntegerL (toInteger x))))-liftIntegral TypeCInt{} x = return (TH.TExp (TH.LitE (TH.IntegerL (toInteger x))))-liftIntegral TypeCUInt{} x = return (TH.TExp (TH.LitE (TH.IntegerL (toInteger x))))-liftIntegral TypeCLong{} x = return (TH.TExp (TH.LitE (TH.IntegerL (toInteger x))))-liftIntegral TypeCULong{} x = return (TH.TExp (TH.LitE (TH.IntegerL (toInteger x))))-liftIntegral TypeCLLong{} x = return (TH.TExp (TH.LitE (TH.IntegerL (toInteger x))))-liftIntegral TypeCULLong{} x = return (TH.TExp (TH.LitE (TH.IntegerL (toInteger x))))--liftFloating :: FloatingType t -> t -> Q (TExp t)-liftFloating TypeFloat{} x = [|| x ||]-liftFloating TypeDouble{} x = [|| x ||]-liftFloating TypeCFloat{} x = return (TH.TExp (TH.LitE (TH.RationalL (toRational x))))-liftFloating TypeCDouble{} x = return (TH.TExp (TH.LitE (TH.RationalL (toRational x))))---liftIntegralType :: IntegralType t -> Q (TExp (IntegralType t))-liftIntegralType TypeInt{} = [|| TypeInt IntegralDict ||]-liftIntegralType TypeInt8{} = [|| TypeInt8 IntegralDict ||]-liftIntegralType TypeInt16{} = [|| TypeInt16 IntegralDict ||]-liftIntegralType TypeInt32{} = [|| TypeInt32 IntegralDict ||]-liftIntegralType TypeInt64{} = [|| TypeInt64 IntegralDict ||]-liftIntegralType TypeWord{} = [|| TypeWord IntegralDict ||]-liftIntegralType TypeWord8{} = [|| TypeWord8 IntegralDict ||]-liftIntegralType TypeWord16{} = [|| TypeWord16 IntegralDict ||]-liftIntegralType TypeWord32{} = [|| TypeWord32 IntegralDict ||]-liftIntegralType TypeWord64{} = [|| TypeWord64 IntegralDict ||]-liftIntegralType TypeCShort{} = [|| TypeCShort IntegralDict ||]-liftIntegralType TypeCUShort{} = [|| TypeCUShort IntegralDict ||]-liftIntegralType TypeCInt{} = [|| TypeCInt IntegralDict ||]-liftIntegralType TypeCUInt{} = [|| TypeCUInt IntegralDict ||]-liftIntegralType TypeCLong{} = [|| TypeCLong IntegralDict ||]-liftIntegralType TypeCULong{} = [|| TypeCULong IntegralDict ||]-liftIntegralType TypeCLLong{} = [|| TypeCLLong IntegralDict ||]-liftIntegralType TypeCULLong{} = [|| TypeCULLong IntegralDict ||]--liftFloatingType :: FloatingType t -> Q (TExp (FloatingType t))-liftFloatingType TypeFloat{} = [|| TypeFloat FloatingDict ||]-liftFloatingType TypeDouble{} = [|| TypeDouble FloatingDict ||]-liftFloatingType TypeCFloat{} = [|| TypeCFloat FloatingDict ||]-liftFloatingType TypeCDouble{} = [|| TypeCDouble FloatingDict ||]--liftNonNumType :: NonNumType t -> Q (TExp (NonNumType t))-liftNonNumType TypeBool{} = [|| TypeBool NonNumDict ||]-liftNonNumType TypeChar{} = [|| TypeChar NonNumDict ||]-liftNonNumType TypeCChar{} = [|| TypeCChar NonNumDict ||]-liftNonNumType TypeCSChar{} = [|| TypeCSChar NonNumDict ||]-liftNonNumType TypeCUChar{} = [|| TypeCUChar NonNumDict ||]--liftNumType :: NumType t -> Q (TExp (NumType t))-liftNumType (IntegralNumType t) = [|| IntegralNumType $$(liftIntegralType t) ||]-liftNumType (FloatingNumType t) = [|| FloatingNumType $$(liftFloatingType t) ||]--liftBoundedType :: BoundedType t -> Q (TExp (BoundedType t))-liftBoundedType (IntegralBoundedType t) = [|| IntegralBoundedType $$(liftIntegralType t) ||]-liftBoundedType (NonNumBoundedType t) = [|| NonNumBoundedType $$(liftNonNumType t) ||]--liftScalarType :: ScalarType t -> Q (TExp (ScalarType t))-liftScalarType (NumScalarType t) = [|| NumScalarType $$(liftNumType t) ||]-liftScalarType (NonNumScalarType t) = [|| NonNumScalarType $$(liftNonNumType t) ||]----- Debugging--- =========--showPreAccOp :: forall acc aenv arrs. PreOpenAcc acc aenv arrs -> String-showPreAccOp Alet{} = "Alet"-showPreAccOp (Avar ix) = "Avar a" ++ show (idxToInt ix)-showPreAccOp (Use a) = "Use " ++ showArrays (toArr a :: arrs)-showPreAccOp Apply{} = "Apply"-showPreAccOp Aforeign{} = "Aforeign"-showPreAccOp Acond{} = "Acond"-showPreAccOp Awhile{} = "Awhile"-showPreAccOp Atuple{} = "Atuple"-showPreAccOp Aprj{} = "Aprj"-showPreAccOp Unit{} = "Unit"-showPreAccOp Generate{} = "Generate"-showPreAccOp Transform{} = "Transform"-showPreAccOp Reshape{} = "Reshape"-showPreAccOp Replicate{} = "Replicate"-showPreAccOp Slice{} = "Slice"-showPreAccOp Map{} = "Map"-showPreAccOp ZipWith{} = "ZipWith"-showPreAccOp Fold{} = "Fold"-showPreAccOp Fold1{} = "Fold1"-showPreAccOp FoldSeg{} = "FoldSeg"-showPreAccOp Fold1Seg{} = "Fold1Seg"-showPreAccOp Scanl{} = "Scanl"-showPreAccOp Scanl'{} = "Scanl'"-showPreAccOp Scanl1{} = "Scanl1"-showPreAccOp Scanr{} = "Scanr"-showPreAccOp Scanr'{} = "Scanr'"-showPreAccOp Scanr1{} = "Scanr1"-showPreAccOp Permute{} = "Permute"-showPreAccOp Backpermute{} = "Backpermute"-showPreAccOp Stencil{} = "Stencil"-showPreAccOp Stencil2{} = "Stencil2"--- showPreAccOp Collect{} = "Collect"--showArrays :: forall arrs. Arrays arrs => arrs -> String-showArrays = display . collect (arrays (undefined::arrs)) . fromArr- where- collect :: ArraysR a -> a -> [String]- collect ArraysRunit _ = []- collect ArraysRarray arr = [showShortendArr arr]- collect (ArraysRpair r1 r2) (a1, a2) = collect r1 a1 ++ collect r2 a2- --- display [] = []- display [x] = x- display xs = "(" ++ intercalate ", " xs ++ ")"---showShortendArr :: Elt e => Array sh e -> String-showShortendArr arr- = show (take cutoff l) ++ if length l > cutoff then ".." else ""- where- l = toList arr- cutoff = 5---showPreExpOp :: forall acc env aenv t. PreOpenExp acc env aenv t -> String-showPreExpOp Let{} = "Let"-showPreExpOp (Var ix) = "Var x" ++ show (idxToInt ix)-showPreExpOp (Const c) = "Const " ++ show (toElt c :: t)-showPreExpOp Foreign{} = "Foreign"-showPreExpOp Tuple{} = "Tuple"-showPreExpOp Prj{} = "Prj"-showPreExpOp IndexNil = "IndexNil"-showPreExpOp IndexCons{} = "IndexCons"-showPreExpOp IndexHead{} = "IndexHead"-showPreExpOp IndexTail{} = "IndexTail"-showPreExpOp IndexAny = "IndexAny"-showPreExpOp IndexSlice{} = "IndexSlice"-showPreExpOp IndexFull{} = "IndexFull"-showPreExpOp ToIndex{} = "ToIndex"-showPreExpOp FromIndex{} = "FromIndex"-showPreExpOp Cond{} = "Cond"-showPreExpOp While{} = "While"-showPreExpOp PrimConst{} = "PrimConst"-showPreExpOp PrimApp{} = "PrimApp"-showPreExpOp Index{} = "Index"-showPreExpOp LinearIndex{} = "LinearIndex"-showPreExpOp Shape{} = "Shape"-showPreExpOp ShapeSize{} = "ShapeSize"-showPreExpOp Intersect{} = "Intersect"-showPreExpOp Union{} = "Union"-
− Data/Array/Accelerate/Analysis/Hash.hs
@@ -1,506 +0,0 @@-{-# LANGUAGE GADTs #-}-{-# LANGUAGE PatternGuards #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell #-}-{-# OPTIONS_HADDOCK hide #-}--- |--- Module : Data.Array.Accelerate.Analysis.Hash--- Copyright : [2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Analysis.Hash (-- -- hashing expressions- HashAcc,- hashPreOpenAcc, hashOpenAcc,- hashPreOpenExp, hashOpenExp,- hashPreOpenFun,-- -- auxiliary- hashQ,- commutes,--) where--import Data.Array.Accelerate.AST-import Data.Array.Accelerate.Analysis.Hash.TH-import Data.Array.Accelerate.Array.Sugar-import Data.Array.Accelerate.Array.Representation ( SliceIndex(..) )-import Data.Array.Accelerate.Product-import Data.Array.Accelerate.Type--import Data.Hashable-import Foreign.C.Types-import Data.Maybe ( fromMaybe )-import System.Mem.StableName ( hashStableName, makeStableName )-import System.IO.Unsafe ( unsafePerformIO )-import Prelude hiding ( exp )----- Array computations--- --------------------type HashAcc acc = forall aenv a. acc aenv a -> Int---hashOpenAcc :: OpenAcc aenv arrs -> Int-hashOpenAcc (OpenAcc pacc) = hashPreOpenAcc hashOpenAcc pacc--hashPreOpenAcc :: forall acc aenv arrs. HashAcc acc -> PreOpenAcc acc aenv arrs -> Int-hashPreOpenAcc hashAcc pacc =- let- hashA :: forall aenv' a. Arrays a => Int -> acc aenv' a -> Int- hashA salt- = hashWithSalt salt- . hashWithSalt (hashArraysType (arrays (undefined::a)))- . hashAcc-- hashE :: Int -> PreOpenExp acc env' aenv' e -> Int- hashE salt = hashWithSalt salt . hashPreOpenExp hashAcc-- hashF :: Int -> PreOpenFun acc env' aenv' f -> Int- hashF salt = hashWithSalt salt . hashPreOpenFun hashAcc-- hashB :: Int -> PreBoundary acc aenv' (Array sh e) -> Int- hashB salt = hashWithSalt salt . hashPreBoundary hashAcc-- -- hashS :: Int -> PreOpenSeq acc aenv senv arrs -> Int- -- hashS salt = hashWithSalt salt . hashPreOpenSeq hashAcc-- nacl :: Arrays arrs => Int- nacl = hashArraysType (arrays (undefined::arrs))-- in case pacc of- Alet bnd body -> $(hashQ "Alet") `hashA` bnd `hashA` body- Avar v -> $(hashQ "Avar") `hashWithSalt` nacl `hashWithSalt` hashIdx v- Atuple t -> $(hashQ "Atuple") `hashWithSalt` nacl `hashWithSalt` hashAtuple hashAcc t- Aprj ix a -> $(hashQ "Aprj") `hashWithSalt` nacl `hashWithSalt` hashTupleIdx ix `hashA` a- Apply f a -> $(hashQ "Apply") `hashWithSalt` nacl `hashWithSalt` hashAfun hashAcc f `hashA` a- Aforeign _ f a -> $(hashQ "Aforeign") `hashWithSalt` nacl `hashWithSalt` hashAfun hashAcc f `hashA` a- Use a -> $(hashQ "Use") `hashWithSalt` hashArrays (arrays (undefined::arrs)) a- Awhile p f a -> $(hashQ "Awhile") `hashWithSalt` hashAfun hashAcc f `hashWithSalt` hashAfun hashAcc p `hashA` a- Unit e -> $(hashQ "Unit") `hashE` e- Generate e f -> $(hashQ "Generate") `hashE` e `hashF` f- Acond e a1 a2 -> $(hashQ "Acond") `hashE` e `hashA` a1 `hashA` a2- Reshape sh a -> $(hashQ "Reshape") `hashE` sh `hashA` a- Transform sh f1 f2 a -> $(hashQ "Transform") `hashE` sh `hashF` f1 `hashF` f2 `hashA` a- Replicate spec ix a -> $(hashQ "Replicate") `hashE` ix `hashA` a `hashWithSalt` hashSliceIndex spec- Slice spec a ix -> $(hashQ "Slice") `hashE` ix `hashA` a `hashWithSalt` hashSliceIndex spec- Map f a -> $(hashQ "Map") `hashF` f `hashA` a- ZipWith f a1 a2 -> $(hashQ "ZipWith") `hashF` f `hashA` a1 `hashA` a2- Fold f e a -> $(hashQ "Fold") `hashF` f `hashE` e `hashA` a- Fold1 f a -> $(hashQ "Fold1") `hashF` f `hashA` a- FoldSeg f e a s -> $(hashQ "FoldSeg") `hashF` f `hashE` e `hashA` a `hashA` s- Fold1Seg f a s -> $(hashQ "Fold1Seg") `hashF` f `hashA` a `hashA` s- Scanl f e a -> $(hashQ "Scanl") `hashF` f `hashE` e `hashA` a- Scanl' f e a -> $(hashQ "Scanl'") `hashF` f `hashE` e `hashA` a- Scanl1 f a -> $(hashQ "Scanl1") `hashF` f `hashA` a- Scanr f e a -> $(hashQ "Scanr") `hashF` f `hashE` e `hashA` a- Scanr' f e a -> $(hashQ "Scanr'") `hashF` f `hashE` e `hashA` a- Scanr1 f a -> $(hashQ "Scanr1") `hashF` f `hashA` a- Backpermute sh f a -> $(hashQ "Backpermute") `hashF` f `hashE` sh `hashA` a- Permute f1 a1 f2 a2 -> $(hashQ "Permute") `hashF` f1 `hashA` a1 `hashF` f2 `hashA` a2- Stencil f b a -> $(hashQ "Stencil") `hashF` f `hashB` b `hashA` a- Stencil2 f b1 a1 b2 a2 -> $(hashQ "Stencil2") `hashF` f `hashB` b1 `hashA` a1 `hashB` b2 `hashA` a2--{---hashPreOpenSeq :: forall acc aenv senv arrs. HashAcc acc -> PreOpenSeq acc aenv senv arrs -> Int-hashPreOpenSeq hashAcc s =- let- hashA :: Int -> acc aenv' a -> Int- hashA salt = hashWithSalt salt . hashAcc-- hashE :: Int -> PreOpenExp acc env' aenv' e -> Int- hashE salt = hashWithSalt salt . hashPreOpenExp hashAcc-- hashAF :: Int -> PreOpenAfun acc aenv' f -> Int- hashAF salt = hashWithSalt salt . hashAfun hashAcc-- hashF :: Int -> PreOpenFun acc env' aenv' f -> Int- hashF salt = hashWithSalt salt . hashPreOpenFun hashAcc-- hashS :: Int -> PreOpenSeq acc aenv senv' arrs' -> Int- hashS salt = hashWithSalt salt . hashPreOpenSeq hashAcc-- hashVar :: Int -> Idx senv' a -> Int- hashVar salt = hashWithSalt salt . idxToInt-- hashP :: Int -> Producer acc aenv senv a -> Int- hashP salt p =- case p of- StreamIn arrs -> unsafePerformIO $! hashStableName `fmap` makeStableName arrs- ToSeq spec _ acc -> hashWithSalt salt "ToSeq" `hashA` acc `hashWithSalt` show spec- MapSeq f x -> hashWithSalt salt "MapSeq" `hashAF` f `hashVar` x- ChunkedMapSeq f x -> hashWithSalt salt "ChunkedMapSeq" `hashAF` f `hashVar` x- ZipWithSeq f x y -> hashWithSalt salt "ZipWithSeq" `hashAF` f `hashVar` x `hashVar` y- ScanSeq f e x -> hashWithSalt salt "ScanSeq" `hashF` f `hashE` e `hashVar` x-- hashC :: Int -> Consumer acc aenv senv' a -> Int- hashC salt c =- case c of- FoldSeq f e x -> hashWithSalt salt "FoldSeq" `hashF` f `hashE` e `hashVar` x- FoldSeqFlatten f acc x -> hashWithSalt salt "FoldSeqFlatten" `hashAF` f `hashA` acc `hashVar` x- Stuple t -> hash "Stuple" `hashWithSalt` hashAtuple (hashC salt) t-- in case s of- Producer p s' -> hash "Producer" `hashP` p `hashS` s'- Consumer c -> hash "Consumer" `hashC` c- Reify ix -> hash "Reify" `hashVar` ix---}---hashIdx :: Idx env t -> Int-hashIdx = hash . idxToInt--hashTupleIdx :: TupleIdx tup e -> Int-hashTupleIdx = hash . tupleIdxToInt---hashArrays :: ArraysR a -> a -> Int-hashArrays ArraysRunit () = hash ()-hashArrays (ArraysRpair r1 r2) (a1, a2) = hash (hashArrays r1 a1, hashArrays r2 a2)-hashArrays ArraysRarray ad = unsafePerformIO $! hashStableName `fmap` makeStableName ad--hashArraysType :: forall a. ArraysR a -> Int-hashArraysType ArraysRunit = $(hashQ "ArraysRunit")-hashArraysType (ArraysRpair r1 r2) = $(hashQ "ArraysRpair") `hashWithSalt` hashArraysType r1 `hashWithSalt` hashArraysType r2-hashArraysType ArraysRarray = $(hashQ "ArraysRarray") `hashWithSalt` hashArrayType (undefined::a)- where- hashArrayType :: forall sh e. (Shape sh, Elt e) => Array sh e -> Int- hashArrayType _ = hashTupleType (eltType (undefined::sh)) `hashWithSalt` hashTupleType (eltType (undefined::e))--hashAtuple :: HashAcc acc -> Atuple (acc aenv) a -> Int-hashAtuple _ NilAtup = $(hashQ "NilAtup")-hashAtuple h (SnocAtup t a) = $(hashQ "SnocAtup") `hashWithSalt` hashAtuple h t `hashWithSalt` h a--hashAfun :: forall acc aenv f. HashAcc acc -> PreOpenAfun acc aenv f -> Int-hashAfun hashAcc afun =- let- hashA :: forall aenv' a. Arrays a => Int -> acc aenv' a -> Int- hashA salt- = hashWithSalt salt- . hashWithSalt (hashArraysType (arrays (undefined::a)))- . hashAcc-- hashL :: forall aenv' a b. Arrays a => Int -> PreOpenAfun acc (aenv',a) b -> Int- hashL salt- = hashWithSalt salt- . hashWithSalt (hashArraysType (arrays (undefined::a)))- . hashAfun hashAcc-- in case afun of- Abody b -> $(hashQ "Abody") `hashA` b- Alam l -> $(hashQ "Alam") `hashL` l---hashPreBoundary :: forall acc aenv sh e. HashAcc acc -> PreBoundary acc aenv (Array sh e) -> Int-hashPreBoundary _ Wrap = $(hashQ "Wrap")-hashPreBoundary _ Clamp = $(hashQ "Clamp")-hashPreBoundary _ Mirror = $(hashQ "Mirror")-hashPreBoundary _ (Constant c) = $(hashQ "Constant") `hashWithSalt` hashConst (eltType (undefined::e)) c-hashPreBoundary h (Function f) = $(hashQ "Function") `hashWithSalt` hashPreOpenFun h f--hashSliceIndex :: SliceIndex slix sl co sh -> Int-hashSliceIndex SliceNil = $(hashQ "SliceNil")-hashSliceIndex (SliceAll r) = $(hashQ "SliceAll") `hashWithSalt` hashSliceIndex r-hashSliceIndex (SliceFixed r) = $(hashQ "sliceFixed") `hashWithSalt` hashSliceIndex r----- Scalar expressions--- --------------------hashOpenExp :: OpenExp env aenv exp -> Int-hashOpenExp = hashPreOpenExp hashOpenAcc--hashPreOpenExp :: forall acc env aenv exp. HashAcc acc -> PreOpenExp acc env aenv exp -> Int-hashPreOpenExp hashAcc exp =- let- hashE :: forall env' aenv' e. Elt e => Int -> PreOpenExp acc env' aenv' e -> Int- hashE salt- = hashWithSalt salt- . hashWithSalt (hashTupleType (eltType (undefined::e)))- . hashPreOpenExp hashAcc-- hashA :: Int -> acc aenv' a -> Int- hashA salt = hashWithSalt salt . hashAcc-- hashF :: Int -> PreOpenFun acc env' aenv' f -> Int- hashF salt = hashWithSalt salt . hashPreOpenFun hashAcc-- nacl :: Elt exp => Int- nacl = hashTupleType (eltType (undefined::exp))-- in case exp of- Let bnd body -> $(hashQ "Let") `hashE` bnd `hashE` body- Const c -> $(hashQ "Const") `hashWithSalt` hashConst (eltType (undefined::exp)) c- Var ix -> $(hashQ "Var") `hashWithSalt` nacl `hashWithSalt` hashIdx ix- Tuple t -> $(hashQ "Tuple") `hashWithSalt` nacl `hashWithSalt` hashTuple hashAcc t- Prj i e -> $(hashQ "Prj") `hashWithSalt` nacl `hashWithSalt` hashTupleIdx i `hashE` e- IndexAny -> $(hashQ "IndexAny") `hashWithSalt` nacl- IndexNil -> $(hashQ "IndexNil")- IndexCons sl a -> $(hashQ "IndexCons") `hashE` sl `hashE` a- IndexHead sl -> $(hashQ "IndexHead") `hashE` sl- IndexTail sl -> $(hashQ "IndexTail") `hashE` sl- IndexSlice spec ix sh -> $(hashQ "IndexSlice") `hashE` ix `hashE` sh `hashWithSalt` hashSliceIndex spec- IndexFull spec ix sl -> $(hashQ "IndexFull") `hashE` ix `hashE` sl `hashWithSalt` hashSliceIndex spec- ToIndex sh i -> $(hashQ "ToIndex") `hashE` sh `hashE` i- FromIndex sh i -> $(hashQ "FromIndex") `hashE` sh `hashE` i- Cond c t e -> $(hashQ "Cond") `hashE` c `hashE` t `hashE` e- While p f x -> $(hashQ "While") `hashF` p `hashF` f `hashE` x- PrimApp f x -> $(hashQ "PrimApp") `hashWithSalt` hashPrimFun f `hashE` fromMaybe x (commutes hashAcc f x)- PrimConst c -> $(hashQ "PrimConst") `hashWithSalt` hashPrimConst c- Index a ix -> $(hashQ "Index") `hashA` a `hashE` ix- LinearIndex a ix -> $(hashQ "LinearIndex") `hashA` a `hashE` ix- Shape a -> $(hashQ "Shape") `hashA` a- ShapeSize sh -> $(hashQ "ShapeSize") `hashE` sh- Intersect sa sb -> $(hashQ "Intersect") `hashE` sa `hashE` sb- Union sa sb -> $(hashQ "Union") `hashE` sa `hashE` sb- Foreign _ f e -> $(hashQ "Foreign") `hashF` f `hashE` e---hashPreOpenFun :: forall acc env aenv f. HashAcc acc -> PreOpenFun acc env aenv f -> Int-hashPreOpenFun hashAcc fun =- let- hashE :: forall env' aenv' e. Elt e => Int -> PreOpenExp acc env' aenv' e -> Int- hashE salt- = hashWithSalt salt- . hashWithSalt (hashTupleType (eltType (undefined::e)))- . hashPreOpenExp hashAcc-- hashL :: forall env' aenv' a b. Elt a => Int -> PreOpenFun acc (env',a) aenv' b -> Int- hashL salt- = hashWithSalt salt- . hashWithSalt (hashTupleType (eltType (undefined::a)))- . hashPreOpenFun hashAcc-- in case fun of- Body b -> $(hashQ "Body") `hashE` b- Lam f -> $(hashQ "Lam") `hashL` f---hashTuple :: HashAcc acc -> Tuple (PreOpenExp acc env aenv) e -> Int-hashTuple _ NilTup = $(hashQ "NilTup")-hashTuple h (SnocTup t e) = $(hashQ "SnocTup") `hashWithSalt` hashTuple h t `hashWithSalt` hashPreOpenExp h e---hashConst :: TupleType t -> t -> Int-hashConst UnitTuple () = hash ()-hashConst (PairTuple ta tb) (a,b) = hash (hashConst ta a, hashConst tb b)-hashConst (SingleTuple t) c = hashScalarConst t c--hashScalarConst :: ScalarType t -> t -> Int-hashScalarConst (NumScalarType t) = hashNumConst t-hashScalarConst (NonNumScalarType t) = hashNonNumConst t--hashNonNumConst :: NonNumType t -> t -> Int-hashNonNumConst TypeBool{} x = $(hashQ "Bool") `hashWithSalt` x-hashNonNumConst TypeChar{} x = $(hashQ "Char") `hashWithSalt` x-hashNonNumConst TypeCChar{} (CChar x) = $(hashQ "CChar") `hashWithSalt` x-hashNonNumConst TypeCSChar{} (CSChar x) = $(hashQ "CSChar") `hashWithSalt` x-hashNonNumConst TypeCUChar{} (CUChar x) = $(hashQ "CUChar") `hashWithSalt` x--hashNumConst :: NumType t -> t -> Int-hashNumConst (IntegralNumType t) = hashIntegralConst t-hashNumConst (FloatingNumType t) = hashFloatingConst t--hashIntegralConst :: IntegralType t -> t -> Int-hashIntegralConst TypeInt{} x = $(hashQ "Int") `hashWithSalt` x-hashIntegralConst TypeInt8{} x = $(hashQ "Int8") `hashWithSalt` x-hashIntegralConst TypeInt16{} x = $(hashQ "Int16") `hashWithSalt` x-hashIntegralConst TypeInt32{} x = $(hashQ "Int32") `hashWithSalt` x-hashIntegralConst TypeInt64{} x = $(hashQ "Int64") `hashWithSalt` x-hashIntegralConst TypeWord{} x = $(hashQ "Word") `hashWithSalt` x-hashIntegralConst TypeWord8{} x = $(hashQ "Word8") `hashWithSalt` x-hashIntegralConst TypeWord16{} x = $(hashQ "Word16") `hashWithSalt` x-hashIntegralConst TypeWord32{} x = $(hashQ "Word32") `hashWithSalt` x-hashIntegralConst TypeWord64{} x = $(hashQ "Word64") `hashWithSalt` x-hashIntegralConst TypeCShort{} (CShort x) = $(hashQ "CShort") `hashWithSalt` x-hashIntegralConst TypeCUShort{} (CUShort x) = $(hashQ "CUShort") `hashWithSalt` x-hashIntegralConst TypeCInt{} (CInt x) = $(hashQ "CInt") `hashWithSalt` x-hashIntegralConst TypeCUInt{} (CUInt x) = $(hashQ "CUInt") `hashWithSalt` x-hashIntegralConst TypeCLong{} (CLong x) = $(hashQ "CLong") `hashWithSalt` x-hashIntegralConst TypeCULong{} (CULong x) = $(hashQ "CULong") `hashWithSalt` x-hashIntegralConst TypeCLLong{} (CLLong x) = $(hashQ "CLLong") `hashWithSalt` x-hashIntegralConst TypeCULLong{} (CULLong x) = $(hashQ "CULLong") `hashWithSalt` x--hashFloatingConst :: FloatingType t -> t -> Int-hashFloatingConst TypeFloat{} x = $(hashQ "Float") `hashWithSalt` x-hashFloatingConst TypeDouble{} x = $(hashQ "Double") `hashWithSalt` x-hashFloatingConst TypeCFloat{} (CFloat x) = $(hashQ "CFloat") `hashWithSalt` x-hashFloatingConst TypeCDouble{} (CDouble x) = $(hashQ "CDouble") `hashWithSalt` x--hashPrimConst :: PrimConst c -> Int-hashPrimConst (PrimMinBound t) = $(hashQ "PrimMinBound") `hashWithSalt` hashBoundedType t-hashPrimConst (PrimMaxBound t) = $(hashQ "PrimMaxBound") `hashWithSalt` hashBoundedType t-hashPrimConst (PrimPi t) = $(hashQ "PrimPi") `hashWithSalt` hashFloatingType t---hashPrimFun :: PrimFun f -> Int-hashPrimFun (PrimAdd a) = $(hashQ "PrimAdd") `hashWithSalt` hashNumType a-hashPrimFun (PrimSub a) = $(hashQ "PrimSub") `hashWithSalt` hashNumType a-hashPrimFun (PrimMul a) = $(hashQ "PrimMul") `hashWithSalt` hashNumType a-hashPrimFun (PrimNeg a) = $(hashQ "PrimNeg") `hashWithSalt` hashNumType a-hashPrimFun (PrimAbs a) = $(hashQ "PrimAbs") `hashWithSalt` hashNumType a-hashPrimFun (PrimSig a) = $(hashQ "PrimSig") `hashWithSalt` hashNumType a-hashPrimFun (PrimQuot a) = $(hashQ "PrimQuot") `hashWithSalt` hashIntegralType a-hashPrimFun (PrimRem a) = $(hashQ "PrimRem") `hashWithSalt` hashIntegralType a-hashPrimFun (PrimQuotRem a) = $(hashQ "PrimQuotRem") `hashWithSalt` hashIntegralType a-hashPrimFun (PrimIDiv a) = $(hashQ "PrimIDiv") `hashWithSalt` hashIntegralType a-hashPrimFun (PrimMod a) = $(hashQ "PrimMod") `hashWithSalt` hashIntegralType a-hashPrimFun (PrimDivMod a) = $(hashQ "PrimDivMod") `hashWithSalt` hashIntegralType a-hashPrimFun (PrimBAnd a) = $(hashQ "PrimBAnd") `hashWithSalt` hashIntegralType a-hashPrimFun (PrimBOr a) = $(hashQ "PrimBOr") `hashWithSalt` hashIntegralType a-hashPrimFun (PrimBXor a) = $(hashQ "PrimBXor") `hashWithSalt` hashIntegralType a-hashPrimFun (PrimBNot a) = $(hashQ "PrimBNot") `hashWithSalt` hashIntegralType a-hashPrimFun (PrimBShiftL a) = $(hashQ "PrimBShiftL") `hashWithSalt` hashIntegralType a-hashPrimFun (PrimBShiftR a) = $(hashQ "PrimBShiftR") `hashWithSalt` hashIntegralType a-hashPrimFun (PrimBRotateL a) = $(hashQ "PrimBRotateL") `hashWithSalt` hashIntegralType a-hashPrimFun (PrimBRotateR a) = $(hashQ "PrimBRotateR") `hashWithSalt` hashIntegralType a-hashPrimFun (PrimPopCount a) = $(hashQ "PrimPopCount") `hashWithSalt` hashIntegralType a-hashPrimFun (PrimCountLeadingZeros a) = $(hashQ "PrimCountLeadingZeros") `hashWithSalt` hashIntegralType a-hashPrimFun (PrimCountTrailingZeros a) = $(hashQ "PrimCountTrailingZeros") `hashWithSalt` hashIntegralType a-hashPrimFun (PrimFDiv a) = $(hashQ "PrimFDiv") `hashWithSalt` hashFloatingType a-hashPrimFun (PrimRecip a) = $(hashQ "PrimRecip") `hashWithSalt` hashFloatingType a-hashPrimFun (PrimSin a) = $(hashQ "PrimSin") `hashWithSalt` hashFloatingType a-hashPrimFun (PrimCos a) = $(hashQ "PrimCos") `hashWithSalt` hashFloatingType a-hashPrimFun (PrimTan a) = $(hashQ "PrimTan") `hashWithSalt` hashFloatingType a-hashPrimFun (PrimAsin a) = $(hashQ "PrimAsin") `hashWithSalt` hashFloatingType a-hashPrimFun (PrimAcos a) = $(hashQ "PrimAcos") `hashWithSalt` hashFloatingType a-hashPrimFun (PrimAtan a) = $(hashQ "PrimAtan") `hashWithSalt` hashFloatingType a-hashPrimFun (PrimSinh a) = $(hashQ "PrimSinh") `hashWithSalt` hashFloatingType a-hashPrimFun (PrimCosh a) = $(hashQ "PrimCosh") `hashWithSalt` hashFloatingType a-hashPrimFun (PrimTanh a) = $(hashQ "PrimTanh") `hashWithSalt` hashFloatingType a-hashPrimFun (PrimAsinh a) = $(hashQ "PrimAsinh") `hashWithSalt` hashFloatingType a-hashPrimFun (PrimAcosh a) = $(hashQ "PrimAcosh") `hashWithSalt` hashFloatingType a-hashPrimFun (PrimAtanh a) = $(hashQ "PrimAtanh") `hashWithSalt` hashFloatingType a-hashPrimFun (PrimExpFloating a) = $(hashQ "PrimExpFloating") `hashWithSalt` hashFloatingType a-hashPrimFun (PrimSqrt a) = $(hashQ "PrimSqrt") `hashWithSalt` hashFloatingType a-hashPrimFun (PrimLog a) = $(hashQ "PrimLog") `hashWithSalt` hashFloatingType a-hashPrimFun (PrimFPow a) = $(hashQ "PrimFPow") `hashWithSalt` hashFloatingType a-hashPrimFun (PrimLogBase a) = $(hashQ "PrimLogBase") `hashWithSalt` hashFloatingType a-hashPrimFun (PrimAtan2 a) = $(hashQ "PrimAtan2") `hashWithSalt` hashFloatingType a-hashPrimFun (PrimTruncate a b) = $(hashQ "PrimTruncate") `hashWithSalt` hashFloatingType a `hashWithSalt` hashIntegralType b-hashPrimFun (PrimRound a b) = $(hashQ "PrimRound") `hashWithSalt` hashFloatingType a `hashWithSalt` hashIntegralType b-hashPrimFun (PrimFloor a b) = $(hashQ "PrimFloor") `hashWithSalt` hashFloatingType a `hashWithSalt` hashIntegralType b-hashPrimFun (PrimCeiling a b) = $(hashQ "PrimCeiling") `hashWithSalt` hashFloatingType a `hashWithSalt` hashIntegralType b-hashPrimFun (PrimIsNaN a) = $(hashQ "PrimIsNaN") `hashWithSalt` hashFloatingType a-hashPrimFun (PrimIsInfinite a) = $(hashQ "PrimIsInfinite") `hashWithSalt` hashFloatingType a-hashPrimFun (PrimLt a) = $(hashQ "PrimLt") `hashWithSalt` hashScalarType a-hashPrimFun (PrimGt a) = $(hashQ "PrimGt") `hashWithSalt` hashScalarType a-hashPrimFun (PrimLtEq a) = $(hashQ "PrimLtEq") `hashWithSalt` hashScalarType a-hashPrimFun (PrimGtEq a) = $(hashQ "PrimGtEq") `hashWithSalt` hashScalarType a-hashPrimFun (PrimEq a) = $(hashQ "PrimEq") `hashWithSalt` hashScalarType a-hashPrimFun (PrimNEq a) = $(hashQ "PrimNEq") `hashWithSalt` hashScalarType a-hashPrimFun (PrimMax a) = $(hashQ "PrimMax") `hashWithSalt` hashScalarType a-hashPrimFun (PrimMin a) = $(hashQ "PrimMin") `hashWithSalt` hashScalarType a-hashPrimFun (PrimFromIntegral a b) = $(hashQ "PrimFromIntegral") `hashWithSalt` hashIntegralType a `hashWithSalt` hashNumType b-hashPrimFun (PrimToFloating a b) = $(hashQ "PrimToFloating") `hashWithSalt` hashNumType a `hashWithSalt` hashFloatingType b-hashPrimFun (PrimCoerce a b) = $(hashQ "PrimCoerce") `hashWithSalt` hashScalarType a `hashWithSalt` hashScalarType b-hashPrimFun PrimLAnd = $(hashQ "PrimLAnd")-hashPrimFun PrimLOr = $(hashQ "PrimLOr")-hashPrimFun PrimLNot = $(hashQ "PrimLNot")-hashPrimFun PrimOrd = $(hashQ "PrimOrd")-hashPrimFun PrimChr = $(hashQ "PrimChr")-hashPrimFun PrimBoolToInt = $(hashQ "PrimBoolToInt")----- TLM: We need to include the depth of the branches in the pair case, otherwise--- we are getting a collision at @hash t == hash (t,(t,t))@.----hashTupleType :: TupleType t -> Int-hashTupleType UnitTuple = $(hashQ "UnitTuple")-hashTupleType (SingleTuple t) = $(hashQ "SingleTuple") `hashWithSalt` hashScalarType t-hashTupleType (PairTuple a b) = $(hashQ "PairTuple") `hashWithSalt` hashTupleType a `hashWithSalt` depthTupleType a- `hashWithSalt` hashTupleType b `hashWithSalt` depthTupleType b--depthTupleType :: TupleType t -> Int-depthTupleType UnitTuple = 0-depthTupleType SingleTuple{} = 1-depthTupleType (PairTuple a b) = depthTupleType a + depthTupleType b--hashScalarType :: ScalarType t -> Int-hashScalarType (NumScalarType t) = $(hashQ "NumScalarType") `hashWithSalt` hashNumType t-hashScalarType (NonNumScalarType t) = $(hashQ "NonNumScalarType") `hashWithSalt` hashNonNumType t--hashBoundedType :: BoundedType t -> Int-hashBoundedType (IntegralBoundedType t) = $(hashQ "IntegralBoundedType") `hashWithSalt` hashIntegralType t-hashBoundedType (NonNumBoundedType t) = $(hashQ "NonNumBoundedType") `hashWithSalt` hashNonNumType t--hashNonNumType :: NonNumType t -> Int-hashNonNumType TypeBool{} = $(hashQ "Bool")-hashNonNumType TypeChar{} = $(hashQ "Char")-hashNonNumType TypeCChar{} = $(hashQ "CChar")-hashNonNumType TypeCSChar{} = $(hashQ "CSChar")-hashNonNumType TypeCUChar{} = $(hashQ "CUChar")--hashNumType :: NumType t -> Int-hashNumType (IntegralNumType t) = $(hashQ "IntegralNumType") `hashWithSalt` hashIntegralType t-hashNumType (FloatingNumType t) = $(hashQ "FloatingNumType") `hashWithSalt` hashFloatingType t--hashIntegralType :: IntegralType t -> Int-hashIntegralType TypeInt{} = $(hashQ "Int")-hashIntegralType TypeInt8{} = $(hashQ "Int8")-hashIntegralType TypeInt16{} = $(hashQ "Int16")-hashIntegralType TypeInt32{} = $(hashQ "Int32")-hashIntegralType TypeInt64{} = $(hashQ "Int64")-hashIntegralType TypeWord{} = $(hashQ "Word")-hashIntegralType TypeWord8{} = $(hashQ "Word8")-hashIntegralType TypeWord16{} = $(hashQ "Word16")-hashIntegralType TypeWord32{} = $(hashQ "Word32")-hashIntegralType TypeWord64{} = $(hashQ "Word64")-hashIntegralType TypeCShort{} = $(hashQ "CShort")-hashIntegralType TypeCUShort{} = $(hashQ "CUShort")-hashIntegralType TypeCInt{} = $(hashQ "CInt")-hashIntegralType TypeCUInt{} = $(hashQ "CUInt")-hashIntegralType TypeCLong{} = $(hashQ "CLong")-hashIntegralType TypeCULong{} = $(hashQ "CULong")-hashIntegralType TypeCLLong{} = $(hashQ "CLLong")-hashIntegralType TypeCULLong{} = $(hashQ "CULLong")--hashFloatingType :: FloatingType t -> Int-hashFloatingType TypeFloat{} = $(hashQ "Float")-hashFloatingType TypeDouble{} = $(hashQ "Double")-hashFloatingType TypeCFloat{} = $(hashQ "CFloat")-hashFloatingType TypeCDouble{} = $(hashQ "CDouble")----- Auxiliary--- ------------- Discriminate binary functions that commute, and if so return the operands in--- a stable ordering such that matching recognises expressions modulo--- commutativity.----commutes- :: forall acc env aenv a r.- HashAcc acc- -> PrimFun (a -> r)- -> PreOpenExp acc env aenv a- -> Maybe (PreOpenExp acc env aenv a)-commutes h f x = case f of- PrimAdd{} -> Just (swizzle x)- PrimMul{} -> Just (swizzle x)- PrimBAnd{} -> Just (swizzle x)- PrimBOr{} -> Just (swizzle x)- PrimBXor{} -> Just (swizzle x)- PrimEq{} -> Just (swizzle x)- PrimNEq{} -> Just (swizzle x)- PrimMax{} -> Just (swizzle x)- PrimMin{} -> Just (swizzle x)- PrimLAnd -> Just (swizzle x)- PrimLOr -> Just (swizzle x)- _ -> Nothing- where- swizzle :: PreOpenExp acc env aenv (a',a') -> PreOpenExp acc env aenv (a',a')- swizzle exp- | Tuple (NilTup `SnocTup` a `SnocTup` b) <- exp- , hashPreOpenExp h a > hashPreOpenExp h b = Tuple (NilTup `SnocTup` b `SnocTup` a)- --- | otherwise = exp-
− Data/Array/Accelerate/Analysis/Hash/TH.hs
@@ -1,30 +0,0 @@--- |--- Module : Data.Array.Accelerate.Analysis.Hash.TH--- Copyright : [2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Analysis.Hash.TH (-- hashQ,- hashWithSaltQ,--) where--import Data.Hashable-import Language.Haskell.TH---hashQ :: Hashable a => a -> ExpQ-hashQ = intE . hash--hashWithSaltQ :: Hashable a => Int -> a -> ExpQ-hashWithSaltQ s x = intE (hashWithSalt s x)--intE :: Int -> ExpQ-intE = litE . integerL . fromIntegral-
− Data/Array/Accelerate/Analysis/Match.hs
@@ -1,934 +0,0 @@-{-# LANGUAGE GADTs #-}-{-# LANGUAGE PatternGuards #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeOperators #-}-{-# OPTIONS_HADDOCK hide #-}--- |--- Module : Data.Array.Accelerate.Analysis.Match--- Copyright : [2012..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Analysis.Match (-- -- matching expressions- MatchAcc,- (:~:)(..),- matchOpenAcc, matchPreOpenAcc,- matchOpenAfun, matchPreOpenAfun,- matchOpenExp, matchPreOpenExp,- matchOpenFun, matchPreOpenFun,- matchPrimFun, matchPrimFun',-- -- auxiliary- matchIdx, matchTupleType,- matchIntegralType, matchFloatingType, matchNumType, matchScalarType,--) where---- standard library-import Data.Maybe-import Data.Typeable-import System.IO.Unsafe ( unsafePerformIO )-import System.Mem.StableName-import Prelude hiding ( exp )---- friends-import Data.Array.Accelerate.AST-import Data.Array.Accelerate.Analysis.Hash-import Data.Array.Accelerate.Array.Representation ( SliceIndex(..) )-import Data.Array.Accelerate.Array.Sugar-import Data.Array.Accelerate.Product-import Data.Array.Accelerate.Type----- The type of matching array computations----type MatchAcc acc = forall aenv s t. acc aenv s -> acc aenv t -> Maybe (s :~: t)----- Compute the congruence of two array computations. The nodes are congruent if--- they have the same operator and their operands are congruent.----{-# INLINEABLE matchOpenAcc #-}-matchOpenAcc- :: OpenAcc aenv s- -> OpenAcc aenv t- -> Maybe (s :~: t)-matchOpenAcc (OpenAcc acc1) (OpenAcc acc2) =- matchPreOpenAcc matchOpenAcc hashOpenAcc acc1 acc2---matchPreOpenAcc- :: forall acc aenv s t.- MatchAcc acc- -> HashAcc acc- -> PreOpenAcc acc aenv s- -> PreOpenAcc acc aenv t- -> Maybe (s :~: t)-matchPreOpenAcc matchAcc hashAcc = match- where- matchFun :: PreOpenFun acc env' aenv' u -> PreOpenFun acc env' aenv' v -> Maybe (u :~: v)- matchFun = matchPreOpenFun matchAcc hashAcc-- matchExp :: PreOpenExp acc env' aenv' u -> PreOpenExp acc env' aenv' v -> Maybe (u :~: v)- matchExp = matchPreOpenExp matchAcc hashAcc-- match :: PreOpenAcc acc aenv s -> PreOpenAcc acc aenv t -> Maybe (s :~: t)- match (Alet x1 a1) (Alet x2 a2)- | Just Refl <- matchAcc x1 x2- , Just Refl <- matchAcc a1 a2- = Just Refl-- match (Avar v1) (Avar v2)- = matchIdx v1 v2-- match (Atuple t1) (Atuple t2)- | Just Refl <- matchAtuple matchAcc t1 t2- = gcast Refl -- surface/representation type-- match (Aprj ix1 t1) (Aprj ix2 t2)- | Just Refl <- matchAcc t1 t2- , Just Refl <- matchTupleIdx ix1 ix2- = Just Refl-- match (Apply f1 a1) (Apply f2 a2)- | Just Refl <- matchPreOpenAfun matchAcc f1 f2- , Just Refl <- matchAcc a1 a2- = Just Refl-- match (Aforeign ff1 _ a1) (Aforeign ff2 _ a2)- | Just Refl <- matchAcc a1 a2- , unsafePerformIO $ do- sn1 <- makeStableName ff1- sn2 <- makeStableName ff2- return $! hashStableName sn1 == hashStableName sn2- = gcast Refl-- match (Acond p1 t1 e1) (Acond p2 t2 e2)- | Just Refl <- matchExp p1 p2- , Just Refl <- matchAcc t1 t2- , Just Refl <- matchAcc e1 e2- = Just Refl-- match (Awhile p1 f1 a1) (Awhile p2 f2 a2)- | Just Refl <- matchAcc a1 a2- , Just Refl <- matchPreOpenAfun matchAcc p1 p2- , Just Refl <- matchPreOpenAfun matchAcc f1 f2- = Just Refl-- match (Use a1) (Use a2)- | Just Refl <- matchArrays (arrays (undefined::s)) (arrays (undefined::t)) a1 a2- = gcast Refl-- match (Unit e1) (Unit e2)- | Just Refl <- matchExp e1 e2- = Just Refl-- match (Reshape sh1 a1) (Reshape sh2 a2)- | Just Refl <- matchExp sh1 sh2- , Just Refl <- matchAcc a1 a2- = Just Refl-- match (Generate sh1 f1) (Generate sh2 f2)- | Just Refl <- matchExp sh1 sh2- , Just Refl <- matchFun f1 f2- = Just Refl-- match (Transform sh1 ix1 f1 a1) (Transform sh2 ix2 f2 a2)- | Just Refl <- matchExp sh1 sh2- , Just Refl <- matchFun ix1 ix2- , Just Refl <- matchFun f1 f2- , Just Refl <- matchAcc a1 a2- = Just Refl-- match (Replicate _ ix1 a1) (Replicate _ ix2 a2)- | Just Refl <- matchExp ix1 ix2- , Just Refl <- matchAcc a1 a2- = gcast Refl -- slice specification ??-- match (Slice _ a1 ix1) (Slice _ a2 ix2)- | Just Refl <- matchAcc a1 a2- , Just Refl <- matchExp ix1 ix2- = gcast Refl -- slice specification ??-- match (Map f1 a1) (Map f2 a2)- | Just Refl <- matchFun f1 f2- , Just Refl <- matchAcc a1 a2- = Just Refl-- match (ZipWith f1 a1 b1) (ZipWith f2 a2 b2)- | Just Refl <- matchFun f1 f2- , Just Refl <- matchAcc a1 a2- , Just Refl <- matchAcc b1 b2- = Just Refl-- match (Fold f1 z1 a1) (Fold f2 z2 a2)- | Just Refl <- matchFun f1 f2- , Just Refl <- matchExp z1 z2- , Just Refl <- matchAcc a1 a2- = Just Refl-- match (Fold1 f1 a1) (Fold1 f2 a2)- | Just Refl <- matchFun f1 f2- , Just Refl <- matchAcc a1 a2- = Just Refl-- match (FoldSeg f1 z1 a1 s1) (FoldSeg f2 z2 a2 s2)- | Just Refl <- matchFun f1 f2- , Just Refl <- matchExp z1 z2- , Just Refl <- matchAcc a1 a2- , Just Refl <- matchAcc s1 s2- = Just Refl-- match (Fold1Seg f1 a1 s1) (Fold1Seg f2 a2 s2)- | Just Refl <- matchFun f1 f2- , Just Refl <- matchAcc a1 a2- , Just Refl <- matchAcc s1 s2- = Just Refl-- match (Scanl f1 z1 a1) (Scanl f2 z2 a2)- | Just Refl <- matchFun f1 f2- , Just Refl <- matchExp z1 z2- , Just Refl <- matchAcc a1 a2- = Just Refl-- match (Scanl' f1 z1 a1) (Scanl' f2 z2 a2)- | Just Refl <- matchFun f1 f2- , Just Refl <- matchExp z1 z2- , Just Refl <- matchAcc a1 a2- = Just Refl-- match (Scanl1 f1 a1) (Scanl1 f2 a2)- | Just Refl <- matchFun f1 f2- , Just Refl <- matchAcc a1 a2- = Just Refl-- match (Scanr f1 z1 a1) (Scanr f2 z2 a2)- | Just Refl <- matchFun f1 f2- , Just Refl <- matchExp z1 z2- , Just Refl <- matchAcc a1 a2- = Just Refl-- match (Scanr' f1 z1 a1) (Scanr' f2 z2 a2)- | Just Refl <- matchFun f1 f2- , Just Refl <- matchExp z1 z2- , Just Refl <- matchAcc a1 a2- = Just Refl-- match (Scanr1 f1 a1) (Scanr1 f2 a2)- | Just Refl <- matchFun f1 f2- , Just Refl <- matchAcc a1 a2- = Just Refl-- match (Permute f1 d1 p1 a1) (Permute f2 d2 p2 a2)- | Just Refl <- matchFun f1 f2- , Just Refl <- matchAcc d1 d2- , Just Refl <- matchFun p1 p2- , Just Refl <- matchAcc a1 a2- = Just Refl-- match (Backpermute sh1 ix1 a1) (Backpermute sh2 ix2 a2)- | Just Refl <- matchExp sh1 sh2- , Just Refl <- matchFun ix1 ix2- , Just Refl <- matchAcc a1 a2- = Just Refl-- match (Stencil f1 b1 a1) (Stencil f2 b2 a2)- | Just Refl <- matchFun f1 f2- , Just Refl <- matchAcc a1 a2- , matchBoundary matchAcc hashAcc b1 b2- = Just Refl-- match (Stencil2 f1 b1 a1 b2 a2) (Stencil2 f2 b1' a1' b2' a2')- | Just Refl <- matchFun f1 f2- , Just Refl <- matchAcc a1 a1'- , Just Refl <- matchAcc a2 a2'- , matchBoundary matchAcc hashAcc b1 b1'- , matchBoundary matchAcc hashAcc b2 b2'- = Just Refl-- -- match (Collect s1) (Collect s2)- -- = matchSeq matchAcc hashAcc s1 s2-- match _ _- = Nothing----- Array tuples----matchAtuple- :: MatchAcc acc- -> Atuple (acc aenv) s- -> Atuple (acc aenv) t- -> Maybe (s :~: t)-matchAtuple matchAcc (SnocAtup t1 a1) (SnocAtup t2 a2)- | Just Refl <- matchAtuple matchAcc t1 t2- , Just Refl <- matchAcc a1 a2- = Just Refl--matchAtuple _ NilAtup NilAtup = Just Refl-matchAtuple _ _ _ = Nothing----- Array functions----matchOpenAfun- :: OpenAfun aenv s- -> OpenAfun aenv t- -> Maybe (s :~: t)-matchOpenAfun = matchPreOpenAfun matchOpenAcc--matchPreOpenAfun- :: MatchAcc acc- -> PreOpenAfun acc aenv s- -> PreOpenAfun acc aenv t- -> Maybe (s :~: t)-matchPreOpenAfun m (Alam s) (Alam t)- | Just Refl <- matchEnvTop s t- , Just Refl <- matchPreOpenAfun m s t- = Just Refl- where- matchEnvTop :: (Arrays s, Arrays t)- => PreOpenAfun acc (aenv, s) f -> PreOpenAfun acc (aenv, t) g -> Maybe (s :~: t)- matchEnvTop _ _ = gcast Refl -- ???--matchPreOpenAfun m (Abody s) (Abody t) = m s t-matchPreOpenAfun _ _ _ = Nothing----- Match stencil boundaries----matchBoundary- :: forall acc aenv sh t. Elt t- => MatchAcc acc- -> HashAcc acc- -> PreBoundary acc aenv (Array sh t)- -> PreBoundary acc aenv (Array sh t)- -> Bool-matchBoundary _ _ Clamp Clamp = True-matchBoundary _ _ Mirror Mirror = True-matchBoundary _ _ Wrap Wrap = True-matchBoundary _ _ (Constant s) (Constant t) = matchConst (eltType (undefined::t)) s t-matchBoundary m h (Function f) (Function g)- | Just Refl <- matchPreOpenFun m h f g- = True-matchBoundary _ _ _ _- = False---{----- Match sequences----matchSeq- :: forall acc aenv senv s t.- MatchAcc acc- -> HashAcc acc- -> PreOpenSeq acc aenv senv s- -> PreOpenSeq acc aenv senv t- -> Maybe (s :~: t)-matchSeq m h = match- where- matchFun :: PreOpenFun acc env' aenv' u -> PreOpenFun acc env' aenv' v -> Maybe (u :~: v)- matchFun = matchPreOpenFun m h-- matchExp :: PreOpenExp acc env' aenv' u -> PreOpenExp acc env' aenv' v -> Maybe (u :~: v)- matchExp = matchPreOpenExp m h-- match :: PreOpenSeq acc aenv senv' u -> PreOpenSeq acc aenv senv' v -> Maybe (u :~: v)- match (Producer p1 s1) (Producer p2 s2)- | Just Refl <- matchP p1 p2- , Just Refl <- match s1 s2- = Just Refl- match (Consumer c1) (Consumer c2)- | Just Refl <- matchC c1 c2- = Just Refl- match (Reify ix1) (Reify ix2)- | Just Refl <- matchIdx ix1 ix2- = Just Refl- match _ _- = Nothing-- matchP :: Producer acc aenv senv' u -> Producer acc aenv senv' v -> Maybe (u :~: v)- matchP (StreamIn arrs1) (StreamIn arrs2)- | unsafePerformIO $ do- sn1 <- makeStableName arrs1- sn2 <- makeStableName arrs2- return $! hashStableName sn1 == hashStableName sn2- = gcast Refl- matchP (ToSeq _ (_::proxy1 slix1) a1) (ToSeq _ (_::proxy2 slix2) a2)- | Just Refl <- gcast Refl :: Maybe (slix1 :~: slix2) -- Divisions are singleton.- , Just Refl <- m a1 a2- = gcast Refl- matchP (MapSeq f1 x1) (MapSeq f2 x2)- | Just Refl <- matchPreOpenAfun m f1 f2- , Just Refl <- matchIdx x1 x2- = Just Refl- matchP (ZipWithSeq f1 x1 y1) (ZipWithSeq f2 x2 y2)- | Just Refl <- matchPreOpenAfun m f1 f2- , Just Refl <- matchIdx x1 x2- , Just Refl <- matchIdx y1 y2- = Just Refl- matchP (ScanSeq f1 e1 x1) (ScanSeq f2 e2 x2)- | Just Refl <- matchFun f1 f2- , Just Refl <- matchIdx x1 x2- , Just Refl <- matchExp e1 e2- = Just Refl- matchP _ _- = Nothing-- matchC :: Consumer acc aenv senv' u -> Consumer acc aenv senv' v -> Maybe (u :~: v)- matchC (FoldSeq f1 e1 x1) (FoldSeq f2 e2 x2)- | Just Refl <- matchIdx x1 x2- , Just Refl <- matchFun f1 f2- , Just Refl <- matchExp e1 e2- = Just Refl- matchC (FoldSeqFlatten f1 acc1 x1) (FoldSeqFlatten f2 acc2 x2)- | Just Refl <- matchIdx x1 x2- , Just Refl <- matchPreOpenAfun m f1 f2- , Just Refl <- m acc1 acc2- = Just Refl- matchC (Stuple s1) (Stuple s2)- | Just Refl <- matchAtuple matchC s1 s2- = gcast Refl- matchC _ _- = Nothing---}---- Match arrays------ As a convenience, we are just comparing the stable names, but we could also--- walk the structure comparing the underlying ptrsOfArrayData.----matchArrays :: ArraysR s -> ArraysR t -> s -> t -> Maybe (s :~: t)-matchArrays ArraysRunit ArraysRunit () ()- = Just Refl--matchArrays (ArraysRpair a1 b1) (ArraysRpair a2 b2) (arr1,brr1) (arr2,brr2)- | Just Refl <- matchArrays a1 a2 arr1 arr2- , Just Refl <- matchArrays b1 b2 brr1 brr2- = Just Refl--matchArrays ArraysRarray ArraysRarray (Array _ ad1) (Array _ ad2)- | unsafePerformIO $ do- sn1 <- makeStableName ad1- sn2 <- makeStableName ad2- return $! hashStableName sn1 == hashStableName sn2- = gcast Refl--matchArrays _ _ _ _- = Nothing----- Compute the congruence of two scalar expressions. Two nodes are congruent if--- either:------ 1. The nodes label constants and the contents are equal--- 2. They have the same operator and their operands are congruent------ The below attempts to use real typed equality, but occasionally still needs--- to use a cast, particularly when we can only match the representation types.----matchOpenExp- :: OpenExp env aenv s- -> OpenExp env aenv t- -> Maybe (s :~: t)-matchOpenExp = matchPreOpenExp matchOpenAcc hashOpenAcc--matchPreOpenExp- :: forall acc env aenv s t.- MatchAcc acc- -> HashAcc acc- -> PreOpenExp acc env aenv s- -> PreOpenExp acc env aenv t- -> Maybe (s :~: t)-matchPreOpenExp matchAcc hashAcc = match- where- match :: forall env' aenv' s' t'.- PreOpenExp acc env' aenv' s'- -> PreOpenExp acc env' aenv' t'- -> Maybe (s' :~: t')- match (Let x1 e1) (Let x2 e2)- | Just Refl <- match x1 x2- , Just Refl <- match e1 e2- = Just Refl-- match (Var v1) (Var v2)- = matchIdx v1 v2-- match (Foreign ff1 _ e1) (Foreign ff2 _ e2)- | Just Refl <- match e1 e2- , unsafePerformIO $ do- sn1 <- makeStableName ff1- sn2 <- makeStableName ff2- return $! hashStableName sn1 == hashStableName sn2- = gcast Refl-- match (Const c1) (Const c2)- | Just Refl <- matchTupleType (eltType (undefined::s')) (eltType (undefined::t'))- , matchConst (eltType (undefined::s')) c1 c2- = gcast Refl -- surface/representation type-- match (Tuple t1) (Tuple t2)- | Just Refl <- matchTuple matchAcc hashAcc t1 t2- = gcast Refl -- surface/representation type-- match (Prj ix1 t1) (Prj ix2 t2)- | Just Refl <- match t1 t2- , Just Refl <- matchTupleIdx ix1 ix2- = Just Refl-- match IndexAny IndexAny- = gcast Refl -- ???-- match IndexNil IndexNil- = Just Refl-- match (IndexCons sl1 a1) (IndexCons sl2 a2)- | Just Refl <- match sl1 sl2- , Just Refl <- match a1 a2- = Just Refl-- match (IndexHead sl1) (IndexHead sl2)- | Just Refl <- match sl1 sl2- = Just Refl-- match (IndexTail sl1) (IndexTail sl2)- | Just Refl <- match sl1 sl2- = Just Refl-- match (IndexSlice sliceIndex1 ix1 sh1) (IndexSlice sliceIndex2 ix2 sh2)- | Just Refl <- match ix1 ix2- , Just Refl <- match sh1 sh2- , Just Refl <- matchSliceRestrict sliceIndex1 sliceIndex2- = gcast Refl -- SliceIndex representation/surface type-- match (IndexFull sliceIndex1 ix1 sl1) (IndexFull sliceIndex2 ix2 sl2)- | Just Refl <- match ix1 ix2- , Just Refl <- match sl1 sl2- , Just Refl <- matchSliceExtend sliceIndex1 sliceIndex2- = gcast Refl -- SliceIndex representation/surface type-- match (ToIndex sh1 i1) (ToIndex sh2 i2)- | Just Refl <- match sh1 sh2- , Just Refl <- match i1 i2- = Just Refl-- match (FromIndex sh1 i1) (FromIndex sh2 i2)- | Just Refl <- match i1 i2- , Just Refl <- match sh1 sh2- = Just Refl-- match (Cond p1 t1 e1) (Cond p2 t2 e2)- | Just Refl <- match p1 p2- , Just Refl <- match t1 t2- , Just Refl <- match e1 e2- = Just Refl-- match (While p1 f1 x1) (While p2 f2 x2)- | Just Refl <- match x1 x2- , Just Refl <- matchPreOpenFun matchAcc hashAcc p1 p2- , Just Refl <- matchPreOpenFun matchAcc hashAcc f1 f2- = Just Refl-- match (PrimConst c1) (PrimConst c2)- = matchPrimConst c1 c2-- match (PrimApp f1 x1) (PrimApp f2 x2)- | Just x1' <- commutes hashAcc f1 x1- , Just x2' <- commutes hashAcc f2 x2- , Just Refl <- match x1' x2'- , Just Refl <- matchPrimFun f1 f2- = Just Refl-- | Just Refl <- match x1 x2- , Just Refl <- matchPrimFun f1 f2- = Just Refl-- match (Index a1 x1) (Index a2 x2)- | Just Refl <- matchAcc a1 a2 -- should only be array indices- , Just Refl <- match x1 x2- = Just Refl-- match (LinearIndex a1 x1) (LinearIndex a2 x2)- | Just Refl <- matchAcc a1 a2- , Just Refl <- match x1 x2- = Just Refl-- match (Shape a1) (Shape a2)- | Just Refl <- matchAcc a1 a2 -- should only be array indices- = Just Refl-- match (ShapeSize sh1) (ShapeSize sh2)- | Just Refl <- match sh1 sh2- = Just Refl-- match (Intersect sa1 sb1) (Intersect sa2 sb2)- | Just Refl <- match sa1 sa2- , Just Refl <- match sb1 sb2- = Just Refl-- match (Union sa1 sb1) (Union sa2 sb2)- | Just Refl <- match sa1 sa2- , Just Refl <- match sb1 sb2- = Just Refl-- match _ _- = Nothing----- Match scalar functions----matchOpenFun- :: OpenFun env aenv s- -> OpenFun env aenv t- -> Maybe (s :~: t)-matchOpenFun = matchPreOpenFun matchOpenAcc hashOpenAcc--matchPreOpenFun- :: MatchAcc acc- -> HashAcc acc- -> PreOpenFun acc env aenv s- -> PreOpenFun acc env aenv t- -> Maybe (s :~: t)-matchPreOpenFun m h (Lam s) (Lam t)- | Just Refl <- matchEnvTop s t- , Just Refl <- matchPreOpenFun m h s t- = Just Refl- where- matchEnvTop :: (Elt s, Elt t) => PreOpenFun acc (env, s) aenv f -> PreOpenFun acc (env, t) aenv g -> Maybe (s :~: t)- matchEnvTop _ _ = gcast Refl -- ???--matchPreOpenFun m h (Body s) (Body t) = matchPreOpenExp m h s t-matchPreOpenFun _ _ _ _ = Nothing---- Matching constants----matchConst :: TupleType a -> a -> a -> Bool-matchConst UnitTuple () () = True-matchConst (SingleTuple ty) a b = evalEq ty (a,b)-matchConst (PairTuple ta tb) (a1,b1) (a2,b2) = matchConst ta a1 a2 && matchConst tb b1 b2--evalEq :: ScalarType a -> (a, a) -> Bool-evalEq (NumScalarType (IntegralNumType ty)) | IntegralDict <- integralDict ty = uncurry (==)-evalEq (NumScalarType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = uncurry (==)-evalEq (NonNumScalarType ty) | NonNumDict <- nonNumDict ty = uncurry (==)----- Environment projection indices----matchIdx :: Idx env s -> Idx env t -> Maybe (s :~: t)-matchIdx ZeroIdx ZeroIdx = Just Refl-matchIdx (SuccIdx u) (SuccIdx v) = matchIdx u v-matchIdx _ _ = Nothing----- Tuple projection indices. Given the same tuple expression structure (tup),--- check that the indices project identical elements.----matchTupleIdx :: TupleIdx tup s -> TupleIdx tup t -> Maybe (s :~: t)-matchTupleIdx ZeroTupIdx ZeroTupIdx = Just Refl-matchTupleIdx (SuccTupIdx s) (SuccTupIdx t) = matchTupleIdx s t-matchTupleIdx _ _ = Nothing---- Tuples----matchTuple- :: MatchAcc acc- -> HashAcc acc- -> Tuple (PreOpenExp acc env aenv) s- -> Tuple (PreOpenExp acc env aenv) t- -> Maybe (s :~: t)-matchTuple _ _ NilTup NilTup = Just Refl-matchTuple m h (SnocTup t1 e1) (SnocTup t2 e2)- | Just Refl <- matchTuple m h t1 t2- , Just Refl <- matchPreOpenExp m h e1 e2- = Just Refl--matchTuple _ _ _ _ = Nothing----- Slice specifications----matchSliceRestrict- :: SliceIndex slix s co sh- -> SliceIndex slix t co' sh- -> Maybe (s :~: t)-matchSliceRestrict SliceNil SliceNil- = Just Refl--matchSliceRestrict (SliceAll sl1) (SliceAll sl2)- | Just Refl <- matchSliceRestrict sl1 sl2- = Just Refl--matchSliceRestrict (SliceFixed sl1) (SliceFixed sl2)- | Just Refl <- matchSliceRestrict sl1 sl2- = Just Refl--matchSliceRestrict _ _- = Nothing---matchSliceExtend- :: SliceIndex slix sl co s- -> SliceIndex slix sl co' t- -> Maybe (s :~: t)-matchSliceExtend SliceNil SliceNil- = Just Refl--matchSliceExtend (SliceAll sl1) (SliceAll sl2)- | Just Refl <- matchSliceExtend sl1 sl2- = Just Refl--matchSliceExtend (SliceFixed sl1) (SliceFixed sl2)- | Just Refl <- matchSliceExtend sl1 sl2- = Just Refl--matchSliceExtend _ _- = Nothing----- Primitive constants and functions----matchPrimConst :: PrimConst s -> PrimConst t -> Maybe (s :~: t)-matchPrimConst (PrimMinBound s) (PrimMinBound t) = matchBoundedType s t-matchPrimConst (PrimMaxBound s) (PrimMaxBound t) = matchBoundedType s t-matchPrimConst (PrimPi s) (PrimPi t) = matchFloatingType s t-matchPrimConst _ _ = Nothing----- Covariant function matching----matchPrimFun :: PrimFun (a -> s) -> PrimFun (a -> t) -> Maybe (s :~: t)-matchPrimFun (PrimAdd _) (PrimAdd _) = Just Refl-matchPrimFun (PrimSub _) (PrimSub _) = Just Refl-matchPrimFun (PrimMul _) (PrimMul _) = Just Refl-matchPrimFun (PrimNeg _) (PrimNeg _) = Just Refl-matchPrimFun (PrimAbs _) (PrimAbs _) = Just Refl-matchPrimFun (PrimSig _) (PrimSig _) = Just Refl-matchPrimFun (PrimQuot _) (PrimQuot _) = Just Refl-matchPrimFun (PrimRem _) (PrimRem _) = Just Refl-matchPrimFun (PrimQuotRem _) (PrimQuotRem _) = Just Refl-matchPrimFun (PrimIDiv _) (PrimIDiv _) = Just Refl-matchPrimFun (PrimMod _) (PrimMod _) = Just Refl-matchPrimFun (PrimDivMod _) (PrimDivMod _) = Just Refl-matchPrimFun (PrimBAnd _) (PrimBAnd _) = Just Refl-matchPrimFun (PrimBOr _) (PrimBOr _) = Just Refl-matchPrimFun (PrimBXor _) (PrimBXor _) = Just Refl-matchPrimFun (PrimBNot _) (PrimBNot _) = Just Refl-matchPrimFun (PrimBShiftL _) (PrimBShiftL _) = Just Refl-matchPrimFun (PrimBShiftR _) (PrimBShiftR _) = Just Refl-matchPrimFun (PrimBRotateL _) (PrimBRotateL _) = Just Refl-matchPrimFun (PrimBRotateR _) (PrimBRotateR _) = Just Refl-matchPrimFun (PrimPopCount _) (PrimPopCount _) = Just Refl-matchPrimFun (PrimCountLeadingZeros _) (PrimCountLeadingZeros _) = Just Refl-matchPrimFun (PrimCountTrailingZeros _) (PrimCountTrailingZeros _) = Just Refl-matchPrimFun (PrimFDiv _) (PrimFDiv _) = Just Refl-matchPrimFun (PrimRecip _) (PrimRecip _) = Just Refl-matchPrimFun (PrimSin _) (PrimSin _) = Just Refl-matchPrimFun (PrimCos _) (PrimCos _) = Just Refl-matchPrimFun (PrimTan _) (PrimTan _) = Just Refl-matchPrimFun (PrimAsin _) (PrimAsin _) = Just Refl-matchPrimFun (PrimAcos _) (PrimAcos _) = Just Refl-matchPrimFun (PrimAtan _) (PrimAtan _) = Just Refl-matchPrimFun (PrimSinh _) (PrimSinh _) = Just Refl-matchPrimFun (PrimCosh _) (PrimCosh _) = Just Refl-matchPrimFun (PrimTanh _) (PrimTanh _) = Just Refl-matchPrimFun (PrimAsinh _) (PrimAsinh _) = Just Refl-matchPrimFun (PrimAcosh _) (PrimAcosh _) = Just Refl-matchPrimFun (PrimAtanh _) (PrimAtanh _) = Just Refl-matchPrimFun (PrimExpFloating _) (PrimExpFloating _) = Just Refl-matchPrimFun (PrimSqrt _) (PrimSqrt _) = Just Refl-matchPrimFun (PrimLog _) (PrimLog _) = Just Refl-matchPrimFun (PrimFPow _) (PrimFPow _) = Just Refl-matchPrimFun (PrimLogBase _) (PrimLogBase _) = Just Refl-matchPrimFun (PrimAtan2 _) (PrimAtan2 _) = Just Refl-matchPrimFun (PrimTruncate _ s) (PrimTruncate _ t) = matchIntegralType s t-matchPrimFun (PrimRound _ s) (PrimRound _ t) = matchIntegralType s t-matchPrimFun (PrimFloor _ s) (PrimFloor _ t) = matchIntegralType s t-matchPrimFun (PrimCeiling _ s) (PrimCeiling _ t) = matchIntegralType s t-matchPrimFun (PrimIsNaN _) (PrimIsNaN _) = Just Refl-matchPrimFun (PrimIsInfinite _) (PrimIsInfinite _) = Just Refl-matchPrimFun (PrimLt _) (PrimLt _) = Just Refl-matchPrimFun (PrimGt _) (PrimGt _) = Just Refl-matchPrimFun (PrimLtEq _) (PrimLtEq _) = Just Refl-matchPrimFun (PrimGtEq _) (PrimGtEq _) = Just Refl-matchPrimFun (PrimEq _) (PrimEq _) = Just Refl-matchPrimFun (PrimNEq _) (PrimNEq _) = Just Refl-matchPrimFun (PrimMax _) (PrimMax _) = Just Refl-matchPrimFun (PrimMin _) (PrimMin _) = Just Refl-matchPrimFun (PrimFromIntegral _ s) (PrimFromIntegral _ t) = matchNumType s t-matchPrimFun (PrimToFloating _ s) (PrimToFloating _ t) = matchFloatingType s t-matchPrimFun (PrimCoerce _ s) (PrimCoerce _ t) = matchScalarType s t-matchPrimFun PrimLAnd PrimLAnd = Just Refl-matchPrimFun PrimLOr PrimLOr = Just Refl-matchPrimFun PrimLNot PrimLNot = Just Refl-matchPrimFun PrimOrd PrimOrd = Just Refl-matchPrimFun PrimChr PrimChr = Just Refl-matchPrimFun PrimBoolToInt PrimBoolToInt = Just Refl-matchPrimFun _ _ = Nothing----- Contravariant function matching----matchPrimFun' :: PrimFun (s -> a) -> PrimFun (t -> a) -> Maybe (s :~: t)-matchPrimFun' (PrimAdd _) (PrimAdd _) = Just Refl-matchPrimFun' (PrimSub _) (PrimSub _) = Just Refl-matchPrimFun' (PrimMul _) (PrimMul _) = Just Refl-matchPrimFun' (PrimNeg _) (PrimNeg _) = Just Refl-matchPrimFun' (PrimAbs _) (PrimAbs _) = Just Refl-matchPrimFun' (PrimSig _) (PrimSig _) = Just Refl-matchPrimFun' (PrimQuot _) (PrimQuot _) = Just Refl-matchPrimFun' (PrimRem _) (PrimRem _) = Just Refl-matchPrimFun' (PrimQuotRem _) (PrimQuotRem _) = Just Refl-matchPrimFun' (PrimIDiv _) (PrimIDiv _) = Just Refl-matchPrimFun' (PrimMod _) (PrimMod _) = Just Refl-matchPrimFun' (PrimDivMod _) (PrimDivMod _) = Just Refl-matchPrimFun' (PrimBAnd _) (PrimBAnd _) = Just Refl-matchPrimFun' (PrimBOr _) (PrimBOr _) = Just Refl-matchPrimFun' (PrimBXor _) (PrimBXor _) = Just Refl-matchPrimFun' (PrimBNot _) (PrimBNot _) = Just Refl-matchPrimFun' (PrimBShiftL _) (PrimBShiftL _) = Just Refl-matchPrimFun' (PrimBShiftR _) (PrimBShiftR _) = Just Refl-matchPrimFun' (PrimBRotateL _) (PrimBRotateL _) = Just Refl-matchPrimFun' (PrimBRotateR _) (PrimBRotateR _) = Just Refl-matchPrimFun' (PrimPopCount s) (PrimPopCount t) = matchIntegralType s t-matchPrimFun' (PrimCountLeadingZeros s) (PrimCountLeadingZeros t) = matchIntegralType s t-matchPrimFun' (PrimCountTrailingZeros s) (PrimCountTrailingZeros t) = matchIntegralType s t-matchPrimFun' (PrimFDiv _) (PrimFDiv _) = Just Refl-matchPrimFun' (PrimRecip _) (PrimRecip _) = Just Refl-matchPrimFun' (PrimSin _) (PrimSin _) = Just Refl-matchPrimFun' (PrimCos _) (PrimCos _) = Just Refl-matchPrimFun' (PrimTan _) (PrimTan _) = Just Refl-matchPrimFun' (PrimAsin _) (PrimAsin _) = Just Refl-matchPrimFun' (PrimAcos _) (PrimAcos _) = Just Refl-matchPrimFun' (PrimAtan _) (PrimAtan _) = Just Refl-matchPrimFun' (PrimSinh _) (PrimSinh _) = Just Refl-matchPrimFun' (PrimCosh _) (PrimCosh _) = Just Refl-matchPrimFun' (PrimTanh _) (PrimTanh _) = Just Refl-matchPrimFun' (PrimAsinh _) (PrimAsinh _) = Just Refl-matchPrimFun' (PrimAcosh _) (PrimAcosh _) = Just Refl-matchPrimFun' (PrimAtanh _) (PrimAtanh _) = Just Refl-matchPrimFun' (PrimExpFloating _) (PrimExpFloating _) = Just Refl-matchPrimFun' (PrimSqrt _) (PrimSqrt _) = Just Refl-matchPrimFun' (PrimLog _) (PrimLog _) = Just Refl-matchPrimFun' (PrimFPow _) (PrimFPow _) = Just Refl-matchPrimFun' (PrimLogBase _) (PrimLogBase _) = Just Refl-matchPrimFun' (PrimAtan2 _) (PrimAtan2 _) = Just Refl-matchPrimFun' (PrimTruncate s _) (PrimTruncate t _) = matchFloatingType s t-matchPrimFun' (PrimRound s _) (PrimRound t _) = matchFloatingType s t-matchPrimFun' (PrimFloor s _) (PrimFloor t _) = matchFloatingType s t-matchPrimFun' (PrimCeiling s _) (PrimCeiling t _) = matchFloatingType s t-matchPrimFun' (PrimIsNaN s) (PrimIsNaN t) = matchFloatingType s t-matchPrimFun' (PrimIsInfinite s) (PrimIsInfinite t) = matchFloatingType s t-matchPrimFun' (PrimMax _) (PrimMax _) = Just Refl-matchPrimFun' (PrimMin _) (PrimMin _) = Just Refl-matchPrimFun' (PrimFromIntegral s _) (PrimFromIntegral t _) = matchIntegralType s t-matchPrimFun' (PrimToFloating s _) (PrimToFloating t _) = matchNumType s t-matchPrimFun' (PrimCoerce s _) (PrimCoerce t _) = matchScalarType s t-matchPrimFun' PrimLAnd PrimLAnd = Just Refl-matchPrimFun' PrimLOr PrimLOr = Just Refl-matchPrimFun' PrimLNot PrimLNot = Just Refl-matchPrimFun' PrimOrd PrimOrd = Just Refl-matchPrimFun' PrimChr PrimChr = Just Refl-matchPrimFun' PrimBoolToInt PrimBoolToInt = Just Refl-matchPrimFun' (PrimLt s) (PrimLt t)- | Just Refl <- matchScalarType s t- = Just Refl--matchPrimFun' (PrimGt s) (PrimGt t)- | Just Refl <- matchScalarType s t- = Just Refl--matchPrimFun' (PrimLtEq s) (PrimLtEq t)- | Just Refl <- matchScalarType s t- = Just Refl--matchPrimFun' (PrimGtEq s) (PrimGtEq t)- | Just Refl <- matchScalarType s t- = Just Refl--matchPrimFun' (PrimEq s) (PrimEq t)- | Just Refl <- matchScalarType s t- = Just Refl--matchPrimFun' (PrimNEq s) (PrimNEq t)- | Just Refl <- matchScalarType s t- = Just Refl--matchPrimFun' _ _- = Nothing----- Match reified types----matchTupleType :: TupleType s -> TupleType t -> Maybe (s :~: t)-matchTupleType UnitTuple UnitTuple = Just Refl-matchTupleType (SingleTuple s) (SingleTuple t) = matchScalarType s t-matchTupleType (PairTuple s1 s2) (PairTuple t1 t2)- | Just Refl <- matchTupleType s1 t1- , Just Refl <- matchTupleType s2 t2- = Just Refl--matchTupleType _ _- = Nothing----- Match reified type dictionaries----matchScalarType :: ScalarType s -> ScalarType t -> Maybe (s :~: t)-matchScalarType (NumScalarType s) (NumScalarType t) = matchNumType s t-matchScalarType (NonNumScalarType s) (NonNumScalarType t) = matchNonNumType s t-matchScalarType _ _ = Nothing--matchNumType :: NumType s -> NumType t -> Maybe (s :~: t)-matchNumType (IntegralNumType s) (IntegralNumType t) = matchIntegralType s t-matchNumType (FloatingNumType s) (FloatingNumType t) = matchFloatingType s t-matchNumType _ _ = Nothing--matchBoundedType :: BoundedType s -> BoundedType t -> Maybe (s :~: t)-matchBoundedType (IntegralBoundedType s) (IntegralBoundedType t) = matchIntegralType s t-matchBoundedType (NonNumBoundedType s) (NonNumBoundedType t) = matchNonNumType s t-matchBoundedType _ _ = Nothing--matchIntegralType :: IntegralType s -> IntegralType t -> Maybe (s :~: t)-matchIntegralType (TypeInt _) (TypeInt _) = Just Refl-matchIntegralType (TypeInt8 _) (TypeInt8 _) = Just Refl-matchIntegralType (TypeInt16 _) (TypeInt16 _) = Just Refl-matchIntegralType (TypeInt32 _) (TypeInt32 _) = Just Refl-matchIntegralType (TypeInt64 _) (TypeInt64 _) = Just Refl-matchIntegralType (TypeWord _) (TypeWord _) = Just Refl-matchIntegralType (TypeWord8 _) (TypeWord8 _) = Just Refl-matchIntegralType (TypeWord16 _) (TypeWord16 _) = Just Refl-matchIntegralType (TypeWord32 _) (TypeWord32 _) = Just Refl-matchIntegralType (TypeWord64 _) (TypeWord64 _) = Just Refl-matchIntegralType (TypeCShort _) (TypeCShort _) = Just Refl-matchIntegralType (TypeCUShort _) (TypeCUShort _) = Just Refl-matchIntegralType (TypeCInt _) (TypeCInt _) = Just Refl-matchIntegralType (TypeCUInt _) (TypeCUInt _) = Just Refl-matchIntegralType (TypeCLong _) (TypeCLong _) = Just Refl-matchIntegralType (TypeCULong _) (TypeCULong _) = Just Refl-matchIntegralType (TypeCLLong _) (TypeCLLong _) = Just Refl-matchIntegralType (TypeCULLong _) (TypeCULLong _) = Just Refl-matchIntegralType _ _ = Nothing--matchFloatingType :: FloatingType s -> FloatingType t -> Maybe (s :~: t)-matchFloatingType (TypeFloat _) (TypeFloat _) = Just Refl-matchFloatingType (TypeDouble _) (TypeDouble _) = Just Refl-matchFloatingType (TypeCFloat _) (TypeCFloat _) = Just Refl-matchFloatingType (TypeCDouble _) (TypeCDouble _) = Just Refl-matchFloatingType _ _ = Nothing--matchNonNumType :: NonNumType s -> NonNumType t -> Maybe (s :~: t)-matchNonNumType (TypeBool _) (TypeBool _) = Just Refl-matchNonNumType (TypeChar _) (TypeChar _) = Just Refl-matchNonNumType (TypeCChar _) (TypeCChar _) = Just Refl-matchNonNumType (TypeCSChar _) (TypeCSChar _) = Just Refl-matchNonNumType (TypeCUChar _) (TypeCUChar _) = Just Refl-matchNonNumType _ _ = Nothing-
− Data/Array/Accelerate/Analysis/Shape.hs
@@ -1,124 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# OPTIONS_HADDOCK hide #-}--- |--- Module : Data.Array.Accelerate.Analysis.Shape--- Copyright : [2008..2017] Manuel M T Chakravarty, Gabriele Keller--- [2009..2017] Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Analysis.Shape (-- -- * query AST dimensionality- AccDim, accDim, delayedDim, preAccDim,- expDim,--) where--import Data.Array.Accelerate.AST-import Data.Array.Accelerate.Type-import Data.Array.Accelerate.Trafo.Base-import Data.Array.Accelerate.Array.Sugar---type AccDim acc = forall aenv sh e. acc aenv (Array sh e) -> Int---- |Reify the dimensionality of the result type of an array computation----accDim :: AccDim OpenAcc-accDim (OpenAcc acc) = preAccDim accDim acc--delayedDim :: AccDim DelayedOpenAcc-delayedDim (Manifest acc) = preAccDim delayedDim acc-delayedDim (Delayed sh _ _) = expDim sh----- |Reify dimensionality of a computation parameterised over a recursive closure----preAccDim :: forall acc aenv sh e. AccDim acc -> PreOpenAcc acc aenv (Array sh e) -> Int-preAccDim k pacc =- case pacc of- Alet _ acc -> k acc- Avar _ -> case arrays (undefined :: Array sh e) of- ArraysRarray -> ndim (eltType (undefined::sh))-#if __GLASGOW_HASKELL__ < 800- _ -> error "halt, fiend!"-#endif-- Apply _ _ -> case arrays (undefined :: Array sh e) of- ArraysRarray -> ndim (eltType (undefined::sh))-#if __GLASGOW_HASKELL__ < 800- _ -> error "umm, hello"-#endif-- Aforeign _ _ _ -> case arrays (undefined :: Array sh e) of- ArraysRarray -> ndim (eltType (undefined::sh))-#if __GLASGOW_HASKELL__ < 800- _ -> error "I don't even like snails!"-#endif-- Atuple _ -> case arrays (undefined :: Array sh e) of- ArraysRarray -> ndim (eltType (undefined::sh))-#if __GLASGOW_HASKELL__ < 800- _ -> error "can we keep him?"-#endif-- Aprj _ _ -> case arrays (undefined :: Array sh e) of- ArraysRarray -> ndim (eltType (undefined::sh))-#if __GLASGOW_HASKELL__ < 800- _ -> error "inconceivable!"-#endif--{--- Collect _ -> case arrays (undefined :: Array sh e) of- ArraysRarray -> ndim (eltType (undefined::sh))-#if __GLASGOW_HASKELL__ < 800- _ -> error "ppbbbbbt~"-#endif---}-- Acond _ acc _ -> k acc- Awhile _ _ acc -> k acc- Use Array{} -> ndim (eltType (undefined::sh))- Unit _ -> 0- Generate _ _ -> ndim (eltType (undefined::sh))- Transform _ _ _ _ -> ndim (eltType (undefined::sh))- Reshape _ _ -> ndim (eltType (undefined::sh))- Replicate _ _ _ -> ndim (eltType (undefined::sh))- Slice _ _ _ -> ndim (eltType (undefined::sh))- Map _ acc -> k acc- ZipWith _ _ acc -> k acc- Fold _ _ acc -> k acc - 1- Fold1 _ acc -> k acc - 1- FoldSeg _ _ acc _ -> k acc- Fold1Seg _ acc _ -> k acc- Scanl _ _ acc -> k acc- Scanl1 _ acc -> k acc- Scanr _ _ acc -> k acc- Scanr1 _ acc -> k acc- Permute _ acc _ _ -> k acc- Backpermute _ _ _ -> ndim (eltType (undefined::sh))- Stencil _ _ acc -> k acc- Stencil2 _ _ acc _ _ -> k acc----- |Reify dimensionality of a scalar expression yielding a shape----expDim :: forall acc env aenv sh. Elt sh => PreOpenExp acc env aenv sh -> Int-expDim _ = ndim (eltType (undefined :: sh))----- Count the number of components to a tuple type----ndim :: TupleType a -> Int-ndim UnitTuple = 0-ndim (SingleTuple _) = 1-ndim (PairTuple a b) = ndim a + ndim b-
− Data/Array/Accelerate/Analysis/Stencil.hs
@@ -1,91 +0,0 @@-{-# LANGUAGE GADTs #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeOperators #-}-{-# OPTIONS_HADDOCK hide #-}--- |--- Module : Data.Array.Accelerate.Analysis.Stencil--- Copyright : [2010..2011] Ben Lever--- [2010..2017] Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Analysis.Stencil (offsets, offsets2) where--import Data.Array.Accelerate.AST-import Data.Array.Accelerate.Array.Sugar----- |Calculate the offset coordinates for each stencil element relative to the--- focal point. The coordinates are returned as a flattened list from the--- bottom-left element to the top-right. This ordering matches the Var indexing--- order.----offsets :: forall a b sh aenv stencil. Stencil sh a stencil- => {- dummy -} Fun aenv (stencil -> b)- -> {- dummy -} OpenAcc aenv (Array sh a)- -> [sh]-offsets _ _ = positionsR (stencil :: StencilR sh a stencil)--offsets2 :: forall a b c sh aenv stencil1 stencil2. (Stencil sh a stencil1, Stencil sh b stencil2)- => {- dummy -} Fun aenv (stencil1 -> stencil2 -> c)- -> {- dummy -} OpenAcc aenv (Array sh a)- -> {- dummy -} OpenAcc aenv (Array sh b)- -> ([sh], [sh])-offsets2 _ _ _ =- ( positionsR (stencil :: StencilR sh a stencil1)- , positionsR (stencil :: StencilR sh b stencil2) )----- |Position calculation on reified stencil values.----positionsR :: StencilR sh e pat -> [sh]-positionsR StencilRunit3 = map (Z:.) [ -1, 0, 1 ]-positionsR StencilRunit5 = map (Z:.) [ -2,-1, 0, 1, 2 ]-positionsR StencilRunit7 = map (Z:.) [ -3,-2,-1, 0, 1, 2, 3 ]-positionsR StencilRunit9 = map (Z:.) [-4,-3,-2,-1, 0, 1, 2, 3, 4 ]--positionsR (StencilRtup3 c b a) = concat- [ map (innermost (:. -1)) $ positionsR c- , map (innermost (:. 0)) $ positionsR b- , map (innermost (:. 1)) $ positionsR a ]--positionsR (StencilRtup5 e d c b a) = concat- [ map (innermost (:. -2)) $ positionsR e- , map (innermost (:. -1)) $ positionsR d- , map (innermost (:. 0)) $ positionsR c- , map (innermost (:. 1)) $ positionsR b- , map (innermost (:. 2)) $ positionsR a ]--positionsR (StencilRtup7 g f e d c b a) = concat- [ map (innermost (:. -3)) $ positionsR g- , map (innermost (:. -2)) $ positionsR f- , map (innermost (:. -1)) $ positionsR e- , map (innermost (:. 0)) $ positionsR d- , map (innermost (:. 1)) $ positionsR c- , map (innermost (:. 2)) $ positionsR b- , map (innermost (:. 3)) $ positionsR a ]--positionsR (StencilRtup9 i h g f e d c b a) = concat- [ map (innermost (:. -4)) $ positionsR i- , map (innermost (:. -3)) $ positionsR h- , map (innermost (:. -2)) $ positionsR g- , map (innermost (:. -1)) $ positionsR f- , map (innermost (:. 0)) $ positionsR e- , map (innermost (:. 1)) $ positionsR d- , map (innermost (:. 2)) $ positionsR c- , map (innermost (:. 3)) $ positionsR b- , map (innermost (:. 4)) $ positionsR a ]----- Inject a dimension component inner-most----innermost :: Shape sh => (sh -> sh :. Int) -> sh -> sh :. Int-innermost f = invertShape . f . invertShape--invertShape :: Shape sh => sh -> sh-invertShape = listToShape . reverse . shapeToList-
− Data/Array/Accelerate/Analysis/Type.hs
@@ -1,204 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE PatternGuards #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}-{-# OPTIONS_HADDOCK hide #-}--- |--- Module : Data.Array.Accelerate.Analysis.Type--- Copyright : [2008..2017] Manuel M T Chakravarty, Gabriele Keller--- [2009..2017] Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)------ The Accelerate AST does not explicitly store much type information. Most of--- it is only indirectly through type class constraints -especially, 'Elt'--- constraints- available. This module provides functions that reify that--- type information in the form of a 'TupleType' value. This is, for example,--- needed to emit type information in a backend.-----module Data.Array.Accelerate.Analysis.Type (-- -- * Query AST types- AccType, arrayType, sizeOf,- accType, expType, delayedAccType, delayedExpType,- preAccType, preExpType--) where---- standard library-import qualified Foreign.Storable as F---- friends-import Data.Array.Accelerate.Type-import Data.Array.Accelerate.Array.Sugar-import Data.Array.Accelerate.AST-import Data.Array.Accelerate.Trafo------ |Determine an array type--- ---------------------------- |Reify the element type of an array.----arrayType :: forall sh e. Array sh e -> TupleType (EltRepr e)-arrayType (Array _ _) = eltType (undefined::e)----- |Determine the type of an expressions--- ---------------------------------------type AccType acc = forall aenv sh e. acc aenv (Array sh e) -> TupleType (EltRepr e)---- |Reify the element type of the result of an array computation.----accType :: AccType OpenAcc-accType (OpenAcc acc) = preAccType accType acc--delayedAccType :: AccType DelayedOpenAcc-delayedAccType (Manifest acc) = preAccType delayedAccType acc-delayedAccType (Delayed _ f _)- | Lam (Body e) <- f = delayedExpType e- | otherwise = error "my favourite place in the world is wherever you happen to be"----- |Reify the element type of the result of an array computation using the array computation AST--- before tying the knot.----preAccType :: forall acc aenv sh e.- AccType acc- -> PreOpenAcc acc aenv (Array sh e)- -> TupleType (EltRepr e)-preAccType k pacc =- case pacc of- Alet _ acc -> k acc-- -- The following all contain impossible pattern matches, but GHC's type- -- checker does no grok that- --- Avar _ -> case arrays (undefined :: (Array sh e)) of- ArraysRarray -> eltType (undefined::e)-#if __GLASGOW_HASKELL__ < 800- _ -> error "When I get sad, I stop being sad and be AWESOME instead."-#endif-- Apply _ _ -> case arrays (undefined :: Array sh e) of- ArraysRarray -> eltType (undefined::e)-#if __GLASGOW_HASKELL__ < 800- _ -> error "TRUE STORY."-#endif-- Atuple _ -> case arrays (undefined :: Array sh e) of- ArraysRarray -> eltType (undefined::e)-#if __GLASGOW_HASKELL__ < 800- _ -> error "I made you a cookie, but I eated it."-#endif-- Aprj _ _ -> case arrays (undefined :: Array sh e) of- ArraysRarray -> eltType (undefined::e)-#if __GLASGOW_HASKELL__ < 800- _ -> error "Hey look! even the leaves are falling for you."-#endif-- Aforeign _ _ _ -> case arrays (undefined :: Array sh e) of- ArraysRarray -> eltType (undefined::e)-#if __GLASGOW_HASKELL__ < 800- _ -> error "Who on earth wrote all these weird error messages?"-#endif--{--- Collect _ -> case arrays (undefined :: Array sh e) of- ArraysRarray -> eltType (undefined::e)-#if __GLASGOW_HASKELL__ < 800- _ -> error "rob you are terrible at this game"-#endif---}-- Acond _ acc _ -> k acc- Awhile _ _ acc -> k acc- Use a -> arrayType a- Unit _ -> eltType (undefined::e)- Generate _ _ -> eltType (undefined::e)- Transform _ _ _ _ -> eltType (undefined::e)- Reshape _ acc -> k acc- Replicate _ _ acc -> k acc- Slice _ acc _ -> k acc- Map _ _ -> eltType (undefined::e)- ZipWith _ _ _ -> eltType (undefined::e)- Fold _ _ acc -> k acc- FoldSeg _ _ acc _ -> k acc- Fold1 _ acc -> k acc- Fold1Seg _ acc _ -> k acc- Scanl _ _ acc -> k acc- Scanl1 _ acc -> k acc- Scanr _ _ acc -> k acc- Scanr1 _ acc -> k acc- Permute _ _ _ acc -> k acc- Backpermute _ _ acc -> k acc- Stencil _ _ _ -> eltType (undefined::e)- Stencil2 _ _ _ _ _ -> eltType (undefined::e)----- |Reify the result type of a scalar expression.----expType :: OpenExp env aenv t -> TupleType (EltRepr t)-expType = preExpType accType--delayedExpType :: DelayedOpenExp env aenv t -> TupleType (EltRepr t)-delayedExpType = preExpType delayedAccType---- |Reify the result types of of a scalar expression using the expression AST before tying the--- knot.----preExpType :: forall acc aenv env t.- AccType acc- -> PreOpenExp acc aenv env t- -> TupleType (EltRepr t)-preExpType k e =- case e of- Let _ _ -> eltType (undefined::t)- Var _ -> eltType (undefined::t)- Const _ -> eltType (undefined::t)- Tuple _ -> eltType (undefined::t)- Prj _ _ -> eltType (undefined::t)- IndexNil -> eltType (undefined::t)- IndexCons _ _ -> eltType (undefined::t)- IndexHead _ -> eltType (undefined::t)- IndexTail _ -> eltType (undefined::t)- IndexAny -> eltType (undefined::t)- IndexSlice _ _ _ -> eltType (undefined::t)- IndexFull _ _ _ -> eltType (undefined::t)- ToIndex _ _ -> eltType (undefined::t)- FromIndex _ _ -> eltType (undefined::t)- Cond _ t _ -> preExpType k t- While _ _ _ -> eltType (undefined::t)- PrimConst _ -> eltType (undefined::t)- PrimApp _ _ -> eltType (undefined::t)- Index acc _ -> k acc- LinearIndex acc _ -> k acc- Shape _ -> eltType (undefined::t)- ShapeSize _ -> eltType (undefined::t)- Intersect _ _ -> eltType (undefined::t)- Union _ _ -> eltType (undefined::t)- Foreign _ _ _ -> eltType (undefined::t)----- |Size of a tuple type, in bytes----sizeOf :: TupleType a -> Int-sizeOf UnitTuple = 0-sizeOf (PairTuple a b) = sizeOf a + sizeOf b--sizeOf (SingleTuple (NumScalarType (IntegralNumType t)))- | IntegralDict <- integralDict t = F.sizeOf $ (undefined :: IntegralType a -> a) t-sizeOf (SingleTuple (NumScalarType (FloatingNumType t)))- | FloatingDict <- floatingDict t = F.sizeOf $ (undefined :: FloatingType a -> a) t-sizeOf (SingleTuple (NonNumScalarType t))- | NonNumDict <- nonNumDict t = F.sizeOf $ (undefined :: NonNumType a -> a) t-
− Data/Array/Accelerate/Array/Data.hs
@@ -1,810 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE UnboxedTuples #-}-{-# OPTIONS_HADDOCK hide #-}--- |--- Module : Data.Array.Accelerate.Array.Data--- Copyright : [2008..2017] Manuel M T Chakravarty, Gabriele Keller--- [2009..2017] Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)------ This module fixes the concrete representation of Accelerate arrays. We--- allocate all arrays using pinned memory to enable safe direct-access by--- non-Haskell code in multi-threaded code. In particular, we can safely pass--- pointers to an array's payload to foreign code.-----module Data.Array.Accelerate.Array.Data (-- -- * Array operations and representations- ArrayElt(..), ArrayData, MutableArrayData, runArrayData,- ArrayEltR(..), GArrayData(..),-- -- * Array tuple operations- fstArrayData, sndArrayData, pairArrayData,-- -- * Type macros- HTYPE_INT, HTYPE_WORD, HTYPE_LONG, HTYPE_UNSIGNED_LONG, HTYPE_CCHAR,-- -- * Allocator internals- registerForeignPtrAllocator,--) where---- friends-import Data.Array.Accelerate.Array.Unique-import Data.Array.Accelerate.Error-import Data.Array.Accelerate.Type--import Data.Array.Accelerate.Debug.Flags-import Data.Array.Accelerate.Debug.Monitoring-import Data.Array.Accelerate.Debug.Trace---- standard libraries-import Control.Applicative-import Control.Monad-import Data.Bits-import Data.IORef-import Data.Typeable ( Typeable )-import Foreign.C.Types-import Foreign.ForeignPtr-import Foreign.Ptr-import Foreign.Storable-import Language.Haskell.TH-import System.IO.Unsafe-import Text.Printf-import Prelude--import GHC.Base ( Int(..), IO(..), unsafeCoerce#, newAlignedPinnedByteArray#, byteArrayContents# )-import GHC.ForeignPtr ( ForeignPtr(..), ForeignPtrContents(..) )----- Determine the underlying type of a Haskell CLong or CULong.----$( runQ [d| type HTYPE_INT = $(- case finiteBitSize (undefined::Int) of- 32 -> [t| Int32 |]- 64 -> [t| Int64 |]- _ -> error "I don't know what architecture I am" ) |] )--$( runQ [d| type HTYPE_WORD = $(- case finiteBitSize (undefined::Word) of- 32 -> [t| Word32 |]- 64 -> [t| Word64 |]- _ -> error "I don't know what architecture I am" ) |] )--$( runQ [d| type HTYPE_LONG = $(- case finiteBitSize (undefined::CLong) of- 32 -> [t| Int32 |]- 64 -> [t| Int64 |]- _ -> error "I don't know what architecture I am" ) |] )--$( runQ [d| type HTYPE_UNSIGNED_LONG = $(- case finiteBitSize (undefined::CULong) of- 32 -> [t| Word32 |]- 64 -> [t| Word64 |]- _ -> error "I don't know what architecture I am" ) |] )--$( runQ [d| type HTYPE_CCHAR = $(- case isSigned (undefined::CChar) of- True -> [t| Int8 |]- False -> [t| Word8 |] ) |] )----- Array representation--- ------------------------ |Immutable array representation----type ArrayData e = MutableArrayData e---- |Mutable array representation----type MutableArrayData e = GArrayData UniqueArray e---- Array representation in dependence on the element type, but abstracting--- over the basic array type (in particular, abstracting over mutability)----data family GArrayData :: (* -> *) -> * -> *-data instance GArrayData ba () = AD_Unit-data instance GArrayData ba Int = AD_Int (ba Int)-data instance GArrayData ba Int8 = AD_Int8 (ba Int8)-data instance GArrayData ba Int16 = AD_Int16 (ba Int16)-data instance GArrayData ba Int32 = AD_Int32 (ba Int32)-data instance GArrayData ba Int64 = AD_Int64 (ba Int64)-data instance GArrayData ba Word = AD_Word (ba Word)-data instance GArrayData ba Word8 = AD_Word8 (ba Word8)-data instance GArrayData ba Word16 = AD_Word16 (ba Word16)-data instance GArrayData ba Word32 = AD_Word32 (ba Word32)-data instance GArrayData ba Word64 = AD_Word64 (ba Word64)-data instance GArrayData ba CShort = AD_CShort (ba Int16)-data instance GArrayData ba CUShort = AD_CUShort (ba Word16)-data instance GArrayData ba CInt = AD_CInt (ba Int32)-data instance GArrayData ba CUInt = AD_CUInt (ba Word32)-data instance GArrayData ba CLong = AD_CLong (ba HTYPE_LONG)-data instance GArrayData ba CULong = AD_CULong (ba HTYPE_UNSIGNED_LONG)-data instance GArrayData ba CLLong = AD_CLLong (ba Int64)-data instance GArrayData ba CULLong = AD_CULLong (ba Word64)-data instance GArrayData ba Float = AD_Float (ba Float)-data instance GArrayData ba Double = AD_Double (ba Double)-data instance GArrayData ba CFloat = AD_CFloat (ba Float)-data instance GArrayData ba CDouble = AD_CDouble (ba Double)-data instance GArrayData ba Bool = AD_Bool (ba Word8)-data instance GArrayData ba Char = AD_Char (ba Char)-data instance GArrayData ba CChar = AD_CChar (ba HTYPE_CCHAR)-data instance GArrayData ba CSChar = AD_CSChar (ba Int8)-data instance GArrayData ba CUChar = AD_CUChar (ba Word8)-data instance GArrayData ba (a, b) = AD_Pair (GArrayData ba a)- (GArrayData ba b)--deriving instance Typeable GArrayData----- | GADT to reify the 'ArrayElt' class.----data ArrayEltR a where- ArrayEltRunit :: ArrayEltR ()- ArrayEltRint :: ArrayEltR Int- ArrayEltRint8 :: ArrayEltR Int8- ArrayEltRint16 :: ArrayEltR Int16- ArrayEltRint32 :: ArrayEltR Int32- ArrayEltRint64 :: ArrayEltR Int64- ArrayEltRword :: ArrayEltR Word- ArrayEltRword8 :: ArrayEltR Word8- ArrayEltRword16 :: ArrayEltR Word16- ArrayEltRword32 :: ArrayEltR Word32- ArrayEltRword64 :: ArrayEltR Word64- ArrayEltRcshort :: ArrayEltR CShort- ArrayEltRcushort :: ArrayEltR CUShort- ArrayEltRcint :: ArrayEltR CInt- ArrayEltRcuint :: ArrayEltR CUInt- ArrayEltRclong :: ArrayEltR CLong- ArrayEltRculong :: ArrayEltR CULong- ArrayEltRcllong :: ArrayEltR CLLong- ArrayEltRcullong :: ArrayEltR CULLong- ArrayEltRfloat :: ArrayEltR Float- ArrayEltRdouble :: ArrayEltR Double- ArrayEltRcfloat :: ArrayEltR CFloat- ArrayEltRcdouble :: ArrayEltR CDouble- ArrayEltRbool :: ArrayEltR Bool- ArrayEltRchar :: ArrayEltR Char- ArrayEltRcchar :: ArrayEltR CChar- ArrayEltRcschar :: ArrayEltR CSChar- ArrayEltRcuchar :: ArrayEltR CUChar- ArrayEltRpair :: (ArrayElt a, ArrayElt b)- => ArrayEltR a -> ArrayEltR b -> ArrayEltR (a,b)---- Array operations--- ---------------------- TLM: do we need to INLINE these functions to get good performance interfacing--- to external libraries, especially Repa?--class ArrayElt e where- type ArrayPtrs e- arrayElt :: ArrayEltR e- --- unsafeIndexArrayData :: ArrayData e -> Int -> e- ptrsOfArrayData :: ArrayData e -> ArrayPtrs e- touchArrayData :: ArrayData e -> IO ()- --- newArrayData :: Int -> IO (MutableArrayData e)- unsafeReadArrayData :: MutableArrayData e -> Int -> IO e- unsafeWriteArrayData :: MutableArrayData e -> Int -> e -> IO ()- unsafeFreezeArrayData :: MutableArrayData e -> IO (ArrayData e)- ptrsOfMutableArrayData :: MutableArrayData e -> IO (ArrayPtrs e)- --- {-# INLINE unsafeFreezeArrayData #-}- {-# INLINE ptrsOfMutableArrayData #-}- unsafeFreezeArrayData = return- ptrsOfMutableArrayData = return . ptrsOfArrayData--instance ArrayElt () where- type ArrayPtrs () = ()- arrayElt = ArrayEltRunit- {-# INLINE unsafeIndexArrayData #-}- unsafeIndexArrayData AD_Unit i = i `seq` ()- {-# INLINE ptrsOfArrayData #-}- ptrsOfArrayData AD_Unit = ()- {-# INLINE touchArrayData #-}- touchArrayData AD_Unit = return ()- {-# INLINE newArrayData #-}- newArrayData size = size `seq` return AD_Unit- {-# INLINE unsafeReadArrayData #-}- unsafeReadArrayData AD_Unit i = i `seq` return ()- {-# INLINE unsafeWriteArrayData #-}- unsafeWriteArrayData AD_Unit i () = i `seq` return ()--instance ArrayElt Int where- type ArrayPtrs Int = Ptr Int- arrayElt = ArrayEltRint- {-# INLINE unsafeIndexArrayData #-}- unsafeIndexArrayData (AD_Int ba) i = unsafeIndexArray ba i- {-# INLINE ptrsOfArrayData #-}- ptrsOfArrayData (AD_Int ba) = unsafeUniqueArrayPtr ba- {-# INLINE touchArrayData #-}- touchArrayData (AD_Int ba) = touchUniqueArray ba- {-# INLINE newArrayData #-}- newArrayData size = AD_Int <$> newArrayData' size- {-# INLINE unsafeReadArrayData #-}- unsafeReadArrayData (AD_Int ba) i = unsafeReadArray ba i- {-# INLINE unsafeWriteArrayData #-}- unsafeWriteArrayData (AD_Int ba) i e = unsafeWriteArray ba i e--instance ArrayElt Int8 where- type ArrayPtrs Int8 = Ptr Int8- arrayElt = ArrayEltRint8- {-# INLINE unsafeIndexArrayData #-}- unsafeIndexArrayData (AD_Int8 ba) i = unsafeIndexArray ba i- {-# INLINE ptrsOfArrayData #-}- ptrsOfArrayData (AD_Int8 ba) = unsafeUniqueArrayPtr ba- {-# INLINE touchArrayData #-}- touchArrayData (AD_Int8 ba) = touchUniqueArray ba- {-# INLINE newArrayData #-}- newArrayData size = AD_Int8 <$> newArrayData' size- {-# INLINE unsafeReadArrayData #-}- unsafeReadArrayData (AD_Int8 ba) i = unsafeReadArray ba i- {-# INLINE unsafeWriteArrayData #-}- unsafeWriteArrayData (AD_Int8 ba) i e = unsafeWriteArray ba i e--instance ArrayElt Int16 where- type ArrayPtrs Int16 = Ptr Int16- arrayElt = ArrayEltRint16- {-# INLINE unsafeIndexArrayData #-}- unsafeIndexArrayData (AD_Int16 ba) i = unsafeIndexArray ba i- {-# INLINE ptrsOfArrayData #-}- ptrsOfArrayData (AD_Int16 ba) = unsafeUniqueArrayPtr ba- {-# INLINE touchArrayData #-}- touchArrayData (AD_Int16 ba) = touchUniqueArray ba- {-# INLINE newArrayData #-}- newArrayData size = AD_Int16 <$> newArrayData' size- {-# INLINE unsafeReadArrayData #-}- unsafeReadArrayData (AD_Int16 ba) i = unsafeReadArray ba i- {-# INLINE unsafeWriteArrayData #-}- unsafeWriteArrayData (AD_Int16 ba) i e = unsafeWriteArray ba i e--instance ArrayElt Int32 where- type ArrayPtrs Int32 = Ptr Int32- arrayElt = ArrayEltRint32- {-# INLINE unsafeIndexArrayData #-}- unsafeIndexArrayData (AD_Int32 ba) i = unsafeIndexArray ba i- {-# INLINE ptrsOfArrayData #-}- ptrsOfArrayData (AD_Int32 ba) = unsafeUniqueArrayPtr ba- {-# INLINE touchArrayData #-}- touchArrayData (AD_Int32 ba) = touchUniqueArray ba- {-# INLINE newArrayData #-}- newArrayData size = AD_Int32 <$> newArrayData' size- {-# INLINE unsafeReadArrayData #-}- unsafeReadArrayData (AD_Int32 ba) i = unsafeReadArray ba i- {-# INLINE unsafeWriteArrayData #-}- unsafeWriteArrayData (AD_Int32 ba) i e = unsafeWriteArray ba i e--instance ArrayElt Int64 where- type ArrayPtrs Int64 = Ptr Int64- arrayElt = ArrayEltRint64- {-# INLINE unsafeIndexArrayData #-}- unsafeIndexArrayData (AD_Int64 ba) i = unsafeIndexArray ba i- {-# INLINE ptrsOfArrayData #-}- ptrsOfArrayData (AD_Int64 ba) = unsafeUniqueArrayPtr ba- {-# INLINE touchArrayData #-}- touchArrayData (AD_Int64 ba) = touchUniqueArray ba- {-# INLINE newArrayData #-}- newArrayData size = AD_Int64 <$> newArrayData' size- {-# INLINE unsafeReadArrayData #-}- unsafeReadArrayData (AD_Int64 ba) i = unsafeReadArray ba i- {-# INLINE unsafeWriteArrayData #-}- unsafeWriteArrayData (AD_Int64 ba) i e = unsafeWriteArray ba i e--instance ArrayElt Word where- type ArrayPtrs Word = Ptr Word- arrayElt = ArrayEltRword- {-# INLINE unsafeIndexArrayData #-}- unsafeIndexArrayData (AD_Word ba) i = unsafeIndexArray ba i- {-# INLINE ptrsOfArrayData #-}- ptrsOfArrayData (AD_Word ba) = unsafeUniqueArrayPtr ba- {-# INLINE touchArrayData #-}- touchArrayData (AD_Word ba) = touchUniqueArray ba- {-# INLINE newArrayData #-}- newArrayData size = AD_Word <$> newArrayData' size- {-# INLINE unsafeReadArrayData #-}- unsafeReadArrayData (AD_Word ba) i = unsafeReadArray ba i- {-# INLINE unsafeWriteArrayData #-}- unsafeWriteArrayData (AD_Word ba) i e = unsafeWriteArray ba i e--instance ArrayElt Word8 where- type ArrayPtrs Word8 = Ptr Word8- arrayElt = ArrayEltRword8- {-# INLINE unsafeIndexArrayData #-}- unsafeIndexArrayData (AD_Word8 ba) i = unsafeIndexArray ba i- {-# INLINE ptrsOfArrayData #-}- ptrsOfArrayData (AD_Word8 ba) = unsafeUniqueArrayPtr ba- {-# INLINE touchArrayData #-}- touchArrayData (AD_Word8 ba) = touchUniqueArray ba- {-# INLINE newArrayData #-}- newArrayData size = AD_Word8 <$> newArrayData' size- {-# INLINE unsafeReadArrayData #-}- unsafeReadArrayData (AD_Word8 ba) i = unsafeReadArray ba i- {-# INLINE unsafeWriteArrayData #-}- unsafeWriteArrayData (AD_Word8 ba) i e = unsafeWriteArray ba i e--instance ArrayElt Word16 where- type ArrayPtrs Word16 = Ptr Word16- arrayElt = ArrayEltRword16- {-# INLINE unsafeIndexArrayData #-}- unsafeIndexArrayData (AD_Word16 ba) i = unsafeIndexArray ba i- {-# INLINE ptrsOfArrayData #-}- ptrsOfArrayData (AD_Word16 ba) = unsafeUniqueArrayPtr ba- {-# INLINE touchArrayData #-}- touchArrayData (AD_Word16 ba) = touchUniqueArray ba- {-# INLINE newArrayData #-}- newArrayData size = AD_Word16 <$> newArrayData' size- {-# INLINE unsafeReadArrayData #-}- unsafeReadArrayData (AD_Word16 ba) i = unsafeReadArray ba i- {-# INLINE unsafeWriteArrayData #-}- unsafeWriteArrayData (AD_Word16 ba) i e = unsafeWriteArray ba i e--instance ArrayElt Word32 where- type ArrayPtrs Word32 = Ptr Word32- arrayElt = ArrayEltRword32- {-# INLINE unsafeIndexArrayData #-}- unsafeIndexArrayData (AD_Word32 ba) i = unsafeIndexArray ba i- {-# INLINE ptrsOfArrayData #-}- ptrsOfArrayData (AD_Word32 ba) = unsafeUniqueArrayPtr ba- {-# INLINE touchArrayData #-}- touchArrayData (AD_Word32 ba) = touchUniqueArray ba- {-# INLINE newArrayData #-}- newArrayData size = AD_Word32 <$> newArrayData' size- {-# INLINE unsafeReadArrayData #-}- unsafeReadArrayData (AD_Word32 ba) i = unsafeReadArray ba i- {-# INLINE unsafeWriteArrayData #-}- unsafeWriteArrayData (AD_Word32 ba) i e = unsafeWriteArray ba i e--instance ArrayElt Word64 where- type ArrayPtrs Word64 = Ptr Word64- arrayElt = ArrayEltRword64- {-# INLINE unsafeIndexArrayData #-}- unsafeIndexArrayData (AD_Word64 ba) i = unsafeIndexArray ba i- {-# INLINE ptrsOfArrayData #-}- ptrsOfArrayData (AD_Word64 ba) = unsafeUniqueArrayPtr ba- {-# INLINE touchArrayData #-}- touchArrayData (AD_Word64 ba) = touchUniqueArray ba- {-# INLINE newArrayData #-}- newArrayData size = AD_Word64 <$> newArrayData' size- {-# INLINE unsafeReadArrayData #-}- unsafeReadArrayData (AD_Word64 ba) i = unsafeReadArray ba i- {-# INLINE unsafeWriteArrayData #-}- unsafeWriteArrayData (AD_Word64 ba) i e = unsafeWriteArray ba i e--instance ArrayElt CShort where- type ArrayPtrs CShort = Ptr Int16- arrayElt = ArrayEltRcshort- {-# INLINE unsafeIndexArrayData #-}- unsafeIndexArrayData (AD_CShort ba) i = CShort $ unsafeIndexArray ba i- {-# INLINE ptrsOfArrayData #-}- ptrsOfArrayData (AD_CShort ba) = unsafeUniqueArrayPtr ba- {-# INLINE touchArrayData #-}- touchArrayData (AD_CShort ba) = touchUniqueArray ba- {-# INLINE newArrayData #-}- newArrayData size = AD_CShort <$> newArrayData' size- {-# INLINE unsafeReadArrayData #-}- unsafeReadArrayData (AD_CShort ba) i = CShort <$> unsafeReadArray ba i- {-# INLINE unsafeWriteArrayData #-}- unsafeWriteArrayData (AD_CShort ba) i (CShort e)- = unsafeWriteArray ba i e--instance ArrayElt CUShort where- type ArrayPtrs CUShort = Ptr Word16- arrayElt = ArrayEltRcushort- {-# INLINE unsafeIndexArrayData #-}- unsafeIndexArrayData (AD_CUShort ba) i = CUShort $ unsafeIndexArray ba i- {-# INLINE ptrsOfArrayData #-}- ptrsOfArrayData (AD_CUShort ba) = unsafeUniqueArrayPtr ba- {-# INLINE touchArrayData #-}- touchArrayData (AD_CUShort ba) = touchUniqueArray ba- {-# INLINE newArrayData #-}- newArrayData size = AD_CUShort <$> newArrayData' size- {-# INLINE unsafeReadArrayData #-}- unsafeReadArrayData (AD_CUShort ba) i = CUShort <$> unsafeReadArray ba i- {-# INLINE unsafeWriteArrayData #-}- unsafeWriteArrayData (AD_CUShort ba) i (CUShort e)- = unsafeWriteArray ba i e--instance ArrayElt CInt where- type ArrayPtrs CInt = Ptr Int32- arrayElt = ArrayEltRcint- {-# INLINE unsafeIndexArrayData #-}- unsafeIndexArrayData (AD_CInt ba) i = CInt $ unsafeIndexArray ba i- {-# INLINE ptrsOfArrayData #-}- ptrsOfArrayData (AD_CInt ba) = unsafeUniqueArrayPtr ba- {-# INLINE touchArrayData #-}- touchArrayData (AD_CInt ba) = touchUniqueArray ba- {-# INLINE newArrayData #-}- newArrayData size = AD_CInt <$> newArrayData' size- {-# INLINE unsafeReadArrayData #-}- unsafeReadArrayData (AD_CInt ba) i = CInt <$> unsafeReadArray ba i- {-# INLINE unsafeWriteArrayData #-}- unsafeWriteArrayData (AD_CInt ba) i (CInt e)- = unsafeWriteArray ba i e--instance ArrayElt CUInt where- type ArrayPtrs CUInt = Ptr Word32- arrayElt = ArrayEltRcuint- {-# INLINE unsafeIndexArrayData #-}- unsafeIndexArrayData (AD_CUInt ba) i = CUInt $ unsafeIndexArray ba i- {-# INLINE ptrsOfArrayData #-}- ptrsOfArrayData (AD_CUInt ba) = unsafeUniqueArrayPtr ba- {-# INLINE touchArrayData #-}- touchArrayData (AD_CUInt ba) = touchUniqueArray ba- {-# INLINE newArrayData #-}- newArrayData size = AD_CUInt <$> newArrayData' size- {-# INLINE unsafeReadArrayData #-}- unsafeReadArrayData (AD_CUInt ba) i = CUInt <$> unsafeReadArray ba i- {-# INLINE unsafeWriteArrayData #-}- unsafeWriteArrayData (AD_CUInt ba) i (CUInt e)- = unsafeWriteArray ba i e--instance ArrayElt CLong where- type ArrayPtrs CLong = Ptr HTYPE_LONG- arrayElt = ArrayEltRclong- {-# INLINE unsafeIndexArrayData #-}- unsafeIndexArrayData (AD_CLong ba) i = CLong $ unsafeIndexArray ba i- {-# INLINE ptrsOfArrayData #-}- ptrsOfArrayData (AD_CLong ba) = unsafeUniqueArrayPtr ba- {-# INLINE touchArrayData #-}- touchArrayData (AD_CLong ba) = touchUniqueArray ba- {-# INLINE newArrayData #-}- newArrayData size = AD_CLong <$> newArrayData' size- {-# INLINE unsafeReadArrayData #-}- unsafeReadArrayData (AD_CLong ba) i = CLong <$> unsafeReadArray ba i- {-# INLINE unsafeWriteArrayData #-}- unsafeWriteArrayData (AD_CLong ba) i (CLong e)- = unsafeWriteArray ba i e--instance ArrayElt CULong where- type ArrayPtrs CULong = Ptr HTYPE_UNSIGNED_LONG- arrayElt = ArrayEltRculong- {-# INLINE unsafeIndexArrayData #-}- unsafeIndexArrayData (AD_CULong ba) i = CULong $ unsafeIndexArray ba i- {-# INLINE ptrsOfArrayData #-}- ptrsOfArrayData (AD_CULong ba) = unsafeUniqueArrayPtr ba- {-# INLINE touchArrayData #-}- touchArrayData (AD_CULong ba) = touchUniqueArray ba- {-# INLINE newArrayData #-}- newArrayData size = AD_CULong <$> newArrayData' size- {-# INLINE unsafeReadArrayData #-}- unsafeReadArrayData (AD_CULong ba) i = CULong <$> unsafeReadArray ba i- {-# INLINE unsafeWriteArrayData #-}- unsafeWriteArrayData (AD_CULong ba) i (CULong e)- = unsafeWriteArray ba i e--instance ArrayElt CLLong where- type ArrayPtrs CLLong = Ptr Int64- arrayElt = ArrayEltRcllong- {-# INLINE unsafeIndexArrayData #-}- unsafeIndexArrayData (AD_CLLong ba) i = CLLong $ unsafeIndexArray ba i- {-# INLINE ptrsOfArrayData #-}- ptrsOfArrayData (AD_CLLong ba) = unsafeUniqueArrayPtr ba- {-# INLINE touchArrayData #-}- touchArrayData (AD_CLLong ba) = touchUniqueArray ba- {-# INLINE newArrayData #-}- newArrayData size = AD_CLLong <$> newArrayData' size- {-# INLINE unsafeReadArrayData #-}- unsafeReadArrayData (AD_CLLong ba) i = CLLong <$> unsafeReadArray ba i- {-# INLINE unsafeWriteArrayData #-}- unsafeWriteArrayData (AD_CLLong ba) i (CLLong e)- = unsafeWriteArray ba i e--instance ArrayElt CULLong where- type ArrayPtrs CULLong = Ptr Word64- arrayElt = ArrayEltRcullong- {-# INLINE unsafeIndexArrayData #-}- unsafeIndexArrayData (AD_CULLong ba) i = CULLong $ unsafeIndexArray ba i- {-# INLINE ptrsOfArrayData #-}- ptrsOfArrayData (AD_CULLong ba) = unsafeUniqueArrayPtr ba- {-# INLINE touchArrayData #-}- touchArrayData (AD_CULLong ba) = touchUniqueArray ba- {-# INLINE newArrayData #-}- newArrayData size = AD_CULLong <$> newArrayData' size- {-# INLINE unsafeReadArrayData #-}- unsafeReadArrayData (AD_CULLong ba) i = CULLong <$> unsafeReadArray ba i- {-# INLINE unsafeWriteArrayData #-}- unsafeWriteArrayData (AD_CULLong ba) i (CULLong e)- = unsafeWriteArray ba i e--instance ArrayElt Float where- type ArrayPtrs Float = Ptr Float- arrayElt = ArrayEltRfloat- {-# INLINE unsafeIndexArrayData #-}- unsafeIndexArrayData (AD_Float ba) i = unsafeIndexArray ba i- {-# INLINE ptrsOfArrayData #-}- ptrsOfArrayData (AD_Float ba) = unsafeUniqueArrayPtr ba- {-# INLINE touchArrayData #-}- touchArrayData (AD_Float ba) = touchUniqueArray ba- {-# INLINE newArrayData #-}- newArrayData size = AD_Float <$> newArrayData' size- {-# INLINE unsafeReadArrayData #-}- unsafeReadArrayData (AD_Float ba) i = unsafeReadArray ba i- {-# INLINE unsafeWriteArrayData #-}- unsafeWriteArrayData (AD_Float ba) i e = unsafeWriteArray ba i e--instance ArrayElt Double where- type ArrayPtrs Double = Ptr Double- arrayElt = ArrayEltRdouble- {-# INLINE unsafeIndexArrayData #-}- unsafeIndexArrayData (AD_Double ba) i = unsafeIndexArray ba i- {-# INLINE ptrsOfArrayData #-}- ptrsOfArrayData (AD_Double ba) = unsafeUniqueArrayPtr ba- {-# INLINE touchArrayData #-}- touchArrayData (AD_Double ba) = touchUniqueArray ba- {-# INLINE newArrayData #-}- newArrayData size = AD_Double <$> newArrayData' size- {-# INLINE unsafeReadArrayData #-}- unsafeReadArrayData (AD_Double ba) i = unsafeReadArray ba i- {-# INLINE unsafeWriteArrayData #-}- unsafeWriteArrayData (AD_Double ba) i e = unsafeWriteArray ba i e--instance ArrayElt CFloat where- type ArrayPtrs CFloat = Ptr Float- arrayElt = ArrayEltRcfloat- {-# INLINE unsafeIndexArrayData #-}- unsafeIndexArrayData (AD_CFloat ba) i = CFloat $ unsafeIndexArray ba i- {-# INLINE ptrsOfArrayData #-}- ptrsOfArrayData (AD_CFloat ba) = unsafeUniqueArrayPtr ba- {-# INLINE touchArrayData #-}- touchArrayData (AD_CFloat ba) = touchUniqueArray ba- {-# INLINE newArrayData #-}- newArrayData size = AD_CFloat <$> newArrayData' size- {-# INLINE unsafeReadArrayData #-}- unsafeReadArrayData (AD_CFloat ba) i = CFloat <$> unsafeReadArray ba i- {-# INLINE unsafeWriteArrayData #-}- unsafeWriteArrayData (AD_CFloat ba) i (CFloat e)- = unsafeWriteArray ba i e--instance ArrayElt CDouble where- type ArrayPtrs CDouble = Ptr Double- arrayElt = ArrayEltRcdouble- {-# INLINE unsafeIndexArrayData #-}- unsafeIndexArrayData (AD_CDouble ba) i = CDouble $ unsafeIndexArray ba i- {-# INLINE ptrsOfArrayData #-}- ptrsOfArrayData (AD_CDouble ba) = unsafeUniqueArrayPtr ba- {-# INLINE touchArrayData #-}- touchArrayData (AD_CDouble ba) = touchUniqueArray ba- {-# INLINE newArrayData #-}- newArrayData size = AD_CDouble <$> newArrayData' size- {-# INLINE unsafeReadArrayData #-}- unsafeReadArrayData (AD_CDouble ba) i = CDouble <$> unsafeReadArray ba i- {-# INLINE unsafeWriteArrayData #-}- unsafeWriteArrayData (AD_CDouble ba) i (CDouble e)- = unsafeWriteArray ba i e---- Bool arrays are stored as arrays of bytes. While this is memory inefficient,--- it is better suited to parallel backends than a packed bit-vector--- representation.----instance ArrayElt Bool where- type ArrayPtrs Bool = Ptr Word8- arrayElt = ArrayEltRbool- {-# INLINE unsafeIndexArrayData #-}- unsafeIndexArrayData (AD_Bool ba) i = toBool (unsafeIndexArray ba i)- {-# INLINE ptrsOfArrayData #-}- ptrsOfArrayData (AD_Bool ba) = unsafeUniqueArrayPtr ba- {-# INLINE touchArrayData #-}- touchArrayData (AD_Bool ba) = touchUniqueArray ba- {-# INLINE newArrayData #-}- newArrayData size = AD_Bool <$> newArrayData' size- {-# INLINE unsafeReadArrayData #-}- unsafeReadArrayData (AD_Bool ba) i = toBool <$> unsafeReadArray ba i- {-# INLINE unsafeWriteArrayData #-}- unsafeWriteArrayData (AD_Bool ba) i e = unsafeWriteArray ba i (fromBool e)---- Unboxed Char is stored as a wide character, which is 4-bytes----instance ArrayElt Char where- type ArrayPtrs Char = Ptr Char- arrayElt = ArrayEltRchar- {-# INLINE unsafeIndexArrayData #-}- unsafeIndexArrayData (AD_Char ba) i = unsafeIndexArray ba i- {-# INLINE ptrsOfArrayData #-}- ptrsOfArrayData (AD_Char ba) = unsafeUniqueArrayPtr ba- {-# INLINE touchArrayData #-}- touchArrayData (AD_Char ba) = touchUniqueArray ba- {-# INLINE newArrayData #-}- newArrayData size = AD_Char <$> newArrayData' size- {-# INLINE unsafeReadArrayData #-}- unsafeReadArrayData (AD_Char ba) i = unsafeReadArray ba i- {-# INLINE unsafeWriteArrayData #-}- unsafeWriteArrayData (AD_Char ba) i e = unsafeWriteArray ba i e--instance ArrayElt CChar where- type ArrayPtrs CChar = Ptr HTYPE_CCHAR- arrayElt = ArrayEltRcchar- {-# INLINE unsafeIndexArrayData #-}- unsafeIndexArrayData (AD_CChar ba) i = CChar $ unsafeIndexArray ba i- {-# INLINE ptrsOfArrayData #-}- ptrsOfArrayData (AD_CChar ba) = unsafeUniqueArrayPtr ba- {-# INLINE touchArrayData #-}- touchArrayData (AD_CChar ba) = touchUniqueArray ba- {-# INLINE newArrayData #-}- newArrayData size = AD_CChar <$> newArrayData' size- {-# INLINE unsafeReadArrayData #-}- unsafeReadArrayData (AD_CChar ba) i = CChar <$> unsafeReadArray ba i- {-# INLINE unsafeWriteArrayData #-}- unsafeWriteArrayData (AD_CChar ba) i (CChar e)- = unsafeWriteArray ba i e--instance ArrayElt CSChar where- type ArrayPtrs CSChar = Ptr Int8- arrayElt = ArrayEltRcschar- {-# INLINE unsafeIndexArrayData #-}- unsafeIndexArrayData (AD_CSChar ba) i = CSChar $ unsafeIndexArray ba i- {-# INLINE ptrsOfArrayData #-}- ptrsOfArrayData (AD_CSChar ba) = unsafeUniqueArrayPtr ba- {-# INLINE touchArrayData #-}- touchArrayData (AD_CSChar ba) = touchUniqueArray ba- {-# INLINE newArrayData #-}- newArrayData size = AD_CSChar <$> newArrayData' size- {-# INLINE unsafeReadArrayData #-}- unsafeReadArrayData (AD_CSChar ba) i = CSChar <$> unsafeReadArray ba i- {-# INLINE unsafeWriteArrayData #-}- unsafeWriteArrayData (AD_CSChar ba) i (CSChar e)- = unsafeWriteArray ba i e--instance ArrayElt CUChar where- type ArrayPtrs CUChar = Ptr Word8- arrayElt = ArrayEltRcuchar- {-# INLINE unsafeIndexArrayData #-}- unsafeIndexArrayData (AD_CUChar ba) i = CUChar $ unsafeIndexArray ba i- {-# INLINE ptrsOfArrayData #-}- ptrsOfArrayData (AD_CUChar ba) = unsafeUniqueArrayPtr ba- {-# INLINE touchArrayData #-}- touchArrayData (AD_CUChar ba) = touchUniqueArray ba- {-# INLINE newArrayData #-}- newArrayData size = AD_CUChar <$> newArrayData' size- {-# INLINE unsafeReadArrayData #-}- unsafeReadArrayData (AD_CUChar ba) i = CUChar <$> unsafeReadArray ba i- {-# INLINE unsafeWriteArrayData #-}- unsafeWriteArrayData (AD_CUChar ba) i (CUChar e)- = unsafeWriteArray ba i e--instance (ArrayElt a, ArrayElt b) => ArrayElt (a, b) where- type ArrayPtrs (a, b) = (ArrayPtrs a, ArrayPtrs b)- arrayElt = ArrayEltRpair arrayElt arrayElt- {-# INLINE unsafeIndexArrayData #-}- unsafeIndexArrayData (AD_Pair a b) i = (unsafeIndexArrayData a i, unsafeIndexArrayData b i)- {-# INLINE ptrsOfArrayData #-}- ptrsOfArrayData (AD_Pair a b) = (ptrsOfArrayData a, ptrsOfArrayData b)- {-# INLINE touchArrayData #-}- touchArrayData (AD_Pair a b) = touchArrayData a >> touchArrayData b- {-# INLINE unsafeWriteArrayData #-}- unsafeWriteArrayData (AD_Pair a b) i (x, y) = unsafeWriteArrayData a i x >> unsafeWriteArrayData b i y- {-# INLINE newArrayData #-}- newArrayData size = AD_Pair <$> newArrayData size <*> newArrayData size- {-# INLINE unsafeFreezeArrayData #-}- unsafeFreezeArrayData (AD_Pair a b) = AD_Pair <$> unsafeFreezeArrayData a <*> unsafeFreezeArrayData b- {-# INLINE unsafeReadArrayData #-}- unsafeReadArrayData (AD_Pair a b) i = (,) <$> unsafeReadArrayData a i <*> unsafeReadArrayData b i- {-# INLINE ptrsOfMutableArrayData #-}- ptrsOfMutableArrayData (AD_Pair a b) = (,) <$> ptrsOfMutableArrayData a <*> ptrsOfMutableArrayData b----- Array tuple operations--- ------------------------{-# INLINE fstArrayData #-}-fstArrayData :: ArrayData (a, b) -> ArrayData a-fstArrayData (AD_Pair x _) = x--{-# INLINE sndArrayData #-}-sndArrayData :: ArrayData (a, b) -> ArrayData b-sndArrayData (AD_Pair _ y) = y--{-# INLINE pairArrayData #-}-pairArrayData :: ArrayData a -> ArrayData b -> ArrayData (a, b)-pairArrayData = AD_Pair----- Auxiliary functions--- ---------------------{-# INLINE toBool #-}-toBool :: Word8 -> Bool-toBool 0 = False-toBool _ = True--{-# INLINE fromBool #-}-fromBool :: Bool -> Word8-fromBool True = 1-fromBool False = 0---- | Safe combination of creating and fast freezing of array data.----{-# INLINE runArrayData #-}-runArrayData- :: IO (MutableArrayData e, e)- -> (ArrayData e, e)-runArrayData st = unsafePerformIO $ do- (mad, r) <- st- return (mad, r)---- Returns the element of an immutable array at the specified index. This does--- no bounds checking.----{-# INLINE unsafeIndexArray #-}-unsafeIndexArray :: Storable e => UniqueArray e -> Int -> e-unsafeIndexArray ua i = unsafePerformIO $! unsafeReadArray ua i---- Read an element from a mutable array at the given index. This does no bounds--- checking.----{-# INLINE unsafeReadArray #-}-unsafeReadArray :: Storable e => UniqueArray e -> Int -> IO e-unsafeReadArray ua i =- withUniqueArrayPtr ua $ \ptr -> peekElemOff ptr i---- Write an element into a mutable array at the given index. This does no bounds--- checking.----{-# INLINE unsafeWriteArray #-}-unsafeWriteArray :: Storable e => UniqueArray e -> Int -> e -> IO ()-unsafeWriteArray ua i e =- withUniqueArrayPtr ua $ \ptr -> pokeElemOff ptr i e---- Allocate a new array with enough storage to hold the given number of--- elements.------ The array is uninitialised and, in particular, allocated lazily. The latter--- is important because it means that for backends that have discrete memory--- spaces (e.g. GPUs), we will not increase host memory pressure simply to track--- intermediate arrays that contain meaningful data only on the device.----{-# INLINE newArrayData' #-}-newArrayData' :: forall e. Storable e => Int -> IO (UniqueArray e)-newArrayData' size- = $internalCheck "newArrayData" "size must be >= 0" (size >= 0)- $ newUniqueArray <=< unsafeInterleaveIO $ do- let bytes = size * sizeOf (undefined :: e)- new <- readIORef __mallocForeignPtrBytes- ptr <- new bytes- traceIO dump_gc $ printf "gc: allocated new host array (size=%d, ptr=%s)" bytes (show ptr)- didAllocateBytesLocal (fromIntegral bytes)- return (castForeignPtr ptr)---- | Register the given function as the callback to use to allocate new array--- data on the host containing the specified number of bytes. The returned array--- must be pinned (with respect to Haskell's GC), so that it can be passed to--- foreign code.----registerForeignPtrAllocator- :: (Int -> IO (ForeignPtr Word8))- -> IO ()-registerForeignPtrAllocator new = do- traceIO dump_gc "registering new array allocator"- atomicWriteIORef __mallocForeignPtrBytes new--{-# NOINLINE __mallocForeignPtrBytes #-}-__mallocForeignPtrBytes :: IORef (Int -> IO (ForeignPtr Word8))-__mallocForeignPtrBytes = unsafePerformIO $! newIORef mallocPlainForeignPtrBytesAligned---- | Allocate the given number of bytes with 16-byte alignment. This is--- essential for SIMD instructions.------ Additionally, we return a plain ForeignPtr, which unlike a regular ForeignPtr--- created with 'mallocForeignPtr' carries no finalisers. It is an error to try--- to add a finaliser to the plain ForeignPtr. For our purposes this is fine,--- since in Accelerate finalisers are handled using Lifetime----{-# INLINE mallocPlainForeignPtrBytesAligned #-}-mallocPlainForeignPtrBytesAligned :: Int -> IO (ForeignPtr a)-mallocPlainForeignPtrBytesAligned (I# size) = IO $ \s ->- case newAlignedPinnedByteArray# size 16# s of- (# s', mbarr# #) -> (# s', ForeignPtr (byteArrayContents# (unsafeCoerce# mbarr#)) (PlainPtr mbarr#) #)-
− Data/Array/Accelerate/Array/Lifted.hs
@@ -1,283 +0,0 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE PatternGuards #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE UndecidableInstances #-}--- |--- Module : Data.Array.Accelerate.Array.Lifted--- Copyright : [2012..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell, Robert Clifton-Everest--- License : BSD3------ Maintainer : Robert Clifton-Everest <robertce@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)------ Lifted array representation. Vector of arrays represented as segmented--- vectors.-----module Data.Array.Accelerate.Array.Lifted (-- Vector'(..), LiftedArray,-- LiftedTupleRepr,-- IsConstrained(..),-- isArraysFlat,-- elements', shapes', empty', length', drop', vec2Vec', fromList', toList'--) where--import Prelude hiding ( concat )-import Data.Typeable---- friends-import Data.Array.Accelerate.Product-import Data.Array.Accelerate.Array.Sugar-import qualified Data.Array.Accelerate.Array.Representation as Repr----- Lifted arrays--- ---------------------- We specify a special new type of surface tuple to represent the lifted version of members of the--- `Arrays' class. We do this in order to convince the type checker that the lifted arrays or tuples--- of arrays, are still members of the 'Arrays' class.--newtype Vector' a = Vector' (LiftedRepr (ArrRepr a) a)- deriving Typeable--type family LiftedRepr r a where- LiftedRepr () () = ((),Scalar Int)- LiftedRepr (Array sh e) (Array sh e) = (((),Segments sh), Vector e)- LiftedRepr (l,r) a = LiftedTupleRepr (TupleRepr a)--type family LiftedTupleRepr t :: *-type instance LiftedTupleRepr () = ()-type instance LiftedTupleRepr (b, a) = (LiftedTupleRepr b, Vector' a)--type LiftedArray sh e = Vector' (Array sh e)--instance Arrays t => IsProduct Arrays (Vector' t) where- type ProdRepr (Vector' t) = LiftedRepr (ArrRepr t) t- fromProd _ (Vector' t) = t- toProd _ = Vector'- prod _ _ = case flavour (undefined :: t) of- ArraysFunit -> ProdRsnoc ProdRunit- ArraysFarray -> ProdRsnoc (ProdRsnoc ProdRunit)- ArraysFtuple -> tup $ prod (Proxy :: Proxy Arrays) (undefined :: t)- where- tup :: forall a. ProdR Arrays a -> ProdR Arrays (LiftedTupleRepr a)- tup ProdRunit = ProdRunit- tup (ProdRsnoc t) = swiz- where- swiz :: forall l r. (a ~ (l,r), Arrays r) => ProdR Arrays (LiftedTupleRepr a)- swiz | IsC <- isArraysFlat (undefined :: r)- = ProdRsnoc (tup t)---type instance ArrRepr (Vector' a) = ArrRepr (TupleRepr (Vector' a))---instance (Arrays t, Typeable (ArrRepr (Vector' t))) => Arrays (Vector' t) where- arrays _ = arrs (prod (Proxy :: Proxy Arrays) (undefined :: Vector' t))- where- arrs :: forall a. ProdR Arrays a -> ArraysR (ArrRepr a)- arrs ProdRunit = ArraysRunit- arrs (ProdRsnoc t) = ArraysRpair (ArraysRpair ArraysRunit (arrs t)) (arrays t')- where t' :: (a ~ (l,r)) => r- t' = undefined- flavour _ = case flavour (undefined :: t) of- ArraysFunit -> ArraysFtuple- ArraysFarray -> ArraysFtuple- ArraysFtuple | ProdRsnoc _ <- prod (Proxy :: Proxy Arrays) (undefined::t)- -> ArraysFtuple- | otherwise -> error "Absurd"- --- fromArr (Vector' vt) = fa (prod (Proxy :: Proxy Arrays) (undefined :: Vector' t)) vt- where- fa :: forall a. ProdR Arrays a -> a -> ArrRepr a- fa ProdRunit () = ()- fa (ProdRsnoc t) (l,a) = (((), fa t l), fromArr a)- toArr = Vector' . ta (prod (Proxy :: Proxy Arrays) (undefined :: Vector' t))- where- ta :: forall a. ProdR Arrays a -> ArrRepr a -> a- ta ProdRunit () = ()- ta (ProdRsnoc t) (((),l),a) = (ta t l, toArr a)--data IsConstrained c where- IsC :: c => IsConstrained c--type IsTypeableArrRepr t = IsConstrained (Typeable (ArrRepr t))--type IsArraysFlat t = IsConstrained (Arrays (Vector' t))--isTypeableArrRepr :: forall t. Arrays t => {- dummy -} t -> IsTypeableArrRepr (Vector' t)-isTypeableArrRepr _ =- case flavour (undefined :: t) of- ArraysFunit -> IsC- ArraysFarray -> IsC- ArraysFtuple | IsC <- isT (prod (Proxy :: Proxy Arrays) (undefined :: Vector' t))- -> IsC- where- isT :: ProdR Arrays t' -> IsTypeableArrRepr t'- isT ProdRunit = IsC- isT (ProdRsnoc t) | IsC <- isT t = IsC--isArraysFlat :: forall t. Arrays t => {- dummy -} t -> IsArraysFlat t-isArraysFlat t = case flavour t of- ArraysFunit -> IsC- ArraysFtuple | IsC <- isTypeableArrRepr t- -> IsC- ArraysFarray -> IsC----- Useful helper-functions (not exported)--- ----------------------------------------scalar :: Elt a => a -> Scalar a-scalar n = fromList Z [n]--emptyVec :: Elt a => Vector a-emptyVec = fromList (Z :. (0 :: Int)) []--flatten :: Array sh e -> Vector e-flatten (Array sh e) = Array ((), Repr.size sh) e----- Useful helper-functions for Vector'--- -------------------------------------- Get all the elements. O(1).----elements' :: Vector' (Array sh e) -> Vector e-elements' (Vector' (_, elts)) = elts---- Get all the shapes. O(1).----shapes' :: Vector' (Array sh a) -> Vector sh-shapes' (Vector' (((), shapes), _)) = shapes---- The empty Vector'. O(1).-empty' :: forall a. Arrays a => Vector' a-empty' = Vector' $- case flavour (undefined :: a) of- ArraysFunit -> ((), scalar 0)- ArraysFarray -> (((), emptyVec), emptyVec)- ArraysFtuple -> tup (prod (Proxy :: Proxy Arrays) (undefined :: a))- where- tup :: forall t. ProdR Arrays t -> LiftedTupleRepr t- tup ProdRunit = ()- tup (ProdRsnoc t) = (tup t, empty')---- Number of arrays in Vector'. O(1).----length' :: forall a. Arrays a => Vector' a -> Int-length' (Vector' x) =- case flavour (undefined :: a) of- ArraysFunit | ((), n) <- x- -> n ! Z- ArraysFarray | (((), Array ((), n) _), _) <- x- -> n- ArraysFtuple -> tup (prod (Proxy :: Proxy Arrays) (undefined :: a)) x- where- tup :: forall t. ProdR Arrays t -> LiftedTupleRepr t -> Int- tup ProdRunit () = error "unreachable"- tup (ProdRsnoc _) (_, b) = length' b---- Drop a number of arrays from a Vector'.----drop' :: forall a. Arrays a- -- Implementation specific drop for basic vectors:- => (forall e. Elt e => Int -> Vector e -> Vector e)- -- Implementation specific segments-to-offsets:- -> (forall sh. Shape sh => Segments sh -> Vector Int)- -> Int -> Vector' a -> Vector' a-drop' dropVec s2o k (Vector' x) = Vector' $- case flavour (undefined :: a) of- ArraysFunit | ((), n ) <- x- -> ((), scalar (n ! Z - k `max` 0))- ArraysFarray | (((), segs), vals) <- x- , Array ((), n) _ <- segs- , k < n- -> let offsets = s2o segs- k' = offsets ! (Z :. k)- in (((), dropVec k segs), dropVec k' vals)- ArraysFarray -> (((), emptyVec), emptyVec)- ArraysFtuple -> tup (prod (Proxy :: Proxy Arrays) (undefined :: a)) x- where- tup :: forall t. ProdR Arrays t -> LiftedTupleRepr t -> LiftedTupleRepr t- tup ProdRunit () = ()- tup (ProdRsnoc t) (a, b) = (tup t a, drop' dropVec s2o k b)---- Convert a vector to a Vector' of scalars.----vec2Vec' :: Elt e => Vector e -> Vector' (Scalar e)-vec2Vec' v = Vector' (((), undefined), v) -- TODO undefined Vector of Z's?--toList' :: forall a. Arrays a- -- Implementation-specific fetchAll:- => (forall sh e. (Shape sh, Elt e) => Segments sh -> Vector e -> [Array sh e])- -> Vector' a -> [a]-toList' fetchAll (Vector' x) =- case flavour (undefined :: a) of- ArraysFunit | ((), n) <- x -> replicate (n ! Z) ()- ArraysFarray | (((), lens), vals) <- x- -> fetchAll lens vals- ArraysFtuple -> map (toProd (Proxy :: Proxy Arrays)) (tup (prod (Proxy :: Proxy Arrays) (undefined :: a)) x)- where- tup :: forall t. ProdR Arrays t -> LiftedTupleRepr t -> [t]- tup ProdRunit () = repeat ()- tup (ProdRsnoc t) (a, b) = tup t a `zip` toList' fetchAll b--fromList' :: forall a. Arrays a- -- Implementation specific concat- => (forall e. Elt e => [Vector e] -> Vector e)- -> [a] -> Vector' a-fromList' concat xs = Vector' $- case flavour (undefined :: a) of- ArraysFunit -> ((), scalar (length xs))- ArraysFarray ->- let segs = map shape xs- vals = concat (map flatten xs)- in (((), fromList (Z :. length segs) segs), vals)- ArraysFtuple -> tup (prod (Proxy :: Proxy Arrays) (undefined :: a)) (map (fromProd (Proxy :: Proxy Arrays)) xs)- where- tup :: forall t. ProdR Arrays t -> [t] -> LiftedTupleRepr t- tup ProdRunit _ = ()- tup (ProdRsnoc t) a = (tup t (Prelude.map fst a), fromList' concat (map snd a))--{--map' :: (Arrays a, Arrays b)- => (forall e. Elt e => [Vector e] -> Vector e)- -> (forall sh e. (Shape sh, Elt e) => Segments sh -> Vector e -> [Array sh e])- -> (a -> b) -> Vector' a -> Vector' b-map' concat fetchAll f x = fromList' concat $ map f (toList' fetchAll x)--}--{--helper :: forall a r. Arrays a- => (Scalar Int -> r ())- -> (forall sh e. (Shape sh, Elt e) => Segments sh -> Vector e -> r (Array sh e))- -> r ()- -> (forall t s. r t -> r s -> r (t, s))- -> (forall t. r (ProdRepr t) -> r t)- -> Vector' a -> r a-helper units arr unit pair fix (Vector' x) =- case flavour (undefined :: a) of- ArraysFunit | ((), n) <- x -> units n- ArraysFarray | (((), lens), vals) <- x- -> arr lens vals- ArraysFtuple -> fix $ tup (prod (Proxy :: Proxy Arrays) (undefined :: a)) x- where- tup :: forall t. ProdR Arrays t -> LiftedTupleRepr t -> r t- tup ProdRunit () = unit- tup (ProdRsnoc t) (x, y) = tup t x `pair` helper units arr unit pair fix y--}-
− Data/Array/Accelerate/Array/Remote.hs
@@ -1,26 +0,0 @@-{-# OPTIONS_HADDOCK hide #-}--- |--- Module : Data.Array.Accelerate.Array.Remote--- Copyright : [2015..2017] Manuel M T Chakravarty, Gabriele Keller, Robert Clifton-Everest--- [2016..2017] Trevor L. McDonell--- License : BSD3------ Maintainer : Robert Clifton-Everest <robertce@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)------ Umbrella module for the remote memory management facilities. To implement an--- LRU cache for your backend, provide an instance of the 'RemoteMemory' class,--- and, if required, specialise or overload the LRU functions to your particular--- memory table types.-----module Data.Array.Accelerate.Array.Remote (-- module Remote--) where--import Data.Array.Accelerate.Array.Remote.Class as Remote-import Data.Array.Accelerate.Array.Remote.LRU as Remote-
− Data/Array/Accelerate/Array/Remote/Class.hs
@@ -1,81 +0,0 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE TypeFamilies #-}-{-# OPTIONS_HADDOCK hide #-}--- |--- Module : Data.Array.Accelerate.Array.Remote.Class--- Copyright : [2015..2017] Manuel M T Chakravarty, Gabriele Keller, Robert Clifton-Everest--- [2016..2017] Trevor L. McDonell--- License : BSD3------ Maintainer : Robert Clifton-Everest <robertce@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)------ This module define a class of operations over pointers in a remote memory--- space. Backends provide an instance of this class, and then can use (or--- extend upon) one of the following modules in order to manage the remote--- memory:------ * 'Data.Array.Accelerate.Array.Remote.Table': basic, unmanaged memory tables,--- mapping accelerate arrays on the host to the corresponding array in the--- remote memory space.------ * 'Data.Array.Accelerate.Array.Remote.LRU': managed memory tables which--- additionally evict old entries from the device if the remote memory is--- exhausted.-----module Data.Array.Accelerate.Array.Remote.Class (-- RemoteMemory(..), PrimElt--) where--import Data.Array.Accelerate.Array.Data--import Control.Applicative-import Control.Monad.Catch-import Data.Int-import Data.Word-import Data.Typeable-import Foreign.Ptr-import Foreign.Storable-import Prelude----- | Matches array element types to primitive types.----type PrimElt e a = (ArrayElt e, Storable a, ArrayPtrs e ~ Ptr a, Typeable e, Typeable a)---- | Accelerate backends can provide an instance of this class in order to take--- advantage of the automated memory managers we provide as part of the base--- package.----class (Applicative m, Monad m, MonadCatch m, MonadMask m) => RemoteMemory m where-- -- | Pointers into this particular remote memory.- type RemotePtr m :: * -> *-- -- | Attempt to allocate the given number of bytes in the remote memory space.- -- Returns Nothing on failure.- mallocRemote :: Int -> m (Maybe (RemotePtr m Word8))-- -- | Copy the given number of elements from the host array into remote memory.- pokeRemote :: PrimElt e a => Int -> RemotePtr m a -> ArrayData e -> m ()-- -- | Copy the given number of elements from remote memory to the host array.- peekRemote :: PrimElt e a => Int -> RemotePtr m a -> MutableArrayData e -> m ()-- -- | Cast a remote pointer.- castRemotePtr :: proxy m -> RemotePtr m a -> RemotePtr m b-- -- | Returns the total remote memory available in bytes.- totalRemoteMem :: m Int64-- -- | Returns, in bytes, the available remote memory.- availableRemoteMem :: m Int64-- -- | The chunk allocation size (bytes).- remoteAllocationSize :: m Int- remoteAllocationSize = return 1024-
− Data/Array/Accelerate/Array/Remote/LRU.hs
@@ -1,405 +0,0 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE DoAndIfThenElse #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE PatternGuards #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell #-}-{-# OPTIONS_HADDOCK hide #-}--- |--- Module : Data.Array.Accelerate.Array.Remote.Cache--- Copyright : [2015..2017] Manuel M T Chakravarty, Gabriele Keller, Robert Clifton-Everest--- [2016..2017] Trevor L. McDonell--- License : BSD3------ Maintainer : Robert Clifton-Everest <robertce@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)------ This module extends the memory tables provided by--- 'Data.Array.Accelerate.Array.Remote.Table' with an LRU caching policy that--- evicts old arrays from the remote memory space once it runs out of memory.--- Consequently, use of this module requires the backend client to keep track of--- which remote arrays are currently being used, so that they will not be--- evicted. See: 'withRemote' for more details on this requirement.----module Data.Array.Accelerate.Array.Remote.LRU (-- -- Tables for host/device memory associations- MemoryTable, new, withRemote, malloc, free, insertUnmanaged, reclaim,-- -- Asynchronous tasks- Task(..)--) where--import Control.Concurrent.MVar ( MVar, newMVar, takeMVar, putMVar, mkWeakMVar )-import Control.Monad ( filterM )-import Control.Monad.Catch-import Control.Monad.IO.Class ( MonadIO, liftIO )-import Data.Functor-import Data.Int ( Int64 )-import Data.Maybe ( isNothing )-import Data.Proxy-import Foreign.Storable ( sizeOf )-import System.CPUTime-import System.Mem.Weak ( Weak, deRefWeak, finalize )-import Prelude hiding ( lookup )-import qualified Data.HashTable.IO as HT--import Data.Array.Accelerate.Array.Data ( ArrayData, touchArrayData )-import Data.Array.Accelerate.Array.Remote.Class-import Data.Array.Accelerate.Array.Remote.Table ( StableArray, makeWeakArrayData )-import Data.Array.Accelerate.Error ( internalError )-import qualified Data.Array.Accelerate.Array.Remote.Table as Basic-import qualified Data.Array.Accelerate.Debug as D----- We build cached memory tables on top of a basic memory table.------ A key invariant is that the arrays in the MemoryTable are a subset of the--- arrays in the UseTable. The UseTable reflects all arrays that have ever been--- in the cache.----data MemoryTable p task = MemoryTable {-# UNPACK #-} !(Basic.MemoryTable p)- {-# UNPACK #-} !(UseTable task)- {-# UNPACK #-} !(Weak (UseTable task))--type UT task = HT.BasicHashTable StableArray (Used task)-type UseTable task = MVar (UT task)--data Status = Clean -- Array in remote memory matches array in host memory.- | Dirty -- Array in remote memory has been modified.- | Unmanaged -- Array in remote memory was injected by FFI, so we- -- cannot remove it under any circumstance.- | Evicted -- Array has been evicted from remote memory- deriving Eq--type Timestamp = Integer--data Used task where- Used :: PrimElt e a- => !Timestamp- -> !Status- -> {-# UNPACK #-} !Int -- Use count- -> ![task] -- Asynchronous tasks using the array- -> {-# UNPACK #-} !Int -- Array size- -> {-# UNPACK #-} !(Weak (ArrayData e))- -> Used task---- |A Task represents a process executing asynchronously that can be polled for--- its status. This is necessary for backends that work asynchronously (i.e.--- the CUDA backend). If a backend is synchronous, the () instance can be used.----class Task task where- -- |Returns true when the task has finished.- completed :: task -> IO Bool--instance Task () where- completed () = return True---- |Create a new memory cache from host to remote arrays.------ The function supplied should be the `free` for the remote pointers being--- stored. This function will be called by the GC, which typically runs on a--- different thread. Unlike the `free` in `RemoteMemory`, this function cannot--- depend on any state.----new :: (forall a. ptr a -> IO ()) -> IO (MemoryTable ptr task)-new release = do- mt <- Basic.new release- utbl <- HT.new- ref <- newMVar utbl- weak_utbl <- mkWeakMVar ref (cache_finalizer utbl)- return $! MemoryTable mt ref weak_utbl---- |Perform some action that requires the remote pointer corresponding to--- the given array. Returns `Nothing` if the array have NEVER been in the--- cache. If the array was previously in the cache, but was evicted due to its--- age, then the array will be copied back from host memory.------ The continuation passed as the third argument needs to obey some precise--- properties. As with all bracketed functions, the supplied remote pointer must--- not leak out of the function, as it is only guaranteed to be valid within it.--- If it is required that it does leak (e.g. the backend is uses concurrency to--- interleave execution of different parts of the program), then `completed` on--- the returned task should not return true until it is guaranteed there are no--- more accesses of the remote pointer.----withRemote- :: forall task m a b c. (PrimElt a b, Task task, RemoteMemory m, MonadIO m, Functor m)- => MemoryTable (RemotePtr m) task- -> ArrayData a- -> (RemotePtr m b -> m (task, c))- -> m (Maybe c)-withRemote (MemoryTable !mt !ref _) !arr run = do- key <- Basic.makeStableArray arr- mp <- withMVar' ref $ \utbl -> do- mu <- liftIO $ HT.lookup utbl key- case mu of- Nothing -> do message ("withRemote/array has never been malloc'd: " ++ show key)- return Nothing- Just u -> do- mp <- liftIO $ do HT.insert utbl key (incCount u)- Basic.lookup mt arr- case mp of- Nothing | isEvicted u -> Just <$> copy utbl (incCount u)- Just p -> return (Just p)- _ -> do message ("lost array " ++ show key)- $internalError "withRemote" "non-evicted array has been lost"- --- case mp of- Just p -> Just <$> run' p- Nothing -> return Nothing -- The array was never in the table.- where- updateTask :: Maybe (Used task) -> task -> IO (Used task)- updateTask mu task = do- ts <- getCPUTime- case mu of- Nothing -> $internalError "withRemote" "Invariant violated"- Just (Used _ status count tasks n weak_arr) -> do- tasks' <- cleanUses tasks- return (Used ts status (count - 1) (task : tasks') n weak_arr)-- copy :: UT task -> Used task -> m (RemotePtr m b)- copy utbl (Used ts _ count tasks n weak_arr) = do- message "withRemote/reuploading-evicted-array"- p <- mallocWithUsage mt utbl arr (Used ts Clean count tasks n weak_arr)- pokeRemote n p arr- return p-- run' :: RemotePtr m b -> m c- run' p = do- key <- Basic.makeStableArray arr- message ("withRemote/using: " ++ show key)- (task, c) <- run p- withMVar' ref $ \utbl -> liftIO $ do- mu <- HT.lookup utbl key- u <- updateTask mu task- HT.insert utbl key u- liftIO $ touchArrayData arr- return c----- | Allocate a new device array to be associated with the given host-side array.--- This has similar behaviour to malloc in Data.Array.Accelerate.Array.Memory.Table--- but also will copy remote arrays back to main memory in order to make space.------ The third argument indicates that the array should be considered frozen. That--- is to say that the array contents will never change. In the event that the--- array has to be evicted from the remote memory, the copy already residing in--- host memory should be considered valid.------ If this function is called on an array that is already contained within the--- cache, this is a no-op.------ On return, 'True' indicates that we allocated some remote memory, and 'False'--- indicates that we did not need to.----malloc :: forall a e m task. (PrimElt e a, RemoteMemory m, MonadIO m, Task task)- => MemoryTable (RemotePtr m) task- -> ArrayData e- -> Bool -- ^ True if host array is frozen.- -> Int- -> m Bool -- ^ Was the array allocated successfully?-malloc (MemoryTable mt ref weak_utbl) !ad !frozen !n = do- ts <- liftIO $ getCPUTime- key <- Basic.makeStableArray ad- --- let status = if frozen- then Clean- else Dirty- --- withMVar' ref $ \utbl -> do- mu <- liftIO $ HT.lookup utbl key- if isNothing mu- then do- weak_arr <- liftIO $ makeWeakArrayData ad ad (Just $ finalizer key weak_utbl)- _ <- mallocWithUsage mt utbl ad (Used ts status 0 [] n weak_arr)- return True- else- return False--mallocWithUsage- :: forall a e m task. (PrimElt e a, RemoteMemory m, MonadIO m, Task task)- => Basic.MemoryTable (RemotePtr m)- -> UT task- -> ArrayData e- -> Used task- -> m (RemotePtr m a)-mallocWithUsage !mt utbl !ad !usage@(Used _ _ _ _ n _) = malloc'- where- malloc' = do- mp <- Basic.malloc mt ad n :: m (Maybe (RemotePtr m a))- case mp of- Nothing -> do- success <- evictLRU utbl mt- if success then malloc'- else $internalError "malloc" "Remote memory exhausted"- Just p -> liftIO $ do- key <- Basic.makeStableArray ad- HT.insert utbl key usage- return p--evictLRU :: forall m task. (RemoteMemory m, MonadIO m, Task task)- => UT task- -> Basic.MemoryTable (RemotePtr m)- -> m Bool-evictLRU utbl mt = trace "evictLRU/evicting-eldest-array" $ do- mused <- liftIO $ HT.foldM eldest Nothing utbl- case mused of- Just (sa, Used ts status count tasks n weak_arr) -> do- mad <- liftIO $ deRefWeak weak_arr- case mad of- Nothing -> liftIO $ do- -- This can only happen if our eviction process was interrupted by- -- garbage collection. In which case, even though we didn't actually- -- evict anything, we should return true, as we know some remote- -- memory is now free.- --- -- Small caveat: Due to finalisers being delayed, it's a good idea- -- to free the array here.- Basic.freeStable (Proxy :: Proxy m) mt sa- delete utbl sa- message "evictLRU/Accelerate GC interrupted by GHC GC"- Just arr -> do- message ("evictLRU/evicting " ++ show sa)- copyIfNecessary status n arr- liftIO $ D.didEvictBytes (remoteBytes n weak_arr)- liftIO $ Basic.freeStable (Proxy :: Proxy m) mt sa- liftIO $ HT.insert utbl sa (Used ts Evicted count tasks n weak_arr)- return True- _ -> trace "evictLRU/All arrays in use, unable to evict" $ return False- where- -- Find the eldest, not currently in use, array.- eldest :: (Maybe (StableArray, Used task)) -> (StableArray, Used task) -> IO (Maybe (StableArray, Used task))- eldest prev (sa, used@(Used ts status count tasks n weak_arr)) | count == 0- , evictable status = do- tasks' <- cleanUses tasks- HT.insert utbl sa (Used ts status count tasks' n weak_arr)- case tasks' of- [] | Just (_, Used ts' _ _ _ _ _) <- prev- , ts < ts' -> return (Just (sa, used))- | Nothing <- prev -> return (Just (sa, used))- _ -> return prev- eldest prev _ = return prev-- remoteBytes :: forall e a. PrimElt e a => Int -> Weak (ArrayData e) -> Int64- remoteBytes n _ = fromIntegral n * fromIntegral (sizeOf (undefined::a))-- evictable :: Status -> Bool- evictable Clean = True- evictable Dirty = True- evictable Unmanaged = False- evictable Evicted = False-- copyIfNecessary :: PrimElt e a => Status -> Int -> ArrayData e -> m ()- copyIfNecessary Clean _ _ = return ()- copyIfNecessary Unmanaged _ _ = return ()- copyIfNecessary Evicted _ _ = $internalError "evictLRU" "Attempting to evict already evicted array"- copyIfNecessary Dirty n ad = do- mp <- liftIO $ Basic.lookup mt ad- case mp of- Nothing -> return () -- RCE: I think this branch is actually impossible.- Just p -> peekRemote n p ad---- | Deallocate the device array associated with the given host-side array.--- Typically this should only be called in very specific circumstances. This--- operation is not thread-safe.----free :: (RemoteMemory m, PrimElt a b)- => proxy m- -> MemoryTable (RemotePtr m) task- -> ArrayData a- -> IO ()-free proxy (MemoryTable !mt !ref _) !arr = withMVar' ref $ \utbl -> do- key <- Basic.makeStableArray arr- delete utbl key- Basic.freeStable proxy mt key---- |Record an association between a host-side array and a remote memory area--- that was not allocated by accelerate. The remote memory will NOT be re-used--- once the host-side array is garbage collected.------ This typically only has use for backends that provide an FFI.----insertUnmanaged- :: (PrimElt e a, MonadIO m)- => MemoryTable p task- -> ArrayData e- -> p a- -> m ()-insertUnmanaged (MemoryTable mt ref weak_utbl) !arr !ptr = liftIO . withMVar' ref $ \utbl -> do- key <- Basic.makeStableArray arr- Basic.insertUnmanaged mt arr ptr- ts <- getCPUTime- weak_arr <- makeWeakArrayData arr arr (Just $ finalizer key weak_utbl)- HT.insert utbl key (Used ts Unmanaged 0 [] 0 weak_arr)----- Removing entries--- ------------------finalizer :: StableArray -> Weak (UseTable task) -> IO ()-finalizer !key !weak_utbl = do- mref <- deRefWeak weak_utbl- case mref of- Nothing -> message "finalize cache/dead table"- Just ref -> trace ("finalize cache: " ++ show key) $ withMVar' ref (`delete` key)--delete :: UT task -> StableArray -> IO ()-delete utbl key = do- mu <- HT.lookup utbl key- case mu of- Nothing -> return ()- Just _ -> HT.delete utbl key---- |Initiate garbage collection and `free` any remote arrays that no longer--- have matching host-side equivalents.----reclaim- :: forall m task. (RemoteMemory m, MonadIO m)- => MemoryTable (RemotePtr m) task- -> m ()-reclaim (MemoryTable !mt _ _) = Basic.reclaim mt--cache_finalizer :: UT task -> IO ()-cache_finalizer !tbl- = trace "cache finaliser"- $ HT.mapM_ (\(_,u) -> f u)- tbl- where- f :: Used task -> IO ()- f (Used _ _ _ _ _ w) = finalize w---- Miscellaneous--- ---------------cleanUses :: Task task => [task] -> IO [task]-cleanUses = filterM (fmap not . completed)--incCount :: Used task -> Used task-incCount (Used ts status count uses n weak_arr) = Used ts status (count + 1) uses n weak_arr--isEvicted :: Used task -> Bool-isEvicted (Used _ status _ _ _ _) = status == Evicted--withMVar' :: (MonadIO m, MonadMask m) => MVar a -> (a -> m b) -> m b-withMVar' m f = mask $ \restore -> do- a <- liftIO $ takeMVar m- b <- restore (f a) `onException` (liftIO $ putMVar m a)- liftIO $ putMVar m a- return b---- Debug--- -------{-# INLINE trace #-}-trace :: MonadIO m => String -> m a -> m a-trace msg next = message msg >> next--{-# INLINE message #-}-message :: MonadIO m => String -> m ()-message msg = liftIO $ D.traceIO D.dump_gc ("gc: " ++ msg)-
− Data/Array/Accelerate/Array/Remote/Nursery.hs
@@ -1,127 +0,0 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE TemplateHaskell #-}--- |--- Module : Data.Array.Accelerate.Array.Remote.Nursery--- Copyright : [2008..2017] Manuel M T Chakravarty, Gabriele Keller--- [2009..2017] Trevor L. McDonell--- [2015..2017] Robert Clifton-Everest--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Array.Remote.Nursery (-- Nursery(..), NRS, new, lookup, insert, cleanup, size--) where---- friends-import Data.Array.Accelerate.Error-import qualified Data.Array.Accelerate.Debug as Debug---- libraries-import Control.Concurrent.MVar-import Data.Int-import Data.IntMap ( IntMap )-import Data.Sequence ( Seq )-import Data.Word-import System.Mem.Weak ( Weak )-import Prelude hiding ( lookup )-import qualified Data.IntMap.Strict as IM-import qualified Data.Sequence as Seq-import qualified Data.Traversable as Seq----- The nursery is a place to store remote memory arrays that are no longer--- needed. Often it is quicker to reuse an existing array, rather than call out--- to the external API to allocate fresh memory.------ The nursery is wrapped in an MVar so that several threads may safely access--- it concurrently.----data Nursery ptr = Nursery {-# UNPACK #-} !(NRS ptr)- {-# UNPACK #-} !(Weak (NRS ptr))-type NRS ptr = MVar (N ptr)--data N ptr = N !(IntMap (Seq (ptr Word8))) -- #bytes -> ptr- {-# UNPACK #-} !Int64 -- total allocated bytes----- | Create a fresh nursery.------ When the nursery is garbage collected, the provided function will be run on--- each value to free the retained memory.----{-# INLINEABLE new #-}-new :: (ptr Word8 -> IO ()) -> IO (Nursery ptr)-new delete = do- message "initialise nursery"- ref <- newMVar ( N IM.empty 0 )- weak <- mkWeakMVar ref (cleanup delete ref)- return $! Nursery ref weak----- | Look for an entry with the requested size.----{-# INLINEABLE lookup #-}-lookup :: Int -> Nursery ptr -> IO (Maybe (ptr Word8))-lookup !key (Nursery !ref !_) =- modifyMVar ref $ \nrs@( N im sz ) ->- let- (mv, nrs') = IM.updateLookupWithKey f key im -- returns _original_ value, if located- f _k v =- case Seq.viewl v of- Seq.EmptyL -> $internalError "lookup" "expected non-empty sequence"- _ Seq.:< vs -> if Seq.null vs then Nothing -- delete this entry in the map- else Just vs -- re-insert the tail- in- case fmap Seq.viewl mv of- Just (v Seq.:< _) -> let sz' = sz - fromIntegral key in do- Debug.setCurrentBytesNursery sz'- return ( N nrs' sz', Just v )- _ -> return ( nrs, Nothing )----- | Add an entry to the nursery----{-# INLINEABLE insert #-}-insert :: Int -> ptr Word8 -> Nursery ptr -> IO ()-insert !key !val (Nursery !ref _) =- let- f Nothing = Just (Seq.singleton val)- f (Just vs) = Just (vs Seq.|> val)- in- modifyMVar_ ref $ \(N im sz) -> do- let sz' = sz + fromIntegral key- Debug.setCurrentBytesNursery sz'- return $! N (IM.alter f key im) sz'----- | Delete all entries from the nursery----{-# INLINEABLE cleanup #-}-cleanup :: (ptr Word8 -> IO ()) -> NRS ptr -> IO ()-cleanup delete !ref = do- message "nursery cleanup"- modifyMVar_ ref $ \(N nrs _) -> do mapM_ (Seq.mapM delete) (IM.elems nrs)- Debug.setCurrentBytesNursery 0- return ( N IM.empty 0 )----- | The total number of bytes retained by the nursery----{-# INLINEABLE size #-}-size :: Nursery ptr -> IO Int64-size (Nursery ref _) = withMVar ref $ \(N _ sz) -> return sz----- Debug--- -------{-# INLINE message #-}-message :: String -> IO ()-message msg = Debug.traceIO Debug.dump_gc ("gc: " ++ msg)-
− Data/Array/Accelerate/Array/Remote/Table.hs
@@ -1,469 +0,0 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE PatternGuards #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE UnboxedTuples #-}-{-# LANGUAGE ViewPatterns #-}-{-# OPTIONS_HADDOCK hide #-}--- |--- Module : Data.Array.Accelerate.Array.Remote.Table--- Copyright : [2008..2017] Manuel M T Chakravarty, Gabriele Keller--- [2009..2017] Trevor L. McDonell--- [2015..2017] Robert Clifton-Everest--- License : BSD3------ Maintainer : Robert Clifton-Everest <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)------ Accelerate backends often need to copy arrays to a remote memory before they--- can be used in computation. This module provides an automated method for--- doing so. Keeping track of arrays in a `MemoryTable` ensures that any memory--- allocated for them will be freed when GHC's garbage collector collects the--- host array.----module Data.Array.Accelerate.Array.Remote.Table (-- -- Tables for host/device memory associations- MemoryTable, new, lookup, malloc, free, freeStable, insertUnmanaged, reclaim,-- -- Internals- StableArray, makeStableArray,- makeWeakArrayData--) where--import Control.Concurrent ( yield )-import Control.Concurrent.MVar ( MVar, newMVar, withMVar, mkWeakMVar )-import Control.Concurrent.Unique ( Unique )-import Control.Monad.IO.Class ( MonadIO, liftIO )-import Data.Functor-import Data.Hashable ( hash, Hashable )-import Data.Maybe ( isJust )-import Data.Proxy-import Data.Typeable ( Typeable, gcast )-import Data.Word-import Foreign.Storable ( sizeOf )-import System.Mem ( performGC )-import System.Mem.Weak ( Weak, deRefWeak )-import Prelude hiding ( lookup, id )-import qualified Data.HashTable.IO as HT--import GHC.Exts ( Ptr(..) )--import Data.Array.Accelerate.Error ( internalError )-import Data.Array.Accelerate.Array.Unique ( UniqueArray(..) )-import Data.Array.Accelerate.Array.Data ( ArrayData, GArrayData(..),- ArrayPtrs, ArrayElt, arrayElt, ArrayEltR(..) )-import Data.Array.Accelerate.Array.Remote.Class-import Data.Array.Accelerate.Array.Remote.Nursery ( Nursery(..) )-import Data.Array.Accelerate.Lifetime-import qualified Data.Array.Accelerate.Array.Remote.Nursery as N-import qualified Data.Array.Accelerate.Debug as D----- We use an MVar to the hash table, so that several threads may safely access--- it concurrently. This includes the finalisation threads that remove entries--- from the table.------ It is important that we can garbage collect old entries from the table when--- the key is no longer reachable in the heap. Hence the value part of each--- table entry is a (Weak val), where the stable name 'key' is the key for the--- memo table, and the 'val' is the value of this table entry. When the key--- becomes unreachable, a finaliser will fire and remove this entry from the--- hash buckets, and further attempts to dereference the weak pointer will--- return Nothing. References from 'val' to the key are ignored (see the--- semantics of weak pointers in the documentation).----type HashTable key val = HT.BasicHashTable key val-type MT p = MVar ( HashTable StableArray (RemoteArray p) )-data MemoryTable p = MemoryTable {-# UNPACK #-} !(MT p)- {-# UNPACK #-} !(Weak (MT p))- {-# UNPACK #-} !(Nursery p)- (p Word8 -> IO ())--data RemoteArray p where- RemoteArray :: Typeable e- => {-# UNPACK #-} !(Weak ()) -- Keep track of host array liveness- -> !(p e) -- The actual remote pointer- -> {-# UNPACK #-} !Int -- The array size in bytes- -> RemoteArray p---- | An untyped reference to an array, similar to a StableName.----newtype StableArray = StableArray Unique- deriving (Eq, Hashable)--instance Show StableArray where- show (StableArray u) = show (hash u)---- |Create a new memory table from host to remote arrays.------ The function supplied should be the `free` for the remote pointers being--- stored. This function will be called by the GC, which typically runs on a--- different thread. Unlike the `free` in `RemoteMemory`, this function cannot--- depend on any state.----new :: (forall a. ptr a -> IO ()) -> IO (MemoryTable ptr)-new release = do- message "initialise memory table"- tbl <- HT.new- ref <- newMVar tbl- nrs <- N.new release- weak <- mkWeakMVar ref (return ())- return $! MemoryTable ref weak nrs release----- | Look for the remote pointer corresponding to a given host-side array.----lookup- :: (PrimElt a b)- => MemoryTable p- -> ArrayData a- -> IO (Maybe (p b))-lookup (MemoryTable !ref _ _ _) !arr = do- sa <- makeStableArray arr- mw <- withMVar ref (`HT.lookup` sa)- case mw of- Nothing -> trace ("lookup/not found: " ++ show sa) $ return Nothing- Just (RemoteArray w p _) -> do- mv <- deRefWeak w- case mv of- Just _ | Just p' <- gcast p -> trace ("lookup/found: " ++ show sa) $ return (Just p')- | otherwise -> $internalError "lookup" $ "type mismatch"-- -- Note: [Weak pointer weirdness]- --- -- After the lookup is successful, there might conceivably be no further- -- references to 'arr'. If that is so, and a garbage collection- -- intervenes, the weak pointer might get tombstoned before 'deRefWeak'- -- gets to it. In that case we throw an error (below). However, because- -- we have used 'arr' in the continuation, this ensures that 'arr' is- -- reachable in the continuation of 'deRefWeak' and thus 'deRefWeak'- -- always succeeds. This sort of weirdness, typical of the world of weak- -- pointers, is why we can not reuse the stable name 'sa' computed- -- above in the error message.- --- Nothing ->- makeStableArray arr >>= \x -> $internalError "lookup" $ "dead weak pair: " ++ show x----- | Allocate a new device array to be associated with the given host-side array.--- This may not always use the `malloc` provided by the `RemoteMemory` instance.--- In order to reduce the number of raw allocations, previously allocated remote--- arrays will be re-used. In the event that the remote memory is exhausted,--- 'Nothing' is returned.----malloc :: forall a b m. (PrimElt a b, RemoteMemory m, MonadIO m)- => MemoryTable (RemotePtr m)- -> ArrayData a- -> Int- -> m (Maybe (RemotePtr m b))-malloc mt@(MemoryTable _ _ !nursery _) !ad !n = do- -- Note: [Allocation sizes]- --- -- Instead of allocating the exact number of elements requested, we round up to- -- a fixed chunk size as specified by RemoteMemory.remoteAllocationSize. This- -- means there is a greater chance the nursery will get a hit, and moreover- -- that we can search the nursery for an exact size.- --- chunk <- remoteAllocationSize- let -- next highest multiple of f from x- multiple x f = (x + (f-1)) `div` f- bytes = chunk * multiple (n * sizeOf (undefined::b)) chunk- --- message ("malloc: " ++ showBytes bytes)- mp <-- fmap (castRemotePtr (Proxy :: Proxy m))- <$> attempt "malloc/nursery" (liftIO $ N.lookup bytes nursery)- `orElse`- attempt "malloc/new" (mallocRemote bytes)- `orElse` do message "malloc/remote-malloc-failed (cleaning)"- clean mt- liftIO $ N.lookup bytes nursery- `orElse` do message "malloc/remote-malloc-failed (purging)"- purge mt- mallocRemote bytes- `orElse` do message "malloc/remote-malloc-failed (non-recoverable)"- return Nothing- case mp of- Nothing -> return Nothing- Just p' -> do- insert mt ad p' bytes- return (Just p')-- where- orElse :: m (Maybe x) -> m (Maybe x) -> m (Maybe x)- orElse ra rb = do- ma <- ra- case ma of- Nothing -> rb- Just a -> return (Just a)-- attempt :: String -> m (Maybe x) -> m (Maybe x)- attempt msg next = do- ma <- next- case ma of- Nothing -> return Nothing- Just a -> trace msg (return (Just a))------ | Deallocate the device array associated with the given host-side array.--- Typically this should only be called in very specific circumstances.----free :: (RemoteMemory m, PrimElt a b)- => proxy m- -> MemoryTable (RemotePtr m)- -> ArrayData a- -> IO ()-free proxy mt !arr = do- sa <- makeStableArray arr- freeStable proxy mt sa----- | Deallocate the device array associated with the given StableArray. This--- is useful for other memory managers built on top of the memory table.----freeStable- :: RemoteMemory m- => proxy m- -> MemoryTable (RemotePtr m)- -> StableArray- -> IO ()-freeStable proxy (MemoryTable !ref _ !nrs _) !sa =- withMVar ref $ \mt -> do- mw <- mt `HT.lookup` sa- case mw of- Nothing -> message ("free/already-removed: " ++ show sa)- Just (RemoteArray _ !p !bytes) -> do- message ("free/evict: " ++ show sa ++ " of " ++ showBytes bytes)- N.insert bytes (castRemotePtr proxy p) nrs- D.decreaseCurrentBytesRemote (fromIntegral bytes)- mt `HT.delete` sa----- Record an association between a host-side array and a new device memory area.--- The device memory will be freed when the host array is garbage collected.----insert :: forall m a b. (PrimElt a b, RemoteMemory m, MonadIO m)- => MemoryTable (RemotePtr m)- -> ArrayData a- -> RemotePtr m b- -> Int- -> m ()-insert mt@(MemoryTable !ref _ _ _) !arr !ptr !bytes = do- key <- makeStableArray arr- weak <- liftIO $ makeWeakArrayData arr () (Just $ freeStable (Proxy :: Proxy m) mt key)- message $ "insert: " ++ show key- liftIO $ D.increaseCurrentBytesRemote (fromIntegral bytes)- liftIO $ withMVar ref $ \tbl -> HT.insert tbl key (RemoteArray weak ptr bytes)----- |Record an association between a host-side array and a remote memory area--- that was not allocated by accelerate. The remote memory will NOT be re-used--- once the host-side array is garbage collected.------ This typically only has use for backends that provide an FFI.----insertUnmanaged- :: (PrimElt a b, MonadIO m)- => MemoryTable p- -> ArrayData a- -> p b- -> m ()-insertUnmanaged (MemoryTable !ref !weak_ref _ _) !arr !ptr = do- key <- makeStableArray arr- weak <- liftIO $ makeWeakArrayData arr () (Just $ remoteFinalizer weak_ref key)- message $ "insertUnmanaged: " ++ show key- liftIO $ withMVar ref $ \tbl -> HT.insert tbl key (RemoteArray weak ptr 0)----- Removing entries--- -------------------- |Initiate garbage collection and mark any arrays that no longer have host-side--- equivalents as reusable.----clean :: forall m. (RemoteMemory m, MonadIO m) => MemoryTable (RemotePtr m) -> m ()-clean mt@(MemoryTable _ weak_ref nrs _) = management "clean" nrs . liftIO $ do- -- Unfortunately there is no real way to force a GC then wait for it to- -- finish. Calling performGC then yielding works moderately well in- -- single-threaded cases, but tends to fall down otherwise. Either way, given- -- that finalizers are often significantly delayed, it is worth our while- -- traversing the table and explicitly freeing any dead entires.- --- D.didRemoteGC- performGC- yield- mr <- deRefWeak weak_ref- case mr of- Nothing -> return ()- Just ref -> do- rs <- withMVar ref $ HT.foldM removable [] -- collect arrays that can be removed- mapM_ (freeStable (Proxy :: Proxy m) mt) rs -- remove them all- where- removable rs (sa, RemoteArray w _ _) = do- alive <- isJust <$> deRefWeak w- if alive- then return rs- else return (sa:rs)----- | Call `free` on all arrays that are not currently associated with host-side--- arrays.----purge :: (RemoteMemory m, MonadIO m) => MemoryTable (RemotePtr m) -> m ()-purge (MemoryTable _ _ nursery@(Nursery nrs _) release)- = management "purge" nursery- $ liftIO (N.cleanup release nrs)----- |Initiate garbage collection and `free` any remote arrays that no longer--- have matching host-side equivalents.----reclaim :: forall m. (RemoteMemory m, MonadIO m) => MemoryTable (RemotePtr m) -> m ()-reclaim mt = clean mt >> purge mt--remoteFinalizer :: Weak (MT p) -> StableArray -> IO ()-remoteFinalizer !weak_ref !key = do- mr <- deRefWeak weak_ref- case mr of- Nothing -> message ("finalise/dead table: " ++ show key)- Just ref -> trace ("finalise: " ++ show key) $ withMVar ref (`HT.delete` key)----- Miscellaneous--- ----------------- | Make a new 'StableArray'.----{-# INLINE makeStableArray #-}-makeStableArray- :: (MonadIO m, Typeable a, Typeable e, ArrayPtrs a ~ Ptr e, ArrayElt a)- => ArrayData a- -> m StableArray-makeStableArray !ad = return $! StableArray (id arrayElt ad)- where- id :: ArrayEltR e -> ArrayData e -> Unique- id ArrayEltRint (AD_Int ua) = uniqueArrayId ua- id ArrayEltRint8 (AD_Int8 ua) = uniqueArrayId ua- id ArrayEltRint16 (AD_Int16 ua) = uniqueArrayId ua- id ArrayEltRint32 (AD_Int32 ua) = uniqueArrayId ua- id ArrayEltRint64 (AD_Int64 ua) = uniqueArrayId ua- id ArrayEltRword (AD_Word ua) = uniqueArrayId ua- id ArrayEltRword8 (AD_Word8 ua) = uniqueArrayId ua- id ArrayEltRword16 (AD_Word16 ua) = uniqueArrayId ua- id ArrayEltRword32 (AD_Word32 ua) = uniqueArrayId ua- id ArrayEltRword64 (AD_Word64 ua) = uniqueArrayId ua- id ArrayEltRcshort (AD_CShort ua) = uniqueArrayId ua- id ArrayEltRcushort (AD_CUShort ua) = uniqueArrayId ua- id ArrayEltRcint (AD_CInt ua) = uniqueArrayId ua- id ArrayEltRcuint (AD_CUInt ua) = uniqueArrayId ua- id ArrayEltRclong (AD_CLong ua) = uniqueArrayId ua- id ArrayEltRculong (AD_CULong ua) = uniqueArrayId ua- id ArrayEltRcllong (AD_CLLong ua) = uniqueArrayId ua- id ArrayEltRcullong (AD_CULLong ua) = uniqueArrayId ua- id ArrayEltRfloat (AD_Float ua) = uniqueArrayId ua- id ArrayEltRdouble (AD_Double ua) = uniqueArrayId ua- id ArrayEltRcfloat (AD_CFloat ua) = uniqueArrayId ua- id ArrayEltRcdouble (AD_CDouble ua) = uniqueArrayId ua- id ArrayEltRbool (AD_Bool ua) = uniqueArrayId ua- id ArrayEltRchar (AD_Char ua) = uniqueArrayId ua- id ArrayEltRcchar (AD_CChar ua) = uniqueArrayId ua- id ArrayEltRcschar (AD_CSChar ua) = uniqueArrayId ua- id ArrayEltRcuchar (AD_CUChar ua) = uniqueArrayId ua- id _ _ = error "I do have a cause, though. It is obscenity. I'm for it."---- Weak arrays--- -------------------------- |Make a weak pointer using an array as a key. Unlike the standard `mkWeak`,--- this guarantees finalisers won't fire early.----makeWeakArrayData- :: forall a e c. (ArrayElt e, ArrayPtrs e ~ Ptr a)- => ArrayData e- -> c- -> Maybe (IO ())- -> IO (Weak c)-makeWeakArrayData !ad !c !mf = mw arrayElt ad- where- mw :: ArrayEltR e -> ArrayData e -> IO (Weak c)- mw ArrayEltRint (AD_Int ua) = mkWeak' ua- mw ArrayEltRint8 (AD_Int8 ua) = mkWeak' ua- mw ArrayEltRint16 (AD_Int16 ua) = mkWeak' ua- mw ArrayEltRint32 (AD_Int32 ua) = mkWeak' ua- mw ArrayEltRint64 (AD_Int64 ua) = mkWeak' ua- mw ArrayEltRword (AD_Word ua) = mkWeak' ua- mw ArrayEltRword8 (AD_Word8 ua) = mkWeak' ua- mw ArrayEltRword16 (AD_Word16 ua) = mkWeak' ua- mw ArrayEltRword32 (AD_Word32 ua) = mkWeak' ua- mw ArrayEltRword64 (AD_Word64 ua) = mkWeak' ua- mw ArrayEltRcshort (AD_CShort ua) = mkWeak' ua- mw ArrayEltRcushort (AD_CUShort ua) = mkWeak' ua- mw ArrayEltRcint (AD_CInt ua) = mkWeak' ua- mw ArrayEltRcuint (AD_CUInt ua) = mkWeak' ua- mw ArrayEltRclong (AD_CLong ua) = mkWeak' ua- mw ArrayEltRculong (AD_CULong ua) = mkWeak' ua- mw ArrayEltRcllong (AD_CLLong ua) = mkWeak' ua- mw ArrayEltRcullong (AD_CULLong ua) = mkWeak' ua- mw ArrayEltRfloat (AD_Float ua) = mkWeak' ua- mw ArrayEltRdouble (AD_Double ua) = mkWeak' ua- mw ArrayEltRcfloat (AD_CFloat ua) = mkWeak' ua- mw ArrayEltRcdouble (AD_CDouble ua) = mkWeak' ua- mw ArrayEltRbool (AD_Bool ua) = mkWeak' ua- mw ArrayEltRchar (AD_Char ua) = mkWeak' ua- mw ArrayEltRcchar (AD_CChar ua) = mkWeak' ua- mw ArrayEltRcschar (AD_CSChar ua) = mkWeak' ua- mw ArrayEltRcuchar (AD_CUChar ua) = mkWeak' ua-#if __GLASGOW_HASKELL__ < 800- mw _ _ = error "Base eight is just like base ten really - if you're missing two fingers."-#endif-- mkWeak' :: UniqueArray a -> IO (Weak c)- mkWeak' !ua = do- let !uad = uniqueArrayData ua- case mf of- Nothing -> return ()- Just f -> addFinalizer uad f- mkWeak uad c----- Debug--- -------{-# INLINE showBytes #-}-showBytes :: Integral n => n -> String-showBytes x = D.showFFloatSIBase (Just 0) 1024 (fromIntegral x :: Double) "B"--{-# INLINE trace #-}-trace :: MonadIO m => String -> m a -> m a-trace msg next = message msg >> next--{-# INLINE message #-}-message :: MonadIO m => String -> m ()-message msg = liftIO $ D.traceIO D.dump_gc ("gc: " ++ msg)--{-# INLINE management #-}-management :: (RemoteMemory m, MonadIO m) => String -> Nursery p -> m a -> m a-management msg nrs next = do- before <- availableRemoteMem- before_nrs <- liftIO $ N.size nrs- total <- totalRemoteMem- r <- next- D.when D.dump_gc $ do- after <- availableRemoteMem- after_nrs <- liftIO $ N.size nrs- message $ msg ++ " (freed: " ++ showBytes (after - before)- ++ ", stashed: " ++ showBytes (before_nrs - after_nrs)- ++ ", remaining: " ++ showBytes after- ++ " of " ++ showBytes total ++ ")"- return r-
− Data/Array/Accelerate/Array/Representation.hs
@@ -1,235 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}-{-# OPTIONS_HADDOCK hide #-}--- |--- Module : Data.Array.Accelerate.Array.Representation--- Copyright : [2008..2017] Manuel M T Chakravarty, Gabriele Keller--- [2009..2017] Trevor L. McDonell--- [2013..2017] Robert Clifton-Everest--- [2014..2014] Frederik M. Madsen--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Array.Representation (-- -- * Array shapes, indices, and slices- Shape(..), Slice(..), SliceIndex(..),-- -- * Slice shape functions- sliceShape, enumSlices,--) where---- friends-import Data.Array.Accelerate.Error---- standard library-import GHC.Base ( quotInt, remInt )----- |Index representation------- |Class of index representations (which are nested pairs)----class (Eq sh, Slice sh) => Shape sh where- -- user-facing methods- rank :: sh -> Int -- ^number of dimensions (>= 0); rank of the array- size :: sh -> Int -- ^total number of elements in an array of this /shape/- empty :: sh -- ^empty shape.-- -- internal methods- intersect :: sh -> sh -> sh -- yield the intersection of two shapes- union :: sh -> sh -> sh -- yield the union of two shapes- ignore :: sh -- identifies ignored elements in 'permute'- toIndex :: sh -> sh -> Int -- yield the index position in a linear, row-major representation of- -- the array (first argument is the shape)- fromIndex :: sh -> Int -> sh -- inverse of `toIndex`-- iter :: sh -> (sh -> a) -> (a -> a -> a) -> a -> a- -- iterate through the entire shape, applying the function in the- -- second argument; third argument combines results and fourth is an- -- initial value that is combined with the results; the index space- -- is traversed in row-major order-- iter1 :: sh -> (sh -> a) -> (a -> a -> a) -> a- -- variant of 'iter' without an initial value-- -- operations to facilitate conversion with IArray- rangeToShape :: (sh, sh) -> sh -- convert a minpoint-maxpoint index- -- into a shape- shapeToRange :: sh -> (sh, sh) -- ...the converse--- -- other conversions- shapeToList :: sh -> [Int] -- convert a shape into its list of dimensions- listToShape :: [Int] -> sh -- convert a list of dimensions into a shape--instance Shape () where- rank _ = 0- empty = ()- ignore = ()- () `intersect` () = ()- () `union` () = ()- size () = 1- toIndex () () = 0- fromIndex () _ = ()- iter () f _ _ = f ()- iter1 () f _ = f ()-- rangeToShape ((), ()) = ()- shapeToRange () = ((), ())-- shapeToList () = []- listToShape [] = ()- listToShape _ = $internalError "listToShape" "non-empty list when converting to unit"--instance Shape sh => Shape (sh, Int) where- rank _ = rank (undefined :: sh) + 1- empty = (empty, 0)- ignore = (ignore, -1)- (sh1, sz1) `intersect` (sh2, sz2) = (sh1 `intersect` sh2, sz1 `min` sz2)- (sh1, sz1) `union` (sh2, sz2) = (sh1 `union` sh2, sz1 `max` sz2)-- size (sh, sz) = $boundsCheck "size" "negative shape dimension" (sz >= 0)- $ size sh * sz-- toIndex (sh, sz) (ix, i) = $indexCheck "toIndex" i sz- $ toIndex sh ix * sz + i-- fromIndex (sh, sz) i = (fromIndex sh (i `quotInt` sz), r)- -- If we assume that the index is in range, there is no point in computing- -- the remainder for the highest dimension since i < sz must hold.- --- where- r | rank sh == 0 = $indexCheck "fromIndex" i sz i- | otherwise = i `remInt` sz--{--- bound (sh, sz) (ix, i) bndy- | i < 0 = case bndy of- Clamp -> next `addDim` 0- Mirror -> next `addDim` (-i)- Wrap -> next `addDim` (sz+i)- Constant e -> Left e- | i >= sz = case bndy of- Clamp -> next `addDim` (sz-1)- Mirror -> next `addDim` (sz-(i-sz+2))- Wrap -> next `addDim` (i-sz)- Constant e -> Left e- | otherwise = next `addDim` i- where- -- This function is quite difficult to optimize due to the deep recursion- -- that it can generate with high-dimensional arrays. If we let 'next' be- -- inlined into each alternative of the cases above the size of this- -- function on an n-dimensional array will grow as 7^n. This quickly causes- -- GHC's head to explode. See GHC Trac #10491 for more details.- next = bound sh ix bndy- {-# NOINLINE next #-}-- Right ds `addDim` d = Right (ds, d)- Left e `addDim` _ = Left e---}-- iter (sh, sz) f c r = iter sh (\ix -> iter' (ix,0)) c r- where- iter' (ix,i) | i >= sz = r- | otherwise = f (ix,i) `c` iter' (ix,i+1)-- iter1 (_, 0) _ _ = $boundsError "iter1" "empty iteration space"- iter1 (sh, sz) f c = iter1 sh (\ix -> iter1' (ix,0)) c- where- iter1' (ix,i) | i == sz-1 = f (ix,i)- | otherwise = f (ix,i) `c` iter1' (ix,i+1)-- rangeToShape ((sh1, sz1), (sh2, sz2))- = (rangeToShape (sh1, sh2), sz2 - sz1 + 1)- shapeToRange (sh, sz)- = let (low, high) = shapeToRange sh- in- ((low, 0), (high, sz - 1))-- shapeToList (sh,sz) = sz : shapeToList sh- listToShape [] = $internalError "listToShape" "empty list when converting to Ix"- listToShape (x:xs) = (listToShape xs,x)----- |Slice representation------- |Class of slice representations (which are nested pairs)----class Slice sl where- type SliceShape sl -- the projected slice- type CoSliceShape sl -- the complement of the slice- type FullShape sl -- the combined dimension- -- argument *value* not used; it's just a phantom value to fix the type- sliceIndex :: {-dummy-} sl -> SliceIndex sl (SliceShape sl) (CoSliceShape sl) (FullShape sl)--instance Slice () where- type SliceShape () = ()- type CoSliceShape () = ()- type FullShape () = ()- sliceIndex _ = SliceNil--instance Slice sl => Slice (sl, ()) where- type SliceShape (sl, ()) = (SliceShape sl, Int)- type CoSliceShape (sl, ()) = CoSliceShape sl- type FullShape (sl, ()) = (FullShape sl, Int)- sliceIndex _ = SliceAll (sliceIndex (undefined::sl))--instance Slice sl => Slice (sl, Int) where- type SliceShape (sl, Int) = SliceShape sl- type CoSliceShape (sl, Int) = (CoSliceShape sl, Int)- type FullShape (sl, Int) = (FullShape sl, Int)- sliceIndex _ = SliceFixed (sliceIndex (undefined::sl))---- |Generalised array index, which may index only in a subset of the dimensions--- of a shape.----data SliceIndex ix slice coSlice sliceDim where- SliceNil :: SliceIndex () () () ()- SliceAll ::- SliceIndex ix slice co dim -> SliceIndex (ix, ()) (slice, Int) co (dim, Int)- SliceFixed ::- SliceIndex ix slice co dim -> SliceIndex (ix, Int) slice (co, Int) (dim, Int)--instance Show (SliceIndex ix slice coSlice sliceDim) where- show SliceNil = "SliceNil"- show (SliceAll rest) = "SliceAll (" ++ show rest ++ ")"- show (SliceFixed rest) = "SliceFixed (" ++ show rest ++ ")"---- | Project the shape of a slice from the full shape.----sliceShape :: forall slix co sl dim.- SliceIndex slix sl co dim- -> dim- -> sl-sliceShape SliceNil () = ()-sliceShape (SliceAll sl) (sh, n) = (sliceShape sl sh, n)-sliceShape (SliceFixed sl) (sh, _) = sliceShape sl sh----- | Enumerate all slices within a given bound. The innermost dimension changes--- most rapidly.------ See 'Data.Array.Accelerate.Array.Sugar.enumSlices' for an example.----enumSlices :: forall slix co sl dim.- SliceIndex slix sl co dim- -> dim- -> [slix]-enumSlices SliceNil () = [()]-enumSlices (SliceAll sl) (sh, _) = [ (sh', ()) | sh' <- enumSlices sl sh]-enumSlices (SliceFixed sl) (sh, n) = [ (sh', i) | sh' <- enumSlices sl sh, i <- [0..n-1]]-
− Data/Array/Accelerate/Array/Sugar.hs
@@ -1,1294 +0,0 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE UndecidableInstances #-}-#if __GLASGOW_HASKELL__ <= 708-{-# OPTIONS_GHC -fno-warn-unrecognised-pragmas #-}-#endif-{-# OPTIONS_HADDOCK hide #-}--- |--- Module : Data.Array.Accelerate.Array.Sugar--- Copyright : [2008..2017] Manuel M T Chakravarty, Gabriele Keller--- [2009..2017] Trevor L. McDonell--- [2013..2017] Robert Clifton-Everest--- [2014..2014] Frederik M. Madsen--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Array.Sugar (-- -- * Array representation- Array(..), Scalar, Vector, Segments,- Arrays(..), ArraysR(..), ArraysFlavour(..), ArrRepr,-- -- * Class of supported surface element types and their mapping to representation types- Elt(..), EltRepr,-- -- * Derived functions- liftToElt, liftToElt2, sinkFromElt, sinkFromElt2,-- -- * Array shapes- DIM0, DIM1, DIM2, DIM3, DIM4, DIM5, DIM6, DIM7, DIM8, DIM9,-- -- * Array indexing and slicing- Z(..), (:.)(..), All(..), Split(..), Any(..), Divide(..), Shape(..), Slice(..), Division(..),-- -- * Array shape query, indexing, and conversions- shape, (!), allocateArray, fromFunction, fromList, toList, concatVectors,-- -- * Tuples- TupleR, TupleRepr, tuple,- Tuple(..), IsTuple, fromTuple, toTuple,- Atuple(..), IsAtuple, fromAtuple, toAtuple,-- -- * Miscellaneous- showShape, Foreign(..), sliceShape, enumSlices,--) where---- standard library-import Control.DeepSeq-import Data.List ( intercalate, transpose )-import Data.Typeable-import GHC.Exts ( IsList )-import Language.Haskell.TH hiding ( Foreign )-import qualified GHC.Exts as GHC---- friends-import Data.Array.Accelerate.Array.Data-import Data.Array.Accelerate.Error-import Data.Array.Accelerate.Product-import Data.Array.Accelerate.Type-import qualified Data.Array.Accelerate.Array.Representation as Repr----- Surface types representing array indices and slices--- --------------------------------------------------------- Array indices are snoc type lists. That is, they're backwards ----- the end-of-list token, `Z`, occurs first. For example, the type of a--- rank-2 array index is @Z :. Int :. Int@.------ In Accelerate the rightmost dimension is the /fastest varying/ or innermost.---- |Rank-0 index----data Z = Z- deriving (Typeable, Show, Eq)---- |Increase an index rank by one dimension. The `:.` operator is--- used to construct both values and types.----infixl 3 :.-data tail :. head = tail :. head- deriving (Typeable, Eq)---- We don't we use a derived Show instance for (:.) because this will insert--- parenthesis to demonstrate which order the operator is applied, i.e.:------ (((Z :. z) :. y) :. x)------ This is fine, but I find it a little unsightly. Instead, we drop all--- parenthesis and just display the shape thus:------ Z :. z :. y :. x------ and then require the down-stream user to wrap the whole thing in parentheses.--- This works fine for the most important case, which is to show Acc and Exp--- expressions via the pretty printer, although Show-ing a Shape directly--- results in no parenthesis being displayed.------ One way around this might be to have specialised instances for DIM1, DIM2,--- etc.----instance (Show sh, Show sz) => Show (sh :. sz) where- show (sh :. sz) = show sh ++ " :. " ++ show sz---- | Marker for entire dimensions in 'Data.Array.Accelerate.Language.slice' and--- 'Data.Array.Accelerate.Language.replicate' descriptors.------ Occurrences of 'All' indicate the dimensions into which the array's existing--- extent will be placed unchanged.------ See 'Data.Array.Accelerate.Language.slice' and--- 'Data.Array.Accelerate.Language.replicate' for examples.----data All = All- deriving (Typeable, Show, Eq)---- | Marker for arbitrary dimensions in 'Data.Array.Accelerate.Language.slice'--- and 'Data.Array.Accelerate.Language.replicate' descriptors.------ 'Any' can be used in the leftmost position of a slice instead of 'Z',--- indicating that any dimensionality is admissible in that position.------ See 'Data.Array.Accelerate.Language.slice' and--- 'Data.Array.Accelerate.Language.replicate' for examples.----data Any sh = Any- deriving (Typeable, Show, Eq)---- | Marker for splitting along an entire dimension in division descriptors.------ For example, when used in a division descriptor passed to--- 'Data.Array.Accelerate.toSeq', a `Split` indicates that the array should be--- divided along this dimension forming the elements of the output sequence.----data Split = Split- deriving (Typeable, Show, Eq)---- | Marker for arbitrary shapes in slices descriptors, where it is desired to--- split along an unknown number of dimensions.------ For example, in the following definition, 'Divide' matches against any shape--- and flattens everything but the innermost dimension.------ > vectors :: (Shape sh, Elt e) => Acc (Array (sh:.Int) e) -> Seq [Vector e]--- > vectors = toSeq (Divide :. All)----data Divide sh = Divide- deriving (Typeable, Show, Eq)----- Representation change for array element types--- ------------------------------------------------- | Type representation mapping------ We represent tuples by using '()' and '(,)' as type-level nil and snoc to--- construct snoc-lists of types, and are flattened all the way down to--- primitive types.----type family EltRepr a :: *-type instance EltRepr () = ()-type instance EltRepr Z = ()-type instance EltRepr (t:.h) = (EltRepr t, EltRepr h)-type instance EltRepr All = ()-type instance EltRepr (Any Z) = ()-type instance EltRepr (Any (sh:.Int)) = (EltRepr (Any sh), ())-type instance EltRepr Int = Int-type instance EltRepr Int8 = Int8-type instance EltRepr Int16 = Int16-type instance EltRepr Int32 = Int32-type instance EltRepr Int64 = Int64-type instance EltRepr Word = Word-type instance EltRepr Word8 = Word8-type instance EltRepr Word16 = Word16-type instance EltRepr Word32 = Word32-type instance EltRepr Word64 = Word64-type instance EltRepr CShort = CShort-type instance EltRepr CUShort = CUShort-type instance EltRepr CInt = CInt-type instance EltRepr CUInt = CUInt-type instance EltRepr CLong = CLong-type instance EltRepr CULong = CULong-type instance EltRepr CLLong = CLLong-type instance EltRepr CULLong = CULLong-type instance EltRepr Float = Float-type instance EltRepr Double = Double-type instance EltRepr CFloat = CFloat-type instance EltRepr CDouble = CDouble-type instance EltRepr Bool = Bool-type instance EltRepr Char = Char-type instance EltRepr CChar = CChar-type instance EltRepr CSChar = CSChar-type instance EltRepr CUChar = CUChar-type instance EltRepr (a, b) = TupleRepr (EltRepr a, EltRepr b)-type instance EltRepr (a, b, c) = TupleRepr (EltRepr a, EltRepr b, EltRepr c)-type instance EltRepr (a, b, c, d) = TupleRepr (EltRepr a, EltRepr b, EltRepr c, EltRepr d)-type instance EltRepr (a, b, c, d, e) = TupleRepr (EltRepr a, EltRepr b, EltRepr c, EltRepr d, EltRepr e)-type instance EltRepr (a, b, c, d, e, f) = TupleRepr (EltRepr a, EltRepr b, EltRepr c, EltRepr d, EltRepr e, EltRepr f)-type instance EltRepr (a, b, c, d, e, f, g) = TupleRepr (EltRepr a, EltRepr b, EltRepr c, EltRepr d, EltRepr e, EltRepr f, EltRepr g)-type instance EltRepr (a, b, c, d, e, f, g, h) = TupleRepr (EltRepr a, EltRepr b, EltRepr c, EltRepr d, EltRepr e, EltRepr f, EltRepr g, EltRepr h)-type instance EltRepr (a, b, c, d, e, f, g, h, i) = TupleRepr (EltRepr a, EltRepr b, EltRepr c, EltRepr d, EltRepr e, EltRepr f, EltRepr g, EltRepr h, EltRepr i)-type instance EltRepr (a, b, c, d, e, f, g, h, i, j) = TupleRepr (EltRepr a, EltRepr b, EltRepr c, EltRepr d, EltRepr e, EltRepr f, EltRepr g, EltRepr h, EltRepr i, EltRepr j)-type instance EltRepr (a, b, c, d, e, f, g, h, i, j, k) = TupleRepr (EltRepr a, EltRepr b, EltRepr c, EltRepr d, EltRepr e, EltRepr f, EltRepr g, EltRepr h, EltRepr i, EltRepr j, EltRepr k)-type instance EltRepr (a, b, c, d, e, f, g, h, i, j, k, l) = TupleRepr (EltRepr a, EltRepr b, EltRepr c, EltRepr d, EltRepr e, EltRepr f, EltRepr g, EltRepr h, EltRepr i, EltRepr j, EltRepr k, EltRepr l)-type instance EltRepr (a, b, c, d, e, f, g, h, i, j, k, l, m) = TupleRepr (EltRepr a, EltRepr b, EltRepr c, EltRepr d, EltRepr e, EltRepr f, EltRepr g, EltRepr h, EltRepr i, EltRepr j, EltRepr k, EltRepr l, EltRepr m)-type instance EltRepr (a, b, c, d, e, f, g, h, i, j, k, l, m, n) = TupleRepr (EltRepr a, EltRepr b, EltRepr c, EltRepr d, EltRepr e, EltRepr f, EltRepr g, EltRepr h, EltRepr i, EltRepr j, EltRepr k, EltRepr l, EltRepr m, EltRepr n)-type instance EltRepr (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) = TupleRepr (EltRepr a, EltRepr b, EltRepr c, EltRepr d, EltRepr e, EltRepr f, EltRepr g, EltRepr h, EltRepr i, EltRepr j, EltRepr k, EltRepr l, EltRepr m, EltRepr n, EltRepr o)--type IsTuple = IsProduct Elt--fromTuple :: IsTuple tup => tup -> TupleRepr tup-fromTuple = fromProd (Proxy :: Proxy Elt)--toTuple :: IsTuple tup => TupleRepr tup -> tup-toTuple = toProd (Proxy :: Proxy Elt)----- Array elements (tuples of scalars)--- -------------------------------------- | The 'Elt' class characterises the allowable array element types, and hence--- the types which can appear in scalar Accelerate expressions.------ Accelerate arrays consist of simple atomic types as well as nested tuples--- thereof, stored efficiently in memory as consecutive unpacked elements--- without pointers. It roughly consists of:------ * Signed and unsigned integers (8, 16, 32, and 64-bits wide)--- * Floating point numbers (single and double precision)--- * 'Char'--- * 'Bool'--- * ()--- * Shapes formed from 'Z' and (':.')--- * Nested tuples of all of these, currently up to 15-elements wide------ Adding new instances for 'Elt' consists of explaining to Accelerate how to--- map between your data type and a (tuple of) primitive values. For examples--- see:------ * "Data.Array.Accelerate.Data.Complex"--- * "Data.Array.Accelerate.Data.Monoid"--- * <https://hackage.haskell.org/package/linear-accelerate linear-accelerate>--- * <https://hackage.haskell.org/package/colour-accelerate colour-accelerate>----class (Show a, Typeable a, Typeable (EltRepr a), ArrayElt (EltRepr a))- => Elt a where- eltType :: {-dummy-} a -> TupleType (EltRepr a)- fromElt :: a -> EltRepr a- toElt :: EltRepr a -> a--instance Elt () where- eltType _ = UnitTuple- fromElt = id- toElt = id--instance Elt Z where- eltType _ = UnitTuple- fromElt Z = ()- toElt () = Z--instance (Elt t, Elt h) => Elt (t:.h) where- eltType (_::(t:.h)) = PairTuple (eltType (undefined :: t)) (eltType (undefined :: h))- fromElt (t:.h) = (fromElt t, fromElt h)- toElt (t, h) = toElt t :. toElt h--instance Elt All where- eltType _ = UnitTuple- fromElt All = ()- toElt () = All--instance Elt (Any Z) where- eltType _ = UnitTuple- fromElt _ = ()- toElt _ = Any--instance Shape sh => Elt (Any (sh:.Int)) where- eltType _ = PairTuple (eltType (undefined::Any sh)) UnitTuple- fromElt _ = (fromElt (undefined :: Any sh), ())- toElt _ = Any--instance Elt Int where- eltType = singletonScalarType- fromElt = id- toElt = id--instance Elt Int8 where- eltType = singletonScalarType- fromElt = id- toElt = id--instance Elt Int16 where- eltType = singletonScalarType- fromElt = id- toElt = id--instance Elt Int32 where- eltType = singletonScalarType- fromElt = id- toElt = id--instance Elt Int64 where- eltType = singletonScalarType- fromElt = id- toElt = id--instance Elt Word where- eltType = singletonScalarType- fromElt = id- toElt = id--instance Elt Word8 where- eltType = singletonScalarType- fromElt = id- toElt = id--instance Elt Word16 where- eltType = singletonScalarType- fromElt = id- toElt = id--instance Elt Word32 where- eltType = singletonScalarType- fromElt = id- toElt = id--instance Elt Word64 where- eltType = singletonScalarType- fromElt = id- toElt = id--instance Elt CShort where- eltType = singletonScalarType- fromElt = id- toElt = id--instance Elt CUShort where- eltType = singletonScalarType- fromElt = id- toElt = id--instance Elt CInt where- eltType = singletonScalarType- fromElt = id- toElt = id--instance Elt CUInt where- eltType = singletonScalarType- fromElt = id- toElt = id--instance Elt CLong where- eltType = singletonScalarType- fromElt = id- toElt = id--instance Elt CULong where- eltType = singletonScalarType- fromElt = id- toElt = id--instance Elt CLLong where- eltType = singletonScalarType- fromElt = id- toElt = id--instance Elt CULLong where- eltType = singletonScalarType- fromElt = id- toElt = id--instance Elt Float where- eltType = singletonScalarType- fromElt = id- toElt = id--instance Elt Double where- eltType = singletonScalarType- fromElt = id- toElt = id--instance Elt CFloat where- eltType = singletonScalarType- fromElt = id- toElt = id--instance Elt CDouble where- eltType = singletonScalarType- fromElt = id- toElt = id--instance Elt Bool where- eltType = singletonScalarType- fromElt = id- toElt = id--instance Elt Char where- eltType = singletonScalarType- fromElt = id- toElt = id--instance Elt CChar where- eltType = singletonScalarType- fromElt = id- toElt = id--instance Elt CSChar where- eltType = singletonScalarType- fromElt = id- toElt = id--instance Elt CUChar where- eltType = singletonScalarType- fromElt = id- toElt = id--instance (Elt a, Elt b) => Elt (a, b) where- eltType _ = PairTuple (PairTuple UnitTuple (eltType (undefined::a))) (eltType (undefined::b))- fromElt (a,b) = (((), fromElt a), fromElt b)- toElt (((),a),b) = (toElt a, toElt b)--instance (Elt a, Elt b, Elt c) => Elt (a, b, c) where- eltType _ = PairTuple (eltType (undefined :: (a, b))) (eltType (undefined :: c))- fromElt (a, b, c) = (fromElt (a, b), fromElt c)- toElt (ab, c) = let (a, b) = toElt ab in (a, b, toElt c)--instance (Elt a, Elt b, Elt c, Elt d) => Elt (a, b, c, d) where- eltType _ = PairTuple (eltType (undefined :: (a, b, c))) (eltType (undefined :: d))- fromElt (a, b, c, d) = (fromElt (a, b, c), fromElt d)- toElt (abc, d) = let (a, b, c) = toElt abc in (a, b, c, toElt d)--instance (Elt a, Elt b, Elt c, Elt d, Elt e) => Elt (a, b, c, d, e) where- eltType _ = PairTuple (eltType (undefined :: (a, b, c, d))) (eltType (undefined :: e))- fromElt (a, b, c, d, e) = (fromElt (a, b, c, d), fromElt e)- toElt (abcd, e) = let (a, b, c, d) = toElt abcd in (a, b, c, d, toElt e)--instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f) => Elt (a, b, c, d, e, f) where- eltType _- = PairTuple (eltType (undefined :: (a, b, c, d, e)))- (eltType (undefined :: f))- fromElt (a, b, c, d, e, f) = (fromElt (a, b, c, d, e), fromElt f)- toElt (abcde, f) = let (a, b, c, d, e) = toElt abcde in (a, b, c, d, e, toElt f)--instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g)- => Elt (a, b, c, d, e, f, g) where- eltType _- = PairTuple (eltType (undefined :: (a, b, c, d, e, f)))- (eltType (undefined :: g))- fromElt (a, b, c, d, e, f, g) = (fromElt (a, b, c, d, e, f), fromElt g)- toElt (abcdef, g) = let (a, b, c, d, e, f) = toElt abcdef- in (a, b, c, d, e, f, toElt g)--instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h)- => Elt (a, b, c, d, e, f, g, h) where- eltType _- = PairTuple (eltType (undefined :: (a, b, c, d, e, f, g)))- (eltType (undefined :: h))- fromElt (a, b, c, d, e, f, g, h) = (fromElt (a, b, c, d, e, f, g), fromElt h)- toElt (abcdefg, h) = let (a, b, c, d, e, f, g) = toElt abcdefg- in (a, b, c, d, e, f, g, toElt h)--instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i)- => Elt (a, b, c, d, e, f, g, h, i) where- eltType _- = PairTuple (eltType (undefined :: (a, b, c, d, e, f, g, h)))- (eltType (undefined :: i))- fromElt (a, b, c, d, e, f, g, h, i) = (fromElt (a, b, c, d, e, f, g, h), fromElt i)- toElt (abcdefgh, i) = let (a, b, c, d, e, f, g, h) = toElt abcdefgh- in (a, b, c, d, e, f, g, h, toElt i)--instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j)- => Elt (a, b, c, d, e, f, g, h, i, j) where- eltType _- = PairTuple (eltType (undefined :: (a, b, c, d, e, f, g, h, i)))- (eltType (undefined :: j))- fromElt (a, b, c, d, e, f, g, h, i, j) = (fromElt (a, b, c, d, e, f, g, h, i), fromElt j)- toElt (abcdefghi, j) = let (a, b, c, d, e, f, g, h, i) = toElt abcdefghi- in (a, b, c, d, e, f, g, h, i, toElt j)--instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k)- => Elt (a, b, c, d, e, f, g, h, i, j, k) where- eltType _- = PairTuple (eltType (undefined :: (a, b, c, d, e, f, g, h, i, j)))- (eltType (undefined :: k))- fromElt (a, b, c, d, e, f, g, h, i, j, k) = (fromElt (a, b, c, d, e, f, g, h, i, j), fromElt k)- toElt (abcdefghij, k) = let (a, b, c, d, e, f, g, h, i, j) = toElt abcdefghij- in (a, b, c, d, e, f, g, h, i, j, toElt k)--instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l)- => Elt (a, b, c, d, e, f, g, h, i, j, k, l) where- eltType _- = PairTuple (eltType (undefined :: (a, b, c, d, e, f, g, h, i, j, k)))- (eltType (undefined :: l))- fromElt (a, b, c, d, e, f, g, h, i, j, k, l) = (fromElt (a, b, c, d, e, f, g, h, i, j, k), fromElt l)- toElt (abcdefghijk, l) = let (a, b, c, d, e, f, g, h, i, j, k) = toElt abcdefghijk- in (a, b, c, d, e, f, g, h, i, j, k, toElt l)--instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l, Elt m)- => Elt (a, b, c, d, e, f, g, h, i, j, k, l, m) where- eltType _- = PairTuple (eltType (undefined :: (a, b, c, d, e, f, g, h, i, j, k, l)))- (eltType (undefined :: m))- fromElt (a, b, c, d, e, f, g, h, i, j, k, l, m) = (fromElt (a, b, c, d, e, f, g, h, i, j, k, l), fromElt m)- toElt (abcdefghijkl, m) = let (a, b, c, d, e, f, g, h, i, j, k, l) = toElt abcdefghijkl- in (a, b, c, d, e, f, g, h, i, j, k, l, toElt m)--instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l, Elt m, Elt n)- => Elt (a, b, c, d, e, f, g, h, i, j, k, l, m, n) where- eltType _- = PairTuple (eltType (undefined :: (a, b, c, d, e, f, g, h, i, j, k, l, m)))- (eltType (undefined :: n))- fromElt (a, b, c, d, e, f, g, h, i, j, k, l, m, n) = (fromElt (a, b, c, d, e, f, g, h, i, j, k, l, m), fromElt n)- toElt (abcdefghijklm, n) = let (a, b, c, d, e, f, g, h, i, j, k, l, m) = toElt abcdefghijklm- in (a, b, c, d, e, f, g, h, i, j, k, l, m, toElt n)--instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l, Elt m, Elt n, Elt o)- => Elt (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) where- eltType _- = PairTuple (eltType (undefined :: (a, b, c, d, e, f, g, h, i, j, k, l, m, n)))- (eltType (undefined :: o))- fromElt (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) = (fromElt (a, b, c, d, e, f, g, h, i, j, k, l, m, n), fromElt o)- toElt (abcdefghijklmn, o) = let (a, b, c, d, e, f, g, h, i, j, k, l, m, n) = toElt abcdefghijklmn- in (a, b, c, d, e, f, g, h, i, j, k, l, m, n, toElt o)----- |Convenience functions-----singletonScalarType :: IsScalar a => a -> TupleType a-singletonScalarType _ = SingleTuple scalarType--liftToElt :: (Elt a, Elt b)- => (EltRepr a -> EltRepr b)- -> (a -> b)-{-# INLINE liftToElt #-}-liftToElt f = toElt . f . fromElt--liftToElt2 :: (Elt a, Elt b, Elt c)- => (EltRepr a -> EltRepr b -> EltRepr c)- -> (a -> b -> c)-{-# INLINE liftToElt2 #-}-liftToElt2 f x y = toElt $ f (fromElt x) (fromElt y)--sinkFromElt :: (Elt a, Elt b)- => (a -> b)- -> (EltRepr a -> EltRepr b)-{-# INLINE sinkFromElt #-}-sinkFromElt f = fromElt . f . toElt--sinkFromElt2 :: (Elt a, Elt b, Elt c)- => (a -> b -> c)- -> (EltRepr a -> EltRepr b -> EltRepr c)-{-# INLINE sinkFromElt2 #-}-sinkFromElt2 f x y = fromElt $ f (toElt x) (toElt y)---- {-# RULES--- "fromElt/toElt" forall e. fromElt (toElt e) = e--- "toElt/fromElt" forall e. toElt (fromElt e) = e--- #-}----- Foreign functions--- --------------------- Class for backends to choose their own representation of foreign functions.--- By default it has no instances. If a backend wishes to have an FFI it must--- provide an instance.----class Typeable asm => Foreign asm where-- -- Backends should be able to produce a string representation of the foreign- -- function for pretty printing, typically the name of the function.- strForeign :: asm args -> String- strForeign _ = "<foreign>"-- -- Backends which want to support compile-time embedding must be able to lift- -- the foreign function into Template Haskell- liftForeign :: asm args -> Q (TExp (asm args))- liftForeign _ = $internalError "liftForeign" "not supported by this backend"----- Surface arrays--- ------------------ We represent tuples of arrays in the same way as tuples of scalars; using--- '()' and '(,)' as type-level nil and snoc. This characterises the domain of--- results of Accelerate array computations.----type family ArrRepr a :: *-type instance ArrRepr () = ()-type instance ArrRepr (Array sh e) = Array sh e-type instance ArrRepr (a, b) = TupleRepr (ArrRepr a, ArrRepr b)-type instance ArrRepr (a, b, c) = TupleRepr (ArrRepr a, ArrRepr b, ArrRepr c)-type instance ArrRepr (a, b, c, d) = TupleRepr (ArrRepr a, ArrRepr b, ArrRepr c, ArrRepr d)-type instance ArrRepr (a, b, c, d, e) = TupleRepr (ArrRepr a, ArrRepr b, ArrRepr c, ArrRepr d, ArrRepr e)-type instance ArrRepr (a, b, c, d, e, f) = TupleRepr (ArrRepr a, ArrRepr b, ArrRepr c, ArrRepr d, ArrRepr e, ArrRepr f)-type instance ArrRepr (a, b, c, d, e, f, g) = TupleRepr (ArrRepr a, ArrRepr b, ArrRepr c, ArrRepr d, ArrRepr e, ArrRepr f, ArrRepr g)-type instance ArrRepr (a, b, c, d, e, f, g, h) = TupleRepr (ArrRepr a, ArrRepr b, ArrRepr c, ArrRepr d, ArrRepr e, ArrRepr f, ArrRepr g, ArrRepr h)-type instance ArrRepr (a, b, c, d, e, f, g, h, i) = TupleRepr (ArrRepr a, ArrRepr b, ArrRepr c, ArrRepr d, ArrRepr e, ArrRepr f, ArrRepr g, ArrRepr h, ArrRepr i)-type instance ArrRepr (a, b, c, d, e, f, g, h, i, j) = TupleRepr (ArrRepr a, ArrRepr b, ArrRepr c, ArrRepr d, ArrRepr e, ArrRepr f, ArrRepr g, ArrRepr h, ArrRepr i, ArrRepr j)-type instance ArrRepr (a, b, c, d, e, f, g, h, i, j, k) = TupleRepr (ArrRepr a, ArrRepr b, ArrRepr c, ArrRepr d, ArrRepr e, ArrRepr f, ArrRepr g, ArrRepr h, ArrRepr i, ArrRepr j, ArrRepr k)-type instance ArrRepr (a, b, c, d, e, f, g, h, i, j, k, l) = TupleRepr (ArrRepr a, ArrRepr b, ArrRepr c, ArrRepr d, ArrRepr e, ArrRepr f, ArrRepr g, ArrRepr h, ArrRepr i, ArrRepr j, ArrRepr k, ArrRepr l)-type instance ArrRepr (a, b, c, d, e, f, g, h, i, j, k, l, m) = TupleRepr (ArrRepr a, ArrRepr b, ArrRepr c, ArrRepr d, ArrRepr e, ArrRepr f, ArrRepr g, ArrRepr h, ArrRepr i, ArrRepr j, ArrRepr k, ArrRepr l, ArrRepr m)-type instance ArrRepr (a, b, c, d, e, f, g, h, i, j, k, l, m, n) = TupleRepr (ArrRepr a, ArrRepr b, ArrRepr c, ArrRepr d, ArrRepr e, ArrRepr f, ArrRepr g, ArrRepr h, ArrRepr i, ArrRepr j, ArrRepr k, ArrRepr l, ArrRepr m, ArrRepr n)-type instance ArrRepr (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) = TupleRepr (ArrRepr a, ArrRepr b, ArrRepr c, ArrRepr d, ArrRepr e, ArrRepr f, ArrRepr g, ArrRepr h, ArrRepr i, ArrRepr j, ArrRepr k, ArrRepr l, ArrRepr m, ArrRepr n, ArrRepr o)--type IsAtuple = IsProduct Arrays--fromAtuple :: IsAtuple tup => tup -> TupleRepr tup-fromAtuple = fromProd (Proxy :: Proxy Arrays)--toAtuple :: IsAtuple tup => TupleRepr tup -> tup-toAtuple = toProd (Proxy :: Proxy Arrays)---- Array type reification----data ArraysR arrs where- ArraysRunit :: ArraysR ()- ArraysRarray :: (Shape sh, Elt e) => ArraysR (Array sh e)- ArraysRpair :: ArraysR arrs1 -> ArraysR arrs2 -> ArraysR (arrs1, arrs2)--data ArraysFlavour arrs where- ArraysFunit :: ArraysFlavour ()- ArraysFarray :: (Shape sh, Elt e) => ArraysFlavour (Array sh e)- ArraysFtuple :: (IsAtuple arrs, ArrRepr arrs ~ (l,r)) => ArraysFlavour arrs---- | 'Arrays' consists of nested tuples of individual 'Array's, currently up to--- 15-elements wide. Accelerate computations can thereby return multiple--- results.----class (Typeable a, Typeable (ArrRepr a)) => Arrays a where- arrays :: a {- dummy -} -> ArraysR (ArrRepr a)- flavour :: a {- dummy -} -> ArraysFlavour a- --- toArr :: ArrRepr a -> a- fromArr :: a -> ArrRepr a---instance Arrays () where- arrays _ = ArraysRunit- flavour _ = ArraysFunit- --- toArr = id- fromArr = id--instance (Shape sh, Elt e) => Arrays (Array sh e) where- arrays _ = ArraysRarray- flavour _ = ArraysFarray- --- toArr = id- fromArr = id--instance (Arrays a, Arrays b) => Arrays (a, b) where- arrays _ = ArraysRpair (ArraysRpair ArraysRunit (arrays (undefined::a))) (arrays (undefined::b))- flavour _ = ArraysFtuple- --- toArr (((),a), b) = (toArr a, toArr b)- fromArr (a, b) = (((), fromArr a), fromArr b)--instance (Arrays a, Arrays b, Arrays c) => Arrays (a, b, c) where- arrays _ = ArraysRpair (arrays (undefined :: (a, b))) (arrays (undefined::c))- flavour _ = ArraysFtuple- --- toArr (ab, c) = let (a, b) = toArr ab in (a, b, toArr c)- fromArr (a, b, c) = (fromArr (a, b), fromArr c)--instance (Arrays a, Arrays b, Arrays c, Arrays d) => Arrays (a, b, c, d) where- arrays _ = ArraysRpair (arrays (undefined :: (a, b, c))) (arrays (undefined::d))- flavour _ = ArraysFtuple- --- toArr (abc, d) = let (a, b, c) = toArr abc in (a, b, c, toArr d)- fromArr (a, b, c, d) = (fromArr (a, b, c), fromArr d)--instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e) => Arrays (a, b, c, d, e) where- arrays _ = ArraysRpair (arrays (undefined :: (a, b, c, d))) (arrays (undefined::e))- flavour _ = ArraysFtuple- --- toArr (abcd, e) = let (a, b, c, d) = toArr abcd in (a, b, c, d, toArr e)- fromArr (a, b, c, d, e) = (fromArr (a, b, c, d), fromArr e)--instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f)- => Arrays (a, b, c, d, e, f) where- arrays _ = ArraysRpair (arrays (undefined :: (a, b, c, d, e))) (arrays (undefined::f))- flavour _ = ArraysFtuple- --- toArr (abcde, f) = let (a, b, c, d, e) = toArr abcde in (a, b, c, d, e, toArr f)- fromArr (a, b, c, d, e, f) = (fromArr (a, b, c, d, e), fromArr f)--instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g)- => Arrays (a, b, c, d, e, f, g) where- arrays _ = ArraysRpair (arrays (undefined :: (a, b, c, d, e, f))) (arrays (undefined::g))- flavour _ = ArraysFtuple- --- toArr (abcdef, g) = let (a, b, c, d, e, f) = toArr abcdef in (a, b, c, d, e, f, toArr g)- fromArr (a, b, c, d, e, f, g) = (fromArr (a, b, c, d, e, f), fromArr g)--instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h)- => Arrays (a, b, c, d, e, f, g, h) where- arrays _ = ArraysRpair (arrays (undefined :: (a, b, c, d, e, f, g))) (arrays (undefined::h))- flavour _ = ArraysFtuple- --- toArr (abcdefg, h) = let (a, b, c, d, e, f, g) = toArr abcdefg in (a, b, c, d, e, f, g, toArr h)- fromArr (a, b, c, d, e, f, g, h) = (fromArr (a, b, c, d, e, f, g), fromArr h)--instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i)- => Arrays (a, b, c, d, e, f, g, h, i) where- arrays _ = ArraysRpair (arrays (undefined :: (a, b, c, d, e, f, g, h))) (arrays (undefined::i))- flavour _ = ArraysFtuple- --- toArr (abcdefgh, i) = let (a, b, c, d, e, f, g, h) = toArr abcdefgh in (a, b, c, d, e, f, g, h, toArr i)- fromArr (a, b, c, d, e, f, g, h, i) = (fromArr (a, b, c, d, e, f, g, h), fromArr i)--instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j)- => Arrays (a, b, c, d, e, f, g, h, i, j) where- arrays _ = ArraysRpair (arrays (undefined :: (a, b, c, d, e, f, g, h, i))) (arrays (undefined::j))- flavour _ = ArraysFtuple- --- toArr (abcdefghi, j) = let (a, b, c, d, e, f, g, h, i) = toArr abcdefghi in (a, b, c, d, e, f, g, h, i, toArr j)- fromArr (a, b, c, d, e, f, g, h, i, j) = (fromArr (a, b, c, d, e, f, g, h, i), fromArr j)--instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k)- => Arrays (a, b, c, d, e, f, g, h, i, j, k) where- arrays _ = ArraysRpair (arrays (undefined :: (a, b, c, d, e, f, g, h, i, j))) (arrays (undefined::k))- flavour _ = ArraysFtuple- --- toArr (abcdefghij, k) = let (a, b, c, d, e, f, g, h, i, j) = toArr abcdefghij in (a, b, c, d, e, f, g, h, i, j, toArr k)- fromArr (a, b, c, d, e, f, g, h, i, j, k) = (fromArr (a, b, c, d, e, f, g, h, i, j), fromArr k)--instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l)- => Arrays (a, b, c, d, e, f, g, h, i, j, k, l) where- arrays _ = ArraysRpair (arrays (undefined :: (a, b, c, d, e, f, g, h, i, j, k))) (arrays (undefined::l))- flavour _ = ArraysFtuple- --- toArr (abcdefghijk, l) = let (a, b, c, d, e, f, g, h, i, j, k) = toArr abcdefghijk in (a, b, c, d, e, f, g, h, i, j, k, toArr l)- fromArr (a, b, c, d, e, f, g, h, i, j, k, l) = (fromArr (a, b, c, d, e, f, g, h, i, j, k), fromArr l)--instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l, Arrays m)- => Arrays (a, b, c, d, e, f, g, h, i, j, k, l, m) where- arrays _ = ArraysRpair (arrays (undefined :: (a, b, c, d, e, f, g, h, i, j, k, l))) (arrays (undefined::m))- flavour _ = ArraysFtuple- --- toArr (abcdefghijkl, m) = let (a, b, c, d, e, f, g, h, i, j, k, l) = toArr abcdefghijkl in (a, b, c, d, e, f, g, h, i, j, k, l, toArr m)- fromArr (a, b, c, d, e, f, g, h, i, j, k, l, m) = (fromArr (a, b, c, d, e, f, g, h, i, j, k, l), fromArr m)--instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l, Arrays m, Arrays n)- => Arrays (a, b, c, d, e, f, g, h, i, j, k, l, m, n) where- arrays _ = ArraysRpair (arrays (undefined :: (a, b, c, d, e, f, g, h, i, j, k, l, m))) (arrays (undefined::n))- flavour _ = ArraysFtuple- --- toArr (abcdefghijklm, n) = let (a, b, c, d, e, f, g, h, i, j, k, l, m) = toArr abcdefghijklm in (a, b, c, d, e, f, g, h, i, j, k, l, m, toArr n)- fromArr (a, b, c, d, e, f, g, h, i, j, k, l, m, n) = (fromArr (a, b, c, d, e, f, g, h, i, j, k, l, m), fromArr n)--instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l, Arrays m, Arrays n, Arrays o)- => Arrays (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) where- arrays _ = ArraysRpair (arrays (undefined :: (a, b, c, d, e, f, g, h, i, j, k, l, m, n))) (arrays (undefined::o))- flavour _ = ArraysFtuple- --- toArr (abcdefghijklmn, o) = let (a, b, c, d, e, f, g, h, i, j, k, l, m, n) = toArr abcdefghijklmn in (a, b, c, d, e, f, g, h, i, j, k, l, m, n, toArr o)- fromArr (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) = (fromArr (a, b, c, d, e, f, g, h, i, j, k, l, m, n), fromArr o)----- {-# RULES--- "fromArr/toArr" forall a. fromArr (toArr a) = a--- "toArr/fromArr" forall a. toArr (fromArr a) = a--- #-}----- Tuple representation--- ------------------------ |The tuple representation is equivalent to the product representation.----type TupleRepr a = ProdRepr a---- |We represent tuples as heterogeneous lists, typed by a type list.----data Tuple c t where- NilTup :: Tuple c ()- SnocTup :: Elt t => Tuple c s -> c t -> Tuple c (s, t)---- TLM: It is irritating that we need a separate data type for tuples of scalars--- vs. arrays, purely to carry the class constraint.------ | Tuples of Arrays. Note that this carries the `Arrays` class--- constraint rather than `Elt` in the case of tuples of scalars.----data Atuple c t where- NilAtup :: Atuple c ()- SnocAtup :: Arrays a => Atuple c s -> c a -> Atuple c (s, a)---- |Tuple reification----type TupleR a = ProdR Elt a--tuple :: IsTuple tup => {- dummy -} tup -> TupleR (TupleRepr tup)-tuple = prod (Proxy :: Proxy Elt)----- | Dense, regular, multi-dimensional arrays.------ The 'Array' is the core computational unit of Accelerate; all programs in--- Accelerate take zero or more arrays as input and produce one or more arrays--- as output. The 'Array' type has two type parameters:------ * /sh/: is the shape of the array, tracking the dimensionality and extent of--- each dimension of the array; for example, 'DIM1' for one-dimensional--- 'Vector's, 'DIM2' for two-dimensional matrices, and so on.--- * /e/: represents the type of each element of the array; for example,--- 'Int', 'Float', et cetera.------ Array data is store unboxed in an unzipped struct-of-array representation.--- Elements are laid out in row-major order (the right-most index of a 'Shape'--- is the fastest varying). The allowable array element types are members of the--- 'Elt' class, which roughly consists of:------ * Signed and unsigned integers (8, 16, 32, and 64-bits wide).--- * Floating point numbers (single and double precision)--- * 'Char'--- * 'Bool'--- * ()--- * Shapes formed from 'Z' and (':.')--- * Nested tuples of all of these, currently up to 15-elements wide.------ Note that 'Array' itself is not an allowable element type---there are no--- nested arrays in Accelerate, regular arrays only!------ If device and host memory are separate, arrays will be transferred to the--- device when necessary (possibly asynchronously and in parallel with other--- tasks) and cached on the device if sufficient memory is available. Arrays are--- made available to embedded language computations via--- 'Data.Array.Accelerate.use'.------ Section "Getting data in" lists functions for getting data into and out of--- the 'Array' type.----data Array sh e where- Array :: (Shape sh, Elt e)- => EltRepr sh -- extent of dimensions = shape- -> ArrayData (EltRepr e) -- array payload- -> Array sh e--deriving instance Typeable Array--instance (Eq sh, Eq e) => Eq (Array sh e) where- arr1@Array{} == arr2@Array{} = shape arr1 == shape arr2 && toList arr1 == toList arr2- arr1@Array{} /= arr2@Array{} = shape arr1 /= shape arr2 || toList arr1 /= toList arr2--#if __GLASGOW_HASKELL__ >= 710--- Convert an array to a string, using specialised instances for dimensions--- zero, one, and two. These are available for ghc-7.10 and later only (earlier--- versions of ghc would require -XIncoherentInstances in the client module).------ TODO:--- * Make special formatting optional? It is more difficult to copy/paste the--- result, for example. Also it does not look good if the matrix row does--- not fit on a single line.--- * The AST pretty printer does not use these instances----instance Show (Scalar e) where- show arr@Array{} =- "Scalar Z " ++ show (toList arr)--instance Show (Vector e) where- show arr@Array{} =- "Vector (" ++ showShape (shape arr) ++ ") " ++ show (toList arr)--instance Show (Array DIM2 e) where- show arr@Array{} =- "Matrix (" ++ showShape (shape arr) ++ ") " ++ showMat (toMatrix (toList arr))- where- Z :. _ :. cols = shape arr- toMatrix [] = []- toMatrix xs = let (r,rs) = splitAt cols xs- in r : toMatrix rs- --- showMat [] = "[]"- showMat mat = "\n " ++ ppMat (map (map show) mat)- --- ppRow row = concatMap (++",") row- ppMat mat = "[" ++ init (intercalate "\n " (map ppRow (ppColumns mat))) ++ "]"- ppColumns = transpose . map (\col -> pad (width col) col) . transpose- where- extra = 0- width = maximum . map length- pad w = map (\x -> replicate (w - length x + extra) ' ' ++ x)-#endif---- This is a bit unfortunate, but we need to use an INCOHERENT instance because--- GHC can't determine that with the above specialisations, a DIM3+ instance--- covers all remaining possibilities, and lacking a general instance is--- problematic for operations which want a 'Show (Array sh e)' constraint.--- Furthermore, those clients are likely to pick this instance, rather than the--- more specific ones above, which is (perhaps) a little unfortunate.----instance {-# INCOHERENT #-} Show (Array sh e) where- show arr@Array{} =- "Array (" ++ showShape (shape arr) ++ ") " ++ show (toList arr)--instance Elt e => IsList (Vector e) where- type Item (Vector e) = e- toList = toList- fromListN n xs = fromList (Z:.n) xs- fromList xs = GHC.fromListN (length xs) xs--instance NFData (Array sh e) where- rnf (Array sh ad) = Repr.size sh `seq` go arrayElt ad `seq` ()- where- go :: ArrayEltR e' -> ArrayData e' -> ()- go ArrayEltRunit AD_Unit = ()- go ArrayEltRint (AD_Int ua) = rnf ua- go ArrayEltRint8 (AD_Int8 ua) = rnf ua- go ArrayEltRint16 (AD_Int16 ua) = rnf ua- go ArrayEltRint32 (AD_Int32 ua) = rnf ua- go ArrayEltRint64 (AD_Int64 ua) = rnf ua- go ArrayEltRword (AD_Word ua) = rnf ua- go ArrayEltRword8 (AD_Word8 ua) = rnf ua- go ArrayEltRword16 (AD_Word16 ua) = rnf ua- go ArrayEltRword32 (AD_Word32 ua) = rnf ua- go ArrayEltRword64 (AD_Word64 ua) = rnf ua- go ArrayEltRcshort (AD_CShort ua) = rnf ua- go ArrayEltRcushort (AD_CUShort ua) = rnf ua- go ArrayEltRcint (AD_CInt ua) = rnf ua- go ArrayEltRcuint (AD_CUInt ua) = rnf ua- go ArrayEltRclong (AD_CLong ua) = rnf ua- go ArrayEltRculong (AD_CULong ua) = rnf ua- go ArrayEltRcllong (AD_CLLong ua) = rnf ua- go ArrayEltRcullong (AD_CULLong ua) = rnf ua- go ArrayEltRfloat (AD_Float ua) = rnf ua- go ArrayEltRdouble (AD_Double ua) = rnf ua- go ArrayEltRcfloat (AD_CFloat ua) = rnf ua- go ArrayEltRcdouble (AD_CDouble ua) = rnf ua- go ArrayEltRbool (AD_Bool ua) = rnf ua- go ArrayEltRchar (AD_Char ua) = rnf ua- go ArrayEltRcchar (AD_CChar ua) = rnf ua- go ArrayEltRcschar (AD_CSChar ua) = rnf ua- go ArrayEltRcuchar (AD_CUChar ua) = rnf ua- go (ArrayEltRpair r1 r2) (AD_Pair a1 a2) = go r1 a1 `seq` go r2 a2 `seq` ()----- |Scalars arrays hold a single element----type Scalar e = Array DIM0 e---- |Vectors are one-dimensional arrays----type Vector e = Array DIM1 e---- |Segment descriptor (vector of segment lengths).------ To represent nested one-dimensional arrays, we use a flat array of data--- values in conjunction with a /segment descriptor/, which stores the lengths--- of the subarrays.----type Segments i = Vector i---- Shorthand for common shape types----type DIM0 = Z-type DIM1 = DIM0:.Int-type DIM2 = DIM1:.Int-type DIM3 = DIM2:.Int-type DIM4 = DIM3:.Int-type DIM5 = DIM4:.Int-type DIM6 = DIM5:.Int-type DIM7 = DIM6:.Int-type DIM8 = DIM7:.Int-type DIM9 = DIM8:.Int----- Shape constraints and indexing--- ---------------------------------- |Shapes and indices of multi-dimensional arrays----class (Elt sh, Elt (Any sh), Repr.Shape (EltRepr sh), FullShape sh ~ sh, CoSliceShape sh ~ sh, SliceShape sh ~ Z)- => Shape sh where-- -- |Number of dimensions of a /shape/ or /index/ (>= 0).- rank :: sh -> Int-- -- |Total number of elements in an array of the given /shape/.- size :: sh -> Int-- -- |Empty /shape/.- empty :: sh-- -- |Magic value identifying elements ignored in 'permute'.- ignore :: sh-- -- |Yield the intersection of two shapes- intersect :: sh -> sh -> sh-- -- |Yield the union of two shapes- union :: sh -> sh -> sh-- -- |Map a multi-dimensional index into one in a linear, row-major- -- representation of the array (first argument is the /shape/, second- -- argument is the index).- toIndex :: sh -> sh -> Int-- -- |Inverse of 'toIndex'.- fromIndex :: sh -> Int -> sh-- -- |Iterate through the entire shape, applying the function; third argument- -- combines results and fourth is returned in case of an empty iteration- -- space; the index space is traversed in row-major order.- iter :: sh -> (sh -> a) -> (a -> a -> a) -> a -> a-- -- |Variant of 'iter' without an initial value- iter1 :: sh -> (sh -> a) -> (a -> a -> a) -> a-- -- |Convert a minpoint-maxpoint index into a /shape/.- rangeToShape :: (sh, sh) -> sh-- -- |Convert a /shape/ into a minpoint-maxpoint index.- shapeToRange :: sh -> (sh, sh)-- -- |Convert a shape to a list of dimensions.- shapeToList :: sh -> [Int]-- -- |Convert a list of dimensions into a shape.- listToShape :: [Int] -> sh-- -- | The slice index for slice specifier 'Any sh'- sliceAnyIndex :: sh -> Repr.SliceIndex (EltRepr (Any sh)) (EltRepr sh) () (EltRepr sh)-- -- | The slice index for specifying a slice with only the Z component projected- sliceNoneIndex :: sh -> Repr.SliceIndex (EltRepr sh) () (EltRepr sh) (EltRepr sh)-- rank = Repr.rank . fromElt- size = Repr.size . fromElt- empty = toElt Repr.empty- -- (#) must be individually defined, as it holds for all instances *except*- -- the one with the largest arity-- ignore = toElt Repr.ignore- intersect sh1 sh2 = toElt (Repr.intersect (fromElt sh1) (fromElt sh2))- union sh1 sh2 = toElt (Repr.union (fromElt sh1) (fromElt sh2))- fromIndex sh ix = toElt (Repr.fromIndex (fromElt sh) ix)- toIndex sh ix = Repr.toIndex (fromElt sh) (fromElt ix)-- iter sh f c r = Repr.iter (fromElt sh) (f . toElt) c r- iter1 sh f r = Repr.iter1 (fromElt sh) (f . toElt) r-- rangeToShape (low, high)- = toElt (Repr.rangeToShape (fromElt low, fromElt high))- shapeToRange ix- = let (low, high) = Repr.shapeToRange (fromElt ix)- in- (toElt low, toElt high)-- shapeToList = Repr.shapeToList . fromElt- listToShape = toElt . Repr.listToShape--instance Shape Z where- sliceAnyIndex _ = Repr.SliceNil- sliceNoneIndex _ = Repr.SliceNil--instance Shape sh => Shape (sh:.Int) where- sliceAnyIndex _ = Repr.SliceAll (sliceAnyIndex (undefined :: sh))- sliceNoneIndex _ = Repr.SliceFixed (sliceNoneIndex (undefined :: sh))---- | Slices, aka generalised indices, as /n/-tuples and mappings of slice--- indices to slices, co-slices, and slice dimensions----class (Elt sl, Shape (SliceShape sl), Shape (CoSliceShape sl), Shape (FullShape sl))- => Slice sl where- type SliceShape sl :: * -- the projected slice- type CoSliceShape sl :: * -- the complement of the slice- type FullShape sl :: * -- the combined dimension- sliceIndex :: sl {- dummy -} -> Repr.SliceIndex (EltRepr sl)- (EltRepr (SliceShape sl))- (EltRepr (CoSliceShape sl))- (EltRepr (FullShape sl))--instance Slice Z where- type SliceShape Z = Z- type CoSliceShape Z = Z- type FullShape Z = Z- sliceIndex _ = Repr.SliceNil--instance Slice sl => Slice (sl:.All) where- type SliceShape (sl:.All) = SliceShape sl :. Int- type CoSliceShape (sl:.All) = CoSliceShape sl- type FullShape (sl:.All) = FullShape sl :. Int- sliceIndex _ = Repr.SliceAll (sliceIndex (undefined :: sl))--instance Slice sl => Slice (sl:.Int) where- type SliceShape (sl:.Int) = SliceShape sl- type CoSliceShape (sl:.Int) = CoSliceShape sl :. Int- type FullShape (sl:.Int) = FullShape sl :. Int- sliceIndex _ = Repr.SliceFixed (sliceIndex (undefined :: sl))--instance Shape sh => Slice (Any sh) where- type SliceShape (Any sh) = sh- type CoSliceShape (Any sh) = Z- type FullShape (Any sh) = sh- sliceIndex _ = sliceAnyIndex (undefined :: sh)----- | Generalised array division, like above but use for splitting an array into--- many subarrays, as opposed to extracting a single subarray.----class (Slice (DivisionSlice sl))- => Division sl where- type DivisionSlice sl :: * -- the slice- slicesIndex :: slix ~ DivisionSlice sl- => sl {- dummy -}- -> Repr.SliceIndex (EltRepr slix)- (EltRepr (SliceShape slix))- (EltRepr (CoSliceShape slix))- (EltRepr (FullShape slix))--instance Division Z where- type DivisionSlice Z = Z- slicesIndex _ = Repr.SliceNil--instance Division sl => Division (sl:.All) where- type DivisionSlice (sl:.All) = DivisionSlice sl :. All- slicesIndex _ = Repr.SliceAll (slicesIndex (undefined :: sl))--instance Division sl => Division (sl:.Split) where- type DivisionSlice (sl:.Split) = DivisionSlice sl :. Int- slicesIndex _ = Repr.SliceFixed (slicesIndex (undefined :: sl))--instance Shape sh => Division (Any sh) where- type DivisionSlice (Any sh) = Any sh- slicesIndex _ = sliceAnyIndex (undefined :: sh)--instance (Shape sh, Slice sh) => Division (Divide sh) where- type DivisionSlice (Divide sh) = sh- slicesIndex _ = sliceNoneIndex (undefined :: sh)----- Array operations--- -------------------- |Yield an array's shape----shape :: Shape sh => Array sh e -> sh-shape (Array sh _) = toElt sh---- | Array indexing----infixl 9 !-(!) :: Array sh e -> sh -> e-{-# INLINE (!) #-}--- (Array sh adata) ! ix = toElt (adata `indexArrayData` index sh ix)--- FIXME: using this due to a bug in 6.10.x-(!) (Array sh adata) ix = toElt (adata `unsafeIndexArrayData` toIndex (toElt sh) ix)---- | Create an array from its representation function, applied at each index of--- the array.----fromFunction :: (Shape sh, Elt e) => sh -> (sh -> e) -> Array sh e-{-# INLINE fromFunction #-}-fromFunction sh f = adata `seq` Array (fromElt sh) adata- where- (adata, _) = runArrayData $ do- arr <- newArrayData (size sh)- let write ix = unsafeWriteArrayData arr (toIndex sh ix)- (fromElt (f ix))- iter sh write (>>) (return ())- return (arr, undefined)----- | Create a vector from the concatenation of the given list of vectors.----concatVectors :: Elt e => [Vector e] -> Vector e-{-# INLINE concatVectors #-}-concatVectors vs = adata `seq` Array ((), len) adata- where- offsets = scanl (+) 0 (map (size . shape) vs)- len = last offsets- (adata, _) = runArrayData $ do- arr <- newArrayData len- sequence_ [ unsafeWriteArrayData arr (i + k) (unsafeIndexArrayData ad i)- | (Array ((), n) ad, k) <- vs `zip` offsets- , i <- [0 .. n - 1] ]- return (arr, undefined)---- | Creates a new, uninitialized Accelerate array.----allocateArray :: (Shape sh, Elt e) => sh -> IO (Array sh e)-{-# INLINE allocateArray #-}-allocateArray sh = adata `seq` return (Array (fromElt sh) adata)- where- (adata, _) = runArrayData $ (,undefined) `fmap` newArrayData (size sh)----- | Convert elements of a list into an Accelerate 'Array'.------ This will generate a new multidimensional 'Array' of the specified shape and--- extent by consuming elements from the list and adding them to the array in--- row-major order.------ >>> fromList (Z:.10) [0..] :: Vector Int--- Vector (Z :. 10) [0,1,2,3,4,5,6,7,8,9]------ Note that we pull elements off the list lazily, so infinite lists are--- accepted:------ >>> fromList (Z:.5:.10) (repeat 0) :: Array DIM2 Float--- Matrix (Z :. 5 :. 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]------ You can also make use of the @OverloadedLists@ extension to produce--- one-dimensional vectors from a /finite/ list.------ >>> [0..9] :: Vector Int--- Vector (Z :. 10) [0,1,2,3,4,5,6,7,8,9]------ Note that this requires first traversing the list to determine its length,--- and then traversing it a second time to collect the elements into the array,--- thus forcing the spine of the list to be manifest on the heap.----fromList :: (Shape sh, Elt e) => sh -> [e] -> Array sh e-{-# INLINE fromList #-}-fromList sh xs = adata `seq` Array (fromElt sh) adata- where- -- Assume the array is in dense row-major order. This is safe because- -- otherwise backends would not be able to directly memcpy.- --- !n = size sh- (adata, _) = runArrayData $ do- arr <- newArrayData n- let go !i _ | i >= n = return ()- go !i (v:vs) = unsafeWriteArrayData arr i (fromElt v) >> go (i+1) vs- go _ [] = error "Data.Array.Accelerate.fromList: not enough input data"- --- go 0 xs- return (arr, undefined)---- | Convert an accelerated 'Array' to a list in row-major order.----toList :: forall sh e. Array sh e -> [e]-{-# INLINE toList #-}-toList (Array sh adata) = go 0- where- -- Assume underling array is in row-major order. This is safe because- -- otherwise backends would not be able to directly memcpy.- --- !n = Repr.size sh- go !i | i >= n = []- | otherwise = toElt (adata `unsafeIndexArrayData` i) : go (i+1)---- | Nicely format a shape as a string----showShape :: Shape sh => sh -> String-showShape = foldr (\sh str -> str ++ " :. " ++ show sh) "Z" . shapeToList---- | Project the shape of a slice from the full shape.----sliceShape :: forall slix co sl dim. (Shape sl, Shape dim)- => Repr.SliceIndex slix (EltRepr sl) co (EltRepr dim)- -> dim- -> sl-sliceShape slix = toElt . Repr.sliceShape slix . fromElt---- | Enumerate all slices within a given bound. The innermost dimension--- changes most rapidly.------ Example:------ > let slix = sliceIndex (undefined :: Z :. Int :. Int :. All)--- > sh = Z :. 2 :. 3 :. 1 :: DIM3--- > in--- > enumSlices slix sh :: [ Z :. Int :. Int :. All ]----enumSlices :: forall slix co sl dim. (Elt slix, Elt dim)- => Repr.SliceIndex (EltRepr slix) sl co (EltRepr dim)- -> dim -- Bounds- -> [slix] -- All slices within bounds.-enumSlices slix = map toElt . Repr.enumSlices slix . fromElt-
− Data/Array/Accelerate/Array/Unique.hs
@@ -1,98 +0,0 @@-{-# OPTIONS_HADDOCK hide #-}--- |--- Module : Data.Array.Accelerate.Array.Unique--- Copyright : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell, Robert Clifton-Everest--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Array.Unique (-- UniqueArray(..),- newUniqueArray,- withUniqueArrayPtr,- unsafeUniqueArrayPtr,- touchUniqueArray,--) where---- library-import Control.Applicative-import Control.Concurrent.Unique-import Control.DeepSeq-import Foreign.ForeignPtr-import Foreign.ForeignPtr.Unsafe-import Foreign.Ptr-import Prelude---- friends-import Data.Array.Accelerate.Lifetime----- | A uniquely identifiable array.------ For the purposes of memory management, we use arrays as keys in a table. For--- this reason we need a way to uniquely identify each array we create. We do--- this by attaching a unique identifier to each array.------ Note: [Unique array strictness]------ The actual array data is in many cases unnecessary. For discrete memory--- backends such as for GPUs, we require the unique identifier to track the data--- in the remote memory space, but the data will in most cases never be copied--- back to the host. Thus, the array payload field is only lazily allocated, and--- we should be careful not to make this field overly strict.----data UniqueArray e = UniqueArray- { uniqueArrayId :: {-# UNPACK #-} !Unique- , uniqueArrayData :: {-# UNPACK #-} !(Lifetime (ForeignPtr e))- }--instance NFData (UniqueArray e) where- rnf (UniqueArray _ ad) = unsafeGetValue ad `seq` ()----- | Create a new UniqueArray----{-# INLINE newUniqueArray #-}-newUniqueArray :: ForeignPtr e -> IO (UniqueArray e)-newUniqueArray fp = UniqueArray <$> newUnique <*> newLifetime fp---- | Access the pointer backing the unique array.------ The array data is kept alive at least during the whole action, even if it is--- not directly used inside. Note that it is not safe to return the pointer from--- the action and use it after the action completes. All uses of the pointer--- should be inside the bracketed function.----{-# INLINE withUniqueArrayPtr #-}-withUniqueArrayPtr :: UniqueArray a -> (Ptr a -> IO b) -> IO b-withUniqueArrayPtr ua go =- withLifetime (uniqueArrayData ua) $ \fp -> withForeignPtr fp go----- | Extract the pointer backing the unique array.------ This is potentially unsafe, as if the argument is the last occurrence of this--- unique array then the finalisers will be run, potentially invalidating the--- plain pointer just obtained.------ See also: 'unsafeGetValue', 'unsafeForeignPtrToPtr'.----{-# INLINE unsafeUniqueArrayPtr #-}-unsafeUniqueArrayPtr :: UniqueArray a -> Ptr a-unsafeUniqueArrayPtr = unsafeForeignPtrToPtr . unsafeGetValue . uniqueArrayData----- | Ensure that the unique array is alive at the given place in a sequence of--- IO actions. Note that this does not force the actual array payload.------ See: [Unique array strictness]----{-# INLINE touchUniqueArray #-}-touchUniqueArray :: UniqueArray a -> IO ()-touchUniqueArray = touchLifetime . uniqueArrayData-
− Data/Array/Accelerate/Async.hs
@@ -1,103 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE UnboxedTuples #-}-{-# OPTIONS_HADDOCK hide #-}--- |--- Module : Data.Array.Accelerate.Async--- Copyright : [2009..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Async (-- -- * Asynchronous actions- Async,-- -- ** Spawning- async, asyncOn, asyncBound,-- -- ** Querying 'Async's- wait, poll, cancel,--) where--import Control.Exception-import Control.Concurrent--import GHC.Exts-import GHC.Conc-import GHC.IO----- We need to execute the main thread asynchronously to give finalisers a chance--- to run. Make sure to catch exceptions to avoid "blocked indefinitely on MVar"--- errors.----data Async a = Async {-# UNPACK #-} !ThreadId- {-# UNPACK #-} !(MVar (Either SomeException a))---- | Spawn an asynchronous action in a separate thread.----async :: IO a -> IO (Async a)-async = inline asyncUsing rawForkIO---- | Like 'async', but using 'forkOn' internally.----asyncOn :: Int -> IO a -> IO (Async a)-asyncOn cpu = inline asyncUsing (rawForkOn cpu)---- | Like 'async', but using 'forkOS' internally.----asyncBound :: IO a -> IO (Async a)-asyncBound = inline asyncUsing forkOS--asyncUsing :: (IO () -> IO ThreadId) -> IO a -> IO (Async a)-asyncUsing fork action = do- var <- newEmptyMVar- tid <- mask $ \restore ->- fork $ try (restore action) >>= putMVar var- return (Async tid var)---- | Block the calling thread until the computation completes, then return the--- result.----{-# INLINE wait #-}-wait :: Async a -> IO a-wait (Async _ var) = either throwIO return =<< readMVar var---- | Test whether the asynchronous computation has already completed. If so,--- return the result, else 'Nothing'.----{-# INLINE poll #-}-poll :: Async a -> IO (Maybe a)-poll (Async _ var) =- maybe (return Nothing) (either throwIO (return . Just)) =<< tryReadMVar var---- | Cancel a running asynchronous computation.----{-# INLINE cancel #-}-cancel :: Async a -> IO ()-cancel (Async tid _) = throwTo tid ThreadKilled----- A version of 'forkIO' that does not include the outer exception handler. This--- saves a bit of time when we will be installing our own exception handler.------ Stolen from Simon Marlow's 'async' package (BSD).----{-# INLINE rawForkIO #-}-rawForkIO :: IO () -> IO ThreadId-rawForkIO action = IO $ \s ->- case fork# action s of- (# s', tid #) -> (# s', ThreadId tid #)--{-# INLINE rawForkOn #-}-rawForkOn :: Int -> IO () -> IO ThreadId-rawForkOn (I# cpu) action = IO $ \s ->- case forkOn# cpu action s of- (# s', tid #) -> (# s', ThreadId tid #)-
− Data/Array/Accelerate/Classes.hs
@@ -1,52 +0,0 @@-{-# LANGUAGE NoImplicitPrelude #-}--- |--- Module : Data.Array.Accelerate.Classes--- Copyright : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)------ This module provides instances for standard Haskell 98 classes where--- possible, and provides new implementations of those classes where the types--- do not match.-----module Data.Array.Accelerate.Classes (-- -- *** Basic type classes- module Eq,- module Ord,- module Enum,- module Bounded,-- -- *** Numeric type classes- module Num,- module Real,- module Integral,- module Fractional,- module Floating,- module RealFrac,- module RealFloat,-- -- *** Numeric conversions- module FromIntegral,- module ToFloating,--) where--import Data.Array.Accelerate.Classes.Bounded as Bounded-import Data.Array.Accelerate.Classes.Enum as Enum-import Data.Array.Accelerate.Classes.Eq as Eq-import Data.Array.Accelerate.Classes.Floating as Floating-import Data.Array.Accelerate.Classes.Fractional as Fractional-import Data.Array.Accelerate.Classes.FromIntegral as FromIntegral-import Data.Array.Accelerate.Classes.Integral as Integral-import Data.Array.Accelerate.Classes.Num as Num-import Data.Array.Accelerate.Classes.Ord as Ord-import Data.Array.Accelerate.Classes.Real as Real-import Data.Array.Accelerate.Classes.RealFloat as RealFloat-import Data.Array.Accelerate.Classes.RealFrac as RealFrac-import Data.Array.Accelerate.Classes.ToFloating as ToFloating-
− Data/Array/Accelerate/Classes/Bounded.hs
@@ -1,214 +0,0 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}--- |--- Module : Data.Array.Accelerate.Classes.Bounded--- Copyright : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Classes.Bounded (-- Bounded,- P.minBound, P.maxBound,--) where--import Data.Array.Accelerate.Array.Sugar-import Data.Array.Accelerate.Smart-import Data.Array.Accelerate.Type--import qualified Prelude as P----- | Name the upper and lower limits of a type. Types which are not totally--- ordered may still have upper and lower bounds.----type Bounded a = (Elt a, P.Bounded (Exp a))---instance P.Bounded (Exp ()) where- minBound = constant ()- maxBound = constant ()--instance P.Bounded (Exp Int) where- minBound = mkMinBound- maxBound = mkMaxBound--instance P.Bounded (Exp Int8) where- minBound = mkMinBound- maxBound = mkMaxBound--instance P.Bounded (Exp Int16) where- minBound = mkMinBound- maxBound = mkMaxBound--instance P.Bounded (Exp Int32) where- minBound = mkMinBound- maxBound = mkMaxBound--instance P.Bounded (Exp Int64) where- minBound = mkMinBound- maxBound = mkMaxBound--instance P.Bounded (Exp Word) where- minBound = mkMinBound- maxBound = mkMaxBound--instance P.Bounded (Exp Word8) where- minBound = mkMinBound- maxBound = mkMaxBound--instance P.Bounded (Exp Word16) where- minBound = mkMinBound- maxBound = mkMaxBound--instance P.Bounded (Exp Word32) where- minBound = mkMinBound- maxBound = mkMaxBound--instance P.Bounded (Exp Word64) where- minBound = mkMinBound- maxBound = mkMaxBound--instance P.Bounded (Exp CShort) where- minBound = mkMinBound- maxBound = mkMaxBound--instance P.Bounded (Exp CUShort) where- minBound = mkMinBound- maxBound = mkMaxBound--instance P.Bounded (Exp CInt) where- minBound = mkMinBound- maxBound = mkMaxBound--instance P.Bounded (Exp CUInt) where- minBound = mkMinBound- maxBound = mkMaxBound--instance P.Bounded (Exp CLong) where- minBound = mkMinBound- maxBound = mkMaxBound--instance P.Bounded (Exp CULong) where- minBound = mkMinBound- maxBound = mkMaxBound--instance P.Bounded (Exp CLLong) where- minBound = mkMinBound- maxBound = mkMaxBound--instance P.Bounded (Exp CULLong) where- minBound = mkMinBound- maxBound = mkMaxBound--instance P.Bounded (Exp Bool) where- minBound = mkMinBound- maxBound = mkMaxBound--instance P.Bounded (Exp Char) where- minBound = mkMinBound- maxBound = mkMaxBound--instance P.Bounded (Exp CChar) where- minBound = mkMinBound- maxBound = mkMaxBound--instance P.Bounded (Exp CSChar) where- minBound = mkMinBound- maxBound = mkMaxBound--instance P.Bounded (Exp CUChar) where- minBound = mkMinBound- maxBound = mkMaxBound--instance ( P.Bounded (Exp a), P.Bounded (Exp b)- , Elt a, Elt b- ) => P.Bounded (Exp (a,b)) where- minBound = tup2 (P.minBound, P.minBound)- maxBound = tup2 (P.maxBound, P.maxBound)--instance ( P.Bounded (Exp a), P.Bounded (Exp b), P.Bounded (Exp c)- , Elt a, Elt b, Elt c- ) => P.Bounded (Exp (a,b,c)) where- minBound = tup3 (P.minBound, P.minBound, P.minBound)- maxBound = tup3 (P.maxBound, P.maxBound, P.maxBound)--instance ( P.Bounded (Exp a), P.Bounded (Exp b), P.Bounded (Exp c), P.Bounded (Exp d)- , Elt a, Elt b, Elt c, Elt d- ) => P.Bounded (Exp (a,b,c,d)) where- minBound = tup4 (P.minBound, P.minBound, P.minBound, P.minBound)- maxBound = tup4 (P.maxBound, P.maxBound, P.maxBound, P.maxBound)--instance ( P.Bounded (Exp a), P.Bounded (Exp b), P.Bounded (Exp c), P.Bounded (Exp d), P.Bounded (Exp e)- , Elt a, Elt b, Elt c, Elt d, Elt e- ) => P.Bounded (Exp (a,b,c,d,e)) where- minBound = tup5 (P.minBound, P.minBound, P.minBound, P.minBound, P.minBound)- maxBound = tup5 (P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound)--instance ( P.Bounded (Exp a), P.Bounded (Exp b), P.Bounded (Exp c), P.Bounded (Exp d), P.Bounded (Exp e), P.Bounded (Exp f)- , Elt a, Elt b, Elt c, Elt d, Elt e, Elt f- ) => P.Bounded (Exp (a,b,c,d,e,f)) where- minBound = tup6 (P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound)- maxBound = tup6 (P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound)--instance ( P.Bounded (Exp a), P.Bounded (Exp b), P.Bounded (Exp c), P.Bounded (Exp d), P.Bounded (Exp e), P.Bounded (Exp f), P.Bounded (Exp g)- , Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g- ) => P.Bounded (Exp (a,b,c,d,e,f,g)) where- minBound = tup7 (P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound)- maxBound = tup7 (P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound)--instance ( P.Bounded (Exp a), P.Bounded (Exp b), P.Bounded (Exp c), P.Bounded (Exp d), P.Bounded (Exp e), P.Bounded (Exp f), P.Bounded (Exp g), P.Bounded (Exp h)- , Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h- ) => P.Bounded (Exp (a,b,c,d,e,f,g,h)) where- minBound = tup8 (P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound)- maxBound = tup8 (P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound)--instance ( P.Bounded (Exp a), P.Bounded (Exp b), P.Bounded (Exp c), P.Bounded (Exp d), P.Bounded (Exp e), P.Bounded (Exp f), P.Bounded (Exp g), P.Bounded (Exp h), P.Bounded (Exp i)- , Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i- ) => P.Bounded (Exp (a,b,c,d,e,f,g,h,i)) where- minBound = tup9 (P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound)- maxBound = tup9 (P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound)--instance ( P.Bounded (Exp a), P.Bounded (Exp b), P.Bounded (Exp c), P.Bounded (Exp d), P.Bounded (Exp e), P.Bounded (Exp f), P.Bounded (Exp g), P.Bounded (Exp h), P.Bounded (Exp i), P.Bounded (Exp j)- , Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j- ) => P.Bounded (Exp (a,b,c,d,e,f,g,h,i,j)) where- minBound = tup10 (P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound)- maxBound = tup10 (P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound)--instance ( P.Bounded (Exp a), P.Bounded (Exp b), P.Bounded (Exp c), P.Bounded (Exp d), P.Bounded (Exp e), P.Bounded (Exp f), P.Bounded (Exp g), P.Bounded (Exp h), P.Bounded (Exp i), P.Bounded (Exp j), P.Bounded (Exp k)- , Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k- ) => P.Bounded (Exp (a,b,c,d,e,f,g,h,i,j,k)) where- minBound = tup11 (P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound)- maxBound = tup11 (P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound)--instance ( P.Bounded (Exp a), P.Bounded (Exp b), P.Bounded (Exp c), P.Bounded (Exp d), P.Bounded (Exp e), P.Bounded (Exp f), P.Bounded (Exp g), P.Bounded (Exp h), P.Bounded (Exp i), P.Bounded (Exp j), P.Bounded (Exp k), P.Bounded (Exp l)- , Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l- ) => P.Bounded (Exp (a,b,c,d,e,f,g,h,i,j,k,l)) where- minBound = tup12 (P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound)- maxBound = tup12 (P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound)--instance ( P.Bounded (Exp a), P.Bounded (Exp b), P.Bounded (Exp c), P.Bounded (Exp d), P.Bounded (Exp e), P.Bounded (Exp f), P.Bounded (Exp g), P.Bounded (Exp h), P.Bounded (Exp i), P.Bounded (Exp j), P.Bounded (Exp k), P.Bounded (Exp l), P.Bounded (Exp m)- , Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l, Elt m- ) => P.Bounded (Exp (a,b,c,d,e,f,g,h,i,j,k,l,m)) where- minBound = tup13 (P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound)- maxBound = tup13 (P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound)--instance ( P.Bounded (Exp a), P.Bounded (Exp b), P.Bounded (Exp c), P.Bounded (Exp d), P.Bounded (Exp e), P.Bounded (Exp f), P.Bounded (Exp g), P.Bounded (Exp h), P.Bounded (Exp i), P.Bounded (Exp j), P.Bounded (Exp k), P.Bounded (Exp l), P.Bounded (Exp m), P.Bounded (Exp n)- , Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l, Elt m, Elt n- ) => P.Bounded (Exp (a,b,c,d,e,f,g,h,i,j,k,l,m,n)) where- minBound = tup14 (P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound)- maxBound = tup14 (P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound)--instance ( P.Bounded (Exp a), P.Bounded (Exp b), P.Bounded (Exp c), P.Bounded (Exp d), P.Bounded (Exp e), P.Bounded (Exp f), P.Bounded (Exp g), P.Bounded (Exp h), P.Bounded (Exp i), P.Bounded (Exp j), P.Bounded (Exp k), P.Bounded (Exp l), P.Bounded (Exp m), P.Bounded (Exp n), P.Bounded (Exp o)- , Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l, Elt m, Elt n, Elt o- ) => P.Bounded (Exp (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o)) where- minBound = tup15 (P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound)- maxBound = tup15 (P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound)-
− Data/Array/Accelerate/Classes/Enum.hs
@@ -1,71 +0,0 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MonoLocalBinds #-}-{-# OPTIONS_GHC -fno-warn-missing-methods #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}--- |--- Module : Data.Array.Accelerate.Classes.Enum--- Copyright : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Classes.Enum (-- Enum,--) where--import Data.Array.Accelerate.Smart-import Text.Printf--import Prelude ( String, error )-import qualified Prelude as P----- | Operations over sequentially ordered types----type Enum a = P.Enum (Exp a)----- Instances of 'Enum' don't make sense in Accelerate at the moment. These are--- only provided to fulfil superclass constraints; e.g. Integral.----instance P.Enum (Exp a) where- toEnum = preludeError "toEnum"- fromEnum = preludeError "fromEnum"--preludeError :: String -> a-preludeError x = error (printf "Prelude.%s not supported Accelerate types" x)---- instance Enum (Exp Int8)--- instance Enum (Exp Int16)--- instance Enum (Exp Int32)--- instance Enum (Exp Int64)--- instance Enum (Exp Word)--- instance Enum (Exp Word8)--- instance Enum (Exp Word16)--- instance Enum (Exp Word32)--- instance Enum (Exp Word64)--- instance Enum (Exp CInt)--- instance Enum (Exp CUInt)--- instance Enum (Exp CLong)--- instance Enum (Exp CULong)--- instance Enum (Exp CLLong)--- instance Enum (Exp CULLong)--- instance Enum (Exp CShort)--- instance Enum (Exp CUShort)--- instance Enum (Exp Bool)--- instance Enum (Exp Char)--- instance Enum (Exp CChar)--- instance Enum (Exp CUChar)--- instance Enum (Exp CSChar)--- instance Enum (Exp Float)--- instance Enum (Exp Double)--- instance Enum (Exp CFloat)--- instance Enum (Exp CDouble)-
− Data/Array/Accelerate/Classes/Eq.hs
@@ -1,304 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}--- |--- Module : Data.Array.Accelerate.Classes.Eq--- Copyright : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Classes.Eq (-- Eq(..),- (&&),- (||),- not,--) where--import Data.Array.Accelerate.Array.Sugar-import Data.Array.Accelerate.Smart-import Data.Array.Accelerate.Type--import Text.Printf-import Prelude ( String, error)-import qualified Prelude as P---infix 4 ==-infix 4 /=---- | Conjunction: True if both arguments are true. This is a short-circuit--- operator, so the second argument will be evaluated only if the first is true.----infixr 3 &&-(&&) :: Exp Bool -> Exp Bool -> Exp Bool-(&&) = mkLAnd---- | Disjunction: True if either argument is true. This is a short-circuit--- operator, so the second argument will be evaluated only if the first is--- false.----infixr 2 ||-(||) :: Exp Bool -> Exp Bool -> Exp Bool-(||) = mkLOr---- | Logical negation----not :: Exp Bool -> Exp Bool-not = mkLNot----- | The 'Eq' class defines equality '==' and inequality '/=' for scalar--- Accelerate expressions.------ For convenience, we include 'Elt' as a superclass.----class Elt a => Eq a where- (==) :: Exp a -> Exp a -> Exp Bool- (/=) :: Exp a -> Exp a -> Exp Bool- {-# MINIMAL (==) | (/=) #-}- x == y = mkLNot (x /= y)- x /= y = mkLNot (x == y)---instance Eq () where- _ == _ = constant True -- force arguments?- _ /= _ = constant False -- force arguments?--instance Eq Int where- (==) = mkEq- (/=) = mkNEq--instance Eq Int8 where- (==) = mkEq- (/=) = mkNEq--instance Eq Int16 where- (==) = mkEq- (/=) = mkNEq--instance Eq Int32 where- (==) = mkEq- (/=) = mkNEq--instance Eq Int64 where- (==) = mkEq- (/=) = mkNEq--instance Eq Word where- (==) = mkEq- (/=) = mkNEq--instance Eq Word8 where- (==) = mkEq- (/=) = mkNEq--instance Eq Word16 where- (==) = mkEq- (/=) = mkNEq--instance Eq Word32 where- (==) = mkEq- (/=) = mkNEq--instance Eq Word64 where- (==) = mkEq- (/=) = mkNEq--instance Eq CInt where- (==) = mkEq- (/=) = mkNEq--instance Eq CUInt where- (==) = mkEq- (/=) = mkNEq--instance Eq CLong where- (==) = mkEq- (/=) = mkNEq--instance Eq CULong where- (==) = mkEq- (/=) = mkNEq--instance Eq CLLong where- (==) = mkEq- (/=) = mkNEq--instance Eq CULLong where- (==) = mkEq- (/=) = mkNEq--instance Eq CShort where- (==) = mkEq- (/=) = mkNEq--instance Eq CUShort where- (==) = mkEq- (/=) = mkNEq--instance Eq Bool where- (==) = mkEq- (/=) = mkNEq--instance Eq Char where- (==) = mkEq- (/=) = mkNEq--instance Eq CChar where- (==) = mkEq- (/=) = mkNEq--instance Eq CUChar where- (==) = mkEq- (/=) = mkNEq--instance Eq CSChar where- (==) = mkEq- (/=) = mkNEq--instance Eq Float where- (==) = mkEq- (/=) = mkNEq--instance Eq Double where- (==) = mkEq- (/=) = mkNEq--instance Eq CFloat where- (==) = mkEq- (/=) = mkNEq--instance Eq CDouble where- (==) = mkEq- (/=) = mkNEq--instance (Eq a, Eq b) => Eq (a, b) where- x == y = let (a1,b1) = untup2 x- (a2,b2) = untup2 y- in a1 == a2 && b1 == b2- x /= y = let (a1,b1) = untup2 x- (a2,b2) = untup2 y- in a1 /= a2 || b1 /= b2--instance (Eq a, Eq b, Eq c) => Eq (a, b, c) where- x == y = let (a1,b1,c1) = untup3 x- (a2,b2,c2) = untup3 y- in a1 == a2 && b1 == b2 && c1 == c2- x /= y = let (a1,b1,c1) = untup3 x- (a2,b2,c2) = untup3 y- in a1 /= a2 || b1 /= b2 || c1 /= c2--instance (Eq a, Eq b, Eq c, Eq d) => Eq (a, b, c, d) where- x == y = let (a1,b1,c1,d1) = untup4 x- (a2,b2,c2,d2) = untup4 y- in a1 == a2 && b1 == b2 && c1 == c2 && d1 == d2- x /= y = let (a1,b1,c1,d1) = untup4 x- (a2,b2,c2,d2) = untup4 y- in a1 /= a2 || b1 /= b2 || c1 /= c2 || d1 /= d2--instance (Eq a, Eq b, Eq c, Eq d, Eq e) => Eq (a, b, c, d, e) where- x == y = let (a1,b1,c1,d1,e1) = untup5 x- (a2,b2,c2,d2,e2) = untup5 y- in a1 == a2 && b1 == b2 && c1 == c2 && d1 == d2 && e1 == e2- x /= y = let (a1,b1,c1,d1,e1) = untup5 x- (a2,b2,c2,d2,e2) = untup5 y- in a1 /= a2 || b1 /= b2 || c1 /= c2 || d1 /= d2 || e1 /= e2--instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f) => Eq (a, b, c, d, e, f) where- x == y = let (a1,b1,c1,d1,e1,f1) = untup6 x- (a2,b2,c2,d2,e2,f2) = untup6 y- in a1 == a2 && b1 == b2 && c1 == c2 && d1 == d2 && e1 == e2 && f1 == f2- x /= y = let (a1,b1,c1,d1,e1,f1) = untup6 x- (a2,b2,c2,d2,e2,f2) = untup6 y- in a1 /= a2 || b1 /= b2 || c1 /= c2 || d1 /= d2 || e1 /= e2 || f1 /= f2--instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g) => Eq (a, b, c, d, e, f, g) where- x == y = let (a1,b1,c1,d1,e1,f1,g1) = untup7 x- (a2,b2,c2,d2,e2,f2,g2) = untup7 y- in a1 == a2 && b1 == b2 && c1 == c2 && d1 == d2 && e1 == e2 && f1 == f2 && g1 == g2- x /= y = let (a1,b1,c1,d1,e1,f1,g1) = untup7 x- (a2,b2,c2,d2,e2,f2,g2) = untup7 y- in a1 /= a2 || b1 /= b2 || c1 /= c2 || d1 /= d2 || e1 /= e2 || f1 /= f2 || g1 /= g2--instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g, Eq h) => Eq (a, b, c, d, e, f, g, h) where- x == y = let (a1,b1,c1,d1,e1,f1,g1,h1) = untup8 x- (a2,b2,c2,d2,e2,f2,g2,h2) = untup8 y- in a1 == a2 && b1 == b2 && c1 == c2 && d1 == d2 && e1 == e2 && f1 == f2 && g1 == g2 && h1 == h2- x /= y = let (a1,b1,c1,d1,e1,f1,g1,h1) = untup8 x- (a2,b2,c2,d2,e2,f2,g2,h2) = untup8 y- in a1 /= a2 || b1 /= b2 || c1 /= c2 || d1 /= d2 || e1 /= e2 || f1 /= f2 || g1 /= g2 || h1 /= h2--instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g, Eq h, Eq i) => Eq (a, b, c, d, e, f, g, h, i) where- x == y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1) = untup9 x- (a2,b2,c2,d2,e2,f2,g2,h2,i2) = untup9 y- in a1 == a2 && b1 == b2 && c1 == c2 && d1 == d2 && e1 == e2 && f1 == f2 && g1 == g2 && h1 == h2 && i1 == i2- x /= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1) = untup9 x- (a2,b2,c2,d2,e2,f2,g2,h2,i2) = untup9 y- in a1 /= a2 || b1 /= b2 || c1 /= c2 || d1 /= d2 || e1 /= e2 || f1 /= f2 || g1 /= g2 || h1 /= h2 || i1 /= i2--instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g, Eq h, Eq i, Eq j) => Eq (a, b, c, d, e, f, g, h, i, j) where- x == y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1) = untup10 x- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2) = untup10 y- in a1 == a2 && b1 == b2 && c1 == c2 && d1 == d2 && e1 == e2 && f1 == f2 && g1 == g2 && h1 == h2 && i1 == i2 && j1 == j2- x /= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1) = untup10 x- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2) = untup10 y- in a1 /= a2 || b1 /= b2 || c1 /= c2 || d1 /= d2 || e1 /= e2 || f1 /= f2 || g1 /= g2 || h1 /= h2 || i1 /= i2 || j1 /= j2--instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g, Eq h, Eq i, Eq j, Eq k) => Eq (a, b, c, d, e, f, g, h, i, j, k) where- x == y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1) = untup11 x- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2) = untup11 y- in a1 == a2 && b1 == b2 && c1 == c2 && d1 == d2 && e1 == e2 && f1 == f2 && g1 == g2 && h1 == h2 && i1 == i2 && j1 == j2 && k1 == k2- x /= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1) = untup11 x- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2) = untup11 y- in a1 /= a2 || b1 /= b2 || c1 /= c2 || d1 /= d2 || e1 /= e2 || f1 /= f2 || g1 /= g2 || h1 /= h2 || i1 /= i2 || j1 /= j2 || k1 /= k2--instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g, Eq h, Eq i, Eq j, Eq k, Eq l) => Eq (a, b, c, d, e, f, g, h, i, j, k, l) where- x == y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1) = untup12 x- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2) = untup12 y- in a1 == a2 && b1 == b2 && c1 == c2 && d1 == d2 && e1 == e2 && f1 == f2 && g1 == g2 && h1 == h2 && i1 == i2 && j1 == j2 && k1 == k2 && l1 == l2- x /= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1) = untup12 x- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2) = untup12 y- in a1 /= a2 || b1 /= b2 || c1 /= c2 || d1 /= d2 || e1 /= e2 || f1 /= f2 || g1 /= g2 || h1 /= h2 || i1 /= i2 || j1 /= j2 || k1 /= k2 || l1 /= l2--instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g, Eq h, Eq i, Eq j, Eq k, Eq l, Eq m) => Eq (a, b, c, d, e, f, g, h, i, j, k, l, m) where- x == y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1) = untup13 x- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2) = untup13 y- in a1 == a2 && b1 == b2 && c1 == c2 && d1 == d2 && e1 == e2 && f1 == f2 && g1 == g2 && h1 == h2 && i1 == i2 && j1 == j2 && k1 == k2 && l1 == l2 && m1 == m2- x /= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1) = untup13 x- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2) = untup13 y- in a1 /= a2 || b1 /= b2 || c1 /= c2 || d1 /= d2 || e1 /= e2 || f1 /= f2 || g1 /= g2 || h1 /= h2 || i1 /= i2 || j1 /= j2 || k1 /= k2 || l1 /= l2 || m1 /= m2--instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g, Eq h, Eq i, Eq j, Eq k, Eq l, Eq m, Eq n) => Eq (a, b, c, d, e, f, g, h, i, j, k, l, m, n) where- x == y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1) = untup14 x- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2) = untup14 y- in a1 == a2 && b1 == b2 && c1 == c2 && d1 == d2 && e1 == e2 && f1 == f2 && g1 == g2 && h1 == h2 && i1 == i2 && j1 == j2 && k1 == k2 && l1 == l2 && m1 == m2 && n1 == n2- x /= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1) = untup14 x- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2) = untup14 y- in a1 /= a2 || b1 /= b2 || c1 /= c2 || d1 /= d2 || e1 /= e2 || f1 /= f2 || g1 /= g2 || h1 /= h2 || i1 /= i2 || j1 /= j2 || k1 /= k2 || l1 /= l2 || m1 /= m2 || n1 /= n2--instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g, Eq h, Eq i, Eq j, Eq k, Eq l, Eq m, Eq n, Eq o) => Eq (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) where- x == y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,o1) = untup15 x- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2,o2) = untup15 y- in a1 == a2 && b1 == b2 && c1 == c2 && d1 == d2 && e1 == e2 && f1 == f2 && g1 == g2 && h1 == h2 && i1 == i2 && j1 == j2 && k1 == k2 && l1 == l2 && m1 == m2 && n1 == n2 && o1 == o2- x /= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,o1) = untup15 x- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2,o2) = untup15 y- in a1 /= a2 || b1 /= b2 || c1 /= c2 || d1 /= d2 || e1 /= e2 || f1 /= f2 || g1 /= g2 || h1 /= h2 || i1 /= i2 || j1 /= j2 || k1 /= k2 || l1 /= l2 || m1 /= m2 || n1 /= n2 || o1 /= o2----- Instances of 'Prelude.Eq' don't make sense with the standard signatures as--- the return type is fixed to 'Bool'. This instance is provided to provide--- a useful error message.----instance P.Eq (Exp a) where- (==) = preludeError "Eq.==" "(==)"- (/=) = preludeError "Eq./=" "(/=)"--preludeError :: String -> String -> a-preludeError x y = error (printf "Prelude.%s applied to EDSL types: use Data.Array.Accelerate.%s instead" x y)-
− Data/Array/Accelerate/Classes/Floating.hs
@@ -1,123 +0,0 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}--- |--- Module : Data.Array.Accelerate.Classes.Floating--- Copyright : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Classes.Floating (-- Floating,- P.pi,- P.sin, P.cos, P.tan,- P.asin, P.acos, P.atan,- P.sinh, P.cosh, P.tanh,- P.asinh, P.acosh, P.atanh,- P.exp,- P.sqrt,- P.log,- (P.**),- P.logBase,--) where--import Data.Array.Accelerate.Smart-import Data.Array.Accelerate.Type--import Data.Array.Accelerate.Classes.Fractional--import qualified Prelude as P----- | Trigonometric and hyperbolic functions and related functions----type Floating a = (Fractional a, P.Floating (Exp a))---instance P.Floating (Exp Float) where- pi = mkPi- sin = mkSin- cos = mkCos- tan = mkTan- asin = mkAsin- acos = mkAcos- atan = mkAtan- sinh = mkSinh- cosh = mkCosh- tanh = mkTanh- asinh = mkAsinh- acosh = mkAcosh- atanh = mkAtanh- exp = mkExpFloating- sqrt = mkSqrt- log = mkLog- (**) = mkFPow- logBase = mkLogBase--instance P.Floating (Exp Double) where- pi = mkPi- sin = mkSin- cos = mkCos- tan = mkTan- asin = mkAsin- acos = mkAcos- atan = mkAtan- sinh = mkSinh- cosh = mkCosh- tanh = mkTanh- asinh = mkAsinh- acosh = mkAcosh- atanh = mkAtanh- exp = mkExpFloating- sqrt = mkSqrt- log = mkLog- (**) = mkFPow- logBase = mkLogBase--instance P.Floating (Exp CFloat) where- pi = mkPi- sin = mkSin- cos = mkCos- tan = mkTan- asin = mkAsin- acos = mkAcos- atan = mkAtan- sinh = mkSinh- cosh = mkCosh- tanh = mkTanh- asinh = mkAsinh- acosh = mkAcosh- atanh = mkAtanh- exp = mkExpFloating- sqrt = mkSqrt- log = mkLog- (**) = mkFPow- logBase = mkLogBase--instance P.Floating (Exp CDouble) where- pi = mkPi- sin = mkSin- cos = mkCos- tan = mkTan- asin = mkAsin- acos = mkAcos- atan = mkAtan- sinh = mkSinh- cosh = mkCosh- tanh = mkTanh- asinh = mkAsinh- acosh = mkAcosh- atanh = mkAtanh- exp = mkExpFloating- sqrt = mkSqrt- log = mkLog- (**) = mkFPow- logBase = mkLogBase-
− Data/Array/Accelerate/Classes/Fractional.hs
@@ -1,55 +0,0 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}--- |--- Module : Data.Array.Accelerate.Classes.Fractional--- Copyright : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Classes.Fractional (-- Fractional,- (P./), P.recip, P.fromRational,--) where--import Data.Array.Accelerate.Smart-import Data.Array.Accelerate.Type--import Data.Array.Accelerate.Classes.Num--import Prelude ( (.), fromRational )-import qualified Prelude as P----- | Fractional numbers, supporting real division----type Fractional a = (Num a, P.Fractional (Exp a))---instance P.Fractional (Exp Float) where- (/) = mkFDiv- recip = mkRecip- fromRational = constant . fromRational--instance P.Fractional (Exp Double) where- (/) = mkFDiv- recip = mkRecip- fromRational = constant . fromRational--instance P.Fractional (Exp CFloat) where- (/) = mkFDiv- recip = mkRecip- fromRational = constant . fromRational--instance P.Fractional (Exp CDouble) where- (/) = mkFDiv- recip = mkRecip- fromRational = constant . fromRational-
− Data/Array/Accelerate/Classes/FromIntegral.hs
@@ -1,86 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE MonoLocalBinds #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE TemplateHaskell #-}--- |--- Module : Data.Array.Accelerate.Classes.FromIntegral--- Copyright : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Classes.FromIntegral (-- FromIntegral(..),--) where--import Data.Array.Accelerate.Smart-import Data.Array.Accelerate.Type--import Data.Array.Accelerate.Classes.Integral--import Language.Haskell.TH hiding ( Exp )-import Prelude hiding ( Integral )----- | Accelerate lacks a most-general lossless 'Prelude.Integer' type, which the--- standard 'Prelude.fromIntegral' function uses as an intermediate value when--- coercing from integral types. Instead, we use this class to capture a direct--- coercion between two types.----class FromIntegral a b where- -- | General coercion from integral types- fromIntegral :: Integral a => Exp a -> Exp b---- instance {-# OVERLAPPABLE #-} (Elt a, Elt b, IsIntegral a, IsNum b) => FromIntegral a b where--- fromIntegral = mkFromIntegral----- Reify in ghci:------ $( stringE . show =<< reify ''Thing )---- Generate all the standard instances explicitly. This gives us sensible error--- messages when we don't have an instance available, rather than a "can not--- deduce IsNum..." style error (which the user can do nothing about).----$(runQ $ do- let- -- Get all the types that our dictionaries reify- digItOut :: Name -> Q [Name]- digItOut name = do-#if __GLASGOW_HASKELL__ < 800- TyConI (DataD _ _ _ cons _) <- reify name-#else- TyConI (DataD _ _ _ _ cons _) <- reify name-#endif- let- dig (NormalC _ [(_, AppT (ConT n) (VarT _))]) = digItOut n-#if __GLASGOW_HASKELL__ < 800- dig (ForallC _ _ (NormalC _ [(_, AppT (ConT _) (ConT n))])) = return [n]-#else- dig (GadtC _ _ (AppT (ConT _) (ConT n))) = return [n]-#endif- dig _ = error "Unexpected case generating FromIntegral instances"- --- concat `fmap` mapM dig cons-- thFromIntegral :: Name -> Name -> Q Dec- thFromIntegral a b =- let- ty = AppT (AppT (ConT (mkName "FromIntegral")) (ConT a)) (ConT b)- dec = ValD (VarP (mkName "fromIntegral")) (NormalB (VarE (mkName "mkFromIntegral"))) []- in- instanceD (return []) (return ty) [return dec]- --- as <- digItOut ''IntegralType- bs <- digItOut ''NumType- sequence [ thFromIntegral a b | a <- as, b <- bs ]- )-
− Data/Array/Accelerate/Classes/Integral.hs
@@ -1,204 +0,0 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MonoLocalBinds #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}--- |--- Module : Data.Array.Accelerate.Classes.Integral--- Copyright : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Classes.Integral (-- Integral,- P.quot,- P.rem,- P.div,- P.mod,- P.quotRem,- P.divMod,--) where--import Data.Array.Accelerate.Smart-import Data.Array.Accelerate.Type--import Data.Array.Accelerate.Classes.Enum-import Data.Array.Accelerate.Classes.Real--import Prelude ( error )-import qualified Prelude as P----- | Integral numbers, supporting integral division----type Integral a = (Enum a, Real a, P.Integral (Exp a))---instance P.Integral (Exp Int) where- quot = mkQuot- rem = mkRem- div = mkIDiv- mod = mkMod- quotRem = mkQuotRem- divMod = mkDivMod- toInteger = error "Prelude.toInteger not supported for Accelerate types"--instance P.Integral (Exp Int8) where- quot = mkQuot- rem = mkRem- div = mkIDiv- mod = mkMod- quotRem = mkQuotRem- divMod = mkDivMod- toInteger = error "Prelude.toInteger not supported for Accelerate types"--instance P.Integral (Exp Int16) where- quot = mkQuot- rem = mkRem- div = mkIDiv- mod = mkMod- quotRem = mkQuotRem- divMod = mkDivMod- toInteger = error "Prelude.toInteger not supported for Accelerate types"--instance P.Integral (Exp Int32) where- quot = mkQuot- rem = mkRem- div = mkIDiv- mod = mkMod- quotRem = mkQuotRem- divMod = mkDivMod- toInteger = error "Prelude.toInteger not supported for Accelerate types"--instance P.Integral (Exp Int64) where- quot = mkQuot- rem = mkRem- div = mkIDiv- mod = mkMod- quotRem = mkQuotRem- divMod = mkDivMod- toInteger = error "Prelude.toInteger not supported for Accelerate types"--instance P.Integral (Exp Word) where- quot = mkQuot- rem = mkRem- div = mkIDiv- mod = mkMod- quotRem = mkQuotRem- divMod = mkDivMod- toInteger = error "Prelude.toInteger not supported for Accelerate types"--instance P.Integral (Exp Word8) where- quot = mkQuot- rem = mkRem- div = mkIDiv- mod = mkMod- quotRem = mkQuotRem- divMod = mkDivMod- toInteger = error "Prelude.toInteger not supported for Accelerate types"--instance P.Integral (Exp Word16) where- quot = mkQuot- rem = mkRem- div = mkIDiv- mod = mkMod- quotRem = mkQuotRem- divMod = mkDivMod- toInteger = error "Prelude.toInteger not supported for Accelerate types"--instance P.Integral (Exp Word32) where- quot = mkQuot- rem = mkRem- div = mkIDiv- mod = mkMod- quotRem = mkQuotRem- divMod = mkDivMod- toInteger = error "Prelude.toInteger not supported for Accelerate types"--instance P.Integral (Exp Word64) where- quot = mkQuot- rem = mkRem- div = mkIDiv- mod = mkMod- quotRem = mkQuotRem- divMod = mkDivMod- toInteger = error "Prelude.toInteger not supported for Accelerate types"--instance P.Integral (Exp CInt) where- quot = mkQuot- rem = mkRem- div = mkIDiv- mod = mkMod- quotRem = mkQuotRem- divMod = mkDivMod- toInteger = error "Prelude.toInteger not supported for Accelerate types"--instance P.Integral (Exp CUInt) where- quot = mkQuot- rem = mkRem- div = mkIDiv- mod = mkMod- quotRem = mkQuotRem- divMod = mkDivMod- toInteger = error "Prelude.toInteger not supported for Accelerate types"--instance P.Integral (Exp CLong) where- quot = mkQuot- rem = mkRem- div = mkIDiv- mod = mkMod- quotRem = mkQuotRem- divMod = mkDivMod- toInteger = error "Prelude.toInteger not supported for Accelerate types"--instance P.Integral (Exp CULong) where- quot = mkQuot- rem = mkRem- div = mkIDiv- mod = mkMod- quotRem = mkQuotRem- divMod = mkDivMod- toInteger = error "Prelude.toInteger not supported for Accelerate types"--instance P.Integral (Exp CLLong) where- quot = mkQuot- rem = mkRem- div = mkIDiv- mod = mkMod- quotRem = mkQuotRem- divMod = mkDivMod- toInteger = error "Prelude.toInteger not supported for Accelerate types"--instance P.Integral (Exp CULLong) where- quot = mkQuot- rem = mkRem- div = mkIDiv- mod = mkMod- quotRem = mkQuotRem- divMod = mkDivMod- toInteger = error "Prelude.toInteger not supported for Accelerate types"--instance P.Integral (Exp CShort) where- quot = mkQuot- rem = mkRem- div = mkIDiv- mod = mkMod- quotRem = mkQuotRem- divMod = mkDivMod- toInteger = error "Prelude.toInteger not supported for Accelerate types"--instance P.Integral (Exp CUShort) where- quot = mkQuot- rem = mkRem- div = mkIDiv- mod = mkMod- quotRem = mkQuotRem- divMod = mkDivMod- toInteger = error "Prelude.toInteger not supported for Accelerate types"-
− Data/Array/Accelerate/Classes/Num.hs
@@ -1,245 +0,0 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}--- |--- Module : Data.Array.Accelerate.Classes.Num--- Copyright : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Classes.Num (-- Num,- (P.+), (P.-), (P.*), P.negate, P.abs, P.signum, P.fromInteger,--) where--import Data.Array.Accelerate.Array.Sugar-import Data.Array.Accelerate.Smart-import Data.Array.Accelerate.Type--import Prelude ( (.) )-import qualified Prelude as P----- Should we replace 'Prelude.Num' with our own version, as we did with 'Ord'--- and 'Eq'? That might require clients to enable RebindableSyntax in order to--- get the correct 'fromInteger' (or miss out on special magic and need to add--- 'constant' instead).------ I think that we should, because otherwise we require FlexibleContexts and--- constraints are going to be inconsistent, e.g.:------ f :: (P.Num (Exp a), A.Ord a) => ...------ A light-weight alternative is the following constraint kind:------- | Basic numeric class----type Num a = (Elt a, P.Num (Exp a))---instance P.Num (Exp Int) where- (+) = mkAdd- (-) = mkSub- (*) = mkMul- negate = mkNeg- abs = mkAbs- signum = mkSig- fromInteger = constant . P.fromInteger--instance P.Num (Exp Int8) where- (+) = mkAdd- (-) = mkSub- (*) = mkMul- negate = mkNeg- abs = mkAbs- signum = mkSig- fromInteger = constant . P.fromInteger--instance P.Num (Exp Int16) where- (+) = mkAdd- (-) = mkSub- (*) = mkMul- negate = mkNeg- abs = mkAbs- signum = mkSig- fromInteger = constant . P.fromInteger--instance P.Num (Exp Int32) where- (+) = mkAdd- (-) = mkSub- (*) = mkMul- negate = mkNeg- abs = mkAbs- signum = mkSig- fromInteger = constant . P.fromInteger--instance P.Num (Exp Int64) where- (+) = mkAdd- (-) = mkSub- (*) = mkMul- negate = mkNeg- abs = mkAbs- signum = mkSig- fromInteger = constant . P.fromInteger--instance P.Num (Exp Word) where- (+) = mkAdd- (-) = mkSub- (*) = mkMul- negate = mkNeg- abs = mkAbs- signum = mkSig- fromInteger = constant . P.fromInteger--instance P.Num (Exp Word8) where- (+) = mkAdd- (-) = mkSub- (*) = mkMul- negate = mkNeg- abs = mkAbs- signum = mkSig- fromInteger = constant . P.fromInteger--instance P.Num (Exp Word16) where- (+) = mkAdd- (-) = mkSub- (*) = mkMul- negate = mkNeg- abs = mkAbs- signum = mkSig- fromInteger = constant . P.fromInteger--instance P.Num (Exp Word32) where- (+) = mkAdd- (-) = mkSub- (*) = mkMul- negate = mkNeg- abs = mkAbs- signum = mkSig- fromInteger = constant . P.fromInteger--instance P.Num (Exp Word64) where- (+) = mkAdd- (-) = mkSub- (*) = mkMul- negate = mkNeg- abs = mkAbs- signum = mkSig- fromInteger = constant . P.fromInteger--instance P.Num (Exp CInt) where- (+) = mkAdd- (-) = mkSub- (*) = mkMul- negate = mkNeg- abs = mkAbs- signum = mkSig- fromInteger = constant . P.fromInteger--instance P.Num (Exp CUInt) where- (+) = mkAdd- (-) = mkSub- (*) = mkMul- negate = mkNeg- abs = mkAbs- signum = mkSig- fromInteger = constant . P.fromInteger--instance P.Num (Exp CLong) where- (+) = mkAdd- (-) = mkSub- (*) = mkMul- negate = mkNeg- abs = mkAbs- signum = mkSig- fromInteger = constant . P.fromInteger--instance P.Num (Exp CULong) where- (+) = mkAdd- (-) = mkSub- (*) = mkMul- negate = mkNeg- abs = mkAbs- signum = mkSig- fromInteger = constant . P.fromInteger--instance P.Num (Exp CLLong) where- (+) = mkAdd- (-) = mkSub- (*) = mkMul- negate = mkNeg- abs = mkAbs- signum = mkSig- fromInteger = constant . P.fromInteger--instance P.Num (Exp CULLong) where- (+) = mkAdd- (-) = mkSub- (*) = mkMul- negate = mkNeg- abs = mkAbs- signum = mkSig- fromInteger = constant . P.fromInteger--instance P.Num (Exp CShort) where- (+) = mkAdd- (-) = mkSub- (*) = mkMul- negate = mkNeg- abs = mkAbs- signum = mkSig- fromInteger = constant . P.fromInteger--instance P.Num (Exp CUShort) where- (+) = mkAdd- (-) = mkSub- (*) = mkMul- negate = mkNeg- abs = mkAbs- signum = mkSig- fromInteger = constant . P.fromInteger--instance P.Num (Exp Float) where- (+) = mkAdd- (-) = mkSub- (*) = mkMul- negate = mkNeg- abs = mkAbs- signum = mkSig- fromInteger = constant . P.fromInteger--instance P.Num (Exp Double) where- (+) = mkAdd- (-) = mkSub- (*) = mkMul- negate = mkNeg- abs = mkAbs- signum = mkSig- fromInteger = constant . P.fromInteger--instance P.Num (Exp CFloat) where- (+) = mkAdd- (-) = mkSub- (*) = mkMul- negate = mkNeg- abs = mkAbs- signum = mkSig- fromInteger = constant . P.fromInteger--instance P.Num (Exp CDouble) where- (+) = mkAdd- (-) = mkSub- (*) = mkMul- negate = mkNeg- abs = mkAbs- signum = mkSig- fromInteger = constant . P.fromInteger-
− Data/Array/Accelerate/Classes/Ord.hs
@@ -1,493 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}--- |--- Module : Data.Array.Accelerate.Classes.Ord--- Copyright : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Classes.Ord (-- Ord(..),--) where--import Data.Array.Accelerate.Classes.Eq-import Data.Array.Accelerate.Smart-import Data.Array.Accelerate.Type--import Text.Printf-import Prelude ( ($), String, error)-import qualified Prelude as P---infix 4 <-infix 4 >-infix 4 <=-infix 4 >=---- | The 'Ord' class for totally ordered datatypes----class Eq a => Ord a where- {-# MINIMAL (<=) #-}- (<) :: Exp a -> Exp a -> Exp Bool- (>) :: Exp a -> Exp a -> Exp Bool- (<=) :: Exp a -> Exp a -> Exp Bool- (>=) :: Exp a -> Exp a -> Exp Bool- min :: Exp a -> Exp a -> Exp a- max :: Exp a -> Exp a -> Exp a- --- x < y = x /= y && x <= y- x > y = not (x <= y)- x <= y = not (x > y)- x >= y = x == y || not (x <= y)- min x y = Exp $ Cond (x <= y) x y- max x y = Exp $ Cond (x <= y) y x---instance Ord () where- (<) _ _ = constant False- (>) _ _ = constant False- (>=) _ _ = constant True- (<=) _ _ = constant True- min _ _ = constant ()- max _ _ = constant ()--instance Ord Int where- (<) = mkLt- (>) = mkGt- (<=) = mkLtEq- (>=) = mkGtEq- min = mkMin- max = mkMax--instance Ord Int8 where- (<) = mkLt- (>) = mkGt- (<=) = mkLtEq- (>=) = mkGtEq- min = mkMin- max = mkMax--instance Ord Int16 where- (<) = mkLt- (>) = mkGt- (<=) = mkLtEq- (>=) = mkGtEq- min = mkMin- max = mkMax--instance Ord Int32 where- (<) = mkLt- (>) = mkGt- (<=) = mkLtEq- (>=) = mkGtEq- min = mkMin- max = mkMax--instance Ord Int64 where- (<) = mkLt- (>) = mkGt- (<=) = mkLtEq- (>=) = mkGtEq- min = mkMin- max = mkMax--instance Ord Word where- (<) = mkLt- (>) = mkGt- (<=) = mkLtEq- (>=) = mkGtEq- min = mkMin- max = mkMax--instance Ord Word8 where- (<) = mkLt- (>) = mkGt- (<=) = mkLtEq- (>=) = mkGtEq- min = mkMin- max = mkMax--instance Ord Word16 where- (<) = mkLt- (>) = mkGt- (<=) = mkLtEq- (>=) = mkGtEq- min = mkMin- max = mkMax--instance Ord Word32 where- (<) = mkLt- (>) = mkGt- (<=) = mkLtEq- (>=) = mkGtEq- min = mkMin- max = mkMax--instance Ord Word64 where- (<) = mkLt- (>) = mkGt- (<=) = mkLtEq- (>=) = mkGtEq- min = mkMin- max = mkMax--instance Ord CInt where- (<) = mkLt- (>) = mkGt- (<=) = mkLtEq- (>=) = mkGtEq- min = mkMin- max = mkMax--instance Ord CUInt where- (<) = mkLt- (>) = mkGt- (<=) = mkLtEq- (>=) = mkGtEq- min = mkMin- max = mkMax--instance Ord CLong where- (<) = mkLt- (>) = mkGt- (<=) = mkLtEq- (>=) = mkGtEq- min = mkMin- max = mkMax--instance Ord CULong where- (<) = mkLt- (>) = mkGt- (<=) = mkLtEq- (>=) = mkGtEq- min = mkMin- max = mkMax--instance Ord CLLong where- (<) = mkLt- (>) = mkGt- (<=) = mkLtEq- (>=) = mkGtEq- min = mkMin- max = mkMax--instance Ord CULLong where- (<) = mkLt- (>) = mkGt- (<=) = mkLtEq- (>=) = mkGtEq- min = mkMin- max = mkMax--instance Ord CShort where- (<) = mkLt- (>) = mkGt- (<=) = mkLtEq- (>=) = mkGtEq- min = mkMin- max = mkMax--instance Ord CUShort where- (<) = mkLt- (>) = mkGt- (<=) = mkLtEq- (>=) = mkGtEq- min = mkMin- max = mkMax--instance Ord Bool where- (<) = mkLt- (>) = mkGt- (<=) = mkLtEq- (>=) = mkGtEq- min = mkMin- max = mkMax--instance Ord Char where- (<) = mkLt- (>) = mkGt- (<=) = mkLtEq- (>=) = mkGtEq- min = mkMin- max = mkMax--instance Ord CChar where- (<) = mkLt- (>) = mkGt- (<=) = mkLtEq- (>=) = mkGtEq- min = mkMin- max = mkMax--instance Ord CUChar where- (<) = mkLt- (>) = mkGt- (<=) = mkLtEq- (>=) = mkGtEq- min = mkMin- max = mkMax--instance Ord CSChar where- (<) = mkLt- (>) = mkGt- (<=) = mkLtEq- (>=) = mkGtEq- min = mkMin- max = mkMax--instance Ord Float where- (<) = mkLt- (>) = mkGt- (<=) = mkLtEq- (>=) = mkGtEq- min = mkMin- max = mkMax--instance Ord Double where- (<) = mkLt- (>) = mkGt- (<=) = mkLtEq- (>=) = mkGtEq- min = mkMin- max = mkMax--instance Ord CFloat where- (<) = mkLt- (>) = mkGt- (<=) = mkLtEq- (>=) = mkGtEq- min = mkMin- max = mkMax--instance Ord CDouble where- (<) = mkLt- (>) = mkGt- (<=) = mkLtEq- (>=) = mkGtEq- min = mkMin- max = mkMax--instance (Ord a, Ord b) => Ord (a, b) where- x <= y = let (a1,b1) = untup2 x- (a2,b2) = untup2 y- in a1 < a2 || (a1 == a2 && b1 <= b2)- x >= y = let (a1,b1) = untup2 x- (a2,b2) = untup2 y- in a1 > a2 || (a1 == a2 && b1 >= b2)- x < y = let (a1,b1) = untup2 x- (a2,b2) = untup2 y- in a1 < a2 || (a1 == a2 && b1 < b2)- x > y = let (a1,b1) = untup2 x- (a2,b2) = untup2 y- in a1 > a2 || (a1 == a2 && b1 > b2)--instance (Ord a, Ord b, Ord c) => Ord (a, b, c) where- x <= y = let (a1,b1,c1) = untup3 x; x' = tup2 (b1,c1)- (a2,b2,c2) = untup3 y; y' = tup2 (b2,c2)- in a1 < a2 || (a1 == a2 && x' <= y')- x >= y = let (a1,b1,c1) = untup3 x; x' = tup2 (b1,c1)- (a2,b2,c2) = untup3 y; y' = tup2 (b2,c2)- in a1 > a2 || (a1 == a2 && x' >= y')- x < y = let (a1,b1,c1) = untup3 x; x' = tup2 (b1,c1)- (a2,b2,c2) = untup3 y; y' = tup2 (b2,c2)- in a1 < a2 || (a1 == a2 && x' < y')- x > y = let (a1,b1,c1) = untup3 x; x' = tup2 (b1,c1)- (a2,b2,c2) = untup3 y; y' = tup2 (b2,c2)- in a1 > a2 || (a1 == a2 && x' > y')--instance (Ord a, Ord b, Ord c, Ord d) => Ord (a, b, c, d) where- x <= y = let (a1,b1,c1,d1) = untup4 x; x' = tup3 (b1,c1,d1)- (a2,b2,c2,d2) = untup4 y; y' = tup3 (b2,c2,d2)- in a1 < a2 || (a1 == a2 && x' <= y')- x >= y = let (a1,b1,c1,d1) = untup4 x; x' = tup3 (b1,c1,d1)- (a2,b2,c2,d2) = untup4 y; y' = tup3 (b2,c2,d2)- in a1 > a2 || (a1 == a2 && x' >= y')- x < y = let (a1,b1,c1,d1) = untup4 x; x' = tup3 (b1,c1,d1)- (a2,b2,c2,d2) = untup4 y; y' = tup3 (b2,c2,d2)- in a1 < a2 || (a1 == a2 && x' < y')- x > y = let (a1,b1,c1,d1) = untup4 x; x' = tup3 (b1,c1,d1)- (a2,b2,c2,d2) = untup4 y; y' = tup3 (b2,c2,d2)- in a1 > a2 || (a1 == a2 && x' > y')--instance (Ord a, Ord b, Ord c, Ord d, Ord e) => Ord (a, b, c, d, e) where- x <= y = let (a1,b1,c1,d1,e1) = untup5 x; x' = tup4 (b1,c1,d1,e1)- (a2,b2,c2,d2,e2) = untup5 y; y' = tup4 (b2,c2,d2,e2)- in a1 < a2 || (a1 == a2 && x' <= y')- x >= y = let (a1,b1,c1,d1,e1) = untup5 x; x' = tup4 (b1,c1,d1,e1)- (a2,b2,c2,d2,e2) = untup5 y; y' = tup4 (b2,c2,d2,e2)- in a1 > a2 || (a1 == a2 && x' >= y')- x < y = let (a1,b1,c1,d1,e1) = untup5 x; x' = tup4 (b1,c1,d1,e1)- (a2,b2,c2,d2,e2) = untup5 y; y' = tup4 (b2,c2,d2,e2)- in a1 < a2 || (a1 == a2 && x' < y')- x > y = let (a1,b1,c1,d1,e1) = untup5 x; x' = tup4 (b1,c1,d1,e1)- (a2,b2,c2,d2,e2) = untup5 y; y' = tup4 (b2,c2,d2,e2)- in a1 > a2 || (a1 == a2 && x' > y')--instance (Ord a, Ord b, Ord c, Ord d, Ord e, Ord f) => Ord (a, b, c, d, e, f) where- x <= y = let (a1,b1,c1,d1,e1,f1) = untup6 x; x' = tup5 (b1,c1,d1,e1,f1)- (a2,b2,c2,d2,e2,f2) = untup6 y; y' = tup5 (b2,c2,d2,e2,f2)- in a1 < a2 || (a1 == a2 && x' <= y')- x >= y = let (a1,b1,c1,d1,e1,f1) = untup6 x; x' = tup5 (b1,c1,d1,e1,f1)- (a2,b2,c2,d2,e2,f2) = untup6 y; y' = tup5 (b2,c2,d2,e2,f2)- in a1 > a2 || (a1 == a2 && x' >= y')- x < y = let (a1,b1,c1,d1,e1,f1) = untup6 x; x' = tup5 (b1,c1,d1,e1,f1)- (a2,b2,c2,d2,e2,f2) = untup6 y; y' = tup5 (b2,c2,d2,e2,f2)- in a1 < a2 || (a1 == a2 && x' < y')- x > y = let (a1,b1,c1,d1,e1,f1) = untup6 x; x' = tup5 (b1,c1,d1,e1,f1)- (a2,b2,c2,d2,e2,f2) = untup6 y; y' = tup5 (b2,c2,d2,e2,f2)- in a1 > a2 || (a1 == a2 && x' > y')--instance (Ord a, Ord b, Ord c, Ord d, Ord e, Ord f, Ord g) => Ord (a, b, c, d, e, f, g) where- x <= y = let (a1,b1,c1,d1,e1,f1,g1) = untup7 x; x' = tup6 (b1,c1,d1,e1,f1,g1)- (a2,b2,c2,d2,e2,f2,g2) = untup7 y; y' = tup6 (b2,c2,d2,e2,f2,g2)- in a1 < a2 || (a1 == a2 && x' <= y')- x >= y = let (a1,b1,c1,d1,e1,f1,g1) = untup7 x; x' = tup6 (b1,c1,d1,e1,f1,g1)- (a2,b2,c2,d2,e2,f2,g2) = untup7 y; y' = tup6 (b2,c2,d2,e2,f2,g2)- in a1 > a2 || (a1 == a2 && x' >= y')- x < y = let (a1,b1,c1,d1,e1,f1,g1) = untup7 x; x' = tup6 (b1,c1,d1,e1,f1,g1)- (a2,b2,c2,d2,e2,f2,g2) = untup7 y; y' = tup6 (b2,c2,d2,e2,f2,g2)- in a1 < a2 || (a1 == a2 && x' < y')- x > y = let (a1,b1,c1,d1,e1,f1,g1) = untup7 x; x' = tup6 (b1,c1,d1,e1,f1,g1)- (a2,b2,c2,d2,e2,f2,g2) = untup7 y; y' = tup6 (b2,c2,d2,e2,f2,g2)- in a1 > a2 || (a1 == a2 && x' > y')--instance (Ord a, Ord b, Ord c, Ord d, Ord e, Ord f, Ord g, Ord h) => Ord (a, b, c, d, e, f, g, h) where- x <= y = let (a1,b1,c1,d1,e1,f1,g1,h1) = untup8 x; x' = tup7 (b1,c1,d1,e1,f1,g1,h1)- (a2,b2,c2,d2,e2,f2,g2,h2) = untup8 y; y' = tup7 (b2,c2,d2,e2,f2,g2,h2)- in a1 < a2 || (a1 == a2 && x' <= y')- x >= y = let (a1,b1,c1,d1,e1,f1,g1,h1) = untup8 x; x' = tup7 (b1,c1,d1,e1,f1,g1,h1)- (a2,b2,c2,d2,e2,f2,g2,h2) = untup8 y; y' = tup7 (b2,c2,d2,e2,f2,g2,h2)- in a1 > a2 || (a1 == a2 && x' >= y')- x < y = let (a1,b1,c1,d1,e1,f1,g1,h1) = untup8 x; x' = tup7 (b1,c1,d1,e1,f1,g1,h1)- (a2,b2,c2,d2,e2,f2,g2,h2) = untup8 y; y' = tup7 (b2,c2,d2,e2,f2,g2,h2)- in a1 < a2 || (a1 == a2 && x' < y')- x > y = let (a1,b1,c1,d1,e1,f1,g1,h1) = untup8 x; x' = tup7 (b1,c1,d1,e1,f1,g1,h1)- (a2,b2,c2,d2,e2,f2,g2,h2) = untup8 y; y' = tup7 (b2,c2,d2,e2,f2,g2,h2)- in a1 > a2 || (a1 == a2 && x' > y')--instance (Ord a, Ord b, Ord c, Ord d, Ord e, Ord f, Ord g, Ord h, Ord i) => Ord (a, b, c, d, e, f, g, h, i) where- x <= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1) = untup9 x; x' = tup8 (b1,c1,d1,e1,f1,g1,h1,i1)- (a2,b2,c2,d2,e2,f2,g2,h2,i2) = untup9 y; y' = tup8 (b2,c2,d2,e2,f2,g2,h2,i2)- in a1 < a2 || (a1 == a2 && x' <= y')- x >= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1) = untup9 x; x' = tup8 (b1,c1,d1,e1,f1,g1,h1,i1)- (a2,b2,c2,d2,e2,f2,g2,h2,i2) = untup9 y; y' = tup8 (b2,c2,d2,e2,f2,g2,h2,i2)- in a1 > a2 || (a1 == a2 && x' >= y')- x < y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1) = untup9 x; x' = tup8 (b1,c1,d1,e1,f1,g1,h1,i1)- (a2,b2,c2,d2,e2,f2,g2,h2,i2) = untup9 y; y' = tup8 (b2,c2,d2,e2,f2,g2,h2,i2)- in a1 < a2 || (a1 == a2 && x' < y')- x > y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1) = untup9 x; x' = tup8 (b1,c1,d1,e1,f1,g1,h1,i1)- (a2,b2,c2,d2,e2,f2,g2,h2,i2) = untup9 y; y' = tup8 (b2,c2,d2,e2,f2,g2,h2,i2)- in a1 > a2 || (a1 == a2 && x' > y')--instance (Ord a, Ord b, Ord c, Ord d, Ord e, Ord f, Ord g, Ord h, Ord i, Ord j) => Ord (a, b, c, d, e, f, g, h, i, j) where- x <= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1) = untup10 x; x' = tup9 (b1,c1,d1,e1,f1,g1,h1,i1,j1)- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2) = untup10 y; y' = tup9 (b2,c2,d2,e2,f2,g2,h2,i2,j2)- in a1 < a2 || (a1 == a2 && x' <= y')- x >= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1) = untup10 x; x' = tup9 (b1,c1,d1,e1,f1,g1,h1,i1,j1)- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2) = untup10 y; y' = tup9 (b2,c2,d2,e2,f2,g2,h2,i2,j2)- in a1 > a2 || (a1 == a2 && x' >= y')- x < y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1) = untup10 x; x' = tup9 (b1,c1,d1,e1,f1,g1,h1,i1,j1)- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2) = untup10 y; y' = tup9 (b2,c2,d2,e2,f2,g2,h2,i2,j2)- in a1 < a2 || (a1 == a2 && x' < y')- x > y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1) = untup10 x; x' = tup9 (b1,c1,d1,e1,f1,g1,h1,i1,j1)- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2) = untup10 y; y' = tup9 (b2,c2,d2,e2,f2,g2,h2,i2,j2)- in a1 > a2 || (a1 == a2 && x' > y')--instance (Ord a, Ord b, Ord c, Ord d, Ord e, Ord f, Ord g, Ord h, Ord i, Ord j, Ord k) => Ord (a, b, c, d, e, f, g, h, i, j, k) where- x <= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1) = untup11 x; x' = tup10 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1)- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2) = untup11 y; y' = tup10 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2)- in a1 < a2 || (a1 == a2 && x' <= y')- x >= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1) = untup11 x; x' = tup10 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1)- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2) = untup11 y; y' = tup10 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2)- in a1 > a2 || (a1 == a2 && x' >= y')- x < y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1) = untup11 x; x' = tup10 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1)- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2) = untup11 y; y' = tup10 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2)- in a1 < a2 || (a1 == a2 && x' < y')- x > y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1) = untup11 x; x' = tup10 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1)- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2) = untup11 y; y' = tup10 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2)- in a1 > a2 || (a1 == a2 && x' > y')--instance (Ord a, Ord b, Ord c, Ord d, Ord e, Ord f, Ord g, Ord h, Ord i, Ord j, Ord k, Ord l) => Ord (a, b, c, d, e, f, g, h, i, j, k, l) where- x <= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1) = untup12 x; x' = tup11 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1)- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2) = untup12 y; y' = tup11 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2)- in a1 < a2 || (a1 == a2 && x' <= y')- x >= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1) = untup12 x; x' = tup11 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1)- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2) = untup12 y; y' = tup11 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2)- in a1 > a2 || (a1 == a2 && x' >= y')- x < y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1) = untup12 x; x' = tup11 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1)- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2) = untup12 y; y' = tup11 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2)- in a1 < a2 || (a1 == a2 && x' < y')- x > y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1) = untup12 x; x' = tup11 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1)- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2) = untup12 y; y' = tup11 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2)- in a1 > a2 || (a1 == a2 && x' > y')--instance (Ord a, Ord b, Ord c, Ord d, Ord e, Ord f, Ord g, Ord h, Ord i, Ord j, Ord k, Ord l, Ord m) => Ord (a, b, c, d, e, f, g, h, i, j, k, l, m) where- x <= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1) = untup13 x; x' = tup12 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1)- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2) = untup13 y; y' = tup12 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2)- in a1 < a2 || (a1 == a2 && x' <= y')- x >= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1) = untup13 x; x' = tup12 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1)- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2) = untup13 y; y' = tup12 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2)- in a1 > a2 || (a1 == a2 && x' >= y')- x < y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1) = untup13 x; x' = tup12 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1)- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2) = untup13 y; y' = tup12 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2)- in a1 < a2 || (a1 == a2 && x' < y')- x > y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1) = untup13 x; x' = tup12 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1)- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2) = untup13 y; y' = tup12 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2)- in a1 > a2 || (a1 == a2 && x' > y')--instance (Ord a, Ord b, Ord c, Ord d, Ord e, Ord f, Ord g, Ord h, Ord i, Ord j, Ord k, Ord l, Ord m, Ord n) => Ord (a, b, c, d, e, f, g, h, i, j, k, l, m, n) where- x <= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1) = untup14 x; x' = tup13 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1)- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2) = untup14 y; y' = tup13 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2)- in a1 < a2 || (a1 == a2 && x' <= y')- x >= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1) = untup14 x; x' = tup13 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1)- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2) = untup14 y; y' = tup13 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2)- in a1 > a2 || (a1 == a2 && x' >= y')- x < y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1) = untup14 x; x' = tup13 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1)- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2) = untup14 y; y' = tup13 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2)- in a1 < a2 || (a1 == a2 && x' < y')- x > y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1) = untup14 x; x' = tup13 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1)- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2) = untup14 y; y' = tup13 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2)- in a1 > a2 || (a1 == a2 && x' > y')--instance (Ord a, Ord b, Ord c, Ord d, Ord e, Ord f, Ord g, Ord h, Ord i, Ord j, Ord k, Ord l, Ord m, Ord n, Ord o) => Ord (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) where- x <= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,o1) = untup15 x; x' = tup14 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,o1)- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2,o2) = untup15 y; y' = tup14 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2,o2)- in a1 < a2 || (a1 == a2 && x' <= y')- x >= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,o1) = untup15 x; x' = tup14 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,o1)- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2,o2) = untup15 y; y' = tup14 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2,o2)- in a1 > a2 || (a1 == a2 && x' >= y')- x < y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,o1) = untup15 x; x' = tup14 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,o1)- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2,o2) = untup15 y; y' = tup14 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2,o2)- in a1 < a2 || (a1 == a2 && x' < y')- x > y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,o1) = untup15 x; x' = tup14 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,o1)- (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2,o2) = untup15 y; y' = tup14 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2,o2)- in a1 > a2 || (a1 == a2 && x' > y')----- Instances of 'Prelude.Ord' (mostly) don't make sense with the standard--- signatures as the return type is fixed to 'Bool'. This instance is provided--- to provide a useful error message.------ Note that 'min' and 'max' are implementable, so we do hook those into the--- accelerate instances defined here. This allows us to use operations such as--- 'Prelude.minimum' and 'Prelude.maximum'.----instance Ord a => P.Ord (Exp a) where- compare = error "Prelude.Ord.compare applied to EDSL types"- (<) = preludeError "Ord.<" "(<)"- (<=) = preludeError "Ord.<=" "(<=)"- (>) = preludeError "Ord.>" "(>)"- (>=) = preludeError "Ord.>=" "(>=)"- min = min- max = max--preludeError :: String -> String -> a-preludeError x y = error (printf "Prelude.%s applied to EDSL types: use Data.Array.Accelerate.%s instead" x y)-
− Data/Array/Accelerate/Classes/Real.hs
@@ -1,41 +0,0 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MonoLocalBinds #-}-{-# LANGUAGE UndecidableInstances #-}-{-# OPTIONS_GHC -fno-warn-missing-methods #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}--- |--- Module : Data.Array.Accelerate.Classes.Real--- Copyright : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Classes.Real (-- Real,--) where--import Data.Array.Accelerate.Smart-import Data.Array.Accelerate.Classes.Num-import Data.Array.Accelerate.Classes.Ord--import qualified Prelude as P---type Real a = (Num a, Ord a, P.Real (Exp a))---- Instances of 'Real' don't make sense in Accelerate at the moment. These are--- only provided to fulfil superclass constraints; e.g. Integral.------ We won't need `toRational' until we support rational numbers in AP--- computations.----instance (Num a, Ord a) => P.Real (Exp a) where- toRational = P.error "Prelude.toRational not supported for Accelerate types"-
− Data/Array/Accelerate/Classes/RealFloat.hs
@@ -1,328 +0,0 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE DefaultSignatures #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE ViewPatterns #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}--- |--- Module : Data.Array.Accelerate.Classes.RealFloat--- Copyright : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Classes.RealFloat (-- RealFloat(..),--) where--import Data.Array.Accelerate.Error-import Data.Array.Accelerate.Smart-import Data.Array.Accelerate.Type--import Data.Array.Accelerate.Data.Bits--import Data.Array.Accelerate.Classes.Eq-import Data.Array.Accelerate.Classes.Floating-import Data.Array.Accelerate.Classes.FromIntegral-import Data.Array.Accelerate.Classes.Num-import Data.Array.Accelerate.Classes.Ord-import Data.Array.Accelerate.Classes.RealFrac--import Text.Printf-import Prelude ( (.), ($), String, error, undefined, otherwise )-import qualified Prelude as P----- | Efficient, machine-independent access to the components of a floating-point--- number----class (RealFrac a, Floating a) => RealFloat a where- -- | The radix of the representation (often 2) (constant)- floatRadix :: Exp a -> Exp Int64 -- Integer- default floatRadix :: P.RealFloat a => Exp a -> Exp Int64- floatRadix _ = P.fromInteger (P.floatRadix (undefined::a))-- -- | The number of digits of 'floatRadix' in the significand (constant)- floatDigits :: Exp a -> Exp Int- default floatDigits :: P.RealFloat a => Exp a -> Exp Int- floatDigits _ = constant (P.floatDigits (undefined::a))-- -- | The lowest and highest values the exponent may assume (constant)- floatRange :: Exp a -> (Exp Int, Exp Int)- default floatRange :: P.RealFloat a => Exp a -> (Exp Int, Exp Int)- floatRange _ = let (m,n) = P.floatRange (undefined::a)- in (constant m, constant n)-- -- | Return the significand and an appropriately scaled exponent. If- -- @(m,n) = 'decodeFloat' x@ then @x = m*b^^n@, where @b@ is the- -- floating-point radix ('floatRadix'). Furthermore, either @m@ and @n@ are- -- both zero, or @b^(d-1) <= 'abs' m < b^d@, where @d = 'floatDigits' x@.- decodeFloat :: Exp a -> (Exp Int64, Exp Int) -- Integer-- -- | Inverse of 'decodeFloat'- encodeFloat :: Exp Int64 -> Exp Int -> Exp a -- Integer- default encodeFloat :: (FromIntegral Int a, FromIntegral Int64 a) => Exp Int64 -> Exp Int -> Exp a- encodeFloat x e = fromIntegral x * (fromIntegral (floatRadix (undefined :: Exp a)) ** fromIntegral e)-- -- | Corresponds to the second component of 'decodeFloat'- exponent :: Exp a -> Exp Int- exponent x = let (m,n) = decodeFloat x- in Exp $ Cond (m == 0)- 0- (n + floatDigits x)-- -- | Corresponds to the first component of 'decodeFloat'- significand :: Exp a -> Exp a- significand x = let (m,_) = decodeFloat x- in encodeFloat m (negate (floatDigits x))-- -- | Multiply a floating point number by an integer power of the radix- scaleFloat :: Exp Int -> Exp a -> Exp a- scaleFloat k x =- Exp $ Cond (k == 0 || isFix) x- $ encodeFloat m (n + clamp b)- where- isFix = x == 0 || isNaN x || isInfinite x- (m,n) = decodeFloat x- (l,h) = floatRange x- d = floatDigits x- b = h - l + 4*d- -- n+k may overflow, which would lead to incorrect results, hence we clamp- -- the scaling parameter. If (n+k) would be larger than h, (n + clamp b k)- -- must be too, similar for smaller than (l-d).- clamp bd = max (-bd) (min bd k)-- -- | 'True' if the argument is an IEEE \"not-a-number\" (NaN) value- isNaN :: Exp a -> Exp Bool-- -- | 'True' if the argument is an IEEE infinity or negative-infinity- isInfinite :: Exp a -> Exp Bool-- -- | 'True' if the argument is too small to be represented in normalized- -- format- isDenormalized :: Exp a -> Exp Bool-- -- | 'True' if the argument is an IEEE negative zero- isNegativeZero :: Exp a -> Exp Bool-- -- | 'True' if the argument is an IEEE floating point number- isIEEE :: Exp a -> Exp Bool- default isIEEE :: P.RealFloat a => Exp a -> Exp Bool- isIEEE _ = constant (P.isIEEE (undefined::Float))-- -- | A version of arctangent taking two real floating-point arguments.- -- For real floating @x@ and @y@, @'atan2' y x@ computes the angle (from the- -- positive x-axis) of the vector from the origin to the point @(x,y)@.- -- @'atan2' y x@ returns a value in the range [@-pi@, @pi@].- atan2 :: Exp a -> Exp a -> Exp a---instance RealFloat Float where- atan2 = mkAtan2- isNaN = mkIsNaN- isInfinite = mkIsInfinite- isDenormalized = ieee754 "isDenormalized" (ieee754_f32_is_denormalized . mkUnsafeCoerce)- isNegativeZero = ieee754 "isNegativeZero" (ieee754_f32_is_negative_zero . mkUnsafeCoerce)- decodeFloat = ieee754 "decodeFloat" (\x -> let (m,n) = untup2 $ ieee754_f32_decode (mkUnsafeCoerce x)- in (fromIntegral m, n))--instance RealFloat Double where- atan2 = mkAtan2- isNaN = mkIsNaN- isInfinite = mkIsInfinite- isDenormalized = ieee754 "isDenormalized" (ieee754_f64_is_denormalized . mkUnsafeCoerce)- isNegativeZero = ieee754 "isNegativeZero" (ieee754_f64_is_negative_zero . mkUnsafeCoerce)- decodeFloat = ieee754 "decodeFloat" (untup2 . ieee754_f64_decode . mkUnsafeCoerce)--instance RealFloat CFloat where- atan2 = mkAtan2- isNaN = mkIsNaN- isInfinite = mkIsInfinite- isDenormalized = ieee754 "isDenormalized" (ieee754_f32_is_denormalized . mkUnsafeCoerce)- isNegativeZero = ieee754 "isNegativeZero" (ieee754_f32_is_negative_zero . mkUnsafeCoerce)- decodeFloat = ieee754 "decodeFloat" (\x -> let (m,n) = untup2 $ ieee754_f32_decode (mkUnsafeCoerce x)- in (fromIntegral m, n))--instance RealFloat CDouble where- atan2 = mkAtan2- isNaN = mkIsNaN- isInfinite = mkIsInfinite- isDenormalized = ieee754 "isDenormalized" (ieee754_f64_is_denormalized . mkUnsafeCoerce)- isNegativeZero = ieee754 "isNegativeZero" (ieee754_f64_is_negative_zero . mkUnsafeCoerce)- decodeFloat = ieee754 "decodeFloat" (untup2 . ieee754_f64_decode . mkUnsafeCoerce)----- To satisfy superclass constraints----instance RealFloat a => P.RealFloat (Exp a) where- floatRadix = preludeError "floatRadix"- floatDigits = preludeError "floatDigits"- floatRange = preludeError "floatRange"- decodeFloat = preludeError "decodeFloat"- encodeFloat = preludeError "encodeFloat"- isNaN = preludeError "isNaN"- isInfinite = preludeError "isInfinite"- isDenormalized = preludeError "isDenormalized"- isNegativeZero = preludeError "isNegativeZero"- isIEEE = preludeError "isIEEE"--preludeError :: String -> a-preludeError x = error (printf "Prelude.%s applied to EDSL types: use Data.Array.Accelerate.%s instead" x x)---ieee754 :: forall a b. P.RealFloat a => String -> (Exp a -> b) -> Exp a -> b-ieee754 name f x- | P.isIEEE (undefined::a) = f x- | otherwise = $internalError (printf "RealFloat.%s" name) "Not implemented for non-IEEE floating point"---- From: ghc/libraries/base/cbits/primFloat.c--- ---------------------------------------------- An IEEE754 number is denormalised iff:--- * exponent is zero--- * mantissa is non-zero.--- * (don't care about setting of sign bit.)----ieee754_f64_is_denormalized :: Exp Word64 -> Exp Bool-ieee754_f64_is_denormalized x =- ieee754_f64_mantissa x == 0 &&- ieee754_f64_exponent x /= 0--ieee754_f32_is_denormalized :: Exp Word32 -> Exp Bool-ieee754_f32_is_denormalized x =- ieee754_f32_mantissa x == 0 &&- ieee754_f32_exponent x /= 0---- Negative zero if only the sign bit is set----ieee754_f64_is_negative_zero :: Exp Word64 -> Exp Bool-ieee754_f64_is_negative_zero x =- ieee754_f64_negative x &&- ieee754_f64_exponent x == 0 &&- ieee754_f64_mantissa x == 0--ieee754_f32_is_negative_zero :: Exp Word32 -> Exp Bool-ieee754_f32_is_negative_zero x =- ieee754_f32_negative x &&- ieee754_f32_exponent x == 0 &&- ieee754_f32_mantissa x == 0----- Assume the host processor stores integers and floating point numbers in the--- same endianness (true for modern processors).------ To recap, here's the representation of a double precision--- IEEE floating point number:------ sign 63 sign bit (0==positive, 1==negative)--- exponent 62-52 exponent (biased by 1023)--- fraction 51-0 fraction (bits to right of binary point)----ieee754_f64_mantissa :: Exp Word64 -> Exp Word64-ieee754_f64_mantissa x = x .&. 0xFFFFFFFFFFFFF--ieee754_f64_exponent :: Exp Word64 -> Exp Word16-ieee754_f64_exponent x = fromIntegral (x `unsafeShiftR` 52) .&. 0x7FF--ieee754_f64_negative :: Exp Word64 -> Exp Bool-ieee754_f64_negative x = testBit x 63---- Representation of single precision IEEE floating point number:------ sign 31 sign bit (0==positive, 1==negative)--- exponent 30-23 exponent (biased by 127)--- fraction 22-0 fraction (bits to right of binary point)----ieee754_f32_mantissa :: Exp Word32 -> Exp Word32-ieee754_f32_mantissa x = x .&. 0x7FFFFF--ieee754_f32_exponent :: Exp Word32 -> Exp Word8-ieee754_f32_exponent x = fromIntegral (x `unsafeShiftR` 23)--ieee754_f32_negative :: Exp Word32 -> Exp Bool-ieee754_f32_negative x = testBit x 31---- From: ghc/rts/StgPrimFloat.c--- ------------------------------ieee754_f32_decode :: Exp Word32 -> Exp (Int32, Int)-ieee754_f32_decode i =- let- _FMSBIT = 0x80000000- _FHIGHBIT = 0x00800000- _FMINEXP = ((_FLT_MIN_EXP) - (_FLT_MANT_DIG) - 1)- _FLT_MANT_DIG = floatDigits (undefined::Exp Float)- (_FLT_MIN_EXP, _FLT_MAX_EXP) = floatRange (undefined::Exp Float)-- high1 = fromIntegral i- high2 = high1 .&. (_FHIGHBIT - 1)-- exp1 = ((fromIntegral high1 `unsafeShiftR` 23) .&. 0xFF) + _FMINEXP- exp2 = exp1 + 1-- (high3, exp3)- = untup2- $ Exp $ Cond (exp1 /= _FMINEXP)- -- don't add hidden bit to denorms- (tup2 (high2 .|. _FHIGHBIT, exp1))- -- a denorm, normalise the mantissa- (Exp $ While (\(untup2 -> (h,_)) -> (h .&. _FHIGHBIT) /= 0 )- (\(untup2 -> (h,e)) -> tup2 (h `unsafeShiftL` 1, e-1))- (tup2 (high2, exp2)))-- high4 = Exp $ Cond (fromIntegral i < (0 :: Exp Int32)) (-high3) high3- in- Exp $ Cond (high1 .&. complement _FMSBIT == 0)- (tup2 (0,0))- (tup2 (high4, exp3))---ieee754_f64_decode :: Exp Word64 -> Exp (Int64, Int)-ieee754_f64_decode i =- let (s,h,l,e) = untup4 $ ieee754_f64_decode2 i- in tup2 (fromIntegral s * (fromIntegral h `unsafeShiftL` 32 .|. fromIntegral l), e)--ieee754_f64_decode2 :: Exp Word64 -> Exp (Int, Word32, Word32, Int)-ieee754_f64_decode2 i =- let- _DHIGHBIT = 0x00100000- _DMSBIT = 0x80000000- _DMINEXP = ((_DBL_MIN_EXP) - (_DBL_MANT_DIG) - 1)- _DBL_MANT_DIG = floatDigits (undefined::Exp Double)- (_DBL_MIN_EXP, _DBL_MAX_EXP) = floatRange (undefined::Exp Double)-- low = fromIntegral i- high = fromIntegral (i `unsafeShiftR` 32)-- iexp = (fromIntegral ((high `unsafeShiftR` 20) .&. 0x7FF) + _DMINEXP)- sign = Exp $ Cond (fromIntegral i < (0 :: Exp Int64)) (-1) 1-- high2 = high .&. (_DHIGHBIT - 1)- iexp2 = iexp + 1-- (hi,lo,ie)- = untup3- $ Exp $ Cond (iexp2 /= _DMINEXP)- -- don't add hidden bit to denorms- (tup3 (high2 .|. _DHIGHBIT, low, iexp))- -- a denorm, nermalise the mantissa- (Exp $ While (\(untup3 -> (h,_,_)) -> (h .&. _DHIGHBIT) /= 0)- (\(untup3 -> (h,l,e)) ->- let h1 = h `unsafeShiftL` 1- h2 = Exp $ Cond ((l .&. _DMSBIT) /= 0) (h1+1) h1- in tup3 (h2, l `unsafeShiftL` 1, e-1))- (tup3 (high2, low, iexp2)))-- in- Exp $ Cond (low == 0 && (high .&. (complement _DMSBIT)) == 0)- (tup4 (1,0,0,0))- (tup4 (sign,hi,lo,ie))-
− Data/Array/Accelerate/Classes/RealFrac.hs
@@ -1,166 +0,0 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MonoLocalBinds #-}-{-# LANGUAGE NoImplicitPrelude #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}--- |--- Module : Data.Array.Accelerate.Classes.RealFrac--- Copyright : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Classes.RealFrac (-- RealFrac(..),- div', mod', divMod',--) where--import Data.Array.Accelerate.Array.Sugar-import Data.Array.Accelerate.Smart-import Data.Array.Accelerate.Type--import Data.Array.Accelerate.Classes.Eq-import Data.Array.Accelerate.Classes.Floating-import Data.Array.Accelerate.Classes.Fractional-import Data.Array.Accelerate.Classes.Num-import Data.Array.Accelerate.Classes.Real-import Data.Array.Accelerate.Classes.ToFloating--import Text.Printf-import Prelude ( ($), String, error )-import qualified Prelude as P----- | Generalisation of 'P.div' to any instance of 'RealFrac'----div' :: (RealFrac a, Elt b, IsIntegral b) => Exp a -> Exp a -> Exp b-div' n d = floor (n / d)---- | Generalisation of 'P.mod' to any instance of 'RealFrac'----mod' :: (Floating a, RealFrac a, ToFloating Int a) => Exp a -> Exp a -> Exp a-mod' n d = n - (toFloating f) * d- where- f :: Exp Int- f = div' n d---- | Generalisation of 'P.divMod' to any instance of 'RealFrac'----divMod'- :: (Floating a, RealFrac a, Num b, IsIntegral b, ToFloating b a)- => Exp a- -> Exp a- -> (Exp b, Exp a)-divMod' n d = (f, n - (toFloating f) * d)- where- f = div' n d----- | Extracting components of fractions.----class (Real a, Fractional a) => RealFrac a where- -- The function 'properFraction' takes a real fractional number @x@ and- -- returns a pair @(n,f)@ such that @x = n+f@, and:- --- -- * @n@ is an integral number with the same sign as @x@; and- --- -- * @f@ is a fraction with the same type and sign as @x@,- -- and with absolute value less than @1@.- --- -- The default definitions of the 'ceiling', 'floor', 'truncate'- -- and 'round' functions are in terms of 'properFraction'.- properFraction :: (Num b, ToFloating b a, IsIntegral b) => Exp a -> (Exp b, Exp a)-- -- The function 'splitFraction' takes a real fractional number @x@ and- -- returns a pair @(n,f)@ such that @x = n+f@, and:- --- -- * @n@ is an integral number with the same sign as @x@; and- --- -- * @f@ is a fraction with the same type as @x@ in the range [0,1). Note that- -- this differs from 'Prelude.properFraction'.- --- -- splitFraction :: (Elt b, IsIntegral b) => Exp a -> (Exp b, Exp a)-- -- @fraction x@ returns @x@ with the integer part removed.- -- fraction :: Exp a -> Exp a-- -- properFraction is part of the standard Haskell'98 RealFrac type classes- -- splitFraction / fraction are from numeric-prelude Algebra.RealRing-- -- | @truncate x@ returns the integer nearest @x@ between zero and @x@- truncate :: (Elt b, IsIntegral b) => Exp a -> Exp b-- -- | @'round' x@ returns the nearest integer to @x@; the even integer if @x@- -- is equidistant between two integers- round :: (Elt b, IsIntegral b) => Exp a -> Exp b-- -- | @'ceiling' x@ returns the least integer not less than @x@- ceiling :: (Elt b, IsIntegral b) => Exp a -> Exp b-- -- | @'floor' x@ returns the greatest integer not greater than @x@- floor :: (Elt b, IsIntegral b) => Exp a -> Exp b---instance RealFrac Float where- properFraction = defaultProperFraction- truncate = mkTruncate- round = mkRound- ceiling = mkCeiling- floor = mkFloor--instance RealFrac Double where- properFraction = defaultProperFraction- truncate = mkTruncate- round = mkRound- ceiling = mkCeiling- floor = mkFloor--instance RealFrac CFloat where- properFraction = defaultProperFraction- truncate = mkTruncate- round = mkRound- ceiling = mkCeiling- floor = mkFloor--instance RealFrac CDouble where- properFraction = defaultProperFraction- truncate = mkTruncate- round = mkRound- ceiling = mkCeiling- floor = mkFloor----- Must test for ±0.0 to avoid returning -0.0 in the second component of the--- pair. Unfortunately the branching costs a lot of performance.----defaultProperFraction- :: (ToFloating a b, RealFrac b, IsIntegral a, Num a, Floating b)- => Exp b- -> (Exp a, Exp b)-defaultProperFraction x =- untup2 $ Exp- $ Cond (x == 0) (tup2 (0, 0))- (tup2 (n, f))- where- n = truncate x- f = x - toFloating n----- To satisfy superclass constraints----instance RealFrac a => P.RealFrac (Exp a) where- properFraction = preludeError "properFraction"- truncate = preludeError "truncate"- round = preludeError "round"- ceiling = preludeError "ceiling"- floor = preludeError "floor"--preludeError :: String -> a-preludeError x = error (printf "Prelude.%s applied to EDSL types: use Data.Array.Accelerate.%s instead" x x)-
− Data/Array/Accelerate/Classes/ToFloating.hs
@@ -1,82 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE TemplateHaskell #-}--- |--- Module : Data.Array.Accelerate.Classes.ToFloating--- Copyright : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Classes.ToFloating (-- ToFloating(..),--) where--import Data.Array.Accelerate.Smart-import Data.Array.Accelerate.Type--import Data.Array.Accelerate.Classes.Floating-import Data.Array.Accelerate.Classes.Num--import Language.Haskell.TH hiding ( Exp )-import Control.Monad-import Prelude ( ($), error, concat )----- | Accelerate lacks an arbitrary-precision 'Prelude.Rational' type, which the--- standard 'Prelude.realToFrac' uses as an intermediate value when coercing--- to floating-point types. Instead, we use this class to capture a direct--- coercion between to types.----class ToFloating a b where- -- | General coercion to floating types- toFloating :: (Num a, Floating b) => Exp a -> Exp b---- instance (Elt a, Elt b, IsNum a, IsFloating b) => ToFloating a b where--- toFloating = mkToFloating---- Generate standard instances explicitly. See also: 'FromIntegral'.----$(runQ $ do- let- -- Get all the types that our dictionaries reify- digItOut :: Name -> Q [Name]- digItOut name = do-#if __GLASGOW_HASKELL__ < 800- TyConI (DataD _ _ _ cons _) <- reify name-#else- TyConI (DataD _ _ _ _ cons _) <- reify name-#endif- let- dig (NormalC _ [(_, AppT (ConT n) (VarT _))]) = digItOut n-#if __GLASGOW_HASKELL__ < 800- dig (ForallC _ _ (NormalC _ [(_, AppT (ConT _) (ConT n))])) = return [n]-#else- dig (GadtC _ _ (AppT (ConT _) (ConT n))) = return [n]-#endif- dig _ = error "Unexpected case generating ToFloating instances"- --- concat `fmap` mapM dig cons-- thToFloating :: Name -> Name -> Q Dec- thToFloating a b =- let- ty = AppT (AppT (ConT (mkName "ToFloating")) (ConT a)) (ConT b)- dec = ValD (VarP (mkName "toFloating")) (NormalB (VarE (mkName "mkToFloating"))) []- in- instanceD (return []) (return ty) [return dec]- --- as <- digItOut ''NumType- bs <- digItOut ''FloatingType- sequence [ thToFloating a b | a <- as, b <- bs ]- )-
− Data/Array/Accelerate/Data/Bits.hs
@@ -1,806 +0,0 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE ViewPatterns #-}--- |--- Module : Data.Array.Accelerate.Data.Bits--- Copyright : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)------ Bitwise operations for signed and unsigned integer expressions.-----module Data.Array.Accelerate.Data.Bits (-- Bits(..),- FiniteBits(..),--) where--import Data.Array.Accelerate.Array.Sugar-import Data.Array.Accelerate.Language-import Data.Array.Accelerate.Smart-import Data.Array.Accelerate.Type--import Data.Array.Accelerate.Classes.Eq-import Data.Array.Accelerate.Classes.Ord-import Data.Array.Accelerate.Classes.Num-import Data.Array.Accelerate.Classes.Integral ()--import Prelude ( ($), (.), undefined, otherwise )-import qualified Data.Bits as B---infixl 8 `shift`, `rotate`, `shiftL`, `shiftR`, `rotateL`, `rotateR`-infixl 7 .&.-infixl 6 `xor`-infixl 5 .|.----- | The 'Bits' class defines bitwise operations over integral scalar expression--- types. As usual, bits are numbered from zero, with zero being the least--- significant bit.----class Eq a => Bits a where- {-# MINIMAL (.&.), (.|.), xor, complement,- (shift | (shiftL, shiftR)),- (rotate | (rotateL, rotateR)),- isSigned, testBit, bit, popCount #-}-- -- | Bitwise "and"- (.&.) :: Exp a -> Exp a -> Exp a-- -- | Bitwise "or"- (.|.) :: Exp a -> Exp a -> Exp a-- -- | Bitwise "xor"- xor :: Exp a -> Exp a -> Exp a-- -- | Reverse all bits in the argument- complement :: Exp a -> Exp a-- -- | @'shift' x i@ shifts @x@ left by @i@ bits if @i@ is positive, or right by- -- @-i@ bits otherwise. Right shifts perform sign extension on signed number- -- types; i.e. they fill the top bits with 1 if the @x@ is negative and with- -- 0 otherwise.- shift :: Exp a -> Exp Int -> Exp a- shift x i- = cond (i < 0) (x `shiftR` (-i))- $ cond (i > 0) (x `shiftL` i)- $ x-- -- | @'rotate' x i@ rotates @x@ left by @i@ bits if @i@ is positive, or right- -- by @-i@ bits otherwise.- rotate :: Exp a -> Exp Int -> Exp a- rotate x i- = cond (i < 0) (x `rotateR` (-i))- $ cond (i > 0) (x `rotateL` i)- $ x-- -- | The value with all bits unset- zeroBits :: Exp a- zeroBits = clearBit (bit 0) 0-- -- | @bit /i/@ is a value with the @/i/@th bit set and all other bits clear.- bit :: Exp Int -> Exp a-- -- | @x \`setBit\` i@ is the same as @x .|. bit i@- setBit :: Exp a -> Exp Int -> Exp a- setBit x i = x .|. bit i-- -- | @x \`clearBit\` i@ is the same as @x .&. complement (bit i)@- clearBit :: Exp a -> Exp Int -> Exp a- clearBit x i = x .&. complement (bit i)-- -- | @x \`complementBit\` i@ is the same as @x \`xor\` bit i@- complementBit :: Exp a -> Exp Int -> Exp a- complementBit x i = x `xor` bit i-- -- | Return 'True' if the @n@th bit of the argument is 1- testBit :: Exp a -> Exp Int -> Exp Bool-- -- | Return 'True' if the argument is a signed type.- isSigned :: Exp a -> Exp Bool-- -- | Shift the argument left by the specified number of bits (which must be- -- non-negative).- shiftL :: Exp a -> Exp Int -> Exp a- shiftL x i = x `shift` i-- -- | Shift the argument left by the specified number of bits. The result is- -- undefined for negative shift amounts and shift amounts greater or equal to- -- the 'finiteBitSize'.- unsafeShiftL :: Exp a -> Exp Int -> Exp a- unsafeShiftL = shiftL-- -- | Shift the first argument right by the specified number of bits (which- -- must be non-negative).- --- -- Right shifts perform sign extension on signed number types; i.e. they fill- -- the top bits with 1 if @x@ is negative and with 0 otherwise.- shiftR :: Exp a -> Exp Int -> Exp a- shiftR x i = x `shift` (-i)-- -- | Shift the first argument right by the specified number of bits. The- -- result is undefined for negative shift amounts and shift amounts greater or- -- equal to the 'finiteBitSize'.- unsafeShiftR :: Exp a -> Exp Int -> Exp a- unsafeShiftR = shiftR-- -- | Rotate the argument left by the specified number of bits (which must be- -- non-negative).- rotateL :: Exp a -> Exp Int -> Exp a- rotateL x i = x `rotate` i-- -- | Rotate the argument right by the specified number of bits (which must be non-negative).- rotateR :: Exp a -> Exp Int -> Exp a- rotateR x i = x `rotate` (-i)-- -- | Return the number of set bits in the argument. This number is known as- -- the population count or the Hamming weight.- popCount :: Exp a -> Exp Int---class Bits b => FiniteBits b where- -- | Return the number of bits in the type of the argument.- finiteBitSize :: Exp b -> Exp Int-- -- | Count the number of zero bits preceding the most significant set bit.- -- This can be used to compute a base-2 logarithm via:- --- -- > logBase2 x = finiteBitSize x - 1 - countLeadingZeros x- --- countLeadingZeros :: Exp b -> Exp Int-- -- | Count the number of zero bits following the least significant set bit.- -- The related- -- <http://en.wikipedia.org/wiki/Find_first_set find-first-set operation> can- -- be expressed in terms of this as:- --- -- > findFirstSet x = 1 + countTrailingZeros x- --- countTrailingZeros :: Exp b -> Exp Int----- Instances for Bits--- --------------------instance Bits Bool where- (.&.) = (&&)- (.|.) = (||)- xor = (/=)- complement = not- shift x i = cond (i == 0) x (constant False)- testBit x i = cond (i == 0) x (constant False)- rotate x _ = x- bit i = i == 0- isSigned = isSignedDefault- popCount = mkBoolToInt--instance Bits Int where- (.&.) = mkBAnd- (.|.) = mkBOr- xor = mkBXor- complement = mkBNot- bit = bitDefault- testBit = testBitDefault- shift = shiftDefault- shiftL = shiftLDefault- shiftR = shiftRDefault- unsafeShiftL = mkBShiftL- unsafeShiftR = mkBShiftR- rotate = rotateDefault- rotateL = rotateLDefault- rotateR = rotateRDefault- isSigned = isSignedDefault- popCount = mkPopCount--instance Bits Int8 where- (.&.) = mkBAnd- (.|.) = mkBOr- xor = mkBXor- complement = mkBNot- bit = bitDefault- testBit = testBitDefault- shift = shiftDefault- shiftL = shiftLDefault- shiftR = shiftRDefault- unsafeShiftL = mkBShiftL- unsafeShiftR = mkBShiftR- rotate = rotateDefault- rotateL = rotateLDefault- rotateR = rotateRDefault- isSigned = isSignedDefault- popCount = mkPopCount--instance Bits Int16 where- (.&.) = mkBAnd- (.|.) = mkBOr- xor = mkBXor- complement = mkBNot- bit = bitDefault- testBit = testBitDefault- shift = shiftDefault- shiftL = shiftLDefault- shiftR = shiftRDefault- unsafeShiftL = mkBShiftL- unsafeShiftR = mkBShiftR- rotate = rotateDefault- rotateL = rotateLDefault- rotateR = rotateRDefault- isSigned = isSignedDefault- popCount = mkPopCount--instance Bits Int32 where- (.&.) = mkBAnd- (.|.) = mkBOr- xor = mkBXor- complement = mkBNot- bit = bitDefault- testBit = testBitDefault- shift = shiftDefault- shiftL = shiftLDefault- shiftR = shiftRDefault- unsafeShiftL = mkBShiftL- unsafeShiftR = mkBShiftR- rotate = rotateDefault- rotateL = rotateLDefault- rotateR = rotateRDefault- isSigned = isSignedDefault- popCount = mkPopCount--instance Bits Int64 where- (.&.) = mkBAnd- (.|.) = mkBOr- xor = mkBXor- complement = mkBNot- bit = bitDefault- testBit = testBitDefault- shift = shiftDefault- shiftL = shiftLDefault- shiftR = shiftRDefault- unsafeShiftL = mkBShiftL- unsafeShiftR = mkBShiftR- rotate = rotateDefault- rotateL = rotateLDefault- rotateR = rotateRDefault- isSigned = isSignedDefault- popCount = mkPopCount--instance Bits Word where- (.&.) = mkBAnd- (.|.) = mkBOr- xor = mkBXor- complement = mkBNot- bit = bitDefault- testBit = testBitDefault- shift = shiftDefault- shiftL = shiftLDefault- shiftR = shiftRDefault- unsafeShiftL = mkBShiftL- unsafeShiftR = mkBShiftR- rotate = rotateDefault- rotateL = rotateLDefault- rotateR = rotateRDefault- isSigned = isSignedDefault- popCount = mkPopCount--instance Bits Word8 where- (.&.) = mkBAnd- (.|.) = mkBOr- xor = mkBXor- complement = mkBNot- bit = bitDefault- testBit = testBitDefault- shift = shiftDefault- shiftL = shiftLDefault- shiftR = shiftRDefault- unsafeShiftL = mkBShiftL- unsafeShiftR = mkBShiftR- rotate = rotateDefault- rotateL = rotateLDefault- rotateR = rotateRDefault- isSigned = isSignedDefault- popCount = mkPopCount--instance Bits Word16 where- (.&.) = mkBAnd- (.|.) = mkBOr- xor = mkBXor- complement = mkBNot- bit = bitDefault- testBit = testBitDefault- shift = shiftDefault- shiftL = shiftLDefault- shiftR = shiftRDefault- unsafeShiftL = mkBShiftL- unsafeShiftR = mkBShiftR- rotate = rotateDefault- rotateL = rotateLDefault- rotateR = rotateRDefault- isSigned = isSignedDefault- popCount = mkPopCount--instance Bits Word32 where- (.&.) = mkBAnd- (.|.) = mkBOr- xor = mkBXor- complement = mkBNot- bit = bitDefault- testBit = testBitDefault- shift = shiftDefault- shiftL = shiftLDefault- shiftR = shiftRDefault- unsafeShiftL = mkBShiftL- unsafeShiftR = mkBShiftR- rotate = rotateDefault- rotateL = rotateLDefault- rotateR = rotateRDefault- isSigned = isSignedDefault- popCount = mkPopCount--instance Bits Word64 where- (.&.) = mkBAnd- (.|.) = mkBOr- xor = mkBXor- complement = mkBNot- bit = bitDefault- testBit = testBitDefault- shift = shiftDefault- shiftL = shiftLDefault- shiftR = shiftRDefault- unsafeShiftL = mkBShiftL- unsafeShiftR = mkBShiftR- rotate = rotateDefault- rotateL = rotateLDefault- rotateR = rotateRDefault- isSigned = isSignedDefault- popCount = mkPopCount--instance Bits CInt where- (.&.) = mkBAnd- (.|.) = mkBOr- xor = mkBXor- complement = mkBNot- bit = bitDefault- testBit = testBitDefault- shift = shiftDefault- shiftL = shiftLDefault- shiftR = shiftRDefault- unsafeShiftL = mkBShiftL- unsafeShiftR = mkBShiftR- rotate = rotateDefault- rotateL = rotateLDefault- rotateR = rotateRDefault- isSigned = isSignedDefault- popCount = mkPopCount--instance Bits CUInt where- (.&.) = mkBAnd- (.|.) = mkBOr- xor = mkBXor- complement = mkBNot- bit = bitDefault- testBit = testBitDefault- shift = shiftDefault- shiftL = shiftLDefault- shiftR = shiftRDefault- unsafeShiftL = mkBShiftL- unsafeShiftR = mkBShiftR- rotate = rotateDefault- rotateL = rotateLDefault- rotateR = rotateRDefault- isSigned = isSignedDefault- popCount = mkPopCount--instance Bits CLong where- (.&.) = mkBAnd- (.|.) = mkBOr- xor = mkBXor- complement = mkBNot- bit = bitDefault- testBit = testBitDefault- shift = shiftDefault- shiftL = shiftLDefault- shiftR = shiftRDefault- unsafeShiftL = mkBShiftL- unsafeShiftR = mkBShiftR- rotate = rotateDefault- rotateL = rotateLDefault- rotateR = rotateRDefault- isSigned = isSignedDefault- popCount = mkPopCount--instance Bits CULong where- (.&.) = mkBAnd- (.|.) = mkBOr- xor = mkBXor- complement = mkBNot- bit = bitDefault- testBit = testBitDefault- shift = shiftDefault- shiftL = shiftLDefault- shiftR = shiftRDefault- unsafeShiftL = mkBShiftL- unsafeShiftR = mkBShiftR- rotate = rotateDefault- rotateL = rotateLDefault- rotateR = rotateRDefault- isSigned = isSignedDefault- popCount = mkPopCount--instance Bits CLLong where- (.&.) = mkBAnd- (.|.) = mkBOr- xor = mkBXor- complement = mkBNot- bit = bitDefault- testBit = testBitDefault- shift = shiftDefault- shiftL = shiftLDefault- shiftR = shiftRDefault- unsafeShiftL = mkBShiftL- unsafeShiftR = mkBShiftR- rotate = rotateDefault- rotateL = rotateLDefault- rotateR = rotateRDefault- isSigned = isSignedDefault- popCount = mkPopCount--instance Bits CULLong where- (.&.) = mkBAnd- (.|.) = mkBOr- xor = mkBXor- complement = mkBNot- bit = bitDefault- testBit = testBitDefault- shift = shiftDefault- shiftL = shiftLDefault- shiftR = shiftRDefault- unsafeShiftL = mkBShiftL- unsafeShiftR = mkBShiftR- rotate = rotateDefault- rotateL = rotateLDefault- rotateR = rotateRDefault- isSigned = isSignedDefault- popCount = mkPopCount--instance Bits CShort where- (.&.) = mkBAnd- (.|.) = mkBOr- xor = mkBXor- complement = mkBNot- bit = bitDefault- testBit = testBitDefault- shift = shiftDefault- shiftL = shiftLDefault- shiftR = shiftRDefault- unsafeShiftL = mkBShiftL- unsafeShiftR = mkBShiftR- rotate = rotateDefault- rotateL = rotateLDefault- rotateR = rotateRDefault- isSigned = isSignedDefault- popCount = mkPopCount--instance Bits CUShort where- (.&.) = mkBAnd- (.|.) = mkBOr- xor = mkBXor- complement = mkBNot- bit = bitDefault- testBit = testBitDefault- shift = shiftDefault- shiftL = shiftLDefault- shiftR = shiftRDefault- unsafeShiftL = mkBShiftL- unsafeShiftR = mkBShiftR- rotate = rotateDefault- rotateL = rotateLDefault- rotateR = rotateRDefault- isSigned = isSignedDefault- popCount = mkPopCount---- instance Bits CChar where--- (.&.) = mkBAnd--- (.|.) = mkBOr--- xor = mkBXor--- complement = mkBNot--- bit = bitDefault--- testBit = testBitDefault--- shift = shiftDefault--- shiftL = shiftLDefault--- shiftR = shiftRDefault--- unsafeShiftL = mkBShiftL--- unsafeShiftR = mkBShiftR--- rotate = rotateDefault--- rotateL = rotateLDefault--- rotateR = rotateRDefault--- isSigned = isSignedDefault--- popCount = mkPopCount---- instance Bits CUChar where--- (.&.) = mkBAnd--- (.|.) = mkBOr--- xor = mkBXor--- complement = mkBNot--- bit = bitDefault--- testBit = testBitDefault--- shift = shiftDefault--- shiftL = shiftLDefault--- shiftR = shiftRDefault--- unsafeShiftL = mkBShiftL--- unsafeShiftR = mkBShiftR--- rotate = rotateDefault--- rotateL = rotateLDefault--- rotateR = rotateRDefault--- isSigned = isSignedDefault--- popCount = mkPopCount---- instance Bits CSChar where--- (.&.) = mkBAnd--- (.|.) = mkBOr--- xor = mkBXor--- complement = mkBNot--- bit = bitDefault--- testBit = testBitDefault--- shift = shiftDefault--- shiftL = shiftLDefault--- shiftR = shiftRDefault--- unsafeShiftL = mkBShiftL--- unsafeShiftR = mkBShiftR--- rotate = rotateDefault--- rotateL = rotateLDefault--- rotateR = rotateRDefault--- isSigned = isSignedDefault--- popCount = mkPopCount----- Instances for FiniteBits--- --------------------------instance FiniteBits Bool where- finiteBitSize _ = constant (B.finiteBitSize (undefined::Bool))- countLeadingZeros x = cond x 0 1- countTrailingZeros x = cond x 0 1--instance FiniteBits Int where- finiteBitSize _ = constant (B.finiteBitSize (undefined::Int))- countLeadingZeros = mkCountLeadingZeros- countTrailingZeros = mkCountTrailingZeros--instance FiniteBits Int8 where- finiteBitSize _ = constant (B.finiteBitSize (undefined::Int8))- countLeadingZeros = mkCountLeadingZeros- countTrailingZeros = mkCountTrailingZeros--instance FiniteBits Int16 where- finiteBitSize _ = constant (B.finiteBitSize (undefined::Int16))- countLeadingZeros = mkCountLeadingZeros- countTrailingZeros = mkCountTrailingZeros--instance FiniteBits Int32 where- finiteBitSize _ = constant (B.finiteBitSize (undefined::Int32))- countLeadingZeros = mkCountLeadingZeros- countTrailingZeros = mkCountTrailingZeros--instance FiniteBits Int64 where- finiteBitSize _ = constant (B.finiteBitSize (undefined::Int64))- countLeadingZeros = mkCountLeadingZeros- countTrailingZeros = mkCountTrailingZeros--instance FiniteBits Word where- finiteBitSize _ = constant (B.finiteBitSize (undefined::Word))- countLeadingZeros = mkCountLeadingZeros- countTrailingZeros = mkCountTrailingZeros--instance FiniteBits Word8 where- finiteBitSize _ = constant (B.finiteBitSize (undefined::Word8))- countLeadingZeros = mkCountLeadingZeros- countTrailingZeros = mkCountTrailingZeros--instance FiniteBits Word16 where- finiteBitSize _ = constant (B.finiteBitSize (undefined::Word16))- countLeadingZeros = mkCountLeadingZeros- countTrailingZeros = mkCountTrailingZeros--instance FiniteBits Word32 where- finiteBitSize _ = constant (B.finiteBitSize (undefined::Word32))- countLeadingZeros = mkCountLeadingZeros- countTrailingZeros = mkCountTrailingZeros--instance FiniteBits Word64 where- finiteBitSize _ = constant (B.finiteBitSize (undefined::Word64))- countLeadingZeros = mkCountLeadingZeros- countTrailingZeros = mkCountTrailingZeros--instance FiniteBits CInt where- finiteBitSize _ = constant (B.finiteBitSize (undefined::CInt))- countLeadingZeros = mkCountLeadingZeros- countTrailingZeros = mkCountTrailingZeros--instance FiniteBits CUInt where- finiteBitSize _ = constant (B.finiteBitSize (undefined::CUInt))- countLeadingZeros = mkCountLeadingZeros- countTrailingZeros = mkCountTrailingZeros--instance FiniteBits CLong where- finiteBitSize _ = constant (B.finiteBitSize (undefined::CLong))- countLeadingZeros = mkCountLeadingZeros- countTrailingZeros = mkCountTrailingZeros--instance FiniteBits CULong where- finiteBitSize _ = constant (B.finiteBitSize (undefined::CULong))- countLeadingZeros = mkCountLeadingZeros- countTrailingZeros = mkCountTrailingZeros--instance FiniteBits CLLong where- finiteBitSize _ = constant (B.finiteBitSize (undefined::CLLong))- countLeadingZeros = mkCountLeadingZeros- countTrailingZeros = mkCountTrailingZeros--instance FiniteBits CULLong where- finiteBitSize _ = constant (B.finiteBitSize (undefined::CULLong))- countLeadingZeros = mkCountLeadingZeros- countTrailingZeros = mkCountTrailingZeros--instance FiniteBits CShort where- finiteBitSize _ = constant (B.finiteBitSize (undefined::CShort))- countLeadingZeros = mkCountLeadingZeros- countTrailingZeros = mkCountTrailingZeros--instance FiniteBits CUShort where- finiteBitSize _ = constant (B.finiteBitSize (undefined::CUShort))- countLeadingZeros = mkCountLeadingZeros- countTrailingZeros = mkCountTrailingZeros---- instance FiniteBits CChar--- instance FiniteBits CUChar--- instance FiniteBits CSChar----- Default implementations--- -------------------------bitDefault :: (IsIntegral t, Bits t) => Exp Int -> Exp t-bitDefault x = constant 1 `shiftL` x--testBitDefault :: (IsIntegral t, Bits t) => Exp t -> Exp Int -> Exp Bool-testBitDefault x i = (x .&. bit i) /= constant 0--shiftDefault :: (FiniteBits t, IsIntegral t, B.Bits t) => Exp t -> Exp Int -> Exp t-shiftDefault x i- = cond (i >= 0) (shiftLDefault x i)- (shiftRDefault x (-i))--shiftLDefault :: (FiniteBits t, IsIntegral t) => Exp t -> Exp Int -> Exp t-shiftLDefault x i- = cond (i >= finiteBitSize x) (constant 0)- $ mkBShiftL x i--shiftRDefault :: forall t. (B.Bits t, FiniteBits t, IsIntegral t) => Exp t -> Exp Int -> Exp t-shiftRDefault- | B.isSigned (undefined::t) = shiftRADefault- | otherwise = shiftRLDefault---- Shift the argument right (signed)-shiftRADefault :: (FiniteBits t, IsIntegral t) => Exp t -> Exp Int -> Exp t-shiftRADefault x i- = cond (i >= finiteBitSize x) (cond (mkLt x (constant 0)) (constant (-1)) (constant 0))- $ mkBShiftR x i---- Shift the argument right (unsigned)-shiftRLDefault :: (FiniteBits t, IsIntegral t) => Exp t -> Exp Int -> Exp t-shiftRLDefault x i- = cond (i >= finiteBitSize x) (constant 0)- $ mkBShiftR x i--rotateDefault :: forall t. (FiniteBits t, IsIntegral t) => Exp t -> Exp Int -> Exp t-rotateDefault =- case (integralType :: IntegralType t) of- TypeInt{} -> rotateDefault' (undefined::Word)- TypeInt8{} -> rotateDefault' (undefined::Word8)- TypeInt16{} -> rotateDefault' (undefined::Word16)- TypeInt32{} -> rotateDefault' (undefined::Word32)- TypeInt64{} -> rotateDefault' (undefined::Word64)- TypeWord{} -> rotateDefault' (undefined::Word)- TypeWord8{} -> rotateDefault' (undefined::Word8)- TypeWord16{} -> rotateDefault' (undefined::Word16)- TypeWord32{} -> rotateDefault' (undefined::Word32)- TypeWord64{} -> rotateDefault' (undefined::Word64)- TypeCShort{} -> rotateDefault' (undefined::CUShort)- TypeCUShort{} -> rotateDefault' (undefined::CUShort)- TypeCInt{} -> rotateDefault' (undefined::CUInt)- TypeCUInt{} -> rotateDefault' (undefined::CUInt)- TypeCLong{} -> rotateDefault' (undefined::CULong)- TypeCULong{} -> rotateDefault' (undefined::CULong)- TypeCLLong{} -> rotateDefault' (undefined::CULLong)- TypeCULLong{} -> rotateDefault' (undefined::CULLong)--rotateDefault'- :: forall i w. (Elt w, FiniteBits i, IsIntegral i, IsIntegral w, BitSizeEq i w, BitSizeEq w i)- => w {- dummy -}- -> Exp i- -> Exp Int- -> Exp i-rotateDefault' _ x i- = cond (i' == 0) x- $ w2i ((x' `mkBShiftL` i') `mkBOr` (x' `mkBShiftR` (wsib - i')))- where- w2i = mkBitcast :: Exp w -> Exp i- i2w = mkBitcast :: Exp i -> Exp w- --- x' = i2w x- i' = i `mkBAnd` (wsib - 1)- wsib = finiteBitSize x--rotateLDefault :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t-rotateLDefault x i- = cond (i == 0) x- $ mkBRotateL x i--rotateRDefault :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t-rotateRDefault x i- = cond (i == 0) x- $ mkBRotateR x i--isSignedDefault :: forall b. B.Bits b => Exp b -> Exp Bool-isSignedDefault _ = constant (B.isSigned (undefined::b))--_popCountDefault :: forall a. (B.FiniteBits a, IsScalar a, Bits a, Num a) => Exp a -> Exp Int-_popCountDefault =- $( [e| case B.finiteBitSize (undefined::a) of- 8 -> popCnt8 . mkUnsafeCoerce- 16 -> popCnt16 . mkUnsafeCoerce- 32 -> popCnt32 . mkUnsafeCoerce- 64 -> popCnt64 . mkUnsafeCoerce- _ -> popCountKernighan |] )---- http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan-popCountKernighan :: (Bits a, Num a) => Exp a -> Exp Int-popCountKernighan x = r- where- (r,_) = untup2- $ while (\(untup2 -> (_,v)) -> v /= 0)- (\(untup2 -> (c,v)) -> tup2 (c+1, v .&. (v-1)))- (tup2 (0,x))---- http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel-popCnt8 :: Exp Word8 -> Exp Int-popCnt8 v1 = mkFromIntegral c- where- v2 = v1 - ((v1 `unsafeShiftR` 1) .&. 0x55)- v3 = (v2 .&. 0x33) + ((v2 `unsafeShiftR` 2) .&. 0x33)- v4 = (v3 + (v3 `unsafeShiftR` 4)) .&. 0x0F- c = v4 * 0x01--popCnt16 :: Exp Word16 -> Exp Int-popCnt16 v1 = mkFromIntegral c- where- v2 = v1 - ((v1 `unsafeShiftR` 1) .&. 0x5555)- v3 = (v2 .&. 0x3333) + ((v2 `unsafeShiftR` 2) .&. 0x3333)- v4 = (v3 + (v3 `unsafeShiftR` 4)) .&. 0x0F0F- c = (v4 * 0x0101) `unsafeShiftR` 8--popCnt32 :: Exp Word32 -> Exp Int-popCnt32 v1 = mkFromIntegral c- where- v2 = v1 - ((v1 `unsafeShiftR` 1) .&. 0x55555555)- v3 = (v2 .&. 0x33333333) + ((v2 `unsafeShiftR` 2) .&. 0x33333333)- v4 = (v3 + (v3 `unsafeShiftR` 4)) .&. 0x0F0F0F0F- c = (v4 * 0x01010101) `unsafeShiftR` 24--popCnt64 :: Exp Word64 -> Exp Int-popCnt64 v1 = mkFromIntegral c- where- v2 = v1 - ((v1 `unsafeShiftR` 1) .&. 0x5555555555555555)- v3 = (v2 .&. 0x3333333333333333) + ((v2 `unsafeShiftR` 2) .&. 0x3333333333333333)- v4 = (v3 + (v3 `unsafeShiftR` 4)) .&. 0X0F0F0F0F0F0F0F0F- c = (v4 * 0x0101010101010101) `unsafeShiftR` 56-
− Data/Array/Accelerate/Data/Complex.hs
@@ -1,202 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeSynonymInstances #-}-{-# LANGUAGE UndecidableInstances #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}--- |--- Module : Data.Array.Accelerate.Data.Complex--- Copyright : [2015..2017] Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)------ Complex numbers----module Data.Array.Accelerate.Data.Complex (-- -- * Rectangular from- Complex(..),- real,- imag,-- -- * Polar form- mkPolar,- cis,- polar,- magnitude,- phase,-- -- * Conjugate- conjugate,--) where--import Data.Array.Accelerate.Array.Sugar-import Data.Array.Accelerate.Classes as A-import Data.Array.Accelerate.Language-import Data.Array.Accelerate.Lift-import Data.Array.Accelerate.Product-import Data.Array.Accelerate.Smart-import Data.Array.Accelerate.Type--import Prelude ( ($), undefined, fromInteger )-import Data.Complex ( Complex(..) )-import qualified Data.Complex as C-import qualified Prelude as P---type instance EltRepr (Complex a) = EltRepr (a, a)--instance Elt a => Elt (Complex a) where- eltType _ = eltType (undefined :: (a,a))- toElt p = let (a, b) = toElt p in a :+ b- fromElt (a :+ b) = fromElt (a, b)--instance cst a => IsProduct cst (Complex a) where- type ProdRepr (Complex a) = ProdRepr (a, a)- fromProd cst (x :+ y) = fromProd cst (x, y)- toProd cst p = let (x, y) = toProd cst p in (x :+ y)- prod cst _ = prod cst (undefined :: (a, a))--instance (Lift Exp a, Elt (Plain a)) => Lift Exp (Complex a) where- type Plain (Complex a) = Complex (Plain a)- lift (x1 :+ x2) = Exp $ Tuple (NilTup `SnocTup` lift x1 `SnocTup` lift x2)--instance Elt a => Unlift Exp (Complex (Exp a)) where- unlift e- = let x = Exp $ SuccTupIdx ZeroTupIdx `Prj` e- y = Exp $ ZeroTupIdx `Prj` e- in- x :+ y--instance A.Eq a => A.Eq (Complex a) where- x == y = let r1 :+ c1 = unlift x- r2 :+ c2 = unlift y- in r1 == r2 && c1 == c2- x /= y = let r1 :+ c1 = unlift x- r2 :+ c2 = unlift y- in r1 /= r2 || c1 /= c2--instance A.RealFloat a => P.Num (Exp (Complex a)) where- (+) = lift2 ((+) :: Complex (Exp a) -> Complex (Exp a) -> Complex (Exp a))- (-) = lift2 ((-) :: Complex (Exp a) -> Complex (Exp a) -> Complex (Exp a))- (*) = lift2 ((*) :: Complex (Exp a) -> Complex (Exp a) -> Complex (Exp a))- negate = lift1 (negate :: Complex (Exp a) -> Complex (Exp a))- signum = lift1 (signum :: Complex (Exp a) -> Complex (Exp a))- abs = lift1 (abs :: Complex (Exp a) -> Complex (Exp a))- fromInteger n = lift ((fromInteger n :: Exp a) :+ 0)--instance A.RealFloat a => P.Fractional (Exp (Complex a)) where- c / c'- = let x :+ y = unlift c- x' :+ y' = unlift c' :: Complex (Exp a)- den = x' P.^ (2 :: Int) + y' P.^ (2 :: Int)- re = (x * x' + y * y') / den- im = (y * x' - x * y') / den- in- lift (re :+ im)-- fromRational x- = lift ((fromRational x :: Exp a) :+ 0)--instance A.RealFloat a => P.Floating (Exp (Complex a)) where- sqrt z- = let- x :+ y = unlift z- v' = abs y / (u'*2)- u' = sqrt ((magnitude z + abs x) / 2)- (u, v) = unlift $ cond (x < 0) (lift (v',u')) (lift (u',v'))- in- cond (x == 0 && y == 0)- {- then -} 0- {- else -} (lift (u :+ (cond (y < 0) (-v) v)))-- pi = lift (pi :: Complex (Exp a))- log z = lift (log (magnitude z) :+ phase z)- exp = lift1 (exp :: Complex (Exp a) -> Complex (Exp a))- sin = lift1 (sin :: Complex (Exp a) -> Complex (Exp a))- cos = lift1 (cos :: Complex (Exp a) -> Complex (Exp a))- tan = lift1 (tan :: Complex (Exp a) -> Complex (Exp a))- sinh = lift1 (sinh :: Complex (Exp a) -> Complex (Exp a))- cosh = lift1 (cosh :: Complex (Exp a) -> Complex (Exp a))- tanh = lift1 (tanh :: Complex (Exp a) -> Complex (Exp a))- asin = lift1 (asin :: Complex (Exp a) -> Complex (Exp a))- acos = lift1 (acos :: Complex (Exp a) -> Complex (Exp a))- atan = lift1 (atan :: Complex (Exp a) -> Complex (Exp a))- asinh = lift1 (asinh :: Complex (Exp a) -> Complex (Exp a))- acosh = lift1 (acosh :: Complex (Exp a) -> Complex (Exp a))- atanh = lift1 (atanh :: Complex (Exp a) -> Complex (Exp a))--instance (A.FromIntegral a b, A.Num b) => A.FromIntegral a (Complex b) where- fromIntegral x = lift (fromIntegral x :+ (0 :: Exp b))----- | The non-negative magnitude of a complex number----magnitude :: RealFloat a => Exp (Complex a) -> Exp a-magnitude c =- let r :+ i = unlift c- in sqrt (r*r + i*i)---- | The phase of a complex number, in the range @(-'pi', 'pi']@. If the--- magnitude is zero, then so is the phase.----phase :: RealFloat a => Exp (Complex a) -> Exp a-phase c =- let x :+ y = unlift c- in atan2 y x---- | The function 'polar' takes a complex number and returns a (magnitude,--- phase) pair in canonical form: the magnitude is non-negative, and the phase--- in the range @(-'pi', 'pi']@; if the magnitude is zero, then so is the phase.----polar :: RealFloat a => Exp (Complex a) -> Exp (a,a)-polar z = lift (magnitude z, phase z)---- | Form a complex number from polar components of magnitude and phase.----#if __GLASGOW_HASKELL__ <= 708-mkPolar :: forall a. RealFloat a => Exp a -> Exp a -> Exp (Complex a)-#else-mkPolar :: forall a. Floating a => Exp a -> Exp a -> Exp (Complex a)-#endif-mkPolar = lift2 (C.mkPolar :: Exp a -> Exp a -> Complex (Exp a))---- | @'cis' t@ is a complex value with magnitude @1@ and phase @t@ (modulo--- @2*'pi'@).----#if __GLASGOW_HASKELL__ <= 708-cis :: forall a. RealFloat a => Exp a -> Exp (Complex a)-#else-cis :: forall a. Floating a => Exp a -> Exp (Complex a)-#endif-cis = lift1 (C.cis :: Exp a -> Complex (Exp a))---- | Return the real part of a complex number----real :: Elt a => Exp (Complex a) -> Exp a-real c =- let r :+ _ = unlift c- in r---- | Return the imaginary part of a complex number----imag :: Elt a => Exp (Complex a) -> Exp a-imag c =- let _ :+ i = unlift c- in i---- | Return the complex conjugate of a complex number, defined as------ > conjugate(Z) = X - iY----conjugate :: Num a => Exp (Complex a) -> Exp (Complex a)-conjugate z = lift $ real z :+ (- imag z)-
− Data/Array/Accelerate/Data/Fold.hs
@@ -1,155 +0,0 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE TypeOperators #-}--- |--- Module : Data.Array.Accelerate.Data.Fold--- Copyright : [2016..2017] Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)------ Combine folds in 'Applicative' style to generate multiple results with--- a single pass over the array. Based on Max Rabkin's "Beautiful Folding" [1]--- and talks by Gabriel Gonzalez [2].------ 1. <http://squing.blogspot.com/2008/11/beautiful-folding.html>--- 2. <https://www.youtube.com/watch?v=6a5Ti0r8Q2s>-----module Data.Array.Accelerate.Data.Fold (-- Fold(..), runFold,--) where--import Data.Array.Accelerate hiding ( fold, sum, product, length )-import Data.Array.Accelerate.Data.Monoid-import qualified Data.Array.Accelerate as A--import Control.Applicative as P-import Prelude hiding ( sum, product, length )-import qualified Prelude as P----- | 'Fold' describes how to process data of some 'i'nput type into some--- 'o'utput type, via a reduction using some intermediate Monoid 'w'. For--- example, both 'sum' and 'length' below use the 'Sum' monoid:------ >>> let sum = Fold (lift . Sum) (getSum . unlift)--- >>> let length = Fold (\_ -> 1) (getSum . unlift)------ The key is that 'Fold's can be combined using 'Applicative' in order to--- produce multiple outputs from a /single/ reduction of the array. For example:------ >>> let average = (/) <$> sum <*> length------ This computes both the sum of the array as well as its length in a single--- traversal, then combines both results to compute the average.------ Because 'Fold' has some numeric instances, this can also be defined more--- succinctly as:------ >>> let average = sum / length------ A more complex example:------ >>> let sumOfSquares = Fold (lift . Sum . (^2)) (getSum . unlift)--- >>> let standardDeviation = sqrt ((sumOfSquares / length) - (sum / length) ^ 2)------ These will all execute with a single reduction kernel and a single map to--- summarise (combine) the results.----data Fold i o where- Fold :: (Elt w, Monoid (Exp w))- => (i -> Exp w) -- transform input element into internal monoid type- -> (Exp w -> o) -- summarise the reduction to retrieve the final result- -> Fold i o---- | Apply a 'Fold' to an array.----runFold- :: (Shape sh, Elt i, Elt o)- => Fold (Exp i) (Exp o)- -> Acc (Array (sh:.Int) i)- -> Acc (Array sh o)-runFold (Fold tally summarise) is- = A.map summarise- $ A.fold (<>) mempty- $ A.map tally is----- sum :: A.Num e => Fold (Exp e) (Exp e)--- sum = Fold (lift . Sum) (getSum . unlift)---- product :: A.Num e => Fold (Exp e) (Exp e)--- product = Fold (lift . Product) (getProduct . unlift)---- length :: A.Num i => Fold (Exp e) (Exp i)--- length = Fold (\_ -> 1) (getSum . unlift)----- combine2 :: (Elt a, Elt b) => Exp a -> Exp b -> Exp (a,b)--- combine2 a b = lift (a,b)---- combine3 :: (Elt a, Elt b, Elt c) => Exp a -> Exp b -> Exp c -> Exp (a,b,c)--- combine3 a b c = lift (a,b,c)---- combine4 :: (Elt a, Elt b, Elt c, Elt d) => Exp a -> Exp b -> Exp c -> Exp d -> Exp (a,b,c,d)--- combine4 a b c d = lift (a,b,c,d)---- combine5 :: (Elt a, Elt b, Elt c, Elt d, Elt e) => Exp a -> Exp b -> Exp c -> Exp d -> Exp e -> Exp (a,b,c,d,e)--- combine5 a b c d e = lift (a,b,c,d,e)----- Instances for 'Fold'--- ----------------------instance P.Functor (Fold i) where- fmap k (Fold tally summarise) = Fold tally (k . summarise)--instance P.Applicative (Fold i) where- pure o = Fold (\_ -> constant ()) (\_ -> o)- Fold tF sF <*> Fold tX sX = Fold tally summarise- where- tally i = lift (tF i, tX i)- summarise t = let (mF, mX) = unlift t- in sF mF (sX mX)--instance A.Num b => P.Num (Fold a (Exp b)) where- (+) = liftA2 (+)- (-) = liftA2 (-)- (*) = liftA2 (*)- negate = fmap negate- abs = fmap abs- signum = fmap signum- fromInteger n = pure (fromInteger n)--instance A.Fractional b => P.Fractional (Fold a (Exp b)) where- (/) = liftA2 (/)- recip = fmap recip- fromRational n = pure (fromRational n)--instance A.Floating b => P.Floating (Fold a (Exp b)) where- pi = pure pi- sin = fmap sin- cos = fmap cos- tan = fmap tan- asin = fmap asin- acos = fmap acos- atan = fmap atan- sinh = fmap sinh- cosh = fmap cosh- tanh = fmap tanh- asinh = fmap asinh- acosh = fmap acosh- atanh = fmap atanh- exp = fmap exp- sqrt = fmap sqrt- log = fmap log- (**) = liftA2 (**)- logBase = liftA2 logBase-
− Data/Array/Accelerate/Data/Monoid.hs
@@ -1,172 +0,0 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}--- |--- Module : Data.Array.Accelerate.Data.Monoid--- Copyright : [2016..2017] Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)------ Monoid instances for Accelerate-----module Data.Array.Accelerate.Data.Monoid (-- Monoid(..), (<>),-- Sum(..),- Product(..),--) where--import Data.Array.Accelerate as A-import Data.Array.Accelerate.Type as A-import Data.Array.Accelerate.Smart as A ( Exp(..), PreExp(..) )-import Data.Array.Accelerate.Product as A-import Data.Array.Accelerate.Array.Sugar as A--import Data.Function-import Data.Monoid hiding ( mconcat )-import qualified Prelude as P----- Sum: Monoid under addition--- ----------------------------type instance EltRepr (Sum a) = ((), EltRepr a)--instance Elt a => Elt (Sum a) where- eltType _ = PairTuple UnitTuple (eltType (undefined::a))- toElt ((),x) = Sum (toElt x)- fromElt (Sum x) = ((), fromElt x)--instance Elt a => IsProduct Elt (Sum a) where- type ProdRepr (Sum a) = ((), a)- toProd _ ((),a) = Sum a- fromProd _ (Sum a) = ((),a)- prod _ _ = ProdRsnoc ProdRunit--instance (Lift Exp a, Elt (Plain a)) => Lift Exp (Sum a) where- type Plain (Sum a) = Sum (Plain a)- lift (Sum a) = Exp $ Tuple $ NilTup `SnocTup` lift a--instance Elt a => Unlift Exp (Sum (Exp a)) where- unlift t = Sum . Exp $ ZeroTupIdx `Prj` t--instance A.Num a => Monoid (Exp (Sum a)) where- mempty = 0- mappend = lift2 (mappend :: Sum (Exp a) -> Sum (Exp a) -> Sum (Exp a))--instance A.Num a => P.Num (Exp (Sum a)) where- (+) = lift2 ((+) :: Sum (Exp a) -> Sum (Exp a) -> Sum (Exp a))- (-) = lift2 ((-) :: Sum (Exp a) -> Sum (Exp a) -> Sum (Exp a))- (*) = lift2 ((*) :: Sum (Exp a) -> Sum (Exp a) -> Sum (Exp a))- negate = lift1 (negate :: Sum (Exp a) -> Sum (Exp a))- signum = lift1 (signum :: Sum (Exp a) -> Sum (Exp a))- abs = lift1 (signum :: Sum (Exp a) -> Sum (Exp a))- fromInteger x = lift (P.fromInteger x :: Sum (Exp a))--instance A.Eq a => A.Eq (Sum a) where- (==) = lift2 ((==) `on` getSum)- (/=) = lift2 ((/=) `on` getSum)--instance A.Ord a => A.Ord (Sum a) where- (<) = lift2 ((<) `on` getSum)- (>) = lift2 ((>) `on` getSum)- (<=) = lift2 ((<=) `on` getSum)- (>=) = lift2 ((>=) `on` getSum)- min x y = lift . Sum $ lift2 (min `on` getSum) x y- max x y = lift . Sum $ lift2 (max `on` getSum) x y----- Product: Monoid under multiplication--- --------------------------------------type instance EltRepr (Product a) = ((), EltRepr a)--instance Elt a => Elt (Product a) where- eltType _ = PairTuple UnitTuple (eltType (undefined::a))- toElt ((),x) = Product (toElt x)- fromElt (Product x) = ((), fromElt x)--instance Elt a => IsProduct Elt (Product a) where- type ProdRepr (Product a) = ((), a)- toProd _ ((),a) = Product a- fromProd _ (Product a) = ((),a)- prod _ _ = ProdRsnoc ProdRunit--instance (Lift Exp a, Elt (Plain a)) => Lift Exp (Product a) where- type Plain (Product a) = Product (Plain a)- lift (Product a) = Exp $ Tuple $ NilTup `SnocTup` lift a--instance Elt a => Unlift Exp (Product (Exp a)) where- unlift t = Product . Exp $ ZeroTupIdx `Prj` t--instance A.Num a => Monoid (Exp (Product a)) where- mempty = 1- mappend = lift2 (mappend :: Product (Exp a) -> Product (Exp a) -> Product (Exp a))--instance A.Num a => P.Num (Exp (Product a)) where- (+) = lift2 ((+) :: Product (Exp a) -> Product (Exp a) -> Product (Exp a))- (-) = lift2 ((-) :: Product (Exp a) -> Product (Exp a) -> Product (Exp a))- (*) = lift2 ((*) :: Product (Exp a) -> Product (Exp a) -> Product (Exp a))- negate = lift1 (negate :: Product (Exp a) -> Product (Exp a))- signum = lift1 (signum :: Product (Exp a) -> Product (Exp a))- abs = lift1 (signum :: Product (Exp a) -> Product (Exp a))- fromInteger x = lift (P.fromInteger x :: Product (Exp a))--instance A.Eq a => A.Eq (Product a) where- (==) = lift2 ((==) `on` getProduct)- (/=) = lift2 ((/=) `on` getProduct)--instance A.Ord a => A.Ord (Product a) where- (<) = lift2 ((<) `on` getProduct)- (>) = lift2 ((>) `on` getProduct)- (<=) = lift2 ((<=) `on` getProduct)- (>=) = lift2 ((>=) `on` getProduct)- min x y = lift . Product $ lift2 (min `on` getProduct) x y- max x y = lift . Product $ lift2 (max `on` getProduct) x y----- Instances for unit and tuples--- -------------------------------instance Monoid (Exp ()) where- mempty = constant ()- mappend _ _ = constant ()--instance (Elt a, Elt b, Monoid (Exp a), Monoid (Exp b)) => Monoid (Exp (a,b)) where- mempty = lift (mempty :: Exp a, mempty :: Exp b)- mappend x y = let (a1,b1) = unlift x :: (Exp a, Exp b)- (a2,b2) = unlift y- in- lift (a1<>a2, b1<>b2)--instance (Elt a, Elt b, Elt c, Monoid (Exp a), Monoid (Exp b), Monoid (Exp c)) => Monoid (Exp (a,b,c)) where- mempty = lift (mempty :: Exp a, mempty :: Exp b, mempty :: Exp c)- mappend x y = let (a1,b1,c1) = unlift x :: (Exp a, Exp b, Exp c)- (a2,b2,c2) = unlift y- in- lift (a1<>a2, b1<>b2, c1<>c2)--instance (Elt a, Elt b, Elt c, Elt d, Monoid (Exp a), Monoid (Exp b), Monoid (Exp c), Monoid (Exp d)) => Monoid (Exp (a,b,c,d)) where- mempty = lift (mempty :: Exp a, mempty :: Exp b, mempty :: Exp c, mempty :: Exp d)- mappend x y = let (a1,b1,c1,d1) = unlift x :: (Exp a, Exp b, Exp c, Exp d)- (a2,b2,c2,d2) = unlift y- in- lift (a1<>a2, b1<>b2, c1<>c2, d1<>d2)--instance (Elt a, Elt b, Elt c, Elt d, Elt e, Monoid (Exp a), Monoid (Exp b), Monoid (Exp c), Monoid (Exp d), Monoid (Exp e)) => Monoid (Exp (a,b,c,d,e)) where- mempty = lift (mempty :: Exp a, mempty :: Exp b, mempty :: Exp c, mempty :: Exp d, mempty :: Exp e)- mappend x y = let (a1,b1,c1,d1,e1) = unlift x :: (Exp a, Exp b, Exp c, Exp d, Exp e)- (a2,b2,c2,d2,e2) = unlift y- in- lift (a1<>a2, b1<>b2, c1<>c2, d1<>d2, e1<>e2)-
− Data/Array/Accelerate/Debug.hs
@@ -1,120 +0,0 @@-{-# LANGUAGE CPP #-}-{-# OPTIONS_HADDOCK hide #-}--- |--- Module : Data.Array.Accelerate.Debug--- Copyright : [2008..2017] Manuel M T Chakravarty, Gabriele Keller--- [2009..2017] Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)------ Embedded array processing language: debugging support (internal). This module--- provides functionality that is useful for developers of the library. It is--- not meant for library users.-----module Data.Array.Accelerate.Debug (-- module Debug,-- dumpGraph,- dumpSimplStats,-- monitoringIsEnabled,- debuggingIsEnabled,--) where--import Data.Array.Accelerate.Debug.Flags as Debug-import Data.Array.Accelerate.Debug.Monitoring as Debug-import Data.Array.Accelerate.Debug.Stats as Debug-import Data.Array.Accelerate.Debug.Timed as Debug-import Data.Array.Accelerate.Debug.Trace as Debug--import Data.Array.Accelerate.Pretty.Graphviz--import Control.Monad.Trans ( MonadIO )--#if ACCELERATE_DEBUG-import Control.Exception ( bracket )-import Control.Monad.Trans ( liftIO )-import System.Directory ( getTemporaryDirectory, createDirectoryIfMissing )-import System.FilePath ( (</>) )-import System.IO ( Handle, openTempFile, hPutStrLn, hPrint, hClose, stderr )--#if defined(UNIX)-import System.Posix.Process ( getProcessID )-#elif defined(WIN32)-import System.Win32.Process ( ProcessId )-#else-#error "I don't know what operating system I am"-#endif-#endif---debuggingIsEnabled :: Bool-#if ACCELERATE_DEBUG-debuggingIsEnabled = True-#else-debuggingIsEnabled = False-#endif--monitoringIsEnabled :: Bool-#if ACCELERATE_MONITORING-monitoringIsEnabled = True-#else-monitoringIsEnabled = False-#endif----- | Display simplifier statistics. The counts are reset afterwards.----{-# INLINEABLE dumpSimplStats #-}-dumpSimplStats :: MonadIO m => m ()-#if ACCELERATE_DEBUG-dumpSimplStats = do- liftIO $ Debug.when dump_simpl_stats $ do- stats <- simplCount- putTraceMsg (show stats)- resetSimplCount-#else-dumpSimplStats = return ()-#endif----- | Write a representation of the given input (a closed array expression or--- function) to file in Graphviz dot format in the temporary directory.----{-# INLINEABLE dumpGraph #-}-dumpGraph :: (MonadIO m, PrettyGraph g) => g -> m ()-#if ACCELERATE_DEBUG-dumpGraph g =- liftIO $ do- Debug.when dump_dot $ writeGraph Full g- Debug.when dump_simpl_dot $ writeGraph Simple g-#else-dumpGraph _ = return ()-#endif--#if ACCELERATE_DEBUG-writeGraph :: PrettyGraph g => Detail -> g -> IO ()-writeGraph simple g = do- withTemporaryFile "acc.dot" $ \path hdl -> do- hPrint hdl (ppGraph simple g)- hPutStrLn stderr ("program graph: " ++ path)--withTemporaryFile :: String -> (FilePath -> Handle -> IO a) -> IO a-withTemporaryFile template go = do- pid <- getProcessID- tmp <- getTemporaryDirectory- let dir = tmp </> "accelerate-" ++ show pid- createDirectoryIfMissing True dir- bracket (openTempFile dir template) (hClose . snd) (uncurry go)--#ifdef WIN32-getProcessID :: IO ProcessId-getProcessID = return 0xaaaa-#endif-#endif
− Data/Array/Accelerate/Debug/Flags.hs
@@ -1,343 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE ForeignFunctionInterface #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TypeOperators #-}-#ifdef ACCELERATE_DEBUG-#if __GLASGOW_HASKELL >= 800-{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}-#endif-#else-{-# OPTIONS_GHC -fno-warn-unused-binds #-}-{-# OPTIONS_GHC -fno-warn-unused-do-bind #-}-{-# OPTIONS_GHC -fno-warn-unused-imports #-}-#endif--- |--- Module : Data.Array.Accelerate.Debug.Flags--- Copyright : [2008..2017] Manuel M T Chakravarty, Gabriele Keller--- [2009..2017] Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)------ Option parsing for debug flags-----module Data.Array.Accelerate.Debug.Flags (-- Flags, Mode,- acc_sharing, exp_sharing, fusion, simplify, flush_cache, force_recomp, fast_math, verbose,- dump_phases, dump_sharing, dump_simpl_stats, dump_simpl_iterations, dump_vectorisation,- dump_dot, dump_simpl_dot, dump_gc, dump_gc_stats, debug_cc, dump_cc, dump_ld, dump_asm,- dump_exec, dump_sched,-- accInit,- queryFlag, setFlag, setFlag', setFlags, clearFlag, clearFlags,- when, unless,--) where--import Control.Monad.IO.Class-import Data.IORef-import Data.Label-import Data.Label.Derive-import Data.List-import System.Environment-import System.IO.Unsafe-import Text.PrettyPrint.ANSI.Leijen-import qualified Control.Monad as M ( when, unless )--import Foreign.C-import Foreign.Marshal-import Foreign.Ptr-import GHC.Foreign as GHC-import GHC.IO.Encoding ( getFileSystemEncoding )--import Debug.Trace---data FlagSpec flag = Option String -- external form- flag -- internal form--data OptKind f- = NoArg f- | IntArg (Int -> f)----- The runtime debug and control options supported by Accelerate. This is a bit--- awkward, as we process both frontend as well as backend option flags, but--- gives some control over error messages and overlapping options.----data Flags = Flags- {- -- Functionality and phase control- -- -------------------------------- --- -- These are Maybe types because they will only override the backend- -- options if the user specifies a value- --- _acc_sharing :: !(Maybe Bool) -- recover sharing of array computations- , _exp_sharing :: !(Maybe Bool) -- recover sharing of scalar expressions- , _fusion :: !(Maybe Bool) -- fuse array expressions- , _simplify :: !(Maybe Bool) -- simplify scalar expressions- , _unfolding_use_threshold :: !(Maybe Int) -- the magic cut-off figure for inlining- , _flush_cache :: !(Maybe Bool) -- delete persistent compilation cache(s)- , _force_recomp :: !(Maybe Bool) -- force recompilation of array programs- , _fast_math :: !(Maybe Bool) -- use faster, less precise math library operations-- -- Debug trace- -- ------------ , _verbose :: !Bool -- be very chatty-- -- optimisation and simplification- , _dump_phases :: !Bool -- print information about each phase of the compiler- , _dump_sharing :: !Bool -- sharing recovery phase- , _dump_simpl_stats :: !Bool -- statistics form fusion/simplification- , _dump_simpl_iterations :: !Bool -- output from each simplifier iteration- , _dump_vectorisation :: !Bool -- output from the vectoriser- , _dump_dot :: !Bool -- generate dot output of the program- , _dump_simpl_dot :: !Bool -- generate simplified dot output-- -- garbage collection- , _dump_gc :: !Bool -- trace garbage collector- , _dump_gc_stats :: !Bool -- print final GC statistics-- -- code generation / compilation- , _debug_cc :: !Bool -- compile with debug symbols- , _dump_cc :: !Bool -- trace code generation & compilation- , _dump_ld :: !Bool -- trace runtime linker- , _dump_asm :: !Bool -- trace assembler-- -- execution- , _dump_exec :: !Bool -- trace execution- , _dump_sched :: !Bool -- trace scheduler- }---- Generate labels with INLINE pragmas-$(mkLabelsWith defaultNaming True False False True ''Flags)---allFlags :: [FlagSpec (OptKind (Flags -> Flags))]-allFlags- = map (enableB 'd') dflags- ++ map (enableB 'f') fflagsB ++ map (disableB 'f') fflagsB- ++ map (enableI 'f') fflagsI- where- enableI p (Option f go) = Option ('-':p:f) (IntArg go)- enableB p (Option f go) = Option ('-':p:f) (NoArg (go True))- disableB p (Option f go) = Option ('-':p:"no-"++f) (NoArg (go False))----- These @-f\<blah\>@ phase control flags can be reversed with @-fno-\<blah\>@----fflagsB :: [FlagSpec (Bool -> Flags -> Flags)]-fflagsB =- [ Option "acc-sharing" (set' acc_sharing)- , Option "exp-sharing" (set' exp_sharing)- , Option "fusion" (set' fusion)- , Option "simplify" (set' simplify)- , Option "flush-cache" (set' flush_cache)- , Option "force-recomp" (set' force_recomp)- , Option "fast-math" (set' fast_math)- ]- where- set' f v = set f (Just v)---- These @-f\<blah\>@ flags require an integer argument----fflagsI :: [FlagSpec (Int -> Flags -> Flags)]-fflagsI =- [ Option "unfolding-use-threshold" (set' unfolding_use_threshold)- ]- where- set' f v = set f (Just v)---- These debugging flags default to off and can be enable with @-d\<blah\>@----dflags :: [FlagSpec (Bool -> Flags -> Flags)]-dflags =- [ Option "verbose" (set verbose)- , Option "dump-phases" (set dump_phases)- , Option "dump-sharing" (set dump_sharing)- , Option "dump-simpl-stats" (set dump_simpl_stats)- , Option "dump-simpl-iterations" (set dump_simpl_iterations)- , Option "dump-vectorisation" (set dump_vectorisation)- , Option "dump-dot" (set dump_dot)- , Option "dump-simpl-dot" (set dump_simpl_dot)- , Option "dump-gc" (set dump_gc)- , Option "dump-gc-stats" (set dump_gc_stats)- , Option "debug-cc" (set debug_cc)- , Option "dump-cc" (set dump_cc)- , Option "dump-ld" (set dump_ld)- , Option "dump-asm" (set dump_asm)- , Option "dump-exec" (set dump_exec)- , Option "dump-sched" (set dump_sched)- ]---class DebugFlag a where- def :: a--instance DebugFlag Bool where- {-# INLINE def #-}- def = False--instance DebugFlag (Maybe a) where- {-# INLINE def #-}- def = Nothing----- | A bit of a hack to get the command line options processing out of the way.------ We would like to have this automatically called once during program--- initialisation, so that our command-line debug flags between +ACC .. [-ACC]--- don't interfere with other programs.------ Hacks beget hacks beget hacks...----accInit :: IO ()-#ifdef ACCELERATE_DEBUG-accInit = _flags `seq` return ()-#else-accInit = getUpdateArgs >> return ()-#endif---- Initialise the debugging flags structure. This reads from both the command--- line arguments as well as the environment variable "ACCELERATE_FLAGS".--- Where applicable, options on the command line take precedence.------ This is only available when compiled with debugging mode, because trying to--- access it at any other time is an error.----#ifdef ACCELERATE_DEBUG-initialiseFlags :: IO Flags-initialiseFlags = do- argv <- getUpdateArgs- env <- maybe [] words `fmap` lookupEnv "ACCELERATE_FLAGS"- return $ parse (env ++ argv)- where- defaults :: Flags- defaults = Flags def def def def def def def def def def def def def def def def def def def def def def def def-- parse :: [String] -> Flags- parse = foldl parse1 defaults-- parse1 :: Flags -> String -> Flags- parse1 opts this =- case filter (\(Option flag _) -> prefix `isPrefixOf` flag) allFlags of- [Option _ f] -> apply f- [] -> trace unknown opts- alts -> case find (\(Option flag _) -> flag == prefix) alts of- Just (Option _ f) -> apply f- Nothing -> trace (ambiguous alts) opts- where- apply :: OptKind (Flags -> Flags) -> Flags- apply (NoArg f) = f opts- apply (IntArg f) = f (read suffix) opts-- (prefix,rest) = break (== '=') this- suffix = if null rest then [] else tail rest-- unknown = show $ text "Unknown option:" <+> squotes (text this)- ambiguous alts = show $- vcat [ text "Ambiguous option:" <+> squotes (text this)- , text ""- , text "Did you mean one of these?"- , nest 4 $ vcat (map (\(Option s _) -> text s) alts)- ]-#endif----- If the command line arguments include a section "+ACC ... [-ACC]" then return--- that section, and update the command line arguments to not include that part.----getUpdateArgs :: IO [String]-getUpdateArgs = do- argv <- getArgs- --- let (before, r1) = span (/= "+ACC") argv- (flags, r2) = span (/= "-ACC") $ dropWhile (== "+ACC") r1- after = dropWhile (== "-ACC") r2- ---#ifdef ACCELERATE_DEBUG- prog <- getProgName- setProgArgv (prog : before ++ after)-#else- M.unless (null flags)- $ error "Data.Array.Accelerate: Debugging options are disabled. Reinstall package 'accelerate' with '-fdebug' to enable them."-#endif- return flags----- This is only defined in debug mode because to access it at any other time--- should be an error.----#ifdef ACCELERATE_DEBUG-{-# NOINLINE _flags #-}-_flags :: IORef Flags-_flags = unsafePerformIO $ newIORef =<< initialiseFlags-#endif--{-# INLINE queryFlag #-}-queryFlag :: DebugFlag a => (Flags :-> a) -> IO a-#ifdef ACCELERATE_DEBUG-queryFlag f = get f `fmap` readIORef _flags-#else-queryFlag _ = return def-#endif---type Mode = Flags :-> Bool--setFlag, clearFlag :: Mode -> IO ()-setFlag f = setFlags [f]-clearFlag f = clearFlags [f]--setFlag' :: (Flags :-> a) -> a -> IO ()-#ifdef ACCELERATE_DEBUG-setFlag' f v = modifyIORef _flags (set f v)-#else-setFlag' _ _ = return ()-#endif--setFlags, clearFlags :: [Mode] -> IO ()-#ifdef ACCELERATE_DEBUG-setFlags f = modifyIORef _flags (\opt -> foldr (flip set True) opt f)-clearFlags f = modifyIORef _flags (\opt -> foldr (flip set False) opt f)-#else-setFlags _ = return ()-clearFlags _ = return ()-#endif----- | Conditional execution of a monadic debugging expression----{-# INLINEABLE when #-}-when :: MonadIO m => Mode -> m () -> m ()-when f s = do- yes <- liftIO $ queryFlag f- M.when yes s---- | The opposite of 'when'----{-# INLINEABLE unless #-}-unless :: MonadIO m => Mode -> m () -> m ()-unless f s = do- yes <- liftIO $ queryFlag f- M.unless yes s---#ifdef ACCELERATE_DEBUG--- Stolen from System.Environment----setProgArgv :: [String] -> IO ()-setProgArgv argv = do- enc <- getFileSystemEncoding- vs <- mapM (GHC.newCString enc) argv >>= newArray0 nullPtr- c_setProgArgv (genericLength argv) vs--foreign import ccall unsafe "setProgArgv"- c_setProgArgv :: CInt -> Ptr CString -> IO ()-#endif-
− Data/Array/Accelerate/Debug/Monitoring.hs
@@ -1,459 +0,0 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards #-}-{-# OPTIONS_HADDOCK hide #-}--- |--- Module : Data.Array.Accelerate.Debug.Monitoring--- Copyright : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Debug.Monitoring (-- beginMonitoring,- initAccMetrics,-- -- Load monitoring- Processor(..),- withProcessor, addProcessorTime,-- -- GC subsystem monitoring- didAllocateBytesLocal, didAllocateBytesRemote,- didCopyBytesToRemote, didCopyBytesFromRemote,- increaseCurrentBytesRemote, decreaseCurrentBytesRemote,- setCurrentBytesNursery,- didRemoteGC,- didEvictBytes,--) where--#ifdef ACCELERATE_MONITORING-import Data.Atomic ( Atomic )-import qualified Data.Atomic as Atomic--import System.Metrics-import System.Metrics.Counter ( Counter )-import System.Metrics.Gauge ( Gauge )-import qualified System.Metrics.Counter as Counter-import qualified System.Metrics.Gauge as Gauge--import Control.Concurrent-import Control.Concurrent.Async-import Control.Monad-import Data.IORef-import Data.Text ( Text )-import Data.Time.Clock-import System.IO.Unsafe-import System.Remote.Monitoring-import Text.Printf-import qualified Data.HashMap.Strict as Map-#endif--import Data.Int-import Prelude----- | Launch a monitoring server that will collect statistics on the running--- application. This should be called as soon as the application starts. The--- program will need to be run with the RTS option -T.----beginMonitoring :: IO ()-#ifdef ACCELERATE_MONITORING-beginMonitoring = do- store <- initAccMetrics- registerGcMetrics store- r <- withAsync (forkServerWith store "localhost" 8000 >> threadDelay 10000) waitCatch- case r of- Right _ -> printf "EKG monitor started at: http://localhost:8000\n"- Left _ -> printf "Failed to start EKG monitor\n"-#else-beginMonitoring = return ()-#endif----- | Initialise and return the Accelerate monitoring store. To enable monitoring--- of your application:------ > import Data.Array.Accelerate.Debug--- >--- > import System.Metrics--- > import System.Remote.Monitoring--- >--- > main :: IO ()--- > main = do--- > store <- initAccMetrics--- > registerGcMetrics store -- optional--- >--- > server <- forkServerWith store "localhost" 8000--- >--- > ...------ Note that aside from the processor load metrics, counters are shared between--- all active backends.------ Registered rates:------ [@acc.load.llvm_native@] Current processor load (%) of the LLVM CPU backend.--- This only includes time spent executing Accelerate functions; compare this to--- the total processor load (e.g. via top) to estimate the productivity of the--- Accelerate program.------ [@acc.load.llvm_ptx@] Current processor load (%) of the GPU in the LLVM PTX--- backend. This only takes into account how much time the GPU spent executing--- Accelerate code, and does not consider the number of active cores during that--- time.------ Registered gauges:------ [@acc.gc.current_bytes_remote@] Total number of bytes currently considered--- live in the remote address space.------ [@acc.gc.current_bytes_nursery@] Total number of bytes allocated in the--- remote address space but not currently live (available for reallocation).------ Registered counters:------ [@acc.gc.bytes_allocated_local@] Total number of bytes allocated in the local--- address space.------ [@acc.gc.bytes_allocated_remote@] Total number of bytes allocated in the--- remote address space.------ [@acc.gc.bytes_copied_to_remote@] Total number of bytes copied from the host--- to the remote address space (e.g. from the CPU to the GPU).------ [@acc.gc.bytes_copied_from_remote@] Total number of bytes copied from the--- remote address space back to the host (e.g. from the GPU back to the CPU).------ [@acc.gc.bytes_evicted_from_remote@] Total number of bytes evicted from the--- remote address space by the LRU memory manager, in order to make space for--- new allocations. A subset of __acc.gc.bytes_copied_from_remote__.------ [@acc.gc.num_gcs@] Number of garbage collections of the remote address space--- performed.------ [@acc.gc.num_lru_evict@] Total number of evictions from the remote address--- space performed.----#ifndef ACCELERATE_MONITORING-initAccMetrics :: IO a-initAccMetrics = error "Data.Array.Accelerate: Monitoring is disabled. Reinstall package 'accelerate' with '-fekg' to enable it."-#else-initAccMetrics :: IO Store-initAccMetrics = do- store <- newStore-- registerRate "acc.load.llvm_native" (estimateProcessorLoad _active_ns_llvm_native) store- registerRate "acc.load.llvm_ptx" (estimateProcessorLoad _active_ns_llvm_ptx) store- registerGauge "acc.gc.current_bytes_remote" (Gauge.read _current_bytes_remote) store- registerGauge "acc.gc.current_bytes_nursery" (Gauge.read _current_bytes_nursery) store- registerCounter "acc.gc.bytes_allocated_local" (Counter.read _total_bytes_allocated_local) store- registerCounter "acc.gc.bytes_allocated_remote" (Counter.read _total_bytes_allocated_remote) store- registerCounter "acc.gc.bytes_copied_to_remote" (Counter.read _total_bytes_copied_to_remote) store- registerCounter "acc.gc.bytes_copied_from_remote" (Counter.read _total_bytes_copied_from_remote) store- registerCounter "acc.gc.bytes_evicted_from_remote" (Counter.read _total_bytes_evicted_from_remote) store- registerCounter "acc.gc.num_gcs" (Counter.read _num_remote_gcs) store- registerCounter "acc.gc.num_lru_evict" (Counter.read _num_evictions) store-- return store----- Abusing 'registerGroup' to perform the rate calculation on every wake-up.----registerRate :: Text -> (IORef EMAState -> IO Int64) -> Store -> IO ()-registerRate name sample store = do- now <- getCurrentTime- st <- newIORef (ES now 0 0)- registerGroup (Map.singleton name Gauge) (sample st) store-#endif----- Recording metrics--- -------------------data Processor = Native | PTX---- | Execute the given action and assign the elapsed wall-clock time as active--- time for the given processing element.----{-# INLINE withProcessor #-}-withProcessor :: Processor -> IO a -> IO a-#ifndef ACCELERATE_MONITORING-withProcessor _ = id-#else-withProcessor Native = withProcessor' _active_ns_llvm_native-withProcessor PTX = withProcessor' _active_ns_llvm_ptx--withProcessor' :: Atomic -> IO a -> IO a-withProcessor' var action = do- wall0 <- getCurrentTime- !r <- action- wall1 <- getCurrentTime- addProcessorTime' var (realToFrac (diffUTCTime wall1 wall0))- return r-#endif---- | Record the given number of seconds as active processing time for the given--- processing element.----{-# INLINE addProcessorTime #-}-addProcessorTime :: Processor -> Double -> IO ()-#ifndef ACCELERATE_MONITORING-addProcessorTime _ _ = return ()-#else-addProcessorTime Native = addProcessorTime' _active_ns_llvm_native-addProcessorTime PTX = addProcessorTime' _active_ns_llvm_ptx--addProcessorTime' :: Atomic -> Double -> IO ()-addProcessorTime' var secs =- let ns = round (secs * 1.0E9)- in void $ Atomic.add var ns-#endif----- | Allocated the number of bytes in the local memory space----didAllocateBytesLocal :: Int64 -> IO ()-#ifndef ACCELERATE_MONITORING-didAllocateBytesLocal _ = return ()-#else-didAllocateBytesLocal n = do- -- void $ Atomic.add _active_bytes_allocated_local n- Counter.add _total_bytes_allocated_local n-#endif---- | Allocated the number of bytes of /new/ memory in the remote memory space----didAllocateBytesRemote :: Int64 -> IO ()-#ifndef ACCELERATE_MONITORING-didAllocateBytesRemote _ = return ()-#else-didAllocateBytesRemote n = do- -- void $ Atomic.add _active_bytes_allocated_remote n- Counter.add _total_bytes_allocated_remote n-#endif--{-# INLINE increaseCurrentBytesRemote #-}-increaseCurrentBytesRemote :: Int64 -> IO ()-#ifndef ACCELERATE_MONITORING-increaseCurrentBytesRemote _ = return ()-#else-increaseCurrentBytesRemote n = Gauge.add _current_bytes_remote n-#endif--{-# INLINE decreaseCurrentBytesRemote #-}-decreaseCurrentBytesRemote :: Int64 -> IO ()-#ifndef ACCELERATE_MONITORING-decreaseCurrentBytesRemote _ = return ()-#else-decreaseCurrentBytesRemote n = Gauge.subtract _current_bytes_remote n-#endif---- | Copied data between the local and remote memory spaces----didCopyBytesToRemote :: Int64 -> IO ()-#ifndef ACCELERATE_MONITORING-didCopyBytesToRemote _ = return ()-#else-didCopyBytesToRemote n = Counter.add _total_bytes_copied_to_remote n-#endif--didCopyBytesFromRemote :: Int64 -> IO ()-#ifndef ACCELERATE_MONITORING-didCopyBytesFromRemote _ = return ()-#else-didCopyBytesFromRemote n = Counter.add _total_bytes_copied_from_remote n-#endif----- TLM: This is required for the 'cleanup' function (which deletes everything--- from the nursery) and is somewhat useful for the add/remove functions, since--- we keep track of the size anyway, but we do lose track of the number of--- allocations/deletions to/from the nursery.----{-# INLINE setCurrentBytesNursery #-}-setCurrentBytesNursery :: Int64 -> IO ()-#ifndef ACCELERATE_MONITORING-setCurrentBytesNursery _ = return ()-#else-setCurrentBytesNursery n = Gauge.set _current_bytes_nursery n-#endif----- | Performed a major GC of the remote memory space----didRemoteGC :: IO ()-#ifndef ACCELERATE_MONITORING-didRemoteGC = return ()-#else-didRemoteGC = Counter.inc _num_remote_gcs-#endif---- | Performed an eviction of a remote array of the given number of bytes----didEvictBytes :: Int64 -> IO ()-#ifndef ACCELERATE_MONITORING-didEvictBytes _ = return ()-#else-didEvictBytes n = do- Counter.inc _num_evictions- Counter.add _total_bytes_evicted_from_remote n-#endif----- Implementation--- ----------------#ifdef ACCELERATE_MONITORING---- In order to calculate the processor load we need to remember the previous--- values. Storing this state in an IORef has a bit of extra overhead (as--- indirection) compared to the rest of the monitoring counters (which are--- unboxed values on the heap manipulated directly with atomic primops), but--- since 'calculateProcessorLoad' will only be called by the EKG monitor--- whenever it refreshes the value for display, rather than running continuously--- in the background, we should be okay.----data EMAState = ES- { old_time :: {-# UNPACK #-} !UTCTime- , old_inst :: {-# UNPACK #-} !Double- , old_avg :: {-# UNPACK #-} !Double- }---- Estimate the load on the processor as a moving exponential average--- (weight of previous measurement = 0.2).----estimateProcessorLoad :: Atomic -> IORef EMAState -> IO Int64-estimateProcessorLoad !var !ref = do- ES{..} <- readIORef ref- time <- getCurrentTime- sample <- Atomic.and var 0- --- let- active_ns = fromIntegral sample- elapsed_s = realToFrac (diffUTCTime time old_time)- elapsed_ns = 1.0E9 * elapsed_s- --- new_inst = 100 * (active_ns / elapsed_ns) -- instantaneous load- new_avg = ema 0.2 elapsed_s old_avg old_inst new_inst -- moving average load- --- writeIORef ref (ES time new_inst new_avg)- return (round new_avg)---{----- Compute the current load on a processor as a percentage of time spent working--- over the elapsed time. This is meant to run continuously by a background--- thread, updating the gauge each time it wakes up.----monitorProcessorLoad :: Gauge -> Atomic -> UTCTime -> Double -> Double -> IO ()-monitorProcessorLoad !gauge !var !old_time !old_inst !old_avg = do- time <- getCurrentTime- sample <- Atomic.and var 0-- let- active_ns = fromIntegral sample- elapsed_s = realToFrac (diffUTCTime time old_time)- elapsed_ns = 1.0E9 * elapsed_s-- load_inst = 100 * (active_ns / elapsed_ns) -- instantaneous load- load_avg = ema 0.2 elapsed_s old_avg old_inst load_inst -- moving average load-- -- Set what we thing the processor load over the previous interval should be- Gauge.set gauge (round load_avg)-- -- Sleep for a bit, then do it all again- threadDelay 500000 -- 500 ms- monitorProcessorLoad gauge var time load_inst load_avg---}---- Exponential moving average for irregular time series----ema :: Double -> Double -> Double -> Double -> Double -> Double-ema !alpha !dt !old_ema !old_sample !new_sample =- let- a = dt / alpha- u = exp ( -a )- v = ( 1 - u ) / a- in- (u * old_ema) + ((v-u) * old_sample) + ((1-v) * new_sample)----- Monitoring variables--- ------------------------ Number of nanoseconds a backend has spent doing real work since the last--- check. This is an integer amount because there are no built-in functions for--- atomic memory access on double precision (as specified by the Intel docs).----{-# NOINLINE _active_ns_llvm_native #-}-_active_ns_llvm_native :: Atomic-_active_ns_llvm_native = unsafePerformIO (Atomic.new 0)--{-# NOINLINE _active_ns_llvm_ptx #-}-_active_ns_llvm_ptx :: Atomic-_active_ns_llvm_ptx = unsafePerformIO (Atomic.new 0)--{-# NOINLINE _active_ns_cuda #-}-_active_ns_cuda :: Atomic-_active_ns_cuda = unsafePerformIO (Atomic.new 0)---- Total number of bytes allocated in the local and remote (e.g. on the GPU)--- address spaces----{-# NOINLINE _total_bytes_allocated_local #-}-_total_bytes_allocated_local :: Counter-_total_bytes_allocated_local = unsafePerformIO Counter.new--{-# NOINLINE _total_bytes_allocated_remote #-}-_total_bytes_allocated_remote :: Counter-_total_bytes_allocated_remote = unsafePerformIO Counter.new---- Total number of bytes copied to and from the remote memory space----{-# NOINLINE _total_bytes_copied_to_remote #-}-_total_bytes_copied_to_remote :: Counter-_total_bytes_copied_to_remote = unsafePerformIO Counter.new--{-# NOINLINE _total_bytes_copied_from_remote #-}-_total_bytes_copied_from_remote :: Counter-_total_bytes_copied_from_remote = unsafePerformIO Counter.new---- Total number of bytes copied out of the remote memory space due to evictions.----{-# NOINLINE _total_bytes_evicted_from_remote #-}-_total_bytes_evicted_from_remote :: Counter-_total_bytes_evicted_from_remote = unsafePerformIO Counter.new---- Current working remote memory size----{-# NOINLINE _current_bytes_remote #-}-_current_bytes_remote :: Gauge-_current_bytes_remote = unsafePerformIO Gauge.new---- Current size of the nursery----{-# NOINLINE _current_bytes_nursery #-}-_current_bytes_nursery :: Gauge-_current_bytes_nursery = unsafePerformIO Gauge.new---- Number of times the remote memory was forcibly garbage collected, and nursery--- flushed.----{-# NOINLINE _num_remote_gcs #-}-_num_remote_gcs :: Counter-_num_remote_gcs = unsafePerformIO Counter.new---- number of LRU eviction events----{-# NOINLINE _num_evictions #-}-_num_evictions :: Counter-_num_evictions = unsafePerformIO Counter.new--#endif-
− Data/Array/Accelerate/Debug/Stats.hs
@@ -1,210 +0,0 @@-{-# LANGUAGE CPP #-}-{-# OPTIONS_GHC -fno-warn-unused-binds #-}-{-# OPTIONS_GHC -fno-warn-unused-imports #-}--- |--- Module : Data.Array.Accelerate.Debug.Simpl--- Copyright : [2008..2017] Manuel M T Chakravarty, Gabriele Keller--- [2009..2017] Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)------ Tick-count statistics collection of the compiler passes, for debugging--- purposes.-----module Data.Array.Accelerate.Debug.Stats (-- simplCount, resetSimplCount,- inline, ruleFired, knownBranch, betaReduce, substitution, simplifierDone, fusionDone,--) where--import Data.Array.Accelerate.Debug.Flags--import Data.Function ( on )-import Data.IORef-import Data.List ( groupBy, sortBy )-import Data.Ord ( comparing )-import Data.Map ( Map )-import Text.PrettyPrint.ANSI.Leijen-import System.IO.Unsafe--import qualified Data.Map as Map----- Recording statistics--- ----------------------ruleFired, inline, knownBranch, betaReduce, substitution :: String -> a -> a-inline = annotate Inline-ruleFired = annotate RuleFired-knownBranch = annotate KnownBranch-betaReduce = annotate BetaReduce-substitution = annotate Substitution--simplifierDone, fusionDone :: a -> a-simplifierDone = tick SimplifierDone-fusionDone = tick FusionDone---- Add an entry to the statistics counters----tick :: Tick -> a -> a-#ifdef ACCELERATE_DEBUG-{-# NOINLINE tick #-}-tick t expr = unsafeDupablePerformIO $ do- modifyIORef' statistics (simplTick t)- return expr-#else-{-# INLINE tick #-}-tick _ expr = expr-#endif---- Add an entry to the statistics counters with an annotation----annotate :: (Id -> Tick) -> String -> a -> a-annotate name ctx = tick (name (Id ctx))----- Simplifier counts--- -------------------data SimplStats- = Simple {-# UNPACK #-} !Int -- when we don't want detailed stats-- | Detail {- ticks :: {-# UNPACK #-} !Int, -- total ticks- details :: !TickCount -- how many of each type- }--instance Show SimplStats where- show = show . pprSimplCount----- Stores the current statistics counters----{-# NOINLINE statistics #-}-statistics :: IORef SimplStats-statistics = unsafePerformIO $ newIORef =<< initSimplCount---- Initialise the statistics counters. If we are dumping the stats--- (-ddump-simpl-stats) record extra information, else just a total tick count.----initSimplCount :: IO SimplStats-#ifdef ACCELERATE_DEBUG-initSimplCount = do- d <- queryFlag dump_simpl_stats- return $! if d then Detail { ticks = 0, details = Map.empty }- else Simple 0-#else-initSimplCount = return $! Simple 0-#endif----- Reset the statistics counters. Do this at the beginning at each HOAS -> de--- Bruijn conversion + optimisation pass.----resetSimplCount :: IO ()-#ifdef ACCELERATE_DEBUG-resetSimplCount = writeIORef statistics =<< initSimplCount-#else-resetSimplCount = return ()-#endif----- Tick a counter----simplTick :: Tick -> SimplStats -> SimplStats-simplTick _ (Simple n) = Simple (n+1)-simplTick t (Detail n dts) = Detail (n+1) (dts `addTick` t)---- Pretty print the tick counts. Remarkably reminiscent of GHC style...----pprSimplCount :: SimplStats -> Doc-pprSimplCount (Simple n) = text "Total ticks:" <+> int n-pprSimplCount (Detail n dts)- = vcat [ text "Total ticks:" <+> int n- , text ""- , pprTickCount dts- ]--simplCount :: IO Doc-simplCount = pprSimplCount `fmap` readIORef statistics----- Ticks--- -------type TickCount = Map Tick Int--data Id = Id String- deriving (Eq, Ord)--data Tick- = Inline Id- | RuleFired Id- | KnownBranch Id- | BetaReduce Id- | Substitution Id-- -- tick at each iteration- | SimplifierDone- | FusionDone- deriving (Eq, Ord)---addTick :: TickCount -> Tick -> TickCount-addTick tc t =- Map.alter f t tc- where- f Nothing = Just 1- f (Just x) = let x' = x+1 in x' `seq` Just x'--pprTickCount :: TickCount -> Doc-pprTickCount counts =- vcat (map pprTickGroup groups)- where- groups = groupBy sameTag (Map.toList counts)- sameTag = (==) `on` tickToTag . fst--pprTickGroup :: [(Tick,Int)] -> Doc-pprTickGroup [] = error "pprTickGroup"-pprTickGroup grp =- hang 2 (vcat $ (int groupTotal <+> text groupName)- : [ int n <+> pprTickCtx t | (t,n) <- sortBy (flip (comparing snd)) grp ])- where- groupName = tickToStr (fst (head grp))- groupTotal = sum [n | (_,n) <- grp]--tickToTag :: Tick -> Int-tickToTag Inline{} = 0-tickToTag RuleFired{} = 1-tickToTag KnownBranch{} = 2-tickToTag BetaReduce{} = 3-tickToTag Substitution{} = 4-tickToTag SimplifierDone = 99-tickToTag FusionDone = 100--tickToStr :: Tick -> String-tickToStr Inline{} = "Inline"-tickToStr RuleFired{} = "RuleFired"-tickToStr KnownBranch{} = "KnownBranch"-tickToStr BetaReduce{} = "BetaReduce"-tickToStr Substitution{} = "Substitution"-tickToStr SimplifierDone = "SimplifierDone"-tickToStr FusionDone = "FusionDone"--pprTickCtx :: Tick -> Doc-pprTickCtx (Inline v) = pprId v-pprTickCtx (RuleFired v) = pprId v-pprTickCtx (KnownBranch v) = pprId v-pprTickCtx (BetaReduce v) = pprId v-pprTickCtx (Substitution v) = pprId v-pprTickCtx SimplifierDone = empty-pprTickCtx FusionDone = empty--pprId :: Id -> Doc-pprId (Id s) = text s-
− Data/Array/Accelerate/Debug/Timed.hs
@@ -1,134 +0,0 @@-{-# LANGUAGE CPP #-}--- |--- Module : Data.Array.Accelerate.Debug.Timed--- Copyright : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Debug.Timed (-- timed,- elapsed,--) where--import Data.Array.Accelerate.Debug.Trace-import Data.Array.Accelerate.Debug.Flags--import Control.Monad.Trans ( MonadIO )-import Text.Printf--#if ACCELERATE_DEBUG-import Control.Applicative-import Control.Monad.Trans ( liftIO )-import Data.List-import Data.Time.Clock-import System.CPUTime-import Prelude--import GHC.Stats-#endif----- | Execute an action and time the results. If GC stats have been enabled (with--- @+RTS -t@ for example) then timing and memory usage information is displayed,--- otherwise only timing information is shown.----{-# INLINEABLE timed #-}-timed :: MonadIO m => Mode -> (Double -> Double -> String) -> m a -> m a-#ifdef ACCELERATE_DEBUG-timed mode fmt action = do- enabled <- liftIO $ queryFlag mode- if enabled- then do- with_gc <- liftIO $ (&&) <$> getRTSStatsEnabled <*> queryFlag verbose- if with_gc- then timed_gc fmt action- else timed_simpl fmt action- else- action-#else-timed _ _ action = action-#endif--#ifdef ACCELERATE_DEBUG-timed_simpl :: MonadIO m => (Double -> Double -> String) -> m a -> m a-timed_simpl fmt action = do- wall0 <- liftIO getCurrentTime- cpu0 <- liftIO getCPUTime- res <- action- wall1 <- liftIO getCurrentTime- cpu1 <- liftIO getCPUTime- --- let wallTime = realToFrac (diffUTCTime wall1 wall0)- cpuTime = fromIntegral (cpu1 - cpu0) * 1E-12- --- liftIO $ putTraceMsg (fmt wallTime cpuTime)- return res---timed_gc :: MonadIO m => (Double -> Double -> String) -> m a -> m a-timed_gc fmt action = do-#if __GLASGOW_HASKELL__ < 802- gc0 <- liftIO getGCStats- res <- action- gc1 <- liftIO getGCStats-#else- rts0 <- liftIO getRTSStats- res <- action- rts1 <- liftIO getRTSStats-#endif- --- let toDouble :: Integral a => a -> Double- toDouble = fromIntegral- ---#if __GLASGOW_HASKELL__ < 802- allocated = toDouble (bytesAllocated gc1 - bytesAllocated gc0)- copied = toDouble (bytesCopied gc1 - bytesCopied gc0)- totalWall = wallSeconds gc1 - wallSeconds gc0- totalCPU = cpuSeconds gc1 - cpuSeconds gc0- mutatorWall = mutatorWallSeconds gc1 - mutatorWallSeconds gc0- mutatorCPU = mutatorCpuSeconds gc1 - mutatorCpuSeconds gc0- gcWall = gcWallSeconds gc1 - gcWallSeconds gc0- gcCPU = gcCpuSeconds gc1 - gcCpuSeconds gc0- totalGCs = numGcs gc1 - numGcs gc0-#else- gc0 = gc rts0- gc1 = gc rts1- allocated = toDouble (gcdetails_allocated_bytes gc1 - gcdetails_allocated_bytes gc0)- copied = toDouble (gcdetails_copied_bytes gc1 - gcdetails_copied_bytes gc0)- totalWall = toDouble (elapsed_ns rts1 - elapsed_ns rts0) * 1.0E-9- totalCPU = toDouble (cpu_ns rts1 - cpu_ns rts0) * 1.0E-9- mutatorWall = toDouble (mutator_elapsed_ns rts1 - mutator_elapsed_ns rts0) * 1.0E-9- mutatorCPU = toDouble (mutator_cpu_ns rts1 - mutator_cpu_ns rts0) * 1.0E-9- gcWall = toDouble (gcdetails_elapsed_ns gc1 - gcdetails_elapsed_ns gc0) * 1.0E-9- gcCPU = toDouble (gcdetails_cpu_ns gc1 - gcdetails_cpu_ns gc0) * 1.0E-9- totalGCs = gcs rts1 - gcs rts0-#endif-- liftIO . putTraceMsg $ intercalate "\n"- [ fmt totalWall totalCPU- , printf " %s allocated on the heap" (showFFloatSIBase (Just 1) 1024 allocated "B")- , printf " %s copied during GC (%d collections)" (showFFloatSIBase (Just 1) 1024 copied "B") totalGCs- , printf " MUT: %s" (elapsed mutatorWall mutatorCPU)- , printf " GC: %s" (elapsed gcWall gcCPU)- ]- --- return res--#if __GLASGOW_HASKELL__ < 802-getRTSStatsEnabled :: IO Bool-getRTSStatsEnabled = getGCStatsEnabled-#endif-#endif--elapsed :: Double -> Double -> String-elapsed wallTime cpuTime =- printf "%s (wall), %s (cpu)"- (showFFloatSIBase (Just 3) 1000 wallTime "s")- (showFFloatSIBase (Just 3) 1000 cpuTime "s")-
− Data/Array/Accelerate/Debug/Trace.hs
@@ -1,137 +0,0 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE CPP #-}-{-# OPTIONS_GHC -fno-warn-unused-imports #-}--- |--- Module : Data.Array.Accelerate.Debug.Trace--- Copyright : [2008..2017] Manuel M T Chakravarty, Gabriele Keller--- [2009..2017] Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)------ Functions for tracing and monitoring execution. These are useful for--- investigating bugs and performance problems, but by default are not enabled--- in performance code.-----module Data.Array.Accelerate.Debug.Trace- where--import Data.Array.Accelerate.Debug.Flags--import Numeric-import System.CPUTime-import System.IO.Unsafe-import Text.Printf-import qualified Debug.Trace as D----- | Show a signed 'RealFloat' value using SI unit prefixes. In the call to:------ > showFFloatSIBase prec base val------ If @prec@ is @'Nothing'@ the value is shown to full precision, and if @prec@--- is @'Just' d@, then at most @d@ digits are shown after the decimal place.--- Here @base@ represents the increment size between multiples of the original--- unit. For measures in base-10 this will be 1000 and for values in base-2 this--- is usually 1024, for example when measuring seconds versus bytes,--- respectively.----showFFloatSIBase :: RealFloat a => Maybe Int -> a -> a -> ShowS-showFFloatSIBase prec !base !k- = showString- $ case pow of- 4 -> with "T"- 3 -> with "G"- 2 -> with "M"- 1 -> with "k"- -1 -> with "m"- -2 -> with "µ"- -3 -> with "n"- -4 -> with "p"- _ -> showGFloat prec k " " -- no unit or unhandled SI prefix- where- !k' = k / (base ^^ pow)- !pow = floor (logBase base k) :: Int- with unit = showFFloat prec k' (' ':unit)----- | The 'trace' function outputs the message given as its second argument when--- the debug mode indicated by the first argument is enabled, before returning--- the third argument as its result. The message is prefixed with a time stamp.----trace :: Mode -> String -> a -> a-#ifdef ACCELERATE_DEBUG-{-# NOINLINE trace #-}-trace f msg expr = unsafePerformIO $ do- traceIO f msg- return expr-#else-{-# INLINE trace #-}-trace _ _ expr = expr-#endif----- | The 'traceIO' function outputs the trace message together with a time stamp--- from the IO monad. This sequences the output with respect to other IO--- actions.---- TLM: Perhaps we should automatically format the log messages. Namely:--- * prefix with a description of the mode (e.g. "gc: foo")--- * align multi-line messages----traceIO :: Mode -> String -> IO ()-#ifdef ACCELERATE_DEBUG-traceIO f msg = when f $ putTraceMsg msg-#else-{-# INLINE traceIO #-}-traceIO _ _ = return ()-#endif----- | The 'traceEvent' function behaves like 'trace' with the difference that the--- message is emitted to the eventlog, if eventlog profiling is enabled at--- runtime.----traceEvent :: Mode -> String -> a -> a-#ifdef ACCELERATE_DEBUG-{-# NOINLINE traceEvent #-}-traceEvent f msg expr = unsafePerformIO $ do- traceEventIO f msg- return expr-#else-{-# INLINE traceEvent #-}-traceEvent _ _ expr = expr-#endif----- | Print a message prefixed with the current CPU time.----putTraceMsg :: String -> IO ()-#ifdef ACCELERATE_DEBUG-putTraceMsg msg = do- psec <- getCPUTime- let secs = fromIntegral psec * 1E-12 :: Double- D.traceIO $ printf "[%8.3f] %s" secs msg-#else-putTraceMsg _ = return ()-#endif----- | The 'traceEventIO' function emits a message to the eventlog, if eventlog--- profiling is available and enabled at runtime.------ Compared to 'traceEvent', 'traceEventIO' sequences the event with respect to--- other IO actions.----traceEventIO :: Mode -> String -> IO ()-#ifdef ACCELERATE_DEBUG-traceEventIO f msg = do- when f $ D.traceEventIO msg-#else-{-# INLINE traceEventIO #-}-traceEventIO _ _ = return ()-#endif-
− Data/Array/Accelerate/Error.hs
@@ -1,165 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE TemplateHaskell #-}-{-# OPTIONS_HADDOCK hide #-}--- |--- Module : Data.Array.Accelerate.Error--- Copyright : [2009..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Error (-- internalError, boundsError, unsafeError,- internalCheck, boundsCheck, unsafeCheck, indexCheck,- internalWarning, boundsWarning, unsafeWarning,--) where--import Data.List-import Debug.Trace-import Language.Haskell.TH hiding ( Unsafe )--data Check = Bounds | Unsafe | Internal----- | Issue an internal error message------ $internalError :: String -> String -> a----internalError :: Q Exp-internalError = appE errorQ [| Internal |]--boundsError :: Q Exp-boundsError = appE errorQ [| Bounds |]--unsafeError :: Q Exp-unsafeError = appE errorQ [| Unsafe |]----- | Throw an error if the condition evaluates to False, otherwise evaluate the--- result.------ $internalCheck :: String -> String -> Bool -> a -> a----internalCheck :: Q Exp-internalCheck = appE checkQ [| Internal |]--boundsCheck :: Q Exp-boundsCheck = appE checkQ [| Bounds |]--unsafeCheck :: Q Exp-unsafeCheck = appE checkQ [| Unsafe |]----- | Throw an error if the index is not in range, otherwise evaluate the result.------ $boundsCheck :: String -> Int -> Int -> a -> a----indexCheck :: Q Exp-indexCheck = withLocation- [| \format fn i n x ->- case not (doChecks Bounds) || (i >= 0 && i < n) of- True -> x- False -> error (format Bounds (call fn ("index out of bounds: " ++ show (i,n)))) x |]----- | Print a warning message if the condition evaluates to False.------ $internalWarning :: String -> String -> Bool -> a -> a----internalWarning :: Q Exp-internalWarning = appE warningQ [| Internal |]--boundsWarning :: Q Exp-boundsWarning = appE warningQ [| Bounds |]--unsafeWarning :: Q Exp-unsafeWarning = appE warningQ [| Unsafe |]----- Template Haskell implementation--- ---------------------------------call :: String -> String -> String-call f m = concat ["(", f, "): ", m]--errorQ :: Q Exp-errorQ = withLocation- [| \format kind fn msg -> error (format kind (call fn msg)) |]--checkQ :: Q Exp-checkQ = withLocation- [| \format kind fn msg cond x ->- case not (doChecks kind) || cond of- True -> x- False -> error (format kind (call fn msg)) |]--warningQ :: Q Exp-warningQ = withLocation- [| \format kind fn msg cond x ->- case not (doChecks kind) || cond of- True -> x- False -> trace (format kind (call fn msg)) x |]--withLocation :: Q Exp -> Q Exp-withLocation f =- appE f (locatedMessage =<< location)--locatedMessage :: Loc -> Q Exp-locatedMessage loc =- [| \kind msg -> message kind ($(litE (stringL (formatLoc loc))) ++ msg) |]--formatLoc :: Loc -> String-formatLoc loc =- let file = loc_filename loc- (line,col) = loc_start loc- in- intercalate ":" [file, show line, show col, " "]--message :: Check -> String -> String-message kind msg = unlines header ++ msg- where- header =- case kind of- Internal -> [""- ,"*** Internal error in package accelerate ***"- ,"*** Please submit a bug report at https://github.com/AccelerateHS/accelerate/issues"]- _ -> []----- CPP malarky--- -------------{-# INLINE doChecks #-}-doChecks :: Check -> Bool-doChecks Bounds = doBoundsChecks-doChecks Unsafe = doUnsafeChecks-doChecks Internal = doInternalChecks--doBoundsChecks :: Bool-#ifdef ACCELERATE_BOUNDS_CHECKS-doBoundsChecks = True-#else-doBoundsChecks = False-#endif--doUnsafeChecks :: Bool-#ifdef ACCELERATE_UNSAFE_CHECKS-doUnsafeChecks = True-#else-doUnsafeChecks = False-#endif--doInternalChecks :: Bool-#ifdef ACCELERATE_INTERNAL_CHECKS-doInternalChecks = True-#else-doInternalChecks = False-#endif-
− Data/Array/Accelerate/FullList.hs
@@ -1,119 +0,0 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE PatternGuards #-}-{-# OPTIONS_HADDOCK hide #-}--- |--- Module : Data.Array.Accelerate.FullList--- Copyright : [2008..2017] Manuel M T Chakravarty, Gabriele Keller--- [2009..2017] Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)------ Non-empty lists of key/value pairs. The lists are strict in the key and lazy--- in the values. We assume that keys only occur once.-----module Data.Array.Accelerate.FullList (-- FullList(..),- List(..),-- singleton,- cons,- size,- mapM_,- lookup,- lookupDelete,--) where--import Prelude hiding ( lookup, mapM_ )---data FullList k v = FL !k v !(List k v)-data List k v = Nil | Cons !k v !(List k v)--infixr 5 `Cons`--instance (Eq k, Eq v) => Eq (FullList k v) where- (FL k1 v1 xs) == (FL k2 v2 ys) = k1 == k2 && v1 == v2 && xs == ys- (FL k1 v1 xs) /= (FL k2 v2 ys) = k1 /= k2 || v1 /= v2 || xs /= ys--instance (Eq k, Eq v) => Eq (List k v) where- (Cons k1 v1 xs) == (Cons k2 v2 ys) = k1 == k2 && v1 == v2 && xs == ys- Nil == Nil = True- _ == _ = False-- (Cons k1 v1 xs) /= (Cons k2 v2 ys) = k1 /= k2 || v1 /= v2 || xs /= ys- Nil /= Nil = False- _ /= _ = True----- List-like operations----infixr 5 `cons`-cons :: k -> v -> FullList k v -> FullList k v-cons k v (FL k' v' xs) = FL k v (Cons k' v' xs)--singleton :: k -> v -> FullList k v-singleton k v = FL k v Nil--size :: FullList k v -> Int-size (FL _ _ xs) = 1 + sizeL xs--sizeL :: List k v -> Int-sizeL Nil = 0-sizeL (Cons _ _ xs) = 1 + sizeL xs--lookup :: Eq k => k -> FullList k v -> Maybe v-lookup key (FL k v xs)- | key == k = Just v- | otherwise = lookupL key xs-{-# INLINABLE lookup #-}-{-# SPECIALISE lookup :: () -> FullList () v -> Maybe v #-}--lookupL :: Eq k => k -> List k v -> Maybe v-lookupL !key = go- where- go Nil = Nothing- go (Cons k v xs)- | key == k = Just v- | otherwise = go xs-{-# INLINABLE lookupL #-}-{-# SPECIALISE lookupL :: () -> List () v -> Maybe v #-}--lookupDelete :: Eq k => k -> FullList k v -> (Maybe v, Maybe (FullList k v))-lookupDelete key (FL k v xs)- | key == k- = case xs of- Nil -> (Just v, Nothing)- Cons k' v' xs' -> (Just v, Just $ FL k' v' xs')-- | (r, xs') <- lookupDeleteL k xs- = (r, Just $ FL k v xs')-{-# INLINABLE lookupDelete #-}-{-# SPECIALISE lookupDelete :: () -> FullList () v -> (Maybe v, Maybe (FullList () v)) #-}--lookupDeleteL :: Eq k => k -> List k v -> (Maybe v, List k v)-lookupDeleteL !key = go- where- go Nil = (Nothing, Nil)- go (Cons k v xs)- | key == k = (Just v, xs)- | (r, xs') <- go xs = (r, Cons k v xs')-{-# INLINABLE lookupDeleteL #-}-{-# SPECIALISE lookupDeleteL :: () -> List () v -> (Maybe v, List () v) #-}--mapM_ :: Monad m => (k -> v -> m a) -> FullList k v -> m ()-mapM_ !f (FL k v xs) = f k v >> mapML_ f xs-{-# INLINABLE mapM_ #-}--mapML_ :: Monad m => (k -> v -> m a) -> List k v -> m ()-mapML_ !f = go- where- go Nil = return ()- go (Cons k v xs) = f k v >> go xs-{-# INLINABLE mapML_ #-}-
− Data/Array/Accelerate/Interpreter.hs
@@ -1,1875 +0,0 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE PatternGuards #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE ViewPatterns #-}-{-# OPTIONS_GHC -fno-warn-name-shadowing #-}-{-# OPTIONS_HADDOCK prune #-}--- |--- Module : Data.Array.Accelerate.Interpreter--- Copyright : [2008..2017] Manuel M T Chakravarty, Gabriele Keller--- [2009..2017] Trevor L. McDonell--- [2014..2014] Frederik M. Madsen--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)------ This interpreter is meant to be a reference implementation of the semantics--- of the embedded array language. The emphasis is on defining the semantics--- clearly, not on performance.------- [/Surface types versus representation types:/]------ As a general rule, we perform all computations on representation types and we--- store all data as values of representation types. To guarantee the type--- safety of the interpreter, this currently implies a lot of conversions--- between surface and representation types. Optimising the code by eliminating--- back and forth conversions is fine, but only where it doesn't negatively--- affects clarity---after all, the main purpose of the interpreter is to serve--- as an executable specification.-----module Data.Array.Accelerate.Interpreter (-- -- * Interpret an array expression- Sugar.Acc, Arrays,- run, run1, runN,-- -- Internal (hidden)- evalPrim, evalPrimConst, evalPrj--) where---- standard libraries-import Control.DeepSeq-import Control.Exception-import Control.Monad-import Data.Bits-import Data.Char ( chr, ord )-import System.IO.Unsafe ( unsafePerformIO )-import Text.Printf ( printf )-import Unsafe.Coerce ( unsafeCoerce )-import Prelude hiding ( sum )---- friends-import Data.Array.Accelerate.AST hiding ( Boundary, PreBoundary(..) )-import Data.Array.Accelerate.Analysis.Match-import Data.Array.Accelerate.Array.Data-import Data.Array.Accelerate.Array.Representation ( SliceIndex(..) )-import Data.Array.Accelerate.Array.Sugar-import Data.Array.Accelerate.Error-import Data.Array.Accelerate.Product-import Data.Array.Accelerate.Trafo hiding ( Delayed )-import Data.Array.Accelerate.Type-import qualified Data.Array.Accelerate.AST as AST-import qualified Data.Array.Accelerate.Array.Representation as R-import qualified Data.Array.Accelerate.Smart as Sugar-import qualified Data.Array.Accelerate.Trafo as AST--import qualified Data.Array.Accelerate.Debug as D----- Program execution--- --------------------- | Run a complete embedded array program using the reference interpreter.----run :: Arrays a => Sugar.Acc a -> a-run a = unsafePerformIO execute- where- !acc = convertAccWith config a- execute = do- D.dumpGraph $!! acc- D.dumpSimplStats- phase "execute" D.elapsed (evaluate (evalOpenAcc acc Empty))---- | This is 'runN' specialised to an array program of one argument.----run1 :: (Arrays a, Arrays b) => (Sugar.Acc a -> Sugar.Acc b) -> a -> b-run1 = runN---- | Prepare and execute an embedded array program.----runN :: Afunction f => f -> AfunctionR f-runN f = go- where- !acc = convertAfunWith config f- !afun = unsafePerformIO $ do- D.dumpGraph $!! acc- D.dumpSimplStats- return acc- !go = eval afun Empty- --- eval :: DelayedOpenAfun aenv f -> Val aenv -> f- eval (Alam f) aenv = \a -> eval f (aenv `Push` a)- eval (Abody b) aenv = unsafePerformIO $ phase "execute" D.elapsed (evaluate (evalOpenAcc b aenv))----- -- | Stream a lazily read list of input arrays through the given program,--- -- collecting results as we go--- ----- streamOut :: Arrays a => Sugar.Seq [a] -> [a]--- streamOut seq = let seq' = convertSeqWith config seq--- in evalDelayedSeq defaultSeqConfig seq'---config :: Phase-config = Phase- { recoverAccSharing = True- , recoverExpSharing = True- , recoverSeqSharing = True- , floatOutAccFromExp = True- , enableAccFusion = True- , convertOffsetOfSegment = False- -- , vectoriseSequences = True- }---- Debugging--- -----------phase :: String -> (Double -> Double -> String) -> IO a -> IO a-phase n fmt go = D.timed D.dump_phases (\wall cpu -> printf "phase %s: %s" n (fmt wall cpu)) go----- Delayed Arrays--- ------------------ Note that in contrast to the representation used in the optimised AST, the--- delayed array representation used here is _only_ for delayed arrays --- we do--- not require an optional Manifest|Delayed data type to evaluate the program.----data Delayed a where- Delayed :: (Shape sh, Elt e)- => sh- -> (sh -> e)- -> (Int -> e)- -> Delayed (Array sh e)----- Array expression evaluation--- -----------------------------type EvalAcc acc = forall aenv a. acc aenv a -> Val aenv -> a---- Evaluate an open array function----evalOpenAfun :: DelayedOpenAfun aenv f -> Val aenv -> f-evalOpenAfun (Alam f) aenv = \a -> evalOpenAfun f (aenv `Push` a)-evalOpenAfun (Abody b) aenv = evalOpenAcc b aenv----- The core interpreter for optimised array programs----evalOpenAcc- :: forall aenv a.- DelayedOpenAcc aenv a- -> Val aenv- -> a-evalOpenAcc AST.Delayed{} _ = $internalError "evalOpenAcc" "expected manifest array"-evalOpenAcc (AST.Manifest pacc) aenv =- let- manifest :: DelayedOpenAcc aenv a' -> a'- manifest acc = evalOpenAcc acc aenv-- delayed :: DelayedOpenAcc aenv (Array sh e) -> Delayed (Array sh e)- delayed AST.Manifest{} = $internalError "evalOpenAcc" "expected delayed array"- delayed AST.Delayed{..} = Delayed (evalE extentD) (evalF indexD) (evalF linearIndexD)-- evalE :: DelayedExp aenv t -> t- evalE exp = evalPreExp evalOpenAcc exp aenv-- evalF :: DelayedFun aenv f -> f- evalF fun = evalPreFun evalOpenAcc fun aenv-- evalB :: AST.PreBoundary DelayedOpenAcc aenv t -> Boundary t- evalB bnd = evalPreBoundary evalOpenAcc bnd aenv- in- case pacc of- Avar ix -> prj ix aenv- Alet acc1 acc2 -> evalOpenAcc acc2 (aenv `Push` manifest acc1)- Atuple atup -> toAtuple $ evalAtuple atup aenv- Aprj ix atup -> evalPrj ix . fromAtuple $ manifest atup- Apply afun acc -> evalOpenAfun afun aenv $ manifest acc- Aforeign _ afun acc -> evalOpenAfun afun Empty $ manifest acc- Acond p acc1 acc2- | evalE p -> manifest acc1- | otherwise -> manifest acc2-- Awhile cond body acc -> go (manifest acc)- where- p = evalOpenAfun cond aenv- f = evalOpenAfun body aenv- go !x- | p x ! Z = go (f x)- | otherwise = x-- Use arr -> toArr arr- Unit e -> unitOp (evalE e)- -- Collect s -> evalSeq defaultSeqConfig s aenv-- -- Producers- -- ---------- Map f acc -> mapOp (evalF f) (delayed acc)- Generate sh f -> generateOp (evalE sh) (evalF f)- Transform sh p f acc -> transformOp (evalE sh) (evalF p) (evalF f) (delayed acc)- Backpermute sh p acc -> backpermuteOp (evalE sh) (evalF p) (delayed acc)- Reshape sh acc -> reshapeOp (evalE sh) (manifest acc)-- ZipWith f acc1 acc2 -> zipWithOp (evalF f) (delayed acc1) (delayed acc2)- Replicate slice slix acc -> replicateOp slice (evalE slix) (manifest acc)- Slice slice acc slix -> sliceOp slice (manifest acc) (evalE slix)-- -- Consumers- -- ---------- Fold f z acc -> foldOp (evalF f) (evalE z) (delayed acc)- Fold1 f acc -> fold1Op (evalF f) (delayed acc)- FoldSeg f z acc seg -> foldSegOp (evalF f) (evalE z) (delayed acc) (delayed seg)- Fold1Seg f acc seg -> fold1SegOp (evalF f) (delayed acc) (delayed seg)- Scanl f z acc -> scanlOp (evalF f) (evalE z) (delayed acc)- Scanl' f z acc -> scanl'Op (evalF f) (evalE z) (delayed acc)- Scanl1 f acc -> scanl1Op (evalF f) (delayed acc)- Scanr f z acc -> scanrOp (evalF f) (evalE z) (delayed acc)- Scanr' f z acc -> scanr'Op (evalF f) (evalE z) (delayed acc)- Scanr1 f acc -> scanr1Op (evalF f) (delayed acc)- Permute f def p acc -> permuteOp (evalF f) (manifest def) (evalF p) (delayed acc)- Stencil sten b acc -> stencilOp (evalF sten) (evalB b) (manifest acc)- Stencil2 sten b1 a1 b2 a2 -> stencil2Op (evalF sten) (evalB b1) (manifest a1) (evalB b2) (manifest a2)---- Array tuple construction and projection----evalAtuple :: Atuple (DelayedOpenAcc aenv) t -> Val aenv -> t-evalAtuple NilAtup _ = ()-evalAtuple (SnocAtup t a) aenv = (evalAtuple t aenv, evalOpenAcc a aenv)----- Array primitives--- ------------------unitOp :: Elt e => e -> Scalar e-unitOp e = fromFunction Z (const e)---generateOp- :: (Shape sh, Elt e)- => sh- -> (sh -> e)- -> Array sh e-generateOp = fromFunction---transformOp- :: (Shape sh', Elt b)- => sh'- -> (sh' -> sh)- -> (a -> b)- -> Delayed (Array sh a)- -> Array sh' b-transformOp sh' p f (Delayed _ xs _)- = fromFunction sh' (\ix -> f (xs $ p ix))---reshapeOp- :: (Shape sh, Shape sh', Elt e)- => sh- -> Array sh' e- -> Array sh e-reshapeOp newShape arr@(Array _ adata)- = $boundsCheck "reshape" "shape mismatch" (size newShape == size (shape arr))- $ Array (fromElt newShape) adata---replicateOp- :: (Shape sh, Shape sl, Elt slix, Elt e)- => SliceIndex (EltRepr slix) (EltRepr sl) co (EltRepr sh)- -> slix- -> Array sl e- -> Array sh e-replicateOp slice slix arr- = fromFunction (toElt sh) (\ix -> arr ! liftToElt pf ix)- where- (sh, pf) = extend slice (fromElt slix) (fromElt (shape arr))-- extend :: SliceIndex slix sl co dim- -> slix- -> sl- -> (dim, dim -> sl)- extend SliceNil () () = ((), const ())- extend (SliceAll sliceIdx) (slx, ()) (sl, sz)- = let (dim', f') = extend sliceIdx slx sl- in ((dim', sz), \(ix, i) -> (f' ix, i))- extend (SliceFixed sliceIdx) (slx, sz) sl- = let (dim', f') = extend sliceIdx slx sl- in ((dim', sz), \(ix, _) -> f' ix)---sliceOp- :: (Shape sh, Shape sl, Elt slix, Elt e)- => SliceIndex (EltRepr slix) (EltRepr sl) co (EltRepr sh)- -> Array sh e- -> slix- -> Array sl e-sliceOp slice arr slix- = fromFunction (toElt sh') (\ix -> arr ! liftToElt pf ix)- where- (sh', pf) = restrict slice (fromElt slix) (fromElt (shape arr))-- restrict :: SliceIndex slix sl co sh- -> slix- -> sh- -> (sl, sl -> sh)- restrict SliceNil () () = ((), const ())- restrict (SliceAll sliceIdx) (slx, ()) (sl, sz)- = let (sl', f') = restrict sliceIdx slx sl- in ((sl', sz), \(ix, i) -> (f' ix, i))- restrict (SliceFixed sliceIdx) (slx, i) (sl, sz)- = let (sl', f') = restrict sliceIdx slx sl- in $indexCheck "slice" i sz $ (sl', \ix -> (f' ix, i))---mapOp :: (Shape sh, Elt b)- => (a -> b)- -> Delayed (Array sh a)- -> Array sh b-mapOp f (Delayed sh xs _)- = fromFunction sh (\ix -> f (xs ix))---zipWithOp- :: (Shape sh, Elt c)- => (a -> b -> c)- -> Delayed (Array sh a)- -> Delayed (Array sh b)- -> Array sh c-zipWithOp f (Delayed shx xs _) (Delayed shy ys _)- = fromFunction (shx `intersect` shy) (\ix -> f (xs ix) (ys ix))---- zipWith'Op--- :: (Shape sh, Elt a)--- => (a -> a -> a)--- -> Delayed (Array sh a)--- -> Delayed (Array sh a)--- -> Array sh a--- zipWith'Op f (Delayed shx xs _) (Delayed shy ys _)--- = fromFunction (shx `union` shy) (\ix -> if ix `outside` shx--- then ys ix--- else if ix `outside` shy--- then xs ix--- else f (xs ix) (ys ix))--- where--- a `outside` b = or $ zipWith (>=) (shapeToList a) (shapeToList b)---foldOp- :: (Shape sh, Elt e)- => (e -> e -> e)- -> e- -> Delayed (Array (sh :. Int) e)- -> Array sh e-foldOp f z (Delayed (sh :. n) arr _)- | size sh == 0- = fromFunction (listToShape . map (max 1) . shapeToList $ sh) (const z)-- | otherwise- = fromFunction sh (\ix -> iter (Z:.n) (\(Z:.i) -> arr (ix :. i)) f z)---fold1Op- :: (Shape sh, Elt e)- => (e -> e -> e)- -> Delayed (Array (sh :. Int) e)- -> Array sh e-fold1Op f (Delayed (sh :. n) arr _)- = $boundsCheck "fold1" "empty array" (n > 0)- $ fromFunction sh (\ix -> iter1 (Z:.n) (\(Z:.i) -> arr (ix :. i)) f)---foldSegOp- :: forall sh e i. (Elt e, Elt i, IsIntegral i)- => (e -> e -> e)- -> e- -> Delayed (Array (sh :. Int) e)- -> Delayed (Segments i)- -> Array (sh :. Int) e-foldSegOp f z (Delayed (sh :. _) arr _) seg@(Delayed (Z :. n) _ _)- | IntegralDict <- integralDict (integralType :: IntegralType i)- = fromFunction (sh :. n)- $ \(sz :. ix) -> let start = fromIntegral $ offset ! (Z :. ix)- end = fromIntegral $ offset ! (Z :. ix+1)- in- iter (Z :. end-start) (\(Z:.i) -> arr (sz :. start+i)) f z- where- offset = scanlOp (+) 0 seg---fold1SegOp- :: forall sh e i. (Shape sh, Elt e, Elt i, IsIntegral i)- => (e -> e -> e)- -> Delayed (Array (sh :. Int) e)- -> Delayed (Segments i)- -> Array (sh :. Int) e-fold1SegOp f (Delayed (sh :. _) arr _) seg@(Delayed (Z :. n) _ _)- | IntegralDict <- integralDict (integralType :: IntegralType i)- = fromFunction (sh :. n)- $ \(sz :. ix) -> let start = fromIntegral $ offset ! (Z :. ix)- end = fromIntegral $ offset ! (Z :. ix+1)- in- $boundsCheck "fold1Seg" "empty segment" (end > start)- $ iter1 (Z :. end-start) (\(Z:.i) -> arr (sz :. start+i)) f- where- offset = scanlOp (+) 0 seg---scanl1Op- :: (Shape sh, Elt e)- => (e -> e -> e)- -> Delayed (Array (sh:.Int) e)- -> Array (sh:.Int) e-scanl1Op f (Delayed sh@(_ :. n) ain _)- = $boundsCheck "scanl1" "empty array" (n > 0)- $ adata `seq` Array (fromElt sh) adata- where- f' = sinkFromElt2 f- --- (adata, _) = runArrayData $ do- aout <- newArrayData (size sh)-- let write (sz:.0) = unsafeWriteArrayData aout (toIndex sh (sz:.0)) (fromElt (ain (sz:.0)))- write (sz:.i) = do- x <- unsafeReadArrayData aout (toIndex sh (sz:.i-1))- y <- return $ fromElt (ain (sz:.i))- unsafeWriteArrayData aout (toIndex sh (sz:.i)) (f' x y)-- iter1 sh write (>>)- return (aout, undefined)---scanlOp- :: (Shape sh, Elt e)- => (e -> e -> e)- -> e- -> Delayed (Array (sh:.Int) e)- -> Array (sh:.Int) e-scanlOp f z (Delayed (sh :. n) ain _)- = adata `seq` Array (fromElt sh') adata- where- sh' = sh :. n+1- f' = sinkFromElt2 f- --- (adata, _) = runArrayData $ do- aout <- newArrayData (size sh')-- let write (sz:.0) = unsafeWriteArrayData aout (toIndex sh' (sz:.0)) (fromElt z)- write (sz:.i) = do- x <- unsafeReadArrayData aout (toIndex sh' (sz:.i-1))- y <- return $ fromElt (ain (sz:.i-1))- unsafeWriteArrayData aout (toIndex sh' (sz:.i)) (f' x y)-- iter sh' write (>>) (return ())- return (aout, undefined)---scanl'Op- :: (Shape sh, Elt e)- => (e -> e -> e)- -> e- -> Delayed (Array (sh:.Int) e)- -> (Array (sh:.Int) e, Array sh e)-scanl'Op f z (Delayed (sh :. n) ain _)- = aout `seq` asum `seq` ( Array (fromElt (sh:.n)) aout- , Array (fromElt sh) asum )- where- f' = sinkFromElt2 f- --- (AD_Pair aout asum, _) = runArrayData $ do- aout <- newArrayData (size (sh:.n))- asum <- newArrayData (size sh)-- let write (sz:.0)- | n == 0 = unsafeWriteArrayData asum (toIndex sh sz) (fromElt z)- | otherwise = unsafeWriteArrayData aout (toIndex (sh:.n) (sz:.0)) (fromElt z)- write (sz:.i) = do- x <- unsafeReadArrayData aout (toIndex (sh:.n) (sz:.i-1))- y <- return $ fromElt (ain (sz:.i-1))- if i == n- then unsafeWriteArrayData asum (toIndex sh sz) (f' x y)- else unsafeWriteArrayData aout (toIndex (sh:.n) (sz:.i)) (f' x y)-- iter (sh:.n+1) write (>>) (return ())- return (AD_Pair aout asum, undefined)---scanrOp- :: (Shape sh, Elt e)- => (e -> e -> e)- -> e- -> Delayed (Array (sh:.Int) e)- -> Array (sh:.Int) e-scanrOp f z (Delayed (sz :. n) ain _)- = adata `seq` Array (fromElt sh') adata- where- sh' = sz :. n+1- f' = sinkFromElt2 f- --- (adata, _) = runArrayData $ do- aout <- newArrayData (size sh')-- let write (sz:.0) = unsafeWriteArrayData aout (toIndex sh' (sz:.n)) (fromElt z)- write (sz:.i) = do- x <- return $ fromElt (ain (sz:.n-i))- y <- unsafeReadArrayData aout (toIndex sh' (sz:.n-i+1))- unsafeWriteArrayData aout (toIndex sh' (sz:.n-i)) (f' x y)-- iter sh' write (>>) (return ())- return (aout, undefined)---scanr1Op- :: (Shape sh, Elt e)- => (e -> e -> e)- -> Delayed (Array (sh:.Int) e)- -> Array (sh:.Int) e-scanr1Op f (Delayed sh@(_ :. n) ain _)- = $boundsCheck "scanr1" "empty array" (n > 0)- $ adata `seq` Array (fromElt sh) adata- where- f' = sinkFromElt2 f- --- (adata, _) = runArrayData $ do- aout <- newArrayData (size sh)-- let write (sz:.0) = unsafeWriteArrayData aout (toIndex sh (sz:.n-1)) (fromElt (ain (sz:.n-1)))- write (sz:.i) = do- x <- return $ fromElt (ain (sz:.n-i-1))- y <- unsafeReadArrayData aout (toIndex sh (sz:.n-i))- unsafeWriteArrayData aout (toIndex sh (sz:.n-i-1)) (f' x y)-- iter1 sh write (>>)- return (aout, undefined)---scanr'Op- :: forall sh e. (Shape sh, Elt e)- => (e -> e -> e)- -> e- -> Delayed (Array (sh:.Int) e)- -> (Array (sh:.Int) e, Array sh e)-scanr'Op f z (Delayed (sh :. n) ain _)- = aout `seq` asum `seq` ( Array (fromElt (sh:.n)) aout- , Array (fromElt sh) asum )- where- f' = sinkFromElt2 f- --- (AD_Pair aout asum, _) = runArrayData $ do- aout <- newArrayData (size (sh:.n))- asum <- newArrayData (size sh)-- let write (sz:.0)- | n == 0 = unsafeWriteArrayData asum (toIndex sh sz) (fromElt z)- | otherwise = unsafeWriteArrayData aout (toIndex (sh:.n) (sz:.n-1)) (fromElt z)-- write (sz:.i) = do- x <- return $ fromElt (ain (sz:.n-i))- y <- unsafeReadArrayData aout (toIndex (sh:.n) (sz:.n-i))- if i == n- then unsafeWriteArrayData asum (toIndex sh sz) (f' x y)- else unsafeWriteArrayData aout (toIndex (sh:.n) (sz:.n-i-1)) (f' x y)-- iter (sh:.n+1) write (>>) (return ())- return (AD_Pair aout asum, undefined)---permuteOp- :: (Shape sh, Shape sh', Elt e)- => (e -> e -> e)- -> Array sh' e- -> (sh -> sh')- -> Delayed (Array sh e)- -> Array sh' e-permuteOp f def@(Array _ adef) p (Delayed sh _ ain)- = adata `seq` Array (fromElt sh') adata- where- sh' = shape def- n' = size sh'- f' = sinkFromElt2 f- --- (adata, _) = runArrayData $ do- aout <- newArrayData n'-- let -- initialise array with default values- init i- | i >= n' = return ()- | otherwise = do- x <- unsafeReadArrayData adef i- unsafeWriteArrayData aout i x- init (i+1)-- -- project each element onto the destination array and update- update src- = let dst = p src- i = toIndex sh src- j = toIndex sh' dst- in- unless (fromElt dst == R.ignore) $ do- x <- return . fromElt $ ain i- y <- unsafeReadArrayData aout j- unsafeWriteArrayData aout j (f' x y)-- init 0- iter sh update (>>) (return ())- return (aout, undefined)---backpermuteOp- :: (Shape sh', Elt e)- => sh'- -> (sh' -> sh)- -> Delayed (Array sh e)- -> Array sh' e-backpermuteOp sh' p (Delayed _ arr _)- = fromFunction sh' (\ix -> arr $ p ix)---stencilOp- :: (Stencil sh a stencil, Elt b)- => (stencil -> b)- -> Boundary (Array sh a)- -> Array sh a- -> Array sh b-stencilOp stencil bnd arr- = fromFunction sh f- where- sh = shape arr- f = stencil . stencilAccess (bounded bnd arr)---stencil2Op- :: (Stencil sh a stencil1, Stencil sh b stencil2, Elt c)- => (stencil1 -> stencil2 -> c)- -> Boundary (Array sh a)- -> Array sh a- -> Boundary (Array sh b)- -> Array sh b- -> Array sh c-stencil2Op stencil bnd1 arr1 bnd2 arr2- = fromFunction (sh1 `intersect` sh2) f- where- sh1 = shape arr1- sh2 = shape arr2- f ix = stencil (stencilAccess (bounded bnd1 arr1) ix)- (stencilAccess (bounded bnd2 arr2) ix)--stencilAccess- :: Stencil sh e stencil- => (sh -> e)- -> sh- -> stencil-stencilAccess = goR stencil- where- -- Base cases, nothing interesting to do here since we know the lower- -- dimension is Z.- --- goR :: StencilR sh e stencil -> (sh -> e) -> sh -> stencil- goR StencilRunit3 rf ix =- let- z :. i = ix- rf' d = rf (z :. i+d)- in- ( rf' (-1)- , rf' 0- , rf' 1- )-- goR StencilRunit5 rf ix =- let z :. i = ix- rf' d = rf (z :. i+d)- in- ( rf' (-2)- , rf' (-1)- , rf' 0- , rf' 1- , rf' 2- )-- goR StencilRunit7 rf ix =- let z :. i = ix- rf' d = rf (z :. i+d)- in- ( rf' (-3)- , rf' (-2)- , rf' (-1)- , rf' 0- , rf' 1- , rf' 2- , rf' 3- )-- goR StencilRunit9 rf ix =- let z :. i = ix- rf' d = rf (z :. i+d)- in- ( rf' (-4)- , rf' (-3)- , rf' (-2)- , rf' (-1)- , rf' 0- , rf' 1- , rf' 2- , rf' 3- , rf' 4- )-- -- Recursive cases. Note that because the stencil pattern is defined with- -- cons ordering, whereas shapes (and indices) are defined as a snoc-list,- -- when we recurse on the stencil structure we must manipulate the- -- _left-most_ index component.- --- goR (StencilRtup3 s1 s2 s3) rf ix =- let (i, ix') = uncons ix- rf' d ds = rf (cons (i+d) ds)- in- ( goR s1 (rf' (-1)) ix'- , goR s2 (rf' 0) ix'- , goR s3 (rf' 1) ix'- )-- goR (StencilRtup5 s1 s2 s3 s4 s5) rf ix =- let (i, ix') = uncons ix- rf' d ds = rf (cons (i+d) ds)- in- ( goR s1 (rf' (-2)) ix'- , goR s2 (rf' (-1)) ix'- , goR s3 (rf' 0) ix'- , goR s4 (rf' 1) ix'- , goR s5 (rf' 2) ix'- )-- goR (StencilRtup7 s1 s2 s3 s4 s5 s6 s7) rf ix =- let (i, ix') = uncons ix- rf' d ds = rf (cons (i+d) ds)- in- ( goR s1 (rf' (-3)) ix'- , goR s2 (rf' (-2)) ix'- , goR s3 (rf' (-1)) ix'- , goR s4 (rf' 0) ix'- , goR s5 (rf' 1) ix'- , goR s6 (rf' 2) ix'- , goR s7 (rf' 3) ix'- )-- goR (StencilRtup9 s1 s2 s3 s4 s5 s6 s7 s8 s9) rf ix =- let (i, ix') = uncons ix- rf' d ds = rf (cons (i+d) ds)- in- ( goR s1 (rf' (-4)) ix'- , goR s2 (rf' (-3)) ix'- , goR s3 (rf' (-2)) ix'- , goR s4 (rf' (-1)) ix'- , goR s5 (rf' 0) ix'- , goR s6 (rf' 1) ix'- , goR s7 (rf' 2) ix'- , goR s8 (rf' 3) ix'- , goR s9 (rf' 4) ix'- )-- -- Add a left-most component to an index- --- cons :: forall sh. Shape sh => Int -> sh -> (sh :. Int)- cons ix extent = toElt $ go (eltType (undefined::sh)) (fromElt extent)- where- go :: TupleType t -> t -> (t, Int)- go UnitTuple () = ((), ix)- go (PairTuple th tz) (sh, sz)- | SingleTuple t <- tz- , Just Refl <- matchScalarType t (scalarType :: ScalarType Int)- = (go th sh, sz)- go _ _- = $internalError "cons" "expected index with Int components"-- -- Remove the left-most index of an index, and return the remainder- --- uncons :: forall sh. Shape sh => sh :. Int -> (Int, sh)- uncons extent = let (i,ix) = go (eltType (undefined::(sh:.Int))) (fromElt extent)- in (i, toElt ix)- where- go :: TupleType (t, Int) -> (t, Int) -> (Int, t)- go (PairTuple UnitTuple _) ((), v) = (v, ())- go (PairTuple t1@(PairTuple _ t2) _) (v1,v3)- | SingleTuple t <- t2- , Just Refl <- matchScalarType t (scalarType :: ScalarType Int)- = let (i, v1') = go t1 v1- in (i, (v1', v3))- go _ _- = $internalError "uncons" "expected index with Int components"---bounded- :: (Shape sh, Elt e)- => Boundary (Array sh e)- -> Array sh e- -> sh- -> e-bounded bnd arr ix =- if inside (shape arr) ix- then arr ! ix- else- case bnd of- Function f -> f ix- Constant v -> toElt v- _ -> arr ! bound (shape arr) ix-- where- -- Whether the index (second argument) is inside the bounds of the given- -- shape (first argument).- --- inside :: forall sh. Shape sh => sh -> sh -> Bool- inside sh1 ix1 = go (eltType (undefined::sh)) (fromElt sh1) (fromElt ix1)- where- go :: TupleType t -> t -> t -> Bool- go UnitTuple () () = True- go (PairTuple tsh ti) (sh, sz) (ih,iz)- = if go ti sz iz- then go tsh sh ih- else False- go (SingleTuple t) sz iz- | Just Refl <- matchScalarType t (scalarType :: ScalarType Int)- = if iz < 0 || iz >= sz- then False- else True- --- | otherwise- = $internalError "inside" "expected index with Int components"-- -- Return the index (second argument), updated to obey the given boundary- -- conditions when outside the bounds of the given shape (first argument)- --- bound :: forall sh. Shape sh => sh -> sh -> sh- bound sh1 ix1 = toElt $ go (eltType (undefined::sh)) (fromElt sh1) (fromElt ix1)- where- go :: TupleType t -> t -> t -> t- go UnitTuple () () = ()- go (PairTuple tsh ti) (sh, sz) (ih, iz) = (go tsh sh ih, go ti sz iz)- go (SingleTuple t) sz iz- | Just Refl <- matchScalarType t (scalarType :: ScalarType Int)- = let i | iz < 0 = case bnd of- Clamp -> 0- Mirror -> -iz- Wrap -> sz + iz- _ -> $internalError "bound" "unexpected boundary condition"- | iz >= sz = case bnd of- Clamp -> sz - 1- Mirror -> sz - (iz - sz + 2)- Wrap -> iz - sz- _ -> $internalError "bound" "unexpected boundary condition"- | otherwise = iz- in i- | otherwise- = $internalError "bound" "expected index with Int components"----- toSeqOp :: forall slix sl dim co e proxy. (Elt slix, Shape sl, Shape dim, Elt e)--- => SliceIndex (EltRepr slix)--- (EltRepr sl)--- co--- (EltRepr dim)--- -> proxy slix--- -> Array dim e--- -> [Array sl e]--- toSeqOp sliceIndex _ arr = map (sliceOp sliceIndex arr :: slix -> Array sl e)--- (enumSlices sliceIndex (shape arr))----- Stencil boundary conditions--- -----------------------------data Boundary t where- Clamp :: Boundary t- Mirror :: Boundary t- Wrap :: Boundary t- Constant :: Elt t => EltRepr t -> Boundary (Array sh t)- Function :: (Shape sh, Elt e) => (sh -> e) -> Boundary (Array sh e)---evalPreBoundary :: EvalAcc acc -> AST.PreBoundary acc aenv t -> Val aenv -> Boundary t-evalPreBoundary evalAcc bnd aenv =- case bnd of- AST.Clamp -> Clamp- AST.Mirror -> Mirror- AST.Wrap -> Wrap- AST.Constant v -> Constant v- AST.Function f -> Function (evalPreFun evalAcc f aenv)----- Scalar expression evaluation--- -------------------------------- Evaluate a closed scalar expression----evalPreExp :: EvalAcc acc -> PreExp acc aenv t -> Val aenv -> t-evalPreExp evalAcc e aenv = evalPreOpenExp evalAcc e EmptyElt aenv---- Evaluate a closed scalar function----evalPreFun :: EvalAcc acc -> PreFun acc aenv t -> Val aenv -> t-evalPreFun evalAcc f aenv = evalPreOpenFun evalAcc f EmptyElt aenv---- Evaluate an open scalar function----evalPreOpenFun :: EvalAcc acc -> PreOpenFun acc env aenv t -> ValElt env -> Val aenv -> t-evalPreOpenFun evalAcc (Body e) env aenv = evalPreOpenExp evalAcc e env aenv-evalPreOpenFun evalAcc (Lam f) env aenv =- \x -> evalPreOpenFun evalAcc f (env `PushElt` fromElt x) aenv----- Evaluate an open scalar expression------ NB: The implementation of 'Index' and 'Shape' demonstrate clearly why--- array expressions must be hoisted out of scalar expressions before code--- execution. If these operations are in the body of a function that gets--- mapped over an array, the array argument would be evaluated many times--- leading to a large amount of wasteful recomputation.----evalPreOpenExp- :: forall acc env aenv t.- EvalAcc acc- -> PreOpenExp acc env aenv t- -> ValElt env- -> Val aenv- -> t-evalPreOpenExp evalAcc pexp env aenv =- let- evalE :: PreOpenExp acc env aenv t' -> t'- evalE e = evalPreOpenExp evalAcc e env aenv-- evalF :: PreOpenFun acc env aenv f' -> f'- evalF f = evalPreOpenFun evalAcc f env aenv-- evalA :: acc aenv a -> a- evalA a = evalAcc a aenv- in- case pexp of- Let exp1 exp2 -> let !v1 = evalE exp1- env' = env `PushElt` fromElt v1- in evalPreOpenExp evalAcc exp2 env' aenv- Var ix -> prjElt ix env- Const c -> toElt c- PrimConst c -> evalPrimConst c- PrimApp f x -> evalPrim f (evalE x)- Tuple tup -> toTuple $ evalTuple evalAcc tup env aenv- Prj ix tup -> evalPrj ix . fromTuple $ evalE tup- IndexNil -> Z- IndexAny -> Any- IndexCons sh sz -> evalE sh :. evalE sz- IndexHead sh -> let _ :. ix = evalE sh in ix- IndexTail sh -> let ix :. _ = evalE sh in ix- IndexSlice slice slix sh -> toElt $ restrict slice (fromElt (evalE slix))- (fromElt (evalE sh))- where- restrict :: SliceIndex slix sl co sh -> slix -> sh -> sl- restrict SliceNil () () = ()- restrict (SliceAll sliceIdx) (slx, ()) (sl, sz) =- let sl' = restrict sliceIdx slx sl- in (sl', sz)- restrict (SliceFixed sliceIdx) (slx, _i) (sl, _sz) =- restrict sliceIdx slx sl-- IndexFull slice slix sh -> toElt $ extend slice (fromElt (evalE slix))- (fromElt (evalE sh))- where- extend :: SliceIndex slix sl co sh -> slix -> sl -> sh- extend SliceNil () () = ()- extend (SliceAll sliceIdx) (slx, ()) (sl, sz) =- let sh' = extend sliceIdx slx sl- in (sh', sz)- extend (SliceFixed sliceIdx) (slx, sz) sl =- let sh' = extend sliceIdx slx sl- in (sh', sz)-- ToIndex sh ix -> toIndex (evalE sh) (evalE ix)- FromIndex sh ix -> fromIndex (evalE sh) (evalE ix)- Cond c t e- | evalE c -> evalE t- | otherwise -> evalE e-- While cond body seed -> go (evalE seed)- where- f = evalF body- p = evalF cond- go !x- | p x = go (f x)- | otherwise = x-- Index acc ix -> evalA acc ! evalE ix- LinearIndex acc i -> let a = evalA acc- ix = fromIndex (shape a) (evalE i)- in a ! ix- Shape acc -> shape (evalA acc)- ShapeSize sh -> size (evalE sh)- Intersect sh1 sh2 -> intersect (evalE sh1) (evalE sh2)- Union sh1 sh2 -> union (evalE sh1) (evalE sh2)- Foreign _ f e -> evalPreOpenFun evalAcc f EmptyElt Empty $ evalE e----- Scalar primitives--- -------------------evalPrimConst :: PrimConst a -> a-evalPrimConst (PrimMinBound ty) = evalMinBound ty-evalPrimConst (PrimMaxBound ty) = evalMaxBound ty-evalPrimConst (PrimPi ty) = evalPi ty--evalPrim :: PrimFun p -> p-evalPrim (PrimAdd ty) = evalAdd ty-evalPrim (PrimSub ty) = evalSub ty-evalPrim (PrimMul ty) = evalMul ty-evalPrim (PrimNeg ty) = evalNeg ty-evalPrim (PrimAbs ty) = evalAbs ty-evalPrim (PrimSig ty) = evalSig ty-evalPrim (PrimQuot ty) = evalQuot ty-evalPrim (PrimRem ty) = evalRem ty-evalPrim (PrimQuotRem ty) = evalQuotRem ty-evalPrim (PrimIDiv ty) = evalIDiv ty-evalPrim (PrimMod ty) = evalMod ty-evalPrim (PrimDivMod ty) = evalDivMod ty-evalPrim (PrimBAnd ty) = evalBAnd ty-evalPrim (PrimBOr ty) = evalBOr ty-evalPrim (PrimBXor ty) = evalBXor ty-evalPrim (PrimBNot ty) = evalBNot ty-evalPrim (PrimBShiftL ty) = evalBShiftL ty-evalPrim (PrimBShiftR ty) = evalBShiftR ty-evalPrim (PrimBRotateL ty) = evalBRotateL ty-evalPrim (PrimBRotateR ty) = evalBRotateR ty-evalPrim (PrimPopCount ty) = evalPopCount ty-evalPrim (PrimCountLeadingZeros ty) = evalCountLeadingZeros ty-evalPrim (PrimCountTrailingZeros ty) = evalCountTrailingZeros ty-evalPrim (PrimFDiv ty) = evalFDiv ty-evalPrim (PrimRecip ty) = evalRecip ty-evalPrim (PrimSin ty) = evalSin ty-evalPrim (PrimCos ty) = evalCos ty-evalPrim (PrimTan ty) = evalTan ty-evalPrim (PrimAsin ty) = evalAsin ty-evalPrim (PrimAcos ty) = evalAcos ty-evalPrim (PrimAtan ty) = evalAtan ty-evalPrim (PrimSinh ty) = evalSinh ty-evalPrim (PrimCosh ty) = evalCosh ty-evalPrim (PrimTanh ty) = evalTanh ty-evalPrim (PrimAsinh ty) = evalAsinh ty-evalPrim (PrimAcosh ty) = evalAcosh ty-evalPrim (PrimAtanh ty) = evalAtanh ty-evalPrim (PrimExpFloating ty) = evalExpFloating ty-evalPrim (PrimSqrt ty) = evalSqrt ty-evalPrim (PrimLog ty) = evalLog ty-evalPrim (PrimFPow ty) = evalFPow ty-evalPrim (PrimLogBase ty) = evalLogBase ty-evalPrim (PrimTruncate ta tb) = evalTruncate ta tb-evalPrim (PrimRound ta tb) = evalRound ta tb-evalPrim (PrimFloor ta tb) = evalFloor ta tb-evalPrim (PrimCeiling ta tb) = evalCeiling ta tb-evalPrim (PrimAtan2 ty) = evalAtan2 ty-evalPrim (PrimIsNaN ty) = evalIsNaN ty-evalPrim (PrimIsInfinite ty) = evalIsInfinite ty-evalPrim (PrimLt ty) = evalLt ty-evalPrim (PrimGt ty) = evalGt ty-evalPrim (PrimLtEq ty) = evalLtEq ty-evalPrim (PrimGtEq ty) = evalGtEq ty-evalPrim (PrimEq ty) = evalEq ty-evalPrim (PrimNEq ty) = evalNEq ty-evalPrim (PrimMax ty) = evalMax ty-evalPrim (PrimMin ty) = evalMin ty-evalPrim PrimLAnd = evalLAnd-evalPrim PrimLOr = evalLOr-evalPrim PrimLNot = evalLNot-evalPrim PrimOrd = evalOrd-evalPrim PrimChr = evalChr-evalPrim PrimBoolToInt = evalBoolToInt-evalPrim (PrimFromIntegral ta tb) = evalFromIntegral ta tb-evalPrim (PrimToFloating ta tb) = evalToFloating ta tb-evalPrim PrimCoerce{} = unsafeCoerce----- Tuple construction and projection--- -----------------------------------evalTuple :: EvalAcc acc -> Tuple (PreOpenExp acc env aenv) t -> ValElt env -> Val aenv -> t-evalTuple _ NilTup _env _aenv = ()-evalTuple evalAcc (tup `SnocTup` e) env aenv =- (evalTuple evalAcc tup env aenv, evalPreOpenExp evalAcc e env aenv)--evalPrj :: TupleIdx t e -> t -> e-evalPrj ZeroTupIdx (!_, v) = v-evalPrj (SuccTupIdx idx) (tup, !_) = evalPrj idx tup- -- FIXME: Strictly speaking, we ought to force all components of a tuples;- -- not only those that we happen to encounter during the recursive- -- walk.----- Implementation of scalar primitives--- -------------------------------------evalLAnd :: (Bool, Bool) -> Bool-evalLAnd (x, y) = x && y--evalLOr :: (Bool, Bool) -> Bool-evalLOr (x, y) = x || y--evalLNot :: Bool -> Bool-evalLNot = not--evalOrd :: Char -> Int-evalOrd = ord--evalChr :: Int -> Char-evalChr = chr--evalBoolToInt :: Bool -> Int-evalBoolToInt = fromEnum--evalFromIntegral :: IntegralType a -> NumType b -> a -> b-evalFromIntegral ta (IntegralNumType tb)- | IntegralDict <- integralDict ta- , IntegralDict <- integralDict tb- = fromIntegral--evalFromIntegral ta (FloatingNumType tb)- | IntegralDict <- integralDict ta- , FloatingDict <- floatingDict tb- = fromIntegral--evalToFloating :: NumType a -> FloatingType b -> a -> b-evalToFloating (IntegralNumType ta) tb- | IntegralDict <- integralDict ta- , FloatingDict <- floatingDict tb- = realToFrac--evalToFloating (FloatingNumType ta) tb- | FloatingDict <- floatingDict ta- , FloatingDict <- floatingDict tb- = realToFrac----- Extract methods from reified dictionaries------- Constant methods of Bounded-----evalMinBound :: BoundedType a -> a-evalMinBound (IntegralBoundedType ty)- | IntegralDict <- integralDict ty- = minBound--evalMinBound (NonNumBoundedType ty)- | NonNumDict <- nonNumDict ty- = minBound--evalMaxBound :: BoundedType a -> a-evalMaxBound (IntegralBoundedType ty)- | IntegralDict <- integralDict ty- = maxBound--evalMaxBound (NonNumBoundedType ty)- | NonNumDict <- nonNumDict ty- = maxBound---- Constant method of floating-----evalPi :: FloatingType a -> a-evalPi ty | FloatingDict <- floatingDict ty = pi--evalSin :: FloatingType a -> (a -> a)-evalSin ty | FloatingDict <- floatingDict ty = sin--evalCos :: FloatingType a -> (a -> a)-evalCos ty | FloatingDict <- floatingDict ty = cos--evalTan :: FloatingType a -> (a -> a)-evalTan ty | FloatingDict <- floatingDict ty = tan--evalAsin :: FloatingType a -> (a -> a)-evalAsin ty | FloatingDict <- floatingDict ty = asin--evalAcos :: FloatingType a -> (a -> a)-evalAcos ty | FloatingDict <- floatingDict ty = acos--evalAtan :: FloatingType a -> (a -> a)-evalAtan ty | FloatingDict <- floatingDict ty = atan--evalSinh :: FloatingType a -> (a -> a)-evalSinh ty | FloatingDict <- floatingDict ty = sinh--evalCosh :: FloatingType a -> (a -> a)-evalCosh ty | FloatingDict <- floatingDict ty = cosh--evalTanh :: FloatingType a -> (a -> a)-evalTanh ty | FloatingDict <- floatingDict ty = tanh--evalAsinh :: FloatingType a -> (a -> a)-evalAsinh ty | FloatingDict <- floatingDict ty = asinh--evalAcosh :: FloatingType a -> (a -> a)-evalAcosh ty | FloatingDict <- floatingDict ty = acosh--evalAtanh :: FloatingType a -> (a -> a)-evalAtanh ty | FloatingDict <- floatingDict ty = atanh--evalExpFloating :: FloatingType a -> (a -> a)-evalExpFloating ty | FloatingDict <- floatingDict ty = exp--evalSqrt :: FloatingType a -> (a -> a)-evalSqrt ty | FloatingDict <- floatingDict ty = sqrt--evalLog :: FloatingType a -> (a -> a)-evalLog ty | FloatingDict <- floatingDict ty = log--evalFPow :: FloatingType a -> ((a, a) -> a)-evalFPow ty | FloatingDict <- floatingDict ty = uncurry (**)--evalLogBase :: FloatingType a -> ((a, a) -> a)-evalLogBase ty | FloatingDict <- floatingDict ty = uncurry logBase--evalTruncate :: FloatingType a -> IntegralType b -> (a -> b)-evalTruncate ta tb- | FloatingDict <- floatingDict ta- , IntegralDict <- integralDict tb- = truncate--evalRound :: FloatingType a -> IntegralType b -> (a -> b)-evalRound ta tb- | FloatingDict <- floatingDict ta- , IntegralDict <- integralDict tb- = round--evalFloor :: FloatingType a -> IntegralType b -> (a -> b)-evalFloor ta tb- | FloatingDict <- floatingDict ta- , IntegralDict <- integralDict tb- = floor--evalCeiling :: FloatingType a -> IntegralType b -> (a -> b)-evalCeiling ta tb- | FloatingDict <- floatingDict ta- , IntegralDict <- integralDict tb- = ceiling--evalAtan2 :: FloatingType a -> ((a, a) -> a)-evalAtan2 ty | FloatingDict <- floatingDict ty = uncurry atan2--evalIsNaN :: FloatingType a -> (a -> Bool)-evalIsNaN ty | FloatingDict <- floatingDict ty = isNaN--evalIsInfinite :: FloatingType a -> (a -> Bool)-evalIsInfinite ty | FloatingDict <- floatingDict ty = isInfinite----- Methods of Num-----evalAdd :: NumType a -> ((a, a) -> a)-evalAdd (IntegralNumType ty) | IntegralDict <- integralDict ty = uncurry (+)-evalAdd (FloatingNumType ty) | FloatingDict <- floatingDict ty = uncurry (+)--evalSub :: NumType a -> ((a, a) -> a)-evalSub (IntegralNumType ty) | IntegralDict <- integralDict ty = uncurry (-)-evalSub (FloatingNumType ty) | FloatingDict <- floatingDict ty = uncurry (-)--evalMul :: NumType a -> ((a, a) -> a)-evalMul (IntegralNumType ty) | IntegralDict <- integralDict ty = uncurry (*)-evalMul (FloatingNumType ty) | FloatingDict <- floatingDict ty = uncurry (*)--evalNeg :: NumType a -> (a -> a)-evalNeg (IntegralNumType ty) | IntegralDict <- integralDict ty = negate-evalNeg (FloatingNumType ty) | FloatingDict <- floatingDict ty = negate--evalAbs :: NumType a -> (a -> a)-evalAbs (IntegralNumType ty) | IntegralDict <- integralDict ty = abs-evalAbs (FloatingNumType ty) | FloatingDict <- floatingDict ty = abs--evalSig :: NumType a -> (a -> a)-evalSig (IntegralNumType ty) | IntegralDict <- integralDict ty = signum-evalSig (FloatingNumType ty) | FloatingDict <- floatingDict ty = signum--evalQuot :: IntegralType a -> ((a, a) -> a)-evalQuot ty | IntegralDict <- integralDict ty = uncurry quot--evalRem :: IntegralType a -> ((a, a) -> a)-evalRem ty | IntegralDict <- integralDict ty = uncurry rem--evalQuotRem :: IntegralType a -> ((a, a) -> (a, a))-evalQuotRem ty | IntegralDict <- integralDict ty = uncurry quotRem--evalIDiv :: IntegralType a -> ((a, a) -> a)-evalIDiv ty | IntegralDict <- integralDict ty = uncurry div--evalMod :: IntegralType a -> ((a, a) -> a)-evalMod ty | IntegralDict <- integralDict ty = uncurry mod--evalDivMod :: IntegralType a -> ((a, a) -> (a, a))-evalDivMod ty | IntegralDict <- integralDict ty = uncurry divMod--evalBAnd :: IntegralType a -> ((a, a) -> a)-evalBAnd ty | IntegralDict <- integralDict ty = uncurry (.&.)--evalBOr :: IntegralType a -> ((a, a) -> a)-evalBOr ty | IntegralDict <- integralDict ty = uncurry (.|.)--evalBXor :: IntegralType a -> ((a, a) -> a)-evalBXor ty | IntegralDict <- integralDict ty = uncurry xor--evalBNot :: IntegralType a -> (a -> a)-evalBNot ty | IntegralDict <- integralDict ty = complement--evalBShiftL :: IntegralType a -> ((a, Int) -> a)-evalBShiftL ty | IntegralDict <- integralDict ty = uncurry shiftL--evalBShiftR :: IntegralType a -> ((a, Int) -> a)-evalBShiftR ty | IntegralDict <- integralDict ty = uncurry shiftR--evalBRotateL :: IntegralType a -> ((a, Int) -> a)-evalBRotateL ty | IntegralDict <- integralDict ty = uncurry rotateL--evalBRotateR :: IntegralType a -> ((a, Int) -> a)-evalBRotateR ty | IntegralDict <- integralDict ty = uncurry rotateR--evalPopCount :: IntegralType a -> (a -> Int)-evalPopCount ty | IntegralDict <- integralDict ty = popCount--evalCountLeadingZeros :: IntegralType a -> (a -> Int)-#if __GLASGOW_HASKELL__ >= 710-evalCountLeadingZeros ty | IntegralDict <- integralDict ty = countLeadingZeros-#else-evalCountLeadingZeros ty | IntegralDict <- integralDict ty = clz- where- clz x = (w-1) - go (w-1)- where- go i | i < 0 = i -- no bit set- | testBit x i = i- | otherwise = go (i-1)- w = finiteBitSize x-#endif--evalCountTrailingZeros :: IntegralType a -> (a -> Int)-#if __GLASGOW_HASKELL__ >= 710-evalCountTrailingZeros ty | IntegralDict <- integralDict ty = countTrailingZeros-#else-evalCountTrailingZeros ty | IntegralDict <- integralDict ty = ctz- where- ctz x = go 0- where- go i | i >= w = i- | testBit x i = i- | otherwise = go (i+1)- w = finiteBitSize x-#endif---evalFDiv :: FloatingType a -> ((a, a) -> a)-evalFDiv ty | FloatingDict <- floatingDict ty = uncurry (/)--evalRecip :: FloatingType a -> (a -> a)-evalRecip ty | FloatingDict <- floatingDict ty = recip---evalLt :: ScalarType a -> ((a, a) -> Bool)-evalLt (NumScalarType (IntegralNumType ty)) | IntegralDict <- integralDict ty = uncurry (<)-evalLt (NumScalarType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = uncurry (<)-evalLt (NonNumScalarType ty) | NonNumDict <- nonNumDict ty = uncurry (<)--evalGt :: ScalarType a -> ((a, a) -> Bool)-evalGt (NumScalarType (IntegralNumType ty)) | IntegralDict <- integralDict ty = uncurry (>)-evalGt (NumScalarType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = uncurry (>)-evalGt (NonNumScalarType ty) | NonNumDict <- nonNumDict ty = uncurry (>)--evalLtEq :: ScalarType a -> ((a, a) -> Bool)-evalLtEq (NumScalarType (IntegralNumType ty)) | IntegralDict <- integralDict ty = uncurry (<=)-evalLtEq (NumScalarType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = uncurry (<=)-evalLtEq (NonNumScalarType ty) | NonNumDict <- nonNumDict ty = uncurry (<=)--evalGtEq :: ScalarType a -> ((a, a) -> Bool)-evalGtEq (NumScalarType (IntegralNumType ty)) | IntegralDict <- integralDict ty = uncurry (>=)-evalGtEq (NumScalarType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = uncurry (>=)-evalGtEq (NonNumScalarType ty) | NonNumDict <- nonNumDict ty = uncurry (>=)--evalEq :: ScalarType a -> ((a, a) -> Bool)-evalEq (NumScalarType (IntegralNumType ty)) | IntegralDict <- integralDict ty = uncurry (==)-evalEq (NumScalarType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = uncurry (==)-evalEq (NonNumScalarType ty) | NonNumDict <- nonNumDict ty = uncurry (==)--evalNEq :: ScalarType a -> ((a, a) -> Bool)-evalNEq (NumScalarType (IntegralNumType ty)) | IntegralDict <- integralDict ty = uncurry (/=)-evalNEq (NumScalarType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = uncurry (/=)-evalNEq (NonNumScalarType ty) | NonNumDict <- nonNumDict ty = uncurry (/=)--evalMax :: ScalarType a -> ((a, a) -> a)-evalMax (NumScalarType (IntegralNumType ty)) | IntegralDict <- integralDict ty = uncurry max-evalMax (NumScalarType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = uncurry max-evalMax (NonNumScalarType ty) | NonNumDict <- nonNumDict ty = uncurry max--evalMin :: ScalarType a -> ((a, a) -> a)-evalMin (NumScalarType (IntegralNumType ty)) | IntegralDict <- integralDict ty = uncurry min-evalMin (NumScalarType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = uncurry min-evalMin (NonNumScalarType ty) | NonNumDict <- nonNumDict ty = uncurry min---{----- Sequence evaluation--- ------------------- Position in sequence.----type SeqPos = Int---- Configuration for sequence evaluation.----data SeqConfig = SeqConfig- { chunkSize :: Int -- Allocation limit for a sequence in- -- words. Actual runtime allocation should be the- -- maximum of this size and the size of the- -- largest element in the sequence.- }---- Default sequence evaluation configuration for testing purposes.----defaultSeqConfig :: SeqConfig-defaultSeqConfig = SeqConfig { chunkSize = 2 }--type Chunk a = Vector' a---- The empty chunk. O(1).-emptyChunk :: Arrays a => Chunk a-emptyChunk = empty'---- Number of arrays in chunk. O(1).----clen :: Arrays a => Chunk a -> Int-clen = length'--elemsPerChunk :: SeqConfig -> Int -> Int-elemsPerChunk conf n- | n < 1 = chunkSize conf- | otherwise =- let (a,b) = chunkSize conf `quotRem` n- in a + signum b---- Drop a number of arrays from a chunk. O(1). Note: Require keeping a--- scan of element sizes.----cdrop :: Arrays a => Int -> Chunk a -> Chunk a-cdrop = drop' dropOp (fst . offsetsOp)---- Get all the shapes of a chunk of arrays. O(1).----chunkShapes :: Chunk (Array sh a) -> Vector sh-chunkShapes = shapes'---- Get all the elements of a chunk of arrays. O(1).----chunkElems :: Chunk (Array sh a) -> Vector a-chunkElems = elements'---- Convert a vector to a chunk of scalars.----vec2Chunk :: Elt e => Vector e -> Chunk (Scalar e)-vec2Chunk = vec2Vec'---- Convert a list of arrays to a chunk.----fromListChunk :: Arrays a => [a] -> Vector' a-fromListChunk = fromList' concatOp---- Convert a chunk to a list of arrays.----toListChunk :: Arrays a => Vector' a -> [a]-toListChunk = toList' fetchAllOp---- fmap for Chunk. O(n).--- TODO: Use vectorised function.-mapChunk :: (Arrays a, Arrays b)- => (a -> b)- -> Chunk a -> Chunk b-mapChunk f c = fromListChunk $ map f (toListChunk c)---- zipWith for Chunk. O(n).--- TODO: Use vectorised function.-zipWithChunk :: (Arrays a, Arrays b, Arrays c)- => (a -> b -> c)- -> Chunk a -> Chunk b -> Chunk c-zipWithChunk f c1 c2 = fromListChunk $ zipWith f (toListChunk c1) (toListChunk c2)---- A window on a sequence.----data Window a = Window- { chunk :: Chunk a -- Current allocated chunk.- , wpos :: SeqPos -- Position of the window on the sequence, given- -- in number of elements.- }---- The initial empty window.----window0 :: Arrays a => Window a-window0 = Window { chunk = emptyChunk, wpos = 0 }---- Index the given window by the given index on the sequence.----(!#) :: Arrays a => Window a -> SeqPos -> Chunk a-w !# i- | j <- i - wpos w- , j >= 0- = cdrop j (chunk w)- --- | otherwise- = error $ "Window indexed before position. wpos = " ++ show (wpos w) ++ " i = " ++ show i---- Move the give window by supplying the next chunk.----moveWin :: Arrays a => Window a -> Chunk a -> Window a-moveWin w c = w { chunk = c- , wpos = wpos w + clen (chunk w)- }---- A cursor on a sequence.----data Cursor senv a = Cursor- { ref :: Idx senv a -- Reference to the sequence.- , cpos :: SeqPos -- Position of the cursor on the sequence,- -- given in number of elements.- }---- Initial cursor.----cursor0 :: Idx senv a -> Cursor senv a-cursor0 x = Cursor { ref = x, cpos = 0 }---- Advance cursor by a relative amount.----moveCursor :: Int -> Cursor senv a -> Cursor senv a-moveCursor k c = c { cpos = cpos c + k }---- Valuation for an environment of sequence windows.----data Val' senv where- Empty' :: Val' ()- Push' :: Val' senv -> Window t -> Val' (senv, t)---- Projection of a window from a window valuation using a de Bruijn--- index.----prj' :: Idx senv t -> Val' senv -> Window t-prj' ZeroIdx (Push' _ v) = v-prj' (SuccIdx idx) (Push' val _) = prj' idx val-#if __GLASGOW_HASKELL__ < 800-prj' _ _ = $internalError "prj" "inconsistent valuation"-#endif---- Projection of a chunk from a window valuation using a sequence--- cursor.----prjChunk :: Arrays a => Cursor senv a -> Val' senv -> Chunk a-prjChunk c senv = prj' (ref c) senv !# cpos c---- An executable sequence.----data ExecSeq senv arrs where- ExecP :: Arrays a => Window a -> ExecP senv a -> ExecSeq (senv, a) arrs -> ExecSeq senv arrs- ExecC :: Arrays a => ExecC senv a -> ExecSeq senv a- ExecR :: Arrays a => Cursor senv a -> ExecSeq senv [a]---- An executable producer.----data ExecP senv a where- ExecStreamIn :: Int- -> [a]- -> ExecP senv a-- ExecMap :: Arrays a- => (Chunk a -> Chunk b)- -> Cursor senv a- -> ExecP senv b-- ExecZipWith :: (Arrays a, Arrays b)- => (Chunk a -> Chunk b -> Chunk c)- -> Cursor senv a- -> Cursor senv b- -> ExecP senv c-- -- Stream scan skeleton.- ExecScan :: Arrays a- => (s -> Chunk a -> (Chunk r, s)) -- Chunk scanner.- -> s -- Accumulator (internal state).- -> Cursor senv a -- Input stream.- -> ExecP senv r---- An executable consumer.----data ExecC senv a where-- -- Stream reduction skeleton.- ExecFold :: Arrays a- => (s -> Chunk a -> s) -- Chunk consumer function.- -> (s -> r) -- Finalizer function.- -> s -- Accumulator (internal state).- -> Cursor senv a -- Input stream.- -> ExecC senv r-- ExecStuple :: IsAtuple a- => Atuple (ExecC senv) (TupleRepr a)- -> ExecC senv a--minCursor :: ExecSeq senv a -> SeqPos-minCursor s = travS s 0- where- travS :: ExecSeq senv a -> Int -> SeqPos- travS s i =- case s of- ExecP _ p s' -> travP p i `min` travS s' (i+1)- ExecC c -> travC c i- ExecR _ -> maxBound-- k :: Cursor senv a -> Int -> SeqPos- k c i- | i == idxToInt (ref c) = cpos c- | otherwise = maxBound-- travP :: ExecP senv a -> Int -> SeqPos- travP p i =- case p of- ExecStreamIn _ _ -> maxBound- ExecMap _ c -> k c i- ExecZipWith _ c1 c2 -> k c1 i `min` k c2 i- ExecScan _ _ c -> k c i-- travT :: Atuple (ExecC senv) t -> Int -> SeqPos- travT NilAtup _ = maxBound- travT (SnocAtup t c) i = travT t i `min` travC c i-- travC :: ExecC senv a -> Int -> SeqPos- travC c i =- case c of- ExecFold _ _ _ cu -> k cu i- ExecStuple t -> travT t i---evalDelayedSeq :: SeqConfig- -> DelayedSeq arrs- -> arrs-evalDelayedSeq cfg (DelayedSeq aenv s) | aenv' <- evalExtend aenv Empty- = evalSeq cfg s aenv'--evalSeq :: forall aenv arrs.- SeqConfig- -> PreOpenSeq DelayedOpenAcc aenv () arrs- -> Val aenv -> arrs-evalSeq conf s aenv = evalSeq' s- where- evalSeq' :: PreOpenSeq DelayedOpenAcc aenv senv arrs -> arrs- evalSeq' (Producer _ s) = evalSeq' s- evalSeq' (Consumer _) = loop (initSeq aenv s)- evalSeq' (Reify _) = reify (initSeq aenv s)-- -- Initialize the producers and the accumulators of the consumers- -- with the given array enviroment.- initSeq :: forall senv arrs'.- Val aenv- -> PreOpenSeq DelayedOpenAcc aenv senv arrs'- -> ExecSeq senv arrs'- initSeq aenv s =- case s of- Producer p s' -> ExecP window0 (initProducer p) (initSeq aenv s')- Consumer c -> ExecC (initConsumer c)- Reify ix -> ExecR (cursor0 ix)-- -- Generate a list from the sequence.- reify :: forall arrs. ExecSeq () [arrs]- -> [arrs]- reify s = case step s Empty' of- (Just s', a) -> a ++ reify s'- (Nothing, a) -> a-- -- Iterate the given sequence until it terminates.- -- A sequence only terminates when one of the producers are exhausted.- loop :: Arrays arrs- => ExecSeq () arrs- -> arrs- loop s =- case step' s of- (Nothing, arrs) -> arrs- (Just s', _) -> loop s'-- where- step' :: ExecSeq () arrs -> (Maybe (ExecSeq () arrs), arrs)- step' s = step s Empty'-- -- One iteration of a sequence.- step :: forall senv arrs'.- ExecSeq senv arrs'- -> Val' senv- -> (Maybe (ExecSeq senv arrs'), arrs')- step s senv =- case s of- ExecP w p s' ->- let (c, mp') = produce p senv- finished = 0 == clen (w !# minCursor s')- w' = if finished then moveWin w c else w- (ms'', a) = step s' (senv `Push'` w')- in case ms'' of- Nothing -> (Nothing, a)- Just s'' | finished- , Just p' <- mp'- -> (Just (ExecP w' p' s''), a)- | not finished- -> (Just (ExecP w' p s''), a)- | otherwise- -> (Nothing, a)- ExecC c -> let (c', acc) = consume c senv- in (Just (ExecC c'), acc)- ExecR ix -> let c = prjChunk ix senv in (Just (ExecR (moveCursor (clen c) ix)), toListChunk c)-- evalA :: DelayedOpenAcc aenv a -> a- evalA acc = evalOpenAcc acc aenv-- evalAF :: DelayedOpenAfun aenv f -> f- evalAF f = evalOpenAfun f aenv-- evalE :: DelayedExp aenv t -> t- evalE exp = evalPreExp evalOpenAcc exp aenv-- evalF :: DelayedFun aenv f -> f- evalF fun = evalPreFun evalOpenAcc fun aenv-- initProducer :: forall a senv.- Producer DelayedOpenAcc aenv senv a- -> ExecP senv a- initProducer p =- case p of- StreamIn arrs -> ExecStreamIn 1 arrs- ToSeq sliceIndex slix (delayed -> Delayed sh ix _) ->- let n = R.size (R.sliceShape sliceIndex (fromElt sh))- k = elemsPerChunk conf n- in ExecStreamIn k (toSeqOp sliceIndex slix (fromFunction sh ix))- MapSeq f x -> ExecMap (mapChunk (evalAF f)) (cursor0 x)- ChunkedMapSeq f x -> ExecMap (evalAF f) (cursor0 x)- ZipWithSeq f x y -> ExecZipWith (zipWithChunk (evalAF f)) (cursor0 x) (cursor0 y)- ScanSeq f e x -> ExecScan scanner (evalE e) (cursor0 x)- where- scanner a c =- let v0 = chunkElems c- (v1, a') = scanl'Op (evalF f) a (delayArray v0)- in (vec2Chunk v1, fromScalar a')-- initConsumer :: forall a senv.- Consumer DelayedOpenAcc aenv senv a- -> ExecC senv a- initConsumer c =- case c of- FoldSeq f e x ->- let f' = evalF f- a0 = fromFunction (Z :. chunkSize conf) (const (evalE e))- consumer v c = zipWith'Op f' (delayArray v) (delayArray (chunkElems c))- finalizer = fold1Op f' . delayArray- in ExecFold consumer finalizer a0 (cursor0 x)- FoldSeqFlatten f acc x ->- let f' = evalAF f- a0 = evalA acc- consumer a c = f' a (chunkShapes c) (chunkElems c)- in ExecFold consumer id a0 (cursor0 x)- Stuple t ->- let initTup :: Atuple (Consumer DelayedOpenAcc aenv senv) t -> Atuple (ExecC senv) t- initTup NilAtup = NilAtup- initTup (SnocAtup t c) = SnocAtup (initTup t) (initConsumer c)- in ExecStuple (initTup t)-- delayed :: DelayedOpenAcc aenv (Array sh e) -> Delayed (Array sh e)- delayed AST.Manifest{} = $internalError "evalOpenAcc" "expected delayed array"- delayed AST.Delayed{..} = Delayed (evalPreExp evalOpenAcc extentD aenv)- (evalPreFun evalOpenAcc indexD aenv)- (evalPreFun evalOpenAcc linearIndexD aenv)--produce :: Arrays a => ExecP senv a -> Val' senv -> (Chunk a, Maybe (ExecP senv a))-produce p senv =- case p of- ExecStreamIn k xs ->- let (xs', xs'') = (take k xs, drop k xs)- c = fromListChunk xs'- mp = if null xs''- then Nothing- else Just (ExecStreamIn k xs'')- in (c, mp)- ExecMap f x ->- let c = prjChunk x senv- in (f c, Just $ ExecMap f (moveCursor (clen c) x))- ExecZipWith f x y ->- let c1 = prjChunk x senv- c2 = prjChunk y senv- k = clen c1 `min` clen c2- in (f c1 c2, Just $ ExecZipWith f (moveCursor k x) (moveCursor k y))- ExecScan scanner a x ->- let c = prjChunk x senv- (c', a') = scanner a c- k = clen c- in (c', Just $ ExecScan scanner a' (moveCursor k x))--consume :: forall senv a. ExecC senv a -> Val' senv -> (ExecC senv a, a)-consume c senv =- case c of- ExecFold f g acc x ->- let c = prjChunk x senv- acc' = f acc c- -- Even though we call g here, lazy evaluation should guarantee it is- -- only ever called once.- in (ExecFold f g acc' (moveCursor (clen c) x), g acc')- ExecStuple t ->- let consT :: Atuple (ExecC senv) t -> (Atuple (ExecC senv) t, t)- consT NilAtup = (NilAtup, ())- consT (SnocAtup t c) | (c', acc) <- consume c senv- , (t', acc') <- consT t- = (SnocAtup t' c', (acc', acc))- (t', acc) = consT t- in (ExecStuple t', toAtuple acc)--evalExtend :: Extend DelayedOpenAcc aenv aenv' -> Val aenv -> Val aenv'-evalExtend BaseEnv aenv = aenv-evalExtend (PushEnv ext1 ext2) aenv | aenv' <- evalExtend ext1 aenv- = Push aenv' (evalOpenAcc ext2 aenv')--delayArray :: Array sh e -> Delayed (Array sh e)-delayArray arr@(Array _ adata) = Delayed (shape arr) (arr!) (toElt . unsafeIndexArrayData adata)--fromScalar :: Scalar a -> a-fromScalar = (!Z)--concatOp :: forall e. Elt e => [Vector e] -> Vector e-concatOp = concatVectors--fetchAllOp :: (Shape sh, Elt e) => Segments sh -> Vector e -> [Array sh e]-fetchAllOp segs elts- | (offsets, n) <- offsetsOp segs- , (n ! Z) <= size (shape elts)- = [fetch (segs ! (Z :. i)) (offsets ! (Z :. i)) | i <- [0 .. size (shape segs) - 1]]- | otherwise = error $ "illegal argument to fetchAllOp"- where- fetch sh offset = fromFunction sh (\ ix -> elts ! (Z :. ((toIndex sh ix) + offset)))--dropOp :: Elt e => Int -> Vector e -> Vector e-dropOp i v -- TODO- -- * Implement using C-style pointer-plus.- -- ; dropOp is used often (from prjChunk),- -- so it ought to be efficient O(1).- | n <- size (shape v)- , i <= n- , i >= 0- = fromFunction (Z :. n - i) (\ (Z :. j) -> v ! (Z :. i + j))- | otherwise = error $ "illegal argument to drop"--offsetsOp :: Shape sh => Segments sh -> (Vector Int, Scalar Int)-offsetsOp segs = scanl'Op (+) 0 $ delayArray (mapOp size (delayArray segs))---}-
− Data/Array/Accelerate/Language.hs
@@ -1,1373 +0,0 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE ViewPatterns #-}--- |--- Module : Data.Array.Accelerate.Language--- Copyright : [2008..2017] Manuel M T Chakravarty, Gabriele Keller--- [2009..2017] Trevor L. McDonell--- [2014..2014] Frederik M. Madsen--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)------ We use the dictionary view of overloaded operations (such as arithmetic and--- bit manipulation) to reify such expressions. With non-overloaded--- operations (such as, the logical connectives) and partially overloaded--- operations (such as comparisons), we use the standard operator names with a--- \'*\' attached. We keep the standard alphanumeric names as they can be--- easily qualified.-----module Data.Array.Accelerate.Language (-- -- * Array and scalar expressions- Acc, Exp, -- re-exporting from 'Smart'-- -- * Scalar introduction- constant, -- re-exporting from 'Smart'-- -- * Array construction- use, unit, replicate, generate,-- -- * Shape manipulation- reshape,-- -- * Extraction of sub-arrays- slice,-- -- * Map-like functions- map, zipWith,-- -- -- * Sequence collection- -- collect,-- -- -- * Sequence producers- -- streamIn, toSeq,-- -- -- * Sequence transducers- -- mapSeq, zipWithSeq, scanSeq,-- -- -- * Sequence consumers- -- foldSeq, foldSeqFlatten,-- -- * Reductions- fold, fold1, foldSeg, fold1Seg,-- -- * Scan functions- scanl, scanl', scanl1, scanr, scanr', scanr1,-- -- * Permutations- permute, backpermute,-- -- * Stencil operations- stencil, stencil2,-- -- ** Stencil specification- Boundary, Stencil,- clamp, mirror, wrap, function,--- -- ** Common stencil types- Stencil3, Stencil5, Stencil7, Stencil9,- Stencil3x3, Stencil5x3, Stencil3x5, Stencil5x5,- Stencil3x3x3, Stencil5x3x3, Stencil3x5x3, Stencil3x3x5, Stencil5x5x3, Stencil5x3x5,- Stencil3x5x5, Stencil5x5x5,-- -- * Foreign functions- foreignAcc,- foreignExp,-- -- * Pipelining- (>->),-- -- * Index construction and destruction- indexHead, indexTail, toIndex, fromIndex,- intersect, union,-- -- * Flow-control- acond, awhile,- cond, while,-- -- * Array operations with a scalar result- (!), (!!), shape, size, shapeSize,-- -- * Numeric functions- subtract, even, odd, gcd, lcm, (^), (^^),-- -- * Conversions- ord, chr, boolToInt, bitcast,-- -- * Constants- ignore--) where---- friends-import Data.Array.Accelerate.Array.Sugar hiding ( (!), ignore, shape, size, toIndex, fromIndex, intersect, union )-import Data.Array.Accelerate.Smart-import Data.Array.Accelerate.Type-import qualified Data.Array.Accelerate.Array.Sugar as Sugar--import Data.Array.Accelerate.Classes.Eq-import Data.Array.Accelerate.Classes.Fractional-import Data.Array.Accelerate.Classes.Integral-import Data.Array.Accelerate.Classes.Num-import Data.Array.Accelerate.Classes.Ord---- standard libraries-import Prelude ( ($), (.) )----- Array introduction--- ---------------------- | Make an array from vanilla Haskell available for processing within embedded--- Accelerate computations.------ Depending upon which backend is used to eventually execute array--- computations, 'use' may entail data transfer (e.g. to a GPU).------ 'use' is overloaded so that it can accept tuples of 'Arrays':------ >>> let vec = fromList (Z:.10) [0..] :: Array DIM1 Int--- Vector (Z :. 10) [0,1,2,3,4,5,6,7,8,9]------ >>> let mat = fromList (Z:.5:.10) [0..] :: Array DIM2 Int--- >>> mat--- Matrix (Z :. 5 :. 10)--- [ 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]------ >>> let vec' = use vec :: Acc (Array DIM1 Int)--- >>> let mat' = use mat :: Acc (Array DIM2 Int)--- >>> let tup = use (vec, mat) :: Acc (Array DIM1 Int, Array DIM2 Int)----use :: Arrays arrays => arrays -> Acc arrays-use = Acc . Use---- | Construct a singleton (one element) array from a scalar value (or tuple of--- scalar values).----unit :: Elt e => Exp e -> Acc (Scalar e)-unit = Acc . Unit---- | Replicate an array across one or more dimensions as specified by the--- /generalised/ array index provided as the first argument.------ For example, given the following vector:------ >>> let vec = fromList (Z:.10) [0..]--- Vector (Z :. 10) [0,1,2,3,4,5,6,7,8,9]------ ...we can replicate these elements to form a two-dimensional array either by--- replicating those elements as new rows:------ >>> replicate (lift (Z :. 4 :. All)) (use vec)--- Matrix (Z :. 4 :. 10)--- [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,--- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,--- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,--- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]------ ...or as columns:------ >>> replicate (lift (Z :. All :. 4)) (use vec)--- Matrix (Z :. 10 :. 4)--- [ 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]------ Replication along more than one dimension is also possible. Here we replicate--- twice across the first dimension and three times across the third dimension:------ >>> replicate (lift (Z :. 2 :. All :. 3)) (use vec)--- Array (Z :. 2 :. 10 :. 3) [0,0,0,1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,8,8,8,9,9,9,0,0,0,1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,8,8,8,9,9,9]------ The marker 'Any' can be used in the slice specification to match against some--- arbitrary dimension. For example, here 'Any' matches against whatever shape--- type variable @sh@ takes.------ > rep0 :: (Shape sh, Elt e) => Exp Int -> Acc (Array sh e) -> Acc (Array (sh :. Int) e)--- > rep0 n a = replicate (lift (Any :. n)) a------ >>> let x = unit 42 :: Acc (Scalar Int)--- >>> rep0 10 x--- Vector (Z :. 10) [42,42,42,42,42,42,42,42,42,42]------ >>> rep0 5 (use vec)--- Matrix (Z :. 10 :. 5)--- [ 0, 0, 0, 0, 0,--- 1, 1, 1, 1, 1,--- 2, 2, 2, 2, 2,--- 3, 3, 3, 3, 3,--- 4, 4, 4, 4, 4,--- 5, 5, 5, 5, 5,--- 6, 6, 6, 6, 6,--- 7, 7, 7, 7, 7,--- 8, 8, 8, 8, 8,--- 9, 9, 9, 9, 9]------ Of course, 'Any' and 'All' can be used together.------ > rep1 :: (Shape sh, Elt e) => Exp Int -> Acc (Array (sh :. Int) e) -> Acc (Array (sh :. Int :. Int) e)--- > rep1 n a = A.replicate (lift (Any :. n :. All)) a------ >>> rep1 5 (use vec)--- Matrix (Z :. 5 :. 10)--- [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,--- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,--- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,--- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,--- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]----replicate- :: (Slice slix, Elt e)- => Exp slix- -> Acc (Array (SliceShape slix) e)- -> Acc (Array (FullShape slix) e)-replicate = Acc $$ Replicate---- | Construct a new array by applying a function to each index.------ For example, the following will generate a one-dimensional array--- (`Vector`) of three floating point numbers:------ >>> generate (index1 3) (\_ -> 1.2)--- Vector (Z :. 3) [1.2,1.2,1.2]------ Or equivalently:------ >>> fill (constant (Z :. 3)) 1.2--- Vector (Z :. 3) [1.2,1.2,1.2]------ The following will create a vector with the elements @[1..10]@:------ >>> generate (index1 10) (\ix -> unindex1 ix + 1)--- Vector (Z :. 10) [1,2,3,4,5,6,7,8,9,10]------ [/NOTE:/]------ Using 'generate', it is possible to introduce nested data parallelism, which--- will cause the program to fail.------ If the index given by the scalar function is then used to dispatch further--- parallel work, whose result is returned into 'Exp' terms by array indexing--- operations such as ('!') or 'Data.Array.Accelerate.Prelude.the', the program--- will fail with the error:--- '.\/Data\/Array\/Accelerate\/Trafo\/Sharing.hs:447 (convertSharingExp): inconsistent valuation \@ shared \'Exp\' tree ...'.----generate- :: (Shape sh, Elt a)- => Exp sh- -> (Exp sh -> Exp a)- -> Acc (Array sh a)-generate = Acc $$ Generate---- Shape manipulation--- ---------------------- | Change the shape of an array without altering its contents. The 'size' of--- the source and result arrays must be identical.------ > precondition: shapeSize sh == shapeSize sh'------ If the argument array is manifest in memory, 'reshape' is a no-op. If the--- argument is to be fused into a subsequent operation, 'reshape' corresponds to--- an index transformation in the fused code.----reshape- :: (Shape sh, Shape sh', Elt e)- => Exp sh- -> Acc (Array sh' e)- -> Acc (Array sh e)-reshape = Acc $$ Reshape---- Extraction of sub-arrays--- ---------------------------- | Index an array with a /generalised/ array index, supplied as the second--- argument. The result is a new array (possibly a singleton) containing the--- selected dimensions ('All's) in their entirety.------ 'slice' is the opposite of 'replicate', and can be used to /cut out/ entire--- dimensions. For example, for the two dimensional array 'mat':------ >>> let mat = fromList (Z:.5:.10) [0..]--- >>> mat--- Matrix (Z :. 5 :. 10)--- [ 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]------ ...will can select a specific row to yield a one dimensional result by fixing--- the row index (2) while allowing the column index to vary (via 'All'):------ >>> slice (use mat) (lift (Z :. 2 :. All))--- Vector (Z :. 10) [20,21,22,23,24,25,26,27,28,29]------ A fully specified index (with no 'All's) returns a single element (zero--- dimensional array).------ >>> slice (use mat) (lift (Z :. 4 :. 2))--- Scalar Z [42]------ The marker 'Any' can be used in the slice specification to match against some--- arbitrary (lower) dimension. Here 'Any' matches whatever shape type variable--- @sh@ takes:------ > sl0 :: (Shape sh, Elt e) => Acc (Array (sh:.Int) e) -> Exp Int -> Acc (Array sh e)--- > sl0 a n = A.slice a (lift (Any :. n))------ >>> let vec = fromList (Z:.10) [0..]--- >>> sl0 (use vec) 4--- Scalar Z [4]------ >>> sl0 (use mat) 4--- Vector (Z :. 5) [4,14,24,34,44]------ Of course, 'Any' and 'All' can be used together.------ > sl1 :: (Shape sh, Elt e) => Acc (Array (sh:.Int:.Int) e) -> Exp Int -> Acc (Array (sh:.Int) e)--- > sl1 a n = A.slice a (lift (Any :. n :. All))------ >>> sl1 (use mat) 4--- Vector (Z :. 10) [40,41,42,43,44,45,46,47,48,49]------ >>> let cube = fromList (Z:.3:.4:.5) [0..]--- >>> cube--- Array (Z :. 3 :. 4 :. 5) [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]------ >>> sl1 (use cube) 2--- Matrix (Z :. 3 :. 5)--- [ 10, 11, 12, 13, 14,--- 30, 31, 32, 33, 34,--- 50, 51, 52, 53, 54]----slice :: (Slice slix, Elt e)- => Acc (Array (FullShape slix) e)- -> Exp slix- -> Acc (Array (SliceShape slix) e)-slice = Acc $$ Slice---- Map-like functions--- ---------------------- | Apply the given function element-wise to an array. Denotationally we have:------ > map f [x1, x2, ... xn] = [f x1, f x2, ... f xn]------ >>> let xs = fromList (Z:.10) [0..]--- >>> xs--- Vector (Z :. 10) [0,1,2,3,4,5,6,7,8,9]------ >>> map (+1) (use xs)--- Vector (Z :. 10) [1,2,3,4,5,6,7,8,9,10]----map :: (Shape sh, Elt a, Elt b)- => (Exp a -> Exp b)- -> Acc (Array sh a)- -> Acc (Array sh b)-map = Acc $$ Map---- | Apply the given binary function element-wise to the two arrays. The extent--- of the resulting array is the intersection of the extents of the two source--- arrays.------ >>> let xs = fromList (Z:.3:.5) [0..]--- >>> xs--- Matrix (Z :. 3 :. 5)--- [ 0, 1, 2, 3, 4,--- 5, 6, 7, 8, 9,--- 10,11,12,13,14]------ >>> let ys = fromList (Z:.5:.10) [1..]--- >>> ys--- Matrix (Z :. 5 :. 10)--- [ 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]------ >>> zipWith (+) (use xs) (use ys)--- Matrix (Z :. 3 :. 5)--- [ 1, 3, 5, 7, 9,--- 16,18,20,22,24,--- 31,33,35,37,39]----zipWith :: (Shape sh, Elt a, Elt b, Elt c)- => (Exp a -> Exp b -> Exp c)- -> Acc (Array sh a)- -> Acc (Array sh b)- -> Acc (Array sh c)-zipWith = Acc $$$ ZipWith---- Reductions--- -------------- | Reduction of the innermost dimension of an array of arbitrary rank. The--- first argument needs to be an /associative/ function to enable an efficient--- parallel implementation. The initial element does not need to be an identity--- element of the combination function.------ >>> let mat = fromList (Z:.5:.10) [0..]--- >>> mat--- Matrix (Z :. 5 :. 10)--- [ 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]------ >>> fold (+) 42 (use mat)--- Vector (Z :. 5) [87,187,287,387,487]------ Reductions with non-commutative operators are supported. For example, the--- following computes the maximum segment sum problem along each innermost--- dimension of the array.------ <https://en.wikipedia.org/wiki/Maximum_subarray_problem>------ > maximumSegmentSum--- > :: forall sh e. (Shape sh, Num e, Ord e)--- > => Acc (Array (sh :. Int) e)--- > -> Acc (Array sh e)--- > maximumSegmentSum--- > = map (\v -> let (x,_,_,_) = unlift v :: (Exp e, Exp e, Exp e, Exp e) in x)--- > . fold1 f--- > . map g--- > where--- > f :: (Num a, Ord a) => Exp (a,a,a,a) -> Exp (a,a,a,a) -> Exp (a,a,a,a)--- > f x y =--- > let (mssx, misx, mcsx, tsx) = unlift x--- > (mssy, misy, mcsy, tsy) = unlift y--- > in--- > lift ( mssx `max` (mssy `max` (mcsx+misy))--- > , misx `max` (tsx+misy)--- > , mcsy `max` (mcsx+tsy)--- > , tsx+tsy--- > )--- >--- > g :: (Num a, Ord a) => Exp a -> Exp (a,a,a,a)--- > g x = let y = max x 0--- > in lift (y,y,y,x)------ >>> let vec = fromList (Z:.10) [-2,1,-3,4,-1,2,1,-5,4,0]--- >>> maximumSegmentSum (use vec)--- Scalar Z [6]------ See also 'Data.Array.Accelerate.Data.Fold.Fold', which can be a useful way to--- compute multiple results from a single reduction.----fold :: (Shape sh, Elt a)- => (Exp a -> Exp a -> Exp a)- -> Exp a- -> Acc (Array (sh:.Int) a)- -> Acc (Array sh a)-fold = Acc $$$ Fold---- | Variant of 'fold' that requires the reduced array to be non-empty and--- doesn't need an default value. The first argument needs to be an--- /associative/ function to enable an efficient parallel implementation. The--- initial element does not need to be an identity element.----fold1 :: (Shape sh, Elt a)- => (Exp a -> Exp a -> Exp a)- -> Acc (Array (sh:.Int) a)- -> Acc (Array sh a)-fold1 = Acc $$ Fold1---- | Segmented reduction along the innermost dimension of an array. The segment--- descriptor specifies the lengths of the logical sub-arrays, each of which is--- reduced independently. The innermost dimension must contain at least as many--- elements as required by the segment descriptor (sum thereof).------ >>> let seg = fromList (Z:.4) [1,4,0,3]--- >>> seg--- Vector (Z :. 4) [1,4,0,3]------ >>> let mat = fromList (Z:.5:.10) [0..]--- >>> mat--- Matrix (Z :. 5 :. 10)--- [ 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]------ >>> foldSeg (+) 0 (use mat) (use seg)--- Matrix (Z :. 5 :. 4)--- [ 0, 10, 0, 18,--- 10, 50, 0, 48,--- 20, 90, 0, 78,--- 30, 130, 0, 108,--- 40, 170, 0, 138]----foldSeg- :: (Shape sh, Elt a, Elt i, IsIntegral i)- => (Exp a -> Exp a -> Exp a)- -> Exp a- -> Acc (Array (sh:.Int) a)- -> Acc (Segments i)- -> Acc (Array (sh:.Int) a)-foldSeg = Acc $$$$ FoldSeg---- | Variant of 'foldSeg' that requires /all/ segments of the reduced array to--- be non-empty and doesn't need a default value. The segment descriptor--- specifies the length of each of the logical sub-arrays.----fold1Seg- :: (Shape sh, Elt a, Elt i, IsIntegral i)- => (Exp a -> Exp a -> Exp a)- -> Acc (Array (sh:.Int) a)- -> Acc (Segments i)- -> Acc (Array (sh:.Int) a)-fold1Seg = Acc $$$ Fold1Seg---- Scan functions--- ------------------ | Data.List style left-to-right scan along the innermost dimension of an--- arbitrary rank array. The first argument needs to be an /associative/--- function to enable efficient parallel implementation. The initial value--- (second argument) may be arbitrary.------ >>> scanl (+) 10 (use $ fromList (Z :. 10) [0..])--- Array (Z :. 11) [10,10,11,13,16,20,25,31,38,46,55]------ >>> scanl (+) 0 (use $ fromList (Z :. 4 :. 10) [0..])--- Matrix (Z :. 4 :. 11)--- [ 0, 0, 1, 3, 6, 10, 15, 21, 28, 36, 45,--- 0, 10, 21, 33, 46, 60, 75, 91, 108, 126, 145,--- 0, 20, 41, 63, 86, 110, 135, 161, 188, 216, 245,--- 0, 30, 61, 93, 126, 160, 195, 231, 268, 306, 345]----scanl :: (Shape sh, Elt a)- => (Exp a -> Exp a -> Exp a)- -> Exp a- -> Acc (Array (sh:.Int) a)- -> Acc (Array (sh:.Int) a)-scanl = Acc $$$ Scanl---- | Variant of 'scanl', where the last element (final reduction result) along--- each dimension is returned separately. Denotationally we have:------ > scanl' f e arr = (init res, unit (res!len))--- > where--- > len = shape arr--- > res = scanl f e arr------ >>> let (res,sum) = scanl' (+) 0 (use $ fromList (Z:.10) [0..])--- >>> res--- Vector (Z :. 10) [0,0,1,3,6,10,15,21,28,36]--- >>> sum--- Scalar Z [45]------ >>> let (res,sums) = scanl' (+) 0 (use $ fromList (Z:.4:.10) [0..])--- >>> res--- Matrix (Z :. 4 :. 10)--- [ 0, 0, 1, 3, 6, 10, 15, 21, 28, 36,--- 0, 10, 21, 33, 46, 60, 75, 91, 108, 126,--- 0, 20, 41, 63, 86, 110, 135, 161, 188, 216,--- 0, 30, 61, 93, 126, 160, 195, 231, 268, 306]--- >>> sums--- Vector (Z :. 4) [45,145,245,345]----scanl' :: (Shape sh, Elt a)- => (Exp a -> Exp a -> Exp a)- -> Exp a- -> Acc (Array (sh:.Int) a)- -> Acc (Array (sh:.Int) a, Array sh a)-scanl' = Acc $$$ Scanl'---- | Data.List style left-to-right scan along the innermost dimension without an--- initial value (aka inclusive scan). The array must not be empty. The first--- argument needs to be an /associative/ function. Denotationally, we have:------ > scanl1 f e arr = tail (scanl f e arr)------ >>> let mat = fromList (Z:.4:.10) [0..]--- >>> scanl (+) (use mat)--- Matrix (Z :. 4 :. 10)--- [ 0, 1, 3, 6, 10, 15, 21, 28, 36, 45,--- 10, 21, 33, 46, 60, 75, 91, 108, 126, 145,--- 20, 41, 63, 86, 110, 135, 161, 188, 216, 245,--- 30, 61, 93, 126, 160, 195, 231, 268, 306, 345]----scanl1 :: (Shape sh, Elt a)- => (Exp a -> Exp a -> Exp a)- -> Acc (Array (sh:.Int) a)- -> Acc (Array (sh:.Int) a)-scanl1 = Acc $$ Scanl1---- | Right-to-left variant of 'scanl'.----scanr :: (Shape sh, Elt a)- => (Exp a -> Exp a -> Exp a)- -> Exp a- -> Acc (Array (sh:.Int) a)- -> Acc (Array (sh:.Int) a)-scanr = Acc $$$ Scanr---- | Right-to-left variant of 'scanl''.----scanr' :: (Shape sh, Elt a)- => (Exp a -> Exp a -> Exp a)- -> Exp a- -> Acc (Array (sh:.Int) a)- -> Acc (Array (sh:.Int) a, Array sh a)-scanr' = Acc $$$ Scanr'---- | Right-to-left variant of 'scanl1'.----scanr1 :: (Shape sh, Elt a)- => (Exp a -> Exp a -> Exp a)- -> Acc (Array (sh:.Int) a)- -> Acc (Array (sh:.Int) a)-scanr1 = Acc $$ Scanr1---- Permutations--- ---------------- | Generalised forward permutation operation (array scatter).------ Forward permutation specified by a function mapping indices from the source--- array to indices in the result array. The result array is initialised with--- the given defaults and any further values that are permuted into the result--- array are added to the current value using the given combination function.------ The combination function must be /associative/ and /commutative/. Elements--- that are mapped to the magic value 'ignore' by the permutation function are--- dropped.------ The combination function is given the new value being permuted as its first--- argument, and the current value of the array as its second.------ For example, we can use 'permute' to compute the occurrence count (histogram)--- for an array of values in the range @[0,10)@:------ > histogram :: Acc (Vector Int) -> Acc (Vector Int)--- > histogram xs =--- > let zeros = fill (constant (Z:.10)) 0--- > ones = fill (shape xs) 1--- > in--- > permute (+) zeros (\ix -> index1 (xs!ix)) ones------ >>> let xs = fromList (Z :. 20) [0,0,1,2,1,1,2,4,8,3,4,9,8,3,2,5,5,3,1,2]--- >>> histogram (use xs)--- Vector (Z :. 10) [2,4,4,3,2,2,0,0,2,1]------ As a second example, note that the dimensionality of the source and--- destination arrays can differ. In this way, we can use 'permute' to create an--- identity matrix by overwriting elements along the diagonal:------ > identity :: Num a => Exp Int -> Acc (Array DIM2 a)--- > identity n =--- > let zeros = fill (index2 n n) 0--- > ones = fill (index1 n) 1--- > in--- > permute const zeros (\(unindex1 -> i) -> index2 i i) ones------ >>> identity 5--- Matrix (Z :. 5 :. 5)--- [1,0,0,0,0,--- 0,1,0,0,0,--- 0,0,1,0,0,--- 0,0,0,1,0,--- 0,0,0,0,1]------ [/Note:/]------ Regarding array fusion:------ 1. The 'permute' operation will always be evaluated; it can not be fused--- into a later step.------ 2. Since the index permutation function might not cover all positions in--- the output array (the function is not surjective), the array of default--- values must be evaluated. However, other operations may fuse into this.------ 3. The array of source values can fuse into the permutation operation.------ 4. If the array of default values is only used once, it will be updated--- in-place.----permute- :: (Shape sh, Shape sh', Elt a)- => (Exp a -> Exp a -> Exp a) -- ^ combination function- -> Acc (Array sh' a) -- ^ array of default values- -> (Exp sh -> Exp sh') -- ^ index permutation function- -> Acc (Array sh a) -- ^ array of source values to be permuted- -> Acc (Array sh' a)-permute = Acc $$$$ Permute---- | Generalised backward permutation operation (array gather).------ Backward permutation specified by a function mapping indices in the--- destination array to indices in the source array. Elements of the output--- array are thus generated by reading from the corresponding index in the--- source array.------ For example, backpermute can be used to--- 'Data.Array.Accelerate.Prelude.transpose' a matrix; at every index @Z:.y:.x@--- in the result array, we get the value at that index by reading from the--- source array at index @Z:.x:.y@:------ > swap :: Exp DIM2 -> Exp DIM2--- > swap = lift1 $ \(Z:.y:.x) -> Z:.x:.y------ >>> let mat = fromList (Z:.5:.10) [0..]--- >>> mat--- Matrix (Z :. 5 :. 10)--- [ 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]------ >>> let mat' = use mat--- >>> backpermute (swap (shape mat')) swap mat'--- Matrix (Z :. 10 :. 5)--- [ 0, 10, 20, 30, 40,--- 1, 11, 21, 31, 41,--- 2, 12, 22, 32, 42,--- 3, 13, 23, 33, 43,--- 4, 14, 24, 34, 44,--- 5, 15, 25, 35, 45,--- 6, 16, 26, 36, 46,--- 7, 17, 27, 37, 47,--- 8, 18, 28, 38, 48,--- 9, 19, 29, 39, 49]----backpermute- :: (Shape sh, Shape sh', Elt a)- => Exp sh' -- ^ shape of the result array- -> (Exp sh' -> Exp sh) -- ^ index permutation function- -> Acc (Array sh a) -- ^ source array- -> Acc (Array sh' a)-backpermute = Acc $$$ Backpermute----- Stencil operations--- ---------------------- Common stencil types------- DIM1 stencil type-type Stencil3 a = (Exp a, Exp a, Exp a)-type Stencil5 a = (Exp a, Exp a, Exp a, Exp a, Exp a)-type Stencil7 a = (Exp a, Exp a, Exp a, Exp a, Exp a, Exp a, Exp a)-type Stencil9 a = (Exp a, Exp a, Exp a, Exp a, Exp a, Exp a, Exp a, Exp a, Exp a)---- DIM2 stencil type-type Stencil3x3 a = (Stencil3 a, Stencil3 a, Stencil3 a)-type Stencil5x3 a = (Stencil5 a, Stencil5 a, Stencil5 a)-type Stencil3x5 a = (Stencil3 a, Stencil3 a, Stencil3 a, Stencil3 a, Stencil3 a)-type Stencil5x5 a = (Stencil5 a, Stencil5 a, Stencil5 a, Stencil5 a, Stencil5 a)---- DIM3 stencil type-type Stencil3x3x3 a = (Stencil3x3 a, Stencil3x3 a, Stencil3x3 a)-type Stencil5x3x3 a = (Stencil5x3 a, Stencil5x3 a, Stencil5x3 a)-type Stencil3x5x3 a = (Stencil3x5 a, Stencil3x5 a, Stencil3x5 a)-type Stencil3x3x5 a = (Stencil3x3 a, Stencil3x3 a, Stencil3x3 a, Stencil3x3 a, Stencil3x3 a)-type Stencil5x5x3 a = (Stencil5x5 a, Stencil5x5 a, Stencil5x5 a)-type Stencil5x3x5 a = (Stencil5x3 a, Stencil5x3 a, Stencil5x3 a, Stencil5x3 a, Stencil5x3 a)-type Stencil3x5x5 a = (Stencil3x5 a, Stencil3x5 a, Stencil3x5 a, Stencil3x5 a, Stencil3x5 a)-type Stencil5x5x5 a = (Stencil5x5 a, Stencil5x5 a, Stencil5x5 a, Stencil5x5 a, Stencil5x5 a)----- | Map a stencil over an array. In contrast to 'map', the domain of a stencil--- function is an entire /neighbourhood/ of each array element. Neighbourhoods--- are sub-arrays centred around a focal point. They are not necessarily--- rectangular, but they are symmetric and have an extent of at least three--- along each axis. Due to the symmetry requirement the extent is necessarily--- odd. The focal point is the array position that is determined by the stencil.------ For those array positions where the neighbourhood extends past the boundaries--- of the source array, a boundary condition determines the contents of the--- out-of-bounds neighbourhood positions.------ Stencil neighbourhoods are specified via nested tuples, where the nesting--- depth is equal to the dimensionality of the array. For example, a 3x1 stencil--- for a one-dimensional array:------ > s31 :: Stencil3 a -> Exp a--- > s31 (l,c,r) = ...------ ...where @c@ is the focal point of the stencil, and @l@ and @r@ represent the--- elements to the left and right of the focal point, respectively. Similarly,--- a 3x3 stencil for a two-dimensional array:------ > s33 :: Stencil3x3 a -> Exp a--- > s33 ((_,t,_)--- > ,(l,c,r)--- > ,(_,b,_)) = ...------ ...where @c@ is again the focal point and @t@, @b@, @l@ and @r@ are the--- elements to the top, bottom, left, and right of the focal point, respectively--- (the diagonal elements have been elided).------ For example, the following computes a 5x5--- <https://en.wikipedia.org/wiki/Gaussian_blur Gaussian blur> as a separable--- 2-pass operation.------ > type Stencil5x1 a = (Stencil3 a, Stencil5 a, Stencil3 a)--- > type Stencil1x5 a = (Stencil3 a, Stencil3 a, Stencil3 a, Stencil3 a, Stencil3 a)--- >--- > convolve5x1 :: Num a => [Exp a] -> Stencil5x1 a -> Exp a--- > convolve5x1 kernel (_, (a,b,c,d,e), _)--- > = Prelude.sum $ Prelude.zipWith (*) kernel [a,b,c,d,e]--- >--- > convolve1x5 :: Num a => [Exp a] -> Stencil1x5 a -> Exp a--- > convolve1x5 kernel ((_,a,_), (_,b,_), (_,c,_), (_,d,_), (_,e,_))--- > = Prelude.sum $ Prelude.zipWith (*) kernel [a,b,c,d,e]--- >--- > gaussian = [0.06136,0.24477,0.38774,0.24477,0.06136]--- >--- > blur :: Num a => Acc (Array DIM2 a) -> Acc (Array DIM2 a)--- > blur = stencil (convolve5x1 gaussian) clamp--- > . stencil (convolve1x5 gaussian) clamp----stencil- :: (Stencil sh a stencil, Elt b)- => (stencil -> Exp b) -- ^ stencil function- -> Boundary (Array sh a) -- ^ boundary condition- -> Acc (Array sh a) -- ^ source array- -> Acc (Array sh b) -- ^ destination array-stencil f (Boundary b) a = Acc $ Stencil f b a---- | Map a binary stencil of an array. The extent of the resulting array is the--- intersection of the extents of the two source arrays. This is the stencil--- equivalent of 'zipWith'.----stencil2- :: (Stencil sh a stencil1, Stencil sh b stencil2, Elt c)- => (stencil1 -> stencil2 -> Exp c) -- ^ binary stencil function- -> Boundary (Array sh a) -- ^ boundary condition #1- -> Acc (Array sh a) -- ^ source array #1- -> Boundary (Array sh b) -- ^ boundary condition #2- -> Acc (Array sh b) -- ^ source array #2- -> Acc (Array sh c) -- ^ destination array-stencil2 f (Boundary b1) a1 (Boundary b2) a2 = Acc $ Stencil2 f b1 a1 b2 a2---- | Boundary condition where elements of the stencil which would be--- out-of-bounds are instead clamped to the edges of the array.------ In the following 3x3 stencil, the out-of-bounds element @b@ will instead--- return the value at position @c@:------ > +------------+--- > |a |--- > b|cd |--- > |e |--- > +------------+----clamp :: Boundary (Array sh e)-clamp = Boundary Clamp---- | Stencil boundary condition where coordinates beyond the array extent are--- instead mirrored------ In the following 5x3 stencil, the out-of-bounds element @c@ will instead--- return the value at position @d@, and similarly the element at @b@ will--- return the value at @e@:------ > +------------+--- > |a |--- > bc|def |--- > |g |--- > +------------+----mirror :: Boundary (Array sh e)-mirror = Boundary Mirror---- | Stencil boundary condition where coordinates beyond the array extent--- instead wrap around the array.------ In the following 3x3 stencil, the out of bounds elements will be read as in--- the pattern on the right.------ > a bc--- > +------------+ +------------+--- > d|ef | |ef d|--- > g|hi | -> |hi g|--- > | | |bc a|--- > +------------+ +------------+----wrap :: Boundary (Array sh e)-wrap = Boundary Wrap---- | Stencil boundary condition where the given function is applied to any--- outlying coordinates.----function- :: (Shape sh, Elt e)- => (Exp sh -> Exp e)- -> Boundary (Array sh e)-function = Boundary . Function---{----- Sequence operations--- ---------------------- Common sequence types-----streamIn :: Arrays a- => [a]- -> Seq [a]-streamIn arrs = Seq (StreamIn arrs)---- | Convert the given array to a sequence by dividing the array up into subarrays.--- The first argument captures how to the division should be performed. The--- presence of `All` in the division descriptor indicates that elements in the--- corresponding dimension should be retained in the subarrays, whereas `Split`--- indicates that the input array should divided along this dimension.----toSeq :: (Division slsix, Elt a)- => slsix- -> Acc (Array (FullShape (DivisionSlice slsix)) a)- -> Seq [Array (SliceShape (DivisionSlice slsix)) a]-toSeq spec acc = Seq (ToSeq spec acc)---- | Apply the given array function element-wise to the given sequence.----mapSeq :: (Arrays a, Arrays b)- => (Acc a -> Acc b)- -> Seq [a]- -> Seq [b]-mapSeq = Seq $$ MapSeq---- | Apply the given binary function element-wise to the two sequences. The length of the resulting--- sequence is the minumum of the lengths of the two source sequences.----zipWithSeq :: (Arrays a, Arrays b, Arrays c)- => (Acc a -> Acc b -> Acc c)- -> Seq [a]- -> Seq [b]- -> Seq [c]-zipWithSeq = Seq $$$ ZipWithSeq---- | scanSeq (+) a0 x seq. Scan a sequence x by combining each--- element using the given binary operation (+). (+) must be--- associative:------ Forall a b c. (a + b) + c = a + (b + c),------ and a0 must be the identity element for (+):------ Forall a. a0 + a = a = a + a0.----scanSeq :: Elt a- => (Exp a -> Exp a -> Exp a)- -> Exp a- -> Seq [Scalar a]- -> Seq [Scalar a]-scanSeq = Seq $$$ ScanSeq---- | foldSeq (+) a0 x seq. Fold a sequence x by combining each--- element using the given binary operation (+). (+) must be--- associative:------ Forall a b c. (a + b) + c = a + (b + c),------ and a0 must be the identity element for (+):------ Forall a. a0 + a = a = a + a0.----foldSeq :: Elt a- => (Exp a -> Exp a -> Exp a)- -> Exp a- -> Seq [Scalar a]- -> Seq (Scalar a)-foldSeq = Seq $$$ FoldSeq---- | foldSeqFlatten f a0 x seq. A specialized version of--- FoldSeqAct where reduction with the companion operator--- corresponds to flattening. f must be semi-associative, with vecotor--- append (++) as the companion operator:------ Forall b sh1 a1 sh2 a2.--- f (f b sh1 a1) sh2 a2 = f b (sh1 ++ sh2) (a1 ++ a2).------ It is common to ignore the shape vectors, yielding the usual--- semi-associativity law:------ f b a _ = b + a,------ for some (+) satisfying:------ Forall b a1 a2. (b + a1) + a2 = b + (a1 ++ a2).----foldSeqFlatten :: (Arrays a, Shape jx, Elt b)- => (Acc a -> Acc (Vector jx) -> Acc (Vector b) -> Acc a)- -> Acc a- -> Seq [Array jx b]- -> Seq a-foldSeqFlatten = Seq $$$ FoldSeqFlatten--collect :: Arrays arrs => Seq arrs -> Acc arrs-collect = Acc . Collect---}---- Foreign function calling--- ---------------------------- | Call a foreign array function.------ The form the first argument takes is dependent on the backend being targeted.--- Note that the foreign function only has access to the input array(s) passed--- in as its argument.------ In case the operation is being executed on a backend which does not support--- this foreign implementation, the fallback implementation is used instead,--- which itself could be a foreign implementation for a (presumably) different--- backend, or an implementation in pure Accelerate. In this way, multiple--- foreign implementations can be supplied, and will be tested for suitability--- against the target backend in sequence.------ For an example see the <https://hackage.haskell.org/package/accelerate-fft accelerate-fft> package.----foreignAcc- :: (Arrays as, Arrays bs, Foreign asm)- => asm (as -> bs)- -> (Acc as -> Acc bs)- -> Acc as- -> Acc bs-foreignAcc = Acc $$$ Aforeign---- | Call a foreign scalar expression.------ The form of the first argument is dependent on the backend being targeted.--- Note that the foreign function only has access to the input element(s) passed--- in as its first argument.------ As with 'foreignAcc', the fallback implementation itself may be a (sequence--- of) foreign implementation(s) for a different backend(s), or implemented--- purely in Accelerate.----foreignExp- :: (Elt x, Elt y, Foreign asm)- => asm (x -> y)- -> (Exp x -> Exp y)- -> Exp x- -> Exp y-foreignExp = Exp $$$ Foreign----- Composition of array computations--- ------------------------------------- | Pipelining of two array computations. The first argument will be fully--- evaluated before being passed to the second computation. This can be used to--- prevent the argument being fused into the function, for example.------ Denotationally, we have------ > (acc1 >-> acc2) arrs = let tmp = acc1 arrs--- > in tmp `seq` acc2 tmp------ For an example use of this operation see the 'Data.Array.Accelerate.compute'--- function.----infixl 1 >->-(>->) :: (Arrays a, Arrays b, Arrays c) => (Acc a -> Acc b) -> (Acc b -> Acc c) -> (Acc a -> Acc c)-(>->) = Acc $$$ Pipe----- Flow control constructs--- --------------------------- | An array-level if-then-else construct.------ Enabling the @RebindableSyntax@ extension will allow you to use the standard--- if-then-else syntax instead.----acond :: Arrays a- => Exp Bool -- ^ if-condition- -> Acc a -- ^ then-array- -> Acc a -- ^ else-array- -> Acc a-acond = Acc $$$ Acond---- | An array-level 'while' construct. Continue to apply the given function,--- starting with the initial value, until the test function evaluates to--- 'False'.----awhile :: Arrays a- => (Acc a -> Acc (Scalar Bool)) -- ^ keep evaluating while this returns 'True'- -> (Acc a -> Acc a) -- ^ function to apply- -> Acc a -- ^ initial value- -> Acc a-awhile = Acc $$$ Awhile----- Shapes and indices--- ---------------------- | Get the innermost dimension of a shape.------ The innermost dimension (right-most component of the shape) is the index of--- the array which varies most rapidly, and corresponds to elements of the array--- which are adjacent in memory.------ Another way to think of this is, for example when writing nested loops over--- an array in C, this index corresponds to the index iterated over by the--- innermost nested loop.----indexHead :: (Slice sh, Elt a) => Exp (sh :. a) -> Exp a-indexHead = Exp . IndexHead---- | Get all but the innermost element of a shape----indexTail :: (Slice sh, Elt a) => Exp (sh :. a) -> Exp sh-indexTail = Exp . IndexTail---- | Map a multi-dimensional index into a linear, row-major representation of an--- array.----toIndex- :: Shape sh- => Exp sh -- ^ extent of the array- -> Exp sh -- ^ index to remap- -> Exp Int-toIndex = Exp $$ ToIndex---- | Inverse of 'toIndex'----fromIndex :: Shape sh => Exp sh -> Exp Int -> Exp sh-fromIndex = Exp $$ FromIndex---- | Intersection of two shapes----intersect :: Shape sh => Exp sh -> Exp sh -> Exp sh-intersect = Exp $$ Intersect---- | Union of two shapes----union :: Shape sh => Exp sh -> Exp sh -> Exp sh-union = Exp $$ Union----- Flow-control--- ---------------- | A scalar-level if-then-else construct.------ Enabling the @RebindableSyntax@ extension will allow you to use the standard--- if-then-else syntax instead.----cond :: Elt t- => Exp Bool -- ^ condition- -> Exp t -- ^ then-expression- -> Exp t -- ^ else-expression- -> Exp t-cond = Exp $$$ Cond---- | While construct. Continue to apply the given function, starting with the--- initial value, until the test function evaluates to 'False'.----while :: Elt e- => (Exp e -> Exp Bool) -- ^ keep evaluating while this returns 'True'- -> (Exp e -> Exp e) -- ^ function to apply- -> Exp e -- ^ initial value- -> Exp e-while = Exp $$$ While----- Array operations with a scalar result--- ----------------------------------------- | Multidimensional array indexing. Extract the value from an array at the--- specified zero-based index.------ >>> let mat = fromList (Z:.5:.10) [0..]--- >>> mat--- Matrix (Z :. 5 :. 10)--- [ 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]------ >>> mat ! Z:.1:.2--- 12----infixl 9 !-(!) :: (Shape sh, Elt e) => Acc (Array sh e) -> Exp sh -> Exp e-(!) = Exp $$ Index---- | Extract the value from an array at the specified linear index.--- Multidimensional arrays in Accelerate are stored in row-major order with--- zero-based indexing.------ >>> let mat = fromList (Z:.5:.10) [0..]--- >>> mat--- Matrix (Z :. 5 :. 10)--- [ 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]------ >>> mat !! 12--- 12----infixl 9 !!-(!!) :: (Shape sh, Elt e) => Acc (Array sh e) -> Exp Int -> Exp e-(!!) = Exp $$ LinearIndex---- | Extract the shape (extent) of an array.----shape :: (Shape sh, Elt e) => Acc (Array sh e) -> Exp sh-shape = Exp . Shape---- | The number of elements in the array----size :: (Shape sh, Elt e) => Acc (Array sh e) -> Exp Int-size = shapeSize . shape---- | The number of elements that would be held by an array of the given shape.----shapeSize :: Shape sh => Exp sh -> Exp Int-shapeSize = Exp . ShapeSize----- Numeric functions--- --------------------- | 'subtract' is the same as @'flip' ('-')@.----subtract :: Num a => Exp a -> Exp a -> Exp a-subtract x y = y - x---- | Determine if a number is even----even :: Integral a => Exp a -> Exp Bool-even n = n `rem` 2 == 0---- | Determine if a number is odd----odd :: Integral a => Exp a -> Exp Bool-odd n = n `rem` 2 /= 0---- | @'gcd' x y@ is the non-negative factor of both @x@ and @y@ of which every--- common factor of both @x@ and @y@ is also a factor; for example:------ >>> gcd 4 2 = 2--- >>> gcd (-4) 6 = 2--- >>> gcd 0 4 = 4--- >>> gcd 0 0 = 0------ That is, the common divisor that is \"greatest\" in the divisibility--- preordering.----gcd :: Integral a => Exp a -> Exp a -> Exp a-gcd x y = gcd' (abs x) (abs y)- where- gcd' :: Integral a => Exp a -> Exp a -> Exp a- gcd' u v =- let (r,_) = untup2- $ while (\(untup2 -> (_,b)) -> b /= 0)- (\(untup2 -> (a,b)) -> tup2 (b, a `rem` b))- (tup2 (u,v))- in r----- | @'lcm' x y@ is the smallest positive integer that both @x@ and @y@ divide.----lcm :: Integral a => Exp a -> Exp a -> Exp a-lcm x y- = cond (x == 0 || y == 0) 0- $ abs ((x `quot` (gcd x y)) * y)----- | Raise a number to a non-negative integral power----infixr 8 ^-(^) :: forall a b. (Num a, Integral b) => Exp a -> Exp b -> Exp a-x0 ^ y0 = cond (y0 <= 0) 1 (f x0 y0)- where- f :: Exp a -> Exp b -> Exp a- f x y =- let (x',y') = untup2- $ while (\(untup2 -> (_,v)) -> even v)- (\(untup2 -> (u,v)) -> tup2 (u * u, v `quot` 2))- (tup2 (x, y))- in- cond (y' == 1) x' (g (x'*x') ((y'-1) `quot` 2) x')-- g :: Exp a -> Exp b -> Exp a -> Exp a- g x y z =- let (x',_,z') = untup3- $ while (\(untup3 -> (_,v,_)) -> v /= 1)- (\(untup3 -> (u,v,w)) ->- cond (even v) (tup3 (u*u, v `quot` 2, w))- (tup3 (u*u, (v-1) `quot` 2, w*u)))- (tup3 (x,y,z))- in- x' * z'---- | Raise a number to an integral power----infixr 8 ^^-(^^) :: (Fractional a, Integral b) => Exp a -> Exp b -> Exp a-x ^^ n- = cond (n >= 0)- {- then -} (x ^ n)- {- else -} (recip (x ^ (negate n)))----- Conversions--- --------------- |Convert a character to an 'Int'.----ord :: Exp Char -> Exp Int-ord = mkOrd---- |Convert an 'Int' into a character.----chr :: Exp Int -> Exp Char-chr = mkChr---- |Convert a Boolean value to an 'Int', where 'False' turns into '0' and 'True'--- into '1'.----boolToInt :: Exp Bool -> Exp Int-boolToInt = mkBoolToInt---- |Reinterpret a value as another type. The two representations must have the--- same bit size.----bitcast :: (Elt a, Elt b, IsScalar a, IsScalar b, BitSizeEq a b) => Exp a -> Exp b-bitcast = mkBitcast----- Constants--- ------------- |Magic value identifying elements that are ignored in a forward permutation.----ignore :: Shape sh => Exp sh-ignore = constant Sugar.ignore-
− Data/Array/Accelerate/Lifetime.hs
@@ -1,161 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE UnboxedTuples #-}-{-# OPTIONS_HADDOCK hide #-}--- |--- Module : Data.Array.Accelerate.Lifetime--- Copyright : [2015..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell, Robert Clifton-Everest--- License : BSD3------ Maintainer : Robert Clifton-Everest <robertce@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Lifetime (-- Lifetime(..),- newLifetime, withLifetime, touchLifetime,- addFinalizer, finalize, mkWeak, mkWeakPtr,-- unsafeGetValue,--) where--import Data.Function ( on )-import Data.IORef ( mkWeakIORef, atomicModifyIORef' )-import Prelude--import GHC.Base ( touch#, IO(..))-import GHC.IORef ( IORef(.. ), newIORef )-import GHC.Prim ( mkWeak# )-import GHC.STRef ( STRef(..) )-import GHC.Weak ( Weak(..) )----- | A lifetime represents a value with attached finalizers. This is similar to--- the functionality provided by "System.Mem.Weak", but has the following--- stronger properties:------ * Unless explicitly forced, finalizers will not fire until after the--- 'Lifetime' has become unreachable, where \"reachability\" is the same as--- defined in "System.Mem.Weak". That is to say, there is no issue with--- creating a 'Lifetime' for a non-primitve type and finalizers firing while--- an object is still reachable.------ * Finalizers are fired sequentially in reverse of the order in which they--- were attached.------ * As the finalizers are attached to the 'Lifetime' and not the underlying--- value, there is no danger in storing it UNPACKED as part of another--- structure.----type LTF = IORef [IO ()]-data Lifetime a = Lifetime {-# UNPACK #-} !LTF- {-# UNPACK #-} !(Weak LTF)- {- LAZY -} a--instance Eq a => Eq (Lifetime a) where- (==) = (==) `on` unsafeGetValue---- | Construct a new 'Lifetime' from the given value.----{-# INLINE newLifetime #-}-newLifetime :: a -> IO (Lifetime a)-newLifetime a = do- ref <- newIORef []- weak <- mkWeakIORef ref (finalizer ref)- return $! Lifetime ref weak a---- | This provides a way of looking at the value inside a 'Lifetime'. The--- supplied function is executed immediately and the 'Lifetime' kept alive--- throughout its execution. It is important to not let the value /leak/ outside--- the function, either by returning it or by lazy IO.----{-# INLINE withLifetime #-}-withLifetime :: Lifetime a -> (a -> IO b) -> IO b-withLifetime (Lifetime ref _ a) f = do- r <- f a- touchIORef ref- return r---- | Ensure that the lifetime is alive at the given place in a sequence of IO--- actions. Does not force the payload.----{-# INLINE touchLifetime #-}-touchLifetime :: Lifetime a -> IO ()-touchLifetime (Lifetime ref _ _) = touchIORef ref---- | Attaches a finalizer to a 'Lifetime'. Like in "System.Mem.Weak", there is--- no guarantee that the finalizers will eventually run. If they do run,--- they will be executed in the order in which they were supplied.----addFinalizer :: Lifetime a -> IO () -> IO ()-addFinalizer (Lifetime ref _ _) f =- atomicModifyIORef' ref (\fs -> (f:fs,()))---- | Causes any finalizers associated with the given lifetime to be run--- immediately on the calling thread.------ Because the finalizer is run on the calling thread. Care should be taken to--- ensure that the it does not try to acquire any locks the calling thread might--- already possess. This can result in deadlock and is in contrast to calling--- 'System.Mem.Weak.finalize' on 'System.Mem.Weak.Weak'.----finalize :: Lifetime a -> IO ()-finalize (Lifetime ref _ _) = finalizer ref---- | Create a weak pointer from a 'Lifetime' to the supplied value.------ Because weak pointers have their own concept of finalizers, it is important--- to note these behaviours:------ * Calling 'System.Mem.Weak.finalize' causes the finalizers attached to the--- lifetime to be scheduled, and run in the correct order, but does not--- guarantee they will execute on the calling thread.------ * If 'deRefWeak' returns Nothing, there is no guarantee that the finalizers--- have already run.----mkWeak :: Lifetime k -> v -> IO (Weak v)-mkWeak (Lifetime ref@(IORef (STRef r#)) _ _) v = go (finalizer ref)- where-#if __GLASGOW_HASKELL__ >= 800- go (IO f) = -- GHC-8.x-#else- go f = -- GHC-7.x-#endif- IO $ \s -> case mkWeak# r# v f s of- (# s', w# #) -> (# s', Weak w# #)---- A specialised version of 'mkWeak' where the key and value are the same--- 'Lifetime'.------ > mkWeakPtr key = mkWeak key key----mkWeakPtr :: Lifetime a -> IO (Weak (Lifetime a))-mkWeakPtr l = mkWeak l l---- | Retrieve the value from a lifetime. This is unsafe because, unless the--- 'Lifetime' is still reachable, the finalizers may fire, potentially--- invalidating the value.----{-# INLINE unsafeGetValue #-}-unsafeGetValue :: Lifetime a -> a-unsafeGetValue (Lifetime _ _ a) = a---- The actual finalizer for 'Lifetime's.----finalizer :: IORef [IO ()] -> IO ()-finalizer ref = do- fins <- atomicModifyIORef' ref ([],)- sequence_ fins---- Touch an 'IORef', ensuring that it is alive at this point in a sequence of IO--- actions.----{-# INLINE touchIORef #-}-touchIORef :: IORef a -> IO ()-touchIORef r = IO $ \s -> case touch# r s of s' -> (# s', () #)-
− Data/Array/Accelerate/Lift.hs
@@ -1,747 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}-#if __GLASGOW_HASKELL__ <= 708-{-# LANGUAGE OverlappingInstances #-}-{-# OPTIONS_GHC -fno-warn-unrecognised-pragmas #-}-#endif--- |--- Module : Data.Array.Accelerate.Lift--- Copyright : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)------ Lifting and lowering surface expressions through constructors.-----module Data.Array.Accelerate.Lift (-- -- * Lifting and unlifting- Lift(..), Unlift(..),-- lift1, lift2, lift3,- ilift1, ilift2, ilift3,--) where--import Data.Array.Accelerate.Array.Sugar-import Data.Array.Accelerate.Smart-import Data.Array.Accelerate.Type----- |Lift a unary function into 'Exp'.----lift1 :: (Unlift Exp a, Lift Exp b)- => (a -> b)- -> Exp (Plain a)- -> Exp (Plain b)-lift1 f = lift . f . unlift---- |Lift a binary function into 'Exp'.----lift2 :: (Unlift Exp a, Unlift Exp b, Lift Exp c)- => (a -> b -> c)- -> Exp (Plain a)- -> Exp (Plain b)- -> Exp (Plain c)-lift2 f x y = lift $ f (unlift x) (unlift y)---- |Lift a ternary function into 'Exp'.----lift3 :: (Unlift Exp a, Unlift Exp b, Unlift Exp c, Lift Exp d)- => (a -> b -> c -> d)- -> Exp (Plain a)- -> Exp (Plain b)- -> Exp (Plain c)- -> Exp (Plain d)-lift3 f x y z = lift $ f (unlift x) (unlift y) (unlift z)---- |Lift a unary function to a computation over rank-1 indices.----ilift1 :: (Exp Int -> Exp Int) -> Exp DIM1 -> Exp DIM1-ilift1 f = lift1 (\(Z:.i) -> Z :. f i)---- |Lift a binary function to a computation over rank-1 indices.----ilift2 :: (Exp Int -> Exp Int -> Exp Int) -> Exp DIM1 -> Exp DIM1 -> Exp DIM1-ilift2 f = lift2 (\(Z:.i) (Z:.j) -> Z :. f i j)---- |Lift a ternary function to a computation over rank-1 indices.----ilift3 :: (Exp Int -> Exp Int -> Exp Int -> Exp Int) -> Exp DIM1 -> Exp DIM1 -> Exp DIM1 -> Exp DIM1-ilift3 f = lift3 (\(Z:.i) (Z:.j) (Z:.k) -> Z :. f i j k)------ | The class of types @e@ which can be lifted into @c@.-class Lift c e where- -- | An associated-type (i.e. a type-level function) that strips all- -- instances of surface type constructors @c@ from the input type @e@.- --- -- For example, the tuple types @(Exp Int, Int)@ and @(Int, Exp- -- Int)@ have the same \"Plain\" representation. That is, the- -- following type equality holds:- --- -- @Plain (Exp Int, Int) ~ (Int,Int) ~ Plain (Int, Exp Int)@- type Plain e-- -- | Lift the given value into a surface type 'c' --- either 'Exp' for scalar- -- expressions or 'Acc' for array computations. The value may already contain- -- subexpressions in 'c'.- --- lift :: e -> c (Plain e)---- | A limited subset of types which can be lifted, can also be unlifted.-class Lift c e => Unlift c e where-- -- | Unlift the outermost constructor through the surface type. This is only- -- possible if the constructor is fully determined by its type - i.e., it is a- -- singleton.- --- unlift :: c (Plain e) -> e----- identity instances--instance Lift Exp (Exp e) where- type Plain (Exp e) = e- lift = id--instance Unlift Exp (Exp e) where- unlift = id--instance Lift Acc (Acc a) where- type Plain (Acc a) = a- lift = id--instance Unlift Acc (Acc a) where- unlift = id---- instance Lift Seq (Seq a) where--- type Plain (Seq a) = a--- lift = id---- instance Unlift Seq (Seq a) where--- unlift = id----- instances for indices--instance Lift Exp () where- type Plain () = ()- lift _ = Exp $ Tuple NilTup--instance Unlift Exp () where- unlift _ = ()--instance Lift Exp Z where- type Plain Z = Z- lift _ = Exp $ IndexNil--instance Unlift Exp Z where- unlift _ = Z--instance (Slice (Plain ix), Lift Exp ix) => Lift Exp (ix :. Int) where- type Plain (ix :. Int) = Plain ix :. Int- lift (ix:.i) = Exp $ IndexCons (lift ix) (Exp $ Const i)--instance (Slice (Plain ix), Lift Exp ix) => Lift Exp (ix :. All) where- type Plain (ix :. All) = Plain ix :. All- lift (ix:.i) = Exp $ IndexCons (lift ix) (Exp $ Const i)--instance (Elt e, Slice (Plain ix), Lift Exp ix) => Lift Exp (ix :. Exp e) where- type Plain (ix :. Exp e) = Plain ix :. e- lift (ix:.i) = Exp $ IndexCons (lift ix) i--instance {-# OVERLAPPABLE #-} (Elt e, Slice (Plain ix), Unlift Exp ix) => Unlift Exp (ix :. Exp e) where- unlift e = unlift (Exp $ IndexTail e) :. Exp (IndexHead e)--instance {-# OVERLAPPABLE #-} (Elt e, Slice ix) => Unlift Exp (Exp ix :. Exp e) where- unlift e = (Exp $ IndexTail e) :. Exp (IndexHead e)--instance Shape sh => Lift Exp (Any sh) where- type Plain (Any sh) = Any sh- lift Any = Exp $ IndexAny---- instances for numeric types--instance Lift Exp Int where- type Plain Int = Int- lift = Exp . Const--instance Lift Exp Int8 where- type Plain Int8 = Int8- lift = Exp . Const--instance Lift Exp Int16 where- type Plain Int16 = Int16- lift = Exp . Const--instance Lift Exp Int32 where- type Plain Int32 = Int32- lift = Exp . Const--instance Lift Exp Int64 where- type Plain Int64 = Int64- lift = Exp . Const--instance Lift Exp Word where- type Plain Word = Word- lift = Exp . Const--instance Lift Exp Word8 where- type Plain Word8 = Word8- lift = Exp . Const--instance Lift Exp Word16 where- type Plain Word16 = Word16- lift = Exp . Const--instance Lift Exp Word32 where- type Plain Word32 = Word32- lift = Exp . Const--instance Lift Exp Word64 where- type Plain Word64 = Word64- lift = Exp . Const--instance Lift Exp CShort where- type Plain CShort = CShort- lift = Exp . Const--instance Lift Exp CUShort where- type Plain CUShort = CUShort- lift = Exp . Const--instance Lift Exp CInt where- type Plain CInt = CInt- lift = Exp . Const--instance Lift Exp CUInt where- type Plain CUInt = CUInt- lift = Exp . Const--instance Lift Exp CLong where- type Plain CLong = CLong- lift = Exp . Const--instance Lift Exp CULong where- type Plain CULong = CULong- lift = Exp . Const--instance Lift Exp CLLong where- type Plain CLLong = CLLong- lift = Exp . Const--instance Lift Exp CULLong where- type Plain CULLong = CULLong- lift = Exp . Const--instance Lift Exp Float where- type Plain Float = Float- lift = Exp . Const--instance Lift Exp Double where- type Plain Double = Double- lift = Exp . Const--instance Lift Exp CFloat where- type Plain CFloat = CFloat- lift = Exp . Const--instance Lift Exp CDouble where- type Plain CDouble = CDouble- lift = Exp . Const--instance Lift Exp Bool where- type Plain Bool = Bool- lift = Exp . Const--instance Lift Exp Char where- type Plain Char = Char- lift = Exp . Const--instance Lift Exp CChar where- type Plain CChar = CChar- lift = Exp . Const--instance Lift Exp CSChar where- type Plain CSChar = CSChar- lift = Exp . Const--instance Lift Exp CUChar where- type Plain CUChar = CUChar- lift = Exp . Const---- Instances for tuples--instance (Lift Exp a, Lift Exp b, Elt (Plain a), Elt (Plain b)) => Lift Exp (a, b) where- type Plain (a, b) = (Plain a, Plain b)- lift (a, b) = tup2 (lift a, lift b)--instance (Elt a, Elt b) => Unlift Exp (Exp a, Exp b) where- unlift = untup2--instance (Lift Exp a, Lift Exp b, Lift Exp c,- Elt (Plain a), Elt (Plain b), Elt (Plain c))- => Lift Exp (a, b, c) where- type Plain (a, b, c) = (Plain a, Plain b, Plain c)- lift (a, b, c) = tup3 (lift a, lift b, lift c)--instance (Elt a, Elt b, Elt c) => Unlift Exp (Exp a, Exp b, Exp c) where- unlift = untup3--instance (Lift Exp a, Lift Exp b, Lift Exp c, Lift Exp d,- Elt (Plain a), Elt (Plain b), Elt (Plain c), Elt (Plain d))- => Lift Exp (a, b, c, d) where- type Plain (a, b, c, d) = (Plain a, Plain b, Plain c, Plain d)- lift (a, b, c, d) = tup4 (lift a, lift b, lift c, lift d)--instance (Elt a, Elt b, Elt c, Elt d) => Unlift Exp (Exp a, Exp b, Exp c, Exp d) where- unlift = untup4--instance (Lift Exp a, Lift Exp b, Lift Exp c, Lift Exp d, Lift Exp e,- Elt (Plain a), Elt (Plain b), Elt (Plain c), Elt (Plain d), Elt (Plain e))- => Lift Exp (a, b, c, d, e) where- type Plain (a, b, c, d, e) = (Plain a, Plain b, Plain c, Plain d, Plain e)- lift (a, b, c, d, e) = tup5 (lift a, lift b, lift c, lift d, lift e)--instance (Elt a, Elt b, Elt c, Elt d, Elt e)- => Unlift Exp (Exp a, Exp b, Exp c, Exp d, Exp e) where- unlift = untup5--instance (Lift Exp a, Lift Exp b, Lift Exp c, Lift Exp d, Lift Exp e, Lift Exp f,- Elt (Plain a), Elt (Plain b), Elt (Plain c), Elt (Plain d), Elt (Plain e), Elt (Plain f))- => Lift Exp (a, b, c, d, e, f) where- type Plain (a, b, c, d, e, f) = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f)- lift (a, b, c, d, e, f) = tup6 (lift a, lift b, lift c, lift d, lift e, lift f)--instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f)- => Unlift Exp (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f) where- unlift = untup6--instance (Lift Exp a, Lift Exp b, Lift Exp c, Lift Exp d, Lift Exp e, Lift Exp f, Lift Exp g,- Elt (Plain a), Elt (Plain b), Elt (Plain c), Elt (Plain d), Elt (Plain e), Elt (Plain f),- Elt (Plain g))- => Lift Exp (a, b, c, d, e, f, g) where- type Plain (a, b, c, d, e, f, g) = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g)- lift (a, b, c, d, e, f, g) = tup7 (lift a, lift b, lift c, lift d, lift e, lift f, lift g)--instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g)- => Unlift Exp (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g) where- unlift = untup7--instance (Lift Exp a, Lift Exp b, Lift Exp c, Lift Exp d, Lift Exp e, Lift Exp f, Lift Exp g, Lift Exp h,- Elt (Plain a), Elt (Plain b), Elt (Plain c), Elt (Plain d), Elt (Plain e), Elt (Plain f),- Elt (Plain g), Elt (Plain h))- => Lift Exp (a, b, c, d, e, f, g, h) where- type Plain (a, b, c, d, e, f, g, h)- = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h)- lift (a, b, c, d, e, f, g, h)- = tup8 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h)--instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h)- => Unlift Exp (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h) where- unlift = untup8--instance (Lift Exp a, Lift Exp b, Lift Exp c, Lift Exp d, Lift Exp e,- Lift Exp f, Lift Exp g, Lift Exp h, Lift Exp i,- Elt (Plain a), Elt (Plain b), Elt (Plain c), Elt (Plain d), Elt (Plain e),- Elt (Plain f), Elt (Plain g), Elt (Plain h), Elt (Plain i))- => Lift Exp (a, b, c, d, e, f, g, h, i) where- type Plain (a, b, c, d, e, f, g, h, i)- = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i)- lift (a, b, c, d, e, f, g, h, i)- = tup9 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i)--instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i)- => Unlift Exp (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i) where- unlift = untup9--instance (Lift Exp a, Lift Exp b, Lift Exp c, Lift Exp d, Lift Exp e,- Lift Exp f, Lift Exp g, Lift Exp h, Lift Exp i, Lift Exp j,- Elt (Plain a), Elt (Plain b), Elt (Plain c), Elt (Plain d), Elt (Plain e),- Elt (Plain f), Elt (Plain g), Elt (Plain h), Elt (Plain i), Elt (Plain j))- => Lift Exp (a, b, c, d, e, f, g, h, i, j) where- type Plain (a, b, c, d, e, f, g, h, i, j)- = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j)- lift (a, b, c, d, e, f, g, h, i, j)- = tup10 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j)--instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j)- => Unlift Exp (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j) where- unlift = untup10--instance (Lift Exp a, Lift Exp b, Lift Exp c, Lift Exp d, Lift Exp e,- Lift Exp f, Lift Exp g, Lift Exp h, Lift Exp i, Lift Exp j, Lift Exp k,- Elt (Plain a), Elt (Plain b), Elt (Plain c), Elt (Plain d), Elt (Plain e),- Elt (Plain f), Elt (Plain g), Elt (Plain h), Elt (Plain i), Elt (Plain j), Elt (Plain k))- => Lift Exp (a, b, c, d, e, f, g, h, i, j, k) where- type Plain (a, b, c, d, e, f, g, h, i, j, k)- = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j, Plain k)- lift (a, b, c, d, e, f, g, h, i, j, k)- = tup11 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j, lift k)--instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k)- => Unlift Exp (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j, Exp k) where- unlift = untup11--instance (Lift Exp a, Lift Exp b, Lift Exp c, Lift Exp d, Lift Exp e, Lift Exp f,- Lift Exp g, Lift Exp h, Lift Exp i, Lift Exp j, Lift Exp k, Lift Exp l,- Elt (Plain a), Elt (Plain b), Elt (Plain c), Elt (Plain d), Elt (Plain e), Elt (Plain f),- Elt (Plain g), Elt (Plain h), Elt (Plain i), Elt (Plain j), Elt (Plain k), Elt (Plain l))- => Lift Exp (a, b, c, d, e, f, g, h, i, j, k, l) where- type Plain (a, b, c, d, e, f, g, h, i, j, k, l)- = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j, Plain k, Plain l)- lift (a, b, c, d, e, f, g, h, i, j, k, l)- = tup12 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j, lift k, lift l)--instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l)- => Unlift Exp (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j, Exp k, Exp l) where- unlift = untup12--instance (Lift Exp a, Lift Exp b, Lift Exp c, Lift Exp d, Lift Exp e, Lift Exp f,- Lift Exp g, Lift Exp h, Lift Exp i, Lift Exp j, Lift Exp k, Lift Exp l, Lift Exp m,- Elt (Plain a), Elt (Plain b), Elt (Plain c), Elt (Plain d), Elt (Plain e), Elt (Plain f),- Elt (Plain g), Elt (Plain h), Elt (Plain i), Elt (Plain j), Elt (Plain k), Elt (Plain l), Elt (Plain m))- => Lift Exp (a, b, c, d, e, f, g, h, i, j, k, l, m) where- type Plain (a, b, c, d, e, f, g, h, i, j, k, l, m)- = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j, Plain k, Plain l, Plain m)- lift (a, b, c, d, e, f, g, h, i, j, k, l, m)- = tup13 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j, lift k, lift l, lift m)--instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l, Elt m)- => Unlift Exp (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j, Exp k, Exp l, Exp m) where- unlift = untup13--instance (Lift Exp a, Lift Exp b, Lift Exp c, Lift Exp d, Lift Exp e, Lift Exp f, Lift Exp g,- Lift Exp h, Lift Exp i, Lift Exp j, Lift Exp k, Lift Exp l, Lift Exp m, Lift Exp n,- Elt (Plain a), Elt (Plain b), Elt (Plain c), Elt (Plain d), Elt (Plain e), Elt (Plain f), Elt (Plain g),- Elt (Plain h), Elt (Plain i), Elt (Plain j), Elt (Plain k), Elt (Plain l), Elt (Plain m), Elt (Plain n))- => Lift Exp (a, b, c, d, e, f, g, h, i, j, k, l, m, n) where- type Plain (a, b, c, d, e, f, g, h, i, j, k, l, m, n)- = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j, Plain k, Plain l, Plain m, Plain n)- lift (a, b, c, d, e, f, g, h, i, j, k, l, m, n)- = tup14 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j, lift k, lift l, lift m, lift n)--instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l, Elt m, Elt n)- => Unlift Exp (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j, Exp k, Exp l, Exp m, Exp n) where- unlift = untup14--instance (Lift Exp a, Lift Exp b, Lift Exp c, Lift Exp d, Lift Exp e, Lift Exp f, Lift Exp g,- Lift Exp h, Lift Exp i, Lift Exp j, Lift Exp k, Lift Exp l, Lift Exp m, Lift Exp n, Lift Exp o,- Elt (Plain a), Elt (Plain b), Elt (Plain c), Elt (Plain d), Elt (Plain e), Elt (Plain f), Elt (Plain g),- Elt (Plain h), Elt (Plain i), Elt (Plain j), Elt (Plain k), Elt (Plain l), Elt (Plain m), Elt (Plain n), Elt (Plain o))- => Lift Exp (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) where- type Plain (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)- = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j, Plain k, Plain l, Plain m, Plain n, Plain o)- lift (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)- = tup15 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j, lift k, lift l, lift m, lift n, lift o)--instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l, Elt m, Elt n, Elt o)- => Unlift Exp (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j, Exp k, Exp l, Exp m, Exp n, Exp o) where- unlift = untup15------ Instances for Arrays class----instance Lift Acc () where--- type Plain () = ()--- lift _ = Acc (Atuple NilAtup)--instance (Shape sh, Elt e) => Lift Acc (Array sh e) where- type Plain (Array sh e) = Array sh e- lift = Acc . Use--instance (Lift Acc a, Lift Acc b, Arrays (Plain a), Arrays (Plain b)) => Lift Acc (a, b) where- type Plain (a, b) = (Plain a, Plain b)- lift (a, b) = atup2 (lift a, lift b)--instance (Arrays a, Arrays b) => Unlift Acc (Acc a, Acc b) where- unlift = unatup2--instance (Lift Acc a, Lift Acc b, Lift Acc c,- Arrays (Plain a), Arrays (Plain b), Arrays (Plain c))- => Lift Acc (a, b, c) where- type Plain (a, b, c) = (Plain a, Plain b, Plain c)- lift (a, b, c) = atup3 (lift a, lift b, lift c)--instance (Arrays a, Arrays b, Arrays c) => Unlift Acc (Acc a, Acc b, Acc c) where- unlift = unatup3--instance (Lift Acc a, Lift Acc b, Lift Acc c, Lift Acc d,- Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d))- => Lift Acc (a, b, c, d) where- type Plain (a, b, c, d) = (Plain a, Plain b, Plain c, Plain d)- lift (a, b, c, d) = atup4 (lift a, lift b, lift c, lift d)--instance (Arrays a, Arrays b, Arrays c, Arrays d) => Unlift Acc (Acc a, Acc b, Acc c, Acc d) where- unlift = unatup4--instance (Lift Acc a, Lift Acc b, Lift Acc c, Lift Acc d, Lift Acc e,- Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e))- => Lift Acc (a, b, c, d, e) where- type Plain (a, b, c, d, e) = (Plain a, Plain b, Plain c, Plain d, Plain e)- lift (a, b, c, d, e) = atup5 (lift a, lift b, lift c, lift d, lift e)--instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e)- => Unlift Acc (Acc a, Acc b, Acc c, Acc d, Acc e) where- unlift = unatup5--instance (Lift Acc a, Lift Acc b, Lift Acc c, Lift Acc d, Lift Acc e, Lift Acc f,- Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e), Arrays (Plain f))- => Lift Acc (a, b, c, d, e, f) where- type Plain (a, b, c, d, e, f) = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f)- lift (a, b, c, d, e, f) = atup6 (lift a, lift b, lift c, lift d, lift e, lift f)--instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f)- => Unlift Acc (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f) where- unlift = unatup6--instance (Lift Acc a, Lift Acc b, Lift Acc c, Lift Acc d, Lift Acc e, Lift Acc f, Lift Acc g,- Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e), Arrays (Plain f),- Arrays (Plain g))- => Lift Acc (a, b, c, d, e, f, g) where- type Plain (a, b, c, d, e, f, g) = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g)- lift (a, b, c, d, e, f, g) = atup7 (lift a, lift b, lift c, lift d, lift e, lift f, lift g)--instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g)- => Unlift Acc (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g) where- unlift = unatup7--instance (Lift Acc a, Lift Acc b, Lift Acc c, Lift Acc d, Lift Acc e, Lift Acc f, Lift Acc g, Lift Acc h,- Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e), Arrays (Plain f),- Arrays (Plain g), Arrays (Plain h))- => Lift Acc (a, b, c, d, e, f, g, h) where- type Plain (a, b, c, d, e, f, g, h)- = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h)- lift (a, b, c, d, e, f, g, h)- = atup8 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h)--instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h)- => Unlift Acc (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h) where- unlift = unatup8--instance (Lift Acc a, Lift Acc b, Lift Acc c, Lift Acc d, Lift Acc e,- Lift Acc f, Lift Acc g, Lift Acc h, Lift Acc i,- Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e),- Arrays (Plain f), Arrays (Plain g), Arrays (Plain h), Arrays (Plain i))- => Lift Acc (a, b, c, d, e, f, g, h, i) where- type Plain (a, b, c, d, e, f, g, h, i)- = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i)- lift (a, b, c, d, e, f, g, h, i)- = atup9 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i)--instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i)- => Unlift Acc (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i) where- unlift = unatup9--instance (Lift Acc a, Lift Acc b, Lift Acc c, Lift Acc d, Lift Acc e,- Lift Acc f, Lift Acc g, Lift Acc h, Lift Acc i, Lift Acc j,- Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e),- Arrays (Plain f), Arrays (Plain g), Arrays (Plain h), Arrays (Plain i), Arrays (Plain j))- => Lift Acc (a, b, c, d, e, f, g, h, i, j) where- type Plain (a, b, c, d, e, f, g, h, i, j)- = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j)- lift (a, b, c, d, e, f, g, h, i, j)- = atup10 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j)--instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j)- => Unlift Acc (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j) where- unlift = unatup10--instance (Lift Acc a, Lift Acc b, Lift Acc c, Lift Acc d, Lift Acc e,- Lift Acc f, Lift Acc g, Lift Acc h, Lift Acc i, Lift Acc j, Lift Acc k,- Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e),- Arrays (Plain f), Arrays (Plain g), Arrays (Plain h), Arrays (Plain i), Arrays (Plain j), Arrays (Plain k))- => Lift Acc (a, b, c, d, e, f, g, h, i, j, k) where- type Plain (a, b, c, d, e, f, g, h, i, j, k)- = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j, Plain k)- lift (a, b, c, d, e, f, g, h, i, j, k)- = atup11 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j, lift k)--instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k)- => Unlift Acc (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j, Acc k) where- unlift = unatup11--instance (Lift Acc a, Lift Acc b, Lift Acc c, Lift Acc d, Lift Acc e, Lift Acc f,- Lift Acc g, Lift Acc h, Lift Acc i, Lift Acc j, Lift Acc k, Lift Acc l,- Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e), Arrays (Plain f),- Arrays (Plain g), Arrays (Plain h), Arrays (Plain i), Arrays (Plain j), Arrays (Plain k), Arrays (Plain l))- => Lift Acc (a, b, c, d, e, f, g, h, i, j, k, l) where- type Plain (a, b, c, d, e, f, g, h, i, j, k, l)- = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j, Plain k, Plain l)- lift (a, b, c, d, e, f, g, h, i, j, k, l)- = atup12 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j, lift k, lift l)--instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l)- => Unlift Acc (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j, Acc k, Acc l) where- unlift = unatup12--instance (Lift Acc a, Lift Acc b, Lift Acc c, Lift Acc d, Lift Acc e, Lift Acc f,- Lift Acc g, Lift Acc h, Lift Acc i, Lift Acc j, Lift Acc k, Lift Acc l, Lift Acc m,- Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e), Arrays (Plain f),- Arrays (Plain g), Arrays (Plain h), Arrays (Plain i), Arrays (Plain j), Arrays (Plain k), Arrays (Plain l), Arrays (Plain m))- => Lift Acc (a, b, c, d, e, f, g, h, i, j, k, l, m) where- type Plain (a, b, c, d, e, f, g, h, i, j, k, l, m)- = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j, Plain k, Plain l, Plain m)- lift (a, b, c, d, e, f, g, h, i, j, k, l, m)- = atup13 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j, lift k, lift l, lift m)--instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l, Arrays m)- => Unlift Acc (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j, Acc k, Acc l, Acc m) where- unlift = unatup13--instance (Lift Acc a, Lift Acc b, Lift Acc c, Lift Acc d, Lift Acc e, Lift Acc f, Lift Acc g,- Lift Acc h, Lift Acc i, Lift Acc j, Lift Acc k, Lift Acc l, Lift Acc m, Lift Acc n,- Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e), Arrays (Plain f), Arrays (Plain g),- Arrays (Plain h), Arrays (Plain i), Arrays (Plain j), Arrays (Plain k), Arrays (Plain l), Arrays (Plain m), Arrays (Plain n))- => Lift Acc (a, b, c, d, e, f, g, h, i, j, k, l, m, n) where- type Plain (a, b, c, d, e, f, g, h, i, j, k, l, m, n)- = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j, Plain k, Plain l, Plain m, Plain n)- lift (a, b, c, d, e, f, g, h, i, j, k, l, m, n)- = atup14 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j, lift k, lift l, lift m, lift n)--instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l, Arrays m, Arrays n)- => Unlift Acc (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j, Acc k, Acc l, Acc m, Acc n) where- unlift = unatup14--instance (Lift Acc a, Lift Acc b, Lift Acc c, Lift Acc d, Lift Acc e, Lift Acc f, Lift Acc g,- Lift Acc h, Lift Acc i, Lift Acc j, Lift Acc k, Lift Acc l, Lift Acc m, Lift Acc n, Lift Acc o,- Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e), Arrays (Plain f), Arrays (Plain g),- Arrays (Plain h), Arrays (Plain i), Arrays (Plain j), Arrays (Plain k), Arrays (Plain l), Arrays (Plain m), Arrays (Plain n), Arrays (Plain o))- => Lift Acc (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) where- type Plain (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)- = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j, Plain k, Plain l, Plain m, Plain n, Plain o)- lift (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)- = atup15 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j, lift k, lift l, lift m, lift n, lift o)--instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l, Arrays m, Arrays n, Arrays o)- => Unlift Acc (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j, Acc k, Acc l, Acc m, Acc n, Acc o) where- unlift = unatup15--{----- Instances for Seq--instance (Lift Seq a, Lift Seq b, Arrays (Plain a), Arrays (Plain b)) => Lift Seq (a, b) where- type Plain (a, b) = (Plain a, Plain b)- lift (a, b) = stup2 (lift a, lift b)--instance (Lift Seq a, Lift Seq b, Lift Seq c,- Arrays (Plain a), Arrays (Plain b), Arrays (Plain c))- => Lift Seq (a, b, c) where- type Plain (a, b, c) = (Plain a, Plain b, Plain c)- lift (a, b, c) = stup3 (lift a, lift b, lift c)--instance (Lift Seq a, Lift Seq b, Lift Seq c, Lift Seq d,- Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d))- => Lift Seq (a, b, c, d) where- type Plain (a, b, c, d) = (Plain a, Plain b, Plain c, Plain d)- lift (a, b, c, d) = stup4 (lift a, lift b, lift c, lift d)--instance (Lift Seq a, Lift Seq b, Lift Seq c, Lift Seq d, Lift Seq e,- Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e))- => Lift Seq (a, b, c, d, e) where- type Plain (a, b, c, d, e) = (Plain a, Plain b, Plain c, Plain d, Plain e)- lift (a, b, c, d, e) = stup5 (lift a, lift b, lift c, lift d, lift e)--instance (Lift Seq a, Lift Seq b, Lift Seq c, Lift Seq d, Lift Seq e, Lift Seq f,- Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e), Arrays (Plain f))- => Lift Seq (a, b, c, d, e, f) where- type Plain (a, b, c, d, e, f) = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f)- lift (a, b, c, d, e, f) = stup6 (lift a, lift b, lift c, lift d, lift e, lift f)--instance (Lift Seq a, Lift Seq b, Lift Seq c, Lift Seq d, Lift Seq e, Lift Seq f, Lift Seq g,- Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e), Arrays (Plain f),- Arrays (Plain g))- => Lift Seq (a, b, c, d, e, f, g) where- type Plain (a, b, c, d, e, f, g) = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g)- lift (a, b, c, d, e, f, g) = stup7 (lift a, lift b, lift c, lift d, lift e, lift f, lift g)--instance (Lift Seq a, Lift Seq b, Lift Seq c, Lift Seq d, Lift Seq e, Lift Seq f, Lift Seq g, Lift Seq h,- Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e), Arrays (Plain f),- Arrays (Plain g), Arrays (Plain h))- => Lift Seq (a, b, c, d, e, f, g, h) where- type Plain (a, b, c, d, e, f, g, h)- = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h)- lift (a, b, c, d, e, f, g, h)- = stup8 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h)--instance (Lift Seq a, Lift Seq b, Lift Seq c, Lift Seq d, Lift Seq e,- Lift Seq f, Lift Seq g, Lift Seq h, Lift Seq i,- Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e),- Arrays (Plain f), Arrays (Plain g), Arrays (Plain h), Arrays (Plain i))- => Lift Seq (a, b, c, d, e, f, g, h, i) where- type Plain (a, b, c, d, e, f, g, h, i)- = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i)- lift (a, b, c, d, e, f, g, h, i)- = stup9 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i)--instance (Lift Seq a, Lift Seq b, Lift Seq c, Lift Seq d, Lift Seq e,- Lift Seq f, Lift Seq g, Lift Seq h, Lift Seq i, Lift Seq j,- Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e),- Arrays (Plain f), Arrays (Plain g), Arrays (Plain h), Arrays (Plain i), Arrays (Plain j))- => Lift Seq (a, b, c, d, e, f, g, h, i, j) where- type Plain (a, b, c, d, e, f, g, h, i, j)- = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j)- lift (a, b, c, d, e, f, g, h, i, j)- = stup10 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j)--instance (Lift Seq a, Lift Seq b, Lift Seq c, Lift Seq d, Lift Seq e,- Lift Seq f, Lift Seq g, Lift Seq h, Lift Seq i, Lift Seq j, Lift Seq k,- Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e),- Arrays (Plain f), Arrays (Plain g), Arrays (Plain h), Arrays (Plain i), Arrays (Plain j), Arrays (Plain k))- => Lift Seq (a, b, c, d, e, f, g, h, i, j, k) where- type Plain (a, b, c, d, e, f, g, h, i, j, k)- = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j, Plain k)- lift (a, b, c, d, e, f, g, h, i, j, k)- = stup11 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j, lift k)--instance (Lift Seq a, Lift Seq b, Lift Seq c, Lift Seq d, Lift Seq e, Lift Seq f,- Lift Seq g, Lift Seq h, Lift Seq i, Lift Seq j, Lift Seq k, Lift Seq l,- Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e), Arrays (Plain f),- Arrays (Plain g), Arrays (Plain h), Arrays (Plain i), Arrays (Plain j), Arrays (Plain k), Arrays (Plain l))- => Lift Seq (a, b, c, d, e, f, g, h, i, j, k, l) where- type Plain (a, b, c, d, e, f, g, h, i, j, k, l)- = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j, Plain k, Plain l)- lift (a, b, c, d, e, f, g, h, i, j, k, l)- = stup12 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j, lift k, lift l)--instance (Lift Seq a, Lift Seq b, Lift Seq c, Lift Seq d, Lift Seq e, Lift Seq f,- Lift Seq g, Lift Seq h, Lift Seq i, Lift Seq j, Lift Seq k, Lift Seq l, Lift Seq m,- Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e), Arrays (Plain f),- Arrays (Plain g), Arrays (Plain h), Arrays (Plain i), Arrays (Plain j), Arrays (Plain k), Arrays (Plain l), Arrays (Plain m))- => Lift Seq (a, b, c, d, e, f, g, h, i, j, k, l, m) where- type Plain (a, b, c, d, e, f, g, h, i, j, k, l, m)- = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j, Plain k, Plain l, Plain m)- lift (a, b, c, d, e, f, g, h, i, j, k, l, m)- = stup13 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j, lift k, lift l, lift m)--instance (Lift Seq a, Lift Seq b, Lift Seq c, Lift Seq d, Lift Seq e, Lift Seq f, Lift Seq g,- Lift Seq h, Lift Seq i, Lift Seq j, Lift Seq k, Lift Seq l, Lift Seq m, Lift Seq n,- Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e), Arrays (Plain f), Arrays (Plain g),- Arrays (Plain h), Arrays (Plain i), Arrays (Plain j), Arrays (Plain k), Arrays (Plain l), Arrays (Plain m), Arrays (Plain n))- => Lift Seq (a, b, c, d, e, f, g, h, i, j, k, l, m, n) where- type Plain (a, b, c, d, e, f, g, h, i, j, k, l, m, n)- = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j, Plain k, Plain l, Plain m, Plain n)- lift (a, b, c, d, e, f, g, h, i, j, k, l, m, n)- = stup14 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j, lift k, lift l, lift m, lift n)--instance (Lift Seq a, Lift Seq b, Lift Seq c, Lift Seq d, Lift Seq e, Lift Seq f, Lift Seq g,- Lift Seq h, Lift Seq i, Lift Seq j, Lift Seq k, Lift Seq l, Lift Seq m, Lift Seq n, Lift Seq o,- Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e), Arrays (Plain f), Arrays (Plain g),- Arrays (Plain h), Arrays (Plain i), Arrays (Plain j), Arrays (Plain k), Arrays (Plain l), Arrays (Plain m), Arrays (Plain n), Arrays (Plain o))- => Lift Seq (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) where- type Plain (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)- = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j, Plain k, Plain l, Plain m, Plain n, Plain o)- lift (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)- = stup15 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j, lift k, lift l, lift m, lift n, lift o)---}-
− Data/Array/Accelerate/Prelude.hs
@@ -1,2113 +0,0 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE PatternGuards #-}-{-# LANGUAGE RebindableSyntax #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}--- |--- Module : Data.Array.Accelerate.Prelude--- Copyright : [2009..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- [2010..2011] Ben Lever--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)------ Standard functions that are not part of the core set (directly represented in--- the AST), but are instead implemented in terms of the core set.-----module Data.Array.Accelerate.Prelude (-- -- * Element-wise operations- indexed,- imap,-- -- * Zipping- zipWith3, zipWith4, zipWith5, zipWith6, zipWith7, zipWith8, zipWith9,- izipWith, izipWith3, izipWith4, izipWith5, izipWith6, izipWith7, izipWith8, izipWith9,- zip, zip3, zip4, zip5, zip6, zip7, zip8, zip9,-- -- * Unzipping- unzip, unzip3, unzip4, unzip5, unzip6, unzip7, unzip8, unzip9,-- -- * Reductions- foldAll, fold1All,-- -- ** Specialised folds- all, any, and, or, sum, product, minimum, maximum,-- -- * Scans- prescanl, postscanl, prescanr, postscanr,-- -- ** Segmented scans- scanlSeg, scanl'Seg, scanl1Seg, prescanlSeg, postscanlSeg,- scanrSeg, scanr'Seg, scanr1Seg, prescanrSeg, postscanrSeg,-- -- * Shape manipulation- flatten,-- -- * Enumeration and filling- fill, enumFromN, enumFromStepN,-- -- * Concatenation- (++),-- -- * Working with predicates- -- ** Filtering- filter,-- -- ** Scatter / Gather- scatter, scatterIf,- gather, gatherIf,-- -- * Permutations- reverse, transpose,-- -- * Extracting sub-vectors- init, tail, take, drop, slit,-- -- * Controlling execution- compute,-- -- * Flow control- IfThenElse(..),-- -- ** Array-level- (?|),-- -- ** Expression-level- (?), caseof,-- -- * Scalar iteration- iterate,-- -- * Scalar reduction- sfoldl, -- sfoldr,-- -- * Lifting and unlifting- Lift(..), Unlift(..),- lift1, lift2, lift3, ilift1, ilift2, ilift3,-- -- ** Tuple construction and destruction- fst, afst, snd, asnd, curry, uncurry,-- -- ** Index construction and destruction- index0, index1, unindex1, index2, unindex2, index3, unindex3,-- -- * Array operations with a scalar result- the, null, length,-- -- * Sequence operations- -- fromSeq, fromSeqElems, fromSeqShapes, toSeqInner, toSeqOuter2, toSeqOuter3, generateSeq,--) where---- avoid clashes with Prelude functions----import Data.Typeable ( gcast )-import GHC.Base ( Constraint )-import Prelude ( (.), ($), Maybe(..), const, id, fromInteger, flip, undefined, fail )---- friends-import Data.Array.Accelerate.Analysis.Match-import Data.Array.Accelerate.Array.Sugar hiding ( (!), ignore, shape, size, intersect, toIndex, fromIndex )-import Data.Array.Accelerate.Language-import Data.Array.Accelerate.Lift-import Data.Array.Accelerate.Smart-import Data.Array.Accelerate.Type--import Data.Array.Accelerate.Classes.Eq-import Data.Array.Accelerate.Classes.FromIntegral-import Data.Array.Accelerate.Classes.Integral-import Data.Array.Accelerate.Classes.Num-import Data.Array.Accelerate.Classes.Ord--import Data.Array.Accelerate.Data.Bits----- Element-wise operations--- --------------------------- | Pair each element with its index------ >>> let xs = fromList (Z:.5) [0..]--- >>> indexed (use xs)--- Vector (Z :. 5) [(Z :. 0,0.0),(Z :. 1,1.0),(Z :. 2,2.0),(Z :. 3,3.0),(Z :. 4,4.0)]------ >>> let mat = fromList (Z:.3:.4) [0..]--- >>> indexed (use mat)--- Matrix (Z :. 3 :. 4)--- [(Z :. 0 :. 0,0.0),(Z :. 0 :. 1,1.0), (Z :. 0 :. 2,2.0), (Z :. 0 :. 3,3.0),--- (Z :. 1 :. 0,4.0),(Z :. 1 :. 1,5.0), (Z :. 1 :. 2,6.0), (Z :. 1 :. 3,7.0),--- (Z :. 2 :. 0,8.0),(Z :. 2 :. 1,9.0),(Z :. 2 :. 2,10.0),(Z :. 2 :. 3,11.0)]----indexed :: (Shape sh, Elt a) => Acc (Array sh a) -> Acc (Array sh (sh, a))-indexed xs = zip (generate (shape xs) id) xs---- | Apply a function to every element of an array and its index----imap :: (Shape sh, Elt a, Elt b)- => (Exp sh -> Exp a -> Exp b)- -> Acc (Array sh a)- -> Acc (Array sh b)-imap f xs = zipWith f (generate (shape xs) id) xs----- | Zip three arrays with the given function, analogous to 'zipWith'.----zipWith3- :: (Shape sh, Elt a, Elt b, Elt c, Elt d)- => (Exp a -> Exp b -> Exp c -> Exp d)- -> Acc (Array sh a)- -> Acc (Array sh b)- -> Acc (Array sh c)- -> Acc (Array sh d)-zipWith3 f as bs cs- = generate (shape as `intersect` shape bs `intersect` shape cs)- (\ix -> f (as ! ix) (bs ! ix) (cs ! ix))---- | Zip four arrays with the given function, analogous to 'zipWith'.----zipWith4- :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e)- => (Exp a -> Exp b -> Exp c -> Exp d -> Exp e)- -> Acc (Array sh a)- -> Acc (Array sh b)- -> Acc (Array sh c)- -> Acc (Array sh d)- -> Acc (Array sh e)-zipWith4 f as bs cs ds- = generate (shape as `intersect` shape bs `intersect`- shape cs `intersect` shape ds)- (\ix -> f (as ! ix) (bs ! ix) (cs ! ix) (ds ! ix))---- | Zip five arrays with the given function, analogous to 'zipWith'.----zipWith5- :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f)- => (Exp a -> Exp b -> Exp c -> Exp d -> Exp e -> Exp f)- -> Acc (Array sh a)- -> Acc (Array sh b)- -> Acc (Array sh c)- -> Acc (Array sh d)- -> Acc (Array sh e)- -> Acc (Array sh f)-zipWith5 f as bs cs ds es- = generate (shape as `intersect` shape bs `intersect` shape cs- `intersect` shape ds `intersect` shape es)- (\ix -> f (as ! ix) (bs ! ix) (cs ! ix) (ds ! ix) (es ! ix))---- | Zip six arrays with the given function, analogous to 'zipWith'.----zipWith6- :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g)- => (Exp a -> Exp b -> Exp c -> Exp d -> Exp e -> Exp f -> Exp g)- -> Acc (Array sh a)- -> Acc (Array sh b)- -> Acc (Array sh c)- -> Acc (Array sh d)- -> Acc (Array sh e)- -> Acc (Array sh f)- -> Acc (Array sh g)-zipWith6 f as bs cs ds es fs- = generate (shape as `intersect` shape bs `intersect` shape cs- `intersect` shape ds `intersect` shape es- `intersect` shape fs)- (\ix -> f (as ! ix) (bs ! ix) (cs ! ix) (ds ! ix) (es ! ix) (fs ! ix))---- | Zip seven arrays with the given function, analogous to 'zipWith'.----zipWith7- :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h)- => (Exp a -> Exp b -> Exp c -> Exp d -> Exp e -> Exp f -> Exp g -> Exp h)- -> Acc (Array sh a)- -> Acc (Array sh b)- -> Acc (Array sh c)- -> Acc (Array sh d)- -> Acc (Array sh e)- -> Acc (Array sh f)- -> Acc (Array sh g)- -> Acc (Array sh h)-zipWith7 f as bs cs ds es fs gs- = generate (shape as `intersect` shape bs `intersect` shape cs- `intersect` shape ds `intersect` shape es- `intersect` shape fs `intersect` shape gs)- (\ix -> f (as ! ix) (bs ! ix) (cs ! ix) (ds ! ix) (es ! ix) (fs ! ix) (gs ! ix))---- | Zip eight arrays with the given function, analogous to 'zipWith'.----zipWith8- :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i)- => (Exp a -> Exp b -> Exp c -> Exp d -> Exp e -> Exp f -> Exp g -> Exp h -> Exp i)- -> Acc (Array sh a)- -> Acc (Array sh b)- -> Acc (Array sh c)- -> Acc (Array sh d)- -> Acc (Array sh e)- -> Acc (Array sh f)- -> Acc (Array sh g)- -> Acc (Array sh h)- -> Acc (Array sh i)-zipWith8 f as bs cs ds es fs gs hs- = generate (shape as `intersect` shape bs `intersect` shape cs- `intersect` shape ds `intersect` shape es- `intersect` shape fs `intersect` shape gs- `intersect` shape hs)- (\ix -> f (as ! ix) (bs ! ix) (cs ! ix) (ds ! ix) (es ! ix) (fs ! ix) (gs ! ix) (hs ! ix))---- | Zip nine arrays with the given function, analogous to 'zipWith'.----zipWith9- :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j)- => (Exp a -> Exp b -> Exp c -> Exp d -> Exp e -> Exp f -> Exp g -> Exp h -> Exp i -> Exp j)- -> Acc (Array sh a)- -> Acc (Array sh b)- -> Acc (Array sh c)- -> Acc (Array sh d)- -> Acc (Array sh e)- -> Acc (Array sh f)- -> Acc (Array sh g)- -> Acc (Array sh h)- -> Acc (Array sh i)- -> Acc (Array sh j)-zipWith9 f as bs cs ds es fs gs hs is- = generate (shape as `intersect` shape bs `intersect` shape cs- `intersect` shape ds `intersect` shape es- `intersect` shape fs `intersect` shape gs- `intersect` shape hs `intersect` shape is)- (\ix -> f (as ! ix) (bs ! ix) (cs ! ix) (ds ! ix) (es ! ix) (fs ! ix) (gs ! ix) (hs ! ix) (is ! ix))----- | Zip two arrays with a function that also takes the element index----izipWith- :: (Shape sh, Elt a, Elt b, Elt c)- => (Exp sh -> Exp a -> Exp b -> Exp c)- -> Acc (Array sh a)- -> Acc (Array sh b)- -> Acc (Array sh c)-izipWith f as bs- = generate (shape as `intersect` shape bs)- (\ix -> f ix (as ! ix) (bs ! ix))---- | Zip three arrays with a function that also takes the element index,--- analogous to 'izipWith'.----izipWith3- :: (Shape sh, Elt a, Elt b, Elt c, Elt d)- => (Exp sh -> Exp a -> Exp b -> Exp c -> Exp d)- -> Acc (Array sh a)- -> Acc (Array sh b)- -> Acc (Array sh c)- -> Acc (Array sh d)-izipWith3 f as bs cs- = generate (shape as `intersect` shape bs `intersect` shape cs)- (\ix -> f ix (as ! ix) (bs ! ix) (cs ! ix))---- | Zip four arrays with the given function that also takes the element index,--- analogous to 'zipWith'.----izipWith4- :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e)- => (Exp sh -> Exp a -> Exp b -> Exp c -> Exp d -> Exp e)- -> Acc (Array sh a)- -> Acc (Array sh b)- -> Acc (Array sh c)- -> Acc (Array sh d)- -> Acc (Array sh e)-izipWith4 f as bs cs ds- = generate (shape as `intersect` shape bs `intersect`- shape cs `intersect` shape ds)- (\ix -> f ix (as ! ix) (bs ! ix) (cs ! ix) (ds ! ix))---- | Zip five arrays with the given function that also takes the element index,--- analogous to 'zipWith'.----izipWith5- :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f)- => (Exp sh -> Exp a -> Exp b -> Exp c -> Exp d -> Exp e -> Exp f)- -> Acc (Array sh a)- -> Acc (Array sh b)- -> Acc (Array sh c)- -> Acc (Array sh d)- -> Acc (Array sh e)- -> Acc (Array sh f)-izipWith5 f as bs cs ds es- = generate (shape as `intersect` shape bs `intersect` shape cs- `intersect` shape ds `intersect` shape es)- (\ix -> f ix (as ! ix) (bs ! ix) (cs ! ix) (ds ! ix) (es ! ix))---- | Zip six arrays with the given function that also takes the element index,--- analogous to 'zipWith'.----izipWith6- :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g)- => (Exp sh -> Exp a -> Exp b -> Exp c -> Exp d -> Exp e -> Exp f -> Exp g)- -> Acc (Array sh a)- -> Acc (Array sh b)- -> Acc (Array sh c)- -> Acc (Array sh d)- -> Acc (Array sh e)- -> Acc (Array sh f)- -> Acc (Array sh g)-izipWith6 f as bs cs ds es fs- = generate (shape as `intersect` shape bs `intersect` shape cs- `intersect` shape ds `intersect` shape es- `intersect` shape fs)- (\ix -> f ix (as ! ix) (bs ! ix) (cs ! ix) (ds ! ix) (es ! ix) (fs ! ix))---- | Zip seven arrays with the given function that also takes the element--- index, analogous to 'zipWith'.----izipWith7- :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h)- => (Exp sh -> Exp a -> Exp b -> Exp c -> Exp d -> Exp e -> Exp f -> Exp g -> Exp h)- -> Acc (Array sh a)- -> Acc (Array sh b)- -> Acc (Array sh c)- -> Acc (Array sh d)- -> Acc (Array sh e)- -> Acc (Array sh f)- -> Acc (Array sh g)- -> Acc (Array sh h)-izipWith7 f as bs cs ds es fs gs- = generate (shape as `intersect` shape bs `intersect` shape cs- `intersect` shape ds `intersect` shape es- `intersect` shape fs `intersect` shape gs)- (\ix -> f ix (as ! ix) (bs ! ix) (cs ! ix) (ds ! ix) (es ! ix) (fs ! ix) (gs ! ix))---- | Zip eight arrays with the given function that also takes the element--- index, analogous to 'zipWith'.----izipWith8- :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i)- => (Exp sh -> Exp a -> Exp b -> Exp c -> Exp d -> Exp e -> Exp f -> Exp g -> Exp h -> Exp i)- -> Acc (Array sh a)- -> Acc (Array sh b)- -> Acc (Array sh c)- -> Acc (Array sh d)- -> Acc (Array sh e)- -> Acc (Array sh f)- -> Acc (Array sh g)- -> Acc (Array sh h)- -> Acc (Array sh i)-izipWith8 f as bs cs ds es fs gs hs- = generate (shape as `intersect` shape bs `intersect` shape cs- `intersect` shape ds `intersect` shape es- `intersect` shape fs `intersect` shape gs- `intersect` shape hs)- (\ix -> f ix (as ! ix) (bs ! ix) (cs ! ix) (ds ! ix) (es ! ix) (fs ! ix) (gs ! ix) (hs ! ix))---- | Zip nine arrays with the given function that also takes the element index,--- analogous to 'zipWith'.----izipWith9- :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j)- => (Exp sh -> Exp a -> Exp b -> Exp c -> Exp d -> Exp e -> Exp f -> Exp g -> Exp h -> Exp i -> Exp j)- -> Acc (Array sh a)- -> Acc (Array sh b)- -> Acc (Array sh c)- -> Acc (Array sh d)- -> Acc (Array sh e)- -> Acc (Array sh f)- -> Acc (Array sh g)- -> Acc (Array sh h)- -> Acc (Array sh i)- -> Acc (Array sh j)-izipWith9 f as bs cs ds es fs gs hs is- = generate (shape as `intersect` shape bs `intersect` shape cs- `intersect` shape ds `intersect` shape es- `intersect` shape fs `intersect` shape gs- `intersect` shape hs `intersect` shape is)- (\ix -> f ix (as ! ix) (bs ! ix) (cs ! ix) (ds ! ix) (es ! ix) (fs ! ix) (gs ! ix) (hs ! ix) (is ! ix))----- | Combine the elements of two arrays pairwise. The shape of the result is the--- intersection of the two argument shapes.----zip :: (Shape sh, Elt a, Elt b)- => Acc (Array sh a)- -> Acc (Array sh b)- -> Acc (Array sh (a, b))-zip = zipWith (curry lift)---- | Take three arrays and return an array of triples, analogous to zip.----zip3 :: (Shape sh, Elt a, Elt b, Elt c)- => Acc (Array sh a)- -> Acc (Array sh b)- -> Acc (Array sh c)- -> Acc (Array sh (a, b, c))-zip3 = zipWith3 (\a b c -> lift (a,b,c))---- | Take four arrays and return an array of quadruples, analogous to zip.----zip4 :: (Shape sh, Elt a, Elt b, Elt c, Elt d)- => Acc (Array sh a)- -> Acc (Array sh b)- -> Acc (Array sh c)- -> Acc (Array sh d)- -> Acc (Array sh (a, b, c, d))-zip4 = zipWith4 (\a b c d -> lift (a,b,c,d))---- | Take five arrays and return an array of five-tuples, analogous to zip.----zip5 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e)- => Acc (Array sh a)- -> Acc (Array sh b)- -> Acc (Array sh c)- -> Acc (Array sh d)- -> Acc (Array sh e)- -> Acc (Array sh (a, b, c, d, e))-zip5 = zipWith5 (\a b c d e -> lift (a,b,c,d,e))---- | Take six arrays and return an array of six-tuples, analogous to zip.----zip6 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f)- => Acc (Array sh a)- -> Acc (Array sh b)- -> Acc (Array sh c)- -> Acc (Array sh d)- -> Acc (Array sh e)- -> Acc (Array sh f)- -> Acc (Array sh (a, b, c, d, e, f))-zip6 = zipWith6 (\a b c d e f -> lift (a,b,c,d,e,f))---- | Take seven arrays and return an array of seven-tuples, analogous to zip.----zip7 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g)- => Acc (Array sh a)- -> Acc (Array sh b)- -> Acc (Array sh c)- -> Acc (Array sh d)- -> Acc (Array sh e)- -> Acc (Array sh f)- -> Acc (Array sh g)- -> Acc (Array sh (a, b, c, d, e, f, g))-zip7 = zipWith7 (\a b c d e f g -> lift (a,b,c,d,e,f,g))---- | Take seven arrays and return an array of seven-tuples, analogous to zip.----zip8 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h)- => Acc (Array sh a)- -> Acc (Array sh b)- -> Acc (Array sh c)- -> Acc (Array sh d)- -> Acc (Array sh e)- -> Acc (Array sh f)- -> Acc (Array sh g)- -> Acc (Array sh h)- -> Acc (Array sh (a, b, c, d, e, f, g, h))-zip8 = zipWith8 (\a b c d e f g h -> lift (a,b,c,d,e,f,g,h))---- | Take seven arrays and return an array of seven-tuples, analogous to zip.----zip9 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i)- => Acc (Array sh a)- -> Acc (Array sh b)- -> Acc (Array sh c)- -> Acc (Array sh d)- -> Acc (Array sh e)- -> Acc (Array sh f)- -> Acc (Array sh g)- -> Acc (Array sh h)- -> Acc (Array sh i)- -> Acc (Array sh (a, b, c, d, e, f, g, h, i))-zip9 = zipWith9 (\a b c d e f g h i -> lift (a,b,c,d,e,f,g,h,i))----- | The converse of 'zip', but the shape of the two results is identical to the--- shape of the argument.------ If the argument array is manifest in memory, 'unzip' is a no-op.----unzip :: (Shape sh, Elt a, Elt b)- => Acc (Array sh (a, b))- -> (Acc (Array sh a), Acc (Array sh b))-unzip arr = (map fst arr, map snd arr)---- | Take an array of triples and return three arrays, analogous to 'unzip'.----unzip3 :: (Shape sh, Elt a, Elt b, Elt c)- => Acc (Array sh (a, b, c))- -> (Acc (Array sh a), Acc (Array sh b), Acc (Array sh c))-unzip3 xs = (map get1 xs, map get2 xs, map get3 xs)- where- get1 x = let (a,_,_) = untup3 x in a- get2 x = let (_,b,_) = untup3 x in b- get3 x = let (_,_,c) = untup3 x in c----- | Take an array of quadruples and return four arrays, analogous to 'unzip'.----unzip4 :: (Shape sh, Elt a, Elt b, Elt c, Elt d)- => Acc (Array sh (a, b, c, d))- -> (Acc (Array sh a), Acc (Array sh b), Acc (Array sh c), Acc (Array sh d))-unzip4 xs = (map get1 xs, map get2 xs, map get3 xs, map get4 xs)- where- get1 x = let (a,_,_,_) = untup4 x in a- get2 x = let (_,b,_,_) = untup4 x in b- get3 x = let (_,_,c,_) = untup4 x in c- get4 x = let (_,_,_,d) = untup4 x in d---- | Take an array of 5-tuples and return five arrays, analogous to 'unzip'.----unzip5 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e)- => Acc (Array sh (a, b, c, d, e))- -> (Acc (Array sh a), Acc (Array sh b), Acc (Array sh c), Acc (Array sh d), Acc (Array sh e))-unzip5 xs = (map get1 xs, map get2 xs, map get3 xs, map get4 xs, map get5 xs)- where- get1 x = let (a,_,_,_,_) = untup5 x in a- get2 x = let (_,b,_,_,_) = untup5 x in b- get3 x = let (_,_,c,_,_) = untup5 x in c- get4 x = let (_,_,_,d,_) = untup5 x in d- get5 x = let (_,_,_,_,e) = untup5 x in e---- | Take an array of 6-tuples and return six arrays, analogous to 'unzip'.----unzip6 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f)- => Acc (Array sh (a, b, c, d, e, f))- -> ( Acc (Array sh a), Acc (Array sh b), Acc (Array sh c)- , Acc (Array sh d), Acc (Array sh e), Acc (Array sh f))-unzip6 xs = (map get1 xs, map get2 xs, map get3 xs, map get4 xs, map get5 xs, map get6 xs)- where- get1 x = let (a,_,_,_,_,_) = untup6 x in a- get2 x = let (_,b,_,_,_,_) = untup6 x in b- get3 x = let (_,_,c,_,_,_) = untup6 x in c- get4 x = let (_,_,_,d,_,_) = untup6 x in d- get5 x = let (_,_,_,_,e,_) = untup6 x in e- get6 x = let (_,_,_,_,_,f) = untup6 x in f---- | Take an array of 7-tuples and return seven arrays, analogous to 'unzip'.----unzip7 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g)- => Acc (Array sh (a, b, c, d, e, f, g))- -> ( Acc (Array sh a), Acc (Array sh b), Acc (Array sh c)- , Acc (Array sh d), Acc (Array sh e), Acc (Array sh f)- , Acc (Array sh g))-unzip7 xs = ( map get1 xs, map get2 xs, map get3 xs- , map get4 xs, map get5 xs, map get6 xs- , map get7 xs )- where- get1 x = let (a,_,_,_,_,_,_) = untup7 x in a- get2 x = let (_,b,_,_,_,_,_) = untup7 x in b- get3 x = let (_,_,c,_,_,_,_) = untup7 x in c- get4 x = let (_,_,_,d,_,_,_) = untup7 x in d- get5 x = let (_,_,_,_,e,_,_) = untup7 x in e- get6 x = let (_,_,_,_,_,f,_) = untup7 x in f- get7 x = let (_,_,_,_,_,_,g) = untup7 x in g---- | Take an array of 8-tuples and return eight arrays, analogous to 'unzip'.----unzip8 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h)- => Acc (Array sh (a, b, c, d, e, f, g, h))- -> ( Acc (Array sh a), Acc (Array sh b), Acc (Array sh c)- , Acc (Array sh d), Acc (Array sh e), Acc (Array sh f)- , Acc (Array sh g), Acc (Array sh h) )-unzip8 xs = ( map get1 xs, map get2 xs, map get3 xs- , map get4 xs, map get5 xs, map get6 xs- , map get7 xs, map get8 xs )- where- get1 x = let (a,_,_,_,_,_,_,_) = untup8 x in a- get2 x = let (_,b,_,_,_,_,_,_) = untup8 x in b- get3 x = let (_,_,c,_,_,_,_,_) = untup8 x in c- get4 x = let (_,_,_,d,_,_,_,_) = untup8 x in d- get5 x = let (_,_,_,_,e,_,_,_) = untup8 x in e- get6 x = let (_,_,_,_,_,f,_,_) = untup8 x in f- get7 x = let (_,_,_,_,_,_,g,_) = untup8 x in g- get8 x = let (_,_,_,_,_,_,_,h) = untup8 x in h---- | Take an array of 8-tuples and return eight arrays, analogous to 'unzip'.----unzip9 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i)- => Acc (Array sh (a, b, c, d, e, f, g, h, i))- -> ( Acc (Array sh a), Acc (Array sh b), Acc (Array sh c)- , Acc (Array sh d), Acc (Array sh e), Acc (Array sh f)- , Acc (Array sh g), Acc (Array sh h), Acc (Array sh i))-unzip9 xs = ( map get1 xs, map get2 xs, map get3 xs- , map get4 xs, map get5 xs, map get6 xs- , map get7 xs, map get8 xs, map get9 xs )- where- get1 x = let (a,_,_,_,_,_,_,_,_) = untup9 x in a- get2 x = let (_,b,_,_,_,_,_,_,_) = untup9 x in b- get3 x = let (_,_,c,_,_,_,_,_,_) = untup9 x in c- get4 x = let (_,_,_,d,_,_,_,_,_) = untup9 x in d- get5 x = let (_,_,_,_,e,_,_,_,_) = untup9 x in e- get6 x = let (_,_,_,_,_,f,_,_,_) = untup9 x in f- get7 x = let (_,_,_,_,_,_,g,_,_) = untup9 x in g- get8 x = let (_,_,_,_,_,_,_,h,_) = untup9 x in h- get9 x = let (_,_,_,_,_,_,_,_,i) = untup9 x in i----- Reductions--- -------------- | Reduction of an array of arbitrary rank to a single scalar value. The first--- argument needs to be an /associative/ function to enable efficient parallel--- implementation. The initial element does not need to be an identity element.------ >>> let vec = fromList (Z:.10) [0..]--- >>> foldAll (+) 42 (use vec)--- Scalar Z [87]------ >>> let mat = fromList (Z:.5:.10) [0..]--- >>> foldAll (+) 0 (use mat)--- Scalar Z [1225]----foldAll- :: (Shape sh, Elt a)- => (Exp a -> Exp a -> Exp a)- -> Exp a- -> Acc (Array sh a)- -> Acc (Scalar a)-foldAll f e arr = fold f e (flatten arr)---- | Variant of 'foldAll' that requires the reduced array to be non-empty and--- does not need a default value. The first argument must be an /associative/--- function.----fold1All- :: (Shape sh, Elt a)- => (Exp a -> Exp a -> Exp a)- -> Acc (Array sh a)- -> Acc (Scalar a)-fold1All f arr = fold1 f (flatten arr)----- Specialised reductions--- ---------------------------- Leave the results of these as scalar arrays to make it clear that these are--- array computations, and thus can not be nested.---- | Check if all elements along the innermost dimension satisfy a predicate.------ >>> let mat = fromList (Z :. 4 :. 10) [1,2,3,4,5,6,7,8,9,10,1,1,1,1,1,2,2,2,2,2,2,4,6,8,10,12,14,16,18,20,1,3,5,7,9,11,13,15,17,19] :: Array DIM2 Int--- >>> mat--- Matrix (Z :. 4 :. 10)--- [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,--- 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,--- 2, 4, 6, 8, 10, 12, 14, 16, 18, 20,--- 1, 3, 5, 7, 9, 11, 13, 15, 17, 19]------ >>> all even (use mat)--- Vector (Z :. 4) [False,False,True,False]----all :: (Shape sh, Elt e)- => (Exp e -> Exp Bool)- -> Acc (Array (sh:.Int) e)- -> Acc (Array sh Bool)-all f = and . map f---- | Check if any element along the innermost dimension satisfies the predicate.------ >>> let mat = fromList (Z :. 4 :. 10) [1,2,3,4,5,6,7,8,9,10,1,1,1,1,1,2,2,2,2,2,2,4,6,8,10,12,14,16,18,20,1,3,5,7,9,11,13,15,17,19] :: Array DIM2 Int--- >>> mat--- Matrix (Z :. 4 :. 10)--- [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,--- 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,--- 2, 4, 6, 8, 10, 12, 14, 16, 18, 20,--- 1, 3, 5, 7, 9, 11, 13, 15, 17, 19]------ >>> any even (use mat)--- Vector (Z :. 4) [True,True,True,False]----any :: (Shape sh, Elt e)- => (Exp e -> Exp Bool)- -> Acc (Array (sh:.Int) e)- -> Acc (Array sh Bool)-any f = or . map f---- | Check if all elements along the innermost dimension are 'True'.----and :: Shape sh- => Acc (Array (sh:.Int) Bool)- -> Acc (Array sh Bool)-and = fold (&&) (constant True)---- | Check if any element along the innermost dimension is 'True'.----or :: Shape sh- => Acc (Array (sh:.Int) Bool)- -> Acc (Array sh Bool)-or = fold (||) (constant False)---- | Compute the sum of elements along the innermost dimension of the array. To--- find the sum of the entire array, 'flatten' it first.------ >>> let mat = fromList (Z:.2:.5) [0..]--- Vector (Z :. 2) [10,35]----sum :: (Shape sh, Num e)- => Acc (Array (sh:.Int) e)- -> Acc (Array sh e)-sum = fold (+) 0---- | Compute the product of the elements along the innermost dimension of the--- array. To find the product of the entire array, 'flatten' it first.------ >>> let mat = fromList (Z:.2:.5) [0..]--- Vector (Z :. 2) [0,15120]----product- :: (Shape sh, Num e)- => Acc (Array (sh:.Int) e)- -> Acc (Array sh e)-product = fold (*) 1---- | Yield the minimum element along the innermost dimension of the array. To--- find find the minimum element of the entire array, 'flatten' it first.------ The array must not be empty. See also 'fold1'.------ >>> let mat = fromList (Z :. 3 :. 4) [1,4,3,8, 0,2,8,4, 7,9,8,8]--- >>> mat--- Matrix (Z :. 3 :. 4)--- [ 1, 4, 3, 8,--- 0, 2, 8, 4,--- 7, 9, 8, 8]------ >>> minimum (use mat)--- Vector (Z :. 3) [1,0,7]----minimum- :: (Shape sh, Ord e)- => Acc (Array (sh:.Int) e)- -> Acc (Array sh e)-minimum = fold1 min---- | Yield the maximum element along the innermost dimension of the array. To--- find the maximum element of the entire array, 'flatten' it first.------ The array must not be empty. See also 'fold1'.------ >>> let mat = fromList (Z :. 3 :. 4) [1,4,3,8, 0,2,8,4, 7,9,8,8]--- >>> mat--- Matrix (Z :. 3 :. 4)--- [ 1, 4, 3, 8,--- 0, 2, 8, 4,--- 7, 9, 8, 8]------ >>> maximum (use mat)--- Vector (Z :. 3) [8,8,9]----maximum- :: (Shape sh, Ord e)- => Acc (Array (sh:.Int) e)- -> Acc (Array sh e)-maximum = fold1 max----- Composite scans--- ------------------- | Left-to-right pre-scan (aka exclusive scan). As for 'scan', the first--- argument must be an /associative/ function. Denotationally, we have:------ > prescanl f e = afst . scanl' f e------ >>> let vec = fromList (Z:.10) [1..10]--- >>> prescanl (+) 0 (use vec)--- Vector (Z :. 10) [0,1,3,6,10,15,21,28,36,45]----prescanl- :: (Shape sh, Elt a)- => (Exp a -> Exp a -> Exp a)- -> Exp a- -> Acc (Array (sh:.Int) a)- -> Acc (Array (sh:.Int) a)-prescanl f e = afst . scanl' f e---- | Left-to-right post-scan, a variant of 'scanl1' with an initial value. As--- with 'scanl1', the array must not be empty. Denotationally, we have:------ > postscanl f e = map (e `f`) . scanl1 f------ >>> let vec = fromList (Z:.10) [1..10]--- >>> postscanl (+) 42 (use vec)--- Vector (Z :. 10) [43,45,48,52,57,63,70,78,87,97]----postscanl- :: (Shape sh, Elt a)- => (Exp a -> Exp a -> Exp a)- -> Exp a- -> Acc (Array (sh:.Int) a)- -> Acc (Array (sh:.Int) a)-postscanl f e = map (e `f`) . scanl1 f---- | Right-to-left pre-scan (aka exclusive scan). As for 'scan', the first--- argument must be an /associative/ function. Denotationally, we have:------ > prescanr f e = afst . scanr' f e----prescanr- :: (Shape sh, Elt a)- => (Exp a -> Exp a -> Exp a)- -> Exp a- -> Acc (Array (sh:.Int) a)- -> Acc (Array (sh:.Int) a)-prescanr f e = afst . scanr' f e---- | Right-to-left postscan, a variant of 'scanr1' with an initial value.--- Denotationally, we have:------ > postscanr f e = map (e `f`) . scanr1 f----postscanr- :: (Shape sh, Elt a)- => (Exp a -> Exp a -> Exp a)- -> Exp a- -> Acc (Array (sh:.Int) a)- -> Acc (Array (sh:.Int) a)-postscanr f e = map (`f` e) . scanr1 f----- Segmented scans--- ------------------- | Segmented version of 'scanl' along the innermost dimension of an array. The--- innermost dimension must have at least as many elements as the sum of the--- segment descriptor.------ >>> let seg = fromList (Z:.4) [1,4,0,3]--- >>> seg--- Vector (Z :. 4) [1,4,0,3]------ >>> let mat = fromList (Z:.5:.10) [0..]--- >>> mat--- Matrix (Z :. 5 :. 10)--- [ 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]------ >>> scanlSeg (+) 0 (use mat) (use seg)--- Matrix (Z :. 5 :. 12)--- [ 0, 0, 0, 1, 3, 6, 10, 0, 0, 5, 11, 18,--- 0, 10, 0, 11, 23, 36, 50, 0, 0, 15, 31, 48,--- 0, 20, 0, 21, 43, 66, 90, 0, 0, 25, 51, 78,--- 0, 30, 0, 31, 63, 96, 130, 0, 0, 35, 71, 108,--- 0, 40, 0, 41, 83, 126, 170, 0, 0, 45, 91, 138]----scanlSeg- :: forall sh e i. (Shape sh, Slice sh, Elt e, Integral i, Bits i, FromIntegral i Int)- => (Exp e -> Exp e -> Exp e)- -> Exp e- -> Acc (Array (sh:.Int) e)- -> Acc (Segments i)- -> Acc (Array (sh:.Int) e)-scanlSeg f z arr seg =- if null arr || null flags- then fill (lift (sh:.sz + length seg)) z- else scanl1Seg f arr' seg'- where- sh :. sz = unlift (shape arr) :: Exp sh :. Exp Int-- -- Segmented exclusive scan is implemented by first injecting the seed- -- element at the head of each segment, and then performing a segmented- -- inclusive scan.- --- -- This is done by creating a creating a vector entirely of the seed- -- element, and overlaying the input data in all places other than at the- -- start of a segment.- --- seg' = map (+1) seg- arr' = permute const- (fill (lift (sh :. sz + length seg)) z)- (\ix -> let sx :. i = unlift ix :: Exp sh :. Exp Int- in lift (sx :. i + fromIntegral (inc ! index1 i)))- (take (length flags) arr)-- -- Each element in the segments must be shifted to the right one additional- -- place for each successive segment, to make room for the seed element.- -- Here, we make use of the fact that the vector returned by 'mkHeadFlags'- -- contains non-unit entries, which indicate zero length segments.- --- flags = mkHeadFlags seg- inc = scanl1 (+) flags----- | Segmented version of 'scanl'' along the innermost dimension of an array. The--- innermost dimension must have at least as many elements as the sum of the--- segment descriptor.------ The first element of the resulting tuple is a vector of scanned values. The--- second element is a vector of segment scan totals and has the same size as--- the segment vector.------ >>> let seg = fromList (Z:.4) [1,4,0,3]--- >>> seg--- Vector (Z :. 4) [1,4,0,3]------ >>> let mat = fromList (Z:.5:.10) [0..]--- >>> mat--- Matrix (Z :. 5 :. 10)--- [ 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]------ >>> let (res,sums) = scanl'Seg (+) 0 (use mat) (use seg)--- >>> res--- Matrix (Z :. 5 :. 8)--- [ 0, 0, 1, 3, 6, 0, 5, 11,--- 0, 0, 11, 23, 36, 0, 15, 31,--- 0, 0, 21, 43, 66, 0, 25, 51,--- 0, 0, 31, 63, 96, 0, 35, 71,--- 0, 0, 41, 83, 126, 0, 45, 91]--- >>> sums--- Matrix (Z :. 5 :. 4)--- [ 0, 10, 0, 18,--- 10, 50, 0, 48,--- 20, 90, 0, 78,--- 30, 130, 0, 108,--- 40, 170, 0, 138]----scanl'Seg- :: forall sh e i. (Shape sh, Slice sh, Elt e, Integral i, Bits i, FromIntegral i Int)- => (Exp e -> Exp e -> Exp e)- -> Exp e- -> Acc (Array (sh:.Int) e)- -> Acc (Segments i)- -> Acc (Array (sh:.Int) e, Array (sh:.Int) e)-scanl'Seg f z arr seg =- if null arr- then lift (arr, fill (lift (indexTail (shape arr) :. length seg)) z)- else lift (body, sums)- where- -- Segmented scan' is implemented by deconstructing a segmented exclusive- -- scan, to separate the final value and scan body.- --- -- TLM: Segmented scans, and this version in particular, expend a lot of- -- effort scanning flag arrays. On inspection it appears that several- -- of these operations are duplicated, but this will not be picked up- -- by sharing _observation_. Perhaps a global CSE-style pass would be- -- beneficial.- --- arr' = scanlSeg f z arr seg-- -- Extract the final reduction value for each segment, which is at the last- -- index of each segment.- --- seg' = map (+1) seg- tails = zipWith (+) seg $ prescanl (+) 0 seg'- sums = backpermute- (lift (indexTail (shape arr') :. length seg))- (\ix -> let sz:.i = unlift ix :: Exp sh :. Exp Int- in lift (sz :. fromIntegral (tails ! index1 i)))- arr'-- -- Slice out the body of each segment.- --- -- Build a head-flags representation based on the original segment- -- descriptor. This contains the target length of each of the body segments,- -- which is one fewer element than the actual bodies stored in arr'. Thus,- -- the flags align with the last element of each body section, and when- -- scanned, this element will be incremented over.- --- offset = scanl1 (+) seg- inc = scanl1 (+)- $ permute (+) (fill (index1 $ size arr + 1) 0)- (\ix -> index1' $ offset ! ix)- (fill (shape seg) (1 :: Exp i))-- len = offset ! index1 (length offset - 1)- body = backpermute- (lift (indexTail (shape arr) :. fromIntegral len))- (\ix -> let sz:.i = unlift ix :: Exp sh :. Exp Int- in lift (sz :. i + fromIntegral (inc ! index1 i)))- arr'----- | Segmented version of 'scanl1' along the innermost dimension.------ As with 'scanl1', the total number of elements considered, in this case given--- by the 'sum' of segment descriptor, must not be zero. The input vector must--- contain at least this many elements.------ Zero length segments are allowed, and the behaviour is as if those entries--- were not present in the segment descriptor; that is:------ > scanl1Seg f xs [n,0,0] == scanl1Seg f xs [n] where n /= 0------ >>> let seg = fromList (Z:.4) [1,4,0,3]--- >>> seg--- Vector (Z :. 4) [1,4,0,3]------ >>> let mat = fromList (Z:.5:.10) [0..]--- >>> mat--- Matrix (Z :. 5 :. 10)--- [ 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]------ >>> scanl1Seg (+) (use mat) (use seg)--- Matrix (Z :. 5 :. 8)--- [ 0, 1, 3, 6, 10, 5, 11, 18,--- 10, 11, 23, 36, 50, 15, 31, 48,--- 20, 21, 43, 66, 90, 25, 51, 78,--- 30, 31, 63, 96, 130, 35, 71, 108,--- 40, 41, 83, 126, 170, 45, 91, 138]----scanl1Seg- :: (Shape sh, Slice sh, Elt e, Integral i, Bits i, FromIntegral i Int)- => (Exp e -> Exp e -> Exp e)- -> Acc (Array (sh:.Int) e)- -> Acc (Segments i)- -> Acc (Array (sh:.Int) e)-scanl1Seg f arr seg- = map snd- . scanl1 (segmented f)- $ zip (replicate (lift (indexTail (shape arr) :. All)) (mkHeadFlags seg)) arr---- |Segmented version of 'prescanl'.----prescanlSeg- :: (Shape sh, Slice sh, Elt e, Integral i, Bits i, FromIntegral i Int)- => (Exp e -> Exp e -> Exp e)- -> Exp e- -> Acc (Array (sh:.Int) e)- -> Acc (Segments i)- -> Acc (Array (sh:.Int) e)-prescanlSeg f e vec seg- = afst- $ scanl'Seg f e vec seg---- |Segmented version of 'postscanl'.----postscanlSeg- :: (Shape sh, Slice sh, Elt e, Integral i, Bits i, FromIntegral i Int)- => (Exp e -> Exp e -> Exp e)- -> Exp e- -> Acc (Array (sh:.Int) e)- -> Acc (Segments i)- -> Acc (Array (sh:.Int) e)-postscanlSeg f e vec seg- = map (f e)- $ scanl1Seg f vec seg---- | Segmented version of 'scanr' along the innermost dimension of an array. The--- innermost dimension must have at least as many elements as the sum of the--- segment descriptor.------ >>> let seg = fromList (Z:.4) [1,4,0,3]--- >>> seg--- Vector (Z :. 4) [1,4,0,3]------ >>> let mat = fromList (Z:.5:.10) [0..]--- >>> mat--- Matrix (Z :. 5 :. 10)--- [ 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]------ >>> scanrSeg (+) 0 (use mat) (use seg)--- Matrix (Z :. 5 :. 12)--- [ 2, 0, 18, 15, 11, 6, 0, 0, 24, 17, 9, 0,--- 12, 0, 58, 45, 31, 16, 0, 0, 54, 37, 19, 0,--- 22, 0, 98, 75, 51, 26, 0, 0, 84, 57, 29, 0,--- 32, 0, 138, 105, 71, 36, 0, 0, 114, 77, 39, 0,--- 42, 0, 178, 135, 91, 46, 0, 0, 144, 97, 49, 0]----scanrSeg- :: forall sh e i. (Shape sh, Slice sh, Elt e, Integral i, Bits i, FromIntegral i Int)- => (Exp e -> Exp e -> Exp e)- -> Exp e- -> Acc (Array (sh:.Int) e)- -> Acc (Segments i)- -> Acc (Array (sh:.Int) e)-scanrSeg f z arr seg =- if null arr || null flags- then fill (lift (sh :. sz + length seg)) z- else scanr1Seg f arr' seg'- where- sh :. sz = unlift (shape arr) :: Exp sh :. Exp Int-- -- Using technique described for 'scanlSeg', where we intersperse the array- -- with the seed element at the start of each segment, and then perform an- -- inclusive segmented scan.- --- flags = mkHeadFlags seg- inc = scanl1 (+) flags-- seg' = map (+1) seg- arr' = permute const- (fill (lift (sh :. sz + length seg)) z)- (\ix -> let sx :. i = unlift ix :: Exp sh :. Exp Int- in lift (sx :. i + fromIntegral (inc ! index1 i) - 1))- (drop (sz - length flags) arr)----- | Segmented version of 'scanr''.------ >>> let seg = fromList (Z:.4) [1,4,0,3]--- >>> seg--- Vector (Z :. 4) [1,4,0,3]------ >>> let mat = fromList (Z:.5:.10) [0..]--- >>> mat--- Matrix (Z :. 5 :. 10)--- [ 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]------ >>> let (res,sums) = scanr'Seg (+) 0 (use mat) (use seg)--- >>> res--- Matrix (Z :. 5 :. 8)--- [ 0, 15, 11, 6, 0, 17, 9, 0,--- 0, 45, 31, 16, 0, 37, 19, 0,--- 0, 75, 51, 26, 0, 57, 29, 0,--- 0, 105, 71, 36, 0, 77, 39, 0,--- 0, 135, 91, 46, 0, 97, 49, 0]--- >>> sums--- Matrix (Z :. 5 :. 4)--- [ 2, 18, 0, 24,--- 12, 58, 0, 54,--- 22, 98, 0, 84,--- 32, 138, 0, 114,--- 42, 178, 0, 144]----scanr'Seg- :: forall sh e i. (Shape sh, Slice sh, Elt e, Integral i, Bits i, FromIntegral i Int)- => (Exp e -> Exp e -> Exp e)- -> Exp e- -> Acc (Array (sh:.Int) e)- -> Acc (Segments i)- -> Acc (Array (sh:.Int) e, Array (sh:.Int) e)-scanr'Seg f z arr seg =- if null arr- then lift (arr, fill (lift (indexTail (shape arr) :. length seg)) z)- else lift (body, sums)- where- -- Using technique described for scanl'Seg- --- arr' = scanrSeg f z arr seg-- -- reduction values- seg' = map (+1) seg- heads = prescanl (+) 0 seg'- sums = backpermute- (lift (indexTail (shape arr') :. length seg))- (\ix -> let sz:.i = unlift ix :: Exp sh :. Exp Int- in lift (sz :. fromIntegral (heads ! index1 i)))- arr'-- -- body segments- flags = mkHeadFlags seg- inc = scanl1 (+) flags- body = backpermute- (lift (indexTail (shape arr) :. indexHead (shape flags)))- (\ix -> let sz:.i = unlift ix :: Exp sh :. Exp Int- in lift (sz :. i + fromIntegral (inc ! index1 i)))- arr'----- | Segmented version of 'scanr1'.------ >>> let seg = fromList (Z:.4) [1,4,0,3]--- >>> seg--- Vector (Z :. 4) [1,4,0,3]------ >>> let mat = fromList (Z:.5:.10) [0..]--- >>> mat--- Matrix (Z :. 5 :. 10)--- [ 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]------ >>> scanr1Seg (+) (use mat) (use seg)--- Matrix (Z :. 5 :. 8)--- [ 0, 10, 9, 7, 4, 18, 13, 7,--- 10, 50, 39, 27, 14, 48, 33, 17,--- 20, 90, 69, 47, 24, 78, 53, 27,--- 30, 130, 99, 67, 34, 108, 73, 37,--- 40, 170, 129, 87, 44, 138, 93, 47]----scanr1Seg- :: (Shape sh, Slice sh, Elt e, Integral i, Bits i, FromIntegral i Int)- => (Exp e -> Exp e -> Exp e)- -> Acc (Array (sh:.Int) e)- -> Acc (Segments i)- -> Acc (Array (sh:.Int) e)-scanr1Seg f arr seg- = map snd- . scanr1 (flip (segmented f))- $ zip (replicate (lift (indexTail (shape arr) :. All)) (mkTailFlags seg)) arr----- |Segmented version of 'prescanr'.----prescanrSeg- :: (Shape sh, Slice sh, Elt e, Integral i, Bits i, FromIntegral i Int)- => (Exp e -> Exp e -> Exp e)- -> Exp e- -> Acc (Array (sh:.Int) e)- -> Acc (Segments i)- -> Acc (Array (sh:.Int) e)-prescanrSeg f e vec seg- = afst- $ scanr'Seg f e vec seg---- |Segmented version of 'postscanr'.----postscanrSeg- :: (Shape sh, Slice sh, Elt e, Integral i, Bits i, FromIntegral i Int)- => (Exp e -> Exp e -> Exp e)- -> Exp e- -> Acc (Array (sh:.Int) e)- -> Acc (Segments i)- -> Acc (Array (sh:.Int) e)-postscanrSeg f e vec seg- = map (f e)- $ scanr1Seg f vec seg----- Segmented scan helpers--- -------------------------- |Compute head flags vector from segment vector for left-scans.------ The vector will be full of zeros in the body of a segment, and non-zero--- otherwise. The "flag" value, if greater than one, indicates that several--- empty segments are represented by this single flag entry. This is additional--- data is used by exclusive segmented scan.----mkHeadFlags- :: (Integral i, FromIntegral i Int)- => Acc (Segments i)- -> Acc (Segments i)-mkHeadFlags seg- = init- $ permute (+) zeros (\ix -> index1' (offset ! ix)) ones- where- (offset, len) = unlift (scanl' (+) 0 seg)- zeros = fill (index1' $ the len + 1) 0- ones = fill (index1 $ size offset) 1---- |Compute tail flags vector from segment vector for right-scans. That is, the--- flag is placed at the last place in each segment.----mkTailFlags- :: (Integral i, FromIntegral i Int)- => Acc (Segments i)- -> Acc (Segments i)-mkTailFlags seg- = init- $ permute (+) zeros (\ix -> index1' (the len - 1 - offset ! ix)) ones- where- (offset, len) = unlift (scanr' (+) 0 seg)- zeros = fill (index1' $ the len + 1) 0- ones = fill (index1 $ size offset) 1---- |Construct a segmented version of a function from a non-segmented version.--- The segmented apply operates on a head-flag value tuple, and follows the--- procedure of Sengupta et. al.----segmented- :: (Elt e, Num i, Bits i)- => (Exp e -> Exp e -> Exp e)- -> Exp (i, e)- -> Exp (i, e)- -> Exp (i, e)-segmented f a b =- let (aF, aV) = unlift a- (bF, bV) = unlift b- in- lift (aF .|. bF, bF /= 0 ? (bV, f aV bV))---- |Index construction and destruction generalised to integral types.------ We generalise the segment descriptor to integral types because some--- architectures, such as GPUs, have poor performance for 64-bit types. So,--- there is a tension between performance and requiring 64-bit indices for some--- applications, and we would not like to restrict ourselves to either one.------ As we don't yet support non-Int dimensions in shapes, we will need to convert--- back to concrete Int. However, don't put these generalised forms into the--- base library, because it results in too many ambiguity errors.----index1' :: (Integral i, FromIntegral i Int) => Exp i -> Exp DIM1-index1' i = lift (Z :. fromIntegral i)----- Reshaping of arrays--- ----------------------- | Flatten the given array of arbitrary dimension into a one-dimensional--- vector. As with 'reshape', this operation performs no work.----flatten :: forall sh e. (Shape sh, Elt e) => Acc (Array sh e) -> Acc (Vector e)-flatten a- | Just Refl <- matchShapeType (undefined::sh) (undefined::DIM1)- = a-flatten a- = reshape (index1 (size a)) a----- Enumeration and filling--- --------------------------- | Create an array where all elements are the same value.------ >>> let zeros = fill (Z:.10) 0--- Vector (Z :. 10) [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0]----fill :: (Shape sh, Elt e) => Exp sh -> Exp e -> Acc (Array sh e)-fill sh c = generate sh (const c)---- | Create an array of the given shape containing the values @x@, @x+1@, etc.--- (in row-major order).------ >>> enumFromN (constant (Z:.5:.10)) 0 :: Array DIM2 Int--- Matrix (Z :. 5 :. 10)--- [ 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]----enumFromN- :: (Shape sh, Num e, FromIntegral Int e)- => Exp sh- -> Exp e- -> Acc (Array sh e)-enumFromN sh x = enumFromStepN sh x 1---- | Create an array of the given shape containing the values @x@, @x+y@,--- @x+y+y@ etc. (in row-major order).------ >>> enumFromStepN (constant (Z:.5:.10)) 0 0.5 :: Array DIM2 Float--- Matrix (Z :. 5 :. 10)--- [ 0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5,--- 5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5,--- 10.0, 10.5, 11.0, 11.5, 12.0, 12.5, 13.0, 13.5, 14.0, 14.5,--- 15.0, 15.5, 16.0, 16.5, 17.0, 17.5, 18.0, 18.5, 19.0, 19.5,--- 20.0, 20.5, 21.0, 21.5, 22.0, 22.5, 23.0, 23.5, 24.0, 24.5]----enumFromStepN- :: (Shape sh, Num e, FromIntegral Int e)- => Exp sh- -> Exp e -- ^ x: start- -> Exp e -- ^ y: step- -> Acc (Array sh e)-enumFromStepN sh x y- = reshape sh- $ generate (index1 $ shapeSize sh)- (\ix -> (fromIntegral (unindex1 ix :: Exp Int) * y) + x)---- Concatenation--- ----------------- | Concatenate innermost component of two arrays. The extent of the lower--- dimensional component is the intersection of the two arrays.------ >>> let m1 = fromList (Z:.5:.10) [0..]--- >>> m1--- Matrix (Z :. 5 :. 10)--- [ 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]------ >>> let m2 = fromList (Z:.10:.3) [0..]--- >>> m2--- Matrix (Z :. 10 :. 3)--- [ 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]------ >>> use m1 ++ use m2--- Matrix (Z :. 5 :. 13)--- [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2,--- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 3, 4, 5,--- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 6, 7, 8,--- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 9, 10, 11,--- 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 12, 13, 14]----infixr 5 ++-(++) :: forall sh e. (Slice sh, Shape sh, Elt e)- => Acc (Array (sh :. Int) e)- -> Acc (Array (sh :. Int) e)- -> Acc (Array (sh :. Int) e)-(++) xs ys- = let sh1 :. n = unlift (shape xs) :: Exp sh :. Exp Int- sh2 :. m = unlift (shape ys) :: Exp sh :. Exp Int- in- generate (lift (intersect sh1 sh2 :. n + m))- (\ix -> let sh :. i = unlift ix :: Exp sh :. Exp Int- in i < n ? ( xs ! ix, ys ! lift (sh :. i-n)) )---- TLM: If we have something like (concat . split) then the source array will--- have two use sites, but is actually safe (and better) to inline.----- Filtering--- ------------- | Drop elements that do not satisfy the predicate. Returns the elements which--- pass the predicate, together with a segment descriptor indicating how many--- elements along each outer dimension were valid.------ >>> let vec = fromList (Z :. 10) [1..10] :: Vector Int--- >>> vec--- Vector (Z :. 10) [1,2,3,4,5,6,7,8,9,10]------ >>> filter even (use vec)--- (Vector (Z :. 5) [2,4,6,8,10], Scalar Z [5])------ >>> let mat = fromList (Z :. 4 :. 10) [1,2,3,4,5,6,7,8,9,10,1,1,1,1,1,2,2,2,2,2,2,4,6,8,10,12,14,16,18,20,1,3,5,7,9,11,13,15,17,19] :: Array DIM2 Int--- >>> mat--- Matrix (Z :. 4 :. 10)--- [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,--- 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,--- 2, 4, 6, 8, 10, 12, 14, 16, 18, 20,--- 1, 3, 5, 7, 9, 11, 13, 15, 17, 19]------ >>> filter odd (use mat)--- (Vector (Z :. 20) [1,3,5,7,9,1,1,1,1,1,1,3,5,7,9,11,13,15,17,19], Vector (Z :. 4) [5,5,0,10])----filter :: forall sh e. (Shape sh, Slice sh, Elt e)- => (Exp e -> Exp Bool)- -> Acc (Array (sh:.Int) e)- -> Acc (Vector e, Array sh Int)-filter p arr- -- Optimise 1-dimensional arrays, where we can avoid additional computations- -- for the offset indices.- | Just Refl <- matchShapeType (undefined::sh) (undefined::Z)- = let- keep = map p arr- (target, len) = unlift $ scanl' (+) 0 (map boolToInt keep)- prj ix = keep!ix ? ( index1 (target!ix), ignore )- dummy = backpermute (index1 (the len)) id arr- result = permute const dummy prj arr- in- if null arr- then lift (emptyArray, fill (constant Z) 0)- else lift (result, len)--filter p arr- = let- sz = indexTail (shape arr)- keep = map p arr- (target, len) = unlift $ scanl' (+) 0 (map boolToInt keep)- (offset, valid) = unlift $ scanl' (+) 0 (flatten len)- prj ix = if keep!ix- then index1 $ offset!index1 (toIndex sz (indexTail ix)) + target!ix- else ignore- dummy = backpermute (index1 (the valid)) id (flatten arr)- result = permute const dummy prj arr- in- if null arr- then lift (emptyArray, fill sz 0)- else lift (result, len)---- FIXME: [Permute in the filter operation]------ This is abusing 'permute' in that the first two arguments, the combination--- function and array of default values, are only justified because we know the--- permutation function will write to each location in the target exactly once.------ Instead, we should have a primitive that directly encodes the compaction--- pattern of the permutation function. This may be more efficient to compute,--- and avoids the computation of the defaults array, which is ultimately wasted--- work.-----{-# NOINLINE filter #-}-{-# RULES- "ACC filter/filter" forall f g arr.- filter f (afst (filter g arr)) = filter (\x -> g x && f x) arr- #-}----- Gather operations--- --------------------- | Gather elements from a source array by reading values at the given indices.------ >>> let input = fromList (Z:.9) [1,9,6,4,4,2,0,1,2]--- >>> let from = fromList (Z:.6) [1,3,7,2,5,3]--- >>> gather (use from) (use input)--- Vector (Z :. 6) [9,4,1,6,2,4]----gather- :: (Shape sh, Elt e)- => Acc (Array sh Int) -- ^ index of source at each index to gather- -> Acc (Vector e) -- ^ source values- -> Acc (Array sh e)-gather indices input = map (input !!) indices- -- TLM NOTES:- -- * (!!) has potential for later optimisation- -- * We needn't fix the source array to Vector, but this matches the- -- intuition that 'Int' ~ 'DIM1'.----- | Conditionally copy elements from source array to destination array--- according to an index mapping.------ In addition, the 'mask' vector and associated predication function specifies--- whether the element is copied or a default value is used instead.------ >>> let defaults = fromList (Z :. 6) [6,6,6,6,6,6]--- >>> let from = fromList (Z :. 6) [1,3,7,2,5,3]--- >>> let mask = fromList (Z :. 6) [3,4,9,2,7,5]--- >>> let input = fromList (Z :. 9) [1,9,6,4,4,2,0,1,2]--- >>> gatherIf (use from) (use mask) (> 4) (use defaults) (use input)--- Vector (Z :. 6) [6,6,1,6,2,4]----gatherIf- :: (Elt a, Elt b)- => Acc (Vector Int) -- ^ source indices to gather from- -> Acc (Vector a) -- ^ mask vector- -> (Exp a -> Exp Bool) -- ^ predicate function- -> Acc (Vector b) -- ^ default values- -> Acc (Vector b) -- ^ source values- -> Acc (Vector b)-gatherIf from maskV pred defaults input = zipWith zf pf gatheredV- where- zf p g = p ? (unlift g)- gatheredV = zip (gather from input) defaults- pf = map pred maskV----- Scatter operations--- ---------------------- | Overwrite elements of the destination by scattering the values of the--- source array according to the given index mapping.------ Note that if the destination index appears more than once in the mapping the--- result is undefined.------ >>> let to = fromList (Z :. 6) [1,3,7,2,5,8]--- >>> let input = fromList (Z :. 7) [1,9,6,4,4,2,5]--- >>> scatter (use to) (fill (constant (Z:.10)) 0) (use input)--- Vector (Z :. 10) [0,1,4,9,0,4,0,6,2,0]----scatter- :: Elt e- => Acc (Vector Int) -- ^ destination indices to scatter into- -> Acc (Vector e) -- ^ default values- -> Acc (Vector e) -- ^ source values- -> Acc (Vector e)-scatter to defaults input = permute const defaults pf input'- where- pf ix = index1 (to ! ix)- input' = backpermute (shape to `intersect` shape input) id input----- | Conditionally overwrite elements of the destination by scattering values of--- the source array according to a given index mapping, whenever the masking--- function resolves to 'True'.------ Note that if the destination index appears more than once in the mapping the--- result is undefined.------ >>> let to = fromList (Z :. 6) [1,3,7,2,5,8]--- >>> let mask = fromList (Z :. 6) [3,4,9,2,7,5]--- >>> let input = fromList (Z :. 7) [1,9,6,4,4,2,5]--- >>> scatterIf (use to) (use mask) (> 4) (fill (constant (Z:.10)) 0) (use input)--- Vector (Z :. 10) [0,0,0,0,0,4,0,6,2,0]----scatterIf- :: (Elt e, Elt e')- => Acc (Vector Int) -- ^ destination indices to scatter into- -> Acc (Vector e) -- ^ mask vector- -> (Exp e -> Exp Bool) -- ^ predicate function- -> Acc (Vector e') -- ^ default values- -> Acc (Vector e') -- ^ source values- -> Acc (Vector e')-scatterIf to maskV pred defaults input = permute const defaults pf input'- where- pf ix = pred (maskV ! ix) ? ( index1 (to ! ix), ignore )- input' = backpermute (shape to `intersect` shape input) id input----- Permutations--- ---------------- | Reverse the elements of a vector.----reverse :: Elt e => Acc (Vector e) -> Acc (Vector e)-reverse xs =- let len = unindex1 (shape xs)- pf i = len - i - 1- in backpermute (shape xs) (ilift1 pf) xs---- | Transpose the rows and columns of a matrix.----transpose :: Elt e => Acc (Array DIM2 e) -> Acc (Array DIM2 e)-transpose mat =- let swap = lift1 $ \(Z:.x:.y) -> Z:.y:.x :: Z:.Exp Int:.Exp Int- in backpermute (swap $ shape mat) swap mat----- Extracting sub-vectors--- -------------------------- | Yield the first @n@ elements in the innermost dimension of the array (plus--- all lower dimensional elements).------ >>> let mat = fromList (Z:.5:.10) [0..]--- >>> mat--- Matrix (Z :. 5 :. 10)--- [ 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]------ >>> take 5 (use mat)--- Matrix (Z :. 5 :. 5)--- [ 0, 1, 2, 3, 4,--- 10, 11, 12, 13, 14,--- 20, 21, 22, 23, 24,--- 30, 31, 32, 33, 34,--- 40, 41, 42, 43, 44]----take :: forall sh e. (Slice sh, Shape sh, Elt e)- => Exp Int- -> Acc (Array (sh :. Int) e)- -> Acc (Array (sh :. Int) e)-take n acc =- let n' = the (unit (n `min` sz))- sh :. sz = unlift (shape acc) :: Exp sh :. Exp Int- in- backpermute (lift (sh :. n')) id acc----- | Yield all but the first @n@ elements along the innermost dimension of the--- array (plus all lower dimensional elements).------ >>> let mat = fromList (Z:.5:.10) [0..]--- >>> mat--- Matrix (Z :. 5 :. 10)--- [ 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]------ >>> drop 7 (use mat)--- Matrix (Z :. 5 :. 3)--- [ 7, 8, 9,--- 17, 18, 19,--- 27, 28, 29,--- 37, 38, 39,--- 47, 48, 49]----drop :: forall sh e. (Slice sh, Shape sh, Elt e)- => Exp Int- -> Acc (Array (sh :. Int) e)- -> Acc (Array (sh :. Int) e)-drop n acc =- let n' = the (unit n)- sh :. sz = unlift (shape acc) :: Exp sh :. Exp Int- index ix = let j :. i = unlift ix :: Exp sh :. Exp Int- in lift (j :. i + n')- in- backpermute (lift (sh :. 0 `max` (sz - n'))) index acc----- | Yield all but the elements in the last index of the innermost dimension.------ >>> let mat = fromList (Z:.5:.10) [0..]--- >>> mat--- Matrix (Z :. 5 :. 10)--- [ 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]------ >>> init (use mat)--- Matrix (Z :. 5 :. 9)--- [ 0, 1, 2, 3, 4, 5, 6, 7, 8,--- 10, 11, 12, 13, 14, 15, 16, 17, 18,--- 20, 21, 22, 23, 24, 25, 26, 27, 28,--- 30, 31, 32, 33, 34, 35, 36, 37, 38,--- 40, 41, 42, 43, 44, 45, 46, 47, 48]----init :: forall sh e. (Slice sh, Shape sh, Elt e)- => Acc (Array (sh :. Int) e)- -> Acc (Array (sh :. Int) e)-init acc =- let sh :. sz = unlift (shape acc) :: Exp sh :. Exp Int- in backpermute (lift (sh :. sz `min` (sz - 1))) id acc----- | Yield all but the first element along the innermost dimension of an array.--- The innermost dimension must not be empty.------ >>> let mat = fromList (Z:.5:.10) [0..]--- >>> mat--- Matrix (Z :. 5 :. 10)--- [ 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]------ >>> tail (use mat)--- Matrix (Z :. 5 :. 9)--- [ 1, 2, 3, 4, 5, 6, 7, 8, 9,--- 11, 12, 13, 14, 15, 16, 17, 18, 19,--- 21, 22, 23, 24, 25, 26, 27, 28, 29,--- 31, 32, 33, 34, 35, 36, 37, 38, 39,--- 41, 42, 43, 44, 45, 46, 47, 48, 49]----tail :: forall sh e. (Slice sh, Shape sh, Elt e)- => Acc (Array (sh :. Int) e)- -> Acc (Array (sh :. Int) e)-tail acc =- let sh :. sz = unlift (shape acc) :: Exp sh :. Exp Int- index ix = let j :. i = unlift ix :: Exp sh :. Exp Int- in lift (j :. i + 1)- in- backpermute (lift (sh :. 0 `max` (sz - 1))) index acc----- | Yield a slit (slice) of the innermost indices of an array. Denotationally,--- we have:------ > slit i n = take n . drop i----slit :: forall sh e. (Slice sh, Shape sh, Elt e)- => Exp Int- -> Exp Int- -> Acc (Array (sh :. Int) e)- -> Acc (Array (sh :. Int) e)-slit m n acc =- let m' = the (unit m)- n' = the (unit n)- sh :. sz = unlift (shape acc) :: Exp sh :. Exp Int- index ix = let j :. i = unlift ix :: Exp sh :. Exp Int- in lift (j :. i + m')- in- backpermute (lift (sh :. (n' `min` ((sz - m') `max` 0)))) index acc----- Controlling execution--- ------------------------- | Force an array expression to be evaluated, preventing it from fusing with--- other operations. Forcing operations to be computed to memory, rather than--- being fused into their consuming function, can sometimes improve performance.--- For example, computing a matrix 'transpose' could provide better memory--- locality for the subsequent operation. Preventing fusion to split large--- operations into several simpler steps could also help by reducing register--- pressure.------ Preventing fusion also means that the individual operations are available to--- be executed concurrently with other kernels. In particular, consider using--- this if you have a series of operations that are compute bound rather than--- memory bound.------ Here is the synthetic example:------ > loop :: Exp Int -> Exp Int--- > loop ticks =--- > let clockRate = 900000 -- kHz--- > in while (\i -> i < clockRate * ticks) (+1) 0--- >--- > test :: Acc (Vector Int)--- > test =--- > zip3--- > (compute $ map loop (use $ fromList (Z:.1) [10]))--- > (compute $ map loop (use $ fromList (Z:.1) [10]))--- > (compute $ map loop (use $ fromList (Z:.1) [10]))--- >------ Without the use of 'compute', the operations are fused together and the three--- long-running loops are executed sequentially in a single kernel. Instead, the--- individual operations can now be executed concurrently, potentially reducing--- overall runtime.----compute :: Arrays a => Acc a -> Acc a-compute = id >-> id----- Flow control--- ---------------- | Infix version of 'acond'. If the predicate evaluates to 'True', the first--- component of the tuple is returned, else the second.------ Enabling the @RebindableSyntax@ extension will allow you to use the standard--- if-then-else syntax instead.----infix 0 ?|-(?|) :: Arrays a => Exp Bool -> (Acc a, Acc a) -> Acc a-c ?| (t, e) = acond c t e---- | An infix version of 'cond'. If the predicate evaluates to 'True', the first--- component of the tuple is returned, else the second.------ Enabling the @RebindableSyntax@ extension will allow you to use the standard--- if-then-else syntax instead.----infix 0 ?-(?) :: Elt t => Exp Bool -> (Exp t, Exp t) -> Exp t-c ? (t, e) = cond c t e---- | A case-like control structure----caseof :: (Elt a, Elt b)- => Exp a -- ^ case subject- -> [(Exp a -> Exp Bool, Exp b)] -- ^ list of cases to attempt- -> Exp b -- ^ default value- -> Exp b-caseof _ [] e = e-caseof x ((p,b):l) e = cond (p x) b (caseof x l e)----- | For use with @-XRebindableSyntax@, this class provides 'ifThenElse' lifted--- to both scalar and array types.----class IfThenElse t where- type EltT t a :: Constraint- ifThenElse :: EltT t a => Exp Bool -> t a -> t a -> t a--instance IfThenElse Exp where- type EltT Exp t = Elt t- ifThenElse = cond--instance IfThenElse Acc where- type EltT Acc a = Arrays a- ifThenElse = acond----- Scalar iteration--- -------------------- | Repeatedly apply a function a fixed number of times----iterate- :: forall a. Elt a- => Exp Int- -> (Exp a -> Exp a)- -> Exp a- -> Exp a-iterate n f z- = let step :: (Exp Int, Exp a) -> (Exp Int, Exp a)- step (i, acc) = ( i+1, f acc )- in- snd $ while (\v -> fst v < n) (lift1 step) (lift (constant 0, z))----- Scalar bulk operations--- -------------------------- | Reduce along an innermost slice of an array /sequentially/, by applying a--- binary operator to a starting value and the array from left to right.----sfoldl :: forall sh a b. (Shape sh, Slice sh, Elt a, Elt b)- => (Exp a -> Exp b -> Exp a)- -> Exp a- -> Exp sh- -> Acc (Array (sh :. Int) b)- -> Exp a-sfoldl f z ix xs- = let step :: (Exp Int, Exp a) -> (Exp Int, Exp a)- step (i, acc) = ( i+1, acc `f` (xs ! lift (ix :. i)) )- (_ :. n) = unlift (shape xs) :: Exp sh :. Exp Int- in- snd $ while (\v -> fst v < n) (lift1 step) (lift (constant 0, z))----- Tuples--- ---------- |Extract the first component of a scalar pair.----fst :: forall a b. (Elt a, Elt b) => Exp (a, b) -> Exp a-fst e = let (x, _::Exp b) = unlift e in x---- |Extract the first component of an array pair.-{-# NOINLINE[1] afst #-}-afst :: forall a b. (Arrays a, Arrays b) => Acc (a, b) -> Acc a-afst a = let (x, _::Acc b) = unlift a in x---- |Extract the second component of a scalar pair.----snd :: forall a b. (Elt a, Elt b) => Exp (a, b) -> Exp b-snd e = let (_:: Exp a, y) = unlift e in y---- | Extract the second component of an array pair-asnd :: forall a b. (Arrays a, Arrays b) => Acc (a, b) -> Acc b-asnd a = let (_::Acc a, y) = unlift a in y---- |Converts an uncurried function to a curried function.----curry :: Lift f (f a, f b) => (f (Plain (f a), Plain (f b)) -> f c) -> f a -> f b -> f c-curry f x y = f (lift (x, y))---- |Converts a curried function to a function on pairs.----uncurry :: Unlift f (f a, f b) => (f a -> f b -> f c) -> f (Plain (f a), Plain (f b)) -> f c-uncurry f t = let (x, y) = unlift t in f x y----- Shapes and indices--- ---------------------- | The one index for a rank-0 array.----index0 :: Exp Z-index0 = lift Z---- | Turn an 'Int' expression into a rank-1 indexing expression.----index1 :: Elt i => Exp i -> Exp (Z :. i)-index1 i = lift (Z :. i)---- | Turn a rank-1 indexing expression into an 'Int' expression.----unindex1 :: Elt i => Exp (Z :. i) -> Exp i-unindex1 ix = let Z :. i = unlift ix in i---- | Creates a rank-2 index from two Exp Int`s----index2- :: (Elt i, Slice (Z :. i))- => Exp i- -> Exp i- -> Exp (Z :. i :. i)-index2 i j = lift (Z :. i :. j)---- | Destructs a rank-2 index to an Exp tuple of two Int`s.----unindex2- :: forall i. (Elt i, Slice (Z :. i))- => Exp (Z :. i :. i)- -> Exp (i, i)-unindex2 ix- = let Z :. i :. j = unlift ix :: Z :. Exp i :. Exp i- in lift (i, j)---- | Create a rank-3 index from three Exp Int`s----index3- :: (Elt i, Slice (Z :. i), Slice (Z :. i :. i))- => Exp i- -> Exp i- -> Exp i- -> Exp (Z :. i :. i :. i)-index3 k j i = lift (Z :. k :. j :. i)---- | Destruct a rank-3 index into an Exp tuple of Int`s-unindex3- :: forall i. (Elt i, Slice (Z :. i), Slice (Z :. i :. i))- => Exp (Z :. i :. i :. i)- -> Exp (i, i, i)-unindex3 ix = let Z :. k :. j :. i = unlift ix :: Z :. Exp i :. Exp i :. Exp i- in lift (k, j, i)----- Array operations with a scalar result--- ----------------------------------------- | Extract the element of a singleton array.------ > the xs == xs ! Z----the :: Elt e => Acc (Scalar e) -> Exp e-the = (!index0)---- | Test whether an array is empty.----null :: (Shape sh, Elt e) => Acc (Array sh e) -> Exp Bool-null arr = size arr == 0---- | Get the length of a vector.----length :: Elt e => Acc (Vector e) -> Exp Int-length = unindex1 . shape---{----- Sequence operations--- ------------------------------------------ | Reduce a sequence by appending all the shapes and all the elements in two--- separate vectors.----fromSeq :: (Shape sh, Elt a) => Seq [Array sh a] -> Seq (Vector sh, Vector a)-fromSeq = foldSeqFlatten f (lift (emptyArray, emptyArray))- where- f x sh1 a1 =- let (sh0, a0) = unlift x- in lift (sh0 ++ sh1, a0 ++ a1)---fromSeqElems :: (Shape sh, Elt a) => Seq [Array sh a] -> Seq (Vector a)-fromSeqElems = foldSeqFlatten f emptyArray- where- f a0 _ a1 = a0 ++ a1--fromSeqShapes :: (Shape sh, Elt a) => Seq [Array sh a] -> Seq (Vector sh)-fromSeqShapes = foldSeqFlatten f emptyArray- where- f sh0 sh1 _ = sh0 ++ sh1---- | Sequence an array on the innermost dimension.----toSeqInner :: (Shape sh, Elt a) => Acc (Array (sh :. Int) a) -> Seq [Array sh a]-toSeqInner a = toSeq (Any :. Split) a---- | Sequence a 2-dimensional array on the outermost dimension.----toSeqOuter2 :: Elt a => Acc (Array DIM2 a) -> Seq [Array DIM1 a]-toSeqOuter2 a = toSeq (Z :. Split :. All) a---- | Sequence a 3-dimensional array on the outermost dimension.-toSeqOuter3 :: Elt a => Acc (Array DIM3 a) -> Seq [Array DIM2 a]-toSeqOuter3 a = toSeq (Z :. Split :. All :. All) a---- | Generate a scalar sequence of a fixed given length, by applying--- the given scalar function at each index.-generateSeq :: Elt a => Exp Int -> (Exp Int -> Exp a) -> Seq [Scalar a]-generateSeq n f = toSeq (Z :. Split) (generate (index1 n) (f . unindex1))---}---- Utilities--- -----------emptyArray :: (Shape sh, Elt e) => Acc (Array sh e)-emptyArray = use (fromList empty [])----- Utilities--- -----------matchShapeType :: forall s t. (Shape s, Shape t) => s -> t -> Maybe (s :~: t)-matchShapeType _ _- | Just Refl <- matchTupleType (eltType (undefined::s)) (eltType (undefined::t))- = gcast Refl--matchShapeType _ _- = Nothing-
− Data/Array/Accelerate/Pretty.hs
@@ -1,93 +0,0 @@-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeSynonymInstances #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}-{-# OPTIONS_HADDOCK hide #-}--- |--- Module : Data.Array.Accelerate.Pretty--- Copyright : [2008..2017] Manuel M T Chakravarty, Gabriele Keller--- [2009..2017] Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Pretty (-- -- * Pretty printing functions- module Data.Array.Accelerate.Pretty.Print,- module Data.Array.Accelerate.Pretty.Graphviz,-- -- * Instances of Show--) where---- standard libraries-import Text.PrettyPrint.ANSI.Leijen---- friends-import Data.Array.Accelerate.AST-import Data.Array.Accelerate.Trafo.Base-import Data.Array.Accelerate.Pretty.Print-import Data.Array.Accelerate.Pretty.Graphviz----- Show--- -------- Explicitly enumerate Show instances for the Accelerate array AST types. If we--- instead use a generic instance of the form:------ instance Kit acc => Show (acc aenv a) where------ This matches any type of kind (* -> * -> *), which can cause problems--- interacting with other packages. See Issue #108.----instance PrettyEnv aenv => Show (OpenAcc aenv a) where- showsPrec _ = displayS . renderStyle . pretty--instance PrettyEnv aenv => Show (DelayedOpenAcc aenv a) where- showsPrec _ = displayS . renderStyle . pretty---- These parameterised instances are fine because there is a concrete kind------ TLM: Ugh, his new 'PrettyEnv' constraint really just enforces something--- that we already know, which is that our environments are nested--- tuples, but our type parameter 'env' doesn't capture that.----instance (Kit acc, PrettyEnv aenv) => Show (PreOpenAfun acc aenv f) where- showsPrec _ = displayS . renderStyle . pretty--instance (Kit acc, PrettyEnv env, PrettyEnv aenv) => Show (PreOpenFun acc env aenv f) where- showsPrec _ = displayS . renderStyle . pretty--instance (Kit acc, PrettyEnv env, PrettyEnv aenv) => Show (PreOpenExp acc env aenv t) where- showsPrec _ = displayS . renderStyle . pretty---- instance Kit acc => Show (PreOpenSeq acc aenv senv t) where--- show s = renderStyle wide $ sep $ punctuate (text ";") $ prettySeq prettyAcc 0 0 noParens s--renderStyle :: Doc -> SimpleDoc-renderStyle = renderSmart 0.7 120---- Pretty--- --------instance PrettyEnv aenv => Pretty (OpenAcc aenv a) where- pretty c = prettyAcc noParens prettyEnv c--instance PrettyEnv aenv => Pretty (DelayedOpenAcc aenv a) where- pretty c = prettyAcc noParens prettyEnv c--instance (Kit acc, PrettyEnv aenv) => Pretty (PreOpenAfun acc aenv f) where- pretty f = prettyPreOpenAfun prettyAcc prettyEnv f--instance (Kit acc, PrettyEnv env, PrettyEnv aenv) => Pretty (PreOpenFun acc env aenv f) where- pretty f = prettyPreOpenFun prettyAcc prettyEnv prettyEnv f--instance (Kit acc, PrettyEnv env, PrettyEnv aenv) => Pretty (PreOpenExp acc env aenv t) where- pretty e = prettyPreOpenExp prettyAcc noParens prettyEnv prettyEnv e-
− Data/Array/Accelerate/Pretty/Graphviz.hs
@@ -1,557 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE PatternGuards #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE TypeSynonymInstances #-}-{-# LANGUAGE ViewPatterns #-}--- |--- Module : Data.Array.Accelerate.Pretty.Graphviz--- Copyright : [2015..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)----module Data.Array.Accelerate.Pretty.Graphviz (-- Graph,- PrettyGraph(..), Detail(..),-- graphDelayedAcc, graphDelayedAfun,--) where---- standard libraries-import Control.Applicative hiding ( Const, empty )-import Control.Arrow ( (&&&) )-import Control.Monad.State ( modify, gets, state )-import Data.HashSet ( HashSet )-import Data.List-import Data.Maybe-import System.IO.Unsafe ( unsafePerformIO )-import Text.PrettyPrint.ANSI.Leijen hiding ( (<$>), parens )-import Prelude hiding ( exp )-import qualified Data.Sequence as Seq-import qualified Data.HashSet as Set-import qualified Text.PrettyPrint.ANSI.Leijen as PP---- friends-import Data.Array.Accelerate.AST ( PreOpenAcc(..), PreOpenAfun(..), PreOpenFun(..), PreOpenExp(..), PreBoundary(..), Idx(..) )-import Data.Array.Accelerate.Array.Sugar ( Array, Shape, Elt, Tuple(..), Atuple(..), arrays, toElt, strForeign )-import Data.Array.Accelerate.Error-import Data.Array.Accelerate.Trafo.Base-import Data.Array.Accelerate.Pretty.Print-import Data.Array.Accelerate.Pretty.Graphviz.Monad-import Data.Array.Accelerate.Pretty.Graphviz.Type----- Configuration options--- -----------------------cfgIncludeShape, cfgUnique :: Bool-cfgIncludeShape = False -- draw edges for uses of shape information-cfgUnique = False -- draw a single edge per data dependency----- Environments--- ---------------- This is the standard environment typed by de Bruijn indices, where at each--- index we need to record both the pretty printed label as well its 'NodeId',--- which we use to track data dependencies.----data Aval env where- Aempty :: Aval ()- Apush :: Aval env -> NodeId -> Label -> Aval (env, t)---- Convert to the 'Val' used by the base pretty printing module by stripping out--- the 'NodeId' part.----avalToVal :: Aval aenv -> Val aenv-avalToVal Aempty = Empty-avalToVal (Apush aenv _ v) = Push (avalToVal aenv) (text v)--aprj :: Idx aenv t -> Aval aenv -> (NodeId, Label) -- TLM: (Vertex, Label) ??-aprj ZeroIdx (Apush _ n v) = (n,v)-aprj (SuccIdx ix) (Apush aenv _ _) = aprj ix aenv-#if __GLASGOW_HASKELL__ < 800-aprj _ _ = $internalError "aprj" "inconsistent valuation"-#endif----- Graph construction--- --------------------mkNode :: PNode -> Maybe Label -> Dot NodeId-mkNode (PNode ident tree deps) label =- let node = Node label ident tree- edges = Seq.fromList- $ map (\(from, to) -> Edge from (Vertex ident to))- $ if cfgUnique then nub deps else deps- in- state $ \s ->- ( ident- , s { dotNodes = node Seq.<| dotNodes s- , dotEdges = edges Seq.>< dotEdges s- }- )----- Add [T|F] ports underneath the given tree.----mkTF :: Tree (Maybe Port, Doc) -> Tree (Maybe Port, Doc)-mkTF this =- Forest [ this- , Forest [ Leaf (Just "T", "T")- , Leaf (Just "F", "F")- ]- ]----- Pretty Printing--- ===============------ The use of unsafePerformIO in the below is safe in the sense that we only--- require IO to recover the stable names of terms. At worst, if we do not--- recover the correct stable name for some reason, we will be left with--- dandling edges in the graph.-----class PrettyGraph g where- ppGraph :: Detail -> g -> Graph--instance PrettyGraph (DelayedAcc a) where- ppGraph = graphDelayedAcc--instance PrettyGraph (DelayedAfun a) where- ppGraph = graphDelayedAfun--data Detail = Simple | Full--simple :: Detail -> Bool-simple Simple = True-simple _ = False---- | Generate a dependency graph for the given computation----{-# NOINLINE graphDelayedAcc #-}-graphDelayedAcc :: Detail -> DelayedAcc a -> Graph-graphDelayedAcc detail acc =- unsafePerformIO $! evalDot (graphDelayedOpenAcc detail Aempty acc)---- | Generate a dependency graph for an array function----{-# NOINLINE graphDelayedAfun #-}-graphDelayedAfun :: Detail -> DelayedAfun f -> Graph-graphDelayedAfun detail afun = unsafePerformIO . evalDot $! do- l <- prettyDelayedAfun detail Aempty afun- state $ \s ->- case Seq.viewl (dotGraph s) of- g@(Graph l' _) Seq.:< gs | l == l' -> (g, s { dotGraph = gs })- _ -> $internalError "graphDelaydAfun" "unexpected error"----- Pretty-printing data-dependency graphs--- ------------------------------------------ Partially constructed graph nodes, consists of some body text and a list of--- vertices which we will draw edges from (and later, the port we connect into).----data PDoc = PDoc Doc [Vertex]-data PNode = PNode NodeId (Tree (Maybe Port, Doc)) [(Vertex, Maybe Port)]--graphDelayedOpenAcc- :: Detail- -> Aval aenv- -> DelayedOpenAcc aenv a- -> Dot Graph-graphDelayedOpenAcc detail aenv acc = do- r <- prettyDelayedOpenAcc detail noParens aenv acc- i <- mkNodeId r- v <- mkNode r Nothing- _ <- mkNode (PNode i (Leaf (Nothing,"result")) [(Vertex v Nothing, Nothing)]) Nothing- mkGraph---- Generate a graph for the given term.----prettyDelayedOpenAcc- :: forall aenv arrs.- Detail -- simplified output: only print operator name- -> (Doc -> Doc)- -> Aval aenv- -> DelayedOpenAcc aenv arrs- -> Dot PNode-prettyDelayedOpenAcc _ _ _ Delayed{} = $internalError "prettyDelayedOpenAcc" "expected manifest array"-prettyDelayedOpenAcc detail wrap aenv atop@(Manifest pacc) =- case pacc of- Avar ix -> pnode (avar ix)- Alet bnd body -> do- bnd' <- prettyDelayedOpenAcc detail noParens aenv bnd- a <- mkLabel- ident <- mkNode bnd' (Just a)- body' <- prettyDelayedOpenAcc detail noParens (Apush aenv ident a) body- return body'-- Acond p t e -> do- ident <- mkNodeId atop- vt <- lift t- ve <- lift e- PDoc p' vs <- ppE p- let port = Just "P"- doc = mkTF $ Leaf (port, if simple detail then "?|" else p')- deps = (vt, Just "T") : (ve, Just "F") : map (,port) vs- return $ PNode ident doc deps-- Apply afun acc -> apply <$> prettyDelayedAfun detail aenv afun- <*> prettyDelayedOpenAcc detail parens aenv acc-- Awhile p f x -> do- ident <- mkNodeId atop- x' <- replant =<< prettyDelayedOpenAcc detail parens aenv x- p' <- prettyDelayedAfun detail aenv p- f' <- prettyDelayedAfun detail aenv f- --- let PNode _ (Leaf (Nothing,xb)) fvs = x'- loop = wrap $ hang 2 (sep ["awhile", text p', text f', xb ])- return $ PNode ident (Leaf (Nothing,loop)) fvs-- Atuple atup -> prettyDelayedAtuple detail wrap aenv atup- Aprj ix atup -> do- ident <- mkNodeId atop- PNode _ (Leaf (p,d)) deps <- replant =<< prettyDelayedOpenAcc detail parens aenv atup- return $ PNode ident (Leaf (p, wrap (prettyTupleIdx ix <+> nest 2 d))) deps-- Use arrs -> "use" .$ [ return $ PDoc (prettyArrays (arrays (undefined::arrs)) arrs) [] ]- Unit e -> "unit" .$ [ ppE e ]- Generate sh f -> "generate" .$ [ ppSh sh, ppF f ]- Transform sh ix f xs -> "transform" .$ [ ppSh sh, ppF ix, ppF f, ppA xs ]- Reshape sh xs -> "reshape" .$ [ ppSh sh, ppA xs ]- Replicate _ty ix xs -> "replicate" .$ [ ppSh ix, ppA xs ]- Slice _ty xs ix -> "slice" .$ [ ppA xs, ppSh ix ]- Map f xs -> "map" .$ [ ppF f, ppA xs ]- ZipWith f xs ys -> "zipWith" .$ [ ppF f, ppA xs, ppA ys ]- Fold f e xs -> "fold" .$ [ ppF f, ppE e, ppA xs ]- Fold1 f xs -> "fold1" .$ [ ppF f, ppA xs ]- FoldSeg f e xs ys -> "foldSeg" .$ [ ppF f, ppE e, ppA xs, ppA ys ]- Fold1Seg f xs ys -> "fold1Seg" .$ [ ppF f, ppA xs, ppA ys ]- Scanl f e xs -> "scanl" .$ [ ppF f, ppE e, ppA xs ]- Scanl' f e xs -> "scanl'" .$ [ ppF f, ppE e, ppA xs ]- Scanl1 f xs -> "scanl1" .$ [ ppF f, ppA xs ]- Scanr f e xs -> "scanr" .$ [ ppF f, ppE e, ppA xs ]- Scanr' f e xs -> "scanr'" .$ [ ppF f, ppE e, ppA xs ]- Scanr1 f xs -> "scanr1" .$ [ ppF f, ppA xs ]- Permute f dfts p xs -> "permute" .$ [ ppF f, ppA dfts, ppF p, ppA xs ]- Backpermute sh p xs -> "backpermute" .$ [ ppSh sh, ppF p, ppA xs ]- Stencil sten bndy xs -> "stencil" .$ [ ppF sten, ppB bndy, ppA xs ]- Stencil2 sten bndy1 acc1 bndy2 acc2- -> "stencil2" .$ [ ppF sten, ppB bndy1, ppA acc1, ppB bndy2, ppA acc2 ]- Aforeign ff _afun xs -> "aforeign" .$ [ return (PDoc (text (strForeign ff)) []), {- ppAf afun, -} ppA xs ]- -- Collect{} -> error "Collect"-- where- (.$) :: String -> [Dot PDoc] -> Dot PNode- name .$ docs = pnode =<< fmt name docs-- fmt :: String -> [Dot PDoc] -> Dot PDoc- fmt name docs = do- docs' <- sequence docs- let args = [ x | PDoc x _ <- docs' ]- fvs = [ x | PDoc _ x <- docs' ]- return $ PDoc (wrap $ hang 2 (sep [text name, if simple detail then empty else sep args]))- (concat fvs)-- pnode :: PDoc -> Dot PNode- pnode (PDoc doc vs) = do- let port = Nothing- ident <- mkNodeId atop- return $ PNode ident (Leaf (port, doc)) (map (,port) vs)-- -- Free variables- --- fvA :: FVAcc DelayedOpenAcc- fvA env (Manifest (Avar ix)) = [ Vertex (fst $ aprj ix env) Nothing ]- fvA _ _ = $internalError "graphviz" "expected array variable"-- fvF :: DelayedFun aenv t -> [Vertex]- fvF = fvPreOpenFun fvA Empty aenv-- fvE :: DelayedExp aenv t -> [Vertex]- fvE = fvPreOpenExp fvA Empty aenv-- -- Pretty-printing- --- avar :: Idx aenv t -> PDoc- avar ix = let (ident, v) = aprj ix aenv- in PDoc (text v) [Vertex ident Nothing]-- aenv' :: Val aenv- aenv' = avalToVal aenv-- ppA :: DelayedOpenAcc aenv a -> Dot PDoc- ppA (Manifest (Avar ix)) = return (avar ix)- ppA acc@Manifest{} = do- -- Lift out and draw as a separate node. This can occur with the manifest- -- array arguments to permute (defaults array) and stencil[2].- acc' <- prettyDelayedOpenAcc detail noParens aenv acc- v <- mkLabel- ident <- mkNode acc' (Just v)- return $ PDoc (text v) [Vertex ident Nothing]- ppA (Delayed sh f _)- | Shape a <- sh -- identical shape- , Just Refl <- match f (Lam (Body (Index a (Var ZeroIdx)))) -- identity function- = ppA a- ppA (Delayed sh f _) = do- PDoc d v <- "Delayed" `fmt` [ ppSh sh, ppF f ]- return $ PDoc (parens d) v-- ppB :: forall sh e. (Shape sh, Elt e)- => PreBoundary DelayedOpenAcc aenv (Array sh e)- -> Dot PDoc- ppB Clamp = return (PDoc "clamp" [])- ppB Mirror = return (PDoc "mirror" [])- ppB Wrap = return (PDoc "wrap" [])- ppB (Constant e) = return (PDoc (parens $ "constant" <+> text (show (toElt e :: e))) [])- ppB (Function f) = ppF f-- ppF :: DelayedFun aenv t -> Dot PDoc- ppF = return . uncurry PDoc . (parens . prettyDelayedFun aenv' &&& fvF)-- ppE :: DelayedExp aenv t -> Dot PDoc- ppE = return . uncurry PDoc . (prettyDelayedExp parens aenv' &&& fvE)-- ppSh :: DelayedExp aenv sh -> Dot PDoc- ppSh = return . uncurry PDoc . (parens . prettyDelayedExp noParens aenv' &&& fvE)-- lift :: DelayedOpenAcc aenv a -> Dot Vertex- lift Delayed{} = $internalError "prettyDelayedOpenAcc" "expected manifest array"- lift (Manifest (Avar ix)) = return $ Vertex (fst (aprj ix aenv)) Nothing- lift acc = do- acc' <- prettyDelayedOpenAcc detail noParens aenv acc- ident <- mkNode acc' Nothing- return $ Vertex ident Nothing-- apply :: Label -> PNode -> PNode- apply f (PNode ident x vs) =- let x' = case x of- Leaf (p,d) -> Leaf (p, wrap (text f <+> d))- Forest ts -> Forest (Leaf (Nothing,text f) : ts)- in- PNode ident x' vs-- parens :: Doc -> Doc- parens = PP.parens . align----- Pretty print array functions as separate sub-graphs, and return the name of--- the sub-graph as if it can be called like a function. We will add additional--- nodes at the top of the graph to represent the bound variables.------ Note: [Edge placement]------ If a node belongs to a particular graph, so too must all its edges (and--- vertices). This means that if the subgraph references anything from the--- enclosing environment, we must lift those edges out of this subgraph,--- otherwise the referenced node will be drawn inside of the subgraph.----prettyDelayedAfun- :: Detail- -> Aval aenv- -> DelayedOpenAfun aenv afun- -> Dot Label-prettyDelayedAfun detail aenv afun = do- Graph _ ss <- mkSubgraph (go aenv afun)- n <- Seq.length <$> gets dotGraph- let label = "afun" ++ show (n+1)- outer = collect aenv- (lifted,ss') =- flip partition ss $ \s ->- case s of- E (Edge (Vertex ident _) _) -> Set.member ident outer- _ -> False- --- modify $ \s -> s { dotGraph = dotGraph s Seq.|> Graph label ss'- , dotEdges = Seq.fromList [ e | E e <- lifted ] Seq.>< dotEdges s- }- return label- where- go :: Aval aenv' -> DelayedOpenAfun aenv' a' -> Dot Graph- go aenv' (Abody b) = graphDelayedOpenAcc detail aenv' b- go aenv' (Alam f) = do- a <- mkLabel- ident <- mkNodeId f- _ <- mkNode (PNode ident (Leaf (Nothing, text a)) []) Nothing- go (Apush aenv' ident a) f-- collect :: Aval aenv' -> HashSet NodeId- collect Aempty = Set.empty- collect (Apush a i _) = Set.insert i (collect a)----- Display array tuples. This is a little tricky...----prettyDelayedAtuple- :: forall aenv atup.- Detail- -> (Doc -> Doc)- -> Aval aenv- -> Atuple (DelayedOpenAcc aenv) atup- -> Dot PNode-prettyDelayedAtuple detail wrap aenv atup = do- ident <- mkNodeId atup- (ids, ts, vs) <- unzip3 . map (\(PNode i t v) -> (i,t,v)) <$> collect [] atup- modify $ \s -> s { dotEdges = fmap (redirect ident ids) (dotEdges s) }- return $ PNode ident (forest ts) (concat vs)- where- collect :: [PNode] -> Atuple (DelayedOpenAcc aenv) t -> Dot [PNode]- collect acc NilAtup = return acc- collect acc (SnocAtup tup a) = do- a' <- replant =<< prettyDelayedOpenAcc detail wrap aenv a- tup' <- collect (a':acc) tup- return tup'-- -- Redirect any edges that pointed into one of the nodes now part of this- -- tuple, to instead point to the container node.- --- redirect :: NodeId -> [NodeId] -> Edge -> Edge- redirect new subs edge@(Edge from (Vertex to port))- | to `elem` subs = Edge from (Vertex new port)- | otherwise = edge-- -- Since we have lifted out any non-leaves into separate nodes, we can- -- simply tuple-up all of the elements.- --- forest :: [Tree (Maybe Port, Doc)] -> Tree (Maybe Port, Doc)- forest leaves = Leaf (Nothing, tupled [ align d | Leaf (Nothing,d) <- leaves ])----- Lift out anything that isn't a Leaf node and output it to the graph--- immediately as a new labelled node.----replant :: PNode -> Dot PNode-replant pnode@(PNode ident tree _) =- case tree of- Leaf (Nothing, _) -> return pnode- _ -> do- vacuous <- mkNodeId pnode- a <- mkLabel- _ <- mkNode pnode (Just a)- return $ PNode vacuous (Leaf (Nothing, text a)) [(Vertex ident Nothing, Nothing)]----- Pretty printing scalar functions and expressions--- ------------------------------------------------------ This is done with the usual machinery. Note that we rely on knowing that all--- array operations will be lifted out of scalar expressions. This means that we--- don't really need to recurse into the scalar terms to uncover new graph--- nodes.-----prettyDelayedFun :: Val aenv -> DelayedFun aenv f -> Doc-prettyDelayedFun = prettyDelayedOpenFun Empty--prettyDelayedExp :: (Doc -> Doc) -> Val aenv -> DelayedExp aenv t -> Doc-prettyDelayedExp wrap = prettyDelayedOpenExp wrap Empty---prettyDelayedOpenFun- :: forall env aenv f.- Val env- -> Val aenv- -> DelayedOpenFun env aenv f- -> Doc-prettyDelayedOpenFun env aenv fun = "\\\\" <> next env fun- where- -- graphviz will silently not print a label containing the string "->",- -- so instead we use the special token "&rarr" for a short right arrow.- --- next :: Val env' -> PreOpenFun DelayedOpenAcc env' aenv f' -> Doc- next env' (Body body) = "→" <+> prettyDelayedOpenExp noParens env' aenv body- next env' (Lam fun') =- let x = char 'x' <> int (sizeEnv env')- in x <+> next (env' `Push` x) fun'--prettyDelayedOpenExp- :: (Doc -> Doc)- -> Val env- -> Val aenv- -> DelayedOpenExp env aenv t- -> Doc-prettyDelayedOpenExp = prettyPreOpenExp pp- where- pp :: PrettyAcc DelayedOpenAcc- pp _ aenv (Manifest (Avar ix)) = prj ix aenv- pp _ _ _ = $internalError "prettyDelayedOpenExp" "expected array variable"----- Data dependencies--- ----------------------- Return the data-dependencies of the given term. This is just a tree traversal--- to extract all of the free variables. We will draw an edge from each of those--- nodes (vertices) into the current term.-----type FVAcc acc = forall aenv a. Aval aenv -> acc aenv a -> [Vertex]--fvPreOpenFun- :: forall acc env aenv fun.- FVAcc acc- -> Val env- -> Aval aenv- -> PreOpenFun acc env aenv fun- -> [Vertex]-fvPreOpenFun fvA env aenv (Body b) = fvPreOpenExp fvA env aenv b-fvPreOpenFun fvA env aenv (Lam f) = fvPreOpenFun fvA (env `Push` (char 'x' <> int (sizeEnv env))) aenv f--fvPreOpenExp- :: forall acc env aenv exp.- FVAcc acc- -> Val env- -> Aval aenv- -> PreOpenExp acc env aenv exp- -> [Vertex]-fvPreOpenExp fvA env aenv = fv- where- fvT :: Tuple (PreOpenExp acc env aenv) t -> [Vertex]- fvT NilTup = []- fvT (SnocTup tup e) = concat [ fv e, fvT tup ]-- fvF :: PreOpenFun acc env aenv f -> [Vertex]- fvF = fvPreOpenFun fvA env aenv-- fv :: PreOpenExp acc env aenv e -> [Vertex]- fv (Shape acc) = if cfgIncludeShape then fvA aenv acc else []- fv (Index acc i) = concat [ fvA aenv acc, fv i ]- fv (LinearIndex acc i) = concat [ fvA aenv acc, fv i ]- --- fv (Let e1 e2) = concat [ fv e1, fvPreOpenExp fvA (env `Push` (char 'x' <> int (sizeEnv env))) aenv e2 ]- fv Var{} = []- fv Const{} = []- fv PrimConst{} = []- fv (PrimApp _ x) = fv x- fv (Tuple tup) = fvT tup- fv (Prj _ e) = fv e- fv IndexNil = []- fv IndexAny = []- fv (IndexHead sh) = fv sh- fv (IndexTail sh) = fv sh- fv (IndexCons t h) = concat [ fv t, fv h ]- fv (IndexSlice _ slix sh) = concat [ fv slix, fv sh ]- fv (IndexFull _ slix sh) = concat [ fv slix, fv sh ]- fv (ToIndex sh ix) = concat [ fv sh, fv ix ]- fv (FromIndex sh ix) = concat [ fv sh, fv ix ]- fv (Union sh1 sh2) = concat [ fv sh1, fv sh2 ]- fv (Intersect sh1 sh2) = concat [ fv sh1, fv sh2 ]- fv (ShapeSize sh) = fv sh- fv Foreign{} = []- fv (Cond p t e) = concat [ fv p, fv t, fv e ]- fv (While p f x) = concat [ fvF p, fvF f, fv x ]-
− Data/Array/Accelerate/Pretty/Graphviz/Monad.hs
@@ -1,74 +0,0 @@-{-# LANGUAGE RecordWildCards #-}--- |--- Module : Data.Array.Accelerate.Pretty.Graphviz.Monad--- Copyright : [2015..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)----module Data.Array.Accelerate.Pretty.Graphviz.Monad- where--import Control.Applicative-import Control.Monad.State-import Data.Foldable ( toList )-import Data.Sequence ( Seq )-import System.Mem.StableName-import Prelude-import qualified Data.Sequence as Seq--import Data.Array.Accelerate.Pretty.Graphviz.Type----- Graph construction state ------------------------------------------------------type Dot a = StateT DotState IO a-data DotState = DotState- { fresh :: !Int- , dotGraph :: Seq Graph- , dotEdges :: Seq Edge- , dotNodes :: Seq Node- }--emptyState :: DotState-emptyState = DotState 0 Seq.empty Seq.empty Seq.empty--runDot :: Dot a -> IO (a, DotState)-runDot dot = runStateT dot emptyState--evalDot :: Dot a -> IO a-evalDot dot = fst <$> runDot dot--execDot :: Dot a -> IO DotState-execDot dot = snd <$> runDot dot----- Utilities ---------------------------------------------------------------------mkLabel :: Dot Label-mkLabel = state $ \s ->- let n = fresh s- in ( 'a' : show n, s { fresh = n + 1 } )--mkNodeId :: a -> Dot NodeId-mkNodeId node = do- sn <- liftIO $ makeStableName node- return $ NodeId (hashStableName sn)--mkGraph :: Dot Graph-mkGraph =- state $ \DotState{..} ->- ( Graph [] (toList $ fmap N dotNodes Seq.>< fmap E dotEdges Seq.>< fmap G dotGraph)- , emptyState { fresh = fresh }- )--mkSubgraph :: Dot Graph -> Dot Graph-mkSubgraph g = do- n <- gets fresh- (r, s') <- lift . runDot $ do- modify $ \s -> s { fresh = n }- g- state $ \s -> (r, s { fresh = fresh s' })-
− Data/Array/Accelerate/Pretty/Graphviz/Type.hs
@@ -1,154 +0,0 @@-{-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE ViewPatterns #-}--- |--- Module : Data.Array.Accelerate.Pretty.Graphviz.Type--- Copyright : [2015..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)------ Simple data types for representing (simple, directed) graphs and--- pretty-printing to Graphviz dot format.----module Data.Array.Accelerate.Pretty.Graphviz.Type- where--import Data.Maybe-import Data.Hashable-import Text.Printf-import Text.PrettyPrint.ANSI.Leijen----- Rose tree, with all information at the leaves.----data Tree a = Leaf a- | Forest [Tree a]--instance Functor Tree where- fmap f (Leaf x) = Leaf (f x)- fmap f (Forest xs) = Forest (map (fmap f) xs)----- Representation for simple Graphviz graphs----data Graph = Graph Label [Statement]-data Statement = N Node | E Edge | G Graph--data Node = Node (Maybe Label) NodeId (Tree (Maybe Port, Doc))-data NodeId = NodeId !Int---- XXX: Changed from 'Doc' to 'String' because the version of 'pretty' included--- with ghc-7.8 does not have an Eq Doc instance, which was added in--- pretty-1.1.1.2. However, we don't want to simply depend on a newer--- version of the library, because this will indirectly lead to--- a dependency on multiple versions (through, e.g., template-haskell).----type Label = String-type Port = String--data Vertex = Vertex NodeId (Maybe Port)-data Edge = Edge {- from -} Vertex- {- to -} Vertex--deriving instance Eq NodeId-deriving instance Eq Vertex--instance Hashable NodeId where- hashWithSalt salt (NodeId ident) = hashWithSalt salt ident--instance Show Graph where- show = show . ppGraph----- Pretty print a (directed) graph to dot format----ppGraph :: Graph -> Doc-ppGraph (Graph l ss) =- vcat [ text "digraph" <+> text l <+> lbrace- , nest 4 $ vcat- $ punctuate semi- $ text "graph [compound=true]"- : text "node [shape=record,fontsize=10]"- : map ppStatement ss- , rbrace- ]--ppSubgraph :: Graph -> Doc-ppSubgraph (Graph l ss) =- vcat [ text "subgraph cluster_" <> text l <+> lbrace- , nest 4 $ vcat- $ punctuate semi- $ text "label" <> equals <> text l- : map ppStatement ss- , rbrace- ]--ppStatement :: Statement -> Doc-ppStatement (N n) = ppNode n-ppStatement (E e) = ppEdge e-ppStatement (G g) = ppSubgraph g--ppEdge :: Edge -> Doc-ppEdge (Edge from to) = ppVertex from <+> text "->" <+> ppVertex to--ppVertex :: Vertex -> Doc-ppVertex (Vertex n p) = ppNodeId n <> maybe empty (colon<>) (fmap text p)--ppNode :: Node -> Doc-ppNode (Node label nid body) =- hcat [ ppNodeId nid- , brackets- $ hcat- $ punctuate comma- $ catMaybes [ fmap ((\x -> text "xlabel" <> equals <> x) . dquotes . text) label- , Just ( text "label" <> equals <> dquotes (ppNodeTree body))- ]- ]--ppNodeTree :: Tree (Maybe Port, Doc) -> Doc-ppNodeTree (Forest trees) = braces $ hcat (punctuate (char '|') (map ppNodeTree trees))-ppNodeTree (Leaf (port, body)) = maybe empty (\p -> char '<' <> p <> char '>') (fmap text port) <> pp body- where- -- In order for the text to be properly rendered by graphviz, we need to- -- escape some special characters. If the text takes up more than one line,- -- then newlines '\n' need be be replaced with '\l', to ensure that the text- -- is left justified rather than centred. The last line also needs a final- -- '\l'. Single lines of text remain centred, which provides better- -- formatting for short statements and port labels.- --- pp :: Doc -> Doc- pp = encode . renderSmart 0.7 120-- encode :: SimpleDoc -> Doc- encode doc =- let- go SFail = error "unexpected failure rendering SimpleDoc"- go SEmpty = (empty, False)- go (SChar c x) = let (x',m) = go x in (text (escape c) <> x', m)- go (SText _ t x) = let (x',m) = go x in (text (concatMap escape t) <> x', m)- go (SLine i x) = let (x',_) = go x in (text "\\l" <> spaces i <> x', True) -- [1] left justify- go (SSGR _ x) = go x-- (doc',multiline) = go doc- in- doc' <> if multiline- then text "\\l"- else empty-- spaces :: Int -> Doc- spaces i | i <= 0 = empty- | otherwise = text (concat (replicate i "\\ "))-- escape :: Char -> String- escape ' ' = "\\ " -- don't collapse multiple spaces- escape '>' = "\\>"- escape '<' = "\\<"- escape '|' = "\\|"- -- escape '\n' = "\\l" -- handled at [1] instead- escape c = [c]--ppNodeId :: NodeId -> Doc-ppNodeId (NodeId nid) = text (printf "Node_%#0x" nid)-
− Data/Array/Accelerate/Pretty/Print.hs
@@ -1,620 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE PatternGuards #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeOperators #-}--- |--- Module : Data.Array.Accelerate.Pretty.Print--- Copyright : [2008..2017] Manuel M T Chakravarty, Gabriele Keller--- [2009..2017] Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Pretty.Print (-- -- * Pretty printing- -- ** 'OpenAcc'- --- prettyOpenAcc,- prettyOpenAfun,- prettyOpenExp,- prettyOpenFun,-- -- ** 'PreOpenAcc'- PrettyAcc,- prettyPreOpenAcc,- prettyPreOpenAfun,- -- prettyPreOpenSeq,- prettyPreExp, prettyPreOpenExp,- prettyPreFun, prettyPreOpenFun,- prettyPrim,- prettyArrays,- prettyTupleIdx,-- -- ** Utilities- Val(..), PrettyEnv(..), prj, sizeEnv,- noParens,--) where---- standard libraries-import Prelude hiding ( (<$>), exp, seq )-import Data.List ( isPrefixOf )-import Text.PrettyPrint.ANSI.Leijen hiding ( parens, tupled )-import qualified Text.PrettyPrint.ANSI.Leijen as PP---- friends-import Data.Array.Accelerate.AST hiding ( Val(..), prj )-import Data.Array.Accelerate.Array.Sugar-import Data.Array.Accelerate.Product----- Pretty printing--- ===============---- Pretty printing for the knot-tied 'OpenAcc'--- ----------------------------------------------- Pretty print an array expression----prettyOpenAcc :: PrettyAcc OpenAcc-prettyOpenAcc wrap aenv (OpenAcc acc) = prettyPreOpenAcc prettyOpenAcc wrap aenv acc--prettyOpenAfun :: Val aenv -> OpenAfun aenv t -> Doc-prettyOpenAfun = prettyPreOpenAfun prettyOpenAcc----- Pretty print scalar expressions----prettyOpenFun :: Val env -> Val aenv -> OpenFun env aenv fun -> Doc-prettyOpenFun = prettyPreOpenFun prettyOpenAcc--prettyOpenExp :: (Doc -> Doc) -> Val env -> Val aenv -> OpenExp env aenv t -> Doc-prettyOpenExp = prettyPreOpenExp prettyOpenAcc----- Pretty printing for open 'PreOpenAcc'--- ----------------------------------------- The type of pretty printing functions for array computations.----type PrettyAcc acc = forall aenv t.- (Doc -> Doc)- -> Val aenv- -> acc aenv t- -> Doc--prettyPreOpenAcc- :: forall acc aenv arrs.- PrettyAcc acc- -> (Doc -> Doc) -- apply to compound expressions- -> Val aenv -- environment of array variables- -> PreOpenAcc acc aenv arrs- -> Doc-prettyPreOpenAcc prettyAcc wrap aenv = pp- where- ppE :: PreExp acc aenv e -> Doc- ppE = prettyPreExp prettyAcc parens aenv-- ppSh :: PreExp acc aenv sh -> Doc- ppSh x = encase (prettyPreExp prettyAcc noParens aenv x)- where- encase = case x of- Var{} -> id- IndexNil -> id- IndexAny -> id- Const{} -> id- _ -> parens-- ppF :: PreFun acc aenv f -> Doc- ppF = parens . prettyPreFun prettyAcc aenv-- ppA :: acc aenv a -> Doc- ppA = prettyAcc parens aenv-- ppAF :: PreOpenAfun acc aenv f -> Doc- ppAF = parens . prettyPreOpenAfun prettyAcc aenv-- ppB :: forall sh e. (Shape sh, Elt e)- => PreBoundary acc aenv (Array sh e)- -> Doc- ppB Clamp = text "clamp"- ppB Mirror = text "mirror"- ppB Wrap = text "wrap"- ppB (Constant e) = parens $ text "constant" <+> text (show (toElt e :: e))- ppB (Function f) = ppF f-- -- pretty print a named array operation with its arguments- name .$ docs = wrap $ hang 2 (sep (manifest (text name) : docs))-- -- The main pretty-printer- -- ------------------------ --- pp :: PreOpenAcc acc aenv arrs -> Doc- pp (Alet acc1 acc2)- | isAlet acc2'- = if isAlet acc1'- then wrap $ vsep [ let_ <+> a <+> equals <$> indent 2 acc1' <+> in_, acc2' ]- else wrap $ vsep [ hang 2 (sep [let_ <+> a <+> equals, acc1']) <+> in_, acc2' ]-- | otherwise- = wrap $ vsep [ hang 2 (sep [let_ <+> a <+> equals, acc1']), in_ </> acc2' ]- where- -- TLM: derp, can't unwrap into a PreOpenAcc to pattern match on Alet- render doc = displayS (renderCompact (plain doc)) ""- isAlet doc = "let" `isPrefixOf` render doc- acc1' = prettyAcc noParens aenv acc1- acc2' = prettyAcc noParens (aenv `Push` a) acc2- a = char 'a' <> int (sizeEnv aenv)-- pp (Awhile p afun acc) = "awhile" .$ [ppAF p, ppAF afun, ppA acc]- pp (Atuple tup) = prettyAtuple prettyAcc aenv tup- pp (Avar idx) = prj idx aenv- pp (Aprj ix arrs) = wrap $ prettyTupleIdx ix <+> ppA arrs- pp (Apply afun acc) = wrap $ sep [ ppAF afun, ppA acc ]- pp (Acond e acc1 acc2) = wrap $ hang 3 (vsep [if_ <+> ppE e, then_ <+> ppA acc1, else_ <+> ppA acc2])- pp (Slice _ty acc ix) = "slice" .$ [ ppA acc, ppE ix ]- pp (Use arrs) = "use" .$ [ prettyArrays (arrays (undefined :: arrs)) arrs ]- pp (Unit e) = "unit" .$ [ ppE e ]- pp (Generate sh f) = "generate" .$ [ ppSh sh, ppF f ]- pp (Transform sh ix f acc) = "transform" .$ [ ppSh sh, ppF ix, ppF f, ppA acc ]- pp (Reshape sh acc) = "reshape" .$ [ ppSh sh, ppA acc ]- pp (Replicate _ty ix acc) = "replicate" .$ [ ppSh ix, ppA acc ]- pp (Map f acc) = "map" .$ [ ppF f, ppA acc ]- pp (ZipWith f acc1 acc2) = "zipWith" .$ [ ppF f, ppA acc1, ppA acc2 ]- pp (Fold f e acc) = "fold" .$ [ ppF f, ppE e, ppA acc ]- pp (Fold1 f acc) = "fold1" .$ [ ppF f, ppA acc ]- pp (FoldSeg f e acc1 acc2) = "foldSeg" .$ [ ppF f, ppE e, ppA acc1, ppA acc2 ]- pp (Fold1Seg f acc1 acc2) = "fold1Seg" .$ [ ppF f, ppA acc1, ppA acc2 ]- pp (Scanl f e acc) = "scanl" .$ [ ppF f, ppE e, ppA acc ]- pp (Scanl' f e acc) = "scanl'" .$ [ ppF f, ppE e, ppA acc ]- pp (Scanl1 f acc) = "scanl1" .$ [ ppF f, ppA acc ]- pp (Scanr f e acc) = "scanr" .$ [ ppF f, ppE e, ppA acc ]- pp (Scanr' f e acc) = "scanr'" .$ [ ppF f, ppE e, ppA acc ]- pp (Scanr1 f acc) = "scanr1" .$ [ ppF f, ppA acc ]- pp (Permute f dfts p acc) = "permute" .$ [ ppF f, ppA dfts, ppF p, ppA acc ]- pp (Backpermute sh p acc) = "backpermute" .$ [ ppSh sh, ppF p, ppA acc ]- pp (Aforeign ff _afun acc) = "aforeign" .$ [ text (strForeign ff), {- ppAf afun, -} ppA acc ]- pp (Stencil sten bndy acc) = "stencil" .$ [ ppF sten, ppB bndy, ppA acc ]- pp (Stencil2 sten bndy1 acc1 bndy2 acc2)- = "stencil2" .$ [ ppF sten, ppB bndy1, ppA acc1, ppB bndy2, ppA acc2 ]-- -- pp (Collect s) = wrap $ hang (text "collect") 2- -- $ encloseSep lbrace rbrace semi- -- $ prettyPreOpenSeq prettyAcc wrap aenv Empty s---{----- Pretty print a computation over sequences----prettyPreOpenSeq- :: forall acc aenv senv arrs.- PrettyAcc acc- -> (Doc -> Doc) -- apply to compound expressions- -> Val aenv -- environment of array variables- -> Val senv -- environment of sequence variables- -> PreOpenSeq acc aenv senv arrs- -> [Doc]-prettyPreOpenSeq prettyAcc wrap aenv senv seq =- case seq of- Producer p s' -> prettyP p : prettyPreOpenSeq prettyAcc wrap aenv (senv `Push` var (sizeEnv senv)) s'- Consumer c -> [prettyC c]- Reify ix -> [var (idxToInt ix)]- where- var n = char 's' <> int n- name .$ docs = wrap $ hang (var (sizeEnv senv) <+> text ":=" <+> text name) 2 (sep docs)- name ..$ docs = wrap $ hang (text name) 2 (sep docs)-- ppE :: PreExp acc aenv e -> Doc- ppE = prettyPreExp prettyAcc parens aenv-- ppF :: PreFun acc aenv f -> Doc- ppF = parens . prettyPreFun prettyAcc aenv-- ppA :: acc aenv a -> Doc- ppA = prettyAcc parens aenv-- ppAF :: PreOpenAfun acc aenv f -> Doc- ppAF = parens . prettyPreOpenAfun prettyAcc aenv-- ppX :: Idx aenv' a -> Doc- ppX x = var (idxToInt x)-- ppSlix :: SliceIndex slix sl co sh -> Doc- ppSlix SliceNil = text "Z"- ppSlix (SliceAll s) = sep [ ppSlix s, text ":.", text "All" ]- ppSlix (SliceFixed s) = sep [ ppSlix s, text ":.", text "Split" ]-- prettyP :: forall a. Producer acc aenv senv a -> Doc- prettyP p =- case p of- StreamIn _ -> "streamIn" .$ [ text "..." ]- ToSeq slix _ a -> "toSeq" .$ [ ppSlix slix, ppA a ]- MapSeq f x -> "mapSeq" .$ [ ppAF f , ppX x ]- ChunkedMapSeq f x -> "chunkedMapSeq" .$ [ ppAF f , ppX x ]- ZipWithSeq f x y -> "zipWithSeq" .$ [ ppAF f , ppX x , ppX y ]- ScanSeq f e x -> "foldSeq" .$ [ ppF f , ppE e , ppX x ]-- prettyC :: forall a. Consumer acc aenv senv a -> Doc- prettyC c =- case c of- FoldSeq f e x -> "foldSeq" ..$ [ ppF f , ppE e , ppX x ]- FoldSeqFlatten f a x -> "foldSeqFlatten" ..$ [ ppAF f , ppA a , ppX x ]- Stuple t -> tupled (prettyT t)-- prettyT :: forall t. Atuple (Consumer acc aenv senv) t -> [Doc]- prettyT NilAtup = []- prettyT (SnocAtup t c) = prettyT t ++ [prettyC c]---}----- Pretty print a function over array computations.----prettyPreOpenAfun- :: forall acc aenv f.- PrettyAcc acc- -> Val aenv- -> PreOpenAfun acc aenv f- -> Doc-prettyPreOpenAfun pp aenv afun = char '\\' <> next aenv afun- where- next :: Val aenv' -> PreOpenAfun acc aenv' f' -> Doc- next aenv' (Abody body) = text "->" <+> align (pp noParens aenv' body)- next aenv' (Alam afun') =- let a = char 'a' <> int (sizeEnv aenv')- in a <+> next (aenv' `Push` a) afun'----- Pretty print a scalar function.----prettyPreFun :: PrettyAcc acc -> Val aenv -> PreFun acc aenv fun -> Doc-prettyPreFun pp = prettyPreOpenFun pp Empty--prettyPreOpenFun- :: forall acc env aenv f.- PrettyAcc acc- -> Val env -- environment of scalar variables- -> Val aenv -- environment of array variables- -> PreOpenFun acc env aenv f- -> Doc-prettyPreOpenFun pp env aenv fun = char '\\' <> next env fun- where- next :: Val env' -> PreOpenFun acc env' aenv f' -> Doc- next env' (Body body) = text "->" <+> align (prettyPreOpenExp pp noParens env' aenv body)- next env' (Lam fun') =- let x = char 'x' <> int (sizeEnv env')- in x <+> next (env' `Push` x) fun'----- Pretty print a scalar expression.----prettyPreExp :: PrettyAcc acc -> (Doc -> Doc) -> Val aenv -> PreExp acc aenv t -> Doc-prettyPreExp pp wrap = prettyPreOpenExp pp wrap Empty--prettyPreOpenExp- :: forall acc t env aenv.- PrettyAcc acc- -> (Doc -> Doc) -- apply to compound expressions- -> Val env -- environment of scalar variables- -> Val aenv -- environment of array variables- -> PreOpenExp acc env aenv t- -> Doc-prettyPreOpenExp prettyAcc wrap env aenv = pp- where- ppE, ppE' :: PreOpenExp acc env aenv e -> Doc- ppE = prettyPreOpenExp prettyAcc parens env aenv- ppE' = prettyPreOpenExp prettyAcc noParens env aenv-- ppE'' :: PreOpenExp acc env aenv sh -> Doc- ppE'' x = encase (ppE' x)- where- encase = case x of- Var{} -> id- IndexNil -> id- IndexAny -> id- Const{} -> id- _ -> parens-- ppF :: PreOpenFun acc env aenv f -> Doc- ppF = parens . prettyPreOpenFun prettyAcc env aenv-- ppA :: acc aenv a -> Doc- ppA = prettyAcc parens aenv-- -- pretty print a named array operation with its arguments- name .$ docs = wrap $ hang 2 (sep (text name : docs))-- -- The main pretty-printer- -- ------------------------ --- pp :: PreOpenExp acc env aenv t -> Doc- pp (Let e1 e2)- | isLet e2- = if isLet e1- then wrap $ vsep [ let_ <+> x <+> equals <$> indent 2 e1' <+> in_, e2' ]- else wrap $ vsep [ hang 2 (sep [let_ <+> x <+> equals, e1']) <+> in_, e2' ]- | otherwise- = wrap $ vsep [ hang 2 (sep [let_ <+> x <+> equals, e1']), in_ </> e2' ]- where- isLet (Let _ _) = True- isLet _ = False- e1' = align $ prettyPreOpenExp prettyAcc noParens env aenv e1- e2' = align $ prettyPreOpenExp prettyAcc noParens (env `Push` x) aenv e2- x = char 'x' <> int (sizeEnv env)-- pp (PrimApp p a)- | Tuple (NilTup `SnocTup` x `SnocTup` y) <- a- = if infixOp- then wrap $ sep [ppE x, f, ppE y]- else hang 2 (sep [f, ppE'' x, ppE'' y])- | otherwise- = wrap $ hang 2 (sep [f', ppE a])- where- -- sometimes the infix function arguments are obstructed. If so, add- -- parentheses and print prefix.- --- (infixOp, f) = prettyPrim p- f' = if infixOp then parens f else f-- pp (PrimConst a) = prettyConst a- pp (Tuple tup) = prettyTuple prettyAcc env aenv tup- pp (Var idx) = prj idx env- pp (Const v) = text $ show (toElt v :: t)- pp (Prj idx e) = wrap $ prettyTupleIdx idx <+> ppE e- pp (Cond c t e) = wrap $ hang 3 (vsep [ if_ <+> ppE' c, then_ <+> ppE' t, else_ <+> ppE' e ])- pp IndexNil = char 'Z'- pp IndexAny = text "indexAny"- pp (IndexCons t h) = sep [ ppE' t, text ":.", ppE' h ]- pp (IndexHead ix) = "indexHead" .$ [ ppE ix ]- pp (IndexTail ix) = "indexTail" .$ [ ppE ix ]- pp (IndexSlice _ slix sh) = "indexSlice" .$ [ ppE slix, ppE sh ]- pp (IndexFull _ slix sl) = "indexFull" .$ [ ppE slix, ppE sl ]- pp (ToIndex sh ix) = "toIndex" .$ [ ppE'' sh, ppE'' ix ]- pp (FromIndex sh ix) = "fromIndex" .$ [ ppE'' sh, ppE ix ]- pp (While p f x) = "while" .$ [ ppF p, ppF f, ppE x ]- pp (Foreign ff _f e) = "foreign" .$ [ text (strForeign ff), {- ppF f, -} ppE e ]- pp (Shape idx) = "shape" .$ [ ppA idx ]- pp (ShapeSize idx) = "shapeSize" .$ [ ppE'' idx ]- pp (Intersect sh1 sh2) = "intersect" .$ [ ppE'' sh1, ppE'' sh2 ]- pp (Union sh1 sh2) = "union" .$ [ ppE'' sh1, ppE'' sh2 ]- pp (Index idx i) = wrap $ cat [ ppA idx, char '!', ppE'' i ]- pp (LinearIndex idx i) = wrap $ cat [ ppA idx, text "!!", ppE'' i ]----- Pretty print nested pairs as a proper tuple.----prettyAtuple- :: forall acc aenv t.- PrettyAcc acc- -> Val aenv- -> Atuple (acc aenv) t- -> Doc-prettyAtuple pp aenv = tupled . collect- where- collect :: Atuple (acc aenv) t' -> [Doc]- collect NilAtup = []- collect (SnocAtup tup a) = collect tup ++ [pp noParens aenv a]--prettyTuple- :: forall acc env aenv t.- PrettyAcc acc- -> Val env- -> Val aenv- -> Tuple (PreOpenExp acc env aenv) t- -> Doc-prettyTuple pp env aenv = tupled . collect- where- collect :: Tuple (PreOpenExp acc env aenv) t' -> [Doc]- collect NilTup = []- collect (SnocTup tup e) = collect tup ++ [prettyPreOpenExp pp noParens env aenv e]----- Pretty print an index for a tuple projection----prettyTupleIdx :: TupleIdx t e -> Doc-prettyTupleIdx ix = char '#' <> int (toInt ix)- where- toInt :: TupleIdx t e -> Int- toInt ZeroTupIdx = 0- toInt (SuccTupIdx tup) = toInt tup + 1---- Pretty print a primitive constant----prettyConst :: PrimConst a -> Doc-prettyConst (PrimMinBound _) = text "minBound"-prettyConst (PrimMaxBound _) = text "maxBound"-prettyConst (PrimPi _) = text "pi"---- Pretty print a primitive operation. The first parameter indicates whether the--- operator should be printed infix.----prettyPrim :: PrimFun a -> (Bool, Doc)-prettyPrim PrimAdd{} = (True, char '+')-prettyPrim PrimSub{} = (True, char '-')-prettyPrim PrimMul{} = (True, char '*')-prettyPrim PrimNeg{} = (False, text "negate")-prettyPrim PrimAbs{} = (False, text "abs")-prettyPrim PrimSig{} = (False, text "signum")-prettyPrim PrimQuot{} = (False, text "quot")-prettyPrim PrimRem{} = (False, text "rem")-prettyPrim PrimQuotRem{} = (False, text "quotRem")-prettyPrim PrimIDiv{} = (False, text "div")-prettyPrim PrimMod{} = (False, text "mod")-prettyPrim PrimDivMod{} = (False, text "divMod")-prettyPrim PrimBAnd{} = (True, text ".&.")-prettyPrim PrimBOr{} = (True, text ".|.")-prettyPrim PrimBXor{} = (False, text "xor")-prettyPrim PrimBNot{} = (False, text "complement")-prettyPrim PrimBShiftL{} = (False, text "shiftL")-prettyPrim PrimBShiftR{} = (False, text "shiftR")-prettyPrim PrimBRotateL{} = (False, text "rotateL")-prettyPrim PrimBRotateR{} = (False, text "rotateR")-prettyPrim PrimPopCount{} = (False, text "popCount")-prettyPrim PrimCountLeadingZeros{} = (False, text "countLeadingZeros")-prettyPrim PrimCountTrailingZeros{} = (False, text "countTrailingZeros")-prettyPrim PrimFDiv{} = (True, char '/')-prettyPrim PrimRecip{} = (False, text "recip")-prettyPrim PrimSin{} = (False, text "sin")-prettyPrim PrimCos{} = (False, text "cos")-prettyPrim PrimTan{} = (False, text "tan")-prettyPrim PrimAsin{} = (False, text "asin")-prettyPrim PrimAcos{} = (False, text "acos")-prettyPrim PrimAtan{} = (False, text "atan")-prettyPrim PrimSinh{} = (False, text "sinh")-prettyPrim PrimCosh{} = (False, text "cosh")-prettyPrim PrimTanh{} = (False, text "tanh")-prettyPrim PrimAsinh{} = (False, text "asinh")-prettyPrim PrimAcosh{} = (False, text "acosh")-prettyPrim PrimAtanh{} = (False, text "atanh")-prettyPrim PrimExpFloating{} = (False, text "exp")-prettyPrim PrimSqrt{} = (False, text "sqrt")-prettyPrim PrimLog{} = (False, text "log")-prettyPrim PrimFPow{} = (True, text "**")-prettyPrim PrimLogBase{} = (False, text "logBase")-prettyPrim PrimTruncate{} = (False, text "truncate")-prettyPrim PrimRound{} = (False, text "round")-prettyPrim PrimFloor{} = (False, text "floor")-prettyPrim PrimCeiling{} = (False, text "ceiling")-prettyPrim PrimAtan2{} = (False, text "atan2")-prettyPrim PrimIsNaN{} = (False, text "isNaN")-prettyPrim PrimIsInfinite{} = (False, text "isInfinite")-prettyPrim PrimLt{} = (True, text "<")-prettyPrim PrimGt{} = (True, text ">")-prettyPrim PrimLtEq{} = (True, text "<=")-prettyPrim PrimGtEq{} = (True, text ">=")-prettyPrim PrimEq{} = (True, text "==")-prettyPrim PrimNEq{} = (True, text "/=")-prettyPrim PrimMax{} = (False, text "max")-prettyPrim PrimMin{} = (False, text "min")-prettyPrim PrimLAnd = (True, text "&&")-prettyPrim PrimLOr = (True, text "||")-prettyPrim PrimLNot = (False, text "not")-prettyPrim PrimOrd = (False, text "ord")-prettyPrim PrimChr = (False, text "chr")-prettyPrim PrimBoolToInt = (False, text "boolToInt")-prettyPrim PrimFromIntegral{} = (False, text "fromIntegral")-prettyPrim PrimToFloating{} = (False, text "toFloating")-prettyPrim (PrimCoerce _ t) = (False, text "reinterpret_cast" <> char '<' <> text (show t) <> char '>')--{---- Pretty print type----prettyAnyType :: ScalarType a -> Doc-prettyAnyType ty = text $ show ty--}---- TLM: seems to flatten the nesting structure----prettyArrays :: ArraysR arrs -> arrs -> Doc-prettyArrays arrs = tupled . collect arrs- where- collect :: ArraysR arrs -> arrs -> [Doc]- collect ArraysRunit _ = []- collect ArraysRarray arr = [prettyArray arr]- collect (ArraysRpair r1 r2) (a1, a2) = collect r1 a1 ++ collect r2 a2--prettyArray :: forall dim e. Array dim e -> Doc-prettyArray arr@(Array sh _)- = hang 2 $ sep [ text "Array"- , parens . text $ showShape (toElt sh :: dim)- , dataDoc ]- where- showDoc :: forall a. Show a => a -> Doc- showDoc = text . show- l = toList arr- dataDoc | length l <= 1000 = showDoc l- | otherwise = showDoc (take 1000 l) <+>- text "{truncated at 1000 elements}"----- Auxiliary pretty printing combinators-----parens :: Doc -> Doc-parens = PP.parens . align--noParens :: Doc -> Doc-noParens = id--tupled :: [Doc] -> Doc-tupled = PP.tupled . map align----- ANSI colourisation-----control :: Doc -> Doc-control = dullyellow--manifest :: Doc -> Doc-manifest = blue---- delayed :: Doc -> Doc--- delayed = green--let_, in_ :: Doc-let_ = control (text "let")-in_ = control (text "in")--if_, then_, else_ :: Doc-if_ = control (text "if")-then_ = control (text "then")-else_ = control (text "else")----- Environments--- --------------data Val env where- Empty :: Val ()- Push :: Val env -> Doc -> Val (env, t)--class PrettyEnv env where- prettyEnv :: Val env--instance PrettyEnv () where- prettyEnv = Empty--instance PrettyEnv env => PrettyEnv (env, t) where- prettyEnv =- let env = prettyEnv :: Val env- x = char 'a' <> int (sizeEnv env)- in- env `Push` x--sizeEnv :: Val env -> Int-sizeEnv Empty = 0-sizeEnv (Push env _) = 1 + sizeEnv env--prj :: Idx env t -> Val env -> Doc-prj ZeroIdx (Push _ v) = v-prj (SuccIdx ix) (Push env _) = prj ix env-#if __GLASGOW_HASKELL__ < 800-prj _ _ = error "inconsistent valuation"-#endif----- Auxiliary operations--- ------------------------ Auxiliary dictionary operations-----{---- Show scalar values----runScalarShow :: ScalarType a -> (a -> String)-runScalarShow (NumScalarType (IntegralNumType ty))- | IntegralDict <- integralDict ty = show-runScalarShow (NumScalarType (FloatingNumType ty))- | FloatingDict <- floatingDict ty = show-runScalarShow (NonNumScalarType ty)- | NonNumDict <- nonNumDict ty = show--}-
− Data/Array/Accelerate/Product.hs
@@ -1,177 +0,0 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE UndecidableInstances #-}-{-# OPTIONS_HADDOCK hide #-}--- |--- Module : Data.Array.Accelerate.Product--- Copyright : [2008..2017] Manuel M T Chakravarty, Gabriele Keller--- [2009..2017] Trevor L. McDonell--- [2013..2017] Robert Clifton-Everest--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)------ Our representation of products are heterogenous snoc lists, which are typed by--- type lists, where '()' and '(,)' are type-level nil and snoc, respectively.--- The components may only be drawn from types that can be used as array--- elements.-----module Data.Array.Accelerate.Product (-- -- * Tuple representation- TupleIdx(..), IsProduct(..), ProdR(..)--) where----- |Type-safe projection indices for tuples.------ NB: We index tuples by starting to count from the *right*!----data TupleIdx t e where- ZeroTupIdx :: TupleIdx (t, s) s- SuccTupIdx :: TupleIdx t e -> TupleIdx (t, s) e---- |Product reification----data ProdR cst t where- ProdRunit :: ProdR cst ()- ProdRsnoc :: cst e => ProdR cst t -> ProdR cst (t,e)---- |Conversion between surface product types and our product representation.------ We parameterise our products by a constraint on their elements (the 'cst' argument). Every element--- in the product must obey this constraint, but the products themselves do necessarily not have to.----class IsProduct cst tup where- type ProdRepr tup- fromProd :: proxy cst -> tup -> ProdRepr tup- toProd :: proxy cst -> ProdRepr tup -> tup- prod :: proxy cst -> {- dummy -} tup -> ProdR cst (ProdRepr tup)--instance IsProduct cst () where- type ProdRepr () = ()- fromProd _ = id- toProd _ = id- prod _ _ = ProdRunit--instance (cst a, cst b) => IsProduct cst (a, b) where- type ProdRepr (a, b) = (((), a), b)- fromProd _ (a, b) = (((), a), b)- toProd _ (((), a), b) = (a, b)- prod _ _ = ProdRsnoc $ ProdRsnoc ProdRunit--instance (cst a, cst b, cst c) => IsProduct cst (a, b, c) where- type ProdRepr (a, b, c) = (ProdRepr (a, b), c)- fromProd _ (a, b, c) = ((((), a), b), c)- toProd _ ((((), a), b), c) = (a, b, c)- prod p _ = ProdRsnoc (prod p (undefined :: (a,b)))--instance (cst a, cst b, cst c, cst d) => IsProduct cst (a, b, c, d) where- type ProdRepr (a, b, c, d) = (ProdRepr (a, b, c), d)- fromProd _ (a, b, c, d) = (((((), a), b), c), d)- toProd _ (((((), a), b), c), d) = (a, b, c, d)- prod p _ = ProdRsnoc (prod p (undefined :: (a,b,c)))--instance (cst a, cst b, cst c, cst d, cst e) => IsProduct cst (a, b, c, d, e) where- type ProdRepr (a, b, c, d, e) = (ProdRepr (a, b, c, d), e)- fromProd _ (a, b, c, d, e) = ((((((), a), b), c), d), e)- toProd _ ((((((), a), b), c), d), e) = (a, b, c, d, e)- prod p _ = ProdRsnoc (prod p (undefined :: (a,b,c,d)))--instance (cst a, cst b, cst c, cst d, cst e, cst f) => IsProduct cst (a, b, c, d, e, f) where- type ProdRepr (a, b, c, d, e, f) = (ProdRepr (a, b, c, d, e), f)- fromProd _ (a, b, c, d, e, f) = (((((((), a), b), c), d), e), f)- toProd _ (((((((), a), b), c), d), e), f) = (a, b, c, d, e, f)- prod p _ = ProdRsnoc (prod p (undefined :: (a,b,c,d,e)))--instance (cst a, cst b, cst c, cst d, cst e, cst f, cst g)- => IsProduct cst (a, b, c, d, e, f, g) where- type ProdRepr (a, b, c, d, e, f, g) = (ProdRepr (a, b, c, d, e, f), g)- fromProd _ (a, b, c, d, e, f, g) = ((((((((), a), b), c), d), e), f), g)- toProd _ ((((((((), a), b), c), d), e), f), g) = (a, b, c, d, e, f, g)- prod p _ = ProdRsnoc (prod p (undefined :: (a,b,c,d,e,f)))--instance (cst a, cst b, cst c, cst d, cst e, cst f, cst g, cst h)- => IsProduct cst (a, b, c, d, e, f, g, h) where- type ProdRepr (a, b, c, d, e, f, g, h) = (ProdRepr (a, b, c, d, e, f, g), h)- fromProd _ (a, b, c, d, e, f, g, h) = (((((((((), a), b), c), d), e), f), g), h)- toProd _ (((((((((), a), b), c), d), e), f), g), h) = (a, b, c, d, e, f, g, h)- prod p _ = ProdRsnoc (prod p (undefined :: (a,b,c,d,e,f,g)))--instance (cst a, cst b, cst c, cst d, cst e, cst f, cst g, cst h, cst i)- => IsProduct cst (a, b, c, d, e, f, g, h, i) where- type ProdRepr (a, b, c, d, e, f, g, h, i) = (ProdRepr (a, b, c, d, e, f, g, h), i)- fromProd _ (a, b, c, d, e, f, g, h, i)- = ((((((((((), a), b), c), d), e), f), g), h), i)- toProd _ ((((((((((), a), b), c), d), e), f), g), h), i)- = (a, b, c, d, e, f, g, h, i)- prod p _- = ProdRsnoc (prod p (undefined :: (a,b,c,d,e,f,g,h)))--instance (cst a, cst b, cst c, cst d, cst e, cst f, cst g, cst h, cst i, cst j)- => IsProduct cst (a, b, c, d, e, f, g, h, i, j) where- type ProdRepr (a, b, c, d, e, f, g, h, i, j) = (ProdRepr (a, b, c, d, e, f, g, h, i), j)- fromProd _ (a, b, c, d, e, f, g, h, i, j)- = (((((((((((), a), b), c), d), e), f), g), h), i), j)- toProd _ (((((((((((), a), b), c), d), e), f), g), h), i), j)- = (a, b, c, d, e, f, g, h, i, j)- prod p _- = ProdRsnoc (prod p (undefined :: (a,b,c,d,e,f,g,h,i)))--instance (cst a, cst b, cst c, cst d, cst e, cst f, cst g, cst h, cst i, cst j, cst k)- => IsProduct cst (a, b, c, d, e, f, g, h, i, j, k) where- type ProdRepr (a, b, c, d, e, f, g, h, i, j, k) = (ProdRepr (a, b, c, d, e, f, g, h, i, j), k)- fromProd _ (a, b, c, d, e, f, g, h, i, j, k)- = ((((((((((((), a), b), c), d), e), f), g), h), i), j), k)- toProd _ ((((((((((((), a), b), c), d), e), f), g), h), i), j), k)- = (a, b, c, d, e, f, g, h, i, j, k)- prod p _- = ProdRsnoc (prod p (undefined :: (a,b,c,d,e,f,g,h,i,j)))--instance (cst a, cst b, cst c, cst d, cst e, cst f, cst g, cst h, cst i, cst j, cst k, cst l)- => IsProduct cst (a, b, c, d, e, f, g, h, i, j, k, l) where- type ProdRepr (a, b, c, d, e, f, g, h, i, j, k, l) = (ProdRepr (a, b, c, d, e, f, g, h, i, j, k), l)- fromProd _ (a, b, c, d, e, f, g, h, i, j, k, l)- = (((((((((((((), a), b), c), d), e), f), g), h), i), j), k), l)- toProd _ (((((((((((((), a), b), c), d), e), f), g), h), i), j), k), l)- = (a, b, c, d, e, f, g, h, i, j, k, l)- prod p _- = ProdRsnoc (prod p (undefined :: (a,b,c,d,e,f,g,h,i,j,k)))--instance (cst a, cst b, cst c, cst d, cst e, cst f, cst g, cst h, cst i, cst j, cst k, cst l, cst m)- => IsProduct cst (a, b, c, d, e, f, g, h, i, j, k, l, m) where- type ProdRepr (a, b, c, d, e, f, g, h, i, j, k, l, m) = (ProdRepr (a, b, c, d, e, f, g, h, i, j, k, l), m)- fromProd _ (a, b, c, d, e, f, g, h, i, j, k, l, m)- = ((((((((((((((), a), b), c), d), e), f), g), h), i), j), k), l), m)- toProd _ ((((((((((((((), a), b), c), d), e), f), g), h), i), j), k), l), m)- = (a, b, c, d, e, f, g, h, i, j, k, l, m)- prod p _- = ProdRsnoc (prod p (undefined :: (a,b,c,d,e,f,g,h,i,j,k,l)))--instance (cst a, cst b, cst c, cst d, cst e, cst f, cst g, cst h, cst i, cst j, cst k, cst l, cst m, cst n)- => IsProduct cst (a, b, c, d, e, f, g, h, i, j, k, l, m, n) where- type ProdRepr (a, b, c, d, e, f, g, h, i, j, k, l, m, n) = (ProdRepr (a, b, c, d, e, f, g, h, i, j, k, l, m), n)- fromProd _ (a, b, c, d, e, f, g, h, i, j, k, l, m, n)- = (((((((((((((((), a), b), c), d), e), f), g), h), i), j), k), l), m), n)- toProd _ (((((((((((((((), a), b), c), d), e), f), g), h), i), j), k), l), m), n)- = (a, b, c, d, e, f, g, h, i, j, k, l, m, n)- prod p _- = ProdRsnoc (prod p (undefined :: (a,b,c,d,e,f,g,h,i,j,k,l,m)))--instance (cst a, cst b, cst c, cst d, cst e, cst f, cst g, cst h, cst i, cst j, cst k, cst l, cst m, cst n, cst o)- => IsProduct cst (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) where- type ProdRepr (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) = (ProdRepr (a, b, c, d, e, f, g, h, i, j, k, l, m, n), o)- fromProd _ (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)- = ((((((((((((((((), a), b), c), d), e), f), g), h), i), j), k), l), m), n), o)- toProd _ ((((((((((((((((), a), b), c), d), e), f), g), h), i), j), k), l), m), n), o)- = (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)- prod p _- = ProdRsnoc (prod p (undefined :: (a,b,c,d,e,f,g,h,i,j,k,l,m,n)))-
− Data/Array/Accelerate/Smart.hs
@@ -1,2129 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}-{-# OPTIONS_HADDOCK hide #-}--- |--- Module : Data.Array.Accelerate.Smart--- Copyright : [2008..2017] Manuel M T Chakravarty, Gabriele Keller--- [2009..2017] Trevor L. McDonell--- [2013..2017] Robert Clifton-Everest--- [2014..2014] Frederik M. Madsen--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)------ This modules defines the AST of the user-visible embedded language using more--- convenient higher-order abstract syntax (instead of de Bruijn indices).--- Moreover, it defines smart constructors to construct programs.-----module Data.Array.Accelerate.Smart (-- -- * HOAS AST- Acc(..), PreAcc(..), Exp(..), PreExp(..), Boundary(..), PreBoundary(..), Stencil(..), Level,-- -- * Smart constructors for literals- constant,-- -- * Smart constructors and destructors for tuples- tup2, tup3, tup4, tup5, tup6, tup7, tup8, tup9, tup10, tup11, tup12, tup13, tup14, tup15,- untup2, untup3, untup4, untup5, untup6, untup7, untup8, untup9, untup10, untup11, untup12, untup13, untup14, untup15,-- atup2, atup3, atup4, atup5, atup6, atup7, atup8, atup9, atup10, atup11, atup12, atup13, atup14, atup15,- unatup2, unatup3, unatup4, unatup5, unatup6, unatup7, unatup8, unatup9, unatup10, unatup11, unatup12, unatup13, unatup14, unatup15,-- -- * Smart constructors for constants- mkMinBound, mkMaxBound, mkPi,- mkSin, mkCos, mkTan,- mkAsin, mkAcos, mkAtan,- mkSinh, mkCosh, mkTanh,- mkAsinh, mkAcosh, mkAtanh,- mkExpFloating, mkSqrt, mkLog,- mkFPow, mkLogBase,- mkTruncate, mkRound, mkFloor, mkCeiling,- mkAtan2,-- -- * Smart constructors for primitive functions- mkAdd, mkSub, mkMul, mkNeg, mkAbs, mkSig, mkQuot, mkRem, mkQuotRem, mkIDiv, mkMod, mkDivMod,- mkBAnd, mkBOr, mkBXor, mkBNot, mkBShiftL, mkBShiftR, mkBRotateL, mkBRotateR, mkPopCount, mkCountLeadingZeros, mkCountTrailingZeros,- mkFDiv, mkRecip, mkLt, mkGt, mkLtEq, mkGtEq, mkEq, mkNEq, mkMax, mkMin,- mkLAnd, mkLOr, mkLNot, mkIsNaN, mkIsInfinite,-- -- * Smart constructors for type coercion functions- mkOrd, mkChr, mkBoolToInt, mkFromIntegral, mkToFloating, mkBitcast, mkUnsafeCoerce,-- -- * Auxiliary functions- ($$), ($$$), ($$$$), ($$$$$),-- -- Debugging- showPreAccOp, showPreExpOp,--) where---- standard library-import Prelude hiding ( exp )-import Data.List-import Data.Typeable---- friends-import Data.Array.Accelerate.Type-import Data.Array.Accelerate.Array.Sugar-import Data.Array.Accelerate.Product-import Data.Array.Accelerate.AST hiding ( PreOpenAcc(..), OpenAcc(..), Acc- , PreOpenExp(..), OpenExp, PreExp, Exp- , Stencil(..), PreBoundary(..), Boundary- , showPreAccOp, showPreExpOp )-import qualified Data.Array.Accelerate.AST as AST---- Array computations--- ---------------------- | Accelerate is an /embedded language/ that distinguishes between vanilla--- arrays (e.g. in Haskell memory on the CPU) and embedded arrays (e.g. in--- device memory on a GPU), as well as the computations on both of these. Since--- Accelerate is an embedded language, programs written in Accelerate are not--- compiled by the Haskell compiler (GHC). Rather, each Accelerate backend is--- a /runtime compiler/ which generates and executes parallel SIMD code of the--- target language at application /runtime/.------ The type constructor 'Acc' represents embedded collective array operations.--- A term of type @Acc a@ is an Accelerate program which, once executed, will--- produce a value of type 'a' (an 'Array' or a tuple of 'Arrays'). Collective--- operations of type @Acc a@ comprise many /scalar expressions/, wrapped in--- type constructor 'Exp', which will be executed in parallel. Although--- collective operations comprise many scalar operations executed in parallel,--- scalar operations /cannot/ initiate new collective operations: this--- stratification between scalar operations in 'Exp' and array operations in--- 'Acc' helps statically exclude /nested data parallelism/, which is difficult--- to execute efficiently on constrained hardware such as GPUs.------ For example, to compute a vector dot product we could write:------ > dotp :: Num a => Vector a -> Vector a -> Acc (Scalar a)--- > dotp xs ys =--- > let--- > xs' = use xs--- > ys' = use ys--- > in--- > fold (+) 0 ( zipWith (*) xs' ys' )------ The function @dotp@ consumes two one-dimensional arrays ('Vector's) of--- values, and produces a single ('Scalar') result as output. As the return type--- is wrapped in the type 'Acc', we see that it is an embedded Accelerate--- computation - it will be evaluated in the /object/ language of dynamically--- generated parallel code, rather than the /meta/ language of vanilla Haskell.------ As the arguments to @dotp@ are plain Haskell arrays, to make these available--- to Accelerate computations they must be embedded with the--- 'Data.Array.Accelerate.Language.use' function.------ An Accelerate backend is used to evaluate the embedded computation and return--- the result back to vanilla Haskell. Calling the 'run' function of a backend--- will generate code for the target architecture, compile, and execute it. For--- example, the following backends are available:------ * <http://hackage.haskell.org/package/accelerate-llvm-native accelerate-llvm-native>: for execution on multicore CPUs--- * <http://hackage.haskell.org/package/accelerate-llvm-ptx accelerate-llvm-ptx>: for execution on NVIDIA CUDA-capable GPUs------ See also 'Exp', which encapsulates embedded /scalar/ computations.------ [/Fusion:/]------ Array computations of type 'Acc' will be subject to /array fusion/;--- Accelerate will combine individual 'Acc' computations into a single--- computation, which reduces the number of traversals over the input data and--- thus improves performance. As such, it is often useful to have some intuition--- on when fusion should occur.------ The main idea is to first partition array operations into two categories:------ 1. Element-wise operations, such as 'Data.Array.Accelerate.map',--- 'Data.Array.Accelerate.generate', and--- 'Data.Array.Accelerate.backpermute'. Each element of these operations--- can be computed independently of all others.------ 2. Collective operations such as 'Data.Array.Accelerate.fold',--- 'Data.Array.Accelerate.scanl', and 'Data.Array.Accelerate.stencil'. To--- compute each output element of these operations requires reading--- multiple elements from the input array(s).------ Element-wise operations fuse together whenever the consumer operation uses--- a single element of the input array. Element-wise operations can both fuse--- their inputs into themselves, as well be fused into later operations. Both--- these examples should fuse into a single loop:------ > map -> reverse -> reshape -> map -> map------ > map -> backpermute ->--- > zipWith -> map--- > generate ->------ If the consumer operation uses more than one element of the input array--- (typically, via 'Data.Array.Accelerate.generate' indexing an array multiple--- times), then the input array will be completely evaluated first; no fusion--- occurs in this case, because fusing the first operation into the second--- implies duplicating work.------ On the other hand, collective operations can fuse their input arrays into--- themselves, but on output always evaluate to an array; collective operations--- will not be fused into a later step. For example:------ > use ->--- > zipWith -> fold |-> map--- > generate ->------ Here the element-wise sequence ('Data.Array.Accelerate.use'--- + 'Data.Array.Accelerate.generate' + 'Data.Array.Accelerate.zipWith') will--- fuse into a single operation, which then fuses into the collective--- 'Data.Array.Accelerate.fold' operation. At this point in the program the--- 'Data.Array.Accelerate.fold' must now be evaluated. In the final step the--- 'Data.Array.Accelerate.map' reads in the array produced by--- 'Data.Array.Accelerate.fold'. As there is no fusion between the--- 'Data.Array.Accelerate.fold' and 'Data.Array.Accelerate.map' steps, this--- program consists of two "loops"; one for the 'Data.Array.Accelerate.use'--- + 'Data.Array.Accelerate.generate' + 'Data.Array.Accelerate.zipWith'--- + 'Data.Array.Accelerate.fold' step, and one for the final--- 'Data.Array.Accelerate.map' step.------ You can see how many operations will be executed in the fused program by--- 'Show'-ing the 'Acc' program, or by using the debugging option @-ddump-dot@--- to save the program as a graphviz DOT file.------ As a special note, the operations 'Data.Array.Accelerate.unzip' and--- 'Data.Array.Accelerate.reshape', when applied to a real array, are executed--- in constant time, so in this situation these operations will not be fused.------ [/Tips:/]------ * Since 'Acc' represents embedded computations that will only be executed--- when evaluated by a backend, we can programatically generate these--- computations using the meta language Haskell; for example, unrolling loops--- or embedding input values into the generated code.------ * It is usually best to keep all intermediate computations in 'Acc', and--- only 'run' the computation at the very end to produce the final result.--- This enables optimisations between intermediate results (e.g. array--- fusion) and, if the target architecture has a separate memory space as is--- the case of GPUs, to prevent excessive data transfers.----newtype Acc a = Acc (PreAcc Acc Exp a)-deriving instance Typeable Acc----- The level of lambda-bound variables. The root has level 0; then it increases with each bound--- variable — i.e., it is the same as the size of the environment at the defining occurrence.----type Level = Int---- | Array-valued collective computations without a recursive knot----data PreAcc acc exp as where- -- Needed for conversion to de Bruijn form- Atag :: Arrays as- => Level -- environment size at defining occurrence- -> PreAcc acc exp as-- Pipe :: (Arrays as, Arrays bs, Arrays cs)- => (Acc as -> acc bs)- -> (Acc bs -> acc cs)- -> acc as- -> PreAcc acc exp cs-- Aforeign :: (Arrays as, Arrays bs, Foreign asm)- => asm (as -> bs)- -> (Acc as -> Acc bs)- -> acc as- -> PreAcc acc exp bs-- Acond :: Arrays as- => exp Bool- -> acc as- -> acc as- -> PreAcc acc exp as-- Awhile :: Arrays arrs- => (Acc arrs -> acc (Scalar Bool))- -> (Acc arrs -> acc arrs)- -> acc arrs- -> PreAcc acc exp arrs-- Atuple :: (Arrays arrs, IsAtuple arrs)- => Atuple acc (TupleRepr arrs)- -> PreAcc acc exp arrs-- Aprj :: (Arrays arrs, IsAtuple arrs, Arrays a)- => TupleIdx (TupleRepr arrs) a- -> acc arrs- -> PreAcc acc exp a-- Use :: Arrays arrs- => arrs- -> PreAcc acc exp arrs-- Unit :: Elt e- => exp e- -> PreAcc acc exp (Scalar e)-- Generate :: (Shape sh, Elt e)- => exp sh- -> (Exp sh -> exp e)- -> PreAcc acc exp (Array sh e)-- Reshape :: (Shape sh, Shape sh', Elt e)- => exp sh- -> acc (Array sh' e)- -> PreAcc acc exp (Array sh e)-- Replicate :: (Slice slix, Elt e)- => exp slix- -> acc (Array (SliceShape slix) e)- -> PreAcc acc exp (Array (FullShape slix) e)-- Slice :: (Slice slix, Elt e)- => acc (Array (FullShape slix) e)- -> exp slix- -> PreAcc acc exp (Array (SliceShape slix) e)-- Map :: (Shape sh, Elt e, Elt e')- => (Exp e -> exp e')- -> acc (Array sh e)- -> PreAcc acc exp (Array sh e')-- ZipWith :: (Shape sh, Elt e1, Elt e2, Elt e3)- => (Exp e1 -> Exp e2 -> exp e3)- -> acc (Array sh e1)- -> acc (Array sh e2)- -> PreAcc acc exp (Array sh e3)-- Fold :: (Shape sh, Elt e)- => (Exp e -> Exp e -> exp e)- -> exp e- -> acc (Array (sh:.Int) e)- -> PreAcc acc exp (Array sh e)-- Fold1 :: (Shape sh, Elt e)- => (Exp e -> Exp e -> exp e)- -> acc (Array (sh:.Int) e)- -> PreAcc acc exp (Array sh e)-- FoldSeg :: (Shape sh, Elt e, Elt i, IsIntegral i)- => (Exp e -> Exp e -> exp e)- -> exp e- -> acc (Array (sh:.Int) e)- -> acc (Segments i)- -> PreAcc acc exp (Array (sh:.Int) e)-- Fold1Seg :: (Shape sh, Elt e, Elt i, IsIntegral i)- => (Exp e -> Exp e -> exp e)- -> acc (Array (sh:.Int) e)- -> acc (Segments i)- -> PreAcc acc exp (Array (sh:.Int) e)-- Scanl :: (Shape sh, Elt e)- => (Exp e -> Exp e -> exp e)- -> exp e- -> acc (Array (sh :. Int) e)- -> PreAcc acc exp (Array (sh :. Int) e)-- Scanl' :: (Shape sh, Elt e)- => (Exp e -> Exp e -> exp e)- -> exp e- -> acc (Array (sh :. Int) e)- -> PreAcc acc exp (Array (sh :. Int) e, Array sh e)-- Scanl1 :: (Shape sh, Elt e)- => (Exp e -> Exp e -> exp e)- -> acc (Array (sh :. Int) e)- -> PreAcc acc exp (Array (sh :. Int) e)-- Scanr :: (Shape sh, Elt e)- => (Exp e -> Exp e -> exp e)- -> exp e- -> acc (Array (sh :. Int) e)- -> PreAcc acc exp (Array (sh :. Int) e)-- Scanr' :: (Shape sh, Elt e)- => (Exp e -> Exp e -> exp e)- -> exp e- -> acc (Array (sh :. Int) e)- -> PreAcc acc exp (Array (sh :. Int) e, Array sh e)-- Scanr1 :: (Shape sh, Elt e)- => (Exp e -> Exp e -> exp e)- -> acc (Array (sh :. Int) e)- -> PreAcc acc exp (Array (sh :. Int) e)-- Permute :: (Shape sh, Shape sh', Elt e)- => (Exp e -> Exp e -> exp e)- -> acc (Array sh' e)- -> (Exp sh -> exp sh')- -> acc (Array sh e)- -> PreAcc acc exp (Array sh' e)-- Backpermute :: (Shape sh, Shape sh', Elt e)- => exp sh'- -> (Exp sh' -> exp sh)- -> acc (Array sh e)- -> PreAcc acc exp (Array sh' e)-- Stencil :: (Shape sh, Elt a, Elt b, Stencil sh a stencil)- => (stencil -> exp b)- -> PreBoundary acc exp (Array sh a)- -> acc (Array sh a)- -> PreAcc acc exp (Array sh b)-- Stencil2 :: (Shape sh, Elt a, Elt b, Elt c, Stencil sh a stencil1, Stencil sh b stencil2)- => (stencil1 -> stencil2 -> exp c)- -> PreBoundary acc exp (Array sh a)- -> acc (Array sh a)- -> PreBoundary acc exp (Array sh b)- -> acc (Array sh b)- -> PreAcc acc exp (Array sh c)-- -- Collect :: Arrays arrs- -- => seq arrs- -- -> PreAcc acc seq exp arrs---{---data PreSeq acc seq exp arrs where- -- Convert the given Haskell-list of arrays to a sequence.- StreamIn :: Arrays a- => [a]- -> PreSeq acc seq exp [a]-- -- Convert the given array to a sequence.- -- Example:- -- slix = Z :. All :. Split :. All :. All :. Split- -- ^ ^ ^ ^ ^- -- | \ / / |- -- | \___/______/_______ Iteration space.- -- | / /- -- Element________/______/- -- shape.- --- ToSeq :: ( Elt e- , Slice slix- , Division slsix- , DivisionSlice slsix ~ slix- , Typeable (FullShape slix)- , Typeable (SliceShape slix)- )- => slsix- -> acc (Array (FullShape slix) e)- -> PreSeq acc seq exp [Array (SliceShape slix) e]-- -- Apply the given the given function to all elements of the given sequence.- MapSeq :: (Arrays a, Arrays b)- => (Acc a -> acc b)- -> seq [a]- -> PreSeq acc seq exp [b]-- -- Apply a given binary function pairwise to all elements of the given sequences.- -- The length of the result is the length of the shorter of the two argument- -- arrays.- ZipWithSeq :: (Arrays a, Arrays b, Arrays c)- => (Acc a -> Acc b -> acc c)- -> seq [a]- -> seq [b]- -> PreSeq acc seq exp [c]-- -- ScanSeq (+) a0 x. Scan a sequence x by combining each element- -- using the given binary operation (+). (+) must be associative:- --- -- Forall a b c. (a + b) + c = a + (b + c),- --- -- and a0 must be the identity element for (+):- --- -- Forall a. a0 + a = a = a + a0.- --- ScanSeq :: Elt a- => (Exp a -> Exp a -> exp a)- -> exp a- -> seq [Scalar a]- -> PreSeq acc seq exp [Scalar a]-- -- FoldSeq (+) a0 x. Fold a sequence x by combining each element- -- using the given binary operation (+). (+) must be associative:- --- -- Forall a b c. (a + b) + c = a + (b + c),- --- -- and a0 must be the identity element for (+):- --- -- Forall a. a0 + a = a = a + a0.- --- FoldSeq :: Elt a- => (Exp a -> Exp a -> exp a)- -> exp a- -> seq [Scalar a]- -> PreSeq acc seq exp (Scalar a)-- -- FoldSeqFlatten f a0 x. A specialized version of FoldSeqAct- -- where reduction with the companion operator corresponds to- -- flattening. f must be semi-associative, with vecotor append (++)- -- as the companion operator:- --- -- Forall b s1 a2 sh2 a2.- -- f (f b sh1 a1) sh2 a2 = f b (sh1 ++ sh2) (a1 ++ a2).- --- -- It is common to ignore the shape vectors, yielding the usual- -- semi-associativity law:- --- -- f b a _ = b + a,- --- -- for some (+) satisfying:- --- -- Forall b a1 a2. (b + a1) + a2 = b + (a1 ++ a2).- --- FoldSeqFlatten :: (Arrays a, Shape sh, Elt e)- => (Acc a -> Acc (Vector sh) -> Acc (Vector e) -> acc a)- -> acc a- -> seq [Array sh e]- -> PreSeq acc seq exp a-- -- Tuple up the results of a sequence computation. Note that the Arrays- -- constraint requires that the elements of the tuple are Arrays, not- -- streams ([]).- Stuple :: (Arrays arrs, IsAtuple arrs)- => Atuple (seq) (TupleRepr arrs)- -> PreSeq acc seq exp arrs---- |Array-valued sequence computations----newtype Seq a = Seq (PreSeq Acc Seq Exp a)--deriving instance Typeable Seq---}----- Embedded expressions of the surface language--- ------------------------------------------------ HOAS expressions mirror the constructors of 'AST.OpenExp', but with the 'Tag'--- constructor instead of variables in the form of de Bruijn indices. Moreover,--- HOAS expression use n-tuples and the type class 'Elt' to constrain element--- types, whereas 'AST.OpenExp' uses nested pairs and the GADT 'TupleType'.------- | The type 'Exp' represents embedded scalar expressions. The collective--- operations of Accelerate 'Acc' consist of many scalar expressions executed in--- data-parallel.------ Note that scalar expressions can not initiate new collective operations:--- doing so introduces /nested data parallelism/, which is difficult to execute--- efficiently on constrained hardware such as GPUs, and is thus currently--- unsupported.----newtype Exp t = Exp (PreExp Acc Exp t)--deriving instance Typeable Exp---- | Scalar expressions to parametrise collective array operations, themselves parameterised over--- the type of collective array operations.----data PreExp acc exp t where- -- Needed for conversion to de Bruijn form- Tag :: Elt t- => Level -- environment size at defining occurrence- -> PreExp acc exp t-- -- All the same constructors as 'AST.Exp'- Const :: Elt t- => t- -> PreExp acc exp t-- Tuple :: (Elt t, IsTuple t)- => Tuple exp (TupleRepr t)- -> PreExp acc exp t-- Prj :: (Elt t, IsTuple t, Elt e)- => TupleIdx (TupleRepr t) e- -> exp t- -> PreExp acc exp e-- IndexNil :: PreExp acc exp Z-- IndexCons :: (Slice sl, Elt a)- => exp sl- -> exp a- -> PreExp acc exp (sl:.a)-- IndexHead :: (Slice sl, Elt a)- => exp (sl:.a)- -> PreExp acc exp a-- IndexTail :: (Slice sl, Elt a)- => exp (sl:.a)- -> PreExp acc exp sl-- IndexAny :: Shape sh- => PreExp acc exp (Any sh)-- ToIndex :: Shape sh- => exp sh- -> exp sh- -> PreExp acc exp Int-- FromIndex :: Shape sh- => exp sh- -> exp Int- -> PreExp acc exp sh-- Cond :: Elt t- => exp Bool- -> exp t- -> exp t- -> PreExp acc exp t-- While :: Elt t- => (Exp t -> exp Bool)- -> (Exp t -> exp t)- -> exp t- -> PreExp acc exp t-- PrimConst :: Elt t- => PrimConst t- -> PreExp acc exp t-- PrimApp :: (Elt a, Elt r)- => PrimFun (a -> r)- -> exp a- -> PreExp acc exp r-- Index :: (Shape sh, Elt t)- => acc (Array sh t)- -> exp sh- -> PreExp acc exp t-- LinearIndex :: (Shape sh, Elt t)- => acc (Array sh t)- -> exp Int- -> PreExp acc exp t-- Shape :: (Shape sh, Elt e)- => acc (Array sh e)- -> PreExp acc exp sh-- ShapeSize :: Shape sh- => exp sh- -> PreExp acc exp Int-- Intersect :: Shape sh- => exp sh- -> exp sh- -> PreExp acc exp sh-- Union :: Shape sh- => exp sh- -> exp sh- -> PreExp acc exp sh-- Foreign :: (Elt x, Elt y, Foreign asm)- => asm (x -> y)- -> (Exp x -> Exp y) -- RCE: Using Exp instead of exp to aid in sharing recovery.- -> exp x- -> PreExp acc exp y----- Smart constructors and destructors for array tuples--- -----------------------------------------------------atup2 :: (Arrays a, Arrays b)- => (Acc a, Acc b)- -> Acc (a, b)-atup2 (a, b)- = Acc- $ Atuple- $ NilAtup `SnocAtup` a- `SnocAtup` b--atup3 :: (Arrays a, Arrays b, Arrays c)- => (Acc a, Acc b, Acc c)- -> Acc (a, b, c)-atup3 (a, b, c)- = Acc $ Atuple- $ NilAtup `SnocAtup` a- `SnocAtup` b- `SnocAtup` c--atup4 :: (Arrays a, Arrays b, Arrays c, Arrays d)- => (Acc a, Acc b, Acc c, Acc d)- -> Acc (a, b, c, d)-atup4 (a, b, c, d)- = Acc- $ Atuple- $ NilAtup `SnocAtup` a- `SnocAtup` b- `SnocAtup` c- `SnocAtup` d--atup5 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e)- => (Acc a, Acc b, Acc c, Acc d, Acc e)- -> Acc (a, b, c, d, e)-atup5 (a, b, c, d, e)- = Acc- $ Atuple- $ NilAtup `SnocAtup` a- `SnocAtup` b- `SnocAtup` c- `SnocAtup` d- `SnocAtup` e--atup6 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f)- => (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f)- -> Acc (a, b, c, d, e, f)-atup6 (a, b, c, d, e, f)- = Acc- $ Atuple- $ NilAtup `SnocAtup` a- `SnocAtup` b- `SnocAtup` c- `SnocAtup` d- `SnocAtup` e- `SnocAtup` f--atup7 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g)- => (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g)- -> Acc (a, b, c, d, e, f, g)-atup7 (a, b, c, d, e, f, g)- = Acc- $ Atuple- $ NilAtup `SnocAtup` a- `SnocAtup` b- `SnocAtup` c- `SnocAtup` d- `SnocAtup` e- `SnocAtup` f- `SnocAtup` g--atup8 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h)- => (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h)- -> Acc (a, b, c, d, e, f, g, h)-atup8 (a, b, c, d, e, f, g, h)- = Acc- $ Atuple- $ NilAtup `SnocAtup` a- `SnocAtup` b- `SnocAtup` c- `SnocAtup` d- `SnocAtup` e- `SnocAtup` f- `SnocAtup` g- `SnocAtup` h--atup9 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i)- => (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i)- -> Acc (a, b, c, d, e, f, g, h, i)-atup9 (a, b, c, d, e, f, g, h, i)- = Acc- $ Atuple- $ NilAtup `SnocAtup` a- `SnocAtup` b- `SnocAtup` c- `SnocAtup` d- `SnocAtup` e- `SnocAtup` f- `SnocAtup` g- `SnocAtup` h- `SnocAtup` i--atup10 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j)- => (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j)- -> Acc (a, b, c, d, e, f, g, h, i, j)-atup10 (a, b, c, d, e, f, g, h, i, j)- = Acc- $ Atuple- $ NilAtup `SnocAtup` a- `SnocAtup` b- `SnocAtup` c- `SnocAtup` d- `SnocAtup` e- `SnocAtup` f- `SnocAtup` g- `SnocAtup` h- `SnocAtup` i- `SnocAtup` j--atup11 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k)- => (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j, Acc k)- -> Acc (a, b, c, d, e, f, g, h, i, j, k)-atup11 (a, b, c, d, e, f, g, h, i, j, k)- = Acc- $ Atuple- $ NilAtup `SnocAtup` a- `SnocAtup` b- `SnocAtup` c- `SnocAtup` d- `SnocAtup` e- `SnocAtup` f- `SnocAtup` g- `SnocAtup` h- `SnocAtup` i- `SnocAtup` j- `SnocAtup` k--atup12 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l)- => (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j, Acc k, Acc l)- -> Acc (a, b, c, d, e, f, g, h, i, j, k, l)-atup12 (a, b, c, d, e, f, g, h, i, j, k, l)- = Acc- $ Atuple- $ NilAtup `SnocAtup` a- `SnocAtup` b- `SnocAtup` c- `SnocAtup` d- `SnocAtup` e- `SnocAtup` f- `SnocAtup` g- `SnocAtup` h- `SnocAtup` i- `SnocAtup` j- `SnocAtup` k- `SnocAtup` l--atup13 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l, Arrays m)- => (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j, Acc k, Acc l, Acc m)- -> Acc (a, b, c, d, e, f, g, h, i, j, k, l, m)-atup13 (a, b, c, d, e, f, g, h, i, j, k, l, m)- = Acc- $ Atuple- $ NilAtup `SnocAtup` a- `SnocAtup` b- `SnocAtup` c- `SnocAtup` d- `SnocAtup` e- `SnocAtup` f- `SnocAtup` g- `SnocAtup` h- `SnocAtup` i- `SnocAtup` j- `SnocAtup` k- `SnocAtup` l- `SnocAtup` m--atup14 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l, Arrays m, Arrays n)- => (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j, Acc k, Acc l, Acc m, Acc n)- -> Acc (a, b, c, d, e, f, g, h, i, j, k, l, m, n)-atup14 (a, b, c, d, e, f, g, h, i, j, k, l, m, n)- = Acc- $ Atuple- $ NilAtup `SnocAtup` a- `SnocAtup` b- `SnocAtup` c- `SnocAtup` d- `SnocAtup` e- `SnocAtup` f- `SnocAtup` g- `SnocAtup` h- `SnocAtup` i- `SnocAtup` j- `SnocAtup` k- `SnocAtup` l- `SnocAtup` m- `SnocAtup` n--atup15 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l, Arrays m, Arrays n, Arrays o)- => (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j, Acc k, Acc l, Acc m, Acc n, Acc o)- -> Acc (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)-atup15 (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)- = Acc- $ Atuple- $ NilAtup `SnocAtup` a- `SnocAtup` b- `SnocAtup` c- `SnocAtup` d- `SnocAtup` e- `SnocAtup` f- `SnocAtup` g- `SnocAtup` h- `SnocAtup` i- `SnocAtup` j- `SnocAtup` k- `SnocAtup` l- `SnocAtup` m- `SnocAtup` n- `SnocAtup` o--unatup2 :: (Arrays a, Arrays b)- => Acc (a, b)- -> (Acc a, Acc b)-unatup2 e =- ( Acc $ tix1 `Aprj` e- , Acc $ tix0 `Aprj` e )--unatup3 :: (Arrays a, Arrays b, Arrays c)- => Acc (a, b, c)- -> (Acc a, Acc b, Acc c)-unatup3 e =- ( Acc $ tix2 `Aprj` e- , Acc $ tix1 `Aprj` e- , Acc $ tix0 `Aprj` e )--unatup4- :: (Arrays a, Arrays b, Arrays c, Arrays d)- => Acc (a, b, c, d)- -> (Acc a, Acc b, Acc c, Acc d)-unatup4 e =- ( Acc $ tix3 `Aprj` e- , Acc $ tix2 `Aprj` e- , Acc $ tix1 `Aprj` e- , Acc $ tix0 `Aprj` e )--unatup5- :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e)- => Acc (a, b, c, d, e)- -> (Acc a, Acc b, Acc c, Acc d, Acc e)-unatup5 e =- ( Acc $ tix4 `Aprj` e- , Acc $ tix3 `Aprj` e- , Acc $ tix2 `Aprj` e- , Acc $ tix1 `Aprj` e- , Acc $ tix0 `Aprj` e )--unatup6- :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f)- => Acc (a, b, c, d, e, f)- -> (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f)-unatup6 e =- ( Acc $ tix5 `Aprj` e- , Acc $ tix4 `Aprj` e- , Acc $ tix3 `Aprj` e- , Acc $ tix2 `Aprj` e- , Acc $ tix1 `Aprj` e- , Acc $ tix0 `Aprj` e )--unatup7- :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g)- => Acc (a, b, c, d, e, f, g)- -> (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g)-unatup7 e =- ( Acc $ tix6 `Aprj` e- , Acc $ tix5 `Aprj` e- , Acc $ tix4 `Aprj` e- , Acc $ tix3 `Aprj` e- , Acc $ tix2 `Aprj` e- , Acc $ tix1 `Aprj` e- , Acc $ tix0 `Aprj` e )--unatup8- :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h)- => Acc (a, b, c, d, e, f, g, h)- -> (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h)-unatup8 e =- ( Acc $ tix7 `Aprj` e- , Acc $ tix6 `Aprj` e- , Acc $ tix5 `Aprj` e- , Acc $ tix4 `Aprj` e- , Acc $ tix3 `Aprj` e- , Acc $ tix2 `Aprj` e- , Acc $ tix1 `Aprj` e- , Acc $ tix0 `Aprj` e )--unatup9- :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i)- => Acc (a, b, c, d, e, f, g, h, i)- -> (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i)-unatup9 e =- ( Acc $ tix8 `Aprj` e- , Acc $ tix7 `Aprj` e- , Acc $ tix6 `Aprj` e- , Acc $ tix5 `Aprj` e- , Acc $ tix4 `Aprj` e- , Acc $ tix3 `Aprj` e- , Acc $ tix2 `Aprj` e- , Acc $ tix1 `Aprj` e- , Acc $ tix0 `Aprj` e )--unatup10- :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j)- => Acc (a, b, c, d, e, f, g, h, i, j)- -> (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j)-unatup10 e =- ( Acc $ tix9 `Aprj` e- , Acc $ tix8 `Aprj` e- , Acc $ tix7 `Aprj` e- , Acc $ tix6 `Aprj` e- , Acc $ tix5 `Aprj` e- , Acc $ tix4 `Aprj` e- , Acc $ tix3 `Aprj` e- , Acc $ tix2 `Aprj` e- , Acc $ tix1 `Aprj` e- , Acc $ tix0 `Aprj` e )--unatup11- :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k)- => Acc (a, b, c, d, e, f, g, h, i, j, k)- -> (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j, Acc k)-unatup11 e =- ( Acc $ tix10 `Aprj` e- , Acc $ tix9 `Aprj` e- , Acc $ tix8 `Aprj` e- , Acc $ tix7 `Aprj` e- , Acc $ tix6 `Aprj` e- , Acc $ tix5 `Aprj` e- , Acc $ tix4 `Aprj` e- , Acc $ tix3 `Aprj` e- , Acc $ tix2 `Aprj` e- , Acc $ tix1 `Aprj` e- , Acc $ tix0 `Aprj` e )--unatup12- :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l)- => Acc (a, b, c, d, e, f, g, h, i, j, k, l)- -> (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j, Acc k, Acc l)-unatup12 e =- ( Acc $ tix11 `Aprj` e- , Acc $ tix10 `Aprj` e- , Acc $ tix9 `Aprj` e- , Acc $ tix8 `Aprj` e- , Acc $ tix7 `Aprj` e- , Acc $ tix6 `Aprj` e- , Acc $ tix5 `Aprj` e- , Acc $ tix4 `Aprj` e- , Acc $ tix3 `Aprj` e- , Acc $ tix2 `Aprj` e- , Acc $ tix1 `Aprj` e- , Acc $ tix0 `Aprj` e )--unatup13- :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l, Arrays m)- => Acc (a, b, c, d, e, f, g, h, i, j, k, l, m)- -> (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j, Acc k, Acc l, Acc m)-unatup13 e =- ( Acc $ tix12 `Aprj` e- , Acc $ tix11 `Aprj` e- , Acc $ tix10 `Aprj` e- , Acc $ tix9 `Aprj` e- , Acc $ tix8 `Aprj` e- , Acc $ tix7 `Aprj` e- , Acc $ tix6 `Aprj` e- , Acc $ tix5 `Aprj` e- , Acc $ tix4 `Aprj` e- , Acc $ tix3 `Aprj` e- , Acc $ tix2 `Aprj` e- , Acc $ tix1 `Aprj` e- , Acc $ tix0 `Aprj` e )--unatup14- :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l, Arrays m, Arrays n)- => Acc (a, b, c, d, e, f, g, h, i, j, k, l, m, n)- -> (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j, Acc k, Acc l, Acc m, Acc n)-unatup14 e =- ( Acc $ tix13 `Aprj` e- , Acc $ tix12 `Aprj` e- , Acc $ tix11 `Aprj` e- , Acc $ tix10 `Aprj` e- , Acc $ tix9 `Aprj` e- , Acc $ tix8 `Aprj` e- , Acc $ tix7 `Aprj` e- , Acc $ tix6 `Aprj` e- , Acc $ tix5 `Aprj` e- , Acc $ tix4 `Aprj` e- , Acc $ tix3 `Aprj` e- , Acc $ tix2 `Aprj` e- , Acc $ tix1 `Aprj` e- , Acc $ tix0 `Aprj` e )--unatup15- :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l, Arrays m, Arrays n, Arrays o)- => Acc (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)- -> (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j, Acc k, Acc l, Acc m, Acc n, Acc o)-unatup15 e =- ( Acc $ tix14 `Aprj` e- , Acc $ tix13 `Aprj` e- , Acc $ tix12 `Aprj` e- , Acc $ tix11 `Aprj` e- , Acc $ tix10 `Aprj` e- , Acc $ tix9 `Aprj` e- , Acc $ tix8 `Aprj` e- , Acc $ tix7 `Aprj` e- , Acc $ tix6 `Aprj` e- , Acc $ tix5 `Aprj` e- , Acc $ tix4 `Aprj` e- , Acc $ tix3 `Aprj` e- , Acc $ tix2 `Aprj` e- , Acc $ tix1 `Aprj` e- , Acc $ tix0 `Aprj` e )----- Smart constructors for stencils--- ----------------------------------- | Boundary condition specification for stencil operations----newtype Boundary t = Boundary (PreBoundary Acc Exp t)--data PreBoundary acc exp t where- Clamp :: PreBoundary acc exp t- Mirror :: PreBoundary acc exp t- Wrap :: PreBoundary acc exp t-- Constant :: Elt e- => e- -> PreBoundary acc exp (Array sh e)-- Function :: (Shape sh, Elt e)- => (Exp sh -> exp e)- -> PreBoundary acc exp (Array sh e)----- Stencil reification------ In the AST representation, we turn the stencil type from nested tuples of Accelerate expressions--- into an Accelerate expression whose type is a tuple nested in the same manner. This enables us--- to represent the stencil function as a unary function (which also only needs one de Bruijn--- index). The various positions in the stencil are accessed via tuple indices (i.e., projections).----class (Elt (StencilRepr sh stencil), AST.Stencil sh a (StencilRepr sh stencil)) => Stencil sh a stencil where- type StencilRepr sh stencil :: *- stencilPrj :: {-dummy-} sh- -> {-dummy-} a- -> Exp (StencilRepr sh stencil)- -> stencil---- DIM1-instance Elt e => Stencil DIM1 e (Exp e, Exp e, Exp e) where- type StencilRepr DIM1 (Exp e, Exp e, Exp e)- = (e, e, e)- stencilPrj _ _ s = (Exp $ Prj tix2 s,- Exp $ Prj tix1 s,- Exp $ Prj tix0 s)--instance Elt e => Stencil DIM1 e (Exp e, Exp e, Exp e, Exp e, Exp e) where- type StencilRepr DIM1 (Exp e, Exp e, Exp e, Exp e, Exp e)- = (e, e, e, e, e)- stencilPrj _ _ s = (Exp $ Prj tix4 s,- Exp $ Prj tix3 s,- Exp $ Prj tix2 s,- Exp $ Prj tix1 s,- Exp $ Prj tix0 s)--instance Elt e => Stencil DIM1 e (Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e) where- type StencilRepr DIM1 (Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e)- = (e, e, e, e, e, e, e)- stencilPrj _ _ s = (Exp $ Prj tix6 s,- Exp $ Prj tix5 s,- Exp $ Prj tix4 s,- Exp $ Prj tix3 s,- Exp $ Prj tix2 s,- Exp $ Prj tix1 s,- Exp $ Prj tix0 s)--instance Elt e => Stencil DIM1 e (Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e)- where- type StencilRepr DIM1 (Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e)- = (e, e, e, e, e, e, e, e, e)- stencilPrj _ _ s = (Exp $ Prj tix8 s,- Exp $ Prj tix7 s,- Exp $ Prj tix6 s,- Exp $ Prj tix5 s,- Exp $ Prj tix4 s,- Exp $ Prj tix3 s,- Exp $ Prj tix2 s,- Exp $ Prj tix1 s,- Exp $ Prj tix0 s)---- DIM(n+1)-instance (Stencil (sh:.Int) a row2,- Stencil (sh:.Int) a row1,- Stencil (sh:.Int) a row0) => Stencil (sh:.Int:.Int) a (row2, row1, row0) where- type StencilRepr (sh:.Int:.Int) (row2, row1, row0)- = (StencilRepr (sh:.Int) row2, StencilRepr (sh:.Int) row1, StencilRepr (sh:.Int) row0)- stencilPrj _ a s = (stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix2 s),- stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix1 s),- stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix0 s))--instance (Stencil (sh:.Int) a row1,- Stencil (sh:.Int) a row2,- Stencil (sh:.Int) a row3,- Stencil (sh:.Int) a row4,- Stencil (sh:.Int) a row5) => Stencil (sh:.Int:.Int) a (row1, row2, row3, row4, row5) where- type StencilRepr (sh:.Int:.Int) (row1, row2, row3, row4, row5)- = (StencilRepr (sh:.Int) row1, StencilRepr (sh:.Int) row2, StencilRepr (sh:.Int) row3,- StencilRepr (sh:.Int) row4, StencilRepr (sh:.Int) row5)- stencilPrj _ a s = (stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix4 s),- stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix3 s),- stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix2 s),- stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix1 s),- stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix0 s))--instance (Stencil (sh:.Int) a row1,- Stencil (sh:.Int) a row2,- Stencil (sh:.Int) a row3,- Stencil (sh:.Int) a row4,- Stencil (sh:.Int) a row5,- Stencil (sh:.Int) a row6,- Stencil (sh:.Int) a row7)- => Stencil (sh:.Int:.Int) a (row1, row2, row3, row4, row5, row6, row7) where- type StencilRepr (sh:.Int:.Int) (row1, row2, row3, row4, row5, row6, row7)- = (StencilRepr (sh:.Int) row1, StencilRepr (sh:.Int) row2, StencilRepr (sh:.Int) row3,- StencilRepr (sh:.Int) row4, StencilRepr (sh:.Int) row5, StencilRepr (sh:.Int) row6,- StencilRepr (sh:.Int) row7)- stencilPrj _ a s = (stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix6 s),- stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix5 s),- stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix4 s),- stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix3 s),- stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix2 s),- stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix1 s),- stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix0 s))--instance (Stencil (sh:.Int) a row1,- Stencil (sh:.Int) a row2,- Stencil (sh:.Int) a row3,- Stencil (sh:.Int) a row4,- Stencil (sh:.Int) a row5,- Stencil (sh:.Int) a row6,- Stencil (sh:.Int) a row7,- Stencil (sh:.Int) a row8,- Stencil (sh:.Int) a row9)- => Stencil (sh:.Int:.Int) a (row1, row2, row3, row4, row5, row6, row7, row8, row9) where- type StencilRepr (sh:.Int:.Int) (row1, row2, row3, row4, row5, row6, row7, row8, row9)- = (StencilRepr (sh:.Int) row1, StencilRepr (sh:.Int) row2, StencilRepr (sh:.Int) row3,- StencilRepr (sh:.Int) row4, StencilRepr (sh:.Int) row5, StencilRepr (sh:.Int) row6,- StencilRepr (sh:.Int) row7, StencilRepr (sh:.Int) row8, StencilRepr (sh:.Int) row9)- stencilPrj _ a s = (stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix8 s),- stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix7 s),- stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix6 s),- stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix5 s),- stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix4 s),- stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix3 s),- stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix2 s),- stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix1 s),- stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix0 s))---- Auxiliary tuple index constants----tix0 :: TupleIdx (t, s0) s0-tix0 = ZeroTupIdx--tix1 :: TupleIdx ((t, s1), s0) s1-tix1 = SuccTupIdx tix0--tix2 :: TupleIdx (((t, s2), s1), s0) s2-tix2 = SuccTupIdx tix1--tix3 :: TupleIdx ((((t, s3), s2), s1), s0) s3-tix3 = SuccTupIdx tix2--tix4 :: TupleIdx (((((t, s4), s3), s2), s1), s0) s4-tix4 = SuccTupIdx tix3--tix5 :: TupleIdx ((((((t, s5), s4), s3), s2), s1), s0) s5-tix5 = SuccTupIdx tix4--tix6 :: TupleIdx (((((((t, s6), s5), s4), s3), s2), s1), s0) s6-tix6 = SuccTupIdx tix5--tix7 :: TupleIdx ((((((((t, s7), s6), s5), s4), s3), s2), s1), s0) s7-tix7 = SuccTupIdx tix6--tix8 :: TupleIdx (((((((((t, s8), s7), s6), s5), s4), s3), s2), s1), s0) s8-tix8 = SuccTupIdx tix7--tix9 :: TupleIdx ((((((((((t, s9), s8), s7), s6), s5), s4), s3), s2), s1), s0) s9-tix9 = SuccTupIdx tix8--tix10 :: TupleIdx (((((((((((t, s10), s9), s8), s7), s6), s5), s4), s3), s2), s1), s0) s10-tix10 = SuccTupIdx tix9--tix11 :: TupleIdx ((((((((((((t, s11), s10), s9), s8), s7), s6), s5), s4), s3), s2), s1), s0) s11-tix11 = SuccTupIdx tix10--tix12 :: TupleIdx (((((((((((((t, s12), s11), s10), s9), s8), s7), s6), s5), s4), s3), s2), s1), s0) s12-tix12 = SuccTupIdx tix11--tix13 :: TupleIdx ((((((((((((((t, s13), s12), s11), s10), s9), s8), s7), s6), s5), s4), s3), s2), s1), s0) s13-tix13 = SuccTupIdx tix12--tix14 :: TupleIdx (((((((((((((((t, s14), s13), s12), s11), s10), s9), s8), s7), s6), s5), s4), s3), s2), s1), s0) s14-tix14 = SuccTupIdx tix13--{----- Smart constructors for array tuples in sequence computations--- -----------------------------------------------------stup2 :: (Arrays a, Arrays b) => (Seq a, Seq b) -> Seq (a, b)-stup2 (a, b) = Seq $ Stuple (NilAtup `SnocAtup` a `SnocAtup` b)--stup3 :: (Arrays a, Arrays b, Arrays c) => (Seq a, Seq b, Seq c) -> Seq (a, b, c)-stup3 (a, b, c) = Seq $ Stuple (NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c)--stup4 :: (Arrays a, Arrays b, Arrays c, Arrays d)- => (Seq a, Seq b, Seq c, Seq d) -> Seq (a, b, c, d)-stup4 (a, b, c, d)- = Seq $ Stuple (NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c `SnocAtup` d)--stup5 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e)- => (Seq a, Seq b, Seq c, Seq d, Seq e) -> Seq (a, b, c, d, e)-stup5 (a, b, c, d, e)- = Seq $ Stuple $- NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c `SnocAtup` d `SnocAtup` e--stup6 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f)- => (Seq a, Seq b, Seq c, Seq d, Seq e, Seq f) -> Seq (a, b, c, d, e, f)-stup6 (a, b, c, d, e, f)- = Seq $ Stuple $- NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c- `SnocAtup` d `SnocAtup` e `SnocAtup` f--stup7 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g)- => (Seq a, Seq b, Seq c, Seq d, Seq e, Seq f, Seq g)- -> Seq (a, b, c, d, e, f, g)-stup7 (a, b, c, d, e, f, g)- = Seq $ Stuple $- NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c- `SnocAtup` d `SnocAtup` e `SnocAtup` f `SnocAtup` g--stup8 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h)- => (Seq a, Seq b, Seq c, Seq d, Seq e, Seq f, Seq g, Seq h)- -> Seq (a, b, c, d, e, f, g, h)-stup8 (a, b, c, d, e, f, g, h)- = Seq $ Stuple $- NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c `SnocAtup` d- `SnocAtup` e `SnocAtup` f `SnocAtup` g `SnocAtup` h--stup9 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i)- => (Seq a, Seq b, Seq c, Seq d, Seq e, Seq f, Seq g, Seq h, Seq i)- -> Seq (a, b, c, d, e, f, g, h, i)-stup9 (a, b, c, d, e, f, g, h, i)- = Seq $ Stuple $- NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c `SnocAtup` d- `SnocAtup` e `SnocAtup` f `SnocAtup` g `SnocAtup` h `SnocAtup` i--stup10 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j)- => (Seq a, Seq b, Seq c, Seq d, Seq e, Seq f, Seq g, Seq h, Seq i, Seq j)- -> Seq (a, b, c, d, e, f, g, h, i, j)-stup10 (a, b, c, d, e, f, g, h, i, j)- = Seq $ Stuple $- NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c `SnocAtup` d `SnocAtup` e- `SnocAtup` f `SnocAtup` g `SnocAtup` h `SnocAtup` i `SnocAtup` j--stup11 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k)- => (Seq a, Seq b, Seq c, Seq d, Seq e, Seq f, Seq g, Seq h, Seq i, Seq j, Seq k)- -> Seq (a, b, c, d, e, f, g, h, i, j, k)-stup11 (a, b, c, d, e, f, g, h, i, j, k)- = Seq $ Stuple $- NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c `SnocAtup` d `SnocAtup` e- `SnocAtup` f `SnocAtup` g `SnocAtup` h `SnocAtup` i `SnocAtup` j `SnocAtup` k--stup12 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l)- => (Seq a, Seq b, Seq c, Seq d, Seq e, Seq f, Seq g, Seq h, Seq i, Seq j, Seq k, Seq l)- -> Seq (a, b, c, d, e, f, g, h, i, j, k, l)-stup12 (a, b, c, d, e, f, g, h, i, j, k, l)- = Seq $ Stuple $- NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c `SnocAtup` d `SnocAtup` e `SnocAtup` f- `SnocAtup` g `SnocAtup` h `SnocAtup` i `SnocAtup` j `SnocAtup` k `SnocAtup` l--stup13 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l, Arrays m)- => (Seq a, Seq b, Seq c, Seq d, Seq e, Seq f, Seq g, Seq h, Seq i, Seq j, Seq k, Seq l, Seq m)- -> Seq (a, b, c, d, e, f, g, h, i, j, k, l, m)-stup13 (a, b, c, d, e, f, g, h, i, j, k, l, m)- = Seq $ Stuple $- NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c `SnocAtup` d `SnocAtup` e `SnocAtup` f- `SnocAtup` g `SnocAtup` h `SnocAtup` i `SnocAtup` j `SnocAtup` k `SnocAtup` l `SnocAtup` m--stup14 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l, Arrays m, Arrays n)- => (Seq a, Seq b, Seq c, Seq d, Seq e, Seq f, Seq g, Seq h, Seq i, Seq j, Seq k, Seq l, Seq m, Seq n)- -> Seq (a, b, c, d, e, f, g, h, i, j, k, l, m, n)-stup14 (a, b, c, d, e, f, g, h, i, j, k, l, m, n)- = Seq $ Stuple $- NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c `SnocAtup` d `SnocAtup` e `SnocAtup` f `SnocAtup` g- `SnocAtup` h `SnocAtup` i `SnocAtup` j `SnocAtup` k `SnocAtup` l `SnocAtup` m `SnocAtup` n--stup15 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l, Arrays m, Arrays n, Arrays o)- => (Seq a, Seq b, Seq c, Seq d, Seq e, Seq f, Seq g, Seq h, Seq i, Seq j, Seq k, Seq l, Seq m, Seq n, Seq o)- -> Seq (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)-stup15 (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)- = Seq $ Stuple $- NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c `SnocAtup` d `SnocAtup` e `SnocAtup` f `SnocAtup` g- `SnocAtup` h `SnocAtup` i `SnocAtup` j `SnocAtup` k `SnocAtup` l `SnocAtup` m `SnocAtup` n `SnocAtup` o---}---- Smart constructor for literals------- | Scalar expression inlet: make a Haskell value available for processing in--- an Accelerate scalar expression.------ Note that this embeds the value directly into the expression. Depending on--- the backend used to execute the computation, this might not always be--- desirable. For example, a backend that does external code generation may--- embed this constant directly into the generated code, which means new code--- will need to be generated and compiled every time the value changes. In such--- cases, consider instead lifting scalar values into (singleton) arrays so that--- they can be passed as an input to the computation and thus the value can--- change without the need to generate fresh code.----constant :: Elt t => t -> Exp t-constant = Exp . Const---- Smart constructor and destructors for scalar tuples----tup2 :: (Elt a, Elt b) => (Exp a, Exp b) -> Exp (a, b)-tup2 (a, b)- = Exp- $ Tuple- $ NilTup `SnocTup` a- `SnocTup` b--tup3 :: (Elt a, Elt b, Elt c)- => (Exp a, Exp b, Exp c)- -> Exp (a, b, c)-tup3 (a, b, c)- = Exp- $ Tuple- $ NilTup `SnocTup` a- `SnocTup` b- `SnocTup` c--tup4 :: (Elt a, Elt b, Elt c, Elt d)- => (Exp a, Exp b, Exp c, Exp d)- -> Exp (a, b, c, d)-tup4 (a, b, c, d)- = Exp- $ Tuple- $ NilTup `SnocTup` a- `SnocTup` b- `SnocTup` c- `SnocTup` d--tup5 :: (Elt a, Elt b, Elt c, Elt d, Elt e)- => (Exp a, Exp b, Exp c, Exp d, Exp e)- -> Exp (a, b, c, d, e)-tup5 (a, b, c, d, e)- = Exp- $ Tuple- $ NilTup `SnocTup` a- `SnocTup` b- `SnocTup` c- `SnocTup` d- `SnocTup` e--tup6 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f)- => (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f)- -> Exp (a, b, c, d, e, f)-tup6 (a, b, c, d, e, f)- = Exp- $ Tuple- $ NilTup `SnocTup` a- `SnocTup` b- `SnocTup` c- `SnocTup` d- `SnocTup` e- `SnocTup` f--tup7 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g)- => (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g)- -> Exp (a, b, c, d, e, f, g)-tup7 (a, b, c, d, e, f, g)- = Exp- $ Tuple- $ NilTup `SnocTup` a- `SnocTup` b- `SnocTup` c- `SnocTup` d- `SnocTup` e- `SnocTup` f- `SnocTup` g--tup8 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h)- => (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h)- -> Exp (a, b, c, d, e, f, g, h)-tup8 (a, b, c, d, e, f, g, h)- = Exp- $ Tuple- $ NilTup `SnocTup` a- `SnocTup` b- `SnocTup` c- `SnocTup` d- `SnocTup` e- `SnocTup` f- `SnocTup` g- `SnocTup` h--tup9 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i)- => (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i)- -> Exp (a, b, c, d, e, f, g, h, i)-tup9 (a, b, c, d, e, f, g, h, i)- = Exp- $ Tuple- $ NilTup `SnocTup` a- `SnocTup` b- `SnocTup` c- `SnocTup` d- `SnocTup` e- `SnocTup` f- `SnocTup` g- `SnocTup` h- `SnocTup` i--tup10 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j)- => (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j)- -> Exp (a, b, c, d, e, f, g, h, i, j)-tup10 (a, b, c, d, e, f, g, h, i, j)- = Exp- $ Tuple- $ NilTup `SnocTup` a- `SnocTup` b- `SnocTup` c- `SnocTup` d- `SnocTup` e- `SnocTup` f- `SnocTup` g- `SnocTup` h- `SnocTup` i- `SnocTup` j--tup11 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k)- => (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j, Exp k)- -> Exp (a, b, c, d, e, f, g, h, i, j, k)-tup11 (a, b, c, d, e, f, g, h, i, j, k)- = Exp- $ Tuple- $ NilTup `SnocTup` a- `SnocTup` b- `SnocTup` c- `SnocTup` d- `SnocTup` e- `SnocTup` f- `SnocTup` g- `SnocTup` h- `SnocTup` i- `SnocTup` j- `SnocTup` k--tup12 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l)- => (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j, Exp k, Exp l)- -> Exp (a, b, c, d, e, f, g, h, i, j, k, l)-tup12 (a, b, c, d, e, f, g, h, i, j, k, l)- = Exp- $ Tuple- $ NilTup `SnocTup` a- `SnocTup` b- `SnocTup` c- `SnocTup` d- `SnocTup` e- `SnocTup` f- `SnocTup` g- `SnocTup` h- `SnocTup` i- `SnocTup` j- `SnocTup` k- `SnocTup` l--tup13 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l, Elt m)- => (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j, Exp k, Exp l, Exp m)- -> Exp (a, b, c, d, e, f, g, h, i, j, k, l, m)-tup13 (a, b, c, d, e, f, g, h, i, j, k, l, m)- = Exp- $ Tuple- $ NilTup `SnocTup` a- `SnocTup` b- `SnocTup` c- `SnocTup` d- `SnocTup` e- `SnocTup` f- `SnocTup` g- `SnocTup` h- `SnocTup` i- `SnocTup` j- `SnocTup` k- `SnocTup` l- `SnocTup` m--tup14 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l, Elt m, Elt n)- => (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j, Exp k, Exp l, Exp m, Exp n)- -> Exp (a, b, c, d, e, f, g, h, i, j, k, l, m, n)-tup14 (a, b, c, d, e, f, g, h, i, j, k, l, m, n)- = Exp- $ Tuple- $ NilTup `SnocTup` a- `SnocTup` b- `SnocTup` c- `SnocTup` d- `SnocTup` e- `SnocTup` f- `SnocTup` g- `SnocTup` h- `SnocTup` i- `SnocTup` j- `SnocTup` k- `SnocTup` l- `SnocTup` m- `SnocTup` n--tup15 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l, Elt m, Elt n, Elt o)- => (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j, Exp k, Exp l, Exp m, Exp n, Exp o)- -> Exp (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)-tup15 (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)- = Exp- $ Tuple- $ NilTup `SnocTup` a- `SnocTup` b- `SnocTup` c- `SnocTup` d- `SnocTup` e- `SnocTup` f- `SnocTup` g- `SnocTup` h- `SnocTup` i- `SnocTup` j- `SnocTup` k- `SnocTup` l- `SnocTup` m- `SnocTup` n- `SnocTup` o--untup2 :: (Elt a, Elt b) => Exp (a, b) -> (Exp a, Exp b)-untup2 e =- ( Exp $ tix1 `Prj` e- , Exp $ tix0 `Prj` e )--untup3 :: (Elt a, Elt b, Elt c) => Exp (a, b, c) -> (Exp a, Exp b, Exp c)-untup3 e =- ( Exp $ tix2 `Prj` e- , Exp $ tix1 `Prj` e- , Exp $ tix0 `Prj` e )--untup4 :: (Elt a, Elt b, Elt c, Elt d)- => Exp (a, b, c, d)- -> (Exp a, Exp b, Exp c, Exp d)-untup4 e =- ( Exp $ tix3 `Prj` e- , Exp $ tix2 `Prj` e- , Exp $ tix1 `Prj` e- , Exp $ tix0 `Prj` e )--untup5 :: (Elt a, Elt b, Elt c, Elt d, Elt e)- => Exp (a, b, c, d, e)- -> (Exp a, Exp b, Exp c, Exp d, Exp e)-untup5 e =- ( Exp $ tix4 `Prj` e- , Exp $ tix3 `Prj` e- , Exp $ tix2 `Prj` e- , Exp $ tix1 `Prj` e- , Exp $ tix0 `Prj` e )--untup6 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f)- => Exp (a, b, c, d, e, f)- -> (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f)-untup6 e =- ( Exp $ tix5 `Prj` e- , Exp $ tix4 `Prj` e- , Exp $ tix3 `Prj` e- , Exp $ tix2 `Prj` e- , Exp $ tix1 `Prj` e- , Exp $ tix0 `Prj` e )--untup7 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g)- => Exp (a, b, c, d, e, f, g)- -> (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g)-untup7 e =- ( Exp $ tix6 `Prj` e- , Exp $ tix5 `Prj` e- , Exp $ tix4 `Prj` e- , Exp $ tix3 `Prj` e- , Exp $ tix2 `Prj` e- , Exp $ tix1 `Prj` e- , Exp $ tix0 `Prj` e )--untup8 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h)- => Exp (a, b, c, d, e, f, g, h)- -> (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h)-untup8 e =- ( Exp $ tix7 `Prj` e- , Exp $ tix6 `Prj` e- , Exp $ tix5 `Prj` e- , Exp $ tix4 `Prj` e- , Exp $ tix3 `Prj` e- , Exp $ tix2 `Prj` e- , Exp $ tix1 `Prj` e- , Exp $ tix0 `Prj` e )--untup9 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i)- => Exp (a, b, c, d, e, f, g, h, i)- -> (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i)-untup9 e =- ( Exp $ tix8 `Prj` e- , Exp $ tix7 `Prj` e- , Exp $ tix6 `Prj` e- , Exp $ tix5 `Prj` e- , Exp $ tix4 `Prj` e- , Exp $ tix3 `Prj` e- , Exp $ tix2 `Prj` e- , Exp $ tix1 `Prj` e- , Exp $ tix0 `Prj` e )--untup10 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j)- => Exp (a, b, c, d, e, f, g, h, i, j)- -> (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j)-untup10 e =- ( Exp $ tix9 `Prj` e- , Exp $ tix8 `Prj` e- , Exp $ tix7 `Prj` e- , Exp $ tix6 `Prj` e- , Exp $ tix5 `Prj` e- , Exp $ tix4 `Prj` e- , Exp $ tix3 `Prj` e- , Exp $ tix2 `Prj` e- , Exp $ tix1 `Prj` e- , Exp $ tix0 `Prj` e )--untup11 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k)- => Exp (a, b, c, d, e, f, g, h, i, j, k)- -> (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j, Exp k)-untup11 e =- ( Exp $ tix10 `Prj` e- , Exp $ tix9 `Prj` e- , Exp $ tix8 `Prj` e- , Exp $ tix7 `Prj` e- , Exp $ tix6 `Prj` e- , Exp $ tix5 `Prj` e- , Exp $ tix4 `Prj` e- , Exp $ tix3 `Prj` e- , Exp $ tix2 `Prj` e- , Exp $ tix1 `Prj` e- , Exp $ tix0 `Prj` e )--untup12 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l)- => Exp (a, b, c, d, e, f, g, h, i, j, k, l)- -> (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j, Exp k, Exp l)-untup12 e =- ( Exp $ tix11 `Prj` e- , Exp $ tix10 `Prj` e- , Exp $ tix9 `Prj` e- , Exp $ tix8 `Prj` e- , Exp $ tix7 `Prj` e- , Exp $ tix6 `Prj` e- , Exp $ tix5 `Prj` e- , Exp $ tix4 `Prj` e- , Exp $ tix3 `Prj` e- , Exp $ tix2 `Prj` e- , Exp $ tix1 `Prj` e- , Exp $ tix0 `Prj` e )--untup13 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l, Elt m)- => Exp (a, b, c, d, e, f, g, h, i, j, k, l, m)- -> (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j, Exp k, Exp l, Exp m)-untup13 e =- ( Exp $ tix12 `Prj` e- , Exp $ tix11 `Prj` e- , Exp $ tix10 `Prj` e- , Exp $ tix9 `Prj` e- , Exp $ tix8 `Prj` e- , Exp $ tix7 `Prj` e- , Exp $ tix6 `Prj` e- , Exp $ tix5 `Prj` e- , Exp $ tix4 `Prj` e- , Exp $ tix3 `Prj` e- , Exp $ tix2 `Prj` e- , Exp $ tix1 `Prj` e- , Exp $ tix0 `Prj` e )--untup14 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l, Elt m, Elt n)- => Exp (a, b, c, d, e, f, g, h, i, j, k, l, m, n)- -> (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j, Exp k, Exp l, Exp m, Exp n)-untup14 e =- ( Exp $ tix13 `Prj` e- , Exp $ tix12 `Prj` e- , Exp $ tix11 `Prj` e- , Exp $ tix10 `Prj` e- , Exp $ tix9 `Prj` e- , Exp $ tix8 `Prj` e- , Exp $ tix7 `Prj` e- , Exp $ tix6 `Prj` e- , Exp $ tix5 `Prj` e- , Exp $ tix4 `Prj` e- , Exp $ tix3 `Prj` e- , Exp $ tix2 `Prj` e- , Exp $ tix1 `Prj` e- , Exp $ tix0 `Prj` e )--untup15 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l, Elt m, Elt n, Elt o)- => Exp (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)- -> (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j, Exp k, Exp l, Exp m, Exp n, Exp o)-untup15 e =- ( Exp $ tix14 `Prj` e- , Exp $ tix13 `Prj` e- , Exp $ tix12 `Prj` e- , Exp $ tix11 `Prj` e- , Exp $ tix10 `Prj` e- , Exp $ tix9 `Prj` e- , Exp $ tix8 `Prj` e- , Exp $ tix7 `Prj` e- , Exp $ tix6 `Prj` e- , Exp $ tix5 `Prj` e- , Exp $ tix4 `Prj` e- , Exp $ tix3 `Prj` e- , Exp $ tix2 `Prj` e- , Exp $ tix1 `Prj` e- , Exp $ tix0 `Prj` e )----- Smart constructor for constants-----mkMinBound :: (Elt t, IsBounded t) => Exp t-mkMinBound = Exp $ PrimConst (PrimMinBound boundedType)--mkMaxBound :: (Elt t, IsBounded t) => Exp t-mkMaxBound = Exp $ PrimConst (PrimMaxBound boundedType)--mkPi :: (Elt r, IsFloating r) => Exp r-mkPi = Exp $ PrimConst (PrimPi floatingType)----- Smart constructors for primitive applications------- Operators from Floating--mkSin :: (Elt t, IsFloating t) => Exp t -> Exp t-mkSin x = Exp $ PrimSin floatingType `PrimApp` x--mkCos :: (Elt t, IsFloating t) => Exp t -> Exp t-mkCos x = Exp $ PrimCos floatingType `PrimApp` x--mkTan :: (Elt t, IsFloating t) => Exp t -> Exp t-mkTan x = Exp $ PrimTan floatingType `PrimApp` x--mkAsin :: (Elt t, IsFloating t) => Exp t -> Exp t-mkAsin x = Exp $ PrimAsin floatingType `PrimApp` x--mkAcos :: (Elt t, IsFloating t) => Exp t -> Exp t-mkAcos x = Exp $ PrimAcos floatingType `PrimApp` x--mkAtan :: (Elt t, IsFloating t) => Exp t -> Exp t-mkAtan x = Exp $ PrimAtan floatingType `PrimApp` x--mkSinh :: (Elt t, IsFloating t) => Exp t -> Exp t-mkSinh x = Exp $ PrimSinh floatingType `PrimApp` x--mkCosh :: (Elt t, IsFloating t) => Exp t -> Exp t-mkCosh x = Exp $ PrimCosh floatingType `PrimApp` x--mkTanh :: (Elt t, IsFloating t) => Exp t -> Exp t-mkTanh x = Exp $ PrimTanh floatingType `PrimApp` x--mkAsinh :: (Elt t, IsFloating t) => Exp t -> Exp t-mkAsinh x = Exp $ PrimAsinh floatingType `PrimApp` x--mkAcosh :: (Elt t, IsFloating t) => Exp t -> Exp t-mkAcosh x = Exp $ PrimAcosh floatingType `PrimApp` x--mkAtanh :: (Elt t, IsFloating t) => Exp t -> Exp t-mkAtanh x = Exp $ PrimAtanh floatingType `PrimApp` x--mkExpFloating :: (Elt t, IsFloating t) => Exp t -> Exp t-mkExpFloating x = Exp $ PrimExpFloating floatingType `PrimApp` x--mkSqrt :: (Elt t, IsFloating t) => Exp t -> Exp t-mkSqrt x = Exp $ PrimSqrt floatingType `PrimApp` x--mkLog :: (Elt t, IsFloating t) => Exp t -> Exp t-mkLog x = Exp $ PrimLog floatingType `PrimApp` x--mkFPow :: (Elt t, IsFloating t) => Exp t -> Exp t -> Exp t-mkFPow x y = Exp $ PrimFPow floatingType `PrimApp` tup2 (x, y)--mkLogBase :: (Elt t, IsFloating t) => Exp t -> Exp t -> Exp t-mkLogBase x y = Exp $ PrimLogBase floatingType `PrimApp` tup2 (x, y)---- Operators from Num--mkAdd :: (Elt t, IsNum t) => Exp t -> Exp t -> Exp t-mkAdd x y = Exp $ PrimAdd numType `PrimApp` tup2 (x, y)--mkSub :: (Elt t, IsNum t) => Exp t -> Exp t -> Exp t-mkSub x y = Exp $ PrimSub numType `PrimApp` tup2 (x, y)--mkMul :: (Elt t, IsNum t) => Exp t -> Exp t -> Exp t-mkMul x y = Exp $ PrimMul numType `PrimApp` tup2 (x, y)--mkNeg :: (Elt t, IsNum t) => Exp t -> Exp t-mkNeg x = Exp $ PrimNeg numType `PrimApp` x--mkAbs :: (Elt t, IsNum t) => Exp t -> Exp t-mkAbs x = Exp $ PrimAbs numType `PrimApp` x--mkSig :: (Elt t, IsNum t) => Exp t -> Exp t-mkSig x = Exp $ PrimSig numType `PrimApp` x---- Operators from Integral--mkQuot :: (Elt t, IsIntegral t) => Exp t -> Exp t -> Exp t-mkQuot x y = Exp $ PrimQuot integralType `PrimApp` tup2 (x, y)--mkRem :: (Elt t, IsIntegral t) => Exp t -> Exp t -> Exp t-mkRem x y = Exp $ PrimRem integralType `PrimApp` tup2 (x, y)--mkQuotRem :: (Elt t, IsIntegral t) => Exp t -> Exp t -> (Exp t, Exp t)-mkQuotRem x y = untup2 $ Exp $ PrimQuotRem integralType `PrimApp` tup2 (x ,y)--mkIDiv :: (Elt t, IsIntegral t) => Exp t -> Exp t -> Exp t-mkIDiv x y = Exp $ PrimIDiv integralType `PrimApp` tup2 (x, y)--mkMod :: (Elt t, IsIntegral t) => Exp t -> Exp t -> Exp t-mkMod x y = Exp $ PrimMod integralType `PrimApp` tup2 (x, y)--mkDivMod :: (Elt t, IsIntegral t) => Exp t -> Exp t -> (Exp t, Exp t)-mkDivMod x y = untup2 $ Exp $ PrimDivMod integralType `PrimApp` tup2 (x ,y)----- Operators from Bits and FiniteBits--mkBAnd :: (Elt t, IsIntegral t) => Exp t -> Exp t -> Exp t-mkBAnd x y = Exp $ PrimBAnd integralType `PrimApp` tup2 (x, y)--mkBOr :: (Elt t, IsIntegral t) => Exp t -> Exp t -> Exp t-mkBOr x y = Exp $ PrimBOr integralType `PrimApp` tup2 (x, y)--mkBXor :: (Elt t, IsIntegral t) => Exp t -> Exp t -> Exp t-mkBXor x y = Exp $ PrimBXor integralType `PrimApp` tup2 (x, y)--mkBNot :: (Elt t, IsIntegral t) => Exp t -> Exp t-mkBNot x = Exp $ PrimBNot integralType `PrimApp` x--mkBShiftL :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t-mkBShiftL x i = Exp $ PrimBShiftL integralType `PrimApp` tup2 (x, i)--mkBShiftR :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t-mkBShiftR x i = Exp $ PrimBShiftR integralType `PrimApp` tup2 (x, i)--mkBRotateL :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t-mkBRotateL x i = Exp $ PrimBRotateL integralType `PrimApp` tup2 (x, i)--mkBRotateR :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t-mkBRotateR x i = Exp $ PrimBRotateR integralType `PrimApp` tup2 (x, i)--mkPopCount :: (Elt t, IsIntegral t) => Exp t -> Exp Int-mkPopCount x = Exp $ PrimPopCount integralType `PrimApp` x--mkCountLeadingZeros :: (Elt t, IsIntegral t) => Exp t -> Exp Int-mkCountLeadingZeros x = Exp $ PrimCountLeadingZeros integralType `PrimApp` x--mkCountTrailingZeros :: (Elt t, IsIntegral t) => Exp t -> Exp Int-mkCountTrailingZeros x = Exp $ PrimCountTrailingZeros integralType `PrimApp` x----- Operators from Fractional--mkFDiv :: (Elt t, IsFloating t) => Exp t -> Exp t -> Exp t-mkFDiv x y = Exp $ PrimFDiv floatingType `PrimApp` tup2 (x, y)--mkRecip :: (Elt t, IsFloating t) => Exp t -> Exp t-mkRecip x = Exp $ PrimRecip floatingType `PrimApp` x---- Operators from RealFrac--mkTruncate :: (Elt a, Elt b, IsFloating a, IsIntegral b) => Exp a -> Exp b-mkTruncate x = Exp $ PrimTruncate floatingType integralType `PrimApp` x--mkRound :: (Elt a, Elt b, IsFloating a, IsIntegral b) => Exp a -> Exp b-mkRound x = Exp $ PrimRound floatingType integralType `PrimApp` x--mkFloor :: (Elt a, Elt b, IsFloating a, IsIntegral b) => Exp a -> Exp b-mkFloor x = Exp $ PrimFloor floatingType integralType `PrimApp` x--mkCeiling :: (Elt a, Elt b, IsFloating a, IsIntegral b) => Exp a -> Exp b-mkCeiling x = Exp $ PrimCeiling floatingType integralType `PrimApp` x---- Operators from RealFloat--mkAtan2 :: (Elt t, IsFloating t) => Exp t -> Exp t -> Exp t-mkAtan2 x y = Exp $ PrimAtan2 floatingType `PrimApp` tup2 (x, y)--mkIsNaN :: (Elt t, IsFloating t) => Exp t -> Exp Bool-mkIsNaN x = Exp $ PrimIsNaN floatingType `PrimApp` x--mkIsInfinite :: (Elt t, IsFloating t) => Exp t -> Exp Bool-mkIsInfinite x = Exp $ PrimIsInfinite floatingType `PrimApp` x---- FIXME: add missing operations from Floating, RealFrac & RealFloat---- Relational and equality operators--mkLt :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp Bool-mkLt x y = Exp $ PrimLt scalarType `PrimApp` tup2 (x, y)--mkGt :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp Bool-mkGt x y = Exp $ PrimGt scalarType `PrimApp` tup2 (x, y)--mkLtEq :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp Bool-mkLtEq x y = Exp $ PrimLtEq scalarType `PrimApp` tup2 (x, y)--mkGtEq :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp Bool-mkGtEq x y = Exp $ PrimGtEq scalarType `PrimApp` tup2 (x, y)--mkEq :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp Bool-mkEq x y = Exp $ PrimEq scalarType `PrimApp` tup2 (x, y)--mkNEq :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp Bool-mkNEq x y = Exp $ PrimNEq scalarType `PrimApp` tup2 (x, y)--mkMax :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp t-mkMax x y = Exp $ PrimMax scalarType `PrimApp` tup2 (x, y)--mkMin :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp t-mkMin x y = Exp $ PrimMin scalarType `PrimApp` tup2 (x, y)---- Logical operators--mkLAnd :: Exp Bool -> Exp Bool -> Exp Bool-mkLAnd x y = Exp $ PrimLAnd `PrimApp` tup2 (x, y)--mkLOr :: Exp Bool -> Exp Bool -> Exp Bool-mkLOr x y = Exp $ PrimLOr `PrimApp` tup2 (x, y)--mkLNot :: Exp Bool -> Exp Bool-mkLNot x = Exp $ PrimLNot `PrimApp` x---- Character conversions--mkOrd :: Exp Char -> Exp Int-mkOrd x = Exp $ PrimOrd `PrimApp` x--mkChr :: Exp Int -> Exp Char-mkChr x = Exp $ PrimChr `PrimApp` x---- Numeric conversions--mkFromIntegral :: (Elt a, Elt b, IsIntegral a, IsNum b) => Exp a -> Exp b-mkFromIntegral x = Exp $ PrimFromIntegral integralType numType `PrimApp` x--mkToFloating :: (Elt a, Elt b, IsNum a, IsFloating b) => Exp a -> Exp b-mkToFloating x = Exp $ PrimToFloating numType floatingType `PrimApp` x---- Other conversions--mkBoolToInt :: Exp Bool -> Exp Int-mkBoolToInt b = Exp $ PrimBoolToInt `PrimApp` b---- NOTE: BitSizeEq constraint is used to make this version "safe"-mkBitcast :: (Elt a, Elt b, IsScalar a, IsScalar b, BitSizeEq a b) => Exp a -> Exp b-mkBitcast = mkUnsafeCoerce--mkUnsafeCoerce :: (Elt a, Elt b, IsScalar a, IsScalar b) => Exp a -> Exp b-mkUnsafeCoerce x = Exp $ PrimCoerce scalarType scalarType `PrimApp` x----- Auxiliary functions--- ----------------------infixr 0 $$-($$) :: (b -> a) -> (c -> d -> b) -> c -> d -> a-(f $$ g) x y = f (g x y)--infixr 0 $$$-($$$) :: (b -> a) -> (c -> d -> e -> b) -> c -> d -> e -> a-(f $$$ g) x y z = f (g x y z)--infixr 0 $$$$-($$$$) :: (b -> a) -> (c -> d -> e -> f -> b) -> c -> d -> e -> f -> a-(f $$$$ g) x y z u = f (g x y z u)--infixr 0 $$$$$-($$$$$) :: (b -> a) -> (c -> d -> e -> f -> g -> b) -> c -> d -> e -> f -> g-> a-(f $$$$$ g) x y z u v = f (g x y z u v)----- Debugging--- -----------showPreAccOp :: forall acc exp arrs. PreAcc acc exp arrs -> String-showPreAccOp (Atag i) = "Atag " ++ show i-showPreAccOp (Use a) = "Use " ++ showArrays a-showPreAccOp Pipe{} = "Pipe"-showPreAccOp Acond{} = "Acond"-showPreAccOp Awhile{} = "Awhile"-showPreAccOp Atuple{} = "Atuple"-showPreAccOp Aprj{} = "Aprj"-showPreAccOp Unit{} = "Unit"-showPreAccOp Generate{} = "Generate"-showPreAccOp Reshape{} = "Reshape"-showPreAccOp Replicate{} = "Replicate"-showPreAccOp Slice{} = "Slice"-showPreAccOp Map{} = "Map"-showPreAccOp ZipWith{} = "ZipWith"-showPreAccOp Fold{} = "Fold"-showPreAccOp Fold1{} = "Fold1"-showPreAccOp FoldSeg{} = "FoldSeg"-showPreAccOp Fold1Seg{} = "Fold1Seg"-showPreAccOp Scanl{} = "Scanl"-showPreAccOp Scanl'{} = "Scanl'"-showPreAccOp Scanl1{} = "Scanl1"-showPreAccOp Scanr{} = "Scanr"-showPreAccOp Scanr'{} = "Scanr'"-showPreAccOp Scanr1{} = "Scanr1"-showPreAccOp Permute{} = "Permute"-showPreAccOp Backpermute{} = "Backpermute"-showPreAccOp Stencil{} = "Stencil"-showPreAccOp Stencil2{} = "Stencil2"-showPreAccOp Aforeign{} = "Aforeign"--- showPreAccOp Collect{} = "Collect"--{---showPreSeqOp :: PreSeq acc seq exp arrs -> String-showPreSeqOp (StreamIn{}) = "StreamIn"-showPreSeqOp (ToSeq{}) = "ToSeq"-showPreSeqOp (MapSeq{}) = "MapSeq"-showPreSeqOp (ZipWithSeq{}) = "ZipWithSeq"-showPreSeqOp (ScanSeq{}) = "ScanSeq"-showPreSeqOp (FoldSeq{}) = "FoldSeq"-showPreSeqOp (FoldSeqFlatten{}) = "FoldSeqFlatten"-showPreSeqOp (Stuple{}) = "Stuple"---}--showArrays :: forall arrs. Arrays arrs => arrs -> String-showArrays = display . collect (arrays (undefined::arrs)) . fromArr- where- collect :: ArraysR a -> a -> [String]- collect ArraysRunit _ = []- collect ArraysRarray arr = [showShortendArr arr]- collect (ArraysRpair r1 r2) (a1, a2) = collect r1 a1 ++ collect r2 a2- --- display [] = []- display [x] = x- display xs = "(" ++ intercalate ", " xs ++ ")"---showShortendArr :: Elt e => Array sh e -> String-showShortendArr arr- = show (take cutoff l) ++ if length l > cutoff then ".." else ""- where- l = toList arr- cutoff = 5---showPreExpOp :: PreExp acc exp t -> String-showPreExpOp (Const c) = "Const " ++ show c-showPreExpOp (Tag i) = "Tag" ++ show i-showPreExpOp Tuple{} = "Tuple"-showPreExpOp Prj{} = "Prj"-showPreExpOp IndexNil = "IndexNil"-showPreExpOp IndexCons{} = "IndexCons"-showPreExpOp IndexHead{} = "IndexHead"-showPreExpOp IndexTail{} = "IndexTail"-showPreExpOp IndexAny = "IndexAny"-showPreExpOp ToIndex{} = "ToIndex"-showPreExpOp FromIndex{} = "FromIndex"-showPreExpOp Cond{} = "Cond"-showPreExpOp While{} = "While"-showPreExpOp PrimConst{} = "PrimConst"-showPreExpOp PrimApp{} = "PrimApp"-showPreExpOp Index{} = "Index"-showPreExpOp LinearIndex{} = "LinearIndex"-showPreExpOp Shape{} = "Shape"-showPreExpOp ShapeSize{} = "ShapeSize"-showPreExpOp Intersect{} = "Intersect"-showPreExpOp Union{} = "Union"-showPreExpOp Foreign{} = "Foreign"-
− Data/Array/Accelerate/Trafo.hs
@@ -1,242 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MonoLocalBinds #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE UndecidableInstances #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}-{-# OPTIONS_HADDOCK hide #-}--- |--- Module : Data.Array.Accelerate.Trafo--- Copyright : [2012..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Trafo (-- -- * HOAS -> de Bruijn conversion- Phase(..), phases,-- -- ** Array computations- convertAcc, convertAccWith,-- -- ** Array functions- Afunction, AfunctionR,- convertAfun, convertAfunWith,-- -- ** Sequence computations- -- convertSeq, convertSeqWith,-- -- * Fusion- module Data.Array.Accelerate.Trafo.Fusion,- -- DelayedSeq(..), Extend(..),-- -- * Substitution- module Data.Array.Accelerate.Trafo.Substitution,-- -- * Term equality- Match(..), (:~:)(..),-- -- ** Auxiliary- matchDelayedOpenAcc, hashDelayedOpenAcc,--) where--import Control.DeepSeq-import Data.Typeable--import Data.Array.Accelerate.Smart-import Data.Array.Accelerate.Pretty ( ) -- show instances-import Data.Array.Accelerate.Array.Sugar ( Arrays, Elt )-import Data.Array.Accelerate.Trafo.Base-import Data.Array.Accelerate.Trafo.Fusion hiding ( convertAcc, convertAfun ) -- to export types-import Data.Array.Accelerate.Trafo.Sharing ( Function, FunctionR, Afunction, AfunctionR )-import Data.Array.Accelerate.Trafo.Substitution-import qualified Data.Array.Accelerate.AST as AST-import qualified Data.Array.Accelerate.Trafo.Fusion as Fusion-import qualified Data.Array.Accelerate.Trafo.Rewrite as Rewrite-import qualified Data.Array.Accelerate.Trafo.Simplify as Rewrite-import qualified Data.Array.Accelerate.Trafo.Sharing as Sharing--- import qualified Data.Array.Accelerate.Trafo.Vectorise as Vectorise--#ifdef ACCELERATE_DEBUG-import Text.Printf-import System.IO.Unsafe-import Data.Array.Accelerate.Debug hiding ( when )-import qualified Data.Array.Accelerate.Debug as Debug-#endif----- Configuration--- ---------------data Phase = Phase- {- -- | Recover sharing of array computations?- recoverAccSharing :: Bool-- -- | Recover sharing of scalar expressions?- , recoverExpSharing :: Bool-- -- | Recover sharing of sequence computations?- , recoverSeqSharing :: Bool-- -- | Are array computations floated out of expressions irrespective of- -- whether they are shared or not? Requires 'recoverAccSharing'.- , floatOutAccFromExp :: Bool-- -- | Fuse array computations? This also implies simplifying scalar- -- expressions. NOTE: currently always enabled.- , enableAccFusion :: Bool-- -- | Convert segment length arrays into segment offset arrays?- , convertOffsetOfSegment :: Bool-- -- Vectorise maps and zipwiths in sequence computations to- -- enable chunked execution?- -- , vectoriseSequences :: Bool- }----- | The default method of converting from HOAS to de Bruijn; incorporating--- sharing recovery and fusion optimisation.----phases :: Phase-phases = Phase- { recoverAccSharing = True- , recoverExpSharing = True- , recoverSeqSharing = True- , floatOutAccFromExp = True- , enableAccFusion = True- , convertOffsetOfSegment = False- -- , vectoriseSequences = True- }--when :: (a -> a) -> Bool -> a -> a-when f True = f-when _ False = id----- HOAS -> de Bruijn conversion--- -------------------------------- | Convert a closed array expression to de Bruijn form while also--- incorporating sharing observation and array fusion.----convertAcc :: Arrays arrs => Acc arrs -> DelayedAcc arrs-convertAcc = convertAccWith phases--convertAccWith :: Arrays arrs => Phase -> Acc arrs -> DelayedAcc arrs-convertAccWith Phase{..} acc- = phase "array-fusion" (Fusion.convertAcc enableAccFusion)- -- phase "vectorise-sequences" Vectorise.vectoriseSeqAcc `when` vectoriseSequences- $ phase "rewrite-segment-offset" Rewrite.convertSegments `when` convertOffsetOfSegment- $ phase "sharing-recovery" (Sharing.convertAcc recoverAccSharing recoverExpSharing recoverSeqSharing floatOutAccFromExp)- $ acc----- | Convert a unary function over array computations, incorporating sharing--- observation and array fusion----convertAfun :: Afunction f => f -> DelayedAfun (AfunctionR f)-convertAfun = convertAfunWith phases--convertAfunWith :: Afunction f => Phase -> f -> DelayedAfun (AfunctionR f)-convertAfunWith Phase{..} acc- = phase "array-fusion" (Fusion.convertAfun enableAccFusion)- -- phase "vectorise-sequences" Vectorise.vectoriseSeqAfun `when` vectoriseSequences- $ phase "rewrite-segment-offset" Rewrite.convertSegmentsAfun `when` convertOffsetOfSegment- $ phase "sharing-recovery" (Sharing.convertAfun recoverAccSharing recoverExpSharing recoverSeqSharing floatOutAccFromExp)- $ acc----- | Convert a closed scalar expression, incorporating sharing observation and--- optimisation.----convertExp :: Elt e => Exp e -> AST.Exp () e-convertExp- = phase "exp-simplify" Rewrite.simplify- . phase "sharing-recovery" (Sharing.convertExp (recoverExpSharing phases))----- | Convert closed scalar functions, incorporating sharing observation and--- optimisation.----convertFun :: Function f => f -> AST.Fun () (FunctionR f)-convertFun- = phase "exp-simplify" Rewrite.simplify- . phase "sharing-recovery" (Sharing.convertFun (recoverExpSharing phases))--{----- | Convert a closed sequence computation, incorporating sharing observation and--- optimisation.----convertSeq :: Typeable s => Seq s -> DelayedSeq s-convertSeq = convertSeqWith phases--convertSeqWith :: Typeable s => Phase -> Seq s -> DelayedSeq s-convertSeqWith Phase{..} s- = phase "array-fusion" (Fusion.convertSeq enableAccFusion)- -- $ phase "vectorise-sequences" Vectorise.vectoriseSeq `when` vectoriseSequences- $ phase "rewrite-segment-offset" Rewrite.convertSegmentsSeq `when` convertOffsetOfSegment- $ phase "sharing-recovery" (Sharing.convertSeq recoverAccSharing recoverExpSharing recoverSeqSharing floatOutAccFromExp)- $ s---}---- Pretty printing--- -----------------instance Arrays arrs => Show (Acc arrs) where- show = withSimplStats . show . convertAcc--instance Afunction (Acc a -> f) => Show (Acc a -> f) where- show = withSimplStats . show . convertAfun--instance Elt e => Show (Exp e) where- show = withSimplStats . show . convertExp--instance Function (Exp a -> f) => Show (Exp a -> f) where- show = withSimplStats . show . convertFun---- instance Typeable a => Show (Seq a) where--- show = withSimplStats . show . convertSeq----- Debugging--- ------------- Attach simplifier statistics to the tail of the given string. Since the--- statistics rely on fully evaluating the expression this is difficult to do--- generally (without an additional deepseq), but easy enough for our show--- instances.------ For now, we just reset the statistics at the beginning of a conversion, and--- leave it to a backend to choose an appropriate moment to dump the summary.----withSimplStats :: String -> String-#ifdef ACCELERATE_DEBUG-withSimplStats x = unsafePerformIO $ do- Debug.when dump_simpl_stats $ x `deepseq` dumpSimplStats- return x-#else-withSimplStats x = x-#endif---- Execute a phase of the compiler and (possibly) print some timing/gc--- statistics.----phase :: NFData b => String -> (a -> b) -> a -> b-#ifdef ACCELERATE_DEBUG-phase n f x = unsafePerformIO $ do- enabled <- queryFlag dump_phases- if enabled- then timed dump_phases (\wall cpu -> printf "phase %s: %s" n (elapsed wall cpu)) (return $!! f x)- else return (f x)-#else-phase _ f x = f x-#endif-
− Data/Array/Accelerate/Trafo/Algebra.hs
@@ -1,740 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE PatternGuards #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE ViewPatterns #-}--- |--- Module : Data.Array.Accelerate.Trafo.Algebra--- Copyright : [2012..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)------ Algebraic simplifications of scalar expressions, including constant folding--- and using algebraic properties of particular operator-operand combinations.-----module Data.Array.Accelerate.Trafo.Algebra (-- evalPrimApp--) where--import Prelude hiding ( exp )-import Data.Bits-import Data.Char-import Data.Monoid-import GHC.Float ( float2Double, double2Float )-import Text.PrettyPrint.ANSI.Leijen-import Unsafe.Coerce-import qualified Prelude as P---- friends-import Data.Array.Accelerate.AST-import Data.Array.Accelerate.Type-import Data.Array.Accelerate.Product-import Data.Array.Accelerate.Pretty.Print ( prettyPrim )-import Data.Array.Accelerate.Array.Sugar ( (:.)(..), Elt(..), Tuple(..), fromTuple )-import Data.Array.Accelerate.Analysis.Match-import Data.Array.Accelerate.Trafo.Base--import qualified Data.Array.Accelerate.Debug as Stats----- Propagate constant expressions, which are either constant valued expressions--- or constant let bindings. Be careful not to follow self-cycles.----propagate- :: forall acc env aenv exp. Kit acc- => Gamma acc env env aenv- -> PreOpenExp acc env aenv exp- -> Maybe exp-propagate env = cvtE- where- cvtE :: PreOpenExp acc env aenv e -> Maybe e- cvtE exp = case exp of- Const c -> Just (toElt c)- PrimConst c -> Just (evalPrimConst c)- Prj ix (Var v) | Tuple t <- prjExp v env -> cvtT ix t- Prj ix e | Just c <- cvtE e -> cvtP ix (fromTuple c)- Var ix- | e <- prjExp ix env- , Nothing <- match exp e -> cvtE e- --- IndexHead (cvtE -> Just (_ :. z)) -> Just z- IndexTail (cvtE -> Just (sh :. _)) -> Just sh- _ -> Nothing-- cvtP :: TupleIdx t e -> t -> Maybe e- cvtP ZeroTupIdx (_, v) = Just v- cvtP (SuccTupIdx idx) (tup, _) = cvtP idx tup-- cvtT :: TupleIdx t e -> Tuple (PreOpenExp acc env aenv) t -> Maybe e- cvtT ZeroTupIdx (SnocTup _ e) = cvtE e- cvtT (SuccTupIdx idx) (SnocTup tup _) = cvtT idx tup-#if __GLASGOW_HASKELL__ < 800- cvtT _ _ = error "hey what's the head angle on that thing?"-#endif----- Attempt to evaluate primitive function applications----evalPrimApp- :: forall acc env aenv a r. (Kit acc, Elt a, Elt r)- => Gamma acc env env aenv- -> PrimFun (a -> r)- -> PreOpenExp acc env aenv a- -> (Any, PreOpenExp acc env aenv r)-evalPrimApp env f x- -- First attempt to move constant values towards the left- | Just r <- commutes f x env = evalPrimApp env f r--- | Just r <- associates f x = r-- -- Now attempt to evaluate any expressions- | otherwise- = maybe (Any False, PrimApp f x) (Any True,)- $ case f of- PrimAdd ty -> evalAdd ty x env- PrimSub ty -> evalSub ty x env- PrimMul ty -> evalMul ty x env- PrimNeg ty -> evalNeg ty x env- PrimAbs ty -> evalAbs ty x env- PrimSig ty -> evalSig ty x env- PrimQuot ty -> evalQuot ty x env- PrimRem ty -> evalRem ty x env- PrimQuotRem ty -> evalQuotRem ty x env- PrimIDiv ty -> evalIDiv ty x env- PrimMod ty -> evalMod ty x env- PrimDivMod ty -> evalDivMod ty x env- PrimBAnd ty -> evalBAnd ty x env- PrimBOr ty -> evalBOr ty x env- PrimBXor ty -> evalBXor ty x env- PrimBNot ty -> evalBNot ty x env- PrimBShiftL ty -> evalBShiftL ty x env- PrimBShiftR ty -> evalBShiftR ty x env- PrimBRotateL ty -> evalBRotateL ty x env- PrimBRotateR ty -> evalBRotateR ty x env- PrimPopCount ty -> evalPopCount ty x env- PrimCountLeadingZeros ty -> evalCountLeadingZeros ty x env- PrimCountTrailingZeros ty -> evalCountTrailingZeros ty x env- PrimFDiv ty -> evalFDiv ty x env- PrimRecip ty -> evalRecip ty x env- PrimSin ty -> evalSin ty x env- PrimCos ty -> evalCos ty x env- PrimTan ty -> evalTan ty x env- PrimAsin ty -> evalAsin ty x env- PrimAcos ty -> evalAcos ty x env- PrimAtan ty -> evalAtan ty x env- PrimSinh ty -> evalSinh ty x env- PrimCosh ty -> evalCosh ty x env- PrimTanh ty -> evalTanh ty x env- PrimAsinh ty -> evalAsinh ty x env- PrimAcosh ty -> evalAcosh ty x env- PrimAtanh ty -> evalAtanh ty x env- PrimExpFloating ty -> evalExpFloating ty x env- PrimSqrt ty -> evalSqrt ty x env- PrimLog ty -> evalLog ty x env- PrimFPow ty -> evalFPow ty x env- PrimLogBase ty -> evalLogBase ty x env- PrimAtan2 ty -> evalAtan2 ty x env- PrimTruncate ta tb -> evalTruncate ta tb x env- PrimRound ta tb -> evalRound ta tb x env- PrimFloor ta tb -> evalFloor ta tb x env- PrimCeiling ta tb -> evalCeiling ta tb x env- PrimIsNaN ty -> evalIsNaN ty x env- PrimIsInfinite ty -> evalIsInfinite ty x env- PrimLt ty -> evalLt ty x env- PrimGt ty -> evalGt ty x env- PrimLtEq ty -> evalLtEq ty x env- PrimGtEq ty -> evalGtEq ty x env- PrimEq ty -> evalEq ty x env- PrimNEq ty -> evalNEq ty x env- PrimMax ty -> evalMax ty x env- PrimMin ty -> evalMin ty x env- PrimLAnd -> evalLAnd x env- PrimLOr -> evalLOr x env- PrimLNot -> evalLNot x env- PrimOrd -> evalOrd x env- PrimChr -> evalChr x env- PrimBoolToInt -> evalBoolToInt x env- PrimFromIntegral ta tb -> evalFromIntegral ta tb x env- PrimToFloating ta tb -> evalToFloating ta tb x env- PrimCoerce ta tb -> evalCoerce ta tb x env----- Discriminate binary functions that commute, and if so return the operands in--- a stable ordering. If only one of the arguments is a constant, this is placed--- to the left of the operator. Returning Nothing indicates no change is made.----commutes- :: forall acc env aenv a r. Kit acc- => PrimFun (a -> r)- -> PreOpenExp acc env aenv a- -> Gamma acc env env aenv- -> Maybe (PreOpenExp acc env aenv a)-commutes f x env = case f of- PrimAdd _ -> swizzle x- PrimMul _ -> swizzle x- PrimBAnd _ -> swizzle x- PrimBOr _ -> swizzle x- PrimBXor _ -> swizzle x- PrimEq _ -> swizzle x- PrimNEq _ -> swizzle x- PrimMax _ -> swizzle x- PrimMin _ -> swizzle x- _ -> Nothing- where- swizzle :: PreOpenExp acc env aenv (b,b) -> Maybe (PreOpenExp acc env aenv (b,b))- swizzle (Tuple (NilTup `SnocTup` a `SnocTup` b))- | Nothing <- propagate env a- , Just _ <- propagate env b- = Stats.ruleFired (pprFun "commutes" f)- $ Just $ Tuple (NilTup `SnocTup` b `SnocTup` a)---- TLM: changing the ordering here when neither term can be reduced can be--- disadvantageous: for example in (x &&* y), the user might have put a--- simpler condition first that is designed to fail fast.------ | Nothing <- propagate env a--- , Nothing <- propagate env b--- , hashOpenExp a > hashOpenExp b--- = Just $ Tuple (NilTup `SnocTup` b `SnocTup` a)-- swizzle _- = Nothing---{----- Determine if successive applications of a binary operator will associate, and--- if so move them to the left. That is:------ a + (b + c) --> (a + b) + c------ Returning Nothing indicates no change is made.------ TLM: we might get into trouble here, as we've lost track of where the user--- has explicitly put parenthesis.------ TLM: BROKEN!! does not correctly change the sign of expressions when flipping--- (-x+y) or (-y+x).----associates- :: (Elt a, Elt r)- => PrimFun (a -> r)- -> PreOpenExp acc env aenv a- -> Maybe (PreOpenExp acc env aenv r)-associates fun exp = case fun of- PrimAdd _ -> swizzle fun exp [PrimAdd ty, PrimSub ty]- PrimSub _ -> swizzle fun exp [PrimAdd ty, PrimSub ty]- PrimLAnd -> swizzle fun exp [fun]- PrimLOr -> swizzle fun exp [fun]- _ -> swizzle fun exp [fun]- where- -- TODO: check the list of ops is complete (and correct)- ty = undefined- ops = [ PrimMul ty, PrimFDiv ty, PrimAdd ty, PrimSub ty, PrimBAnd ty, PrimBOr ty, PrimBXor ty ]-- swizzle :: (Elt a, Elt r) => PrimFun (a -> r) -> PreOpenExp acc env aenv a -> [PrimFun (a -> r)] -> Maybe (PreOpenExp acc env aenv r)- swizzle f x lvl- | Just Refl <- matches f ops- , Just (a,bc) <- untup2 x- , PrimApp g y <- bc- , Just Refl <- matches g lvl- , Just (b,c) <- untup2 y- = Stats.ruleFired (pprFun "associates" f)- $ Just $ PrimApp g (tup2 (PrimApp f (tup2 (a,b)), c))-- swizzle _ _ _- = Nothing-- matches :: (Elt s, Elt t) => PrimFun (s -> a) -> [PrimFun (t -> a)] -> Maybe (s :=: t)- matches _ [] = Nothing- matches f (x:xs)- | Just Refl <- matchPrimFun' f x- = Just Refl-- | otherwise- = matches f xs---}----- Helper functions--- ------------------type a :-> b = forall acc env aenv. Kit acc => PreOpenExp acc env aenv a -> Gamma acc env env aenv -> Maybe (PreOpenExp acc env aenv b)--eval1 :: Elt b => (a -> b) -> a :-> b-eval1 f x env- | Just a <- propagate env x = Stats.substitution "constant fold" . Just $ Const (fromElt (f a))- | otherwise = Nothing--eval2 :: Elt c => (a -> b -> c) -> (a,b) :-> c-eval2 f (untup2 -> Just (x,y)) env- | Just a <- propagate env x- , Just b <- propagate env y- = Stats.substitution "constant fold"- $ Just $ Const (fromElt (f a b))--eval2 _ _ _- = Nothing--tup2 :: (Elt a, Elt b) => (PreOpenExp acc env aenv a, PreOpenExp acc env aenv b) -> PreOpenExp acc env aenv (a, b)-tup2 (a,b) = Tuple (NilTup `SnocTup` a `SnocTup` b)--untup2 :: PreOpenExp acc env aenv (a, b) -> Maybe (PreOpenExp acc env aenv a, PreOpenExp acc env aenv b)-untup2 exp- | Tuple (NilTup `SnocTup` a `SnocTup` b) <- exp = Just (a, b)- | otherwise = Nothing---pprFun :: String -> PrimFun f -> String-pprFun rule f = show $ text rule <+> snd (prettyPrim f)----- Methods of Num--- ----------------evalAdd :: Elt a => NumType a -> (a,a) :-> a-evalAdd (IntegralNumType ty) | IntegralDict <- integralDict ty = evalAdd'-evalAdd (FloatingNumType ty) | FloatingDict <- floatingDict ty = evalAdd'--evalAdd' :: (Elt a, Eq a, Num a) => (a,a) :-> a-evalAdd' (untup2 -> Just (x,y)) env- | Just a <- propagate env x- , a == 0- = Stats.ruleFired "x+0" $ Just y--evalAdd' arg env- = eval2 (+) arg env---evalSub :: Elt a => NumType a -> (a,a) :-> a-evalSub ty@(IntegralNumType ty') | IntegralDict <- integralDict ty' = evalSub' ty-evalSub ty@(FloatingNumType ty') | FloatingDict <- floatingDict ty' = evalSub' ty--evalSub' :: forall a. (Elt a, Eq a, Num a) => NumType a -> (a,a) :-> a-evalSub' ty (untup2 -> Just (x,y)) env- | Just b <- propagate env y- , b == 0- = Stats.ruleFired "x-0" $ Just x-- | Nothing <- propagate env x- , Just b <- propagate env y- = Stats.ruleFired "-y+x"- $ Just . snd $ evalPrimApp env (PrimAdd ty) (Tuple $ NilTup `SnocTup` Const (fromElt (-b)) `SnocTup` x)-- | Just Refl <- match x y- = Stats.ruleFired "x-x"- $ Just $ Const (fromElt (0::a))--evalSub' _ arg env- = eval2 (-) arg env---evalMul :: Elt a => NumType a -> (a,a) :-> a-evalMul (IntegralNumType ty) | IntegralDict <- integralDict ty = evalMul'-evalMul (FloatingNumType ty) | FloatingDict <- floatingDict ty = evalMul'--evalMul' :: (Elt a, Eq a, Num a) => (a,a) :-> a-evalMul' (untup2 -> Just (x,y)) env- | Just a <- propagate env x- , Nothing <- propagate env y- = case a of- 0 -> Stats.ruleFired "x*0" $ Just x- 1 -> Stats.ruleFired "x*1" $ Just y- _ -> Nothing--evalMul' arg env- = eval2 (*) arg env--evalNeg :: Elt a => NumType a -> a :-> a-evalNeg _ x _ | PrimApp PrimNeg{} x' <- x = Stats.ruleFired "negate/negate" $ Just x'-evalNeg (IntegralNumType ty) x env | IntegralDict <- integralDict ty = eval1 negate x env-evalNeg (FloatingNumType ty) x env | FloatingDict <- floatingDict ty = eval1 negate x env--evalAbs :: Elt a => NumType a -> a :-> a-evalAbs (IntegralNumType ty) | IntegralDict <- integralDict ty = eval1 abs-evalAbs (FloatingNumType ty) | FloatingDict <- floatingDict ty = eval1 abs--evalSig :: Elt a => NumType a -> a :-> a-evalSig (IntegralNumType ty) | IntegralDict <- integralDict ty = eval1 signum-evalSig (FloatingNumType ty) | FloatingDict <- floatingDict ty = eval1 signum----- Methods of Integral & Bits--- ----------------------------evalQuot :: IntegralType a -> (a,a) :-> a-evalQuot ty exp env- | Just qr <- evalQuotRem ty exp env- , Just (q,_) <- untup2 qr- = Just q-evalQuot _ _ _- = Nothing--evalRem :: IntegralType a -> (a,a) :-> a-evalRem ty exp env- | Just qr <- evalQuotRem ty exp env- , Just (_,r) <- untup2 qr- = Just r-evalRem _ _ _- = Nothing--evalQuotRem :: forall a. IntegralType a -> (a,a) :-> (a,a)-evalQuotRem ty exp env- | IntegralDict <- integralDict ty- , Tuple (NilTup `SnocTup` x `SnocTup` y) <- exp -- TLM: untup2, but inlined to expose the Elt dictionary- , Just b <- propagate env y- = case b of- 0 -> Nothing- 1 -> Stats.ruleFired "quotRem x 1" $ Just (tup2 (x, Const (fromElt (0::a))))- _ -> case propagate env x of- Nothing -> Nothing- Just a -> Stats.substitution "constant fold"- $ Just $ let (u,v) = quotRem a b- in tup2 (Const (fromElt u), Const (fromElt v))-evalQuotRem _ _ _- = Nothing---evalIDiv :: IntegralType a -> (a,a) :-> a-evalIDiv ty exp env- | Just dm <- evalDivMod ty exp env- , Just (d,_) <- untup2 dm- = Just d-evalIDiv _ _ _- = Nothing--evalMod :: IntegralType a -> (a,a) :-> a-evalMod ty exp env- | Just dm <- evalDivMod ty exp env- , Just (_,m) <- untup2 dm- = Just m-evalMod _ _ _- = Nothing--evalDivMod :: forall a. IntegralType a -> (a,a) :-> (a,a)-evalDivMod ty exp env- | IntegralDict <- integralDict ty- , Tuple (NilTup `SnocTup` x `SnocTup` y) <- exp -- TLM: untup2, but inlined to expose the Elt dictionary- , Just b <- propagate env y- = case b of- 0 -> Nothing- 1 -> Stats.ruleFired "divMod x 1" $ Just (tup2 (x, Const (fromElt (0::a))))- _ -> case propagate env x of- Nothing -> Nothing- Just a -> Stats.substitution "constant fold"- $ Just $ let (u,v) = divMod a b- in tup2 (Const (fromElt u), Const (fromElt v))-evalDivMod _ _ _- = Nothing--evalBAnd :: Elt a => IntegralType a -> (a,a) :-> a-evalBAnd ty | IntegralDict <- integralDict ty = eval2 (.&.)--evalBOr :: Elt a => IntegralType a -> (a,a) :-> a-evalBOr ty | IntegralDict <- integralDict ty = eval2 (.|.)--evalBXor :: Elt a => IntegralType a -> (a,a) :-> a-evalBXor ty | IntegralDict <- integralDict ty = eval2 xor--evalBNot :: Elt a => IntegralType a -> a :-> a-evalBNot ty | IntegralDict <- integralDict ty = eval1 complement--evalBShiftL :: Elt a => IntegralType a -> (a,Int) :-> a-evalBShiftL _ (untup2 -> Just (x,i)) env- | Just 0 <- propagate env i- = Stats.ruleFired "x `shiftL` 0" $ Just x--evalBShiftL ty arg env- | IntegralDict <- integralDict ty = eval2 shiftL arg env--evalBShiftR :: Elt a => IntegralType a -> (a,Int) :-> a-evalBShiftR _ (untup2 -> Just (x,i)) env- | Just 0 <- propagate env i- = Stats.ruleFired "x `shiftR` 0" $ Just x--evalBShiftR ty arg env- | IntegralDict <- integralDict ty = eval2 shiftR arg env--evalBRotateL :: Elt a => IntegralType a -> (a,Int) :-> a-evalBRotateL _ (untup2 -> Just (x,i)) env- | Just 0 <- propagate env i- = Stats.ruleFired "x `rotateL` 0" $ Just x-evalBRotateL ty arg env- | IntegralDict <- integralDict ty = eval2 rotateL arg env--evalBRotateR :: Elt a => IntegralType a -> (a,Int) :-> a-evalBRotateR _ (untup2 -> Just (x,i)) env- | Just 0 <- propagate env i- = Stats.ruleFired "x `rotateR` 0" $ Just x-evalBRotateR ty arg env- | IntegralDict <- integralDict ty = eval2 rotateR arg env--evalPopCount :: IntegralType a -> a :-> Int-evalPopCount ty | IntegralDict <- integralDict ty = eval1 popCount--evalCountLeadingZeros :: IntegralType a -> a :-> Int-#if __GLASGOW_HASKELL__ >= 710-evalCountLeadingZeros ty | IntegralDict <- integralDict ty = eval1 countLeadingZeros-#else-evalCountLeadingZeros ty | IntegralDict <- integralDict ty = eval1 clz- where- clz x = (w-1) - go (w-1)- where- go i | i < 0 = i -- no bit set- | testBit x i = i- | otherwise = go (i-1)- w = finiteBitSize x-#endif--evalCountTrailingZeros :: IntegralType a -> a :-> Int-#if __GLASGOW_HASKELL__ >= 710-evalCountTrailingZeros ty | IntegralDict <- integralDict ty = eval1 countTrailingZeros-#else-evalCountTrailingZeros ty | IntegralDict <- integralDict ty = eval1 ctz- where- ctz x = go 0- where- go i | i >= w = i- | testBit x i = i- | otherwise = go (i+1)- w = finiteBitSize x-#endif----- Methods of Fractional & Floating--- ----------------------------------evalFDiv :: Elt a => FloatingType a -> (a,a) :-> a-evalFDiv ty | FloatingDict <- floatingDict ty = evalFDiv'--evalFDiv' :: (Elt a, Fractional a, Eq a) => (a,a) :-> a-evalFDiv' (untup2 -> Just (x,y)) env- | Just 1 <- propagate env y- = Stats.ruleFired "x/1" $ Just x--evalFDiv' arg env- = eval2 (/) arg env---evalRecip :: Elt a => FloatingType a -> a :-> a-evalRecip ty | FloatingDict <- floatingDict ty = eval1 recip--evalSin :: Elt a => FloatingType a -> a :-> a-evalSin ty | FloatingDict <- floatingDict ty = eval1 sin--evalCos :: Elt a => FloatingType a -> a :-> a-evalCos ty | FloatingDict <- floatingDict ty = eval1 cos--evalTan :: Elt a => FloatingType a -> a :-> a-evalTan ty | FloatingDict <- floatingDict ty = eval1 tan--evalAsin :: Elt a => FloatingType a -> a :-> a-evalAsin ty | FloatingDict <- floatingDict ty = eval1 asin--evalAcos :: Elt a => FloatingType a -> a :-> a-evalAcos ty | FloatingDict <- floatingDict ty = eval1 acos--evalAtan :: Elt a => FloatingType a -> a :-> a-evalAtan ty | FloatingDict <- floatingDict ty = eval1 atan--evalSinh :: Elt a => FloatingType a -> a :-> a-evalSinh ty | FloatingDict <- floatingDict ty = eval1 sinh--evalCosh :: Elt a => FloatingType a -> a :-> a-evalCosh ty | FloatingDict <- floatingDict ty = eval1 cosh--evalTanh :: Elt a => FloatingType a -> a :-> a-evalTanh ty | FloatingDict <- floatingDict ty = eval1 tanh--evalAsinh :: Elt a => FloatingType a -> a :-> a-evalAsinh ty | FloatingDict <- floatingDict ty = eval1 asinh--evalAcosh :: Elt a => FloatingType a -> a :-> a-evalAcosh ty | FloatingDict <- floatingDict ty = eval1 acosh--evalAtanh :: Elt a => FloatingType a -> a :-> a-evalAtanh ty | FloatingDict <- floatingDict ty = eval1 atanh--evalExpFloating :: Elt a => FloatingType a -> a :-> a-evalExpFloating ty | FloatingDict <- floatingDict ty = eval1 P.exp--evalSqrt :: Elt a => FloatingType a -> a :-> a-evalSqrt ty | FloatingDict <- floatingDict ty = eval1 sqrt--evalLog :: Elt a => FloatingType a -> a :-> a-evalLog ty | FloatingDict <- floatingDict ty = eval1 log--evalFPow :: Elt a => FloatingType a -> (a,a) :-> a-evalFPow ty | FloatingDict <- floatingDict ty = eval2 (**)--evalLogBase :: Elt a => FloatingType a -> (a,a) :-> a-evalLogBase ty | FloatingDict <- floatingDict ty = eval2 logBase--evalAtan2 :: Elt a => FloatingType a -> (a,a) :-> a-evalAtan2 ty | FloatingDict <- floatingDict ty = eval2 atan2--evalTruncate :: Elt b => FloatingType a -> IntegralType b -> a :-> b-evalTruncate ta tb- | FloatingDict <- floatingDict ta- , IntegralDict <- integralDict tb = eval1 truncate--evalRound :: Elt b => FloatingType a -> IntegralType b -> a :-> b-evalRound ta tb- | FloatingDict <- floatingDict ta- , IntegralDict <- integralDict tb = eval1 round--evalFloor :: Elt b => FloatingType a -> IntegralType b -> a :-> b-evalFloor ta tb- | FloatingDict <- floatingDict ta- , IntegralDict <- integralDict tb = eval1 floor--evalCeiling :: Elt b => FloatingType a -> IntegralType b -> a :-> b-evalCeiling ta tb- | FloatingDict <- floatingDict ta- , IntegralDict <- integralDict tb = eval1 ceiling--evalIsNaN :: FloatingType a -> a :-> Bool-evalIsNaN ty | FloatingDict <- floatingDict ty = eval1 isNaN--evalIsInfinite :: FloatingType a -> a :-> Bool-evalIsInfinite ty | FloatingDict <- floatingDict ty = eval1 isInfinite----- Relational & Equality--- -----------------------evalLt :: ScalarType a -> (a,a) :-> Bool-evalLt (NumScalarType (IntegralNumType ty)) | IntegralDict <- integralDict ty = eval2 (<)-evalLt (NumScalarType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = eval2 (<)-evalLt (NonNumScalarType ty) | NonNumDict <- nonNumDict ty = eval2 (<)--evalGt :: ScalarType a -> (a,a) :-> Bool-evalGt (NumScalarType (IntegralNumType ty)) | IntegralDict <- integralDict ty = eval2 (>)-evalGt (NumScalarType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = eval2 (>)-evalGt (NonNumScalarType ty) | NonNumDict <- nonNumDict ty = eval2 (>)--evalLtEq :: ScalarType a -> (a,a) :-> Bool-evalLtEq (NumScalarType (IntegralNumType ty)) | IntegralDict <- integralDict ty = eval2 (<=)-evalLtEq (NumScalarType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = eval2 (<=)-evalLtEq (NonNumScalarType ty) | NonNumDict <- nonNumDict ty = eval2 (<=)--evalGtEq :: ScalarType a -> (a,a) :-> Bool-evalGtEq (NumScalarType (IntegralNumType ty)) | IntegralDict <- integralDict ty = eval2 (>=)-evalGtEq (NumScalarType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = eval2 (>=)-evalGtEq (NonNumScalarType ty) | NonNumDict <- nonNumDict ty = eval2 (>=)--evalEq :: ScalarType a -> (a,a) :-> Bool-evalEq (NumScalarType (IntegralNumType ty)) | IntegralDict <- integralDict ty = eval2 (==)-evalEq (NumScalarType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = eval2 (==)-evalEq (NonNumScalarType ty) | NonNumDict <- nonNumDict ty = eval2 (==)--evalNEq :: ScalarType a -> (a,a) :-> Bool-evalNEq (NumScalarType (IntegralNumType ty)) | IntegralDict <- integralDict ty = eval2 (/=)-evalNEq (NumScalarType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = eval2 (/=)-evalNEq (NonNumScalarType ty) | NonNumDict <- nonNumDict ty = eval2 (/=)--evalMax :: Elt a => ScalarType a -> (a,a) :-> a-evalMax (NumScalarType (IntegralNumType ty)) | IntegralDict <- integralDict ty = eval2 max-evalMax (NumScalarType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = eval2 max-evalMax (NonNumScalarType ty) | NonNumDict <- nonNumDict ty = eval2 max--evalMin :: Elt a => ScalarType a -> (a,a) :-> a-evalMin (NumScalarType (IntegralNumType ty)) | IntegralDict <- integralDict ty = eval2 min-evalMin (NumScalarType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = eval2 min-evalMin (NonNumScalarType ty) | NonNumDict <- nonNumDict ty = eval2 min----- Logical operators--- -------------------evalLAnd :: (Bool,Bool) :-> Bool-evalLAnd (untup2 -> Just (x,y)) env- | Just a <- propagate env x- = Just $ if a then Stats.ruleFired "True &&" y- else Stats.ruleFired "False &&" $ Const (fromElt False)--evalLAnd _ _- = Nothing--evalLOr :: (Bool,Bool) :-> Bool-evalLOr (untup2 -> Just (x,y)) env- | Just a <- propagate env x- = Just $ if a then Stats.ruleFired "True ||" $ Const (fromElt True)- else Stats.ruleFired "False ||" y--evalLOr _ _- = Nothing--evalLNot :: Bool :-> Bool-evalLNot x _ | PrimApp PrimLNot x' <- x = Stats.ruleFired "not/not" $ Just x'-evalLNot x env = eval1 not x env--evalOrd :: Char :-> Int-evalOrd = eval1 ord--evalChr :: Int :-> Char-evalChr = eval1 chr--evalBoolToInt :: Bool :-> Int-evalBoolToInt = eval1 fromEnum--evalFromIntegral :: Elt b => IntegralType a -> NumType b -> a :-> b-evalFromIntegral ta (IntegralNumType tb)- | IntegralDict <- integralDict ta- , IntegralDict <- integralDict tb = eval1 fromIntegral--evalFromIntegral ta (FloatingNumType tb)- | IntegralDict <- integralDict ta- , FloatingDict <- floatingDict tb = eval1 fromIntegral--evalToFloating :: Elt b => NumType a -> FloatingType b -> a :-> b-evalToFloating (IntegralNumType ta) tb x env- | IntegralDict <- integralDict ta- , FloatingDict <- floatingDict tb = eval1 realToFrac x env--evalToFloating (FloatingNumType ta) tb x env- | TypeFloat FloatingDict <- ta- , TypeFloat FloatingDict <- tb = Just x-- | TypeDouble FloatingDict <- ta- , TypeDouble FloatingDict <- tb = Just x-- | TypeFloat FloatingDict <- ta- , TypeDouble FloatingDict <- tb = eval1 float2Double x env-- | TypeDouble FloatingDict <- ta- , TypeFloat FloatingDict <- tb = eval1 double2Float x env-- | FloatingDict <- floatingDict ta- , FloatingDict <- floatingDict tb = eval1 realToFrac x env--evalCoerce :: Elt b => ScalarType a -> ScalarType b -> a :-> b-evalCoerce _ _ = eval1 unsafeCoerce----- Scalar primitives--- -------------------evalPrimConst :: PrimConst a -> a-evalPrimConst (PrimMinBound ty) = evalMinBound ty-evalPrimConst (PrimMaxBound ty) = evalMaxBound ty-evalPrimConst (PrimPi ty) = evalPi ty--evalMinBound :: BoundedType a -> a-evalMinBound (IntegralBoundedType ty) | IntegralDict <- integralDict ty = minBound-evalMinBound (NonNumBoundedType ty) | NonNumDict <- nonNumDict ty = minBound--evalMaxBound :: BoundedType a -> a-evalMaxBound (IntegralBoundedType ty) | IntegralDict <- integralDict ty = maxBound-evalMaxBound (NonNumBoundedType ty) | NonNumDict <- nonNumDict ty = maxBound--evalPi :: FloatingType a -> a-evalPi ty | FloatingDict <- floatingDict ty = pi-
− Data/Array/Accelerate/Trafo/Base.hs
@@ -1,405 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE PatternGuards #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}-#if __GLASGOW_HASKELL__ <= 708-{-# LANGUAGE IncoherentInstances #-}-{-# LANGUAGE OverlappingInstances #-}-{-# LANGUAGE UndecidableInstances #-}-{-# OPTIONS_GHC -fno-warn-unrecognised-pragmas #-}-#endif--- |--- Module : Data.Array.Accelerate.Trafo.Base--- Copyright : [2012..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Trafo.Base (-- -- Toolkit- Kit(..), Match(..), (:~:)(..),- avarIn, kmap, fromOpenAfun,-- -- Delayed Arrays- DelayedAcc, DelayedOpenAcc(..),- DelayedAfun, DelayedOpenAfun,- DelayedExp, DelayedFun, DelayedOpenExp, DelayedOpenFun,- -- DelayedSeq(..), DelayedOpenSeq,- matchDelayedOpenAcc, hashDelayedOpenAcc,-- -- Environments- Gamma(..), incExp, prjExp, lookupExp,- Extend(..), append, bind, Sink(..), sink, sink1,- weakenGamma1, sinkGamma,- Supplement(..), bindExps,-- subApply, inlineA,--) where---- standard library-import Control.Applicative-import Control.DeepSeq-import Data.Hashable-import Data.Type.Equality-import Text.PrettyPrint.ANSI.Leijen hiding ( (<$>) )-import Prelude hiding ( until )---- friends-import Data.Array.Accelerate.AST hiding ( Val(..) )-import Data.Array.Accelerate.Analysis.Hash-import Data.Array.Accelerate.Analysis.Match-import Data.Array.Accelerate.Array.Sugar ( Array, Arrays, Shape, Elt )-import Data.Array.Accelerate.Error-import Data.Array.Accelerate.Pretty.Print-import Data.Array.Accelerate.Trafo.Substitution--import Data.Array.Accelerate.Debug.Stats as Stats----- Toolkit--- =======---- The bat utility belt of operations required to manipulate terms parameterised--- by the recursive closure.----class (RebuildableAcc acc, Sink acc) => Kit acc where- inject :: PreOpenAcc acc aenv a -> acc aenv a- extract :: acc aenv a -> PreOpenAcc acc aenv a- fromOpenAcc :: OpenAcc aenv a -> acc aenv a- --- matchAcc :: MatchAcc acc- hashAcc :: HashAcc acc- prettyAcc :: PrettyAcc acc--instance Kit OpenAcc where- inject = OpenAcc- extract (OpenAcc pacc) = pacc- fromOpenAcc = id- --- {-# INLINEABLE hashAcc #-}- {-# INLINEABLE matchAcc #-}- {-# INLINEABLE prettyAcc #-}- hashAcc = hashOpenAcc- matchAcc = matchOpenAcc- prettyAcc = prettyOpenAcc--avarIn :: (Kit acc, Arrays arrs) => Idx aenv arrs -> acc aenv arrs-avarIn = inject . Avar--kmap :: Kit acc => (PreOpenAcc acc aenv a -> PreOpenAcc acc aenv b) -> acc aenv a -> acc aenv b-kmap f = inject . f . extract--fromOpenAfun :: Kit acc => OpenAfun aenv f -> PreOpenAfun acc aenv f-fromOpenAfun (Abody a) = Abody $ fromOpenAcc a-fromOpenAfun (Alam f) = Alam $ fromOpenAfun f---- A class for testing the equality of terms homogeneously, returning a witness--- to the existentially quantified terms in the positive case.----class Match f where- match :: f s -> f t -> Maybe (s :~: t)--instance Match (Idx env) where- {-# INLINEABLE match #-}- match = matchIdx--instance Kit acc => Match (PreOpenExp acc env aenv) where- {-# INLINEABLE match #-}- match = matchPreOpenExp matchAcc hashAcc--instance Kit acc => Match (PreOpenFun acc env aenv) where- {-# INLINEABLE match #-}- match = matchPreOpenFun matchAcc hashAcc--instance Kit acc => Match (PreOpenAcc acc aenv) where- {-# INLINEABLE match #-}- match = matchPreOpenAcc matchAcc hashAcc--instance {-# INCOHERENT #-} Kit acc => Match (acc aenv) where- {-# INLINEABLE match #-}- match = matchAcc----- Delayed Arrays--- ==============---- The type of delayed arrays. This representation is used to annotate the AST--- in the recursive knot to distinguish standard AST terms from operand arrays--- that should be embedded into their consumers.----type DelayedAcc = DelayedOpenAcc ()-type DelayedAfun = PreOpenAfun DelayedOpenAcc ()--type DelayedExp = DelayedOpenExp ()-type DelayedFun = DelayedOpenFun ()---- data DelayedSeq t where--- DelayedSeq :: Extend DelayedOpenAcc () aenv--- -> DelayedOpenSeq aenv () t--- -> DelayedSeq t--type DelayedOpenAfun = PreOpenAfun DelayedOpenAcc-type DelayedOpenExp = PreOpenExp DelayedOpenAcc-type DelayedOpenFun = PreOpenFun DelayedOpenAcc--- type DelayedOpenSeq = PreOpenSeq DelayedOpenAcc--data DelayedOpenAcc aenv a where- Manifest :: PreOpenAcc DelayedOpenAcc aenv a -> DelayedOpenAcc aenv a-- Delayed :: (Shape sh, Elt e) =>- { extentD :: PreExp DelayedOpenAcc aenv sh- , indexD :: PreFun DelayedOpenAcc aenv (sh -> e)- , linearIndexD :: PreFun DelayedOpenAcc aenv (Int -> e)- } -> DelayedOpenAcc aenv (Array sh e)--instance Rebuildable DelayedOpenAcc where- type AccClo DelayedOpenAcc = DelayedOpenAcc- {-# INLINEABLE rebuildPartial #-}- rebuildPartial v acc = case acc of- Manifest pacc -> Manifest <$> rebuildPartial v pacc- Delayed{..} -> Delayed <$> rebuildPartial v extentD- <*> rebuildPartial v indexD- <*> rebuildPartial v linearIndexD--instance Sink DelayedOpenAcc where- weaken k = Stats.substitution "weaken" . rebuildA (Avar . k)--instance Kit DelayedOpenAcc where- inject = Manifest- extract (Manifest pacc) = pacc- extract Delayed{} = error "DelayedAcc.extract"- fromOpenAcc = error "DelayedAcc.fromOpenAcc"- --- {-# INLINEABLE hashAcc #-}- {-# INLINEABLE matchAcc #-}- {-# INLINEABLE prettyAcc #-}- hashAcc = hashDelayedOpenAcc- matchAcc = matchDelayedOpenAcc- prettyAcc = prettyDelayedOpenAcc--instance NFData (DelayedOpenAfun aenv t) where- rnf = rnfPreOpenAfun rnfDelayedOpenAcc--instance NFData (DelayedOpenAcc aenv t) where- rnf = rnfDelayedOpenAcc---- instance NFData (DelayedSeq t) where--- rnf = rnfDelayedSeq--hashDelayedOpenAcc :: HashAcc DelayedOpenAcc-hashDelayedOpenAcc (Manifest pacc) = $(hashQ "Manifest") `hashWithSalt` hashPreOpenAcc hashAcc pacc-hashDelayedOpenAcc Delayed{..} = $(hashQ "Delayed") `hashE` extentD `hashF` indexD `hashF` linearIndexD- where- hashE salt = hashWithSalt salt . hashPreOpenExp hashAcc- hashF salt = hashWithSalt salt . hashPreOpenFun hashAcc--matchDelayedOpenAcc :: MatchAcc DelayedOpenAcc-matchDelayedOpenAcc (Manifest pacc1) (Manifest pacc2)- = matchPreOpenAcc matchAcc hashAcc pacc1 pacc2--matchDelayedOpenAcc (Delayed sh1 ix1 lx1) (Delayed sh2 ix2 lx2)- | Just Refl <- matchPreOpenExp matchAcc hashAcc sh1 sh2- , Just Refl <- matchPreOpenFun matchAcc hashAcc ix1 ix2- , Just Refl <- matchPreOpenFun matchAcc hashAcc lx1 lx2- = Just Refl--matchDelayedOpenAcc _ _- = Nothing--rnfDelayedOpenAcc :: DelayedOpenAcc aenv t -> ()-rnfDelayedOpenAcc (Manifest pacc) = rnfPreOpenAcc rnfDelayedOpenAcc pacc-rnfDelayedOpenAcc (Delayed sh ix lx) = rnfPreOpenExp rnfDelayedOpenAcc sh- `seq` rnfPreOpenFun rnfDelayedOpenAcc ix- `seq` rnfPreOpenFun rnfDelayedOpenAcc lx--{---rnfDelayedSeq :: DelayedSeq t -> ()-rnfDelayedSeq (DelayedSeq env s) = rnfExtend rnfDelayedOpenAcc env- `seq` rnfPreOpenSeq rnfDelayedOpenAcc s--rnfExtend :: NFDataAcc acc -> Extend acc aenv aenv' -> ()-rnfExtend _ BaseEnv = ()-rnfExtend rnfA (PushEnv env a) = rnfExtend rnfA env `seq` rnfA a---}----- Note: If we detect that the delayed array is simply accessing an array--- variable, then just print the variable name. That is:------ > let a0 = <...> in map f (Delayed (shape a0) (\x0 -> a0!x0))------ becomes------ > let a0 = <...> in map f a0----prettyDelayedOpenAcc :: PrettyAcc DelayedOpenAcc-prettyDelayedOpenAcc wrap aenv acc = case acc of- Manifest pacc -> prettyPreOpenAcc prettyDelayedOpenAcc wrap aenv pacc- Delayed sh f _- | Shape a <- sh- , Just Refl <- match f (Lam (Body (Index a (Var ZeroIdx))))- -> prettyDelayedOpenAcc wrap aenv a-- | otherwise- -> wrap $ hang 2 (sep [ green (text "delayed")- , parens (align (prettyPreExp prettyDelayedOpenAcc (parens . align) aenv sh))- , parens (align (prettyPreFun prettyDelayedOpenAcc aenv f))- ])--{----- Pretty print delayed sequences------ TLM: What is going on with this sequence thing, why is it closed?----prettyDelayedSeq- :: (Doc -> Doc) -- apply to compound expressions- -> DelayedSeq arrs- -> Doc-prettyDelayedSeq wrap (DelayedSeq aenv s)- | (d, lvl) <- pp env 0- = wrap $ (hang (text "let") 2 $ sep $ punctuate semi d)- <+> (hang (text "in") 2 $ sep $ punctuate semi- $ prettyPreSeq wrap prettyAcc lvl 0 s)- where- pp :: Extend DelayedOpenAcc aenv aenv' -> Int -> ([Doc], Int)- pp BaseEnv lvl = ([],lvl)- pp (PushEnv env' a) lvl | (d', _) <- pp env' (lvl + 1)- = (prettyAcc lvl wrap a : d', lvl)---}----- Environments--- ============---- An environment that holds let-bound scalar expressions. The second--- environment variable env' is used to project out the corresponding--- index when looking up in the environment congruent expressions.----data Gamma acc env env' aenv where- EmptyExp :: Gamma acc env env' aenv-- PushExp :: Gamma acc env env' aenv- -> PreOpenExp acc env aenv t- -> Gamma acc env (env', t) aenv--incExp :: RebuildableAcc acc => Gamma acc env env' aenv -> Gamma acc (env, s) env' aenv-incExp EmptyExp = EmptyExp-incExp (PushExp env e) = incExp env `PushExp` weakenE SuccIdx e--prjExp :: Idx env' t -> Gamma acc env env' aenv -> PreOpenExp acc env aenv t-prjExp ZeroIdx (PushExp _ v) = v-prjExp (SuccIdx ix) (PushExp env _) = prjExp ix env-prjExp _ _ = $internalError "prjExp" "inconsistent valuation"--weakenGamma1 :: Kit acc => Gamma acc env env' aenv -> Gamma acc env env' (aenv,t)-weakenGamma1 EmptyExp = EmptyExp-weakenGamma1 (PushExp env e) = PushExp (weakenGamma1 env) (weaken SuccIdx e)--sinkGamma :: Kit acc => Extend acc aenv aenv' -> Gamma acc env env' aenv -> Gamma acc env env' aenv'-sinkGamma _ EmptyExp = EmptyExp-sinkGamma ext (PushExp env e) = PushExp (sinkGamma ext env) (sink ext e)--lookupExp :: Kit acc => Gamma acc env env' aenv -> PreOpenExp acc env aenv t -> Maybe (Idx env' t)-lookupExp EmptyExp _ = Nothing-lookupExp (PushExp env e) x- | Just Refl <- match e x = Just ZeroIdx- | otherwise = SuccIdx `fmap` lookupExp env x----- As part of various transformations we often need to lift out array valued--- inputs to be let-bound at a higher point.------ The Extend type is a heterogeneous snoc-list of array terms that witnesses--- how the array environment is extended by binding these additional terms.----data Extend acc aenv aenv' where- BaseEnv :: Extend acc aenv aenv-- PushEnv :: Arrays a- => Extend acc aenv aenv' -> acc aenv' a -> Extend acc aenv (aenv', a)---- Append two environment witnesses----append :: Extend acc env env' -> Extend acc env' env'' -> Extend acc env env''-append x BaseEnv = x-append x (PushEnv as a) = x `append` as `PushEnv` a---- Bring into scope all of the array terms in the Extend environment list. This--- converts a term in the inner environment (aenv') into the outer (aenv).----bind :: (Kit acc, Arrays a)- => Extend acc aenv aenv'- -> PreOpenAcc acc aenv' a- -> PreOpenAcc acc aenv a-bind BaseEnv = id-bind (PushEnv env a) = bind env . Alet a . inject---- Sink a term from one array environment into another, where additional--- bindings have come into scope according to the witness and no old things have--- vanished.----sink :: Sink f => Extend acc env env' -> f env t -> f env' t-sink env = weaken (k env)- where- k :: Extend acc env env' -> Idx env t -> Idx env' t- k BaseEnv = Stats.substitution "sink" id- k (PushEnv e _) = SuccIdx . k e--sink1 :: Sink f => Extend acc env env' -> f (env,s) t -> f (env',s) t-sink1 env = weaken (k env)- where- k :: Extend acc env env' -> Idx (env,s) t -> Idx (env',s) t- k BaseEnv = Stats.substitution "sink1" id- k (PushEnv e _) = split . k e- --- split :: Idx (env,s) t -> Idx ((env,u),s) t- split ZeroIdx = ZeroIdx- split (SuccIdx ix) = SuccIdx (SuccIdx ix)---- This is the same as above, however for the scalar environment.------ RCE: This is much the same as `Gamma` above. The main difference being that the expressions--- stored in a `Gamma` can not depend on each other, whereas in `Supplement` they can. We should--- perhaps look at using `Supplement` wherever possible.----data Supplement acc env env' aenv where- BaseSup :: Supplement acc env env aenv- PushSup :: Elt e- => Supplement acc env env' aenv- -> PreOpenExp acc env' aenv e- -> Supplement acc env (env', e) aenv--bindExps :: (Kit acc, Elt e)- => Supplement acc env env' aenv- -> PreOpenExp acc env' aenv e- -> PreOpenExp acc env aenv e-bindExps BaseSup = id-bindExps (PushSup g b) = bindExps g . Let b---- Application via let binding.----subApply :: (RebuildableAcc acc, Arrays a)- => PreOpenAfun acc aenv (a -> b)- -> acc aenv a- -> PreOpenAcc acc aenv b-subApply (Alam (Abody f)) a = Alet a f-subApply _ _ = error "subApply: inconsistent evaluation"---- | Replace all occurrences of the first variable with the given array--- expression. The environment shrinks.----inlineA :: Rebuildable f => f (aenv,s) t -> PreOpenAcc (AccClo f) aenv s -> f aenv t-inlineA f g = Stats.substitution "inlineA" $ rebuildA (subAtop g) f-
− Data/Array/Accelerate/Trafo/Fusion.hs
@@ -1,1559 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE IncoherentInstances #-}-{-# LANGUAGE InstanceSigs #-}-{-# LANGUAGE PatternGuards #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE ViewPatterns #-}-{-# OPTIONS_GHC -fno-warn-incomplete-patterns #-}-{-# OPTIONS_GHC -fno-warn-name-shadowing #-}--- |--- Module : Data.Array.Accelerate.Trafo.Fusion--- Copyright : [2012..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- [2014..2014] Frederik M. Madsen--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)------ This module implements producer/producer and consumer/producer fusion as a--- term rewriting of the Accelerate AST.------ The function 'quench' perform the source-to-source fusion transformation,--- while 'anneal' additionally makes the representation of embedded producers--- explicit by representing the AST as a 'DelayedAcc' of manifest and delayed--- nodes.-----module Data.Array.Accelerate.Trafo.Fusion (-- -- ** Types- DelayedAcc, DelayedOpenAcc(..),- DelayedAfun, DelayedOpenAfun,- DelayedExp, DelayedFun, DelayedOpenExp, DelayedOpenFun,-- -- ** Conversion- convertAcc, convertAfun,--) where---- standard library-import Prelude hiding ( exp, until )---- friends-import Data.Array.Accelerate.AST-import Data.Array.Accelerate.Error-import Data.Array.Accelerate.Trafo.Base-import Data.Array.Accelerate.Trafo.Shrink-import Data.Array.Accelerate.Trafo.Simplify-import Data.Array.Accelerate.Trafo.Substitution-import Data.Array.Accelerate.Array.Representation ( SliceIndex(..) )-import Data.Array.Accelerate.Array.Sugar ( Array, Arrays(..), ArraysR(..), ArrRepr- , Elt, EltRepr, Shape, Tuple(..), Atuple(..)- , IsAtuple, TupleRepr )-import Data.Array.Accelerate.Product--import qualified Data.Array.Accelerate.Debug as Stats-#ifdef ACCELERATE_DEBUG-import System.IO.Unsafe -- for debugging-#endif----- Delayed Array Fusion--- ====================---- | Apply the fusion transformation to a closed de Bruijn AST----convertAcc :: Arrays arrs => Bool -> Acc arrs -> DelayedAcc arrs-convertAcc fuseAcc = withSimplStats . convertOpenAcc fuseAcc---- | Apply the fusion transformation to a function of array arguments----convertAfun :: Bool -> Afun f -> DelayedAfun f-convertAfun fuseAcc = withSimplStats . convertOpenAfun fuseAcc---- -- | Apply the fusion transformation to the array computations embedded--- -- in a sequence computation.--- convertSeq :: Bool -> Seq a -> DelayedSeq a--- convertSeq fuseAcc (embedSeq (embedOpenAcc fuseAcc) -> ExtendSeq aenv s)--- = withSimplStats (DelayedSeq (cvtE aenv) (convertOpenSeq fuseAcc s))--- where--- cvtE :: Extend OpenAcc aenv aenv' -> Extend DelayedOpenAcc aenv aenv'--- cvtE BaseEnv = BaseEnv--- cvtE (PushEnv env a) | a' <- convertOpenAcc fuseAcc a = PushEnv (cvtE env) a'--withSimplStats :: a -> a-#ifdef ACCELERATE_DEBUG-withSimplStats x = unsafePerformIO Stats.resetSimplCount `seq` x-#else-withSimplStats x = x-#endif----- | Apply the fusion transformation to an AST. This consists of two phases:------ 1. A bottom-up traversal that converts nodes into the internal delayed--- representation, merging adjacent producer/producer pairs.------ 2. A top-down traversal that makes the representation of fused--- consumer/producer pairs explicit as a 'DelayedAcc' of manifest and--- delayed nodes.------ TLM: Note that there really is no ambiguity as to which state an array will--- be in following this process: an array will be either delayed or--- manifest, and the two helper functions are even named as such! We should--- encode this property in the type somehow...----convertOpenAcc :: Arrays arrs => Bool -> OpenAcc aenv arrs -> DelayedOpenAcc aenv arrs-convertOpenAcc fuseAcc = manifest fuseAcc . computeAcc . embedOpenAcc fuseAcc---- Convert array computations into an embeddable delayed representation.--- Reapply the embedding function from the first pass and unpack the--- representation. It is safe to match on BaseEnv because the first pass--- will put producers adjacent to the term consuming it.----delayed :: (Shape sh, Elt e) => Bool -> OpenAcc aenv (Array sh e) -> DelayedOpenAcc aenv (Array sh e)-delayed fuseAcc (embedOpenAcc fuseAcc -> Embed BaseEnv cc) =- case cc of- Done v -> Delayed (arrayShape v) (indexArray v) (linearIndex v)- Yield (cvtE -> sh) (cvtF -> f) -> Delayed sh f (f `compose` fromIndex sh)- Step (cvtE -> sh) (cvtF -> p) (cvtF -> f) v- | Just Refl <- match sh (arrayShape v)- , Just Refl <- isIdentity p- -> Delayed sh (f `compose` indexArray v) (f `compose` linearIndex v)-- | f' <- f `compose` indexArray v `compose` p- -> Delayed sh f' (f' `compose` fromIndex sh)- where- cvtE :: OpenExp env aenv t -> DelayedOpenExp env aenv t- cvtE = convertOpenExp fuseAcc-- cvtF :: OpenFun env aenv f -> DelayedOpenFun env aenv f- cvtF (Lam f) = Lam (cvtF f)- cvtF (Body b) = Body (cvtE b)---- Convert array programs as manifest terms.----manifest :: Bool -> OpenAcc aenv a -> DelayedOpenAcc aenv a-manifest fuseAcc (OpenAcc pacc) =- let fusionError = $internalError "manifest" "unexpected fusible materials"- in- Manifest $ case pacc of- -- Non-fusible terms- -- ------------------ Avar ix -> Avar ix- Use arr -> Use arr- Unit e -> Unit (cvtE e)- Alet bnd body -> alet (manifest fuseAcc bnd) (manifest fuseAcc body)- Acond p t e -> Acond (cvtE p) (manifest fuseAcc t) (manifest fuseAcc e)- Awhile p f a -> Awhile (cvtAF p) (cvtAF f) (manifest fuseAcc a)- Atuple tup -> Atuple (cvtAT tup)- Aprj ix tup -> Aprj ix (manifest fuseAcc tup)- Apply f a -> Apply (cvtAF f) (manifest fuseAcc a)- Aforeign ff f a -> Aforeign ff (cvtAF f) (manifest fuseAcc a)-- -- Producers- -- ---------- --- -- Some producers might still exist as a manifest array. Typically- -- this is because they are the last stage of the computation, or the- -- result of a let-binding to be used multiple times. The input array- -- here should be an array variable, else something went wrong.- --- Map f a -> Map (cvtF f) (delayed fuseAcc a)- Generate sh f -> Generate (cvtE sh) (cvtF f)- Transform sh p f a -> Transform (cvtE sh) (cvtF p) (cvtF f) (delayed fuseAcc a)- Backpermute sh p a -> Backpermute (cvtE sh) (cvtF p) (delayed fuseAcc a)- Reshape sl a -> Reshape (cvtE sl) (manifest fuseAcc a)-- Replicate{} -> fusionError- Slice{} -> fusionError- ZipWith{} -> fusionError-- -- Consumers- -- ---------- --- -- Embed producers directly into the representation. For stencils we- -- make an exception. Since these consumers access elements of the- -- argument array multiple times, we are careful not to duplicate work- -- and instead force the argument to be a manifest array.- --- Fold f z a -> Fold (cvtF f) (cvtE z) (delayed fuseAcc a)- Fold1 f a -> Fold1 (cvtF f) (delayed fuseAcc a)- FoldSeg f z a s -> FoldSeg (cvtF f) (cvtE z) (delayed fuseAcc a) (delayed fuseAcc s)- Fold1Seg f a s -> Fold1Seg (cvtF f) (delayed fuseAcc a) (delayed fuseAcc s)- Scanl f z a -> Scanl (cvtF f) (cvtE z) (delayed fuseAcc a)- Scanl1 f a -> Scanl1 (cvtF f) (delayed fuseAcc a)- Scanl' f z a -> Scanl' (cvtF f) (cvtE z) (delayed fuseAcc a)- Scanr f z a -> Scanr (cvtF f) (cvtE z) (delayed fuseAcc a)- Scanr1 f a -> Scanr1 (cvtF f) (delayed fuseAcc a)- Scanr' f z a -> Scanr' (cvtF f) (cvtE z) (delayed fuseAcc a)- Permute f d p a -> Permute (cvtF f) (manifest fuseAcc d) (cvtF p) (delayed fuseAcc a)- Stencil f x a -> Stencil (cvtF f) (cvtB x) (manifest fuseAcc a)- Stencil2 f x a y b -> Stencil2 (cvtF f) (cvtB x) (manifest fuseAcc a) (cvtB y) (manifest fuseAcc b)- -- Collect s -> Collect (cvtS s)-- where- -- Flatten needless let-binds, which can be introduced by the conversion to- -- the internal embeddable representation.- --- alet bnd body- | Manifest (Avar ZeroIdx) <- body- , Manifest x <- bnd- = x-- | otherwise- = Alet bnd body-- cvtAT :: Atuple (OpenAcc aenv) a -> Atuple (DelayedOpenAcc aenv) a- cvtAT NilAtup = NilAtup- cvtAT (SnocAtup t a) = cvtAT t `SnocAtup` manifest fuseAcc a-- cvtAF :: OpenAfun aenv f -> PreOpenAfun DelayedOpenAcc aenv f- cvtAF (Alam f) = Alam (cvtAF f)- cvtAF (Abody b) = Abody (manifest fuseAcc b)-- -- cvtS :: PreOpenSeq OpenAcc aenv senv s -> PreOpenSeq DelayedOpenAcc aenv senv s- -- cvtS = convertOpenSeq fuseAcc-- -- Conversions for closed scalar functions and expressions- --- cvtF :: OpenFun env aenv f -> DelayedOpenFun env aenv f- cvtF (Lam f) = Lam (cvtF f)- cvtF (Body b) = Body (cvtE b)-- cvtE :: OpenExp env aenv t -> DelayedOpenExp env aenv t- cvtE = convertOpenExp fuseAcc-- cvtB :: Boundary aenv t -> PreBoundary DelayedOpenAcc aenv t- cvtB Clamp = Clamp- cvtB Mirror = Mirror- cvtB Wrap = Wrap- cvtB (Constant v) = Constant v- cvtB (Function f) = Function (cvtF f)--convertOpenExp :: Bool -> OpenExp env aenv t -> DelayedOpenExp env aenv t-convertOpenExp fuseAcc exp =- case exp of- Let bnd body -> Let (cvtE bnd) (cvtE body)- Var ix -> Var ix- Const c -> Const c- Tuple tup -> Tuple (cvtT tup)- Prj ix t -> Prj ix (cvtE t)- IndexNil -> IndexNil- IndexCons sh sz -> IndexCons (cvtE sh) (cvtE sz)- IndexHead sh -> IndexHead (cvtE sh)- IndexTail sh -> IndexTail (cvtE sh)- IndexAny -> IndexAny- IndexSlice x ix sh -> IndexSlice x (cvtE ix) (cvtE sh)- IndexFull x ix sl -> IndexFull x (cvtE ix) (cvtE sl)- ToIndex sh ix -> ToIndex (cvtE sh) (cvtE ix)- FromIndex sh ix -> FromIndex (cvtE sh) (cvtE ix)- Cond p t e -> Cond (cvtE p) (cvtE t) (cvtE e)- While p f x -> While (cvtF p) (cvtF f) (cvtE x)- PrimConst c -> PrimConst c- PrimApp f x -> PrimApp f (cvtE x)- Index a sh -> Index (manifest fuseAcc a) (cvtE sh)- LinearIndex a i -> LinearIndex (manifest fuseAcc a) (cvtE i)- Shape a -> Shape (manifest fuseAcc a)- ShapeSize sh -> ShapeSize (cvtE sh)- Intersect s t -> Intersect (cvtE s) (cvtE t)- Union s t -> Union (cvtE s) (cvtE t)- Foreign ff f e -> Foreign ff (cvtF f) (cvtE e)- where- cvtT :: Tuple (OpenExp env aenv) t -> Tuple (DelayedOpenExp env aenv) t- cvtT NilTup = NilTup- cvtT (SnocTup t e) = cvtT t `SnocTup` cvtE e-- -- Conversions for closed scalar functions and expressions- --- cvtF :: OpenFun env aenv f -> DelayedOpenFun env aenv f- cvtF (Lam f) = Lam (cvtF f)- cvtF (Body b) = Body (cvtE b)-- cvtE :: OpenExp env aenv t -> DelayedOpenExp env aenv t- cvtE = convertOpenExp fuseAcc---convertOpenAfun :: Bool -> OpenAfun aenv f -> DelayedOpenAfun aenv f-convertOpenAfun c (Alam f) = Alam (convertOpenAfun c f)-convertOpenAfun c (Abody b) = Abody (convertOpenAcc c b)--{---convertOpenSeq :: Bool -> PreOpenSeq OpenAcc aenv senv a -> PreOpenSeq DelayedOpenAcc aenv senv a-convertOpenSeq fuseAcc s =- case s of- Consumer c -> Consumer (cvtC c)- Reify ix -> Reify ix- Producer p s' -> Producer p' (convertOpenSeq fuseAcc s')- where- p' = case p of- StreamIn arrs -> StreamIn arrs- ToSeq slix sh a -> ToSeq slix sh (delayed fuseAcc a)- MapSeq f x -> MapSeq (cvtAF f) x- ChunkedMapSeq f x -> ChunkedMapSeq (cvtAF f) x- ZipWithSeq f x y -> ZipWithSeq (cvtAF f) x y- ScanSeq f e x -> ScanSeq (cvtF f) (cvtE e) x- where- cvtC :: Consumer OpenAcc aenv senv a -> Consumer DelayedOpenAcc aenv senv a- cvtC c =- case c of- FoldSeq f e x -> FoldSeq (cvtF f) (cvtE e) x- FoldSeqFlatten f a x -> FoldSeqFlatten (cvtAF f) (manifest fuseAcc a) x- Stuple t -> Stuple (cvtCT t)-- cvtCT :: Atuple (Consumer OpenAcc aenv senv) t -> Atuple (Consumer DelayedOpenAcc aenv senv) t- cvtCT NilAtup = NilAtup- cvtCT (SnocAtup t c) = SnocAtup (cvtCT t) (cvtC c)-- cvtAF :: OpenAfun aenv f -> PreOpenAfun DelayedOpenAcc aenv f- cvtAF (Alam f) = Alam (cvtAF f)- cvtAF (Abody b) = Abody (manifest fuseAcc b)-- cvtE :: OpenExp env aenv t -> DelayedOpenExp env aenv t- cvtE = convertOpenExp fuseAcc-- cvtF :: OpenFun env aenv f -> DelayedOpenFun env aenv f- cvtF (Lam f) = Lam (cvtF f)- cvtF (Body b) = Body (cvtE b)---}----- | Apply the fusion transformation to the AST to combine and simplify terms.--- This converts terms into the internal delayed array representation and merges--- adjacent producer/producer terms. Using the reduced internal form limits the--- number of combinations that need to be considered.----type EmbedAcc acc = forall aenv arrs. Arrays arrs => acc aenv arrs -> Embed acc aenv arrs-type ElimAcc acc = forall aenv s t. acc aenv s -> acc (aenv,s) t -> Bool--embedOpenAcc :: Arrays arrs => Bool -> OpenAcc aenv arrs -> Embed OpenAcc aenv arrs-embedOpenAcc fuseAcc (OpenAcc pacc) =- embedPreAcc fuseAcc (embedOpenAcc fuseAcc) elimOpenAcc pacc- where- -- When does the cost of re-computation outweigh that of memory access? For- -- the moment only do the substitution on a single use of the bound array- -- into the use site, but it is likely advantageous to be far more- -- aggressive here.- --- -- SEE: [Sharing vs. Fusion]- --- elimOpenAcc :: ElimAcc OpenAcc- elimOpenAcc _bnd body- | count False ZeroIdx body <= lIMIT = True- | otherwise = False- where- lIMIT = 1-- count :: UsesOfAcc OpenAcc- count no ix (OpenAcc pacc) = usesOfPreAcc no count ix pacc---embedPreAcc- :: forall acc aenv arrs. (Kit acc, Arrays arrs)- => Bool- -> EmbedAcc acc- -> ElimAcc acc- -> PreOpenAcc acc aenv arrs- -> Embed acc aenv arrs-embedPreAcc fuseAcc embedAcc elimAcc pacc- = unembed- $ case pacc of-- -- Non-fusible terms- -- ------------------ --- -- Solid and semi-solid terms that we generally do not wish to fuse, such- -- as control flow (|?), array introduction (use, unit), array tupling and- -- projection, and foreign function operations. Generally we also do not- -- want to fuse past array let bindings, as this would imply work- -- duplication. SEE: [Sharing vs. Fusion]- --- Apply f a -> applyD (cvtAF f) (cvtA a)- Alet bnd body -> aletD embedAcc elimAcc bnd body- Aprj ix tup -> aprjD embedAcc ix tup- Acond p at ae -> acondD embedAcc (cvtE p) at ae- Awhile p f a -> done $ Awhile (cvtAF p) (cvtAF f) (cvtA a)- Atuple tup -> done $ Atuple (cvtAT tup)- Aforeign ff f a -> done $ Aforeign ff (cvtAF f) (cvtA a)- -- Collect s -> collectD s-- -- Array injection- Avar v -> done $ Avar v- Use arrs -> done $ Use arrs- Unit e -> done $ Unit (cvtE e)-- -- Producers- -- ---------- --- -- The class of operations that given a set of zero or more input arrays,- -- produce a _single_ element for the output array by manipulating a- -- _single_ element from each input array. These can be further classified- -- as value (map, zipWith) or index space (backpermute, slice, replicate)- -- transformations.- --- -- The critical feature is that each element of the output is produced- -- independently of all others, and so we can aggressively fuse arbitrary- -- sequences of these operations.- --- Generate sh f -> generateD (cvtE sh) (cvtF f)-- Map f a -> mapD (cvtF f) (embedAcc a)- ZipWith f a b -> fuse2 (into zipWithD (cvtF f)) a b- Transform sh p f a -> transformD (cvtE sh) (cvtF p) (cvtF f) (embedAcc a)-- Backpermute sl p a -> fuse (into2 backpermuteD (cvtE sl) (cvtF p)) a- Slice slix a sl -> fuse (into (sliceD slix) (cvtE sl)) a- Replicate slix sh a -> fuse (into (replicateD slix) (cvtE sh)) a- Reshape sl a -> reshapeD (embedAcc a) (cvtE sl)-- -- Consumers- -- ---------- --- -- Operations where each element of the output array depends on multiple- -- elements of the input array. To implement these operations efficiently in- -- parallel, we need to know how elements of the array depend on each other:- -- a parallel scan is implemented very differently from a parallel fold, for- -- example.- --- -- In order to avoid obfuscating this crucial information required for- -- parallel implementation, fusion is separated into to phases:- -- producer/producer, implemented above, and consumer/producer, which is- -- implemented below. This will place producers adjacent to the consumer- -- node, so that the producer can be directly embedded into the consumer- -- during the code generation phase.- --- Fold f z a -> embed (into2 Fold (cvtF f) (cvtE z)) a- Fold1 f a -> embed (into Fold1 (cvtF f)) a- FoldSeg f z a s -> embed2 (into2 FoldSeg (cvtF f) (cvtE z)) a s- Fold1Seg f a s -> embed2 (into Fold1Seg (cvtF f)) a s- Scanl f z a -> embed (into2 Scanl (cvtF f) (cvtE z)) a- Scanl1 f a -> embed (into Scanl1 (cvtF f)) a- Scanl' f z a -> embed (into2 Scanl' (cvtF f) (cvtE z)) a- Scanr f z a -> embed (into2 Scanr (cvtF f) (cvtE z)) a- Scanr1 f a -> embed (into Scanr1 (cvtF f)) a- Scanr' f z a -> embed (into2 Scanr' (cvtF f) (cvtE z)) a- Permute f d p a -> embed2 (into2 permute (cvtF f) (cvtF p)) d a- Stencil f x a -> lift (into2 Stencil (cvtF f) (cvtB x)) a- Stencil2 f x a y b -> lift2 (into3 stencil2 (cvtF f) (cvtB x) (cvtB y)) a b-- where- -- If fusion is not enabled, force terms to the manifest representation- --- unembed :: Embed acc aenv arrs -> Embed acc aenv arrs- unembed x- | fuseAcc = x- | otherwise = done (compute x)-- cvtA :: Arrays a => acc aenv' a -> acc aenv' a- cvtA = computeAcc . embedAcc-- cvtAT :: Atuple (acc aenv') a -> Atuple (acc aenv') a- cvtAT NilAtup = NilAtup- cvtAT (SnocAtup tup a) = cvtAT tup `SnocAtup` cvtA a-- cvtAF :: PreOpenAfun acc aenv' f -> PreOpenAfun acc aenv' f- cvtAF (Alam f) = Alam (cvtAF f)- cvtAF (Abody a) = Abody (cvtA a)-- -- Helpers to shuffle the order of arguments to a constructor- --- permute f p d a = Permute f d p a- stencil2 f x y a b = Stencil2 f x a y b-- -- Conversions for closed scalar functions and expressions. This just- -- applies scalar simplifications.- --- cvtF :: PreFun acc aenv' t -> PreFun acc aenv' t- cvtF = simplify-- cvtE :: Elt t => PreExp acc aenv' t -> PreExp acc aenv' t- cvtE = simplify-- cvtB :: PreBoundary acc aenv' t -> PreBoundary acc aenv' t- cvtB Clamp = Clamp- cvtB Mirror = Mirror- cvtB Wrap = Wrap- cvtB (Constant c) = Constant c- cvtB (Function f) = Function (cvtF f)-- -- Helpers to embed and fuse delayed terms- --- into :: Sink f => (f env' a -> b) -> f env a -> Extend acc env env' -> b- into op a env = op (sink env a)-- into2 :: (Sink f1, Sink f2)- => (f1 env' a -> f2 env' b -> c) -> f1 env a -> f2 env b -> Extend acc env env' -> c- into2 op a b env = op (sink env a) (sink env b)-- into3 :: (Sink f1, Sink f2, Sink f3)- => (f1 env' a -> f2 env' b -> f3 env' c -> d) -> f1 env a -> f2 env b -> f3 env c -> Extend acc env env' -> d- into3 op a b c env = op (sink env a) (sink env b) (sink env c)-- fuse :: Arrays as- => (forall aenv'. Extend acc aenv aenv' -> Cunctation acc aenv' as -> Cunctation acc aenv' bs)- -> acc aenv as- -> Embed acc aenv bs- fuse op (embedAcc -> Embed env cc) = Embed env (op env cc)-- fuse2 :: (Arrays as, Arrays bs)- => (forall aenv'. Extend acc aenv aenv' -> Cunctation acc aenv' as -> Cunctation acc aenv' bs -> Cunctation acc aenv' cs)- -> acc aenv as- -> acc aenv bs- -> Embed acc aenv cs- fuse2 op a1 a0- | Embed env1 cc1 <- embedAcc a1- , Embed env0 cc0 <- embedAcc (sink env1 a0)- , env <- env1 `append` env0- = Embed env (op env (sink env0 cc1) cc0)-- embed :: (Arrays as, Arrays bs)- => (forall aenv'. Extend acc aenv aenv' -> acc aenv' as -> PreOpenAcc acc aenv' bs)- -> acc aenv as- -> Embed acc aenv bs- embed = trav1 id-- embed2 :: forall aenv as bs cs. (Arrays as, Arrays bs, Arrays cs)- => (forall aenv'. Extend acc aenv aenv' -> acc aenv' as -> acc aenv' bs -> PreOpenAcc acc aenv' cs)- -> acc aenv as- -> acc aenv bs- -> Embed acc aenv cs- embed2 = trav2 id id-- lift :: (Arrays as, Arrays bs)- => (forall aenv'. Extend acc aenv aenv' -> acc aenv' as -> PreOpenAcc acc aenv' bs)- -> acc aenv as- -> Embed acc aenv bs- lift = trav1 bind-- lift2 :: forall aenv as bs cs. (Arrays as, Arrays bs, Arrays cs)- => (forall aenv'. Extend acc aenv aenv' -> acc aenv' as -> acc aenv' bs -> PreOpenAcc acc aenv' cs)- -> acc aenv as- -> acc aenv bs- -> Embed acc aenv cs- lift2 = trav2 bind bind-- trav1 :: (Arrays as, Arrays bs)- => (forall aenv'. Embed acc aenv' as -> Embed acc aenv' as)- -> (forall aenv'. Extend acc aenv aenv' -> acc aenv' as -> PreOpenAcc acc aenv' bs)- -> acc aenv as- -> Embed acc aenv bs- trav1 f op (f . embedAcc -> Embed env cc)- = Embed (env `PushEnv` inject (op env (inject (compute' cc)))) (Done ZeroIdx)-- trav2 :: forall aenv as bs cs. (Arrays as, Arrays bs, Arrays cs)- => (forall aenv'. Embed acc aenv' as -> Embed acc aenv' as)- -> (forall aenv'. Embed acc aenv' bs -> Embed acc aenv' bs)- -> (forall aenv'. Extend acc aenv aenv' -> acc aenv' as -> acc aenv' bs -> PreOpenAcc acc aenv' cs)- -> acc aenv as- -> acc aenv bs- -> Embed acc aenv cs- trav2 f1 f0 op (f1 . embedAcc -> Embed env1 cc1) (f0 . embedAcc . sink env1 -> Embed env0 cc0)- | env <- env1 `append` env0- , acc1 <- inject . compute' $ sink env0 cc1- , acc0 <- inject . compute' $ cc0- = Embed (env `PushEnv` inject (op env acc1 acc0)) (Done ZeroIdx)-- -- Helper functions to lift out and let-bind a manifest array. That is,- -- instead of the sequence- --- -- > stencil s (map f a)- --- -- we get:- --- -- > let a' = map f a- -- > in stencil s a'- --- -- This is required for the LLVM backend's default implementation of- -- stencil operations.- --- bind :: Arrays as => Embed acc aenv' as -> Embed acc aenv' as- bind (Embed env cc)- | Done{} <- cc = Embed env cc- | otherwise = Embed (env `PushEnv` inject (compute' cc)) (Done ZeroIdx)-- -- -- Move additional bindings for producers outside of the sequence, so that- -- -- producers may fuse with their arguments resulting in actual sequencing- -- collectD :: PreOpenSeq acc aenv () arrs- -- -> Embed acc aenv arrs- -- collectD (embedSeq embedAcc -> ExtendSeq env s')- -- = Embed (env `PushEnv` inject (Collect s')) (Done ZeroIdx)---{----- Move additional bindings for producer outside of sequence, so--- that producers may fuse with their arguments, resulting in--- actual sequencing.-embedSeq :: forall acc aenv arrs. Kit acc- => EmbedAcc acc- -> PreOpenSeq acc aenv () arrs- -> ExtendSeq acc aenv () arrs-embedSeq embedAcc s- = travS s BaseEnv- where- travS :: forall senv aenv' arrs'.- PreOpenSeq acc aenv senv arrs'- -> Extend acc aenv aenv'- -> ExtendSeq acc aenv senv arrs'- travS s env =- case s of- Producer p s- | ExtendSeq env' s' <- travS s env- , ExtendProducer env'' p' <- travP p env'- -> ExtendSeq (env' `append` env'') (Producer p' (sinkSeq env'' s'))- Consumer c- | c' <- travC c env- -> ExtendSeq env (Consumer c')- Reify ix- -> ExtendSeq env (Reify ix)-- travP :: forall arrs' aenv' senv.- Producer acc aenv senv arrs'- -> Extend acc aenv aenv'- -> ExtendProducer acc aenv' senv arrs'- travP (ToSeq slix sh a) env- | Embed env' cc <- embedAcc (sink env a)- = ExtendProducer env' (ToSeq slix sh (inject (compute' cc)))- travP (StreamIn arrs) _ = ExtendProducer BaseEnv (StreamIn arrs)- travP (MapSeq f x) env = ExtendProducer BaseEnv (MapSeq (cvtAF (sink env f)) x)- travP (ChunkedMapSeq f x) env = ExtendProducer BaseEnv (ChunkedMapSeq (cvtAF (sink env f)) x)- travP (ZipWithSeq f x y) env = ExtendProducer BaseEnv (ZipWithSeq (cvtAF (sink env f)) x y)- travP (ScanSeq f e x) env = ExtendProducer BaseEnv (ScanSeq (cvtF (sink env f)) (cvtE (sink env e)) x)-- travC :: forall arrs' aenv' senv.- Consumer acc aenv senv arrs'- -> Extend acc aenv aenv'- -> Consumer acc aenv' senv arrs'- travC (FoldSeq f e x) env = FoldSeq (cvtF (sink env f)) (cvtE (sink env e)) x- travC (FoldSeqFlatten f a x) env = FoldSeqFlatten (cvtAF (sink env f)) (cvtA (sink env a)) x- travC (Stuple t) env = Stuple (cvtCT t)- where- cvtCT :: Atuple (Consumer acc aenv senv) t -> Atuple (Consumer acc aenv' senv) t- cvtCT NilAtup = NilAtup- cvtCT (SnocAtup t c) = SnocAtup (cvtCT t) (travC c env)-- cvtE :: Elt t => PreExp acc aenv' t -> PreExp acc aenv' t- cvtE = simplify-- cvtF :: PreFun acc aenv' t -> PreFun acc aenv' t- cvtF = simplify-- cvtA :: Arrays a => acc aenv' a -> acc aenv' a- cvtA = computeAcc . embedAcc-- cvtAF :: PreOpenAfun acc aenv' f -> PreOpenAfun acc aenv' f- cvtAF (Alam f) = Alam (cvtAF f)- cvtAF (Abody a) = Abody (cvtA a)----- A sequence with additional bindings-data ExtendSeq acc aenv senv arrs where- ExtendSeq :: forall acc aenv aenv' senv arrs.- Extend acc aenv aenv'- -> PreOpenSeq acc aenv' senv arrs- -> ExtendSeq acc aenv senv arrs---- A producer with additional bindings-data ExtendProducer acc aenv senv arrs where- ExtendProducer :: forall acc aenv aenv' senv arrs.- Extend acc aenv aenv'- -> Producer acc aenv' senv arrs- -> ExtendProducer acc aenv senv arrs---}----- Internal representation--- =======================---- Note: [Representing delayed array]------ During the fusion transformation we represent terms as a pair consisting of--- a collection of supplementary environment bindings and a description of how--- to construct the array.------ It is critical to separate these two. To create a real AST node we need both--- the environment and array term, but analysis of how to fuse terms requires--- only the array description. If the additional bindings are bundled as part of--- the representation, the existentially quantified extended environment type--- will be untouchable. This is problematic because the terms of the two arrays--- are defined with respect to this existentially quantified type, and there is--- no way to directly combine these two environments:------ append :: Extend env env1 -> Extend env env2 -> Extend env ???------ And hence, no way to combine the terms of the delayed representation.------ The only way to bring terms into the same scope is to operate via the--- manifest terms. This entails a great deal of conversion between delayed and--- AST terms, but is certainly possible.------ However, because of the limited scope into which this existential type is--- available, we ultimately perform this process many times. In fact, complexity--- of the fusion algorithm for an AST of N terms becomes O(r^n), where r is the--- number of different rules we have for combining terms.----data Embed acc aenv a where- Embed :: Extend acc aenv aenv'- -> Cunctation acc aenv' a- -> Embed acc aenv a----- Cunctation (n): the action or an instance of delaying; a tardy action.------ This describes the ways in which the fusion transformation represents--- intermediate arrays. The fusion process operates by recasting producer array--- computations in terms of a set of scalar functions used to construct an--- element at each index, and fusing successive producers by combining these--- scalar functions.----data Cunctation acc aenv a where-- -- The base case is just a real (manifest) array term. No fusion happens here.- -- Note that the array is referenced by an index into the extended- -- environment, ensuring that the array is manifest and making the term- -- non-recursive in 'acc'. Also note that the return type is a general- -- instance of Arrays and not restricted to a single Array.- --- Done :: Arrays a- => Idx aenv a- -> Cunctation acc aenv a-- -- We can represent an array by its shape and a function to compute an element- -- at each index.- --- Yield :: (Shape sh, Elt e)- => PreExp acc aenv sh- -> PreFun acc aenv (sh -> e)- -> Cunctation acc aenv (Array sh e)-- -- A more restrictive form than 'Yield' may afford greater opportunities for- -- optimisation by a backend. This more structured form applies an index and- -- value transform to an input array. Note that the transform is applied to an- -- array stored as an environment index, so that the term is non-recursive and- -- it is always possible to embed into a collective operation.- --- Step :: (Shape sh, Shape sh', Elt a, Elt b)- => PreExp acc aenv sh'- -> PreFun acc aenv (sh' -> sh)- -> PreFun acc aenv (a -> b)- -> Idx aenv (Array sh a)- -> Cunctation acc aenv (Array sh' b)---instance Kit acc => Simplify (Cunctation acc aenv a) where- simplify (Done v) = Done v- simplify (Yield sh f) = Yield (simplify sh) (simplify f)- simplify (Step sh p f v) = Step (simplify sh) (simplify p) (simplify f) v----- Convert a real AST node into the internal representation----done :: (Arrays a, Kit acc) => PreOpenAcc acc aenv a -> Embed acc aenv a-done pacc- | Avar v <- pacc = Embed BaseEnv (Done v)- | otherwise = Embed (BaseEnv `PushEnv` inject pacc) (Done ZeroIdx)----- Recast a cunctation into a mapping from indices to elements.----yield :: Kit acc- => Cunctation acc aenv (Array sh e)- -> Cunctation acc aenv (Array sh e)-yield cc =- case cc of- Yield{} -> cc- Step sh p f v -> Yield sh (f `compose` indexArray v `compose` p)- Done v- | ArraysRarray <- accType cc -> Yield (arrayShape v) (indexArray v)- | otherwise -> error "yield: impossible case"----- Recast a cunctation into transformation step form. Not possible if the source--- was in the Yield formulation.----step :: Kit acc- => Cunctation acc aenv (Array sh e)- -> Maybe (Cunctation acc aenv (Array sh e))-step cc =- case cc of- Yield{} -> Nothing- Step{} -> Just cc- Done v- | ArraysRarray <- accType cc -> Just $ Step (arrayShape v) identity identity v- | otherwise -> error "step: impossible case"----- Get the shape of a delayed array----shape :: Kit acc => Cunctation acc aenv (Array sh e) -> PreExp acc aenv sh-shape cc- | Just (Step sh _ _ _) <- step cc = sh- | Yield sh _ <- yield cc = sh----- Reified type of a delayed array representation.----accType :: forall acc aenv a. Arrays a => Cunctation acc aenv a -> ArraysR (ArrRepr a)-accType _ = arrays (undefined :: a)----- Environment manipulation--- ========================--instance Kit acc => Sink (Cunctation acc) where- weaken k cc = case cc of- Done v -> Done (weaken k v)- Step sh p f v -> Step (weaken k sh) (weaken k p) (weaken k f) (weaken k v)- Yield sh f -> Yield (weaken k sh) (weaken k f)---- prjExtend :: Kit acc => Extend acc env env' -> Idx env' t -> PreOpenAcc acc env' t--- prjExtend (PushEnv _ v) ZeroIdx = weakenA rebuildAcc SuccIdx v--- prjExtend (PushEnv env _) (SuccIdx idx) = weakenA rebuildAcc SuccIdx $ prjExtend env idx--- prjExtend _ _ = $internalError "prjExtend" "inconsistent valuation"--{----- Rearrange type arguments to fit with Sink type class.-newtype SinkSeq acc senv aenv a = SinkSeq { unSinkSeq :: PreOpenSeq acc aenv senv a }---- sink for sequences.-sinkSeq :: Kit acc => Extend acc aenv aenv' -> PreOpenSeq acc aenv senv a -> PreOpenSeq acc aenv' senv a-sinkSeq env s = unSinkSeq $ sink env (SinkSeq s)--instance Kit acc => Sink (SinkSeq acc senv) where- weaken :: forall aenv aenv' arrs. aenv :> aenv' -> SinkSeq acc senv aenv arrs -> SinkSeq acc senv aenv' arrs- weaken k (SinkSeq s) = SinkSeq $- case s of- Producer p s' -> Producer (weakenP p) (weakenL s')- Consumer c -> Consumer (weakenC c)- Reify ix -> Reify ix-- where- weakenL :: forall senv' arrs'. PreOpenSeq acc aenv senv' arrs' -> PreOpenSeq acc aenv' senv' arrs'- weakenL s' = unSinkSeq (weaken k (SinkSeq s'))-- weakenP :: forall a. Producer acc aenv senv a -> Producer acc aenv' senv a- weakenP p =- case p of- StreamIn arrs -> StreamIn arrs- ToSeq slix sh a -> ToSeq slix sh (weaken k a)- MapSeq f x -> MapSeq (weaken k f) x- ChunkedMapSeq f x -> ChunkedMapSeq (weaken k f) x- ZipWithSeq f x y -> ZipWithSeq (weaken k f) x y- ScanSeq f a x -> ScanSeq (weaken k f) (weaken k a) x-- weakenC :: forall a. Consumer acc aenv senv a -> Consumer acc aenv' senv a- weakenC c =- case c of- FoldSeq f a x -> FoldSeq (weaken k f) (weaken k a) x- FoldSeqFlatten f a x -> FoldSeqFlatten (weaken k f) (weaken k a) x- Stuple t ->- let wk :: Atuple (Consumer acc aenv senv) t -> Atuple (Consumer acc aenv' senv) t- wk NilAtup = NilAtup- wk (SnocAtup t c) = wk t `SnocAtup` weakenC c- in- Stuple (wk t)---}---- Array fusion of a de Bruijn computation AST--- ===========================================---- Array computations--- ---------------------- Recast the internal representation of delayed arrays into a real AST node.--- Use the most specific version of a combinator whenever possible.----compute :: (Kit acc, Arrays arrs) => Embed acc aenv arrs -> PreOpenAcc acc aenv arrs-compute (Embed env cc) = bind env (compute' cc)--compute' :: (Kit acc, Arrays arrs) => Cunctation acc aenv arrs -> PreOpenAcc acc aenv arrs-compute' cc = case simplify cc of- Done v -> Avar v- Yield sh f -> Generate sh f- Step sh p f v- | Just Refl <- match sh (simplify (arrayShape v))- , Just Refl <- isIdentity p- , Just Refl <- isIdentity f -> Avar v- | Just Refl <- match sh (simplify (arrayShape v))- , Just Refl <- isIdentity p -> Map f (avarIn v)- | Just Refl <- isIdentity f -> Backpermute sh p (avarIn v)- | otherwise -> Transform sh p f (avarIn v)----- Evaluate a delayed computation and tie the recursive knot----computeAcc :: (Kit acc, Arrays arrs) => Embed acc aenv arrs -> acc aenv arrs-computeAcc = inject . compute----- Representation of a generator as a delayed array----generateD :: (Shape sh, Elt e)- => PreExp acc aenv sh- -> PreFun acc aenv (sh -> e)- -> Embed acc aenv (Array sh e)-generateD sh f- = Stats.ruleFired "generateD"- $ Embed BaseEnv (Yield sh f)----- Fuse a unary function into a delayed array. Also looks for unzips which can--- be executed in constant time; SEE [unzipD]----mapD :: (Kit acc, Shape sh, Elt b)- => PreFun acc aenv (a -> b)- -> Embed acc aenv (Array sh a)- -> Embed acc aenv (Array sh b)-mapD f (unzipD f -> Just a) = a-mapD f (Embed env cc)- = Stats.ruleFired "mapD"- $ Embed env (go cc)- where- go (step -> Just (Step sh ix g v)) = Step sh ix (sink env f `compose` g) v- go (yield -> Yield sh g) = Yield sh (sink env f `compose` g)----- If we are unzipping a manifest array then force the term to be computed;--- a backend will be able to execute this in constant time. This operations--- looks for the right terms recursively, splitting operations such as:------ > map (\x -> fst . fst ... x) arr------ into multiple stages so that they can all be executed in constant time:------ > map fst . map fst ... arr------ Note that this is a speculative operation, since we could dig under several--- levels of projection before discovering that the operation can not be--- unzipped. This should be fine though because digging through the terms is--- relatively cheap; no environment changing operations are required.----unzipD- :: (Kit acc, Shape sh, Elt b)- => PreFun acc aenv (a -> b)- -> Embed acc aenv (Array sh a)- -> Maybe (Embed acc aenv (Array sh b))-unzipD f (Embed env (Done v))- | Lam (Body (Prj tix (Var ZeroIdx))) <- f- = Stats.ruleFired "unzipD"- $ let f' = Lam (Body (Prj tix (Var ZeroIdx)))- a' = avarIn v- in- Just $ Embed (env `PushEnv` inject (Map f' a')) (Done ZeroIdx)-- | Lam (Body (Prj tix p@Prj{})) <- f- , Just (Embed env' (Done v')) <- unzipD (Lam (Body p)) (Embed env (Done v))- = Stats.ruleFired "unzipD"- $ let f' = Lam (Body (Prj tix (Var ZeroIdx)))- a' = avarIn v'- in- Just $ Embed (env' `PushEnv` inject (Map f' a')) (Done ZeroIdx)--unzipD _ _- = Nothing----- Fuse an index space transformation function that specifies where elements in--- the destination array read there data from in the source array.----backpermuteD- :: (Kit acc, Shape sh')- => PreExp acc aenv sh'- -> PreFun acc aenv (sh' -> sh)- -> Cunctation acc aenv (Array sh e)- -> Cunctation acc aenv (Array sh' e)-backpermuteD sh' p = Stats.ruleFired "backpermuteD" . go- where- go (step -> Just (Step _ q f v)) = Step sh' (q `compose` p) f v- go (yield -> Yield _ g) = Yield sh' (g `compose` p)----- Transform as a combined map and backwards permutation----transformD- :: (Kit acc, Shape sh, Shape sh', Elt b)- => PreExp acc aenv sh'- -> PreFun acc aenv (sh' -> sh)- -> PreFun acc aenv (a -> b)- -> Embed acc aenv (Array sh a)- -> Embed acc aenv (Array sh' b)-transformD sh' p f- = Stats.ruleFired "transformD"- . fuse (into2 backpermuteD sh' p)- . mapD f- where- fuse :: (forall aenv'. Extend acc aenv aenv' -> Cunctation acc aenv' as -> Cunctation acc aenv' bs)- -> Embed acc aenv as- -> Embed acc aenv bs- fuse op (Embed env cc) = Embed env (op env cc)-- into2 :: (Sink f1, Sink f2)- => (f1 env' a -> f2 env' b -> c) -> f1 env a -> f2 env b -> Extend acc env env' -> c- into2 op a b env = op (sink env a) (sink env b)----- Replicate as a backwards permutation------ TODO: If we have a pattern such as `replicate sh (map f xs)` then in some--- cases it might be beneficial to not fuse these terms, if `f` is--- expensive and/or `sh` is large.----replicateD- :: (Kit acc, Shape sh, Shape sl, Elt slix)- => SliceIndex (EltRepr slix) (EltRepr sl) co (EltRepr sh)- -> PreExp acc aenv slix- -> Cunctation acc aenv (Array sl e)- -> Cunctation acc aenv (Array sh e)-replicateD sliceIndex slix cc- = Stats.ruleFired "replicateD"- $ backpermuteD (IndexFull sliceIndex slix (shape cc)) (extend sliceIndex slix) cc----- Dimensional slice as a backwards permutation----sliceD- :: (Kit acc, Shape sh, Shape sl, Elt slix)- => SliceIndex (EltRepr slix) (EltRepr sl) co (EltRepr sh)- -> PreExp acc aenv slix- -> Cunctation acc aenv (Array sh e)- -> Cunctation acc aenv (Array sl e)-sliceD sliceIndex slix cc- = Stats.ruleFired "sliceD"- $ backpermuteD (IndexSlice sliceIndex slix (shape cc)) (restrict sliceIndex slix) cc----- Reshape an array------ For delayed arrays this is implemented as an index space transformation. For--- manifest arrays this can be done with the standard Reshape operation in--- constant time without executing any array operations. This does not affect--- the fusion process since the term is already manifest.------ TLM: there was a runtime check to ensure the old and new shapes contained the--- same number of elements: this has been lost for the delayed cases!----reshapeD- :: (Kit acc, Shape sh, Shape sl, Elt e)- => Embed acc aenv (Array sh e)- -> PreExp acc aenv sl- -> Embed acc aenv (Array sl e)-reshapeD (Embed env cc) (sink env -> sl)- | Done v <- cc- = Embed (env `PushEnv` inject (Reshape sl (avarIn v))) (Done ZeroIdx)-- | otherwise- = Stats.ruleFired "reshapeD"- $ Embed env (backpermuteD sl (reindex (shape cc) sl) cc)----- Combine two arrays element-wise with a binary function to produce a delayed--- array.----zipWithD :: (Kit acc, Shape sh, Elt a, Elt b, Elt c)- => PreFun acc aenv (a -> b -> c)- -> Cunctation acc aenv (Array sh a)- -> Cunctation acc aenv (Array sh b)- -> Cunctation acc aenv (Array sh c)-zipWithD f cc1 cc0- -- Two stepper functions identically accessing the same array can be kept in- -- stepping form. This might yield a simpler final term.- --- | Just (Step sh1 p1 f1 v1) <- step cc1- , Just (Step sh0 p0 f0 v0) <- step cc0- , Just Refl <- match v1 v0- , Just Refl <- match p1 p0- = Stats.ruleFired "zipWithD/step"- $ Step (sh1 `Intersect` sh0) p0 (combine f f1 f0) v0-- -- Otherwise transform both delayed terms into (index -> value) mappings and- -- combine the two indexing functions that way.- --- | Yield sh1 f1 <- yield cc1- , Yield sh0 f0 <- yield cc0- = Stats.ruleFired "zipWithD"- $ Yield (sh1 `Intersect` sh0) (combine f f1 f0)-- where- combine :: forall acc aenv a b c e. (Kit acc, Elt a, Elt b, Elt c)- => PreFun acc aenv (a -> b -> c)- -> PreFun acc aenv (e -> a)- -> PreFun acc aenv (e -> b)- -> PreFun acc aenv (e -> c)- combine c ixa ixb- | Lam (Lam (Body c')) <- weakenE SuccIdx c :: PreOpenFun acc ((),e) aenv (a -> b -> c)- , Lam (Body ixa') <- ixa -- else the skolem 'e' will escape- , Lam (Body ixb') <- ixb- = Lam $ Body $ Let ixa' $ Let (weakenE SuccIdx ixb') c'----- NOTE: [Sharing vs. Fusion]------ The approach to array fusion is similar to that the first generation of Repa.--- It was discovered that the most immediately pressing problem with delayed--- arrays in Repa-1 was that it did not preserve sharing of collective--- operations, leading to excessive recomputation and severe repercussions on--- performance if the user did not explicitly intervene.------ However, as we have explicit sharing information in the term tree, so it is--- straightforward to respect sharing by not fusing let-bindings, as that--- introduces work duplication. However, sometimes we can be cleverer.------ let-floating:--- ------------------- If the binding is of manifest data, we can instead move the let-binding to a--- different point in the program and then continue to fuse into the body. This--- is done by adding the bound term to the Extend environment. In essence this--- is covering a different occurrence of the same problem Extend was introduced--- to handle: let bindings of manifest data unnecessarily get in the way of the--- fusion process. For example:------ map f (zipWith g xs (map h xs))------ after sharing recovery results in:------ map f (let a0 = xs in zipWith g a0 (map h a0))------ Without allowing the binding for a0 to float outwards, `map f` will not be--- fused into the rest of the program.------ let-elimination:--- ---------------------- Array binding points appear in the program because the array data _or_ shape--- was accessed multiple times in the source program. In general we want to fuse--- arbitrary sequences of array _data_, irrespective of how the shape component--- is used. For example, reverse is defined in the prelude as:------ reverse xs = let len = unindex1 (shape xs)--- pf i = len - i - 1--- in--- backpermute (shape xs) (ilift1 pf) xs------ Sharing recovery introduces a let-binding for the input `xs` since it is used--- thrice in the definition, which impedes subsequent fusion. However the actual--- array data is only accessed once, with the remaining two uses querying the--- array shape. Since the delayed terms contain the shape of the array they--- represent as a scalar term, if the data component otherwise satisfies the--- rules for fusing terms, as it does in this example, we can eliminate the--- let-binding by pushing the scalar shape and value generation terms directly--- into the body.------ Let-elimination can also be used to _introduce_ work duplication, which may--- be beneficial if we can estimate that the cost of recomputation is less than--- the cost of completely evaluating the array and subsequently retrieving the--- data from memory.------ let-binding:--- ------------------ Ultimately, we might not want to eliminate the binding. If so, evaluate it--- and add it to a _clean_ Extend environment for the body. If not, the Extend--- list effectively _flattens_ all bindings, so any terms required for the bound--- term get lifted out to the same scope as the body. This increases their--- lifetime and hence raises the maximum memory used. If we don't do this, we--- get terms such as:------ let a0 = <terms for binding> in--- let bnd = <bound term> in--- <body term>------ rather than the following, where the scope of a0 is clearly only availably--- when evaluating the bound term, as it should be:------ let bnd =--- let a0 = <terms for binding>--- in <bound term>--- in <body term>----aletD :: (Kit acc, Arrays arrs, Arrays brrs)- => EmbedAcc acc- -> ElimAcc acc- -> acc aenv arrs- -> acc (aenv,arrs) brrs- -> Embed acc aenv brrs-aletD embedAcc elimAcc (embedAcc -> Embed env1 cc1) acc0-- -- let-floating- -- ------------- --- -- Immediately inline the variable referring to the bound expression into the- -- body, instead of adding to the environments and creating an indirection- -- that must be later eliminated by shrinking.- --- | Done v1 <- cc1- , Embed env0 cc0 <- embedAcc $ rebuildA (subAtop (Avar v1) . sink1 env1) acc0- = Stats.ruleFired "aletD/float"- $ Embed (env1 `append` env0) cc0-- -- Ensure we only call 'embedAcc' once on the body expression- --- | otherwise- = aletD' embedAcc elimAcc (Embed env1 cc1) (embedAcc acc0)---aletD' :: forall acc aenv arrs brrs. (Kit acc, Arrays arrs, Arrays brrs)- => EmbedAcc acc- -> ElimAcc acc- -> Embed acc aenv arrs- -> Embed acc (aenv, arrs) brrs- -> Embed acc aenv brrs-aletD' embedAcc elimAcc (Embed env1 cc1) (Embed env0 cc0)-- -- let-binding- -- ------------ --- -- Check whether we can eliminate the let-binding. Note that we must inspect- -- the entire term, not just the Cunctation that would be produced by- -- embedAcc. If we don't we can be left with dead terms that don't get- -- eliminated. This problem occurred in the canny program.- --- | acc1 <- compute (Embed env1 cc1)- , False <- elimAcc (inject acc1) acc0- = Stats.ruleFired "aletD/bind"- $ Embed (BaseEnv `PushEnv` inject acc1 `append` env0) cc0-- -- let-elimination- -- ---------------- --- -- Handle the remaining cases in a separate function. It turns out that this- -- is important so we aren't excessively sinking/delaying terms.- --- | acc0' <- sink1 env1 acc0- = Stats.ruleFired "aletD/eliminate"- $ case cc1 of- Step{} -> eliminate env1 cc1 acc0'- Yield{} -> eliminate env1 cc1 acc0'-- where- acc0 :: acc (aenv, arrs) brrs- acc0 = computeAcc (Embed env0 cc0)-- -- The second part of let-elimination. Splitting into two steps exposes the- -- extra type variables, and ensures we don't do extra work manipulating the- -- body when not necessary (which can lead to a complexity blowup).- --- eliminate :: forall aenv aenv' sh e brrs. (Shape sh, Elt e, Arrays brrs)- => Extend acc aenv aenv'- -> Cunctation acc aenv' (Array sh e)- -> acc (aenv', Array sh e) brrs- -> Embed acc aenv brrs- eliminate env1 cc1 body- | Done v1 <- cc1 = elim (arrayShape v1) (indexArray v1)- | Step sh1 p1 f1 v1 <- cc1 = elim sh1 (f1 `compose` indexArray v1 `compose` p1)- | Yield sh1 f1 <- cc1 = elim sh1 f1- where- bnd :: PreOpenAcc acc aenv' (Array sh e)- bnd = compute' cc1-- elim :: PreExp acc aenv' sh -> PreFun acc aenv' (sh -> e) -> Embed acc aenv brrs- elim sh1 f1- | sh1' <- weaken SuccIdx sh1- , f1' <- weaken SuccIdx f1- , Embed env0' cc0' <- embedAcc $ rebuildA (subAtop bnd) $ kmap (replaceA sh1' f1' ZeroIdx) body- = Embed (env1 `append` env0') cc0'-- -- As part of let-elimination, we need to replace uses of array variables in- -- scalar expressions with an equivalent expression that generates the- -- result directly- --- -- TODO: when we inline bindings we ought to let bind at the first- -- occurrence and use a variable at all subsequent locations. At the- -- moment we are just hoping CSE in the simplifier phase does good- -- things, but that is limited in what it looks for.- --- replaceE :: forall env aenv sh e t. (Shape sh, Elt e)- => PreOpenExp acc env aenv sh -> PreOpenFun acc env aenv (sh -> e) -> Idx aenv (Array sh e)- -> PreOpenExp acc env aenv t- -> PreOpenExp acc env aenv t- replaceE sh' f' avar exp =- case exp of- Let x y -> Let (cvtE x) (replaceE (weakenE SuccIdx sh') (weakenE SuccIdx f') avar y)- Var i -> Var i- Foreign ff f e -> Foreign ff f (cvtE e)- Const c -> Const c- Tuple t -> Tuple (cvtT t)- Prj ix e -> Prj ix (cvtE e)- IndexNil -> IndexNil- IndexCons sl sz -> IndexCons (cvtE sl) (cvtE sz)- IndexHead sh -> IndexHead (cvtE sh)- IndexTail sz -> IndexTail (cvtE sz)- IndexAny -> IndexAny- IndexSlice x ix sh -> IndexSlice x (cvtE ix) (cvtE sh)- IndexFull x ix sl -> IndexFull x (cvtE ix) (cvtE sl)- ToIndex sh ix -> ToIndex (cvtE sh) (cvtE ix)- FromIndex sh i -> FromIndex (cvtE sh) (cvtE i)- Cond p t e -> Cond (cvtE p) (cvtE t) (cvtE e)- PrimConst c -> PrimConst c- PrimApp g x -> PrimApp g (cvtE x)- ShapeSize sh -> ShapeSize (cvtE sh)- Intersect sh sl -> Intersect (cvtE sh) (cvtE sl)- Union s t -> Union (cvtE s) (cvtE t)- While p f x -> While (replaceF sh' f' avar p) (replaceF sh' f' avar f) (cvtE x)-- Shape a- | Just Refl <- match a a' -> Stats.substitution "replaceE/shape" sh'- | otherwise -> exp-- Index a sh- | Just Refl <- match a a'- , Lam (Body b) <- f' -> Stats.substitution "replaceE/!" . cvtE $ Let sh b- | otherwise -> Index a (cvtE sh)-- LinearIndex a i- | Just Refl <- match a a'- , Lam (Body b) <- f' -> Stats.substitution "replaceE/!!" . cvtE $ Let (Let i (FromIndex (weakenE SuccIdx sh') (Var ZeroIdx))) b- | otherwise -> LinearIndex a (cvtE i)-- where- a' :: acc aenv (Array sh e)- a' = avarIn avar-- cvtE :: PreOpenExp acc env aenv s -> PreOpenExp acc env aenv s- cvtE = replaceE sh' f' avar-- cvtT :: Tuple (PreOpenExp acc env aenv) s -> Tuple (PreOpenExp acc env aenv) s- cvtT NilTup = NilTup- cvtT (SnocTup t e) = cvtT t `SnocTup` cvtE e-- replaceF :: forall env aenv sh e t. (Shape sh, Elt e)- => PreOpenExp acc env aenv sh -> PreOpenFun acc env aenv (sh -> e) -> Idx aenv (Array sh e)- -> PreOpenFun acc env aenv t- -> PreOpenFun acc env aenv t- replaceF sh' f' avar fun =- case fun of- Body e -> Body (replaceE sh' f' avar e)- Lam f -> Lam (replaceF (weakenE SuccIdx sh') (weakenE SuccIdx f') avar f)-- replaceA :: forall aenv sh e a. (Shape sh, Elt e)- => PreExp acc aenv sh -> PreFun acc aenv (sh -> e) -> Idx aenv (Array sh e)- -> PreOpenAcc acc aenv a- -> PreOpenAcc acc aenv a- replaceA sh' f' avar pacc =- case pacc of- Avar v- | Just Refl <- match v avar -> Avar avar- | otherwise -> Avar v-- Alet bnd body ->- let sh'' = weaken SuccIdx sh'- f'' = weaken SuccIdx f'- in- Alet (cvtA bnd) (kmap (replaceA sh'' f'' (SuccIdx avar)) body)-- Use arrs -> Use arrs- Unit e -> Unit (cvtE e)- Acond p at ae -> Acond (cvtE p) (cvtA at) (cvtA ae)- Aprj ix tup -> Aprj ix (cvtA tup)- Atuple tup -> Atuple (cvtAT tup)- Awhile p f a -> Awhile (cvtAF p) (cvtAF f) (cvtA a)- Apply f a -> Apply (cvtAF f) (cvtA a)- Aforeign ff f a -> Aforeign ff f (cvtA a) -- no sharing between f and a- Generate sh f -> Generate (cvtE sh) (cvtF f)- Map f a -> Map (cvtF f) (cvtA a)- ZipWith f a b -> ZipWith (cvtF f) (cvtA a) (cvtA b)- Backpermute sh p a -> Backpermute (cvtE sh) (cvtF p) (cvtA a)- Transform sh p f a -> Transform (cvtE sh) (cvtF p) (cvtF f) (cvtA a)- Slice slix a sl -> Slice slix (cvtA a) (cvtE sl)- Replicate slix sh a -> Replicate slix (cvtE sh) (cvtA a)- Reshape sl a -> Reshape (cvtE sl) (cvtA a)- Fold f z a -> Fold (cvtF f) (cvtE z) (cvtA a)- Fold1 f a -> Fold1 (cvtF f) (cvtA a)- FoldSeg f z a s -> FoldSeg (cvtF f) (cvtE z) (cvtA a) (cvtA s)- Fold1Seg f a s -> Fold1Seg (cvtF f) (cvtA a) (cvtA s)- Scanl f z a -> Scanl (cvtF f) (cvtE z) (cvtA a)- Scanl1 f a -> Scanl1 (cvtF f) (cvtA a)- Scanl' f z a -> Scanl' (cvtF f) (cvtE z) (cvtA a)- Scanr f z a -> Scanr (cvtF f) (cvtE z) (cvtA a)- Scanr1 f a -> Scanr1 (cvtF f) (cvtA a)- Scanr' f z a -> Scanr' (cvtF f) (cvtE z) (cvtA a)- Permute f d p a -> Permute (cvtF f) (cvtA d) (cvtF p) (cvtA a)- Stencil f x a -> Stencil (cvtF f) (cvtB x) (cvtA a)- Stencil2 f x a y b -> Stencil2 (cvtF f) (cvtB x) (cvtA a) (cvtB y) (cvtA b)- -- Collect seq -> Collect (cvtSeq seq)-- where- cvtA :: acc aenv s -> acc aenv s- cvtA = kmap (replaceA sh' f' avar)-- cvtE :: PreExp acc aenv s -> PreExp acc aenv s- cvtE = replaceE sh' f' avar-- cvtF :: PreFun acc aenv s -> PreFun acc aenv s- cvtF = replaceF sh' f' avar-- cvtB :: PreBoundary acc aenv s -> PreBoundary acc aenv s- cvtB Clamp = Clamp- cvtB Mirror = Mirror- cvtB Wrap = Wrap- cvtB (Constant c) = Constant c- cvtB (Function f) = Function (cvtF f)-- cvtAT :: Atuple (acc aenv) s -> Atuple (acc aenv) s- cvtAT NilAtup = NilAtup- cvtAT (SnocAtup tup a) = cvtAT tup `SnocAtup` cvtA a-- cvtAF :: PreOpenAfun acc aenv s -> PreOpenAfun acc aenv s- cvtAF = cvt sh' f' avar- where- cvt :: forall aenv a.- PreExp acc aenv sh -> PreFun acc aenv (sh -> e) -> Idx aenv (Array sh e)- -> PreOpenAfun acc aenv a- -> PreOpenAfun acc aenv a- cvt sh'' f'' avar' (Abody a) = Abody $ kmap (replaceA sh'' f'' avar') a- cvt sh'' f'' avar' (Alam af) = Alam $ cvt (weaken SuccIdx sh'')- (weaken SuccIdx f'')- (SuccIdx avar')- af--{--- cvtSeq :: PreOpenSeq acc aenv senv s -> PreOpenSeq acc aenv senv s- cvtSeq s =- case s of- Producer p s' ->- Producer- (case p of- StreamIn arrs -> StreamIn arrs- ToSeq slix sh a -> ToSeq slix sh (cvtA a)- MapSeq f x -> MapSeq (cvtAF f) x- ChunkedMapSeq f x -> ChunkedMapSeq (cvtAF f) x- ZipWithSeq f x y -> ZipWithSeq (cvtAF f) x y- ScanSeq f e x -> ScanSeq (cvtF f) (cvtE e) x)- (cvtSeq s')- Consumer c ->- Consumer (cvtC c)- Reify ix -> Reify ix-- cvtC :: Consumer acc aenv senv s -> Consumer acc aenv senv s- cvtC c =- case c of- FoldSeq f e x -> FoldSeq (cvtF f) (cvtE e) x- FoldSeqFlatten f a x -> FoldSeqFlatten (cvtAF f) (cvtA a) x- Stuple t -> Stuple (cvtCT t)-- cvtCT :: Atuple (Consumer acc aenv senv) t -> Atuple (Consumer acc aenv senv) t- cvtCT NilAtup = NilAtup- cvtCT (SnocAtup t c) = cvtCT t `SnocAtup` cvtC c---}----- The apply operator, or (>->) in the surface language. This eliminates--- redundant application to an identity function, instead lifting the argument--- to a let-binding. This case arises in the use of pipe to avoid fusion and--- force its argument to be evaluated, e.g.:------ > compute :: Acc a -> Acc a--- > compute = id >-> id----applyD :: (Kit acc, Arrays as, Arrays bs)- => PreOpenAfun acc aenv (as -> bs)- -> acc aenv as- -> Embed acc aenv bs-applyD afun x- | Alam (Abody body) <- afun- , Avar ZeroIdx <- extract body- = Stats.ruleFired "applyD/identity"- $ done $ extract x-- | otherwise- = done $ Apply afun x----- Array conditionals, in particular eliminate branches when the predicate--- reduces to a known constant.------ Note that we take the raw unprocessed terms as input. If instead we had the--- terms for each branch in the delayed representation, this would require that--- each term has been sunk into a common environment, which implies the--- conditional has been pushed underneath the intersection of bound terms for--- both branches. This would result in redundant work processing the bindings--- for the branch not taken.----acondD :: (Kit acc, Arrays arrs)- => EmbedAcc acc- -> PreExp acc aenv Bool- -> acc aenv arrs- -> acc aenv arrs- -> Embed acc aenv arrs-acondD embedAcc p t e- | Const True <- p = Stats.knownBranch "True" $ embedAcc t- | Const False <- p = Stats.knownBranch "False" $ embedAcc e- | Just Refl <- match t e = Stats.knownBranch "redundant" $ embedAcc e- | otherwise = done $ Acond p (computeAcc (embedAcc t))- (computeAcc (embedAcc e))----- Array tuple projection. Whenever possible we want to peek underneath the--- tuple structure and continue the fusion process.----aprjD :: forall acc aenv arrs a. (Kit acc, IsAtuple arrs, Arrays arrs, Arrays a)- => EmbedAcc acc- -> TupleIdx (TupleRepr arrs) a- -> acc aenv arrs- -> Embed acc aenv a-aprjD embedAcc ix a- | Atuple tup <- extract a = Stats.ruleFired "aprj/Atuple" . embedAcc $ aprjAT ix tup- | otherwise = done $ Aprj ix (cvtA a)- where- cvtA :: acc aenv arrs -> acc aenv arrs- cvtA = computeAcc . embedAcc-- aprjAT :: TupleIdx atup a -> Atuple (acc aenv) atup -> acc aenv a- aprjAT ZeroTupIdx (SnocAtup _ a) = a- aprjAT (SuccTupIdx ix) (SnocAtup t _) = aprjAT ix t----- Scalar expressions--- --------------------isIdentity :: PreFun acc aenv (a -> b) -> Maybe (a :~: b)-isIdentity f- | Lam (Body (Var ZeroIdx)) <- f = Just Refl- | otherwise = Nothing--identity :: Elt a => PreOpenFun acc env aenv (a -> a)-identity = Lam (Body (Var ZeroIdx))--toIndex :: (Kit acc, Shape sh) => PreOpenExp acc env aenv sh -> PreOpenFun acc env aenv (sh -> Int)-toIndex sh = Lam (Body (ToIndex (weakenE SuccIdx sh) (Var ZeroIdx)))--fromIndex :: (Kit acc, Shape sh) => PreOpenExp acc env aenv sh -> PreOpenFun acc env aenv (Int -> sh)-fromIndex sh = Lam (Body (FromIndex (weakenE SuccIdx sh) (Var ZeroIdx)))--reindex :: (Kit acc, Shape sh, Shape sh')- => PreOpenExp acc env aenv sh'- -> PreOpenExp acc env aenv sh- -> PreOpenFun acc env aenv (sh -> sh')-reindex sh' sh- | Just Refl <- match sh sh' = identity- | otherwise = fromIndex sh' `compose` toIndex sh--extend :: (Kit acc, Shape sh, Shape sl, Elt slix)- => SliceIndex (EltRepr slix) (EltRepr sl) co (EltRepr sh)- -> PreExp acc aenv slix- -> PreFun acc aenv (sh -> sl)-extend sliceIndex slix = Lam (Body (IndexSlice sliceIndex (weakenE SuccIdx slix) (Var ZeroIdx)))--restrict :: (Kit acc, Shape sh, Shape sl, Elt slix)- => SliceIndex (EltRepr slix) (EltRepr sl) co (EltRepr sh)- -> PreExp acc aenv slix- -> PreFun acc aenv (sl -> sh)-restrict sliceIndex slix = Lam (Body (IndexFull sliceIndex (weakenE SuccIdx slix) (Var ZeroIdx)))--arrayShape :: (Kit acc, Shape sh, Elt e) => Idx aenv (Array sh e) -> PreExp acc aenv sh-arrayShape = Shape . avarIn--indexArray :: (Kit acc, Shape sh, Elt e) => Idx aenv (Array sh e) -> PreFun acc aenv (sh -> e)-indexArray v = Lam (Body (Index (avarIn v) (Var ZeroIdx)))--linearIndex :: (Kit acc, Shape sh, Elt e) => Idx aenv (Array sh e) -> PreFun acc aenv (Int -> e)-linearIndex v = Lam (Body (LinearIndex (avarIn v) (Var ZeroIdx)))-
− Data/Array/Accelerate/Trafo/Rewrite.hs
@@ -1,152 +0,0 @@-{-# LANGUAGE GADTs #-}-{-# LANGUAGE ScopedTypeVariables #-}--- |--- Module : Data.Array.Accelerate.Trafo.Rewrite--- Copyright : [2012..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Trafo.Rewrite- where--import Prelude hiding ( seq )---- friends-import Data.Array.Accelerate.AST-import Data.Array.Accelerate.Type-import Data.Array.Accelerate.Trafo.Substitution-import Data.Array.Accelerate.Array.Sugar ( Arrays, Segments, Elt, fromElt, Tuple(..), Atuple(..) )----- Convert segment length arrays passed to segmented operations into offset--- index style. This is achieved by wrapping the segmented array argument in a--- left prefix-sum, so you must only ever apply this once.----convertSegments :: OpenAcc aenv a -> OpenAcc aenv a-convertSegments = cvtA- where- cvtT :: Atuple (OpenAcc aenv) t -> Atuple (OpenAcc aenv) t- cvtT atup = case atup of- NilAtup -> NilAtup- SnocAtup t a -> cvtT t `SnocAtup` cvtA a-- cvtAfun :: OpenAfun aenv t -> OpenAfun aenv t- cvtAfun = convertSegmentsAfun-- cvtE :: Exp aenv t -> Exp aenv t- cvtE = id-- cvtF :: Fun aenv t -> Fun aenv t- cvtF = id-- a0 :: Arrays a => OpenAcc (aenv, a) a- a0 = OpenAcc (Avar ZeroIdx)-- segments :: (Elt i, IsIntegral i) => OpenAcc aenv (Segments i) -> OpenAcc aenv (Segments i)- segments s = OpenAcc $ Scanl plus zero (cvtA s)-- zero :: forall aenv i. (Elt i, IsIntegral i) => PreOpenExp OpenAcc () aenv i- zero = Const (fromElt (0::i))-- plus :: (Elt i, IsIntegral i) => PreOpenFun OpenAcc () aenv (i -> i -> i)- plus = Lam (Lam (Body (PrimAdd numType- `PrimApp`- Tuple (NilTup `SnocTup` Var (SuccIdx ZeroIdx)- `SnocTup` Var ZeroIdx))))-- cvtA :: OpenAcc aenv a -> OpenAcc aenv a- cvtA (OpenAcc pacc) = OpenAcc $ case pacc of- Alet bnd body -> Alet (cvtA bnd) (cvtA body)- Avar ix -> Avar ix- Atuple tup -> Atuple (cvtT tup)- Aprj tup a -> Aprj tup (cvtA a)- Apply f a -> Apply (cvtAfun f) (cvtA a)- Aforeign ff afun acc -> Aforeign ff (cvtAfun afun) (cvtA acc)- Acond p t e -> Acond (cvtE p) (cvtA t) (cvtA e)- Awhile p f a -> Awhile (cvtAfun p) (cvtAfun f) (cvtA a)- Use a -> Use a- Unit e -> Unit (cvtE e)- Reshape e a -> Reshape (cvtE e) (cvtA a)- Generate e f -> Generate (cvtE e) (cvtF f)- Transform sh ix f a -> Transform (cvtE sh) (cvtF ix) (cvtF f) (cvtA a)- Replicate sl slix a -> Replicate sl (cvtE slix) (cvtA a)- Slice sl a slix -> Slice sl (cvtA a) (cvtE slix)- Map f a -> Map (cvtF f) (cvtA a)- ZipWith f a1 a2 -> ZipWith (cvtF f) (cvtA a1) (cvtA a2)- Fold f z a -> Fold (cvtF f) (cvtE z) (cvtA a)- Fold1 f a -> Fold1 (cvtF f) (cvtA a)- Scanl f z a -> Scanl (cvtF f) (cvtE z) (cvtA a)- Scanl' f z a -> Scanl' (cvtF f) (cvtE z) (cvtA a)- Scanl1 f a -> Scanl1 (cvtF f) (cvtA a)- Scanr f z a -> Scanr (cvtF f) (cvtE z) (cvtA a)- Scanr' f z a -> Scanr' (cvtF f) (cvtE z) (cvtA a)- Scanr1 f a -> Scanr1 (cvtF f) (cvtA a)- Permute f1 a1 f2 a2 -> Permute (cvtF f1) (cvtA a1) (cvtF f2) (cvtA a2)- Backpermute sh f a -> Backpermute (cvtE sh) (cvtF f) (cvtA a)- Stencil f b a -> Stencil (cvtF f) b (cvtA a)- Stencil2 f b1 a1 b2 a2 -> Stencil2 (cvtF f) b1 (cvtA a1) b2 (cvtA a2)- -- Collect s -> Collect (convertSegmentsSeq s)-- -- Things we are interested in, whoo!- FoldSeg f z a s -> Alet (segments s) (OpenAcc (FoldSeg (cvtF f') (cvtE z') (cvtA a') a0))- where f' = weaken SuccIdx f- z' = weaken SuccIdx z- a' = weaken SuccIdx a-- Fold1Seg f a s -> Alet (segments s) (OpenAcc (Fold1Seg (cvtF f') (cvtA a') a0))- where f' = weaken SuccIdx f- a' = weaken SuccIdx a---convertSegmentsAfun :: OpenAfun aenv t -> OpenAfun aenv t-convertSegmentsAfun afun =- case afun of- Abody b -> Abody (convertSegments b)- Alam f -> Alam (convertSegmentsAfun f)--{---convertSegmentsSeq :: PreOpenSeq OpenAcc aenv senv a -> PreOpenSeq OpenAcc aenv senv a-convertSegmentsSeq seq =- case seq of- Producer p s -> Producer (cvtP p) (convertSegmentsSeq s)- Consumer c -> Consumer (cvtC c)- Reify ix -> Reify ix- where- cvtP :: Producer OpenAcc aenv senv a -> Producer OpenAcc aenv senv a- cvtP p =- case p of- StreamIn arrs -> StreamIn arrs- ToSeq sl slix a -> ToSeq sl slix (cvtA a)- MapSeq f x -> MapSeq (cvtAfun f) x- ChunkedMapSeq f x -> ChunkedMapSeq (cvtAfun f) x- ZipWithSeq f x y -> ZipWithSeq (cvtAfun f) x y- ScanSeq f e x -> ScanSeq (cvtF f) (cvtE e) x-- cvtC :: Consumer OpenAcc aenv senv a -> Consumer OpenAcc aenv senv a- cvtC c =- case c of- FoldSeq f e x -> FoldSeq (cvtF f) (cvtE e) x- FoldSeqFlatten f a x -> FoldSeqFlatten (cvtAfun f) (cvtA a) x- Stuple t -> Stuple (cvtCT t)-- cvtCT :: Atuple (Consumer OpenAcc senv aenv) t -> Atuple (Consumer OpenAcc senv aenv) t- cvtCT NilAtup = NilAtup- cvtCT (SnocAtup t c) = SnocAtup (cvtCT t) (cvtC c)-- cvtE :: Exp aenv t -> Exp aenv t- cvtE = id-- cvtF :: Fun aenv t -> Fun aenv t- cvtF = id-- cvtA :: OpenAcc aenv t -> OpenAcc aenv t- cvtA = convertSegments-- cvtAfun :: OpenAfun aenv t -> OpenAfun aenv t- cvtAfun = convertSegmentsAfun---}-
− Data/Array/Accelerate/Trafo/Sharing.hs
@@ -1,2919 +0,0 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE PatternGuards #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}-{-# OPTIONS_GHC -fno-warn-name-shadowing #-}-{-# OPTIONS_HADDOCK hide #-}--- |--- Module : Data.Array.Accelerate.Trafo.Sharing--- Copyright : [2008..2017] Manuel M T Chakravarty, Gabriele Keller--- [2009..2017] Trevor L. McDonell--- [2013..2017] Robert Clifton-Everest--- License : BSD3------ Maintainer : Manuel M T Chakravarty <chak@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)------ This module implements HOAS to de Bruijn conversion of array expressions--- while incorporating sharing information.-----module Data.Array.Accelerate.Trafo.Sharing (-- -- * HOAS -> de Bruijn conversion- convertAcc, convertAfun, Afunction, AfunctionR,- convertExp, convertFun, Function, FunctionR,- -- convertSeq--) where---- standard library-import Control.Applicative hiding ( Const )-import Control.Monad.Fix-import Data.List-import Data.Maybe-import Data.Hashable-import Data.Typeable-import System.Mem.StableName-import System.IO.Unsafe ( unsafePerformIO )-import qualified Data.HashTable.IO as Hash-import qualified Data.IntMap as IntMap-import qualified Data.HashMap.Strict as Map-import qualified Data.HashSet as Set-import Prelude---- friends-import Data.Array.Accelerate.Error-import Data.Array.Accelerate.Smart-import Data.Array.Accelerate.Array.Sugar as Sugar-import Data.Array.Accelerate.AST hiding ( PreOpenAcc(..), OpenAcc(..), Acc- , PreOpenExp(..), OpenExp, PreExp, Exp- , PreBoundary(..), Boundary, Stencil(..)- , showPreAccOp, showPreExpOp )-import qualified Data.Array.Accelerate.AST as AST-import qualified Data.Array.Accelerate.Debug as Debug----- Configuration--- ----------------- Perhaps the configuration should be passed as a reader monad or some such,--- but that's a little inconvenient.----data Config = Config- {- recoverAccSharing :: Bool -- ^ Recover sharing of array computations ?- , recoverExpSharing :: Bool -- ^ Recover sharing of scalar expressions ?- , recoverSeqSharing :: Bool -- ^ Recover sharing of sequence computations ?- , floatOutAcc :: Bool -- ^ Always float array computations out of expressions ?- }---- Layouts--- ----------- A layout of an environment has an entry for each entry of the environment.--- Each entry in the layout holds the de Bruijn index that refers to the--- corresponding entry in the environment.----data Layout env env' where- EmptyLayout :: Layout env ()- PushLayout :: Typeable t- => Layout env env' -> Idx env t -> Layout env (env', t)---- Project the nth index out of an environment layout.------ The first argument provides context information for error messages in the case of failure.----prjIdx :: forall t env env'. Typeable t => String -> Int -> Layout env env' -> Idx env t-prjIdx ctxt 0 (PushLayout _ (ix :: Idx env0 t0))- = flip fromMaybe (gcast ix)- $ possiblyNestedErr ctxt $- "Couldn't match expected type `" ++ show (typeOf (undefined::t)) ++- "' with actual type `" ++ show (typeOf (undefined::t0)) ++ "'" ++- "\n Type mismatch"-prjIdx ctxt n (PushLayout l _) = prjIdx ctxt (n - 1) l-prjIdx ctxt _ EmptyLayout = possiblyNestedErr ctxt "Environment doesn't contain index"--possiblyNestedErr :: String -> String -> a-possiblyNestedErr ctxt failreason- = error $ "Fatal error in Sharing.prjIdx:"- ++ "\n " ++ failreason ++ " at " ++ ctxt- ++ "\n Possible reason: nested data parallelism — array computation that depends on a"- ++ "\n scalar variable of type 'Exp a'"---- Add an entry to a layout, incrementing all indices----incLayout :: Layout env env' -> Layout (env, t) env'-incLayout EmptyLayout = EmptyLayout-incLayout (PushLayout lyt ix) = PushLayout (incLayout lyt) (SuccIdx ix)--sizeLayout :: Layout env env' -> Int-sizeLayout EmptyLayout = 0-sizeLayout (PushLayout lyt _) = 1 + sizeLayout lyt----- Conversion from HOAS to de Bruijn computation AST--- =================================================---- Array computations--- ---------------------- | Convert a closed array expression to de Bruijn form while also incorporating sharing--- information.----convertAcc- :: Arrays arrs- => Bool -- ^ recover sharing of array computations ?- -> Bool -- ^ recover sharing of scalar expressions ?- -> Bool -- ^ recover sharing of sequence computations ?- -> Bool -- ^ always float array computations out of expressions?- -> Acc arrs- -> AST.Acc arrs-convertAcc shareAcc shareExp shareSeq floatAcc acc- = let config = Config shareAcc shareExp shareSeq (shareAcc && floatAcc)- in- convertOpenAcc config 0 [] EmptyLayout acc----- | Convert a closed function over array computations, while incorporating--- sharing information.----convertAfun :: Afunction f => Bool -> Bool -> Bool -> Bool -> f -> AST.Afun (AfunctionR f)-convertAfun shareAcc shareExp shareSeq floatAcc =- let config = Config shareAcc shareExp shareSeq (shareAcc && floatAcc)- in aconvert config EmptyLayout----- Convert a HOAS fragment into de Bruijn form, binding variables into the typed--- environment layout one binder at a time.------ NOTE: Because we convert one binder at a time left-to-right, the bound--- variables ('vars') will have de Bruijn index _zero_ as the outermost--- binding, and thus go to the end of the list.----class Afunction f where- type AfunctionR f- aconvert :: Config -> Layout aenv aenv -> f -> AST.OpenAfun aenv (AfunctionR f)--instance (Arrays a, Afunction r) => Afunction (Acc a -> r) where- type AfunctionR (Acc a -> r) = a -> AfunctionR r- --- aconvert config alyt f- = let a = Acc $ Atag (sizeLayout alyt)- alyt' = incLayout alyt `PushLayout` ZeroIdx- in- Alam $ aconvert config alyt' (f a)--instance Arrays b => Afunction (Acc b) where- type AfunctionR (Acc b) = b- --- aconvert config alyt body- = let lvl = sizeLayout alyt- vars = [lvl-1, lvl-2 .. 0]- in- Abody $ convertOpenAcc config lvl vars alyt body----- | Convert an open array expression to de Bruijn form while also incorporating sharing--- information.----convertOpenAcc- :: Arrays arrs- => Config- -> Level- -> [Level]- -> Layout aenv aenv- -> Acc arrs- -> AST.OpenAcc aenv arrs-convertOpenAcc config lvl fvs alyt acc- = let (sharingAcc, initialEnv) = recoverSharingAcc config lvl fvs acc- in- convertSharingAcc config alyt initialEnv sharingAcc---- | Convert an array expression with given array environment layout and sharing information into--- de Bruijn form while recovering sharing at the same time (by introducing appropriate let--- bindings). The latter implements the third phase of sharing recovery.------ The sharing environment 'env' keeps track of all currently bound sharing variables, keeping them--- in reverse chronological order (outermost variable is at the end of the list).----convertSharingAcc- :: forall aenv arrs. Arrays arrs- => Config- -> Layout aenv aenv- -> [StableSharingAcc]- -> ScopedAcc arrs- -> AST.OpenAcc aenv arrs-convertSharingAcc _ alyt aenv (ScopedAcc lams (AvarSharing sa))- | Just i <- findIndex (matchStableAcc sa) aenv'- = AST.OpenAcc $ AST.Avar (prjIdx (ctxt ++ "; i = " ++ show i) i alyt)- | null aenv'- = error $ "Cyclic definition of a value of type 'Acc' (sa = " ++- show (hashStableNameHeight sa) ++ ")"- | otherwise- = $internalError "convertSharingAcc" err- where- aenv' = lams ++ aenv- ctxt = "shared 'Acc' tree with stable name " ++ show (hashStableNameHeight sa)- err = "inconsistent valuation @ " ++ ctxt ++ ";\n aenv = " ++ show aenv'--convertSharingAcc config alyt aenv (ScopedAcc lams (AletSharing sa@(StableSharingAcc _ boundAcc) bodyAcc))- = AST.OpenAcc- $ let alyt' = incLayout alyt `PushLayout` ZeroIdx- aenv' = lams ++ aenv- in- AST.Alet (convertSharingAcc config alyt aenv' (ScopedAcc [] boundAcc))- (convertSharingAcc config alyt' (sa:aenv') bodyAcc)--convertSharingAcc config alyt aenv (ScopedAcc lams (AccSharing _ preAcc))- = AST.OpenAcc- $ let aenv' = lams ++ aenv-- cvtA :: Arrays a => ScopedAcc a -> AST.OpenAcc aenv a- cvtA = convertSharingAcc config alyt aenv'-- cvtE :: Elt t => ScopedExp t -> AST.Exp aenv t- cvtE = convertSharingExp config EmptyLayout alyt [] aenv'-- cvtF1 :: (Elt a, Elt b) => (Exp a -> ScopedExp b) -> AST.Fun aenv (a -> b)- cvtF1 = convertSharingFun1 config alyt aenv'-- cvtF2 :: (Elt a, Elt b, Elt c) => (Exp a -> Exp b -> ScopedExp c) -> AST.Fun aenv (a -> b -> c)- cvtF2 = convertSharingFun2 config alyt aenv'-- cvtAfun1 :: (Arrays a, Arrays b) => (Acc a -> ScopedAcc b) -> AST.OpenAfun aenv (a -> b)- cvtAfun1 = convertSharingAfun1 config alyt aenv'- in- case preAcc of-- Atag i- -> AST.Avar (prjIdx ("de Bruijn conversion tag " ++ show i) i alyt)-- Pipe afun1 afun2 acc- -> let noStableSharing = StableSharingAcc noStableAccName (undefined :: SharingAcc acc exp ())- alyt' = incLayout alyt `PushLayout` ZeroIdx- boundAcc = cvtAfun1 afun1 `AST.Apply` cvtA acc- bodyAcc = convertSharingAfun1 config alyt' (noStableSharing : aenv') afun2- `AST.Apply`- AST.OpenAcc (AST.Avar AST.ZeroIdx)- in- AST.Alet (AST.OpenAcc boundAcc) (AST.OpenAcc bodyAcc)-- Aforeign ff afun acc- -> let a = recoverAccSharing config- e = recoverExpSharing config- s = recoverSeqSharing config- f = floatOutAcc config- in- AST.Aforeign ff (convertAfun a e s f afun) (cvtA acc)-- Acond b acc1 acc2 -> AST.Acond (cvtE b) (cvtA acc1) (cvtA acc2)- Awhile pred iter init -> AST.Awhile (cvtAfun1 pred) (cvtAfun1 iter) (cvtA init)- Atuple arrs -> AST.Atuple (convertSharingAtuple config alyt aenv' arrs)- Aprj ix a -> AST.Aprj ix (cvtA a)- Use array -> AST.Use (fromArr array)- Unit e -> AST.Unit (cvtE e)- Generate sh f -> AST.Generate (cvtE sh) (cvtF1 f)- Reshape e acc -> AST.Reshape (cvtE e) (cvtA acc)- Replicate ix acc -> mkReplicate (cvtE ix) (cvtA acc)- Slice acc ix -> mkIndex (cvtA acc) (cvtE ix)- Map f acc -> AST.Map (cvtF1 f) (cvtA acc)- ZipWith f acc1 acc2 -> AST.ZipWith (cvtF2 f) (cvtA acc1) (cvtA acc2)- Fold f e acc -> AST.Fold (cvtF2 f) (cvtE e) (cvtA acc)- Fold1 f acc -> AST.Fold1 (cvtF2 f) (cvtA acc)- FoldSeg f e acc1 acc2 -> AST.FoldSeg (cvtF2 f) (cvtE e) (cvtA acc1) (cvtA acc2)- Fold1Seg f acc1 acc2 -> AST.Fold1Seg (cvtF2 f) (cvtA acc1) (cvtA acc2)- Scanl f e acc -> AST.Scanl (cvtF2 f) (cvtE e) (cvtA acc)- Scanl' f e acc -> AST.Scanl' (cvtF2 f) (cvtE e) (cvtA acc)- Scanl1 f acc -> AST.Scanl1 (cvtF2 f) (cvtA acc)- Scanr f e acc -> AST.Scanr (cvtF2 f) (cvtE e) (cvtA acc)- Scanr' f e acc -> AST.Scanr' (cvtF2 f) (cvtE e) (cvtA acc)- Scanr1 f acc -> AST.Scanr1 (cvtF2 f) (cvtA acc)- Permute f dftAcc perm acc -> AST.Permute (cvtF2 f) (cvtA dftAcc) (cvtF1 perm) (cvtA acc)- Backpermute newDim perm acc -> AST.Backpermute (cvtE newDim) (cvtF1 perm) (cvtA acc)- Stencil stencil boundary acc- -> AST.Stencil (convertSharingStencilFun1 config acc alyt aenv' stencil)- (convertSharingBoundary config alyt aenv' boundary)- (cvtA acc)- Stencil2 stencil bndy1 acc1 bndy2 acc2- -> AST.Stencil2 (convertSharingStencilFun2 config acc1 acc2 alyt aenv' stencil)- (convertSharingBoundary config alyt aenv' bndy1)- (cvtA acc1)- (convertSharingBoundary config alyt aenv' bndy2)- (cvtA acc2)- -- Collect seq -> AST.Collect (convertSharingSeq config alyt EmptyLayout aenv' [] seq)---{----- Sequence expressions--- ---------------------- | Convert a closed sequence expression to de Bruijn form while incorporating--- sharing information.----convertSeq- :: Typeable s- => Bool -- ^ recover sharing of array computations ?- -> Bool -- ^ recover sharing of scalar expressions ?- -> Bool -- ^ recover sharing of sequence computations ?- -> Bool -- ^ always float array computations out of expressions?- -> Seq s -- ^ computation to be converted- -> AST.Seq s-convertSeq shareAcc shareExp shareSeq floatAcc seq- = let config = Config shareAcc shareExp shareSeq floatAcc- (sharingSeq, initialEnv) = recoverSharingSeq config seq- in- convertSharingSeq config EmptyLayout EmptyLayout [] initialEnv sharingSeq--convertSharingSeq- :: forall aenv senv arrs.- Config- -> Layout aenv aenv- -> Layout senv senv- -> [StableSharingAcc]- -> [StableSharingSeq]- -> ScopedSeq arrs- -> AST.PreOpenSeq AST.OpenAcc aenv senv arrs-convertSharingSeq _ _ slyt _ senv (ScopedSeq (SvarSharing sn))- | Just i <- findIndex (matchStableSeq sn) senv- = AST.Reify $ prjIdx (ctxt ++ "; i = " ++ show i) i slyt- | null senv- = error $ "Cyclic definition of a value of type 'Seq' (sa = " ++- show (hashStableNameHeight sn) ++ ")"- | otherwise- = $internalError "convertSharingSeq" err- where- ctxt = "shared 'Seq' tree with stable name " ++ show (hashStableNameHeight sn)- err = "inconsistent valuation @ " ++ ctxt ++ ";\n senv = " ++ show senv-convertSharingSeq config alyt slyt aenv senv (ScopedSeq (SletSharing sa@(StableSharingSeq _ (SeqSharing _ boundSeq)) bodySeq))- = convSeq boundSeq bodySeq- where- convSeq :: forall bnd body.- PreSeq ScopedAcc ScopedSeq ScopedExp bnd- -> ScopedSeq body- -> AST.PreOpenSeq AST.OpenAcc aenv senv body- convSeq bnd body =- case bnd of- StreamIn arrs -> producer $ AST.StreamIn arrs- ToSeq slix acc -> producer $ mkToSeq slix (cvtA acc)- MapSeq afun x -> producer $ AST.MapSeq (cvtAF1 afun) (asIdx x)- ZipWithSeq afun x y -> producer $ AST.ZipWithSeq (cvtAF2 afun) (asIdx x) (asIdx y)- ScanSeq fun e x -> producer $ AST.ScanSeq (cvtF2 fun) (cvtE e) (asIdx x)- _ -> $internalError "convertSharingSeq:convSeq" "Consumer appears to have been let bound"- where- producer :: Arrays a- => AST.Producer AST.OpenAcc aenv senv a- -> AST.PreOpenSeq AST.OpenAcc aenv senv body- producer p = AST.Producer p $ convertSharingSeq config alyt slyt' aenv (sa:senv) body- where- slyt' = incLayout slyt `PushLayout` ZeroIdx-- asIdx :: Arrays a- => ScopedSeq [a]- -> Idx senv a- asIdx (ScopedSeq (SvarSharing sn))- | Just i <- findIndex (matchStableSeq sn) senv- = prjIdx (ctxt ++ "; i = " ++ show i) i slyt- | null senv- = error $ "Cyclic definition of a value of type 'Seq' (sa = " ++- show (hashStableNameHeight sn) ++ ")"- | otherwise- = $internalError "convertSharingSeq" err- where- ctxt = "shared 'Seq' tree with stable name " ++ show (hashStableNameHeight sn)- err = "inconsistent valuation @ " ++ ctxt ++ ";\n senv = " ++ show senv- asIdx _- = $internalError "convertSharingSeq:asIdx" "Sequence computation not in A-normal form"-- cvtA :: forall a. Arrays a => ScopedAcc a -> AST.OpenAcc aenv a- cvtA acc = convertSharingAcc config alyt aenv acc-- cvtE :: forall t. Elt t => ScopedExp t -> AST.Exp aenv t- cvtE = convertSharingExp config EmptyLayout alyt [] aenv-- cvtF2 :: (Elt a, Elt b, Elt c) => (Exp a -> Exp b -> ScopedExp c) -> AST.Fun aenv (a -> b -> c)- cvtF2 = convertSharingFun2 config alyt aenv-- cvtAF1 :: forall a b. (Arrays a, Arrays b) => (Acc a -> ScopedAcc b) -> OpenAfun aenv (a -> b)- cvtAF1 afun = convertSharingAfun1 config alyt aenv afun-- cvtAF2 :: forall a b c. (Arrays a, Arrays b, Arrays c) => (Acc a -> Acc b -> ScopedAcc c) -> OpenAfun aenv (a -> b -> c)- cvtAF2 afun = convertSharingAfun2 config alyt aenv afun--convertSharingSeq _ _ _ _ _ (ScopedSeq (SletSharing _ _))- = $internalError "convertSharingSeq" "Sequence computation not in A-normal form"--convertSharingSeq config alyt slyt aenv senv s- = cvtC s- where- cvtC :: ScopedSeq a -> AST.PreOpenSeq AST.OpenAcc aenv senv a- cvtC (ScopedSeq (SeqSharing _ s)) =- case s of- FoldSeq fun e x -> AST.Consumer $ AST.FoldSeq (cvtF2 fun) (cvtE e) (asIdx x)- FoldSeqFlatten afun acc x -> AST.Consumer $ AST.FoldSeqFlatten (cvtAF3 afun) (cvtA acc) (asIdx x)- Stuple t -> AST.Consumer $ AST.Stuple (cvtST t)- _ -> $internalError "convertSharingSeq" "Producer has not been let bound"- cvtC _ = $internalError "convertSharingSeq" "Unreachable"-- asIdx :: Arrays a- => ScopedSeq [a]- -> Idx senv a- asIdx (ScopedSeq (SvarSharing sn))- | Just i <- findIndex (matchStableSeq sn) senv- = prjIdx (ctxt ++ "; i = " ++ show i) i slyt- | null senv- = error $ "Cyclic definition of a value of type 'Seq' (sa = " ++- show (hashStableNameHeight sn) ++ ")"- | otherwise- = $internalError "convertSharingSeq" err- where- ctxt = "shared 'Seq' tree with stable name " ++ show (hashStableNameHeight sn)- err = "inconsistent valuation @ " ++ ctxt ++ ";\n senv = " ++ show senv- asIdx _- = $internalError "convertSharingSeq:asIdx" "Sequence computation not in A-normal form"-- cvtA :: forall a. Arrays a => ScopedAcc a -> AST.OpenAcc aenv a- cvtA acc = convertSharingAcc config alyt aenv acc-- cvtE :: forall t. Elt t => ScopedExp t -> AST.Exp aenv t- cvtE = convertSharingExp config EmptyLayout alyt [] aenv-- cvtF2 :: (Elt a, Elt b, Elt c) => (Exp a -> Exp b -> ScopedExp c) -> AST.Fun aenv (a -> b -> c)- cvtF2 = convertSharingFun2 config alyt aenv-- cvtAF3 :: forall a b c d. (Arrays a, Arrays b, Arrays c, Arrays d) => (Acc a -> Acc b -> Acc c -> ScopedAcc d) -> OpenAfun aenv (a -> b -> c -> d)- cvtAF3 afun = convertSharingAfun3 config alyt aenv afun-- cvtST :: Atuple ScopedSeq t -> Atuple (AST.Consumer AST.OpenAcc aenv senv) t- cvtST NilAtup = NilAtup- cvtST (SnocAtup t c) | AST.Consumer c' <- cvtC c- = SnocAtup (cvtST t) c'- | otherwise- = $internalError "convertSharingSeq" "Unreachable"---}--convertSharingAfun1- :: forall aenv a b. (Arrays a, Arrays b)- => Config- -> Layout aenv aenv- -> [StableSharingAcc]- -> (Acc a -> ScopedAcc b)- -> OpenAfun aenv (a -> b)-convertSharingAfun1 config alyt aenv f- = Alam (Abody (convertSharingAcc config alyt' aenv body))- where- alyt' = incLayout alyt `PushLayout` ZeroIdx- body = f undefined--{---convertSharingAfun2- :: forall aenv a b c. (Arrays a, Arrays b, Arrays c)- => Config- -> Layout aenv aenv- -> [StableSharingAcc]- -> (Acc a -> Acc b -> ScopedAcc c)- -> OpenAfun aenv (a -> b -> c)-convertSharingAfun2 config alyt aenv f- = Alam (Alam (Abody (convertSharingAcc config alyt' aenv body)))- where- alyt' = incLayout (incLayout alyt `PushLayout` ZeroIdx) `PushLayout` ZeroIdx- body = f undefined undefined--convertSharingAfun3- :: forall aenv a b c d. (Arrays a, Arrays b, Arrays c, Arrays d)- => Config- -> Layout aenv aenv- -> [StableSharingAcc]- -> (Acc a -> Acc b -> Acc c -> ScopedAcc d)- -> OpenAfun aenv (a -> b -> c -> d)-convertSharingAfun3 config alyt aenv f- = Alam (Alam (Alam (Abody (convertSharingAcc config alyt' aenv body))))- where- alyt' = incLayout (incLayout (incLayout alyt `PushLayout` ZeroIdx) `PushLayout` ZeroIdx) `PushLayout` ZeroIdx- body = f undefined undefined undefined---}--convertSharingAtuple- :: forall aenv a.- Config- -> Layout aenv aenv- -> [StableSharingAcc]- -> Atuple ScopedAcc a- -> Atuple (AST.OpenAcc aenv) a-convertSharingAtuple config alyt aenv = cvt- where- cvt :: Atuple ScopedAcc a' -> Atuple (AST.OpenAcc aenv) a'- cvt NilAtup = NilAtup- cvt (SnocAtup t a) = cvt t `SnocAtup` convertSharingAcc config alyt aenv a----- | Convert a boundary condition----convertSharingBoundary- :: forall aenv t.- Config- -> Layout aenv aenv- -> [StableSharingAcc]- -> PreBoundary ScopedAcc ScopedExp t- -> AST.PreBoundary AST.OpenAcc aenv t-convertSharingBoundary config alyt aenv = cvt- where- cvt :: PreBoundary ScopedAcc ScopedExp t -> AST.Boundary aenv t- cvt bndy =- case bndy of- Clamp -> AST.Clamp- Mirror -> AST.Mirror- Wrap -> AST.Wrap- Constant v -> AST.Constant $ fromElt v- Function f -> AST.Function $ convertSharingFun1 config alyt aenv f----- Smart constructors to represent AST forms----mkIndex :: forall slix e aenv. (Slice slix, Elt e)- => AST.OpenAcc aenv (Array (FullShape slix) e)- -> AST.Exp aenv slix- -> AST.PreOpenAcc AST.OpenAcc aenv (Array (SliceShape slix) e)-mkIndex = AST.Slice (sliceIndex slix)- where- slix = undefined :: slix--mkReplicate :: forall slix e aenv. (Slice slix, Elt e)- => AST.Exp aenv slix- -> AST.OpenAcc aenv (Array (SliceShape slix) e)- -> AST.PreOpenAcc AST.OpenAcc aenv (Array (FullShape slix) e)-mkReplicate = AST.Replicate (sliceIndex slix)- where- slix = undefined :: slix---- mkToSeq :: forall slsix slix e aenv senv. (Division slsix, DivisionSlice slsix ~ slix, Elt e, Elt slix, Slice slix)--- => slsix--- -> AST.OpenAcc aenv (Array (FullShape slix) e)--- -> AST.Producer AST.OpenAcc aenv senv (Array (SliceShape slix) e)--- mkToSeq _ = AST.ToSeq (sliceIndex slix) (Proxy :: Proxy slix)--- where--- slix = undefined :: slix----- Scalar functions--- -------------------- | Convert a closed scalar function to de Bruijn form while incorporating--- sharing information.------ The current design requires all free variables to be bound at the outermost--- level --- we have no general apply term, and so lambdas are always outermost.--- In higher-order abstract syntax, this represents an n-ary, polyvariadic--- function.----convertFun :: Function f => Bool -> f -> AST.Fun () (FunctionR f)-convertFun shareExp =- let config = Config False shareExp False False- in convert config EmptyLayout---class Function f where- type FunctionR f- convert :: Config -> Layout env env -> f -> AST.OpenFun env () (FunctionR f)--instance (Elt a, Function r) => Function (Exp a -> r) where- type FunctionR (Exp a -> r) = a -> FunctionR r- --- convert config lyt f- = let x = Exp $ Tag (sizeLayout lyt)- lyt' = incLayout lyt `PushLayout` ZeroIdx- in- Lam $ convert config lyt' (f x)--instance Elt b => Function (Exp b) where- type FunctionR (Exp b) = b- --- convert config lyt body- = let lvl = sizeLayout lyt- vars = [lvl-1, lvl-2 .. 0]- in- Body $ convertOpenExp config lvl vars lyt body----- Scalar expressions--- ---------------------- | Convert a closed scalar expression to de Bruijn form while incorporating--- sharing information.----convertExp- :: Elt e- => Bool -- ^ recover sharing of scalar expressions ?- -> Exp e -- ^ expression to be converted- -> AST.Exp () e-convertExp shareExp exp- = let config = Config False shareExp False False- in- convertOpenExp config 0 [] EmptyLayout exp--convertOpenExp- :: Elt e- => Config- -> Level -- level of currently bound scalar variables- -> [Level] -- tags of bound scalar variables- -> Layout env env- -> Exp e- -> AST.OpenExp env () e-convertOpenExp config lvl fvar lyt exp- = let (sharingExp, initialEnv) = recoverSharingExp config lvl fvar exp- in- convertSharingExp config lyt EmptyLayout initialEnv [] sharingExp----- | Convert an open expression with given environment layouts and sharing information into--- de Bruijn form while recovering sharing at the same time (by introducing appropriate let--- bindings). The latter implements the third phase of sharing recovery.------ The sharing environments 'env' and 'aenv' keep track of all currently bound sharing variables,--- keeping them in reverse chronological order (outermost variable is at the end of the list).----convertSharingExp- :: forall t env aenv. Elt t- => Config- -> Layout env env -- scalar environment- -> Layout aenv aenv -- array environment- -> [StableSharingExp] -- currently bound sharing variables of expressions- -> [StableSharingAcc] -- currently bound sharing variables of array computations- -> ScopedExp t -- expression to be converted- -> AST.OpenExp env aenv t-convertSharingExp config lyt alyt env aenv exp@(ScopedExp lams _) = cvt exp- where- -- scalar environment with any lambda bound variables this expression is rooted in- env' = lams ++ env-- cvt :: Elt t' => ScopedExp t' -> AST.OpenExp env aenv t'- cvt (ScopedExp _ (VarSharing se))- | Just i <- findIndex (matchStableExp se) env'- = AST.Var (prjIdx (ctxt ++ "; i = " ++ show i) i lyt)- | null env'- = error $ "Cyclic definition of a value of type 'Exp' (sa = " ++ show (hashStableNameHeight se) ++ ")"- | otherwise- = $internalError "convertSharingExp" err- where- ctxt = "shared 'Exp' tree with stable name " ++ show (hashStableNameHeight se)- err = "inconsistent valuation @ " ++ ctxt ++ ";\n env' = " ++ show env'- cvt (ScopedExp _ (LetSharing se@(StableSharingExp _ boundExp) bodyExp))- = let lyt' = incLayout lyt `PushLayout` ZeroIdx- in- AST.Let (cvt (ScopedExp [] boundExp)) (convertSharingExp config lyt' alyt (se:env') aenv bodyExp)- cvt (ScopedExp _ (ExpSharing _ pexp))- = case pexp of- Tag i -> AST.Var (prjIdx ("de Bruijn conversion tag " ++ show i) i lyt)- Const v -> AST.Const (fromElt v)- Tuple tup -> AST.Tuple (cvtT tup)- Prj idx e -> AST.Prj idx (cvt e)- IndexNil -> AST.IndexNil- IndexCons ix i -> AST.IndexCons (cvt ix) (cvt i)- IndexHead i -> AST.IndexHead (cvt i)- IndexTail ix -> AST.IndexTail (cvt ix)- IndexAny -> AST.IndexAny- ToIndex sh ix -> AST.ToIndex (cvt sh) (cvt ix)- FromIndex sh e -> AST.FromIndex (cvt sh) (cvt e)- Cond e1 e2 e3 -> AST.Cond (cvt e1) (cvt e2) (cvt e3)- While p it i -> AST.While (cvtFun1 p) (cvtFun1 it) (cvt i)- PrimConst c -> AST.PrimConst c- PrimApp f e -> cvtPrimFun f (cvt e)- Index a e -> AST.Index (cvtA a) (cvt e)- LinearIndex a i -> AST.LinearIndex (cvtA a) (cvt i)- Shape a -> AST.Shape (cvtA a)- ShapeSize e -> AST.ShapeSize (cvt e)- Intersect sh1 sh2 -> AST.Intersect (cvt sh1) (cvt sh2)- Union sh1 sh2 -> AST.Union (cvt sh1) (cvt sh2)- Foreign ff f e -> AST.Foreign ff (convertFun (recoverExpSharing config) f) (cvt e)-- cvtA :: Arrays a => ScopedAcc a -> AST.OpenAcc aenv a- cvtA = convertSharingAcc config alyt aenv-- cvtT :: Tuple ScopedExp tup -> Tuple (AST.OpenExp env aenv) tup- cvtT = convertSharingTuple config lyt alyt env' aenv-- cvtFun1 :: (Elt a, Elt b) => (Exp a -> ScopedExp b) -> AST.OpenFun env aenv (a -> b)- cvtFun1 f = Lam (Body (convertSharingExp config lyt' alyt env' aenv body))- where- lyt' = incLayout lyt `PushLayout` ZeroIdx- body = f undefined-- -- Push primitive function applications down through let bindings so that- -- they are adjacent to their arguments. It looks a bit nicer this way.- --- cvtPrimFun :: (Elt a, Elt r)- => AST.PrimFun (a -> r) -> AST.OpenExp env' aenv' a -> AST.OpenExp env' aenv' r- cvtPrimFun f e = case e of- AST.Let bnd body -> AST.Let bnd (cvtPrimFun f body)- x -> AST.PrimApp f x---- | Convert a tuple expression----convertSharingTuple- :: Config- -> Layout env env- -> Layout aenv aenv- -> [StableSharingExp] -- currently bound scalar sharing-variables- -> [StableSharingAcc] -- currently bound array sharing-variables- -> Tuple ScopedExp t- -> Tuple (AST.OpenExp env aenv) t-convertSharingTuple config lyt alyt env aenv tup =- case tup of- NilTup -> NilTup- SnocTup t e -> convertSharingTuple config lyt alyt env aenv t- `SnocTup` convertSharingExp config lyt alyt env aenv e---- | Convert a unary functions----convertSharingFun1- :: forall a b aenv. (Elt a, Elt b)- => Config- -> Layout aenv aenv- -> [StableSharingAcc] -- currently bound array sharing-variables- -> (Exp a -> ScopedExp b)- -> AST.Fun aenv (a -> b)-convertSharingFun1 config alyt aenv f = Lam (Body openF)- where- a = Exp undefined -- the 'tag' was already embedded in Phase 1- lyt = EmptyLayout- `PushLayout`- (ZeroIdx :: Idx ((), a) a)- openF = convertSharingExp config lyt alyt [] aenv (f a)---- | Convert a binary functions----convertSharingFun2- :: forall a b c aenv. (Elt a, Elt b, Elt c)- => Config- -> Layout aenv aenv- -> [StableSharingAcc] -- currently bound array sharing-variables- -> (Exp a -> Exp b -> ScopedExp c)- -> AST.Fun aenv (a -> b -> c)-convertSharingFun2 config alyt aenv f = Lam (Lam (Body openF))- where- a = Exp undefined- b = Exp undefined- lyt = EmptyLayout- `PushLayout`- (SuccIdx ZeroIdx :: Idx (((), a), b) a)- `PushLayout`- (ZeroIdx :: Idx (((), a), b) b)- openF = convertSharingExp config lyt alyt [] aenv (f a b)---- | Convert a unary stencil function----convertSharingStencilFun1- :: forall sh a stencil b aenv. (Elt a, Stencil sh a stencil, Elt b)- => Config- -> ScopedAcc (Array sh a) -- just passed to fix the type variables- -> Layout aenv aenv- -> [StableSharingAcc] -- currently bound array sharing-variables- -> (stencil -> ScopedExp b)- -> AST.Fun aenv (StencilRepr sh stencil -> b)-convertSharingStencilFun1 config _ alyt aenv stencilFun = Lam (Body openStencilFun)- where- stencil = Exp undefined :: Exp (StencilRepr sh stencil)- lyt = EmptyLayout- `PushLayout`- (ZeroIdx :: Idx ((), StencilRepr sh stencil)- (StencilRepr sh stencil))-- body = stencilFun (stencilPrj (undefined::sh) (undefined::a) stencil)- openStencilFun = convertSharingExp config lyt alyt [] aenv body---- | Convert a binary stencil function----convertSharingStencilFun2- :: forall sh a b stencil1 stencil2 c aenv.- (Elt a, Stencil sh a stencil1,- Elt b, Stencil sh b stencil2,- Elt c)- => Config- -> ScopedAcc (Array sh a) -- just passed to fix the type variables- -> ScopedAcc (Array sh b) -- just passed to fix the type variables- -> Layout aenv aenv- -> [StableSharingAcc] -- currently bound array sharing-variables- -> (stencil1 -> stencil2 -> ScopedExp c)- -> AST.Fun aenv (StencilRepr sh stencil1 -> StencilRepr sh stencil2 -> c)-convertSharingStencilFun2 config _ _ alyt aenv stencilFun = Lam (Lam (Body openStencilFun))- where- stencil1 = Exp undefined :: Exp (StencilRepr sh stencil1)- stencil2 = Exp undefined :: Exp (StencilRepr sh stencil2)- lyt = EmptyLayout- `PushLayout`- (SuccIdx ZeroIdx :: Idx (((), StencilRepr sh stencil1),- StencilRepr sh stencil2)- (StencilRepr sh stencil1))- `PushLayout`- (ZeroIdx :: Idx (((), StencilRepr sh stencil1),- StencilRepr sh stencil2)- (StencilRepr sh stencil2))-- body = stencilFun (stencilPrj (undefined::sh) (undefined::a) stencil1)- (stencilPrj (undefined::sh) (undefined::b) stencil2)- openStencilFun = convertSharingExp config lyt alyt [] aenv body----- Sharing recovery--- ================---- Sharing recovery proceeds in two phases:------ /Phase One: build the occurrence map/------ This is a top-down traversal of the AST that computes a map from AST nodes to the number of--- occurrences of that AST node in the overall Accelerate program. An occurrences count of two or--- more indicates sharing.------ IMPORTANT: To avoid unfolding the sharing, we do not descent into subtrees that we have--- previously encountered. Hence, the complexity is proportional to the number of nodes in the--- tree /with/ sharing. Consequently, the occurrence count is that in the tree with sharing--- as well.------ During computation of the occurrences, the tree is annotated with stable names on every node--- using 'AccSharing' constructors and all but the first occurrence of shared subtrees are pruned--- using 'AvarSharing' constructors (see 'SharingAcc' below). This phase is impure as it is based--- on stable names.------ We use a hash table (instead of 'Data.Map') as computing stable names forces us to live in IO--- anyway. Once, the computation of occurrence counts is complete, we freeze the hash table into--- a 'Data.Map'.------ (Implemented by 'makeOccMap*'.)------ /Phase Two: determine scopes and inject sharing information/------ This is a bottom-up traversal that determines the scope for every binding to be introduced--- to share a subterm. It uses the occurrence map to determine, for every shared subtree, the--- lowest AST node at which the binding for that shared subtree can be placed (using a--- 'AletSharing' constructor)— it's the meet of all the shared subtree occurrences.------ The second phase is also replacing the first occurrence of each shared subtree with a--- 'AvarSharing' node and floats the shared subtree up to its binding point.------ (Implemented by 'determineScopes*'.)------ /Sharing recovery for expressions/------ We recover sharing for each expression (including function bodies) independently of any other--- expression — i.e., we cannot share scalar expressions across array computations. Hence, during--- Phase One, we mark all scalar expression nodes with a stable name and compute one occurrence map--- for every scalar expression (including functions) that occurs in an array computation. These--- occurrence maps are added to the root of scalar expressions using 'RootExp'.------ NB: We do not need to worry sharing recovery will try to float a shared subexpression past a--- binder that occurs in that subexpression. Why? Otherwise, the binder would already occur--- out of scope in the original source program.------ /Lambda bound variables/------ During sharing recovery, lambda bound variables appear in the form of 'Atag' and 'Tag' data--- constructors. The tag values are determined during Phase One of sharing recovery by computing--- the /level/ of each variable at its binding occurrence. The level at the root of the AST is 0--- and increases by one with each lambda on each path through the AST.---- Stable names--- ---------------- Opaque stable name for AST nodes — used to key the occurrence map.----data StableASTName c where- StableASTName :: (Typeable c, Typeable t) => StableName (c t) -> StableASTName c--instance Show (StableASTName c) where- show (StableASTName sn) = show $ hashStableName sn--instance Eq (StableASTName c) where- StableASTName sn1 == StableASTName sn2- | Just sn1' <- gcast sn1 = sn1' == sn2- | otherwise = False--instance Hashable (StableASTName c) where- hashWithSalt s (StableASTName sn) = hashWithSalt s sn--makeStableAST :: c t -> IO (StableName (c t))-makeStableAST e = e `seq` makeStableName e---- Stable name for an AST node including the height of the AST representing the array computation.----data StableNameHeight t = StableNameHeight (StableName t) Int--instance Eq (StableNameHeight t) where- (StableNameHeight sn1 _) == (StableNameHeight sn2 _) = sn1 == sn2--higherSNH :: StableNameHeight t1 -> StableNameHeight t2 -> Bool-StableNameHeight _ h1 `higherSNH` StableNameHeight _ h2 = h1 > h2--hashStableNameHeight :: StableNameHeight t -> Int-hashStableNameHeight (StableNameHeight sn _) = hashStableName sn---- Mutable occurrence map--- -------------------------- Hash table keyed on the stable names of array computations.----type HashTable key val = Hash.BasicHashTable key val-type ASTHashTable c v = HashTable (StableASTName c) v---- Mutable hashtable version of the occurrence map, which associates each AST node with an--- occurrence count and the height of the AST.----type OccMapHash c = ASTHashTable c (Int, Int)---- Create a new hash table keyed on AST nodes.----newASTHashTable :: IO (ASTHashTable c v)-newASTHashTable = Hash.new---- Enter one AST node occurrence into an occurrence map. Returns 'Just h' if this is a repeated--- occurrence and the height of the repeatedly occurring AST is 'h'.------ If this is the first occurrence, the 'height' *argument* must provide the height of the AST;--- otherwise, the height will be *extracted* from the occurrence map. In the latter case, this--- function yields the AST height.----enterOcc :: OccMapHash c -> StableASTName c -> Int -> IO (Maybe Int)-enterOcc occMap sa height- = do- entry <- Hash.lookup occMap sa- case entry of- Nothing -> Hash.insert occMap sa (1 , height) >> return Nothing- Just (n, heightS) -> Hash.insert occMap sa (n + 1, heightS) >> return (Just heightS)---- Immutable occurrence map--- ---------------------------- Immutable version of the occurrence map (storing the occurrence count only, not the height). We--- use the 'StableName' hash to index an 'IntMap' and disambiguate 'StableName's with identical--- hashes explicitly, storing them in a list in the 'IntMap'.----type OccMap c = IntMap.IntMap [(StableASTName c, Int)]---- Turn a mutable into an immutable occurrence map.----freezeOccMap :: OccMapHash c -> IO (OccMap c)-freezeOccMap oc- = do- ocl <- Hash.toList oc- traceChunk "OccMap" (show ocl)-- return . IntMap.fromList- . map (\kvs -> (key (head kvs), kvs))- . groupBy sameKey- . map dropHeight- $ ocl- where- key (StableASTName sn, _) = hashStableName sn- sameKey kv1 kv2 = key kv1 == key kv2- dropHeight (k, (cnt, _)) = (k, cnt)---- Look up the occurrence map keyed by array computations using a stable name. If the key does--- not exist in the map, return an occurrence count of '1'.----lookupWithASTName :: OccMap c -> StableASTName c -> Int-lookupWithASTName oc sa@(StableASTName sn)- = fromMaybe 1 $ IntMap.lookup (hashStableName sn) oc >>= Prelude.lookup sa---- Look up the occurrence map keyed by array computations using a sharing array computation. If an--- the key does not exist in the map, return an occurrence count of '1'.----lookupWithSharingAcc :: OccMap Acc -> StableSharingAcc -> Int-lookupWithSharingAcc oc (StableSharingAcc (StableNameHeight sn _) _)- = lookupWithASTName oc (StableASTName sn)---- Look up the occurrence map keyed by scalar expressions using a sharing expression. If an--- the key does not exist in the map, return an occurrence count of '1'.----lookupWithSharingExp :: OccMap Exp -> StableSharingExp -> Int-lookupWithSharingExp oc (StableSharingExp (StableNameHeight sn _) _)- = lookupWithASTName oc (StableASTName sn)----- Stable 'Acc' nodes--- ---------------------- Stable name for 'Acc' nodes including the height of the AST.----type StableAccName arrs = StableNameHeight (Acc arrs)---- Interleave sharing annotations into an array computation AST. Subtrees can be marked as being--- represented by variable (binding a shared subtree) using 'AvarSharing' and as being prefixed by--- a let binding (for a shared subtree) using 'AletSharing'.----data SharingAcc acc exp arrs where- AvarSharing :: Arrays arrs- => StableAccName arrs -> SharingAcc acc exp arrs- AletSharing :: StableSharingAcc -> acc arrs -> SharingAcc acc exp arrs- AccSharing :: Arrays arrs- => StableAccName arrs -> PreAcc acc exp arrs -> SharingAcc acc exp arrs---- Array expression with sharing but shared values have not been scoped; i.e. no let bindings. If--- the expression is rooted in a function, the list contains the tags of the variables bound by the--- immediate surrounding lambdas.-data UnscopedAcc t = UnscopedAcc [Int] (SharingAcc UnscopedAcc RootExp t)---- Array expression with sharing. For expressions rooted in functions the list holds a sorted--- environment corresponding to the variables bound in the immediate surounding lambdas.-data ScopedAcc t = ScopedAcc [StableSharingAcc] (SharingAcc ScopedAcc ScopedExp t)---- Stable name for an array computation associated with its sharing-annotated version.----data StableSharingAcc where- StableSharingAcc :: Arrays arrs- => StableAccName arrs- -> SharingAcc ScopedAcc ScopedExp arrs- -> StableSharingAcc--instance Show StableSharingAcc where- show (StableSharingAcc sn _) = show $ hashStableNameHeight sn--instance Eq StableSharingAcc where- StableSharingAcc sn1 _ == StableSharingAcc sn2 _- | Just sn1' <- gcast sn1 = sn1' == sn2- | otherwise = False--higherSSA :: StableSharingAcc -> StableSharingAcc -> Bool-StableSharingAcc sn1 _ `higherSSA` StableSharingAcc sn2 _ = sn1 `higherSNH` sn2---- Test whether the given stable names matches an array computation with sharing.----matchStableAcc :: Typeable arrs => StableAccName arrs -> StableSharingAcc -> Bool-matchStableAcc sn1 (StableSharingAcc sn2 _)- | Just sn1' <- gcast sn1 = sn1' == sn2- | otherwise = False---- Dummy entry for environments to be used for unused variables.----noStableAccName :: StableAccName arrs-noStableAccName = unsafePerformIO $ StableNameHeight <$> makeStableName undefined <*> pure 0---- Stable 'Exp' nodes--- ---------------------- Stable name for 'Exp' nodes including the height of the AST.----type StableExpName t = StableNameHeight (Exp t)---- Interleave sharing annotations into a scalar expressions AST in the same manner as 'SharingAcc'--- do for array computations.----data SharingExp (acc :: * -> *) exp t where- VarSharing :: Elt t- => StableExpName t -> SharingExp acc exp t- LetSharing :: StableSharingExp -> exp t -> SharingExp acc exp t- ExpSharing :: Elt t- => StableExpName t -> PreExp acc exp t -> SharingExp acc exp t---- Specifies a scalar expression AST with sharing annotations but no scoping; i.e. no LetSharing--- constructors. If the expression is rooted in a function, the list contains the tags of the--- variables bound by the immediate surrounding lambdas.-data UnscopedExp t = UnscopedExp [Int] (SharingExp UnscopedAcc UnscopedExp t)---- Specifies a scalar expression AST with sharing. For expressions rooted in functions the list--- holds a sorted environment corresponding to the variables bound in the immediate surounding--- lambdas.-data ScopedExp t = ScopedExp [StableSharingExp] (SharingExp ScopedAcc ScopedExp t)---- Expressions rooted in 'Acc' computations.------ * When counting occurrences, the root of every expression embedded in an 'Acc' is annotated by--- an occurrence map for that one expression (excluding any subterms that are rooted in embedded--- 'Acc's.)----data RootExp t = RootExp (OccMap Exp) (UnscopedExp t)---- Stable name for an expression associated with its sharing-annotated version.----data StableSharingExp where- StableSharingExp :: Elt t => StableExpName t -> SharingExp ScopedAcc ScopedExp t -> StableSharingExp--instance Show StableSharingExp where- show (StableSharingExp sn _) = show $ hashStableNameHeight sn--instance Eq StableSharingExp where- StableSharingExp sn1 _ == StableSharingExp sn2 _- | Just sn1' <- gcast sn1 = sn1' == sn2- | otherwise = False--higherSSE :: StableSharingExp -> StableSharingExp -> Bool-StableSharingExp sn1 _ `higherSSE` StableSharingExp sn2 _ = sn1 `higherSNH` sn2---- Test whether the given stable names matches an expression with sharing.----matchStableExp :: Typeable t => StableExpName t -> StableSharingExp -> Bool-matchStableExp sn1 (StableSharingExp sn2 _)- | Just sn1' <- gcast sn1 = sn1' == sn2- | otherwise = False---- Dummy entry for environments to be used for unused variables.----noStableExpName :: StableExpName t-noStableExpName = unsafePerformIO $ StableNameHeight <$> makeStableName undefined <*> pure 0---{----- Stable 'Seq' nodes--- ---------------------- Stable name for 'Seq' nodes including the height of the AST.----type StableSeqName arrs = StableNameHeight (Seq arrs)---- Interleave sharing annotations into an sequence computation AST in the same manner as SharingAcc--- and SharingExp----data SharingSeq acc seq exp arrs where- SvarSharing :: (Typeable arrs, Arrays arrs)- => StableSeqName [arrs] -> SharingSeq acc seq exp [arrs]- SletSharing :: StableSharingSeq -> seq t -> SharingSeq acc seq exp t- SeqSharing :: Typeable arrs- => StableSeqName arrs -> PreSeq acc seq exp arrs -> SharingSeq acc seq exp arrs---- Array expression with sharing but shared values have not been scoped; i.e. no let bindings. If--- the expression is rooted in a function, the list contains the tags of the variables bound by the--- immediate surrounding lambdas.-data UnscopedSeq t = UnscopedSeq (SharingSeq UnscopedAcc UnscopedSeq RootExp t)---- Array expression with sharing. For expressions rooted in functions the list holds a sorted--- environment corresponding to the variables bound in the immediate surounding lambdas.-data ScopedSeq t = ScopedSeq (SharingSeq ScopedAcc ScopedSeq ScopedExp t)---- Sequences rooted in 'Acc' computations.------ * When counting occurrences, the root of every sequence embedded in an 'Acc' is annotated by--- an occurrence map for that one expression (excluding any subterms that are rooted in embedded--- 'Acc's.)----data RootSeq t = RootSeq (OccMap Seq) (UnscopedSeq t)---- Stable name for an array computation associated with its sharing-annotated version.----data StableSharingSeq where- StableSharingSeq :: Typeable arrs- => StableSeqName arrs- -> SharingSeq ScopedAcc ScopedSeq ScopedExp arrs- -> StableSharingSeq--instance Show StableSharingSeq where- show (StableSharingSeq sn _) = show $ hashStableNameHeight sn--instance Eq StableSharingSeq where- StableSharingSeq sn1 _ == StableSharingSeq sn2 _- | Just sn1' <- gcast sn1 = sn1' == sn2- | otherwise = False--higherSSS :: StableSharingSeq -> StableSharingSeq -> Bool-StableSharingSeq sn1 _ `higherSSS` StableSharingSeq sn2 _ = sn1 `higherSNH` sn2---- Test whether the given stable names matches an array computation with sharing.----matchStableSeq :: Typeable arrs => StableSeqName arrs -> StableSharingSeq -> Bool-matchStableSeq sn1 (StableSharingSeq sn2 _)- | Just sn1' <- gcast sn1 = sn1' == sn2- | otherwise = False---}----- Occurrence counting--- ===================---- Compute the 'Acc' occurrence map, marks all nodes (both 'Seq' and 'Exp' nodes) with stable names,--- and drop repeated occurrences of shared 'Acc' and 'Exp' subtrees (Phase One).------ We compute a single 'Acc' occurrence map for the whole AST, but one 'Exp' occurrence map for each--- sub-expression rooted in an 'Acc' operation. This is as we cannot float 'Exp' subtrees across--- 'Acc' operations, but we can float 'Acc' subtrees out of 'Exp' expressions.------ Note [Traversing functions and side effects]--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--- We need to descent into function bodies to build the 'OccMap' with all occurrences in the--- function bodies. Due to the side effects in the construction of the occurrence map and, more--- importantly, the dependence of the second phase on /global/ occurrence information, we may not--- delay the body traversals by putting them under a lambda. Hence, we apply each function, to--- traverse its body and use a /dummy abstraction/ of the result.------ For example, given a function 'f', we traverse 'f (Tag 0)', which yields a transformed body 'e'.--- As the result of the traversal of the overall function, we use 'const e'. Hence, it is crucial--- that the 'Tag' supplied during the initial traversal is already the one required by the HOAS to--- de Bruijn conversion in 'convertSharingAcc' — any subsequent application of 'const e' will only--- yield 'e' with the embedded 'Tag 0' of the original application. During sharing recovery, we--- float /all/ free variables ('Atag' and 'Tag') out to construct the initial environment for--- producing de Bruijn indices, which replaces them by 'AvarSharing' or 'VarSharing' nodes. Hence,--- the tag values only serve the purpose of determining the ordering in that initial environment.--- They are /not/ directly used to compute the de Brujin indices.----makeOccMapAcc- :: Typeable arrs- => Config- -> Level- -> Acc arrs- -> IO (UnscopedAcc arrs, OccMap Acc)-makeOccMapAcc config lvl acc = do- traceLine "makeOccMapAcc" "Enter"- accOccMap <- newASTHashTable- (acc', _) <- makeOccMapSharingAcc config accOccMap lvl acc- frozenAccOccMap <- freezeOccMap accOccMap- traceLine "makeOccMapAcc" "Exit"- return (acc', frozenAccOccMap)---makeOccMapSharingAcc- :: Typeable arrs- => Config- -> OccMapHash Acc- -> Level- -> Acc arrs- -> IO (UnscopedAcc arrs, Int)-makeOccMapSharingAcc config accOccMap = traverseAcc- where- traverseFun1 :: (Elt a, Typeable b) => Level -> (Exp a -> Exp b) -> IO (Exp a -> RootExp b, Int)- traverseFun1 = makeOccMapFun1 config accOccMap-- traverseFun2 :: (Elt a, Elt b, Typeable c)- => Level- -> (Exp a -> Exp b -> Exp c)- -> IO (Exp a -> Exp b -> RootExp c, Int)- traverseFun2 = makeOccMapFun2 config accOccMap-- traverseAfun1 :: (Arrays a, Typeable b) => Level -> (Acc a -> Acc b) -> IO (Acc a -> UnscopedAcc b, Int)- traverseAfun1 = makeOccMapAfun1 config accOccMap-- traverseExp :: Typeable e => Level -> Exp e -> IO (RootExp e, Int)- traverseExp = makeOccMapExp config accOccMap-- traverseBoundary- :: Level- -> PreBoundary Acc Exp t- -> IO (PreBoundary UnscopedAcc RootExp t, Int)- traverseBoundary lvl bndy =- case bndy of- Clamp -> return (Clamp, 0)- Mirror -> return (Mirror, 0)- Wrap -> return (Wrap, 0)- Constant v -> return (Constant v, 0)- Function f -> do- (f', h) <- traverseFun1 lvl f- return (Function f', h)-- -- traverseSeq :: forall arrs. Typeable arrs- -- => Level -> Seq arrs- -- -> IO (RootSeq arrs, Int)- -- traverseSeq = makeOccMapRootSeq config accOccMap-- traverseAcc :: forall arrs. Typeable arrs => Level -> Acc arrs -> IO (UnscopedAcc arrs, Int)- traverseAcc lvl acc@(Acc pacc)- = mfix $ \ ~(_, height) -> do- -- Compute stable name and enter it into the occurrence map- --- sn <- makeStableAST acc- heightIfRepeatedOccurrence <- enterOcc accOccMap (StableASTName sn) height-- traceLine (showPreAccOp pacc) $ do- let hash = show (hashStableName sn)- case heightIfRepeatedOccurrence of- Just height -> "REPEATED occurrence (sn = " ++ hash ++ "; height = " ++ show height ++ ")"- Nothing -> "first occurrence (sn = " ++ hash ++ ")"-- -- Reconstruct the computation in shared form.- --- -- In case of a repeated occurrence, the height comes from the occurrence map; otherwise- -- it is computed by the traversal function passed in 'newAcc'. See also 'enterOcc'.- --- -- NB: This function can only be used in the case alternatives below; outside of the- -- case we cannot discharge the 'Arrays arrs' constraint.- --- let reconstruct :: Arrays arrs- => IO (PreAcc UnscopedAcc RootExp arrs, Int)- -> IO (UnscopedAcc arrs, Int)- reconstruct newAcc- = case heightIfRepeatedOccurrence of- Just height | recoverAccSharing config- -> return (UnscopedAcc [] (AvarSharing (StableNameHeight sn height)), height)- _ -> do (acc, height) <- newAcc- return (UnscopedAcc [] (AccSharing (StableNameHeight sn height) acc), height)-- case pacc of- Atag i -> reconstruct $ return (Atag i, 0) -- height is 0!- Pipe afun1 afun2 acc -> reconstruct $ do- (afun1', h1) <- traverseAfun1 lvl afun1- (afun2', h2) <- traverseAfun1 lvl afun2- (acc', h3) <- traverseAcc lvl acc- return (Pipe afun1' afun2' acc'- , h1 `max` h2 `max` h3 + 1)- Aforeign ff afun acc -> reconstruct $ travA (Aforeign ff afun) acc- Acond e acc1 acc2 -> reconstruct $ do- (e' , h1) <- traverseExp lvl e- (acc1', h2) <- traverseAcc lvl acc1- (acc2', h3) <- traverseAcc lvl acc2- return (Acond e' acc1' acc2', h1 `max` h2 `max` h3 + 1)- Awhile pred iter init -> reconstruct $ do- (pred', h1) <- traverseAfun1 lvl pred- (iter', h2) <- traverseAfun1 lvl iter- (init', h3) <- traverseAcc lvl init- return (Awhile pred' iter' init'- , h1 `max` h2 `max` h3 + 1)-- Atuple tup -> reconstruct $ do- (tup', h) <- travAtup tup- return (Atuple tup', h)- Aprj ix a -> reconstruct $ travA (Aprj ix) a-- Use arr -> reconstruct $ return (Use arr, 1)- Unit e -> reconstruct $ do- (e', h) <- traverseExp lvl e- return (Unit e', h + 1)- Generate e f -> reconstruct $ do- (e', h1) <- traverseExp lvl e- (f', h2) <- traverseFun1 lvl f- return (Generate e' f', h1 `max` h2 + 1)- Reshape e acc -> reconstruct $ travEA Reshape e acc- Replicate e acc -> reconstruct $ travEA Replicate e acc- Slice acc e -> reconstruct $ travEA (flip Slice) e acc- Map f acc -> reconstruct $ do- (f' , h1) <- traverseFun1 lvl f- (acc', h2) <- traverseAcc lvl acc- return (Map f' acc', h1 `max` h2 + 1)- ZipWith f acc1 acc2 -> reconstruct $ travF2A2 ZipWith f acc1 acc2- Fold f e acc -> reconstruct $ travF2EA Fold f e acc- Fold1 f acc -> reconstruct $ travF2A Fold1 f acc- FoldSeg f e acc1 acc2 -> reconstruct $ do- (f' , h1) <- traverseFun2 lvl f- (e' , h2) <- traverseExp lvl e- (acc1', h3) <- traverseAcc lvl acc1- (acc2', h4) <- traverseAcc lvl acc2- return (FoldSeg f' e' acc1' acc2',- h1 `max` h2 `max` h3 `max` h4 + 1)- Fold1Seg f acc1 acc2 -> reconstruct $ travF2A2 Fold1Seg f acc1 acc2- Scanl f e acc -> reconstruct $ travF2EA Scanl f e acc- Scanl' f e acc -> reconstruct $ travF2EA Scanl' f e acc- Scanl1 f acc -> reconstruct $ travF2A Scanl1 f acc- Scanr f e acc -> reconstruct $ travF2EA Scanr f e acc- Scanr' f e acc -> reconstruct $ travF2EA Scanr' f e acc- Scanr1 f acc -> reconstruct $ travF2A Scanr1 f acc- Permute c acc1 p acc2 -> reconstruct $ do- (c' , h1) <- traverseFun2 lvl c- (p' , h2) <- traverseFun1 lvl p- (acc1', h3) <- traverseAcc lvl acc1- (acc2', h4) <- traverseAcc lvl acc2- return (Permute c' acc1' p' acc2',- h1 `max` h2 `max` h3 `max` h4 + 1)- Backpermute e p acc -> reconstruct $ do- (e' , h1) <- traverseExp lvl e- (p' , h2) <- traverseFun1 lvl p- (acc', h3) <- traverseAcc lvl acc- return (Backpermute e' p' acc', h1 `max` h2 `max` h3 + 1)- Stencil s bnd acc -> reconstruct $ do- (s' , h1) <- makeOccMapStencil1 config accOccMap acc lvl s- (bnd', h2) <- traverseBoundary lvl bnd- (acc', h3) <- traverseAcc lvl acc- return (Stencil s' bnd' acc', h1 `max` h2 `max` h3 + 1)- Stencil2 s bnd1 acc1- bnd2 acc2 -> reconstruct $ do- (s' , h1) <- makeOccMapStencil2 config accOccMap acc1 acc2 lvl s- (bnd1', h2) <- traverseBoundary lvl bnd1- (acc1', h3) <- traverseAcc lvl acc1- (bnd2', h4) <- traverseBoundary lvl bnd2- (acc2', h5) <- traverseAcc lvl acc2- return (Stencil2 s' bnd1' acc1' bnd2' acc2',- h1 `max` h2 `max` h3 `max` h4 `max` h5 + 1)- -- Collect s -> reconstruct $ do- -- (s', h) <- traverseSeq lvl s- -- return (Collect s', h + 1)--- where- travA :: Arrays arrs'- => (UnscopedAcc arrs' -> PreAcc UnscopedAcc RootExp arrs)- -> Acc arrs' -> IO (PreAcc UnscopedAcc RootExp arrs, Int)- travA c acc- = do- (acc', h) <- traverseAcc lvl acc- return (c acc', h + 1)-- travEA :: (Typeable b, Arrays arrs')- => (RootExp b -> UnscopedAcc arrs' -> PreAcc UnscopedAcc RootExp arrs)- -> Exp b -> Acc arrs' -> IO (PreAcc UnscopedAcc RootExp arrs, Int)- travEA c exp acc- = do- (exp', h1) <- traverseExp lvl exp- (acc', h2) <- traverseAcc lvl acc- return (c exp' acc', h1 `max` h2 + 1)-- travF2A :: (Elt b, Elt c, Typeable d, Arrays arrs')- => ((Exp b -> Exp c -> RootExp d) -> UnscopedAcc arrs'- -> PreAcc UnscopedAcc RootExp arrs)- -> (Exp b -> Exp c -> Exp d) -> Acc arrs'- -> IO (PreAcc UnscopedAcc RootExp arrs, Int)- travF2A c fun acc- = do- (fun', h1) <- traverseFun2 lvl fun- (acc', h2) <- traverseAcc lvl acc- return (c fun' acc', h1 `max` h2 + 1)-- travF2EA :: (Elt b, Elt c, Typeable d, Typeable e, Arrays arrs')- => ((Exp b -> Exp c -> RootExp d) -> RootExp e -> UnscopedAcc arrs' -> PreAcc UnscopedAcc RootExp arrs)- -> (Exp b -> Exp c -> Exp d) -> Exp e -> Acc arrs'- -> IO (PreAcc UnscopedAcc RootExp arrs, Int)- travF2EA c fun exp acc- = do- (fun', h1) <- traverseFun2 lvl fun- (exp', h2) <- traverseExp lvl exp- (acc', h3) <- traverseAcc lvl acc- return (c fun' exp' acc', h1 `max` h2 `max` h3 + 1)-- travF2A2 :: (Elt b, Elt c, Typeable d, Arrays arrs1, Arrays arrs2)- => ((Exp b -> Exp c -> RootExp d) -> UnscopedAcc arrs1 -> UnscopedAcc arrs2 -> PreAcc UnscopedAcc RootExp arrs)- -> (Exp b -> Exp c -> Exp d) -> Acc arrs1 -> Acc arrs2- -> IO (PreAcc UnscopedAcc RootExp arrs, Int)- travF2A2 c fun acc1 acc2- = do- (fun' , h1) <- traverseFun2 lvl fun- (acc1', h2) <- traverseAcc lvl acc1- (acc2', h3) <- traverseAcc lvl acc2- return (c fun' acc1' acc2', h1 `max` h2 `max` h3 + 1)-- travAtup :: Atuple Acc a- -> IO (Atuple UnscopedAcc a, Int)- travAtup NilAtup = return (NilAtup, 1)- travAtup (SnocAtup tup a) = do- (tup', h1) <- travAtup tup- (a', h2) <- traverseAcc lvl a- return (SnocAtup tup' a', h1 `max` h2 + 1)--makeOccMapAfun1 :: (Arrays a, Typeable b)- => Config- -> OccMapHash Acc- -> Level- -> (Acc a -> Acc b)- -> IO (Acc a -> UnscopedAcc b, Int)-makeOccMapAfun1 config accOccMap lvl f = do- let x = Acc (Atag lvl)- --- (UnscopedAcc [] body, height) <- makeOccMapSharingAcc config accOccMap (lvl+1) (f x)- return (const (UnscopedAcc [lvl] body), height)--{---makeOccMapAfun2 :: (Arrays a, Arrays b, Typeable c)- => Config- -> OccMapHash Acc- -> Level- -> (Acc a -> Acc b -> Acc c)- -> IO (Acc a -> Acc b -> UnscopedAcc c, Int)-makeOccMapAfun2 config accOccMap lvl f = do- let x = Acc (Atag (lvl + 1))- y = Acc (Atag (lvl + 0))- --- (UnscopedAcc [] body, height) <- makeOccMapSharingAcc config accOccMap (lvl+2) (f x y)- return (\ _ _ -> (UnscopedAcc [lvl, lvl+1] body), height)--makeOccMapAfun3 :: (Arrays a, Arrays b, Arrays c, Typeable d)- => Config- -> OccMapHash Acc- -> Level- -> (Acc a -> Acc b -> Acc c -> Acc d)- -> IO (Acc a -> Acc b -> Acc c -> UnscopedAcc d, Int)-makeOccMapAfun3 config accOccMap lvl f = do- let x = Acc (Atag (lvl + 2))- y = Acc (Atag (lvl + 1))- z = Acc (Atag (lvl + 0))- --- (UnscopedAcc [] body, height) <- makeOccMapSharingAcc config accOccMap (lvl+3) (f x y z)- return (\ _ _ _ -> (UnscopedAcc [lvl, lvl+1, lvl+2] body), height)---}---- Generate occupancy information for scalar functions and expressions. Helper--- functions wrapping around 'makeOccMapRootExp' with more specific types.------ See Note [Traversing functions and side effects]----makeOccMapExp- :: Typeable e- => Config- -> OccMapHash Acc- -> Level- -> Exp e- -> IO (RootExp e, Int)-makeOccMapExp config accOccMap lvl = makeOccMapRootExp config accOccMap lvl []--makeOccMapFun1- :: (Elt a, Typeable b)- => Config- -> OccMapHash Acc- -> Level- -> (Exp a -> Exp b)- -> IO (Exp a -> RootExp b, Int)-makeOccMapFun1 config accOccMap lvl f = do- let x = Exp (Tag lvl)- --- (body, height) <- makeOccMapRootExp config accOccMap (lvl+1) [lvl] (f x)- return (const body, height)--makeOccMapFun2- :: (Elt a, Elt b, Typeable c)- => Config- -> OccMapHash Acc- -> Level- -> (Exp a -> Exp b -> Exp c)- -> IO (Exp a -> Exp b -> RootExp c, Int)-makeOccMapFun2 config accOccMap lvl f = do- let x = Exp (Tag (lvl+1))- y = Exp (Tag lvl)- --- (body, height) <- makeOccMapRootExp config accOccMap (lvl+2) [lvl, lvl+1] (f x y)- return (\_ _ -> body, height)--makeOccMapStencil1- :: forall sh a b stencil. (Stencil sh a stencil, Typeable b)- => Config- -> OccMapHash Acc- -> Acc (Array sh a) {- dummy -}- -> Level- -> (stencil -> Exp b)- -> IO (stencil -> RootExp b, Int)-makeOccMapStencil1 config accOccMap _ lvl stencil = do- let x = Exp (Tag lvl)- f = stencil . stencilPrj (undefined::sh) (undefined::a)- --- (body, height) <- makeOccMapRootExp config accOccMap (lvl+1) [lvl] (f x)- return (const body, height)--makeOccMapStencil2- :: forall sh a b c stencil1 stencil2. (Stencil sh a stencil1, Stencil sh b stencil2, Typeable c)- => Config- -> OccMapHash Acc- -> Acc (Array sh a) {- dummy -}- -> Acc (Array sh b) {- dummy -}- -> Level- -> (stencil1 -> stencil2 -> Exp c)- -> IO (stencil1 -> stencil2 -> RootExp c, Int)-makeOccMapStencil2 config accOccMap _ _ lvl stencil = do- let x = Exp (Tag (lvl+1))- y = Exp (Tag lvl)- f a b = stencil (stencilPrj (undefined::sh) (undefined::a) a)- (stencilPrj (undefined::sh) (undefined::b) b)- --- (body, height) <- makeOccMapRootExp config accOccMap (lvl+2) [lvl, lvl+1] (f x y)- return (\_ _ -> body, height)----- Generate sharing information for expressions embedded in Acc computations.--- Expressions are annotated with:------ 1) the tags of free scalar variables (for scalar functions)--- 2) a local occurrence map for that expression.----makeOccMapRootExp- :: Typeable e- => Config- -> OccMapHash Acc- -> Level -- The level of currently bound scalar variables- -> [Int] -- The tags of newly introduced free scalar variables in this expression- -> Exp e- -> IO (RootExp e, Int)-makeOccMapRootExp config accOccMap lvl fvs exp = do- traceLine "makeOccMapRootExp" "Enter"- expOccMap <- newASTHashTable- (UnscopedExp [] exp', height) <- makeOccMapSharingExp config accOccMap expOccMap lvl exp- frozenExpOccMap <- freezeOccMap expOccMap- traceLine "makeOccMapRootExp" "Exit"- return (RootExp frozenExpOccMap (UnscopedExp fvs exp'), height)----- Generate sharing information for an open scalar expression.----makeOccMapSharingExp- :: Typeable e- => Config- -> OccMapHash Acc- -> OccMapHash Exp- -> Level -- The level of currently bound variables- -> Exp e- -> IO (UnscopedExp e, Int)-makeOccMapSharingExp config accOccMap expOccMap = travE- where- travE :: forall a. Typeable a => Level -> Exp a -> IO (UnscopedExp a, Int)- travE lvl exp@(Exp pexp)- = mfix $ \ ~(_, height) -> do- -- Compute stable name and enter it into the occurrence map- --- sn <- makeStableAST exp- heightIfRepeatedOccurrence <- enterOcc expOccMap (StableASTName sn) height-- traceLine (showPreExpOp pexp) $ do- let hash = show (hashStableName sn)- case heightIfRepeatedOccurrence of- Just height -> "REPEATED occurrence (sn = " ++ hash ++ "; height = " ++ show height ++ ")"- Nothing -> "first occurrence (sn = " ++ hash ++ ")"-- -- Reconstruct the computation in shared form.- --- -- In case of a repeated occurrence, the height comes from the occurrence map; otherwise- -- it is computed by the traversal function passed in 'newExp'. See also 'enterOcc'.- --- -- NB: This function can only be used in the case alternatives below; outside of the- -- case we cannot discharge the 'Elt a' constraint.- --- let reconstruct :: Elt a- => IO (PreExp UnscopedAcc UnscopedExp a, Int)- -> IO (UnscopedExp a, Int)- reconstruct newExp- = case heightIfRepeatedOccurrence of- Just height | recoverExpSharing config- -> return (UnscopedExp [] (VarSharing (StableNameHeight sn height)), height)- _ -> do (exp, height) <- newExp- return (UnscopedExp [] (ExpSharing (StableNameHeight sn height) exp), height)-- case pexp of- Tag i -> reconstruct $ return (Tag i, 0) -- height is 0!- Const c -> reconstruct $ return (Const c, 1)- Tuple tup -> reconstruct $ do- (tup', h) <- travTup tup- return (Tuple tup', h)- Prj i e -> reconstruct $ travE1 (Prj i) e- IndexNil -> reconstruct $ return (IndexNil, 1)- IndexCons ix i -> reconstruct $ travE2 IndexCons ix i- IndexHead i -> reconstruct $ travE1 IndexHead i- IndexTail ix -> reconstruct $ travE1 IndexTail ix- IndexAny -> reconstruct $ return (IndexAny, 1)- ToIndex sh ix -> reconstruct $ travE2 ToIndex sh ix- FromIndex sh e -> reconstruct $ travE2 FromIndex sh e- Cond e1 e2 e3 -> reconstruct $ travE3 Cond e1 e2 e3- While p iter init -> reconstruct $ do- (p' , h1) <- traverseFun1 lvl p- (iter', h2) <- traverseFun1 lvl iter- (init', h3) <- travE lvl init- return (While p' iter' init', h1 `max` h2 `max` h3 + 1)- PrimConst c -> reconstruct $ return (PrimConst c, 1)- PrimApp p e -> reconstruct $ travE1 (PrimApp p) e- Index a e -> reconstruct $ travAE Index a e- LinearIndex a i -> reconstruct $ travAE LinearIndex a i- Shape a -> reconstruct $ travA Shape a- ShapeSize e -> reconstruct $ travE1 ShapeSize e- Intersect sh1 sh2 -> reconstruct $ travE2 Intersect sh1 sh2- Union sh1 sh2 -> reconstruct $ travE2 Union sh1 sh2- Foreign ff f e -> reconstruct $ do- (e', h) <- travE lvl e- return (Foreign ff f e', h+1)-- where- traverseAcc :: Typeable arrs => Level -> Acc arrs -> IO (UnscopedAcc arrs, Int)- traverseAcc = makeOccMapSharingAcc config accOccMap-- traverseFun1 :: (Elt a, Typeable b)- => Level- -> (Exp a -> Exp b)- -> IO (Exp a -> UnscopedExp b, Int)- traverseFun1 lvl f- = do- let x = Exp (Tag lvl)- (UnscopedExp [] body, height) <- travE (lvl+1) (f x)- return (const (UnscopedExp [lvl] body), height + 1)--- travE1 :: Typeable b => (UnscopedExp b -> PreExp UnscopedAcc UnscopedExp a) -> Exp b- -> IO (PreExp UnscopedAcc UnscopedExp a, Int)- travE1 c e- = do- (e', h) <- travE lvl e- return (c e', h + 1)-- travE2 :: (Typeable b, Typeable c)- => (UnscopedExp b -> UnscopedExp c -> PreExp UnscopedAcc UnscopedExp a)- -> Exp b -> Exp c- -> IO (PreExp UnscopedAcc UnscopedExp a, Int)- travE2 c e1 e2- = do- (e1', h1) <- travE lvl e1- (e2', h2) <- travE lvl e2- return (c e1' e2', h1 `max` h2 + 1)-- travE3 :: (Typeable b, Typeable c, Typeable d)- => (UnscopedExp b -> UnscopedExp c -> UnscopedExp d -> PreExp UnscopedAcc UnscopedExp a)- -> Exp b -> Exp c -> Exp d- -> IO (PreExp UnscopedAcc UnscopedExp a, Int)- travE3 c e1 e2 e3- = do- (e1', h1) <- travE lvl e1- (e2', h2) <- travE lvl e2- (e3', h3) <- travE lvl e3- return (c e1' e2' e3', h1 `max` h2 `max` h3 + 1)-- travA :: Typeable b => (UnscopedAcc b -> PreExp UnscopedAcc UnscopedExp a) -> Acc b- -> IO (PreExp UnscopedAcc UnscopedExp a, Int)- travA c acc- = do- (acc', h) <- traverseAcc lvl acc- return (c acc', h + 1)-- travAE :: (Typeable b, Typeable c)- => (UnscopedAcc b -> UnscopedExp c -> PreExp UnscopedAcc UnscopedExp a)- -> Acc b -> Exp c- -> IO (PreExp UnscopedAcc UnscopedExp a, Int)- travAE c acc e- = do- (acc', h1) <- traverseAcc lvl acc- (e' , h2) <- travE lvl e- return (c acc' e', h1 `max` h2 + 1)-- travTup :: Tuple Exp tup -> IO (Tuple UnscopedExp tup, Int)- travTup NilTup = return (NilTup, 1)- travTup (SnocTup tup e) = do- (tup', h1) <- travTup tup- (e' , h2) <- travE lvl e- return (SnocTup tup' e', h1 `max` h2 + 1)---{---makeOccMapRootSeq- :: Typeable arrs- => Config- -> OccMapHash Acc- -> Level- -> Seq arrs- -> IO (RootSeq arrs, Int)-makeOccMapRootSeq config accOccMap lvl seq = do- traceLine "makeOccMapRootSeq" "Enter"- seqOccMap <- newASTHashTable- (seq', height) <- makeOccMapSharingSeq config accOccMap seqOccMap lvl seq- frozenSeqOccMap <- freezeOccMap seqOccMap- traceLine "makeOccMapRootSeq" "Exit"- return (RootSeq frozenSeqOccMap seq', height)---- Generate sharing information for an open sequence expression.----makeOccMapSharingSeq- :: Typeable e- => Config- -> OccMapHash Acc- -> OccMapHash Seq- -> Level -- The level of currently bound variables- -> Seq e- -> IO (UnscopedSeq e, Int)-makeOccMapSharingSeq config accOccMap seqOccMap = traverseSeq- where- traverseAcc :: Typeable arrs => Level -> Acc arrs -> IO (UnscopedAcc arrs, Int)- traverseAcc = makeOccMapSharingAcc config accOccMap-- traverseAfun1 :: (Arrays a, Typeable b) => Level -> (Acc a -> Acc b) -> IO (Acc a -> UnscopedAcc b, Int)- traverseAfun1 = makeOccMapAfun1 config accOccMap-- traverseAfun2 :: (Arrays a, Arrays b, Typeable c) => Level -> (Acc a -> Acc b -> Acc c) -> IO (Acc a -> Acc b -> UnscopedAcc c, Int)- traverseAfun2 = makeOccMapAfun2 config accOccMap-- traverseAfun3 :: (Arrays a, Arrays b, Arrays c, Typeable d) => Level -> (Acc a -> Acc b -> Acc c -> Acc d) -> IO (Acc a -> Acc b -> Acc c -> UnscopedAcc d, Int)- traverseAfun3 = makeOccMapAfun3 config accOccMap-- traverseExp :: Typeable e => Level -> Exp e -> IO (RootExp e, Int)- traverseExp = makeOccMapExp config accOccMap-- traverseFun2 :: (Elt a, Elt b, Typeable c)- => Level- -> (Exp a -> Exp b -> Exp c)- -> IO (Exp a -> Exp b -> RootExp c, Int)- traverseFun2 = makeOccMapFun2 config accOccMap-- traverseTup :: Level -> Atuple Seq tup -> IO (Atuple UnscopedSeq tup, Int)- traverseTup _ NilAtup = return (NilAtup, 1)- traverseTup lvl (SnocAtup tup s) = do- (tup', h1) <- traverseTup lvl tup- (s' , h2) <- traverseSeq lvl s- return (SnocAtup tup' s', h1 `max` h2 + 1)-- traverseSeq :: forall arrs. Typeable arrs => Level -> Seq arrs -> IO (UnscopedSeq arrs, Int)- traverseSeq lvl acc@(Seq seq)- = mfix $ \ ~(_, height) -> do- -- Compute stable name and enter it into the occurrence map- --- sn <- makeStableAST acc- heightIfRepeatedOccurrence <- enterOcc seqOccMap (StableASTName sn) height-- traceLine (showPreSeqOp seq) $ do- let hash = show (hashStableName sn)- case heightIfRepeatedOccurrence of- Just height -> "REPEATED occurrence (sn = " ++ hash ++ "; height = " ++ show height ++ ")"- Nothing -> "first occurrence (sn = " ++ hash ++ ")"-- -- Reconstruct the computation in shared form.- --- -- In case of a repeated occurrence, the height comes from the occurrence map; otherwise- -- it is computed by the traversal function passed in 'newAcc'. See also 'enterOcc'.- --- -- NB: This function can only be used in the case alternatives below; outside of the- -- case we cannot discharge the 'Arrays arrs' constraint.- --- let producer :: (arrs ~ [a], Arrays a)- => IO (PreSeq UnscopedAcc UnscopedSeq RootExp arrs, Int)- -> IO (UnscopedSeq arrs, Int)- producer newSeq- = case heightIfRepeatedOccurrence of- Just height | recoverSeqSharing config- -> return (UnscopedSeq (SvarSharing (StableNameHeight sn height)), height)- _ -> do (seq, height) <- newSeq- return (UnscopedSeq (SeqSharing (StableNameHeight sn height) seq), height)-- let consumer :: IO (PreSeq UnscopedAcc UnscopedSeq RootExp arrs, Int)- -> IO (UnscopedSeq arrs, Int)- consumer newSeq- = do (seq, height) <- newSeq- return (UnscopedSeq (SeqSharing (StableNameHeight sn height) seq), height)-- case seq of- StreamIn arrs -> producer $ return (StreamIn arrs, 1)- ToSeq sl acc -> producer $ do- (acc', h1) <- traverseAcc lvl acc- return (ToSeq sl acc', h1 + 1)- MapSeq afun s -> producer $ do- (afun', h1) <- traverseAfun1 lvl afun- (s' , h2) <- traverseSeq lvl s- return (MapSeq afun' s', h1 `max` h2 + 1)- ZipWithSeq afun s1 s2 -> producer $ do- (afun', h1) <- traverseAfun2 lvl afun- (s1' , h2) <- traverseSeq lvl s1- (s2' , h3) <- traverseSeq lvl s2- return (ZipWithSeq afun' s1' s2', h1 `max` h2 `max` h3 + 1)- ScanSeq fun e s -> producer $ do- (fun', h1) <- traverseFun2 lvl fun- (e', h2) <- traverseExp lvl e- (s' , h3) <- traverseSeq lvl s- return (ScanSeq fun' e' s', h1 `max` h2 `max` h3 + 1)- FoldSeq fun e s -> consumer $ do- (fun', h1) <- traverseFun2 lvl fun- (e' , h2) <- traverseExp lvl e- (s' , h3) <- traverseSeq lvl s- return (FoldSeq fun' e' s', h1 `max` h2 `max` h3 + 1)- FoldSeqFlatten afun acc s -> consumer $ do- (afun', h1) <- traverseAfun3 lvl afun- (acc', h2) <- traverseAcc lvl acc- (s' , h3) <- traverseSeq lvl s- return (FoldSeqFlatten afun' acc' s', h1 `max` h2 `max` h3 + 1)- Stuple t -> consumer $ do- (t', h1) <- traverseTup lvl t- return (Stuple t', h1 + 1)---}----- Type used to maintain how often each shared subterm, so far, occurred during a bottom-up sweep,--- as well as the relation between subterms. It is comprised of a list of terms and a graph giving--- their relation.------ Invariants of the list:--- - If one shared term 's' is itself a subterm of another shared term 't', then 's' must occur--- *after* 't' in the list.--- - No shared term occurs twice.--- - A term may have a final occurrence count of only 1 iff it is either a free variable ('Atag'--- or 'Tag') or an array computation lifted out of an expression.--- - All 'Exp' node counts precede all 'Acc' node counts as we don't share 'Exp' nodes across 'Acc'--- nodes. Similarly, all 'Seq' nodes precede 'Acc' nodes and 'Exp' nodes precede 'Seq' nodes.------ We determine the subterm property by using the tree height in 'StableNameHeight'. Trees get--- smaller towards the end of a 'NodeCounts' list. The height of free variables ('Atag' or 'Tag')--- is 0, whereas other leaves have height 1. This guarantees that all free variables are at the end--- of the 'NodeCounts' list.------ The graph is represented as a map where a stable name 'a' is mapped to a set of stables names 'b'--- such that if there exists a edge from 'a' to 'c' that 'c' is contained within 'b'.------ Properties of the graph:--- - There exists an edge from 'a' to 'b' if the term 'a' names is a subterm of the term named by--- 'b'.------ To ensure the list invariant and the graph properties are preserved over merging node counts from--- sibling subterms, the function '(+++)' must be used.----type NodeCounts = ([NodeCount], Map.HashMap NodeName (Set.HashSet NodeName))--data NodeName where- NodeName :: Typeable a => StableName a -> NodeName--instance Eq NodeName where- (NodeName sn1) == (NodeName sn2) | Just sn2' <- gcast sn2 = sn1 == sn2'- | otherwise = False--instance Hashable NodeName where- hashWithSalt hash (NodeName sn1) = hash + hashStableName sn1--instance Show NodeName where- show (NodeName sn) = show (hashStableName sn)--data NodeCount = AccNodeCount StableSharingAcc Int- | ExpNodeCount StableSharingExp Int- -- SeqNodeCount StableSharingSeq Int- deriving Show---- Empty node counts----noNodeCounts :: NodeCounts-noNodeCounts = ([], Map.empty)---- Insert an Acc node into the node counts, assuming that it is a superterm of the all the existing--- nodes.------ TODO: Perform cycle detection here.-insertAccNode :: StableSharingAcc -> NodeCounts -> NodeCounts-insertAccNode ssa@(StableSharingAcc (StableNameHeight sn _) _) (subterms,g)- = ([AccNodeCount ssa 1], g') +++ (subterms,g)- where- k = NodeName sn- hs = map nodeName subterms- g' = Map.fromList $ (k, Set.empty) : [(h, Set.singleton k) | h <- hs]---- Insert an Exp node into the node counts, assuming that it is a superterm of the all the existing--- nodes.------ TODO: Perform cycle detection here.-insertExpNode :: StableSharingExp -> NodeCounts -> NodeCounts-insertExpNode ssa@(StableSharingExp (StableNameHeight sn _) _) (subterms,g)- = ([ExpNodeCount ssa 1], g') +++ (subterms,g)- where- k = NodeName sn- hs = map nodeName subterms- g' = Map.fromList $ (k, Set.empty) : [(h, Set.singleton k) | h <- hs]--{----- Insert an Seq node into the node counts, assuming that it is a superterm of the all the existing--- nodes.------ TODO: Perform cycle detection here.-insertSeqNode :: StableSharingSeq -> NodeCounts -> NodeCounts-insertSeqNode ssa@(StableSharingSeq (StableNameHeight sn _) _) (subterms,g)- = ([SeqNodeCount ssa 1], g') +++ (subterms,g)- where- k = NodeName sn- hs = map nodeName subterms- g' = Map.fromList $ (k, Set.empty) : [(h, Set.singleton k) | h <- hs]---}---- Remove nodes that aren't in the list from the graph.------ RCE: This is no longer necessary when NDP is supported.-cleanCounts :: NodeCounts -> NodeCounts-cleanCounts (ns, g) = (ns, Map.fromList $ [(h, Set.filter (flip elem hs) (g Map.! h)) | h <- hs ])- where- hs = (map nodeName ns)--nodeName :: NodeCount -> NodeName-nodeName (AccNodeCount (StableSharingAcc (StableNameHeight sn _) _) _) = NodeName sn-nodeName (ExpNodeCount (StableSharingExp (StableNameHeight sn _) _) _) = NodeName sn--- nodeName (SeqNodeCount (StableSharingSeq (StableNameHeight sn _) _) _) = NodeName sn---- Combine node counts that belong to the same node.------ * We assume that the list invariant —subterms follow their parents— holds for both arguments and--- guarantee that it still holds for the result.--- * In the same manner, we assume that all 'Exp' node counts precede 'Acc' node counts and--- guarantee that this also hold for the result.------ RCE: The list combination should be able to be performed as a more efficient merge.----(+++) :: NodeCounts -> NodeCounts -> NodeCounts-(ns1,g1) +++ (ns2,g2) = (foldr insert ns1 ns2, Map.unionWith Set.union g1 g2)- where- insert x [] = [x]- insert x@(AccNodeCount sa1 count1) ys@(y@(AccNodeCount sa2 count2) : ys')- | sa1 == sa2 = AccNodeCount (sa1 `pickNoneAvar` sa2) (count1 + count2) : ys'- | sa1 `higherSSA` sa2 = x : ys- | otherwise = y : insert x ys'- insert x@(ExpNodeCount se1 count1) ys@(y@(ExpNodeCount se2 count2) : ys')- | se1 == se2 = ExpNodeCount (se1 `pickNoneVar` se2) (count1 + count2) : ys'- | se1 `higherSSE` se2 = x : ys- | otherwise = y : insert x ys'- -- insert x@(SeqNodeCount se1 count1) ys@(y@(SeqNodeCount se2 count2) : ys')- -- | se1 == se2 = SeqNodeCount (se1 `pickNoneSvar` se2) (count1 + count2) : ys'- -- | se1 `higherSSS` se2 = x : ys- -- | otherwise = y : insert x ys'- insert x@(AccNodeCount _ _) (y@(ExpNodeCount _ _) : ys')- = y : insert x ys'- insert x@(ExpNodeCount _ _) (y@(AccNodeCount _ _) : ys')- = x : insert y ys'- -- insert x@(SeqNodeCount _ _) (y@(ExpNodeCount _ _) : ys')- -- = y : insert x ys'- -- insert x@(ExpNodeCount _ _) (y@(SeqNodeCount _ _) : ys')- -- = x : insert y ys'- -- insert x@(AccNodeCount _ _) (y@(SeqNodeCount _ _) : ys')- -- = y : insert x ys'- -- insert x@(SeqNodeCount _ _) (y@(AccNodeCount _ _) : ys')- -- = x : insert y ys'-- (StableSharingAcc _ (AvarSharing _)) `pickNoneAvar` sa2 = sa2- sa1 `pickNoneAvar` _sa2 = sa1-- (StableSharingExp _ (VarSharing _)) `pickNoneVar` sa2 = sa2- sa1 `pickNoneVar` _sa2 = sa1-- -- pickNoneSvar :: StableSharingSeq -> StableSharingSeq -> StableSharingSeq- -- (StableSharingSeq _ (SvarSharing _)) `pickNoneSvar` sa2 = sa2- -- sa1 `pickNoneSvar` _sa2 = sa1---- Build an initial environment for the tag values given in the first argument for traversing an--- array expression. The 'StableSharingAcc's for all tags /actually used/ in the expressions are--- in the second argument. (Tags are not used if a bound variable has no usage occurrence.)------ Bail out if any tag occurs multiple times as this indicates that the sharing of an argument--- variable was not preserved and we cannot build an appropriate initial environment (c.f., comments--- at 'determineScopesAcc'.----buildInitialEnvAcc :: [Level] -> [StableSharingAcc] -> [StableSharingAcc]-buildInitialEnvAcc tags sas = map (lookupSA sas) tags- where- lookupSA sas tag1- = case filter hasTag sas of- [] -> noStableSharing -- tag is not used in the analysed expression- [sa] -> sa -- tag has a unique occurrence- sas2 -> $internalError "buildInitialEnvAcc"- $ "Encountered duplicate 'ATag's\n " ++ intercalate ", " (map showSA sas2)- where- hasTag (StableSharingAcc _ (AccSharing _ (Atag tag2))) = tag1 == tag2- hasTag sa- = $internalError "buildInitialEnvAcc"- $ "Encountered a node that is not a plain 'Atag'\n " ++ showSA sa-- noStableSharing :: StableSharingAcc- noStableSharing = StableSharingAcc noStableAccName (undefined :: SharingAcc acc exp ())-- showSA (StableSharingAcc _ (AccSharing sn acc)) = show (hashStableNameHeight sn) ++ ": " ++- showPreAccOp acc- showSA (StableSharingAcc _ (AvarSharing sn)) = "AvarSharing " ++ show (hashStableNameHeight sn)- showSA (StableSharingAcc _ (AletSharing sa _ )) = "AletSharing " ++ show sa ++ "..."---- Build an initial environment for the tag values given in the first argument for traversing a--- scalar expression. The 'StableSharingExp's for all tags /actually used/ in the expressions are--- in the second argument. (Tags are not used if a bound variable has no usage occurrence.)------ Bail out if any tag occurs multiple times as this indicates that the sharing of an argument--- variable was not preserved and we cannot build an appropriate initial environment (c.f., comments--- at 'determineScopesAcc'.----buildInitialEnvExp :: [Level] -> [StableSharingExp] -> [StableSharingExp]-buildInitialEnvExp tags ses = map (lookupSE ses) tags- where- lookupSE ses tag1- = case filter hasTag ses of- [] -> noStableSharing -- tag is not used in the analysed expression- [se] -> se -- tag has a unique occurrence- ses2 -> $internalError "buildInitialEnvExp"- ("Encountered a duplicate 'Tag'\n " ++ intercalate ", " (map showSE ses2))- where- hasTag (StableSharingExp _ (ExpSharing _ (Tag tag2))) = tag1 == tag2- hasTag se- = $internalError "buildInitialEnvExp"- ("Encountered a node that is not a plain 'Tag'\n " ++ showSE se)-- noStableSharing :: StableSharingExp- noStableSharing = StableSharingExp noStableExpName (undefined :: SharingExp acc exp ())-- showSE (StableSharingExp _ (ExpSharing sn exp)) = show (hashStableNameHeight sn) ++ ": " ++- showPreExpOp exp- showSE (StableSharingExp _ (VarSharing sn)) = "VarSharing " ++ show (hashStableNameHeight sn)- showSE (StableSharingExp _ (LetSharing se _ )) = "LetSharing " ++ show se ++ "..."---- Determine whether a 'NodeCount' is for an 'Atag' or 'Tag', which represent free variables.----isFreeVar :: NodeCount -> Bool-isFreeVar (AccNodeCount (StableSharingAcc _ (AccSharing _ (Atag _))) _) = True-isFreeVar (ExpNodeCount (StableSharingExp _ (ExpSharing _ (Tag _))) _) = True-isFreeVar _ = False----- Determine scope of shared subterms--- ==================================---- Determine the scopes of all variables representing shared subterms (Phase Two) in a bottom-up--- sweep. The first argument determines whether array computations are floated out of expressions--- irrespective of whether they are shared or not — 'True' implies floating them out.------ In addition to the AST with sharing information, yield the 'StableSharingAcc's for all free--- variables of 'rootAcc', which are represented by 'Atag' leaves in the tree. They are in order of--- the tag values — i.e., in the same order that they need to appear in an environment to use the--- tag for indexing into that environment.------ Precondition: there are only 'AvarSharing' and 'AccSharing' nodes in the argument.----determineScopesAcc- :: Typeable a- => Config- -> [Level]- -> OccMap Acc- -> UnscopedAcc a- -> (ScopedAcc a, [StableSharingAcc])-determineScopesAcc config fvs accOccMap rootAcc- = let (sharingAcc, (counts, _)) = determineScopesSharingAcc config accOccMap rootAcc- unboundTrees = filter (not . isFreeVar) counts- in- if all isFreeVar counts- then (sharingAcc, buildInitialEnvAcc fvs [sa | AccNodeCount sa _ <- counts])- else $internalError "determineScopesAcc" ("unbound shared subtrees" ++ show unboundTrees)---determineScopesSharingAcc- :: Config- -> OccMap Acc- -> UnscopedAcc a- -> (ScopedAcc a, NodeCounts)-determineScopesSharingAcc config accOccMap = scopesAcc- where- scopesAcc :: forall arrs. UnscopedAcc arrs -> (ScopedAcc arrs, NodeCounts)- scopesAcc (UnscopedAcc _ (AletSharing _ _))- = $internalError "determineScopesSharingAcc: scopesAcc" "unexpected 'AletSharing'"-- scopesAcc (UnscopedAcc _ (AvarSharing sn))- = (ScopedAcc [] (AvarSharing sn), StableSharingAcc sn (AvarSharing sn) `insertAccNode` noNodeCounts)-- scopesAcc (UnscopedAcc _ (AccSharing sn pacc))- = case pacc of- Atag i -> reconstruct (Atag i) noNodeCounts- Pipe afun1 afun2 acc -> let- (afun1', accCount1) = scopesAfun1 afun1- (afun2', accCount2) = scopesAfun1 afun2- (acc', accCount3) = scopesAcc acc- in- reconstruct (Pipe afun1' afun2' acc')- (accCount1 +++ accCount2 +++ accCount3)-- Aforeign ff afun acc -> let- (acc', accCount) = scopesAcc acc- in- reconstruct (Aforeign ff afun acc') accCount- Acond e acc1 acc2 -> let- (e' , accCount1) = scopesExp e- (acc1', accCount2) = scopesAcc acc1- (acc2', accCount3) = scopesAcc acc2- in- reconstruct (Acond e' acc1' acc2')- (accCount1 +++ accCount2 +++ accCount3)-- Awhile pred iter init -> let- (pred', accCount1) = scopesAfun1 pred- (iter', accCount2) = scopesAfun1 iter- (init', accCount3) = scopesAcc init- in- reconstruct (Awhile pred' iter' init')- (accCount1 +++ accCount2 +++ accCount3)-- Atuple tup -> let (tup', accCount) = travAtup tup- in reconstruct (Atuple tup') accCount- Aprj ix a -> travA (Aprj ix) a-- Use arr -> reconstruct (Use arr) noNodeCounts- Unit e -> let- (e', accCount) = scopesExp e- in- reconstruct (Unit e') accCount- Generate sh f -> let- (sh', accCount1) = scopesExp sh- (f' , accCount2) = scopesFun1 f- in- reconstruct (Generate sh' f') (accCount1 +++ accCount2)- Reshape sh acc -> travEA Reshape sh acc- Replicate n acc -> travEA Replicate n acc- Slice acc i -> travEA (flip Slice) i acc- Map f acc -> let- (f' , accCount1) = scopesFun1 f- (acc', accCount2) = scopesAcc acc- in- reconstruct (Map f' acc') (accCount1 +++ accCount2)- ZipWith f acc1 acc2 -> travF2A2 ZipWith f acc1 acc2- Fold f z acc -> travF2EA Fold f z acc- Fold1 f acc -> travF2A Fold1 f acc- FoldSeg f z acc1 acc2 -> let- (f' , accCount1) = scopesFun2 f- (z' , accCount2) = scopesExp z- (acc1', accCount3) = scopesAcc acc1- (acc2', accCount4) = scopesAcc acc2- in- reconstruct (FoldSeg f' z' acc1' acc2')- (accCount1 +++ accCount2 +++ accCount3 +++ accCount4)- Fold1Seg f acc1 acc2 -> travF2A2 Fold1Seg f acc1 acc2- Scanl f z acc -> travF2EA Scanl f z acc- Scanl' f z acc -> travF2EA Scanl' f z acc- Scanl1 f acc -> travF2A Scanl1 f acc- Scanr f z acc -> travF2EA Scanr f z acc- Scanr' f z acc -> travF2EA Scanr' f z acc- Scanr1 f acc -> travF2A Scanr1 f acc- Permute fc acc1 fp acc2 -> let- (fc' , accCount1) = scopesFun2 fc- (acc1', accCount2) = scopesAcc acc1- (fp' , accCount3) = scopesFun1 fp- (acc2', accCount4) = scopesAcc acc2- in- reconstruct (Permute fc' acc1' fp' acc2')- (accCount1 +++ accCount2 +++ accCount3 +++ accCount4)- Backpermute sh fp acc -> let- (sh' , accCount1) = scopesExp sh- (fp' , accCount2) = scopesFun1 fp- (acc', accCount3) = scopesAcc acc- in- reconstruct (Backpermute sh' fp' acc')- (accCount1 +++ accCount2 +++ accCount3)- Stencil st bnd acc -> let- (st' , accCount1) = scopesStencil1 acc st- (bnd', accCount2) = scopesBoundary bnd- (acc', accCount3) = scopesAcc acc- in- reconstruct (Stencil st' bnd' acc') (accCount1 +++ accCount2 +++ accCount3)- Stencil2 st bnd1 acc1 bnd2 acc2- -> let- (st' , accCount1) = scopesStencil2 acc1 acc2 st- (bnd1', accCount2) = scopesBoundary bnd1- (acc1', accCount3) = scopesAcc acc1- (bnd2', accCount4) = scopesBoundary bnd2- (acc2', accCount5) = scopesAcc acc2- in- reconstruct (Stencil2 st' bnd1' acc1' bnd2' acc2')- (accCount1 +++ accCount2 +++ accCount3 +++ accCount4 +++ accCount5)- -- Collect seq -> let- -- (seq', accCount1) = scopesSeq seq- -- in- -- reconstruct (Collect seq') accCount1-- where- travEA :: (ScopedExp e -> ScopedAcc arrs' -> PreAcc ScopedAcc ScopedExp arrs)- -> RootExp e- -> UnscopedAcc arrs'- -> (ScopedAcc arrs, NodeCounts)- travEA c e acc = reconstruct (c e' acc') (accCount1 +++ accCount2)- where- (e' , accCount1) = scopesExp e- (acc', accCount2) = scopesAcc acc-- travF2A :: (Elt a, Elt b)- => ((Exp a -> Exp b -> ScopedExp c) -> ScopedAcc arrs'- -> PreAcc ScopedAcc ScopedExp arrs)- -> (Exp a -> Exp b -> RootExp c)- -> UnscopedAcc arrs'- -> (ScopedAcc arrs, NodeCounts)- travF2A c f acc = reconstruct (c f' acc') (accCount1 +++ accCount2)- where- (f' , accCount1) = scopesFun2 f- (acc', accCount2) = scopesAcc acc-- travF2EA :: (Elt a, Elt b)- => ((Exp a -> Exp b -> ScopedExp c) -> ScopedExp e- -> ScopedAcc arrs' -> PreAcc ScopedAcc ScopedExp arrs)- -> (Exp a -> Exp b -> RootExp c)- -> RootExp e- -> UnscopedAcc arrs'- -> (ScopedAcc arrs, NodeCounts)- travF2EA c f e acc = reconstruct (c f' e' acc') (accCount1 +++ accCount2 +++ accCount3)- where- (f' , accCount1) = scopesFun2 f- (e' , accCount2) = scopesExp e- (acc', accCount3) = scopesAcc acc-- travF2A2 :: (Elt a, Elt b)- => ((Exp a -> Exp b -> ScopedExp c) -> ScopedAcc arrs1- -> ScopedAcc arrs2 -> PreAcc ScopedAcc ScopedExp arrs)- -> (Exp a -> Exp b -> RootExp c)- -> UnscopedAcc arrs1- -> UnscopedAcc arrs2- -> (ScopedAcc arrs, NodeCounts)- travF2A2 c f acc1 acc2 = reconstruct (c f' acc1' acc2')- (accCount1 +++ accCount2 +++ accCount3)- where- (f' , accCount1) = scopesFun2 f- (acc1', accCount2) = scopesAcc acc1- (acc2', accCount3) = scopesAcc acc2-- travAtup :: Atuple UnscopedAcc a- -> (Atuple ScopedAcc a, NodeCounts)- travAtup NilAtup = (NilAtup, noNodeCounts)- travAtup (SnocAtup tup a) = let (tup', accCountT) = travAtup tup- (a', accCountA) = scopesAcc a- in- (SnocAtup tup' a', accCountT +++ accCountA)-- travA :: (ScopedAcc arrs' -> PreAcc ScopedAcc ScopedExp arrs)- -> UnscopedAcc arrs'- -> (ScopedAcc arrs, NodeCounts)- travA c acc = reconstruct (c acc') accCount- where- (acc', accCount) = scopesAcc acc-- -- Occurrence count of the currently processed node- accOccCount = let StableNameHeight sn' _ = sn- in- lookupWithASTName accOccMap (StableASTName sn')-- -- Reconstruct the current tree node.- --- -- * If the current node is being shared ('accOccCount > 1'), replace it by a 'AvarSharing'- -- node and float the shared subtree out wrapped in a 'NodeCounts' value.- -- * If the current node is not shared, reconstruct it in place.- -- * Special case for free variables ('Atag'): Replace the tree by a sharing variable and- -- float the 'Atag' out in a 'NodeCounts' value. This is independent of the number of- -- occurrences.- --- -- In either case, any completed 'NodeCounts' are injected as bindings using 'AletSharing'- -- node.- --- reconstruct :: PreAcc ScopedAcc ScopedExp arrs- -> NodeCounts- -> (ScopedAcc arrs, NodeCounts)- reconstruct newAcc@(Atag _) _subCount- -- free variable => replace by a sharing variable regardless of the number of- -- occurrences- = let thisCount = StableSharingAcc sn (AccSharing sn newAcc) `insertAccNode` noNodeCounts- in- tracePure "FREE" (show thisCount)- (ScopedAcc [] (AvarSharing sn), thisCount)- reconstruct newAcc subCount- -- shared subtree => replace by a sharing variable (if 'recoverAccSharing' enabled)- | accOccCount > 1 && recoverAccSharing config- = let allCount = (StableSharingAcc sn sharingAcc `insertAccNode` newCount)- in- tracePure ("SHARED" ++ completed) (show allCount)- (ScopedAcc [] (AvarSharing sn), allCount)- -- neither shared nor free variable => leave it as it is- | otherwise- = tracePure ("Normal" ++ completed) (show newCount)- (ScopedAcc [] sharingAcc, newCount)- where- -- Determine the bindings that need to be attached to the current node...- (newCount, bindHere) = filterCompleted subCount-- -- ...and wrap them in 'AletSharing' constructors- lets = foldl (flip (.)) id . map (\x y -> AletSharing x (ScopedAcc [] y)) $ bindHere- sharingAcc = lets $ AccSharing sn newAcc-- -- trace support- completed | null bindHere = ""- | otherwise = "(" ++ show (length bindHere) ++ " lets)"-- -- Extract *leading* nodes that have a complete node count (i.e., their node count is equal- -- to the number of occurrences of that node in the overall expression).- --- -- Nodes with a completed node count should be let bound at the currently processed node.- --- -- NB: Only extract leading nodes (i.e., the longest run at the *front* of the list that is- -- complete). Otherwise, we would let-bind subterms before their parents, which leads- -- scope errors.- --- filterCompleted :: NodeCounts -> (NodeCounts, [StableSharingAcc])- filterCompleted (ns, graph)- = let bindable = map (isBindable bindable (map nodeName ns)) ns- (bind, rest) = partition fst $ zip bindable ns- in ((map snd rest, graph), [sa | AccNodeCount sa _ <- map snd bind])- where- -- a node is not yet complete while the node count 'n' is below the overall number- -- of occurrences for that node in the whole program, with the exception that free- -- variables are never complete- isCompleted nc@(AccNodeCount sa n) | not . isFreeVar $ nc = lookupWithSharingAcc accOccMap sa == n- isCompleted _ = False-- isBindable :: [Bool] -> [NodeName] -> NodeCount -> Bool- isBindable bindable nodes nc@(AccNodeCount _ _) =- let superTerms = Set.toList $ graph Map.! nodeName nc- unbound = mapMaybe (`elemIndex` nodes) superTerms- in isCompleted nc- && all (bindable !!) unbound- isBindable _ _ (ExpNodeCount _ _) = False- -- isBindable _ _ (SeqNodeCount _ _) = False-- -- scopesSeq :: forall arrs. RootSeq arrs -> (ScopedSeq arrs, NodeCounts)- -- scopesSeq = determineScopesSeq config accOccMap-- scopesExp :: RootExp t -> (ScopedExp t, NodeCounts)- scopesExp = determineScopesExp config accOccMap-- -- The lambda bound variable is at this point already irrelevant; for details, see- -- Note [Traversing functions and side effects]- --- scopesAfun1 :: Arrays a1 => (Acc a1 -> UnscopedAcc a2) -> (Acc a1 -> ScopedAcc a2, NodeCounts)- scopesAfun1 f = (const (ScopedAcc ssa body'), (counts',graph))- where- body@(UnscopedAcc fvs _) = f undefined- ((ScopedAcc [] body'), (counts,graph)) = scopesAcc body- ssa = buildInitialEnvAcc fvs [sa | AccNodeCount sa _ <- freeCounts]- (freeCounts, counts') = partition isBoundHere counts-- isBoundHere (AccNodeCount (StableSharingAcc _ (AccSharing _ (Atag i))) _) = i `elem` fvs- isBoundHere _ = False-- -- The lambda bound variable is at this point already irrelevant; for details, see- -- Note [Traversing functions and side effects]- --- scopesFun1 :: Elt e1 => (Exp e1 -> RootExp e2) -> (Exp e1 -> ScopedExp e2, NodeCounts)- scopesFun1 f = (const body, counts)- where- (body, counts) = scopesExp (f undefined)-- -- The lambda bound variable is at this point already irrelevant; for details, see- -- Note [Traversing functions and side effects]- --- scopesFun2 :: (Elt e1, Elt e2)- => (Exp e1 -> Exp e2 -> RootExp e3)- -> (Exp e1 -> Exp e2 -> ScopedExp e3, NodeCounts)- scopesFun2 f = (\_ _ -> body, counts)- where- (body, counts) = scopesExp (f undefined undefined)-- -- The lambda bound variable is at this point already irrelevant; for details, see- -- Note [Traversing functions and side effects]- --- scopesStencil1 :: forall sh e1 e2 stencil. Stencil sh e1 stencil- => UnscopedAcc (Array sh e1){-dummy-}- -> (stencil -> RootExp e2)- -> (stencil -> ScopedExp e2, NodeCounts)- scopesStencil1 _ stencilFun = (const body, counts)- where- (body, counts) = scopesExp (stencilFun undefined)-- -- The lambda bound variable is at this point already irrelevant; for details, see- -- Note [Traversing functions and side effects]- --- scopesStencil2 :: forall sh e1 e2 e3 stencil1 stencil2.- (Stencil sh e1 stencil1, Stencil sh e2 stencil2)- => UnscopedAcc (Array sh e1){-dummy-}- -> UnscopedAcc (Array sh e2){-dummy-}- -> (stencil1 -> stencil2 -> RootExp e3)- -> (stencil1 -> stencil2 -> ScopedExp e3, NodeCounts)- scopesStencil2 _ _ stencilFun = (\_ _ -> body, counts)- where- (body, counts) = scopesExp (stencilFun undefined undefined)-- scopesBoundary :: PreBoundary UnscopedAcc RootExp t- -> (PreBoundary ScopedAcc ScopedExp t, NodeCounts)- scopesBoundary bndy =- case bndy of- Clamp -> (Clamp, noNodeCounts)- Mirror -> (Mirror, noNodeCounts)- Wrap -> (Wrap, noNodeCounts)- Constant v -> (Constant v, noNodeCounts)- Function f -> let (body, counts) = scopesFun1 f- in (Function body, counts)---determineScopesExp- :: Config- -> OccMap Acc- -> RootExp t- -> (ScopedExp t, NodeCounts) -- Root (closed) expression plus Acc node counts-determineScopesExp config accOccMap (RootExp expOccMap exp@(UnscopedExp fvs _))- = let- ((ScopedExp [] expWithScopes), (nodeCounts,graph)) = determineScopesSharingExp config accOccMap expOccMap exp- (expCounts, accCounts) = partition isExpNodeCount nodeCounts-- isExpNodeCount ExpNodeCount{} = True- isExpNodeCount _ = False- in- (ScopedExp (buildInitialEnvExp fvs [se | ExpNodeCount se _ <- expCounts]) expWithScopes, cleanCounts (accCounts,graph))---determineScopesSharingExp- :: Config- -> OccMap Acc- -> OccMap Exp- -> UnscopedExp t- -> (ScopedExp t, NodeCounts)-determineScopesSharingExp config accOccMap expOccMap = scopesExp- where- scopesAcc :: UnscopedAcc a -> (ScopedAcc a, NodeCounts)- scopesAcc = determineScopesSharingAcc config accOccMap-- scopesFun1 :: (Exp a -> UnscopedExp b) -> (Exp a -> ScopedExp b, NodeCounts)- scopesFun1 f = tracePure ("LAMBDA " ++ (show ssa)) (show counts) (const (ScopedExp ssa body'), (counts',graph))- where- body@(UnscopedExp fvs _) = f undefined- ((ScopedExp [] body'), (counts, graph)) = scopesExp body- ssa = buildInitialEnvExp fvs [se | ExpNodeCount se _ <- freeCounts]- (freeCounts, counts') = partition isBoundHere counts-- isBoundHere (ExpNodeCount (StableSharingExp _ (ExpSharing _ (Tag i))) _) = i `elem` fvs- isBoundHere _ = False--- scopesExp :: forall t. UnscopedExp t -> (ScopedExp t, NodeCounts)- scopesExp (UnscopedExp _ (LetSharing _ _))- = $internalError "determineScopesSharingExp: scopesExp" "unexpected 'LetSharing'"-- scopesExp (UnscopedExp _ (VarSharing sn))- = (ScopedExp [] (VarSharing sn), StableSharingExp sn (VarSharing sn) `insertExpNode` noNodeCounts)-- scopesExp (UnscopedExp _ (ExpSharing sn pexp))- = case pexp of- Tag i -> reconstruct (Tag i) noNodeCounts- Const c -> reconstruct (Const c) noNodeCounts- Tuple tup -> let (tup', accCount) = travTup tup- in- reconstruct (Tuple tup') accCount- Prj i e -> travE1 (Prj i) e- IndexNil -> reconstruct IndexNil noNodeCounts- IndexCons ix i -> travE2 IndexCons ix i- IndexHead i -> travE1 IndexHead i- IndexTail ix -> travE1 IndexTail ix- IndexAny -> reconstruct IndexAny noNodeCounts- ToIndex sh ix -> travE2 ToIndex sh ix- FromIndex sh e -> travE2 FromIndex sh e- Cond e1 e2 e3 -> travE3 Cond e1 e2 e3- While p it i -> let- (p' , accCount1) = scopesFun1 p- (it', accCount2) = scopesFun1 it- (i' , accCount3) = scopesExp i- in reconstruct (While p' it' i') (accCount1 +++ accCount2 +++ accCount3)- PrimConst c -> reconstruct (PrimConst c) noNodeCounts- PrimApp p e -> travE1 (PrimApp p) e- Index a e -> travAE Index a e- LinearIndex a e -> travAE LinearIndex a e- Shape a -> travA Shape a- ShapeSize e -> travE1 ShapeSize e- Intersect sh1 sh2 -> travE2 Intersect sh1 sh2- Union sh1 sh2 -> travE2 Union sh1 sh2- Foreign ff f e -> travE1 (Foreign ff f) e- where- travTup :: Tuple UnscopedExp tup -> (Tuple ScopedExp tup, NodeCounts)- travTup NilTup = (NilTup, noNodeCounts)- travTup (SnocTup tup e) = let- (tup', accCountT) = travTup tup- (e' , accCountE) = scopesExp e- in- (SnocTup tup' e', accCountT +++ accCountE)-- travE1 :: (ScopedExp a -> PreExp ScopedAcc ScopedExp t) -> UnscopedExp a- -> (ScopedExp t, NodeCounts)- travE1 c e = reconstruct (c e') accCount- where- (e', accCount) = scopesExp e-- travE2 :: (ScopedExp a -> ScopedExp b -> PreExp ScopedAcc ScopedExp t)- -> UnscopedExp a- -> UnscopedExp b- -> (ScopedExp t, NodeCounts)- travE2 c e1 e2 = reconstruct (c e1' e2') (accCount1 +++ accCount2)- where- (e1', accCount1) = scopesExp e1- (e2', accCount2) = scopesExp e2-- travE3 :: (ScopedExp a -> ScopedExp b -> ScopedExp c -> PreExp ScopedAcc ScopedExp t)- -> UnscopedExp a- -> UnscopedExp b- -> UnscopedExp c- -> (ScopedExp t, NodeCounts)- travE3 c e1 e2 e3 = reconstruct (c e1' e2' e3') (accCount1 +++ accCount2 +++ accCount3)- where- (e1', accCount1) = scopesExp e1- (e2', accCount2) = scopesExp e2- (e3', accCount3) = scopesExp e3-- travA :: (ScopedAcc a -> PreExp ScopedAcc ScopedExp t) -> UnscopedAcc a- -> (ScopedExp t, NodeCounts)- travA c acc = maybeFloatOutAcc c acc' accCount- where- (acc', accCount) = scopesAcc acc-- travAE :: (ScopedAcc a -> ScopedExp b -> PreExp ScopedAcc ScopedExp t)- -> UnscopedAcc a- -> UnscopedExp b- -> (ScopedExp t, NodeCounts)- travAE c acc e = maybeFloatOutAcc (`c` e') acc' (accCountA +++ accCountE)- where- (acc', accCountA) = scopesAcc acc- (e' , accCountE) = scopesExp e-- maybeFloatOutAcc :: (ScopedAcc a -> PreExp ScopedAcc ScopedExp t)- -> ScopedAcc a- -> NodeCounts- -> (ScopedExp t, NodeCounts)- maybeFloatOutAcc c acc@(ScopedAcc _ (AvarSharing _)) accCount -- nothing to float out- = reconstruct (c acc) accCount- maybeFloatOutAcc c acc accCount- | floatOutAcc config = reconstruct (c var) ((stableAcc `insertAccNode` noNodeCounts) +++ accCount)- | otherwise = reconstruct (c acc) accCount- where- (var, stableAcc) = abstract acc (\(ScopedAcc _ s) -> s)-- abstract :: ScopedAcc a -> (ScopedAcc a -> SharingAcc ScopedAcc ScopedExp a)- -> (ScopedAcc a, StableSharingAcc)- abstract (ScopedAcc _ (AvarSharing _)) _ = $internalError "sharingAccToVar" "AvarSharing"- abstract (ScopedAcc ssa (AletSharing sa acc)) lets = abstract acc (lets . (\x -> ScopedAcc ssa (AletSharing sa x)))- abstract acc@(ScopedAcc ssa (AccSharing sn _)) lets = (ScopedAcc ssa (AvarSharing sn), StableSharingAcc sn (lets acc))-- -- Occurrence count of the currently processed node- expOccCount = let StableNameHeight sn' _ = sn- in- lookupWithASTName expOccMap (StableASTName sn')-- -- Reconstruct the current tree node.- --- -- * If the current node is being shared ('expOccCount > 1'), replace it by a 'VarSharing'- -- node and float the shared subtree out wrapped in a 'NodeCounts' value.- -- * If the current node is not shared, reconstruct it in place.- -- * Special case for free variables ('Tag'): Replace the tree by a sharing variable and- -- float the 'Tag' out in a 'NodeCounts' value. This is independent of the number of- -- occurrences.- --- -- In either case, any completed 'NodeCounts' are injected as bindings using 'LetSharing'- -- node.- --- reconstruct :: PreExp ScopedAcc ScopedExp t -> NodeCounts- -> (ScopedExp t, NodeCounts)- reconstruct newExp@(Tag _) _subCount- -- free variable => replace by a sharing variable regardless of the number of- -- occurrences- = let thisCount = StableSharingExp sn (ExpSharing sn newExp) `insertExpNode` noNodeCounts- in- tracePure "FREE" (show thisCount)- (ScopedExp [] (VarSharing sn), thisCount)- reconstruct newExp subCount- -- shared subtree => replace by a sharing variable (if 'recoverExpSharing' enabled)- | expOccCount > 1 && recoverExpSharing config- = let allCount = StableSharingExp sn sharingExp `insertExpNode` newCount- in- tracePure ("SHARED" ++ completed) (show allCount)- (ScopedExp [] (VarSharing sn), allCount)- -- neither shared nor free variable => leave it as it is- | otherwise- = tracePure ("Normal" ++ completed) (show newCount)- (ScopedExp [] sharingExp, newCount)- where- -- Determine the bindings that need to be attached to the current node...- (newCount, bindHere) = filterCompleted subCount-- -- ...and wrap them in 'LetSharing' constructors- lets = foldl (flip (.)) id . map (\x y -> LetSharing x (ScopedExp [] y)) $ bindHere- sharingExp = lets $ ExpSharing sn newExp-- -- trace support- completed | null bindHere = ""- | otherwise = "(" ++ show (length bindHere) ++ " lets)"-- -- Extract *leading* nodes that have a complete node count (i.e., their node count is equal- -- to the number of occurrences of that node in the overall expression).- --- -- Nodes with a completed node count should be let bound at the currently processed node.- --- -- NB: Only extract leading nodes (i.e., the longest run at the *front* of the list that is- -- complete). Otherwise, we would let-bind subterms before their parents, which leads- -- scope errors.- --- filterCompleted :: NodeCounts -> (NodeCounts, [StableSharingExp])- filterCompleted (ns,graph)- = let bindable = map (isBindable bindable (map nodeName ns)) ns- (bind, unbind) = partition fst $ zip bindable ns- in ((map snd unbind, graph), [se | ExpNodeCount se _ <- map snd bind])- where- -- a node is not yet complete while the node count 'n' is below the overall number- -- of occurrences for that node in the whole program, with the exception that free- -- variables are never complete- isCompleted nc@(ExpNodeCount sa n) | not . isFreeVar $ nc = lookupWithSharingExp expOccMap sa == n- isCompleted _ = False-- isBindable :: [Bool] -> [NodeName] -> NodeCount -> Bool- isBindable bindable nodes nc@(ExpNodeCount _ _) =- let superTerms = Set.toList $ graph Map.! nodeName nc- unbound = mapMaybe (`elemIndex` nodes) superTerms- in isCompleted nc- && all (bindable !!) unbound- isBindable _ _ (AccNodeCount _ _) = False- -- isBindable _ _ (SeqNodeCount _ _) = False--{---determineScopesSeq- :: Config- -> OccMap Acc- -> RootSeq t- -> (ScopedSeq t, NodeCounts) -- Root (closed) expression plus Acc node counts-determineScopesSeq config accOccMap (RootSeq seqOccMap seq)- = let- (ScopedSeq seqWithScopes, (nodeCounts,graph)) = determineScopesSharingSeq config accOccMap seqOccMap seq- binds = [s | SeqNodeCount s _ <- nodeCounts]- lets = foldl (flip (.)) id . map (\x y -> SletSharing x (ScopedSeq y)) $ binds- sharingSeq = lets seqWithScopes- newCounts = filter (not . isSeqCount) nodeCounts- isSeqCount SeqNodeCount{} = True- isSeqCount _ = False- in- (ScopedSeq sharingSeq, cleanCounts (newCounts,graph))--determineScopesSharingSeq- :: Config- -> OccMap Acc- -> OccMap Seq- -> UnscopedSeq t- -> (ScopedSeq t, NodeCounts)-determineScopesSharingSeq config accOccMap _seqOccMap = scopesSeq- where- scopesAcc :: UnscopedAcc a -> (ScopedAcc a, NodeCounts)- scopesAcc = determineScopesSharingAcc config accOccMap-- scopesExp :: RootExp t -> (ScopedExp t, NodeCounts)- scopesExp = determineScopesExp config accOccMap-- scopesFun2 :: (Elt e1, Elt e2)- => (Exp e1 -> Exp e2 -> RootExp e3)- -> (Exp e1 -> Exp e2 -> ScopedExp e3, NodeCounts)- scopesFun2 f = (\_ _ -> body, counts)- where- (body, counts) = scopesExp (f undefined undefined)-- -- The lambda bound variable is at this point already irrelevant; for details, see- -- Note [Traversing functions and side effects]- --- scopesAfun1 :: Arrays a1 => (Acc a1 -> UnscopedAcc a2) -> (Acc a1 -> ScopedAcc a2, NodeCounts)- scopesAfun1 f = (const (ScopedAcc ssa body'), (counts',graph))- where- body@(UnscopedAcc fvs _) = f undefined- ((ScopedAcc [] body'), (counts,graph)) = scopesAcc body- ssa = buildInitialEnvAcc fvs [sa | AccNodeCount sa _ <- freeCounts]- (freeCounts, counts') = partition isBoundHere counts-- isBoundHere (AccNodeCount (StableSharingAcc _ (AccSharing _ (Atag i))) _) = i `elem` fvs- isBoundHere _ = False-- scopesAfun2 :: (Arrays a1, Arrays a2) => (Acc a1 -> Acc a2 -> UnscopedAcc a3) -> (Acc a1 -> Acc a2 -> ScopedAcc a3, NodeCounts)- scopesAfun2 f = (\ _ _ -> (ScopedAcc ssa body'), (counts',graph))- where- body@(UnscopedAcc fvs _) = f undefined undefined- ((ScopedAcc [] body'), (counts,graph)) = scopesAcc body- ssa = buildInitialEnvAcc fvs [sa | AccNodeCount sa _ <- freeCounts]- (freeCounts, counts') = partition isBoundHere counts-- isBoundHere (AccNodeCount (StableSharingAcc _ (AccSharing _ (Atag i))) _) = i `elem` fvs- isBoundHere _ = False-- scopesAfun3 :: (Arrays a1, Arrays a2, Arrays a3) => (Acc a1 -> Acc a2 -> Acc a3 -> UnscopedAcc a4) -> (Acc a1 -> Acc a2 -> Acc a3 -> ScopedAcc a4, NodeCounts)- scopesAfun3 f = (\ _ _ _ -> (ScopedAcc ssa body'), (counts',graph))- where- body@(UnscopedAcc fvs _) = f undefined undefined undefined- ((ScopedAcc [] body'), (counts,graph)) = scopesAcc body- ssa = buildInitialEnvAcc fvs [sa | AccNodeCount sa _ <- freeCounts]- (freeCounts, counts') = partition isBoundHere counts-- isBoundHere (AccNodeCount (StableSharingAcc _ (AccSharing _ (Atag i))) _) = i `elem` fvs- isBoundHere _ = False-- scopesTup :: Atuple UnscopedSeq tup -> (Atuple ScopedSeq tup, NodeCounts)- scopesTup NilAtup = (NilAtup, noNodeCounts)- scopesTup (SnocAtup tup s) = let- (tup', accCountT) = scopesTup tup- (s' , accCountS) = scopesSeq s- in- (SnocAtup tup' s', accCountT +++ accCountS)-- scopesSeq :: forall t. UnscopedSeq t -> (ScopedSeq t, NodeCounts)- scopesSeq (UnscopedSeq (SletSharing _ _))- = $internalError "determineScopesSharingSeq: scopesSeq" "unexpected 'LetSharing'"- scopesSeq (UnscopedSeq (SvarSharing sn))- = (ScopedSeq (SvarSharing sn), StableSharingSeq sn (SvarSharing sn) `insertSeqNode` noNodeCounts)-- scopesSeq (UnscopedSeq (SeqSharing sn s)) =- case s of- StreamIn arrs -> producer (StreamIn arrs) noNodeCounts- ToSeq sl acc -> let- (acc', accCount1) = scopesAcc acc- in producer (ToSeq sl acc') accCount1- MapSeq afun s' -> let- (afun', accCount1) = scopesAfun1 afun- (s'' , accCount2) = scopesSeq s'- in producer (MapSeq afun' s'') (accCount1 +++ accCount2)- ZipWithSeq afun s1 s2 -> let- (afun', accCount1) = scopesAfun2 afun- (s1' , accCount2) = scopesSeq s1- (s2' , accCount3) = scopesSeq s2- in producer (ZipWithSeq afun' s1' s2') (accCount1 +++ accCount2 +++ accCount3)- ScanSeq fun e s' -> let- (fun', accCount1) = scopesFun2 fun- (e' , accCount2) = scopesExp e- (s'' , accCount3) = scopesSeq s'- in producer (ScanSeq fun' e' s'') (accCount1 +++ accCount2 +++ accCount3)- FoldSeq fun e s' -> let- (fun', accCount1) = scopesFun2 fun- (e' , accCount2) = scopesExp e- (s'' , accCount3) = scopesSeq s'- in consumer (FoldSeq fun' e' s'') (accCount1 +++ accCount2 +++ accCount3)- FoldSeqFlatten afun acc s' ->- let- (afun', accCount1) = scopesAfun3 afun- (acc' , accCount2) = scopesAcc acc- (s'' , accCount3) = scopesSeq s'- in consumer (FoldSeqFlatten afun' acc' s'') (accCount1 +++ accCount2 +++ accCount3)- Stuple tup -> let- (tup', accCount1) = scopesTup tup- in consumer (Stuple tup') accCount1- where- -- All producers must be replaced by sharing variables- --- producer :: (t ~ [a], Arrays a)- => PreSeq ScopedAcc ScopedSeq ScopedExp t- -> NodeCounts- -> (ScopedSeq t, NodeCounts)- producer newSeq subCount- = let allCount = StableSharingSeq sn (SeqSharing sn newSeq) `insertSeqNode` subCount- in- tracePure "Producer" (show allCount)- (ScopedSeq (SvarSharing sn), allCount)-- -- Consumers cannot be shared.- --- consumer :: PreSeq ScopedAcc ScopedSeq ScopedExp t- -> NodeCounts- -> (ScopedSeq t, NodeCounts)- consumer newSeq subCount- = tracePure "Consumer" (show subCount)- (ScopedSeq (SeqSharing sn newSeq), subCount)---}---- |Recover sharing information and annotate the HOAS AST with variable and let binding--- annotations. The first argument determines whether array computations are floated out of--- expressions irrespective of whether they are shared or not — 'True' implies floating them out.------ Also returns the 'StableSharingAcc's of all 'Atag' leaves in environment order — they represent--- the free variables of the AST.------ NB: Strictly speaking, this function is not deterministic, as it uses stable pointers to--- determine the sharing of subterms. The stable pointer API does not guarantee its--- completeness; i.e., it may miss some equalities, which implies that we may fail to discover--- some sharing. However, sharing does not affect the denotational meaning of an array--- computation; hence, we do not compromise denotational correctness.------ There is one caveat: We currently rely on the 'Atag' and 'Tag' leaves representing free--- variables to be shared if any of them is used more than once. If one is duplicated, the--- environment for de Bruijn conversion will have a duplicate entry, and hence, be of the wrong--- size, which is fatal. (The 'buildInitialEnv*' functions will already bail out.)----{-# NOINLINE recoverSharingAcc #-}-recoverSharingAcc- :: Typeable a- => Config- -> Level -- The level of currently bound array variables- -> [Level] -- The tags of newly introduced free array variables- -> Acc a- -> (ScopedAcc a, [StableSharingAcc])-recoverSharingAcc config alvl avars acc- = let (acc', occMap)- = unsafePerformIO -- to enable stable pointers; this is safe as explained above- $ makeOccMapAcc config alvl acc- in- determineScopesAcc config avars occMap acc'---{-# NOINLINE recoverSharingExp #-}-recoverSharingExp- :: Typeable e- => Config- -> Level -- The level of currently bound scalar variables- -> [Level] -- The tags of newly introduced free scalar variables- -> Exp e- -> (ScopedExp e, [StableSharingExp])-recoverSharingExp config lvl fvar exp- = let- (rootExp, accOccMap) = unsafePerformIO $ do- accOccMap <- newASTHashTable- (exp', _) <- makeOccMapRootExp config accOccMap lvl fvar exp- frozenAccOccMap <- freezeOccMap accOccMap-- return (exp', frozenAccOccMap)-- (ScopedExp sse sharingExp, _) =- determineScopesExp config accOccMap rootExp- in- (ScopedExp [] sharingExp, sse)---{---{-# NOINLINE recoverSharingSeq #-}-recoverSharingSeq- :: Typeable e- => Config- -> Seq e- -> (ScopedSeq e, [StableSharingSeq])-recoverSharingSeq config seq- = let- (rootSeq, accOccMap) = unsafePerformIO $ do- accOccMap <- newASTHashTable- (seq', _) <- makeOccMapRootSeq config accOccMap 0 seq- frozenAccOccMap <- freezeOccMap accOccMap-- return (seq', frozenAccOccMap)-- (ScopedSeq sharingSeq, (ns, _)) =- determineScopesSeq config accOccMap rootSeq- in- (ScopedSeq sharingSeq, [a | SeqNodeCount a _ <- ns])---}----- Debugging--- -----------traceLine :: String -> String -> IO ()-traceLine header msg- = Debug.traceIO Debug.dump_sharing- $ header ++ ": " ++ msg--traceChunk :: String -> String -> IO ()-traceChunk header msg- = Debug.traceIO Debug.dump_sharing- $ header ++ "\n " ++ msg--tracePure :: String -> String -> a -> a-tracePure header msg- = Debug.trace Debug.dump_sharing- $ header ++ ": " ++ msg-
− Data/Array/Accelerate/Trafo/Shrink.hs
@@ -1,481 +0,0 @@-{-# LANGUAGE GADTs #-}-{-# LANGUAGE PatternGuards #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE ViewPatterns #-}--- |--- Module : Data.Array.Accelerate.Trafo.Shrink--- Copyright : [2012..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)------ The shrinking substitution arises as a restriction of beta-reduction to cases--- where the bound variable is used zero (dead-code elimination) or one (linear--- inlining) times. By simplifying terms, the shrinking reduction can expose--- opportunities for further optimisation.------ TODO: replace with a linear shrinking algorithm; e.g.------ * Andrew Appel & Trevor Jim, "Shrinking lambda expressions in linear time".------ * Nick Benton, Andrew Kennedy, Sam Lindley and Claudio Russo, "Shrinking--- Reductions in SML.NET"-----module Data.Array.Accelerate.Trafo.Shrink (-- -- Shrinking- Shrink(..),- ShrinkAcc, shrinkPreAcc, basicReduceAcc,-- -- Occurrence counting- UsesOfAcc, usesOfPreAcc, usesOfExp,--) where---- standard library-import Data.Monoid-import Control.Applicative hiding ( Const )-import Prelude hiding ( exp, seq )---- friends-import Data.Array.Accelerate.AST-import Data.Array.Accelerate.Array.Sugar hiding ( Any )-import Data.Array.Accelerate.Trafo.Base-import Data.Array.Accelerate.Trafo.Substitution--import qualified Data.Array.Accelerate.Debug as Stats---class Shrink f where- shrink :: f -> f- shrink' :: f -> (Bool, f)-- shrink = snd . shrink'--instance Kit acc => Shrink (PreOpenExp acc env aenv e) where- shrink' = shrinkExp--instance Kit acc => Shrink (PreOpenFun acc env aenv f) where- shrink' = shrinkFun----- Shrinking--- =========---- The shrinking substitution for scalar expressions. This is a restricted--- instance of beta-reduction to cases where the bound variable is used zero--- (dead-code elimination) or one (linear inlining) times.----shrinkExp :: Kit acc => PreOpenExp acc env aenv t -> (Bool, PreOpenExp acc env aenv t)-shrinkExp = Stats.substitution "shrink exp" . first getAny . shrinkE- where- -- If the bound variable is used at most this many times, it will be inlined- -- into the body. In cases where it is not used at all, this is equivalent- -- to dead-code elimination.- --- lIMIT :: Int- lIMIT = 1-- shrinkE :: Kit acc => PreOpenExp acc env aenv t -> (Any, PreOpenExp acc env aenv t)- shrinkE exp = case exp of- Let bnd body- | Var _ <- bnd -> Stats.inline "Var" . yes $ shrinkE (inline body bnd)- | uses <= lIMIT -> Stats.betaReduce msg . yes $ shrinkE (inline (snd body') (snd bnd'))- | otherwise -> Let <$> bnd' <*> body'- where- bnd' = shrinkE bnd- body' = shrinkE body- uses = usesOfExp ZeroIdx (snd body')-- msg = case uses of- 0 -> "dead exp"- _ -> "inline exp" -- forced inlining when lIMIT > 1- --- Var idx -> pure (Var idx)- Const c -> pure (Const c)- Tuple t -> Tuple <$> shrinkT t- Prj tup e -> Prj tup <$> shrinkE e- IndexNil -> pure IndexNil- IndexCons sl sz -> IndexCons <$> shrinkE sl <*> shrinkE sz- IndexHead sh -> IndexHead <$> shrinkE sh- IndexTail sh -> IndexTail <$> shrinkE sh- IndexSlice x ix sh -> IndexSlice x <$> shrinkE ix <*> shrinkE sh- IndexFull x ix sl -> IndexFull x <$> shrinkE ix <*> shrinkE sl- IndexAny -> pure IndexAny- ToIndex sh ix -> ToIndex <$> shrinkE sh <*> shrinkE ix- FromIndex sh i -> FromIndex <$> shrinkE sh <*> shrinkE i- Cond p t e -> Cond <$> shrinkE p <*> shrinkE t <*> shrinkE e- While p f x -> While <$> shrinkF p <*> shrinkF f <*> shrinkE x- PrimConst c -> pure (PrimConst c)- PrimApp f x -> PrimApp f <$> shrinkE x- Index a sh -> Index a <$> shrinkE sh- LinearIndex a i -> LinearIndex a <$> shrinkE i- Shape a -> pure (Shape a)- ShapeSize sh -> ShapeSize <$> shrinkE sh- Intersect sh sz -> Intersect <$> shrinkE sh <*> shrinkE sz- Union sh sz -> Union <$> shrinkE sh <*> shrinkE sz- Foreign ff f e -> Foreign ff <$> shrinkF f <*> shrinkE e-- shrinkT :: Kit acc => Tuple (PreOpenExp acc env aenv) t -> (Any, Tuple (PreOpenExp acc env aenv) t)- shrinkT NilTup = pure NilTup- shrinkT (SnocTup t e) = SnocTup <$> shrinkT t <*> shrinkE e-- shrinkF :: Kit acc => PreOpenFun acc env aenv t -> (Any, PreOpenFun acc env aenv t)- shrinkF = first Any . shrinkFun-- first :: (a -> a') -> (a,b) -> (a',b)- first f (x,y) = (f x, y)-- yes :: (Any, x) -> (Any, x)- yes (_, x) = (Any True, x)--shrinkFun :: Kit acc => PreOpenFun acc env aenv f -> (Bool, PreOpenFun acc env aenv f)-shrinkFun (Lam f) = Lam <$> shrinkFun f-shrinkFun (Body b) = Body <$> shrinkExp b----- The shrinking substitution for array computations. This is further limited to--- dead-code elimination only, primarily because linear inlining may inline--- array computations into scalar expressions, which is generally not desirable.----type ShrinkAcc acc = forall aenv a. acc aenv a -> acc aenv a-type ReduceAcc acc = forall aenv s t. acc aenv s -> acc (aenv,s) t -> Maybe (PreOpenAcc acc aenv t)--shrinkPreAcc- :: forall acc aenv arrs. ShrinkAcc acc -> ReduceAcc acc- -> PreOpenAcc acc aenv arrs- -> PreOpenAcc acc aenv arrs-shrinkPreAcc shrinkAcc reduceAcc = Stats.substitution "shrink acc" shrinkA- where- shrinkA :: PreOpenAcc acc aenv' a -> PreOpenAcc acc aenv' a- shrinkA pacc = case pacc of- Alet bnd body- | Just reduct <- reduceAcc bnd' body' -> shrinkA reduct- | otherwise -> Alet bnd' body'- where- bnd' = shrinkAcc bnd- body' = shrinkAcc body- --- Avar ix -> Avar ix- Atuple tup -> Atuple (shrinkAT tup)- Aprj tup a -> Aprj tup (shrinkAcc a)- Apply f a -> Apply (shrinkAF f) (shrinkAcc a)- Aforeign ff af a -> Aforeign ff af (shrinkAcc a)- Acond p t e -> Acond (shrinkE p) (shrinkAcc t) (shrinkAcc e)- Awhile p f a -> Awhile (shrinkAF p) (shrinkAF f) (shrinkAcc a)- Use a -> Use a- Unit e -> Unit (shrinkE e)- Reshape e a -> Reshape (shrinkE e) (shrinkAcc a)- Generate e f -> Generate (shrinkE e) (shrinkF f)- Transform sh ix f a -> Transform (shrinkE sh) (shrinkF ix) (shrinkF f) (shrinkAcc a)- Replicate sl slix a -> Replicate sl (shrinkE slix) (shrinkAcc a)- Slice sl a slix -> Slice sl (shrinkAcc a) (shrinkE slix)- Map f a -> Map (shrinkF f) (shrinkAcc a)- ZipWith f a1 a2 -> ZipWith (shrinkF f) (shrinkAcc a1) (shrinkAcc a2)- Fold f z a -> Fold (shrinkF f) (shrinkE z) (shrinkAcc a)- Fold1 f a -> Fold1 (shrinkF f) (shrinkAcc a)- FoldSeg f z a b -> FoldSeg (shrinkF f) (shrinkE z) (shrinkAcc a) (shrinkAcc b)- Fold1Seg f a b -> Fold1Seg (shrinkF f) (shrinkAcc a) (shrinkAcc b)- Scanl f z a -> Scanl (shrinkF f) (shrinkE z) (shrinkAcc a)- Scanl' f z a -> Scanl' (shrinkF f) (shrinkE z) (shrinkAcc a)- Scanl1 f a -> Scanl1 (shrinkF f) (shrinkAcc a)- Scanr f z a -> Scanr (shrinkF f) (shrinkE z) (shrinkAcc a)- Scanr' f z a -> Scanr' (shrinkF f) (shrinkE z) (shrinkAcc a)- Scanr1 f a -> Scanr1 (shrinkF f) (shrinkAcc a)- Permute f1 a1 f2 a2 -> Permute (shrinkF f1) (shrinkAcc a1) (shrinkF f2) (shrinkAcc a2)- Backpermute sh f a -> Backpermute (shrinkE sh) (shrinkF f) (shrinkAcc a)- Stencil f b a -> Stencil (shrinkF f) b (shrinkAcc a)- Stencil2 f b1 a1 b2 a2 -> Stencil2 (shrinkF f) b1 (shrinkAcc a1) b2 (shrinkAcc a2)- -- Collect s -> Collect (shrinkS s)--{--- shrinkS :: PreOpenSeq acc aenv' senv a -> PreOpenSeq acc aenv' senv a- shrinkS seq =- case seq of- Producer p s -> Producer (shrinkP p) (shrinkS s)- Consumer c -> Consumer (shrinkC c)- Reify ix -> Reify ix-- shrinkP :: Producer acc aenv' senv a -> Producer acc aenv' senv a- shrinkP p =- case p of- StreamIn arrs -> StreamIn arrs- ToSeq sl slix a -> ToSeq sl slix (shrinkAcc a)- MapSeq f x -> MapSeq (shrinkAF f) x- ChunkedMapSeq f x -> ChunkedMapSeq (shrinkAF f) x- ZipWithSeq f x y -> ZipWithSeq (shrinkAF f) x y- ScanSeq f e x -> ScanSeq (shrinkF f) (shrinkE e) x-- shrinkC :: Consumer acc aenv' senv a -> Consumer acc aenv' senv a- shrinkC c =- case c of- FoldSeq f e x -> FoldSeq (shrinkF f) (shrinkE e) x- FoldSeqFlatten f a x -> FoldSeqFlatten (shrinkAF f) (shrinkAcc a) x- Stuple t -> Stuple (shrinkCT t)-- shrinkCT :: Atuple (Consumer acc aenv' senv) t -> Atuple (Consumer acc aenv' senv) t- shrinkCT NilAtup = NilAtup- shrinkCT (SnocAtup t c) = SnocAtup (shrinkCT t) (shrinkC c)---}-- shrinkE :: PreOpenExp acc env aenv' t -> PreOpenExp acc env aenv' t- shrinkE exp = case exp of- Let bnd body -> Let (shrinkE bnd) (shrinkE body)- Var idx -> Var idx- Const c -> Const c- Tuple t -> Tuple (shrinkT t)- Prj tup e -> Prj tup (shrinkE e)- IndexNil -> IndexNil- IndexCons sl sz -> IndexCons (shrinkE sl) (shrinkE sz)- IndexHead sh -> IndexHead (shrinkE sh)- IndexTail sh -> IndexTail (shrinkE sh)- IndexSlice x ix sh -> IndexSlice x (shrinkE ix) (shrinkE sh)- IndexFull x ix sl -> IndexFull x (shrinkE ix) (shrinkE sl)- IndexAny -> IndexAny- ToIndex sh ix -> ToIndex (shrinkE sh) (shrinkE ix)- FromIndex sh i -> FromIndex (shrinkE sh) (shrinkE i)- Cond p t e -> Cond (shrinkE p) (shrinkE t) (shrinkE e)- While p f x -> While (shrinkF p) (shrinkF f) (shrinkE x)- PrimConst c -> PrimConst c- PrimApp f x -> PrimApp f (shrinkE x)- Index a sh -> Index (shrinkAcc a) (shrinkE sh)- LinearIndex a i -> LinearIndex (shrinkAcc a) (shrinkE i)- Shape a -> Shape (shrinkAcc a)- ShapeSize sh -> ShapeSize (shrinkE sh)- Intersect sh sz -> Intersect (shrinkE sh) (shrinkE sz)- Union sh sz -> Union (shrinkE sh) (shrinkE sz)- Foreign ff f e -> Foreign ff (shrinkF f) (shrinkE e)-- shrinkF :: PreOpenFun acc env aenv' f -> PreOpenFun acc env aenv' f- shrinkF (Lam f) = Lam (shrinkF f)- shrinkF (Body b) = Body (shrinkE b)-- shrinkT :: Tuple (PreOpenExp acc env aenv') t -> Tuple (PreOpenExp acc env aenv') t- shrinkT NilTup = NilTup- shrinkT (SnocTup t e) = shrinkT t `SnocTup` shrinkE e-- shrinkAT :: Atuple (acc aenv') t -> Atuple (acc aenv') t- shrinkAT NilAtup = NilAtup- shrinkAT (SnocAtup t a) = shrinkAT t `SnocAtup` shrinkAcc a-- shrinkAF :: PreOpenAfun acc aenv' f -> PreOpenAfun acc aenv' f- shrinkAF (Alam f) = Alam (shrinkAF f)- shrinkAF (Abody a) = Abody (shrinkAcc a)----- A somewhat hacky example implementation of the reduction step. It requires a--- function to open the recursive closure of an array term.----basicReduceAcc- :: Kit acc- => (forall aenv a. acc aenv a -> PreOpenAcc acc aenv a)- -> UsesOfAcc acc- -> ReduceAcc acc-basicReduceAcc unwrapAcc countAcc (unwrapAcc -> bnd) body@(unwrapAcc -> pbody)- | Avar _ <- bnd = Stats.inline "Avar" . Just $ rebuildA (subAtop bnd) pbody- | uses <= lIMIT = Stats.betaReduce msg . Just $ rebuildA (subAtop bnd) pbody- | otherwise = Nothing- where- -- If the bound variable is used at most this many times, it will be inlined- -- into the body. Since this implies an array computation could be inlined- -- into a scalar expression, we limit the shrinking reduction for array- -- computations to dead-code elimination only.- --- lIMIT = 0-- uses = countAcc True ZeroIdx body- msg = case uses of- 0 -> "dead acc"- _ -> "inline acc" -- forced inlining when lIMIT > 1----- Occurrence Counting--- ===================---- Count the number of occurrences an in-scope scalar expression bound at the--- given variable index recursively in a term.----usesOfExp :: forall acc env aenv s t. Idx env s -> PreOpenExp acc env aenv t -> Int-usesOfExp idx = countE- where- countE :: PreOpenExp acc env aenv e -> Int- countE exp = case exp of- Var this- | Just Refl <- match this idx -> 1- | otherwise -> 0- --- Let bnd body -> countE bnd + usesOfExp (SuccIdx idx) body- Const _ -> 0- Tuple t -> countT t- Prj _ e -> countE e- IndexNil -> 0- IndexCons sl sz -> countE sl + countE sz- IndexHead sh -> countE sh- IndexTail sh -> countE sh- IndexSlice _ ix sh -> countE ix + countE sh- IndexFull _ ix sl -> countE ix + countE sl- IndexAny -> 0- ToIndex sh ix -> countE sh + countE ix- FromIndex sh i -> countE sh + countE i- Cond p t e -> countE p + countE t + countE e- While p f x -> countE x + countF idx p + countF idx f- PrimConst _ -> 0- PrimApp _ x -> countE x- Index _ sh -> countE sh- LinearIndex _ i -> countE i- Shape _ -> 0- ShapeSize sh -> countE sh- Intersect sh sz -> countE sh + countE sz- Union sh sz -> countE sh + countE sz- Foreign _ _ e -> countE e-- countF :: Idx env' s -> PreOpenFun acc env' aenv f -> Int- countF idx' (Lam f) = countF (SuccIdx idx') f- countF idx' (Body b) = usesOfExp idx' b-- countT :: Tuple (PreOpenExp acc env aenv) e -> Int- countT NilTup = 0- countT (SnocTup t e) = countT t + countE e----- Count the number of occurrences of the array term bound at the given--- environment index. If the first argument is 'True' then it includes in the--- total uses of the variable for 'Shape' information, otherwise not.----type UsesOfAcc acc = forall aenv s t. Bool -> Idx aenv s -> acc aenv t -> Int--usesOfPreAcc- :: forall acc aenv s t.- Bool- -> UsesOfAcc acc- -> Idx aenv s- -> PreOpenAcc acc aenv t- -> Int-usesOfPreAcc withShape countAcc idx = count- where- countIdx :: Idx aenv a -> Int- countIdx this- | Just Refl <- match this idx = 1- | otherwise = 0-- count :: PreOpenAcc acc aenv a -> Int- count pacc = case pacc of- Avar this -> countIdx this- --- Alet bnd body -> countA bnd + countAcc withShape (SuccIdx idx) body- Atuple tup -> countAT tup- Aprj _ a -> countA a -- special case discount?- Apply _ a -> countA a- Aforeign _ _ a -> countA a- Acond p t e -> countE p + countA t + countA e- Awhile _ _ a -> countA a- Use _ -> 0- Unit e -> countE e- Reshape e a -> countE e + countA a- Generate e f -> countE e + countF f- Transform sh ix f a -> countE sh + countF ix + countF f + countA a- Replicate _ sh a -> countE sh + countA a- Slice _ a sl -> countE sl + countA a- Map f a -> countF f + countA a- ZipWith f a1 a2 -> countF f + countA a1 + countA a2- Fold f z a -> countF f + countE z + countA a- Fold1 f a -> countF f + countA a- FoldSeg f z a s -> countF f + countE z + countA a + countA s- Fold1Seg f a s -> countF f + countA a + countA s- Scanl f z a -> countF f + countE z + countA a- Scanl' f z a -> countF f + countE z + countA a- Scanl1 f a -> countF f + countA a- Scanr f z a -> countF f + countE z + countA a- Scanr' f z a -> countF f + countE z + countA a- Scanr1 f a -> countF f + countA a- Permute f1 a1 f2 a2 -> countF f1 + countA a1 + countF f2 + countA a2- Backpermute sh f a -> countE sh + countF f + countA a- Stencil f _ a -> countF f + countA a- Stencil2 f _ a1 _ a2 -> countF f + countA a1 + countA a2- -- Collect s -> countS s-- countE :: PreOpenExp acc env aenv e -> Int- countE exp = case exp of- Let bnd body -> countE bnd + countE body- Var _ -> 0- Const _ -> 0- Tuple t -> countT t- Prj _ e -> countE e- IndexNil -> 0- IndexCons sl sz -> countE sl + countE sz- IndexHead sh -> countE sh- IndexTail sh -> countE sh- IndexSlice _ ix sh -> countE ix + countE sh- IndexFull _ ix sl -> countE ix + countE sl- IndexAny -> 0- ToIndex sh ix -> countE sh + countE ix- FromIndex sh i -> countE sh + countE i- Cond p t e -> countE p + countE t + countE e- While p f x -> countF p + countF f + countE x- PrimConst _ -> 0- PrimApp _ x -> countE x- Index a sh -> countA a + countE sh- LinearIndex a i -> countA a + countE i- ShapeSize sh -> countE sh- Intersect sh sz -> countE sh + countE sz- Union sh sz -> countE sh + countE sz- Shape a- | withShape -> countA a- | otherwise -> 0- Foreign _ _ e -> countE e-- countA :: acc aenv a -> Int- countA = countAcc withShape idx-- -- countAF :: PreOpenAfun acc aenv' f- -- -> Idx aenv' s- -- -> Int- -- countAF (Alam f) v = countAF f (SuccIdx v)- -- countAF (Abody a) v = countAcc withShape v a-- countF :: PreOpenFun acc env aenv f -> Int- countF (Lam f) = countF f- countF (Body b) = countE b-- countT :: Tuple (PreOpenExp acc env aenv) e -> Int- countT NilTup = 0- countT (SnocTup t e) = countT t + countE e-- countAT :: Atuple (acc aenv) a -> Int- countAT NilAtup = 0- countAT (SnocAtup t a) = countAT t + countA a--{--- countS :: PreOpenSeq acc aenv senv arrs -> Int- countS seq =- case seq of- Producer p s -> countP p + countS s- Consumer c -> countC c- Reify _ -> 0-- countP :: Producer acc aenv senv arrs -> Int- countP p =- case p of- StreamIn _ -> 0- ToSeq _ _ a -> countA a- MapSeq f _ -> countAF f idx- ChunkedMapSeq f _ -> countAF f idx- ZipWithSeq f _ _ -> countAF f idx- ScanSeq f e _ -> countF f + countE e-- countC :: Consumer acc aenv senv arrs -> Int- countC c =- case c of- FoldSeq f e _ -> countF f + countE e- FoldSeqFlatten f a _ -> countAF f idx + countA a- Stuple t -> countCT t-- countCT :: Atuple (Consumer acc aenv senv) t' -> Int- countCT NilAtup = 0- countCT (SnocAtup t c) = countCT t + countC c---}-
− Data/Array/Accelerate/Trafo/Simplify.hs
@@ -1,701 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE PatternGuards #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE TypeSynonymInstances #-}-{-# LANGUAGE ViewPatterns #-}--- |--- Module : Data.Array.Accelerate.Trafo.Simplify--- Copyright : [2012..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Trafo.Simplify (-- Simplify(..),--) where---- standard library-import Data.Label-import Data.List ( nubBy )-import Data.Maybe-import Data.Monoid-import Data.Typeable-import Text.Printf-import Control.Applicative hiding ( Const )-import Prelude hiding ( exp, iterate )---- friends-import Data.Array.Accelerate.AST hiding ( prj )-import Data.Array.Accelerate.Analysis.Match-import Data.Array.Accelerate.Analysis.Shape-import Data.Array.Accelerate.Error-import Data.Array.Accelerate.Product-import Data.Array.Accelerate.Trafo.Algebra-import Data.Array.Accelerate.Trafo.Base-import Data.Array.Accelerate.Trafo.Shrink-import Data.Array.Accelerate.Trafo.Substitution-import Data.Array.Accelerate.Type-import Data.Array.Accelerate.Array.Sugar ( Array, Elt(eltType), Shape, Slice, toElt, fromElt, Z(..), (:.)(..)- , Tuple(..), IsTuple, fromTuple, TupleRepr, shapeToList )-import qualified Data.Array.Accelerate.Debug as Stats---class Simplify f where- simplify :: f -> f--instance Kit acc => Simplify (PreFun acc aenv f) where- simplify = simplifyFun--instance (Kit acc, Elt e) => Simplify (PreExp acc aenv e) where- simplify = simplifyExp----- Scalar optimisations--- ====================---- Common subexpression elimination finds computations that are performed at--- least twice on a given execution path and eliminates the second and later--- occurrences, replacing them with uses of saved values. This implements a--- simplified version of that idea, where we look for the expressions of the--- form:------ let x = e1 in e2------ and replace all occurrences of e1 in e2 with x. This is not full redundancy--- elimination, but good enough to catch some cases, and in particular those--- likely to be introduced by scalar composition of terms in the fusion process.------ While it may seem that common subexpression elimination is always worthwhile,--- as it reduces the number of arithmetic operations performed, this is not--- necessarily advantageous. The simplest case in which it may not be desirable--- is if it causes a register to be occupied for a long time in order to hold--- the shared expression's value, which hence reduces the number of registers--- available for other uses. Even worse is if the value has to be spilled to--- memory because there are insufficient registers available. We sidestep this--- tricky and target-dependent issue by, for now, simply ignoring it.----localCSE :: (Kit acc, Elt a)- => Gamma acc env env aenv- -> PreOpenExp acc env aenv a- -> PreOpenExp acc (env,a) aenv b- -> Maybe (PreOpenExp acc env aenv b)-localCSE env bnd body- | Just ix <- lookupExp env bnd = Stats.ruleFired "CSE" . Just $ inline body (Var ix)- | otherwise = Nothing---- Common subexpression elimination, which attempts to match the given--- expression against something already bound in the environment. This can occur--- due to simplification, in which case we replace the entire subterm with x.------ > let x = e in .. e ..----globalCSE :: (Kit acc, Elt t)- => Gamma acc env env aenv- -> PreOpenExp acc env aenv t- -> Maybe (PreOpenExp acc env aenv t)-globalCSE env exp- | Just ix <- lookupExp env exp = Stats.ruleFired "CSE" . Just $ Var ix- | otherwise = Nothing---{----- Compared to regular Haskell, the scalar expression language of Accelerate is--- rather limited in order to meet the restrictions of what can be efficiently--- implemented on specialised hardware, such as GPUs. For example, to avoid--- excessive SIMD divergence, we do not support any form of recursion or--- iteration in scalar expressions. This harmonises well with the stratified--- design of the Accelerate language: collective array operations comprise many--- scalar computations that are executed in parallel, so for simplicity of--- scheduling these operations we would like some assurance that each scalar--- computation takes approximately the same time to execute as all others.------ However, some computations are naturally expressed in terms of iteration. For--- some problems, we can instead use generative techniques to implement the--- program by defining a single step of a recurrence relation as an Accelerate--- collective operation and using standard Haskell to unroll the loop a _fixed_--- number of times.------ However, this is outrageously slow because the intermediate values are--- written to memory at the end of every iteration. Luckily the fusion process--- will eliminate this intermediate memory traffic by combining the 'n'--- collective operations into a single operation with 'n' instances of the loop--- body. However, doing this we uncover an embarrassing secret: C compilers do--- not compile C code, they compile _idiomatic_ C code.------ This process recovers the iteration structure that was lost in the process of--- fusing the collective operations. This allows a backend to generate explicit--- loops in its target language.----recoverLoops- :: (Kit acc, Elt b)- => Gamma acc env env aenv- -> PreOpenExp acc env aenv a- -> PreOpenExp acc (env,a) aenv b- -> Maybe (PreOpenExp acc env aenv b)-recoverLoops _ bnd e3- -- To introduce scaler loops, we look for expressions of the form:- --- -- let x =- -- let y = e1 in e2- -- in e3- --- -- and if e2 and e3 are congruent, replace with:- --- -- iterate[2] (\y -> e2) e1- --- | Let e1 e2 <- bnd- , Just Refl <- matchEnvTop e2 e3- , Just Refl <- match e2 e3- = Stats.ruleFired "loop recovery/intro" . Just- $ Iterate (constant 2) e2 e1-- -- To merge expressions into a loop body, look for the pattern:- --- -- let x = iterate[n] f e1- -- in e3- --- -- and if e3 matches the loop body, replace the let binding with the bare- -- iteration with the trip count increased by one.- --- | Iterate n f e1 <- bnd- , Just Refl <- match f e3- = Stats.ruleFired "loop recovery/merge" . Just- $ Iterate (constant 1 `plus` n) f e1-- | otherwise- = Nothing-- where- plus :: PreOpenExp acc env aenv Int -> PreOpenExp acc env aenv Int -> PreOpenExp acc env aenv Int- plus x y = PrimApp (PrimAdd numType) $ Tuple $ NilTup `SnocTup` x `SnocTup` y-- constant :: Int -> PreOpenExp acc env aenv Int- constant i = Const ((),i)-- matchEnvTop :: (Elt s, Elt t)- => PreOpenExp acc (env,s) aenv f- -> PreOpenExp acc (env,t) aenv g- -> Maybe (s :=: t)- matchEnvTop _ _ = gcast Refl---}----- Walk a scalar expression applying simplifications to terms bottom-up.------ TODO: Look for particular patterns of expressions that can be replaced by--- something equivalent and simpler. In particular, indexing operations--- introduced by the fusion transformation. This would benefit from a--- rewrite rule schema.----simplifyOpenExp- :: forall acc env aenv e. (Kit acc, Elt e)- => Gamma acc env env aenv- -> PreOpenExp acc env aenv e- -> (Bool, PreOpenExp acc env aenv e)-simplifyOpenExp env = first getAny . cvtE- where- cvtE :: Elt t => PreOpenExp acc env aenv t -> (Any, PreOpenExp acc env aenv t)- cvtE exp | Just e <- globalCSE env exp = yes e- cvtE exp = case exp of- Let bnd body- -- Just reduct <- recoverLoops env (snd bnd') (snd body') -> yes . snd $ cvtE reduct- | Just reduct <- localCSE env (snd bnd') (snd body') -> yes . snd $ cvtE reduct- | otherwise -> Let <$> bnd' <*> body'- where- bnd' = cvtE bnd- env' = PushExp env (snd bnd')- body' = cvtE' (incExp env') body-- Var ix -> pure $ Var ix- Const c -> pure $ Const c- Tuple tup -> Tuple <$> cvtT tup- Prj ix t -> prj env ix (cvtE t)- IndexNil -> pure IndexNil- IndexAny -> pure IndexAny- IndexCons sh sz -> indexCons (cvtE sh) (cvtE sz)- IndexHead sh -> indexHead (cvtE sh)- IndexTail sh -> indexTail (cvtE sh)- IndexSlice x ix sh -> IndexSlice x <$> cvtE ix <*> cvtE sh- IndexFull x ix sl -> IndexFull x <$> cvtE ix <*> cvtE sl- ToIndex sh ix -> toIndex (cvtE sh) (cvtE ix)- FromIndex sh ix -> fromIndex (cvtE sh) (cvtE ix)- Cond p t e -> cond (cvtE p) (cvtE t) (cvtE e)- PrimConst c -> pure $ PrimConst c- PrimApp f x -> (u<>v, fx)- where- (u, x') = cvtE x- (v, fx) = evalPrimApp env f x'- Index a sh -> Index a <$> cvtE sh- LinearIndex a i -> LinearIndex a <$> cvtE i- Shape a -> shape a- ShapeSize sh -> shapeSize (cvtE sh)- Intersect s t -> cvtE s `intersect` cvtE t- Union s t -> cvtE s `union` cvtE t- Foreign ff f e -> Foreign ff <$> first Any (simplifyOpenFun EmptyExp f) <*> cvtE e- While p f x -> While <$> cvtF env p <*> cvtF env f <*> cvtE x-- cvtT :: Tuple (PreOpenExp acc env aenv) t -> (Any, Tuple (PreOpenExp acc env aenv) t)- cvtT NilTup = pure NilTup- cvtT (SnocTup t e) = SnocTup <$> cvtT t <*> cvtE e-- cvtE' :: Elt e' => Gamma acc env' env' aenv -> PreOpenExp acc env' aenv e' -> (Any, PreOpenExp acc env' aenv e')- cvtE' env' = first Any . simplifyOpenExp env'-- cvtF :: Gamma acc env' env' aenv -> PreOpenFun acc env' aenv f -> (Any, PreOpenFun acc env' aenv f)- cvtF env' = first Any . simplifyOpenFun env'-- -- Return the minimal set of unique shapes to intersect. This is a bit- -- inefficient, but the number of shapes is expected to be small so should- -- be fine in practice.- --- intersect :: Shape t- => (Any, PreOpenExp acc env aenv t)- -> (Any, PreOpenExp acc env aenv t)- -> (Any, PreOpenExp acc env aenv t)- intersect (c1, sh1) (c2, sh2)- | Nothing <- match sh sh' = Stats.ruleFired "intersect" (yes sh')- | otherwise = (c1 <> c2, sh')- where- sh = Intersect sh1 sh2- sh' = foldl1 Intersect- $ nubBy (\x y -> isJust (match x y))- $ leaves sh1 ++ leaves sh2-- leaves :: Shape t => PreOpenExp acc env aenv t -> [PreOpenExp acc env aenv t]- leaves (Intersect x y) = leaves x ++ leaves y- leaves rest = [rest]-- -- Return the minimal set of unique shapes to take the union of. This is a bit- -- inefficient, but the number of shapes is expected to be small so should- -- be fine in practice.- --- union :: Shape t- => (Any, PreOpenExp acc env aenv t)- -> (Any, PreOpenExp acc env aenv t)- -> (Any, PreOpenExp acc env aenv t)- union (c1, sh1) (c2, sh2)- | Nothing <- match sh sh' = Stats.ruleFired "union" (yes sh')- | otherwise = (c1 <> c2, sh')- where- sh = Union sh1 sh2- sh' = foldl1 Union- $ nubBy (\x y -> isJust (match x y))- $ leaves sh1 ++ leaves sh2-- leaves :: Shape t => PreOpenExp acc env aenv t -> [PreOpenExp acc env aenv t]- leaves (Union x y) = leaves x ++ leaves y- leaves rest = [rest]--- -- Simplify conditional expressions, in particular by eliminating branches- -- when the predicate is a known constant.- --- cond :: forall t. Elt t- => (Any, PreOpenExp acc env aenv Bool)- -> (Any, PreOpenExp acc env aenv t)- -> (Any, PreOpenExp acc env aenv t)- -> (Any, PreOpenExp acc env aenv t)- cond p@(_,p') t@(_,t') e@(_,e')- | Const True <- p' = Stats.knownBranch "True" (yes t')- | Const False <- p' = Stats.knownBranch "False" (yes e')- | Just Refl <- match t' e' = Stats.knownBranch "redundant" (yes e')- | otherwise = Cond <$> p <*> t <*> e-- -- If we are projecting elements from a tuple structure or tuple of constant- -- valued tuple, pick out the appropriate component directly.- --- -- Follow variable bindings, but only if they result in a simplification.- --- prj :: forall env' s t. (Elt s, Elt t, IsTuple t)- => Gamma acc env' env' aenv- -> TupleIdx (TupleRepr t) s- -> (Any, PreOpenExp acc env' aenv t)- -> (Any, PreOpenExp acc env' aenv s)- prj env' ix top@(_,e) = case e of- Tuple t -> Stats.inline "prj/Tuple" . yes $ prjT ix t- Const c -> Stats.inline "prj/Const" . yes $ prjC ix (fromTuple (toElt c :: t))- Var v | Just x <- prjV v -> Stats.inline "prj/Var" . yes $ x- Let a b | Just x <- prjL a b -> Stats.inline "prj/Let" . yes $ x- _ -> Prj ix <$> top- where- prjT :: TupleIdx tup s -> Tuple (PreOpenExp acc env' aenv) tup -> PreOpenExp acc env' aenv s- prjT ZeroTupIdx (SnocTup _ v) = v- prjT (SuccTupIdx idx) (SnocTup t _) = prjT idx t-#if __GLASGOW_HASKELL__ < 800- prjT _ _ = error "DO MORE OF WHAT MAKES YOU HAPPY"-#endif-- prjC :: TupleIdx tup s -> tup -> PreOpenExp acc env' aenv s- prjC ZeroTupIdx (_, v) = Const (fromElt v)- prjC (SuccTupIdx idx) (tup, _) = prjC idx tup-- prjV :: Idx env' t -> Maybe (PreOpenExp acc env' aenv s)- prjV var- | e' <- prjExp var env'- , Nothing <- match e e'- = case e' of- -- Don't push through nested let-bindings; this leads to code explosion- Let _ _ -> Nothing- _ | (Any True, x) <- prj env' ix (pure e') -> Just x- _ -> Nothing- | otherwise- = Nothing-- prjL :: Elt a- => PreOpenExp acc env' aenv a- -> PreOpenExp acc (env',a) aenv t- -> Maybe (PreOpenExp acc env' aenv s)- prjL a b- | (Any True, c) <- prj (incExp $ PushExp env' a) ix (pure b) = Just (Let a c)- prjL _ _ = Nothing--- -- Shape manipulations- --- indexCons :: (Slice sl, Elt sz)- => (Any, PreOpenExp acc env aenv sl)- -> (Any, PreOpenExp acc env aenv sz)- -> (Any, PreOpenExp acc env aenv (sl :. sz))- indexCons (_,IndexNil) (_,Const c)- | Just c' <- cast c -- EltRepr Z ~ EltRepr ()- = Stats.ruleFired "Z:.const" $ yes (Const c')- indexCons (_,IndexNil) (_,IndexHead sz')- | 1 <- expDim sz' -- no type information that this is a 1D shape, hence gcast next- , Just sh' <- gcast sz'- = Stats.ruleFired "Z:.indexHead" $ yes sh'- indexCons (_,IndexTail sl') (_,IndexHead sz')- | Just Refl <- match sl' sz'- = Stats.ruleFired "indexTail:.indexHead" $ yes sl'- indexCons sl sz- = IndexCons <$> sl <*> sz-- indexHead :: forall sl sz. (Slice sl, Elt sz) => (Any, PreOpenExp acc env aenv (sl :. sz)) -> (Any, PreOpenExp acc env aenv sz)- indexHead (_, Const c)- | _ :. sz <- toElt c :: sl :. sz = Stats.ruleFired "indexHead/const" $ yes (Const (fromElt sz))- indexHead (_, IndexCons _ sz) = Stats.ruleFired "indexHead/indexCons" $ yes sz- indexHead sh = IndexHead <$> sh-- indexTail :: forall sl sz. (Slice sl, Elt sz) => (Any, PreOpenExp acc env aenv (sl :. sz)) -> (Any, PreOpenExp acc env aenv sl)- indexTail (_, Const c)- | sl :. _ <- toElt c :: sl :. sz = Stats.ruleFired "indexTail/const" $ yes (Const (fromElt sl))- indexTail (_, IndexCons sl _) = Stats.ruleFired "indexTail/indexCons" $ yes sl- indexTail sh = IndexTail <$> sh-- shape :: forall sh t. (Shape sh, Elt t) => acc aenv (Array sh t) -> (Any, PreOpenExp acc env aenv sh)- shape _- | Just Refl <- matchTupleType (eltType (undefined::sh)) (eltType (undefined::Z))- = Stats.ruleFired "shape/Z" $ yes (Const (fromElt Z))- shape a- = pure $ Shape a-- shapeSize :: forall sh. Shape sh => (Any, PreOpenExp acc env aenv sh) -> (Any, PreOpenExp acc env aenv Int)- shapeSize (_, Const c) = Stats.ruleFired "shapeSize/const" $ yes (Const (product (shapeToList (toElt c :: sh))))- shapeSize sh = ShapeSize <$> sh-- toIndex :: forall sh. Shape sh => (Any, PreOpenExp acc env aenv sh) -> (Any, PreOpenExp acc env aenv sh) -> (Any, PreOpenExp acc env aenv Int)- toIndex (_,sh) (_,FromIndex sh' ix)- | Just Refl <- match sh sh' = Stats.ruleFired "toIndex/fromIndex" $ yes ix- toIndex sh ix = ToIndex <$> sh <*> ix-- fromIndex :: forall sh. Shape sh => (Any, PreOpenExp acc env aenv sh) -> (Any, PreOpenExp acc env aenv Int) -> (Any, PreOpenExp acc env aenv sh)- fromIndex (_,sh) (_,ToIndex sh' ix)- | Just Refl <- match sh sh' = Stats.ruleFired "fromIndex/toIndex" $ yes ix- fromIndex sh ix = FromIndex <$> sh <*> ix-- first :: (a -> a') -> (a,b) -> (a',b)- first f (x,y) = (f x, y)-- yes :: x -> (Any, x)- yes x = (Any True, x)----- Simplification for open functions----simplifyOpenFun- :: Kit acc- => Gamma acc env env aenv- -> PreOpenFun acc env aenv f- -> (Bool, PreOpenFun acc env aenv f)-simplifyOpenFun env (Body e) = Body <$> simplifyOpenExp env e-simplifyOpenFun env (Lam f) = Lam <$> simplifyOpenFun env' f- where- env' = incExp env `PushExp` Var ZeroIdx----- Simplify closed expressions and functions. The process is applied--- repeatedly until no more changes are made.----simplifyExp :: (Elt t, Kit acc) => PreExp acc aenv t -> PreExp acc aenv t-simplifyExp = iterate summariseOpenExp (simplifyOpenExp EmptyExp)--simplifyFun :: Kit acc => PreFun acc aenv f -> PreFun acc aenv f-simplifyFun = iterate summariseOpenFun (simplifyOpenFun EmptyExp)----- NOTE: [Simplifier iterations]------ Run the simplification pass _before_ the shrinking step. There are cases--- where it is better to run shrinking first, and then simplification would--- complete in a single step, but the converse is also true. However, as--- shrinking can remove some structure of the let bindings, which might be--- useful for the transformations (e.g. loop recovery) we want to maintain this--- information for at least the first pass.------ We always apply the simplification step once. Following this, we iterate--- shrinking and simplification until the expression no longer changes. Both--- shrink and simplify return a boolean indicating whether any work was done; we--- stop as soon as either returns false.------ With internal checks on, we also issue a warning if the iteration limit is--- reached, but it was still possible to make changes to the expression.----{-# SPECIALISE iterate :: (Exp aenv t -> Stats) -> (Exp aenv t -> (Bool, Exp aenv t)) -> Exp aenv t -> Exp aenv t #-}-{-# SPECIALISE iterate :: (Fun aenv t -> Stats) -> (Fun aenv t -> (Bool, Fun aenv t)) -> Fun aenv t -> Fun aenv t #-}--iterate- :: forall f a. (Match f, Shrink (f a))- => (f a -> Stats)- -> (f a -> (Bool, f a))- -> f a- -> f a-iterate summarise f = fix 1 . setup- where- -- The maximum number of simplifier iterations. To be conservative and avoid- -- excessive run times, we (should) set this value very low.- --- -- TODO: make this tunable via debug flags.- --- lIMIT = 25-- simplify' = Stats.simplifierDone . f- setup x = Stats.trace Stats.dump_simpl_iterations (msg 0 "init" x)- $ snd (trace 1 "simplify" (simplify' x))-- fix :: Int -> f a -> f a- fix i x0- | i > lIMIT = $internalWarning "simplify" "iteration limit reached" (not (x0 ==^ f x0)) x0- | not shrunk = x1- | not simplified = x2- | otherwise = fix (i+1) x2- where- (shrunk, x1) = trace i "shrink" $ shrink' x0- (simplified, x2) = trace i "simplify" $ simplify' x1-- -- debugging support- --- u ==^ (_,v) = isJust (match u v)-- trace i s v@(changed,x)- | changed = Stats.trace Stats.dump_simpl_iterations (msg i s x) v- | otherwise = v-- msg :: Int -> String -> f a -> String- msg i s x = printf "simpl-iters/%-8s [%d]: %s" s i (ppr x)-- ppr :: f a -> String- ppr = show . summarise----- Debugging support--- -------------------data Stats = Stats- { _terms :: {-# UNPACK #-} !Int- , _types :: {-# UNPACK #-} !Int- , _binders :: {-# UNPACK #-} !Int- , _vars :: {-# UNPACK #-} !Int- , _ops :: {-# UNPACK #-} !Int- }--instance Show Stats where- show (Stats a b c d e) =- printf "terms = %d, types = %d, lets = %d, vars = %d, primops = %d" a b c d e---- Rather than using the TH deriving mechanism, otherwise the summarise*--- functions will not be in scope for the above.----terms, types, binders, vars, ops :: Stats :-> Int-terms = lens _terms (\f Stats{..} -> Stats { _terms = f _terms, ..})-types = lens _types (\f Stats{..} -> Stats { _types = f _types, ..})-binders = lens _binders (\f Stats{..} -> Stats { _binders = f _binders, ..})-vars = lens _vars (\f Stats{..} -> Stats { _vars = f _vars, ..})-ops = lens _ops (\f Stats{..} -> Stats { _ops = f _ops, ..})--infixl 1 &-(&) :: a -> (a -> b) -> b-(&) x f = f x--infixr 4 +~-(+~) :: Num a => f :-> a -> a -> f -> f-(+~) l c s = modify l (+c) s--infixl 6 +++-(+++) :: Stats -> Stats -> Stats-Stats a1 b1 c1 d1 e1 +++ Stats a2 b2 c2 d2 e2 = Stats (a1+a2) (b1+b2) (c1+c2) (d1+d2) (e1+e2)--summariseOpenFun :: PreOpenFun acc env aenv f -> Stats-summariseOpenFun (Body e) = summariseOpenExp e & terms +~ 1-summariseOpenFun (Lam f) = summariseOpenFun f & terms +~ 1 & binders +~ 1--summariseOpenExp :: PreOpenExp acc env aenv t -> Stats-summariseOpenExp = modify terms (+1) . goE- where- zero = Stats 0 0 0 0 0-- travE :: PreOpenExp acc env aenv t -> Stats- travE = summariseOpenExp-- travF :: PreOpenFun acc env aenv t -> Stats- travF = summariseOpenFun-- travA :: acc aenv a -> Stats- travA _ = zero & vars +~ 1 -- assume an array index, else we should have failed elsewhere-- travT :: Tuple (PreOpenExp acc env aenv) t -> Stats- travT NilTup = zero & terms +~ 1- travT (SnocTup t e) = travT t +++ travE e & terms +~ 1-- travTix :: TupleIdx t e -> Stats- travTix ZeroTupIdx = zero & terms +~ 1- travTix (SuccTupIdx t) = travTix t & terms +~ 1-- travC :: PrimConst c -> Stats- travC (PrimMinBound t) = travBoundedType t & terms +~ 1- travC (PrimMaxBound t) = travBoundedType t & terms +~ 1- travC (PrimPi t) = travFloatingType t & terms +~ 1-- travNonNumType :: NonNumType t -> Stats- travNonNumType _ = zero & types +~ 1-- travIntegralType :: IntegralType t -> Stats- travIntegralType _ = zero & types +~ 1-- travFloatingType :: FloatingType t -> Stats- travFloatingType _ = zero & types +~ 1-- travNumType :: NumType t -> Stats- travNumType (IntegralNumType t) = travIntegralType t & types +~ 1- travNumType (FloatingNumType t) = travFloatingType t & types +~ 1-- travBoundedType :: BoundedType t -> Stats- travBoundedType (IntegralBoundedType t) = travIntegralType t & types +~ 1- travBoundedType (NonNumBoundedType t) = travNonNumType t & types +~ 1-- travScalarType :: ScalarType t -> Stats- travScalarType (NumScalarType t) = travNumType t & types +~ 1- travScalarType (NonNumScalarType t) = travNonNumType t & types +~ 1-- -- The scrutinee has already been counted- goE :: PreOpenExp acc env aenv t -> Stats- goE exp =- case exp of- Let bnd body -> travE bnd +++ travE body & binders +~ 1- Var{} -> zero & vars +~ 1- Foreign _ _ x -> travE x & terms +~ 1 -- +1 for asm, ignore fallback impls.- Const{} -> zero- Tuple tup -> travT tup & terms +~ 1- Prj ix e -> travTix ix +++ travE e- IndexNil -> zero- IndexCons sh sz -> travE sh +++ travE sz- IndexHead sh -> travE sh- IndexTail sh -> travE sh- IndexAny -> zero- IndexSlice _ slix sh -> travE slix +++ travE sh & terms +~ 1 -- +1 for sliceIndex- IndexFull _ slix sl -> travE slix +++ travE sl & terms +~ 1 -- +1 for sliceIndex- ToIndex sh ix -> travE sh +++ travE ix- FromIndex sh ix -> travE sh +++ travE ix- Cond p t e -> travE p +++ travE t +++ travE e- While p f x -> travF p +++ travF f +++ travE x- PrimConst c -> travC c- Index a ix -> travA a +++ travE ix- LinearIndex a ix -> travA a +++ travE ix- Shape a -> travA a- ShapeSize sh -> travE sh- Intersect sh1 sh2 -> travE sh1 +++ travE sh2- Union sh1 sh2 -> travE sh1 +++ travE sh2- PrimApp f x -> travPrimFun f +++ travE x-- travPrimFun :: PrimFun f -> Stats- travPrimFun = modify ops (+1) . goF- where- goF :: PrimFun f -> Stats- goF fun =- case fun of- PrimAdd t -> travNumType t- PrimSub t -> travNumType t- PrimMul t -> travNumType t- PrimNeg t -> travNumType t- PrimAbs t -> travNumType t- PrimSig t -> travNumType t- PrimQuot t -> travIntegralType t- PrimRem t -> travIntegralType t- PrimQuotRem t -> travIntegralType t- PrimIDiv t -> travIntegralType t- PrimMod t -> travIntegralType t- PrimDivMod t -> travIntegralType t- PrimBAnd t -> travIntegralType t- PrimBOr t -> travIntegralType t- PrimBXor t -> travIntegralType t- PrimBNot t -> travIntegralType t- PrimBShiftL t -> travIntegralType t- PrimBShiftR t -> travIntegralType t- PrimBRotateL t -> travIntegralType t- PrimBRotateR t -> travIntegralType t- PrimPopCount t -> travIntegralType t- PrimCountLeadingZeros t -> travIntegralType t- PrimCountTrailingZeros t -> travIntegralType t- PrimFDiv t -> travFloatingType t- PrimRecip t -> travFloatingType t- PrimSin t -> travFloatingType t- PrimCos t -> travFloatingType t- PrimTan t -> travFloatingType t- PrimAsin t -> travFloatingType t- PrimAcos t -> travFloatingType t- PrimAtan t -> travFloatingType t- PrimSinh t -> travFloatingType t- PrimCosh t -> travFloatingType t- PrimTanh t -> travFloatingType t- PrimAsinh t -> travFloatingType t- PrimAcosh t -> travFloatingType t- PrimAtanh t -> travFloatingType t- PrimExpFloating t -> travFloatingType t- PrimSqrt t -> travFloatingType t- PrimLog t -> travFloatingType t- PrimFPow t -> travFloatingType t- PrimLogBase t -> travFloatingType t- PrimTruncate f i -> travFloatingType f +++ travIntegralType i- PrimRound f i -> travFloatingType f +++ travIntegralType i- PrimFloor f i -> travFloatingType f +++ travIntegralType i- PrimCeiling f i -> travFloatingType f +++ travIntegralType i- PrimIsNaN t -> travFloatingType t- PrimIsInfinite t -> travFloatingType t- PrimAtan2 t -> travFloatingType t- PrimLt t -> travScalarType t- PrimGt t -> travScalarType t- PrimLtEq t -> travScalarType t- PrimGtEq t -> travScalarType t- PrimEq t -> travScalarType t- PrimNEq t -> travScalarType t- PrimMax t -> travScalarType t- PrimMin t -> travScalarType t- PrimLAnd -> zero- PrimLOr -> zero- PrimLNot -> zero- PrimOrd -> zero- PrimChr -> zero- PrimBoolToInt -> zero- PrimFromIntegral i n -> travIntegralType i +++ travNumType n- PrimToFloating n f -> travNumType n +++ travFloatingType f- PrimCoerce a b -> travScalarType a +++ travScalarType b-
− Data/Array/Accelerate/Trafo/Substitution.hs
@@ -1,597 +0,0 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE PatternGuards #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}-{-# OPTIONS_HADDOCK hide #-}--- |--- Module : Data.Array.Accelerate.Trafo.Substitution--- Copyright : [2012..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Trafo.Substitution (-- -- ** Renaming & Substitution- inline, substitute, compose,- subTop, subAtop,-- -- ** Weakening- (:>), Sink(..), SinkExp(..),-- -- ** Strengthening- (:?>), strengthen, strengthenE,-- -- ** Rebuilding terms- RebuildAcc, Rebuildable(..), RebuildableAcc,- RebuildableExp(..), RebuildTup(..)--) where--import Control.Applicative hiding ( Const )-import Prelude hiding ( exp, seq )--import Data.Array.Accelerate.AST-import Data.Array.Accelerate.Array.Sugar ( Elt, Arrays, Tuple(..), Atuple(..) )-import qualified Data.Array.Accelerate.Debug.Stats as Stats----- NOTE: [Renaming and Substitution]------ To do things like renaming and substitution, we need some operation on--- variables that we push structurally through terms, applying to each variable.--- We have a type preserving but environment changing operation:------ v :: forall t. Idx env t -> f env' aenv t------ The crafty bit is that 'f' might represent variables (for renaming) or terms--- (for substitutions). The demonic forall, --- which is to say that the--- quantifier is in a position which gives us obligation, not opportunity ------ forces us to respect type: when pattern matching detects the variable we care--- about, happily we discover that it has the type we must respect. The demon is--- not so free to mess with us as one might fear at first.------ We then lift this to an operation which traverses terms and rebuild them--- after applying 'v' to the variables:------ rebuildPartial v :: OpenExp env aenv t -> OpenExp env' aenv t------ The Syntactic class tells us what we need to know about 'f' if we want to be--- able to rebuildPartial terms. In essence, the crucial functionality is to propagate--- a class of operations on variables that is closed under shifting.----infixr `compose`-infixr `substitute`---- | Replace the first variable with the given expression. The environment--- shrinks.----inline :: RebuildableAcc acc- => PreOpenExp acc (env, s) aenv t- -> PreOpenExp acc env aenv s- -> PreOpenExp acc env aenv t-inline f g = Stats.substitution "inline" $ rebuildE (subTop g) f---- | Replace an expression that uses the top environment variable with another.--- The result of the first is let bound into the second.----substitute :: (RebuildableAcc acc, Elt b, Elt c)- => PreOpenExp acc (env, b) aenv c- -> PreOpenExp acc (env, a) aenv b- -> PreOpenExp acc (env, a) aenv c-substitute f g- | Stats.substitution "substitute" False = undefined-- | Var ZeroIdx <- g = f -- don't rebind an identity function- | otherwise = Let g $ rebuildE split f- where- split :: Elt c => Idx (env,b) c -> PreOpenExp acc ((env,a),b) aenv c- split ZeroIdx = Var ZeroIdx- split (SuccIdx ix) = Var (SuccIdx (SuccIdx ix))----- | Composition of unary functions.----compose :: (RebuildableAcc acc, Elt c)- => PreOpenFun acc env aenv (b -> c)- -> PreOpenFun acc env aenv (a -> b)- -> PreOpenFun acc env aenv (a -> c)-compose (Lam (Body f)) (Lam (Body g)) = Stats.substitution "compose" . Lam . Body $ substitute f g-compose _ _ = error "compose: impossible evaluation"--subTop :: Elt t => PreOpenExp acc env aenv s -> Idx (env, s) t -> PreOpenExp acc env aenv t-subTop s ZeroIdx = s-subTop _ (SuccIdx ix) = Var ix--subAtop :: Arrays t => PreOpenAcc acc aenv s -> Idx (aenv, s) t -> PreOpenAcc acc aenv t-subAtop t ZeroIdx = t-subAtop _ (SuccIdx idx) = Avar idx--data Identity a = Identity { runIdentity :: a }--instance Functor Identity where- fmap f (Identity a) = Identity (f a)--instance Applicative Identity where- Identity f <*> Identity a = Identity (f a)- pure a = Identity a---- A class for rebuilding terms.----class Rebuildable f where- {-# MINIMAL rebuildPartial #-}- type AccClo f :: (* -> * -> *)-- rebuildPartial :: (Applicative f', SyntacticAcc fa)- => (forall a'. Arrays a' => Idx aenv a' -> f' (fa (AccClo f) aenv' a'))- -> f aenv a- -> f' (f aenv' a)-- {-# INLINEABLE rebuildA #-}- rebuildA :: (SyntacticAcc fa)- => (forall a'. Arrays a' => Idx aenv a' -> fa (AccClo f) aenv' a')- -> f aenv a- -> f aenv' a- rebuildA av = runIdentity . rebuildPartial (Identity . av)---- A class for rebuilding scalar terms.----class RebuildableExp f where- {-# MINIMAL rebuildPartialE #-}- rebuildPartialE :: (Applicative f', SyntacticExp fe)- => (forall e'. Elt e' => Idx env e' -> f' (fe (AccClo (f env)) env' aenv e'))- -> f env aenv e- -> f' (f env' aenv e)-- {-# INLINABLE rebuildE #-}- rebuildE :: SyntacticExp fe- => (forall e'. Elt e' => Idx env e' -> fe (AccClo (f env)) env' aenv e')- -> f env aenv e- -> f env' aenv e- rebuildE v = runIdentity . rebuildPartialE (Identity . v)---- Terms that are rebuildable and also recursive closures----type RebuildableAcc acc = (Rebuildable acc, AccClo acc ~ acc)---- We can use the same plumbing to rebuildPartial all the things we want to rebuild.----instance RebuildableAcc acc => Rebuildable (PreOpenExp acc env) where- type AccClo (PreOpenExp acc env) = acc- {-# INLINEABLE rebuildPartial #-}- rebuildPartial = rebuildPreOpenExp rebuildPartial (pure . IE)--instance RebuildableAcc acc => Rebuildable (PreOpenFun acc env) where- type AccClo (PreOpenFun acc env) = acc- {-# INLINEABLE rebuildPartial #-}- rebuildPartial = rebuildFun rebuildPartial (pure . IE)--instance RebuildableAcc acc => Rebuildable (PreOpenAcc acc) where- type AccClo (PreOpenAcc acc) = acc- {-# INLINEABLE rebuildPartial #-}- rebuildPartial = rebuildPreOpenAcc rebuildPartial--instance RebuildableAcc acc => Rebuildable (PreOpenAfun acc) where- type AccClo (PreOpenAfun acc) = acc- {-# INLINEABLE rebuildPartial #-}- rebuildPartial = rebuildAfun rebuildPartial---- Tuples have to be handled specially.-newtype RebuildTup acc env aenv t = RebuildTup { unRTup :: Tuple (PreOpenExp acc env aenv) t }--instance RebuildableAcc acc => Rebuildable (RebuildTup acc env) where- type AccClo (RebuildTup acc env) = acc- {-# INLINEABLE rebuildPartial #-}- rebuildPartial v t = RebuildTup <$> rebuildTup rebuildPartial (pure . IE) v (unRTup t)--instance Rebuildable OpenAcc where- type AccClo OpenAcc = OpenAcc- {-# INLINEABLE rebuildPartial #-}- rebuildPartial = rebuildOpenAcc--instance RebuildableAcc acc => RebuildableExp (PreOpenExp acc) where- {-# INLINEABLE rebuildPartialE #-}- rebuildPartialE v = rebuildPreOpenExp rebuildPartial v (pure . IA)--instance RebuildableAcc acc => RebuildableExp (PreOpenFun acc) where- {-# INLINEABLE rebuildPartialE #-}- rebuildPartialE v = rebuildFun rebuildPartial v (pure . IA)---- NOTE: [Weakening]------ Weakening is something we usually take for granted: every time you learn a--- new word, old sentences still make sense. If a conclusion is justified by a--- hypothesis, it is still justified if you add more hypotheses. Similarly, a--- term remains in scope if you bind more (fresh) variables. Weakening is the--- operation of shifting things from one scope to a larger scope in which new--- things have become meaningful, but no old things have vanished.------ When we use a named representation (or HOAS) we get weakening for free. But--- in the de Bruijn representation weakening takes work: you have to shift all--- variable references to make room for the new bindings.------- The type of shifting terms from one context into another----type env :> env' = forall t'. Idx env t' -> Idx env' t'--class Sink f where- weaken :: env :> env' -> f env t -> f env' t-- -- TLM: We can't use this default instance because it doesn't lead to- -- specialised code. Perhaps the INLINEABLE pragma is ignored: GHC bug?- --- -- {-# INLINEABLE weaken #-}- -- default weaken :: Rebuildable f => env :> env' -> f env t -> f env' t- -- weaken k = Stats.substitution "weaken" . rebuildA (Avar . k)----instance Rebuildable f => Sink f where -- undecidable, incoherent--- weaken k = Stats.substitution "weaken" . rebuildA (Avar . k)--instance Sink Idx where- {-# INLINEABLE weaken #-}- weaken k = k--instance RebuildableAcc acc => Sink (PreOpenAcc acc) where- {-# INLINEABLE weaken #-}- weaken k = Stats.substitution "weaken" . rebuildA (Avar . k)--instance RebuildableAcc acc => Sink (PreOpenAfun acc) where- {-# INLINEABLE weaken #-}- weaken k = Stats.substitution "weaken" . rebuildA (Avar . k)--instance RebuildableAcc acc => Sink (PreOpenExp acc env) where- {-# INLINEABLE weaken #-}- weaken k = Stats.substitution "weaken" . rebuildA (Avar . k)--instance RebuildableAcc acc => Sink (PreOpenFun acc env) where- {-# INLINEABLE weaken #-}- weaken k = Stats.substitution "weaken" . rebuildA (Avar . k)--instance RebuildableAcc acc => Sink (RebuildTup acc env) where- {-# INLINEABLE weaken #-}- weaken k = Stats.substitution "weaken" . rebuildA (Avar . k)--instance RebuildableAcc acc => Sink (PreBoundary acc) where- {-# INLINEABLE weaken #-}- weaken k bndy =- case bndy of- Clamp -> Clamp- Mirror -> Mirror- Wrap -> Wrap- Constant c -> Constant c- Function f -> Function (weaken k f)--instance Sink OpenAcc where- {-# INLINEABLE weaken #-}- weaken k = Stats.substitution "weaken" . rebuildA (Avar . k)---- This rewrite rule is disabled because 'weaken' is now part of a type class.--- As such, we cannot attach a NOINLINE pragma because it has many definitions.--- {-# RULES--- "weaken/weaken" forall a (v1 :: env' :> env'') (v2 :: env :> env').--- weaken v1 (weaken v2 a) = weaken (v1 . v2) a--- #-}--class SinkExp f where- weakenE :: env :> env' -> f env aenv t -> f env' aenv t-- -- See comment in 'weaken'- --- -- {-# INLINEABLE weakenE #-}- -- default weakenE :: RebuildableExp f => env :> env' -> f env aenv t -> f env' aenv t- -- weakenE v = Stats.substitution "weakenE" . rebuildE (IE . v)--instance RebuildableAcc acc => SinkExp (PreOpenExp acc) where- {-# INLINEABLE weakenE #-}- weakenE v = Stats.substitution "weakenE" . rebuildE (IE . v)--instance RebuildableAcc acc => SinkExp (PreOpenFun acc) where- {-# INLINEABLE weakenE #-}- weakenE v = Stats.substitution "weakenE" . rebuildE (IE . v)---- See above for why this is disabled.--- {-# RULES--- "weakenE/weakenE" forall a (v1 :: env' :> env'') (v2 :: env :> env').--- weakenE v1 (weakenE v2 a) = weakenE (v1 . v2) a--- #-}---- NOTE: [Strengthening]------ Strengthening is the dual of weakening. Shifting terms from one scope to a--- smaller scope. Of course this is not always possible. If the term contains--- any variables not in the new environment, then it cannot be strengthened.--- This partial behaviour is captured with 'Maybe'.------- The type of partially shifting terms from one context into another.-type env :?> env' = forall t'. Idx env t' -> Maybe (Idx env' t')--{-# INLINEABLE strengthen #-}-strengthen :: Rebuildable f => env :?> env' -> f env t -> Maybe (f env' t)-strengthen k = rebuildPartial (fmap IA . k)--{-# INLINEABLE strengthenE #-}-strengthenE :: RebuildableExp f => env :?> env' -> f env aenv t -> Maybe (f env' aenv t)-strengthenE k = rebuildPartialE (fmap IE . k)---- Simultaneous Substitution ===================================================------- The scalar environment--- ---------------------- SEE: [Renaming and Substitution]--- SEE: [Weakening]----class SyntacticExp f where- varIn :: Elt t => Idx env t -> f acc env aenv t- expOut :: Elt t => f acc env aenv t -> PreOpenExp acc env aenv t- weakenExp :: Elt t => RebuildAcc acc -> f acc env aenv t -> f acc (env, s) aenv t- weakenExpAcc :: Elt t => RebuildAcc acc -> f acc env aenv t -> f acc env (aenv, s) t--newtype IdxE (acc :: * -> * -> *) env aenv t = IE { unIE :: Idx env t }--instance SyntacticExp IdxE where- varIn = IE- expOut = Var . unIE- weakenExp _ = IE . SuccIdx . unIE- weakenExpAcc _ = IE . unIE--instance SyntacticExp PreOpenExp where- varIn = Var- expOut = id- weakenExp k = runIdentity . rebuildPreOpenExp k (Identity . weakenExp k . IE) (Identity . IA)- weakenExpAcc k = runIdentity . rebuildPreOpenExp k (Identity . IE) (Identity . weakenAcc k . IA)--{-# INLINEABLE shiftE #-}-shiftE- :: (Applicative f, SyntacticExp fe, Elt t)- => RebuildAcc acc- -> (forall t'. Elt t' => Idx env t' -> f (fe acc env' aenv t'))- -> Idx (env, s) t- -> f (fe acc (env', s) aenv t)-shiftE _ _ ZeroIdx = pure $ varIn ZeroIdx-shiftE k v (SuccIdx ix) = weakenExp k <$> (v ix)--{-# INLINEABLE rebuildPreOpenExp #-}-rebuildPreOpenExp- :: (Applicative f, SyntacticExp fe, SyntacticAcc fa)- => RebuildAcc acc- -> (forall t'. Elt t' => Idx env t' -> f (fe acc env' aenv' t'))- -> (forall t'. Arrays t' => Idx aenv t' -> f (fa acc aenv' t'))- -> PreOpenExp acc env aenv t- -> f (PreOpenExp acc env' aenv' t)-rebuildPreOpenExp k v av exp =- case exp of- Const c -> pure (Const c)- PrimConst c -> pure (PrimConst c)- IndexNil -> pure IndexNil- IndexAny -> pure IndexAny- Var ix -> expOut <$> v ix- Let a b -> Let <$> rebuildPreOpenExp k v av a <*> rebuildPreOpenExp k (shiftE k v) av b- Tuple tup -> Tuple <$> rebuildTup k v av tup- Prj tup e -> Prj tup <$> rebuildPreOpenExp k v av e- IndexCons sh sz -> IndexCons <$> rebuildPreOpenExp k v av sh <*> rebuildPreOpenExp k v av sz- IndexHead sh -> IndexHead <$> rebuildPreOpenExp k v av sh- IndexTail sh -> IndexTail <$> rebuildPreOpenExp k v av sh- IndexSlice x ix sh -> IndexSlice x <$> rebuildPreOpenExp k v av ix <*> rebuildPreOpenExp k v av sh- IndexFull x ix sl -> IndexFull x <$> rebuildPreOpenExp k v av ix <*> rebuildPreOpenExp k v av sl- ToIndex sh ix -> ToIndex <$> rebuildPreOpenExp k v av sh <*> rebuildPreOpenExp k v av ix- FromIndex sh ix -> FromIndex <$> rebuildPreOpenExp k v av sh <*> rebuildPreOpenExp k v av ix- Cond p t e -> Cond <$> rebuildPreOpenExp k v av p <*> rebuildPreOpenExp k v av t <*> rebuildPreOpenExp k v av e- While p f x -> While <$> rebuildFun k v av p <*> rebuildFun k v av f <*> rebuildPreOpenExp k v av x- PrimApp f x -> PrimApp f <$> rebuildPreOpenExp k v av x- Index a sh -> Index <$> k av a <*> rebuildPreOpenExp k v av sh- LinearIndex a i -> LinearIndex <$> k av a <*> rebuildPreOpenExp k v av i- Shape a -> Shape <$> k av a- ShapeSize sh -> ShapeSize <$> rebuildPreOpenExp k v av sh- Intersect s t -> Intersect <$> rebuildPreOpenExp k v av s <*> rebuildPreOpenExp k v av t- Union s t -> Union <$> rebuildPreOpenExp k v av s <*> rebuildPreOpenExp k v av t- Foreign ff f e -> Foreign ff f <$> rebuildPreOpenExp k v av e--{-# INLINEABLE rebuildTup #-}-rebuildTup- :: (Applicative f, SyntacticExp fe, SyntacticAcc fa)- => RebuildAcc acc- -> (forall t'. Elt t' => Idx env t' -> f (fe acc env' aenv' t'))- -> (forall t'. Arrays t' => Idx aenv t' -> f (fa acc aenv' t'))- -> Tuple (PreOpenExp acc env aenv) t- -> f (Tuple (PreOpenExp acc env' aenv') t)-rebuildTup k v av tup =- case tup of- NilTup -> pure NilTup- SnocTup t e -> SnocTup <$> rebuildTup k v av t <*> rebuildPreOpenExp k v av e--{-# INLINEABLE rebuildFun #-}-rebuildFun- :: (Applicative f, SyntacticExp fe, SyntacticAcc fa)- => RebuildAcc acc- -> (forall t'. Elt t' => Idx env t' -> f (fe acc env' aenv' t'))- -> (forall t'. Arrays t' => Idx aenv t' -> f (fa acc aenv' t'))- -> PreOpenFun acc env aenv t- -> f (PreOpenFun acc env' aenv' t)-rebuildFun k v av fun =- case fun of- Body e -> Body <$> rebuildPreOpenExp k v av e- Lam f -> Lam <$> rebuildFun k (shiftE k v) av f---- The array environment--- -------------------type RebuildAcc acc =- forall aenv aenv' f fa a. (Applicative f, SyntacticAcc fa)- => (forall a'. Arrays a' => Idx aenv a' -> f (fa acc aenv' a'))- -> acc aenv a- -> f (acc aenv' a)--class SyntacticAcc f where- avarIn :: Arrays t => Idx aenv t -> f acc aenv t- accOut :: Arrays t => f acc aenv t -> PreOpenAcc acc aenv t- weakenAcc :: Arrays t => RebuildAcc acc -> f acc aenv t -> f acc (aenv, s) t--newtype IdxA (acc :: * -> * -> *) aenv t = IA { unIA :: Idx aenv t }--instance SyntacticAcc IdxA where- avarIn = IA- accOut = Avar . unIA- weakenAcc _ = IA . SuccIdx . unIA--instance SyntacticAcc PreOpenAcc where- avarIn = Avar- accOut = id- weakenAcc k = runIdentity . rebuildPreOpenAcc k (Identity . weakenAcc k . IA)--{-# INLINEABLE shiftA #-}-shiftA- :: (Applicative f, SyntacticAcc fa, Arrays t)- => RebuildAcc acc- -> (forall t'. Arrays t' => Idx aenv t' -> f (fa acc aenv' t'))- -> Idx (aenv, s) t- -> f (fa acc (aenv', s) t)-shiftA _ _ ZeroIdx = pure $ avarIn ZeroIdx-shiftA k v (SuccIdx ix) = weakenAcc k <$> v ix--{-# INLINEABLE rebuildOpenAcc #-}-rebuildOpenAcc- :: (Applicative f, SyntacticAcc fa)- => (forall t'. Arrays t' => Idx aenv t' -> f (fa OpenAcc aenv' t'))- -> OpenAcc aenv t- -> f (OpenAcc aenv' t)-rebuildOpenAcc av (OpenAcc acc) = OpenAcc <$> rebuildPreOpenAcc rebuildOpenAcc av acc--{-# INLINEABLE rebuildPreOpenAcc #-}-rebuildPreOpenAcc- :: (Applicative f, SyntacticAcc fa)- => RebuildAcc acc- -> (forall t'. Arrays t' => Idx aenv t' -> f (fa acc aenv' t'))- -> PreOpenAcc acc aenv t- -> f (PreOpenAcc acc aenv' t)-rebuildPreOpenAcc k av acc =- case acc of- Use a -> pure (Use a)- Alet a b -> Alet <$> k av a <*> k (shiftA k av) b- Avar ix -> accOut <$> av ix- Atuple tup -> Atuple <$> rebuildAtup k av tup- Aprj tup a -> Aprj tup <$> k av a- Apply f a -> Apply <$> rebuildAfun k av f <*> k av a- Acond p t e -> Acond <$> rebuildPreOpenExp k (pure . IE) av p <*> k av t <*> k av e- Awhile p f a -> Awhile <$> rebuildAfun k av p <*> rebuildAfun k av f <*> k av a- Unit e -> Unit <$> rebuildPreOpenExp k (pure . IE) av e- Reshape e a -> Reshape <$> rebuildPreOpenExp k (pure . IE) av e <*> k av a- Generate e f -> Generate <$> rebuildPreOpenExp k (pure . IE) av e <*> rebuildFun k (pure . IE) av f- Transform sh ix f a -> Transform <$> rebuildPreOpenExp k (pure . IE) av sh <*> rebuildFun k (pure . IE) av ix <*> rebuildFun k (pure . IE) av f <*> k av a- Replicate sl slix a -> Replicate sl <$> rebuildPreOpenExp k (pure . IE) av slix <*> k av a- Slice sl a slix -> Slice sl <$> k av a <*> rebuildPreOpenExp k (pure . IE) av slix- Map f a -> Map <$> rebuildFun k (pure . IE) av f <*> k av a- ZipWith f a1 a2 -> ZipWith <$> rebuildFun k (pure . IE) av f <*> k av a1 <*> k av a2- Fold f z a -> Fold <$> rebuildFun k (pure . IE) av f <*> rebuildPreOpenExp k (pure . IE) av z <*> k av a- Fold1 f a -> Fold1 <$> rebuildFun k (pure . IE) av f <*> k av a- FoldSeg f z a s -> FoldSeg <$> rebuildFun k (pure . IE) av f <*> rebuildPreOpenExp k (pure . IE) av z <*> k av a <*> k av s- Fold1Seg f a s -> Fold1Seg <$> rebuildFun k (pure . IE) av f <*> k av a <*> k av s- Scanl f z a -> Scanl <$> rebuildFun k (pure . IE) av f <*> rebuildPreOpenExp k (pure . IE) av z <*> k av a- Scanl' f z a -> Scanl' <$> rebuildFun k (pure . IE) av f <*> rebuildPreOpenExp k (pure . IE) av z <*> k av a- Scanl1 f a -> Scanl1 <$> rebuildFun k (pure . IE) av f <*> k av a- Scanr f z a -> Scanr <$> rebuildFun k (pure . IE) av f <*> rebuildPreOpenExp k (pure . IE) av z <*> k av a- Scanr' f z a -> Scanr' <$> rebuildFun k (pure . IE) av f <*> rebuildPreOpenExp k (pure . IE) av z <*> k av a- Scanr1 f a -> Scanr1 <$> rebuildFun k (pure . IE) av f <*> k av a- Permute f1 a1 f2 a2 -> Permute <$> rebuildFun k (pure . IE) av f1 <*> k av a1 <*> rebuildFun k (pure . IE) av f2 <*> k av a2- Backpermute sh f a -> Backpermute <$> rebuildPreOpenExp k (pure . IE) av sh <*> rebuildFun k (pure . IE) av f <*> k av a- Stencil f b a -> Stencil <$> rebuildFun k (pure . IE) av f <*> rebuildBoundary k av b <*> k av a- Stencil2 f b1 a1 b2 a2 -> Stencil2 <$> rebuildFun k (pure . IE) av f <*> rebuildBoundary k av b1 <*> k av a1 <*> rebuildBoundary k av b2 <*> k av a2- -- Collect seq -> Collect <$> rebuildSeq k av seq- Aforeign ff afun as -> Aforeign ff afun <$> k av as--{-# INLINEABLE rebuildAfun #-}-rebuildAfun- :: (Applicative f, SyntacticAcc fa)- => RebuildAcc acc- -> (forall t'. Arrays t' => Idx aenv t' -> f (fa acc aenv' t'))- -> PreOpenAfun acc aenv t- -> f (PreOpenAfun acc aenv' t)-rebuildAfun k av afun =- case afun of- Abody b -> Abody <$> k av b- Alam f -> Alam <$> rebuildAfun k (shiftA k av) f--{-# INLINEABLE rebuildAtup #-}-rebuildAtup- :: (Applicative f, SyntacticAcc fa)- => RebuildAcc acc- -> (forall t'. Arrays t' => Idx aenv t' -> f (fa acc aenv' t'))- -> Atuple (acc aenv) t- -> f (Atuple (acc aenv') t)-rebuildAtup k av atup =- case atup of- NilAtup -> pure NilAtup- SnocAtup t a -> SnocAtup <$> rebuildAtup k av t <*> k av a--{-# INLINEABLE rebuildBoundary #-}-rebuildBoundary- :: (Applicative f, SyntacticAcc fa)- => RebuildAcc acc- -> (forall t'. Arrays t' => Idx aenv t' -> f (fa acc aenv' t'))- -> PreBoundary acc aenv t- -> f (PreBoundary acc aenv' t)-rebuildBoundary k av bndy =- case bndy of- Clamp -> pure Clamp- Mirror -> pure Mirror- Wrap -> pure Wrap- Constant v -> pure (Constant v)- Function f -> Function <$> rebuildFun k (pure . IE) av f--{---{-# INLINEABLE rebuildSeq #-}-rebuildSeq- :: (SyntacticAcc fa, Applicative f)- => RebuildAcc acc- -> (forall t'. Arrays t' => Idx aenv t' -> f (fa acc aenv' t'))- -> PreOpenSeq acc aenv senv t- -> f (PreOpenSeq acc aenv' senv t)-rebuildSeq k v seq =- case seq of- Producer p s -> Producer <$> (rebuildP k v p) <*> (rebuildSeq k v s)- Consumer c -> Consumer <$> (rebuildC k v c)- Reify ix -> pure $ Reify ix--{-# INLINEABLE rebuildP #-}-rebuildP :: (SyntacticAcc fa, Applicative f)- => RebuildAcc acc- -> (forall t'. Arrays t' => Idx aenv t' -> f (fa acc aenv' t'))- -> Producer acc aenv senv a- -> f (Producer acc aenv' senv a)-rebuildP k v p =- case p of- StreamIn arrs -> pure (StreamIn arrs)- ToSeq sl slix acc -> ToSeq sl slix <$> k v acc- MapSeq f x -> MapSeq <$> rebuildAfun k v f <*> pure x- ChunkedMapSeq f x -> ChunkedMapSeq <$> rebuildAfun k v f <*> pure x- ZipWithSeq f x y -> ZipWithSeq <$> rebuildAfun k v f <*> pure x <*> pure y- ScanSeq f e x -> ScanSeq <$> rebuildFun k (pure . IE) v f <*> rebuildPreOpenExp k (pure . IE) v e <*> pure x--{-# INLINEABLE rebuildC #-}-rebuildC :: forall acc fa f aenv aenv' senv a. (SyntacticAcc fa, Applicative f)- => RebuildAcc acc- -> (forall t'. Arrays t' => Idx aenv t' -> f (fa acc aenv' t'))- -> Consumer acc aenv senv a- -> f (Consumer acc aenv' senv a)-rebuildC k v c =- case c of- FoldSeq f e x -> FoldSeq <$> rebuildFun k (pure . IE) v f <*> rebuildPreOpenExp k (pure . IE) v e <*> pure x- FoldSeqFlatten f acc x -> FoldSeqFlatten <$> rebuildAfun k v f <*> k v acc <*> pure x- Stuple t -> Stuple <$> rebuildT t- where- rebuildT :: Atuple (Consumer acc aenv senv) t -> f (Atuple (Consumer acc aenv' senv) t)- rebuildT NilAtup = pure NilAtup- rebuildT (SnocAtup t s) = SnocAtup <$> (rebuildT t) <*> (rebuildC k v s)---}-
− Data/Array/Accelerate/Type.hs
@@ -1,712 +0,0 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}-{-# OPTIONS_HADDOCK hide #-}--- |--- Module : Data.Array.Accelerate.Type--- Copyright : [2008..2017] Manuel M T Chakravarty, Gabriele Keller--- [2009..2017] Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)------ /Scalar types supported in array computations/------ Integral types:--- * Int--- * Int8--- * Int16--- * Int32--- * Int64--- * Word--- * Word8--- * Word16--- * Word32--- * Word64--- * CShort--- * CUShort--- * CInt--- * CUInt--- * CLong--- * CULong--- * CLLong--- * CULLong------ Floating types:--- * Float--- * Double--- * CFloat--- * CDouble------ Non-numeric types:--- * Bool--- * Char--- * CChar--- * CSChar--- * CUChar------ Note that 'Int' has the same bit width as in plain Haskell computations, and--- 'Float' and 'Double' represent IEEE single and double precision floating--- point numbers, respectively.-----module Data.Array.Accelerate.Type (- Float, Double, Char, Bool(..),- module Data.Int,- module Data.Word,- module Foreign.C.Types,- module Data.Array.Accelerate.Type-) where---import Data.Orphans () -- orphan instances for 8-tuples and beyond---- standard libraries-import Data.Bits-import Data.Int-import Data.Type.Equality-import Data.Typeable-import Data.Word-import GHC.TypeLits-import Foreign.Storable-import Foreign.C.Types (- CChar, CSChar, CUChar, CShort, CUShort, CInt, CUInt, CLong, CULong,- CLLong, CULLong, CFloat, CDouble)- -- in the future, CHalf----- Scalar types--- ---------------- Reified dictionaries-----data IntegralDict a where- IntegralDict :: ( Bounded a, Enum a, Eq a, Ord a, Show a- , Bits a, FiniteBits a, Integral a, Num a, Real a, Storable a )- => IntegralDict a--data FloatingDict a where- FloatingDict :: ( Enum a, Eq a, Ord a, Show a- , Floating a, Fractional a, Num a, Real a, RealFrac a- , RealFloat a, Storable a )- => FloatingDict a--data NonNumDict a where- NonNumDict :: ( Bounded a, Enum a, Eq a, Ord a, Show a, Storable a )- => NonNumDict a----- Scalar type representation------- |Integral types supported in array computations.----data IntegralType a where- TypeInt :: IntegralDict Int -> IntegralType Int- TypeInt8 :: IntegralDict Int8 -> IntegralType Int8- TypeInt16 :: IntegralDict Int16 -> IntegralType Int16- TypeInt32 :: IntegralDict Int32 -> IntegralType Int32- TypeInt64 :: IntegralDict Int64 -> IntegralType Int64- TypeWord :: IntegralDict Word -> IntegralType Word- TypeWord8 :: IntegralDict Word8 -> IntegralType Word8- TypeWord16 :: IntegralDict Word16 -> IntegralType Word16- TypeWord32 :: IntegralDict Word32 -> IntegralType Word32- TypeWord64 :: IntegralDict Word64 -> IntegralType Word64- TypeCShort :: IntegralDict CShort -> IntegralType CShort- TypeCUShort :: IntegralDict CUShort -> IntegralType CUShort- TypeCInt :: IntegralDict CInt -> IntegralType CInt- TypeCUInt :: IntegralDict CUInt -> IntegralType CUInt- TypeCLong :: IntegralDict CLong -> IntegralType CLong- TypeCULong :: IntegralDict CULong -> IntegralType CULong- TypeCLLong :: IntegralDict CLLong -> IntegralType CLLong- TypeCULLong :: IntegralDict CULLong -> IntegralType CULLong---- |Floating-point types supported in array computations.----data FloatingType a where- TypeFloat :: FloatingDict Float -> FloatingType Float- TypeDouble :: FloatingDict Double -> FloatingType Double- TypeCFloat :: FloatingDict CFloat -> FloatingType CFloat- TypeCDouble :: FloatingDict CDouble -> FloatingType CDouble---- |Non-numeric types supported in array computations.----data NonNumType a where- TypeBool :: NonNumDict Bool -> NonNumType Bool -- marshalled to Word8- TypeChar :: NonNumDict Char -> NonNumType Char- TypeCChar :: NonNumDict CChar -> NonNumType CChar- TypeCSChar :: NonNumDict CSChar -> NonNumType CSChar- TypeCUChar :: NonNumDict CUChar -> NonNumType CUChar---- |Numeric element types implement Num & Real----data NumType a where- IntegralNumType :: IntegralType a -> NumType a- FloatingNumType :: FloatingType a -> NumType a---- |Bounded element types implement Bounded----data BoundedType a where- IntegralBoundedType :: IntegralType a -> BoundedType a- NonNumBoundedType :: NonNumType a -> BoundedType a---- |All scalar element types implement Eq, Ord & Enum----data ScalarType a where- NumScalarType :: NumType a -> ScalarType a- NonNumScalarType :: NonNumType a -> ScalarType a---- Showing type names-----instance Show (IntegralType a) where- show (TypeInt _) = "Int"- show (TypeInt8 _) = "Int8"- show (TypeInt16 _) = "Int16"- show (TypeInt32 _) = "Int32"- show (TypeInt64 _) = "Int64"- show (TypeWord _) = "Word"- show (TypeWord8 _) = "Word8"- show (TypeWord16 _) = "Word16"- show (TypeWord32 _) = "Word32"- show (TypeWord64 _) = "Word64"- show (TypeCShort _) = "CShort"- show (TypeCUShort _) = "CUShort"- show (TypeCInt _) = "CInt"- show (TypeCUInt _) = "CUInt"- show (TypeCLong _) = "CLong"- show (TypeCULong _) = "CULong"- show (TypeCLLong _) = "CLLong"- show (TypeCULLong _) = "CULLong"--instance Show (FloatingType a) where- show (TypeFloat _) = "Float"- show (TypeDouble _) = "Double"- show (TypeCFloat _) = "CFloat"- show (TypeCDouble _) = "CDouble"--instance Show (NonNumType a) where- show (TypeBool _) = "Bool"- show (TypeChar _) = "Char"- show (TypeCChar _) = "CChar"- show (TypeCSChar _) = "CSChar"- show (TypeCUChar _) = "CUChar"--instance Show (NumType a) where- show (IntegralNumType ty) = show ty- show (FloatingNumType ty) = show ty--instance Show (BoundedType a) where- show (IntegralBoundedType ty) = show ty- show (NonNumBoundedType ty) = show ty--instance Show (ScalarType a) where- show (NumScalarType ty) = show ty- show (NonNumScalarType ty) = show ty----- Querying scalar type representations------- |Integral types----class (IsScalar a, IsNum a, IsBounded a) => IsIntegral a where- integralType :: IntegralType a--instance IsIntegral Int where- integralType = TypeInt IntegralDict--instance IsIntegral Int8 where- integralType = TypeInt8 IntegralDict--instance IsIntegral Int16 where- integralType = TypeInt16 IntegralDict--instance IsIntegral Int32 where- integralType = TypeInt32 IntegralDict--instance IsIntegral Int64 where- integralType = TypeInt64 IntegralDict--instance IsIntegral Word where- integralType = TypeWord IntegralDict--instance IsIntegral Word8 where- integralType = TypeWord8 IntegralDict--instance IsIntegral Word16 where- integralType = TypeWord16 IntegralDict--instance IsIntegral Word32 where- integralType = TypeWord32 IntegralDict--instance IsIntegral Word64 where- integralType = TypeWord64 IntegralDict--instance IsIntegral CShort where- integralType = TypeCShort IntegralDict--instance IsIntegral CUShort where- integralType = TypeCUShort IntegralDict--instance IsIntegral CInt where- integralType = TypeCInt IntegralDict--instance IsIntegral CUInt where- integralType = TypeCUInt IntegralDict--instance IsIntegral CLong where- integralType = TypeCLong IntegralDict--instance IsIntegral CULong where- integralType = TypeCULong IntegralDict--instance IsIntegral CLLong where- integralType = TypeCLLong IntegralDict--instance IsIntegral CULLong where- integralType = TypeCULLong IntegralDict---- |Floating types----class (Floating a, IsScalar a, IsNum a) => IsFloating a where- floatingType :: FloatingType a--instance IsFloating Float where- floatingType = TypeFloat FloatingDict--instance IsFloating Double where- floatingType = TypeDouble FloatingDict--instance IsFloating CFloat where- floatingType = TypeCFloat FloatingDict--instance IsFloating CDouble where- floatingType = TypeCDouble FloatingDict---- |Non-numeric types----class IsNonNum a where- nonNumType :: NonNumType a--instance IsNonNum Bool where- nonNumType = TypeBool NonNumDict--instance IsNonNum Char where- nonNumType = TypeChar NonNumDict--instance IsNonNum CChar where- nonNumType = TypeCChar NonNumDict--instance IsNonNum CSChar where- nonNumType = TypeCSChar NonNumDict--instance IsNonNum CUChar where- nonNumType = TypeCUChar NonNumDict---- |Numeric types----class (Num a, IsScalar a) => IsNum a where- numType :: NumType a--instance IsNum Int where- numType = IntegralNumType integralType--instance IsNum Int8 where- numType = IntegralNumType integralType--instance IsNum Int16 where- numType = IntegralNumType integralType--instance IsNum Int32 where- numType = IntegralNumType integralType--instance IsNum Int64 where- numType = IntegralNumType integralType--instance IsNum Word where- numType = IntegralNumType integralType--instance IsNum Word8 where- numType = IntegralNumType integralType--instance IsNum Word16 where- numType = IntegralNumType integralType--instance IsNum Word32 where- numType = IntegralNumType integralType--instance IsNum Word64 where- numType = IntegralNumType integralType--instance IsNum CShort where- numType = IntegralNumType integralType--instance IsNum CUShort where- numType = IntegralNumType integralType--instance IsNum CInt where- numType = IntegralNumType integralType--instance IsNum CUInt where- numType = IntegralNumType integralType--instance IsNum CLong where- numType = IntegralNumType integralType--instance IsNum CULong where- numType = IntegralNumType integralType--instance IsNum CLLong where- numType = IntegralNumType integralType--instance IsNum CULLong where- numType = IntegralNumType integralType--instance IsNum Float where- numType = FloatingNumType floatingType--instance IsNum Double where- numType = FloatingNumType floatingType--instance IsNum CFloat where- numType = FloatingNumType floatingType--instance IsNum CDouble where- numType = FloatingNumType floatingType---- |Bounded types----class IsBounded a where- boundedType :: BoundedType a--instance IsBounded Int where- boundedType = IntegralBoundedType integralType--instance IsBounded Int8 where- boundedType = IntegralBoundedType integralType--instance IsBounded Int16 where- boundedType = IntegralBoundedType integralType--instance IsBounded Int32 where- boundedType = IntegralBoundedType integralType--instance IsBounded Int64 where- boundedType = IntegralBoundedType integralType--instance IsBounded Word where- boundedType = IntegralBoundedType integralType--instance IsBounded Word8 where- boundedType = IntegralBoundedType integralType--instance IsBounded Word16 where- boundedType = IntegralBoundedType integralType--instance IsBounded Word32 where- boundedType = IntegralBoundedType integralType--instance IsBounded Word64 where- boundedType = IntegralBoundedType integralType--instance IsBounded CShort where- boundedType = IntegralBoundedType integralType--instance IsBounded CUShort where- boundedType = IntegralBoundedType integralType--instance IsBounded CInt where- boundedType = IntegralBoundedType integralType--instance IsBounded CUInt where- boundedType = IntegralBoundedType integralType--instance IsBounded CLong where- boundedType = IntegralBoundedType integralType--instance IsBounded CULong where- boundedType = IntegralBoundedType integralType--instance IsBounded CLLong where- boundedType = IntegralBoundedType integralType--instance IsBounded CULLong where- boundedType = IntegralBoundedType integralType--instance IsBounded Bool where- boundedType = NonNumBoundedType nonNumType--instance IsBounded Char where- boundedType = NonNumBoundedType nonNumType--instance IsBounded CChar where- boundedType = NonNumBoundedType nonNumType--instance IsBounded CSChar where- boundedType = NonNumBoundedType nonNumType--instance IsBounded CUChar where- boundedType = NonNumBoundedType nonNumType---- |All scalar types----class Typeable a => IsScalar a where- scalarType :: ScalarType a--instance IsScalar Int where- scalarType = NumScalarType numType--instance IsScalar Int8 where- scalarType = NumScalarType numType--instance IsScalar Int16 where- scalarType = NumScalarType numType--instance IsScalar Int32 where- scalarType = NumScalarType numType--instance IsScalar Int64 where- scalarType = NumScalarType numType--instance IsScalar Word where- scalarType = NumScalarType numType--instance IsScalar Word8 where- scalarType = NumScalarType numType--instance IsScalar Word16 where- scalarType = NumScalarType numType--instance IsScalar Word32 where- scalarType = NumScalarType numType--instance IsScalar Word64 where- scalarType = NumScalarType numType--instance IsScalar CShort where- scalarType = NumScalarType numType--instance IsScalar CUShort where- scalarType = NumScalarType numType--instance IsScalar CInt where- scalarType = NumScalarType numType--instance IsScalar CUInt where- scalarType = NumScalarType numType--instance IsScalar CLong where- scalarType = NumScalarType numType--instance IsScalar CULong where- scalarType = NumScalarType numType--instance IsScalar CLLong where- scalarType = NumScalarType numType--instance IsScalar CULLong where- scalarType = NumScalarType numType--instance IsScalar Float where- scalarType = NumScalarType numType--instance IsScalar Double where- scalarType = NumScalarType numType--instance IsScalar CFloat where- scalarType = NumScalarType numType--instance IsScalar CDouble where- scalarType = NumScalarType numType--instance IsScalar Bool where- scalarType = NonNumScalarType nonNumType--instance IsScalar Char where- scalarType = NonNumScalarType nonNumType--instance IsScalar CChar where- scalarType = NonNumScalarType nonNumType--instance IsScalar CSChar where- scalarType = NonNumScalarType nonNumType--instance IsScalar CUChar where- scalarType = NonNumScalarType nonNumType---- Extract reified dictionaries-----integralDict :: IntegralType a -> IntegralDict a-integralDict (TypeInt dict) = dict-integralDict (TypeInt8 dict) = dict-integralDict (TypeInt16 dict) = dict-integralDict (TypeInt32 dict) = dict-integralDict (TypeInt64 dict) = dict-integralDict (TypeWord dict) = dict-integralDict (TypeWord8 dict) = dict-integralDict (TypeWord16 dict) = dict-integralDict (TypeWord32 dict) = dict-integralDict (TypeWord64 dict) = dict-integralDict (TypeCShort dict) = dict-integralDict (TypeCUShort dict) = dict-integralDict (TypeCInt dict) = dict-integralDict (TypeCUInt dict) = dict-integralDict (TypeCLong dict) = dict-integralDict (TypeCULong dict) = dict-integralDict (TypeCLLong dict) = dict-integralDict (TypeCULLong dict) = dict--floatingDict :: FloatingType a -> FloatingDict a-floatingDict (TypeFloat dict) = dict-floatingDict (TypeDouble dict) = dict-floatingDict (TypeCFloat dict) = dict-floatingDict (TypeCDouble dict) = dict--nonNumDict :: NonNumType a -> NonNumDict a-nonNumDict (TypeBool dict) = dict-nonNumDict (TypeChar dict) = dict-nonNumDict (TypeCChar dict) = dict-nonNumDict (TypeCSChar dict) = dict-nonNumDict (TypeCUChar dict) = dict----- Tuple types--- -------------data TupleType a where- UnitTuple :: TupleType ()- SingleTuple :: ScalarType a -> TupleType a- PairTuple :: TupleType a -> TupleType b -> TupleType (a, b)--instance Show (TupleType a) where- show UnitTuple = "()"- show (SingleTuple scalarTy) = show scalarTy- show (PairTuple a b) = "("++show a++", "++show b++")"----- Type-level bit sizes--- ------------------------ |Constraint that values of these two types have the same bit width----type BitSizeEq a b = (BitSize a == BitSize b) ~ 'True--type family BitSize a :: Nat--type instance BitSize Int8 = 8-type instance BitSize Int16 = 16-type instance BitSize Int32 = 32-type instance BitSize Int64 = 64-type instance BitSize Word8 = 8-type instance BitSize Word16 = 16-type instance BitSize Word32 = 32-type instance BitSize Word64 = 64-type instance BitSize Char = 32-type instance BitSize Bool = 1--type instance BitSize CShort = 16-type instance BitSize CUShort = 16-type instance BitSize CInt = 32-type instance BitSize CUInt = 32-type instance BitSize CLLong = 64-type instance BitSize CULLong = 64-type instance BitSize CChar = 8-type instance BitSize CUChar = 8-type instance BitSize CSChar = 8--type instance BitSize Float = 32-type instance BitSize CFloat = 32-type instance BitSize Double = 64-type instance BitSize CDouble = 64--type instance BitSize Int = $( case finiteBitSize (undefined::Int) of- 32 -> [t| 32 |]- 64 -> [t| 64 |]- _ -> error "I don't know what architecture I am" )--type instance BitSize Word = $( case finiteBitSize (undefined::Word) of- 32 -> [t| 32 |]- 64 -> [t| 64 |]- _ -> error "I don't know what architecture I am" )--type instance BitSize CLong = $( case finiteBitSize (undefined::CLong) of- 32 -> [t| 32 |]- 64 -> [t| 64 |]- _ -> error "I don't know what architecture I am" )--type instance BitSize CULong = $( case finiteBitSize (undefined::CULong) of- 32 -> [t| 32 |]- 64 -> [t| 64 |]- _ -> error "I don't know what architecture I am" )---{---- Vector GPU data types--- -----------------------data CChar1 = CChar1 CChar-data CChar2 = CChar2 CChar CChar-data CChar3 = CChar3 CChar CChar CChar-data CChar4 = CChar4 CChar CChar CChar CChar-data CSChar1 = CSChar1 CSChar-data CSChar2 = CSChar2 CSChar CSChar-data CSChar3 = CSChar3 CSChar CSChar CSChar-data CSChar4 = CSChar4 CSChar CSChar CSChar CSChar-data CUChar1 = CUChar1 CUChar-data CUChar2 = CUChar2 CUChar CUChar-data CUChar3 = CUChar3 CUChar CUChar CUChar-data CUChar4 = CUChar4 CUChar CUChar CUChar CUChar-data CShort1 = CShort1 CShort-data CShort2 = CShort2 CShort CShort-data CShort3 = CShort3 CShort CShort CShort-data CShort4 = CShort4 CShort CShort CShort CShort-data CUShort1 = CUShort1 CUShort-data CUShort2 = CUShort2 CUShort CUShort-data CUShort3 = CUShort3 CUShort CUShort CUShort-data CUShort4 = CUShort4 CUShort CUShort CUShort CUShort-data CInt1 = CInt1 CInt-data CInt2 = CInt2 CInt CInt-data CInt3 = CInt3 CInt CInt CInt-data CInt4 = CInt4 CInt CInt CInt CInt-data CUInt1 = CUInt1 CUInt-data CUInt2 = CUInt2 CUInt CUInt-data CUInt3 = CUInt3 CUInt CUInt CUInt-data CUInt4 = CUInt4 CUInt CUInt CUInt CUInt-data CLong1 = CLong1 CLong-data CLong2 = CLong2 CLong CLong-data CLong3 = CLong3 CLong CLong CLong-data CLong4 = CLong4 CLong CLong CLong CLong-data CULong1 = CULong1 CULong-data CULong2 = CULong2 CULong CULong-data CULong3 = CULong3 CULong CULong CULong-data CULong4 = CULong4 CULong CULong CULong CULong-data CLLong1 = CLLong1 CLLong-data CLLong2 = CLLong2 CLLong CLLong-data CLLong3 = CLLong3 CLLong CLLong CLLong-data CLLong4 = CLLong4 CLLong CLLong CLLong CLLong-data CULLong1 = CULLong1 CULLong-data CULLong2 = CULLong2 CULLong CULLong-data CULLong3 = CULLong3 CULLong CULLong CULLong-data CULLong4 = CULLong4 CULLong CULLong CULLong CULLong-data CFloat1 = CFloat1 CFloat-data CFloat2 = CFloat2 CFloat CFloat-data CFloat3 = CFloat3 CFloat CFloat CFloat-data CFloat4 = CFloat4 CFloat CFloat CFloat CFloat-data CDouble1 = CDouble1 CDouble-data CDouble2 = CDouble2 CDouble CDouble-data CDouble3 = CDouble3 CDouble CDouble CDouble-data CDouble4 = CDouble4 CDouble CDouble CDouble CDouble--- in the future, vector types for CHalf- -}-
− Data/Atomic.hs
@@ -1,60 +0,0 @@-{-# LANGUAGE ForeignFunctionInterface #-}--- |--- Module : Data.Atomic--- Copyright : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License : BSD3------ Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable (GHC extensions)------ Atomic integer values. All operations are thread safe.-----module Data.Atomic (-- Atomic,- new,- add, and,--) where--import Data.Int-import Foreign.Ptr-import Foreign.ForeignPtr-import Foreign.Storable-import Prelude ( ($), IO, return )----- | A mutable atomic integer----newtype Atomic = Atomic ( ForeignPtr Int64 )---- | Create a new atomic variable initialised to the given value----new :: Int64 -> IO Atomic-new v = do- fp <- mallocForeignPtr- withForeignPtr fp $ \p -> poke p v- return $ Atomic fp---- | Increase the atomic by the given amount. Returns the old value.----add :: Atomic -> Int64 -> IO Int64-add (Atomic fp) v =- withForeignPtr fp $ \p -> atomic_fetch_and_add_64 p v---- | Bitwise AND the atomic with the given value. Return the old value.----and :: Atomic -> Int64 -> IO Int64-and (Atomic fp) v =- withForeignPtr fp $ \p -> atomic_fetch_and_and_64 p v----- Perform the operation suggested by the name and return the old value------ > { tmp = *ptr; *ptr op= value; return tmp; }----foreign import ccall unsafe "hs_atomic_fetch_and_add_64" atomic_fetch_and_add_64 :: Ptr Int64 -> Int64 -> IO Int64-foreign import ccall unsafe "hs_atomic_fetch_and_and_64" atomic_fetch_and_and_64 :: Ptr Int64 -> Int64 -> IO Int64-
LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) [2007..2017] The Accelerate Team. All rights reserved.+Copyright (c) [2007..2020] The Accelerate Team. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:@@ -7,8 +7,8 @@ * 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 names of the contributors nor of their affiliations may - be used to endorse or promote products derived from this software + * Neither the names of the contributors nor of their affiliations 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 ''AS IS'' AND ANY
README.md view
@@ -1,9 +1,16 @@-An Embedded Language for Accelerated Array Computations-=======================================================+<div align="center">+<img width="450" src="https://github.com/AccelerateHS/accelerate/raw/master/images/accelerate-logo-text-v.png?raw=true" alt="henlo, my name is Theia"/> -[](https://travis-ci.org/AccelerateHS/accelerate)+# High-performance parallel arrays for Haskell++[](https://github.com/tmcdonell/accelerate/actions/workflows/ci.yml)+[](https://gitter.im/AccelerateHS/Lobby) [](https://hackage.haskell.org/package/accelerate)+[](https://stackage.org/lts/package/accelerate)+[](https://stackage.org/nightly/package/accelerate) +</div>+ `Data.Array.Accelerate` defines an embedded language of array computations for high-performance computing in Haskell. Computations on multi-dimensional, regular arrays are expressed in the form of parameterised collective operations (such as maps, reductions, and permutations). These computations are online-compiled and executed on a range of architectures. For more details, see our papers:@@ -12,8 +19,9 @@ * [Optimising Purely Functional GPU Programs][MCKL13] ([slides][MCKL13-slides]) * [Embedding Foreign Code][CMCK14] * [Type-safe Runtime Code Generation: Accelerate to LLVM][MCGN15] ([slides][MCGN15-slides]) ([video][MCGN15-video])+ * [Streaming Irregular Arrays][CMCK17] ([video][CMCK17-video]) -There are also slides from some fairly recent presentations:+There are also slides from some presentations on Accelerate: * [Embedded Languages for High-Performance Computing in Haskell][Embedded] * [GPGPU Programming in Haskell with Accelerate][YLJ13-slides] ([video][YLJ13-video]) ([workshop][YLJ13-workshop])@@ -32,6 +40,7 @@ - [Requirements](#requirements) - [Documentation](#documentation) - [Examples](#examples)+ - [Who are we?](#who-are-we) - [Mailing list and contacts](#mailing-list-and-contacts) - [Citing Accelerate](#citing-accelerate) - [What's missing?](#whats-missing)@@ -49,39 +58,53 @@ Availability ------------ -Package accelerate is available from+Package _Accelerate_ is available from: - * Hackage: [accelerate][Hackage] - install with `cabal install accelerate`- * GitHub: [AccelerateHS/accelerate][GitHub] - get the source with `git clone https://github.com/AccelerateHS/accelerate.git`. The easiest way to compile the source distributions is via the Haskell [stack](https://docs.haskellstack.org/en/stable/README/) tool.+ * Hackage: [accelerate][Hackage] - just add it to your cabal file+ * GitHub: [AccelerateHS/accelerate][GitHub] - get the source with `git clone https://github.com/AccelerateHS/accelerate.git` +To install the Haskell toolchain try [GHCup](https://www.haskell.org/ghcup/).+ Additional components --------------------- The following supported add-ons are available as separate packages: * [accelerate-llvm-native][accelerate-llvm-native]: Backend targeting multicore CPUs- * [accelerate-llvm-ptx][accelerate-llvm-ptx]: Backend targeting CUDA-enabled NVIDIA GPUs. Requires a GPU with compute capability 2.0 or greater (see the [table on Wikipedia][wiki-cc])+ * [accelerate-llvm-ptx][accelerate-llvm-ptx]: Backend targeting CUDA-enabled NVIDIA GPUs. Requires a GPU with compute capability 3.0 or greater (see the [table on Wikipedia][wiki-cc]) * [accelerate-examples][accelerate-examples]: Computational kernels and applications showcasing the use of Accelerate as well as a regression test suite (supporting function and performance testing)- * [accelerate-io][accelerate-io]: Fast conversion between Accelerate arrays and other array formats (for example, Repa and Vector)+ * Conversion between various formats:+ * [accelerate-io](https://hackage.haskell.org/package/accelerate-io): For copying data directly between raw pointers+ * [accelerate-io-array](https://hackage.haskell.org/package/accelerate-io-array): Immutable arrays+ * [accelerate-io-bmp](https://hackage.haskell.org/package/accelerate-io-bmp): Uncompressed BMP image files+ * [accelerate-io-bytestring](https://hackage.haskell.org/package/accelerate-io-bytestring): Compact, immutable binary data+ * [accelerate-io-cereal](https://hackage.haskell.org/package/accelerate-io-cereal): Binary serialisation of arrays using [cereal](https://hackage.haskell.org/package/cereal)+ * [accelerate-io-JuicyPixels](https://hackage.haskell.org/package/accelerate-io-JuicyPixels): Images in various pixel formats+ * [accelerate-io-repa](https://hackage.haskell.org/package/accelerate-io-repa): Another Haskell library for high-performance parallel arrays+ * [accelerate-io-serialise](https://hackage.haskell.org/package/accelerate-io-serialise): Binary serialisation of arrays using [serialise](https://hackage.haskell.org/package/serialise)+ * [accelerate-io-vector](https://hackage.haskell.org/package/accelerate-io-vector): Efficient boxed and unboxed one-dimensional arrays * [accelerate-fft][accelerate-fft]: Fast Fourier transform implementation, with FFI bindings to optimised implementations * [accelerate-blas][accelerate-blas]: BLAS and LAPACK operations, with FFI bindings to optimised implementations * [accelerate-bignum][accelerate-bignum]: Fixed-width large integer arithmetic * [colour-accelerate][colour-accelerate]: Colour representations in Accelerate (RGB, sRGB, HSV, and HSL)+ * [containers-accelerate](http://hackage.haskell.org/package/containers-accelerate): Hashing-based container types * [gloss-accelerate][gloss-accelerate]: Generate [gloss][gloss] pictures from Accelerate * [gloss-raster-accelerate][gloss-raster-accelerate]: Parallel rendering of raster images and animations+ * [hashable-accelerate](http://hackage.haskell.org/package/hashable-accelerate): A class for types which can be converted into a hash value * [lens-accelerate][lens-accelerate]: [Lens][lens] operators for Accelerate types * [linear-accelerate][linear-accelerate]: [Linear][linear] vector spaces in Accelerate * [mwc-random-accelerate][mwc-random-accelerate]: Generate Accelerate arrays filled with high quality pseudorandom numbers * [numeric-prelude-accelerate][numeric-prelude-accelerate]: Lifting the [numeric-prelude][numeric-prelude] to Accelerate+ * [wigner-ville-accelerate](https://github.com/Haskell-mouse/wigner-ville-accelerate): Wigner-Ville time-frequency distribution. -Install them from Hackage with `cabal install PACKAGENAME`.+These are all available on Hackage. Documentation ------------- * Haddock documentation is included and linked with the individual package releases on [Hackage][Hackage].- * Haddock documentation for in-development components can be found [here](http://tmcdonell-bot.github.io/accelerate-travis-buildbot/).+ <!-- * Haddock documentation for in-development components can be found [here](http://tmcdonell-bot.github.io/accelerate-travis-buildbot/). --> * The idea behind the HOAS (higher-order abstract syntax) to de-Bruijn conversion used in the library is [described separately][HOAS-conv]. Examples@@ -89,7 +112,7 @@ ### accelerate-examples -The [accelerate-examples][accelerate-examples] package provides a range of computational kernels and a few complete applications. To install these from Hackage, issue `cabal install accelerate-examples`. The examples include:+The [accelerate-examples][accelerate-examples] package provides a range of computational kernels and a few complete applications. The examples include: * An implementation of [canny edge detection][wiki-canny] * An interactive [mandelbrot set][wiki-mandelbrot] generator@@ -100,9 +123,11 @@ * A cellular automata simulation * A "password recovery" tool, for dictionary lookup of MD5 hashes -[](http://i.imgur.com/RgXRqsc.jpg)-[](http://i.imgur.com/ZNEGEJK.jpg)+To run these, either get the source from Hackage using `cabal get accelerate-examples` or clone the [git repository][accelerate-examples], then use `cabal run` on the individual executables. +[](https://i.imgur.com/RgXRqsc.jpg)+[](https://i.imgur.com/ZNEGEJK.jpg)+ <!-- <video width=400 height=300 controls=false autoplay loop> <source="http://www.cse.unsw.edu.au/~tmcdonell/images/ray.mp4" type="video/mp4">@@ -114,12 +139,7 @@ [LULESH-accelerate][lulesh-accelerate] is in implementation of the Livermore Unstructured Lagrangian Explicit Shock Hydrodynamics (LULESH) mini-app. [LULESH][LULESH] represents a typical hydrodynamics code such as [ALE3D][ALE3D], but is a highly simplified application, hard-coded to solve the Sedov blast problem on an unstructured hexahedron mesh. ----### Λ ○ λ (Lol)--Λ ○ λ ([Lol][lol]) is a general-purpose library for ring-based lattice cryptography. Lol has applications in, for example, symmetric-key somewhat-homomorphic encryption schemes. The [lol-accelerate][lol-accelerate] package provides an Accelerate backend for Lol.+ ### Additional examples@@ -127,27 +147,51 @@ Accelerate users have also built some substantial applications of their own. Please feel free to add your own examples! + * Jonathan Fraser, [GPUVAC](https://github.com/GeneralFusion/gpuvac): An explicit advection magnetohydrodynamics simulation+ * David van Balen, [Sudokus](https://github.com/dpvanbalen/Sudokus): A sudoku solver+ * Trevor L. McDonell, [lol-accelerate][lol-accelerate]: A backend to the Λ ○ λ ([Lol][lol]) library for ring-based lattice cryptography * Henning Thielemann, [patch-image](http://hackage.haskell.org/package/patch-image): Combine a collage of overlapping images * apunktbau, [bildpunkt](https://github.com/abau/bildpunkt): A ray-marching distance field renderer * klarh, [hasdy](https://github.com/klarh/hasdy): Molecular dynamics in Haskell using Accelerate * Alexandros Gremm used Accelerate as part of the [2014 CSCS summer school](http://user.cscs.ch/blog/2014/cscs_usi_summer_school_2014_30_june_10_july_2014_in_serpiano_tessin/index.html) ([code](https://github.com/agremm/cscs)) +Who are we?+-----------++The Accelerate team (past and present) consists of:++ * Manuel M T Chakravarty ([@mchakravarty]) <!-- 2008..2017? -->+ * Gabriele Keller ([@gckeller]) <!-- 2008.. -->+ * Trevor L. McDonell ([@tmcdonell]) <!-- 2009.. -->+ * Robert Clifton-Everest ([@robeverest]) <!-- 2013.. -->+ * Frederik M. Madsen ([@fmma]) <!-- 2014 -->+ * Ryan R. Newton ([@rrnewton]) <!-- 2012..2013 -->+ * Joshua Meredith ([@JoshMeredith]) <!-- 2018.. -->+ * Ben Lever ([@blever]) <!-- 2010..2011 -->+ * Sean Seefried ([@sseefried]) <!-- 2010..2011 -->+ * Ivo Gabe de Wolff ([@ivogabe]) <!-- 2019.. -->+ * Tom Smeding ([@tomsmeding]) <!-- 2021..2026? -->++The maintainer and principal developer of Accelerate is Trevor L.+McDonell <trevor.mcdonell@gmail.com>.++ Mailing list and contacts ------------------------- * Mailing list: [`accelerate-haskell@googlegroups.com`](mailto:accelerate-haskell@googlegroups.com) (discussions on both use and development are welcome)- * Sign up for the mailing list at the [Accelerate Google Groups page][Google-Group].- * Bug reports and issues tracking: [GitHub project page][Issues].--The maintainers of Accelerate are Manuel M T Chakravarty <chak@cse.unsw.edu.au> and Trevor L McDonell <tmcdonell@cse.unsw.edu.au>.+ * Sign up for the mailing list at the [Accelerate Google Groups page][Google-Group]+ * Bug reports and issues tracking: [GitHub project page][Issues]+ * Chat with us on [gitter](https://gitter.im/AccelerateHS/Lobby) Citing Accelerate ----------------- If you use Accelerate for academic research, you are encouraged (though not-required) to cite the following papers ([BibTeX](http://www.cse.unsw.edu.au/~tmcdonell/papers/accelerate.bib)):+required) to cite the following papers:+<!-- ([BibTeX](http://www.cse.unsw.edu.au/~tmcdonell/papers/accelerate.bib)): --> * Manuel M. T. Chakravarty, Gabriele Keller, Sean Lee, Trevor L. McDonell, and Vinod Grover. [Accelerating Haskell Array Codes with Multicore GPUs][CKLM+11].@@ -165,6 +209,11 @@ [Type-safe Runtime Code Generation: Accelerate to LLVM][MCGN15]. In _Haskell '15: The 8th ACM SIGPLAN Symposium on Haskell_, ACM, 2015. + * Robert Clifton-Everest, Trevor L. McDonell, Manuel M. T. Chakravarty, and Gabriele Keller.+ [Streaming Irregular Arrays][CMCK17].+ In Haskell '17: The 10th ACM SIGPLAN Symposium on Haskell, ACM, 2017.++ Accelerate is primarily developed by academics, so citations matter a lot to us. As an added benefit, you increase Accelerate's exposure and potential user (and developer!) base, which is a benefit to all users of Accelerate. Thanks in advance!@@ -176,17 +225,30 @@ Here is a list of features that are currently missing: * Preliminary API (parts of the API may still change in subsequent releases)-+ * Many more features... contact us! + [@mchakravarty]: https://github.com/mchakravarty+ [@gckeller]: https://github.com/gckeller+ [@tmcdonell]: https://github.com/tmcdonell+ [@robeverest]: https://github.com/robeverest+ [@fmma]: https://github.com/fmma+ [@rrnewton]: https://github.com/rrnewton+ [@JoshMeredith]: https://github.com/JoshMeredith+ [@blever]: https://github.com/blever+ [@sseefried]: https://github.com/sseefried+ [@ivogabe]: https://github.com/ivogabe+ [@tomsmeding]: https://github.com/tomsmeding - [CKLM+11]: http://www.cse.unsw.edu.au/~chak/papers/CKLM+11.html- [MCKL13]: http://www.cse.unsw.edu.au/~chak/papers/MCKL13.html+ [CKLM+11]: https://github.com/tmcdonell/tmcdonell.github.io/raw/master/papers/acc-cuda-damp2011.pdf+ [MCKL13]: https://github.com/tmcdonell/tmcdonell.github.io/raw/master/papers/acc-optim-icfp2013.pdf [MCKL13-slides]: https://speakerdeck.com/tmcdonell/optimising-purely-functional-gpu-programs- [CMCK14]: http://www.cse.unsw.edu.au/~chak/papers/CMCK14.html- [MCGN15]: http://www.cse.unsw.edu.au/~chak/papers/MCGN15.html+ [CMCK14]: https://github.com/tmcdonell/tmcdonell.github.io/raw/master/papers/acc-ffi-padl2014.pdf+ [MCGN15]: https://github.com/tmcdonell/tmcdonell.github.io/raw/master/papers/acc-llvm-haskell2015.pdf [MCGN15-slides]: https://speakerdeck.com/tmcdonell/type-safe-runtime-code-generation-accelerate-to-llvm [MCGN15-video]: https://www.youtube.com/watch?v=snXhXA5noVc [HIW'09]: https://wiki.haskell.org/HaskellImplementorsWorkshop+ [CMCK17]: https://github.com/tmcdonell/tmcdonell.github.io/raw/master/papers/acc-seq2-haskell2017.pdf+ [CMCK17-video]: https://www.youtube.com/watch?v=QIWSqp7AaNo [Mar13]: http://chimera.labs.oreilly.com/books/1230000000929 [Embedded]: https://speakerdeck.com/mchakravarty/embedded-languages-for-high-performance-computing-in-haskell [Hackage]: http://hackage.haskell.org/package/accelerate@@ -209,7 +271,8 @@ [Wiki]: https://github.com/AccelerateHS/accelerate/wiki [Issues]: https://github.com/AccelerateHS/accelerate/issues [Google-Group]: http://groups.google.com/group/accelerate-haskell- [HOAS-conv]: http://www.cse.unsw.edu.au/~chak/haskell/term-conv/+ [HOAS-conv]: https://github.com/mchakravarty/hoas-conv+ <!-- [HOAS-conv]: https://web.archive.org/web/20180805092417/http://www.cse.unsw.edu.au/~chak/haskell/term-conv/ --> [repa]: http://hackage.haskell.org/package/repa [wiki-cc]: https://en.wikipedia.org/wiki/CUDA#Supported_GPUs [YLJ13-video]: http://youtu.be/ARqE4yT2Z0o@@ -220,7 +283,7 @@ [wiki-nbody]: https://en.wikipedia.org/wiki/N-body [wiki-raytracing]: https://en.wikipedia.org/wiki/Ray_tracing [wiki-pagerank]: https://en.wikipedia.org/wiki/Pagerank- [Trevor-thesis]: http://www.cse.unsw.edu.au/~tmcdonell/papers/TrevorMcDonell_PhD_submission.pdf+ [Trevor-thesis]: https://github.com/tmcdonell/tmcdonell.github.io/raw/master/papers/TrevorMcDonell_PhD_Thesis.pdf [colour-accelerate]: https://github.com/tmcdonell/colour-accelerate [gloss]: https://hackage.haskell.org/package/gloss [gloss-accelerate]: https://github.com/tmcdonell/gloss-accelerate
Setup.hs view
@@ -1,3 +1,141 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE MultiWayIf #-}+{-# OPTIONS -Wall #-}+module Main where++import Distribution.Extra.Doctest+import Distribution.PackageDescription hiding (Flag) import Distribution.Simple-main = defaultMain+import Distribution.Simple.LocalBuildInfo+import Distribution.Simple.Setup+import Distribution.Simple.Utils+import Distribution.System+import Distribution.Verbosity +#if MIN_VERSION_Cabal(3,14,0)+-- Note [Cabal 3.14]+--+-- If you change any path stuff, either test that the package still works with+-- Cabal 3.12 or stop declaring support for it in accelerate.cabal. (If you do+-- the latter, also remove all of the other conditionals in this file.)+-- Note that supporting old versions of Cabal is useful for being able to run+-- e.g. Accelerate on old GPU clusters, which is nice.+import Distribution.Utils.Path (SymbolicPath, FileOrDir(Dir), Pkg, CWD, interpretSymbolicPath)+#endif++import Control.Monad+import Data.Maybe+import System.Directory+import System.FilePath+import Text.Printf+++main :: IO ()+main =+ defaultMainWithHooks (doctestsUserHooks "doctest")+ { preConf = preConfHook+ , postBuild = postBuildHook+ }++preConfHook :: Args -> ConfigFlags -> IO HookedBuildInfo+preConfHook args config_flags = do+ let verbosity = fromFlagOrDefault normal $ configVerbosity config_flags++ when (tracyMode config_flags) $ do+ yes <- doesFileExist "cbits/tracy/public/TracyClient.cpp"+ if yes+ then+ -- Nix (and apparently future versions of stack) automatically update+ -- submodules, so there is no need to do so again.+ return ()+ else do+ -- Stack and cabal based builds require updating the submodules+ git <- doesDirectoryExist ".git"+ if git+ then rawSystemExit' verbosity "git" ["submodule", "update", "--init", "--recursive"]+ else do+ -- XXX: This must be kept up to date with the git submodule revision+ let archive = "v0.11.1.tar.gz"+ createDirectoryIfMissing True "cbits/tracy"+ rawSystemExit' verbosity "curl" ["-LO", "https://github.com/wolfpld/tracy/archive/refs/tags/" ++ archive]+ rawSystemExit' verbosity "tar" ["-xzf", archive, "-C", "cbits/tracy", "--strip-components", "1"]+ removeFile archive++ preConf simpleUserHooks args config_flags++-- TODO: only build the executables which are enabled+--+postBuildHook :: Args -> BuildFlags -> PackageDescription -> LocalBuildInfo -> IO ()+postBuildHook args build_flags pkg_desc lbi = do+ let Platform _ os = hostPlatform lbi+ verbosity = fromFlagOrDefault normal $ buildVerbosity build_flags+ targets = [ ("tracy-capture", "capture", "tracy-capture")+ , ("tracy", "profiler", "tracy-profiler") ]++ when (tracyMode (configFlags lbi)) $ do+ case os of+ Windows -> return () -- XXX TODO: Windows users get the dummy executable that just throws an error+ _ ->+ forM_ targets $ \(hs_exe, c_dir, c_exe) -> do+ let cwd = flagToMaybe (workingDirFlag build_flags)+ c_projdir = "cbits/tracy" </> c_dir+ hs_builddir = interpretSymbolicPath cwd (buildDir lbi) </> hs_exe+ hs_tmpdir = hs_builddir </> hs_exe ++ "-tmp"++ -- TODO: This creates a separate build directory for each tracy+ -- executable (of which we build two, at the time of writing). This+ -- means that some duplicate work is done (building capstone twice).+ -- Could we share a build directory between the two?++ -- Existence of the hs_exe doesn't mean anything because before we+ -- overwrite it it's just a dummy executable. So check existence (and+ -- mtime) of the c_exe instead.+ c_exe_exists <- doesFileExist (hs_tmpdir </> c_exe)+ tracy_newer <- if c_exe_exists+ then do c_exe_modtime <- getModificationTime (hs_tmpdir </> c_exe)+ tracy_modtime <- getModificationTime "cbits/tracy"+ return (tracy_modtime > c_exe_modtime)+ else return True++ when tracy_newer $ do+ setupMessage verbosity (printf "Building executable '%s' from Tracy C++ sources for" hs_exe) (package pkg_desc)++ -- We set LEGACY=1 so that tracy builds with X11 instead of Wayland.+ rawSystemExit' verbosity "cmake" ["-B", hs_tmpdir, "-S", c_projdir, "-DCMAKE_BUILD_TYPE=Release", "-DLEGACY=1"]++ -- Build in parallel with 2 jobs because likely, accelerate is one of+ -- the last dependencies in a build, so we aren't stealing CPU time+ -- from other packages, and tracy takes way too long to build+ rawSystemExit' verbosity "cmake" ["--build", hs_tmpdir, "--config", "Release", "-j", "2"]++ -- Copy, not rename, to prevent cmake from linking again on the next+ -- reconfigure+ copyFile (hs_tmpdir </> c_exe) (hs_builddir </> hs_exe)++ postBuild simpleUserHooks args build_flags pkg_desc lbi++tracyMode :: ConfigFlags -> Bool+tracyMode config_flags =+ fromMaybe False $+ lookupFlagAssignment (mkFlagName "tracy") (configConfigurationsFlags config_flags)+++rawSystemExit' :: Verbosity -> FilePath -> [String] -> IO ()++#if MIN_VERSION_Cabal(3,14,0)+rawSystemExit' verb = rawSystemExit verb Nothing++workingDirFlag :: BuildFlags -> Flag (SymbolicPath CWD ('Dir Pkg))+workingDirFlag = setupWorkingDir . buildCommonFlags++-- interpretSymbolicPath is an actual useful function in Cabal-3.14+#else+rawSystemExit' = rawSystemExit++workingDirFlag :: BuildFlags -> Flag ()+workingDirFlag _ = NoFlag++interpretSymbolicPath :: Maybe () -> FilePath -> FilePath+interpretSymbolicPath _ = id+#endif
accelerate.cabal view
@@ -1,12 +1,13 @@-Name: accelerate-Version: 1.1.1.0-Cabal-version: >= 1.8-Tested-with: GHC >= 7.8-Build-type: Simple+cabal-version: 2.2 -Synopsis: An embedded language for accelerated array processing+name: accelerate+version: 1.4.0.0+tested-with: GHC >= 8.6+build-type: Custom -Description:+synopsis: An embedded language for accelerated array processing++description: @Data.Array.Accelerate@ defines an embedded array language for computations for high-performance computing in Haskell. Computations on multi-dimensional, regular arrays are expressed in the form of parameterised collective@@ -26,10 +27,12 @@ online-compiled for performance - for example, using @Data.Array.Accelerate.LLVM.PTX@ it may be on-the-fly off-loaded to the GPU. .+ See the "Data.Array.Accelerate" module for further information.+ . [/Additional components/] .- The following supported add-ons are available as separate packages. Install- them from Hackage with @cabal install \<package\>@+ The following supported add-ons are available as separate packages. Use them by+ adding them as dependencies to your project's cabal file. . * @accelerate-llvm-native@: Backend supporting parallel execution on multicore CPUs.@@ -39,20 +42,32 @@ greater. See the following table for supported GPUs: <http://en.wikipedia.org/wiki/CUDA#Supported_GPUs> .- * @accelerate-examples@: Computational kernels and applications showcasing- the use of Accelerate as well as a regression test suite, supporting- function and performance testing.+ * @containers-accelerate@: Container types for use with Accelerate. .- * @accelerate-io@: Fast conversions between Accelerate arrays and other- array formats (including vector and repa).+ * @hashable-accelerate@: Class for types which can be converted to a hash+ value. .+ * @colour-accelerate@: Colour representations in Accelerate (RGB, sRGB, HSV, and HSL).+ .+ * @mwc-random-accelerate@: Generate Accelerate arrays filled with high+ quality pseudorandom numbers.+ .+ Additional libraries that have worked in the past but are not included in the+ current release (they may be updated later, check to be sure):+ .+ * @accelerate-examples@: Computational kernels and applications+ demonstrating the use of Accelerate.+ .+ * @accelerate-io*@: Fast conversions between Accelerate arrays and other+ array and data formats.+ . * @accelerate-fft@: Discrete Fourier transforms, with FFI bindings to optimised implementations. .- * @accelerate-bignum@: Fixed-width large integer arithmetic.+ * @accelerate-blas@: Numeric linear algebra, with FFI bindings to optimised+ implementations. .- * @colour-accelerate@: Colour representations in Accelerate (RGB, sRGB, HSV,- and HSL).+ * @accelerate-bignum@: Fixed-width large integer arithmetic. . * @gloss-accelerate@: Generate gloss pictures from Accelerate. .@@ -63,19 +78,16 @@ . * @linear-accelerate@: Linear vector spaces in Accelerate. .- * @mwc-random-accelerate@: Generate Accelerate arrays filled with high- quality pseudorandom numbers.- . [/Examples and documentation/] .- Haddock documentation is included in the package+ Haddock documentation is included in the package. . The @accelerate-examples@ package demonstrates a range of computational kernels and several complete applications, including: . * An implementation of the Canny edge detection algorithm .- * An interactive Mandelbrot set generator+ * Interactive Mandelbrot and Julia set generators . * A particle-based simulation of stable fluid flows .@@ -85,8 +97,6 @@ . * A simple interactive ray tracer .- * A particle based simulation of stable fluid flows- . * A cellular automata simulation . * A \"password recovery\" tool, for dictionary lookup of MD5 hashes@@ -99,6 +109,8 @@ . [/Mailing list and contacts/] .+ * Gitter chat: <https://gitter.im/AccelerateHS/Lobby>+ . * Mailing list: <accelerate-haskell@googlegroups.com> (discussion of both use and development welcome). .@@ -109,38 +121,88 @@ <https://github.com/AccelerateHS/accelerate/issues> . -License: BSD3-License-file: LICENSE-Author: Manuel M T Chakravarty,- Robert Clifton-Everest,- Gabriele Keller,- Ben Lever,- Trevor L. McDonell,- Ryan Newtown,- Sean Seefried-Maintainer: Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>-Homepage: https://github.com/AccelerateHS/accelerate/-Bug-reports: https://github.com/AccelerateHS/accelerate/issues+license: BSD-3-Clause+license-file: LICENSE+author: The Accelerate Team+maintainer: Trevor L. McDonell <trevor.mcdonell@gmail.com>+homepage: https://github.com/AccelerateHS/accelerate/+bug-reports: https://github.com/AccelerateHS/accelerate/issues -Category: Compilers/Interpreters, Concurrency, Data, Parallelism-Stability: Experimental+category: Accelerate, Compilers/Interpreters, Concurrency, Data, Parallelism+stability: Experimental -Extra-source-files:+extra-source-files:+ cbits/*.c+ cbits/*.h+ -- XKCP+ cbits/xkcp/*.c+ cbits/xkcp/*.h+ cbits/xkcp/*.macros+ cbits/xkcp/*.inc+ -- TRACY+ -- These are referenced directly using the FFI+ cbits/tracy/public/*.cpp+ cbits/tracy/public/tracy/*.h+ cbits/tracy/public/tracy/*.hpp+ cbits/tracy/public/common/*.h+ cbits/tracy/public/common/*.hpp+ cbits/tracy/public/common/*.cpp+ cbits/tracy/public/client/*.h+ cbits/tracy/public/client/*.hpp+ cbits/tracy/public/client/*.cpp+ -- These are used to build Tracy's client tools in Setup.hs+ cbits/tracy/cmake/*.cmake+ cbits/tracy/cmake/*.patch+ cbits/tracy/capture/CMakeLists.txt+ cbits/tracy/profiler/CMakeLists.txt+ -- Used by Tracy's client tools+ cbits/tracy/capture/src/*.cpp+ cbits/tracy/dtl/*.hpp+ cbits/tracy/getopt/*.c+ cbits/tracy/getopt/*.h+ cbits/tracy/profiler/src/*.cpp+ cbits/tracy/profiler/src/*.c+ cbits/tracy/profiler/src/*.h+ cbits/tracy/profiler/src/*.hpp+ cbits/tracy/profiler/src/font/*.hpp+ cbits/tracy/profiler/src/profiler/*.cpp+ cbits/tracy/profiler/src/profiler/*.h+ cbits/tracy/profiler/src/profiler/*.hpp+ cbits/tracy/public/libbacktrace/*.cpp+ cbits/tracy/public/libbacktrace/*.h+ cbits/tracy/public/libbacktrace/*.hpp+ cbits/tracy/server/*.cpp+ cbits/tracy/server/*.h+ cbits/tracy/server/*.hpp++extra-doc-files:+ images/*.png README.md CHANGELOG.md -Flag debug- Default: False- Description:- Enable debug tracing messages. The following options are read from the- environment variable @ACCELERATE_FLAGS@, and via the command-line as:+custom-setup+ setup-depends:+ base >= 4.10 && < 4.23+ , Cabal >= 2 && < 3.18+ , cabal-doctest >= 1.0+ , directory >= 1.0+ , filepath >= 1.0++flag debug+ manual: True+ default: False+ description:+ Enable debug tracing messages. .+ With debugging enabled, applications will read the following options from+ the environment variable @ACCELERATE_FLAGS@, and via the command-line as:+ . > ./program +ACC ... -ACC . Note that a backend may not implement (or be applicable to) all options. . The following flags control phases of the compiler. The are enabled with- @-f\<flag\>@ and can be reveresed with @-fno-\<flag\>@:+ @-f\<flag\>@ and can be reversed with @-fno-\<flag\>@: . * @acc-sharing@: Enable sharing recovery of array expressions (True). .@@ -148,18 +210,21 @@ . * @fusion@: Enable array fusion (True). .- * @simplify@: Enable program simplification phase (True).- .- * @flush-cache@: Clear any persistent caches on program startup (False).+ * @inplace@: Enable in-place array updates (True). . * @force-recomp@: Force recompilation of array programs (False). . * @fast-math@: Allow algebraically equivalent transformations which may change floating point results (e.g., reassociate) (True). .+ * @fast-permute-const@: Allow non-atomic `permute const` for product types+ (True).+ . The following options control debug message output, and are enabled with @-d\<flag\>@. .+ * @debug@: Include debug symbols in the generated and compiled kernels.+ . * @verbose@: Be extra chatty. . * @dump-phases@: Print timing information about each phase of the compiler.@@ -186,8 +251,6 @@ * @dump-gc-stats@: Print aggregate garbage collection information at the end of program execution. .- * @dubug-cc@: Include debug symbols in the generated and compiled kernels.- . * @dump-cc@: Print information related to kernel code generation/compilation. Print the generated code if @verbose@. .@@ -199,120 +262,168 @@ * @dump-exec@: Print information related to program execution. . * @dump-sched@: Print information related to execution scheduling.- . -Flag ekg- Default: False- Description:- Enable hooks for monitoring the running application using EKG. Implies- @debug@ mode. In order to view the metrics, your application will need to- call @Data.Array.Accelerate.Debug.beginMonitoring@ before running any- Accelerate computations. This will launch the server on the local machine at- port 8000.+flag tracy+ manual: True+ default: False+ description:+ Enable kernel profiling using Tracy. This flag requires @+debug@ to also be+ set. Note: currently only works with @accelerate-llvm-native@; for PTX+ profiling, use Nvidia Nsight directly instead. .- Alternatively, if you wish to configure the EKG monitoring server you can- initialise it like so:+ The executables 'tracy' (GUI) and 'tracy-capture' (command line) will be+ built to collect and view profiling data from supported backends. This+ requires several external dependencies: .- > import Data.Array.Accelerate.Debug- >- > import System.Metrics- > import System.Remote.Monitoring- >- > main :: IO ()- > main = do- > store <- initAccMetrics- > registerGcMetrics store -- optional- >- > server <- forkServerWith store "localhost" 8000- >- > ...+ * cmake .- Note that, as with any program utilising EKG, in order to collect Haskell GC- statistics, you must either run the program with:+ * pkg-config .- > +RTS -T -RTS+ * freetype2 .- or compile it with:+ * glfw3 .- > -with-rtsopts=-T+ * gtk3 (linux only) .+ * TBB (should be part of your compiler toolchain)+ .+ For example on Debian/Ubuntu you can install all of these via:+ .+ > sudo apt install cmake pkg-config libfreetype-dev libglfw3-dev libgtk-3-dev libtbb-dev+ .+ Or on macOS via:+ .+ > brew install cmake pkg-config freetype glfw -Flag bounds-checks- Description: Enable bounds checking- Default: True+flag bounds-checks+ manual: True+ default: True+ description: Enable bounds checking in the interpreter -Flag unsafe-checks- Description: Enable bounds checking in unsafe operations- Default: False+-- This flag is currently completely unused, so let's not expose it to users+-- flag unsafe-checks+-- manual: True+-- default: False+-- description: Enable bounds checking in unsafe operations -Flag internal-checks- Description: Enable internal consistency checks- Default: False+flag internal-checks+ manual: True+ default: False+ description: Enable some internal consistency checks -Library- Build-depends:- base >= 4.7 && < 4.11+-- Enabling this increases build times+-- See: https://gitlab.haskell.org/ghc/ghc/issues/15751+flag nofib+ manual: True+ default: False+ description: Build the nofib test suite (required for backend testing)++library+ build-depends:+ base >= 4.12 && < 4.23+ , ansi-terminal >= 0.6.2 , base-orphans >= 0.3+ , bytestring >= 0.10.2 , containers >= 0.3 , deepseq >= 1.3 , directory >= 1.0+ , double-conversion >= 2.0 , exceptions >= 0.6- , fclabels >= 2.0 , filepath >= 1.0+ , formatting >= 7.0 , ghc-prim+ , half >= 0.3 , hashable >= 1.1- , hashtables >= 1.0+ , hashtables >= 1.2.3+ , hedgehog >= 0.5+ , microlens >= 0.4 , mtl >= 2.0- , ansi-wl-pprint >= 0.6- , template-haskell- , time >= 1.4+ , prettyprinter >= 1.7+ , prettyprinter-ansi-terminal >= 1.1.2+ , primitive >= 0.6.4+ , tasty >= 0.11+ , template-haskell < 2.25+ , terminal-size >= 0.3+ , text >= 1.2.4 , transformers >= 0.3 , unique , unordered-containers >= 0.2+ , vector >= 0.10 - Exposed-modules:+ exposed-modules: -- The core language and reference implementation Data.Array.Accelerate Data.Array.Accelerate.Interpreter -- Prelude-like+ Data.Array.Accelerate.Control.Monad Data.Array.Accelerate.Data.Bits Data.Array.Accelerate.Data.Complex+ Data.Array.Accelerate.Data.Either Data.Array.Accelerate.Data.Fold+ Data.Array.Accelerate.Data.Functor+ Data.Array.Accelerate.Data.Maybe Data.Array.Accelerate.Data.Monoid+ Data.Array.Accelerate.Data.Ratio+ Data.Array.Accelerate.Debug.Trace+ Data.Array.Accelerate.Unsafe - -- For backend development+ -- For backend development (hidden) Data.Array.Accelerate.AST+ Data.Array.Accelerate.AST.Environment+ Data.Array.Accelerate.AST.Idx+ Data.Array.Accelerate.AST.LeftHandSide+ Data.Array.Accelerate.AST.Var Data.Array.Accelerate.Analysis.Hash Data.Array.Accelerate.Analysis.Match- Data.Array.Accelerate.Analysis.Shape- Data.Array.Accelerate.Analysis.Stencil- Data.Array.Accelerate.Analysis.Type Data.Array.Accelerate.Array.Data Data.Array.Accelerate.Array.Remote Data.Array.Accelerate.Array.Remote.Class Data.Array.Accelerate.Array.Remote.LRU Data.Array.Accelerate.Array.Remote.Table- Data.Array.Accelerate.Array.Representation- Data.Array.Accelerate.Array.Sugar Data.Array.Accelerate.Array.Unique Data.Array.Accelerate.Async- Data.Array.Accelerate.Debug Data.Array.Accelerate.Error- Data.Array.Accelerate.FullList+ Data.Array.Accelerate.Debug.Internal Data.Array.Accelerate.Lifetime Data.Array.Accelerate.Pretty- Data.Array.Accelerate.Product+ Data.Array.Accelerate.Representation.Array+ Data.Array.Accelerate.Representation.Elt+ Data.Array.Accelerate.Representation.Shape+ Data.Array.Accelerate.Representation.Slice+ Data.Array.Accelerate.Representation.Stencil+ Data.Array.Accelerate.Representation.Tag+ Data.Array.Accelerate.Representation.Type+ Data.Array.Accelerate.Representation.Vec Data.Array.Accelerate.Smart+ Data.Array.Accelerate.Sugar.Array+ Data.Array.Accelerate.Sugar.Elt+ Data.Array.Accelerate.Sugar.Foreign+ Data.Array.Accelerate.Sugar.Shape+ Data.Array.Accelerate.Sugar.Vec Data.Array.Accelerate.Trafo+ Data.Array.Accelerate.Trafo.Config+ Data.Array.Accelerate.Trafo.Delayed+ Data.Array.Accelerate.Trafo.Fusion+ Data.Array.Accelerate.Trafo.LetSplit+ Data.Array.Accelerate.Trafo.Sharing+ Data.Array.Accelerate.Trafo.Simplify+ Data.Array.Accelerate.Trafo.Substitution+ Data.Array.Accelerate.Trafo.Var Data.Array.Accelerate.Type - Other-modules:- Data.Atomic+ -- For testing+ Data.Array.Accelerate.Test.NoFib+ Data.Array.Accelerate.Test.Similar++ -- Other+ Data.BitSet+ Data.Primitive.Vec+ Crypto.Hash.XKCP++ other-modules: Data.Array.Accelerate.Analysis.Hash.TH- Data.Array.Accelerate.Array.Lifted Data.Array.Accelerate.Array.Remote.Nursery- Data.Array.Accelerate.Classes Data.Array.Accelerate.Classes.Bounded Data.Array.Accelerate.Classes.Enum Data.Array.Accelerate.Classes.Eq@@ -322,91 +433,343 @@ Data.Array.Accelerate.Classes.Integral Data.Array.Accelerate.Classes.Num Data.Array.Accelerate.Classes.Ord+ Data.Array.Accelerate.Classes.Rational Data.Array.Accelerate.Classes.Real Data.Array.Accelerate.Classes.RealFloat Data.Array.Accelerate.Classes.RealFrac Data.Array.Accelerate.Classes.ToFloating- Data.Array.Accelerate.Debug.Flags- Data.Array.Accelerate.Debug.Monitoring- Data.Array.Accelerate.Debug.Stats- Data.Array.Accelerate.Debug.Timed- Data.Array.Accelerate.Debug.Trace+ Data.Array.Accelerate.Debug.Internal.Clock+ Data.Array.Accelerate.Debug.Internal.Flags+ Data.Array.Accelerate.Debug.Internal.Graph+ Data.Array.Accelerate.Debug.Internal.Profile+ Data.Array.Accelerate.Debug.Internal.Stats+ Data.Array.Accelerate.Debug.Internal.Timed+ Data.Array.Accelerate.Debug.Internal.Trace+ Data.Array.Accelerate.Debug.Internal.Tracy Data.Array.Accelerate.Language Data.Array.Accelerate.Lift+ Data.Array.Accelerate.Orphans+ Data.Array.Accelerate.Pattern+ Data.Array.Accelerate.Pattern.Bool+ Data.Array.Accelerate.Pattern.Either+ Data.Array.Accelerate.Pattern.Maybe+ Data.Array.Accelerate.Pattern.Ordering+ Data.Array.Accelerate.Pattern.TH Data.Array.Accelerate.Prelude Data.Array.Accelerate.Pretty.Graphviz Data.Array.Accelerate.Pretty.Graphviz.Monad Data.Array.Accelerate.Pretty.Graphviz.Type Data.Array.Accelerate.Pretty.Print Data.Array.Accelerate.Trafo.Algebra- Data.Array.Accelerate.Trafo.Base- Data.Array.Accelerate.Trafo.Fusion- Data.Array.Accelerate.Trafo.Rewrite- Data.Array.Accelerate.Trafo.Sharing+ Data.Array.Accelerate.Trafo.Environment Data.Array.Accelerate.Trafo.Shrink- Data.Array.Accelerate.Trafo.Simplify- Data.Array.Accelerate.Trafo.Substitution- -- Data.Array.Accelerate.Trafo.Vectorise+ Data.Atomic - c-sources: cbits/atomic.c+ -- Data.Array.Accelerate.Array.Lifted - if flag(debug) || flag(ekg)- cpp-options: -DACCELERATE_DEBUG+ -- nofib test suite+ Data.Array.Accelerate.Test.NoFib.Base+ Data.Array.Accelerate.Test.NoFib.Config - if flag(ekg)- cpp-options: -DACCELERATE_MONITORING+ Language.Haskell.TH.Extra++ if flag(nofib) build-depends:- async >= 2.0- , ekg >= 0.1- , ekg-core >= 0.1- , text >= 1.0- , time >= 1.4+ tasty-expected-failure >= 0.11+ , tasty-hedgehog >= 0.1+ , tasty-hunit >= 0.9+ , tasty-rerun >= 1.1+ -- , pipes >= 4.1.6 -- #286 - if flag(bounds-checks)- cpp-options: -DACCELERATE_BOUNDS_CHECKS+ other-modules:+ Data.Array.Accelerate.Test.NoFib.Sharing+ Data.Array.Accelerate.Test.NoFib.Prelude+ Data.Array.Accelerate.Test.NoFib.Prelude.Map+ Data.Array.Accelerate.Test.NoFib.Prelude.ZipWith+ Data.Array.Accelerate.Test.NoFib.Prelude.SIMD+ Data.Array.Accelerate.Test.NoFib.Prelude.Fold+ Data.Array.Accelerate.Test.NoFib.Prelude.Scan+ Data.Array.Accelerate.Test.NoFib.Prelude.Backpermute+ Data.Array.Accelerate.Test.NoFib.Prelude.Permute+ Data.Array.Accelerate.Test.NoFib.Prelude.Filter+ Data.Array.Accelerate.Test.NoFib.Prelude.Stencil+ Data.Array.Accelerate.Test.NoFib.Imaginary+ Data.Array.Accelerate.Test.NoFib.Imaginary.DotP+ Data.Array.Accelerate.Test.NoFib.Imaginary.SASUM+ Data.Array.Accelerate.Test.NoFib.Imaginary.SAXPY+ Data.Array.Accelerate.Test.NoFib.Spectral+ Data.Array.Accelerate.Test.NoFib.Spectral.SMVM+ Data.Array.Accelerate.Test.NoFib.Spectral.RadixSort+ Data.Array.Accelerate.Test.NoFib.Spectral.BlackScholes+ Data.Array.Accelerate.Test.NoFib.Issues+ Data.Array.Accelerate.Test.NoFib.Issues.Issue93+ Data.Array.Accelerate.Test.NoFib.Issues.Issue102+ Data.Array.Accelerate.Test.NoFib.Issues.Issue114+ Data.Array.Accelerate.Test.NoFib.Issues.Issue119+ Data.Array.Accelerate.Test.NoFib.Issues.Issue123+ Data.Array.Accelerate.Test.NoFib.Issues.Issue137+ Data.Array.Accelerate.Test.NoFib.Issues.Issue168+ Data.Array.Accelerate.Test.NoFib.Issues.Issue184+ Data.Array.Accelerate.Test.NoFib.Issues.Issue185+ Data.Array.Accelerate.Test.NoFib.Issues.Issue187+ Data.Array.Accelerate.Test.NoFib.Issues.Issue228+ Data.Array.Accelerate.Test.NoFib.Issues.Issue255+ Data.Array.Accelerate.Test.NoFib.Issues.Issue264+ -- Data.Array.Accelerate.Test.NoFib.Issues.Issue286+ Data.Array.Accelerate.Test.NoFib.Issues.Issue287+ Data.Array.Accelerate.Test.NoFib.Issues.Issue288+ Data.Array.Accelerate.Test.NoFib.Issues.Issue362+ Data.Array.Accelerate.Test.NoFib.Issues.Issue364+ Data.Array.Accelerate.Test.NoFib.Issues.Issue407+ Data.Array.Accelerate.Test.NoFib.Issues.Issue409+ Data.Array.Accelerate.Test.NoFib.Issues.Issue427+ Data.Array.Accelerate.Test.NoFib.Issues.Issue436+ Data.Array.Accelerate.Test.NoFib.Issues.Issue437+ Data.Array.Accelerate.Test.NoFib.Issues.Issue439+ Data.Array.Accelerate.Test.NoFib.Issues.Issue517+ Data.Array.Accelerate.Test.NoFib.Issues.Issue551+ Data.Array.Accelerate.Test.NoFib.Misc+ Data.Array.Accelerate.Test.NoFib.Misc.Cache+ Data.Array.Accelerate.Test.NoFib.Misc.Scanl1 - if flag(unsafe-checks)- cpp-options: -DACCELERATE_UNSAFE_CHECKS+ else+ cpp-options:+ -DACCELERATE_DISABLE_NOFIB - if flag(internal-checks)- cpp-options: -DACCELERATE_INTERNAL_CHECKS+ if impl(ghc >= 8.0)+ exposed-modules:+ Data.Array.Accelerate.Data.Semigroup - if os(windows)- cpp-options: -DWIN32- build-depends: Win32- else- cpp-options: -DUNIX- build-depends: unix+ default-language:+ Haskell2010 - ghc-options: -O2 -Wall -funbox-strict-fields -fno-warn-name-shadowing- ghc-prof-options: -caf-all -auto-all+ hs-source-dirs:+ src - if impl(ghc >= 7.0)- ghc-options: -fspec-constr-count=25+ cc-options:+ -O3+ -Wall - if impl(ghc == 7.*)- ghc-options: -fcontext-stack=35+ cxx-options:+ -O3+ -Wall+ -std=c++11 - if impl(ghc >= 8.0)- ghc-options: -freduction-depth=35+ ghc-options:+ -O2+ -Wall+ -Wcompat+ -- -Wredundant-constraints+ -freduction-depth=100+ -fspec-constr-count=50+ -funbox-strict-fields+ -optc=-O3+ -optc=-Wall - if impl(ghc < 7.10)+ if impl(ghc >= 8.10)+ ghc-options:+ -optcxx=-O3+ -optcxx=-Wall+ -optcxx=-std=c++11++ if flag(debug)+ cc-options:+ -DACCELERATE_DEBUG++ cpp-options:+ -DACCELERATE_DEBUG++ if flag(tracy)+ if !flag(debug)+ build-depends: accelerate-tracy-flag-depends-on-debug-flag < 0+ -- buildable: False -- this suppresses any other error output++ cc-options:+ -DACCELERATE_TRACY++ cpp-options:+ -DACCELERATE_TRACY+ -DTRACY_ENABLE+ -DTRACY_NO_SAMPLING++ cxx-options:+ -DTRACY_ENABLE+ -DTRACY_NO_SAMPLING++ if impl(ghc >= 8.10)+ ghc-options:+ -optcxx=-DTRACY_ENABLE+ -optcxx=-DTRACY_NO_SAMPLING++ -- Accelerate's backends may use dynamic linking to load compiled kernels+ -- that directly call Tracy's functions. In that case these symbols need to+ -- be available in the global namespace. @-rdynamic@ implies+ -- @-Wl,--export-dynamic@, which adds every symbol to the dynamic symbol+ -- table. There's also a @--export-dynamic-symbol=glob@ and a+ -- @--export-dynamic-symbol-list=file@ but these seem to be less portable+ -- between compilers.+ if !os(windows)+ ld-options:+ -rdynamic++ if flag(bounds-checks)+ cpp-options:+ -DACCELERATE_BOUNDS_CHECKS++ -- if flag(unsafe-checks)+ -- cpp-options:+ -- -DACCELERATE_UNSAFE_CHECKS++ if flag(internal-checks)+ cpp-options:+ -DACCELERATE_INTERNAL_CHECKS++ if os(windows)+ cc-options:+ -- https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65782+ -fno-asynchronous-unwind-tables+ ghc-options:+ -optc=-fno-asynchronous-unwind-tables+ -fexternal-interpreter build-depends:- th-lift-instances >= 0.1+ Win32+ else+ build-depends:+ unix + -- We assume only SSE2 to make Accelerate widely compatible; Windows 8+ -- assumes SSE2. However, we tune for native, see the next block.+ if !arch(aarch64)+ cc-options: -msse2+ cxx-options: -msse2+ ghc-options: -optc=-msse2+ if impl(ghc >= 8.10)+ ghc-options: -optcxx=-msse2++ -- https://stackoverflow.com/questions/65966969/why-does-march-native-not-work-on-apple-m1+ if !(os(darwin) && arch(aarch64))+ cc-options: -mtune=native+ cxx-options: -mtune=native+ ghc-options: -optc=-mtune=native+ if impl(ghc >= 8.10)+ ghc-options: -optcxx=-mtune=native+ -- Don't add the extensions list here. Instead, place individual LANGUAGE -- pragmas in the files that require a specific extension. This means the -- project loads in GHCi, and avoids extension clashes. -- -- Extensions: ++test-suite doctest+ type: exitcode-stdio-1.0+ default-language: Haskell2010+ hs-source-dirs: test/doctest+ main-is: Main.hs+ other-modules: Build_doctests+ autogen-modules: Build_doctests++ build-depends:+ base >= 4.10+ , accelerate+ , doctest >= 0.11++ ghc-options:+ -Wall+ -threaded+ -rtsopts++ x-doctest-options:+ -freduction-depth=100+ -fspec-constr-count=50++ if os(windows)+ ghc-options:+ -fexternal-interpreter+++test-suite nofib-interpreter+ type: exitcode-stdio-1.0+ default-language: Haskell2010+ hs-source-dirs: test/nofib+ main-is: Main.hs++ if !flag(nofib)+ buildable: False++ build-depends:+ base >= 4.10+ , accelerate+ , tasty++ ghc-options:+ -O2+ -Wall+ -threaded+ -rtsopts+ -with-rtsopts=-A128M+ -with-rtsopts=-n4M++ if os(windows)+ ghc-options:+ -fexternal-interpreter+++executable tracy+ default-language: Haskell2010+ hs-source-dirs: app+ main-is: Main.hs++ if !flag(tracy)+ buildable: False++ build-depends:+ base >= 4.10+ , accelerate+ , formatting++ pkgconfig-depends:+ freetype2+ , glfw3++ if !os(windows) && !os(darwin)+ pkgconfig-depends:+ gtk+-3.0++ cpp-options:+ -DEXECUTABLE="tracy"++ ghc-options:+ -O0+++executable tracy-capture+ default-language: Haskell2010+ hs-source-dirs: app+ main-is: Main.hs++ if !flag(tracy)+ buildable: False++ build-depends:+ base >= 4.10+ , accelerate+ , formatting++ cpp-options:+ -DEXECUTABLE="tracy-capure"++ ghc-options:+ -O0++ source-repository head Type: git- Location: git://github.com/AccelerateHS/accelerate.git+ Location: https://github.com/AccelerateHS/accelerate.git source-repository this Type: git- Tag: 1.1.1.0- Location: git://github.com/AccelerateHS/accelerate.git+ Tag: v1.4.0.0+ Location: https://github.com/AccelerateHS/accelerate.git -- vim: nospell
+ app/Main.hs view
@@ -0,0 +1,23 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-}+-- |+-- Module : Main+-- Copyright : [2016..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Main where++import Formatting+import Data.Array.Accelerate.Error++-- This should be replaced by the executable built via the Makefiles. If it+-- hasn't been something went wrong...+--+main :: IO ()+main = internalError ("Unexpected error building application " % squoted builder) EXECUTABLE+
+ cbits/align.h view
@@ -0,0 +1,24 @@+/*+ * Module : Data.Atomic.Align+ * Copyright : [2021] The Accelerate Team+ * License : BSD3+ *+ * Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+ * Stability : experimental+ * Portability : non-portable (GHC extensions)+ */++#ifndef __ACCELERATE_ALIGN_H__+#define __ACCELERATE_ALIGN_H__++/* Cache lines on x86_64 are 64-bytes. On a miss the pre-fetcher will fetch the+ * next cache line as well. Thus to prevent false sharing we need to pad hot+ * variables to 128-bytes.+ */+#define PAGE_SIZE 4096+#define CACHE_LINE_SIZE 64+#define CACHE_ALIGNED __attribute__((aligned(CACHE_LINE_SIZE)))+#define DOUBLE_CACHE_ALIGNED __attribute__((aligned(2 * CACHE_LINE_SIZE)))++#endif // __ACCELERATE_ALIGN_H__+
cbits/atomic.c view
@@ -1,12 +1,40 @@-#include "HsFFI.h"+/*+ * Module : Data.Atomic+ * Copyright : [2017..2020] The Accelerate Team+ * License : BSD3+ *+ * Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+ * Stability : experimental+ * Portability : non-portable (GHC extensions)+ *+ * Thread-safe atomic integer operations+ */ -StgInt64 hs_atomic_fetch_and_add_64(volatile StgInt64* ptr, StgInt64 val)+#include <stdint.h>++int64_t atomic_fetch_and_add_64(volatile int64_t* ptr, int64_t val) { return __sync_fetch_and_add(ptr, val); } -StgInt64 hs_atomic_fetch_and_and_64(volatile StgInt64* ptr, StgInt64 val)+int64_t atomic_fetch_and_sub_64(volatile int64_t* ptr, int64_t val) {+ return __sync_fetch_and_sub(ptr, val);+}++int64_t atomic_fetch_and_and_64(volatile int64_t* ptr, int64_t val)+{ return __sync_fetch_and_and(ptr, val);+}++int64_t atomic_read_64(volatile int64_t* ptr)+{+ return *ptr;+}++void atomic_write_64(volatile int64_t* ptr, int64_t val)+{+ *ptr = val;+ return; }
+ cbits/clock.c view
@@ -0,0 +1,145 @@+/*+ * Module : Data.Array.Accelerate.Debug.Clock+ * Copyright : [2017..2020] The Accelerate Team+ * License : BSD3+ *+ * Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+ * Stability : experimental+ * Portability : non-portable (GHC extensions)+ *+ * Get the monotonic wall-clock time.+ *+ * Implementations for macOS and Win32 stolen from the clock package, which has+ * a BSD3 license.+ *+ * <https://github.com/corsis/clock/tree/0.5.1>+ */++#if defined(__MACH__) && defined(__APPLE__)+/*+ * macOS+ *+ * macOS 10.12 also has clock_gettime(), so it might be worthwhile to use that+ * when available.+ */+#include <time.h>+#include <mach/clock.h>+#include <mach/mach.h>++static clock_serv_t __cclock;++/* constructors with priority execute before constructors without a priority+ * value.+ *+ * constructors with a lower [numeric] priority value are executed before+ * constructors with a higher [numeric] priority.+ *+ * constructor priority values [0,100] are reserved.+ */+__attribute__((constructor(101))) void initialise_clock_service(void)+{+ host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &__cclock);+}++/* destructors without a priority execute before destructors with a priority+ *+ * destructors with a higher [numeric] priority value are executed before+ * destructors with a lower priority value.+ *+ * destructor priority values [0,100] are reserved.+ */+__attribute__((destructor(101))) void deallocate_clock_service(void)+{+ mach_port_deallocate(mach_task_self(), __cclock);+}++static void clock_darwin_gettime(struct timespec *t)+{+ // OS X does not have clock_gettime, use clock_get_time+ // see http://stackoverflow.com/questions/11680461/monotonic-clock-on-osx+ mach_timespec_t mts;+ clock_get_time(__cclock, &mts);++ t->tv_sec = mts.tv_sec;+ t->tv_nsec = mts.tv_nsec;+}++double clock_gettime_monotonic_seconds()+{+ struct timespec t;+ clock_darwin_gettime(&t);++ return (double) t.tv_sec + (double) t.tv_nsec * 1.0E-9;+}++#elif defined(_WIN32)+/*+ * Windows+ */+#include <windows.h>++static long ticks_to_nanos(LONGLONG subsecond_time, LONGLONG frequency)+{+ return (long)((1E9 * subsecond_time) / frequency);+}++static void clock_win32_gettime_monotonic(long long* t)+{+ LARGE_INTEGER time;+ static LARGE_INTEGER frequency;+ static int hasFreq = 0;++ QueryPerformanceCounter(&time);+ if (!hasFreq)+ {+ hasFreq = 1;+ QueryPerformanceFrequency(&frequency);+ }++ // seconds+ t[0] = time.QuadPart / frequency.QuadPart;++ // nanoseconds+ t[1] = ticks_to_nanos(time.QuadPart % frequency.QuadPart, frequency.QuadPart);+}++double clock_gettime_monotonic_seconds()+{+ long long t[2];+ clock_win32_gettime_monotonic(t);++ return (double) t[0] + (double) t[1] * 1.0E-9;+}++#else+/*+ * *nix+ */+#include <time.h>++double clock_gettime_monotonic_seconds()+{+ struct timespec t;+ clock_gettime(CLOCK_MONOTONIC, &t);++ return (double) t.tv_sec + (double) t.tv_nsec * 1.0E-9;+}++#endif /* OS */+++static double __program_epoch;++double clock_gettime_elapsed_seconds(void)+{+ double now = clock_gettime_monotonic_seconds();+ double diff = now - __program_epoch;++ return diff;+}++__attribute__((constructor)) void initialise_program_epoch(void)+{+ __program_epoch = clock_gettime_monotonic_seconds();+}+
+ cbits/flags.c view
@@ -0,0 +1,428 @@+/*+ * Module : Data.Array.Accelerate.Debug.Flags+ * Copyright : [2017..2020] The Accelerate Team+ * License : BSD3+ *+ * Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+ * Stability : experimental+ * Portability : non-portable (GHC extensions)+ *+ * Option parsing for debug flags. This is a translation of the module+ * Data.Array.Accelerate.Debug.Flags into C, so that we can implement it at+ * program initialisation.+ *+ * This processes flags between +ACC ... -ACC on the command line. The+ * corresponding fields are removed from the command line. Note that we can't at+ * this stage update the number of command line arguments, but with some tricks+ * they can be mostly deleted.+ */++#include <ctype.h>+#include <inttypes.h>+#include <libgen.h>+#include <stdint.h>+#include <stdio.h>+#include <stdlib.h>+#include <stdbool.h>+#include <string.h>++#include "flags.h"+#include "getopt.h"+++/* SEE: [layout of command line options bitfield]+ * There are 7 default-enabled options, followed by 1 default-disabled option,+ * followed by 17 debug options.+ * Note the bit trick: ((1 << n) - 1) is a number with the lowest n bits set. */+static const uint32_t def_enabled_opts_bitfield = { (1<<7) - 1 };+#ifndef ACCELERATE_DEBUG+static const uint32_t debug_opts_bitfield = { ((1<<17) - 1) << (7+1) };+#endif+static const int disable_opts_offset = (7+1+17);++/* This global is accessed from the Haskell side. */+__flags_t __cmd_line_flags = { def_enabled_opts_bitfield };++enum {+ OPT_ENABLE = 1,+ OPT_DISABLE,+};++/* NOTE: [layout of command line options bitfield]+ *+ * HERE BE DRAGONS.+ *+ * When adding, removing, reordering, or changing options in ANY way, be aware+ * of the following:+ * - Various code relies on the fact (by bit hacks) that these options come in+ * this order: -f enablers, -d enablers, -f disablers.+ * - The -f enablers and -f disablers lists must be exactly the same, including+ * the order.+ * - The order of the options in __flags_t in flags.h must also be the same.+ * - Data.Array.Accelerate.Debug.Internal.Flags contains 2 blocks of code+ * hard-coding offsets into this options list.+ * - Some metrics about this options list used in the bit hacks are at the top+ * of this file (def_enabled_opts_bitfield etc.).+ */+static const char* shortopts = "";+static const struct option longopts[] =+ { { "fseq-sharing", no_argument, NULL, OPT_ENABLE }+ , { "facc-sharing", no_argument, NULL, OPT_ENABLE }+ , { "fexp-sharing", no_argument, NULL, OPT_ENABLE }+ , { "ffusion", no_argument, NULL, OPT_ENABLE }+ , { "finplace", no_argument, NULL, OPT_ENABLE }+ , { "ffast-math", no_argument, NULL, OPT_ENABLE }+ , { "ffast-permute-const", no_argument, NULL, OPT_ENABLE }+ , { "fforce-recomp", no_argument, NULL, OPT_ENABLE }++ , { "ddebug", no_argument, NULL, OPT_ENABLE }+ , { "dverbose", no_argument, NULL, OPT_ENABLE }+ , { "ddump-phases", no_argument, NULL, OPT_ENABLE }+ , { "ddump-sharing", no_argument, NULL, OPT_ENABLE }+ , { "ddump-fusion", no_argument, NULL, OPT_ENABLE }+ , { "ddump-simpl-stats", no_argument, NULL, OPT_ENABLE }+ , { "ddump-simpl-iterations", no_argument, NULL, OPT_ENABLE }+ , { "ddump-vectorisation", no_argument, NULL, OPT_ENABLE }+ , { "ddump-dot", no_argument, NULL, OPT_ENABLE }+ , { "ddump-simpl-dot", no_argument, NULL, OPT_ENABLE }+ , { "ddump-gc", no_argument, NULL, OPT_ENABLE }+ , { "ddump-gc-stats", no_argument, NULL, OPT_ENABLE }+ , { "ddump-cc", no_argument, NULL, OPT_ENABLE }+ , { "ddump-ld", no_argument, NULL, OPT_ENABLE }+ , { "ddump-asm", no_argument, NULL, OPT_ENABLE }+ , { "ddump-exec", no_argument, NULL, OPT_ENABLE }+ , { "ddump-sched", no_argument, NULL, OPT_ENABLE }++ , { "fno-seq-sharing", no_argument, NULL, OPT_DISABLE }+ , { "fno-acc-sharing", no_argument, NULL, OPT_DISABLE }+ , { "fno-exp-sharing", no_argument, NULL, OPT_DISABLE }+ , { "fno-fusion", no_argument, NULL, OPT_DISABLE }+ , { "fno-inplace", no_argument, NULL, OPT_DISABLE }+ , { "fno-fast-math", no_argument, NULL, OPT_DISABLE }+ , { "fno-fast-permute-const", no_argument, NULL, OPT_DISABLE }+ , { "fno-force-recomp", no_argument, NULL, OPT_DISABLE }++ /* There were options that took arguments here before; see the git blame of+ * this comment for how that looked. */++ /* required sentinel */+ , { NULL, 0, NULL, 0 }+ };+++/* Parse the given vector of command line arguments and set the corresponding+ * flags. The vector should contain no non-option arguments (aside from the name+ * of the program as the first entry, which is required for getopt()).+ */+static void parse_options(int argc, char *argv[])+{+ const struct option* opt;+ char* this;+ int did_show_banner;+ int prefix;+ int result;+ int longindex;++ while (-1 != (result = getopt_long_only(argc, argv, shortopts, longopts, &longindex)))+ {+ switch(result)+ {+ /* the option flag was set */+ case 0:+ break;++ case OPT_ENABLE:+ __cmd_line_flags.bitfield |= 1 << longindex;+ break;++ case OPT_DISABLE:+ __cmd_line_flags.bitfield &= ~(1 << (longindex - disable_opts_offset));+ break;++ /* option was ambiguous or was missing a required argument+ *+ * TLM: longindex is not being updated correctly on my system for the case+ * of an ambiguous argument, which makes it tricker to directly test+ * whether we got here due to a missing argument or ambiguous option.+ */+ case ':':+ case '?':+ opt = longopts;+ this = argv[optind-1];+ did_show_banner = 0;++ /* drop the leading '-' from the input command line argument */+ while (*this) {+ if ('-' == *this) {+ ++this;+ } else {+ break;+ }+ }+ prefix = strlen(this);++ /* display any options which are a prefix match for the ambiguous option */+ while (opt->name) {+ if (0 == strncmp(opt->name, this, prefix)) {+ /* only here can we determine if this was a missing argument case */+ if (opt->has_arg == required_argument)+ break;++ /* only show the banner if there are possible matches */+ if (0 == did_show_banner) {+ did_show_banner = 1;+ fprintf(stderr, "Did you mean one of these?\n");+ }+ fprintf(stderr, " -%s\n", opt->name);+ }+ ++opt;+ }+ break;++ default:+ fprintf(stderr, "failed to process command line options (%d)\n", result);+ abort();+ }+ }+#if !defined(ACCELERATE_DEBUG)+ if (__cmd_line_flags.bitfield & debug_opts_bitfield) {+ fprintf(stderr, "Data.Array.Accelerate: Debugging options are disabled.\n");+ fprintf(stderr, "Reinstall package 'accelerate' with '-fdebug' to enable them.\n");+ }+#endif+}+++/* This function will be run automatically before main() to process options sent+ * to the Accelerate runtime system.+ *+ * This processes both command line flags as well as those specified via the+ * environment variable "ACCELERATE_FLAGS" (with precedence to the former).+ *+ * The input 'argv' vector is mutated to remove the entries processed by this+ * module. This prevents the flags from interfering with the regular Haskell+ * program (in the same way as the RTS options). Note however that since we can+ * not update the 'argc' length of the vector, the removed entries are replaced+ * with "-RTS" (see the comment at the end of the function).+ */+static void process_options(int argc, char *argv[])+{+ /* Find the command line options which need to be processed. These will be+ * between +ACC ... [-ACC] (similar to the Haskell RTS options).+ *+ * First we collect the total number of command-line options. We also+ * already store what occurs where in the argument list, so that we only have+ * to do the complicated parsing once.+ *+ * Note that this function may well be called twice; this probably has+ * something to do with runtime loading of binaries in e.g.+ * accelerate-llvm-native (but I'm not sure). If so, we have already parsed+ * out +ACC stuff the first time round, and the GHC RTS has already removed+ * the +RTS flags including the -RTS drop-ins that we replaced the +ACC+ * arguments with. It does that by reordering arguments so that the non-RTS+ * ones come first, and by replacing the first not-an-argument-anymore with+ * NULL.+ *+ * Long story short, if we encounter a NULL, we have encountered what is,+ * according to the GHC RTS, de-facto the end of the argument list. So we+ * update argc and exit the loop.+ */+ typedef enum {+ PROC_OPT_OTHER, /* some non-accelerate argument */+ PROC_OPT_MARKER, /* +ACC or -ACC (not +/-RTS!) */+ PROC_OPT_OPT, /* an option for accelerate */+ } cl_option_t;+ cl_option_t *cl_option_type = malloc(argc * sizeof(cl_option_t));+ if (argc > 0) cl_option_type[0] = PROC_OPT_OTHER;++ int num_cl_options = 0; /* the number of PROC_OPT_OPT */++ {+ bool in_rts = false;+ bool in_acc = false;+ for (int i = 1; i < argc; ++i) {+ if (NULL == argv[i]) { /* see above */+ argc = i;+ break;+ }++ /* the default, overriden in the case analysis below */+ cl_option_type[i] = PROC_OPT_OTHER;++ if (0 == strncmp("+RTS", argv[i], 4)) {+ if (in_acc) {+ fprintf(stderr,+ "accelerate: error: a '+RTS' option found inside a '+ACC' block. Close the '+ACC'\n"+ "block using '-ACC' before opening a '+RTS' block. Continuing, assuming a '-ACC'.\n"+ );+ in_acc = false;+ }+ in_rts = true; /* let's not error on +RTS +RTS */++ } else if (0 == strncmp("-RTS", argv[i], 4)) {+ if (in_acc) {+ fprintf(stderr,+ "accelerate: error: a '-RTS' option found inside a '+ACC' block. Close the '+ACC'\n"+ "block using '-ACC' before opening a '+RTS' block. Continuing, assuming a '-ACC'.\n"+ );+ in_acc = false;+ }+ in_rts = false;++ } else if (0 == strncmp("+ACC", argv[i], 4)) {+ if (in_rts) {+ fprintf(stderr,+ "accelerate: error: a '+ACC' option found inside a '+RTS' block. Close the '+RTS'\n"+ "block using '-RTS' before opening a '+ACC' block.\n"+ );+ } else {+ in_acc = true;+ cl_option_type[i] = PROC_OPT_MARKER;+ }++ } else if (0 == strncmp("-ACC", argv[i], 4)) {+ /* inside +RTS, just leave them alone; the GHC RTS will error for us */+ if (!in_rts) {+ cl_option_type[i] = PROC_OPT_MARKER;+ in_acc = false;+ }++ } else {+ /* a normal argument */+ if (in_acc) {+ cl_option_type[i] = PROC_OPT_OPT;+ ++num_cl_options;+ }+ }+ }+ }++ /* Gather options from the ACCELERATE_FLAGS environment variable. Note that we+ * must not modify this variable, otherwise subsequent invocations of getenv()+ * will get the modified version.+ */+ char *env = getenv("ACCELERATE_FLAGS");+ int num_env_options = 0;++ if (NULL != env) {+ /* copy the environment string, as we will mutate it during tokenisation */+ char *p = env = strdup(env);++ /* first count how many tokens there are, so that we can allocate memory for+ * the combined options vector+ */+ while (*p) {+ while (*p && isspace(*p)) ++p;++ if (*p) {+ ++num_env_options;+ while (*p && !isspace(*p)) ++p;+ }+ }+ }++ /* Create the combined options vector containing both the environment and+ * command line options for parsing. The command line options are placed at+ * the end, so that they may override environment options.+ */+ int argc2 = 1 + num_env_options + num_cl_options;+ char** argv2 = NULL;++ if (argc2 > 1) {+ char** r = argv2 = malloc(argc2 * sizeof(char*));++ /* program name */+ *r++ = argv[0];++ /* environment variables */+ if (env) {+ char* p = env;+ while (*p) {+ while (*p && isspace(*p)) ++p;++ if (*p) {+ *r++ = p;+ while (*p && !isspace(*p)) ++p;++ if (isspace(*p)) {+ *p++ = '\0';+ }+ }+ }+ }++ /* command line flags */+ for (int i = 1; i < argc; ++i) {+ if (cl_option_type[i] == PROC_OPT_OPT) {+ *r++ = argv[i];+ }+ }++ /* finally process command lines */+ parse_options(argc2, argv2);+ }++ /* Remove the Accelerate options from the command line arguments which will be+ * passed to main(). We can't do this in a sensible fashion by updating argc,+ * but we can pull a small sleight-of-hand by rewriting them to -RTS, so that+ * they will be deleted by the GHC RTS when it is initialised.+ *+ * In this method, we can also update them in place, without permuting the+ * order of the options to place the (now unused) Accelerate flags at the end+ * of the vector.+ *+ * Note that we do not have to worry about a +RTS +ACC situation where this+ * replacement would change semantics, because we did not parse +ACC arguments+ * inside a +RTS block above.+ */+ for (int i = 1; i < argc; ++i) {+ /* Replace markers _and_ accelerate options. */+ if (cl_option_type[i] == PROC_OPT_MARKER ||+ cl_option_type[i] == PROC_OPT_OPT) {+ if (strlen(argv[i]) >= 4) {+ strcpy(argv[i], "-RTS");+ } else {+ argv[i] = malloc(5); /* 4 + the zero byte */+ strcpy(argv[i], "-RTS");+ }+ }+ }++ /* cleanup */+ if (cl_option_type) free(cl_option_type);+ if (argv2) free(argv2);+ if (env) free(env);+}++/* On Windows, the GHC RTS uses GetCommandLineW() to get the actual command line+ * using the Windows API; the memory that this function reads from cannot easily+ * be modified. Supposedly one can locate the PEB and modify the string+ * in-place, but that is too much hackery. So we'll just disable +ACC parsing on+ * Windows. */+#ifndef _WIN32++/* On MacOS, we use a constructor attribute, because .init_array seems to be a+ * Linux-only thing. */+#if defined(__APPLE__) && defined(__MACH__)+__attribute__((constructor))+static void process_options_constructor(int argc, char *argv[]) {+ process_options(argc, argv);+}+#else+/* On Linux(/BSD? Do we even support that?), register process_options() as a+ * constructor function in the new style by putting a reference to it in the+ * .init_array section. The advantage of this approach over simply using+ * __attribute__((constructor)) is that this way, the function will predictably+ * be called with the same arguments as main(). A simple constructor might+ * _accidentally_ be called with the same arguments as main(), but it isn't+ * defined to be, and sometimes will not be. (In particular, this failed with+ * clang on Windows, which is a bad reason to do this on Linux, but whatever.)+ * Source: https://stackoverflow.com/a/37358751 */+#pragma GCC diagnostic push+#pragma GCC diagnostic ignored "-Wunused-variable"+/* Add 'used' so that the variable is not optimised away. */+__attribute__((section(".init_array"), used))+ static void *process_options_ctor_entry = &process_options;+#pragma GCC diagnostic pop+#endif /* APPLE */+#endif /* WIN32 */
+ cbits/flags.h view
@@ -0,0 +1,52 @@+/*+ * Module : Data.Array.Accelerate.Debug.Flags+ * Copyright : [2017..2020] The Accelerate Team+ * License : BSD3+ *+ * Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+ * Stability : experimental+ * Portability : non-portable (GHC extensions)+ */++#ifndef __ACCELERATE_FLAGS_H__+#define __ACCELERATE_FLAGS_H__++#include <stdint.h>++/* NOTE: [layout of command line options bitfield]+ */+typedef union {+ uint32_t bitfield;++ struct {+ uint32_t seq_sharing : 1;+ uint32_t acc_sharing : 1;+ uint32_t exp_sharing : 1;+ uint32_t fusion : 1;+ uint32_t inplace : 1;+ uint32_t fast_math : 1;+ uint32_t fast_permute_const : 1;+ uint32_t force_recomp : 1;++ uint32_t debug : 1;+ uint32_t verbose : 1;+ uint32_t dump_phases : 1;+ uint32_t dump_sharing : 1;+ uint32_t dump_fusion : 1;+ uint32_t dump_simpl_stats : 1;+ uint32_t dump_simpl_iterations : 1;+ uint32_t dump_vectorisation : 1;+ uint32_t dump_dot : 1;+ uint32_t dump_simpl_dot : 1;+ uint32_t dump_gc : 1;+ uint32_t dump_gc_stats : 1;+ uint32_t dump_cc : 1;+ uint32_t dump_ld : 1;+ uint32_t dump_asm : 1;+ uint32_t dump_exec : 1;+ uint32_t dump_sched : 1;+ };+} __flags_t;++#endif // __ACCELERATE_FLAGS_H__+
+ cbits/getopt.h view
@@ -0,0 +1,80 @@+/* $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $ */+/* $FreeBSD$ */++/*-+ * SPDX-License-Identifier: BSD-2-Clause-NetBSD+ *+ * Copyright (c) 2000 The NetBSD Foundation, Inc.+ * All rights reserved.+ *+ * This code is derived from software contributed to The NetBSD Foundation+ * by Dieter Baron and Thomas Klausner.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ * notice, this list of conditions and the following disclaimer.+ * 2. Redistributions in binary form must reproduce the above copyright+ * notice, this list of conditions and the following disclaimer in the+ * documentation and/or other materials provided with the distribution.+ *+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.+ */++#ifndef _GETOPT_H_+#define _GETOPT_H_++#include <sys/cdefs.h>++/*+ * GNU-like getopt_long()/getopt_long_only() with 4.4BSD optreset extension.+ * getopt() is declared here too for GNU programs.+ */+#define no_argument 0+#define required_argument 1+#define optional_argument 2++struct option {+ /* name of long option */+ const char *name;+ /*+ * one of no_argument, required_argument, and optional_argument:+ * whether option takes an argument+ */+ int has_arg;+ /* if not NULL, set *flag to val when option found */+ int *flag;+ /* if flag not NULL, value to set *flag to; else return value */+ int val;+};++__BEGIN_DECLS+int getopt_long(int, char * const *, const char *,+ const struct option *, int *);+int getopt_long_only(int, char * const *, const char *,+ const struct option *, int *);+#ifndef _GETOPT_DECLARED+#define _GETOPT_DECLARED+int getopt(int, char * const [], const char *);++extern char *optarg; /* getopt(3) external variables */+extern int optind, opterr, optopt;+#endif+#ifndef _OPTRESET_DECLARED+#define _OPTRESET_DECLARED+extern int optreset; /* getopt(3) external variable */+#endif+__END_DECLS++#endif /* !_GETOPT_H_ */
+ cbits/getopt_long.c view
@@ -0,0 +1,642 @@+/* $OpenBSD: getopt_long.c,v 1.26 2013/06/08 22:47:56 millert Exp $ */+/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */++/*+ * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>+ *+ * Permission to use, copy, modify, and distribute this software for any+ * purpose with or without fee is hereby granted, provided that the above+ * copyright notice and this permission notice appear in all copies.+ *+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.+ *+ * Sponsored in part by the Defense Advanced Research Projects+ * Agency (DARPA) and Air Force Research Laboratory, Air Force+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.+ */+/*-+ * Copyright (c) 2000 The NetBSD Foundation, Inc.+ * All rights reserved.+ *+ * This code is derived from software contributed to The NetBSD Foundation+ * by Dieter Baron and Thomas Klausner.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ * notice, this list of conditions and the following disclaimer.+ * 2. Redistributions in binary form must reproduce the above copyright+ * notice, this list of conditions and the following disclaimer in the+ * documentation and/or other materials provided with the distribution.+ *+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.+ */++#include <sys/cdefs.h>++#include <errno.h>+#include <getopt.h>+#include <stdarg.h>+#include <stdio.h>+#include <stdlib.h>+#include <string.h>++#define GNU_COMPATIBLE /* Be more compatible, configure's use us! */++#if 1 /* we prefer to keep our getopt(3) */+#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */+#endif++#ifdef REPLACE_GETOPT+int opterr = 1; /* if error message should be printed */+int optind = 1; /* index into parent argv vector */+int optopt = '?'; /* character checked for validity */+int optreset; /* reset getopt */+char *optarg; /* argument associated with option */+#endif++#define PRINT_ERROR ((opterr) && (*options != ':'))++#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */+#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */+#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */++/* return values */+#define BADCH (int)'?'+#define BADARG ((*options == ':') ? (int)':' : (int)'?')+#define INORDER (int)1++static char EMSG[] = "";++#ifdef GNU_COMPATIBLE+#define NO_PREFIX (-1)+#define D_PREFIX 0+#define DD_PREFIX 1+#define W_PREFIX 2+#endif++static int getopt_internal(int, char * const *, const char *,+ const struct option *, int *, int);+static int parse_long_options(char * const *, const char *,+ const struct option *, int *, int, int);+static int gcd(int, int);+static void permute_args(int, int, int, char * const *);++static char *place = EMSG; /* option letter processing */++/* XXX: set optreset to 1 rather than these two */+static int nonopt_start = -1; /* first non option argument (for permute) */+static int nonopt_end = -1; /* first option after non options (for permute) */++/* Error messages */+static const char recargchar[] = "option requires an argument -- %c";+static const char illoptchar[] = "illegal option -- %c"; /* From P1003.2 */+#ifdef GNU_COMPATIBLE+static int dash_prefix = NO_PREFIX;+static const char gnuoptchar[] = "invalid option -- %c";++static const char recargstring[] = "option `%s%s' requires an argument";+static const char ambig[] = "option `%s%.*s' is ambiguous";+static const char noarg[] = "option `%s%.*s' doesn't allow an argument";+static const char illoptstring[] = "unrecognized option `%s%s'";+#else+static const char recargstring[] = "option requires an argument -- %s";+static const char ambig[] = "ambiguous option -- %.*s";+static const char noarg[] = "option doesn't take an argument -- %.*s";+static const char illoptstring[] = "unknown option -- %s";+#endif++/* XXX: work around lack of getprogname() */+static const char * prognamestring;++/* XXX: stolen from freebsd-src/lib/libc/gen/err.c */+static void+vwarnx(const char *fmt, va_list ap)+{+ int saved_errno = errno;+ FILE* err_file = stderr; /* XXX: simplified */++ fprintf(err_file, "%s: ", prognamestring);+ if (fmt != NULL)+ vfprintf(err_file, fmt, ap);+ fprintf(err_file, "\n");++ errno = saved_errno;+}++static void+warnx(const char* fmt, ...)+{+ va_list ap;+ va_start(ap, fmt);+ vwarnx(fmt, ap);+ va_end(ap);+}++/*+ * Compute the greatest common divisor of a and b.+ */+static int+gcd(int a, int b)+{+ int c;++ c = a % b;+ while (c != 0) {+ a = b;+ b = c;+ c = a % b;+ }++ return (b);+}++/*+ * Exchange the block from nonopt_start to nonopt_end with the block+ * from nonopt_end to opt_end (keeping the same order of arguments+ * in each block).+ */+static void+permute_args(int panonopt_start, int panonopt_end, int opt_end,+ char * const *nargv)+{+ int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;+ char *swap;++ /*+ * compute lengths of blocks and number and size of cycles+ */+ nnonopts = panonopt_end - panonopt_start;+ nopts = opt_end - panonopt_end;+ ncycle = gcd(nnonopts, nopts);+ cyclelen = (opt_end - panonopt_start) / ncycle;++ for (i = 0; i < ncycle; i++) {+ cstart = panonopt_end+i;+ pos = cstart;+ for (j = 0; j < cyclelen; j++) {+ if (pos >= panonopt_end)+ pos -= nnonopts;+ else+ pos += nopts;+ swap = nargv[pos];+ /* LINTED const cast */+ ((char **) nargv)[pos] = nargv[cstart];+ /* LINTED const cast */+ ((char **)nargv)[cstart] = swap;+ }+ }+}++/*+ * parse_long_options --+ * Parse long options in argc/argv argument vector.+ * Returns -1 if short_too is set and the option does not match long_options.+ */+static int+parse_long_options(char * const *nargv, const char *options,+ const struct option *long_options, int *idx, int short_too, int flags)+{+ char *current_argv, *has_equal;+#ifdef GNU_COMPATIBLE+ const char *current_dash;+#endif+ size_t current_argv_len;+ int i, match, exact_match, second_partial_match;++ current_argv = place;+#ifdef GNU_COMPATIBLE+ switch (dash_prefix) {+ case D_PREFIX:+ current_dash = "-";+ break;+ case DD_PREFIX:+ current_dash = "--";+ break;+ case W_PREFIX:+ current_dash = "-W ";+ break;+ default:+ current_dash = "";+ break;+ }+#endif+ match = -1;+ exact_match = 0;+ second_partial_match = 0;++ optind++;++ if ((has_equal = strchr(current_argv, '=')) != NULL) {+ /* argument found (--option=arg) */+ current_argv_len = has_equal - current_argv;+ has_equal++;+ } else+ current_argv_len = strlen(current_argv);++ for (i = 0; long_options[i].name; i++) {+ /* find matching long option */+ if (strncmp(current_argv, long_options[i].name,+ current_argv_len))+ continue;++ if (strlen(long_options[i].name) == current_argv_len) {+ /* exact match */+ match = i;+ exact_match = 1;+ break;+ }+ /*+ * If this is a known short option, don't allow+ * a partial match of a single character.+ */+ if (short_too && current_argv_len == 1)+ continue;++ if (match == -1) /* first partial match */+ match = i;+ else if ((flags & FLAG_LONGONLY) ||+ long_options[i].has_arg !=+ long_options[match].has_arg ||+ long_options[i].flag != long_options[match].flag ||+ long_options[i].val != long_options[match].val)+ second_partial_match = 1;+ }+ if (!exact_match && second_partial_match) {+ /* ambiguous abbreviation */+ if (PRINT_ERROR)+ warnx(ambig,+#ifdef GNU_COMPATIBLE+ current_dash,+#endif+ (int)current_argv_len,+ current_argv);+ optopt = 0;+ return (BADCH);+ }+ if (match != -1) { /* option found */+ if (long_options[match].has_arg == no_argument+ && has_equal) {+ if (PRINT_ERROR)+ warnx(noarg,+#ifdef GNU_COMPATIBLE+ current_dash,+#endif+ (int)current_argv_len,+ current_argv);+ /*+ * XXX: GNU sets optopt to val regardless of flag+ */+ if (long_options[match].flag == NULL)+ optopt = long_options[match].val;+ else+ optopt = 0;+#ifdef GNU_COMPATIBLE+ return (BADCH);+#else+ return (BADARG);+#endif+ }+ if (long_options[match].has_arg == required_argument ||+ long_options[match].has_arg == optional_argument) {+ if (has_equal)+ optarg = has_equal;+ else if (long_options[match].has_arg ==+ required_argument) {+ /*+ * optional argument doesn't use next nargv+ */+ optarg = nargv[optind++];+ }+ }+ if ((long_options[match].has_arg == required_argument)+ && (optarg == NULL)) {+ /*+ * Missing argument; leading ':' indicates no error+ * should be generated.+ */+ if (PRINT_ERROR)+ warnx(recargstring,+#ifdef GNU_COMPATIBLE+ current_dash,+#endif+ current_argv);+ /*+ * XXX: GNU sets optopt to val regardless of flag+ */+ if (long_options[match].flag == NULL)+ optopt = long_options[match].val;+ else+ optopt = 0;+ --optind;+ return (BADARG);+ }+ } else { /* unknown option */+ if (short_too) {+ --optind;+ return (-1);+ }+ if (PRINT_ERROR)+ warnx(illoptstring,+#ifdef GNU_COMPATIBLE+ current_dash,+#endif+ current_argv);+ optopt = 0;+ return (BADCH);+ }+ if (idx)+ *idx = match;+ if (long_options[match].flag) {+ *long_options[match].flag = long_options[match].val;+ return (0);+ } else+ return (long_options[match].val);+}++/*+ * getopt_internal --+ * Parse argc/argv argument vector. Called by user level routines.+ */+static int+getopt_internal(int nargc, char * const *nargv, const char *options,+ const struct option *long_options, int *idx, int flags)+{+ char *oli; /* option letter list index */+ int optchar, short_too;+ static int posixly_correct = -1;++ if (options == NULL)+ return (-1);++ /*+ * XXX work around lack of getprogname()+ */+ prognamestring = nargv[0];++ /*+ * XXX Some GNU programs (like cvs) set optind to 0 instead of+ * XXX using optreset. Work around this braindamage.+ */+ if (optind == 0)+ optind = optreset = 1;++ /*+ * Disable GNU extensions if POSIXLY_CORRECT is set or options+ * string begins with a '+'.+ */+ if (posixly_correct == -1 || optreset)+ posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);+ if (*options == '-')+ flags |= FLAG_ALLARGS;+ else if (posixly_correct || *options == '+')+ flags &= ~FLAG_PERMUTE;+ if (*options == '+' || *options == '-')+ options++;++ optarg = NULL;+ if (optreset)+ nonopt_start = nonopt_end = -1;+start:+ if (optreset || !*place) { /* update scanning pointer */+ optreset = 0;+ if (optind >= nargc) { /* end of argument vector */+ place = EMSG;+ if (nonopt_end != -1) {+ /* do permutation, if we have to */+ permute_args(nonopt_start, nonopt_end,+ optind, nargv);+ optind -= nonopt_end - nonopt_start;+ }+ else if (nonopt_start != -1) {+ /*+ * If we skipped non-options, set optind+ * to the first of them.+ */+ optind = nonopt_start;+ }+ nonopt_start = nonopt_end = -1;+ return (-1);+ }+ if (*(place = nargv[optind]) != '-' ||+#ifdef GNU_COMPATIBLE+ place[1] == '\0') {+#else+ (place[1] == '\0' && strchr(options, '-') == NULL)) {+#endif+ place = EMSG; /* found non-option */+ if (flags & FLAG_ALLARGS) {+ /*+ * GNU extension:+ * return non-option as argument to option 1+ */+ optarg = nargv[optind++];+ return (INORDER);+ }+ if (!(flags & FLAG_PERMUTE)) {+ /*+ * If no permutation wanted, stop parsing+ * at first non-option.+ */+ return (-1);+ }+ /* do permutation */+ if (nonopt_start == -1)+ nonopt_start = optind;+ else if (nonopt_end != -1) {+ permute_args(nonopt_start, nonopt_end,+ optind, nargv);+ nonopt_start = optind -+ (nonopt_end - nonopt_start);+ nonopt_end = -1;+ }+ optind++;+ /* process next argument */+ goto start;+ }+ if (nonopt_start != -1 && nonopt_end == -1)+ nonopt_end = optind;++ /*+ * If we have "-" do nothing, if "--" we are done.+ */+ if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {+ optind++;+ place = EMSG;+ /*+ * We found an option (--), so if we skipped+ * non-options, we have to permute.+ */+ if (nonopt_end != -1) {+ permute_args(nonopt_start, nonopt_end,+ optind, nargv);+ optind -= nonopt_end - nonopt_start;+ }+ nonopt_start = nonopt_end = -1;+ return (-1);+ }+ }++ /*+ * Check long options if:+ * 1) we were passed some+ * 2) the arg is not just "-"+ * 3) either the arg starts with -- we are getopt_long_only()+ */+ if (long_options != NULL && place != nargv[optind] &&+ (*place == '-' || (flags & FLAG_LONGONLY))) {+ short_too = 0;+#ifdef GNU_COMPATIBLE+ dash_prefix = D_PREFIX;+#endif+ if (*place == '-') {+ place++; /* --foo long option */+ if (*place == '\0')+ return (BADARG); /* malformed option */+#ifdef GNU_COMPATIBLE+ dash_prefix = DD_PREFIX;+#endif+ } else if (*place != ':' && strchr(options, *place) != NULL)+ short_too = 1; /* could be short option too */++ optchar = parse_long_options(nargv, options, long_options,+ idx, short_too, flags);+ if (optchar != -1) {+ place = EMSG;+ return (optchar);+ }+ }++ if ((optchar = (int)*place++) == (int)':' ||+ (optchar == (int)'-' && *place != '\0') ||+ (oli = strchr(options, optchar)) == NULL) {+ /*+ * If the user specified "-" and '-' isn't listed in+ * options, return -1 (non-option) as per POSIX.+ * Otherwise, it is an unknown option character (or ':').+ */+ if (optchar == (int)'-' && *place == '\0')+ return (-1);+ if (!*place)+ ++optind;+#ifdef GNU_COMPATIBLE+ if (PRINT_ERROR)+ warnx(posixly_correct ? illoptchar : gnuoptchar,+ optchar);+#else+ if (PRINT_ERROR)+ warnx(illoptchar, optchar);+#endif+ optopt = optchar;+ return (BADCH);+ }+ if (long_options != NULL && optchar == 'W' && oli[1] == ';') {+ /* -W long-option */+ if (*place) /* no space */+ /* NOTHING */;+ else if (++optind >= nargc) { /* no arg */+ place = EMSG;+ if (PRINT_ERROR)+ warnx(recargchar, optchar);+ optopt = optchar;+ return (BADARG);+ } else /* white space */+ place = nargv[optind];+#ifdef GNU_COMPATIBLE+ dash_prefix = W_PREFIX;+#endif+ optchar = parse_long_options(nargv, options, long_options,+ idx, 0, flags);+ place = EMSG;+ return (optchar);+ }+ if (*++oli != ':') { /* doesn't take argument */+ if (!*place)+ ++optind;+ } else { /* takes (optional) argument */+ optarg = NULL;+ if (*place) /* no white space */+ optarg = place;+ else if (oli[1] != ':') { /* arg not optional */+ if (++optind >= nargc) { /* no arg */+ place = EMSG;+ if (PRINT_ERROR)+ warnx(recargchar, optchar);+ optopt = optchar;+ return (BADARG);+ } else+ optarg = nargv[optind];+ }+ place = EMSG;+ ++optind;+ }+ /* dump back option letter */+ return (optchar);+}++#ifdef REPLACE_GETOPT+/*+ * getopt --+ * Parse argc/argv argument vector.+ *+ * [eventually this will replace the BSD getopt]+ */+int+getopt(int nargc, char * const *nargv, const char *options)+{++ /*+ * We don't pass FLAG_PERMUTE to getopt_internal() since+ * the BSD getopt(3) (unlike GNU) has never done this.+ *+ * Furthermore, since many privileged programs call getopt()+ * before dropping privileges it makes sense to keep things+ * as simple (and bug-free) as possible.+ */+ return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));+}+#endif /* REPLACE_GETOPT */++/*+ * getopt_long --+ * Parse argc/argv argument vector.+ */+int+getopt_long(int nargc, char * const *nargv, const char *options,+ const struct option *long_options, int *idx)+{++ return (getopt_internal(nargc, nargv, options, long_options, idx,+ FLAG_PERMUTE));+}++/*+ * getopt_long_only --+ * Parse argc/argv argument vector.+ */+int+getopt_long_only(int nargc, char * const *nargv, const char *options,+ const struct option *long_options, int *idx)+{++ return (getopt_internal(nargc, nargv, options, long_options, idx,+ FLAG_PERMUTE|FLAG_LONGONLY));+}+
+ cbits/monitoring.c view
@@ -0,0 +1,137 @@+/*+ * Module : Data.Array.Accelerate.Debug.Monitoring+ * Copyright : [2016..2020] The Accelerate Team+ * License : BSD3+ *+ * Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+ * Stability : experimental+ * Portability : non-portable (GHC extensions)+ *+ * Support for runtime system monitoring+ *+ * This is a hack to work around <https://github.com/haskell/cabal/issues/4937>+ */++#include <inttypes.h>+#include <stdint.h>+#include <stdio.h>++#include "align.h"+#include "flags.h"+++/* These monitoring counters are globals which will be accessed from the+ * Haskell side.+ */+int64_t DOUBLE_CACHE_ALIGNED __total_bytes_allocated_local = 0;+int64_t DOUBLE_CACHE_ALIGNED __total_bytes_allocated_remote = 0;+int64_t DOUBLE_CACHE_ALIGNED __total_bytes_copied_to_remote = 0;+int64_t DOUBLE_CACHE_ALIGNED __total_bytes_copied_from_remote = 0;+int64_t DOUBLE_CACHE_ALIGNED __total_bytes_evicted_from_remote = 0;+int64_t DOUBLE_CACHE_ALIGNED __num_remote_gcs = 0;+int64_t DOUBLE_CACHE_ALIGNED __num_evictions = 0;++/* cbits/flags.c */+extern __flags_t __cmd_line_flags;++#if defined(ACCELERATE_DEBUG)++/* cbits/clock.c */+double clock_gettime_elapsed_seconds(void);++/*+ * Format a large number, using comma separators.+ */+static char* format_int64(char *buffer, int64_t x)+{+ char *s = buffer;++ if (x < 0)+ {+ *s++ = '-';+ x = -x;+ }++ if (x < 1000)+ {+ sprintf(s, "%"PRIi64, x);+ }+ else if (x < 1000000)+ {+ sprintf(s, "%"PRIi64",%03"PRIi64, x/1000, x%1000);+ }+ else if (x < 1000000000)+ {+ sprintf(s, "%"PRIi64",%03"PRIi64",%03"PRIi64+ , x/1000000+ , (x/1000)%1000+ , x%1000);+ }+ else if (x < 1000000000000)+ {+ sprintf(s, "%"PRIi64",%03"PRIi64",%03"PRIi64",%03"PRIi64+ , x/1000000000+ , (x/1000000)%1000+ , (x/1000)%1000+ , x%1000);+ }+ else if (x < 1000000000000000)+ {+ sprintf(s, "%"PRIi64",%03"PRIi64",%03"PRIi64",%03"PRIi64",%03"PRIi64+ , x/1000000000000+ , (x/1000000000)%1000+ , (x/1000000)%1000+ , (x/1000)%1000+ , x%1000);+ }+ else if (x < 1000000000000000000)+ {+ sprintf(s, "%"PRIi64",%03"PRIi64",%03"PRIi64",%03"PRIi64",%03"PRIi64",%03"PRIi64+ , x/1000000000000000+ , (x/1000000000000)%1000+ , (x/1000000000)%1000+ , (x/1000000)%1000+ , (x/1000)%1000+ , x%1000);+ }+ else+ {+ sprintf(s, "%"PRIi64",%03"PRIi64",%03"PRIi64",%03"PRIi64",%03"PRIi64",%03"PRIi64",%03"PRIi64+ , x/1000000000000000000+ , (x/1000000000000000)%1000+ , (x/1000000000000)%1000+ , (x/1000000000)%1000+ , (x/1000000)%1000+ , (x/1000)%1000+ , x%1000);+ }++ return buffer;+}++/*+ * This function runs after main(), and is used to print final GC and memory+ * statistics (if enabled). This is similar to the +RTS -s option.+ */+__attribute__((destructor)) void dump_gc_stats(void)+{+ if (__cmd_line_flags.dump_gc_stats) {+ /*+ * int64 ranges from -9223372036854775807..9223372036854775807, so we need a+ * buffer size of at least 27 characters (including the terminating \0) to+ * format any number with commas.+ */+ char buffer[96];+ double timestamp = clock_gettime_elapsed_seconds();++ fprintf(stderr, "\n");+ fprintf(stderr, "[%8.3f] gc: %s bytes allocated locally\n", timestamp, format_int64(buffer, __total_bytes_allocated_local));+ fprintf(stderr, "[%8.3f] gc: %s bytes allocated on the remote device\n", timestamp, format_int64(buffer, __total_bytes_allocated_remote));+ fprintf(stderr, "[%8.3f] gc: %s bytes copied to the remote device\n", timestamp, format_int64(buffer, __total_bytes_copied_to_remote));+ fprintf(stderr, "[%8.3f] gc: %s bytes copied from the remote device\n", timestamp, format_int64(buffer, __total_bytes_copied_from_remote));+ fprintf(stderr, "[%8.3f] gc: %s bytes evicted from the remote (%s evictions, %s GCs)\n", timestamp, format_int64(&buffer[0], __total_bytes_evicted_from_remote), format_int64(&buffer[32], __num_evictions), format_int64(&buffer[64], __num_remote_gcs));+ }+}++#endif /* ACCELERATE_DEBUG */+
+ cbits/tracy/capture/CMakeLists.txt view
@@ -0,0 +1,28 @@+cmake_minimum_required(VERSION 3.16)++option(NO_ISA_EXTENSIONS "Disable ISA extensions (don't pass -march=native or -mcpu=native to the compiler)" OFF)+option(NO_STATISTICS "Disable calculation of statistics" ON)++include(${CMAKE_CURRENT_LIST_DIR}/../cmake/version.cmake)++set(CMAKE_CXX_STANDARD 20)++project(+ tracy-capture+ LANGUAGES C CXX+ VERSION ${TRACY_VERSION_STRING}+)++include(${CMAKE_CURRENT_LIST_DIR}/../cmake/config.cmake)+include(${CMAKE_CURRENT_LIST_DIR}/../cmake/vendor.cmake)+include(${CMAKE_CURRENT_LIST_DIR}/../cmake/server.cmake)++set(PROGRAM_FILES+ src/capture.cpp+)++add_executable(${PROJECT_NAME} ${PROGRAM_FILES} ${COMMON_FILES} ${SERVER_FILES})+target_link_libraries(${PROJECT_NAME} PRIVATE TracyServer TracyGetOpt)+set_property(DIRECTORY ${CMAKE_CURRENT_LIST_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME})++install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
+ cbits/tracy/capture/src/capture.cpp view
@@ -0,0 +1,364 @@+#ifdef _WIN32+# include <windows.h>+# include <io.h>+#else+# include <unistd.h>+#endif++#include <atomic>+#include <chrono>+#include <inttypes.h>+#include <mutex>+#include <signal.h>+#include <stdarg.h>+#include <stdint.h>+#include <stdio.h>+#include <stdlib.h>+#include <sys/stat.h>++#include "../../public/common/TracyProtocol.hpp"+#include "../../public/common/TracyStackFrames.hpp"+#include "../../server/TracyFileWrite.hpp"+#include "../../server/TracyMemory.hpp"+#include "../../server/TracyPrint.hpp"+#include "../../server/TracySysUtil.hpp"+#include "../../server/TracyWorker.hpp"++#ifdef _WIN32+# include "../../getopt/getopt.h"+#endif+++// This atomic is written by a signal handler (SigInt). Traditionally that would+// have had to be `volatile sig_atomic_t`, and annoyingly, `bool` was+// technically not allowed there, even though in practice it would work.+// The good thing with C++11 atomics is that we can use atomic<bool> instead+// here and be on the actually supported path.+static std::atomic<bool> s_disconnect { false };++void SigInt( int )+{+ // Relaxed order is closest to a traditional `volatile` write.+ // We don't need stronger ordering since this signal handler doesn't do+ // anything else that would need to be ordered relatively to this.+ s_disconnect.store(true, std::memory_order_relaxed);+}++static bool s_isStdoutATerminal = false;++void InitIsStdoutATerminal() {+#ifdef _WIN32+ s_isStdoutATerminal = _isatty( fileno( stdout ) );+#else+ s_isStdoutATerminal = isatty( fileno( stdout ) );+#endif+}++bool IsStdoutATerminal() { return s_isStdoutATerminal; }++#define ANSI_RESET "\033[0m"+#define ANSI_BOLD "\033[1m"+#define ANSI_BLACK "\033[30m"+#define ANSI_RED "\033[31m"+#define ANSI_GREEN "\033[32m"+#define ANSI_YELLOW "\033[33m"+#define ANSI_BLUE "\033[34m"+#define ANSI_MAGENTA "\033[35m"+#define ANSI_CYAN "\033[36m"+#define ANSI_ERASE_LINE "\033[2K"++// Like printf, but if stdout is a terminal, prepends the output with+// the given `ansiEscape` and appends ANSI_RESET.+void AnsiPrintf( const char* ansiEscape, const char* format, ... ) {+ if( IsStdoutATerminal() )+ {+ // Prepend ansiEscape and append ANSI_RESET.+ char buf[256];+ va_list args;+ va_start( args, format );+ vsnprintf( buf, sizeof buf, format, args );+ va_end( args );+ printf( "%s%s" ANSI_RESET, ansiEscape, buf );+ }+ else+ {+ // Just a normal printf.+ va_list args;+ va_start( args, format );+ vfprintf( stdout, format, args );+ va_end( args );+ }+}++[[noreturn]] void Usage()+{+ printf( "Usage: capture -o output.tracy [-a address] [-p port] [-f] [-s seconds] [-m memlimit]\n" );+ exit( 1 );+}++int main( int argc, char** argv )+{+#ifdef _WIN32+ if( !AttachConsole( ATTACH_PARENT_PROCESS ) )+ {+ AllocConsole();+ SetConsoleMode( GetStdHandle( STD_OUTPUT_HANDLE ), 0x07 );+ }+#endif++ InitIsStdoutATerminal();++ bool overwrite = false;+ const char* address = "127.0.0.1";+ const char* output = nullptr;+ int port = 8086;+ int seconds = -1;+ int64_t memoryLimit = -1;++ int c;+ while( ( c = getopt( argc, argv, "a:o:p:fs:m:" ) ) != -1 )+ {+ switch( c )+ {+ case 'a':+ address = optarg;+ break;+ case 'o':+ output = optarg;+ break;+ case 'p':+ port = atoi( optarg );+ break;+ case 'f':+ overwrite = true;+ break;+ case 's':+ seconds = atoi(optarg);+ break;+ case 'm':+ memoryLimit = std::clamp( atoll( optarg ), 1ll, 999ll ) * tracy::GetPhysicalMemorySize() / 100;+ break;+ default:+ Usage();+ break;+ }+ }++ if( !address || !output ) Usage();++ struct stat st;+ if( stat( output, &st ) == 0 && !overwrite )+ {+ printf( "Output file %s already exists! Use -f to force overwrite.\n", output );+ return 4;+ }++ FILE* test = fopen( output, "wb" );+ if( !test )+ {+ printf( "Cannot open output file %s for writing!\n", output );+ return 5;+ }+ fclose( test );+ unlink( output );++ printf( "Connecting to %s:%i...", address, port );+ fflush( stdout );+ tracy::Worker worker( address, port, memoryLimit );+ while( !worker.HasData() )+ {+ const auto handshake = worker.GetHandshakeStatus();+ if( handshake == tracy::HandshakeProtocolMismatch )+ {+ printf( "\nThe client you are trying to connect to uses incompatible protocol version.\nMake sure you are using the same Tracy version on both client and server.\n" );+ return 1;+ }+ if( handshake == tracy::HandshakeNotAvailable )+ {+ printf( "\nThe client you are trying to connect to is no longer able to sent profiling data,\nbecause another server was already connected to it.\nYou can do the following:\n\n 1. Restart the client application.\n 2. Rebuild the client application with on-demand mode enabled.\n" );+ return 2;+ }+ if( handshake == tracy::HandshakeDropped )+ {+ printf( "\nThe client you are trying to connect to has disconnected during the initial\nconnection handshake. Please check your network configuration.\n" );+ return 3;+ }+ std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) );+ }+ printf( "\nQueue delay: %s\nTimer resolution: %s\n", tracy::TimeToString( worker.GetDelay() ), tracy::TimeToString( worker.GetResolution() ) );++#ifdef _WIN32+ signal( SIGINT, SigInt );+#else+ struct sigaction sigint, oldsigint;+ memset( &sigint, 0, sizeof( sigint ) );+ sigint.sa_handler = SigInt;+ sigaction( SIGINT, &sigint, &oldsigint );+#endif++ const auto firstTime = worker.GetFirstTime();+ auto& lock = worker.GetMbpsDataLock();++ const auto t0 = std::chrono::high_resolution_clock::now();+ while( worker.IsConnected() )+ {+ // Relaxed order is sufficient here because `s_disconnect` is only ever+ // set by this thread or by the SigInt handler, and that handler does+ // nothing else than storing `s_disconnect`.+ if( s_disconnect.load( std::memory_order_relaxed ) )+ {+ worker.Disconnect();+ // Relaxed order is sufficient because only this thread ever reads+ // this value.+ s_disconnect.store(false, std::memory_order_relaxed );+ break;+ }++ lock.lock();+ const auto mbps = worker.GetMbpsData().back();+ const auto compRatio = worker.GetCompRatio();+ const auto netTotal = worker.GetDataTransferred();+ lock.unlock();++ // Output progress info only if destination is a TTY to avoid bloating+ // log files (so this is not just about usage of ANSI color codes).+ if( IsStdoutATerminal() )+ {+ const char* unit = "Mbps";+ float unitsPerMbps = 1.f;+ if( mbps < 0.1f )+ {+ unit = "Kbps";+ unitsPerMbps = 1000.f;+ }+ AnsiPrintf( ANSI_ERASE_LINE ANSI_CYAN ANSI_BOLD, "\r%7.2f %s", mbps * unitsPerMbps, unit );+ printf( " /");+ AnsiPrintf( ANSI_CYAN ANSI_BOLD, "%5.1f%%", compRatio * 100.f );+ printf( " =");+ AnsiPrintf( ANSI_YELLOW ANSI_BOLD, "%7.2f Mbps", mbps / compRatio );+ printf( " | ");+ AnsiPrintf( ANSI_YELLOW, "Tx: ");+ AnsiPrintf( ANSI_GREEN, "%s", tracy::MemSizeToString( netTotal ) );+ printf( " | ");+ AnsiPrintf( ANSI_RED ANSI_BOLD, "%s", tracy::MemSizeToString( tracy::memUsage.load( std::memory_order_relaxed ) ) );+ if( memoryLimit > 0 )+ {+ printf( " / " );+ AnsiPrintf( ANSI_BLUE ANSI_BOLD, "%s", tracy::MemSizeToString( memoryLimit ) );+ }+ printf( " | ");+ AnsiPrintf( ANSI_RED, "%s", tracy::TimeToString( worker.GetLastTime() - firstTime ) );+ fflush( stdout );+ }++ std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) );+ if( seconds != -1 )+ {+ const auto dur = std::chrono::high_resolution_clock::now() - t0;+ if( std::chrono::duration_cast<std::chrono::seconds>(dur).count() >= seconds )+ {+ // Relaxed order is sufficient because only this thread ever reads+ // this value.+ s_disconnect.store(true, std::memory_order_relaxed );+ }+ }+ }+ const auto t1 = std::chrono::high_resolution_clock::now();++ const auto& failure = worker.GetFailureType();+ if( failure != tracy::Worker::Failure::None )+ {+ AnsiPrintf( ANSI_RED ANSI_BOLD, "\nInstrumentation failure: %s", tracy::Worker::GetFailureString( failure ) );+ auto& fd = worker.GetFailureData();+ if( !fd.message.empty() )+ {+ printf( "\nContext: %s", fd.message.c_str() );+ }+ if( fd.callstack != 0 )+ {+ AnsiPrintf( ANSI_BOLD, "\nFailure callstack:\n" );+ auto& cs = worker.GetCallstack( fd.callstack );+ int fidx = 0;+ for( auto& entry : cs )+ {+ auto frameData = worker.GetCallstackFrame( entry );+ if( !frameData )+ {+ printf( "%3i. %p\n", fidx++, (void*)worker.GetCanonicalPointer( entry ) );+ }+ else+ {+ const auto fsz = frameData->size;+ for( uint8_t f=0; f<fsz; f++ )+ {+ const auto& frame = frameData->data[f];+ auto txt = worker.GetString( frame.name );++ if( fidx == 0 && f != fsz-1 )+ {+ auto test = tracy::s_tracyStackFrames;+ bool match = false;+ do+ {+ if( strcmp( txt, *test ) == 0 )+ {+ match = true;+ break;+ }+ }+ while( *++test );+ if( match ) continue;+ }++ if( f == fsz-1 )+ {+ printf( "%3i. ", fidx++ );+ }+ else+ {+ AnsiPrintf( ANSI_BLACK ANSI_BOLD, "inl. " );+ }+ AnsiPrintf( ANSI_CYAN, "%s ", txt );+ txt = worker.GetString( frame.file );+ if( frame.line == 0 )+ {+ AnsiPrintf( ANSI_YELLOW, "(%s)", txt );+ }+ else+ {+ AnsiPrintf( ANSI_YELLOW, "(%s:%" PRIu32 ")", txt, frame.line );+ }+ if( frameData->imageName.Active() )+ {+ AnsiPrintf( ANSI_MAGENTA, " %s\n", worker.GetString( frameData->imageName ) );+ }+ else+ {+ printf( "\n" );+ }+ }+ }+ }+ }+ }++ printf( "\nFrames: %" PRIu64 "\nTime span: %s\nZones: %s\nElapsed time: %s\nSaving trace...",+ worker.GetFrameCount( *worker.GetFramesBase() ), tracy::TimeToString( worker.GetLastTime() - firstTime ), tracy::RealToString( worker.GetZoneCount() ),+ tracy::TimeToString( std::chrono::duration_cast<std::chrono::nanoseconds>( t1 - t0 ).count() ) );+ fflush( stdout );+ auto f = std::unique_ptr<tracy::FileWrite>( tracy::FileWrite::Open( output, tracy::FileCompression::Zstd, 3, 4 ) );+ if( f )+ {+ worker.Write( *f, false );+ AnsiPrintf( ANSI_GREEN ANSI_BOLD, " done!\n" );+ f->Finish();+ const auto stats = f->GetCompressionStatistics();+ printf( "Trace size %s (%.2f%% ratio)\n", tracy::MemSizeToString( stats.second ), 100.f * stats.second / stats.first );+ }+ else+ {+ AnsiPrintf( ANSI_RED ANSI_BOLD, " failed!\n");+ }++ return 0;+}
+ cbits/tracy/cmake/CPM.cmake view
@@ -0,0 +1,1269 @@+# CPM.cmake - CMake's missing package manager+# ===========================================+# See https://github.com/cpm-cmake/CPM.cmake for usage and update instructions.+#+# MIT License+# -----------+#[[+ Copyright (c) 2019-2023 Lars Melchior and 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.+]]++cmake_minimum_required(VERSION 3.14 FATAL_ERROR)++# Initialize logging prefix+if(NOT CPM_INDENT)+ set(CPM_INDENT+ "CPM:"+ CACHE INTERNAL ""+ )+endif()++if(NOT COMMAND cpm_message)+ function(cpm_message)+ message(${ARGV})+ endfunction()+endif()++set(CURRENT_CPM_VERSION 0.40.2)++get_filename_component(CPM_CURRENT_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}" REALPATH)+if(CPM_DIRECTORY)+ if(NOT CPM_DIRECTORY STREQUAL CPM_CURRENT_DIRECTORY)+ if(CPM_VERSION VERSION_LESS CURRENT_CPM_VERSION)+ message(+ AUTHOR_WARNING+ "${CPM_INDENT} \+A dependency is using a more recent CPM version (${CURRENT_CPM_VERSION}) than the current project (${CPM_VERSION}). \+It is recommended to upgrade CPM to the most recent version. \+See https://github.com/cpm-cmake/CPM.cmake for more information."+ )+ endif()+ if(${CMAKE_VERSION} VERSION_LESS "3.17.0")+ include(FetchContent)+ endif()+ return()+ endif()++ get_property(+ CPM_INITIALIZED GLOBAL ""+ PROPERTY CPM_INITIALIZED+ SET+ )+ if(CPM_INITIALIZED)+ return()+ endif()+endif()++if(CURRENT_CPM_VERSION MATCHES "development-version")+ message(+ WARNING "${CPM_INDENT} Your project is using an unstable development version of CPM.cmake. \+Please update to a recent release if possible. \+See https://github.com/cpm-cmake/CPM.cmake for details."+ )+endif()++set_property(GLOBAL PROPERTY CPM_INITIALIZED true)++macro(cpm_set_policies)+ # the policy allows us to change options without caching+ cmake_policy(SET CMP0077 NEW)+ set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)++ # the policy allows us to change set(CACHE) without caching+ if(POLICY CMP0126)+ cmake_policy(SET CMP0126 NEW)+ set(CMAKE_POLICY_DEFAULT_CMP0126 NEW)+ endif()++ # The policy uses the download time for timestamp, instead of the timestamp in the archive. This+ # allows for proper rebuilds when a projects url changes+ if(POLICY CMP0135)+ cmake_policy(SET CMP0135 NEW)+ set(CMAKE_POLICY_DEFAULT_CMP0135 NEW)+ endif()++ # treat relative git repository paths as being relative to the parent project's remote+ if(POLICY CMP0150)+ cmake_policy(SET CMP0150 NEW)+ set(CMAKE_POLICY_DEFAULT_CMP0150 NEW)+ endif()+endmacro()+cpm_set_policies()++option(CPM_USE_LOCAL_PACKAGES "Always try to use `find_package` to get dependencies"+ $ENV{CPM_USE_LOCAL_PACKAGES}+)+option(CPM_LOCAL_PACKAGES_ONLY "Only use `find_package` to get dependencies"+ $ENV{CPM_LOCAL_PACKAGES_ONLY}+)+option(CPM_DOWNLOAD_ALL "Always download dependencies from source" $ENV{CPM_DOWNLOAD_ALL})+option(CPM_DONT_UPDATE_MODULE_PATH "Don't update the module path to allow using find_package"+ $ENV{CPM_DONT_UPDATE_MODULE_PATH}+)+option(CPM_DONT_CREATE_PACKAGE_LOCK "Don't create a package lock file in the binary path"+ $ENV{CPM_DONT_CREATE_PACKAGE_LOCK}+)+option(CPM_INCLUDE_ALL_IN_PACKAGE_LOCK+ "Add all packages added through CPM.cmake to the package lock"+ $ENV{CPM_INCLUDE_ALL_IN_PACKAGE_LOCK}+)+option(CPM_USE_NAMED_CACHE_DIRECTORIES+ "Use additional directory of package name in cache on the most nested level."+ $ENV{CPM_USE_NAMED_CACHE_DIRECTORIES}+)++set(CPM_VERSION+ ${CURRENT_CPM_VERSION}+ CACHE INTERNAL ""+)+set(CPM_DIRECTORY+ ${CPM_CURRENT_DIRECTORY}+ CACHE INTERNAL ""+)+set(CPM_FILE+ ${CMAKE_CURRENT_LIST_FILE}+ CACHE INTERNAL ""+)+set(CPM_PACKAGES+ ""+ CACHE INTERNAL ""+)+set(CPM_DRY_RUN+ OFF+ CACHE INTERNAL "Don't download or configure dependencies (for testing)"+)++if(DEFINED ENV{CPM_SOURCE_CACHE})+ set(CPM_SOURCE_CACHE_DEFAULT $ENV{CPM_SOURCE_CACHE})+else()+ set(CPM_SOURCE_CACHE_DEFAULT ${CMAKE_CURRENT_BINARY_DIR}/.cpm-cache)+endif()++set(CPM_SOURCE_CACHE+ ${CPM_SOURCE_CACHE_DEFAULT}+ CACHE PATH "Directory to download CPM dependencies"+)++if(NOT CPM_DONT_UPDATE_MODULE_PATH)+ set(CPM_MODULE_PATH+ "${CMAKE_BINARY_DIR}/CPM_modules"+ CACHE INTERNAL ""+ )+ # remove old modules+ file(REMOVE_RECURSE ${CPM_MODULE_PATH})+ file(MAKE_DIRECTORY ${CPM_MODULE_PATH})+ # locally added CPM modules should override global packages+ set(CMAKE_MODULE_PATH "${CPM_MODULE_PATH};${CMAKE_MODULE_PATH}")+endif()++if(NOT CPM_DONT_CREATE_PACKAGE_LOCK)+ set(CPM_PACKAGE_LOCK_FILE+ "${CMAKE_BINARY_DIR}/cpm-package-lock.cmake"+ CACHE INTERNAL ""+ )+ file(WRITE ${CPM_PACKAGE_LOCK_FILE}+ "# CPM Package Lock\n# This file should be committed to version control\n\n"+ )+endif()++include(FetchContent)++# Try to infer package name from git repository uri (path or url)+function(cpm_package_name_from_git_uri URI RESULT)+ if("${URI}" MATCHES "([^/:]+)/?.git/?$")+ set(${RESULT}+ ${CMAKE_MATCH_1}+ PARENT_SCOPE+ )+ else()+ unset(${RESULT} PARENT_SCOPE)+ endif()+endfunction()++# Try to infer package name and version from a url+function(cpm_package_name_and_ver_from_url url outName outVer)+ if(url MATCHES "[/\\?]([a-zA-Z0-9_\\.-]+)\\.(tar|tar\\.gz|tar\\.bz2|zip|ZIP)(\\?|/|$)")+ # We matched an archive+ set(filename "${CMAKE_MATCH_1}")++ if(filename MATCHES "([a-zA-Z0-9_\\.-]+)[_-]v?(([0-9]+\\.)*[0-9]+[a-zA-Z0-9]*)")+ # We matched <name>-<version> (ie foo-1.2.3)+ set(${outName}+ "${CMAKE_MATCH_1}"+ PARENT_SCOPE+ )+ set(${outVer}+ "${CMAKE_MATCH_2}"+ PARENT_SCOPE+ )+ elseif(filename MATCHES "(([0-9]+\\.)+[0-9]+[a-zA-Z0-9]*)")+ # We couldn't find a name, but we found a version+ #+ # In many cases (which we don't handle here) the url would look something like+ # `irrelevant/ACTUAL_PACKAGE_NAME/irrelevant/1.2.3.zip`. In such a case we can't possibly+ # distinguish the package name from the irrelevant bits. Moreover if we try to match the+ # package name from the filename, we'd get bogus at best.+ unset(${outName} PARENT_SCOPE)+ set(${outVer}+ "${CMAKE_MATCH_1}"+ PARENT_SCOPE+ )+ else()+ # Boldly assume that the file name is the package name.+ #+ # Yes, something like `irrelevant/ACTUAL_NAME/irrelevant/download.zip` will ruin our day, but+ # such cases should be quite rare. No popular service does this... we think.+ set(${outName}+ "${filename}"+ PARENT_SCOPE+ )+ unset(${outVer} PARENT_SCOPE)+ endif()+ else()+ # No ideas yet what to do with non-archives+ unset(${outName} PARENT_SCOPE)+ unset(${outVer} PARENT_SCOPE)+ endif()+endfunction()++function(cpm_find_package NAME VERSION)+ string(REPLACE " " ";" EXTRA_ARGS "${ARGN}")+ find_package(${NAME} ${VERSION} ${EXTRA_ARGS} QUIET)+ if(${CPM_ARGS_NAME}_FOUND)+ if(DEFINED ${CPM_ARGS_NAME}_VERSION)+ set(VERSION ${${CPM_ARGS_NAME}_VERSION})+ endif()+ cpm_message(STATUS "${CPM_INDENT} Using local package ${CPM_ARGS_NAME}@${VERSION}")+ CPMRegisterPackage(${CPM_ARGS_NAME} "${VERSION}")+ set(CPM_PACKAGE_FOUND+ YES+ PARENT_SCOPE+ )+ else()+ set(CPM_PACKAGE_FOUND+ NO+ PARENT_SCOPE+ )+ endif()+endfunction()++# Create a custom FindXXX.cmake module for a CPM package This prevents `find_package(NAME)` from+# finding the system library+function(cpm_create_module_file Name)+ if(NOT CPM_DONT_UPDATE_MODULE_PATH)+ # erase any previous modules+ file(WRITE ${CPM_MODULE_PATH}/Find${Name}.cmake+ "include(\"${CPM_FILE}\")\n${ARGN}\nset(${Name}_FOUND TRUE)"+ )+ endif()+endfunction()++# Find a package locally or fallback to CPMAddPackage+function(CPMFindPackage)+ set(oneValueArgs NAME VERSION GIT_TAG FIND_PACKAGE_ARGUMENTS)++ cmake_parse_arguments(CPM_ARGS "" "${oneValueArgs}" "" ${ARGN})++ if(NOT DEFINED CPM_ARGS_VERSION)+ if(DEFINED CPM_ARGS_GIT_TAG)+ cpm_get_version_from_git_tag("${CPM_ARGS_GIT_TAG}" CPM_ARGS_VERSION)+ endif()+ endif()++ set(downloadPackage ${CPM_DOWNLOAD_ALL})+ if(DEFINED CPM_DOWNLOAD_${CPM_ARGS_NAME})+ set(downloadPackage ${CPM_DOWNLOAD_${CPM_ARGS_NAME}})+ elseif(DEFINED ENV{CPM_DOWNLOAD_${CPM_ARGS_NAME}})+ set(downloadPackage $ENV{CPM_DOWNLOAD_${CPM_ARGS_NAME}})+ endif()+ if(downloadPackage)+ CPMAddPackage(${ARGN})+ cpm_export_variables(${CPM_ARGS_NAME})+ return()+ endif()++ cpm_find_package(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}" ${CPM_ARGS_FIND_PACKAGE_ARGUMENTS})++ if(NOT CPM_PACKAGE_FOUND)+ CPMAddPackage(${ARGN})+ cpm_export_variables(${CPM_ARGS_NAME})+ endif()++endfunction()++# checks if a package has been added before+function(cpm_check_if_package_already_added CPM_ARGS_NAME CPM_ARGS_VERSION)+ if("${CPM_ARGS_NAME}" IN_LIST CPM_PACKAGES)+ CPMGetPackageVersion(${CPM_ARGS_NAME} CPM_PACKAGE_VERSION)+ if("${CPM_PACKAGE_VERSION}" VERSION_LESS "${CPM_ARGS_VERSION}")+ message(+ WARNING+ "${CPM_INDENT} Requires a newer version of ${CPM_ARGS_NAME} (${CPM_ARGS_VERSION}) than currently included (${CPM_PACKAGE_VERSION})."+ )+ endif()+ cpm_get_fetch_properties(${CPM_ARGS_NAME})+ set(${CPM_ARGS_NAME}_ADDED NO)+ set(CPM_PACKAGE_ALREADY_ADDED+ YES+ PARENT_SCOPE+ )+ cpm_export_variables(${CPM_ARGS_NAME})+ else()+ set(CPM_PACKAGE_ALREADY_ADDED+ NO+ PARENT_SCOPE+ )+ endif()+endfunction()++# Parse the argument of CPMAddPackage in case a single one was provided and convert it to a list of+# arguments which can then be parsed idiomatically. For example gh:foo/bar@1.2.3 will be converted+# to: GITHUB_REPOSITORY;foo/bar;VERSION;1.2.3+function(cpm_parse_add_package_single_arg arg outArgs)+ # Look for a scheme+ if("${arg}" MATCHES "^([a-zA-Z]+):(.+)$")+ string(TOLOWER "${CMAKE_MATCH_1}" scheme)+ set(uri "${CMAKE_MATCH_2}")++ # Check for CPM-specific schemes+ if(scheme STREQUAL "gh")+ set(out "GITHUB_REPOSITORY;${uri}")+ set(packageType "git")+ elseif(scheme STREQUAL "gl")+ set(out "GITLAB_REPOSITORY;${uri}")+ set(packageType "git")+ elseif(scheme STREQUAL "bb")+ set(out "BITBUCKET_REPOSITORY;${uri}")+ set(packageType "git")+ # A CPM-specific scheme was not found. Looks like this is a generic URL so try to determine+ # type+ elseif(arg MATCHES ".git/?(@|#|$)")+ set(out "GIT_REPOSITORY;${arg}")+ set(packageType "git")+ else()+ # Fall back to a URL+ set(out "URL;${arg}")+ set(packageType "archive")++ # We could also check for SVN since FetchContent supports it, but SVN is so rare these days.+ # We just won't bother with the additional complexity it will induce in this function. SVN is+ # done by multi-arg+ endif()+ else()+ if(arg MATCHES ".git/?(@|#|$)")+ set(out "GIT_REPOSITORY;${arg}")+ set(packageType "git")+ else()+ # Give up+ message(FATAL_ERROR "${CPM_INDENT} Can't determine package type of '${arg}'")+ endif()+ endif()++ # For all packages we interpret @... as version. Only replace the last occurrence. Thus URIs+ # containing '@' can be used+ string(REGEX REPLACE "@([^@]+)$" ";VERSION;\\1" out "${out}")++ # Parse the rest according to package type+ if(packageType STREQUAL "git")+ # For git repos we interpret #... as a tag or branch or commit hash+ string(REGEX REPLACE "#([^#]+)$" ";GIT_TAG;\\1" out "${out}")+ elseif(packageType STREQUAL "archive")+ # For archives we interpret #... as a URL hash.+ string(REGEX REPLACE "#([^#]+)$" ";URL_HASH;\\1" out "${out}")+ # We don't try to parse the version if it's not provided explicitly. cpm_get_version_from_url+ # should do this at a later point+ else()+ # We should never get here. This is an assertion and hitting it means there's a problem with the+ # code above. A packageType was set, but not handled by this if-else.+ message(FATAL_ERROR "${CPM_INDENT} Unsupported package type '${packageType}' of '${arg}'")+ endif()++ set(${outArgs}+ ${out}+ PARENT_SCOPE+ )+endfunction()++# Check that the working directory for a git repo is clean+function(cpm_check_git_working_dir_is_clean repoPath gitTag isClean)++ find_package(Git REQUIRED)++ if(NOT GIT_EXECUTABLE)+ # No git executable, assume directory is clean+ set(${isClean}+ TRUE+ PARENT_SCOPE+ )+ return()+ endif()++ # check for uncommitted changes+ execute_process(+ COMMAND ${GIT_EXECUTABLE} status --porcelain+ RESULT_VARIABLE resultGitStatus+ OUTPUT_VARIABLE repoStatus+ OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET+ WORKING_DIRECTORY ${repoPath}+ )+ if(resultGitStatus)+ # not supposed to happen, assume clean anyway+ message(WARNING "${CPM_INDENT} Calling git status on folder ${repoPath} failed")+ set(${isClean}+ TRUE+ PARENT_SCOPE+ )+ return()+ endif()++ if(NOT "${repoStatus}" STREQUAL "")+ set(${isClean}+ FALSE+ PARENT_SCOPE+ )+ return()+ endif()++ # check for committed changes+ execute_process(+ COMMAND ${GIT_EXECUTABLE} diff -s --exit-code ${gitTag}+ RESULT_VARIABLE resultGitDiff+ OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_QUIET+ WORKING_DIRECTORY ${repoPath}+ )++ if(${resultGitDiff} EQUAL 0)+ set(${isClean}+ TRUE+ PARENT_SCOPE+ )+ else()+ set(${isClean}+ FALSE+ PARENT_SCOPE+ )+ endif()++endfunction()++# Add PATCH_COMMAND to CPM_ARGS_UNPARSED_ARGUMENTS. This method consumes a list of files in ARGN+# then generates a `PATCH_COMMAND` appropriate for `ExternalProject_Add()`. This command is appended+# to the parent scope's `CPM_ARGS_UNPARSED_ARGUMENTS`.+function(cpm_add_patches)+ # Return if no patch files are supplied.+ if(NOT ARGN)+ return()+ endif()++ # Find the patch program.+ find_program(PATCH_EXECUTABLE patch)+ if(WIN32 AND NOT PATCH_EXECUTABLE)+ # The Windows git executable is distributed with patch.exe. Find the path to the executable, if+ # it exists, then search `../usr/bin` and `../../usr/bin` for patch.exe.+ find_package(Git QUIET)+ if(GIT_EXECUTABLE)+ get_filename_component(extra_search_path ${GIT_EXECUTABLE} DIRECTORY)+ get_filename_component(extra_search_path_1up ${extra_search_path} DIRECTORY)+ get_filename_component(extra_search_path_2up ${extra_search_path_1up} DIRECTORY)+ find_program(+ PATCH_EXECUTABLE patch HINTS "${extra_search_path_1up}/usr/bin"+ "${extra_search_path_2up}/usr/bin"+ )+ endif()+ endif()+ if(NOT PATCH_EXECUTABLE)+ message(FATAL_ERROR "Couldn't find `patch` executable to use with PATCHES keyword.")+ endif()++ # Create a temporary+ set(temp_list ${CPM_ARGS_UNPARSED_ARGUMENTS})++ # Ensure each file exists (or error out) and add it to the list.+ set(first_item True)+ foreach(PATCH_FILE ${ARGN})+ # Make sure the patch file exists, if we can't find it, try again in the current directory.+ if(NOT EXISTS "${PATCH_FILE}")+ if(NOT EXISTS "${CMAKE_CURRENT_LIST_DIR}/${PATCH_FILE}")+ message(FATAL_ERROR "Couldn't find patch file: '${PATCH_FILE}'")+ endif()+ set(PATCH_FILE "${CMAKE_CURRENT_LIST_DIR}/${PATCH_FILE}")+ endif()++ # Convert to absolute path for use with patch file command.+ get_filename_component(PATCH_FILE "${PATCH_FILE}" ABSOLUTE)++ # The first patch entry must be preceded by "PATCH_COMMAND" while the following items are+ # preceded by "&&".+ if(first_item)+ set(first_item False)+ list(APPEND temp_list "PATCH_COMMAND")+ else()+ list(APPEND temp_list "&&")+ endif()+ # Add the patch command to the list+ list(APPEND temp_list "${PATCH_EXECUTABLE}" "-p1" "<" "${PATCH_FILE}")+ endforeach()++ # Move temp out into parent scope.+ set(CPM_ARGS_UNPARSED_ARGUMENTS+ ${temp_list}+ PARENT_SCOPE+ )++endfunction()++# method to overwrite internal FetchContent properties, to allow using CPM.cmake to overload+# FetchContent calls. As these are internal cmake properties, this method should be used carefully+# and may need modification in future CMake versions. Source:+# https://github.com/Kitware/CMake/blob/dc3d0b5a0a7d26d43d6cfeb511e224533b5d188f/Modules/FetchContent.cmake#L1152+function(cpm_override_fetchcontent contentName)+ cmake_parse_arguments(PARSE_ARGV 1 arg "" "SOURCE_DIR;BINARY_DIR" "")+ if(NOT "${arg_UNPARSED_ARGUMENTS}" STREQUAL "")+ message(FATAL_ERROR "${CPM_INDENT} Unsupported arguments: ${arg_UNPARSED_ARGUMENTS}")+ endif()++ string(TOLOWER ${contentName} contentNameLower)+ set(prefix "_FetchContent_${contentNameLower}")++ set(propertyName "${prefix}_sourceDir")+ define_property(+ GLOBAL+ PROPERTY ${propertyName}+ BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()"+ FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}"+ )+ set_property(GLOBAL PROPERTY ${propertyName} "${arg_SOURCE_DIR}")++ set(propertyName "${prefix}_binaryDir")+ define_property(+ GLOBAL+ PROPERTY ${propertyName}+ BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()"+ FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}"+ )+ set_property(GLOBAL PROPERTY ${propertyName} "${arg_BINARY_DIR}")++ set(propertyName "${prefix}_populated")+ define_property(+ GLOBAL+ PROPERTY ${propertyName}+ BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()"+ FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}"+ )+ set_property(GLOBAL PROPERTY ${propertyName} TRUE)+endfunction()++# Download and add a package from source+function(CPMAddPackage)+ cpm_set_policies()++ list(LENGTH ARGN argnLength)+ if(argnLength EQUAL 1)+ cpm_parse_add_package_single_arg("${ARGN}" ARGN)++ # The shorthand syntax implies EXCLUDE_FROM_ALL and SYSTEM+ set(ARGN "${ARGN};EXCLUDE_FROM_ALL;YES;SYSTEM;YES;")+ endif()++ set(oneValueArgs+ NAME+ FORCE+ VERSION+ GIT_TAG+ DOWNLOAD_ONLY+ GITHUB_REPOSITORY+ GITLAB_REPOSITORY+ BITBUCKET_REPOSITORY+ GIT_REPOSITORY+ SOURCE_DIR+ FIND_PACKAGE_ARGUMENTS+ NO_CACHE+ SYSTEM+ GIT_SHALLOW+ EXCLUDE_FROM_ALL+ SOURCE_SUBDIR+ CUSTOM_CACHE_KEY+ )++ set(multiValueArgs URL OPTIONS DOWNLOAD_COMMAND PATCHES)++ cmake_parse_arguments(CPM_ARGS "" "${oneValueArgs}" "${multiValueArgs}" "${ARGN}")++ # Set default values for arguments++ if(NOT DEFINED CPM_ARGS_VERSION)+ if(DEFINED CPM_ARGS_GIT_TAG)+ cpm_get_version_from_git_tag("${CPM_ARGS_GIT_TAG}" CPM_ARGS_VERSION)+ endif()+ endif()++ if(CPM_ARGS_DOWNLOAD_ONLY)+ set(DOWNLOAD_ONLY ${CPM_ARGS_DOWNLOAD_ONLY})+ else()+ set(DOWNLOAD_ONLY NO)+ endif()++ if(DEFINED CPM_ARGS_GITHUB_REPOSITORY)+ set(CPM_ARGS_GIT_REPOSITORY "https://github.com/${CPM_ARGS_GITHUB_REPOSITORY}.git")+ elseif(DEFINED CPM_ARGS_GITLAB_REPOSITORY)+ set(CPM_ARGS_GIT_REPOSITORY "https://gitlab.com/${CPM_ARGS_GITLAB_REPOSITORY}.git")+ elseif(DEFINED CPM_ARGS_BITBUCKET_REPOSITORY)+ set(CPM_ARGS_GIT_REPOSITORY "https://bitbucket.org/${CPM_ARGS_BITBUCKET_REPOSITORY}.git")+ endif()++ if(DEFINED CPM_ARGS_GIT_REPOSITORY)+ list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_REPOSITORY ${CPM_ARGS_GIT_REPOSITORY})+ if(NOT DEFINED CPM_ARGS_GIT_TAG)+ set(CPM_ARGS_GIT_TAG v${CPM_ARGS_VERSION})+ endif()++ # If a name wasn't provided, try to infer it from the git repo+ if(NOT DEFINED CPM_ARGS_NAME)+ cpm_package_name_from_git_uri(${CPM_ARGS_GIT_REPOSITORY} CPM_ARGS_NAME)+ endif()+ endif()++ set(CPM_SKIP_FETCH FALSE)++ if(DEFINED CPM_ARGS_GIT_TAG)+ list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_TAG ${CPM_ARGS_GIT_TAG})+ # If GIT_SHALLOW is explicitly specified, honor the value.+ if(DEFINED CPM_ARGS_GIT_SHALLOW)+ list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_SHALLOW ${CPM_ARGS_GIT_SHALLOW})+ endif()+ endif()++ if(DEFINED CPM_ARGS_URL)+ # If a name or version aren't provided, try to infer them from the URL+ list(GET CPM_ARGS_URL 0 firstUrl)+ cpm_package_name_and_ver_from_url(${firstUrl} nameFromUrl verFromUrl)+ # If we fail to obtain name and version from the first URL, we could try other URLs if any.+ # However multiple URLs are expected to be quite rare, so for now we won't bother.++ # If the caller provided their own name and version, they trump the inferred ones.+ if(NOT DEFINED CPM_ARGS_NAME)+ set(CPM_ARGS_NAME ${nameFromUrl})+ endif()+ if(NOT DEFINED CPM_ARGS_VERSION)+ set(CPM_ARGS_VERSION ${verFromUrl})+ endif()++ list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS URL "${CPM_ARGS_URL}")+ endif()++ # Check for required arguments++ if(NOT DEFINED CPM_ARGS_NAME)+ message(+ FATAL_ERROR+ "${CPM_INDENT} 'NAME' was not provided and couldn't be automatically inferred for package added with arguments: '${ARGN}'"+ )+ endif()++ # Check if package has been added before+ cpm_check_if_package_already_added(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}")+ if(CPM_PACKAGE_ALREADY_ADDED)+ cpm_export_variables(${CPM_ARGS_NAME})+ return()+ endif()++ # Check for manual overrides+ if(NOT CPM_ARGS_FORCE AND NOT "${CPM_${CPM_ARGS_NAME}_SOURCE}" STREQUAL "")+ set(PACKAGE_SOURCE ${CPM_${CPM_ARGS_NAME}_SOURCE})+ set(CPM_${CPM_ARGS_NAME}_SOURCE "")+ CPMAddPackage(+ NAME "${CPM_ARGS_NAME}"+ SOURCE_DIR "${PACKAGE_SOURCE}"+ EXCLUDE_FROM_ALL "${CPM_ARGS_EXCLUDE_FROM_ALL}"+ SYSTEM "${CPM_ARGS_SYSTEM}"+ PATCHES "${CPM_ARGS_PATCHES}"+ OPTIONS "${CPM_ARGS_OPTIONS}"+ SOURCE_SUBDIR "${CPM_ARGS_SOURCE_SUBDIR}"+ DOWNLOAD_ONLY "${DOWNLOAD_ONLY}"+ FORCE True+ )+ cpm_export_variables(${CPM_ARGS_NAME})+ return()+ endif()++ # Check for available declaration+ if(NOT CPM_ARGS_FORCE AND NOT "${CPM_DECLARATION_${CPM_ARGS_NAME}}" STREQUAL "")+ set(declaration ${CPM_DECLARATION_${CPM_ARGS_NAME}})+ set(CPM_DECLARATION_${CPM_ARGS_NAME} "")+ CPMAddPackage(${declaration})+ cpm_export_variables(${CPM_ARGS_NAME})+ # checking again to ensure version and option compatibility+ cpm_check_if_package_already_added(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}")+ return()+ endif()++ if(NOT CPM_ARGS_FORCE)+ if(CPM_USE_LOCAL_PACKAGES OR CPM_LOCAL_PACKAGES_ONLY)+ cpm_find_package(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}" ${CPM_ARGS_FIND_PACKAGE_ARGUMENTS})++ if(CPM_PACKAGE_FOUND)+ cpm_export_variables(${CPM_ARGS_NAME})+ return()+ endif()++ if(CPM_LOCAL_PACKAGES_ONLY)+ message(+ SEND_ERROR+ "${CPM_INDENT} ${CPM_ARGS_NAME} not found via find_package(${CPM_ARGS_NAME} ${CPM_ARGS_VERSION})"+ )+ endif()+ endif()+ endif()++ CPMRegisterPackage("${CPM_ARGS_NAME}" "${CPM_ARGS_VERSION}")++ if(DEFINED CPM_ARGS_GIT_TAG)+ set(PACKAGE_INFO "${CPM_ARGS_GIT_TAG}")+ elseif(DEFINED CPM_ARGS_SOURCE_DIR)+ set(PACKAGE_INFO "${CPM_ARGS_SOURCE_DIR}")+ else()+ set(PACKAGE_INFO "${CPM_ARGS_VERSION}")+ endif()++ if(DEFINED FETCHCONTENT_BASE_DIR)+ # respect user's FETCHCONTENT_BASE_DIR if set+ set(CPM_FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR})+ else()+ set(CPM_FETCHCONTENT_BASE_DIR ${CMAKE_BINARY_DIR}/_deps)+ endif()++ cpm_add_patches(${CPM_ARGS_PATCHES})++ if(DEFINED CPM_ARGS_DOWNLOAD_COMMAND)+ list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS DOWNLOAD_COMMAND ${CPM_ARGS_DOWNLOAD_COMMAND})+ elseif(DEFINED CPM_ARGS_SOURCE_DIR)+ list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS SOURCE_DIR ${CPM_ARGS_SOURCE_DIR})+ if(NOT IS_ABSOLUTE ${CPM_ARGS_SOURCE_DIR})+ # Expand `CPM_ARGS_SOURCE_DIR` relative path. This is important because EXISTS doesn't work+ # for relative paths.+ get_filename_component(+ source_directory ${CPM_ARGS_SOURCE_DIR} REALPATH BASE_DIR ${CMAKE_CURRENT_BINARY_DIR}+ )+ else()+ set(source_directory ${CPM_ARGS_SOURCE_DIR})+ endif()+ if(NOT EXISTS ${source_directory})+ string(TOLOWER ${CPM_ARGS_NAME} lower_case_name)+ # remove timestamps so CMake will re-download the dependency+ file(REMOVE_RECURSE "${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-subbuild")+ endif()+ elseif(CPM_SOURCE_CACHE AND NOT CPM_ARGS_NO_CACHE)+ string(TOLOWER ${CPM_ARGS_NAME} lower_case_name)+ set(origin_parameters ${CPM_ARGS_UNPARSED_ARGUMENTS})+ list(SORT origin_parameters)+ if(CPM_ARGS_CUSTOM_CACHE_KEY)+ # Application set a custom unique directory name+ set(download_directory ${CPM_SOURCE_CACHE}/${lower_case_name}/${CPM_ARGS_CUSTOM_CACHE_KEY})+ elseif(CPM_USE_NAMED_CACHE_DIRECTORIES)+ string(SHA1 origin_hash "${origin_parameters};NEW_CACHE_STRUCTURE_TAG")+ set(download_directory ${CPM_SOURCE_CACHE}/${lower_case_name}/${origin_hash}/${CPM_ARGS_NAME})+ else()+ string(SHA1 origin_hash "${origin_parameters}")+ set(download_directory ${CPM_SOURCE_CACHE}/${lower_case_name}/${origin_hash})+ endif()+ # Expand `download_directory` relative path. This is important because EXISTS doesn't work for+ # relative paths.+ get_filename_component(download_directory ${download_directory} ABSOLUTE)+ list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS SOURCE_DIR ${download_directory})++ if(CPM_SOURCE_CACHE)+ file(LOCK ${download_directory}/../cmake.lock)+ endif()++ if(EXISTS ${download_directory})+ if(CPM_SOURCE_CACHE)+ file(LOCK ${download_directory}/../cmake.lock RELEASE)+ endif()++ cpm_store_fetch_properties(+ ${CPM_ARGS_NAME} "${download_directory}"+ "${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-build"+ )+ cpm_get_fetch_properties("${CPM_ARGS_NAME}")++ if(DEFINED CPM_ARGS_GIT_TAG AND NOT (PATCH_COMMAND IN_LIST CPM_ARGS_UNPARSED_ARGUMENTS))+ # warn if cache has been changed since checkout+ cpm_check_git_working_dir_is_clean(${download_directory} ${CPM_ARGS_GIT_TAG} IS_CLEAN)+ if(NOT ${IS_CLEAN})+ message(+ WARNING "${CPM_INDENT} Cache for ${CPM_ARGS_NAME} (${download_directory}) is dirty"+ )+ endif()+ endif()++ cpm_add_subdirectory(+ "${CPM_ARGS_NAME}"+ "${DOWNLOAD_ONLY}"+ "${${CPM_ARGS_NAME}_SOURCE_DIR}/${CPM_ARGS_SOURCE_SUBDIR}"+ "${${CPM_ARGS_NAME}_BINARY_DIR}"+ "${CPM_ARGS_EXCLUDE_FROM_ALL}"+ "${CPM_ARGS_SYSTEM}"+ "${CPM_ARGS_OPTIONS}"+ )+ set(PACKAGE_INFO "${PACKAGE_INFO} at ${download_directory}")++ # As the source dir is already cached/populated, we override the call to FetchContent.+ set(CPM_SKIP_FETCH TRUE)+ cpm_override_fetchcontent(+ "${lower_case_name}" SOURCE_DIR "${${CPM_ARGS_NAME}_SOURCE_DIR}/${CPM_ARGS_SOURCE_SUBDIR}"+ BINARY_DIR "${${CPM_ARGS_NAME}_BINARY_DIR}"+ )++ else()+ # Enable shallow clone when GIT_TAG is not a commit hash. Our guess may not be accurate, but+ # it should guarantee no commit hash get mis-detected.+ if(NOT DEFINED CPM_ARGS_GIT_SHALLOW)+ cpm_is_git_tag_commit_hash("${CPM_ARGS_GIT_TAG}" IS_HASH)+ if(NOT ${IS_HASH})+ list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_SHALLOW TRUE)+ endif()+ endif()++ # remove timestamps so CMake will re-download the dependency+ file(REMOVE_RECURSE ${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-subbuild)+ set(PACKAGE_INFO "${PACKAGE_INFO} to ${download_directory}")+ endif()+ endif()++ cpm_create_module_file(${CPM_ARGS_NAME} "CPMAddPackage(\"${ARGN}\")")++ if(CPM_PACKAGE_LOCK_ENABLED)+ if((CPM_ARGS_VERSION AND NOT CPM_ARGS_SOURCE_DIR) OR CPM_INCLUDE_ALL_IN_PACKAGE_LOCK)+ cpm_add_to_package_lock(${CPM_ARGS_NAME} "${ARGN}")+ elseif(CPM_ARGS_SOURCE_DIR)+ cpm_add_comment_to_package_lock(${CPM_ARGS_NAME} "local directory")+ else()+ cpm_add_comment_to_package_lock(${CPM_ARGS_NAME} "${ARGN}")+ endif()+ endif()++ cpm_message(+ STATUS "${CPM_INDENT} Adding package ${CPM_ARGS_NAME}@${CPM_ARGS_VERSION} (${PACKAGE_INFO})"+ )++ if(NOT CPM_SKIP_FETCH)+ # CMake 3.28 added EXCLUDE, SYSTEM (3.25), and SOURCE_SUBDIR (3.18) to FetchContent_Declare.+ # Calling FetchContent_MakeAvailable will then internally forward these options to+ # add_subdirectory. Up until these changes, we had to call FetchContent_Populate and+ # add_subdirectory separately, which is no longer necessary and has been deprecated as of 3.30.+ set(fetchContentDeclareExtraArgs "")+ if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.28.0")+ if(${CPM_ARGS_EXCLUDE_FROM_ALL})+ list(APPEND fetchContentDeclareExtraArgs EXCLUDE_FROM_ALL)+ endif()+ if(${CPM_ARGS_SYSTEM})+ list(APPEND fetchContentDeclareExtraArgs SYSTEM)+ endif()+ if(DEFINED CPM_ARGS_SOURCE_SUBDIR)+ list(APPEND fetchContentDeclareExtraArgs SOURCE_SUBDIR ${CPM_ARGS_SOURCE_SUBDIR})+ endif()+ # For CMake version <3.28 OPTIONS are parsed in cpm_add_subdirectory+ if(CPM_ARGS_OPTIONS AND NOT DOWNLOAD_ONLY)+ foreach(OPTION ${CPM_ARGS_OPTIONS})+ cpm_parse_option("${OPTION}")+ set(${OPTION_KEY} "${OPTION_VALUE}")+ endforeach()+ endif()+ endif()+ cpm_declare_fetch(+ "${CPM_ARGS_NAME}" ${fetchContentDeclareExtraArgs} "${CPM_ARGS_UNPARSED_ARGUMENTS}"+ )++ cpm_fetch_package("${CPM_ARGS_NAME}" ${DOWNLOAD_ONLY} populated ${CPM_ARGS_UNPARSED_ARGUMENTS})+ if(CPM_SOURCE_CACHE AND download_directory)+ file(LOCK ${download_directory}/../cmake.lock RELEASE)+ endif()+ if(${populated} AND ${CMAKE_VERSION} VERSION_LESS "3.28.0")+ cpm_add_subdirectory(+ "${CPM_ARGS_NAME}"+ "${DOWNLOAD_ONLY}"+ "${${CPM_ARGS_NAME}_SOURCE_DIR}/${CPM_ARGS_SOURCE_SUBDIR}"+ "${${CPM_ARGS_NAME}_BINARY_DIR}"+ "${CPM_ARGS_EXCLUDE_FROM_ALL}"+ "${CPM_ARGS_SYSTEM}"+ "${CPM_ARGS_OPTIONS}"+ )+ endif()+ cpm_get_fetch_properties("${CPM_ARGS_NAME}")+ endif()++ set(${CPM_ARGS_NAME}_ADDED YES)+ cpm_export_variables("${CPM_ARGS_NAME}")+endfunction()++# Fetch a previously declared package+macro(CPMGetPackage Name)+ if(DEFINED "CPM_DECLARATION_${Name}")+ CPMAddPackage(NAME ${Name})+ else()+ message(SEND_ERROR "${CPM_INDENT} Cannot retrieve package ${Name}: no declaration available")+ endif()+endmacro()++# export variables available to the caller to the parent scope expects ${CPM_ARGS_NAME} to be set+macro(cpm_export_variables name)+ set(${name}_SOURCE_DIR+ "${${name}_SOURCE_DIR}"+ PARENT_SCOPE+ )+ set(${name}_BINARY_DIR+ "${${name}_BINARY_DIR}"+ PARENT_SCOPE+ )+ set(${name}_ADDED+ "${${name}_ADDED}"+ PARENT_SCOPE+ )+ set(CPM_LAST_PACKAGE_NAME+ "${name}"+ PARENT_SCOPE+ )+endmacro()++# declares a package, so that any call to CPMAddPackage for the package name will use these+# arguments instead. Previous declarations will not be overridden.+macro(CPMDeclarePackage Name)+ if(NOT DEFINED "CPM_DECLARATION_${Name}")+ set("CPM_DECLARATION_${Name}" "${ARGN}")+ endif()+endmacro()++function(cpm_add_to_package_lock Name)+ if(NOT CPM_DONT_CREATE_PACKAGE_LOCK)+ cpm_prettify_package_arguments(PRETTY_ARGN false ${ARGN})+ file(APPEND ${CPM_PACKAGE_LOCK_FILE} "# ${Name}\nCPMDeclarePackage(${Name}\n${PRETTY_ARGN})\n")+ endif()+endfunction()++function(cpm_add_comment_to_package_lock Name)+ if(NOT CPM_DONT_CREATE_PACKAGE_LOCK)+ cpm_prettify_package_arguments(PRETTY_ARGN true ${ARGN})+ file(APPEND ${CPM_PACKAGE_LOCK_FILE}+ "# ${Name} (unversioned)\n# CPMDeclarePackage(${Name}\n${PRETTY_ARGN}#)\n"+ )+ endif()+endfunction()++# includes the package lock file if it exists and creates a target `cpm-update-package-lock` to+# update it+macro(CPMUsePackageLock file)+ if(NOT CPM_DONT_CREATE_PACKAGE_LOCK)+ get_filename_component(CPM_ABSOLUTE_PACKAGE_LOCK_PATH ${file} ABSOLUTE)+ if(EXISTS ${CPM_ABSOLUTE_PACKAGE_LOCK_PATH})+ include(${CPM_ABSOLUTE_PACKAGE_LOCK_PATH})+ endif()+ if(NOT TARGET cpm-update-package-lock)+ add_custom_target(+ cpm-update-package-lock COMMAND ${CMAKE_COMMAND} -E copy ${CPM_PACKAGE_LOCK_FILE}+ ${CPM_ABSOLUTE_PACKAGE_LOCK_PATH}+ )+ endif()+ set(CPM_PACKAGE_LOCK_ENABLED true)+ endif()+endmacro()++# registers a package that has been added to CPM+function(CPMRegisterPackage PACKAGE VERSION)+ list(APPEND CPM_PACKAGES ${PACKAGE})+ set(CPM_PACKAGES+ ${CPM_PACKAGES}+ CACHE INTERNAL ""+ )+ set("CPM_PACKAGE_${PACKAGE}_VERSION"+ ${VERSION}+ CACHE INTERNAL ""+ )+endfunction()++# retrieve the current version of the package to ${OUTPUT}+function(CPMGetPackageVersion PACKAGE OUTPUT)+ set(${OUTPUT}+ "${CPM_PACKAGE_${PACKAGE}_VERSION}"+ PARENT_SCOPE+ )+endfunction()++# declares a package in FetchContent_Declare+function(cpm_declare_fetch PACKAGE)+ if(${CPM_DRY_RUN})+ cpm_message(STATUS "${CPM_INDENT} Package not declared (dry run)")+ return()+ endif()++ FetchContent_Declare(${PACKAGE} ${ARGN})+endfunction()++# returns properties for a package previously defined by cpm_declare_fetch+function(cpm_get_fetch_properties PACKAGE)+ if(${CPM_DRY_RUN})+ return()+ endif()++ set(${PACKAGE}_SOURCE_DIR+ "${CPM_PACKAGE_${PACKAGE}_SOURCE_DIR}"+ PARENT_SCOPE+ )+ set(${PACKAGE}_BINARY_DIR+ "${CPM_PACKAGE_${PACKAGE}_BINARY_DIR}"+ PARENT_SCOPE+ )+endfunction()++function(cpm_store_fetch_properties PACKAGE source_dir binary_dir)+ if(${CPM_DRY_RUN})+ return()+ endif()++ set(CPM_PACKAGE_${PACKAGE}_SOURCE_DIR+ "${source_dir}"+ CACHE INTERNAL ""+ )+ set(CPM_PACKAGE_${PACKAGE}_BINARY_DIR+ "${binary_dir}"+ CACHE INTERNAL ""+ )+endfunction()++# adds a package as a subdirectory if viable, according to provided options+function(+ cpm_add_subdirectory+ PACKAGE+ DOWNLOAD_ONLY+ SOURCE_DIR+ BINARY_DIR+ EXCLUDE+ SYSTEM+ OPTIONS+)++ if(NOT DOWNLOAD_ONLY AND EXISTS ${SOURCE_DIR}/CMakeLists.txt)+ set(addSubdirectoryExtraArgs "")+ if(EXCLUDE)+ list(APPEND addSubdirectoryExtraArgs EXCLUDE_FROM_ALL)+ endif()+ if("${SYSTEM}" AND "${CMAKE_VERSION}" VERSION_GREATER_EQUAL "3.25")+ # https://cmake.org/cmake/help/latest/prop_dir/SYSTEM.html#prop_dir:SYSTEM+ list(APPEND addSubdirectoryExtraArgs SYSTEM)+ endif()+ if(OPTIONS)+ foreach(OPTION ${OPTIONS})+ cpm_parse_option("${OPTION}")+ set(${OPTION_KEY} "${OPTION_VALUE}")+ endforeach()+ endif()+ set(CPM_OLD_INDENT "${CPM_INDENT}")+ set(CPM_INDENT "${CPM_INDENT} ${PACKAGE}:")+ add_subdirectory(${SOURCE_DIR} ${BINARY_DIR} ${addSubdirectoryExtraArgs})+ set(CPM_INDENT "${CPM_OLD_INDENT}")+ endif()+endfunction()++# downloads a previously declared package via FetchContent and exports the variables+# `${PACKAGE}_SOURCE_DIR` and `${PACKAGE}_BINARY_DIR` to the parent scope+function(cpm_fetch_package PACKAGE DOWNLOAD_ONLY populated)+ set(${populated}+ FALSE+ PARENT_SCOPE+ )+ if(${CPM_DRY_RUN})+ cpm_message(STATUS "${CPM_INDENT} Package ${PACKAGE} not fetched (dry run)")+ return()+ endif()++ FetchContent_GetProperties(${PACKAGE})++ string(TOLOWER "${PACKAGE}" lower_case_name)++ if(NOT ${lower_case_name}_POPULATED)+ if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.28.0")+ if(DOWNLOAD_ONLY)+ # MakeAvailable will call add_subdirectory internally which is not what we want when+ # DOWNLOAD_ONLY is set. Populate will only download the dependency without adding it to the+ # build+ FetchContent_Populate(+ ${PACKAGE}+ SOURCE_DIR "${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-src"+ BINARY_DIR "${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-build"+ SUBBUILD_DIR "${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-subbuild"+ ${ARGN}+ )+ else()+ FetchContent_MakeAvailable(${PACKAGE})+ endif()+ else()+ FetchContent_Populate(${PACKAGE})+ endif()+ set(${populated}+ TRUE+ PARENT_SCOPE+ )+ endif()++ cpm_store_fetch_properties(+ ${CPM_ARGS_NAME} ${${lower_case_name}_SOURCE_DIR} ${${lower_case_name}_BINARY_DIR}+ )++ set(${PACKAGE}_SOURCE_DIR+ ${${lower_case_name}_SOURCE_DIR}+ PARENT_SCOPE+ )+ set(${PACKAGE}_BINARY_DIR+ ${${lower_case_name}_BINARY_DIR}+ PARENT_SCOPE+ )+endfunction()++# splits a package option+function(cpm_parse_option OPTION)+ string(REGEX MATCH "^[^ ]+" OPTION_KEY "${OPTION}")+ string(LENGTH "${OPTION}" OPTION_LENGTH)+ string(LENGTH "${OPTION_KEY}" OPTION_KEY_LENGTH)+ if(OPTION_KEY_LENGTH STREQUAL OPTION_LENGTH)+ # no value for key provided, assume user wants to set option to "ON"+ set(OPTION_VALUE "ON")+ else()+ math(EXPR OPTION_KEY_LENGTH "${OPTION_KEY_LENGTH}+1")+ string(SUBSTRING "${OPTION}" "${OPTION_KEY_LENGTH}" "-1" OPTION_VALUE)+ endif()+ set(OPTION_KEY+ "${OPTION_KEY}"+ PARENT_SCOPE+ )+ set(OPTION_VALUE+ "${OPTION_VALUE}"+ PARENT_SCOPE+ )+endfunction()++# guesses the package version from a git tag+function(cpm_get_version_from_git_tag GIT_TAG RESULT)+ string(LENGTH ${GIT_TAG} length)+ if(length EQUAL 40)+ # GIT_TAG is probably a git hash+ set(${RESULT}+ 0+ PARENT_SCOPE+ )+ else()+ string(REGEX MATCH "v?([0123456789.]*).*" _ ${GIT_TAG})+ set(${RESULT}+ ${CMAKE_MATCH_1}+ PARENT_SCOPE+ )+ endif()+endfunction()++# guesses if the git tag is a commit hash or an actual tag or a branch name.+function(cpm_is_git_tag_commit_hash GIT_TAG RESULT)+ string(LENGTH "${GIT_TAG}" length)+ # full hash has 40 characters, and short hash has at least 7 characters.+ if(length LESS 7 OR length GREATER 40)+ set(${RESULT}+ 0+ PARENT_SCOPE+ )+ else()+ if(${GIT_TAG} MATCHES "^[a-fA-F0-9]+$")+ set(${RESULT}+ 1+ PARENT_SCOPE+ )+ else()+ set(${RESULT}+ 0+ PARENT_SCOPE+ )+ endif()+ endif()+endfunction()++function(cpm_prettify_package_arguments OUT_VAR IS_IN_COMMENT)+ set(oneValueArgs+ NAME+ FORCE+ VERSION+ GIT_TAG+ DOWNLOAD_ONLY+ GITHUB_REPOSITORY+ GITLAB_REPOSITORY+ BITBUCKET_REPOSITORY+ GIT_REPOSITORY+ SOURCE_DIR+ FIND_PACKAGE_ARGUMENTS+ NO_CACHE+ SYSTEM+ GIT_SHALLOW+ EXCLUDE_FROM_ALL+ SOURCE_SUBDIR+ )+ set(multiValueArgs URL OPTIONS DOWNLOAD_COMMAND)+ cmake_parse_arguments(CPM_ARGS "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})++ foreach(oneArgName ${oneValueArgs})+ if(DEFINED CPM_ARGS_${oneArgName})+ if(${IS_IN_COMMENT})+ string(APPEND PRETTY_OUT_VAR "#")+ endif()+ if(${oneArgName} STREQUAL "SOURCE_DIR")+ string(REPLACE ${CMAKE_SOURCE_DIR} "\${CMAKE_SOURCE_DIR}" CPM_ARGS_${oneArgName}+ ${CPM_ARGS_${oneArgName}}+ )+ endif()+ string(APPEND PRETTY_OUT_VAR " ${oneArgName} ${CPM_ARGS_${oneArgName}}\n")+ endif()+ endforeach()+ foreach(multiArgName ${multiValueArgs})+ if(DEFINED CPM_ARGS_${multiArgName})+ if(${IS_IN_COMMENT})+ string(APPEND PRETTY_OUT_VAR "#")+ endif()+ string(APPEND PRETTY_OUT_VAR " ${multiArgName}\n")+ foreach(singleOption ${CPM_ARGS_${multiArgName}})+ if(${IS_IN_COMMENT})+ string(APPEND PRETTY_OUT_VAR "#")+ endif()+ string(APPEND PRETTY_OUT_VAR " \"${singleOption}\"\n")+ endforeach()+ endif()+ endforeach()++ if(NOT "${CPM_ARGS_UNPARSED_ARGUMENTS}" STREQUAL "")+ if(${IS_IN_COMMENT})+ string(APPEND PRETTY_OUT_VAR "#")+ endif()+ string(APPEND PRETTY_OUT_VAR " ")+ foreach(CPM_ARGS_UNPARSED_ARGUMENT ${CPM_ARGS_UNPARSED_ARGUMENTS})+ string(APPEND PRETTY_OUT_VAR " ${CPM_ARGS_UNPARSED_ARGUMENT}")+ endforeach()+ string(APPEND PRETTY_OUT_VAR "\n")+ endif()++ set(${OUT_VAR}+ ${PRETTY_OUT_VAR}+ PARENT_SCOPE+ )++endfunction()
+ cbits/tracy/cmake/ECMFindModuleHelpers.cmake view
@@ -0,0 +1,300 @@+#.rst:+# ECMFindModuleHelpers+# --------------------+#+# Helper macros for find modules: ecm_find_package_version_check(),+# ecm_find_package_parse_components() and+# ecm_find_package_handle_library_components().+#+# ::+#+# ecm_find_package_version_check(<name>)+#+# Prints warnings if the CMake version or the project's required CMake version+# is older than that required by extra-cmake-modules.+#+# ::+#+# ecm_find_package_parse_components(<name>+# RESULT_VAR <variable>+# KNOWN_COMPONENTS <component1> [<component2> [...]]+# [SKIP_DEPENDENCY_HANDLING])+#+# This macro will populate <variable> with a list of components found in+# <name>_FIND_COMPONENTS, after checking that all those components are in the+# list of KNOWN_COMPONENTS; if there are any unknown components, it will print+# an error or warning (depending on the value of <name>_FIND_REQUIRED) and call+# return().+#+# The order of components in <variable> is guaranteed to match the order they+# are listed in the KNOWN_COMPONENTS argument.+#+# If SKIP_DEPENDENCY_HANDLING is not set, for each component the variable+# <name>_<component>_component_deps will be checked for dependent components.+# If <component> is listed in <name>_FIND_COMPONENTS, then all its (transitive)+# dependencies will also be added to <variable>.+#+# ::+#+# ecm_find_package_handle_library_components(<name>+# COMPONENTS <component> [<component> [...]]+# [SKIP_DEPENDENCY_HANDLING])+# [SKIP_PKG_CONFIG])+#+# Creates an imported library target for each component. The operation of this+# macro depends on the presence of a number of CMake variables.+#+# The <name>_<component>_lib variable should contain the name of this library,+# and <name>_<component>_header variable should contain the name of a header+# file associated with it (whatever relative path is normally passed to+# '#include'). <name>_<component>_header_subdir variable can be used to specify+# which subdirectory of the include path the headers will be found in.+# ecm_find_package_components() will then search for the library+# and include directory (creating appropriate cache variables) and create an+# imported library target named <name>::<component>.+#+# Additional variables can be used to provide additional information:+#+# If SKIP_PKG_CONFIG, the <name>_<component>_pkg_config variable is set, and+# pkg-config is found, the pkg-config module given by+# <name>_<component>_pkg_config will be searched for and used to help locate the+# library and header file. It will also be used to set+# <name>_<component>_VERSION.+#+# Note that if version information is found via pkg-config,+# <name>_<component>_FIND_VERSION can be set to require a particular version+# for each component.+#+# If SKIP_DEPENDENCY_HANDLING is not set, the INTERFACE_LINK_LIBRARIES property+# of the imported target for <component> will be set to contain the imported+# targets for the components listed in <name>_<component>_component_deps.+# <component>_FOUND will also be set to false if any of the components in+# <name>_<component>_component_deps are not found. This requires the components+# in <name>_<component>_component_deps to be listed before <component> in the+# COMPONENTS argument.+#+# The following variables will be set:+#+# ``<name>_TARGETS``+# the imported targets+# ``<name>_LIBRARIES``+# the found libraries+# ``<name>_INCLUDE_DIRS``+# the combined required include directories for the components+# ``<name>_DEFINITIONS``+# the "other" CFLAGS provided by pkg-config, if any+# ``<name>_VERSION``+# the value of ``<name>_<component>_VERSION`` for the first component that+# has this variable set (note that components are searched for in the order+# they are passed to the macro), although if it is already set, it will not+# be altered+#+# Note that these variables are never cleared, so if+# ecm_find_package_handle_library_components() is called multiple times with+# different components (typically because of multiple find_package() calls) then+# ``<name>_TARGETS``, for example, will contain all the targets found in any+# call (although no duplicates).+#+# Since pre-1.0.0.++#=============================================================================+# Copyright 2014 Alex Merry <alex.merry@kde.org>+#+# Redistribution and use in source and binary forms, with or without+# modification, are permitted provided that the following conditions+# are met:+#+# 1. Redistributions of source code must retain the copyright+# notice, this list of conditions and the following disclaimer.+# 2. Redistributions in binary form must reproduce the copyright+# notice, this list of conditions and the following disclaimer in the+# documentation and/or other materials provided with the distribution.+# 3. The name of the author may not be used to endorse or promote products+# derived from this software without specific prior written permission.+#+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.++macro(ecm_find_package_version_check module_name)+ if(CMAKE_VERSION VERSION_LESS 2.8.12)+ message(FATAL_ERROR "CMake 2.8.12 is required by Find${module_name}.cmake")+ endif()+ if(CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.12)+ message(AUTHOR_WARNING "Your project should require at least CMake 2.8.12 to use Find${module_name}.cmake")+ endif()+endmacro()++macro(ecm_find_package_parse_components module_name)+ set(ecm_fppc_options SKIP_DEPENDENCY_HANDLING)+ set(ecm_fppc_oneValueArgs RESULT_VAR)+ set(ecm_fppc_multiValueArgs KNOWN_COMPONENTS DEFAULT_COMPONENTS)+ cmake_parse_arguments(ECM_FPPC "${ecm_fppc_options}" "${ecm_fppc_oneValueArgs}" "${ecm_fppc_multiValueArgs}" ${ARGN})++ if(ECM_FPPC_UNPARSED_ARGUMENTS)+ message(FATAL_ERROR "Unexpected arguments to ecm_find_package_parse_components: ${ECM_FPPC_UNPARSED_ARGUMENTS}")+ endif()+ if(NOT ECM_FPPC_RESULT_VAR)+ message(FATAL_ERROR "Missing RESULT_VAR argument to ecm_find_package_parse_components")+ endif()+ if(NOT ECM_FPPC_KNOWN_COMPONENTS)+ message(FATAL_ERROR "Missing KNOWN_COMPONENTS argument to ecm_find_package_parse_components")+ endif()+ if(NOT ECM_FPPC_DEFAULT_COMPONENTS)+ set(ECM_FPPC_DEFAULT_COMPONENTS ${ECM_FPPC_KNOWN_COMPONENTS})+ endif()++ if(${module_name}_FIND_COMPONENTS)+ set(ecm_fppc_requestedComps ${${module_name}_FIND_COMPONENTS})++ if(NOT ECM_FPPC_SKIP_DEPENDENCY_HANDLING)+ # Make sure deps are included+ foreach(ecm_fppc_comp ${ecm_fppc_requestedComps})+ foreach(ecm_fppc_dep_comp ${${module_name}_${ecm_fppc_comp}_component_deps})+ list(FIND ecm_fppc_requestedComps "${ecm_fppc_dep_comp}" ecm_fppc_index)+ if("${ecm_fppc_index}" STREQUAL "-1")+ if(NOT ${module_name}_FIND_QUIETLY)+ message(STATUS "${module_name}: ${ecm_fppc_comp} requires ${${module_name}_${ecm_fppc_comp}_component_deps}")+ endif()+ list(APPEND ecm_fppc_requestedComps "${ecm_fppc_dep_comp}")+ endif()+ endforeach()+ endforeach()+ else()+ message(STATUS "Skipping dependency handling for ${module_name}")+ endif()+ list(REMOVE_DUPLICATES ecm_fppc_requestedComps)++ # This makes sure components are listed in the same order as+ # KNOWN_COMPONENTS (potentially important for inter-dependencies)+ set(${ECM_FPPC_RESULT_VAR})+ foreach(ecm_fppc_comp ${ECM_FPPC_KNOWN_COMPONENTS})+ list(FIND ecm_fppc_requestedComps "${ecm_fppc_comp}" ecm_fppc_index)+ if(NOT "${ecm_fppc_index}" STREQUAL "-1")+ list(APPEND ${ECM_FPPC_RESULT_VAR} "${ecm_fppc_comp}")+ list(REMOVE_AT ecm_fppc_requestedComps ${ecm_fppc_index})+ endif()+ endforeach()+ # if there are any left, they are unknown components+ if(ecm_fppc_requestedComps)+ set(ecm_fppc_msgType STATUS)+ if(${module_name}_FIND_REQUIRED)+ set(ecm_fppc_msgType FATAL_ERROR)+ endif()+ if(NOT ${module_name}_FIND_QUIETLY)+ message(${ecm_fppc_msgType} "${module_name}: requested unknown components ${ecm_fppc_requestedComps}")+ endif()+ return()+ endif()+ else()+ set(${ECM_FPPC_RESULT_VAR} ${ECM_FPPC_DEFAULT_COMPONENTS})+ endif()+endmacro()++macro(ecm_find_package_handle_library_components module_name)+ set(ecm_fpwc_options SKIP_PKG_CONFIG SKIP_DEPENDENCY_HANDLING)+ set(ecm_fpwc_oneValueArgs)+ set(ecm_fpwc_multiValueArgs COMPONENTS)+ cmake_parse_arguments(ECM_FPWC "${ecm_fpwc_options}" "${ecm_fpwc_oneValueArgs}" "${ecm_fpwc_multiValueArgs}" ${ARGN})++ if(ECM_FPWC_UNPARSED_ARGUMENTS)+ message(FATAL_ERROR "Unexpected arguments to ecm_find_package_handle_components: ${ECM_FPWC_UNPARSED_ARGUMENTS}")+ endif()+ if(NOT ECM_FPWC_COMPONENTS)+ message(FATAL_ERROR "Missing COMPONENTS argument to ecm_find_package_handle_components")+ endif()++ include(FindPackageHandleStandardArgs)+ find_package(PkgConfig QUIET)+ foreach(ecm_fpwc_comp ${ECM_FPWC_COMPONENTS})+ set(ecm_fpwc_dep_vars)+ set(ecm_fpwc_dep_targets)+ if(NOT SKIP_DEPENDENCY_HANDLING)+ foreach(ecm_fpwc_dep ${${module_name}_${ecm_fpwc_comp}_component_deps})+ list(APPEND ecm_fpwc_dep_vars "${module_name}_${ecm_fpwc_dep}_FOUND")+ list(APPEND ecm_fpwc_dep_targets "${module_name}::${ecm_fpwc_dep}")+ endforeach()+ endif()++ if(NOT ECM_FPWC_SKIP_PKG_CONFIG AND ${module_name}_${ecm_fpwc_comp}_pkg_config)+ pkg_check_modules(PKG_${module_name}_${ecm_fpwc_comp} QUIET+ ${${module_name}_${ecm_fpwc_comp}_pkg_config})+ endif()++ find_path(${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR+ NAMES ${${module_name}_${ecm_fpwc_comp}_header}+ HINTS ${PKG_${module_name}_${ecm_fpwc_comp}_INCLUDE_DIRS}+ PATH_SUFFIXES ${${module_name}_${ecm_fpwc_comp}_header_subdir}+ )+ find_library(${module_name}_${ecm_fpwc_comp}_LIBRARY+ NAMES ${${module_name}_${ecm_fpwc_comp}_lib}+ HINTS ${PKG_${module_name}_${ecm_fpwc_comp}_LIBRARY_DIRS}+ )++ set(${module_name}_${ecm_fpwc_comp}_VERSION "${PKG_${module_name}_${ecm_fpwc_comp}_VERSION}")+ if(NOT ${module_name}_VERSION)+ set(${module_name}_VERSION ${${module_name}_${ecm_fpwc_comp}_VERSION})+ endif()++ set(_name_mismatched_arg)+ if(NOT CMAKE_VERSION VERSION_LESS 3.17)+ set(_name_mismatched_arg NAME_MISMATCHED)+ endif()+ find_package_handle_standard_args(${module_name}_${ecm_fpwc_comp}+ FOUND_VAR+ ${module_name}_${ecm_fpwc_comp}_FOUND+ REQUIRED_VARS+ ${module_name}_${ecm_fpwc_comp}_LIBRARY+ ${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR+ ${ecm_fpwc_dep_vars}+ VERSION_VAR+ ${module_name}_${ecm_fpwc_comp}_VERSION+ ${_name_mismatched_arg}+ )++ mark_as_advanced(+ ${module_name}_${ecm_fpwc_comp}_LIBRARY+ ${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR+ )++ if(${module_name}_${ecm_fpwc_comp}_FOUND)+ list(APPEND ${module_name}_LIBRARIES+ "${${module_name}_${ecm_fpwc_comp}_LIBRARY}")+ list(APPEND ${module_name}_INCLUDE_DIRS+ "${${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR}")+ set(${module_name}_DEFINITIONS+ ${${module_name}_DEFINITIONS}+ ${PKG_${module_name}_${ecm_fpwc_comp}_DEFINITIONS})+ if(NOT TARGET ${module_name}::${ecm_fpwc_comp})+ add_library(${module_name}::${ecm_fpwc_comp} UNKNOWN IMPORTED)+ set_target_properties(${module_name}::${ecm_fpwc_comp} PROPERTIES+ IMPORTED_LOCATION "${${module_name}_${ecm_fpwc_comp}_LIBRARY}"+ INTERFACE_COMPILE_OPTIONS "${PKG_${module_name}_${ecm_fpwc_comp}_DEFINITIONS}"+ INTERFACE_INCLUDE_DIRECTORIES "${${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR}"+ INTERFACE_LINK_LIBRARIES "${ecm_fpwc_dep_targets}"+ )+ endif()+ list(APPEND ${module_name}_TARGETS+ "${module_name}::${ecm_fpwc_comp}")+ endif()+ endforeach()+ if(${module_name}_LIBRARIES)+ list(REMOVE_DUPLICATES ${module_name}_LIBRARIES)+ endif()+ if(${module_name}_INCLUDE_DIRS)+ list(REMOVE_DUPLICATES ${module_name}_INCLUDE_DIRS)+ endif()+ if(${module_name}_DEFINITIONS)+ list(REMOVE_DUPLICATES ${module_name}_DEFINITIONS)+ endif()+ if(${module_name}_TARGETS)+ list(REMOVE_DUPLICATES ${module_name}_TARGETS)+ endif()+endmacro()
+ cbits/tracy/cmake/FindWaylandScanner.cmake view
@@ -0,0 +1,170 @@+#.rst:+# FindWaylandScanner+# ------------------+#+# Try to find wayland-scanner.+#+# If the wayland-scanner executable is not in your PATH, you can provide+# an alternative name or full path location with the ``WaylandScanner_EXECUTABLE``+# variable.+#+# This will define the following variables:+#+# ``WaylandScanner_FOUND``+# True if wayland-scanner is available.+#+# ``WaylandScanner_EXECUTABLE``+# The wayland-scanner executable.+#+# If ``WaylandScanner_FOUND`` is TRUE, it will also define the following imported+# target:+#+# ``Wayland::Scanner``+# The wayland-scanner executable.+#+# This module provides the following functions to generate C protocol+# implementations:+#+# - ``ecm_add_wayland_client_protocol``+# - ``ecm_add_wayland_server_protocol``+#+# ::+#+# ecm_add_wayland_client_protocol(<source_files_var>+# PROTOCOL <xmlfile>+# BASENAME <basename>)+#+# Generate Wayland client protocol files from ``<xmlfile>`` XML+# definition for the ``<basename>`` interface and append those files+# to ``<source_files_var>``.+#+# ::+#+# ecm_add_wayland_server_protocol(<source_files_var>+# PROTOCOL <xmlfile>+# BASENAME <basename>)+#+# Generate Wayland server protocol files from ``<xmlfile>`` XML+# definition for the ``<basename>`` interface and append those files+# to ``<source_files_var>``.+#+# Since 1.4.0.++#=============================================================================+# Copyright 2012-2014 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>+#+# Redistribution and use in source and binary forms, with or without+# modification, are permitted provided that the following conditions+# are met:+#+# 1. Redistributions of source code must retain the copyright+# notice, this list of conditions and the following disclaimer.+# 2. Redistributions in binary form must reproduce the copyright+# notice, this list of conditions and the following disclaimer in the+# documentation and/or other materials provided with the distribution.+# 3. The name of the author may not be used to endorse or promote products+# derived from this software without specific prior written permission.+#+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.+#=============================================================================++include(${CMAKE_CURRENT_LIST_DIR}/ECMFindModuleHelpers.cmake)++ecm_find_package_version_check(WaylandScanner)++# Find wayland-scanner+find_program(WaylandScanner_EXECUTABLE NAMES wayland-scanner)++include(FindPackageHandleStandardArgs)+find_package_handle_standard_args(WaylandScanner+ FOUND_VAR+ WaylandScanner_FOUND+ REQUIRED_VARS+ WaylandScanner_EXECUTABLE+)++mark_as_advanced(WaylandScanner_EXECUTABLE)++if(NOT TARGET Wayland::Scanner AND WaylandScanner_FOUND)+ add_executable(Wayland::Scanner IMPORTED)+ set_target_properties(Wayland::Scanner PROPERTIES+ IMPORTED_LOCATION "${WaylandScanner_EXECUTABLE}"+ )+endif()++include(FeatureSummary)+set_package_properties(WaylandScanner PROPERTIES+ URL "https://wayland.freedesktop.org/"+ DESCRIPTION "Executable that converts XML protocol files to C code"+)++function(ecm_add_wayland_client_protocol out_var)+ # Parse arguments+ set(oneValueArgs PROTOCOL BASENAME)+ cmake_parse_arguments(ARGS "" "${oneValueArgs}" "" ${ARGN})++ if(ARGS_UNPARSED_ARGUMENTS)+ message(FATAL_ERROR "Unknown keywords given to ecm_add_wayland_client_protocol(): \"${ARGS_UNPARSED_ARGUMENTS}\"")+ endif()++ get_filename_component(_infile ${ARGS_PROTOCOL} ABSOLUTE)+ set(_client_header "${CMAKE_CURRENT_BINARY_DIR}/wayland-${ARGS_BASENAME}-client-protocol.h")+ set(_code "${CMAKE_CURRENT_BINARY_DIR}/wayland-${ARGS_BASENAME}-protocol.c")++ set_source_files_properties(${_client_header} GENERATED)+ set_source_files_properties(${_code} GENERATED)+ set_property(SOURCE ${_client_header} PROPERTY SKIP_AUTOMOC ON)++ add_custom_command(OUTPUT "${_client_header}"+ COMMAND ${WaylandScanner_EXECUTABLE} client-header ${_infile} ${_client_header}+ DEPENDS ${WaylandScanner_EXECUTABLE} ${_infile}+ VERBATIM+ )++ add_custom_command(OUTPUT "${_code}"+ COMMAND ${WaylandScanner_EXECUTABLE} private-code ${_infile} ${_code}+ DEPENDS ${WaylandScanner_EXECUTABLE} ${_infile} ${_client_header}+ VERBATIM+ )++ list(APPEND ${out_var} "${_client_header}" "${_code}")+ set(${out_var} ${${out_var}} PARENT_SCOPE)+endfunction()+++function(ecm_add_wayland_server_protocol out_var)+ # Parse arguments+ set(oneValueArgs PROTOCOL BASENAME)+ cmake_parse_arguments(ARGS "" "${oneValueArgs}" "" ${ARGN})++ if(ARGS_UNPARSED_ARGUMENTS)+ message(FATAL_ERROR "Unknown keywords given to ecm_add_wayland_server_protocol(): \"${ARGS_UNPARSED_ARGUMENTS}\"")+ endif()++ ecm_add_wayland_client_protocol(${out_var}+ PROTOCOL ${ARGS_PROTOCOL}+ BASENAME ${ARGS_BASENAME})++ get_filename_component(_infile ${ARGS_PROTOCOL} ABSOLUTE)+ set(_server_header "${CMAKE_CURRENT_BINARY_DIR}/wayland-${ARGS_BASENAME}-server-protocol.h")+ set_property(SOURCE ${_server_header} PROPERTY SKIP_AUTOMOC ON)+ set_source_files_properties(${_server_header} GENERATED)++ add_custom_command(OUTPUT "${_server_header}"+ COMMAND ${WaylandScanner_EXECUTABLE} server-header ${_infile} ${_server_header}+ DEPENDS ${WaylandScanner_EXECUTABLE} ${_infile}+ VERBATIM+ )++ list(APPEND ${out_var} "${_server_header}")+ set(${out_var} ${${out_var}} PARENT_SCOPE)+endfunction()
+ cbits/tracy/cmake/config.cmake view
@@ -0,0 +1,62 @@+if (NOT NO_ISA_EXTENSIONS)+ include(CheckCXXCompilerFlag)+ if (CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64" OR CMAKE_SYSTEM_PROCESSOR MATCHES "arm64")+ CHECK_CXX_COMPILER_FLAG("-mcpu=native" COMPILER_SUPPORTS_MCPU_NATIVE)+ if(COMPILER_SUPPORTS_MARCH_NATIVE)+ add_compile_options(-mcpu=native)+ endif()+ else()+ CHECK_CXX_COMPILER_FLAG("-march=native" COMPILER_SUPPORTS_MARCH_NATIVE)+ if(COMPILER_SUPPORTS_MARCH_NATIVE)+ add_compile_options(-march=native)+ endif()+ endif()+ if(WIN32)+ add_compile_options(/arch:AVX2)+ endif()+endif()++if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND NOT LEGACY)+ set(USE_WAYLAND ON)+else()+ set(USE_WAYLAND OFF)+endif()++if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")+ if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")+ add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fexperimental-library>)+ endif()+endif()++if(WIN32)+ add_definitions(-DNOMINMAX -DWIN32_LEAN_AND_MEAN -D_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR)+ add_compile_options(/MP)+endif()++if(EMSCRIPTEN)+ add_compile_options(-pthread -DIMGUI_IMPL_OPENGL_ES2)+endif()++if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT EMSCRIPTEN)+ set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON)+endif()++if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_SYSTEM_NAME STREQUAL "Linux")+ find_program(MOLD_LINKER mold)+ if(MOLD_LINKER)+ set(CMAKE_LINKER_TYPE "MOLD")+ endif()+ if (CMAKE_BUILD_TYPE STREQUAL "Debug")+ add_compile_options(-fno-eliminate-unused-debug-types)+ endif()+endif()++find_program(CCACHE ccache)+if(CCACHE)+ set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)+ set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache) +endif()++file(GENERATE OUTPUT .gitignore CONTENT "*")++set(CMAKE_COLOR_DIAGNOSTICS ON)
+ cbits/tracy/cmake/gl3w-extra-symbols.patch view
@@ -0,0 +1,12 @@+diff --git a/extra_symbols.txt b/extra_symbols.txt+index b95bb58..6b8f616 100644+--- a/extra_symbols.txt++++ b/extra_symbols.txt+@@ -1,3 +1,7 @@++glCompressedTexImage2D++GL_LINEAR_MIPMAP_LINEAR++GL_TEXTURE_WRAP_S++GL_TEXTURE_WRAP_T+ glReadPixels+ glClearColor+ glClear
+ cbits/tracy/cmake/imgui-emscripten.patch view
@@ -0,0 +1,14 @@+diff '--color=auto' -ruN 72d8f61727dc878102157113d1998f86b852d20e/imconfig.h new/imconfig.h+--- 72d8f61727dc878102157113d1998f86b852d20e/imconfig.h 2024-09-27 14:28:05.568760349 +0200++++ new/imconfig.h 2024-09-27 14:29:47.310243707 +0200+@@ -113,6 +113,10 @@+ // Read about ImGuiBackendFlags_RendererHasVtxOffset for details.+ //#define ImDrawIdx unsigned int+ ++#ifdef __EMSCRIPTEN__++#define ImDrawIdx unsigned int++#endif+++ //---- Override ImDrawCallback signature (will need to modify renderer backends accordingly)+ //struct ImDrawList;+ //struct ImDrawCmd;
+ cbits/tracy/cmake/imgui-loader.patch view
@@ -0,0 +1,56 @@+diff --git a/backends/imgui_impl_opengl3_loader.h b/backends/imgui_impl_opengl3_loader.h+index d6ffa5a2d..e48372c64 100644+--- a/backends/imgui_impl_opengl3_loader.h++++ b/backends/imgui_impl_opengl3_loader.h+@@ -179,6 +179,7 @@ typedef khronos_uint8_t GLubyte;+ #define GL_VERSION 0x1F02+ #define GL_EXTENSIONS 0x1F03+ #define GL_LINEAR 0x2601++#define GL_LINEAR_MIPMAP_LINEAR 0x2703+ #define GL_TEXTURE_MAG_FILTER 0x2800+ #define GL_TEXTURE_MIN_FILTER 0x2801+ #define GL_TEXTURE_WRAP_S 0x2802+@@ -241,8 +242,10 @@ GLAPI void APIENTRY glGenTextures (GLsizei n, GLuint *textures);+ #define GL_TEXTURE0 0x84C0+ #define GL_ACTIVE_TEXTURE 0x84E0+ typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);++typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);+ #ifdef GL_GLEXT_PROTOTYPES+ GLAPI void APIENTRY glActiveTexture (GLenum texture);++GLAPI void APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);+ #endif+ #endif /* GL_VERSION_1_3 */+ #ifndef GL_VERSION_1_4+@@ -478,7 +481,7 @@ GL3W_API GL3WglProc imgl3wGetProcAddress(const char *proc);+ + /* gl3w internal state */+ union ImGL3WProcs {+- GL3WglProc ptr[59];++ GL3WglProc ptr[60];+ struct {+ PFNGLACTIVETEXTUREPROC ActiveTexture;+ PFNGLATTACHSHADERPROC AttachShader;+@@ -494,6 +497,7 @@ union ImGL3WProcs {+ PFNGLCLEARPROC Clear;+ PFNGLCLEARCOLORPROC ClearColor;+ PFNGLCOMPILESHADERPROC CompileShader;++ PFNGLCOMPRESSEDTEXIMAGE2DPROC CompressedTexImage2D;+ PFNGLCREATEPROGRAMPROC CreateProgram;+ PFNGLCREATESHADERPROC CreateShader;+ PFNGLDELETEBUFFERSPROC DeleteBuffers;+@@ -559,6 +563,7 @@ GL3W_API extern union ImGL3WProcs imgl3wProcs;+ #define glClear imgl3wProcs.gl.Clear+ #define glClearColor imgl3wProcs.gl.ClearColor+ #define glCompileShader imgl3wProcs.gl.CompileShader++#define glCompressedTexImage2D imgl3wProcs.gl.CompressedTexImage2D+ #define glCreateProgram imgl3wProcs.gl.CreateProgram+ #define glCreateShader imgl3wProcs.gl.CreateShader+ #define glDeleteBuffers imgl3wProcs.gl.DeleteBuffers+@@ -854,6 +859,7 @@ static const char *proc_names[] = {+ "glClear",+ "glClearColor",+ "glCompileShader",++ "glCompressedTexImage2D",+ "glCreateProgram",+ "glCreateShader",+ "glDeleteBuffers",
+ cbits/tracy/cmake/ppqsort-nodebug.patch view
@@ -0,0 +1,14 @@+diff --git i/include/ppqsort/parameters.h w/include/ppqsort/parameters.h+index 115c3a1..3f4b669 100644+--- i/include/ppqsort/parameters.h++++ w/include/ppqsort/parameters.h+@@ -3,7 +3,8 @@+ #include <bit>+ #include <execution>+ +-#ifndef NDEBUG++//#ifndef NDEBUG++#if 0+ #include <bitset>+ #include <iostream>+ #include <syncstream>
+ cbits/tracy/cmake/server.cmake view
@@ -0,0 +1,35 @@+set(TRACY_COMMON_DIR ${CMAKE_CURRENT_LIST_DIR}/../public/common)++set(TRACY_COMMON_SOURCES+ tracy_lz4.cpp+ tracy_lz4hc.cpp+ TracySocket.cpp+ TracyStackFrames.cpp+ TracySystem.cpp+)++list(TRANSFORM TRACY_COMMON_SOURCES PREPEND "${TRACY_COMMON_DIR}/")+++set(TRACY_SERVER_DIR ${CMAKE_CURRENT_LIST_DIR}/../server)++set(TRACY_SERVER_SOURCES+ TracyMemory.cpp+ TracyMmap.cpp+ TracyPrint.cpp+ TracySysUtil.cpp+ TracyTaskDispatch.cpp+ TracyTextureCompression.cpp+ TracyThreadCompress.cpp+ TracyWorker.cpp+)++list(TRANSFORM TRACY_SERVER_SOURCES PREPEND "${TRACY_SERVER_DIR}/")+++add_library(TracyServer STATIC EXCLUDE_FROM_ALL ${TRACY_COMMON_SOURCES} ${TRACY_SERVER_SOURCES})+target_include_directories(TracyServer PUBLIC ${TRACY_COMMON_DIR} ${TRACY_SERVER_DIR})+target_link_libraries(TracyServer PUBLIC TracyCapstone libzstd PPQSort::PPQSort)+if(NO_STATISTICS)+ target_compile_definitions(TracyServer PUBLIC TRACY_NO_STATISTICS)+endif()
+ cbits/tracy/cmake/vendor.cmake view
@@ -0,0 +1,193 @@+# Vendor Specific CMake+# The Tracy project keeps most vendor source locally++set (ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}/../")++# Dependencies are taken from the system first and if not found, they are pulled with CPM and built from source++include(FindPkgConfig)+include(${CMAKE_CURRENT_LIST_DIR}/CPM.cmake)++option(DOWNLOAD_CAPSTONE "Force download capstone" ON)+option(DOWNLOAD_GLFW "Force download glfw" OFF)+option(DOWNLOAD_FREETYPE "Force download freetype" OFF)++# capstone++pkg_check_modules(CAPSTONE capstone)+if(CAPSTONE_FOUND AND NOT DOWNLOAD_CAPSTONE)+ message(STATUS "Capstone found: ${CAPSTONE}")+ add_library(TracyCapstone INTERFACE)+ target_include_directories(TracyCapstone INTERFACE ${CAPSTONE_INCLUDE_DIRS})+ target_link_libraries(TracyCapstone INTERFACE ${CAPSTONE_LINK_LIBRARIES})+else()+ CPMAddPackage(+ NAME capstone+ GITHUB_REPOSITORY capstone-engine/capstone+ GIT_TAG 6.0.0-Alpha1+ OPTIONS+ "CAPSTONE_X86_ATT_DISABLE ON"+ "CAPSTONE_ALPHA_SUPPORT OFF"+ "CAPSTONE_HPPA_SUPPORT OFF"+ "CAPSTONE_LOONGARCH_SUPPORT OFF"+ "CAPSTONE_M680X_SUPPORT OFF"+ "CAPSTONE_M68K_SUPPORT OFF"+ "CAPSTONE_MIPS_SUPPORT OFF"+ "CAPSTONE_MOS65XX_SUPPORT OFF"+ "CAPSTONE_PPC_SUPPORT OFF"+ "CAPSTONE_SPARC_SUPPORT OFF"+ "CAPSTONE_SYSTEMZ_SUPPORT OFF"+ "CAPSTONE_XCORE_SUPPORT OFF"+ "CAPSTONE_TRICORE_SUPPORT OFF"+ "CAPSTONE_TMS320C64X_SUPPORT OFF"+ "CAPSTONE_M680X_SUPPORT OFF"+ "CAPSTONE_EVM_SUPPORT OFF"+ "CAPSTONE_WASM_SUPPORT OFF"+ "CAPSTONE_BPF_SUPPORT OFF"+ "CAPSTONE_RISCV_SUPPORT OFF"+ "CAPSTONE_SH_SUPPORT OFF"+ "CAPSTONE_XTENSA_SUPPORT OFF"+ "CAPSTONE_BUILD_MACOS_THIN ON"+ EXCLUDE_FROM_ALL TRUE+ )+ add_library(TracyCapstone INTERFACE)+ target_include_directories(TracyCapstone INTERFACE ${capstone_SOURCE_DIR}/include/capstone)+ target_link_libraries(TracyCapstone INTERFACE capstone)+endif()++# GLFW++if(NOT USE_WAYLAND AND NOT EMSCRIPTEN)+ pkg_check_modules(GLFW glfw3)+ if (GLFW_FOUND AND NOT DOWNLOAD_GLFW)+ add_library(TracyGlfw3 INTERFACE)+ target_include_directories(TracyGlfw3 INTERFACE ${GLFW_INCLUDE_DIRS})+ target_link_libraries(TracyGlfw3 INTERFACE ${GLFW_LINK_LIBRARIES})+ else()+ CPMAddPackage(+ NAME glfw+ GITHUB_REPOSITORY glfw/glfw+ GIT_TAG 3.4+ OPTIONS+ "GLFW_BUILD_EXAMPLES OFF"+ "GLFW_BUILD_TESTS OFF"+ "GLFW_BUILD_DOCS OFF"+ "GLFW_INSTALL OFF"+ EXCLUDE_FROM_ALL TRUE+ )+ add_library(TracyGlfw3 INTERFACE)+ target_link_libraries(TracyGlfw3 INTERFACE glfw)+ endif()+endif()++# freetype++pkg_check_modules(FREETYPE freetype2)+if (FREETYPE_FOUND AND NOT DOWNLOAD_FREETYPE)+ add_library(TracyFreetype INTERFACE)+ target_include_directories(TracyFreetype INTERFACE ${FREETYPE_INCLUDE_DIRS})+ target_link_libraries(TracyFreetype INTERFACE ${FREETYPE_LINK_LIBRARIES})+else()+ CPMAddPackage(+ NAME freetype+ GITHUB_REPOSITORY freetype/freetype+ GIT_TAG VER-2-13-3+ OPTIONS+ "FT_DISABLE_HARFBUZZ ON"+ "FT_WITH_HARFBUZZ OFF"+ EXCLUDE_FROM_ALL TRUE+ )+ add_library(TracyFreetype INTERFACE)+ target_link_libraries(TracyFreetype INTERFACE freetype)+endif()++# Zstd++CPMAddPackage(+ NAME zstd+ GITHUB_REPOSITORY facebook/zstd+ GIT_TAG v1.5.7+ OPTIONS+ "ZSTD_BUILD_SHARED OFF"+ EXCLUDE_FROM_ALL TRUE+ SOURCE_SUBDIR build/cmake+)++# Diff Template Library++set(DTL_DIR "${ROOT_DIR}/dtl")+file(GLOB_RECURSE DTL_HEADERS CONFIGURE_DEPENDS RELATIVE ${DTL_DIR} "*.hpp")+add_library(TracyDtl INTERFACE)+target_sources(TracyDtl INTERFACE ${DTL_HEADERS})+target_include_directories(TracyDtl INTERFACE ${DTL_DIR})++# Get Opt++set(GETOPT_DIR "${ROOT_DIR}/getopt")+set(GETOPT_SOURCES ${GETOPT_DIR}/getopt.c)+set(GETOPT_HEADERS ${GETOPT_DIR}/getopt.h)+add_library(TracyGetOpt STATIC EXCLUDE_FROM_ALL ${GETOPT_SOURCES} ${GETOPT_HEADERS})+target_include_directories(TracyGetOpt PUBLIC ${GETOPT_DIR})++# ImGui++CPMAddPackage(+ NAME ImGui+ GITHUB_REPOSITORY ocornut/imgui+ GIT_TAG v1.91.9b-docking+ DOWNLOAD_ONLY TRUE+ PATCHES+ "${CMAKE_CURRENT_LIST_DIR}/imgui-emscripten.patch"+ "${CMAKE_CURRENT_LIST_DIR}/imgui-loader.patch"+)++set(IMGUI_SOURCES+ imgui_widgets.cpp+ imgui_draw.cpp+ imgui_demo.cpp+ imgui.cpp+ imgui_tables.cpp+ misc/freetype/imgui_freetype.cpp+ backends/imgui_impl_opengl3.cpp+)++list(TRANSFORM IMGUI_SOURCES PREPEND "${ImGui_SOURCE_DIR}/")++add_library(TracyImGui STATIC EXCLUDE_FROM_ALL ${IMGUI_SOURCES})+target_include_directories(TracyImGui PUBLIC ${ImGui_SOURCE_DIR})+target_link_libraries(TracyImGui PUBLIC TracyFreetype)+target_compile_definitions(TracyImGui PRIVATE "IMGUI_ENABLE_FREETYPE")++if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")+ target_compile_definitions(TracyImGui PRIVATE "IMGUI_DISABLE_DEBUG_TOOLS")+endif()++# NFD++if(NOT NO_FILESELECTOR AND NOT EMSCRIPTEN)+ if(GTK_FILESELECTOR)+ set(NFD_PORTAL OFF)+ else()+ set(NFD_PORTAL ON)+ endif()++ CPMAddPackage(+ NAME nfd+ GITHUB_REPOSITORY btzy/nativefiledialog-extended+ GIT_TAG v1.2.1+ EXCLUDE_FROM_ALL TRUE+ OPTIONS+ "NFD_PORTAL ${NFD_PORTAL}"+ )+endif()++# PPQSort++CPMAddPackage(+ NAME PPQSort+ GITHUB_REPOSITORY GabTux/PPQSort+ VERSION 1.0.5+ PATCHES+ "${CMAKE_CURRENT_LIST_DIR}/ppqsort-nodebug.patch"+ EXCLUDE_FROM_ALL TRUE+)
+ cbits/tracy/cmake/version.cmake view
@@ -0,0 +1,24 @@+cmake_minimum_required(VERSION 3.10)++message("Parsing public/common/TracyVersion.hpp file")++file(READ "${CMAKE_CURRENT_LIST_DIR}/../public/common/TracyVersion.hpp" version)++# Note: This looks for a specific pattern in TracyVersion.hpp, if it changes+# this needs updating.+string(REGEX MATCH "Major = ([0-9]+)" _ ${version})++# This works do to the above () subexpression selection. See+# https://cmake.org/cmake/help/latest/command/string.html#regex-match for more+# details+set(TRACY_VERSION_MAJOR ${CMAKE_MATCH_1})++string(REGEX MATCH "Minor = ([0-9]+)" _ ${version})+set(TRACY_VERSION_MINOR ${CMAKE_MATCH_1})++string(REGEX MATCH "Patch = ([0-9]+)" _ ${version})+set(TRACY_VERSION_PATCH ${CMAKE_MATCH_1})++set(TRACY_VERSION_STRING "${TRACY_VERSION_MAJOR}.${TRACY_VERSION_MINOR}.${TRACY_VERSION_PATCH}")++message("VERSION ${TRACY_VERSION_STRING}")
+ cbits/tracy/dtl/Diff.hpp view
@@ -0,0 +1,706 @@+/**+ dtl -- Diff Template Library+ + In short, Diff Template Library is distributed under so called "BSD license",+ + Copyright (c) 2015 Tatsuhiko Kubo <cubicdaiya@gmail.com>+ All rights reserved.+ + 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 authors 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.+*/++/* If you use this library, you must include dtl.hpp only. */++#ifndef DTL_DIFF_H+#define DTL_DIFF_H++namespace dtl {+ + /**+ * diff class template+ * sequence must support random_access_iterator.+ */+ template <typename elem, typename sequence = vector< elem >, typename comparator = Compare< elem > >+ class Diff+ {+ private :+ dtl_typedefs(elem, sequence)+ sequence A;+ sequence B;+ size_t M;+ size_t N;+ size_t delta;+ size_t offset;+ long long *fp;+ long long editDistance;+ Lcs< elem > lcs;+ Ses< elem > ses;+ editPath path;+ editPathCordinates pathCordinates;+ bool swapped;+ bool huge;+ bool trivial;+ bool editDistanceOnly;+ uniHunkVec uniHunks;+ comparator cmp;+ long long ox;+ long long oy;+ public :+ Diff () {}+ + Diff (const sequence& a, + const sequence& b) : A(a), B(b), ses(false) {+ init();+ }+ + Diff (const sequence& a,+ const sequence& b,+ bool deletesFirst) : A(a), B(b), ses(deletesFirst) {+ init();+ }+ + Diff (const sequence& a,+ const sequence& b, + const comparator& comp) : A(a), B(b), ses(false), cmp(comp) {+ init();+ }+ + Diff (const sequence& a, + const sequence& b, + bool deleteFirst,+ const comparator& comp) : A(a), B(b), ses(deleteFirst), cmp(comp) {+ init();+ }+ + ~Diff() {}+ + long long getEditDistance () const {+ return editDistance;+ }+ + Lcs< elem > getLcs () const {+ return lcs;+ }+ + elemVec getLcsVec () const {+ return lcs.getSequence();+ }+ + Ses< elem > getSes () const {+ return ses;+ }+ + uniHunkVec getUniHunks () const {+ return uniHunks;+ }+ + /* These should be deprecated */+ bool isHuge () const {+ return huge;+ }+ + void onHuge () {+ this->huge = true;+ }+ + void offHuge () {+ this->huge = false;+ }+ + bool isUnserious () const {+ return trivial;+ }+ + void onUnserious () {+ this->trivial = true;+ }+ + void offUnserious () {+ this->trivial = false;+ }+ + void onOnlyEditDistance () {+ this->editDistanceOnly = true;+ }+ + /* These are the replacements for the above */+ bool hugeEnabled () const {+ return huge;+ }+ + void enableHuge () {+ this->huge = true;+ }+ + void disableHuge () {+ this->huge = false;+ }+ + bool trivialEnabled () const {+ return trivial;+ }+ + void enableTrivial () {+ this->trivial = true;+ }+ + void disableTrivial () {+ this->trivial = false;+ }+ + void editDistanceOnlyEnabled () {+ this->editDistanceOnly = true;+ }+ + /**+ * patching with Unified Format Hunks+ */+ sequence uniPatch (const sequence& seq) {+ elemList seqLst(seq.begin(), seq.end());+ sesElemVec shunk;+ sesElemVec_iter vsesIt;+ elemList_iter lstIt = seqLst.begin();+ long long inc_dec_total = 0;+ long long gap = 1;+ for (uniHunkVec_iter it=uniHunks.begin();it!=uniHunks.end();++it) {+ joinSesVec(shunk, it->common[0]);+ joinSesVec(shunk, it->change);+ joinSesVec(shunk, it->common[1]);+ it->a += inc_dec_total;+ inc_dec_total += it->inc_dec_count;+ for (long long i=0;i<it->a - gap;++i) {+ ++lstIt;+ }+ gap = it->a + it->b + it->inc_dec_count;+ vsesIt = shunk.begin();+ while (vsesIt!=shunk.end()) {+ switch (vsesIt->second.type) {+ case SES_ADD :+ seqLst.insert(lstIt, vsesIt->first);+ break;+ case SES_DELETE :+ if (lstIt != seqLst.end()) {+ lstIt = seqLst.erase(lstIt);+ }+ break;+ case SES_COMMON :+ if (lstIt != seqLst.end()) {+ ++lstIt;+ }+ break;+ default :+ // no fall-through+ break;+ }+ ++vsesIt;+ }+ shunk.clear();+ }+ + sequence patchedSeq(seqLst.begin(), seqLst.end());+ return patchedSeq;+ }+ + /**+ * patching with Shortest Edit Script (SES)+ */+ sequence patch (const sequence& seq) const {+ sesElemVec sesSeq = ses.getSequence();+ elemList seqLst(seq.begin(), seq.end());+ elemList_iter lstIt = seqLst.begin();+ for (sesElemVec_iter sesIt=sesSeq.begin();sesIt!=sesSeq.end();++sesIt) {+ switch (sesIt->second.type) {+ case SES_ADD :+ seqLst.insert(lstIt, sesIt->first);+ break;+ case SES_DELETE :+ lstIt = seqLst.erase(lstIt);+ break;+ case SES_COMMON :+ ++lstIt;+ break;+ default :+ // no through+ break;+ }+ }+ sequence patchedSeq(seqLst.begin(), seqLst.end());+ return patchedSeq;+ }+ + /**+ * compose Longest Common Subsequence and Shortest Edit Script.+ * The algorithm implemented here is based on "An O(NP) Sequence Comparison Algorithm"+ * described by Sun Wu, Udi Manber and Gene Myers+ */+ void compose() {+ + if (isHuge()) {+ pathCordinates.reserve(MAX_CORDINATES_SIZE);+ }+ ox = 0;+ oy = 0;+ long long p = -1;+ fp = new long long[M + N + 3];+ fill(&fp[0], &fp[M + N + 3], -1);+ path = editPath(M + N + 3);+ fill(path.begin(), path.end(), -1);+ ONP:+ do {+ ++p;+ for (long long k=-p;k<=static_cast<long long>(delta)-1;++k) {+ fp[k+offset] = snake(k, fp[k-1+offset]+1, fp[k+1+offset]);+ }+ for (long long k=static_cast<long long>(delta)+p;k>=static_cast<long long>(delta)+1;--k) {+ fp[k+offset] = snake(k, fp[k-1+offset]+1, fp[k+1+offset]);+ }+ fp[delta+offset] = snake(static_cast<long long>(delta), fp[delta-1+offset]+1, fp[delta+1+offset]);+ } while (fp[delta+offset] != static_cast<long long>(N) && pathCordinates.size() < MAX_CORDINATES_SIZE);+ + editDistance += static_cast<long long>(delta) + 2 * p;+ long long r = path[delta+offset];+ P cordinate;+ editPathCordinates epc(0);+ + // recording edit distance only+ if (editDistanceOnly) {+ delete[] this->fp;+ return;+ }+ + while(r != -1) {+ cordinate.x = pathCordinates[(size_t)r].x;+ cordinate.y = pathCordinates[(size_t)r].y;+ epc.push_back(cordinate);+ r = pathCordinates[(size_t)r].k;+ }+ + // record Longest Common Subsequence & Shortest Edit Script+ if (!recordSequence(epc)) {+ pathCordinates.resize(0);+ epc.resize(0);+ p = -1;+ goto ONP;+ }+ delete[] this->fp;+ }++ /**+ * print difference between A and B as an SES+ */+ template < typename stream >+ void printSES (stream& out) const {+ sesElemVec ses_v = ses.getSequence();+ for_each(ses_v.begin(), ses_v.end(), ChangePrinter< sesElem, stream >(out));+ }+ + void printSES (ostream& out = cout) const {+ printSES< ostream >(out);+ }+ + /**+ * print differences given an SES+ */+ template < typename stream >+ static void printSES (const Ses< elem >& s, stream& out) {+ sesElemVec ses_v = s.getSequence();+ for_each(ses_v.begin(), ses_v.end(), ChangePrinter< sesElem, stream >(out));+ }+ + static void printSES (const Ses< elem >& s, ostream& out = cout) {+ printSES< ostream >(s, out);+ }++ /**+ * print difference between A and B as an SES with custom printer+ */+ template < typename stream, template < typename SEET, typename STRT > class PT >+ void printSES (stream& out) const {+ sesElemVec ses_v = ses.getSequence ();+ for_each (ses_v.begin (), ses_v.end(), PT < sesElem, stream > (out));+ }++ /**+ * store difference between A and B as an SES with custom storage+ */+ template < typename storedData, template < typename SEET, typename STRT > class ST >+ void storeSES(storedData& sd) const {+ sesElemVec ses_v = ses.getSequence();+ for_each(ses_v.begin(), ses_v.end(), ST < sesElem, storedData >(sd));+ }+ + /**+ * print difference between A and B in the Unified Format+ */+ template < typename stream >+ void printUnifiedFormat (stream& out) const {+ for_each(uniHunks.begin(), uniHunks.end(), UniHunkPrinter< sesElem, stream >(out));+ }+ + void printUnifiedFormat (ostream& out = cout) const {+ printUnifiedFormat< ostream >(out);+ }+ + /**+ * print unified format difference with given unified format hunks+ */+ template < typename stream >+ static void printUnifiedFormat (const uniHunkVec& hunks, stream& out) {+ for_each(hunks.begin(), hunks.end(), UniHunkPrinter< sesElem >(out));+ }++ static void printUnifiedFormat (const uniHunkVec& hunks, ostream& out = cout) {+ printUnifiedFormat< ostream >(hunks, out);+ }++ /**+ * compose Unified Format Hunks from Shortest Edit Script+ */+ void composeUnifiedHunks () {+ sesElemVec common[2];+ sesElemVec change;+ sesElemVec ses_v = ses.getSequence();+ long long l_cnt = 1;+ long long length = distance(ses_v.begin(), ses_v.end());+ long long middle = 0;+ bool isMiddle, isAfter;+ elemInfo einfo;+ long long a, b, c, d; // @@ -a,b +c,d @@+ long long inc_dec_count = 0;+ uniHunk< sesElem > hunk;+ sesElemVec adds;+ sesElemVec deletes;+ + isMiddle = isAfter = false;+ a = b = c = d = 0;+ + for (sesElemVec_iter it=ses_v.begin();it!=ses_v.end();++it, ++l_cnt) {+ einfo = it->second;+ switch (einfo.type) {+ case SES_ADD :+ middle = 0;+ ++inc_dec_count;+ adds.push_back(*it);+ if (!isMiddle) isMiddle = true;+ if (isMiddle) ++d;+ if (l_cnt >= length) {+ joinSesVec(change, deletes);+ joinSesVec(change, adds);+ isAfter = true;+ }+ break;+ case SES_DELETE :+ middle = 0;+ --inc_dec_count;+ deletes.push_back(*it);+ if (!isMiddle) isMiddle = true;+ if (isMiddle) ++b;+ if (l_cnt >= length) {+ joinSesVec(change, deletes);+ joinSesVec(change, adds);+ isAfter = true;+ }+ break;+ case SES_COMMON :+ ++b;++d;+ if (common[1].empty() && adds.empty() && deletes.empty() && change.empty()) {+ if (static_cast<long long>(common[0].size()) < DTL_CONTEXT_SIZE) {+ if (a == 0 && c == 0) {+ if (!wasSwapped()) {+ a = einfo.beforeIdx;+ c = einfo.afterIdx;+ } else {+ a = einfo.afterIdx;+ c = einfo.beforeIdx;+ }+ }+ common[0].push_back(*it);+ } else {+ rotate(common[0].begin(), common[0].begin() + 1, common[0].end());+ common[0].pop_back();+ common[0].push_back(*it);+ ++a;++c;+ --b;--d;+ }+ }+ if (isMiddle && !isAfter) {+ ++middle;+ joinSesVec(change, deletes);+ joinSesVec(change, adds);+ change.push_back(*it);+ if (middle >= DTL_SEPARATE_SIZE || l_cnt >= length) {+ isAfter = true;+ }+ adds.clear();+ deletes.clear();+ }+ break;+ default :+ // no through+ break;+ }+ // compose unified format hunk+ if (isAfter && !change.empty()) {+ sesElemVec_iter cit = it;+ long long cnt = 0;+ for (long long i=0;i<DTL_SEPARATE_SIZE && (cit != ses_v.end());++i, ++cit) {+ if (cit->second.type == SES_COMMON) {+ ++cnt;+ }+ }+ if (cnt < DTL_SEPARATE_SIZE && l_cnt < length) {+ middle = 0;+ isAfter = false;+ continue;+ }+ if (static_cast<long long>(common[0].size()) >= DTL_SEPARATE_SIZE) {+ long long c0size = static_cast<long long>(common[0].size());+ rotate(common[0].begin(), + common[0].begin() + (size_t)c0size - DTL_SEPARATE_SIZE, + common[0].end());+ for (long long i=0;i<c0size - DTL_SEPARATE_SIZE;++i) {+ common[0].pop_back();+ }+ a += c0size - DTL_SEPARATE_SIZE;+ c += c0size - DTL_SEPARATE_SIZE;+ }+ if (a == 0) ++a;+ if (c == 0) ++c;+ if (wasSwapped()) swap(a, c);+ hunk.a = a;+ hunk.b = b;+ hunk.c = c;+ hunk.d = d;+ hunk.common[0] = common[0];+ hunk.change = change;+ hunk.common[1] = common[1];+ hunk.inc_dec_count = inc_dec_count;+ uniHunks.push_back(hunk);+ isMiddle = false;+ isAfter = false;+ common[0].clear();+ common[1].clear();+ adds.clear();+ deletes.clear();+ change.clear();+ a = b = c = d = middle = inc_dec_count = 0;+ }+ }+ }+ + /**+ * compose ses from stream+ */+ template <typename stream>+ static Ses< elem > composeSesFromStream (stream& st)+ {+ elem line;+ Ses< elem > ret;+ long long x_idx, y_idx;+ x_idx = y_idx = 1;+ while (getline(st, line)) {+ elem mark(line.begin(), line.begin() + 1);+ elem e(line.begin() + 1, line.end());+ if (mark == SES_MARK_DELETE) {+ ret.addSequence(e, x_idx, 0, SES_DELETE);+ ++x_idx;+ } else if (mark == SES_MARK_ADD) {+ ret.addSequence(e, y_idx, 0, SES_ADD);+ ++y_idx;+ } else if (mark == SES_MARK_COMMON) {+ ret.addSequence(e, x_idx, y_idx, SES_COMMON);+ ++x_idx;+ ++y_idx;+ }+ }+ return ret;+ }+ + private :+ /**+ * initialize+ */+ void init () {+ M = distance(A.begin(), A.end());+ N = distance(B.begin(), B.end());+ if (M < N) {+ swapped = false;+ } else {+ swap(A, B);+ swap(M, N);+ swapped = true;+ }+ editDistance = 0;+ delta = N - M;+ offset = M + 1;+ huge = false;+ trivial = false;+ editDistanceOnly = false;+ fp = NULL;+ }+ + /**+ * search shortest path and record the path+ */+ long long snake(const long long& k, const long long& above, const long long& below) {+ long long r = above > below ? path[(size_t)k-1+offset] : path[(size_t)k+1+offset];+ long long y = max(above, below);+ long long x = y - k;+ while ((size_t)x < M && (size_t)y < N && (swapped ? cmp.impl(B[(size_t)y], A[(size_t)x]) : cmp.impl(A[(size_t)x], B[(size_t)y]))) {+ ++x;++y;+ }+ + path[(size_t)k+offset] = static_cast<long long>(pathCordinates.size());+ if (!editDistanceOnly) {+ P p;+ p.x = x;p.y = y;p.k = r;+ pathCordinates.push_back(p); + }+ return y;+ }+ + /**+ * record SES and LCS+ */+ bool recordSequence (const editPathCordinates& v) {+ sequence_const_iter x(A.begin());+ sequence_const_iter y(B.begin());+ long long x_idx, y_idx; // line number for Unified Format+ long long px_idx, py_idx; // cordinates+ bool complete = false;+ x_idx = y_idx = 1;+ px_idx = py_idx = 0;+ for (size_t i=v.size()-1;!complete;--i) {+ while(px_idx < v[i].x || py_idx < v[i].y) {+ if (v[i].y - v[i].x > py_idx - px_idx) {+ if (!wasSwapped()) {+ ses.addSequence(*y, 0, y_idx + oy, SES_ADD);+ } else {+ ses.addSequence(*y, y_idx + oy, 0, SES_DELETE);+ }+ ++y;+ ++y_idx;+ ++py_idx;+ } else if (v[i].y - v[i].x < py_idx - px_idx) {+ if (!wasSwapped()) {+ ses.addSequence(*x, x_idx + ox, 0, SES_DELETE);+ } else {+ ses.addSequence(*x, 0, x_idx + ox, SES_ADD);+ }+ ++x;+ ++x_idx;+ ++px_idx;+ } else {+ if (!wasSwapped()) {+ lcs.addSequence(*x);+ ses.addSequence(*x, x_idx + ox, y_idx + oy, SES_COMMON);+ } else {+ lcs.addSequence(*y);+ ses.addSequence(*y, y_idx + oy, x_idx + ox, SES_COMMON);+ }+ ++x;+ ++y;+ ++x_idx;+ ++y_idx;+ ++px_idx;+ ++py_idx;+ }+ }+ if (i == 0) complete = true;+ }+ + if (x_idx > static_cast<long long>(M) && y_idx > static_cast<long long>(N)) {+ // all recording succeeded+ } else {+ // trivial difference+ if (trivialEnabled()) {+ if (!wasSwapped()) {+ recordOddSequence(x_idx, M, x, SES_DELETE);+ recordOddSequence(y_idx, N, y, SES_ADD);+ } else {+ recordOddSequence(x_idx, M, x, SES_ADD);+ recordOddSequence(y_idx, N, y, SES_DELETE);+ }+ return true;+ }+ + // nontrivial difference+ sequence A_(A.begin() + (size_t)x_idx - 1, A.end());+ sequence B_(B.begin() + (size_t)y_idx - 1, B.end());+ A = A_;+ B = B_;+ M = distance(A.begin(), A.end());+ N = distance(B.begin(), B.end());+ delta = N - M;+ offset = M + 1;+ delete[] fp;+ fp = new long long[M + N + 3];+ fill(&fp[0], &fp[M + N + 3], -1);+ fill(path.begin(), path.end(), -1);+ ox = x_idx - 1;+ oy = y_idx - 1;+ return false;+ }+ return true;+ }+ + /**+ * record odd sequence in SES+ */+ void inline recordOddSequence (long long idx, long long length, sequence_const_iter it, const edit_t et) {+ while(idx < length){+ ses.addSequence(*it, idx, 0, et);+ ++it;+ ++idx;+ ++editDistance;+ }+ ses.addSequence(*it, idx, 0, et);+ ++editDistance;+ }+ + /**+ * join SES vectors+ */+ void inline joinSesVec (sesElemVec& s1, sesElemVec& s2) const {+ if (!s2.empty()) {+ for (sesElemVec_iter vit=s2.begin();vit!=s2.end();++vit) {+ s1.push_back(*vit);+ }+ } + }+ + /**+ * check if the sequences have been swapped+ */+ bool inline wasSwapped () const {+ return swapped;+ }++ };+}++#endif // DTL_DIFF_H
+ cbits/tracy/dtl/Diff3.hpp view
@@ -0,0 +1,245 @@+/**+ dtl -- Diff Template Library+ + In short, Diff Template Library is distributed under so called "BSD license",+ + Copyright (c) 2015 Tatsuhiko Kubo <cubicdaiya@gmail.com>+ All rights reserved.+ + 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 authors 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.+*/++/* If you use this library, you must include dtl.hpp only. */++#ifndef DTL_DIFF3_H+#define DTL_DIFF3_H++namespace dtl {+ + /**+ * diff3 class template+ * sequence must support random_access_iterator.+ */+ template <typename elem, typename sequence = vector< elem >, typename comparator = Compare< elem > >+ class Diff3+ {+ private:+ dtl_typedefs(elem, sequence)+ sequence A;+ sequence B;+ sequence C;+ sequence S;+ Diff< elem, sequence, comparator > diff_ba;+ Diff< elem, sequence, comparator > diff_bc;+ bool conflict;+ elem csepabegin;+ elem csepa;+ elem csepaend;+ public :+ Diff3 () {}+ Diff3 (const sequence& a, + const sequence& b, + const sequence& c) : A(a), B(b), C(c), + diff_ba(b, a), diff_bc(b, c), + conflict(false) {} + + ~Diff3 () {}+ + bool isConflict () const {+ return conflict;+ }+ + sequence getMergedSequence () const {+ return S;+ }+ + /**+ * merge changes B and C into A+ */+ bool merge () {+ if (diff_ba.getEditDistance() == 0) { // A == B+ if (diff_bc.getEditDistance() == 0) { // A == B == C+ S = B;+ return true;+ }+ S = C;+ return true;+ } else { // A != B+ if (diff_bc.getEditDistance() == 0) { // A != B == C+ S = A; + return true;+ } else { // A != B != C+ S = merge_();+ if (isConflict()) { // conflict occured+ return false;+ }+ }+ }+ return true;+ }+ + /**+ * compose differences+ */+ void compose () {+ diff_ba.compose();+ diff_bc.compose();+ }+ + private :+ /**+ * merge implementation+ */+ sequence merge_ () {+ elemVec seq;+ Ses< elem > ses_ba = diff_ba.getSes();+ Ses< elem > ses_bc = diff_bc.getSes();+ sesElemVec ses_ba_v = ses_ba.getSequence();+ sesElemVec ses_bc_v = ses_bc.getSequence();+ sesElemVec_iter ba_it = ses_ba_v.begin();+ sesElemVec_iter bc_it = ses_bc_v.begin();+ sesElemVec_iter ba_end = ses_ba_v.end();+ sesElemVec_iter bc_end = ses_bc_v.end();+ + while (!isEnd(ba_end, ba_it) || !isEnd(bc_end, bc_it)) {+ while (true) {+ if (!isEnd(ba_end, ba_it) && + !isEnd(bc_end, bc_it) &&+ ba_it->first == bc_it->first && + ba_it->second.type == SES_COMMON && + bc_it->second.type == SES_COMMON) {+ // do nothing+ } else {+ break;+ }+ if (!isEnd(ba_end, ba_it)) seq.push_back(ba_it->first);+ else if (!isEnd(bc_end, bc_it)) seq.push_back(bc_it->first);+ forwardUntilEnd(ba_end, ba_it);+ forwardUntilEnd(bc_end, bc_it);+ }+ if (isEnd(ba_end, ba_it) || isEnd(bc_end, bc_it)) break;+ if ( ba_it->second.type == SES_COMMON + && bc_it->second.type == SES_DELETE) {+ forwardUntilEnd(ba_end, ba_it);+ forwardUntilEnd(bc_end, bc_it);+ } else if (ba_it->second.type == SES_COMMON && + bc_it->second.type == SES_ADD) {+ seq.push_back(bc_it->first);+ forwardUntilEnd(bc_end, bc_it);+ } else if (ba_it->second.type == SES_DELETE && + bc_it->second.type == SES_COMMON) {+ forwardUntilEnd(ba_end, ba_it);+ forwardUntilEnd(bc_end, bc_it);+ } else if (ba_it->second.type == SES_DELETE && + bc_it->second.type == SES_DELETE) {+ if (ba_it->first == bc_it->first) {+ forwardUntilEnd(ba_end, ba_it);+ forwardUntilEnd(bc_end, bc_it);+ } else {+ // conflict+ conflict = true;+ return B;+ }+ } else if (ba_it->second.type == SES_DELETE && + bc_it->second.type == SES_ADD) {+ // conflict+ conflict = true;+ return B;+ } else if (ba_it->second.type == SES_ADD && + bc_it->second.type == SES_COMMON) {+ seq.push_back(ba_it->first);+ forwardUntilEnd(ba_end, ba_it);+ } else if (ba_it->second.type == SES_ADD && + bc_it->second.type == SES_DELETE) {+ // conflict+ conflict = true;+ return B;+ } else if (ba_it->second.type == SES_ADD && + bc_it->second.type == SES_ADD) {+ if (ba_it->first == bc_it->first) {+ seq.push_back(ba_it->first);+ forwardUntilEnd(ba_end, ba_it);+ forwardUntilEnd(bc_end, bc_it);+ } else {+ // conflict+ conflict = true;+ return B;+ }+ }+ }+ + if (isEnd(ba_end, ba_it)) {+ addDecentSequence(bc_end, bc_it, seq);+ } else if (isEnd(bc_end, bc_it)) {+ addDecentSequence(ba_end, ba_it, seq);+ }+ + sequence mergedSeq(seq.begin(), seq.end());+ return mergedSeq;+ }+ + /**+ * join elem vectors+ */+ void inline joinElemVec (elemVec& s1, elemVec& s2) const {+ if (!s2.empty()) {+ for (elemVec_iter vit=s2.begin();vit!=s2.end();++vit) {+ s1.push_back(*vit);+ }+ }+ }+ + /**+ * check if sequence is at end+ */+ template <typename T_iter>+ bool inline isEnd (const T_iter& end, const T_iter& it) const {+ return it == end ? true : false;+ }+ + /**+ * increment iterator until iterator is at end+ */+ template <typename T_iter>+ void inline forwardUntilEnd (const T_iter& end, T_iter& it) const {+ if (!isEnd(end, it)) ++it;+ }+ + /**+ * add elements whose SES's type is ADD+ */+ void inline addDecentSequence (const sesElemVec_iter& end, sesElemVec_iter& it, elemVec& seq) const {+ while (!isEnd(end, it)) {+ if (it->second.type == SES_ADD) seq.push_back(it->first);+ ++it;+ } + }+ + };+}++#endif // DTL_DIFF3_H
+ cbits/tracy/dtl/Lcs.hpp view
@@ -0,0 +1,55 @@+/**+ dtl -- Diff Template Library+ + In short, Diff Template Library is distributed under so called "BSD license",+ + Copyright (c) 2015 Tatsuhiko Kubo <cubicdaiya@gmail.com>+ All rights reserved.+ + 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 authors 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.+*/++/* If you use this library, you must include dtl.hpp only. */++#ifndef DTL_LCS_H+#define DTL_LCS_H++namespace dtl {+ + /**+ * Longest Common Subsequence template class+ */+ template <typename elem>+ class Lcs : public Sequence< elem >+ {+ public :+ Lcs () {}+ ~Lcs () {}+ };+}++#endif // DTL_LCS_H
+ cbits/tracy/dtl/Sequence.hpp view
@@ -0,0 +1,65 @@+/**+ dtl -- Diff Template Library+ + In short, Diff Template Library is distributed under so called "BSD license",+ + Copyright (c) 2015 Tatsuhiko Kubo <cubicdaiya@gmail.com>+ All rights reserved.+ + 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 authors 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.+*/++/* If you use this library, you must include dtl.hpp only. */++#ifndef DTL_SEQUENCE_H+#define DTL_SEQUENCE_H++namespace dtl {+ + /** + * sequence class template+ */+ template <typename elem>+ class Sequence+ {+ public :+ typedef vector< elem > elemVec;+ Sequence () {}+ virtual ~Sequence () {}+ + elemVec getSequence () const {+ return sequence;+ }+ void addSequence (elem e) {+ sequence.push_back(e);+ }+ protected :+ elemVec sequence;+ };+}++#endif // DTL_SEQUENCE_H
+ cbits/tracy/dtl/Ses.hpp view
@@ -0,0 +1,132 @@+/**+ dtl -- Diff Template Library+ + In short, Diff Template Library is distributed under so called "BSD license",+ + Copyright (c) 2015 Tatsuhiko Kubo <cubicdaiya@gmail.com>+ All rights reserved.+ + 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 authors 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.+*/++/* If you use this library, you must include dtl.hpp only. */++#ifndef DTL_SES_H+#define DTL_SES_H++namespace dtl {+ + /**+ * Shortest Edit Script template class+ */+ template <typename elem>+ class Ses : public Sequence< elem >+ {+ private :+ typedef pair< elem, elemInfo > sesElem;+ typedef vector< sesElem > sesElemVec;+ public :+ + Ses () : onlyAdd(true), onlyDelete(true), onlyCopy(true), deletesFirst(false) {+ nextDeleteIdx = 0;+ }+ Ses (bool moveDel) : onlyAdd(true), onlyDelete(true), onlyCopy(true), deletesFirst(moveDel) {+ nextDeleteIdx = 0;+ }+ ~Ses () {}+ + bool isOnlyAdd () const {+ return onlyAdd;+ }+ + bool isOnlyDelete () const {+ return onlyDelete;+ }+ + bool isOnlyCopy () const {+ return onlyCopy;+ }+ + bool isOnlyOneOperation () const {+ return isOnlyAdd() || isOnlyDelete() || isOnlyCopy();+ }+ + bool isChange () const {+ return !onlyCopy;+ }+ + using Sequence< elem >::addSequence;+ void addSequence (elem e, long long beforeIdx, long long afterIdx, const edit_t type) {+ elemInfo info;+ info.beforeIdx = beforeIdx;+ info.afterIdx = afterIdx;+ info.type = type;+ sesElem pe(e, info);+ if (!deletesFirst) {+ sequence.push_back(pe);+ }+ switch (type) {+ case SES_DELETE:+ onlyCopy = false;+ onlyAdd = false;+ if (deletesFirst) {+ sequence.insert(sequence.begin() + nextDeleteIdx, pe);+ nextDeleteIdx++;+ }+ break;+ case SES_COMMON:+ onlyAdd = false;+ onlyDelete = false;+ if (deletesFirst) {+ sequence.push_back(pe);+ nextDeleteIdx = sequence.size();+ }+ break;+ case SES_ADD:+ onlyDelete = false;+ onlyCopy = false;+ if (deletesFirst) {+ sequence.push_back(pe);+ }+ break;+ }+ }+ + sesElemVec getSequence () const {+ return sequence;+ }+ private :+ sesElemVec sequence;+ bool onlyAdd;+ bool onlyDelete;+ bool onlyCopy;+ bool deletesFirst;+ size_t nextDeleteIdx;+ };+}++#endif // DTL_SES_H
+ cbits/tracy/dtl/dtl.hpp view
@@ -0,0 +1,47 @@+/**+ dtl -- Diff Template Library+ + In short, Diff Template Library is distributed under so called "BSD license",+ + Copyright (c) 2015 Tatsuhiko Kubo <cubicdaiya@gmail.com>+ All rights reserved.+ + 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 authors 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.+*/++#ifndef DTL_H+#define DTL_H++#include "variables.hpp"+#include "functors.hpp"+#include "Sequence.hpp"+#include "Lcs.hpp"+#include "Ses.hpp"+#include "Diff.hpp"+#include "Diff3.hpp"++#endif // DTL_H
+ cbits/tracy/dtl/functors.hpp view
@@ -0,0 +1,151 @@+/**+ dtl -- Diff Template Library+ + In short, Diff Template Library is distributed under so called "BSD license",+ + Copyright (c) 2015 Tatsuhiko Kubo <cubicdaiya@gmail.com>+ All rights reserved.+ + 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 authors 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.+*/++/* If you use this library, you must include dtl.hpp only. */++#ifndef DTL_FUNCTORS_H+#define DTL_FUNCTORS_H++namespace dtl {+ + /**+ * printer class template+ */+ template <typename sesElem, typename stream = ostream >+ class Printer+ {+ public :+ Printer () : out_(cout) {}+ Printer (stream& out) : out_(out) {}+ virtual ~Printer () {}+ virtual void operator() (const sesElem& se) const = 0;+ protected :+ stream& out_;+ };+ + /**+ * common element printer class template+ */+ template <typename sesElem, typename stream = ostream >+ class CommonPrinter : public Printer < sesElem, stream >+ {+ public :+ CommonPrinter () : Printer < sesElem, stream > () {}+ CommonPrinter (stream& out) : Printer < sesElem, stream > (out) {}+ ~CommonPrinter () {}+ void operator() (const sesElem& se) const {+ this->out_ << SES_MARK_COMMON << se.first << endl; + }+ };+ + /**+ * ses element printer class template+ */+ template <typename sesElem, typename stream = ostream >+ class ChangePrinter : public Printer < sesElem, stream >+ {+ public :+ ChangePrinter () : Printer < sesElem, stream > () {}+ ChangePrinter (stream& out) : Printer < sesElem, stream > (out) {}+ ~ChangePrinter () {}+ void operator() (const sesElem& se) const {+ switch (se.second.type) {+ case SES_ADD:+ this->out_ << SES_MARK_ADD << se.first << endl;+ break;+ case SES_DELETE:+ this->out_ << SES_MARK_DELETE << se.first << endl;+ break;+ case SES_COMMON:+ this->out_ << SES_MARK_COMMON << se.first << endl;+ break;+ }+ }+ };+ + /**+ * unified format element printer class template+ */+ template <typename sesElem, typename stream = ostream >+ class UniHunkPrinter+ {+ public :+ UniHunkPrinter () : out_(cout) {}+ UniHunkPrinter (stream& out) : out_(out) {}+ ~UniHunkPrinter () {}+ void operator() (const uniHunk< sesElem >& hunk) const {+ out_ << "@@"+ << " -" << hunk.a << "," << hunk.b+ << " +" << hunk.c << "," << hunk.d+ << " @@" << endl;+ + for_each(hunk.common[0].begin(), hunk.common[0].end(), CommonPrinter< sesElem, stream >(out_));+ for_each(hunk.change.begin(), hunk.change.end(), ChangePrinter< sesElem, stream >(out_));+ for_each(hunk.common[1].begin(), hunk.common[1].end(), CommonPrinter< sesElem, stream >(out_));+ }+ private :+ stream& out_;+ };++ /**+ * storage class template+ */+ template <typename sesElem, typename storedData >+ class Storage+ {+ public:+ Storage(storedData& sd) : storedData_(sd) {}+ virtual ~Storage() {}+ virtual void operator() (const sesElem& se) const = 0;+ protected:+ storedData& storedData_;+ };+ + /**+ * compare class template+ */+ template <typename elem>+ class Compare+ {+ public :+ Compare () {}+ virtual ~Compare () {}+ virtual inline bool impl (const elem& e1, const elem& e2) const {+ return e1 == e2;+ }+ };+}++#endif // DTL_FUNCTORS_H
+ cbits/tracy/dtl/variables.hpp view
@@ -0,0 +1,142 @@+/**+ dtl -- Diff Template Library+ + In short, Diff Template Library is distributed under so called "BSD license",+ + Copyright (c) 2015 Tatsuhiko Kubo <cubicdaiya@gmail.com>+ All rights reserved.+ + 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 authors 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.+*/++/* If you use this library, you must include dtl.hpp only. */++#ifndef DTL_VARIABLES_H+#define DTL_VARIABLES_H++#include <vector>+#include <list>+#include <string>+#include <algorithm>+#include <iostream>++namespace dtl {+ + using std::vector;+ using std::string;+ using std::pair;+ using std::ostream;+ using std::list;+ using std::for_each;+ using std::distance;+ using std::fill;+ using std::cout;+ using std::endl;+ using std::rotate;+ using std::swap;+ using std::max;++ /**+ * version string+ */+ const string version = "1.20";++ /**+ * type of edit for SES+ */+ typedef int edit_t;+ const edit_t SES_DELETE = -1;+ const edit_t SES_COMMON = 0;+ const edit_t SES_ADD = 1;+ + /**+ * mark of SES+ */+#define SES_MARK_DELETE "-"+#define SES_MARK_COMMON " "+#define SES_MARK_ADD "+"++ /**+ * info for Unified Format+ */+ typedef struct eleminfo {+ long long beforeIdx; // index of prev sequence+ long long afterIdx; // index of after sequence+ edit_t type; // type of edit(Add, Delete, Common)+ bool operator==(const eleminfo& other) const{+ return (this->beforeIdx == other.beforeIdx && this->afterIdx == other.afterIdx && this->type == other.type);+ }+ } elemInfo;+ + const long long DTL_SEPARATE_SIZE = 3;+ const long long DTL_CONTEXT_SIZE = 3;+ + /**+ * cordinate for registering route+ */+ typedef struct Point {+ long long x; // x cordinate+ long long y; // y cordinate+ long long k; // vertex+ } P;+ + /**+ * limit of cordinate size+ */+ const unsigned long long MAX_CORDINATES_SIZE = 2000000;+ + typedef vector< long long > editPath;+ typedef vector< P > editPathCordinates;+ + /**+ * Structure of Unified Format Hunk+ */+ template <typename sesElem>+ struct uniHunk {+ long long a, b, c, d; // @@ -a,b +c,d @@+ vector< sesElem > common[2]; // anteroposterior commons on changes+ vector< sesElem > change; // changes+ long long inc_dec_count; // count of increace and decrease+ };++#define dtl_typedefs(elem, sequence) \+ typedef pair< elem, elemInfo > sesElem; \+ typedef vector< sesElem > sesElemVec; \+ typedef vector< uniHunk< sesElem > > uniHunkVec; \+ typedef list< elem > elemList; \+ typedef vector< elem > elemVec; \+ typedef typename uniHunkVec::iterator uniHunkVec_iter; \+ typedef typename sesElemVec::iterator sesElemVec_iter; \+ typedef typename elemList::iterator elemList_iter; \+ typedef typename sequence::iterator sequence_iter; \+ typedef typename sequence::const_iterator sequence_const_iter; \+ typedef typename elemVec::iterator elemVec_iter;+++} ++#endif // DTL_VARIABLES_H
+ cbits/tracy/getopt/getopt.c view
@@ -0,0 +1,239 @@+/*******************************************************************************+ * Copyright (c) 2012-2023, Kim Grasman <kim.grasman@gmail.com>+ * All rights reserved.+ *+ * 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 Kim Grasman nor the+ * names of 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 KIM GRASMAN 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.+ *+ ******************************************************************************/++#include "getopt.h"++#include <stddef.h>+#include <string.h>++char* optarg;+int optopt;+/* The variable optind [...] shall be initialized to 1 by the system. */+int optind = 1;+int opterr;++static char* optcursor = NULL;++/* Implemented based on [1] and [2] for optional arguments.+ optopt is handled FreeBSD-style, per [3].+ Other GNU and FreeBSD extensions are purely accidental.++[1] http://pubs.opengroup.org/onlinepubs/000095399/functions/getopt.html+[2] http://www.kernel.org/doc/man-pages/online/pages/man3/getopt.3.html+[3] http://www.freebsd.org/cgi/man.cgi?query=getopt&sektion=3&manpath=FreeBSD+9.0-RELEASE+*/+int getopt(int argc, char* const argv[], const char* optstring) {+ int optchar = -1;+ const char* optdecl = NULL;++ optarg = NULL;+ opterr = 0;+ optopt = 0;++ /* Unspecified, but we need it to avoid overrunning the argv bounds. */+ if (optind >= argc)+ goto no_more_optchars;++ /* If, when getopt() is called argv[optind] is a null pointer, getopt()+ shall return -1 without changing optind. */+ if (argv[optind] == NULL)+ goto no_more_optchars;++ /* If, when getopt() is called *argv[optind] is not the character '-',+ getopt() shall return -1 without changing optind. */+ if (*argv[optind] != '-')+ goto no_more_optchars;++ /* If, when getopt() is called argv[optind] points to the string "-",+ getopt() shall return -1 without changing optind. */+ if (strcmp(argv[optind], "-") == 0)+ goto no_more_optchars;++ /* If, when getopt() is called argv[optind] points to the string "--",+ getopt() shall return -1 after incrementing optind. */+ if (strcmp(argv[optind], "--") == 0) {+ ++optind;+ goto no_more_optchars;+ }++ if (optcursor == NULL || *optcursor == '\0')+ optcursor = argv[optind] + 1;++ optchar = *optcursor;++ /* FreeBSD: The variable optopt saves the last known option character+ returned by getopt(). */+ optopt = optchar;++ /* The getopt() function shall return the next option character (if one is+ found) from argv that matches a character in optstring, if there is+ one that matches. */+ optdecl = strchr(optstring, optchar);+ if (optdecl) {+ /* [I]f a character is followed by a colon, the option takes an+ argument. */+ if (optdecl[1] == ':') {+ optarg = ++optcursor;+ if (*optarg == '\0') {+ /* GNU extension: Two colons mean an option takes an+ optional arg; if there is text in the current argv-element+ (i.e., in the same word as the option name itself, for example,+ "-oarg"), then it is returned in optarg, otherwise optarg is set+ to zero. */+ if (optdecl[2] != ':') {+ /* If the option was the last character in the string pointed to by+ an element of argv, then optarg shall contain the next element+ of argv, and optind shall be incremented by 2. If the resulting+ value of optind is greater than argc, this indicates a missing+ option-argument, and getopt() shall return an error indication.++ Otherwise, optarg shall point to the string following the+ option character in that element of argv, and optind shall be+ incremented by 1.+ */+ if (++optind < argc) {+ optarg = argv[optind];+ } else {+ /* If it detects a missing option-argument, it shall return the+ colon character ( ':' ) if the first character of optstring+ was a colon, or a question-mark character ( '?' ) otherwise.+ */+ optarg = NULL;+ optchar = (optstring[0] == ':') ? ':' : '?';+ }+ } else {+ optarg = NULL;+ }+ }++ optcursor = NULL;+ }+ } else {+ /* If getopt() encounters an option character that is not contained in+ optstring, it shall return the question-mark ( '?' ) character. */+ optchar = '?';+ }++ if (optcursor == NULL || *++optcursor == '\0')+ ++optind;++ return optchar;++no_more_optchars:+ optcursor = NULL;+ return -1;+}++/* Implementation based on [1].++[1] http://www.kernel.org/doc/man-pages/online/pages/man3/getopt.3.html+*/+int getopt_long(int argc, char* const argv[], const char* optstring,+ const struct option* longopts, int* longindex) {+ const struct option* o = longopts;+ const struct option* match = NULL;+ int num_matches = 0;+ size_t argument_name_length = 0;+ size_t option_length = 0;+ const char* current_argument = NULL;+ int retval = -1;++ optarg = NULL;+ optopt = 0;++ if (optind >= argc)+ return -1;++ if (strlen(argv[optind]) < 3 || strncmp(argv[optind], "--", 2) != 0)+ return getopt(argc, argv, optstring);++ /* It's an option; starts with -- and is longer than two chars. */+ current_argument = argv[optind] + 2;+ argument_name_length = strcspn(current_argument, "=");+ for (; o->name; ++o) {+ /* Check for exact match first. */+ option_length = strlen(o->name);+ if (option_length == argument_name_length &&+ strncmp(o->name, current_argument, option_length) == 0) {+ match = o;+ num_matches = 1;+ break;+ }++ /* If not exact, count the number of abbreviated matches. */+ if (strncmp(o->name, current_argument, argument_name_length) == 0) {+ match = o;+ ++num_matches;+ }+ }++ if (num_matches == 1) {+ /* If longindex is not NULL, it points to a variable which is set to the+ index of the long option relative to longopts. */+ if (longindex)+ *longindex = (match - longopts);++ /* If flag is NULL, then getopt_long() shall return val.+ Otherwise, getopt_long() returns 0, and flag shall point to a variable+ which shall be set to val if the option is found, but left unchanged if+ the option is not found. */+ if (match->flag)+ *(match->flag) = match->val;++ retval = match->flag ? 0 : match->val;++ if (match->has_arg != no_argument) {+ optarg = strchr(argv[optind], '=');+ if (optarg != NULL)+ ++optarg;++ if (match->has_arg == required_argument) {+ /* Only scan the next argv for required arguments. Behavior is not+ specified, but has been observed with Ubuntu and Mac OSX. */+ if (optarg == NULL && ++optind < argc) {+ optarg = argv[optind];+ }++ if (optarg == NULL)+ retval = ':';+ }+ } else if (strchr(argv[optind], '=')) {+ /* An argument was provided to a non-argument option.+ I haven't seen this specified explicitly, but both GNU and BSD-based+ implementations show this behavior.+ */+ retval = '?';+ }+ } else {+ /* Unknown option or ambiguous match. */+ retval = '?';+ }++ ++optind;+ return retval;+}
+ cbits/tracy/getopt/getopt.h view
@@ -0,0 +1,59 @@+/*******************************************************************************+ * Copyright (c) 2012-2023, Kim Grasman <kim.grasman@gmail.com>+ * All rights reserved.+ *+ * 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 Kim Grasman nor the+ * names of 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 KIM GRASMAN 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.+ *+ ******************************************************************************/++#ifndef INCLUDED_GETOPT_PORT_H+#define INCLUDED_GETOPT_PORT_H++#if defined(__cplusplus)+extern "C" {+#endif++#define no_argument 1+#define required_argument 2+#define optional_argument 3++extern char* optarg;+extern int optind, opterr, optopt;++struct option {+ const char* name;+ int has_arg;+ int* flag;+ int val;+};++int getopt(int argc, char* const argv[], const char* optstring);++int getopt_long(int argc, char* const argv[],+ const char* optstring, const struct option* longopts, int* longindex);++#if defined(__cplusplus)+}+#endif++#endif // INCLUDED_GETOPT_PORT_H
+ cbits/tracy/profiler/CMakeLists.txt view
@@ -0,0 +1,233 @@+cmake_minimum_required(VERSION 3.21)++option(NO_FILESELECTOR "Disable the file selector" OFF)+option(GTK_FILESELECTOR "Use the GTK file selector on Linux instead of the xdg-portal one" OFF)+option(LEGACY "Instead of Wayland, use the legacy X11 backend on Linux" OFF)+option(NO_ISA_EXTENSIONS "Disable ISA extensions (don't pass -march=native or -mcpu=native to the compiler)" OFF)+option(NO_STATISTICS "Disable calculation of statistics" OFF)+option(SELF_PROFILE "Enable self-profiling" OFF)++include(${CMAKE_CURRENT_LIST_DIR}/../cmake/version.cmake)++set(CMAKE_CXX_STANDARD 20)++project(+ tracy-profiler+ LANGUAGES C CXX+ VERSION ${TRACY_VERSION_STRING}+)++if(SELF_PROFILE)+ add_definitions(-DTRACY_ENABLE)+ add_compile_options(-g -O3 -fno-omit-frame-pointer)+endif()++include(${CMAKE_CURRENT_LIST_DIR}/../cmake/config.cmake)+include(${CMAKE_CURRENT_LIST_DIR}/../cmake/vendor.cmake)+include(${CMAKE_CURRENT_LIST_DIR}/../cmake/server.cmake)++set(SERVER_FILES+ TracyAchievementData.cpp+ TracyAchievements.cpp+ TracyBadVersion.cpp+ TracyColor.cpp+ TracyEventDebug.cpp+ TracyFileselector.cpp+ TracyFilesystem.cpp+ TracyImGui.cpp+ TracyMicroArchitecture.cpp+ TracyMouse.cpp+ TracyProtoHistory.cpp+ TracySourceContents.cpp+ TracySourceTokenizer.cpp+ TracySourceView.cpp+ TracyStorage.cpp+ TracyTexture.cpp+ TracyTimelineController.cpp+ TracyTimelineItem.cpp+ TracyTimelineItemCpuData.cpp+ TracyTimelineItemGpu.cpp+ TracyTimelineItemPlot.cpp+ TracyTimelineItemThread.cpp+ TracyUserData.cpp+ TracyUtility.cpp+ TracyView.cpp+ TracyView_Annotations.cpp+ TracyView_Callstack.cpp+ TracyView_Compare.cpp+ TracyView_ConnectionState.cpp+ TracyView_ContextSwitch.cpp+ TracyView_CpuData.cpp+ TracyView_FindZone.cpp+ TracyView_FlameGraph.cpp+ TracyView_FrameOverview.cpp+ TracyView_FrameTimeline.cpp+ TracyView_FrameTree.cpp+ TracyView_GpuTimeline.cpp+ TracyView_Locks.cpp+ TracyView_Memory.cpp+ TracyView_Messages.cpp+ TracyView_Navigation.cpp+ TracyView_NotificationArea.cpp+ TracyView_Options.cpp+ TracyView_Playback.cpp+ TracyView_Plots.cpp+ TracyView_Ranges.cpp+ TracyView_Samples.cpp+ TracyView_Statistics.cpp+ TracyView_Timeline.cpp+ TracyView_TraceInfo.cpp+ TracyView_Utility.cpp+ TracyView_ZoneInfo.cpp+ TracyView_ZoneTimeline.cpp+ TracyWeb.cpp+)++list(TRANSFORM SERVER_FILES PREPEND "src/profiler/")++set(PROFILER_FILES+ src/ConnectionHistory.cpp+ src/Filters.cpp+ src/Fonts.cpp+ src/HttpRequest.cpp+ src/ImGuiContext.cpp+ src/ini.c+ src/IsElevated.cpp+ src/main.cpp+ src/ResolvService.cpp+ src/RunQueue.cpp+ src/WindowPosition.cpp+ src/winmain.cpp+ src/winmainArchDiscovery.cpp+)++set(INCLUDES "${CMAKE_CURRENT_BINARY_DIR}")+set(LIBS "")++if(USE_WAYLAND)+ pkg_check_modules(WAYLAND REQUIRED egl wayland-egl wayland-cursor xkbcommon)+ set(INCLUDES "${INCLUDES};${WAYLAND_INCLUDE_DIRS}")+ set(LIBS "${LIBS};${WAYLAND_LIBRARIES}")+ set(PROFILER_FILES ${PROFILER_FILES}+ src/BackendWayland.cpp+ )++ include(${CMAKE_CURRENT_LIST_DIR}/../cmake/FindWaylandScanner.cmake)++ CPMAddPackage(+ NAME wayland-protocols+ GIT_REPOSITORY https://gitlab.freedesktop.org/wayland/wayland-protocols.git+ GIT_TAG 1.37+ DOWNLOAD_ONLY YES+ )++ ecm_add_wayland_client_protocol(PROFILER_FILES+ PROTOCOL ${wayland-protocols_SOURCE_DIR}/stable/xdg-shell/xdg-shell.xml+ BASENAME xdg-shell+ )+ ecm_add_wayland_client_protocol(PROFILER_FILES+ PROTOCOL ${wayland-protocols_SOURCE_DIR}/staging/xdg-activation/xdg-activation-v1.xml+ BASENAME xdg-activation+ )+ ecm_add_wayland_client_protocol(PROFILER_FILES+ PROTOCOL ${wayland-protocols_SOURCE_DIR}/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml+ BASENAME xdg-decoration+ )+ ecm_add_wayland_client_protocol(PROFILER_FILES+ PROTOCOL ${wayland-protocols_SOURCE_DIR}/staging/fractional-scale/fractional-scale-v1.xml+ BASENAME fractional-scale+ )+ ecm_add_wayland_client_protocol(PROFILER_FILES+ PROTOCOL ${wayland-protocols_SOURCE_DIR}/stable/viewporter/viewporter.xml+ BASENAME viewporter+ )+ ecm_add_wayland_client_protocol(PROFILER_FILES+ PROTOCOL ${wayland-protocols_SOURCE_DIR}/staging/cursor-shape/cursor-shape-v1.xml+ BASENAME cursor-shape+ )+ ecm_add_wayland_client_protocol(PROFILER_FILES+ PROTOCOL ${wayland-protocols_SOURCE_DIR}/unstable/tablet/tablet-unstable-v2.xml+ BASENAME tablet+ )+ ecm_add_wayland_client_protocol(PROFILER_FILES+ PROTOCOL ${wayland-protocols_SOURCE_DIR}/staging/xdg-toplevel-icon/xdg-toplevel-icon-v1.xml+ BASENAME xdg-toplevel-icon+ )+elseif(EMSCRIPTEN)+ set(PROFILER_FILES ${PROFILER_FILES}+ src/BackendEmscripten.cpp+ )+else()+ set(PROFILER_FILES ${PROFILER_FILES}+ src/BackendGlfw.cpp+ ${ImGui_SOURCE_DIR}/backends/imgui_impl_glfw.cpp+ )+endif()++include_directories(${INCLUDES})+link_libraries(${LIBS})++if(SELF_PROFILE)+ set(PROFILER_FILES ${PROFILER_FILES}+ ../public/TracyClient.cpp+ )+endif()++if(WIN32)+ set(PROFILER_FILES ${PROFILER_FILES}+ win32/Tracy.manifest+ win32/Tracy.rc+ )+ add_executable(${PROJECT_NAME} WIN32 ${PROFILER_FILES} ${COMMON_FILES} ${SERVER_FILES})+ set_property(DIRECTORY ${CMAKE_CURRENT_LIST_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME})+else()+ add_executable(${PROJECT_NAME} ${PROFILER_FILES} ${COMMON_FILES} ${SERVER_FILES})+endif()++find_package(Threads REQUIRED)+target_link_libraries(${PROJECT_NAME} PRIVATE TracyServer TracyImGui Threads::Threads)++if(NOT DEFINED GIT_REV)+ set(GIT_REV "HEAD")+endif()++find_package(Git)+if(Git_FOUND)+ add_custom_target(git-ref+ COMMAND ${CMAKE_COMMAND} -E echo "#pragma once" > GitRef.hpp.tmp+ COMMAND ${GIT_EXECUTABLE} -C ${CMAKE_CURRENT_SOURCE_DIR} log -1 "--format=namespace tracy { static inline const char* GitRef = %x22%h%x22; }" ${GIT_REV} >> GitRef.hpp.tmp || echo "namespace tracy { static inline const char* GitRef = \"unknown\"; }" >> GitRef.hpp.tmp+ COMMAND ${CMAKE_COMMAND} -E copy_if_different GitRef.hpp.tmp GitRef.hpp+ BYPRODUCTS GitRef.hpp GitRef.hpp.tmp+ VERBATIM+ )+ add_dependencies(${PROJECT_NAME} git-ref)+else()+ message(WARNING "git not found, using 'unknown' as git ref.")+ add_custom_command(+ OUTPUT GitRef.hpp+ COMMAND ${CMAKE_COMMAND} -E echo "#pragma once" > GitRef.hpp+ COMMAND ${CMAKE_COMMAND} -E echo "namespace tracy { static inline const char* GitRef = \"unknown\"; }" >> GitRef.hpp+ VERBATIM+ )+ target_sources(${PROJECT_NAME} PUBLIC GitRef.hpp)+endif()++if(NOT EMSCRIPTEN)+ if(NOT NO_FILESELECTOR)+ target_link_libraries(${PROJECT_NAME} PRIVATE nfd::nfd)+ endif()+ if(NOT USE_WAYLAND)+ target_link_libraries(${PROJECT_NAME} PRIVATE TracyGlfw3)+ endif()+endif()++if(EMSCRIPTEN)+ target_link_options(${PROJECT_NAME} PRIVATE -pthread -sASSERTIONS=0 -sINITIAL_MEMORY=384mb -sALLOW_MEMORY_GROWTH=1 -sMAXIMUM_MEMORY=4gb -sSTACK_SIZE=1048576 -sWASM_BIGINT=1 -sPTHREAD_POOL_SIZE=8 -sEXPORTED_FUNCTIONS=_main,_nativeOpenFile -sEXPORTED_RUNTIME_METHODS=ccall -sENVIRONMENT=web,worker --preload-file embed.tracy)++ file(DOWNLOAD https://share.nereid.pl/i/embed.tracy ${CMAKE_CURRENT_BINARY_DIR}/embed.tracy EXPECTED_MD5 ca0fa4f01e7b8ca5581daa16b16c768d)+ file(COPY ${CMAKE_CURRENT_LIST_DIR}/wasm/index.html DESTINATION ${CMAKE_CURRENT_BINARY_DIR})+ file(COPY ${CMAKE_CURRENT_LIST_DIR}/wasm/httpd.py DESTINATION ${CMAKE_CURRENT_BINARY_DIR})+ file(COPY_FILE ${CMAKE_CURRENT_LIST_DIR}/../icon/icon.svg ${CMAKE_CURRENT_BINARY_DIR}/favicon.svg)+endif()++install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
+ cbits/tracy/profiler/src/Backend.hpp view
@@ -0,0 +1,34 @@+#ifndef __BACKEND_HPP__+#define __BACKEND_HPP__++#include <functional>+#include <stdint.h>++#include "WindowPosition.hpp"++class RunQueue;++class Backend+{+public:+ Backend( const char* title, const std::function<void()>& redraw, const std::function<void(float)>& scaleChanged, const std::function<int(void)>& isBusy, RunQueue* mainThreadTasks );+ ~Backend();++ void Show();+ void Run();+ void Attention();++ void NewFrame( int& w, int& h );+ void EndFrame();++ void SetIcon( uint8_t* data, int w, int h );+ void SetTitle( const char* title );++ float GetDpiScale();++private:+ WindowPosition m_winPos;+ int m_w, m_h;+};++#endif
+ cbits/tracy/profiler/src/BackendEmscripten.cpp view
@@ -0,0 +1,341 @@+#include <stdio.h>+#include <stdlib.h>+#include <string.h>+#include <EGL/egl.h>+#include <EGL/eglext.h>+#include <GLES2/gl2.h>+#include <emscripten/html5.h>+#include <backends/imgui_impl_opengl3.h>++#include "Backend.hpp"+#include "RunQueue.hpp"+#include "profiler/TracyImGui.hpp"++static std::function<void()> s_redraw;+static std::function<void(float)> s_scaleChanged;+static std::function<int(void)> s_isBusy;+static RunQueue* s_mainThreadTasks;++static EGLDisplay s_eglDpy;+static EGLContext s_eglCtx;+static EGLSurface s_eglSurf;++static float s_prevScale = -1;+static int s_width, s_height;+static uint64_t s_time;+static const char* s_prevCursor = nullptr;++static ImGuiKey TranslateKeyCode( const char* code )+{+ if( strcmp( code, "Backquote" ) == 0 ) return ImGuiKey_GraveAccent;+ if( strcmp( code, "Backslash" ) == 0 ) return ImGuiKey_Backslash;+ if( strcmp( code, "BracketLeft" ) == 0 ) return ImGuiKey_LeftBracket;+ if( strcmp( code, "BracketRight" ) == 0 ) return ImGuiKey_RightBracket;+ if( strcmp( code, "Comma" ) == 0 ) return ImGuiKey_Comma;+ if( strcmp( code, "Digit0" ) == 0 ) return ImGuiKey_0;+ if( strcmp( code, "Digit1" ) == 0 ) return ImGuiKey_1;+ if( strcmp( code, "Digit2" ) == 0 ) return ImGuiKey_2;+ if( strcmp( code, "Digit3" ) == 0 ) return ImGuiKey_3;+ if( strcmp( code, "Digit4" ) == 0 ) return ImGuiKey_4;+ if( strcmp( code, "Digit5" ) == 0 ) return ImGuiKey_5;+ if( strcmp( code, "Digit6" ) == 0 ) return ImGuiKey_6;+ if( strcmp( code, "Digit7" ) == 0 ) return ImGuiKey_7;+ if( strcmp( code, "Digit8" ) == 0 ) return ImGuiKey_8;+ if( strcmp( code, "Digit9" ) == 0 ) return ImGuiKey_9;+ if( strcmp( code, "Equal" ) == 0 ) return ImGuiKey_Equal;+ if( strcmp( code, "IntlBackslash" ) == 0 ) return ImGuiKey_Backslash;+ if( strcmp( code, "IntlRo" ) == 0 ) return ImGuiKey_Backslash;+ if( strcmp( code, "IntlYen" ) == 0 ) return ImGuiKey_Backslash;+ if( strcmp( code, "KeyA" ) == 0 ) return ImGuiKey_A;+ if( strcmp( code, "KeyB" ) == 0 ) return ImGuiKey_B;+ if( strcmp( code, "KeyC" ) == 0 ) return ImGuiKey_C;+ if( strcmp( code, "KeyD" ) == 0 ) return ImGuiKey_D;+ if( strcmp( code, "KeyE" ) == 0 ) return ImGuiKey_E;+ if( strcmp( code, "KeyF" ) == 0 ) return ImGuiKey_F;+ if( strcmp( code, "KeyG" ) == 0 ) return ImGuiKey_G;+ if( strcmp( code, "KeyH" ) == 0 ) return ImGuiKey_H;+ if( strcmp( code, "KeyI" ) == 0 ) return ImGuiKey_I;+ if( strcmp( code, "KeyJ" ) == 0 ) return ImGuiKey_J;+ if( strcmp( code, "KeyK" ) == 0 ) return ImGuiKey_K;+ if( strcmp( code, "KeyL" ) == 0 ) return ImGuiKey_L;+ if( strcmp( code, "KeyM" ) == 0 ) return ImGuiKey_M;+ if( strcmp( code, "KeyN" ) == 0 ) return ImGuiKey_N;+ if( strcmp( code, "KeyO" ) == 0 ) return ImGuiKey_O;+ if( strcmp( code, "KeyP" ) == 0 ) return ImGuiKey_P;+ if( strcmp( code, "KeyQ" ) == 0 ) return ImGuiKey_Q;+ if( strcmp( code, "KeyR" ) == 0 ) return ImGuiKey_R;+ if( strcmp( code, "KeyS" ) == 0 ) return ImGuiKey_S;+ if( strcmp( code, "KeyT" ) == 0 ) return ImGuiKey_T;+ if( strcmp( code, "KeyU" ) == 0 ) return ImGuiKey_U;+ if( strcmp( code, "KeyV" ) == 0 ) return ImGuiKey_V;+ if( strcmp( code, "KeyW" ) == 0 ) return ImGuiKey_W;+ if( strcmp( code, "KeyX" ) == 0 ) return ImGuiKey_X;+ if( strcmp( code, "KeyY" ) == 0 ) return ImGuiKey_Y;+ if( strcmp( code, "KeyZ" ) == 0 ) return ImGuiKey_Z;+ if( strcmp( code, "Minus" ) == 0 ) return ImGuiKey_Minus;+ if( strcmp( code, "Period" ) == 0 ) return ImGuiKey_Period;+ if( strcmp( code, "Quote" ) == 0 ) return ImGuiKey_Apostrophe;+ if( strcmp( code, "Semicolon" ) == 0 ) return ImGuiKey_Semicolon;+ if( strcmp( code, "Slash" ) == 0 ) return ImGuiKey_Slash;+ if( strcmp( code, "AltLeft" ) == 0 ) return ImGuiKey_LeftAlt;+ if( strcmp( code, "AltRight" ) == 0 ) return ImGuiKey_RightAlt;+ if( strcmp( code, "Backspace" ) == 0 ) return ImGuiKey_Backspace;+ if( strcmp( code, "CapsLock" ) == 0 ) return ImGuiKey_CapsLock;+ if( strcmp( code, "ContextMenu" ) == 0 ) return ImGuiKey_Menu;+ if( strcmp( code, "ControlLeft" ) == 0 ) return ImGuiKey_LeftCtrl;+ if( strcmp( code, "ControlRight" ) == 0 ) return ImGuiKey_RightCtrl;+ if( strcmp( code, "Enter" ) == 0 ) return ImGuiKey_Enter;+ if( strcmp( code, "MetaLeft" ) == 0 ) return ImGuiKey_LeftSuper;+ if( strcmp( code, "MetaRight" ) == 0 ) return ImGuiKey_RightSuper;+ if( strcmp( code, "ShiftLeft" ) == 0 ) return ImGuiKey_LeftShift;+ if( strcmp( code, "ShiftRight" ) == 0 ) return ImGuiKey_RightShift;+ if( strcmp( code, "Space" ) == 0 ) return ImGuiKey_Space;+ if( strcmp( code, "Tab" ) == 0 ) return ImGuiKey_Tab;+ if( strcmp( code, "Delete" ) == 0 ) return ImGuiKey_Delete;+ if( strcmp( code, "End" ) == 0 ) return ImGuiKey_End;+ if( strcmp( code, "Home" ) == 0 ) return ImGuiKey_Home;+ if( strcmp( code, "Insert" ) == 0 ) return ImGuiKey_Insert;+ if( strcmp( code, "PageDown" ) == 0 ) return ImGuiKey_PageDown;+ if( strcmp( code, "PageUp" ) == 0 ) return ImGuiKey_PageUp;+ if( strcmp( code, "ArrowDown" ) == 0 ) return ImGuiKey_DownArrow;+ if( strcmp( code, "ArrowLeft" ) == 0 ) return ImGuiKey_LeftArrow;+ if( strcmp( code, "ArrowRight" ) == 0 ) return ImGuiKey_RightArrow;+ if( strcmp( code, "ArrowUp" ) == 0 ) return ImGuiKey_UpArrow;+ if( strcmp( code, "NumLock" ) == 0 ) return ImGuiKey_NumLock;+ if( strcmp( code, "Numpad0" ) == 0 ) return ImGuiKey_Keypad0;+ if( strcmp( code, "Numpad1" ) == 0 ) return ImGuiKey_Keypad1;+ if( strcmp( code, "Numpad2" ) == 0 ) return ImGuiKey_Keypad2;+ if( strcmp( code, "Numpad3" ) == 0 ) return ImGuiKey_Keypad3;+ if( strcmp( code, "Numpad4" ) == 0 ) return ImGuiKey_Keypad4;+ if( strcmp( code, "Numpad5" ) == 0 ) return ImGuiKey_Keypad5;+ if( strcmp( code, "Numpad6" ) == 0 ) return ImGuiKey_Keypad6;+ if( strcmp( code, "Numpad7" ) == 0 ) return ImGuiKey_Keypad7;+ if( strcmp( code, "Numpad8" ) == 0 ) return ImGuiKey_Keypad8;+ if( strcmp( code, "Numpad9" ) == 0 ) return ImGuiKey_Keypad9;+ if( strcmp( code, "NumpadAdd" ) == 0 ) return ImGuiKey_KeypadAdd;+ if( strcmp( code, "NumpadBackspace" ) == 0 ) return ImGuiKey_Backspace;+ if( strcmp( code, "NumpadComma" ) == 0 ) return ImGuiKey_KeypadDecimal;+ if( strcmp( code, "NumpadDecimal" ) == 0 ) return ImGuiKey_KeypadDecimal;+ if( strcmp( code, "NumpadDivide" ) == 0 ) return ImGuiKey_KeypadDivide;+ if( strcmp( code, "NumpadEnter" ) == 0 ) return ImGuiKey_KeypadEnter;+ if( strcmp( code, "NumpadEqual" ) == 0 ) return ImGuiKey_KeypadEqual;+ if( strcmp( code, "NumpadMultiply" ) == 0 ) return ImGuiKey_KeypadMultiply;+ if( strcmp( code, "NumpadSubtract" ) == 0 ) return ImGuiKey_KeypadSubtract;+ if( strcmp( code, "Escape" ) == 0 ) return ImGuiKey_Escape;+ if( strcmp( code, "F1" ) == 0 ) return ImGuiKey_F1;+ if( strcmp( code, "F2" ) == 0 ) return ImGuiKey_F2;+ if( strcmp( code, "F3" ) == 0 ) return ImGuiKey_F3;+ if( strcmp( code, "F4" ) == 0 ) return ImGuiKey_F4;+ if( strcmp( code, "F5" ) == 0 ) return ImGuiKey_F5;+ if( strcmp( code, "F6" ) == 0 ) return ImGuiKey_F6;+ if( strcmp( code, "F7" ) == 0 ) return ImGuiKey_F7;+ if( strcmp( code, "F8" ) == 0 ) return ImGuiKey_F8;+ if( strcmp( code, "F9" ) == 0 ) return ImGuiKey_F9;+ if( strcmp( code, "F10" ) == 0 ) return ImGuiKey_F10;+ // F11 is browser fullscreen, F12 is browser dev tools, omitting them+ if( strcmp( code, "ScrollLock" ) == 0 ) return ImGuiKey_ScrollLock;+ if( strcmp( code, "Pause" ) == 0 ) return ImGuiKey_Pause;+ return ImGuiKey_None;+}++Backend::Backend( const char* title, const std::function<void()>& redraw, const std::function<void(float)>& scaleChanged, const std::function<int(void)>& isBusy, RunQueue* mainThreadTasks )+{+ constexpr EGLint eglConfigAttrib[] = {+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,+ EGL_RED_SIZE, 8,+ EGL_GREEN_SIZE, 8,+ EGL_BLUE_SIZE, 8,+ EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,+ EGL_NONE+ };++ s_eglDpy = eglGetDisplay( EGL_DEFAULT_DISPLAY );+ EGLBoolean res;+ res = eglInitialize( s_eglDpy, nullptr, nullptr );+ if( res != EGL_TRUE ) { fprintf( stderr, "Cannot initialize EGL!\n" ); exit( 1 ); }++ EGLint count;+ EGLConfig eglConfig;+ res = eglChooseConfig( s_eglDpy, eglConfigAttrib, &eglConfig, 1, &count );+ if( res != EGL_TRUE || count != 1 ) { fprintf( stderr, "No suitable EGL config found!\n" ); exit( 1 ); }++ s_eglSurf = eglCreateWindowSurface( s_eglDpy, eglConfig, 0, nullptr );++ constexpr EGLint eglCtxAttrib[] = {+ EGL_CONTEXT_CLIENT_VERSION, 2,+ EGL_NONE+ };++ s_eglCtx = eglCreateContext( s_eglDpy, eglConfig, EGL_NO_CONTEXT, eglCtxAttrib );+ if( !s_eglCtx ) { fprintf( stderr, "Cannot create OpenGL 3.2 Core Profile context!\n" ); exit( 1 ); }+ res = eglMakeCurrent( s_eglDpy, s_eglSurf, s_eglSurf, s_eglCtx );+ if( res != EGL_TRUE ) { fprintf( stderr, "Cannot make EGL context current!\n" ); exit( 1 ); }++ ImGui_ImplOpenGL3_Init( "#version 100" );++ EM_ASM( document.title = UTF8ToString($0), title );++ s_redraw = redraw;+ s_scaleChanged = scaleChanged;+ s_isBusy = isBusy;+ s_mainThreadTasks = mainThreadTasks;++ ImGuiIO& io = ImGui::GetIO();+ io.BackendPlatformName = "wasm (tracy profiler)";++ emscripten_set_mousedown_callback( "#canvas", nullptr, EM_TRUE, []( int, const EmscriptenMouseEvent* e, void* ) -> EM_BOOL {+ ImGui::GetIO().AddMouseButtonEvent( e->button == 0 ? 0 : 3 - e->button, true );+ tracy::s_wasActive = true;+ return EM_TRUE;+ } );+ emscripten_set_mouseup_callback( "#canvas", nullptr, EM_TRUE, []( int, const EmscriptenMouseEvent* e, void* ) -> EM_BOOL {+ ImGui::GetIO().AddMouseButtonEvent( e->button == 0 ? 0 : 3 - e->button, false );+ tracy::s_wasActive = true;+ return EM_TRUE;+ } );+ emscripten_set_mousemove_callback( "#canvas", nullptr, EM_TRUE, []( int, const EmscriptenMouseEvent* e, void* ) -> EM_BOOL {+ const auto scale = EM_ASM_DOUBLE( { return window.devicePixelRatio; } );+ ImGui::GetIO().AddMousePosEvent( e->targetX * scale, e->targetY * scale );+ tracy::s_wasActive = true;+ return EM_TRUE;+ } );+ emscripten_set_mouseleave_callback( "#canvas", nullptr, EM_TRUE, []( int, const EmscriptenMouseEvent*, void* ) -> EM_BOOL {+ ImGui::GetIO().AddFocusEvent( false );+ tracy::s_wasActive = true;+ return EM_TRUE;+ } );+ emscripten_set_mouseenter_callback( "#canvas", nullptr, EM_TRUE, []( int, const EmscriptenMouseEvent*, void* ) -> EM_BOOL {+ ImGui::GetIO().AddFocusEvent( true );+ tracy::s_wasActive = true;+ return EM_TRUE;+ } );+ emscripten_set_wheel_callback( "#canvas", nullptr, EM_TRUE, []( int, const EmscriptenWheelEvent* e, void* ) -> EM_BOOL {+ ImGui::GetIO().AddMouseWheelEvent( e->deltaX * -0.05, e->deltaY * -0.05 );+ tracy::s_wasActive = true;+ return EM_TRUE;+ } );+ emscripten_set_keydown_callback( EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, EM_TRUE, [] ( int, const EmscriptenKeyboardEvent* e, void* ) -> EM_BOOL {+ const auto code = TranslateKeyCode( e->code );+ if( code == ImGuiKey_None ) return EM_FALSE;+ ImGui::GetIO().AddKeyEvent( code, true );+ if( e->key[0] && !e->key[1] ) ImGui::GetIO().AddInputCharacter( *e->key );+ return EM_TRUE;+ } );+ emscripten_set_keyup_callback( EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, EM_TRUE, [] ( int, const EmscriptenKeyboardEvent* e, void* ) -> EM_BOOL {+ const auto code = TranslateKeyCode( e->code );+ if( code == ImGuiKey_None ) return EM_FALSE;+ ImGui::GetIO().AddKeyEvent( code, false );+ return EM_TRUE;+ } );++ s_time = std::chrono::duration_cast<std::chrono::microseconds>( std::chrono::high_resolution_clock::now().time_since_epoch() ).count();+}++Backend::~Backend()+{+}++void Backend::Show()+{+}++void Backend::Run()+{+ emscripten_set_main_loop( []() {+ s_redraw();+ s_mainThreadTasks->Run();+ }, 0, 1 );+}++void Backend::Attention()+{+}++void Backend::NewFrame( int& w, int& h )+{+ const auto scale = GetDpiScale();+ if( scale != s_prevScale )+ {+ s_prevScale = scale;+ s_scaleChanged( scale );+ }++ w = EM_ASM_INT( { return window.innerWidth; } ) * scale;+ h = EM_ASM_INT( { return window.innerHeight; } ) * scale;++ if( s_width != w || s_height != h )+ {+ EM_ASM( Module.canvas.style.width = window.innerWidth + 'px'; Module.canvas.style.height = window.innerHeight + 'px' );+ EM_ASM( Module.canvas.width = $0; Module.canvas.height = $1, w, h );++ s_width = w;+ s_height = h;++ glViewport( 0, 0, s_width, s_height );+ tracy::s_wasActive = true;+ }++ ImGuiIO& io = ImGui::GetIO();+ io.DisplaySize = ImVec2( w, h );+ io.DisplayFramebufferScale = ImVec2( 1, 1 );++ ImGui_ImplOpenGL3_NewFrame();++ ImGuiMouseCursor cursor = ImGui::GetMouseCursor();+ const char* cursorName;+ switch( cursor )+ {+ case ImGuiMouseCursor_None: cursorName = "none"; break;+ case ImGuiMouseCursor_Arrow:+ switch( s_isBusy() )+ {+ default:+ case 0: cursorName = "default"; break;+ case 1: cursorName = "progress"; break;+ case 2: cursorName = "wait"; break;+ }+ break;+ case ImGuiMouseCursor_TextInput: cursorName = "text"; break;+ case ImGuiMouseCursor_ResizeAll: cursorName = "move"; break;+ case ImGuiMouseCursor_ResizeNS: cursorName = "ns-resize"; break;+ case ImGuiMouseCursor_ResizeEW: cursorName = "ew-resize"; break;+ case ImGuiMouseCursor_ResizeNESW: cursorName = "nesw-resize"; break;+ case ImGuiMouseCursor_ResizeNWSE: cursorName = "nwse-resize"; break;+ case ImGuiMouseCursor_Hand: cursorName = "pointer"; break;+ case ImGuiMouseCursor_NotAllowed: cursorName = "not-allowed"; break;+ default: cursorName = "auto"; break;+ };+ if( s_prevCursor != cursorName )+ {+ s_prevCursor = cursorName;+ EM_ASM_INT( { document.getElementById('canvas').style.cursor = UTF8ToString($0); }, cursorName );+ }++ uint64_t time = std::chrono::duration_cast<std::chrono::microseconds>( std::chrono::high_resolution_clock::now().time_since_epoch() ).count();+ io.DeltaTime = std::min( 0.1f, ( time - s_time ) / 1000000.f );+ s_time = time;+}++void Backend::EndFrame()+{+ const ImVec4 clear_color = ImColor( 20, 20, 17 );++ ImGui::Render();+ glClearColor( clear_color.x, clear_color.y, clear_color.z, clear_color.w );+ glClear( GL_COLOR_BUFFER_BIT );+ ImGui_ImplOpenGL3_RenderDrawData( ImGui::GetDrawData() );+}++void Backend::SetIcon( uint8_t* data, int w, int h )+{+}++void Backend::SetTitle( const char* title )+{+ EM_ASM( document.title = UTF8ToString($0), title );+}++float Backend::GetDpiScale()+{+ return EM_ASM_DOUBLE( { return window.devicePixelRatio; } );+}
+ cbits/tracy/profiler/src/BackendGlfw.cpp view
@@ -0,0 +1,216 @@+#include <backends/imgui_impl_glfw.h>+#include <backends/imgui_impl_opengl3.h>+#include <backends/imgui_impl_opengl3_loader.h>++#include <chrono>+#include <GLFW/glfw3.h>+#include <stdio.h>+#include <stdlib.h>+#include <thread>++#include "profiler/TracyConfig.hpp"+#include "profiler/TracyImGui.hpp"++#include "Backend.hpp"+#include "RunQueue.hpp"+++static GLFWwindow* s_window;+static std::function<void()> s_redraw;+static std::function<void(float)> s_scaleChanged;+static RunQueue* s_mainThreadTasks;+static WindowPosition* s_winPos;+static bool s_iconified;+static float s_prevScale = -1;++extern tracy::Config s_config;+++static void glfw_error_callback( int error, const char* description )+{+ fprintf(stderr, "Error %d: %s\n", error, description);+}++static void glfw_window_pos_callback( GLFWwindow* window, int x, int y )+{+ if( !glfwGetWindowAttrib( window, GLFW_MAXIMIZED ) )+ {+ s_winPos->x = x;+ s_winPos->y = y;+ }+}++static void glfw_window_size_callback( GLFWwindow* window, int w, int h )+{+ if( !glfwGetWindowAttrib( window, GLFW_MAXIMIZED ) )+ {+ s_winPos->w = w;+ s_winPos->h = h;+ }+ tracy::s_wasActive = true;+}++static void glfw_window_maximize_callback( GLFWwindow*, int maximized )+{+ s_winPos->maximize = maximized;+}++static void glfw_window_iconify_callback( GLFWwindow*, int iconified )+{+ s_iconified = iconified != 0;+}+++Backend::Backend( const char* title, const std::function<void()>& redraw, const std::function<void(float)>& scaleChanged, const std::function<int(void)>& isBusy, RunQueue* mainThreadTasks )+{+ glfwSetErrorCallback( glfw_error_callback );+ if( !glfwInit() ) exit( 1 );+#ifdef DISPLAY_SERVER_WAYLAND+ glfwWindowHint( GLFW_ALPHA_BITS, 0 );+#else+ glfwWindowHint( GLFW_VISIBLE, 0 );+#endif+ glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 3 );+ glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 2 );+ glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE );+#ifdef __APPLE__+ glfwWindowHint( GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE );+#endif+#ifdef WIN32+# if GLFW_VERSION_MAJOR > 3 || ( GLFW_VERSION_MAJOR == 3 && GLFW_VERSION_MINOR >= 4 )+ glfwWindowHint( GLFW_WIN32_KEYBOARD_MENU, 1 );+# endif+# if GLFW_VERSION_MAJOR > 3 || ( GLFW_VERSION_MAJOR == 3 && GLFW_VERSION_MINOR >= 3 )+ glfwWindowHint( GLFW_SCALE_TO_MONITOR, 1 );+# endif+#endif+ s_window = glfwCreateWindow( m_winPos.w, m_winPos.h, title, NULL, NULL );+ if( !s_window ) exit( 1 );++ glfwSetWindowPos( s_window, m_winPos.x, m_winPos.y );+#if GLFW_VERSION_MAJOR > 3 || ( GLFW_VERSION_MAJOR == 3 && GLFW_VERSION_MINOR >= 2 )+ if( m_winPos.maximize ) glfwMaximizeWindow( s_window );+#endif++ glfwMakeContextCurrent( s_window );+ glfwSwapInterval( 1 ); // Enable vsync+ glfwSetWindowRefreshCallback( s_window, []( GLFWwindow* ) { tracy::s_wasActive = true; s_redraw(); } );++ ImGui_ImplGlfw_InitForOpenGL( s_window, true );+ ImGui_ImplOpenGL3_Init( "#version 150" );++ s_redraw = redraw;+ s_scaleChanged = scaleChanged;+ s_mainThreadTasks = mainThreadTasks;+ s_winPos = &m_winPos;+ s_iconified = false;++ glfwSetWindowPosCallback( s_window, glfw_window_pos_callback );+ glfwSetWindowSizeCallback( s_window, glfw_window_size_callback );+#if GLFW_VERSION_MAJOR > 3 || ( GLFW_VERSION_MAJOR == 3 && GLFW_VERSION_MINOR >= 3 )+ glfwSetWindowMaximizeCallback( s_window, glfw_window_maximize_callback );+#endif+ glfwSetWindowIconifyCallback( s_window, glfw_window_iconify_callback );+}++Backend::~Backend()+{+ ImGui_ImplOpenGL3_Shutdown();+ ImGui_ImplGlfw_Shutdown();++ glfwDestroyWindow( s_window );++ glfwTerminate();+}++void Backend::Show()+{+ glfwShowWindow( s_window );+}++void Backend::Run()+{+ while( !glfwWindowShouldClose( s_window ) )+ {+ if( s_iconified )+ {+ glfwWaitEvents();+ }+ else+ {+ glfwPollEvents();+ s_redraw();+ if( s_config.focusLostLimit && !glfwGetWindowAttrib( s_window, GLFW_FOCUSED ) ) std::this_thread::sleep_for( std::chrono::milliseconds( 50 ) );+ s_mainThreadTasks->Run();+ }+ }+}++void Backend::Attention()+{+#if GLFW_VERSION_MAJOR > 3 || ( GLFW_VERSION_MAJOR == 3 && GLFW_VERSION_MINOR >= 3 )+ if( !glfwGetWindowAttrib( s_window, GLFW_FOCUSED ) )+ {+ glfwRequestWindowAttention( s_window );+ }+#endif+}++void Backend::NewFrame( int& w, int& h )+{+ const auto scale = GetDpiScale();+ if( scale != s_prevScale )+ {+ s_prevScale = scale;+ s_scaleChanged( scale );+ }++ glfwGetFramebufferSize( s_window, &w, &h );+#if defined( __APPLE__ )+ w = static_cast<int>( w / scale );+ h = static_cast<int>( h / scale );+#endif+ m_w = w;+ m_h = h;++ ImGui_ImplOpenGL3_NewFrame();+ ImGui_ImplGlfw_NewFrame();+}++void Backend::EndFrame()+{+ const ImVec4 clear_color = ImColor( 20, 20, 17 );++ ImGui::Render();+ glViewport( 0, 0, m_w, m_h );+ glClearColor( clear_color.x, clear_color.y, clear_color.z, clear_color.w );+ glClear( GL_COLOR_BUFFER_BIT );+ ImGui_ImplOpenGL3_RenderDrawData( ImGui::GetDrawData() );++ glfwSwapBuffers( s_window );+}++void Backend::SetIcon( uint8_t* data, int w, int h )+{+ GLFWimage icon;+ icon.width = w;+ icon.height = h;+ icon.pixels = data;+ glfwSetWindowIcon( s_window, 1, &icon );+}++void Backend::SetTitle( const char* title )+{+ glfwSetWindowTitle( s_window, title );+}++float Backend::GetDpiScale()+{+#if GLFW_VERSION_MAJOR > 3 || ( GLFW_VERSION_MAJOR == 3 && GLFW_VERSION_MINOR >= 3 )+ float x, y;+ glfwGetWindowContentScale( s_window, &x, &y );+ return x;+#else+ return 1;+#endif+}
+ cbits/tracy/profiler/src/BackendWayland.cpp view
@@ -0,0 +1,1319 @@+#include <EGL/egl.h>+#include <EGL/eglext.h>+#include <backends/imgui_impl_opengl3.h>+#include <backends/imgui_impl_opengl3_loader.h>++#include <chrono>+#include <linux/input-event-codes.h>+#include <memory>+#include <stdio.h>+#include <stdlib.h>+#include <string>+#include <string.h>+#include <sys/mman.h>+#include <unistd.h>+#include <unordered_map>+#include <xkbcommon/xkbcommon.h>+#include <xkbcommon/xkbcommon-compose.h>+#include <wayland-client.h>+#include <wayland-cursor.h>+#include <wayland-egl.h>++#include "wayland-xdg-activation-client-protocol.h"+#include "wayland-xdg-decoration-client-protocol.h"+#include "wayland-xdg-shell-client-protocol.h"+#include "wayland-fractional-scale-client-protocol.h"+#include "wayland-viewporter-client-protocol.h"+#include "wayland-cursor-shape-client-protocol.h"+#include "wayland-xdg-toplevel-icon-client-protocol.h"++#include "profiler/TracyImGui.hpp"+#include "stb_image_resize.h"++#include "Backend.hpp"+#include "RunQueue.hpp"+#include "profiler/TracyConfig.hpp"++constexpr ImGuiKey s_keyTable[] = {+ /* 0 */ ImGuiKey_None,+ /* 1 */ ImGuiKey_Escape,+ /* 2 */ ImGuiKey_1,+ /* 3 */ ImGuiKey_2,+ /* 4 */ ImGuiKey_3,+ /* 5 */ ImGuiKey_4,+ /* 6 */ ImGuiKey_5,+ /* 7 */ ImGuiKey_6,+ /* 8 */ ImGuiKey_7,+ /* 9 */ ImGuiKey_8,+ /* 10 */ ImGuiKey_9,+ /* 11 */ ImGuiKey_0,+ /* 12 */ ImGuiKey_Minus,+ /* 13 */ ImGuiKey_Equal,+ /* 14 */ ImGuiKey_Backspace,+ /* 15 */ ImGuiKey_Tab,+ /* 16 */ ImGuiKey_Q,+ /* 17 */ ImGuiKey_W,+ /* 18 */ ImGuiKey_E,+ /* 19 */ ImGuiKey_R,+ /* 20 */ ImGuiKey_T,+ /* 21 */ ImGuiKey_Y,+ /* 22 */ ImGuiKey_U,+ /* 23 */ ImGuiKey_I,+ /* 24 */ ImGuiKey_O,+ /* 25 */ ImGuiKey_P,+ /* 26 */ ImGuiKey_LeftBracket,+ /* 27 */ ImGuiKey_RightBracket,+ /* 28 */ ImGuiKey_Enter,+ /* 29 */ ImGuiKey_LeftCtrl,+ /* 30 */ ImGuiKey_A,+ /* 31 */ ImGuiKey_S,+ /* 32 */ ImGuiKey_D,+ /* 33 */ ImGuiKey_F,+ /* 34 */ ImGuiKey_G,+ /* 35 */ ImGuiKey_H,+ /* 36 */ ImGuiKey_J,+ /* 37 */ ImGuiKey_K,+ /* 38 */ ImGuiKey_L,+ /* 39 */ ImGuiKey_Semicolon,+ /* 40 */ ImGuiKey_Apostrophe,+ /* 41 */ ImGuiKey_GraveAccent,+ /* 42 */ ImGuiKey_LeftShift,+ /* 43 */ ImGuiKey_Backslash,+ /* 44 */ ImGuiKey_Z,+ /* 45 */ ImGuiKey_X,+ /* 46 */ ImGuiKey_C,+ /* 47 */ ImGuiKey_V,+ /* 48 */ ImGuiKey_B,+ /* 49 */ ImGuiKey_N,+ /* 50 */ ImGuiKey_M,+ /* 51 */ ImGuiKey_Comma,+ /* 52 */ ImGuiKey_Period,+ /* 53 */ ImGuiKey_Slash,+ /* 54 */ ImGuiKey_RightShift,+ /* 55 */ ImGuiKey_KeypadMultiply,+ /* 56 */ ImGuiKey_LeftAlt,+ /* 57 */ ImGuiKey_Space,+ /* 58 */ ImGuiKey_CapsLock,+ /* 59 */ ImGuiKey_F1,+ /* 60 */ ImGuiKey_F2,+ /* 61 */ ImGuiKey_F3,+ /* 62 */ ImGuiKey_F4,+ /* 63 */ ImGuiKey_F5,+ /* 64 */ ImGuiKey_F6,+ /* 65 */ ImGuiKey_F7,+ /* 66 */ ImGuiKey_F8,+ /* 67 */ ImGuiKey_F9,+ /* 68 */ ImGuiKey_F10,+ /* 69 */ ImGuiKey_NumLock,+ /* 70 */ ImGuiKey_ScrollLock,+ /* 71 */ ImGuiKey_Keypad7,+ /* 72 */ ImGuiKey_Keypad8,+ /* 73 */ ImGuiKey_Keypad9,+ /* 74 */ ImGuiKey_KeypadSubtract,+ /* 75 */ ImGuiKey_Keypad4,+ /* 76 */ ImGuiKey_Keypad5,+ /* 77 */ ImGuiKey_Keypad6,+ /* 78 */ ImGuiKey_KeypadAdd,+ /* 79 */ ImGuiKey_Keypad1,+ /* 80 */ ImGuiKey_Keypad2,+ /* 81 */ ImGuiKey_Keypad3,+ /* 82 */ ImGuiKey_Keypad0,+ /* 83 */ ImGuiKey_KeypadDecimal,+ /* 84 */ ImGuiKey_RightAlt,+ /* 85 */ ImGuiKey_None,+ /* 86 */ ImGuiKey_Backslash,+ /* 87 */ ImGuiKey_F11,+ /* 88 */ ImGuiKey_F12,+ /* 89 */ ImGuiKey_None,+ /* 90 */ ImGuiKey_None,+ /* 91 */ ImGuiKey_None,+ /* 92 */ ImGuiKey_None,+ /* 93 */ ImGuiKey_None,+ /* 94 */ ImGuiKey_None,+ /* 95 */ ImGuiKey_None,+ /* 96 */ ImGuiKey_KeypadEnter,+ /* 97 */ ImGuiKey_RightCtrl,+ /* 98 */ ImGuiKey_KeypadDivide,+ /* 99 */ ImGuiKey_PrintScreen,+ /* 100 */ ImGuiKey_RightAlt,+ /* 101 */ ImGuiKey_None,+ /* 102 */ ImGuiKey_Home,+ /* 103 */ ImGuiKey_UpArrow,+ /* 104 */ ImGuiKey_PageUp,+ /* 105 */ ImGuiKey_LeftArrow,+ /* 106 */ ImGuiKey_RightArrow,+ /* 107 */ ImGuiKey_End,+ /* 108 */ ImGuiKey_DownArrow,+ /* 109 */ ImGuiKey_PageDown,+ /* 110 */ ImGuiKey_Insert,+ /* 111 */ ImGuiKey_Delete,+ /* 112 */ ImGuiKey_None,+ /* 113 */ ImGuiKey_None,+ /* 114 */ ImGuiKey_None,+ /* 115 */ ImGuiKey_None,+ /* 116 */ ImGuiKey_None,+ /* 117 */ ImGuiKey_KeypadEqual,+ /* 118 */ ImGuiKey_None,+ /* 119 */ ImGuiKey_Pause,+ /* 120 */ ImGuiKey_None,+ /* 121 */ ImGuiKey_KeypadDecimal,+ /* 122 */ ImGuiKey_None,+ /* 123 */ ImGuiKey_None,+ /* 124 */ ImGuiKey_None,+ /* 125 */ ImGuiKey_LeftSuper,+ /* 126 */ ImGuiKey_RightSuper,+ /* 127 */ ImGuiKey_Menu,+};++static std::function<void()> s_redraw;+static std::function<void(float)> s_scaleChanged;+static std::function<int(void)> s_isBusy;+static RunQueue* s_mainThreadTasks;++static struct wl_display* s_dpy;+static struct wl_compositor* s_comp;+static uint32_t s_comp_version;+static struct wl_surface* s_surf;+static struct wl_egl_window* s_eglWin;+static struct wl_shm* s_shm;+static struct xdg_wm_base* s_wm;+static EGLDisplay s_eglDpy;+static EGLContext s_eglCtx;+static EGLSurface s_eglSurf;+static struct xdg_surface* s_xdgSurf;+static struct xdg_toplevel* s_toplevel;+static struct wl_seat* s_seat;+static struct wl_pointer* s_pointer;+static struct wl_cursor_theme* s_cursorTheme;+static struct wl_surface* s_cursorSurf;+static int32_t s_cursorX, s_cursorY;+static struct xdg_activation_v1* s_activation;+static struct xdg_activation_token_v1* s_actToken;+static struct zxdg_decoration_manager_v1* s_decoration;+static struct zxdg_toplevel_decoration_v1* s_tldec;+static struct wp_fractional_scale_manager_v1* s_fractionalScale;+static struct wp_fractional_scale_v1* s_fracSurf;+static struct wp_viewporter* s_viewporter;+static struct wp_viewport* s_viewport;+static struct wp_cursor_shape_manager_v1* s_cursorShape;+static struct wp_cursor_shape_device_v1* s_cursorShapeDev;+static struct wl_keyboard* s_keyboard;+static struct xkb_context* s_xkbCtx;+static struct xkb_keymap* s_xkbKeymap;+static struct xkb_state* s_xkbState;+static struct xkb_compose_table* s_xkbComposeTable;+static struct xkb_compose_state* s_xkbComposeState;+static xkb_mod_index_t s_xkbCtrl, s_xkbAlt, s_xkbShift, s_xkbSuper;+static wp_cursor_shape_device_v1_shape s_mouseCursor;+static uint32_t s_mouseCursorSerial;+static bool s_hasFocus = false;+static struct wl_data_device_manager* s_dataDevMgr;+static struct wl_data_device* s_dataDev;+static struct wl_data_source* s_dataSource;+static uint32_t s_dataSerial;+static std::string s_clipboard, s_clipboardIncoming;+static struct wl_data_offer* s_dataOffer;+static struct wl_data_offer* s_newDataOffer;+static bool s_newDataOfferValid;+static struct xdg_toplevel_icon_manager_v1* s_iconMgr;+static std::vector<int> s_iconSizes;++struct Output+{+ int32_t scale;+ wl_output* obj;+ bool entered;+};+static std::unordered_map<uint32_t, std::unique_ptr<Output>> s_output;+static int s_maxScale = 120;+static int s_prevScale = -1;++static bool s_running = true;+static int s_width, s_height;+static int s_prevWidth, s_prevHeight;+static bool s_maximized;+static uint64_t s_time;++static wl_fixed_t s_wheelAxisX, s_wheelAxisY;+static bool s_wheel;++extern tracy::Config s_config;+++static void RecomputeScale()+{+ if( s_fracSurf ) return;++ // On wl_compositor >= 6 the scale is sent explicitly via wl_surface.preferred_buffer_scale.+ if( s_comp_version >= 6 ) return;++ int max = 1;+ for( auto& out : s_output )+ {+ if( out.second->entered && out.second->scale > max ) max = out.second->scale;+ }+ s_maxScale = max * 120;+ tracy::s_wasActive = true;+}++static void PointerEnter( void*, struct wl_pointer* pointer, uint32_t serial, struct wl_surface* surf, wl_fixed_t sx, wl_fixed_t sy )+{+ if( s_cursorShapeDev )+ {+ wp_cursor_shape_device_v1_set_shape( s_cursorShapeDev, serial, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT );+ s_mouseCursor = WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT;+ s_mouseCursorSerial = serial;+ }+ else+ {+ wl_pointer_set_cursor( pointer, serial, s_cursorSurf, s_cursorX, s_cursorY );+ }+ ImGuiIO& io = ImGui::GetIO();+ io.AddMousePosEvent( wl_fixed_to_double( sx * s_maxScale / 120 ), wl_fixed_to_double( sy * s_maxScale / 120 ) );+}++static void PointerLeave( void*, struct wl_pointer* pointer, uint32_t serial, struct wl_surface* surf )+{+ ImGuiIO& io = ImGui::GetIO();+ io.AddMousePosEvent( -FLT_MAX, -FLT_MAX );+}++static void PointerMotion( void*, struct wl_pointer* pointer, uint32_t time, wl_fixed_t sx, wl_fixed_t sy )+{+ ImGuiIO& io = ImGui::GetIO();+ io.AddMousePosEvent( wl_fixed_to_double( sx * s_maxScale / 120 ), wl_fixed_to_double( sy * s_maxScale / 120 ) );+}++static void PointerButton( void*, struct wl_pointer* pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state )+{+ int b;+ switch( button )+ {+ case BTN_LEFT: b = 0; break;+ case BTN_MIDDLE: b = 2; break;+ case BTN_RIGHT: b = 1; break;+ default: return;+ }+ ImGuiIO& io = ImGui::GetIO();+ io.AddMouseButtonEvent( b, state == WL_POINTER_BUTTON_STATE_PRESSED );+}++static void PointerAxis( void*, struct wl_pointer* pointer, uint32_t time, uint32_t axis, wl_fixed_t value )+{+ s_wheel = true;+ if( axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL )+ {+ s_wheelAxisX -= value;+ }+ else+ {+ s_wheelAxisY -= value;+ }+}++static void PointerAxisSource( void*, struct wl_pointer* pointer, uint32_t source )+{+}++static void PointerAxisStop( void*, struct wl_pointer* pointer, uint32_t time, uint32_t axis )+{+}++static void PointerAxisDiscrete( void*, struct wl_pointer* pointer, uint32_t axis, int32_t type )+{+}++static void PointerFrame( void*, struct wl_pointer* pointer )+{+ if( s_wheel )+ {+ s_wheel = false;+ s_wheelAxisX /= 8;+ s_wheelAxisY /= 8;+ ImGuiIO& io = ImGui::GetIO();+ io.AddMouseWheelEvent( wl_fixed_to_double( s_wheelAxisX ), wl_fixed_to_double( s_wheelAxisY ) );+ s_wheelAxisX = s_wheelAxisY = 0;+ }+}++constexpr struct wl_pointer_listener pointerListener = {+ .enter = PointerEnter,+ .leave = PointerLeave,+ .motion = PointerMotion,+ .button = PointerButton,+ .axis = PointerAxis,+ .frame = PointerFrame,+ .axis_source = PointerAxisSource,+ .axis_stop = PointerAxisStop,+ .axis_discrete = PointerAxisDiscrete+};+++static void KeyboardKeymap( void*, struct wl_keyboard* kbd, uint32_t format, int32_t fd, uint32_t size )+{+ if( format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1 )+ {+ close( fd );+ return;+ }++ auto map = (char*)mmap( nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0 );+ close( fd );+ if( map == MAP_FAILED ) return;++ if( s_xkbKeymap ) xkb_keymap_unref( s_xkbKeymap );+ s_xkbKeymap = xkb_keymap_new_from_string( s_xkbCtx, map, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS );+ munmap( map, size );+ if( !s_xkbKeymap ) return;++ if( s_xkbState ) xkb_state_unref( s_xkbState );+ s_xkbState = xkb_state_new( s_xkbKeymap );++ const char* locale = getenv( "LC_ALL" );+ if( !locale )+ {+ locale = getenv( "LC_CTYPE" );+ if( !locale )+ {+ locale = getenv( "LANG" );+ if( !locale )+ {+ locale = "C";+ }+ }+ }++ if( s_xkbComposeTable ) xkb_compose_table_unref( s_xkbComposeTable );+ s_xkbComposeTable = xkb_compose_table_new_from_locale( s_xkbCtx, locale, XKB_COMPOSE_COMPILE_NO_FLAGS );++ if( s_xkbComposeState ) xkb_compose_state_unref( s_xkbComposeState );+ s_xkbComposeState = xkb_compose_state_new( s_xkbComposeTable, XKB_COMPOSE_STATE_NO_FLAGS );++ s_xkbCtrl = xkb_keymap_mod_get_index( s_xkbKeymap, "Control" );+ s_xkbAlt = xkb_keymap_mod_get_index( s_xkbKeymap, "Mod1" );+ s_xkbShift = xkb_keymap_mod_get_index( s_xkbKeymap, "Shift" );+ s_xkbSuper = xkb_keymap_mod_get_index( s_xkbKeymap, "Mod4" );+}++static void KeyboardEnter( void*, struct wl_keyboard* kbd, uint32_t serial, struct wl_surface* surf, struct wl_array* keys )+{+ ImGui::GetIO().AddFocusEvent( true );+ s_hasFocus = true;+}++static void KeyboardLeave( void*, struct wl_keyboard* kbd, uint32_t serial, struct wl_surface* surf )+{+ if( s_dataOffer )+ {+ wl_data_offer_destroy( s_dataOffer );+ s_dataOffer = nullptr;+ }++ ImGui::GetIO().AddFocusEvent( false );+ s_hasFocus = false;+}++static xkb_keysym_t Compose( const xkb_keysym_t sym )+{+ if( sym == XKB_KEY_NoSymbol ) return sym;+ if( xkb_compose_state_feed( s_xkbComposeState, sym ) != XKB_COMPOSE_FEED_ACCEPTED ) return sym;+ switch( xkb_compose_state_get_status( s_xkbComposeState ) )+ {+ case XKB_COMPOSE_COMPOSED:+ return xkb_compose_state_get_one_sym( s_xkbComposeState );+ case XKB_COMPOSE_COMPOSING:+ case XKB_COMPOSE_CANCELLED:+ return XKB_KEY_NoSymbol;+ case XKB_COMPOSE_NOTHING:+ default:+ return sym;+ }+}++static void KeyboardKey( void*, struct wl_keyboard* kbd, uint32_t serial, uint32_t time, uint32_t key, uint32_t state )+{+ auto& io = ImGui::GetIO();+ if( key < ( sizeof( s_keyTable ) / sizeof( *s_keyTable ) ) )+ {+ io.AddKeyEvent( s_keyTable[key], state == WL_KEYBOARD_KEY_STATE_PRESSED );+ }++ if( state == WL_KEYBOARD_KEY_STATE_PRESSED )+ {+ const xkb_keysym_t* keysyms;+ if( xkb_state_key_get_syms( s_xkbState, key + 8, &keysyms ) == 1 )+ {+ const auto sym = Compose( keysyms[0] );+ char txt[8];+ if( xkb_keysym_to_utf8( sym, txt, sizeof( txt ) ) > 0 )+ {+ ImGui::GetIO().AddInputCharactersUTF8( txt );+ }+ }+ s_dataSerial = serial;+ }+}++static void KeyboardModifiers( void*, struct wl_keyboard* kbd, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group )+{+ xkb_state_update_mask( s_xkbState, mods_depressed, mods_latched, mods_locked, 0, 0, group );++ auto& io = ImGui::GetIO();++ io.AddKeyEvent( ImGuiMod_Ctrl, xkb_state_mod_index_is_active( s_xkbState, s_xkbCtrl, XKB_STATE_MODS_EFFECTIVE ) );+ io.AddKeyEvent( ImGuiMod_Shift, xkb_state_mod_index_is_active( s_xkbState, s_xkbShift, XKB_STATE_MODS_EFFECTIVE ) );+ io.AddKeyEvent( ImGuiMod_Alt, xkb_state_mod_index_is_active( s_xkbState, s_xkbAlt, XKB_STATE_MODS_EFFECTIVE ) );+ io.AddKeyEvent( ImGuiMod_Super, xkb_state_mod_index_is_active( s_xkbState, s_xkbSuper, XKB_STATE_MODS_EFFECTIVE ) );+}++static void KeyboardRepeatInfo( void*, struct wl_keyboard* kbd, int32_t rate, int32_t delay )+{+}++constexpr struct wl_keyboard_listener keyboardListener = {+ .keymap = KeyboardKeymap,+ .enter = KeyboardEnter,+ .leave = KeyboardLeave,+ .key = KeyboardKey,+ .modifiers = KeyboardModifiers,+ .repeat_info = KeyboardRepeatInfo+};+++static void SeatCapabilities( void*, struct wl_seat* seat, uint32_t caps )+{+ const bool hasPointer = caps & WL_SEAT_CAPABILITY_POINTER;+ const bool hasKeyboard = caps & WL_SEAT_CAPABILITY_KEYBOARD;++ if( hasPointer && !s_pointer )+ {+ s_pointer = wl_seat_get_pointer( s_seat );+ wl_pointer_add_listener( s_pointer, &pointerListener, nullptr );+ if( s_cursorShape ) s_cursorShapeDev = wp_cursor_shape_manager_v1_get_pointer( s_cursorShape, s_pointer );+ }+ else if( !hasPointer && s_pointer )+ {+ if( s_cursorShapeDev )+ {+ wp_cursor_shape_device_v1_destroy( s_cursorShapeDev );+ s_cursorShapeDev = nullptr;+ }+ wl_pointer_release( s_pointer );+ s_pointer = nullptr;+ }++ if( hasKeyboard && !s_keyboard )+ {+ s_keyboard = wl_seat_get_keyboard( s_seat );+ wl_keyboard_add_listener( s_keyboard, &keyboardListener, nullptr );+ }+ else if( !hasKeyboard && s_keyboard )+ {+ wl_keyboard_release( s_keyboard );+ s_keyboard = nullptr;+ }+}++static void SeatName( void*, struct wl_seat* seat, const char* name )+{+}++constexpr struct wl_seat_listener seatListener = {+ .capabilities = SeatCapabilities,+ .name = SeatName+};+++static void WmPing( void*, struct xdg_wm_base* shell, uint32_t serial )+{+ xdg_wm_base_pong( shell, serial );+}++constexpr struct xdg_wm_base_listener wmListener = {+ .ping = WmPing+};+++static void OutputGeometry( void*, struct wl_output* output, int32_t x, int32_t y, int32_t phys_w, int32_t phys_h, int32_t subpixel, const char* make, const char* model, int32_t transform )+{+}++static void OutputMode( void*, struct wl_output* output, uint32_t flags, int32_t w, int32_t h, int32_t refresh )+{+}++static void OutputDone( void*, struct wl_output* output )+{+ RecomputeScale();+}++static void OutputScale( void* data, struct wl_output* output, int32_t scale )+{+ auto out = (Output*)data;+ out->scale = scale;+}++constexpr struct wl_output_listener outputListener = {+ .geometry = OutputGeometry,+ .mode = OutputMode,+ .done = OutputDone,+ .scale = OutputScale+};+++static void DecorationConfigure( void*, struct zxdg_toplevel_decoration_v1* tldec, uint32_t mode )+{+}++constexpr struct zxdg_toplevel_decoration_v1_listener decorationListener = {+ .configure = DecorationConfigure+};+++static void IconMgrSize( void*, struct xdg_toplevel_icon_manager_v1*, int32_t size )+{+ s_iconSizes.push_back( size );+}++static void IconMgrDone( void*, struct xdg_toplevel_icon_manager_v1* )+{+}++constexpr struct xdg_toplevel_icon_manager_v1_listener iconMgrListener = {+ .icon_size = IconMgrSize,+ .done = IconMgrDone+};+++static void RegistryGlobal( void*, struct wl_registry* reg, uint32_t name, const char* interface, uint32_t version )+{+ if( strcmp( interface, wl_compositor_interface.name ) == 0 )+ {+ s_comp_version = version;+ s_comp = (wl_compositor*)wl_registry_bind( reg, name, &wl_compositor_interface, version >= 6 ? 6 : 4 );+ }+ else if( strcmp( interface, wl_shm_interface.name ) == 0 )+ {+ s_shm = (wl_shm*)wl_registry_bind( reg, name, &wl_shm_interface, 1 );+ }+ else if( strcmp( interface, xdg_wm_base_interface.name ) == 0 )+ {+ s_wm = (xdg_wm_base*)wl_registry_bind( reg, name, &xdg_wm_base_interface, 1 );+ xdg_wm_base_add_listener( s_wm, &wmListener, nullptr );+ }+ else if( strcmp( interface, wl_seat_interface.name ) == 0 )+ {+ s_seat = (wl_seat*)wl_registry_bind( reg, name, &wl_seat_interface, 5 );+ wl_seat_add_listener( s_seat, &seatListener, nullptr );+ }+ else if( strcmp( interface, xdg_activation_v1_interface.name ) == 0 )+ {+ s_activation = (xdg_activation_v1*)wl_registry_bind( reg, name, &xdg_activation_v1_interface, 1 );+ }+ else if( strcmp( interface, wl_output_interface.name ) == 0 )+ {+ auto output = (wl_output*)wl_registry_bind( reg, name, &wl_output_interface, 2 );+ auto ptr = std::make_unique<Output>( Output { 1, output, false } );+ wl_output_add_listener( output, &outputListener, ptr.get() );+ s_output.emplace( name, std::move( ptr ) );+ }+ else if( strcmp( interface, zxdg_decoration_manager_v1_interface.name ) == 0 )+ {+ s_decoration = (zxdg_decoration_manager_v1*)wl_registry_bind( reg, name, &zxdg_decoration_manager_v1_interface, 1 );+ }+ else if( strcmp( interface, wp_fractional_scale_manager_v1_interface.name ) == 0 )+ {+ s_fractionalScale = (wp_fractional_scale_manager_v1*)wl_registry_bind( reg, name, &wp_fractional_scale_manager_v1_interface, 1 );+ }+ else if( strcmp( interface, wp_viewporter_interface.name ) == 0 )+ {+ s_viewporter = (wp_viewporter*)wl_registry_bind( reg, name, &wp_viewporter_interface, 1 );+ }+ else if( strcmp( interface, wp_cursor_shape_manager_v1_interface.name ) == 0 )+ {+ s_cursorShape = (wp_cursor_shape_manager_v1*)wl_registry_bind( reg, name, &wp_cursor_shape_manager_v1_interface, 1 );+ if( s_pointer ) s_cursorShapeDev = wp_cursor_shape_manager_v1_get_pointer( s_cursorShape, s_pointer );+ }+ else if( strcmp( interface, wl_data_device_manager_interface.name ) == 0 )+ {+ s_dataDevMgr = (wl_data_device_manager*)wl_registry_bind( reg, name, &wl_data_device_manager_interface, 2 );+ }+ else if( strcmp( interface, xdg_toplevel_icon_manager_v1_interface.name ) == 0 )+ {+ s_iconMgr = (xdg_toplevel_icon_manager_v1*)wl_registry_bind( reg, name, &xdg_toplevel_icon_manager_v1_interface, 1 );+ xdg_toplevel_icon_manager_v1_add_listener( s_iconMgr, &iconMgrListener, nullptr );+ }+}++static void RegistryGlobalRemove( void*, struct wl_registry* reg, uint32_t name )+{+ auto it = s_output.find( name );+ if( it == s_output.end() ) return;+ wl_output_destroy( it->second->obj );+ s_output.erase( it );+ RecomputeScale();+}++constexpr struct wl_registry_listener registryListener = {+ .global = RegistryGlobal,+ .global_remove = RegistryGlobalRemove+};+++static void XdgSurfaceConfigure( void*, struct xdg_surface* surf, uint32_t serial )+{+ tracy::s_wasActive = true;+ xdg_surface_ack_configure( surf, serial );+}++constexpr struct xdg_surface_listener xdgSurfaceListener = {+ .configure = XdgSurfaceConfigure+};+++static void XdgToplevelConfigure( void*, struct xdg_toplevel* toplevel, int32_t width, int32_t height, struct wl_array* states )+{+ if( width == 0 || height == 0 ) return;++ bool max = false;+ auto data = (uint32_t*)states->data;+ for( size_t i = 0; i < states->size / sizeof(uint32_t); i++ )+ {+ if( data[i] == XDG_TOPLEVEL_STATE_MAXIMIZED )+ {+ max = true;+ break;+ }+ }+ s_maximized = max;++ s_width = width;+ s_height = height;+}++static void XdgToplevelClose( void*, struct xdg_toplevel* toplevel )+{+ s_running = false;+}++constexpr struct xdg_toplevel_listener toplevelListener = {+ .configure = XdgToplevelConfigure,+ .close = XdgToplevelClose+};++static void SurfaceEnter( void*, struct wl_surface* surface, struct wl_output* output )+{+ for ( auto& out : s_output )+ {+ if ( out.second->obj == output )+ {+ out.second->entered = true;+ RecomputeScale();+ break;+ }+ }+}++static void SurfaceLeave( void*, struct wl_surface* surface, struct wl_output* output )+{+ for ( auto& out : s_output )+ {+ if ( out.second->obj == output )+ {+ out.second->entered = false;+ RecomputeScale();+ break;+ }+ }+}++static void SurfacePreferredBufferScale( void*, struct wl_surface* surface, int32_t scale )+{+ if( s_fracSurf ) return;+ s_maxScale = scale * 120;+ tracy::s_wasActive = true;+}++static void SurfacePreferredBufferTransform( void*, struct wl_surface* surface, uint32_t transform )+{+}++constexpr struct wl_surface_listener surfaceListener = {+ .enter = SurfaceEnter,+ .leave = SurfaceLeave,+ .preferred_buffer_scale = SurfacePreferredBufferScale,+ .preferred_buffer_transform = SurfacePreferredBufferTransform+};++static void FractionalPreferredScale( void*, struct wp_fractional_scale_v1* frac, uint32_t scale )+{+ s_maxScale = scale;+ tracy::s_wasActive = true;+}++constexpr struct wp_fractional_scale_v1_listener fractionalListener = {+ .preferred_scale = FractionalPreferredScale+};+++static void DataOfferOffer( void*, struct wl_data_offer* offer, const char* mimeType )+{+ assert( s_newDataOffer == offer );++ if( strcmp( mimeType, "text/plain" ) == 0 )+ {+ wl_data_offer_accept( offer, 0, mimeType );+ s_newDataOfferValid = true;+ }+ else+ {+ wl_data_offer_accept( offer, 0, nullptr );+ }+}++static void DataOfferSourceActions( void*, struct wl_data_offer* offer, uint32_t sourceActions )+{+}++static void DataOfferAction( void*, struct wl_data_offer* offer, uint32_t dndAction )+{+}++constexpr struct wl_data_offer_listener dataOfferListener = {+ .offer = DataOfferOffer,+ .source_actions = DataOfferSourceActions,+ .action = DataOfferAction+};+++static void DataDeviceDataOffer( void*, struct wl_data_device* dataDevice, struct wl_data_offer* offer )+{+ s_newDataOffer = offer;+ wl_data_offer_add_listener( offer, &dataOfferListener, nullptr );+ s_newDataOfferValid = false;+}++static void DataDeviceEnter( void*, struct wl_data_device* dataDevice, uint32_t serial, struct wl_surface* surface, wl_fixed_t x, wl_fixed_t y, struct wl_data_offer* offer )+{+ if( s_newDataOffer )+ {+ wl_data_offer_destroy( s_newDataOffer );+ s_newDataOffer = nullptr;+ }+}++static void DataDeviceLeave( void*, struct wl_data_device* dataDevice )+{+}++static void DataDeviceMotion( void*, struct wl_data_device* dataDevice, uint32_t time, wl_fixed_t x, wl_fixed_t y )+{+}++static void DataDeviceSelection( void*, struct wl_data_device* dataDevice, struct wl_data_offer* offer )+{+ if( s_dataOffer ) wl_data_offer_destroy( s_dataOffer );+ if( offer )+ {+ if( s_newDataOfferValid )+ {+ s_dataOffer = s_newDataOffer;+ }+ else+ {+ if( s_newDataOffer ) wl_data_offer_destroy( s_newDataOffer );+ s_dataOffer = nullptr;+ }+ s_newDataOffer = nullptr;+ }+ else+ {+ s_dataOffer = nullptr;+ }+}++constexpr struct wl_data_device_listener dataDeviceListener = {+ .data_offer = DataDeviceDataOffer,+ .enter = DataDeviceEnter,+ .leave = DataDeviceLeave,+ .motion = DataDeviceMotion,+ .selection = DataDeviceSelection+};+++void DataSourceTarget( void*, struct wl_data_source* dataSource, const char* mimeType )+{+}++void DataSourceSend( void*, struct wl_data_source* dataSource, const char* mimeType, int32_t fd )+{+ if( !s_clipboard.empty() )+ {+ auto len = s_clipboard.size();+ auto ptr = s_clipboard.data();+ while( len > 0 )+ {+ auto sz = write( fd, ptr, len );+ if( sz < 0 ) break;+ len -= sz;+ ptr += sz;+ }+ }+ close( fd );+}++void DataSourceCancelled( void*, struct wl_data_source* dataSource )+{+ s_clipboard.clear();+ wl_data_source_destroy( s_dataSource );+ s_dataSource = nullptr;+}++constexpr struct wl_data_source_listener dataSourceListener = {+ .target = DataSourceTarget,+ .send = DataSourceSend,+ .cancelled = DataSourceCancelled+};+++static void SetupCursor()+{+ if( s_cursorShape ) return;++ auto env_xcursor_theme = getenv( "XCURSOR_THEME" );+ auto env_xcursor_size = getenv( "XCURSOR_SIZE" );++ int size = env_xcursor_size ? atoi( env_xcursor_size ) : 24;+ size = size * s_maxScale / 120;++ if( s_cursorSurf ) wl_surface_destroy( s_cursorSurf );+ if( s_cursorTheme ) wl_cursor_theme_destroy( s_cursorTheme );++ s_cursorTheme = wl_cursor_theme_load( env_xcursor_theme, size, s_shm );+ auto cursor = wl_cursor_theme_get_cursor( s_cursorTheme, "left_ptr" );+ s_cursorSurf = wl_compositor_create_surface( s_comp );+ if( s_maxScale != 120 ) wl_surface_set_buffer_scale( s_cursorSurf, s_maxScale / 120 );+ wl_surface_attach( s_cursorSurf, wl_cursor_image_get_buffer( cursor->images[0] ), 0, 0 );+ wl_surface_commit( s_cursorSurf );+ s_cursorX = cursor->images[0]->hotspot_x * 120 / s_maxScale;+ s_cursorY = cursor->images[0]->hotspot_y * 120 / s_maxScale;+}++static void SetClipboard( void*, const char* text )+{+ s_clipboard = text;++ if( s_dataSource ) wl_data_source_destroy( s_dataSource );+ s_dataSource = wl_data_device_manager_create_data_source( s_dataDevMgr );+ wl_data_source_add_listener( s_dataSource, &dataSourceListener, nullptr );+ wl_data_source_offer( s_dataSource, "text/plain" );+ wl_data_device_set_selection( s_dataDev, s_dataSource, s_dataSerial );+}++static const char* GetClipboard( void* )+{+ if( !s_dataOffer ) return nullptr;+ int fd[2];+ if( pipe( fd ) != 0 ) return nullptr;+ wl_data_offer_receive( s_dataOffer, "text/plain", fd[1] );+ close( fd[1] );+ wl_display_roundtrip( s_dpy );++ s_clipboardIncoming.clear();+ char buf[4096];+ while( true )+ {+ auto len = read( fd[0], buf, sizeof( buf ) );+ if( len <= 0 ) break;+ s_clipboardIncoming.append( buf, len );+ }++ close( fd[0] );+ return s_clipboardIncoming.c_str();+}++Backend::Backend( const char* title, const std::function<void()>& redraw, const std::function<void(float)>& scaleChanged, const std::function<int(void)>& isBusy, RunQueue* mainThreadTasks )+{+ s_redraw = redraw;+ s_scaleChanged = scaleChanged;+ s_isBusy = isBusy;+ s_mainThreadTasks = mainThreadTasks;++ s_prevWidth = s_width = m_winPos.w;+ s_prevHeight = s_height = m_winPos.h;+ s_maximized = m_winPos.maximize;++ s_dpy = wl_display_connect( nullptr );+ if( !s_dpy ) { fprintf( stderr, "Cannot establish wayland display connection!\n" ); exit( 1 ); }++ wl_registry_add_listener( wl_display_get_registry( s_dpy ), ®istryListener, nullptr );+ s_xkbCtx = xkb_context_new( XKB_CONTEXT_NO_FLAGS );+ wl_display_roundtrip( s_dpy );++ if( !s_comp ) { fprintf( stderr, "No wayland compositor!\n" ); exit( 1 ); }+ if( !s_shm ) { fprintf( stderr, "No wayland shared memory!\n" ); exit( 1 ); }+ if( !s_wm ) { fprintf( stderr, "No wayland window manager!\n" ); exit( 1 ); }+ if( !s_seat ) { fprintf( stderr, "No wayland seat!\n" ); exit( 1 ); }++ s_surf = wl_compositor_create_surface( s_comp );+ wl_surface_add_listener( s_surf, &surfaceListener, nullptr );+ s_eglWin = wl_egl_window_create( s_surf, m_winPos.w, m_winPos.h );+ s_xdgSurf = xdg_wm_base_get_xdg_surface( s_wm, s_surf );+ xdg_surface_add_listener( s_xdgSurf, &xdgSurfaceListener, nullptr );++ if( s_fractionalScale && s_viewporter )+ {+ s_fracSurf = wp_fractional_scale_manager_v1_get_fractional_scale( s_fractionalScale, s_surf );+ wp_fractional_scale_v1_add_listener( s_fracSurf, &fractionalListener, nullptr );+ s_viewport = wp_viewporter_get_viewport( s_viewporter, s_surf );+ }++ SetupCursor();++ constexpr EGLint eglConfigAttrib[] = {+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,+ EGL_RED_SIZE, 8,+ EGL_GREEN_SIZE, 8,+ EGL_BLUE_SIZE, 8,+ EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,+ EGL_NONE+ };++ s_eglDpy = eglGetPlatformDisplay( EGL_PLATFORM_WAYLAND_KHR, s_dpy, nullptr );+ EGLBoolean res;+ res = eglInitialize( s_eglDpy, nullptr, nullptr );+ if( res != EGL_TRUE ) { fprintf( stderr, "Cannot initialize EGL!\n" ); exit( 1 ); }++ EGLint count;+ EGLConfig eglConfig;+ res = eglChooseConfig( s_eglDpy, eglConfigAttrib, &eglConfig, 1, &count );+ if( res != EGL_TRUE || count != 1 ) { fprintf( stderr, "No suitable EGL config found!\n" ); exit( 1 ); }++ res = eglBindAPI( EGL_OPENGL_API );+ if( res != EGL_TRUE ) { fprintf( stderr, "Cannot use OpenGL through EGL!\n" ); exit( 1 ); }++ s_eglSurf = eglCreatePlatformWindowSurface( s_eglDpy, eglConfig, s_eglWin, nullptr );++ constexpr EGLint eglCtxAttrib[] = {+ EGL_CONTEXT_MAJOR_VERSION, 3,+ EGL_CONTEXT_MINOR_VERSION, 2,+ EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,+ EGL_NONE+ };++ s_eglCtx = eglCreateContext( s_eglDpy, eglConfig, EGL_NO_CONTEXT, eglCtxAttrib );+ if( !s_eglCtx ) { fprintf( stderr, "Cannot create OpenGL 3.2 Core Profile context!\n" ); exit( 1 ); }+ res = eglMakeCurrent( s_eglDpy, s_eglSurf, s_eglSurf, s_eglCtx );+ if( res != EGL_TRUE ) { fprintf( stderr, "Cannot make EGL context current!\n" ); exit( 1 ); }++ ImGui_ImplOpenGL3_Init( "#version 150" );++ wl_display_roundtrip( s_dpy );+ s_toplevel = xdg_surface_get_toplevel( s_xdgSurf );+ xdg_toplevel_add_listener( s_toplevel, &toplevelListener, nullptr );+ xdg_toplevel_set_title( s_toplevel, title );+ xdg_toplevel_set_app_id( s_toplevel, "tracy" );++ if( s_activation )+ {+ const char* token = getenv( "XDG_ACTIVATION_TOKEN" );+ if( token )+ {+ xdg_activation_v1_activate( s_activation, token, s_surf );+ unsetenv( "XDG_ACTIVATION_TOKEN" );+ }+ }++ if( s_decoration )+ {+ s_tldec = zxdg_decoration_manager_v1_get_toplevel_decoration( s_decoration, s_toplevel );+ zxdg_toplevel_decoration_v1_add_listener( s_tldec, &decorationListener, nullptr );+ zxdg_toplevel_decoration_v1_set_mode( s_tldec, ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE );+ wl_display_roundtrip( s_dpy );+ }++ ImGuiIO& io = ImGui::GetIO();+ io.BackendPlatformName = "wayland (tracy profiler)";++ if( s_dataDevMgr )+ {+ s_dataDev = wl_data_device_manager_get_data_device( s_dataDevMgr, s_seat );+ wl_data_device_add_listener( s_dataDev, &dataDeviceListener, nullptr );++ io.SetClipboardTextFn = SetClipboard;+ io.GetClipboardTextFn = GetClipboard;+ }++ s_time = std::chrono::duration_cast<std::chrono::microseconds>( std::chrono::high_resolution_clock::now().time_since_epoch() ).count();+}++Backend::~Backend()+{+ ImGui_ImplOpenGL3_Shutdown();++ if( s_iconMgr ) xdg_toplevel_icon_manager_v1_destroy( s_iconMgr );+ if( s_dataOffer ) wl_data_offer_destroy( s_dataOffer );+ if( s_dataSource ) wl_data_source_destroy( s_dataSource );+ if( s_dataDev ) wl_data_device_destroy( s_dataDev );+ if( s_dataDevMgr ) wl_data_device_manager_destroy( s_dataDevMgr );+ if( s_cursorShapeDev ) wp_cursor_shape_device_v1_destroy( s_cursorShapeDev );+ if( s_cursorShape ) wp_cursor_shape_manager_v1_destroy( s_cursorShape );+ if( s_viewport ) wp_viewport_destroy( s_viewport );+ if( s_fracSurf ) wp_fractional_scale_v1_destroy( s_fracSurf );+ if( s_viewporter ) wp_viewporter_destroy( s_viewporter );+ if( s_fractionalScale ) wp_fractional_scale_manager_v1_destroy( s_fractionalScale );+ if( s_tldec ) zxdg_toplevel_decoration_v1_destroy( s_tldec );+ if( s_decoration ) zxdg_decoration_manager_v1_destroy( s_decoration );+ if( s_actToken ) xdg_activation_token_v1_destroy( s_actToken );+ if( s_activation ) xdg_activation_v1_destroy( s_activation );+ if( s_keyboard ) wl_keyboard_destroy( s_keyboard );+ if( s_pointer ) wl_pointer_destroy( s_pointer );+ eglMakeCurrent( s_eglDpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );+ eglDestroySurface( s_eglDpy, s_eglSurf );+ eglDestroyContext( s_eglDpy, s_eglCtx );+ eglTerminate( s_eglDpy );+ xdg_toplevel_destroy( s_toplevel );+ if( s_cursorSurf ) wl_surface_destroy( s_cursorSurf );+ if( s_cursorTheme ) wl_cursor_theme_destroy( s_cursorTheme );+ xdg_surface_destroy( s_xdgSurf );+ wl_egl_window_destroy( s_eglWin );+ wl_surface_destroy( s_surf );+ for( auto& v : s_output ) wl_output_destroy( v.second->obj );+ s_output.clear();+ wl_seat_destroy( s_seat );+ xdg_wm_base_destroy( s_wm );+ wl_shm_destroy( s_shm );+ wl_compositor_destroy( s_comp );+ if( s_xkbComposeState ) xkb_compose_state_unref( s_xkbComposeState );+ if( s_xkbComposeTable ) xkb_compose_table_unref( s_xkbComposeTable );+ if( s_xkbState ) xkb_state_unref( s_xkbState );+ if( s_xkbKeymap ) xkb_keymap_unref( s_xkbKeymap );+ xkb_context_unref( s_xkbCtx );+ wl_display_disconnect( s_dpy );+}++void Backend::Show()+{+ wl_surface_commit( s_surf );+}++void Backend::Run()+{+ while( s_running && wl_display_dispatch( s_dpy ) != -1 )+ {+ if( s_config.focusLostLimit && !s_hasFocus ) std::this_thread::sleep_for( std::chrono::milliseconds( 50 ) );+ s_redraw();+ s_mainThreadTasks->Run();+ }+}+++static void TokenDone( void*, xdg_activation_token_v1* token, const char* str )+{+ xdg_activation_v1_activate( s_activation, str, s_surf );+ xdg_activation_token_v1_destroy( token );+ s_actToken = nullptr;+}++constexpr struct xdg_activation_token_v1_listener tokenListener = {+ .done = TokenDone+}; +++void Backend::Attention()+{+ if( !s_activation ) return;+ if( s_actToken ) return;+ s_actToken = xdg_activation_v1_get_activation_token( s_activation );+ xdg_activation_token_v1_set_surface( s_actToken, s_surf );+ xdg_activation_token_v1_commit( s_actToken );+ xdg_activation_token_v1_add_listener( s_actToken, &tokenListener, nullptr );+}++void Backend::NewFrame( int& w, int& h )+{+ if( s_prevWidth != s_width || s_prevHeight != s_height || s_prevScale != s_maxScale )+ {+ s_prevWidth = s_width;+ s_prevHeight = s_height;+ wl_egl_window_resize( s_eglWin, s_width * s_maxScale / 120, s_height * s_maxScale / 120, 0, 0 );+ if( s_fracSurf )+ {+ wp_viewport_set_source( s_viewport, 0, 0, wl_fixed_from_double( s_width * s_maxScale / 120. ), wl_fixed_from_double( s_height * s_maxScale / 120. ) );+ wp_viewport_set_destination( s_viewport, s_width, s_height );+ }+ }++ if( s_prevScale != s_maxScale )+ {+ s_scaleChanged( s_maxScale / 120.f );+ SetupCursor();+ if( !s_fracSurf ) wl_surface_set_buffer_scale( s_surf, s_maxScale / 120 );+ s_prevScale = s_maxScale;+ }++ m_winPos.maximize = s_maximized;+ if( !s_maximized )+ {+ m_winPos.w = s_width;+ m_winPos.h = s_height;+ }++ w = s_width * s_maxScale / 120;+ h = s_height * s_maxScale / 120;++ ImGuiIO& io = ImGui::GetIO();+ io.DisplaySize = ImVec2( w, h );+ io.DisplayFramebufferScale = ImVec2( 1, 1 );++ ImGui_ImplOpenGL3_NewFrame();++ uint64_t time = std::chrono::duration_cast<std::chrono::microseconds>( std::chrono::high_resolution_clock::now().time_since_epoch() ).count();+ io.DeltaTime = std::min( 0.1f, ( time - s_time ) / 1000000.f );+ s_time = time;++ if( s_cursorShapeDev )+ {+ ImGuiMouseCursor cursor = ImGui::GetMouseCursor();+ wp_cursor_shape_device_v1_shape shape;++ switch( cursor )+ {+ case ImGuiMouseCursor_None:+ shape = (wp_cursor_shape_device_v1_shape)0;+ break;+ case ImGuiMouseCursor_Arrow:+ switch( s_isBusy() )+ {+ default:+ case 0:+ shape = WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT;+ break;+ case 1:+ shape = WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_PROGRESS;+ break;+ case 2:+ shape = WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_WAIT;+ break;+ }+ break;+ case ImGuiMouseCursor_TextInput:+ shape = WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_TEXT;+ break;+ case ImGuiMouseCursor_ResizeNS:+ shape = WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NS_RESIZE;+ break;+ case ImGuiMouseCursor_ResizeEW:+ shape = WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_EW_RESIZE;+ break;+ case ImGuiMouseCursor_ResizeNESW:+ shape = WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NESW_RESIZE;+ break;+ case ImGuiMouseCursor_ResizeNWSE:+ shape = WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NWSE_RESIZE;+ break;+ case ImGuiMouseCursor_NotAllowed:+ shape = WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NOT_ALLOWED;+ break;+ default:+ shape = WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT;+ break;+ };++ if( shape != s_mouseCursor )+ {+ s_mouseCursor = shape;+ if( shape == 0 )+ {+ wl_pointer_set_cursor( s_pointer, s_mouseCursorSerial, nullptr, 0, 0 );+ }+ else+ {+ wp_cursor_shape_device_v1_set_shape( s_cursorShapeDev, s_mouseCursorSerial, shape );+ }+ }+ }+}++void Backend::EndFrame()+{+ const ImVec4 clear_color = ImColor( 20, 20, 17 );++ ImGui::Render();+ glViewport( 0, 0, s_width * s_maxScale / 120, s_height * s_maxScale / 120 );+ glClearColor( clear_color.x, clear_color.y, clear_color.z, clear_color.w );+ glClear( GL_COLOR_BUFFER_BIT );+ ImGui_ImplOpenGL3_RenderDrawData( ImGui::GetDrawData() );++ eglSwapBuffers( s_eglDpy, s_eglSurf );+}++void Backend::SetIcon( uint8_t* data, int w, int h )+{+ if( !s_iconMgr ) return;+ if( s_iconSizes.empty() ) return;++ size_t size = 0;+ for( auto sz : s_iconSizes )+ {+ size += sz * sz;+ }+ size *= 4;++ auto path = getenv( "XDG_RUNTIME_DIR" );+ if( !path ) return;++ std::string shmPath = path;+ shmPath += "/tracy_icon-XXXXXX";+ int fd = mkstemp( shmPath.data() );+ if( fd < 0 ) return;+ unlink( shmPath.data() );+ ftruncate( fd, size );+ auto membuf = (char*)mmap( nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );+ if( membuf == MAP_FAILED )+ {+ close( fd );+ return;+ }++ auto pool = wl_shm_create_pool( s_shm, fd, size );+ close( fd );+ auto icon = xdg_toplevel_icon_manager_v1_create_icon( s_iconMgr );++ auto rgb = new uint32_t[w * h];+ auto bgr = (uint32_t*)data;+ for( int i=0; i<w*h; i++ )+ {+ rgb[i] = ( bgr[i] & 0xff00ff00 ) | ( ( bgr[i] & 0xff ) << 16 ) | ( ( bgr[i] >> 16 ) & 0xff );+ }++ std::vector<wl_buffer*> bufs;+ int32_t offset = 0;+ for( auto sz : s_iconSizes )+ {+ auto buffer = wl_shm_pool_create_buffer( pool, offset, sz, sz, sz * 4, WL_SHM_FORMAT_ARGB8888 );+ bufs.push_back( buffer );++ auto ptr = membuf + offset;+ offset += sz * sz * 4;++ stbir_resize_uint8( (uint8_t*)rgb, w, h, 0, (uint8_t*)ptr, sz, sz, 0, 4 );+ xdg_toplevel_icon_v1_add_buffer( icon, buffer, sz );+ }++ xdg_toplevel_icon_manager_v1_set_icon( s_iconMgr, s_toplevel, icon );+ xdg_toplevel_icon_v1_destroy( icon );+ for( auto buf : bufs ) wl_buffer_destroy( buf );+ munmap( membuf, size );+ wl_shm_pool_destroy( pool );+}++void Backend::SetTitle( const char* title )+{+ xdg_toplevel_set_title( s_toplevel, title );+}++float Backend::GetDpiScale()+{+ return s_maxScale / 120.f;+}
+ cbits/tracy/profiler/src/ConnectionHistory.cpp view
@@ -0,0 +1,87 @@+#include <assert.h>+#include <stdint.h>+#include <stdio.h>++#include "ConnectionHistory.hpp"++#include "../../server/tracy_pdqsort.h"+#include "profiler/TracyStorage.hpp"+++ConnectionHistory::ConnectionHistory()+ : m_fn( tracy::GetSavePath( "connection.history" ) )+{+ FILE* f = fopen( m_fn.c_str(), "rb" );+ if( !f ) return;++ uint64_t sz;+ if( fread( &sz, 1, sizeof( sz ), f ) != sizeof( sz ) ) goto err;+ for( uint64_t i=0; i<sz; i++ )+ {+ uint64_t ssz, cnt;+ if( fread( &ssz, 1, sizeof( ssz ), f ) != sizeof( ssz ) ) goto err;+ if( ssz >= 1024 ) goto err;+ char tmp[1024];+ if( fread( tmp, 1, ssz, f ) != ssz ) goto err;+ if( fread( &cnt, 1, sizeof( cnt ), f ) != sizeof( cnt ) ) goto err;+ m_connHistMap.emplace( std::string( tmp, tmp+ssz ), cnt );+ }+ fclose( f );++ Rebuild();+ return;++err:+ fclose( f );+ m_connHistMap.clear();+}++ConnectionHistory::~ConnectionHistory()+{+ FILE* f = fopen( m_fn.c_str(), "wb" );+ if( !f ) return;++ uint64_t sz = uint64_t( m_connHistMap.size() );+ fwrite( &sz, 1, sizeof( uint64_t ), f );+ for( auto& v : m_connHistMap )+ {+ sz = uint64_t( v.first.size() );+ fwrite( &sz, 1, sizeof( uint64_t ), f );+ fwrite( v.first.c_str(), 1, sz, f );+ fwrite( &v.second, 1, sizeof( v.second ), f );+ }+ fclose( f );+}++void ConnectionHistory::Rebuild()+{+ std::vector<std::unordered_map<std::string, uint64_t>::const_iterator> vec;+ vec.reserve( m_connHistMap.size() );+ for( auto it = m_connHistMap.begin(); it != m_connHistMap.end(); ++it )+ {+ vec.emplace_back( it );+ }+ tracy::pdqsort_branchless( vec.begin(), vec.end(), []( const auto& lhs, const auto& rhs ) { return lhs->second > rhs->second; } );+ std::swap( m_connHistVec, vec );+}++void ConnectionHistory::Count( const std::string& name )+{+ auto it = m_connHistMap.find( name );+ if( it != m_connHistMap.end() )+ {+ it->second++;+ }+ else+ {+ m_connHistMap.emplace( name, 1 );+ }+ Rebuild();+}++void ConnectionHistory::Erase( size_t idx )+{+ assert( idx < m_connHistVec.size() );+ m_connHistMap.erase( m_connHistVec[idx] );+ Rebuild();+}
+ cbits/tracy/profiler/src/ConnectionHistory.hpp view
@@ -0,0 +1,32 @@+#ifndef __CONNECTIONHISTORY_HPP__+#define __CONNECTIONHISTORY_HPP__++#include <stdint.h>+#include <string>+#include <unordered_map>+#include <vector>++class ConnectionHistory+{+public:+ ConnectionHistory();+ ~ConnectionHistory();++ const std::string& Name( size_t idx ) const { return m_connHistVec[idx]->first; }++ void Count( const std::string& name );+ void Erase( size_t idx );++ bool empty() const { return m_connHistVec.empty(); }+ size_t size() const { return m_connHistVec.size(); }++private:+ void Rebuild();++ std::string m_fn;++ std::unordered_map<std::string, uint64_t> m_connHistMap;+ std::vector<std::unordered_map<std::string, uint64_t>::const_iterator> m_connHistVec;+};++#endif
+ cbits/tracy/profiler/src/Filters.cpp view
@@ -0,0 +1,87 @@+#include <inttypes.h>+#include <stdint.h>+#include <stdio.h>++#include "Filters.hpp"++#include "profiler/TracyStorage.hpp"+++Filters::Filters()+ : m_fn( tracy::GetSavePath( "client.filters" ) )+{+ FILE* f = fopen( m_fn.c_str(), "rb" );+ if( !f ) return;++ uint8_t sz;+ fread( &sz, 1, sizeof( sz ), f );+ fread( m_addrFilter.InputBuf, 1, sz, f );+ m_addrFilter.Build();++ fread( &sz, 1, sizeof( sz ), f );+ fread( m_portFilter.InputBuf, 1, sz, f );+ m_portFilter.Build();++ fread( &sz, 1, sizeof( sz ), f );+ fread( m_progFilter.InputBuf, 1, sz, f );+ m_progFilter.Build();++ fclose( f );+}++Filters::~Filters()+{+ FILE* f = fopen( m_fn.c_str(), "wb" );+ if( !f ) return;++ uint8_t sz = (uint8_t)strlen( m_addrFilter.InputBuf );+ fwrite( &sz, 1, sizeof( sz ), f );+ fwrite( m_addrFilter.InputBuf, 1, sz, f );++ sz = (uint8_t)strlen( m_portFilter.InputBuf );+ fwrite( &sz, 1, sizeof( sz ), f );+ fwrite( m_portFilter.InputBuf, 1, sz, f );++ sz = (uint8_t)strlen( m_progFilter.InputBuf );+ fwrite( &sz, 1, sizeof( sz ), f );+ fwrite( m_progFilter.InputBuf, 1, sz, f );++ fclose( f );+}++void Filters::Clear()+{+ m_addrFilter.Clear();+ m_portFilter.Clear();+ m_progFilter.Clear();+}++void Filters::Draw( float w )+{+ m_addrFilter.Draw( "Address filter", w );+ m_portFilter.Draw( "Port filter", w );+ m_progFilter.Draw( "Program filter", w );+}++bool Filters::IsActive() const+{+ return m_addrFilter.IsActive() || m_portFilter.IsActive() || m_progFilter.IsActive();+}++bool Filters::FailAddr( const char* addr )+{+ return m_addrFilter.IsActive() && !m_addrFilter.PassFilter( addr );+}++bool Filters::FailPort( uint16_t port )+{+ if( !m_portFilter.IsActive() ) return false;+ char buf[32];+ sprintf( buf, "%" PRIu16, port );+ return !m_portFilter.PassFilter( buf );+}++bool Filters::FailProg( const char* prog )+{+ return m_progFilter.IsActive() && !m_progFilter.PassFilter( prog );+}
+ cbits/tracy/profiler/src/Filters.hpp view
@@ -0,0 +1,28 @@+#ifndef __FILTERS_HPP__+#define __FILTERS_HPP__++#include <imgui.h>+#include <string>++class Filters+{+public:+ Filters();+ ~Filters();++ void Clear();+ void Draw( float w );++ bool IsActive() const;++ bool FailAddr( const char* addr );+ bool FailPort( uint16_t port );+ bool FailProg( const char* prog );++private:+ std::string m_fn;++ ImGuiTextFilter m_addrFilter, m_portFilter, m_progFilter;+};++#endif
+ cbits/tracy/profiler/src/Fonts.cpp view
@@ -0,0 +1,59 @@+#include <imgui.h>+#include <math.h>+#include <backends/imgui_impl_opengl3.h>+#include <misc/freetype/imgui_freetype.h>++#include "Fonts.hpp"+#include "profiler/IconsFontAwesome6.h"++#include "font/DroidSans.hpp"+#include "font/FiraCodeRetina.hpp"+#include "font/FontAwesomeSolid.hpp"++ImFont* s_bigFont;+ImFont* s_smallFont;+ImFont* s_fixedWidth;++void LoadFonts( float scale )+{+ static const ImWchar rangesBasic[] = {+ 0x0020, 0x00FF, // Basic Latin + Latin Supplement+ 0x03BC, 0x03BC, // micro+ 0x03C3, 0x03C3, // small sigma+ 0x2013, 0x2013, // en dash+ 0x2026, 0x2026, // ellipsis+ 0x2264, 0x2264, // less-than or equal to+ 0,+ };+ static const ImWchar rangesIcons[] = {+ ICON_MIN_FA, ICON_MAX_FA,+ 0+ };+ static const ImWchar rangesFixed[] = {+ 0x0020, 0x00FF, // Basic Latin + Latin Supplement+ 0x2026, 0x2026, // ellipsis+ 0+ };++ ImGuiIO& io = ImGui::GetIO();++ ImFontConfig configBasic;+ configBasic.FontBuilderFlags = ImGuiFreeTypeBuilderFlags_LightHinting;+ ImFontConfig configMerge;+ configMerge.MergeMode = true;+ configMerge.FontBuilderFlags = ImGuiFreeTypeBuilderFlags_LightHinting;+ ImFontConfig configFixed;+ configFixed.FontBuilderFlags = ImGuiFreeTypeBuilderFlags_LightHinting;+ configFixed.GlyphExtraAdvanceX = -1;++ io.Fonts->Clear();+ io.Fonts->AddFontFromMemoryCompressedTTF( tracy::DroidSans_compressed_data, tracy::DroidSans_compressed_size, round( 15.0f * scale ), &configBasic, rangesBasic );+ io.Fonts->AddFontFromMemoryCompressedTTF( tracy::FontAwesomeSolid_compressed_data, tracy::FontAwesomeSolid_compressed_size, round( 14.0f * scale ), &configMerge, rangesIcons );+ s_fixedWidth = io.Fonts->AddFontFromMemoryCompressedTTF( tracy::FiraCodeRetina_compressed_data, tracy::FiraCodeRetina_compressed_size, round( 15.0f * scale ), &configFixed, rangesFixed );+ s_bigFont = io.Fonts->AddFontFromMemoryCompressedTTF( tracy::DroidSans_compressed_data, tracy::DroidSans_compressed_size, round( 21.0f * scale ), &configBasic );+ io.Fonts->AddFontFromMemoryCompressedTTF( tracy::FontAwesomeSolid_compressed_data, tracy::FontAwesomeSolid_compressed_size, round( 20.0f * scale ), &configMerge, rangesIcons );+ s_smallFont = io.Fonts->AddFontFromMemoryCompressedTTF( tracy::DroidSans_compressed_data, tracy::DroidSans_compressed_size, round( 10.0f * scale ), &configBasic );++ ImGui_ImplOpenGL3_DestroyFontsTexture();+ ImGui_ImplOpenGL3_CreateFontsTexture();+}
+ cbits/tracy/profiler/src/Fonts.hpp view
@@ -0,0 +1,12 @@+#ifndef __FONTS_HPP__+#define __FONTS_HPP__++struct ImFont;++extern ImFont* s_bigFont;+extern ImFont* s_smallFont;+extern ImFont* s_fixedWidth;++void LoadFonts( float scale );++#endif
+ cbits/tracy/profiler/src/HttpRequest.cpp view
@@ -0,0 +1,134 @@+#include <assert.h>+#include <stdio.h>+#include <stdlib.h>+#include <string.h>++#include "../public/common/TracySocket.hpp"+#include "../public/common/TracyVersion.hpp"+#include "GitRef.hpp"+#include "HttpRequest.hpp"++#if defined _WIN32+# include <windows.h>+extern "C" typedef LONG (WINAPI *t_RtlGetVersion)( PRTL_OSVERSIONINFOW );+extern "C" typedef char* (WINAPI *t_WineGetVersion)();+extern "C" typedef char* (WINAPI *t_WineGetBuildId)();+#elif defined __linux__+# include <sys/utsname.h>+#elif defined __APPLE__+# include "TargetConditionals.h"+#endif++static constexpr char CRLF[2] = { '\r', '\n' };++static const char* GetOsInfo()+{+ static char buf[1024];+#if defined _WIN32+ t_RtlGetVersion RtlGetVersion = (t_RtlGetVersion)GetProcAddress( GetModuleHandleA( "ntdll.dll" ), "RtlGetVersion" );+ if( !RtlGetVersion )+ {+# ifdef __MINGW32__+ sprintf( buf, "Windows (MingW)" );+# else+ sprintf( buf, "Windows" );+# endif+ }+ else+ {+ RTL_OSVERSIONINFOW ver = { sizeof( RTL_OSVERSIONINFOW ) };+ RtlGetVersion( &ver );++# ifdef __MINGW32__+ sprintf( buf, "Windows %i.%i.%i (MingW)", (int)ver.dwMajorVersion, (int)ver.dwMinorVersion, (int)ver.dwBuildNumber );+# else+ auto WineGetVersion = (t_WineGetVersion)GetProcAddress( GetModuleHandleA( "ntdll.dll" ), "wine_get_version" );+ auto WineGetBuildId = (t_WineGetBuildId)GetProcAddress( GetModuleHandleA( "ntdll.dll" ), "wine_get_build_id" );+ if( WineGetVersion && WineGetBuildId )+ {+ sprintf( buf, "Windows %i.%i.%i (Wine %s [%s])", ver.dwMajorVersion, ver.dwMinorVersion, ver.dwBuildNumber, WineGetVersion(), WineGetBuildId() );+ }+ else+ {+ sprintf( buf, "Windows %i.%i.%i", ver.dwMajorVersion, ver.dwMinorVersion, ver.dwBuildNumber );+ }+# endif+ }+#elif defined __linux__+ struct utsname utsName;+ uname( &utsName );+# if defined __ANDROID__+ sprintf( buf, "Linux %s (Android)", utsName.release );+# else+ sprintf( buf, "Linux %s", utsName.release );+# endif+#elif defined __APPLE__+# if TARGET_OS_IPHONE == 1+ sprintf( buf, "Darwin (iOS)" );+# elif TARGET_OS_MAC == 1+ sprintf( buf, "Darwin (OSX)" );+# else+ sprintf( buf, "Darwin (unknown)" );+# endif+#elif defined __DragonFly__+ sprintf( buf, "BSD (DragonFly)" );+#elif defined __FreeBSD__+ sprintf( buf, "BSD (FreeBSD)" );+#elif defined __NetBSD__+ sprintf( buf, "BSD (NetBSD)" );+#elif defined __OpenBSD__+ sprintf( buf, "BSD (OpenBSD)" );+#elif defined __QNX__+ sprintf( buf, "QNX" );+#else+ sprintf( buf, "unknown" );+#endif+ return buf;+}++void HttpRequest( const char* server, const char* resource, int port, const std::function<void(int, char*)>& cb )+{+ tracy::Socket sock;+ if( !sock.ConnectBlocking( server, port ) ) return;+ char request[4096];+ const auto len = sprintf( request, "GET %s HTTP/1.1\r\nHost: %s\r\nUser-Agent: Tracy Profiler %i.%i.%i (%s) [%s]\r\nConnection: close\r\nCache-Control: no-cache, no-store, must-revalidate\r\n\r\n", resource, server, tracy::Version::Major, tracy::Version::Minor, tracy::Version::Patch, GetOsInfo(), tracy::GitRef );+ sock.Send( request, len );+ char response[4096];+ const auto sz = sock.ReadUpTo( response, 4096 );+ if( sz < 13 ) return;+ if( memcmp( response, "HTTP/1.1 200", 12 ) != 0 ) return;+ auto hdr = response + 13;+ int contentLength = 0;+ for(;;)+ {+ while( memcmp( hdr, CRLF, 2 ) != 0 ) hdr++;+ hdr += 2;+ if( memcmp( hdr, "Content-Length: ", 16 ) == 0 )+ {+ hdr += 16;+ contentLength = atoi( hdr );+ break;+ }+ }+ assert( contentLength != 0 );+ for(;;)+ {+ while( memcmp( hdr, CRLF, 2 ) != 0 ) hdr++;+ hdr += 2;+ if( memcmp( hdr, CRLF, 2 ) == 0 )+ {+ hdr += 2;+ break;+ }+ hdr += 2;+ }++ const auto hdrSize = hdr - response;+ const auto partSize = sz - hdrSize;+ char* data = new char[contentLength];+ memcpy( data, hdr, partSize );+ auto remaining = contentLength - partSize;+ if( remaining > 0 ) sock.Read( data + partSize, remaining, 15 );++ cb( contentLength, data );+}
+ cbits/tracy/profiler/src/HttpRequest.hpp view
@@ -0,0 +1,8 @@+#ifndef __HTTPREQUEST_HPP__+#define __HTTPREQUEST_HPP__++#include <functional>++void HttpRequest( const char* server, const char* resource, int port, const std::function<void(int, char*)>& cb );++#endif
+ cbits/tracy/profiler/src/ImGuiContext.cpp view
@@ -0,0 +1,20 @@+#include <imgui.h>+#include "profiler/TracyStorage.hpp"+#include "ImGuiContext.hpp"++ImGuiTracyContext::ImGuiTracyContext()+ : m_iniFilename( tracy::GetSavePath( "imgui.ini" ) )+{+ IMGUI_CHECKVERSION();+ ImGui::CreateContext();+ ImGuiIO& io = ImGui::GetIO();+ io.IniFilename = m_iniFilename.c_str();+ io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard | ImGuiConfigFlags_DockingEnable;+ io.ConfigInputTextCursorBlink = false;+ io.ConfigScrollbarScrollByPage = false;+}++ImGuiTracyContext::~ImGuiTracyContext()+{+ ImGui::DestroyContext();+}
+ cbits/tracy/profiler/src/ImGuiContext.hpp view
@@ -0,0 +1,16 @@+#ifndef __IMGUICONTEXT_HPP__+#define __IMGUICONTEXT_HPP__++#include <string>++class ImGuiTracyContext+{+public:+ ImGuiTracyContext();+ ~ImGuiTracyContext();++private:+ std::string m_iniFilename;+};++#endif
+ cbits/tracy/profiler/src/IsElevated.cpp view
@@ -0,0 +1,41 @@+#include "IsElevated.hpp"++#ifdef _WIN32++#include <windows.h>++bool IsElevated()+{+ HANDLE token;+ if( OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &token ) == 0 ) return false;++ TOKEN_ELEVATION te;+ DWORD sz;+ if( GetTokenInformation( token, TokenElevation, &te, sizeof( te ), &sz ) == 0 )+ {+ CloseHandle( token );+ return false;+ }++ bool ret = te.TokenIsElevated;+ CloseHandle( token );+ return ret;+}++#elif defined __EMSCRIPTEN__++bool IsElevated()+{+ return false;+}++#else++#include <unistd.h>++bool IsElevated()+{+ return getuid() == 0;+}++#endif
+ cbits/tracy/profiler/src/IsElevated.hpp view
@@ -0,0 +1,6 @@+#ifndef __ISELEVATED_HPP__+#define __ISELEVATED_HPP__++bool IsElevated();++#endif
+ cbits/tracy/profiler/src/ResolvService.cpp view
@@ -0,0 +1,65 @@+#ifdef _WIN32+# include <ws2tcpip.h>+#else+# ifdef __FreeBSD__+# include <netinet/in.h>+# endif+# include <arpa/inet.h>+# include <sys/socket.h>+# include <netdb.h>+#endif++#include "ResolvService.hpp"++ResolvService::ResolvService( uint16_t port )+ : m_exit( false )+ , m_port( port )+#ifndef __EMSCRIPTEN__+ , m_thread( [this] { Worker(); } )+#endif+{+}++ResolvService::~ResolvService()+{+#ifndef __EMSCRIPTEN__+ m_exit.store( true, std::memory_order_relaxed );+ m_cv.notify_one();+ m_thread.join();+#endif+}++void ResolvService::Query( uint32_t ip, const std::function<void(std::string&&)>& callback )+{+#ifndef __EMSCRIPTEN__+ std::lock_guard<std::mutex> lock( m_lock );+ m_queue.emplace_back( QueueItem { ip, callback } );+ m_cv.notify_one();+#endif+}++void ResolvService::Worker()+{+ struct sockaddr_in addr = {};+ addr.sin_family = AF_INET;+ addr.sin_port = htons( m_port );++ char buf[128];++ for(;;)+ {+ std::unique_lock<std::mutex> lock( m_lock );+ m_cv.wait( lock, [this] { return !m_queue.empty() || m_exit.load( std::memory_order_relaxed ); } );+ if( m_exit.load( std::memory_order_relaxed ) ) return;+ auto query = m_queue.back();+ m_queue.pop_back();+ lock.unlock();++ addr.sin_addr.s_addr = query.ip;+ if( getnameinfo( (const struct sockaddr*)&addr, sizeof( sockaddr_in ), buf, 128, nullptr, 0, NI_NOFQDN ) != 0 )+ {+ inet_ntop( AF_INET, &query.ip, buf, 17 );+ }+ query.callback( buf );+ }+}
+ cbits/tracy/profiler/src/ResolvService.hpp view
@@ -0,0 +1,38 @@+#ifndef __RESOLVSERVICE_HPP__+#define __RESOLVSERVICE_HPP__++#include <atomic>+#include <condition_variable>+#include <functional>+#include <mutex>+#include <stdint.h>+#include <string>+#include <thread>+#include <vector>++class ResolvService+{+ struct QueueItem+ {+ uint32_t ip;+ std::function<void(std::string&&)> callback;+ };++public:+ ResolvService( uint16_t port );+ ~ResolvService();++ void Query( uint32_t ip, const std::function<void(std::string&&)>& callback );++private:+ void Worker();++ std::atomic<bool> m_exit;+ std::mutex m_lock;+ std::condition_variable m_cv;+ std::vector<QueueItem> m_queue;+ uint16_t m_port;+ std::thread m_thread;+};++#endif
+ cbits/tracy/profiler/src/RunQueue.cpp view
@@ -0,0 +1,31 @@+#include "RunQueue.hpp"++RunQueue::RunQueue()+ : m_mainThread( std::this_thread::get_id() )+{+}++void RunQueue::Queue( const std::function<void()>& cb, bool forceDelay )+{+ if( !forceDelay && std::this_thread::get_id() == m_mainThread )+ {+ cb();+ }+ else+ {+ std::lock_guard<std::mutex> lock( m_lock );+ m_queue.emplace_back( cb );+ }+}++void RunQueue::Run()+{+ std::unique_lock<std::mutex> lock( m_lock );+ if( !m_queue.empty() )+ {+ std::vector<std::function<void()>> tmp;+ std::swap( tmp, m_queue );+ lock.unlock();+ for( auto& cb : tmp ) cb();+ }+}
+ cbits/tracy/profiler/src/RunQueue.hpp view
@@ -0,0 +1,23 @@+#ifndef __RUNQUEUE_HPP__+#define __RUNQUEUE_HPP__++#include <functional>+#include <mutex>+#include <thread>+#include <vector>++class RunQueue+{+public:+ RunQueue();++ void Queue( const std::function<void()>& cb, bool forceDelay = false );+ void Run();++private:+ std::vector<std::function<void()>> m_queue;+ std::mutex m_lock;+ std::thread::id m_mainThread;+};++#endif
+ cbits/tracy/profiler/src/WindowPosition.cpp view
@@ -0,0 +1,48 @@+#include <stdint.h>+#include <stdio.h>++#include "WindowPosition.hpp"++#include "profiler/TracyStorage.hpp"+++WindowPosition::WindowPosition()+ : m_fn( tracy::GetSavePath( "window.position" ) )+{+ Defaults();++ FILE* f = fopen( m_fn.c_str(), "rb" );+ if( f )+ {+ uint32_t data[5];+ if( fread( data, 1, sizeof( data ), f ) == sizeof( data ) )+ {+ x = data[0];+ y = data[1];+ w = data[2];+ h = data[3];+ maximize = data[4];+ }+ fclose( f );++ if( w <= 0 || h <= 0 ) Defaults();+ }+}++WindowPosition::~WindowPosition()+{+ FILE* f = fopen( m_fn.c_str(), "wb" );+ if( !f ) return;+ uint32_t data[5] = { uint32_t( x ), uint32_t( y ), uint32_t( w ), uint32_t( h ), uint32_t( maximize ) };+ fwrite( data, 1, sizeof( data ), f );+ fclose( f );+}++void WindowPosition::Defaults()+{+ x = 200;+ y = 200;+ w = 1650;+ h = 960;+ maximize = 0;+}
+ cbits/tracy/profiler/src/WindowPosition.hpp view
@@ -0,0 +1,20 @@+#ifndef __WINDOWPOSITION_HPP__+#define __WINDOWPOSITION_HPP__++#include <string>++class WindowPosition+{+public:+ WindowPosition();+ ~WindowPosition();++ int x, y, w, h, maximize;++private:+ void Defaults();++ std::string m_fn;+};++#endif
+ cbits/tracy/profiler/src/font/DroidSans.hpp view
@@ -0,0 +1,2821 @@+namespace tracy+{++// File: 'DroidSans.ttf' (190776 bytes)+// Exported using binary_to_compressed_c.cpp+static const unsigned int DroidSans_compressed_size = 134868;+static const unsigned int DroidSans_compressed_data[134868/4] =+{+ 0x0000bc57, 0x00000000, 0x38e90200, 0x00000400, 0x00010025, 0x82130000, 0x00042e04, 0x45444730, 0x03260046, 0x3f02008a, 0x28158268, 0x4f50471e, + 0xad87f253, 0x300f82a7, 0xa9000088, 0x5553478e, 0x74916c42, 0xe902008f, 0x3c1f8218, 0x53544c20, 0xc49bd848, 0x1000003e, 0x0300002c, 0x2f534f89, + 0x95cba032, 0x0100008b, 0x081f82b8, 0x6d636038, 0x5e027061, 0x00008709, 0x0000d856, 0x76633608, 0x7e392074, 0x00004c3e, 0x00000469, 0x7066fc01, + 0xd3736d67, 0x0000b023, 0x0000105f, 0x61670507, 0x04007073, 0x6f820700, 0x3f825c20, 0x6c670c3b, 0x00966679, 0x000099a9, 0x01000c72, 0x64684ca9, + 0xa195786d, 0x0000af5b, 0x295f8213, 0x65682043, 0x29ef6461, 0x4b82cc74, 0x2f823c20, 0x82683621, 0x530c2310, 0x0f82a909, 0x0f827420, 0x6d68242b, + 0x9ee17874, 0x0000dd2e, 0x2caf8202, 0x6f6c140e, 0x4a5f6163, 0x00002eca, 0x291e826b, 0x616d0c07, 0x39067078, 0x2f828502, 0x10829820, 0x6e202c08, + 0xb5656d61, 0x0056905a, 0x00581b02, 0x70a20600, 0x9b74736f, 0x008c59ef, 0x00fc2102, 0x705d1d00, 0x82706572, 0x001321dc, 0x82186600, 0x00ec2253, + 0x82358201, 0x9fe32b03, 0x0f5f3c08, 0x1900f53c, 0x00830008, 0x339ac122, 0x002c0683, 0x9af67ec9, 0xd5fd89fb, 0x62085a09, 0x06221082, 0x2f820200, + 0x33820283, 0xfe6d072d, 0x0900001d, 0xfe89fb64, 0x845a09a2, 0x86198349, 0x85032103, 0x05821183, 0x1600a026, 0x05007a00, 0x102c3982, 0x5a002f00, + 0x2b020000, 0x03003901, 0x03241d82, 0x90019904, 0x08231982, 0x82059a05, 0x1e01216e, 0x03250785, 0x016600d0, 0x302782f2, 0x0306060b, 0x02020408, + 0x0200e004, 0x200040ef, 0x205a825b, 0x25038228, 0x53413100, 0x10820043, 0x06fdff2f, 0x0014fe1f, 0x016d0784, 0x010020e3, 0x231b839f, 0xb6054a04, + 0x20260782, 0xcd040200, 0x1184c100, 0x00001423, 0x3e038302, 0x03930027, 0x05850037, 0x0433002b, 0x067b0068, 0x0566009a, 0x016d009e, 0x028500cf, + 0x82520068, 0x823d2003, 0x82522017, 0x02662603, 0x023f0000, 0x26138293, 0x02930025, 0x821400fc, 0x82622013, 0x82b22003, 0x86602003, 0x82172023, + 0x82832007, 0x82712003, 0x825a2003, 0x836a2003, 0x83022003, 0x0025222f, 0x200b823f, 0x35038766, 0x25006803, 0x6d00ee06, 0x0000dd04, 0xc700f804, + 0x7d00d304, 0x07827905, 0xc7003928, 0xc700ee03, 0x0f828505, 0xc7009c24, 0x6f82b602, 0x48ff2b24, 0x1785a204, 0x82f60621, 0x82d5201b, 0x00f02303, + 0x1f82047d, 0x07830520, 0x3782b820, 0x68002730, 0x14002704, 0xb8009605, 0x00008b04, 0x9f821207, 0x5b826020, 0x03823720, 0x43825020, 0xa4006d22, + 0x1722b382, 0xe7826d02, 0x29004236, 0xfcff4a03, 0x89019e04, 0x5e003f04, 0xae00b004, 0x7100b403, 0x713a0782, 0x71004804, 0x1d00a202, 0x25002504, + 0xae00b604, 0xa0001202, 0xbcff1202, 0x0b84f803, 0x2b07ae24, 0x1783ae00, 0x849e0421, 0x83ae202f, 0x31032133, 0x9c223f82, 0xab825a00, 0x1b822120, + 0xd503a426, 0xf8050000, 0x00287f82, 0xe9032300, 0x87030a00, 0xd5287f82, 0x68043d00, 0xd502e901, 0x68227f82, 0x7b416600, 0x68042307, 0x0382bc00, + 0x03824420, 0x03827b20, 0x23831d20, 0x00e30323, 0x2b9b8279, 0x00a80633, 0x00a60264, 0x00e50344, 0x22057f41, 0x83520093, 0x00042613, 0x6d03faff, + 0x202f8300, 0x201f8266, 0x20038231, 0x24cb841f, 0x05ae00c1, 0x26bf823d, 0x01930025, 0x822300a4, 0x023f2417, 0x824200cd, 0x0554243f, 0x823f00e5, + 0x822c2003, 0x031f2803, 0x04440068, 0x930000dd, 0xd1062903, 0xd304feff, 0x39047d00, 0x87058b41, 0x20db8207, 0x2003823e, 0x20038252, 0x25038211, + 0x00790540, 0x8741052f, 0xf0052306, 0x038b7d00, 0x8d20c782, 0x96230f84, 0x8a05b800, 0x37042103, 0x9c207382, 0xd1265782, 0x3f04ae00, 0x03935e00, + 0x00aa0629, 0x00b4035e, 0x8d480471, 0x12022703, 0x1202deff, 0x0782ae00, 0x0382bd20, 0x9e04ee24, 0x87416f00, 0x829e2008, 0x22038b2b, 0x82660068, + 0x8273201f, 0x8ba4201f, 0xe9032703, 0xb0040a00, 0x0784ae00, 0x8383ff83, 0xfb82078f, 0x07967f84, 0xc720f782, 0x71204382, 0x2f200782, 0x04210783, + 0x83cf8239, 0x27079eab, 0x7d008505, 0x25002504, 0x9c200798, 0xb62e4782, 0x9c05ae00, 0xb6040000, 0xb6021200, 0xe782f5ff, 0xb602a324, 0x07823d00, + 0x0782eb20, 0x07823020, 0x0782de20, 0x12025224, 0x07864400, 0xe104ae24, 0x57825200, 0x2b02a024, 0x1f8248ff, 0xa204bc26, 0xf803c700, 0x0383e382, + 0xc700ee22, 0xab212b82, 0x20078503, 0x20078666, 0x200784ae, 0x22238266, 0x821d00ee, 0x05f62233, 0x8f7b86d5, 0xff462207, 0x201b88ff, 0x23bf82f0, + 0x0571009e, 0x0724078e, 0x077d001f, 0xb820ff83, 0x31237782, 0x8504ae00, 0x86602007, 0x04722807, 0x03680027, 0x9a5a009c, 0x82142007, 0x822120cb, + 0x27078c1f, 0xb8009605, 0xa400b604, 0x072f07a7, 0x05140012, 0x041400f8, 0x03000037, 0x830a00e9, 0x50042707, 0x87035200, 0x078f5200, 0x824c0221, + 0x006823a7, 0xfb4104cb, 0xd1062706, 0xaa06feff, 0xdb865e00, 0xab887320, 0x02019e23, 0x22038304, 0x821b0175, 0x02212407, 0x82a00012, 0x016d2407, + 0x841f007b, 0x009e2217, 0x200782df, 0x320382f8, 0xffdd0414, 0x002502e9, 0xffc90493, 0xff1706e7, 0x82b203e7, 0xff422407, 0x825405e7, 0xff4a2607, + 0xff9e02e7, 0x206f84e4, 0x05c744f8, 0x008b0427, 0x00390425, 0x209b83c7, 0x06c74405, 0x82b60221, 0x82a220ab, 0x008b2213, 0x07e74400, 0x003f0423, + 0x21978352, 0x17828705, 0x04232782, 0x824e0042, 0x25e7849f, 0x68002306, 0x2b826004, 0x23820782, 0x3f824e20, 0xf7844020, 0x7100b030, 0x5a00a003, + 0xae00b604, 0xa4009e02, 0x0382b804, 0x04221382, 0xfb4200d1, 0x009e2205, 0x231f836f, 0x7100a403, 0x04232383, 0x83710087, 0xf8032927, 0x1704ae00, + 0xc104f2ff, 0x23220782, 0x1f840000, 0x71009e27, 0x19000a05, 0x84478204, 0x82b4200f, 0x0098225b, 0x21538312, 0x3f829605, 0xecff3128, 0xa400ec05, + 0x43840606, 0x6b841520, 0x07833382, 0xe3831383, 0x00a00525, 0x45ee0314, 0xbb8205e3, 0xa7826820, 0x03825220, 0x2b02402c, 0x480748ff, 0x75070000, + 0x2383c700, 0xfb830420, 0x1900ae22, 0xdd20eb84, 0x41062b44, 0x0523062f, 0x830e0033, 0x85062b4b, 0x5c040400, 0xd5054800, 0x0383c900, 0x05223383, + 0x2f41005a, 0x06474105, 0x22082b41, 0x827d00d3, 0x0414216f, 0x2b415382, 0x9a052107, 0x48266b82, 0xfa07a600, 0x0383c700, 0x003d0525, 0x41960614, + 0xc124065b, 0x1d083b00, 0xb8200b82, 0x2008ef82, 0x045e003f, 0x0475008f, 0x03ae0089, 0x04ae0033, 0x04290060, 0x05710048, 0x030400c3, 0x044400ae, + 0x821382e9, 0x26d78203, 0x005e04ae, 0x85be0510, 0x8304200f, 0x82c120fb, 0x46b0200b, 0x03310553, 0x03290087, 0x050a00e9, 0x04710093, 0x04230000, + 0x301b82d1, 0x069a00ac, 0x07ae00f4, 0x05ae0004, 0x0529006d, 0x831382fe, 0x00b22467, 0x82790637, 0x823f200b, 0x236b8227, 0x1200b604, 0x03277b83, + 0x037100b4, 0x465a009c, 0xee2a068b, 0xbcff1202, 0x10008306, 0x2b82e506, 0xee202383, 0x8206d741, 0x208f8277, 0x433383c7, 0x078f070f, 0x23081f43, + 0x08520000, 0x03270386, 0x01fcff4a, 0x83170066, 0x00022303, 0x07823f00, 0xe7021924, 0x03831700, 0x00810329, 0x00e3033f, 0x82f8037b, 0x00023603, + 0x006f0696, 0x005a0993, 0x00cf0166, 0x00370385, 0x004e0285, 0x2f038352, 0x9300f603, 0xa0fe0a01, 0x6a00f802, 0x60006804, 0x44240382, 0x96000006, + 0x3f2c0782, 0x8d006806, 0x77000004, 0xc700e707, 0x252ceb82, 0x4e00f005, 0x6600f404, 0x53000e06, 0x33200382, 0x4f200382, 0x712a0382, 0x6200a604, + 0x29008b04, 0x2782ee05, 0x4a000c32, 0x66006804, 0x25006404, 0x7700a805, 0x10001903, 0x13830f84, 0xaa260387, 0xb4046d00, 0x03841d00, 0xcf009e2a, + 0xbcff1202, 0x87010004, 0x6f200382, 0x7d240382, 0x2500a602, 0x0c200382, 0x3b200382, 0x2f200b86, 0x20062f47, 0x248f8221, 0x00000800, 0x29078700, + 0x0000ab02, 0x00000002, 0x13825501, 0x0b826820, 0x0b822520, 0x10829a20, 0x0382cd20, 0x08230286, 0x83540000, 0x37678303, 0x17006601, 0x0a00cd04, + 0x00005204, 0x1200a006, 0xc700f606, 0xae002b07, 0x2e085344, 0x02d3fe42, 0x037300aa, 0x07930033, 0x831d0056, 0x34f78203, 0x00aa047d, 0x00f40571, + 0x002f05b8, 0xfc0000a4, 0xfd00008f, 0x20078248, 0x20078246, 0x22038204, 0x82390431, 0x00d53cfb, 0x004804c9, 0x00e90471, 0x00db07ae, 0x006f067d, + 0x00250500, 0x00dd0414, 0x82270714, 0x00b6221f, 0x2a3f82ae, 0x00640400, 0x0029070a, 0x821206c7, 0x827f200f, 0x82f0201f, 0x828b200f, 0x82a2200f, + 0x005e2e87, 0x00ae0339, 0x00230617, 0x00ec0568, 0x427b84a4, 0x0022059b, 0xe382dd03, 0x8400c121, 0x64093107, 0x58087d00, 0x3f067100, 0x19057d00, + 0xb2077100, 0x50206f82, 0x77860782, 0x07470420, 0x00df2407, 0x82750468, 0x009e2697, 0x019e04f4, 0x290383e1, 0x2900e907, 0x2900a607, 0x1782e705, + 0x7382fc20, 0x2f009c32, 0x12008904, 0xc7009c04, 0xae00b004, 0x2f00ee03, 0x1222ff82, 0x0f820005, 0xae000826, 0x0400e906, 0x04248f82, 0x48005c04, + 0x44229b82, 0x17820a05, 0x37824a20, 0x0782a220, 0x07842b20, 0xf8032f26, 0x44051200, 0xd120cb82, 0xcd245782, 0xfa04e500, 0x5c283782, 0xac05e500, + 0x4408ae00, 0xb820db82, 0xec26eb82, 0xf2047d00, 0x9b887100, 0x14002728, 0x29008703, 0xd3823704, 0xdb82d520, 0xd3200787, 0x3d280b82, 0x89062300, + 0x8b051400, 0x48274f82, 0xbc04a600, 0x83059a00, 0x84ac2007, 0x04c72107, 0x06275782, 0x053d0077, 0x8733001d, 0xb6022907, 0x85065200, 0xc3050400, + 0x4a200382, 0x2d209b82, 0x6a207382, 0x71244b82, 0x9c051000, 0xe9209382, 0xcb200f82, 0xf3820782, 0x07274b87, 0x05c70006, 0x83ae00d1, 0x0703423b, + 0x200f5f46, 0x06234804, 0x828f0521, 0x004822bb, 0x87078766, 0x0717416b, 0xb8270784, 0xd5051b00, 0x8304c900, 0x4707876b, 0xd3410e7b, 0x033b2c0a, + 0x043700b2, 0x031900ae, 0x8f0a00e9, 0x44a38707, 0x0621071b, 0x20ab8296, 0x099f41fe, 0x82c30421, 0x002f24db, 0x82600423, 0x82002007, 0x009c2c07, + 0x00b00489, 0x00f40671, 0x82fe0689, 0xfc2e0807, 0x46064e00, 0xc5045000, 0x10044e00, 0xa4075000, 0xa4060000, 0xe5071000, 0x2f07c700, 0xc305ae00, + 0xe1047d00, 0x81057100, 0x12051400, 0xbf822900, 0xae036f26, 0x5a055c00, 0x5e224f82, 0x0f411000, 0x200f8e0f, 0x200f8e12, 0x490fb05e, 0x04271e7b, + 0x04270039, 0x49120048, 0x022717ab, 0x025200b6, 0x86620012, 0x489e2007, 0x0f8e0fe3, 0x0f8e3320, 0x200d1349, 0x062349aa, 0xdb48079b, 0x060f440f, + 0x97071744, 0x08bb4507, 0x200ae348, 0x05d34a03, 0x00007128, 0x0000dbfb, 0x07826afc, 0x07858920, 0x8264fc21, 0x8a732007, 0x01642403, 0x823100a4, + 0x83102003, 0xb0042303, 0x73497100, 0x00002e07, 0x01018503, 0x18281a01, 0x010a0101, 0x2504822b, 0x1401160b, 0x00880b05, 0x82141421, 0x1c3d080a, + 0x1422260b, 0x0b12010b, 0x15151915, 0x22191c14, 0x1b162213, 0x1017151b, 0x01122610, 0x01200105, 0x1c0b1101, 0x192a150b, 0x0a0c0c2e, 0x152e180c, + 0x2a120b0b, 0x0b192e0b, 0x1912161a, 0x20068218, 0x2e448228, 0x0115180b, 0x0b271404, 0x10010401, 0x8211110b, 0x0114294d, 0x01270a11, 0x261c0a01, + 0x01210084, 0x21898214, 0x00821901, 0x22190b22, 0x0b220083, 0x00821522, 0x16132623, 0x21008411, 0x0d821c16, 0x820c1521, 0x2e152100, 0x15230983, + 0x822e150b, 0x0b162400, 0x83112616, 0x1c142101, 0x6b830185, 0x87150121, 0x190b2101, 0x33820185, 0x0c192e22, 0x15280187, 0x150c1517, 0x0c140a0a, + 0x24240184, 0x2e190c14, 0x18240183, 0x15222e19, 0x2a230183, 0x83121628, 0x2a1b2101, 0x0b210186, 0x8301821b, 0x25038743, 0x16260b10, 0x00841226, + 0x260b302c, 0x22160111, 0x012a1b15, 0xc3832401, 0x5b080383, 0x2d151426, 0x150d150c, 0x19222616, 0x15120117, 0x19151922, 0x2211191c, 0x1b201315, + 0x19101926, 0x0b261922, 0x12162e16, 0x15160c0b, 0x172e1616, 0x122d0a16, 0x18151818, 0x01181813, 0x13131912, 0x15121618, 0x0e011812, 0x191b1419, + 0x19281519, 0x1530150e, 0x19221326, 0x1218011f, 0x10211082, 0x08a7821c, 0x1b141327, 0x15101930, 0x17191914, 0x24161910, 0x19141116, 0x19151614, + 0x0a19191a, 0x15191316, 0x191c0b12, 0x161a1916, 0x361f8212, 0x19111918, 0x142e1511, 0x0c0c2a1c, 0x2e18180c, 0x1712160a, 0x830b1001, 0x16262101, + 0x1523af83, 0x82151915, 0x82192003, 0x2b143100, 0x0c191918, 0x0b0b1901, 0x01010b11, 0x0122192a, 0x0c293382, 0x2b1e1726, 0x17170101, 0x2200820b, + 0x82141419, 0x01012220, 0x85008511, 0x852e20f3, 0x01012a06, 0x1611150c, 0x26181c18, 0x22108211, 0x82221414, 0x2c1985f7, 0x1d191519, 0x01262017, + 0x18181c01, 0x28938216, 0x191a0114, 0x18152213, 0x2a018216, 0x19151401, 0x14181d01, 0x82240d1c, 0x012e282c, 0x17011916, 0x82120b13, 0x19192515, + 0x01151a12, 0x0a229d82, 0x9782180b, 0x192e1929, 0x1c141312, 0x8226191b, 0x19193301, 0x1613152a, 0x18191214, 0x160a160a, 0x20191819, 0x32821818, + 0x14191823, 0x21cb8212, 0x82821126, 0x82011621, 0x151522d6, 0x21458218, 0xdc821112, 0xe0411920, 0x11162305, 0x01831630, 0x142c3b82, 0x14121810, + 0x1a100116, 0x15170b13, 0x16236282, 0x82271817, 0x171324aa, 0x42101a12, 0x6042065a, 0x42058b05, 0x09850960, 0x190c1923, 0x9159850c, 0x2e152505, + 0x1c192e15, 0x26210187, 0x20018316, 0x0512410b, 0x0b220585, 0x67480b1b, 0x00133505, 0x06880300, 0x03000407, 0x04020202, 0x01040503, 0x03030202, + 0x05820b82, 0x00860320, 0x03201183, 0x04271a82, 0x03030404, 0x82020404, 0x8205201a, 0x210d850b, 0x2e840305, 0x82020321, 0x04032119, 0x1f820683, + 0x1f840220, 0x02030223, 0x82158304, 0x870a8214, 0x82052050, 0x83022008, 0x23388235, 0x01020404, 0x27833984, 0x05215283, 0x84158204, 0x8260847e, + 0x84688862, 0x20378508, 0x8d008202, 0x823f871f, 0x85848207, 0x82bd860d, 0x82158b06, 0x8202863a, 0x8293847c, 0x85a1859b, 0x84ba8452, 0x0405228b, + 0x88018302, 0x85288447, 0x85058524, 0x241f84ad, 0x03040302, 0x843a8205, 0x214e820c, 0x00820301, 0x05263d82, 0x05040503, 0x81830402, 0x70820320, + 0x05040322, 0x06239c87, 0x83040603, 0x8a248235, 0x82f1851e, 0x2228824c, 0x82020605, 0x03062267, 0x820e8205, 0x060621b3, 0x10820882, 0x12834082, + 0xaa850682, 0x06040325, 0x82040403, 0x8206201d, 0x82042005, 0x20d58200, 0x20118204, 0x82428203, 0x2087820d, 0x24068205, 0x05040606, 0x20728203, + 0x20748203, 0x234d8203, 0x03040505, 0x05205783, 0xc7842582, 0x02060627, 0x01020101, 0x233d8202, 0x07060203, 0x02220882, 0x0c820103, 0x05030524, + 0x41820603, 0x00820520, 0x41847d84, 0x04223b82, 0x24420304, 0x8203200a, 0x020223cf, 0x44820301, 0x06000022, 0x04204b82, 0x36833582, 0x82020221, + 0x2038827a, 0x82008300, 0x84042071, 0x823c824c, 0x200b8281, 0x825c8403, 0x070321af, 0x06211882, 0x82048205, 0x21b48224, 0x23820606, 0x03820320, + 0x03040225, 0x85030505, 0x200f8214, 0x82008204, 0x41188224, 0x1d82056b, 0x02831182, 0x0220ca83, 0x2a827282, 0x05221185, 0x17840205, 0x27833d84, + 0xc0413183, 0x052a420a, 0x06256384, 0x04020305, 0x229e8403, 0x83050506, 0x20b584bb, 0x8ae78405, 0x850a8b32, 0x4205897f, 0x31960a96, 0x33851687, + 0x87000421, 0x01013200, 0x02030401, 0x04090700, 0x02020400, 0x06040503, 0x214c8205, 0x04820404, 0x3983f186, 0xcd830220, 0x3e410320, 0x05052306, + 0x62410204, 0x26f18205, 0x06050504, 0x43040404, 0xfc410670, 0x233c8205, 0x04060204, 0x03200082, 0x0423da82, 0x82040406, 0x83022006, 0x23138415, + 0x03020604, 0x032e1f83, 0x04030304, 0x01020504, 0x05030203, 0x03830505, 0x37840682, 0x00830420, 0x00850520, 0xff416182, 0x20158406, 0x93968406, + 0x054f42f0, 0x83077143, 0x090b410d, 0x05851b85, 0x83055b43, 0x85052005, 0x05834393, 0x20850583, 0x06860520, 0x06060422, 0x4108bf43, 0xc48205b0, + 0x8b020421, 0x8221824b, 0x221c8464, 0x82050402, 0x04052130, 0x23056543, 0x04010402, 0x05210082, 0x24be8402, 0x04050206, 0x821a8203, 0x05042259, + 0x82408206, 0x0404230b, 0x4d420406, 0x208a8205, 0x22008204, 0x85040303, 0x84078209, 0x211f8277, 0x18820206, 0x43040621, 0x0222057e, 0x43860707, + 0x6a820320, 0x4b835882, 0x4a860520, 0x08050529, 0x04060508, 0x82040704, 0x20418200, 0x0b874306, 0x04206a82, 0x2405a743, 0x04040603, 0x05384504, + 0x04060624, 0x0b820403, 0x00840620, 0x07261682, 0x01010307, 0x22420102, 0x08062705, 0x02020302, 0x22820103, 0x07206c83, 0x05206782, 0x75830082, + 0x8f860420, 0x00820420, 0x03820220, 0x03203085, 0x072b7a82, 0x04010202, 0x00010102, 0x82070700, 0x06042309, 0xec820606, 0x84030221, 0x00042106, + 0x04210083, 0x23898405, 0x05050604, 0x06220382, 0x0f860704, 0x04212782, 0x820c8209, 0x41062032, 0x04200542, 0xce87ee84, 0x03221485, 0x7e410304, + 0x82072005, 0x20268227, 0x211e8303, 0x0d820404, 0x50845782, 0x41058441, 0x088508c1, 0x1f85ea82, 0xc0414584, 0x82688609, 0x8203201b, 0x840d87a3, + 0x205382b5, 0x05a94107, 0x35897186, 0x7d850989, 0x0220058a, 0x930d1e42, 0x86138533, 0x0c874333, 0x00020426, 0x00050a08, 0x27058743, 0x02020607, + 0x02040402, 0x8605a446, 0x8202202e, 0x24ed8311, 0x04050505, 0x26d48204, 0x08040502, 0x82050606, 0x200d82a7, 0x82598208, 0x0721412e, 0x05040322, + 0x02212e82, 0x212b8208, 0x14830305, 0x04040622, 0x0320e182, 0x8205f342, 0x0705220b, 0x20108203, 0x82f58407, 0x202c8224, 0x20458203, 0x23038306, + 0x07060606, 0x82098d46, 0x8502820d, 0x05ff4117, 0x07203d82, 0x04200382, 0x02214b82, 0x0da74302, 0x82040521, 0x88038241, 0x0bbc43fa, 0x21821b86, + 0x0221b383, 0x20018604, 0x20478205, 0x884f8205, 0x82062010, 0x8603821e, 0x07052406, 0x83030507, 0x08684101, 0xb4820320, 0x1d870320, 0x08240783, + 0x04040406, 0x02207285, 0x07226482, 0x29430607, 0x02052305, 0x80820105, 0x02060522, 0x02205185, 0x06231782, 0x83060504, 0x22338203, 0x82050606, + 0x83062027, 0x8204200f, 0x8202203d, 0x8404202a, 0x04022138, 0x52840785, 0x3f82ae82, 0x82050521, 0x23158307, 0x08080204, 0x3b843782, 0x08040623, + 0x22088204, 0x84060806, 0x8264840e, 0x0507231d, 0x3a820805, 0x04030524, 0xa7430604, 0x84588208, 0x08a7430d, 0x02211e83, 0x06d54302, 0x08030423, + 0x82018306, 0x080821c7, 0x82068743, 0x0603280b, 0x02030209, 0x84010402, 0x826e824a, 0x836b8267, 0x204f82b2, 0x20158206, 0x46608204, 0x2f82066e, + 0x083b0283, 0x02030804, 0x02020401, 0x08000001, 0x05010208, 0x08080704, 0x03060406, 0x82070703, 0x00052138, 0x8a830083, 0x05060831, 0x06060705, + 0x06050704, 0x04070806, 0x82060604, 0x0604261e, 0x06080a04, 0x848b8305, 0x050522fd, 0x200e8208, 0x25008205, 0x04050304, 0x6f820608, 0x85056941, + 0x070622ec, 0x07294206, 0x0c826782, 0x05212882, 0x82018207, 0x0590432a, 0x11820620, 0x06203682, 0x07225882, 0x05820407, 0x0420c583, 0xc0410082, + 0x092c4209, 0x07030423, 0x06c14206, 0x08070529, 0x04040606, 0x84090708, 0x20398255, 0x055a4205, 0x87430591, 0x9b5d8913, 0x41398509, 0x00200512, + 0x02380082, 0x04050202, 0x0c090003, 0x02050005, 0x05060402, 0x03020608, 0x02050603, 0x4205a446, 0x248206eb, 0x83050521, 0x820520e0, 0x20a482dc, + 0x830c8303, 0x20f182f4, 0x22b58206, 0x82030305, 0x202c8212, 0x21268204, 0x2e820505, 0x82080221, 0x8205200d, 0x0505226d, 0x22138206, 0x83030503, + 0x27138415, 0x05040705, 0x05070305, 0x28057142, 0x04020206, 0x07070504, 0x056f4308, 0x37840620, 0x0f823883, 0x00830720, 0x06070522, 0x89860083, + 0x41080521, 0x022005fe, 0x87088743, 0x85052018, 0x090945f6, 0x19880620, 0x14418383, 0x090f4709, 0x03040623, 0x86248202, 0x04032210, 0x08874302, + 0x0723db83, 0x44080905, 0xce820dd0, 0x210cc641, 0x8d440506, 0x050f4906, 0x08200e82, 0x21073746, 0x59830502, 0x02060528, 0x08050706, 0x59820807, + 0x05279f82, 0x05040706, 0x82060806, 0x050521d2, 0x0722ef84, 0x87430604, 0x21108206, 0x34850504, 0x87432382, 0x06062105, 0x83058743, 0x0405273a, + 0x09090304, 0x13820506, 0xcf830520, 0x09820820, 0x08070525, 0x86060706, 0x0806274a, 0x05070708, 0x63410905, 0x06052205, 0x20088304, 0x200d8406, + 0x20408404, 0x222c8208, 0x44070405, 0x0224059f, 0x08080202, 0x3c820a82, 0x82058743, 0x09092229, 0x08674804, 0x0b060334, 0x03030402, 0x05040104, + 0x07050805, 0x07080905, 0x00820806, 0x07217f85, 0x235c8403, 0x02040606, 0x2509ee44, 0x09050905, 0xf8820203, 0x00010227, 0x02090900, 0x29aa8202, + 0x05060808, 0x09040307, 0x82820709, 0x00830020, 0x05280782, 0x05060708, 0x06060608, 0x03820782, 0x06040523, 0x221e8306, 0x820c0506, 0x07082326, + 0xfd820708, 0x05205682, 0xa285ee83, 0x06208382, 0x0c842682, 0x06060624, 0x8f840605, 0x21056044, 0x4c820406, 0x84070721, 0x21ca8315, 0x0a820804, + 0x18824f85, 0x22057a45, 0x82050808, 0x820720c3, 0x215a8274, 0x3f820604, 0x4305e041, 0x062407b0, 0x07040505, 0x09827684, 0xe6820520, 0x05050726, + 0x0809070a, 0x19822983, 0x43065a42, 0x61421157, 0x230a840a, 0x02040204, 0x05915985, 0x6b823d91, 0x00870020, 0x02020222, 0x002dce82, 0x00060c0a, + 0x04020305, 0x07080606, 0x06874302, 0x65890420, 0x05222482, 0xe0820405, 0x87430620, 0x03042117, 0xe582d383, 0x87430283, 0x82042011, 0x02032116, + 0x06265085, 0x05050408, 0x11820803, 0x82040421, 0x0687439c, 0x7b820720, 0x00820620, 0x3a420920, 0x201b8206, 0x33874306, 0x2008b444, 0x22874305, + 0x8743f282, 0x43042009, 0x07220787, 0x87430506, 0x08092336, 0x60430507, 0x06032205, 0x20cc8202, 0x09874306, 0x0520e982, 0x220e8743, 0x43080608, + 0x07222687, 0x87430605, 0x83088205, 0x430e8256, 0xf2820a87, 0x15820820, 0x070a0a22, 0x0a200682, 0x241a8743, 0x04050707, 0x19874308, 0x430a0a21, + 0x09210a87, 0x0a87430c, 0x09050823, 0x07874307, 0x06060723, 0x08874305, 0x87430620, 0x050a2d0b, 0x0203030a, 0x01020306, 0x0a0a0000, 0x20088743, + 0x10874308, 0x43820a20, 0x03830920, 0x06080823, 0x4393830a, 0x0c820787, 0x82080a21, 0x050b421d, 0x060a0a23, 0x256c8205, 0x06040505, 0x87430805, + 0x06072a0c, 0x0607080a, 0x04040406, 0x21018306, 0x87430805, 0x4309201e, 0xa5431687, 0x05062205, 0x21638206, 0x67830708, 0x210a8743, 0x12820908, + 0x43050721, 0x0b306c87, 0x0600070e, 0x07050303, 0x03080906, 0x06060303, 0x2005af4e, 0x83008606, 0x05063411, 0x0707070a, 0x08050608, 0x07030308, + 0x09080a05, 0x82070906, 0x0907240d, 0x82070706, 0x20cd822e, 0x28038306, 0x02060604, 0x0a020502, 0x20008206, 0x072f4704, 0x44840883, 0x0627e782, + 0x06050409, 0x82060904, 0x06042704, 0x02030706, 0x53820404, 0x07050822, 0x09220084, 0x00820607, 0x00820320, 0x09080822, 0x06220083, 0x00820809, + 0x18821584, 0x050a0622, 0x02200583, 0x9b860082, 0x07210688, 0x43018406, 0x08220643, 0x19880806, 0x0b820620, 0x8305f545, 0x090e4e05, 0x03050727, + 0x05050702, 0x82ae8205, 0x05032203, 0x21248602, 0xdb820608, 0x0a230382, 0x8304070a, 0x07ca4401, 0xc6820520, 0x89040521, 0x20278249, 0x43738208, + 0x022005b4, 0x09237e82, 0x8206090a, 0x0606222c, 0x06874306, 0x07030729, 0x08090409, 0x84070409, 0x0908289b, 0x0a070703, 0x82090508, 0x0705219b, + 0x0f826482, 0x76422f82, 0x4a052005, 0x408305b6, 0x71840820, 0x08226882, 0xbc850604, 0x0306072b, 0x0a0a0303, 0x08060708, 0x224b8407, 0x82080609, + 0x080a2109, 0x07214a82, 0x29ab8205, 0x0b0b0808, 0x07070908, 0x3182070c, 0x26820420, 0x48830520, 0xb5430720, 0x43062005, 0x082805a7, 0x09050608, + 0x04060606, 0x0221f282, 0x20ab8202, 0x21238205, 0x43820904, 0x58820920, 0x0b0b0623, 0x060f4705, 0x0505052c, 0x05030d09, 0x01060303, 0x5c820604, + 0x0b060926, 0x09070909, 0x06210082, 0x84298307, 0x07062596, 0x02060606, 0x04200382, 0x06240085, 0x040b060b, 0x2e078743, 0x02020b0b, 0x0a080707, + 0x0906070a, 0x820a0404, 0x0708226b, 0x83008300, 0x840b208a, 0x060723b9, 0x2183080a, 0x08219382, 0x24168209, 0x0b0e0608, 0x82688209, 0x8205201d, + 0x06062155, 0x0784d082, 0x0704052b, 0x06080906, 0x07060705, 0x2d018205, 0x09060807, 0x090a0b07, 0x05050707, 0x85840706, 0x82090a21, 0x82428249, + 0x030721a3, 0x14820b82, 0x2205a541, 0x8303070a, 0x0a092121, 0x4583c585, 0x4105fa4a, 0xd64405e0, 0x23398206, 0x08090406, 0x06206783, 0x09280082, + 0x0609090a, 0x0b090a06, 0x08212e82, 0x84778407, 0x90072067, 0x0a614205, 0x03230a84, 0x85020302, 0x84059159, 0x82072090, 0x850384a7, 0x0006214b, + 0x250a0f47, 0x00040506, 0x87430f0c, 0x07082b05, 0x0403080a, 0x03070704, 0x05820304, 0x00860720, 0x82030321, 0x06874308, 0x08080623, 0x21dc8204, + 0xf483090b, 0x54820720, 0x1b820b20, 0x04040428, 0x07070506, 0x39820607, 0x03070625, 0x83030603, 0x04072815, 0x05070406, 0x82050609, 0x82042006, + 0x274d8415, 0x040a0706, 0x0a040706, 0x04262f82, 0x08070704, 0x3b820203, 0x09090923, 0x231d8405, 0x06070a07, 0x4f820082, 0x86430420, 0x20658205, + 0x85008208, 0x2105821c, 0x0482060b, 0x92844b82, 0xa0411588, 0x410e8405, 0xf083062c, 0x43093741, 0xaf82083b, 0xdd83d982, 0x07210382, 0x82458206, + 0x25ae826d, 0x04060306, 0x6c820306, 0x07090723, 0x23068508, 0x0b0b0709, 0x41058743, 0x04200880, 0x4a410f83, 0x21078307, 0x7982090b, 0x03201e85, + 0x0a207d82, 0x0d820f82, 0x03220982, 0x8d840207, 0x09070323, 0x43dc8206, 0x08820887, 0x09212382, 0x821c8308, 0x05a04366, 0x46821482, 0x07050624, + 0x04820407, 0x82060621, 0x820620a4, 0x83398310, 0x2007821a, 0x221a8206, 0x820b0304, 0x211b823a, 0x72420707, 0x21a98205, 0x4a87080b, 0x0b080829, + 0x070a080b, 0x82070c07, 0x06052100, 0x26827682, 0x0d82cc82, 0x05050623, 0x82408209, 0x0709221f, 0x22228206, 0x82060507, 0x820320f8, 0x226d83dd, + 0x83090b05, 0x21148201, 0x87430c0c, 0x030f2f0b, 0x06040405, 0x07070402, 0x060a070a, 0x87430a0d, 0x07072505, 0x07070808, 0x2207ac41, 0x43030707, + 0x0c2d0a87, 0x03040c06, 0x02030702, 0x0c000001, 0x2109820c, 0x63820907, 0x04090724, 0xb8820b05, 0x00080922, 0x06230083, 0x82070709, 0x2303840d, + 0x07070a0a, 0x062b0382, 0x07090909, 0x05080508, 0x82090d0e, 0x820b2017, 0x070621a5, 0x0c200082, 0x06820982, 0xa5820720, 0x090a0723, 0x21f48207, + 0x05820607, 0x07080726, 0x0b0c0809, 0x07201183, 0x22057445, 0x82080a06, 0x26178240, 0x080a080a, 0x41090904, 0x0b2309a1, 0x82070409, 0x0b0a2400, + 0x83090706, 0x83092001, 0x84098441, 0x06d9430f, 0x82080521, 0x090a2163, 0x5f826782, 0x5b849e82, 0x830a0b21, 0x21ad827f, 0x66420806, 0x43098e09, + 0x04220f98, 0x43420403, 0x87638906, 0x84082009, 0x05f444b7, 0x82056947, 0x870020bd, 0x02023200, 0x04070702, 0x08100d00, 0x04030700, 0x0b070805, + 0x07874309, 0x42061843, 0x058205f6, 0x080b0623, 0x2bef8208, 0x05090906, 0x0b060803, 0x0a070a09, 0x0922a182, 0x1b820b07, 0x04050423, 0x203c8207, + 0x26b38208, 0x03080704, 0x83030603, 0x05082a2c, 0x06080406, 0x0606070a, 0x43738205, 0x062c06d8, 0x06050b08, 0x070b0407, 0x05050706, 0x03285082, + 0x06050503, 0x060a0a0a, 0x02825d82, 0x07080b22, 0x05200082, 0x09210082, 0x20158209, 0x2065820a, 0x21008209, 0x17840707, 0x43070721, 0x2f850987, + 0x0883de82, 0x82080621, 0x200b827a, 0x07714307, 0x3541f083, 0x08164109, 0x08090822, 0x83057b51, 0x06082205, 0x21c98203, 0x87430606, 0x821e8209, + 0x08092238, 0x2301840a, 0x05080c0c, 0x87430183, 0x074a410d, 0x0b200783, 0x0720dc82, 0x04201e85, 0x0b26a182, 0x07080a0b, 0x87820806, 0x02080322, + 0x08299683, 0x060a0803, 0x040a090a, 0x29be8408, 0x08050a09, 0x07090b08, 0x9a83090a, 0x0a22da82, 0xb0820705, 0x2a820420, 0x0624c082, 0x06040808, + 0x06204582, 0x08200e85, 0x0b211f82, 0x220b8204, 0x820a070b, 0x05052615, 0x0a0c0c03, 0x21a18208, 0x0e820808, 0x09070b22, 0x0b218082, 0x824a8209, + 0x070a2a0e, 0x0d0d0909, 0x08080b09, 0x2b0d820d, 0x07070507, 0x08080609, 0x08090706, 0x06240082, 0x07090605, 0x2406a743, 0x07070b06, 0x07874308, + 0x06060827, 0x0b050608, 0x8201830a, 0x0d0d23c4, 0x774f0205, 0x10092108, 0x82058743, 0x247f834a, 0x080a0a0d, 0x2000820a, 0x43528208, 0xac410c87, + 0x05053f06, 0x070d0705, 0x0203040d, 0x01030307, 0x0d0d0000, 0x07080203, 0x080b0b0b, 0x05040a07, 0x3d820b0b, 0x83000921, 0x09072c00, 0x0a0d0807, + 0x090c0808, 0x820c0708, 0x0a0c25bc, 0x0a0a0607, 0x06251082, 0x0e0f0608, 0x821b820a, 0x0806281d, 0x08080807, 0x410a0c0d, 0x052005d1, 0x09214982, + 0x44148307, 0x08240580, 0x0b0d090a, 0x06223382, 0xb6820507, 0x07070624, 0x9441090b, 0x090b2505, 0x0b05090b, 0x0920f482, 0x1283a682, 0x42830e82, + 0x070b0b24, 0x01820a07, 0x45820b20, 0x1a840720, 0x4205e041, 0x0724092c, 0x060a0b05, 0x07256782, 0x0b080707, 0x23ae820c, 0x0d0b0d07, 0x0923a382, + 0x43060708, 0xdc4305e3, 0x43098909, 0x07240e96, 0x03050305, 0x05915985, 0x0a218e83, 0x84018709, 0x080622b7, 0x3c008700, 0x08030303, 0x0e000407, + 0x07000811, 0x09060404, 0x030a0c08, 0x08080404, 0x05040504, 0x83008808, 0x06082611, 0x0809090c, 0x21d0820a, 0x3382050a, 0x0b0a0c23, 0x055f4808, + 0x97820d20, 0x04050423, 0x05084307, 0x07040828, 0x07040408, 0x3c830d04, 0x82070521, 0x820a20da, 0x200883ad, 0x21568204, 0xe7820808, 0x07050c25, + 0x820c0508, 0x05052e2f, 0x04090808, 0x07050503, 0x060a0a0a, 0x20008409, 0x0887430c, 0x0b0a0a22, 0x08210083, 0x211c820b, 0x3983070a, 0x07214882, + 0x8209820c, 0x8504209e, 0x22a1884d, 0x43070807, 0x2441056b, 0x080a2107, 0x8205c441, 0x21128218, 0x0186070a, 0x7b511582, 0x08082309, 0x6e830403, + 0x0725ae82, 0x07050704, 0x063d4104, 0xd9820a20, 0x0c21dd83, 0x0687430d, 0x82076f41, 0x050721c6, 0x210b6241, 0x1a820a0d, 0x04287285, 0x0c070908, + 0x07080b0c, 0x0822a085, 0x00820803, 0x08040929, 0x090b060b, 0x8309040b, 0x0a08279d, 0x0908050b, 0xd2820a0c, 0x27820820, 0x0b226282, 0x3d820705, + 0x29820420, 0x06200782, 0x0720d782, 0x07210782, 0x05664908, 0x26108743, 0x080a0d0d, 0x82090a08, 0x07092568, 0x0a0a080b, 0x0b204b83, 0x07221282, + 0x16820b08, 0x090d0d26, 0x0f08090c, 0xb5824f82, 0x08202382, 0x1c820982, 0x05210682, 0x05874307, 0x080b0922, 0x08293782, 0x07070508, 0x0c040404, + 0x2483820c, 0x0d060708, 0x2601830a, 0x0e070707, 0x8203060e, 0x06063600, 0x06070706, 0x0603110c, 0x02070404, 0x0c080805, 0x0e070b08, 0x24c5820a, + 0x080b0b0b, 0x217f8209, 0x15820a08, 0x08205782, 0x0720b084, 0x3605f64f, 0x070e0705, 0x0204050e, 0x01030408, 0x0e0e0000, 0x08080304, 0x820d0c0b, + 0x060523a9, 0xeb820d0d, 0x30068743, 0x0d08080a, 0x0d08090b, 0x0c07090a, 0x0d09090a, 0x2093820c, 0x2557820a, 0x11070907, 0x1b820b0f, 0x080b0d22, + 0x21053f44, 0xbe840d0e, 0x05070826, 0x0a0b0809, 0x07201484, 0x0a200583, 0x0f210d82, 0x2211830c, 0x82070507, 0x82408300, 0x82082049, 0x05874317, + 0x45080921, 0x09260549, 0x050a0c08, 0x68820709, 0x08070c23, 0x2101830b, 0x35470809, 0x200d8406, 0x460d8308, 0x072505a7, 0x070b0c05, 0x300f8405, + 0x0c0c0c08, 0x0d07080b, 0x0a0c0e0c, 0x08090a08, 0x05704107, 0x2111e146, 0x664a0709, 0x25388408, 0x04050807, 0x59850405, 0x4b820591, 0x7a480820, + 0x42058305, 0x87430551, 0x0005320e, 0x0009120f, 0x07040408, 0x0b0c080a, 0x08050504, 0x46508208, 0x082006a0, 0x04210082, 0x2f048204, 0x0a0a0d06, + 0x08080a09, 0x04060b0a, 0x0b0d0709, 0x5a824e84, 0x08090e28, 0x05060508, 0xaf840608, 0x2a820820, 0x042b4882, 0x0909080d, 0x05070609, 0x430b0708, + 0x09200e87, 0x82058743, 0x05052eba, 0x040a0809, 0x07050503, 0x060b0b0b, 0x2000840a, 0x05c2450d, 0x06060623, 0x8214820a, 0x84082002, 0x204d8206, + 0x20008408, 0x0887430d, 0x09206e82, 0x08200082, 0x07213084, 0x22bb8209, 0x4a0a080a, 0xaa820853, 0x34841884, 0x3b430820, 0x080b2307, 0xc951080b, + 0x09042108, 0x0920f282, 0x87439d82, 0x053d4108, 0x06820a20, 0xdd830920, 0x4b0e0d21, 0x344105e6, 0x07072105, 0x41059543, 0x0e210b62, 0x41c6820b, + 0x04200584, 0x0d266482, 0x07090b0d, 0x99820907, 0x03090422, 0x092a9b82, 0x0c09040a, 0x0c0a0c07, 0x81830a04, 0x0623ca82, 0x820d0a09, 0x830b2040, + 0x2962829b, 0x0908060b, 0x08040807, 0xc0820909, 0x09080728, 0x08070704, 0x39820708, 0x08220e82, 0x3882080b, 0x0c20de82, 0x092a0982, 0x04060607, + 0x090b0f0e, 0xd9820b09, 0x080a0823, 0x244c820c, 0x0b0d0b09, 0x2212820b, 0x820b0908, 0x0e0e2616, 0x090a0d0a, 0x247c8210, 0x08080608, 0x8348830b, + 0x21608238, 0x0d830707, 0x0a0d0d2a, 0x0c07080b, 0x06080808, 0x20058743, 0x0587430d, 0x830b0e21, 0x21c48201, 0x87430f0f, 0x82082007, 0x04122227, + 0x08874307, 0x0f080c23, 0x0587430c, 0x0b0a0923, 0x205c8209, 0x82458206, 0x090922b4, 0x43088204, 0x08330687, 0x050f080f, 0x04080304, 0x00000203, + 0x03040f0f, 0x820c0809, 0x0c082573, 0x0e0e0605, 0x87433d82, 0x0b082205, 0x2e4c8208, 0x0b0d090a, 0x0a0d080a, 0x0c0e090a, 0x820b0708, 0x07092b54, + 0x10120709, 0x0c0d090b, 0x0b820c0f, 0x0f225c83, 0x63840b0e, 0x0a060824, 0xba820c08, 0xca820920, 0x0a070928, 0x0c080b09, 0x3f82100a, 0x41070921, + 0x09210579, 0x05994207, 0x09261782, 0x0c06090c, 0x74430a0b, 0x82082005, 0x820b2061, 0x2106823b, 0x1284080d, 0x6e824583, 0x09200b83, 0x5b439183, + 0x080a2507, 0x0b0d0608, 0x2506c142, 0x0e0e0e09, 0xa482090c, 0x0a20f384, 0xdd462f83, 0x46118511, 0x08860806, 0x06040623, 0x096b4304, 0x0820098e, + 0x83075642, 0x20b98617, 0x0a0f4700, 0x05080926, 0x0a141000, 0x2a058743, 0x040b0d09, 0x09090505, 0x46040504, 0x092006a0, 0x04210082, 0x25048204, + 0x0b0b0e07, 0xd0820b0a, 0x04060b26, 0x0c0e0809, 0x0a204e82, 0x0a270d82, 0x0908090e, 0x82050605, 0x820920d3, 0x04092809, 0x04040908, 0x820e0408, + 0x06092731, 0x08090507, 0xe582080c, 0x82060921, 0x82128315, 0x060d2122, 0x0d323082, 0x06090708, 0x0a090906, 0x06060304, 0x0c0c0c08, 0x00840b07, + 0x080a0e22, 0x06200082, 0x0b210082, 0x2010840c, 0x22058409, 0x840a0908, 0x0e09223d, 0x21908508, 0x0f850404, 0x08210586, 0x066c4409, 0x21087143, + 0xab480b09, 0x43058405, 0x1582083b, 0x21098743, 0x4582080a, 0xae826d82, 0x08040827, 0x0c040806, 0x21018309, 0x25820c0b, 0x0924dd82, 0x060a0f0e, + 0x88480183, 0x08052108, 0x5e410182, 0x0c0e210b, 0x61843e82, 0x82050821, 0x0e0e2134, 0x07207482, 0x8743a084, 0x040b3405, 0x0d070c0a, 0x0b050d0b, + 0x080a080b, 0x060b0b09, 0x820e0a09, 0x090b305e, 0x0d080809, 0x060b0d09, 0x09070908, 0x82090905, 0x0707261c, 0x08050909, 0x20188208, 0x05f34609, + 0x0c080b29, 0x0909050c, 0x83080c09, 0x0606283c, 0x0b0f0f04, 0x820b0a09, 0x224b827f, 0x820c090e, 0x0b0e2147, 0x0a2e0e82, 0x090d0a08, 0x10100a0b, + 0x0a0a0d0b, 0x31820a10, 0x09090625, 0x8209070b, 0x090b2197, 0xbe820082, 0x09080b25, 0x820e0e09, 0x0d0821d8, 0x06271082, 0x04040708, 0x830e0e04, + 0x0608236a, 0x01830c0e, 0x08080825, 0x47071010, 0x082a060f, 0x140c0708, 0x05050704, 0x4a820208, 0x0d090d28, 0x0b0d1008, 0x00820c0a, 0x0b0a0923, + 0x825c820a, 0x23478215, 0x040a0909, 0x06203782, 0x082e0085, 0x05100810, 0x04090304, 0x00000203, 0x09821010, 0x820c0921, 0x0d092173, 0x21068743, + 0x0083000a, 0x090c0827, 0x0b0d1009, 0x29b98209, 0x0b0c0e09, 0x090e0f09, 0x07820d07, 0x0822c482, 0x17821113, 0x0d100d22, 0x5d830b82, 0x820f1021, + 0x2708822b, 0x080b0608, 0x07090b0e, 0x082e7882, 0x0a0b0809, 0x0b0c090b, 0x0a0d0d11, 0x9841080a, 0x08092e05, 0x0a0b0b0d, 0x090b090a, 0x0a0d0a0d, + 0x41598306, 0x0a2005a3, 0x06206582, 0x0e220a83, 0x1d82080e, 0x45825c82, 0x81820920, 0x0d840c20, 0x43090b21, 0x0927085f, 0x0c0d0608, 0x820a0608, + 0x0909245f, 0x820f0e0e, 0x0e102382, 0x3b820e10, 0xb24e0a20, 0x0e534305, 0x2e833f86, 0x8743038b, 0x2033831c, 0x05044c0a, 0xba820b20, 0x00820820, + 0x20059a44, 0x32008200, 0x09030303, 0x11000508, 0x09000a14, 0x0b070404, 0x430c0e09, 0x0f201887, 0x0c2a4582, 0x0c0c0909, 0x080a0506, 0xf4820d0f, + 0x0d820b20, 0x090f0a2b, 0x06050a09, 0x0a070905, 0x21d78209, 0x87430609, 0x090f2a05, 0x060a0a0a, 0x08090608, 0x0e87430d, 0x060e0a37, 0x0e050908, + 0x06090709, 0x0b090a06, 0x06060304, 0x0d0d0d08, 0x822f8207, 0x0a0e2202, 0x20008209, 0x20008206, 0x8214820c, 0x0d092102, 0x4305ff41, 0x6e821087, + 0x00820a20, 0x2005a043, 0x827a8308, 0x085a4111, 0x0c0a0c22, 0x4e823186, 0x080c0922, 0x09220186, 0x8743090c, 0x080b2409, 0x430a0405, 0x0d210b87, + 0x20018309, 0x2004820b, 0x24dd820a, 0x0b0f0f0a, 0x43018306, 0x062108d0, 0x43018209, 0x058505ac, 0x820d0f21, 0x05cd411b, 0x88820520, 0x0d0e0e26, + 0x0a08090a, 0x04228782, 0xcf84030a, 0x0d0a0429, 0x0d0b0d08, 0x820b0a05, 0x0c0a251e, 0x0a0a060d, 0x0d203382, 0x0e289b84, 0x060d0e09, 0x09080a09, + 0x43833a82, 0x0a09082b, 0x09090805, 0x0b0a0808, 0x82cf820a, 0x0d0c21aa, 0x09211a82, 0x2809820d, 0x0606090a, 0x0c100f05, 0x82d6820a, 0x090b294b, + 0x0d0d0a0e, 0x0c0f0b0a, 0x0a2d4a82, 0x090e0a09, 0x11110b0c, 0x0a0b0e0b, 0x21688312, 0xf1820906, 0x38844982, 0x08080a22, 0x092efd82, 0x0b0f0f09, + 0x0e08090c, 0x06090909, 0x87430808, 0x0f072209, 0x8201830d, 0x111121c7, 0x21098743, 0x87430f06, 0x090e230b, 0xc5820e12, 0x72820d20, 0x0b0c0a22, + 0x07205c82, 0x22058543, 0x41040a0a, 0x200806ac, 0x09060606, 0x06110911, 0x05090304, 0x00000203, 0x03041111, 0x0f0d0a0a, 0x0d090a0f, 0x10100706, + 0x20b7820d, 0x82008300, 0x11092acd, 0x0f0a0b0e, 0x0f090a0c, 0x20b5820c, 0x2293820e, 0x830a0d0c, 0x121427f1, 0x0d0f0a0d, 0x0b820e11, 0x0a0a0926, + 0x0e10110a, 0xfa820683, 0x0c22ee82, 0x3743080a, 0x0a0b2705, 0x0b0d090c, 0x43820f12, 0x21470820, 0x08092f05, 0x0a0c0c0d, 0x090c090b, 0x0a0e0a0e, + 0xa1820e06, 0x0c220c83, 0x61820b09, 0x090a0627, 0x0e0e090a, 0x22778209, 0x820e090d, 0x080a2245, 0x210b830d, 0x01820d0a, 0x2009b445, 0x20368209, + 0x2c2b8209, 0x0a0a0809, 0x0d100f0f, 0x0e10090b, 0x212e8211, 0x77840b0d, 0x4d08d74d, 0x098309e1, 0x820c0a46, 0x0406230c, 0xe64b0406, 0x20059105, + 0x219f820c, 0x01870a0c, 0x44055242, 0x8743059a, 0x31e78206, 0x0b161200, 0x04050900, 0x0f0a0c07, 0x0505040d, 0x50820a0a, 0x20061843, 0x2100820a, + 0x04820404, 0x0b100833, 0x0a0c0b0b, 0x060d0c09, 0x10090a05, 0x0d0b0d0d, 0x21de820b, 0x9182100a, 0x05070523, 0x222f820a, 0x820b080b, 0x050b3706, + 0x10050905, 0x0b0b0a0b, 0x0b060907, 0x0a090d0a, 0x060a0608, 0x4483050a, 0x2c820a20, 0x0a060f25, 0x820f060a, 0x060626f1, 0x040c0b0a, 0x22068204, + 0x4a0d0d0d, 0x0b23057f, 0x820a0b0f, 0x0a874300, 0x1b820a20, 0x090d0d23, 0x2417840b, 0x080f0a0a, 0x2000820a, 0x20008205, 0x2111860a, 0x00820b0a, + 0x46086844, 0x0c2207f9, 0x1f870c0b, 0xfe872f82, 0x0620b383, 0x2708965d, 0x05050a0b, 0x0909090a, 0x0382ae82, 0x05090622, 0x03821e83, 0x0a210282, + 0x2301820d, 0x070b1010, 0x6e410183, 0x09062108, 0x24860182, 0x0d22fd82, 0xdc82100b, 0x2006fa43, 0x22828205, 0x820d0f0f, 0x43a0844f, 0x0b280587, + 0x080e0b04, 0x060e0c0e, 0x0b21be82, 0x21ca820a, 0x33820a06, 0x0b200782, 0x0e252782, 0x060d0e0a, 0x82b08209, 0x371c821d, 0x0a0b0808, 0x0b090906, + 0x0c0a0809, 0x080a080b, 0x0c0a0d0b, 0x0a0b060d, 0x0d280782, 0x06090b0a, 0x11100506, 0x0d200882, 0x0c22ed83, 0x44820e0a, 0x100c0a24, 0x0f820d0d, + 0x820b0921, 0x120c270d, 0x0b0f0c12, 0x4982130b, 0x82070a21, 0x0b08256a, 0x0e0a090b, 0x0b393e82, 0x0d0a0808, 0x100b0b09, 0x0a0e0c10, 0x0a0a0f08, + 0x0908070b, 0x0f050505, 0x24208210, 0x1007090b, 0x3901830d, 0x12090a09, 0x03030712, 0x06060304, 0x07080806, 0x0704150f, 0x02090606, 0x6a820a07, + 0x13090e26, 0x0e0b0d0e, 0x8d820082, 0x34456082, 0x820b2005, 0x43052000, 0x20080a87, 0x06120912, 0x050a0305, 0x00000204, 0x03051212, 0x100f0a0b, + 0x0e0a0b10, 0x11110706, 0x0c0d0a0d, 0x20008300, 0x28c2820a, 0x0b0c0e12, 0x0a0b0d10, 0x20078210, 0x23938211, 0x0a0d0c0e, 0x16280083, 0x110a0d13, + 0x0b0e120e, 0x21051350, 0x23821112, 0xc6820b20, 0x090b0725, 0x830a0d0e, 0x0a092414, 0x820b0c09, 0x130c2889, 0x0b0c0d0f, 0x82080908, 0x2313827e, + 0x0b0d0d0f, 0x0f2b1783, 0x060c0f0c, 0x0a0c0d0e, 0x820d0a0c, 0x23658226, 0x0a0b060e, 0x0f218782, 0x2777820a, 0x0d0e0a0d, 0x080a080a, 0x27431a83, + 0x20688305, 0x261f820b, 0x070a0b0c, 0x82090e0f, 0x090a2d67, 0x11100b0b, 0x090b0f10, 0x10130f12, 0x0c232582, 0x420c080a, 0x098e095c, 0x89053a46, + 0x05062305, 0x81430506, 0x82118611, 0x0c0d2190, 0xd8430187, 0x06e26d05, 0x00000038, 0x0b040404, 0x13000609, 0x0a000b17, 0x0c080405, 0x040d100a, + 0x87430606, 0x0c0c3616, 0x090a0d0c, 0x05060e0d, 0x0e110a0b, 0x0c0e0b0e, 0x0b0e0a0a, 0x24878211, 0x0a060706, 0x20d18208, 0x08874309, 0x0d821120, + 0x09080b2c, 0x0e0a0b06, 0x07080a0a, 0x8743070a, 0x0b0a3807, 0x0a0a0710, 0x080a1006, 0x0b06060a, 0x04040c0b, 0x0e0a0706, 0x82080e0e, 0x2102825d, + 0x87430c10, 0x820d2007, 0x83028214, 0x0e0e221b, 0x0787430a, 0x43091021, 0x6b431787, 0x0c092106, 0x0d200184, 0x2041f682, 0x060a4109, 0xb3820a20, + 0x87430b20, 0x090b240d, 0x84050a09, 0x0a062201, 0x221e8305, 0x820d0b0e, 0x25b58206, 0x11110a0e, 0x0183080c, 0x21080445, 0x01820a06, 0x05852485, + 0x830e1121, 0x82082063, 0x050826cb, 0x100a0c0a, 0x210f8210, 0x00820b09, 0x040b0522, 0xdd820582, 0x090e0b2b, 0x060f0d0f, 0x0b0a0c0c, 0x22ca820a, + 0x820c0b06, 0x0e0e2133, 0x62830c82, 0x0a060e22, 0x24098743, 0x060a0b09, 0x28268209, 0x0b0c0a09, 0x0b090a09, 0x242f840d, 0x0a0e0b0a, 0x2a5b820d, + 0x11050606, 0x0b0b0d12, 0x830b0c0e, 0x821020e9, 0x0d0b231c, 0x4a820e11, 0x0e325a82, 0x120c0e0a, 0x0c100c12, 0x0a0c140c, 0x0b070a0a, 0x87430e0a, + 0x09092109, 0x0b2d4082, 0x0d11110b, 0x0f090a0f, 0x070b0a0a, 0x09874309, 0x11080a23, 0x8201830e, 0x13133035, 0x04030308, 0x07070703, 0x0f070808, + 0x43080417, 0x0f260887, 0x0e0e130a, 0x00820e0c, 0x87437f82, 0x0c0c2309, 0x3445050b, 0x06062606, 0x0a130a06, 0x08874313, 0x0513132f, 0x100a0b03, + 0x0a0c1111, 0x1208060f, 0x20a08312, 0x82008300, 0x130b26f5, 0x110b0c0f, 0x2603820e, 0x130d0e0f, 0x82080a11, 0x0b0a2157, 0x16250182, 0x120b0e14, + 0x221d820f, 0x820b0c09, 0x12132200, 0x2905820e, 0x07090b0b, 0x0e100a0c, 0xe782080a, 0x090b092e, 0x0b0e0b0d, 0x10140c0f, 0x090c0c0e, 0x25069841, + 0x0d0d100a, 0x17840c0b, 0x060c0f25, 0x820d0e10, 0x820e20ef, 0x2361820e, 0x0a0c060e, 0x10213d82, 0x2077820a, 0x2145840e, 0x1a83090a, 0x11828f82, + 0x4a090c21, 0x0c280527, 0x10070a0b, 0x0b07090f, 0x0b32cd82, 0x1111110b, 0x13090b0f, 0x0e111410, 0x0a0c0d0a, 0xc5460d08, 0x06624208, 0x87430f88, + 0x92598513, 0x820b2005, 0x4c0c2077, 0x0e210504, 0x4339850c, 0x0a380d87, 0x18140006, 0x050a000c, 0x0b0d0805, 0x06050e11, 0x050b0b06, 0x0b070506, + 0x05210088, 0x380a8205, 0x0c0d1109, 0x0a0b0e0c, 0x06070d0e, 0x0e110a0b, 0x0c100c10, 0x0c0d0b0b, 0x201b8212, 0x2e128206, 0x0c0b0c08, 0x070a0c09, + 0x05050c0b, 0x8213050a, 0x080c280d, 0x0a0c0709, 0x820a0a0f, 0x0b0721e1, 0x0b3b4484, 0x110c090b, 0x060b0a07, 0x0b090a11, 0x0c0c0707, 0x0704050d, + 0x0f0f0a07, 0x840d090f, 0x82112000, 0x820b2053, 0x07072419, 0x83100e0e, 0x100b2100, 0x0b211783, 0x2217840c, 0x43110b0b, 0x0b200887, 0x1a821186, + 0x01450c20, 0x0b0d2107, 0x25058543, 0x0c0e090c, 0x64410c0e, 0x21058305, 0x01850b0e, 0x0d0c0d25, 0x8705070c, 0x0a0d2601, 0x0a0b0506, 0x0a87430a, + 0x23052741, 0x0b100c0e, 0x12230183, 0x83080c12, 0x081c4c01, 0x820b0721, 0x09d44401, 0x0f20fb82, 0x1e855d82, 0x0d0b0631, 0x1011110b, 0x0c090b0b, + 0x050c0b0c, 0x820c040c, 0x050d2900, 0x11090f0d, 0x0d06110d, 0x0b2a1382, 0x07100d0b, 0x0e110c0b, 0x0e82100b, 0x0f0b0b24, 0x0f830f0b, 0x060c0822, + 0x0b2f2982, 0x0c09080b, 0x0a0a060b, 0x0b090a0c, 0x82090c0d, 0x0a0d2446, 0x82060f0f, 0x820f2037, 0x0b0c2bbc, 0x13060707, 0x0c0b0e13, 0x5f820d0d, + 0x0b276a82, 0x0d0b0e0e, 0x83100d11, 0x0f0c2d0e, 0x130d0d0b, 0x0c100d13, 0x0b0c150d, 0x2d084a82, 0x080f0a0b, 0x0b0a0c0c, 0x0c0b0c0e, 0x0a09090c, + 0x0c0c0a0f, 0x100e1111, 0x0b11090b, 0x09080c0a, 0x05050509, 0x0a0c1111, 0x08090c0a, 0x01830f12, 0x0a0a0b26, 0x04081414, 0x08390082, 0x0a0a0808, + 0x05170f08, 0x0a060608, 0x0b0b0703, 0x0a100b0f, 0x0c100f14, 0x2200820f, 0x820e0c0c, 0x080e2160, 0x0b216482, 0x23b6820b, 0x0a0a0a05, 0x0806c652, + 0x0a140a21, 0x03050714, 0x0204050b, 0x14140000, 0x0b0c0405, 0x0d131111, 0x0807100b, 0x0b101212, 0x83000d0f, 0x0e0b2400, 0x82130c0a, 0x0e123db4, + 0x0f120b0d, 0x11130d0f, 0x0f0f080b, 0x0a0c0b10, 0x15180a0c, 0x10120c10, 0x090c1013, 0x0c24b683, 0x0c0e1314, 0x0a270083, 0x110a0c08, 0x82080b0f, + 0x0b0a2e78, 0x0d0c0d0a, 0x150e0f0c, 0x0c0c0f11, 0x053b5209, 0x1d820b20, 0x830d0d21, 0x0d102717, 0x11070d10, 0x7a460d0f, 0x0e112208, 0x240c8307, + 0x0a0b1111, 0x8301820f, 0x090b2245, 0x41c3820e, 0x0d2105e0, 0x05594309, 0x0b0c0d25, 0x83101008, 0x0a0b2567, 0x12120c0c, 0x09282782, 0x12131113, + 0x0e0e0b0f, 0x4905c255, 0x0b890b04, 0x85096042, 0x05072309, 0x59850507, 0xb7840591, 0x860f0d21, 0x482f8501, 0x00200522, 0x043c0082, 0x0b0c0404, + 0x1a150007, 0x050b000d, 0x0c0e0806, 0x06040f11, 0x060c0c06, 0x0c080607, 0x11830088, 0x12090c22, 0x0e2cec82, 0x0f0e0a0b, 0x0a0c0608, 0x0c0f0f12, + 0x0a2df082, 0x0b130c0f, 0x08060b0c, 0x0c090b06, 0x20d5820b, 0x0887430b, 0x08273d82, 0x0b0c0709, 0x820b0b10, 0x0c072206, 0x82568205, 0x0c0a2713, + 0x0c0a0711, 0x2f821107, 0x0c070725, 0x43060e0c, 0x12220d87, 0x00820b0d, 0x00820820, 0x840f0e21, 0x850c2000, 0x430c2005, 0x12210675, 0x211e820a, + 0x0082050b, 0x02894b82, 0x0b0c0b22, 0x20061e41, 0x05fb460a, 0x0e0c0e22, 0x2f833186, 0x21058543, 0xb3820b0e, 0xf5540c20, 0x24058305, 0x05060b0d, + 0x0b87430c, 0x0f221e83, 0x06850e0c, 0x1422d982, 0x0183080d, 0x23056843, 0x070a090b, 0x1d870183, 0x13220783, 0x79820c10, 0x20830920, 0x0d0c0627, + 0x0f12120b, 0x21d7820c, 0x87430c0c, 0x0d062908, 0x0e100a10, 0x0d0d0611, 0x0b272782, 0x0c080f0f, 0x820f120d, 0x0b0c2607, 0x0b100c0a, 0x250f8210, + 0x060c090c, 0x1e820c0c, 0x0c090925, 0x820a060c, 0x0c0a2426, 0x820a0c0d, 0x820f2016, 0x201a821f, 0x822f820c, 0x080829dc, 0x0f141306, 0x0d0f0c0c, + 0x0e222c82, 0x4483120b, 0x0f120e27, 0x0d0c0f0f, 0x284a820a, 0x14140e0f, 0x0d0d110e, 0x24498215, 0x0b0c080b, 0x214d820f, 0x2f820c0a, 0x0a0c0c26, + 0x0b0f0b09, 0x2d068743, 0x0b0b120a, 0x090a080c, 0x11050505, 0x6d820c12, 0x13080a23, 0x25018310, 0x150b0b0c, 0x87430915, 0x12092308, 0x87430419, + 0x0c0c2a05, 0x0b110c10, 0x0d0f1115, 0x20008210, 0x8352840c, 0x0c0c21b6, 0x0c225382, 0x34450b05, 0x07220805, 0x150b0707, 0x0507150b, 0x04060c04, + 0x15000002, 0x0d040515, 0x1312110c, 0x07100b0d, 0x0f131308, 0x8743100c, 0x318a8206, 0x0c0d1114, 0x0b0d0f13, 0x0d0e0f12, 0x090b1114, 0xa7821010, + 0x0b0c0b28, 0x0d10161a, 0x1d821113, 0x0c0d0a22, 0x15220082, 0x05821014, 0x0820bf82, 0x0b352a83, 0x0c0b0d09, 0x0e0a0c0a, 0x110c0f0d, 0x1012160e, + 0x0a0a0d0d, 0x23848209, 0x110b0b0b, 0x0e204882, 0x11249982, 0x080e110e, 0x0b205582, 0x0f250c83, 0x120c0e0c, 0x823b820f, 0x0b12233d, 0x01820f0b, + 0x0b0f1225, 0x410a0b09, 0x0d2309c0, 0x830b0c0a, 0x0c0e2601, 0x1011080b, 0x202b820a, 0x29d4820b, 0x10121212, 0x12140a0c, 0x42821215, 0x090b0e24, + 0x85430c0e, 0x460d2015, 0x088708a7, 0x08050823, 0x915d8905, 0x05024c09, 0x77850583, 0x2a0d8743, 0x1600070a, 0x0b000d1a, 0x83080606, 0x070422b9, + 0x15874307, 0x0e0d132e, 0x0b0c0f0d, 0x06080f0f, 0x10130b0d, 0xde824e83, 0x0c130d38, 0x08070c0c, 0x0d090c07, 0x0d0a0d0c, 0x0d0b070c, 0x060b0606, + 0x00820d14, 0x070a092e, 0x0b100b0d, 0x0c080a0b, 0x06060c08, 0x0c3a2882, 0x120d0b0c, 0x070c0b07, 0x0c090b12, 0x0d0d0707, 0x0705060e, 0x10100b08, + 0x2f820910, 0x13210282, 0x2025830d, 0x20008208, 0x8214820f, 0x100c2202, 0x2100820f, 0x17840d0c, 0x120c0c23, 0x201f830a, 0x85008206, 0x8374822f, + 0x08014508, 0x24058543, 0x0d0f0a0d, 0x8331860f, 0x0b0f212f, 0x15820186, 0x21085b63, 0x93820d06, 0x0b0b0d22, 0x23058c51, 0x060b070b, 0x20052741, + 0x2506850f, 0x15140d10, 0x0183090d, 0x2008f644, 0x20248207, 0x07d24407, 0x13240783, 0x0c0b0c10, 0x2a055345, 0x0c0d0c06, 0x0d101213, 0x820d0a0b, + 0x0d062293, 0x2a9f8404, 0x0a110d06, 0x07110f11, 0x820c0e0d, 0x100f248e, 0x820d0d08, 0x0f102233, 0x2537820d, 0x10100c10, 0xb0820c08, 0xf7820720, + 0x0a0d0b27, 0x070d0d0a, 0x22c8820b, 0x840e0d0a, 0x831f83c5, 0x0c102c1a, 0x0b0d0c0f, 0x14060808, 0x820d0f15, 0x224b82c0, 0x82120c0e, 0x0f0d233c, + 0x4a820f13, 0x0d0b0d22, 0x0f362282, 0x120f1616, 0x0d170d0e, 0x090c0d0c, 0x0a100c0c, 0x0c0b0d0d, 0x00820d10, 0x0b0a0a38, 0x0d0d0b10, 0x110e1414, + 0x0c130a0c, 0x0a090d0c, 0x0606060a, 0xfb821312, 0x090a0d22, 0x08088743, 0x09161620, 0x04050404, 0x0b080808, 0x1a12080b, 0x07070804, 0x0c08030b, + 0x120c110c, 0x1011160b, 0x0082110e, 0x7f820d20, 0x430c0c21, 0x5a820587, 0x43060c21, 0x16240a87, 0x0607160b, 0x34068743, 0x04061616, 0x13120c0d, + 0x110c0d14, 0x14140907, 0x0e100d10, 0x27008300, 0x0d0c100c, 0x0d0e1116, 0x0c2b1182, 0x0e0e1113, 0x0a0c1214, 0x82101010, 0x0b0d29ac, 0x0e11171a, + 0x12161115, 0x0c20fd82, 0x16215c82, 0x22be8415, 0x82090b0d, 0x0c1022ee, 0x050f430a, 0x81820e20, 0x170f1128, 0x0d0e1013, 0x214a0b0a, 0x120b2205, + 0x0594410f, 0x120e1228, 0x1012080e, 0x01820c0f, 0x9f410d20, 0x0d082605, 0x130c0d0c, 0x82b38212, 0x82122014, 0x206e8245, 0x07e0410d, 0x0b216882, + 0x3e01820d, 0x090c0d0f, 0x090b1112, 0x0b0c0c0d, 0x13140d0d, 0x0b0d1114, 0x13161216, 0x0f0f0d10, 0x4d0f0a0c, 0x0a4908d5, 0x200b830b, 0x22008e0c, + 0x42080608, 0x71430643, 0x83098709, 0x0e10218e, 0x87430187, 0x059a4405, 0x00820020, 0x0505053a, 0x00070b0d, 0x000e1c17, 0x0806060c, 0x10130d0f, + 0x0d070704, 0x0607060d, 0x20061843, 0x2100820d, 0x04820606, 0x0e140a38, 0x0c100e0e, 0x0810100b, 0x140b0d06, 0x110d1111, 0x100c0c0e, 0xbd82140d, + 0x43090721, 0x0b2b0587, 0x0c080c0d, 0x0b06060e, 0x820e1406, 0x0a092532, 0x110b0e08, 0x20058743, 0x2044840d, 0x35e8820d, 0x0d0b0813, 0x0a0c1307, + 0x0d08080d, 0x05060f0e, 0x110b0808, 0x074e1111, 0x140e2105, 0x0c225382, 0x0082080c, 0xf07d1020, 0x110d2205, 0x21008210, 0x17840d0c, 0x130c0c23, + 0x0887430b, 0x61820e20, 0x0e200283, 0x0b230082, 0x4a0e0b0d, 0x814a0554, 0x41fe8306, 0x10210925, 0x2201860c, 0x430e100e, 0x0e200987, 0x240c8743, + 0x11060b08, 0x2001830e, 0x20048210, 0x24dd820d, 0x0e15140d, 0x4c018309, 0x08210816, 0x4101820c, 0x1023094c, 0x4311140e, 0x07200887, 0x1423a182, + 0x820d1113, 0x0d0d22d7, 0x0687430d, 0x0e060e32, 0x0f120b12, 0x0e0e0812, 0x0c0c0d0c, 0x0d081110, 0x11213383, 0x3c0c8210, 0x120d120c, 0x0d0c0811, + 0x0e080e0a, 0x0d0b0e0d, 0x0d0e0a0a, 0x0e0c0b08, 0x0f0d0b0b, 0x250e820d, 0x110c100e, 0x1a820810, 0x0e2bba83, 0x0608080c, 0x0d101615, 0x820e100d, + 0x820f2068, 0x1111273c, 0x10140f0d, 0x0e821011, 0x0d120d2b, 0x16160f10, 0x0e0e130f, 0x24688218, 0x0c0d090d, 0x05b74a10, 0x0d372c82, 0x100b0a0b, + 0x140d0e0b, 0x0d121014, 0x0c0c130b, 0x0a0b090e, 0x82060606, 0x0b0b26dd, 0x14090b0e, 0x82018311, 0x171721c7, 0x36078743, 0x120a0a0a, 0x0808041b, + 0x08030b08, 0x0d110d0d, 0x12170c12, 0x82110e11, 0x217f8400, 0x1b42100d, 0x0e0e2405, 0x410c060d, 0x2b8205ac, 0x0c170c35, 0x04060817, 0x0205060d, + 0x17170000, 0x0c0e0406, 0x82141412, 0x09082804, 0x0d111515, 0x83000f11, 0x110c3400, 0x12160e0c, 0x10150d0e, 0x11140c0e, 0x13160e10, 0x82120b0d, + 0x0b0d2fca, 0x181c0b0d, 0x12150f12, 0x0b0e1316, 0x00820d0e, 0x11161722, 0x0b270784, 0x120d0e09, 0x820b0d10, 0x302482d9, 0x0e100d0f, 0x14181012, + 0x0b0e0e11, 0x0b0c0a0c, 0x2313820c, 0x0e0f1013, 0x13261783, 0x080f130f, 0xf2421012, 0x0d0f2607, 0x0e081114, 0x8268820c, 0x0c1023f5, 0x45830c10, + 0x820b0d21, 0x820e20c9, 0x110d238f, 0x3b820e0d, 0x21078743, 0xf9461213, 0x140d2c06, 0x0e131514, 0x1714160c, 0x820d1115, 0x0f0b224b, 0x9343830d, + 0x0e864303, 0x06080c24, 0x59850608, 0x10250591, 0x110e100e, 0x4301870f, 0x0c231387, 0x43180008, 0x0a210587, 0x24b98210, 0x0d070705, 0x4350820d, + 0x20081087, 0x0e0f0f15, 0x110c0d10, 0x0e070911, 0x1212150c, 0x0d0e120e, 0x150e110d, 0x070d0d0d, 0x0a0d0709, 0x2ad7820e, 0x0d080d0e, 0x0c06060e, + 0x820e1606, 0x0b0a2b00, 0x120c0e08, 0x090b0c0c, 0x8743090d, 0x0c0d3a06, 0x0c08140e, 0x0c14080d, 0x08080d0a, 0x06100e0e, 0x0c080805, 0x0a121212, + 0x2100840f, 0x4e820e14, 0x82090d21, 0x12102100, 0x0d220084, 0x00821112, 0x840e0d21, 0x0d0d2317, 0x18440b14, 0x06062105, 0x02835f82, 0x2205ce51, + 0x450c0e0c, 0x814a0512, 0x43f68307, 0x068206a7, 0x24081641, 0x090e110e, 0x27018706, 0x06070c0f, 0x0c0c0c0e, 0x0382ae82, 0x060c0822, 0x1222d283, + 0x0685100e, 0x150e1223, 0x056e4f16, 0x21089648, 0x01820d08, 0x43821120, 0x15240387, 0x0d0c0d12, 0x07291e85, 0x140d0f0d, 0x0d0e1214, 0x24aa820b, + 0x040e060e, 0x3300820e, 0x120e060f, 0x1310130b, 0x0d0f0f08, 0x110d0d0e, 0x0f0e0912, 0x12213382, 0x260c8211, 0x130d130d, 0x820d0912, 0x820820b0, + 0x0e0c2d29, 0x0e0e0b0b, 0x0e0c0c08, 0x0f0e0b0c, 0x1023c584, 0x8312120d, 0x0d12351a, 0x0d0e0d11, 0x16070909, 0x0e0e1117, 0x0f0e0f11, 0x140d100d, + 0x0e341c82, 0x12111510, 0x0d0e0e11, 0x110d130e, 0x10171710, 0x190e0f14, 0x0d290d82, 0x100d0d0a, 0x0c0e0e0b, 0x281c820d, 0x0a0b0e0e, 0x0e0c100c, + 0x0587430e, 0x0d0d1426, 0x0b0b0a0e, 0x83058743, 0x150a226d, 0x08018312, 0x0c0c0d23, 0x040a1818, 0x09040504, 0x0b0b0909, 0x051c120a, 0x0c08080a, + 0x0d0d0803, 0x0c130d12, 0x0f121318, 0x82008212, 0x22ba827f, 0x820d0911, 0x430f2000, 0x18220e87, 0x8743180c, 0x18183108, 0x0d0e0406, 0x0f161514, + 0x0a08130d, 0x0e121616, 0x82068743, 0x170e334d, 0x150e0f13, 0x150d0f11, 0x170e1112, 0x130b0d14, 0xac821212, 0x1c0c0e32, 0x160f1319, 0x0e131713, + 0x0e0d0f0b, 0x17180e0e, 0x07821682, 0x0f0a0c26, 0x0d10140d, 0x2b060f43, 0x0e110e10, 0x15191012, 0x0b0e0f12, 0x0c21e882, 0x2301820d, 0x0e101114, + 0x13291783, 0x090f130f, 0x0d101014, 0x22f98210, 0x82100e11, 0x0f092265, 0x823d820d, 0x0d1122f5, 0x21458411, 0xde410b0d, 0x455d8207, 0x103906bc, + 0x140a0d0e, 0x0e0a0c12, 0x0e0c0d0d, 0x1515150e, 0x170c0d13, 0x11151814, 0x21a5820e, 0xd54d100b, 0x0b0a4908, 0x60420b83, 0x22098509, 0x42090609, + 0x63890643, 0x4b820987, 0x470a8743, 0x22480559, 0x82002005, 0x05052600, 0x080d0e05, 0x20008200, 0x22038603, 0x8401001c, 0x0024220e, 0x24098303, + 0x04002e05, 0x08208303, 0x800092a0, 0x12000600, 0x61017e00, 0x92017f01, 0xb001a101, 0xff01f001, 0xbc021b02, 0xc902c702, 0xf302dd02, 0x03030103, + 0x0f030903, 0x8a032303, 0xa1038c03, 0xd203ce03, 0x0d04d603, 0x5f044f04, 0x91048604, 0x011e1305, 0x851e3f1e, 0xf91ef11e, 0x0b204d1f, 0x1e201520, + 0x26202220, 0x33203020, 0x3c203a20, 0x7f204420, 0xa720a420, 0x0521ac20, 0x16211321, 0x26212221, 0x5e212e21, 0x06220222, 0x12220f22, 0x1e221a22, + 0x48222b22, 0x65226022, 0x04fbca25, 0xfdfffffe, 0x0000ffff, 0xa0002000, 0x93826201, 0xaf01a022, 0xfa229382, 0x93821802, 0x9382c620, 0x9382d820, + 0x93880020, 0x93828420, 0xa3038e24, 0x9382d103, 0x0e040034, 0x60045004, 0x92048804, 0x3e1e001e, 0xa01e801e, 0x9382f21e, 0x13200026, 0x20201720, + 0x32229384, 0x93863920, 0x9382a320, 0x938cab20, 0x93865b20, 0x938a1120, 0x93826420, 0x93820120, 0xfffffc32, 0xc2ffe3ff, 0xb0ff0000, 0xb200bf00, + 0x49ff6100, 0x26080b82, 0xfe85fe96, 0xff76fe84, 0xff63ff68, 0x005dff62, 0xfd44ff67, 0xfdcffdd0, 0xfecdfdce, 0x007ffe82, 0x009afd00, 0x820cfe00, + 0x09550803, 0x18e458e4, 0x7de47ae3, 0x0de30000, 0xefe142e2, 0xede1eee1, 0xe1e1eae1, 0xdbe1e0e1, 0xd3e1dae1, 0x76e199e1, 0x000074e1, 0x0be118e1, + 0xfee009e1, 0xf4e0fbe0, 0x25e0c8e0, 0x1ae022e0, 0x12e019e0, 0x03e00fe0, 0xd0dfe7df, 0x69dccddf, 0x4f030000, 0x01005302, 0x20008300, 0x8604838e, + 0x86be2003, 0x20069907, 0x201a82a4, 0x200382bc, 0x870382d8, 0x87e02002, 0x20079408, 0x8f1594d2, 0x85b02014, 0x03b30810, 0x01840383, 0x01270126, + 0x01290128, 0x012b012a, 0x012d012c, 0x012f012e, 0x01310130, 0x01330132, 0x01350134, 0x01370136, 0x01390138, 0x013b013a, 0x013d013c, 0x013f013e, + 0x01410140, 0x014a0149, 0x02250124, 0x019c0168, 0x019e019d, 0x01a0019f, 0x01a201a1, 0x01a401a3, 0x01a601a5, 0x026902a7, 0x01ea016a, 0x01ec01eb, + 0x01ee01ed, 0x01f001ef, 0x01f201f1, 0x01f401f3, 0x016b02f5, 0x02f701f6, 0x02940293, 0x02960295, 0x02980297, 0x019a0299, 0x02f901f8, 0x03010200, + 0x0370036f, 0x03720371, 0x03740373, 0x021c0275, 0x02350234, 0x005e025d, 0x830a0206, 0x000121b9, 0x83064d41, 0x2203850c, 0x82020001, 0x210b8301, + 0x009d0002, 0x08058741, 0x040003bc, 0x06000500, 0x08000700, 0x0a000900, 0x0c000b00, 0x0e000d00, 0x10000f00, 0x12001100, 0x14001300, 0x16001500, + 0x18001700, 0x1a001900, 0x1c001b00, 0x1e001d00, 0x20001f00, 0x22002100, 0x24002300, 0x26002500, 0x28002700, 0x2a002900, 0x2c002b00, 0x2e002d00, + 0x30002f00, 0x32003100, 0x34003300, 0x36003500, 0x38003700, 0x3a003900, 0x3c003b00, 0x3e003d00, 0x40003f00, 0x42004100, 0x44004300, 0x46004500, + 0x48004700, 0x4a004900, 0x4c004b00, 0x4e004d00, 0x50004f00, 0x52005100, 0x54005300, 0x56005500, 0x58005700, 0x5a005900, 0x5c005b00, 0x5e005d00, + 0x60005f00, 0xe0826100, 0x0086de08, 0x00890087, 0x0093008b, 0x009e0098, 0x00a200a3, 0x00a600a4, 0x00a700a5, 0x00ab00a9, 0x00ac00aa, 0x00af00ad, + 0x00b000ae, 0x00b300b1, 0x00b400b5, 0x00b800b6, 0x00bc00b7, 0x00bd00bb, 0x000d02be, 0x00640072, 0x02690065, 0x0078000f, 0x007000a1, 0x0020026b, + 0x026a0076, 0x00880030, 0x002d029a, 0x02310273, 0x00670032, 0x02270277, 0x0129022a, 0x002e028d, 0x027c006c, 0x00a80021, 0x008100ba, 0x026e0063, + 0x0242012c, 0x0028022f, 0x027d006d, 0x00620010, 0x00850082, 0x01140197, 0x02020215, 0x020a0203, 0x0206020b, 0x02b90007, 0x01c10033, 0x0217023a, + 0x0214021c, 0x02340215, 0x000e0235, 0x02080279, 0x0011020c, 0x008c0084, 0x008d0083, 0x008f008a, 0x00910090, 0x0095008e, 0x3ce18296, 0x009c0094, + 0x009b009d, 0x014b01f3, 0x01710052, 0x014f014e, 0x017a0050, 0x01510153, 0x1105104c, 0x57080803, 0x59454000, 0x53545558, 0x4f505152, 0x4b4c4d4e, + 0x4748494a, 0x43444546, 0x3f404142, 0x3b3c3d3e, 0x3738393a, 0x30313536, 0x2c2d2e2f, 0x25262728, 0x21222324, 0x1114181f, 0x0d0e0f10, 0x08090a0b, + 0x04050607, 0x00010203, 0x4623452c, 0x26b02060, 0x2604b060, 0x2d484823, 0x23210f83, 0x20108261, 0x22108a61, 0x8220b060, 0x8d462012, 0x20b02123, + 0x61203783, 0x298c1a82, 0x29824020, 0x298e6620, 0x29854020, 0x53884020, 0x20100135, 0x2d3c003c, 0x2345202c, 0x44cdb020, 0x01b82023, 0x8258515a, + 0x448d260b, 0xb0205923, 0x200b84ed, 0x210b844d, 0x0c842604, 0x0c820d20, 0x82212121, 0x20230831, 0x44681845, 0x6001b020, 0x46b04520, 0x458a6876, + 0x2c2d4460, 0x0a0bb101, 0x65432343, 0x002c2d0a, 0x820b0ab1, 0x820b200a, 0x28b02809, 0x01b17023, 0x84013e28, 0x28022808, 0x02b13a45, 0x820d0800, + 0xb0453644, 0x61452503, 0x5150b064, 0x1b444558, 0x2d592121, 0x0eb0492c, 0x82498223, 0x43002155, 0xb0245284, 0x07b04306, 0x20225284, 0xba82b069, + 0x208b0037, 0x8ac02cb1, 0x0010b88c, 0x0c2b6062, 0x61642364, 0x03b0585c, 0x3c3b8261, 0x8a45038a, 0x11b0878a, 0x2329b02b, 0x7a29b044, 0x2c2d18e4, + 0x2cb06545, 0xb0454423, 0x2155832b, 0x6788524b, 0x72894b20, 0x05b00129, 0x20231025, 0x8200f58a, 0xed2322ce, 0x8ac782ec, 0x86612011, 0x25062411, + 0x8300f510, 0x4624081c, 0x8a604623, 0x2023468a, 0x8a608a46, 0x80ffb861, 0x10202362, 0x0cb18a23, 0x45708a0c, 0x00b02060, 0x01b05850, 0xba2c1782, + 0x46b01b8b, 0x10b0598c, 0x3a016860, 0x462eec86, 0x13b04b52, 0xb0585b51, 0x20462502, 0xfe826168, 0x3f260282, 0x1b382123, 0xc0821121, 0x0322f582, + 0x3f824625, 0x002b1e95, 0xb04307b0, 0x2d0b4306, 0x8321212c, 0xb88b24f8, 0x82620040, 0x80b0230c, 0x0f855851, 0x6200202c, 0x4000b21b, 0xb0592b2f, + 0x19836002, 0x1987c020, 0x83551521, 0x87802019, 0x083e8819, 0x2123602d, 0x534b2c2d, 0x04b08a58, 0x23644925, 0x40b06945, 0x80b0618b, 0x6120b062, + 0x230eb06a, 0xb0102344, 0x211bf60e, 0x11128a23, 0x822f3920, 0x202b82a3, 0x28b48220, 0x20696449, 0xb02605b0, 0x8b358306, 0x04b02230, 0x20328326, + 0x2104828a, 0x3b824423, 0xb0234483, 0x821bed0e, 0x11262560, 0x23392012, 0x47834682, 0x45234523, 0x22028660, 0x82186876, 0x2d203071, 0x2b48b02c, + 0x45202c2d, 0x585400b0, 0x824440b0, 0x61402108, 0x23061642, 0x2f30b145, 0x61263182, 0x6001b060, 0xb1824469, 0xb0585129, 0xb070232f, 0x42422314, + 0x4b220537, 0x96835851, 0x53694523, 0x85328458, 0xb0452715, 0x00b04314, 0x35866360, 0x452fb022, 0x45253b82, 0x8a452023, 0x20088460, 0x33068345, + 0x5851234b, 0xff3300b9, 0x2034b1e0, 0x0033b31b, 0x44590034, 0x2c081d82, 0x584316b0, 0x452603b0, 0x6664588a, 0x1b601fb0, 0x6020b064, 0x1b582066, + 0x5940b021, 0x596101b0, 0x59655823, 0x442329b0, 0x29b01023, 0x236e82e0, 0x59212121, 0x022bc282, 0x4b585443, 0x514b2353, 0x8238585a, 0x84592015, + 0x83188319, 0x2504224e, 0x22468e45, 0x851b5823, 0x05b03046, 0x2508b025, 0x02582008, 0xb059031b, 0x82102504, 0x46202110, 0x23220882, 0x05823c42, + 0x2507b023, 0x23038208, 0x2506b010, 0xd1821584, 0x20241882, 0x001b0158, 0x86822d87, 0x2029b025, 0x86446545, 0x8c0f8327, 0x230c8254, 0x48432503, + 0x06244d87, 0x2503b025, 0x43244782, 0x59211b48, 0x0283bd82, 0x022c2d22, 0x20201e82, 0x23216284, 0x20828242, 0x21238208, 0x1a874845, 0x20250322, + 0x08221e82, 0x468202b0, 0x24081382, 0x23452c2d, 0x20184520, 0x205000b0, 0x23652358, 0x20682359, 0x585040b0, 0x5940b021, 0x59655823, 0x2d44608a, + 0x060c412c, 0x82452021, 0x0595410d, 0x58544b22, 0x2c410d8b, 0x2c2d240a, 0x822100b0, 0x8538201e, 0x02b02728, 0xb0585443, 0x43412b46, 0x200f8408, + 0x410f8447, 0xb021076b, 0x201e8e48, 0x820f8449, 0x8a202b1e, 0x534b2308, 0x5a514b8a, 0x50862358, 0xb9820020, 0x00b04924, 0xa6825853, 0x82113821, + 0x2c2d2ef6, 0x46234601, 0x61462360, 0x20102023, 0x05cf4346, 0x40b18a35, 0x45708a40, 0x2d3a6860, 0x238a202c, 0x238a6449, 0x843c5853, 0x524b262d, + 0x7a1b7d58, 0x08a78259, 0x4b00122a, 0x42544b01, 0x02b12c2d, 0x23b14200, 0xb1518801, 0x53880140, 0x10b9585a, 0x88200000, 0x02b25854, 0x60430201, + 0x24b15942, 0x58251b82, 0x000020b9, 0x20158440, 0x83158302, 0x20228314, 0x830c8320, 0x82522049, 0x8408202f, 0xb91b252f, 0x80000040, 0x04202a84, + 0x0f841084, 0x01b86323, 0x85138400, 0x24138224, 0xb8630001, 0x20138502, 0x20278710, 0x20138202, 0x20138504, 0x20138440, 0x38008259, 0x18452c2d, + 0x514b2368, 0x45202358, 0x40b06420, 0x597c5850, 0x59608a68, 0x24c58244, 0x02b01600, 0x37028225, 0x2301b001, 0x02b0003e, 0x01b13e23, 0xb00c0602, + 0x4265230a, 0x42230bb0, 0x3f201783, 0x3f201783, 0x06201785, 0x07311783, 0x01b04223, 0x2c2d0116, 0x45108a7a, 0x2d18f523, 0x08db8200, 0xf809105c, + 0x8f1fff03, 0x02f79ff7, 0x6001f37f, 0xffb801f2, 0xeb2b40e8, 0xdf46100c, 0xde55dd33, 0x3055dcff, 0x01dd01dd, 0x03dc5503, 0xc2301ffa, 0xefc06f01, + 0xb6fc02c0, 0xb7301f18, 0x80b76001, 0xffb802b7, 0xb73840c0, 0xe746130f, 0xaf1f01b1, 0xaf3faf2f, 0x5faf4f03, 0x03af6faf, 0x1582af40, 0x51ac3a08, + 0x9c1f1f18, 0xe0029c5f, 0x2b03019b, 0x9a1f019a, 0xa09a9001, 0x9a73029a, 0x05029a83, 0x40eaffb8, 0x0b099a19, 0xbf97af46, 0x2b030297, 0x961f0196, + 0xaf969f01, 0x967c0296, 0x211d8401, 0x1d829685, 0x922f5908, 0x924f923f, 0x0c924003, 0x912f460f, 0x01919f01, 0x1f188687, 0x7c507c40, 0x74100302, + 0x74307420, 0x01740203, 0x0a0174f2, 0x6fff016f, 0x016fa901, 0x75016f97, 0x026f856f, 0x0a016f4b, 0x6eff016e, 0x016ea901, 0x4b016e97, 0x1a06016e, + 0x19551801, 0x071fff13, 0x061fff04, 0x2308fb82, 0x1f01673f, 0x3f672f67, 0x0467ff67, 0x66506640, 0x66b066a0, 0x01653f04, 0x65af650f, 0x64a00502, + 0x030264e0, 0x4e08e483, 0x0a06644f, 0x2b5f6146, 0x475f601f, 0x22505f1f, 0x015bf71f, 0x54015bec, 0x025b845b, 0x3b015b49, 0x5af9015b, 0x015aef01, + 0x4b015a6b, 0x5a3b015a, 0x33130601, 0x01055512, 0x33045503, 0x031f5503, 0x3f030f01, 0x0303af03, 0x571f570f, 0x8303572f, 0x56b32b53, 0xb8461512, + 0x56b3e0ff, 0x07820b07, 0x54b3c022, 0x87080f84, 0x546d40c0, 0x52460b06, 0x3f1f2b50, 0x5f504f50, 0x48fa0350, 0x0148ef01, 0x65014887, 0x48560148, + 0x01483a01, 0xef0147fa, 0x47870147, 0x01473b01, 0xff1b1c06, 0x1533161f, 0x0f011155, 0x0f331055, 0x00010255, 0x00470155, 0x2bfafb55, 0x121bfa1f, + 0x010f0f1f, 0x0fcf0f1f, 0xff0f0f02, 0x6f06020f, 0xaf007f00, 0x0400ef00, 0x80010010, 0x01050116, 0xb19001b8, 0x2b2b5354, 0xff07b84b, 0x06b04b52, + 0x01b05b50, 0x5325b088, 0x22080583, 0xb05a5140, 0x00b08806, 0x585b5a55, 0x8e0101b1, 0x8d8d8559, 0x4b1d4200, 0x585332b0, 0x591d60b0, 0x8264b04b, + 0x83402008, 0x82802008, 0x1d102d08, 0x420016b1, 0x5e737359, 0x2b757473, 0x01220086, 0x0088735f, 0x2b730023, 0x24168301, 0x7300735f, 0x8c088274, + 0x210f831b, 0x3b835f2b, 0x74737323, 0x200d8200, 0x201e852b, 0x203e8474, 0x20318274, 0x20108274, 0x2207822b, 0x8201732b, 0x74732428, 0x85735f74, + 0x82002007, 0x2b012763, 0x74732b00, 0x05837301, 0x06822b20, 0x2b2b7322, 0x01210282, 0x343d822b, 0x5e182b00, 0x0b001406, 0xb6054e00, 0x75001700, + 0xcd05b605, 0x29008c00, 0x14004a04, 0x00008f00, 0x1683ecff, 0xfe220589, 0x1083fe14, 0x082103c8, 0x24008400, 0x00b600ac, 0x200982bc, 0x830382d5, + 0x00552c02, 0x00970083, 0x007d009f, 0x82ae00e5, 0x00712201, 0x23168371, 0xc500ba00, 0x0a830382, 0x1d82a420, 0x08838c20, 0x82c70021, 0x827d2001, + 0x860c8429, 0x00b02404, 0x848a00b9, 0x009b220b, 0x20c782a6, 0x850b8477, 0x85962004, 0x29058406, 0x006e0069, 0x00b40090, 0x798700c1, 0x6600002e, + 0x78006f00, 0xc0009600, 0x4701d500, 0x00242584, 0x3a01fe00, 0x78207982, 0x16220782, 0x1386f601, 0xee20068f, 0x96221082, 0xad828800, 0x89009633, + 0x96000c01, 0x00001801, 0x94001d03, 0x82005a02, 0x21758303, 0xb18400a8, 0x00790231, 0x01b400d9, 0x0100000a, 0x006d0083, 0x82a0007f, 0x82002039, + 0x84882009, 0x20048b07, 0x221b8493, 0x89890082, 0xb6052914, 0x110094fc, 0x8300efff, 0x1683d782, 0x7b006d22, 0x03860683, 0xaa01bc24, 0x0b845403, + 0xb600bc26, 0x9501d701, 0x96300b82, 0xae000001, 0xbcfeb605, 0x83fe6ffe, 0xad026f00, 0x2a211382, 0x08018500, 0xa1006fba, 0xe2012901, 0x29037102, + 0x7c034d03, 0xe203ac03, 0x44040f04, 0x95045b04, 0x0605b404, 0x94053f05, 0x65061206, 0x3f07cc06, 0x11086707, 0xda088208, 0x79093d09, 0xf709bb09, + 0x340b6a0a, 0x170ca00b, 0xb30c740c, 0x390dec0c, 0xcd0d970d, 0x490e100e, 0xb70e970e, 0x7c0f2b0f, 0x2210d50f, 0xf7108610, 0xa2116111, 0x3312e011, + 0x4813e912, 0xcc139913, 0x1214f213, 0x54143614, 0x90146b14, 0x64150315, 0x0916a915, 0xc9166616, 0xde179d17, 0x5a180f18, 0xc318aa18, 0x72193419, + 0x1d1abb19, 0xc41a7e1a, 0x891b341b, 0x221cca1b, 0x601dcf1c, 0x161ec91d, 0x941e701e, 0x431ff01e, 0xbc0b0182, 0x20ef1f8b, 0x21fc2065, 0x229f216f, + 0x239c2258, 0x24af2345, 0x24302403, 0x25072538, 0x2579251e, 0x260526b5, 0x269f267a, 0x272627e9, 0x27a62760, 0x282528dd, 0x289e2875, 0x29f228c3, + 0x29802968, 0x29af2997, 0x2adf29c6, 0x2a6d2a04, 0x2a982a80, 0x2ac72aaf, 0x2bf82ae0, 0x2b262b0f, 0x2ba32b3f, 0x2bd22bba, 0x2c002ce9, 0x2c312c18, + 0x2d172d96, 0x2d462d2f, 0x2d772d5e, 0x2ed82d8e, 0x2e8a2e73, 0x2eb62ea0, 0x2ee42ecc, 0x2fac2ffc, 0x2fd62fbf, 0x300230ec, 0x3032301a, 0x30603049, + 0x31093179, 0x3136311f, 0x3163314c, 0x3293317a, 0x327d3204, 0x32aa3294, 0x32d932c0, 0x335433ef, 0x3384336c, 0x33b1339a, 0x33de33c7, 0x341234fb, + 0x3441342a, 0x34703459, 0x34a03489, 0x34d034b8, 0x35eb34e3, 0x357b3564, 0x35a83591, 0x35d535be, 0x360036ec, 0x36383621, 0x3665364e, 0x3692367b, + 0x36c036a9, 0x37eb36d8, 0x37193701, 0x37873736, 0x38f937e2, 0x38273810, 0x3855383e, 0x387f386c, 0x38aa3893, 0x39ec38c3, 0x39273910, 0x3951393e, + 0x39ad3964, 0x39e239c5, 0x3a093af5, 0x3a393a21, 0x3a6f3a4c, 0x3b093bbc, 0x3b363b20, 0x3b5d3b4a, 0x3b8b3b74, 0x3c0e3cad, 0x3c7e3c67, 0x3cab3c94, + 0x3cdb3cc2, 0x3d643df3, 0x3e0a3ef2, 0x3e333e20, 0x3e5f3e47, 0x3e8e3e77, 0x3ebb3ea4, 0x3ee53ed1, 0x3f0f3ff8, 0x3f383f25, 0x3f633f4c, 0x40cc3f75, + 0x404e4036, 0x407c4064, 0x40a94092, 0x40d840bf, 0x410941f0, 0x41344121, 0x415e4147, 0x418c4175, 0x41bb41a2, 0x41e841d2, 0x421642ff, 0x4243422d, + 0x43da4276, 0x449144bc, 0x44c044a9, 0x45ed44d7, 0x45134500, 0x457f4549, 0x45d24597, 0x464946f9, 0x47bd4676, 0x472d4700, 0x47b7479e, 0x481648f1, + 0x487d483c, 0x49e248ae, 0x4923490a, 0x4933492b, 0x49b14965, 0x49c149b9, 0x4a384ac9, 0x4a484a40, 0x4a9c4a94, 0x4af14aa4, 0x4b244bf9, 0x4b744b2c, + 0x4c844b7c, 0x4c1b4c13, 0x4d0b4d89, 0x4d3d4d24, 0x4d694d53, 0x4d974d7f, 0x4e1e4eac, 0x4fff4ea0, 0x50035087, 0x51a95069, 0x5159511b, 0x52dd5161, + 0x536d522b, 0x5315530d, 0x54c35369, 0x548b5432, 0x551755d5, 0x56295695, 0x5714578a, 0x5746572d, 0x5772575c, 0x58a95790, 0x583a5823, 0x58ad58a5, + 0x58ce58b5, 0x596d59d6, 0x5a2a5acc, 0x5a585a41, 0x5aa95aa1, 0x5b045bfc, 0x5b7f5b0c, 0x5c145c87, 0x5df65c97, 0x5d565d0e, 0x5dc25dba, 0x5dd25dca, + 0x5de25dda, 0x5ef25dea, 0x5e6a5e62, 0x5ea75e72, 0x5f365fee, 0x60e25f8c, 0x60866038, 0x616061e9, 0x62e561dd, 0x62d26260, 0x636063fa, 0x64dd6368, + 0x649f645b, 0x65f064b6, 0x65a0653b, 0x66ee65e6, 0x661f6617, 0x66666627, 0x66eb666e, 0x672d67f3, 0x68b8676d, 0x686e6811, 0x691a69d0, 0x6af76983, + 0x6a666a4e, 0x6beb6ad5, 0x6b4f6b47, 0x6b706b57, 0x6cf06b78, 0x6ca96c4f, 0x6dd56cbf, 0x6d4f6d1a, 0x6d926d7a, 0x6dc06da9, 0x6ef16dd7, 0x6e236e0b, + 0x6e566e3b, 0x6e8c6e71, 0x6fe06eb5, 0x6f3f6f0c, 0x70c96f6d, 0x708f7025, 0x717071ea, 0x735872b3, 0x732d7325, 0x73687335, 0x73af739d, 0x741074cd, + 0x75f2746b, 0x7610767c, 0x773c77be, 0x787978f2, 0x79e47881, 0x793c790d, 0x7a96796b, 0x7a5d7a10, 0x7ad67a8c, 0x7b287bfc, 0x7c157cc4, 0x7d167d9e, + 0x7d9f7d5b, 0x7e0a7eeb, 0x7e6b7e28, 0x7ec47e9e, 0x7f0e7fe9, 0x7f9a7f51, 0x805680f7, 0x81228185, 0x0a01998c, 0x83d68286, 0x83558349, 0x8406845d, + 0x851f8583, 0x854d8536, 0x85758561, 0x86ef85a2, 0x866f8642, 0x8710879b, 0x88d68777, 0x885e8839, 0x89ca8883, 0x89298909, 0x89598941, 0x8a878970, + 0x8bdf8a24, 0x8cd58b60, 0x8db78c46, 0x8ece8d3b, 0x8f128f66, 0x915790b3, 0x92b59105, 0x938e939f, 0x949e9396, 0x946b940b, 0x953395cb, 0x9667954d, + 0x963d9627, 0x984197c3, 0x992e9945, 0x9be19af4, 0x9c929b43, 0x9c969c51, 0x9d089dd9, 0x9e189e39, 0x9f5c9fb6, 0xa03fa0e4, 0xa11fa1a3, 0xa20ca2ad, + 0xa3caa25c, 0xa4cca32e, 0xa497a481, 0xa521a5ad, 0xa6faa58c, 0xa7d3a66d, 0xa789a73f, 0xa829a8db, 0xa9cba882, 0xa984a919, 0xaba8aaf7, 0xab66ab52, + 0xacc9ab7a, 0xac20ac18, 0xadf4ac83, 0xae0aae63, 0xaf31afca, 0xb0eeaf8f, 0xb1b1b04a, 0xb162b114, 0xb22ab2a8, 0xb347b3ba, 0xb4e9b3e1, 0xb417b400, + 0xb5f4b485, 0xb6bfb567, 0xb672b611, 0xb712b7b9, 0xb8b8b76c, 0xb8bcb83c, 0xb8dbb8c4, 0xb90ab9f1, 0xb92ab922, 0xb949b932, 0xbac5b95f, 0xba3dba23, + 0xba6fba56, 0xbaa3ba89, 0xbb27bbbd, 0xbba7bb8f, 0xbbd8bbbe, 0xbc0abcf1, 0xbc2bbc23, 0xbc4cbc33, 0xbc7ebc64, 0xbcb0bc98, 0xbce0bcc6, 0xbd11bdf8, + 0xbd42bd29, 0xbda1bd5a, 0xbef5bddc, 0xbe20be0e, 0xbe4bbe32, 0xbfe2be61, 0xbfdfbf95, 0xc061c0e7, 0xc286c1ed, 0xc39dc218, 0xc4b6c323, 0xc47fc423, + 0xc54ac5e6, 0xc621c6c6, 0xc700c782, 0xc798c784, 0xc7c3c7ac, 0xc8f1c7da, 0xc822c808, 0xc855c83b, 0xc888c86e, 0xc8bbc8a1, 0xc9f8c8d4, 0xc932c919, + 0xc964c94b, 0xc996c97d, 0xc9c8c9af, 0xca03cae1, 0xca3bca24, 0xca69ca52, 0xca98ca80, 0xcac8caae, 0xcbfbcae1, 0xcb2ecb14, 0xcb61cb47, 0xcb9ecb7a, + 0xcbd6cbbf, 0xcc05cced, 0xcc34cc1d, 0xcc63cc4c, 0xcc93cc7a, 0xccc6ccad, 0xcdf9cce0, 0xcd2ccd13, 0xcd68cd46, 0xcda3cd8c, 0xcdd2cdba, 0xce01cee9, + 0xce31ce19, 0xce60ce48, 0xce8fce78, 0xcebecea7, 0xcfedced5, 0xcf1acf02, 0xcf45cf2f, 0xcf73cf5b, 0xcfa0cf88, 0xcfd0cfb8, 0xd0fdcfe6, 0xd02bd014, + 0xd055d041, 0xd1f1d098, 0xd2b5d146, 0xd275d22a, 0xd324d3c3, 0xd3bad38d, 0xd40ad4e2, 0xd492d47f, 0x000200a6, 0x040000c1, 0x00b6050a, 0x00070003, + 0x050b402b, 0x04090202, 0x03800370, 0x2705e94a, 0x48090609, 0x07030403, 0x3f331e82, 0x01332f32, 0x335d2b2f, 0x332f3311, 0x21133031, 0x82372111, + 0x03c13003, 0x68b7fc49, 0x87fd7902, 0x4afab605, 0x82e60468, 0xff932453, 0x849101e3, 0x17300853, 0x00b93a00, 0x40f0ff01, 0x48140a13, 0x19801910, + 0x19a01990, 0x9a0e0304, 0x04020204, 0x40c0ffb8, 0x480a070a, 0x9b090104, 0x00030213, 0xcef52f3f, 0x48086182, 0xe1102f33, 0x30315d32, 0x0323012b, + 0x3e340333, 0x1e323302, 0x0e141502, 0x2e222302, 0x79500102, 0x14f0df33, 0x1a1b2e22, 0x1414222f, 0x1b1a2f22, 0x0114222e, 0xfa18049e, 0x213526b9, + 0x35210f0f, 0x22352526, 0x35221010, 0x24898200, 0x02a60385, 0x3e8984b2, 0x40370007, 0x07980423, 0x09d00907, 0x2f0209e0, 0x7f096f09, 0x98000309, + 0x03100300, 0x82f003e0, 0x020624e4, 0x82030702, 0x82332085, 0x2f0130df, 0x5d5de15d, 0xe12f3912, 0x03013031, 0x82210323, 0x4a012f03, 0x02297329, + 0x2972292d, 0xf0fdb605, 0x03831002, 0x33246383, 0xf8040000, 0x70086382, 0x001f001b, 0x03584099, 0x181a1a03, 0x071d1e16, 0x17170604, 0x01001906, + 0xb1050404, 0x15211818, 0x04081c1f, 0x12141409, 0x040b0e0f, 0x500ab113, 0x10100110, 0x50090c0c, 0x1c0a010a, 0x010d4801, 0x080cae0d, 0x001f0c04, + 0x1911ae10, 0x113f1115, 0x11df114f, 0x0c110c03, 0x13170511, 0x00050a06, 0x333f332f, 0x2f393912, 0x33115d2f, 0x32e11033, 0x22068432, 0x8232325d, + 0x2db383ac, 0xe4105d2f, 0x11323917, 0x11391712, 0x0a832f33, 0x0b863320, 0x832f3321, 0x152121c5, 0x1320c582, 0x35230384, 0x82211321, 0x03332303, + 0x03821321, 0x82011521, 0x0331080e, 0x18013fd7, 0x9352cdfe, 0x52ddfe54, 0xfefe4e90, 0xfe411d01, 0x522b01ee, 0x25015293, 0x01549054, 0x01ebfc06, + 0xddfe4023, 0xb8fe7d03, 0x0154fe89, 0x270383ac, 0x89480189, 0x50feb001, 0x80080383, 0x01b8fe89, 0x00030048, 0x0389ff7b, 0x001206d9, 0x0036002d, + 0x40b4003f, 0x292f3433, 0x212f2901, 0x70062101, 0x3c013c2f, 0x1e011e2f, 0x01072013, 0x2e0d0707, 0x000f246e, 0xff02001f, 0x00000100, 0x41000701, + 0x6e370d0d, 0x190119e0, 0x40c0ffb8, 0x480b0830, 0x14143319, 0x133c3c29, 0x3d08372e, 0x25217328, 0x0e401f21, 0x1f1f4811, 0x0121501e, 0x211f210f, + 0x34210802, 0x0e087313, 0x05060608, 0x33348208, 0x480d0ab3, 0x2b2f0008, 0x112f3333, 0x32e11033, 0x5d5d5e2f, 0x2b200b82, 0x12320c84, 0x39123939, + 0x11333311, 0x2b2f0133, 0x2f33e15d, 0x1e82d610, 0xe1327125, 0x822f3911, 0x335d2525, 0x5d32e15d, 0x28080182, 0x14013031, 0x1507020e, 0x2e223523, + 0x1e352702, 0x2e113303, 0x3e343503, 0x33353702, 0x17161615, 0x27262607, 0x07031e11, 0x081d8234, 0x363611d8, 0x021e1401, 0x06061117, 0x5d32d903, + 0x328a5485, 0x20546066, 0x65605721, 0x5683592f, 0x815b312a, 0xa9648a4f, 0x8c384243, 0x5b87584a, 0x2b14b02e, 0x5b5d3346, 0x281112fe, 0x53593142, + 0x7246be01, 0xe60c3754, 0x1a1209dd, 0x2110ac11, 0xb201111a, 0x6e55421e, 0x536f434a, 0xb0b40935, 0x911f2a05, 0xfe062919, 0x53421f5a, 0x3721486b, + 0xfe12262d, 0x02620e8b, 0x2f3924a3, 0x71011126, 0x00005910, 0xff660005, 0x053306ec, 0x000900cb, 0x0027001d, 0x003f003b, 0x103cb25d, 0xf0ffb83e, + 0x3e3c3340, 0x14283e3c, 0xb532b41e, 0x4128b423, 0x0501410f, 0x00b50ab4, 0x201410b4, 0x03143014, 0x3e063f14, 0x37b62518, 0x2db621b7, 0x0fb60319, + 0x19b607b7, 0xe13f0007, 0x0384e1f4, 0x2f013f23, 0x220b825d, 0x82de105d, 0x12113505, 0x2f2f3939, 0x30313838, 0x33161413, 0x23101132, 0x14050622, + 0x20059643, 0x06a64335, 0x19990120, 0x0123013d, 0x9c5047fa, 0x0147509c, 0x734a24c7, 0x4c70494f, 0x71492326, 0x4d714b4e, 0x86ac0127, 0x23c62119, + 0x4a221982, 0x19864b70, 0x274c2708, 0xd5fc00ff, 0x042c039e, 0x01a5a502, 0xa348014a, 0x76ac6ca5, 0xac763f3f, 0x75aa6c6c, 0xaa753e3e, 0xa4a54afd, + 0x18844901, 0x1883ab20, 0x1887ab20, 0x92035608, 0xb6054afa, 0x00030000, 0x05ecff6d, 0x00cd057d, 0x00210011, 0x40800053, 0x1718274d, 0x2c49044a, + 0x470a4849, 0x42474136, 0x36014220, 0x1d423642, 0x473c3b05, 0x47004804, 0x2c102c00, 0x2c2c0802, 0x01482022, 0x481d5548, 0x22202210, 0x41412202, + 0x4f511231, 0x323b8416, 0x3b3c470f, 0x49310405, 0x31500f15, 0x3fe12f00, 0x82391712, 0xe13f2b02, 0x012f3911, 0x10e15d2f, 0x09825dc6, 0xe15d5e23, + 0x2b178211, 0x2f2f3939, 0x10e1105d, 0x113311e1, 0x31382482, 0x1e140130, 0x033e1702, 0x022e3435, 0x13062223, 0x37023e32, 0x15030e01, 0x25211582, + 0x420b8234, 0xf2440569, 0x07620807, 0x37033e01, 0x07030e33, 0x0e272301, 0x2e222303, 0x10a60102, 0x3b243421, 0x191c3856, 0x562a422f, 0x623a8764, + 0xfe204854, 0x3750347d, 0x6042231c, 0x4d287dfe, 0x3c1f476f, 0x5e321c2d, 0x8353588a, 0x5432305b, 0x60013c6d, 0x1b222b1b, 0x290fb80a, 0x01274135, + 0x31a8e115, 0x4e7c6c60, 0x3d73a769, 0xd9828d04, 0x25436608, 0x46403e23, 0x2c3d2429, 0xaffb5919, 0x1f362817, 0x3f219701, 0x36385548, 0xf024415b, + 0x56647a4e, 0x574d242a, 0x774b3963, 0x532b2b53, 0x6d404b77, 0xfe244f5d, 0x443c1d8c, 0x6f422f4e, 0xfe295562, 0x472dacdb, 0x67351b31, 0x00010095, + 0x01a60385, 0x00b6054a, 0x402a0003, 0xd005c01c, 0x0305e005, 0x056f052f, 0x0b6c4502, 0x03020227, 0x333f0003, 0x0568452f, 0x23056445, 0x73294a01, + 0x20065b45, 0x24478200, 0x02bcfe52, 0x2a47822b, 0x401a0013, 0xf20e060d, 0x823ff009, 0xf90e2615, 0x3f00f805, 0x0837833f, 0x3132e438, 0x3e341330, + 0x06333702, 0x1e141502, 0x2e231702, 0x4a245203, 0x8cac4e71, 0x6a472591, 0x714eaa45, 0x3102244a, 0xd3e5f37d, 0x32fec15d, 0xe2ec77f4, 0xce5a5ed4, + 0x5d83f0e1, 0x5d823d20, 0x5d841720, 0x0e401c22, 0x0b225d82, 0x5d82b0f0, 0xf80e1524, 0x5e83f905, 0x5dde1023, 0x3f5f83e1, 0x020e1401, 0x033e2307, + 0x27023435, 0x02031e33, 0x714b2417, 0x6a45aa4e, 0x8d902448, 0x4b714eac, 0x7c315f82, 0x5acee1f0, 0xece2d45e, 0xce01f477, 0xe5d35dc1, 0x2ebd84f3, + 0x14047702, 0x0e001406, 0x15402400, 0x8201101f, 0x800e39fc, 0x030e900e, 0x061f0e08, 0x00060601, 0x323f0000, 0x2f015d2f, 0x5de55d5e, 0x3708ff83, + 0x13051725, 0x27030307, 0x05372513, 0x2b980203, 0xfe1a8d01, 0xb0b2f586, 0xfef2b89e, 0x87011d89, 0xfe14062b, 0x1cc16f77, 0x0160bafe, 0x609afe66, + 0xc11c4601, 0x0089016f, 0x3008b582, 0x04060166, 0x00a20402, 0x4029000b, 0x010d1018, 0x03aa0906, 0x200100ef, 0xa0006000, 0x09000300, 0x0306ad00, + 0x333f00b3, 0x2f0132e1, 0xe1325d5d, 0x08708332, 0x21352120, 0x21113311, 0x23112115, 0x7dfee901, 0x01968301, 0x967dfe83, 0x01968702, 0x967bfe85, + 0x59837ffe, 0xf8fe3f30, 0xee007901, 0x38000c00, 0x0ecf1440, 0xc1821001, 0x0ea02108, 0x2b0c1b03, 0x010c020c, 0xb8070697, 0x0d40c0ff, 0x5f481410, + 0x07100107, 0x9c060701, 0xed2f000c, 0x2b256583, 0x5d32ed33, 0x0868825d, 0x0e172522, 0x3e230703, 0x6a013703, 0x2f270e0f, 0x0f8a1933, 0x08161b1d, + 0x7a3617ee, 0x3d387b7c, 0x357d8384, 0x52266983, 0x4202d101, 0xae827902, 0x09401525, 0x82400502, 0xb90025d6, 0xe12f0001, 0x102e4c82, 0x133031ce, + 0x52152135, 0xd101f001, 0x1a82a8a8, 0xff932708, 0x009101e3, 0x001300fa, 0x801b4035, 0xa0159015, 0x15110315, 0xc0960a01, 0x0200d000, 0x00440034, + 0x00740064, 0x9e820004, 0x0a07b627, 0x9b050048, 0x2397840f, 0xed5d5d2b, 0x37209483, 0x200e5648, 0x0f514893, 0x4c486f20, 0x0001280f, 0x02000014, + 0x82b605e7, 0xb11e26a1, 0xffb80201, 0x25a782f0, 0x00100003, 0x12820105, 0x112f3f38, 0x32383301, 0x3133382f, 0x23010130, 0xfde70201, 0x2102b3e0, + 0x8544b605, 0x00022805, 0x04ecff62, 0x82cd0508, 0x00273db1, 0x1e154026, 0x1029006f, 0x6f140129, 0x0a010a20, 0x070f7323, 0x19057319, 0x3fe13f00, + 0xe124ef83, 0xe1de105d, 0x14394782, 0x23060602, 0x02262622, 0x36123435, 0x16323336, 0x14051216, 0x3233021e, 0x0811823e, 0x23022e53, 0x04020e22, + 0xb2713308, 0x73af767f, 0xb16f3339, 0x74b0777e, 0x1e13fd3a, 0x4d4d6b42, 0x1f1f456c, 0x4d4d6c45, 0x021e426b, 0xe8feb1dd, 0xc26666c2, 0xb1b11801, + 0x66c11801, 0xe8fec165, 0x95e096b2, 0xe1944a4b, 0x94e09697, 0xe0944a4a, 0x00010000, 0x20e182b2, 0x08e182c7, 0x35001066, 0x12402140, 0x0e010f01, + 0xbf6e000e, 0x0201ff01, 0x0001017e, 0x20011001, 0x04014001, 0x0f0d0106, 0x00180006, 0x01cd3f3f, 0x5d5d5e2f, 0x2f33e15d, 0x315d3311, 0x11232130, + 0x37023e34, 0x0707030e, 0x02330127, 0x0301b0c7, 0x1a110103, 0x94151e1b, 0x967f0160, 0x622b9103, 0x12225961, 0x121b181a, 0x2b017b79, 0x2b087182, + 0x03000060, 0x00cb05f0, 0x403c0023, 0x6f082320, 0x10251b1b, 0x6f220125, 0x11012101, 0x01012011, 0x10220801, 0x0716730d, 0x01742202, 0xe1297082, + 0x33e13f32, 0x2f013912, 0x2771835d, 0x115ded10, 0x33e12f33, 0x21227882, 0x52450135, 0x27072308, 0x3f45033e, 0x154c0809, 0xfcf00321, 0x4b5e0170, + 0x222c5376, 0x5f35563f, 0x28664599, 0x41766a5c, 0x3b6c9b60, 0x4b815d35, 0xb102e7fe, 0x517d019c, 0x4c818086, 0x203f5a3b, 0x24773c4d, 0x361b2e3f, + 0x555b9165, 0x5196959a, 0x0008d5fe, 0x52000100, 0xee03ecff, 0x4008a982, 0x405d0039, 0x2130210b, 0x6f1a1230, 0x006f2709, 0x40c0ffb8, 0x48171428, + 0x3b090000, 0x4f013b20, 0x06120112, 0x21ab7320, 0x01217901, 0x0801210b, 0x2f152121, 0x0735732c, 0x0e127315, 0x333f0019, 0x41c184e1, 0xc8830536, + 0xce105d2d, 0xe12b2f32, 0x3911e110, 0x482f2f39, 0x1621077a, 0x05f04a16, 0x35272624, 0xef411616, 0x35232108, 0x22210a88, 0x08e68706, 0x2ec103a6, + 0xb1477453, 0xca8441b8, 0x55c16d8a, 0x5c5dcb57, 0x35295786, 0x85598d62, 0x557e5185, 0x5c42242c, 0x4aa36b38, 0x6e5d265c, 0xa36c467d, 0x6004386e, + 0x39587849, 0xb516060c, 0x74a06091, 0xaa2d2240, 0x4a28322e, 0x6144436c, 0x28971e3f, 0x343d664a, 0x431e3952, 0x361f7d36, 0x61361829, 0x00020085, + 0x04000017, 0x00be053f, 0x0018000a, 0x092c404e, 0x00010056, 0x116e0200, 0x20070b0c, 0x03030103, 0x011a101a, 0x18871877, 0x055f1802, 0x06090501, + 0x05017418, 0x07110205, 0x00180206, 0x12333f3f, 0xe1332f39, 0x2105a64a, 0x0c825d5d, 0x82335d21, 0x32e12400, 0x82325d2f, 0x234608ee, 0x21112311, + 0x11330135, 0x34112133, 0x2337023e, 0x0107030e, 0xb0d53f04, 0x97025dfd, 0x7bfed5bc, 0x01050403, 0x19150709, 0x65fe0b1a, 0xb8fe4801, 0x039f4801, + 0x0130fcd7, 0x757b3864, 0x31142266, 0xfd102e31, 0x918200a0, 0xecff8328, 0xb605f603, 0xa3822a00, 0x26182e08, 0x2c056f1a, 0x27012c10, 0x68282424, + 0x23590123, 0xf0232301, 0xb80f010f, 0x1240c0ff, 0x0f480b08, 0x0000731d, 0x24742715, 0x10731506, 0x0698410a, 0xe1279b82, 0x5d2b2f01, 0x825d2f33, + 0x331126a3, 0xe1de105d, 0x4ca38233, 0x27230a7f, 0x41031e35, 0x95080584, 0x0e222326, 0x13270702, 0x03211521, 0x21023636, 0x487fab63, 0x80c58644, + 0x525b6333, 0x62592121, 0x7c4f2a63, 0xa8b02e56, 0x393f3f1b, 0x02375a15, 0x27ecfdb2, 0x81036920, 0x69a06c37, 0x437eb672, 0x141e130a, 0x182417ac, + 0x764e250d, 0x05978f51, 0x39040908, 0xfea6b002, 0x000e065d, 0x71000200, 0x0a04ecff, 0x2b00cb05, 0x37003f00, 0x6e312040, 0x1041220c, 0x3b170141, + 0x1000006f, 0x03002000, 0x1d753600, 0x732c071d, 0x73101927, 0x3f000707, 0x11e13fe1, 0xbf822f39, 0x32e15d22, 0x3228b882, 0x133031e1, 0x33043e34, + 0x1722bc82, 0xad832615, 0x33070422, 0x24091943, 0x022e2223, 0x0a484401, 0x14158808, 0x1571021e, 0xc68e5c35, 0x2f2e1385, 0x5823112b, 0x64895a2b, + 0x03142a43, 0x4c39140c, 0x9a5f3b5f, 0x743e3b6c, 0xaf6466a4, 0xdb014a80, 0x2748633c, 0x42634221, 0x2b4e6f43, 0x026e4925, 0xbfd06971, 0x024579a4, + 0x9b050705, 0x4e2b0c0c, 0x5094836c, 0x1a2d3f24, 0x6aa5723b, 0x447fb672, 0xfef2a04e, 0x7f5329b9, 0x4e6f4657, 0x604b2f2a, 0x6a854330, 0x00010043, + 0x0400005a, 0x00b60506, 0xb12b0006, 0xffb80006, 0x821140f0, 0x05012afc, 0x01081008, 0x74020502, 0x05674403, 0x0132e127, 0xce105d2f, 0x08e08232, + 0x31333880, 0x21012130, 0x01152135, 0x33021901, 0xac030efd, 0x1005d5fd, 0xdbfa91a6, 0x6a000300, 0x0004ecff, 0x2700cd05, 0x4a003a00, 0x53408000, + 0x6e32231e, 0x48280a0f, 0xd305c36e, 0x05b50205, 0x0f050501, 0x014c104c, 0x3e196e28, 0x0123d56e, 0xba0123cc, 0x23230123, 0x19201910, 0x1e0a1902, + 0x38983868, 0x01385902, 0x38383828, 0x38033848, 0x26014393, 0x02435643, 0x2d004343, 0x3b191473, 0x6a410073, 0x5d5d2708, 0x5d5d5dc1, 0x9a823939, + 0x822f3321, 0x10e12209, 0x82a383e1, 0x12e1260a, 0x11e11039, 0x09394239, 0x031e0722, 0x2205cf43, 0x4935022e, 0x032009e4, 0x270acb45, 0x06062727, + 0x15062201, 0x08071c4a, 0x350226b7, 0x42719554, 0x38604628, 0x35576f3a, 0x66a97943, 0x3d75ab6e, 0x3a684c2d, 0x253f5631, 0xc7957243, 0x48684420, + 0x24486b46, 0x3f664927, 0x01807e1e, 0x237d6a16, 0x3033573e, 0x7e243f55, 0x582ccd05, 0x6c435884, 0x1f1c4557, 0x49765f4c, 0x3868955c, 0x5c926536, + 0x4a60784b, 0x5a491f1c, 0x8357426d, 0xa6fb2c58, 0x233f5935, 0x385c4123, 0x40485434, 0x9b3c0e1f, 0x656a5403, 0x33405239, 0x42341618, 0x6a653654, + 0x00020000, 0x04ecff6a, 0x00cb0504, 0x003d0029, 0x391e4035, 0x3f006f15, 0x2f013f10, 0x20100c6e, 0x20022020, 0x1b1b7534, 0x25732a07, 0x07751007, + 0x0b87421a, 0x5de13330, 0x32e1de10, 0x14013031, 0x2223040e, 0xcc44022e, 0x23372107, 0x4c05cb4a, 0x22220835, 0xf983020e, 0x23055843, 0x0404022e, + 0x3e078842, 0x23112c2e, 0xae872b58, 0x0d052b66, 0x604c3814, 0x6c9a5f3b, 0xa5733f3b, 0x80ae6566, 0x4225fe4a, 0x443c0786, 0x252b4e6e, 0x46036e49, + 0xa5bed169, 0x05024578, 0x0d9c0506, 0xd6a15e0c, 0x2e3e2477, 0x29058442, 0x4e447fb7, 0x4701f3a0, 0x84425428, 0x426b210b, 0x933be183, 0x9101e3ff, + 0x13006604, 0x3e002700, 0x29101c40, 0x29902980, 0x1e0429a0, 0x4814960a, 0x40291150, 0x480a070b, 0x199b2300, 0x05554810, 0x01ed3f2c, 0x5d5d2b2f, + 0x5d32e533, 0x58483031, 0x4811200f, 0x78481f68, 0x9103361f, 0x0e213527, 0x2735210e, 0x10223425, 0x00342210, 0xfe3f0002, 0x08af84f8, 0x20000c2b, + 0x2f406100, 0x22802210, 0x22a02290, 0xc0961704, 0x020dd00d, 0x0d740d64, 0x010d5002, 0x3b010d44, 0x0d1f010d, 0x0d020d2f, 0x0db2490d, 0xb2491120, + 0x9b1c2309, 0xb6491012, 0x29c88305, 0x332b5d5d, 0x335d32ed, 0x00845d2f, 0xc049e520, 0x108b510b, 0x200cd049, 0x49c98f11, 0x02210be1, 0x08c58fed, + 0x66000141, 0x0204ee00, 0x0600dd04, 0x30404e00, 0x08400800, 0x01014001, 0x05010201, 0x6f060305, 0x02007f00, 0x00010030, 0x03200400, 0x70035001, + 0xd0038003, 0x0503f003, 0x0001033f, 0x03060103, 0x825e2f00, 0x337121a0, 0x3228a883, 0x2f3d3912, 0x18013333, 0x4e08b482, 0x3031ce10, 0x01350125, + 0x04010115, 0x0364fc02, 0x0221fd9c, 0xa801eedf, 0xa0e10166, 0xbefe94fe, 0x66000200, 0x0204ba01, 0x0300e903, 0x5c000700, 0x02073d40, 0x01094009, + 0x0100c604, 0xa90100bb, 0x00860100, 0x01007b01, 0x42010068, 0x82390100, 0xad043981, 0x052f051f, 0x01057f02, 0x05100500, 0x05050602, 0x01f0ad00, + 0x6f010f01, 0x0020ab82, 0xe1217282, 0x228b8333, 0x4101e171, 0x5d260633, 0x105d335d, 0xb24a32ce, 0x35012605, 0x03661521, 0x2889839c, 0x95955403, + 0x969666fe, 0x8c548200, 0x840520fb, 0x01062efb, 0x01040506, 0x6f000301, 0x02067f06, 0x210e8230, 0xfba10206, 0xfb8e3320, 0x84011321, 0x026624fc, + 0x8320fde0, 0x8f012b76, 0x6c014201, 0x661ffea0, 0xfb8258fe, 0xff253108, 0x052503e3, 0x002700cb, 0x403e003b, 0x289a3221, 0x00462728, 0x460b1400, + 0x3d2f3d1c, 0x170b1401, 0x0601000f, 0x9b2d0000, 0x51101337, 0x3f000417, 0xe521dd82, 0x21e08232, 0xdf823912, 0xe1de1025, 0x822f3911, 0x31e12812, + 0x34350130, 0x4937023e, 0x36210a75, 0x08754936, 0x15030e23, 0x102d4215, 0x0f192008, 0x30324227, 0x1e152b44, 0x53385539, 0x513f4696, 0x955d61bc, + 0x361b3868, 0x42343650, 0x42bb0e26, 0x26080f40, 0x39259e01, 0x2a4d505c, 0x4f454329, 0x394f3035, 0x9122341f, 0x60333b2a, 0x6943578b, 0x2d2f545a, + 0x2c423f43, 0x4bd1fe12, 0x71080fa9, 0xff6d0002, 0x0581064a, 0x005700b6, 0x406f0068, 0x6017583f, 0x01171f27, 0x1701277f, 0x27464627, 0x314e0317, + 0x00010020, 0x016a406a, 0x014e403b, 0x5b0c2c4e, 0x64120712, 0x1f120f1c, 0x0312bf12, 0x011c0006, 0x121c1207, 0x5336401c, 0x49454003, 0xc1332f00, + 0x3912c13f, 0x5e2f2f39, 0x105d5e5d, 0x103311c1, 0x013232c1, 0x5dc15d2f, 0xc171de10, 0x19821711, 0x825d2f21, 0xc1102118, 0x440aeb44, 0x17250ee3, + 0x14060603, 0x0be54414, 0x04222322, 0x2a05b74e, 0x023e3233, 0x06061537, 0x4b242223, 0x242805ea, 0x16043233, 0x16140112, 0xc5081984, 0x23262637, + 0x06020e22, 0x39251381, 0x2d3a614c, 0x06213449, 0x47361204, 0x774d3559, 0x6f3b2b52, 0x5a2d629e, 0x17174552, 0x22150101, 0x462e172b, 0x9856182f, + 0xfea97bd1, 0x4f5aaffe, 0x3d93e399, 0x2b646f77, 0xb382d856, 0x66c3e7fe, 0x3701db76, 0x06019cc1, 0x15fc6abf, 0x4e375565, 0x0e041a32, 0x4a2a4d1c, + 0x021c3f65, 0x717d3edb, 0x1e294861, 0x25234132, 0x381c3142, 0x65568e65, 0x08447aa8, 0xfe08110e, 0x101b1660, 0x44350308, 0x683d0f28, 0xdd8e4e8c, + 0xc76f4f98, 0x97a2effe, 0x0e52a0ea, 0x8d111f18, 0xc3662c26, 0xbcb31901, 0x88ee4501, 0xf1febd65, 0x7785d5fe, 0x4573532d, 0x3a0d08fd, 0x0000785e, + 0x00820002, 0xdd047e08, 0x0700bc05, 0x84001400, 0x05062440, 0x46010246, 0x14020114, 0x01084903, 0x08010149, 0x0e0e0001, 0x10000003, 0x07800107, + 0x07d00790, 0xffb80703, 0x061840c0, 0x1007480a, 0x0f160707, 0x2f161f16, 0x9f168f16, 0x0616df16, 0xb8040307, 0x1140f0ff, 0x0e5f0204, 0x480e0a20, + 0x1414050e, 0x00040305, 0x323f0012, 0x122f393f, 0x01e12b39, 0x5e33382f, 0x2f33115d, 0x715d2b38, 0x39121133, 0x2416823d, 0x125d5d39, 0x08048239, + 0x31333397, 0x21032130, 0x33012303, 0x2e030101, 0x030e2703, 0x1f040307, 0xa2dffda0, 0xaa1902bc, 0x67fe1a02, 0x12110694, 0x12070812, 0x91061112, + 0x3bfec501, 0x44fabc05, 0xa8016a02, 0x413c3412, 0x3d421f1f, 0x58fe1133, 0x00030000, 0x040000c7, 0x00b60587, 0x00220017, 0x4062002f, 0x5a1e0b3e, + 0xe5010605, 0x0206f506, 0x060106d6, 0x5b2a2406, 0x11801170, 0x31671102, 0x318f317f, 0x01311002, 0x175a2418, 0x230b3064, 0x01187960, 0x0801180b, + 0x24001818, 0x22121760, 0x494f8260, 0x5e3b06c7, 0x39e15d5d, 0xe1f61001, 0x105d5d32, 0x12e15df6, 0x5d5d2f39, 0x3132e171, 0x4a211330, 0x0721068e, + 0x06554815, 0x47132121, 0x26270538, 0x11112323, 0x4e3e3221, 0x7508051c, 0x808f01c7, 0x274283c3, 0x45456d4a, 0x41345a79, 0xfe6fb07b, 0x54f4ba1b, + 0x9a1f4672, 0x0a01dfa6, 0x20497758, 0x5c7c4b21, 0x5727b605, 0x6c3e678d, 0x0a093752, 0x784f2d0c, 0x6d9d6456, 0x1e4a033a, 0x783b593b, 0xfd97fd68, + 0x654828f0, 0x435e383d, 0x01000025, 0xecff7d00, 0xcb059804, 0x4c002300, 0x0eaf1440, 0x15400e01, 0x0e0e4818, 0x0120ba18, 0x20702060, 0xb3412002, + 0x20203807, 0x0125af25, 0x66185b05, 0x5f002124, 0x0a0d041d, 0x0013135f, 0x8233e13f, 0x26d68302, 0x2f33115d, 0x825d5d2b, 0x5d2b24d6, 0x48013031, + 0x36240800, 0x030e1537, 0x080cf34e, 0x2607176a, 0x6b190326, 0x3b437bae, 0x5976b076, 0x4e274ea0, 0xa43b6155, 0x574c9df0, 0x6ca2faa9, 0x3f4e4fc4, + 0x51270594, 0x8d89da98, 0x234e96db, 0x170fa217, 0xc66c070e, 0xa6a91601, 0x6ec61401, 0x209c2a2c, 0x0002002e, 0x040000c7, 0x00b605fc, 0x0017000c, + 0x0d154026, 0x1967005b, 0x14011910, 0x1864065a, 0x03076013, 0x12066014, 0x3f219f82, 0x229d84e1, 0x82e1f610, 0x02143495, 0x21230406, 0x16322111, + 0x34071216, 0x2323022e, 0x82203311, 0x60300846, 0xa8f7feb6, 0x970192fe, 0x5faef899, 0xb87e42c5, 0x01a2c975, 0x020c0108, 0xe9feb9e9, 0xb6055ebb, + 0xf4feb55c, 0x8ad592b6, 0x0189fb43, 0x01000024, 0x03217d83, 0x087d82be, 0x42000b29, 0x08142640, 0x01080801, 0x0d670004, 0x015a0a06, 0x5f090c64, + 0x0f01064f, 0x0206af06, 0x0a060608, 0x03025f05, 0x85015f0a, 0x3912258c, 0x715d5e2f, 0x322a9384, 0x1132e610, 0x315d2f39, 0x92822130, 0x03861520, + 0xfdbe0335, 0xfdf70209, 0xfd1702c3, 0x053d02e9, 0x3cfea4b6, 0x8af8fda2, 0x00092471, 0x82114070, 0x0f24086e, 0x03ff0103, 0x90038001, 0x0303d003, + 0xc0ffb803, 0x0a073840, 0x0b030348, 0x0b2f0b0f, 0x0baf0b8f, 0x00060704, 0x0a238d82, 0x830f5f09, 0x063f348d, 0x06ff066f, 0x40060804, 0x06481d1a, + 0x48151040, 0x83000606, 0x8200209b, 0xe13f2199, 0x2b219882, 0x209a882b, 0x06ce415e, 0x16827120, 0x23229f82, 0x9f852111, 0xba810122, 0x9a829c87, + 0xa4fcfd23, 0x06434200, 0x05f22908, 0x002b00cb, 0x2b1e4037, 0x5a290c2b, 0x2d670214, 0x1f012d10, 0x2c660c5b, 0x00005f2b, 0x115f1a24, 0x075f2404, + 0xe13f0013, 0xe1206a84, 0x29069441, 0x3911e132, 0x0130312f, 0x24421121, 0x3324280a, 0x07171632, 0x4223032e, 0x55080844, 0x1137023e, 0x010e0321, + 0x767037e4, 0xf29d4b82, 0xb65f56a6, 0x6fab0b01, 0x244858cc, 0x2e5d5853, 0x427fbc7a, 0x86be7837, 0x373e492c, 0x03d5fe1a, 0x1233fd04, 0x690a131c, + 0xae1701c3, 0xc31601ac, 0xa22a2c69, 0x0e171e11, 0x89da9851, 0x569cd882, 0x050b0805, 0xbb83b401, 0x00c72d08, 0x05d50400, 0x000b00b6, 0x0923403d, + 0x65005a01, 0x010dc00d, 0x20010dbf, 0x0408010d, 0x0c64055a, 0x080f5f03, 0x08080801, 0x0503060a, 0x24058f44, 0x5e2f3933, 0x27c1845d, 0x5d5d5d32, + 0x32e1f610, 0x3b052241, 0x33112311, 0x33112111, 0xfdbad504, 0x02baba66, 0xaa02ba9a, 0xb60556fd, 0x680298fd, 0x52246b83, 0x64020000, 0x3b086b84, + 0x0b264057, 0x020d2b0d, 0x0d9b0d7b, 0x0dfb0dab, 0x010d5404, 0x0d3b0d2b, 0x1f030d4b, 0x0802010d, 0x055a0a0b, 0x0103c902, 0xf8ffb803, 0x100d1040, + 0x01030048, 0x04090306, 0x0a030306, 0xc1258383, 0x32c13f32, 0x28858201, 0x32c15d2b, 0x5f32c1f1, 0x2000825d, 0x08858271, 0x37352127, 0x21352711, + 0x17110715, 0xeefd6402, 0x1202acac, 0x2966acac, 0x66299804, 0x68fb2966, 0xff010029, 0x017bfe48, 0x08858273, 0x2f001324, 0x15df1c40, 0x70156001, + 0x152f0215, 0x0c5a0f01, 0x0c000303, 0x07020c10, 0x07030d0c, 0x2f00005f, 0x63833fe1, 0x102f3323, 0x235e82e1, 0x22033031, 0x8209bd50, 0x142408e9, + 0x331d020e, 0x4e221c4c, 0x3d4b252d, 0x693bbb26, 0x0d7bfe93, 0x0b09a00b, 0x44583213, 0x5efab605, 0x31659a69, 0x20076341, 0x377182a2, 0x4064000c, + 0x660c022d, 0x000c010c, 0x0b100b0a, 0x0000010b, 0x07020010, 0x00290482, 0x010eb00e, 0x10010e2f, 0x0575410e, 0x10020d2b, 0x0848100b, 0x40f0ffb8, + 0x3208820c, 0x0a050802, 0x05000306, 0x333f0012, 0x3912333f, 0x452b2b39, 0x5d27064a, 0x382f3311, 0x82335d5e, 0x11332205, 0x270d8239, 0x23213031, + 0x23110701, 0x373fa082, 0x04013301, 0x3dfed3a2, 0x79baba8b, 0xfdd1c401, 0x72ba02f8, 0xb605b8fd, 0x02a825fd, 0x4383fd33, 0x05360bc7, 0x13402300, + 0x07af0704, 0x01071001, 0x64005a03, 0x03030106, 0x7082005f, 0x833fe121, 0x845d206a, 0x8233205a, 0x15212555, 0x3d02bac7, 0xf021df82, 0x059543a6, + 0x822f0621, 0x00193cdb, 0x3613408b, 0x00390119, 0x080e1701, 0x39480f0c, 0x110e010e, 0xffb8195a, 0x821c40f8, 0x0019210e, 0x00321483, 0x090c0d0d, + 0x4f1b6510, 0x1b20011b, 0x011b0f01, 0x20830b08, 0x20821a20, 0x010b263a, 0x5a08020b, 0x181a6409, 0x09100101, 0x0e014812, 0x0c11030b, 0xb6f0ffb8, + 0x0c210c82, 0x298a8308, 0x322b3232, 0x2b33333f, 0xfd843311, 0x2b5d3231, 0x5d5d5d5e, 0x3911f610, 0x2b331139, 0x82e12b33, 0x31323411, 0x215d5d30, + 0x17162301, 0x11151616, 0x01211123, 0x82210133, 0x343b0807, 0x37363736, 0x23030123, 0x060845fe, 0xac050404, 0x9c011401, 0x019e0106, 0x0304ba14, + 0xfe080304, 0x4a000541, 0x398b3f49, 0xb60596fc, 0xa80458fb, 0x77034afa, 0x473d8634, 0x8502fb49, 0x0e0521e7, 0x2d08e782, 0x40510017, 0x01280e29, + 0x5a150101, 0xb0196500, 0x198f0119, 0x10190001, 0x0c270219, 0x09030c01, 0x18640a5a, 0x06100216, 0x0b024818, 0xbd830d03, 0x0d210a82, 0x20bd860a, + 0x86a5823f, 0x82b884ba, 0x21af82b0, 0xae892321, 0x3301332e, 0x032e2726, 0x05331135, 0x31fdd70e, 0xd533aa85, 0x0307cc02, 0x03030104, 0xba04ae01, + 0x8e414c4d, 0x82e7fc39, 0x4c4c32a4, 0x4343204a, 0x20031a3e, 0x00020000, 0x05ecff7d, 0x068f5571, 0x40342108, 0x005b1e20, 0x29c02967, 0x0129bf01, + 0x2f012970, 0x02295f29, 0x660a5b14, 0x0f5f2328, 0x055f1904, 0x41058944, 0x5d2105d9, 0x081d465d, 0x081f9d55, 0x51710548, 0xa39beda0, 0x4c4c9def, + 0x9ba3f09e, 0xfb51a0eb, 0xa56b34d1, 0x6ba57272, 0xa46a3232, 0x6ca67272, 0xa9dd0234, 0x6cc6eafe, 0x1701c66c, 0x1501aaaa, 0xc56b6bc4, 0x89abebfe, + 0x515199db, 0x8a89db99, 0x515197da, 0xb183da97, 0x00c74108, 0x05330400, 0x000e00b6, 0x40460019, 0x285b152c, 0x48003800, 0x67000300, 0x011bcf1b, + 0x0f011b40, 0x0f06011b, 0x64085a07, 0x30600f1a, 0x02064006, 0x19070606, 0x07030960, 0x3f3f0012, 0x2f3911e1, 0x42068544, 0x5d310505, 0x013031e1, + 0x23020e14, 0x11231123, 0x021e3221, 0x08454801, 0x33043608, 0x98cf7e37, 0x6a01ba96, 0x3c7ec286, 0x5d814efd, 0xa42e5b8b, 0x0a04a0ae, 0x4d81a85b, + 0xb605c7fd, 0xfea06d39, 0x71472067, 0x00898e51, 0xfe7d0002, 0x057105a4, 0x089782cd, 0x38002d2b, 0x5b242240, 0xc02f6700, 0x2fbf012f, 0x012f7001, + 0x2f5f2f2f, 0x105b1a02, 0x5f292e66, 0x5f1f0415, 0x07130b05, 0x333f2f00, 0x066a47e1, 0x8505d941, 0x0107248b, 0x41060123, 0x312b2154, 0x015d8e5f, + 0xebfef452, 0x41122411, 0xef23055c, 0x41ec9aa4, 0x832a155c, 0x2585b5e2, 0x4c018bfe, 0x62410202, 0x0523481e, 0x05a03108, 0x000f00b6, 0x4082001c, + 0x190f0956, 0x0ff9020f, 0x0b080f01, 0x0c0f480f, 0x07010c09, 0x5b16010c, 0x07180708, 0x09070702, 0x0ee9010e, 0x0e020ef9, 0x20081d83, 0x0d100d0e, + 0x8f1e3f1e, 0xbf1e9f1e, 0x051edf1e, 0x10011e20, 0x64025a01, 0x10030c1d, 0x01000060, 0x32038208, 0x0303601c, 0x0012010e, 0xe13f333f, 0x5e2f3911, + 0x4912e15d, 0xce2708e1, 0x5d2b3238, 0x832f3271, 0x5d5e2313, 0x0c823311, 0x01303131, 0x21112311, 0x14151620, 0x0107020e, 0x41270123, 0x7008059f, + 0x2323022e, 0x01ba8101, 0xfe0a0164, 0x37685131, 0xfedb8e01, 0x5aa4e5a1, 0x2925517e, 0xa0577f53, 0xa4fd5c02, 0xd1ceb605, 0x3e5d8257, 0x0271fd14, + 0x45239e5c, 0x64484567, 0x01001d40, 0xecff6800, 0xcb05c903, 0x42003300, 0x23592740, 0x5a112301, 0xbf356700, 0x0235ff35, 0x3f013560, 0x5a2a0135, + 0x34661b09, 0x27052a11, 0x0420245f, 0x0509600e, 0x22b08213, 0x82333fe1, 0x21ad83ac, 0xaf41e132, 0x5d332105, 0x2205b141, 0x55262223, 0x36270512, + 0x022e3435, 0x51032e27, 0x162505d3, 0x26260717, 0x06cf5223, 0x031e5b08, 0x8045c903, 0xc16f73b8, 0x60572241, 0x99a03266, 0x5d7a491d, 0x29558359, + 0x61a17440, 0x434abe77, 0x7a58a541, 0x73461e86, 0x5c895b54, 0x6187012f, 0x23376a99, 0x1f10b222, 0x70780f18, 0x3f435036, 0x68532325, 0x8a585484, + 0x232d325f, 0x712b1d9c, 0x43533960, 0x4c24213b, 0xd3827e60, 0x00145f08, 0x05120400, 0x000700b6, 0x0f32405e, 0x09d00109, 0xcf094f01, 0x09100209, + 0x09300920, 0xef06af03, 0x06840206, 0x07060601, 0x0340025a, 0x0f0203e0, 0x03080103, 0x67025703, 0x03027702, 0xc0ffb802, 0x0a070b40, 0x03070248, + 0x0003045f, 0x3f3f0012, 0x2f0132e1, 0x2f335d2b, 0x105d5d5e, 0xd64f32e1, 0x47712005, 0x353105b4, 0x02211521, 0x5efebb71, 0x5ffefe03, 0xa4a41205, + 0x08818200, 0xecffb82b, 0xb805dd04, 0x2f001700, 0x5a161c40, 0xb0196501, 0x196f0119, 0x100219af, 0x5a0e0119, 0x1118640b, 0x0c13065f, 0x3f000300, + 0x08f54232, 0x20054444, 0x07405f11, 0x11331122, 0x0806ef4d, 0xdd04112a, 0x88c98542, 0x4485c480, 0x59afadbb, 0x01285280, 0x4cfcb805, 0x5290c472, + 0x7ac78e4d, 0x48fcae03, 0x6236c0af, 0xb8035188, 0x00247b82, 0x8b040000, 0x0c34fd82, 0x10406c00, 0x09090203, 0x01600004, 0x01b00170, 0x010401f0, + 0x2608db83, 0x480a0616, 0x01011001, 0x7f0e2f0e, 0x030ebf0e, 0x0906400e, 0xb8040548, 0x04b4f0ff, 0x09030405, 0xb3e0ffb8, 0x8248110a, 0x40f02207, + 0x251a820a, 0x12030209, 0xaa820100, 0x333f332d, 0x3f2b2b33, 0x382f0133, 0x4d5d2b33, 0x332c0549, 0x2f3d3912, 0x30313333, 0x23013301, 0x16360382, + 0x36361716, 0xc6c50337, 0xfebb17fe, 0x2701c519, 0x0f112a1d, 0xf65a1f2e, 0x61fc2705, 0x4a4aa95b, 0xa34161a9, 0xfe062105, 0x2a2ea582, 0x10b6df00, + 0x48181508, 0xffb80f10, 0x0882b5f8, 0x82070f21, 0x40f822a5, 0x210a8212, 0x19830001, 0x1d160022, 0x1d210683, 0x2120821c, 0x16822f40, 0x251c2808, + 0x04010714, 0xb4074407, 0x04070307, 0x24251425, 0x54254425, 0x16070525, 0x07162525, 0x000d1e03, 0x0e70010e, 0x82c00e80, 0x38f083db, 0x480a0718, + 0x0e0e100e, 0x7f2c6f2c, 0x2c20022c, 0x0f022c30, 0x1f08012c, 0x24f2821e, 0x161e1340, 0x21ed8220, 0xe9821016, 0x000d1627, 0x2507031e, 0x06014125, + 0xf0210782, 0x241682b6, 0x121d1025, 0x21fb8400, 0x06823311, 0x2b2b3322, 0x20054b4e, 0x0603415d, 0x12337131, 0x2f3d3917, 0x5e5d2f2f, 0x3311715d, + 0x892b332b, 0x30313b04, 0x1e133301, 0x033e1703, 0x01331337, 0x26260323, 0x06272627, 0x07060607, 0x19882303, 0x29034d08, 0x1d0fe5c5, 0x04061319, + 0x0b13100c, 0x91fec7c8, 0x1a0efebc, 0x0b0b0c0b, 0x0e190a0b, 0x7efebcf2, 0x140cdfc5, 0x05050e11, 0x0d17140f, 0xa8fcb605, 0x5e697038, 0x635a2626, + 0x72033167, 0xaa034afa, 0x372f6c33, 0x2f373334, 0x5cfc3670, 0x872a1f82, 0x5b62632e, 0x6c622526, 0x1142316f, 0x60440806, 0x0b00b605, 0x1d408100, + 0x0a100a09, 0x0b37000a, 0x38080b01, 0x02050105, 0x00000102, 0x80007001, 0x0300c000, 0xc0ffb800, 0x0a071440, 0x00100048, 0x0d0f0d00, 0x0d2f0d1f, + 0x08040d7f, 0xffb80607, 0x0606b3f0, 0x2b05644f, 0x02280410, 0x01082701, 0x09040802, 0x00301282, 0x323f0012, 0x3912333f, 0x015d5d39, 0x3232382f, + 0x2a0c674f, 0x332f3d39, 0x5d33335d, 0x82183311, 0x30312517, 0x01012321, 0x33290282, 0x01330101, 0xfed36004, 0x39eb829e, 0x5afec501, 0x014c01c6, + 0x5bfebe4e, 0x85fd7b02, 0xba02fc02, 0x2f02d1fd, 0x9a824cfd, 0x00820020, 0x82370421, 0x00083dbd, 0xef194073, 0x400a010a, 0x08480c09, 0x980107ab, + 0x07400107, 0x01071b01, 0x0701070f, 0x403da082, 0x0507072f, 0x01028001, 0x1b01024f, 0x10020102, 0x04000202, 0x8705775a, 0x03059705, 0x06ad534f, + 0x36050729, 0x01000100, 0x42071204, 0x122105d1, 0x25b48239, 0x5d5d5d5e, 0xb88239e1, 0x33240782, 0x382f3311, 0x5d260782, 0x5d2b335d, 0xa7833031, + 0x1123113b, 0x1b023301, 0xfec85401, 0x42febb42, 0x02d302cb, 0xfd83fce3, 0x032f02c7, 0x06974b87, 0x82fe0321, 0x092108a1, 0x20403800, 0x07030909, + 0x0b0f0b67, 0x0b4f0b3f, 0x08040b9f, 0x01040408, 0x04070a66, 0x0203055f, 0x05c54d08, 0xe13f392b, 0xe6100139, 0x5e322f32, 0x2606825d, 0x30312f32, + 0x58352121, 0x213505c2, 0x54fcfe03, 0x4dfdc702, 0x3afd8303, 0x0491db02, 0xfb91a67f, 0x24658381, 0x02bcfea4, 0x3b658239, 0x40260007, 0xf3000417, + 0x0100f106, 0x01b00110, 0x010401c0, 0xf802f505, 0xf901f506, 0x21082f5e, 0xba8232ed, 0x21112135, 0x33112315, 0x6bfe3902, 0xdfdf9501, 0xfa06bcfe, + 0x8331fa95, 0x0017244b, 0x82e90200, 0x0003254b, 0x0102b721, 0x05284682, 0xffb80300, 0x0203b4f0, 0x3505ba5e, 0x382f012f, 0x38331133, 0x30313311, + 0x01230113, 0xb22002c9, 0xc443e0fd, 0x243f8305, 0x01bcfe33, 0x368b84c9, 0x03144024, 0xf101f300, 0x06700660, 0x00090602, 0x03f907f5, 0x85f804f5, + 0xd6102388, 0x8983e15d, 0x11331724, 0x8d823523, 0xdfdf333f, 0x6afe9601, 0x95cf05ae, 0x000006f9, 0x02290001, 0x05190425, 0x000600c1, 0x0303b612, + 0x28128208, 0xcd3f0006, 0x33112f01, 0x2078832f, 0x087a8233, 0x01290121, 0xbf0166cb, 0xfeaffea1, 0x032502a3, 0x0264fc9c, 0x0021fddf, 0xfefcff01, + 0xff4e03bc, 0x82030048, 0x0000293b, 0xba010105, 0xe12f0002, 0x012c3b86, 0x03213521, 0x03aefc4e, 0x8cbcfe52, 0x47085682, 0xd9048901, 0x21061203, + 0x16000d00, 0x06000a40, 0x000f8008, 0x0002005f, 0x1a5d2f00, 0xcd2f01cc, 0x23013031, 0x3527032e, 0x17031e33, 0x23781203, 0x103f4d52, 0x2e2b10db, + 0xd9041530, 0x5158531c, 0x5122151b, 0x001d4c51, 0x6f083282, 0x03ecff5e, 0x005e049c, 0x00320023, 0x10114054, 0x23472901, 0x340f3455, 0x0602346f, + 0x1a0c4830, 0x40d0ffb8, 0x48110d1e, 0x0c09101a, 0x0c1a1a48, 0x16193356, 0x522a1d50, 0x101d1010, 0x07025024, 0x00150016, 0xe1333f3f, 0xe12f393f, + 0x0132e110, 0x2f32e610, 0xe1102b2b, 0xf6105d5e, 0x313232e1, 0x23272130, 0x2223030e, 0x3435022e, 0x35373736, 0x21051664, 0x4d552707, 0x11620806, + 0x023e3225, 0x0e073535, 0x16141503, 0x08251903, 0x604e4221, 0x5574453f, 0xb8ece730, 0x3451371d, 0x40428f53, 0x6664b64a, 0xfe306195, 0x4c683d2f, + 0x7a5a8f2b, 0x98612049, 0x142a412d, 0x547b5127, 0x0708b0a4, 0x375a4345, 0x89223018, 0x59293828, 0x10fd628a, 0x754d267f, 0x0407634f, 0x33513920, + 0xe583565c, 0xffae3308, 0x063f04ec, 0x001f0014, 0xb538002f, 0x5705482d, 0xffb83131, 0x0a1740b8, 0x25101549, 0x30541247, 0x15120013, 0x0a0f502a, + 0x1b502016, 0x3f001000, 0xd483e132, 0x84013f21, 0x462b20c5, 0x275d05cc, 0x07232e0b, 0x11331123, 0x06070614, 0x033e3307, 0x089b4f17, 0x34353637, + 0x5e9e0226, 0x3c3c6d9a, 0x3b5e9a6d, 0x173b4d60, 0xb685250c, 0x08008202, 0x3a170843, 0x5019604d, 0x1b1b416b, 0x87516c41, 0x5e047f7f, 0x8cd48f48, + 0x4990d58d, 0x203a2b1a, 0xfe14068b, 0x224f2388, 0x3c232628, 0x3397192c, 0x65699c68, 0xda376b9d, 0x00ced0cc, 0xff710001, 0x046f03ec, 0x3ac1825e, + 0x1d18402a, 0x215f210d, 0x1002217f, 0x48160121, 0x13205605, 0x19100a51, 0x51160051, 0x5d2909e0, 0x3132ce10, 0x2e220530, 0x08b04802, 0x032e4408, + 0x15062223, 0x32331614, 0x06153736, 0x65520206, 0x4c4a82b0, 0x4e66b285, 0x17363295, 0x1a3a3c38, 0x9491909d, 0x36368351, 0x893f147b, 0xdb9d96d5, + 0x19223e89, 0x0f130a9a, 0xd3d4c909, 0xa21925c3, 0x5d001e1d, 0x022206b9, 0x89821406, 0x00302008, 0x261d4034, 0x1e471b00, 0x32103255, 0x0b482e01, + 0x151f3156, 0x502b001c, 0x20101016, 0x82060150, 0x41332090, 0x11420947, 0x42252007, 0xfb6a0810, 0x33172e05, 0x26262726, 0x11331135, 0x3e322523, + 0x07234202, 0x2208aa82, 0x16085403, 0x3c604d3b, 0x3c6e9a5d, 0x5d9a6e3c, 0x3c4d603b, 0x03030c16, 0x93b60402, 0x694cc6fe, 0x41021f41, 0x9324064a, + 0x1a2e3d22, 0x31084d41, 0x22203a2c, 0x10371a1f, 0xecf9b401, 0x8d5e2e83, 0x4941295e, 0xcdd12105, 0x3008bf85, 0x5e04e103, 0x27001e00, 0x28404300, + 0x10194823, 0x29e02957, 0x01296f01, 0x05481122, 0x50112856, 0x222b221b, 0x01220f02, 0x14222206, 0x100a501f, 0x075b4114, 0x2f391224, 0xec505d5e, + 0xf6102308, 0x6441e132, 0x021e240b, 0x60211515, 0xb90805cf, 0x030e1537, 0x07062203, 0x022e3421, 0xb66e6002, 0x78424883, 0x9e6365a7, 0x4cfd3b6e, + 0x33979905, 0x274c5157, 0x57514d28, 0x0b857260, 0x391bec01, 0x8e4a1458, 0xd68887d2, 0x81474e95, 0xc1716eb5, 0x1d130ab6, 0x1c13a212, 0xdb030812, + 0x7144959c, 0x01002c50, 0x00001d00, 0x1f06f002, 0x70001b00, 0x1dcf4e40, 0x60021ddf, 0x901d801d, 0x041da01d, 0x1d3f1d1f, 0x1b031d4f, 0xbf107f1b, + 0x10100210, 0x0347021a, 0x050f0307, 0x052f051f, 0x050405af, 0x10030005, 0x80032003, 0xa0039003, 0x03060603, 0x074f0501, 0x07011a00, 0x50140f1a, + 0x1502010d, 0xe13f3f00, 0x335d5e3f, 0xe35032e1, 0x115d2d05, 0x32e11033, 0x395d2f32, 0x5d5d5d2f, 0x2206c760, 0x4a373523, 0x0e200cfe, 0xb008ef82, + 0xf58b0233, 0x2dc2c2b7, 0x3b4e7c55, 0x1f2f2763, 0x3a282849, 0x03f51326, 0x033ffcc1, 0x60444bc1, 0x23548d6b, 0x0b8d0e17, 0x53301311, 0x00006841, + 0xfe250003, 0x04fc0314, 0x003f005e, 0x005e0052, 0x0d1940a7, 0x47530532, 0x602f1237, 0x80377037, 0x2f370337, 0x48272f37, 0x0547591d, 0x40c0ffb8, + 0x480a074d, 0x0a010505, 0x1dfd011d, 0x011db001, 0x20011d88, 0x401d301d, 0x1d1d031d, 0x01601f60, 0x60df60bf, 0x0160a002, 0x0c402740, 0x0227480f, + 0x040d3205, 0x0a52563c, 0x4f5c220a, 0x0f4e2c3c, 0x17070117, 0x45103c17, 0x011b224f, 0x3f000f00, 0x37e782c1, 0x5d5e2f39, 0xe11039c1, 0xe12f3911, + 0x01391712, 0x5dc12b2f, 0x3311715d, 0x5d3aea83, 0x2f393371, 0xc110e12b, 0x2f393911, 0xc1105d2f, 0x3912e110, 0x01303139, 0xb4620715, 0x030e2609, + 0x021e1415, 0x070f5a33, 0x2805dd44, 0x2637023e, 0x36343526, 0x09244c37, 0x25830120, 0x3536322e, 0x23022e34, 0x020e2223, 0x33161413, 0xd2080e83, + 0x06222326, 0x1cc5fc03, 0x8c5f2f26, 0x0e2c165d, 0x111b2111, 0x1f382918, 0x51805db0, 0xcd864124, 0x6aa06b8b, 0x57422735, 0x40362a2f, 0x31472b45, + 0x9262321b, 0x1b4f2561, 0x3b1a40fe, 0xb9ba4861, 0x415a3718, 0x3f4c23b0, 0x636c5c29, 0x64696764, 0x4a046a63, 0x6d231b71, 0x5e814c45, 0x0a030135, + 0x18282019, 0x0612211b, 0x3d6d502f, 0x34618c58, 0x4771502a, 0x2a425b3c, 0x3552130b, 0x122a593d, 0x3360513f, 0x34628c59, 0x02fb090b, 0x1b2e4025, + 0x3a2e6c73, 0x2c100c21, 0x7360034d, 0x7b776f70, 0x01007874, 0x0000ae00, 0x14061204, 0x32001900, 0x47001d40, 0x101b5519, 0x801b601b, 0x0e0f031b, + 0x540b470a, 0x5004101a, 0x000c1015, 0x0015000b, 0x563f323f, 0x322a06f7, 0xf6105d32, 0x213031e1, 0xe4823411, 0x15020e27, 0x33112311, 0x05986111, + 0x15165108, 0x695c0311, 0x436e5170, 0x08b6b61d, 0x5245190a, 0xb9b7305c, 0x8282c302, 0x60946634, 0x1406c7fd, 0x2b9032fe, 0xbf142a3f, 0x0033fdd2, + 0xa0000200, 0x75010000, 0x0300e505, 0x25001100, 0x13101440, 0x0c021320, 0x01044700, 0x53071254, 0x0f020f0f, 0x27057b46, 0x1001e52f, 0x32e132f6, + 0x2205a165, 0x5b340333, 0x250806a8, 0x26222306, 0xb6b66401, 0x162d3dc4, 0x3f111d27, 0x043d2d2c, 0x3c29014a, 0x2b1c0d36, 0x38393a1e, 0xbcff0200, + 0x618414fe, 0x00132408, 0x402e0021, 0x20231019, 0x0f1c0223, 0x03140c47, 0x22540c03, 0x1f1f5317, 0x50070f0d, 0x3f001b00, 0x83333fe1, 0x32e62467, + 0x8410322f, 0x5313206a, 0x132010fe, 0x422f788b, 0x1a173f30, 0x2e1b2336, 0x22b61323, 0x89136d48, 0x14fe3483, 0x0a940b0e, 0x41270f0b, 0xfbf40433, + 0x577b4d18, 0x895f072f, 0x05794194, 0xf0033a08, 0x0e001406, 0x0b405e00, 0x02040407, 0x44060303, 0xb8050105, 0x1740c0ff, 0x05480a07, 0x10050510, + 0x102f100f, 0x090d0702, 0x0f540a47, 0xb800000b, 0x1040f8ff, 0x07480f0c, 0x2a048208, 0x06030700, 0x0f03150a, 0x543f3f00, 0xc746051e, 0x4b5e2005, + 0x332e06e1, 0x39331133, 0x30313311, 0x33013701, 0x20540101, 0x03250807, 0x01875601, 0x6ffed325, 0xfed1ac01, 0xb4b46db0, 0xaa370210, 0x25fe6901, + 0xf80191fd, 0x065afe52, 0xfe36fd14, 0x219f85ed, 0x9f826401, 0x1a000332, 0x05100e40, 0x00020520, 0x04540147, 0x15000002, 0x01237182, 0x41e1f610, + 0x0123068a, 0x82b6b664, 0x014a0827, 0x0000ae00, 0x5e048706, 0x65002c00, 0x0a233f40, 0x010bb947, 0x0ba60b96, 0x010b8902, 0x0b770b67, 0x160b0b02, + 0x552c4700, 0x012ef02e, 0x20012ecf, 0x022e502e, 0x08012e0f, 0x16471519, 0x1a232d54, 0x500f041a, 0x17101f28, 0x6d42160f, 0x82322005, 0x32e122d7, + 0x06f85332, 0x4f5d5e21, 0x112205b3, 0x08822f39, 0x32e15d22, 0x420d7e42, 0x17260a88, 0x33033e33, 0x06861632, 0x11152e08, 0x6964d105, 0x1e416649, + 0x4d6963b7, 0xb61b3f68, 0x180a1a94, 0x2e594f42, 0x08269f78, 0x6057491a, 0x02b1af32, 0x2f8282c3, 0xfd58875b, 0x09a842a2, 0x944a0430, 0x142a3f2b, + 0x442f5e58, 0xd2bf162d, 0x134133fd, 0x12042105, 0x183de182, 0x1c403000, 0x55184700, 0x601a101a, 0x031a801a, 0x0b470a0e, 0x040f1954, 0x0c101450, + 0x0e2c430f, 0x88122b43, 0x082a439b, 0x2a439482, 0x84818610, 0x054b657b, 0x7b822d20, 0x1f001322, 0x1d3c7d82, 0x5700481a, 0xd0214021, 0x0321e021, + 0x0601210f, 0x560a4814, 0x0f501d20, 0x05501710, 0x20092248, 0x08e7535e, 0x200de26e, 0x0aa34405, 0x432d042c, 0x676fb27d, 0x43477fae, 0x0784b37c, + 0x8900fd25, 0x83879a9a, 0x02210803, 0x91d58927, 0xd5914c4c, 0x91d38889, 0xd3914b4b, 0xd3d3d188, 0xcfcfd1d1, 0x00020000, 0x0414feae, 0x8291823f, + 0x0020088f, 0x2e1e4036, 0x32571b48, 0x26013210, 0x470c0610, 0x2031540d, 0x10161150, 0x1b0c0f0e, 0x0005502b, 0x32259282, 0x3f3f3fe1, 0x05435833, + 0x24074144, 0x022e2205, 0x08b75527, 0x17413320, 0x021e2b05, 0x020e1415, 0x020e2203, 0x5b451507, 0x02262207, 0x0566499e, 0x0203032c, 0x1a94b604, + 0x4d3a1708, 0x81493c60, 0x48812006, 0x14220b24, 0x18482b1a, 0x2bfe2806, 0x23943606, 0x481b2d3d, 0x03250732, 0x8c5e2edb, 0x0626485f, 0x83ced021, + 0x827120c3, 0x820220c3, 0x001022c3, 0x26c38330, 0x2505202b, 0x83552447, 0x480e2fc6, 0x24315616, 0x200f221b, 0x101b500b, 0xcd82002c, 0x2506fa5b, + 0x10013f3f, 0xe848e1f6, 0x31322205, 0x0ece4830, 0x8e491720, 0x021e2508, 0x33373317, 0x23088756, 0x3502030e, 0x6620a88b, 0x2f09f048, 0x08173c4c, + 0x04b6931b, 0x0c030302, 0x604d3b16, 0x200dce48, 0x31bf8797, 0x233d2d1b, 0x01caf994, 0x1b3a13d5, 0x3d222220, 0x93421a2e, 0x08032105, 0x3308c182, + 0x40410016, 0xc203b20b, 0x03900203, 0x030203a0, 0x40c0ffb8, 0x480b071b, 0x30180303, 0x80185018, 0x0d110318, 0x17540e47, 0x150d0f0f, 0x10000712, + 0x33c13f00, 0x3220c985, 0x2306f85a, 0x32013031, 0x4506f352, 0x2c0806d3, 0x033e3317, 0x481d8902, 0x3b1c181a, 0x4b683f1a, 0x1694b629, 0x47391908, + 0x055e0458, 0x0705a805, 0x51855f33, 0x4a04b0fd, 0x3d502bc9, 0x248b8225, 0x03ecff5a, 0x088b823f, 0x4800352e, 0x13252d40, 0xa0009047, 0x57000200, + 0x5f373f37, 0x03379f37, 0x2c013710, 0x1d9f0947, 0x1d021daf, 0x29263656, 0x052c1350, 0x0e091022, 0x2c05b142, 0x39123f32, 0x0132e139, 0x325df610, + 0x05305ee1, 0x9f533320, 0x05155e0e, 0x0818a053, 0x6d3a3f5d, 0x9c6d609a, 0x544c1f3b, 0x5b412c59, 0x35141a39, 0x7348485c, 0x64372b50, 0xa161568c, + 0x89413f48, 0x17626647, 0x48465e38, 0x012a5071, 0x5178502d, 0xa6222328, 0x0f181f10, 0x243b2916, 0x3231321f, 0x4a3c1f1f, 0x6d464361, 0x222a264a, + 0x432b1d93, 0x2e34233e, 0x3c1e1d2f, 0x8200604b, 0x214608df, 0x8f02ecff, 0x1d004605, 0x19b15000, 0xc0ffb805, 0x0b082f40, 0x1f050548, 0x1f4f1f3f, + 0x471b1702, 0x2f121f14, 0x00120212, 0x20101010, 0xc010b010, 0x0610d010, 0x121a1006, 0x1714164f, 0x0b50000f, 0xe13f0016, 0x8049333f, 0x5dc62106, + 0x5d240882, 0x2b2f3311, 0x2525e782, 0x37023e32, 0x06444d15, 0x23113e08, 0x33373735, 0x21152115, 0x01161411, 0x2a2d12fa, 0x280d0923, 0x3e193430, + 0x9b2c4d6a, 0x01694e9b, 0x3fecfe14, 0x08060481, 0x0c068a03, 0x4e200509, 0x7d026585, 0xfce64e51, 0x6183fd89, 0x08a98262, 0xecffa422, 0x4a040804, + 0x30001a00, 0x17011c40, 0x1c551a47, 0x1c601c10, 0x0f031c80, 0x1b540c47, 0x120f0d18, 0x200bd74d, 0x08d14233, 0xcb4d3120, 0x08ce530a, 0x09823520, + 0x1b750322, 0x0805cd47, 0x5c8a5b22, 0x6f6ab62f, 0x1d436e51, 0x3f2b93b6, 0x622e1429, 0xcd026998, 0x82823dfd, 0x60946534, 0xb6fb3a02, 0x21060351, + 0x8182d503, 0x6d00112f, 0xff1100b9, 0x0a0f40f8, 0x0011480e, 0x2c058208, 0x01090900, 0xffb8100f, 0x1512b3c0, 0x25078348, 0x0b071c40, 0x00821048, + 0xbf132008, 0xef13cf13, 0x13500313, 0x2f130f01, 0x03134f13, 0xb8010207, 0x0a40f0ff, 0x01094701, 0x48010f09, 0x3927060d, 0x382f015d, 0x525d5ec1, + 0x2b2906ce, 0x3d3912c1, 0x332b332f, 0x52be822b, 0x332005a2, 0x0805bd52, 0xfe770124, 0x0bc7bc89, 0x04191e1e, 0x1e180507, 0xbcc70b1e, 0x4a0489fe, + 0x68219dfd, 0x1919606c, 0x21686c60, 0xb0826302, 0x14000126, 0xe3050000, 0x2f25af82, 0x00b9c300, 0x20af822f, 0x29a9820c, 0x0908002f, 0x2700480e, + 0x1082b820, 0x0a821220, 0x831f2021, 0x091f2210, 0x21c78310, 0x16830f10, 0x16820920, 0x54180f32, 0xb8270127, 0x1540e0ff, 0x5b480a07, 0x20180118, + 0x27290782, 0x09181809, 0x2d110327, 0x83eb862e, 0x13402107, 0x2e30eb82, 0x312e2e10, 0x31303120, 0x01310f02, 0xb8111207, 0x1624e282, 0x091f2d11, + 0x113ae482, 0x0619270f, 0x76196619, 0x00190319, 0x3f001510, 0x115d3333, 0x5d333f33, 0xf4823333, 0xf4823320, 0x2f331125, 0x532b2b38, 0x2b2207c1, + 0x1f822b5d, 0x270ec153, 0x032e0321, 0x23272627, 0x410cb653, 0x13230513, 0x8517031e, 0x01590809, 0x04a8f003, 0x060d0c0c, 0x0e060f0e, 0x0b190b0d, + 0xe7fed3ac, 0x140a83bf, 0x06040e12, 0x16151105, 0xacc4b30a, 0x12161709, 0x0d030604, 0x890b1512, 0x02e4feba, 0x322d1268, 0x3e3a1934, 0x6a323a3f, + 0x049cfd25, 0x2db8fd4a, 0x1d5b6769, 0x5f61571a, 0xfd6b0221, 0x5f5c2295, 0x080d8258, 0x2f6d6830, 0xb6fb4802, 0x23000100, 0xdb030000, 0x0b004a04, + 0xa140e500, 0x86010989, 0x04060103, 0x0104f701, 0x360104e5, 0x05040104, 0x060106e8, 0x2982e703, 0x09098908, 0x02f80102, 0x0102ea01, 0x02010239, + 0x7b056b01, 0x05570205, 0x4a053a01, 0x01640205, 0x58020174, 0x01350101, 0x05020145, 0x09010901, 0x060b0305, 0x08f70108, 0x0108e501, 0x08010836, + 0x19164007, 0x0e400748, 0x076b4811, 0x5702077b, 0x073a0107, 0x0702074a, 0x300d100d, 0x0d90020d, 0x0f020db0, 0xd906010d, 0x0ac8010a, 0x010aba01, + 0x0a010a09, 0x0b4b0b3b, 0x010b2802, 0x0b150b05, 0x15070b02, 0x3f000f01, 0x5d2f013f, 0x2605176b, 0x5d5d5e5d, 0x82de1071, 0x2b2b220d, 0x270582c1, + 0x39171271, 0x2f182f3d, 0x0e821f83, 0x13841020, 0x5d331125, 0x855d3333, 0x30312d0b, 0x015d5d00, 0x13133301, 0x23010133, 0x21080283, 0xcf9ffe98, + 0xfecffafa, 0xcf75019d, 0xf2fef4fe, 0x023302cf, 0x0166fe17, 0xfde9fd9a, 0xfeb401cd, 0xf782004c, 0x14fe0a32, 0x4a04df03, 0x64002200, 0x081022b6, + 0x0f0e0008, 0x83063142, 0x40240807, 0x480b071d, 0x0f0f100f, 0xcf24bf24, 0x0324ef24, 0x0f012450, 0x4f242f24, 0x18070324, 0xffb80001, 0x000c40f0, + 0x23263682, 0x1b15501c, 0xc182000e, 0xe13f322b, 0x33333311, 0xc1382f01, 0x0f244333, 0x30313324, 0x03423313, 0x030e220a, 0x09e44a23, 0x37374408, + 0x0ed7bd0a, 0x0412191d, 0x1b160506, 0xbcc70b1d, 0x411c4efe, 0x34507456, 0x40151b4c, 0x34463023, 0x04390f25, 0x289bfd4a, 0x23525858, 0x5e615619, + 0xfb630221, 0x5a815127, 0x91060b31, 0x2c170705, 0x83a02940, 0x005224d1, 0x82350300, 0x00092fd1, 0x090b406c, 0x03010397, 0x480d0908, 0xd6820703, + 0x07114036, 0x0707480a, 0x5f0b3f0b, 0x030b7f0b, 0x08010898, 0xb5f8ffb8, 0x08221e82, 0x1f820204, 0x1512b727, 0x01023f48, 0x2c2b8202, 0x071240f0, + 0x0407480c, 0x020f054f, 0x29098210, 0x014f0802, 0xe13f0015, 0x03832b32, 0x5d2f0127, 0x2b33332b, 0x0542455d, 0x825d2b21, 0x0a9354d9, 0x1dfd3533, + 0x09fe1802, 0xf4fdb002, 0x037d1e02, 0xfc928944, 0x089983d1, 0xbcfe3d30, 0xb605a202, 0x40002700, 0x051a2540, 0x2720f705, 0x0f1323f1, 0x010c10f6, + 0xf50f230c, 0x0f0110d9, 0x02105f10, 0x1a291010, 0x05f819f5, 0xa15406f5, 0x39122605, 0xe15d5d2f, 0x39738239, 0xf13333e6, 0x322fe232, 0x14053031, + 0x1517021e, 0x1135032e, 0x35232634, 0x07823632, 0x0805c445, 0x1411154b, 0x16150706, 0xf4011516, 0x28412d18, 0x365f834d, 0x837d7d83, 0x4d835f36, + 0x182d4128, 0x77737377, 0x233d3010, 0x0196010d, 0x4e6e4721, 0x56674e01, 0x0167569b, 0x476e4e4d, 0x01950121, 0x303d230d, 0x7b69b4fe, 0x7a140c14, + 0x08b3826a, 0xfee90143, 0x067f0214, 0x00030014, 0x001f402d, 0x05300105, 0x05700540, 0x02040580, 0x100300aa, 0x80034003, 0x0503c003, 0x1b020307, + 0x3f000000, 0x5e2f013f, 0x715de15d, 0x33013031, 0xe9012311, 0x14069696, 0x221882f8, 0x82330001, 0x829820fb, 0x832920fb, 0x0d2308fb, 0x07f72424, + 0xf61af100, 0x1d900314, 0x1a041d01, 0xff19eff5, 0x19d90219, 0x0e191901, 0xf923f524, 0x550ef50d, 0x11200514, 0x3322fb88, 0xfb86e633, 0x36341326, + 0x26263537, 0x5e7af282, 0x25f28205, 0x1533021e, 0x08820622, 0x07020e27, 0x35033e35, 0x87e783e1, 0x412123ff, 0x01413e60, 0x3b012309, 0xdd827a6a, + 0x01697b27, 0x233d304c, 0x08f3820d, 0x6e472168, 0x34b3fe4e, 0x9b142d48, 0xb2fe6756, 0x21476e4e, 0x0d019601, 0x00303d23, 0x02660001, 0x0302044a, + 0x0023005a, 0x1d0d403c, 0x01251025, 0x0a010a10, 0x1f0aad17, 0x40c0ffb8, 0x48131016, 0xad051f1f, 0x1f0d0f1c, 0x4f0d3f0d, 0x8f0d6f0d, 0x000d060d, + 0xf1335d2f, 0x322b2fc8, 0x5d2f01e1, 0x31ce105d, 0x032e0130, 0x9c832223, 0x33362908, 0x17021e32, 0x3233031e, 0x1537023e, 0x2e222306, 0x25120202, + 0x16292d37, 0x383b3c1c, 0x1d946419, 0x2f433732, 0x282f3725, 0x18221084, 0x10839563, 0x108b022f, 0x13050d16, 0xa2192c21, 0x190d056c, 0x330d8c14, + 0x93000200, 0x91018bfe, 0x03005e04, 0x41001700, 0xff0000b9, 0x2f05317e, 0x19a01930, 0x19c019b0, 0x9a040204, 0x0e03030e, 0x0f39b283, 0x0e480a07, + 0x139b0900, 0x02100200, 0x00020702, 0x2f5d5e2f, 0x2f01cef5, 0x08387e2b, 0x13331324, 0x585b1323, 0x06806d07, 0x3379d53b, 0x2313efdf, 0x2e1a1b2e, + 0x23141423, 0x2e1b1a2e, 0xa4021323, 0x4805e7fb, 0x07377e26, 0x0806606d, 0x00010034, 0x03ecffbc, 0x00cb05ba, 0x405a0025, 0x46031225, 0x0a04040f, + 0x40271525, 0x481e0127, 0x0a300a00, 0x0ad00a40, 0x1b0a0604, 0x0f120f73, 0x02057321, 0x9a830f05, 0x120f0c39, 0x0f050f48, 0x07100305, 0x3f001903, + 0x3939123f, 0x112b2f2f, 0x83e11033, 0x055a4203, 0x32c61030, 0x332f3911, 0x303132e1, 0x15070624, 0x5a7c3523, 0x0c84540d, 0x6e760336, 0x8a57894c, + 0x61353462, 0x4889568b, 0x17352e88, 0x193b3c38, 0x08068654, 0x021ed420, 0x4b0dcec8, 0x8d89c785, 0x0d4b88cb, 0x2103a4ac, 0x130a9a17, 0xd4ca090f, + 0x1825c3d2, 0xc78200a1, 0x00004437, 0xc9052304, 0x75002800, 0x110d1140, 0x0f0f236f, 0x07020f1f, 0x2205821f, 0x82170319, 0x0ab323b3, 0x0782480e, + 0x40c83008, 0x48090630, 0x102a1717, 0x1921012a, 0x480e0b40, 0x10291919, 0x2f0d7521, 0x8f227f22, 0xbf22af22, 0xff22df22, 0x22220722, 0x19741600, + 0x71730718, 0xcb820a06, 0x33011127, 0x5d332b2f, 0x21058211, 0xf584332b, 0x845d5e21, 0x0c154be2, 0x21152127, 0x020e1415, 0x08078207, 0x033e3585, + 0x35233535, 0x3e341133, 0x6a9a0202, 0x384242ae, 0x52304b8d, 0x7801213c, 0x271788fe, 0xec021b33, 0x492c21fc, 0xc6c61e35, 0x0592693b, 0x90232dc9, + 0x3b1b2b1d, 0xd9fe425e, 0x593ed389, 0xa6102b40, 0x44290b9a, 0x89d54361, 0x89574401, 0x0200325f, 0x1d017b00, 0x8b04ec03, 0x37002300, 0x23408600, + 0x01168f0e, 0xab2e1616, 0x180c0f15, 0x03211e06, 0x12700008, 0x39121201, 0x04013910, 0x80aa2420, 0x82000100, 0x404508ff, 0x480a0631, 0x17380000, + 0x1f011f80, 0x1e18060c, 0x0904060f, 0x1b00ae29, 0x050d1b01, 0x09cfae33, 0x900209ef, 0xb009a009, 0x091f0309, 0x096f093f, 0x2f000903, 0xe15d5d5d, + 0x5d2f32c6, 0x391712e1, 0x5dc63311, 0x83ff8432, 0x115d2413, 0x825d2f33, 0xf12b0815, 0x325d2fc0, 0x34133031, 0x37273736, 0x33363617, 0x37171632, + 0x16160717, 0x07061415, 0x06270717, 0x26222306, 0x37270727, 0x72372626, 0x42080a05, 0x020e2223, 0x811f23ba, 0x6c2f7f62, 0x2e6b3c3c, 0x1f826381, + 0x7f212325, 0x6b2e8160, 0x2d6e3c3c, 0x1f7f607f, 0x41258a23, 0x59333257, 0x42262642, 0x57323359, 0xd3022541, 0x812f6b3b, 0x24208162, 0x82812024, + 0x886d202a, 0x2024212a, 0x2d223182, 0x25823c6c, 0x89262621, 0x55002035, 0x2208052b, 0xb6054c04, 0x95001600, 0x18305b40, 0x0c130f01, 0x0115aa16, + 0x040c1515, 0x02ab0108, 0x01021f01, 0x82980202, 0x072e0828, 0x995a0b03, 0x10140114, 0x8a010c0f, 0x0c00010c, 0x0c400c10, 0x0a0c0703, 0x070f600e, + 0x6012060f, 0x13000313, 0x0f8f0f7f, 0x01133002, 0x488213d0, 0x02131f2a, 0x130f130f, 0x15120b01, 0x2d07755b, 0x5d2f2f39, 0x115d715d, 0xe1103333, + 0x04831132, 0x5e2f0122, 0x33281182, 0x32e15d33, 0x325d3932, 0x33341e82, 0x33113939, 0x12335d2f, 0x315d3939, 0x33010130, 0x21153301, 0x11240183, + 0x35211123, 0x11820183, 0x0133022e, 0x7ffebf5a, 0x01d3feef, 0xb2d3fe2d, 0xea300685, 0x02c085fe, 0xfde302d3, 0x899e8900, 0x0601fafe, 0x03240682, + 0x02000000, 0x080afd45, 0x39000726, 0x09002540, 0x40093001, 0x80097009, 0x06020409, 0x070003aa, 0x07400710, 0x07c00780, 0x04070705, 0x06030403, + 0x20050546, 0x83af8239, 0xe13322a0, 0x070b4632, 0x0f461120, 0x96962906, 0xf4fc1406, 0xf3fc19fe, 0x5e085f82, 0xf6ff7900, 0x1f065e03, 0x5a004500, + 0x4b407900, 0x51085605, 0x4c262146, 0x29463c46, 0x21ff1029, 0xb021a001, 0x5c210221, 0xbf015cc0, 0x4646015c, 0x08461700, 0x00003108, 0x10000001, + 0xc0003000, 0xf000d000, 0x00080600, 0x054c265b, 0x4c561756, 0x370d0429, 0x14152e50, 0x00010d50, 0x423fe13f, 0x1133055f, 0xc6100133, 0x32715d5e, + 0x10e12f32, 0x105d5de1, 0x835d5dce, 0x39122b0b, 0x11e11039, 0x30313939, 0x5b553413, 0x023e2206, 0x07864e33, 0x1415062c, 0x1e17021e, 0x0e141503, + 0x99550702, 0x08be7609, 0x27022e25, 0x8337032e, 0x3e172423, 0x82343503, 0x0e28080e, 0x2d1a8903, 0x554b1f3a, 0x568c6437, 0x38489d61, 0x63478c41, + 0x5f391866, 0x4e714846, 0x3429182a, 0x3b4c451c, 0x6c609b6c, 0x0805254e, 0x5d452bc5, 0x33111737, 0x73494c5e, 0x1c9a2950, 0x2348653f, 0x15212914, + 0x526c411a, 0x17262f19, 0x53332903, 0x260f2d40, 0x623d5472, 0x20282544, 0x3b271c8b, 0x2c2e1b39, 0x411c1d2f, 0x343e614e, 0x10314455, 0x474e6d26, + 0x21284d6f, 0x1e0f9e20, 0x27180e17, 0x2d1d1b33, 0x1f1f312d, 0x59644e3e, 0x373a3f25, 0x240d0f1e, 0x2622382e, 0x1e393b40, 0x3a2d1f08, 0x01020000, + 0x030c0533, 0x00d9056a, 0x0019000b, 0x0c214035, 0x0114af86, 0x8606c014, 0x00100000, 0x00500040, 0x0f000604, 0x9f179103, 0x0209cf09, 0x09010930, + 0x5d5d2f00, 0x0132e533, 0xe15d5e2f, 0xe15ddc1a, 0x34013031, 0x16323336, 0x23061415, 0x55252622, 0x24080c0b, 0x27283833, 0x28273a3a, 0x38770138, + 0x1a231328, 0x28263a10, 0x36730538, 0x35353130, 0x36353232, 0x26190c30, 0x3b09821b, 0x00030000, 0x06ecff64, 0x00cb0544, 0x00410025, 0x406a0055, + 0x1ac50543, 0x1a220f0f, 0x2c080182, 0x00c34c26, 0x34c00134, 0x42573401, 0xc90a26c3, 0x1fc90015, 0x151f150f, 0x157f152f, 0x159f158f, 0x1f000806, + 0x1f601f10, 0x1f801f70, 0x2d178205, 0xc8472d1f, 0x2dc8513b, 0xe13f0004, 0x5757e12f, 0x5d5e2c05, 0xe110e110, 0x10e12f01, 0x85715dde, 0x33112313, + 0xbe83102f, 0x20084a5b, 0x09f54e3e, 0xf9413420, 0x77012008, 0x042105f3, 0x05737515, 0x5e440420, 0x032f080f, 0x405e3d7b, 0x5f3d1d21, 0x39361743, + 0x31181938, 0x66233c35, 0x36336598, 0x3f649969, 0x343e3b84, 0x36befc61, 0xc0a78a61, 0xa7c06868, 0x8b36618a, 0x656d280b, 0x8585eaaf, 0x8765afea, + 0x04210807, 0x78532c1d, 0x52784e4b, 0x110c072b, 0x120b8309, 0x7a42070e, 0xa76567aa, 0x1d214378, 0xfe1c1a7f, 0x25448ebe, 0x35356289, 0x5c828962, + 0x4d82458b, 0x00006008, 0x03440002, 0x05420210, 0x001e00c7, 0x404e002d, 0x0f012d2f, 0x101d00e0, 0x2f1d021d, 0x2f1f2f0f, 0x2f7f2f4f, 0x24052faf, + 0x17170be0, 0x0b010b60, 0x0fe42d2e, 0x27011a0f, 0xc00600e4, 0xde1ae413, 0x1ae13f00, 0x39e1c4dc, 0xe12f3911, 0x5dc61001, 0xe1102f32, 0x5dd6105d, + 0x313232e1, 0x5d270130, 0x26230c62, 0x5d062223, 0x5c080561, 0x03111516, 0x1415030e, 0x3e323316, 0x01353502, 0x27121ce7, 0x2b23382f, 0x8d1d3448, + 0x383d638f, 0x302a5a30, 0x7d3c7533, 0x4433c977, 0x2a321229, 0x192b3a22, 0x16521d03, 0x1a0d1923, 0x66334d33, 0x1f04056c, 0x161d3948, 0x6a241a64, + 0x013afe7a, 0x1e120339, 0x2d331d2b, 0x2c412c15, 0x08d38231, 0x73005253, 0xc7039303, 0x0d000600, 0x11406000, 0xeb0d0402, 0x6004500a, 0x0a040204, + 0x0b060a04, 0xc0ffb809, 0x0c092140, 0x0f0f0948, 0xaf0f9f0f, 0xeb06030f, 0x0301039f, 0x0d030006, 0x050a0a07, 0x0c010303, 0x00010805, 0x332f332f, + 0x2f3d3912, 0x33113912, 0x23028233, 0x5d2f1801, 0xc622dd82, 0x2d42322b, 0xe1102105, 0x2605ba5f, 0x07130317, 0x84012501, 0x01523f06, 0xeeee7535, + 0x01cbfe75, 0x74360197, 0xfe74eded, 0x012902ca, 0xa4fe4e9e, 0x014ea4fe, 0x0a891b9b, 0x01003708, 0x06016600, 0x1d030204, 0x39000500, 0xaa022440, + 0x07100701, 0x01049601, 0x7901048b, 0x04560104, 0x01044b01, 0x12010438, 0x04090104, 0xad040401, 0x3f00b305, 0xca4d01e1, 0x5d5d3d06, 0xe1de105d, + 0x11013031, 0x35211123, 0xfc950204, 0xfd1d03f9, 0x968101e9, 0x00ffff00, 0x2706d77f, 0x10000602, 0x04000000, 0x08083743, 0x1e00085e, 0x4e003a00, + 0x7d40c200, 0x16b416a4, 0xb40316c4, 0x0217c417, 0x52011617, 0x0e170e15, 0x0e15c516, 0x0e151514, 0x1900090e, 0xc5091ac5, 0x00041504, 0x1a00011a, + 0x1ad01ac0, 0x048f0703, 0x1a041a01, 0xc3451f04, 0xc0012d00, 0x502d012d, 0x0e1fc33b, 0x0000c918, 0x15161b16, 0x1bc9081a, 0x26082c82, 0x1a1f1a0f, + 0x1a7f1a2f, 0x1a9f1a8f, 0x1b000806, 0x1b601b10, 0x1b801b70, 0x1a1b1a05, 0xc840261b, 0xc84a1334, 0x71000426, 0x39310570, 0x5e5d2f2f, 0xe110715d, + 0x11333311, 0xe1103912, 0x0c7b4332, 0x11201b83, 0x17821582, 0x87391132, 0x00102b10, 0x2b0587c1, 0x5d01c410, 0x015d3031, 0x3406b35a, 0x0e140523, + 0x17160702, 0x1717021e, 0x11230323, 0x32331123, 0x1f8f4316, 0x48e7023d, 0x59534f5b, 0x1b920146, 0x431f392d, 0x212a1735, 0xceb30a0a, 0xa8e99d5f, + 0x43ebfb9e, 0x033b2889, 0x4a454800, 0x4b30813b, 0x6e0d2839, 0x38472557, 0x60011111, 0x7d03a0fe, 0x43c3fe82, 0x01282883, 0x1406faff, 0xa0060604, + 0x08196561, 0xfb060427, 0x060c04f4, 0x00008c14, 0x037b0002, 0x05f20256, 0x001300cb, 0x40430027, 0x0aab1e2c, 0x01299f29, 0x0030aa14, 0x301d8240, + 0x0f10ae19, 0xe0020f20, 0x020ff00f, 0x00010f6f, 0x260e830f, 0x0f0f0603, 0x7605ae23, 0x5e2d0558, 0x715d5d5d, 0x5d2f01e1, 0xd6105de1, 0x05c746e1, + 0x440b335c, 0x7b2a0fbb, 0x41735532, 0x32567341, 0x07835632, 0x7b32552c, 0x2846341e, 0x1e354628, 0x0783351e, 0x041e3423, 0x351e888f, 0x31315572, + 0x27417255, 0x1e1e3445, 0x28274534, 0x1f1f3547, 0x97824735, 0x00662a08, 0x04020400, 0x000b00a2, 0x403a000f, 0x01111021, 0x0608080f, 0x010caa09, + 0x00ef0301, 0x60002001, 0x0300a000, 0x0cad0d00, 0x38431809, 0x832f2009, 0x335d29a6, 0xe1331133, 0x33113232, 0x0f404318, 0x15213524, 0x4318e901, + 0xfe230944, 0x189c037d, 0x08094843, 0x96fafe42, 0x00010096, 0x024a0231, 0x00c9056d, 0x4040001e, 0x00e10815, 0x204f2017, 0x2002207f, 0x480a0640, + 0x0f01e11d, 0xffb8010f, 0x150e40c0, 0x08014818, 0x12e50b1d, 0x01e51dde, 0xe13f00dd, 0x3912e13f, 0x2f06dd4c, 0xde105d2b, 0x3031e132, 0x37352101, + 0x3435033e, 0x5709c844, 0x390805f8, 0x02210707, 0xd1c4fd6d, 0x0f284839, 0x5d333642, 0x85364e2d, 0x44613c52, 0x4f361d25, 0x8c019433, 0xe4704a02, + 0x3b43553e, 0x32404122, 0x41305e26, 0x395b3f21, 0x5b555632, 0x9f829d37, 0x39021f24, 0x9f826802, 0x61003038, 0x00033c40, 0x060e1919, 0x0000e11e, + 0x3206e115, 0x328f325f, 0xa8833202, 0x0e27272a, 0x48201940, 0xe419030e, 0x35055f43, 0x1adf1a5f, 0x1a1a0805, 0xe5232612, 0xe512de2c, 0x00df0b0f, + 0xb482333f, 0x39123326, 0xe15d5e2f, 0xb883ba85, 0x2f33e124, 0x148211e1, 0x82391221, 0x061421c0, 0x210b9448, 0x42431616, 0x84352007, 0x2e5d0808, + 0x06222302, 0x033e2707, 0x021e3233, 0x45514e02, 0x53285858, 0x7b46567e, 0x35843f39, 0x606b5862, 0x545c6262, 0x1b2f2314, 0x4533613b, 0x4c443d1d, + 0x4669452c, 0x4ee70423, 0x6a17186a, 0x47643c4e, 0x851f1928, 0x49532622, 0x4f71434a, 0x1e2f2040, 0x6025290e, 0x0f1a2517, 0x00533c22, 0x0d1d6401, + 0x0500062e, 0x5f0c0f80, 0x000c020c, 0xcd1a5d2f, 0x08051d64, 0x37033e3d, 0x030e1533, 0x89012307, 0x2a2f2f16, 0x3f10db10, 0x7923514d, 0x4c1df404, + 0x15225151, 0x5358511b, 0x0100001c, 0x14feae00, 0x4a041204, 0x37001d00, 0x090d2240, 0x1f550a47, 0x47201f10, 0x143507db, 0x541c471d, 0x031b1a1e, + 0x0b161150, 0x0f091c15, 0x3f333f00, 0x0521703f, 0x105d3223, 0x051b7df6, 0x25057b46, 0x23113311, 0x174c2327, 0x078c6f05, 0x6401333b, 0x6e526f6a, + 0x93b61c43, 0x90300a1b, 0x236a4867, 0x01020201, 0x8701b6b6, 0x08305682, 0x5453932d, 0x28262a2e, 0xfe2a5523, 0x823606c0, 0xfe712893, 0x066604fc, + 0x82130014, 0x212d0893, 0x05009904, 0x05400530, 0x06040550, 0x010d0505, 0x10150099, 0x0d000115, 0x0d020d10, 0x05001203, 0x322f0000, 0x2f01c13f, + 0xd6105d5d, 0x05b141e1, 0x2107cc60, 0xb75f0611, 0x33240807, 0x78660421, 0x553d79cf, 0x3c6d9b5f, 0x64a67741, 0xfcfe3302, 0x87f97906, 0x33123303, + 0x938cc076, 0x003278c5, 0x93267982, 0x91014802, 0x79825e03, 0x1a40332b, 0x15801510, 0x15a01590, 0x94451804, 0x01e5271d, 0x5d5d2b2f, 0xfd435ded, + 0x7a932011, 0x02210f0f, 0x12a94fd3, 0xfe233608, 0x00980114, 0x00190000, 0x141f4039, 0x7f151313, 0x02128f12, 0x0d061212, 0x061b0084, 0x158c121a, + 0x480e0940, 0x0a131515, 0x2f00038d, 0x2f392fe1, 0x1001e12b, 0x27ed82c6, 0x5d2f3911, 0x33113333, 0x1420ef82, 0x2622ea82, 0x86423527, 0x2e340806, + 0x33372702, 0x01031e07, 0x16968d98, 0x310f0f2d, 0x1a504710, 0x5a253f2e, 0x3a223979, 0xe1fe192b, 0x03066c61, 0x2b03036c, 0x1a231831, 0x73b00913, + 0x3a291a08, 0x3c08ff83, 0x014a023f, 0x00b605ba, 0x4034000e, 0x7f104f21, 0x40100210, 0x0e480a06, 0x00e1020e, 0x038f037f, 0x30032002, 0x02030203, + 0xe5090ddd, 0x3f00dc00, 0x013fcde1, 0x335d5d2f, 0x2b2f33e1, 0x0572525d, 0x34115308, 0x0637023e, 0x27070706, 0x91873301, 0x01030301, 0x5e16260e, + 0xfcb6054a, 0x19040294, 0x16383c3c, 0x49112811, 0x02000060, 0x10034200, 0xc7058b02, 0x1f001300, 0x1ab22e00, 0xffb800e0, 0x091440c0, 0x2100480f, + 0x1401210f, 0x17200ae0, 0x1dc005e4, 0x1b490fe4, 0x25f58205, 0x105de1d6, 0xf76f2bd6, 0x0a6c5b07, 0x080bd35c, 0x298b0234, 0x3f446d4d, 0x292b4e6a, + 0x3e446d4c, 0xfe2c4e6b, 0x55564b3a, 0x56554b4b, 0x536d044b, 0x2f2f5982, 0x53538259, 0x2e2e5881, 0x77538158, 0x78777979, 0x8f837373, 0x73005424, + 0xeb489603, 0x40562206, 0x06d0482f, 0x04eb0724, 0x01820a02, 0x090b0337, 0x9feb000e, 0x03100103, 0x03400320, 0x070d0303, 0x0300060a, 0x4801820a, + 0x39230be3, 0x482f2f3d, 0x5d2309e3, 0x48c610e1, 0x112d05e2, 0x315de133, 0x27010130, 0x01370313, 0x08068505, 0xfe960320, 0xeded74ca, 0xfe360174, + 0x75cbfe68, 0x0175eeee, 0xfe0e0235, 0x5c014e65, 0xfe4e5c01, 0x0a891b62, 0xff003f08, 0x003f00ff, 0x058b0500, 0x002600b6, 0x0000007b, 0x02170227, + 0x0100004a, 0x023c0207, 0x00b7fdfc, 0x031d4030, 0x03181602, 0x0116bf02, 0x3f01168f, 0x01160116, 0x00011140, 0x00110111, 0x07820040, 0x11355d23, + 0x2603845d, 0x0035355d, 0x8235353f, 0x822c2051, 0x85a02051, 0x85ed2051, 0x83352051, 0x74002351, 0x51823303, 0x1840282d, 0x02181402, 0x14011400, + 0x8311b001, 0x0011244c, 0x85010070, 0x8249844c, 0x824a8351, 0x821f2049, 0x05ce2249, 0x209b82c9, 0x209b8675, 0x234983a8, 0x3f033c02, 0x3c254982, + 0x02032740, 0x089b8238, 0x01387021, 0x38013850, 0x0133b401, 0x840133a4, 0x33640133, 0x01335001, 0x20013330, 0x0f330133, 0x825d014c, 0x835d20a3, + 0x84ac8400, 0x020032a7, 0x77fe4400, 0x5e044403, 0x3b002700, 0x12404400, 0x06f57d32, 0x140b3208, 0x013d0f3d, 0x1c460b08, 0x40c0ffb8, 0x481b0f10, + 0x27170b1c, 0x379b2d27, 0x51101310, 0xe12f0017, 0x32e53f33, 0x0139122f, 0x5ee12b2f, 0x11ce105d, 0x29128239, 0x3031e12f, 0x0e141501, 0xe5630702, + 0x36322406, 0x44061737, 0x3724082b, 0x3535033e, 0x240f7c53, 0x27105002, 0x07fb7d41, 0x96543734, 0xbc524045, 0x67955d61, 0x51351b38, 0x26423436, + 0x9953ba0e, 0x3a252411, 0x7d4c515b, 0x333509fb, 0x3a2a9223, 0x588a6033, 0x545a6844, 0x3e432d2f, 0x01132b43, 0x0e10442f, 0x00ffff22, 0x26080082, + 0x7307dd04, 0x24002602, 0x07010000, 0xbdff4300, 0x15005201, 0x051502b4, 0xffb80226, 0x151bb49c, 0x01250704, 0x8200352b, 0x222f9202, 0x828d0076, + 0x4013242f, 0x8221020b, 0x156c2230, 0x232d9b1b, 0x1f004b01, 0xff225d8b, 0x5d931db4, 0x8d873520, 0x06202b82, 0x1d205d86, 0x01225d82, 0x5d922c1e, + 0xbb882b20, 0x21006a22, 0x172c2d82, 0x02030d40, 0x0326051e, 0x29150102, 0xbc832f85, 0x88003521, 0x860420bd, 0x06240831, 0x7d1f5001, 0x20403100, + 0x1aef0203, 0x011adf01, 0x40011a50, 0x1a20011a, 0x011a1001, 0x1a011a00, 0x1f000203, 0x3521a086, 0x082a4200, 0x00353208, 0xfeff0200, 0x56060000, + 0x0f00b605, 0x84001300, 0x13062a40, 0x015a0e0a, 0x03100111, 0x13a91304, 0x34132401, 0x03135413, 0x14010110, 0x0113010c, 0x0804820c, 0x0805033b, + 0x04156700, 0xf0ffb805, 0x09052040, 0x03065f13, 0x5f0d105f, 0x010a4f0a, 0x0aaf0a0f, 0x0a100802, 0x03060a10, 0x055f0e04, 0x3f001201, 0x3f2fe133, + 0x2f2f3939, 0x10715d5e, 0x280183e1, 0x382f0132, 0x32e61033, 0x063e7f11, 0x7d5d5d27, 0x11c4c487, 0x05215201, 0x2205e57a, 0x7a012303, 0x52080649, + 0x21012111, 0x56062311, 0x25fe08fd, 0x8f02bacb, 0xc3fdc903, 0xeafd1602, 0x75fb3d02, 0x016c9301, 0x053bfec5, 0x3cfea4b6, 0x01f8fda2, 0x00a802c6, + 0x7d00ffff, 0x980414fe, 0x2602cb05, 0x00002600, 0x7a000701, 0x0000fc01, 0x01b60b00, 0x18242a4f, 0x41012520, 0xc72a05ff, 0xbe030000, 0x26027307, + 0x25842800, 0xb7ff4334, 0x15005201, 0x050c01b4, 0xffb80126, 0x0c12b4c2, 0x2f420001, 0x222f8f0a, 0x413f0076, 0x012105d1, 0x22308218, 0x9b120c4a, + 0x4b01232d, 0x5d8bf1ff, 0x14b4fd22, 0x2b205d93, 0x6a228d88, 0x0142f5ff, 0x01022905, 0x02260515, 0x200c0101, 0x01425f85, 0x003e2408, 0x84640200, + 0x852c20bf, 0xb5fe21bf, 0xa820618b, 0x5220bf8f, 0x8a202f82, 0x76222f8a, 0xbf8a78ff, 0xbf8e6a20, 0x2d821120, 0x2d89a920, 0x0f20bf82, 0x0c202d86, + 0x0220ed82, 0x4020bd8e, 0x77212d82, 0x85bd8307, 0xff6a228b, 0x20bd8c0d, 0x08bd8d00, 0x00020040, 0x0400002f, 0x00b605fc, 0x001f0010, 0x1a3a405d, + 0x5b110e1a, 0x20216708, 0x1c180121, 0x10100e5a, 0x20640e01, 0x185f101b, 0x0f01000f, 0x6f003f00, 0xdf00af00, 0x0600ff00, 0x1a400008, 0x6e82481d, + 0x601c2208, 0x6017120e, 0x3f000302, 0x11e13fe1, 0x5e2b2f39, 0xe133715d, 0xe6100132, 0x102f3232, 0x105d32e1, 0x231683f6, 0x33133031, 0x3805c77d, + 0x06021415, 0x11212304, 0x2e342523, 0x11232302, 0x11211521, 0x2f002033, 0x05cd7d98, 0xb6604508, 0xfea8f7fe, 0x08049892, 0x75b87e42, 0xfe5001c9, + 0x0801a2b0, 0x25030c01, 0xb55c9102, 0xb9b0f4fe, 0x5ebbe9fe, 0x92608302, 0xfe438ad5, 0x1dfea20e, 0xffff2401, 0x0000c700, 0x35070e05, 0x31002602, + 0x07010000, 0x8b20f582, 0x27062741, 0x01260520, 0x0a2f210a, 0x260b4342, 0x05ecff7d, 0x82730771, 0x4132202d, 0x002105b3, 0x2c2d8254, 0x2802b415, + 0xb8022605, 0x2eb4abff, 0x222f9c28, 0x85020176, 0x3402215d, 0x58223082, 0x2d9b2e28, 0x004b0123, 0x832d86ae, 0x3005215e, 0xb9835b93, 0x29828b84, + 0x8b857d20, 0x8b843020, 0x31b4f023, 0x205d923f, 0x22bb882b, 0x41aa006a, 0x032905e3, 0x26053102, 0x28010203, 0x422f853c, 0x210805a1, 0x8d000100, + 0xdd032d01, 0x0b007b04, 0x00b98700, 0xb3f0ff06, 0x06481714, 0x40e0ffb8, 0x48120f18, 0x0d821000, 0x82200021, 0x83092009, 0x83092009, 0xb8032109, + 0x07822485, 0x3040e022, 0x40341a82, 0x0507010d, 0x010b0305, 0x01035001, 0x0a0a0803, 0x20020204, 0x002a5982, 0x00500020, 0x00800070, 0x4a5500a0, + 0x06092c05, 0x1900b300, 0x715d5e3f, 0x82331132, 0x2f012402, 0x8411335d, 0x315d2401, 0x822b0030, 0x84012000, 0x01800804, 0x17010137, 0x01070101, + 0xcb012701, 0x0169c2fe, 0x6842013d, 0x3f01bffe, 0xfebefe66, 0xd30267c3, 0xfe693f01, 0x673e01c2, 0xc0febffe, 0xfe3d0166, 0x000067c5, 0xff7d0003, + 0x057105b4, 0x001a00fc, 0x00310026, 0x293a405c, 0x041e2a1f, 0x015b271b, 0x040e0b19, 0x33670411, 0xbf0133c0, 0x33700133, 0x5f332f01, 0x5b1b0233, + 0x1f326611, 0x042a1e29, 0x195f222d, 0x040b0e01, 0x04161a09, 0x090c5f2d, 0x26065477, 0xe1391712, 0x7a391711, 0x0c820957, 0x31321083, 0x16070130, + 0x02141512, 0x22230606, 0x37270727, 0x50180226, 0x80080702, 0x14013717, 0x26011716, 0x0e222326, 0x27100502, 0x33161601, 0x05023e32, 0x5e5b5c14, + 0x9beda051, 0x894e85bd, 0x4c5b615a, 0x5ea3f09e, 0xfc5042a1, 0x02302eb7, 0x47723043, 0x346ca672, 0xfd586a03, 0x45722fbe, 0x326ba572, 0x6395ae05, + 0xa9b7defe, 0x6cc6eafe, 0x914e7f47, 0xbe2a0164, 0xc41501aa, 0x7f262a6b, 0xd183e1fc, 0x1db1034e, 0xda975120, 0x9701018a, 0x1e1c54fc, 0xffdb9951, + 0xffb800ff, 0x065d47ec, 0xb9423820, 0x013d3106, 0xb4150052, 0x26051801, 0xc0ffb801, 0x0b181eb4, 0x8f0be942, 0x0076222f, 0x058b42c5, 0x82240121, + 0x18482230, 0x232d9b1e, 0x79004b01, 0xfd225d8b, 0x5d9320b4, 0x26022b23, 0x228d8500, 0x427d006a, 0x0229058b, 0x26052101, 0x18010102, 0x475f852c, + 0x37220c2f, 0x31827307, 0xbf843c20, 0x31007622, 0x15208f86, 0x63248f82, 0x02070f09, 0x2207eb45, 0x7b000200, 0x103f0771, 0x3c001b00, 0x5b172140, + 0x9f1d6700, 0x1d10011d, 0x070b1101, 0x1c64085a, 0x1b066011, 0x82060b60, 0x7b072001, 0x12280666, 0x2f2f3939, 0xe110e110, 0x20051871, 0x05c1685d, + 0x0e14012c, 0x11232302, 0x15331123, 0x697b3233, 0xb0ba2113, 0x2b0d697b, 0xa85b0e03, 0xc3fe4d81, 0x39fcb605, 0x21076a7b, 0xb282888f, 0xae005d08, + 0x7504ecff, 0x4b001f06, 0x48406d00, 0x352e4607, 0x190f0047, 0x192f191f, 0x0d401903, 0x2e5f4813, 0x0f022e6f, 0x2f001f00, 0x19080300, 0x2e00002e, + 0x24410319, 0x4d571147, 0x4d204d10, 0x40034dc0, 0x4c544147, 0x03350724, 0x47503a16, 0x1f154101, 0x16161a50, 0xe1333f00, 0x12e13f3f, 0x21068a42, + 0x0a83f610, 0x2f2f2f27, 0x2b5d5d5e, 0x21cd835d, 0xc2823031, 0x58150421, 0x23200952, 0x6607f779, 0x04260b57, 0x022e3435, 0x01672223, 0x70342005, + 0x530805bc, 0x3f2bf203, 0x0e2b3f4b, 0x38394627, 0x38213d58, 0x61558d65, 0x411a358b, 0x38254c48, 0x11183451, 0x3f38482b, 0x29163555, 0x293e483e, + 0x33533c21, 0x27425831, 0x9c713fb6, 0x6c985c5c, 0x39ec043c, 0x373c4959, 0x21151e36, 0x25263127, 0x3e605248, 0x27517e57, 0x08067866, 0x402d194d, + 0x383b2428, 0x4428233a, 0x362a4643, 0x3a363f4f, 0x3e2a2c43, 0x30131329, 0x4efb4153, 0x8d68b004, 0x4c262555, 0x00ffff74, 0x03ecff5e, 0x0221069c, + 0x00440026, 0x00060100, 0x00009443, 0x3302b415, 0xb8022611, 0x39b4e5ff, 0x41220c33, 0x2d9207f7, 0x00357628, 0x0b401300, 0x2e823f02, 0x39338522, + 0x01222b9b, 0x2b85e24b, 0x33215a83, 0x2157923b, 0x8587e305, 0xbd520122, 0x3b202b85, 0x29225782, 0x57914a3c, 0x88d90521, 0xde6a30b1, 0x40170000, + 0x3c02030d, 0x02032611, 0x8547332f, 0x08d9422d, 0x8720e185, 0x50205b88, 0x38202f87, 0x30212f83, 0x8589863d, 0x0300222f, 0x082f8200, 0x04440661, + 0x0038005e, 0x00500047, 0x2f1a407c, 0x481e4b14, 0x00424204, 0x1d26484c, 0x524f5257, 0x529f525f, 0x00483903, 0xc0ffb80e, 0x110d2e40, 0x000e0e48, + 0x42005156, 0x42024210, 0x0400501e, 0x04020410, 0x4b1f4b0f, 0x4b4b0702, 0x503c2111, 0x16342c2f, 0x500a0d48, 0x10111417, 0x33333f00, 0x843232e1, + 0x39113605, 0x335d5e2f, 0x5d32e15d, 0x32e61001, 0xe1102b2f, 0x32f6105d, 0x05055fe1, 0x7405be5a, 0x16210ff8, 0x06fe7417, 0x2e721520, 0x2223230a, + 0xc6572726, 0x14372205, 0x05af5716, 0x030e0724, 0x44722201, 0x755e2005, 0x27080d0f, 0x332ba683, 0x9a6167a6, 0x60fd396c, 0x31939305, 0x254a4e55, + 0x554f4b27, 0x3eca8a31, 0x745f4c22, 0x5a7b474a, 0x4f61bd34, 0x2b083175, 0x7f6e8503, 0x1ad7010b, 0x33015437, 0x230d3375, 0x5d555d55, 0x2c0f7472, + 0x55367372, 0x51271f3b, 0x565c527b, 0x084c7526, 0x9c630237, 0x50714495, 0xffff002c, 0x14fe7100, 0x5e046f03, 0x46002602, 0x057d4a00, 0x0000422c, + 0x01b60b00, 0x0520262f, 0x7d4a250d, 0xff712606, 0x06e103ec, 0x20258221, 0x0b974248, 0x2611282b, 0xb9ffb802, 0x05282eb4, 0x0a97420f, 0x76212d8f, + 0x053f4252, 0x2e823420, 0x2e287622, 0x01222b9b, 0x2b85de4b, 0x03215a83, 0x21579230, 0x8588d905, 0x42da6a21, 0x3127066b, 0x02032611, 0x853c2800, + 0x053b4259, 0xffffff22, 0x01214a82, 0x20b58467, 0x22db84f3, 0x8255fe43, 0xb4152cdb, 0x26110401, 0x9affb801, 0x4b040ab4, 0xae240c05, 0x42020000, + 0x76222f8a, 0x2f8230ff, 0x0b401324, 0x30821001, 0x0a047422, 0xff212d8b, 0x202d82bd, 0x232d8955, 0xbbfe4b01, 0x5e832d86, 0x8c0c0021, 0xeeff215b, + 0x25202d82, 0x8b85bb84, 0x2d846a20, 0x0d40172c, 0x110d0102, 0x00010226, 0x314b1804, 0x0061080b, 0xff6f0002, 0x062d04ec, 0x00270023, 0x40740039, + 0x48281246, 0x16202300, 0x221c0419, 0x22221c18, 0x0a03181c, 0x403b5700, 0xe03bd03b, 0x3b0f033b, 0x48320601, 0x203a560a, 0x04162319, 0x1d212117, + 0x120f502d, 0xbf0faf0f, 0x0f30020f, 0x170f1701, 0x37011d0f, 0x00160550, 0x393fe13f, 0x5d2f2f39, 0x05ee615d, 0x4b451120, 0x5d5e2406, 0x4ce6105d, + 0x128305e2, 0xf2531020, 0x0b516e05, 0x37171627, 0x05272626, 0x21058327, 0x0d821637, 0x1e071724, 0x48450703, 0x1e142507, 0x36323302, 0x0805676e, + 0x7faf6887, 0xa8763f47, 0x2b9a6669, 0x5a781f08, 0xd94a00ff, 0x462f5528, 0xe33b7a41, 0x6f43c34a, 0x22bc2c4f, 0x4d4b6e46, 0x2121466d, 0x9a4c6d47, + 0x8e3d0287, 0x424f98dc, 0x7777b97f, 0x3b417eb8, 0xc076043c, 0x83729951, 0x7b1a371c, 0x8a2c4820, 0x9c417571, 0x38b0ddbb, 0x2e32526b, 0x4c558358, + 0xc7315a7d, 0x00ffff00, 0x040000ae, 0x02e30512, 0x00510026, 0x01060100, 0x0000f952, 0x010b4013, 0x01261121, 0x0b302202, 0x0d914217, 0x062d0423, + 0x202b8221, 0x05bf4252, 0x0000d82f, 0x2002b415, 0xb8022611, 0x26b4d7ff, 0x0c3b4a20, 0xecff7122, 0x76212d8c, 0x21598450, 0x2e822c02, 0x26204e22, + 0x01222b9b, 0x598afb4b, 0x28b4fa22, 0xb3845992, 0x01228784, 0x2d84e252, 0x87842820, 0x29b4fd23, 0x215b9137, 0xb588d905, 0x00f96a2b, 0x03b61900, + 0x26112902, 0x23b78203, 0x3420b4f9, 0x080cc34a, 0x66000375, 0x0204f800, 0x0300ac04, 0x2b001700, 0x15406000, 0x22012d30, 0x0e1818aa, 0x660356aa, + 0x03280203, 0x03020338, 0xf0ffb800, 0x0d092840, 0x27040048, 0x011d10ad, 0x1d011d0f, 0xad09011d, 0x13101300, 0x13601320, 0x13c013b0, 0x070713d0, + 0xad001313, 0x3f00b301, 0x5e2f33e1, 0x3311e15d, 0xe1715d2f, 0x2b332f01, 0xe15d5d33, 0x5de12f33, 0x35133031, 0x18011521, 0x180e3952, 0x340f4952, + 0xfd9c0366, 0x291f12bf, 0x202a1718, 0x2a201212, 0x1f291817, 0x360f8f12, 0x96968702, 0x2f23eefe, 0x1e0d0d1e, 0x2f21232f, 0x1f0e0e1f, 0x8edb022f, + 0x00550810, 0x73000300, 0x2f04b4ff, 0x1a009104, 0x2d002400, 0x3b405c00, 0x1e281f27, 0x48251b04, 0x15161817, 0x090a0807, 0x57000d08, 0xd02f402f, + 0x032fe02f, 0x06012f0f, 0x560d481b, 0x271e282e, 0x222b041f, 0x180a0750, 0x16050415, 0x502b1012, 0x00160508, 0x3fe1c63f, 0x0adc4ac6, 0x5d5d5e24, + 0xdb4af610, 0x0e142209, 0x06d64a02, 0x84352621, 0x171627e5, 0x16071737, 0xd94a0516, 0x05062207, 0x05d84a34, 0x2f043634, 0x6fb27d43, 0x8344627d, + 0x43463f50, 0x3f6fb37c, 0x0b823171, 0xfd453e33, 0x01161300, 0x2d4b1d8d, 0x4402879a, 0x1f72fe27, 0x29098348, 0x91d58927, 0x4a6d354c, 0x76714883, + 0x1d260805, 0x81496c1c, 0x5486d149, 0x87023383, 0xd1cf1211, 0x7bfd639f, 0x00d31011, 0xa400ffff, 0x0804ecff, 0x26022106, 0xbb425800, 0x00a33105, + 0x01b41500, 0x0126111b, 0xb49bffb8, 0x190c1b21, 0x8f0ae942, 0x6076282d, 0x40130000, 0x8227010b, 0x1b57222e, 0x222b9b21, 0x85084b01, 0x215a832b, + 0x57922300, 0x88d90521, 0x026a2b85, 0xb6190000, 0x11240102, 0x87820226, 0x1bb4fb23, 0x475b852f, 0x0a2408e9, 0xdf0314fe, 0x5c20b784, 0x7621b784, + 0x205d850e, 0x2389822f, 0x00292367, 0x72083146, 0x2a080767, 0x20001406, 0x38003100, 0x482f1f40, 0x1033570a, 0x20270133, 0x471b151f, 0x1d32541c, + 0x2c1b1b00, 0x160f1550, 0x05005021, 0x7a3f0010, 0x32200a8d, 0xbd4a0082, 0x05875906, 0x0e141525, 0x72222302, 0x11220c74, 0x6a722507, 0x6401210d, + 0x7b0b5c72, 0x032806de, 0xb6040203, 0x1f0108b6, 0x210bc271, 0x5e72b603, 0x0a78720b, 0xfe000825, 0x72119436, 0xff220d6d, 0xf58400ff, 0x02d90524, + 0xf5850026, 0x00b16a30, 0x0d401700, 0x112c0102, 0x0b010226, 0xf7853723, 0x220ce94b, 0x53c106dd, 0x4d220879, 0xa9533300, 0x05172905, 0xffb80226, + 0x1615b4ff, 0x260c7b53, 0x03ecff5e, 0x496f059c, 0x4d21083f, 0x05c749e6, 0x5e823520, 0x34332322, 0x54056d49, 0x40200c33, 0x4e225b88, 0x454c2100, + 0x1a022105, 0x62535c82, 0x852d8608, 0x88ee2059, 0xd44e2159, 0x38205985, 0x25205982, 0x86079749, 0xfe00262b, 0x05dd0442, 0x265988bc, 0x00620351, + 0x82140000, 0x27803ae7, 0x01273001, 0x00272700, 0x2b012500, 0xff355d5d, 0xfe5e00ff, 0x04b80342, 0x2459865e, 0x02510107, 0x352d825a, 0x02164020, + 0xa00145f0, 0x45900145, 0x01458001, 0x00014530, 0x36864545, 0x39855d20, 0xecff7d26, 0x73079804, 0x22081b53, 0x850a0176, 0x300127c1, 0xcd012605, + 0x20532a24, 0x05235306, 0xecff7126, 0x21066f03, 0x3606cb48, 0x4a760006, 0x40170000, 0x112c010e, 0x20100126, 0x2620a701, 0x82250d05, 0x86352094, + 0x235d8ec5, 0xb4004b01, 0x210af54d, 0x7e532c77, 0x205d8907, 0x225d898f, 0x85f54b01, 0x8320205d, 0x0128235d, 0x2f492853, 0x8d5d2005, 0x8737205d, + 0x4f0123bb, 0x5d860002, 0xbb822f20, 0x2c248022, 0x0521bb91, 0x25bb86e5, 0x014f0107, 0x5f850033, 0xbd852b20, 0x28204d22, 0x4c22bd9d, 0x5f86a800, + 0x5f822920, 0x912f6b21, 0x8aa020bd, 0x064c21bd, 0x25205d85, 0x2b235d83, 0x8e2b6401, 0x00c726bd, 0x07fc0400, 0x288f8273, 0x01000027, 0x004c0107, + 0x0597424a, 0x26051d2a, 0xb7ffb802, 0x061823b4, 0x260b414f, 0x05ecff71, 0x82140652, 0x8347202f, 0x3802232f, 0xbf82d902, 0x02b60b28, 0x1d3e3e5e, + 0x474a251d, 0x06475306, 0x00060223, 0x211d8292, 0x35820002, 0x9e044208, 0x27001406, 0x55003800, 0x1b1f3140, 0x26472d00, 0x220b1d1d, 0x103a5526, + 0x4836013a, 0x2739560b, 0x4f1d2515, 0x101e1e22, 0x50330020, 0x10100016, 0x03102010, 0x50281010, 0x00160600, 0x3fe1333f, 0x2503825d, 0x332f3912, + 0xb57532e1, 0x32e62b06, 0x102f3911, 0x323232e1, 0xa47e3031, 0x05a76716, 0x15331523, 0x2aac7e23, 0x0185fe27, 0x9c9cb67b, 0x12b27e93, 0x8a462508, + 0xce8786cc, 0x2c19478b, 0x1f21203a, 0x9e10371a, 0x89b6b689, 0x2c832bfb, 0x275a8559, 0x34669561, 0xc3c6c3cf, 0x23058153, 0xc106be03, 0x22073955, + 0x42004d01, 0x0e2607d1, 0x02012605, 0x914a0d0c, 0xff71260c, 0x05e103ec, 0x07f14a6f, 0x93432d82, 0x112a2605, 0x28110226, 0x0c494b29, 0x2005f155, + 0x22598840, 0x42fbff4e, 0x1120060f, 0x06215982, 0x0dc15516, 0xee205985, 0x4e215988, 0x205985ea, 0x2159822d, 0x774b320f, 0x2059850d, 0x2a59881a, + 0x013f014f, 0x40130035, 0x8217010b, 0x0c072259, 0x20b39214, 0x255986e5, 0x014f0107, 0x5b85002b, 0x5b823320, 0x30280c22, 0xfe25b58d, 0x05be0342, + 0x225b88b6, 0x82210251, 0xb90e382d, 0xc1ff0100, 0x001212b4, 0x2b012500, 0x00ffff35, 0x0361fe71, 0x885e04e1, 0x51230855, 0x1f003b02, 0x13402700, + 0x013bf002, 0xa0013be0, 0x3b90013b, 0x013b5001, 0xb8013b00, 0x3bb4caff, 0x821a1a3b, 0x845d203a, 0x00352100, 0x57077941, 0x01230941, 0x41f9ff4c, + 0x04210a1f, 0x121f4117, 0x2209f14c, 0x41e44c01, 0x0921091f, 0x0d1f4133, 0xecff7d24, 0x5984f204, 0x00002a28, 0x4b010701, 0x5986d700, 0x26052c28, + 0x2c346d01, 0xa147010c, 0xfe25240a, 0x84fc0314, 0x824a2059, 0x0106232d, 0x5984c64b, 0x115f0328, 0x67030326, 0x8155275f, 0x2059820e, 0x85f58240, + 0x004e2259, 0x205986c9, 0x21598231, 0x5992365f, 0x82ee0521, 0x2759852d, 0x0000b14e, 0x6403b415, 0xb8245882, 0x69b4efff, 0x37205b93, 0x4f225b88, + 0x5b860c02, 0x5b833720, 0x91342c21, 0xe50521b5, 0x07255b86, 0xf2004f01, 0x205d8400, 0x235d846a, 0x675fb4ec, 0xfe25b98d, 0x05f2043b, 0x235d87cb, + 0x17013902, 0x0b252f82, 0x2c5101b6, 0x22588632, 0x4100ffff, 0x02220e0b, 0x0b412d3a, 0x21b28305, 0xaf8d651c, 0x0000c726, 0x7307d504, 0x2b215182, + 0x05654100, 0x41587f20, 0xb4ff240b, 0x41050c14, 0xae200b3b, 0x12222f82, 0x2f82aa07, 0x2f864b20, 0x89012b39, 0x14401f00, 0x70010d70, 0x7001010c, + 0x021a011a, 0x22190126, 0x41180b1a, 0x5d27059e, 0x005d5d35, 0x82000200, 0x05300800, 0x00b6059c, 0x00170013, 0x142f4056, 0x075a0c04, 0xb019650b, + 0x19af0119, 0x01191001, 0x5a0f0317, 0x18641000, 0x16175f0e, 0x1360120a, 0x17130307, 0x01240182, 0x05120b10, 0x2505496c, 0x39391233, 0x466c2f2f, + 0x10322205, 0x05d77ee1, 0x5d5d3230, 0x32f6105d, 0x313232e1, 0x33351330, 0x03822115, 0x23153326, 0x21112311, 0x23380382, 0x21350135, 0x02bac715, + 0xc7c7ba9a, 0xba66fdba, 0xfd1b04c7, 0xf3c30466, 0x4f080082, 0x02d3fb96, 0x0456fdaa, 0x8bfe962d, 0x0100dfdf, 0x00001200, 0x14061204, 0x55002100, + 0x0b133440, 0x55214700, 0x60231023, 0x03238023, 0x0a121617, 0x540b0f47, 0x4f0d1522, 0xcf0ebf12, 0x0e0e020e, 0x50041710, 0x1d101d00, 0x1d031d20, + 0x0b001010, 0x2106ea7f, 0xa782e15d, 0x335d2f24, 0xa08632e1, 0x9f823220, 0x3912e122, 0x220d777d, 0x82333523, 0x152123a8, 0xfe7f1521, 0x9c9c2711, + 0xfe7b01b6, 0x40180885, 0x2f080804, 0x3482829a, 0xfd609466, 0x89d504f0, 0xb889b6b6, 0x2a3f2b90, 0xfdd2bf14, 0xffff005c, 0x0000f5ff, 0x3507c402, + 0x2c002602, 0x07010000, 0xf3fe5201, 0x26067142, 0x01260514, 0x44231501, 0xff210b47, 0x222d82a3, 0x82e30572, 0x86f3202d, 0x44a1202d, 0x01220547, + 0x2d82110c, 0x441b0d21, 0x3d200c75, 0x7c222d82, 0x5b88c106, 0x22ff4d22, 0x0e205b86, 0x57455b83, 0xebff210d, 0x2a222d82, 0x5b886f05, 0xd0fe4d22, + 0x06205b86, 0x04215b83, 0x205b8c05, 0x222d8230, 0x8840078a, 0xff4e215b, 0x20075d5a, 0x205b8211, 0x0d594502, 0x82deff21, 0x0538222d, 0x225b88ee, + 0x86bdfe4e, 0x8209205b, 0x0e02215b, 0x270c1750, 0x42fe5200, 0xb6056402, 0x51225b88, 0x27439c00, 0x19002105, 0x2907a25b, 0x4400ffff, 0x830142fe, + 0x2582e505, 0x00004c2f, 0x51010601, 0x10000025, 0x6f020a40, 0x82a88225, 0x0125240b, 0x82355d2b, 0x82522027, 0x0764227b, 0x224d8837, 0x4150004f, + 0x17200605, 0x0020a982, 0x7c0ba945, 0x01240557, 0x004a0464, 0x200fff7f, 0x13ff7f0f, 0x834a0421, 0x7bfe265f, 0xb6052904, 0x06c14100, 0x022d0023, + 0x08ad82b6, 0x0e403828, 0x187f1801, 0x01184f01, 0x07074018, 0xffb81848, 0x061740c0, 0x21bf4806, 0x0121a001, 0x5001218f, 0x210f0121, 0x1c832101, + 0x835d2b21, 0x822b2000, 0x83112006, 0xfea026b1, 0x05870314, 0x835182e5, 0x000724d9, 0x8212024d, 0x402e3f51, 0x1e020320, 0xdf011ecf, 0x359f0135, + 0x01358001, 0x4001355f, 0x35200135, 0x01350001, 0x5b824035, 0x4b824785, 0x82351121, 0x48ff2347, 0x5f5c7bfe, 0x002d2806, 0x01070100, 0x86cafe4b, + 0x831420f9, 0x141c23f9, 0x83450e0d, 0xbcff2b09, 0x570214fe, 0x26022106, 0x2d863702, 0x2407a341, 0x01261114, 0x2b2d8d00, 0x3bfec700, 0xb605a204, + 0x2e002602, 0x062e2d82, 0x00733902, 0x00b90e00, 0xb4b1ff01, 0x7344130d, 0xffff2905, 0x3bfeae00, 0x1406f003, 0x4e202582, 0x21202585, 0xc4252586, + 0x0a150fb4, 0x087d8405, 0xae000137, 0xf0030000, 0x11004a04, 0x0a404900, 0x0e101001, 0x11440f0f, 0xffb81101, 0x071c40c0, 0x1011480a, 0x0f131111, + 0x02132f13, 0x47030707, 0x0c125404, 0x0f050e01, 0x05b04304, 0x39393327, 0xe1f61001, 0xff411832, 0x11400808, 0x33113933, 0x01213031, 0x11231107, + 0x06141133, 0x37070607, 0x01013301, 0xacfe2303, 0x05b4b46d, 0x83040403, 0xfecd3301, 0x01ac016f, 0x68fe51e9, 0xe7fe4a04, 0x2c26663c, 0x8101b024, + 0xa0fd16fe, 0x200d1747, 0x24b7822f, 0xff760007, 0x05574565, 0x2605122b, 0x70ffb801, 0x000c06b4, 0x093b4104, 0x00ab0027, 0x07340200, 0x20e782ac, + 0x352f864f, 0x008b0122, 0x7014401f, 0x02700103, 0x10700101, 0x26021001, 0x2e536601, 0x355d2309, 0x69845d5d, 0x473bfe21, 0x698306eb, 0x39020623, + 0x0621412d, 0x6388dd20, 0x00ffff29, 0x013bfe66, 0x8714066c, 0x3902245f, 0x8600f7fe, 0xb4e02127, 0xcf475487, 0xb7052107, 0xb7842782, 0x01380234, + 0x00a3ff00, 0x010d4016, 0x1001030b, 0x06600106, 0xb783020c, 0xbb625d20, 0x82ae2006, 0x88b420b7, 0x02063857, 0x00003b38, 0x01114018, 0x100e4004, + 0x06400448, 0x045e4809, 0x82030304, 0x2b2b22e9, 0x205f8835, 0x2c5f87b6, 0xe3014f01, 0x0b0065fd, 0x06ab01b6, 0x0610410e, 0x2b058552, 0x1406a202, + 0x4f002600, 0x07010000, 0x21082582, 0x0038fd2d, 0xff16402b, 0x13ef0113, 0x01139f01, 0x7f01138f, 0x135f0113, 0x01131f01, 0x2e01b801, 0x694804b4, + 0x855d2006, 0x08368200, 0x001d0035, 0x05be0300, 0x000d00b6, 0x0b324061, 0x050c0506, 0x0d040300, 0x05050404, 0x0f08080a, 0x10010faf, 0x0d0c010f, + 0x0703060d, 0x0a000b5a, 0x04050e64, 0x82040c0d, 0x07012a01, 0x01120a5f, 0x3f3f0003, 0x067146e1, 0x33112208, 0x32f61001, 0x3232e132, 0x5d332f33, + 0x1133115d, 0x332f3912, 0x04877d10, 0x8710c4c4, 0x3031c4c4, 0x08138213, 0x05173725, 0x21152111, 0xc7270711, 0xfe4ee3ba, 0xfd3d02cf, 0x02496109, + 0xfd1203a4, 0xbe7d8f63, 0x01a639fe, 0x827d3cf8, 0xf6ff2599, 0x1d020000, 0x0b2ddf82, 0x3b406900, 0x0d500d40, 0x05060902, 0x379e830a, 0x0b0b0a0b, + 0x05dd0408, 0xcb05bb01, 0x050f0205, 0x052f051f, 0x05050603, 0x472aa482, 0x54080009, 0x050a0b0c, 0x01820a04, 0x15070124, 0xa2820001, 0x3227a190, + 0x5d5d5e2f, 0x8211335d, 0x219f88a9, 0xa1875d01, 0x23110722, 0xae369f82, 0xb94e6bb6, 0x024e6ab6, 0xfd1e03f6, 0x78794559, 0x4a023ffd, 0xcb5e7946, + 0x5e732008, 0x002307cb, 0x4df20076, 0x55220abd, 0x4b531e18, 0x00ae260c, 0x06120400, 0x072d5421, 0x6f76002f, 0x40130000, 0x1125010b, 0x195c0126, + 0x0c2d541f, 0x3bfec726, 0xb6050e05, 0x02235987, 0x42d90039, 0xe1210781, 0x435787b4, 0x042305f1, 0x875e0412, 0x39022253, 0x06a7424c, 0x87b4de21, + 0x23a79151, 0x9c004c01, 0x1d26a786, 0x00012605, 0xa79b1823, 0x0c4c0128, 0xb4150000, 0xa6821e01, 0xfaffb825, 0x8b1924b4, 0x085d82a9, 0xa1040034, + 0x2700b605, 0x8f005100, 0x06010000, 0x00e80702, 0x1d402900, 0x27551800, 0xbf0127ef, 0x279f0127, 0x01275f01, 0x2701272f, 0x48080840, 0x06064027, + 0x3b452b48, 0xf6102205, 0x23328234, 0x7bfec700, 0x4408ed83, 0x4a002500, 0x0c182a40, 0x04205a1f, 0x65201504, 0x0127b027, 0x0001278f, 0x02271027, + 0x140e1317, 0x2664155a, 0x03160d1f, 0x0c181215, 0x005f0712, 0x3fe12f00, 0x333f3f33, 0xf6100133, 0x323232e1, 0x105d5d5d, 0x06774de6, 0x01303122, + 0x2109707c, 0x43180135, 0x2c0809fd, 0x27263301, 0x11352626, 0x0e141133, 0x338b0302, 0x4e221b4d, 0x3d4b252d, 0x0808fd26, 0x05040406, 0xcc02d5ac, + 0x03040307, 0x6437ae05, 0x775b188f, 0x1f59180a, 0x4175270b, 0x347d3841, 0x5b182003, 0xdd6a0989, 0x5e2f0805, 0x3a002800, 0x03032240, 0x24470c17, + 0x2a102a55, 0x2a802a60, 0x47161a03, 0x1a295417, 0x10205010, 0x15170f18, 0x1b005007, 0x3fe13f00, 0x85e13f3f, 0x087861b8, 0x1320b18b, 0x116b4618, + 0x82031521, 0xee0221b1, 0x090d4818, 0x70690229, 0x1d436e51, 0x481a94b6, 0x222208fc, 0x48186d48, 0x03210a14, 0x060b496d, 0x4a04c723, 0x05064994, + 0x4d95fc3b, 0xff2f577b, 0xff7d00ff, 0x067105ec, 0x002602c1, 0x01000032, 0x004d0107, 0x051342bc, 0x052a0227, 0x28000226, 0x0c134229, 0xecff7126, + 0x6f052d04, 0x2a070756, 0x00144d01, 0x0b401300, 0x82112202, 0x2120212b, 0x59842b8c, 0x88400721, 0x004e2259, 0x205986aa, 0x2159822d, 0x55613201, + 0x2059850d, 0x275988ee, 0x0000004e, 0x2502b415, 0xb8245882, 0x2ab4ffff, 0x850dbd56, 0x080f625b, 0x00530123, 0x2a5b82ec, 0x030d4017, 0x26053402, + 0x61430203, 0xe7820d53, 0x230e4957, 0x00465301, 0x21051d5c, 0x2f82112c, 0xbf564520, 0x0002210e, 0x44086182, 0xcd05a406, 0x2a001900, 0x36405b00, + 0x16011614, 0x18140016, 0x0927275a, 0x2c670012, 0x1f012c1f, 0x2b66095b, 0x144f5f17, 0xaf140f01, 0x14080214, 0x5f121914, 0x5f1a0311, 0x5f24040e, + 0x5f191304, 0x3f001200, 0x210185e1, 0x60183912, 0x5d270895, 0x1132e610, 0x83e12f39, 0x315d2504, 0x06212130, 0x0cbe5918, 0xbe651720, 0x08b67409, + 0x37363108, 0x06262611, 0x2b0afda4, 0xefa3305b, 0x9e4c4c9d, 0x5462a3f0, 0xc2fdf402, 0xe9fd1702, 0x56fc3e02, 0x346ca672, 0x72a56b34, 0x26265a34, + 0x6c0b0959, 0x081a5b18, 0xe1651720, 0x85043a05, 0x8ada9751, 0x5199db89, 0x58040f12, 0x00001110, 0xff710003, 0x04e106ec, 0x08df825e, 0x3f003641, + 0x3b406400, 0x1d3f0313, 0x0131d048, 0x370b3131, 0x571c2548, 0x01410f41, 0x400141ff, 0x482b0141, 0x1d40560b, 0x2b3f1b50, 0x3f0f023f, 0x3f3f0601, + 0x50343c2e, 0x10101316, 0x03502e20, 0x5c160600, 0x3f2405bd, 0x32e13333, 0x0ad04e18, 0x715d5d22, 0x2a06b75c, 0x3932e15d, 0x05303139, 0x68272622, + 0x332109f8, 0x14b55c32, 0x18140121, 0x3d09d24c, 0x022e3405, 0x07062223, 0xcc826005, 0x80c63f41, 0x477fae67, 0x6fb37c43, 0x3c3fc379, 0x4e1875b9, + 0xfb3711fc, 0x969a899a, 0x9a978c8b, 0x1bf00487, 0x723e5839, 0x70140b85, 0x18706d6d, 0x23075448, 0x70696a6f, 0x300f995c, 0xd3d13b02, 0xcedcd1c9, + 0x714462cf, 0x959c2c50, 0x05294500, 0x07a00426, 0x00260273, 0x20059f6a, 0x076f6476, 0x2605292b, 0xeeffb802, 0x02231db4, 0x0a89480d, 0x0000ae23, + 0x05195703, 0x00005527, 0x76000601, 0x05d345ce, 0x26112328, 0x1d174001, 0x2b8a030e, 0x3bfec726, 0xb605a004, 0x062b5b86, 0x00773902, 0x00b90e00, + 0x88b6ff02, 0x26818255, 0x033bfe60, 0x825e0408, 0x25518325, 0xfe390207, 0x278400f1, 0x08ff0123, 0x915187b4, 0x4c012aa9, 0x52010e00, 0x02b41500, + 0x23a98422, 0x1d28b4a9, 0x7220a98c, 0x0a22a982, 0x57872106, 0xff4c0123, 0x23578270, 0x1c01b415, 0xb825aa82, 0x22b4e3ff, 0x26ad8c17, 0x03ecff68, + 0x827307c9, 0x4936202f, 0x00210563, 0x05c5433b, 0x05400128, 0x34700126, 0xe94e083a, 0x825a200b, 0x843f202d, 0x8256205d, 0x0006232d, 0x0741dc76, + 0x82422005, 0x365d225c, 0x8e2b8c3c, 0x4b012359, 0x5986edff, 0x59823420, 0x343c2222, 0x598e2d8c, 0x9b4b0122, 0x36205985, 0x1c225982, 0x2b8c363e, + 0x14fe6826, 0xcb05c903, 0x7a22b388, 0x3b413501, 0xb4fa2207, 0x2357863a, 0x5a00ffff, 0x3f222782, 0x27825e04, 0x0724ad83, 0xf0007a00, 0x0b242782, + 0x3c0101b6, 0x25825087, 0x4c22a78f, 0xa786e6ff, 0xa7823920, 0x9d3f1b21, 0x974c21a7, 0x3b20a785, 0x1821a782, 0x26a78d41, 0x043bfe14, 0x82b60512, + 0x0037277f, 0x02060100, 0xe141f939, 0xb4d82506, 0x05030e08, 0x26066f52, 0x023bfe21, 0x8246058f, 0x82572025, 0x02072425, 0x875dff39, 0xb4f724cd, + 0x8712241e, 0x00142627, 0x07120400, 0x244d8673, 0xff4c0107, 0x20a786c8, 0x22a7820d, 0x85081303, 0x06715651, 0xecff2126, 0x1406e802, 0x062c5586, + 0x006f3802, 0x01b60b00, 0x18242461, 0x18058350, 0x080a275c, 0x73000f5c, 0x111f4c40, 0x0111e001, 0x11df115f, 0x30112002, 0x03114011, 0xff05bf08, + 0x05050205, 0x015a060a, 0x0250010f, 0x1f0202f0, 0x02020102, 0x8701770d, 0x03019701, 0x00010131, 0x20011001, 0x01070301, 0x07600d0a, 0x0b030000, + 0x5f020612, 0x3f000303, 0x123f32e1, 0xe1332f39, 0x79490132, 0x2f333605, 0x39125d5d, 0x3232e110, 0x5d395d2f, 0x31715d5d, 0x21110130, 0x070c4535, + 0x0b822320, 0xfeb6013c, 0xfefe035e, 0xfe27015f, 0xd7febbd9, 0xdf013303, 0x21fea4a4, 0x0262fd95, 0x4918959e, 0x41080a2f, 0xb66a0025, 0x20011f14, + 0xb8051c1c, 0x3740c0ff, 0x05480b08, 0x272f2705, 0x1f02273f, 0x1347231b, 0x161f160f, 0x14181602, 0x10101000, 0x10b010a0, 0x070510c0, 0x4f221110, + 0x0b1f1f14, 0x1a4f1e15, 0x49181b18, 0xa6890c3c, 0xc4333324, 0xa182325d, 0x33115d2b, 0x11332b2f, 0x315d0033, 0x49491830, 0x2335230c, 0x03823335, + 0x33373723, 0x84b88215, 0x51491803, 0x8b8b2e11, 0x694e9b9b, 0xecfe1401, 0xfefe0201, 0x5749183f, 0x8afb2c0d, 0xe64e51f8, 0x8af889fc, 0x666261fb, + 0x3521083d, 0x06af6502, 0x00520123, 0x2c038260, 0x2001b415, 0xb8012605, 0x21b4ffff, 0x0c0f662f, 0xecffa426, 0xe3050804, 0x58272f82, 0x06010000, + 0x44f35201, 0x06220987, 0x735b3224, 0x82b8200c, 0x05ef592b, 0x2b823820, 0x4d010724, 0x5b858f00, 0x5b861a20, 0x92191821, 0x886f205b, 0x214d215b, + 0x1d265b85, 0x05012611, 0x5b911c1b, 0x88400721, 0x004e22b7, 0x0b694a7d, 0x95662220, 0x20b5850d, 0x215988ee, 0x59850c4e, 0x59822020, 0x5b250421, + 0xb5840dfd, 0x88d90721, 0x00502259, 0x07316b7b, 0x26051d25, 0x87000102, 0x08d75a5b, 0x06215d84, 0x205d8887, 0x245d8250, 0x020d4017, 0x225e8201, + 0x87050102, 0x672f885f, 0x01230e81, 0x87b20053, 0x83242061, 0x67362061, 0x61831023, 0x175d0e20, 0x53012409, 0x84000050, 0x11272161, 0x48209182, + 0x26108f5c, 0x0442feb8, 0x88b805dd, 0x02512ac3, 0x00000019, 0x0d01b60b, 0x07de6725, 0x00ffff23, 0x222582a4, 0x864a0416, 0x010724b7, 0x85b80251, + 0x210e2525, 0x251a1a21, 0x2606c758, 0x06000014, 0x827307fe, 0x003a2725, 0x01070100, 0x9f45014b, 0x052b2707, 0x33000126, 0x6d501e2b, 0x8200200a, + 0xe305212d, 0x5a20a984, 0x00212d85, 0x255382ae, 0x010b4013, 0x2d821130, 0x11303823, 0x0ee96f2e, 0x230afb67, 0xd0ff4b01, 0x2006c541, 0x225b8209, + 0x67091102, 0x6f5c09fb, 0x09655d07, 0xa94b0122, 0x22097b42, 0x5d232b02, 0x2b820965, 0x04237482, 0x822b0737, 0x833c20b5, 0x6a002387, 0x6341ceff, + 0x05122707, 0x01010226, 0x5b851d09, 0x23089541, 0x03000052, 0x3d20e785, 0x76223184, 0x8b863900, 0x8b821620, 0x100a5e22, 0x830c2753, 0x8435202d, + 0x465d208b, 0xd6200587, 0x16208b85, 0x6020e582, 0xfe222b92, 0x8b823707, 0x01235984, 0x6829014f, 0x0b210ae1, 0x0d9f6e0a, 0x05215984, 0x832d82e5, + 0x01072459, 0x41cd004f, 0x15200641, 0x14205b82, 0xb58a2d92, 0xff4c0123, 0x205b86e0, 0x21b5820f, 0xc7631506, 0x8e00200c, 0x4c0122b5, 0x20b58586, + 0x2059820f, 0x082b8b10, 0x00010033, 0x020000ae, 0x001f06be, 0x40250013, 0x15090915, 0x15101500, 0x13031520, 0x14540047, 0x0106500d, 0x3f001500, + 0x1001e13f, 0x115de1f6, 0x30312f33, 0x050d6133, 0x0a724f18, 0x552dae32, 0x633b4e7c, 0x481f2f26, 0x273a2828, 0x6bb00413, 0x0b595718, 0x824efb21, + 0xcb320865, 0xe90314fe, 0x2b00cb05, 0x2a404a00, 0x29012d30, 0x47011f1f, 0x14121612, 0x0a0a1214, 0x12101200, 0x12401230, 0x13120704, 0x29166000, + 0x50230d29, 0x7c82071c, 0x79001b21, 0xdf450583, 0x2f332107, 0x112f8282, 0x32e11033, 0x315d322f, 0x14110130, 0x4d23020e, 0x11200a96, 0x14065818, + 0x8f021530, 0x4e7b552d, 0x1a1c3d20, 0x3b281f39, 0x58181326, 0xb1880713, 0x4403f624, 0xb4833ffc, 0x9906092d, 0x30130a08, 0xc3034153, 0x8c89444b, + 0x899125c6, 0x00040000, 0xc8080082, 0xaa07dd04, 0x23001600, 0x3e003100, 0x5e400101, 0x29012989, 0x302a2abe, 0x381d3131, 0x1f0d0f83, 0x0d10020d, + 0x0d020d20, 0x6623560d, 0x07230223, 0x69175908, 0x17060217, 0x83321d05, 0x001f000f, 0x0003006f, 0x010ad600, 0x0a470a37, 0x0ac70a57, 0x03d90a04, + 0x48033801, 0xc8035803, 0x1d030403, 0x1005091d, 0x04800104, 0x04d00490, 0xffb80403, 0x061840c0, 0x1004480a, 0x0f400404, 0x2f401f40, 0x9f408f40, + 0x0640df40, 0xb8090807, 0x3140f0ff, 0x235f0709, 0x0e0a201d, 0x030a1d48, 0x0135193c, 0x10128c35, 0x128f013c, 0x600212ef, 0x31100112, 0x23023120, + 0x3131123c, 0x04233c12, 0x04092904, 0x333f0012, 0x3917122f, 0x2000822f, 0x2800825d, 0x115de110, 0x2b333333, 0xb86f1810, 0x3912260e, 0x5d332f3d, + 0x2802835d, 0xe15d2f18, 0x39391211, 0x3a03835d, 0x715d2f33, 0x2f3311e1, 0xed2f3333, 0x0130315d, 0x01070614, 0x03210323, 0x62260123, 0x1e2c0653, + 0x2e030302, 0x030e2703, 0x3e130307, 0x0807ce79, 0x26341326, 0x15062223, 0x33171614, 0x50033632, 0xfc01333c, 0xd3fd9abe, 0xf801bc9c, 0x3b203a33, + 0x54313252, 0x940c233e, 0x0afb6f18, 0x30158523, 0x08ff792f, 0x3fbc7008, 0x333f3132, 0x3f320c31, 0x60469c05, 0x0123fb19, 0x0479fe87, 0x466019db, + 0x1d384f33, 0xfc4f371d, 0x107d015f, 0x1c3b362e, 0x2e363c1c, 0x0483fe0f, 0x413d188b, 0x16101c40, 0x16424741, 0x3c34f6fe, 0x3b33343c, 0x05003c03, + 0xecff5e00, 0xaa079c03, 0x31000d00, 0x54004000, 0x9c006000, 0x83552340, 0x411f410f, 0x4103412f, 0x4b835b41, 0x824b0d06, 0x1a500801, 0x47370f1e, + 0x3f625531, 0x483e0162, 0xffb8281a, 0x0d3a40d0, 0x10284811, 0x28480c09, 0x61561a28, 0x50508c58, 0x700d600d, 0x0d0d030d, 0x5e055050, 0x5046408c, + 0x46460246, 0x2b502427, 0x1e1e5238, 0x5032102b, 0x0e16150f, 0x01050f15, 0x5d2f0005, 0x0a8d5e18, 0x5d2f3326, 0x2f3911e1, 0x10210682, 0x059c69e1, + 0x2b059d69, 0x113232e1, 0x2f2f3939, 0xe110cd10, 0xe1231c82, 0x41013031, 0x01200842, 0x29af5e18, 0x18140121, 0x200d3a55, 0x077d4107, 0x36323324, + 0x5841c701, 0x23522508, 0x25520178, 0x27d95e18, 0x2386013c, 0x3231543d, 0x21213b52, 0x3032523b, 0x75233e54, 0x3f32313f, 0x3f313839, 0x6d41b806, + 0x5cf9220a, 0x035f1898, 0x08052929, 0x1d385133, 0x334f381d, 0x2406c841, 0x3c3c3534, 0x2d038235, 0xfeffffff, 0x56060000, 0x26027307, 0xab458800, + 0x25022105, 0x2905934c, 0x02260520, 0xb44801b8, 0x1f5b1a14, 0xff5e260c, 0x064406ec, 0x202f8221, 0x212f85a8, 0x53457501, 0x5d032905, 0x71032611, + 0x1c005751, 0x220a9546, 0x72b4ff7d, 0x9a20060b, 0x02202d86, 0x28055345, 0x26053e03, 0x38325803, 0x0b235611, 0xb4ff7324, 0x5b842f04, 0x0946ba20, + 0x05416705, 0x823a0321, 0x2e4c2359, 0xbd4c0d34, 0xfe68220b, 0x0a374c3b, 0x39020622, 0x2107674b, 0xe74cb4da, 0xffff2307, 0x25825a00, 0x8209354c, + 0x4bbb2025, 0xe12106b5, 0x08e14cb4, 0x01016b08, 0x03d90402, 0x0021069a, 0x40250014, 0x040e0f11, 0x08c00004, 0x00800e04, 0x085f080f, 0x2f000802, + 0xcc1a335d, 0x1a2f0132, 0x2f3d39cc, 0x30313333, 0x26262301, 0x07060627, 0x033e3523, 0x031e3337, 0x799a0317, 0x36346c33, 0x1a79336a, 0x103b4344, + 0x433b10c0, 0xd9041945, 0x37376122, 0x1d1b2261, 0x2251514c, 0x4c515122, 0x6b8e001d, 0x10050630, 0x0bc00010, 0x10800d13, 0x065f060f, 0x6b840602, + 0x6b8ccd20, 0x07030e33, 0x27032e23, 0x16163335, 0x37363617, 0x199a0333, 0x2b638645, 0x33791a44, 0x6c34366a, 0x06067933, 0x50236482, 0x82502323, + 0x221b2664, 0x61383861, 0x206b8222, 0x32d7821b, 0x006f055a, 0x40150003, 0x0000010a, 0x5f030f8f, 0x82030203, 0x7ee12064, 0x212b0508, 0x1b012115, + 0xc1fd3f02, 0x82966f05, 0x8221202f, 0x057b2d2f, 0x001500ee, 0x151c402f, 0x0100ff83, 0x83339c82, 0x0a7f000a, 0x0a9f0a8f, 0x10800a03, 0x5f050f8f, + 0x83050205, 0xcd1a2241, 0x27a7825d, 0x5ddc1ae1, 0x013031e1, 0x0805ba6c, 0x1e332731, 0x3e323303, 0x7b033702, 0x6d4d2c04, 0x496d4947, 0x046c0327, + 0x2c43301c, 0x22334124, 0x3dee0504, 0x27294a65, 0x2b3f6649, 0x09071932, 0x8228311b, 0x05a03c62, 0x05750100, 0x000d00e5, 0x0810401c, 0x91030087, + 0x0bcf0b9f, 0x30030bef, 0x820b010b, 0xe55d2369, 0x62822f01, 0x46181320, 0xa0200bcc, 0x09505b18, 0x3c73052f, 0x2b1c0d36, 0x38393a1e, 0x01020000, + 0x08c3826d, 0x87063131, 0x1f001300, 0x2d404000, 0x000f8314, 0x004f003f, 0x0004005f, 0x0a30831a, 0x8c170a01, 0x0f1f0f0f, 0x0f4f0f3f, 0x0faf0f5f, + 0x06070fff, 0x898c1d0f, 0x5ed428d6, 0x2f01e15d, 0x84d4e15d, 0x1ae243d6, 0x43310321, 0x202106a9, 0x0fa94320, 0x43b20521, 0xed82166f, 0x42fe1f39, + 0x00005e01, 0x16001400, 0x80060940, 0x120d8400, 0x000a8e03, 0x822fe12f, 0x1a3908e5, 0x173031cc, 0x32331614, 0x06153736, 0x26222306, 0x023e3435, + 0xb4063337, 0x2d192234, 0x1d401a0e, 0x2f1e6464, 0x8b811a38, 0x052b2dee, 0x08087104, 0x4b2a5a68, 0x85133440, 0x06594200, 0x05d12808, 0x001b00e3, + 0x0f234038, 0x02172f17, 0x20090017, 0x09070209, 0x0e8f0516, 0x48131040, 0x0b07400e, 0x130e0e48, 0x820f098f, 0x2f003489, 0x33e1325d, 0xe12b2b2f, + 0x5e2f0133, 0x315dcc5d, 0x51220130, 0x232005c2, 0x83051367, 0x0e333b87, 0x28fe0203, 0x20464c4f, 0x680e302d, 0x4a352105, 0x4c512a2e, 0x2e2d1d45, + 0x0d83690f, 0xdb042008, 0x35232b23, 0x45623c3e, 0x232a2325, 0x613c3e34, 0x00002645, 0x04df0002, 0x06be03d9, 0x820d0021, 0x402d2d8f, 0x0e0e1419, + 0x00504007, 0x4f003f01, 0x13241c82, 0x1b809205, 0x08964018, 0xed1a332e, 0x5d2f0132, 0x39cd1a5d, 0x3031cd2f, 0x2009cf46, 0x08964525, 0x2f16df30, + 0xc7102a2f, 0x514d3f10, 0x6b016523, 0x0d823015, 0x0d84c620, 0x40186420, 0x6b430cb5, 0xc1401805, 0xf8012108, 0x04208582, 0x272c8584, 0x10051640, + 0x0548110c, 0x000c4006, 0x8182fd82, 0x1a218088, 0x247e82ed, 0x32cd1a33, 0x0c0a462b, 0x0af82308, 0x04101314, 0x2d2106c7, 0x046c1834, 0x514d1ef4, + 0x18152150, 0x2056574e, 0x14010300, 0x89030c05, 0xdf84b406, 0x6600292b, 0x841c1940, 0x241f240f, 0x37048302, 0x240324cf, 0x480c0940, 0x160d2424, + 0xffb80e84, 0x092740c0, 0x0e0e480d, 0x0c3b8086, 0x0c92050d, 0x91111f0c, 0x0119ff27, 0x19b01960, 0x0f0319d0, 0x02191f19, 0x4f001906, 0xe5230561, + 0x822f3932, 0x82332093, 0x2f332491, 0x8211e12b, 0x715d2104, 0x200ca746, 0x0b0d4327, 0x0de74918, 0x190bfe39, 0xcf081618, 0x3d383012, 0x38ea5220, + 0x1a231329, 0x29263a10, 0x18b50138, 0x320af649, 0x4f4b1e87, 0x20142451, 0x2551504d, 0x0c303606, 0x181b2619, 0x250c044a, 0xe9ffffff, 0xad670000, + 0xfd54350c, 0x0097fff1, 0x1a02b618, 0x22300203, 0xe9ffb801, 0x042222b4, 0x18082b5b, 0x82732141, 0x82e720a5, 0x054d30a5, 0x002700b8, 0x008f0028, + 0x01070100, 0x82effd54, 0x2e2a08a7, 0x031101b4, 0xffb81201, 0x0f08b2c0, 0x9dffb848, 0x12120f40, 0x00250202, 0xbf1b6700, 0x1b0f011b, 0x5d5d0101, + 0x0134fe10, 0xe95b2b2b, 0x82ff2005, 0x50052149, 0x26234982, 0x897b2b00, 0x8a312047, 0x82112047, 0x40b12647, 0x06121212, 0x29478206, 0x011b6f65, + 0x10011b2f, 0x0482011b, 0x5d5d5d24, 0x4a8534fe, 0x95850020, 0x84600321, 0x002c2295, 0x22958afc, 0x83164066, 0x12c03696, 0x0112a001, 0x20011230, + 0x12100112, 0x01120001, 0x40a5ffb8, 0x3c58852f, 0xd00100f0, 0x00c00100, 0x0100af01, 0x60010070, 0x00500100, 0x01004001, 0x0001003f, 0x286c8220, + 0x48070740, 0x0907401b, 0x21ba8248, 0x7882115d, 0x35200285, 0x5c059e59, 0xff2c06b7, 0x05ecffe7, 0x00cd05c3, 0x52320026, 0x2408cd89, 0x02304047, + 0xa002032d, 0x2e80012e, 0x012e7001, 0x20012e50, 0x2e10012e, 0x012e0001, 0x0a2e2e24, 0x0001250a, 0x2a708450, 0x37bf6700, 0x01370f01, 0x82100137, + 0x5d5d23da, 0x5f863434, 0xe3866084, 0x84540521, 0x013c22e3, 0x2fe38a1d, 0x0e01b44b, 0xb80f0103, 0x16b6c0ff, 0x0fa04817, 0x25080a84, 0x481109b2, + 0x40d6ffb8, 0x070f0f1c, 0xc0002507, 0x05b00105, 0x01057f01, 0x05010520, 0x2f01183f, 0x180f0118, 0xc9820101, 0x3528d084, 0x2b5d2b2b, 0x353f0035, + 0x06216786, 0x22c98300, 0x895a7601, 0x403539c9, 0x03350123, 0x01362001, 0x00013610, 0x36160136, 0x25131336, 0x011d5000, 0x1d280282, 0x013fbf67, + 0x3f013f0f, 0xbb83bc87, 0xe42a4f87, 0x7702ecff, 0x2602b406, 0xb5848601, 0xd0fe5535, 0x18000000, 0x02030f40, 0x0124c001, 0x20012440, 0x6a153a24, + 0x35230687, 0x82ffff35, 0x0509431d, 0x24000623, 0x07715600, 0xb6058726, 0x25000602, 0x3c081b82, 0x00c70001, 0x05be0300, 0x000500b6, 0xc40a4043, + 0x0200f400, 0x020100b0, 0xc0ffb800, 0x13081f40, 0x07000048, 0x072f070f, 0x076f074f, 0x11400704, 0x5a034818, 0x02066404, 0x0303055f, 0x07f84d12, + 0x115d2b3a, 0x5f2b2f33, 0x30315d5d, 0x11211501, 0xbe031123, 0x05bac3fd, 0xf0faa6b6, 0x00215882, 0x21698302, 0x63846804, 0x58000e30, 0x04051140, + 0x0b020606, 0x7001605b, 0x6f18b001, 0x2608080c, 0x480a0627, 0x2f100101, 0x6f105f10, 0x9f107f10, 0x0610bf10, 0x09064010, 0x025b0a48, 0x110a2006, + 0x03040648, 0x82025f0a, 0x3fe12674, 0x2f012b33, 0x227585e1, 0x4812e15d, 0x2e0806d8, 0x35211525, 0x06073301, 0x21030706, 0x04262603, 0x01bdfb68, + 0x115ebbc2, 0x02fe1d2a, 0x2e1ffcae, 0x05857d7d, 0xa84acd31, 0x020afd5b, 0x41a861f0, 0xfb83060b, 0x00060224, 0x0f830028, 0x00005226, 0xb605fe03, + 0x3d200f82, 0x20082b41, 0x210f84d5, 0x1a82002b, 0x2205c35a, 0x7000cd05, 0x2208056b, 0x00344053, 0x0e010001, 0x67045b22, 0x012dd02d, 0x80012dcf, + 0x2d3f012d, 0x18022d6f, 0x2c660e5b, 0x7d0f6003, 0x042b0614, 0x1d000008, 0x04135f27, 0x18095f1d, 0x27083979, 0x01e15d5e, 0x5de1f610, 0x06820082, + 0x3939122b, 0x30312f2f, 0x21152101, 0x055c7a25, 0x597a2620, 0x18162009, 0x28105c8a, 0x1602ec01, 0x8503eafd, 0xc4741851, 0x39032620, 0xfea945a1, + 0xc67418ea, 0x0749631f, 0x2c20ed84, 0xa220fd88, 0x2e200f84, 0x0120fd82, 0x003a0382, 0xb6058b04, 0x5f000c00, 0x0e2f1c40, 0x0eff0eef, 0x12400e03, + 0x400e4815, 0x0482100d, 0x09064c08, 0x050b0c48, 0xb80a0905, 0x2240f0ff, 0x002f010a, 0x005f004f, 0x00af009f, 0x00ef00cf, 0x01001007, 0x05001000, + 0x480e0a20, 0x0a030b05, 0x3f001200, 0x2b333f32, 0x5d382f01, 0x382f325d, 0x2f3d3933, 0x2b2b3333, 0x30315d2b, 0x4a012321, 0x013e05a4, 0x04330123, + 0xdbfec68b, 0x110f2e1f, 0xd9fe1d2a, 0xbbe701c5, 0xa8619a03, 0x5ba84b4b, 0x8c8260fc, 0x00ffff27, 0x060000c7, 0x20a7842f, 0x21b78730, 0x0f840e05, + 0xb3823120, 0x52000326, 0xee030000, 0x032e2a82, 0x0b000700, 0x3e406300, 0x1b010014, 0x8e820101, 0x0b012408, 0x08000606, 0x0108c001, 0x0801083f, + 0x6f0d4f0d, 0x0d30020d, 0x70070701, 0x020b800b, 0x0b010b4f, 0x820f5f03, 0x08022dbf, 0x0b040000, 0x07120a5f, 0x0003045f, 0x4906cf7e, 0x5d2f056b, + 0x5d5d2f33, 0x5d5dce10, 0x112f3271, 0x822f3939, 0x3031260d, 0x21152113, 0x3c038203, 0x35211501, 0xfda602cd, 0x4a03525a, 0x7303b6fc, 0x4e0364fc, + 0xa40a03a2, 0xa4a492fb, 0x07135d00, 0x02cd0525, 0x82320006, 0x830120a9, 0xc10421c9, 0x2008a982, 0x40310007, 0x005a011e, 0x09b00965, 0x9f096f01, + 0x0309af09, 0x04010910, 0x0864055a, 0x03065f03, 0x053c4105, 0x25073f42, 0x31e1f610, 0x53672130, 0x04212b05, 0x7bfdbbc1, 0x05fa03ba, 0xf483fa12, + 0x23051f41, 0xb6053304, 0x33206582, 0x4e206584, 0x1220cc82, 0x3a086582, 0x405a000b, 0x065b080d, 0x48171420, 0x06020602, 0xffb80a01, 0x062640c0, + 0x0a0a4815, 0x2f0d0f0d, 0x8f0d6f0d, 0x0706040d, 0x2f035b09, 0x02013f01, 0x02020801, 0x045f0709, 0x835f0903, 0x3fe1217f, 0x24057a43, 0x5d2f1801, + 0x06a16333, 0x39122b26, 0x2b2f2f39, 0x24088e82, 0x01013533, 0x21152135, 0x15210101, 0xfe9e014e, 0xfd7d036e, 0xfe850158, 0x98f70267, 0x25026602, + 0xeefda493, 0x050541fd, 0x8f851420, 0x37229f82, 0xb1440000, 0x84372006, 0x823c20af, 0x035b08af, 0xecff6800, 0xcb05ba05, 0x2e002100, 0x81003b00, + 0x02225040, 0x11011167, 0x9a213b5a, 0x12870112, 0x01127a01, 0x281b1212, 0x3d67085b, 0x00013d2f, 0x3dd0013d, 0xbf3daf01, 0x3d90023d, 0x013d5f01, + 0x0f013d30, 0x023d1f3d, 0x1b5b3506, 0x3b223c66, 0x13101360, 0x21602f2e, 0x82132102, 0x13112601, 0x3f000400, 0x24b6833f, 0xe1103311, 0x24048432, + 0xe1f61001, 0x0599465e, 0x82717121, 0x3911220b, 0x280d822f, 0x5de13333, 0x30313232, 0x052a7c01, 0x0e141535, 0x15232304, 0x22233523, 0x3435042e, + 0x3333023e, 0x7b323313, 0x2b270574, 0x020e2203, 0x821e1415, 0x025c0813, 0x8649bbb4, 0x183c7ec2, 0x9f785434, 0x2fbb2f65, 0x54789f65, 0x7e3d1835, + 0xbb4a85c2, 0x5b8b5d1a, 0x7f53292e, 0x39bb3957, 0x28547f57, 0x5d8b5b2e, 0xb4cb051a, 0x66c4995e, 0x6e7b813d, 0xe1e13052, 0x7b6e5230, 0xc4663d81, + 0x53fc5e99, 0x5894693b, 0x3c688b4e, 0x4e8b683c, 0x3b699458, 0x08062d41, 0xb6056064, 0x3b000602, 0x01000000, 0x00006800, 0xb605ba05, 0x70002500, + 0x671f4740, 0x5a090109, 0x010a9a1c, 0x7a010a87, 0x0a0a010a, 0x005b2313, 0x272f2767, 0x01270001, 0xaf0127d0, 0x0227bf27, 0x5f012790, 0x27300127, + 0x1f270f01, 0x16060227, 0x2666135b, 0x08601c1f, 0x24090b0b, 0x0903141d, 0x3f3f0012, 0x9f583333, 0x151a4106, 0x325de12b, 0x14013031, 0x2323040e, + 0x2b018211, 0x35042e22, 0x14113311, 0x3333021e, 0x33220782, 0x0e823632, 0x41ba0521, 0xc1200e03, 0x2608ee84, 0xb7ba1abb, 0x3dd703c0, 0x4e6a777f, + 0x0142fe2e, 0x684e2dbe, 0x013d7e77, 0x5821fee3, 0x0334628d, 0xc6a6fc5a, 0x83e301b1, 0x824e20db, 0xa64908db, 0x2f00cd05, 0x51407c00, 0x220b5b0e, + 0x0b20255b, 0x04020b30, 0x252f010b, 0x25df253f, 0x0b0425ef, 0x0b070125, 0x13250b25, 0x23065b2b, 0x23022316, 0xd031671d, 0x31cf0131, 0x01318001, + 0x316f313f, 0x190d0902, 0x0d08020d, 0x2be68205, 0x185f0030, 0x0a222604, 0x0c255f0d, 0x3324e582, 0x323232e1, 0x2005cc54, 0x05ff4133, 0x32f61029, + 0x3911e15d, 0x842f2f39, 0xe110210f, 0x0be75318, 0x2115172a, 0x032e2135, 0x023e3435, 0x085f8518, 0x13822120, 0x12823e20, 0x022e5808, 0xa472fa02, + 0x5123326a, 0xb0fd5f83, 0x6f406201, 0xa0512e50, 0xeb9b9aec, 0x502e51a0, 0x6201416e, 0x835fb0fd, 0x6a322351, 0x442905a4, 0x6475ba81, 0x4197abbb, + 0x8730a493, 0x966fc7a8, 0x5e5eacf4, 0x6f96f4ac, 0x3087a8c7, 0x974193a4, 0x7564bbab, 0x004481ba, 0x1800ffff, 0x572ec943, 0x20083403, 0x04ecff71, + 0x02210691, 0x007e0126, 0x01060100, 0x00001954, 0x020b4013, 0x0226114a, 0x16443e16, 0x0a25512f, 0xecff5a24, 0x2b845c03, 0x2b858220, 0x2b84ca20, + 0x11460129, 0x3a6d0126, 0x8a2d1840, 0xfeae222b, 0x05916414, 0x85840121, 0x8544202b, 0x8225202b, 0x6462202b, 0xa4240e91, 0x7702ecff, 0xe9485784, + 0xfe542205, 0x053f5ece, 0x2c822220, 0xfdffb826, 0x152216b4, 0x820b5351, 0x3d04232f, 0xb382b406, 0x5b849220, 0x00105530, 0x03b21200, 0xffb80102, + 0x422cb4ee, 0x87831b05, 0x00353524, 0xdd840002, 0x5e042908, 0x3d001000, 0x1e403800, 0x47051e38, 0x103f282f, 0x480e013f, 0x223e5616, 0x500b1e0f, + 0x2f380f1b, 0x3350002c, 0x3f001611, 0x20061442, 0x06697133, 0xe132d424, 0x67183232, 0x162a1a1f, 0x36363317, 0x030e3337, 0x0c4f1115, 0x022e250a, + 0x030e2327, 0x122a6718, 0x713d2f08, 0x907064a2, 0x210a0c31, 0x130b8f19, 0x2232080d, 0x0f08250e, 0x3f262241, 0x0c0c2432, 0x604d3b16, 0x98622f83, + 0x9d650f68, 0xccda376b, 0x6718cdd1, 0x533a0836, 0x1f522355, 0x7e796821, 0x3c5dfe37, 0x85030733, 0x27101109, 0x3d223040, 0x5d761a2e, 0x06752406, + 0x821b001f, 0x594308e3, 0x48393440, 0x1f050805, 0x02332f33, 0x05330533, 0x0c472c15, 0x3f203f57, 0x22023f30, 0x54164715, 0x081b153e, 0x330f5032, + 0x33330801, 0x50272200, 0x501c1611, 0x3f000100, 0x32e13fe1, 0x5e2f3911, 0x8439e15d, 0x062b6dfc, 0x2f2f3934, 0x1039125d, 0x013031e1, 0x15021e32, + 0x15070614, 0x82761616, 0x27262d05, 0x34112311, 0x2217023e, 0x1115020e, 0x25054f51, 0x022e3435, 0x91182323, 0x6608081f, 0xa3607702, 0x8f984376, + 0x783fb9b0, 0xa4606dad, 0x7945b63c, 0x643863a8, 0x4e202c4b, 0x50245252, 0x351f466f, 0x664f8460, 0x4e77524d, 0x5f442625, 0x62311f06, 0xad956294, + 0xca150617, 0x6da26cba, 0xfd1f2037, 0x7b3406e9, 0x963773b2, 0x607f4c1f, 0x1e1292fc, 0x4d280b15, 0x7550476f, 0x2898254d, 0x3f3d6649, 0x181f3e5e, + 0x080a7f62, 0x63001b34, 0x401d1640, 0x50481512, 0x1d0f011d, 0x1d4f1d2f, 0x051a0703, 0x06480501, 0x40f0ffb8, 0x0b060615, 0x0c131300, 0x201b001a, + 0x031b401b, 0x1b101b08, 0x19830c0d, 0x1a0c0a3a, 0x00130f0c, 0x1b05150b, 0x333f3f00, 0x01333f33, 0x2f33382f, 0x335d5e38, 0x3005744a, 0x382f1833, + 0x5d5e5de1, 0x30312b5d, 0x15030e25, 0x20fa8223, 0xa9651837, 0x0237080b, 0x18221660, 0x1b0fbe0c, 0x60fe1525, 0x1e0ed9bd, 0x0604141a, 0x1b191405, + 0x12bcc70b, 0x7e86883e, 0x89792a34, 0x3e043f8d, 0x5d28bafd, 0x1a1b505a, 0x215a5d52, 0x7d004c02, 0x4408080b, 0x0032001f, 0x40510044, 0x00461a2e, + 0x2e050538, 0x240f4833, 0x46404657, 0x46e046d0, 0x01460f03, 0x2e483d06, 0x24004556, 0x380a1a42, 0x50420a38, 0x50151629, 0x00010a10, 0x3fe1333f, + 0x2f3911e1, 0x39123912, 0x06ce4633, 0x32f61022, 0x39251283, 0x3031e139, 0x09b64401, 0x2e071722, 0x08a08318, 0x181e1721, 0x240c0d8f, 0x022e3401, + 0x4b4c1827, 0x02c20808, 0x435d3814, 0x7d5c3325, 0x6071444a, 0x204a2351, 0x335b5149, 0x12273c2a, 0x47623c1b, 0x315c8655, 0x6db27f45, 0x477fae67, + 0x01997243, 0x52391eb4, 0x687e3a35, 0x69492644, 0x03998e43, 0x564b20aa, 0x69483962, 0x1f142246, 0x14911327, 0x17121e26, 0x251b3225, 0x29413d3e, + 0x937e6c31, 0x83c17f58, 0xaa753d43, 0x7aa36a6e, 0x4551fe53, 0x1f49596f, 0x91623a10, 0x516f4267, 0x0100b42d, 0xecff5a00, 0x5e045c03, 0x59003900, + 0x231d3740, 0x10180101, 0xa03b572d, 0xc03bb03b, 0x3b3f033b, 0x10023b5f, 0x4634013b, 0x47052323, 0x1e3a5618, 0x39bf5002, 0x89397901, 0x39390239, + 0x2850310a, 0x13500a10, 0x2e5a0016, 0x5d5d2d06, 0x100139e1, 0x2f33e1f6, 0x5d5d5de1, 0x2c052765, 0x30313912, 0x22231501, 0x1e141506, 0xf7891802, + 0x022e2709, 0x023e3435, 0x2f413537, 0x5826200b, 0x268205a9, 0x9c025f08, 0x29858a81, 0x33376046, 0x1f47515c, 0x716d9e3b, 0x26356ca6, 0x2b2c523f, + 0x3a1c3346, 0x35569069, 0x284d525a, 0x47814b3f, 0x4827736c, 0x87023d64, 0x335e5b99, 0x0f122a45, 0xa0101f18, 0x56312922, 0x583e4375, 0x0b0f293e, + 0x503e2b0e, 0x4a6d4632, 0x1c130926, 0x26229314, 0x402d4d4d, 0xf7821227, 0xfe712b08, 0x066a036f, 0x00330014, 0x2e1f4039, 0x461f0303, 0x0114201a, + 0x35103514, 0x0a0235c0, 0x00002948, 0x19345629, 0x5000032e, 0xdf820001, 0x2f323223, 0x27d08201, 0x5de1102f, 0x325dd610, 0x3320e282, 0x2105b47c, + 0x4418050e, 0x07210a23, 0x05a34623, 0xd6832720, 0x36126608, 0x07063736, 0xae230606, 0xb880b602, 0x0d284c7e, 0x4b78542d, 0x193a5f47, 0x162b2215, + 0x222b18aa, 0x5b300e14, 0x5c87594d, 0xc99a5c2e, 0x282f2b6c, 0x7b052f60, 0xcd768d99, 0x6f859ab3, 0x406c5930, 0x2e0f1123, 0x2d2a483b, 0x1f4b5258, + 0x43484820, 0x2225141d, 0x42110f1f, 0x9466986c, 0xd9e80101, 0x0203036c, 0x93531804, 0x005e2808, 0x40310018, 0x1847001d, 0x2c0f696e, 0x1450040e, + 0x0b0f0c10, 0x001b0015, 0x0daf683f, 0x01303122, 0x0b967118, 0x3e331729, 0x16323303, 0x18031115, 0x68079571, 0xfe230993, 0x68af0414, 0xfb221086, + 0x89660047, 0x04210805, 0x002b0617, 0x001e0013, 0x405b0027, 0x4719253a, 0x0f295700, 0x29d00129, 0x9f297f01, 0x29400229, 0x080d8201, 0x1a240621, + 0x28560a47, 0x24cb501a, 0x0124ba01, 0x24992489, 0x01240f02, 0x14242408, 0x010f501f, 0x42055014, 0x5e21084a, 0x2100825d, 0xa36e01e1, 0x200a8205, + 0x3b541871, 0x06022107, 0x080c6e67, 0x12161698, 0x023e3201, 0x031e2137, 0x020e2213, 0x02022107, 0x70341704, 0xaf767eb3, 0x6f333874, 0xb0767eb1, + 0x2bfe3a75, 0x23456849, 0x02cbfd03, 0x4a684421, 0x23446647, 0x09330205, 0xbc0c0384, 0x6dced7fe, 0x2901ce6d, 0x2901bcbc, 0xcd6b6cce, 0xb9fcd7fe, + 0x95df944a, 0x4b95df93, 0x89451005, 0x110189cd, 0x00001301, 0xffa40001, 0x047702ec, 0x00150048, 0x30234035, 0x09090109, 0x10170017, 0x60172017, + 0x90177017, 0xd017c017, 0x01080817, 0x16541447, 0x160f5004, 0xc44f0f00, 0x5d5e2407, 0x5d2f3311, 0x16200534, 0x5705fe42, 0x35390516, 0x3f5a0111, + 0x2a2d1248, 0x290d0924, 0x3e183430, 0x042c4d6a, 0x61fcfc48, 0xa86b1862, 0x0403300c, 0xae00ffff, 0xf0030000, 0x06024a04, 0x8200fa00, 0xf2ff368b, + 0x1704ecff, 0x2e002106, 0x2a406800, 0x1a151522, 0x29011212, 0x0801820a, 0x1a500030, 0x441a3401, 0x1a00021a, 0x1a201a10, 0x301a1a03, 0x30903060, + 0x01300f02, 0xb8002e06, 0x0f40f0ff, 0x29152e00, 0x170e0101, 0x07161e50, 0x8d460e50, 0x39112405, 0x183f332f, 0x08092e6a, 0x5d5d5d26, 0x3d393912, + 0x112f182f, 0x12113333, 0x31331139, 0x27012330, 0x2223032e, 0x36350706, 0x1e323336, 0x16011702, 0x9256ce82, 0x2e630806, 0x2e032702, 0x06232703, + 0x0e030706, 0x0d35b801, 0x2b3d2b1f, 0x1a143222, 0x694a2342, 0x011f3f4f, 0x262e1248, 0x1708260e, 0x3b272537, 0x870f252f, 0x161b1d0b, 0x350d0605, + 0x3304e51f, 0x314329a0, 0x9105071b, 0x592a0a07, 0x36fc5d87, 0x03073936, 0x110e0c85, 0x012e4028, 0x615e21a2, 0xaa4d1957, 0x82c1fd4f, 0x7b5618f7, + 0x403f250a, 0x090c0d26, 0x0f7c5618, 0x471a002b, 0x1a1e541b, 0x030d141b, 0x7f561850, 0x4833200c, 0x322b0565, 0xf6105d32, 0x313232e1, 0x18140130, + 0x084f8356, 0x0000003a, 0x4a04cf03, 0x3b001400, 0x13141640, 0x0d000707, 0x16570e47, 0xb0011610, 0x160f0116, 0x00010601, 0xb6f0ffb8, 0x15140700, + 0x000f000d, 0x333f323f, 0x32382f01, 0x715d5d5e, 0xf7469382, 0x313c0805, 0x13331130, 0x3317031e, 0x3512023e, 0x02021433, 0xbc230706, 0x1e1f0cc9, + 0x5a060519, 0xb6194272, 0x759a5c25, 0xfd4a04c0, 0x676321b0, 0xcd60195c, 0x970501e7, 0xfee0fea3, 0x007ffdf5, 0x320ad344, 0x407e0046, 0x3b3b324e, + 0x41012a11, 0x2d2d3846, 0x65001c24, 0x4b0805c7, 0x1c010108, 0x01112046, 0x483f4811, 0x487f485f, 0x100448ef, 0x48070148, 0x3c475624, 0x39503832, + 0x1c49002a, 0x1c691c59, 0x011c3803, 0x031c2407, 0x004f0116, 0x00391600, 0x3f00fa16, 0x2f39123f, 0x391711e1, 0x39115d5d, 0x3232e110, 0x28056451, + 0xf15dd610, 0x5d5e2fc0, 0x271d8211, 0x3912e133, 0x332f3311, 0x4d05f045, 0xf94605a8, 0x08184506, 0x2105ab5e, 0x07863537, 0x06070629, 0x35232306, + 0x4d231521, 0x032607d8, 0x7f51a223, 0x2a452d57, 0xb2270814, 0x664e2fb8, 0x2d726537, 0x223e6b4f, 0x2e552127, 0x3781023e, 0x47739149, 0x51724620, + 0x31897703, 0x4e417155, 0x45223b60, 0x33081436, 0x4db5c722, 0x1143637f, 0x75861c0c, 0x31496648, 0x02030313, 0x268d9904, 0x354e754e, 0x001c3751, + 0x7100ffff, 0x2d04ecff, 0x06025e04, 0x00005200, 0x19000100, 0x25080f82, 0x004a04c9, 0x40580018, 0x8f470a38, 0x16160116, 0x1414030e, 0x03100300, + 0x1a030302, 0x1a9f1a2f, 0x10031aef, 0xb651470d, 0x15103608, 0x19540e48, 0x50100c15, 0x150e0f12, 0x16075000, 0x3fe13f00, 0x052f413f, 0xe15d2b33, + 0x33115d33, 0x2f335d2f, 0x2f391211, 0x3031e15d, 0x09d65925, 0x21113c08, 0x23112311, 0x15213735, 0x16141123, 0x2f1c5004, 0x304a0f0f, 0x6dfe7171, + 0x0489ddb6, 0x812fd327, 0x0990080d, 0x02828411, 0x0350fcbe, 0x9a504ab0, 0x37464efd, 0x00020000, 0x8314fea4, 0x1a002fb7, 0x39002700, 0x48252140, + 0xcf295700, 0x74450129, 0x091f3006, 0x5410470f, 0x16501b28, 0x221b0f10, 0x82050850, 0x83332092, 0x10012293, 0x209782f6, 0x0528535e, 0x5e303121, + 0x262105bb, 0x08636f27, 0x25067f4d, 0x07062201, 0xd36b1611, 0x04450806, 0xa7753f2d, 0x368f4b68, 0x02020106, 0x7841b601, 0xa36169a9, 0x3bfe4377, + 0x36038289, 0x7b8c4b8f, 0x8927027d, 0x2d4c91d5, 0x272e2b2d, 0xddfe2e61, 0xd3881304, 0x914b4b91, 0xc41801d3, 0x33acfec8, 0xd1d1d331, 0x06ab42cf, + 0x046f4708, 0x0031005e, 0x27364051, 0x10461527, 0x0a100a00, 0x0a030a20, 0x5f333f33, 0xef337f33, 0x33100433, 0x1f480001, 0x2d283256, 0x010a3751, + 0x15381528, 0x15031548, 0x04001f0a, 0x0f10240f, 0x3f3f00fa, 0x5d391712, 0x8b42e15d, 0xe1322309, 0xc9832f33, 0x09086418, 0x240b9147, 0x3233023e, + 0x07974916, 0x1c2d0125, 0x47617e49, 0x4d3b108e, 0x49376284, 0x4e6ab383, 0x17363295, 0x1a3a3c38, 0x22497250, 0x79600602, 0x47162f4e, 0x0f32138d, + 0x82b47641, 0x4995e29a, 0x0a9a1922, 0x39090f13, 0x0b4da470, 0x85280806, 0x16004a04, 0x36002900, 0x21242140, 0x00101248, 0x2b102b57, 0x2ba02b90, + 0x2be02bb0, 0x0a481705, 0x25122a56, 0x1c0f0f50, 0x8507f646, 0xf61023c6, 0x47183232, 0x21251033, 0x031e2115, 0x06414905, 0x34355908, 0x22232726, + 0x2d04020e, 0x75b47a3e, 0x447daf6b, 0x80ce904d, 0xf6fee901, 0x1c304125, 0x472100fd, 0x6d4c4d6e, 0x4b4f2147, 0x5a8b5f3b, 0x6ff8012b, 0x46508dc0, + 0x9c85cb8a, 0x9a3e8ada, 0x7c6c5d29, 0x69905536, 0x8662373b, 0x59d7904e, 0x00a1632c, 0x12000100, 0x6603e5ff, 0x2508b182, 0x403a001c, 0x0d0f0124, + 0x06020d1f, 0x101e570d, 0x1a2b011e, 0x1a021a3b, 0x18104703, 0x180218e0, 0x1c501902, 0xf449080f, 0x01322c07, 0xc6e15d2f, 0xe6105d5d, 0x56325d5e, + 0xe64905a6, 0x07e74608, 0x35213508, 0xfe660337, 0x3e2d198c, 0x282a1224, 0x270d0d24, 0x401b352e, 0xfe345975, 0x4a0486d7, 0x3ba2fd9a, 0x03173352, + 0x87040706, 0x060b0c06, 0x68864d1d, 0x504a7302, 0xa4249383, 0x3d04ecff, 0x26089382, 0x4029001d, 0x1b471018, 0x1f101f57, 0x1f801f60, 0x05470803, + 0x06151e54, 0x00500d0f, 0xe13f0016, 0x1001333f, 0x825de1f6, 0x30312503, 0x022e2205, 0x08072351, 0x35363259, 0x27022e34, 0x15031e33, 0x5c020210, + 0x2964aa81, 0x664220b6, 0x098d9246, 0xb60f1710, 0x0810180f, 0x8c5014f4, 0x58026dbd, 0x8c56b2fd, 0xf7e83663, 0x74757d47, 0x77723d3d, 0xc1fe4b81, + 0x0200d3fe, 0x14fe7100, 0x5e042505, 0x35002500, 0x3c405e00, 0x16472531, 0x82a60096, 0x06003718, 0x571f4826, 0x01372037, 0xe001370f, 0x376f0137, + 0x379f377f, 0x0f834003, 0x02371f3b, 0x06471106, 0x502b3656, 0x31101a0b, 0x01245016, 0x001b0016, 0xe1333f3f, 0x53038232, 0x05530807, 0x23178208, + 0x11013031, 0x21050d4b, 0x1b4c1737, 0x11172305, 0x00513634, 0x01112108, 0x08694e18, 0x033ea208, 0xb76d6602, 0x38204b86, 0x258d2d4e, 0x33192d3f, + 0xa5407458, 0x66925a91, 0xbe905637, 0x1e4f0168, 0x1b2b4936, 0x48162531, 0xfe33597b, 0x05da0114, 0x97d58943, 0x7d8a9853, 0x68336037, 0x6f477d72, + 0x07306199, 0xc1bc5e02, 0x7ac99050, 0x4a90d995, 0x0426fe05, 0x65946225, 0x57351733, 0x07a0fd41, 0x009f6b3b, 0xecff0100, 0x250414fe, 0x28004e04, + 0x1a40a000, 0x1f781f68, 0x09671f02, 0x09c70977, 0x76060903, 0x1c37011c, 0x1e1c1c01, 0xffb80807, 0x130e40c0, 0x08344816, 0x08100801, 0x0112c008, + 0x08128312, 0x0b06193d, 0x2a121248, 0x2a3f2a0f, 0x2acf2a4f, 0x25b00604, 0x250225c0, 0xb81e1d25, 0x1f40f0ff, 0x1e291e1e, 0x2706171b, 0x1c180206, + 0x1c021c28, 0x04061f09, 0x16500f00, 0x230f071b, 0x450f0050, 0x12350536, 0x5d5d3917, 0x3301113f, 0x3333382f, 0x5d5e5d2f, 0x2b2f3311, 0x3b0d825d, + 0x12332b5d, 0x5d2f3d39, 0x5d33335d, 0x30315d33, 0x021e3213, 0x33011317, 0x031e1301, 0x08082a5f, 0x27022ea5, 0x01230103, 0x23262603, 0x36350722, + 0x492dbc36, 0x7b15313a, 0xfeb21f01, 0x1d0eb273, 0x1a253426, 0x3916102e, 0x475f4328, 0xfe831733, 0xc601c2b6, 0x35471ba0, 0x3e161c24, 0x3e1f4e04, + 0xa8fe3d5c, 0xf8fc4a02, 0x422620fe, 0x03051d33, 0x260b068d, 0x01416646, 0x0383fd6a, 0x4fbe013e, 0x078f0a59, 0x0100000a, 0x14fea400, 0x12067105, + 0x4c002700, 0x17012f40, 0x18182647, 0x1147061e, 0x29302957, 0x29902940, 0x29c029b0, 0x1f290f05, 0x21060229, 0x28541e47, 0x010f1f0b, 0x19165026, + 0x001b1716, 0x423f0000, 0x4d4e0615, 0x11e12308, 0x0f422f39, 0x064d4c06, 0x3e4e3320, 0x11072505, 0x032e1123, 0x0806dc42, 0x0311174a, 0x5f834e56, + 0x180f0834, 0x1810b610, 0x93570810, 0x6fb26dc4, 0xb64c89bc, 0x42785a36, 0x73fa1206, 0x9c6c3c09, 0x7e804767, 0x83484983, 0x9d447e7e, 0x07458cdc, + 0xda0126fe, 0xd6884104, 0xfd1f029a, 0x619a72d9, 0x8f05052e, 0x3a08c182, 0x05ecff71, 0x004a0496, 0x4070003b, 0x1d673848, 0xd5471d01, 0x1ab7011a, + 0x011aa901, 0x03011a9a, 0x25051a1a, 0x3d573048, 0x3d143d04, 0xf43dc402, 0x3d7b023d, 0x40023d9b, 0x5602013d, 0x103a0807, 0x3c560548, 0x0a2a1b1b, + 0x5015200f, 0x16003539, 0x32323f00, 0x333f32e1, 0xdb862f39, 0xc84b5f20, 0x21e08206, 0x00825d5f, 0x395de122, 0x2406b043, 0x37023e34, 0x05f54233, + 0x3e323322, 0x4905c043, 0xc04305a1, 0x14270807, 0x2223020e, 0x06232726, 0x5ae90106, 0x0f32608c, 0xba202f1f, 0x0f1f2f20, 0x2d4b361d, 0x162c442e, + 0x2d5163b2, 0x831d364b, 0x83bb2017, 0x32470817, 0x6b5a8d60, 0x1f0a1f8b, 0x9252148b, 0x8f5179cb, 0x49488787, 0x528e8786, 0x34659662, 0x39624829, + 0xcefe3201, 0x65348b81, 0x8e526296, 0x48498687, 0x518f8787, 0x5292cb79, 0x575b5b57, 0x00ffff00, 0x02ecff15, 0x5cd90577, 0x003b0713, 0x00e2fe6a, + 0x40170000, 0x1f01020d, 0x01022611, 0x142a1632, 0x2b012500, 0x83003535, 0x24318203, 0x04ecffa4, 0x2631843d, 0x01000092, 0x826a0006, 0xb619242f, + 0x83270102, 0xffb8252e, 0x321eb4de, 0x87062f53, 0x0fd57431, 0x000e5428, 0x0b401300, 0x31822c02, 0x18203d21, 0x840d1f4c, 0x2106215d, 0x5d848f82, + 0x10540122, 0x01272b84, 0x0126112a, 0x85241e1d, 0x48588259, 0x052106c9, 0x202b8496, 0x24898296, 0x00540107, 0x248b82c3, 0x01094021, 0x302d8248, + 0x3c013c60, 0x40c0ffb8, 0x480b0909, 0x05423c3d, 0x21c58230, 0x46185d2b, 0xc725076d, 0xbe030000, 0x91591807, 0x00690828, 0xff140001, 0x050605ec, + 0x002500b6, 0x045a4085, 0x5a0c1304, 0xdf01210f, 0x0221ff21, 0x0f275521, 0x7f276f27, 0x1a060327, 0xa00118f4, 0x0218b018, 0x18011874, 0x135a1218, + 0x15301500, 0x15501540, 0x150515c0, 0x0113b015, 0x13771367, 0x01135e02, 0x134f133f, 0x01130002, 0x1a5f1113, 0x1519071a, 0x1303165f, 0x005f0712, + 0x05124413, 0x39123227, 0x2f01e12f, 0x2500835d, 0x105d2f33, 0x0b8332e1, 0x5d5e3227, 0x715df610, 0x271c82e1, 0x22053031, 0x16352726, 0x26053f42, + 0x23263435, 0x70231121, 0x4708078b, 0x15021e32, 0x020e1415, 0x462f9e03, 0x27441d19, 0x21334020, 0xbbfe7b69, 0x03acfebb, 0x015efeb1, 0x65925d5a, + 0x845f3535, 0xa00b0d14, 0x33130c09, 0x73854557, 0x0523fd74, 0xfea4a412, 0x8b5e316f, 0x9a698959, 0xffff3165, 0x2505df5d, 0x26027307, 0xc5666101, + 0x33002105, 0x2905c566, 0x26051201, 0x0c063e01, 0x55180004, 0x4a080857, 0xff7d0001, 0x059804ec, 0x002600cb, 0x1113405f, 0x48181340, 0x11071107, + 0x0123ca1b, 0x23802370, 0xffb82302, 0x072440c0, 0x2323480a, 0x0128bf28, 0x1b5b0805, 0x5f082766, 0x05af050f, 0x05050802, 0x5f00240d, 0x5f0d0420, + 0x18131610, 0x240c6964, 0xe1f61001, 0x05124532, 0x215a5d20, 0x30312905, 0x020e2201, 0x21152107, 0x23060645, 0x2223030e, 0x330af15c, 0x26260717, + 0xa05f1903, 0x020d4d78, 0x0586fd74, 0x71ab7640, 0x17609818, 0xaf7a4129, 0xc982a26f, 0x1823488a, 0x73146198, 0x05270759, 0x000602cb, 0x5c000036, + 0x535712e9, 0x48ff2730, 0x73017bfe, 0x5182b605, 0x00002d24, 0x55820200, 0x06e96a08, 0x00b605df, 0x0035002a, 0x2b25b58d, 0x080d065a, 0x40f8ffb8, + 0x48171453, 0x99235a08, 0x101e011e, 0x0600231e, 0x06020690, 0xb40123e0, 0xd423c423, 0x23000323, 0x23902350, 0x070423a0, 0x23062306, 0x005b2f15, + 0x37cf3767, 0x06403701, 0x15154809, 0x0f5f3536, 0x0225af25, 0x2b252508, 0x03235f08, 0x13126019, 0x1206602b, 0x0aea7700, 0x0111e125, 0x792b2f33, + 0x392005d1, 0x2a05a458, 0x33115d5e, 0xe1105d38, 0x4910322b, 0x2127089e, 0x030e2111, 0x6d030e07, 0x372c0a0c, 0x12123636, 0x33112137, 0x01021e32, + 0x07da6518, 0x06237d08, 0xc27e3cdf, 0xfebffe86, 0x211f0fc2, 0x35141022, 0x234e6e4f, 0x3a171c4a, 0x2a3e3020, 0x200c0c1a, 0x02162b27, 0xcf986d93, + 0x77fd377e, 0x2ea4ae77, 0x585d8b5b, 0x9e61ac01, 0x12053d70, 0xd4ecf471, 0x6fa26751, 0x9a0b0e3b, 0x623f100d, 0xc8393675, 0x3a010601, 0x4298fdaa, + 0x9dfe9871, 0x61468884, 0x02001b3c, 0x0000c700, 0xb6050c07, 0x21001600, 0x32405300, 0x0e5a1711, 0x1b0a0606, 0x3108fe82, 0x01230f23, 0x231f230f, + 0x23ff237f, 0x5a090d04, 0x2122640a, 0x0f115f08, 0x020daf0d, 0x0f0d0d08, 0x6017030b, 0x0012060a, 0x3fe1333f, 0x5e2f3933, 0x544b335d, 0x5d322105, + 0x4606a75b, 0x14230590, 0x8223020e, 0x231125f3, 0x21113311, 0xe48d0382, 0x850c0721, 0xb8fd26e4, 0x4802baba, 0x29cd94ba, 0x56fdaa02, 0x98fdb605, + 0xbc8d6802, 0x2105ad74, 0xbd820605, 0x00155008, 0x084d4073, 0x1755075a, 0x176f170f, 0x0603177f, 0xa00114f4, 0x0214b014, 0x14011474, 0x5a0e0014, + 0x3011000f, 0x50114011, 0x0511c011, 0x0fb01111, 0x770f6701, 0x0f5e020f, 0x4f0f3f01, 0x0f00020f, 0x11150f01, 0x5f0d125f, 0x12070000, 0x83070f03, + 0x123f25d6, 0x10e12f39, 0x2f20d482, 0x200a3844, 0x200c8332, 0x05374a5e, 0x32210125, 0x8215021e, 0x0b2f44d9, 0x44230221, 0xba200510, 0x290a2244, + 0x5e318103, 0xf2fd598b, 0x1844f601, 0x050d4407, 0x07a20427, 0x01260273, 0x060d44b4, 0x0d448920, 0x05172606, 0x0b220126, 0x090d4411, 0x19262d82, + 0xae04ecff, 0x2d826907, 0x2d83bd20, 0x00360223, 0x202d8623, 0x232d8227, 0x13222c0d, 0x080b3b44, 0x7ffec727, 0xb605c104, 0x63000b00, 0x02c64140, + 0x020202d6, 0xd503c55a, 0x03a80203, 0x01039601, 0x110e1003, 0x01034748, 0x080a823a, 0x09050328, 0x0d65005a, 0x6f010db0, 0xaf0d9f0d, 0x0d10030d, + 0x055a0801, 0x060a0c64, 0x055f0803, 0x05010202, 0x33332f00, 0x324b102f, 0x425d2007, 0x2f3005e2, 0x5d2b5d5d, 0x5de15d5d, 0x21213031, 0x21112311, + 0x3405df41, 0x5afec104, 0xba5dfeb1, 0xfebb8502, 0x0581017f, 0x05f0fab6, 0x0ffb6210, 0x21057742, 0xa1823304, 0x00103108, 0x404b001b, 0x01085f2e, + 0x15110808, 0x1d67005b, 0x1d5f1d0f, 0x1dcf1d7f, 0x110b0604, 0x1c64065a, 0x0b0f5f1b, 0x08020baf, 0x0a110b0b, 0x1103075f, 0x22077643, 0x612f3912, + 0x322106b7, 0x8292835e, 0x208b820f, 0x066f4201, 0x4e431520, 0x3304330f, 0x86c27e3c, 0x140396fe, 0x9896a6fd, 0xfd377ecf, 0x3443a04e, 0x43812005, + 0xb6230634, 0x433cfea4, 0xa3410b1c, 0x08a16306, 0x0a954118, 0x6101062c, 0x02000000, 0x7ffe0e00, 0xc5820a05, 0xc5821120, 0x408b7308, 0x281b180b, + 0x071b021b, 0x14011437, 0x40f8ffb8, 0x4817140b, 0x0f0e5a14, 0x07070107, 0x40f0ffb8, 0xc00e3010, 0x0e07020e, 0x12050e07, 0x5a01105a, 0xc0ffb800, + 0x15102540, 0x10000048, 0x1d201d65, 0x011d0f01, 0x055a0408, 0x5f141c05, 0x5109030e, 0x06101b08, 0x0500035f, 0x00120305, 0x332f333f, 0x3232e110, + 0xe13fe22f, 0x2f330111, 0x5d5d5ee1, 0xab18e410, 0x56080a14, 0x5d5e385d, 0x5d2be110, 0x315d3311, 0x11230130, 0x11231121, 0x37053e33, 0x21331121, + 0x050e2111, 0xb00a0507, 0x71b064fc, 0x414d562f, 0x02041d30, 0x83fec265, 0x1f04fafe, 0x4d463d2e, 0x017ffe27, 0x027ffe81, 0xd9c85527, 0x69e3e8e6, + 0x6a04f0fa, 0xd1cab94c, 0x634bb7c8, 0x0027109b, 0x00040001, 0x84810600, 0xcb4f08f5, 0x09664e40, 0x09860976, 0x47093703, 0x03095709, 0x47060609, + 0x020df70d, 0x00695a0d, 0x00890079, 0x48003803, 0x03005800, 0xa8030300, 0x020eb80e, 0x86010e99, 0x0e57010e, 0x0e770e67, 0x110e0e03, 0x0808070a, + 0x010a000b, 0x0a800a70, 0x60030ac0, 0x3d0805f6, 0x0a480a07, 0x130a0a10, 0xbf0113f0, 0xdf13cf13, 0x13a00313, 0x01138f01, 0x0f011340, 0x02131f13, + 0x01010208, 0xffb81110, 0x110f40f0, 0x03061211, 0x0a110403, 0x0107120e, 0x3f000304, 0x02823333, 0x11391223, 0x06004c33, 0x3d5e1120, 0x115d2906, + 0x2b382f33, 0x3333715d, 0x12231a82, 0x825d2f39, 0x2e0a8200, 0x5de15d5d, 0x5d331132, 0x0130315d, 0x84013301, 0x01240836, 0x11012301, 0x23011123, + 0xedfd2502, 0xb30a02cd, 0xfdcd0a02, 0xd32102ed, 0xfdb3eefd, 0xf202d3ee, 0x3cfdc402, 0xfd250387, 0xfde5020e, 0x0803831b, 0x0100004e, 0xecff4800, + 0xcb05ec03, 0x68003900, 0x5b273f40, 0x00210500, 0x00002130, 0x13033021, 0x670b5b1c, 0x013b9f3b, 0x13801370, 0x4f133f02, 0x03135f13, 0x053a1313, + 0x21aa6020, 0x01217801, 0x0801210f, 0x2f192121, 0x0435602c, 0x10146019, 0x820cb647, 0x833920a6, 0x20b482d0, 0x765c1810, 0x5b112007, 0x142306f8, + 0x1807020e, 0x2b07e4a0, 0x35272622, 0x3233031e, 0x26343536, 0x210ae85b, 0x6c182223, 0x92080827, 0x5b33d103, 0x8a574b7d, 0x8843325e, 0xc06e89cd, + 0x63602b55, 0xb0b22e63, 0xb0bfbacf, 0x32618e5c, 0x3a5f4425, 0x5c4ba96e, 0x83746226, 0x71a66d47, 0x49600439, 0x0c395878, 0x59390b06, 0xa0604877, + 0x2d224074, 0x182417aa, 0x8787940d, 0x48279781, 0x53363d65, 0x36431e3a, 0x29361f7d, 0x85613618, 0x00010000, 0x050000c9, 0x00b60510, 0x406b0017, + 0x0e0b141b, 0x19650d5a, 0xaf0119d0, 0x19200119, 0x16021930, 0x175a0209, 0x09171864, 0xb3e8ffb8, 0x82481814, 0x40e03107, 0x48130a23, 0x09160906, + 0x09030926, 0x1814120d, 0x14211782, 0x35138220, 0x14191409, 0x07031429, 0x03000b14, 0x32323f00, 0x2b2b5d5e, 0x0482333f, 0x9a183320, 0x103108f3, + 0x3232e1f6, 0x33133031, 0x020e1411, 0x33070607, 0x13851801, 0x01310809, 0x01aec923, 0x04020202, 0xcc020704, 0x0406acd5, 0xfd080504, 0xb605d731, + 0x3e1ae0fc, 0x4a204343, 0xfab4044c, 0x3919034a, 0x4d4c418e, 0xff0046fb, 0x25bd85ff, 0x26026907, 0x6945b201, 0x01893206, 0xb4150052, 0x26051d01, + 0xebffb801, 0x001822b4, 0x0aa7490c, 0x0000c724, 0xed82a204, 0x5e000a30, 0x09082140, 0x01091009, 0x00100000, 0x04820702, 0x0c002808, 0x2f010cb0, + 0x0c10010c, 0x010a9701, 0x0a010a56, 0x40f8ffb8, 0x480c0814, 0x0307070a, 0x0b64045a, 0x08040207, 0x64040305, 0x33230545, 0x84393912, 0x331123d6, + 0x00835d2b, 0x2f331131, 0x335d5e38, 0x33113833, 0x23213031, 0x42231101, 0x043705a1, 0xbafddba2, 0x3502baba, 0x02cbfdcf, 0x051bfde5, 0x023cfdb6, + 0x8242fdc4, 0x000025b0, 0x9304e9ff, 0x1f258f82, 0x08b16200, 0x086f8303, 0x17143b39, 0x895a0348, 0x10190119, 0x011ee019, 0x1ec41eb4, 0x00031ed4, + 0x801e501e, 0x1e07031e, 0x5a01101e, 0x0f216500, 0x7f211f21, 0x10080321, 0x5f032010, 0x6014031e, 0x83130d11, 0x05bf5c96, 0x2f330123, 0x06f8455e, + 0x99825e20, 0x5d383325, 0x64322be1, 0xce4805ea, 0x93042416, 0x4885feba, 0xd0201aba, 0x441aa548, 0x4b660675, 0x6804200f, 0xb1650801, 0x2b0f820f, + 0x040000c7, 0x02b605c1, 0x006e0106, 0x6b653f86, 0x272f8509, 0xcb059804, 0x26000602, 0xeb641f84, 0x06b9550c, 0x05ae5f08, 0x002100b6, 0x1210406f, + 0x131b1b01, 0x70006021, 0xf000b000, 0xb8000400, 0x1040c0ff, 0x00480a06, 0x23000010, 0x237f230f, 0x13091402, 0x40f0ffb8, 0x2213130c, 0x1af71ae7, + 0x011ad602, 0xe0ffb81a, 0x0e0a1040, 0x1a011248, 0x5f0d0003, 0x1313060a, 0x3f000300, 0xe1333f32, 0x2b391711, 0x94445d5d, 0x068c4406, 0x39123329, + 0x31333311, 0x4a010130, 0x52080d0e, 0x1e013301, 0x3e331703, 0x04013703, 0x2654feae, 0x6f9c7053, 0x25255a33, 0x52353459, 0xfd1c3842, 0x7f01ccee, + 0x09090a05, 0x0b030204, 0x01030b0b, 0xfbb60537, 0x7ba45dfa, 0xb90f0f48, 0x35171914, 0x3f043f56, 0x180ad7fc, 0x0909171a, 0x071d211f, 0x4b001803, + 0x05210579, 0x21ff83ba, 0xff847301, 0x00000023, 0x0bad6404, 0x7ffec724, 0xff827105, 0x3b000b32, 0x5a032140, 0x5a090202, 0x0db00d00, 0x010daf01, + 0x2d0a1248, 0x055f0800, 0x12050202, 0x2f333f00, 0xd982e110, 0xf6100130, 0x5d5d5de1, 0x33e1d410, 0x3031e12f, 0x0b483325, 0xb0b02a0b, 0x02ba06fc, + 0xfda6bb85, 0x070b48d9, 0x00010023, 0x207982a6, 0x08698281, 0x48001532, 0x01131d40, 0x1765005a, 0x17a01770, 0x01172f02, 0x0d011710, 0x700a605a, + 0xb00aa00a, 0xb80a040a, 0x0e40c0ff, 0x0a480a07, 0x055f1013, 0x030b1405, 0x27059042, 0x33e12f39, 0x5d2b2f01, 0xf6217884, 0x058742e1, 0x23060623, + 0x06c75322, 0x33162908, 0x11373632, 0xba810433, 0x5d62c373, 0xba356592, 0xb95a7b69, 0x5602ba70, 0x5f312e2c, 0x4702598a, 0x7473d1fd, 0xc6022828, + 0xc7248d82, 0x33070000, 0x603af784, 0x08564240, 0x175a0801, 0x05860105, 0x05a60596, 0x77056703, 0x05050205, 0xa3820901, 0x000d3208, 0x020d100d, + 0x0d500d20, 0x0d800d70, 0x0dd00dc0, 0x0f070de0, 0x0407010d, 0x0c64015a, 0x0302060a, 0x015f0408, 0xe13f0012, 0x33333f32, 0xe1f61001, 0x05a8595e, + 0x2f391122, 0x28490882, 0x05044b06, 0x33112129, 0x94f93307, 0x831f02ba, 0x05244902, 0x05f0fa24, 0x8f830010, 0x077ffe23, 0x088f82e3, 0x71000f47, + 0x0c564b40, 0x175a0c01, 0x09860109, 0x09a60996, 0x77096703, 0x09090209, 0x005a0d05, 0x02025a03, 0x00116500, 0x02111011, 0x11501120, 0x11801170, + 0x11d011c0, 0x0f0711e0, 0x08070111, 0x1064055a, 0x03060a0e, 0x0eb1410c, 0xe4259c8c, 0x10e12f32, 0x41a089e1, 0x11200bbd, 0xb021a484, 0x41a688b0, + 0xab850ac4, 0x14000226, 0xd5040000, 0x2b06c549, 0x0b334052, 0x06905a11, 0x08060601, 0x2e06c849, 0x2f1d0f01, 0x5f1d3f1d, 0x051daf1d, 0x49080806, + 0x08220bca, 0xca49095f, 0x0111240f, 0x4c5e2f33, 0x5d20073c, 0x200b304d, 0x10cc4935, 0x7e3cd538, 0x95fe86c2, 0x0f02acfe, 0x7fcf9895, 0xa04efd37, + 0x5c2da3ae, 0xcc495d8a, 0xa4122107, 0x260d2c4c, 0x00c70003, 0x82cf0500, 0x0e3108ab, 0x1d001900, 0x2b404900, 0x00005b13, 0x06000001, 0x651d5a1a, + 0x9f1f0f1f, 0x0906021f, 0x64065a0f, 0x0f5f191e, 0x0209af09, 0x1b090908, 0x600f0307, 0x0be44c1a, 0x68075f5e, 0xe121068a, 0x05035931, 0x2311d94c, + 0x11331101, 0x2007734a, 0x0e704aba, 0xbb930322, 0x8c07734a, 0x56fd25a5, 0x4afab605, 0x830a1d4b, 0x404825ab, 0x905b132e, 0x6731a982, 0x5f1b0f1b, + 0x1b06021b, 0x48181540, 0x130d401b, 0x20ae8448, 0x83ae891a, 0x21ac83ad, 0x1b4b3fe1, 0x2b2b2509, 0xf6105d5e, 0x91088574, 0x94a497a8, 0x088682a1, + 0xecff3b43, 0xcb054404, 0x51002400, 0x201d2f40, 0x1e160c5b, 0x0c041e16, 0x26bf2667, 0x26df26cf, 0x25040403, 0x1faa5f1e, 0x011f7801, 0x08011f0f, + 0x1a071f1f, 0x1311175f, 0x075f0003, 0xe13f0004, 0xe1333f33, 0x2e9e8311, 0x11e15d5d, 0x5d2f3301, 0x3911e610, 0x4f2f2f39, 0x22280521, 0x36270706, + 0x16323336, 0x08d86718, 0x51022e21, 0x99080597, 0x35211312, 0x01032e21, 0x3f945eba, 0x6cc44f4e, 0x52a2f4a2, 0xa4f7a552, 0x4e56613a, 0x59a04e27, + 0xfd06f7ed, 0x0971028b, 0x059d7347, 0x9c202e27, 0xc16d2c2a, 0xb39df6fe, 0x6dcae0fe, 0x0f170e07, 0x012317a2, 0xa2060117, 0x407ab06f, 0xc7000200, + 0x9e07ecff, 0x1a00cd05, 0x5e002e00, 0x5b1b3c40, 0x0111900a, 0x250d1111, 0x3067005b, 0x3f01300f, 0x7f306f30, 0xff30ef30, 0x40300530, 0x10481411, + 0x640d5a0c, 0x165f2a2f, 0x0f5f0b04, 0x10080110, 0x030e0d10, 0x5f20120d, 0xd4821305, 0x4c3f3f21, 0x3f20058d, 0x20051e42, 0x08c5422b, 0x31e13324, + 0x446e0130, 0x21272908, 0x33112311, 0x033e2111, 0x9c59e184, 0x2e2b0809, 0x0e222302, 0x4f9e0702, 0x9796e59b, 0x065098e1, 0xbabaaefe, 0x550b5601, + 0x9591db98, 0xfb4f9ae5, 0x9d6731fa, 0x669d6d6c, 0x82653030, 0x679e2e07, 0xa9dd0231, 0x6cc6eafe, 0x0301b764, 0x051e4fa0, 0xa7ec9226, 0xfec56b5a, + 0x1415a318, 0x00192b08, 0x05f20300, 0x000f00b6, 0x409b001c, 0x01000609, 0x00f600e6, 0xffb80002, 0x0b2440f8, 0x0e1c480f, 0x0000035a, 0x1e650d08, + 0xa1181e3f, 0x06280b9e, 0x01e60101, 0x010201f6, 0x0d202883, 0x59082882, 0x01024b01, 0x0b084002, 0xffb80248, 0x022640f0, 0xdf5b1602, 0xff08ef08, + 0x40080308, 0x0748130f, 0x02081708, 0x1d660808, 0x0f03601c, 0x6011010f, 0x010e030b, 0x333f0012, 0x3912e13f, 0x01e1332f, 0x5d5ef610, 0x33e15d2b, + 0x5d2b382f, 0x715d2b33, 0xf6105d5d, 0x33113911, 0x0c8232e1, 0x01303130, 0x2e012301, 0x36343503, 0x23112133, 0xe15d1111, 0x33890808, 0xb2fe4202, + 0x377d01db, 0xfd2c4b63, 0xbb7501fb, 0x4f734abc, 0x774e2729, 0x5c02b451, 0x8f02a4fd, 0x88613e14, 0xfac9c65d, 0x025c024a, 0x613e1dbb, 0x4a694244, + 0xffff0028, 0xecff5e00, 0x5e049c03, 0x44000602, 0x02000000, 0xecff7500, 0x23062104, 0x3b002700, 0x2c404900, 0x1e09482d, 0x3dd03d57, 0x013d7f01, + 0x0f013d40, 0x1306013d, 0x56004837, 0x1350323c, 0x28081919, 0x09162350, 0x48100b08, 0x01085109, 0x2be13f00, 0x0569573f, 0x2b096462, 0xe132f610, + 0x34133031, 0x37363612, 0x17230282, 0x8207030e, 0x18332002, 0x200d0c5e, 0x068b6c01, 0xc008cf83, 0x021e1407, 0xa2683175, 0x66f27d71, 0x7d7b3221, + 0x643e2c75, 0x0d042948, 0x6b543e12, 0x65966340, 0xae7c4532, 0x7bad6b68, 0x3ce10142, 0x1a264662, 0x3d415a3a, 0x0d39536a, 0x02724119, 0x1901b593, + 0x1b197ecb, 0x08a01431, 0x0a181816, 0xa571420e, 0x313c1d71, 0xb4834920, 0x8ace896c, 0xfdad5945, 0x582794fe, 0x8654698f, 0x4430335f, 0xbc641a49, + 0x03005993, 0x0000ae00, 0x4a041904, 0x20001500, 0x5c002b00, 0x1b033a40, 0x00004621, 0x0947160f, 0x2d202d57, 0x902d4001, 0xd02db02d, 0x052df02d, + 0x06012d0f, 0x0f471b26, 0x1a032c54, 0x0126bf50, 0x26892679, 0x1b262602, 0x0f105025, 0x150f501b, 0x0eb86500, 0x28098e60, 0x3912e12f, 0x14013031, + 0x088e4c06, 0x21112129, 0x03021e32, 0x83232634, 0x863e2009, 0x32332109, 0x50080982, 0x386b7bf6, 0x2f294761, 0xfe719f65, 0x53c50139, 0x903b678e, + 0x00ff8082, 0x5d380401, 0x6d1e2643, 0xecf5fe6c, 0x1f3f5c3e, 0x75683503, 0x24070712, 0x433f5b3d, 0x04305674, 0x6b401c4a, 0x485cc7fd, 0x2a12a8fe, + 0x4d0c0245, 0x0fd7fe40, 0x00003c24, 0x21e38301, 0xe3820a03, 0x2f00053f, 0x00001c40, 0x00020010, 0x07a00700, 0x01078101, 0x02010750, 0x06540347, + 0x0f045001, 0x24411802, 0x5d5d2509, 0x5d2f3311, 0x212fb282, 0x21112311, 0x5afe0a03, 0x035c02b6, 0x8250fcb0, 0x00022645, 0x0483fe29, 0x08098237, + 0x17000f5a, 0x10407900, 0x46120717, 0x3f072f0c, 0x070b0207, 0x0702071b, 0x40f0ffb8, 0xb20ca239, 0x0c04020c, 0x07020c14, 0x050c070c, 0x010e4710, + 0x20000046, 0x550e010e, 0xcf19af19, 0x19300219, 0x01192f01, 0x05054604, 0x0c4f1218, 0x060e170f, 0x05150350, 0x3f00fb00, 0x32e13f32, 0x11210382, + 0x06f96601, 0x475de421, 0x392b068b, 0x5d5d2f2f, 0x105d5d38, 0x4f3311e1, 0x02210ac9, 0x05ca4f12, 0x0e233108, 0x37040703, 0xae4efdae, 0x43634156, + 0x17020122, 0xc0b2fe97, 0x513a2407, 0x0183fe34, 0x0283fe7d, 0xf3df5f17, 0xfc7f0001, 0x67240350, 0x53c2d1d7, 0x2905a560, 0x5e04e103, 0x48000602, + 0xc14f0000, 0xbe052105, 0x2208db82, 0x409c0011, 0x0303061f, 0x000f460a, 0x010bd600, 0x0bc90bb9, 0x010ba602, 0x0b010b97, 0x04070e0b, 0x82080505, + 0xb3c024e8, 0x83481512, 0x402e0807, 0x480b0724, 0x0601070f, 0x07071007, 0x10130013, 0x13df0213, 0x70133001, 0x03139013, 0x0701130f, 0x0d101011, + 0xf0ffb80e, 0x0e0e0f40, 0x69820312, 0x0a080d27, 0x01041115, 0x17984f0f, 0x33117128, 0x5d5e382f, 0x974f2b2b, 0x32e1210e, 0x8f4ffc84, 0x01013e0d, + 0xa48f0233, 0xfec5a001, 0xcece0158, 0xfea443fe, 0xcf01cf44, 0x02c558fe, 0xfd150235, 0x250383eb, 0x2d02cbfd, 0x0384d3fd, 0xe9821382, 0xecff4432, + 0x5e045203, 0x5f003900, 0x46053a40, 0x39161b16, 0x31080182, 0x2147340c, 0x3bb03b57, 0x3bd03bc0, 0x013b6f03, 0x29013b20, 0x1b3a560c, 0x39cf5038, + 0x99398901, 0x390f0239, 0x39390801, 0x26502f11, 0x11500816, 0x69720010, 0x5d5d2708, 0x100139e1, 0x8a4f32e6, 0x39392306, 0x884f2f2f, 0x3e322506, + 0x26343502, 0x200a6b4f, 0x139a4f15, 0x61082485, 0x71013523, 0x2748643d, 0x81476c73, 0x4d283f4b, 0x56355a52, 0x1c3a6990, 0x2c2b4633, 0x35263f52, + 0x6d71a66c, 0x4c1f3aaf, 0x37336157, 0x85294660, 0x8702818a, 0x2d402712, 0x22264d4d, 0x131c1493, 0x6d4a2609, 0x3b4d3246, 0x0e0b0e29, 0x3e5a422c, + 0x31567543, 0x10a62223, 0x120f181f, 0x5e33452a, 0x1143995b, 0x04310805, 0x004a043b, 0x4051000b, 0x0910031b, 0x06034818, 0x0d550546, 0x0d100d00, + 0x0da00d20, 0x0dd00dc0, 0x0d070df0, 0xb3c0ffb8, 0x0948110e, 0x40f0ffb8, 0x2d258211, 0x0a460009, 0x03080c54, 0x02060f0b, 0xba41150a, 0x10012706, + 0x2b32e1f6, 0x06845d2b, 0x30312708, 0x01071101, 0x11231133, 0x11230113, 0x020c5a01, 0x0bace904, 0x04eafefd, 0xfc64fd4a, 0xb6fb9803, 0x0f018702, + 0x7c826afc, 0x3f058b66, 0x17063b04, 0xd2012602, 0x06010000, 0x00253602, 0x01b41500, 0x01261111, 0xb4ffffb8, 0x040a0c16, 0x240a4f4f, 0x030000ae, + 0x283882e5, 0x4041000a, 0x01010023, 0x053a6304, 0x03031037, 0x010c0f0c, 0x4706020a, 0x050b5407, 0x070a0a02, 0x040f0800, 0x209f8307, 0x05494d3f, + 0x3230a284, 0x2f33115d, 0x33335d38, 0x30313311, 0x01013301, 0x2b06354f, 0xfec4fa02, 0xcec60161, 0xb4b44bfe, 0xf126a582, 0x2d02c5fd, 0x0982d3fd, + 0x0100eb28, 0xf2ff1000, 0x7382b003, 0x00143408, 0x0331404c, 0x01130446, 0x800113f4, 0xc0139013, 0x0413d013, 0x13011354, 0x47010b13, 0x0f165500, + 0xff162f16, 0x0b060316, 0x5003150b, 0x4f0e0f13, 0x82011608, 0xe13f2181, 0x20059553, 0x06224f5e, 0x5d5d5d23, 0x06087471, 0x7d680220, 0x27300805, + 0x32331635, 0x37123636, 0xb6b00321, 0x4014fefe, 0x1c56825f, 0x1b171031, 0x33455937, 0x03540212, 0xfefdfeb0, 0x0669e694, 0x75068306, 0xfa6f01f1, + 0x2105bf41, 0x95821005, 0x00204208, 0x1f3f405e, 0x55004601, 0x0122cf22, 0x22502240, 0x01220f02, 0x46101306, 0x02215411, 0x4b0f3b0f, 0x030f5b0f, + 0x0f190f09, 0x0f030f29, 0x340f121f, 0x54194419, 0x19060319, 0x19261916, 0x01091903, 0x25a38211, 0x5d333333, 0x04833f5d, 0x46331121, 0x102008bf, + 0x2a073d4d, 0x0107030e, 0x032e0123, 0x82231127, 0x031e351e, 0x37033e17, 0x10053301, 0x141106a1, 0xf8fe0712, 0x05f7fe87, 0x32080983, 0x0b01dda2, + 0x0f13160d, 0x130e0604, 0x0e010d16, 0x158103d9, 0x12363b39, 0xb00250fd, 0x3e3b310d, 0x047ffc1a, 0x2247fd4a, 0x10323c43, 0x413b3111, 0x42bd0221, + 0x44080c89, 0x0217405b, 0x55054706, 0x200d000d, 0x0d30020d, 0x0d500d40, 0x0df00dd0, 0xffb80d05, 0x0e2340c0, 0x09014811, 0x0c540a47, 0x01eb5008, + 0xb901a901, 0x010f0201, 0x012f011f, 0x01010603, 0x0315050a, 0x3f000f00, 0x056f5832, 0x495d5d21, 0x32260b6d, 0x11013031, 0x7e4e1121, 0x11233805, + 0x21026401, 0xdffdb6b6, 0xfe4a04b6, 0xfbc70139, 0xfee901b6, 0x654a0417, 0x280812b1, 0x040000ae, 0x004a0412, 0x402d0007, 0x0447051c, 0x09100955, + 0x09600920, 0x09800970, 0x01470005, 0x50070854, 0x00050f02, 0x84788315, 0x755d2071, 0x012e0ce5, 0x6403b664, 0x0408feb6, 0x03b6fb4a, 0x618200b0, + 0x14feae2b, 0x5e043f04, 0x53000602, 0x240f8300, 0x03ecff71, 0x2a0f846f, 0x00000046, 0x00290001, 0x845e0300, 0x40582871, 0x0109203c, 0x830109df, + 0x5f02286c, 0x000f0109, 0x8200cc01, 0x00bf2105, 0x003d3d82, 0x60034702, 0xd0057005, 0x051f0305, 0x00050501, 0xb0031003, 0x0403c003, 0x50050103, + 0x06c94606, 0x2f013230, 0x5d2f335d, 0x32e1105d, 0x5d5d5e2f, 0x03825d71, 0x3b07d246, 0x5e032135, 0xfeb7c1fe, 0x033503c1, 0x0350fcb0, 0xffff9ab0, + 0x14fe0a00, 0x4a04df03, 0x5c205f82, 0x032c8d82, 0x14fe7100, 0x14062305, 0x22001900, 0x30089982, 0x274b4074, 0x1d460b00, 0x130d0c17, 0xc90cb949, + 0x0c97020c, 0x0c020ca7, 0x4823120c, 0x202b5705, 0x2b0f012b, 0xef2b9f01, 0x2b80022b, 0x012b6f01, 0x37108340, 0x06022b1f, 0x5612481a, 0x2600182a, + 0x1700501e, 0x501d2710, 0x0b160d0a, 0x2209be62, 0x4f013f32, 0x9e830510, 0x2508c775, 0xe133332b, 0xad823232, 0x080cac60, 0x023e3483, 0x01331137, + 0x11171614, 0x3405030e, 0x36112726, 0x71210336, 0x474c88bd, 0xaa77be86, 0x4c89bf72, 0x79c18547, 0x9c0cfeaa, 0x507d58ae, 0x9b390325, 0x0499acaa, + 0x8f550c5a, 0xc87d7dc6, 0xfe0b5691, 0x0adc0124, 0x7ec99056, 0x558fc77d, 0xfcba010b, 0x13d2bb13, 0x3d093c03, 0xba5e9167, 0xc6fc14cc, 0xff00d114, + 0x002300ff, 0x04db0300, 0x0006024a, 0x0000005b, 0xfeae0001, 0x04b20483, 0x000b004a, 0x32d68244, 0x01000f47, 0x07000006, 0x010a8f47, 0x0d100d0a, + 0x4f600d20, 0x063206f9, 0x54034706, 0x0f04080c, 0x0350060a, 0x00fb0115, 0x09513f3f, 0xd4102808, 0x2f33e15d, 0x47e15d5e, 0xef4f06ba, 0x04333605, + 0xb2fcb6b2, 0xb6f801b6, 0x0183fea0, 0xfc4a047d, 0xfcb00350, 0x20738250, 0x2083829a, 0x287382fe, 0x40310018, 0x470c081c, 0xf29b180b, 0x47012c08, + 0x08195417, 0x12125003, 0x4209150b, 0x392205f6, 0xb664e12f, 0x82322008, 0x14112b60, 0x023e3233, 0x11331137, 0x3a651123, 0x012b0807, 0x502db850, + 0xb62a4d4c, 0x55502cb6, 0x7a4e3a5e, 0x4a042b52, 0x0fae66fe, 0x011c2c1c, 0x01b6fbd5, 0x20301ee9, 0x73542f11, 0x43a60144, 0x06210599, 0x08f38446, + 0x4340662f, 0x09b64700, 0xa90209c6, 0x74030109, 0x94098409, 0x09670309, 0x09090601, 0x04470105, 0x0d200d55, 0x010d0f01, 0x0df00d80, 0x010d6f02, + 0x300d8340, 0x06020d2f, 0x54054708, 0x5008000c, 0x060a1505, 0x05e84702, 0x4132e121, 0xae6408ed, 0x5d5f2207, 0x2302825d, 0x253031e1, 0x2006285a, + 0x2f078211, 0xba01d503, 0xb668fab7, 0x9ab6bb01, 0xb6fbb003, 0x41051741, 0x06210589, 0x2d9582e5, 0x4077000f, 0xb6470a4e, 0x0207c607, 0x958207a9, + 0x07840732, 0x67030794, 0x07060107, 0x470b0307, 0x0e47010e, 0x24082e82, 0x010ebf00, 0x1120110e, 0x01110f01, 0x11801140, 0x11f011e0, 0x2f110f04, + 0x06060211, 0x10540347, 0x0f04080c, 0x0bac410e, 0xa1513220, 0x1071260a, 0x2f325dc4, 0x0507515d, 0x0120a688, 0x8308d15a, 0x331126a8, 0xfab6e506, + 0x82a8837f, 0x419f20b1, 0x032b0bc3, 0x0050fcb0, 0x00290002, 0x82fc0400, 0x0e3708b1, 0x5c001b00, 0x470f3e40, 0x501d5704, 0x901d601d, 0x041de01d, + 0x00011d3f, 0x000a4716, 0x020c100c, 0x0cf00cb0, 0x000c0c02, 0x500a100a, 0xa00a600a, 0x0a08050a, 0x83bf5015, 0x0c1627c5, 0x160f0d50, 0x634b0a50, + 0x01e12c09, 0x335d5e2f, 0x10715d2f, 0x5c5d32e1, 0xe1730874, 0x11212805, 0x01213521, 0x4b022e34, 0x0225065c, 0xd4140148, 0x05504bcc, 0x98fe2808, + 0x02021f02, 0x40604121, 0x040100ff, 0x26445d37, 0x9b9c8702, 0x2f587c4d, 0xfc9ab003, 0x284231f8, 0x11a8fe11, 0x4c004229, 0x3f08051b, 0x4a045005, + 0x10000c00, 0x61001d00, 0x47184040, 0x04100400, 0x04700420, 0x060504d0, 0x0e0a0404, 0x1f550d47, 0xbf011f0f, 0xdf1fcf1f, 0x041fff1f, 0x0f011fa0, + 0x021f7f1f, 0x47120007, 0x111e540a, 0x0f25be85, 0x50120f0b, 0x5ebd830e, 0x9e450511, 0x635e2006, 0x164309c1, 0x32332105, 0x332bc087, 0x33112301, + 0x32331101, 0x8335023e, 0x640122c8, 0x2dc186ec, 0xec03b662, 0x14fcb6b6, 0x435d38db, 0xc7822126, 0x0427bf87, 0x04b6fb4a, 0x84a4fd4a, 0x833020be, + 0x000022c8, 0x08df4c02, 0x19000c3e, 0x29404000, 0x57044714, 0x011b001b, 0x1b201b00, 0x1b901b70, 0x1bd01bb0, 0x0e000806, 0x1a21ac82, 0x22ac850d, + 0x410e0f0b, 0x39200668, 0x09f1b118, 0xf6107127, 0x013031e1, 0x22a08921, 0x89211111, 0x1501219c, 0x39239d86, 0x910401b6, 0x08948c98, 0x3700014b, + 0x4203ecff, 0x26005e04, 0x3e405e00, 0x0c040e0e, 0x5722480f, 0xaf288f28, 0x28400228, 0x040f1801, 0x042f041f, 0x0c400403, 0x58044811, 0xef500d27, + 0x0ea9010e, 0x0f020eb9, 0x2f0e1f0e, 0x0e06030e, 0x5112070e, 0x5107101d, 0x0ce17000, 0x1001e125, 0x42712be6, 0x3223050d, 0x622f3911, 0x372b0cba, + 0x26213521, 0x0e222326, 0x4e270702, 0x4c080982, 0x7c594201, 0x52833636, 0x30527449, 0x0123fe04, 0x8c920ddb, 0x383c3b19, 0x40183517, 0x66264e48, + 0x514d84b3, 0x1e14ba8c, 0x2519a21d, 0x5c845428, 0x0997a69a, 0x9a0a130f, 0x0910160c, 0x9ddb893e, 0x438ad492, 0x00020000, 0x06ecffae, 0x20d18208, + 0x08d3821a, 0x4b407220, 0x200a481b, 0x114f0111, 0x0d111101, 0x57004821, 0x2f280f28, 0x28ef0228, 0x470228ff, 0x0c840128, 0x0c102608, 0x27540d47, + 0x10165024, 0x10ef500b, 0xb910a901, 0x102c0210, 0x1b100b01, 0x10060210, 0x0f0e0d10, 0x501e150d, 0x21e08405, 0x1552123f, 0xe15d2105, 0x42064551, + 0x5d210937, 0x05475171, 0x23020e25, 0x51022e22, 0x1e210b45, 0x95831802, 0x0623080b, 0xab784008, 0x75a2626a, 0xeffe0746, 0x1301b6b6, 0xa076480a, + 0x79a76263, 0x8029fd44, 0x807e8f8e, 0x6c7e8e8f, 0x4230056b, 0xfe7cbe81, 0xfe4a0417, 0x78b17439, 0xd3914b3e, 0x0b77a018, 0x00233e08, 0x04910300, + 0x0011004a, 0x4053001c, 0x11110214, 0x470f1807, 0x0f1e550e, 0x8f1e6f1e, 0x0006031e, 0xf0ffb801, 0x01011940, 0x40074612, 0x07481512, 0x10021d56, + 0x00181850, 0x0f0d5019, 0x0629480f, 0xe137ce82, 0xf6100132, 0x2f33e12b, 0x5d5e3338, 0x32e1f610, 0x33113911, 0x50333031, 0x420805e4, 0x2133023e, + 0x23112311, 0x021e1403, 0x23113333, 0xc6e90622, 0x542d2301, 0x64382841, 0xbc01538a, 0x25ddf4b6, 0xdb365a41, 0x01686bfe, 0x4c300ccd, 0x794e476c, + 0xb6fb2a51, 0x5401b001, 0x162e4630, 0x485f6601, 0xe12b075d, 0x2602d905, 0x00004800, 0x18000601, 0x2b1c9774, 0x12000100, 0x120414fe, 0x31001406, + 0x2c08db82, 0x0c171f32, 0x33552d47, 0x33603310, 0x23033380, 0x47161e22, 0x3254171b, 0x1e4f1921, 0x231c1a1a, 0x29005010, 0x29202910, 0x1c0f2903, + 0xbf5c1800, 0xe15d220b, 0x08847c33, 0x32e13222, 0x22052571, 0x18313912, 0x200c7a5d, 0xc85c1811, 0x35232109, 0x10c66518, 0x020e1424, 0x5c18f002, + 0x692809d1, 0x436e5170, 0x9c9cb61d, 0x0dd36518, 0x0ed55c18, 0x65184420, 0xfc2615e1, 0x577b4dbe, 0x6b4c002f, 0x0a032e05, 0x26022106, 0x0000cd01, + 0x76000601, 0x05f166d4, 0x26111227, 0x0c064501, 0x0b256103, 0x08069749, 0x00220033, 0x1731404f, 0x0d1f1617, 0xaf248f24, 0x24400224, 0x48191601, + 0x19235605, 0x0116ef50, 0x16b916a9, 0x1f160f02, 0x03162f16, 0x1c161606, 0x100a5113, 0x1194431c, 0x32e1f626, 0xce105d5d, 0x21079243, 0x8b7c022e, + 0x063b6e05, 0x21070624, 0xfe722115, 0x52022208, 0x35ab1865, 0x928b380f, 0xfedb010e, 0x8a920923, 0x36368351, 0x893f147b, 0xdb9d96d5, 0x6e223e89, + 0x97290522, 0xa4b89aa6, 0x1da21925, 0x23e3821e, 0x03ecff5a, 0x21055f4a, 0xf3830056, 0xe982a020, 0xe5057527, 0x4c000602, 0x210f8200, 0x7518eeff, + 0xff262ded, 0xfebcffff, 0x41850114, 0x82004d21, 0x0041083c, 0x06f2ff10, 0x004a0412, 0x002a001d, 0x0c45406b, 0x25001c46, 0x1cd40a47, 0xa01c9001, + 0x1c24021c, 0x011c0001, 0x0a1c0a1c, 0x04471e14, 0x2c0f2c57, 0x2c3f2c2f, 0x2c7f2c5f, 0x2cef2cbf, 0x2b141407, 0x05644524, 0x500c2529, 0x4f170f1c, + 0x45251611, 0xe126066b, 0x3912e13f, 0xf8555d2f, 0xe1f62706, 0x2f393911, 0x00825d2f, 0x32e11027, 0x3031e110, 0x091b4601, 0x384d2320, 0x34013610, + 0x2323022e, 0x3e323311, 0xec870302, 0x652ecbd4, 0x62fe719f, 0x0f4a4dd9, 0xd9012b2b, 0x40604121, 0x5d38dbd7, 0x0af64643, 0x470e5e4d, 0x02260b04, + 0x0000ae00, 0xef827506, 0x00142a08, 0x40530021, 0x471c0530, 0x130f0f02, 0x57094715, 0x0123ef23, 0x3f012380, 0x23100123, 0x47120101, 0x1b225413, + 0xbf055011, 0x24008201, 0x13501c00, 0x08924c0f, 0x2f21cc82, 0x0803655d, 0x20051e50, 0x08966b11, 0x33112122, 0xb947b982, 0x23112208, 0x24ce8a11, + 0xcf016401, 0x08fa46b6, 0xb631fe2e, 0x41211505, 0xdcd83f61, 0x26445d37, 0x2105c04c, 0xbf473dfe, 0x05c64c05, 0x0127bd8b, 0x00001200, 0x85061204, + 0x683226bb, 0x0b140114, 0x92691800, 0x0e0e2117, 0x0b8d6918, 0x00100f23, 0x8d69180b, 0x8c69180c, 0x3911230e, 0xa918315d, 0xc6430c84, 0x5c032112, + 0x2016b943, 0x8d691802, 0xae00321b, 0xe5030000, 0x26022106, 0x0000d401, 0x76000601, 0x05a74308, 0x26111728, 0x110b0c01, 0x11500307, 0x07b14c07, + 0x02170625, 0x835c0026, 0x3602222b, 0x202b85b1, 0x232b8228, 0x00232d0a, 0x09cb7318, 0x2205c34b, 0x824a0412, 0x592408d7, 0x06d63d40, 0xc706b701, + 0x47060206, 0x07c507b5, 0x760307d5, 0x02078607, 0x075a074a, 0x09070702, 0x55044701, 0x340ad74b, 0x09470005, 0x00050c54, 0x06150950, 0x0f020afb, + 0x3f333f00, 0x096f4b3f, 0x2f391128, 0xe15d5d5d, 0xc24a5d5d, 0x11232e08, 0x01331121, 0xb6f80164, 0xfeb7b3fe, 0x05c24aa0, 0x82051a4a, 0xc70021a6, + 0xbe31e182, 0x0700e306, 0x2c404400, 0x03df5a00, 0x03ff03ef, 0x05cc5003, 0xb0090335, 0x0209d009, 0x09af090f, 0x065a0502, 0x5f040864, 0x82012007, + 0x03072e00, 0x3f001206, 0x5d2f333f, 0x1001e110, 0x206e82f6, 0x260b8211, 0x3031e15d, 0x82331101, 0x1123316f, 0xfdb00e03, 0xb605bac3, 0x2dfe2d01, + 0xb605f0fa, 0x2305c34b, 0x89050a03, 0x30346982, 0x47051c40, 0x00100000, 0x09000002, 0x54034702, 0x20061008, 0x0622ff82, 0xf9544f01, 0x834e8207, + 0x83568358, 0x5d212055, 0x033205ae, 0xb65afe0a, 0x03b6a601, 0x043ffcc1, 0xff3f014a, 0x581800ff, 0x00230e65, 0x61e70043, 0x2b2b0507, 0xb8012605, + 0x31b4acff, 0x410e1e2b, 0x58180aa5, 0x062a0d67, 0x004c4300, 0x01b41500, 0x2d831130, 0x36b49e25, 0x8d2e1130, 0xc358182d, 0x7600230b, 0x5d82a001, + 0x0b401324, 0x5e823701, 0x312b6422, 0x07205b9a, 0x17242d82, 0x13000000, 0x3c202d82, 0x69225e82, 0x5b923630, 0x26022b2c, 0x00003a00, 0x6a000701, + 0x5b823901, 0x02b61927, 0x26053401, 0x23bb8202, 0x3f2bb4ff, 0x876d5f85, 0x21bd8408, 0x3382d905, 0x33855a20, 0x82ac0021, 0x21338361, 0x33861139, + 0x85443021, 0x82338865, 0x18042020, 0x230a2b59, 0x72ff4300, 0x20052141, 0x24c28209, 0xb4a4ffb8, 0x2d59180f, 0x8207201b, 0x824b202f, 0xb4152342, + 0xc4822301, 0x29202f83, 0x080dcb42, 0xd1015225, 0x7902ae03, 0x1d000300, 0xff0200b9, 0x060b40c0, 0x0202480c, 0xb9000005, 0x3f00bd01, 0x112f01e1, + 0x7c2b2f33, 0x52290553, 0xd1015c03, 0x0100a8a8, 0x20358200, 0x2035a807, 0x2835bb07, 0xfefcff02, 0xff4e0331, 0x34a182d3, 0x402a0007, 0x00000418, + 0x05010509, 0xff06efba, 0x02060206, 0x064278ba, 0x2f000124, 0x0282e15d, 0x332f0122, 0x3325b082, 0x21013031, 0x25018435, 0xaefc4e03, 0x03835203, + 0x8b31fe25, 0x82008b8c, 0x172808bd, 0x5001c103, 0x0c00b605, 0x17402500, 0x06010e5f, 0x075f070f, 0x07bf076f, 0x070507cf, 0x0c01980c, 0x0003069c, + 0x2f01e53f, 0x33215082, 0x08fb825d, 0x033e2721, 0x030e3337, 0x0e0e2507, 0x19342e27, 0x1a1d0f89, 0xc1030816, 0x7c7a3616, 0x843d387b, 0x93357c83, + 0x2d4a8255, 0x015f010f, 0x01bf016f, 0x010501cf, 0xc2829c06, 0xa7825583, 0x01215583, 0x20518217, 0x21598223, 0x56824201, 0x19332f33, 0x1b1d0e89, + 0xb6050816, 0x7d793716, 0x843c387a, 0x82568284, 0xfe3f2657, 0x007901f8, 0x2cad82ee, 0x0e00b935, 0x1440c0ff, 0x0c48180a, 0x205a8598, 0x2a5a847f, + 0xb8070601, 0x10b7c0ff, 0x82074815, 0x84a82065, 0x332b29bb, 0xe15d2f33, 0x2530312b, 0x6a226788, 0xd5180e0f, 0x012816f6, 0xc1031900, 0xb6055201, + 0x2b3a6582, 0x0e5f1c40, 0x050f0601, 0x056f055f, 0x05bf057f, 0x05df05cf, 0x00050507, 0xc2880b98, 0x5b82e120, 0x2a08c383, 0x17031e13, 0x27032e23, + 0x1608ee37, 0x890f1d1a, 0x272e3419, 0xb6050e0e, 0x84847c35, 0x7d7a383c, 0x00163779, 0x03170002, 0x84d102c1, 0x1938085b, 0x48406200, 0x90011bbf, + 0x1b0f011b, 0x1b6f1b5f, 0x140f1303, 0x146f145f, 0x14bf147f, 0x14df14cf, 0x19141407, 0x980c0e98, 0x01500100, 0x01700160, 0x01c001b0, 0x010701d0, + 0x2d0da341, 0x139c0c19, 0x3f000306, 0x0132e533, 0xe8845d2f, 0x92852f20, 0x315d5d24, 0xae410130, 0x87212007, 0xa6012108, 0x210bb841, 0xc641b8fd, + 0x0bd14118, 0x002cb79e, 0x60145014, 0xb0147014, 0xd014c014, 0x0f2ab785, 0x6f0e5f0e, 0xcf0ebf0e, 0xc282050e, 0x2407a041, 0x01cf01bf, 0x25c284df, + 0x9c061307, 0xb782000d, 0xb7833220, 0x5d20b685, 0xa841b78a, 0x42212007, 0x02211519, 0x18274248, 0x080b3242, 0x3f000230, 0xfa02f8fe, 0x0c00ee00, + 0x7e001900, 0x1bd05140, 0x1bf01be0, 0xb41ba403, 0x031bc41b, 0x02011b90, 0x1b301b20, 0x1b601b40, 0x1b801b70, 0xc9871306, 0x062bc783, 0x98191414, + 0x0ee00e90, 0x83030ef0, 0x8a0220ce, 0x21c683c8, 0x6b420106, 0x0a402405, 0x85481810, 0x00a822cf, 0x42cf843f, 0x2f210570, 0x23d1865d, 0x5d5d5d5f, + 0x890a7c42, 0x0c8542d3, 0xee21d38d, 0x07514317, 0x8a357d21, 0x006a080a, 0x7b000100, 0x68030000, 0x0b001406, 0x52407c00, 0x0da00d90, 0x0df00de0, + 0x010d6f04, 0x0d300d10, 0x07030d40, 0x0804c006, 0x0be40308, 0xd6020bf4, 0x0b77010b, 0x010b6a01, 0x45010b54, 0x0b26010b, 0x09c00b01, 0x0909010a, + 0x02010236, 0x100300be, 0x0303a003, 0x00010403, 0x0a0bbf05, 0x08c20607, 0x2f000300, 0x3232f63f, 0x0382e132, 0x5d2f012a, 0x11325de1, 0xe6103333, + 0x0283c282, 0x2f331125, 0x8433e633, 0x250136cf, 0x05132313, 0x33030535, 0x68032503, 0xd937b5fe, 0x01c9fe37, 0x31068237, 0xdd034b01, 0x0304fc1f, + 0x1eb41ffc, 0x5ffea101, 0xb586001e, 0xb5827d20, 0x00154e08, 0x007140b0, 0x17a00117, 0x17f017b0, 0x01177f03, 0x17401720, 0x08031750, 0x0b0ec00d, + 0x01050f0f, 0xf4011204, 0x12e60112, 0x01128701, 0x6401127a, 0x12550112, 0x46123601, 0xc0120212, 0x10111410, 0x00031510, 0x0a05be04, 0x0006090a, + 0x08b98205, 0x20051025, 0xa0055005, 0x0605b005, 0x13140508, 0x12bf0c0b, 0xc20d0e11, 0x0109000f, 0x06bf0800, 0xc2070203, 0x872f0005, 0x27dc8ad3, + 0x33715d5e, 0x102f3333, 0xe58cea83, 0x0d827120, 0x33332f24, 0xdd5532e6, 0x15252106, 0xf087eb87, 0x022e1082, 0xfe4c0131, 0x38d937b4, 0x4c01b4fe, + 0x05832f2f, 0x37d93822, 0x2f301383, 0xb41ef001, 0x0187fe1f, 0x1eb41f79, 0x13012201, 0x78220683, 0x148388fe, 0x00ed3208, 0x96000100, 0x6d02e501, + 0x1300f203, 0x24404600, 0x155f152f, 0x157f156f, 0x15ef15cf, 0x100715ff, 0x0a5f0115, 0x0a9f0a6f, 0x0adf0aaf, 0x0a060aef, 0x2f3082d0, 0x40c0ffb8, + 0x480a070c, 0x010f1f00, 0x0105100f, 0x5d25cf82, 0x2f015dc5, 0x2005822b, 0xa694185d, 0x962b0812, 0x32563f24, 0x25405631, 0x31564025, 0x243f5632, + 0x6447ec02, 0x3f1c1c3f, 0x64464764, 0x3f1e1e3f, 0x00030064, 0x05e3ff93, 0x82fa00db, 0x278a0885, 0xa8003900, 0x3b147640, 0xfb023b24, 0x3be4013b, + 0xcb3bbb01, 0x3ba4023b, 0x013b8b01, 0x3b743b64, 0x013b4b02, 0x0b013b34, 0x961e013b, 0x14761466, 0x00141402, 0x32249628, 0x0132fb01, 0xd40132e0, + 0x32bb0132, 0x0132a401, 0x7201328b, 0x32660132, 0x01324b01, 0x02013230, 0x0f013220, 0x32060132, 0x00e0960a, 0x540200f0, 0x02006400, 0x00100000, + 0x07030020, 0x05192d00, 0x0f23379b, 0x33332f00, 0x013232ed, 0x5d5d5e2f, 0x0583ed5d, 0x6c425f20, 0x26068206, 0x3911ed71, 0x88ed5d2f, 0x31712410, + 0x18343730, 0x2409744a, 0x022e2223, 0x210f9c25, 0x95189326, 0x252010b1, 0x13221191, 0xe3182e23, 0x363208bb, 0x35266f49, 0x210f0f21, 0x35252635, + 0x22101022, 0x0f9b2535, 0x00425208, 0xff660007, 0x05f408ec, 0x000900cb, 0x0027001d, 0x003f003b, 0x005d0049, 0x405c4089, 0x4ab554b4, 0xb532b41e, + 0xa028b423, 0x3c30013e, 0x3cb03c40, 0x40283003, 0x3c3e0228, 0x3e3c2828, 0xb4451403, 0x5f3f5f4a, 0x5f5f5f4f, 0x5faf5f7f, 0x0ab40505, 0x09e118b5, + 0xb6472709, 0xb643b759, 0xe118194f, 0x3f231e11, 0x18e1f4e1, 0x290915e1, 0x2f391712, 0x5d5d2f2f, 0x1682105d, 0xe1f4102f, 0x14133031, 0x11323316, + 0x06222310, 0x1a591805, 0x9901200e, 0x23012219, 0x3a1d9901, 0x9c5047fa, 0x0147509c, 0x734a24c7, 0x4c70494f, 0x71492326, 0x4d714b4e, 0x86ac0127, + 0x18c62019, 0x261635e1, 0x51479702, 0x82519b9b, 0x2c208b3a, 0x274c724a, 0xa5a50204, 0x48014a01, 0x4fe118a3, 0x02fc252e, 0x4901a4a5, 0xab3d3784, + 0x763f3f76, 0xaa6c6cab, 0x753e3e75, 0x00ffffaa, 0x01a60385, 0x02b6054a, 0x000a0006, 0x210f8500, 0x0f84b202, 0x00054008, 0x00010000, 0x01730052, + 0x00c703fc, 0xb13c0006, 0xffb80204, 0x091f40c0, 0x0802480c, 0x089f083f, 0x08df08af, 0x08ff08ef, 0x9feb0606, 0x06030103, 0x01030300, 0x2f000105, + 0x3d39122f, 0x1833332f, 0x2309ef9e, 0x01133031, 0x0dde9e18, 0x0bd49e18, 0x3f24658c, 0xeb002840, 0x25069b4c, 0x03200310, 0x698c0302, 0x023f0424, + 0x68930201, 0x2f5d3325, 0x18e15d5d, 0x26086c96, 0xcbfefc01, 0x18eded75, 0x820e5b96, 0xff932cdf, 0x056203e3, 0x002700b6, 0x82d10104, 0x000622e0, + 0x32e78204, 0x312fb509, 0x01311001, 0x00005d5d, 0x00a0fe01, 0x82680200, 0x00032223, 0x33de181d, 0x12012d0c, 0x3f000300, 0x382f013f, 0x33382f32, + 0x2a051d64, 0xd5fc6802, 0x052b039d, 0x824afab6, 0x01380831, 0x1d036a00, 0xc7059302, 0x41001400, 0xe0001740, 0x14011400, 0xc0166016, 0xf016e016, + 0x160f0416, 0xe00a0e01, 0xc0ffb80b, 0x0f0a0e40, 0x000a0b48, 0xe4040ec0, 0xdc0cde11, 0xe12d5682, 0x32cc1a33, 0xe12b2f01, 0x105d5d32, 0x52cb84d6, + 0x29080ab0, 0x36331733, 0x11153233, 0x3f3f1402, 0x152a412d, 0x0910697f, 0x03e58240, 0x51a6011d, 0x57341544, 0x02a6fe41, 0xfa65589d, 0xc18250fe, + 0x00600022, 0x8f82d682, 0x00112a08, 0x02484076, 0x05100210, 0x0b100b00, 0x0b030b20, 0x1330130b, 0x04000e01, 0x0509055a, 0x070107df, 0x10050007, + 0x0305c005, 0x3e028207, 0x08000860, 0x0f0e5f11, 0x6f0e3f0e, 0x0e08030e, 0x48151040, 0x0e080e08, 0x0a5f0d04, 0x83120403, 0x39122aa3, 0x2b2f2f39, + 0xe1105d5e, 0x0fa61811, 0x2f332207, 0x200b845d, 0x20068232, 0x05c3772f, 0x0130312c, 0x11211521, 0x35231123, 0x09831133, 0x013e0382, 0xfe2401c3, + 0xb0b0b3dc, 0xc3fdf002, 0xeafd1602, 0xfe898f01, 0x890601fa, 0xfda42704, 0xb583a4fc, 0xb5824420, 0xc9052332, 0x87003000, 0x0d111040, 0x272b6f15, + 0x23130f23, 0x4b080182, 0xb81b031e, 0x3e40c0ff, 0x1b480e09, 0x3210321b, 0x1e252901, 0x480e0b40, 0x7525141e, 0x10261126, 0x0d2a7529, 0x01266f2a, + 0x0f012ad0, 0x3f2a1f2a, 0xaf2a4f2a, 0x062abf2a, 0x2a262a26, 0x741a1e00, 0x7307181d, 0x3f000700, 0x32e13fe1, 0x8407e351, 0x240484b4, 0x332b2f01, + 0x21bd8333, 0xdf84332b, 0x11331122, 0x2307085c, 0x07171632, 0x2105c056, 0xc4821515, 0xa9180384, 0x35200e0d, 0x3527e482, 0x02023e34, 0x18ae6a9a, + 0x240c11a9, 0x88fe7801, 0x15a91817, 0x17a9180c, 0x89c0310f, 0x3e13899e, 0x102b4059, 0x290b9aa6, 0x15436144, 0x23081082, 0x5f8957dd, 0x00030032, + 0x05ecff96, 0x00b605b6, 0x002a001b, 0x40790035, 0x1c6f3118, 0x6e0f1012, 0x1c181518, 0x2c080182, 0x0105ff24, 0x15124005, 0xffb80548, 0x092c40c0, + 0x0505480e, 0x01370f37, 0x100b4037, 0x6e232b48, 0x0f367c24, 0x12157518, 0x22732b15, 0x30018215, 0x25733524, 0x00182406, 0x00190975, 0x3f3fe13f, + 0x41ea84e1, 0x102a07c7, 0x2b32e1f6, 0x2f33115d, 0xc2412b2b, 0x33112f05, 0x3232e110, 0x3031e110, 0x023e3225, 0xcd6c1537, 0x35233407, 0x15333737, + 0x11231533, 0x14011614, 0x2323020e, 0x77112311, 0x4a620643, 0x054a0806, 0x23240f3b, 0x5017071e, 0x4058353f, 0x419c9c24, 0x34d1d16b, 0x7c348cfe, + 0xb22f98cc, 0x7bbf86fb, 0x1abdfd3a, 0x2e5b8b5d, 0x8139aea4, 0x03080604, 0x22140c8a, 0x01486a46, 0xbd4d52bf, 0x56fe89d3, 0x89034e4c, 0x4d81a85b, + 0xca18c7fd, 0x01320db3, 0xecff3f00, 0xcb054a04, 0x86003900, 0x280712b4, 0xfb831936, 0x094b5108, 0x1919480d, 0x013b103b, 0x1323232c, 0x2e6f0d05, + 0x01286322, 0x133a2828, 0x10246023, 0x602c0824, 0x5f2d052d, 0x8f247f24, 0xff24ef24, 0x2d0f0524, 0x2d2f2d1f, 0x2d9f2d5f, 0x24062dcf, 0x162d242d, + 0x33740037, 0x195f1607, 0x3f00191d, 0xe13fe133, 0x20050642, 0x05d7425d, 0x10331130, 0x011132e1, 0x335d2f33, 0x3232e133, 0x2a421133, 0x09aa7a09, + 0x06071427, 0x14141514, 0x0b555517, 0x2e22232d, 0x35232702, 0x35342633, 0x82353634, 0x033e2208, 0x054f4233, 0x0803d308, 0x435e7645, 0xfeb00112, + 0x02010141, 0x92fe8101, 0x4b95b922, 0x853b3b87, 0x87b6735b, 0x94a41558, 0xa0940202, 0xb8875812, 0x4fa06172, 0x05773350, 0x8f633427, 0x0e0f895b, + 0x13091a0c, 0xaf891629, 0xa21a20b8, 0x87491f1c, 0x178979c1, 0x2e161d1e, 0xca7d8908, 0x312b4e90, 0x002b1f92, 0x8d000400, 0xdb05f8ff, 0x0300c105, + 0x2b001700, 0x86004800, 0x02010a40, 0xb4184639, 0x0200030e, 0x40f0ffb8, 0x9046704a, 0xd046a046, 0x0edf0446, 0x02100001, 0x00000e46, 0x0402460e, + 0x0fb42231, 0x04ef0104, 0x040204ff, 0x00b4404a, 0x31000131, 0x31203110, 0x31f031e0, 0x42310805, 0x3dfd2cfc, 0x270736fc, 0x1dfd13fc, 0x031909fc, + 0x00180106, 0xe13f3f3f, 0x6247e1f4, 0x5d5e2505, 0xde10e171, 0x11230482, 0x822f3917, 0x5d382a00, 0x3311385d, 0x3311e110, 0x06304511, 0x60470120, + 0x0f746a0e, 0x56220121, 0x51080aaa, 0x22232626, 0x33141506, 0x15373632, 0x0a050606, 0x039dd5fc, 0x2d6e012b, 0x3f447050, 0x2c2f516e, 0x3e447150, + 0xfe2f526e, 0x3c261133, 0x253c2a2b, 0x3c251111, 0x263c2b2a, 0x45cbfd11, 0x35345a79, 0x33487d5c, 0x1f212064, 0x5f672255, 0x235a33c2, 0xa8456323, + 0x98fb2905, 0x2d577f53, 0x537f572d, 0x7e080787, 0x233e5633, 0x33563e23, 0x213d5534, 0x01553d21, 0x80522692, 0x52845f5a, 0x6b0f1626, 0x7674140d, + 0x6b1011e5, 0x00001312, 0xff770002, 0x057b03ec, 0x002d00cb, 0x4055003a, 0x23702e32, 0x48141040, 0x05112323, 0x28353c06, 0x1014196e, 0x30112011, + 0x90118011, 0x18110511, 0x14763615, 0x00282811, 0x071e7630, 0x060b7500, 0x00190b06, 0x102f333f, 0x12e13fe1, 0x33332f39, 0x013232e1, 0x82c55d2f, + 0xd6102207, 0x201182c1, 0x0771432b, 0x030e3330, 0x022e2223, 0x06063535, 0x36363507, 0xc5491137, 0x0701090a, 0x021e1411, 0x22233413, 0x1115020e, + 0x6f02033e, 0x1e2e3920, 0x26046403, 0x3a466946, 0x2e30516a, 0x5f343161, 0x68401c2d, 0x3d57364b, 0x7c5c3521, 0x37241147, 0x29206663, 0x4e360917, + 0x16771833, 0x533b5232, 0x25305a83, 0xe7638854, 0x790c1c11, 0x010f1e0e, 0x536c3bee, 0x6f4f2a31, 0x86a66345, 0xd3fe2668, 0x213b5130, 0x1bbc2104, + 0xfe2a4532, 0x624e216a, 0x00040079, 0x070000c7, 0x00b60589, 0x002b0017, 0x003b0037, 0x0e7240ba, 0x005a1501, 0xe12c3939, 0x01001022, 0x9f0100b0, + 0x00300100, 0x00020040, 0x0a220022, 0x0f18e132, 0x2f3a1f3a, 0x3a3a033a, 0x180118ef, 0x3d6f3d67, 0x3dcf3dbf, 0x013d4003, 0x0903080c, 0x3c640a5a, + 0x351de52f, 0x1dcf27e5, 0x1def1ddf, 0x06401d03, 0x270f480b, 0x275f271f, 0x277f276f, 0x060627ef, 0x271d271d, 0x06100316, 0x0b034818, 0x38e53903, + 0xf0ffb80e, 0x2b0d82b6, 0x120a010e, 0x33333f00, 0x3fe0332b, 0x39280482, 0x5e2f2f39, 0x105d2b5d, 0x08c69318, 0x5d5d3229, 0x325de610, 0x5710712f, + 0x0a8208d7, 0x2305ce4c, 0x23213031, 0x0e897718, 0x35032e24, 0x9d423311, 0x08741811, 0x03230809, 0x04152135, 0x87fdcda8, 0x04040608, 0x02cfa605, + 0x04030676, 0x01020301, 0x29e102a4, 0x3f446d4d, 0x832c4d6b, 0x6b3e3c07, 0x42fe2c4e, 0x47515148, 0x48515147, 0x04f00163, 0x414c4dba, 0xe7fc398e, + 0x18fbb605, 0x2409cfd0, 0x8253b9fc, 0x969f1859, 0x717e080c, 0x72717373, 0x1ffd6d6d, 0x02009393, 0xe5022500, 0xb6055005, 0x20000700, 0x5d40a300, + 0x1301c400, 0x11c4100a, 0x06d006c0, 0x6f0306e0, 0x06300106, 0x06500640, 0x01061f03, 0x20010604, 0x0211d011, 0x11110601, 0x03030106, 0x1815191e, + 0xaf179fc4, 0x22170217, 0x222f220f, 0x2203223f, 0x48181540, 0x120f4022, 0xef03cf48, 0x1f030203, 0x0c200909, 0x07094818, 0x1804c803, 0xe0ffb814, + 0x0e820c40, 0x0811142e, 0x12150101, 0x3f000304, 0x2f333333, 0x2b350382, 0x32e11033, 0x33112b33, 0x2b5d2f01, 0xd6105d2b, 0x3232e15d, 0x05dd4332, + 0x4605744c, 0x01340727, 0x35231123, 0x01231521, 0x031e2303, 0x11231115, 0x33131333, 0x343b0682, 0x2337023e, 0x7f680103, 0xc70a02c4, 0x07ba4002, + 0x01010201, 0xbfb4ba7b, 0x82017fb2, 0x06640800, 0x02e502c3, 0xfd6c6c65, 0x1025029b, 0x06181e22, 0xd10249fe, 0x2702d9fd, 0xac012ffd, 0x23231e09, + 0xffdbfd0c, 0x004e00ff, 0x05a60500, 0x010602cd, 0x00000076, 0xff660002, 0x048b04dd, 0x00220048, 0x403b002f, 0x1e4a2321, 0x132f3111, 0x0105104a, + 0x181d1d05, 0x2f2b4e12, 0x2f022f3b, 0x4e29182f, 0x4e180f0c, 0x2409b25e, 0x3911e15d, 0x23cb822f, 0xde1032e1, 0x0ae7c418, 0x3233042b, 0x2115021e, + 0x33031e11, 0x08af8232, 0x030e1764, 0x032e1113, 0x020e2223, 0x79021107, 0x4586c682, 0x76664c2c, 0xc2713f80, 0xc5fc518e, 0x584d4016, 0x5e744a2e, + 0x2448224d, 0xcc8f6e53, 0x5d4d3b13, 0x49573335, 0x5e23183c, 0x636ecc9d, 0x3c5c7ea0, 0xd1934f1d, 0x189cfe83, 0x2015222c, 0x2937573c, 0x2c4d6539, + 0x15018b02, 0x16232a14, 0x172a2113, 0xd582e9fe, 0xff534208, 0x05d305ec, 0x002600b6, 0x0000147b, 0x02170227, 0x0100005e, 0x03400207, 0x00b3fd62, + 0x041f4030, 0x19270203, 0x0111f401, 0xd00111e4, 0x11b00111, 0x0111a001, 0x11011130, 0x0f01592f, 0x5d5d0159, 0x05844111, 0x3f003525, 0x82353535, + 0x84332051, 0x82c92051, 0x86752051, 0x8a8b2051, 0x403c2251, 0x08518228, 0x01194923, 0xd00133f0, 0x33c40133, 0x0133b401, 0x940133a0, 0x33600133, + 0x01333001, 0x33013324, 0x0f017b2f, 0x825a897b, 0x205d8860, 0x825d844f, 0x3d0221af, 0x3d205d98, 0x273f5d82, 0x0127d001, 0xb40127c4, 0x27a00127, + 0x01279401, 0x30012760, 0x27240127, 0x6f2f2701, 0x956f0f01, 0x8871205d, 0x423f215d, 0x20050d41, 0x22bb8a39, 0x82224034, 0x191f3dbb, 0x0109f401, + 0xcb0109eb, 0x09b40109, 0x01099b01, 0x2b01097f, 0x2f090109, 0x510f0151, 0xb385578a, 0x02003408, 0xecff6200, 0xc5053b04, 0x43002b00, 0x21403b00, + 0x00471933, 0x45404557, 0x01450f01, 0x21483f06, 0x3844560c, 0x2c13134f, 0x27501c21, 0x07502c04, 0x483f0016, 0x2f290501, 0xf61001e1, 0x5d5ee132, + 0x0594685d, 0x0e14013a, 0x2e222304, 0x3e343502, 0x16323304, 0x35343617, 0x22232634, 0x3507020e, 0x2605da60, 0x043e3201, 0x82032e37, 0x047d0812, + 0x021e1415, 0x41203b04, 0x6db18a65, 0x22538c6a, 0x73513217, 0x935b6299, 0x898b022d, 0x4143441f, 0x4b43181b, 0xa67d254f, 0x9efd2a63, 0x43515e35, + 0x0a0a2535, 0x2a493b29, 0x3a4f663e, 0x2d151225, 0x6aa60346, 0x8dbcd4e1, 0x8f6e4252, 0x8d8d3c4c, 0x4f3d6583, 0x0b2a1345, 0x160cc9be, 0x0cae131f, + 0x590a1117, 0x73fcc496, 0x7a684d2c, 0x45284385, 0x51301e33, 0x2f6e6f68, 0x24405632, 0x08f38200, 0x0000292a, 0xb6056204, 0x0e000500, 0x11405800, + 0x09090102, 0x605b0e05, 0xb0047004, 0x0404f004, 0xc0ffb804, 0x0a062740, 0x10040448, 0x11556118, 0x055b0d37, 0x12055f0d, 0x110a2009, 0x03010948, + 0x2b333f00, 0x2f01e13f, 0x051f4ae1, 0x4de15d21, 0x3b0805dd, 0x01373031, 0x21150133, 0x27262601, 0x03070606, 0xbe012921, 0xfbc001bb, 0x207702c7, + 0x2a110f2d, 0xa602fa1d, 0xfa450571, 0x9a036fb9, 0x4b4ba861, 0x04fd5ba8, 0xc7000100, 0x270514fe, 0x072e9982, 0x11403700, 0x65075a00, 0x30090009, + 0xdd684009, 0x83092005, 0x140f2f97, 0x5a034818, 0x02086404, 0x0403055f, 0xe6681b00, 0x5d2b2b08, 0x31e1f610, 0x21110130, 0x03822311, 0xfd6d0430, + 0x6004ba14, 0xfc0614fe, 0xa20704f9, 0x5d825ef8, 0x14fe4a24, 0x5d82e304, 0x5c000b2f, 0x5b080b40, 0x02010670, 0x00060206, 0x2757820a, 0x480e09b7, + 0x070d0a0a, 0xe02b6382, 0x180f0940, 0x00030948, 0x840d0c00, 0x18132571, 0x02020848, 0x07c05e18, 0xe1207182, 0x07c05e18, 0x33112b32, 0x33332f18, + 0x3311322b, 0x39122b2f, 0x5d2f2f39, 0x13208282, 0x0ac15e18, 0x70024a3d, 0x4804a0fd, 0x3a02bcfc, 0x9b03b0fd, 0x037314fe, 0x722b0392, 0xfc09fda4, + 0x8200a49d, 0x66240893, 0x02048702, 0x03001d03, 0x1f403200, 0x00960502, 0x01008b01, 0x56010079, 0x004b0100, 0x01003801, 0x09010014, 0x00242782, + 0x00b301ad, 0x0ba0ad18, 0x31ce102e, 0x21351330, 0x9c036615, 0x96968702, 0x25304b83, 0xc504f2ff, 0x0800a006, 0x13402c00, 0x05060001, 0x0739de83, + 0x03081008, 0x0404ae03, 0x2f000007, 0xe12f392f, 0x382f2f01, 0x19393933, 0x08ba822f, 0x33331122, 0x23053031, 0x21352301, 0x02330113, 0xebfe8573, + 0xe52901b4, 0x0e920002, 0xfd8f0a03, 0x00ac0569, 0x79089982, 0x05910177, 0x000e0431, 0x00330023, 0x40760043, 0x0117494f, 0xf0010d48, 0x452f0145, + 0x3a02455f, 0x6a274a27, 0x372a0327, 0x081a3701, 0x773f0427, 0x022f972f, 0x1220aa2f, 0x12021230, 0x3f013f78, 0x2a3400ab, 0x243a17ae, 0x273708ae, + 0x0517041a, 0x0d100d00, 0x0d0d0702, 0x01179f1f, 0x17011720, 0x5d5d2f00, 0x5e2f3333, 0x1712335d, 0x1032e139, 0x2f0132e1, 0x5d2f5de1, 0x0f825de1, + 0x00825d20, 0x5d30312b, 0x0e14015d, 0x26222302, 0x06f84827, 0x023e3426, 0x17163233, 0x08055b43, 0x3632058b, 0x23262637, 0x15020e22, 0x01021e14, + 0x16070622, 0x3e323316, 0x2e343502, 0x2b310502, 0x5d426d4d, 0x461d419b, 0x412b534e, 0x2b2d4f6e, 0x55436f4e, 0x441d3e9e, 0x4230574f, 0xfc2b4d6d, + 0x346c3f7b, 0x28456b31, 0x15182c40, 0x7c02412c, 0x33376b3f, 0x4027446c, 0x2e19182d, 0x3fcd0240, 0x69345772, 0x384f3073, 0x75522c1e, 0x56734148, + 0x30706b31, 0x2d1f384e, 0x57f97552, 0x1d5a5e61, 0x24264433, 0x011e3242, 0x5d61576a, 0x080d825c, 0x43262744, 0x01001c31, 0x14fe1000, 0x14060603, + 0x37002300, 0x25102340, 0x140225d0, 0x04060104, 0xac0d0401, 0x0901151b, 0x10150115, 0x021e201e, 0x12ae191e, 0x00ae071c, 0xe13f0000, 0x2f01e13f, + 0x5d5d335d, 0xf68432e1, 0xe2820120, 0xd9861520, 0x72181120, 0x3b080f93, 0x02023e34, 0x164b2283, 0x33243d12, 0x32102742, 0x244a7c59, 0x3e14174b, + 0x2a453323, 0x79572f12, 0x09091406, 0x27110993, 0xfa2d5441, 0x56865ed7, 0x93080b29, 0x40251008, 0x27053054, 0x282a0e82, 0x66000200, 0x02047b01, + 0xa1822504, 0x00474308, 0x412e404b, 0x4910491d, 0x0a102e01, 0x0a020a20, 0x31ad2940, 0xad1743af, 0x1caf1f0a, 0x0ddfad05, 0x0dff0def, 0x0f400d03, + 0x0d0d4812, 0x432ead3b, 0x333f00b3, 0x2b2f33e1, 0xf533e15d, 0xf510e132, 0xba8433e1, 0x32ce1026, 0x2e013031, 0x22051d47, 0x18333635, 0x20105aba, + 0x271b9a03, 0x37251202, 0x1c16292d, 0x1a76ba18, 0x219a2f20, 0x1d97612e, 0x01433732, 0x0d1610bc, 0x2c211305, 0x1398ba18, 0x10ae0123, 0x281c8215, + 0xa21a2c20, 0x190e056d, 0x200d8514, 0x082a852d, 0x00010074, 0x04a40066, 0x00040502, 0x40a60013, 0x0e0d0a11, 0x12091211, 0x04030012, 0x08130807, + 0xffb81309, 0x094f40f0, 0x13091310, 0x0b100609, 0x01154015, 0x0106c601, 0xa90106bb, 0x06860106, 0x01067b01, 0x42010668, 0x06390106, 0x08090601, + 0xad040d08, 0x12121307, 0x0ead0011, 0x032f031f, 0x01037f02, 0x03100300, 0x03030602, 0x0107f00a, 0x076f070f, 0xfd420702, 0x715d2f08, 0x3232e133, + 0xe1103311, 0x33113332, 0xbb472f01, 0x5d5d2205, 0x05a86333, 0x2f2f3929, 0x33113838, 0x82c4877d, 0x33012200, 0x27078410, 0x23013031, 0x21132135, + 0x17260382, 0x21153307, 0x03822103, 0x01272a08, 0x3e01f85e, 0x0149fe79, 0x698a85fc, 0x7bc1fefa, 0x00feba01, 0xba018981, 0x95040196, 0xe03b1b01, + 0x96fcfe95, 0x0039eafe, 0x08ef8202, 0x02040021, 0x0600dd04, 0x52000a00, 0x00093240, 0x010c400c, 0x01014008, 0x05010201, 0x6f060305, 0x18007f00, + 0x8433b5e7, 0x303135b4, 0x01350125, 0x35020915, 0x02041521, 0x9c0364fc, 0xdf0221fd, 0xee210783, 0xbee71801, 0x71fe2408, 0x92009696, 0x85052089, + 0x01062a89, 0x01040506, 0x6f000301, 0x43e71806, 0x21898635, 0x8a830113, 0x82150121, 0x0266268a, 0x031efde2, 0x2c87839c, 0x42018f01, 0xfea26a01, + 0x58fe661f, 0x088785ee, 0x00006d39, 0xc3053f04, 0x09000500, 0x36405d00, 0x05090102, 0x07090704, 0x00ac0603, 0x010bff0b, 0x0b500b40, 0x0bb00b80, + 0x0f050bc0, 0x020b2f0b, 0x0310aa08, 0x08030301, 0x82080600, 0x07022201, 0x302c82ad, 0x2f0002ad, 0x12e13fe1, 0x2f3d3939, 0x1133112f, 0x05ec5433, + 0x105d5d23, 0x211483de, 0x12823311, 0x31333108, 0x23010130, 0x09330101, 0xfe3f0403, 0x3efe4c3c, 0x014cc201, 0xfecffe0c, 0x023101cf, 0x021ffde1, + 0xfde402df, 0xfe00021e, 0x00fefd00, 0x1d00ffff, 0x2d089782, 0x001f0617, 0x00490026, 0x00070100, 0x00a2024c, 0x40240000, 0xaf010218, 0x1d50011d, + 0x011d1f01, 0x1d011d0f, 0x40012faf, 0x2f0f012f, 0xff495d01, 0x35352106, 0x06203d86, 0x4f203d8a, 0x22223d84, 0x3c8e1740, 0x40012126, 0x210f0121, + 0x003f3c89, 0x04cf0001, 0x06cd03d9, 0x00150017, 0x0029403f, 0x02172017, 0x17cf17af, 0x70173002, 0x820f0217, 0x0000291f, 0x020a300a, 0x7f0a0a06, + 0x40360c82, 0x00480906, 0x058e1000, 0x33e12f00, 0x335d2b2f, 0x5d5e2f01, 0x0a5a2f33, 0x05bd4506, 0x4b332721, 0x56820649, 0x5d314308, 0x8c67648d, + 0xaa052958, 0x4c321b05, 0x36492c35, 0x17060622, 0x2951764e, 0x50775027, 0x10294939, 0x35482b13, 0xbcff0100, 0x640114fe, 0x13004a04, 0x13402300, + 0x15201510, 0x0c470f02, 0x540c0303, 0xcc180d14, 0x5c1808af, 0x312207c1, 0x4d181330, 0x112a0a21, 0x0e141133, 0x3f304202, 0xcc181a17, 0x8418099d, + 0x2c080a7d, 0x18fbf404, 0x2f577b4d, 0x01010000, 0x02cd0487, 0x00140679, 0x4019000d, 0x3f85050c, 0x0c060106, 0x05920c00, 0xe53f0000, 0xdd332f01, + 0x906e185d, 0x87013a0c, 0x0e111209, 0x1f06b404, 0x60162e29, 0x4d1ee704, 0x14215051, 0x56564e19, 0x264b8220, 0x023bfe6f, 0x8283ff75, 0x4016284b, + 0x00000c09, 0x83068505, 0x822f2049, 0x32e12548, 0x3031332f, 0x0a817518, 0x1a0b6f32, 0xb2041318, 0x362c1f06, 0x56fe621d, 0x53544c19, 0x4d234882, + 0x83215657, 0x047d2695, 0x068302d9, 0x22498221, 0x850a4017, 0x92052149, 0x93830782, 0x0e384a86, 0x35230703, 0x3337033e, 0x1a0c8302, 0xb2041218, + 0x372d1f05, 0x0606621c, 0x15214a84, 0x08938218, 0x0200212b, 0x39022500, 0xc7057f02, 0x1d000b00, 0x19402a00, 0x1f0ce106, 0x1f7f1f4f, 0x06401f02, + 0xe100480a, 0x1be50916, 0x11e503de, 0x068b46df, 0x5d2be124, 0xf282de10, 0x4e141321, 0x045909e9, 0xb816240d, 0x824e5147, 0x0f925800, 0x049a952b, + 0x9fa1a502, 0x9f9fa5a7, 0x065058a5, 0xa96c6c26, 0x00ec3c74, 0x0c3c8582, 0x8f024a02, 0x0a00bc05, 0x46001500, 0x02092a40, 0x03070be1, 0x175f1703, + 0x1702178f, 0x25088983, 0x0105e115, 0x0f09e504, 0x2f0b1f0b, 0x0b08030b, 0xe50f020b, 0xdd02dc07, 0xe13f3f00, 0x5e2f3912, 0x32e1335d, 0x9d822f01, + 0x08062651, 0x0130315f, 0x35231523, 0x33013521, 0x35213311, 0x0e373634, 0x02070703, 0xfe8f7d8f, 0x8d790189, 0x03f4fe7d, 0x16140503, 0x039b0918, + 0x6fc0c00a, 0xcdfd4302, 0x31632ac3, 0x282a250b, 0x0000f00f, 0x023b0001, 0x05660237, 0x002400b6, 0x2117404a, 0x1d1e2222, 0x14200b1d, 0x4f2605e1, + 0x02267f26, 0x35938326, 0xc0ffb80b, 0x18121140, 0xe5170b48, 0x21110000, 0x11dc1ee5, 0x294108e5, 0x29868205, 0x2b2f01e1, 0xde105d2b, 0x938433e1, + 0x82331121, 0x1e322693, 0x06141502, 0xe8461823, 0x224c080c, 0x2707020e, 0x21152113, 0x01363607, 0x4f6b3d42, 0x3fa1a62d, 0x3c1a2c79, 0x55183b3d, + 0x0d595f5f, 0x0e252725, 0xba012143, 0x1412befe, 0x236d0439, 0x8c416544, 0x8d1a1c9d, 0x0a131b12, 0x554d584c, 0x02070604, 0x7ba8012b, 0x000603d7, + 0x3408d141, 0x001d00d5, 0x4038002d, 0x210a1020, 0x4f2f00e1, 0x022f7f2f, 0x2eb5832f, 0x0ae12915, 0x1915e424, 0xde0f1019, 0x8405e51e, 0x393323ae, + 0xae82332f, 0x8432e121, 0x391221af, 0x7753a982, 0x1737280a, 0x3307030e, 0x82333636, 0x320522bd, 0x06c74c36, 0x14157508, 0x7f02021e, 0x446f4e2a, + 0x2f526e40, 0x6eb27e45, 0x607f4f2d, 0x1b0b0f40, 0x5a364a63, 0xdbfe2440, 0x474d5444, 0x192d3f27, 0x033d2d19, 0x506f4166, 0x80582d2d, 0x8fb36e53, + 0x1b6d276d, 0x3b604f40, 0x4825312b, 0x565cf769, 0x29195a52, 0x492c1e37, 0x01001d35, 0x4a022f00, 0xb6056402, 0x38000600, 0xff0000b9, 0x001f40f0, + 0xe1010200, 0x084f0805, 0x0802087f, 0xd030c183, 0xf002e002, 0x02020302, 0x00dc03e5, 0x3f3f00dd, 0x5d20ba82, 0x1135b984, 0x31382f39, 0x21011330, + 0x01152135, 0xfe40018d, 0xfe350262, 0x085182bf, 0x647bf125, 0x0300f8fc, 0x39023100, 0xc7057102, 0x34002500, 0x77004400, 0xe1382240, 0x05e14221, + 0x1c323d0a, 0x82210504, 0x2c172a01, 0x4f460fe1, 0x02467f46, 0x086a8346, 0x17e12638, 0x40c0ffb8, 0x48181527, 0x3d1c0a17, 0x5b324b32, 0x9b326b32, + 0x0532ab32, 0xb6351432, 0xd63dc63d, 0x003d033d, 0xdf14e529, 0xde00e535, 0x3fe13f00, 0x5d3911e1, 0x03841211, 0x2f013924, 0x9884e12b, 0x3939122b, + 0x17122f2f, 0x10e11039, 0x070642e1, 0x07020e22, 0x18053874, 0x2607e174, 0x3435032e, 0x4303023e, 0x2e2e0659, 0x06272702, 0x06221306, 0x021e1415, + 0x1b823e17, 0x0126aa08, 0x465e3452, 0x3427162a, 0x303e221e, 0x694d2a1c, 0x19968b3f, 0x1b1f382a, 0x2b13232e, 0x4a625f48, 0x164b4a48, 0x0f213727, + 0x38944241, 0x2d20123f, 0x202c181a, 0xc7054113, 0x3854371b, 0x28323e25, 0x372d1311, 0x5d392a45, 0x73832442, 0x2b38452a, 0x352b1411, 0x5338253e, + 0x68fd1c37, 0x3b46463b, 0x2027301e, 0x4d22060f, 0x3637e801, 0x1d242a1b, 0x231c0c0d, 0x37361c2c, 0x21000200, 0x7b023902, 0x2500c905, 0x3b003500, + 0x11312240, 0x001c09e0, 0x7f374f37, 0x40370237, 0x29480a06, 0xe42c1ce1, 0x05171711, 0xde21e526, 0x0657420c, 0x4212e121, 0x2b250658, 0x11de105d, + 0x14431839, 0x098b4508, 0x4b233721, 0x1e220bbf, 0xef832502, 0x0908ab4b, 0x217b021d, 0x1981a25a, 0x36151540, 0x406c5319, 0x0d09031d, 0x263d3024, + 0x2444603c, 0x436c4b29, 0x30547241, 0x5644cbfe, 0x3f264c4a, 0x2a15182d, 0x6042043e, 0x085b93bb, 0x0a0d7d07, 0x3d725735, 0x111b2412, 0x41664725, + 0x2d516f42, 0xac93612f, 0x584c585e, 0x1a332919, 0x243b4824, 0x00160000, 0x0781fe54, 0x00ee05c1, 0x000b0005, 0x00170011, 0x001f001b, 0x00270023, + 0x002f002b, 0x00370033, 0x003f003b, 0x00470043, 0x005f0053, 0x0078006f, 0x00900081, 0x345940e4, 0x381c202c, 0x7a515718, 0x67746f70, 0x7e826464, + 0xc051706b, 0x0351d051, 0x6b6b6f51, 0x5d03516f, 0x5f8c4f89, 0x8c8c028c, 0x09242844, 0x4b505d17, 0x4b024b60, 0x313d414b, 0x422a0c00, 0x32263e46, + 0x6f8f8f86, 0x70706779, 0x6f7a607a, 0x70484854, 0x026f806f, 0x6f016f61, 0x40c0ffb8, 0x480c0725, 0x5a606f6f, 0x788a4e4e, 0x602f601f, 0x606f603f, + 0x01606004, 0x12181c2c, 0x2135390c, 0x01010f07, 0x2f000107, 0x53335d5e, 0x33230673, 0x832f3912, 0x332f280c, 0x2b2f3311, 0x83335d5d, 0x44112008, + 0x2f200673, 0x03830d82, 0x822f0121, 0x3333212d, 0x08882882, 0x2006d75e, 0x82468511, 0x843e8206, 0x30313c2d, 0x15211113, 0x35251523, 0x35231121, + 0x15331101, 0x35211533, 0x11333533, 0x82213521, 0x15212209, 0x24078201, 0x33112301, 0x87038211, 0x2007830b, 0x20178633, 0x83178335, 0x26222b03, + 0x37363435, 0x14151632, 0x39442706, 0x15062506, 0x33011614, 0x07221284, 0x19831615, 0x13232323, 0x221c8533, 0x86151523, 0x35052309, 0x0a831616, + 0x23086382, 0x22230614, 0xc02f0154, 0x3001ce05, 0x6f00f96d, 0xc30e05c0, 0x0149fd6d, 0x01e1fb11, 0x01f2fe0e, 0x6db7040e, 0xfb310082, 0xfc1001c2, + 0x026f6f30, 0x771001c0, 0xa8fa1101, 0x2900826f, 0x6d6dfe06, 0x877f99fa, 0x03837f87, 0x3f483e08, 0x4245483f, 0xac9f0142, 0x2d2d706d, 0x5e6d3338, + 0x2e427bcf, 0x3b302924, 0x2625314a, 0x100e0134, 0x31251420, 0x3d5f687d, 0x3001be04, 0x6fc1c16f, 0xf9c1d0fe, 0xc22f0102, 0xfec26d6d, 0x326482d1, + 0x6ffe066d, 0x01a8fa6f, 0x0102020e, 0x6d3bfa0f, 0x82a6016d, 0x824a207f, 0x6f4e0869, 0x10012ffc, 0xfd0f0179, 0xfe100168, 0x918e9f8a, 0x919c019b, + 0x67689f8e, 0x66665e5e, 0x01675e5e, 0x315343ea, 0x0b040844, 0x59513a44, 0x20226201, 0x9ae31d22, 0x2a20252b, 0x050366fc, 0x92013224, 0x645e72fe, + 0x54000300, 0xaa07c1fe, 0x09821406, 0x00233e08, 0x4050002f, 0x23230428, 0x302a2024, 0x032a402a, 0x244f2a2a, 0x02242401, 0x020b0b1c, 0x23021515, + 0x012d3023, 0x27272d2d, 0x10101903, 0x2f190003, 0x332f1833, 0x332f3311, 0x2f335d2f, 0x830e8401, 0x8203820d, 0x825d200f, 0x31333706, 0x05030930, + 0x37363435, 0x34353636, 0x2223022e, 0x1707020e, 0x8d413636, 0x06062306, 0x7d441515, 0x26720807, 0x03062223, 0xfcac03fe, 0x0356fc54, 0x634c21eb, + 0x835b314d, 0x575a2b51, 0x44522252, 0x3e3f387e, 0x4a455227, 0x4446471b, 0x46444747, 0xfc140647, 0x0357fc56, 0x2c2ffba9, 0x834c3a3e, 0x4a6b4559, + 0x231b1027, 0x2e22b214, 0x44312f3a, 0x50793541, 0x3eedfe3b, 0x403e4949, 0xff004949, 0xfebcffff, 0x06550214, 0x02260221, 0x00000037, 0xfe4c0107, + 0x178200bb, 0x69170021, 0x0223053f, 0x82070206, 0x02560817, 0xecff0a00, 0x2b06b204, 0x4f000c00, 0x47407500, 0x10430d4d, 0x083b003e, 0x1a434347, + 0x004f473b, 0x10100110, 0x0151a051, 0x3301513f, 0x101a0047, 0x031a201a, 0x2950221a, 0x4e4f4f3e, 0x29004e00, 0x29302910, 0x29502940, 0x4e290605, + 0x05384e29, 0x38014850, 0xb3531550, 0x58122005, 0x11290502, 0x32e11033, 0x2f01e110, 0x06ad6c5d, 0x11e13324, 0x03822f39, 0x82113921, 0x30312521, + 0x23032e01, 0x27058345, 0x15161605, 0x06060214, 0x7f06d553, 0x3627082d, 0x1e323336, 0x50141502, 0x3326056c, 0x34111232, 0xcb452726, 0x08188305, + 0x1533172a, 0x390d6a03, 0x4c305b4d, 0xab6a2e56, 0x02023c01, 0x83c48140, 0x2256926f, 0x1f0a0b0a, 0x1036181f, 0x36642525, 0x132c4532, 0x60080f82, + 0x3a4e3015, 0x0202a4a4, 0x4396f2ae, 0x597f5127, 0x4b75a168, 0xd1038f12, 0x3d74aa6c, 0x69384858, 0x168a3352, 0xfe9f1f3a, 0x3773c9ee, 0x28457d5f, + 0x184b595d, 0x0a0f212d, 0x1c1a117f, 0x23284432, 0x2d615d56, 0x1f364a2a, 0x30013201, 0x02143e17, 0x519a784b, 0x2e527043, 0x8bdf9c54, 0x01000089, + 0x08008200, 0x0548047d, 0x002200c3, 0xaf1b408f, 0x0224ef24, 0x0c094024, 0x21ab2248, 0x01219801, 0x1b012140, 0x210f0121, 0xffb82101, 0x214440f0, + 0x1b1f0021, 0x0d0f010d, 0x12200d01, 0x0d9f4816, 0x7d020daf, 0x0d6b010d, 0x010d5a01, 0x2b010d4f, 0x020d3b0d, 0x5a1e0d0d, 0x1f871f77, 0x4f031f97, + 0x1f00011f, 0x07021f10, 0x1f001d1f, 0x121f0321, 0x00040a11, 0x3f3fc13f, 0x01393912, 0x5d5d5e2f, 0x4e32e15d, 0x2b2706c6, 0x39117171, 0x82382f33, + 0x5d5d2a13, 0x315d2b33, 0x033e0130, 0x05f35c37, 0x0806e150, 0x050e0759, 0x11231107, 0x1d023301, 0x3c3f3d19, 0x352f1618, 0x2b232940, 0x0d200d11, + 0x23201c0b, 0x32280d13, 0x13323636, 0xcb42febb, 0xa84bdb02, 0x282c89a0, 0x0914273d, 0x05039108, 0x232a1707, 0x806e5518, 0xfd3c8585, 0x032f02e3, + 0x00020087, 0x06ecff12, 0x004a0460, 0x823c001c, 0x476e08fb, 0x012f6719, 0x2cd5472f, 0x012cb701, 0x9a012ca9, 0x2c03012c, 0x4837032c, 0x12bb12ab, + 0x3e121202, 0x54013e14, 0x843e643e, 0xb43ea43e, 0x3e40053e, 0x3e300201, 0x013e0f01, 0x03004822, 0x03300310, 0x03500340, 0xb8030605, 0x1540c0ff, + 0x03481512, 0x2d2d001a, 0x080e1d27, 0x320f0b50, 0x00165027, 0x323f0016, 0xe13f32e1, 0x39123232, 0xfe82122f, 0x5d5e2b31, 0x5f5d5de1, 0x11715d5d, + 0xe15d2f33, 0x822f3911, 0x825d200b, 0x31393213, 0x26220530, 0x023e3435, 0x37352137, 0x1e231521, 0x06244a03, 0x06062323, 0x235c1803, 0x3335230a, + 0x1b471415, 0x278b0808, 0xc3b62902, 0x1a2b2012, 0x0586ebfe, 0x2618f3c8, 0xb5c40f1b, 0x0b1f8b6a, 0x16ba8b1f, 0x1d121f28, 0x2e2d4b36, 0xb3162c44, + 0x4b2d5262, 0x190f1d36, 0xea141524, 0x7e7d39f3, 0x504a387b, 0x7e7b389a, 0xeaf3397d, 0x575b5b57, 0x7636c403, 0x623a7a79, 0x29214e83, 0xb0396248, + 0x218a82b0, 0x3a62834e, 0x3676797a, 0x00ffff00, 0x060000c7, 0x0275072f, 0x00300026, 0x00070100, 0x01790176, 0x40130054, 0x0527010b, 0x1a4b0126, + 0x6f0f0920, 0xae200a19, 0x87222d82, 0x2d822106, 0x2d865020, 0x2d843f82, 0x26113a28, 0x332d7a01, 0x2d8a2b16, 0xd5fd0026, 0xbc05dd04, 0x24202d82, + 0x022f2d83, 0x001b015b, 0xb70d0000, 0x1f010203, 0x83070415, 0x83352029, 0xfd5e2683, 0x049c03d5, 0x2027825e, 0x21278544, 0x2786bc00, 0x183d1421, + 0x2508f5ac, 0xd3feffff, 0x7918ecff, 0x02230bef, 0x8240fe5c, 0x3f300827, 0x2d0203b6, 0x35020303, 0xb2c0ffb8, 0xb8480f09, 0x1a4021ff, 0x0a0a3535, + 0xb0000125, 0x00800100, 0x01007f01, 0x40010050, 0x001f0100, 0x5d110001, 0x35270084, 0x352b2b35, 0x823f0035, 0x02003203, 0xd5fd7300, 0x83ff3702, + 0x1f001300, 0x28403a00, 0x517f1814, 0x1d200810, 0x1005008c, 0x40053005, 0xa0055005, 0x0705f005, 0x8c170506, 0xe12f000f, 0xe15d5ed4, 0xe15d2f01, + 0x204b7f18, 0x37022008, 0x31543d23, 0x203b5232, 0x32523b20, 0x233e5430, 0x32314074, 0x3138393f, 0x33aefe40, 0x181d3851, 0x8212bb82, 0x04932899, + 0x05d90268, 0x820d00c7, 0x40422b99, 0x0e301509, 0x0e020e40, 0xec821a11, 0x1c403108, 0x1a481009, 0x010d2b1a, 0x0d140d04, 0x05060d02, 0x3f0c050c, + 0x5f114f11, 0x1d110311, 0x5dcc2f00, 0x2f2f3939, 0x5dcd2f01, 0x2b2f325d, 0x395dcd33, 0x2f058643, 0x030e1533, 0x34252307, 0x06153736, 0x1e141506, + 0x3d06b44c, 0x190bb001, 0xcf081618, 0x3e383012, 0xe3fe521f, 0x393c7a78, 0x321f251f, 0x04453a2f, 0x7d181e89, 0x7838094a, 0x4c1f734e, 0x13182e16, + 0x1c1a1012, 0x00462725, 0x1d00ffff, 0xb9060000, 0x08076f50, 0x0027003a, 0x00a20249, 0x00070100, 0x0044054c, 0x40380000, 0x8f020326, 0x39700139, + 0x01394001, 0x0f01392f, 0x01390139, 0xb0011fe0, 0xaf1f011f, 0x4b70014b, 0x014b4001, 0x5d014b0f, 0x2005c450, 0x05a34135, 0x2107c950, 0x5992a806, + 0x59844f20, 0x25403622, 0x3d295899, 0x013d7001, 0x0f013d40, 0x08588f3d, 0x0002004a, 0x06ecff7d, 0x00140625, 0x00340020, 0x1b2c404b, 0x20091306, + 0x2b01015b, 0x3667095b, 0xbf0136c0, 0x36700136, 0x5f362f01, 0x5b210236, 0x06356613, 0x5f300e1b, 0x26041820, 0x00130e5f, 0xce3fe13f, 0x393912e1, + 0xe1f61001, 0x5d20b182, 0x33220682, 0x5146e12f, 0x0e172306, 0x4b460703, 0x26262708, 0x12343502, 0xbc563636, 0x01352405, 0x56021e14, 0x232e07a9, + 0x06020e22, 0x280c0e17, 0x2b3f5a3f, 0x7918512d, 0x280808a0, 0xec9ea4ef, 0x19312951, 0x34f2fb08, 0x7272a56b, 0x32326ba5, 0x7272a46a, 0x06346ca6, + 0x703c1614, 0x59184c61, 0xfeaa7fd8, 0xaa7918eb, 0x666f2b0b, 0x5d4a350c, 0x89c9fc34, 0xee1899db, 0x71260f75, 0xf404ecff, 0xe982f204, 0x002c2d08, + 0x172c404a, 0x1e19194a, 0x48270a12, 0x00100000, 0x00000702, 0x902e102e, 0xb02ea02e, 0x4821042e, 0x122d560a, 0x502a051e, 0x24100f17, 0x2006fa7a, + 0x24e988c6, 0x5e2f3311, 0x820d835d, 0x0d434eec, 0x3320de86, 0xf57afb85, 0x0423080b, 0xb27d432d, 0x7fae676f, 0xb37c4347, 0x3fa9646f, 0x0619342e, + 0x2d100fc6, 0x2039563f, 0x8900fd24, 0x83879a9a, 0x02660803, 0x91d58927, 0xd5914c4c, 0x91d38889, 0x0d44474b, 0x335d4b37, 0x5e784a17, 0x9e411443, + 0xd3d3d15e, 0xd0d0d0d1, 0x00010000, 0x06ecffb8, 0x0014064e, 0x40510024, 0x085b0632, 0x015a2308, 0xb0010e9f, 0x0eaf010e, 0x260e0e01, 0x26802670, + 0x5f0326f0, 0x26000126, 0x1b022610, 0x2564185a, 0x240d0d01, 0x1e031906, 0xbb41135f, 0x33332305, 0xbb41332f, 0x24d38206, 0x33715d5d, 0x23d285e1, + 0x35033e15, 0x1120c484, 0x2207204f, 0x45113311, 0x42080594, 0xdd041137, 0x0a203e34, 0x320f0fc6, 0x425b8055, 0x8088c985, 0xbb4485c4, 0x8059b0ac, + 0x05012852, 0x3206c4b6, 0x1638644e, 0x4a698247, 0x7291fd0f, 0x4d5290c4, 0x037ac78e, 0xb048fcae, 0x886236bf, 0x82b60351, 0xa44708bd, 0x7905ecff, + 0x2700f204, 0x33405400, 0x21214a1f, 0x1a471701, 0x10292727, 0x29800129, 0x29e029a0, 0x01296f03, 0x29202900, 0x07032930, 0x540c470f, 0x26261a28, + 0x0f0d181f, 0x07025012, 0x00150016, 0xe1333f3f, 0x86c6333f, 0x5d5e21c0, 0x22056f46, 0x8432e133, 0x272121c0, 0x8807704d, 0x113522b7, 0x34d58933, + 0x0a1b7503, 0x5c524519, 0x5c8a5b30, 0x6f6ab62f, 0x1d436e51, 0x24d58ab6, 0x293f2b93, 0xd1d81814, 0x827b200f, 0x38653cd8, 0x6d884717, 0xb0fc0748, + 0xfc010000, 0xfed9048f, 0x00210619, 0x4016000d, 0x1806000a, 0x3a1b9be7, 0x237919fe, 0x10404d51, 0x2e2b10db, 0xd9041630, 0x5158531c, 0x5023151b, + 0x821d4c51, 0x48fd2149, 0xd1204982, 0x06254987, 0x0f800500, 0xc7c3180c, 0x48fd2517, 0x2b2e3015, 0x3f2b4882, 0x7922524d, 0x4c1df404, 0x18235051, + 0x2c080583, 0xd90446fc, 0xe30514ff, 0x38001b00, 0x19841840, 0x42fe374c, 0x474c4f28, 0x0e302d1f, 0x35210568, 0x51292e4a, 0x2d1d454d, 0x0d830f2e, + 0xdb04492b, 0x35232b23, 0x45613c3e, 0x19841826, 0xfd01280a, 0xfeb80404, 0x828f0679, 0x4026288d, 0x08080512, 0x8215000d, 0x0f123405, 0x02191f19, + 0x00068019, 0x5dcc1a2f, 0x33113932, 0x83cc2f01, 0x054d4306, 0x23070725, 0x4b033e27, 0x580805ba, 0x36350706, 0x16323336, 0x2d1b79fe, 0x710a223c, + 0x2a3c250e, 0x32241517, 0x10341c1d, 0x85293210, 0x27d30585, 0x071b293a, 0x1006b06f, 0x18182118, 0x03071320, 0x05036c03, 0x0100005b, 0x98fe31fd, + 0x7dff06fe, 0x0f000d00, 0x008708b5, 0x0003910b, 0x2f01e52f, 0x053031e1, 0x050e4c34, 0x020e2008, 0xfd262223, 0x2b2d3e31, 0x271d113f, 0xf63e2d15, + 0x3c37373c, 0x0e1c2b1d, 0x00ffff37, 0x180000c7, 0x2a2c51bd, 0x050000c9, 0x02730710, 0x82b20126, 0x0007347e, 0x01420043, 0xb4150052, 0x26051801, + 0xa3ffb801, 0x18181eb4, 0x82099558, 0xff712a5f, 0x06e103ec, 0x00260221, 0x242f8248, 0x94430006, 0x202d8200, 0x33b31802, 0x00ae2416, 0x833b0400, + 0xd201212d, 0xca202d85, 0x01222d83, 0x5b85110c, 0x180c1221, 0x080ca149, 0xecff7d5f, 0xc9055e07, 0x71004500, 0x04144840, 0xc5255a39, 0x36960136, + 0x890236a6, 0x36360136, 0x0c5b411d, 0x47004767, 0x00024710, 0x50472047, 0xd0477047, 0x0647e047, 0x1d5b2e07, 0x37374666, 0x5f290033, 0x07262603, + 0x20140422, 0x14480e09, 0x115f333c, 0x3f001318, 0x3232e133, 0x33333f2b, 0x26088211, 0x012f3912, 0x18e1f610, 0x21090e54, 0x15825d5d, 0x30313923, + 0x21521801, 0x27262611, 0x23060623, 0x0b074622, 0x2907436a, 0x33021e14, 0x11373632, 0xbe5c1133, 0x6877080a, 0x4c2a5e3c, 0x77518f3b, 0x3f407db7, + 0x6f88c681, 0x4b0249aa, 0xc6886ea8, 0x7d403f81, 0x8f5177b7, 0x5f294c3b, 0x5071453c, 0x8a5c2e2b, 0x2e76395c, 0x3b762ebb, 0x2e5c8b5c, 0x0571502c, + 0x9c202e25, 0xb8632c2a, 0xaaa6f8fe, 0x77d2dffe, 0x32303032, 0x2101d277, 0x0801a6aa, 0x2a2c63b8, 0x462e209c, 0x8d88cf8a, 0x2459a4e5, 0xfebd0126, + 0x59242643, 0x888de5a4, 0x4c468acf, 0x053a053b, 0x004a04f4, 0x40e7002c, 0x01106509, 0x22f922c9, 0xffb82102, 0x100ab3f0, 0x07832c48, 0x841b1221, + 0x19403a07, 0x00480f0a, 0x481b0a10, 0x0e220d26, 0x2c152221, 0x0f560600, 0x0f020f66, 0x0825820e, 0x1f484049, 0x0e6f010e, 0x0e9f0e7f, 0x59040edf, + 0x0e4f010e, 0x01157401, 0x2401156b, 0x02153415, 0x06340624, 0x06740644, 0x0e050694, 0x0e151506, 0x1b010306, 0x101c0047, 0x1c07021c, 0x2e102e1c, + 0x2e302e20, 0x2ee02ed0, 0x83010205, 0x011e2a4c, 0x1d154026, 0x0c202648, 0x086d8214, 0x1b031022, 0x150f010e, 0x36062606, 0x22060206, 0x3f001500, + 0x115d3232, 0x33333f33, 0x2b2b3917, 0x33382f01, 0x2f2a0d82, 0x12e15d5e, 0x2f3d3917, 0x8e4c182f, 0x715d2106, 0x33261884, 0x11333311, 0x29823912, + 0x5d2b2b36, 0x215d3031, 0x16133301, 0x3e331716, 0x03133703, 0x031e1333, 0x98080a83, 0x02143335, 0x23070602, 0x35262603, 0x0307030e, 0x89fe7701, + 0x261ce0bc, 0x15070709, 0x770f1d1a, 0x0cc9bca2, 0x05181e1f, 0x41725a07, 0x5c25b719, 0x77c0759a, 0x06010d0c, 0x98040a09, 0x56fd4a04, 0x16339d57, + 0x2045413a, 0xcf010c01, 0x6321b0fd, 0x67195c67, 0x98ffe2d0, 0xfedffea3, 0x017ffcf5, 0x03352054, 0x1d1b1301, 0x00aafe0a, 0x14000200, 0xbc040000, + 0x16001406, 0x9b002100, 0x00130a40, 0x150c5a17, 0x0c100615, 0x40c0ffb8, 0x48271a0d, 0x02010c20, 0x0ca00c90, 0x23118302, 0x481813b3, 0x44081984, + 0x480e0b40, 0x1b0e0c0c, 0x2367065b, 0x23302300, 0x23602350, 0xe0052380, 0x239f0123, 0x01235001, 0x005f210e, 0x105f0d16, 0x00b01013, 0x01008901, + 0x0f01004f, 0x00070110, 0x11100010, 0x0c601700, 0xe13f0012, 0x05234f3f, 0xdb6a5d20, 0xe1102306, 0x0b822f01, 0xf6107137, 0x2f3911e1, 0x5f5d2b2b, + 0x12332b71, 0xe1102f39, 0x30313232, 0x07064f01, 0x1121232a, 0x11213521, 0x15211133, 0x32200582, 0x08056a50, 0x0a022338, 0x7ecf9896, 0xc27e3c37, + 0xfe96fe86, 0xba3c01c4, 0x87fe7901, 0x2ea4aea0, 0x815d8b5b, 0x71424e03, 0x9e615798, 0x60043d70, 0xfe1001a4, 0x40fca4f0, 0x61468884, 0x01411b3c, + 0x056d3206, 0x00140027, 0x40810021, 0x16021309, 0x0c001047, 0x2ce68401, 0x481a0d47, 0x000c000c, 0x06471c0e, 0x3fe88257, 0x70022310, 0xc0239023, + 0x0423e023, 0x0250150e, 0x10500d01, 0x020f1013, 0x0202021f, 0x481e0c40, 0x0f34e382, 0x02101f10, 0x02100207, 0x01117f10, 0x11011130, 0x150c5016, + 0xdb82ed82, 0x7122ef85, 0x16505d2b, 0x20ed8309, 0x22178312, 0x85335d2b, 0x30de82e7, 0x14151632, 0x2123020e, 0x33352311, 0x21153335, 0x68451801, + 0xe3023209, 0x1501d5fe, 0x652fcdd3, 0x39fe719f, 0x01b6eeee, 0x2c10822b, 0x435e3704, 0x60412126, 0xfeb00340, 0xcb4618d7, 0xdddd2108, 0x0e754518, + 0xffc73708, 0x05ec06ec, 0x002d00cb, 0x082f4058, 0x221b5b05, 0x07111107, 0x2a1e0322, 0x1d212f2a, 0x2e641e5a, 0x275f002b, 0x1c081b04, 0x0f05225f, + 0x21080121, 0x1e031f21, 0x67180d12, 0x3f230828, 0x6c5e2f39, 0x3f320579, 0x100133e1, 0x1132e1f6, 0x122f7d33, 0x2f183917, 0xbf822f2f, 0x2c09836c, + 0x3233031e, 0x0e153736, 0x26222303, 0x95441826, 0x1716270c, 0x05262607, 0x67185f6d, 0x23080933, 0x5971ac75, 0x4e274ea0, 0x9e3a6156, 0x05529deb, + 0xbabab0fe, 0x630e5601, 0x6c95e9a7, 0x3f4e4fc4, 0x41270595, 0x0e3b6718, 0xb8644a08, 0xfd9f0301, 0xfdb60556, 0xa7eb8f98, 0x9c2a2c5c, 0x00002e20, + 0xffae0001, 0x047105ec, 0x0029005e, 0x20394064, 0x4f05481d, 0x1f0c010c, 0x27081f0c, 0x0b2b1414, 0x54084707, 0x15511a2a, 0x05201011, 0x0c1d5006, + 0x0bb90ba9, 0x06f45902, 0x0b0b0629, 0x15080f09, 0x4f265123, 0x3f20055b, 0xec86eb84, 0x88e13321, 0x123322ec, 0x20ed8339, 0x22ed845d, 0x8f2e2205, + 0x822e20db, 0x070621f1, 0x3c0b7a6d, 0xa9615404, 0xfe074f81, 0x01b6b6f1, 0x81550c13, 0x954e5ea5, 0x38173632, 0x8c193b3c, 0xd8421891, 0x82523b07, + 0x147c3536, 0x87c17b3a, 0x4a0417fe, 0xb58039fe, 0x19223472, 0x0f130a9a, 0x42189709, 0x002308de, 0x82000200, 0x05490800, 0x00b6052f, 0x0018000b, + 0x084940ae, 0x06d80106, 0x070206e8, 0x07d70107, 0xa60207e7, 0x019b0107, 0xa7007701, 0x0a0d0200, 0x04030c09, 0x13130607, 0x0100a708, 0x05010100, + 0x01080009, 0x08100800, 0x08700820, 0x08c00880, 0x080b8206, 0x901a084f, 0x021aa01a, 0xc0ffb81a, 0x18150f40, 0x011a8f48, 0x0f011a40, 0x0408011a, + 0xf0ffb805, 0x0b051340, 0x10135f03, 0x13480e0a, 0x04060c0c, 0x06120900, 0x3f3f0003, 0x39123333, 0xe12b392f, 0x382f0132, 0x5d5d5e33, 0x115d2b5d, + 0x5d382f33, 0x25178371, 0x39115d33, 0x22832f3d, 0x39123923, 0x2d1c8239, 0x715d715d, 0x23213031, 0x23012311, 0x03823301, 0x27239508, 0x032e2721, + 0x07030e27, 0x7fa6ec02, 0x02c5fefe, 0x3b02bb39, 0x7afefec7, 0x352301e8, 0x11161c12, 0x15110907, 0xaa021119, 0xb60556fd, 0xaa024afa, 0x4c308fa4, + 0x25254143, 0x2d494341, 0x00020000, 0x0400000a, 0x004a045a, 0x0017000b, 0x393840cf, 0x79025902, 0x04028902, 0x022b021b, 0x0105b502, 0x05a60596, + 0x01058702, 0x03190309, 0x16080602, 0x12090208, 0x06021219, 0x02111611, 0x02031207, 0xb6090811, 0xb8000100, 0x1b40f8ff, 0xb9480f0a, 0x080b010b, + 0x00360782, 0x010cb40b, 0x05050c0c, 0x010a0606, 0xb8010210, 0x12b3c0ff, 0x07834815, 0x18403708, 0x01480b07, 0x19c01901, 0xaf0219e0, 0x19500119, + 0x1f190f01, 0x0a090219, 0x40f0ffb8, 0x08040a0f, 0x110b0c50, 0x0f0b0111, 0x1501060a, 0x33333f00, 0x2f39123f, 0x23413912, 0x825d2005, 0x33112600, + 0x332b2b2f, 0x2e158238, 0x3d391233, 0x33335d2f, 0x5d2b5d2b, 0x82393912, 0x825e2002, 0x2902831f, 0x5d5d3031, 0x03230101, 0x01821123, 0x23032b08, + 0x030e1701, 0x032e3307, 0x01a60227, 0x60bbbcb4, 0xbdba60a2, 0x0571b401, 0x0d25231b, 0x23250ef0, 0x4a04041b, 0xe901b6fb, 0x038317fe, 0x794a043f, + 0x5e605519, 0x605f2222, 0x00001954, 0x00c70002, 0x05290700, 0x001300b6, 0x40bf0020, 0x081a421b, 0x050e0627, 0x14111215, 0x263e8203, 0x0f010005, + 0x83051b0e, 0x5d6208c3, 0xcb010180, 0x1b84011b, 0x7b1b2b01, 0x050f021b, 0x052f051f, 0x05cf057f, 0x05ff05df, 0x01050807, 0x05011b1b, 0x10101103, + 0x10101000, 0x10b01070, 0x100510f0, 0x22302210, 0x22c02250, 0x22e022d0, 0x5a080c05, 0x13216409, 0x0d5f0306, 0x1009201b, 0x14141b48, 0x0104090e, + 0x0e0a1211, 0x333f0003, 0x3742333f, 0xe1333606, 0x10013232, 0x5d32e1f6, 0x5d2f3311, 0x39173338, 0x2f182f3d, 0x0504412f, 0x33113824, 0x01831133, + 0x39391223, 0x82028211, 0x5d5d2106, 0x22083e42, 0x82231121, 0x1321211c, 0x2f0d4642, 0x81a5e704, 0x01c4fdfe, 0xba7ffe08, 0xf1c101ba, 0x2a054d42, + 0x2301e979, 0x151c1335, 0x42080811, 0x5142074d, 0x98fd2305, 0x55426802, 0xae3c0813, 0x08060000, 0x13004a04, 0xeb001f00, 0x05a53140, 0x96058601, + 0x05770205, 0x16090601, 0x02190209, 0x02490229, 0x02790269, 0x01020b05, 0x1902031a, 0x12091408, 0x110a130b, 0xc60e470d, 0x28064e42, 0x480f0a17, + 0x130113c9, 0x29078208, 0x14c41300, 0x05141401, 0x25420605, 0x2f133205, 0xaf0a3f0a, 0x060a030a, 0x0e01060a, 0x01022054, 0x0c624210, 0x072c3d08, + 0x0101480b, 0x0121d021, 0x600121bf, 0x90217021, 0x214f0321, 0x01210001, 0x08040b08, 0x13141250, 0x0f021919, 0x090e0f13, 0x00150206, 0x3333333f, + 0x3912333f, 0x3339122f, 0x013232e1, 0x31053e41, 0x2b2f3311, 0x1033382b, 0x393911e6, 0x385d2f2f, 0x6d421133, 0xe110240b, 0x41121132, 0x11200554, + 0x23059b43, 0x30315d5d, 0x200a7142, 0x07604113, 0x79421720, 0x54042106, 0x28087942, 0xb6e9fec3, 0xb55401b6, 0x167f4270, 0x28058342, 0xc70139fe, + 0x60541979, 0x0987425f, 0x00142408, 0x056a0500, 0x002300b6, 0x40c00026, 0x01228611, 0x59011a86, 0x02128912, 0x0c091025, 0xffb82648, 0x822c40f0, + 0x25520808, 0x24060b0a, 0x1b5a1a24, 0x0a000726, 0x0a200a10, 0x071b0a03, 0x030a1b07, 0x11101200, 0xd0021120, 0x11800111, 0x11021190, 0x40c0ffb8, + 0x480a073b, 0x1f281111, 0x28f00128, 0xdf28cf01, 0x28400228, 0x28702850, 0x3f280f03, 0x23070228, 0x611c1900, 0x05190b24, 0x002d0a19, 0x5f26070a, + 0x121b0308, 0x3f001200, 0x073d5532, 0x715d5e2b, 0x32e13333, 0x5e332f01, 0x2000825d, 0x05e75a71, 0x5a337121, 0x240808c1, 0x3d39e110, 0x1133332f, + 0x5d2b2b33, 0x5d30315d, 0x033e1333, 0x21350137, 0x031e0115, 0x03231317, 0x2323032e, 0x08018211, 0x020e2259, 0x01010307, 0x187b1421, 0x5f7c5436, + 0x490490fe, 0x806185fe, 0x7a183756, 0x26147bbe, 0x183d4f36, 0x4f3d18bb, 0x7b142636, 0x4a01eb01, 0xc5016ffd, 0x3a628855, 0x8be70106, 0x0619fe8b, + 0x56896238, 0xc1013bfe, 0x17395f48, 0xb80248fd, 0x485f3917, 0x5a033ffe, 0x4400b801, 0xe53506ef, 0x23004a04, 0xc7002600, 0x1a760d40, 0x1a961a86, + 0x07102503, 0x053d410c, 0x08821820, 0x0112093c, 0x0b012306, 0x1a242406, 0x0a251b46, 0x1ba70726, 0xffb80a01, 0x161040c0, 0x48414819, 0x11202308, + 0xd6441101, 0x28078306, 0x0b073f40, 0x28111148, 0x06434110, 0x28602e08, 0x1f022890, 0x02284f28, 0x070a0023, 0x19085026, 0x2416521c, 0x24362426, + 0x240424a6, 0x1f060f0b, 0x5f064f06, 0x06070406, 0x1b0f0806, 0x05034b12, 0x18483f20, 0xe15d2905, 0x32e11032, 0x332f0132, 0x20074841, 0x0747412b, + 0x115d2b25, 0x41331133, 0x5d26064a, 0x5d2b2b5d, 0x48413031, 0x1353081d, 0x167b0a21, 0x5367422c, 0xcf03cefe, 0x6853c9fe, 0x7b172c43, 0x24147bba, + 0x04354430, 0x463504a6, 0x7a142530, 0xfefcb401, 0x3d54010a, 0x09314d65, 0x69696401, 0x31089cfe, 0xfe3d674c, 0x365001ac, 0xfd112b48, 0x110a02f6, + 0xfe36482b, 0x018302b0, 0x4500002d, 0x24080511, 0x00b60589, 0x002b0028, 0x861540ca, 0x1759011f, 0x10021789, 0x1f29290b, 0x102a205a, 0x2b480c09, + 0x40f0ffb8, 0x3c088233, 0x0c2b0f2a, 0x0f100f00, 0x07030f20, 0x20200c0f, 0x16030f0c, 0xc000b028, 0x000f0200, 0x084b821f, 0x1707004e, 0x16101600, + 0x80167002, 0x0316c016, 0xc0ffb816, 0x0a073440, 0x2d161648, 0x9f012de0, 0x022dbf2d, 0x2f012d40, 0x060a012d, 0x2c64075a, 0x5f2b0c0f, 0x21051e0d, + 0x0f102961, 0x0b08010b, 0x030d080b, 0x03201707, 0x3f001200, 0x333f3217, 0x21054341, 0x434132e1, 0xf6102305, 0x344632e1, 0x05564707, 0x425d5d21, + 0x5e270693, 0x1133115d, 0x412b2b33, 0x3126084d, 0x36132130, 0xb9433736, 0x1a9a4206, 0x7b330237, 0xfe1c2913, 0x02baba7b, 0x0495fea4, 0x6185fe4a, + 0x18375580, 0x069f427b, 0x19ba1923, 0x0c9f423c, 0x2e734422, 0x21056549, 0xa342dd01, 0x00ae3822, 0x04980600, 0x0028004a, 0x40cf002b, 0x861f760d, + 0x031f961f, 0x4107102a, 0x2c200653, 0x28080882, 0x10011709, 0x1f29290b, 0x0f2a2046, 0x20a70c2b, 0x0c200f01, 0x030f200c, 0x2f001f16, 0x00ff0200, + 0x07000001, 0x01162017, 0x06a24216, 0x3a080783, 0x0b073f40, 0x2d161648, 0xb0012dcf, 0x2d9f012d, 0x012d6001, 0x00012d4f, 0x022d302d, 0x0747060a, + 0x0c0f2c54, 0x1e0d502b, 0xa6522105, 0x10290129, 0x0b1f0b0f, 0x0b0b0702, 0x820f0d08, 0x0003224b, 0x0b5f4115, 0x60415d20, 0x5d5d2d0f, 0x2b2f3311, + 0x1233712b, 0x715d2f39, 0x4208f543, 0x2b2209ac, 0x60415d2b, 0x21133a26, 0x107bbc01, 0xedfe131d, 0x0b02b6b6, 0xce03d5fe, 0x6853c9fe, 0x7b172d43, + 0x09b742bb, 0x24314524, 0xb7427b14, 0x4b2a2206, 0x05ef4920, 0x425e0121, 0x8f0820bb, 0xfe390001, 0x06ec0346, 0x007600d5, 0x2127409f, 0x480e0918, + 0x51596259, 0x51474d4d, 0x6c675b3b, 0x35446751, 0x14511467, 0x44355167, 0x5b2e2405, 0x05786772, 0xffb8245a, 0x143640c0, 0x5d244818, 0x568f4d52, + 0x56af569f, 0x07405603, 0x5656480b, 0x60346c47, 0x0f01354f, 0x0235af35, 0x29353508, 0x03625143, 0x03476140, 0x1f5f0a15, 0x006029fb, 0xe13f0013, + 0x3f33e13f, 0x123317e1, 0x5d5e2f39, 0x1139e171, 0x5d2b2f33, 0x2f01e133, 0xf610e12b, 0x2105e34e, 0x00822f18, 0x39121128, 0x3311e110, 0x03832f33, + 0x00303125, 0x5c22052b, 0x3e2707af, 0x1e323302, 0x6b151702, 0x23200586, 0x6d085077, 0x2322052e, 0x8f563523, 0x07062b09, 0x37363627, 0x3527032e, + 0x6b6d1633, 0x17162105, 0x6207ac5b, 0x5f1805cb, 0x2d08073c, 0x5a47e101, 0x240e1434, 0x61412f3d, 0x2b325153, 0x0c233142, 0x4d361f08, 0x4a473135, + 0x8868465c, 0x6631204f, 0x80596c9d, 0x67392651, 0x6b185891, 0x80080dbc, 0x1867a63b, 0x14323637, 0x36613379, 0x4b433b1a, 0x0e2f1f2a, 0x1611220b, + 0x142e3030, 0x2b557e52, 0x4b7d5b33, 0x325e8a57, 0x14c48343, 0x18292012, 0x0e1a2416, 0x07040404, 0xb6070f0a, 0x0c101207, 0x29020303, 0x3c376048, + 0x26264662, 0x47446948, 0x971d3f65, 0x3e644827, 0x1e3a5336, 0x307d3643, 0x411e114b, 0x1b173a3f, 0x24386122, 0x09233846, 0x07057705, 0x21382917, + 0x765c3f0d, 0x58774a45, 0x2e6c1839, 0x0080080a, 0xfe170001, 0x05520373, 0x00700052, 0x407140b7, 0x480e0918, 0x6c626868, 0x6c030c03, 0x16114658, + 0x5fe0116c, 0x11525f01, 0x11336c33, 0x055f526c, 0x1c474d43, 0x72c07257, 0x72e072d0, 0x01727f03, 0x0f017230, 0x26070172, 0x0c404346, 0x16434811, + 0x89505116, 0x02529952, 0x0801520f, 0x48625252, 0x00520768, 0x48141040, 0x0c074000, 0x6c5e0048, 0x505b0300, 0x3410620c, 0xfb3e502b, 0x16215048, + 0x3806e241, 0x3317e133, 0xe12b2b2f, 0x39121133, 0x5d5d5e2f, 0x2f3d39e1, 0x2b2f1801, 0x210b82e1, 0xea415d5d, 0x415d200c, 0x356e10eb, 0x0672640a, + 0x2007a641, 0x0c054223, 0x04421620, 0x8b6d1815, 0x23262109, 0x4205bf52, 0x02300a02, 0x0e2f1fcf, 0x1511210b, 0x132d2e2e, 0x233f5937, 0x0b045e18, + 0x594b5308, 0x220e0f2f, 0x63322c3a, 0x4221535d, 0x22090d47, 0x20132c28, 0x396f6455, 0x18407058, 0x6e905622, 0x2c4c6437, 0x61818a85, 0x2748643d, + 0x81476c73, 0x6b393f4b, 0x30311741, 0x3379122c, 0x3a1a3662, 0x52054b43, 0x05770509, 0x33261507, 0x45310e1f, 0x5e183558, 0x3a080836, 0x74443d5b, + 0x1a0e3156, 0x23161726, 0x04030d18, 0x97131603, 0x060a0f0a, 0x2e030303, 0x2f295647, 0x132a4659, 0x5e33452b, 0x2712995b, 0x4d4d2d40, 0x1c932226, + 0x3b1c0822, 0x41153237, 0xff3907fa, 0x006800ff, 0x05ba0500, 0x010602b6, 0xff000075, 0xfea400ff, 0x06710514, 0x080f8212, 0x00009547, 0x7d000300, + 0x7105ecff, 0x1300cd05, 0x29001e00, 0x32404f00, 0x005b1925, 0x2bd02b67, 0x012bcf01, 0x3f012b80, 0x022b6f2b, 0x0a5b1a24, 0x601a2a66, 0x0f01244f, + 0xdf24af24, 0x24080324, 0x5f1f1424, 0x5f14040f, 0x05a54305, 0xa0431220, 0x05524b05, 0x5d5d5d22, 0x20072574, 0x0efc5302, 0x85181620, 0x2e240edd, + 0x51710503, 0x3e0afa59, 0x51a0ec9a, 0x9e6a87fd, 0xfc06396b, 0x6b3a069a, 0x9c696d9e, 0x03083d6c, 0x693b0864, 0x59dd029b, 0x6b370ef5, 0xfdebfec5, + 0xc2864707, 0x86c27a7a, 0x439a0447, 0x7575b880, 0x834380b8, 0xff7126d9, 0x042d04ec, 0x22d9825e, 0x8221001a, 0x333008d9, 0x0048171f, 0x23402357, + 0x23e023d0, 0x01230f03, 0x0a48181e, 0x50182256, 0xa9011eef, 0x021eb91e, 0x1e1f1e0f, 0x06031e2f, 0x1b141e1e, 0x14100f50, 0x2006fe59, 0x21da84e1, + 0x814f5d5d, 0x21d98905, 0x4b44020e, 0x021e2f09, 0x37363201, 0x13161621, 0x21070622, 0xf4592626, 0xae67340d, 0x23fe477f, 0xfd0a888d, 0x8c8c09be, + 0x020e8889, 0x598a0d3e, 0x4b250def, 0xd4fdd391, 0x290082b2, 0xa4a24403, 0x0000a2a4, 0x00820001, 0x02052208, 0x1c00c305, 0x29405a00, 0x0d0b0607, + 0x010dfb01, 0x90080d0d, 0x0219d019, 0x001e1919, 0x1eb0011e, 0x08b48501, 0x5f1e4f22, 0x061e7f1e, 0xb8080907, 0x0c40f0ff, 0x16600008, 0x03080904, + 0x1207060d, 0x33333f00, 0xe13f333f, 0x2c06264f, 0x2f331171, 0x3d39125d, 0x33715d2f, 0x062d5133, 0x0123012e, 0x16160133, 0x37363617, 0x33033e13, + 0x08058371, 0x2496043c, 0x12242a35, 0xfecdd7fe, 0x2701c519, 0x0e112e1d, 0x1f8d1a2a, 0x4b674c3d, 0x171a4423, 0x252d0535, 0xfb426748, 0xfcb605e9, + 0x4faf5b61, 0x0261bc4e, 0x629c7100, 0x97080d2b, 0xbf860d09, 0x040e0433, 0x001f0052, 0x1e00b96d, 0x1640f8ff, 0x1f480e0a, 0x08048308, 0x20071e2b, + 0x0748110d, 0x16e00007, 0xffb81601, 0x071a40e0, 0x1616480a, 0xcf21bf21, 0x0321ef21, 0x0f012150, 0x4f212f21, 0x01070321, 0x30d08400, 0x1f071e00, + 0x134f1a15, 0x0f00010f, 0x3f323f00, 0x86d482e1, 0x825d20d0, 0x842b20d0, 0x332b27d1, 0x312b2b33, 0xc7541130, 0x08cc8a07, 0x06222342, 0xbc230307, + 0x1f200bc9, 0x0406051a, 0x09191814, 0x43351956, 0x221a3c58, 0x12260b11, 0xe0183a2f, 0xfd4a04f3, 0x6e6a21a2, 0x5f191961, 0x0121676c, 0x42755e40, + 0x87050518, 0x58500503, 0xffffdffc, 0x25058f41, 0x26027307, 0xde828002, 0x76030738, 0x5201b804, 0x02b61900, 0x26051d01, 0xffb80102, 0x1d31b482, + 0xd35f1908, 0x352b2305, 0x33850035, 0x060e0423, 0x20338221, 0x20338681, 0x83478250, 0x11202133, 0x94253384, 0x002034b4, 0x08338916, 0x00030045, + 0x0914fe7d, 0x00cd055a, 0x00270013, 0x40a1004a, 0x1e5b000a, 0x2f2f4a38, 0xb8282937, 0x2340f0ff, 0x00402828, 0x02401040, 0x1f0140f0, 0x3f402f40, + 0x1e000340, 0x1e401e01, 0x37360a40, 0xe037d010, 0x4a370237, 0x2f080506, 0x3737480b, 0x014c0f4c, 0x4c1f4c0f, 0x4c4f4c2f, 0x4cbf4c7f, 0x4cef4cdf, + 0x5b140708, 0x384b660a, 0x284a4a2f, 0x1b3d5044, 0x230f2836, 0x19040f5f, 0x2607ca43, 0xe13f333f, 0x18113911, 0x4c07256d, 0x3826058e, 0x393912c1, + 0x554b2f2f, 0x280d8306, 0x33332f3d, 0x3031e110, 0x05346401, 0x230ae057, 0x14051216, 0x200de65d, 0x09934125, 0x0e013324, 0x20692303, 0x3748080a, + 0x964c1f05, 0xe09891dd, 0x93474793, 0xdd9099e1, 0x23fc4c95, 0x6796612f, 0x2e609667, 0x6794602e, 0x2f619768, 0xd7bd4304, 0x13191d0d, 0x17040604, + 0xc70b1d1b, 0x1d4efebc, 0x50745640, 0x151b4c34, 0x46302340, 0x390f2534, 0x20141c44, 0x0e0e5eab, 0xfde39608, 0x5858289b, 0x56192253, 0x02215e61, + 0x5127fb63, 0x0b315a81, 0x07059106, 0x29402c17, 0xffff00a0, 0x14fe7100, 0x5e044e08, 0x52002600, 0x07010000, 0x6f045c00, 0x11000000, 0xb80202b1, + 0x20b41404, 0x25000a2f, 0x00352b01, 0x02000035, 0x83ff7d00, 0x3106c305, 0x3f001f00, 0x33405200, 0x67005b30, 0xc441b441, 0x41900241, 0x41300201, + 0x20024180, 0x4066105b, 0x0b011819, 0x08040118, 0x07020814, 0x5f3b3538, 0x0315181b, 0x085f2528, 0x00120b05, 0xe133333f, 0x2b048432, 0x5d5d5e32, + 0xf610015d, 0x5d5f5de1, 0x2706dc77, 0x07020e14, 0x22230606, 0x2d077065, 0x33363637, 0x1e171632, 0x1e140503, 0x555f1702, 0x2e342308, 0x26852702, + 0x030e9508, 0x8949c305, 0x4a0e7cc5, 0x0d483b37, 0x4587c781, 0x81c78745, 0x373b480d, 0xc57b0e4a, 0x7ffb4a89, 0x537f572d, 0x31354311, 0x80521145, + 0x572d2d57, 0x46105280, 0x11433531, 0x2d577f53, 0xfc95dd02, 0x3f177dc0, 0x163f3636, 0x96fec07d, 0x7bbffb96, 0x33313f17, 0xbf7d173d, 0xc07496fb, + 0x30156292, 0x152e2826, 0x74c09262, 0x6292bf73, 0x29293216, 0x91611630, 0x020000bf, 0x91ff7100, 0xb604a804, 0x37001f00, 0x2cb55400, 0x39570048, + 0xc0ffb839, 0x48140eb3, 0x40290783, 0x480c0924, 0x56104820, 0x0b0d4138, 0x352f322f, 0x15021b50, 0x2326290f, 0x0b050850, 0x050e4116, 0x240e0f41, + 0xf6102b2b, 0x06215ce1, 0x20160d41, 0x060c4116, 0x35363624, 0x0b412634, 0x06480806, 0x39a80406, 0x095f996b, 0x3b3a383c, 0x6e995d08, 0x9a6c393d, + 0x3a3b0862, 0x5b093d37, 0xfc3c6d98, 0x0b7b6f85, 0x39323439, 0x6e6d790c, 0x32390c78, 0x7b0b3934, 0x7627026f, 0x125a8ebf, 0x382d2e39, 0xc08e5a12, + 0x8dbf7577, 0xe8080d82, 0x123a2a29, 0x75bc8d5b, 0x2c1fcdac, 0x1f2a2020, 0xc8a9abcc, 0x20202b20, 0x00c81f2d, 0x7d000300, 0x3507ecff, 0x45003d08, + 0x6d005b00, 0x9240da00, 0x04241437, 0x24140414, 0x5b411c03, 0x006f670c, 0x026f106f, 0x6f206f00, 0x6f806f50, 0x6fa06f90, 0x6fe06fd0, 0x1c5b2d08, + 0x68636e66, 0x685c4747, 0x50524051, 0x03526052, 0x005f5252, 0x20681068, 0x90688068, 0x68070568, 0x4d014de0, 0x56cf56bf, 0xef525602, 0x47460146, + 0x01524f47, 0x6b605252, 0x6bd06bc0, 0x6b046be0, 0x5f7f5f6f, 0x5fef5faf, 0x015f1004, 0x5f3c325f, 0x377f1411, 0x3702378f, 0x480a0740, 0x11173737, + 0x03032513, 0x215f0028, 0x3f000407, 0x3332e133, 0x333f3311, 0x5d2b2f33, 0x32e11033, 0xcc5d5d2f, 0x712f325d, 0x5dcd1033, 0xcd5ddd10, 0x5e2f015d, + 0x2c1d825d, 0xcd10cd5d, 0x39112f32, 0x5de1f610, 0x0a7a4971, 0x5b331121, 0xe24716e0, 0x5b17200e, 0x3e220cdf, 0xfc723702, 0x34353e05, 0x1503022e, + 0x022e2223, 0x15062223, 0x34352315, 0x1e323336, 0x14053302, 0x36350706, 0x841e8336, 0x05162212, 0x0e025c3f, 0x45a26725, 0x5c67a047, 0x2a291601, + 0x17424e56, 0x564e4217, 0x06045c2a, 0x5610033d, 0x2a647a90, 0x7c853a2e, 0x77703a6d, 0xeffe4e85, 0x383c7978, 0x321f241f, 0x5c443b2e, 0x2a231022, + 0x5c2a2c2c, 0x13281622, 0x1c1c2f23, 0x5913232f, 0x2b06225c, 0x2481a602, 0x352d242a, 0x656b2310, 0xe2270882, 0x4c1f734d, 0x64192d16, 0x8b080506, + 0x03004626, 0xecff7100, 0x0807df05, 0x59004300, 0xb2006c00, 0x67606b40, 0x675a4545, 0x5050404f, 0x50500250, 0x9f676f5d, 0x67100267, 0x15246701, + 0x033f350b, 0x482c0b03, 0x1e6e573f, 0x6d560b48, 0x4b014b00, 0x540154df, 0x01440f50, 0x6f454544, 0x50500150, 0xe0016a00, 0x026af06a, 0x7f5d0f6a, + 0x5d07025d, 0x34511b2f, 0x103a1616, 0x51292110, 0x40240300, 0x24481510, 0x480c0740, 0x00062424, 0x323f0016, 0x2b2b2f32, 0x32e11033, 0x2506a65d, + 0xcc5d5e2f, 0xe141715d, 0x10712905, 0x71cd5ddd, 0xe1f61001, 0x122b0282, 0x122f3d39, 0x33391239, 0x415d2f18, 0x31230bf1, 0x43220530, 0x2e23053d, + 0x4d343502, 0x07230638, 0x6e23032e, 0x362106b5, 0xbe781837, 0x18222008, 0x200dc45e, 0x18d84113, 0x2e343523, 0x05d74104, 0x10043d08, 0x2b2b6d51, + 0xa95f506a, 0x6d3f4a7f, 0x401f5493, 0x3f14343c, 0x2b2b2911, 0x8d697012, 0x29734988, 0x42393116, 0x698c8529, 0x2b2b1270, 0x14401129, 0x203f3c35, + 0x3f6d9354, 0x3aa97e4a, 0x2507d541, 0x396e7c86, 0xd5417870, 0x0f742e05, 0x0f151a15, 0x443b2e32, 0x20202314, 0x955b1823, 0x10093907, 0x0a9a0c16, + 0xca090f13, 0x34c3d3d3, 0x181e1020, 0xd3d3c30e, 0x130f09ca, 0x09355f18, 0x89d5962e, 0x82aa063f, 0x2e242b24, 0x6c231134, 0x0808cf41, 0x0d332934, + 0x0f0a0c0f, 0x26261217, 0x02000046, 0xecff7d00, 0x04075e07, 0x53000d00, 0x62409b00, 0x5a471223, 0x0144c533, 0x44a64496, 0x01448902, 0x4f2b4444, + 0x1d821a5b, 0x2b0d4708, 0x0055671a, 0x02551055, 0x55205500, 0x55705550, 0x55e055d0, 0x5b3c0706, 0x4554662b, 0x370e4145, 0x3411305f, 0x00040409, + 0x3f060a80, 0xcf027f02, 0xef02df02, 0x34020502, 0x4a043015, 0x0e092023, 0x5f412348, 0x695f261f, 0x322b3205, 0x2f33333f, 0x1a33335d, 0x332f39cd, + 0xe1103311, 0x0a735f32, 0x25055755, 0x3911e110, 0x795f5d2f, 0x07152408, 0x86232723, 0x5f352003, 0x8b2d4287, 0xb8322252, 0xb8312331, 0x03502232, + 0x0e91431c, 0x242b945f, 0xac1b0407, 0x23008267, 0x21fe1bac, 0x203a9e5f, 0x05795a00, 0xa405f42a, 0x3a000d00, 0x0d402301, 0x0d290782, 0x30b90f2a, + 0x01308201, 0x06a55f2f, 0x07833a20, 0x481b1322, 0x40290783, 0x480f0a19, 0x0e010ea9, 0x21108210, 0x0c82100e, 0x1c1b3028, 0x011d6634, 0x25821c1d, + 0x53405408, 0x1c1f1c0f, 0x4f031c3f, 0x7f1c6f1c, 0xbf1c9f1c, 0x1c1c051c, 0x232f3034, 0x74012390, 0x236b0123, 0x34232401, 0x0e3a0223, 0x01349014, + 0x14341424, 0x14741444, 0x23051494, 0x34141434, 0x290f0323, 0x102a0047, 0x2a07022a, 0x3c103c2a, 0x3c303c20, 0x830f1003, 0x0f352157, 0x0806e541, + 0x7f020f30, 0x9f028f02, 0x40020402, 0x02481714, 0x1d154034, 0x0c203448, 0x341b4814, 0x290e031e, 0x230f0f1c, 0x36142614, 0x30140214, 0x3f00150e, + 0xc75f3333, 0x17122605, 0x2f2b2b39, 0x07fc412b, 0xd25f0120, 0x5d2f210f, 0x33202782, 0x31059853, 0x18331133, 0x38715d2f, 0xc0875d33, 0x2b2b01c0, + 0x03822b5d, 0x12115d29, 0x2f2f3939, 0x42013031, 0x03200c13, 0x2123eb5f, 0xf641ba04, 0x23312307, 0xf75f0450, 0xa4052129, 0x2107e441, 0x03605cfa, + 0x01490830, 0x14fe7d00, 0xcb059804, 0x54002300, 0x5a111740, 0x0701100f, 0x120f4010, 0x18101048, 0x600120ba, 0x02207020, 0xc0ffb820, 0x0a061a40, + 0x25202048, 0x050125af, 0x2466185b, 0x1d5f0021, 0x5f0a0f04, 0x1b101313, 0xe13f3f00, 0x06145e33, 0x2705134c, 0x2f39125d, 0xe15d5e2b, 0x2005e54c, + 0x06924a15, 0x23113723, 0x108e6211, 0x19033a08, 0x437bae6b, 0x76b0763b, 0x25282d1d, 0xa410bb15, 0x574c9df0, 0x6ca2faa9, 0x3f4e4fc4, 0x51270594, + 0x8d89da98, 0x044e96db, 0xfd090d09, 0x6cd80162, 0xaa1501c6, 0xc61401a6, 0x08f95d6e, 0xfe713508, 0x046f0314, 0x001f005e, 0x1d25403e, 0x0e401c47, + 0x1c1c4811, 0x5f210c04, 0x02217f21, 0x15012110, 0x20560448, 0x1f51181b, 0x121b1c16, 0x10090d51, 0xe1333f00, 0x0128b583, 0x5de1f610, 0x11ce105d, + 0xad82af82, 0x7c450420, 0x17162107, 0x830c7b45, 0xed0128b8, 0x4c4a82b0, 0x5d66b285, 0x9d2908c1, 0x3e949190, 0x12b72368, 0x07fe4414, 0x0806b55d, + 0xd3d3ca4e, 0xfd141bc3, 0x00d8015a, 0x68000100, 0x7904faff, 0x13000a05, 0x67402501, 0x111d110d, 0x1d010d02, 0x0b020201, 0x02020b12, 0x02071207, + 0x0c111007, 0x000b1213, 0x02030801, 0x040f0407, 0x0a0c110d, 0x01090b12, 0x07020608, 0x0d050e05, 0x11211e82, 0x2120820a, 0x22820912, 0x82060121, + 0x02440824, 0x0b0c0504, 0x0f0e0102, 0x4001014f, 0x0b05010b, 0x010f0f01, 0x1204050b, 0x11701160, 0x110311f0, 0x40c0ffb8, 0x480a074d, 0x11070811, + 0x30152015, 0x06030215, 0x07040900, 0x13020101, 0x040d100a, 0x1211110b, 0x30080d82, 0x0b080707, 0x0b0b010b, 0xc00cb00c, 0x120f020c, 0x0002121f, + 0x02081008, 0x0c081202, 0x0212080c, 0x0e0f0404, 0x480d0740, 0x0004050e, 0x2b2f332f, 0x05215533, 0xcf5c2f20, 0x11712305, 0x03832f33, 0x09821482, + 0x01210582, 0x2707825d, 0x5d2b2f32, 0x2f391733, 0x5d200082, 0x11210f82, 0x23018333, 0xc0c08710, 0x0821038d, 0x210185c0, 0x07858710, 0x31c00825, + 0x825e0030, 0x015d2a58, 0x03250705, 0x37251327, 0x21038405, 0x0f820317, 0x4c023308, 0xfe471c01, 0xb481b4e3, 0x0146e5fe, 0xe4fec61f, 0xb61d0147, + 0x1f01b67f, 0x01e5fe4a, 0xa47ba6b0, 0x014ac7fe, 0xa47ba43b, 0x7da45a01, 0x493901a4, 0x0c82c4fe, 0x00010039, 0x038f04c9, 0x00b805b0, 0xb5420015, + 0x0a07200f, 0xffb80348, 0x821e40e0, 0x0c280808, 0x00171212, 0x06100600, 0x06900620, 0x070506a0, 0x0f160606, 0x03000b0f, 0x2f000003, 0xcd102f32, + 0x01112f32, 0x5d5e2f33, 0x2f29c182, 0x2b2b0033, 0x06013031, 0x06527706, 0x21332f08, 0x32333636, 0x06141516, 0x068b0123, 0x2838302c, 0x1d251709, + 0x2d05c101, 0x2b2a3830, 0x2cee0439, 0x1c383333, 0x2d091625, 0x39363231, 0x89820029, 0xe504f426, 0xd905df03, 0x403c8983, 0x90088011, 0x08080208, + 0x10140017, 0x03142014, 0xffb81407, 0x0d1240c0, 0x14144810, 0x14345482, 0xbf400e09, 0x80050105, 0x1a2f0009, 0xcd1a5ddd, 0xcd2f3311, 0x2b228c83, + 0x0a825d5e, 0x89825d20, 0x023e3222, 0x28087f83, 0x34352315, 0x0e222326, 0x35232302, 0x854e0201, 0x6d3a7077, 0x2e3a857c, 0x9179652a, 0x66051055, + 0x65242b24, 0x3411236c, 0x2008822e, 0x08858281, 0x04e10129, 0x06d302d7, 0x00110035, 0x0b124020, 0x4f063f0e, 0x00060206, 0x034f033f, 0x0303035f, + 0xcc2f000f, 0xcd2f015d, 0x8239325d, 0x08b06763, 0x14152408, 0x26151716, 0x44e10126, 0x1f322f3b, 0x3c391f25, 0xb605787a, 0x26264639, 0x11111a1b, + 0x152e1913, 0x8b731f4c, 0x8313205d, 0x3f07295d, 0x02004f00, 0x3f0e0300, 0x2006176e, 0x6e5d8503, 0x7c4a060d, 0x06a44808, 0x78d30225, 0x48393c7a, + 0x05280857, 0x1f734db6, 0x192e154c, 0x2e0b1548, 0xfe290008, 0x05c107c1, 0x00130091, 0x823b0027, 0x0063265f, 0x008b0077, 0x567c829f, 0x07290565, + 0x33363623, 0x17021e32, 0x200f8e03, 0x200f8e01, 0xbf0f8e21, 0x6f04351f, 0x2e241803, 0x212f1e19, 0x054b0314, 0x4d316764, 0x4f031e36, 0x01231392, + 0x821703f4, 0x2f1f2728, 0x4c031321, 0x28856505, 0x922ffb21, 0x31042114, 0x29951492, 0x6882f020, 0x82192d21, 0x277c8453, 0x364c3168, 0xbef9031f, + 0x04313e92, 0x13231ccf, 0x23120506, 0x1c685a1e, 0xf92b4833, 0x270f87f2, 0x331d6959, 0x16012b47, 0x0f821f88, 0x8d2b4821, 0xdb03210d, 0x0d8d0f8d, + 0x8819fe21, 0x8368200f, 0x080d8d4b, 0x08000027, 0x7ffe2900, 0xd3057d07, 0x19000c00, 0x33002600, 0x4d004000, 0x67005a00, 0x17050000, 0x2307030e, + 0x0337033e, 0x20048227, 0x2a0c8233, 0x031e3701, 0x032e1517, 0x82070527, 0x82352004, 0x3701210c, 0x27831a82, 0x82070121, 0x2127831f, 0x1a822703, + 0x1a833720, 0x04821720, 0x042e2783, 0x1c0a0b37, 0x61122320, 0x1012150a, 0x0c8b3b05, 0x0e230233, 0x57575526, 0x5b5d2a27, 0x68fb2557, 0x5755270e, + 0x320c8556, 0x2202a603, 0x28565450, 0x4e4f2545, 0xeafc1e49, 0x884f2302, 0x112b330d, 0x24272914, 0x3317430f, 0x03173234, 0x2814116a, 0x0d822527, + 0x32343424, 0x428a2316, 0x8a980421, 0x16fe215c, 0x01228498, 0x4f8210aa, 0x440f2522, 0x16224f83, 0x0d8b95fc, 0x83de0221, 0x28552286, 0x20868546, + 0x878683e9, 0x004f080d, 0xfec90002, 0x07d3057f, 0x001b0068, 0x40b30031, 0x301c1c48, 0x26d00126, 0xcf26af01, 0x26200226, 0x26802630, 0x17262603, + 0x1a1a190a, 0x07151b18, 0x65175a00, 0x0133d033, 0x200133af, 0x02333033, 0x5a0c0813, 0x26326409, 0x1c011c9f, 0x82090640, 0x8e2c2d3e, 0xfb1a0521, + 0xe8ffb813, 0x481814b3, 0xe0340782, 0x130a2640, 0x16130648, 0x03132613, 0x5f171309, 0x18061200, 0x06211a82, 0x37168220, 0x06190609, 0x07030629, + 0x030a1606, 0x33333f00, 0x2b2b5d5e, 0x3333e13f, 0x07820683, 0x5d2b2f2e, 0xf6100133, 0x5d3232e1, 0xf4105d5d, 0x33280782, 0x332f3933, 0x2f391211, + 0x71311082, 0x30312f33, 0x36341121, 0x23373637, 0x33112301, 0x91841811, 0x03332b09, 0x0e031323, 0x2e222303, 0x41182702, 0xae0807ac, 0x04056404, + 0xfd080604, 0x01aed731, 0x04010303, 0xcc020703, 0xda8fc3d5, 0x31069da6, 0x67648d5d, 0x042a588c, 0x321c04aa, 0x492b354c, 0x03062237, 0x418f3819, + 0x46fb4d4c, 0xe0fcb605, 0x44433e1a, 0x044c4a1f, 0xfdf0fab4, 0x078101d9, 0x50774d68, 0x774f2729, 0x29483950, 0x472c1210, 0x02000035, 0x83feae00, + 0x1706f204, 0x25000f00, 0x3a409600, 0x1a041010, 0x1a841a34, 0x1a1a0703, 0x0e0d050b, 0x090c0f0e, 0x48180910, 0x46000209, 0xa427550b, 0xd427c427, + 0x0427f427, 0x02012780, 0x27102700, 0x27502720, 0x27702760, 0xffb80306, 0x822540f0, 0x08033f29, 0x54044607, 0x107f1a26, 0x06401001, 0x10104809, + 0x11158e20, 0x0209fb0e, 0x600b0f05, 0x2a5f0408, 0x3fe12405, 0x413f3333, 0x2b220c2d, 0x2f415f5d, 0x412b2006, 0x5e210830, 0x052e415d, 0x23011329, + 0x07113311, 0x41113301, 0x032f1323, 0xfefd0b8f, 0x020cacea, 0x7bb7e904, 0x41477ab6, 0x76181419, 0xfd2e076d, 0x9803fc64, 0xe9fd50fc, 0x17067d01, + 0x4218764e, 0x123609f1, 0x0035482c, 0x002f0002, 0x05330400, 0x001600b6, 0x40520021, 0x096a132c, 0x06e66908, 0xd2690e20, 0x00892108, 0x2009cc69, + 0x0ecc6903, 0x6908da68, 0xc06905c6, 0x06d76815, 0x210bc069, 0xc0698101, 0x9898260a, 0xfe3b01ba, 0x14be69c5, 0x69b2b221, 0xb58209bc, 0x00001228, + 0x14061904, 0xb5821400, 0x40613d08, 0x0e01013b, 0x5708471c, 0xbf236f23, 0xff23df23, 0x00030423, 0x11124716, 0x1522540e, 0x0f030450, 0x12001250, + 0x24074004, 0x01120f48, 0x121f120f, 0x12040702, 0x00131204, 0x150e5016, 0x2109916a, 0xc5872b71, 0xc4f61027, 0x3232e133, 0x26cc825d, 0x312f3912, + 0x82210130, 0x692120b3, 0x11200d9f, 0x25099d69, 0x17016401, 0x9f69e9fe, 0x9c9c2309, 0x9b6901b6, 0x21053a08, 0x9ceffd89, 0x587c4d9b, 0x8998042f, + 0xfedafbf3, 0x422911a8, 0x28423130, 0x20c78211, 0x36c782c7, 0x00b60533, 0x00220013, 0x1b4f4088, 0x1a061a05, 0x07190818, 0x82190607, 0x0c4a0801, + 0x00285b1e, 0x00480038, 0x24670003, 0x400124cf, 0x240f0124, 0x0c140601, 0x23640d5a, 0xaf1b1819, 0x1a1a011a, 0xb0062214, 0x07070107, 0x1408050c, + 0x400b3060, 0x0b0b020b, 0x0e60220c, 0x00120c03, 0x11e13f3f, 0xe15d2f39, 0xc7823939, 0x93435d20, 0x39392105, 0x2205ae43, 0x825d5d5e, 0xe15d27e0, + 0x2f393912, 0x1b83112f, 0x74323921, 0x142b064c, 0x1707020e, 0x23062707, 0x82231123, 0x1e4f08e6, 0x32330102, 0x37273736, 0x35363617, 0x23232634, + 0x2f163304, 0x6a6e364b, 0x967c5d81, 0x866a01ba, 0xfd3c7ec2, 0x4426814e, 0x706d5c1f, 0xaea43433, 0x3a0a04a0, 0x2056646f, 0x1bb64e9b, 0xb605c7fd, + 0xfea06d39, 0x85050567, 0x7324a04c, 0x82898e57, 0xae4b08f7, 0x3f0414fe, 0x23005e04, 0x72003900, 0x35344040, 0x2a333332, 0x1f1f1e20, 0x2a214837, + 0x303b571b, 0x102a013b, 0x540d470c, 0x3235333a, 0x1f340f2f, 0xcf346f34, 0x34070434, 0x50242f34, 0x0e101610, 0x20201f0f, 0x211b0c00, 0x51502f1e, + 0xe3820586, 0xe4823f20, 0x3f3f3323, 0x21f38333, 0xd7825d5e, 0x3220e885, 0x1127e682, 0x2f39e139, 0x82113339, 0x33392e04, 0x22053031, 0x2327022e, + 0x16161716, 0x28e18215, 0x3e331733, 0x1e323303, 0x64011902, 0x22032408, 0x4c07020e, 0xf78505bc, 0xad08f682, 0x603b9e02, 0x0c163c4d, 0x04020303, + 0x081a94b6, 0x604d3b16, 0x6e995e3c, 0x6d525a3c, 0x411f756a, 0x41694c46, 0x411b021f, 0x2111516c, 0x6e6d6a0f, 0x19147f54, 0x22203a2c, 0x10371a1f, + 0x36062bfe, 0x2d3e2294, 0xd48f481b, 0x44f2af8c, 0x09a64e9a, 0x2edb030b, 0x295e8d5e, 0x376b9d65, 0x4c980503, 0xd0ee6a9e, 0x010000ce, 0x00002f00, + 0xb605be03, 0x89000d00, 0x051f1540, 0x0502052f, 0x000f0805, 0x9002001f, 0xe000a000, 0xb8000300, 0x1e40c0ff, 0x00480a07, 0x0f1f0f00, 0x0f9f0f3f, + 0x03040fbf, 0x000c5a07, 0x0a06010a, 0x08c00880, 0x22830802, 0x0a062632, 0x09060848, 0x0c0f035f, 0x0c3f0c2f, 0x0f040c4f, 0xaf300682, 0xff0cdf0c, + 0x0c08050c, 0x5f02070c, 0x1207030d, 0x08ee4418, 0xe133712a, 0x2b2f0132, 0x5d5ec65d, 0xcf4d0982, 0x12712b05, 0x315d2f39, 0x21150130, 0x5b182111, + 0x0337084f, 0x01c3fdbe, 0xbab0fe50, 0xb6059898, 0xa215fea6, 0x83027dfd, 0x839102a2, 0x821220bd, 0x040a22bd, 0x3ebd824a, 0x0b1d406e, 0x0620000b, + 0x06020630, 0x0f700f06, 0x0fc00fa0, 0x470d0903, 0xef02df04, 0x83020202, 0x12b323c5, 0x07834815, 0x21402208, 0x00480b06, 0x094f010c, 0x045f044f, + 0x17400402, 0x040b481c, 0x0702041b, 0x08000404, 0x000f0550, 0x20a58815, 0x829c832b, 0xc62b21a6, 0x5d20a587, 0x3125a382, 0x23113330, 0x051e6e35, + 0xae3ca883, 0x5c029c9c, 0x17015afe, 0xe101e9fe, 0x9ae00189, 0xfe89bafe, 0x0001001f, 0x0400fec7, 0x3408b582, 0x66002600, 0x15094140, 0x07070701, + 0x125b2205, 0x0128c028, 0x288f287f, 0x40281002, 0x1c1c0228, 0x055a040a, 0x201d2764, 0x001c175f, 0x2f0d0f60, 0x030d3f0d, 0x2d04820f, 0x0dff0ddf, + 0x0d0d0804, 0x065f0905, 0x3b410503, 0x4fe1200a, 0xf1290506, 0x5d2fc032, 0xde105d5d, 0x299484e1, 0x015d5e00, 0x11070622, 0x94831123, 0x08059f4a, + 0x0e141556, 0x2e222302, 0x16352702, 0x11203316, 0x01022e34, 0x1a3c25fc, 0xfdf702ba, 0x2d471dc3, 0x57a5f09a, 0x76c99252, 0x3d444e31, 0x487f3f1f, + 0x7b437701, 0x058302ae, 0x0587fd05, 0x0bfea6b6, 0xab5c0305, 0xf8aa97f2, 0x0c064fa2, 0x17a20c13, 0x79ef0118, 0x00407eb9, 0x4a08db82, 0x030afeae, + 0x004a04c5, 0x405c0023, 0x19220939, 0x03222922, 0x0a121414, 0x0f251f48, 0x02251f25, 0x257f255f, 0x030325ff, 0x47111703, 0x04245412, 0x0b510d00, + 0x021a1b1a, 0x121a1a07, 0x0f135016, 0x51071512, 0x3f001b00, 0x5d3f3fe1, 0xe9210580, 0x05424311, 0x5d2f3923, 0x82d28871, 0x842620d1, 0x363225bb, + 0x23263435, 0x3b08de93, 0x6a4b2902, 0x426a2b2e, 0x9d907576, 0xb61f3e1a, 0x5afe5c02, 0x661f3b1d, 0x404c85b3, 0x0afe966f, 0x18a11d1f, 0xd4d2c325, + 0xfe080aca, 0x9a4a0435, 0x0505c3fe, 0x9ddb8a3e, 0x4088d596, 0x043cc782, 0xcb067ffe, 0x1500b605, 0x5740e200, 0x18144011, 0x09201148, 0x110a4813, + 0x0002111a, 0x00200e83, 0x003c0e84, 0x0702001a, 0x020d0d10, 0x0a0a075a, 0x03b803a8, 0x01039902, 0x5701038d, 0x77036703, 0x5e08e582, 0x06120303, + 0x100f0e00, 0x180c400f, 0x0f110f48, 0x12045a15, 0x84127401, 0x0312c412, 0xc0ffb812, 0x0a072740, 0x17121248, 0xf0011704, 0x17e40117, 0x0117a001, + 0x30172002, 0x70176017, 0x05179017, 0x0801170f, 0x08050809, 0xf0ffb806, 0x06061340, 0x0dfb1316, 0x0f000a0a, 0x11030b08, 0x6803055f, 0xe135054e, + 0x1233333f, 0x3f331139, 0x2f330111, 0x11333338, 0x5d5d5e33, 0x06b25b5f, 0x715d2b30, 0x2f3333e1, 0x3233382b, 0x2f391211, 0x00825d5f, 0xe1212182, + 0x33258332, 0x2b5d2b2b, 0x2130312b, 0x11231101, 0x01012301, 0x33110133, 0x08824482, 0x053c1082, 0xb3eefdae, 0x02d3eefd, 0xcdedfd21, 0x02b30a02, + 0xedfdcd0a, 0xb0c3a801, 0x1bfde502, 0xf2240384, 0x3cfdc402, 0x2e080387, 0xd9fdb4fd, 0x00008101, 0xfe040001, 0x04040683, 0x0115004a, 0x276c4011, + 0x02103710, 0x0e390e29, 0x36092602, 0x0a270209, 0x27020a37, 0x86043704, 0x37012304, 0x5e410201, 0x0d10371d, 0x0746020d, 0x03cd0a0a, 0x0103b901, + 0x960103a9, 0x03870103, 0x5a410301, 0x410a2009, 0x4628055a, 0xc0ffb812, 0x481512b3, 0x40380783, 0x480b0717, 0x10171212, 0x17000117, 0xf417e401, + 0x17b40217, 0x170217c4, 0x402f2382, 0x48110d13, 0x02011730, 0x0f011720, 0x41070117, 0x0f241560, 0x03056011, 0x41093949, 0x2b251260, 0x71715d5d, + 0x05bf6211, 0x200e6141, 0x0662415d, 0x61415d20, 0x5d002406, 0x835d015d, 0x156a4100, 0xfef0043c, 0x44fea443, 0xfecf01cf, 0x9f01c558, 0xc5a001a4, + 0x4f0158fe, 0x2d02aec5, 0x0384d3fd, 0x15023524, 0x0387ebfd, 0x65fe2a08, 0x7d01e9fd, 0x4800ffff, 0xec0342fe, 0x2602cb05, 0x0000b101, 0x7f030701, + 0x00004801, 0x01b11100, 0xffffb801, 0x134248b4, 0x06b35c0b, 0x44202b82, 0x52222b82, 0x2b825e04, 0x2b85d120, 0x88f20021, 0x82f8202b, 0x2129212b, + 0x24082b86, 0xc7000100, 0xec047ffe, 0x1000b605, 0x5940a600, 0x18144005, 0xcd05bd48, 0x0305dd05, 0x10092005, 0x2a051a48, 0x05044305, 0xcd00bd27, + 0x0300dd00, 0x3c158400, 0x02002a00, 0x08101006, 0x7f100f0e, 0x020f9f0f, 0x0f300f00, 0x06030f40, 0x04050f0f, 0x3a72825a, 0x07020110, 0xb0120101, + 0x080c0112, 0x1164095a, 0xf0ffb80c, 0x100b1640, 0x82100648, 0x060c3a04, 0x030a0f09, 0x05055f00, 0xfb021209, 0x333f3f00, 0x333fe12f, 0x2b393912, + 0x08af6d2b, 0x335d5e2a, 0x2f3332e1, 0x385d5d5e, 0x11231982, 0x852b5d33, 0x30312901, 0x23113325, 0x07012311, 0x333f0582, 0x33013711, 0xb7350401, + 0x3dfe6cb1, 0x79baba8b, 0xfdd1c401, 0xd9fda6f8, 0xba028101, 0x19b8fd72, 0x2f09142d, 0xfeae0001, 0x042b0483, 0x000e004a, 0x086a4099, 0x0826e784, + 0x08dd08cd, 0xd1840803, 0x082a0824, 0x15840302, 0x03cd0326, 0x030303dd, 0x3f081584, 0x02032a03, 0x00460708, 0x86017601, 0x016d0201, 0x01015501, + 0x013b012b, 0x1403014b, 0x010b0101, 0x01030601, 0x04100400, 0x10040402, 0x470a020e, 0x090f540b, 0x000e0e02, 0x0850030b, 0x0cfb0515, 0x2105ca60, + 0xc284e13f, 0x2505dc44, 0x2f331132, 0x066c335d, 0x5d5d2205, 0x89e58211, 0x20cc82da, 0x84dd8501, 0xfa0238dc, 0x0161fec4, 0x66aec14b, 0xb4b44bfe, + 0xf1fd4a04, 0xe9fd5ffe, 0x18027d01, 0x08093781, 0x0000c748, 0xb605a204, 0x97001200, 0xff0f00b9, 0x125d40e0, 0x0f504815, 0x22020f60, 0x420f320f, + 0x4002030f, 0x0b480d09, 0x34085a07, 0x02125412, 0x03570f12, 0x1d0c0301, 0x040b0104, 0x00040401, 0x10136408, 0x00011111, 0x02820010, 0x07022008, + 0xb0140000, 0x142f0114, 0x01141001, 0x0809050b, 0x04300420, 0x04030440, 0x100d040d, 0x82080309, 0x323f2e65, 0x3939333f, 0x115d2f2f, 0x01393912, + 0x08c0835d, 0x5d5e2f24, 0x11333338, 0x11e61033, 0x5d5d2f39, 0x325dc133, 0xe1105d32, 0x00303132, 0x2b5d5d2b, 0x15012321, 0xad411123, 0x33112206, + 0x08e38215, 0xd3a2043c, 0x7785aefe, 0x8577baba, 0xfdd14101, 0xcdf401f8, 0xfd626401, 0xfdb605d7, 0x6301a406, 0xfda601b3, 0x00010065, 0x040000ae, + 0x004a0423, 0xb59c0013, 0x110b4011, 0xffb80a48, 0x0782b3c0, 0xb80e5208, 0x5740f0ff, 0x0e480d08, 0x0112260a, 0x13890712, 0x13a91399, 0x2f131f03, + 0x03133f13, 0x1301130b, 0x02060f13, 0x14540347, 0x100c0c0b, 0x0f20100f, 0x0f020f30, 0x1500150f, 0x00021510, 0x60154015, 0xa0158015, 0xe015c015, + 0x0e070715, 0x0806060d, 0x2b018213, 0x0f040b02, 0x00150210, 0x333f333f, 0x2f2ddc82, 0x1139122f, 0x5e013333, 0x3311715d, 0x22e2862f, 0x4e32e1f6, + 0xe5840568, 0xe2832b20, 0x27012b28, 0x33112311, 0xdb823711, 0x01331324, 0xef830115, 0xcf012708, 0x6db4b46d, 0xfec5eb7d, 0xcfd70150, 0x017df8fe, + 0xd3fd7bb2, 0xebfd4a04, 0xb946017b, 0x16fe0d01, 0x01e9fd49, 0x7f49cd27, 0x04270805, 0x00b605a2, 0x40850014, 0x66140240, 0x13140114, 0x500e4004, + 0x0e0e020e, 0x040c1000, 0x0507095a, 0x13121564, 0x41131310, 0x163b0aa7, 0x2f0116b0, 0x16100116, 0x5f060f01, 0x0009090c, 0x100b1002, 0xffb81048, + 0x830c40f0, 0x05022508, 0x05030a12, 0x8206b041, 0x2b2b21cd, 0x3322b782, 0xb24132e1, 0x382f250b, 0xc6f61033, 0xd3841482, 0x39121128, 0x3133115d, + 0x5a432130, 0x053d4d05, 0x23153322, 0x2a056243, 0x3dfed3a2, 0x9898ba8b, 0x43d5d5ba, 0x02310564, 0xb8fd72ba, 0xb2a46004, 0x7bfea4b2, 0xfd3302a8, + 0x08cb8283, 0x00001222, 0x1406f003, 0x84001600, 0x0e110f40, 0x08040f0e, 0x47130309, 0x01060014, 0xc0ffb806, 0x481510b3, 0x3a080783, 0x0e093540, + 0x0f060648, 0x54140116, 0x100d0c17, 0x35100f0d, 0x0f00010f, 0x0f200f10, 0x0f0f0803, 0x01180f18, 0x14021109, 0x15070f14, 0x0101044f, 0x0c150f02, + 0x0000020f, 0x853f3f3f, 0x053f4cc5, 0xaf820120, 0x21052044, 0xc9821133, 0x82c63221, 0x2b2b281c, 0x17e11071, 0x83391132, 0x33132fca, 0x21153335, + 0x03112115, 0x33013733, 0xd9860101, 0x9c122e08, 0xfe7b01b4, 0x87041085, 0xfed32501, 0xd1ac016f, 0xb46db0fe, 0xb65e059c, 0x75fe89b6, 0x01aaedfe, + 0xfd25fe69, 0x52f80191, 0xd5045afe, 0x3dd78200, 0x05000014, 0x00b60544, 0x4057000e, 0x0e0e0233, 0x5a040a0d, 0x05300520, 0x05800540, 0x008205f0, + 0x0c070024, 0x9e410d0d, 0x10102a0a, 0x0a020110, 0x5f070c05, 0x07854108, 0x1233e124, 0xb2863939, 0x82333821, 0x822f20b1, 0xe15d21ae, 0x7541aa86, + 0x35212306, 0xaa831121, 0xd344052a, 0xbb8b3dfe, 0x0f02acfe, 0x240a6e41, 0xfda41205, 0x076b4125, 0x00294008, 0x04c90400, 0x000d004a, 0x02404067, + 0x060b0d0d, 0x01070047, 0x07100700, 0x07600720, 0x080507c0, 0x09030707, 0x01d50100, 0x010201f5, 0x00100304, 0x02031003, 0x400f0303, 0x020fe00f, + 0x82010f0f, 0x09072733, 0x0f0a0050, 0xf4420307, 0x12e12705, 0x01331139, 0xee425d5d, 0x82078306, 0x5d5e29a2, 0x3232e171, 0x30313311, 0x22054241, + 0x82112311, 0x076908a5, 0xc5dd0311, 0xc70160fe, 0xb54cfecf, 0x1f0298fe, 0xfd4a0402, 0x02c5fdf1, 0x03d3fd2d, 0xfd029ab0, 0x010000ed, 0x7ffee500, + 0xb605a405, 0x63000f00, 0x5a043f40, 0x74010104, 0x94018401, 0x01010301, 0x5a050d11, 0x11e41100, 0xc00211f4, 0x10020111, 0x40112011, 0x04118011, + 0x095a080c, 0x5f071064, 0x08010c0f, 0x0e050c0c, 0x21c3820a, 0x2646055f, 0x33e12305, 0x9184333f, 0x2646e120, 0x5d5f2605, 0xe1dc105d, 0x21af8332, + 0x1846e171, 0x6e112007, 0x112d06a0, 0xb0f40433, 0x67fdbbb0, 0x9902bbbb, 0x051346bb, 0x676eaa20, 0x68022105, 0xae269b82, 0xdb0483fe, 0x9b824a04, + 0x5240793a, 0x04470008, 0x0b0b010b, 0x0cc4470f, 0x0c020cd4, 0x1104110c, 0xd4021124, 0xb0209e83, 0x30209e82, 0x50209c82, 0x26089e82, 0x11a01190, + 0x47030706, 0x0d105404, 0xeb5002fb, 0x07a90107, 0x0f0207b9, 0x2f071f07, 0x07060307, 0x05090007, 0x51500b0f, 0xe1200585, 0x5d23ad86, 0x883fe15d, + 0x837120b0, 0x33e128ad, 0x32e15d2f, 0x89213031, 0x33112fac, 0x03112311, 0xb6dffd85, 0xb62102b6, 0xe572b6a0, 0x054d5109, 0xe536b182, 0x48060000, + 0x0d00b605, 0x3b405d00, 0x005a0109, 0x0b400500, 0xb782e001, 0x43200f21, 0x2108053e, 0x0f400f30, 0x0fa00f60, 0x0fe00fb0, 0x04080608, 0x0e64055a, + 0x0a0a5f0d, 0x0f5f0306, 0x08080108, 0x8d420608, 0x2f392407, 0x82e15d5e, 0x0549418a, 0x715d5e29, 0x715dc610, 0x842f3911, 0x88232095, 0x15212496, + 0x41f40421, 0x02240643, 0x02acfe0f, 0x21084141, 0xa14500a4, 0xa4052305, 0x91824a04, 0x21406833, 0x05470408, 0x00470109, 0x54050b00, 0x0f0b0b0e, + 0x21958200, 0x8b829002, 0x0fc03208, 0x0ff00fd0, 0xffb80f05, 0x071f40c0, 0x5003480c, 0xa90108eb, 0x0208b908, 0x081f080f, 0x0603082f, 0x0d000808, + 0x050f060a, 0x3f001500, 0xc4333f32, 0x249e8312, 0x01e15d5d, 0x2394822b, 0xe6102f33, 0x10209984, 0x3b219c92, 0x053141b6, 0xfe1f0223, 0x09324197, + 0x9b829a20, 0xfec72e08, 0x05db0700, 0x002700b6, 0x093a405f, 0x1207010b, 0x5a200012, 0x18252121, 0x6f29085b, 0x5a240129, 0x1d286425, 0x2f030f60, + 0x03033f03, 0x3c04820f, 0x03ff03df, 0x03030804, 0x265f2325, 0x12252103, 0x0d5f1613, 0xe13f001c, 0x3f333f33, 0x299284e1, 0x1001e171, 0x105de1f6, + 0x9084e1de, 0x312f3927, 0x5d5e0030, 0x17684d01, 0x07222323, 0x054b4111, 0xc1042129, 0x9a2e491e, 0x4d56a5f0, 0x4335056b, 0x7e3f1f3d, 0x43770149, + 0x4b6bae7c, 0x7bfdbb33, 0x03fa03ba, 0x166b4d1b, 0x89fd0c26, 0xeefa1205, 0x5808cb82, 0xfeae0001, 0x0475060a, 0x0024004a, 0x0b4e4077, 0x02231b23, + 0x11190303, 0x01120247, 0xa60112c2, 0x0212b612, 0x12871277, 0x16121202, 0x2620480a, 0x261f260f, 0x5f264f02, 0xff26af26, 0x26100426, 0x16471501, + 0x510d2554, 0x1b1b1b0b, 0x1b1b0702, 0x17501416, 0x1516120f, 0x06884d04, 0xe885e989, 0x85715d21, 0x5d5d25ea, 0x32e1715d, 0x8e4dee84, 0x18e68415, + 0x2108444c, 0x8f4dd904, 0x3e1c2a09, 0x08feb61f, 0x3a6403b6, 0x158f4d3f, 0xfcb00328, 0xfe4a0450, 0x914d0c27, 0x02660808, 0xacff7d00, 0xcd059605, + 0x52003e00, 0x50407a00, 0x32104e05, 0x5b490004, 0x20102000, 0x35203502, 0x5b3f1820, 0x0f546700, 0x4f541f54, 0x7f545f54, 0xaf549f54, 0x2b070754, + 0x5366185b, 0x054e6044, 0x3a103a00, 0x3a603a20, 0x3a803a70, 0x073a3a06, 0x1d215f26, 0x30321004, 0x5f07135f, 0x13130e0e, 0x2f333f00, 0xd08210e1, + 0xe1333f28, 0x5d2f3912, 0xee843939, 0xa2185e20, 0x5d36083a, 0x391712e1, 0x14013031, 0x1607020e, 0x37363233, 0x23060615, 0x04652722, 0x032e2110, + 0x21097d6e, 0x4f632637, 0x34072308, 0x1887022e, 0x3e17ee08, 0x276f0503, 0x362d5541, 0x1f462551, 0xa6264f1d, 0x3c7c328b, 0x519de896, 0xa6f29e4d, + 0x35257842, 0x3330280a, 0x6ca97615, 0xa0703c33, 0x4f263064, 0x8360375b, 0x62854b4c, 0x2a16c539, 0x3d29273d, 0x29181529, 0x422a1f36, 0xa602182e, + 0x6f90af65, 0x0b0e1924, 0x620c0daa, 0xc06a1111, 0xb5a50e01, 0x69c71f01, 0x059c0f16, 0x5105090a, 0x948dde9a, 0x074690da, 0x9b160169, 0x3b7bc185, + 0x95c67b38, 0x36638954, 0x50876237, 0x65768548, 0x77622127, 0x02000088, 0xc5ff7100, 0x5e04a404, 0x4d000d00, 0x49407900, 0x32110544, 0x48003f04, + 0x21642154, 0x35213502, 0x48081921, 0x3f4a4a3f, 0x4f7b4f57, 0x4fbb4f8b, 0x6f4f5f03, 0x4f1b024f, 0x014f0f01, 0x482a0207, 0x0b4e5619, 0x3a3a0544, + 0x22502547, 0x3211101e, 0x4714502f, 0x140e0e50, 0x0a5a4116, 0x3912e92d, 0xc139392f, 0xe1f61001, 0x825d5e5f, 0xe6102500, 0xe1102f32, 0x41053078, + 0x1e210760, 0x06e55302, 0x01062223, 0x0d976422, 0x64661620, 0x3736270d, 0x34352626, 0x3953023e, 0x020e2305, 0x99411607, 0x02920807, 0x2a2014dd, + 0x38483915, 0x01413e3d, 0x3988454c, 0x75476228, 0x3c3f7ab3, 0x4279b478, 0x13291a52, 0x70542a4a, 0x431e1c43, 0x3225506e, 0x314a3903, 0x40417255, + 0x1e2e526f, 0x14274534, 0x391a1d37, 0x0142191c, 0x4b5c35f4, 0x96281239, 0x7a7a676b, 0x252a68fd, 0x97571711, 0xd68375cc, 0x06105397, 0x3a100596, + 0x5967a06f, 0x083c6b94, 0x77b44202, 0x2b59885e, 0x638a5627, 0x4d637846, 0x060d0a1b, 0x07099308, 0x7d00ffff, 0x980442fe, 0x2602cb05, 0x754d2600, + 0x2f022d05, 0x0e000000, 0x750101b7, 0x20182c32, 0x8205724d, 0xfe712a27, 0x046f0342, 0x0026025e, 0x21278546, 0x27867101, 0x282e5224, 0x27850d05, + 0x01005708, 0x7ffe1400, 0xb6051204, 0x6f000b00, 0x0d1f3940, 0x010de001, 0x0ddf0d5f, 0x300d2002, 0x030d400d, 0x010f5a04, 0x0702011f, 0x0aaf0101, + 0x0a020aef, 0x065a0b0a, 0x07e00740, 0x01070f02, 0x57070708, 0x77066706, 0xb8060306, 0x0f40c0ff, 0x06480a07, 0x085f070b, 0x4b470003, 0xe13f3108, + 0x2b2f0132, 0x5e2f335d, 0xe1105d5d, 0x395d2f32, 0xe1240982, 0x715d5d5d, 0x37094947, 0x21152135, 0xb0b07102, 0x035efebb, 0xa65ffefe, 0x8101d9fd, + 0xa4a41205, 0x0027b682, 0x0383fe29, 0x844a045e, 0xf04d399d, 0x0daf010d, 0x500d4001, 0x0d2f020d, 0xaf470b01, 0xcf08bf08, 0x40080308, 0x33087882, + 0x05df0808, 0x01059d01, 0x0501058f, 0x00470705, 0x02700260, 0x1f0302d0, 0x02020102, 0x00100000, 0x00c000b0, 0xfb090004, 0x03500206, 0x0050070f, + 0xe13f0015, 0x3f209c82, 0x0a568b18, 0x39209582, 0x9d83ab82, 0x30315d25, 0x83211121, 0x33113898, 0x01112311, 0x03c1fe68, 0x9fc1fe35, 0x9ab003b6, + 0xfdeafc9a, 0x6d7d01e9, 0x37270795, 0x0602b605, 0x83003c00, 0xfe0024ad, 0x82d50314, 0x001336ad, 0x0a13407c, 0xa647000a, 0x01870101, 0x01020197, + 0x12110301, 0x0c4e5010, 0x07204208, 0x1212480b, 0x0115f015, 0x15ef15df, 0x90155002, 0x0315a015, 0x3001154f, 0x150f0115, 0xb8030401, 0x1040f0ff, + 0x0f031103, 0x0a150a05, 0x0a130702, 0x1b001502, 0x333f3f00, 0x3f5d5e33, 0x382f0133, 0x82b08233, 0x33112902, 0x382b2b2f, 0x2f391233, 0x2205ed72, + 0x82013031, 0x333908b1, 0x17031e13, 0x37033e33, 0x02013313, 0x71feb746, 0x2010c7bc, 0x0705141b, 0x201b1504, 0xfebcc710, 0x0114fe71, 0xfd4e04e8, + 0x5e642ecf, 0x4f19194f, 0x022e645e, 0x00b2fb31, 0x21c98201, 0xd5820400, 0x10002e08, 0x19409f00, 0x120112ef, 0x480c0940, 0x08040000, 0x090d095a, + 0x77010996, 0x02098709, 0xc0ffb806, 0x18150d40, 0x06090b48, 0x030b0906, 0x05b36402, 0xab383c08, 0x0f90010f, 0x010f1401, 0x1002010f, 0xef010210, + 0x02d00102, 0x0102bf01, 0x4f010280, 0x02025f02, 0x00010214, 0x02070102, 0x0a071202, 0x0d00045f, 0x1208010d, 0x0003010f, 0x823f333f, 0x333928c2, + 0x011132e1, 0x855e2f33, 0x715d23db, 0xd6823338, 0xde825d20, 0x2f39172e, 0x5d2b2f2f, 0x1033115d, 0x3d3932e1, 0xe8820a82, 0x01330123, 0x05c25515, + 0x35212808, 0x33013521, 0x54011b02, 0x0142fec8, 0xbbd9fe27, 0x2601dafe, 0x02cb42fe, 0xfce302d3, 0xfea43d83, 0xa45801a8, 0x41870333, 0x19310ba7, + 0x15408500, 0x01170e0e, 0x02a60647, 0x97028701, 0x23008202, 0x10161507, 0x080cb277, 0x0b072037, 0x1b161648, 0xdf011bf0, 0x021bef1b, 0x1b901b50, + 0x4f031ba0, 0x1b30011b, 0x011b0f01, 0xffb80708, 0x071340f0, 0x000f0715, 0x0e054f03, 0x07020e15, 0x1506170e, 0x07ac4101, 0x4132e121, 0xec8217ae, + 0x3125c982, 0x23110530, 0x20c08211, 0x0bb44101, 0x0215212a, 0xf6feb746, 0x73fe0801, 0x2910ba41, 0xfe890a01, 0x8963019d, 0xbe414a04, 0xb62b080e, + 0x00010089, 0x047ffe00, 0x00b605b4, 0x4006010f, 0x010f4788, 0x03010948, 0x060b000f, 0x0e070a05, 0x0b000c07, 0x080a0509, 0x820c080d, 0x09002112, + 0x32081482, 0x0f0c0905, 0x0e060603, 0x01050a08, 0x05ba05aa, 0x05ea05ca, 0x050505fa, 0x480e0b30, 0x015a0405, 0x0b100e0d, 0x0eab010e, 0x0ecb0ebb, + 0x0efb0eeb, 0x82400e05, 0x0a0e2f19, 0x00aa0100, 0x00ca00ba, 0x00fa00ea, 0x2d830005, 0x000e3e08, 0x01140104, 0x01010702, 0xe411d411, 0x0311f411, + 0x020111c0, 0x11401120, 0xffb81102, 0x100b40c0, 0x110f4814, 0x0a0a0b01, 0xffb80807, 0x081440f0, 0x27010628, 0x060c010c, 0x030a0d05, 0x09354407, + 0x333f3328, 0x5d393912, 0x7c54015d, 0x2b5d2405, 0x4d5d5f5d, 0x33250586, 0x715d2b33, 0x2403822f, 0xe1103338, 0x30078232, 0x3d391211, 0x1033172f, + 0x04c00e87, 0xc08710c0, 0x2204820e, 0x8608c008, 0x82012005, 0x08cb5137, 0x08058f54, 0x01330143, 0xb0b6fe03, 0xfe9efe77, 0xc501bc91, 0x01c65afe, + 0xbe4e014c, 0xfda65bfe, 0x028101d9, 0x0285fd7b, 0xfdba02fc, 0xfd2f02d1, 0x0100004c, 0x83fe2300, 0x4a041f04, 0x39010f00, 0x0d592540, 0x01035601, + 0x3ab282b4, 0x48110e20, 0x29010c3d, 0x0c0b010c, 0x0c020c1b, 0x0008460b, 0x0d030603, 0x8304010d, 0x714508da, 0xb5481815, 0x04990104, 0x6a0204a9, + 0x8a047a04, 0x04450304, 0x06020455, 0x05040104, 0x02eb02db, 0xc90302fb, 0x02bb0102, 0xa6029601, 0x02650202, 0x02850275, 0x5a024a03, 0x01020202, + 0x05ef05df, 0x050305ff, 0x3a638240, 0x054b053b, 0x01052702, 0x051a050a, 0x44013402, 0x01280201, 0x15010501, 0x82050201, 0x3b0f2406, 0x83070107, + 0x0754088a, 0xc0ffb808, 0x0c074940, 0x11080848, 0x11801160, 0x11b01190, 0x11e011d0, 0xdb0711f0, 0x0ec9010e, 0x010eba01, 0x0e750e65, 0x4a030e85, + 0x020e5a0e, 0x0e010e09, 0x0f4b0f3b, 0x010f2802, 0x0f150f05, 0x0d030f02, 0x50070e01, 0xfb09150c, 0x000f0104, 0x3f3f333f, 0x24054c4e, 0x5d5d5d2f, + 0x068e43c5, 0x2f33112a, 0x5d2b332b, 0x2f393912, 0x15821683, 0x105d2b22, 0x07861c86, 0x90412b20, 0x32e12106, 0x312a1d84, 0x5d5d0030, 0x13330101, + 0x04563313, 0x232c0805, 0x01230101, 0xcf9ffe98, 0xfecffafa, 0xaa0f019d, 0xf4fe65ae, 0x02cff2fe, 0xfe170233, 0xfd9a0166, 0xfd67fee9, 0x017d01e9, + 0x004cfeb4, 0x33059f46, 0xb6056006, 0x94000f00, 0x5a010d40, 0x5a080404, 0xd0010510, 0xf183fd82, 0x07444408, 0x05054812, 0x0111df11, 0x0f0111a0, + 0x4f112f11, 0x04118f11, 0x200e1007, 0x500e400e, 0x800e600e, 0x0e0e060e, 0x0f095a00, 0x2f0b1f0b, 0x6f0b5f0b, 0x060baf0b, 0x300b0b08, 0x50094009, + 0x90098009, 0x83090509, 0x07112348, 0x2482480a, 0x0c025f30, 0x5f000403, 0xfb061209, 0xe13f3f00, 0x3e5a3f32, 0x2f332206, 0x05bf465e, 0xd5825e20, + 0x2f33112f, 0xe1715d2b, 0x31e12f33, 0x11212530, 0x21018233, 0x2f461123, 0x71022806, 0xb0ba8502, 0x4606fcb0, 0x052106cc, 0x05b85f10, 0xa4120523, + 0x26cd82a4, 0x0583fe29, 0x824a046d, 0xb68028cd, 0x0e0e470b, 0x820f4702, 0x0eb3237d, 0x07834818, 0x0733402a, 0x0f0f480b, 0x1f110f11, 0xbf20ca84, + 0x062ed882, 0xe0086007, 0x0308f008, 0x470a0808, 0x1a421f03, 0x00052a06, 0x60031003, 0x04037003, 0x2fbd8403, 0x03481814, 0x0c500509, 0x0a0e0f06, + 0x00150350, 0xbc87bd8f, 0x2b20ba83, 0x0120b985, 0xbb82b388, 0x0524c382, 0xb2fcb76d, 0x2705e746, 0xa0b6f801, 0x7d0183fe, 0x2405ed46, 0x50fcb003, + 0x3ebb8200, 0x057ffea6, 0x00b60531, 0x4063001d, 0x1b0d0b12, 0x041a020d, 0xa01d905a, 0x1d1d021d, 0x83005a03, 0x2c2b0887, 0x00481007, 0x1f0f1f00, + 0x1f2f1f1f, 0x1f5f1f4f, 0x1faf1f7f, 0x07081fbf, 0x640f5a12, 0x1a5f151e, 0x1b040a0a, 0x5f1d0310, 0x84011204, 0x333f25a2, 0x332f3912, 0x8306184b, + 0x07b44e9c, 0x11255d23, 0x26018223, 0x2223030e, 0x1835022e, 0x2008834f, 0x35098237, 0xbab03105, 0x6163693a, 0x65925d31, 0x7b69ba35, 0x665e5a2d, + 0xbe43ba38, 0x16563605, 0x310c1622, 0x02598b5e, 0x73d1fd47, 0x1e140a74, 0xfac60214, 0x08bd82f0, 0x83fe9a23, 0x4a049e04, 0x61001c00, 0x090b1740, + 0x092b091b, 0x00150703, 0x1c181847, 0x10190047, 0x03192019, 0x08c28319, 0x150e2522, 0x1e191948, 0x1e5f1e0f, 0x1ebf1e7f, 0x0e051ecf, 0x1d540b47, + 0x1015fb1a, 0x00060650, 0x180f0c16, 0x83063d48, 0x33e127ba, 0xf610013f, 0xba835de1, 0xbb825d20, 0x3132e127, 0x215d5e30, 0x23b78a11, 0x023e3233, + 0x3320b683, 0x0334ce82, 0x55502c48, 0x7a4e3a5e, 0xb8b62b52, 0x4d4c502d, 0xb7a0b62a, 0x0baa9118, 0xae66fe28, 0x1d2b1c0f, 0x8f4fd501, 0xa6580808, + 0x81040000, 0x1d00b605, 0x2e407000, 0x041b040b, 0x1d0f1c02, 0x0e140e04, 0x0e0e0702, 0x5a171306, 0x701f6516, 0x021fa01f, 0x10011f2f, 0x5a09011f, + 0x06700660, 0x06b006a0, 0xffb80604, 0x071640c0, 0x0e06480a, 0x131d0e10, 0x0c031d1b, 0x1701015f, 0x17030714, 0x3f3f0012, 0x1726be84, 0x32322f33, + 0xf648012f, 0x27c98206, 0x2f391132, 0xc1335d5e, 0x5d21c782, 0x0a7b4101, 0x33113325, 0x83363611, 0x112329c7, 0x11070606, 0x21500223, 0x2c067f41, + 0x7638850c, 0x42baba44, 0x01853977, 0x097b41fc, 0x58012108, 0x2209b4fe, 0xfac60219, 0x1a56024a, 0xc9fe0b25, 0x9a000100, 0xfe030000, 0x1c004a04, + 0x42406b00, 0x2308cd84, 0x1c0e1b07, 0x04010d50, 0x240d140d, 0x0d08030d, 0x1612060d, 0x1e55155a, 0x1e601e10, 0x09031e80, 0x1d54065a, 0x28068b4a, + 0x1c0d0f0d, 0x031c1a12, 0x25c6820b, 0x0f071316, 0xc68d1516, 0x8805f374, 0x23c585c4, 0x30315d5e, 0x3320c889, 0x0e21c791, 0x058e412f, 0x7d062708, + 0xb6335b2f, 0x325932b6, 0x2f6a017d, 0x01447354, 0xae66fea6, 0xe5fe2d01, 0x0123300e, 0x01b6fbd5, 0x103323e9, 0xc58200ff, 0x08070f57, 0x5000173a, + 0x07043640, 0x07020714, 0x650b5a0c, 0x5f192f19, 0x8f196f19, 0xaf199f19, 0xef19cf19, 0x0919ff19, 0x02011910, 0x64175a16, 0x5f101518, 0x05100500, + 0x17050502, 0x0300120b, 0x3923b983, 0x57e15d2f, 0x5d2005ae, 0x2505a675, 0x135d5e00, 0xe84f1133, 0x11330806, 0x26341123, 0x020e2223, 0xc7231107, + 0x62c373ba, 0x3565925d, 0x2d7b68bb, 0x38655f5a, 0xfdb605ba, 0x312d2daa, 0xfd598a5e, 0x732f02b8, 0x1e140a75, 0x5139fd14, 0x2408052d, 0x4a041204, + 0x3f001800, 0xff1400b9, 0x072240e0, 0x4700480a, 0xef1a5518, 0x1a10011a, 0x1a801a60, 0x47090d03, 0x7494180a, 0x0a0f2107, 0x21050f51, 0x8b8e2f39, + 0x11212b23, 0x227e8634, 0x60113311, 0x1122064c, 0xb7425c03, 0x42b62006, 0x6b0808c9, 0x0fae9a01, 0xfe1c2c1c, 0xfe4a042b, 0x202f1f16, 0x73532f11, + 0x005afe44, 0xff3d0002, 0x050606ec, 0x002b00cd, 0x40640036, 0x145b323e, 0x0f38670b, 0x02381f38, 0x01222029, 0x0c312222, 0x1f70005b, 0x1fc01f80, + 0x1f371f03, 0x4f31600c, 0x2b0f012b, 0x2bff2baf, 0x01250f03, 0x2b252b08, 0x5f110525, 0x2c131a14, 0x0004055f, 0x333fe13f, 0x3905d84d, 0x715d5d5e, + 0x0132e133, 0x325dd610, 0x2f3332e1, 0x105dc15d, 0x31e132f6, 0xa6830130, 0x1216162c, 0x1e211515, 0x36323303, 0x88431537, 0x27eb0805, 0x34352622, + 0x06333736, 0x33141506, 0x020e2201, 0x2e342107, 0x0a660102, 0x8ddd9c5b, 0x3e88d699, 0x3f0725fc, 0x8070a974, 0x5b2a5bcf, 0x984c7c69, 0x095ca4eb, + 0x0b129a8f, 0x670f069c, 0x955b8902, 0x0307416e, 0x8b562512, 0xf49a3903, 0xc56b5bab, 0x45abebfe, 0x4786c27a, 0x0faa202c, 0x610a121a, 0x759bfdb3, + 0x17422a7a, 0x61233e0f, 0x7e41f001, 0xb87578b9, 0x00004380, 0xff330002, 0x04b604ec, 0x002c005e, 0x40840035, 0x2748312b, 0xff37571e, 0x37900137, + 0x1f0237b0, 0x02377f37, 0x05481f30, 0x0108df0f, 0x00130808, 0x20051005, 0x05400305, 0x05020550, 0x40c0ffb8, 0x48131028, 0x1f053605, 0x121b3050, + 0x0f02122b, 0x0b1b0112, 0x0f020b2b, 0x1206010b, 0x220b120b, 0x1018502d, 0x00275122, 0x323f0016, 0x12e13fe1, 0x4b2f3939, 0x3332053b, 0x100132e1, + 0x715d2bc6, 0x5d2f3232, 0x32e110c1, 0x23415d5d, 0x22052506, 0x2627022e, 0x21090f41, 0x29623316, 0x15340807, 0x33161621, 0x37023e32, 0x03030e15, + 0x21070622, 0x03022e34, 0x82b36b35, 0x8e85044b, 0x06950912, 0x1b31310e, 0x98744c0e, 0x6e9e635a, 0x054cfd3b, 0x57339799, 0x0e9b3819, 0x14598208, + 0x81c78846, 0x27726f02, 0x3a0e153f, 0x6c312f22, 0x473e75a9, 0x716eb581, 0x130ab6c1, 0x13a2121d, 0x0308121c, 0x44959cdb, 0x002c5071, 0x3d000200, + 0x06067ffe, 0x2e00cd05, 0x72003900, 0x5a1b4640, 0x35221c1c, 0x670b145b, 0x1f3b0f3b, 0x202c023b, 0x25250125, 0x005b0c34, 0x22802270, 0x220322c0, + 0x600c223a, 0x012e4f34, 0x2e3f2e0f, 0x0f032eaf, 0x2e080128, 0x05282e28, 0x6011141a, 0xfb1b121d, 0x062b422f, 0x33e13f22, 0x42056159, 0x1222162d, + 0x31422f39, 0x11072516, 0x032e1123, 0x2a2a3342, 0x64584e25, 0xc480b63a, 0x42084d8a, 0x0e2d2634, 0x020b1117, 0x730191fe, 0xebb06d10, 0x133a428e, + 0x00027508, 0x0483fe33, 0x005e04b6, 0x0036002d, 0x04304092, 0x0b050547, 0x242d4832, 0x38ff3857, 0xb0389001, 0x381f0238, 0x3102387f, 0x150b4825, + 0x0e010edf, 0x0b00190e, 0x0b200b10, 0x500b4003, 0xb80b020b, 0x2b40c0ff, 0x0b481310, 0x50250b37, 0x2b181b31, 0x180f0218, 0x2b111b01, 0x110f0211, + 0x11180601, 0x2e281118, 0x28101e50, 0x06032d51, 0x00fb0416, 0x33333f3f, 0x41244342, 0x25220539, 0x28410606, 0x1d4c4206, 0x49420120, 0x85042a06, + 0xb64c8042, 0x38638954, 0x1c4d4203, 0x7283fe36, 0xec010b85, 0x3559391b, 0xfe042320, 0x11750195, 0x6fb28454, 0x21195242, 0x4d42f002, 0xff3a0806, + 0x005200ff, 0x05640200, 0x000602b6, 0xff00002c, 0x000400ff, 0x07810600, 0x01260269, 0x010000b0, 0x00360207, 0x005201f4, 0x010b4013, 0x01260517, + 0x11121c00, 0x2b01250a, 0x02820035, 0x05232d85, 0x821706be, 0x86d0202d, 0x0093212d, 0x09af8e18, 0x0e212d82, 0x202d8707, 0x05756300, 0x05e14308, + 0x002500b6, 0x1b3f4067, 0x5b21051b, 0x100a0911, 0x180c400a, 0x040a0a48, 0x27102711, 0x0b022740, 0x5a040808, 0x1f266405, 0x1c161c5f, 0x60000308, + 0x0c5f0c2f, 0x0cff0cef, 0x10400c04, 0x0c0c4815, 0x73630905, 0x12332906, 0x5d2b2f39, 0x3f3333e1, 0x23050f49, 0x5d331132, 0x2905ca71, 0xe1103338, + 0x312f3911, 0x97620130, 0x11332405, 0x52013301, 0x756307a1, 0x46022c0d, 0xba285c41, 0xcf3502ba, 0x5606d1fd, 0x7f370d09, 0x43770148, 0x6f02ae7c, + 0xb0fd0e11, 0x3cfdb605, 0x58fdc402, 0x63eca355, 0xb3220e76, 0xdb823a76, 0xfeae5408, 0x04e9030a, 0x0023004a, 0x0b474072, 0x02081b08, 0x1f102322, + 0x23230123, 0x0d0d051d, 0x0548141e, 0x01250f25, 0x256f255f, 0x259f257f, 0x25df25bf, 0x000725ff, 0x471d2121, 0x2124541e, 0x0b51191c, 0x02001b00, + 0x1e000007, 0x1e0f1f22, 0x0e511115, 0x82001b0a, 0x057648d8, 0x825d5e21, 0x100123e6, 0xe383e1f6, 0x2006fd55, 0x29fe8211, 0x31333871, 0x015d0030, + 0x4f64031e, 0x09926305, 0x63022e21, 0xfb830693, 0x2b022908, 0x4578a35e, 0x57966f3f, 0x2c2f694c, 0x75764369, 0x4e724a23, 0xb4295520, 0xc49801b4, + 0x40056a02, 0x9694d084, 0x1f4088d5, 0x2d059263, 0x2d60976a, 0x50fe0d10, 0x0afe4a04, 0xdd82f601, 0x7ffe0026, 0xb6055605, 0x3a08dd82, 0x0207b173, + 0x40f8ffb8, 0x48171446, 0x18895a02, 0x18101801, 0xb4011de0, 0xd41dc41d, 0x1d00031d, 0x07021d50, 0x0f1f1d1d, 0x00222221, 0x1f20235a, 0xc0259025, + 0x0325f025, 0x821f250f, 0x080333f9, 0x02fb210f, 0x13031d5f, 0x1f130c60, 0x0012005f, 0x0184e13f, 0x5e2f012a, 0xd4105d5d, 0x39e13232, 0x8205356c, + 0x335d2f0e, 0x2be15d38, 0x21303132, 0x030e2111, 0xbc7e0e07, 0x3636250c, 0x21371212, 0x2a05196b, 0x0f85fed9, 0x10212120, 0x184f3514, 0x2c120ab8, + 0xd98fc3d0, 0x711205a5, 0x51d4ebf5, 0xf9b71867, 0x056e4c12, 0xe5820020, 0xfe104108, 0x04660483, 0x0018004a, 0x02384058, 0xe412d446, 0x12600212, + 0x12a01270, 0x340412b0, 0x12120112, 0x1717160a, 0x15184700, 0x201a5514, 0x021ab01a, 0x08011a0f, 0x02fb160a, 0x0d0f1250, 0x1416074f, 0x8306e84a, + 0x20d185d3, 0x25d186f4, 0x5d5d2f39, 0xca84e15d, 0xa0180220, 0xc4840ff8, 0xfefa0239, 0x5f4014fe, 0x311c5682, 0x371c1610, 0x12334559, 0x7ab65402, + 0x18037bb7, 0x250f00a1, 0xe9fd50fc, 0xaf837d01, 0xfee53b08, 0x05f40400, 0x001b00b6, 0x052b404b, 0x0c141005, 0x1d65175a, 0xbf011dc0, 0x1d20011d, + 0x5a0f1301, 0x0e1c6410, 0x01130f5f, 0x10131308, 0x10031115, 0x065f0912, 0x3f001c00, 0x5742e132, 0x10012208, 0x06eb46f6, 0x4332e121, 0x2e210633, + 0x07d96502, 0x11211125, 0x82331123, 0x11332605, 0x02020e14, 0x078e66d1, 0xfdc6bb22, 0x2405c05b, 0xfec99252, 0x06826600, 0x02f7f023, 0x07c95b1f, + 0xaaddfa25, 0x434fa2f8, 0x04230517, 0x824a043b, 0x406924a3, 0x8203031a, 0x473408a3, 0x001d5517, 0x021d201d, 0x1d401d30, 0x1dd01d50, 0x1d051df0, + 0x40c0ffb8, 0x48110e28, 0x10470f13, 0x500e1c54, 0xa90113eb, 0x0213b913, 0x131f130f, 0x0603132f, 0x0f25bf84, 0x51071510, 0x8a4a8204, 0x1d4418bf, + 0x5d2b2207, 0x86c88371, 0x060743c1, 0x35023e22, 0xa02ac18e, 0x2c2f694c, 0x5b3b4269, 0xa15a1f3d, 0x3fb62105, 0x2f088a66, 0x6996612d, 0x17feb201, + 0x39fe4a04, 0xf3fbc701, 0x36068766, 0x057ffee5, 0x00b605b6, 0x4052000f, 0x03030232, 0x045a050d, 0x5d110001, 0xc020071a, 0x5d053350, 0x102f2b20, + 0xe13232d4, 0x332f3932, 0x33253031, 0x5b132303, 0x332609d8, 0x8fc2f404, 0x1e5da6d9, 0x01002917, 0x83feae00, 0x4a04f204, 0x76318d82, 0x0e0d4f40, + 0x4700080e, 0x0bab0c0f, 0x0b020bbb, 0x581c5d11, 0x5dd41022, 0x1c5db188, 0x20bc820c, 0x071c5d03, 0xb67bb723, 0x09eb5b7a, 0x2209a542, 0x4d7ffea6, + 0x592a068f, 0x5a1d2140, 0x00161a1a, 0x824d195a, 0x0e30080c, 0x700b605a, 0xb00ba00b, 0xb80b040b, 0x1440c0ff, 0x0b480a07, 0x065f1116, 0x1b1a0c06, + 0x1a5f1dfb, 0x030c1712, 0x3f333f00, 0x12113fe1, 0x33e12f39, 0x250b7e4d, 0x31e12f32, 0x3f4e2530, 0x0592490b, 0x11331123, 0x21018223, 0xf94ec703, + 0xb0ba2411, 0x4eb001a6, 0x4a2414f7, 0x27027ffe, 0x4d05fb4e, 0x402a0675, 0x471b2540, 0x1c141818, 0x624d1747, 0x470d3308, 0x191d540a, 0x500f14fb, + 0x1b0b0505, 0x15151850, 0x9e840f0b, 0xdf4e9c84, 0xf6102305, 0x9a8432e1, 0xd94e0120, 0x20988312, 0x13da4e33, 0x4ea0b621, 0xfb2514db, 0x0283feb6, + 0x3d978217, 0x067ffec7, 0x00b605f2, 0xb69a001f, 0x39011f36, 0xb81f0100, 0x2c40f8ff, 0x1f480f0c, 0x05820800, 0x0d0d0029, 0x1209100c, 0x830e1313, + 0x0e39340d, 0x151d0e01, 0x1011145a, 0xc0212021, 0x210f0221, 0x830b0801, 0x82102030, 0x0b263f2a, 0x08020b01, 0x2064095a, 0xb80c5f10, 0x1640f0ff, + 0x00481209, 0x15030c09, 0x1efb1212, 0x46820101, 0x0e014824, 0xd982030a, 0x112b332a, 0x173f3f33, 0x01e12b33, 0x5d21d784, 0x07ad452b, 0x5d323223, + 0x05b1452b, 0x3311392b, 0x312b332b, 0x215d5d30, 0x08546d01, 0x33012123, 0x05a44501, 0x11233908, 0x37023e34, 0x01233736, 0x45fe2303, 0x04040508, + 0x1401ac06, 0x01069c01, 0xc314019e, 0xbaa6d990, 0x02020201, 0xfe080403, 0x4a000541, 0x398b3f49, 0xb60596fc, 0xa80458fb, 0x2a059f45, 0x3d197703, + 0x471e4241, 0x4302fb49, 0x70080505, 0x4a04c705, 0x87002400, 0x07085a40, 0x20101818, 0x1e232322, 0x21244600, 0x20bf20af, 0xe0262002, 0x26cf0126, + 0x40263001, 0xa0265026, 0x260f0426, 0x0f120601, 0x25541046, 0x3b01fb22, 0x5b0e4b0e, 0x0e0b030e, 0x0e2b0e1b, 0x1e0e0e03, 0x50200f11, 0x18441834, + 0x05031854, 0x25181518, 0x10080318, 0x15000318, 0x32173f00, 0x3fe15d5d, 0x5d2f3333, 0x05b8505d, 0xf9823220, 0x435d5d21, 0x11210910, 0x38f88212, + 0x21303133, 0x07030e11, 0x2e012301, 0x23112703, 0x1e013311, 0x033e1703, 0x06bb7137, 0x066f0422, 0x142da618, 0x06050e2f, 0x0d16130e, 0xb7d90e01, + 0x037ab67b, 0x31a61881, 0x0554431f, 0x2b12b549, 0x04000000, 0x026907dd, 0x00240026, 0x2005b549, 0x05b54921, 0x051a0228, 0x1f000226, 0x87490415, + 0x263d8208, 0x03ecff5e, 0x821706a1, 0x8244202d, 0x0206322d, 0x0000d436, 0x020b4013, 0x02261138, 0x0c333d25, 0x07b34922, 0x59852b82, 0x59872b20, + 0x006a0022, 0x172c5983, 0x02030d40, 0x0326051e, 0x29150102, 0x95185b85, 0x5d8308fd, 0x19059c21, 0x2d287b14, 0x0000feff, 0xb6055606, 0x88000602, + 0x9d850000, 0x04440623, 0x200f825e, 0x240f84a8, 0x030000c7, 0x20db84c8, 0x21db8528, 0xdb85fbff, 0x05110129, 0x16060126, 0x8a00010c, 0x827120af, + 0x84e120db, 0x854820db, 0x19ea20db, 0x22164107, 0x82000200, 0x053e082b, 0x00cd0512, 0x0029001e, 0x242f4049, 0x670e5b1a, 0x8f2b0f2b, 0xbf2baf2b, + 0x402b042b, 0x25480f0b, 0x6619035b, 0x2f5f252a, 0x7f195f19, 0x19190319, 0x135f1f09, 0x5f000313, 0x3f000409, 0x597133e1, 0x10012a06, 0x2be132f6, + 0xe1f6105d, 0x05734a32, 0x564f3520, 0xa1471807, 0x35520809, 0x03032e21, 0x37023e32, 0x021e1421, 0xcf807902, 0x695a2a5b, 0xf4a04c7d, 0x9d5154a5, + 0xd79996e8, 0xdb033e87, 0xa9734007, 0x6d955b43, 0xedfc0742, 0x058c5526, 0xaa202c29, 0x0a131a0f, 0xe9fec66c, 0xebfeaeab, 0xc46b68c2, 0x46ab1501, + 0x4786c17a, 0x354f66fb, 0x447f2205, 0x20cb8200, 0x22f78266, 0x825e04d7, 0x272d08cb, 0x29404300, 0x05481122, 0x29b02957, 0x01293f01, 0x10194823, + 0x50232856, 0x10af109f, 0x10df10cf, 0x00101004, 0x160a501f, 0x00511419, 0x20c58f10, 0x22c5875d, 0x4a021e32, 0x2e2b0553, 0x21353502, 0x22232626, + 0x8207020e, 0x321322d7, 0x08c28436, 0x6ee7013a, 0x424983b6, 0x6366a778, 0x023b6e9e, 0x979a05b5, 0x4c505733, 0x514c2827, 0x85736057, 0x1b14fe0b, + 0x5e045839, 0x87d28e4a, 0x4e95d688, 0x6eb58147, 0x0ab6c071, 0xa1121c13, 0x09220382, 0x834c25fc, 0x712a0809, 0x1205ecff, 0x26022b07, 0x0000e102, + 0x6a000701, 0x52014600, 0x03b61900, 0x26053302, 0xffb80203, 0x3e2ab4d3, 0x01250e18, 0x6542352b, 0x21ef8408, 0x3382d905, 0x3382e220, 0x6a000624, + 0x318400c4, 0x84113121, 0xb4f42531, 0x050f3c28, 0x0424318c, 0x81060000, 0xd94c6583, 0x20658205, 0x2c6582f4, 0x020d4017, 0x26051b01, 0x12000102, + 0x05db4c26, 0x31826388, 0x83be0521, 0xd0012263, 0x21978500, 0x65830091, 0x11203082, 0xb8253082, 0x12b4ffff, 0x05e14c26, 0x48243388, 0xec03ecff, + 0xb1206584, 0xff213385, 0x22cb84bf, 0x83430102, 0xffb82764, 0x4e3ab4f4, 0x998c0b13, 0x33824420, 0x67845220, 0x3386d120, 0x67865520, 0x67854320, + 0x3382d920, 0x85051c6c, 0x01002267, 0x08678400, 0x00b60564, 0x40720020, 0x1b5b002d, 0x20205b1c, 0x48181040, 0x20201b1d, 0x0d031d1b, 0x67055b16, + 0x01229f22, 0x0d800d70, 0x4f0d3f02, 0x030d5f0d, 0x5f1d200d, 0xffb81b1e, 0x071840f0, 0x191b480d, 0x780100aa, 0x000f0100, 0x00000801, 0x6013031e, + 0x00130a0e, 0x3fe1333f, 0x5d5e2f39, 0x33335d5d, 0x32e1102b, 0x0a822f01, 0xe1f61023, 0x054e5c12, 0x10e11025, 0x4c3031e1, 0x44180b6f, 0x23310897, + 0x35210135, 0xf4011521, 0x4784ba73, 0x89cd8843, 0x44bd186e, 0x7b21080a, 0xa6fda601, 0x3b033d03, 0x97643505, 0x74a06066, 0xaa2d2240, 0x0d182417, + 0x81878794, 0xa6d10197, 0x23d38291, 0x0314fe1b, 0x08054563, 0x3e40643d, 0x201f4a00, 0x4024244a, 0x21481813, 0x1f24241f, 0x180d0321, 0x26570547, + 0x269f266f, 0x01263002, 0x0701260f, 0x110c400d, 0x21240d48, 0x1d1f2250, 0x0c092000, 0x22000048, 0x4d50130f, 0x3924073a, 0x33332b2f, 0x2b20c384, + 0xc59fd083, 0x08965218, 0x3e08c785, 0x7da85fa8, 0xba844749, 0x3ab57373, 0x665b4e1f, 0x56774736, 0x8b633730, 0x92016d54, 0x0603c6fd, 0x4107d501, + 0x6e6ca675, 0x244984b7, 0x1f10a622, 0x572e0f18, 0x7d564e7d, 0x017d2752, 0x18859aed, 0x3d0731bd, 0x2602c106, 0x0000b201, 0x4d010701, 0x5201b000, + 0x01b41500, 0x0126051a, 0xb4feffb8, 0x64181918, 0xae260c9b, 0x3b040000, 0x2f826f05, 0x2f82d220, 0x4d010624, 0x2d830039, 0x83110e21, 0xb4ff252d, + 0x040a0d0c, 0x260ae944, 0x050000c9, 0x872b0710, 0x6a00235d, 0x69429c00, 0x42212006, 0x5f820569, 0x5f852c20, 0x82053542, 0x20618591, 0x226187d9, + 0x42256a00, 0x152005cf, 0x82056742, 0x85202063, 0x24318863, 0x05ecff7d, 0x21658371, 0x9b423200, 0xaa002105, 0x2b053543, 0x05310203, 0x01020326, + 0x000a3c28, 0x250ccd42, 0x04ecff71, 0x6382052d, 0x43520021, 0xf9200599, 0x20059943, 0x05994329, 0x20b4f923, 0x84318e34, 0xcd052a63, 0x7e020602, + 0xffff0000, 0x21418400, 0x0f825e04, 0x0f847f20, 0x1f838388, 0x82070121, 0x298386e9, 0x05330304, 0x01030426, 0x518e3e2a, 0x02208388, 0x01214182, + 0x28318206, 0x40170000, 0x2b03040d, 0x222f8211, 0x8e362200, 0x823b202f, 0x834420b3, 0xc70121e5, 0x6182b382, 0x4197ff21, 0x2e20064b, 0x25054b41, + 0x3925b4a6, 0xe78c0c04, 0xecff3724, 0xe7834203, 0x86e70121, 0x43382033, 0x302006b5, 0x25054d41, 0x3b27b4ca, 0x338c2203, 0x67821920, 0xc106ae26, + 0xbd012602, 0x01233383, 0x4227004d, 0x24210511, 0x05114205, 0x13232222, 0x2a0bcd46, 0x0314fe0a, 0x026f05df, 0x425c0026, 0xbb2d0511, 0x40130000, + 0x1125010b, 0x23010126, 0x47f61824, 0x845b840c, 0x825b84c3, 0x861220f3, 0x852b20c3, 0xb4fd23c3, 0x5d853622, 0x1908dd41, 0x28101713, 0x170000a7, + 0x01020d40, 0x22c2832c, 0x85372301, 0x852f8861, 0x88732063, 0x005322bf, 0x050d4266, 0x2e010222, 0x51206483, 0x06216195, 0x21c18821, 0x61860053, + 0x61832f20, 0x61905a20, 0x0000a623, 0x05a54504, 0x5541c120, 0x54002105, 0x1f206187, 0x0f226183, 0xbb412a16, 0x009a260e, 0x05fe0300, 0x209382d9, + 0x233182e1, 0x066a0006, 0x22206186, 0x08246183, 0x0a172d19, 0x4b098341, 0x4b080543, 0xb605be03, 0x64000900, 0x00140b40, 0x0100e401, 0x020100d0, + 0xc0ffb800, 0x13083540, 0x0b000048, 0x0b4f0b2f, 0x0b8f0b6f, 0x11400b04, 0x5a074818, 0x04cf04bf, 0x01048402, 0x041f040f, 0x04040702, 0x64085a03, + 0x095f020a, 0x075f0303, 0x2006f85c, 0x051a4b3f, 0x5d5e2f34, 0x2be15d5d, 0x2f33115d, 0x5d5d5f2b, 0x01303171, 0x8a4c2115, 0xfdbe2e07, 0xbab0b0c3, + 0xfba6b605, 0x01d9fd96, 0x28838281, 0xfeae0001, 0x040a0383, 0x268d824a, 0x2032404e, 0x82023002, 0x0b2a0800, 0xa1010bc0, 0x0b70010b, 0xbf470901, + 0x0206cf06, 0x0f010684, 0x02061f06, 0x05060607, 0x0a540047, 0x15095005, 0x5004fb08, 0xa6750f01, 0x10012405, 0x8532e1f6, 0x056d5d7a, 0x30315d25, + 0x86211133, 0x02ae2879, 0xa05afe5c, 0x634a04b6, 0xff2d0688, 0x00c700ff, 0x07cf0500, 0x0126022b, 0x066541c5, 0x6541fc20, 0x03042b05, 0x04260527, + 0x321e0003, 0xb9421c06, 0x82ae200c, 0x05502231, 0x203182d9, 0x203186e5, 0x05c941b0, 0x11203182, 0x0a213185, 0x2a318c0d, 0x036dfe2f, 0x02b605be, + 0x839b0226, 0x80032331, 0x3182a600, 0x01b30a2a, 0x01071f1f, 0x35113c10, 0x12208782, 0xfd822382, 0x9c202382, 0x81222384, 0x23878900, 0x23870d20, + 0x6dfe002a, 0xb6059a04, 0x3b002600, 0x80222384, 0x23822303, 0x01b11735, 0xc0ffb81d, 0x481513b2, 0xb49effb8, 0x00001d1d, 0x542b0125, 0x23200595, + 0x11223182, 0x31824a04, 0x31845b20, 0x9a028122, 0x12283182, 0x1d5001b3, 0x9affb801, 0x07212c82, 0x212c8207, 0xbb63355d, 0x82602006, 0x1133085d, + 0x2740b200, 0x0f560f46, 0x59094902, 0x00360209, 0x01063901, 0x000f0906, 0x03030c04, 0x01113001, 0x0701073f, 0x05110711, 0xb80a0b01, 0x0ab3f0ff, + 0x8205040a, 0x14403407, 0x100e0d05, 0x01020e0e, 0x01010010, 0x01800170, 0x820301c0, 0x40c02864, 0x480a0727, 0x50130101, 0x7f3a05c0, 0x00080413, + 0x090f5f06, 0x27010328, 0x0c03010c, 0x0109090a, 0x05030a0d, 0xd8701201, 0x112f2b06, 0x5d5d3939, 0x32e13311, 0x06825e01, 0x2205b161, 0x83382f33, + 0x25038302, 0x39391211, 0x21822f2f, 0x2f3d3926, 0x5d331733, 0x31240082, 0x23010130, 0x21250283, 0x33012135, 0x26028201, 0xc5021521, 0x61d39b01, + 0x9a2605a9, 0x1401dffe, 0xad6192fe, 0x8e400806, 0xb4021c01, 0x7b024cfd, 0xb40285fd, 0xfd5e02a4, 0xfd2f02d1, 0x0100a4a2, 0x00002300, 0x4a04db03, + 0x17011100, 0x0880bf40, 0x08020890, 0x0b000800, 0x0105060f, 0xe50105f7, 0x05360105, 0x07060501, 0x9508f082, 0x1010010d, 0x0103090d, 0xea0103f8, + 0x03390103, 0x6b020301, 0x02067b06, 0x3a010657, 0x02064a06, 0x02740264, 0x01025802, 0x02450235, 0x0d020602, 0x03060d02, 0x010c060f, 0xe5010cf7, + 0x0c36010c, 0x400b0c01, 0x0b481916, 0x48110e40, 0x0b7b0b6b, 0x010b5702, 0x0b4a0b3a, 0x130b0b02, 0x13301310, 0xb0139002, 0x130f0213, 0x010e0901, + 0xea010ef8, 0x0e39010e, 0x0f6b0e01, 0x58020f7b, 0x0f35010f, 0x0f020f45, 0x4f100a0d, 0x01ef0704, 0x1b010b01, 0x5b012b01, 0x9c826b01, 0x02010128, + 0x05150b0f, 0x4c410f02, 0x5d5e2607, 0xe133335d, 0x05bd4832, 0x5d5dc124, 0x0282715d, 0x2fce1022, 0x2b210982, 0x250f842b, 0x3d391712, 0x9461182f, + 0x84102007, 0x33112113, 0x04820183, 0x72410e86, 0x30312305, 0x8e612113, 0x15212205, 0x06704121, 0x01685f08, 0xcfcffe00, 0xfecffafa, 0xfe0401cd, + 0xcf4a01f7, 0xf2fef4fe, 0xfe4a01cf, 0x017b02fb, 0x0166fecf, 0x8931fe9a, 0xb4010efe, 0xf2014cfe, 0x00020000, 0x03000089, 0x00b605f6, 0x0019000e, + 0x06294040, 0x65095a19, 0x011b9f1b, 0x15011b10, 0x1a66005b, 0x063f5f0f, 0x066f064f, 0x06bf069f, 0x008206df, 0x5f190728, 0x03071209, 0x634c3f00, + 0x4be12009, 0x1324079c, 0x33023e34, 0x1125a782, 0x022e2221, 0x05d36a01, 0x33162e08, 0x7f378933, 0xbb9598cf, 0xc28695fe, 0xb2023c7e, 0x5b8a5d81, + 0x9fafa32e, 0x9857ac01, 0x68024271, 0x703d4afa, 0x1b5f019e, 0x8846613c, 0x07674784, 0x14060227, 0x47000602, 0x23a38400, 0x3b06ecff, 0x2108a382, + 0x00320023, 0x183f4063, 0x1a5a3209, 0x5a22111a, 0x0f346501, 0x346f0134, 0x34ef349f, 0x50344003, 0x0e820234, 0x2a063308, 0x3366115b, 0x23175f24, + 0x4f173f23, 0xbf176f17, 0x0517df17, 0x03181717, 0x09602d1d, 0x00130e06, 0xe133333f, 0x2f393f32, 0x102f335d, 0xf61001e1, 0x69185ee1, 0xe12f09e2, + 0x30313239, 0x0e141101, 0x26222302, 0x18030e27, 0x83075647, 0x161428d4, 0x023e3233, 0x87051135, 0x080d83d8, 0x2d3b0653, 0x725e8c5b, 0x3f182b99, + 0xd73f6752, 0xd78a41e4, 0x67bb7a96, 0x33482c61, 0x81bafd1c, 0x2d5b8b5d, 0x5b43867e, 0x50031738, 0x8b5118fe, 0x4d613a66, 0x192e3f26, 0xa367d6d2, + 0x68023c72, 0x6970b2fb, 0x3250391e, 0x1ea6e801, 0x804d6b43, 0x4d3e2582, 0x20f38329, 0x22f38271, 0x8214065a, 0x433d08f1, 0x39405c00, 0x47382c10, + 0x2e012e50, 0x47031b2e, 0x6f455506, 0x9f457f45, 0xef45cf45, 0x45400545, 0x2f450f01, 0x41060245, 0x44561b48, 0x3e330404, 0x10202550, 0x3300002c, + 0x160b1050, 0x22ed8616, 0x18e1333f, 0x21082e4e, 0xf3825d5d, 0xff821120, 0x3932e12a, 0x32253031, 0x33113536, 0x2e23f185, 0x52232702, 0x3a6b0616, + 0x33172506, 0x26262726, 0x1e222083, 0xef822103, 0x35373708, 0x23022e34, 0x14150622, 0x6fd30416, 0x5c2fb662, 0x67415b8b, 0x06173d51, 0x795b441b, + 0x6e9a5d51, 0x9a6e3c3c, 0x4d603b5d, 0x030c173b, 0xb6040203, 0x512c0f01, 0x7e7ea6fd, 0x7f873e08, 0x8282837f, 0xc1fe3501, 0x2e629869, 0x2c4a361e, + 0x20374a29, 0x8cd48f48, 0x4990d58d, 0x05937e1a, 0x11366d08, 0x92fbb401, 0x2d4e6a3e, 0x5f8c5e2e, 0x6b9d6529, 0xd1ccda37, 0x010000cd, 0xecff4e00, + 0xcb054406, 0x85003f00, 0x5b0d5640, 0x2b5b0020, 0x20072025, 0x07202b2b, 0x5a331603, 0x7f416536, 0x9f418f41, 0xff41ef41, 0x41000541, 0x41304120, + 0x80167003, 0x163f0216, 0x1602164f, 0x06254016, 0x34000760, 0xdf343401, 0x07aa0107, 0x01077801, 0x2805006b, 0x3b5f301b, 0x60121513, 0x09404f1b, + 0x825d5e21, 0x2f332700, 0x39e1105d, 0x07820111, 0x2705714c, 0x2f391711, 0x39122f2f, 0x2706724c, 0x23022e34, 0x32333523, 0x2106a54b, 0xaf180622, + 0x07230bc9, 0x7f031e15, 0x644106a9, 0x033a080a, 0x92653529, 0x5cb0bf5d, 0x2532618e, 0x6e3a5f44, 0x265c4ba9, 0x47837462, 0x3971a66d, 0x4b7d5b33, + 0x325e8a57, 0x374f3218, 0x38b7626f, 0x57599166, 0x013c6c94, 0x466d4d87, 0x5d189721, 0x74080ad5, 0x1829361f, 0x4f856136, 0x3958774a, 0x390b060c, + 0x4a487759, 0x771e4168, 0xfec90181, 0x6298692d, 0x9c642f2e, 0x00010000, 0x05ecff50, 0x005e04a2, 0x4081003b, 0x00471523, 0x36314620, 0x31001931, + 0x00311919, 0x47082703, 0x0f3d550b, 0x3dd0013d, 0x013dbf01, 0x27013d30, 0x40c0ffb8, 0x48151229, 0x2701275f, 0x19363c27, 0x09091a50, 0x99011adf, + 0x021aa91a, 0x06907d0b, 0x2326052e, 0x05102c50, 0x00161050, 0xe13fe13f, 0x23056673, 0x2f335d5d, 0x20072a41, 0x0752432b, 0x2f391725, 0x41112f2f, + 0x1423082d, 0x4233021e, 0x35220c70, 0x3e412634, 0x23262108, 0x31113d41, 0x31155203, 0x60693b50, 0x8f5f2fb6, 0x64905c60, 0x5d188535, 0x28360c3b, + 0x355a524d, 0x3a699056, 0x2b46331c, 0x223c5332, 0x49274c01, 0x61422138, 0x542b2309, 0x5d184f7b, 0x13240b10, 0x2609131d, 0x088bbb18, 0x3e290939, + 0x01000052, 0x7ffe4e00, 0xcb059c04, 0x83003100, 0x5b0f5440, 0x82220927, 0x184a0801, 0x2e705a01, 0x2e022e80, 0x2f5a002e, 0x3300332f, 0xd033c001, + 0x339f0233, 0x20330001, 0x03333033, 0x18801870, 0x4f183f02, 0x18180218, 0x27fb3032, 0x09df6008, 0x0109aa01, 0x0f010978, 0x09080109, 0x14170109, + 0x2e041d60, 0x4f5a015f, 0x07264105, 0x39e15d23, 0x0750423f, 0x11715d36, 0x32e12f33, 0x12e15d2f, 0x2f2f3939, 0x31e13912, 0x11232130, 0x29215542, + 0x23113315, 0x38bbec03, 0x49429567, 0xb0b0271f, 0x6443a001, 0x3c422041, 0xfdfa381e, 0x000100d9, 0x0383fe50, 0x005e04f2, 0x408d002d, 0x1d460c1a, + 0x82061d22, 0x13230801, 0x29294700, 0x2a20472d, 0x2a402a30, 0x2a042a60, 0x40c0ffb8, 0x48130f0e, 0xc02f2a2a, 0xe02fd02f, 0x8313032f, 0x2d2a0812, + 0x5f481512, 0x13130113, 0x22fb2b2e, 0x06df5005, 0xa9069901, 0x064f0206, 0x0b02065f, 0x02061b06, 0x00060607, 0x18500f12, 0x925a2910, 0x08144107, + 0x1441e920, 0x05a44a06, 0x32e15d23, 0x0712412f, 0x31e11025, 0x42112130, 0x15281e28, 0x23113315, 0x819c0211, 0x29191f42, 0x263f522c, 0x2b01b7a0, + 0x5f18655e, 0x0f420920, 0x2c0e250d, 0x913d5b42, 0x0807c75a, 0xe9ff0077, 0xb605ec06, 0x92003100, 0x06d76540, 0x060206e7, 0xd7010107, 0x0201f701, + 0x171c5a01, 0x48181010, 0x1701178b, 0x480e0710, 0x5a311c17, 0x011eb01e, 0xb4011ce0, 0xd41cc41c, 0x1c00031c, 0x1c901c50, 0x07041ca0, 0x1e1c1e1c, + 0x275a240e, 0x334f3365, 0x337f336f, 0x33af339f, 0x200633df, 0x330f0133, 0x25250e01, 0x1c5f0112, 0x60122103, 0x00130b2c, 0x32e1333f, 0x20f7823f, + 0x07df502f, 0x39391122, 0x2f060862, 0x3311e110, 0x102b5d2b, 0x32715de1, 0x0130315d, 0x20187b5c, 0x47821814, 0x020e2708, 0x022e2223, 0x885c0335, + 0x6e63211e, 0x22076844, 0x5c3a6892, 0xfb231a91, 0x447781d1, 0x4d08095e, 0x6c99602c, 0x00010000, 0x06ecff10, 0x004a0400, 0x405c0028, 0x11460139, + 0xa0134728, 0x11db0113, 0x0111c401, 0x11a01190, 0x01112402, 0x11011110, 0x09131113, 0x551e471b, 0xcf2a7f2a, 0x032aef2a, 0x0c1c1c09, 0x0f115001, + 0x234f0c18, 0xf98c1606, 0xe1f61022, 0xac6af784, 0x06684505, 0xa05c2120, 0x114d4411, 0x4414ae5c, 0x91220b41, 0xb95c3666, 0x3dfd2510, 0x20416241, + 0x23093344, 0x6996622e, 0xc728d983, 0x2d07ecff, 0x1d00b605, 0x3724d982, 0xa05a131b, 0x3108ed82, 0x5a061700, 0xc01f6509, 0x1faf011f, 0x20021fbf, + 0x1f0f011f, 0x5a161a01, 0x151e6417, 0x07071a5f, 0x08011a0f, 0x1c171a1a, 0x12170318, 0x130e5f03, 0xd25c3f00, 0x076e4808, 0xd6833220, 0x22088247, + 0x41013031, 0x1c5c10b0, 0xd5043709, 0x636e6f62, 0x906638b6, 0x68915859, 0xba66fd3a, 0xba9a02ba, 0x88418701, 0x2d01210f, 0x080bab78, 0x06ecff37, + 0x004a048b, 0x406c001f, 0x471a0247, 0x0d1e0505, 0x21551047, 0x21202100, 0x50214002, 0x90218021, 0xf021b021, 0x210f0621, 0x471d0101, 0x1c20541e, + 0x0e0e0150, 0xc1bd18eb, 0x031e2910, 0x151e0f1f, 0x1615500a, 0xe745c78a, 0x5d012005, 0x7120059f, 0xe121c885, 0x5dc78232, 0xe145058f, 0x21353b10, + 0x01112311, 0xb6210264, 0x3b503115, 0x2fb65f6a, 0x5b608f5f, 0xfd366692, 0xd35cb6df, 0x13804105, 0x17fe6e22, 0x3808c282, 0x7d000100, 0x5205ecff, + 0x2a00cb05, 0x29404700, 0x290c2a2a, 0x4014015b, 0x14480e09, 0x2c670114, 0x70012cbf, 0x5b1f012c, 0x2a2b660c, 0x2400005f, 0x11155f1a, 0x075f2404, + 0x25af8313, 0x3912e133, 0xa883e12f, 0x105d5d27, 0x2b2f32e6, 0x82108310, 0x152121a8, 0x0ca15e18, 0x32332427, 0x2e071716, 0x05d74903, 0x021e5408, + 0x023e3233, 0x17032135, 0x8e423b02, 0xf29d9cde, 0xb65f56a6, 0x6fab0b01, 0x244858cc, 0x2e5d5853, 0x427fbc7a, 0x75ab7036, 0x295d956c, 0xf60288fe, + 0xfefea856, 0xc3695baf, 0xacae1701, 0x69c31601, 0x11a22a2c, 0x510e171e, 0x8289da98, 0x42569cd8, 0x8264a677, 0xff7131c7, 0x047b04ec, 0x0028005e, + 0x285a4081, 0x47270c28, 0x0c21c782, 0x08c78311, 0x142a574b, 0x022a242a, 0x2af42ae4, 0x012ad002, 0x502a4002, 0xa02a802a, 0x052ac02a, 0x560c481d, + 0x00502829, 0x48191540, 0x00db00cb, 0xa90300eb, 0x0200b900, 0x009f008f, 0x1b000b02, 0x03002b00, 0x22000006, 0x11155018, 0x07502210, 0x21f88816, + 0x00825d5e, 0xfe852b20, 0x5d5d5f23, 0x0f014171, 0x21061c44, 0xef823e34, 0x4957fe82, 0x05ac4805, 0xfe823e20, 0x7b024508, 0x78390002, 0xcb8781ba, + 0x954c4488, 0xad6f8fdb, 0x943c3e4d, 0x6595615b, 0x87562934, 0x4a74515e, 0x02b8fe23, 0xc882444a, 0x934f4789, 0xd38284d3, 0x27255094, 0x3a291d8d, + 0x5d629d6d, 0x2d3e709b, 0x00447050, 0x1420f782, 0x3508f782, 0x00b605c9, 0x40650019, 0x095a062f, 0x1b4f1b65, 0x1b9f1b7f, 0x00041baf, 0x18af011b, + 0x840218ef, 0x18180118, 0x40135a00, 0x150f0115, 0x15150801, 0x13671357, 0x53461377, 0x07102c05, 0x1913480a, 0x07165f15, 0x43031607, 0x39210752, + 0x053f552f, 0x490a9074, 0x4e43059d, 0x21352a15, 0x71022115, 0x626e6f62, 0x054a43b7, 0xfe3a6927, 0xfefe035e, 0x1149435f, 0x6d950321, 0xb58205df, + 0x046f3c08, 0x001b004a, 0x0d4a406d, 0x1d551047, 0xcf011d0f, 0xff1def1d, 0x1d30031d, 0x1d601d40, 0x1f1d0f03, 0x030f021d, 0x0103cc01, 0x03bf030f, + 0x03030602, 0x601a4705, 0xd0007000, 0x821f0300, 0x00003df9, 0x021a101a, 0x010e0e1a, 0x1615500a, 0x01500004, 0xe13f000f, 0x11e13f32, 0x2f012f39, + 0x4a75ba82, 0x5d5e2305, 0x2e49715d, 0x30312206, 0x20aa8313, 0x11d84411, 0x0329113a, 0x15c1fe35, 0x693b5031, 0x5f2fb75f, 0x925c608f, 0xb0033666, + 0xd7fd9a9a, 0x2111bc44, 0x7d823502, 0xc1826f20, 0x050c4308, 0x003900cb, 0x5b13b45d, 0xb8001a34, 0x2e40c0ff, 0x00481a17, 0x2f1a001a, 0x3b270a0a, + 0x20013b9f, 0x3a662f5b, 0xaa601b34, 0x18780118, 0x01180f01, 0x05181808, 0x2a266023, 0x0b600e13, 0x3f000405, 0x0282e133, 0xa482af82, 0x39e15d34, + 0xe1f61001, 0x32ce105d, 0x3939122f, 0x122b2f2f, 0xb182e139, 0x023e3426, 0x021e3233, 0x210c7f77, 0x244d1533, 0x79362008, 0x2e22050e, 0x28823502, + 0x35376308, 0x3b9c032e, 0x486da973, 0x265a697b, 0x67a24b5c, 0x26445f39, 0x5782572c, 0x925dbfc3, 0xa4aa3565, 0x5353cc6c, 0xc38080c0, 0x5f314283, + 0x784a5789, 0x60042d54, 0x3661854f, 0x1f362918, 0x1e43367d, 0x3e36533a, 0x97274864, 0x43654321, 0x2b318e89, 0x3c2526aa, 0x48609c6f, 0x0b3d5e7b, + 0x58390c06, 0xfb820077, 0xecff5c30, 0x5e046a03, 0x6d003700, 0x1e4632b4, 0xfb832301, 0xfb823d20, 0x01233908, 0x2b180123, 0x39d0390f, 0x39f039e0, + 0x01398f03, 0x05013940, 0x38561847, 0xef50021d, 0x37a90137, 0x0f0237b9, 0x2f371f37, 0x37060337, 0x502f0a37, 0x0a10282c, 0x16130f50, 0x20060a41, + 0x05845812, 0x25060a41, 0xce105d5d, 0x0b411132, 0x15012409, 0x43062223, 0xf78f0743, 0x3321ff83, 0x066a4332, 0x83082585, 0x8a819e02, 0x60462985, + 0x57613337, 0xaf3c1e4d, 0x6ba26e73, 0x59432835, 0x35492b30, 0x90693a1e, 0x50a25a56, 0x47834b3f, 0x44266d66, 0x8702395f, 0x335e5b99, 0x0e122a45, + 0xa2101e16, 0x5630281d, 0x5b3d4778, 0x0b0d2940, 0x4d3b290e, 0x4a6d4632, 0x93272526, 0x4d4d2622, 0x1227402d, 0x00ffff00, 0x056dfe00, 0x02b6052f, + 0x00b50126, 0x03070100, 0x00b80380, 0xb40d0000, 0x31310101, 0x3c100100, 0x35003511, 0x10262783, 0x4c046dfe, 0x27824a04, 0x2784d520, 0x82028121, + 0x21278407, 0x278b2626, 0x98fe0026, 0xbc05dd04, 0x2208cf5d, 0x82d30467, 0x40132a4f, 0x1418020b, 0x15000227, 0x0dcf5d1b, 0x1898fe21, 0x220cc384, + 0x866f0467, 0x1736262d, 0x330d0227, 0x12d15d39, 0x5b88e120, 0xd1046622, 0x26054f5d, 0x26051b02, 0x5e2a2102, 0x9c22112b, 0x2d828f06, 0xb1834420, + 0x04660223, 0x255b8675, 0x02261139, 0x2d5e4836, 0x87d12013, 0x7703235b, 0x5b82cb04, 0x03b6192d, 0x26051502, 0xffb80203, 0x861db4ff, 0x0853565f, + 0xecff5e26, 0x7f064704, 0x33826187, 0x59548920, 0x02032305, 0x34821133, 0x863b3321, 0x82318863, 0xdd04221e, 0x20658907, 0x20658878, 0x2165871d, + 0x955e1d25, 0xff12240e, 0x8a9c03ec, 0x04782165, 0x3b206588, 0x43216584, 0x0525413b, 0x0821658d, 0x20cb884a, 0x22cba679, 0x88f80606, 0x897920cb, + 0x21cb9b65, 0x65886208, 0xcba27a20, 0xcb835e20, 0x88100721, 0x8e7a2065, 0x410b20cb, 0xfe251131, 0x07dd0498, 0x2a658573, 0x4b012700, 0x52011f00, + 0x42020701, 0x25310557, 0x2d031040, 0x15022714, 0x00032605, 0x0704302a, 0x0ca94125, 0x00352b24, 0x5955352b, 0xfe5e2605, 0x069c0398, 0x25798521, + 0x4b012600, 0x458400d4, 0x00006f2b, 0x16402200, 0x27174b03, 0x27e88302, 0x0c4e480d, 0x25022522, 0x42868887, 0x82ffff21, 0x04002427, 0x881308dd, + 0x847b20ef, 0x401725ef, 0x2602030d, 0x02237e82, 0x41212900, 0xed840eb9, 0x88c10621, 0x047b22ed, 0x071f427b, 0x26114427, 0x471e0203, 0x14b9413f, + 0x7c206389, 0x7c2063b0, 0x582063a6, 0x7d20c788, 0x1a206389, 0xe742c784, 0x9c032313, 0xc7880607, 0x63897d20, 0xc7843820, 0x2311b541, 0xdd040000, + 0x200a1b42, 0x4263a67e, 0x7e200919, 0x5021638f, 0x0f2b415e, 0x0498fe25, 0x425b07dd, 0x4e240819, 0x6d012100, 0x27081942, 0x03164022, 0x0227142e, + 0x0026d283, 0x0704312b, 0x4c620225, 0x09d34108, 0x98fe5e26, 0xee059c03, 0x20081542, 0x0e15424e, 0x27174c23, 0x22e28302, 0x824f490d, 0x1e02217d, + 0x89076262, 0x82c72041, 0x05be2241, 0x214182b6, 0x51420028, 0x44aa2005, 0x01270565, 0x0127140f, 0x61120c03, 0x2d820de3, 0x5e04e122, 0x48202d82, + 0xbe202d86, 0x02212d85, 0x2469822b, 0x052e2830, 0x0a275d0f, 0x0000c726, 0xe107be03, 0x66225b88, 0xef449104, 0x12012605, 0x0d012605, 0x133f6221, + 0x5b888f20, 0x98046622, 0x2e265b86, 0x2d022611, 0x5b92283d, 0x5b873520, 0xff520123, 0x235b82d4, 0x1401b415, 0xb8255a82, 0x15b4fbff, 0x25b98d23, + 0xe103ecff, 0x5d86e305, 0x5201062a, 0x130000de, 0x30020b40, 0x1e225b82, 0x5b8f3f31, 0x075c0423, 0x235b87d1, 0x9e047703, 0x19245b82, 0x0c0102b6, + 0x2007cf5b, 0x44bb8614, 0x712008b3, 0x24084b45, 0x01000048, 0x0b4b4507, 0x26112825, 0x19030203, 0x8807bb35, 0x00272431, 0x8abe0300, 0x88782065, + 0x27c28265, 0xffb80102, 0x141cb4fd, 0x3388c385, 0xc5831220, 0x867f0621, 0x030721c5, 0x820a4b45, 0x216582c8, 0xc9853038, 0xc7263188, 0x1b040000, + 0xcb884a08, 0xcba67920, 0x85054b45, 0x0a4b45cb, 0x6582cb96, 0x08be0323, 0x20658862, 0x20cba27a, 0x21cb8371, 0xcb881007, 0x970a4b45, 0x98fe25cb, + 0x7307be03, 0x00256585, 0xff4b0127, 0x064b45f1, 0x0000aa3a, 0x10402500, 0x27142402, 0x26050c01, 0x27210302, 0x01250001, 0xb4fdffb8, 0x4507a941, + 0x71200a4b, 0xe1224782, 0x79852106, 0x01260024, 0xf942de4b, 0x40222709, 0x17400316, 0xe8830227, 0x433d1c25, 0x41250f05, 0x354309ba, 0x00522609, + 0x07640200, 0x214182e1, 0x3b83002c, 0xb0036622, 0x200ad942, 0x0ed94213, 0x23826220, 0x8f06d722, 0xf3202d82, 0x5e202d86, 0x132aaf82, 0x0a010b40, + 0x13012611, 0xa9420419, 0xfe52260c, 0x05640298, 0x225b88b6, 0x82be0367, 0xb415232d, 0xdc820f01, 0xffffb823, 0x0e9343b4, 0x98fe9e26, 0xe5057501, + 0x4c202f82, 0x67225d84, 0x2f846d03, 0x82150221, 0xffb827c6, 0x1812b4fe, 0x95430c04, 0xfe7d260a, 0x05710598, 0x202f82cd, 0x212f8532, 0x8d855c05, + 0x142b0228, 0x28000227, 0x075f0a2e, 0xfe71260b, 0x042d0498, 0x822d825e, 0x070125f3, 0xb2046702, 0x23205d85, 0xff235d84, 0x8c2620b4, 0x0531602f, + 0x5d88e120, 0x4e056622, 0x27051941, 0x26052e02, 0x283d1502, 0x71262d8c, 0x2d04ecff, 0x5d888f06, 0xa4046622, 0x26268b86, 0x13022611, 0x2d8c2035, + 0xd1205b85, 0x03235b87, 0x5d580577, 0x0328053b, 0x26052802, 0x30050203, 0x95435d86, 0x0668220c, 0x235f877f, 0xaa047703, 0x19255f82, 0x200203b6, + 0x24308211, 0xb4faffb8, 0x61638628, 0x65890e77, 0x65897820, 0x65843020, 0x5f303821, 0x33200e07, 0x6589c584, 0x65887820, 0x65872820, 0xcb849990, + 0x884a0821, 0xa47920cb, 0x062d22cb, 0x20cb88f8, 0x21cba779, 0x65886208, 0xcba07a20, 0xcb837120, 0x88100721, 0xa37a2065, 0x98fe25cb, 0x73077105, + 0x00256585, 0x004b0127, 0x059743ae, 0x005c0522, 0x2d059d48, 0x02271440, 0x03260528, 0x0a433d00, 0xa8412500, 0x09514309, 0x98fe7126, 0x21062d04, + 0x00247785, 0xfb4b0126, 0x20059343, 0x314182b2, 0x03094028, 0x02271738, 0x03261120, 0xb5ffffb8, 0x44833b35, 0x890bbc41, 0xff7d2447, 0x832506ec, + 0x5f02228b, 0x23418200, 0x06017600, 0x28067f42, 0x02260541, 0x133b3502, 0x0db36801, 0x83f40421, 0x60022175, 0x06342d82, 0x00507600, 0x02b41500, + 0x0226113a, 0xb4ebffb8, 0x190a332d, 0x5b8f2d8a, 0x54004322, 0x2f825b82, 0x5a823520, 0x51ffb825, 0x9c353bb4, 0xd843215d, 0x2e205d84, 0xd7235d84, + 0x422d34b4, 0xb9820fdd, 0x2602e122, 0x0220b985, 0x23053943, 0x3c02b415, 0xbc225d84, 0x5d934ab4, 0x2f828f20, 0x0721bb83, 0x053b4302, 0x34202f82, + 0xb0235f84, 0x922d42b4, 0x873520bd, 0x20b9825f, 0x20bd857d, 0x235f843d, 0x4c3eb496, 0x0521bd91, 0x235f86e3, 0xe2520106, 0x2d20bd84, 0xfd235d84, + 0x8d4436b4, 0x98fe25bd, 0x14062506, 0x6723bd88, 0x84005c05, 0x1438272f, 0xffb80227, 0x7941b4a7, 0x98fe250f, 0xf204f404, 0x5744bd88, 0x17302108, + 0x9b202f83, 0x200f7b41, 0x2e2f82b8, 0x02b805dd, 0x00380026, 0x02070100, 0x442f0567, 0x01280529, 0x0127141b, 0x0b1e1800, 0x200bb544, 0x222d82a4, + 0x824a0408, 0x8558202d, 0xb804212d, 0x012b8d84, 0x0127171e, 0xb4feffb8, 0x410c211b, 0xb8260bd9, 0xdd04ecff, 0x5d88e107, 0x1d056622, 0x27053542, + 0x26051e01, 0x182d1101, 0x2d825d8d, 0x8f060822, 0x66225d88, 0x8b86a604, 0x26112126, 0x1b300e01, 0x06235b8f, 0x8273074e, 0x426120e9, 0x00210591, + 0x235b82c5, 0x3101b415, 0xb8275a82, 0x25b490ff, 0x4208182b, 0xa4260a65, 0x7905ecff, 0x2f822106, 0x2f826220, 0x76000628, 0x11000060, 0xb68201b1, + 0x28b49f25, 0x84210c2e, 0x0035272a, 0xb800ffff, 0x598cecff, 0x3d004322, 0x25205985, 0x08235984, 0x9c252bb4, 0xa3432159, 0xfe245986, 0x282eb4e2, + 0xe1205991, 0x0220b387, 0x85050f41, 0xb4592285, 0x8456873a, 0x20af8585, 0x21af868f, 0x0d410207, 0x222b8505, 0x923db456, 0x87352057, 0x491e1957, + 0x842d2009, 0xb44723b1, 0xb1913c2e, 0x86e30521, 0x0106235b, 0xb186f352, 0xb44eff24, 0xb18c3f31, 0x0698fe25, 0x8814064e, 0x051f42b1, 0x01b41529, + 0x01271428, 0x4148ffb8, 0xfe251065, 0x04790598, 0x20b588f2, 0x07214267, 0x83172b21, 0x4145202f, 0x7f4d096a, 0xfe002a05, 0x05370498, 0x002602b6, + 0x0651423c, 0x51427f20, 0x840c2005, 0xb4ff255f, 0x02070f09, 0x260ac541, 0x0314fe0a, 0x654a04df, 0x0724067d, 0x8b056702, 0x11292f82, 0xb80101b1, + 0x23b43201, 0x05de6529, 0x82059b50, 0x37042318, 0x5b88e107, 0x71046622, 0x26067d42, 0x0126050f, 0x91091e14, 0x8f062159, 0x66225988, 0x7d424a04, + 0x11292106, 0x38212d82, 0x0c9b6623, 0x35205b85, 0x01235b87, 0x86b3ff52, 0x8211205b, 0x1201225b, 0x215b9120, 0x3366e305, 0x8c522808, 0x40130000, + 0x822b010b, 0x2c012259, 0x26598c3a, 0x04bcfe71, 0x8214069e, 0x00d3282b, 0x00070100, 0x82b40042, 0x0e56086c, 0xff0200b9, 0x393ab4d2, 0x0125230b, + 0x0200352b, 0xd904dbfb, 0x2106bafe, 0x1b000d00, 0x19402d00, 0x070e0e14, 0x01005040, 0x004f003f, 0x07150002, 0x0f0f8092, 0x02015f01, 0x5d2f0001, + 0x32ed1a33, 0x5d5d2f01, 0x2f39cd1a, 0x013031cd, 0x27032e23, 0x031e3335, 0x09880517, 0x64bafe32, 0x3f4d5123, 0x2a10c610, 0xfe15302f, 0x52236496, + 0xc7200d82, 0x042d0d84, 0x58531cd9, 0x23151b51, 0x1d4c5150, 0x080b8a1b, 0xfc020042, 0xffd9046a, 0x007f06be, 0x001c0010, 0x0d314052, 0x1710040c, + 0x2f401701, 0x4f1c3f1c, 0x041c031c, 0x002f1c04, 0x008f005f, 0x0004009f, 0x1b1608c0, 0x0c7f041b, 0x0c020c8f, 0x080f0080, 0x0802085f, 0xcc229d84, + 0x9882325d, 0x1a2f012a, 0x39395dcc, 0x2f182f3d, 0x5d23a982, 0x83333311, 0x262634aa, 0x07060627, 0x36363523, 0x16163337, 0x033e2717, 0x83153337, + 0xfe3c0811, 0x6c3364d9, 0x336a3634, 0x30753365, 0x337430c0, 0x1d21144e, 0x2db4101d, 0x0465376a, 0x305422d9, 0x1b225430, 0x4545843b, 0x19c23b84, + 0x21342e2d, 0x2b673c15, 0x89fb0200, 0xddfed904, 0x4a2fb186, 0x03042a40, 0x01161f0c, 0x0c1c4016, 0x822f1c0c, 0x088f3392, 0x0804089f, 0x121600c0, + 0x037f0c12, 0x0302038f, 0xaa8a1080, 0xaa8fcd20, 0x86cd1a21, 0x21a086a9, 0xb1862315, 0x08833720, 0x1e333528, 0x6ffc1703, 0xa1847433, 0x6a336434, + 0x336b3536, 0x38644d64, 0x10b42d6a, 0x14201e1d, 0xa285f404, 0xb0851b20, 0x672bc329, 0x3421153c, 0x41192d2e, 0x2008065b, 0x00f8067d, 0x00280010, + 0x1638405e, 0x06201919, 0x1c19480e, 0x232f8011, 0x234f233f, 0x04042303, 0x0c5e4123, 0x1f191925, 0x41181826, 0xcc241862, 0x33113932, 0x230d6641, + 0x112b3932, 0x36136741, 0x020e1413, 0x27230707, 0x34353636, 0x06222326, 0x36363507, 0x41163233, 0xa4331074, 0x192e2214, 0x370a5606, 0x162b3941, + 0x260b0b27, 0x4164631f, 0x01330e7d, 0x1e2b1d76, 0x83510615, 0x25251f09, 0x52030319, 0x82450303, 0x232682dd, 0x1007e9fe, 0x2c2bdd82, 0x3b406100, + 0x0c0c0304, 0x41282800, 0x003a0982, 0x001a1ac0, 0xcf8e1627, 0xef1fdf1f, 0x401f031f, 0x1f480d09, 0x198e241f, 0x98411111, 0x2f322816, 0x2f33e133, + 0x82e15d2b, 0x2f332ce3, 0x5dcc101a, 0x39112f32, 0x83332f3d, 0x0f9e41e0, 0x2e220123, 0x2dd78302, 0x33033e23, 0x33021e32, 0x33373632, 0xaa41030e, + 0xbe013410, 0x40454724, 0x0e2a281c, 0x301d055d, 0x4a252a41, 0x821a3e45, 0x055c240d, 0x4141301c, 0x012a0ebc, 0x1c221c5a, 0x5130322a, 0x0882213b, + 0x83312b21, 0x82002008, 0x04733be9, 0x06cdfed9, 0x000b00c1, 0x4032001f, 0x0b800619, 0x0c2f1f0b, 0x15c00c01, 0x0a820514, 0x1a801436, 0x115f110f, + 0x2f001102, 0xcd1a335d, 0xcc2f3232, 0x1a332f01, 0x3926bd82, 0x31cd1a2f, 0xf2420130, 0x0e252808, 0x26222303, 0x821e3327, 0x023e27b2, 0x145efd37, + 0xf1421e20, 0x01260806, 0x4d2b056f, 0x9192466e, 0x1b046c06, 0x242c4430, 0x05213341, 0x2c19f805, 0x1521352e, 0x062c673c, 0x2645633c, 0x19197e8c, + 0x02210845, 0x29958bfc, 0x051e4038, 0x13400b80, 0x9a8a4816, 0x1f000022, 0xcd209a91, 0x2b209a88, 0xe4429b84, 0x8e172008, 0x42d1209b, 0xfc2009e3, + 0xdd2a9a93, 0x153c672c, 0x2c2e3521, 0x9a8e1519, 0x2c073141, 0x13000607, 0x42002a00, 0x1c192140, 0x288a821c, 0x2f132525, 0x09000100, 0x2e0e8208, + 0x1bc02822, 0x8008131b, 0x5f050f0e, 0x41050205, 0x39220639, 0xe2421a2f, 0x41332006, 0x0d84053d, 0x01303122, 0x27209b8d, 0x2411db42, 0xfe163233, + 0x20a692cd, 0x06de422b, 0x3941382c, 0x0b27152c, 0x63643a15, 0xaf8de305, 0x2b1d9632, 0x2906141f, 0x2520095a, 0x03031825, 0x00450652, 0x2d0add42, + 0x002f0013, 0x1c274048, 0x2a081d1d, 0xc0842b2b, 0x0809c030, 0x22cf192a, 0x22ef22df, 0x1c272203, 0xc7901414, 0x332f3227, 0x325dcd33, 0x066b4132, + 0x11230e82, 0x91332f33, 0x14c242c7, 0x2f20c794, 0x8f1ac542, 0x425020d0, 0x013b13c5, 0x42fe3100, 0x00007101, 0x18001400, 0x800f0940, 0x02080800, + 0x00020b12, 0x82332f2f, 0x332f2ea6, 0x3031cc1a, 0x33273417, 0x1415031e, 0x947b1806, 0x363a0808, 0x1a818bdb, 0x651e2f39, 0x1a401d64, 0x22192d0e, + 0x8569ee34, 0x4b403413, 0x08685a2a, 0x05047108, 0x0001002b, 0x016dfe10, 0x00a60077, 0xb6120011, 0x0d100109, 0x0000fa06, 0x56833f2f, 0x0879c420, + 0x06fe7a07, 0x35362208, 0x01770111, 0x3f59391a, 0x0e163f26, 0x322e223b, 0x42d9fea6, 0x11244666, 0x0e079609, 0x3c013131, 0x204f8800, 0x224fb49a, + 0x8be5fe9a, 0x3034084f, 0x00020000, 0x0414fe71, 0x005e0402, 0x003e0010, 0x2d21403b, 0x47063e2c, 0x1040552f, 0x480e0140, 0x3f562136, 0x1b325039, + 0x0b2c0f2e, 0x16102650, 0x161c5000, 0x2f058174, 0xe13f3f33, 0xc4f61001, 0xf6105de1, 0x323232e1, 0x0667ca82, 0x3405250d, 0x37363736, 0x22103667, + 0x41113337, 0x3e240a40, 0x35023502, 0x220b0367, 0x8201a001, 0x17042500, 0x3c604d3a, 0x32093467, 0x08173c4c, 0xe8eb931b, 0x4545b077, 0x69466cbf, + 0x67832347, 0x772a0c00, 0x1a172d0c, 0x2e3c231d, 0x3067481a, 0x2d1b3506, 0xfb94223e, 0x24eaeea2, 0x2e28a622, 0x4470502d, 0x1400ffff, 0x1237e982, + 0x2602b605, 0x00003700, 0x7a000701, 0x00002201, 0x01b60b00, 0x511c1b03, 0x2582064c, 0x14fe2126, 0x46058f02, 0x57202582, 0x00212585, 0x05a148be, + 0xf6ff012b, 0x101e25b4, 0x2b012506, 0x24118235, 0x004a011b, 0x83078201, 0x82342002, 0x240b8504, 0x000a0001, 0x24178634, 0x00070002, 0x240b863e, + 0x00150003, 0x200b8645, 0x24238a04, 0x000c0005, 0x2417865a, 0x00090006, 0x240b8666, 0x004e0007, 0x240b866f, 0x00140008, 0x240b86bd, 0x0067000a, + 0x240b86d1, 0x012e000d, 0x230b8638, 0x012a000e, 0x12203b87, 0x03245f84, 0x09040100, 0x68239782, 0x85009001, 0x0001240b, 0x86f80114, 0x0002240b, + 0x860c020e, 0x0003240b, 0x861a022a, 0x8a04200b, 0x00052423, 0x8644022c, 0x00062417, 0x86700212, 0x0007240b, 0x8682029c, 0x0008240b, 0x861e0328, + 0x000a240b, 0x864603ce, 0x000b240b, 0x86140438, 0x000c240b, 0x864c045c, 0x820d200b, 0x86a8200b, 0x0e54080b, 0x04055400, 0x69676944, 0x657a6974, + 0x61642064, 0x63206174, 0x7279706f, 0x74686769, 0x3220a920, 0x2c373030, 0x6f6f4720, 0x20656c67, 0x70726f43, 0x7461726f, 0x2e6e6f69, 0x696f7244, + 0x61532064, 0x6552736e, 0x616c7567, 0x63734172, 0x65646e65, 0x202d2072, 0x56231b89, 0x82737265, 0x3120242d, 0x8430302e, 0x84308315, 0x69203108, + 0x20612073, 0x64617274, 0x72616d65, 0x666f206b, 0x61326587, 0x6d20646e, 0x62207961, 0x65722065, 0x74736967, 0x99827265, 0x206e6927, 0x74726563, + 0x27078261, 0x6972756a, 0x63696473, 0x73218783, 0x8a77882e, 0x8580899d, 0x75682466, 0x826e616d, 0x73202149, 0x2035af82, 0x69726573, 0x79742066, + 0x61666570, 0x64206563, 0x67697365, 0x2462826e, 0x20726f66, 0x221c8275, 0x826e6920, 0x211b8373, 0x8c832073, 0x656c652f, 0x6f727463, 0x2063696e, + 0x6d6d6f63, 0x41088275, 0x4c210503, 0x20f28269, 0x20398273, 0x27f88475, 0x20656874, 0x63617041, 0x19860682, 0x41202c21, 0x322e0700, 0x7468302e, + 0x2f3a7074, 0x7777772f, 0x2584612e, 0x726f2e25, 0x856c2f67, 0x2f732943, 0x4543494c, 0x2d45534e, 0x00252982, 0x00690044, 0x20038267, 0x26038274, + 0x0065007a, 0x82200064, 0x00612403, 0x82610074, 0x00632809, 0x0070006f, 0x84720079, 0x82682025, 0x00202215, 0x221782a9, 0x82300032, 0x00372201, + 0x200b822c, 0x20238247, 0x2043826f, 0x223d826c, 0x82430020, 0x8272200d, 0x826f2033, 0x20458333, 0x220f8269, 0x822e006e, 0x82722067, 0x84692009, + 0x8253205f, 0x006e245b, 0x82520073, 0x00672631, 0x006c0075, 0x202d8261, 0x20118241, 0x20118263, 0x2023826e, 0x220f8265, 0x822d0020, 0x8244205d, + 0x826f2009, 0x8797837d, 0x82562037, 0x82722025, 0x225b852d, 0x82310020, 0x228f835f, 0x82620020, 0x8269204d, 0x8264204f, 0x82312039, 0x8a342017, + 0x8b3d8777, 0x82692051, 0x84202045, 0x847420e9, 0x826420af, 0x846d2059, 0x826b208d, 0x006f2241, 0x21df9066, 0x9f830061, 0x83002021, 0x82792025, + 0x8462201d, 0x847220f5, 0x204d83c9, 0x419b8474, 0x69200547, 0x20222b82, 0x11846300, 0x55827420, 0x6a200f85, 0x7220a382, 0x7322d182, 0x05826400, + 0x74006322, 0x6f200582, 0x73202982, 0x0341c582, 0x154f4111, 0x20131541, 0x85538420, 0x826820cd, 0x20a18363, 0x2013846e, 0x20a78274, 0x207f8273, + 0x20ed846e, 0x208f8473, 0x24db8469, 0x00790074, 0x200f8270, 0x201d8266, 0x20c98463, 0x20058264, 0x20358273, 0x85918267, 0x006624c5, 0x8272006f, + 0x82752041, 0x0597413d, 0x7420c783, 0x37874584, 0x1f827320, 0x22071941, 0x826c0065, 0x20d7831b, 0x83398272, 0x42632081, 0x6d220649, 0x97826d00, + 0x1b421185, 0x0068220b, 0x24018274, 0x003a0070, 0x2101822f, 0x01830077, 0x91822e20, 0x42007321, 0x63200b0f, 0x70228784, 0x15822e00, 0x49826f20, + 0xb7002f21, 0x8df58737, 0x827220eb, 0x842e20df, 0x826d2053, 0x004c22c1, 0x207d8669, 0x20cd8273, 0x42ff8464, 0x74200999, 0x65202782, 0x41221382, + 0xa7827000, 0x0d866320, 0x2c20338d, 0xa9421f82, 0x8232200f, 0x983020bd, 0x204b89b7, 0x22eb842e, 0x822f0067, 0x20878b89, 0x2a118273, 0x0049004c, + 0x00450043, 0x8253004e, 0x002d2105, 0x00235385, 0x84000200, 0x66ff2300, 0x08846600, 0x0325048e, 0x01000085, 0x08258202, 0x04000338, 0x06000500, + 0x08000700, 0x0a000900, 0x0c000b00, 0x0e000d00, 0x10000f00, 0x12001100, 0x14001300, 0x16001500, 0x18001700, 0x1a001900, 0x1c001b00, 0x1e001d00, + 0xcf821f00, 0x22002130, 0x24002300, 0x26002500, 0x28002700, 0xc7192900, 0x750e70dd, 0x00a300ac, 0x00850084, 0x009600bd, 0x008600e8, 0x008b008e, + 0x00a9009d, 0x000301a4, 0x0004018a, 0x00930083, 0x00f300f2, 0x0097008d, 0x00050188, 0x00f100de, 0x00aa009e, 0x00f400f5, 0x00a200f6, 0x00c900ad, + 0x00ae00c7, 0x00630062, 0x00640090, 0x006500cb, 0x00ca00c8, 0x00cc00cf, 0x00ce00cd, 0x006600e9, 0x00d000d3, 0x00af00d1, 0x00f00067, 0x00d60091, + 0x00d500d4, 0x00eb0068, 0x008900ed, 0x0069006a, 0x006d006b, 0x006e006c, 0x006f00a0, 0x00700071, 0x00730072, 0x00740075, 0x00770076, 0x007800ea, + 0x0079007a, 0x007d007b, 0x00b8007c, 0x007f00a1, 0x0080007e, 0x00ec0081, 0x01ba00ee, 0x01070106, 0x01090108, 0x000b010a, 0x01fe00fd, 0x010d010c, + 0x000f010e, 0x010001ff, 0x01110110, 0x01130112, 0x01150114, 0x01170116, 0x01190118, 0x011b011a, 0x011d011c, 0x001f011e, 0x01f900f8, 0x01210120, + 0x01230122, 0x01250124, 0x01270126, 0x01290128, 0x012b012a, 0x012d012c, 0x012f012e, 0x01d70030, 0x01320131, 0x01340133, 0x01360135, 0x01380137, + 0x013a0139, 0x013c013b, 0x013e013d, 0x00e2003f, 0x014001e3, 0x01420141, 0x01440143, 0x01460145, 0x01480147, 0x014a0149, 0x014c014b, 0x004e014d, + 0x01b100b0, 0x0150014f, 0x01520151, 0x01540153, 0x01560155, 0x00580157, 0x00fc00fb, 0x01e500e4, 0x015a0159, 0x015c015b, 0x015e015d, 0x0160015f, + 0x01620161, 0x01640163, 0x01660165, 0x01680167, 0x016a0169, 0x016c016b, 0x006e016d, 0x016f01bb, 0x01710170, 0x00e60072, 0x007301e7, 0x017401a6, + 0x01760175, 0x01780177, 0x017a0179, 0x00d8007b, 0x007c01e1, 0x00dc00db, 0x00e000dd, 0x01df00d9, 0x017e017d, 0x0180017f, 0x01820181, 0x01840183, + 0x01860185, 0x01880187, 0x018a0189, 0x018c018b, 0x018e018d, 0x0190018f, 0x01920191, 0x01940193, 0x01960195, 0x01980197, 0x019a0199, 0x019c019b, + 0x019e019d, 0x01a0019f, 0x01a201a1, 0x01a401a3, 0x01a601a5, 0x01a801a7, 0x01aa01a9, 0x01ac01ab, 0x01ae01ad, 0x01b001af, 0x01b201b1, 0x01b401b3, + 0x019b00b5, 0x01b701b6, 0x01b901b8, 0x01bb01ba, 0x01bd01bc, 0x01bf01be, 0x01c101c0, 0x01c301c2, 0x01c501c4, 0x01c701c6, 0x01c901c8, 0x01cb01ca, + 0x01cd01cc, 0x01cf01ce, 0x01d101d0, 0x01d301d2, 0x01d501d4, 0x01d701d6, 0x01d901d8, 0x01db01da, 0x01dd01dc, 0x01df01de, 0x01e101e0, 0x01e301e2, + 0x01e501e4, 0x01e701e6, 0x01e901e8, 0x01eb01ea, 0x01ed01ec, 0x01ef01ee, 0x01f101f0, 0x01f301f2, 0x01f501f4, 0x01f701f6, 0x01f901f8, 0x01fb01fa, + 0x01fd01fc, 0x02ff01fe, 0x02010200, 0x02030202, 0x02050204, 0x02070206, 0x02090208, 0x020b020a, 0x020d020c, 0x020f020e, 0x02110210, 0x02130212, + 0x02150214, 0x02170216, 0x02190218, 0x021b021a, 0x021d021c, 0x021f021e, 0x02210220, 0x02230222, 0x02250224, 0x02270226, 0x00290228, 0x02b300b2, + 0x002b022a, 0x00b700b6, 0x002c02c4, 0x00b500b4, 0x008200c5, 0x008700c2, 0x02c600ab, 0x002e022d, 0x02bf00be, 0x02bc002f, 0x02f70030, 0x02320231, + 0x02340233, 0x00360235, 0x029f008c, 0x02380237, 0x023a0239, 0x0298003b, 0x009a003c, 0x00ef0099, 0x009200a5, 0x00a7009c, 0x0094008f, 0x02b90095, + 0x023e023d, 0x0240023f, 0x02420241, 0x02440243, 0x02460245, 0x02480247, 0x024a0249, 0x024c024b, 0x024e024d, 0x0250024f, 0x02520251, 0x02540253, + 0x02560255, 0x02580257, 0x025a0259, 0x025c025b, 0x025e025d, 0x0260025f, 0x02620261, 0x02640263, 0x02660265, 0x02680267, 0x026a0269, 0x026c026b, + 0x026e026d, 0x0270026f, 0x02720271, 0x02740273, 0x02760275, 0x02780277, 0x027a0279, 0x027c027b, 0x027e027d, 0x0280027f, 0x02820281, 0x02840283, + 0x02860285, 0x02880287, 0x028a0289, 0x028c028b, 0x028e028d, 0x0290028f, 0x02920291, 0x02940293, 0x02960295, 0x02980297, 0x029a0299, 0x029c029b, + 0x029e029d, 0x02a0029f, 0x02a202a1, 0x02a402a3, 0x02a602a5, 0x02a802a7, 0x02aa02a9, 0x02ac02ab, 0x02ae02ad, 0x02b002af, 0x02b202b1, 0x02b402b3, + 0x02b602b5, 0x02b802b7, 0x02ba02b9, 0x02bc02bb, 0x02be02bd, 0x02c002bf, 0x02c202c1, 0x02c402c3, 0x02c602c5, 0x02c802c7, 0x02ca02c9, 0x02cc02cb, + 0x02ce02cd, 0x02d002cf, 0x02d202d1, 0x02d402d3, 0x02d602d5, 0x02d802d7, 0x02da02d9, 0x02dc02db, 0x02de02dd, 0x02e002df, 0x02e202e1, 0x02e402e3, + 0x02e602e5, 0x02e802e7, 0x02ea02e9, 0x02ec02eb, 0x02ee02ed, 0x02f002ef, 0x02f202f1, 0x02f402f3, 0x02f602f5, 0x02f802f7, 0x02fa02f9, 0x02fc02fb, + 0x02fe02fd, 0x030003ff, 0x03020301, 0x03040303, 0x03060305, 0x03080307, 0x030a0309, 0x030c030b, 0x030e030d, 0x0310030f, 0x03120311, 0x03140313, + 0x03160315, 0x03180317, 0x031a0319, 0x031c031b, 0x031e031d, 0x0320031f, 0x03220321, 0x03240323, 0x03260325, 0x03280327, 0x032a0329, 0x032c032b, + 0x032e032d, 0x0330032f, 0x03320331, 0x03340333, 0x03360335, 0x03380337, 0x033a0339, 0x033c033b, 0x033e033d, 0x0340033f, 0x03420341, 0x03440343, + 0x03460345, 0x03480347, 0x034a0349, 0x034c034b, 0x034e034d, 0x0350034f, 0x03520351, 0x03540353, 0x03560355, 0x03580357, 0x035a0359, 0x035c035b, + 0x035e035d, 0x0360035f, 0x03620361, 0x03640363, 0x03660365, 0x03680367, 0x036a0369, 0x036c036b, 0x036e036d, 0x0370036f, 0x03720371, 0x03740373, + 0x03760375, 0x03780377, 0x037a0379, 0x037c037b, 0x037e037d, 0x0380037f, 0x03820381, 0x03840383, 0x03860385, 0x03880387, 0x038a0389, 0x038c038b, + 0x6e2e058d, 0x076c6c75, 0x30696e75, 0x09444130, 0x7265766f, 0x726f6373, 0x65700e65, 0x646f6972, 0x746e6563, 0x64657265, 0x616d4107, 0x6e6f7263, + 0x07856107, 0x62410628, 0x65766572, 0x06846106, 0x6f410729, 0x656e6f67, 0x8561076b, 0x430b2d07, 0x63726963, 0x6c666d75, 0x630b7865, 0x04260b89, + 0x746f6443, 0x04826304, 0x63440623, 0x214e8261, 0x06856406, 0x72634425, 0x8274616f, 0x2106830d, 0x63854507, 0x85650721, 0x45062107, 0x06216484, + 0x21068465, 0x3e82450a, 0x83636121, 0x650a2198, 0x07210a88, 0x21798545, 0x07856507, 0x85450621, 0x84652058, 0x470b2106, 0x0b218389, 0x210b8967, + 0x40824704, 0x82670421, 0x470c2604, 0x6d6d6f63, 0x21578561, 0x0c8a670c, 0x89480b21, 0x680b212f, 0x04260b89, 0x72616248, 0x04826804, 0x74490628, + 0x65646c69, 0x06846906, 0x85490721, 0x690721b5, 0x06210785, 0x21b68449, 0x06846906, 0x85490721, 0x6907219f, 0x0a210785, 0x27c28849, 0x024a4902, + 0x4a0b6a69, 0x0b216289, 0x210b896a, 0x938a4b0c, 0x8c6b0c21, 0x7267330c, 0x6c6e6565, 0x69646e61, 0x614c0663, 0x65747563, 0x06846c06, 0x8b4c0c21, + 0x8a6c2027, 0x4c06280c, 0x6f726163, 0x846c066e, 0x4c042106, 0x04218582, 0x2104826c, 0x3f854e06, 0x3f856e20, 0x328a4e20, 0x8a6e0c21, 0x4e06210c, + 0x06213884, 0x3506846e, 0x70616e0b, 0x7274736f, 0x6568706f, 0x676e4503, 0x676e6503, 0xff854f07, 0x856f0721, 0x4f062807, 0x76657262, 0x846f0665, + 0x4f0d2f06, 0x676e7568, 0x6d757261, 0x7475616c, 0x0d8b6f0d, 0x84520621, 0x7206217c, 0x0c210684, 0x21768a52, 0x0c8a720c, 0x84520621, 0x7206217c, + 0x53200685, 0x06212e84, 0x21068473, 0x3a41530b, 0x730b2109, 0x0c210b89, 0x21408a54, 0x0c8a740c, 0x85540621, 0x84742046, 0x54042606, 0x04726162, + 0x28048274, 0x69745506, 0x0665646c, 0x21068475, 0xcd855507, 0x85750721, 0x55062107, 0x0621ce84, 0x27068475, 0x69725505, 0x7505676e, 0x0d210583, + 0x20e18c55, 0x210d8b75, 0xfd415507, 0x75072105, 0x0b210785, 0x21a18957, 0x0b8a770b, 0x0b8a5920, 0x0b897920, 0x845a0621, 0x7a0621e4, 0x0a210684, + 0x0843425a, 0x887a0a21, 0x6c05270a, 0x73676e6f, 0x8b83410a, 0x61202685, 0x07220a88, 0x12844541, 0x65610722, 0x0b260784, 0x616c734f, 0x0b856873, + 0x0b896f20, 0x41530c21, 0x0c210a20, 0x200c8a73, 0x2efe8506, 0x6e6f7405, 0x640d736f, 0x65726569, 0x84736973, 0x410a250d, 0x6168706c, 0x092e0a84, + 0x746f6e61, 0x69656c65, 0x70450c61, 0x91826973, 0x08221684, 0x1f867445, 0x866f4921, 0x4f0c2709, 0x7263696d, 0x1f846e6f, 0x8a550c21, 0x4f0a242c, + 0x8567656d, 0x6911212e, 0x6b8c2e82, 0x6b840520, 0x65420433, 0x47056174, 0x616d6d61, 0x696e7507, 0x34393330, 0x216f8607, 0x1a825a04, 0x6f820320, + 0x68540522, 0x04200982, 0x05367083, 0x7070614b, 0x614c0661, 0x6164626d, 0x02754d02, 0x5802754e, 0x81860769, 0x69500231, 0x6f685203, 0x67695305, + 0x5403616d, 0x86077561, 0x5003258d, 0x43036968, 0x50220382, 0x66856973, 0x0c394122, 0x91874f83, 0x28860f20, 0x0a210f87, 0x08084161, 0x8a650c21, + 0x820820d1, 0x20e78488, 0x84cf8309, 0x75142109, 0xdc8d1f85, 0x04213f84, 0x212e8262, 0xdc836705, 0x65640526, 0x0761746c, 0x04214b86, 0x2018827a, + 0x21038203, 0xda847405, 0x05214c83, 0x20da846b, 0x85da846c, 0x434229a4, 0x02756e02, 0x6f076978, 0x25056141, 0x6f687203, 0xdc837306, 0x84053121, + 0x74032106, 0x7f86e382, 0x82700321, 0x826320df, 0x268e8203, 0x656d6f05, 0x410c6167, 0x0f200b73, 0x0c20a68e, 0xc3845386, 0x1c860c20, 0x0a200c84, + 0x0a843c84, 0x66610929, 0x30316969, 0x87333230, 0x31352109, 0x32200988, 0x1d890988, 0x13883420, 0x09883520, 0x09883620, 0x09883720, 0x09883820, + 0x09873920, 0x88303621, 0x20638809, 0x21638736, 0x4f883431, 0x45883120, 0x45883120, 0x45883120, 0x45883220, 0x45883220, 0xa9883220, 0x9f883220, + 0x4f883220, 0x9f883220, 0x59883220, 0x59883220, 0x59883220, 0x59883320, 0x59883320, 0x59883320, 0x03413320, 0x88332008, 0x88332063, 0x88332063, + 0x88332063, 0x88332063, 0x88332063, 0x88342063, 0x88342063, 0x88342063, 0x88342063, 0x88342063, 0x09174163, 0x63883420, 0x63883420, 0x63883420, + 0x63883420, 0x95883620, 0x31883620, 0x31883620, 0x31883620, 0x31883620, 0x95883720, 0x8b883720, 0x8b883720, 0x8b883720, 0x59883720, 0x59883720, + 0x59883720, 0x59883720, 0x59883720, 0x59883820, 0xef883820, 0x63883820, 0x63883820, 0x63883820, 0x63883820, 0x63883820, 0x63883820, 0x63883820, + 0x63883820, 0x63883920, 0x63883920, 0x63883920, 0x63883920, 0x63883920, 0x63883920, 0x63883920, 0x63883920, 0x45893720, 0x31216387, 0x21638730, + 0x1d873031, 0x42303121, 0x302008bb, 0x31216387, 0x21638730, 0x63873031, 0x87303121, 0x30312163, 0x31216387, 0x21c78730, 0x63883031, 0x63883120, + 0x3520b389, 0x3829db89, 0x72675706, 0x06657661, 0x24068577, 0x75636157, 0x840d8274, 0x57092106, 0x21079d44, 0x09877709, 0x85590621, 0x84792028, + 0x61092d06, 0x30696966, 0x38303230, 0x646e750d, 0x2b06484a, 0x0d6c6264, 0x746f7571, 0x76657265, 0x65251282, 0x696d0664, 0x2c55836e, 0x6f636573, + 0x6509646e, 0x616c6378, 0x2925826d, 0x75736e09, 0x69726570, 0x4785726f, 0x3439382f, 0x65700631, 0x61746573, 0x72754504, 0x2215846f, 0x42323136, + 0x0982068f, 0x3d069f41, 0x35333136, 0x73650932, 0x616d6974, 0x09646574, 0x65656e6f, 0x74686769, 0x68740c68, 0x0b866572, 0x660b7324, 0x0b877669, + 0x82730c21, 0x856e208b, 0x05732e24, 0x746c6544, 0x6e750761, 0x30424669, 0x2a078631, 0x79630d32, 0x6c6c6972, 0x83626369, 0x64082db7, 0x656c746f, + 0x106a7373, 0x6f726163, 0x200b0849, 0x0a14470b, 0x0b8a1120, 0x746f7222, 0x0c248c82, 0x6f72657a, 0x0c24d687, 0x72756f66, 0x8e820c89, 0x0b230c87, + 0x87786973, 0x840d200b, 0x840d889b, 0x233488a4, 0x656e696e, 0xa9830c87, 0x30303223, 0x84078630, 0x303223b9, 0x0f863230, 0x07863320, 0x07863420, + 0x07863520, 0x07863620, 0x07863720, 0x07863820, 0x07863920, 0x07864120, 0x07834220, 0x46454623, 0x22078446, 0x86434646, 0x83442007, 0x31302307, + 0x07843046, 0x84423221, 0x33302317, 0x0f843144, 0x84443321, 0x840f827f, 0x45312367, 0x17834533, 0x47840782, 0x85453121, 0x840782af, 0x4631222f, + 0x2b4f8534, 0x09334632, 0x69736164, 0x69786f61, 0x84078b41, 0x42462bc1, 0x4f053430, 0x6e726f68, 0x05846f05, 0x05845520, 0x05837520, 0x51857185, + 0x41333021, 0x078205bb, 0x6804332e, 0x086b6f6f, 0x62746f64, 0x776f6c65, 0x34202584, 0x34212586, 0x216f8530, 0xbf853534, 0x86353421, 0x8636200f, + 0x8436200f, 0x34302297, 0x21c78536, 0x85843634, 0x34200f82, 0x36214785, 0x84078635, 0x201782df, 0x200f8637, 0x20078638, 0x20078639, 0x20078641, + 0x41078642, 0x34210527, 0x206f8736, 0x20178645, 0x21078546, 0x07863037, 0x07863120, 0x37207f86, 0x37207f86, 0x37207f86, 0x37207f86, 0x37207f86, + 0x37207f86, 0x37207f86, 0x37207f86, 0x37207f86, 0x37207f86, 0x37207f86, 0x37207f86, 0x37207f86, 0x38217f86, 0x21778530, 0x07863138, 0x38207f86, + 0x38207f86, 0x38207f86, 0x38207f86, 0x38207f86, 0x38207786, 0x38207786, 0x38207786, 0x38207786, 0x38207786, 0x38207786, 0x38207786, 0x39207786, + 0x39206786, 0x39206786, 0x39206786, 0x39206786, 0x39206786, 0x3920e786, 0x39206f86, 0x39206f86, 0x39206f86, 0x39206f86, 0x39206f86, 0x39206f86, + 0x39206f86, 0x41216f86, 0x21df8530, 0x07863141, 0x41207f86, 0x41207f86, 0x41207f86, 0x41207f86, 0x41207f86, 0x41207f86, 0x41207f86, 0x41207f86, + 0x41207f86, 0x41207f86, 0x41207f86, 0x41207f86, 0x41207f86, 0x42217f86, 0x21778530, 0x07863142, 0x42207f86, 0x42207f86, 0x42207f86, 0x42207f86, + 0x42207f86, 0x42207f86, 0x42207f86, 0x42207f86, 0x42207f86, 0x8f437f86, 0x42342106, 0x42207f86, 0x42207f86, 0x43217f86, 0x21778530, 0x07863143, + 0x43207f86, 0x43207f86, 0x43207f86, 0x43207f86, 0x43207f86, 0x43207f86, 0x43207f86, 0x43207f86, 0x43207f86, 0x43207f86, 0x4320ff86, 0x43207f86, + 0x43207f86, 0x44217f86, 0x44778530, 0x3420062f, 0x21062f44, 0x7f864434, 0x7f864420, 0x7f864420, 0x7f864420, 0x7f864420, 0x7f864420, 0x7f864420, + 0x7f864420, 0x7f864420, 0x7f864420, 0x7f864420, 0x7f864420, 0x7f864420, 0x7f864520, 0x85314521, 0x86452087, 0x864520ff, 0x8645207f, 0x8645207f, + 0x8645207f, 0x8645207f, 0x8645207f, 0x8645207f, 0x8645207f, 0x8645207f, 0x8645207f, 0x8645207f, 0x8645207f, 0x8645207f, 0x0637457f, 0x31463422, + 0x46207f85, 0x46207f86, 0x46207f86, 0x46207f86, 0x46207f86, 0x46207f86, 0x46207f86, 0x46207f86, 0x46207f86, 0x46207f86, 0xa7457f86, 0x34302205, + 0x207f8646, 0x457f8646, 0x302105c7, 0x06074535, 0x2d453520, 0x46352006, 0x1782052f, 0x35217f85, 0x217f8530, 0x7f853035, 0x85303521, 0x3035217f, + 0x35217f85, 0x217f8530, 0x7f853035, 0x85303521, 0x3035217f, 0x35217f85, 0x21ff8530, 0x7f853035, 0x85303521, 0x3035217f, 0x3522ff85, 0xf7843031, + 0x31313522, 0xff850786, 0x84313521, 0x4531217f, 0x82059f43, 0x821f8407, 0x821f8407, 0x841f8707, 0x840f829f, 0x8407829f, 0x8407829f, 0x8407829f, + 0x8407829f, 0x8407829f, 0x8407829f, 0x8407829f, 0x8407829f, 0x8407829f, 0x8407829f, 0x4531219f, 0x82059f43, 0x46312007, 0x422005b7, 0x9f437f86, + 0x86178205, 0x059f437f, 0x7f860f82, 0x82059f43, 0x437f860f, 0x0f82059f, 0x9f437f86, 0x860f8205, 0x059f437f, 0x7f860f82, 0x21059f43, 0x9f434531, + 0x86078205, 0x8643207f, 0x059f437f, 0x7f861782, 0x82059f43, 0x437f860f, 0x0f82059f, 0x9f437f86, 0x860f8205, 0x059f437f, 0x7f860f82, 0x82059f43, + 0x437f860f, 0x3121059f, 0x059f4345, 0x7f860782, 0x82059f43, 0x067f410f, 0x82059f43, 0x067f410f, 0x82059f43, 0x067f410f, 0x82059f43, 0x067f410f, + 0x82059f43, 0x067f410f, 0x82059f43, 0x067f410f, 0x82059f43, 0x067f410f, 0x21059f43, 0x9f434531, 0x86078205, 0x059f43ff, 0xff860f82, 0x82059f43, + 0x43ff860f, 0x0f82059f, 0x9f43ff86, 0x860f8205, 0x059f43ff, 0xff860f82, 0x82059f43, 0x43ff860f, 0x3121059f, 0x059f4345, 0x31200782, 0x4305ff41, + 0x0f82058f, 0x8f43ef86, 0x860f8205, 0x058f43ef, 0xef840f82, 0x46303221, 0x33230607, 0x51134630, 0x612809af, 0x65747563, 0x626d6f63, 0x6723138a, + 0x84766172, 0x89122013, 0x6f682327, 0x268e6b6f, 0x6c697423, 0x25268464, 0x6572620e, 0x49886576, 0x44880e85, 0x1d840d20, 0x1c853f87, 0x10203a88, + 0x8307cb4a, 0x656c241f, 0x4a117466, 0x692108dc, 0x21138367, 0x118f4355, 0x05434c32, 0x6c612e67, 0x63540874, 0x6c696465, 0x7408616c, 0x00200886, + 0x022a0084, 0x02000500, 0x0300ffff, 0x0f820100, 0x03820c20, 0x03821620, 0x0d830220, 0x82840321, 0x82042005, 0x2219830d, 0x82010000, 0x000a2e09, + 0x002c001e, 0x74616c01, 0x0008006e, 0x20118204, 0x203b8200, 0x23078201, 0x72656b01, 0x00211383, 0x820d8400, 0x8202201b, 0x83012021, 0xc8a52103, + 0x38080d82, 0x03f10100, 0x07ec03ec, 0x08600752, 0x096007de, 0x0bce0a3c, 0x0d220c34, 0x0f3a0e54, 0x11061020, 0x13ca1298, 0x15d214a0, 0x1a8a1904, + 0x21ba1d18, 0x27922360, 0x285207ac, 0x20018292, 0x26038298, 0x294429aa, 0x8260295a, 0x29922a09, 0x28802972, 0x2afe2998, 0x08018214, 0x042b2a22, + 0x52071a2b, 0xf22be42b, 0x522e002c, 0x002c522e, 0xe2329830, 0x3835340b, 0x38351e36, 0x3a0e3835, 0x36230185, 0x877e37fc, 0x98112301, 0x0185dc38, + 0x84e63921, 0x82658361, 0x72292503, 0xa43e9828, 0xae220186, 0x0187bc3e, 0x3e722923, 0x260186d6, 0x096640e0, 0x8392283c, 0x84402703, 0x340b9228, + 0x01839828, 0x42210783, 0x214b851a, 0x07839842, 0x423a0e23, 0x23db839e, 0x06106029, 0x42210183, 0x8505831a, 0x98112121, 0x7220c382, 0x3f850585, + 0x2888432b, 0x44964498, 0x191a4296, 0x3101858a, 0x142aba1d, 0x042b9223, 0xac271049, 0x8a4dac27, 0x7383a050, 0x98285b08, 0x9c516e51, 0xd851aa51, + 0x78526a52, 0x2054de52, 0x4c568254, 0x38591659, 0x6c5a565a, 0x585e165b, 0x845f665e, 0x04615e60, 0x6465ae64, 0xec658e65, 0x2c661e66, 0x9c6ade66, + 0x9228a26a, 0x9c6abc6a, 0x146b0e6b, 0x4c6b426b, 0x92287a6b, 0x2e6cec6b, 0x8a6c546c, 0xb66ca86c, 0x0382cc6c, 0xfc6cde2c, 0x486d366d, 0x9e6d7229, + 0xa383b06d, 0xfe6d7708, 0xd66fe06e, 0xaa732c73, 0x2a74c073, 0xda750875, 0x1677a076, 0x6a7acc78, 0x3e7d947c, 0x0680c87d, 0xd6811081, 0xa2837082, + 0x16860085, 0x6e8c2087, 0xa68efc8d, 0x2290608f, 0x96911c91, 0xa6921892, 0x82931c93, 0x9a940894, 0xfa94b894, 0xb2953095, 0xae962896, 0x86973897, + 0xa698e497, 0xaa993899, 0x769a209a, 0x9828d09a, 0xa89b369b, 0x9828ee9b, 0x3e9c309c, 0x07829828, 0xba9cb032, 0xbe9d409d, 0x369ec49d, 0x9a94ac9e, + 0x142aba1d, 0x23250387, 0xa2042b92, 0x0801821a, 0x28a22820, 0x3c093c09, 0x7ca53aa5, 0xa283fa94, 0x9691a698, 0x1686ae96, 0x6a7a8697, 0x10816a7a, + 0x03833095, 0x96a28325, 0x830085ae, 0x6e8c2305, 0x0383a698, 0x98a69823, 0x850f83a6, 0xa6982703, 0x608fbea5, 0x3b83209a, 0x96008529, 0x972087ae, + 0x83a076e4, 0xae962111, 0x47870583, 0x0f830783, 0x3b831f85, 0x0d836983, 0x98208723, 0x830383a6, 0x2703871d, 0xa283a076, 0xc073a283, 0x4d853583, + 0x73211987, 0x219d83c0, 0xb183fa94, 0x83ae9621, 0x83a58747, 0x85118531, 0xae962199, 0x0783b187, 0x97216985, 0x859387e4, 0x89a385d1, 0x833f85cd, + 0x21278399, 0x01953c09, 0x420bf542, 0x0e2505ad, 0x2998113a, 0x21039772, 0x01873aa5, 0x198a1925, 0x877ca58a, 0x92232301, 0x0387042b, 0x00964431, + 0xff2400d9, 0x002c00ae, 0x00370029, 0x82390052, 0x003a2403, 0x823b0066, 0x823c200f, 0x823d200b, 0xff462407, 0x824700c3, 0x82482003, 0xff4a2403, + 0x825200d7, 0x82542007, 0x82572003, 0x8259201b, 0x005a2403, 0x825c0014, 0x82822007, 0x82832047, 0x82842003, 0x82852003, 0x82862003, 0x82872003, + 0xff882403, 0x828e005c, 0x828f201f, 0x82902003, 0x82912003, 0x829f2003, 0x82a8205b, 0x82a92043, 0x82aa2003, 0x82ab2003, 0x82ac2003, 0x82ad2003, + 0x82b42003, 0x82b52003, 0x82b62003, 0x82b72003, 0x82b82003, 0x82ba2003, 0x82bf2003, 0x82c12037, 0x82c22003, 0x82c42053, 0x82c62003, 0x82c92003, + 0x82cb2017, 0x82cd2003, 0x82cf2003, 0x82d52003, 0x82d72003, 0x82d92003, 0x82db2003, 0x82dd2003, 0x82ec2003, 0x82f02033, 0x00f22803, 0xff0f0129, + 0x821101c3, 0x82132003, 0x82152003, 0x00242403, 0x82260152, 0x00362803, 0x00370166, 0x82380114, 0x8239200b, 0x823a2027, 0x823b2007, 0x21ff8207, + 0x07823f01, 0xaeff4324, 0x03825f01, 0x03826920, 0x1b827120, 0x3b827920, 0x03827e20, 0x1b828020, 0x07828220, 0x07828a20, 0x07828c20, 0x03828e20, + 0x03829020, 0x0121e382, 0x20078293, 0x20178294, 0x20078296, 0x20038299, 0x2003829b, 0x243b829d, 0x019affa4, 0x240782a6, 0x013d00a8, 0x244f82aa, + 0x0185ffae, 0x200b82b0, 0x207f82b1, 0x200b82b5, 0x201b82bc, 0x820f82bd, 0xc40121ef, 0xd7820b82, 0x82d80121, 0x82db203b, 0x82dc2003, 0x82dd204f, + 0x82de2003, 0x82ea200b, 0x82ed2003, 0x82fa2003, 0x82fb20bb, 0x82fc203b, 0x82fd2007, 0x82fe2007, 0x00ff3007, 0x00000214, 0x00010252, 0xff280229, + 0x825802ae, 0xff602403, 0x826a02c3, 0x826d2003, 0x82722013, 0x0076240f, 0x827f023d, 0x8281200f, 0x8283200f, 0x82852003, 0x8287200b, 0x82892003, + 0x828b2003, 0x828d200f, 0x829f2007, 0x82a92023, 0x82aa2047, 0x82b2200f, 0x82b4200f, 0x82b52003, 0x82b6200f, 0x82b7200f, 0x82b82007, 0x82b92007, + 0x82ba2007, 0x82bb2007, 0x82bd202b, 0x82ca200b, 0xffce2407, 0x82d90285, 0x82db2063, 0x82dd2003, 0x82e02003, 0x82e52037, 0x82f02017, 0x82f22007, + 0x82f42003, 0x82f72003, 0x82f8200f, 0x82f92037, 0x82fa2007, 0x82fb2007, 0x00fc2807, 0x00050329, 0x8207033d, 0xff0a2403, 0x820c03c3, 0x820e2003, + 0x82102013, 0xff112403, 0x82160385, 0x0017240f, 0x82180352, 0x821a200f, 0x821b200b, 0xff1d2413, 0x821f03ae, 0x82212003, 0x82232003, 0x82252003, + 0x82272003, 0x82292003, 0x822b2003, 0x822d2003, 0x822f2003, 0x82312003, 0x82332003, 0x82362003, 0x82382037, 0x823a2003, 0x823c2003, 0x823e2003, + 0x82402003, 0x82422003, 0x82442003, 0x82452003, 0x8247205b, 0x824a2003, 0x824c200b, 0x824e2003, 0x82502003, 0x82522003, 0x82542003, 0x82562003, + 0x82582003, 0x825a2003, 0x825c2003, 0x825e2003, 0x82602003, 0x826f2003, 0x82702097, 0x82712037, 0x82722007, 0x82732007, 0x82742007, 0x00832e07, + 0x00030052, 0x007b002d, 0x017b00f6, 0x260782a3, 0xff26005f, 0x822a00c3, 0x82322003, 0x82342003, 0xff372803, 0xff38009a, 0x823900d7, 0xff3a2407, + 0x823c00ae, 0x82892007, 0x82942017, 0x82952003, 0x82962003, 0x82972003, 0x82982003, 0x829a2003, 0x829b2003, 0x829c202b, 0x829d2003, 0x829e2003, + 0x829f2003, 0x82c8202f, 0x82ce2017, 0x82de2003, 0x82e02003, 0x82e22003, 0xffe42403, 0x820e01c3, 0x82122003, 0xff242403, 0x8226019a, 0xff2c2403, + 0x823001d7, 0x82322003, 0x82342003, 0xff362403, 0x823801ae, 0x823a2017, 0x82662003, 0x826d2027, 0x82712003, 0x82b8200b, 0x82bb2007, 0x82bc2003, + 0x82fa200b, 0x82fc2023, 0xfffe3003, 0xff0002ae, 0xff5f029a, 0xff6102c3, 0x826c02d7, 0x827e2007, 0x82842003, 0x82862003, 0x82882003, 0x828a2003, + 0x828c2003, 0x82a92003, 0x82b12027, 0x82b32007, 0x82b52003, 0x82b7200b, 0x82b92003, 0x82bd2003, 0x82e12003, 0x82e32013, 0x82ef2003, 0x82f12003, + 0xfff32403, 0x821503c3, 0xff172403, 0x8219039a, 0x82492007, 0x824b2003, 0x824d2003, 0x824f2003, 0x82512003, 0x82532003, 0x82552003, 0x82572003, + 0x82592003, 0x825b2003, 0x825d2003, 0x258b8203, 0xd7ff6103, 0x03826303, 0x03826520, 0x03826720, 0x03826920, 0x03826b20, 0x03826d20, 0x53826f20, + 0x03827120, 0x03827320, 0x9aff8326, 0x37001700, 0x1182d182, 0xff720129, 0xffb001c3, 0x82b501d7, 0x20e58303, 0x20dd82c4, 0x20d58276, 0x8303829f, + 0x20b58bbd, 0x201382bb, 0x20b982bd, 0x200782ca, 0x200382ce, 0x205982e5, 0x20038205, 0x20038207, 0x83038211, 0xff1b2ab9, 0x006400d7, 0x00aeff05, + 0x2403820a, 0x00ecff26, 0x2003822a, 0x20038232, 0x24038234, 0x0085ff37, 0x24078238, 0x00c3ff39, 0x4129823a, 0xec2205e3, 0x13829400, 0x03829520, + 0x03829620, 0x03829720, 0x03829820, 0x03829a20, 0x03829b20, 0x03829c20, 0x03829d20, 0x03829e20, 0x2205e341, 0x82ce00ec, 0x82de200b, 0x82e02003, + 0x82e22003, 0xffe42403, 0x820e01ec, 0x82122003, 0x82142003, 0xff2424c9, 0x82260185, 0x822c2003, 0x8230200f, 0x82322003, 0x82342003, 0x82362003, + 0x09e7411b, 0x6d01ec22, 0x71201382, 0xb8202782, 0xbb200782, 0xbc200382, 0xfa200b82, 0xfc202382, 0xfe200382, 0x0020e182, 0x0724ed82, 0x0b02aeff, + 0x5f240382, 0x6102ecff, 0x6c200382, 0x7e200382, 0x84200382, 0x86200382, 0x88200382, 0x8a200382, 0x8c200382, 0xa9240382, 0xb10285ff, 0xb3200782, + 0xb5200382, 0xb7200b82, 0xb9200382, 0xbd200382, 0xe1200382, 0xe3201382, 0xef200382, 0xf1200382, 0xf3240382, 0x1503ecff, 0x17240382, 0x190385ff, + 0x49200782, 0x4b200382, 0x4d200382, 0x4f200382, 0x51200382, 0x53200382, 0x55200382, 0x57200382, 0x59200382, 0x5b200382, 0x5d200382, 0x5f200382, + 0x61200382, 0x63200382, 0x65200382, 0x67200382, 0x69200382, 0x6b200382, 0x6d200382, 0xef410382, 0x0085280d, 0xff2c0019, 0x823700ec, 0x82392003, + 0x823b2003, 0x823c2003, 0x829f2003, 0x822420f1, 0x82262003, 0x82382003, 0x823a2003, 0x82712003, 0x82bc2003, 0x8400209d, 0x02ec22cd, 0x200782b5, + 0x200382b7, 0x200382b9, 0x22ad84bd, 0x824503ec, 0x84472007, 0x03ec2165, 0x03212f82, 0x200b8273, 0x264f8283, 0x0005003b, 0x820a0029, 0x820c2003, + 0xff262403, 0x822a00d7, 0x82322003, 0x82342003, 0x82402003, 0x82602013, 0x82892003, 0x8294200b, 0x82952003, 0x82962003, 0x82972003, 0x82982003, + 0x829a2003, 0x82c82003, 0x82ce2003, 0x82de2003, 0x82e02003, 0x82e22003, 0xffe42403, 0x820e01d7, 0x82122003, 0x82662003, 0x826d2003, 0x82b82003, + 0xffbb2803, 0x000702d7, 0x820b0229, 0x825f2003, 0x826c200b, 0x827e2003, 0x82842003, 0x82862003, 0x82882003, 0x828a2003, 0x828c2003, 0x82b12003, + 0x82b32003, 0x82e12003, 0x82e32003, 0x82ef2003, 0x82f12003, 0xfff32403, 0x821503d7, 0x82192003, 0x82492003, 0x824b2003, 0x824d2003, 0x824f2003, + 0x82512003, 0x82532003, 0x82552003, 0x82572003, 0x82592003, 0x825b2003, 0x825d2003, 0x276f8203, 0x0f004c00, 0x1100c3ff, 0x24200382, 0x5f41fb82, + 0x00c32205, 0x200b8239, 0x0863413a, 0x3d00d722, 0x82200b82, 0x83200382, 0x84200382, 0x85200382, 0x86200382, 0x87200382, 0x88200382, 0x8e203b82, + 0x8f200782, 0x90200382, 0x91200382, 0x9f200382, 0xc220f182, 0xc4200782, 0xc6200382, 0xec200382, 0xf0200382, 0xf2280382, 0x2401ecff, 0x2601c3ff, + 0x36280382, 0x3801ecff, 0x3a01d7ff, 0x3b200382, 0x3d200b82, 0x3f200382, 0x43200382, 0x5f200382, 0x69200382, 0x71200382, 0xaa202782, 0xbc200782, + 0xfa200782, 0xfc200782, 0xfe240382, 0x0002ecff, 0x2820f582, 0x58200782, 0x72200382, 0xa9240382, 0xb502c3ff, 0xb7200382, 0xb9200382, 0xbd200382, + 0xd9200382, 0xdb201782, 0xdd280382, 0x1703ecff, 0x1d03c3ff, 0x1f200782, 0x21200382, 0x23200382, 0x25200382, 0x27200382, 0x29200382, 0x2b200382, + 0x2d200382, 0x2f200382, 0x31200382, 0x33200382, 0x1f420382, 0x03d72609, 0x03d7ff71, 0x20038273, 0x26eb8283, 0x00050039, 0x820a003d, 0x000c2803, + 0xff0f0029, 0x8211009a, 0x82222003, 0x8224200b, 0x003924f5, 0x823a0014, 0x823c2003, 0x072b4203, 0x17828220, 0x03828320, 0x03828420, 0x03828520, + 0x03828620, 0x03828720, 0x4d828820, 0x27829f20, 0x0b82c220, 0x0382c420, 0xd7ffc628, 0x14003601, 0x03823801, 0x03823a20, 0x0f824320, 0x03825f20, + 0x03826920, 0x0382aa20, 0x1382fa20, 0x0382fc20, 0x1400fe24, 0x03820002, 0x3d000724, 0x03820b02, 0xd7ff2824, 0x03825802, 0x03827220, 0x0382d920, + 0x0382db20, 0xad82dd20, 0x03821d20, 0x03821f20, 0x03822120, 0x03822320, 0x03822520, 0x03822720, 0x03822920, 0x03822b20, 0x03822d20, 0x03822f20, + 0x03823120, 0x03823320, 0x14006f24, 0x03827103, 0x93827320, 0x0543e583, 0x0ffd4405, 0x44ff8921, 0xc82019e9, 0xd5441b82, 0x01ec231d, 0xb144ff66, + 0x06ad4405, 0x210afd42, 0x954402ec, 0x0791441b, 0x44178144, 0x0020327d, 0xe743e58b, 0x3bdf430d, 0xe3431420, 0x0064268e, 0x009aff05, 0x4103820a, + 0xc9460fcb, 0x00ae2409, 0x48c3ff3a, 0xdf4106ad, 0x35c94619, 0x4601ec21, 0xc32019c9, 0x460ab148, 0xc32917c9, 0xc3fffc01, 0xc3fffe01, 0x05c94602, + 0x0b029a25, 0x46029aff, 0x7545bbc9, 0x00d72117, 0x23057545, 0xff3c00d7, 0x211f7545, 0x754500d7, 0x003526eb, 0x0033ff0f, 0x20038211, 0x06914924, + 0x2307ff47, 0x00d7ff3d, 0x2619b14e, 0xff890071, 0x829f00ec, 0x0b6d4e03, 0x2006a744, 0x072f4801, 0xd7ff3b24, 0x03823d01, 0x03823f20, 0x280b214e, + 0x01aeffaa, 0x02ecffbb, 0x4d038200, 0x7222077d, 0x114daeff, 0x4c03200b, 0x6f212fb5, 0x086f48ff, 0x42187d47, 0xc3202b07, 0x22ec0742, 0x4937000c, + 0xe7490aef, 0xffa92107, 0x2015e349, 0x262b8283, 0x00050021, 0x820a0052, 0xff0f2403, 0x4710009a, 0x85200caf, 0x2c10bf4d, 0x00ecff36, 0x00140037, + 0x0085ff44, 0x20038246, 0x20038247, 0x20038248, 0x2437824a, 0x00aeff50, 0x20038251, 0x200f8252, 0x20078253, 0x20078254, 0x20078255, 0x20078256, + 0x24078258, 0x00c3ff59, 0x2003825a, 0x2003825b, 0x2003825c, 0x2003825d, 0x201b8282, 0x20038283, 0x20038284, 0x20038285, 0x20038286, 0x23038287, + 0x0071ff88, 0x201b174e, 0x202382a2, 0x200382a3, 0x200382a4, 0x200382a5, 0x200382a6, 0x200382a7, 0x200382a8, 0x200382a9, 0x200382aa, 0x200382ab, + 0x200382ac, 0x200382ad, 0x207f82b3, 0x200782b4, 0x200382b5, 0x200382b6, 0x200382b7, 0x200382b8, 0x200382ba, 0x201b82bb, 0x200382bc, 0x200382bd, + 0x200382be, 0x209782bf, 0x200382c1, 0x201b82c2, 0x200382c3, 0x200382c4, 0x200382c5, 0x200382c6, 0x200382c7, 0x201b82c8, 0x200782c9, 0x200382cb, + 0x200382cd, 0x200f82ce, 0x200782cf, 0x200382d5, 0x200382d7, 0x200382d9, 0x200382db, 0x4e0382dd, 0x06240fa3, 0x0801aeff, 0x0a200382, 0x0e280382, + 0x0f01c3ff, 0x110185ff, 0x12200382, 0x13200b82, 0x14200782, 0x15200782, 0x1c240782, 0x1d01ecff, 0x1f200782, 0x20200382, 0x21200b82, 0x22200782, + 0x23200782, 0x24240782, 0x26011400, 0x37200382, 0x39202b82, 0x40200382, 0x43200382, 0x44201782, 0x4a200382, 0x5f200382, 0x66200382, 0x69201382, + 0x6d200782, 0x71200782, 0x79202b82, 0x7b200b82, 0x7e207382, 0x80200782, 0x82201382, 0x84200782, 0x8a200f82, 0x8c200b82, 0x8e200b82, 0x90200382, + 0x91200382, 0x93200f82, 0x94200782, 0x96200782, 0x99200782, 0x9b200382, 0xa0200382, 0xaa207b82, 0x2b4f0782, 0x20538208, 0x820f82ca, 0xd80121f7, + 0xdb200782, 0xdc200382, 0xdd203382, 0xde200382, 0xea200b82, 0xed200382, 0xee200382, 0xfb200382, 0xfd201382, 0xff240382, 0x0102c3ff, 0x022c0382, + 0x0302aeff, 0x07029aff, 0x0b025200, 0x28240382, 0x580285ff, 0x59200382, 0x5f200382, 0x60201f82, 0x6a200782, 0x6c200382, 0xbf820b82, 0x82720221, + 0x827e200b, 0x827f200b, 0x82812007, 0x4f832007, 0x85200687, 0x86200f82, 0x87200b82, 0x88200782, 0x89200782, 0xcf820782, 0x828b0221, 0x828c200b, + 0x828d2003, 0x00a9240f, 0x82aa0214, 0x82b1200b, 0x82b22003, 0x82b3200f, 0x82b42007, 0x82b52007, 0x82b62017, 0x82b7200b, 0x82b82007, 0x82b92007, + 0x82ba2007, 0x82bd2007, 0x82d92007, 0x82da201f, 0x21d38203, 0x0782dc02, 0x0382dd20, 0x0382e020, 0x200bcb4f, 0x200f82f0, 0x202f82f1, 0x200782f2, + 0x200782f3, 0x200782f4, 0x200782f8, 0x280382fa, 0x03c3fffc, 0x0385ff0a, 0x2003820c, 0x200b820e, 0x20038210, 0x20038215, 0x240f8216, 0x03140017, + 0x200b8218, 0x20038219, 0x200f821a, 0x2003821d, 0x2003821e, 0x2003821f, 0x20038221, 0x20038222, 0x20038223, 0x20038224, 0x20038225, 0x20038226, + 0x20038227, 0x20038228, 0x20038229, 0x2003822a, 0x2003822b, 0x2003822c, 0x2003822d, 0x2003822e, 0x2003822f, 0x20038230, 0x20038231, 0x20038232, + 0x20038233, 0x20038234, 0x20038236, 0x20038238, 0x2003823a, 0x2003823c, 0x2003823e, 0x20038240, 0x20038242, 0x20038244, 0x20838249, 0x2007824a, + 0x2007824b, 0x2007824c, 0x2007824d, 0x2007824e, 0x2007824f, 0x20078250, 0x20078251, 0x20078252, 0x20078253, 0x20078254, 0x20078255, 0x20078256, + 0x20078257, 0x20078258, 0x20078259, 0x2007825a, 0x2007825b, 0x2007825c, 0x2007825d, 0x2007825e, 0x2007825f, 0x24078260, 0x03aeff62, 0x20038264, + 0x20038266, 0x20038268, 0x2003826a, 0x2003826c, 0x2003826e, 0x20238270, 0x20038272, 0x2a038274, 0x00140083, 0xff0f0023, 0x821100d7, 0x4d242003, + 0xd7211c4b, 0x0a374d00, 0x0b4d0120, 0xffaa230b, 0xf34c02ec, 0x0bdf4c0b, 0x212edb4c, 0x1345e800, 0x09bf4c0c, 0x4e00c321, 0x44230fef, 0x5600c3ff, + 0xc3220d37, 0xc5825000, 0x3f565120, 0x82532006, 0x82542007, 0x82552023, 0x82562007, 0x82582003, 0x82822003, 0x8283200f, 0x82842003, 0x82852003, + 0x82862003, 0x82872003, 0xff882303, 0x574b0085, 0x82a2201b, 0x82a32023, 0x82a42003, 0x82a52003, 0x82a62003, 0x82a72003, 0x175f5603, 0x6b82b320, + 0x6356b420, 0x82bb2016, 0x82bc201b, 0x82bd2003, 0x82be2003, 0x82c22003, 0x82c32027, 0x82c42003, 0x82c52003, 0x82c62003, 0x82c72003, 0x82c82003, + 0x0b7b561b, 0x0f82ce20, 0x4f177f56, 0x06240fcf, 0x0801d7ff, 0x0a200382, 0x0e200382, 0x93560382, 0x82122007, 0xff13240b, 0x821401c3, 0x82152007, + 0x821d2007, 0x821f2007, 0x82212003, 0x82232003, 0x82432003, 0x82442013, 0x824a2003, 0x825f200b, 0x82662007, 0x82692007, 0x826d2007, 0x82792007, + 0x827b2007, 0x827e2007, 0x82822007, 0x82842003, 0x0b8f560b, 0x13829320, 0x200b8756, 0x500f82aa, 0x01210647, 0x560b82ca, 0x5b560b63, 0xffee220b, + 0x0a8f44d7, 0x5802c326, 0x5902c3ff, 0x5f200382, 0x4f561782, 0x826c2007, 0x8272200b, 0x827e2013, 0x827f2007, 0x217b8207, 0x07828502, 0x0f828620, + 0x07828720, 0x07828820, 0x07828920, 0x20078f50, 0x200b828d, 0x201382b1, 0x200782b2, 0x200782b3, 0x200782b4, 0x200382d9, 0x200382da, 0x200382db, + 0x200382dc, 0x200382dd, 0x500382e0, 0xf0200bb3, 0xf1200f82, 0xf2202f82, 0xf3200782, 0xf4240782, 0x0a03c3ff, 0x0c200382, 0x15240382, 0x1603d7ff, + 0x19200782, 0x1a200782, 0x1d200782, 0x1e200382, 0x1f200382, 0x21200382, 0x22200382, 0x23200382, 0x24200382, 0x25200382, 0x26200382, 0x27200382, + 0x28200382, 0x29200382, 0x2a200382, 0x2b200382, 0x2c200382, 0x2d200382, 0x2e200382, 0x2f200382, 0x30200382, 0x31200382, 0x32200382, 0x33200382, + 0x34200382, 0x3f560382, 0x8249201f, 0x824a2083, 0x824b2027, 0x824c2007, 0x824d2007, 0x824e2007, 0x824f2007, 0x82502007, 0x82512007, 0x82522007, + 0x82532007, 0x82542007, 0x82552007, 0x82562007, 0x82572007, 0x82582007, 0x82592007, 0x825a2007, 0x825b2007, 0x825c2007, 0x825d2007, 0x825e2007, + 0x825f2007, 0x82602007, 0x82622007, 0x82642007, 0x82662003, 0x82682003, 0x826a2003, 0x826c2003, 0xff6e2a03, 0x00e900d7, 0x00660005, 0x2403820a, + 0x00aeff0f, 0x20038211, 0x4d158224, 0x44200fbf, 0x46201382, 0x47200382, 0x48200382, 0x4a240382, 0x5000ecff, 0x51200382, 0x52200382, 0x53200f82, + 0x54200782, 0x55200782, 0x56200782, 0x58200782, 0x5d200782, 0x91500382, 0x00ae2119, 0x201bdf4f, 0x204382a2, 0x200382a3, 0x200382a4, 0x200382a5, + 0x200382a6, 0x200382a7, 0x200382a8, 0x200382a9, 0x200382aa, 0x200382ab, 0x200382ac, 0x200382ad, 0x206b82b3, 0x200782b4, 0x200382b5, 0x200382b6, + 0x200382b7, 0x200382b8, 0x200382ba, 0x201b82bb, 0x200382bc, 0x200382bd, 0x200382be, 0x201382c2, 0x200382c3, 0x200382c4, 0x200382c5, 0x200382c6, + 0x200382c7, 0x201b82c8, 0x200782c9, 0x200382cb, 0x200382cd, 0x200f82ce, 0x200782cf, 0x200382d5, 0x200382d7, 0x200382d9, 0x200382db, 0x550382dd, + 0x06240f4d, 0x0801ecff, 0x0a200382, 0x24065955, 0x01d7ff0f, 0x20038211, 0x200f8212, 0x20078213, 0x20078214, 0x43078215, 0x40200fa1, 0x43201782, + 0x44201782, 0xa5430382, 0x01d72205, 0x20138266, 0x200f8269, 0x2007826d, 0x20078279, 0x2007827b, 0x2007827e, 0x20038282, 0x200b8284, 0x2007828c, + 0x2003828e, 0x20038290, 0x20038293, 0x20038296, 0x20038299, 0x06bd519b, 0x2106ef50, 0x0f82ca01, 0x0382cf20, 0x0382d820, 0x0382db20, 0x0382de20, + 0x0382ea20, 0x0382ed20, 0x2a05a543, 0x000b0266, 0xff280266, 0x825802d7, 0x82592003, 0xff5f2403, 0x826002ec, 0x826a2007, 0x826c2003, 0x8272200b, + 0x827e2007, 0x827f2007, 0x82842007, 0x82852007, 0x82862007, 0x82872007, 0x82882007, 0x82892007, 0x07cd5507, 0x0b828d20, 0x1382b120, 0x0782b220, + 0x0782b320, 0x0782b420, 0x0382d920, 0x0382da20, 0x02217f82, 0x200782dc, 0x200382dd, 0x510382e0, 0xf0200b5b, 0xf1200f82, 0xf2202f82, 0xf3200782, + 0xf4240782, 0x0a03d7ff, 0x0c200382, 0x15240382, 0x1603ecff, 0x19200782, 0x1a200782, 0x1d200782, 0x1e200382, 0x200a6d52, 0x200b8222, 0x20038223, + 0x20038224, 0x20038225, 0x20038226, 0x20038227, 0x20038228, 0x20038229, 0x2003822a, 0x2003822b, 0x2003822c, 0x2003822d, 0x2003822e, 0x2003822f, + 0x20038230, 0x20038231, 0x20038232, 0x20038233, 0x20038234, 0x20038236, 0x20038238, 0x2003823a, 0x2003823c, 0x2003823e, 0x20038240, 0x20038242, + 0x20038244, 0x20838249, 0x2007824a, 0x2007824b, 0x2007824c, 0x2007824d, 0x2007824e, 0x2007824f, 0x20078250, 0x20078251, 0x20078252, 0x20078253, + 0x20078254, 0x20078255, 0x20078256, 0x20078257, 0x20078258, 0x20078259, 0x2007825a, 0x2007825b, 0x2007825c, 0x2007825d, 0x2007825e, 0x2007825f, + 0x20078260, 0x20078262, 0x20038264, 0x20038266, 0x20038268, 0x2003826a, 0x2403826c, 0x00ecff6e, 0x082b568c, 0x200f3747, 0x201d8246, 0x20038247, + 0x20038248, 0x20038252, 0x46038254, 0xa8201bfb, 0xa9201f82, 0xaa200382, 0xab200382, 0xac200382, 0xad200382, 0xb4200382, 0xb5200382, 0xb6200382, + 0xb7200382, 0xb8200382, 0xba200382, 0xb7460382, 0x00ec2205, 0x200b82cb, 0x460382cd, 0xec2205b7, 0x0b82d500, 0x0382d720, 0x0382d920, 0x0382db20, + 0x0382dd20, 0x460fb746, 0xec2505ab, 0xecff1101, 0x05ab4601, 0xab46ec20, 0x01ec2106, 0x20079b56, 0x201b8279, 0x2003827e, 0x20038282, 0x2003828c, + 0x2003828e, 0x20038290, 0x20038293, 0x20038296, 0x20038299, 0x4603829b, 0xcf20077b, 0xd8200b82, 0xdb200382, 0xde200382, 0xea200382, 0xed220382, + 0xdb56ecff, 0x8260200c, 0x826a200f, 0x07e35603, 0x0b827f20, 0x21056346, 0x634602ec, 0x02ec2105, 0x21056346, 0x634602ec, 0x02ec2109, 0x21056346, + 0x634602ec, 0x02ec2205, 0x463782e0, 0xec260d4f, 0xd7fff102, 0x1782f202, 0x26054f46, 0xff0a03ec, 0x820c03ec, 0x054f4603, 0x4603ec21, 0xec22054f, + 0x13823603, 0x03823820, 0x03823a20, 0x03823c20, 0x03823e20, 0x03824020, 0x03824220, 0x03824420, 0x2105f345, 0xf34503ec, 0x03ec2105, 0x2105f345, + 0xf34503ec, 0x03ec2105, 0x2105f345, 0xf34503ec, 0x03ec2105, 0x2105f345, 0xf34503ec, 0x03ec2105, 0x2105f345, 0xf34503ec, 0x03ec2105, 0x2105f345, + 0xf34503ec, 0x01ec2205, 0x16794906, 0x79499a20, 0xff362810, 0xff4400ec, 0x8246009a, 0x82472003, 0x82482003, 0x05854e03, 0x5100c326, 0x5200c3ff, + 0x53200f82, 0x54200782, 0x55200782, 0x56240782, 0x5800aeff, 0x5b240782, 0x5c00d7ff, 0x7d4e3b82, 0x009a2205, 0x201f8283, 0x20038284, 0x20038285, + 0x20038286, 0x4e038287, 0xd721057d, 0x17c15800, 0x2382a220, 0x0382a320, 0x0382a420, 0x0382a520, 0x0382a620, 0x0382a720, 0x0382a820, 0x0382a920, + 0x0382aa20, 0x0382ab20, 0x0382ac20, 0x0382ad20, 0x7782b320, 0x0782b420, 0x0382b520, 0x0382b620, 0x0382b720, 0x0382b820, 0x0382ba20, 0x1b82bb20, + 0x0382bc20, 0x0382bd20, 0x0382be20, 0x9b82bf20, 0x0382c120, 0x1b82c220, 0x0382c320, 0x0382c420, 0x0382c520, 0x0382c620, 0x0382c720, 0x2205d942, + 0x82cb009a, 0x82cd200b, 0x05d94203, 0xd5009a22, 0xd7200b82, 0xd9200382, 0xdb200382, 0xdd200382, 0xd9420382, 0xff06240f, 0x820801c3, 0x820a2003, + 0x05e54203, 0x11019a24, 0xe5429aff, 0x429a2006, 0x9a2106e5, 0x057d4e01, 0x1f01ae25, 0x4e01aeff, 0xae21057d, 0x057d4e01, 0x3901ae25, 0x4e01ecff, + 0x9a220571, 0x3b824401, 0x23824a20, 0x07825f20, 0x2105a549, 0xa549019a, 0x019a2205, 0x2063827b, 0x2017827e, 0x202f8280, 0x20078282, 0x200f8284, + 0x200b828a, 0x200b828c, 0x2003828e, 0x20038290, 0x20038293, 0x20038296, 0x20038299, 0x4e03829b, 0x9a210565, 0x09b14901, 0xcf019a22, 0xd8201782, + 0xdb200382, 0xdd200382, 0xde203f82, 0xea200782, 0xed200382, 0xee260382, 0x0102aeff, 0xb949ecff, 0x029a260a, 0x029aff58, 0x49038259, 0x9a2205b9, + 0x0b826a02, 0xd7ff6c24, 0x27826d02, 0x0b827220, 0x2205bd49, 0x8281029a, 0x4383200f, 0x9a200861, 0x20066143, 0x0661439a, 0x8a029a22, 0x8b203382, + 0x8c201f82, 0x8d200782, 0x65433782, 0x439a2005, 0x9a220665, 0x1b82b802, 0x0382ba20, 0x1b82d920, 0x0382da20, 0x02219f82, 0x200782dc, 0x200382dd, + 0x430382e0, 0x9a200d81, 0x21068143, 0x8143029a, 0x029a2205, 0x203b82f8, 0x280382fa, 0x03ecfffc, 0x039aff0a, 0x2003820c, 0x200b820e, 0x08954310, + 0x95439a20, 0x039a2206, 0x201b821d, 0x2003821e, 0x2003821f, 0x20038221, 0x20038222, 0x20038223, 0x20038224, 0x20038225, 0x20038226, 0x20038227, + 0x20038228, 0x20038229, 0x2003822a, 0x2003822b, 0x2003822c, 0x2003822d, 0x2003822e, 0x2003822f, 0x20038230, 0x20038231, 0x20038232, 0x20038233, + 0x20038234, 0x20038236, 0x20038238, 0x2003823a, 0x2003823c, 0x2003823e, 0x20038240, 0x20038242, 0x43038244, 0x9a2005f1, 0x2006f143, 0x06f1439a, + 0xf1439a20, 0x439a2006, 0x9a2006f1, 0x2006f143, 0x06f1439a, 0xf1439a20, 0x439a2006, 0x9a2006f1, 0x2006f143, 0x06f1439a, 0xf1439a20, 0x039a2606, + 0x03c3ff62, 0x20038264, 0x20038266, 0x20038268, 0x2003826a, 0x2003826c, 0x2403826e, 0x03ecff70, 0x22038272, 0x58ecff74, 0x6f5e0c8b, 0x1b91490d, + 0x48217159, 0x6d2305b9, 0x5901ecff, 0x01268371, 0xd7ff0a00, 0x435b0400, 0x5a022007, 0x002106c3, 0x08ef4a26, 0x14005923, 0x05896400, 0xbf001422, + 0xc1240b82, 0x37011400, 0x39200382, 0x80200382, 0x8a200382, 0x91200382, 0x94200382, 0xdc200382, 0xdd200382, 0xfb200382, 0xfd200382, 0xff240382, + 0x01021400, 0x07210382, 0x05434900, 0x0b826d20, 0x03828120, 0x03828320, 0x03828b20, 0x0382aa20, 0x0382b620, 0x0382b820, 0x0382ba20, 0x0382f820, + 0x0382fa20, 0x1400fc24, 0x03820e03, 0x03821020, 0x03821820, 0x03827020, 0x03827220, 0x7f827420, 0xe3470520, 0x844a2008, 0x02292559, 0x0029000b, + 0xc320c783, 0x2924c784, 0x29000a00, 0x2307e746, 0x5b000300, 0x5d28df82, 0x4001ecff, 0x1f00ecff, 0x4420d588, 0x4a200d82, 0xa2200382, 0xa3200382, + 0xa4200382, 0xa5200382, 0xa6200382, 0xa7200382, 0xc3200382, 0xc5200382, 0xc7200382, 0x2b823982, 0xffca0123, 0x855382ec, 0x825920c5, 0x82da200b, + 0xffdc2403, 0x821e03ec, 0x82222003, 0x82242003, 0x82262003, 0x82282003, 0x822a2003, 0x822c2003, 0x822e2003, 0x82302003, 0x82322003, 0x82342003, + 0x20b9834b, 0x229d8252, 0x84570052, 0x825220b9, 0x825220b9, 0x070f5591, 0x158a4920, 0xe5883620, 0xbf825220, 0x0382a820, 0x2016b74b, 0x07434b01, + 0xd7ff1324, 0x03821501, 0x201bf74a, 0x05df4ad8, 0x4a080548, 0x7f2407c3, 0x8502d7ff, 0x87200382, 0x89200382, 0x8d200382, 0xb2200382, 0xb4200382, + 0x2006874a, 0x200782f0, 0x4a0382f2, 0x16240b73, 0x1a03d7ff, 0x4a200382, 0x4c200382, 0x4e200382, 0x50200382, 0xaf820382, 0x82540321, 0x82562007, + 0x82582003, 0x825a2003, 0x825c2003, 0x825e2003, 0x82602003, 0x5d0520c7, 0xef8508af, 0x0b023d2c, 0x32003d00, 0xecff5200, 0x0382a800, 0x82166149, + 0x01ec26e7, 0x01ecff11, 0x20038213, 0x1e054915, 0x1f82d820, 0xecffde23, 0x07e14802, 0x0b827f20, 0x03828520, 0x03828720, 0x03828920, 0x03828d20, + 0x0382b220, 0x0382b420, 0x0382e020, 0x0382f020, 0x0382f220, 0x48fff421, 0x162009a9, 0x1a200b82, 0x4a200382, 0x4c200382, 0x4e200382, 0x50200382, + 0xa7820382, 0xec22df82, 0x0b825603, 0x03825820, 0x03825a20, 0x03825c20, 0x03825e20, 0xbf826020, 0x71010326, 0x7801d7ff, 0x91230382, 0x83002900, + 0x019a240d, 0x82c3ff72, 0x00c32211, 0x08c36294, 0x85ff0d28, 0x44000f00, 0x03821e00, 0xc3ff2224, 0x39822600, 0x03822a20, 0x5e002d23, 0x1bd76200, + 0x3b003d24, 0x27824900, 0x03825720, 0xd7ff5924, 0x07825a00, 0x07825c20, 0x03828220, 0x5c1b9744, 0xbf201329, 0xc1203382, 0x5e06d14d, 0x00231225, + 0x625e00f6, 0x372828ff, 0x3801ecff, 0x39019aff, 0x3a20f782, 0x3b230782, 0x82013b00, 0x3f0121ab, 0x66200782, 0x2406615e, 0x0185ff71, 0x201f8280, + 0x2003828a, 0x20038291, 0x20038294, 0x636382a3, 0xdc200b27, 0xdd201382, 0xfa200382, 0xfb200382, 0xfc203782, 0xfd200782, 0xfe200782, 0xff2b0782, + 0x0002ecff, 0x01029aff, 0x6302d7ff, 0x6d20133f, 0x2006854d, 0x20078281, 0x63038283, 0x8b200f4b, 0x4f631382, 0x82aa2007, 0x0b53630b, 0x0f82b620, + 0x85ffb724, 0x0782b802, 0x0782b920, 0x0782ba20, 0x21165f63, 0x1b82f802, 0x0382fa20, 0xd7fffc24, 0x03820e03, 0x03821020, 0xecff1528, 0x85ff1703, + 0x854d1803, 0x4f776306, 0x57827020, 0x9aff7124, 0x07827203, 0x07827320, 0x07827420, 0x85ff8324, 0x51429100, 0x334d4220, 0x104e4942, 0xa0014502, + 0x45429220, 0x447f200a, 0xd7200a97, 0x282c9744, 0x00e5ff57, 0x00d5ff59, 0x2207825a, 0x52dbff5c, 0x8f441cb9, 0x00db2215, 0x493782c1, 0x8f441643, + 0x44e5202e, 0xdb21068f, 0x1d8f4401, 0x8a01db26, 0x9101d5ff, 0x94200382, 0x8f440382, 0x01d52511, 0x01dbffdd, 0x21058f44, 0x8f4401e5, 0x01e52105, + 0x20058f44, 0x068f44e5, 0x8f44db20, 0x02db2a16, 0x02ecff7e, 0x02dbff81, 0x44038283, 0xdb21118f, 0x098f4402, 0xe367d520, 0xffb6230c, 0x8f4402d5, + 0x02db2105, 0x21058f44, 0x8f4402db, 0x02db2219, 0x245f82fa, 0x03dbfffc, 0x2003820e, 0x44038210, 0xd520098f, 0x20540768, 0x44638270, 0xdb21058f, + 0x058f4403, 0x8303db2c, 0x950085ff, 0x66ff0500, 0x03820a00, 0x10ff0d21, 0x35014902, 0x66ff0628, 0xaeff0702, 0x07820a02, 0x07820b20, 0x5b632020, + 0xff6d210e, 0x66f15542, 0x10200917, 0x46067557, 0x842407d5, 0x8900ecff, 0x8a200382, 0x6b06f168, 0x534417f3, 0x00f62207, 0x088d463d, 0x20079748, + 0x4d1382a3, 0x3720838b, 0x8f08f34b, 0x20e183e5, 0x22e7678b, 0x229bdd40, 0x5d240020, 0x655d1a69, 0x00572463, 0x6bd7ff0c, 0x2d24105f, 0x3600f6ff, + 0x37249982, 0x3900c3ff, 0xf1651f82, 0x8240200f, 0x82602013, 0x196f6b03, 0x292cf965, 0xf6fff600, 0xecff1c01, 0x03822001, 0x7f6b2220, 0x82a02032, + 0x82a32033, 0x8f876b43, 0x515f4220, 0xff30240c, 0x823d00ec, 0x41442003, 0x88231af3, 0x4f00d7ff, 0xc220177f, 0x2006834f, 0x06874fc4, 0x8b4fc620, + 0x0f996c06, 0x01205f82, 0x24079d6c, 0x01ecffaa, 0x0a955fca, 0x0b825920, 0x03827220, 0x0382d920, 0x0382da20, 0x0382db20, 0x0382dc20, 0xecffdd24, + 0xbb4f1d03, 0x821f2006, 0x82212007, 0x82222003, 0x82232003, 0x82242003, 0x4f252003, 0x272006cb, 0x28200782, 0x29200382, 0x2006d34f, 0x06d74f2b, + 0xdb4f2d20, 0x4f2f2006, 0x312006df, 0x32200782, 0x2006a56c, 0x2a838234, 0x0005002f, 0xff090052, 0x820a00c3, 0x000c2507, 0x000d003d, 0x6405996c, + 0x63560ded, 0xff2d2409, 0x823000be, 0xff32242f, 0x823400d7, 0x82362003, 0x003724ed, 0x82390027, 0x003a2437, 0x82400014, 0x0f7b5643, 0xe5ff4923, + 0x237f5600, 0x5607254e, 0x60200b87, 0x82214f82, 0xec8b56ff, 0xfff60024, 0x8f5601be, 0x00242443, 0x82260127, 0x00362603, 0xff370114, 0x249f56ec, + 0x2f827120, 0x56ff7921, 0xd72117a3, 0x0ba35601, 0xd7ff9124, 0x2b829301, 0x07829420, 0x200fab56, 0x20c382a3, 0x561b82aa, 0xbc2007af, 0xca205782, + 0xb3560f82, 0x05414f0b, 0x5601ec21, 0x01210eb7, 0x20af82fa, 0x20af82fb, 0x200782fc, 0x200782fd, 0x220782fe, 0x56ecffff, 0xa92368cf, 0x4f022700, + 0xd7230575, 0x56ffb202, 0xb52009d7, 0xb6241782, 0xb702d7ff, 0xb8200782, 0xb9208f82, 0xba200782, 0xbd200782, 0xeb560782, 0x0017225b, 0x06ad4f27, + 0x1a03d723, 0xf31610ff, 0x032f0401, 0x00270083, 0xff050002, 0xff0a0098, 0x870300d7, 0x0b022109, 0x06200d82, 0x6f200d82, 0x6f241782, 0xdbff4900, + 0x830c5555, 0x82be2031, 0x00be2219, 0x08db5361, 0xbeff0f24, 0x03821100, 0xb4ff2228, 0xf6ff4600, 0x03824700, 0x03824820, 0x14004924, 0x07824a00, + 0x03825220, 0x03825420, 0x06005724, 0x0782a800, 0x0382a920, 0x0382aa20, 0x0382ab20, 0x0382ac20, 0x0382ad20, 0x0382b420, 0x0382b520, 0x0382b620, + 0x0382b720, 0x0382b820, 0x0382ba20, 0x0382c920, 0x0382cb20, 0x0382cd20, 0x0382cf20, 0x0382d520, 0x0382d720, 0x0382d920, 0x0382db20, 0xf6ffdd24, + 0x03820f01, 0x03821120, 0x03821320, 0x03821520, 0x03827920, 0x03827e20, 0x03828220, 0x03828c20, 0x03828e20, 0x03829020, 0x03829320, 0x03829620, + 0x03829920, 0x03829b20, 0x01214f82, 0x200782d8, 0x200382db, 0x200382de, 0x2c0382ea, 0x02f6ffed, 0x023d0007, 0x028dff08, 0x2007820b, 0x2807820c, + 0x0281ff10, 0x020c0015, 0x201b8260, 0x2003826a, 0x2003827f, 0x20038285, 0x20038287, 0x20038289, 0x2003828d, 0x200382b2, 0x200382b4, 0x200382e0, + 0x200382f0, 0x240382f2, 0x03f6fff4, 0x2003820a, 0x2003820c, 0x20038216, 0x2003821a, 0x20038236, 0x20038238, 0x2003823a, 0x2003823c, 0x2003823e, + 0x20038240, 0x20038242, 0x20038244, 0x2003824a, 0x2003824c, 0x2003824e, 0x20038250, 0x20038252, 0x20038254, 0x20038256, 0x20038258, 0x2003825a, + 0x2003825c, 0x2003825e, 0x20ff8260, 0x10854107, 0x200b6955, 0x08eb4f65, 0x20097354, 0x1c7354e1, 0x4f2f0d52, 0x055216bf, 0xf34b7728, 0x28099958, + 0x008f000c, 0x00a40022, 0x24038240, 0x00520045, 0x2403824b, 0x003d004c, 0x2003824d, 0x200b824e, 0x2c03824f, 0x00b80060, 0x00f600ae, 0x00cd00b0, + 0x200382b1, 0x201382e7, 0x242f82e9, 0x000a01eb, 0x200f82ed, 0x241b82ef, 0x002900f1, 0x243382f5, 0x00e100f7, 0x201f82f9, 0x240382fc, 0x015200fe, + 0x20038200, 0x28038202, 0x02520004, 0x028f0007, 0x266f820b, 0x002d0001, 0x4c3a0066, 0x1942087f, 0x42522009, 0x05420819, 0x21f1411b, 0x208d6774, + 0x22e98843, 0x4b140030, 0xd72006fd, 0x710a6577, 0x592405ef, 0x5c00ecff, 0x9f240382, 0xbf00d7ff, 0x4b05255f, 0x23280cb9, 0x2401ecff, 0x2601d7ff, + 0x36200382, 0x38200b82, 0x39200782, 0x3a200782, 0x71200782, 0x80200382, 0x8a200b82, 0x91200382, 0x94200382, 0xa0200382, 0xbc200382, 0xdc201782, + 0xdd200782, 0x41770382, 0x05595e0f, 0x0b022928, 0x6d022900, 0x315eecff, 0x828b2008, 0xffa9240b, 0x82aa02d7, 0x82b52007, 0x82b62007, 0x82b72007, + 0x82b82007, 0x82b92007, 0x82ba2007, 0x82bd2007, 0x0be15d07, 0x2807d95d, 0x03d7ff17, 0x03ecff18, 0x2007826f, 0x20078270, 0x20078271, 0x20078272, + 0x20078273, 0x20078274, 0x208f8283, 0x1603611e, 0x028d2f10, 0x852f1055, 0x01200a02, 0x4f057944, 0x5c201529, 0x4f0ac77b, 0xec210f29, 0x0f294f00, + 0x103b214f, 0x4f01190f, 0x4f23b165, 0xec201d11, 0x650c114f, 0x094f13b5, 0x1fbd6523, 0xd7ff0f25, 0x65ff2802, 0xa92259c1, 0x2b692700, 0x0ded4e06, + 0x2173e94e, 0x0e10ff19, 0x200d01e5, 0x08014ac5, 0x7d611020, 0x0755580a, 0xd7ff3627, 0xecff3800, 0x13356c00, 0x22054f53, 0x615c00d7, 0x516c2e71, + 0x0b9d612f, 0x8b82c920, 0x2209596c, 0x82cf00ec, 0x15596c0f, 0x1800ec21, 0x240fbd44, 0x01ecff0f, 0x20038211, 0x063b6312, 0x26050573, 0xff1c01ec, + 0x822001d7, 0x82222003, 0xd1441803, 0x8237200f, 0x82392013, 0x07215903, 0x20077d6c, 0x20138280, 0x20478282, 0x6c07828a, 0xb3520b85, 0x01ec2105, + 0x2105b352, 0x8d6c01ec, 0x82a02007, 0x82b82027, 0x82bb202f, 0x0b916c03, 0x2105a352, 0x996c01d7, 0xfb01210a, 0xfd202b82, 0xff220382, 0xe161d7ff, + 0x85431805, 0x05c76308, 0xad6c6120, 0x02ec2108, 0x2007e961, 0x6113827f, 0x85200bed, 0x776f0f82, 0x02ec2105, 0x2205776f, 0x828a02ec, 0x07f96113, + 0x0b828d20, 0x22058352, 0x82b202ec, 0x057f6f0b, 0xb602ec22, 0xb8207382, 0xba200382, 0xcd6c0382, 0x02ec2105, 0x07554518, 0x2782f020, 0x2105776f, + 0x776f02ec, 0x62ec2005, 0x0a240c01, 0x0c03ecff, 0x09620382, 0x8216200b, 0x0709620f, 0x0b821a20, 0x2221e56c, 0x824a03ec, 0x05336f27, 0x6f03ec21, + 0xec220533, 0x73644f03, 0x05336f06, 0x6f03ec21, 0xec210533, 0x05336f03, 0x6f03ec21, 0xec220533, 0x27825903, 0x03825a20, 0x2105336f, 0x336f03ec, + 0x03ec2105, 0x2105336f, 0x451803ec, 0x70241bd5, 0x7203d7ff, 0x74240382, 0x3300d7ff, 0x22548565, 0x6514000b, 0x0b247489, 0x29006201, 0x82052772, + 0xff6d3007, 0xff7101ec, 0xff720185, 0xff73019a, 0x827501d7, 0x82782003, 0x8288200b, 0xff91241b, 0x180300c3, 0x26080943, 0x00ecff73, 0x825f010b, + 0x8264202f, 0x82672003, 0x826c2003, 0x84702003, 0x82c3203f, 0x01d7223f, 0x203b8274, 0x200f8277, 0x20078278, 0x222d8288, 0x82100024, 0xff6d2241, + 0x223582c3, 0x7662019a, 0x73200a43, 0x76202182, 0x79200382, 0x7a206982, 0x20060156, 0x201f827d, 0x240b827e, 0x01aeff81, 0x20078282, 0x201f8283, + 0x20138284, 0x20078285, 0x20078286, 0x20038287, 0x20038289, 0x06b96c8c, 0x07828f20, 0x03829020, 0x13829220, 0x33829320, 0x27829420, 0x0b829520, + 0x0b829620, 0x0b829820, 0x1b829920, 0x0f829a20, 0xaeff9b28, 0xc3ff0202, 0xcd840302, 0x11827120, 0x03827220, 0x0d827820, 0x79011922, 0x7d202782, + 0x7e200382, 0x80200382, 0x81200382, 0x83200382, 0x7385c182, 0x8801d726, 0x8a012900, 0x8b201382, 0x8c201382, 0x8d200782, 0x8f200782, 0x90200382, + 0x91200b82, 0x92200782, 0x93200782, 0x94200382, 0x95200b82, 0x96200782, 0x7b850782, 0x9a01d722, 0x9b240f82, 0x5000d7ff, 0x64105952, 0x4f501b7b, + 0x131d621b, 0x20216350, 0xd74218d7, 0x18d7201a, 0x4214d742, 0xc329090b, 0x9aff7801, 0xc3ff9101, 0xa9491801, 0x6503201e, 0x71204fd9, 0x08414b18, + 0x18008523, 0x4d491800, 0x05914223, 0x4201d721, 0xec260591, 0xecff7201, 0x03827401, 0x20059142, 0x29c582ec, 0xff9401ec, 0xff0002ec, 0x401803ec, + 0x03250add, 0x00ecff83, 0x7b441872, 0x0b7d7f08, 0x180fc776, 0x25138744, 0x009aff6d, 0x8f76ff7d, 0x35b7411d, 0x258f4418, 0x85ff5f28, 0x9aff6201, + 0xe9826601, 0x07826920, 0x07826d20, 0xaeff7323, 0x055d4301, 0x7a018522, 0x200e717e, 0x7e238281, 0xc3210575, 0x0b554301, 0xc3ff8a24, 0x2b828c01, + 0x07828d20, 0x23828e20, 0x897e8f20, 0x0561430a, 0x94018522, 0x61431b82, 0x019a2605, 0x01290097, 0x200f8298, 0x43278299, 0x9a220565, 0x0f82fa01, + 0x0b034518, 0x9aff0224, 0x03820302, 0x03820720, 0x0a0b4518, 0x205c2b42, 0x16b551b2, 0x01333c10, 0x00622271, 0x08a77514, 0x6bff7121, 0x614605ed, + 0x01c32a09, 0x01c3ff79, 0x01290088, 0x1df37b8d, 0x5b7b0320, 0x470820f7, 0x01250b79, 0x01d7ff92, 0x43038295, 0xd7260577, 0xd7ff9a01, 0xb5614700, + 0x17ad6110, 0x1846a561, 0x2028154d, 0x24a98262, 0x01ecff67, 0x16254869, 0x1f827820, 0x240fe755, 0x02ecff28, 0x06836058, 0x43014d18, 0x3f410520, + 0x8281200c, 0x00882489, 0x792a0029, 0xf778180b, 0x2b4f181b, 0x4b4b181f, 0xff73240b, 0x419101ae, 0x517005a9, 0xff5f2308, 0x4e1803d7, 0xd0202ff3, + 0x20083748, 0x20b78222, 0x128f4d24, 0x13e15118, 0x51094118, 0x2d674b18, 0x751d4118, 0x1800ec21, 0x210d1d41, 0x411800ec, 0x0b4e191d, 0x1d41180d, + 0x01ec210d, 0x091d4118, 0x1801ec21, 0x181b1d41, 0x49192b4c, 0x41180953, 0xed6f0b41, 0x115f490b, 0x5f49d720, 0xff282118, 0x0b054118, 0x6002ec22, + 0x61220f82, 0x1545ecff, 0x03ec257e, 0x03c3ff4a, 0x2005974d, 0x06974dc3, 0x974dc320, 0x03c32106, 0x2005974d, 0x06974dc3, 0x974dc320, 0x4dc32006, + 0xc3200697, 0x2106974d, 0x974d03c3, 0x4dc32005, 0xc3200697, 0x2106974d, 0xdf8303c3, 0xd7ff6224, 0xe7826303, 0x07826420, 0x07826520, 0x07826620, + 0x07826720, 0x07826820, 0x07826920, 0x07826a20, 0x07826b20, 0x07826c20, 0x07826d20, 0x55186e20, 0x85201079, 0x220abb4c, 0x45290088, 0x29459a2d, + 0x05bd4a1b, 0x4501d721, 0x36205f2d, 0x70b94c18, 0xaeff6228, 0xecff6401, 0x07826901, 0x07827420, 0x03827820, 0xd7ff8124, 0x03828801, 0xd7ff8e22, + 0x0bcd4c18, 0x3cbd4c18, 0xf1452920, 0x77b58262, 0x0220095d, 0x2033ed45, 0x0cb74aea, 0x5c0d1167, 0xc54c6171, 0x00d72105, 0x01074c10, 0x05a14d57, + 0x1801c321, 0x240b0b4c, 0x01c3ff73, 0x21038276, 0xa54dff79, 0x187d2009, 0x510a1b4c, 0x85220507, 0x13828401, 0x03828620, 0x03828720, 0x14008824, + 0x4c188901, 0xa94d0e2f, 0x01ae210d, 0x07374c18, 0x27829520, 0x5b829620, 0x3d009724, 0x0b829801, 0x2205a94d, 0x189b01ae, 0x4d140b4c, 0x4c1806a9, + 0x0320190b, 0x01234b10, 0x002d2107, 0x25052350, 0xff1100c3, 0xdd52009a, 0x019a2511, 0x01d7ff6d, 0x2105dd41, 0xe15201d7, 0x01ae2905, 0x01c3ff7b, + 0x01ecff7c, 0x22056d52, 0x827f019a, 0x058b4f23, 0x5201ae21, 0xe94113e9, 0x01c32105, 0x21057952, 0x934f019a, 0x019a2505, 0x019aff90, 0x20057952, + 0x080f69c3, 0x2005934f, 0x0a934fae, 0x52019a21, 0x0a250ff9, 0xd7ff5f01, 0x09974b01, 0x5301d721, 0x74200709, 0x77209982, 0x78201b82, 0x88240782, + 0x1700d7ff, 0x8308b54d, 0x827920c3, 0x22b785b3, 0x827e01ec, 0x8281200b, 0x82852003, 0x82862003, 0x20a38303, 0x0811538c, 0x9782ec20, 0x5301d721, + 0xec210511, 0x0d0d5301, 0x0d53ec20, 0x00ec2a06, 0xff0f000c, 0xff1100ae, 0x208f82ae, 0x208f84c3, 0x20778269, 0x95461881, 0x82ec2008, 0x01ec21d5, + 0x0abb4318, 0x86030021, 0x01d722a9, 0x209d8278, 0x108d632c, 0x53074d53, 0x25531b39, 0x09896321, 0x8b827320, 0xe9868020, 0x9120e183, 0x0c1f4418, + 0xbd50ec20, 0xef00212f, 0x5d1af76c, 0x6d2779cd, 0x7d00c3ff, 0x1000d7ff, 0x3f01ef2c, 0x5617d55d, 0x0f4409ed, 0x01c3231f, 0x0f44ff7e, 0x05754205, + 0xfd569a20, 0x0da3530c, 0x0f44ec20, 0xff8d2208, 0x0e1344d7, 0x5301d721, 0x9a2105a7, 0x09095701, 0x440ba753, 0x9a200713, 0x5d0cdb6c, 0x421016ed, + 0x2f0301eb, 0x27008303, 0x88010100, 0x06002900, 0xd7ff7901, 0x2408ff44, 0x01ecff8c, 0x24038290, 0x00ecff93, 0x20198214, 0x06d945ec, 0x4101ec21, + 0xec2105c1, 0x09214501, 0x83053f58, 0x093b5831, 0x22072945, 0x829501ec, 0x82972045, 0x82982003, 0x82992003, 0x829a2003, 0x01012651, 0x00ecff94, + 0x08ad6a0b, 0x63824920, 0x1b828120, 0x29008d24, 0x07828e01, 0x0f829120, 0x03829420, 0x5d189620, 0x0022095b, 0x4d670102, 0x89d72005, 0x83b18437, + 0x828c2037, 0x07b358b9, 0x0b829320, 0xd7ff9922, 0x08cf4218, 0x25821c20, 0x7a01ae22, 0x20080559, 0x26c182c3, 0xff8101d7, 0x828201c3, 0x05974613, + 0xcd82d720, 0x8601d722, 0x87200f82, 0x11597d82, 0x01d72209, 0x2027828c, 0x2003828d, 0x2003828f, 0x20038290, 0x42038291, 0xc3200583, 0xc322d982, + 0x0f829601, 0x03829820, 0x03829920, 0x22058f46, 0x821000c3, 0x005224d7, 0x8452000a, 0x827d209f, 0x827e2051, 0x82802003, 0x0573595d, 0x7359ec20, + 0x828d2008, 0x82912013, 0x20b38303, 0x5d461897, 0x09002109, 0x84070146, 0x827e2041, 0x82812021, 0x82822003, 0x458c2045, 0x002109a9, 0x0c3f410d, + 0x80206783, 0x63832182, 0x3d008824, 0x31828a01, 0xc3225f85, 0x0f419401, 0x09236c0a, 0x14004924, 0x03828d01, 0x53848e20, 0x0b023d28, 0x03003d00, + 0x3b821e00, 0x05417e20, 0x185f8205, 0x410a4343, 0x0421087f, 0x82cf8401, 0x008a2839, 0x00910129, 0x6e070014, 0x01200b15, 0x071b4418, 0x91245b83, + 0x0e002900, 0x8208f74b, 0x7d002171, 0x21833382, 0x63828120, 0x8c203f83, 0x4b82a783, 0x07828f20, 0xfb419020, 0x65471805, 0x04002107, 0x9424578c, + 0x1500ecff, 0x01214b8b, 0x20338279, 0x2003827a, 0x8503827e, 0x01d72253, 0x200b8282, 0x42478285, 0xd7220513, 0x0f829001, 0xc9429220, 0x94012105, + 0xb5477b82, 0x01d72205, 0x0a6f4199, 0x4982678d, 0x82130021, 0x01ec215b, 0x2005bb41, 0x063142d7, 0x4101ec21, 0x2922055b, 0x4f828c01, 0x73428d20, + 0x09eb4208, 0x4207235b, 0x01210aeb, 0x20b5829b, 0x10df7738, 0x3d002d22, 0x78085f6b, 0x635f3bc9, 0x47be2007, 0x5f180dc1, 0x3d2e70bf, 0xc3ff0500, + 0xc3ff0a00, 0x85ff9d01, 0x0382a601, 0xd7ffb024, 0x0782bc01, 0x0782bd20, 0xecffbf24, 0x1b82c101, 0x5718c420, 0xec2208bb, 0x1382df01, 0x1382e120, + 0xaeffe428, 0xc3ff0702, 0x03820b02, 0xc5826d20, 0xd7ff7624, 0x0b827c02, 0x03827d20, 0x03828020, 0x13828120, 0x07828220, 0x07828320, 0x03828b20, + 0x1f829f20, 0x85ffa924, 0x1382aa02, 0x0782b520, 0x0782b620, 0x0782b720, 0x2205136b, 0x82ba0285, 0x82bb2023, 0x82bd2023, 0x82bf2013, 0x82c0201b, + 0x82c12003, 0x82c22003, 0x82ca2003, 0x82d42017, 0x82d52007, 0x82e52003, 0x82f7200b, 0x82f82003, 0x82f9202f, 0x82fa2007, 0x82fb2007, 0x82fc2007, + 0x82fd2007, 0xfffe281f, 0xff0503c3, 0x820703d7, 0x820d2003, 0xff0e240b, 0x820f03ec, 0x18102007, 0x2208ef41, 0x42d500c3, 0x1022088d, 0x317f5cff, + 0x11fb5c08, 0x81d35f18, 0xecff9f2c, 0x9affa401, 0x85ffaa01, 0x0382ae01, 0x0382b520, 0x26054b74, 0xffbe01ec, 0x82ca01c3, 0xffcb240f, 0x82cc01d7, + 0x82cd200b, 0xffce2403, 0x82cf015c, 0x82d02013, 0x82d1200b, 0x82d22003, 0x82d32003, 0x82d42003, 0x82d52003, 0x82d6201b, 0x82d72007, 0x82d82003, + 0x82d92023, 0x82da2007, 0x99591803, 0x82df200f, 0x82e02013, 0x82e12003, 0x82e22003, 0x82e32003, 0x82e42003, 0x82e52003, 0x82e62003, 0x82e72003, + 0x82e82003, 0x82e92003, 0x82ea2097, 0x82ec2047, 0x82ed200b, 0xffee2807, 0x00f001ae, 0x82f2013d, 0x82f32067, 0x82f52013, 0x82f72003, 0x82f92003, + 0x0f7f5b03, 0xcd4d0720, 0xff5f2306, 0x276202ec, 0x02852905, 0x02c3ff6b, 0x02d7ff6c, 0x07d15918, 0x55187d20, 0x85210849, 0xd5591802, 0x02d72609, + 0x0285ff85, 0x20278286, 0x20078287, 0x20078288, 0x20078289, 0x2007828a, 0x202f828b, 0x2007828c, 0x200f828d, 0x200b8296, 0x2003829a, 0x200382a0, + 0x200382a4, 0x200382a6, 0x200382aa, 0x200382ac, 0x200382ae, 0x200382b0, 0x202b82b1, 0x202b82b2, 0x200782b3, 0x069142b4, 0xc3ffb824, 0x0382ba02, + 0x8142bc20, 0x82c22006, 0x82c42007, 0xffc52803, 0xffc602ae, 0x82c70271, 0x82cb2007, 0x82ce200f, 0xffcf242f, 0x82d1025c, 0x42d3200b, 0xd7200699, + 0xd9200782, 0x18195a18, 0xe302d722, 0xe6206782, 0xec202382, 0xee200382, 0xef200382, 0xf0200f82, 0xf1202f82, 0xf2200782, 0xf3200782, 0x5a180782, + 0x02250e25, 0x03c3fffe, 0x20038200, 0x20038206, 0x28038208, 0x035cff09, 0x0385ff0a, 0x1807820b, 0x200b3d5a, 0x20138211, 0x20138212, 0x01561814, + 0x03852208, 0x660b8218, 0x85220545, 0x1f821b03, 0x1f821c20, 0x205b0b5f, 0x08fd461f, 0x45649f20, 0x01d72608, 0x01ecffbe, 0x200f82de, 0x20dd82e1, + 0x06216407, 0xecff6c24, 0x0f827d02, 0x173f6918, 0x07e74518, 0x2382c020, 0x0382c220, 0x5318d520, 0xf1200e59, 0xf3203f82, 0xfe2e0382, 0x1503d7ff, + 0x1903ecff, 0x0500ecff, 0x6982a001, 0x2982dc20, 0x0382aa20, 0x1982b620, 0xd7ff1826, 0x9f011a00, 0x01211585, 0x820782dd, 0xe4012183, 0x6d203782, + 0x4d187f86, 0x8b2007e1, 0x64066564, 0xec220555, 0x0f82ba02, 0xc5207b87, 0xc7204d82, 0xaf6f8386, 0x8302200a, 0x07b36f7b, 0x0b7e6983, 0x0f9b5f09, + 0x833ffd4d, 0x062f46c1, 0x000b0225, 0x185f0229, 0x411e7d6a, 0x5418073d, 0x31410b8b, 0x072d4106, 0x2030294e, 0x07856034, 0xffa60129, 0xffa80185, + 0x82b001d7, 0xffb52203, 0x062b46ec, 0x4601ec21, 0xae21052b, 0x052b4601, 0x4101d721, 0xc321056b, 0x07615f02, 0x2a051f46, 0xff7d02ae, 0xff8002d7, + 0x828202ae, 0x09134603, 0x4602d721, 0xd7260513, 0x85ffb702, 0x0382b902, 0x22090b46, 0x82c002ae, 0x82c12033, 0x82c2202f, 0x82ca2007, 0xffce2403, + 0x82d402ec, 0x82d5200f, 0x050f460b, 0xf902ec22, 0xfb201382, 0xfd200382, 0xfe221782, 0x0346d7ff, 0x03ae260a, 0x03aeff0f, 0x08ff4511, 0x1b03d726, + 0x3100ecff, 0xf946d188, 0x87d58507, 0x01d721d1, 0xcd887182, 0x2205f546, 0x82e401ec, 0x22d18971, 0x827c02ec, 0x827d206d, 0x21d18975, 0xe54602ec, + 0x21d19305, 0xdd4602ec, 0x82ae2005, 0x02ec21d1, 0xec22d185, 0xcd88ca02, 0xe502ec22, 0xf7200b82, 0xf9206382, 0xfb200382, 0xcd850382, 0xcd82ec20, + 0x0703ec22, 0x0d20c182, 0xcd83c982, 0x85ff172e, 0xd7ff1803, 0x9d011d00, 0xa6019aff, 0x77410382, 0x09e74207, 0xf601c322, 0x2056eb42, 0x58b7566d, + 0xd7ff9f28, 0x2900a401, 0x0382b501, 0x2d05e746, 0xffbe01d7, 0xffcb01ae, 0x00ce01ec, 0x57180114, 0x93680bf7, 0x01d72109, 0x22059148, 0x82ea01d7, + 0x44ed203f, 0x5f200a69, 0x08f35718, 0x6d02d722, 0x53460b82, 0x02d72109, 0x22098768, 0x828502d7, 0x0553461b, 0x4602d721, 0xd7220553, 0x13828a02, + 0x22058768, 0x448d02d7, 0x33460657, 0x02d72105, 0x20053346, 0x0c8768d7, 0xad48c020, 0x00ce2406, 0x82d50229, 0x18e0200b, 0x200e696c, 0x450f82f0, + 0xd72105eb, 0x05eb4502, 0x9768d720, 0xfe02230b, 0x5818c3ff, 0x0e24081f, 0x1003d7ff, 0x11240382, 0x15032900, 0x16200782, 0x2005cf44, 0x05cf4503, + 0x1b03d722, 0xb55d1782, 0x4c67202f, 0x514808df, 0x01712e09, 0x019affb5, 0x01d7ffbb, 0x012900bc, 0x2c0782be, 0x011400c4, 0x01ecffc9, 0x01aeffca, + 0x200f82cc, 0x480382cd, 0xae220555, 0x0b82d101, 0x0382d220, 0x0382d320, 0x0382d420, 0x22055148, 0x82d701d7, 0x82d8200b, 0x82d9202f, 0x82da2007, + 0x82db2003, 0x82de200b, 0x45e02003, 0x012105f7, 0x200782e2, 0x200382e3, 0x200382e5, 0x200382e6, 0x200382e8, 0x200382e9, 0x200382ea, 0x200382ec, + 0x202b82ed, 0x280782ee, 0x015200f0, 0x0171fff2, 0x200b82f3, 0x200382f5, 0x200382f7, 0x0a8361f9, 0xaeff6a24, 0x0f826b02, 0x85ff7224, 0x07827d02, + 0x0f827f20, 0x03828520, 0x03828720, 0x03828920, 0x03828d20, 0x17829620, 0x03829a20, 0x0382a420, 0x0382a620, 0x2900a924, 0x0782ac02, 0x0382ae20, + 0x0382b020, 0x2382b220, 0x0382b420, 0x1782b520, 0x0382b720, 0x0382b920, 0x0382bd20, 0x2007ef45, 0x232382c4, 0x029affce, 0x2105dd47, 0xeb8202d7, + 0x82d50221, 0x82d72013, 0x05dd4703, 0xdb02ae22, 0xdc207f82, 0xdd204382, 0xe0200782, 0xc3820782, 0xbf820220, 0x82f00221, 0x82f2200b, 0x44f42003, + 0x00280683, 0x0a03d7ff, 0x0c03aeff, 0x11230382, 0x47039aff, 0xd72205a1, 0x0f821603, 0x29001724, 0x07821a03, 0x17821b20, 0x5cff1c24, 0x8b678a00, + 0xff9d30a4, 0xff9f019a, 0x00a401ec, 0xffa6013d, 0x43ae0185, 0xec2108ab, 0x39711801, 0xffbe2107, 0x22073b45, 0x82d5019a, 0x82dc201f, 0x059f430f, + 0xe701c322, 0xf2200f82, 0xb3670382, 0x6c02231e, 0x5b45ecff, 0x02c32206, 0x0a5f457e, 0x0f914918, 0x098d4918, 0x4918d720, 0x49460e8d, 0x09734509, + 0x7345c320, 0x02c32106, 0x2a05cf49, 0xffc702c3, 0x00ce02ae, 0x82cf0229, 0x05514603, 0x4702c321, 0x02201237, 0x21058745, 0x7f4503c3, 0x00112407, + 0x82120329, 0xb5491803, 0x03d72609, 0x03ecff19, 0x2013821b, 0x4903821c, 0x2a265b67, 0xd7ff9d01, 0x0382bc01, 0x220da34d, 0x48d001d7, 0xe12006eb, + 0xe4211b82, 0x078f4dff, 0x8002d726, 0x8202c3ff, 0xa0200382, 0x21089778, 0x977802d7, 0x02d72205, 0x202782b7, 0x200382b9, 0x069378bc, 0x21057b4d, + 0x7b4d02d7, 0x02d72205, 0x4d1782cb, 0xd722057b, 0x9d46e602, 0x02c32610, 0x03d7fffe, 0x20f98206, 0x24038208, 0x03c3ff0d, 0x2003820f, 0x05ad4417, + 0x69220021, 0xb020241d, 0x7d82b582, 0x82bd0121, 0x82bf2007, 0x82002061, 0x82762003, 0x189f2003, 0x20127b72, 0x47a584bb, 0x2b470533, 0x08f94705, + 0x20082347, 0x12456917, 0xf14d8f20, 0x05c1420b, 0x4d12554d, 0x4d4d0751, 0x0767519e, 0xff6a0222, 0x01350d10, 0x42002f64, 0xd7ff9d01, 0xf600a301, + 0x2900a401, 0x0b82a601, 0x1400aa22, 0x4c12fb44, 0xc12005ed, 0xc4201f82, 0xce200382, 0xd5202b82, 0xe1200382, 0xe7200b82, 0xf1320782, 0xf2016600, + 0x6c022900, 0x7202ecff, 0x7c021400, 0x054dd7ff, 0x82802008, 0x1882200b, 0x44120153, 0xdb4405df, 0x09b1430b, 0x2f82bd20, 0x0382bf20, 0x22051d4b, + 0x82c202d7, 0x82c6200b, 0x09cf4403, 0xd502d722, 0xd9200f82, 0xdb206b82, 0xdd200382, 0xdb440382, 0x02d72615, 0x03d7fffe, 0x2003820d, 0x0673480f, + 0x4409db44, 0x00210cd7, 0x08bb5431, 0xd5821020, 0x2215ad49, 0x82cb01c3, 0x09f9451b, 0xf584ae20, 0x3d000724, 0x03820b02, 0xf5846c20, 0x7e02ae22, + 0x16a37518, 0x4905ed71, 0xb6200561, 0xae20dd84, 0xae2ad982, 0xc3ffc502, 0x9affc602, 0x0782c702, 0xd523e187, 0x1802aeff, 0x8212cb75, 0x03ae21cd, + 0x2009a145, 0x354418d7, 0x069d4508, 0x4e260021, 0xb12408a9, 0xb501ecff, 0x22084d45, 0x82be01ec, 0x82bf200f, 0x82c1200f, 0x82c42007, 0x53c72003, + 0x7c200a9f, 0x80200b82, 0x82200382, 0xa1200382, 0xa9200382, 0x3b829d82, 0x41084145, 0xec21058f, 0x213b8202, 0x1b82ce02, 0x2382d420, 0x0382e720, + 0x0382e920, 0x0382f520, 0x0382f720, 0x2609a54c, 0xff0d03ec, 0x820f03ec, 0xff112403, 0x821703d7, 0xff1b2403, 0x544c00d7, 0xd7210e71, 0x3b771800, + 0x3f07680b, 0x2005af41, 0x125d4b3d, 0x4201d721, 0xae2205a9, 0xfd82e401, 0x3162f220, 0x4102200d, 0x77181fb3, 0xc0210757, 0x05ab41ff, 0x202f9f41, + 0x47fd8319, 0xd7210839, 0x7f771803, 0x6a57202b, 0x9d249469, 0xa401d7ff, 0xa6200382, 0xaa240382, 0xae01ecff, 0x59550382, 0x01c32205, 0x200b82bf, + 0x19656ac4, 0xff720225, 0x187602ec, 0x18087b7b, 0x4f0d9777, 0xc3220515, 0x1f82ca02, 0x2782d920, 0x0382db20, 0x0382dd20, 0x0b837b18, 0x4bab7718, + 0xef434520, 0x3d721808, 0xffa4246b, 0x82aa01ae, 0xffae2203, 0x069f4c9a, 0xce01ec22, 0xd5200b82, 0xf2241382, 0x0002aeff, 0x7718f182, 0xae2209bb, + 0x13825802, 0x03827220, 0x1805b74b, 0x240d5d72, 0x03aeff09, 0x087f4b0b, 0x4b03ae21, 0xae20056f, 0x203cb765, 0xe17a1842, 0x05415360, 0xbb01d726, + 0xbe01d7ff, 0x18058b55, 0x430c0964, 0xc3200591, 0x43184545, 0xc32a0991, 0xc3ffc202, 0xaeffc602, 0x0782d502, 0x20152d45, 0xfd7a18c3, 0x53012137, + 0x107c1b66, 0x53011326, 0xc3ff9f27, 0xecffa001, 0x05834301, 0x43018521, 0x71180783, 0xbe200bd7, 0xc4262382, 0xca011400, 0x795885ff, 0x5871200a, + 0x75581079, 0x01712105, 0x20377558, 0x206782e5, 0x580382e6, 0xc322056d, 0x6f82ea01, 0x2900eb23, 0x09715801, 0x50018521, 0x85210533, 0x0f715801, + 0x0f537218, 0x18077158, 0x58174b72, 0xc320057d, 0x210e7d58, 0x721802c3, 0x7d583353, 0x00a92313, 0x81580214, 0x02c32611, 0x0285ffb2, 0x737218b3, + 0x82bc201e, 0x82bd201f, 0x0761523f, 0x22059158, 0x82c602c3, 0x82c7203b, 0x82cb201b, 0x05fb4403, 0x91587120, 0x02c3222a, 0x583782e3, 0xc3210d91, + 0x05915802, 0x1802c321, 0x5816b772, 0x85201291, 0x18069158, 0x500dcf72, 0x712105ef, 0x05915803, 0x1803c321, 0x4513db72, 0x7120058b, 0x01bf2710, + 0x4b632008, 0xff25115d, 0xffaa01ae, 0x06fb5b9a, 0x2705a953, 0x01ecffbe, 0x012900c4, 0x2105a153, 0xf75b01c3, 0x01712205, 0x10ef5bcf, 0x210b7943, + 0xef5b019a, 0x01c32209, 0x5b5782de, 0x6d430fe3, 0x43c32011, 0xc3220669, 0x5b82ee01, 0x4305db5b, 0xb1611069, 0x6a022907, 0x6b029aff, 0x7202c3ff, + 0x7d200782, 0x7f200782, 0x85200782, 0x87200382, 0x89200382, 0x8d200382, 0x19430382, 0x5ba42007, 0x8f5b0693, 0x82b2200b, 0x82b4201f, 0x0be54203, + 0xd547c620, 0x13d94208, 0xda029a22, 0xdb201f82, 0x8d533382, 0x029a2205, 0x200b82e0, 0x065f5bec, 0x0b82f020, 0x0382f220, 0x0382f420, 0x2807475b, + 0x0385ff09, 0x039aff0a, 0x2007820b, 0x4207820c, 0x16200ba5, 0x1a200f82, 0x95420382, 0x51002006, 0xc5490567, 0x01c32a05, 0x01ecffa8, 0x01d7ffaa, + 0x220382ae, 0x4cc3ffb0, 0xc3220635, 0x0f82bf01, 0x0f82c420, 0x0782c720, 0x0782ce20, 0x0382d520, 0x8182f220, 0xd7ff7224, 0x07827602, 0x03829f20, + 0x0b82a120, 0x8118a920, 0xbb200e61, 0xbd200f82, 0xca200382, 0xce200382, 0xcf201f82, 0x80180782, 0x02210a7b, 0x200f82e5, 0x201782e7, 0x280382e9, + 0x03d7fff5, 0x03c3ff05, 0x20038207, 0x200b8211, 0x20078212, 0x20038217, 0x240b821b, 0x00c3ff1c, 0x0c795b2e, 0x3d00a422, 0x210e9b4e, 0x935301d7, + 0x01ec2205, 0x5b5582e1, 0x7c230b85, 0x5702ecff, 0xec210513, 0x07db4c02, 0x20136353, 0x202782b1, 0x200382b3, 0x5f0382bf, 0xec220599, 0x894dc202, + 0x82d42006, 0x055b4813, 0x837fec20, 0x066f5a08, 0x82fd0221, 0x82fe201b, 0x08eb4ca9, 0x53063353, 0x0021062b, 0x08554f30, 0x210b514f, 0x894dffbc, + 0x14002306, 0x0b82c101, 0x2005494f, 0x21bd8214, 0x494f01d7, 0x05454f0b, 0x87054b5c, 0xc97a18bd, 0x85022012, 0x02d722b5, 0x248d82c1, 0x02d7ffc2, + 0x200382c5, 0x200382c6, 0x082d4fc7, 0x85021421, 0x02d721c5, 0x850b2d4f, 0x4dd720bd, 0xbd8209a9, 0x14001224, 0xe9531703, 0x00142408, 0x829d013e, + 0x00a32aa1, 0x00a401e1, 0x00aa013d, 0x087b4129, 0xbd20c583, 0xbe200f82, 0xbf201f82, 0xc420c986, 0xc7200b82, 0xce200b82, 0xd1202b82, 0x254f0782, + 0x84ec2005, 0x82e420d9, 0x21dd8d1b, 0x9f410229, 0x41d72005, 0xa123089b, 0x83021400, 0x82aa20e1, 0x82b520c9, 0x18b62003, 0x900d9785, 0x090b50e9, + 0x0b50ec20, 0x02292606, 0x022900db, 0x200382dd, 0x204b82e7, 0x200382e9, 0x200382f5, 0x200f82f7, 0x200382f9, 0x950382fb, 0x842920f5, 0x881820f5, + 0x002922f9, 0x0e3b621e, 0xa8017123, 0x053b62ff, 0x20093362, 0x06315bd7, 0x22052762, 0x54c3ff7c, 0x255b088b, 0x05ad5517, 0x8202c321, 0xd4022143, + 0xfd232f82, 0x5403c3ff, 0xf55a0957, 0x5b202005, 0xbc2214bb, 0xad6285ff, 0x2579870a, 0xff0b029a, 0x79af029a, 0x7982c520, 0x0382c720, 0x23218197, + 0x0be14d01, 0x1744f783, 0x05515007, 0x9f55c320, 0x01ec2606, 0x01d7ffbf, 0x200382d5, 0x0a0f44f2, 0x440f3950, 0xd721050b, 0x050b4402, 0xcf02c322, + 0xe5202b82, 0x31507d82, 0x0aff430a, 0x1203c322, 0x22083150, 0x5c1c03c3, 0x6f4e0605, 0xffa82209, 0x06a544ec, 0x8501d721, 0x55d7208d, 0xd722065b, + 0x8d8cce01, 0x9f02d722, 0xbb206982, 0x2008555d, 0x217986d7, 0x798d02d7, 0x0703d722, 0x79447182, 0x03d72105, 0x24057544, 0x001900d7, 0x204d820a, + 0x5c0382dc, 0xec220573, 0x0b82e401, 0x4d82f620, 0x18055f5f, 0x5f0d0f4f, 0x6d180695, 0xc0240815, 0xc202ecff, 0xd5200382, 0x575f0382, 0x03ec210d, + 0x200b575f, 0x20b38421, 0x226988d0, 0x82df01d7, 0x82e1200b, 0x226d89e3, 0x187d02d7, 0x200a5744, 0x2081828b, 0x090760a0, 0xd7227182, 0x0f82ba02, + 0x0382bc20, 0xcb207587, 0x79830b82, 0x0782e620, 0x0a1d6618, 0xfffe0225, 0x820603ec, 0x820820eb, 0x07835b03, 0xd7ff1824, 0x99472400, 0x08635707, + 0x8582dd20, 0x934e898f, 0x05695c07, 0xd722ff83, 0x61828302, 0xec219185, 0x09034102, 0xec219187, 0x21918902, 0x918502ec, 0x0cad4418, 0xec229186, + 0x44180803, 0x91830ab1, 0x114f0720, 0x019a2e06, 0x01ecffed, 0x029afff2, 0x039affcf, 0x2a038212, 0x009aff1c, 0x00ca0110, 0x59ce0114, 0xd72a087d, + 0xc3ffe401, 0x7b00f101, 0x19417d02, 0x0b5f610a, 0x1400da24, 0x0382dc02, 0xf982fe20, 0x0d225f83, 0xe1820a00, 0x25057741, 0xffdf01ec, 0x534102ec, + 0x02ec2205, 0x200b82b6, 0x204582bc, 0x200382cb, 0x412d82e6, 0x1824072f, 0x2000ecff, 0x5d088946, 0xff6109a9, 0x109d5d08, 0x41826a20, 0x6a188f83, + 0xa38b1bcd, 0x2f82e020, 0x0ad96a18, 0xab830220, 0x0321a582, 0x2085820c, 0x24038216, 0x00d7ff1a, 0x08a9411d, 0xecffd124, 0x0382dc01, 0x0382dd20, + 0x2205bf5f, 0x50f601d7, 0x05620a39, 0x20df8515, 0x622782b8, 0xd5200b05, 0x0dad5118, 0x220efd61, 0x882100ec, 0x18cb20f7, 0x20129d76, 0xa17618e1, + 0x08c54f09, 0x2220fbd3, 0x200c7769, 0x207582d0, 0x20fb82d1, 0x0a0163d5, 0x1382df20, 0x0f82f220, 0x1960f620, 0x0b016306, 0x630d3343, 0xe7410505, + 0x82cf2007, 0x052b432f, 0x1802ec21, 0x43079370, 0xec260927, 0xecff1003, 0x03821203, 0xd7ff1829, 0xecff1c03, 0x8d011300, 0x01ec227d, 0x207582df, + 0x820382e4, 0x1449427d, 0x7d436186, 0x204d8508, 0x204d84ec, 0x08d34117, 0x01212582, 0x197518d8, 0x05515608, 0x9b826a20, 0x3a2f6c18, 0x6a300021, + 0xca270c9b, 0xce01d7ff, 0x83019aff, 0xffd52269, 0x226d82c3, 0x82db01d7, 0x00dd2413, 0x82de0114, 0x82ed2007, 0x82f22003, 0x18f6201f, 0x2509fb6d, + 0xd7ff6a02, 0x0f826d02, 0x07827f20, 0x07828120, 0x03828320, 0x0b9d6d18, 0x0f828b20, 0x6d188d20, 0xb8200aa1, 0xba200f82, 0xcf240382, 0xda02c3ff, + 0xdc201782, 0x11b56d18, 0x6f180220, 0xe3420b59, 0x616f1807, 0xff122307, 0xef4203c3, 0x1c032306, 0x9d44c3ff, 0x49002109, 0xca22a582, 0xc182ecff, + 0x8501c321, 0x01ec22bd, 0x22b984dc, 0x82f201ec, 0x07a1446d, 0x20173341, 0x249582aa, 0x02ecffb2, 0x200382b4, 0x22a188b6, 0x18dc02ec, 0x851a776d, + 0x03ec288d, 0x03140018, 0x84ecff1a, 0x421c2091, 0x4d631c89, 0x4595820a, 0x7d4205bd, 0x0fa9450b, 0x2746cf20, 0xffe62206, 0x0ca145d7, 0x220b7142, + 0x18cb011d, 0x200eb34a, 0x200f82de, 0x200382e1, 0x062f42ea, 0x7d20f383, 0x461e2b42, 0x6e180b95, 0x79840e67, 0xdf820a20, 0x03820c20, 0x03821620, + 0x0022eb82, 0x9b4a0115, 0x01292205, 0x206d86dc, 0x06ed59e4, 0x1400e924, 0xf159f101, 0xf6012405, 0x83021400, 0x49aa2079, 0x658706b1, 0x2900cf24, + 0x1382d502, 0x4d82fe20, 0x29001224, 0x07821803, 0x29001c24, 0x55821600, 0x4a013d21, 0xec21091b, 0x051b4a01, 0x86011421, 0x2059b8cb, 0x21a78219, + 0xbb46019a, 0x07754a05, 0xf6017124, 0x1d63c3ff, 0x09156306, 0xd7ff8b28, 0x9affaa02, 0x0382b602, 0x07694b18, 0x470b8b45, 0x6d180d35, 0x18240957, + 0x1c009aff, 0x2108af43, 0x6d90ffdc, 0x47082f4e, 0x71c50525, 0x25481120, 0x07f14408, 0x24056f44, 0xfff201d7, 0x22df82ec, 0x48a002d7, 0xcb200601, + 0x6b440782, 0xff1c2413, 0x981000ec, 0x46f62045, 0x0f4506ff, 0x0cad440e, 0x5d184183, 0x01200881, 0x00217f82, 0x0649441c, 0xd501d724, 0x49449aff, + 0x050d4706, 0x4705a764, 0x6a2005b7, 0x01479182, 0xffcf231b, 0xf946029a, 0x0827640e, 0x9aff1222, 0x2d0a0944, 0x0102009a, 0x013d00eb, 0x003d00f4, + 0xbb470121, 0x019a2605, 0x01c3ffdd, 0x0a0347de, 0x8b82e420, 0x2205a549, 0x827d02c3, 0xff81247b, 0x828302c3, 0x828b2003, 0x05854303, 0x6b07f541, + 0xd721070b, 0x07f94102, 0x22053749, 0x82e602d7, 0xcd841837, 0xfe02210a, 0x240a0748, 0x03c3ff0e, 0x24038210, 0x009aff18, 0x43858c1f, 0xd72105f7, + 0x21818201, 0x6d826d02, 0x01217ddf, 0x21e78201, 0x9b471c00, 0x66ec200a, 0x89410a41, 0x0719480b, 0x0b022925, 0x41022900, 0x8d411f91, 0x08834817, + 0xffca0123, 0x0c7f45d7, 0xd7fff222, 0xec215582, 0x13a74602, 0x21157345, 0x154602d7, 0x02ec2105, 0x13eb7218, 0x20137345, 0xc4d56edb, 0x85ffbc22, + 0x6108d96e, 0x4a189e87, 0xd56e1055, 0x71a92073, 0xd96e0653, 0x0d6f711b, 0xb902c322, 0xba203382, 0x2006e56e, 0x560b82bd, 0xe96e0d57, 0x050d6bb1, + 0x1d69c320, 0x65ed6e06, 0x99180320, 0x00210b3b, 0x3b9e18c4, 0x858f1844, 0x379e1819, 0xc18f1845, 0x2f9e180b, 0x2b9e1853, 0x279e1827, 0x239e186f, + 0xa1901827, 0xff602407, 0x826a02c3, 0x1b9e1803, 0x8285200b, 0x8287200f, 0x82892003, 0x0f9e1803, 0x00b92423, 0x18bb0252, 0x2032079e, 0x223382f9, + 0x183d00fb, 0x1810fb9d, 0x24a3f39d, 0x03520071, 0x2e038273, 0x00520083, 0x00450010, 0x0049003d, 0x824b0066, 0x0f631807, 0x003d2209, 0x200f824f, + 0x20178257, 0x20038259, 0x2403825a, 0x0029005b, 0x2807825c, 0x0329005d, 0x03660070, 0x20038272, 0xa70f8274, 0x00522141, 0x14204189, 0x022e418c, + 0x85ff0903, 0x85ff0b03, 0x97000200, 0x01820500, 0x0a000032, 0x01000b00, 0x11000f00, 0x24000300, 0x06002700, 0x29207d82, 0x2c221582, 0x19822c00, + 0x2f002e38, 0x32000c00, 0x0e003500, 0x3e003700, 0x44001200, 0x1a004600, 0xc5824800, 0x4e001d22, 0x21220182, 0xdd825000, 0x5500222e, 0x25005700, + 0x5e005900, 0x6d002800, 0x2e220182, 0x01827d00, 0x82002f3c, 0x30008700, 0x92008900, 0x94003600, 0x40009800, 0x9f009a00, 0xa2004500, 0x4382ad00, + 0xb800b322, 0xba2c3782, 0x5d00bf00, 0xc900c100, 0xcb006300, 0x6c240182, 0xcf00cd00, 0xd1264382, 0x7000d100, 0x0182d500, 0xd7007122, 0x72280182, + 0xdb00d900, 0xdd007300, 0x76220182, 0x0182ec00, 0xf0007722, 0x78220182, 0x0182f200, 0xf8007922, 0x7a280182, 0xfb00fa00, 0xfd007b00, 0x04090182, + 0x01ff007d, 0x017e0001, 0x00030103, 0x01060181, 0x01820006, 0x00080108, 0x010a0183, 0x0184000a, 0x000f010e, 0x01110185, 0x01870013, 0x00150115, + 0x011d018a, 0x018b001d, 0x001f011f, 0x0121018c, 0x018d0024, 0x00270126, 0x012c0191, 0x0193002c, 0x00300130, 0x01320194, 0x01950032, 0x00340134, + 0x01360196, 0x0197003b, 0x003d013d, 0x013f019d, 0x019e0040, 0x00440143, 0x014a01a0, 0x01a2004a, 0x00560156, 0x015a01a3, 0x01a40062, 0x00640164, + 0x016601ad, 0x01ae0069, 0x006d016c, 0x016f01b2, 0x01b4007c, 0x0084017e, 0x018601c2, 0x01c90088, 0x008e018a, 0x019001cc, 0x01d10091, 0x00970193, + 0x019901d3, 0x01d80099, 0x00a2019b, 0x01a401d9, 0x01e100a8, 0x00ae01aa, 0x01b001e6, 0x01eb00b1, 0x00b401b4, 0x01b801ed, 0x01ee00b8, 0x00c001ba, + 0x01c301ef, 0x01f600c4, 0x00c801c6, 0x01ca01f8, 0x01fb00d1, 0x220182d4, 0x82d80103, 0x01043401, 0x01e001da, 0x01e30105, 0x010c01ea, 0x01ee01ec, + 0x82f00114, 0x17840901, 0xf601f201, 0xf8011801, 0x1d010302, 0x06020602, 0x0a022901, 0x2a010a02, 0x28022802, 0x58022b01, 0x2c015802, 0x60026002, + 0x62022d01, 0x2e016202, 0x6a026a02, 0x6c022f01, 0x30017202, 0x74027402, 0x76023701, 0x38017c02, 0x8c027e02, 0x95023f01, 0x4e019d02, 0xa0029f02, + 0xa2025701, 0x5901af02, 0xc002b102, 0xc3026701, 0x7701c302, 0xc502c502, 0xc7027801, 0x7901c702, 0xcc02c902, 0xce027a01, 0x7e01cf02, 0xd302d202, + 0xd6028001, 0x8201d902, 0xdb02db02, 0xde028601, 0x8701de02, 0xe902e002, 0xef028801, 0x9201fc02, 0x0003ff02, 0x0303a001, 0xa2010803, 0x1d030b03, + 0x1f03a801, 0xbb011f03, 0x21032103, 0x2303bc01, 0xbd012303, 0x25032503, 0x2703be01, 0xbf012703, 0x29032903, 0x2b03c001, 0xc1012b03, 0x2d032d03, + 0x2f03c201, 0xc3012f03, 0x31033103, 0x3303c401, 0xc5013303, 0x36033603, 0x3803c601, 0xc7013803, 0x3a033a03, 0x3c03c801, 0xc9013c03, 0x3e033e03, + 0x4003ca01, 0xcb014003, 0x42034203, 0x4403cc01, 0xcd014503, 0x47034703, 0x4903cf01, 0xd0015603, 0x58035803, 0x5a03de01, 0xdf015a03, 0x5c035c03, + 0x5e03e001, 0xe1015e03, 0x61036003, 0x6303e201, 0xe4016303, 0x66036603, 0x6803e501, 0xe6016803, 0x6a036a03, 0x6c03e701, 0xe8016c03, 0x74036e03, + 0x8303e901, 0xf0018303, 0x01000000, 0x0a240382, 0x1e001c00, 0x108fa918, 0x00000024, 0xfa050000, 0x4812c497, +};++}
+ cbits/tracy/profiler/src/font/FiraCodeRetina.hpp view
@@ -0,0 +1,3995 @@+// File: 'FiraCode-Retina.ttf' (295252 bytes)+// Exported using binary_to_compressed_c.cpp++namespace tracy+{++static const unsigned int FiraCodeRetina_compressed_size = 191172;+static const unsigned int FiraCodeRetina_compressed_data[191172/4] =+{+ 0x0000bc57, 0x00000000, 0x54810400, 0x00000400, 0x00010025, 0x82120000, 0x00042604, 0x49534420, 0x240d8247, 0x81040001, 0x2c07824c, 0x45444708, + 0x051f0446, 0x0100008d, 0x0803822c, 0x5047ea2c, 0x03c0534f, 0x0000bc3b, 0x00001803, 0x53476c1e, 0x6a844255, 0x00006f79, 0x00008421, 0x534f3e6f, + 0x08a7322f, 0x0000c707, 0x3f82c490, 0x6d63603c, 0xe1bd7061, 0x0000d394, 0x00002491, 0x7663f441, 0x43472074, 0x0400f819, 0x1f82b471, 0x7066a834, + 0x369e6d67, 0x0400d215, 0x00005c72, 0x6167150e, 0x17827073, 0x1f821020, 0x0782ac20, 0x6c67083c, 0x9b6c6679, 0x000003a3, 0x030018d3, 0x6568240d, + 0x96106461, 0x03008fa5, 0x1f823ce0, 0x82683621, 0x70022310, 0x0f82f004, 0x0f827420, 0x6d682428, 0xcf8e7874, 0x0f82b467, 0x00982008, 0x6cf01c00, + 0x0961636f, 0x00e0aa69, 0x0088fd03, 0x6d081d00, 0x0c707861, 0x00b61277, 0x82901a04, 0x6e20282f, 0x3a656d61, 0x826bbb77, 0x00b03f0f, 0x70c10900, + 0x9474736f, 0x005b5263, 0x00742404, 0x70354d00, 0x8a706572, 0x001e9ccd, 0x0f828004, 0x00d60023, 0x20358201, 0x8303820c, 0x00022602, 0x0004004f, + 0x2213822b, 0x822e002d, 0x00302205, 0x22058262, 0x82880064, 0x008b2205, 0x2205829e, 0x82bc00a0, 0x00be2205, 0x220582d2, 0x82df00d4, 0x00e12205, + 0x280582ed, 0x001301ef, 0x01150101, 0x22058217, 0x821b011b, 0x011d2805, 0x0102001d, 0x82440121, 0x0146220b, 0x2205824e, 0x82520150, 0x01542205, + 0x2205825e, 0x82650160, 0x01682205, 0x22058268, 0x8275016a, 0x01772205, 0x2205827b, 0x827d017d, 0x017f2205, 0x2105827f, 0x77820181, 0x018a0123, + 0x220b82a0, 0x82af01a2, 0x01b12205, 0x220582b2, 0x82bf01b4, 0x01c12205, 0x220582c4, 0x82d401c6, 0x01d62205, 0x220582ee, 0x82f101f0, 0x01f32205, + 0x280582f5, 0x000602fa, 0x02090201, 0x2205820b, 0x820f020f, 0x02112205, 0x21058218, 0xd782021a, 0x02300223, 0x220b8230, 0x823c0232, 0x023e2205, + 0x2205823f, 0x824b0241, 0x024d2205, 0x280582fc, 0x00fe02fe, 0x03000301, 0x22058205, 0x82070307, 0x03092205, 0x2205828c, 0x8290038f, 0x03942e05, + 0x04010094, 0x00720446, 0x04780402, 0x22058279, 0x8282047d, 0x04862205, 0x21058288, 0xa78204af, 0x04b10423, 0x222382b1, 0x82dc04dc, 0x04fe2105, + 0x05294d82, 0x00020502, 0x061a0601, 0x2105821a, 0x7d82062f, 0x06320623, 0x220b8232, 0x82430643, 0x06452205, 0x22058245, 0x82480647, 0x064a2105, + 0x06238982, 0x8250064d, 0x0652220b, 0x2205825a, 0x825c065c, 0x06692205, 0x2205826c, 0x8275066f, 0x06772205, 0x22058277, 0x827b067a, 0x06852805, + 0x060200b0, 0x82c006b4, 0x06c42805, 0x060200e3, 0x82e606e6, 0x06ed2817, 0x070300ff, 0x820e070e, 0x071d2805, 0x0003001e, 0x82010000, 0x0a2c0803, + 0x46032401, 0x46440600, 0x2600544c, 0x6c727963, 0x72673400, 0x42006b65, 0x6e74616c, 0x697a5000, 0xfe00686e, 0x7979797a, 0x04000c01, 0x00242f82, + 0x0200ffff, 0x8805c142, 0x0001220d, 0x3a1b8a11, 0x00120002, 0x410a0040, 0x00204b46, 0x455a414a, 0x43540020, 0x00205441, 0x8252435e, 0x4b682e05, + 0x00205a41, 0x4c4f4d72, 0x507c0020, 0x2723824c, 0x4d4f5286, 0x54900020, 0x9a222383, 0x11825254, 0x8500a421, 0x00032265, 0x22098613, 0x86140004, + 0x00052209, 0x22098615, 0x86160006, 0x00072209, 0x22098617, 0x86180008, 0x00092209, 0x22098619, 0x861a000a, 0x000b2209, 0x2209861b, 0x861c000c, + 0x000d2209, 0x22bb8a1d, 0x8a1e000e, 0x000f2a0d, 0x6d20001f, 0x006b7261, 0x200584c2, 0x200584ce, 0x200584da, 0x200584e6, 0x200584f2, 0x210583fe, + 0x05840a01, 0x05841620, 0x05842220, 0x05842e20, 0x05843a20, 0x05844620, 0x05845220, 0x05845e20, 0x05846a20, 0x6b6d7626, 0x82016b6d, 0x8c200584, + 0x96200584, 0xa0200584, 0xaa200584, 0xb4200584, 0xbe200584, 0xc8200584, 0xd2200584, 0xdc200584, 0xe6200584, 0xf0200584, 0xfa200584, 0x02210583, + 0x20058404, 0x2205840e, 0x84000018, 0x000124d1, 0x40030002, 0x0326b60b, 0x05000400, 0xbd820600, 0x2e930940, 0x00100007, 0x00200018, 0x00300028, + 0x41400038, 0x3820066d, 0x02210785, 0x21078544, 0x07858e08, 0x847e1121, 0x170122c7, 0x2107858a, 0x07860818, 0x01003432, 0x1019fa18, 0x0c000200, + 0x14005e00, 0x18010100, 0x1e20038e, 0x1f8f0f8e, 0x1f822420, 0x03822a20, 0x00003024, 0x03880c01, 0x002c4783, 0x2e001201, 0xea00e400, 0xf600f000, + 0xfc220784, 0x07840201, 0x0b841383, 0x01080135, 0x0014010e, 0x011a01e4, 0x01260120, 0x0132012c, 0x823e0138, 0x0144340f, 0x0150014a, 0x015c0156, + 0x01680162, 0x0174016e, 0x8c80017a, 0x831b8303, 0x01862223, 0x832b848c, 0x0192220b, 0x83438498, 0x224b831b, 0x84a4019e, 0x225b8343, 0x83b001aa, + 0x831f885b, 0x83438723, 0x8603873b, 0x01002937, 0x0000a8fd, 0x26fd0100, 0xa8260584, 0x01001e04, 0x058359fd, 0x840dfe21, 0x8456200b, 0x83a42005, + 0x58022105, 0x02272383, 0x00620558, 0x84bc0201, 0x84da200b, 0x8427200b, 0x842e200b, 0x8454200b, 0x01792805, 0x0201001c, 0x82860679, 0x05582805, + 0x0301006a, 0x82ca01f2, 0x03f52205, 0x20058291, 0x200b841c, 0x200b8422, 0x200b84f9, 0x820b8396, 0x82c62059, 0x84e6201d, 0x84e62011, 0x841e201d, + 0x841e200b, 0x84f6200b, 0x84f4200b, 0x83662029, 0x6402210b, 0x77200b84, 0x81200b84, 0xe5202384, 0xe5202384, 0x04210b83, 0x210b8307, 0x17841104, + 0x17841d20, 0x0b841d20, 0x2f843120, 0x0b83ce20, 0x17e61623, 0x0913425c, 0x00540423, 0x20038c01, 0x8f0f8e5a, 0x8260201f, 0x8266201f, 0x006c2403, + 0x88480400, 0x2a438303, 0x004e0400, 0x042004fd, 0x862c0426, 0x04322303, 0x03870438, 0x13823e20, 0x4a044423, 0x83038704, 0x04502223, 0x872b8856, + 0x042c2233, 0x8313825c, 0x89478903, 0x0426281b, 0x04680462, 0x8274046e, 0x867a2023, 0x22278703, 0x822c0480, 0x8b2b888f, 0x228f860b, 0x868c0486, + 0x8a92206f, 0x88982077, 0x8a3e200b, 0x854788bb, 0x204d8213, 0x2227889e, 0x82a4042c, 0x04aa250b, 0x04b604b0, 0xcb853387, 0xbc22b785, 0x1788c204, + 0xb3891f83, 0x3782c820, 0x26200383, 0xb3821f86, 0x03830420, 0x8b89eb91, 0x20048022, 0x57418382, 0x04ce2405, 0x824a0444, 0x86d42043, 0x04262103, + 0x20154341, 0x831f8226, 0x072341e3, 0x80240783, 0x38043204, 0xda26c384, 0xe604e004, 0x7b41ec04, 0x24738910, 0x04f20426, 0x411f90f8, 0xfe220b13, + 0xc3840405, 0x830f3341, 0x2913840f, 0x2c040a05, 0x16051005, 0x03871c05, 0x053e0423, 0x20138222, 0x20038628, 0x2407822e, 0x05bc0422, 0x20078434, + 0x831b842c, 0x823a201f, 0x8303830f, 0x23038c0b, 0x46054005, 0x22231b82, 0x84050000, 0x204f8203, 0x243b8610, 0x0050044c, 0x8b478900, 0x2257860b, + 0x86520586, 0x0458231f, 0x0082002c, 0x005e0525, 0x82640500, 0x20438713, 0x204f8422, 0x202f846e, 0x84938e6a, 0x202f8287, 0x83238270, 0x8276207b, + 0x827c201f, 0x05822403, 0x848e0588, 0x84c785d7, 0x940523b7, 0x13849a05, 0xb387ef82, 0x57840f87, 0xa0221783, 0x0b82a605, 0x03824c20, 0xac051028, + 0xb805b205, 0x1b87be05, 0x2c222b84, 0x0f820a05, 0x7382c420, 0x0782ca20, 0x07822820, 0x0382d020, 0x0b82d620, 0xbc04dc24, 0x2b84e205, 0xdc052c22, + 0xdc200782, 0x76201782, 0x5e200382, 0xe8200b82, 0x9f830782, 0xb3831383, 0x1605ee24, 0x33841c05, 0x57867382, 0xf3831783, 0x9341f785, 0x0c674105, + 0x93418788, 0x8b1f8509, 0x820b8743, 0x2c4f4507, 0x4f455420, 0x8358200a, 0x6501210b, 0xb4281184, 0x01006205, 0x6afe5802, 0x89200582, 0x82201184, + 0x49201184, 0x51200b84, 0x80200b84, 0x20108545, 0x201d8456, 0x20178456, 0x2005846c, 0x20058442, 0x20178452, 0x200b8464, 0x2005843f, 0x200584bc, + 0x20058436, 0x27058345, 0xcd07e101, 0xa0010100, 0xef202984, 0x57201784, 0x57200b84, 0x5e200b84, 0xcf200584, 0x4a220584, 0x29826305, 0x1d83bc20, + 0x840b0321, 0x843b2011, 0x843b2029, 0x8494200b, 0x8494200b, 0x844f200b, 0x8477200b, 0x4648200b, 0x0521053f, 0x203b82c6, 0x20178490, 0x841185a8, + 0x856c2005, 0x7e052505, 0x49020100, 0x80200b84, 0xa6200584, 0xb0262984, 0x01000c04, 0x11843e02, 0x05846920, 0x05844f20, 0x2f845a20, 0x0b83e020, + 0x05730123, 0x20238218, 0x8417853d, 0x84552005, 0x06f12217, 0x20718289, 0x204784cc, 0x201784e4, 0x200b844a, 0x200b844a, 0x200b8444, 0x200b842a, + 0x200b844e, 0x21a1834e, 0x0b84cf02, 0x0b840f20, 0x65844820, 0x23846720, 0x05855b20, 0x58201184, 0x49200584, 0x4f200584, 0x3e200584, 0x10230583, + 0x46b61194, 0x05230951, 0x8c010080, 0x8e862003, 0x201f8f0f, 0x201f828c, 0x24038292, 0x05000098, 0x83038874, 0x05002c43, 0x0548017a, 0x0552054c, + 0x825e0558, 0x055e2407, 0x846a0564, 0x05702207, 0x20078276, 0x200b847c, 0x221b864c, 0x86880582, 0x8c8e200f, 0x221f8717, 0x829a0594, 0x8ca02017, + 0x82a6201b, 0x8258203b, 0x854f8503, 0x212f8563, 0x1b8305a0, 0x07850b87, 0xac221f85, 0xa5825e05, 0xb2055e24, 0x4b88b805, 0x8200ac21, 0xa0052300, + 0x03850000, 0x3b8b638c, 0x58220b83, 0xcf82be05, 0x0382c420, 0x0382ca20, 0x0382d020, 0x0382d620, 0x0382dc20, 0x0382e220, 0xeb84e820, 0x03879383, + 0x5e05ee24, 0x3382ee05, 0xc405ee22, 0xca200782, 0xd0200382, 0xd6200382, 0xdc200382, 0xe2200382, 0xe8240382, 0xf4057005, 0xfa240382, 0x00067005, + 0x06200382, 0x0c200382, 0x12200382, 0x76201382, 0x4c260384, 0x4c051806, 0x03821e06, 0x03822420, 0x03822a20, 0x03823020, 0x03823620, 0x03823c20, + 0xaf874220, 0x05480627, 0x0648065e, 0x20038218, 0x2003821e, 0x20038224, 0x2003822a, 0x20038230, 0x20038236, 0x8203823c, 0x4e06212b, 0x54203382, + 0x5a200382, 0x60200382, 0x66200382, 0x6c200382, 0x72200382, 0x78200382, 0x0621fb91, 0x2017827e, 0x20038284, 0x2003828a, 0x20038290, 0x20038296, + 0x2127899c, 0x0f82a206, 0x0382a820, 0x0382ae20, 0x0382b420, 0xa741ba20, 0x88a02006, 0x82a62007, 0x06a62643, 0x06a605c0, 0x200382c6, 0x200382cc, + 0x200382d2, 0x200382d8, 0x240382de, 0x05a605e4, 0x2103835e, 0xbf82ea06, 0x7e06ea26, 0xc006ea06, 0xc6200382, 0xcc200382, 0xd2200382, 0xd8200382, + 0xde200382, 0xe42c0382, 0xf606f006, 0xfc06ac05, 0x0207ac05, 0xfc246b82, 0x0e070807, 0x07230f83, 0x831a0714, 0x4c05230f, 0x03822007, 0x23851b84, + 0x2f832782, 0x07824c20, 0xac220383, 0x17882607, 0x02201389, 0x53831384, 0x27849420, 0x2c204383, 0x07214b89, 0x82538532, 0x831f821b, 0x85778383, + 0x84138273, 0x895f888b, 0x834c204b, 0x88ab89a7, 0x232f8643, 0x38070000, 0xcf861384, 0x073e0727, 0x07f00644, 0x2003824a, 0x20038250, 0x20038256, + 0x2003825c, 0x20038262, 0x20038268, 0x2103826e, 0xff820674, 0x072b038f, 0x07f6067a, 0x0780077a, 0x8286077a, 0x824a2003, 0x82502003, 0x82562003, + 0x825c2003, 0x82622003, 0x82682003, 0x826e2003, 0x82742003, 0x828c2003, 0x829220bb, 0x82982003, 0x829e2003, 0x82a42003, 0x82aa2003, 0x84b02003, + 0x070822d3, 0x20d7820e, 0x200382b6, 0x200382bc, 0x200382c2, 0x200382c8, 0x200382ce, 0x200382d4, 0x200382da, 0x200382e0, 0x2603881a, 0x071a07e6, + 0x82ec07e6, 0x82f22003, 0x82b62003, 0x82bc2003, 0x82c22003, 0x82c82003, 0x82ce2003, 0x82d42003, 0x82da2003, 0x82e02003, 0x82f82003, 0x05fe24ef, + 0x8204084c, 0x820a2003, 0x82102003, 0x82162003, 0x821c2003, 0x82222003, 0x41282003, 0x20200673, 0x08210795, 0x2023822e, 0x20038234, 0x2003823a, + 0x20038240, 0x20038246, 0x2003824c, 0x095b4152, 0x05580825, 0x995e08ac, 0x64082127, 0x6a201b82, 0x03422f88, 0x25078c07, 0x94057008, 0x03823408, + 0x03823a20, 0x03824020, 0x03824620, 0x03824c20, 0x03825220, 0x03826420, 0x94056a24, 0x03870207, 0x07760827, 0x08760802, 0x2003827c, 0x20038282, + 0x20038234, 0x2003823a, 0x20038240, 0x20038246, 0x2003824c, 0x20038252, 0x20038264, 0x2503826a, 0x008e0888, 0x03820800, 0x94208782, 0x252c7d47, + 0x00000058, 0x0b470201, 0x0a894705, 0x470c8347, 0x7b220b7d, 0x2f826205, 0x35847e20, 0x0b848520, 0x05845920, 0x200b7747, 0x2011845e, 0x2523845a, + 0x006afe58, 0x59850101, 0x1783a320, 0x05dd002e, 0x00010076, 0x007705bb, 0x0576ff01, 0x00231d82, 0x82700548, 0x83032011, 0x86ff2105, 0x5b221184, + 0x11827505, 0x23834220, 0xfeea0223, 0x200b8282, 0x20358433, 0x21058312, 0x2383e6fe, 0x84c0ff21, 0x835b202f, 0xdefe2105, 0xe0201184, 0xff211d83, + 0x202384bf, 0x20118493, 0x2023846d, 0x20238408, 0x2011848b, 0x2159834c, 0x598432ff, 0x5984ee20, 0x59840820, 0x8f840f20, 0x23841220, 0x3584e320, + 0x35843020, 0x1184b320, 0x35847420, 0x23835a20, 0x84260021, 0x83dd2065, 0x91fe210b, 0x6b201d84, 0x26202f84, 0xa8202f84, 0xf8201184, 0xa3202384, + 0x5a205384, 0x29201784, 0xfe211783, 0x201184ce, 0x203b84dc, 0x20298490, 0x203b846a, 0x20238427, 0x201184a9, 0x206b8492, 0x20a18478, 0x21a183f0, + 0xa1475502, 0x0558280a, 0x020100c6, 0x821e0458, 0x846f2005, 0x83782017, 0x1101210b, 0x59200b84, 0x3b201784, 0x66200584, 0x3b200584, 0x200aa747, + 0x261184e0, 0x006afe95, 0x84a30201, 0x0670260b, 0x01010048, 0x200584e4, 0x2305837d, 0x4e062e02, 0x30201d82, 0x01210583, 0x22118476, 0x82d40660, + 0x062e2211, 0x200582d6, 0x228f84eb, 0x82460632, 0x8416200b, 0x052f2205, 0x200b82b6, 0x202984be, 0x20478432, 0x200b84cb, 0x2047847c, 0x2047847e, + 0x201184c4, 0x2005849f, 0x20238413, 0x200b84ac, 0x2023845d, 0x2023845f, 0x201184a5, 0x206b848f, 0x216b835d, 0x6b84a701, 0x65846120, 0x05844520, + 0x6b845e20, 0x41848120, 0x0584f520, 0x35848e20, 0x47843f20, 0x47844120, 0x11848720, 0x47847120, 0xb3843f20, 0x41054322, 0x9e20a182, 0x12201784, + 0xab203584, 0x5c200b84, 0x5e203584, 0xa4203584, 0x95851184, 0x0b842020, 0x41848e20, 0x41845c20, 0x41846020, 0x8f84ec20, 0x89846020, 0x05844420, + 0x8f845d20, 0x17846c20, 0x1e044f28, 0x9c070100, 0xf748ec08, 0x88042309, 0x038c0100, 0x0f8e8e20, 0x94201f8f, 0x9a201f82, 0xa0240382, 0x7c040000, + 0x43830388, 0x82040028, 0x54040a01, 0x03a45a04, 0x66046023, 0x24038504, 0x046c045a, 0x26039472, 0x04780460, 0x8284047e, 0x23078527, 0x0490048a, + 0x602003a3, 0x96238382, 0x8f049c04, 0xad178303, 0x82a22003, 0x04a2247b, 0x84ae04a8, 0x04b42303, 0x038f04ba, 0xc0049622, 0x5a202382, 0xc6200382, + 0x1b830396, 0xcc2003b5, 0x038bc782, 0xd804d223, 0x23039304, 0x04e404de, 0xe7ad038f, 0xea209f9b, 0x038fd782, 0x1382f020, 0x6c220389, 0xfb867204, + 0x9f845a20, 0x83046021, 0x82f6201b, 0x20038b13, 0x840f8efc, 0x0000231b, 0x03830205, 0x05600427, 0x050e0508, 0x84039314, 0x051a261b, 0x05de0420, + 0x200b8226, 0x2003922c, 0x23138f32, 0x3e053805, 0x44205782, 0x2782038f, 0x03890820, 0x00820020, 0x004a0523, 0x20038c00, 0x870f8e50, 0x8256201f, + 0x21038417, 0xab825c05, 0x47820382, 0x68056224, 0x03936e05, 0x74231b84, 0x83056205, 0x057a2203, 0x86078480, 0x8e1b830f, 0x8b862003, 0x2067820f, + 0x87038362, 0x8c052213, 0x24b38305, 0x05920562, 0x23038b98, 0x9e05d204, 0x05230393, 0x8faa05a4, 0x8a538703, 0x92862007, 0x8a778c13, 0x8e9f8893, + 0x41438433, 0x0e22107b, 0xef831405, 0xa3833f84, 0x2c056025, 0x82006004, 0x56052500, 0xb0056805, 0xff47c383, 0x107d4f2c, 0xe14e0220, 0x0bd95405, + 0x62053826, 0x6c020100, 0x01226482, 0x0b844c02, 0x200b1148, 0x0aed4e94, 0x48054748, 0x92200b1d, 0x01211d83, 0x21358366, 0x2f486801, 0x8459200a, + 0x0b954f35, 0x48114148, 0x354f056b, 0x0b814e05, 0x4f050347, 0x1b200b17, 0x1b264d84, 0x0100c605, 0x05845602, 0x200b4d4f, 0x201d840d, 0x201784e4, + 0x0a1d4f4d, 0x3b4f5a20, 0x61022109, 0x57472384, 0x0bf94e05, 0x4705c548, 0x6d200569, 0x58203b84, 0xd7483584, 0x84c92005, 0x4f932035, 0xe3200a95, + 0xe726ef84, 0x01001805, 0xef830f02, 0x0324032b, 0x00010034, 0x004e000c, 0x201b8210, 0x20038e4a, 0x8f0f8e50, 0x8256201f, 0x825c201f, 0x84622003, + 0x00032927, 0x002c0026, 0xfd010032, 0x211ca356, 0xa383a8fd, 0x06a9fd23, 0x85858289, 0x02b822af, 0x5a8584c4, 0x1620057b, 0x03874d82, 0x17821c20, + 0x33421020, 0xfebc220e, 0x22398282, 0x8a96026a, 0x8b8583b9, 0x86622003, 0x87178f99, 0x8268200f, 0x826e201f, 0x84742003, 0x000c3827, 0x003e0038, + 0x004a0044, 0x00560050, 0x0062005c, 0x006e0068, 0xa07a0074, 0x05ad22cb, 0x228b82b6, 0x8248065e, 0x835d2005, 0xb4012105, 0x8e220b84, 0x11824e06, + 0x05830f20, 0x84860121, 0x066d2211, 0x201182d4, 0x0ab34754, 0x0909ad47, 0x03000220, 0xfd06ed06, 0x0e070000, 0x11000e07, 0x1e071d07, 0x01001200, + 0x8f032e00, 0x94039003, 0xb104af04, 0xfe04dc04, 0x1a060205, 0x30062f06, 0x43063206, 0x47064506, 0x4a064806, 0x4d064b06, 0x4f064e06, 0x52065006, + 0x54065306, 0x56065506, 0x58065706, 0x5a065906, 0x69065c06, 0x6b066a06, 0x6f066c06, 0x71067006, 0x73067206, 0x75067406, 0x7a067706, 0x02007b06, + 0x21011c00, 0x00004401, 0x4e014601, 0x50012400, 0x2d005201, 0x5e015401, 0x60013000, 0x3b006501, 0x68016801, 0x6a014100, 0x42007501, 0x7b017701, + 0x7d014e00, 0x53007d01, 0x7f017f01, 0x81015400, 0x55008801, 0xa0018a01, 0xa2015d00, 0x7400af01, 0xb201b101, 0xb4018200, 0x8400bf01, 0xc401c101, + 0xc6019000, 0x9400d401, 0xee01d601, 0xf001a300, 0xbc00f101, 0xf501f301, 0xfa01be00, 0xc1000602, 0x0b020902, 0x0f02ce00, 0xd1000f02, 0x18021102, + 0x1a02d200, 0xda002e02, 0x30023002, 0x3202ef00, 0xf0003c02, 0x3f023e02, 0xab82fb00, 0x02076208, 0x004b0241, 0x024d0200, 0x020b00fc, 0x00fe02fe, + 0x030003bb, 0x03bc0005, 0x00070307, 0x030903c2, 0x06c3008c, 0x01e606e6, 0x00020047, 0x0004000c, 0x0000002b, 0x002e002d, 0x00300028, 0x002a0062, + 0x00880064, 0x008b005d, 0x0082009e, 0x00bc00a0, 0x00be0096, 0x00b300d2, 0x00df00d4, 0x00e100c8, 0x2c0982ed, 0x001301ef, 0x011501e1, 0x01060117, + 0x2001821b, 0x304b8209, 0x06ed0602, 0x070000fb, 0x001d071d, 0x0001000f, 0x220f8203, 0x820007f9, 0x06042809, 0x07fd06fc, 0x821e070e, 0x8401200b, + 0x820c2005, 0x07223425, 0x07250724, 0x07270726, 0x07290728, 0x072d072a, 0x8230072e, 0x00002621, 0x22b8030a, 0x0c6b5e72, 0x72675c38, 0x92006b65, + 0x6e74616c, 0x697ac800, 0x4203686e, 0x7979797a, 0x855d7803, 0x82162008, 0x001022c5, 0x08c38220, 0x5a004022, 0x7a006a00, 0x9a008a00, 0xba00aa00, + 0xda00ca00, 0xfa00ea00, 0x1a010a01, 0x3a012a01, 0x5a014a01, 0x012e358a, 0x21001100, 0x41003100, 0x6b005b00, 0xf7827b00, 0xab009b2e, 0xcb00bb00, + 0xeb00db00, 0x0b01fb00, 0x2b26dd82, 0x4b013b01, 0x358a5b01, 0x00022a08, 0x00220012, 0x00420032, 0x006c005c, 0x008c007c, 0x00ac009c, 0x00cc00bc, + 0x00ec00dc, 0x010c01fc, 0x012c011c, 0x014c013c, 0x08e35e5c, 0x41722b08, 0x0020455a, 0x544143a6, 0x43da0020, 0x01205452, 0x5a414b0e, 0x4d420120, + 0x01204c4f, 0x4b4c5076, 0x52aa0120, 0x01204d4f, 0x238254de, 0x12023908, 0x204b5254, 0x00004602, 0x1600ffff, 0x13000300, 0x33002300, 0x5d004300, + 0x7d006d00, 0x9d008d00, 0xbd00ad00, 0xdd00cd00, 0xfd00ed00, 0x1d010d01, 0x3d012d01, 0x5d014d01, 0x17203184, 0x2a08ad82, 0x00240014, 0x00440034, + 0x005e0050, 0x007e006e, 0x009e008e, 0x00be00ae, 0x00de00ce, 0x01fe00ee, 0x011e010e, 0x013e012e, 0x865e014e, 0x052c0833, 0x25001500, 0x45003500, + 0x5f005100, 0x7f006f00, 0x9f008f00, 0xbf00af00, 0xdf00cf00, 0xff00ef00, 0x1f010f01, 0x3f012f01, 0x5f014f01, 0x06203386, 0x28089d82, 0x00360026, + 0x00520046, 0x00700060, 0x00900080, 0x00b000a0, 0x00d000c0, 0x01f000e0, 0x01100100, 0x01300120, 0x01500140, 0x08338660, 0x1700072c, 0x37002700, + 0x53004700, 0x71006100, 0x91008100, 0xb100a100, 0xd100c100, 0xf100e100, 0x11010101, 0x31012101, 0x51014101, 0x33866101, 0x00082c08, 0x00280018, + 0x00480038, 0x00620054, 0x00820072, 0x00a20092, 0x00c200b2, 0x00e200d2, 0x010201f2, 0x01220112, 0x01420132, 0x86620152, 0x092c0833, 0x29001900, + 0x49003900, 0x63005500, 0x83007300, 0xa3009300, 0xc300b300, 0xe300d300, 0x0301f300, 0x23011301, 0x43013301, 0x63015301, 0x2c083386, 0x001a000a, + 0x003a002a, 0x0056004a, 0x00740064, 0x00940084, 0x00b400a4, 0x00d400c4, 0x01f400e4, 0x01140104, 0x01340124, 0x01540144, 0x08338664, 0x1b000b2c, + 0x3b002b00, 0x57004b00, 0x75006500, 0x95008500, 0xb500a500, 0xd500c500, 0xf500e500, 0x15010501, 0x35012501, 0x55014501, 0x33866501, 0x000c2c08, + 0x002c001c, 0x004c003c, 0x00660058, 0x00860076, 0x00a60096, 0x00c600b6, 0x00e600d6, 0x010601f6, 0x01260116, 0x01460136, 0x86660156, 0x0d2c0833, + 0x2d001d00, 0x4d003d00, 0x67005900, 0x87007700, 0xa7009700, 0xc700b700, 0xe700d700, 0x0701f700, 0x27011701, 0x47013701, 0x67015701, 0x080aaf42, + 0x1e000e2a, 0x3e002e00, 0x68004e00, 0x88007800, 0xa8009800, 0xc800b800, 0xe800d800, 0x0801f800, 0x28011801, 0x48013801, 0x68015801, 0x3208358a, + 0x001f000f, 0x003f002f, 0x0069004f, 0x00890079, 0x00a90099, 0x00c900b9, 0x00e900d9, 0x010901f9, 0x01290119, 0x01490139, 0x01690159, 0x6c61616a, + 0x847e0874, 0x84862005, 0x848e2005, 0x84962005, 0x849e2005, 0x84a62005, 0x84ae2005, 0x84b62005, 0x84be2005, 0x84c62005, 0x84ce2005, 0x84d62005, + 0x84de2005, 0x84e62005, 0x84ee2005, 0x63f62105, 0xfe205f83, 0x09210583, 0x210583d0, 0x0583a20a, 0x83740b21, 0x460c2105, 0x0d210583, 0x20058418, + 0x210583ea, 0x0583bc0e, 0x838e0f21, 0x60102105, 0x11210583, 0x21058332, 0x05840412, 0x0583d620, 0x83a81321, 0x7a142105, 0x15270583, 0x7361634c, + 0x841e1665, 0x84242005, 0x842a2005, 0x84302005, 0x84362005, 0x843c2005, 0x84422005, 0x84482005, 0x844e2005, 0x84542005, 0x845a2005, 0x826b8205, + 0x84662047, 0x846c200b, 0x84722005, 0x64782605, 0x166d6f6e, 0x2005847e, 0x20058484, 0x2005848a, 0x20058490, 0x20058496, 0x2005849c, 0x200584a2, + 0x200584a8, 0x200584ae, 0x200584b4, 0x200584ba, 0x200584c0, 0x200584c6, 0x200584cc, 0x260584d2, 0x617266d8, 0x84de1663, 0x84e82005, 0x84f22005, + 0x83fc2005, 0x06172105, 0x10200584, 0x1a200584, 0x24200584, 0x2e200584, 0x38200584, 0x42200584, 0x4c200584, 0x56200584, 0x60200584, 0x6a200584, + 0x74260584, 0x6c636f6c, 0x05847e17, 0x05848420, 0x05848a20, 0x05849020, 0x05849620, 0x05849c20, 0x0584a220, 0x0584a820, 0x0584ae20, 0x756eb426, + 0xba17726d, 0xc0200584, 0xc6200584, 0xcc200584, 0xd2200584, 0xd8200584, 0xde200584, 0xe4200584, 0xea200584, 0xf0200584, 0xf6200584, 0xfc200584, + 0x18210583, 0x20058402, 0x20058408, 0x2105840e, 0x06826f14, 0x841a1821, 0x84202005, 0x84262005, 0x842c2005, 0x84322005, 0x84382005, 0x843e2005, + 0x84442005, 0x844a2005, 0x84502005, 0x84562005, 0x845c2005, 0x84622005, 0x84682005, 0x846e2005, 0x6f742605, 0x186e6472, 0x2005847a, 0x20058482, + 0x2005848a, 0x20058492, 0x2005849a, 0x200584a2, 0x200584aa, 0x200584b2, 0x200584ba, 0x200584c2, 0x200584ca, 0x200584d2, 0x200584da, 0x200584e2, + 0x260584ea, 0x6c6173f2, 0x83fa1874, 0x00192105, 0x06200584, 0x0c200584, 0x12200584, 0x18200584, 0x1e200584, 0x24200584, 0x2a200584, 0x30200584, + 0x36200584, 0x3c200584, 0x42200584, 0x48200584, 0x4e200584, 0x54260584, 0x666e6973, 0x05845a19, 0x05846020, 0x05846620, 0x05846c20, 0x05847220, + 0x05847820, 0x05847e20, 0x05848420, 0x05848a20, 0x05849020, 0x05849620, 0x05849c20, 0x0584a220, 0x0584a820, 0x0584ae20, 0x7373b426, 0xba193130, + 0xc0200584, 0xc6200584, 0xcc200584, 0xd2200584, 0xd8200584, 0xde200584, 0xe4200584, 0xea200584, 0xf0200584, 0xf6200584, 0xfc200584, 0x1a210583, + 0x20058402, 0x20058408, 0x2005840e, 0x22058214, 0x841a1a32, 0x84202005, 0x84262005, 0x842c2005, 0x84322005, 0x84382005, 0x843e2005, 0x84442005, + 0x844a2005, 0x84502005, 0x84562005, 0x845c2005, 0x84622005, 0x84682005, 0x846e2005, 0x82742005, 0x1a332205, 0x2005847a, 0x20058482, 0x2005848a, + 0x20058492, 0x2005849a, 0x200584a2, 0x200584aa, 0x830584b2, 0x1a3322ef, 0x200b84c2, 0x830584ca, 0x1a3322e9, 0x200b84da, 0x830584e2, 0x1a3322e3, + 0x220b82f2, 0x83fa1a34, 0x001b2105, 0x06200584, 0x0c200584, 0x12200584, 0x18200584, 0x1e200584, 0x24200584, 0x2a200584, 0x30200584, 0x36200584, + 0x3c200584, 0x42200584, 0x48200584, 0x4e200584, 0x54200584, 0x35220582, 0x05845a1b, 0x3522dd83, 0x0b846a1b, 0x05847220, 0x3521d783, 0x21d7831b, + 0xd7831b35, 0x831b3521, 0x1b3521d7, 0x3521d783, 0x21d7831b, 0xd7831b35, 0x831b3521, 0x1b3521d7, 0x3521d783, 0x21d7831b, 0xd7831b35, 0x831b3521, + 0x1b3621d7, 0x3621d783, 0x21d7831b, 0xd7831b36, 0x831b3621, 0x1b3621d7, 0x3622d783, 0x6b82021c, 0x0a1c3622, 0xd1830584, 0x1a1c3622, 0x22200b84, + 0xcb830584, 0x321c3622, 0x3a200b84, 0xc5830584, 0x4a1c3622, 0x52200b84, 0x37210582, 0x21bf831c, 0xbf831c37, 0x6a1c3722, 0xbf831184, 0x831c3721, + 0x1c3721bf, 0x3721bf83, 0x21bf831c, 0xbf831c37, 0x831c3721, 0x1c3721bf, 0x3721bf83, 0x21bf831c, 0xbf831c37, 0x831c3721, 0x1c3721bf, 0x3721bf83, + 0x21bf831c, 0xbf831c37, 0x831c3821, 0x1c3822bf, 0x225982e0, 0x84e61c38, 0x84ec2005, 0x22c58305, 0x84f81c38, 0x83fe200b, 0x041d2105, 0xcb830584, + 0x101d3822, 0x16200b84, 0x1c200584, 0xd1830584, 0x281d3822, 0x2e200b84, 0x34260584, 0x73627573, 0x05843a1d, 0x05844020, 0x05844620, 0x05844c20, + 0x05845220, 0x05845820, 0x05845e20, 0x05846420, 0x05846a20, 0x05847020, 0x05847620, 0x05847c20, 0x05848220, 0x05848820, 0x05848e20, 0x75739426, + 0x9a1d7370, 0xa0200584, 0xa6200584, 0xac200584, 0xb2200584, 0xb8200584, 0xbe200584, 0xc4200584, 0xca200584, 0xd0200584, 0xd6200584, 0xdc200584, + 0xe2200584, 0xe8200584, 0xee200584, 0xf4260584, 0x6d756e74, 0x0583fa1d, 0x84001e21, 0x84062005, 0x840c2005, 0x84122005, 0x84182005, 0x841e2005, + 0x84242005, 0x842a2005, 0x84302005, 0x84362005, 0x843c2005, 0x84422005, 0x84482005, 0x844e2005, 0x7a542605, 0x1e6f7265, 0x2005845a, 0x20058460, + 0x20058466, 0x2005846c, 0x20058472, 0x20058478, 0x2005847e, 0x20058484, 0x2005848a, 0x20058490, 0x20058496, 0x2005849c, 0x200584a2, 0x200584a8, + 0x240584ae, 0x000000b4, 0x20038202, 0x0807fa01, 0x190067d1, 0x1b001a00, 0x1d001c00, 0x1f001e00, 0x21002000, 0x23002200, 0x25002400, 0x27002600, + 0x29002800, 0x2b002a00, 0x2d002c00, 0x2f002e00, 0x31003000, 0x33003200, 0x35003400, 0x37003600, 0x39003800, 0x3b003a00, 0x3d003c00, 0x3f003e00, + 0x41004000, 0x43004200, 0x45004400, 0x47004600, 0x49004800, 0x4b004a00, 0x4d004c00, 0x4f004e00, 0x51005000, 0x53005200, 0x55005400, 0x57005600, + 0x59005800, 0x5b005a00, 0x5d005c00, 0x5f005e00, 0x61006000, 0x63006200, 0x65006400, 0x67006600, 0x69006800, 0x6b006a00, 0x6d006c00, 0x6f006e00, + 0x71007000, 0x73007200, 0x75007400, 0x77007600, 0x79007800, 0x7b007a00, 0x7d007c00, 0x7f007e00, 0x10000000, 0x4d0cd100, 0x0d000125, 0xdb000000, + 0x84052005, 0x2605d75f, 0x00060003, 0x82080007, 0x95094063, 0x17000122, 0x1420ff84, 0x15200584, 0x16200584, 0x12200584, 0x10200584, 0x13200584, + 0x11200584, 0x0e200584, 0x0f200584, 0x04200584, 0x0c2005de, 0x05d75f84, 0x09000224, 0x61820a00, 0x012207f7, 0xdf848000, 0x8c2005d9, 0x05d45f84, + 0x00c83d27, 0x3d810001, 0x200584c2, 0x200584bc, 0x200584b6, 0x200584b0, 0x200584aa, 0x200584a4, 0x2005849e, 0x20058498, 0x20058492, 0x2005848c, + 0x20058486, 0x20058480, 0x2005847a, 0x20058474, 0x2005846e, 0x22058272, 0x846c3d82, 0x84662005, 0x84602005, 0x845a2005, 0x84542005, 0x844e2005, + 0x84482005, 0x84422005, 0x843c2005, 0x84362005, 0x84302005, 0x842a2005, 0x84242005, 0x841e2005, 0x84182005, 0x00202805, 0x00830002, 0x86183d84, + 0x86102007, 0x86082007, 0x85002007, 0xf83c2107, 0xf0200786, 0xe8200786, 0xe0200786, 0xd8200786, 0xd0200786, 0xc8200786, 0xc0200786, 0xb8200786, + 0xb0200786, 0xa8200786, 0xd2200786, 0x85228582, 0x0584cc3c, 0x0584c620, 0x0584c020, 0x0584ba20, 0x0584b420, 0x0584ae20, 0x0584a820, 0x0584a220, + 0x05849c20, 0x05849620, 0x05849020, 0x05848a20, 0x05848420, 0x05847e20, 0x05847820, 0x67828420, 0x87008624, 0x07867c3c, 0x07867420, 0x07866c20, + 0x07866420, 0x07865c20, 0x07865420, 0x07864c20, 0x07864420, 0x07863c20, 0x07863420, 0x07862c20, 0x07862420, 0x07861c20, 0x07861420, 0x07860c20, + 0x07823220, 0x89008824, 0x07862a3c, 0x07862220, 0x07861a20, 0x07861220, 0x07860a20, 0x07850220, 0x86fa3b21, 0x86f22007, 0x86ea2007, 0x86e22007, + 0x86da2007, 0x86d22007, 0x86ca2007, 0x86c22007, 0x86ba2007, 0x82d82007, 0x008a2407, 0x86d03b8b, 0x86c82007, 0x86c02007, 0x86b82007, 0x86b02007, + 0x86a82007, 0x86a02007, 0x86982007, 0x86902007, 0x86882007, 0x86802007, 0x86782007, 0x86702007, 0x86682007, 0x85602007, 0x063c2707, 0x8d000100, + 0x0583003c, 0x0124d382, 0xf43b8d00, 0xee200b84, 0xe8200584, 0xe2200584, 0xdc200584, 0xd6200584, 0xd0200584, 0xca200584, 0xc4200584, 0xbe200584, + 0xb8200584, 0xb2200584, 0xac200584, 0x00200583, 0xbd545983, 0x2005d905, 0xd9658403, 0x840b2005, 0x2005d95f, 0xd55f8418, 0xf5f40905, 0xf401ec01, + 0x0402fc01, 0x14020c02, 0x24021c02, 0x36022c02, 0x48024002, 0x58025002, 0x68026002, 0x78027002, 0x88028002, 0x98029002, 0xaa02a202, 0xba02b202, + 0xdc02ca02, 0x0003ee02, 0x20031203, 0x3e032e03, 0x62035003, 0x88037403, 0xb0039c03, 0xd403c003, 0xfc03ea03, 0x34041e04, 0x5c044804, 0x7c046c04, + 0x94048804, 0xb004a004, 0xd004c004, 0xf004e004, 0x10050005, 0x2e052005, 0x4a053c05, 0x66055805, 0x86057405, 0xa6059405, 0xc605b605, 0xe605d605, + 0x0806f405, 0x28061a06, 0x5c064806, 0x80066e06, 0xa0068e06, 0xbc06ae06, 0xde06ca06, 0xfa06ec06, 0x16070807, 0x32072407, 0x4e074007, 0x6a075c07, + 0x86077807, 0xa2079407, 0xbe07b007, 0xda07cc07, 0xfa07ec07, 0x16080808, 0x36082808, 0x58084808, 0x74086608, 0x8a088208, 0xfa08f008, 0x12090409, + 0x68095a09, 0x84097609, 0x9e099209, 0xb809b009, 0xc809c009, 0xda09d009, 0xea09e209, 0xfc09f409, 0x120a040a, 0x280a200a, 0x380a300a, 0x480a400a, + 0x580a500a, 0x680a600a, 0x780a700a, 0x880a800a, 0x980a900a, 0xa80aa00a, 0xb80ab00a, 0xc80ac00a, 0xd80ad00a, 0xe80ae00a, 0xf80af00a, 0x080b000b, + 0x180b100b, 0x280b200b, 0x380b300b, 0x480b400b, 0x580b500b, 0x680b600b, 0x780b700b, 0x880b800b, 0x980b900b, 0xa80ba00b, 0xb80bb00b, 0xc80bc00b, + 0xd80bd00b, 0xe80be00b, 0xf80bf00b, 0x080c000c, 0x180c100c, 0x280c200c, 0x380c300c, 0x480c400c, 0x580c500c, 0x680c600c, 0x780c700c, 0x880c800c, + 0x980c900c, 0xa80ca00c, 0xb80cb00c, 0xc80cc00c, 0xd80cd00c, 0xe80ce00c, 0xf80cf00c, 0x080d000d, 0x180d100d, 0x280d200d, 0x380d300d, 0x480d400d, + 0x580d500d, 0x0100600d, 0x01000000, 0x03004c38, 0x39210783, 0x210f85ac, 0x07866c0b, 0x07868620, 0x0786a220, 0x0786be20, 0x0786da20, 0x0600d822, + 0x02243782, 0xe80bd60b, 0xf0240986, 0x0400020c, 0x01221382, 0x23850a0c, 0x86160c21, 0x86142007, 0x862a2007, 0x21638607, 0x0f866a0c, 0x07866820, + 0x07866e20, 0x07867420, 0x07867220, 0x61858620, 0x0c840c23, 0x20118698, 0x206986a2, 0x200f86a0, 0x202184b6, 0x26ff8205, 0x0cdc0cca, 0x84040df0, + 0x8206200f, 0x821c20fb, 0x0d4624f5, 0x86720d5c, 0x0d762a11, 0x0d9e0d8a, 0x0dca0db4, 0x2a1186e0, 0x0ef60de4, 0x0e1a0e08, 0x85420e2e, 0x440e2b11, + 0x680e560e, 0x8e0e7a0e, 0x1184a20e, 0xa40e0428, 0xc40eb40e, 0x0d86d60e, 0xea0eda26, 0x0c0ffa0e, 0x052a0d84, 0x220f100f, 0x480f340f, 0x0f845c0f, + 0x600f062c, 0x840f720f, 0xaa0f960f, 0x1186be0f, 0xd20fc02a, 0xf60fe40f, 0x1e100a10, 0x102a1185, 0x10301020, 0x10501040, 0x97851060, 0x7210072e, + 0x92108210, 0xb210a210, 0xd410c210, 0x072e2584, 0xe210d210, 0x0211f210, 0x22111211, 0x13853411, 0x1132112d, 0x115a1146, 0x11861170, 0x84b2119c, + 0x11052a13, 0x11c611b4, 0x12ec11d8, 0x2e0f8400, 0x12041207, 0x12281216, 0x124c123a, 0x84741260, 0x12083013, 0x12861274, 0x12ac1298, 0x12d012be, + 0x84f812e4, 0x12062c15, 0x130813f6, 0x132e131a, 0x84561342, 0x130e3c11, 0x136a1358, 0x1390137c, 0x13ba13a6, 0x13de13cc, 0x140414f2, 0x142a1416, + 0x8452143e, 0x14083021, 0x14561444, 0x147c1468, 0x14a41492, 0x84cc14b8, 0x14072e15, 0x14dc14ca, 0x150215ee, 0x152c1518, 0x2d138540, 0x52154015, + 0x76156415, 0x9c158815, 0x1384b015, 0xb015052a, 0xd415c215, 0xfc15e815, 0x16290f85, 0x16121600, 0x16381624, 0x260f844c, 0x16501603, 0x86781664, + 0x1680240b, 0x86a81694, 0x16b0230b, 0x734216c4, 0x16052a05, 0x17f216e0, 0x17181704, 0x2a1b842c, 0x17301705, 0x17541742, 0x867c1768, 0x1780270f, + 0x17a41792, 0x9b8517b8, 0xd017052a, 0xf417e217, 0x1c180818, 0x18291f85, 0x18321820, 0x18581844, 0x280f866c, 0x18821870, 0x18a81894, 0x270f86bc, + 0x18d218c0, 0x19f818e4, 0x2806e141, 0x22191019, 0x48193419, 0x05e14119, 0x60190428, 0x80197019, 0x2d849219, 0x96190428, 0xb619a619, 0x0d86c819, + 0xdc19cc26, 0xfe19ec19, 0x1a260d85, 0x1a121a02, 0xbb411a22, 0x1a042805, 0x1a481a38, 0x866a1a58, 0x1a6e261b, 0x1a8e1a7e, 0x2c0d84a0, 0x1aa41a06, + 0x1ac41ab4, 0x1ae41ad4, 0x281184f6, 0x1bf61a04, 0x1b161b06, 0x2c0d8428, 0x1b2c1b06, 0x1b4c1b3c, 0x1b6c1b5c, 0x2a11847e, 0x1b7e1b05, 0x1b9e1b8e, + 0x86c01bae, 0x1bc2270f, 0x1be21bd2, 0xfb421cf2, 0x1c052a05, 0x1c161c06, 0x1c361c26, 0x291f8548, 0x5a1c4a1c, 0x7a1c6a1c, 0x0f848c1c, 0x8e1c0427, + 0xae1c9e1c, 0x2d3d851c, 0x1cc41c07, 0x1ce41cd4, 0x1d061df6, 0x73861d16, 0x1d261d2b, 0x1d461d36, 0x1d681d58, 0x2733857a, 0x8a1d7a1d, 0xac1d9a1d, + 0x0d390d84, 0xc01db01d, 0xe21dd01d, 0x081ef61d, 0x281e181e, 0x4a1e3a1e, 0x6c1e5a1e, 0x2da1851e, 0x1e701e07, 0x1e901e80, 0x1eb61ea2, 0xbb411ec6, + 0x1e062c05, 0x1ee61ed6, 0x1f081ff6, 0x842e1f1c, 0x1f062c45, 0x1f3e1f2e, 0x1f5e1f4e, 0x84801f6e, 0x1f042811, 0x1f901f80, 0x84b21fa0, 0x1f062c0d, + 0x1fc61fb6, 0x1fe61fd6, 0x840820f6, 0x20042811, 0x20182008, 0x863a2028, 0x203e260d, 0x205e204e, 0x260d8670, 0x20842074, 0x84a62094, 0x20072e0d, + 0x20ba20aa, 0x20dc20ca, 0x21fc20ec, 0x2813840e, 0x210c2104, 0x212c211c, 0x250d863e, 0x21522142, 0x25432162, 0x21042805, 0x21882178, 0x86aa2198, + 0x21ae251b, 0x21ce21be, 0x28052744, 0x21e42104, 0x220422f4, 0x261b8516, 0x2a221a22, 0x42223a22, 0x042805b5, 0x60225022, 0x82227022, 0x86261b86, + 0xa6229622, 0x0d86b822, 0xcc22bc26, 0xee22dc22, 0xf2260d86, 0x12230223, 0x0d852423, 0x23282327, 0x23482338, 0x260d865a, 0x236e235e, 0x8690237e, + 0x2394260d, 0x23b423a4, 0x250d86c6, 0x23da23ca, 0x354323ea, 0x24042805, 0x24102400, 0x85322420, 0x3624271b, 0x56244624, 0x0d866824, 0x7c246c26, + 0x9e248c24, 0xa2250d86, 0xc224b224, 0x05514424, 0xd824062c, 0xf824e824, 0x18250825, 0x1f852a25, 0x252a2526, 0x254a253a, 0x2606d942, 0x70256025, + 0x42258025, 0x252606d9, 0x25a62596, 0xd94225b6, 0x25062c05, 0x25dc25cc, 0x26fc25ec, 0x851e260c, 0x1e26273b, 0x3e262e26, 0x0d845026, 0x5426062b, + 0x74266426, 0x94268426, 0x057d4126, 0xa626052a, 0xc826b626, 0xec26da26, 0x04282184, 0xfe26ee26, 0x20270e27, 0x27260d85, 0x27342724, 0x77442744, + 0x27043005, 0x276e275a, 0x00962782, 0x00000002, 0x849c2701, 0x305f0823, 0xbe27ac27, 0xe027ce27, 0x0628f427, 0x32281c28, 0x5e284828, 0x8a287428, + 0xb628a028, 0xde28ca28, 0x0629f228, 0x2e291a29, 0x56294229, 0x7e296a29, 0xa6299229, 0xce29ba29, 0xf229e029, 0x162a042a, 0x3e2a2a2a, 0x662a522a, + 0x8e2a7a2a, 0xb62aa22a, 0xdc2acc2a, 0x042bf02a, 0x282b162b, 0x412b3a2b, 0x022405bd, 0x0a2bf82a, 0x02236f84, 0x412b122b, 0x2b270699, 0x2b3e2b2c, + 0x84642b50, 0x21410817, 0x7c2b6a2b, 0x9e2b8c2b, 0xc42bb22b, 0xf02bda2b, 0x1c2c062c, 0x482c322c, 0x702c5c2c, 0x982c842c, 0xc02cac2c, 0xe82cd42c, + 0x0e2dfc2c, 0x322d202d, 0x5a2d462d, 0x822d6e2d, 0xaa2d962d, 0xce2dbc2d, 0x0643422d, 0xba240d82, 0xdc2dca2d, 0x04285584, 0xf02de02d, 0x122e002e, + 0x2e260d85, 0x2e262e16, 0xad432e36, 0x2e042705, 0x2e5c2e4c, 0x49432e6c, 0x2e032605, 0x2e962e82, 0x2c2784a8, 0x2eae2e06, 0x2ed82ec2, 0x2ffe2eec, + 0x05fd4612, 0x14200788, 0x16200f86, 0xef440786, 0x2f022405, 0x86302f1e, 0x863c2011, 0x84462007, 0x2f02234b, 0x7f412f44, 0x2f012205, 0x22118462, + 0x846a2f01, 0x2f042707, 0x2f882f78, 0x09432f98, 0xae2f2706, 0xce2fbe2f, 0x3d86e02f, 0x0785e420, 0x85023021, 0x86342007, 0x3a342155, 0x21059547, + 0x17864034, 0x07865620, 0x07865a20, 0x0f8e5c20, 0x178e5e20, 0x0f866020, 0x07866220, 0x64200f8f, 0x66201786, 0x68200786, 0x6a200786, 0x6c200786, + 0x76200786, 0x78200786, 0x7a200786, 0x1f870f8e, 0x1f8e7420, 0x0f867c20, 0x07868020, 0x07868420, 0x07868820, 0x07868c20, 0x07869a20, 0x0f969c20, + 0x17869e20, 0x0786a020, 0x0786a220, 0x0786a820, 0x0786b020, 0x0786ba20, 0x0786bc20, 0x0786c420, 0x0786ca20, 0x0786c820, 0x0f96c620, 0x1786ce20, + 0x0786cc20, 0x21069741, 0x0f86f034, 0x0786f620, 0x0786f420, 0x0786fa20, 0x0786f820, 0x0786fe20, 0x0f8dfc20, 0x85043521, 0x4135200f, 0x352106df, + 0x200f860a, 0x2007860e, 0x8707860c, 0x870f8717, 0x8610201f, 0x069f421f, 0x86143521, 0x861a200f, 0x86202007, 0x86222007, 0x86242007, 0x86262007, + 0x862c2007, 0x862e2007, 0x06bd4207, 0x86323521, 0x8634200f, 0x06774207, 0x85183621, 0x8636200f, 0x1c36215f, 0x1e200f86, 0x67860786, 0x86243621, + 0x8626200f, 0x86282007, 0x862c2007, 0x862e2007, 0x206f8607, 0x216f8636, 0x17863636, 0x07863820, 0x2106df42, 0x0f863e36, 0x179e4220, 0x1f864420, + 0x07864620, 0x00482208, 0x004a3602, 0x03ae030e, 0x03b003af, 0x03b203b1, 0x03b403b3, 0x03b603b5, 0x040804b7, 0x04ea0409, 0x082182ba, 0x0f003e20, + 0xcd03cc03, 0xcf03ce03, 0xd103d003, 0xd303d203, 0xd503d403, 0x15041404, 0xbb04eb04, 0x2382ad04, 0x23821a20, 0x03c22008, 0x03c403c3, 0x03c603c5, + 0x03c803c7, 0x03ca03c9, 0x047304cb, 0x06b10674, 0x00b306b2, 0x82f63502, 0xb8220823, 0xba03b903, 0xbc03bb03, 0xbe03bd03, 0xc003bf03, 0x4404c103, + 0x82064504, 0x84068306, 0xee350100, 0x0583e1ff, 0x002b0023, 0x20078203, 0x240382f2, 0x000000f8, 0x20038201, 0x2011848e, 0x201182f0, 0x20118ce6, + 0x201182c4, 0x201186e8, 0x2023848f, 0x201182b2, 0x261188de, 0x00d43501, 0x82080001, 0x06042803, 0x00030042, 0x82e703d5, 0x00c6221f, 0x3a918205, + 0x010c00c6, 0x03a2031c, 0x03a503a4, 0x03a703a6, 0x03a903a8, 0x03ab03aa, 0x82a303ac, 0xb846081d, 0xf8032200, 0x1604f903, 0x18041704, 0x1a041904, + 0x2d041b04, 0x2f042e04, 0x40043004, 0x42044104, 0x04054304, 0x0f070e07, 0x11071007, 0x13071207, 0x15071407, 0x17071607, 0x19071807, 0x20071a07, + 0x31072f07, 0x6d823f07, 0x0600b622, 0xb0200582, 0x022c0582, 0x0400b035, 0x68006200, 0xf300ed00, 0xa2206382, 0x01220d8a, 0x21848e35, 0x0b009a38, + 0x85008400, 0x87008600, 0x0f018800, 0x11011001, 0x13011201, 0x43821b07, 0x21826c20, 0xdb820320, 0x92350224, 0x0f829835, 0x01009222, 0x90200d82, + 0x0026d782, 0x8a350200, 0x13828435, 0x13868a20, 0x3e350122, 0x76267784, 0x0a000200, 0x15821400, 0xd0000422, 0xce200b82, 0x0228098a, 0x02006035, + 0xad03a103, 0x01224182, 0x3d825e35, 0x47825e20, 0x6a356422, 0x03205582, 0x012a0382, 0x03004c35, 0x58355235, 0x11845835, 0x0b820220, 0x01004c24, + 0x0d824635, 0x03820120, 0x37849120, 0x11823820, 0x03822c20, 0x8305a742, 0x82002013, 0x8212200d, 0x35182149, 0x8505fb42, 0x82042027, 0x82042015, + 0x3504244f, 0x820a3504, 0x2561843d, 0x0400f034, 0x0182f034, 0xf634f622, 0x03221384, 0x0183ee34, 0x34010023, 0x286586e2, 0x00030092, 0x34d83402, + 0x201382d8, 0x200382c6, 0x83e184cc, 0x34012215, 0x200f82c2, 0x221d82b0, 0x88b634b0, 0x257d8215, 0x03009a34, 0x01829a34, 0x1588a020, 0x7e340122, + 0x7e202b82, 0x84211782, 0x88018234, 0x826a207f, 0x3470217f, 0x13840184, 0x6e340322, 0x68200182, 0x5c202b82, 0x01200f82, 0x93200382, 0x58227f84, + 0x13825234, 0x03854620, 0x94201582, 0x01221582, 0x0f823c34, 0x7f823020, 0x30343023, 0x832b8300, 0x207f8315, 0x21678214, 0x0182341a, 0x01221588, + 0x2b820434, 0x2b820420, 0x88340421, 0xf23329fd, 0xf2330300, 0xf833f833, 0x03245182, 0xda330100, 0xe0260382, 0xe0330200, 0x1184e633, 0xe0200983, + 0xd4201382, 0x5f870d82, 0xcc330122, 0xba201182, 0xc0200382, 0x73825d88, 0x82a63321, 0x33a62237, 0x221388ac, 0x828c3301, 0x828c2023, 0x33922215, + 0x834d8492, 0x827a2025, 0x33802171, 0x11880182, 0x11826820, 0x6e336e24, 0x11847433, 0x09820220, 0x3320fd82, 0x9521fd87, 0x20978300, 0x20498254, + 0x82038548, 0x82962025, 0x204b8313, 0x225b822e, 0x84343334, 0x22138371, 0x82203301, 0x20038323, 0x205d8826, 0x22238210, 0x84163316, 0x3301220f, + 0x201f8212, 0x830b8206, 0x254586cb, 0x0100ee32, 0x4389f432, 0x82d63221, 0x2003830f, 0x203384dc, 0x260d8200, 0x320200c6, 0x84cc32cc, 0x3201220f, + 0x201182c8, 0x830b82bc, 0x85972043, 0xa4322189, 0xaa201382, 0x11834384, 0x98320122, 0x98200f82, 0x98203582, 0x00200982, 0x86242386, 0x86320300, + 0x3b820183, 0x1b820320, 0x25820b82, 0x0120f583, 0x98211182, 0x21e78200, 0x11827232, 0x03856020, 0x99201382, 0x4c203986, 0x4c222d82, 0x5f844c32, + 0x01221383, 0x23823e32, 0x15823e20, 0x09823e20, 0x2c205f87, 0x2c215f82, 0x82018232, 0x204b8339, 0x2023822c, 0x2223821a, 0x841a321a, 0x32022411, + 0x82243224, 0x82082013, 0x8601200d, 0x3201255d, 0x31010010, 0x0383fd82, 0x9a201382, 0x31257185, 0x310200e0, 0x830582e0, 0x22138327, 0x82c03101, + 0x82c02027, 0x82c02015, 0x25718609, 0x0300ae31, 0x0183ae31, 0x03203982, 0x01220382, 0x11829c31, 0x9c319c24, 0x1184ba31, 0x09820220, 0x01009c24, + 0x71868a31, 0x88204985, 0x76201182, 0x17820385, 0x71869b20, 0x5b826220, 0x62316222, 0x1383e384, 0x54310122, 0x03852382, 0x44206f87, 0x44222382, + 0x35824431, 0x3121df82, 0x201f825c, 0x87038434, 0x8224201f, 0x3124221f, 0x201f864c, 0x201b8226, 0x200b8214, 0x20658a01, 0x82138202, 0x82118203, + 0x010023a9, 0x0388f630, 0x30254386, 0x300200e6, 0x830582e6, 0x3001220f, 0x201f82e8, 0x890384d6, 0x82c6200f, 0x84c6200f, 0x82002063, 0x82b62009, + 0x30b6222f, 0x220f84d8, 0x82c23001, 0x86a62011, 0x83618373, 0x82942021, 0x82038213, 0x009d2215, 0x820b8203, 0x853020fb, 0x20738703, 0x22438266, + 0x88663066, 0x82562053, 0x3056220f, 0x200f8474, 0x22078201, 0x82463001, 0x88462037, 0x8236201f, 0x3036221f, 0x220f8464, 0x82383001, 0x8626201b, + 0x83618373, 0x82142073, 0x82038213, 0x849e2015, 0x82022073, 0x0002280f, 0x30383003, 0x823e303e, 0x82032015, 0x2f012803, 0x300400ee, 0x832a3024, + 0x28138401, 0x30223002, 0x2f01001c, 0x232982da, 0x30163010, 0x26053543, 0x30183003, 0x82d62f12, 0x21248241, 0x53860100, 0xfc2f0224, 0x2b82c02f, + 0x0385ea20, 0x9f221582, 0x0b820300, 0x0382aa20, 0x0200ce26, 0xd42fd42f, 0x15832b84, 0x13820020, 0x03008228, 0xbe2fb82f, 0x1588be2f, 0xc62f0122, + 0xc6201782, 0xc6222b82, 0x9388782f, 0x2782b420, 0x662fb424, 0x1184662f, 0xa82f0224, 0x2582a82f, 0x0d825420, 0x63857983, 0x11829420, 0x03828e20, + 0x618c4020, 0x49827a20, 0x2c2f7a22, 0x01221388, 0x2382722f, 0x15827220, 0x09827220, 0x67420020, 0x602f2105, 0x60215f82, 0x8201822f, 0x21af8251, + 0x2382fc2d, 0x23824e20, 0x4e2f4e22, 0x3c208388, 0x3c242382, 0xea2d3c2f, 0x02241184, 0x302f302f, 0x2a202582, 0x1c20838c, 0x16201182, 0x17820385, + 0x5d86a020, 0x49820220, 0x422f0221, 0x13830561, 0xfa2e0123, 0x22038300, 0x82fa2e02, 0x25838609, 0x0300e82e, 0x0183e82e, 0x03263982, 0xac2e0200, + 0x2582a62e, 0x0982d620, 0xd62ed622, 0x00201384, 0xc2200f82, 0xc2242582, 0xc82ec22e, 0x01221184, 0x1382b62e, 0x2382b020, 0xb02eb022, 0xac203788, + 0x9e201382, 0x6f859786, 0x11829820, 0x03858a20, 0xa1201782, 0x2e219785, 0x20378276, 0x20058276, 0x22138601, 0x82622e01, 0x82622023, 0x82622015, + 0x20978715, 0x23718250, 0x2e642e50, 0x24055942, 0x2e142e02, 0x2025820e, 0x2225823e, 0x82522e3e, 0x22ab8339, 0x84382e38, 0x88a18213, 0x8224204b, + 0x82162011, 0x002a2103, 0x1d825f87, 0x82022e21, 0x2e022137, 0x27881782, 0x23820220, 0x02201585, 0x00284d84, 0xf02d0100, 0xf02d0300, 0x11840183, + 0xa02d0224, 0x15829a2d, 0x0200de26, 0xde2dde2d, 0x03261384, 0x8c2d442d, 0x1582862d, 0x1582ca20, 0xca2dca22, 0x02241584, 0x2e2d762d, 0xb4201382, + 0xb4221382, 0x1384b42d, 0xa62d0122, 0xa0201182, 0xa0221182, 0x6188a02d, 0x61828e20, 0x8e2d8e22, 0xe7835782, 0x09820220, 0x25827c20, 0x25827c20, + 0x7c2d7c22, 0x01222584, 0x1182822d, 0x11826820, 0x682d6822, 0x56203788, 0x56243782, 0x702d562d, 0x44221188, 0x8b820400, 0x13824420, 0x13844420, + 0x09820220, 0x39825620, 0x0d823020, 0xa222f983, 0x0d820300, 0x03824220, 0x03851c20, 0xa3201782, 0x21058141, 0x5d82082d, 0x05820820, 0x13832783, + 0xa42c0123, 0x24038300, 0x2cf42c02, 0x202782f4, 0x26038203, 0x00922c01, 0x83e22c03, 0x2e118401, 0x2c922c02, 0x2c01008c, 0x2c020080, 0x84d02cd0, + 0x2c032613, 0x2c7e2c36, 0x20158278, 0x2215826c, 0x84bc2cbc, 0x2c012215, 0x201182a6, 0x20118256, 0x840982a6, 0xba2c23e7, 0x13825c2c, 0x9b869420, + 0x8200a421, 0x482c219b, 0x51834d84, 0x17820120, 0x9b85a520, 0x821c2c21, 0x2c6c2337, 0x1387006c, 0x082c0122, 0xb1822782, 0x2c082c23, 0x84278284, + 0xf62b299b, 0xf62b0300, 0x722c722c, 0x022e1184, 0xf02bf62b, 0xe42b0100, 0xe42b0200, 0x1384602c, 0x9a2b0326, 0xdc2be22b, 0xd0201582, 0xd0221582, + 0x15844c2c, 0xd22b0224, 0x4f82d22b, 0x0d823620, 0x2b216188, 0x832582be, 0x882220b3, 0x82002075, 0x82922011, 0x2c922137, 0x8305414d, 0x2b01229d, + 0x20158284, 0x20158284, 0x20098284, 0x21af8500, 0x8982722b, 0x822b7221, 0x82518201, 0x207184d5, 0x21238260, 0x87852b60, 0x4e204983, 0x4e232382, + 0x422b4e2b, 0x2b23062d, 0x82542b54, 0x8c3c2049, 0x82402083, 0x85282011, 0x20178203, 0x205d86a6, 0x22498214, 0x84142b14, 0x23138397, 0x00c42a01, + 0x02240383, 0x1e2b1e2b, 0x03202782, 0x01220382, 0x5f82b22a, 0x822b0c21, 0x22118401, 0x82002b02, 0x2a012211, 0x200d82fa, 0x264b8601, 0x009e2a01, + 0x85e62a01, 0x20138203, 0x285f85a7, 0x0200782a, 0xd22ad22a, 0x83278300, 0x2a012213, 0x20238264, 0x21158264, 0x6b422abe, 0x522a2908, 0xac2a0300, + 0x5e2a5e2a, 0x03203982, 0xa0201b82, 0x01221182, 0x0d824c2a, 0x3e203789, 0x86203782, 0x38200382, 0x00204b88, 0x18200d82, 0x72222d82, 0x1388242a, + 0x702a0224, 0x1782162a, 0x3b861020, 0x0300a822, 0x02200d82, 0x56240382, 0xfc290100, 0xa8202784, 0x29279b85, 0x2a0200dc, 0x88e82942, 0x2a022413, + 0x82da298a, 0x86d42025, 0x82a9203b, 0x29012227, 0x203b82c6, 0x2115827c, 0x8b8300c0, 0x00201383, 0xa0200d82, 0x68223b82, 0x1388ac29, 0x5a2a0224, + 0x17829e29, 0x3b869820, 0x3b84aa20, 0x3b828a20, 0x15824c20, 0x27848420, 0x3b831383, 0x3822fd83, 0x13887029, 0x50290122, 0x50262382, 0x64280200, + 0x3f825c29, 0x03820320, 0x3e29012a, 0x52280300, 0x4a294a29, 0x02221184, 0x1182062a, 0x38290122, 0x01200d82, 0xab200382, 0x2a285f84, 0x2c280100, + 0x24290100, 0x13834b84, 0x04205f83, 0x18224982, 0x13881029, 0xd0290122, 0xd0262382, 0xd6290200, 0x5f883229, 0x0300be28, 0x2029c429, 0x11842029, + 0xbe290224, 0x2582b829, 0x5f8c0e20, 0x1182a420, 0x2821d582, 0x205f8cfa, 0x22498284, 0x88e6288a, 0x29012213, 0x20278242, 0x22158242, 0x88162942, + 0x8230205f, 0x2930245f, 0x84042904, 0x29022411, 0x82642964, 0x8cf220ad, 0x20f7835f, 0x2015820a, 0x204b88de, 0x200d8200, 0x21bf82f6, 0x115128f6, + 0x21e78405, 0x1582e228, 0x1582e220, 0x3028e222, 0x25834d84, 0x0300d027, 0x1e28d028, 0x05a54228, 0x69840220, 0x0c280122, 0x01201f82, 0xac220382, + 0x33820300, 0x0382f020, 0x0100aa24, 0x5f84f827, 0x39831383, 0x49829620, 0xe4279622, 0x01221388, 0x27828228, 0x15828220, 0x09828220, 0x1d420020, + 0x70282105, 0x70215f82, 0x82018228, 0x8203204d, 0x28a4221b, 0x202582a4, 0x200d825e, 0x20038201, 0x205f84ad, 0x20118290, 0x8203854a, 0x86ae2013, + 0x82362039, 0x2836222d, 0x835f8436, 0x28012213, 0x20238244, 0x20158244, 0x87098244, 0x8232205f, 0x2832215f, 0x39820182, 0x1a225f83, 0x25821a28, + 0x0d822020, 0x4b860120, 0x06280122, 0x0c201182, 0x13820385, 0x5f85af20, 0x0222cd82, 0xd386f827, 0x01231383, 0x83002426, 0x26022203, 0x20098224, + 0x25258500, 0x03001226, 0x01831226, 0x5f823982, 0x27c62723, 0x822582c6, 0x8497840c, 0xb2272537, 0xec250100, 0x18820385, 0x3985b020, 0x00d82525, + 0x82d82502, 0x86012005, 0x27012313, 0x038300ae, 0xae270222, 0x5f860982, 0x009c2725, 0x839c2703, 0x83258201, 0x2790225f, 0x4a258290, 0x4b8307fd, + 0x7c270122, 0x76201182, 0x25820385, 0x5f85b120, 0x00622725, 0x82622702, 0x86012005, 0x27012213, 0x8523825a, 0x205d8703, 0x2123824a, 0xfb42274a, + 0x27012205, 0x201f8240, 0x872d823a, 0x82002031, 0x8528200f, 0x20158203, 0x225782b2, 0x82222701, 0x2003820f, 0x087d4d26, 0x00122727, 0x26822602, + 0x20218282, 0x201b8203, 0x20fd8208, 0x83438672, 0x21438231, 0x1382f026, 0x83006021, 0x20438455, 0x853f8326, 0x09454103, 0x43410220, 0x26012208, + 0x202f8208, 0x20438d02, 0x83438225, 0x21158203, 0x678200b3, 0x00de2523, 0x21038301, 0x1182a626, 0x03820320, 0xce250122, 0x96228782, 0x0f849626, + 0xc4250122, 0x86204382, 0x31834386, 0x25218782, 0x201382ac, 0x85878474, 0x009a2343, 0x03832501, 0x43884c20, 0x02008a26, 0x3c253c25, 0x01220f84, + 0x1f828025, 0x438e2c20, 0x13826820, 0x438a1a20, 0x0f825620, 0x38200383, 0x46204388, 0x28224382, 0x0f842825, 0x4b820120, 0x18250122, 0x2420438e, + 0x06203382, 0x1e20438a, 0x03850f82, 0xbb410020, 0x0e252105, 0x0e204382, 0x0f830582, 0x82230121, 0xfe2423b7, 0x03820100, 0x24271f86, 0x240200ee, + 0x829c23ee, 0x82032057, 0x82e42017, 0x071f5203, 0x2421eb86, 0x821382cc, 0x21218203, 0x238300b4, 0x0f82ba20, 0xcd460383, 0xaa242108, 0x50224382, + 0x21825024, 0xa0201f83, 0x40201f82, 0x01200b82, 0x00203186, 0x88200f82, 0x2e200382, 0x4385a784, 0x0f827620, 0x23210382, 0x83338424, 0x00662621, + 0x23142302, 0x220f8414, 0x82042301, 0x0056211f, 0xa7870783, 0x02004626, 0x4624f422, 0x24251f85, 0x2201003c, 0x20638ee4, 0x20138224, 0x216389d2, + 0x3f82b223, 0x24210382, 0x823384d4, 0xa2232163, 0xc422a782, 0x0f84c424, 0x82240121, 0x922321c3, 0xb4206782, 0x23210f85, 0x200b8294, 0x21538da4, + 0x13827023, 0xc9862382, 0x5e230122, 0x03835382, 0x83057b4b, 0x824e2053, 0x23da22b7, 0x204386da, 0x201f82c4, 0x4703823e, 0x012205d7, 0x0b824023, + 0x538eba20, 0x13821c20, 0xa789a820, 0x82322421, 0x21038263, 0x0b410a23, 0x82222008, 0x22fa22eb, 0x200f88fa, 0x220f8212, 0x840c24ea, 0x2401220f, + 0x83e78208, 0x8201206f, 0x41b5200f, 0x232105e5, 0x201382f0, 0x835384c8, 0x23012211, 0x8263823c, 0xb6222103, 0x2c20fb88, 0xa6214382, 0x08e34222, + 0x821c2321, 0x2396220f, 0x221f8422, 0x82ba2301, 0x8286203f, 0x2053830b, 0x825385b6, 0x2201227f, 0x83538474, 0x22012211, 0x822382ee, 0x205b8203, + 0x20218600, 0x22fb82de, 0x822c232c, 0x82032037, 0x827c206f, 0x8e1c2003, 0x82bc2043, 0x8a0a2013, 0x828a2043, 0x87038543, 0x827a2043, 0x227a2287, + 0x2443847a, 0x22402202, 0x2021823a, 0x8703846a, 0x82582021, 0x22582221, 0x2221845e, 0x824e2201, 0x8448201b, 0x221f8303, 0x82462201, 0x8e38200b, + 0x82262075, 0x82038213, 0x00b72215, 0x200b8203, 0x20038614, 0x20118228, 0x22038203, 0x82042201, 0x22182253, 0x2c0f8418, 0x21ca2102, 0x210100c4, + 0x220100f4, 0x22118408, 0x82f62101, 0x82e2200f, 0x86f62003, 0x82e0200f, 0x86e6200b, 0x20538365, 0x200f8200, 0x220382c0, 0x880100d4, 0x82042065, + 0x2103823f, 0x33844821, 0xf4252183, 0x38210200, 0x829d8321, 0xde212185, 0x81832f82, 0x21833187, 0x1382d220, 0x43891620, 0x827e2121, 0x2003850f, + 0x05634100, 0x826e2121, 0x826e2043, 0x240f8305, 0x21202102, 0x2021821a, 0x8303845e, 0x20032611, 0x210e21c6, 0x200f8208, 0x8403844c, 0xfa202325, + 0x0d82b220, 0x03843820, 0x01221183, 0x0b822c21, 0x03842620, 0x16205787, 0x16215782, 0x05ff4121, 0x18210224, 0x1d820621, 0x31850385, 0x01000e24, + 0x0384f420, 0x20273186, 0x200200e4, 0x87fe20e4, 0xd42027dd, 0xd4200300, 0x0782e620, 0x20213184, 0x202d82e8, 0x201d82c2, 0x20038201, 0x21bd85b8, + 0x1382b020, 0x11820382, 0x1182b920, 0x4e200122, 0x03830f82, 0x45889e20, 0x55823e20, 0x8e208e22, 0x02240f84, 0x3a204020, 0x2e202182, 0x7e200382, + 0x03261184, 0x2e20e61f, 0x0f822820, 0x03821c20, 0x13846c20, 0x58200122, 0x08200b82, 0x58200382, 0x10200f86, 0x48200b82, 0xba207986, 0x1f217985, + 0x211382e6, 0x8b830036, 0x01231183, 0x8700d41f, 0x86002003, 0x00c42521, 0x1fc41f02, 0x24050d44, 0x1fc61f02, 0x202182c0, 0x830384b4, 0x1f032621, + 0x1fb41f6c, 0x200f82ae, 0x840384a2, 0xa61f21e3, 0xab830b82, 0x6d820120, 0x4786bb20, 0x13827c20, 0x11820382, 0x1182bc20, 0x401f0122, 0x03830f82, + 0x1182ba20, 0x03820320, 0x301f0122, 0xaa226982, 0x0f84aa1f, 0x9a1f0126, 0x201f0100, 0x9a200382, 0x10201f88, 0x8a211f82, 0x063b4720, 0x821c1f21, + 0x827a201b, 0x8601201b, 0x00002451, 0x82ee1e01, 0x00682113, 0x01221187, 0x0f820c1f, 0x2a200383, 0x1e214387, 0x224382fc, 0x841a1f1a, 0x1f01220f, + 0x201f8204, 0x20438e0a, 0x204782da, 0x214389f8, 0x0f82c81e, 0xdb830385, 0xb8266583, 0xb81e0200, 0x4386b81e, 0x1f822420, 0x0384a820, 0x98201f87, + 0x98211f82, 0x06a3451f, 0x82a01e21, 0x8288201b, 0x8201202b, 0x41bd2003, 0x1e21050b, 0x82138276, 0x20118203, 0x221182be, 0x82281e01, 0x2003830f, + 0x20a78882, 0x22438218, 0x84721e72, 0x1e01220f, 0x201f821a, 0x83438662, 0x21858231, 0x1382f61d, 0x83005021, 0x23438455, 0x0100e41d, 0x1e200383, + 0x83051f41, 0x82d42021, 0x1e3a2243, 0x2143853a, 0x2f82d61d, 0x438e2a20, 0x1382b220, 0x438a1820, 0x1d20ab82, 0x3f4faf83, 0x901d2108, 0x58214382, + 0x0641421e, 0x82921d21, 0x8e48202f, 0x826e2043, 0x8a362013, 0x825c2043, 0x20038387, 0x837784e2, 0x004c2687, 0x1dd21d02, 0x240f84d2, 0x1d841d02, + 0x2021827e, 0x2003823c, 0x221184c2, 0x82b01d01, 0x822a200b, 0x88b02003, 0x821a2031, 0x1ea02231, 0x220f8460, 0x821c1d01, 0x8d90201b, 0xf81c2175, + 0x47821382, 0x23074141, 0x0100e61c, 0xf2200384, 0x75823384, 0x00d61c26, 0x1ce21c02, 0x01228585, 0x1f82d81c, 0x2f418183, 0x20218307, 0x201382b4, + 0x21b989c0, 0x0f82a21c, 0x1d210382, 0x20438876, 0x22878292, 0x84661d66, 0x1c01220f, 0x20738294, 0x20878e56, 0x20138270, 0x20438a44, 0x8243825e, + 0x411b2003, 0x658305b9, 0x02004e26, 0x621b621b, 0x50244386, 0x521b0100, 0x2c20438e, 0x40201382, 0xfa20438a, 0x03824382, 0x21451d20, 0xea1c2108, + 0x38228782, 0x4386381d, 0x1d21eb82, 0x20438e28, 0x208782c8, 0x20438a16, 0x834382b6, 0x83778503, 0x00a62587, 0x1c521c02, 0x03207b83, 0x1c21e785, + 0x20438e42, 0x20178284, 0x20438a30, 0x830f8272, 0x41042003, 0x6220080f, 0xf421cb82, 0x05e9501b, 0x5e1c0122, 0xe420b782, 0xc782438e, 0x8ad21b21, + 0x822e2043, 0x20038243, 0x085d481b, 0x821e1c21, 0x1bc42243, 0x05d942c4, 0x821a1c21, 0x82b42043, 0x8201200b, 0x43bf2003, 0x1b21051d, 0x201382fc, + 0x834384a2, 0x1b012211, 0x830f82ea, 0x82402003, 0x82032023, 0x1b012203, 0x224382da, 0x42301b30, 0x1b2505d9, 0x1b0100d6, 0x20438e20, 0x201382b8, + 0x20438a0e, 0x830f82a6, 0x88082003, 0x00962643, 0x1af81a02, 0x260f84f8, 0x00921b01, 0x8ee81a01, 0x82742043, 0x865b8213, 0x1b012299, 0x82438262, + 0xca1a2103, 0x52204388, 0xba224382, 0x0f84ba1a, 0x4e1b0122, 0xaa202f82, 0x3020438e, 0x98201382, 0x1e20878a, 0x03834382, 0x2108d149, 0xcb820e1b, + 0x141b1422, 0x0a204386, 0x04201f82, 0x1a21438d, 0x204382ec, 0x20438af2, 0x85238250, 0x41002003, 0x40200631, 0x40214382, 0x051f411b, 0x361b0122, + 0x30201f82, 0x1b20438d, 0x15827786, 0x3382c020, 0x681a0122, 0x03835382, 0x11823c20, 0x03820320, 0x581a0122, 0x2c22cb82, 0x0f842c1a, 0x8e1a0126, + 0x1c1a0100, 0x31834386, 0x0f820020, 0x1a215782, 0x8587840a, 0x82242043, 0x21038213, 0x4388ae19, 0x02001426, 0x9e199e19, 0x01250f84, 0x01004a1a, + 0x07054619, 0x19204386, 0x1921c782, 0x2143897c, 0x2382e019, 0x00200385, 0x1921cb85, 0x204382d0, 0x830582d0, 0x1a01220f, 0x201f8206, 0x204f82c0, + 0x20038201, 0x202186c1, 0x821382ae, 0x20118203, 0x221182c2, 0x829c1901, 0x5003830f, 0x19210803, 0x2243828c, 0x82221922, 0x82032021, 0x82c2201b, + 0x86122003, 0x82318343, 0x6a1921cb, 0x07821382, 0x7a204388, 0x03820f82, 0x84b21821, 0x24218533, 0x18a21802, 0x260f84a2, 0x00541901, 0x8e921801, + 0x82482043, 0x84802013, 0x208785cb, 0x85438236, 0x83bb8303, 0x82262043, 0x19262187, 0x2205c75a, 0x82101901, 0x8616201f, 0x86c32043, 0x820420cb, + 0x23038213, 0xc4000000, 0x01221182, 0x53826618, 0xa4200383, 0x03201182, 0x01280382, 0x02005618, 0x94189418, 0x01260f84, 0x01004018, 0x03824618, + 0x0f858420, 0x82ee1721, 0x2173820b, 0x0f857418, 0x1f831920, 0x63866420, 0x85825183, 0x82141821, 0x84522023, 0x206385a7, 0x830f8202, 0x846c2003, + 0x00002433, 0x82f21701, 0x185c2263, 0x220f845c, 0x82fc1801, 0x8d4c201f, 0xd0172143, 0x3a201382, 0x17214389, 0x853582be, 0x25eb8603, 0x0200ae17, + 0x0582ae17, 0x01220f83, 0x1f82b818, 0x43869e20, 0xeb85c520, 0x828c1721, 0x82038213, 0x84c62015, 0x829a20eb, 0x86038553, 0x8a182543, 0x8a180200, + 0x43850582, 0x1f828020, 0x43867a20, 0xa9823183, 0x82681821, 0x82038213, 0x83c72015, 0x02162343, 0x03830100, 0x82541721, 0x82032011, 0x15012103, + 0x1723cb82, 0x88441744, 0x82e2200f, 0x15342197, 0x25060746, 0x01002417, 0x8782d215, 0x1f842420, 0x88170122, 0x14200b82, 0x51836386, 0x1f820020, + 0x1382b020, 0xeb840220, 0x15216384, 0x8213829e, 0x96162103, 0x8e265388, 0x86160200, 0x0f848616, 0x6b820120, 0x76160122, 0x6c20438e, 0x64209782, + 0x5a20438a, 0x03854382, 0x0020db83, 0x4a260d82, 0x4a150200, 0x43854a15, 0x82ac1621, 0x843a2011, 0x201f8703, 0x221f822a, 0x869c162a, 0x82e0201f, + 0x821a201b, 0x8201200b, 0x41c82003, 0x1521054f, 0x82138208, 0x20118203, 0x211185c9, 0x97825416, 0x10165a22, 0x03201182, 0x4620c382, 0x44208382, + 0x21833386, 0x3e170122, 0x38201182, 0x8782118a, 0x82261621, 0x84202013, 0x204587a9, 0x2011820e, 0x21118814, 0x0f821701, 0xff821420, 0x84241721, + 0x00002357, 0xff821401, 0x16141722, 0x2205e34a, 0x82441601, 0x8d04206b, 0x83142055, 0x05b344ff, 0x16217984, 0x825382ca, 0x5a1421c3, 0x16264387, + 0x140200d0, 0x3b45164a, 0xc6162106, 0x3a205582, 0xca204386, 0xae20cd86, 0x28201382, 0x11838784, 0xa8160122, 0xb0204382, 0xb6200382, 0xd820138a, + 0x9c200f82, 0xe2200382, 0xcb201384, 0x01223982, 0x0f820217, 0xc3418820, 0x83cc2008, 0x22ab8213, 0x82741601, 0x84fe2017, 0x82cd2027, 0x00f43009, + 0x000a0002, 0x04030012, 0x04750476, 0x82020077, 0x83772007, 0xa014212b, 0xa0207782, 0xa0229d82, 0x91822015, 0xef840320, 0x0122f383, 0x0f850e15, + 0x82c21621, 0x827e2013, 0x147e2221, 0x2011867e, 0x201182b8, 0x205582ec, 0x825f86e4, 0xa4162135, 0xd8201382, 0x01201f82, 0xce220382, 0x2f820300, + 0x8a165222, 0x40201382, 0xef820382, 0x97841586, 0x822a1421, 0x142a211d, 0x1582dd82, 0x2b84cf20, 0x5e163c22, 0x20202782, 0x9a200382, 0x15835384, + 0x48160122, 0x0a200f82, 0x0a222b82, 0x15848414, 0x2b84d020, 0x32160026, 0xee130100, 0x6e201b82, 0x01221588, 0x13821c16, 0x0200d826, 0x5814d813, + 0xd1201584, 0x96262b84, 0x01000616, 0x2b82d012, 0x15884220, 0xf0150122, 0xba261382, 0xba120200, 0x15842c14, 0x2b82d220, 0xda150122, 0x90204182, + 0x16202982, 0xb982138a, 0x82881321, 0x05214313, 0xb2202785, 0x79822782, 0xbf828183, 0x9e201385, 0x68205182, 0xda201782, 0xd3203b84, 0x8a204f84, + 0x2b830f82, 0x1385fd85, 0x13827620, 0x17856220, 0x13833b82, 0x2a130223, 0x20118315, 0x200f8218, 0x22138601, 0x824e1501, 0x85042023, 0x20138203, + 0x244f82d4, 0x15181302, 0x2065823a, 0x832786fc, 0x15012213, 0x20118226, 0x820385e8, 0x83d52017, 0xe0122327, 0x11821215, 0x2786ce20, 0x01221383, + 0xf184fe14, 0xba120122, 0xd6209f84, 0x7a264f84, 0x0100ea14, 0x2786b411, 0x01221383, 0x1182d614, 0x0385a020, 0xd7201782, 0x01222782, 0x3b82c214, + 0x25867820, 0xb0201185, 0x72201182, 0xff83118c, 0x118c5a20, 0x45828c20, 0x11865620, 0x4783d820, 0x82421221, 0x82302035, 0x05d14203, 0x00201383, + 0x1c260d82, 0x1c120200, 0x9784a212, 0x2784d920, 0x14202383, 0x8e201982, 0x27831388, 0x27820020, 0x7a120022, 0xda201384, 0x11212783, 0x206182f8, + 0x202782e6, 0x82138866, 0xd2112627, 0xd2110200, 0x05014612, 0x4f84db20, 0x01009224, 0x2782cc10, 0x27843e20, 0x27821383, 0x00b81027, 0x12b81002, + 0x2013842a, 0x058343dc, 0x009c1129, 0x11161203, 0x8c201490, 0x83862015, 0x7a112179, 0x0320cb82, 0x01220382, 0x6182f011, 0xfa136a22, 0xdc20238c, + 0x6a204d82, 0x87061142, 0x21ef824d, 0x258cc811, 0x01003c23, 0x87fd8511, 0x82242023, 0x8ba42011, 0x82102023, 0x8211207b, 0x206982b1, 0x239586dd, + 0x13010080, 0x83051543, 0x13012211, 0x200f8296, 0x201f82a0, 0x84238601, 0xb4102111, 0x9020118c, 0xb2202382, 0xa620118c, 0xc2201182, 0x0020118a, + 0x8b820f82, 0x9d421320, 0x20598505, 0x201382b4, 0x25238ea4, 0x13020092, 0x9f4113b2, 0x24258305, 0x139e1302, 0x2027828e, 0x23278a7e, 0x005a1001, + 0x02240383, 0x90105a10, 0x03201782, 0x48200d82, 0x27830386, 0x13210f82, 0x260f826e, 0x10020038, 0x85381038, 0x64132121, 0x5c201182, 0xdb434982, + 0x20818505, 0x82358450, 0x2223829b, 0x820300de, 0x130c262f, 0x0f010036, 0x821782fa, 0x22158607, 0x82201301, 0x00e42513, 0x10e40f02, 0x15820982, + 0x2b83df20, 0x13f60f23, 0x2017820a, 0x822b82da, 0x22158607, 0x82f41201, 0x82c42013, 0x0fc4212b, 0x15820982, 0x2b84e020, 0xde12ba22, 0xa8201782, + 0x07820382, 0x01221586, 0x0f82c812, 0x0f22f182, 0x09820f92, 0xe1201582, 0x01222b82, 0x1582b212, 0x03827620, 0x13880782, 0x0f829e20, 0x0f20d382, + 0x13880782, 0x13828a20, 0x03825420, 0x13820782, 0x6784e220, 0x83124c21, 0x07ed4539, 0x01221383, 0x23826212, 0x03852620, 0xe3202782, 0x3a222784, + 0x11824e12, 0x55411e20, 0x22138306, 0x823a1201, 0x20c98211, 0x20cd850f, 0x212784e4, 0x39821202, 0x86f00e21, 0x84e42027, 0x0012249f, 0x85dc0e01, + 0x20178203, 0x211383e5, 0x0f82fe11, 0x8507ef41, 0x82ec2011, 0x86bc2011, 0x20118537, 0x411182da, 0xe62007ef, 0x0e203583, 0x0e21cd82, 0x8515828c, + 0x201383fd, 0x280d8200, 0x0e020078, 0x00b40e78, 0x203d8201, 0x832784e7, 0x82702023, 0x88a02019, 0x20278313, 0x2027825c, 0x823f835c, 0x84e82027, + 0x82542027, 0x84422023, 0x833b8341, 0x20278313, 0x2227822e, 0x84640e2e, 0x42e9203b, 0x0e2105e5, 0x20258214, 0x20118c50, 0x2011820e, 0x21118b3e, + 0x1182f60d, 0x11842c20, 0x3586ea20, 0x01001a23, 0x05d94511, 0x01221183, 0x21823c11, 0x13820820, 0x81826a20, 0x07820320, 0x01005a24, 0x0782f80d, + 0x0f842c20, 0x0d217b82, 0x200d82e8, 0x2143844a, 0x218300eb, 0x21823820, 0x1d82d620, 0x11849f83, 0x2f821020, 0x825c0e21, 0x82262025, 0x20218315, + 0x24538216, 0x1001004c, 0x820f84e8, 0x820e2043, 0x06112165, 0x10214389, 0x202182f4, 0x20438c2a, 0x205582b4, 0x493382aa, 0x10210689, 0x200f82d2, + 0x200f829a, 0x208788a4, 0x200d828a, 0x20438ac2, 0x202182b0, 0x20438c78, 0x20118270, 0x20258272, 0x2233849e, 0x828e1001, 0x8262200f, 0x8660200f, + 0x8250200f, 0x8a52200f, 0x21998231, 0x1f82400d, 0x85053341, 0x827620cb, 0x859c2023, 0x85298203, 0x21438213, 0x3786880d, 0x4741ec20, 0x830d2005, + 0x82038227, 0x82ed2015, 0x10012511, 0x0c010046, 0x0d21a182, 0x85a1846a, 0x823a2013, 0x00562647, 0x0d760c02, 0x20158a56, 0x82158224, 0x88798375, + 0x8210203d, 0x822c2013, 0x8201200d, 0x86ee2003, 0x821a2061, 0x0d3a2239, 0x2039841a, 0x201386ef, 0x41278206, 0xef260547, 0xe20f0100, 0xc2823700, + 0x0f210282, 0x2a0984d8, 0x0f020001, 0x060200d4, 0x82dd06dc, 0x82022014, 0x82ce200d, 0x067f220d, 0x213d857f, 0x3382f20c, 0x4f84cc20, 0x1185f020, + 0x82c00f21, 0x82038211, 0x82f02075, 0x82032031, 0x00b22a31, 0x06a00404, 0x06df06de, 0x201182e0, 0x22d58204, 0x854e00ca, 0x020c212d, 0xa6202d82, + 0xf1203f84, 0x01221182, 0x0f82ea0b, 0x3b829420, 0x03820120, 0x0000f124, 0x27850501, 0x86140d21, 0x82f22013, 0x0f01220f, 0x20258274, 0x22118874, + 0x84060100, 0x00da233b, 0x03830b01, 0x26081d4e, 0x0200ca0b, 0x410b9e0b, 0x0b2106bb, 0x201f82e0, 0x2035868e, 0x215785f3, 0x1382a80b, 0x83007c21, + 0x84f3206d, 0x82462043, 0x6a03830f, 0x0b21084b, 0x22438236, 0x825a0b5a, 0x82032037, 0x823e201b, 0x824a2003, 0x2031830b, 0x204386f4, 0x20138214, + 0x24438438, 0x090200f4, 0x1e9b6cae, 0x07010030, 0xb60e0200, 0x87040400, 0xe2068804, 0x0d82e306, 0x00b44008, 0x001e01b1, 0x01850084, 0x0086001f, + 0x00620087, 0x01880068, 0x010f011e, 0x01170116, 0x011f0110, 0x011b0111, 0x00ed0012, 0x011301f3, 0x0261021c, 0x02420262, 0x02480246, 0x0250024a, + 0x82590255, 0xa642200d, 0x82462003, 0x20038b37, 0xa1458248, 0x824a2003, 0x20039369, 0x8b7f8250, 0x82522003, 0x8c55208d, 0x82592003, 0x2403a09d, + 0xad03a303, 0x12676d03, 0x03f80325, 0x6c0604f9, 0x04270dbf, 0x050d0592, 0x82800604, 0x067f2c01, 0x06dc06de, 0x06e006df, 0x6c8106dd, 0xd36c08d5, + 0x700e2318, 0x60182b00, 0x5808086d, 0x0088007c, 0x00a00094, 0x00b800ac, 0x00d000c4, 0x00e800dc, 0x010401f4, 0x0114010a, 0x012c011e, 0x01540138, + 0x016c015c, 0x01800178, 0x018e0186, 0x01ae0196, 0x01c201ba, 0x02e001d6, 0x024c020a, 0x02800270, 0x028a0286, 0x029a0290, 0x000200c6, 0x001501bb, + 0x011d0102, 0x2a05821a, 0x001c0114, 0x03ae0306, 0x82c203cc, 0x03a22ed5, 0x030500a1, 0x03cd03af, 0x03b903c3, 0x280b82a4, 0x03ce03b0, 0x03ba03c4, + 0x280b82a5, 0x03cf03b1, 0x03bb03c5, 0x280b82a6, 0x03d003b2, 0x03bc03c6, 0x280b82a7, 0x03d103b3, 0x03bd03c7, 0x280b82a8, 0x03d203b4, 0x03be03c8, + 0x280b82a9, 0x03d303b5, 0x03bf03c9, 0x280b82aa, 0x03d403b6, 0x03c003ca, 0x080b82ab, 0xd503b74c, 0xc103cb03, 0x0500ac03, 0xfc035904, 0x4d044e04, + 0x07005c04, 0xfd035404, 0x66045304, 0x7804fa03, 0x02000704, 0xfe035704, 0xff030400, 0x67045804, 0x04007904, 0x51046804, 0x5d040004, 0x60040600, + 0x5f040104, 0x6c049706, 0x4382fb03, 0x04022c08, 0x047b044b, 0x007c047a, 0x04d6030d, 0x046f0403, 0x04a80662, 0x0471046e, 0x047e0481, 0x047d0480, + 0x007f0482, 0x04700403, 0x82050404, 0x04082c67, 0x04730414, 0x04160444, 0x8263046b, 0x0409283f, 0x04740415, 0x82170445, 0x04182423, 0x8264041f, + 0x0619227b, 0x240d8286, 0x0421041a, 0x3c078265, 0x0487061b, 0x040b0022, 0x0496062d, 0x06470432, 0x044604aa, 0x0475044c, 0x04760477, 0x28418231, + 0x046a0433, 0x04830484, 0x382b8285, 0x049d069f, 0x040900a0, 0x06eb04ea, 0x058206b1, 0x068f0608, 0x058e069f, 0x08c18207, 0xbb04bab0, 0x8306b206, + 0xad041400, 0x8406b306, 0x92065504, 0x5b040905, 0xaf064f04, 0x91065604, 0x93065a04, 0x6904a106, 0x5e045204, 0xc206c106, 0x2000c306, 0x8a069c06, + 0x8c068b06, 0x0a059506, 0xae069406, 0x9806a606, 0xa0069e06, 0xac06a906, 0x8d066104, 0x9006a206, 0x05056d04, 0xc506c406, 0xc906c606, 0xc806c706, + 0xcb06ca06, 0xcf06cc06, 0xce06cd06, 0x0b051100, 0xa306a406, 0x06055004, 0xd106d006, 0xd406d206, 0xd506d306, 0xd706d606, 0xda06d806, 0xdb06d906, + 0x0c050700, 0xad06a706, 0xa5064804, 0x8604e106, 0xb0060200, 0x01000e05, 0x0982d204, 0x06ab4e08, 0x06040081, 0x067d0685, 0x0080067f, 0x067e0615, + 0x069a069b, 0x06890699, 0x04490488, 0x06b4064a, 0x06b606b5, 0x06b706bc, 0x06b806bd, 0x06ba06b9, 0x06bb06be, 0x00c006bf, 0x07120702, 0x0501001b, + 0x00f6ff8e, 0x00f80b02, 0x011e0104, 0x2203831f, 0x820b0100, 0x08356f11, 0x0200412a, 0x0100f003, 0xcb000400, 0x02260984, 0x0300ea06, 0xb7829c06, + 0x37827e20, 0x8382d420, 0x7e068a28, 0x22060100, 0x0b825f00, 0x1b82ce20, 0x1b848b20, 0x10060124, 0x11825e00, 0x1182bc20, 0x11848c20, 0xae0b0224, + 0x09820200, 0x75829920, 0x4d00f422, 0x96203d82, 0x95201f82, 0x02223d82, 0x19825606, 0xa4060a22, 0x8a201382, 0x88202384, 0x78200982, 0x94201d82, + 0x38201d84, 0xa3201d84, 0x74201382, 0x96221382, 0x09820b05, 0x0600722e, 0x6004ff03, 0xae063204, 0x0c050b05, 0x70261182, 0x54040200, 0x09820104, + 0xa9826e20, 0x5504fd22, 0x0c229582, 0x0582c801, 0x3f000622, 0x00220582, 0x1b8291ff, 0x04005a24, 0x39825904, 0x09054722, 0x58200d82, 0x32223382, + 0x0982a706, 0xa7825620, 0x4986a620, 0x03005426, 0x98060104, 0x52206784, 0x9f220b82, 0x0b849e06, 0x03005026, 0xa0060805, 0x4e300b84, 0xfc030800, + 0x03040204, 0x33046b04, 0xa9064f04, 0x4c201584, 0xfc227982, 0xe1825004, 0x6700be22, 0x44205582, 0x06210f83, 0x2009828f, 0x22698242, 0x8208056f, + 0x00402609, 0x041d0102, 0x20098203, 0x2209823e, 0x8285061a, 0x003c2a09, 0x06af0604, 0x060d05ad, 0x2c0d827d, 0x0405003a, 0x06aa065f, 0x060c05ac, + 0x2e0f82ab, 0x04060038, 0x06620401, 0x04870686, 0x827e0661, 0x82362011, 0x041f224d, 0x20098249, 0x282b8234, 0x044b0453, 0x04220421, 0x300f824a, + 0x03040032, 0x049f04fd, 0x008d0656, 0x010c0501, 0x830582c7, 0x0b0222ff, 0x288b8224, 0x005a04ff, 0x00a60401, 0x2c29826c, 0x0305001c, 0x063204ff, + 0x040a0593, 0x22158248, 0x82230096, 0x00142e15, 0x0666040d, 0x06020497, 0x046404a8, 0x2a1f8265, 0x069f069d, 0x05a206a1, 0x82a5060b, 0x0012261f, + 0x04670407, 0x26f98268, 0x046a0463, 0x82b00669, 0x82102013, 0x04fc2673, 0x0552044c, 0x2247820e, 0x826600c4, 0x84082013, 0x05512413, 0x82900608, + 0x01d22213, 0x2a1382c8, 0x04040000, 0x0500045c, 0x825e0408, 0x00322613, 0x0a02006f, 0x22c982f8, 0x82000457, 0x82f62009, 0x04fe2c31, 0x0403046c, + 0x0201006d, 0x827900e0, 0x00ee2413, 0x82fa0305, 0x05702411, 0x82060505, 0x00ec280f, 0x04140103, 0x82040471, 0x005822d5, 0x22058217, 0x820f0052, + 0x00de2a17, 0x061c0102, 0x060200c1, 0x22038224, 0x82d006c2, 0x82022055, 0x05c42c09, 0x0902000b, 0x0502002e, 0x82b4060a, 0x82be2027, 0x06812217, + 0x2005827e, 0x268b820c, 0x06c50603, 0x82b506d1, 0x82ae2017, 0x0478290d, 0x067e0479, 0x030200d2, 0x0621ab82, 0x213983c6, 0x3984f408, 0x2182b620, + 0x33828420, 0x39838020, 0x84d20321, 0x06c92439, 0x82bc06d4, 0x82802017, 0x067d2217, 0x203582d3, 0x206f8292, 0x203584c7, 0x203584be, 0x201d82b7, + 0x201d824e, 0x2d358382, 0x0500600a, 0xc3060304, 0xd506c806, 0x1982bd06, 0x6f005e28, 0x16011501, 0x85471701, 0x7f0429d1, 0xc3067504, 0xc6070200, + 0x772cfd82, 0x0200d606, 0x02007602, 0x0b05ca06, 0xa2261382, 0x0a050200, 0x1382b806, 0x0300a228, 0xd706cb06, 0x15827e06, 0x1f829420, 0xb906d822, + 0x4c201582, 0xcc200982, 0x78202984, 0xba202984, 0x78201382, 0xcf222982, 0x2984da06, 0x1f826a20, 0xbe06d922, 0x22201582, 0xcd200982, 0x4e202984, + 0xbb202984, 0x4e201382, 0xce222982, 0x2983db06, 0x823c0921, 0x0676387d, 0x090200bf, 0x0405003a, 0x04fb0307, 0x0531047b, 0x02010007, 0x82860050, + 0x00322815, 0x047c0403, 0x82c00684, 0x00442211, 0x22058258, 0x825a003e, 0x82242017, 0x06802143, 0x0b820182, 0x04236382, 0x828106d2, 0x82202009, + 0x0405224d, 0x20098206, 0x226d821e, 0x82e10609, 0x001c2509, 0x04ff0302, 0x00374b82, 0x03970303, 0x040000a0, 0x000b040a, 0x04c6040a, 0x000c00c7, + 0x91040002, 0xca042b15, 0x0e00ca04, 0x01000100, 0x2182f503, 0x21850120, 0xd6200f84, 0xc2240f84, 0x0000cb03, 0xb8220984, 0x0982c103, 0x0b820120, + 0x8b000423, 0x22078300, 0x82d5004a, 0x00012207, 0x21058344, 0x19828d04, 0x1401022a, 0x00001401, 0xa1039703, 0x22241984, 0xef03ed03, 0x3b088583, + 0x0d040c04, 0x0f040e04, 0x24042304, 0x26042504, 0x3b043a04, 0x3d043c04, 0xfc06d504, 0x01070007, 0x03070207, 0x05070407, 0x07070607, 0x09070807, + 0x0b070a07, 0x2e071f07, 0x3e073007, 0xb5204984, 0x04280582, 0x67006000, 0xf200eb00, 0x0b360b82, 0x45001200, 0x5e004b00, 0x99008100, 0xd600cf00, + 0x0c01e900, 0x2b840307, 0xbf84c720, 0x0b84f020, 0x05823d20, 0x39040224, 0x07833f04, 0xa2209782, 0xcd20ab84, 0x06210583, 0x200b843c, 0x210583cc, + 0x11840b05, 0x05827e20, 0xf2030326, 0xc6049604, 0x0a201584, 0x23223d84, 0x5184ca04, 0x2f84ec20, 0x05842320, 0x01221983, 0x1784ee03, 0x1184ff20, + 0x05843220, 0x3784d220, 0x17840c20, 0x1184f220, 0x0b840120, 0x4984e920, 0x8404cc21, 0xfd032179, 0x55841984, 0x840e0421, 0x840f200b, 0x03e9229f, + 0x230782ec, 0x04f50304, 0x9f852982, 0x84090521, 0x82e7203f, 0x89032005, 0x9f042115, 0x96203584, 0x08206d84, 0xb1840b84, 0x84030421, 0x84f4202d, + 0x842b2011, 0x84022005, 0x84332005, 0x83fc2017, 0x00012105, 0x1a200584, 0x3420f184, 0x7d200584, 0xd4202384, 0x0d204d84, 0x2f841184, 0x0b840420, + 0x840c0421, 0x841f201d, 0x84212005, 0x82222005, 0x03062105, 0xa98bad82, 0x84e80421, 0x84cf853f, 0xea032163, 0xfe207584, 0x03260582, 0x0505fa03, + 0x0f840605, 0x0200fa24, 0x09820300, 0x0000022e, 0x8c040400, 0x93040200, 0x8b044007, 0xf6201b84, 0x04205f84, 0x02200582, 0x21074542, 0x0d820501, + 0x04001938, 0x11001000, 0x1b001700, 0x8b002500, 0x98009700, 0xa2009e00, 0x2582ac00, 0x99039836, 0x9b039a03, 0x9d039c03, 0x9f039e03, 0xa103a003, + 0x79067806, 0xa2247584, 0xad03a303, 0x18200982, 0x21833f98, 0x20117578, 0x85a382ad, 0x84002081, 0x820b204b, 0x0301220f, 0x834b82a2, 0x040224d9, + 0x822a0429, 0x06022455, 0x82c306c1, 0x04143407, 0x04790478, 0x047f047e, 0x06820481, 0x06b506b4, 0x83bd06b7, 0xc4062f1b, 0xc706c506, 0xd006c806, + 0xd306d106, 0x2b82d506, 0x37410720, 0x41ca2006, 0x022408cd, 0xcd04ca04, 0xf522f184, 0x0782ca04, 0x21830520, 0xcc221382, 0x0d823c06, 0xac000326, + 0x16011501, 0x02240982, 0xc100b500, 0x04280782, 0x2e002500, 0x17016400, 0x053e9382, 0x5b025a02, 0x5e020000, 0x02005f02, 0x92027602, 0xb2020400, + 0x2100b902, 0xc202bb02, 0x2d822900, 0x4a020122, 0x04202782, 0x5e202788, 0x03202786, 0x20202784, 0x55202184, 0x02202182, 0x60202182, 0x76244982, + 0x0700d502, 0x42220f84, 0x0f866202, 0x25832120, 0x2305b341, 0x76047504, 0x0e200d82, 0x06370783, 0x06b906b8, 0x06bf06bb, 0x06cb06ca, 0x06ce06cd, + 0x06d706d6, 0x82db06d9, 0x0404221f, 0x20df8623, 0x084d8202, 0x8a000428, 0x21010000, 0x8700b001, 0xd5024102, 0x97031701, 0xac01a003, 0x0f040a04, + 0x3c06b601, 0xbc013c06, 0x79067806, 0x5d44bd01, 0x14012105, 0x1d302d82, 0x8a002001, 0x4002b101, 0xd6028e00, 0x1e018c03, 0x02245582, 0x7c047b04, + 0x84220784, 0x07828504, 0x82040321, 0xc0062107, 0xe4209d84, 0x02240582, 0xa1069306, 0x34210784, 0x221f8306, 0x867f0601, 0x2807830d, 0x06960404, + 0x069d068d, 0x2213829e, 0x83ab0601, 0x05042105, 0x04280582, 0x5b045a04, 0x92069106, 0x30227d82, 0x01820400, 0x12000022, 0x01220182, 0x01824500, + 0x4a000224, 0xfb824b00, 0x5e005e26, 0x60000500, 0x06220182, 0x01826700, 0x81000722, 0x08220182, 0x01828b00, 0x99000922, 0x0a220182, 0x0182c100, + 0xc7000b22, 0x0c220182, 0x0182cf00, 0xd5000d28, 0x0e00d600, 0x0182e400, 0xe9001022, 0x11220182, 0x0182eb00, 0xf2001222, 0x13270182, 0x0c010c01, + 0x82011400, 0x00330801, 0x024a0215, 0x0216004a, 0x00550255, 0x025a0217, 0x02180060, 0x00d50276, 0x03a1031f, 0x037f00a2, 0x00cb03c2, 0x03ed0381, + 0x038b00ed, 0x00ef03ef, 0x8205048c, 0x8d2008bb, 0x26042404, 0x3a048e00, 0x91003d04, 0x8d048d04, 0xd4049500, 0x9600d504, 0x7d067d06, 0x7f069800, + 0x9926ff82, 0x85068506, 0xf9829a00, 0x008d4e08, 0x0693069b, 0x069c0093, 0x009e069d, 0x06a1069d, 0x069f00a1, 0x00ab06ab, 0x06fc06a0, 0x07a100fc, + 0x00020700, 0x070407a2, 0x07a5000b, 0x001f071f, 0x072e07ad, 0x07ae002e, 0x00300730, 0x073e07af, 0x00b0003e, 0x002b0001, 0x010001b5, 0x14794305, + 0xe903e730, 0xec03ea03, 0xf203ee03, 0xf503f403, 0xfd45f603, 0x042b3a0e, 0x04c60496, 0x04ca04c7, 0x04cd04cc, 0x05e804d2, 0x0633060c, 0x073c0634, + 0x28598203, 0x00040004, 0x008b004a, 0x240b82d5, 0x003d0002, 0x200783c7, 0x05074304, 0xcd040224, 0x0f843c06, 0xcd042322, 0x06200782, 0xf2206582, + 0x21056542, 0x0f82d204, 0x79820220, 0x0785f220, 0x82ca0421, 0x03042407, 0x82ec03e7, 0x200b831f, 0x83078202, 0x85032023, 0x221d8275, 0x83f20303, + 0x8209830b, 0x848b8291, 0x86c62009, 0x82082013, 0x82bd823b, 0x852b20bb, 0x205784a9, 0x247784e7, 0x04e70302, 0x200f84c6, 0x230785f5, 0xf5030001, + 0x01230f83, 0x82340600, 0x82042007, 0x04d22231, 0x200b84d4, 0x20658205, 0x22538223, 0x843306d2, 0x03f226b1, 0x040d04f5, 0x20d1880f, 0x20d1840c, + 0x24b98205, 0x040e04f4, 0x220d840f, 0x82e90304, 0x04ca2291, 0x206384cc, 0x20cb84ec, 0x83c98505, 0x20158249, 0x212f820d, 0x9f8303f2, 0x35820c20, + 0x2d822320, 0xa585c620, 0xe3830420, 0xec030726, 0xf403ee03, 0xe820bb86, 0x04202f82, 0x2320b182, 0x0b862182, 0x04ee0322, 0x1785e782, 0xca200b84, + 0xea226984, 0x1384ee03, 0x8303ea21, 0x837d83a5, 0x03f52297, 0x061341f6, 0x05010323, 0x840d8203, 0x840520e9, 0x03022295, 0x82b187f5, 0x44f52073, + 0xcd2008c3, 0x2b822382, 0x21829385, 0x0a000224, 0x0182b500, 0xc1000022, 0x01220182, 0x0182c700, 0x4a020238, 0x03004a02, 0x55025502, 0x5a020400, + 0x05006002, 0xd5027602, 0x63820c00, 0x6c00f528, 0x23042304, 0x41826d00, 0x6e00ca22, 0x4105f341, 0xf9820829, 0xc6201d82, 0x03201582, 0x2b20e582, + 0x03241784, 0x7d063406, 0x2305eb43, 0xab060c05, 0xf622cf84, 0x39840504, 0x4204ca21, 0xec20051d, 0x00280782, 0xb9040400, 0x0500c201, 0xf3270882, + 0x00009204, 0x84049200, 0xaa022b07, 0x78023200, 0x0b020000, 0x1c820908, 0x0400022c, 0x87020040, 0x01390002, 0x00850002, 0x44544337, 0x00c00042, + 0x07ffff0d, 0x00a8fd08, 0x02080700, 0x00006058, 0x231d839f, 0x62051e04, 0x20200782, 0x00215783, 0x20098204, 0x20038203, 0x82038224, 0xcc0e250b, + 0x01000300, 0x03290f84, 0x00000a00, 0x0400cc0e, 0x213f820e, 0x14827c01, 0x0007f409, 0x000d007c, 0x0039002f, 0x017e017e, 0x02ff0192, 0x0237021b, + 0x02bc02ba, 0x02c902c7, 0x030803dd, 0x030f030c, 0x03270314, 0x03420336, 0x03770345, 0x038a037f, 0x0390038c, 0x03a903a1, 0x03c903b0, 0x041a04e1, + 0x042f0423, 0x04350433, 0x043a0439, 0x05790443, 0x1405142f, 0x1e851e0a, 0x1ff31e9e, 0x1f0f1f07, 0x1f1d1f15, 0x1f2f1f27, 0x1f3f1f37, 0x1f4d1f45, + 0x1f591f57, 0x1f5d1f5b, 0x1f671f5f, 0x1f7d1f6f, 0x1f8f1f87, 0x1f9f1f97, 0x1faf1fa7, 0x1fc41fb4, 0x1fd31fcf, 0x1fef1fdb, 0x20fe1ff4, 0x200b2008, + 0x201e201a, 0x20262022, 0x203a2030, 0x204a2044, 0x20792070, 0x2089207f, 0x20ac208e, 0x20ba20af, 0x210221bd, 0x2113210d, 0x211a2116, 0x2122211d, + 0x212e2124, 0x215e2154, 0x218b215f, 0x21a92199, 0x21df21b3, 0x220022ea, 0x220f220d, 0x22152212, 0x221e221a, 0x2236222b, 0x22622248, 0x228b2265, + 0x230023af, 0x23102306, 0x23212318, 0x232b2328, 0x238b2388, 0x24cf23ad, 0x25802526, 0x25942588, 0x25ab259f, 0x25b225af, 0x25ba25b6, 0x25c025bc, + 0x25c725c4, 0x25cf25cb, 0x25d525d3, 0x25e525d7, 0x25f325eb, 0x261226f7, 0x26372620, 0x2640263c, 0x26602642, 0x26662663, 0x2713276b, 0x27a12771, + 0x27f327e9, 0x2b052bff, 0x303b2e07, 0xe003e00d, 0xfeb3e0a2, 0xff63ffff, 0x000000ff, 0x0020000d, 0x003a0030, 0x019201a0, 0x021802fc, 0x02b90237, + 0x02c602bc, 0x03d802c9, 0x030a0300, 0x0313030f, 0x03350326, 0x03450342, 0x037a0370, 0x038c0384, 0x0391038e, 0x03aa03a3, 0x03ca03b1, 0x041b04f0, + 0x04300424, 0x04360434, 0x043b043a, 0x148a0444, 0x1e0a1405, 0x1e9e1e80, 0x1f001ff2, 0x1f101f08, 0x1f201f18, 0x1f301f28, 0x1f401f38, 0x41501f48, + 0x3008087d, 0x1f681f60, 0x1f801f70, 0x1f901f88, 0x1fa01f98, 0x1fb01fa8, 0x1fc61fb6, 0x1fd61fd0, 0x1ff21fdd, 0x200720f6, 0x2012200b, 0x2020201c, + 0x20302026, 0x067d4139, 0x7a20742c, 0x8a208020, 0xaf20ac20, 0x7d41b920, 0x21152208, 0x087d4119, 0x21535008, 0x215f2155, 0x2190218a, 0x21b021a9, + 0x22e421de, 0x22022200, 0x2211220f, 0x22192215, 0x2227221e, 0x22482234, 0x22642260, 0x23a22282, 0x23022300, 0x23182310, 0x23242320, 0x2387232b, + 0x239b238b, 0x250024ce, 0x25812500, 0x25952589, 0x41ac25a0, 0xc63a0c7d, 0xce25c925, 0xd525d025, 0xd925d625, 0xef25e725, 0x1026f425, 0x30262026, + 0x7d413926, 0x65290808, 0x13276a26, 0xa1277027, 0xf027e827, 0x052bf427, 0x3a2e062b, 0x00e00c30, 0xb0e0a0e0, 0x62fffffe, 0xf5ffffff, 0x67030000, + 0x21008200, 0x04820703, 0x8bfe002a, 0x2d040000, 0x22043f04, 0x002d0d83, 0x03ea0300, 0x03d603e7, 0x03db03c9, 0x2b1185d9, 0x0000d2fe, 0xb0feb1fe, + 0x25ff0000, 0xfd251183, 0xfd000018, 0x20038281, 0x20038285, 0x37118388, 0x84ef88ef, 0xc5e10000, 0x12e40000, 0x1be46ee3, 0x13e473e3, 0x1ae46be3, + 0x1a2a0b82, 0x14e46ae3, 0x61e362e3, 0x1d8260e3, 0x5be31430, 0xa2e30000, 0xb1e3fbe2, 0xe2e306e3, 0x3d8326e3, 0x49821182, 0xe4220985, 0x0b86e486, + 0xe4c5e32d, 0xe303e4b9, 0xe3ade392, 0x825ce35c, 0x822e2023, 0xe3ec2203, 0x320582e8, 0xe28ee2de, 0x002be584, 0xe27ae200, 0xe217e578, 0x8213e572, + 0xe288220b, 0x23438378, 0x6ce372e3, 0x02200784, 0xce201382, 0x91200382, 0xb7210382, 0x21bd82e2, 0x178389e2, 0xe3210383, 0x22ad823b, 0x844fe3df, + 0x8235200b, 0x83bb201f, 0x38038309, 0x0000b9df, 0x02e0b7df, 0x05e00000, 0x01e002e0, 0xfadffddf, 0xaddff8df, 0x29008200, 0x8edf8ddf, 0x00008bdf, + 0x0382c7df, 0xe0703808, 0xdffcdf09, 0xdfecdfed, 0xdfe8dfe9, 0xdfc9dfcb, 0xdf7ae0c8, 0xdda2dc1c, 0x00a1dc98, 0xda39dd00, 0x0022da25, 0x2704d400, + 0x26972633, 0x0494058a, 0x000100ba, 0x827a0100, 0x02962803, 0x0300001e, 0x82de03d8, 0x82e22005, 0x25028258, 0xe803de03, 0x0882f803, 0x03290288, + 0x04fe03f0, 0x04000008, 0x83128312, 0x1c042705, 0x00004a04, 0x03829c04, 0x0420cd82, 0xae220383, 0x1d831805, 0x005e0625, 0x83660600, 0x21039709, + 0x19834c06, 0x83480621, 0x24038705, 0x5e065606, 0x278f8206, 0x94068a06, 0xbc06b806, 0x06251783, 0x06d806c8, 0x890983dc, 0xd2062503, 0xda060000, + 0x06210f83, 0x830583de, 0xd8062103, 0x03850583, 0x84d00621, 0x86ce2011, 0x06de2607, 0x060000e0, 0x200382ea, 0x820385fe, 0x82fc2005, 0x07fe2a03, + 0x07040702, 0x07000016, 0x272f832e, 0x34073207, 0x3a070000, 0x07290383, 0x0760075e, 0x080000ac, 0x201983aa, 0x83898408, 0x23038509, 0xb808b408, + 0x00230987, 0x85ca0800, 0x2105970b, 0x1985b408, 0x0d850787, 0x2c080582, 0x04ec0303, 0x04f4033e, 0x06e80496, 0x043f0434, 0x030b040a, 0x03c604f2, + 0x032304e8, 0x03f503e7, 0x04ea03e9, 0x04ca04cd, 0x06ee03cc, 0x0cb74c33, 0x00263208, 0x002e002b, 0x003b0039, 0x0043003d, 0x004a0044, 0x00580056, + 0x005d0059, 0x00690064, 0x00750074, 0x007b007a, 0x030e0480, 0x040f04f6, 0x072b04d4, 0x0b2b4d02, 0x00300807, 0x00b200ad, 0x00c100b5, 0x00c700c4, + 0x00ce00cd, 0x00e100d5, 0x00e400e3, 0x00ef00e8, 0x01ff00f4, 0x01050100, 0x040b0106, 0x043c060c, 0x04d2040d, 0x04ed038f, 0x049d0494, 0x069e0495, + 0x0736063d, 0x01370600, 0x043a041e, 0x062404d3, 0x060a0738, 0x03d0043a, 0x07cf03ce, 0x06e00403, 0x07f00335, 0x01cd030b, 0x033b041f, 0x03d803db, + 0x00ef03dc, 0x00050009, 0x000d0007, 0x000c0008, 0x0014000e, 0x001c0022, 0x0020001f, 0x00300035, 0x00330032, 0x00490018, 0x004b004f, 0x0054004d, + 0x00c8044e, 0x006e0052, 0x006c006a, 0x007c006d, 0x00ee0057, 0x008c0090, 0x0094008e, 0x0093008f, 0x009b0095, 0x00a300a9, 0x00a700a6, 0x00b700bc, + 0x00ba00b9, 0x00d4009f, 0x00d600da, 0x00df00d8, 0x00c904d9, 0x00f900dd, 0x00f700f5, 0x000701f8, 0x000901e2, 0x0091000a, 0x008d0006, 0x0092000b, + 0x00990012, 0x009c0015, 0x009d0016, 0x009a0013, 0x00a00019, 0x00a1001a, 0x00aa0023, 0x00a4001d, 0x00a80021, 0x00ab0024, 0x00a5001e, 0x00af0028, + 0x00ae0027, 0x00b1002a, 0x00b00029, 0x00b4002d, 0x00b3002c, 0x00c00038, 0x00be0036, 0x00b80031, 0x00bf0037, 0x00b60034, 0x00bd002f, 0x00c3003a, + 0x00c5003c, 0x003e00c6, 0x004000c8, 0x003f00ca, 0x004100c9, 0x004200cb, 0x004500cc, 0x004700cf, 0x004600d2, 0x00d000d1, 0x00d30048, 0x00dc0051, + 0x00d7004c, 0x00db0050, 0x00e00055, 0x00e5005a, 0x00e7005c, 0x00e6005b, 0x00e9005e, 0x00ec0061, 0x00eb0060, 0x00ea005f, 0x00f20067, 0x00f10066, + 0x00f00065, 0x00fe0073, 0x00fb0070, 0x00f6006b, 0x00fd0072, 0x00fa006f, 0x00fc0071, 0x00020177, 0x0008017d, 0x0181007e, 0x0183000c, 0x0182000e, + 0x000f000d, 0x00530096, 0x006200de, 0x006800ed, 0x06ec06f3, 0x070707ea, 0x07080701, 0x0709070c, 0x06ef0604, 0x06f206f0, 0x06f706f6, 0x06f406f8, + 0x06ed06ee, 0x06f106f5, 0x026302f3, 0x026402fa, 0x06e706fb, 0x026502e8, 0x028c03fc, 0x02fe02fd, 0x028c04ff, 0x071f0741, 0x045a0221, 0x025b028b, + 0x025d025c, 0x0260025f, 0x026102f1, 0x02f70262, 0x02f902f8, 0x02f402ef, 0x02f302f0, 0x02f202f5, 0x036b02f6, 0x02070306, 0x026d026c, 0x0308036e, + 0x02050309, 0x02000366, 0x02010367, 0x02020368, 0x02030369, 0x0304036a, 0x030b030a, 0x020d030c, 0x060e036f, 0x037002e6, 0x0271020f, 0x03100372, + 0x02730211, 0x01750274, 0x012a0129, 0x01250152, 0x0149014a, 0x014d014c, 0x0147014e, 0x014f0148, 0x012f0132, 0x0143013c, 0x01220121, 0x01240123, + 0x01280127, 0x012c012b, 0x012e012d, 0x013d0131, 0x0140013e, 0x0141013f, 0x01450142, 0x01440146, 0x0150014b, 0x01b70151, 0x01c101b8, 0x01ce01cd, + 0x01cf01d0, 0x01d201d1, 0x01d601d5, 0x01db01d4, 0x01e101e0, 0x01ba01b9, 0x01b501e2, 0x01d901da, 0x01dd01dc, 0x01d701de, 0x01df01d8, 0x01bf01c2, + 0x01d301cc, 0x01e30153, 0x01e40154, 0x01e50155, 0x01e60156, 0x01e70157, 0x01e80158, 0x01e90159, 0x01ea015a, 0x01eb015b, 0x01ec015c, 0x01ed015d, + 0x01ee015e, 0x01ef015f, 0x01c00130, 0x013b02ab, 0x013c02ac, 0x01b60126, 0x01f00160, 0x01f10161, 0x01f20162, 0x01f30163, 0x01f40164, 0x01f50165, + 0x01f60166, 0x01f70167, 0x01f80168, 0x01f90169, 0x01fb016a, 0x01fc016c, 0x01fd016d, 0x01fe016e, 0x01ff016f, 0x01000270, 0x01010271, 0x01020272, + 0x01030273, 0x01040274, 0x01050275, 0x01070277, 0x01080278, 0x027a0179, 0x027b010a, 0x027c010b, 0x027d010c, 0x027e010d, 0x027f010e, 0x0280010f, + 0x01090210, 0x01110281, 0x01120282, 0x01130283, 0x01140284, 0x01150285, 0x01160286, 0x01170287, 0x01180288, 0x01190289, 0x011a028a, 0x011b028b, + 0x011c028c, 0x011d028d, 0x011e028e, 0x011f028f, 0x01200290, 0x01210291, 0x01220292, 0x01230293, 0x01240294, 0x01250295, 0x01260296, 0x01270297, + 0x01280298, 0x01290299, 0x012a029a, 0x012b029b, 0x012c029c, 0x012d029d, 0x012e029e, 0x012f029f, 0x013002a0, 0x013102a1, 0x013202a2, 0x013302a3, + 0x013402a4, 0x013502a5, 0x013602a6, 0x013702a7, 0x013802a8, 0x013902a9, 0x013a02aa, 0x01fa016b, 0x01060276, 0x013d02ad, 0x013e02ae, 0x013f02af, + 0x004002b0, 0x00040179, 0x00010176, 0x00030178, 0x020a017f, 0x031a03be, 0x0331031b, 0x033b0332, 0x0352033c, 0x03600353, 0x036c0361, 0x037c036d, + 0x031d037d, 0x0320031e, 0x0321031f, 0x022a031c, 0x02810280, 0x027f027e, 0x03230782, 0x0722078b, 0x032d0732, 0x033e033f, 0x033d0340, 0x02910249, + 0x029b0292, 0x079d029c, 0x07270725, 0x03540329, 0x02b00259, 0x02ae02b1, 0x072607af, 0x032a0728, 0x0370036f, 0x03720371, 0x03630362, 0x0273036e, + 0x02c202c1, 0x02c002bf, 0x072b07ba, 0x032e072c, 0x037f0380, 0x037e0381, 0x02b8028a, 0x02cb02b9, 0x07cd02cc, 0x04240730, 0x04250428, 0x03270426, + 0x042c04f3, 0x04390438, 0x04360434, 0x06350437, 0x0340063f, 0x04eb04f1, 0x04ad04bb, 0x01150414, 0x04ea0420, 0x04ac04ba, 0x04090408, 0x039a049c, + 0x03420692, 0x06da03d9, 0x05780679, 0x050f0515, 0x05130511, 0x05180517, 0x05100516, 0x06140512, 0x05650666, 0x051a0519, 0x05220525, 0x06240523, + 0x04e1045e, 0x04fe04af, 0x04dc04d6, 0x04aa04b1, 0x04ab04c1, 0x04c004f9, 0x04de04a4, 0x04a304c7, 0x04ff04df, 0x04ec04a2, 0x04ae04cb, 0x04cf04c2, + 0x04f704ce, 0x04c304fa, 0x04ed04c4, 0x04be04ee, 0x04f804bf, 0x04f604fb, 0x05fc04fd, 0x04a10403, 0x040105bc, 0x040005b0, 0x04a804a9, 0x04a704c5, + 0x065d06bd, 0x06260549, 0x046d066e, 0x05b204b3, 0x06640627, 0x065f0661, 0x06310663, 0x04e4045b, 0x04e304e2, 0x04e504e7, 0x04b904e6, 0x04b804b7, + 0x04f304f5, 0x04b604f4, 0x04b404b5, 0x04f204a5, 0x06f004f1, 0x06620668, 0x0673066c, 0x06530674, 0x06560654, 0x06430630, 0x065c0632, 0x067b0669, + 0x06480659, 0x06700671, 0x064e064a, 0x064f0650, 0x066a064d, 0x06550677, 0x06520647, 0x06570675, 0x065a0658, 0x067a066f, 0x064b0672, 0x06440645, + 0x064c066b, 0x05830576, 0x058405d3, 0x05f705e0, 0x05f805d9, 0x05f405da, 0x05f505d6, 0x057a05d7, 0x05c405ca, 0x057c05d2, 0x05c205c8, 0x067b05d1, + 0x0508060e, 0x067d05df, 0x0506060c, 0x068105dd, 0x05070614, 0x051106c5, 0x050d06cb, 0x068205e3, 0x05050613, 0x051006c3, 0x050b06c9, 0x057f05e2, + 0x05fc05e5, 0x05c105c7, 0x05e805ff, 0x058005d0, 0x06fd05e6, 0x0604060a, 0x05e90500, 0x057e05dc, 0x06fe05e7, 0x05030612, 0x050f06c6, 0x050206eb, + 0x05fb05e4, 0x060906cc, 0x05ea0501, 0x05ef05e1, 0x05f005cd, 0x059605ce, 0x059e058a, 0x0592059f, 0x05870588, 0x059d058b, 0x0591059c, 0x058d058e, + 0x058f058c, 0x05950590, 0x05860585, 0x059a0589, 0x0594059b, 0x05990598, 0x05a10593, 0x069705a0, 0x06160615, 0x05180617, 0x05ed05ee, 0x05f205ec, + 0x05f605f9, 0x05d405f1, 0x05d805db, 0x05f305cf, 0x05d505fa, 0x054205de, 0x0549054a, 0x05470548, 0x05450546, 0x054b0544, 0x05580557, 0x05430559, + 0x05780577, 0x05790576, 0x05750568, 0x0569055b, 0x056a055a, 0x056c056b, 0x0570056f, 0x05720571, 0x056e056d, 0x05bf05be, 0x05bd05c0, 0x05b3055c, + 0x05b505b4, 0x052b05b6, 0x0520052c, 0x042a0421, 0x000c0029, 0x33210082, 0x82048228, 0x42042102, 0x0d200482, 0x02240386, 0x20000000, 0x03200386, + 0x21200782, 0x03210385, 0x200782ec, 0x21038522, 0x07823e04, 0x03852320, 0x82f40321, 0x85242007, 0x96042103, 0x25200782, 0x04210385, 0x200782e8, + 0x21038526, 0x07823406, 0x03852720, 0x823f0421, 0x24778307, 0x04000029, 0x200b820a, 0x2103852a, 0x0782f203, 0x03852b20, 0x82c60421, 0x852c2007, + 0x83032003, 0x822d2047, 0x2003820b, 0x20738304, 0x820b822e, 0xe7032103, 0x2f200782, 0x03210385, 0x200782f5, 0x24038230, 0x03000039, 0x20078297, + 0x2003823a, 0x200b823b, 0x200782e9, 0x2103853c, 0x0782cd04, 0x03853d20, 0x82ca0421, 0x853e2007, 0xcc042103, 0x3f200782, 0x03210385, 0x200782ee, + 0x21038540, 0x07823306, 0x03864120, 0x07820420, 0x03824220, 0x03824320, 0x03821020, 0x03864420, 0x07821720, 0x03864520, 0x07821b20, 0x03824620, + 0xff854720, 0x82480021, 0x83038307, 0x824920d3, 0x8203830b, 0x4a0021b7, 0x03830b82, 0x07823920, 0x03864b20, 0x07823b20, 0x03864c20, 0x07823d20, + 0x03824d20, 0x6f864e20, 0x07824f20, 0x33830383, 0x0b825020, 0x56200383, 0x51200782, 0x52200382, 0x58200382, 0x53200382, 0x5d200386, 0x54200782, + 0x64200386, 0x55200782, 0x69200386, 0x56200782, 0x57200382, 0x74200382, 0x59203386, 0x7a200782, 0x5a200382, 0x80200386, 0x5b200782, 0x04210385, + 0x2007820e, 0x2103855c, 0x0782f603, 0x03825783, 0x820f0421, 0x855e200b, 0xd4042103, 0x5f200782, 0x04200385, 0x6020e383, 0x03820b82, 0x00020725, + 0x86610000, 0x828b2003, 0x82622007, 0x82632003, 0x82972003, 0x83938303, 0x829e2003, 0x8665200b, 0x82a22003, 0x82662007, 0x82672003, 0x82ac2003, + 0x86682003, 0x82b22003, 0x83b78307, 0x82b52003, 0x866a200b, 0x82c12003, 0x866b2007, 0x82c42003, 0x866c2007, 0x82c72003, 0x826d2007, 0x826e2003, + 0x82cd2003, 0x866f2003, 0x82d52003, 0x86702007, 0x82e12003, 0x82712007, 0x82722003, 0x82e32003, 0x86732003, 0x41e82003, 0x74200617, 0xef200782, + 0x75200382, 0xf4200386, 0x76200782, 0x77200382, 0xff200382, 0x78200382, 0x79240382, 0x05010000, 0x20063b41, 0x200b827a, 0x200b820b, 0x2103857b, + 0x07820c04, 0x03857c20, 0x823c0621, 0x857d2007, 0x0d042103, 0x7e200782, 0x04210385, 0x200782d2, 0x210385a0, 0x07828f04, 0x0385a120, 0x82ed0321, + 0x85a22007, 0x94042103, 0xa3200782, 0x04210385, 0x2007829d, 0x210385a4, 0x07829504, 0x0385a520, 0x829e0421, 0x85a62007, 0x3d062103, 0xa7200782, + 0x06210385, 0x20078236, 0x200385a8, 0x21068207, 0x0482a900, 0x06210382, 0x20078237, 0x210385aa, 0x07821e01, 0x0385ab20, 0x413a0421, 0xac240677, + 0xd3040000, 0xad200b82, 0x04210385, 0x20078224, 0x210385ae, 0x07823806, 0x0385af20, 0x820a0721, 0x85b02007, 0x3a062103, 0xb1200782, 0x04210385, + 0x200782d0, 0x240382b2, 0x030000b3, 0x200782ce, 0x210385b4, 0x07820307, 0x0385b520, 0x82e00421, 0x85b62007, 0x35062103, 0xb7200782, 0x03210385, + 0x200782f0, 0x210385b8, 0x07820b07, 0x0385b920, 0x82cd0321, 0x85ba2007, 0x1f012103, 0xbb200782, 0x04210385, 0x2007823b, 0x210385bc, 0x0782db03, + 0x0385bd20, 0x82d80321, 0x85be2007, 0xdc032103, 0xbf200782, 0x03210385, 0x200782ef, 0x200386c0, 0x20078209, 0x200386c1, 0x20078205, 0x200386c2, + 0x20078207, 0x200386c3, 0x2007820d, 0x200386c4, 0x20078208, 0x200386c5, 0x2007820c, 0x200386c6, 0x2007820e, 0x200386c7, 0x20078214, 0x200386c8, + 0x20078222, 0x200386c9, 0x2007821c, 0x200382ca, 0x830382cb, 0x82cc20bf, 0x83038307, 0x83db83fb, 0x82302003, 0x82ce2013, 0x82cf2003, 0x82322003, + 0x86d02003, 0x82182003, 0x86d12007, 0x82492003, 0x86d22007, 0x824f2003, 0x86d32007, 0x824b2003, 0x86d42007, 0x824d2003, 0x86d52007, 0x82542003, + 0x86d62007, 0x824e2003, 0x85d72007, 0xc8042103, 0xd8200782, 0x52200386, 0xd9200782, 0x6e200386, 0xda200782, 0x6a200386, 0xdb200782, 0xdc200382, + 0x20065743, 0x830782dd, 0x827c2003, 0x86de2007, 0x82572003, 0x86df2007, 0x82ee2003, 0x86e02007, 0x82902003, 0x86e12007, 0x828c2003, 0x86e22007, + 0x438e2003, 0xe320066f, 0x94200782, 0xe4200382, 0x8f200386, 0xe5200782, 0x93200386, 0xe6200782, 0x95200386, 0xe7200782, 0x9b200386, 0xe8200782, + 0xa9200386, 0xe9200782, 0xa3200386, 0xea200782, 0xeb200382, 0x21050343, 0x0782ec00, 0xbc200383, 0xed200782, 0xb7200386, 0xee200782, 0x2006d343, + 0x200782b9, 0x200386f0, 0x2007829f, 0x200386f1, 0x200782d4, 0x200386f2, 0x200782da, 0x200386f3, 0x200782d6, 0x200386f4, 0x200782d8, 0x830386f5, + 0x82f620f7, 0x2003830b, 0x200782d9, 0x210385f7, 0x0782c904, 0x0386f820, 0x0782dd20, 0x038af920, 0x0b82fa20, 0xf5200383, 0xfb200782, 0xfc200382, + 0x00213385, 0x820782fd, 0x07012103, 0xfe200782, 0xe2200386, 0xff200782, 0x01240385, 0x01000009, 0x03830a82, 0x820a0021, 0x2008820b, 0x21038201, + 0x0b829100, 0x03850220, 0x00060025, 0x85030100, 0x8d002103, 0x04200782, 0x00210385, 0x2007820b, 0x21038505, 0x07829200, 0x03850620, 0x82120021, + 0x85072007, 0x99002103, 0x08200782, 0x00210385, 0x20078215, 0x21038509, 0x07829c00, 0x03850a20, 0x44160021, 0x012505e3, 0x0000000b, 0x200b829d, + 0x2103850c, 0x07821300, 0x03850d20, 0x829a0021, 0x850e2007, 0x19002103, 0x0f200782, 0x00210385, 0x200782a0, 0x21038510, 0x07821a00, 0x03851120, + 0x82a10021, 0x85122007, 0x23002103, 0x13200782, 0x00210385, 0x200782aa, 0x21038514, 0x07821d00, 0x03829383, 0x82a40021, 0x8516200b, 0x21002103, + 0x17200782, 0x00210385, 0x200782a8, 0x21038518, 0x07822400, 0x03827b83, 0x82ab0021, 0x851a200b, 0x1e002103, 0x1b200782, 0x00210385, 0x200782a5, + 0x2103851c, 0x07822800, 0x03826383, 0x82af0021, 0x851e200b, 0x27002103, 0x1f200782, 0x00210385, 0x200782ae, 0x21038520, 0x07822a00, 0x03827b83, + 0x82b10021, 0x8522200b, 0x29002103, 0x23200782, 0x00210385, 0x830782b0, 0x21038287, 0x0b822d00, 0x03852520, 0x82b40021, 0x85262007, 0x2c002103, + 0x27200782, 0x00210385, 0x200782b3, 0x21038528, 0x07823800, 0x03824b83, 0x82c00021, 0x852a200b, 0x36002103, 0x2b200782, 0x00210385, 0x830782be, + 0x2103823f, 0x0b823100, 0x03826383, 0x82b80021, 0x852e200b, 0x37002103, 0x2f200782, 0x00210385, 0x200782bf, 0x21038530, 0x07823400, 0x03823383, + 0x82b60021, 0x8532200b, 0x83002003, 0x8233202b, 0x2103820b, 0x0782bd00, 0x03822783, 0x823a0021, 0x8535200b, 0xc3002103, 0x36200782, 0x00210385, + 0x2007823c, 0x20038237, 0x05134538, 0x82390121, 0x2103820b, 0x07823e00, 0x03853a20, 0x82c80021, 0x853b2007, 0x40002103, 0x3c200782, 0x00210385, + 0x200782ca, 0x2103853d, 0x07823f00, 0x03853e20, 0x82c90021, 0x820f8307, 0x41002103, 0x33830b82, 0x00210382, 0x830b82cb, 0x2103820f, 0x0b824200, + 0x00210386, 0x200b82cc, 0x21038543, 0x07824500, 0x03854420, 0x82cf0021, 0x820f8307, 0x47002103, 0x46200b82, 0x00210385, 0x830782d2, 0x2003820f, + 0x20138300, 0x820f8248, 0xd1002103, 0x49200782, 0x00210385, 0x200782d0, 0x2103854a, 0x07824800, 0x03854b20, 0x82d30021, 0x854c2007, 0x51002103, + 0x4d200782, 0x00210385, 0x200782dc, 0x2103854e, 0x07824c00, 0x03854f20, 0x82d70021, 0x85502007, 0x83002003, 0x82338307, 0xdb002103, 0x52201382, + 0x00210385, 0x20078255, 0x21038553, 0x0782e000, 0x03855420, 0x825a0021, 0x821b8307, 0xe5002103, 0x56200b82, 0x00210385, 0x2007825c, 0x21038557, + 0x0782e700, 0x03855820, 0x825b0021, 0x85592007, 0xe6002103, 0x5a200782, 0x00210385, 0x2007825e, 0x2103855b, 0x0782e900, 0x03855c20, 0x82610021, + 0x855d2007, 0xec002103, 0x5e200782, 0x00210385, 0x20078260, 0x2103855f, 0x0782eb00, 0x03820f83, 0x13830020, 0x03823383, 0x82ea0021, 0x85622017, + 0x67002103, 0x63200782, 0x00210385, 0x200782f2, 0x21038564, 0x07826600, 0x03856520, 0x82f10021, 0x820f8307, 0x83002003, 0x82672013, 0x2103820f, + 0x0782f000, 0x03856820, 0x82730021, 0x85692007, 0xfe002103, 0x6a200782, 0x00210385, 0x20078270, 0x2103856b, 0x0782fb00, 0x03856c20, 0x13830020, + 0x0b826d20, 0x00210382, 0x200782f6, 0x2103856e, 0x07827200, 0x03856f20, 0x82fd0021, 0x85702007, 0x83002003, 0x82712013, 0x2103820b, 0x0782fa00, + 0x03857220, 0x0f820020, 0x82730121, 0x2103820b, 0x0782fc00, 0x03857420, 0x82770021, 0x86752007, 0x82022003, 0x85762007, 0x7d002103, 0x77200782, + 0x08200386, 0x78200782, 0x00210385, 0x2007827e, 0x21038579, 0x07828100, 0x03867a20, 0x07820c20, 0x03857b20, 0x82830021, 0x867c2007, 0x820e2003, + 0x824b8307, 0x82002103, 0x7e200b82, 0x0d200386, 0x92200782, 0x04210385, 0x83078299, 0x21038293, 0x0b820f00, 0x0382cf83, 0x82960021, 0x85fe200b, + 0x53002103, 0xff200782, 0x00250385, 0x020000de, 0x21038518, 0x07826200, 0x03851920, 0x82ed0021, 0x851a2007, 0x68002103, 0x1b200782, 0x00210385, + 0x200782f3, 0x21038537, 0x0782c200, 0x0385b920, 0x82ec0621, 0x85ba2007, 0xea062103, 0xbc200782, 0x06210385, 0x200782e9, 0x240382c6, 0x070000c7, + 0x20078205, 0x210385c9, 0x0782eb06, 0x0385d820, 0x82070721, 0x85d92007, 0x01072103, 0xda200782, 0x07250385, 0x02000008, 0x210385db, 0x07820c07, + 0x0385dc20, 0x82090721, 0x85dd2007, 0x04072503, 0x00030000, 0x01240382, 0xef060000, 0x02200782, 0x06210385, 0x200782f2, 0x20038203, 0x20178205, + 0x200782f6, 0x21038506, 0x0782f406, 0x03850720, 0x82ee0621, 0x85082007, 0xed062103, 0x0a200782, 0x06210385, 0x200782f5, 0x2103850b, 0x0782f106, + 0x03850c20, 0x82f30621, 0x850f2007, 0xf9062103, 0x13200782, 0x14200382, 0xfa205f82, 0x26200782, 0x27200382, 0xfc200b82, 0x35200782, 0x36200382, + 0x21055758, 0x0b824203, 0x07210382, 0x2007821d, 0x21038545, 0x07821e07, 0x03857020, 0x82630221, 0x85712007, 0x83022003, 0x82722047, 0x2103820b, + 0x07826402, 0x03857320, 0x82fb0221, 0x82742007, 0x82752003, 0x82e72053, 0x85762007, 0x65022103, 0x77200782, 0x02200385, 0x7a207783, 0x03830b82, + 0x07828c20, 0x03827b20, 0x00007d24, 0x0782fd02, 0x03857e20, 0x17830420, 0x0b827f20, 0x02210382, 0x20078241, 0x21038584, 0x07821f07, 0x03858520, + 0x82210721, 0x85862007, 0x5a022103, 0x87200782, 0x04210385, 0x2007828b, 0x20038288, 0x2053828a, 0x8307825b, 0x2103824b, 0x0b825e02, 0x03828e20, + 0x17828f20, 0x07825f20, 0x03859020, 0x82f10221, 0x82912007, 0x82a12003, 0x21ff8217, 0x0b82a303, 0x0b82a920, 0x07825320, 0x0382aa20, 0x0b82ab20, + 0x07826120, 0x0382ac20, 0x0b82ae20, 0x0782f720, 0x0385af20, 0x82ef0221, 0x85b02007, 0xf4022103, 0xb1200782, 0xc9200382, 0xd6202382, 0xca200782, + 0x02210385, 0x200782f0, 0x210385cb, 0x0782f302, 0x0385cc20, 0x82f50221, 0x85cd2007, 0xf2022103, 0xce200782, 0x02210385, 0x200782f6, 0x210385cf, + 0x07826b02, 0x0382d020, 0x1342d120, 0xd2032105, 0xd4200782, 0x6c205f82, 0xd5200782, 0xd6200382, 0x21051342, 0x0782d703, 0x05200383, 0xd8200782, + 0x02210385, 0x20078266, 0x200386d9, 0x20078200, 0x210385da, 0x07826702, 0x0386db20, 0x07820120, 0x0385dc20, 0x82680221, 0x86dd2007, 0x82022003, + 0x85de2007, 0x69022103, 0xdf200782, 0x03200386, 0xe0200782, 0x02210385, 0x2007826a, 0x200386e1, 0x20078204, 0x830382f0, 0x820a20df, 0x85f42007, + 0x6f022103, 0xe7830782, 0x0e200383, 0xf620cb82, 0x06210385, 0x200782e6, 0x210385f7, 0x07827002, 0x0386f820, 0x07820f20, 0x0382f920, 0x0000fa24, + 0x07827102, 0x0382fb20, 0x0382fc20, 0x03821020, 0x0382fd20, 0x1782ff20, 0x00007324, 0x03820004, 0x00000124, 0x07822901, 0x03850220, 0x82520121, + 0x85032007, 0x25012103, 0x04200782, 0x01210385, 0x2007824a, 0x21038505, 0x07824901, 0x03820620, 0xe7460820, 0x09042105, 0x0a200b82, 0x47200b82, + 0x0b200782, 0x01210385, 0x2007824f, 0x2103850c, 0x07823201, 0x03850d20, 0x822f0121, 0x850e2007, 0x3c012103, 0x0f200782, 0x01210385, 0x24078243, + 0x04000010, 0x05374913, 0x82140421, 0x8215200b, 0x8227200b, 0x82162007, 0x48192003, 0x042105d3, 0x820b821a, 0x31012103, 0x1b200782, 0x23200382, + 0x21058b48, 0x0b822404, 0x2b482520, 0x26042105, 0x03820b82, 0x82400121, 0x85272007, 0x3f012103, 0x28200782, 0xeb820382, 0x82410121, 0x822a2007, + 0x822b2003, 0x8245202f, 0x852c2007, 0x44012103, 0x2d200782, 0x01210385, 0x2007824b, 0x2003822e, 0x059b472f, 0x82300421, 0x8233200b, 0x82b1200b, + 0x82342007, 0x82352003, 0x82b7200b, 0x82362007, 0x82392003, 0x82bb200b, 0x853a2007, 0xc1012103, 0x3b200782, 0x43200382, 0xc3201782, 0x57830782, + 0x01216782, 0x200b82cd, 0x21038546, 0x0782d001, 0x03854720, 0x82cf0121, 0x82482007, 0x82492003, 0x82d1202f, 0x824a2007, 0x824b2003, 0x82d5200b, + 0x854c2007, 0xd4012103, 0x4d200782, 0x01210385, 0x200782db, 0x2003824e, 0x2023824f, 0x200782e0, 0x20038250, 0x200b8251, 0x200782b9, 0x21038552, + 0x0782e201, 0x03855320, 0x82b50121, 0x85542007, 0xda012103, 0x55200782, 0x01210385, 0x200782d9, 0x20038256, 0x203b8258, 0x200782dc, 0x20038259, + 0x200b825a, 0x200782d7, 0x2103855b, 0x0782df01, 0x03855c20, 0x82c20121, 0x855d2007, 0xbf012103, 0x5e200782, 0x01210385, 0x200782cc, 0x2103855f, + 0x0782d301, 0x03856020, 0x7f830120, 0x0b826120, 0x01210382, 0x200782e3, 0x21038562, 0x07825401, 0x03856320, 0x82e40121, 0x85642007, 0x83012003, + 0x82652097, 0x2103820b, 0x0782e501, 0x03856620, 0x82560121, 0x85672007, 0xe6012103, 0x68200782, 0x01210385, 0x20078257, 0x21038569, 0x0782e701, + 0x03856a20, 0x82580121, 0x856b2007, 0xe8012103, 0x6c200782, 0x01210385, 0x20078259, 0x2103856d, 0x0782e901, 0x03856e20, 0x825a0121, 0x856f2007, + 0xea012103, 0x70200782, 0x01210385, 0x2007825b, 0x21038571, 0x0782eb01, 0x03857220, 0x825c0121, 0x85732007, 0xec012103, 0x74200782, 0x01210385, + 0x2007825d, 0x21038575, 0x0782ed01, 0x03857620, 0x825e0121, 0x85772007, 0xee012103, 0x78200782, 0x01210385, 0x2007825f, 0x21038579, 0x0782ef01, + 0x03858a20, 0x82300121, 0x858b2007, 0xc0012103, 0x8c200782, 0x01210385, 0x200782ab, 0x2103858d, 0x07823b02, 0x03858e20, 0x82ac0121, 0x858f2007, + 0x3c022103, 0x90200782, 0x01210385, 0x20078226, 0x21038591, 0x0782b601, 0x03859220, 0x82600121, 0x85932007, 0xf0012103, 0x94200782, 0x01210385, + 0x20078261, 0x21038595, 0x0782f101, 0x03859620, 0x82620121, 0x85972007, 0xf2012103, 0x98200782, 0x01210385, 0x20078263, 0x21038599, 0x0782f301, + 0x03859a20, 0x82640121, 0x859b2007, 0xf4012103, 0x9c200782, 0x01210385, 0x20078265, 0x2103859d, 0x0782f501, 0x03859e20, 0x82660121, 0x859f2007, + 0xf6012103, 0xa0200782, 0x01210385, 0x20078267, 0x210385a1, 0x0782f701, 0x0385a220, 0x82680121, 0x85a32007, 0xf8012103, 0xa4200782, 0x01210385, + 0x20078269, 0x210385a5, 0x0782f901, 0x0385a620, 0x826a0121, 0x85a72007, 0xfb012103, 0xa8200782, 0x01210385, 0x2007826c, 0x210385a9, 0x0782fc01, + 0x0385aa20, 0x826d0121, 0x85ab2007, 0xfd012103, 0xac200782, 0x01210385, 0x2007826e, 0x210385ad, 0x0782fe01, 0x0385ae20, 0x826f0121, 0x85af2007, + 0xff012103, 0x09610782, 0x70012106, 0xb1200b82, 0x02210385, 0x20078200, 0x210385b2, 0x07827101, 0x0385b320, 0x82010221, 0x85b42007, 0x72012103, + 0xb5200782, 0x02210385, 0x20078202, 0x210385b6, 0x07827301, 0x0385b720, 0x82030221, 0x85b82007, 0x74012103, 0xb9200782, 0x02210385, 0x20078204, + 0x210385ba, 0x07827501, 0x0385bb20, 0x82050221, 0x85bc2007, 0x77012103, 0xbd200782, 0x02210385, 0x20078207, 0x210385be, 0x07827801, 0x0385bf20, + 0x82080221, 0x82c02007, 0x00c12403, 0x82790100, 0x85c22007, 0x0a022103, 0xc3200782, 0x01210385, 0x2007827b, 0x210385c4, 0x07820b02, 0x0385c520, + 0x827c0121, 0x85c62007, 0x0c022103, 0xc7200782, 0x01210385, 0x2007827d, 0x210385c8, 0x07820d02, 0x0385c920, 0x827e0121, 0x85ca2007, 0x0e022103, + 0xcb200782, 0x01210385, 0x2007827f, 0x210385cc, 0x07820f02, 0x0385cd20, 0x82800121, 0x85ce2007, 0x10022503, 0xcf040000, 0x02210385, 0x20078209, + 0x210385d0, 0x07828101, 0x0385d120, 0x82110221, 0x85d22007, 0x82012103, 0xd3200782, 0x02250385, 0x04000012, 0x210385d4, 0x07828301, 0x0385d520, + 0x82130221, 0x85d62007, 0x84012103, 0xd7200782, 0x02210385, 0x20078214, 0x210385d8, 0x07828501, 0x0385d920, 0x82150221, 0x85da2007, 0x86012103, + 0xdb200782, 0x02210385, 0x20078216, 0x210385dc, 0x07828701, 0x0385dd20, 0x82170221, 0x85de2007, 0x88012103, 0xdf200782, 0x02210385, 0x20078218, + 0x210385e0, 0x07828901, 0x0385e120, 0x82190221, 0x85e22007, 0x8a012103, 0xe3200782, 0x02210385, 0x2007821a, 0x210385e4, 0x07828b01, 0x0385e520, + 0x821b0221, 0x85e62007, 0x8c012103, 0xe7200782, 0x02210385, 0x2007821c, 0x210385e8, 0x07828d01, 0x0385e920, 0x821d0221, 0x85ea2007, 0x8e012103, + 0xeb200782, 0x02210385, 0x2007821e, 0x210385ec, 0x07828f01, 0x0385ed20, 0x821f0221, 0x85ee2007, 0x90012103, 0xef200782, 0x02210385, 0x20078220, + 0x210385f0, 0x07829101, 0x0385f120, 0x82210221, 0x85f22007, 0x92012103, 0xf3200782, 0x02210385, 0x20078222, 0x210385f4, 0x07829301, 0x0385f520, + 0x82230221, 0x85f62007, 0x94012103, 0xf7200782, 0x02210385, 0x20078224, 0x210385f8, 0x07829501, 0x0385f920, 0x82250221, 0x85fa2007, 0x96012103, + 0xfb200782, 0x02210385, 0x20078226, 0x210385fc, 0x07829701, 0x0385fd20, 0x82270221, 0x85fe2007, 0x98012103, 0xff200782, 0x02250385, 0x05000028, + 0x21038500, 0x07829901, 0x03850120, 0x82290221, 0x85022007, 0x9a012103, 0x03200782, 0x02210385, 0x2007822a, 0x21038504, 0x07829b01, 0x03850520, + 0x822b0221, 0x85062007, 0x9c012103, 0x07200782, 0x02210385, 0x2007822c, 0x21038508, 0x07829d01, 0x03850920, 0x822d0221, 0x850a2007, 0x9e012103, + 0x0b200782, 0x02210385, 0x2007822e, 0x2103850c, 0x07829f01, 0x03850d20, 0x822f0221, 0x850e2007, 0xa0012103, 0x0f200782, 0x02210385, 0x20078230, + 0x21038510, 0x0782a101, 0x03851120, 0x82310221, 0x85122007, 0xa2012103, 0x13200782, 0x02210385, 0x20078232, 0x21038514, 0x0782a301, 0x03851520, + 0x82330221, 0x85162007, 0xa4012103, 0x17200782, 0x02210385, 0x20078234, 0x21038518, 0x0782a501, 0x03851920, 0x82350221, 0x851a2007, 0xa6012103, + 0x1b200782, 0x02210385, 0x20078236, 0x2103851c, 0x0782a701, 0x03851d20, 0x82370221, 0x851e2007, 0xa8012103, 0x1f200782, 0x02210385, 0x20078238, + 0x21038520, 0x0782a901, 0x03852120, 0x82390221, 0x85222007, 0xaa012103, 0x23200782, 0x02210385, 0x2007823a, 0x21038524, 0x07826b01, 0x03852520, + 0x82fa0121, 0x85262007, 0x76012103, 0x27200782, 0x02210385, 0x20078206, 0x21038528, 0x0782ad01, 0x03852920, 0x823d0221, 0x852a2007, 0xae012103, + 0x2b200782, 0x02210385, 0x2007823e, 0x2103852c, 0x0782af01, 0x03852d20, 0x823f0221, 0x852e2007, 0xb0012103, 0x2f200782, 0x02250385, 0x14000040, + 0x21038505, 0x07828d03, 0x03850a20, 0x008e0325, 0x85801e00, 0x79002103, 0x81200782, 0x01210385, 0x20078204, 0x20038582, 0x21a78200, 0x0b82831e, + 0x01210382, 0x20078201, 0x25038584, 0x00007800, 0x0385851e, 0x82030121, 0x859e2007, 0x63002103, 0xf2200782, 0x00210385, 0x2007827f, 0x200385f3, + 0x29738201, 0x0000001f, 0x0000071f, 0x07821203, 0x03820820, 0x00000f23, 0x215f8202, 0x0b82101f, 0x17821520, 0x1f21df82, 0x200b8218, 0x2017821d, + 0x2007828b, 0x20038220, 0x20178227, 0x20078233, 0x82038228, 0x930221cf, 0x30200782, 0x37200382, 0x4a201782, 0x38200782, 0xf7820382, 0x82a60221, + 0x21e78207, 0x1782451f, 0x0b825a20, 0x03824820, 0x47824d20, 0x0782b220, 0x03825020, 0x17825720, 0x07826420, 0x03855920, 0x82bb0221, 0x855b2007, + 0xbc022103, 0x5d200782, 0x02210385, 0x200782bd, 0x2103855f, 0x0782be02, 0x03826020, 0x3b826720, 0x07827420, 0x03826820, 0x53826f20, 0x0782c320, + 0x03827020, 0x17827120, 0x07821a20, 0x03827220, 0x0b827320, 0x07823120, 0x75202783, 0x3b200b82, 0x76200b82, 0x77200382, 0x52200b82, 0x78200782, + 0x79200382, 0x4f830b82, 0x0b827a20, 0x0b827b20, 0x07826c20, 0x00007c24, 0x0b827d1f, 0x00007c24, 0x0382801f, 0x0b828720, 0x07822220, 0x03828820, + 0x6b828f20, 0x07828320, 0x03829020, 0x17829720, 0x07824120, 0x03829820, 0x17829f20, 0x07829e20, 0x0382a020, 0x1782a720, 0x07828220, 0x0382a820, + 0x1782af20, 0x0782ce20, 0x0382b020, 0x1782b120, 0x07821d20, 0x0385b220, 0x82200321, 0x85b32007, 0x1f032103, 0xb4200782, 0x03210385, 0x20078221, + 0x210385b6, 0x07821c03, 0x0385b720, 0x822a0321, 0x82b82007, 0x82b92003, 0x82802053, 0x82ba2007, 0x82bb2003, 0x007e240b, 0x85bc1f00, 0x82022103, + 0xbd200782, 0x07210385, 0x20078223, 0x210385be, 0x07828b03, 0x0385bf20, 0x82220721, 0x85c02007, 0x32072103, 0xc1200782, 0x07210385, 0x2007822d, + 0x210385c2, 0x07823f03, 0x0385c320, 0x823e0321, 0x85c42007, 0x40032103, 0xc6200782, 0x03210385, 0x2007823d, 0x210385c7, 0x07824903, 0x0382c820, + 0x8f82c920, 0x07829120, 0x0382ca20, 0x0b82cc20, 0x07829b20, 0x0385cd20, 0x82250721, 0x85ce2007, 0x27072103, 0xcf200782, 0x07210385, 0x20078229, + 0x240382d0, 0x030000d3, 0x20078255, 0x210385d6, 0x07825403, 0x0385d720, 0x82590321, 0x82d82007, 0x82d92003, 0x82b02053, 0x82da2007, 0x82db2003, + 0x82ae200b, 0x85dd2007, 0x26072103, 0xde200782, 0x07210385, 0x20078228, 0x210385df, 0x07822a07, 0x0382e020, 0x5f82e320, 0x07826f20, 0x0382e420, + 0x0b82e520, 0x07826220, 0x0385e620, 0x826e0321, 0x85e72007, 0x73032103, 0xe8200782, 0xe9200382, 0xc1205f82, 0xea200782, 0xeb200382, 0xbf200b82, + 0xec200782, 0x02210385, 0x200782ba, 0x240382ed, 0x070000ee, 0x2007822b, 0x210385ef, 0x07822e07, 0x0385f220, 0x82800321, 0x85f32007, 0x7f032103, + 0xf4200782, 0x03210385, 0x20078281, 0x250385f6, 0x00007e03, 0x0385f71f, 0x828a0321, 0x82f82007, 0x82f92003, 0x82b8206b, 0x82fa2007, 0x82fc2003, + 0x82cb200b, 0x85fd2007, 0x30072103, 0xfe200782, 0x07250385, 0x20000024, 0x24038207, 0x04000008, 0x2007828d, 0x2103850b, 0x07829004, 0x03851220, + 0x82280421, 0x82132007, 0x00152403, 0x82250400, 0x85162007, 0x82032003, 0x17202197, 0x03820b82, 0x822c0421, 0x82182007, 0x82192003, 0x82382023, + 0x851a2007, 0x34042103, 0x1c200782, 0x1d200382, 0x2105b34e, 0x0b821e20, 0x04210382, 0x20078235, 0x24038220, 0x06000021, 0x2007823f, 0x21038522, + 0x0782f103, 0x03852620, 0x82eb0321, 0x20ab8207, 0x21038220, 0x0b82e904, 0x03823920, 0x47823a20, 0x07823c20, 0x03854420, 0x82d60321, 0x854a2007, + 0xf7032103, 0x70200782, 0x03210385, 0x200782cc, 0x24038274, 0x03000079, 0x200782d0, 0x2103857a, 0x0782eb04, 0x03857b20, 0x82bb0421, 0x857c2007, + 0xad042103, 0x7d200782, 0x7e200382, 0x14205f82, 0x7f200782, 0x01210385, 0x24078220, 0x20000080, 0x20478289, 0x200782ae, 0x2103858a, 0x0782ea04, + 0x03858b20, 0x82ba0421, 0x858c2007, 0xac042103, 0x8d200782, 0x8e200382, 0x2005a750, 0x820f8320, 0x98042103, 0xaf201382, 0x04210385, 0x20078297, + 0x210385b9, 0x07829c04, 0x03823f83, 0x829a0421, 0x85bd200b, 0x9b042503, 0x02210000, 0x03210385, 0x20078290, 0x2103850d, 0x07829103, 0x03851320, + 0x823e0621, 0x85152007, 0x92032103, 0x16200782, 0x06210385, 0x20078242, 0x20038219, 0x20b3821a, 0x20078293, 0x2103851d, 0x07829503, 0x03852220, + 0x82390621, 0x85242007, 0x96032103, 0x2e200782, 0x06210385, 0x20078241, 0x20038253, 0x203b8254, 0x200782d9, 0x20038255, 0x200b825e, 0x200782dd, + 0x2103855f, 0x0782d703, 0x03858a20, 0x82790621, 0x858b2007, 0x78062103, 0x90200782, 0x05200385, 0x91209783, 0x03820b82, 0x820f0521, 0x85922007, + 0x11052103, 0x93200782, 0x05210385, 0x20078213, 0x82038294, 0x17052197, 0x96200782, 0x05200385, 0x9720c783, 0x03820b82, 0x82100521, 0x85982007, + 0x12052103, 0x99200782, 0x05210385, 0x20078214, 0x210385a9, 0x07821b05, 0x0382b020, 0x0000b324, 0x07821c05, 0x0385de20, 0x82660621, 0x85df2007, + 0x65062103, 0xe4200782, 0xe5200382, 0x19202382, 0xe6200782, 0x05210385, 0x20078225, 0x200382e7, 0x201782e9, 0x20078222, 0x200385ea, 0x82f38206, + 0x8300200e, 0x02052403, 0x86220000, 0xe1042103, 0x03200b82, 0x04210385, 0x200782af, 0x21038504, 0x0782fe04, 0x03850520, 0x82d60421, 0x85062007, + 0xdc042103, 0x07200782, 0x04210385, 0x200782b1, 0x21038508, 0x0782aa04, 0x03850920, 0x82c10421, 0x850a2007, 0xab042103, 0x0b200782, 0x04210385, + 0x200782f9, 0x2103850c, 0x0782c004, 0x03850d20, 0x82a40421, 0x850f2007, 0xdd042103, 0x11200782, 0x04210385, 0x200782de, 0x21038512, 0x0782c704, + 0x03851520, 0x82a60421, 0x20f38207, 0x21038222, 0x0b82a304, 0x03851a20, 0x82df0421, 0x851e2007, 0xd5042103, 0x27200782, 0x2b200382, 0x21057b4c, + 0x0b823422, 0x04210382, 0x200782ff, 0x21038535, 0x0782a204, 0x03853620, 0x82ec0421, 0x85482007, 0xd1042103, 0x60200782, 0x04210385, 0x200782cb, + 0x21038561, 0x0782ae04, 0x03856220, 0x82c20421, 0x85642007, 0xcf042103, 0x65200782, 0x04210385, 0x200782ce, 0x21038582, 0x0782f704, 0x03858320, + 0x82fa0421, 0x82842007, 0x4d852003, 0x222105fb, 0x200b8286, 0x050f4c87, 0x00882225, 0x4e892200, 0x22250543, 0x2200008a, 0x05a34b8a, 0x008b2224, + 0x03822200, 0x82fb0421, 0x82ab8307, 0xf6042103, 0xf3830b82, 0x04210382, 0x200b82fd, 0x210385a4, 0x0782fc04, 0x0385a520, 0x82030521, 0x85a62007, + 0xa1042103, 0xa7200782, 0x04210385, 0x200782bc, 0x210385a8, 0x07820105, 0x0385a920, 0x82b00421, 0x85aa2007, 0x00052103, 0xab200782, 0x04210385, + 0x200782a9, 0x210385ac, 0x0782a804, 0x0385ad20, 0x82c50421, 0x85ae2007, 0x83042003, 0x82af205b, 0x2303820b, 0x0000bd04, 0x22069e66, 0x823b0600, + 0x8502200b, 0x5d062103, 0x03200782, 0x06210385, 0x20078249, 0x21038504, 0x07822605, 0x23207082, 0x06210382, 0x200b826e, 0x21038506, 0x07826d06, + 0x03851020, 0x82ef0421, 0x85182007, 0x67062103, 0x20200782, 0x04210385, 0x200782b3, 0x21038521, 0x0782b204, 0x03852420, 0x82270521, 0x85252007, + 0x64062103, 0x26200782, 0x06210385, 0x20078261, 0x21038527, 0x07825f06, 0x03852820, 0x82630621, 0x852b2007, 0x60062103, 0x87200782, 0x06210385, + 0x20078231, 0x21038588, 0x07825b06, 0x03858b20, 0x82460621, 0x859b2007, 0xe4042103, 0x9c200782, 0x9d200382, 0x21055b4e, 0x0b829e23, 0x04210382, + 0x200782e7, 0x2003829f, 0x054f4ea0, 0x82a12321, 0x2103820b, 0x0782b904, 0x0382a220, 0x8350a320, 0xa4232105, 0x03820b82, 0x82f50421, 0x82a52007, + 0x4da62003, 0x232105d7, 0x820b82a7, 0xb6042103, 0xa8200782, 0x04210385, 0x200782b5, 0x210385a9, 0x0782b404, 0x0385aa20, 0x82a50421, 0x85ab2007, + 0xf2042103, 0xac200782, 0x04210385, 0x200782f1, 0x210385ad, 0x0782f004, 0x0385ce20, 0x82680621, 0x85cf2007, 0x62062503, 0x00240000, 0x06210385, + 0x2007826c, 0x24038201, 0x06000002, 0x20078273, 0x20038203, 0x200b8204, 0x20078253, 0x21038505, 0x07825606, 0x03850620, 0x82300621, 0x85072007, + 0x43062103, 0x08200782, 0x06210385, 0x20078232, 0x21038509, 0x07825c06, 0x03850a20, 0x82690621, 0x850b2007, 0x7b062103, 0x0c200782, 0x06210385, + 0x20078259, 0x2103850d, 0x07824806, 0x03850e20, 0x82710621, 0x850f2007, 0x70062103, 0x10200782, 0x06210385, 0x2007824a, 0x21038511, 0x07824e06, + 0x03851220, 0x82500621, 0x85132007, 0x4f062103, 0x14200782, 0x06210385, 0x2007824d, 0x21038515, 0x07826a06, 0x03851620, 0x82770621, 0x85172007, + 0x55062103, 0x18200782, 0x06210385, 0x20078247, 0x21038519, 0x07825206, 0x03851a20, 0x82750621, 0x821b2007, 0x001c2403, 0x82570600, 0x851d2007, + 0x5a062103, 0x1e200782, 0x06210385, 0x2007826f, 0x2103851f, 0x07827a06, 0x03852020, 0x82720621, 0x85212007, 0x4b062103, 0x22200782, 0x06210385, + 0x20078245, 0x21038523, 0x07824406, 0x03852420, 0x826b0621, 0x85252007, 0x4c062103, 0x26200782, 0x06230385, 0x69000076, 0x002206e6, 0x0b828305, + 0x03850120, 0x82d30521, 0x85022007, 0x84052103, 0x03200782, 0x05210385, 0x200782e0, 0x21038504, 0x0782f705, 0x03850520, 0x82d90521, 0x85062007, + 0xf8052103, 0x07200782, 0x05210385, 0x200782da, 0x21038508, 0x0782f405, 0x03850920, 0x82d60521, 0x850a2007, 0xf5052103, 0x0b200782, 0x05210385, + 0x200782d7, 0x2003850c, 0x21ef8205, 0x0b820d25, 0x05210382, 0x200782ca, 0x2103850e, 0x0782c405, 0x03850f20, 0x82d20521, 0x85102007, 0x7c052103, + 0x11200782, 0x05210385, 0x200782c8, 0x21038512, 0x0782c205, 0x03851320, 0x82d10521, 0x85142007, 0x7b052103, 0x15200782, 0x06200385, 0x16205b83, + 0x03820b82, 0x82080621, 0x85172007, 0xdf052103, 0x18200782, 0x05210385, 0x2007827d, 0x21038519, 0x07820c06, 0x03851a20, 0xf7830620, 0x0b821b20, + 0x05210382, 0x200782dd, 0x2103851c, 0x07828105, 0x03851d20, 0x82140621, 0x851e2007, 0x07062103, 0x1f200782, 0x05210385, 0x200782c5, 0x21038520, + 0x07821106, 0x03852120, 0x82cb0521, 0x85222007, 0x0d062103, 0x23200782, 0x05210385, 0x200782e3, 0x21038524, 0x07828205, 0x03852520, 0x82130621, + 0x85262007, 0x05062103, 0x27200782, 0x05210385, 0x200782c3, 0x21038528, 0x07821006, 0x03852920, 0x82c90521, 0x852a2007, 0x0b062103, 0x2b200782, + 0x05210385, 0x200782e2, 0x2103852c, 0x07827f05, 0x03852d20, 0x82e50521, 0x852e2007, 0xfc052103, 0x2f200782, 0x05210385, 0x200782c7, 0x21038530, + 0x0782c105, 0x03853120, 0x82ff0521, 0x85322007, 0xe8052103, 0x33200782, 0x05210385, 0x200782d0, 0x21038534, 0x07828005, 0x03853520, 0x82e60521, + 0x85362007, 0xfd052103, 0x37200782, 0x06210385, 0x2007820a, 0x21038538, 0x07820406, 0x03853920, 0x82000621, 0x853a2007, 0xe9052103, 0x3b200782, + 0x05210385, 0x200782dc, 0x2103853c, 0x07827e05, 0x03853d20, 0x82e70521, 0x853e2007, 0xfe052103, 0x3f200782, 0x06210385, 0x20078212, 0x21038540, + 0x07820306, 0x03854120, 0x82c60521, 0x85422007, 0x0f062103, 0x43200782, 0x05210385, 0x200782eb, 0x21038544, 0x07820206, 0x03854520, 0x82e40521, + 0x85462007, 0xfb052103, 0x47200782, 0x05210385, 0x200782cc, 0x21038548, 0x07820906, 0x03854920, 0x82010621, 0x854a2007, 0xea052103, 0x4b200782, + 0x05210385, 0x200782e1, 0x2103854c, 0x0782ef05, 0x03854d20, 0x82cd0521, 0x854e2007, 0xf0052103, 0x4f200782, 0x05210385, 0x200782ce, 0x25038550, + 0x00009605, 0x03855125, 0x828a0521, 0x82522007, 0x00532403, 0x829e0500, 0x85542007, 0x92052103, 0x55200782, 0x05210385, 0x20078288, 0x21038556, + 0x07828705, 0x03855720, 0x828b0521, 0x85582007, 0x9d052103, 0x59200782, 0x05210385, 0x2007829c, 0x2103855a, 0x07829105, 0x03855b20, 0x828e0521, + 0x855c2007, 0x8d052103, 0x5d200782, 0x05210385, 0x2007828c, 0x2003825e, 0x2083825f, 0x2007828f, 0x21038560, 0x07829505, 0x03826120, 0x17826220, + 0x07828520, 0x03856320, 0x82890521, 0x82642007, 0x82652003, 0x829a2017, 0x85662007, 0x94052503, 0x67250000, 0x68200382, 0x98201782, 0x69200782, + 0x05210385, 0x20078293, 0x2103856a, 0x0782a105, 0x03856b20, 0x82a00521, 0x856c2007, 0x97052103, 0x6d200782, 0x70240382, 0x15060000, 0x71200782, + 0x05210385, 0x200782ee, 0x21038572, 0x0782ed05, 0x03857320, 0x82ec0521, 0x85742007, 0xf2052103, 0x75200782, 0x05210385, 0x200782f9, 0x21038576, + 0x0782f605, 0x03857720, 0x82f10521, 0x85782007, 0xd4052103, 0x79200782, 0x05210385, 0x200782db, 0x2103857a, 0x0782d805, 0x03857b20, 0x82cf0521, + 0x857c2007, 0xf3052103, 0x7d200782, 0x05210385, 0x200782fa, 0x2103857e, 0x0782d505, 0x03857f20, 0x82de0521, 0x85802007, 0x42052103, 0x81200782, + 0x88240382, 0x3a050000, 0x89200782, 0x05210385, 0x2007824a, 0x2103858a, 0x07824905, 0x03858b20, 0x82480521, 0x858c2007, 0x47052103, 0x8d200782, + 0x05210385, 0x20078246, 0x2103858e, 0x07824505, 0x03858f20, 0x82440521, 0x85902007, 0x4b052103, 0x91200782, 0x93200382, 0x57206b82, 0x94200782, + 0x05210385, 0x20078243, 0x20038295, 0x2017829f, 0x2007824c, 0x200382a0, 0x200b82ab, 0x200782a2, 0x200382ac, 0x200b82ad, 0x20078277, 0x210385ae, + 0x07827605, 0x0385af20, 0x82790521, 0x85b22007, 0xb7052103, 0xb6200782, 0x05210385, 0x200782b8, 0x210385ba, 0x0782bb05, 0x0385bc20, 0x82b90521, + 0x85c02007, 0x83052003, 0x82c4201f, 0x2003820b, 0x201f8305, 0x200b82c6, 0x206b82c7, 0x20078273, 0x210385c9, 0x07826805, 0x0385ca20, 0x82750521, + 0x85cb2007, 0x5b052103, 0xce200782, 0x05210385, 0x20078269, 0x210385cf, 0x07825a05, 0x0382d020, 0x4782d320, 0x07825d20, 0x0385d520, 0x82630521, + 0x82d62007, 0x82d72003, 0x82612017, 0x82d92007, 0x82db2003, 0x826a200b, 0x82dc2007, 0x82df2003, 0x826f200b, 0x82e02007, 0x82e12003, 0x826d200b, + 0x82e22007, 0x82e42003, 0x82be200b, 0x85e52007, 0xbd052103, 0xe7200782, 0xeb200382, 0xae201782, 0xef200782, 0x05210385, 0x2007825c, 0x200382f0, + 0x201782f3, 0x200782b3, 0x200382f4, 0x240b82f7, 0x26000064, 0x24038210, 0x06000012, 0x20078219, 0x21038520, 0x07821c06, 0x03823020, 0x17823720, + 0x07821d20, 0x03823920, 0x0b823c20, 0x07822520, 0x03854020, 0x82290621, 0x85422007, 0x2a062103, 0x60200782, 0x06210385, 0x2007822b, 0x21038563, + 0x07822c06, 0x03826520, 0x3b826620, 0x07822d20, 0x2621cf82, 0x820b826b, 0x132724b7, 0x82270000, 0x2f062103, 0x70200782, 0x71240382, 0x12040000, + 0xa1200782, 0x05200385, 0x27217382, 0x240b82e8, 0x040000e9, 0x82078289, 0xf12721bf, 0x5f82b382, 0x82f22721, 0x56f3200f, 0x27200523, 0x2721cb82, + 0x240b82ff, 0x2b00002d, 0x20038505, 0x218f8205, 0x0b82062b, 0x17820720, 0x00002824, 0x03853a2e, 0x822a0421, 0x853b2007, 0x29042503, 0x0c300000, + 0x0d200382, 0x10245f82, 0x00e00000, 0x03240382, 0x33070000, 0xa0200782, 0xa2200382, 0xff820b82, 0x82b0e021, 0x82b3200b, 0x2043820b, 0x836782fe, + 0x93042503, 0x62ff0000, 0xe7820382, 0x001c0425, 0x8439d501, 0x03002603, 0xf301008f, 0x08038410, 0x51060026, 0x50000400, 0x600498ff, 0x0300c605, + 0x27000700, 0x5e003300, 0x01275b40, 0x4c010504, 0x05060700, 0x80050706, 0x28087482, 0x03000803, 0x00080067, 0x06080706, 0x00050069, 0x04050904, + 0x00090069, 0x0a09020a, 0x01020069, 0x00570201, 0x5f010202, 0x3509820b, 0x00004f01, 0x292b2f31, 0x1a1c2022, 0x0f101517, 0x06070a0c, 0x5e820405, + 0x0c11033e, 0x172b1706, 0x25112111, 0x01211121, 0x22230614, 0x3e353526, 0x26343502, 0x07062223, 0x34260e84, 0x16323336, 0x0d821415, 0x23830886, + 0x04502508, 0x035efc10, 0x01cafc36, 0x14131fa8, 0x204e481e, 0x2d1e4634, 0x160b0f1d, 0x7844761a, 0x78635b66, 0x281e1e28, 0x21080383, 0xf92e0668, + 0x5e0568d2, 0x1b15a6fc, 0x04a8161a, 0x42373f20, 0x060c0a48, 0x2925141a, 0x736a6680, 0x2682ec0f, 0x2a2a202d, 0x00020020, 0x0400001f, 0x82620592, + 0x000a2cf5, 0x00234026, 0x01000004, 0x82680004, 0x4d382dc7, 0x01020305, 0x4e013901, 0x090a0000, 0x07302082, 0x06111111, 0x212b1909, 0x23032103, + 0x01013301, 0xc03f0782, 0x68f6fd68, 0xfabc01c7, 0xc2fdbd01, 0x01ae01d8, 0x05a9fe57, 0x049efa62, 0x0034fdc2, 0x85ffff00, 0x2307235f, 0x59832200, + 0x07020025, 0x89000312, 0xff062117, 0x16211788, 0x21178afe, 0x17882807, 0x16821420, 0x06214788, 0x211788e5, 0x2f8bff0f, 0x17882920, 0x178b1120, + 0x88c20621, 0x83192017, 0x21ef8317, 0xef842dfe, 0x001a2b08, 0x4065001d, 0x0301130a, 0x00010902, 0x4b4c0203, 0x585019b0, 0x06001f40, 0x06030200, + 0x04006802, 0x074d3804, 0x03030205, 0x69824d39, 0x0061012a, 0x013d0101, 0x1c401b4e, 0x00252188, 0x01000100, 0x08288a65, 0x594e0328, 0x00001040, + 0x1a001c1d, 0x11111a00, 0x08262317, 0x212b1b09, 0x1415020e, 0x37323316, 0x22230607, 0x34352626, 0x40413736, 0x33043109, 0x35286b62, 0x1343373b, + 0x734c3c41, 0x5d8f8b3e, 0x300d4f41, 0x28464c2a, 0x8e0e312f, 0x3b5d350f, 0x01369262, 0x0b5e4133, 0x21081741, 0xe7886d07, 0xff8c1720, 0x20095f41, + 0x08ff8518, 0x00e8ff30, 0x05be0400, 0x000f0062, 0x403c0012, 0x00040039, 0x05040805, 0x00080067, 0x00080600, 0x03030067, 0x02005f02, 0x004d3802, + 0x5f010606, 0x01420709, 0x11122107, 0x0f213282, 0x22008511, 0x421d090a, 0x21250605, 0x21132107, 0x08038315, 0x2103012e, 0xfe45d302, 0x01c75c7d, + 0x17f9028b, 0x01603afe, 0x62b2fe6b, 0x24fd5001, 0x013701ab, 0x05a8fe58, 0x40fe9a62, 0x9a2cfe9a, 0x2afdcc04, 0x8b85bb82, 0x82230721, 0x000e27bb, + 0x07020000, 0x06827a12, 0x00030023, 0x20a382b4, 0x2ca38441, 0x00210018, 0x0c2c402f, 0x01030401, 0x2419824c, 0x04030504, 0x249e8267, 0x01005f01, + 0x23a38201, 0x5f000505, 0x26083382, 0x214e0039, 0x212a2124, 0x1c090622, 0x0606242b, 0x21112123, 0x14150432, 0x16160706, 0x23260015, 0x32331123, + 0x87123536, 0x04390808, 0x8eec9341, 0x630180fe, 0x921801d6, 0xfeb3886d, 0xbc7f86fa, 0x367b7acc, 0xd2db8399, 0xb1fca97c, 0xa162054b, 0x19987bbb, + 0x029d9b17, 0x56fe63da, 0x19fe716a, 0x651dfe70, 0x356b8284, 0x75000100, 0x7604e7ff, 0x1c007b05, 0x31403400, 0x03000102, 0x05820310, 0x02011125, + 0x824c0301, 0x61032721, 0x03030104, 0xa2824d3e, 0x82610221, 0x023f22ac, 0x3615824e, 0x251b001c, 0x09052426, 0x16002b19, 0x23260717, 0x15060622, + 0x82161614, 0x17372198, 0x3e08b182, 0x35022422, 0x33241234, 0x57bb5003, 0x74a57a6b, 0xb4686cb5, 0x42946777, 0x8cd14863, 0x9deefead, 0xa61101a0, + 0x46437b05, 0xf76e667e, 0x70f5c0c3, 0x477f373e, 0x4301a655, 0x4201e1e2, 0x85ffffa6, 0x23072593, 0x11002200, 0x03266c82, 0x85001207, 0x17880000, + 0x17881e20, 0x82001522, 0xc3821f82, 0x841bfe21, 0x313008c3, 0x1b407c00, 0x0304011f, 0x0502202d, 0x06012e04, 0x02010005, 0x01010b06, 0x00010a02, + 0x4b4c0601, 0x58500db0, 0x02002340, 0x02060106, 0x00010072, 0x65260282, 0x03040400, 0xe3840061, 0x0605052c, 0x06060061, 0x1b4e063f, 0x25852440, + 0x9b800121, 0x59240826, 0x26150a40, 0x25132824, 0x1d090726, 0x1616052b, 0x06061415, 0x27262223, 0x33161637, 0x26343532, 0x26263723, 0x20050b41, + 0x12284132, 0xe702073a, 0x73445e5f, 0x28703d46, 0x21491c39, 0x0f595675, 0xa07ee192, 0x84a61101, 0x3b0e3841, 0x6f83c646, 0x40445f09, 0x171c2f5b, + 0x4f110f69, 0x18b82230, 0xca2e01b2, 0xa64201e1, 0x230c4741, 0x00045444, 0x200a2b41, 0x082b4128, 0x82001422, 0x0720178a, 0x10221788, 0x30828100, + 0x9d000230, 0x58040000, 0x09006205, 0x1f001300, 0x97421c40, 0x0303210a, 0x32089742, 0x04212126, 0x002b1a09, 0x11212100, 0x12043221, 0x42022e11, + 0x2e08058f, 0xfe580411, 0xfef3fe97, 0xba2f01bb, 0xd2b41e01, 0x9370ad73, 0x01e0ae95, 0x05cffe31, 0xd2fe6f62, 0xe8d8f3fe, 0xefd6fb4d, 0x00002e01, + 0x82250002, 0x826c206b, 0x0d44086b, 0x3f001b00, 0x01063c40, 0x02010703, 0x67020304, 0x00050500, 0x0001085f, 0x094d3800, 0x01040401, 0x0101005f, + 0x0f4e0139, 0x1a00010e, 0x16171819, 0x0f1b0e14, 0x0a0b0c1b, 0x00060809, 0x0a0d010d, 0x012b1609, 0x10208683, 0x232a9083, 0x01113335, 0x34113632, + 0x94822626, 0x21152125, 0x83e00111, 0x2598858c, 0x5b018c8c, 0x9783e0ae, 0xfe300123, 0x2a9486d0, 0xcffe79fe, 0x02907a02, 0x8239fb58, 0x28a2829a, + 0xfe9045fe, 0xff000021, 0x050f41ff, 0x001e0726, 0x00170022, 0x0722b382, 0x0682e015, 0xbb871782, 0x18000222, 0x01221082, 0xcb82f000, 0xcb822220, + 0x29000b2a, 0x01002640, 0x01030200, 0x0023c782, 0x825f0500, 0x4d382dcc, 0x04030300, 0x0404005f, 0x114e0439, 0x10270083, 0x2b1c0906, 0x83112101, + 0x3503849e, 0xbbfdfc03, 0x06fefa01, 0xcefc6b02, 0xc6042303, 0xfe9d45fe, 0x50829b2d, 0x5b846b82, 0x82230721, 0x841b2083, 0x2d122183, 0x17848385, + 0x88ff0621, 0x28162117, 0xb384178a, 0x15212f85, 0x20178b2a, 0x202f8828, 0x21178b14, 0x1788e506, 0x8b290f21, 0x8807202f, 0x8c102017, 0x88292017, + 0x8b112017, 0xc2062117, 0x19201788, 0x00271783, 0xfef00001, 0x8222042d, 0x001f28ca, 0x010cb56e, 0x46010102, 0x282b0698, 0x08000700, 0x67080700, + 0x41060600, 0x00370727, 0x045f0100, 0x39010101, 0x0202004d, 0x03006103, 0x4e033d03, 0x8825401b, 0x0002252a, 0x65030203, 0x01253193, 0x0c40594e, + 0x2c008211, 0x11262316, 0x1f090910, 0x1521252b, 0x11a94623, 0x21112123, 0x26038207, 0xb7012115, 0x467a6b02, 0x62260cab, 0x0319fe65, 0x8a411723, + 0x9b9b2105, 0x290ba946, 0x05328153, 0x45fe9c62, 0x0082009d, 0x0b010126, 0x46040000, 0x0924d382, 0x20402300, 0x260aef41, 0x04005f04, 0x824d3804, + 0x033922b7, 0x248b824e, 0x09051011, 0x07e9411b, 0x21112334, 0xa2fd2f04, 0xedfd1302, 0x043b03c6, 0x9b30fec6, 0x4482a5fd, 0x20083f82, 0x04e7ff54, + 0x007b053f, 0x4041001f, 0x01010a3e, 0x04010b00, 0x02011701, 0x05011c03, 0x004c0402, 0x23f68204, 0x00670304, 0x61201982, 0x3e2d8082, 0x0202004d, + 0x01066105, 0x053f0505, 0x2810824e, 0x111e001f, 0x26252512, 0x206d8207, 0x0b6b4404, 0x08059545, 0x33121023, 0x21113732, 0x06112127, 0xcd012306, + 0x01a184f5, 0xb8839e0c, 0x883f7456, 0x68ab6953, 0x7384b1ae, 0x086e82ff, 0xd56cd925, 0x01a11987, 0x01e4ea40, 0x4f4ca342, 0x6d373b78, 0xdefec4f7, + 0x013ff8fe, 0x6afd9e93, 0x0000403b, 0x8400ffff, 0xff0625ab, 0x26002200, 0x02237982, 0x823a1607, 0x21178706, 0x17882807, 0x863c1421, 0xb8fd2117, + 0x2f85db84, 0xfc060324, 0x4789ec04, 0x88070721, 0x3b10212f, 0x002f2f82, 0x009d0001, 0x05130400, 0x000b0062, 0x821e4021, 0x000130f9, 0x05670104, + 0x38030301, 0x0001024d, 0x43003900, 0x21270a43, 0x11211123, 0x82331123, 0x04333705, 0x16fec613, 0xea01c6c6, 0xfd8202c6, 0xfd62057e, 0x003d02c3, + 0x41820200, 0xac040022, 0x2e084f82, 0x00170013, 0x08334036, 0x0b000206, 0x0a010205, 0x00670100, 0x0203000a, 0x0967030a, 0x38070701, 0x0201044d, + 0x4e023902, 0x14151617, 0x86111213, 0x0c102800, 0x012b1f09, 0x82231533, 0x82212066, 0x35233403, 0x15333533, 0x01333521, 0x04213521, 0xc7999913, + 0x82c718fe, 0xe8013a05, 0x0151fdc7, 0x0418fee8, 0x09fc8d84, 0x7dfd8302, 0xde8df703, 0xc3fddede, 0x064744d2, 0x28071322, 0x2b20eb82, 0x0222e482, + 0x05821407, 0x01000028, 0x0000c500, 0xeb84eb03, 0x20402328, 0x01010105, 0x19825f00, 0x03218a85, 0x0946425f, 0x0610112a, 0x132b1c09, 0x11211521, + 0x35200382, 0xc5340582, 0xd1fe2603, 0xdafc2f01, 0xd1fe2f01, 0xfb9b6205, 0x049c9cd5, 0x01265c82, 0xe1fe1600, 0x53823104, 0x2700142a, 0x01142440, + 0x01044902, 0x26088844, 0x01010103, 0x84005f02, 0x20e084e7, 0x26578315, 0x35023e05, 0x84112111, 0x231121d6, 0x29085d82, 0x01050010, 0x52d6c281, + 0xfd9730fe, 0x04bfbfe4, 0xfed8fe1b, 0x83158e8f, 0x50039dd2, 0x9999d0fb, 0xfc993004, 0xfef0fe10, 0xdb8226a5, 0x0721c384, 0x20db8223, 0x4bdb842e, + 0x1784070f, 0x88ff0621, 0x070f4b17, 0x07211784, 0x20178828, 0x20358214, 0x21478700, 0x1788e506, 0xf7490f20, 0x202f8506, 0x20178807, 0x20178c10, + 0x20178829, 0x21178b11, 0x1788c206, 0x17831920, 0x00010032, 0x032dfec5, 0x006205eb, 0xb562001f, 0x0203010e, 0x08078744, 0x0107222c, 0x5f080000, + 0x38080800, 0x0101064d, 0x055f0201, 0x39020201, 0x0303004d, 0x04006104, 0x4e043d04, 0x001f401b, 0x03040003, 0x2b956504, 0x7b440220, 0x23162306, + 0x7b441126, 0x05dc4505, 0x2d127d44, 0x21112135, 0xeb032135, 0x2f01d1fe, 0x7e44d1fe, 0x83da200f, 0x26032614, 0xd5fbc704, 0x0e7e449c, 0x2b049c24, + 0x2741009b, 0x09574109, 0x2405074b, 0xff860001, 0x25df84e8, 0x40290012, 0xc7820826, 0x0127ab82, 0x02004c02, 0x825f0302, 0x4d3822cb, 0x063d4400, + 0x4e003f2b, 0x23251311, 0x2b1a0904, 0x0ba94801, 0x85353621, 0xd9603e9a, 0x54c26bab, 0x478f5155, 0x65fe9a89, 0xd0016102, 0x4088dc84, 0x2a34813e, + 0xed029eb1, 0x8283839d, 0x0b042e6b, 0x22002807, 0x00003900, 0x14070200, 0x34068264, 0xc3000200, 0x9c040000, 0x03006205, 0x2b000900, 0x05082840, + 0x2b748202, 0x0204024c, 0x4d380101, 0x00020305, 0x4e222f82, 0x25820404, 0x09040924, 0x27820607, 0x11032008, 0x2b170906, 0x11231101, 0x01330209, + 0xc6890101, 0xe9fde702, 0xfddf0402, 0x052802fe, 0x839efa62, 0xe0022703, 0x8bfd8202, 0xff8413fd, 0xb8fdc322, 0x222a6384, 0x00003b00, 0x0e070300, + 0x0782d604, 0x00233a82, 0x82380400, 0x0005247b, 0x4b164019, 0x0223054c, 0x82600002, 0x00393e1b, 0x1011114e, 0x2b190903, 0x33112121, 0x22042111, + 0x02c7dffc, 0xfb620570, 0x00ffff4a, 0x21378377, 0xcb822307, 0x2b823d20, 0x12070324, 0x678311ff, 0x83010121, 0x77052117, 0x02231786, 0x824c0d07, + 0xffff231e, 0x7f820101, 0x22216783, 0x222f8500, 0x8aea040e, 0x8562202f, 0x0701372f, 0x57010107, 0x090061fd, 0xb80101b1, 0x35b061fd, 0x0100002b, + 0x53824700, 0xa3823a20, 0x26000d31, 0x0c0d2340, 0x0607080b, 0x00080005, 0x4c4c0102, 0x238205a1, 0xed486020, 0x11152205, 0x28b08311, 0x07211101, + 0x27071121, 0x3fb78237, 0xca011725, 0xfc167002, 0xbc4d6fdf, 0x503b01c7, 0x25fe8702, 0x450c02ac, 0xac02747b, 0x79c3d0fd, 0x39245f82, 0x77040000, + 0x142a5f82, 0x2b402e00, 0x03070a13, 0x5a820301, 0x00030129, 0x80000103, 0x45020405, 0xcc820a44, 0x00144d08, 0x16161114, 0x1a090611, 0x2313012b, + 0x34352603, 0x03230337, 0x07141516, 0x21132303, 0x29041313, 0x0827ba4e, 0xecbadc02, 0xb6210406, 0xd401014e, 0xfa6205ca, 0xa0bb029e, 0xfc2676b9, + 0x72bb0345, 0xfd5d7fa7, 0xfc620545, 0x00a70359, 0xbb45bb82, 0x000f2608, 0x081a401d, 0x27ca8201, 0x0101024c, 0x034d3801, 0x2306b945, 0x04141115, + 0x172a6e83, 0x23111512, 0x27012111, 0xd9823502, 0x01212208, 0xb4160536, 0xd6010701, 0xfeb41803, 0x42ab04f4, 0xfdafddfe, 0xfb620569, 0x1d012952, + 0xfa9702d1, 0x455e829e, 0x23240847, 0x44002200, 0x02221082, 0xe74a1207, 0x829d2006, 0x071322f7, 0x2017881e, 0x206e8215, 0x252f8300, 0x1304b8fd, + 0x17866205, 0x0e070324, 0xa785b004, 0x8452fe21, 0x001b2f17, 0x182f4032, 0x00030210, 0x03020108, 0x04820107, 0x82054c21, 0x4d382a3b, 0x03030104, + 0x02004d39, 0x07274f02, 0x12151130, 0x06102324, 0x012b1c09, 0x06141133, 0xde4b2223, 0x23352206, 0x2ecc8a01, 0xa4b45f03, 0x4a658390, 0x792d3e28, + 0x882ffe46, 0x62052bd5, 0xa29c2efa, 0x15187e4d, 0xde8f7d93, 0x0621d787, 0x20bf88ff, 0x2fa58218, 0x00020000, 0x04e7ff55, 0x007b055b, 0x001b000f, + 0x2a068f4b, 0x01010061, 0x03004d3e, 0x82610003, 0x003f2c24, 0x2625244e, 0x1a090422, 0x8202002b, 0x02263e94, 0x36123435, 0x12163233, 0x23020215, + 0x10110222, 0x12323312, 0x755b0411, 0xe7a7a6e8, 0x08058575, 0xa292cf2a, 0x9e9693a1, 0xdb0192a2, 0xafb3bffe, 0xd6d84001, 0xb0b44301, 0x01d9befe, + 0xfe130117, 0xfee9feeb, 0x01edfeed, 0x00160112, 0x83849b82, 0x82230721, 0x454a209b, 0x17840cdf, 0x1785b384, 0x8407df45, 0x28072117, 0xdf452f88, + 0x21178407, 0x1788e506, 0xaf450f20, 0x21178406, 0x17882907, 0x178c1120, 0x17887f20, 0x82591321, 0x218f877e, 0x1788c206, 0x0805df45, 0x55000330, + 0x5b0424ff, 0x17004606, 0x29002000, 0x44404700, 0x01020115, 0x1d1e2627, 0x0c020304, 0x03000209, 0x16174c03, 0x0b4a0102, 0x4900020a, 0xd9410104, + 0x4d3e2306, 0x4b410105, 0x21213e09, 0x29211818, 0x20182821, 0x262a1f18, 0x2b180906, 0x15121601, 0x23060214, 0x27072722, 0x075d4137, 0x37172108, + 0x11020017, 0x01171614, 0x12122326, 0x27263411, 0x03331601, 0x757b766a, 0x3b40a6e8, 0x7549a23f, 0x42200983, 0x42080982, 0x349300fe, 0x2c260137, + 0x3393a230, 0x2cdafe38, 0x56270530, 0xd5dcbbfe, 0x0eb3bffe, 0x55ea2cd1, 0xd6db4401, 0x0fb44301, 0xbffe2bda, 0xe9feebfe, 0x033de7b3, 0xaefb0bf8, + 0x16011201, 0xfc3de7b8, 0x41000b07, 0xdb820583, 0x82230721, 0x415220f3, 0x0b461c83, 0x00023105, 0x04e7ff01, 0x007b05cc, 0x00260016, 0x13b04bbd, + 0x3705f04e, 0x02040300, 0x090b6703, 0x00010102, 0x02070a61, 0x4d380000, 0x04040108, 0x2605494a, 0x1b4e0539, 0x8215b04b, 0x0038222a, 0x272a8a02, + 0x010a6107, 0x4d3e0707, 0x9f483785, 0x24358405, 0x0505005f, 0x4f408439, 0x33200930, 0x01223a88, 0x39870909, 0xd7480020, 0x82002008, 0x2236856c, + 0x87080800, 0x59592d35, 0x17171840, 0x26170000, 0x1d1f2517, 0x1523b382, 0x82121122, 0x0c113001, 0x002b1d09, 0x21072117, 0x15211316, 0x82070221, + 0x06062904, 0x10112023, 0x020e3312, 0x08066a50, 0x3435364e, 0x01232626, 0x7b024bf7, 0x6b2dfe17, 0xfe28010e, 0x027809d8, 0x2970fd01, 0x56fe2543, + 0x634ed5d5, 0x4d633230, 0x2f306451, 0x7b055264, 0xfe8a9a19, 0xc1fe9aca, 0x0d0c9a95, 0x5d01c702, 0x729c7001, 0xf5c7c9f6, 0xc9f47170, 0x0070f4cb, + 0xd634be82, 0x60040000, 0x0a006205, 0x23001300, 0x04002040, 0x04010000, 0x380c4752, 0x01390101, 0x2124214e, 0x09052111, 0x04002b1b, 0x23112323, + 0x04202111, 0x51898215, 0x23080598, 0xe2fe6004, 0x01c7acf9, 0x0102016d, 0x92a6d21b, 0xa596b6b9, 0xfed9d002, 0xd5620509, 0xfd838fd6, 0x009e84ca, + 0xc7206b83, 0x5e206b82, 0x0c2f6b82, 0x34001500, 0x00003140, 0x04050107, 0x82670500, 0x02012a74, 0x06670104, 0x38030301, 0x05af494d, 0x000d0d37, + 0x0d150d00, 0x000e1014, 0x110c000c, 0x09082124, 0x15012b19, 0x20778233, 0x08828214, 0x1123152f, 0x32331113, 0x26343536, 0xb88d0123, 0x16010301, + 0xbef7e4fe, 0x93cec6c6, 0x0592a4a0, 0xdbdae762, 0x05fde1e8, 0xfd80fe62, 0x94a387b6, 0x397f848c, 0x04a6fe57, 0x007b05ae, 0x00230017, 0x0227402a, + 0x01030001, 0x0206074c, 0x73824900, 0x6a440120, 0x442a2013, 0x0728056a, 0x0717021e, 0x2223022e, 0x08177044, 0x98865a2d, 0x22618a65, 0x9c692dc4, + 0x71de9e74, 0xa7a6e675, 0x92ce75e6, 0x9592a1a2, 0x0192a29e, 0x53c1fecb, 0x67824c13, 0x498c714b, 0x443d01ad, 0x29081180, 0x01eefeec, 0x00160112, + 0x00bd0002, 0x05850400, 0x000d0062, 0x402b0016, 0x01010228, 0x004c0105, 0x00010005, 0x00670105, 0xdd480404, 0x46022006, 0x212f0561, 0x11112124, + 0x1c090613, 0x0706002b, 0x41012301, 0x2e08119a, 0x0193b43b, 0x95feeb91, 0x6f01c7ab, 0x0b010401, 0xb99a91d3, 0x039693bb, 0xfd26c247, 0xfd4502a1, + 0xc56205bb, 0xfe727dc2, 0x00867912, 0x85ffff00, 0x2307257f, 0x59002200, 0x840c7b43, 0x1e072197, 0x15201788, 0x2f841d82, 0x84b8fd21, 0x242f85af, + 0x040e0703, 0x371982b1, 0xff4d0001, 0x053b04e7, 0x002c007b, 0x1e29402c, 0x01030607, 0x1d4c0103, 0x4b290482, 0x02030300, 0x02020061, 0x0ba2493e, + 0x252e2522, 0x5205d645, 0x6c080a4b, 0x34353636, 0x2e272626, 0x36343502, 0x16323336, 0x26260717, 0x15062223, 0x17161614, 0x0415021e, 0xa0e77a3b, + 0x7159f99b, 0x5377bc4b, 0x7e34538b, 0x66c19574, 0x8d84d175, 0x476e5ada, 0x95735aa9, 0x7f848f3e, 0x080168ad, 0x565e68b9, 0x364b467f, 0x59424e6d, + 0x682c2246, 0xa46a6a96, 0x7c50515c, 0x5d633d3f, 0x2744503a, 0x7ca36025, 0x84cb8300, 0x20fb84b3, 0x20fb855d, 0x2106820f, 0xcb85ffff, 0x1785fb84, + 0x820c1521, 0x82002017, 0x1bfe21e3, 0x413ee384, 0x1a407b00, 0x031b1c33, 0x03040604, 0x0f030202, 0x0e020101, 0x04010001, 0x0601324c, 0x82534b01, + 0x01032208, 0x09825303, 0x05060628, 0x05050061, 0x8c534d3e, 0x033f2107, 0x83058253, 0x09825325, 0x59322693, 0x2e250a40, 0x25131125, 0x1d09072a, + 0x0606002b, 0x86531507, 0x05b44715, 0x22204741, 0x538cc969, 0x86220f93, 0x574150d9, 0xb111241f, 0x53580b6c, 0xb1230da0, 0x414d5c09, 0x4f411f69, + 0x00282308, 0x4f410022, 0x0c142105, 0x25066741, 0x3b04b8fd, 0x17867b05, 0x0e070324, 0x1882aa04, 0x8500012c, 0x9104f3ff, 0x25008705, 0xdd453701, + 0x02153705, 0x19050301, 0x04030418, 0x010e0302, 0x010d0201, 0x4c040100, 0x1791401b, 0x17820420, 0xb04b5929, 0x4058500a, 0x4102001f, 0x0321065a, + 0x05034603, 0x2a068142, 0x00000104, 0x1b4e0039, 0x9f0cb04b, 0x843f2026, 0x9f102026, 0x204d8526, 0x85269f13, 0x4617204d, 0x9b9105ae, 0x39040422, + 0x83082243, 0x23402151, 0x258bc193, 0x59205082, 0x40370083, 0x0000000e, 0x12240025, 0x29251424, 0x2b1b0907, 0x15171600, 0x4c110401, 0x56080dff, + 0x35272634, 0x23262601, 0x23111120, 0x36363411, 0xf4c90233, 0x01a3fe7c, 0x81c76fb5, 0x3b2b7b4b, 0x78334c24, 0x01d3c988, 0x54994f5a, 0x67c2fefe, + 0x87058dc7, 0xfe6a4248, 0xa8fe3582, 0x1a5fb77f, 0x0f0e8517, 0x88897d81, 0x85017c0c, 0xf0fe2622, 0xd3032dfc, 0x8264be85, 0x0100337a, 0x00004a00, + 0x62056704, 0x1b000700, 0x01021840, 0x964d0000, 0x01392c09, 0x1111114e, 0x1a090410, 0x8221012b, 0x3521327a, 0xfe520421, 0x58fec666, 0xbd041d04, + 0xbd0443fb, 0x2f438da5, 0x402f000f, 0x0101052c, 0x03020104, 0x06670201, 0x07264d82, 0x0701085f, 0x7b523807, 0x212e8206, 0xdc58000f, 0x09092907, + 0x07012b1d, 0x15211121, 0x23085c86, 0x04352111, 0x66fe1567, 0xfdfe0301, 0x01fffec6, 0x0558fe01, 0x82fea562, 0x0250fd8f, 0x7e018fb0, 0xffff00a5, + 0x0724af85, 0x0022001e, 0x0223c083, 0x86fe1507, 0x1bfe2183, 0x1d29c784, 0x3a403d00, 0x00030102, 0x2184820d, 0x0482010c, 0x03004c28, 0x03000200, + 0x05828002, 0x0102012e, 0x05010765, 0x005f0605, 0x4d380606, 0x82065142, 0x13112ae5, 0x08102725, 0x212b1e09, 0x14a34323, 0x9c822320, 0x21072125, + 0x4322b802, 0x10250e81, 0x0458fe24, 0x57b5821d, 0xc8240e03, 0xa5a5bd04, 0xfd21af83, 0x859784b8, 0x070324af, 0x82ae040e, 0x000137b0, 0x04e7ff87, + 0x00620529, 0x401b0012, 0x01010318, 0x004d3801, 0x3d4b0202, 0x23122207, 0x0b094f14, 0x35262b08, 0x14113311, 0x11203316, 0x29043311, 0x908fd371, + 0x85c66ed1, 0xc80b0184, 0xd78cc101, 0x8dd67777, 0x6efca103, 0x4401a2a2, 0x73829203, 0x07255b84, 0x00220023, 0x0c1b4669, 0x06211784, 0x4b1788ff, + 0x1784071b, 0x88280721, 0x82142017, 0x87002035, 0xe5062147, 0x1b4b1788, 0x202f8507, 0x20178829, 0x061b4b11, 0x7f201785, 0x1b4b1788, 0x21178407, + 0x1788c206, 0x33051b4b, 0xfe870001, 0x0529042d, 0x00240062, 0x0e18b64c, 0x01040102, 0x3c068455, 0x00040019, 0x01040001, 0x00010380, 0x004d3800, + 0x62020101, 0x3d020200, 0x401b4e02, 0x821b8716, 0x01022321, 0x22846602, 0x594e0027, 0x231b23b7, 0x05d8542a, 0x14113324, 0xe5500706, 0x022e2111, + 0x27084641, 0xa7c86103, 0x26665d95, 0x3409115c, 0xab785251, 0x8485c65a, 0x62050b01, 0xf1ab5ffc, 0x454a292a, 0x07115c27, 0x2f784b26, 0x7fc87e10, + 0x41076441, 0x0721081b, 0x20d3886d, 0x0b034117, 0x4a0a6341, 0x012605fb, 0x00002900, 0xeb828704, 0x2100062d, 0x01011e40, 0x4c010001, 0x86020203, + 0x392808dd, 0x00004e01, 0x06000600, 0x09041211, 0x01132b18, 0x23013301, 0x5e01fe01, 0xfec96201, 0x3dfed83d, 0x6dfb6205, 0x9efa9304, 0x20059755, + 0x204b8207, 0x2c0a82a9, 0x4028000c, 0x04090c25, 0x01040103, 0x0d32414c, 0x62820220, 0x12225582, 0xec551211, 0x03332306, 0x02820323, 0x1313333a, + 0xf4031333, 0x95f6cab5, 0xc3bafc97, 0x95e09d83, 0x9efa6205, 0xf9fb0704, 0x6b246382, 0x0bfcf503, 0xff228982, 0x638400ff, 0x82230721, 0x427520df, + 0x17850c43, 0x17882820, 0x84072b42, 0xe5062117, 0x0f201788, 0x84060f41, 0x29072117, 0x11201788, 0x2006f752, 0x20c38235, 0x08c3827b, 0x1f000b24, + 0x06091c40, 0x00020303, 0x01014c01, 0x4d380000, 0x02020103, 0x124e0239, 0x04111212, 0x012b1a09, 0x02843301, 0x01232708, 0xdf012301, 0x01e07afe, + 0xd521011f, 0xb0017dfe, 0xfeb9fee0, 0xde02d5b6, 0xfdfd8402, 0x86fd0302, 0x5f0218fd, 0xae82a1fd, 0x00010023, 0x205f8225, 0x335f828b, 0x40230008, + 0x01040720, 0x01010003, 0x0202034c, 0x4d380101, 0x39222182, 0x05824e00, 0x08000827, 0x09041212, 0x22638218, 0x83112311, 0x8b043967, 0xfec831fe, + 0x5c01db31, 0x62056001, 0xeffdaffc, 0x53030f02, 0xa2025efd, 0x22065f59, 0x8223078b, 0x417b20cb, 0x09200513, 0x22097759, 0x8828078b, 0x06142117, + 0x0621178a, 0x211788e5, 0x178a050f, 0x88290721, 0x83112017, 0x20b38217, 0x20b38284, 0x2cb3822a, 0x40290009, 0x02010026, 0x01010503, 0x0c2b5300, + 0x01000022, 0x2206775a, 0x41111211, 0x213f061d, 0x01352107, 0x04213521, 0x023afd29, 0x71fc17c7, 0x7bfdcd02, 0xc3045d03, 0x9ea8e5fb, 0x85a51f04, + 0x845b8473, 0x858020bb, 0x8b2620bb, 0x821e2017, 0x2117858b, 0x178b2315, 0x17880720, 0x5b221021, 0x38200bbb, 0x2208a35b, 0x5ac8001c, 0x13210893, + 0x51178307, 0x1c210503, 0x4f2f8547, 0x17830547, 0x21058f4f, 0xab49461c, 0x4817830b, 0x1c21055b, 0x83778b52, 0x218f8517, 0x1782691c, 0x02002f08, + 0xe7ff7e00, 0x37041b04, 0x29001e00, 0x40404300, 0x03020119, 0x02010118, 0x05020621, 0x02030404, 0x4c040500, 0x04000100, 0x67040105, 0xa4590200, + 0x4d412505, 0x05050106, 0x08075245, 0x1f1f1f21, 0x26281f29, 0x28252324, 0x2b1b0907, 0x17161425, 0x06272607, 0x26222306, 0x24343526, 0x62353333, + 0x27290518, 0x16323336, 0x37360015, 0x05c34a35, 0x03334408, 0x2d2c27c8, 0xad382f9d, 0x539b6968, 0x99f10101, 0x9038777d, 0xacb7314d, 0x8dfecec8, + 0xa18c2c88, 0xf2606192, 0x840e3b3d, 0x4c487f14, 0xa4629451, 0x606950b1, 0x458c1b1b, 0x9afda4b6, 0x6dff444c, 0x855f5d66, 0x25c384db, 0x22004606, + 0x10828b00, 0x03070223, 0x20178bf0, 0x2017881c, 0x20178c07, 0x20178833, 0x21178b05, 0x1788f405, 0x2f8c0020, 0x17883520, 0x2f8c0220, 0x1788d120, + 0x17830a20, 0x02003108, 0x15fe7e00, 0x37041b04, 0x3c003100, 0x47404a00, 0x05040128, 0x04030127, 0x0702153c, 0x02133106, 0x01090702, 0x4c050200, + 0x06000300, 0x67060307, 0x0132ac82, 0x00650100, 0x61050404, 0x41050500, 0x0707004d, 0x785f6102, 0x27242c05, 0x2a252324, 0x09082623, 0x45052b1e, + 0x6841117a, 0x14112419, 0x41011716, 0x32240669, 0xee033736, 0x230c7c56, 0x1a3c948e, 0x2f137841, 0xeefe2c27, 0x6192a18c, 0x2c884a60, 0x464c2a18, + 0x2408bb61, 0x24379363, 0x0f864148, 0x3d15fe2e, 0x9a010e3b, 0x5f5d666d, 0xffff444c, 0x21054b42, 0x0f417c06, 0x41082008, 0x0e200c3f, 0x09201788, + 0x66081783, 0xf4ff0300, 0xbb04e7ff, 0x2c003704, 0x41003500, 0x61406400, 0x06050124, 0x04022329, 0x0b123f05, 0x0c000103, 0x04010201, 0x0e04004c, + 0x04000a01, 0x0800690a, 0x08010000, 0x090d6700, 0x06050502, 0x02070c61, 0x4d410606, 0x0101010b, 0x01036102, 0x023f0202, 0x2d36374e, 0x3d00002d, + 0x3741363b, 0x2d352d41, 0x82303134, 0x242b315c, 0x25242522, 0x090f1422, 0x12002b1d, 0x21071415, 0x410ab660, 0x98080941, 0x35333336, 0x06222334, + 0x33362707, 0x36171632, 0x020e3336, 0x022e2107, 0x06220123, 0x33161415, 0x26373632, 0xa8130435, 0x0eeffd04, 0x58366569, 0x88405435, 0x38946a53, + 0x5c63833e, 0xd1d84b89, 0x5732b659, 0x7e933243, 0x20217e6d, 0x4b405f85, 0x6501082a, 0x404b2102, 0x70824bfe, 0x5e3d404b, 0x37041630, 0x3bfbf2fe, + 0x25a2ae24, 0x37347a28, 0x5567605c, 0xa6619551, 0x18cf50af, 0x5744871e, 0x95595153, 0x717a903f, 0x64fe498f, 0x645e646a, 0x726e5b55, 0xff000000, + 0x052741ff, 0x00460625, 0x82950022, 0x07022310, 0x06820f03, 0x0002002f, 0x04e7ffbf, 0x00dd0531, 0x001c0010, 0x05194c7a, 0x18191133, 0x03040300, + 0x0401010c, 0x0f104c02, 0x1b4a0002, 0x20138840, 0x20138702, 0x252c8559, 0x03030017, 0x4b826100, 0x054d4131, 0x01040401, 0x01010261, 0x4e013f01, + 0x891b401b, 0x02002319, 0x1e863902, 0x1d840020, 0x0d405936, 0x1c111111, 0x12261b11, 0x09062225, 0x36012b1a, 0x12323336, 0x08055c4b, 0x23072749, + 0x36003711, 0x22231035, 0x16110706, 0x7f013316, 0xca589739, 0x85bc61c0, 0xa90c66b5, 0x855f01c0, 0x2f7e4ceb, 0x03447429, 0xfe524b9a, 0xa2fbfede, + 0x6b848dfa, 0xfa17c605, 0x01cac8a1, 0xfe475b90, 0x00453d02, 0x82b00001, 0x041133db, 0x00190037, 0x0f314034, 0x10010201, 0x02030201, 0x98820102, + 0x92824c20, 0x82610121, 0x4d41228c, 0x0acd5304, 0x1923c782, 0x62231800, 0x242005a3, 0x21059462, 0x3b4f2626, 0x09b06205, 0x03332e08, 0x465c8332, + 0xe29d61c4, 0x9ce57877, 0x855b99cd, 0x4b875a85, 0x5c8989a2, 0x87463b7d, 0xfda0a5f7, 0x5c7d7c90, 0xc485b358, 0xff0000bd, 0x2d8785ff, 0x22003406, + 0x00009800, 0x03070601, 0xe557ee58, 0xeeff2405, 0x822b35b0, 0x20238873, 0x20238821, 0x20238f06, 0x22cf8200, 0x83041bfe, 0x002e35cf, 0x1e3c403f, + 0x2a030401, 0x0405021f, 0x03002b2e, 0x010b0502, 0x2905ad62, 0x05004c05, 0x05010200, 0x30826902, 0x2b0ba762, 0x254e0441, 0x25132823, 0x1c090626, + 0x50157262, 0xe88a0724, 0x17373227, 0x02070606, 0x0e584bd1, 0xbc830f23, 0x24f98d61, 0xa93f5c83, 0x0e664b58, 0x8e12b524, 0x0b4195e8, 0x7d5c240a, + 0x41074335, 0xeb89090f, 0xeb8f0520, 0x20080f41, 0x080f4104, 0x238f0120, 0x00020027, 0x03e7ff7f, 0x06bb42f1, 0x11406033, 0x02040110, 0x03041819, + 0x4c020403, 0x02020001, 0x06a1424a, 0x04010525, 0x82610204, 0x57412010, 0x01200504, 0x2106ab4e, 0x198b1b40, 0x39000022, 0x01211e83, 0x0fa14261, + 0x1223252f, 0x2b1a0906, 0x23111701, 0x23060627, 0x064a5122, 0x43041721, 0x370805d1, 0x26261137, 0xc0310323, 0x973810a9, 0x64c9c65b, 0x69aa80bb, + 0x7a85a1fe, 0x2a678e75, 0xdd054473, 0x873afa17, 0x28015050, 0x8efba0ff, 0xc9c91f78, 0x029fc6c9, 0x00423d03, 0x2108bf82, 0x04e7ff7d, 0x00130631, + 0x002e001e, 0x192c402f, 0x01010201, 0x1c1d1e4c, 0x05060708, 0x01090203, 0xc682004a, 0x02010323, 0x0abb5769, 0x262a2624, 0x8e83042e, 0x37272628, + 0x17371716, 0x35431607, 0x08a64206, 0x27262626, 0x27002707, 0x22209582, 0x08085e65, 0xdf01355a, 0xbb298a57, 0x796f8c6f, 0xda77aab4, 0x7bd48292, + 0xbe72c474, 0x5d821d76, 0x29028595, 0x5b973005, 0x43467749, 0x99894f79, 0x1c290805, 0x95382790, 0xfe7a7d61, 0xa6e2fe76, 0xe0758afc, 0x7ce0909a, + 0x44c47984, 0xfbfd429a, 0x494d4836, 0x9f717096, 0x00c5d050, 0x4200ffff, 0xe537c382, 0x2200dd05, 0x00c39e00, 0x0d070701, 0x64001002, 0x02b10800, + 0x4264b001, 0x022105dc, 0x20e78300, 0x3623828d, 0x00240018, 0x111140ac, 0x24030701, 0x08030519, 0x174c0207, 0x41050216, 0x233206a7, 0x00000104, + 0x06095f05, 0x38050502, 0x0707004d, 0xf7826103, 0x004d4126, 0x61010808, 0x2706334b, 0x17b04b1b, 0x27405850, 0x01222a97, 0x2f833901, 0xf9460220, + 0x401b2206, 0x824e8325, 0x0503232d, 0x528a6700, 0x593a278e, 0x00134059, 0x1d212300, 0x0018001b, 0x25121118, 0x0a111123, 0x012b1c09, 0xf4412315, + 0x2135210e, 0x17230182, 0x53260315, 0x33250645, 0x8d043732, 0x0cfb419e, 0x4701b932, 0x732ac0c0, 0x7a857e44, 0x05678e75, 0x56fb8e38, 0x08090042, + 0xa58eeb24, 0xe9fd8e17, 0xc9c9423d, 0x009fc6c9, 0xff920002, 0x041f04e7, 0x00190037, 0x40400020, 0x0001073d, 0x594a0803, 0x06042b05, 0x04000301, + 0x01076703, 0xd0840505, 0x004d4125, 0x42010000, 0x1a29069f, 0x1a00001a, 0x1d1f1a20, 0x2d3a821c, 0x23252619, 0x2b190908, 0x33021e01, 0xb6443632, + 0x1616280d, 0x00071415, 0x82210706, 0x013d08b2, 0x8451055a, 0x47834d52, 0x67c24b57, 0x7374de9c, 0xc6878ed5, 0xdafd046a, 0x0c020a91, 0x01758403, + 0x479570ce, 0x3c79302e, 0xa5f98944, 0x7e8ffb9f, 0x322ea0eb, 0xa2a5d301, 0xff00a89f, 0x25ab85ff, 0x22004606, 0x4346a200, 0x82142005, 0x20178806, + 0x2017881c, 0x20178c07, 0x20178833, 0x20179606, 0x21178b05, 0x2f88f405, 0x2f8c0020, 0x17881620, 0x178c0120, 0x17883520, 0x478c0220, 0x1788d120, + 0x17830a20, 0x0002003c, 0x042dfe92, 0x0037041f, 0x0032002b, 0x090c4074, 0x1f000101, 0x02030a15, 0xdb4e0201, 0x00262206, 0x3b268201, 0x07800201, + 0x00000601, 0x67000601, 0x04050500, 0x04040061, 0x02004d41, 0x00620302, 0x20065e64, 0x25289123, 0x02030002, 0x2f886603, 0x594e0537, 0x2c2c0f40, + 0x322c322c, 0x2b232d26, 0x09081123, 0x07002b1c, 0x07a14121, 0x5515034f, 0x162105a4, 0x05bd4315, 0xad820720, 0x413ffd21, 0x582407b2, 0x276a6076, + 0x2409144f, 0xc78c5c5e, 0x05c04167, 0x8403b929, 0x0a917575, 0x41320002, 0x472405be, 0x464c2922, 0x2608204f, 0x0b2a794c, 0x419bf08f, 0x2c2405ce, + 0xa2a5a89f, 0x0033da82, 0x040000b6, 0x00dd0560, 0x405d0017, 0x0001020a, 0x82010306, 0x4b4c27fb, 0x58501ab0, 0x28521b40, 0x00002909, 0x07610600, + 0x3a060601, 0x22062752, 0x4119401b, 0x6920071d, 0x0323268a, 0x83033903, 0x232f82f2, 0x11160017, 0x13210082, 0x68f28424, 0x152306bf, 0x63072115, + 0xe583070d, 0x8d032608, 0x643c4390, 0x016a6c7e, 0xb1fe1564, 0x64f7f7bf, 0xdd0572b3, 0x2c8a1d1e, 0x92ca5754, 0x3d03c3fc, 0x9361c992, 0x3b4e8251, + 0xfe780002, 0x045d0455, 0x003c0098, 0x40160148, 0x020c310b, 0x4c010801, 0x4a07013c, 0x08059554, 0x00003830, 0x00070907, 0x04008009, 0x04060506, + 0x08008005, 0x08020100, 0x010a6901, 0x61070909, 0x41070700, 0x0202004d, 0x06005f06, 0x004d3906, 0x27660505, 0x05ae5408, 0x37903120, 0x82020921, + 0x23389d52, 0x40585020, 0x402178b9, 0x27b39736, 0x06000200, 0x67060204, 0xb189bb8b, 0x5959593c, 0x3d3d1240, 0x473d483d, 0x23342c28, 0x25372513, + 0x1f090b12, 0x0606012b, 0x456a1623, 0x06062807, 0x33161415, 0x82163233, 0x23042611, 0x35262622, 0x05656b33, 0x26343523, 0x220f8423, 0x46373634, + 0x3623072f, 0x84043736, 0x05085a2f, 0x5d047208, 0xbb66913d, 0x317cb762, 0x1c172146, 0x6bbb4c3d, 0xf5fe62ad, 0x55c7acf7, 0x717b2fad, 0x657b99a7, + 0x3c7c5bb9, 0x575c383c, 0x7c7dc36d, 0xfd4a74a9, 0x757977ab, 0x6e707169, 0x0e13ee03, 0xa368b654, 0x100a095b, 0x2d271c34, 0x9d51844c, 0x6f8c46a9, + 0x52254a3e, 0x364b4553, 0x6234375b, 0x668e3125, 0x175ea86b, 0x7fe92327, 0x7b7f6b6a, 0xff757271, 0x05df41ff, 0x001c062c, 0x00ad0022, 0x07020000, + 0x5744f507, 0xfe782605, 0x065d0455, 0x20178833, 0x21178305, 0x2f860300, 0x0e006639, 0x57004b00, 0x0f404e01, 0x00010108, 0x0109014b, 0x03021b40, + 0x424c030a, 0x40080515, 0x09020041, 0x0b02090b, 0x08060080, 0x07060807, 0x0c000080, 0x00090101, 0x0a006901, 0x0a040300, 0x010d6903, 0x61090b0b, + 0x41090900, 0x0404004d, 0x08005f08, 0x004d3908, 0x61050707, 0x3d050500, 0x07cd5605, 0x40993a20, 0x02020b23, 0x23419e02, 0x40585020, 0x40218ac2, + 0x27cea03f, 0x08000400, 0x67080406, 0xcc89d68b, 0x59593708, 0x4c224059, 0x4c00004c, 0x52564c57, 0x3a464850, 0x2e313337, 0x23282a2d, 0x12171920, + 0x000e0011, 0x090e160d, 0x26002b17, 0x37363435, 0x16073337, 0x06141516, 0x58420523, 0x16022d47, 0x63120f43, 0x19163a70, 0x16023243, 0x2e376442, + 0x3142a904, 0xd326361b, 0x1d3211ea, 0x42bb4231, 0x00213471, 0x08734200, 0x5b421620, 0xf5012208, 0x3c008200, 0x00bf0001, 0x05f30300, 0x001300d9, + 0x0f244027, 0x02010200, 0x12134c01, 0x004a0002, 0x05015602, 0x034d4122, 0x2505bf53, 0x22132313, 0xba4c0904, 0x15162406, 0x50112311, 0x088205a4, + 0x01372708, 0x5faf3e7f, 0x51c09395, 0x308d4e58, 0x9503c0c0, 0x96a2534f, 0xee0201fd, 0x4662565e, 0xc40506fd, 0x01000015, 0x6b862300, 0x66001b29, + 0x0b180c40, 0x84010002, 0x4a04216b, 0x2c05e548, 0x0301061e, 0x055f0403, 0x38040401, 0x261b824d, 0x01086107, 0x68410707, 0x1b2207d3, 0x1a821c40, + 0x07232382, 0x91670304, 0x4059221e, 0x26d08210, 0x111a001b, 0x82111113, 0x090924ab, 0x8d002b1d, 0x35232ea6, 0x15373533, 0x11211521, 0x03333636, + 0x26ae8760, 0x01c09c9c, 0x82b7fe49, 0x370421c1, 0x042ab58b, 0x158c8eaa, 0xebfe8ea1, 0x5982534f, 0x41ffff21, 0x0731052b, 0x0022008c, 0x010000b2, + 0x00140706, 0xb1080064, 0x06f94901, 0xe600022e, 0x0c040000, 0x0b001606, 0x62001500, 0x20055946, 0x32398221, 0x01076101, 0x4d400101, 0x02060600, + 0x0202005f, 0x84054d3b, 0x040028e8, 0x4e043904, 0x821f401b, 0x0000251e, 0x69000102, 0x592e2195, 0x00001440, 0x12131415, 0x0e0f1011, 0x5e820c0d, + 0x08240a25, 0x822b1709, 0x741420dd, 0x4d67073a, 0x352a0805, 0x02211121, 0x3b4a4a93, 0x3a4a4a3a, 0xf70198fe, 0xdafc2501, 0xc9fe4101, 0x36491606, + 0x384a4a38, 0x08fe4936, 0x929274fc, 0xc082fa02, 0x0427af85, 0x0009001e, 0x821e4021, 0x5f00218d, 0x3b22ad82, 0x0269034d, 0x0510250e, 0x132b1b09, + 0x20085769, 0x215689f0, 0x4c851e04, 0x85ffff21, 0x4606254b, 0xb6002200, 0x02234482, 0x41020307, 0x13410533, 0x881c2005, 0x8c072017, 0x88332017, + 0x8b052017, 0xf4052117, 0x00201788, 0x16202f8c, 0x01201788, 0x3520178c, 0x02201788, 0x00371783, 0xfe5d0003, 0x06080455, 0x000b0016, 0x002c0017, + 0x1b1cb47a, 0x41490602, 0x25220593, 0xfd820102, 0x030b6133, 0x0101030a, 0x01084d40, 0x5f090404, 0x3b090900, 0x088e594d, 0x4e063925, 0x8423401b, + 0x232c8221, 0x69000109, 0x59382596, 0x0c0c1e40, 0x2b2c0000, 0x2728292a, 0x23242526, 0x170c2122, 0x1012160c, 0x0a227882, 0xa5410c24, 0x1620220e, + 0x08b14115, 0x00141324, 0x566a2707, 0xaa012a0e, 0x3a3a4b4b, 0x023a4a4a, 0x3008864d, 0xf8ebfe74, 0x6ba8793b, 0xfdb18ffe, 0x03a9b3e2, 0x09c94190, + 0x3307d141, 0xfeda6dfa, 0x2d934ffb, 0x036b9660, 0x9202fd1a, 0x8efe0292, 0x210a7b41, 0x1b41d105, 0x020a2208, 0x24008200, 0xfee60002, 0x06a7422d, + 0xb4002927, 0x040118b5, 0x07ec5803, 0x010a2c26, 0x61000101, 0x40242582, 0x0808004d, 0x29081641, 0x5f030202, 0x03030106, 0x71534d39, 0x052e4607, + 0x58501a2b, 0x04002940, 0x05040500, 0x273a9f65, 0x401b4e03, 0x0a000027, 0x85069346, 0x27649434, 0x59594e03, 0x00001a40, 0x23075241, 0x15171a1c, + 0x2008f942, 0x07b3450b, 0x16323329, 0x23061415, 0x75152113, 0x2123126d, 0x82112135, 0x1e022d03, 0x3b3a4a4a, 0x8f3b4b4b, 0xdbfe2501, 0x360cce53, + 0xd0fe6562, 0xc9fe4101, 0x1505f701, 0x4936384a, 0x4a383649, 0x6a927dfb, 0x92250e53, 0x0092fa02, 0x08df4200, 0x4b410e20, 0x41092008, 0xb731064b, + 0x830355fe, 0x0b001606, 0x4c001900, 0x021011b4, 0x06654202, 0x00001626, 0x04610100, 0x2005f943, 0x05616a02, 0x4e023b25, 0x8214401b, 0x00002513, + 0x69000103, 0x8207786a, 0x40592716, 0x1900000e, 0x48831718, 0x05240a22, 0x230e3742, 0x04061413, 0x23062c42, 0x19032135, 0x3a30cf82, 0xa53a4949, + 0xe1d2fe9e, 0x80e5a71f, 0x6d0253fe, 0x2c091742, 0xf9b5aafa, 0x1d942796, 0x028bb76b, 0x21bc82d9, 0xa3840001, 0x001e042c, 0x4018000d, 0x02040515, + 0x9b834900, 0x01005f2d, 0x4e003b01, 0x09021a11, 0x8c252b18, 0x8b832061, 0x8dc02059, 0xffff214e, 0x04274f83, 0x0033062f, 0x82c20022, 0x07032448, + 0x82880005, 0x00022a07, 0x040000c8, 0x00dd0578, 0x05514403, 0x02060922, 0x4c256282, 0x01020001, 0x2008824a, 0x07c8453b, 0x11122a08, 0x19090312, + 0x1137132b, 0x01330123, 0xc8012301, 0x9102c0c0, 0x013afeed, 0x15fef3f8, 0xfa17c605, 0xfe1e0423, 0x02bbfd27, 0x82568240, 0xfdc8226f, 0x225784b8, + 0x82c40022, 0x06032410, 0x84b904fc, 0x82bf206f, 0x826f206f, 0x226f83d7, 0x821b401e, 0x0001276f, 0x01024c01, 0xc4440000, 0x01392405, 0x5e11124e, + 0x13210534, 0x206c8733, 0x2b6c83bf, 0x0137feec, 0x15fef4fc, 0xe2fb1e04, 0x22246b82, 0x3302c0fd, 0x00305282, 0xff6f0001, 0x05f703e7, 0x001100c6, + 0x050a4048, 0x0620bb82, 0x200a274c, 0x07b14115, 0x9a4e3a20, 0x401b220b, 0x24f28213, 0x02030002, 0x0ab04e67, 0x11b65924, 0x30472414, 0x16142305, + 0xa44e3233, 0x11230808, 0x02213521, 0x534f5970, 0x8431325a, 0x4f92634e, 0x0102bffe, 0x43481001, 0x20198924, 0x04608c4b, 0x82009216, 0x2f8784f3, + 0x2200ee07, 0x0000c700, 0x03070701, 0xa801b7ff, 0x24054553, 0x35b0a801, 0x2123882b, 0x2388db05, 0xdf000d22, 0x840c9146, 0xb8fd2123, 0x4784cf84, + 0x06030026, 0x002705fc, 0xff231784, 0x82e904e7, 0x821784e7, 0x0201245f, 0x8566fd0d, 0x66fd215f, 0x0b415f83, 0x0019310a, 0x190e404c, 0x10111213, + 0x08090a0b, 0x01010309, 0x2206374d, 0x6f010015, 0x3a20052c, 0x2a0b6e69, 0x0013401b, 0x03010002, 0x51670102, 0x592a0ac8, 0x181127b6, 0x1a090422, + 0xe858252b, 0x07113306, 0x21113727, 0x37112135, 0x14110717, 0x37323316, 0x1241f703, 0x7f420805, 0xbffecd4e, 0x4eac0102, 0x534f59fa, 0x2019205a, + 0x01608c4b, 0x7c784e36, 0xfd923a02, 0x99786aab, 0x434846fe, 0x00000024, 0x005d0001, 0x04530400, 0x00210037, 0x1e0c405c, 0x05010219, 0x00020b14, + 0xa1820201, 0x58501324, 0xac821640, 0x61050136, 0x03060708, 0x4d3b0505, 0x00020204, 0x4e003900, 0x001a401b, 0x1d830f83, 0x1d820620, 0x06060223, + 0x481c8841, 0x21290549, 0x11232000, 0x24122412, 0x0b494813, 0x22232628, 0x11231107, 0x08862634, 0x36173325, 0x83323336, 0xe2032904, 0x2109af71, + 0xa84d5f22, 0xaf380584, 0x6a320c94, 0x302a9148, 0x37044b6d, 0xf0fca582, 0x4545f402, 0xd4fc7523, 0x04270787, 0x4a45761e, 0x82474289, 0x00bf24c3, + 0x82f30300, 0x001429c3, 0x0313b64d, 0x01030202, 0x1332bd86, 0x00030300, 0x00010161, 0x054d3b00, 0x02020204, 0xba820239, 0x83001721, 0x251a820f, + 0x01006101, 0x19884101, 0x0d405922, 0x142c1982, 0x13241400, 0x09061123, 0x11332b1a, 0x05499e85, 0x08b28206, 0x11070623, 0x400ea5bf, 0x93955fba, + 0x484818c0, 0x04308d4f, 0x584f8e1e, 0x01fd96a2, 0x746d8902, 0xfd466138, 0x0aeb4805, 0x00460625, 0x47ce0022, 0x058205cf, 0x0200002c, 0x0000ffff, + 0xe3050804, 0x19820d00, 0x7054b020, 0x080b2d05, 0x21010001, 0x05040211, 0x401b4c02, 0x03200d82, 0x33570d87, 0x491e2006, 0x3a240804, 0x0505004d, + 0x24057958, 0x06084d3b, 0x05014902, 0x20059647, 0x22258b22, 0x4e3b0202, 0x412008b8, 0x40212989, 0x072b4920, 0x95006721, 0x59593322, 0x0e0e1840, + 0x220e0000, 0x1d1f220e, 0x13151819, 0xac820f10, 0x09160c34, 0x122b1709, 0x06141516, 0x37230707, 0x36343526, 0x1e411333, 0x43af2a13, 0x6d521f15, + 0x32453139, 0x0d284156, 0x41e3052e, 0x403f1b31, 0x362ae5ab, 0x1dfa4230, 0x201d3741, 0x08374133, 0xd5820620, 0xffff002a, 0xb8fdbf00, 0x3704f303, + 0x03241786, 0xb204fc06, 0x01241982, 0x57febf00, 0x1c301784, 0x0c404800, 0x01021116, 0x054c0100, 0x49010204, 0x20055b41, 0x41248211, 0x0028072f, + 0x01390101, 0x15401b4e, 0x0022fa85, 0x30540300, 0x2d178406, 0x1123b659, 0x09042d13, 0x14252b1a, 0x2d460606, 0x26342105, 0x2005f341, 0x2fe98823, + 0x8948f303, 0x554e4777, 0x4948182c, 0xc0308d4e, 0x4332e386, 0x346eb694, 0x7d46248c, 0x6e52026d, 0x46623774, 0xe08606fd, 0x6a82bb84, 0x0e06f322, + 0x0920d388, 0x00289482, 0x89000200, 0x2704e7ff, 0x0f2ad382, 0x2c001b00, 0x01052940, 0xf1460303, 0x4d412105, 0x330a3f62, 0x00001010, 0x1a101b10, + 0x0f001416, 0x06260e00, 0x002b1709, 0x58087a66, 0xc04f056b, 0x05904f05, 0xcfef022f, 0x93d16b69, 0x6c6ad095, 0x838394d1, 0x2c028281, 0x37048181, + 0xa5a9f787, 0xf8878bf9, 0x2a0582a8, 0xcaccc499, 0xcacbc5c4, 0x85ffffc4, 0x46062183, 0xd5209b82, 0x8809a742, 0x881c2017, 0x41072017, 0xb3840687, + 0x88330621, 0x8b052017, 0xf4052117, 0x16831788, 0x2f85fb83, 0x17883520, 0x478c0220, 0x17888e20, 0x82510421, 0x21778718, 0x1788d105, 0x16820a20, + 0x0300002a, 0xf9fe8900, 0x1f052704, 0x22067b6d, 0x6d3f4042, 0x01230777, 0x6d020300, 0x41201376, 0x2020766d, 0x05ff5016, 0x27072722, 0x0808dc50, + 0x17371746, 0x14150600, 0x26131716, 0x35361223, 0x03272634, 0x4a033316, 0xd16b726b, 0x49302f93, 0x746c549b, 0x2e94d16c, 0xfe9b4c2e, 0x2f2e8239, + 0x811c20e5, 0xe42e2d81, 0xf8031d1e, 0xa5abfc41, 0xf6088bf9, 0xfd41fe2e, 0xf02d0984, 0xc4acfe2d, 0x2da782cc, 0xfc05e102, 0x250982e2, 0x20fd2da6, + 0xe3830005, 0x0621cb83, 0x20e38246, 0x127341dd, 0xfb880e20, 0x08052742, 0xf9ff0322, 0xcb04e7ff, 0x1f003704, 0x37002800, 0x51405400, 0x0706011d, + 0x01020a11, 0x02010b00, 0x004c0301, 0x2f067c54, 0x030b090c, 0x61040707, 0x0402050a, 0x084d4104, 0x310ba55c, 0x20202929, 0x37290000, 0x2e303629, + 0x27202820, 0x4e822324, 0x24241e2b, 0x0d132225, 0x002b1b09, 0x13a25c11, 0x10110227, 0x16323312, 0x08965c17, 0x6d060421, 0x95820c14, 0xfbfd4508, + 0x3464640e, 0x41543752, 0x976c5084, 0x6c81292a, 0xaeaaabad, 0x53268271, 0x2a4a41c2, 0x02590108, 0xfd3d461e, 0x4a224f91, 0x20483f3e, 0x043d4921, + 0x29f7fd37, 0x24a1af36, 0x37347a29, 0x655f5f65, 0x04012301, 0x283fa982, 0x95c86266, 0x727a903f, 0xc102498e, 0x51ae8fd1, 0x8c95ad4e, 0x000055af, + 0xfebf0002, 0x82270455, 0x001036ff, 0x4068001d, 0x0d131411, 0x08040303, 0x02030001, 0x02090a4c, 0x06ea4300, 0x0106182c, 0x61010404, 0x01020205, + 0x4f473b01, 0x001c210d, 0x1f831283, 0x05610226, 0x41020201, 0x59381e8b, 0x11111340, 0x1d110000, 0x16181c11, 0x0f001000, 0x09072514, 0x12002b18, + 0x21065d5c, 0xfd430711, 0x5c062005, 0x6543055c, 0x03340805, 0xb75bb572, 0xc068aa84, 0xa03b0ea5, 0x2f7e7d5c, 0x7d467528, 0x0474707d, 0xfee1fe37, + 0x8df9a3f8, 0x170dfe78, 0x518ec905, 0x475b9756, 0x423c02fe, 0xc3cdcbc3, 0x0521cb88, 0x2b6782dd, 0x403f001d, 0x0213143c, 0x010c0302, 0x4c2f9382, + 0x01030100, 0x020f104b, 0x0d0e4a00, 0x5c490102, 0xac820866, 0xc657d282, 0x11112106, 0x2b25a783, 0x09052225, 0x0d045d19, 0x3721a682, 0x25a28b12, + 0x9a387f01, 0xa686c958, 0x88adc021, 0xa00323a2, 0xa48a4e49, 0x17710724, 0xa38dc3fd, 0x55fe8924, 0x9744f103, 0x406b3006, 0x04010114, 0x02171800, + 0x01060403, 0x45030301, 0x18290b5d, 0x04040106, 0x02056100, 0x0b514702, 0x4e013f26, 0x001c401b, 0x72411283, 0x8601200e, 0x405922c5, 0x07d54413, + 0x13155508, 0x0e000f00, 0x09071225, 0x17002b18, 0x27113337, 0x23060611, 0x36341120, 0x11063336, 0x32331614, 0x26113736, 0xd3022326, 0xc0a50e6b, + 0xfe589438, 0x80b75e7c, 0x4d7373ca, 0x75282d7d, 0x87370446, 0x1737fa6e, 0x4b4c1202, 0xfba12702, 0x6efe978d, 0x4656c2ca, 0x2805315b, 0x00010000, + 0x040000c9, 0x22cb8230, 0x46bb0016, 0x0e310511, 0x01000113, 0x00020108, 0x01024c02, 0x401b4a06, 0x22108c0f, 0x55594b01, 0x202005e4, 0x02273d82, + 0x05720001, 0x48010101, 0x3b2406e2, 0x0201044d, 0x2305894c, 0x1b4e0339, 0x21204f85, 0x02212785, 0x21289980, 0x238b2b40, 0x84079651, 0x005f232f, + 0x568d0606, 0x3e495920, 0x00162305, 0x00821115, 0x49211221, 0x1726063e, 0x23352303, 0x42790322, 0x172d0809, 0x03333636, 0x1e2946c1, 0x67ed0194, + 0xa0cafdd6, 0x233301a0, 0x0488b03f, 0xfe0d0c37, 0xadfedc8e, 0x8e8e59fe, 0xf78e0203, 0xff008789, 0x050741ff, 0x00460625, 0x44e40022, 0x3b200573, + 0x17880682, 0x17883320, 0x17870620, 0x04b8fd25, 0x86370430, 0x06032317, 0xe88204fc, 0x00010027, 0x03e7ff8b, 0x341782f6, 0x4034002a, 0x01011031, + 0x02112700, 0x01260103, 0x4c030302, 0x06fb4e00, 0x1805235f, 0x2a0ac741, 0x2d29002a, 0x09052d24, 0x6e242b19, 0x5e6e0d5f, 0x0614210e, 0x08d54018, + 0xa3024808, 0x6d6c2585, 0x65549876, 0xa0e67bb9, 0x5b924352, 0x72316870, 0x52927270, 0x877ace7e, 0x406a4cd2, 0x54805aa1, 0x35403148, 0x74481e1c, + 0x48855959, 0x302d7d77, 0x382c3d44, 0x4c1f1f2e, 0x906c607c, 0x7a424f44, 0x82003d35, 0x84b384e3, 0x85e820fb, 0x821120fb, 0x83178806, 0x201785fb, + 0x83178306, 0x1bfe21e3, 0x3e31e384, 0x1c407d00, 0x0506012f, 0x04021b30, 0x03011a06, 0x0c6a6e04, 0x6e4c0621, 0x41291c65, 0x0404004d, 0x03006103, + 0x1c656e03, 0x5926268c, 0x2d240a40, 0x656e1124, 0x6e242006, 0x27251865, 0x33161637, 0x1c4b4132, 0x65f60324, 0x875f6aaa, 0xdb0e270e, 0xa1406a95, + 0x5a41735a, 0x88c72417, 0x6e5a0a4a, 0x0d240e5e, 0x3d357a82, 0x411a6841, 0x05201247, 0x30075f41, 0xf603b8fd, 0x22003704, 0x0000e800, 0xfc060300, + 0x055b6e04, 0xe7ffb42a, 0xdd056204, 0x92003b00, 0x2c054343, 0x0101190a, 0x00011802, 0x1b4c0201, 0x200c8640, 0x620c8203, 0x02360833, 0x05610402, + 0x3a040401, 0x0101004d, 0x01036100, 0x003f0000, 0xf84a1b4e, 0x001b2105, 0x03221e8a, 0xc06d3903, 0x21228308, 0x37821940, 0x01020026, 0x00690204, + 0x59221b8e, 0xa8834059, 0x3a003b2d, 0x31333637, 0x15171b1d, 0x49160906, 0x0723075b, 0x70150606, 0x142106f4, 0x088b7706, 0x210b7141, 0x0d843637, + 0x22239208, 0x23111506, 0x33363411, 0x59a2b902, 0x2f293324, 0x3439262c, 0x6547634c, 0x6c9569ac, 0x29572549, 0x4a336960, 0x354c413e, 0x32273021, + 0x3e4f2332, 0xd7c06c6d, 0x4add05c4, 0x4e325485, 0x38292436, 0x2c372125, 0x85533222, 0x54a3705c, 0x18158344, 0x573a6164, 0x3f2b283d, 0x492f3e5c, + 0x442a2333, 0x2f47282e, 0xcafb9082, 0xe0d32a04, 0x01000000, 0xe7ff9800, 0x23051704, 0x2e001700, 0x01172b40, 0x4c010105, 0x02020c0d, 0x0101044a, + 0x035f0201, 0x06d94b01, 0xbe770020, 0x11232806, 0x22141113, 0x4e1c0906, 0x35080939, 0x35333523, 0x07211137, 0x16141121, 0x04373233, 0x4f9e3817, + 0xef54a473, 0x6801c0ef, 0x5baefe16, 0x365d6a66, 0x95532b24, 0x905c0263, 0xfbfe17ee, 0x59a6fd90, 0x7b8b3256, 0x3d001f27, 0x011f3a40, 0x2c7b8209, + 0x04021011, 0x0201074a, 0x09010108, 0x05517402, 0x24058556, 0x09004d3b, 0x23858709, 0x11111c1e, 0x11208882, 0x0a228a82, 0x8a8d1f09, 0x15228e88, + 0x928e1521, 0x87d9d921, 0x54012394, 0x9889acfe, 0x8c050123, 0x239a85cb, 0xfdfe8ccb, 0xff219c82, 0x051741ff, 0x00090625, 0x82ef0022, 0x070726aa, + 0x00b9000d, 0x05615692, 0x35b09223, 0x053b412b, 0x041bfe34, 0x00230517, 0x4082002b, 0x0701271b, 0x08012803, 0xbc820007, 0x21091063, 0xcf821c1d, + 0x2105da43, 0xd5820025, 0x40720820, 0x09605708, 0x072cda82, 0x00610807, 0x083f0808, 0x26401b4e, 0x01232785, 0x82010080, 0x65002179, 0x592e2896, + 0x23140c40, 0x15111311, 0x09262513, 0x56631f09, 0x26262315, 0x9f411135, 0x0617250e, 0x0e030706, 0x220ecc43, 0x41887e0f, 0x48230baf, 0x634a8c33, + 0xb8230e50, 0x417eab19, 0x812d0cc0, 0xff042921, 0xfd9800ff, 0x051704b8, 0x05274123, 0x06030026, 0x003b05fc, 0xbf2cb683, 0xf103e7ff, 0x13001e04, + 0x0bb64500, 0x43057c52, 0x1224059f, 0x01010104, 0x0025f282, 0x03620200, 0x06464f01, 0x14861620, 0x4d200e82, 0x03213e82, 0x05e94462, 0x13b75922, + 0x2225e282, 0x2b1b0905, 0x06be4701, 0x14613320, 0x08d88206, 0x7f013321, 0x934e5650, 0x0ea5c02b, 0x975fb43c, 0x3801c099, 0x445b5863, 0xe2fb0203, + 0xa3564e8b, 0x82fe0296, 0x2187849f, 0x9f824606, 0x1f4bf420, 0x2017850c, 0x4c17881c, 0x17850793, 0x17883320, 0x8407934c, 0xf4052117, 0x4c821788, + 0x88000021, 0x8835205f, 0x00022117, 0x17860082, 0x8e06f522, 0x934c1788, 0x20478507, 0x201788d1, 0x082e820a, 0x01000022, 0x2dfebf00, 0x1e04f103, + 0x5b002500, 0x14230f40, 0x00030402, 0x09040201, 0x03020001, 0x19b04b4c, 0x2c05185f, 0x4d3b0303, 0x02040400, 0x02020062, 0x164b183f, 0x8218200d, + 0x00012547, 0x01056501, 0x022e248c, 0x0940594e, 0x29132313, 0x09062623, 0x9d552b1c, 0x06272912, 0x26222306, 0x11331135, 0x21076141, 0x9c55f103, + 0x7a77220c, 0x055e410c, 0x55056c41, 0x5b230b94, 0x4178348a, 0xfd210569, 0x057a411a, 0x200a1341, 0x21e3887c, 0x13410008, 0x06f12209, 0x4c17880e, + 0x01260593, 0x00006f00, 0xfb824104, 0x1b000626, 0x01061840, 0x4f093854, 0x112a0565, 0x09031011, 0x33012b19, 0x03822301, 0xc57c032a, 0xfee086fe, + 0x2101cc88, 0x26053154, 0x000089fc, 0x821e0001, 0x82922043, 0x000c3c43, 0x0b2b402e, 0x00030308, 0x004c0103, 0x02000203, 0x05800003, 0x02020204, + 0x65014d3b, 0x8c82057c, 0x0c000c2d, 0x11121112, 0x2b1a0906, 0x6f210301, 0x132f0800, 0xffb39204, 0xfa8b8100, 0x9f7cbfbb, 0x837c95d2, 0xfb022d60, + 0x1e0405fd, 0x210359fc, 0xa703dffc, 0x6b84df84, 0x00460623, 0x244f8222, 0x07020000, 0x22518203, 0x85ffff00, 0x33062183, 0x3b421788, 0x212f8407, + 0x1788f405, 0x2f892e83, 0x17883520, 0x83000221, 0x00012200, 0x20cb8264, 0x20cb824c, 0x07036f0b, 0x01010029, 0x0101024c, 0x7e4d3b01, 0x036f0699, + 0x23340809, 0x13330101, 0x01013313, 0xfe520223, 0x8101d8ea, 0xe8e0adfe, 0xb0fed7ea, 0x01e78101, 0x0245febb, 0xfef2012c, 0xfe7f0181, 0x00ccfd16, + 0x70000100, 0x400455fe, 0x0e275b82, 0x1d402000, 0x8200010c, 0x03042559, 0x02490002, 0x7f825e84, 0x4e003933, 0x03181112, 0x052b1909, 0x27070606, + 0x2337023e, 0x085e8201, 0xd0023321, 0x1bc9e140, 0x1f4a7f69, 0xcd95fe41, 0x1e011f01, 0xd8ba06c6, 0x45119513, 0x1e04566a, 0x57036efc, 0x5f84059b, + 0x82460621, 0x430620d3, 0x17850c6f, 0x17883320, 0x84071b41, 0xf4052117, 0x34821788, 0xff000023, 0x21a785ff, 0x17883506, 0x24071b41, 0x030000c3, + 0x6fbf82ed, 0x3b21160b, 0x074e574d, 0x4e013922, 0x37110b6f, 0xc5fde703, 0xfc174102, 0xfd3f02ed, 0x03f602ef, 0x9f11fd8e, 0xa0ef028f, 0x73823482, + 0xbb845b84, 0x63640b20, 0x8317850c, 0x641785bb, 0x1785074b, 0xa3821620, 0x01211785, 0x27478514, 0x04e7ffb0, 0x00060611, 0x25057369, 0x001b0707, + 0x7569ff9e, 0x206b820c, 0x22c782bf, 0x511806f3, 0x1b2108c7, 0x0ab35046, 0x43511784, 0x4a178705, 0x2f830577, 0x21055f4a, 0xb38b571b, 0x01201782, + 0x1b218385, 0x0817825a, 0x00010035, 0x03ee00bc, 0x002204f0, 0xb306000b, 0x32010105, 0x1701012b, 0x01070101, 0x01012701, 0x01580237, 0xddfe7622, + 0xfe762301, 0x76dafede, 0xd9fe2701, 0x83000376, 0x210e8813, 0x0e822601, 0x475d0020, 0xd1052106, 0x15244782, 0x31403400, 0x2007f253, 0x241a8269, + 0x06020306, 0x083e5d67, 0x4e041b22, 0x2011195d, 0x2c195d07, 0x5bd10521, 0xfd270747, 0x92c3fcfe, 0x83ab0292, 0x000226cb, 0x0355feb7, 0x29838483, + 0x402f0019, 0x0210112c, 0xb8594902, 0x02032f09, 0x00570302, 0x5f020303, 0x02030200, 0xba59004f, 0x597e8e0a, 0x828922ba, 0x59effa21, 0x8a21096b, + 0x20888292, 0x068f5801, 0x11006226, 0x26402900, 0x21098f58, 0xc74d0200, 0x451a2005, 0x20290891, 0x14114e01, 0x07042224, 0x05b7461a, 0x22287058, + 0x4ea59f03, 0x7d200c67, 0x2f053347, 0x070e130c, 0x01010003, 0x02010d4c, 0x0d401b4a, 0x01210e8a, 0x06d84a4b, 0x51041921, 0x1c3108a2, 0x0001054d, + 0x075f0600, 0x1b060601, 0x401b4e06, 0x261b8323, 0x03006103, 0x844d2103, 0x825f2026, 0x22258eb3, 0x820f4059, 0x001637e4, 0x23251216, 0x08111111, + 0x332b1c07, 0x23113335, 0x36172135, 0xbd7b3336, 0x11032407, 0x4ec91533, 0x2b29071e, 0x23392946, 0x67ed2136, 0x061c4ed6, 0x0d0c5308, 0xfe080aa8, + 0x8e59fead, 0xffff0000, 0x9a00bc00, 0xce03f003, 0x14010601, 0x0900ac00, 0xb80100b1, 0x35b0acff, 0x0100002b, 0x00005ef7, 0x1e04f203, 0x43002400, + 0x1f224040, 0x1116191c, 0x05080b0e, 0x0108010a, 0x0a0b0c4c, 0x00080409, 0x01080001, 0xc9820780, 0x064d1c37, 0x02030405, 0x1b010105, 0x23244e01, + 0x1d1e2021, 0x11121a1b, 0x28008312, 0x070d1111, 0x13252b1f, 0x05c64533, 0x03230322, 0x33220288, 0x028c1313, 0xbf022f08, 0xffb2b67d, 0xf5a08200, + 0x84fb7f7d, 0x8a85f68d, 0xfa8c83fb, 0x9f7dbeba, 0xd69e96d2, 0x98d1a193, 0xb28cd693, 0xa70377d2, 0xfb02e2fb, 0x038f05fd, 0x23080546, 0x03dffc21, + 0x26080388, 0xc6000300, 0xea030000, 0x1f00dd05, 0x2e002a00, 0x54405700, 0x0302011d, 0x0201011c, 0x04050129, 0x0002060a, 0x824c0405, 0x4b013cc7, + 0x00030108, 0x02030102, 0x09010069, 0x01050401, 0x06006904, 0x07060700, 0x72050063, 0x5330058f, 0x20214e00, 0x2d2e0000, 0x25272b2c, 0x2a212a20, + 0x1e305382, 0x0a2c2523, 0x002b190b, 0x14111516, 0x26071716, 0x200ef26f, 0x06f36f26, 0xe66f1320, 0x35530808, 0x21152101, 0x1faaef02, 0x55432922, + 0x4d8e3117, 0xe44c8a5a, 0x606073ce, 0x3144802d, 0x833c9aa1, 0x394d537b, 0xe6fd256b, 0xe7fc1903, 0x8893dd05, 0x2d2b7ffe, 0x3708780b, 0x423e3837, + 0x90854f79, 0x18464f37, 0xfe3c7f17, 0x474a4b30, 0xb9333a4a, 0x82a295fc, 0xba0021e2, 0xf4200482, 0x0f22e782, 0x97821b00, 0x32403526, 0x07010106, + 0x0122ce82, 0x775e6903, 0x56632005, 0xc782076a, 0x00101027, 0x1d1e1f00, 0x0a6e561c, 0x560b0821, 0xb6841d6e, 0xbad54908, 0x7cbb6565, 0x6665bb7e, + 0x786c7cbc, 0x766c6c78, 0x75fe6c76, 0xe8fc1803, 0xc96ddd05, 0x70ca8285, 0x8185c96e, 0x968c70ca, 0x97989999, 0xfb96999a, 0x0100a251, 0xf4024a01, + 0xa6056803, 0x58001400, 0x01110a40, 0x010c0301, 0x2e05795a, 0x40585022, 0x02040517, 0x00010003, 0x83690103, 0x00032309, 0x0c82025f, 0x1b4f0024, + 0x13821a40, 0x5703002d, 0x00040105, 0x01040001, 0x88030069, 0x07c2591c, 0x13111327, 0x0b061324, 0x08c1621a, 0x080cc757, 0x6404033c, 0x24240d9d, + 0x9d1c4d26, 0x6826078c, 0x6aa60533, 0x011cfe64, 0x1f413c9b, 0x24fe2635, 0x2f50a402, 0xffff002f, 0x00001f00, 0x62059204, 0x04000200, 0x02000000, + 0x0000bb00, 0x0f824504, 0x15000c2f, 0x33403600, 0x01070100, 0x05010405, 0x5f1c8267, 0x1a2c05de, 0x0404004d, 0x02005f02, 0x4e021b02, 0x0d4d4118, + 0x11212432, 0x2b190708, 0x11210701, 0x15042033, 0x21230414, 0x094d4118, 0xcd032708, 0xa8c8fd13, 0x17010401, 0xfef8e2fe, 0x98bac78c, 0x0595a6a2, + 0x8ffea162, 0xd1e0d4cb, 0x55fd6205, 0x9a77e7fd, 0x93827e8a, 0x8382b420, 0x93844120, 0x76821020, 0x01010126, 0x46040000, 0x05250f82, 0x16401900, + 0x200e8200, 0x8216825f, 0x23828487, 0x03101111, 0x21207483, 0x232d7582, 0x45030101, 0xc696fd15, 0xfba96205, 0x4f481847, 0x07462608, 0x01220023, + 0x22348224, 0x83120702, 0x8443823b, 0x89063153, 0x2a000800, 0x01032740, 0x004b0103, 0x85000300, 0x03251982, 0x0301045f, 0x825e8703, 0x00082634, + 0x11121108, 0x22648305, 0x83113311, 0x03112366, 0x6685c086, 0xfe270123, 0x826a82d9, 0x0200279c, 0xd1fefdff, 0x0a826d04, 0x17000f27, 0x2e403100, + 0x31a98203, 0x06005301, 0x005f0506, 0x4d1a0505, 0x03040708, 0x3a410000, 0x10102807, 0x17101710, 0x82111512, 0x10510800, 0x2b1d0709, 0x23113325, + 0x23032103, 0x36363311, 0x21131312, 0x07211103, 0x07060202, 0x9c660704, 0x1f06fd1f, 0x3a35549c, 0x02322a2b, 0xb1fec5c0, 0x442e211b, 0x30fea13e, + 0xd1fe2f01, 0x9e35d001, 0x4b011101, 0x3ffb9201, 0xfef82104, 0xa8e1fed5, 0x25fb8337, 0x0000f000, 0x8f822204, 0x1b000222, 0x07250f89, 0x01220029, + 0x21d68228, 0x50180702, 0x50180d73, 0x00270ebb, 0x00150001, 0x829b0400, 0x00153f3f, 0x10334036, 0x03000205, 0x01054c01, 0x00010803, 0x67000301, + 0x02020406, 0x0a4d1a02, 0xe8820709, 0x4e011b22, 0x15245282, 0x12111500, 0x0483cf82, 0x1f070b24, 0xd182212b, 0x03132326, 0x11331333, 0x13240182, + 0x23130333, 0x023edf82, 0xbac77107, 0xb0b8d5f0, 0xb26fa26f, 0xbef0d5b6, 0x8b026fc5, 0xde0275fd, 0xbafd8402, 0x03844602, 0x22fd7c22, 0x53821383, + 0x3d388782, 0x4004e7ff, 0x2d007b05, 0x3c403f00, 0x0302292a, 0x02010704, 0x02121303, 0x4c210582, 0x05ba4400, 0x04006723, 0x057d7f04, 0x1b511f20, + 0x00202108, 0x2d2a9483, 0x21252c00, 0x072e2425, 0xf8501b07, 0x021e2208, 0x08875315, 0x36323329, 0x26343536, 0x87372323, 0x22510809, 0x36270706, + 0xc3023336, 0x834c76da, 0x5b985c53, 0x95a3f282, 0xa7755bfc, 0x4d9366d0, 0x17f28faa, 0x4e824fcf, 0xab6b809e, 0xea676c50, 0x5b7b0588, 0x7d526aa3, + 0x52080d4c, 0xc57c6694, 0x6b5f666f, 0x5279418f, 0x2fa17d80, 0x6d664862, 0x56724041, 0x08c78556, 0x00009d20, 0x62051304, 0x24000e00, 0x060d2140, + 0x01000202, 0x0001014c, 0x044d1a00, 0x02020203, 0xae83021b, 0x000e3708, 0x1115110e, 0x2b190705, 0x11331133, 0x01070614, 0x11231133, 0x9d011310, + 0x011210c1, 0x22c1f5e2, 0x620522fe, 0xefb06dfd, 0xfab30481, 0x0193029e, 0xfb0a010d, 0x48180056, 0x072507ff, 0x01220007, 0x2270822d, 0x823f0702, + 0x20178905, 0x21178829, 0x1883ff11, 0x9d000226, 0xc704d1fe, 0x30082f82, 0x0022000f, 0x20414044, 0x06020218, 0x0a0b4c01, 0x00040304, 0x0800004a, + 0x00060101, 0x02006901, 0x03020300, 0x06010763, 0x054d1a06, 0x1b040401, 0x37a78204, 0x1b1c2122, 0x1415191a, 0x10111213, 0x0e000f00, 0x17070926, + 0x2626002b, 0x2906b553, 0x020e1737, 0x03330123, 0xbb841323, 0xca872320, 0x84020237, 0x147e0851, 0x5b484756, 0x53087d14, 0xbf015386, 0x469da2b4, + 0x20d4827c, 0x33df85f9, 0x6c3afe05, 0x393f1a49, 0x491a3e3a, 0xa7fa3a6c, 0x2f012cfe, 0xf788e487, 0x0130bf83, 0x0000af00, 0x62059c04, 0x2d000c00, + 0x010b2a40, 0x3005594d, 0x03010000, 0x01046700, 0x4d1a0202, 0x01020506, 0x059a4201, 0x0c000c23, 0x27008311, 0x2b1b0707, 0x11230121, 0x33379183, + 0x01013301, 0x5efeb203, 0x9cc7c79a, 0xfed19301, 0x02e40142, 0x827dfd83, 0x02c22566, 0xfd7cfd3e, 0x8406437a, 0x23072567, 0x31012200, 0x02237882, + 0x822b1207, 0x01002706, 0xe7ff1500, 0x7f821304, 0x29000f2e, 0x010a2640, 0x4c010100, 0x49000109, 0xa1520782, 0x4d1a2105, 0x1b222782, 0x05824e00, + 0x0f000f29, 0x07041111, 0x82012b18, 0x21370879, 0x06020203, 0x36362707, 0x04131312, 0xa6fec613, 0x7555252c, 0x473d556e, 0x05482045, 0x049efa62, + 0xfe86febd, 0x98bdfec5, 0x6b328f46, 0x00010c01, 0x00004302, 0x1800ffff, 0x2107974c, 0x0f850002, 0x21074f42, 0x90820002, 0x07d34918, 0x007b0525, + 0x824a0002, 0x18012072, 0x2408474c, 0x401b0007, 0x39958218, 0x03005f03, 0x024d1a03, 0x1b000001, 0x11114e00, 0x07041011, 0x23212b1a, 0x94832111, + 0x16278983, 0x047603c6, 0x8245fbbb, 0x244f82d4, 0x040000d6, 0x220a8260, 0x18560002, 0x8409ef56, 0x8411205f, 0x8b41180f, 0x00022207, 0x246f8464, + 0x04e7ff2b, 0x262f8291, 0x4020000f, 0x82010d1d, 0x054c2171, 0x33054964, 0x02860001, 0x1a010101, 0x11124e01, 0x19070319, 0x020e012b, 0x080bc34d, + 0x7c37f723, 0x6a1d97bf, 0x4b275581, 0x01ce3efe, 0xc9560179, 0xa0847a01, 0x0e99125d, 0x03556036, 0x0393fce9, 0x2262826d, 0x8400ffff, 0xff062563, + 0x3b012200, 0x02231082, 0x82121607, 0x00290806, 0xff170003, 0x059904c3, 0x0011009f, 0x0023001a, 0x0f364039, 0x03040200, 0x00021a1b, 0x054c0204, + 0x00030401, 0x80000403, 0x23948202, 0x7e010003, 0x8d080c82, 0x00570301, 0x5f010303, 0x01030100, 0x16111f4f, 0x06151111, 0x012b1c07, 0x10111216, + 0x23150702, 0x11022635, 0x35371210, 0x020e0333, 0x16161415, 0x023e3317, 0x26263435, 0xf7b20227, 0xb4eef9f0, 0xf7f0f8ef, 0x8167afb4, 0x6a813c3f, + 0x3c816aaa, 0x0567813f, 0xcbfe1226, 0xd4fed7fe, 0x7e0cc3fe, 0x3c010b7e, 0x29012e01, 0x79123501, 0x6304fefe, 0xd2a7aed2, 0x6a09096a, 0xd2aea7d2, + 0x00000463, 0x3500ffff, 0x7b040000, 0x02006205, 0xa7627a00, 0x82132008, 0x00132b0f, 0x13264029, 0x04000401, 0xbd820201, 0x55040021, 0x033a05db, + 0x1a000001, 0x0101004d, 0x234e011b, 0x10112314, 0x2b1b0705, 0x23113301, 0x157c0611, 0x062b5105, 0x03372908, 0x57c6c64d, 0xb87a679c, 0x7f82c764, + 0x620575b3, 0x27029efa, 0xbd65383f, 0xfd11027f, 0x708187fd, 0x9d000100, 0x8a04d1fe, 0x57186b82, 0x0129076b, 0x02050654, 0x4d1a0303, 0x21658204, + 0xde476002, 0x22958205, 0x430b000b, 0x01200837, 0x23226082, 0x05822103, 0x04112133, 0x1f9c7713, 0x01c6cefc, 0xfb6205ea, 0x0130fe3f, 0x2307822f, + 0x00c00440, 0x59205b82, 0x5720d782, 0x1f265b84, 0x02041c40, 0xb6820002, 0x03010525, 0x85600103, 0x235084bc, 0x1c070610, 0x4e83bd83, 0x52823320, + 0xa4033329, 0xb302fcb3, 0x83f8a8f8, 0x254c82af, 0xfbc4043c, 0x4f84003c, 0xce20ab82, 0x0f2d4f82, 0x2a402d00, 0x01000100, 0x05070854, 0x24ac8303, + 0x00020406, 0x20ad8a00, 0xad43180f, 0x1d072209, 0x84af892b, 0x04112260, 0x20b38357, 0x88638546, 0x216784b4, 0x1341c404, 0x84132006, 0x402328b7, + 0x01020020, 0x41048602, 0x052a0572, 0x03600105, 0x1b010101, 0xbb8d4e01, 0x0e410320, 0x4d032c06, 0x14a4fec6, 0xa4fe1496, 0x83ea01c6, 0xd1fe21bf, + 0x20051041, 0x219e8200, 0x0f41b000, 0x000a3606, 0x40300013, 0x0600002d, 0x00030401, 0x01056704, 0x4d1a0202, 0x09184100, 0x000b0b33, 0x0b130b00, + 0x000c0e12, 0x240a000a, 0x18070721, 0x49c4822b, 0x2608104b, 0x01c47601, 0xfe190104, 0x71fef9e1, 0xa295d7c6, 0x620593a5, 0xdad109fe, 0x6205dae6, + 0xcbfd70fd, 0x8391a180, 0x82000200, 0x8d042100, 0x0c27cf82, 0x36001600, 0x18003340, 0x6908174b, 0x7c8207aa, 0x01040423, 0x0595415f, 0x000d0d27, + 0x0d160d00, 0x194b1815, 0x05f14809, 0x23217d87, 0x208a8235, 0x052b4732, 0xc2ae0122, 0x74278087, 0xd6ae01e9, 0x874e8963, 0xd9e72483, 0x83a6bc04, + 0x7f322284, 0x28858270, 0x00030000, 0x0400003b, 0x24878275, 0x000e000a, 0x2b898517, 0x05060108, 0x03690600, 0x02020207, 0x05248582, 0x04600105, + 0x2d056041, 0x00000f0f, 0x160f170f, 0x0d0e1012, 0x07410b0c, 0x07092805, 0x11132b18, 0x4a163233, 0x21230553, 0x84231133, 0x3533088b, 0xfa232634, + 0xfffbf86c, 0xd1feef00, 0xbfbf7b03, 0x8c7f44fd, 0x058a8d8d, 0xda09fe62, 0x05e0e0d1, 0x029efa62, 0x89c1fdd8, 0x008d8d9c, 0xfffeff02, 0x82b004e7, + 0x00153c87, 0x403d001f, 0x04010a3a, 0x01010f05, 0x0e4c0204, 0x00490101, 0x05010600, 0x69050004, 0x1c410871, 0x16162f0c, 0x1e161f16, 0x24111b22, + 0x1b070710, 0x576a012b, 0x11232305, 0xc8440323, 0x21132206, 0x41a08211, 0x3e08051d, 0xf2f5c902, 0xb0c5e4f6, 0x4c35112b, 0x2d235e48, 0x02390e25, + 0x72591e0f, 0x0386813b, 0xe7dad16b, 0xfdc904d9, 0x6ef4eca2, 0x61267e36, 0xed02bacf, 0xbffd77fd, 0x96708135, 0x00020085, 0x8400004f, 0x001135a3, + 0x4031001b, 0x0001052e, 0x02020809, 0x69020007, 0x04040106, 0x07219382, 0x088b4207, 0x12121227, 0x221a121b, 0x24008311, 0x070a1024, 0x1897891e, + 0x8a08cf57, 0xca2d0895, 0xe6f4f2f4, 0xb8f6fec5, 0xb90a01b8, 0x3c715b1c, 0x42038781, 0xcce2d0c4, 0x4ffdb102, 0xe0fd6205, 0x4ffd2002, 0x792ee6fd, + 0x00768f6e, 0x4f491800, 0x7b052107, 0x5d2a9582, 0x01000000, 0xe7ff6b00, 0x0f826d04, 0x41001e36, 0x01023e40, 0x01030500, 0x01120001, 0x01130203, + 0x4c040304, 0x0ac15918, 0x29088949, 0x61040303, 0x20040400, 0x41824e04, 0x1d001e27, 0x12112325, 0x05894924, 0x26071728, 0x07062223, 0xff751521, + 0x23062108, 0x08ed5e18, 0xbd453808, 0x9e896357, 0x0212dba6, 0x08acfd50, 0x6771b06c, 0x4a653d97, 0xfeb18bd4, 0x01a099f1, 0x7b05a711, 0x62764544, + 0xa7a2ecdd, 0x354067dc, 0xa657457b, 0xe0e34201, 0x83a64301, 0x824b20a7, 0x843c20a7, 0x403b2da7, 0x021a1b38, 0x0a0b0403, 0x02020102, 0x82212b4a, + 0x112224a1, 0x85262512, 0x151224a1, 0x18040214, 0x2508825e, 0x35213736, 0xb3842621, 0x36274d08, 0xc2023336, 0xff8a84f6, 0xe385ae00, 0x99487151, + 0x0cbab05d, 0x4f02b1fd, 0x66a5b20d, 0x5a694c96, 0x7b0589d9, 0xe5c8fe9c, 0xa6b8feed, 0x4071525e, 0xa0fcef3f, 0x3c43d7f3, 0x005c4e72, 0xffff0000, + 0x0000c500, 0x6205eb03, 0x2e000200, 0x57180f89, 0x862212b7, 0x2786e8ff, 0x38823920, 0xf6ff0126, 0x72040000, 0x182c3782, 0x34403700, 0x01030103, + 0x03020113, 0x0126d982, 0x01020300, 0x60516903, 0x4d1a2209, 0x22f28204, 0x824e021b, 0x00183036, 0x24131118, 0x08112313, 0x012b1c07, 0x82112107, + 0x673220bf, 0x2e080cf1, 0x35211123, 0xfe154303, 0x568a3ac6, 0x29c4b2b2, 0x6c4d4c5a, 0xc5fec332, 0xfe9e6205, 0xd03c3654, 0x0111fecb, 0x336f5be9, + 0x7efd2d37, 0x829ec404, 0x23b98253, 0x04e7ff58, 0x0025e782, 0x00230013, 0x0511526e, 0x00212408, 0x06010004, 0x09670104, 0x03070701, 0x02050861, + 0x4d1a0303, 0x00060600, 0x00010261, 0x4e002000, 0x8729401b, 0x83002023, 0x2b28831b, 0x01086105, 0x4d1f0505, 0x1b020200, 0x60822c85, 0x592c2b82, + 0x14141640, 0x23140000, 0x1a1c2214, 0x12336682, 0x12111111, 0x1b070a25, 0x1216002b, 0x23021015, 0x49030222, 0x122006ca, 0x10cd5018, 0x99034008, + 0xc9b549a7, 0x7f06adcc, 0x0c81b5b5, 0x5247beb3, 0x47522525, 0x28285243, 0x7b054352, 0xf4c8fe9f, 0x9bfe9cfe, 0x43015201, 0x620584fd, 0x3201b6fd, + 0x689a3101, 0xf3d5d5f2, 0xd2f46969, 0x826af4d3, 0x00022383, 0xb34b0039, 0x000d2a05, 0x40380015, 0x01010735, 0x374f1805, 0x01072709, 0x5f030404, + 0x55490106, 0x0e0f210a, 0x1228af82, 0x150f150e, 0x0c000d00, 0x0822af82, 0xf4491907, 0x013b0805, 0x26260123, 0x21243435, 0x15062207, 0x11332110, + 0xfec61304, 0xdce5fee3, 0x79774101, 0x01010f01, 0x01959910, 0x6205e110, 0x21029efa, 0x4c02dffd, 0xc782c235, 0x868098d6, 0x8202f8fe, 0x01003e54, + 0xe6fef6ff, 0x62057204, 0x39001f00, 0x01003640, 0x01170001, 0x4c020102, 0x02020a0b, 0x24ac8249, 0x01000201, 0x08f75469, 0x3507c04e, 0x1c1d1e1f, + 0x18191a1b, 0x06211315, 0x012b1707, 0x16323336, 0xfe671115, 0x35213112, 0x01210721, 0xb29882f4, 0x779b54b2, 0x235a5732, 0x36080542, 0xfe154d03, + 0x721803c6, 0xd1fecbd0, 0x2870b88a, 0x72502399, 0x4228015d, 0x9e20090f, 0x00257e83, 0x04e7ff1f, 0x399f8292, 0x4034002c, 0x03010a31, 0x004c0104, + 0x02030204, 0x07800304, 0x02020206, 0x9d834d1a, 0x82620021, 0x200023b9, 0x33824e00, 0x2c002c2e, 0x17251323, 0x07082624, 0x16012b1c, 0x5206d441, + 0x022e0648, 0x36123435, 0x02063337, 0x33161415, 0x0a5a3632, 0x36530808, 0x27023435, 0x3b280204, 0x5f99ae2d, 0x71211e74, 0x5d96595d, 0xb72a392e, + 0x525a4544, 0x47b64133, 0x29463139, 0x62054346, 0xdbfec76d, 0xfebbfeb2, 0x676667d5, 0x17017d66, 0x2501b1dc, 0xfebd73c2, 0xdafbe79e, 0xcd01695f, + 0x636735fe, 0xe5b8cd4d, 0x82c65e01, 0x0002268b, 0x04000014, 0x08bf8276, 0x1c001322, 0x41404400, 0x06030105, 0x03000201, 0x01096702, 0x07080000, + 0x00690800, 0x4d1a0404, 0x0707010a, 0x2907ca48, 0x00011415, 0x1c14191b, 0x79731c15, 0x0a0b2e06, 0x00060809, 0x0b130113, 0x012b1607, 0x056e7832, + 0x21112128, 0x33352135, 0x01822115, 0xc9821320, 0x26345008, 0x02112323, 0x7fe79d73, 0xfef5e0fe, 0x01e9feca, 0x2901c617, 0x927ed7fe, 0x83939da3, + 0xbb5d5e03, 0x04dce189, 0xb6b68b21, 0x3ffdc38b, 0x7e8d9b81, 0x0100d9fd, 0xe7ff4a00, 0x7b05a904, 0xa4002500, 0x01150e40, 0x01160306, 0x01250604, + 0x6c030109, 0x212f060b, 0x08040107, 0x04090101, 0x06006701, 0x82610306, 0x1a0321c1, 0x4305a05e, 0x4b26077d, 0x585015b0, 0x28952540, 0x1b020222, + 0x4308ce5e, 0x278a05aa, 0x2206c843, 0x43006105, 0x092009aa, 0x8205fa5e, 0x5959262b, 0x21230e40, 0x05a45511, 0x0a221324, 0xfe5e1f07, 0x27022106, + 0x2206a143, 0x55361236, 0x500808ae, 0x15210706, 0x33161621, 0x04373632, 0x60873da9, 0x087cd994, 0x87c5c585, 0x90db830e, 0x573c7957, 0x86354f2d, + 0xb20112a0, 0x9f0b4afe, 0x32593e8a, 0x96302d44, 0xfdd22401, 0xfd63058d, 0x1301c4b5, 0x7e29268c, 0xf2d9171a, 0x1feffda0, 0x0000001d, 0x08c75202, + 0x0e000b2f, 0x20402300, 0x01030600, 0x01060001, 0x20ac8268, 0x05b56d1a, 0x4e001b24, 0x00831112, 0x07071027, 0x23212b1d, 0x82978303, 0x33013805, + 0x04210307, 0x6daacf92, 0xc6aa6db0, 0x81fabc01, 0x022a0195, 0x83cbfd35, 0x62052403, 0x8310fe9d, 0x3e2a085f, 0xb7040000, 0x13006205, 0x2d001600, + 0x010a2a40, 0x02030508, 0x01080001, 0x07010968, 0x064d1a07, 0x00030204, 0x4e001b00, 0x5e181516, 0x0b220af6, 0x698a1f07, 0x09411320, 0x33133b06, + 0x04330307, 0x427cb9b7, 0xb17b439b, 0xb8b8c787, 0x81f99be9, 0x3d02e170, 0x0387c3fd, 0xfd620528, 0x8892026e, 0xdb82f6fd, 0x7b824020, 0x7b827020, + 0x14001137, 0x34403700, 0x08020e11, 0x144c0107, 0x4b010001, 0x04000106, 0x27878201, 0x08006702, 0x005f0708, 0x98838a83, 0x011b0124, 0xee85124e, + 0x09101122, 0x01228582, 0xf1881333, 0x33132508, 0x15213501, 0x02132107, 0xb2d49dff, 0x69b669a1, 0x90e0b2a3, 0x540301ff, 0xec28febb, 0x04fdfc02, + 0x92fd6e02, 0xfc2c0384, 0x7d7de901, 0x0021fe0a, 0x00020000, 0x04210582, 0x308782e2, 0x001a0017, 0x1738403b, 0x080b0214, 0x01094c01, 0x85fc8200, + 0x0b0b2e83, 0x010a5f08, 0x4d1a0808, 0x03030507, 0x21858301, 0x1141191a, 0x8f0c200c, 0x0513418b, 0x82032121, 0x13013b91, 0x91980321, 0x5688b0b9, + 0xb08a56b5, 0xb8b8d7a1, 0x03dd8001, 0xcc82fe00, 0x958c69fe, 0x05239d82, 0x839afd62, 0x17fe239b, 0x9b83e001, 0xfe9e2d08, 0x07120451, 0x0006001e, + 0x4041002a, 0x0301293e, 0x02012404, 0x064c0201, 0x04030405, 0x15164a00, 0x00490202, 0x85000400, 0x00010105, 0x2a081882, 0x03030063, 0x04005f04, + 0x4e031a04, 0x27280708, 0x21232526, 0x2a082a07, 0x17070611, 0x2305012b, 0x25173725, 0x15163203, 0x7e060614, 0x17260597, 0x35262607, 0x12633634, + 0x23232405, 0x83210135, 0x035408b2, 0x7ef1fe85, 0xfd52effe, 0xdde6ff00, 0x77be71e6, 0x48286762, 0x8789464a, 0xa39fac9f, 0x01da938e, 0x03b8fd9d, + 0x0654fe30, 0x5cdedec2, 0xd5fba2a2, 0xb27abbd0, 0x1b0d1066, 0x43261e24, 0x8c397c26, 0x16716557, 0x847c8214, 0xd3018976, 0x2ffe9ea1, 0x1a00ffff, + 0x9628a782, 0x02006205, 0x00005802, 0x270bd74f, 0x00008d01, 0x32000100, 0xa4291f82, 0x10007b05, 0x0a404600, 0x20cd8210, 0x44d2830a, 0x0d6e0603, + 0x4e1a2009, 0x0d6e062b, 0x200d8205, 0x050d6e00, 0x17861f20, 0xb6593f08, 0x21131124, 0x2b1a0704, 0x22232601, 0x23010706, 0x13013301, 0x32333636, + 0x256f0417, 0x0f2b2419, 0xfee1cffe, 0x2a01d571, 0x64761eee, 0xd804404d, 0xfb36300e, 0xfb620580, 0x78c7036f, 0x9b84216b, 0x07258b84, 0x012200d2, + 0x319a825d, 0x04f90607, 0x00440138, 0x0201b109, 0xb04401b8, 0x73822b35, 0xfe0c0024, 0xaf830455, 0x1b000b30, 0x72002900, 0x01230a40, 0x4c010503, + 0xc16e0129, 0x571e2007, 0x1f38079f, 0x0501064d, 0x084d1c05, 0x01030301, 0x02070461, 0x01200101, 0x22401b4e, 0x0023208f, 0x861b0404, 0x01072125, + 0x27082484, 0x0c184059, 0x2500000c, 0x20212224, 0x0c1b0c1f, 0x0012141a, 0x240a000b, 0x2b170709, 0x10110216, 0x12323312, 0x23021011, 0x1805c54f, + 0x08086669, 0x3636013d, 0x33032337, 0x03331313, 0xa0070606, 0xa5a49594, 0x37a59393, 0x3d19193d, 0x193d3837, 0x01353e1b, 0x14665b59, 0x749ea24c, + 0x1ca3a06d, 0x011986a5, 0x015d016a, 0xfe73015a, 0x82a1fe94, 0x90963201, 0xd0cff575, 0xf77776f6, 0x75f6ccd0, 0x881d61fe, 0x05765e83, 0xb4dcfb37, + 0x000026cb, 0x7b000100, 0x81040000, 0x0d006205, 0x2a402d00, 0x6f521805, 0x5b1b8208, 0x1a27050b, 0x0303004d, 0x824e031b, 0x000d2310, 0x0084110d, + 0x49070821, 0x220805a9, 0x11211521, 0x35231123, 0x81041133, 0x0196fd15, 0xc6c9fe37, 0x6205c1c1, 0x8fa9fea9, 0xd3022dfd, 0x8200028f, 0x00012600, + 0x0454fe9c, 0x08638250, 0x47002022, 0x011d4440, 0x01160602, 0x010a0203, 0x01090301, 0x4c040100, 0x00060107, 0x02060302, 0x05050069, 0x8405f542, + 0x004d2573, 0x61000101, 0x1e214082, 0x267d8300, 0x111f0020, 0x47241311, 0x0024058e, 0x11151616, 0x0aa25d18, 0x2a09ca7b, 0x11210721, 0x03333636, + 0x1860b43c, 0x0808a65d, 0x6477782a, 0x03c64194, 0xcbfd1914, 0x036fac45, 0x88c4688a, 0xa29cbcfd, 0x15187e4d, 0x864f0293, 0xfd494989, 0xa16205af, + 0x494739fe, 0x1524af84, 0xc604d1fe, 0x1934af82, 0x38403b00, 0x0803010f, 0x010a4c01, 0x03010508, 0x67030800, 0x01242184, 0x02090b63, 0x2a065a45, + 0x021b0202, 0x1718194e, 0x56141516, 0x112c0560, 0x070c1111, 0x13012b1f, 0x03231133, 0x5609d844, 0xab280a6a, 0x1d9460bb, 0xa26fc538, 0x2b0b6c56, + 0xc3fdde02, 0x2f0130fe, 0x75fd8b02, 0x410f7356, 0x3d3a0547, 0x40041bfe, 0x42007b05, 0x1d409000, 0x06023233, 0x05013e07, 0x021b1c06, 0x18690504, + 0x002b3214, 0x03010302, 0x06007202, 0x06040500, 0x01006705, 0x21028200, 0x39650065, 0x691f2006, 0x20250820, 0x401b4e03, 0x212d852c, 0x2ea38001, + 0x0c40592c, 0x25212525, 0x25131124, 0xec82092a, 0x1d905718, 0xc6563320, 0x16322117, 0x2705c444, 0x0415021e, 0x8ecf6f40, 0x230e6265, 0x52e0830e, + 0x2016d956, 0x07ff5691, 0xba250125, 0x69590d74, 0x09230e34, 0x566b5664, 0x0a5710e8, 0x8200200a, 0x00012e00, 0x04d1feaf, 0x0062059d, 0x402a0010, + 0x22f58227, 0x41060003, 0x072308df, 0x4c050501, 0x112008a6, 0x082a0086, 0x012b1e07, 0x23113301, 0xa6552303, 0xb8022709, 0x9c6b7a01, 0xaa55301f, + 0x08c84108, 0x2008ae55, 0x090f5600, 0x00142308, 0x10334036, 0x01040101, 0x0401064c, 0x00010109, 0x00670104, 0x02000005, 0x07670005, 0x1a030301, + 0x1b4d084d, 0x47142005, 0x102408ab, 0x2b1f070a, 0x23217084, 0x052d5211, 0x33013324, 0x83820101, 0x37022a08, 0xbfbf5d6c, 0x01316c5d, 0x8cfecb43, + 0xfeda9a01, 0x2c0131a6, 0x7afd5a01, 0xc0fd6205, 0xaefe5201, 0x7cfd4002, 0x860222fd, 0x20838200, 0x06bb4541, 0x3b001428, 0x01013840, 0x83840801, + 0x08257482, 0x00670304, 0x25218208, 0x0a670108, 0xf9830209, 0x00010223, 0x051e5600, 0x14001422, 0x1122fe86, 0x88820b12, 0x23020922, 0x353d8b85, + 0x15333533, 0x15231533, 0x70040133, 0xbc016afe, 0x9a86feea, 0xc79090c7, 0x019bdada, 0x8380826c, 0xfd832b78, 0x8d21047d, 0xfd8db4b4, 0x83833e02, + 0x83821320, 0x6205b12a, 0x33000e00, 0x010d3040, 0x4c35fd82, 0x00000400, 0x67000401, 0x03020200, 0x0301055f, 0x074d1a03, 0x081c5706, 0x0e000e22, + 0x57097544, 0x2108051d, 0x11213523, 0x01330133, 0xfec70301, 0xe9c58781, 0x0188ae01, 0x64fed171, 0x8402c201, 0xbc047cfd, 0x2257fda6, 0x00012207, + 0x064b549c, 0x30000f24, 0xe3412d40, 0x0708210e, 0x8b4eea84, 0x13a25309, 0x097f6818, 0x78120428, 0xfe831f9c, 0x5854c616, 0x8868180a, 0x0001220a, + 0x20db827c, 0x074b45be, 0x00050028, 0x02050102, 0x14820067, 0xcf825f20, 0x1a040423, 0x06a7534d, 0x8a134b45, 0x16be2f66, 0xfec6fafe, 0x01c7c767, + 0xa2620599, 0x638c40fb, 0x54fe3624, 0x63829f04, 0x00222508, 0x20464049, 0x17070201, 0x0b020301, 0x0a030101, 0x04010001, 0x0701084c, 0x07030200, + 0x04006902, 0x005f0604, 0x22051659, 0x451b0303, 0x222d0e4c, 0x11112100, 0x24241311, 0x1d070927, 0x064d452b, 0x2008656b, 0x0a4e4535, 0x98831120, + 0x33363c08, 0x4480db03, 0x8357874d, 0x40264a65, 0x3f44792d, 0xbd284e2b, 0x02bdf2fe, 0x03725588, 0x5d8d4d89, 0x8e653dfd, 0x187b4d48, 0xd0029316, + 0x23214b4a, 0xbd045efd, 0x620543fb, 0x824ed9fd, 0x0cd355ed, 0x27402a22, 0xad821282, 0x03006326, 0x065f0503, 0x550b6843, 0x1a4114d4, 0x13042905, + 0x821f9c77, 0x05c616fe, 0x5806d355, 0x3a08060b, 0x43000200, 0x8c0409ff, 0x2e007b05, 0x41003a00, 0x01163e40, 0x01170102, 0x01310204, 0x02090503, + 0x04030002, 0x0205064c, 0x04004900, 0x04030500, 0x02006905, 0x00610102, 0x721f0101, 0x203d0885, 0x262b4e00, 0x2a262535, 0x2b1c0706, 0x17070200, + 0x27071716, 0x23062726, 0x35022622, 0x0b1b4c34, 0x10150625, 0x74323312, 0x7e0808af, 0x04151616, 0x36361716, 0x23263435, 0x04150622, 0x377a858c, + 0x5f7b4126, 0x483f2039, 0x948afca8, 0xa97893f8, 0x83416658, 0x5d975d49, 0x0710a5bb, 0x93514441, 0x4d91645d, 0x383932fe, 0x4341514e, 0x7f014844, + 0x474afefe, 0x7b5c5631, 0xa50f2a48, 0xe1e44201, 0x42a64201, 0x31357e47, 0xfec4f76d, 0x01f6fee3, 0x635cb664, 0x99545a9f, 0x569f6265, 0x617cad2c, + 0x005d685e, 0xfe750001, 0x8276041c, 0x2f2108f3, 0x37403a00, 0x0203011d, 0x04021e2b, 0x092c2f03, 0x08040103, 0x04010001, 0x0304004c, 0x01040301, + 0x822c8280, 0x00662502, 0x61020303, 0x1f2dfa82, 0x24264e03, 0x0525242c, 0x042b1b07, 0x056a5c16, 0x8206185b, 0x182720c5, 0x331cc770, 0x3f4d6103, + 0x576e4f75, 0x2b3e202f, 0x4c4a3a38, 0xa084ea97, 0x12c57018, 0x71ae3e36, 0x43487744, 0x6f323866, 0x343c1311, 0x1431763d, 0xcf3201b0, 0x7018d983, + 0x3d340cc4, 0x00000b51, 0x4a000100, 0x6704d1fe, 0x0b006205, 0x27402a00, 0x02270f82, 0x04630201, 0x42000001, 0x8148071c, 0x0cf05708, 0x21072a08, + 0x23113311, 0x21112303, 0x15670435, 0x9c7766fe, 0x58fe821f, 0xfba56205, 0x0130fee4, 0xa5bd042f, 0x00ffff00, 0x04000025, 0x225b828b, 0x847b0002, + 0x2a0f876b, 0x4029000e, 0x01010e26, 0x484c0100, 0x682108f5, 0x05525706, 0x1b030323, 0x054c5703, 0x0710112b, 0x012b1d07, 0x15330133, 0x05ea4823, + 0x033c0b82, 0x68fecfbc, 0xfdc8fdc6, 0xdb68fec6, 0x62055c01, 0xfe8e13fd, 0x8ee70119, 0x5efded02, 0x3520cf83, 0x8520cf82, 0x0f2c7382, 0x25402800, + 0x03070a0d, 0x4c010400, 0x01237d84, 0x44010563, 0x022d0508, 0x4e021b02, 0x11121212, 0x07061111, 0x0855461c, 0x01230122, 0x39053968, 0x675301cb, + 0xfe2f1f9c, 0xd5b6feb9, 0x7afeaa01, 0x011f01e0, 0xe802d521, 0xdc83b9fd, 0xfd5f022b, 0x02de02a1, 0x02fdfd84, 0x27588203, 0x00000100, 0x6804d1fe, + 0x31227384, 0x0f822e40, 0x0554012a, 0x04030301, 0x0207085f, 0xd9837083, 0x35208b58, 0x07213523, 0x11211123, 0x9a640404, 0xf444fd1e, 0xe115ae02, + 0x6f438801, 0x99c92608, 0x04d9fb99, 0x206f85c0, 0x0657455d, 0x32001736, 0x01152f40, 0x01060405, 0x4c020503, 0x03000500, 0x69030500, 0x01232482, + 0x56630100, 0xec850617, 0x23142323, 0x05504111, 0xb8412520, 0x0e1a5a05, 0x43331121, 0x1e5a05e3, 0xa1c6210a, 0x205aed84, 0x9b02260c, 0x00010000, + 0x06fb525d, 0x60001a2c, 0x181a0c40, 0x07060502, 0x81830204, 0x22b04b26, 0x1e405850, 0x02208883, 0x25598882, 0x02022706, 0x06005f06, 0x764c1c06, + 0x871c2008, 0x06002720, 0x06010200, 0x28866702, 0x1b01012c, 0x40594e01, 0x1413110a, 0xad851521, 0x2706c65a, 0x35231507, 0x26262223, 0x0805eb51, + 0x33111723, 0x03373611, 0x36c6c64d, 0x15773563, 0xc764b87a, 0x78777173, 0xfa620556, 0x2827029e, 0xbfce0d33, 0x05d35a65, 0x07817f28, 0x25fee201, + 0xf75c5315, 0x05512c08, 0x00140062, 0x112c402f, 0x63040101, 0x05210573, 0x094c6301, 0x055d1a20, 0x29308207, 0x11130014, 0x06142313, 0xa5451a07, + 0xb4461805, 0x267f820a, 0x3d033336, 0x4ac660b4, 0xc62005df, 0x2307db4a, 0xd4012afe, 0x2107d44a, 0xd34a98fd, 0xfe9d2406, 0x82b204d1, 0x00172877, + 0x112f4032, 0x82060301, 0x02032277, 0x0611474c, 0x5007af41, 0x7f480591, 0x82222005, 0x0daf4178, 0x23263427, 0x11070622, 0x08fa8323, 0x1632335b, + 0x40041516, 0x7e1f9c72, 0x885a807b, 0x82c6c639, 0x5fb57fc8, 0x0130fea1, 0x87d4012f, 0xfd474888, 0xfd6205ac, 0xc46887a1, 0x02000088, 0xe7ffffff, + 0x7b057104, 0x2e002800, 0x3f404200, 0x04021819, 0x01010906, 0x02010a00, 0x084c0301, 0x03040207, 0x04010001, 0x06006900, 0x07c65106, 0x0201013c, + 0x02020061, 0x294e0220, 0x292e2929, 0x1c24262e, 0x11222613, 0x2b1d0709, 0xa2510700, 0x68362005, 0x02250626, 0x35022e27, 0x240d8434, 0x33161415, + 0x05d05133, 0x27151223, 0x08b38202, 0x71040357, 0x0462fd06, 0x57377c9a, 0x44582b3f, 0xcf8d69a4, 0x7a560876, 0x7b23283d, 0x33331314, 0xc5750b09, + 0x63ba8280, 0x6b7708b6, 0x980218ec, 0x18e9f736, 0x3b711d24, 0x1d018e48, 0x6c4001d0, 0x33613b43, 0x223b2d37, 0x01c83433, 0xfe9d9921, 0x012fe0cc, + 0x16fee604, 0x21d78400, 0xd7842dfe, 0x3f00392b, 0x11407f00, 0x0502292a, 0xa84e1807, 0x6e032009, 0x282d0687, 0x02000100, 0x80020100, 0x05020809, + 0x20e88204, 0x28e88205, 0x61060707, 0x1f060600, 0x2ae3824d, 0x03006203, 0x4e031e03, 0x9325401b, 0x0002262a, 0x66030203, 0x35318700, 0x40594e07, + 0x3a3a3a11, 0x263f3a3f, 0x23191c24, 0x0a11222c, 0x14411e07, 0xaf4e180c, 0x02262212, 0x28244103, 0x18635621, 0x240cbc4e, 0xcbaf5452, 0x2031410a, + 0x29204c23, 0x3e58184b, 0x784c2709, 0x3e011f30, 0x41411701, 0x126b581a, 0x0000152a, 0x07079b04, 0x2b012200, 0x2f092762, 0x9d000100, 0x3e0454fe, + 0x1d006205, 0x32403500, 0x29073b4e, 0x05004c02, 0x05030200, 0x68446702, 0x0ee94806, 0x00821120, 0x26242527, 0x2b1d0707, 0x11314e01, 0x61232621, + 0x0223086a, 0x4eabb3d6, 0x3930082e, 0xc6e96980, 0x5201bac6, 0x180403cf, 0x33feb9d4, 0x2d062a4e, 0x765dd801, 0x0596fd3a, 0x02a9fd62, 0x93820057, + 0xd1fe1d34, 0x62059304, 0x2c001300, 0x010d2940, 0x010c0002, 0x93820201, 0x01211b83, 0x08c35163, 0xb05e4d20, 0x821b2005, 0x0510258c, 0x252b1b07, + 0x20057a62, 0x0a696121, 0xdf03212d, 0x469da2b4, 0x2ce2fe81, 0x61745625, 0x022e066e, 0x2cfea591, 0xbd042f01, 0xc4fe86fe, 0x7161befe, 0x050f410b, + 0x7b821320, 0x35001529, 0x01083240, 0x85070402, 0x0006307b, 0x03060403, 0x00010567, 0x004d1a00, 0x831b0404, 0x6101277d, 0x1e010100, 0x81824e01, + 0x23241222, 0x4f06d346, 0x21290c3f, 0x33112311, 0x4d032111, 0x080641c6, 0x2107e84a, 0xff8630fa, 0xfdfd0223, 0x21fc827e, 0xdf8300c3, 0xfb828720, + 0x7f828820, 0x2235574b, 0x4a132303, 0x032109f0, 0x28fb85d4, 0x01c6c63f, 0xfb6205c1, 0x4af58343, 0x6f840af4, 0x6f825d20, 0x173def83, 0x2f403200, + 0x00060117, 0x06040108, 0x06004c02, 0x06030400, 0x03006904, 0x02030200, 0x20f68663, 0x07866001, 0x4d06bf44, 0xe08205b2, 0x820e7146, 0x1f9a23ee, + 0x70468f9c, 0x061f5f0a, 0x8601d022, 0x200e9360, 0x827f8226, 0x0021089c, 0x40360018, 0x0a0d1633, 0x01050303, 0x0503004c, 0x00030500, 0x02000080, + 0x7e020005, 0x01020100, 0x0ccf4a86, 0x16111223, 0x08434516, 0x6f18f483, 0x2b081182, 0xa21f0421, 0x5d469aa3, 0xbd010826, 0x0603c9ba, 0x014eb720, + 0x01acb601, 0x2cfea503, 0xbb022f01, 0x1c67c1a8, 0xb2034efc, 0x8f994f75, 0x07896f18, 0x08a37e18, 0x22000724, 0x4f650400, 0x001f240c, 0x18920400, + 0x2111737e, 0x9b4ce8ff, 0x00022206, 0x0a6f670e, 0x01213f82, 0x203f8528, 0x2d06822a, 0x51000200, 0x5704e7ff, 0x17007b05, 0xe9831f00, 0x02080924, + 0xe8820100, 0x04000026, 0x67040005, 0x02240b82, 0x02020061, 0x38050b53, 0x03006103, 0x4e032003, 0x1f181818, 0x25161e18, 0x07112225, 0x122b1b07, + 0x0a8a5c37, 0x11002024, 0x484b0214, 0x00470805, 0x1e213736, 0x07513302, 0xa8093503, 0x4e8d5c9b, 0x7fcc5863, 0x0d010001, 0xa29fe97d, 0x91027ae5, + 0x84fd0d9e, 0x68894c06, 0xfb32ce02, 0x72393be5, 0xa0fe524b, 0xfee4a7fe, 0x019daeb7, 0xebfde035, 0xd3acf6ea, 0x85ffff61, 0xe60637a3, 0x85012200, + 0x06010000, 0x01f10f07, 0x02b10800, 0xb001b002, 0x1f822b35, 0xad821520, 0xe5069b22, 0x21084344, 0xdb82ff0f, 0x3d201782, 0x4020db82, 0x2c201784, + 0x0f21f384, 0x230682f8, 0x83000100, 0x2c081782, 0x0062052d, 0x4046001b, 0x04011a43, 0x03011505, 0x02010b00, 0x01010a03, 0x064c0402, 0x03000001, + 0x67030002, 0x05040400, 0x0505005f, 0x0853431a, 0x4e012033, 0x18190001, 0x12141617, 0x06080d0f, 0x1b011b00, 0x055b5907, 0x2609c367, 0x36323316, + 0x55213435, 0x30080794, 0xe2eb6002, 0x9299e47c, 0x54635ac5, 0x9c906891, 0x01eae9fe, 0x03aefdb0, 0x0351fe34, 0x81b6cd20, 0x4d4d6fc6, 0x92363a77, + 0x0189ef84, 0xfe9ea1ab, 0x20bb855c, 0x22d3829d, 0x82c20613, 0x053f67d3, 0xd3861920, 0xeb831785, 0xeb871785, 0xd3825520, 0xeb845b20, 0xeb853620, + 0x00212f83, 0x6f701803, 0x0016330a, 0x4036001d, 0x00020033, 0x04020504, 0x03010667, 0x164d0103, 0x01072205, 0x055a6d05, 0x4e002038, 0x10101717, + 0x1c171d17, 0x1610191a, 0x26161510, 0x19070822, 0x7018002b, 0x002e0e88, 0x26210706, 0x36122326, 0x16162137, 0x70180433, 0xfd300c8a, 0x020c9369, + 0x94920b64, 0xfd06939a, 0x98970698, 0x10927018, 0xe82a022c, 0xfbe8ecec, 0xf6f7f7ae, 0x535600f8, 0x20bb8408, 0x23bb898d, 0x4b00ffff, 0x3c20d382, + 0x4b201784, 0xe6201785, 0x200b7765, 0x087765c2, 0x8b131921, 0x88e52017, 0x8b0f2017, 0x7f072117, 0x13211788, 0x242f856d, 0x0400005d, 0x205f8413, + 0x205f853f, 0x2d0682e9, 0x01010100, 0x4604d1fe, 0x09006205, 0x9e472800, 0x02012205, 0x21198263, 0xcc4b5f04, 0x089e4c05, 0x09000923, 0x24008211, + 0x2b1a0706, 0x089d4c01, 0x1546042d, 0x9c7a96fd, 0x6205851f, 0x64e8fba9, 0xcb82058c, 0x6b823b20, 0x6b847520, 0xe3894620, 0x00010027, 0x0454fe7e, + 0x086b829d, 0x47001b20, 0x010e4440, 0x010d0605, 0x4c020504, 0x06020300, 0x80060302, 0x07010108, 0x01030201, 0x35826702, 0x5f092008, 0x1a090900, + 0x0606004d, 0x05004d1b, 0x00610405, 0x041e0404, 0x111a1b4e, 0x23241211, 0x52111111, 0x21260538, 0x21152111, 0xef453311, 0x5535200b, 0x212205b6, + 0xb6558804, 0x457c2005, 0x7c2d08f5, 0x4503c1c1, 0xa9feb904, 0xfecefd8f, 0x06f945f1, 0xcb557b20, 0x82182009, 0x828c209f, 0x00192c9f, 0x193a403d, + 0x04101316, 0x82080500, 0x01072191, 0x4c280482, 0x03050000, 0x80030005, 0x21070445, 0x7f460303, 0x8212200c, 0x067f4600, 0x8f8e2520, 0xf94c0120, + 0x04012307, 0x8d888b01, 0xff4c4820, 0x7dfe220e, 0x4d948aa1, 0xfd230a04, 0x66010086, 0x113008b3, 0x2c402f00, 0x0504010d, 0x00010104, 0x01074c02, + 0x20065b4a, 0x20968568, 0x05cc6302, 0x11121123, 0x26038211, 0x1e070810, 0x8321012b, 0x0123277e, 0x01213521, 0x02820133, 0x68042127, 0x810192fe, + 0x207f85e0, 0x220b8281, 0x4da7fe6a, 0x28080583, 0x7601a4fe, 0x69fd9702, 0xa1fd5f02, 0x02919702, 0x02fdfd3a, 0x00c6fd03, 0x00590002, 0x05000400, + 0x000c0062, 0x40320014, 0x3091822f, 0x03010403, 0x02020067, 0x01064d1a, 0x60000404, 0x05555305, 0x0d0d4b08, 0x140d0001, 0x0e10130d, 0x07090a0b, + 0x0c010c00, 0x2b160707, 0x26262221, 0x36363435, 0x33113333, 0x23112711, 0x10150622, 0x985e0221, 0xee8184e9, 0xc6c6d0a2, 0x01a39ad1, 0x8dbf5e37, + 0x0268c589, 0x9d9efa02, 0x908c2902, 0x7782f3fe, 0xe4ff1224, 0x77829204, 0x2a001f36, 0x41404400, 0x04020922, 0x084c0106, 0x06020501, 0x80060502, + 0x062c2182, 0x69060204, 0x1a030300, 0x0207094d, 0x61208882, 0x3706e65e, 0x00002020, 0x29202a20, 0x1f002325, 0x11231f00, 0x0a252326, 0x012b1b07, + 0x51061750, 0x94890502, 0xcb441420, 0x00272305, 0x9e843736, 0x65080f82, 0x560a8804, 0x7f546496, 0x55a15f24, 0xc565558f, 0x37ba598e, 0x0a4f4233, + 0x2854d9fd, 0x5785785a, 0x82f20248, 0x70ecb47c, 0x5e9a4b4f, 0xd49485bb, 0xfb080270, 0xad5b59ce, 0xfd8c76c7, 0x01524b8a, 0x88a5a1af, 0x0001007e, + 0x04e7ff2f, 0x00620581, 0xb5170124, 0x0201011b, 0xb04b4c01, 0x4058500c, 0x0206071f, 0xca820002, 0x49670121, 0x052d0a50, 0x00620005, 0x00200000, + 0xb04b1b4e, 0x2826820e, 0x06010726, 0x06030203, 0x9ced8302, 0xa50f202d, 0xac102054, 0xa3112054, 0xa6402054, 0x835920a4, 0x0f402100, 0x2439df82, + 0x21282400, 0x24132124, 0x2b1c0708, 0x10151601, 0x26222302, 0x35230327, 0x06a85f33, 0x20333529, 0x06141504, 0x41161307, 0x4e080699, 0xc30a7704, + 0x43a982aa, 0x9390a29c, 0xb4a79796, 0x010401b6, 0x8f94930b, 0x513c512b, 0xf8020a5b, 0xf0fe7882, 0x8f85f9fe, 0x7a964a01, 0x98717e86, 0xb490c1c6, + 0x5dc1fe2d, 0x6ecfae4d, 0x0100008c, 0xd1fe8c00, 0x62055904, 0x32001800, 0x61182f40, 0x00230627, 0x57040003, 0x00230819, 0x54060505, 0xd74a0559, + 0x20a08205, 0x0c274e11, 0x35210123, 0x829f8521, 0x339f8508, 0x9c88d103, 0x94fe4d1f, 0x3001e1fe, 0x9a929693, 0x560199fe, 0xb4339983, 0x30fea193, + 0x45022f01, 0x7d867997, 0xc2c59872, 0x8226c294, 0x348782f7, 0x04e4ff07, 0x00620599, 0x40350021, 0x02111232, 0x4c010300, 0x29328205, 0x03040103, + 0x01010080, 0x7d825f02, 0xc1531a20, 0x2937820b, 0x23210021, 0x0625141b, 0xc2421a07, 0x35262309, 0x694b2311, 0x4211200b, 0x043b07c4, 0x97550a8f, + 0x4b825363, 0x3a1321af, 0x2b674d52, 0x2d142a32, 0x33361602, 0x420a4f42, 0x4c3506b4, 0x8e037099, 0xebfe2cfe, 0x478cdcfe, 0x01722c84, 0x0207010d, + 0x07bf4245, 0x01227082, 0xa7825c00, 0xa7829c20, 0x68001d3c, 0x5011b04b, 0x08234058, 0x01040701, 0x80010704, 0x01000400, 0x67010406, 0x67640105, + 0x97272011, 0x10656425, 0x00001028, 0x1d001d00, 0x00821123, 0x09251424, 0xda8c1d07, 0x88094b67, 0x829220d6, 0x826420d6, 0xebfe26d6, 0x1501bbbb, + 0x29cf8ebb, 0x7efd4901, 0xbffd6205, 0xc68a4102, 0x07db7f18, 0x007b0525, 0x84260002, 0xff1e24d7, 0x827304e7, 0x00182dd7, 0x062d4030, 0x04010501, + 0x80040501, 0x085a5518, 0x004d1a26, 0x61000404, 0x2c632a82, 0x00182805, 0x11112218, 0x44072514, 0x3c080b3d, 0x21113526, 0x21072135, 0x32331411, + 0x27343536, 0x790a6904, 0x995e6dc1, 0x03a3fe5a, 0x86fe15b2, 0x0a7c6194, 0x7782f602, 0x5573f0b3, 0x5f0378a8, 0xabfca7a7, 0x6dcbb1e5, 0x0001008c, + 0x357f8470, 0x002c007b, 0x033c403f, 0x00010202, 0x01020124, 0x03021819, 0xcd670302, 0x002c2621, 0x2125242b, 0x218e8424, 0x44181600, 0x333009e5, + 0x22230733, 0x16141506, 0x37323316, 0x23040617, 0x08067245, 0x022e3765, 0x36363435, 0xe6090333, 0xa8516c68, 0xa2a0816a, 0xdc17e77d, 0x934daa8f, + 0x71adce66, 0x97fdfe5b, 0x5b80ef9f, 0x84535c98, 0x8cdc7b4b, 0x57557b05, 0x6e414072, 0xa16d6a67, 0x7851817e, 0x5f6b8f41, 0x7bc16d66, 0x0a559666, + 0x4f794a0d, 0x005da86c, 0x15000100, 0x130454fe, 0x19006205, 0x28402b00, 0x82081415, 0x06a54dba, 0x00030326, 0x0000005f, 0x2c09484a, 0x124e011e, + 0x04102324, 0x012b1a07, 0x0ba94721, 0x264e1120, 0x4601230a, 0x1a47cd02, 0x0b996f08, 0x4d620521, 0x052108a4, 0x0e9f6f38, 0x02248782, 0xc004e7ff, + 0x17358782, 0x27402a00, 0x03060e15, 0x01020004, 0x00010d4c, 0x02020049, 0x06527403, 0x00010137, 0x4e001b00, 0x12121b12, 0x1b070511, 0x2301012b, + 0x01230303, 0x0c3c4303, 0x13132c08, 0x01920333, 0xdde6bf2e, 0xc72701b7, 0x3a132072, 0x2b664e52, 0x2d142a32, 0xc2c59701, 0xfde302b5, 0xfd5a021d, + 0x01e002a6, 0x4334fedf, 0xfd240e36, 0x000202fe, 0x02260082, 0x00006200, 0x8f82a004, 0x70821220, 0x36403930, 0x05020e12, 0x01010206, 0x074c0205, + 0xaf820501, 0x69010525, 0x87060600, 0x85022098, 0x13142d98, 0x1b13181a, 0x21151b14, 0x08102311, 0x2133a082, 0x06060123, 0x23112323, 0x16322111, + 0x13151516, 0x44050133, 0x32080576, 0xa0041123, 0x39cefed1, 0xbb4a5e9f, 0xc0850201, 0xfebbd166, 0x7414feaf, 0x4b72828a, 0x45407c02, 0x620509fe, + 0x1081c169, 0x66fdbb01, 0x899a8936, 0x84c8fd8c, 0x820d2097, 0xac230897, 0x16006205, 0x43001f00, 0x01084040, 0x4c010702, 0x07000600, 0x67070602, + 0x0009010a, 0x02090002, 0x5e010867, 0x002309a6, 0x595f0100, 0x172a06d4, 0x171f1717, 0x1111221e, 0x03822711, 0x070b1026, 0x21252b1f, 0x0322ac83, + 0xd7470123, 0x07212306, 0x12821121, 0x0805da47, 0x33161423, 0xa2010a03, 0xde809afd, 0x760401db, 0x95db7577, 0xfe179402, 0xfe320184, 0x7b4ec4ce, + 0x9b6a7c89, 0x056b679b, 0x83bd373b, 0x9c66bb7e, 0x4d9c44fe, 0x81870f02, 0xff008384, 0xfe5700ff, 0x05ae04a6, 0x2192827b, 0x0f830058, 0xbb820720, + 0xbb82a920, 0x75000222, 0x0122cb82, 0x0f82a600, 0x0f829320, 0x3100142d, 0x13142e40, 0x0d0e0f12, 0x8304070c, 0x020427ab, 0x0004004c, 0x99440001, + 0x41022008, 0x15200560, 0x1128b682, 0x1c070612, 0x0107012b, 0x2e08df5c, 0x17372737, 0x17033337, 0x99480307, 0x5ceae401, 0xab2e05e4, 0x96ee4ce8, + 0x4cd5d3d1, 0xfddebc03, 0xe75c0222, 0x8ff33106, 0xfed5937a, 0x007983cf, 0xefff0100, 0x8e0454fe, 0x2b317f82, 0x46404900, 0x06020128, 0x03021721, + 0x020b2002, 0x5ff58201, 0x554d0df5, 0x0ebe5109, 0x2b29c882, 0x111b2a00, 0x27242413, 0x5a978208, 0xa5421aa7, 0x3611370c, 0xd9033336, 0x874c3f76, + 0x4a658357, 0x792d3e28, 0x4727383a, 0xe845bb25, 0x5b273b0d, 0x4b890339, 0x2afd5485, 0x4d488e65, 0x9416187a, 0x4a4bd002, 0x5bfd2120, 0xf345c704, + 0xdafd2210, 0x05b55a26, 0x7f5b3420, 0x00262b06, 0x244c404f, 0x17090701, 0x7f5b0401, 0x010a320a, 0x04020009, 0x00690209, 0x03040007, 0x08670407, + 0x17835b01, 0x25002623, 0x83008311, 0x070b22dd, 0x1f855b1f, 0x21113325, 0x82113311, 0x10895bd8, 0x45bb2721, 0x532106ea, 0x138b5b73, 0x5dfd2222, + 0x26064c51, 0xfd4102bf, 0x82004dda, 0x00022300, 0xf76e003c, 0x184f6805, 0x4f686720, 0x35232238, 0x104f6833, 0x689e7121, 0x8e2d054f, 0x01c6b2b2, + 0xbafdfe03, 0x939da392, 0x074d68bf, 0xb8872325, 0x68c587b8, 0x0023084d, 0x73000200, 0x2e0807df, 0x001b000f, 0x15464049, 0x05040212, 0x01020205, + 0x004c0204, 0x06040605, 0x00800405, 0x01020100, 0x07800200, 0x01000401, 0x68010400, 0x74060600, 0x99480646, 0x10113705, 0x1314181a, 0x1b111b10, + 0x13221121, 0x2b1a0708, 0x13070600, 0x35442723, 0x20440806, 0x32011504, 0x17330337, 0x21103536, 0x60041123, 0x9e9f555d, 0xac806b7b, 0x016d01c7, + 0xfd1a0103, 0xad3a52f4, 0xfe3b839e, 0x3f03bac8, 0xfbfe39b1, 0x09fe23ca, 0xd8d76205, 0x0110e0fe, 0x8644d71b, 0xcafd1801, 0xff248482, 0x0452fe47, + 0x26088b53, 0x0104010c, 0x8303010b, 0x580620a7, 0x94520559, 0x08706109, 0x4e031e22, 0x5305a24d, 0x2321078b, 0x0df54511, 0x22058b53, 0x4516fec6, + 0xc62008ef, 0x2305bc71, 0x0efd8202, 0x0806954d, 0xfddf052e, 0x000000c3, 0xfee6ff03, 0x05c804d1, 0x001c0062, 0x00280024, 0x0a4f4052, 0x010e0801, + 0x01080601, 0x03010567, 0x00530306, 0x5f070c0c, 0x0806b162, 0x100f1129, 0x0606040d, 0x02045f00, 0x1b000002, 0x25254e00, 0x28251d1d, 0x26272825, + 0x241d241d, 0x1b1c1e1f, 0x1718191a, 0x85111511, 0x07122400, 0x67012b1f, 0x2129089f, 0x33112303, 0x37123636, 0x061b7313, 0x33133e08, 0x03231101, + 0x07060206, 0x11231121, 0xacbc0c04, 0x86793494, 0x1e4ffe1d, 0x2b1e4183, 0x01200f27, 0x36986393, 0x1dfd9981, 0x250b1368, 0x08022b37, 0xfdda0263, + 0xfd860226, 0x01d1fe7a, 0x2b03822f, 0x019f4cbb, 0xf001e01b, 0x4902b7fd, 0xfb320383, 0xfe4a042a, 0xedfedb94, 0xfa0145ab, 0x030006fe, 0xdf826a00, + 0xdf826d20, 0x00172408, 0x0023001d, 0x144b404e, 0x0b080701, 0x02070901, 0x0007004c, 0x09070009, 0x01010367, 0x0b540100, 0x5c080801, 0x0c230734, + 0x7303040a, 0x1e30097f, 0x1e18181e, 0x20231e23, 0x181d181f, 0x1616141d, 0x1025dc83, 0x2b1e070d, 0x09da7a25, 0x26261329, 0x11331127, 0x82171614, + 0x052b08de, 0x33070607, 0x06210219, 0x21040706, 0xfd1f9c4c, 0x4b9c1f73, 0x8c934d89, 0x4439c101, 0x37022f12, 0x071b76fe, 0xeafefc0d, 0x7a4a6927, + 0x220808ed, 0x236c0198, 0x0c01bcd2, 0x8370f9fe, 0x8f01891e, 0x5944f89f, 0xdefb9501, 0xe0c2f001, 0x0000004e, 0x82030001, 0x564f20cb, 0xea5c3333, + 0x0c335605, 0x9c77d826, 0xcffe821f, 0x200b3256, 0x568a84a4, 0xff2d1332, 0xff7e00ff, 0x041b04e7, 0x00020037, 0x228b828b, 0x828d0002, 0x2123080f, + 0x1d00df05, 0x36002b00, 0x1a263340, 0x01020302, 0x0212134c, 0x01044a01, 0x03020001, 0x05690201, 0x49030301, 0x1e2907e7, 0x1e00001e, 0x242a1e2b, + 0x25328222, 0x0706261c, 0x55182b17, 0x02330909, 0x36123435, 0x37363637, 0x07060617, 0x3607020e, 0x5f123336, 0x5c080617, 0x16141507, 0x11033316, + 0xcf7461af, 0x74cd8888, 0x799aaa44, 0x40514b8c, 0x6c5b6e99, 0xa8360e44, 0x72882e6a, 0x3396556a, 0x034e713d, 0x96db75db, 0x827aeea6, 0xe5cd0f01, + 0x34bf2801, 0x8e323f29, 0x21274829, 0x58889c53, 0xa2a5fc62, 0x619fb4cd, 0xad7b815f, 0x00030059, 0x040000d4, 0x29cf8231, 0x001b0011, 0x40440023, + 0x73700841, 0x01112c06, 0x4c030205, 0x05000200, 0x52050204, 0x212709d9, 0x0401074d, 0x825f0004, 0x001b36fc, 0x121c1d4e, 0x1c202212, 0x12231d23, + 0x291a121b, 0x07082522, 0x2bcf8219, 0x06061415, 0x36112123, 0x16163233, 0x07240b82, 0x33110700, 0x20055648, 0x08068313, 0x1123233e, 0x7785ac03, + 0x66fe80cc, 0xc584a9ca, 0xfe72646b, 0x69cc59c8, 0x227b756f, 0xd8fb7d80, 0x76812f02, 0x04428b6b, 0x7c402611, 0x1c735758, 0xfe0c6901, 0x505448d9, + 0x52eefc47, 0xaafeae56, 0x01227a82, 0xb7823001, 0x1e041e32, 0x1f000500, 0x01031c40, 0x5f010202, 0x1c010100, 0x22099179, 0x79050005, 0x072f0a91, + 0x02c0f001, 0x810317ee, 0x1e047ffc, 0x85ffff9d, 0x4606253f, 0xb4012200, 0x02234f82, 0x82500307, 0x84418206, 0x2f052257, 0x17377e00, 0x02246182, + 0x4e021b02, 0x2c16377e, 0xfd17bf5f, 0x1e04c0e9, 0xeffe1101, 0x286b839d, 0x00020000, 0x04d1fe30, 0x2dab823a, 0x0017000f, 0x0d2e4031, 0x01060001, + 0x3d7e034c, 0x4d1c240c, 0x82020407, 0x455f202b, 0x15200575, 0x21053a44, 0x5c430810, 0x3e46080c, 0x21133702, 0x0e072107, 0x03210702, 0x1f9b51e9, + 0x9b1f6afd, 0x283b3049, 0xb702190d, 0x0bb4febf, 0x3e45270d, 0xfe990e02, 0xfe2f0138, 0x2ac801d1, 0x01b8d778, 0xc1b29654, 0x002d79d6, 0x9200ffff, + 0x1f04e7ff, 0x91823704, 0x8800a221, 0x3506260f, 0xb8012200, 0x207b8200, 0x4b6a1807, 0x00f4230d, 0x27820022, 0x07020024, 0x1e821400, 0x00010027, + 0x0400001f, 0x20c78291, 0x22c58315, 0x65020611, 0x07270d80, 0x03030205, 0x45084d1c, 0x15230612, 0x82111214, 0x26048200, 0x1f070a10, 0x7e23212b, + 0x0239132b, 0xca66a0a8, 0xbbe2f4b9, 0x67a067b5, 0xf4e2b5bb, 0x0163cabc, 0x0218fee8, 0x23058236, 0xfeab0155, 0x18250383, 0xe801cafd, 0x207f8200, + 0x20bf8263, 0x08bf8210, 0x4a002822, 0x010a4740, 0x01090201, 0x01140100, 0x011e0005, 0x011d0504, 0x4c050403, 0x00000106, 0x05000405, 0x20086557, + 0x082f4621, 0x4e032032, 0x25270001, 0x1a1c2022, 0x05070c0e, 0x28012800, 0x43056756, 0x27210761, 0x08b04236, 0xd4611620, 0x61202005, 0x450808d4, + 0x02372321, 0x7b766536, 0x46a95174, 0x71df5259, 0x7670c17a, 0x7d9c7a66, 0xf2fe8edc, 0xb15059b8, 0xff8e886f, 0x020dd700, 0x4e445370, 0x702c304e, + 0x8241443c, 0x1c74555d, 0x6c6c7f0d, 0x78924e99, 0x56633a37, 0xc38294a3, 0x0000bf3a, 0x1e04f103, 0x24000e00, 0x050d2140, 0x01020002, 0x0203044c, + 0x4d1c0202, 0x33063d4c, 0x0e000000, 0x14110e00, 0x19070511, 0x2311012b, 0x01373411, 0x08075f7d, 0xbdf10321, 0xe050fe1b, 0x010c0ebd, 0xfb1e04ab, + 0xd4d401e2, 0x04b1fca7, 0x692dfe1e, 0x4b0342cd, 0x8400ffff, 0x0b06255f, 0xbd012200, 0x02234882, 0x82fe3e07, 0x20178806, 0x21178835, 0x00830002, + 0xb1000226, 0x7104d1fe, 0x0f282f82, 0x70002300, 0x19210e40, 0x2f0b237e, 0x5029b04b, 0x001f4058, 0x02030002, 0x01086303, 0x6120a182, 0x1f323682, + 0x0601074d, 0x054d1c06, 0x1b040401, 0x401b4e04, 0x4c7e001d, 0x2b1f8812, 0x00164059, 0x1d222300, 0x151a1b1c, 0x21234f7e, 0xf0893634, 0xea013322, + 0x320f507e, 0x9d8fa392, 0x090e7747, 0xb9de63fe, 0xa3010d12, 0x7e0205e0, 0xfb350b51, 0x0135fe9a, 0x81d4012f, 0x93fc3eda, 0x2dfe1e04, 0x033fe377, + 0x34b5826c, 0x00c80001, 0x04780400, 0x000c001e, 0x08244027, 0x01020501, 0x2bda824c, 0x05020005, 0x01010367, 0x044d1c01, 0x3405c54b, 0x11111211, + 0x07061011, 0x23212b1c, 0x33113311, 0x01013301, 0x2e018223, 0xc9c0c088, 0xfed02401, 0xe18b01a8, 0x82c5b6fe, 0x015a2c5c, 0xfd18fea6, 0x00e401ca, + 0x85ffff00, 0x4606255f, 0xc1012200, 0x02236f82, 0x82280307, 0x01002706, 0xe7ff4b00, 0x77820204, 0x4417477e, 0x477e0ab5, 0x072b080d, 0x2707020e, + 0x1337023e, 0xfec00204, 0x3c111490, 0x3a51696c, 0x200f3141, 0xe2fb1e04, 0xedfe8403, 0x7b3a81f7, 0xc9d25b25, 0x8200a101, 0x824e2067, 0x826220df, + 0x00162a67, 0x152b402e, 0x0103070b, 0x18e18203, 0x200bd78a, 0x0a16611c, 0x1600162a, 0x11171711, 0x2b1a0706, 0x07d78a18, 0x82032321, 0x15163d01, + 0x23030714, 0x13133313, 0xb44b1704, 0x08020925, 0x08dcb2c6, 0xb21b0704, 0xc4d6f149, 0x01357983, 0x26857bea, 0x024cfd54, 0x6a513cb4, 0x0415fe82, + 0x023cfd1e, 0x21eb85c4, 0xdf4200bf, 0x000b2405, 0x4d1e4021, 0x7a880b23, 0x00831120, 0x51075d41, 0x0336087b, 0x4efec0f1, 0xb201c0c0, 0xfece01c0, + 0xfe1e0432, 0x00b70149, 0x5c18ffff, 0x0222085f, 0x6818d500, 0xf12008ab, 0x0720e382, 0x8b0bf37e, 0x0cf37e5b, 0x03255585, 0xfc850332, 0x8234827b, + 0xfebf2b4f, 0x04270455, 0x00020037, 0x5f8300e1, 0xe7ffb024, 0x0f841104, 0x5f849820, 0x00007c24, 0x5f874004, 0x01010325, 0x825f0001, 0x07f54517, + 0x5f84ba82, 0x07211322, 0x2130b983, 0x16c4037c, 0xfec08efe, 0x9b1e0484, 0x83037dfc, 0x4c182a82, 0x43820743, 0x06010222, 0x0a534c18, 0x22000b22, + 0x00200f83, 0x23069343, 0x34000300, 0x20088b82, 0x00dd057c, 0x002a001d, 0x40510038, 0x02021d4e, 0x2d2e0005, 0x04042627, 0x020d1005, 0x4c030401, + 0x34a98201, 0x020e0f4a, 0x07094901, 0x05050308, 0x01036100, 0x4d210000, 0x78761806, 0x01203d08, 0x1e2b2b4e, 0x2b382b1e, 0x1e303237, 0x27291e2a, + 0x23252625, 0x2b1b070a, 0x36111701, 0x09617618, 0x11071122, 0x2706ba5d, 0x32331210, 0x06061716, 0x25057775, 0x26261137, 0x59182023, 0x67080a75, + 0x06022326, 0x967153a4, 0x5d814278, 0x26a44e64, 0x805c315f, 0x36968240, 0x41d1295b, 0x39274641, 0x2939292b, 0x27429801, 0x47273c24, 0x2e381946, + 0xfe16dd05, 0xe7fe6907, 0xf9a8f2fe, 0x17fe6d88, 0x35ff0116, 0xa8f98838, 0x1d010a01, 0xbd2d3530, 0x2bbed8d8, 0x31730235, 0xfd302a27, 0xc02d338f, + 0x51b094d6, 0xffff0000, 0x086f4e18, 0x0501023a, 0x01000000, 0x00009e00, 0x1e04de03, 0x2f001300, 0x01122c40, 0x01030203, 0x4c220482, 0x1b820300, + 0x6a010327, 0x02020405, 0x0a2b4302, 0x13001325, 0x42231323, 0x112005c0, 0x50180782, 0x21080e4f, 0x3cc0de03, 0xa09960ab, 0x4a5956c0, 0x1e042d9a, + 0xb601e2fb, 0x95a43e36, 0x74fea301, 0x333d5862, 0x7383d601, 0xd1feb024, 0x73828104, 0x440e277f, 0x277f050b, 0xe2033122, 0xfc1f9b9f, 0xb201c0e9, + 0x7bfc1e04, 0x2f0138fe, 0x7d220782, 0x5b838303, 0x00005924, 0x5b845704, 0x2107277f, 0x277f4d1c, 0xb1a62722, 0xfbb002fc, 0xb283faa8, 0xfc224c85, + 0x4f84007d, 0xdf20ab82, 0x277f4f82, 0x4d1c210f, 0x202f277f, 0x20b38288, 0x8b638534, 0x83fc20b4, 0x000126b8, 0x03d1febf, 0x7fb784f1, 0x1c220b27, + 0x277f004d, 0xc0312b21, 0x9614c6fe, 0xc0c6fe14, 0xbf83b201, 0x41d1fe21, 0xbf820510, 0xf0000226, 0x32040000, 0x15225784, 0x277f3000, 0x205d820e, + 0x40401803, 0x0c0c2e08, 0x150c0000, 0x0d0f140c, 0x0b000b00, 0x07277f25, 0x95473220, 0x74481805, 0x23263b09, 0xeebfb001, 0x72be73d5, 0xd0c061fe, + 0x6d2f786f, 0xfe1e045e, 0x7baebab7, 0x08824ea4, 0x4ffe272c, 0x5e4b7564, 0x0200002f, 0x7b823c00, 0x7b844b20, 0x7f001421, 0x69290a2b, 0x03020200, + 0x0301065f, 0x23808203, 0x5f010404, 0x84052b7f, 0x0c142280, 0x32808513, 0x08212311, 0x012b1907, 0x11203311, 0x21230414, 0x82352311, 0x05d04a0b, + 0x75f00131, 0x01ffe601, 0xf4c5fee1, 0x7e87b401, 0x8283868a, 0xfeb72878, 0x03afc19b, 0x82fe918d, 0x7d602781, 0x03006470, 0x7f827000, 0x7f824020, + 0x0d000924, 0x81851600, 0x410b237f, 0x043d065c, 0x1b010101, 0x0e0e4e01, 0x160e0000, 0x0f11150e, 0x0a0b0c0d, 0x09000900, 0x07092123, 0x24818618, + 0x11232306, 0x0b227f21, 0x3f220131, 0xd2ebc301, 0xb41c03f7, 0x4896fdb4, 0x83777d7d, 0xfead3a84, 0x04b5b9a3, 0x02e2fb1e, 0x644afe44, 0x0063727d, + 0x00020000, 0x04e7ff03, 0x348782a3, 0x001f0015, 0x103d4040, 0x01040101, 0x01010f4c, 0x07000049, 0x091f7f01, 0x2d101141, 0x00001616, 0x1e161f16, + 0x15001719, 0x11411500, 0x7f8f830c, 0x40180927, 0x023e0944, 0xad011adc, 0xc5d0c8e0, 0x6b3b0a0c, 0x3c2f4463, 0x02160a2d, 0x634d2521, 0x047b6c33, + 0x9f82fe1e, 0x03b8b638, 0xe2f6fe8c, 0x7f3a85fa, 0xc0d35d26, 0x26fea201, 0x622949fe, 0xab857356, 0x00008424, 0xab82a904, 0x1c001139, 0x35403800, + 0x0a000105, 0x07020208, 0x09690200, 0x04040206, 0x7f004d1c, 0x002b0c2c, 0x121c1200, 0x0013151b, 0x83110011, 0x21232500, 0x2b1c070b, 0x16258f83, + 0x23211015, 0x06a96411, 0x1113113f, 0x36363233, 0x26263435, 0x1ae20223, 0x56fedcd1, 0xb5b5f8ce, 0x5020b1f8, 0x63313662, 0x289a8252, 0xfeab9e78, + 0xfd0e02b3, 0x2b0b83f2, 0xf0fd8801, 0x531c80fe, 0x24544950, 0x0a735b18, 0x00370425, 0x82e80002, 0x737b1810, 0x001d2909, 0x013e4041, 0x02050001, + 0x11240482, 0x12020301, 0x2015377f, 0x35951821, 0x05377f08, 0x1c001d25, 0x7f112225, 0x68570637, 0x79072006, 0x17200840, 0x0806b545, 0x36363437, + 0x977a0333, 0x48814559, 0x0113a57b, 0x0c27fed7, 0x814b83a6, 0xc2485744, 0x77e49f5d, 0x049ce478, 0x2e777737, 0x909ba129, 0x2f2ba7ab, 0x87413c78, + 0xfda0a5f7, 0x18a28290, 0x840a177c, 0x011a2ba3, 0x01190504, 0x010b0403, 0xf36e0201, 0x18002005, 0x820f6549, 0x06ed49a3, 0x82059c58, 0x21a282a3, + 0x49182625, 0x397f0a65, 0x27072111, 0x3308a382, 0x6dd9cb02, 0x679fe073, 0x405b49bf, 0x9d854c86, 0x011ffe0c, 0x7e950fdf, 0x49597b99, 0x370468c1, + 0xa6a7f686, 0x3e418bfc, 0xa52e2f79, 0x9d9f90ad, 0x3f3b785b, 0x2f055741, 0x040000e6, 0x0016060c, 0x00b50002, 0x00ffff00, 0x05200f84, 0x11076e18, + 0x55feb724, 0x27848303, 0x2784c120, 0x00002326, 0xd905f303, 0xb3203782, 0x022c4882, 0xe7ff6700, 0x37047604, 0x22001200, 0x201bb77e, 0x1ab77e1c, + 0x094d1c2c, 0x05070701, 0x05010861, 0xb77e2105, 0x13132913, 0x22130000, 0x191b2113, 0x11206682, 0x122c0082, 0x1b070a24, 0x1112002b, 0x22230210, + 0x2009147b, 0x848f1836, 0x033c080f, 0xbcb5b7bf, 0x800ab1ad, 0x0c80b6b6, 0x4b42a9b3, 0x434b1d1e, 0x211e4d45, 0x3704424d, 0xf8fee1fe, 0xdbfefcfe, + 0xfee00701, 0xfe1e0432, 0x96f4dd48, 0x888fae56, 0xae5c5cad, 0x56ae8d89, 0x0023de82, 0x825e0002, 0x04d826ef, 0x000d001e, 0x09b37e16, 0x2207f657, + 0x7e040067, 0x154906b3, 0x094e4408, 0x290fb37e, 0x26132303, 0x36343526, 0x8b5e1333, 0x03400807, 0xfafec0d8, 0x5dfdd6de, 0xc8cde25d, 0x697071cc, + 0xfb1e0475, 0xfe9201e2, 0x2bbe016e, 0xa79c638f, 0x6c0103fe, 0x58625c56, 0x23000100, 0xf30357fe, 0x2300d905, 0x11406100, 0x0402051c, 0x234c0103, + 0x23089f82, 0x0210114a, 0xb04b4904, 0x40585017, 0x0101051c, 0x065f0001, 0x1a000001, 0x0303004d, 0x02006102, 0x004d2102, 0x2006394c, 0x8218821a, + 0x00022321, 0x1c8f6701, 0x0a405931, 0x2f131111, 0x07111123, 0x012b1d07, 0x18152115, 0x2008d740, 0xdc661814, 0x064d6b09, 0x35234b08, 0x7f013533, + 0xb7fe4901, 0x955db13e, 0x78884893, 0x2c554e47, 0x8d4e5752, 0x9c9cc030, 0x8ea1d905, 0x534af0fe, 0x47fd96a2, 0x356db796, 0x7d46248c, 0x5dbb026c, + 0xfd466254, 0x8eaa0406, 0x0000008c, 0x3100ffff, 0x7f04e7ff, 0xa0821e04, 0x1082ee20, 0x6e000237, 0x3e040000, 0x11002405, 0x62001a00, 0x020011b4, + 0xb04b4a00, 0x2ad4822e, 0x08020020, 0x02060701, 0x84046707, 0x820520dd, 0x4d1c21dd, 0x25073a55, 0x1b4e031b, 0x13821e40, 0xd8841c82, 0x208a2c87, + 0x10405928, 0x1a121212, 0xde821912, 0x11212324, 0xe2850911, 0x15230727, 0x14112033, 0x83128206, 0x511320d1, 0x2e080736, 0x0a01d301, 0x0186f416, + 0xfee1fde5, 0xc0a5a5b3, 0x86897f97, 0xf1240582, 0xa0feda8e, 0xa503acbf, 0x2efdda8e, 0x7a5d59fe, 0x0000626e, 0x828c0001, 0x048d29c7, 0x00250037, + 0x13b04b9b, 0x1234af82, 0x03060118, 0x06040119, 0x01090102, 0x09000103, 0x401b4c04, 0x0220148e, 0x59201482, 0x22202e85, 0x25123d7e, 0x010a4d1c, + 0x41180909, 0x2a200ae5, 0x0321248a, 0x22fd8403, 0x43006105, 0x2d85082d, 0x2205db5c, 0x82124059, 0x00252208, 0x073e7e24, 0x070b2526, 0x36242b1f, + 0x2106776c, 0x99452726, 0x023e2406, 0x44163233, 0x2d080dff, 0x2b5aa303, 0x4c973c5f, 0x096ab97c, 0x7cbaba7a, 0x7db76a0e, 0x5c418b53, 0x6d385d2f, + 0x7a011076, 0x810684fe, 0x2727816b, 0x76413c6b, 0x334395dc, 0xd28a3805, 0x6e3a3875, 0x9ca12426, 0x00a7ac90, 0x42000200, 0x70040000, 0x7e001e04, + 0x1c20123b, 0x32233b7e, 0x7496c470, 0xbe96709c, 0x75e3a601, 0x0114018a, 0x836efe92, 0x1e042403, 0x838ffe8a, 0x825c205f, 0x82ad205f, 0x7e13205f, + 0x1c20143b, 0x35323b7e, 0x4a6faead, 0xa86f4491, 0xb2b2c377, 0x76e496ee, 0x9101ce67, 0x03876ffe, 0xfe1e0428, 0x86fa0106, 0xdb828cfe, 0x7b822620, + 0x7b828a20, 0x14001122, 0x21213b7e, 0x3b7e4d1c, 0x35032122, 0x3a053b7e, 0xacd7bef5, 0x8cb58d9e, 0xafdab09c, 0xc62403ee, 0x02cc6bfe, 0x01aafd56, + 0x8339fec7, 0x56022903, 0x65656301, 0x00c0fe23, 0x02220082, 0x87823a00, 0x8782ce20, 0x1a001727, 0x3d404000, 0x053b7e17, 0x00011a24, 0x407e4b01, + 0x7e1c2013, 0x19210940, 0x28407e18, 0x21072208, 0x79940313, 0x4786acc1, 0xad8748a8, 0xb3b3da96, 0x02d27501, 0xa2feb8d5, 0xfd5702b1, 0xfec401a9, + 0x2103873c, 0xa6821e04, 0x65656225, 0x84bdfe1f, 0xa04a089f, 0x120451fe, 0x06003306, 0x37002a00, 0x011b3440, 0x01160302, 0x4c020401, 0x01020506, + 0x2a4a0004, 0x00490101, 0x85000300, 0x01000400, 0x00630104, 0x5f030202, 0x1c030300, 0x11224e02, 0x05132f12, 0x012b1b07, 0x23051737, 0x32453725, + 0x37750805, 0x3435023e, 0x35212326, 0x21352101, 0x32330115, 0x06141516, 0x15020e07, 0x02171614, 0xfe52fb3f, 0xeffe7ef1, 0x87866c56, 0x8778b9a7, + 0xfe505542, 0xfd9601ab, 0xfe3803c0, 0xbca7884f, 0x706cc8dd, 0x0547472a, 0xf45bb77c, 0x1ef85bf4, 0x65578b37, 0x280f1672, 0x484f3d46, 0x9c510189, + 0x93a6fe90, 0x199c9492, 0x1e251c0e, 0xff244325, 0xfe4f00ff, 0x04750455, 0x2196821e, 0x174f00ed, 0x1d02210c, 0x013adf82, 0x00006600, 0x7c04a404, + 0x2e001100, 0x010a2b40, 0x030b0100, 0x02020302, 0x8356004c, 0x25248206, 0x01044d1c, 0x877c0303, 0x11400805, 0x25231100, 0x19070511, 0x3301212b, + 0x023e1301, 0x07173233, 0x06222326, 0xd1010107, 0x01d095fe, 0x3b18e60f, 0x49444257, 0x20201e35, 0xdcfe1025, 0x8bfc1e04, 0x6052f402, 0x0c82232d, + 0x74fc3027, 0x73848383, 0x008e0624, 0x93820122, 0x06030025, 0x824804f9, 0xff032266, 0x33ab82fd, 0x003704bd, 0x001a000b, 0x406e002a, 0x0601140a, + 0x1a4c0105, 0x33080f7e, 0x0505001a, 0x03045f00, 0x1c000002, 0x0601084d, 0x02610106, 0x83090b7e, 0x4d1c21a5, 0x61232283, 0x47000000, 0x2585067d, + 0x2f090b7e, 0x00001b1b, 0x291b2a1b, 0x15162123, 0x10111213, 0x82140b7e, 0x0afc7dd7, 0xf4490220, 0x06222106, 0x0805bd60, 0x9b999652, 0x9a969f9f, + 0x7f63ea9d, 0xb64f144f, 0xaf7c7eb5, 0xc4e723b5, 0x18183bd1, 0x3c34333a, 0x343b191a, 0x01220119, 0x01010105, 0xfedffe28, 0xfefffefa, 0x16effed8, + 0x045c7444, 0x036efc1e, 0xcaedfb92, 0x1e0215d7, 0x9595b256, 0xb45756b2, 0x56b29394, 0x0029af82, 0x00b60001, 0x045a0400, 0x180f7e1e, 0x8741dc82, + 0x100f7e07, 0x37082475, 0x175a0411, 0xf7f7e9fd, 0x04b6b6c0, 0xdefe9d1e, 0x0130fe8f, 0xbf018fd0, 0xc6245f82, 0xee0354fe, 0x1f255f82, 0x45404800, + 0x0a077e15, 0x1c4c0326, 0x4b010201, 0x85100c7e, 0x0ebf7870, 0x1e001f26, 0x23131111, 0x47170c7e, 0x0b7e0658, 0x89182407, 0x5e8fa44d, 0x29080509, + 0x7c519e7e, 0x9902c03d, 0x3a41fe1a, 0xba0260a0, 0xfe648f4b, 0x4da49a16, 0x93141778, 0x52b8eb01, 0x0479fe4b, 0x9bfe951e, 0xab825244, 0xd1fe2a24, + 0xab82b804, 0x2520077e, 0x04064d1c, 0x077e0202, 0x9d200831, 0x1f8671aa, 0xa063bf49, 0xe9b8c066, 0x67aabcd8, 0xb6b067a0, 0x63fe3602, 0x2f0138fe, + 0x18fee801, 0x410f4f56, 0x633805a3, 0x10041bfe, 0x3c003704, 0x23409600, 0x0807012f, 0x0706012e, 0x06050139, 0x20071b4b, 0x188c8203, 0x27082494, + 0xb04b4c08, 0x4058500d, 0x561e0d7e, 0x0d7e0c6c, 0x302e8c21, 0x250c4059, 0x24232124, 0x29251311, 0x2b1f0709, 0x9d951824, 0x0b935617, 0x22065559, + 0x56070622, 0x04230dbc, 0x7eb6d810, 0xf4210f07, 0x09a756a9, 0xca56be20, 0xadaa2211, 0x36671812, 0x0bb0220e, 0x06b75686, 0x2b11d456, 0x01000000, + 0xd1fec800, 0x1e049904, 0x2818fb7d, 0x01044d1c, 0x021b0202, 0x1dfb7d4e, 0x2001ed29, 0x481f9b8c, 0x55c5b6fe, 0xbc41055f, 0xfee42208, 0x0563551c, + 0x00206b83, 0x2a05bb55, 0x40360014, 0x07010c33, 0x824c0102, 0x0109355c, 0x07020807, 0x00030067, 0x08030008, 0x01010567, 0x064d1c01, 0x2405c555, + 0x11111314, 0x58798412, 0x33250780, 0x33353311, 0x07ce5515, 0x35231537, 0xbf870123, 0x355f57bf, 0xfec50e01, 0xd06c01c7, 0x5f35cafe, 0x2c728257, + 0x01e6e658, 0xfd1afea8, 0xf5e501c8, 0x82ea82f5, 0x8245207f, 0x056b287f, 0x001400dd, 0x823b403e, 0x01073d66, 0x020c0d4c, 0x01054a04, 0x03010604, + 0x67030408, 0x01000700, 0x67010700, 0x08080109, 0x82087a4b, 0x0014263c, 0x13111114, 0x24008211, 0x1e070a12, 0x0bfa7d2b, 0x2115373c, 0x33112115, + 0xfe380401, 0xe18c01a7, 0xc09db6fe, 0x01c09e9e, 0xa1dffe21, 0x87822401, 0xcafd1831, 0x1cfee401, 0xca8e6e04, 0xfe8ee117, 0x82a6010a, 0x0001224f, + 0x288b820d, 0x001e049b, 0x4033000e, 0x208b8230, 0xb14a1805, 0x03002309, 0x297d0403, 0x7d828b05, 0x122307ff, 0x8a1c0708, 0x2f7a8480, 0x01a8fe69, + 0xb7fee18a, 0x01f4c0b0, 0x2201b5b4, 0x03247689, 0x5afe918d, 0x00277284, 0xfea00001, 0x827204d1, 0x18ab7273, 0x8208ec41, 0x180f20a2, 0x2112a651, + 0xeb551123, 0xd2032507, 0xa61f9ba0, 0x5305ed55, 0xf4550734, 0x0001220a, 0x20df82a3, 0x356b82b7, 0x4027000d, 0x00060024, 0x03060203, 0x01010067, + 0x01055f00, 0x55420000, 0x0710250e, 0x012b1d07, 0x38068f55, 0x33112311, 0xda022111, 0xfe16dd01, 0x89fec0f9, 0x7701c0c0, 0xfc991e04, 0x825f877b, + 0x0001229c, 0x20cb82b1, 0x7b5f8282, 0x6974052b, 0x05f55e08, 0x477d5e88, 0xe303251a, 0xa51f9b9f, 0xbe87c182, 0x27065f56, 0x35000100, 0xab0454fe, + 0x22285b82, 0x46404900, 0x0702011f, 0x0da74318, 0x54105b7e, 0x1b200511, 0x7e0e9b45, 0x2621085b, 0x18dd8209, 0x821aa943, 0x213f08f0, 0x33363611, + 0x4277f203, 0x65838da4, 0x2d3d294a, 0x323b3e80, 0xfebe254e, 0x9c02bddf, 0x0243682b, 0x538047ba, 0xa39af1fd, 0x1517774d, 0x46150293, 0xfe23224b, + 0xfc860320, 0xfe1e047a, 0x8228284c, 0x02003ee7, 0x09ff6f00, 0x37045504, 0x34002800, 0x3e404100, 0x01020113, 0x02040114, 0x0503012b, 0x05ff7d07, + 0x7d040521, 0x212012ff, 0x2f0b3d6a, 0x2333262b, 0x07062826, 0x06002b1c, 0x07171607, 0x480bfa6c, 0x1522065e, 0xf97d2110, 0x55600819, 0x6a436e7d, + 0x41507b75, 0x74d89447, 0x8d8ed370, 0x584d4a6a, 0x1c018e7e, 0x30340912, 0x565b8546, 0x69fe4882, 0x49492d28, 0x3d39363b, 0x3fd13e01, 0x85597656, + 0xf5820f68, 0x8cfea7a8, 0xc928893c, 0x0179fec7, 0x53459154, 0x85474f87, 0x487d4358, 0x455a8b26, 0x0047544f, 0xb0000100, 0x11041cfe, 0x2b34df82, + 0x37403a00, 0x0203011b, 0x04021c27, 0x08282b03, 0x07040103, 0x2c1beb7d, 0x254e0321, 0x24242c23, 0x2b1b0705, 0x10ea7d04, 0xf3682e20, 0x22dd8605, + 0x69141506, 0x06240514, 0x3f980307, 0x2509e57d, 0xc68a4a48, 0x8d187868, 0x83270c36, 0x4d90375c, 0x7d439073, 0x3c2607e0, 0x8d0d3174, 0x8c189aec, + 0x2e230c3a, 0x83000d3f, 0xfe7c24bb, 0x424004d1, 0x012108af, 0x0ddb7d00, 0x200a4d48, 0xcc55180b, 0x083d710b, 0x04352138, 0x8efe1640, 0xa51f9b9f, + 0x1e0484fe, 0xfe16fd9b, 0x032f0138, 0x5b839b83, 0x55fe6824, 0x5b824804, 0x1700083c, 0x05081440, 0x05000102, 0x01014900, 0x001c0000, 0x0213124e, + 0x012b1807, 0xcf6f1107, 0xb6023c05, 0xcd6efebc, 0x26012701, 0xfe6efec6, 0xc801176c, 0xb0fc0104, 0xfffb5003, 0x87000100, 0x000e2547, 0x0e27402a, + 0x01264082, 0x0206074c, 0xb1434902, 0x01012407, 0x46036002, 0x1321070d, 0x055e5b11, 0x2406147e, 0x35231107, 0x2b0b8233, 0xfec68203, 0xbccfa29b, + 0x9bfea2cf, 0x042f6782, 0x8e72fc1e, 0x01176afe, 0x8e038ead, 0x8200b0fc, 0x00012600, 0x04d1fe64, 0x23af8268, 0x4028000f, 0x2113177e, 0x65864d1c, + 0x2d16177e, 0x02331313, 0x841901cb, 0xfe491f9b, 0x6618feed, 0x022709b8, 0xfe65fe34, 0x182f0138, 0x280bbb66, 0x00010000, 0x04d1fe00, 0x206f8459, + 0x11137e31, 0x58056b46, 0xf8440a25, 0x82212013, 0x072133dd, 0x11211123, 0x9a78e103, 0xee4efd1f, 0xdd17a002, 0x3b447701, 0x8f8f2608, 0x030cfd8f, + 0x23de8283, 0x8a000100, 0x69206f82, 0x137e6f82, 0x826a2015, 0x00012924, 0x01066301, 0x4d1c0404, 0x22052b60, 0x7e132313, 0x35311313, 0x14113311, + 0x36323316, 0x03331137, 0x1f9b9fca, 0x0a0d59a5, 0x8499c021, 0x120f59eb, 0x2a078359, 0x4035001a, 0x02171a32, 0x7e060605, 0x00280513, 0x02030005, + 0x006a0305, 0x30069165, 0x00000104, 0x01004d1c, 0x4e011b01, 0x31131311, 0x0be87d14, 0x23150723, 0x098e5935, 0x8a821720, 0x3736363f, 0xc0c01e03, + 0x0a6f6e4b, 0xc0a09915, 0x376f4e4a, 0x1e042062, 0xb601e2fb, 0x90a11f43, 0x05975901, 0x05585c3d, 0xd6fe3401, 0x0024340d, 0xc1000100, 0xf1030000, + 0x1400d905, 0x28402b00, 0x82020c11, 0x104c286c, 0x4a03020f, 0x82030104, 0x0103221e, 0x61451869, 0x1313260b, 0x07051423, 0x10e37d19, 0x11373208, + 0x03333636, 0xc04b8d19, 0x7d555155, 0x39c0c038, 0xc003639d, 0xfd64914e, 0x6a640283, 0xfd54585d, 0x15c40581, 0x534b49fd, 0x00010000, 0x04d1feb7, + 0x24738286, 0x402e0018, 0x2173832b, 0x73830103, 0x7f4a0521, 0xd9480e95, 0x13252206, 0x06cb4223, 0x8f7f2520, 0x26342105, 0x8406384b, 0x16322976, + 0xe7031516, 0xa51f9b9f, 0x5f277b89, 0xfe994b8d, 0x8e2f0138, 0x3490827c, 0x00020000, 0x04e7ff13, 0x0037045c, 0x002d0027, 0x183f4042, 0x1fe37d17, + 0x004d2122, 0x3709e37d, 0x2d282828, 0x24252d28, 0x2325131b, 0x1d070911, 0x2107002b, 0x3233021e, 0x21096a51, 0xe27d2626, 0x823e200b, 0x21a2821b, + 0xb4830227, 0x4d087782, 0x480383fd, 0x66454d79, 0xa740593e, 0x71c6885d, 0x278b830a, 0x13157624, 0x0c103234, 0x7f77b76d, 0x06b45fb5, 0x0a7e68d7, + 0x70320002, 0x27264795, 0x79413473, 0x7c0294dc, 0x385a3769, 0x223c2d36, 0xd88a3530, 0xa1eb7d7b, 0xa449012c, 0xcf8400a5, 0x842dfe21, 0x003828cf, + 0x407f003e, 0x7d282911, 0xe08230db, 0x7d020221, 0x21362cdb, 0x40594e07, 0x39393911, 0x253e393e, 0x23191b24, 0x0a11232b, 0x0c411e07, 0x05a84f0b, + 0x37323325, 0x6e230607, 0x372305bf, 0x41270226, 0x5124271c, 0x276a5f5e, 0x09968c18, 0xa4545224, 0x29410dc0, 0x1d41231f, 0x8c184c29, 0x78250aa0, + 0x00011c30, 0x163941c6, 0xffff2008, 0xe7ff6f00, 0xc605f703, 0xc7000200, 0xffff0000, 0x00001f00, 0x0b069104, 0xbb012200, 0x5e000000, 0x01290743, + 0x54feca00, 0x1e04eb03, 0x1ad37d00, 0x25052046, 0x0101004d, 0x3b826200, 0x4e001e22, 0x2229d37d, 0x4d9288c8, 0x283108f6, 0xc0d04957, 0x140185c0, + 0x0f5902c8, 0x7ffe93a4, 0x06f34d9a, 0x564a8234, 0x0437fe26, 0x013ffe1e, 0x010000c1, 0xd1fe4800, 0x93826504, 0x441dd37d, 0x1b2007bf, 0x600fd37d, + 0x290808f5, 0xa2c30321, 0x7d479d8f, 0x1215cdfe, 0x52696a3c, 0x0f31423a, 0x9c9f0220, 0x2f0135fe, 0xeefe8403, 0x7b3982f6, 0xc9d35a25, 0xd682a101, + 0xbf247782, 0xf10354fe, 0xcf7d7782, 0x2174821a, 0x4f770404, 0x7d622005, 0x312127cf, 0x080241c0, 0x2107b44a, 0xfb8674fb, 0xfe4d0223, 0x20f88232, + 0x22808249, 0x82c00001, 0x4b6b20f7, 0xcf7d3823, 0xa1ca210d, 0x7c2af982, 0xc0c076fe, 0x1e048a01, 0xf3837efc, 0x2107c44a, 0x6e82b701, 0x00010027, + 0x03d1fe9e, 0x072b46de, 0xcf7d1720, 0x7d6a200f, 0xa8450acf, 0x13232407, 0x45111123, 0x032309a8, 0x60331123, 0x2d460514, 0x1e032609, 0x9b1f95c0, + 0x0e3a5f8f, 0x01d1fe31, 0x353301c8, 0x0195a43e, 0x638bfe8c, 0x82323d58, 0x825f207f, 0x82b020ef, 0x0018297f, 0x162f4032, 0x04060a0d, 0x820dd07d, + 0x63012522, 0x05050106, 0x7d08534b, 0x2c081fcb, 0x33131333, 0x90991704, 0x25654794, 0xb1a6020a, 0x1b0703bb, 0xadf149b1, 0xfe9cf69a, 0x012f0135, + 0x22868fea, 0x0237fd58, 0x764849c9, 0x09786287, 0x9769ff20, 0x0b062306, 0x97692200, 0x3e072505, 0x000000ee, 0x05211787, 0x211788f4, 0x1784f000, + 0xfff4ff2b, 0x04bb04e7, 0x00020037, 0x20278495, 0x200f8292, 0x673f831f, 0x3e21060b, 0x82278212, 0x8289201d, 0x82262017, 0x00162d27, 0x4040001e, + 0x0201143d, 0x01011303, 0x2f055853, 0x04010504, 0x02020067, 0x01066103, 0x4d210303, 0x2d0df37b, 0x1e170000, 0x191a1d17, 0x15001600, 0x19691522, + 0x11122205, 0x07cd5b14, 0x0809e07d, 0x36123340, 0x16152137, 0x3b033316, 0x93d671eb, 0x056dcc8a, 0x8a0acd02, 0x42855283, 0x87d99a56, 0xe8fd0786, + 0x047e8802, 0xfeddfe37, 0x87faa8fc, 0x3ca2eb7d, 0x2da0ad23, 0xfc7f7d35, 0x10af9847, 0x0f54a295, 0x83262007, 0x150221e7, 0x0223b882, 0x82030007, + 0x07374406, 0x37441783, 0x84158206, 0x826320ef, 0x841020d7, 0x85bc2017, 0x42f1202f, 0x73360553, 0x130455fe, 0x1d001e04, 0x40404300, 0x0504011c, + 0x00030117, 0xe4820b0c, 0xc47d0320, 0x4d1c2111, 0x0121fd82, 0x05484361, 0x1b00012f, 0x1618191a, 0x090e1014, 0x011d0007, 0x055c671d, 0x06791620, + 0x82372008, 0x05335fe1, 0x0808c67d, 0xd28f3f33, 0x8ede7c73, 0x6f52d096, 0x87699546, 0xb4999b98, 0xa9fdab01, 0x46fe3103, 0xb25a9d01, 0x6fc98282, + 0x44695a59, 0x868d953d, 0xe7018a79, 0x0ffe909c, 0x07cb6600, 0x66d10521, 0x0a2008cb, 0x1788ba83, 0x1788f420, 0x2f831683, 0xeb828920, 0xeb842720, + 0xeb85c620, 0x00220582, 0x5b640300, 0x000f3c08, 0x001c0015, 0x003a403d, 0x05010802, 0x67050204, 0x03030107, 0x01066101, 0x75210101, 0x16330ba4, + 0x00101016, 0x161c1600, 0x10181a1c, 0x12141015, 0x180f0011, 0x88071a65, 0x35262ce8, 0x33363634, 0x26210306, 0x84012326, 0x183720f3, 0x2e0ccf80, + 0x040212f2, 0xfe768109, 0x787f0cfb, 0x180c7f77, 0x290ed680, 0xa09fc1fe, 0xa3ae33fe, 0xa482aea3, 0x084b8018, 0x0221d382, 0x20bb851d, 0x20178502, + 0x20d382b0, 0x20d38411, 0x201785db, 0x0a7b64f7, 0x64d10521, 0x1b41086b, 0xfe702407, 0x84400455, 0x85cb202f, 0x0633412f, 0x06211784, 0x852f828e, + 0x51042117, 0x9e244785, 0xde030000, 0xcf202f84, 0xe6202f85, 0x00290682, 0xfe300101, 0x041e04d1, 0x15c77d1e, 0x200a8a4c, 0x14c77d09, 0xfd171e32, + 0x1f9b9fe9, 0x9d1e04a5, 0x38fe18fd, 0x1e042f01, 0x7022e382, 0x9b860000, 0x9b89d620, 0x00010027, 0x0454fe87, 0x7d6b825a, 0x7f8228c7, 0x2120c77d, + 0x4c691533, 0x22232105, 0x20054853, 0x08c77d35, 0xe9fd4325, 0x4576f7f7, 0x762d08eb, 0xee02b6b6, 0xdefe8103, 0xfec9fe8f, 0x06ef45f9, 0x83557f20, + 0x82502007, 0x8458209b, 0x4320089b, 0x171a4040, 0x06041114, 0x01010904, 0x00010802, 0x074c0301, 0x02040601, 0x80020604, 0x04040105, 0x4f06924c, + 0x1b230ee2, 0x82121b00, 0x25242900, 0x2b1c0708, 0x15231525, 0x0a8a5318, 0x7d233521, 0x132705ca, 0x01013313, 0x88015804, 0x4c462093, 0xfe260cb3, + 0x991901b0, 0x9a886e99, 0x0c767318, 0x0065fe25, 0x65010000, 0x11200863, 0x211bcf7d, 0xcf7d4d1c, 0x0889831f, 0x17042133, 0x5501e0fe, 0xfef3fee7, + 0x5a01d8e4, 0x1c01d9fe, 0xe6e0dffe, 0xddfed7ec, 0xf4011f01, 0xcf010cfe, 0xf40131fe, 0xfea80182, 0xfe93016d, 0xff000058, 0xaf9a18ff, 0x00022208, + 0x088f829e, 0x0f000225, 0x9f04e4ff, 0x2100dd05, 0x4d002e00, 0x01164a40, 0x01250205, 0x08240504, 0x03040302, 0x0217184c, 0x82074a02, 0x0503270f, + 0x00800304, 0x2e5e0505, 0x06082406, 0x18030302, 0x2908585c, 0x00002222, 0x2d222e22, 0x46822729, 0x26272125, 0x7a092424, 0xdb7b05ad, 0x07614505, + 0x33363627, 0x11171632, 0x05064d17, 0x27343528, 0x11373600, 0xbc782626, 0x33540805, 0xb60a9504, 0x248a5a9e, 0x68457434, 0x97534c93, 0x265d4064, + 0x49353eba, 0xc5fd0a4e, 0x49252c55, 0x4e5b5131, 0x82f20249, 0xfef0fe76, 0x5e5b59fa, 0xa6f78753, 0x348ffda0, 0x170a0230, 0x645c76fb, 0x8c70ceac, + 0x554b8bfd, 0x3a371302, 0xc6cbc8cb, 0x13000100, 0x8330db82, 0x24001e04, 0x3b403e00, 0x0201011c, 0x01074c01, 0x2016527d, 0x08e0581c, 0x4e002022, + 0x200aa67c, 0x06a67c25, 0x22052746, 0x7c232727, 0x625a0aa7, 0x17230805, 0x32331616, 0x04273411, 0xab620a79, 0x4cae8270, 0x6cbdce5a, 0xf37c7970, + 0x72e4d7f5, 0x5e2c6171, 0x830aba3d, 0xefb737b7, 0xa48b7d70, 0x5d615991, 0x9da69056, 0xad288f6d, 0x7a013e50, 0x6c828c70, 0x9824ab82, 0x2e04d1fe, + 0x7c07bb47, 0xa9821ca3, 0x1b020227, 0x24214e02, 0x0da37c21, 0xa37c0320, 0x2a9b850b, 0x9ba38b03, 0xfefa5b1f, 0x822001c7, 0xfe7b3092, 0xd85701aa, + 0x996e6fe3, 0x2f0138fe, 0x84938e01, 0x9ea5248b, 0x8229906c, 0x00012684, 0x04e4ff04, 0x2083829d, 0x1b9f7c20, 0x03217e82, 0x073d7103, 0x20233682, + 0x7c232000, 0x2b6b149f, 0x11212207, 0x06204114, 0x0a933608, 0x52659c5b, 0x16b94f85, 0x53593813, 0x24332d51, 0x1f02200f, 0x0a9c3538, 0x7682f202, + 0x4971efb6, 0x55026d95, 0xf6e8fafe, 0x25793a7f, 0x01c3ce61, 0x44f7fca7, 0x06244155, 0x54000122, 0xa4209f82, 0x977c9f82, 0x0403250c, 0x80040703, + 0x620b977c, 0x27230f47, 0x94070108, 0x2d977c25, 0x2f553520, 0x06c74f07, 0x27343524, 0xd1849a04, 0xfe50862c, 0x01bbbbef, 0x3638bc11, 0xcb8a5647, + 0x32fe9f28, 0x46fe1e04, 0xc583ba01, 0x70cbaf2f, 0x0001008c, 0x03e9ff8c, 0x003704ec, 0xd363181e, 0x00032b09, 0x0201010f, 0x01040114, 0xf7634c04, + 0x00002d08, 0x01066105, 0x4d210505, 0x04010100, 0x0cd36318, 0x12112224, 0xf7632525, 0x07172405, 0x5b232626, 0x3327053f, 0x23113732, 0x4d112127, + 0x4308073f, 0xef023336, 0x406853a6, 0x86514b76, 0x70848850, 0x0115bb5d, 0x93d1b98b, 0xe38771d2, 0x41370486, 0x2c307840, 0xd484b053, 0x17012bbf, + 0x6b00fe92, 0xa6b5f87d, 0x000085f9, 0x06000100, 0x4904e4ff, 0x19001e04, 0x2015277d, 0x0e277d1c, 0x19001923, 0x1a277d23, 0x7d331621, 0x29080528, + 0xc0750841, 0x599d6470, 0x5603bcfe, 0x55c5fe17, 0x087e614a, 0x8778e302, 0x546fe7aa, 0x3d026fa0, 0xc4fd9a9a, 0xc0ac6666, 0x83837d7e, 0xffa02c08, + 0x044d04e7, 0x002a0037, 0x2012407c, 0x21040501, 0x0a050601, 0x0b000101, 0x04010201, 0x26b04b4c, 0x25405850, 0x00060300, 0x18720306, 0x4f102a9b, + 0x1b220c84, 0x27852640, 0x9d800021, 0x40592228, 0x31ff820f, 0x2529002a, 0x23251626, 0x1c070821, 0x2307012b, 0xb6511520, 0x0af76505, 0x48263721, + 0x32200554, 0x83071d61, 0x03450822, 0xffce0c48, 0x6c888e00, 0x53594fb5, 0xdb8d90e7, 0x4680507b, 0xc2707567, 0x52de7279, 0x51a94659, 0x65767b74, + 0xa3947002, 0x373a6356, 0x4d504278, 0x6f4c6c98, 0x711c043b, 0x46835a55, 0x2c703c44, 0x444e4e30, 0x26fb8353, 0x0454fe4b, 0x7d1e0402, 0xe7491963, + 0x17637d0c, 0x2307b64d, 0xdc022601, 0x6e08b046, 0x04210bb5, 0x08364d1e, 0x6e030421, 0x002009bb, 0x01260082, 0xe7ff1c00, 0x8382af04, 0x5f7d1720, + 0x08217119, 0x5f7d1220, 0x08fc4311, 0x3313132e, 0x16019903, 0xb5c4c5c1, 0x9faa1301, 0x2d05f943, 0x0f28322a, 0xa3c10120, 0x3402b1a7, 0xe253ccfd, + 0xfe5e2206, 0x05f843f4, 0xc5d25b39, 0x81fea701, 0x00007f01, 0xfe4f0002, 0x04ab0455, 0x00160037, 0x63900024, 0x1739050e, 0x0205010e, 0x13162021, + 0x05060502, 0x06000109, 0x0a0b4c03, 0x1b490002, 0x22199540, 0x85594901, 0x00192638, 0x5f020505, 0x05dd7104, 0x06010734, 0x01610006, 0x1b000001, + 0x401b4e00, 0x02010421, 0x8c181c02, 0x212208df, 0x1882004d, 0x24834d20, 0x61012c08, 0x20010100, 0x40594e01, 0x1717170f, 0x27231724, 0x24152312, + 0x1c070810, 0x0323212b, 0x2223020e, 0x07112726, 0x36173311, 0x83203336, 0x680020ee, 0x222005cb, 0x0805c26d, 0xc9ab0444, 0x885709cd, 0x2b5f4652, + 0x300ea2bc, 0x10014e71, 0xf0bebf17, 0x1d5d5efe, 0x5c363641, 0x2e522a2c, 0xda91c701, 0xfe383775, 0xc9051615, 0xfe4b487a, 0xfeb8012f, 0xc064fe00, + 0x4eae94ce, 0xe8fd4447, 0x8c823e3d, 0x00030031, 0x04e7ff09, 0x003704a5, 0x00260020, 0x85f10031, 0x0e0e30d4, 0x02050101, 0x03010601, 0x03060001, + 0x8a401b4c, 0x82022010, 0x37fb8610, 0x08010c2a, 0x08010500, 0x09006705, 0x09060100, 0x010a6701, 0x61030707, 0x2205dc5f, 0x1806010b, 0x260a3166, + 0x5024b04b, 0x94384058, 0x61042631, 0x21040400, 0x2a3c844d, 0x0303005f, 0x02004d1c, 0x854d1b02, 0x25a68240, 0x1b4e0020, 0x3a903640, 0x07070022, + 0x00223986, 0xc8610a0a, 0x3e389105, 0x1b405959, 0x00002121, 0x282a2d2f, 0x26212621, 0x20002325, 0x21141f00, 0x25131126, 0x641c070d, 0x03220ca1, + 0x83431323, 0x21740805, 0x12323336, 0x21071415, 0x13331616, 0x22232626, 0x33162403, 0x37363633, 0x15062223, 0x4462a903, 0x61a93f54, 0x1164a269, + 0xd2b9bd5b, 0x79b764b9, 0x443b1701, 0xfd04b1a8, 0x5f7206ec, 0x53530393, 0x4dfe14ad, 0x022a6668, 0x69832f32, 0x2f267c6f, 0x6b4a356b, 0x6efe80c0, + 0xc854b601, 0x19549662, 0x2ef6edfe, 0x01a6ac32, 0xfea7a6dd, 0x725b1fb3, 0x646347c3, 0xff2de882, 0xfe8900ff, 0x04f10355, 0x00020037, 0x0f7e18e3, + 0x1e042409, 0x43010200, 0xc4240543, 0x74040000, 0x14240f82, 0x2e403100, 0x2405ae7e, 0x14030406, 0x05f17b01, 0x7e000421, 0x1c2008af, 0x21070672, + 0x00821115, 0x211aaf7e, 0xea72543d, 0xc0c02e05, 0x48ab61c9, 0xb6d076b0, 0xad0248a8, 0x06965c77, 0x5afe1e31, 0x6d73698d, 0x68fefeaa, 0x01000072, + 0x5afee8ff, 0x2a3005fb, 0x46404900, 0x06020127, 0x03021620, 0x020a1f02, 0x11a55e18, 0x05040426, 0x0505005f, 0x200a9a52, 0x22c38261, 0x454e001e, + 0x1b200510, 0x22a55e18, 0x5b09726c, 0x3e210e01, 0x06015b2c, 0x1215cd2d, 0x52545938, 0x0f29322a, 0x5b350220, 0x8428190a, 0xf7e7fafe, 0x25793a7f, + 0x20050944, 0x05135b4c, 0x2b09cb5b, 0x404f0026, 0x0701234c, 0x04011609, 0x0a735f18, 0xa77e0a20, 0x15cf5b13, 0xa77e2620, 0x7e262009, 0x834c0aa7, + 0x56112008, 0xf4470836, 0x14d55b09, 0xdbfebc27, 0x2501bbbb, 0x52cc98bc, 0x46220623, 0xdb5bba01, 0x00802a09, 0x042f0400, 0x0012001e, 0xf766181a, + 0x00672615, 0x4d1c0404, 0xf766180a, 0x1421080a, 0x19000113, 0x141a1317, 0x0f10111a, 0x0b0c0d0e, 0x0708090a, 0x01120005, 0x16070b12, 0x1632012b, + 0x08a46815, 0x21153326, 0x13152307, 0x0806d879, 0xd5790226, 0xfee6fce1, 0xc0a6a6d9, 0xf8160e01, 0xeb897a7a, 0xaca40292, 0x03afad9c, 0x75758e1b, + 0xf0fd778e, 0xfeb77059, 0x21089282, 0xfebc0002, 0x04250455, 0x00140037, 0x40830026, 0x020e2218, 0x19230504, 0x04060316, 0x03020509, 0x67450601, + 0x05774406, 0x04002427, 0x04050605, 0x2c398206, 0x00860001, 0x61020505, 0x02020103, 0x0533451c, 0x33456220, 0x401b2205, 0x45268d28, 0x07240d63, + 0x01060601, 0x592f2a86, 0x15150f40, 0x25152615, 0x14231526, 0x5c081322, 0x172505b5, 0x23062723, 0x085f4522, 0x11123226, 0x33033700, 0x089d5a18, + 0x11076308, 0x04331616, 0x91555725, 0x3f336b9e, 0xa6c069aa, 0x5ca13a0e, 0x63feb5c9, 0x8f9eb921, 0x74701d20, 0x29307e4c, 0x71014676, 0xafee45f6, + 0x0dfe7810, 0x8ec90517, 0xe0fe5651, 0x72fef9fe, 0xea2e0106, 0xcd7c9c2c, 0xfe475bc3, 0x00423c02, 0xff010000, 0x0352fe63, 0x001e04f1, 0x40350019, + 0x04010e32, 0xf77e0d01, 0x4d1c2110, 0x1b24dc82, 0x0404004d, 0x23070557, 0x25241411, 0x220ac653, 0x4e112111, 0x332a0d3e, 0x21113311, 0xc0c03103, + 0x3b4e4efe, 0x71012009, 0x012c0692, 0x7032fece, 0x784da49a, 0x81931417, 0x2606bb54, 0xfee9ff03, 0x82c504d1, 0x001c2887, 0x00280024, 0x7e4a404d, + 0x1c2519ff, 0x0d0f104d, 0x0dfe7e03, 0x2305fc7e, 0x1d1e2324, 0x210efa7e, 0xfa7e0711, 0x023e2110, 0x260af97e, 0x0e072305, 0x82330702, 0x113208c1, + 0xacd2f303, 0x897830ab, 0x1c6cfe1a, 0x2721318a, 0x01190c1d, 0x329f609b, 0xfcfc9e96, 0x1d0c0e63, 0x00f22b2d, 0x360260ff, 0xe501cafd, 0xd1fe1bfe, + 0x03822f01, 0x6225c62a, 0x8401b6c6, 0xa70159fe, 0x922d0383, 0x68c7bedb, 0xfe4e012d, 0x000300b2, 0x20d38260, 0x08d38267, 0x1d001824, 0x49002300, + 0x151b4640, 0x0c070802, 0x02080901, 0x0008004c, 0x09080009, 0x01010367, 0x00540100, 0xfd5f0707, 0x0a0b2107, 0x2a0df37e, 0x231e231e, 0x11121f20, + 0x82111716, 0x0c102100, 0xee7ecf82, 0x363a080a, 0x35262637, 0x14153335, 0x13351716, 0x07230721, 0x11113307, 0x07060621, 0x9a7ee903, 0x1e79fd1f, + 0x5b3e4f9a, 0xb4858c1a, 0x021c3837, 0x0fe4bc4a, 0xf7fef603, 0x983f5518, 0xbe8439fe, 0x9b2bc73d, 0x98b3199f, 0x6159babd, 0x84010313, 0xfe29d994, + 0x8a5c0110, 0x0000339f, 0x82420001, 0x576f20bf, 0x11253347, 0x11230323, 0x0a475721, 0x9b9fd036, 0xbafea51f, 0x6a3c1216, 0x42395169, 0x02201030, + 0x38fe99b3, 0x220f4657, 0x1800ffff, 0x540c8f6e, 0x9228063f, 0x02006205, 0x00000400, 0x0fbb7b18, 0x01ffff27, 0x04000001, 0x231f8346, 0x00002401, + 0x0aa76918, 0x06000332, 0x05b53f00, 0x01000201, 0x27b04b4c, 0x11405850, 0x28301f82, 0x0201034d, 0x00600102, 0x01290101, 0x0e401b4e, 0x00240e82, + 0x64010201, 0x2d081b83, 0x40594e00, 0x0404040b, 0x11060406, 0x18080410, 0x0133012b, 0x01012521, 0x01fadb01, 0x038dfbbd, 0xfec4fe71, 0xfa6205c3, + 0x1b04a39e, 0x8b82e5fb, 0x7a18f020, 0x84200eff, 0x2a200f82, 0x8020ab84, 0x9d20ab84, 0x13200f82, 0x2b200f84, 0x03205f82, 0x0ab75118, 0x1f001b2f, + 0x2c402f00, 0x00050106, 0x04050304, 0x07c65467, 0xce602e20, 0x00293108, 0x1c1c1c4e, 0x141f1c1f, 0x22262524, 0x2b1b0807, 0x0fb05118, 0x23020230, + 0x10110222, 0x12323312, 0x21152711, 0x51180435, 0xce2b0cb2, 0x93a2a293, 0x93a29f96, 0x1878fe72, 0x3310ad51, 0x14011601, 0xe9feebfe, 0xedfeedfe, + 0x16011201, 0x0096965b, 0x12c75718, 0xbf82c320, 0xbf849c20, 0xbf823b20, 0x27000122, 0x88200f82, 0x06260f82, 0x04b53200, 0x59410101, 0x820c2008, + 0x4d28231d, 0x54410102, 0x820c2006, 0x01002209, 0x06524186, 0x1112b52c, 0x19080310, 0x0133012b, 0x02820123, 0x01fadb32, 0x9efed2b3, 0x05c99cfe, + 0x049efa62, 0x004cfbb4, 0x39207b83, 0x77205b82, 0x78186b84, 0x44200f7b, 0x03224882, 0x1f829100, 0x1f821f20, 0x07000326, 0x4e000b00, 0x2605d241, + 0x0002001d, 0x63020403, 0x8584069c, 0x07df5318, 0x4e052925, 0x881a401b, 0x0004261f, 0x63050405, 0x20b48200, 0x2526835f, 0x40594e01, 0x00831109, + 0x0806102d, 0x21132b1c, 0x21132107, 0x82032115, 0x03913803, 0x9efc1b7d, 0xfdae0267, 0x8e036752, 0x620572fc, 0xaf60feaf, 0x18b450fe, 0x210abfb3, + 0x58827b05, 0xe3414a20, 0x3701210d, 0xd6200f84, 0x6020a782, 0x5620c784, 0x01223082, 0x0f828c00, 0x0f822420, 0x4b000c32, 0x07080e40, 0x00040001, + 0x064c0103, 0x4b010001, 0x152ac385, 0x02030300, 0x0202005f, 0x30834d28, 0x9a425f20, 0x84122007, 0x6301213e, 0x032e1e88, 0x11b6594e, 0x04121114, + 0x012b1a08, 0xaa820115, 0x01013523, 0x08068235, 0xfe2e0320, 0xfcb40242, 0xfeef0168, 0xfd980311, 0x7cf2024b, 0xa1a12bfe, 0x10020f02, 0xff00a0a2, + 0x791800ff, 0x0f820c47, 0x0d4f5f18, 0x13000330, 0x9d040000, 0x11006205, 0x23001a00, 0x97855a00, 0x01041f37, 0x06010900, 0x69060007, 0x03070108, + 0x07020101, 0x05006901, 0x26a68205, 0x02290202, 0x95401b4e, 0x02022321, 0x26835f05, 0x594e0229, 0x22230e40, 0x82111611, 0x141134b4, 0x1f080a10, + 0x1216012b, 0x07021015, 0x26352315, 0x18341102, 0x0815fc78, 0xfbf3f845, 0xfbf0b4f0, 0xafb4f9f2, 0x3e40836a, 0x6baa6c83, 0x83413e84, 0x0bc40469, + 0xfffdfafe, 0x08f4fe00, 0x0108a2a2, 0xfc00010c, 0x9e0b0701, 0x4d02dafe, 0xa9878ea9, 0x56060655, 0xab8e86a9, 0x0000014c, 0x18ffff00, 0x2010fb78, + 0x20e3821a, 0x2ae38296, 0x40390018, 0x0a0d1609, 0x42030400, 0x0d2c08bf, 0x00020102, 0x004d2800, 0x03290303, 0x0d20d882, 0x00210882, 0x2e14855f, + 0xb6594e03, 0x14161515, 0x2b1a0804, 0x5a262601, 0x162005a7, 0x84055160, 0x0633080c, 0x01231107, 0xc1eeeff7, 0xba6b7f37, 0xefc1849b, 0x7d01c4ec, + 0x02cafd15, 0x63fefd09, 0x030b5187, 0x11bafc48, 0x0202959e, 0xfbc8f7fd, 0x0081fe17, 0x82550001, 0x055b2c8b, 0x0021007b, 0x051bb651, 0x44010002, + 0x183207a2, 0x05050106, 0x02006102, 0x034d2e02, 0x00010101, 0xce82045f, 0x82002921, 0x03152393, 0x0c820101, 0x63000122, 0x2c082389, 0x40594e05, + 0x0000000e, 0x11200021, 0x16112616, 0x2b1b0807, 0x14110600, 0x21151712, 0x02263335, 0x36123435, 0x12163233, 0x07021415, 0x08128233, 0x35123642, + 0x01232610, 0x7a7998bc, 0x81ee54fe, 0x9ee87d83, 0x857de89e, 0x56fef081, 0x9a9a7879, 0xfefeda04, 0xf3fee7e7, 0x439b913e, 0xd9d51001, 0xa5a53a01, + 0xd3d9c6fe, 0x9b47f2fe, 0x0e013d91, 0xff1801e7, 0x26080b5e, 0x00880592, 0x82040022, 0x0703247d, 0x8388fe20, 0xa5ff2117, 0x2220d782, 0x1b201784, + 0xfd211785, 0x201784de, 0x20178252, 0x20178413, 0x2017862b, 0x2417848b, 0x0300007a, 0x201784eb, 0x2017862e, 0x241784b3, 0x04e7ff98, 0x2017845b, + 0x2017864a, 0x211783d1, 0x4782eefe, 0x17848b20, 0x17867b20, 0x2f852720, 0x2f841782, 0x8b590221, 0xc500212f, 0x06205f83, 0x11abcc18, 0x2f822520, + 0x17848b20, 0x02234783, 0x82050f07, 0x01002236, 0x27ad8200, 0x6205d203, 0x42000700, 0x29050343, 0x03010414, 0x03010000, 0x9f436700, 0x06e04405, + 0x0121168a, 0x05bb4301, 0x594e0124, 0x45820c40, 0x0700072b, 0x05111111, 0x012b1908, 0x054a4b15, 0xfdd2032e, 0x03c6c6d2, 0x7efda325, 0xc3fd6205, + 0x0f724e82, 0x22678205, 0x854a000b, 0x051a2f67, 0x03020101, 0x80030102, 0x02020104, 0x48825f00, 0x20098d42, 0x231c8819, 0x84030300, 0x02202089, + 0x200fc344, 0x05e26811, 0x42297682, 0xfea72e04, 0xf3fec6f3, 0x287282a7, 0xfb7401e5, 0xfebb0445, 0x0eaf448b, 0x65822d20, 0x5500023d, 0x5b046bfe, + 0x12007b05, 0x4b001e00, 0x020306b6, 0x4c010300, 0x502db04b, 0x46164058, 0x04230995, 0x84030301, 0x002d2596, 0x13401b4e, 0x00240e82, 0x63000300, + 0x8b832088, 0x13130c29, 0x1d131e13, 0x83142828, 0x020023fe, 0x90820706, 0x85422620, 0x079b760a, 0x10113908, 0x5b043312, 0xc287bc5e, 0x755fbc88, + 0xe7a7a6e8, 0x929ffe75, 0x93a1a292, 0xf1019e96, 0x19bdd5fe, 0x84017bfe, 0x2b01b918, 0x4301d6c3, 0xbefeb0b4, 0x01d8fdd9, 0x01160112, 0x0af7c818, + 0x01000034, 0x51fe8b00, 0x62055804, 0x17002000, 0x01201440, 0xdf454901, 0x2e21260a, 0x2b180802, 0x05726f01, 0x022e272d, 0x24123435, 0x21072133, + 0x18150222, 0x08089292, 0x8502073e, 0x6e2f615f, 0x5cba9473, 0xe72b0189, 0xfe1d3201, 0x42e5e5ea, 0x927b8795, 0xfea7964a, 0x445a2bd1, 0x2f383a29, + 0xa7eba23c, 0xb12701b6, 0xe1fdfea6, 0x367ab18b, 0x4f705731, 0x004a9e6c, 0x01260082, 0x0000f000, 0x83823504, 0x51000f2d, 0x01060a40, 0x01070102, + 0x48020203, 0x18220672, 0xd4180100, 0x04240864, 0x0404005f, 0x2509d541, 0x02030018, 0x1f908603, 0x594e0030, 0x251111b7, 0x08051021, 0x21012b1b, + 0x72532111, 0x21210806, 0x21112311, 0x96fd2004, 0x5e472401, 0x4f283431, 0xc6ecfe3b, 0xb9044503, 0x18154afe, 0xfd0e0e90, 0x2083829e, 0x204e8200, + 0x208f8285, 0x240b822d, 0xb7430009, 0x227d8207, 0x46020201, 0x13200668, 0x0220af82, 0x68231182, 0x82030300, 0x06cb4287, 0x82001321, 0x8b8620b3, + 0x4e032a1a, 0x1112b659, 0x08041012, 0x0881821a, 0x23011721, 0x01272101, 0x02620133, 0x3ffe25a6, 0xfdc201de, 0xbf01255a, 0xa80b03de, 0x63029dfd, + 0x825702a8, 0x0100233b, 0x77822c00, 0x77828420, 0x41000b29, 0x070a0940, 0x42040306, 0x27260548, 0x0e405850, 0x72830104, 0x0201022a, 0x00290000, + 0x0e401b4e, 0x03210a84, 0x8217845f, 0x0c4029f2, 0x0b000000, 0x12130b00, 0x26053a43, 0x03032301, 0x82270127, 0x2722087a, 0x0e027602, 0xabadc8c3, + 0xfe4e0901, 0xde01c696, 0xfa620548, 0xfd2c029e, 0x050304d4, 0x041efcd9, 0x3a82aeb4, 0x00020027, 0x0454feb9, 0x347f827f, 0x00170003, 0x170f4067, + 0x01020214, 0x0004010c, 0x0403010b, 0x068e4103, 0x02001f24, 0x84820001, 0x01068028, 0x4d280101, 0x8e820105, 0x04004d2a, 0x00610304, 0x032d0303, + 0x21889882, 0x01211b83, 0x8a27855f, 0x40593221, 0x2412120a, 0x10111123, 0x2b1d0807, 0x33112321, 0x03591801, 0x01332810, 0xc6c67f01, 0x18857b02, + 0x2d08f64b, 0x0112fe42, 0x27fee3d7, 0x40fb6205, 0x5918f0fe, 0xe033088f, 0x8bfd8202, 0x00010000, 0x04000043, 0x007b05a8, 0x4e7b0013, 0x0c24056b, + 0x0306090c, 0x4c27aa82, 0x4a020113, 0x820c401b, 0x85032006, 0x4c022112, 0x2906df52, 0x00000011, 0x01036102, 0xcb410202, 0x054b4408, 0xaa441520, + 0x00002105, 0x2e21d584, 0x074f484d, 0x68821520, 0x8d860121, 0x4e00381c, 0x25b65959, 0x04211412, 0x012b1a08, 0x06222326, 0x23110107, 0x73330111, + 0x2f080691, 0x19208004, 0xfe1b3827, 0x59fec9e6, 0xcb3601db, 0x455f4c26, 0xd6043241, 0xfd3c3108, 0x02effda0, 0xfd53030f, 0x58d9015c, 0x00162a62, + 0x03ffffff, 0x8824c784, 0x6c022200, 0x03259d82, 0x3cfd3107, 0x85178200, 0xe50621df, 0x6f451786, 0x0b0f4b07, 0x1d001622, 0x2405ff5e, 0x02050400, + 0x0afe5e04, 0x084d2e27, 0x00050501, 0x294f8261, 0x174e0029, 0x00101017, 0x5c181700, 0x132108ca, 0x05ff5e12, 0x2b170827, 0x15121600, 0xd25c1814, + 0x1806200a, 0x230cce5c, 0x75e7ff02, 0x82056944, 0x942c0805, 0x66020b94, 0x9994940b, 0x98fd0794, 0x05969608, 0xbefeb07b, 0xbffed5d9, 0x4001afb3, + 0x4301d6d8, 0xe8e7a1b4, 0xaefbe6e9, 0xf6f7f8f5, 0xc72abf83, 0x5e040000, 0x02006205, 0x87825700, 0x75000134, 0x7604e7ff, 0x1c007b05, 0x31403400, + 0x03000102, 0x05820310, 0x0e87db18, 0x17672e20, 0x02292208, 0x2836824e, 0x251b001c, 0x08052426, 0x20aa8219, 0x87db1817, 0x0c3f4b51, 0x00010023, + 0x20a3823a, 0x20a3823b, 0x31a3831b, 0x03020118, 0x01020b17, 0x00010a02, 0x004c0301, 0x08550202, 0x41a38405, 0xa382075c, 0x1a001b25, 0x84262525, + 0x180420a3, 0x080e9c7c, 0x10353642, 0x07222302, 0x33363627, 0x0401ab02, 0xeefe9d8c, 0x48d18cad, 0x67934363, 0xc668b477, 0x5a9ba7bd, 0x0583c760, + 0xc0fea47b, 0xbdfee2e5, 0x7e4755a6, 0xf5703e36, 0x012601c0, 0x467e6602, 0x02000043, 0x370a3741, 0x40480028, 0x00010245, 0x05010303, 0x01011000, + 0x02011104, 0x074c0401, 0x04240d82, 0x69040501, 0x03258b82, 0x03010661, 0x0c454103, 0x001d1d2a, 0x1d281d00, 0x00212327, 0x20054d41, 0x1f4d4108, + 0x15161233, 0x22230614, 0x36343526, 0xbb500333, 0xa57a6b57, 0xe1dc1874, 0x4a462913, 0x4a3a3b4a, 0x7b053a4a, 0x0cdc6a18, 0xdc184720, 0xfd2908e9, + 0x383648bb, 0x36384a4a, 0x41c78248, 0x2720095b, 0x1828c783, 0x17030201, 0x0b020501, 0x0a22c782, 0xc78c0001, 0x9c630220, 0x0c694106, 0x001c1c2a, + 0x1c271c00, 0x00202226, 0x84057141, 0x1a7141c7, 0x7d41c68b, 0x8818201a, 0x178541c5, 0x5b4fc68a, 0x00843908, 0x00420222, 0x07070100, 0xff7ffe22, + 0xb109002e, 0xffb80102, 0x2b35b02e, 0x2207f767, 0x88850592, 0xfe242423, 0x862fff5e, 0x852f2023, 0xf6fe2723, 0x92040000, 0x23886b05, 0xc2fd2524, + 0x238322ff, 0xffb80223, 0x20238622, 0x22238ef0, 0x8fbafd26, 0x28ff2123, 0x2722238e, 0x2390f4fd, 0x23843420, 0x6b886c20, 0x00fe2822, 0xfe21238f, + 0x202384f3, 0x24238875, 0xfeeefd29, 0x218f85a1, 0x8f86a1fe, 0x77202385, 0x2a202388, 0xff212391, 0x4a4784ff, 0x2f2209e7, 0xff4a39fe, 0xfe312214, + 0x21178961, 0x5385ff06, 0x07020024, 0x0365fe16, 0x06922209, 0x201788c2, 0x2a588219, 0x00ffff00, 0x0482fe1f, 0x86620592, 0x07032417, 0x852e051e, + 0x20178447, 0x20178284, 0x8f408276, 0x82852017, 0x8b772017, 0xf6fe2117, 0x6b202f84, 0x78201782, 0xf020178c, 0x79201788, 0xff21178b, 0x20178828, + 0x20178c7a, 0x20178434, 0x4b47826c, 0x8f86055f, 0x84f3fe21, 0x82752017, 0x8c7c2017, 0x2017855f, 0x20178277, 0x25478c7d, 0x040000b3, 0xbf830522, + 0x57424620, 0xd5fd2705, 0x09002eff, 0x574201b1, 0x93ff2109, 0x2422238e, 0x238fb5fd, 0x8466fe21, 0x85d78323, 0xfd252447, 0x8322ff32, 0x0a574247, + 0x238e6820, 0x23922620, 0x238e8020, 0x4cfd2722, 0x8c204790, 0xfb832384, 0x28226b85, 0x238f58fd, 0x4c92ff21, 0x2f220edf, 0xf74cccfd, 0x4c312014, + 0x602006f7, 0x13262f82, 0x22008405, 0x07414802, 0x8f822006, 0x40ff21e3, 0x2422238e, 0x238f62fd, 0x8413fe21, 0x886b2023, 0xfc252247, 0x219b8fdf, + 0x238e15fe, 0x23922620, 0x238e2d20, 0xf9fc2722, 0x39204790, 0x6c202384, 0x28226b88, 0x238f05fd, 0x84e4fd21, 0x88752023, 0xfc292423, 0x41a1fedf, + 0x5f430597, 0xe3fd2107, 0x77202384, 0x2a222388, 0x238fdefc, 0x4e3fff21, 0x2f220e17, 0x2f4e79fd, 0xfd312114, 0x2506bb4c, 0x130482fe, 0x53856205, + 0x07030025, 0x8432051e, 0x8460202f, 0x82842017, 0x42932017, 0x17850687, 0x17884020, 0x178b9420, 0x8413fe21, 0x826b2017, 0x8c95202f, 0x88152017, + 0x8c962017, 0x882d2017, 0x8c972017, 0x84392017, 0x826c2017, 0x8b982047, 0xe4fd2117, 0x75201784, 0x99201782, 0xe320178c, 0x77201784, 0x9a201782, + 0x8825a78c, 0xeb030000, 0x20bf8305, 0x0627424a, 0x0342aa20, 0x90ff210f, 0x85202384, 0x23853b82, 0xb2fd2424, 0x53432fff, 0x07874506, 0x23849220, + 0x2385d783, 0x5efd2522, 0x210fbb41, 0x238e8bfe, 0x55fd2622, 0x55202390, 0x2722238e, 0x239021fd, 0x23846120, 0x6b85fb83, 0x2dfd2822, 0x0c202390, + 0x75202384, 0x2922b388, 0x034207fd, 0x0bfe210f, 0x77202384, 0x2a222388, 0x238f06fd, 0x508dff21, 0x2f220e27, 0x3f50c7fd, 0xfd312214, 0x4f1783b3, + 0xff2006f7, 0x87455385, 0x83c5200a, 0xc2062147, 0x87451788, 0xa6ff2706, 0x5b04e7ff, 0x17828405, 0x7f415020, 0x47c82006, 0xff210f07, 0x2023845e, + 0x22238885, 0x4780fd24, 0x11201007, 0x7b202384, 0x25222388, 0x9b46ddfc, 0x8e132010, 0x92262023, 0x8e4b2023, 0xfd272223, 0x20479017, 0x22238e56, + 0x8f22fd28, 0x33ff2123, 0x280e4751, 0x006dfd2f, 0xffffff00, 0x22178e70, 0x84a9fd31, 0x00792617, 0x05600400, 0x28bf8284, 0x01000052, 0xfd240707, + 0x1007419b, 0x23822420, 0x85058b22, 0x55202382, 0x46202386, 0x20108742, 0x20238402, 0x2223886b, 0x42ccfc26, 0xfd210f1b, 0x202384d7, 0x2223886c, + 0x90a3fc28, 0x847f2023, 0x88772023, 0xfc2a2223, 0x101b427a, 0x13521720, 0xfd2f220e, 0x142b5251, 0x27fd3122, 0x00201783, 0x2005fb51, 0x255385ff, + 0x16070200, 0x178a0004, 0x1788c220, 0x84051921, 0xa6ff2117, 0x1b425f82, 0x42592005, 0xcb460c1b, 0x845d200b, 0x82852023, 0x2223853b, 0x417ffd24, + 0x10201013, 0x7b202384, 0x25222388, 0xef8fdcfc, 0x8e12fe21, 0x92262023, 0x8e4c2023, 0xfd272223, 0x20479018, 0x22238e57, 0x9023fd28, 0x8e2a2023, + 0xfd292223, 0x0f5b4125, 0x8e29fe21, 0xfd2a2223, 0x21238f24, 0x7b5333ff, 0x0763420e, 0x178e7120, 0xaafd312d, 0xffff0000, 0x82fe5500, 0x41055b04, + 0x00250607, 0x051e0703, 0x21178334, 0x1784a6ff, 0x22008426, 0x0000c302, 0x5d20178a, 0x85201784, 0xc4201782, 0xfe21178b, 0x20478810, 0x20178cc5, + 0x20178812, 0x20178cc6, 0x2017884c, 0x20178cc7, 0x20178857, 0x20178cc8, 0x2017882a, 0x20178cc9, 0x20178829, 0x3e1789ca, 0x6d000200, 0x4904e6ff, + 0x17003704, 0x65002400, 0x0e200e40, 0x05020509, 0x4c010403, 0x1801010a, 0x2d0b5cab, 0x02056100, 0x2b000002, 0x0303004d, 0x9c4f6101, 0x001c2107, + 0x062a1283, 0x02040401, 0x02010561, 0x1e8b3102, 0x1340592c, 0x00001818, 0x23182418, 0x60821c1e, 0x2b162008, 0x18080713, 0x1716002b, 0x13033313, + 0x07171616, 0x27272626, 0x02222302, 0x36363411, 0x65060633, 0x790806c0, 0x0223022e, 0x361e9f87, 0x0a3572af, 0x5042292a, 0x60120f5f, 0x5ccab7e9, + 0x6e547fb3, 0x8c556567, 0x60491a2c, 0x95370442, 0xfd2b01af, 0x2ef6feda, 0x0c9d0e2f, 0xfe70565b, 0x011401d4, 0x8efea50b, 0xc8c8d297, 0x97e8b0c0, + 0x020046ad, 0x52feaa00, 0xde054c04, 0x2c001600, 0x3f404200, 0x03020116, 0x02050129, 0x05000108, 0x090a4c03, 0x00490002, 0x05020003, 0x00690203, + 0xd8840404, 0x064d2a22, 0x2d0cba4f, 0x2b172c17, 0x282c2124, 0x1b080724, 0x8870002b, 0x11272206, 0x30b48407, 0x15161632, 0x12070614, 0x34353636, + 0x37232326, 0x05a96f33, 0x11225008, 0x33161611, 0xcb794c04, 0x42954f78, 0x7eb964c0, 0xa26dbc72, 0x497d0a86, 0x1466a4af, 0x7b81675e, 0x8234dd67, + 0xfefd0254, 0x6bc4819a, 0x22fe3233, 0x82e9051c, 0xa35964bd, 0x15a7926c, 0x804058fd, 0x919f9a5a, 0x7372807f, 0xa0fcf4fe, 0x82002d2f, 0x01700800, + 0x55fe4d00, 0x37046304, 0x06001300, 0x010007b3, 0x17012b32, 0x14150601, 0x35260717, 0x02263734, 0x16372702, 0xa1031312, 0x3251fec2, 0x2a349a19, + 0x50a28a2e, 0x36b665c2, 0xfc2c3704, 0x5b7c731a, 0x84671670, 0x01c26e77, 0x50360183, 0x3cfe7d45, 0x0200edfe, 0xe7ff7f00, 0xdd053c04, 0x30002300, + 0x2f403200, 0x02000102, 0x03031c30, 0x4c020003, 0x02267382, 0x02010461, 0xd5412a02, 0x0000230b, 0x2d82282a, 0x252d2223, 0x05cc4105, 0x0d25d818, + 0x456c1420, 0x26372108, 0x36239682, 0x41023336, 0x590806d7, 0x26263435, 0xa2e40227, 0x743f6049, 0x2a615447, 0xb090605b, 0x91d97457, 0xaf73d993, + 0x61576b8f, 0x72bd71af, 0x8d838190, 0x05777e36, 0x703b3ddd, 0x3d462730, 0x2730392c, 0x95ca8b3b, 0x878beb8b, 0xf4aa8fe9, 0x5579373a, 0xfd438057, + 0xa995c766, 0x75b0b9be, 0x0032648f, 0x83680001, 0x29230807, 0x47404a00, 0x0304011d, 0x0405011e, 0x05000113, 0x00010108, 0x01020109, 0x05004c05, + 0x01000106, 0x53670005, 0x31200714, 0x350be650, 0x26280001, 0x191b2022, 0x05070b0d, 0x29012900, 0x2b160807, 0xb7852201, 0x076c4918, 0xc1183520, + 0x4e680a07, 0x3344080b, 0x80600207, 0xcb809072, 0xf65463a1, 0x78d38791, 0x726f8685, 0x6f79c471, 0x405d4fdb, 0x7e76539d, 0x17c26775, 0x544fdc01, + 0x7b6e6455, 0x944d4d3f, 0x127d7568, 0x5a587918, 0x3636417f, 0x4e252774, 0x9452454e, 0x2e05df41, 0x0442fed8, 0x00c60530, 0x403c0024, 0x79011f0b, + 0x002106b6, 0x05205349, 0x665b0b20, 0x002a2507, 0x10401b4e, 0x0022f782, 0x23825701, 0x005f0022, 0x4f270b82, 0x2324b659, 0x83022022, 0x000621b9, + 0x1628ba83, 0x15021e17, 0x27070614, 0x080b4b56, 0x0637004e, 0x21372123, 0xfeea3004, 0x7f3c8cee, 0x48847d76, 0x624da59e, 0x5c512660, 0x8c5cb39a, + 0x3fee2401, 0x17e3fef1, 0x4805d702, 0xf7edfec4, 0x4a725d7c, 0x5e3e2a28, 0x49af724b, 0x435d3283, 0x20232b23, 0x84a86e36, 0x0105018a, 0x991baa17, + 0x8c33b785, 0xf40355fe, 0x18003704, 0x14405100, 0x02000111, 0x82020c15, 0x124c2805, 0x044a0201, 0x86010203, 0x09fa53c0, 0xdd533120, 0x53112008, + 0x002005dd, 0x25061354, 0x594e0031, 0x55820b40, 0x17001831, 0x08042813, 0x16002b18, 0x11071115, 0x7a262634, 0x3508061e, 0x16372734, 0x36361716, + 0x93610333, 0x4a4818c0, 0xc0318d4d, 0x1c0fb333, 0x60ba4305, 0x96a23704, 0x04176dfb, 0x37746e34, 0x06fd4662, 0xb0a1cd02, 0x296a1a19, 0x51825a53, + 0x2707b772, 0x0f00dd05, 0x21001800, 0x7205b753, 0x2a2010b7, 0x3408346b, 0x194e0029, 0x00101019, 0x19211900, 0x101c1e21, 0x14171018, 0x18b75313, + 0x020e5108, 0x022e2107, 0x021e0123, 0x36363233, 0xcef00237, 0x94d06b69, 0x6b6ad095, 0x735995d1, 0x1402043c, 0x58713b04, 0x3d05f4fe, 0x70575771, + 0xdd05053c, 0xf0adfeb2, 0xbba6feec, 0xf05801b7, 0xb65501ec, 0xbdea6c9b, 0xfd6ceabd, 0x70efc15e, 0x00c1ef70, 0x3205af53, 0x001e041a, 0x40290011, + 0x02010926, 0x03010a00, 0x424c0202, 0x2b260707, 0x0202004d, 0xfd5b6103, 0x23242205, 0x06f95611, 0xc86d3720, 0x08b74205, 0xfed4013f, 0x0a0215a1, + 0x5a524f59, 0x48922932, 0x034f9262, 0xf2fc9c82, 0x89244348, 0x8d4a2217, 0x3c4e8260, 0xa2000200, 0x6804e7ff, 0x0b003704, 0x3f001400, 0x060b0d40, + 0x00040102, 0x074c0101, 0x077f4201, 0x01020c24, 0x73820101, 0x0b570020, 0x840c2005, 0x33138486, 0x40594e00, 0x0c0c0c0a, 0x1f140c14, 0x2b170803, + 0x01011701, 0x0806de45, 0x16030139, 0x11231115, 0x03272634, 0x52fea189, 0x5b3c1a01, 0x7b55423b, 0x3e89fe43, 0x1919c036, 0xfe653704, 0x3fd1fe68, + 0x0b9c0e3b, 0xa5014d50, 0xf998ea01, 0xab0273fd, 0x825eb362, 0xff5a26ff, 0x056704e6, 0x2c9182e1, 0x051c401f, 0x4a000204, 0x0d0e1113, 0x05677f04, + 0x4e002b22, 0x5b088182, 0x02140014, 0x012b1608, 0x3727022e, 0x1617021e, 0x07171212, 0x01030226, 0x22020127, 0x6c85501d, 0x7dcca41d, 0x7c6a3d29, + 0xa46dc34d, 0xbac2fe41, 0x1e047e01, 0x11487760, 0xd1731893, 0xa3fefdae, 0x465000ff, 0x01c6018d, 0x2a59fc53, 0xffff0e04, 0x55feaa00, 0x1e040704, + 0xe0040200, 0x01335e82, 0x00003a00, 0x37044f04, 0x2a000a00, 0x070809b7, 0x5a050304, 0xb62206fc, 0x09410101, 0x83b42005, 0x59762308, 0x2f820940, + 0x0a000a22, 0x21208e83, 0x08068b45, 0x01170120, 0xd64bce01, 0xae6abd73, 0xbf410140, 0x4d0166fe, 0x44673d02, 0xfe1ffe7b, 0x2b9403ca, 0x3f43f4fb, + 0xfebd2c05, 0x05560442, 0x003400dd, 0x82324035, 0x0203214d, 0x2d310482, 0x03010201, 0x021d1e4c, 0x01004902, 0x02010200, 0x542c8263, 0x2a2005fe, + 0x3424fa84, 0x24213300, 0x82059855, 0x079e71f3, 0x23073322, 0x4305676e, 0x362113fe, 0x07944536, 0xb1035808, 0x9b415ba5, 0x7d877c4d, 0xe516eb71, + 0x49478358, 0x877d9a96, 0x4da49f42, 0x491e6260, 0x80d7b74a, 0x704b9364, 0x7bcc7985, 0x7076dd05, 0x5f642b2a, 0x45a16662, 0x73654978, 0x4628314a, + 0xb0714c61, 0x642f8349, 0x222a2245, 0xb46f3d18, 0x53996d8f, 0x6b80280d, 0x76529967, 0x04250837, 0x00020037, 0x3cb382d5, 0xff0c0001, 0x046204e7, + 0x0016001e, 0x120f404a, 0x11040001, 0x00020205, 0x01064c02, 0x061a4402, 0x0103122d, 0x04000002, 0x0404005f, 0x5f004d2b, 0x122106a7, 0x20248200, + 0x31198a86, 0xb7594e00, 0x19111125, 0x1b080510, 0x1123012b, 0xf8831614, 0x11354208, 0x11231121, 0x27070606, 0x21333636, 0x2ba26204, 0x68774236, + 0x3ebf9dfe, 0x2d282f3d, 0x58036a67, 0x9bfd8403, 0x990e454c, 0x027f841d, 0x037cfc7d, 0x0f090184, 0x0010148f, 0x00020000, 0x0455feb3, 0x2cab8224, + 0x001b000e, 0x1238403b, 0x08030201, 0x30818201, 0x02090a4c, 0x01054900, 0x61010303, 0x01010104, 0x20968331, 0x06cf5700, 0x000f0f33, 0x0f1b0f00, + 0x0014161a, 0x250d000e, 0x2b170806, 0x06a27800, 0x0711272d, 0x33121011, 0x15150606, 0x48331616, 0x3808050d, 0x5dda4a03, 0x69ac85ba, 0x85d6ddc0, + 0x4776286e, 0x7c78827c, 0xe7fe3704, 0xfc99f2fe, 0x0dfe7894, 0x01c90317, 0x95120107, 0x3dffd4cf, 0xcec3cb41, 0x000100c4, 0x0451fec3, 0x30978227, + 0x40250025, 0x00010222, 0x164c0101, 0x00030315, 0x22b58249, 0x83026101, 0x4e002191, 0x25240b82, 0x03252400, 0x16207f83, 0x410a6370, 0x430815fb, + 0xa62c0333, 0x74415d55, 0x528c5651, 0x72838033, 0xa6994883, 0x26626051, 0xa6866d5c, 0x92e58157, 0x3e353704, 0x56262c7c, 0x726479aa, 0x482a3050, + 0xa06f4c65, 0x55278448, 0x2a302842, 0xb5773128, 0x81f1a487, 0x02277182, 0xe7ff8900, 0x82046404, 0x1e0037f2, 0xb04b4f00, 0x40585022, 0x00010317, + 0x005f0200, 0x4d2b0202, 0x49490105, 0x01292d06, 0x1d401b4e, 0x00020300, 0x00720300, 0x60201f82, 0x59221f90, 0x7e5d0d40, 0x36152905, 0x08061026, + 0x27012b1a, 0x270e1078, 0x36001732, 0x26271035, 0x08051e4a, 0xef640439, 0xcf6c5f50, 0x6dd09291, 0xe7a0e577, 0x8074fef8, 0x5ca47c88, 0x87038183, + 0x8fc73311, 0x8786f9a9, 0xf4a3a8f8, 0x60fc0b86, 0x1d01cbc5, 0xaf420170, 0x00c4ca9f, 0x82480001, 0x040133b3, 0x0019001e, 0x0d29402c, 0x19020101, + 0x0104020c, 0x6e184c02, 0x2b200855, 0x280bf845, 0x24251123, 0x1b080522, 0x6fbd182b, 0x22232108, 0x20066042, 0x065e4515, 0x01042b08, 0x62489229, + 0x485a4f91, 0x3f1f4a69, 0x8b025c91, 0x4e587dfe, 0x17205a53, 0x608d4a22, 0x140e6602, 0x9a131693, 0x43488cfd, 0x7f820024, 0x7f82c220, 0x7f822320, + 0x21001729, 0x03041e40, 0x82010102, 0x02022170, 0x30075142, 0x17000000, 0x14231700, 0x19080526, 0x1216012b, 0x07474915, 0x33114e08, 0x33161411, + 0x35363632, 0xee030334, 0xdd871b1a, 0x60ab7082, 0x4b5f65c0, 0x04345080, 0x00ff8e1e, 0x74f1b292, 0x02739f4f, 0x6c3afdd6, 0x92b14b6c, 0x001301fd, + 0xfe3e0002, 0x04720455, 0x00180037, 0x40490025, 0x07141d09, 0x06040506, 0x06d24b02, 0xfa820e20, 0x032b7b82, 0x00000201, 0x1b4e022b, 0x82001240, + 0x834d2008, 0x61013315, 0x01010103, 0x594e0231, 0x19191040, 0x25190000, 0x45822419, 0x051c1722, 0x0805e542, 0x11051069, 0x11241107, 0x33371234, + 0x14150206, 0x11171616, 0x0e333634, 0x3e111502, 0x26343502, 0xd1032326, 0xad2dfea1, 0x323c4cfe, 0x2d3538b7, 0xa48e616e, 0x680e383f, 0x401b357a, + 0xfe370439, 0xfdeefef3, 0x7ffe2bff, 0x26970116, 0x01a6cc01, 0xffa78416, 0xa47d6f00, 0x06020e60, 0x538fdeda, 0x15fe7281, 0x86ad610d, 0x8251ad92, + 0x01540892, 0x53fe6000, 0x35045304, 0x06001000, 0x01020bb3, 0x01012b32, 0x27010107, 0x27022e01, 0x17121637, 0xd3021701, 0xfebd8001, 0xbec8fecd, + 0x7d4f8701, 0x61bc5078, 0x0d015297, 0xfd7201bd, 0x94022b0c, 0x022270fd, 0x9ce6b3f2, 0xfe674451, 0x4d02ddf6, 0x01000021, 0x08135018, 0x1a001c3d, + 0x0f1a1740, 0x000c0d0e, 0x02490006, 0x00000201, 0x164e002b, 0x0803161d, 0x83252b19, 0x330324ce, 0x84151216, 0x022e25f1, 0x11331135, 0x3708ee84, + 0x6eb00233, 0xb9342a74, 0x3bfe1a1a, 0x5bc397ac, 0x5e6f31b7, 0x5b0e87ac, 0x01e67f9d, 0xfefe8c2c, 0x2c21fe94, 0x01177bfe, 0xad700c9c, 0xfd99026b, + 0x406d5374, 0x0097030b, 0x20080082, 0xff310001, 0x047f04e7, 0x0027001e, 0x1d2a402d, 0x0303081c, 0x064c0102, 0x02020205, 0x01044d2b, 0x06ac7703, + 0x4e002922, 0x273a2d82, 0x25272700, 0x07242415, 0x012b1b08, 0x02141112, 0x27262223, 0x22230606, 0x7e413502, 0x32332508, 0x37353536, 0x08052342, + 0x0234354c, 0x66190427, 0x7e68969c, 0x617d1911, 0x2c389797, 0x3f2130a5, 0xac3d4d50, 0x3e504f3c, 0x1e043126, 0xdefee2fe, 0x73f8feef, 0x01757072, + 0x01a8f601, 0xfe9c7622, 0xb4ad9dfc, 0x19f69bb3, 0xa8a7f2fe, 0x0197adb4, 0xffff9f07, 0xa7827500, 0x5c061a26, 0xde022200, 0x02238982, 0x82281f07, + 0x21178706, 0x1788f405, 0x8ae30021, 0x30072117, 0x21201788, 0xc2201786, 0x23204782, 0xea204784, 0x45204785, 0x17842f85, 0x17854784, 0x00241582, + 0x00ffff00, 0x47841784, 0x21201785, 0x17821883, 0x47828920, 0x47832720, 0x8cd50021, 0x82312047, 0x847f2017, 0x8cee205f, 0xff6d2417, 0x844904e6, + 0x85d62017, 0x82172017, 0x20478206, 0x202f82a0, 0x2017844d, 0x201785da, 0x24178565, 0x0355fe8c, 0x201784f4, 0x201785dc, 0x05af4146, 0x0000d42f, + 0x37041904, 0x45000d00, 0x020809b4, 0x06f96202, 0x01030f29, 0x01000002, 0x4f670002, 0x1724070a, 0x01000100, 0x2105ad46, 0x1d825702, 0x5f000236, + 0x00020000, 0x0b40594f, 0x0d000000, 0x11110d00, 0x2b180804, 0x08055e63, 0x27263420, 0x15161637, 0xfd190415, 0x181bc0ae, 0x022420af, 0x33fea26f, + 0x9b68cd02, 0xb542194e, 0x32823899, 0x23000128, 0x700455fe, 0x3c821e04, 0x2440272c, 0x0200010a, 0x04094c01, 0xff480303, 0x5f022105, 0x05496483, + 0x000d2305, 0x5d86230c, 0x07110524, 0xab440511, 0x04240806, 0xc048fe70, 0x473a00ff, 0x58312133, 0x9b1e044f, 0x17eafa01, 0x08012d05, 0x0c12950e, + 0xb5000100, 0x3f04e7ff, 0x14285f82, 0x0c403900, 0x03040b12, 0x4c21cb82, 0x25f04905, 0x1114b529, 0x1908031c, 0x4914012b, 0x360805e9, 0x37123435, + 0x33112301, 0x01071411, 0x12e40333, 0x76402326, 0xfe111968, 0x1abde04a, 0x01d9b301, 0x263e341f, 0x941f9010, 0x3d015186, 0x04b5fc9d, 0xd22dfe1e, + 0x844b03a6, 0x82ad20e7, 0x04023787, 0x001b0037, 0x10314034, 0x0f020101, 0x01000203, 0x00030102, 0x92824c03, 0x00610226, 0x4d310202, 0x2208fe48, + 0x824e0329, 0x001b260b, 0x2524251a, 0x23828205, 0x37272604, 0x18086b47, 0x080cd24f, 0x01230633, 0x574da9a3, 0x904b6d47, 0x528e8fa1, 0x595b437a, + 0xdc9a6ba7, 0x99e37b74, 0x7b3b3b19, 0xc5bc252a, 0x2925c3cd, 0x89353e78, 0xf5a8abfd, 0x00020082, 0x208b82b0, 0x278b8211, 0x00250019, 0x0f454048, + 0x102b8682, 0x01020501, 0x02040301, 0x5d030001, 0x033206eb, 0x00690405, 0x61010202, 0x31010100, 0x0301064d, 0x1a480003, 0x1a1a2206, 0x2b988200, + 0x1e20241a, 0x18001900, 0x08242623, 0x2420a182, 0x22088c4b, 0x18363634, 0x24073154, 0x16141506, 0x0ce85d33, 0xd8183220, 0x522f1429, 0x3a3b494a, + 0x893a4949, 0x463b7d5c, 0x18a5f787, 0x2e0aea4a, 0x36480c02, 0x374a4a37, 0x00004836, 0x41000200, 0x27200947, 0x102fbb83, 0x0f020101, 0x03010501, + 0x02040001, 0x86000301, 0x830020bb, 0x411a82bb, 0xc0830a55, 0x4e032923, 0x0ddf5d1c, 0x83252421, 0x1b5d41bb, 0x6941bd8b, 0x861b2018, 0x147141bf, + 0x88ae0221, 0x022208c1, 0x55fe8900, 0x37042704, 0x1d001100, 0x23402600, 0x03040506, 0x03490204, 0x02010201, 0x01010086, 0xe5826100, 0x01312408, + 0x1212124e, 0x281c121d, 0x1808042c, 0x0606002b, 0x11071107, 0x34350226, 0x32333636, 0x00151616, 0x4b343536, 0x3408070c, 0xa5542704, 0xbdb2c076, + 0x9594d16c, 0xb4fe69cf, 0x83818181, 0x01838183, 0x1693e67e, 0x01177dfe, 0x1e011f9a, 0x8bf9a5e2, 0xfea9f787, 0xcacbc570, 0xcaccc4c4, 0x356482c4, + 0x87000100, 0xf00351fe, 0x27008504, 0x27b30600, 0x2b320113, 0x6a821401, 0x85650e20, 0x07584f0b, 0x832e2721, 0x374b087d, 0x0335023e, 0x789357f0, + 0x3c458074, 0x86718c8c, 0x4fa7984d, 0x522f5d63, 0xae812757, 0x8cb9c66a, 0x76043273, 0x1d44816d, 0x606d3a1c, 0x2d4c6f5f, 0x4e664324, 0x80499d6b, + 0x2a3d552c, 0x0c1b2133, 0x8db46528, 0x252ec9b3, 0x8244452b, 0xfef0367f, 0x04210453, 0x0015001e, 0x082e4031, 0x01010201, 0x090e0f4c, 0x080c4c03, + 0x00010438, 0x005f0300, 0x002b0303, 0x1400014e, 0x060b0d12, 0x01150004, 0xba500515, 0x0a816506, 0x11072e08, 0x21333634, 0x57560207, 0x484e014f, + 0x28302d5d, 0xc2fe3b4f, 0x01abb0c0, 0x840318d6, 0xfafe5951, 0x0e861815, 0x1b31fd0e, 0xa9a67c04, 0x26ff859a, 0x04e7ffa5, 0x82e3050b, 0xb306237f, + 0xff830510, 0x4b031721, 0x37280563, 0x13270513, 0x17373636, 0x03340e82, 0xc937d403, 0xa90d404b, 0x9a4e460b, 0xc0349ffd, 0xaa0c3f4c, 0x91320b82, + 0xfe96ae03, 0x55b0986c, 0x8bc46a22, 0x98b01a01, 0x0c848201, 0xfe8cc323, 0x375f85f8, 0x0457fe38, 0x00e1050e, 0x402b0016, 0x1114160d, 0x00050c0f, + 0x0207084a, 0x4d066d4e, 0xb4390f5d, 0x08021d14, 0x04132b18, 0x14111200, 0x12270702, 0x03273411, 0x27260123, 0x08048201, 0x01be2539, 0xba750121, + 0x3ea6232f, 0x01a3c916, 0xfe3d2430, 0xfb01ba51, 0x05e8fe9f, 0x97fe8be1, 0xbdfe19fe, 0x80acfe98, 0x011c0117, 0xfe819d39, 0x64c3021f, 0x047afc5f, + 0x859cae16, 0xfe76298b, 0x043a0454, 0x00270037, 0x30056745, 0x274c0101, 0x1e1f2526, 0x11171819, 0x010b040b, 0x077c424a, 0x4e002d24, 0x87832724, + 0x16140125, 0x18151716, 0x300b7940, 0x34352626, 0x27013712, 0x26263411, 0x16163727, 0x36a58215, 0xde031701, 0xa5232712, 0x4a65858e, 0x802d3e2a, + 0x0c262e32, 0x82c549fe, 0x40600812, 0x0c266876, 0x01c5b701, 0x2641361f, 0xa399e210, 0x1517784d, 0x7123b293, 0x85014e59, 0x3da9fc54, 0x3f33d402, + 0x1e8f1026, 0xfe4d8595, 0x5703577d, 0x0300003c, 0xe7ff9500, 0xdd051b04, 0x23001700, 0x47003200, 0x151b4440, 0x2e020402, 0x02040501, 0x0201064c, + 0x02050400, 0x01076904, 0x61010303, 0x2a20b182, 0x2f0c8264, 0x18182424, 0x32240000, 0x292b3124, 0x22182318, 0x16234482, 0x51092525, 0x14220561, + 0x936f0606, 0x05424305, 0x072f0e82, 0x06023336, 0x3e370706, 0x26343502, 0x43361223, 0x60080654, 0x021e0707, 0xaf6c0333, 0xee8bcd6b, 0x8af395d5, + 0x593c8467, 0x25355f9a, 0x0c5d8484, 0x4c9d813d, 0x7009363b, 0x367a5e3b, 0x023a4363, 0x03556935, 0x7cd8d069, 0x6d0184da, 0x00015e01, 0x4bbc6f01, + 0x97574477, 0x010d1e6f, 0xb1ed71e3, 0x856e3519, 0xfb3c3c56, 0x5d8d4f34, 0x211ca39f, 0x67efcc1c, 0x22008200, 0x82940002, 0x823620e7, 0x002128e7, + 0x4043002c, 0x82020040, 0x030236fb, 0x09080a80, 0x01040603, 0x00060200, 0x07070067, 0x05006105, 0x0c9a5405, 0x0022223f, 0x222c2200, 0x0024262b, + 0x26210021, 0x23142333, 0x1c080b11, 0x2315012b, 0x23021015, 0x07066d22, 0x36323325, 0x84353512, 0x3634210f, 0x1221f282, 0x0a9e7d13, 0x36044808, + 0x5df1e948, 0x54bf5e9d, 0x3a71564d, 0x62c48dd6, 0xd36aac62, 0x11cf1aed, 0x57387284, 0x0371842f, 0xfe0596bf, 0x515ffe64, 0x720170a0, 0x6b6b9cfe, + 0xf52a0185, 0x649b5704, 0xfe5ea160, 0x0100ffe2, 0x5832c0c6, 0x82606438, 0x2ab782ca, 0x0455fe51, 0x00d9055f, 0x821b0015, 0x43220894, 0x1c211340, + 0x00041819, 0x104c0102, 0x4a02020f, 0x00020405, 0x1cb04b49, 0x0d405850, 0x02020103, 0x56504d2b, 0x0d402107, 0x2a670983, 0x002b2b05, 0x13b6594e, + 0x04121316, 0xf2441a08, 0x022e2207, 0x08bc8235, 0x37113757, 0x15021e11, 0x11171604, 0x36011106, 0x27263411, 0xc16d5f04, 0xc084b87d, 0x7cc26d67, + 0x66c085b8, 0x7979b2fc, 0xf39b01f2, 0x7301777c, 0xfe077ee7, 0xb2011765, 0x98e38309, 0x067de79f, 0xfe15ad01, 0xe283093e, 0x0ac1b397, 0xfe16fa02, + 0x1b85fe96, 0xc1ae6401, 0x08bc820a, 0x0900022a, 0x9b04e7ff, 0x19001e04, 0x3d002e00, 0x01163a40, 0x26270400, 0x06040a15, 0x054c0200, 0x00000203, + 0x01085f04, 0x4d2b0404, 0x2e057e7b, 0x01010102, 0x004e0129, 0x242a2c00, 0x821c1d22, 0x14182536, 0x09112424, 0x0124b382, 0x15162315, 0x200cbf4a, + 0x054c4437, 0x26003324, 0xda4d0527, 0x325e0805, 0x15373511, 0x32331614, 0x9b043536, 0x909a587e, 0x19117a61, 0x94915979, 0x27312054, 0x91823422, + 0x1b156e02, 0x1219a3fd, 0xab81493c, 0x3c4b4838, 0xc78e1e04, 0xf8feeeec, 0x766f7273, 0xecf50101, 0x0b0901c4, 0xfe0c1288, 0x016fcb37, 0xac7bc66c, + 0xce4e01b5, 0xa9a6e619, 0x0100acb5, 0xcb827600, 0x37043a2b, 0x06001b00, 0x010513b3, 0x0db84832, 0x2613b643, 0x26687640, 0x434afe0b, 0x0b2307ae, + 0x48c5b601, 0x852408c5, 0x5188014e, 0x2e0ea643, 0x57035379, 0x0000003d, 0xfeb30002, 0x8224044f, 0x001e356b, 0x4031002b, 0x0201222e, 0x01011903, + 0x034c0202, 0x49010202, 0x01242082, 0x04650102, 0x3e073448, 0x1f4e0331, 0x1f2b1f1f, 0x2e262c2a, 0x2b190805, 0x07171604, 0x2e27022e, 0x10113502, + 0x4f323312, 0x2726070e, 0x16161415, 0x57500217, 0x0f49080c, 0x0eb11886, 0x78615929, 0xd5dc4b95, 0x6066ca90, 0x61b282bc, 0xa275702d, 0x47762770, + 0x747a857a, 0x404652d9, 0x0f161f1e, 0x76935013, 0x09010102, 0xe17b1001, 0x94f58d99, 0x52509a88, 0x6704122b, 0x47a8d4ce, 0xadb3ca4c, 0x20b782b3, + 0x0afb4801, 0x31403423, 0x20a4820f, 0x82b98210, 0x030023b2, 0xed484c03, 0x4cb88809, 0xe54805a4, 0x48b88305, 0x032019e5, 0x4815d948, 0x002712d1, + 0x00ffff00, 0x1855feb7, 0x490ca764, 0x02220793, 0x1f84da01, 0x55febf2a, 0xdd052704, 0xe2000200, 0x2220b784, 0x642c0f82, 0x10001e04, 0x09404700, + 0x03080a0d, 0x220a2371, 0x82030014, 0x02032627, 0x00010180, 0x095b5200, 0xd7821688, 0x845f0021, 0x4e022e1b, 0x1114b659, 0x08041112, 0x13132b1a, + 0x08028333, 0x2603232f, 0x03230335, 0x22030714, 0xcbb5f481, 0x25b856f7, 0xc6b4d90b, 0x55fe470c, 0x0afdc905, 0xe2fbf602, 0xeea6e501, 0xfe02fcfc, + 0x84fc9eee, 0x20698200, 0x088b8254, 0x37046123, 0x23001600, 0x40404300, 0x07060117, 0x06050101, 0x06074c02, 0x03490102, 0x01020001, 0x63010001, + 0x06677d00, 0x004d3133, 0x61050606, 0x05050108, 0x004e0529, 0x1b1f2100, 0x2d3b8219, 0x13112315, 0x08091211, 0x27042b1b, 0x01822115, 0x23350729, + 0x10113335, 0x52323312, 0x01200567, 0x340af04a, 0x69190215, 0xc6fe3a01, 0xdd9c9cc0, 0x5ddae4d6, 0xebfe85ba, 0x05655228, 0x196e8130, 0x878ede78, + 0x028e9e17, 0x0107019d, 0x7352fe12, 0x19012105, 0x25056752, 0x0000d4cf, 0x035cffff, 0x56062405, 0x4d022200, 0x2222052b, 0x17940012, 0x8b872421, + 0x88492017, 0xc925212f, 0x26211795, 0x211795a0, 0x178b2127, 0x47884a20, 0x8bf02821, 0x88d42017, 0xf3292117, 0xd620178b, 0x2a211788, 0x20178bda, + 0x21178835, 0x178bd202, 0x17884620, 0x178c0320, 0x17880e20, 0x178c3220, 0x17881c20, 0x178b0720, 0x88d10521, 0x870a2017, 0x82fe2517, 0x37044904, + 0x03241786, 0x2f051e07, 0x83053741, 0x87062017, 0x07222277, 0x862f822e, 0x201f941d, 0x411f9430, 0x2225078f, 0x00122207, 0x893f9100, 0x8724211f, + 0x9f411f93, 0x07222307, 0x1f9dc925, 0x9da02621, 0x2127211f, 0xb7411f93, 0x07222307, 0x1f93f028, 0x2307bf41, 0xf3290722, 0xc7411f93, 0x07222307, + 0x1f93da2a, 0x25079f41, 0x041d0723, 0x21880082, 0x8308c34f, 0x243882ff, 0x22070200, 0x0bdb4f60, 0x24211789, 0x23178bd5, 0x02220049, 0x25202f85, + 0x890c0b50, 0xee262117, 0x27212f95, 0x83178b6f, 0x214785f7, 0x178b3e28, 0x5f883520, 0x8b200221, 0x88462017, 0x86032017, 0x056b5017, 0xdc20a783, + 0xbf822882, 0x2f854120, 0x2421178f, 0x83178bb6, 0x212f85a7, 0x1795f825, 0x95cf2621, 0x50272117, 0xbf83178b, 0x28214785, 0x20178b1f, 0x85a782d4, + 0x22292117, 0xd620178b, 0x2a211788, 0x83178b09, 0x212f85ef, 0x178b0102, 0x1785ef83, 0x178c0320, 0x47880e20, 0x178b3220, 0x86370421, 0x07032917, + 0x00eb031e, 0x00ffff00, 0x87050741, 0x07222247, 0x862f822e, 0x201f941d, 0x411f9430, 0x2225075f, 0x00412207, 0x893f9100, 0xb624211f, 0x6f411f93, + 0x07222307, 0x1f9df825, 0x9dcf2621, 0x5027211f, 0x87411f93, 0x07222307, 0x1f931f28, 0x23078f41, 0x22290722, 0x97411f93, 0x07222307, 0x1f93092a, + 0x25076f41, 0x041d0723, 0x218800b1, 0x8308db53, 0x42de20ff, 0x2320057f, 0x17920682, 0x8b982421, 0x53492017, 0x252108db, 0x201795da, 0x88668326, + 0x212f8947, 0x2f8b3227, 0x7785f783, 0x07422820, 0x056b5406, 0x5f88d420, 0x8b042921, 0x88d6202f, 0xeb2a2117, 0x3520178b, 0x02201788, 0x210b8354, + 0x17884606, 0x178c0320, 0x17880e20, 0x178c3220, 0x17881c20, 0x178b0720, 0x88d10521, 0x830a2017, 0x04002117, 0x08051355, 0x00010728, 0x000f0003, + 0x002d001b, 0x03134081, 0x25010001, 0x26040601, 0x03060701, 0x0201024c, 0xb04b4a01, 0x40585029, 0xdc820223, 0x61012108, 0x03080309, 0x4d2a0101, + 0x05040400, 0x0505005f, 0x06004d2b, 0x00610706, 0x07290707, 0x21401b4e, 0x2a821f84, 0x00010523, 0x08239469, 0x1a405922, 0x04041010, 0x2224282a, + 0x1c1d1e1f, 0x1a101b10, 0x0f041416, 0x0a280e04, 0x012b1708, 0x26071337, 0x180a2b70, 0x280b24db, 0x21372101, 0x33161411, 0x087c5232, 0x73290137, + 0x44a34fee, 0x45323243, 0xd9013245, 0x31334444, 0xfe314444, 0x0f1f5ec7, 0x70910628, 0x3348dbfe, 0x1e833144, 0x32210383, 0x210b8343, 0x365ebbfd, + 0x940f410c, 0x05171322, 0x2c2a0f41, 0xfe73eef0, 0x4444a7ee, 0x44443331, 0x1a104133, 0x01dc052c, 0x33fd7025, 0x44313144, 0x10413243, 0x00002118, + 0x2107fb42, 0x3b420407, 0x06273e06, 0xff9b04ed, 0x060701c3, 0x009704f6, 0xb11100f6, 0xffb80201, 0x2b35b0c3, 0xb00103b1, 0x05d36ff6, 0xdb560020, + 0x82562005, 0x43e42033, 0x4020058f, 0xf3560682, 0x21178908, 0x178bb524, 0x2f884920, 0x95f72521, 0xce262117, 0x27211795, 0x20178b4f, 0x2147884a, + 0x178b1e28, 0x17883520, 0x8b000221, 0x88462017, 0x86032017, 0xfeb32517, 0x06240455, 0xe620a783, 0x4e20bf85, 0x178f2f85, 0x57c32421, 0x2f840afb, + 0x2005e357, 0x24ef8622, 0x04e7ffc2, 0x87178a23, 0x831785ef, 0x872f85ef, 0x87178fef, 0x87178fef, 0x831785ef, 0x874785ef, 0x201785ef, 0x85d782d4, + 0x4a292017, 0x1785069f, 0x1788d620, 0x8b082a21, 0x883520bf, 0x071f4117, 0x46202f85, 0x1f411788, 0x20178507, 0x2117880e, 0x478b0032, 0x17881c20, + 0x178b0720, 0x88d10521, 0x830a2017, 0x04002117, 0x44061b59, 0x3329077f, 0x0b407700, 0x01000103, 0x0b774401, 0x77442020, 0x070a220d, 0x06744402, + 0x0061042a, 0x04290404, 0x1e401b4e, 0x910b7444, 0x40593220, 0x101c1c1e, 0x1c040410, 0x2e331c33, 0x2428292c, 0x0a754422, 0x75440b20, 0x5c13201e, + 0x012116bb, 0x137b4446, 0xd05cc420, 0x1679440e, 0x5c57fe21, 0x134116e7, 0x1a79448a, 0x21171341, 0x7f440d02, 0x0f144114, 0x41167d44, 0x00201814, + 0x2009475b, 0x06434204, 0xed062724, 0x8744b804, 0x44b42006, 0x4b5b1887, 0x82562005, 0x44ee2033, 0x178f0c87, 0x85079743, 0x88492017, 0x0797432f, + 0x9743178f, 0x43178f07, 0x17850797, 0x47884a20, 0x85079743, 0x88d42017, 0x07974317, 0xd6201785, 0x97431788, 0x20178507, 0x21178835, 0x00820002, + 0x5dffff21, 0x06210573, 0x43178846, 0x2f850797, 0x17880e20, 0x26079743, 0x0482fe31, 0x861e047f, 0x07032717, 0x0030051e, 0x4782ff00, 0x47881783, + 0x7f072221, 0x1d8405fd, 0x35821f94, 0x3d860020, 0x5f411f8a, 0x07222407, 0x9c004022, 0xb524211f, 0x6f411f93, 0x07222307, 0x1f9df725, 0x9dce2621, + 0x4f27211f, 0x87411f93, 0x07222307, 0x1f931e28, 0x22078f41, 0x4e290722, 0xe7830617, 0x41091f41, 0x22230797, 0x93082a07, 0x076f413f, 0x1d072325, + 0x8800b004, 0xffff2d21, 0x82fe8401, 0xb2ff2e03, 0x1e070300, 0x53821984, 0x00291391, 0x003c0002, 0x05740442, 0x08098220, 0x08000520, 0x010405b5, + 0x2b320200, 0x21011137, 0x043c1101, 0xfdc5fe38, 0xde0442a0, 0x5e0193fd, 0x5f8242fd, 0x04232f8f, 0x82010203, 0x0113252f, 0x01110311, 0x9d322f82, + 0xb302a0fd, 0x22fb6d02, 0xbe021101, 0x0500a2fe, 0x137e6a00, 0x0f2f0806, 0x1c001300, 0x29002000, 0x43404600, 0x0306010f, 0x01044c01, 0x06010903, + 0x69060307, 0x0202050a, 0x005f0102, 0x4d380101, 0x0702080b, 0x825f0007, 0x3929086c, 0x21224e00, 0x26281414, 0x29222921, 0x1d1e1f20, 0x1b141c14, + 0x21161122, 0x1b090c25, 0x1516002b, 0x23060614, 0x32211121, 0x24098204, 0x11230107, 0xab741833, 0x82032008, 0x6421200c, 0x48080530, 0xdc031123, + 0x86e28fa8, 0x0502ddfd, 0x850d01cc, 0x7435fe65, 0x7a56b574, 0xfc7e867b, 0x11017474, 0x8399a97c, 0x9cc50265, 0x4bb18f9e, 0xbba16205, 0x0117997c, + 0x0156feee, 0x6a56feaa, 0xfd636c71, 0x651dfeba, 0xfe708a84, 0x7a91821d, 0x28080abf, 0x001e0019, 0x0e2e4031, 0x1e010201, 0x1314191a, 0x0203060f, + 0x01004c02, 0x01030200, 0x03006902, 0x59030000, 0x00030300, 0x28088261, 0x24235100, 0x06042226, 0x0502631a, 0x02243808, 0x24123435, 0x17163233, + 0x22232607, 0x33161107, 0x01373632, 0x17101106, 0xd1487604, 0xeefead8c, 0x1101a09d, 0x57bb84a6, 0x33a57a6b, 0x67302d2c, 0xb0fd4294, 0x7a838080, + 0x4331098a, 0x0a667e46, 0x3e09c6fb, 0x8d650337, 0xd8fed8fe, 0x0866838d, 0x00002f2a, 0x62058104, 0x0f000b00, 0x3f001300, 0x01043c40, 0x07010900, + 0x67070005, 0x0005010a, 0x02050602, 0x06010867, 0x57060101, 0x06230682, 0x82035f01, 0x4f012b0a, 0x12130000, 0x0e0f1011, 0x39820c0d, 0x83110b21, + 0x060b2600, 0x11012b1b, 0x23018821, 0x23113301, 0x02290383, 0xfea701da, 0xfefcfe59, 0x08078259, 0x6e6ef620, 0x6e6eaa02, 0x3d022503, 0x83029efa, + 0x62057dfd, 0x77fdc3fd, 0xd6fb2a04, 0x00002a04, 0x48180002, 0x8f8307fb, 0x2a402d34, 0x04020208, 0x034c0105, 0x05000201, 0x67050204, 0xaf820400, + 0x04005727, 0x015f0004, 0x080c8201, 0x11114f40, 0x10131113, 0x2b1c0606, 0x13012121, 0x21112311, 0x33110301, 0x23013301, 0x53fe1304, 0xb41dcefe, + 0x44019c01, 0xd1feb41e, 0x7f57fe86, 0x2dfe0a03, 0x6205c9fe, 0xdb01e6fc, 0x37fb3f01, 0x4e823104, 0x82720021, 0x6e4f0804, 0x0c006205, 0x18001400, + 0x42001d00, 0x191d3f40, 0x04030310, 0x01074c01, 0x04010600, 0x67040003, 0x01000300, 0x69010305, 0x02020500, 0x05005705, 0x005f0205, 0x4f020502, + 0x17180001, 0x11141516, 0x0a0b0d0f, 0x0c000709, 0x06080c01, 0x56012b16, 0x4c080737, 0x11211323, 0x37323301, 0x23232611, 0x23113301, 0x34353601, + 0xa7510227, 0xe58583f3, 0xfe014493, 0x6bb50144, 0x12221c1f, 0x76eefe72, 0x6c500276, 0x6262056c, 0xc7988bc1, 0x0509fe5e, 0x0331fd62, 0xfb023102, + 0xfd2b04d3, 0x9fa846fd, 0x18f08245, 0x0807fb8f, 0x2100172e, 0x2b002600, 0x35403800, 0x2226272b, 0x181c1d21, 0x17030208, 0x02020001, 0x0203044c, + 0x01004900, 0x01020300, 0x02006903, 0x59020000, 0x00211682, 0x2c088261, 0x28235100, 0x06042726, 0x16242b1a, 0xe3071916, 0x02142410, 0x85162507, + 0x072227ac, 0x10110607, 0xae832517, 0x8aa10325, 0x19c42261, 0x350ceb07, 0xa9fe9886, 0x33463f34, 0x343f4633, 0x01404080, 0x263b3bec, 0x0719824c, + 0xe53610f0, 0x6653c1fe, 0x20041917, 0x87861619, 0xfdfef7fe, 0xfe840986, 0xc78284ff, 0x00722708, 0x05b20400, 0x000f0062, 0x001b0017, 0x403c0020, + 0x131d1e39, 0x0f050403, 0x02040101, 0x0703004c, 0x03040501, 0x2a826705, 0x04060131, 0x06006701, 0x57060000, 0x00060600, 0x8201025f, 0x114f320c, + 0x21273211, 0x08102111, 0x212b1e06, 0x23230123, 0x410d8213, 0x07210575, 0x0a704125, 0x11270437, 0xb2043536, 0x1cc5feea, 0x44fe0144, 0xf3a7df01, + 0xfe869883, 0x0a7541d7, 0x6c6cbc2f, 0x09fef701, 0xc1626205, 0x2bcea38b, 0x0774417b, 0xfe457626, 0x00a8462e, 0x02220082, 0xaf828400, 0xaf822a20, + 0x0d00092e, 0x36403900, 0x00030103, 0x01020108, 0x0036a982, 0x03020604, 0x67030001, 0x02010105, 0x05570102, 0x02010101, 0x1b82005f, 0x004f5e08, + 0x0b0c0d00, 0x0009000a, 0x11121109, 0x2b190607, 0x15213513, 0x21072101, 0x27050135, 0x03cc3301, 0x012afe5d, 0x71fc17d7, 0x2801d801, 0x852bfe85, + 0x9fa5bd04, 0x9ea8e5fb, 0x01022004, 0x0000ebfb, 0xff8d0003, 0x052304e7, 0x000b007b, 0x001c0013, 0x1937403a, 0x04101118, 0x4c010203, 0x216d8305, + 0x6d820461, 0x01613e20, 0x003f3009, 0x0c14144e, 0x1400000c, 0x0c1b141c, 0x82120c13, 0x240a2438, 0x18170907, 0x3a08e17b, 0x33121011, 0x14110206, + 0x23260117, 0x34111212, 0x16160127, 0xea390333, 0x82e1e1ea, 0x7f370803, 0x98011f87, 0x8581763b, 0x1f6bfe1d, 0x7b053855, 0xa8fe8ffe, 0x8ffea6fe, + 0x5a017101, 0x71015801, 0xfef1fe97, 0x037fdddd, 0x9afb5638, 0x25010f01, 0xc9fc7bd7, 0x82002629, 0x00013300, 0x040000b2, 0x00620516, 0x4029000a, + 0x07080926, 0xb1450003, 0x38032e05, 0x0001024d, 0x00600100, 0x01390101, 0x082b824e, 0x0a000a2b, 0x05111111, 0x012b1909, 0x21152111, 0x05112135, + 0xfb020127, 0xd4fc1b01, 0xc9fe5201, 0x05a00153, 0x9a38fb62, 0xbefe039a, 0x39398288, 0x70000100, 0xe6030000, 0x19007b05, 0x2d403000, 0x00021516, + 0x01010b02, 0x40180200, 0x3e210993, 0x2157824d, 0x62885f01, 0x18001925, 0x83171127, 0x16002c62, 0x06141516, 0x07210700, 0x60003521, 0x3808079e, + 0x36362707, 0xc0a00233, 0xfffe7466, 0x177f02ea, 0x0a01bdfc, 0x7d660201, 0x4280606f, 0x8dcd5380, 0xb0657b05, 0xfeec7c6e, 0x979fd6e5, 0x1f010001, + 0x806f6ecb, 0x68634f43, 0x248b8264, 0x03e7ff5c, 0x288b82f5, 0x403f002d, 0x022a2b3c, 0xf7c71803, 0x00692912, 0x61050404, 0x05050106, 0xa9829882, + 0x9d826120, 0x83003f21, 0x002d2bfb, 0x2421262c, 0x09072e25, 0x9a852b1b, 0x1e070623, 0x33a01802, 0x3536250d, 0x37232134, 0x08ee7f18, 0x82062221, + 0x334c08ae, 0x6ac49b02, 0x564c7b48, 0xde7a568f, 0x4de5808f, 0x579f397c, 0xfe47845b, 0x521775eb, 0x42467444, 0x86564772, 0xe8ac6845, 0x9e5d7b05, + 0x5988525f, 0x93500810, 0x6ec07767, 0x43685d5f, 0x52794145, 0x683492fd, 0x3465464b, 0xa372413d, 0x01268d82, 0x00008700, 0xc7822904, 0x2c000e25, + 0x82082940, 0x4c0130a4, 0x0502090a, 0x0001044a, 0x02010103, 0x44670100, 0x3c0806e6, 0x4e023902, 0x11111411, 0x09061011, 0x33012b1c, 0x23112315, + 0x01352103, 0x13210117, 0xac7d0333, 0xfd01b9ac, 0xa19101c4, 0x740198fe, 0xdf01a018, 0x01b8fe97, 0xab038848, 0x01a6fc42, 0x086a827d, 0x00010022, + 0x04e7ff8e, 0x00620505, 0x40430020, 0x04010340, 0x02111201, 0x4c020503, 0x03040500, 0x80030504, 0x04242282, 0x69040105, 0x06322d82, 0x0601075f, + 0x004d3806, 0x61020303, 0x3f020200, 0x15824e02, 0x20002029, 0x26252412, 0x83081123, 0x21072282, 0xf58a1811, 0x23062208, 0x0e816422, 0x11233808, + 0xfd1bd703, 0x3e703be6, 0x765fab70, 0xc97d8fd9, 0x8f3d7453, 0x81948556, 0x3d5c376d, 0x94620594, 0x1a1f63fe, 0x8987c567, 0x545974d3, 0xa13f416f, + 0x15869796, 0x82b90219, 0x02002367, 0x73439500, 0x001a3106, 0x40450027, 0x02011042, 0x03011101, 0x02172302, 0x4c27ac82, 0x00030106, 0x82030504, + 0x068064aa, 0x184d3e21, 0x36084065, 0x1b4e003f, 0x1b00001b, 0x21261b27, 0x001a001f, 0x26252319, 0x41190908, 0x232507e7, 0x34110222, 0x09816412, + 0x0c288f18, 0x021e4808, 0xb10a0333, 0x7dca7468, 0xee7edff4, 0x4b7b9aa3, 0x92646f5d, 0xa23f0450, 0x777e4464, 0x3494596e, 0x5d753904, 0xc5638603, + 0x78de938e, 0x3e016201, 0xba5601e4, 0x803a7f52, 0x555ba1ed, 0x9cb0f8fc, 0x5560889d, 0x825fc29b, 0x00012fc4, 0x03ebffb9, 0x006205fb, 0x401d0006, + 0xa54e001a, 0x05bd6c06, 0x005f2608, 0x00380101, 0x0213114e, 0x012b1809, 0x21012701, 0xfb032135, 0x02b4ddfd, 0x0380fd15, 0xfbd40442, 0xa5043717, + 0x2946829b, 0x7c000300, 0x3404e7ff, 0xcb827b05, 0x3500272e, 0x25402800, 0x020f1e2b, 0x01020304, 0x2008915c, 0x7b50183e, 0x2afd8208, 0x282b2c2b, + 0x2b1a0904, 0x6c070600, 0x25220b47, 0x20642626, 0x16042308, 0xcf601716, 0x00152407, 0x5e272626, 0x1382067e, 0xfd035c08, 0x988a7774, 0x9392da74, + 0x100170d5, 0xc17d6970, 0x76c06f67, 0x724172fd, 0x7b54606b, 0x017b6e6e, 0x848953fe, 0x858c6d5d, 0x03417f59, 0x3b4292b9, 0xb4707bbd, 0x6eb26767, + 0x94387ce9, 0x51a47671, 0x53739f4f, 0x38233758, 0x75645570, 0xb7fd6974, 0x2c2d4269, 0x8073718f, 0x41466e3f, 0x7e3105db, 0x1004d3ff, 0x17007905, + 0x35002400, 0x0c1a3240, 0x21cb8302, 0x6c6e0708, 0x82002005, 0x006523f1, 0x736e0202, 0x023e2c05, 0x0018184e, 0x18241800, 0x821d1f23, 0x2e162631, + 0x2b170906, 0x27d88200, 0x05040210, 0x37023e27, 0x08086c75, 0x12333652, 0x022e3736, 0x15062223, 0x02331614, 0x9a67cedb, 0xecfebefe, 0x89f8c12b, + 0x619c400d, 0x7865b272, 0x854081ce, 0x7037023f, 0x7c837f5b, 0x88790572, 0xeefeadfc, 0x48c9aefe, 0xd38f358f, 0x6a514b98, 0xd09086c8, 0x5210fd6c, + 0x58c09f50, 0x8d949a9e, 0xff45af83, 0x00172e0b, 0x403d0023, 0x0501083a, 0x05020400, 0x06686204, 0x01010624, 0x1b6f1f01, 0x00202108, 0x0c21b182, + 0x31b3820c, 0x1e221823, 0x0c170c1c, 0x00101216, 0x240a000b, 0x02460709, 0x7ab81810, 0x0c046708, 0x2d090946, 0x85817f87, 0x4b398086, 0x4b37394b, + 0x0a46374b, 0xdbfe3516, 0x0f01f1fe, 0x24012501, 0x50fe0e01, 0x4c38374b, 0x4c36384c, 0x6227bb85, 0x4e04e7ff, 0x73007d04, 0x383605ef, 0x1e1f3540, + 0x03041516, 0x044c0102, 0x01050101, 0x02010302, 0x92180669, 0xee730a63, 0x10202408, 0x82171018, 0x260e2236, 0x18b68307, 0x220ea247, 0x4615020e, + 0x363c05bd, 0x27343536, 0x02331601, 0x7c7ce3ef, 0xe39697e3, 0x98e27c7d, 0x49538b57, 0x4b397001, 0x29080782, 0x3d8dfe56, 0x8e7d0457, 0xb7b3f8fe, + 0x908cf6fe, 0xb7b30a01, 0x978a0801, 0xe098c258, 0x16e6026a, 0xc45998fc, 0xfd67f199, 0xaf8f1e10, 0x2b001f30, 0x38403b00, 0x07010106, 0x01050301, + 0x75416903, 0x02002408, 0x82610002, 0x0020342e, 0x1020204e, 0x20000010, 0x262a202b, 0x101f1024, 0x8416181e, 0x960920b2, 0x161621b2, 0x4108cf45, + 0x02220b70, 0xbc83e2f0, 0xc2829720, 0x5322bc84, 0xba82578b, 0x332d0582, 0x36374949, 0x04364848, 0xf8fe8a7d, 0x23c083b7, 0xb70a018c, 0x9922c087, + 0xbc8259c4, 0x58c2982c, 0x3549ccfe, 0x364a4a36, 0x95824935, 0xc6000128, 0x26040000, 0x83476904, 0x03002210, 0x08834785, 0x83471b20, 0x4707200b, + 0x03360c83, 0xfc18010e, 0xfe5101d7, 0x9f0153cb, 0x30fc6904, 0x05039999, 0x834787bc, 0x008f2e05, 0x04fc0300, 0x001a007d, 0x172b402e, 0x08834716, + 0x03010428, 0x03000200, 0x81836902, 0x01005f23, 0x26608501, 0x2819001a, 0x82051711, 0x06e64660, 0x0721052b, 0x24243521, 0x26343536, 0x07cf6f26, + 0xc2bd022c, 0xfff94c69, 0x16590200, 0x3882c6fc, 0x52052208, 0x5a45693a, 0x557a468d, 0x7d0488d0, 0x6765a25c, 0x9f9dd6a1, 0x8bd8c397, 0x335e3e56, + 0x6b635549, 0x2565836b, 0x15ff7200, 0x8b82eb03, 0x42002930, 0x25263f40, 0x06040302, 0x10030201, 0x0582020f, 0x01064c2a, 0x03040005, 0x00690405, + 0x01209882, 0xc0829883, 0x82590121, 0x61002699, 0x00010000, 0x29428251, 0x24280029, 0x2c242421, 0x86470707, 0x07b14407, 0xce6a2020, 0x09517a0a, + 0x07062908, 0x33363627, 0x5fb9a902, 0xa48b7491, 0xfe91d773, 0x3e7498fa, 0x9386588e, 0x176e878f, 0x7d8d724d, 0x4482556e, 0x77c35664, 0x983cb682, + 0x1ba1735b, 0x7499a810, 0x6bb66abb, 0x7b8d4046, 0x7592797d, 0x38695b6b, 0x4f517140, 0x01267c82, 0x29ff7800, 0xbf824a04, 0x5f680e20, 0x00012105, + 0x25067b47, 0x02000500, 0x81475705, 0x02052210, 0x0680474f, 0x2b1c0723, 0x0e804725, 0xbfbf8b26, 0xa3fd01b5, 0x30058047, 0xe29d1894, 0x01dafe93, + 0xaa038426, 0x01a8fc43, 0x2f6e826a, 0x9b000100, 0x130415ff, 0x20006904, 0x43404600, 0x28127f47, 0x00060107, 0x00060100, 0x08884767, 0x02020324, + 0x83475903, 0x02032206, 0x0c824751, 0x01208482, 0x08208247, 0xfd1ae435, 0x406a35e4, 0x7862b173, 0xc6818ed9, 0x8c3c7452, 0x8697825a, 0x35593874, + 0x95690494, 0x181c7cfe, 0x8483c066, 0x545873cf, 0x9e3f4170, 0x1682918f, 0x47a60218, 0x1f20317f, 0x20097f47, 0x137f4720, 0x47098042, 0xaf3d6a7f, + 0xf10310ff, 0x06006904, 0x20402300, 0x00010102, 0x03044c01, 0x00490102, 0x00010100, 0x06284357, 0x01002108, 0x0210144f, 0x132b1807, 0x27011521, + 0x03af2101, 0xaf0bfe42, 0x81fde101, 0xfb8f6904, 0x83043b36, 0x83472882, 0xceb61823, 0x2b2c240d, 0x47070428, 0x75213983, 0x09834776, 0x7d6a6f26, + 0xc16e66c2, 0x22188347, 0x473e93b6, 0x3b280a83, 0xa4756f93, 0x729f5052, 0x3d1f8347, 0x0410040d, 0x0015007d, 0x403f0022, 0x0301183c, 0x00010b02, + 0x084c0203, 0x49000207, 0x10510104, 0x01052606, 0x03000003, 0x51068259, 0x16290712, 0x16000016, 0x1d211622, 0x233b821b, 0x07062c14, 0x28058d47, + 0x05040214, 0x37242427, 0x08526806, 0x080c8c47, 0x68ceda40, 0xfeb9fe9b, 0x13012bf2, 0x76162601, 0x66b471c5, 0x457fd078, 0x33033985, 0x867c5e6f, + 0x7d04717f, 0xefaaf886, 0x46d2bffe, 0xc9fc498f, 0x7cc36e93, 0xfd6ec982, 0x994f482f, 0x889d54b6, 0x85828e87, 0xcb460020, 0xb61b4609, 0xffff2908, + 0x72fe2201, 0x0c018c03, 0xb8030701, 0x7efe0000, 0x00b10900, 0x7efeb802, 0x002b35b0, 0xffff0000, 0x7efe8801, 0x00012803, 0xb9201f82, 0x01201f87, + 0x31201f8b, 0x7d201f82, 0xba203f84, 0x23201f94, 0x8b205f82, 0xbb201f84, 0x21201f94, 0x8d223f82, 0x5f821401, 0x1f94bc20, 0x3f823320, 0x7f847d20, + 0x1f94bd20, 0x5f882520, 0xbf94be20, 0x6efe3d24, 0x3f847303, 0x3f94bf20, 0x3f821920, 0x9f849720, 0x1f87c020, 0xdf8b0320, 0x71fe2324, 0x1f849103, + 0x5f91c120, 0x0102002d, 0x03f4ff22, 0x008e028c, 0x4b1a000f, 0x02240655, 0x69020103, 0x2c06b253, 0x4e001b00, 0x22262523, 0x2b1a0704, 0x0a184a24, + 0x16163228, 0x23262615, 0x5b691522, 0x03290805, 0x628b478c, 0x48488c62, 0x8b62628c, 0x4848a447, 0x47474b92, 0x5897e349, 0x5f5e9858, 0x97565796, + 0xce606e5f, 0x6d656c66, 0x36008200, 0x00880101, 0x02280300, 0x00060082, 0x0418401b, 0x00030203, 0x824c0101, 0x5f002103, 0x71821e82, 0x33053f44, + 0x07112321, 0x03332527, 0x4cba9a28, 0x017e2201, 0xa76b65d5, 0x31203f85, 0x7d203f82, 0x182ab382, 0x25402800, 0x00021011, 0x374f0702, 0x11b24705, + 0x11272423, 0x05374413, 0x21070625, 0x6c352107, 0x2222057b, 0x694d2707, 0x032b0806, 0x818a3e69, 0xfd125d01, 0x3e96b0d3, 0x4d68353b, 0x57983c6c, + 0x013f7955, 0x3f5d5f7b, 0x636a7080, 0x322b2b49, 0x4745515d, 0x823e6036, 0x0101267c, 0x03f4ff23, 0x397b828b, 0x40430026, 0x04012340, 0x03012205, + 0x02010504, 0x01011003, 0x00010f02, 0xa9470501, 0x05677013, 0x4382da82, 0x25002627, 0x24242122, 0x05a4472b, 0x4c141521, 0x27230a55, 0x55331637, + 0x372406ad, 0x34353233, 0x08085048, 0x428ce33b, 0x4a51594c, 0x9f58608d, 0x785a623a, 0x45424847, 0x7746115f, 0x32643773, 0x56954253, 0x52608e02, + 0x0e0d4237, 0x5b3c4644, 0x513c3833, 0x2e29304d, 0x524c5c2a, 0x37582623, 0x05334131, 0x0000213b, 0x96028d03, 0x2c000e00, 0x01062940, 0x4c010300, + 0x04020708, 0x0301054a, 0x26b58202, 0x00670003, 0x48010404, 0x310806e8, 0x11141111, 0x07061011, 0x23252b1c, 0x21352315, 0x03170135, 0x15333733, + 0x6b8d0333, 0x019afe9b, 0xb6e0860a, 0x706b8c0f, 0x01667070, 0x8bfe35c0, 0x6482a9a9, 0x33010137, 0x7d03f4ff, 0x1c008202, 0x0e406d00, 0x06020116, + 0x03010105, 0x285d8304, 0x0ab04b4c, 0x22405850, 0x336c8200, 0x00720305, 0x06050004, 0x00670504, 0x03020006, 0x00690206, 0x25064c50, 0x1b4e001b, + 0x24832340, 0x01030223, 0x31259a80, 0x230a4059, 0x24121111, 0x07072123, 0x06242b1d, 0x3a412223, 0x22420809, 0x11230706, 0x15210721, 0x32333636, + 0x7d031516, 0x6db685a2, 0x436d525f, 0x1c393d45, 0x01741d45, 0xbcfe0eec, 0x6923481e, 0x6e786c80, 0x34384753, 0x0f113131, 0x787c6601, 0x656d100e, + 0x02000000, 0xe3412501, 0x1a3a0806, 0x3b002600, 0x011a3840, 0x01050300, 0x011d0105, 0x4c030504, 0x00000300, 0x69000301, 0x01060100, 0x05010405, + 0x04040069, 0x02006102, 0x4e021b02, 0x261b1b1b, 0x2626251b, 0x97822426, 0x012b1b24, 0x8c822326, 0x4e0cd34f, 0x17230632, 0x69070600, 0x4008086d, + 0x543f0d03, 0x2e045b57, 0x6d414366, 0x52864d42, 0x4d499068, 0x5e7f6e99, 0x2d56f5fe, 0x3f454613, 0x01363b45, 0x5f5c1ff3, 0x5b2c2928, 0x396b4643, + 0x5d619656, 0xfe385997, 0x3d2725ea, 0x342f3b47, 0x27908232, 0xf0ff3d01, 0x82027303, 0x27059b47, 0x01000100, 0x01024c01, 0x20053255, 0xd2411800, + 0x1311230b, 0x214f0702, 0xfe733609, 0x320198bb, 0x360275fe, 0xd6fd1a02, 0x7ed5013f, 0x01030000, 0x23ff8219, 0x008e0297, 0x322cff83, 0x23402600, + 0x010f1d29, 0x01020304, 0x220ad757, 0x43610003, 0x2a2805ac, 0x04272c2b, 0x002b1a07, 0x7e0c1c4f, 0x32240814, 0x04151616, 0x200a1c4f, 0x091b4f04, + 0x03355d08, 0x56588c75, 0x6462914e, 0x4d534a8f, 0x80483e3e, 0x45815753, 0x564464fe, 0x40412f37, 0x1b01403f, 0x39376960, 0x55494d4e, 0x1b137301, + 0x5a3c3d4c, 0x3a593132, 0x13124e38, 0x4d313b46, 0x2d4c2d2c, 0x12112424, 0x23191d22, 0x28fe1921, 0x1f301113, 0x212d2926, 0x23010200, 0x9103f3ff, + 0x1735bf82, 0x37002100, 0x01193440, 0x01040203, 0x4c020300, 0x49000117, 0x06894700, 0x89470420, 0x84068205, 0x000330ca, 0x18181851, 0x2a201821, + 0x07052626, 0x4f252b19, 0xc6830d09, 0x06061425, 0x74370007, 0x45080707, 0x94746b01, 0x5c3d1b60, 0x4370443b, 0x63548c53, 0xe1704a8e, 0x510c01af, + 0x4d419703, 0x0e6c3d45, 0x2039462a, 0x415a2c1f, 0x43366746, 0xa07a547b, 0x6201145b, 0x2f33922b, 0x00002c2f, 0x2201ffff, 0x8c03d902, 0xb7467305, + 0xe5022105, 0x2105b746, 0xb746e502, 0xe1022509, 0x63052803, 0x2105b746, 0x1f83e102, 0x02b80123, 0x201f88e1, 0x221f8231, 0x826f057d, 0x00ba221f, + 0x241f9200, 0x03d50223, 0x201f848b, 0x201f94bb, 0x223f8221, 0x4677058d, 0x3f9205b7, 0x3f823320, 0x7f847d20, 0x3f94bd20, 0x5f882520, 0x1f87be20, + 0x9f8b0220, 0xd0023d26, 0x62057303, 0xbf205f82, 0xe0201f82, 0xe020bf86, 0x1920bf88, 0x97203f82, 0xc0209f84, 0x03203f87, 0x23243f8b, 0x9103d402, + 0xc1201f84, 0x22265f94, 0x8c036a02, 0x3f410405, 0x41762006, 0x7620063f, 0x88265f88, 0x28037602, 0x3f41f804, 0x221f8406, 0x8902b801, 0x8231201f, + 0x847d201f, 0x82ba203f, 0x201f915f, 0x205f8223, 0x201f848b, 0x201f94bb, 0x223f8221, 0x410c058d, 0x3f91063f, 0x3f823320, 0x7f847d20, 0x3f94bd20, + 0x5f882520, 0x1f87be20, 0x9f8b0220, 0x66023d24, 0x3f847303, 0x3f94bf20, 0x3f821920, 0x9f849720, 0x1f87c020, 0x3f8b0320, 0x69022324, 0x1f849103, + 0x5f91c120, 0x01002508, 0x6d01c9fd, 0xdf033702, 0x06000300, 0x010103b3, 0x01012b32, 0x37020127, 0x0442d4fb, 0xfe6d032e, 0x00027200, 0x023c0082, + 0x6d011d00, 0x63059404, 0x0a000600, 0x1e402100, 0x0203040a, 0x01010004, 0x0208094c, 0x260c7953, 0x09021014, 0x47012b18, 0x4b8305b3, 0x47bd0121, + 0x022105b7, 0x285384d7, 0xd501e102, 0xfea76b65, 0x275a870a, 0xf3ff0300, 0xbe040000, 0x23285b86, 0x06b14800, 0x3d404464, 0x1c356186, 0x0408091b, + 0x01120402, 0x4c030203, 0x00000100, 0x67000105, 0x06265200, 0x0302002b, 0x00570203, 0x5f030202, 0x2e1f8200, 0x1127244f, 0x06101418, 0xb12b1c09, + 0x8a440006, 0x06122184, 0x2115f647, 0x9c869301, 0x9c84ef20, 0x04486820, 0x21b38d15, 0x12489cfd, 0x24c78214, 0x04f4ffe5, 0x24c786cc, 0x405d0031, + 0x08c3865a, 0x06012e20, 0x02092d07, 0x08100605, 0x1b050402, 0x1a040301, 0x06030201, 0x0701084c, 0x07050600, 0xcf836906, 0x04050322, 0x56086350, + 0x3935091f, 0x0b0b4e02, 0x300b310b, 0x2527292b, 0x1c1e2224, 0x10141618, 0x0d614109, 0x48160221, 0x0121243c, 0x20eb8685, 0x20eb84ed, 0x1e4a480e, + 0x210ca741, 0x5848affe, 0xff03361d, 0x05f4ffab, 0x006f0505, 0x001c0018, 0x40810143, 0x10111c22, 0x05904903, 0x08014036, 0x021b3f09, 0x1a220807, + 0x2d070602, 0x2c060501, 0x07050401, 0x29060b48, 0x0000002e, 0x01000901, 0x05820a67, 0x09070825, 0x41006908, 0x023a0715, 0x00610302, 0x4d380303, + 0x04050500, 0x04040061, 0x1b4e0439, 0x500cb04b, 0x35a14058, 0x358e3e20, 0x35a41020, 0x13206b8f, 0x6b8f35a4, 0x35a41720, 0xd2af6b8d, 0x00835920, + 0x1d17403a, 0x1d431d1d, 0x393b3d42, 0x30343637, 0x24282a2e, 0x0b131127, 0x002b1a09, 0x2217f142, 0x42012701, 0xe3202730, 0x26160e43, 0x42d4fbca, + 0x42102e04, 0x04211d40, 0x1126435c, 0xfed2fe26, 0x00027200, 0x261d4d42, 0x00f9ff03, 0x43b80400, 0x19280647, 0x06b14f00, 0x44404464, 0x08064b43, + 0x09121326, 0x08000603, 0x11060501, 0x04050201, 0x0001004c, 0x00010600, 0x05060067, 0x07570603, 0x01040501, 0x02050302, 0x06320f82, 0x03005f03, + 0x114f0306, 0x11111411, 0x08101415, 0x16441e09, 0x4a13200f, 0x01210dd5, 0x06214399, 0xe084f120, 0xe34a6e20, 0x0d03440b, 0x4a91fc21, 0x00310cf2, + 0x00f7ff03, 0x05b90400, 0x0026006f, 0x0039002a, 0x20b3847d, 0x0b174c72, 0x02102a22, 0x3005184c, 0x03293233, 0x0128000a, 0x01310a09, 0x4c080906, + 0x13d0530c, 0x010a2b08, 0x0a006900, 0x570a0709, 0x0809010b, 0x09070601, 0x0a006706, 0x005f070a, 0x4f070a07, 0x38390000, 0x34353637, 0x2d2e2f30, + 0x73822b2c, 0x2205494c, 0x841b090d, 0x440020e1, 0x01222610, 0x01410127, 0x41b7200f, 0x03271dd4, 0x42d4fb5f, 0x415e2e04, 0x05210b19, 0x1a1b446f, + 0xfefefd26, 0x00027200, 0x24112f41, 0x04f4ffd6, 0x06e341db, 0x8f002724, 0xdf411a40, 0x01093106, 0x08210708, 0x10080402, 0x0f050301, 0x05030201, + 0x35062744, 0x0405002c, 0x72050703, 0x07000600, 0x67070608, 0x04000800, 0x33450805, 0x401b2216, 0x232e832d, 0x80030504, 0x59222fa4, 0x474c0c40, + 0x14262505, 0x1f090910, 0x200bbf46, 0x1b544c12, 0x46760121, 0xce200cdc, 0x4218624c, 0x8d200e3e, 0x2612714c, 0xff9fff03, 0x451105f4, 0x39240643, + 0x1d409e01, 0x31094345, 0x090a011b, 0x06021a33, 0x0501220a, 0x04012107, 0x16410605, 0x34200806, 0x05060700, 0x00720709, 0x08010000, 0x00670100, + 0x0a090008, 0x00670908, 0x0706000a, 0x0069060a, 0x201a4445, 0x233b8335, 0x80050706, 0xdf443c9f, 0x5010230f, 0x3ca84058, 0x220de644, 0xab13b04b, + 0x20798f3c, 0x8d3cab17, 0x8cb1a979, 0x05674574, 0x35371029, 0x12113132, 0x45292324, 0x1f200560, 0x421c6045, 0xd7201d33, 0x26165645, 0x42d4fbb2, + 0x42c82e04, 0x51451843, 0x42fc201a, 0x00291350, 0xff030000, 0x04f4ffc5, 0x069744e9, 0x3e024724, 0x93442840, 0x01293114, 0x28410b0c, 0x300c0802, + 0x2f090701, 0x09070601, 0x2b065e42, 0x0809003f, 0x72090b07, 0x00000100, 0x2c059344, 0x0a0c0b00, 0x0c00670b, 0x0c090800, 0x05096008, 0x05010d24, + 0x4e183805, 0x412b0830, 0x0707004d, 0x06006106, 0x47063906, 0x402007ae, 0x08234683, 0xa0800709, 0x983e2047, 0x50102347, 0x47a94058, 0x13208f99, + 0x8f9947ac, 0x47ac1720, 0x1c208f99, 0x8f9747ac, 0x413e4021, 0x175a0862, 0x1cb2410a, 0xa8414a82, 0x84592009, 0x1c403100, 0x43450000, 0x3d3e3f40, + 0x37393b3c, 0x2c2e3133, 0x22085c46, 0x681b090e, 0xdf4f0563, 0x096b5109, 0xa6522320, 0x0101230c, 0x02430127, 0x4685201d, 0x57201e66, 0x461e0a43, + 0x13432473, 0xb52a0818, 0xfb04f4ff, 0x0e007705, 0x2f001200, 0x2040ad00, 0x04030112, 0x03000106, 0x0b0c0111, 0x08021029, 0x0701180c, 0x06011709, + 0x1c530607, 0x05b55205, 0x0b433420, 0x0b2a5306, 0x0a010027, 0x00670104, 0x0e15430a, 0x22095741, 0x4135401b, 0x37ac0798, 0x14405938, 0x27282b2d, + 0x23242526, 0x11262324, 0x11111411, 0x1f090d10, 0xb248012b, 0x4105200d, 0x02211f6a, 0x0cc54821, 0xd4fb5c26, 0xbe2e0442, 0x21186344, 0xd8485103, + 0x47602009, 0x464105ba, 0x00042613, 0x04f4ff11, 0x06bf47a0, 0x31002526, 0x50405300, 0x0806c147, 0x02012522, 0x03010905, 0x02081002, 0x01280307, + 0x4c050706, 0x02000500, 0x69020503, 0x01080300, 0x07030607, 0x210be84c, 0xda4b0606, 0x26262507, 0x30263126, 0x24260582, 0x09101426, 0x85471d09, + 0x5303200b, 0x01212542, 0x068f47b1, 0xe784d120, 0x50532020, 0x0d974720, 0x5314fe21, 0x00231d5e, 0x82090004, 0x82a720f7, 0x1c2908f7, 0x3b002000, + 0xc3004700, 0x01162040, 0x05200602, 0x04030102, 0x3b010001, 0x1f0a0701, 0x26070801, 0x080c021e, 0x0c0b013e, 0x06494507, 0xf3543d20, 0x08eb5407, + 0x08085145, 0x0a080725, 0x08006907, 0x0b0c010d, 0x00690c08, 0x5f040505, 0x38040400, 0x0b0b004d, 0x09006109, 0x4e093909, 0x553e401b, 0x40b4080e, + 0x18405930, 0x473c3c3c, 0x4042463c, 0x3032383a, 0xef482824, 0x0e212505, 0x002b1f09, 0x231be248, 0x01270105, 0x21267d41, 0x57425302, 0x32022718, + 0x0442d4fb, 0x90411c2e, 0x4d032120, 0x25111a49, 0x7200fe4e, 0x9c410002, 0xff05261f, 0x04f4ffe5, 0x0a9342ce, 0x3b003d24, 0x95423840, 0x28342b06, + 0x08090c1a, 0x02040506, 0xe364004c, 0x00003707, 0x01005f01, 0x004d3801, 0x61020505, 0x39020200, 0x2b2a4e02, 0x42502c2c, 0x0b3e5005, 0x4f31d354, + 0xe520086d, 0x8220f884, 0x4226e154, 0xfd210d8f, 0x2aef5494, 0xe1ff0522, 0xd120ff82, 0x2806eb47, 0x00510045, 0x40c1015d, 0x14ef4720, 0x3a485428, + 0x0628292c, 0x464a0809, 0x00302e07, 0x07000001, 0x00690001, 0x09080007, 0x06d84707, 0xd8470a20, 0x0909210f, 0x990ed847, 0x0ca84637, 0x1023378c, + 0x99405850, 0x0c284737, 0x1320378c, 0x6f99379c, 0x379c1720, 0x1c206f99, 0x6f97379c, 0x612e4021, 0x52410b98, 0x893a8214, 0x845920d8, 0x16402b00, + 0x595b0000, 0x40424d4f, 0x72473234, 0x470b2008, 0xa5422e72, 0x47a12032, 0x4d261e88, 0x0442d4fb, 0xbd427c2e, 0x23964726, 0x242ed342, 0x04f4fff3, + 0x0a6f45bd, 0xa1005324, 0x71451840, 0x3e4a290c, 0x1e1f2230, 0x04090a06, 0x5a08124d, 0x2845065d, 0x0108230a, 0x1a4d6900, 0x0b604506, 0x070a0a2c, + 0x07070061, 0x1b4e0739, 0x60453540, 0x2837a013, 0x51104059, 0x2c43454f, 0x064f452e, 0x4f450b20, 0x41122023, 0x022131a9, 0x195b4543, 0xd4fb1e26, + 0x7a2e0442, 0x4526a441, 0x9a411961, 0x0500222c, 0x059b41ff, 0x06006238, 0x25000a00, 0x3d003100, 0x3b403e00, 0x01000100, 0x0301020a, 0x72450003, + 0x45032008, 0x11252172, 0x1c090613, 0x06b0692b, 0x22410683, 0x5a972033, 0x012008c5, 0x4105a252, 0x04212712, 0x05f45afa, 0xfe0bfe26, 0x00027200, + 0x082d0741, 0xa0010120, 0x0f03e7ff, 0x0f005601, 0x10401300, 0x01000000, 0x01010061, 0x264e013f, 0x18090222, 0xf85b242b, 0xa001390e, 0x34335330, + 0x54313154, 0x30533334, 0x313153d2, 0x55333253, 0x33553131, 0x01253982, 0x0391fe94, 0x254b8203, 0x40250010, 0xbf5b0922, 0x82012006, 0x02592619, + 0x00010101, 0x2109825f, 0x63824f00, 0x0f001024, 0xb1690317, 0x06142506, 0x13230307, 0x0806866a, 0x4e880223, 0x9f19162d, 0x252161a1, 0x012f4e2c, + 0x2e4e2d56, 0xfe375128, 0x17900194, 0x4d2e2b4b, 0x0102002d, 0x22af82ad, 0x82070401, 0x001f2aaf, 0x2bb04b3c, 0x15405850, 0x067a5d00, 0x7f4d3b20, + 0x033f2508, 0x13401b4e, 0x01236a82, 0x50010002, 0x15820847, 0x26b6592a, 0x04222626, 0x002b1a09, 0x1020da8e, 0x012d0f8e, 0x2f4d2dad, 0x2d2d4e30, + 0x4d2f304e, 0x210b822d, 0x0b864f2f, 0x838c0321, 0x2e2e2215, 0x2302834e, 0x2e4d61fd, 0x2f209982, 0x2f200c83, 0x93239f82, 0x850392fe, 0x0020299f, + 0x0119b556, 0x4c010302, 0x1428a685, 0x00030105, 0x63020302, 0x61269683, 0x01010104, 0xa582003b, 0xfe181b20, 0x1f820801, 0x63020221, 0x02220557, + 0x2982005f, 0x40594f2d, 0x00101012, 0x10201000, 0x8217181f, 0x260e21f2, 0x1807e86a, 0x25094e60, 0x16123336, 0x46411516, 0x8a86200d, 0x4e3029b6, + 0x9e19162d, 0x262060a1, 0x0422c382, 0xb5842d07, 0x2d2fbb84, 0x4d2d4efd, 0x3652282e, 0x8f0195fe, 0x822b4a17, 0x299a82c6, 0x3a000300, 0x7604e7ff, + 0x70820101, 0x2f001f30, 0x18401b00, 0x00020204, 0x05610100, 0x1b420203, 0x82262005, 0x06222600, 0x3e2b1c09, 0x88491802, 0x26262209, 0x0f2e4235, + 0x3a310f8f, 0x28274025, 0x41252541, 0x25402728, 0x41269001, 0x82078227, 0x41272413, 0x8b920126, 0x409b251b, 0x26402626, 0x22821682, 0x0b940882, + 0x00820020, 0xca010228, 0xe502e7ff, 0xb5826205, 0x25001325, 0x42002240, 0x00240567, 0x01044d38, 0x3009a66e, 0x13040404, 0x11271204, 0x19090510, + 0x0333012b, 0x08d76f23, 0x2805cb5e, 0x15d4ea01, 0x26417da8, 0x82988426, 0x62052488, 0x83cd6dfc, 0x26422475, 0x82274226, 0x336b8508, 0xe50273fe, + 0x0f00e903, 0x49001300, 0x5020b04b, 0x04144058, 0x00247082, 0x69000102, 0x2606c959, 0x4e033d03, 0x8a19401b, 0x0de65916, 0x0e405928, 0x12130000, + 0x45821011, 0x05260e22, 0x65080543, 0x03250923, 0x02231333, 0x4178847d, 0x5129051d, 0x03da1da2, 0x274126e9, 0x3ca18326, 0x26412726, 0x71fc19fe, + 0xa8000200, 0xeb03e7ff, 0x1f007b05, 0x3c002f00, 0x1c1d3940, 0x35fe8202, 0x0100004c, 0x04000104, 0x01010080, 0x01056102, 0x4d3e0202, 0x0b190106, + 0x20290975, 0x20000020, 0x282e202f, 0x25378226, 0x071c2b1e, 0xee701809, 0x020e3608, 0x35231515, 0x37363634, 0x3435023e, 0x06222326, 0x21362707, + 0x0b316e02, 0x3336363d, 0x62b8d102, 0x393f4d35, 0x3abd2d43, 0x3b324151, 0x4a637d26, 0xab853a92, 0x41070301, 0x7b3d0b42, 0x4e529057, 0x2b2e496f, + 0x413c5a3d, 0x4f7a554b, 0x45362531, 0x47594f2c, 0xfbc96347, 0x0d5c4187, 0xc400022a, 0x070452fe, 0x0f00e903, 0x362bcb82, 0x1e1f3340, 0x01040202, + 0x8204004c, 0x020428e6, 0x01010580, 0x41040000, 0x622e0665, 0x3d030300, 0x00004e03, 0x20222e2f, 0x17431a1c, 0x18132018, 0x27089952, 0x37363233, + 0x22210617, 0x83056644, 0x333523dc, 0x6241ac02, 0x8365200a, 0x263a34c8, 0x914a647c, 0xfeab863a, 0x62b87afc, 0x3a3f4c34, 0x41bc2e43, 0xfd220d78, + 0xc78254c9, 0x46342622, 0x4623c782, 0x82c96247, 0x834d20e2, 0x5b3f38e2, 0x0000413e, 0x01ffff00, 0x03f301a0, 0x0162030f, 0x00e70307, 0x5e0c0200, + 0x0c200633, 0x2905d35d, 0x5e010100, 0x5203b201, 0xb482a403, 0x1b401e23, 0x21108200, 0x38825900, 0x02610127, 0x01000101, 0x280a8251, 0x260e000f, + 0x2b170903, 0x0a9a6f00, 0x2328c882, 0x41721102, 0x47477241, 0x01210584, 0x220a82b2, 0x85407246, 0x3d468205, 0xbe005a00, 0x8a045604, 0x1b000e00, + 0x0d0e1840, 0x090a0b0c, 0x05060708, 0x0d020304, 0x56824900, 0x01107622, 0x36085482, 0x25132301, 0x17030507, 0x03371313, 0x02052725, 0xfe12c0b8, + 0x81013a8a, 0xdede98f9, 0x8101f998, 0x048afe3a, 0x8b6ffe8a, 0xc6fe6bb3, 0xfe4d016e, 0x3a016eb3, 0x828bb36b, 0xfd482cd7, 0x076803a8, 0x06230008, + 0x8247ff3c, 0x0603244f, 0x82b9003c, 0x08e48207, 0x0064004a, 0x054c0400, 0x001b0062, 0x4049001f, 0x02070e46, 0x02040601, 0x02010302, 0x0a010c67, + 0x104d380a, 0x0003080f, 0x0d5f0900, 0x0909020b, 0x01054d3b, 0x03390303, 0x1c1c1c4e, 0x1e1f1c1f, 0x191a1b1d, 0x15161718, 0x11121314, 0x102e0086, + 0x2b1f0911, 0x33032301, 0x23032315, 0x03822113, 0x33352323, 0x27038313, 0x13210333, 0x05330333, 0x04370682, 0x9c3aac4c, 0x2ca32ab0, 0xa32bedfe, + 0x3bab982c, 0xa32baf9c, 0x8215012e, 0xfd9a2f04, 0x13013a9f, 0xfe8d033b, 0xb5fe8f4d, 0x03834b01, 0xb3018f27, 0xfe450190, 0x240383bb, 0x014dfe90, + 0x28bc83b3, 0xff610001, 0x064f042f, 0x0d435e55, 0xfc4f042d, 0x56039aac, 0x23f90c06, 0x82e10645, 0x35278d28, 0x32010002, 0x3701052b, 0xfcb50301, + 0x550399ac, 0x49dd06d1, 0x26821ff9, 0x00010029, 0x0355feb0, 0x711e04e9, 0x3b2017df, 0x310fdf71, 0xb001fee9, 0x8dfde901, 0x8c033903, 0x043ac9fa, + 0x47839ff0, 0xcb010230, 0xe6020000, 0x0f007b05, 0x27001300, 0x33462440, 0x4d1f2108, 0x22076844, 0x444e031b, 0x73690b49, 0x0ae16607, 0x13330336, + 0x417f0223, 0x27412626, 0x25264027, 0xa2512741, 0x7b05da1d, 0x220c4944, 0x8272fc13, 0x0002265b, 0x04e4ffc4, 0x246f8407, 0x4038002f, 0x0e7f4335, + 0x05217e84, 0x06d27001, 0x00620325, 0x43200303, 0x80920f81, 0x31328143, 0x3b924a63, 0xfefead85, 0x3562b87a, 0x433a404b, 0xb08dbc2d, 0x43cafd21, + 0x2c080881, 0x6347475a, 0x529057c9, 0x2f496f4e, 0x3e5a3f2a, 0xffff0041, 0x5800ad01, 0x78040103, 0xe9030601, 0x08007100, 0xb00200b1, 0x2b35b071, + 0x271b8200, 0x6e005a00, 0x3a045604, 0xf2221b82, 0x9943b000, 0xb0ff2105, 0x012d1c84, 0x3eff8e00, 0x47062104, 0x06000300, 0x09df41b3, 0xbafcd42c, + 0xc247034c, 0xf926e306, 0x07420018, 0x8202202a, 0x82872087, 0x00a72887, 0x001f000f, 0x481f4022, 0x0324098a, 0x00590203, 0x2805d858, 0x26510302, + 0x04222626, 0x3b8d4807, 0x482c0421, 0xf382188d, 0xfdae012b, 0x01e902ad, 0x040701d8, 0x073b6944, 0x240c3b6a, 0x03adfdc5, 0x201f8400, 0x081f9145, + 0x00010053, 0x03e2fef1, 0x0096065d, 0xb3060011, 0x3201040c, 0x1612002b, 0x02260717, 0x12343502, 0x06173712, 0x01150206, 0x98b359b9, 0x78dfad68, + 0x68addf78, 0x0159b497, 0xf8d7fef6, 0x018e688b, 0xdc580118, 0x015801dc, 0x8b688e18, 0xc7d7fef7, 0x01010000, 0x204f8253, 0x354f8cbf, 0x37272602, + 0x15121216, 0x07020214, 0x12363627, 0x59f70235, 0x4f8797b4, 0x59b39827, 0x29018303, 0x294f82f7, 0xa8fee8fe, 0xa8fedcdc, 0x4f82e8fe, 0x2901f823, + 0x084f82c6, 0xfee70032, 0x068c03f0, 0x002b0088, 0x273d4040, 0x00040226, 0x04030108, 0x0301010e, 0x05004c03, 0x05040000, 0x04006900, 0x04010300, + 0x01006903, 0x59010202, 0x02398482, 0x01020061, 0x2a2b5102, 0x1e1f2021, 0x12131415, 0x17090610, 0x1720012b, 0x087d5c13, 0x0603072c, 0x33161415, + 0x34112015, 0x19711337, 0x32352205, 0x08088236, 0x26032720, 0x03211035, 0x10fffe8c, 0x686a0328, 0x2803676b, 0xfe708201, 0x0227025c, 0x71718338, + 0x08823883, 0xa4012e08, 0xfe9af605, 0x68171978, 0x6712136d, 0xfe1d1969, 0x4a0b0678, 0x1501923f, 0x6d010f1d, 0x4c3b0a1a, 0x4b259a26, 0x011a0b3b, + 0x011d0f6e, 0x21c78215, 0xc7822401, 0xc782c920, 0x3c002931, 0x01253940, 0x011f0501, 0x10110102, 0x82020402, 0x000025c7, 0x05000105, 0x0024bf82, + 0x02010402, 0x0333cf82, 0x00590403, 0x61030404, 0x03040300, 0x11282951, 0x82181118, 0x821b20c3, 0x141121c3, 0x2220ba87, 0xd183c182, 0x82211021, + 0x20b683b9, 0x05d16634, 0x2324cf84, 0xa4012401, 0x8d23aa82, 0x828e9e9f, 0x5cfe2a06, 0x28088277, 0x74776e03, 0x08cf8271, 0x8806f23c, 0x0f1debfe, + 0x091692fe, 0x589a575a, 0xfe16095a, 0xfe1d0f93, 0x544692eb, 0x181d8801, 0x1311666a, 0x1917696e, 0x0b068801, 0x01010089, 0x0317ff67, 0x0061066f, + 0x40220007, 0x9b66001f, 0x00672b05, 0x03000003, 0x03030057, 0x08825f00, 0x114f002e, 0x04101111, 0x052b1a09, 0x15211121, 0x032f0382, 0x02f8fd6f, + 0x01adfe08, 0x4a07e953, 0x82f2f99f, 0x82412047, 0x88492047, 0x32358247, 0x67030002, 0x01010200, 0x02005702, 0x005f0102, 0x88010201, 0x82012047, + 0x82352043, 0x41013103, 0xf8fd0802, 0xadfe5301, 0xb6f86106, 0x000e069d, 0x01260082, 0x00002f02, 0x4b823704, 0x1e00052b, 0x00001b40, 0x00860002, + 0x21438201, 0x047c0057, 0x258f8208, 0x2b190603, 0x8f832321, 0xb5e40222, 0x06228c83, 0xbf829f61, 0x17ff7927, 0xc2058102, 0x203b8800, 0x20849185, + 0x283b8310, 0x21113301, 0xcc012135, 0x248083b5, 0x55f9c205, 0x277b839d, 0x0000c800, 0x6205e803, 0x172d3f82, 0x01031440, 0x4c010001, 0x00010000, + 0x297b8285, 0x02111276, 0x012b1806, 0x02822101, 0x01bc0233, 0xfe0cfe2c, 0x012c01d4, 0x02b102f4, 0xfd4ffdb1, 0x8928834f, 0x4018253f, 0x02020515, + 0x1020408d, 0x3f834084, 0xbc020124, 0x42820cfe, 0xf401d426, 0x62052c01, 0x022b3e83, 0x01ffffb1, 0x02a501ae, 0x43d005e9, 0x022005f3, 0x2411d765, + 0x03a501c5, 0x201f8400, 0x13976545, 0xfef1002d, 0x065d03ce, 0x04060182, 0x45ec000a, 0xec240627, 0x002b35b0, 0x53205b82, 0xbf201b82, 0x0b201b84, + 0x00271b8f, 0x03dcfee7, 0x8274068c, 0x8f0c2037, 0x2401211b, 0xc9201b82, 0x0d201b84, 0x67261b90, 0x6f0303ff, 0x37824d06, 0x1b900e20, 0x1b824120, + 0x1b844920, 0x1b8f0f20, 0x2308e341, 0x00100402, 0x00209b82, 0x3407b741, 0x00110402, 0x00010000, 0x032102c2, 0x00c302ee, 0x40180003, 0x176c1815, + 0x1011280f, 0x2b180902, 0x82352101, 0xd4fc2623, 0x21022c03, 0x213382a2, 0x33821d01, 0x33a29320, 0x8afd9324, 0x33857602, 0x023f0025, 0xa1710421, + 0x71042533, 0x3204cefb, 0x00203386, 0xb0203382, 0xb02433a2, 0xb00450fb, 0xff213383, 0x346782ff, 0x03710471, 0x04060113, 0x00500025, 0x0100b108, + 0x35b050b0, 0x24eb842b, 0x04220246, 0x284fa26a, 0x04dcfb6a, 0xa1220224, 0x874f8200, 0x04022383, 0x0f900026, 0x00010031, 0x0494fe64, 0x0037ff4c, + 0xb1200003, 0x41446406, 0xb1331743, 0x01440006, 0x04213521, 0x0318fc4c, 0xa394fee8, 0x82020000, 0x0452223b, 0x2499824c, 0x00070003, 0x473d842a, + 0x67200703, 0x440ff966, 0x47830719, 0x15213322, 0x64220184, 0x4c83e803, 0x9e18fc24, 0x9b849e72, 0x7102c224, 0xfb84ee03, 0xfb8d2320, 0x01ffff23, + 0x201b821d, 0x201b8493, 0x411b8f24, 0xff841933, 0xb0047122, 0x26203784, 0xc22a3790, 0xee03d101, 0x06017302, 0x2b482304, 0xad012e0f, 0x020394fe, + 0x10000d01, 0x14401700, 0x0ddf430d, 0x37511720, 0x06dd500e, 0x2bc6013f, 0x482b2a49, 0xa118122b, 0x1e1b528a, 0x282845a0, 0x3d202a45, 0x01affe34, + 0x253d136d, 0x22008200, 0x82d40002, 0x84da2057, 0x00212b57, 0x1e19401c, 0x0001020d, 0x04834c01, 0x0385002d, 0x76010101, 0x22172717, 0x4f1a0904, + 0x5d860976, 0x8609674f, 0x84ed2010, 0x112a216d, 0x01216d85, 0x220e84b3, 0x83161129, 0x861f207c, 0x333e217c, 0x2a207c86, 0x21228c84, 0x8c893040, + 0x03258b82, 0x06dc03b1, 0x87e3822a, 0x0100248b, 0x83034c01, 0x828520ec, 0x88002091, 0x4a00208b, 0x37270870, 0x16033313, 0x8f041516, 0x0e022110, + 0x2c2bf882, 0x17102848, 0x1b528c9f, 0x83b5011f, 0x2a47238d, 0x8d831711, 0x1e041e22, 0x20297e84, 0x51013140, 0x3d1393fe, 0x228e8525, 0x8632401f, + 0x051b410f, 0xb203d222, 0x2b208f82, 0x34218f84, 0x061a41b6, 0x1ab04b26, 0x0d405850, 0x86209584, 0x40259583, 0x401b4e00, 0x0a31410b, 0x41b65921, + 0x12200733, 0x4108df51, 0xeb201734, 0x48289783, 0x9f19132b, 0x1e19508a, 0x4920a685, 0x2a064341, 0x45bd051f, 0x2a452929, 0x41363c1e, 0x24280525, + 0x2829452a, 0x3d202a46, 0x2a064541, 0x01010024, 0x03b103ae, 0x422a0601, 0x11820717, 0x01004c25, 0x82850100, 0x427620c1, 0x2c410517, 0xe8022510, + 0x2b2b492a, 0x8c0f0c41, 0x010122fc, 0x215788ad, 0x6e42b52d, 0x20f88505, 0x205d830b, 0x845d8286, 0x460920f6, 0x59210863, 0x8f6d86b4, 0x068542f2, + 0x1a23d385, 0x8bbc051f, 0x122208c3, 0x0200243e, 0x62009b00, 0x31041304, 0x0d000600, 0x0cb50800, 0x02020509, 0x01012b32, 0x01350107, 0x06851317, + 0x0163012a, 0xa3fe7207, 0xa2725d01, 0xa1300883, 0x02725f01, 0x4962fe49, 0x0186a301, 0x61fe49a6, 0x00200a88, 0x0d234f90, 0x8203060a, 0x0137274f, + 0x15013701, 0x06852501, 0x08019b27, 0x0172f8fe, 0x2052825d, 0x2e0a8535, 0xaba1fe5f, 0x9f019e01, 0x865afe49, 0x89495dfe, 0x27eb820a, 0x6f010100, + 0x41036200, 0x0624a384, 0x010205b3, 0x02259f88, 0x73090138, 0x208f82fe, 0x208f8973, 0x212f8e4a, 0x2f820306, 0x01277886, 0xfe09016f, 0x860173f7, + 0x4a9e216e, 0x63836e84, 0x3c01022e, 0x7403b803, 0x0300c605, 0x34000700, 0x32056e41, 0x0001020d, 0x035f0100, 0x3a010101, 0x401b4e00, 0x83010313, + 0x82572010, 0x00012206, 0x241c825f, 0x594f0001, 0x07cd44b6, 0x03230123, 0x30038433, 0xe121a0fd, 0x20a03601, 0x02b803e1, 0x02f2fd0e, 0x2260820e, + 0x82e80101, 0x84c8200d, 0x852d205f, 0xc672185d, 0x185b8408, 0x2011c672, 0x06b046b4, 0x02245682, 0xe020a0a8, 0x0e383f82, 0x9b00ffff, 0x1304bc00, + 0x06018b04, 0x5a003a04, 0x00b10800, 0xb05ab002, 0x8906ef4c, 0x8f3b201b, 0x6f01251b, 0x4103bc00, 0x3c203784, 0x01201b85, 0x1b8a3788, 0x1b8d3d20, + 0x01010029, 0x022fffae, 0x4c5a03e9, 0x3108090f, 0x17161624, 0x35022e07, 0x37363634, 0x15020e17, 0x41214b02, 0x5a4b613c, 0x4b5a3535, 0x21413c61, + 0x5c8194df, 0xb3915e3f, 0x91b37473, 0x815c3f5e, 0xff846694, 0x2fffc524, 0x478b0003, 0x26260024, 0x97533727, 0x27072605, 0x0235023e, 0x21478d63, + 0x4886aa01, 0x86737421, 0x00653348, 0xa7fc0200, 0x59032102, 0x0300c302, 0x1d000700, 0x92411a40, 0x11112c12, 0x07041011, 0x21032b1a, 0x82052135, + 0xfc552603, 0x030403fc, 0x240583ae, 0xa2a22102, 0x238e82a2, 0xf6f70300, 0x5a204782, 0x0b2c4786, 0x1f402200, 0x01020305, 0x57010000, 0x01290783, + 0x02045f00, 0x00010002, 0x6cca184f, 0x86012009, 0x2d52834e, 0x99fc5dfb, 0xff036703, 0x680398fc, 0x0b83fe03, 0x5b855984, 0x44fc0131, 0xc003c201, + 0x23002b03, 0x2f403200, 0x52030123, 0x012a05d8, 0x69010405, 0x00020500, 0xbd825905, 0x03000239, 0x05006702, 0x00610005, 0x51000500, 0x24212425, + 0x07062225, 0x45012b1c, 0x2720054e, 0x82059a7d, 0x2277820c, 0x43373636, 0x590805da, 0x33161617, 0x03373632, 0x77983bc0, 0x2b3d5230, 0x28264230, + 0x462a2638, 0x037bfc35, 0x2b453362, 0x34384a2f, 0x2d2a3f56, 0x5e3a243e, 0x77ca022b, 0x262d2091, 0x19182a2b, 0x01a21c1c, 0x1a1b1919, 0x2a253021, + 0x004f5828, 0xfe54fc02, 0x066002f2, 0x002a0086, 0x4042002e, 0xa5840b3f, 0x02080629, 0x04000005, 0x4d670005, 0x444b0c42, 0x01072b05, 0x4f020102, + 0x2d2e0000, 0x36822b2c, 0x2122293b, 0x16181f20, 0x09211315, 0x012b1707, 0x06222115, 0x14111506, 0x1e070606, 0x82078202, 0x822120a8, 0x26262413, + 0x82341135, 0x356308ca, 0x35363632, 0x33023e13, 0x23113321, 0xf3fd0601, 0x2a29564a, 0x594e4b5a, 0x4a562928, 0xf3fd0d02, 0x2e54a482, 0x817c7b82, + 0x5301022e, 0xb90283a1, 0x8606aeae, 0x3b421a93, 0x725978fe, 0x3d0d0d40, 0x7bfe5d71, 0x931c423c, 0x017c8c39, 0x2e584b6b, 0x4b582d9a, 0x897b7301, + 0x006cf836, 0xfd020000, 0x8217ff7f, 0x00612acf, 0x000b0007, 0x04234026, 0x11964c01, 0x00010523, 0x0bd14103, 0x2007994c, 0x2b928313, 0x037bfc04, + 0x0230fd85, 0xaeaeaed0, 0x2305a04c, 0xb6f8ad06, 0x003d5a82, 0xff91fc03, 0x06d40317, 0x001f0061, 0x00270023, 0x005d4060, 0x0c09000a, 0x1267090a, + 0x09f95210, 0x08002c08, 0x07080700, 0x0c010e63, 0x134d1a0c, 0x00000211, 0x0f145f0b, 0x0b0b030d, 0x01054d1c, 0x031b0303, 0x2700004e, 0x23242526, + 0x82202122, 0x1e1f234a, 0x09531c1d, 0x87112008, 0x07152500, 0x15012b1f, 0x230b0953, 0x35211121, 0x13200386, 0x23050d53, 0x21132101, 0x03210383, + 0x0b1053d4, 0xfd15fe2b, 0xfe5301f8, 0x020802ad, 0x0717534c, 0x015ffb30, 0xc7fd3bfe, 0x1301a002, 0x04ecfe3b, 0x1f53901d, 0xccfd280a, 0x9f0e069d, + 0x5301bcfd, 0xfd3f0623, 0xfeb301bd, 0x00b3014d, 0x01acfc02, 0x03bc037e, 0x000f0070, 0x402a0013, 0x03000027, 0x5e590001, 0x67270629, 0x01000000, + 0x54010461, 0xd85605bd, 0x54072009, 0x252011c1, 0xfd22b882, 0xc554725f, 0x16062709, 0x0a04f6fb, 0xcb547e01, 0xa2a3210b, 0xff2f5082, 0xffe0fdff, + 0x011f02e7, 0x03230056, 0x8240fce7, 0x03032412, 0x8210ffe7, 0xff002807, 0xffd2f9ff, 0x858101e7, 0x52fb211b, 0x23821382, 0x8572fe21, 0x32f82123, + 0x002a0782, 0x08f90400, 0x2003e7ff, 0xa5828003, 0x17000728, 0x2b002700, 0x19822840, 0x02012708, 0x00670100, 0x04030002, 0x06670302, 0x05040401, + 0x05010761, 0x4e052005, 0x23262626, 0x10111111, 0x2b1e0708, 0x844a2103, 0x5a042005, 0x66490e12, 0x05ad5709, 0x60034024, 0x0383a0fc, 0x5b48f921, + 0x03210b16, 0x240d8c84, 0xa2e0a280, 0x0a295b8a, 0x0b8a3220, 0xcf829282, 0xeb82bc20, 0xaa047828, 0xcd042300, 0x128270fe, 0x4d040324, 0x0782dcfb, + 0x03000024, 0x1b8243fd, 0xe357bf20, 0x003f2406, 0x57444047, 0x073013e5, 0x1f020201, 0x0806094d, 0x03040403, 0x03010561, 0x4e2cfa82, 0x20203030, + 0x3f300000, 0x36383e30, 0x210bf057, 0xf057070a, 0x5700201f, 0x20200ef0, 0x01210f8e, 0x170058a5, 0x59cefc21, 0x262506dd, 0x03274026, 0x350e5853, + 0x080d1a58, 0xfc03003d, 0x035c01aa, 0x008003e8, 0x00130003, 0x4b5f0017, 0x585019b0, 0x01002040, 0x57010004, 0x05030400, 0x01025704, 0x03010600, + 0x69030005, 0x05040400, 0x0405005f, 0x401b4f05, 0x84000021, 0x85672024, 0x02002224, 0x20238206, 0x28238b02, 0x04104059, 0x15161704, 0x061f5a14, + 0x19070727, 0x1521032b, 0x0f7c5721, 0x13822520, 0x5e047626, 0xd3fda2fb, 0x210abf42, 0x1283e601, 0xa2800324, 0xc2429dfe, 0xa283310b, 0xc5fdffff, + 0x3902e7ff, 0x23000704, 0x38ffe903, 0x03248782, 0x18fce903, 0x2006bf42, 0x201b823d, 0x211b8511, 0x138290f7, 0xfb212382, 0x42238550, 0x002b05e3, + 0x003ff806, 0x047c034a, 0x440f006a, 0x37260665, 0x42004700, 0xe8823f40, 0x01010325, 0x82010005, 0x057f7ae8, 0x08010a2e, 0x59080907, 0x07000600, + 0x67070609, 0x083a0e82, 0x010b6109, 0x51090809, 0x3a3c4244, 0x11233234, 0x26141111, 0x0c222626, 0xf55c1f07, 0x0fd24210, 0xfa420520, 0x3ff82126, + 0x210b1d5d, 0x0d8b2003, 0x05f50225, 0x83d8fa28, 0xebf92103, 0x830c375d, 0x09455d25, 0xb754ef20, 0x8a2e200a, 0xa241240b, 0x5d3aa2e0, 0x2d200a54, + 0x00200b8a, 0x30080082, 0x0000fd04, 0x04e803cd, 0x000f000d, 0x00230013, 0x40300027, 0x0002002d, 0x03020103, 0x00060067, 0x07060507, 0x00040067, + 0x65050405, 0x00010100, 0x26338261, 0x114e011c, 0x82232614, 0x08222303, 0x05411e07, 0x82252010, 0x0f0f5ef5, 0xfd211383, 0x30bf8200, 0x2d2d4d30, + 0x4d2f2f4e, 0x048a022d, 0xfda2fb5e, 0x20138276, 0x24af822f, 0x4e2f304d, 0x2113852c, 0xbf8a9203, 0xfea21c23, 0x29b28ac7, 0x0000a286, 0xabfdffff, + 0x0f4292fe, 0xfcea2206, 0x24918218, 0xffea0303, 0x82078238, 0x0afe2b1b, 0xf501e7ff, 0x23006205, 0xeb44ec03, 0x42ec2006, 0x05260607, 0xe7ffcef8, + 0x1b828202, 0x44000321, 0x372405c7, 0x3c403f00, 0x0808714a, 0x4d1a0037, 0x070b090c, 0x0505050a, 0x06086104, 0x20040402, 0x28284e04, 0x08081818, + 0x36283728, 0x27182e30, 0x1e202618, 0x16081708, 0x11111127, 0x1b070d10, 0x0333012b, 0x20038323, 0x0ed54304, 0x8f0fe543, 0xeef8260f, 0x04a815d4, + 0x21048235, 0xd84331fc, 0x7404210a, 0x76200c8b, 0x250aff43, 0x6dfc6205, 0x485d9303, 0x0bdc430e, 0x380de843, 0xff18fc01, 0x05e8033f, 0x001300ab, + 0x1238403b, 0x4a060211, 0x02020708, 0x2e048249, 0x00010506, 0x67000601, 0x02010104, 0x82570102, 0x02012306, 0x8048035f, 0x392f8206, 0x11111113, + 0x11111113, 0x2b1d0709, 0x07211501, 0x01211521, 0x35210127, 0x03823721, 0x17012808, 0xfce80301, 0xce0385b7, 0xbffed1fb, 0xfd160196, 0x86410320, + 0x280439fc, 0xfe924b01, 0xa28003e2, 0xe3fda2e0, 0x82d2014b, 0x2b022907, 0x001efe49, 0x68f70100, 0x1b2e8b86, 0x0a407900, 0x0a02191a, 0x020b0c4a, + 0xab4b4904, 0x08212605, 0x01070101, 0x2f808202, 0x03010667, 0x03040105, 0x01096304, 0x5f0a0000, 0x0a272482, 0x4e001c0a, 0x8328401b, 0x2314820a, + 0x67000a01, 0x04232e8c, 0x82570304, 0x04032235, 0x2d38845f, 0x1640594f, 0x1b000000, 0x17181b00, 0xc7861516, 0x0d111124, 0xc9871f07, 0x0322cd83, + 0xcd861327, 0x07823720, 0x17132808, 0xfae80303, 0xb30586d3, 0x0685edf9, 0xd008f998, 0x3afba496, 0xfa862705, 0x870d0653, 0xf4066cf9, 0x04aa92d7, + 0x82e1a143, 0xa2fe24d1, 0x8213014b, 0xa1e12f07, 0xfe496801, 0x030000e1, 0xe7ff56fd, 0x53468402, 0x06265e50, 0x445e0720, 0x0f5d4225, 0x52468120, + 0x0b535e17, 0x42490321, 0x605e0b5e, 0x0c684229, 0xc0fc0326, 0x2303e7ff, 0x3d2cff82, 0x5d004d00, 0x4b404e00, 0x0335363b, 0x08056d7e, 0x0701003f, + 0x80070001, 0x01010103, 0x050a6104, 0x1f040402, 0x0b090c4d, 0x06070703, 0x06010861, 0x4e062006, 0x3e3e4e4e, 0x5d4e0000, 0x54565c4e, 0x4c3e4d3e, + 0x3d004446, 0x2b243c00, 0x0d1c2b1b, 0x3a501807, 0x12064109, 0x06063522, 0x24161d41, 0x36171632, 0x1f764733, 0xb8090238, 0x3f4b3462, 0xbd2e443a, + 0x33415039, 0x637d273b, 0x1772cd53, 0x895f414f, 0xc4892612, 0xfcfeaa2b, 0x0a9a43d9, 0x47480321, 0x4d390f8d, 0x2a2d466d, 0x41405d3e, 0x4e79544b, + 0x48352630, 0x71594f2d, 0x4c3501af, 0x13b25f2f, 0xc2576b22, 0x410db55f, 0x00280c54, 0xfc040000, 0x03e7ff5c, 0x38055742, 0x00270023, 0x40540037, + 0x021c1d51, 0x4c010103, 0x06050000, 0x80060005, 0x05be6a00, 0x82006721, 0x05083e0c, 0x01006706, 0x09610201, 0x1f020201, 0x08010a4d, 0x00610708, + 0x07200707, 0x0028284e, 0x05bf4400, 0x230a204b, 0x0b1c2b1e, 0x2120ba48, 0xfd432101, 0x44062005, 0xfe210edc, 0x175f4285, 0x030d022b, 0x7fddfb6d, + 0x5efba204, 0x0f2141df, 0x2517be60, 0xe0a205fe, 0x00415aa2, 0xff23080d, 0x00dcfbff, 0x042404be, 0x0323008a, 0x0082fbf2, 0x03020000, 0xff00cef2, + 0x00c2f7ff, 0x058e03be, 0x822700b6, 0x01502217, 0x291f832c, 0x000068f7, 0xf2030301, 0x278238ff, 0x00b10929, 0x2c01b801, 0x822b35b0, 0x0200330c, + 0xfeffa5fb, 0xee04a403, 0x15000e00, 0x1f402200, 0x57181415, 0x0b2007d3, 0x2107d45f, 0xd45f1400, 0x11590805, 0x2b170701, 0x03330301, 0x01051725, + 0x27010107, 0x25372501, 0x01150135, 0xc6fd0135, 0x0116c119, 0x16fe38e3, 0xfe9e4601, 0xa2fcfee1, 0x0cfe2d01, 0x0362043f, 0x02a2fc5e, 0x02ea02b9, + 0xb0fefd04, 0x7bfe87b7, 0xfeaa0179, 0x81017162, 0xc77fb688, 0xfdb5ecfd, 0xab01c9e5, 0x27b78200, 0x2ffff2fb, 0x5506a903, 0x9822b784, 0xaf823000, + 0x5afff522, 0x0820a282, 0xb021af82, 0x22ae8330, 0x5c2cfc03, 0x4108061f, 0x002a0026, 0x404e0031, 0x0221224b, 0x03044a08, 0x0e490102, 0x0405020c, + 0x01000202, 0x0a670005, 0x1a080801, 0x020d0f4d, 0x5f070606, 0x0702090b, 0x034d1c07, 0x1b010101, 0x30314e01, 0x292a2b2c, 0xff4c2728, 0x86112005, + 0x10172400, 0x5c2b1f07, 0x2722066b, 0x05600321, 0x36212113, 0x2a06805c, 0x21132105, 0x35262101, 0x5c213734, 0xb424058b, 0xf5fd38e4, 0x37141960, + 0xe635a701, 0xb49768b9, 0x01c0fb59, 0xecfe3b13, 0xd5017b01, 0x68fe0f12, 0x2306b35c, 0xb0240195, 0x23133060, 0x982c01b5, 0x2905c35c, 0xfeb301e2, + 0x7079694d, 0xfb830061, 0x08057b5c, 0x39003562, 0x82004300, 0x01317f40, 0x01080b0a, 0x010e1312, 0x4c030304, 0x00000f00, 0x69000f0b, 0x12001300, + 0x69121308, 0x03101516, 0x02050708, 0x03080403, 0x00010067, 0x65020102, 0x0b0b010d, 0x11144d1a, 0x0a090902, 0x020c0e5f, 0x4d1c0a0a, 0x04040106, + 0x3a4e041b, 0x3a433a3a, 0x3f414243, 0x393c3d3e, 0x210a3279, 0x5a71292a, 0x21222205, 0x06334e20, 0x13141526, 0x07171012, 0x411bc15c, 0x03291641, + 0x21103526, 0x21132101, 0x05934f01, 0x03213723, 0x11d95c03, 0x12fd1e22, 0x37144c41, 0x02209002, 0xedf9a401, 0xfe3b1301, 0x085f04ec, 0x89939b88, + 0x3a58fd0d, 0x201afc5c, 0x135d411a, 0x0f2a0138, 0xfb15011d, 0xfeb30152, 0x9a484d4d, 0x4dfe4440, 0x03000000, 0x575c2cfc, 0x001f2a06, 0x00270023, + 0x14624065, 0x05524101, 0x10126723, 0x0e494102, 0x49416320, 0x13152305, 0x4a410311, 0x24242911, 0x27240000, 0x25262724, 0x201c6c4f, 0x05734716, + 0x9f5c1120, 0x14724205, 0x21011132, 0x03212113, 0x6f031121, 0x5301adfe, 0xb3fdf8fd, 0x35141a41, 0x12fced01, 0xfe3b1301, 0x3ab501ec, 0x61063902, + 0x9df2f99f, 0xfc933402, 0xfb440223, 0x06694f79, 0x04000024, 0xf8827cfc, 0x4b636020, 0x24f58306, 0x0068406b, 0x25f7820e, 0x670f0e12, 0x5e500710, + 0x01133505, 0x12006702, 0x03130116, 0x0c671312, 0x1a0a0a01, 0x0811154d, 0x50096163, 0x24250860, 0x1c202024, 0x22f9851c, 0x82202320, 0x187163fc, + 0xfb821720, 0x71631320, 0x1301271a, 0x03250321, 0x07831321, 0x67506420, 0x0d78630b, 0x2fb20128, 0xfa2f1b01, 0xfc823ad2, 0x83af0221, 0x1884630b, + 0x01e8fe2c, 0x88b5fe4b, 0xb3014dfe, 0x0a833dfd, 0xff860020, 0x8ae00221, 0x406722ff, 0x8ef68b64, 0x0e003ae7, 0x145f0a0e, 0x0a030c0f, 0x164d1a0a, + 0x03131301, 0x0205125f, 0x031b0303, 0x23fbcb4e, 0x01132303, 0x0782fb83, 0x0226fb9a, 0x78ca787c, 0xfa83edfb, 0x264b0324, 0xf99826f2, 0xfc450127, + 0xfe870379, 0x24fa842b, 0x01fafe79, 0x24fa8206, 0x2cfc0300, 0x05cf67ff, 0x003c4d08, 0x00500040, 0x13b04bbc, 0x3d405850, 0x04030000, 0x80040003, + 0x03020911, 0x04020608, 0x67040314, 0x0c010100, 0x0e10155f, 0x1a0c0c03, 0x020a124d, 0x5f0b0202, 0x0b020d0f, 0x164d1c0b, 0x05141401, 0x0207135f, + 0x051b0505, 0x45401b4e, 0x95523f93, 0x26458205, 0x01156110, 0x8e1f1010, 0x01072143, 0x49843c82, 0x61132408, 0x20131300, 0x40594e13, 0x0041412c, + 0x41504100, 0x4047494f, 0x003d3e3f, 0x383b003c, 0x34353637, 0x7d313233, 0xb84505ca, 0x2b132505, 0x1f07171c, 0x221a5168, 0x65210706, 0x3e2619d7, + 0x21013302, 0x09492113, 0xd102210f, 0x2510f948, 0x21848e3c, 0x006694fe, 0x28e72d17, 0xfb5ec7a8, 0x3b130123, 0x9c04ecfe, 0x480fd647, 0x372213f8, + 0x0c538396, 0x0b2c660a, 0x449d7d28, 0xb3015ffc, 0xef4775fd, 0x0400270d, 0x0000b8fb, 0xab42c703, 0xcc20080a, 0x5015b04b, 0x0e2a4058, 0x09030b0d, + 0x080f1114, 0x09010004, 0x10126800, 0x13010307, 0x02030406, 0x20071167, 0x0701541a, 0xcb501b20, 0x0d2f2a05, 0x0e09020b, 0x00570900, 0x2236860e, + 0x9b67000e, 0x36402136, 0x14253183, 0x00030811, 0x2e61820f, 0x0f000e00, 0x670f0e12, 0x13001200, 0x44131202, 0x6f900828, 0x40595929, 0x27202026, + 0x44242526, 0x7454050e, 0x097e670c, 0x1f071524, 0x0c44032b, 0x2117281a, 0x03252115, 0x82051321, 0xac783607, 0x2eb09c22, 0xeefe30a3, 0x9830a330, + 0xaf9c23ab, 0x0142a33f, 0x2d048215, 0x9903a69a, 0xf9fc67fc, 0x23130122, 0x0b83c101, 0xfeff0228, 0x91fe8efe, 0x03836f01, 0x02018e27, 0xfed30190, + 0x0803832d, 0x148e1629, 0x0201fefe, 0x00008eee, 0x2cfc0200, 0x4c0494fe, 0x1d006205, 0x56002100, 0x0d0f5340, 0x0e110502, 0x03020304, 0x82670205, + 0x00012320, 0x4f486301, 0x10122305, 0x5048030c, 0x03002f0a, 0x4e031b03, 0x00001e1e, 0x211e211e, 0x40821f20, 0x20135355, 0x20dd8313, 0x68ba8203, + 0x15201359, 0x0120f683, 0xe626db82, 0xf9760544, 0x5c685ad3, 0x3aac2f12, 0x3ae9fd9c, 0x013b1301, 0xa3ecfd4b, 0x5d68b702, 0x028f2212, 0x053b5542, + 0x7cf72908, 0xad0393fe, 0x30009606, 0x57003400, 0x01305440, 0x4c010e00, 0x07022627, 0x020c0f4a, 0x02030d04, 0x01040201, 0x000e0067, 0x633e0282, + 0x07070109, 0x0b104d1a, 0x06050502, 0x02080a5f, 0x4d1c0606, 0x1b020200, 0x33344e02, 0xac413132, 0x056c430b, 0x30111123, 0x23cc8211, 0x25172701, + 0x2325cb98, 0x02262103, 0x07ac6511, 0x14150727, 0x01171212, 0x242e8221, 0xf6010352, 0x32df961f, 0x650844b0, 0xe078d8c2, 0xb09568ac, 0xdb7d055a, + 0x821cf59c, 0xecfe24ef, 0x820293fe, 0x08f194b0, 0xb5ecfd3c, 0x2101b901, 0x015401d9, 0x89688e15, 0xc9d8fef8, 0xb3fec620, 0x0283edfe, 0x00b301e7, + 0xfcffff00, 0x032fff51, 0x005506e0, 0xfbf50323, 0x010000f0, 0x8af20306, 0xb1080030, 0x4d4a0101, 0x25128205, 0x2fff79fc, 0x23820804, 0x000a3408, + 0x080ab306, 0x132b3201, 0x01150107, 0x27020927, 0x045f6701, 0x6305fd00, 0x5afcb902, 0x039a56fd, 0xc50c0656, 0xfeb587fd, 0xab018b23, 0x82fa3b02, + 0x82e10645, 0x82152063, 0x86eb2063, 0x00b42763, 0x03020000, 0x7b829cf5, 0x82c9f721, 0x85872017, 0x38ff2117, 0x83821782, 0x8268f721, 0x82032007, + 0x8250208b, 0x2d7b8307, 0x030000e7, 0x00620519, 0x401b0006, 0xd75f0418, 0x1a002306, 0xa84a024d, 0x11123e05, 0x19070310, 0x0133032b, 0x23010123, + 0x9b02fb7d, 0xfdb8fdd1, 0x6205d0b7, 0xb0049efa, 0x214583fb, 0x4389fc01, 0x1e40212f, 0x01000105, 0x02034c01, 0x1a010102, 0x2264824d, 0x824e001b, + 0x00062805, 0x04111106, 0x822b1807, 0x33012f45, 0x19030101, 0xfdfb65fd, 0x4902d064, 0x4b834802, 0xfb620525, 0x48b00450, 0x7520060b, 0x1b368f82, + 0x2f002b00, 0x66003f00, 0x010c6340, 0x850a0e0a, 0x13030105, 0x02448603, 0x00692613, 0x12130112, 0x0d294859, 0x61131237, 0x13121300, 0x3c2c2c51, + 0x2c32343a, 0x2e2f2c2f, 0x2026282d, 0x12786b1e, 0x1f061523, 0x1b06482b, 0x230f1257, 0x13210305, 0x470f3953, 0x01221a22, 0x54712cbe, 0xfb2c3109, + 0x13013ae1, 0x2ec4023b, 0x4e312e4d, 0x304e2d2c, 0x34470882, 0x532d2018, 0x2b080a62, 0x014dfe35, 0x4d20feb3, 0x2e4e2e2e, 0x2d2d4d2f, 0x00002f4f, + 0xae01ffff, 0xe9021402, 0x07013f06, 0x00004404, 0x0900e502, 0xb80100b1, 0x0a8f4c18, 0x1302c526, 0x3e060003, 0x45201f82, 0xe4201f82, 0xe4201f86, + 0x2806774d, 0x02ecff01, 0x02c4041f, 0x182f64c5, 0x2b180734, 0x21352101, 0x28fbc404, 0x1f02d804, 0x010000a6, 0x33a7f400, 0x0330fc23, 0x833385d0, + 0xbc032167, 0x1f236784, 0x5e021c40, 0x06820544, 0x21730120, 0x00033209, 0x07031103, 0x15012b17, 0xbc033521, 0xc50230fc, 0x286d82a6, 0xff060000, + 0x04cd00ec, 0x06fb54c4, 0x00172408, 0x002b0027, 0x403b002f, 0x03010538, 0x01020104, 0x0b670203, 0x010a0901, 0x08090708, 0x00060067, 0x55070607, + 0x2f270b03, 0x2b2c2d2e, 0x5626142a, 0x10560512, 0x23052314, 0x03833335, 0x870fd441, 0xaf012117, 0x290b1255, 0xaeaeebfe, 0xaeae2a04, 0x1455ebfc, + 0x5515870b, 0x81250c16, 0xfea2a2a2, 0x0a185520, 0x7b5d1920, 0x23d38206, 0xc404e7ff, 0x2006e354, 0x06d5550b, 0x40404322, 0x0720d385, 0x2708d382, + 0x08070109, 0x070b0601, 0x01006706, 0x005f0001, 0x4d1a0000, 0x0b0b010c, 0x0a00610a, 0x4e0a200a, 0x23141414, 0x1a1c2214, 0x220a416e, 0x541f070d, + 0xcf8605e9, 0x07860120, 0x2e0ff554, 0x15d4ea01, 0xa792fea8, 0xa73104a7, 0x85cffba7, 0xbafd2107, 0x240b3248, 0x016dfc62, 0x21ac8214, 0x0482dafd, + 0x0548ff20, 0xff02220c, 0x1dfb6eec, 0xfb6e1a20, 0x08994b0d, 0x831bfb6e, 0x0cf15bb9, 0x13213523, 0x6e038221, 0xfe2818fb, 0x3b2301f0, 0x7101a2fe, + 0x6e07e75b, 0xbf8528ff, 0xbb6fc420, 0x23bfb719, 0x15210321, 0x8307734e, 0x2ebf89bb, 0x21030521, 0xfec40413, 0x5e013adc, 0x6f2a8efe, 0xc29006be, + 0xfd120124, 0xc36f3a27, 0x00022524, 0x04000064, 0x7f70c3de, 0x4dc3950d, 0xbfa90c09, 0xff012008, 0x043fffec, 0x00ab0575, 0x4031000b, 0x0201022e, + 0x01044a03, 0x01044900, 0x01020003, 0x68670203, 0x002f0fb9, 0x000b0000, 0x1511110b, 0x2b190705, 0x56170101, 0x023d08e9, 0x9248019b, 0x01965bfc, + 0x019afe18, 0xb2fd87c7, 0x26028503, 0x4bddf949, 0xe2a2d501, 0x203682a2, 0x206b8500, 0x546357c4, 0xfec4042a, 0x51028736, 0xbdfe4ffd, 0x02218189, + 0x239282af, 0x8503e5fe, 0xfd218082, 0x828885e0, 0x23fe2293, 0x20d58200, 0x83f7823a, 0x22f7848b, 0x5703010a, 0xf78305ee, 0xfb820020, 0xb06bf782, + 0x84c0820d, 0x841120f7, 0x08e557f7, 0x8b011721, 0xa9032279, 0x226e8992, 0x83492106, 0x00002869, 0xff3cfb02, 0x828d033f, 0x000b2af7, 0x4032000f, + 0x01020e2f, 0x37664103, 0x17010136, 0x01d4fe01, 0x5bfc9148, 0xfd180195, 0x87b002b1, 0x1604c9fc, 0xfc217982, 0x0c71415b, 0x8205fc21, 0xddf92180, + 0x7f84b782, 0xeb850420, 0x46001725, 0x84164340, 0x1314297f, 0x49000304, 0x03080709, 0x2007bd45, 0x050d4605, 0x01360682, 0x01065f00, 0x4f000100, + 0x00000c0c, 0x170c170c, 0x0f101112, 0xfa410d0e, 0x410a2006, 0xf6540efa, 0x27012106, 0x092b9b93, 0x874efd88, 0x67fc3903, 0x4196bdfe, 0x1742061f, + 0x0599410a, 0x22052a41, 0x4173fc02, 0x03200693, 0x27072741, 0x0c4a0302, 0x4902020b, 0x25189641, 0x0f040404, 0x8e420f04, 0x82052006, 0x0980597f, + 0xfc01172a, 0x91a90373, 0xbc075bfc, 0x7620818e, 0xf9236f82, 0x8b4604dd, 0x0000257c, 0xecff0100, 0x2008736a, 0x146f6a18, 0x83470720, 0xfb4c2706, + 0xfe6004a0, 0x3387a394, 0x37ffc422, 0x8525b747, 0x64002133, 0x33a56782, 0x54086788, 0xf6fe30fd, 0xf505d002, 0x64003d00, 0x32336140, 0x04030329, + 0x0305012c, 0x1a212238, 0x39050604, 0x04020319, 0x010c0201, 0x12130107, 0x07000309, 0x2a2b4c06, 0x0b4a0402, 0x4900020a, 0x06000500, 0x69060502, + 0x01000200, 0x69010207, 0x00070108, 0x65000700, 0x26438200, 0x04040061, 0x824e031c, 0x3d2808fe, 0x27253c00, 0x26272427, 0x1d070925, 0x3736002b, + 0x23060617, 0x03272622, 0x23261327, 0x07060622, 0x33023e27, 0x26371732, 0x16240d8a, 0x03171317, 0x84050664, 0x0727222d, 0x3e0d8217, 0x2b949001, + 0x99d03b81, 0xa4528e4e, 0x333db4a4, 0x1a688443, 0xbc862181, 0x424e496d, 0x8831614d, 0x8043290e, 0xaea0a046, 0x5e224a2b, 0x21082f85, 0x1940645b, + 0x01346850, 0x41506a75, 0x3138a874, 0x0222bbfd, 0x4c2c1d78, 0x78434330, 0x2fe71e4d, 0x0a852b2c, 0x02282e28, 0x97fd2033, 0x27841817, 0x0fe22d24, + 0xbf823031, 0x5b030021, 0xc74708c3, 0x40343c05, 0x00010b31, 0x0205064a, 0x01044902, 0x01010500, 0x67010003, 0x02030107, 0x82570302, 0x02033606, + 0x0201065f, 0x114f0203, 0x11121111, 0x08111113, 0x012b1e07, 0x08be5b01, 0x39080a82, 0x21012107, 0x1d022137, 0xe602e5fe, 0xd6fdbafc, 0xfd180196, + 0x0243031e, 0x038dfa30, 0xcffc6899, 0x67fcd007, 0x05310368, 0xa223fe62, 0x014b5cfc, 0xaa03a2d5, 0xfea2dafd, 0x9082a27c, 0xc75b0520, 0x13210808, + 0x1b001700, 0x23001f00, 0x57405a00, 0x00020102, 0x020b0c4a, 0x090a4903, 0x00040710, 0x06080b11, 0x2a138204, 0x0d0f6701, 0x03020305, 0x84570203, + 0x03022508, 0x040c0e5f, 0x03260e82, 0x0018184f, 0x72552300, 0x1b182906, 0x191a1b18, 0x14151617, 0x82057a5c, 0x131124b7, 0x821d0712, 0x011722b9, + 0x08984433, 0x82352321, 0x073529b8, 0x05213521, 0x01152135, 0x30062f66, 0x4801ebfd, 0xdee5fe92, 0x0187c2fe, 0xfedbfdc5, 0x30d082bd, 0x873b01da, + 0xfca03efe, 0x05c00340, 0xf7c00300, 0x21098340, 0x0583c008, 0x02850324, 0xda824926, 0x45a2e221, 0xa220073e, 0xde820083, 0xe082a220, 0x6001012b, + 0x7103f5fe, 0x06008406, 0x0e0b6900, 0x48012937, 0x016afe7b, 0xbd027b96, 0x032961fc, 0x85038684, 0x0101002a, 0x202f823f, 0x082f8650, 0x01000430, + 0x27012b32, 0x01370101, 0x7bba0115, 0xb8fe4801, 0xfe96017b, 0x9f0329f5, 0xfc2a9d03, 0xffff867b, 0xf301a201, 0x62031103, 0xf0030200, 0x0f830002, + 0x0392fe25, 0x82070410, 0xea20080f, 0x0100000f, 0xcbfecb00, 0x5905e503, 0x2f001d00, 0x021b2c40, 0x03000300, 0x0102030e, 0x0f111400, 0x03210682, + 0x05e7564c, 0x00636808, 0x5f030000, 0x38030300, 0x16194e00, 0x09042523, 0x16012b1a, 0x26260717, 0x15062223, 0x36322110, 0x07061737, 0x26112311, + 0x36343502, 0x33113736, 0x6e87f002, 0x3c693d5d, 0x0d018c81, 0x5b3f6a3b, 0xbca28f66, 0x7daf59c7, 0x102d04a0, 0x242e7c59, 0x7ffec8c8, 0x56843027, + 0x01dafe15, 0x19011a29, 0x94e892e3, 0x822e0113, 0x022f0867, 0x92004400, 0xc4046c04, 0x28001c00, 0x20406800, 0x0304061b, 0x161a0003, 0x0204070c, + 0x0f131503, 0x0201040d, 0x051c4c03, 0x144a0002, 0x7b01020e, 0x132006c9, 0x0f7f8618, 0x03414c08, 0x19401b4e, 0x01040000, 0x03000203, 0x01020069, + 0x00590201, 0x61010202, 0x01020100, 0x0c405951, 0x281d1d1d, 0x2d2f271d, 0x19090521, 0x3336012b, 0x17371732, 0x15161607, 0x07170714, 0x22230627, + 0x37270727, 0x37343526, 0x18003727, 0x0809eb9d, 0x65012366, 0x658d8c69, 0x22ab71af, 0x71ad4a26, 0x8e8b65b1, 0xaf71af68, 0x71ad4446, 0x7f7f2d01, + 0x7d7d7878, 0x42130478, 0xad72af42, 0x8a467e33, 0xad72ab71, 0x72af4040, 0x8b8e6baf, 0xfe72b06b, 0x848391fc, 0x83849191, 0x00030091, 0x04cbfe81, + 0x00a3063a, 0x00290021, 0x402d002f, 0x292a2f2a, 0x17181f22, 0x070e1415, 0x0021f382, 0x2aa7820f, 0x0102004c, 0x00008502, 0x7f860001, 0x1e2305d8, + 0x83031f11, 0x161626ae, 0x27260717, 0x05275b11, 0x23110729, 0x27262611, 0x82171637, 0x06814106, 0x83060321, 0x166208b4, 0x35361317, 0x02272634, + 0x45bd72b4, 0xb693726f, 0x7db059d0, 0x4dd6858b, 0xbbb08b6d, 0x77a855b9, 0x5f518b8b, 0x8b454c1f, 0x056955be, 0x3f560b77, 0xfe126973, 0xa8c53b49, + 0x1073aa64, 0x1e01dcfe, 0x794c6809, 0x13020e8b, 0x5789ba3e, 0x010c6496, 0x0e38fe2c, 0x452e4d5e, 0x37fd1d3b, 0x7252c327, 0x0082002c, 0xf6000428, + 0xb8036afe, 0xd5826205, 0x1500063c, 0x51002300, 0x01054e40, 0x01200002, 0x010f0506, 0x4c030603, 0x03021011, 0x12820749, 0x02040131, 0x01086801, + 0x06050004, 0x09690504, 0x82000601, 0x8265201e, 0x38350844, 0x16164e00, 0x04040707, 0x22162316, 0x15071a1c, 0x0c0e1407, 0x06040604, 0x090a1011, + 0x33012b18, 0x03252101, 0x15160403, 0x23060614, 0x07112722, 0x33363411, 0x21dd8312, 0xeb822223, 0x16157c08, 0x09023316, 0xfd13019c, 0xad0b023e, + 0x8c4101af, 0x5e53733a, 0x838b8a3a, 0x42434041, 0x17163832, 0x6205243f, 0x0270f6fc, 0xb6d5fd2b, 0x9c60a5b2, 0xdefe365b, 0xa359020e, 0x71c1fdac, + 0x346f7c77, 0x1aa7586a, 0x0001001c, 0x04e7ff46, 0x007b0546, 0x40550028, 0x00010252, 0x0101030b, 0x05011600, 0x06011704, 0x0a4c0405, 0x01090101, + 0x02010302, 0x03010867, 0x05040107, 0x82670403, 0x610b32be, 0x0b0b010c, 0x05004d3e, 0x00610605, 0x063f0606, 0x2c15824e, 0x24270028, 0x11212223, + 0x11222512, 0x25058211, 0x2b1f090d, 0x39431600, 0x21072406, 0x82152107, 0x05fe4503, 0xd6831520, 0x23270025, 0x82373337, 0x3e5f0803, 0x69033302, + 0x365a4796, 0xa2823e6d, 0x1fde011c, 0xa80133fe, 0x187ffe1f, 0x90558c98, 0x56933a35, 0x24fffed3, 0x028d1eba, 0x1ea01ead, 0x0580d28f, 0x862f2e7b, + 0xafa02024, 0xb57eb27c, 0xba2c38a6, 0x04012821, 0x7cb27ef6, 0x0073de9d, 0xfeca0001, 0x05e40357, 0x001f00dd, 0x020f405b, 0x83050001, 0x4c0223d3, + 0x58191112, 0x1820089c, 0x0527ad82, 0x05010661, 0x824d3a05, 0x01022cdc, 0x0101045f, 0x4e023b01, 0x8216401b, 0x00002515, 0x69000501, 0x5922188c, + 0x33820e40, 0x1e001f2a, 0x13111b11, 0x1b090724, 0x2323d985, 0x82150622, 0x112322d5, 0x05f14614, 0x11353e08, 0x35333523, 0x33363634, 0x42742e03, + 0x555e583d, 0x17020148, 0x798845eb, 0x2b534e44, 0x974ea7a7, 0x1bdd056a, 0x4928881e, 0xfc928d50, 0x71be9dcb, 0x47258a34, 0x55036d7d, 0x8a5a8c92, + 0x3162824f, 0x75000100, 0x61040000, 0x1c006205, 0x2c402f00, 0x535d161c, 0x07267d06, 0x0102112e, 0x01004c01, 0x004d3801, 0x60000202, 0x39333282, + 0x19294e00, 0x19090322, 0x0606012b, 0x07112123, 0x82353727, 0x33112603, 0x05172511, 0x08038215, 0x32331143, 0x04373636, 0xcefc4361, 0x336ec2fe, + 0xa1376aa1, 0x353f01c7, 0x3d018cfe, 0x808efe35, 0x2b67895e, 0xaba85301, 0x70339301, 0x7431944b, 0xfe26024a, 0xae729436, 0xab729494, 0x682ebbfe, + 0x00020059, 0x20938274, 0x08938266, 0x1f001624, 0x3f404200, 0x0b060109, 0x00050208, 0x04690506, 0x01030001, 0x01000201, 0x0a010c67, 0x005f070a, + 0x9a840707, 0x4e023931, 0x00001717, 0x1e171f17, 0x1600181a, 0x54211500, 0x0d260608, 0x012b1e09, 0x01822115, 0x23352324, 0x03833335, 0x20211128, + 0x04141504, 0xa9830323, 0x2634352b, 0x01cd0123, 0xc6acfe54, 0x08008293, 0x0142012a, 0xfe1a0103, 0x8d83f8e2, 0x92a6a496, 0x7d92fa01, 0x927debeb, + 0xd5d80290, 0x02d8e5d6, 0x87c0fdd0, 0x008491a4, 0xb5000100, 0x2b20a382, 0x1d30a382, 0x46404900, 0x0008011b, 0x05040109, 0x08004c02, 0x44081b82, + 0x03007208, 0x00860304, 0x08000009, 0x07670009, 0x01060101, 0x02010502, 0x04050067, 0x00570504, 0x5f040505, 0x04050400, 0x221c1d4f, 0x11211211, + 0x10121114, 0x2b1f060a, 0x17162101, 0x06231533, 0x23010706, 0x08ad8201, 0x37363243, 0x26213521, 0x27232326, 0x04213523, 0x77c3fe2b, 0x0698a422, + 0x81019698, 0xe8a7feea, 0x07978de1, 0x0102f4fd, 0xc1869718, 0x76030a01, 0x8335e604, 0x2cb08f7c, 0x2702b9fd, 0x7c827495, 0x7e0d5257, 0x20ab8300, + 0x36ab828a, 0x007b0526, 0x403e0021, 0x0201023b, 0x01140001, 0x4c020304, 0x82010106, 0x83032095, 0x00002c98, 0x01086107, 0x4d3e0707, 0x83030300, + 0x3904239d, 0x3c824e04, 0x20002124, 0xa0821611, 0x09241326, 0x002b1d09, 0x22065f43, 0x82211515, 0x06142a01, 0x21072107, 0x35023e35, 0x08884235, + 0x82a43408, 0x486f307f, 0x96016b67, 0x48346afe, 0xfc17a102, 0x13474b8e, 0xb15ea1a1, 0xb17b0579, 0x76373c5f, 0xe97de973, 0x9f28825d, 0x5c491897, + 0xf77dee4d, 0x8361ab6c, 0x824520a3, 0x056b34a3, 0x00170062, 0x16364039, 0x01000101, 0x0101094c, 0x82020108, 0x0768249e, 0x44060301, 0x0a2b050f, + 0x38000001, 0x0505004d, 0x7f4e0539, 0x0b270c19, 0x012b1f09, 0x84330133, 0x11212599, 0x35211123, 0x11820183, 0x33012d08, 0xfecaa103, 0xe7fee882, + 0xe7fe1901, 0x01ebfec8, 0xe2ebfe15, 0x01d584fe, 0x62050840, 0xa67d53fd, 0x01eafe7c, 0x7da67c16, 0x92fdad02, 0x4d358b83, 0x3b04cbfe, 0x3200a306, + 0x38403b00, 0x04021d20, 0x090a2403, 0x20068203, 0x258e8201, 0x0401234c, 0x26834b01, 0x03008625, 0x18020400, 0x300a5871, 0x284e0120, 0x251e1f26, + 0x07051411, 0x06002b19, 0x083e4606, 0x3233162a, 0x34353636, 0x2e272626, 0x2107c847, 0xe7471611, 0x82142008, 0x1e5e080a, 0x3b041502, 0xaa77a858, + 0x7155e890, 0x5377bc4b, 0x7e34538b, 0x66c19574, 0xaa75b565, 0x6e48a565, 0x735aa947, 0x848f3e95, 0x0168ad7f, 0x156ea51a, 0x1d01d9fe, 0x7f525d04, + 0x6d364b46, 0x4659424e, 0x96682c22, 0x609c626a, 0xfe2a010a, 0x404d0dd1, 0x633d3f7c, 0x44503a5d, 0xa3602527, 0x0082007c, 0x6801012e, 0x84035f00, + 0x07007d04, 0x21402400, 0x0328bc82, 0x01020085, 0x00008602, 0x0de26918, 0x1111113e, 0x1a060410, 0x1521012b, 0x11231121, 0x010c0233, 0xa488fe78, + 0xa1be02a4, 0x1e0442fe, 0x3b824a82, 0x01883908, 0x0429040d, 0x000f0058, 0x002f001f, 0x0237403a, 0x03070001, 0x04010306, 0x00690100, 0x04050504, + 0x04040059, 0x01086105, 0x51050405, 0x10102020, 0x2f200000, 0x26282e20, 0x0b7a6e18, 0x2b170623, 0xcf411812, 0x8e20200e, 0x0f726a0f, 0x2640ee2d, + 0x28274026, 0x41252541, 0x8a5f0228, 0x96fe210c, 0x03290c8a, 0x2641263c, 0x26264227, 0x1d441842, 0x210b8707, 0x198bd1fd, 0x42180020, 0x00230a9b, + 0x82f00302, 0x01013ddc, 0x03090114, 0x00d903c8, 0x40370016, 0x00010634, 0x00040500, 0x04006705, 0x04020300, 0x3311787b, 0x13150001, 0x0e0f1011, + 0x07090a0c, 0x16011600, 0x2b160607, 0x084e7918, 0x21352122, 0x0808c543, 0x02352128, 0x60a86759, 0xfe67a860, 0x434501bb, 0xfafd1668, 0x69150702, + 0x03bbfe44, 0x67a45dd9, 0x915da467, 0x40913f4f, 0x9383914f, 0xa8fdff2a, 0xe808b102, 0xe2040200, 0x00269383, 0x046d0121, 0x5f18038f, 0x04220ed3, + 0x5f18fb8f, 0x29080fd3, 0x0458ff8f, 0x00950569, 0x0013000f, 0x01324035, 0x074a0401, 0x07490301, 0x04000401, 0x03010685, 0x05860301, 0x01010001, + 0x06825700, 0x5f010023, 0x220a8202, 0x83114f01, 0x11133700, 0x1e060812, 0x0317012b, 0x03231533, 0x11231327, 0x11331123, 0x05820133, 0xf6032a08, + 0xca9fbc73, 0x87b672be, 0xfdb2a3a3, 0x05a3a3ff, 0x45fd1c95, 0x1d3bfda1, 0x42fea802, 0x41fe1e04, 0x1e04a1fd, 0x00010000, 0x207f82a0, 0x237f844c, + 0x0f2e4031, 0x05207d82, 0x00207d82, 0x00207c83, 0x132a7b99, 0x06061011, 0x21012b1c, 0x77882115, 0x17132134, 0x7601d602, 0x73be5ffe, 0xa4a4edb7, + 0x73c31801, 0x718bbe02, 0x1cd7022e, 0x2b000200, 0xb0045f00, 0x03007d04, 0x3828f182, 0x01063540, 0x85010701, 0x0431da82, 0x01088600, 0x03020007, + 0x00670207, 0x03040403, 0x06d84457, 0x4f040322, 0x2907994f, 0x11121111, 0x1d060910, 0xe282372b, 0x39440520, 0x82152005, 0xce152e0a, 0xe203a3a3, + 0x93026dfd, 0xa3a36dfd, 0x23de825f, 0xfda1e1a1, 0xdf820682, 0xa5002c2c, 0x3d044c04, 0x37001800, 0xa8183440, 0x45710925, 0x38698d08, 0x15170001, + 0x0a0c0d0f, 0x04050607, 0x18011800, 0x2b160607, 0x06062201, 0x22e98207, 0x8233021e, 0x42222005, 0x2c0806ee, 0xff011521, 0x10577c46, 0x8bfc7603, + 0x467c5610, 0xb3fd4d02, 0x7d7dd77f, 0x4d027fd7, 0x6f40ac03, 0x6f439144, 0xd37a9140, 0x7ad37f7f, 0x24878291, 0x030901e8, 0x07a3429c, 0x152587a2, + 0x0a0b0d13, 0x20868208, 0x08a34203, 0x86842220, 0x22098072, 0x82363634, 0x57022f91, 0x02156944, 0x16fafd07, 0x45014368, 0xb142bbfe, 0x45012905, + 0x404f4803, 0x914f3f91, 0x3006a942, 0x01ffff00, 0x030fff66, 0x01860048, 0x00840607, 0x9f6b1800, 0x03662612, 0x04480307, 0x261f857e, 0x09007602, + 0x180200b1, 0x2908c762, 0xc8000300, 0xe8039d00, 0x09824304, 0x0b000726, 0x29402c00, 0x260f8970, 0x05050400, 0x6e005704, 0x112008ba, 0x10260083, + 0x2b1c0606, 0xae412113, 0x24078206, 0xfc2003c8, 0x690387e0, 0x498306dd, 0x008e0027, 0x05c00300, 0x395b8262, 0x002f4032, 0x05000001, 0x06670001, + 0x04000501, 0x67040503, 0x02020300, 0x48195703, 0x7e180b58, 0x0727081a, 0x012b1b06, 0x72272111, 0x2208064f, 0xfdf90235, 0x230317bb, 0x6b02cefc, + 0x0b0306fe, 0xfa9cbb01, 0xd3019b9e, 0x0002009d, 0x045f008f, 0x827d044c, 0x000b2cc3, 0x05254028, 0x01020101, 0x82010485, 0x7b86200f, 0x112012cf, + 0x2305e842, 0x33112325, 0x29075d45, 0xa3a33201, 0xcb014f01, 0x6a4235fe, 0x45412005, 0x02260764, 0x00001f00, 0xbf829204, 0x06000326, 0x2e403100, + 0x0223bd82, 0x82004c01, 0x03862174, 0x02226682, 0x06825701, 0x5f020123, 0x23728204, 0x04044f02, 0x06222d82, 0x79820604, 0x05110338, 0x012b1706, + 0x17012301, 0x92040101, 0xfefa43fe, 0x3d01f844, 0x455b3c01, 0xfba33105, 0x001b04e5, 0x8e000100, 0xa90255fe, 0x0f00d007, 0x0729b983, 0x06020101, + 0x02010001, 0x05194d4c, 0x21820120, 0x01005925, 0x82610001, 0x00320808, 0x22251351, 0x2b190603, 0x23061405, 0x37272622, 0x32331616, 0x33113536, + 0x8d9da902, 0x3b426649, 0x3f2b4d2f, 0x9185ba40, 0x8a1e1995, 0x43471016, 0x3a825608, 0x18fcef30, 0xa9062204, 0x2f000e00, 0x01022c40, 0x1b4b0200, + 0x18002005, 0x2409f89e, 0x02010359, 0x2d618302, 0x00510002, 0x000e0000, 0x0424130d, 0xef4a1806, 0x23113f09, 0x33363411, 0x41726f03, 0x4c595b3b, + 0x93a1ba3e, 0x1d1aa906, 0x4d4c288a, 0x5e09a1f6, 0x34829c97, 0xff010133, 0xa103f0fe, 0x0900e808, 0x1b401e00, 0x02000200, 0x22b28285, 0x83590001, + 0x8361201c, 0x1351236d, 0xbd831211, 0x16142526, 0x26221533, 0xb12db783, 0xd8ca747c, 0x45551cb2, 0x08b19092, 0x822982b7, 0x45d62027, 0x162e0673, + 0x27402a00, 0x02010104, 0x03004c01, 0x4d830302, 0x4e860021, 0x14290fe7, 0x04191411, 0x012b1a06, 0x06ca7514, 0x2626a982, 0x32352326, 0x5f843636, + 0x5a2a2408, 0x28584e4a, 0x7b802eb2, 0xb22e807b, 0x7259d403, 0x3d0d0d40, 0x04fc5e70, 0x594bf603, 0x582d9a2d, 0x840f054b, 0xff012777, 0xa203a8fd, + 0xbf868806, 0x01000122, 0x00206c82, 0x0c047f18, 0x10131322, 0x013dbf83, 0x11150622, 0x36341323, 0x74a20333, 0xd801b27d, 0x46f605ca, 0x074cf854, + 0xff90b19f, 0x464783ff, 0x012e0b33, 0x0417ffff, 0x00e80805, 0x401e0005, 0xce82001b, 0x02008522, 0x57255782, 0x00020200, 0x2308825f, 0x11114f00, + 0x053b5784, 0x11331121, 0xfd050421, 0x5401b2fa, 0xf6d109e9, 0x000000cc, 0xfd000201, 0x180504a8, 0x08232b42, 0x11230121, 0x02211521, 0x0502b1b1, + 0xa8fdacfe, 0x009fb908, 0x01ffff00, 0x0385ff68, 0x01070048, 0x44830607, 0x4518071f, 0x68260c63, 0x48037d03, 0x1f85ff03, 0x0f8f4118, 0xaf480020, + 0x000b2e09, 0x00314034, 0x85040504, 0x03020300, 0x07344d86, 0x24190857, 0x06071111, 0x06f74b1b, 0x23152129, 0x03153311, 0x4888fe84, 0x032105c5, + 0x07cc457f, 0x3408e382, 0xff2b0003, 0x05b00458, 0x00130095, 0x001b0017, 0x124c404f, 0x4a050211, 0x04020708, 0x05010949, 0x08850506, 0x04020401, + 0x02070c86, 0x00010b06, 0x67000601, 0x057b430a, 0x01200682, 0x5e096b6f, 0x736f0732, 0x060d210a, 0x2308736f, 0x23132703, 0x21248684, 0x01031713, + 0x01398f82, 0x04213733, 0x3cecfeb0, 0x84fe5001, 0x9d82728a, 0x3001a3a3, 0xfd88738f, 0x24088207, 0xfe3cc94f, 0x33a685fb, 0xe7011dfc, 0xfe1e04fd, + 0xfe1c1602, 0x04e0fc06, 0xe180fd1e, 0x2208b682, 0x2c000200, 0x4c040eff, 0x1d000d06, 0x4a002700, 0x01274740, 0x01100001, 0x4c020102, 0x07021a1b, + 0x820a0b4a, 0x010823bf, 0xb2820907, 0x69000722, 0x077b4418, 0x03010622, 0x260f656f, 0x28131e20, 0x82111311, 0x06824c00, 0x53210321, 0x072605a8, + 0x35233727, 0xaf4a3721, 0x33332105, 0x3323b882, 0x50222305, 0x480806fb, 0xdbfe4c04, 0xfed601b1, 0x1c021e01, 0xa444bcfd, 0x1f01f63b, 0x62ab6b21, + 0xa77fd77d, 0xfc619f6c, 0x527e31fe, 0x7443528d, 0xfd010447, 0x8f6b918a, 0x8fd121f2, 0xbf801474, 0x7ad37f70, 0xfe207b01, 0x915791a5, 0x5a854a53, + 0x22cc820d, 0x82640002, 0x848420cb, 0x002630cb, 0x154d4050, 0x26070601, 0x02060501, 0x8213144c, 0x050638cb, 0x00490102, 0x05060007, 0x09670607, + 0x080a0501, 0x05000402, 0x48036904, 0x068205c6, 0x2708c648, 0x1e200000, 0x1c001d00, 0x1120cd82, 0x0b25d483, 0x252b1e06, 0x85d08307, 0x5c2120cc, + 0x17290631, 0x15021e03, 0x23060614, 0x06974b27, 0x4d022727, 0xfd1d021e, 0x32c982bb, 0x1e1e01f5, 0x6601c3fe, 0x02e7fdb3, 0x689f6c42, 0x82508f5c, + 0x3b3b21d5, 0x6c22cf82, 0xca85fa56, 0x02916b24, 0xc7839176, 0x7f1f8d24, 0xd38265b1, 0x2808ce83, 0x0024a060, 0xff3a0003, 0x0584043f, 0x001b00ab, + 0x00270020, 0x204a404d, 0x01050401, 0x021a1b4c, 0x090a4a06, 0x00490002, 0x2cbc8206, 0x07670506, 0x01090401, 0x03040203, 0x24d08267, 0x02000002, + 0x33078357, 0x015f0002, 0x00020001, 0x2621224f, 0x22272125, 0x21211427, 0x1321cd82, 0x20ca8326, 0x05945201, 0x03212328, 0x35231327, 0xce823733, + 0x82233721, 0x17323304, 0x33011713, 0x03272626, 0x37363632, 0xa1030721, 0xb3827b68, 0xf4fe2808, 0x7fa996d5, 0x9afe90d6, 0x0191bd01, 0x4d02b3fd, + 0x92df262d, 0x0ef96cfe, 0x46a23247, 0xfe10567c, 0xfd038fb1, 0x827ed23c, 0x9afe39c0, 0x911b014b, 0x91f391f2, 0x49750107, 0x653b57fd, 0x40bcfd21, + 0x00f2436f, 0x2c20d382, 0x7520d382, 0x2220d384, 0x4e39d382, 0x01274b40, 0x01120304, 0x4c020405, 0x4a00011b, 0x05021011, 0x00010649, 0x05994f07, + 0xd982c683, 0x03020423, 0x0fbf4767, 0x241c1c29, 0x1c221c23, 0x842a2322, 0x841120d5, 0x330329d4, 0x21072315, 0x33072115, 0x22240482, 0x13270327, + 0x08071249, 0x37011323, 0x06062223, 0x16231707, 0x75041716, 0x90db85ae, 0x3efe6b01, 0x4d02048f, 0x2d29b3fd, 0x66d196d9, 0x33e78279, 0xfedb0901, + 0x46b3913e, 0xf410577c, 0x30450df3, 0xdbfe6205, 0xf22ac882, 0x92fe0891, 0x3c5e014b, 0xe0827dd0, 0xfd6e013d, 0x6f40f30e, 0x64399144, 0x01000021, + 0x58ffc800, 0x9505e803, 0x4b001b00, 0x721a4840, 0x9c7208c7, 0x13997227, 0x721f0621, 0x23230e99, 0x72372135, 0x2308069d, 0x03031713, 0x3dfefee8, + 0x96fe3f01, 0xfea6013c, 0x4f73572e, 0x3cff00d3, 0x6701c5fe, 0x015dfe3c, 0x53735bce, 0x2406ba48, 0x011dbbfe, 0x05987228, 0xfe1c5226, 0x000200ca, + 0x38077f41, 0x00200017, 0x20364039, 0x0e010201, 0x02020301, 0x0001174c, 0x020c0d4a, 0x06435803, 0x01000222, 0x10444418, 0x212a222f, 0x06111121, + 0x012b1c06, 0x23153303, 0x12644101, 0x4106d543, 0xfe210561, 0x125d418a, 0x52b3cf2d, 0x404b528d, 0xdbfe6205, 0x418afd91, 0xfe280e57, 0x53915701, + 0x002c8c4f, 0x02200082, 0x8308ff42, 0x403e2cab, 0x02011f3b, 0x174c0103, 0x42040216, 0x042006fd, 0x2705444d, 0x02020506, 0x57020000, 0xf3420783, + 0x18192508, 0x20192018, 0x1325af82, 0x1b060726, 0x0eee422b, 0xea420120, 0x36322708, 0x26343536, 0xe7420127, 0x7801210d, 0x2709e342, 0x528d523c, + 0xa8fe414e, 0x280dde42, 0x07917602, 0xfb497501, 0x26b082d4, 0xfd2b8e50, 0x4c0200bc, 0x132608af, 0x49001700, 0xfd454640, 0x05002e09, 0x00850506, + 0x86040204, 0x0602070a, 0x05fb4509, 0xfb450820, 0x45068205, 0xf0580afb, 0x13112509, 0x0b111111, 0x3c17f745, 0x04213733, 0x3c88fe4c, 0x20feb401, + 0xae82728a, 0x4101a4a4, 0xfe88738f, 0xfe3cda45, 0x12ef45ea, 0xe17efe23, 0x3b008200, 0x00780001, 0x04380491, 0x000b004e, 0x00234026, 0x00030100, + 0x01010557, 0x03020104, 0x2505ba51, 0x03005f03, 0xc44d0300, 0x06102905, 0x012b1c09, 0x15211133, 0x35060451, 0x01aeff01, 0xae75fe8b, 0x870179fe, + 0x6ffe4e04, 0x0172fe9e, 0x57849e8e, 0x1d02dc24, 0xd763d403, 0x0f055008, 0x06021025, 0x82132b18, 0x02dc2747, 0x0208fdf8, 0x3384a8c5, 0xff00f126, + 0xcf03bf03, 0x06378b82, 0x010105b3, 0x37012b32, 0x07170717, 0x37270727, 0x58023727, 0x87f374f3, 0xda022302, 0x0c8776f5, 0x3b827620, 0x00032a08, + 0x035600dc, 0x008d04d4, 0x0013000f, 0x403c0023, 0x01010639, 0x01020000, 0x02006900, 0x02050300, 0x01076703, 0x05040405, 0x2b068259, 0x00610405, + 0x51040504, 0x00001414, 0x2008c462, 0x223a8210, 0x1808260e, 0x20121c54, 0x62a78201, 0x02270fc2, 0x2626417f, 0x84272741, 0x84fe2105, 0x0121c583, + 0x2a128aa3, 0x40268d04, 0x25412726, 0x82274125, 0x34fe2308, 0xc362b19f, 0xc800210d, 0x21085f7b, 0x4e180007, 0x624309ab, 0x11112610, 0x09041011, + 0x08934c1a, 0x2d098f4c, 0xa2e0a280, 0xc8000100, 0xe8033200, 0xbf77aa04, 0x0b53423b, 0x44233721, 0x133a0557, 0xe8030717, 0x0185f6fe, 0xb011fe8f, + 0x01a68e69, 0x74fe8606, 0x68b1ec01, 0x7883038f, 0x3cd6fe23, 0x237f82ee, 0xf2382a01, 0xaa248382, 0x08043c00, 0x063d8382, 0x04b30600, 0x2b320101, + 0x15013713, 0xaa012701, 0xfd03035b, 0xb9026305, 0xfe8f1b04, 0x05356824, 0x2f8e0020, 0x2f840520, 0x17013908, 0x01070101, 0x5b0303aa, 0xb90247fd, + 0x0205fd63, 0x8fdd01cd, 0x56fe57fe, 0x00dd018c, 0x00020000, 0x030000cb, 0x006704e3, 0x000a0006, 0x061e4021, 0x02030405, 0x4a000601, 0x23106052, + 0x18060217, 0x20088087, 0x21152101, 0xce024acb, 0x024a32fd, 0x02a2fd7f, 0x0309fdf7, 0xbbfe9bcc, 0x97c9fec3, 0xe3fd0101, 0x8e5a82a3, 0x4022225b, + 0x215b851f, 0x5c980700, 0x0523ad82, 0x83110107, 0xcf02295c, 0x0281fd49, 0x31fd497f, 0x222b5c84, 0xfe974501, 0x019cfcf0, 0x8344fe37, 0x0002225c, + 0x2fb782dc, 0x003a04d4, 0x000f000b, 0x22b04b55, 0x1f405850, 0x230a6043, 0x5f000303, 0x3b2f8482, 0x0606004d, 0x07005f07, 0x4e073907, 0x431d401b, + 0x06220d82, 0xf8820300, 0x59231f88, 0x85110b40, 0x08102300, 0x90431e09, 0x2993820d, 0x01b2ff01, 0xb2ddfe23, 0x0683ddfe, 0xfdf80230, 0xfe3a0408, + 0xd9fe9dd3, 0xfd9d2701, 0xef82a194, 0x01b22608, 0x03fe0332, 0x001900b5, 0x405b0033, 0x02080958, 0x15160300, 0x23020102, 0x07040222, 0x05022f30, + 0x084c0406, 0x050a6301, 0x9e826920, 0x0007012b, 0x04006901, 0x59040506, 0x230b8209, 0x06070506, 0x04350e82, 0x05006105, 0x1a510504, 0x1a00001a, + 0x2d321a33, 0x2025272b, 0x2e55821e, 0x24252418, 0x2b19060a, 0x16171600, 0x5f323316, 0x80180852, 0x122009e9, 0x01321998, 0x22395afe, 0x3d2d1830, + 0x83287d1c, 0x3a593d64, 0x0c852f23, 0x3e628524, 0x1987385a, 0x82638421, 0x3719890c, 0x2324b503, 0x32351616, 0x236b4f42, 0x35151622, 0x6e4e4231, + 0x222485fe, 0x0a821382, 0x08826c20, 0x1c831520, 0x006d2108, 0x01500001, 0x036004c2, 0x001c002b, 0x6406b13c, 0x0a314044, 0x03020209, 0x01021718, + 0x044c0200, 0x0022f383, 0xf3820203, 0xe34d0120, 0x0000320c, 0x1b001c00, 0x05252525, 0xb12b1909, 0x00440006, 0x21c18d16, 0xdc862726, 0x33023e2e, + 0x3f56ce01, 0x243e2d2a, 0x812b5e3a, 0x09234418, 0x5b3c2908, 0x5426812c, 0x2b03537d, 0x2a253021, 0x404f5828, 0x2d209177, 0x562a2b26, 0x724c3f51, + 0x0100004b, 0x0301dc00, 0xc102d403, 0x2609534d, 0x02000086, 0x82570002, 0x5f022a7d, 0x02000200, 0x1011114f, 0x31818203, 0x23112113, 0x02dc2111, + 0xb4fdacf8, 0x42fec102, 0x22821f01, 0x8800012c, 0x28041e04, 0x06009006, 0xdb842100, 0x18041621, 0x2509274b, 0x01010102, 0x3e851276, 0x0139c083, + 0x01230133, 0x02022301, 0xcb7a01ac, 0xfbfef9fe, 0xfd9006c9, 0xfece018e, 0x084a8232, 0xff030030, 0x04eb00f2, 0x000304bd, 0x00250017, 0x40480033, + 0x14202945, 0x05040408, 0x03084c01, 0x070a0202, 0x04050309, 0x06690502, 0x00000401, 0x06825904, 0x61000422, 0x04346d82, 0x26265100, 0x00001818, + 0x32263326, 0x25182d2f, 0x1b1d2418, 0x162a4482, 0x0b242424, 0x002b1906, 0xe54f1516, 0x064c0805, 0x26222306, 0x33363435, 0x36171632, 0x15043336, + 0x32331614, 0x27373636, 0x0423022e, 0x17070606, 0x3233021e, 0x23263435, 0x94942904, 0x3894699c, 0xa16b8f38, 0x699c9393, 0x8d3a3d90, 0x441efd6a, + 0x354d3446, 0x311e0921, 0x1a02334c, 0x1d300983, 0x8a334c32, 0x03044644, 0xd8b3b3da, 0x84777f7c, 0x46080783, 0x8477817a, 0x7b7cf794, 0x14576d48, + 0x023c5141, 0x13576c48, 0xf73d543f, 0x00007a7d, 0xfe310003, 0x058004f9, 0x0019001f, 0x002d0023, 0x2b434046, 0x0420212a, 0x010d0203, 0x4c020300, + 0x01021819, 0x020b0c4a, 0x47004900, 0x6923060f, 0x82030105, 0x82592037, 0x00032206, 0x34098261, 0x24245100, 0x2d241a1a, 0x231a2c24, 0x272b221a, + 0x2b180606, 0x06fe4b01, 0x07272223, 0x07e14c27, 0x37173226, 0x06060017, 0x1726e382, 0x12232613, 0xd8823636, 0x03275908, 0x4e033316, 0x944c8b5b, + 0x292f97fe, 0x5b509b4f, 0xfc944d8c, 0x4e302d96, 0xa056fe9b, 0xee515d5a, 0xa25f1c21, 0xeb515c5f, 0xfd031a1e, 0x6bc0962d, 0x0794fd96, 0x2df92ef6, + 0x966bc196, 0xf00894fe, 0x6badfe2d, 0xba706db7, 0x05e70233, 0xb76ce1fc, 0x33b96f6d, 0x00051afd, 0x012d0082, 0x47007500, 0x1e043b04, 0x19000600, + 0x14074240, 0x2b190622, 0x32060342, 0x01e2e601, 0xcbfeae73, 0x04adcafe, 0x0329fc1e, 0x8fb8fc48, 0x401f2643, 0x0001051c, 0x05576d01, 0x85010022, + 0x76201f82, 0x8308556d, 0x230121f4, 0x012c4c82, 0x8dfe3b04, 0xad8ffee2, 0x35013601, 0xd7244a84, 0x4803b8fc, 0x852d8f84, 0x2b044800, 0x15008b04, + 0x24402700, 0x284b8202, 0x01048600, 0x03010103, 0x23068259, 0x00610103, 0x51200c82, 0x15262982, 0x24141400, 0x9d820514, 0x16160024, 0xf8501115, + 0x06222205, 0x3a0a8406, 0x02333636, 0xa27dd7d7, 0x53538c52, 0x7da2528c, 0x8b047fd7, 0xfd7fd67e, 0x82700290, 0x8315820f, 0xd67f2809, 0x0001007e, + 0x82180085, 0x005b266f, 0x40260015, 0x206f8423, 0x22628285, 0x82590103, 0x610321c5, 0x01217382, 0x2a6e8d03, 0x35262624, 0x14113311, 0x51331616, + 0x11260566, 0x23060614, 0x6e8cd901, 0x6d821820, 0xfd700223, 0x836d8590, 0x206d8309, 0x05ef5200, 0x06220438, 0x001a00a9, 0x02344037, 0x10030001, + 0x00020203, 0x0201010f, 0x6d824c03, 0x02000025, 0x51690003, 0xef820fe7, 0x19001a25, 0x85242525, 0x071724ef, 0x82222326, 0x052143e9, 0x20070753, + 0x0aa35234, 0x520a1053, 0xfa2109ad, 0x081a5304, 0x97fc0523, 0x2154829c, 0xdf53ffff, 0x02022208, 0x33108245, 0xfe360001, 0x057a0455, 0x000b0062, + 0x09204023, 0x04040508, 0x0c7f8318, 0x0133ac82, 0x134f0100, 0x04101113, 0x132b1a06, 0x11231521, 0x82211107, 0x36233103, 0xbba54404, 0xa7bd80fe, + 0xf99d6205, 0x700617a7, 0xf3830484, 0x0000c124, 0x5382ed03, 0x33000c2c, 0x050b3040, 0x01020304, 0x4982010a, 0x010c4c25, 0x554b0101, 0x5d180970, + 0x11200d8d, 0x29086389, 0x01150121, 0x35211521, 0x03c10101, 0x01b2fd2c, 0x027ffe81, 0x01d4fc4e, 0x0547feb9, 0x30fea062, 0xa12bfe7c, 0x021002a0, + 0xc3840012, 0x0000282f, 0xc7067705, 0x26000800, 0x07082340, 0x216f8206, 0x665a4c01, 0x03102416, 0x832b1906, 0x23013c5c, 0x03013701, 0xfef9017e, + 0xd949fe8f, 0x01aab2fe, 0x9fc7060b, 0x9203d8f9, 0x85f8fc39, 0xaa240857, 0x070455fe, 0x1d001e04, 0x2a402d00, 0x0202061b, 0x02020c01, 0x4c020200, + 0x03031011, 0x01034900, 0x4d3b0101, 0x00210f82, 0x3c2f8261, 0x134e003f, 0x04281824, 0x012b1a09, 0x26071714, 0x06062726, 0x27262223, 0x11151616, + 0x08404207, 0x11373708, 0x33d40333, 0x051a0eb3, 0x4c4e952e, 0x0e0d2757, 0x4716c0bd, 0x30825249, 0x9f5601c0, 0x631a18b7, 0x2b5b4c2a, 0x285b3f38, + 0x0517e3fe, 0x74b0fdc9, 0x44544a86, 0x6082fc02, 0xa600023f, 0x0904e7ff, 0x16007f05, 0x33002500, 0x13223040, 0x01030202, 0x0101164c, 0x0401004a, + 0xc9921801, 0x17172914, 0x24172517, 0x0527262c, 0x0424f683, 0x14111204, 0x262f9684, 0x36363435, 0x17163233, 0x12270026, 0x42150606, 0x4d0805de, + 0x26263537, 0x01420123, 0x92350100, 0x7786c66a, 0xae6473c3, 0x32925c6a, 0xfee3fe11, 0x393963ee, 0x7f774669, 0x4e7b3c01, 0xd8437f05, 0xfdfea8fe, + 0x6c8ef89c, 0xca8189cc, 0xce465370, 0xfd431701, 0x5c8242dc, 0xc24a8a5c, 0x4c5533ba, 0x1b540100, 0x00032908, 0x000e4011, 0x85000100, 0x76321482, + 0x06021011, 0x33012b18, 0x00022311, 0xe808b2b1, 0x1a82c0f4, 0xfeff0132, 0x086004e2, 0x000b00e8, 0x050d4010, 0x49000204, 0x2b08f282, 0x06011a76, + 0x14012b17, 0x07171612, 0x35020226, 0xb1023311, 0x689ab75e, 0xb273dbab, 0xfec5bc02, 0x688df7d7, 0x0118018d, 0x2c06dd58, 0x22063b54, 0x85960660, + 0x06072443, 0x834a0002, 0x84102043, 0x73232043, 0x15330876, 0x73b1b102, 0x9968abda, 0xa8fd5eb8, 0x01dd1405, 0x82180158, 0xfef62346, 0xb38cc6d7, + 0x14401722, 0x00269882, 0x01010285, 0x48827601, 0x03000324, 0x8e830311, 0x1333112a, 0x01b1ff01, 0x400ba8fd, 0x0025bb84, 0x02e2fe50, 0x83bb87b1, + 0x85bb8477, 0x11333d77, 0x07020214, 0x12363627, 0xb2ff0135, 0x68abdb73, 0x085eb79a, 0xddd4f9e8, 0xe8fea8fe, 0xf72b7782, 0x00c52901, 0xfd500001, + 0x87b002a8, 0x84ff83bb, 0x20ff85bb, 0x96591834, 0x23113107, 0xb85eff01, 0xdaab6899, 0xbc02b173, 0xf62901c6, 0x43084082, 0xa8fee8fe, 0x00ecfadd, + 0xff200005, 0x059104d5, 0x00030089, 0x001f0013, 0x003b002f, 0x02514054, 0x01010301, 0x0002004c, 0x00020500, 0x05010a69, 0x0607010b, 0x09690705, + 0x01030301, 0x01010861, 0x004d3e01, 0x093c6d18, 0x2030302d, 0x04141420, 0x303b3004, 0x5d34363a, 0x1433053d, 0x1a1e141f, 0x04130418, 0x090c2a12, + 0x01372b17, 0x52120117, 0x4a5a0616, 0x65062007, 0x31780a54, 0x3f1b8b0f, 0x76850352, 0x84db78fc, 0x5a844545, 0x4647855a, 0x473c5a86, 0x453c3c47, + 0x82023d44, 0x83464584, 0x2508148e, 0x466e051b, 0xa60592fa, 0x58589255, 0x93575793, 0x55925858, 0x5d5f627e, 0x63636369, 0x5678fd5e, 0x92585991, + 0x1c825757, 0x7e56922b, 0x695c6161, 0x5e646263, 0x08008200, 0x24000727, 0x8d04e8ff, 0x0f007b05, 0x1f001b00, 0x3f002f00, 0x57004b00, 0x6f407200, + 0x0302011d, 0x0200011e, 0x0005011f, 0x08174103, 0x070f2c08, 0x1105030e, 0x0903100b, 0x69090508, 0x0303010d, 0x010c6101, 0x4d3e0101, 0x0808010a, + 0x01066104, 0x043f0404, 0x404c4c4e, 0x5e303040, 0x4c2d0559, 0x52564c57, 0x404b4050, 0x3044464a, 0xd949183f, 0x1b102509, 0x14161a10, 0x0e227882, + 0x354e1226, 0x0b0d4112, 0x17010123, 0x0f414e01, 0x0f8c4318, 0x59410420, 0x8a20200a, 0x012a080b, 0x424276aa, 0x784d4b75, 0x4c794444, 0x44313045, + 0x42303042, 0x3004c4fe, 0x01d1fb30, 0x42437654, 0x774d4c76, 0x4c784343, 0x288a7702, 0x90fd3c08, 0x44433232, 0x01442f2f, 0x443332e8, 0x41313141, + 0x7c437b05, 0x427b5352, 0x51537b42, 0x566f447c, 0x5a5c4b4c, 0xfd574b4d, 0x7599017a, 0x440767fe, 0x7c53527b, 0x537c4242, 0x88447b52, 0x2728830b, + 0x5d4b4b57, 0x574b4e5a, 0x5b310783, 0xff584a4d, 0xfe6901ff, 0x004703da, 0x060701bc, 0x147b5782, 0xd2026926, 0xb4044703, 0x7b571f85, 0x3e3f820f, + 0x038700ad, 0x00a70401, 0x00070402, 0x00020000, 0x0400002c, 0x0092044c, 0x00190015, 0x5b2f4032, 0x063b1aa9, 0x05040501, 0x1616164f, 0x15191619, + 0x22212621, 0x2b1b0607, 0x33363612, 0x56211521, 0x0a84063f, 0x35262631, 0x15213513, 0x7fd77d2c, 0xb3fd4d02, 0x82528d52, 0x2e098302, 0x387dd77f, + 0x4503e703, 0x57917ad3, 0x82535391, 0xd37a2604, 0x8f3afd7f, 0x2087838f, 0x20878264, 0x23878684, 0x0029402c, 0x2205004d, 0x82010067, 0x00012117, + 0x21107154, 0x81831411, 0x1c060631, 0x0606002b, 0x21352123, 0x35363632, 0x84262634, 0x1616230a, 0x94820115, 0x82840421, 0xb3fd2382, 0x82854d02, + 0x82820983, 0x03e1fb27, 0x0219fce7, 0x21858d47, 0x034c8fc9, 0x4b3e2d0c, 0x585009b0, 0x02001640, 0x71020101, 0x220fe74e, 0x4615401b, 0x592114f9, + 0x067759b5, 0x7d821320, 0xdc23112b, 0xb4fdf802, 0x9fc102ac, 0x05ef51fe, 0xfe0f0125, 0x5ab102f0, 0x002308cf, 0x48850002, 0x11200f94, 0x39060f5a, + 0x06141133, 0x36323523, 0xb2ff0135, 0x7c74cad8, 0x49f7e808, 0x459290b1, 0x8b830055, 0xa8fdff24, 0x4782da03, 0x2a00162a, 0x01122740, 0x4c010102, + 0x4d821682, 0x03020323, 0xf45d1886, 0x1114280f, 0x06041014, 0x49012b1a, 0x1520055f, 0x2209cf49, 0x83022e37, 0x5a2e205f, 0x283c05c9, 0x5a4b4e59, + 0xfae8082a, 0x2d584bf1, 0x4b592d9a, 0xfc030afc, 0x0d3d705e, 0x5972400d, 0x00277682, 0xfd0e0101, 0x5ab102a8, 0x022109cf, 0x05234d01, 0x02211d83, + 0x21ce8261, 0xcf5a5102, 0x16323a07, 0x11231315, 0x01232634, 0x01d8ca0e, 0x06747db2, 0xf8b19088, 0x54b40761, 0x36ff4546, 0x17ffab24, 0xf382b102, + 0x24000525, 0x82032140, 0x850221f3, 0x3b122772, 0x11050005, 0x18060411, 0x2111012b, 0x02112135, 0x01fafdb1, 0xf6e80854, 0x34099d2f, 0x0021c384, + 0x29c382ab, 0x006106b0, 0x40250005, 0x42820022, 0x4c838620, 0x57020122, 0x2005a967, 0x20598200, 0x8a29824f, 0x82232048, 0xb0022b4a, 0x06acfeb1, + 0x0847f761, 0x1d829f1a, 0xa0243682, 0x4c045f00, 0x26317363, 0x08034401, 0x63a4f8fc, 0x01220b73, 0x7b602c00, 0x52152006, 0x21261b8d, 0x04222126, + 0x71431a06, 0x146d4316, 0x42f00221, 0xb8820ce4, 0x2c000224, 0xb78257ff, 0x1500f63c, 0x49002100, 0x01174640, 0x4c010204, 0x05021c1d, 0x08030049, + 0x03010001, 0xdd826700, 0x0104022b, 0x01076702, 0x04050504, 0x22068257, 0x435f0504, 0x013405fd, 0x1f202100, 0x191a1b1e, 0x0c121418, 0x0007090a, + 0x09150115, 0x2106fb60, 0x72601415, 0x1701220f, 0x05a35907, 0x21352124, 0x0844ff01, 0xd77d350c, 0xfe4d027f, 0x0139913f, 0x6443fe68, 0x97fe3996, + 0x6504c001, 0x20091644, 0x29b9827f, 0x6148d3fc, 0x5e4ba98f, 0x9182008f, 0xa5006424, 0x9f618404, 0x22bb6307, 0x12151725, 0x840f1011, 0x079f61a3, + 0x4f473220, 0x052d4406, 0x06823720, 0x23022e26, 0xb1023521, 0x33058f61, 0x4d02b3fd, 0x10567c46, 0x76038bfc, 0x467c5710, 0x3d04b3fd, 0x27069761, + 0x91436f40, 0x91406f44, 0xab41878a, 0x0aa54405, 0x00570124, 0xd1780101, 0x07ab4106, 0x44159b44, 0x01211597, 0x0eac41f2, 0x64000224, 0xf38257ff, + 0x2605ab41, 0x1739403c, 0x41000401, 0x002408ab, 0x02030102, 0x41081e45, 0x112312aa, 0x83161113, 0x06082287, 0x1723451e, 0x950a9e41, 0x07fe2193, + 0x210ca041, 0xa28cab02, 0x410efe21, 0x492c0a9f, 0x67047b00, 0x07002704, 0x1d402000, 0x270f1d45, 0x00010103, 0x11114f01, 0x3408e04c, 0x11231121, + 0x1e044921, 0xfea443fe, 0xa2270443, 0x0a03f6fc, 0x28008200, 0x00640001, 0x0410045f, 0x2d47827d, 0x0028402b, 0x85000300, 0x01020100, 0x42710486, + 0x27068205, 0x005f0203, 0x4f020302, 0x07222d82, 0x53820700, 0x19060526, 0x3311012b, 0x352f5183, 0xa3a36d03, 0xbe02f7fc, 0xe2fbbf01, 0x82a1be01, + 0xff8e263e, 0x06c0030b, 0x06075e98, 0x40482b08, 0x06011645, 0x12134b01, 0x054a0002, 0x49010204, 0x00000107, 0x06000506, 0x05010867, 0x0304010a, + 0x09670405, 0x01010301, 0x06825703, 0x5f010323, 0x270a8202, 0x1a1b4f01, 0x11131819, 0x2f054c65, 0x1f060b10, 0x1133012b, 0x37270721, 0x13333523, + 0x21250383, 0x17132127, 0x20838203, 0x08d98201, 0xa51b0335, 0xa23ff9fd, 0x78a57e34, 0xfe72d4ac, 0xd001176f, 0x78dda24f, 0x01effe07, 0x6205a118, + 0x2bf59efa, 0xd3019bca, 0x9cbb019d, 0xfc2f3601, 0xfbbb01a2, 0x82d301d5, 0x018832ab, 0x04290406, 0x000f0051, 0x002f001f, 0x063a403d, 0x2c9d8201, + 0x69000103, 0x03070508, 0x03020203, 0x27088459, 0x04610203, 0x02030201, 0x4a1b7e67, 0x0f8f0f20, 0x2e0f0249, 0x25418002, 0x27284125, 0x40262640, + 0x8ae5fe27, 0xae02210c, 0x04210c8a, 0x0b656751, 0x8b0d7367, 0x00002319, 0xc3650300, 0x8207200a, 0x402c30d3, 0x02030729, 0x85010401, 0x00020206, + 0x5c860005, 0x58550f45, 0x1e062408, 0x6623372b, 0x4d6305a0, 0xa3ce3607, 0xa43e01a3, 0x013d01a4, 0xa399fe67, 0x1e045fa3, 0x1e04e2fb, 0x075463fe, + 0x45000121, 0x5360078f, 0x4c042342, 0xa545f8fc, 0x0c536005, 0x2309b763, 0x000a0007, 0x0a36cd82, 0x01040201, 0x0101034c, 0x00850100, 0x86020402, + 0x04040000, 0xfa825700, 0x005f0426, 0x4f040004, 0x102cd083, 0x2b1b0605, 0x33132101, 0x33012301, 0x33080782, 0x0a024e01, 0x43fed268, 0xc744fefa, + 0x52fe4402, 0x010b04d8, 0x059efa57, 0xfd0afe62, 0x00010034, 0x04610049, 0x000d0467, 0x40270007, 0x03010424, 0x02850300, 0x8205105f, 0x01002306, + 0x0c82005f, 0x350ffb42, 0x35211521, 0xaa021121, 0xe2fbbd01, 0x0d04bd01, 0xa2a2f6fc, 0x87820a03, 0xffffff35, 0x043b01f2, 0x015304bd, 0x00d50406, + 0xb1080050, 0x18b00300, 0x27084361, 0x042c007e, 0x00b80440, 0x37093b58, 0x01150135, 0x037e0135, 0x033efcc2, 0xb7010409, 0xfeb314fe, 0x8f01b713, + 0x20059b43, 0x202f8270, 0x582f8632, 0x1521063b, 0x20318201, 0x3a2f8270, 0xfc0903f7, 0x01cc023e, 0x71feb7ec, 0x01b771fe, 0x00ffffed, 0x04410078, + 0x82fe0338, 0x18c6207b, 0x320f5360, 0x0000e6ff, 0x3e05ca04, 0x14000e00, 0x0d0e1140, 0x58020609, 0x3a080551, 0x01177600, 0x012b1706, 0x26010701, + 0x23112726, 0x07060611, 0x58022701, 0xfe727202, 0x183a2ddc, 0x2c3b18ba, 0x0572dcfe, 0x7eccfd3e, 0x43270e01, 0x04cffb2d, 0x27432d31, 0x827ef2fe, + 0x012508a4, 0x90004500, 0xb3046b04, 0x5a001100, 0x502eb04b, 0x020e4058, 0x11010001, 0x02000201, 0x0201014c, 0x10401b49, 0x270c8211, 0x090a4c01, + 0x4a000302, 0x59201283, 0x15212885, 0x20238200, 0x0f544886, 0x09401b23, 0x05a94900, 0x76024208, 0x1111b559, 0x19060344, 0x0127372b, 0x22230606, + 0x05372527, 0x26030713, 0xc4373435, 0x2df1027f, 0x300f2542, 0x030a90fe, 0x17b52c42, 0x7f901401, 0x0709f302, 0x2cac1302, 0x010baffc, 0x4f1d0f83, + 0x265c825a, 0x04270025, 0x82fd048b, 0x402723f7, 0x9a820124, 0x0e4c0127, 0x034a0101, 0xf78d1802, 0x17390813, 0x2b180602, 0x01270209, 0x21373636, + 0x26262135, 0x61020127, 0xd6fd2a02, 0x2806018a, 0xb6fc2545, 0x362b4a03, 0x04fafe31, 0xfd95fdfd, 0x20017595, 0xa618402b, 0x0135331b, 0x060b4120, + 0x6b044d28, 0x11007004, 0xe2855200, 0x820f0b21, 0x4c0129ef, 0x00021011, 0x0b401b4a, 0x0f250784, 0x02030708, 0x08034149, 0x2008954a, 0x82661857, + 0x0d034109, 0x15114127, 0x2b190603, 0x08f68301, 0x03171334, 0x36252705, 0x17163233, 0xb2033701, 0xb5170114, 0x0abefc2c, 0x0f307001, 0xfd2d4225, + 0x7d017f0f, 0x0f1d4f5a, 0xfc0a8201, 0x13ac2caf, 0x02090702, 0x9b837ff3, 0xffe6ff35, 0x04ca04bb, 0x000e00fa, 0x0c124015, 0x05060708, 0x50070004, + 0x1d250590, 0x2b170601, 0x08f28225, 0x01170135, 0x16013701, 0x33111716, 0x3b18b502, 0x7224012c, 0x8efd8efd, 0x2d240172, 0xc8ba183a, 0x0127442d, + 0xccfd7e0d, 0xfe7e3402, 0x2d4229f3, 0x01003204, 0x87004500, 0x07ff41f3, 0x83011121, 0x200482c9, 0x82fc824c, 0x831020f6, 0x84012010, 0x090a240c, + 0x89000302, 0x000223fb, 0xeb4b8502, 0x00092111, 0x00201785, 0x8209ff41, 0x82362098, 0x172308f4, 0x03250705, 0x15161337, 0xec030714, 0x2d0ffd7f, + 0x300f2542, 0xfc0a7001, 0x17b52cbe, 0x70041401, 0x420dfd7f, 0x03290501, 0x7efe0a51, 0x5a4f1d0f, 0x205f8200, 0x0c034200, 0x01010e23, 0x248d8300, + 0x0c0d4a00, 0x0c175402, 0x18820020, 0x15114f26, 0x2b180602, 0x30087082, 0x21070606, 0x16162115, 0x01070117, 0xfe8a4f02, 0x2b3631fa, 0xb6fc4a03, + 0x01284525, 0xd6fd8a06, 0xfe75fd04, 0x1b3335e0, 0x2b4018a6, 0x0275e0fe, 0x826a826b, 0x090f4341, 0x21090342, 0x03420102, 0x1b492c05, 0x080f0b40, + 0x4a020307, 0x41021011, 0x68180a07, 0x1b21133d, 0x0b074140, 0x85060342, 0x272908fa, 0x05172513, 0x26222306, 0xfe070127, 0xb5170114, 0x0a42032c, + 0x0f3090fe, 0x022d4225, 0x83037ff1, 0x0f1d4f5a, 0x030b7dfe, 0x05024251, 0x7f0dfd22, 0xff2e9b84, 0x0559005a, 0x00c80456, 0x402c0018, 0xed820c29, + 0x184c012f, 0x040d0e17, 0x0a0b4a01, 0x00040102, 0x0f8c4349, 0x0c411c20, 0x01510805, 0x37363727, 0x17161621, 0x01010717, 0x06060717, 0x26262107, + 0x05372727, 0x8a09fe56, 0xfc484ad3, 0x2845253c, 0x03fe8ad9, 0xd98bfc01, 0x032a3533, 0x33352ac4, 0x92028bd5, 0xed76c7fd, 0x40182e55, 0x0276ed2b, + 0x76360239, 0x1b3137ea, 0xea37311b, 0x2f8f8576, 0x047ffee6, 0x00cb06ca, 0xb3060019, 0x3201000d, 0x42088544, 0x90440c8b, 0x3b2c250b, 0x2d3a1818, + 0x83099742, 0x3b28080f, 0x72dcfe2c, 0xccfdcb06, 0x270e017f, 0xcff92d44, 0x0127432d, 0xccfd7f0e, 0xfe7f3402, 0x2d4327f2, 0x442d3106, 0x7ff2fe27, + 0x023a7482, 0x73002700, 0x71048004, 0x0a000300, 0x2b402e00, 0x00020105, 0x0301010a, 0x75444c02, 0x03012205, 0x116f6a01, 0x47491320, 0x33210806, + 0x01132311, 0x21152113, 0xadad2711, 0x010102d1, 0x7afe8601, 0x02fc7104, 0xb601ff01, 0xfea69dfe, 0x2362829d, 0x30000200, 0x89206382, 0x402c6386, + 0x01053d40, 0x01060003, 0x01070302, 0x67820482, 0x85000323, 0x210a8204, 0x18828601, 0x03020223, 0x49068257, 0x04290764, 0x04000004, 0x090a040a, + 0x08a08208, 0x0611033e, 0x252b1706, 0x01113311, 0x11010113, 0xdc033521, 0x012dfdad, 0xfefd0102, 0x03737afe, 0x0202fcfe, 0xfe630152, 0x014afe4a, + 0x0000a663, 0xff380001, 0x048204c2, 0x00180042, 0x0c364039, 0x0b206c82, 0x022b6682, 0x01010a4c, 0x00010449, 0x18020300, 0x6d12ee6a, 0x09260559, + 0x01180007, 0x716f0518, 0x1123210b, 0x33227382, 0xe64f3632, 0x35232605, 0xbb6eeb02, 0x0802826e, 0xf8fdab23, 0x40ab0802, 0x6d40406e, 0x42049341, + 0x706fbb6e, 0xb0fe6dbb, 0xa301a301, 0x6f41b0fe, 0x3f6d4140, 0x208b82ad, 0x2dc8823a, 0x009a0549, 0x402c0008, 0x02010829, 0x8b840700, 0x4a211982, + 0x5bc28200, 0x112412ed, 0x2b190603, 0x113ce682, 0x11051123, 0x02420201, 0xbffec607, 0x9a05f8fd, 0xb8fbaefe, 0xfe01a603, 0x00a301af, 0x01220082, + 0x5b826700, 0x5b877620, 0x6e440120, 0x82578208, 0x0100225b, 0x119d6986, 0x5b831320, 0x11020923, 0x2b5c8225, 0x026e0221, 0xfef8fd08, 0x0702c6bf, + 0x5d295c82, 0x51015dfe, 0x045afc01, 0x265b8448, 0x04c4ff3a, 0x855e0549, 0x820620b7, 0x840520b7, 0x010424b7, 0x45004901, 0x142213ab, 0xb7841011, + 0x2111333c, 0x11010111, 0xc6830305, 0xf8fdf9fd, 0x41010802, 0xb8fb5e05, 0xa301aefe, 0xba82a301, 0x01000024, 0x5b826700, 0x5b877620, 0x02010023, + 0x24bb8401, 0x0001024c, 0x16556a49, 0x2124b787, 0x25113311, 0xfd27b785, 0x4101c6f9, 0x83fe0a03, 0x045225b7, 0x015afc48, 0x8734b784, 0x7307edff, + 0x20007305, 0x31403400, 0x18191a1b, 0x07151617, 0x4c216282, 0x08db5e04, 0x820e896c, 0x00203036, 0x1611261f, 0x2b190605, 0x15120400, 0x6b040214, + 0x33080576, 0x23262634, 0x15060622, 0x01173715, 0x35173701, 0x33241234, 0x45017005, 0xbbfebebe, 0x90f691c0, 0x9191f690, 0x72fc90f5, 0x47fe38fe, + 0x01bef076, 0x7305c045, 0xc0241a83, 0xacbebbfe, 0x902d1c85, 0xe08291f5, 0x0164fe7f, 0x84e27f9c, 0x823a82c0, 0xed0125ff, 0xd908edff, 0x2d2da384, + 0x05202a40, 0x01020304, 0x01000106, 0x2e96184c, 0x18022009, 0x820c3f6f, 0x0429259b, 0x012b1a06, 0x96868686, 0x16161425, 0x18221533, 0x820719ad, + 0x081529b8, 0x47fe7663, 0xfc7238fe, 0x9f857682, 0x98838a83, 0x03217a83, 0x2188850e, 0xb58282e0, 0xac202185, 0xb6831b87, 0x0000843a, 0xff000002, + 0x06b004e8, 0x000c0080, 0x40300013, 0x03010e2d, 0x0205064a, 0x003ea182, 0x67000304, 0x01010400, 0x04005704, 0x005f0104, 0x4f010401, 0x130d0d0d, + 0x1311130d, 0x216b3313, 0x01480805, 0x06141121, 0x26222123, 0x25211135, 0x11330101, 0x58021121, 0xaefe5802, 0xbcfe2d37, 0xaefe372d, 0x82fed603, + 0x01d682fe, 0xfd800650, 0x2d20fcac, 0x032d3737, 0x7a015ae0, 0xbafb86fe, 0x02004604, 0x1a00b0ff, 0xca040005, 0x32247f84, 0x01012f40, 0x4c267a82, + 0x0102000e, 0xaa48134a, 0x03022306, 0x6e180201, 0x132911f5, 0x06042325, 0x02092b1a, 0x327d8411, 0x21333634, 0x21150105, 0x02152111, 0xfd5402ac, + 0x8368fdac, 0x98023e6b, 0x86fed401, 0xfe0202fd, 0xa8fdca04, 0x6001a8fd, 0x28012d37, 0x01f8372d, 0xc0fede7e, 0x24ff84de, 0x05b00444, 0x317f84dc, + 0x1239403c, 0x49040206, 0x00000106, 0x03000103, 0xfd820267, 0x57010422, 0x013e0682, 0x05075f04, 0x04010402, 0x010d0d4f, 0x0d130d00, 0x0f101113, + 0x0507080e, 0x010c0004, 0x4044080b, 0x11152605, 0x21010121, 0x2c8b8211, 0x11211101, 0x02010123, 0x01372dfa, 0x20788452, 0x2e788252, 0xd6b0fe4a, + 0x7e017e01, 0x2d37dc05, 0x82fd20fc, 0xe0032ea7, 0x62fb372d, 0xbafb4604, 0x7a0186fe, 0x0e0f4100, 0x3640392a, 0x02020c0f, 0x0e4c0103, 0x4a29a982, + 0x01020b10, 0x04000049, 0x14d04401, 0x26059a41, 0x05212517, 0x822b1906, 0x16323e7f, 0x06141115, 0x01112123, 0x01013525, 0x02112135, 0x2d980204, + 0xfd2d3737, 0x01acfd68, 0x086f83fa, 0x04fe025c, 0x37a0feca, 0x2dd8fe2d, 0x02a0fe37, 0xfedea058, 0xde82fe82, 0x01004001, 0x6e022400, 0xeb048d04, + 0x06000500, 0x010103b3, 0x02092b32, 0x04010137, 0xfdcbfd8d, 0xc20172cc, 0x6d04c301, 0xff0101fe, 0x0175fe7e, 0x0300008b, 0xc302b5ff, 0x3505fb04, + 0x0a000600, 0x7d010e00, 0x2c8204b5, 0x544c0121, 0x202005de, 0x00222082, 0x11830285, 0x01058625, 0x45040403, 0x043105fb, 0x0706085f, 0x04030403, + 0xb04b1b4f, 0x4058500a, 0x8222861d, 0x040424df, 0x82055700, 0x86002007, 0x84002024, 0x820c2024, 0x204ca324, 0x204ca30d, 0x204ca610, 0x204ca311, + 0x204ca613, 0x204ca114, 0x20e1a040, 0x38008659, 0x0b0b1540, 0x0e0b0707, 0x0c0d0e0b, 0x0a070a07, 0x10111212, 0x2b1a0609, 0x05f76101, 0x21350324, + 0x03822115, 0x280aff61, 0x029d01d3, 0x059d010c, 0x05066235, 0x9acf0122, 0x00230082, 0x44010000, 0x402d0b07, 0x00010210, 0x00850001, 0x13760101, + 0x059e4633, 0x430be843, 0xd8430de1, 0x4347840b, 0x1f27074f, 0x01061c40, 0x84034901, 0x0102214b, 0x01214c82, 0x07304300, 0x30430420, 0x0d29430f, + 0x830d2043, 0x0a27449f, 0x23402624, 0x5482010c, 0x6d824c20, 0x820b4a21, 0x0f4a4b61, 0x02212522, 0x43059955, 0xfb420902, 0x0df3420b, 0xff3d3c82, + 0x040000d4, 0x003e05d8, 0x40210015, 0x1314151e, 0x0b0c0f10, 0x0306070a, 0x000d0102, 0x3205824a, 0x76000003, 0x14131413, 0x2b1a0604, 0x27070101, + 0x84112311, 0x82072003, 0x08038408, 0x5802272c, 0x516b8002, 0x37926699, 0x9966922f, 0x3e056f51, 0x497ec5fd, 0x580332fd, 0x044cfc5c, 0xfb2b3238, + 0x5db903c1, 0xcf02a4fc, 0xce827e4a, 0xff010029, 0x049cffd4, 0x82da04d8, 0x40222973, 0x0f12131f, 0x090a0d0e, 0x22069466, 0x8949000e, 0x84172074, + 0x05904674, 0x11331123, 0x20038317, 0x82048237, 0x1c042803, 0x80fd6b51, 0x836f7cfd, 0x372f2178, 0x42087882, 0x7e490c02, 0x3b02c5fd, 0xcf024a7e, + 0x035da4fc, 0x2bc1fbb9, 0xfc380432, 0x58035c4c, 0x3b000500, 0x2509f6ff, 0x2000ee04, 0x2c002600, 0x38003200, 0x51405400, 0x0320212b, 0x01010403, + 0x31330300, 0x82040203, 0x004c2c07, 0x85040304, 0x01000100, 0x83070a86, 0x00002393, 0x09855703, 0x00032408, 0x080b095f, 0x03000402, 0x2d2d4f00, + 0x37382727, 0x322d322d, 0x2c272c27, 0x11231319, 0x0c172313, 0x4e2b1d06, 0x2d080748, 0x23040606, 0x27262422, 0x36333523, 0x32332436, 0x21171604, + 0x01272626, 0x07020e05, 0x022e2121, 0x1e051127, 0x13111702, 0x2137023e, 0x6e4efb06, 0xfe2e0809, 0xfeb2140e, 0xfe9f9fee, 0xed14b2ed, 0x01b214ed, + 0x019f9f13, 0x0114b212, 0x31362bf2, 0xd8fcfafe, 0x11689b5d, 0x1f027101, 0x5d9b6811, 0x0583e1fd, 0x1283ae20, 0x048ffe23, 0x099f4edd, 0x92fd9a26, + 0xa69afd92, 0x1b300685, 0x20013533, 0x9c69122f, 0x699c5d5d, 0xa68cfe12, 0x01230683, 0x838cfe74, 0x00002b12, 0x3b000100, 0x25090700, 0x2f4fdd04, + 0x342b4d05, 0x2b4d6520, 0xce072305, 0x2b4d32f8, 0x4ddd2008, 0x6b8c142b, 0x41329b4f, 0xf8280b2c, 0x2bce0732, 0xfafe3136, 0x9b4ffb8b, 0x356b870a, + 0x402c0019, 0x02010e29, 0x4c010100, 0x030f1019, 0x0c0d4a01, 0xfb4c0203, 0x0c0c5013, 0x4e05074e, 0x26230616, 0x8b012726, 0x4ef9217b, 0x0221e887, + 0x21fc852a, 0x8b90b206, 0x2107264e, 0x0b416b02, 0x501b2005, 0x73410636, 0x00153e0a, 0x0d364039, 0x03000202, 0x0e0f4c01, 0x0c4a0202, 0x4901020b, + 0x01040200, 0x03020003, 0x0fdf4367, 0x00000033, 0x1c150015, 0x06052311, 0x07012b19, 0x21171707, 0x0da54d15, 0x8d011531, 0x01676701, 0xdff89807, + 0x751b3427, 0x82d6fd8a, 0x1b7533a0, 0x1f072633, 0x7001e302, 0x16a10170, 0x757f202f, 0x94826b02, 0x2e207f24, 0x5282a216, 0x32258f8c, 0x010c2f40, + 0x23018202, 0x0301154c, 0x57063451, 0x11231683, 0x48171123, 0x27210589, 0x053e5137, 0x27373723, 0x05455127, 0x2d412720, 0x1b752706, 0xdff82734, + 0x94839807, 0x0768f827, 0x1b33261f, 0x06af4175, 0x2f207f24, 0x9283a116, 0x2e16a224, 0x87837f20, 0x89000237, 0xd8080700, 0x1900dd04, 0x38002300, + 0x1e233540, 0x0204010e, 0x11b74103, 0x01020324, 0xf44b6703, 0x2523220f, 0x4e8f8c1c, 0x012210be, 0xa1842117, 0x0607072e, 0xfd2a02ae, 0x19758ad6, + 0x43fb2736, 0x2a0d2841, 0x3427b904, 0xb6fb7519, 0x83ab0501, 0x55fa23b4, 0xb0876701, 0x17301e22, 0x260d3d41, 0x7f1e2f17, 0x83019afd, 0x700121c4, + 0x260b4b43, 0x40340012, 0x83010b31, 0x0c0d29ba, 0x0a4a0002, 0x49010209, 0x79096b57, 0x1c210f40, 0x056f4e11, 0x11330124, 0x81501123, 0x06794206, + 0xae770825, 0x42e0f8ae, 0x07270f6d, 0xfc500420, 0x428b0144, 0x838d0f62, 0x3040332e, 0x03000101, 0x01124c01, 0x02034a02, 0x02228283, 0xdf440203, + 0x4c791805, 0x073c4112, 0x36360124, 0x88822137, 0x21113322, 0x250ff742, 0xaeaee0f8, 0xe9422007, 0x75fe2510, 0x75febc03, 0x2008df42, 0x08534402, + 0x1900122d, 0x44404700, 0x04020b18, 0x414c0105, 0x002c150a, 0x05030405, 0x04010667, 0x57040202, 0x043c0682, 0x02005f02, 0x144f0204, 0x13151613, + 0x1c191419, 0x07101111, 0x012b1a06, 0x35231133, 0x2c0ded42, 0x21352101, 0x08170707, 0xf9aeae77, 0x0dc6418d, 0xf971062f, 0xf9ea0616, 0x67670116, + 0x46fc5204, 0x0db841c8, 0xe27cfe25, 0x42707001, 0x27440573, 0x24ab8307, 0x17414044, 0x41ab8401, 0x06211432, 0x21ab8401, 0xb8180400, 0x0882089a, + 0x4f002808, 0x19131313, 0x11161813, 0x07171111, 0x092b1b06, 0x36372702, 0x15213736, 0x15331123, 0x27262621, 0x21150127, 0x43273737, 0xf92d0b13, + 0x06aeae8d, 0x1b332671, 0x0678fa75, 0x20a482ea, 0x0a154301, 0xba03c829, 0x202e16cd, 0x837bfe7f, 0x430120a5, 0x2608069f, 0x00dd043b, 0x4036001c, + 0x12141633, 0x06010a0c, 0x4c010200, 0x0313151c, 0x0b0d4a02, 0x05020309, 0x01034900, 0x5d000002, 0x00200567, 0x22060c75, 0x41161116, 0x07210cd6, + 0x24018327, 0x17253521, 0x83018337, 0x0701239d, 0xf0540211, 0x3a322f05, 0xa809fe26, 0xcdcecdce, 0x0199fea8, 0x088263ac, 0x0263ce25, 0x4539263a, + 0x36240b64, 0xcda81835, 0xa8230082, 0x826401a6, 0x64cd2806, 0x01353518, 0x48010020, 0x01200da7, 0x0125b582, 0x0101004c, 0x05eb4e4a, 0xa3180020, + 0x25240c6e, 0x18060223, 0x4c0cc14c, 0xb24c0dba, 0x01002f0d, 0xa8fd0000, 0xd4feb004, 0x18000300, 0x15451540, 0x1011210f, 0x11294d83, 0x04211121, + 0xfe50fbb0, 0x822782d4, 0x22338522, 0x65000000, 0x312013b7, 0xfd212c86, 0x872082a8, 0x2c01215f, 0x58872b94, 0xfc2c0123, 0x2157887c, 0x2b9c5802, + 0xfb580223, 0x212b8850, 0x2b9c8403, 0xfa840323, 0x212b8824, 0x2b9cb004, 0xf8b00423, 0x212b88f8, 0x2b9cdc05, 0xf7dc0523, 0x212b88cc, 0x2b9c0807, + 0xf6080723, 0x232b84a0, 0xb0045802, 0xdb862ba0, 0x86dc0521, 0x2093412b, 0x41080721, 0x00210993, 0x235f9796, 0x96231133, 0x89831c82, 0xfd238b84, + 0x972c01a8, 0x1121262b, 0xfe2c0121, 0x82b788d4, 0x9bc2202b, 0xfec2222b, 0x212b8a3e, 0x2b9a5802, 0xfd580223, 0x202b8ba8, 0x222b9bee, 0x8a12fdee, + 0x8403212b, 0x03232b9a, 0x8a7cfc84, 0x1a04212b, 0x04232b9a, 0x86e6fb1a, 0x418e832b, 0x01251893, 0x02211121, 0x26b18958, 0x04010000, 0x99a8fd1a, + 0x1133242f, 0x411a0423, 0x01240765, 0xa8fd0000, 0x1b423e83, 0x42598318, 0x878506cb, 0x8916f742, 0x822d8587, 0x00002287, 0x9a988202, 0x43b585e3, + 0x2b820a27, 0x68000521, 0x1e5307af, 0x76022206, 0x056e5311, 0xe9821120, 0xfb25eb85, 0xfb080750, 0x24378d50, 0x401d0007, 0x2c74831a, 0x03010085, + 0x03008501, 0x00850302, 0x473c8302, 0x3d850558, 0xfd233f85, 0x82a8fda8, 0xfb522441, 0x43b0044e, 0x7b9f0b1f, 0x86b00421, 0x867b8e39, 0x00022237, + 0x06fe7f85, 0xb38d0120, 0xf6213787, 0x216f84a0, 0x63435802, 0x0947411a, 0x5021a182, 0x22008200, 0x41000002, 0xe58b08cf, 0xe5820220, 0x02030222, + 0x0320ea82, 0xe5856e82, 0x05203d83, 0x21081142, 0x6141a8fd, 0x02522306, 0xe34450fb, 0x09634107, 0x3f83af92, 0x25052341, 0x580250fb, 0xb1850807, + 0x30000024, 0x83836400, 0x0072062b, 0x00070003, 0x000f000b, 0xfb501813, 0x27530808, 0x2f002b00, 0x37003300, 0x3f003b00, 0x47004300, 0x4f004b00, + 0x57005300, 0x5f005b00, 0x67006300, 0x6f006b00, 0x77007300, 0x7f007b00, 0x87008300, 0x8f008b00, 0x97009300, 0x9f009b00, 0xa700a300, 0xaf00ab00, + 0xb700b300, 0xbf00bb00, 0x33130000, 0x92372315, 0x92052003, 0x40278313, 0x64238f17, 0x8dc86464, 0x18fc2102, 0x1e820f8d, 0x062212f1, 0x00dd9672, + 0x42600021, 0x23420ca7, 0xc361085b, 0xcb00c700, 0xd300cf00, 0xdb00d700, 0xe300df00, 0xeb00e700, 0xf300ef00, 0xfb00f700, 0x0301ff00, 0x0b010701, + 0x13010f01, 0x1b011701, 0x23011f01, 0x2b012701, 0x33012f01, 0x3b013701, 0x43013f01, 0x4b014701, 0x53014f01, 0x5b015701, 0x63015f01, 0x6b016701, + 0x73016f01, 0x7b017701, 0x00007f01, 0x166b4211, 0x00102120, 0x43660117, 0x7c20112f, 0xfb211290, 0x201290b4, 0xf52540fc, 0x43080721, 0x5dd15dd9, + 0x44240021, 0x4e08082b, 0x00390035, 0x0041003d, 0x00490045, 0x0051004d, 0x00590055, 0x0061005d, 0x00690065, 0x0071006d, 0x00790075, 0x0081007d, + 0x00890085, 0x0091008d, 0x00990095, 0x00a1009d, 0x00a900a5, 0x00b100ad, 0x00b900b5, 0x00c100bd, 0x15211100, 0x9a331523, 0x35232303, 0x03901523, + 0x14821320, 0x038e2120, 0x0f8e0120, 0x13e31f83, 0x64b00422, 0xc8230098, 0x892c0164, 0x44fd2102, 0x4b420ed7, 0x3408211b, 0x21090942, 0x0bc5d4fe, + 0x00000035, 0x003c0001, 0x04740400, 0x000f0038, 0x02144017, 0x77000101, 0x0f270880, 0x03260e00, 0x672b1706, 0x02280f59, 0x9191f8eb, 0xf79493f8, + 0x04210583, 0x200a8238, 0x21108293, 0x058294f7, 0x8a020021, 0x001f284f, 0x042c402f, 0x74050101, 0x10231555, 0x18000010, 0x200a524f, 0x23699206, + 0x1415020e, 0x23063277, 0x23262634, 0x6725788c, 0xaf6666af, 0x82028267, 0x20848d08, 0x881182a0, 0x40e3821d, 0x18269f93, 0x27402a00, 0xc8180104, + 0x002b1646, 0x11171800, 0x000f0010, 0x4105260e, 0x11221222, 0x30603632, 0x0c1c4105, 0x21131641, 0x2f4168fc, 0x0aa34105, 0x19001022, 0x022d7b87, + 0x69020103, 0x00000300, 0x03005903, 0x06807a03, 0x19000026, 0x00111218, 0x36207d82, 0x07217b8a, 0x07b07323, 0x16711520, 0x237c8307, 0x168eee8a, + 0x41051342, 0x042e057c, 0x93f89138, 0x0692f490, 0x9394f791, 0x954191f8, 0x0e8f4106, 0x3400182c, 0x02003140, 0x02030003, 0x1b828000, 0x01048427, + 0x01030301, 0x37068259, 0x05610301, 0x03010301, 0x00101051, 0x10181000, 0x00131417, 0x260e000f, 0x20162842, 0x13214221, 0x42f80221, 0x6622141d, + 0x879067af, 0x2e403122, 0x03227482, 0x74828501, 0x85030224, 0x4a180200, 0x84860dc8, 0x99151821, 0x42012084, 0x8a4107ab, 0x84fe210c, 0x42057641, + 0xfd210da3, 0x052441e4, 0x00820020, 0x3c000122, 0x58296b82, 0x08003804, 0x0e401100, 0x07824300, 0x02101626, 0x212b1806, 0x21076c41, 0x5d415802, + 0x054e4105, 0x02223783, 0xbb430058, 0x5b378505, 0x3785073a, 0x0d6e0120, 0x58022307, 0xa943f893, 0x0aff410b, 0x15000f2c, 0x2c402f00, 0x00020300, + 0x7f410302, 0x02022108, 0x2a057f41, 0x02006102, 0x00510201, 0x42141500, 0x15251a80, 0x15060622, 0x82f28c21, 0x7c0121da, 0xa020ef8d, 0xb2821382, + 0x44030021, 0x14330a1f, 0x38002200, 0x10223540, 0x01010202, 0x0101054c, 0x82850102, 0x0403269c, 0x00670302, 0x25da8204, 0x04040059, 0x08826100, + 0x84820020, 0x16191b23, 0x1a014215, 0x06060729, 0x21172107, 0x4333021e, 0x27200610, 0x5032928c, 0x01189f6d, 0x3cfea024, 0x5a9c6b13, 0x4f67af66, + 0xa08d5489, 0xa018a827, 0x8856a06c, 0x231b824e, 0x126b9d58, 0x1d20ab8f, 0x422aab82, 0x15213f40, 0x01040002, 0x9e82004c, 0x01058624, 0xd9440601, + 0x04043c07, 0x02005702, 0x075f0402, 0x04020401, 0x101e1e4f, 0x1e000010, 0x10221e22, 0x861c101d, 0x430820b5, 0x0e3012bd, 0x11210702, 0x3435023e, + 0x01232626, 0x11171616, 0x5930b48c, 0x01136b9d, 0x4f8855c4, 0xfe66af67, 0x6d9f188c, 0xa023b28d, 0x8355884f, 0x599d21d0, 0xfe26b482, 0x16a06e34, + 0xb7962401, 0xb2171f21, 0x181926b7, 0x0e000f00, 0x21b79526, 0xae831415, 0x022e2128, 0x36111323, 0xb78c3736, 0x4e2cae82, 0xc2015688, 0x589d6b12, + 0x189e6c50, 0x1e82b68e, 0x839c5a21, 0x895429d9, 0xfe34fe4f, 0x6ea016dc, 0x200c1742, 0x0817421d, 0x17420420, 0x01042205, 0xc3541885, 0x0d964309, + 0x1f000027, 0x191c1d1e, 0x18194417, 0x43460720, 0x21372509, 0x26262137, 0x310e1742, 0x664e8955, 0x9c5967af, 0x3efe126b, 0x182401a0, 0xad8d6ca0, + 0x6b12aa24, 0xb182599c, 0x55894e23, 0x41ca82a0, 0x1f290f5f, 0x40002f00, 0x01063d40, 0xbfc41801, 0x77a98d11, 0x561805ef, 0x60471449, 0x0ef6460f, + 0x15021e22, 0x410b6f7b, 0x05470f6a, 0x653b2508, 0x3b653c3c, 0x08820282, 0x1147c48d, 0x88a0200c, 0x83278224, 0x470420cf, 0x002e0db3, 0x4051003b, + 0x0101084e, 0x05030109, 0xed790301, 0x0600270a, 0x06020400, 0x1b456904, 0x07cc780f, 0x470bee79, 0x0c200ad9, 0x4714f842, 0xe28e0cd9, 0xa40bde78, + 0x231926ee, 0x24181923, 0x12694224, 0x8c080848, 0x24a022f6, 0x41328518, 0x03310dcf, 0x23001300, 0x3d404000, 0x03050107, 0x04050304, 0x2af08280, + 0x7e020403, 0x01060000, 0x18000503, 0x3f0b3460, 0x0201005f, 0x14144f01, 0x23140404, 0x1a1c2214, 0x12041304, 0x08101127, 0x132b1906, 0x00211121, + 0x5918c384, 0x2320083e, 0x3c2be18e, 0xc8fb3804, 0x7cd39f01, 0x827dd37c, 0xd37d2502, 0x518a517c, 0x52210282, 0x83058389, 0xe803211c, 0x02821482, + 0xa0202085, 0x51221e85, 0x08825289, 0x0230b482, 0x1c023c00, 0x38047404, 0x15000c00, 0x31403400, 0x00209f82, 0x0121b482, 0x23ba8269, 0x59050000, + 0x05330682, 0x02045f00, 0x00050002, 0x000d0d4f, 0x0d150d00, 0x82101114, 0x130c232e, 0xa5831123, 0x23110122, 0x2d077766, 0x16041123, 0x34211516, + 0x04333636, 0x77855074, 0x6d025026, 0xa8fd518a, 0x04236e82, 0x85e4fd38, 0x1c0222a3, 0x468785f0, 0x02210743, 0x2c7f841c, 0x07304033, 0x04030605, + 0x02040001, 0x0b1f4201, 0x82005f21, 0x217e8729, 0x7e841215, 0x86112321, 0x1121227e, 0x07314733, 0xe0422320, 0x74042407, 0x8950c8fb, 0x895228f2, + 0xfd1c0251, 0x411c02e4, 0x7c830508, 0x82528921, 0x010021fe, 0x1121ff88, 0xf3411800, 0x00112a1d, 0x13231310, 0x2b190605, 0x89e38200, 0x21ec83f2, + 0x9748eb02, 0x91a02508, 0x380493f8, 0x3a490482, 0xf8932205, 0x071b4b91, 0x1127e382, 0x23402600, 0x46020304, 0x521806a1, 0x8d820ce1, 0x11001124, + 0x145e1323, 0x88c78705, 0x740421d9, 0x20052a4b, 0x05a643a0, 0x4b1c0221, 0x9642052b, 0x85002005, 0x580229c7, 0x09003804, 0x1b401e00, 0x01200f82, + 0x1a435318, 0x23150622, 0x5820b684, 0xb0833e82, 0x82980321, 0x82508208, 0x58022147, 0x86060f42, 0x1cbb7847, 0x47821620, 0x23262624, 0x3b825802, + 0x2149a020, 0x84a08207, 0x00002347, 0xf3827404, 0x87780920, 0x0059210e, 0x08525518, 0x0929f282, 0x13110900, 0x2b180604, 0x24f18301, 0x36363235, + 0x82e98435, 0x83e28444, 0x412682ee, 0x9b830543, 0x4f870020, 0x12e45418, 0x13204f8b, 0x23056c68, 0xdc352626, 0x94244b82, 0x1c0291f7, 0xf721ec84, + 0x244b8594, 0x38047404, 0x1fba1800, 0x09132508, 0x1c023c02, 0x83052242, 0xe4fd2105, 0x2f0cd749, 0x00070003, 0x0507b508, 0x32020103, 0x0609132b, + 0x01272b86, 0xfec8fe38, 0x853a01c6, 0xe4fd2339, 0x11851c02, 0x7d203b84, 0x3334ff82, 0x05006205, 0x1b000b00, 0x090a1840, 0x05020507, 0x4c010001, + 0x087b4018, 0x02101222, 0x3325f883, 0x01230101, 0x08038221, 0x01330121, 0x6d01dbeb, 0xfedb93fe, 0xfeef0292, 0xf0fe08f0, 0x05081001, 0xfd50fd62, + 0x02b0024e, 0x84e2fd1e, 0x01002796, 0x00001c01, 0xbf845603, 0x12cb4018, 0x2111212c, 0x3a021c01, 0x3804c6fd, 0x3b41c8fb, 0x74042308, 0x1f581c02, + 0x82132014, 0x833c202f, 0x1c02212a, 0xe34c5e82, 0x242b8406, 0x40290007, 0x25408226, 0x02000302, 0xeb750467, 0x23068205, 0x005f0103, 0x4f2a0c82, + 0x07040404, 0x11120704, 0xaa440510, 0x35252306, 0x49841521, 0xfd980323, 0x224d8308, 0x82dcdca0, 0x0200213e, 0x53abaf8a, 0x99820120, 0x23112523, + 0x22cd8511, 0x83fa9a01, 0x02a035a5, 0x0008fdf8, 0x08020100, 0xba0418fc, 0x05000c03, 0x1b401e00, 0x240f4777, 0x01000100, 0x0672584f, 0x15210131, + 0x02231121, 0xfdb20208, 0x0c03a0ee, 0x82acf9a0, 0x253f8294, 0xba046c02, 0x3f86d007, 0x85213082, 0x07981800, 0x33012215, 0x2b418211, 0x02a00802, + 0x074efd12, 0xa03cfbd0, 0xff253f83, 0x0218fcf6, 0x6d7f88a8, 0x10251519, 0x2b190603, 0x2d7d8203, 0x020a2111, 0xeefda0b2, 0x0cf90c03, 0x3f855406, + 0x026c0223, 0x577f89a8, 0x981805c7, 0xa16c0ed0, 0x21352108, 0xfd277f82, 0x0712024e, 0x889cfad0, 0x20bf847f, 0x05a5410b, 0x85000128, 0x03020300, + 0xd4180586, 0x04200bd3, 0x02219682, 0x345a184f, 0x164f1809, 0x20d0850b, 0x839482ee, 0x23d58255, 0x5406acf9, 0x00215a83, 0x21db8301, 0xdb82ba04, + 0xa3780720, 0x21032221, 0x22df8515, 0x83fdc404, 0x0c03224c, 0x824883a0, 0x414783e2, 0x07290663, 0x1e402100, 0x00010000, 0xb7591885, 0x0200220c, + 0x219d8401, 0x17600410, 0x844a8205, 0x120223e8, 0x94863cfb, 0xeb41eb84, 0xd0072705, 0x24000700, 0x47842140, 0xb041eb84, 0x8a112011, 0x2311214a, + 0x0721e287, 0x86de84d0, 0x18fc2393, 0x4b89a802, 0x85000322, 0x01214682, 0x0fcb6186, 0xcb611120, 0x4196840c, 0xf421062a, 0x09274148, 0x0321df83, + 0x1bcf5e0c, 0xd4820320, 0xc4040a26, 0x0c033cfb, 0x7f84cb88, 0x2113cf5e, 0xb4843301, 0xd007a025, 0x410048f4, 0x2b840587, 0x2e000b27, 0x00002b40, + 0x18ab8705, 0x4116c05b, 0x62180ce8, 0x21230700, 0x84a00802, 0xeefd23b9, 0x58831202, 0xa0b40523, 0x338a83a0, 0xf6ff0200, 0x480318fc, 0x0700d007, + 0x28000b00, 0x01042540, 0x8524c982, 0x02010105, 0x26140f41, 0x06101111, 0x622b1c06, 0x352105dd, 0x2a078321, 0xa0a06801, 0x72018efe, 0x84a04001, + 0x540624b4, 0x88c404a0, 0x48032abb, 0x09000c03, 0x1f402200, 0x20538503, 0x284c1800, 0x01042408, 0x77020002, 0x032309f7, 0x84231121, 0x0a212301, + 0x9e825203, 0x438efe21, 0xf9230529, 0x415406ac, 0x03210707, 0x824b82ac, 0x05ae41a5, 0x04000024, 0x5c180003, 0x497811c3, 0x21518408, 0x01823521, + 0x27057943, 0xeefd1202, 0x6cf8ac03, 0x0023fd83, 0x88030000, 0x820520fb, 0x000f3055, 0x032f4032, 0x00020001, 0x04010685, 0x82860407, 0x05013309, + 0x00670102, 0x05070705, 0x05050057, 0x07005f07, 0xb0840705, 0x10246282, 0x2b1e0608, 0x5d82ff82, 0x23220582, 0xbb822101, 0x68012125, 0x41eefda0, + 0xfd35050a, 0xa012024e, 0xd0078efe, 0x04a03cfb, 0x0648f424, 0x05acf954, 0x237682b4, 0x68010200, 0x28067341, 0x00070003, 0x02124015, 0x06164301, + 0xff5b0120, 0x11332209, 0x22568423, 0x41a0a068, 0x0b230758, 0x8448f4b8, 0x25b7853f, 0x0500ac03, 0x73510b00, 0x01052206, 0x07a54586, 0x0503002e, + 0x00570305, 0x5f050303, 0x05030500, 0x410afa43, 0xab43050f, 0x52032206, 0x26a286a0, 0x6cf8ac03, 0x84a0f406, 0xff02289e, 0x03cc01f6, 0x87d00748, + 0x0103215b, 0x85200982, 0x04240382, 0x67040502, 0x11ea9c18, 0x11421120, 0x05094109, 0x02340582, 0xaefca0a8, 0xc0feb202, 0x01eefda0, 0xf9d00772, + 0x6405a0fc, 0x21083345, 0x5f846c02, 0x23000924, 0x6f412040, 0x01042605, 0x02010102, 0x18068257, 0x240ac79d, 0x06051011, 0x0660411b, 0x11331123, + 0x2c548433, 0xa0a07201, 0x9cfad007, 0xfbc404a0, 0x21f0823c, 0xaf830100, 0x82a80221, 0x000928af, 0x00254028, 0x4d000400, 0x9e180adf, 0x548b101c, + 0xa9833520, 0xfda00825, 0x4312024e, 0xa6820516, 0x6b44a020, 0x0673430d, 0x53820120, 0x05040527, 0x00010086, 0x05c76f02, 0x0de06018, 0x210c7343, + 0x01841521, 0x83087944, 0x26b3825d, 0xa0a0dcfb, 0x834cfaa0, 0x010226b3, 0x0418fc68, 0x20b382ba, 0x05734303, 0x43010221, 0x04220673, 0x61188601, + 0x5b8c0fa6, 0xbc452320, 0x42012007, 0x01230516, 0x828efe72, 0x48f4235b, 0xdd44b80b, 0x215b8206, 0x5b84cc01, 0x21061b42, 0x12410103, 0x01052306, + 0x5c180504, 0x5d8c102c, 0x5f85b782, 0x02315d82, 0x01aefcb2, 0x7201a040, 0xd007eefd, 0x06a09cfa, 0x82c08204, 0x42bb86bc, 0x0525097b, 0x02040201, + 0x23198286, 0x01000301, 0x10646218, 0x5d825f8a, 0x47231121, 0x012a0587, 0xfd520368, 0x4001a04e, 0xbf821202, 0xa0ac0326, 0x54060cf9, 0x22051c41, + 0x8af6ff03, 0x000f24bf, 0x422b402e, 0x05240823, 0x02060101, 0x062c6382, 0x57060707, 0x07060600, 0x0607005f, 0x82168f43, 0x8205206d, 0x098f4303, + 0xfd25c983, 0xfbc4044e, 0x0691433c, 0xa021cf82, 0x050344a0, 0x82ba0421, 0x00032dcf, 0x000f0009, 0x072c402f, 0x03040301, 0x0223d184, 0x83670100, + 0x020422df, 0x27068257, 0x065f0402, 0x04020401, 0x200c0044, 0x06ec4103, 0x25211122, 0x0a20e084, 0x02266183, 0x8efea012, 0xdd87b202, 0xacf9a024, + 0xfc41b405, 0x41032006, 0x6f830afb, 0x2f403222, 0x2005fd41, 0x38dc8207, 0x03008601, 0x03050400, 0x05006704, 0x57050606, 0x06050500, 0x0506005f, + 0x20728c06, 0x051a4401, 0x42086742, 0xfd21080b, 0x257184ee, 0x48f4d007, 0x6f42b80b, 0x0553410b, 0x5518e384, 0x062121c3, 0xe292181a, 0x83cc8408, + 0xac0326d0, 0x00a0a0a0, 0x05134804, 0x26061b44, 0x00170011, 0x413b403e, 0x0b28059d, 0x07080701, 0x02010486, 0x2606a341, 0x08060109, 0x82570608, + 0x08062c06, 0x08010a5f, 0x174f0806, 0x18141516, 0x220a8279, 0x451f060c, 0xcb82093d, 0x11210523, 0x07444123, 0x410fb541, 0xbd410b4f, 0x0a56410a, + 0x42020021, 0x07200837, 0x20051345, 0x06524500, 0x82020021, 0x7f672095, 0xc946143d, 0x227d8207, 0x49012135, 0xfb2507df, 0xfd12023c, 0x062842ee, + 0xa0a0dc26, 0x00a0c0fe, 0xff214c82, 0x06c748f6, 0x26000b26, 0x01042340, 0x05275e83, 0x02010203, 0x83570102, 0x02012307, 0xca48005f, 0x0a114506, + 0x35211523, 0x06bc4421, 0xfb720123, 0x05be443c, 0xa03cfb22, 0x8208bf44, 0x18fc21b7, 0x28067f42, 0x402a000b, 0x03040027, 0x087c4204, 0x0a3c6318, + 0x03010523, 0xdd581802, 0x1c062108, 0x2308a341, 0x21112311, 0x4906a741, 0xac27057b, 0xfaa0a0a0, 0x84b4054c, 0x285b84b3, 0x000b000c, 0x04214024, + 0xe7681801, 0x21b6830e, 0x1f460100, 0x4715200c, 0x04230983, 0x478efec4, 0xa0240685, 0x5406acf9, 0x53820383, 0x41680121, 0xbf450607, 0x00012307, + 0x8f180485, 0x05410b78, 0x08bf4508, 0xbf455482, 0x72012c05, 0xa0a0aefc, 0x3cfbd007, 0x456405a0, 0x022106bf, 0x06ef4308, 0x8206bf45, 0x1b66454e, + 0x1520548a, 0x2008914b, 0x06954bee, 0xd448dc20, 0x07174c05, 0x41072b48, 0x00201651, 0x85075041, 0x084f4353, 0x8205254c, 0xa0ee2252, 0x054c4103, + 0xf7840020, 0x24064b41, 0x40220009, 0x104b411f, 0x08b44318, 0x82066146, 0x2311214d, 0x01250183, 0xfe520368, 0x4b98828e, 0xf9210614, 0x05cb48ac, + 0x07ba042a, 0x001300d0, 0x08304033, 0x20054b42, 0x228e8201, 0x42070986, 0x07830551, 0x5f020125, 0x82020406, 0x434f200f, 0x0a200a36, 0x41063643, + 0x604209a8, 0x2167840a, 0x65428efe, 0x07b64108, 0x20066d42, 0x08bf4301, 0x38001324, 0xd4823540, 0x1806d746, 0x2708636c, 0x03010767, 0x57030404, + 0x03270682, 0x01065f04, 0x95040304, 0x8515207c, 0x352121df, 0x634b0184, 0x12022206, 0x054a4cfd, 0x44054e47, 0x6a4a0681, 0x091b5c05, 0x4e13f34a, + 0x0423087f, 0x58c8fb38, 0x03210a53, 0x2b2b4e00, 0x25234583, 0x4e112111, 0x2b4e087f, 0x5cb75b0a, 0xdd470328, 0xefdd5050, 0x0583dcf0, 0x389ba92d, + 0xa8a99b38, 0x9b39399b, 0x823804a8, 0x82ef2016, 0xf0dc211c, 0xa0200582, 0x1d881182, 0x56000021, 0x8b650aa7, 0x40352205, 0x2d158232, 0x02000402, + 0x00040067, 0x05040305, 0x714f0667, 0x4f068205, 0x0b230971, 0x4f08090a, 0x07200675, 0x8207754f, 0x084341f5, 0xfd980328, 0xb801a008, 0xfe8848fe, + 0xfe580223, 0x55598248, 0x6f85099b, 0x51000f24, 0x17824e40, 0x82030221, 0x01092171, 0x35067a46, 0x0b05010a, 0x05060701, 0x06006707, 0x57060101, + 0x01060600, 0x0982085f, 0x0c4f0132, 0x0408080c, 0x0c000004, 0x0e0f0c0f, 0x080b080d, 0x89838a82, 0x05062108, 0x03000300, 0x17060c11, 0x2111332b, + 0x21350311, 0x21350115, 0x3521021d, 0xa038043c, 0xf80208fd, 0x8e830383, 0x98000326, 0x98d0fe98, 0x00210083, 0x278f9100, 0x003b403e, 0x02040700, + 0x06289184, 0x03030509, 0x57030101, 0xff820884, 0x032a8482, 0x08084f01, 0x0e0f0000, 0x7e850c0d, 0x05060723, 0x207c8404, 0x2b7c860a, 0x33112301, + 0x11231121, 0x23113321, 0xfd207d82, 0x01227082, 0x02829830, 0x7f849820, 0x8d879820, 0x0a20f782, 0x6708ab56, 0x8222130b, 0x8b827f40, 0x03051622, + 0x22088c85, 0x03031504, 0x030b170c, 0x09030809, 0x020a0d67, 0x10131908, 0x080f0e03, 0x1812670e, 0x010f0311, 0x84570f01, 0x010f2308, 0x0c82145f, + 0x244f0127, 0x14202024, 0x05304114, 0x24272439, 0x20252627, 0x22232023, 0x1d1e1f21, 0x191a1b1c, 0x14171418, 0x18151617, 0x4107bc8f, 0x1a20104c, + 0x352bcf87, 0x15251523, 0x33173533, 0x82012335, 0x15212803, 0x23213533, 0x82053315, 0x86212003, 0x83e7851b, 0x989824e3, 0x8398a0fd, 0x890c83ed, + 0x21fa840a, 0x00859800, 0x8538fe21, 0x20058407, 0x20008200, 0x0c074105, 0x000a2508, 0x0011000e, 0x10444047, 0x07090d0e, 0x02040606, 0x00004c01, + 0x02020307, 0x67020004, 0x04020508, 0x57040101, 0x04230783, 0x82065f01, 0x4f01310b, 0x08080f0f, 0x110f0000, 0x0b0c110f, 0x0a080a08, 0x20069241, + 0x08924109, 0x0335012b, 0x33013517, 0x27131501, 0x2cac8315, 0x8c02d6aa, 0xbffedede, 0xdf73fdd6, 0x309c84df, 0xd675fd98, 0xdedeb501, 0x8d0208fd, + 0xe04afed7, 0x21978ee0, 0x97850006, 0x39403c23, 0x2164820f, 0x97860407, 0x84010321, 0x01052196, 0x06829584, 0x00229488, 0xc1821100, 0x42090a21, + 0x0720069c, 0x37268c87, 0x01151123, 0x8e820123, 0x33072522, 0xfc2f8c82, 0x02dfdf68, 0x4101d68d, 0x01d674fd, 0x83dedeb6, 0xb902248e, 0x824afedf, + 0xbdfe26a3, 0xdf74fdd7, 0x208b82df, 0x0a23410d, 0x09000626, 0x10000d00, 0x38083969, 0x00250022, 0x002b0028, 0x2a654068, 0x23242527, 0x1f202122, + 0x1a1b1d1e, 0x0adf4119, 0x05080b23, 0x0549411c, 0x07030823, 0x23b38403, 0x0309050a, 0x0884b584, 0x2935b788, 0x07262629, 0x00040407, 0x292b2900, + 0x2628262b, 0x07090728, 0x26ef8209, 0x00030006, 0x870b1103, 0x371726c7, 0x05371721, 0x29038207, 0x35052737, 0x27370107, 0x0d822507, 0x07270724, + 0x11822517, 0x05170727, 0x27210727, 0x08e18307, 0x393ad422, 0x3a393b01, 0x6c6cf0fe, 0x3a18fe6b, 0x39f8023a, 0x6b6ce6fd, 0x6b19026c, 0x6bd76b6c, + 0x83fe6c6c, 0x39281484, 0x3a39e7fd, 0x393a2102, 0x20059241, 0x2b008239, 0x6b6b6b3a, 0x733a3a3a, 0xbefe3972, 0x02830a82, 0x4582d720, 0x3a3a3226, + 0x6d393901, 0x3a211982, 0x078b5400, 0x5b540220, 0x54012015, 0x0221088b, 0x05bb541c, 0x54060b54, 0x4983305f, 0x23352523, 0x080b5415, 0x420b5f54, + 0xb3540cc3, 0x0933462e, 0x4684fe21, 0x87461433, 0x1c02213a, 0x062f5398, 0x28402b00, 0x00020105, 0x00004c01, 0x18850002, 0x2b115b4f, 0x06040404, + 0x10110604, 0x2b180604, 0x2005dd46, 0x12dc4601, 0x2209db46, 0x49060003, 0x012105e9, 0x54538202, 0x1220138f, 0x8305826d, 0x0137224c, 0x244c8421, + 0xfdf802a0, 0x46f68608, 0x362e1093, 0x00003340, 0x03020104, 0x07670200, 0x90450605, 0x21088405, 0x02560103, 0x08082305, 0xbd440404, 0x205f8209, + 0x0a944608, 0x5a412120, 0xcc012707, 0xf802d4fe, 0x5e41d4fe, 0x05c25508, 0x092c6f8c, 0x3c000d00, 0x00003940, 0x06020105, 0x08296f82, 0x03000601, + 0x67030604, 0x05dd4307, 0x04200682, 0x04317483, 0x0a0a4f01, 0x0d0a0404, 0x0b0c0d0a, 0x09040904, 0x06327c11, 0x83052241, 0x41012073, 0xd4240ad2, + 0x2c0134fe, 0xfe257988, 0x01d4fe34, 0x901083cc, 0x403e257b, 0x0000003b, 0x002aea84, 0x04050003, 0x08670503, 0xa3430706, 0xa7088405, 0x8923207d, + 0x08fd247d, 0x89a0cc01, 0x478b867c, 0xf7830dfb, 0x3a403d22, 0x04207b83, 0xe682f682, 0x2705fc47, 0x03020608, 0x57030101, 0x6d410783, 0x83f89907, + 0x112121f2, 0x7a82f88a, 0xcc012c22, 0x02237b85, 0x822c016c, 0x41cc200f, 0x7b48050a, 0x227f830e, 0x4138403b, 0x83820b77, 0x04060324, 0x7f840067, + 0xa7030021, 0x4135207d, 0x012313ee, 0x82cc01cc, 0xa02c257b, 0xd4fe2c01, 0x7b597a82, 0x0002280a, 0x01124015, 0x824a0001, 0x76002103, 0x02351b82, + 0x06020200, 0x01332b16, 0x1c023c01, 0x38041c02, 0xff00c8fb, 0x08db43ff, 0xbb050222, 0x01202482, 0x00260f89, 0x020c400f, 0x58180001, 0x132709de, + 0x043c0121, 0x84e4fd38, 0x8d002039, 0x8ebc203b, 0xb306283b, 0x32010001, 0x8311332b, 0x90348332, 0x0102211f, 0x13221f82, 0x52821101, 0x8c828e83, + 0x28837b9d, 0x278b7985, 0x2d89e397, 0x410b3b67, 0xa6861813, 0x230ccf59, 0x02003804, 0x21160341, 0xfb59c8fb, 0x30cb5708, 0x2111212b, 0xfec4040a, + 0xfe20fe8e, 0x09cc578e, 0x77540120, 0x590c2006, 0x5f44062f, 0x066f5913, 0x41820320, 0x03214382, 0x58418552, 0x3f8605f0, 0x00d00727, 0x40270009, + 0x2cf48324, 0x03020085, 0x01048602, 0x01030301, 0x25068257, 0x005f0301, 0xe74e0103, 0x05964d05, 0x33113323, 0x574c8211, 0x4d83057c, 0x83051458, + 0x4da02051, 0x035a0c97, 0x4d212025, 0xfe21058f, 0x4dd68420, 0x938d08d7, 0x03020322, 0x02219383, 0x4f938502, 0x7e4e0ad9, 0x2995820a, 0xa0080233, + 0x8efe1202, 0xd44e20fe, 0xacf92305, 0x9383f406, 0x82056f41, 0x32975953, 0x5785eb87, 0x598efe21, 0x01200e98, 0x03215b85, 0x3b5218ac, 0x82032023, + 0x061f504c, 0xa0eefd28, 0xac03eefd, 0x1a5020fe, 0x0a4f5705, 0x41053741, 0x23201dcb, 0x2408bb5a, 0x056cf8ac, 0x55e387b4, 0x262506c7, 0x00002340, + 0x05337304, 0x18008621, 0x23096c45, 0x04010103, 0x41055e50, 0x21200536, 0x49828b82, 0x01211126, 0xa0e00168, 0x83081b56, 0xe0012191, 0xe3595383, + 0x41db8205, 0x112022cb, 0xa94f4d82, 0x85a02005, 0x0dcb41d6, 0x01209384, 0x5a060f5b, 0x04200a23, 0x87080d5b, 0x83212093, 0x23112149, 0x01299383, + 0xa0eefd72, 0xfbd007a0, 0x0d2741dc, 0x8331635b, 0x82a08254, 0x84ec845a, 0x050b5758, 0xf1825b87, 0x50000226, 0x6004cc01, 0x22069753, 0x181a401d, + 0x180cbb50, 0x220f0654, 0x82012111, 0x01502655, 0x0248feb8, 0x83058358, 0xe00131f6, 0x020020fe, 0x98fe6801, 0xf8074803, 0x07000300, 0x200a3d75, + 0x16577402, 0xfe219587, 0x273e8320, 0x40fcf807, 0x40fc20fe, 0x23063f41, 0x0c034803, 0x8314235e, 0x6801217d, 0x03243183, 0x000cf90c, 0x4209e742, + 0x57442a8b, 0x088c420c, 0x57440120, 0x44ac2006, 0x8c422f57, 0x55012006, 0x37420553, 0x09034428, 0x43588284, 0x06835305, 0x2018ff78, 0x22bb8503, + 0x82033cfb, 0x85002034, 0xa8022133, 0xc77a7382, 0x2333841a, 0x4efdb202, 0x6784338a, 0x22000724, 0x44821f40, 0x57000322, 0x2708ec52, 0x5f030000, + 0x03000300, 0x08f95518, 0x91520320, 0x020a2606, 0xfd1202b2, 0x524583ee, 0x042605df, 0xcc014b00, 0x7b846504, 0x2b05c375, 0x063f4042, 0x00030204, + 0x57000101, 0x002c0884, 0x070b5f01, 0x0309050a, 0x00010708, 0x2224b84f, 0x8c331113, 0x6e4b2001, 0x01230616, 0x42e001cc, 0x07870528, 0x01040029, + 0x03f8fd68, 0x76480848, 0x50220843, 0xcd824d40, 0x08850023, 0x05d56201, 0x8502033d, 0x04030109, 0x04008503, 0x0a850405, 0x05060501, 0x07060085, + 0x010b8506, 0x50760707, 0x01212246, 0x05ca4811, 0x68200788, 0x0627858d, 0xfd1c022c, 0x8f44fde4, 0x01002105, 0x41054f54, 0x01251d97, 0x02211121, + 0x08984108, 0x87430320, 0x000b2c0c, 0x041f4022, 0x01000202, 0x83570001, 0x01002207, 0x1029555f, 0x83571320, 0x01232105, 0x50240782, 0x9001f0f0, + 0x92430385, 0x22ac8307, 0x41030000, 0x98200627, 0x28062741, 0x003a403d, 0x85000100, 0x09254106, 0x25410720, 0x01082409, 0x50760505, 0x4e4b052e, + 0x06bc4e09, 0x17060923, 0x0c12412b, 0x270a0e41, 0x20037805, 0x40fce0fc, 0x00200589, 0x01220082, 0x675b6801, 0x136f5306, 0x2309cb43, 0x9cfad007, + 0x3f572f84, 0x22a75f0a, 0x84112121, 0x05344501, 0x013cfb23, 0x05344572, 0x88e00121, 0x5c03204b, 0x1e230543, 0x18001b40, 0x6113794d, 0x48830897, + 0xfc214683, 0x05295cae, 0xbb824282, 0x2208935e, 0x60164019, 0x01200833, 0x820c077a, 0x066055c3, 0xa0e00122, 0x5605155c, 0x002005a2, 0x435a3f82, + 0x217f8408, 0xd7610001, 0x21c68a18, 0xc485aefc, 0x7f863f83, 0x5d1f3b41, 0x5755058f, 0x2cef4709, 0x47417a84, 0x056f490b, 0x47074b41, 0xab470816, + 0x48032105, 0x412aaf60, 0xfe230a9e, 0x838efe20, 0x48f42352, 0x5b41b405, 0xba042107, 0x23474b89, 0x0d926112, 0x830cea41, 0x052541a2, 0x564cfa21, + 0x0d3d0ac7, 0x2e403100, 0x00010000, 0x05040085, 0x01068604, 0x01050201, 0x00020057, 0x03020503, 0x260e8267, 0x005f0501, 0x58050105, 0x112c056b, + 0x1d060710, 0x1133012b, 0x15211533, 0x02255e86, 0x01a0a008, 0x05014172, 0x83120221, 0xa0a02362, 0xb284acf9, 0x20088b62, 0x06fb5fac, 0x03040323, + 0x206c8286, 0x053c4504, 0x02010426, 0x00000067, 0x0f455818, 0x4509985b, 0xa024063f, 0xac03eefd, 0x2e825485, 0xef420120, 0x0b375e08, 0x04030122, + 0x24099045, 0x5f030404, 0x606b8200, 0x1d5d09a1, 0x82b28305, 0x059345ae, 0x3c20ab84, 0xe020bb82, 0xf7499182, 0x08ab610a, 0x0523ac84, 0x84050401, + 0x18ac8458, 0x5d08f984, 0x11250f7d, 0x11211123, 0x12946321, 0x59150741, 0x042b05ce, 0x00570001, 0x01030004, 0x83670304, 0x645f20d8, 0x112006f7, + 0x42078958, 0x35200562, 0x2308f546, 0x72018efe, 0x62053249, 0x835909c3, 0x02042212, 0x20578401, 0x18578302, 0x8c0a17bd, 0x21352157, 0x01255783, + 0xfc7201e0, 0x056742ae, 0xfedcfb25, 0x42a0a020, 0x435f0a1b, 0x0203260a, 0x01008603, 0x27588305, 0x02040005, 0x00670405, 0x5b62588c, 0x08184306, + 0x18435b87, 0x5fb7890f, 0x0d330647, 0x2d403000, 0x00060000, 0x03040085, 0x06008604, 0x41060301, 0x062409c8, 0x055f0306, 0x03201182, 0x820c7e42, + 0x21152365, 0x73412315, 0x05c84405, 0x4a8efe21, 0xfb210795, 0x05445b3c, 0xe0014b08, 0x01000000, 0x85fdb5ff, 0x2d07fb04, 0x06000b00, 0x010208b3, + 0x01012b32, 0x27010107, 0x01370101, 0xb2021701, 0xfd914902, 0x91eefdee, 0xbcfd4902, 0x020e0290, 0x5e02900e, 0x04486ffb, 0x48dcfb24, 0x88049104, + 0x04e5fb47, 0x4782471b, 0x4786ba20, 0x2e087368, 0x07013703, 0xb1049046, 0x47e60691, 0x8748a0f6, 0x82f6206b, 0x2f23896b, 0x4b011701, 0xfb90b104, + 0x09cdfd50, 0x9ff64760, 0x002a9282, 0x02500002, 0x0360046c, 0xf349000c, 0x1c3b4a06, 0x25211525, 0x4a211521, 0x0c200b3b, 0x28054a48, 0x08020200, + 0xa802f8fd, 0x05a34608, 0x4a09797f, 0x3323143b, 0x64152311, 0xa027069d, 0xfb9808a0, 0x83fba000, 0x0201228b, 0x06076708, 0x86142f45, 0x05354a31, + 0xf6ff0126, 0xa8026c02, 0x23222f65, 0x4efdb202, 0x5e062f65, 0x374908bf, 0x01032306, 0x64185700, 0x002208f3, 0xf2420100, 0x05f96508, 0x5a112121, + 0x42830695, 0x02eefd31, 0xfeac0312, 0x00a0a020, 0x024b0004, 0x8465046c, 0x4937497b, 0x15333523, 0x49038a33, 0x02220737, 0x0086a06c, 0x41040021, + 0x2f490663, 0x1133235c, 0x03891103, 0x86080221, 0x1828497c, 0x4109ff68, 0x01221d8b, 0x2b491521, 0xa00c2407, 0x42030000, 0x2b490c77, 0x23152326, + 0x03853325, 0x200b2b49, 0x82a2840c, 0x42032087, 0x0b210c83, 0x3f274900, 0x49100641, 0x01231222, 0x69020802, 0xb342057b, 0x051d491b, 0x22268f48, + 0x50331133, 0xa0200613, 0x21061050, 0x0f500cf9, 0x0a27470e, 0x03020325, 0x45010686, 0x0e820c0c, 0x470c4560, 0x10450827, 0x21352206, 0x09715035, + 0x018efe23, 0x08aa4e72, 0xa0540623, 0x087f46a0, 0x46082367, 0x2323291f, 0x41352111, 0xee2105e5, 0x073043a0, 0x824cfa21, 0x05e74c55, 0x65ba0421, + 0x0124095f, 0x01008500, 0x511f1b46, 0x538306b2, 0x1202a024, 0x105e4efd, 0x20fe2107, 0x5382a78a, 0x84311b46, 0x86112059, 0x855b83af, 0x079348b0, + 0x2f48b283, 0x1121253c, 0x52030a21, 0x48078948, 0x2f480930, 0x05634635, 0x5f460582, 0x05e54a07, 0x3048fb20, 0x0b374a05, 0x842f2f48, 0x163c4a59, + 0x39493c20, 0x08134208, 0x00d00722, 0x49062347, 0x062a09ef, 0x00570102, 0x02050006, 0x87470506, 0x091b5105, 0x7a421120, 0x05784206, 0x23112322, + 0x2109e747, 0xed69eefd, 0x09255105, 0x52053367, 0xc68535f3, 0x48112321, 0x5e820846, 0x83062751, 0x540621c5, 0x6c0d7b63, 0x53842443, 0x4c073a48, + 0x3c20069b, 0x52087742, 0x4e8535b3, 0x21071d48, 0x276d9cfa, 0x06674d0b, 0x4c05b352, 0x47851eeb, 0x21050542, 0xdc829cfa, 0x0f660120, 0x00092108, + 0x612ab352, 0xb35205fe, 0x052f410c, 0x00820020, 0xd76e5382, 0x11212328, 0xa2521521, 0xaefc2206, 0x05d86e07, 0x4336cf4c, 0x5082059a, 0x4b06c24a, + 0x4f530bcc, 0xe0012105, 0x410a4f44, 0x538624cb, 0xa0080222, 0x22080f6e, 0x8520fedc, 0x06a34d47, 0x84314b56, 0x56a0209f, 0xdc22084b, 0x5f4b6cf8, + 0xcc012108, 0x84298f6f, 0x058f6f46, 0x82fcf921, 0x05374e92, 0x56062b45, 0x4b5608df, 0x21112122, 0x82104b56, 0x4cfa24e4, 0x50009407, 0xa37007cf, + 0x65938427, 0xfe21070d, 0x0d934c20, 0x26402922, 0x7009376f, 0x5e441d23, 0x12824b08, 0x57089843, 0x936f09cf, 0x20476f06, 0xea435682, 0x09974e07, + 0x43540621, 0xdf6f0c07, 0x43a28627, 0x974e0503, 0xb89a8306, 0x085a46f3, 0x2010824d, 0x08be42dc, 0x70055b46, 0x5284313b, 0x42083b70, 0xbf72056e, + 0x2a8b4f07, 0xd370a286, 0x579a840a, 0x0c270a3b, 0x25000d00, 0x18002240, 0x2b095d8a, 0x02010357, 0x005f0002, 0x4f000200, 0x0d2c2882, 0x21140c00, + 0x2b180604, 0x22231501, 0x09ad7818, 0x96ba0436, 0xa067af66, 0x0393f891, 0xaf67a00c, 0x0428fb66, 0x91f893d8, 0x83082758, 0x40272d57, 0x02010024, + 0x01038601, 0x00020200, 0x53825782, 0x02005f36, 0x014f0200, 0x060a0c00, 0x010d0005, 0x1606040d, 0x1632132b, 0x08107918, 0x8c352322, 0x22061776, + 0x820c0396, 0x8357835d, 0x72898268, 0x0229051b, 0x006009a8, 0x4024000d, 0x21b38321, 0x5a840085, 0x02211d82, 0x21b7825f, 0xb28c0200, 0x3335032e, + 0x35363632, 0x14113311, 0x0a230606, 0x0221b187, 0x23b1836c, 0x28fbd804, 0xd74a6a82, 0x22578409, 0x18234026, 0x830f9d5f, 0x8e0020be, 0x190120b2, + 0x2508e622, 0x15333316, 0xb3872404, 0x826c0221, 0x875983b3, 0x000229b3, 0x04feff3a, 0x003a0476, 0x30351360, 0xfb3c043a, 0xfd8a03c4, 0xfb3a0428, + 0x00039ec4, 0x86af82fd, 0x05200853, 0x00070012, 0x40480012, 0x06011045, 0x094c0107, 0x05000301, 0x01025703, 0x05010800, 0x67050007, 0x06231e82, + 0x18060704, 0x2b10cf5e, 0x11120000, 0x0c0d0e0f, 0x08090a0b, 0x3a082382, 0x11111107, 0x2b19060a, 0x11330701, 0x37211121, 0x23112101, 0x33032303, + 0x04211313, 0xfbb84503, 0x42c602c4, 0xd802aafd, 0xb2e0cc39, 0xfe825cc5, 0xd812051c, 0x3c04c4fb, 0x828afbd8, 0x0180268f, 0x01f3fee0, 0x219682ad, + 0xeb8c0300, 0x39001324, 0xae643640, 0x246a8207, 0x0102030b, 0x2b19764c, 0x01238c82, 0x18071737, 0x41072683, 0x012c0809, 0xe475e36c, 0xe7e375e4, + 0x75e8e875, 0x21081641, 0x1287f801, 0x75e3e725, 0x82080000, 0x2e7e0869, 0x3604b004, 0x29001400, 0x4a003e00, 0x60005600, 0x8a007500, 0xae40b100, + 0x18242e3a, 0x0606060d, 0x1a383907, 0x8a0a0203, 0x5a5b5c5d, 0x070c1959, 0x89020d09, 0x0c036275, 0x696b8000, 0x050c0b03, 0x0101114c, 0x13850103, + 0x03031205, 0x15850307, 0x07031409, 0x16850706, 0x02060a01, 0x80020a06, 0x0d020104, 0x7e0d0206, 0x0c0b0110, 0x010e860b, 0x0d0c000d, 0x06010859, + 0x060c0000, 0x0f826700, 0x0c0d3c08, 0x0c010f61, 0x57510c0d, 0x3f4b4b57, 0x152a2a3f, 0x86000015, 0x7a7e7f84, 0x6d717278, 0x5765676c, 0x4b5f5760, + 0x51554b56, 0x3f4a3f4f, 0x2a434549, 0x363d2a3e, 0x15291534, 0x821c1e28, 0x191322b9, 0x08bf7c17, 0x07150738, 0x27272107, 0x35262635, 0x33363634, + 0x17171600, 0x06062715, 0x0f832223, 0x83373721, 0x20332705, 0x07141516, 0x7e181617, 0x0722078a, 0x29823735, 0x177f7518, 0x1522ff82, 0x4f821737, + 0x17052323, 0x21488607, 0x4e842737, 0x16323324, 0x3a822117, 0x49843220, 0x05840720, 0x26229d08, 0x02372727, 0x1c5493b5, 0xfe56341c, 0x1e3256fe, + 0x5c94541c, 0x0a2141fe, 0x2a226638, 0x24201616, 0x17101a1e, 0x17d70315, 0x241c1a10, 0x2b161420, 0x0a386623, 0x6cfd2422, 0x221f2f2e, 0x01232d2e, + 0x222e2e04, 0x20303020, 0x460b2ba2, 0x10290b44, 0x8c34f2fe, 0x171e1f07, 0x1c1a0a1d, 0x12191f2a, 0x3a032725, 0x19122826, 0x1c1c281d, 0x1e171f0c, + 0x348a071f, 0x8b503604, 0x2e6b3357, 0x96962468, 0x6b2d6824, 0x4f8c5734, 0x353fa8fe, 0x152a6e20, 0x19151711, 0x13360520, 0x1d1d131b, 0x4f080482, + 0x19200536, 0x15111715, 0x35206622, 0x222e0a3f, 0x22303121, 0x232d2d23, 0x21313022, 0x3aa42e22, 0x0e0e3a20, 0xd839213a, 0x453b5654, 0x1b0d1721, + 0x15192130, 0x12130d1d, 0x19161c0e, 0x10183021, 0x3b452117, 0x00005456, 0x96000300, 0x1a049d00, 0x41639118, 0x84039624, 0x03877cfc, 0xa1430426, + 0xa2e0a2e1, 0x04205f82, 0x0f375f8e, 0x2d403000, 0x03000102, 0x00040101, 0x04006701, 0x04060500, 0x70006705, 0x13211ab7, 0x05a25121, 0xf3590520, + 0x01962606, 0x02a2fe5e, 0x21058326, 0x718adafd, 0x739ca120, 0x012d8b82, 0x67010002, 0x05020104, 0x02060301, 0x2073a003, 0x84778a15, 0x84778fdd, + 0x85a220e5, 0x900520e7, 0x001324e7, 0x89324035, 0x010626e9, 0x05010704, 0x2deb8308, 0x08090908, 0x08080057, 0x09005f09, 0x446c0908, 0x20ee8b0f, + 0x83828225, 0x92f28cf6, 0x85fa8386, 0x116f4188, 0x2e403122, 0x0f8b7718, 0x05238b82, 0x82570405, 0x05042206, 0x2095825f, 0x077c5604, 0x08101124, + 0x93181e06, 0x81830c3a, 0x8908da41, 0x23fa8479, 0xa2a2a2e0, 0x00205a82, 0x3622fb93, 0xe5413340, 0x01082611, 0x06070706, 0x27068257, 0x095f0706, + 0x07060701, 0x7f41fc9b, 0x23fc8c07, 0x7cfc8403, 0xf541868c, 0x96888405, 0x11f94187, 0xff4187a5, 0x0806410b, 0xfd217b89, 0x23878cda, 0xa1a1a2e1, + 0x20061041, 0x120b4206, 0x3c001724, 0x0d423940, 0x010a2613, 0x08090908, 0x27068257, 0x0b5f0908, 0x09080901, 0x42130d72, 0x93841314, 0x9b8e8f95, + 0x88a1a121, 0x6405209d, 0x3508061f, 0x000f0036, 0x002b001f, 0x00450037, 0x10664069, 0x0809020b, 0x02090802, 0x01010c80, 0x0503010d, 0x0f690301, + 0x05030e07, 0x0a040106, 0x00690405, 0x0908000a, 0x4218080a, 0x383a1091, 0x202c2c38, 0x00101020, 0x38453800, 0x3d404245, 0x2c393b3c, 0x32362c37, + 0x08192030, 0x11200f45, 0x2008dd45, 0xd7481806, 0x80431808, 0x4506200e, 0x3524067c, 0x20333634, 0x132c0b8a, 0x07222326, 0x33023e23, 0x17161632, + 0x0aa74218, 0x7594f732, 0xc16f6fc2, 0x71c17476, 0x7a74c171, 0x2a2a3636, 0x01210382, 0x2908866a, 0x999a2c2a, 0x4d09582d, 0x02824d7b, 0x04092408, + 0x93f79036, 0x9191f893, 0xf79394f7, 0xc7766890, 0x75c87775, 0x7576c975, 0x34c076c7, 0x35352926, 0x87342629, 0x02fe2907, 0x7a4ab2b2, 0x4a7a4848, + 0x2505df42, 0x0400003c, 0x33410474, 0x0a042412, 0x410a0904, 0x09201233, 0x20063341, 0x20334102, 0x41424425, 0x413b3d40, 0x0e2a5233, 0x26222302, + 0x16332726, 0x46183233, 0x33410b35, 0x4182201e, 0x5824072e, 0x2c9a992d, 0x202c3341, 0x053141d2, 0x00b2b222, 0x04200082, 0x080a6742, 0x27001b32, + 0x58003700, 0x06005540, 0x06070807, 0x010a8008, 0x0b050c01, 0x01020303, 0x01046903, 0x02090d02, 0x07020607, 0x00080067, 0x00590800, 0x61000808, + 0x00390882, 0x1c282851, 0x0010101c, 0x28372800, 0x2f323437, 0x1c2a2c2e, 0x22261c27, 0xb37d1820, 0x420e200a, 0x02201254, 0x16837d18, 0x0606132b, + 0x27262223, 0x33021e23, 0x49471832, 0x94f7220d, 0x063242d8, 0x862a0121, 0x142a2e08, 0x6a52526a, 0x50095614, 0x804d4d80, 0x0e3d4250, 0x42e2fe21, + 0xbe2a1031, 0x52606052, 0x47477a49, 0xfe82497a, 0x2008a771, 0x08fb871e, 0x2223256f, 0x02030421, 0x05070800, 0x00020520, 0x020c1907, 0x17180106, + 0x0f111416, 0x02080d0e, 0x004c0406, 0x07010805, 0x69070500, 0x03000104, 0x00060101, 0x06006701, 0x59060202, 0x02060600, 0x0602005f, 0x28284f02, + 0x36283728, 0x18111827, 0x09171118, 0x012b1d06, 0x17371716, 0x33171607, 0x07062315, 0x06270717, 0x35231507, 0x27072726, 0x2be88237, 0x37363335, + 0x36173727, 0x02333537, 0x0e254518, 0x47880234, 0xa248a241, 0xdede0c32, 0x489e2e0c, 0x604d3f9e, 0x07823b51, 0x820b2f21, 0x30440810, 0x41a048a0, + 0x636f6049, 0x3f633838, 0x3939643f, 0x48033f64, 0x48a42d09, 0x5e523ea0, 0x489c3a50, 0xdc0c2aa0, 0xa02a0cdc, 0x47439c48, 0xa040505e, 0x082ea448, + 0x3ad2fed6, 0x663f3f67, 0x3f663939, 0x003a673f, 0x30080082, 0x00160102, 0x04980300, 0x001a0036, 0xb67f002a, 0x00020712, 0x4b4c0106, 0x58500ab0, + 0x06002940, 0x06000007, 0x01020072, 0x01088602, 0x07010905, 0x2afb8506, 0x57000101, 0x00000104, 0x82036001, 0x5001240a, 0x832a401b, 0x0607232b, + 0x2ca18000, 0x1640592c, 0x00001b1b, 0x291b2a1b, 0x77822123, 0x82111921, 0x0a183e00, 0x002b1b06, 0x14151616, 0x15070606, 0x15231533, 0x35233523, + 0x022e3533, 0x36363435, 0x0e854433, 0x94ae0232, 0x4d7c4756, 0xc060c0c0, 0x477d4ec0, 0x3f589355, 0x360a0941, 0x91543604, 0x54844f57, 0xd250a60b, + 0x0ba450d2, 0x574f8555, 0x905c5491, 0x002708fb, 0x04000078, 0x00ce0338, 0x00310021, 0x1b47404a, 0x04030207, 0x0306011a, 0x01050109, 0x01004c03, + 0x01060506, 0x7d008005, 0x300808a7, 0x01060107, 0x00690603, 0x05020205, 0x05050059, 0x02006102, 0x22510205, 0x22312222, 0x26442730, 0x0810112c, + 0x012b1c06, 0x27071305, 0x27373427, 0x45cf8501, 0x3228084b, 0x06270117, 0x27272223, 0x3210eb41, 0x16ac0176, 0x07010a58, 0x23d8fe04, 0x58945627, + 0x82559358, 0x535b2ad4, 0x10023001, 0xc8121f1d, 0x35de8af5, 0xfe16ce03, 0x19c60454, 0xfe022a1d, 0x39682bd2, 0x51518e57, 0xe182578e, 0x2e013228, + 0x08010104, 0xe98d9cfe, 0x8c000122, 0x242fc182, 0x1c003604, 0x25402800, 0x00020a11, 0x1801044a, 0x2d15c940, 0x13111123, 0x1b060526, 0x021e012b, + 0xab821415, 0x13272627, 0x37211721, 0x05994321, 0x34353b08, 0x37373636, 0xa9aa6c02, 0x4c5a6a65, 0x01202a6e, 0x68fc5038, 0x20380150, 0x5a4c6e2a, + 0xaaa9656a, 0x9d240414, 0x6054a8ad, 0xfe453f72, 0x018282f2, 0x723f450e, 0xada85460, 0x7082129d, 0x2c288787, 0x3b403e00, 0x05121926, 0x4c378683, + 0x00070108, 0x01068507, 0x01010500, 0x69010002, 0x03020104, 0x82570203, 0x03022e06, 0x0203005f, 0x00004f03, 0x2b002c00, 0x279c8325, 0x06092725, + 0x16002b1d, 0x07209c82, 0x9007114c, 0x822620a6, 0x323324a7, 0x84261716, 0xc7022f08, 0x28333981, 0x635f2c32, 0x483b5f36, 0xb48a2868, 0x3b47673b, + 0x5f63365f, 0x3328322c, 0x046f8139, 0x495e6036, 0x0b112a59, 0x603d6f7b, 0x2bc08935, 0x6f3d6035, 0x2a110b7b, 0x605e4959, 0x01348a82, 0x00006400, + 0x36044c04, 0x18001500, 0x07121540, 0x02490002, 0x0021b982, 0x231c8276, 0x2e140015, 0x09285218, 0x26070223, 0x20838302, 0x828d8336, 0x032708ae, + 0x7d3869ab, 0xc4b3b1c6, 0x4769387d, 0x30307963, 0x36046379, 0x6e447143, 0xd2fdfefb, 0xfb0001d4, 0x4371446f, 0x82686864, 0x00002860, 0xffd00001, + 0x82e003e8, 0x084b5d67, 0x02091331, 0x018801d0, 0x0278fe88, 0xfd220214, 0x82d4fdde, 0x00012272, 0x2c8f8284, 0x00620556, 0x40230006, 0x01010120, + 0x0a916f02, 0x00850224, 0x99830101, 0x00062308, 0x04121106, 0x012b1806, 0x01330113, 0x4a010123, 0xc16801e3, 0xfee048fe, 0xfd6403c6, 0xfa8f046f, + 0x7784039e, 0x00053308, 0x04c2010a, 0x009903a5, 0x00210019, 0x002b0025, 0x4b67032e, 0x585009b0, 0x01021440, 0x272a0600, 0x000c0303, 0x0401010e, + 0x0105010f, 0x4b1b4c04, 0x1b860bb0, 0x1b8b0320, 0x1b850220, 0x379a0c20, 0x379a0f20, 0x379a1020, 0x379a1220, 0x379a1320, 0x379a1620, 0x37981720, + 0xda90f684, 0x00875920, 0x08051a41, 0x010d3122, 0x0c000003, 0x00690003, 0x0104000c, 0x0068040c, 0x01020501, 0x090f0a59, 0x0b100603, 0x05070e08, + 0x2508aa58, 0x01020061, 0x37415102, 0x822b2006, 0x0d062221, 0x183c9005, 0x20078e70, 0x203c855f, 0x20328206, 0x2032824f, 0xb4a6820c, 0x820f206b, + 0x206bae38, 0x206bb710, 0x206bb112, 0x206bb713, 0x206bb116, 0x206bb517, 0x2b3e4140, 0x08081e42, 0x262a402b, 0x1a222226, 0x2e00001a, 0x262b262d, + 0x2228292b, 0x24252225, 0x1a211a23, 0x1e1f2021, 0x001b1c1d, 0x24180019, 0x06112424, 0x339f1819, 0x16142609, 0x37363233, 0x09874b17, 0x27015d08, + 0x13230723, 0x11011333, 0x27131123, 0x17073337, 0x02330701, 0x231d3da8, 0x4a3b3728, 0x31213c49, 0x56352116, 0x34345a39, 0xc1fe375a, 0x4222ad22, + 0x02935293, 0xb0f54220, 0xb6aa4aaa, 0x8e4820fc, 0x17169903, 0x5e58222a, 0x1215585e, 0x6b37332a, 0x376a4a4a, 0x717131fe, 0x39fec701, 0xf3380387, + 0x01f7d0d4, 0x0200ec92, 0x00003b00, 0x62057504, 0x0b000700, 0x24402700, 0x03251182, 0x67030201, 0xc3b31805, 0x0104240b, 0x62000100, 0x10260595, + 0x2b1c0606, 0x887e2121, 0x83012005, 0xda3d0807, 0x2c0161fe, 0xa0016e01, 0x2d01d3fe, 0x83017dfe, 0x9ac8049a, 0x009d38fb, 0x01030104, 0x03bd03c2, + 0x00210099, 0x0037002f, 0x400a0240, 0x07011614, 0x08012d03, 0x02040507, 0x4c030801, 0x20238215, 0x0558434b, 0x02002b2f, 0x59020305, 0x01060500, + 0x03050703, 0x25918269, 0x08070108, 0x89820969, 0x01000423, 0x23088304, 0x00610001, 0x52438a82, 0x05252407, 0x82060201, 0x8d02202d, 0x0100242d, + 0x82010959, 0x84612035, 0x232c83b7, 0x4058500c, 0x0f205fae, 0x5fa83282, 0x5fb11020, 0x5fab1220, 0x5fb11320, 0x5fab1620, 0x5faf1720, 0x1a414020, + 0x091c4325, 0x3c3e0e2f, 0x21282124, 0x232a232a, 0x1f060a21, 0xf2f6182b, 0x4727200c, 0x250805c0, 0x26071732, 0x15062223, 0x16171614, 0x06041516, + 0x33112323, 0x14151632, 0x15160706, 0x15232302, 0x35363233, 0x08862616, 0xbd039b08, 0x3e654f5a, 0x2a4c3226, 0x4a38293a, 0x59425548, 0x3d30243b, + 0x402f3126, 0x72fe4441, 0x767f4a63, 0x25305d46, 0x3e565668, 0x12292843, 0x45482c32, 0x0c023829, 0x302a3b4a, 0x25202729, 0x333c1710, 0x29354334, + 0x1b1f2129, 0x3c131322, 0x013d423c, 0x293d36c7, 0x5c130832, 0x238d1201, 0xa025a126, 0x00002b22, 0xff0f0002, 0x0597044a, 0x002a007b, 0x404e0039, + 0x0227284b, 0x01180402, 0x35360207, 0x0706030b, 0x02004c03, 0x06070109, 0x00690702, 0x00010006, 0x00690106, 0x02820003, 0x0400652d, 0x08610504, + 0x3e050501, 0x822b4e04, 0x392b2549, 0x3032382b, 0x29374682, 0x26242526, 0x1b090a26, 0x1204002b, 0x06021015, 0x26262223, 0x83062327, 0x10352207, + 0x32f18212, 0x16141117, 0x36363233, 0x26023435, 0x07062223, 0x4a213627, 0x14830548, 0x11376c08, 0x03232626, 0x620c0129, 0x4d778131, 0x0801346a, + 0x9e6c8422, 0x4bc0ce94, 0x3f445088, 0x430c3337, 0xde70acba, 0x01fd6575, 0x2960c22c, 0x4d3c5144, 0x381d1026, 0xe37b0522, 0xfef095fe, 0xa4bdfef4, + 0x533b845c, 0x01d3f76e, 0x22070100, 0x8fb0fd2b, 0xdeed926e, 0xab2601d8, 0xdd756652, 0xa65372fd, 0x37a49c86, 0xf9012d46, 0x82000d0f, 0xff663cff, + 0x057c04e7, 0x00230079, 0x40480030, 0x02020345, 0x011b0001, 0x112f0102, 0x82020602, 0x080125fe, 0x06020205, 0x3b06dc68, 0x04010761, 0x004d3e04, + 0x61030606, 0x3f030300, 0x24254e03, 0x2b2d0000, 0x30253024, 0x22274182, 0x25251123, 0x441a0909, 0xeb4105fe, 0x33162506, 0x11231521, 0x2626fe84, + 0x37363435, 0x49492635, 0x18132005, 0x08076859, 0x3736326d, 0xa3940211, 0x6834704e, 0x3e676147, 0x2602416d, 0x9dce3cab, 0xa163cc95, 0x5f737d97, + 0x5e1172af, 0x7a3a3e81, 0x267d4e5b, 0x54427905, 0x6a343a65, 0x3d663b59, 0x4ce3fd8f, 0x6fbd736c, 0x0620c49c, 0x5a6a9b1e, 0x43fd5997, 0x4b4a8a59, + 0x2f334b7b, 0x0000dc01, 0x4d000100, 0x610455fe, 0x0f006205, 0x23402600, 0x01020506, 0x82490104, 0x86012116, 0x2307d859, 0x4e003802, 0x0f2d0b82, + 0x13130e00, 0x2b180904, 0x11071101, 0x20038223, 0x05ad4c2e, 0xac61043d, 0xdb9cacd7, 0xa2e5756e, 0x09f96205, 0xf9750616, 0xe40316a1, 0x72b36a03, + 0x826ab974, 0x00240838, 0xffcb0002, 0x05e30370, 0x0034007b, 0x40370042, 0x00010234, 0x2e3b4203, 0x0603141d, 0x011c0002, 0x4c030201, 0x01232482, + 0x82650102, 0x6103262e, 0x03030104, 0x2a73843e, 0x21330034, 0x25191b1f, 0x41170905, 0x17220d2e, 0x1243021e, 0x06143005, 0x27222306, 0x33161637, + 0x34353632, 0x84272626, 0x41372095, 0x0223053d, 0x19141506, 0x08070b1d, 0x02272653, 0x564aa5e2, 0x534e7a3f, 0x67672765, 0x5940846e, 0xb3647647, + 0x5693cc74, 0x554f803e, 0x6866276d, 0x5b40856f, 0xb0667647, 0x352ec76d, 0x2f2a9f79, 0x059d7b35, 0x7e34387b, 0x3d49292b, 0x22343a2d, 0x4f6f5124, + 0x582c824e, 0x48865a83, 0x2a2c7e6f, 0x3c158248, 0x51262233, 0x814d506e, 0x5981592c, 0x9afd4988, 0x40382857, 0x57263935, 0x363f3529, 0x82cd833a, + 0xee3b08f3, 0xd9057c04, 0x1f000f00, 0x63003800, 0x446406b1, 0x01225840, 0x232d0704, 0x2e040502, 0x03050601, 0x0101084c, 0x07030109, 0x0a690301, + 0x04000701, 0x69040705, 0x06000500, 0x52060502, 0x202f10e1, 0x00101020, 0x20382000, 0x2c2f3137, 0x1824262a, 0x350a6f55, 0x2b17090b, 0x440006b1, + 0x15121600, 0x23060214, 0x35022622, 0x4f4e1234, 0x16162110, 0x21086244, 0x75473233, 0x0366080b, 0x8282f703, 0xf9aaa9f7, 0xaaf98383, 0x6060c18c, + 0xc08b8cc1, 0x8bc06060, 0x4b366a52, 0x63505046, 0x4a5c5360, 0x61886945, 0x95575395, 0xa7d9055b, 0xb0b0e1fe, 0xa7a7e2fe, 0xb0b01e01, 0x6aa71f01, + 0x9495ed8a, 0xec8989ec, 0x8aed9594, 0x642a278d, 0x7e837e39, 0x5e66437e, 0x7879ac58, 0x040059ac, 0xd5015600, 0x0b415804, 0x2c350806, 0x6c003400, + 0x446406b1, 0x01256140, 0x4c010806, 0x06050107, 0x02050602, 0x01010a80, 0x0403010b, 0x0c690301, 0x010d0401, 0x09040809, 0x00080069, 0x06080506, + 0x82561867, 0x2d2d370f, 0x10102021, 0x342d0000, 0x2e30332d, 0x28292a2b, 0x2c202627, 0x16412c21, 0x410e200a, 0x16200816, 0x0c4f5718, 0x210e664f, + 0x1d823207, 0x23170737, 0x23152327, 0x33151711, 0x34353632, 0xeae50223, 0x8deb8889, 0x08d5838d, 0xb8718d45, 0x71b86969, 0x6868b771, 0xfa1f71b7, + 0x8aa93c47, 0x76763793, 0x7b3c3b3d, 0xed8ad905, 0x89eb8c8d, 0x8d8ceb89, 0x6f648aed, 0xbc7272bf, 0x72bc6e6e, 0x7d6fbf72, 0x11513caa, 0x02d7d7ec, + 0x29a65b34, 0x82004f2e, 0x012c0800, 0x54021100, 0x63058c04, 0x3e001c00, 0x0b1b3b40, 0x03010307, 0x01004c01, 0x01030003, 0x02048000, 0x84000002, + 0x06020708, 0x57060303, 0x136b0783, 0x00002608, 0x1c001c00, 0x30008211, 0x09111717, 0x012b1d06, 0x26032313, 0x23373435, 0x82018203, 0x030725de, + 0x11231323, 0x4e080182, 0x13132135, 0x861e6e04, 0x07040212, 0x066f885b, 0x800f0104, 0xc08bc91a, 0x5665db02, 0xf1fc6305, 0x2142af01, 0xd0fd343f, + 0x48383002, 0x4ffe1c38, 0x6afd9602, 0xfd799602, 0x002602da, 0x03850002, 0x05180362, 0x000f00dd, 0xb137001f, 0x18446406, 0x412bcf5f, 0x0235256e, + 0x5c5c9824, 0x97555698, 0x55975d5d, 0x302f4f2e, 0x4f2f2e4e, 0x3a08822e, 0x904cdd05, 0x4c906261, 0x6062924c, 0x2a814c8f, 0x563d3c54, 0x3d542b2b, + 0x822b543d, 0x032e08fe, 0x92003b00, 0xcc047504, 0x22001900, 0x3e002b00, 0x01183b40, 0x24250102, 0x010e1b1c, 0x0d020306, 0x0300020b, 0x01194c03, + 0x010c4a01, 0xb1734900, 0x00692206, 0xe05e1803, 0x2727290d, 0x0604272b, 0x07012b1a, 0x2308b550, 0x37270727, 0x08067545, 0x1716323b, 0x01170037, + 0x06222326, 0x27241506, 0x32331601, 0x04353636, 0x312cab75, 0x4e7ed57c, 0x5cab3b8d, 0x7c302cab, 0x8e4d7ed4, 0x0cfdab3b, 0x4ca80131, 0x538d535a, + 0xfe316602, 0x2a098458, 0x3bab7004, 0xd57e4d8e, 0x822d307c, 0x8d3b2e2a, 0x7dd47e4e, 0xfdab2c31, 0xa8014c89, 0x23298231, 0x58fe4c5a, 0x002a0783, + 0x01020100, 0xaf02a8fd, 0xa1820807, 0x18401121, 0x390ce794, 0x012b1809, 0x02231133, 0x07aeae01, 0x00a0f608, 0x00020200, 0xae0234ff, 0x2b824e06, + 0x211b4a18, 0x841a0921, 0x8311203e, 0xae002142, 0x2d080082, 0x37fd4e06, 0x37fd78fe, 0xa2000200, 0xd103e7ff, 0x1c00dd05, 0x3f002600, 0x18203c40, + 0x0a0b0c0d, 0x03020701, 0x02000102, 0x01004c02, 0x0c550105, 0x22768207, 0x18010459, 0x2708f3aa, 0x00001d1d, 0x251d261d, 0x1b273a82, 0x0606242a, + 0x19242b18, 0x08087d35, 0x27073578, 0x36341137, 0x16163233, 0x07021415, 0x33161411, 0x11150602, 0x34353636, 0x2b032326, 0x8431325a, 0x4d91624e, + 0xabd24290, 0x417c54a1, 0x4f59d4cc, 0x6e814068, 0x24853431, 0x4b201989, 0x69ba608c, 0xc4019f5c, 0x7842dfd0, 0xd0fead4e, 0x48b6fe9e, 0x86d20443, + 0x79cafe93, 0x3e4381d4, 0xab000100, 0x05040000, 0x0b004a05, 0xb04b4500, 0x40585029, 0x00000017, 0x9f834d38, 0x055f0130, 0x3b010101, 0x0303004d, + 0x1b4e0339, 0x148c1740, 0x03000023, 0x2319855f, 0x11094059, 0xa2180083, 0xfc341176, 0xfe5101b8, 0xaffeb8af, 0x4a055101, 0xfca0ccfe, 0xa076038a, + 0x778a5f82, 0x86001322, 0x21227785, 0xb3180107, 0x218207e0, 0x084d3828, 0x01020201, 0x8185095f, 0x39050528, 0x4b1b4e05, 0xa0822db0, 0x238c288a, + 0x05000024, 0x2885005f, 0x821f4021, 0x231c8237, 0x67020103, 0x2187568c, 0x40595925, 0x8412130e, 0x290482b5, 0x1f090a10, 0x1133012b, 0x55631521, + 0x11232405, 0x83213521, 0x85012003, 0x86c488c0, 0xbe2a08c8, 0xa074fea0, 0x3c01c4fe, 0xa08c01a0, 0x2a000200, 0x8e04e8ff, 0x16007a05, 0x53001e00, + 0x181b5040, 0x05040213, 0x02011206, 0x89470500, 0x002a0808, 0x07800102, 0x01080401, 0x06040506, 0x00050069, 0x00050200, 0x03010067, 0x00590103, + 0x61030101, 0x03010300, 0x00171751, 0x8a191700, 0x122609c9, 0x06091322, 0x13822b1a, 0x11211128, 0x36323316, 0xd0483337, 0x11272605, 0x06330036, + 0x08158207, 0x23262643, 0x11015a03, 0x71a0fc23, 0x34c688c3, 0xb7f03f62, 0x198aeda6, 0xfe110123, 0x56026cc2, 0x055a9c30, 0xd0fefe7a, 0xf6fdf4fe, + 0x7d5d655e, 0x85cb7491, 0x01d0fc01, 0xfe544e02, 0x27ec0112, 0x0400002f, 0x20048300, 0x24bf8294, 0x001c000a, 0x080d822b, 0x0a40883a, 0x0706010e, + 0x00080117, 0xb04b4c02, 0x40585015, 0x00060024, 0x00060800, 0x07010c69, 0x0b5f0107, 0x040a0405, 0x4d1a0101, 0x02080800, 0x0203095f, 0x021b0202, + 0x28401b4e, 0x0b262687, 0x04040205, 0x2d844d1a, 0x010a6125, 0x8d1f0101, 0x5924082a, 0x1d1d2240, 0x00000b0b, 0x2c2d2e2f, 0x2a1d2b1d, 0x1c0b2325, + 0x15161c0b, 0x0c0d1314, 0x09000a00, 0x17070d24, 0x3805a753, 0x35262223, 0x11052110, 0x16230323, 0x23111512, 0x33133311, 0x11350226, 0x0cf05604, + 0x03235a08, 0x04211521, 0x8a7a771d, 0x0501788d, 0xd9e1d5fe, 0x90150708, 0x0808d5e5, 0x2a970114, 0x25291111, 0x2a112a25, 0xea01f436, 0x7a0516fe, + 0xead2d7e6, 0xbd01d6e6, 0x049efa18, 0xcbfe3389, 0x056bfd8c, 0x3972fb62, 0x029f2101, 0x89456895, 0x4488706f, 0xa6708844, 0x989efb97, 0x08008200, + 0x3b000539, 0x8404ca01, 0x0d009103, 0x1f001900, 0x30002700, 0x49404c00, 0x0304010b, 0x07094c01, 0x010b0102, 0x02010302, 0x03010c69, 0x0504010d, + 0x0e690403, 0x0005020a, 0x83570500, 0x00053507, 0x02060860, 0x50000500, 0x292b2c2e, 0x20222325, 0x1c1d1e1f, 0x23057d42, 0x0f212118, 0x4c05b74c, + 0x01200a95, 0x07016818, 0x21112129, 0x33112101, 0x4c003311, 0x01210fa7, 0x088b4c67, 0xc07a0131, 0xfecca7a7, 0x010901f2, 0x41f8fe95, 0x4c8dfcce, + 0x07200c9c, 0x240a824c, 0x9a349211, 0x06ac4f33, 0x5b017222, 0x3a08904c, 0xfe640001, 0xff4c0494, 0x0007009c, 0x17b04b41, 0x17405850, 0x02010103, + 0x18700102, 0x21099b78, 0x0b820060, 0x401b5023, 0x21198316, 0x188f8501, 0x82b65921, 0x078270d1, 0x21153331, 0x4c043335, 0x02b118fc, 0x94feb186, + 0x4a6a0801, 0x210805b7, 0xe7ffceff, 0xdd053104, 0x24001800, 0x52405500, 0x03020b0c, 0x15202102, 0x08030403, 0x03040101, 0x6363144c, 0x02083506, + 0x0401004a, 0x00010400, 0x02010580, 0x02040300, 0x01066903, 0x04210e82, 0x18068259, 0x2907cb62, 0x00001919, 0x23192419, 0x50821c1e, 0x25121729, + 0x2b180607, 0x4a111200, 0x8b0805c2, 0x07112307, 0x37113727, 0x05173715, 0x33363615, 0x10353612, 0x07062223, 0x33161611, 0x61c07103, 0x66b585bc, + 0x42afa90c, 0x40d5c0f1, 0x9739ebfe, 0xeb853758, 0x292f7e4c, 0x37044474, 0xfbfedefe, 0x848dfaa2, 0x5429046b, 0x0b017373, 0x7266c717, 0x524beb85, + 0xcac847fc, 0x475b9001, 0x453d02fe, 0x02000000, 0xb100f6ff, 0x0d055604, 0x20000600, 0x35403800, 0x03061314, 0x00030502, 0x03010101, 0x00004c02, + 0x04850003, 0x03010301, 0x20058177, 0x5ff31859, 0x07073409, 0x20072007, 0x0514252f, 0x012b1906, 0x11070107, 0x5a030721, 0x352705b7, 0x27262634, + 0x49021e37, 0x3f08075a, 0x7cab0227, 0x02d9a0fe, 0x0b52da2e, 0x60599963, 0x8b5160a4, 0xcf7d0755, 0x8bea8978, 0x0c8dde83, 0x017ad302, 0x2e02da60, + 0x574dfed9, 0xa360528d, 0x64985761, 0x8e0e9b0c, 0xea8b80de, 0x80d17989, 0x0432a782, 0xc2012700, 0x99037804, 0x21001900, 0x32002f00, 0x1d514103, + 0x02132b05, 0x03060001, 0x29000c01, 0x9055020e, 0x201a830e, 0x551a8a03, 0x35960a8f, 0x58500f23, 0x20359640, 0x921a8610, 0x9912206b, 0x99132035, + 0x99162035, 0x97172035, 0x509c9435, 0x1041084b, 0x552f2005, 0x09271787, 0x080b0602, 0x5504070e, 0x29251585, 0x0d06090a, 0x19845504, 0x05213a83, + 0x0a835505, 0x0f2067b2, 0x67acd782, 0x30821020, 0x122067b2, 0x132067af, 0x162067b5, 0x172067af, 0x402067b3, 0x42293241, 0x402f080a, 0x001a1a22, + 0x2f313200, 0x282c2d2e, 0x55252627, 0x0f20106b, 0x32246b55, 0x15151613, 0x13331123, 0x33353526, 0x07012311, 0x55180133, 0x0121146f, 0x066f55e1, + 0x3b097429, 0x3b099b57, 0x5535fe58, 0x8a301e6e, 0x01db4c63, 0x6874fec7, 0x39fedb49, 0x00ec9201, 0x032f0082, 0xc201ef00, 0x9903d603, 0x27001900, + 0x54033000, 0x163606ff, 0x07000102, 0x00090103, 0x0905011c, 0x0501010e, 0x0104010f, 0x3d584c05, 0x201d8306, 0x201d8d03, 0x231d8502, 0x4058500c, + 0x0f203b99, 0x3b951d86, 0x3b9c1020, 0x3b9c1220, 0x3b9c1320, 0x3b9c1620, 0x3b9a1720, 0xae92cc84, 0x080eff43, 0x01063122, 0x01020104, 0x0a800204, + 0x00070301, 0x07005903, 0x09000108, 0x00690007, 0x01050009, 0x00670509, 0x01201c82, 0x410ac945, 0x25240649, 0x03020a07, 0x03202a83, 0x85592a8b, + 0x04062108, 0x02200a82, 0xb3088159, 0x820f2065, 0x2065a8dd, 0xb42c8210, 0xab1220cb, 0xb7132065, 0xab162065, 0xb5172065, 0x41402065, 0x0042252c, + 0x18402308, 0xa0490000, 0x20212806, 0x001d1e1f, 0x18180019, 0x51080ea9, 0x57590ae0, 0x0604210c, 0x2407e050, 0x15163233, 0x07465626, 0x43e00121, + 0x023214e9, 0x85303c09, 0x4238784e, 0x45585679, 0x3e3d3330, 0x56593230, 0x40ba3913, 0xc0c0c80d, 0x4041c701, 0x29a32529, 0x0100002c, 0xc2022400, + 0x3e058d04, 0x09cb8918, 0x01134008, 0x01010701, 0x02340224, 0x3dfe7235, 0x40033efe, 0x02fefe01, 0xfe8b017e, 0x04000075, 0xca013400, 0x91037d04, + 0x0e000800, 0x22001a00, 0x3d404000, 0x0102030a, 0x0605010b, 0x00690501, 0x82070006, 0x0c6724b9, 0x82040208, 0x8357202d, 0x00043107, 0x02020960, + 0x50000400, 0x1c1e1f21, 0x1718191a, 0x2305a14a, 0x0d212113, 0x250ba14a, 0x33112105, 0xa24a3311, 0x8204200b, 0x331133f5, 0x6f013532, 0x646b5977, + 0x7e017760, 0xce41f8fe, 0x964a7d01, 0xb2fc3407, 0x31313a4a, 0x652f0284, 0x8061c701, 0xfec701e6, 0x4a5a0172, 0x7b250589, 0xb3a0fe47, 0x20af8600, + 0x20af8484, 0x4baf8714, 0x00280a57, 0x05040003, 0x0c670403, 0x8306554b, 0x09554b07, 0x2520af9d, 0x8f114c4b, 0x4b7220af, 0xa6200e40, 0xad20af8b, + 0x200c334b, 0x21b08413, 0x00820003, 0x05b00423, 0x08988262, 0x0b000722, 0x29402c00, 0x0102080b, 0x01000104, 0x0402054c, 0x00010003, 0x01010385, + 0x04047601, 0x090a0000, 0x09255418, 0x1606062c, 0x3501012b, 0x23012101, 0x03821301, 0x42032308, 0xa402befc, 0x51fcdc01, 0xceb0039f, 0x03a060fd, + 0xfb620540, 0xda03e83e, 0x62059efa, 0x29fc75fe, 0x6a83bf04, 0x01340031, 0x037f04c2, 0x00190099, 0x00310028, 0x48fb0339, 0x1b3b05ae, 0x02021024, + 0x0901110a, 0x05012202, 0x03010204, 0x06010305, 0x234c0503, 0x444a0101, 0x22840698, 0x228d0120, 0x22890020, 0x58500c23, 0x20459e40, 0x9922870f, + 0xa1102045, 0xa1122045, 0xa1132045, 0xa1162045, 0x9f172045, 0x96ef8545, 0x0e0f46cc, 0x00392c08, 0x01020a01, 0x0a010f59, 0x0902010d, 0x0069020a, + 0x09060409, 0x04010857, 0x03050107, 0x10670504, 0x03030e0c, 0x0006010b, 0x84690603, 0x0003260b, 0x03000061, 0x074c5c00, 0x820f3321, 0x203b833f, + 0x203b8401, 0x823b9000, 0x8759202c, 0x060b2238, 0x203a8602, 0xbcc4820c, 0x820f207b, 0x207bb640, 0x207bbf10, 0x207bb912, 0x207bbf13, 0x207bb916, + 0x207bbd17, 0x336e4140, 0x08086e42, 0x33284025, 0x00292a32, 0x32363800, 0x30393339, 0x2a31292e, 0x26272831, 0x1f202125, 0x1b1c1d1e, 0x0019001a, + 0x5f262418, 0x814605e5, 0x5832200c, 0x253c0a7c, 0x15231533, 0x35232723, 0x33031713, 0x32253337, 0x06141516, 0x13112323, 0x26343532, 0x02210782, + 0x0ae65fa1, 0xa2462c20, 0xc7013a08, 0x013d3838, 0x773584bc, 0xfc35087b, 0x77776051, 0x84726b59, 0x01313a4a, 0x09eb5ff8, 0x3807fd5f, 0x6c6c3270, + 0x1636012d, 0xab7ee5fe, 0x65818061, 0x6cfec701, 0xfe4766b3, 0x08a744a0, 0x99037922, 0x2226ad82, 0x35002d00, 0xa7443d03, 0x10123105, 0x2c040201, + 0x02112a2b, 0x03020305, 0x03030501, 0x8307814a, 0x89012019, 0x85002019, 0x500c2319, 0x33954058, 0x19860f20, 0x10203391, 0x12203398, 0x13203398, + 0x16203398, 0x17203398, 0xb0843396, 0x4d44968e, 0x4a2f200e, 0x0e39053c, 0x04030d09, 0x0302010b, 0x0f690204, 0x0c06080a, 0x01070305, 0x05030005, + 0x270d866a, 0x00620003, 0x52000300, 0x2006c245, 0x21308229, 0x64520404, 0x82238607, 0x89592020, 0x0507222e, 0x20308602, 0xb29e820c, 0x820f2067, + 0x2067ac36, 0x2067b510, 0x2067af12, 0x2067b513, 0x2067af16, 0x2067b317, 0x29324140, 0x3f080a42, 0x2e2f2840, 0x1a1b2323, 0x32340000, 0x352f352e, + 0x2d232d23, 0x26272829, 0x1f212425, 0x221b221a, 0x2406e943, 0x2b190610, 0x18e94300, 0xda430120, 0x11212b07, 0x35211533, 0x27071133, 0xe5430137, + 0x18fe311d, 0x59777760, 0x5de8036b, 0x6770f4fe, 0xc2fc891b, 0x2117e243, 0xd8439901, 0x33332607, 0x2d3f5101, 0x07e14355, 0x34000428, 0x6e04c201, + 0xa3829903, 0x49004026, 0xa7035100, 0x3705df43, 0x0001021a, 0x033d3e0b, 0x1f000703, 0x29070601, 0x01030e28, 0x0a010f06, 0x23054b4e, 0x4058500b, + 0x03202183, 0x6d4e2191, 0x20439d0a, 0x2043a00f, 0x99218610, 0xa0122087, 0xa0132043, 0xa0162043, 0x9e172043, 0x1b0a4143, 0x080e2f44, 0x090f3224, + 0x0b03030e, 0x00590300, 0x02080c0b, 0x000b0700, 0x00070069, 0x06070106, 0x02050d69, 0x020a0001, 0x09840a01, 0x61020125, 0x68020104, 0x2c210916, + 0x213a820b, 0x34840304, 0x348d0320, 0x01020223, 0x823c8359, 0x040a2132, 0x02210c82, 0x06176851, 0x0f206db5, 0x6dafee82, 0x33821020, 0x12206db5, + 0x13206db2, 0x16206db8, 0x17206db2, 0x40206db6, 0x522c4441, 0x243b09ab, 0x00001a1a, 0x4b4d4e50, 0x42444547, 0x3f1a401a, 0x3335393b, 0x2b2d3032, + 0x4e002426, 0x102005c1, 0x241cad52, 0x14151620, 0x05b45d06, 0x0ad6c718, 0x23233428, 0x36323337, 0x2a643435, 0x00332106, 0x20073765, 0x063d4d26, + 0x08163c68, 0x4e96012d, 0x3c2c2733, 0x4c2a4759, 0x3513291a, 0x5b332e1c, 0x231b0827, 0x1c242f31, 0x3922182c, 0x779dfd4d, 0x60646b59, 0x3a4a4577, + 0x4e843131, 0x270813fd, 0x3a293042, 0x32390408, 0x1f1f4f3c, 0x30171622, 0x28305329, 0x14272225, 0xfe362515, 0xc7016596, 0x47668061, 0x00b3a0fe, + 0x22086f48, 0x82990369, 0x003226e9, 0x0343003b, 0x058f4403, 0x01021230, 0x2e2f0900, 0x05030e24, 0x010f0001, 0x6f480105, 0x20198209, 0x20198903, + 0x23198502, 0x4058500c, 0x0f203395, 0x33911986, 0x33981020, 0x33981220, 0x33981320, 0x33981620, 0x33961720, 0x968eb084, 0x3d0e3f44, 0x0c070d2a, + 0x00090303, 0x09005903, 0x0002060a, 0x69000901, 0x0102040b, 0x02050108, 0x0a840501, 0x6c020121, 0x24210c4e, 0x21328209, 0x2c840304, 0x2c850320, + 0x01020223, 0x82348359, 0x05082129, 0xad0b2f44, 0x820f205d, 0x205da7c6, 0xad2b8210, 0xaa12205d, 0xb013205d, 0xaa16205d, 0xae17205d, 0x4140205d, + 0xd8412414, 0x20403708, 0x00001a1a, 0x3d3f4042, 0x34363739, 0x311a321a, 0x22232a2c, 0xeb432021, 0x430e2006, 0x062721eb, 0x21073307, 0x43023e35, + 0x362008db, 0x3629dc43, 0x55264c97, 0xfe07d34e, 0x225558ec, 0x2b202529, 0x431c2a15, 0x439cfd2f, 0x48321fd2, 0x5d4e2938, 0x54323447, 0x2524435f, + 0x211a162a, 0xca432122, 0x118a080c, 0xe2ff62ff, 0xd6054e05, 0x16000f00, 0x24001d00, 0x33002b00, 0x41003b00, 0x4f004700, 0x5b005500, 0x6b006300, + 0x7a007300, 0xa5008100, 0x333ba240, 0x2426282b, 0x191d2022, 0x020c1014, 0x35414701, 0x02070431, 0x4d52595e, 0x810b1004, 0x787a7c7f, 0x6b6c7175, + 0x0c4b6066, 0x4c041000, 0x02010112, 0x00008501, 0x03860010, 0x01080201, 0x07020407, 0x05060969, 0x0f160403, 0x0c140e15, 0x0b0a0713, 0x0d670a04, + 0x10100b01, 0x0682590b, 0x100b3a08, 0x10011161, 0x5c51100b, 0x5056565c, 0x00484850, 0x65727300, 0x5c635c64, 0x565b5663, 0x5057585b, 0x54555055, + 0x484f4853, 0x4344454f, 0x3e3f4042, 0x2f37383d, 0x1617182e, 0x08bf8215, 0x17260e24, 0x002b1706, 0x14151204, 0x22230402, 0x34350224, 0x07332412, + 0x07060722, 0x36331716, 0x26272637, 0x0b830423, 0x04373623, 0x250e8217, 0x06002726, 0x08822107, 0x82042721, 0x26212220, 0x21078226, 0x05833521, + 0x26211526, 0x16160127, 0x27212483, 0x22068333, 0x83153335, 0x84332006, 0x3736223d, 0x25078301, 0x33331632, 0x57843632, 0x82070421, 0x2038832c, + 0x094d8336, 0x0126033e, 0xfecbcb5d, 0xfececea3, 0x01cbcba3, 0x102ace5d, 0x7e498f06, 0x6f815070, 0x100a8e48, 0x44b3cffe, 0x76446242, 0x683ec201, + 0x67b1443c, 0x0441f7fc, 0x2c060401, 0x0c04506a, 0x01032d6a, 0x38420406, 0x01067efc, 0x01867e32, 0x340174c8, 0x28fc2903, 0x58374104, 0x4a062c62, + 0x867e2806, 0x298c7c50, 0x2d034a03, 0x41395761, 0x722cfd04, 0x0491477c, 0x0650060c, 0x4690080c, 0x1efe747c, 0x66b44446, 0x7b024575, 0x45b16679, + 0xd6056440, 0xcfa2fecd, 0xcda2fecf, 0xcf5e01cd, 0xcd5e01cf, 0xb0980250, 0x1f070620, 0x2b029aae, 0x242c4d6c, 0x9b877fa3, 0x6c4d2a26, 0xb9a8fe19, + 0x25888c63, 0x8b263031, 0x4eb96389, 0x06d282e8, 0xd2032926, 0xbafe7f7f, 0x3550b864, 0x86908423, 0xd4062478, 0x7b2703d4, 0x23878d83, 0x64b85035, + 0x2303e8fe, 0x02029eaa, 0x0323a8a0, 0x6c4e2f5b, 0x9da57b18, 0x4e6c1883, 0x0000212d, 0x17010200, 0xd103ca01, 0x0b009103, 0x4f001f00, 0x12154c40, + 0x1e000102, 0x02020701, 0x0207004c, 0x03070203, 0x090a0b80, 0x00000503, 0x67000501, 0x02000100, 0x67020107, 0x0a897018, 0x02060830, 0x4f040304, + 0x1f0c0c0c, 0x1c1d1f0c, 0x39621516, 0x0c102405, 0x552b1f06, 0x21350b07, 0x26272313, 0x23033735, 0x14151603, 0x13230707, 0x02131333, 0x085b5419, + 0x3d1a9732, 0x4901030d, 0x01024e3d, 0x541a3c0b, 0x5d034346, 0x3a075a54, 0x30373ee7, 0x3b01c5fe, 0x17303826, 0xfec701e7, 0x003501cb, 0x014f0003, + 0x849a04ca, 0x851320b7, 0x01172db9, 0x011a0001, 0x011d0102, 0x4c030203, 0x9b82b484, 0x7118b688, 0x0d230e9c, 0x8303070c, 0x1e1f27b7, 0x18191b1c, + 0xf0621516, 0x8e0e200a, 0x660520b9, 0x172d06e1, 0x37173327, 0x23170733, 0x01230727, 0x31b98851, 0x8c4287a5, 0x81ba5c01, 0x475f5f4a, 0x6c498e80, + 0xba87476d, 0x70fe372f, 0xd5379001, 0xd1aaaad5, 0x00c8c8f6, 0x28b38204, 0x039404c2, 0x000b0099, 0x22b38217, 0x4724022b, 0x2f2c058f, 0x02070100, + 0x010b5901, 0x080a0c07, 0x0722bc82, 0xd3556702, 0x010d3207, 0x06010905, 0x67060500, 0x0505010d, 0x00006100, 0x083c5305, 0x820b2921, 0x20318535, + 0x82318c01, 0x84592024, 0x095f232e, 0x30820206, 0xb2075859, 0x500f2367, 0x67ac4058, 0xaf06f84e, 0xaf1220cf, 0x06f84e67, 0x162067af, 0xf84e67af, + 0x4167ad06, 0xba462a32, 0x29162a09, 0x1f212327, 0x1b1c1d1e, 0x065b581a, 0x0e212422, 0x28055b58, 0x34352622, 0x16323336, 0x0bae5715, 0x21079642, + 0xbf6f2604, 0x32332905, 0x00033536, 0x58525258, 0xfe200383, 0x3a08a042, 0x42873503, 0xfe5c018c, 0x36363028, 0x36353130, 0x80420230, 0x816c6c7e, + 0x43b06d7f, 0xa6420561, 0x5b883005, 0x5a5b5c5c, 0x00005b5b, 0x014f0005, 0x438704ca, 0x2c08065b, 0x00290021, 0x404e0032, 0x02011f4b, 0x0b4c0101, + 0x0c050209, 0x00030608, 0x67000501, 0x0e01010d, 0x01030201, 0x010f6902, 0x03040403, 0x34068259, 0x0a5f0403, 0x03040207, 0x2e304f04, 0x25272b2d, + 0x181a2224, 0x0b5e4317, 0x5e431020, 0x08434b16, 0x43157b70, 0x01211071, 0x15707083, 0x210d7d43, 0xe16376fe, 0x0964700a, 0xe3820420, 0xab04583f, + 0x11009903, 0x2b001d00, 0x30023700, 0x01250f40, 0x01010405, 0x4c020500, 0x00020405, 0x059c4349, 0x9c432e20, 0x090a2405, 0x820c0702, 0x020722eb, + 0x0a9b4369, 0x23096943, 0x0306080b, 0x29066a43, 0x4058500b, 0x07090a29, 0x30830103, 0x30a10120, 0x30820c20, 0x0f2066b1, 0x102066af, 0x122066b4, + 0x132066af, 0x162066b4, 0x172066af, 0x964166b2, 0x0a97432a, 0x2f33352b, 0x292a2b2d, 0x14232428, 0x2e008311, 0x0e272413, 0x002b1f06, 0x17161607, + 0x18262607, 0x430802c6, 0x17200c9d, 0x200cde60, 0x0aa34300, 0x5f900431, 0x40103931, 0x4e383e16, 0x52525754, 0x46c1fc58, 0x9e20074a, 0x3306e160, + 0x3630bc01, 0x34313035, 0x11023036, 0x32310934, 0x7d333819, 0x200bb043, 0x0ce0603d, 0x5b5b3f39, 0x5b5a5b5d, 0x0003005b, 0x04c2014f, 0x00990399, + 0x003b0021, 0x42950347, 0x1a3405c0, 0x0d030124, 0x09021625, 0x04053003, 0x310a0103, 0x04010c01, 0x55050476, 0x21830641, 0x218c0220, 0x218a0020, + 0x58500c23, 0x20439d40, 0x9921860f, 0xa0102043, 0xa0122043, 0xa0132043, 0xa0162043, 0x9e172043, 0x96e88443, 0x0e3d4ec6, 0x0e312308, 0x0d020207, + 0x00590203, 0x0204080d, 0x030d0903, 0x00090069, 0x0a09010a, 0x02050b67, 0x000c0001, 0x09840c01, 0x61000124, 0x40770106, 0x0d2b250a, 0x0203070e, + 0x02203384, 0x0022338e, 0x3b835901, 0x0c223182, 0x32860206, 0xb2820c20, 0x0f206bb4, 0x6bae3882, 0x6bb71020, 0x6bb11220, 0x6bb71320, 0x6bb11620, + 0x6bb51720, 0x3e414020, 0x081e422b, 0x221c403d, 0x45464722, 0x41424344, 0x3d3e3f40, 0x223b223c, 0x2d24243a, 0x21232a23, 0x771d060f, 0x00202284, + 0x7a0ab35a, 0x05200da7, 0x210aad5f, 0x8b77f502, 0x43012119, 0x7a08bd5a, 0xfd210bba, 0x07694445, 0x211a9477, 0xc97a5001, 0x483c2011, 0x00260528, + 0x01020000, 0x5f7a0120, 0x022b2e07, 0x1610400e, 0x05030501, 0x06010204, 0x05524402, 0x3f057344, 0x0107002f, 0x00070100, 0x08020080, 0x00590203, + 0x03010408, 0x69030805, 0x06000500, 0x67060501, 0x01211b83, 0xe9851859, 0x06884409, 0x01082324, 0x29820402, 0x298b0220, 0x86000021, 0x43072029, + 0xc4590745, 0x2361b005, 0x4058500f, 0xc54a61a6, 0x2061b005, 0x4a61a912, 0x61b005bf, 0x61a91620, 0xae05b94a, 0x24204161, 0x2109ea42, 0x0082110c, + 0x2a231925, 0x7a092123, 0x104e245f, 0x11232206, 0x1c4a7a21, 0xb0c86c26, 0x110141b0, 0x081ba542, 0x3399142e, 0x00c701c7, 0x01200102, 0x03c103ca, + 0x00090091, 0x40340013, 0x03010831, 0x09860302, 0x01050401, 0x00040100, 0x01010667, 0x57010202, 0x01270682, 0x01075f02, 0x18020102, 0x890f734b, + 0x065e4393, 0x02219d82, 0x21818529, 0x07858801, 0x845d0321, 0x8434206e, 0x82002005, 0x00022200, 0x060743e4, 0x3e001c32, 0x56405900, 0x00010109, + 0x04020a33, 0x14212201, 0x192d8182, 0x04020501, 0x0101324c, 0x01084b01, 0x321c8200, 0x69010004, 0x03000400, 0x67030402, 0x05020107, 0x82590205, + 0x02210806, 0x0a066105, 0x05020502, 0x36000051, 0x252f3134, 0x001e2023, 0x111b001c, 0x25242412, 0x2b1b060b, 0x05597800, 0x300bc65e, 0x23353732, + 0x06153327, 0x06242306, 0x37272223, 0x05895616, 0x3914cf7b, 0x355f4301, 0x3c2c3458, 0x3529261d, 0x3a3a4736, 0x0754242d, 0x2d47239c, 0x3c442502, + 0x78c2341a, 0x366a4b74, 0x26281a19, 0x57605f57, 0xdb348515, 0x7b4a1513, 0x7c0818c4, 0xff070000, 0x04c9ffcc, 0x009d05e4, 0x002a0025, 0x0035002f, + 0x0040003b, 0x403b0045, 0x41444538, 0x38393f40, 0x31323337, 0x2a2b2e2f, 0x21222329, 0x171a1d20, 0x10141516, 0x0a0d0e0f, 0x02030407, 0x01002401, + 0x01004c01, 0x00850100, 0x1c760000, 0x0602181b, 0x07002b17, 0x06270717, 0x23150706, 0x27262635, 0x26372707, 0x27373435, 0x36361737, 0x15333537, + 0x37171616, 0x15160717, 0x211b8203, 0x26820303, 0x1704052d, 0x15062525, 0x05052724, 0x82013536, 0x1313211e, 0x25362982, 0x86338f04, 0xc2458846, + 0xc2708b70, 0x87488745, 0x48873232, 0x0e854488, 0x48882008, 0x34e23388, 0x7f08528c, 0x01348d51, 0x227cfe1b, 0xd7fe2901, 0x227d0322, 0x2901d7fe, + 0x82ecfc22, 0x0923081b, 0x348c527e, 0x3602e6fe, 0x5176516e, 0xb50e6f57, 0x576f0eb5, 0x6f527651, 0x526f7a79, 0x6f565176, 0x82b9b90e, 0x75523f11, + 0x017b6e53, 0x0d503d1f, 0x5101affe, 0xb83d4f0d, 0xacab52c1, 0x505b5a52, 0x5952abab, 0x1882e1fe, 0xfe530127, 0x3d500dad, 0x27e282b8, 0xfc000200, + 0xcc03ca01, 0x35065f4d, 0x092f4032, 0x08030205, 0x03040601, 0x04006706, 0x04000100, 0x12836701, 0x5f000328, 0x00020207, 0xb1420003, 0x23352911, + 0x33112315, 0x33353315, 0x2407054e, 0xa2412002, 0x20028241, 0x058e5001, 0xd4ca0127, 0xbdc701d4, 0x05db4dbd, 0x0200002a, 0x00005000, 0x36046004, + 0x092f6082, 0x1e402100, 0x02050607, 0x01060001, 0x1801004a, 0x080db4a5, 0x0213142d, 0x132b1806, 0x21110101, 0x21110209, 0x02060250, 0x03f0fb0a, + 0xfe82fe84, 0x02f80286, 0xfece0168, 0x0298fd32, 0xfe56012a, 0x8358feaa, 0x00043acf, 0x04e8ff00, 0x008006b0, 0x000d0006, 0x001b0017, 0x08544057, + 0x4a030201, 0x26d8820b, 0x0002020a, 0x84000304, 0x820720d9, 0x07002ed9, 0x07090800, 0x010c6708, 0x09060609, 0x3f068257, 0x005f0609, 0x4f060906, + 0x07071818, 0x1b180000, 0x191a1b18, 0x10131617, 0x0d070d07, 0x090a0b0c, 0x06235682, 0x820d1211, 0x01112a95, 0x21112101, 0x01012511, 0x36068233, + 0x23061413, 0x35262221, 0x35072135, 0x58021521, 0xaefe5802, 0x8302f4fd, 0x822c08a9, 0x5e5001d6, 0xbcfe2d37, 0x0c02372d, 0x04b0fe5e, 0xfd54022c, + 0x02d2fdac, 0x7a015a2e, 0xccfd86fe, 0xc6fb3402, 0x2d37372d, 0xa2a2f6ea, 0x022ac383, 0x380060ff, 0x42055005, 0xbf820f00, 0x25402822, 0x18288382, + 0x14151617, 0x0b111213, 0x094c1d19, 0x01010030, 0x09000176, 0x010f0006, 0x1606030e, 0xaf18012b, 0x86820781, 0x36341131, 0x01270133, 0x01010701, + 0x37010117, 0x83ec0401, 0xd8fa2160, 0x04290583, 0xf4fe8626, 0x0186f4fe, 0x2104840c, 0x0e820c01, 0x37420525, 0x84befb2d, 0x2d422c1d, 0x8a8efe37, + 0x0e01f2fe, 0x89f6fe8a, 0x22988226, 0x86e8fe02, 0x000a2697, 0x40290016, 0x26928526, 0x0d0e0f10, 0x8f0c090c, 0x06082598, 0x0a010a00, 0x0921988c, + 0x27929002, 0x58fda4fc, 0xfa02a802, 0x02239299, 0x95820288, 0x05274190, 0x4205c823, 0x228f8300, 0x8a254028, 0x0c01278f, 0x4c010100, 0xca430102, + 0x2abe8207, 0x2209000a, 0x2b170603, 0x41210209, 0x032d1221, 0xfda80220, 0x2da4fc58, 0x032d3737, 0x268e9386, 0x78fd7efd, 0x41042d37, 0x2208191f, + 0xff1e0004, 0x049204e1, 0x000200d9, 0x000f0005, 0x40470013, 0x02010444, 0x01074a01, 0x00010601, 0x53000103, 0x0826084b, 0x02020501, 0x06825705, + 0x5f02053b, 0x02050200, 0x0310104f, 0x10000003, 0x12131013, 0x0b0e0f11, 0x03050308, 0x2a488205, 0x16060902, 0x0101132b, 0x42020925, 0x34080662, + 0x35032111, 0x021e1521, 0xfe3a023a, 0xfeccfefa, 0x3e5803cc, 0x2d8efc2d, 0x8148043e, 0x2102bafc, 0x48fdb802, 0xfe780177, 0x2db4fd88, 0x012d3e3e, + 0x97eefe26, 0x29ff8297, 0x6aff0900, 0x82054c00, 0x9b82f204, 0x001fa308, 0x003f002f, 0x00660056, 0x00860076, 0x40a80096, 0x3c4453a5, 0x1c242c34, + 0x03020814, 0x6b737b83, 0x074b5b63, 0x8b930c09, 0x03121102, 0x0001134c, 0x07160a17, 0x07140515, 0x03000203, 0x04060867, 0x101a0203, 0x05180e19, + 0x0c02090c, 0x0b0d0f67, 0x011b0903, 0x12091112, 0x01110068, 0x00571101, 0x60011111, 0x01110100, 0x77878750, 0x57676777, 0x30404057, 0x10202030, + 0x87000110, 0x8f958796, 0x7786778d, 0x677d7f85, 0x6f756776, 0x5766576d, 0x405d5f65, 0x4f554056, 0x3046484d, 0x383e303f, 0xea182036, 0xe5420a80, + 0x421c2005, 0x173012e5, 0x15150622, 0x33331614, 0x35353632, 0x33232634, 0x32230fa6, 0x86111516, 0x82112036, 0xa6012036, 0x87668736, 0x8621202f, + 0x1e052776, 0x2d37372d, 0x0583b0fa, 0x17113c25, 0x83941117, 0x10c42404, 0x8e101818, 0x83d62009, 0x17112413, 0x836c1018, 0x7afb2121, 0x36892292, + 0x8328fd21, 0x6803211e, 0x04252a83, 0xfc2d37f2, 0x24608322, 0x372dde03, 0x88628296, 0x9594203a, 0x11172309, 0x1983fcfe, 0x11e80125, 0x9dacfe17, + 0xb6fe2130, 0x00211f89, 0x17461800, 0x40332d0e, 0x00010430, 0x03060507, 0x03000103, 0x109d8718, 0x08083a08, 0x0b080000, 0x090a0b08, 0x07000700, + 0x08111111, 0x132b1906, 0x21012135, 0x05012115, 0x3b152135, 0x6e019f01, 0x60fe2d01, 0x8b0192fe, 0xc8048301, 0x9a38fb9a, 0x9d03c804, 0x2f6a829d, + 0xa2000100, 0x0e04e2fe, 0x1600b605, 0x41404400, 0x49276282, 0x06050600, 0x82010185, 0x07863186, 0x01080501, 0x04050304, 0x03010967, 0x57030202, + 0x03240682, 0x0a0b5f02, 0x02210b82, 0x233f824f, 0x15160016, 0x30050c51, 0x11121111, 0x2b1f060c, 0x01211101, 0x21112501, 0x22018435, 0x82113311, + 0x21152a87, 0x01af0215, 0xfe4afe5f, 0x2305824a, 0xfe2a01d6, 0xae200382, 0x02310685, 0xfda7fe3e, 0x020102fd, 0xe09a5901, 0xfe64019a, 0x2006829c, + 0x20978400, 0x2c9782fe, 0x001600d2, 0x163c403f, 0x0a4a0001, 0x25158201, 0x04050085, 0xb87a8605, 0x1804200c, 0x210e8c82, 0xc3571415, 0x830b200a, + 0x86212092, 0x11212184, 0x08ec8c18, 0x01251126, 0xa1fe0e04, 0xfe228385, 0x9183aed6, 0xa1260384, 0xcf03b601, 0x8482a7fe, 0x019cfe23, 0x08068264, + 0x0259014b, 0x06000102, 0x5100e7ff, 0x2d05c904, 0x48003b00, 0x59005500, 0x73006600, 0x75407800, 0x0d060108, 0x06070a01, 0x150c690a, 0x1607030b, + 0x0503090f, 0x69050700, 0x0314040e, 0x02101200, 0x02001102, 0x02131769, 0x11010111, 0x23078359, 0x03610111, 0x3a080b82, 0x67675101, 0x3c3c5656, + 0x73670001, 0x6c6e7267, 0x5a5c6163, 0x59565956, 0x50525758, 0x483c494b, 0x4042473c, 0x3032383a, 0x25272b2c, 0x1a1c1d1f, 0x0d0e1214, 0x3b000709, + 0x43183b01, 0x40180589, 0x35210954, 0x5f401823, 0x3533210c, 0x090b4f18, 0x15161627, 0x34353315, 0x061c7d36, 0x23060628, 0x35011523, 0x86522634, + 0x33162506, 0x36323321, 0x2d06bf60, 0x15011506, 0x23013533, 0x15060622, 0x17841614, 0x1a830420, 0x33822620, 0x16161428, 0x46c60333, 0x02854677, + 0x0988d620, 0x937e7e21, 0x20fe2614, 0x34223a22, 0x2204824a, 0x827e5e02, 0x35492105, 0xfe240482, 0xa5fed6a5, 0x4a210d83, 0x220d8234, 0x82499302, + 0x210e8305, 0x4d935702, 0x1494d020, 0x88550121, 0x203d824e, 0x25428335, 0xd0d0fdfe, 0x6f87abfe, 0x5c847e20, 0x3b082483, 0xff020000, 0x041e00c4, + 0x00dc05ec, 0x001a0011, 0x174b404e, 0x0302020b, 0x05020a18, 0x194c0204, 0x49010209, 0x00000106, 0x03000203, 0x00020067, 0x04020504, 0x05010767, + 0x57050101, 0x05230682, 0x82005f01, 0x124f340c, 0x12000112, 0x161a121a, 0x0d131415, 0x0006080c, 0x18100111, 0x080805bb, 0x2306143c, 0x01011121, + 0x34113311, 0x11013336, 0x35211121, 0x04350101, 0x37372d88, 0xfd90fd2d, 0xce5402ac, 0x46012d37, 0x7efeb0fe, 0x7a0186fe, 0x2d37dc05, 0x372d66fc, + 0x5402a4fe, 0x05825602, 0x372d0c2f, 0xb203f6fb, 0xfede8efd, 0xde82fe82, 0x21b38200, 0xc74c1d01, 0x00052d06, 0x4030000f, 0x0101072d, 0x01040300, + 0x0421a282, 0x20a18200, 0x06b31805, 0x8260200a, 0x000223be, 0x00851150, 0x1e219582, 0x05077b2b, 0x2709c94c, 0xf8fe2502, 0x8d01ce41, 0x2105bd4c, + 0x5570ca01, 0x06bd4c05, 0x00053408, 0x04ca0134, 0x009103a5, 0x0015000d, 0x001f0019, 0x40590022, 0x021b1e56, 0x0107010c, 0x4c020400, 0x06090e0a, + 0x0c010502, 0x00570100, 0x0004000c, 0x8668040c, 0x01310812, 0x0b0f5f00, 0x05070d08, 0x01000703, 0x1a1a4f00, 0x0e0e1616, 0x1f1a2122, 0x1c1d1f1a, + 0x19161916, 0x150e1718, 0x1111150e, 0x11141112, 0x1d061013, 0x0de7752b, 0x23272122, 0x1805fa5b, 0x210b694b, 0xd9750966, 0xcd012105, 0x2d06ea75, + 0xb0f54290, 0xb6aa4aaa, 0x8e48b0fd, 0xed545403, 0x514b180b, 0x4b002015, 0xbc200653, 0x132fd384, 0x2a402d00, 0x01060107, 0x02054c01, 0x83060102, + 0x6c6819c5, 0x04602508, 0x06000203, 0x82053d41, 0x820720a1, 0x550120a1, 0x21200caa, 0x2005c171, 0x2493872e, 0x41f8feed, 0x2b848dce, 0x72fec701, + 0x03000000, 0xc2013400, 0x2806f77c, 0x0123001d, 0x0107b5d0, 0x5174820a, 0x24270502, 0x02050709, 0x850a0104, 0x0604257d, 0x080a0059, 0x042d7a82, + 0x0068000a, 0x61040606, 0x04060400, 0x07f75051, 0x0a242b8a, 0x570a0006, 0x0020a182, 0x06273182, 0x085f0006, 0x82030304, 0x07c35b0e, 0x0f2456a7, + 0x23405850, 0x102056a5, 0x56a72a82, 0x56a91220, 0x56aa1320, 0x56a91620, 0x56a81720, 0xcb50ffa4, 0x23103009, 0x11202122, 0x23132212, 0x13111411, + 0x421f060b, 0x252c0eba, 0x22230614, 0x33113526, 0x32331411, 0x73430682, 0x08bb4205, 0x4753ef2a, 0x57415147, 0x8e014258, 0x2e113142, 0x55564694, + 0xfe330147, 0x016b6bd2, 0x4239fe2e, 0x70080540, 0x01240002, 0x058d0467, 0x0003004a, 0x402c000e, 0x08090a29, 0x02050607, 0x00000049, 0x01000401, + 0x02040067, 0x00570402, 0x5f020404, 0x04020103, 0x16114f02, 0x05101111, 0x132b1b06, 0x01211521, 0x01070121, 0x21012701, 0x042e2135, 0x04acfb54, + 0x0145fe54, 0x3dfe72c6, 0x01723efe, 0x0444fec6, 0x9a4a0554, 0x65fed0fe, 0xfe8c017e, 0x9b017e74, 0x8357829a, 0x86b22073, 0x00092473, 0x84234026, + 0x01052172, 0x01237382, 0x82570001, 0x5f012221, 0x21098202, 0x0a824f01, 0x0300032d, 0x17060311, 0x2135132b, 0x82020915, 0x2067836c, 0x085475a2, + 0x9ab0042a, 0x0181fd9a, 0x7f02fefe, 0x00236183, 0x54060103, 0x2f33081b, 0x1e023800, 0x01161440, 0x01240309, 0x04050905, 0x18050102, 0x240c794e, + 0x04010630, 0x2fe68301, 0x07020080, 0x00590203, 0x03010807, 0x69030709, 0x200a4978, 0x12225400, 0x01072423, 0x57298302, 0x0520053a, 0x20057378, + 0x26298600, 0x0204065f, 0x43000100, 0x63b3072b, 0x58500f23, 0x2063a740, 0xb32b8210, 0xaa122063, 0xb6132063, 0xaa162063, 0xb4172063, 0x25264163, + 0x28095f43, 0x2434360e, 0x1c111121, 0x8d4e1823, 0x78242028, 0x3a54153e, 0x7870201c, 0x45541043, 0x7896201a, 0x00380f4a, 0x01e10002, 0x03a303c2, + 0x00210099, 0x40d1012d, 0x0405160d, 0x01030103, 0x390bdc56, 0x04020026, 0x00590203, 0x02050904, 0x03040103, 0x02060867, 0x00070001, 0x09840701, + 0x0e2f5118, 0x01042023, 0x20288402, 0x22288602, 0x83570100, 0x56268230, 0x55a90cd0, 0x58500f23, 0x2055a340, 0xa9278210, 0xa6122055, 0xac132055, + 0xa6162055, 0xaa172055, 0x42fca155, 0x2d210a74, 0x08a2562c, 0x25025118, 0x15211323, 0x06357023, 0x2d022322, 0x28192655, 0x640a016c, 0x64f6fe64, + 0x1a5f4264, 0x33480130, 0x33339ffe, 0x03006101, 0xc201e100, 0x5742c803, 0x39002505, 0x35403800, 0x300c5942, 0x06020105, 0x02010301, 0x01076903, + 0x01000001, 0x33068259, 0x04610001, 0x00010001, 0x24242451, 0x232a232a, 0x1e060821, 0x21223e5a, 0x915e0604, 0x07f04b09, 0x36323323, 0x21cc9b35, + 0x37629b01, 0x62442007, 0x51180825, 0x072019b7, 0x20063f62, 0x0832625c, 0xca20df86, 0x2c2fdf84, 0x0e023400, 0x01161040, 0x04050308, 0x5a040102, + 0x05200e19, 0x053cd382, 0x02008000, 0x59020306, 0x01070600, 0x03060803, 0x00080069, 0x04080104, 0x05010069, 0x2313f645, 0x02010623, 0x02202983, + 0x195a298b, 0x5a052008, 0x61b00d19, 0x58500f23, 0x5a61a640, 0x61b00519, 0x61a91220, 0xb005195a, 0xa9162061, 0x05195a61, 0x204161ae, 0x09784324, + 0x23210c25, 0x5a2a1121, 0x242a2919, 0x15232306, 0x32331123, 0x267e1516, 0x1cb04207, 0x525f9d2d, 0x55784139, 0x3d67465e, 0x4336323c, 0x6f341a83, + 0xc701a648, 0xbb5a4647, 0x0000342c, 0x19000400, 0x7804c201, 0x2d088743, 0x40360245, 0x0a011610, 0x02040503, 0xa9420701, 0x01053c0d, 0x03010c02, + 0x6903020a, 0x07000a00, 0x67070a01, 0x0601010d, 0x0b590100, 0x82080901, 0x06092108, 0xa5431083, 0x06cb4b08, 0x090b2924, 0x38920305, 0x38820020, + 0x2e823f82, 0x04060823, 0x0adc5f03, 0x67b12f20, 0x58500f23, 0x2067ac40, 0xb2308210, 0xaf122067, 0xb5132067, 0xaf162067, 0xb3172067, 0x2a324167, + 0x2d09c742, 0x3d414316, 0x3738393b, 0x11343536, 0x87451311, 0x5c0e2005, 0x874524eb, 0x2305210b, 0x6709b159, 0x01210baf, 0x19604665, 0x21099345, + 0xdb597801, 0x45fe2005, 0xe3202b9c, 0x6705005a, 0x003c09d6, 0x01190003, 0x039a04c2, 0x00210099, 0x02350029, 0x3310400a, 0x05162d30, 0x04010604, + 0x210ce048, 0x4a18002b, 0x07220a53, 0x93455704, 0x08092b05, 0x0a0b0702, 0x07000502, 0xb95f6705, 0x00252c10, 0x03020403, 0x07080959, 0x82060203, + 0x0402214e, 0x964b2382, 0x0a0b2308, 0x974b0305, 0x235fae0a, 0x4058500f, 0x10205fa8, 0x5fae2c82, 0x5fab1220, 0x5fb11320, 0x5fab1620, 0x5faf1720, + 0x42261a41, 0x123009d1, 0x31323435, 0x11122e2f, 0x23191111, 0x0c21232a, 0x2024cd42, 0x13046d01, 0x201bbd42, 0x10166d98, 0x211aa445, 0x2a6d1101, + 0x0024080d, 0x01190005, 0x038704c2, 0x00210099, 0x003f0031, 0x02500047, 0x16144044, 0x3d030b01, 0x050b0c01, 0x0c010204, 0x080d4f4e, 0x05020021, + 0x09590203, 0x0a050207, 0x050b0301, 0x0b006903, 0x0b010c00, 0x060d690c, 0x08000102, 0x84080100, 0x0fae4509, 0x07092a22, 0x32833782, 0x328e0220, + 0x59010022, 0x30823a83, 0x65040821, 0x30200b8c, 0x0f2369b2, 0xad405850, 0x82102069, 0x2069b331, 0x2069b012, 0x2069b613, 0x2069b016, 0x4169b417, + 0xe5422b38, 0x4e163209, 0x45494b4c, 0x38404243, 0x22122236, 0x2a232b13, 0x084d6d23, 0x511d3361, 0x976c0fe7, 0x1b04431f, 0x14528a20, 0x6c982008, + 0x134315ac, 0x5215201a, 0xc66c0c33, 0x00300815, 0xffc50002, 0x050804e7, 0x001f007b, 0x4040002f, 0x0201023d, 0x4c010001, 0x04000100, 0x80040100, + 0x00020105, 0x00020100, 0x04010669, 0x59040303, 0x04270682, 0x03006103, 0x19510304, 0x260dcf49, 0x0607241b, 0x6a002b18, 0x062b05d0, 0x16161415, + 0x15021e17, 0x18352315, 0x2108e45a, 0xe9183336, 0x4c080f47, 0x85ab5d03, 0x634a923a, 0x323b267d, 0xbd3a5141, 0x3f39432d, 0xb862354d, 0x2540567b, + 0x28274025, 0x41262641, 0xc97b0528, 0x59474763, 0x36452c4f, 0x7a4f3125, 0x3c414b55, 0x2e2b3d5a, 0x524e6f49, 0x87fb5790, 0x27264026, 0x42262642, + 0x21088227, 0xa3460000, 0x059f4906, 0x38002a2e, 0x1140de01, 0x23262932, 0x07040516, 0x2511854f, 0x02010300, 0xe6826903, 0x5901002f, 0x060b0809, + 0x070a0504, 0x05000402, 0x119f4604, 0x1f832020, 0x02050522, 0x9a463287, 0x070a2208, 0x0b9a4604, 0x88002621, 0x9d042022, 0x500f2355, 0x55a34058, + 0xa606854f, 0xa61220ab, 0x4f132055, 0x55a6052f, 0x55a61620, 0xa406854f, 0x43fca155, 0x1730098c, 0x37382222, 0x30313536, 0x2a222e2f, 0x1b122a22, + 0x20057746, 0x22cd4e1c, 0x15030128, 0x33033523, 0x506d3717, 0x1c38490d, 0x4299ab27, 0x75734899, 0x06c257ba, 0x291a6343, 0xe8fe4801, 0x1901aeaf, + 0x536ddfdf, 0x0020080c, 0x6b000100, 0x0404e7ff, 0x2d007b05, 0x3c403f00, 0x02021213, 0x03010701, 0x022a2b02, 0x4c030304, 0x49072049, 0x00230607, + 0x82004d3e, 0x6120082c, 0x05050106, 0x004e053f, 0x002d0000, 0x2421262c, 0x09072e25, 0x26042b1b, 0x36343526, 0x022e3736, 0x4306915b, 0x06250664, + 0x33211415, 0x06775b07, 0x32331630, 0x06173736, 0xc4c50123, 0x4c7b486a, 0x7e198f56, 0x01240d13, 0x52177515, 0x0b137e19, 0x9e5d1935, 0x5988525f, + 0x93500810, 0x6ec07767, 0x43685d5f, 0x19794145, 0x820f127e, 0xff7a37c7, 0x05f003e7, 0x00190062, 0x0b2d4030, 0x16010001, 0x00020215, 0xa4824c02, + 0x825f0121, 0x4d382dbf, 0x03020200, 0x03010461, 0x4e033f03, 0x19281582, 0x11271800, 0x19090517, 0x0027b886, 0x21372137, 0x5c000015, 0xa482061d, + 0x3608a582, 0x7466c0c0, 0xfdea0101, 0x43031781, 0xfefef6fe, 0x606f7d66, 0x53804280, 0x65198dcd, 0xec7c6eb0, 0x9fd61b01, 0xfe00ff97, 0x6f6ecbe1, + 0x634f4380, 0x00006468, 0x56f50002, 0x3122081f, 0x5b53b501, 0x07242914, 0x03020501, 0x80030502, 0x20078843, 0x050f5106, 0xba470682, 0x071d230f, + 0xad430205, 0x20249506, 0x0503550c, 0x0f2050a4, 0x50a02b82, 0x50aa1020, 0x50a31220, 0x50aa1320, 0x50a31620, 0x50a81720, 0xed9d4020, 0x2009bc43, + 0x073e470b, 0x47257e52, 0xad550f3e, 0x476a201c, 0xa343071f, 0x0c07471a, 0x00820020, 0xd6000222, 0x2d063f67, 0x000e0006, 0x01364039, 0x01030101, + 0x0583044c, 0x07068629, 0x03000302, 0x84570003, 0x03002408, 0x8201055f, 0x004f3b0f, 0x0c0d0e00, 0x08090a0b, 0x00060007, 0x08121106, 0x012b1806, + 0x03331313, 0x41670323, 0x1c013807, 0x94427573, 0xef029448, 0x018c4287, 0xfe91035c, 0xfe83017d, 0x67c70139, 0x35080743, 0xff4f0003, 0x05fe04f3, + 0x00220087, 0x003b0030, 0x3b1640e7, 0x0d101a2a, 0x07080a0b, 0x0e020309, 0x02030001, 0x00010f4c, 0x0ab04b49, 0x17405850, 0x02020105, 0x96826101, + 0x4d1f0122, 0x61209283, 0x1b26bb82, 0x4b1b4e00, 0x1e970cb0, 0x1e842020, 0x1e971020, 0x13203d85, 0x3d851e97, 0x1e971720, 0x95953d83, 0x59203882, + 0x402b0083, 0x00232313, 0x23373900, 0x822f2330, 0x142126e4, 0x16070612, 0x3970182b, 0x36012407, 0x69061737, 0x69600597, 0x07d24406, 0x15020e22, + 0x08f86218, 0x18032321, 0x08087a5a, 0x6c02376e, 0x7a43589f, 0x4a60015e, 0x68419c2a, 0x56c38fef, 0xc47c88d0, 0x478a876f, 0xa1542950, 0x2c53376e, + 0x6d3c411b, 0x3d506466, 0x7a455e62, 0x4094624f, 0x8b4e8705, 0x6b805057, 0x9aaefe39, 0xa8ea30c1, 0x5dbd58df, 0x6fa95c60, 0x4757b87d, 0x57426c65, + 0x3082548f, 0x4b2d3354, 0x7c403b54, 0xfd60544e, 0x56893f89, 0x483c6d47, 0x00000047, 0x37099f41, 0x002a001c, 0x40e20035, 0x14243512, 0x0305070a, + 0x00010802, 0x094c0203, 0x32bc9b41, 0x001d1d12, 0x1d313300, 0x00291d2a, 0x2c1b001c, 0x41170706, 0x0723099a, 0x41060627, 0x02212d94, 0x2b8e41b6, + 0x4168fd21, 0x30082988, 0xfef8ff02, 0x05b80445, 0x00360070, 0x40600046, 0x0901105d, 0x03424301, 0x26090803, 0x27070401, 0x04040501, 0x0b01004c, + 0x01080901, 0x02006909, 0x05747e0a, 0x03030032, 0x06006106, 0x004d1f06, 0x61000808, 0x1b000000, 0x2f055547, 0x1e050500, 0x37374e05, 0x46370000, + 0x3d3f4537, 0x352d5682, 0x25262424, 0x0c262425, 0x042b1d07, 0xc9671826, 0x36343608, 0x17163233, 0x17161411, 0x34351232, 0x22232602, 0x14150206, + 0x075b4712, 0x11002025, 0x82210010, 0x02142305, 0xb9182306, 0x87080a38, 0x26261137, 0x51820323, 0x1d070316, 0x7b885e73, 0x6e3da6ad, 0x2c2e234a, + 0xa4bf5026, 0x5350bfa4, 0x7636a1bf, 0xb5674927, 0xddfec3fe, 0x3b012501, 0x23013d01, 0xfe596727, 0x111e4e60, 0x3e343033, 0x22180f19, 0x6e5d6221, + 0xd55f493f, 0x22e9e1b9, 0x68fefd28, 0x0801016c, 0x4701fc9b, 0xb7feb0ac, 0xb9fef9f9, 0x911a19aa, 0x01df014a, 0x01ab01b3, 0xfe1efeee, 0xfffe874c, + 0x433603b3, 0x75607387, 0x2b322a3e, 0x060cb701, 0x0134f282, 0x5c006901, 0x3e024703, 0x26000b00, 0x00002340, 0x57000301, 0x0d48ff18, 0x03005f24, + 0x6c180300, 0x07240718, 0x33012b1c, 0x09d27318, 0x8e12022e, 0xa98ea7a7, 0xb13e02a9, 0x82afaf82, 0x01273e82, 0x03070168, 0x18890148, 0x261883b2, + 0x012b1807, 0x82211521, 0xfee02427, 0x82890120, 0x01022833, 0x03910066, 0x18080248, 0x2124f761, 0x3f841a07, 0x43831520, 0xe2016624, 0x03831efe, + 0x84080224, 0xce82846f, 0x03005708, 0xe7ff1afc, 0x79051804, 0x52004500, 0x57005f00, 0x3a3b5440, 0x06042425, 0x00011905, 0x0f525f06, 0x000b0403, + 0x090e4c03, 0x0a0c0602, 0x0b000302, 0x08670006, 0x04050501, 0x04010761, 0x0d4d1f04, 0x010b0b01, 0x01010361, 0x4e012001, 0x5b5d0000, 0x4e505355, + 0x4d824648, 0x2625442e, 0x232d2525, 0x0f112316, 0x012b1f07, 0x0cce6818, 0x68182120, 0x322012da, 0x2606ac77, 0x16141506, 0x49213316, 0x33200593, + 0x0919158d, 0x332308bf, 0x65373632, 0x16200711, 0x042c0c83, 0xce3cab18, 0x63cc959d, 0xf8fe4447, 0x0c086918, 0x69186620, 0xa6250b24, 0xaf5f3135, + 0x23128b72, 0x5ee3e4fc, 0x07296918, 0x8ae80321, 0x184b200b, 0x22072b69, 0x18339c67, 0x21103569, 0x69185442, 0x29250751, 0x975a4675, 0x200f8959, + 0x4e69188f, 0x20098709, 0x08008200, 0xa0fd0220, 0xac03f2fe, 0x03008606, 0x47002e00, 0x01234440, 0x4c010304, 0x00020209, 0x00030700, 0x17826707, + 0x03060425, 0x18006904, 0x3809b8a7, 0x01020805, 0x054f0106, 0x2d000004, 0x18191b2b, 0x0d0e0f16, 0x052e040c, 0x082b822e, 0x0a110326, 0x012b1707, + 0x01113311, 0x17161632, 0x16161413, 0x06221533, 0x14111506, 0x21230606, 0x36322135, 0x34113536, 0x2305d54a, 0x26263411, 0x5c081382, 0x02aea0fd, + 0x53a183b9, 0x812e0201, 0x2e827b7c, 0xfd82a454, 0x4a0d02f3, 0x59282956, 0x2a5a4b4e, 0xfd4a5629, 0x07f2fef3, 0x076cf894, 0x7b893694, 0x584b8dfe, + 0x582e9a2d, 0x7c95fe4b, 0x1c93398c, 0x85013c42, 0x0d3d715d, 0x5972400d, 0x423b8801, 0x0000931a, 0xffa0fd02, 0x06810217, 0x26938261, 0x4035000b, + 0x82050732, 0x030423d1, 0xd1820400, 0x03010130, 0x03030057, 0x06025f01, 0x01030102, 0xc982044f, 0x040b0423, 0x0547610b, 0x0820c584, 0x0520c582, + 0x1120c583, 0x0382b382, 0x042ca382, 0x027bfc33, 0xe930fdd0, 0xb6f84a07, 0x9d360383, 0x009f0e06, 0xffff0000, 0xa8fd41fe, 0x0807bf01, 0x3c062300, + 0x128240fc, 0x3c060324, 0x078210ff, 0xf8251b82, 0x02a8fda1, 0x211b85af, 0x138250fb, 0xf6212382, 0x220782a0, 0x823c0602, 0xf5042805, 0x014effc1, + 0x829005ec, 0x00073275, 0x0010000d, 0x100a4067, 0x0a0b0e0f, 0x01000105, 0x0511484c, 0x98181620, 0x1b2e153a, 0x5015b04b, 0x050f4058, 0x01010203, + 0x24835f00, 0x011a0025, 0x96401b4e, 0x5959252f, 0x11130940, 0x10250082, 0x2b1c0706, 0x6e981801, 0x15012c08, 0x11132301, 0xa7c1f501, 0x829803a7, + 0xa7702503, 0x84fb7c04, 0xd7260882, 0xbef99005, 0x03834206, 0xb53efd32, 0x7b0535fd, 0x5b024efb, 0x0ffa0300, 0x50024eff, 0x092bb384, 0x5c000c00, + 0x0b0c0a40, 0x8a06070a, 0x021321b1, 0x0122bd82, 0x06825700, 0x5f010023, 0x219e8203, 0xae864f01, 0x0d820d20, 0x1983ad82, 0x2a93ac84, 0xb6595929, + 0x10111113, 0x861a0704, 0x21a286a6, 0x95820ffa, 0x9e8e1e20, 0x00239a8b, 0x8291fd02, 0x82b4209b, 0x00052b9b, 0x40520008, 0x0607080a, 0x998a0203, + 0x00001022, 0x2008b062, 0x87a48200, 0x830b2096, 0x005f2216, 0x05414100, 0x59272590, 0x1013b459, 0x82180702, 0x218b868f, 0x878a91fd, 0x2f08838c, + 0xfe74fc03, 0x060804cb, 0x002900a3, 0x00380031, 0x353d4040, 0x262a3134, 0x08171c23, 0x01020407, 0x03020e00, 0x01020f16, 0x004c0202, 0x85030203, + 0x00209182, 0x10051119, 0x1b24252b, 0x11121319, 0x16070410, 0x3971822b, 0x24010137, 0x16161127, 0x06061415, 0x35231507, 0x27262606, 0x33161635, + 0x90441137, 0x11372205, 0x211d8233, 0x43492517, 0x17770805, 0x11272600, 0x04353636, 0x3507fd08, 0x47fd1f02, 0xbbb3d5fe, 0x81c86ffd, 0x8a875a8b, + 0x5dbc9262, 0x56b9bb22, 0x7a8b76a8, 0x97fd69fb, 0x4c1f6050, 0x827b0145, 0x02866a6e, 0x22feb5ce, 0x014701f0, 0xfe16bba9, 0xa6e03d3c, 0x1084cd7b, + 0x1502b7be, 0x57ca3435, 0x6502013e, 0x5789ba3e, 0x010c6b9f, 0x0ce5fe1c, 0x0e064456, 0x452e4e6a, 0x55fe1d3b, 0xd4fd2f8d, 0x82808b15, 0xfc2008c9, + 0x0391002c, 0x004e04d4, 0x40300013, 0x0401062d, 0x57040103, 0x03020507, 0x00020208, 0x67000301, 0x04271282, 0x01095f01, 0x72010401, 0x072a0c9f, + 0x21012b1f, 0x21112311, 0xcb822135, 0x15200384, 0x013c0f82, 0xaec6fc9b, 0x870179fe, 0xae3a03ae, 0x75fe8b01, 0xfe1f02ae, 0x9e8e0172, 0x6ffe9101, + 0x9e280383, 0x000072fe, 0xe0f70100, 0x70207782, 0x1b3a7782, 0x3a403d00, 0x0602080a, 0x57060105, 0x0307090b, 0x02040c05, 0x05010003, 0x15836700, + 0x5f010629, 0x0102030d, 0x714f0106, 0x11690aa9, 0x10112205, 0x8d84880e, 0x05966c88, 0x01231123, 0x8a8c8237, 0x8c928d8f, 0x3d9a8996, 0xc8fb0200, + 0xa403feff, 0x0600e204, 0x60001200, 0x00021840, 0x06000102, 0x05010201, 0x01820203, 0x01014c28, 0x01044a00, 0xcf434903, 0x47152005, 0x032610b6, + 0x1b4e031b, 0xd4471a40, 0x40592219, 0x2ec28409, 0x1c070617, 0x0135132b, 0x01350115, 0x18113301, 0x080850af, 0x5e034632, 0xb902a2fc, 0x01aeb4fa, + 0xae11feef, 0xeb0115fe, 0xfdc71b04, 0xe5fdb5ec, 0x02ab01c9, 0x9e0bfe40, 0xf2010efe, 0x0200009e, 0x5c0118fc, 0x8003e803, 0x252fc347, 0xd00718fc, + 0x038330f8, 0xa2800325, 0x8200a2e0, 0xf7032200, 0x87161968, 0x4b51250c, 0x58501ab0, 0x255ac782, 0x00672705, 0x04050004, 0x78436305, 0x011c2107, + 0x2020e482, 0x01243782, 0x67010002, 0x18062951, 0x181065b3, 0x82091769, 0x6e0120ea, 0x0584052c, 0x0c68f725, 0x8780f380, 0x43042303, 0x8683e1a1, + 0xfd025008, 0x0231ffbb, 0x00870571, 0x000a0006, 0x080ab508, 0x32020105, 0x2701012b, 0x09370101, 0x02011702, 0x42b6fb47, 0x3efcc203, 0xfb4a0442, + 0x424b049d, 0xf202b5fb, 0x019719fe, 0x98a601a7, 0x2afc18fe, 0xfe90e101, 0xfb020017, 0x035200fa, 0x829204a4, 0x820d2047, 0x080b2247, 0x22478404, + 0x82150137, 0x8513204a, 0xfafb2a06, 0xfc77034b, 0x09034b89, 0x2c0887df, 0xfe910104, 0x39feb33a, 0x018f0191, 0x240a888f, 0xf7030000, 0x204f82ae, + 0x254f8640, 0xb70a0014, 0x53830f12, 0x9b820320, 0x5a86538c, 0x90aef721, 0x8c639e5a, 0x0024086e, 0xff15f204, 0x05bc03e7, 0x00030062, 0x00160012, + 0x40420026, 0x0201053f, 0x03011200, 0x02101102, 0x4c030706, 0x04260e82, 0x02010301, 0x0b456703, 0x4d270808, 0x07070108, 0x06006106, 0x4e062006, + 0x26171717, 0x11272517, 0x11161117, 0x1d070910, 0x0333012b, 0x01170123, 0x18070606, 0x220818ef, 0x19352105, 0x08104c37, 0xd432f633, 0xf6fda815, + 0x31fafe8a, 0x3e022b36, 0x4525c2fd, 0x8a060128, 0xa711d6fd, 0xd80b28f4, 0x26410af3, 0x27284126, 0x40252540, 0xfc620527, 0x750e036d, 0x48ef18fe, + 0xa653230c, 0xef553dfe, 0xfc02380e, 0x04feff5e, 0x00ee045b, 0x0015000e, 0x151f4022, 0x11121314, 0x4f0e0f10, 0x063706ad, 0x00030405, 0x00490014, + 0x11760000, 0x2b170701, 0x03330301, 0x68051725, 0x252505fa, 0x15010537, 0x08028301, 0xc119ae27, 0x38e30116, 0x460116fe, 0xfee1fe9e, 0x2d01a2fc, + 0xfc3f0cfe, 0xfd5e0392, 0xfcb90247, 0x02ea02a2, 0xb0fefd04, 0xb53e19b7, 0x02cf2a0c, 0x57fec715, 0x02ca56fe, 0x275f821b, 0x12f80300, 0x4003feff, + 0x1c258b86, 0x26402900, 0x0a5c441c, 0x1b20948e, 0xc04394a1, 0x62fd2105, 0x07219b9e, 0x05d643d0, 0x0221a39f, 0x08ea4302, 0xfd020027, 0x024eff4c, + 0x061f476f, 0x09405127, 0x00050708, 0x096a4804, 0x4710f846, 0x1e4706b5, 0x11300821, 0x18070211, 0x3301012b, 0x37012311, 0x4cfd1101, 0xa7a77c04, + 0x03a584fb, 0x02ce02d7, 0x02bef9c2, 0xa5fd59cb, 0x0000b204, 0x00f90300, 0x41014eff, 0x09288384, 0x64000c00, 0x0b0c0940, 0x1420858c, 0x210c3e48, + 0x0e830304, 0x2007a847, 0x480e830e, 0x2c940b40, 0x4059592f, 0x0606060c, 0x13090609, 0x07051111, 0x28988619, 0x11331101, 0xf9110101, 0x249c8500, + 0xf8a79a07, 0x27a08964, 0x420635fd, 0x2403bef9, 0x0426a786, 0x4effb4f4, 0xa786df00, 0x10000d28, 0x09407700, 0xa98c0f10, 0x9a491820, 0x0507240e, + 0x48040306, 0x11200a56, 0x9e491085, 0x8233980c, 0x0a142ab4, 0x0a06060a, 0x0c0d0a0d, 0x20bc860b, 0x20bc8c08, 0x21c08521, 0xc086b4f4, 0x02a7ec26, + 0x7af4a7f1, 0xc78cc38f, 0xdaf80332, 0x780234ff, 0x0300a805, 0x11000a00, 0x21402400, 0x200d2943, 0x2ab0820e, 0x0100004c, 0x01008500, 0x48117601, + 0x112206e7, 0x24430123, 0x068f4206, 0xae513008, 0x0389fbae, 0x020ffd96, 0x066afcf1, 0xfc9a0304, 0x05f50266, 0x038cf9a8, 0xc7380299, 0x34fe34fe, + 0x023c02c9, 0xc9fdc725, 0xc9c2fdb5, 0x8200ce01, 0xfc032600, 0x03cbfe36, 0x080b49ca, 0x39403c36, 0x2a313435, 0x1c232629, 0x12131416, 0x0f000203, + 0x010a0302, 0x271d0b49, 0x1b112b19, 0x2b1a0704, 0x25110249, 0x07013501, 0x07490101, 0xca032120, 0x280c0049, 0x0c03a2fc, 0x02bdfd24, 0x190949b9, + 0x491b0421, 0x02291001, 0xe301b41b, 0xfe9ffedd, 0x250a4956, 0xf8030023, 0x20fb824e, 0x32fb8240, 0x0036002e, 0x4042003d, 0x36393a3f, 0x21282b2f, + 0x4a18191b, 0x1123060a, 0x9e0f0302, 0x292a23fd, 0x094a1e20, 0x2706411e, 0x0e4a4020, 0x220d4113, 0x411a174a, 0xb7452e15, 0x49382005, 0x03250e0b, + 0x06010201, 0x080b4904, 0x0b490520, 0x07c14248, 0x210a0b49, 0xdb455efc, 0x3d052107, 0x21090e49, 0xd345cd02, 0x99022109, 0x45090f49, 0x270807db, + 0x000600e2, 0x0019000d, 0x091f4067, 0x04000207, 0x030d0001, 0x0c010202, 0x0404060a, 0x4c030203, 0x00020108, 0x02050b4a, 0x2442c449, 0x1c07061e, + 0x0d7a432b, 0x210bcb49, 0xbf8712f8, 0x4907ff45, 0xc78c0bd6, 0x4909f745, 0x00270be2, 0xff8ffd02, 0x49450231, 0x47080813, 0x00040709, 0x012b3202, + 0x07010117, 0x01013501, 0x03020137, 0x033efc42, 0xb6fb42c2, 0xb5fb2104, 0x054b0442, 0x5afe9887, 0x019759fe, 0x92fbade7, 0xfe90e901, 0x0000001f, + 0xff5efc02, 0x05a403d4, 0x0005000d, 0xb5080009, 0x01204782, 0x09224782, 0x43821502, 0x1d820920, 0x03a2032e, 0xfc5cfca4, 0xfd02a55e, 0x01fdff02, + 0x402e9b82, 0xfdb5c1fd, 0x594502bb, 0xd5012bfe, 0x4383d401, 0x52005c24, 0x57490604, 0x490c2008, 0x8c84079f, 0x93852520, 0x035cfc2d, 0xf7fc4b77, + 0xfc4b0903, 0x89e80389, 0xcc022c0b, 0xfe91c601, 0x9171fe71, 0x89b3c701, 0x279a820a, 0x10f80300, 0xa2035200, 0x210a5f49, 0x5b830f13, 0xe7820320, + 0x5b865485, 0xf8210686, 0xa2629510, 0x08798c6e, 0x6bfc012f, 0x5b030700, 0x3c00dd04, 0xb04b9a00, 0x40585027, 0x0226271b, 0x01200300, 0x041b0004, + 0x04010303, 0x21224c03, 0x1f4a0302, 0x4901021e, 0x201d851b, 0x201d9505, 0x08408659, 0x02050626, 0x00010203, 0x69000304, 0x01010400, 0x04005904, + 0x00610104, 0x51010401, 0x0020401b, 0x03000503, 0x05010659, 0x05202283, 0x59342291, 0x00001040, 0x3b003c00, 0x2d2f3436, 0x07262525, 0x002b1907, + 0x08232719, 0x020e0732, 0x26262223, 0x23262627, 0x06070622, 0x17160706, 0x8205897e, 0x3615270a, 0x023e3736, 0x2c823233, 0x33161623, 0x080c8432, + 0x8f480236, 0x229d166e, 0x3a263466, 0x5f40272b, 0x405f3f3f, 0x263a2b27, 0x27263725, 0x311f2e42, 0xfd8a0601, 0x8a2a02d6, 0x3a32fafe, 0x1e2d1c26, + 0x3d583926, 0x283f5f3f, 0x30862282, 0x4b2b032e, 0x454c3874, 0x2629265c, 0x31222231, 0x203f0682, 0x0d2b2221, 0xe0fe361c, 0x026b0275, 0xe0fe756b, + 0x27183536, 0x1e191d09, 0x33251923, 0x84282c28, 0x00003929, 0x12f8ffff, 0x40033c00, 0x2300aa04, 0x68f7cd04, 0x23000000, 0x38ffcc04, 0x03240782, + 0xa8fdad06, 0x003b0782, 0xe8f60100, 0x16040700, 0x7400dd04, 0xb04b0b01, 0x40585019, 0x0241741a, 0x823c0801, 0x353631d5, 0x03070002, 0x023d3e4c, + 0x3a3b4a08, 0x1b490002, 0x87056041, 0x01032121, 0x3e882191, 0x02231c90, 0x85595949, 0x0c253561, 0x0508020a, 0x07010203, 0x0d690108, 0x0703090b, + 0x59070000, 0x072a0884, 0x04066100, 0x07000302, 0x6c865100, 0x01052a27, 0x01080301, 0x24338359, 0x08070300, 0x21319a03, 0x2c952b40, 0x00010425, + 0x85000702, 0x02073b38, 0x02010661, 0x59510207, 0x72184059, 0x64696b70, 0x565b5d62, 0x484d4f54, 0x00842546, 0x070e2325, 0x41012b1d, 0x0ca20ce6, + 0x18152721, 0x2009e1ec, 0x0b004207, 0x960c0d42, 0x1604250c, 0x468f6e16, 0x41061a42, 0x3f2606f7, 0x2c283f5e, 0x0d822739, 0x423f2821, 0x1b860836, + 0x3a593d29, 0x1b2c1d24, 0x42333826, 0x2f27093f, 0x283f2c20, 0x42253727, 0x26250d67, 0x40272a3a, 0x07754260, 0x333b1b8d, 0xb0022366, 0x224b7438, + 0x26292631, 0x34282b28, 0x252f2125, 0x25222428, 0x891f2c23, 0x23192913, 0x091b181d, 0x37351723, 0x26097042, 0x2a0d1f33, 0x42202222, 0x26240992, + 0x23312628, 0x13893384, 0x00465b3f, 0xfb010000, 0x03cffefa, 0x00550687, 0xb306000a, 0x32010103, 0x1701372b, 0x01372701, 0x3e068235, 0x98e60209, + 0x549a7efc, 0x03033bfc, 0x5b47fd5b, 0xf849fa05, 0x02ac45c3, 0xdd01b459, 0x8357fe8f, 0x12f8213f, 0x40203f82, 0x11203f82, 0x11213f82, 0x273f8208, + 0x15010703, 0x02092701, 0x092e4385, 0x045f6102, 0x6305fd00, 0x5afcb902, 0x4b8828fd, 0x026a0332, 0xc50c06e6, 0xfeb587fd, 0xab018b23, 0x22fa3b02, + 0xfd235889, 0x82fa05e9, 0x40fc2d9b, 0xbc03b901, 0x23002203, 0x2f403200, 0x8205c955, 0x01052a73, 0x00690500, 0x01040301, 0x08554f59, 0x04010133, + 0x01040061, 0x24255104, 0x22252421, 0x2b1c0706, 0x05f57b01, 0xea431720, 0x270c8205, 0x06211521, 0x06060706, 0x210a1f44, 0x151940fc, 0x283b09d3, + 0x462a2638, 0xfc850335, 0x2b45339e, 0x34384a2f, 0x2d2a3f56, 0x5e3a243e, 0x191a022b, 0x0819f759, 0xffa0fb23, 0x0597044a, 0x0050007b, 0x4060005f, + 0x0a01185d, 0x06015107, 0x02393a0a, 0x0b5f0805, 0x04050b02, 0x32a5824c, 0x0a02060a, 0x00070069, 0x06070806, 0x00080069, 0x82080b05, 0x000b24c3, + 0x180b0001, 0x2e0bb581, 0x010c6109, 0x041f0909, 0x5c00004e, 0x8253555a, 0x254f2c54, 0x26292526, 0x26262425, 0x181f070d, 0x2026b581, 0x20e48204, + 0x20e98e07, 0x0cf84427, 0x36373622, 0x24250282, 0x26261333, 0x09ef7c23, 0x81183720, 0x71281eda, 0x324cfefe, 0x0a1a2a48, 0x27093441, 0x812c5b3c, + 0x537d5426, 0x35092c41, 0x522d1f0b, 0x39016136, 0x381d0990, 0x29605422, 0x4d3c5144, 0x82181026, 0x35262202, 0x68933a58, 0x6a411441, 0x562f0806, + 0x724c3f51, 0x2530214b, 0x4f58282a, 0xa6704c14, 0xfd477440, 0x530d0f56, 0xa49c86a6, 0x002d4637, 0xfc010000, 0x030700a5, 0x00dd0495, 0x448d003c, + 0x393c06f9, 0x01032122, 0x03010104, 0x02070801, 0x4c030300, 0x4a04013c, 0x00020203, 0x1a401b49, 0x02201c8c, 0x99461c8b, 0x04002e07, 0x04030100, + 0x01056901, 0x03000003, 0x2b068259, 0x02610003, 0x00030001, 0x1c401b51, 0x02231d8b, 0x83020300, 0xc8691826, 0x40593607, 0x26252509, 0x062e2525, + 0x092b1c07, 0x36012702, 0x06353736, 0x0d8e4606, 0x2006a744, 0x087d4637, 0x82096f44, 0x27262b2e, 0x026b0101, 0x8ad6fd2a, 0x6d460601, 0x46462017, + 0xfe2a1cad, 0xfddd04fa, 0x7595fd95, 0x73462001, 0x16a84613, 0x20012a08, 0xfc010000, 0x03c2017a, 0x002b0386, 0x40360038, 0x01013833, 0x021b1c04, + 0x4c020500, 0x03040106, 0x04050101, 0x01076901, 0xe9d41805, 0x02612708, 0x00050001, 0xf3842551, 0x08222524, 0x5d191e07, 0x92450e67, 0x0d7c420c, + 0x210c8942, 0x4c428603, 0x3f262d09, 0x503d2830, 0x3d523030, 0x2642302b, 0x260e5a42, 0x292c3c24, 0x4234543d, 0x02210968, 0x062a42ca, 0x252c2929, + 0x2d20202e, 0x422a2b26, 0x28240a34, 0x212f262a, 0x20063e42, 0x2bdf8200, 0x07003af7, 0xdd046804, 0x09017400, 0x3405e546, 0x3d3e711a, 0x01080103, + 0x08010701, 0x07000207, 0x01744c03, 0x062b4208, 0x87064d42, 0x8f268221, 0x88402021, 0x201c843e, 0x473e8b02, 0x06217847, 0x20c78201, 0x06474702, + 0x04610038, 0x00070001, 0x40595951, 0x656a6c16, 0x575c5e63, 0x254e5055, 0x00842526, 0x070e2e23, 0x1fa7421f, 0x23262623, 0x29c14222, 0x8c0cd641, + 0x05db420c, 0x423e0221, 0x332906db, 0x2c1b2638, 0x593a241d, 0x0e51473d, 0x25055749, 0x282c3927, 0x12475e3f, 0x8f46270e, 0x239d166e, 0x21473366, + 0x250d870d, 0x2a274060, 0x1b8d263a, 0x27372527, 0x202c3f28, 0x0a13432f, 0x1735372d, 0x181b0923, 0x2519231d, 0x492b2834, 0x1f290587, 0x2225232c, + 0x2f252824, 0x25138921, 0x4c38744b, 0x29475b46, 0x24098409, 0x28263123, 0x08138926, 0x22222037, 0x331f0d2a, 0x00002001, 0x013cfc02, 0x0584035c, + 0x000800f0, 0x403f000c, 0x0001053c, 0x064c0103, 0x03000301, 0x00020085, 0x01020001, 0x00000080, 0x01000501, 0xd9331967, 0x0000250f, 0x090a0b0c, + 0x082f3982, 0x07111112, 0x012b1907, 0x21152101, 0x82230101, 0x35350807, 0x0162fe21, 0xfba90379, 0xfe9efee8, 0x7a01c9fb, 0xe8fbce05, 0xf0051804, + 0x02a290fd, 0x0232fe6e, 0xa26cfb72, 0xfbffff00, 0x04d5ffae, 0x00890553, 0xfbe80423, 0x2369828e, 0xc2e80402, 0x012b1782, 0x033d0369, 0x011f0547, + 0x82820607, 0x00e12ba6, 0x0100b109, 0xb0e102b8, 0x24822b35, 0x01ffff29, 0x03e80368, 0x826a0448, 0x9483201f, 0x0366221f, 0x201f8272, 0x201f82e9, + 0x201f8784, 0x083f8802, 0xfb02002f, 0x0434ff3c, 0x00a805c4, 0x0017000b, 0x0a404043, 0x01000101, 0x02010985, 0x0c860203, 0x0600020b, 0x00040501, + 0x01076705, 0x04030304, 0x34068257, 0x085f0304, 0x03040301, 0x0c0c0c4f, 0x16170c17, 0x11131415, 0x24f78211, 0x10111111, 0x05ab580d, 0xa9583320, + 0x21352405, 0x83211525, 0x080e8201, 0xfb113322, 0xae4c033c, 0x03b4fcae, 0x09b4fc4c, 0x03b6fc88, 0xaeb6fc4a, 0x028503ae, 0x028cf923, 0xa2e2a22b, + 0xfd250282, 0xfd7406d5, 0x23d782dd, 0xecff0100, 0x13339786, 0x3a403d00, 0x08070800, 0x02030085, 0x090a8603, 0x82060702, 0x000722a2, 0xdaa31867, + 0x233a8212, 0x11130013, 0x0b200087, 0x83888f83, 0x09cf4518, 0xfdc40428, 0xfd1502eb, 0x0685aeeb, 0x82150221, 0x847e8487, 0x23022188, 0x02328385, + 0x34ff3cfb, 0xa8057801, 0x0f000b00, 0x35403800, 0x78820106, 0x07088527, 0x02030202, 0x306a8286, 0x05000405, 0x03040067, 0x00570403, 0x5f030404, + 0x06164100, 0x0f0c0f22, 0x26061041, 0x2b1d0709, 0x41112101, 0x01200810, 0xfb250a82, 0xae4a033c, 0x050041ae, 0x418e0521, 0xfc2a0a01, 0xf9740651, + 0x0200008c, 0xfb8688fe, 0x77880320, 0x85010727, 0x04000105, 0xe7301900, 0x24778227, 0x33112307, 0x26fc8801, 0xaeca1133, 0x858e05ae, 0xaeae2676, + 0xfd7406cc, 0x0a7141dd, 0x20090742, 0x23738207, 0x072a402d, 0x0621eb84, 0x26ea8301, 0x03000104, 0x82570003, 0x08836606, 0x23066141, 0x1e070810, + 0x2520e088, 0x2005db59, 0x07e94133, 0x413e0621, 0x022e05e3, 0xf9e302c5, 0xa6eb028c, 0x0615fda6, 0xdb410074, 0x000b2e0a, 0x00264029, 0x85050005, + 0x02010200, 0x18608286, 0x5d083096, 0x678406a0, 0x85051b5e, 0x3521265d, 0x02331121, 0x08bd41af, 0xc502ae22, 0x5c825682, 0x00e30222, 0xc7840082, + 0x0578012c, 0x000700a8, 0x402e000b, 0xc785042b, 0xb3410520, 0x82c78306, 0x5f032d26, 0x03000300, 0x0808084f, 0x120b080b, 0x10236482, 0x881b0707, + 0x0ba541c8, 0x828e0521, 0x83bf8561, 0x0f9f41bd, 0x19000b21, 0x27250730, 0x072b1c07, 0x01331123, 0x3325c485, 0x02aeaeca, 0x051d4144, 0x7406cc24, + 0x19411dfd, 0x061b4106, 0x82af0221, 0x000b35bf, 0x00314034, 0x85000500, 0x01020100, 0x05010686, 0x05030400, 0x1105d418, 0x0b22cd82, 0xc2820b00, + 0x84111121, 0x096c42c3, 0x01023523, 0x06e142ae, 0x820a6643, 0x01022163, 0x8308f343, 0x05042263, 0x055b4304, 0x00206383, 0x49186782, 0x638f10a0, + 0x430a5542, 0x4243084a, 0x05c14307, 0xecff0124, 0xc78434ff, 0x2b000724, 0xf8182840, 0x04260947, 0x02020301, 0x06825703, 0x0f190320, 0x072310b3, + 0x86012b19, 0x42ba86be, 0x00210739, 0x25b38801, 0x40240007, 0x96450021, 0x02012205, 0x18ce8286, 0x2507eb41, 0x01000100, 0xa35f114f, 0x06694107, + 0x42062a42, 0x06210526, 0x20c98274, 0x2a9b8200, 0xc40494fe, 0x0700a805, 0x19402700, 0x84224f0d, 0x324f8297, 0x02112135, 0xfb1602ae, 0x05140228, + 0xa38ff9a8, 0x837106a3, 0xff02284f, 0x045f01ec, 0x5c8503c4, 0x0120089f, 0x0123ef82, 0x84006700, 0x030021ea, 0x9b89e987, 0x21284982, 0xc4042135, + 0xd80428fb, 0x02250383, 0xdafda2e3, 0x844c82a2, 0xbc03214b, 0x03254bb1, 0x0330fcbc, 0x890383d0, 0xf400214b, 0x4b9097b7, 0x3cfb0335, 0xc4040700, + 0x1500dd04, 0x21001b00, 0x3b403e00, 0x8202010c, 0x1b4c3001, 0x4a030215, 0x02032021, 0x04490004, 0x82050301, 0x02032213, 0x05c46c67, 0x06825720, + 0x5f000133, 0x01000107, 0x12114f00, 0x23111611, 0x07081711, 0x6ff8181e, 0x21352d08, 0x27273737, 0x26213521, 0x25272726, 0x08053547, 0x21152132, + 0x6ffe2701, 0xd6fd2a02, 0x3419758a, 0x046efc27, 0x6767010b, 0x03f5fb01, 0x19342792, 0x01ac0275, 0xfcfe0235, 0x019dfea6, 0xfd5a0363, 0x8acbfe02, + 0x08edfa18, 0xa2172f3b, 0x01707001, 0x1e2f17a2, 0xa8fe757f, 0xfd8501a2, 0xa8fea299, 0xff010075, 0x27bf86ec, 0x4042001d, 0x0203123f, 0x4c2f9382, + 0x06021b1c, 0x0208094a, 0x07084902, 0x82050602, 0x00062212, 0xe5cf1867, 0x01032b0c, 0x4f020102, 0x1d000000, 0xbc821d00, 0xc4821620, 0x1d070928, + 0x2115012b, 0xa8840717, 0xfc183720, 0x37361046, 0xfec40401, 0x016565de, 0xfe4dfe22, 0x1b758acc, 0xb0fd2633, 0xc283c902, 0x0237fd2f, 0x1b332650, + 0x34018a75, 0x71a28503, 0x239a8371, 0x162e207f, 0x1622b485, 0xb483202e, 0xfb020027, 0x0307003c, 0x066b41c3, 0x34403727, 0x010c181b, 0x2f888204, + 0x0215174c, 0x191a4a03, 0x00040203, 0x00030049, 0x08ed1319, 0x0057012b, 0x5f000101, 0x00010000, 0x28a5824f, 0x1a070417, 0x0101032b, 0x219c9127, + 0x16823721, 0x41890121, 0xfb23085c, 0x83130566, 0xedfa2a99, 0x34279a04, 0x22027519, 0x211b848a, 0x5341ca01, 0x05994c15, 0x0300f624, 0x4f415ffc, + 0x00053b06, 0x0011000b, 0x05324035, 0x01020202, 0x010b4c01, 0x114a0002, 0x04030410, 0x385f4903, 0x71201909, 0x1112210e, 0x0120a384, 0x13208d84, + 0x210af741, 0x7f875ffc, 0x3501e134, 0x1ffb8504, 0x63019dfe, 0x7bfbe104, 0x048acbfe, 0x7e867568, 0x416b0221, 0x02220bdb, 0x8b8a0f01, 0x28402b29, + 0x4a000105, 0x9c020a0b, 0x0411237f, 0xa7491a07, 0x15212c07, 0x01270121, 0x01350199, 0x83aefdf6, 0x52022370, 0x70830afe, 0x668bdd20, 0x41054342, + 0x32220697, 0xff422f40, 0x73fe1806, 0x216c8225, 0x8f410209, 0x99012512, 0xd6fd2a02, 0x2c052442, 0x018502f4, 0xfd016767, 0x260c027b, 0x73fe1833, + 0x0b1f420a, 0x00820020, 0x8b430220, 0x000e3a08, 0x40310017, 0x0201152e, 0x4c010100, 0x030e1617, 0x13144a01, 0x00040203, 0x514f1949, 0x4303200c, + 0x15200580, 0x4e057541, 0x754306d9, 0x05aa4a05, 0x01012725, 0x4b24fe37, 0xfc3509db, 0x26f5030b, 0xfafe3338, 0x4402e604, 0x20febcfd, 0xfeca018a, + 0x07674336, 0x37200134, 0x17a61735, 0x20013735, 0xfda65dfe, 0xf60175e8, 0x6343f601, 0x00112e0b, 0x102b402e, 0x4a02020f, 0x00020304, 0x24048249, + 0x02000002, 0x30078357, 0x015f0002, 0x00020001, 0x0000004f, 0x11110011, 0x05095d16, 0x01211524, 0x4a430127, 0x26262905, 0x01370127, 0xb5fec404, + 0x06317683, 0xfd263a32, 0x26bb0245, 0xfafe323a, 0x02e0018a, 0x2c7084c5, 0x18353620, 0x363518a6, 0xfd752001, 0x071341e8, 0x04c3033f, 0x000e00dd, + 0x402c0014, 0x01111429, 0x01010003, 0x020e104c, 0x12134a01, 0x00040203, 0x1e561849, 0x1711270f, 0x2b180702, 0x7a8c0103, 0x20052143, 0x080b41e3, + 0x11fb272b, 0x3827ef04, 0x02fafe33, 0x0e1b437c, 0x420a0741, 0x8a820799, 0x43020021, 0x0e2e0a1b, 0x2a402d00, 0x0302050c, 0x4c010001, 0x93820d0e, + 0x0a0b4a25, 0x18040304, 0x460ca448, 0x162005b8, 0x11438c83, 0x42252005, 0x01210591, 0x090e4337, 0x031b0325, 0x4180fc80, 0x0a430888, 0x41532008, + 0x07430a7f, 0x00082608, 0x06254028, 0x27738301, 0x00020708, 0x0204054a, 0x535d7092, 0x236a8705, 0x4b017903, 0x23057241, 0x8a36feca, 0x41066641, + 0x5b4109d7, 0x9f121906, 0x18072124, 0x0e9f1219, 0x2006e542, 0x0ccc4101, 0x410be650, 0x002205ca, 0x67460000, 0x05300809, 0x21001b00, 0x4b404e00, + 0x02020813, 0x154c0100, 0x04040514, 0x1d1e4a01, 0x03041112, 0x01010449, 0x00020508, 0x67000102, 0x02020709, 0x57020303, 0x27080783, 0x065f0302, + 0x03020301, 0x061c1c4f, 0x1c211c06, 0x061f2021, 0x1c1b061b, 0x10112611, 0x2b1b070a, 0x21352101, 0x07131701, 0x13860219, 0x07010522, 0xfe351e82, + 0x02a6fc96, 0x8a3501fe, 0x676701c0, 0xfc0b0401, 0x1934276e, 0x05405875, 0x34197536, 0xf9920327, 0x8a6301d2, 0x02fdcbfe, 0x01a2e302, 0x7bfe7558, + 0x30097146, 0x6b026b02, 0x2f1e7f75, 0xfee2a217, 0x5801757b, 0x0f7746a2, 0x0202113c, 0x4c010400, 0x05021617, 0x020b0c4a, 0x01064901, 0x02070805, + 0x04050004, 0x9e680367, 0x21068205, 0x4a180100, 0x1d2309b7, 0x47161d00, 0x09230539, 0x192b1d07, 0x820d4003, 0x372721cc, 0x0727d184, 0x21070606, + 0x83fb0115, 0xc9023fb3, 0x3326b0fd, 0xfe8a751b, 0x014dfecc, 0xfe656522, 0x01b301de, 0x1b758a34, 0x50022633, 0xae84e302, 0x202e1623, 0x22a0837f, + 0x82a27171, 0x207f24c3, 0x41a2162e, 0x0324057b, 0x00dd04a1, 0x3705d345, 0x0b3a403d, 0x00030208, 0x05074c01, 0x4a010304, 0x090a0d0e, 0x00490204, + 0x4906dd48, 0x0c2d11c9, 0x0c110c0c, 0x10111c11, 0x2b190705, 0x24988413, 0x01011725, 0x3b018407, 0xfb1d3521, 0x0185041f, 0x97018a35, 0x0136fe8a, + 0xd6fd8aca, 0x8a6301d0, 0x7bfbcbfe, 0x29054941, 0x0afe7575, 0x02750afe, 0x3c41716b, 0x00002506, 0x3dfc0200, 0x3508db45, 0x403e001b, 0x0508133b, + 0x03000402, 0x14154c01, 0x4a020301, 0x4c431112, 0x19022005, 0x21167e04, 0xff410606, 0x83292005, 0x84012092, 0x4125208c, 0xfe2114fd, 0x29948767, + 0x67017403, 0x13050167, 0xf94166fb, 0x9a04230d, 0xa188dd04, 0x8213f341, 0x020025ae, 0x0700ecff, 0x2a084341, 0x05304033, 0x4a010204, 0x41020708, + 0xa4821b37, 0x0b060b23, 0x05374116, 0x2205a242, 0x82070101, 0x3e023108, 0xf601aefd, 0xfe8a3501, 0x8a63019d, 0x0afecbfe, 0x21052941, 0x214199fd, + 0x00012207, 0x089749ed, 0x36403922, 0x33970519, 0x42190721, 0x01210e56, 0x054e4217, 0x013f022c, 0x02016767, 0x26f4fd85, 0x02431b33, 0x331b2407, + 0x420c0226, 0xf3420b44, 0x2e202305, 0xff84a216, 0x08089b46, 0x17000822, 0x35403800, 0x00020211, 0x134c0101, 0x01030112, 0x040f104a, 0x49000403, + 0x01020304, 0x57010000, 0x2c093563, 0x094f0001, 0x09170909, 0x15111217, 0x21908205, 0x00411703, 0x65212005, 0xd36508c4, 0x41a02005, 0xfe2905a4, + 0x02bcfd20, 0xfc440744, 0x0c9e590b, 0x26383322, 0x2208a241, 0x59a6a618, 0x37220c4e, 0x9f831735, 0x2b09074a, 0x402e0011, 0x020c0d2b, 0x06074a02, + 0x5a27a346, 0x2122057e, 0x8d852135, 0xfdc40431, 0x323a2645, 0xfe8a0601, 0x01b5fe20, 0x5ce0014b, 0x02330563, 0x3518a6c5, 0x75e0fe36, 0x02a61802, + 0xe0fe7518, 0x46183536, 0xa13b08a3, 0x0800dd04, 0x2c000e00, 0x0b0e2940, 0x01000302, 0x010a4c01, 0x0d4a0102, 0x4603040c, 0x152513a3, 0x2b180702, + 0x070f4113, 0x2005c242, 0x0706419c, 0x0380fc25, 0x855b0480, 0xd6fd210d, 0x7683fc8a, 0x43054c43, 0x14260d43, 0x31403400, 0x7785050e, 0x010f1023, + 0x48788803, 0x002e0c30, 0x4f000100, 0x14060606, 0x03171406, 0x875f1707, 0x15252206, 0x09805b21, 0x43070621, 0x08240932, 0x2711fb87, 0x220b285b, + 0x88273833, 0x536b218c, 0x20128941, 0x08274301, 0x2700082d, 0x01022440, 0x4c010100, 0x48010101, 0xa8470530, 0x02152310, 0x84861807, 0x21352124, + 0xf1851703, 0x88057541, 0xa6182168, 0x0f43b683, 0x000e2507, 0x082c402f, 0x0a235784, 0x41010209, 0xe49105e5, 0x00000026, 0x110e000e, 0xde8de484, + 0x5e09dd41, 0xd941093d, 0x08155e09, 0x02000030, 0x72ffbbfd, 0x16054702, 0x0a000600, 0x33192100, 0x5e18080b, 0x7048118f, 0x37012705, 0x27011501, + 0xc9821301, 0x42bbfd3c, 0xb6fb4a04, 0xc8c40342, 0x73048dfb, 0xfe977f04, 0x18feac18, 0xfca70197, 0x9a82a39a, 0xb9205b82, 0x45205b82, 0x17205ba9, + 0x82053061, 0x03022b5b, 0x033cfc42, 0xb6fb42c4, 0x5c837304, 0x9716052c, 0x59fe59fe, 0xace80197, 0x5c8344fc, 0x69fc0122, 0x3706136e, 0x403f0038, + 0x0001363c, 0x09222305, 0x06050607, 0x011c0104, 0x4c030403, 0x27069a51, 0x00860203, 0x61000101, 0x1f3e9082, 0x0404004d, 0x03006103, 0x4e032003, + 0x11253738, 0x06102b1f, 0x012b1b07, 0x05040416, 0xda821517, 0x24240037, 0x15062223, 0x17161614, 0x1415021e, 0x11070606, 0x26261323, 0x05305927, + 0x837f3620, 0x1137250a, 0xa3e0fe33, 0x53086a82, 0xa5730151, 0x01332cfd, 0xfe44fefc, 0xa1effe85, 0x8f3e9573, 0x68ad7f84, 0xab77a858, 0x55e89001, + 0x77bc4b71, 0x34538b53, 0xc195747e, 0x75b46566, 0x0a7805ab, 0x64e1bd62, 0xe871feb5, 0x08010001, 0x5d6355cf, 0x2744503a, 0x7ca36025, 0x156ea567, + 0x1d01d9fe, 0x122d4719, 0x010a5f23, 0x3ac2822b, 0xfafb0100, 0x7303cbfe, 0x3700a306, 0x3a403d00, 0x04022225, 0x0c0e2903, 0x82050a0b, 0x012c0808, + 0x4c030201, 0x01040128, 0x0100004b, 0x03008600, 0x03020400, 0x02006904, 0x00610102, 0x01200101, 0x242b2d4e, 0x14112a23, 0x2b190705, 0x07f54719, + 0x0100242c, 0x01070135, 0x33160404, 0xe28e3632, 0x11fa4719, 0x82730321, 0x9aaa32d8, 0x1efeeffe, 0xf60235fe, 0x01c8fd19, 0xe9bd01b9, 0x23e28976, + 0x65aa75b5, 0x15054819, 0x51021c37, 0x19010201, 0xc99c01b4, 0xe4fbd2fe, 0x4e6d3646, 0x22465942, 0x0e48192c, 0x44512a13, 0xa3602526, 0xf801007c, + 0x06f36512, 0x41003e34, 0x013c3e40, 0x26280500, 0x07092425, 0x04080506, 0xe9411d01, 0x3d3e2523, 0x2c1f112a, 0x230de941, 0x022c2725, 0x2110e941, + 0x0b412611, 0x14fe381b, 0x012e01aa, 0xcd440143, 0x01362bfd, 0xe8feedfa, 0xe4fed6fe, 0x4198769c, 0x164108ef, 0x02032407, 0x41b7fd14, 0x05321216, + 0xb5690b77, 0xfeb57dc7, 0x8dfcef6e, 0x62589fa8, 0xe6863a5e, 0x4106f841, 0xa1230820, 0x41cbfec7, 0x2b081320, 0xfd020000, 0x02d20030, 0x001804d0, + 0x003b001d, 0x1a524055, 0x01000219, 0x03020a0b, 0x02373802, 0x28290504, 0x04060702, 0x0802004c, 0x08be6718, 0x06042508, 0x00690405, 0x07010906, + 0x00650706, 0x61010000, 0x1c010100, 0x1e1e4e00, 0x3b1e0000, 0x33353a1e, 0x23252c2e, 0x1c284f82, 0x0a252725, 0x122b1907, 0x2107be62, 0x385b0706, + 0x0617240d, 0x9b022306, 0xef23081c, 0x50406072, 0x84433162, 0x21811a68, 0x3a6dbc86, 0x52415d6f, 0x945e3366, 0xd03b812b, 0x5d723d99, 0x97634f43, + 0x9a023f1d, 0x30283223, 0x304c2b2d, 0x4d784343, 0x31283122, 0x41506a2f, 0x38fea874, 0x30293123, 0x178f2c2e, 0x04000028, 0x5f0118fc, 0x6f52e803, + 0x000b3706, 0x402b000f, 0x00010228, 0x04010103, 0x06670100, 0x05050401, 0xb2185704, 0x0727145d, 0x21012b1e, 0x82252115, 0x86052003, 0x18fc2707, + 0x67fc9903, 0x05833704, 0x89c9fb21, 0x8503250b, 0xe2a2a2a2, 0x00230382, 0x8e68f706, 0x00133a6f, 0x40370017, 0x02020434, 0x02030500, 0x01000601, + 0x02080a67, 0x06070706, 0x2b078357, 0x0b5f0706, 0x06070209, 0x16174f07, 0x0c155d18, 0x1f070c22, 0x838b7f88, 0xf7270b83, 0xfcc00368, 0x89600440, + 0x40f72105, 0x9384118f, 0x22089585, 0x0100a2a2, 0xe8ffda00, 0x1e04a403, 0x2d001c00, 0x070c2a40, 0x02010306, 0x0100011a, 0x02004c02, 0x82850201, + 0xca4f1820, 0x1c56080c, 0x1217191b, 0x16060310, 0x021e012b, 0x27071415, 0x27262634, 0x06141127, 0x26222306, 0x36363435, 0x11173233, 0x3d020333, + 0x3a241f46, 0x2e2e3115, 0x63457241, 0x4572436f, 0x0360313f, 0x514729e0, 0x184c5035, 0x1e436251, 0x2904fd1e, 0x44483754, 0x1a305331, 0x66821003, + 0xff302308, 0x043004e8, 0x001f0082, 0x0d304033, 0x1d010301, 0x02030001, 0x0f1e1f4c, 0x4a01040e, 0x02000300, 0x26825903, 0x00269582, 0x03030069, + 0x10826102, 0x2551022a, 0x04232527, 0x012b1a06, 0x0520818d, 0x2522918e, 0x88893004, 0x892afe21, 0x9602230b, 0x87880001, 0x766e0224, 0x0d8932fd, + 0x00acc82c, 0xb000ffff, 0x1104e7ff, 0x77823704, 0x8200db21, 0x9e01370f, 0x12035403, 0x02006205, 0x0000ec06, 0x9e010100, 0x1203f6fe, 0xa0820401, + 0x18401121, 0x2f0c8b9b, 0x012b1808, 0x02230333, 0xcba98e84, 0xf2fd0401, 0xcc302b82, 0xbe022704, 0x0d00dd05, 0x06b12d00, 0x22404464, 0x4705a747, + 0x5920059d, 0x01200682, 0x8206cc52, 0x000d2459, 0x1803160c, 0x0808179d, 0x06141523, 0x37230707, 0x36343526, 0x437b0233, 0x6d511f15, 0x32453138, + 0x3141dd05, 0xa940401b, 0x31342ce3, 0x23348242, 0x0501ffff, 0xab209f82, 0x23249f82, 0x67ffec06, 0x03201282, 0x9920a782, 0xab830782, 0x53054426, + 0xe2056a03, 0x2720ab82, 0x1c207f84, 0x23141748, 0x11030003, 0x012b7987, 0x03352115, 0x05dafd6a, 0x838f8fe2, 0x86ef8244, 0x000322ff, 0x25438419, + 0x0001000e, 0x1b828501, 0x10117630, 0x2b180902, 0x440006b1, 0x33132301, 0xf7822c02, 0x02540333, 0xfcffff0e, 0xfe0d055e, 0x00f405f0, 0xfb000703, + 0x322a8250, 0xfdffff00, 0xfeaf0424, 0x01b0052e, 0xfb010707, 0x5b9aff52, 0xff2105df, 0x05df5b9a, 0xfc01002d, 0xfefa04b4, 0x00460699, 0x63060003, + 0x012f05db, 0xfc070537, 0x910154b4, 0x9fa7053a, 0x820066e6, 0x82bd2023, 0x8ca22023, 0x17252e23, 0x01bdfc05, 0x55fe5590, 0x9fe66005, 0x267b82ad, + 0xfe8b045c, 0x822806f4, 0xfb042267, 0x21678550, 0x678ab802, 0xa904592a, 0xe405f7fe, 0x1b000600, 0x1028cf84, 0x03040506, 0x49000502, 0x7622a782, + 0x81410110, 0x33013706, 0x07250705, 0x7e6afd27, 0xff500f01, 0x0552fd01, 0xa25cdfe4, 0x24825ca2, 0x59228782, 0x43828d04, 0x4382c820, 0x43841a20, + 0x05060f27, 0x00040102, 0x211d824a, 0x42881376, 0x23349b82, 0xa8fd3725, 0xfe50ff00, 0xeffe7ef1, 0xa3250552, 0x5ddede5d, 0x76284385, 0xdafe9404, + 0x0e00a805, 0x23071b42, 0x0304090a, 0x01214384, 0x26901901, 0x000e230f, 0x1b42250d, 0x26390808, 0x16372726, 0x37363233, 0x23020e17, 0x528353fd, + 0x832e7d08, 0x7d165d46, 0x53885308, 0x713f9404, 0x45831a4a, 0x714a1a3e, 0xff00003f, 0x04c1fcff, 0x068ffe6a, 0x07070116, 0x110f4108, 0x592c1f82, + 0xfafe1d05, 0x03000e06, 0x52fb0907, 0x13829a83, 0xdc049626, 0x6b05bcfe, 0x0a203382, 0x2713ab41, 0xdc04f6fb, 0x6b055cff, 0x342a5742, 0x35211503, + 0x059afca4, 0x008f8f6b, 0x045cfc02, 0x06f4fef1, 0x2f3f828e, 0xb5080007, 0x00020406, 0x012b3202, 0x25030713, 0xfc360382, 0xde73b4f9, 0x76a2f601, + 0xfe8e06cb, 0x4c013b9e, 0x379efe51, 0xcb824e01, 0x041ffd2f, 0x0613fe43, 0x06070100, 0x06f1fffc, 0x0543428b, 0x428b0621, 0xd8260843, 0xccfd4304, + 0x53410006, 0x01052509, 0x4c010100, 0x22146f43, 0x430d000e, 0x2c080e6f, 0x26272317, 0x36343526, 0x437ffd33, 0x6f3a161a, 0x44101263, 0x42000631, + 0x11321d31, 0x3527d3ea, 0x0042311b, 0xfd2efd01, 0xff22feb8, 0x43638975, 0x638b1ad3, 0x43160421, 0x638507d3, 0x0f43df35, 0x3a706312, 0x32431916, + 0x1b31428b, 0xead32636, 0x821d3211, 0xffff3162, 0x08fec0fc, 0x0d0092fe, 0x0b070701, 0xedff52fb, 0xff21e785, 0x26e788ed, 0xff2c0247, 0x41bb0207, + 0xf92e2e7f, 0xbb0240fd, 0x01008f8f, 0x2c021bfb, 0x3fac3700, 0x21151326, 0xe4fa3735, 0x023b3f84, 0x0d050e01, 0xf405a003, 0x17000b00, 0x06b13200, + 0x27404464, 0x01000102, 0x82590001, 0x01002606, 0x04030561, 0x2a0f8203, 0x000c0c51, 0x0c170c00, 0x82101216, 0x240a222a, 0x065c4306, 0x3526002c, + 0x32333634, 0x06141516, 0x0b8a2023, 0x4452012a, 0x44313344, 0x73013144, 0x33200482, 0x05290c82, 0x3231420d, 0x31324242, 0x2b078742, 0x01000000, + 0x1505d201, 0x1606dc02, 0xd7445482, 0x0551450c, 0x21826120, 0x82510021, 0x000b2327, 0x5145240a, 0x05b2460c, 0x91023333, 0x3a3b4b4b, 0x063a4a4a, + 0x38364916, 0x36384a4a, 0x26538249, 0x03dc046a, 0x44350645, 0x072d0a7f, 0x45033725, 0x5f61fe3c, 0xba684405, 0x2555829f, 0xfa046d01, 0x7f445203, + 0x6d01210f, 0x27097f44, 0x0c010200, 0xa403f104, 0x2310db42, 0x13171327, 0x01330382, 0x9fa27682, 0x9db47379, 0x0137f504, 0xaefe4b62, 0x8362013b, + 0x267f82aa, 0x03e40409, 0x443306a7, 0x49200f53, 0x360d5344, 0x33252707, 0x5a020705, 0x110156fb, 0x520f017e, 0x5bb69a05, 0x995bf4f4, 0x0e93443f, + 0x05173725, 0x82372523, 0xfe52293f, 0xeffe7ef1, 0xb77c0556, 0x26283f86, 0x8903e604, 0x0f001c06, 0x21078f44, 0x8f440a0b, 0x000f2318, 0x8f44260e, + 0x0890440d, 0x83fb013e, 0x157d0949, 0x5d454458, 0x4d087e15, 0xe6045a86, 0x1a468254, 0x4e59594e, 0x5482461a, 0x002dcd82, 0x04710102, 0x063f03d0, + 0x000f007c, 0x3ba4181b, 0x101b2426, 0x8214161a, 0x260e212f, 0x21084442, 0x65181616, 0xfc180c4a, 0x52080c17, 0x3b3b699b, 0x6a42426a, 0x43693b3b, + 0x30393930, 0x31383831, 0x62397c06, 0x39623a3c, 0x3c3a6239, 0x3c673962, 0x3b3c3334, 0x003c3434, 0x07010100, 0xa8031d05, 0x19000e06, 0x06b13c00, + 0x31404464, 0x02021516, 0x02080901, 0x4c020003, 0x03000200, 0x54005902, 0x692b050d, 0x03020200, 0x03010461, 0x82510302, 0x00192fcb, 0x24252418, + 0x2b190905, 0x440006b1, 0xca6d2600, 0x36272506, 0x16323336, 0x0806cd69, 0x06061729, 0x3ca50223, 0x16291d29, 0x731a2f21, 0x29486f26, 0x281d283c, + 0x1c311d16, 0x45702772, 0x1b1c1d05, 0x302c1514, 0x8262513a, 0x29142508, 0x5a56392e, 0x44269383, 0x6a034205, 0xe343d105, 0x08bb472a, 0xbb47d120, + 0xfe6e2a07, 0x0040031b, 0x00150020, 0x2ed78438, 0x0001052d, 0x03011001, 0x02010f00, 0x884c0303, 0x820320d3, 0x495920d4, 0x11240b64, 0x1a090411, + 0x0425d384, 0x33372326, 0x086b4115, 0x0805de4e, 0xa2023523, 0x7d135956, 0x73445e5f, 0x28703d46, 0x21491c39, 0xe822ea75, 0x445f098f, 0x1c2f5b40, + 0x110f6917, 0x2ac3834f, 0x032dfe89, 0x00440021, 0x84250013, 0x131a257f, 0x4a000209, 0xe1461983, 0x23818206, 0x26235101, 0x08074748, 0x020e2133, + 0x33161415, 0x06073732, 0x26262223, 0x37363435, 0x6b622103, 0x373b3528, 0x3c411343, 0xba3e734c, 0x464c2ac2, 0x0e312f28, 0x5d350f8e, 0x39a0713b, + 0x264d8300, 0x02ed03f3, 0x437705d5, 0x13300abb, 0xf3010317, 0x0373ad35, 0x147901fe, 0xffff8afe, 0x3108b745, 0x00fc0602, 0x01ffff00, 0x03fe050f, + 0x01e506a1, 0x41820707, 0x00f1002b, 0x0200b108, 0x35b0f1b0, 0x261b822b, 0x020606d3, 0x820707dd, 0x8201201b, 0x201b84a1, 0x291b8401, 0x6a010100, + 0x4703e605, 0xa7482907, 0x6a012a0d, 0x377b0162, 0xde9f8a06, 0x214d8265, 0x23826601, 0x23074b22, 0x252e238a, 0x66010517, 0xfe539201, 0xd84b064d, + 0x63829e9f, 0xe2050d26, 0x7f07a503, 0x04206382, 0x7f856387, 0x092b6382, 0xa703ed05, 0x06002807, 0x48401300, 0x07220e9f, 0x9b482b17, 0x1a022106, + 0x21079b48, 0x9b482807, 0x09012309, 0x3b82e405, 0x3b821e20, 0x48401221, 0x3a830d97, 0x21059348, 0x93485802, 0x7c062508, 0xdede5ca2, 0x2d05d748, + 0xeb052701, 0xff068a03, 0x25000f00, 0xff432240, 0x214e821f, 0xef502600, 0x17373d07, 0x0223020e, 0x08528405, 0x4458157e, 0x7d165c45, 0x52875308, + 0x713feb05, 0x453e1a4a, 0x20078e48, 0x26f78200, 0x03c10572, 0x826d0740, 0x8d0820f7, 0x261b82f7, 0x030e0608, 0x82ff06a9, 0x4109201b, 0x1b820d77, + 0x33064526, 0xc2066b03, 0x0a201b82, 0xe7421b90, 0x07022e07, 0x0000000b, 0x04a50101, 0x060b0382, 0x0c0f4218, 0xd02a1582, 0x04f8fe96, 0x625b01bd, + 0x2682ccfe, 0x05252783, 0x070d03b3, 0x2a278f38, 0xf6fe96d2, 0x4a01ee05, 0x82dcfe61, 0xff340827, 0x0557fcff, 0x06f8fe1d, 0x0602000e, 0x0000fef6, + 0xfed4fc01, 0xff7efe82, 0x000e00b2, 0x6406b15a, 0x0a0a4044, 0x0b000101, 0x02010201, 0x0db04b4c, 0x17405850, 0x01282582, 0x01007000, 0x59010202, + 0x02226882, 0x1d830362, 0x401b5223, 0x21198216, 0x18908500, 0x83405921, 0x000e25b9, 0x0413220d, 0x0806544b, 0x35260026, 0x14153335, 0x37363233, + 0x23060617, 0xa2784cfd, 0x1d312154, 0x405f2945, 0x617482fe, 0x1054575b, 0x281f6012, 0x01274f82, 0x02a504d0, 0x8c5c06e2, 0x01032cc7, 0x8bc74bd0, + 0xa001bc04, 0x826efe25, 0x03c72682, 0x05e902d1, 0x34238e88, 0x94d84ac7, 0xa001e803, 0x006ffe26, 0x040c0103, 0x07a203dd, 0x24238230, 0x001b000f, + 0x21db843f, 0x43490334, 0x01022206, 0x05d7474a, 0x59010022, 0x01230884, 0x82026100, 0x0021081b, 0x04101051, 0x101b1004, 0x0414161a, 0x280e040f, + 0x2b170806, 0x440006b1, 0x03171301, 0x14151626, 0x06774706, 0x0b1ebf18, 0x3a140225, 0x47df7cc1, 0x012106e5, 0x06f747db, 0x01c8052e, 0xa9fe2668, + 0x31314414, 0x31324344, 0x32211e82, 0x320b8343, 0x01ffff00, 0x029904de, 0x015606d2, 0x04fc0607, 0x49e106b0, 0x06200513, 0x9c091f68, 0x86ff821f, + 0x291b4a1f, 0x0020c586, 0x0720c183, 0x2d081b4a, 0x19438402, 0x63703a16, 0x31430f12, 0x1b4a5606, 0x36262e06, 0x0042311b, 0x04340102, 0x066c037f, + 0x2c638249, 0xb1330012, 0x40446406, 0x08101128, 0x227d8203, 0x5e01124c, 0xf74d07ab, 0x000e240e, 0x8c03160d, 0x23072e6b, 0x35262637, 0x17333634, + 0x01071337, 0x09274ae5, 0x5dacaf25, 0x4a49067b, 0x36250b2c, 0x2060fe2c, 0x22008200, 0x93360102, 0xaf05207b, 0x84e7887b, 0x89dc207b, 0x86b920eb, + 0x321d247b, 0x84d3ea11, 0x207b8aef, 0x207b8234, 0x23f7c961, 0x03171313, 0xa423f78b, 0x8d8eac5d, 0x56fe27f7, 0xfe2ca001, 0x7341006c, 0x06612206, + 0x0d73414a, 0x7b84f7b9, 0xf789da20, 0x7b83b020, 0xe7414a20, 0x55fe210b, 0x05327b88, 0xa6038204, 0x1900d406, 0x48002800, 0x446406b1, 0x39483d40, + 0x0833480c, 0x0301063c, 0x69030204, 0x05050400, 0x04005904, 0x005f0504, 0x4f050405, 0x27280000, 0x3e821f21, 0x25241825, 0x48080724, 0x07201f45, + 0x21051642, 0x494c1632, 0xa3022105, 0x2c185448, 0x441f22a7, 0x18423332, 0x056c2922, 0x115f48e3, 0x3214e532, 0x41423122, 0x3f411b32, 0x02000049, + 0x84040501, 0xd620c782, 0x4c20c784, 0x4120c784, 0x2823c789, 0x48050401, 0x02200a2b, 0x0520cb82, 0x0520cb83, 0x5925c682, 0x04050500, 0x20d6825f, + 0x23cb8204, 0x1a1b2123, 0x0320cba8, 0x85076c4d, 0x2ccb9acd, 0x22286d1f, 0x33324218, 0x05212044, 0x36cb91e5, 0x3e499ffe, 0x41321c41, 0x33213142, + 0x01030014, 0x03dd040d, 0x440107a1, 0xe21947c3, 0x46211b5b, 0x49e21973, 0x91062412, 0x19dbfe70, 0x251137e2, 0x03000000, 0x9b820f01, 0x9bc9a320, + 0x05171322, 0x25185f45, 0xfe73ee0f, 0x6045a7ee, 0x45d92007, 0xdc250760, 0xfd702501, 0x135f4533, 0xd0040d3b, 0x0407ae03, 0xed062700, 0xc3ffb804, + 0xf6060701, 0xf600b404, 0x00b11100, 0x270f8202, 0xb12b35b0, 0xf6b00102, 0x2f05834e, 0x6401ffff, 0x4903fa04, 0x03004606, 0xb004ef06, 0x0028dd82, + 0xc6010100, 0xe802d103, 0x2e0c6346, 0x01071337, 0x8e4ad8c6, 0xfe266205, 0x82001760, 0x08434d37, 0x85f00621, 0x46138237, 0x0223079b, 0x83002007, + 0x078f4b23, 0x83820320, 0x5b84ae20, 0x00052008, 0x091eff54, 0x00ee0550, 0x014a0171, 0x0179015f, 0x41c60282, 0x0042016e, 0x000d0001, 0x8236010e, + 0x00102e07, 0x0150010d, 0x0002003e, 0x0110000b, 0x2025826a, 0x082b825c, 0x23013036, 0x74001a01, 0x11000800, 0x6e010b00, 0x02006501, 0x11000c00, + 0x63018201, 0xf9001c01, 0x05007000, 0x14001300, 0x0c017401, 0xef00f500, 0x82008400, 0x69007a00, 0x2a082f82, 0x0112000a, 0x00070109, 0x00e100f2, + 0x00d000d5, 0x006c00c9, 0x00620065, 0x005d005e, 0x00200059, 0x0009000e, 0x00d3000a, 0x82030001, 0x00c32409, 0x8253005a, 0x82022009, 0x00992403, + 0x82550056, 0x00062407, 0x824f0002, 0x0005321f, 0x00bf0006, 0x00b800b9, 0x00a000b2, 0x009e009f, 0x205f824c, 0x2c798208, 0x00ad00af, 0x00a200aa, + 0x00070004, 0x22518208, 0x8257014c, 0x820c202f, 0x4b5c0803, 0x500ab04b, 0x007d4058, 0x110b0d10, 0x0c007210, 0x0c111411, 0x14008014, 0x13141113, + 0x1213007e, 0x0070130b, 0x1209120a, 0x0080090a, 0x09120309, 0x03007e03, 0x02031202, 0x0602007e, 0x7e060212, 0x12050600, 0x007e0506, 0x05120805, + 0x08007e08, 0x70080707, 0x0f000000, 0x690f000e, 0x28085f82, 0x0e010d0e, 0x000d0069, 0x0b0d110b, 0x00110069, 0x12110a12, 0x0407006a, 0x00590704, + 0x62040707, 0x04070400, 0xb04b1b52, 0x2084820c, 0x2384987e, 0x7e121311, 0x402185e1, 0x23808380, 0x800b100d, 0xb1110641, 0x08122381, 0x08417e07, + 0x5951082f, 0x012b4159, 0x017f0180, 0x017b017d, 0x01760178, 0x01670168, 0x014d014f, 0x01450147, 0x0139013b, 0x01330135, 0x012b012c, 0x01260127, + 0x00040106, 0x00cd00ce, 0x00b500b6, 0x00a500a6, 0x00960098, 0x004d004e, 0x00450047, 0x00350037, 0x002f0031, 0x31018225, 0x00060015, 0x36132b18, + 0x33023e37, 0x16171632, 0x06823633, 0x14151624, 0x0c821607, 0x021e1726, 0x34171617, 0x11820382, 0x07060628, 0x26222306, 0x05820627, 0x2726272b, + 0x06222326, 0x020e0707, 0x22178207, 0x82151616, 0x27242d14, 0x37272626, 0x36272726, 0x07063736, 0x04820583, 0x08843720, 0x0f863420, 0x052e0685, + 0x17373625, 0x14150606, 0x022e0717, 0x46822327, 0x82072721, 0x8270830d, 0x82142049, 0x200d8267, 0x29238417, 0x37170707, 0x021e0717, 0x5b833533, + 0x14821620, 0xa6820784, 0x34373524, 0x7b823526, 0x36342729, 0x2e273537, 0x82173502, 0x363622b1, 0x20058337, 0x85248237, 0x5d232002, 0x0720051d, + 0x22820d82, 0x33373428, 0x36361717, 0xa4823435, 0x16173723, 0x83d88204, 0x2223210c, 0x23258a82, 0x36343526, 0x821c8237, 0x8326202a, 0x170724c9, + 0x82262207, 0x37372114, 0x2184ea83, 0x36253683, 0x17323336, 0x05ea7333, 0x6f4fdb84, 0x07062105, 0x19825882, 0x84070721, 0x822320d8, 0x829c826d, + 0x249c8213, 0x35333637, 0x82988327, 0x1507231b, 0x4f820717, 0x2507b10a, 0x26222306, 0x17173727, 0x759e7484, 0x2971deb6, 0x0f57517a, 0x614d495d, + 0x5d1c062a, 0x5171363b, 0x040a4058, 0x0b020406, 0x11372e05, 0x1b0f1a0c, 0x20752904, 0x281f4921, 0x391e356e, 0x46481425, 0x1b06131f, 0x380d0709, + 0xf9fe6946, 0x32955580, 0x04133168, 0x442d2a0f, 0x2e0a0858, 0x27089618, 0x1c06ea6f, 0x49a94064, 0x30922a06, 0x06616057, 0xfe5fc633, 0x3fe601da, + 0x423a0233, 0x1815080e, 0x0804020d, 0x04140a06, 0x07162204, 0x0e262320, 0x060d0e0d, 0x10082664, 0x0c184d75, 0x4d8006ac, 0x1242bbc6, 0x24080f33, + 0x280b1356, 0x1f080b57, 0x220e1972, 0x17531402, 0x4e374b0c, 0x1434400a, 0x235c9731, 0xc33012f3, 0x1a3a2423, 0x5a312726, 0x17655648, 0x27240206, + 0x3f120205, 0x40392717, 0x260a0a1c, 0x0b191b09, 0x9764066a, 0x6c6a5701, 0x0c101292, 0x3e0c0410, 0x0e0e0e10, 0x076e5c0f, 0x3e8f5b2a, 0x5a045808, + 0x04584381, 0x4c2a1c04, 0x2c1f1828, 0x75049a0b, 0x1a3241c8, 0x23290e0a, 0x1d60923d, 0x101b030c, 0x3d832e02, 0x156faf69, 0x736213d4, 0x660a222e, + 0x0c061307, 0x15181d17, 0x1b7a122d, 0x023e3160, 0x0236285e, 0x02205628, 0x36053615, 0x543d5706, 0x19be024a, 0x2b492621, 0x03506a24, 0x5d7c74cc, + 0x1c215a7b, 0x5e481c1d, 0x1e151922, 0x2a171a40, 0x1b2d261d, 0x3806510b, 0x0a19321d, 0x076a760f, 0x21020406, 0x0b060e43, 0x0b14171f, 0x605a4a26, + 0x110d5922, 0x39080734, 0x4088324d, 0x0e020238, 0x161e2012, 0x5124102c, 0x780e681b, 0x3f107866, 0x4e013a81, 0x83481023, 0x2622201b, 0x46a6420e, + 0x0513b24a, 0x508a2a0a, 0x0f082d37, 0x1c052630, 0x02200232, 0x66330c1c, 0x2e2b0c25, 0x2113173e, 0x121f1916, 0x06020519, 0x23401808, 0x0a260a0b, + 0x2d59404c, 0x20511304, 0x1f351b08, 0x216d1e19, 0x273a1806, 0x0201342f, 0x14260201, 0x21463302, 0x4d06200a, 0x38062861, 0x3b010c62, 0x07471a08, + 0x10152404, 0x1a1a0c09, 0x0627421f, 0x212e1c08, 0x0c010805, 0x5e241405, 0x6e5b4546, 0x173d0c40, 0x780b2a0f, 0xdd7d2a06, 0x2a101c1a, 0x263b1f2e, + 0x22482806, 0x0f0e170d, 0x27140c15, 0x1f0f0228, 0x6a023552, 0x2238220a, 0x04081636, 0x2d2d342a, 0x1a234213, 0x10442e0a, 0x23292218, 0x2514020a, + 0x1d11080d, 0x06287e68, 0x0e0a6c42, 0x2a420e34, 0x1a111b19, 0x20072330, 0x2b18ae13, 0x08220609, 0x08440412, 0x0822340e, 0x22087782, 0x12066208, + 0x230a2c0c, 0x06280223, 0x04000000, 0x6cfff601, 0x8205f608, 0xed00d800, 0x10010701, 0x44010000, 0x17250545, 0x17070606, 0x05805237, 0x28442320, + 0x16173505, 0x26331716, 0x33363435, 0x06071732, 0x16161415, 0x37273733, 0x16201482, 0xf3431983, 0x2c218307, 0x15163233, 0x27260714, 0x27272426, + 0x201c8207, 0x211c8215, 0xc8432727, 0x20308206, 0x05c84337, 0x02850982, 0x26070624, 0x70822726, 0x27200582, 0x17335682, 0x06061517, 0x36361715, + 0x15161437, 0x22071407, 0x82072726, 0x82062028, 0x21078351, 0x27822215, 0x07273723, 0x219e8227, 0x15822737, 0x2006f543, 0x20708234, 0x05ee4327, + 0x3725b982, 0x17021e33, 0x83ae8337, 0x864c8523, 0x023f21bf, 0x1720d084, 0x3722c883, 0x67823527, 0x51823720, 0x15170724, 0x04820722, 0x25208782, + 0xd0096f83, 0x37373233, 0x6f156802, 0x833d69af, 0x1b10022e, 0x601d0c03, 0x29233d92, 0x321a0a0e, 0x0475c841, 0x1f2c0b9a, 0x2a4c2818, 0x5804041c, + 0x045a8143, 0x8f3e0858, 0x6e072a5b, 0x0e0e0f5c, 0x0c3e100e, 0x100c1004, 0x6a6c9212, 0x6497a9fe, 0x190b6a06, 0x0a26091b, 0x39401c0a, 0x123f1727, + 0x1b300502, 0x65170602, 0x315a4856, 0x3a1a2627, 0x30c32324, 0x5c23f312, 0x34143197, 0x374e0a40, 0x53170c4b, 0x0e220214, 0x081f7219, 0x0b28570b, + 0x08245613, 0x4212330f, 0x804dc6bb, 0x180cac06, 0x0810754d, 0x0d066426, 0x260e0d0e, 0x16072023, 0x14040422, 0x0408060a, 0x101a1002, 0x3a420e08, + 0xd83f3302, 0x18152d12, 0x060c171d, 0x0a660713, 0x62732e22, 0x544a8e13, 0x3606573d, 0x02153605, 0x02285620, 0x025e2836, 0x1b60313e, 0x246a8402, + 0x2126492b, 0x74040a19, 0x1d687e28, 0x250d0811, 0x230a0214, 0x10182229, 0x1a0a2e44, 0x2d134223, 0x042a342d, 0x22361608, 0x6a0a2238, 0x1f523502, + 0x2728020f, 0x0f150c14, 0x220d170e, 0x26062848, 0x2a2e1f3b, 0xdd1a1c10, 0x78062a7d, 0x170f2a0b, 0x6e400c3d, 0x5e46455b, 0x0c051424, 0x29050801, + 0x0608162c, 0x1a1f4227, 0x10090c1a, 0x07042415, 0x3b081a47, 0x38620c01, 0x4d612806, 0x210a2006, 0x14023346, 0x02010226, 0x272f3401, 0x2106183a, + 0x1f191e6d, 0x20081b35, 0x2d041351, 0x0a4c4059, 0x230b0a26, 0x06081840, 0x12190502, 0x2116191f, 0x2e3e1713, 0x66250c2b, 0x021c0c33, 0x1c320220, + 0x0c2a2f05, 0x50372d08, 0x050a2a8a, 0x20130813, 0x1a302307, 0x2a191b11, 0x0e340e42, 0xbc426c0a, 0x6206120c, 0x08888208, 0x34220847, 0x0444080e, + 0x06220812, 0x3c182b09, 0x23230228, 0x0000100a, 0xe6050900, 0xce08b401, 0x08009204, 0x1a001200, 0x28002000, 0x35002e00, 0x47004000, 0x35403800, + 0x03080c10, 0x30350001, 0x2527282a, 0x141a1e20, 0x26aa820a, 0x3340464c, 0x51490203, 0x2e080787, 0x01038501, 0x41760202, 0x41474141, 0x04162247, + 0x002b1806, 0x17141506, 0x17322726, 0x27222316, 0x35353636, 0x37121716, 0x07171632, 0x82363526, 0x37342905, 0x16313616, 0x27070617, 0x06220482, + 0x05843707, 0x16272629, 0x16163336, 0x82061417, 0x082c8225, 0x0714158d, 0x11150627, 0x26031f04, 0x0c084616, 0x160e0c14, 0x0e0c3c14, 0x023c051f, + 0x30031c65, 0x17084604, 0x02210b0f, 0x1d0d1b67, 0x196f020c, 0x04111d02, 0x05075204, 0x24071908, 0x0672060a, 0x04062808, 0x060e1787, 0x06251908, + 0x14050454, 0x1f130c0d, 0x110e46fe, 0x0d0f2c07, 0x2e080c02, 0x07250f33, 0x210f0c04, 0x14060e30, 0x1840031f, 0x0d270806, 0x081a3115, 0x09020501, + 0x14180326, 0x0f050702, 0x00004c31, 0xffdafd0e, 0x4bd6061e, 0x01350b37, 0x0195018c, 0x01a3019d, 0x01b101ab, 0x01c301b8, 0x41c203ca, 0x1a494b87, + 0x30015c3e, 0x03002301, 0x0b001300, 0x7d018401, 0x5f016a01, 0x1a014a01, 0x07007400, 0x13001100, 0x8a2a4f82, 0x65016e01, 0x0c000400, 0x5b821100, + 0x2209574b, 0x4b150014, 0xb8201657, 0xaf207b82, 0xa8288182, 0xa401a601, 0x9f01a001, 0x98229182, 0x6f4b9701, 0x076b4b08, 0x20005d24, 0x01821600, + 0xba010a2e, 0xac01b301, 0xd000d500, 0x59005e00, 0x09207982, 0x7b4b1582, 0x0010214b, 0x21107b4b, 0x7b4b008b, 0x13290806, 0x130b110b, 0x110c0072, + 0x150c1115, 0x14150080, 0x7e141511, 0x0b121400, 0x0a007014, 0x0a121612, 0x16008016, 0x09161209, 0x3c894b7e, 0x894b1320, 0x9f8c2021, 0x14112392, + 0x93ea7e12, 0x58502224, 0x9c4b8e40, 0x17274108, 0xaa4b94b8, 0x1c294117, 0x8d8f4021, 0x80112190, 0xec11b941, 0x59593491, 0x012f4159, 0x01c901ca, + 0x01920193, 0x018e0190, 0x4c7a017b, 0x17264845, 0x18000600, 0x0c10012b, 0x33700145, 0x17162324, 0x36343526, 0x15271637, 0x16070614, 0x17373233, + 0x2907584c, 0x26371712, 0x15062326, 0x07831516, 0x37361725, 0x49302726, 0x26240518, 0x36171627, 0x06830f83, 0x26263524, 0x17832227, 0x26343526, + 0x0afe2323, 0x212a8e4c, 0x8e4c4a20, 0x0e0d215a, 0x2fc68e4c, 0x1f032642, 0x4e0d1104, 0x140c0e16, 0x041c080c, 0x08079d4c, 0x3c022e2c, 0x0c0e1f05, + 0x1c033054, 0x0b21480d, 0x4c08170f, 0x1b0d1d0c, 0x11045419, 0x1f19021d, 0x240a0652, 0x05081907, 0x08285807, 0xca4c2006, 0x35102137, 0x224bca4c, + 0x4c132116, 0xe030cbca, 0x06081925, 0x3105170e, 0x140d0c13, 0x5e040405, 0x0805da4c, 0x0f6dfe30, 0x0e11072c, 0x2e330d1a, 0x215e0c08, 0x07040c0f, + 0x1f034a09, 0x45040614, 0x08270d15, 0x18340406, 0x02092603, 0x06080105, 0x050f314a, 0x00820007, 0x8800023d, 0x8b05a8fd, 0x03000807, 0x1f002100, + 0x20211c40, 0x05061e1f, 0x01080203, 0x184c0100, 0x08085b53, 0x10121381, 0x2b170602, 0x07113313, 0x11250701, 0x0f060614, 0x15020e02, 0x34112311, + 0x25373636, 0x1135023e, 0x91012705, 0xfa04bcbc, 0x24c2fe49, 0x24c6736e, 0xc0345049, 0x017d8640, 0x082c3312, 0x0149c2fe, 0xfb0807e7, 0x12026218, + 0x97fecc73, 0x3a719583, 0x38251264, 0x2afe4c60, 0x9172e801, 0x1a8a3f67, 0x01605e51, 0x0173cc3d, 0x01020098, 0x039cff3b, 0x0050066d, 0x00150005, + 0x0e3d4040, 0x86040301, 0x01052e8c, 0x02030204, 0x06800304, 0x84030301, 0xa1161900, 0x01072109, 0x2705847b, 0x12131415, 0x0a0b0c0d, 0x052f3b82, + 0x06081111, 0x11012b18, 0x07211133, 0x83161605, 0x133324ae, 0x82352627, 0x01233e10, 0x95019d3b, 0x0862fe0e, 0xcedc8e0a, 0xde901002, 0x20033003, + 0xec8b6bfd, 0xfe518d5e, 0x3a0a8294, 0x859d1c58, 0xe0fc6a01, 0x00040000, 0x0494ff02, 0x004006ae, 0x002f0027, 0x834e003f, 0x45482493, 0x82060802, + 0x08230894, 0x08060706, 0x02008007, 0x02010500, 0x03046905, 0x06000102, 0x67060108, 0x00000700, 0x07005707, 0x825f0007, 0x4f002f08, 0x32343519, + 0x2b342413, 0x1f060938, 0x8c82002b, 0x0706142a, 0x21230606, 0x26272622, 0x34289282, 0x36363736, 0x34113333, 0x32200583, 0x332eac83, 0x25171632, + 0x23341121, 0x01152223, 0x29822634, 0x11150629, 0x21331614, 0x5b353632, 0x15220558, 0x3a823523, 0x042d3982, 0x1f23238b, 0xfd2d521f, 0x1f502d12, + 0x080b831f, 0x5e2d5032, 0x384b7340, 0x5c40734b, 0xfd1f522d, 0x7502016b, 0x3d027518, 0x36fd2434, 0x24323224, 0x3424ca02, 0x265683fe, 0x29229a21, + 0x13033f58, 0xdcfd2d50, 0x02213a89, 0x210b8424, 0x3e82ce01, 0xfe304582, 0x421f2332, 0x7575d301, 0x322344fd, 0xf2fd2332, 0x012f0583, 0x293c53fc, + 0xd6d71543, 0x3c294514, 0x82000653, 0x00013f00, 0x03a8fd00, 0x000807e8, 0xb3060002, 0x32010001, 0x0111112b, 0xa8fde803, 0x50fb6009, 0x1f840000, + 0x829c0421, 0x0005271f, 0x05154018, 0x63420202, 0x1223080c, 0x18060210, 0x0133112b, 0xc7012301, 0x2bfcd503, 0x07ce03c7, 0xfb50fb08, 0x00b00450, + 0xfdc80001, 0x86b004a8, 0x0102215b, 0x132b5b82, 0x03c81101, 0x045802e8, 0x82a0f6b0, 0x8614201f, 0x0005261f, 0x03144017, 0x205a8d01, 0x215a8311, + 0x5b830113, 0xd5031428, 0x0332fcc7, 0x3983c7ce, 0x002e5d83, 0x05270101, 0x068a0302, 0x000f000b, 0xba5fb63d, 0xb04b2806, 0x40585029, 0x8201020c, + 0x82612049, 0x011f25dc, 0x11401b4e, 0x6068c482, 0x4059220d, 0x241c820a, 0x260e000f, 0x12d35f03, 0x5184043d, 0x56147e08, 0x145b4847, 0x8653087d, + 0x3a020553, 0x3f1a496c, 0x1a3e3a39, 0x823a6c49, 0xffff3b38, 0xfe052501, 0x07078803, 0x3e070701, 0xfc00feff, 0x00b10800, 0xb0fcb001, 0xd3822b35, + 0x05000030, 0x8bc78300, 0x0f5f8392, 0x0700f53c, 0x32829e07, 0x09db0024, 0x0786782d, 0x15f28128, 0x500918fc, 0x0f826009, 0x02000722, 0x00203184, + 0x072d0583, 0x00a8fd08, 0xf2600900, 0x09b0f615, 0x82178650, 0x25028524, 0xb0043707, 0x0b835000, 0x00200782, 0x1f200386, 0x03a20782, 0x04e8ff23, + 0x210383b0, 0x2f82b400, 0x03967520, 0x17829d20, 0x03822520, 0xf0200787, 0x03a20b82, 0x820b0121, 0x92542027, 0x20478303, 0x204f8604, 0x200782c5, + 0x83038216, 0x20039f07, 0x83278286, 0x82c32003, 0x21038207, 0x07820101, 0xb0047722, 0x03870783, 0x82470021, 0x86392013, 0x8f67835b, 0x82552003, + 0x8303a71b, 0x82d6205f, 0x82c7202f, 0x82572003, 0x8ebd2003, 0x824d2003, 0x2003930f, 0x20178285, 0x2003924a, 0xa7138287, 0x82292003, 0x9207202b, + 0x41352003, 0x2520068b, 0x8420078e, 0x038b0f82, 0x03417520, 0x86552006, 0x421b83a3, 0x7e20071b, 0x03a21382, 0x04f4ff23, 0x210383b0, 0x2f82bf00, + 0x0396b020, 0x17827f20, 0x03827d20, 0x07864220, 0x07829220, 0xb62003a3, 0x78202782, 0x6b830392, 0x17822320, 0xe6200783, 0x039b0782, 0x1f8e5d20, + 0x0f82b720, 0xc8200387, 0x03830b82, 0x6f204783, 0x03930b82, 0x1f833f83, 0xff210382, 0x867386ff, 0x20f3840f, 0xa6138289, 0xf9ff2103, 0x33833f8a, + 0x0f82c920, 0x8b20038b, 0x03930f82, 0x1782b420, 0x03929820, 0x0b9f878b, 0x1e20db83, 0x038f4382, 0x13826420, 0x03927020, 0x20063f43, 0x20078700, + 0x20bb86b0, 0x83a38689, 0x41bc2017, 0xb720065b, 0x42063b41, 0x0783073b, 0x1f82d783, 0x825ef721, 0x82c6201b, 0x04ba2403, 0x444a01b0, 0xbb20066f, + 0xd3820782, 0x210b9343, 0x2f44fdff, 0x8215200e, 0x433d200f, 0xaf2012a3, 0x03831382, 0xc3431f83, 0x86552007, 0x44d62027, 0x6783069b, 0x0b822b20, + 0x17200383, 0x35200782, 0x5d200382, 0x59202386, 0x03830782, 0xab429d20, 0x24ab8306, 0xffb0043b, 0x200f82fe, 0x0607434f, 0x07826b20, 0x6f444b20, + 0x8286200a, 0x82f6201f, 0x4458200f, 0xff200537, 0x1f200b83, 0x14200b82, 0x8306bf43, 0x823e200b, 0x8240200b, 0x82212003, 0x829e2003, 0x441a2003, + 0x32200643, 0x03830782, 0x07820c20, 0x03827b20, 0x03829c20, 0xcb87db87, 0x13824120, 0x1b861320, 0x07827c20, 0xab863620, 0xcf8a4320, 0x8307cb43, + 0x83b383cb, 0x82d387cf, 0xffff21cb, 0x0382a382, 0x86c50021, 0x2113825f, 0x47861d00, 0xff868720, 0xef452620, 0xe8ff2109, 0x20066f41, 0x83078251, + 0x20938703, 0x0a734183, 0x200b0345, 0x064f414b, 0x82075741, 0x0101217b, 0x3b201382, 0x20062744, 0x06674118, 0x07825920, 0x03821220, 0x03822f20, + 0x9b448c20, 0x455c2006, 0x1e2006df, 0x83066742, 0x8202206b, 0x8262200b, 0x450d2003, 0x07200637, 0xa6200782, 0xef20c382, 0x34200782, 0x3c200382, + 0xd6200382, 0x47200f82, 0xe6200382, 0x6a200b82, 0x03200382, 0x8d206b86, 0xd4240782, 0x3001b004, 0x00200389, 0x00200b82, 0x200b5344, 0x2023821f, + 0x0eaf4363, 0x0f82b120, 0x8307f343, 0x424e20cf, 0x3f430ad3, 0x82b02007, 0x437c2013, 0x8b830a0f, 0xd3416420, 0x421b8306, 0x2f83073f, 0xa786f020, + 0x9b867020, 0x1b438420, 0x07074506, 0x20079744, 0x201782b7, 0x20038223, 0x20038267, 0x200b865e, 0x20078231, 0x0623416e, 0x07824220, 0x03825c20, + 0x03822620, 0x03823a20, 0x8b42a020, 0x82892006, 0x85662007, 0xfdff2103, 0xb6200782, 0x20064b43, 0x87db862a, 0x414520cb, 0x37830647, 0x0b82a320, + 0x3520e783, 0x87069343, 0x826820cf, 0x2003830f, 0x06fb4764, 0xd3868a20, 0x0f45c120, 0x42132006, 0x6f200683, 0x20062342, 0x200782ca, 0x061f4148, + 0x2b86c020, 0x13465f20, 0xf4ff2109, 0x4406c345, 0x6f4107fb, 0x44732007, 0x1f870ee3, 0x67448783, 0x419e200b, 0x002005bb, 0x87201383, 0x50203382, + 0x9b830382, 0x07827f20, 0x8b860f20, 0x07829820, 0x3b420420, 0x828c2006, 0x41062007, 0x4b20061b, 0x1c200782, 0x20062341, 0x067f4509, 0x07821e20, + 0xa748c420, 0x20fb8306, 0x200f8280, 0x200f82bc, 0x20038263, 0x200b82e9, 0x067f4660, 0xdf868620, 0x20067f44, 0x20b78300, 0x201382f0, 0x0a0b4784, + 0x3b48c520, 0x27002105, 0x200a2748, 0x06cf4391, 0x97429d20, 0x83002005, 0x474a208f, 0x1320065f, 0x4306fb42, 0x538207f3, 0x82a5ff21, 0x82522077, + 0x827a2003, 0x21c78203, 0x0785eefe, 0x5b830020, 0x2f822520, 0x8f86de20, 0x55204f83, 0x8b200b82, 0x20068f43, 0x20078285, 0x2003822c, 0x200382b9, + 0x20338243, 0x20078503, 0x20238300, 0x060f44c7, 0x27423920, 0x86752006, 0x06c34907, 0x04f6fe24, 0xcb82feb0, 0x8228ff21, 0x82342037, 0x85f3200b, + 0xffff2103, 0x9819e749, 0x82b32033, 0x82932043, 0x8266203f, 0x82682003, 0x82802003, 0x21f38203, 0x178292ff, 0x6020db83, 0x40200782, 0xfb821382, + 0x8215fe21, 0x822d2007, 0x25978203, 0xb004e4fd, 0x1b82e3fd, 0xff853f20, 0xdf820020, 0x2b9fff20, 0x2b828820, 0x3f829020, 0x03829220, 0x03828b20, + 0xfe21eb82, 0x20078261, 0x2003820c, 0x201b820b, 0x0547418d, 0xfb490020, 0xa6ff2106, 0x5e200f82, 0x11201b82, 0x4b207f86, 0x56200782, 0x33201382, + 0x70200382, 0x79200382, 0x24200382, 0x02201382, 0xd7208b82, 0x7f200382, 0x17200f82, 0xee200f82, 0x84090f49, 0x825d2043, 0x82102013, 0x82122003, + 0x824c2003, 0x82572003, 0x822a2003, 0x86292003, 0x4171204b, 0x2b9f05f3, 0x826d0021, 0x46aa2027, 0x6b82063b, 0x82a00021, 0x43d8200b, 0x892006db, + 0x2006b341, 0x200782a2, 0x2027865a, 0x06234a3a, 0xe3821b83, 0x42b30021, 0x0f83066f, 0x0b824820, 0x0382c220, 0xb3423e20, 0x824f2006, 0x4b312007, + 0x1f830e73, 0x33830387, 0x83831f83, 0x7386a020, 0x6344d420, 0x82b52006, 0x82ad2007, 0x86b02003, 0x202b8307, 0x06674287, 0x0782a520, 0x03823820, + 0x03827620, 0x03829520, 0x07469420, 0x86092006, 0x83938313, 0x86b72037, 0x82bf203f, 0x43222007, 0x6b83068b, 0xcb8303df, 0x8c20039b, 0x07d3eb86, + 0xa717e34c, 0x1f0f4a17, 0xbb82b320, 0xc7410383, 0x200bb30b, 0x061b4231, 0x012307d2, 0x83b00484, 0x3c002103, 0x2006e346, 0x0683426a, 0x27452f20, + 0x82722006, 0x82572007, 0x82078303, 0x8d00212b, 0xb2200b82, 0x70200382, 0x2006cb46, 0x20078287, 0x065b428e, 0x5347b920, 0x827e2006, 0x20278307, + 0x06fb4762, 0x0782c620, 0x43868f20, 0x07827820, 0x2f869b20, 0x2f8aaf20, 0x01212b82, 0x208b8222, 0x82038288, 0x230121e7, 0x21200782, 0x33200382, + 0x25200382, 0x3d200382, 0x19200382, 0x23200382, 0x27f40382, 0xfd000023, 0x24af82c9, 0xffb0041d, 0x200382f3, 0x200382e5, 0x200382ab, 0x200382f9, + 0x200382f7, 0x200382d6, 0x2003829f, 0x200382c5, 0x202782b5, 0x20038211, 0x20278609, 0x823386e1, 0xa0012137, 0x9420bf82, 0xad200382, 0x93200382, + 0x2105d745, 0x0b82ca01, 0x00210382, 0x05db46a8, 0x5e202384, 0x21054744, 0x2f474801, 0x82612006, 0x20038307, 0x202b82b0, 0x822786cb, 0x5a002143, + 0x4b0ae74f, 0x0b8f0b97, 0x3f858e20, 0x33820120, 0x82ae0121, 0x21a78243, 0x0782f100, 0x17825320, 0x0782e720, 0x03822420, 0x03826720, 0xb0044124, + 0x13822f02, 0x43497920, 0x8f2fa809, 0x200f8373, 0x205382c2, 0x204b821d, 0x83a7863f, 0x8a462007, 0x866420b3, 0x82278fdf, 0x8600200f, 0x21b3834f, + 0x0b4ad400, 0xd2002105, 0xbf834f82, 0x0021c782, 0x8213829b, 0x6f012103, 0x03831382, 0x07823c20, 0x1385e820, 0x178b0020, 0xfc29ef86, 0xf7b004a7, + 0xfcb004f6, 0x20038244, 0x052f4654, 0x8291fc21, 0x82ac200b, 0x04e0230b, 0x5b82f9b0, 0x8208f921, 0x82bc2007, 0x8243200f, 0x82aa2017, 0x82c52007, + 0x043d240f, 0x823ff8b0, 0x258f820b, 0xb004abfd, 0x0f820afe, 0x1f82ce20, 0x4f821820, 0x17826820, 0x0b825620, 0x0382c020, 0xb0045c24, 0x1382dcfb, + 0x0782c220, 0x0382a520, 0x1382f220, 0x038a2c20, 0x0b827c20, 0x13820383, 0x85b8fb21, 0x83f72017, 0x8251200f, 0x8279200b, 0x82152003, 0x82c9203b, + 0x86e72007, 0x411b8203, 0xff21077b, 0x22d782ec, 0x83b004f4, 0x21038f07, 0x17896400, 0x823a0021, 0x853c2077, 0x73fc2103, 0x2382178a, 0x8930fd21, + 0x600124b3, 0x8201b004, 0xa20121d3, 0x03820782, 0x20076b41, 0x41008400, 0x0c83079f, 0xcb200b82, 0x44200382, 0x81200382, 0xf6200382, 0x46200382, + 0xca200382, 0x20062744, 0x20078274, 0x200382b5, 0x2003828a, 0x20378645, 0x2053824d, 0x200b8268, 0x20078288, 0x200382a0, 0x20038214, 0x06334dff, + 0xdb498f20, 0x482b2006, 0xe82006ff, 0x66201b82, 0x00210385, 0x201382c8, 0x062b448e, 0x0b851f20, 0x86ef0121, 0x85d6203b, 0x82012007, 0x21038347, + 0x63850002, 0x67820120, 0x00200383, 0x64204f87, 0x21055343, 0xbf422c00, 0x4b078306, 0x7820076b, 0xdc201382, 0xf1200382, 0x574b0786, 0x47aa2007, + 0xe78306af, 0x23830383, 0xab4ab220, 0x820b8306, 0xf2ff21c7, 0x200e9f47, 0x830f8285, 0x83af8303, 0x823620ab, 0x82c1200f, 0x86282003, 0x89a6204b, + 0x82ab84af, 0x500021b7, 0x20205386, 0x24200782, 0x69201f82, 0xad200386, 0x83060b41, 0x216f82bb, 0x3b860f01, 0x07850e20, 0x82ab0021, 0x2003831f, + 0x832786a0, 0x073743d3, 0x49200783, 0x83064343, 0x21ab828b, 0x63412b00, 0x82978306, 0x20bb841b, 0x06b3457e, 0x2f447820, 0xe6ff211d, 0x2006c741, + 0x90078525, 0x045a220f, 0x201384b0, 0x201f8227, 0x065b4830, 0xf34c3a20, 0x27078406, 0x87006009, 0xed016009, 0xff216785, 0x82078ab0, 0xb5ff21f3, + 0x1b837f89, 0x82d4ff21, 0x82d4204f, 0x963b2033, 0x93892003, 0x86338217, 0x44002057, 0x13aa1373, 0x04580225, 0x851a04b0, 0x930b8393, 0x4d178c4f, + 0x63830757, 0x96073347, 0x96378407, 0x086f471b, 0x37831f92, 0x7d263b90, 0x1c01b004, 0x3787b004, 0x02230b83, 0x83b00408, 0xf6ff2103, 0x8b05b750, + 0x97178b07, 0x68012123, 0x53433795, 0x931f8b07, 0x836f872b, 0x8b8b871b, 0x8be39b27, 0x8bcb831b, 0x9b37a7db, 0x0b0b4127, 0x2741cf87, 0x87b3830f, + 0x500021af, 0x8b094f44, 0x21338bd7, 0x23854b00, 0x2f973783, 0x37416b8f, 0x245b881b, 0xffb004b5, 0x063748ba, 0xd7418782, 0x8777830f, 0x41778313, + 0xdb8f136b, 0x9f8f0f97, 0x930fc341, 0x848f8ffb, 0x453a20ff, 0x07830667, 0x0b820020, 0x039e9620, 0x210ee742, 0xef551601, 0x07d74b06, 0x0f826420, + 0x9f4fd020, 0x820a2006, 0x043b2407, 0x500301b0, 0x66200623, 0x2006734d, 0x200782cb, 0x20038234, 0x065f4956, 0x27858520, 0x04010224, 0x838302b0, + 0x2745a220, 0x82ab2006, 0x822a2007, 0x852f2003, 0x6400251f, 0xceffb004, 0x2105eb42, 0x13822700, 0x7f45ef20, 0x83002005, 0x8303834b, 0x860b873b, + 0x62ff2107, 0x17207f82, 0x4f202782, 0x01210391, 0x821b8220, 0xe4002103, 0xcc205382, 0xfc201f82, 0x8206d745, 0x60ff2547, 0xe8feb004, 0x07821782, + 0x821e0021, 0x866a2007, 0x829b8383, 0xe7ff2103, 0xc4201382, 0x83061349, 0x833b836b, 0x85242007, 0x06012193, 0xe1200782, 0x1920038a, 0x03870b82, + 0x0b86c520, 0x07826b20, 0x03827a20, 0xa350f520, 0x0bef4406, 0xff21af86, 0x065b46f8, 0x5b476820, 0x1afc2505, 0xa0fdb004, 0xfe2d0385, 0xf8b00441, + 0xf5b004a1, 0xfab004c1, 0x2413820f, 0xfcb00491, 0x068f4874, 0xb004e024, 0x2748c8fb, 0xbbfd2109, 0xfa280f82, 0xaef7b004, 0x15f2b004, 0x5e201782, + 0x12203b82, 0x4c233382, 0x82f9b004, 0xb4f42177, 0xda200f82, 0x36201782, 0x4e200782, 0x8f201f8a, 0xfc210b85, 0x2017825c, 0x820b8210, 0x12f825b3, + 0xe8f6b004, 0x0b834f85, 0x8240fc21, 0x2193820b, 0x1f82a5fc, 0xf721cf82, 0x2007823a, 0x8213823c, 0x6901216b, 0x21056b43, 0xcb486601, 0xecff2105, + 0xfe210785, 0x830f9188, 0x0102211b, 0x8705eb48, 0x07234907, 0x8df40021, 0x5ffc212f, 0xf3825782, 0x07874f87, 0x3d201798, 0x00215785, 0x8a478eed, + 0xbbfd2517, 0xb9fdb004, 0xb382bb82, 0x41fafb21, 0x6b49061f, 0xda00210a, 0x20062b47, 0x207b82b0, 0x2003869e, 0x200782cc, 0x20038205, 0x28038244, + 0xfc00009e, 0xfd00005e, 0x20078224, 0x200382b4, 0x200382bd, 0x2003825c, 0x20038659, 0x20078276, 0x240b86c1, 0xfb000096, 0x211f85f6, 0x07821ffd, + 0x3782d820, 0x07822e20, 0x0382c020, 0x1b824720, 0x4f821b20, 0x03820e20, 0x0382d220, 0x03826a20, 0x03826d20, 0x03820c20, 0x03860920, 0x07822620, + 0x03827120, 0x7b860720, 0x07826e20, 0x03828920, 0x4783f320, 0x21051b41, 0x3b86d301, 0x07826620, 0x3b8a0d20, 0x0b822720, 0x03827220, 0x03820820, + 0x03824520, 0xa5203b83, 0xa5200782, 0x57207b82, 0xd4200382, 0xd0200b82, 0xc7200382, 0xde207386, 0x03870782, 0x0b823420, 0x03823620, 0x03863420, + 0xff860520, 0x0f205f83, 0x64206786, 0xc6200782, 0x4383b386, 0x00000727, 0x00005400, 0x2cef8201, 0xb004e605, 0x8800dafd, 0x02003b01, 0x26008300, + 0x011400c8, 0x83250127, 0x2003840a, 0x8a0582f8, 0x58012103, 0x70203782, 0x88200382, 0xa0200382, 0xb8200382, 0xd0200382, 0xe8230382, 0x82020000, + 0x8202200b, 0x8202200b, 0x7403290b, 0x8c030000, 0x2c040000, 0xc0200382, 0xd8200382, 0xf0240382, 0x04060000, 0x1c200382, 0x34200382, 0x3f820382, + 0x00440725, 0x825c0700, 0x826c2003, 0x82c82003, 0x82e02003, 0x256f8203, 0x00001008, 0x03822808, 0x03824020, 0x08207382, 0x08207382, 0x09207382, + 0x09242b82, 0x0a0000ac, 0x0a201382, 0x0a201382, 0x0a201382, 0x0a204782, 0x0b247b82, 0x0b000008, 0x0b217382, 0x820782a4, 0x680c2543, 0x800c0000, + 0x98200382, 0xb0200382, 0x5f820382, 0x5f820c20, 0x1b820c20, 0x5f820d20, 0x93820d20, 0x93820d20, 0x53820e20, 0xaf820e20, 0x0f820e20, 0x0f820e20, + 0x00280f24, 0x77820f00, 0x63820f20, 0x63820f20, 0x82940f21, 0x00f4230f, 0x23821000, 0x82d41021, 0x00ec2307, 0xc7821100, 0x821c1121, 0x298b8207, + 0x0000c411, 0x00004812, 0x03826012, 0x03827820, 0x03829020, 0x0382a820, 0x1220f782, 0x12205382, 0x13255382, 0x130000cc, 0x240382e4, 0x150000fc, + 0x82038238, 0x241624a3, 0x82160000, 0x48172493, 0x82170000, 0x8217203b, 0x8217203b, 0x4418253b, 0x5c180000, 0x6f820382, 0x5f821920, 0x5f821920, + 0x00dc1924, 0x1b821b00, 0x7f821b20, 0x00401c25, 0x82581c00, 0x20578203, 0x25f3821d, 0x0000641d, 0x03827c1d, 0x1d20a782, 0x1d202f82, 0x1d202f82, + 0x1d202f82, 0x1e24b382, 0x1e00000c, 0x1e206382, 0x1e20f782, 0x1f20f782, 0x1f205b82, 0x1f209b82, 0x1f209b82, 0x1f209b82, 0x20204382, 0x20254382, + 0x20000068, 0x820382bc, 0x8220205f, 0x822120df, 0x822120df, 0x782124df, 0x82210000, 0x82212077, 0x82212033, 0x82212033, 0x82212033, 0x82222033, + 0x20222433, 0x82220000, 0x820388cb, 0x142325db, 0x2c230000, 0x67820382, 0xc3822320, 0x82742321, 0x008c240b, 0x82842400, 0x829c2003, 0x00b42303, + 0x9b822500, 0x9b822520, 0x00d02624, 0xc7822700, 0xbb822720, 0x00a02724, 0x83822800, 0x2b822820, 0x00b02829, 0x00702900, 0x82342a00, 0x201f8203, + 0x2043822b, 0x206b822c, 0x246b822c, 0x0000502c, 0x2127822c, 0x0782802c, 0x03829820, 0x0000b023, 0x20df822c, 0x20df822c, 0x20b7822d, 0x2013822e, + 0x28b38230, 0x00009030, 0x0000a830, 0x20138232, 0x20cb8233, 0x244f8233, 0x00003034, 0x253f8234, 0x00000035, 0x03824c35, 0x03826420, 0x35217b82, + 0x20078294, 0x200382ac, 0x820382c4, 0x8236209b, 0xf836244b, 0x82380000, 0x823820c7, 0xe83824c7, 0x82390000, 0x8239207b, 0x8239203b, 0xc0392453, + 0x823a0000, 0x9c3a21e7, 0x0b830782, 0x0782e420, 0x3b20fb82, 0x3b20a382, 0x3c254382, 0x3d000088, 0x8203821c, 0x543e25bf, 0x6c3e0000, 0xff820382, + 0x00283f25, 0x82403f00, 0x20238203, 0x2567823f, 0x0000f43f, 0x03820c40, 0x03822420, 0x03823c20, 0x40202b82, 0x41202b82, 0x41206b82, 0x41206b82, + 0x4220e782, 0x43200382, 0x43284782, 0x440000d8, 0x450000a4, 0x4520a782, 0x45203f82, 0x45203f82, 0x46203f82, 0x46208f82, 0x46208382, 0x48241f82, + 0x48000008, 0x48208382, 0x49243f82, 0x49000078, 0x4a291f82, 0x4a000090, 0x4b0000b4, 0x240382b8, 0x4c0000d0, 0x20038258, 0x82038270, 0xa04c21a3, + 0x17820782, 0x17834c20, 0x0000e824, 0x0382004d, 0x0382cc20, 0x4d24cf82, 0x4e0000fc, 0x4e20ab82, 0x4e206f82, 0x4e206f82, 0x4e206f82, 0x4f204f82, + 0x4f20af82, 0x4f259382, 0x4f0000c8, 0x240382e0, 0x500000f8, 0x82038210, 0x825020db, 0x9c5021e3, 0x6f820b82, 0x47825020, 0x00f05024, 0x93825100, + 0x93825120, 0x93825120, 0xd3825120, 0x00985125, 0x821c5200, 0x20cb8203, 0x8c4b8253, 0x00d42303, 0x33825300, 0x00bc5424, 0x1f825500, 0x7f825620, + 0x63825620, 0x13825620, 0x00745724, 0x5f825700, 0xeb825720, 0xeb825720, 0x002c5824, 0x27825800, 0x67825820, 0xaf825820, 0xaf825820, 0x1f825920, + 0x004c5a24, 0xb3825a00, 0xb3825a20, 0x00dc5a24, 0x8f825b00, 0x00045c24, 0x73825c00, 0x828c5c21, 0x820f8307, 0x825c201f, 0x825c203b, 0x825d2033, + 0x825d2083, 0x825d201b, 0x905d294f, 0xa85d0000, 0x5c5e0000, 0x6c200382, 0x67820382, 0x00345f24, 0x57825f00, 0x00ec5f25, 0x82446000, 0x20378203, + 0x20078261, 0x24778261, 0x00007062, 0x20438262, 0x20438263, 0x25f38263, 0x00005864, 0x03826864, 0x03828020, 0x65204b82, 0x66245782, 0x66000000, + 0x67207782, 0x67205f82, 0x68204382, 0x69200b82, 0x6a246382, 0x6a000008, 0x6b205782, 0x6b203b82, 0x6c200f82, 0x6c20df82, 0x6c250f82, 0x6d000094, + 0x82038220, 0x836e2063, 0x201b8203, 0x2557826f, 0x0000f06f, 0x03824071, 0x7224bb82, 0x72000030, 0x73246f82, 0x73000024, 0x73246782, 0x740000f4, + 0x75201782, 0x75205382, 0x76248f82, 0x770000c8, 0x77201b82, 0x7724bb82, 0x78000098, 0x78216382, 0x8207827c, 0x8279201b, 0x827a2037, 0x827a208b, + 0x827b202f, 0xc47c256f, 0xd47c0000, 0x9b820382, 0xb7827d20, 0x23827d20, 0x007c7e24, 0x0f827e00, 0x006c7f24, 0x0f827f00, 0x00148024, 0x33828000, + 0x823c8021, 0x82542007, 0x00f82403, 0x82188100, 0x21878203, 0x07824881, 0x82242b82, 0x82000004, 0x8220ef82, 0x82217382, 0x820b82d8, 0x828320af, + 0x8283208f, 0x388325cb, 0x50830000, 0x68200382, 0xbc200382, 0x6f820382, 0xef828420, 0x00108524, 0xbf828500, 0x27828620, 0x00cc8624, 0x5b828800, + 0x00dc8824, 0x97828900, 0x004c8a25, 0x825c8a00, 0x250f8203, 0x0000a08b, 0x0382288c, 0x0000b823, 0x2047828d, 0x2093828d, 0x20d3828e, 0x246f828e, + 0x00009c8e, 0x204b828f, 0x209b8290, 0x242b8290, 0x00008891, 0x284f8292, 0x0000e892, 0x0000b493, 0x25a38294, 0x00004094, 0x03820095, 0x95203f82, + 0x9620bb82, 0x96247782, 0x96000064, 0x9620b782, 0x97204b82, 0x9720df82, 0x9725df82, 0x980000ac, 0x20038270, 0x820382d0, 0x8299203f, 0x82992033, + 0x829a2023, 0x829a208b, 0x829a202f, 0x829b20a3, 0x829b207f, 0xb09b248f, 0x829b0000, 0x217e82e3, 0x4f829c00, 0xbb829c20, 0x23829c20, 0x007c9c24, + 0x03839d00, 0x00008c23, 0x203f829e, 0x20c3829e, 0x2057829e, 0x2463829f, 0x00006c9f, 0x2457829f, 0x000068a0, 0x253b82a0, 0x00009ca1, 0x038234a2, + 0x03824420, 0xa3201782, 0xa3203382, 0xa3201382, 0xa328b782, 0xa30000c4, 0xa40000d4, 0xa5200b82, 0xa620db82, 0xa620ef82, 0xa620ef82, 0xa7241382, + 0xa80000e4, 0xa8253382, 0xa90000c0, 0x82038248, 0xa8aa243b, 0x82aa0000, 0xc8aa24df, 0x82ab0000, 0x82ab202f, 0x83ac208f, 0x243f8203, 0x000060ad, + 0x20f782ad, 0x201782af, 0x242782af, 0x000028b0, 0x201782b0, 0x280782b1, 0x000094b1, 0x0000f4b1, 0x24d782b2, 0x000008b3, 0x244b82b3, 0x0000a4b4, + 0x20bb82b5, 0x205b82b5, 0x28e782b5, 0x000020b6, 0x000090b6, 0x20e782b7, 0x209f82b7, 0x200782b8, 0x200f82b8, 0x245782b9, 0x000098ba, 0x205382ba, + 0x208b82ba, 0x256f82bb, 0x0000ccbb, 0x03824cbc, 0x0000bc23, 0x206f82bd, 0x218f82bd, 0x0b82e0bd, 0xbe207f82, 0xbe205f82, 0xbe204b82, 0xbe201382, + 0xbe201382, 0xbf201382, 0xbf204b82, 0xbf208b82, 0xbf203782, 0xbf25d782, 0xc00000fc, 0x820382a0, 0xd0c021cb, 0x8f820782, 0x8b82c120, 0x0018c125, + 0x8230c100, 0x82842003, 0x24838203, 0x000038c2, 0x204382c2, 0x248382c3, 0x000070c3, 0x207382c4, 0x254f82c4, 0x00007cc5, 0x03821cc6, 0xc7201b82, + 0xc8202b82, 0xc9287382, 0xc9000004, 0xca000088, 0xcb206b82, 0xcc241b82, 0xcc0000ac, 0xcc209f82, 0xcd207382, 0xce203782, 0xce201382, 0xcf207b82, + 0xd0243b82, 0xd1000080, 0xd1243382, 0xd20000dc, 0xd3206782, 0xd3203382, 0xd320b382, 0xd3257b82, 0xd3000040, 0x82038250, 0x82d3203b, 0x82d3203b, + 0xecd32523, 0x8cd40000, 0x2b820382, 0x5782d420, 0x3b82d520, 0xab82d520, 0x0028d525, 0x82b0d500, 0x82c02003, 0x20c78203, 0x258f82d5, 0x000064d6, + 0x038274d6, 0xd7259782, 0xd7000058, 0x23038268, 0xd80000f4, 0xd820ff82, 0xd8204f82, 0xd8208382, 0xd925ff82, 0xd9000014, 0x2003822c, 0x20038244, + 0x8203825c, 0x82d92033, 0x82d92063, 0x82da202b, 0x82da20eb, 0x3cdb24a3, 0x82db0000, 0x82dc205b, 0xc8dc288f, 0x48dd0000, 0x82de0000, 0x82de20e7, + 0x82de2047, 0x82de2047, 0xa4df2447, 0x82df0000, 0x82e0205b, 0x82e0201b, 0x82e0206f, 0x82e120ab, 0x82e2200f, 0xa0e225e7, 0xc4e20000, 0xe8240382, + 0x0ce30000, 0xdf820382, 0x8254e321, 0x82782007, 0x20cb8203, 0x202782e3, 0x204b82e3, 0x204b82e3, 0x204b82e3, 0x209382e4, 0x209382e4, 0x209382e4, + 0x209382e4, 0x209382e4, 0x209382e4, 0x256382e4, 0x0000bce4, 0x0382d4e4, 0x0000f824, 0x03821ce5, 0x03824020, 0xe521eb82, 0x20078288, 0x820382ac, + 0xdce52567, 0x00e60000, 0x24200382, 0x8f820382, 0x826ce621, 0x82902007, 0x21678203, 0x0782d8e6, 0xe7206382, 0xe7206382, 0xe7206382, 0xe7206382, + 0xe7206382, 0xe7206382, 0xe7206382, 0xe7206382, 0xe7206382, 0xe7206382, 0xe820c382, 0xe825e782, 0xe8000028, 0x2003824c, 0x20038270, 0x20038294, + 0x820382b8, 0x82e92063, 0x82e92063, 0x3ce92463, 0x82e90000, 0x82e920cf, 0x84e92167, 0xa8200b82, 0xcf820382, 0x00f0e924, 0x6782ea00, 0x8238ea21, + 0x20638207, 0x206382ea, 0x216382ea, 0x0f82b0ea, 0xea205f82, 0xeb20c382, 0xeb20c382, 0xeb24c382, 0xeb000058, 0xeb205f82, 0xeb21c782, 0x820b82a0, + 0xe8eb25c7, 0x0cec0000, 0x30200382, 0x5f820382, 0x8278ec21, 0x829c2007, 0x82c02003, 0x20c78203, 0x255f82ec, 0x000008ed, 0x038220ed, 0xed216382, + 0x20078250, 0x20038268, 0x20038280, 0x82038298, 0xc8ed2467, 0x82ee0000, 0x82ef208f, 0x82ef207b, 0x82f0200b, 0x82f1207f, 0x82f2204b, 0xb4f22557, + 0x64f30000, 0xd0230382, 0x82f40000, 0x82f42007, 0x82f42053, 0x82f52073, 0x82f620eb, 0x2cf62497, 0x82f60000, 0x60f72833, 0xfcf70000, 0x82f80000, + 0x82f9204f, 0x82f9208b, 0x82fa209f, 0xbcfa2467, 0x82fb0000, 0xe0fb2177, 0xcb820782, 0x0010fc25, 0x8228fc00, 0x20cf8203, 0x20cf82fc, 0x20cf82fc, + 0x20cf82fc, 0x212f82fc, 0x1782b8fc, 0xfc206782, 0xfd205f82, 0xfd206b82, 0xfe20df82, 0xfe206782, 0xff257382, 0x00010094, 0x24038254, 0x010100e0, + 0x82038260, 0x40023107, 0xcc020100, 0x74030100, 0x5c040100, 0x28050100, 0xe4280382, 0xb0060100, 0x1c070100, 0xd4230382, 0x82080100, 0x6c082117, + 0x7c200782, 0x8c240382, 0x18090100, 0x33820382, 0x27820920, 0x00fc0925, 0x82140a01, 0x822c2003, 0x82442003, 0x202b8203, 0x204b820a, 0x2127820a, + 0x0f82a40a, 0x0382bc20, 0x0a254382, 0x0b0100ec, 0x82038204, 0x3c0b2153, 0x27820782, 0x4f820b20, 0x829c0b21, 0x2123820b, 0x0782dc0b, 0x0c204b82, + 0x0c201f82, 0x0c201f82, 0x0c201f82, 0x0c201f82, 0x0c25b382, 0x0c0100ac, 0x820382c4, 0xf40c2523, 0x0c0d0100, 0x24200382, 0x27820382, 0xcf820d20, + 0x9b820d20, 0x82840d21, 0x214b820f, 0x0782b40d, 0x0d209b82, 0x0d209b82, 0x0e204f82, 0x0e209b82, 0x0e209b82, 0x0e209b82, 0x0e205382, 0x0e205382, + 0x0e202782, 0x0e207382, 0x0e204f82, 0x0f202382, 0x0f207382, 0x0f204b82, 0x0f201f82, 0x0f201f82, 0x0f201f82, 0x0f201f82, 0x0f20b782, 0x1020b782, + 0x1020b782, 0x10252382, 0x10010034, 0x2003824c, 0x82038264, 0x82102027, 0x8210209b, 0x8210209b, 0x8210209b, 0x8210204b, 0x8212209b, 0x1813242b, + 0x82130100, 0x82132027, 0x82132027, 0x82132027, 0x82132027, 0x82132027, 0x82132027, 0x82132027, 0x82142027, 0x821420c3, 0x821420c3, 0x82142077, + 0x821420c3, 0x821420c3, 0x821420c3, 0x8214207b, 0x821420c3, 0x821420c3, 0x821420c3, 0x8215209f, 0x821520c3, 0x821520c3, 0x821520c3, 0x741529a3, + 0x88160100, 0xa0170100, 0xa3820382, 0xa3821720, 0x77821820, 0xa3821820, 0xa3821820, 0x7b821820, 0x7b821820, 0x7b821820, 0x7b821820, 0x7b821820, + 0x7b821820, 0x7b821820, 0x7b821820, 0x4f821920, 0x27821920, 0x77821920, 0x4b821920, 0x23821920, 0x73821920, 0x4b821920, 0x1f821920, 0x1f821a20, + 0x1f821a20, 0x1f821a20, 0x00681a24, 0x47821a01, 0x43821a20, 0x3f821a20, 0x07821b20, 0x00481c28, 0x00d81c01, 0x67821d01, 0x00f81d29, 0x00c01e01, + 0x82701f01, 0x00e82303, 0x4b822001, 0x00f02024, 0x33822101, 0xaf822220, 0x00b02224, 0xb3822301, 0x00202424, 0x4b822401, 0x00382524, 0x27822501, + 0x00a42624, 0x5f822701, 0x00182824, 0x83822801, 0x00002924, 0x47822901, 0x00302a24, 0x67822a01, 0xdb822b20, 0xd7822b20, 0x00bc2c24, 0x5b822d01, + 0x8f822e20, 0x2f822e20, 0x2b822e20, 0x63822e20, 0xaf822e20, 0xaf822e20, 0xaf822e20, 0xaf822f20, 0x1f822f20, 0x1f822f20, 0x1f822f20, 0x5f822f20, + 0x00283024, 0x63823001, 0x7b823120, 0x57823120, 0x00883225, 0x823c3301, 0x20078203, 0x20bf8234, 0x255b8234, 0x01000c35, 0x03822c35, 0x3521c782, + 0x2007826c, 0x8203828c, 0xcc3521df, 0x1f820782, 0x1f823620, 0x1f823620, 0x1f823620, 0x1f823620, 0x1f823620, 0x1f823620, 0x1f823620, 0x1f823620, + 0x1f823720, 0x1f823720, 0x1f823720, 0x1f823720, 0x97823720, 0xfb823720, 0x00b83824, 0x9f823901, 0xd3823c20, 0x07823c20, 0x00e43d28, 0x00f83e01, + 0x27824101, 0x00604424, 0x97824501, 0x009c4628, 0x00384801, 0x03824901, 0x47824c20, 0x00a84d25, 0x82b04e01, 0x00fc2303, 0x23824f01, 0x3b825020, + 0x00c45024, 0xfb825101, 0x00dc5124, 0x5f825201, 0x2b825320, 0x17825420, 0x00205425, 0x82785401, 0x82d82003, 0x20ff8203, 0x20378255, 0x200b8255, + 0x201b8256, 0x20db8256, 0x247f8256, 0x01008057, 0x20638257, 0xa30b8357, 0x00e02403, 0x82085801, 0x82902003, 0x244f8203, 0x0100d058, 0x20678259, + 0x207f8259, 0x2077825a, 0x2567825a, 0x01003c5b, 0x0382885b, 0x5c259782, 0x5c010004, 0x20038244, 0x82038284, 0x835c20cf, 0x20438213, 0x25bf825c, + 0x0100185d, 0x0382345d, 0x03825020, 0x5d21b782, 0x2007827c, 0x2003968c, 0x821782c0, 0x285e255b, 0x5c5e0100, 0xd7820382, 0x82ac5e21, 0x82bc2007, + 0x00cc2303, 0x93825f01, 0x82585f21, 0x82742007, 0x209b8203, 0x211b825f, 0x0b82c85f, 0x0389e420, 0x97826020, 0x13826020, 0x27826120, 0x7f826120, + 0x00546224, 0x57826201, 0x00106325, 0x82646301, 0x82942003, 0x201f8203, 0x20638264, 0x20cf8264, 0x248b8264, 0x0100a864, 0x20b38264, 0x20b38264, + 0x20178265, 0x25178265, 0x0100b865, 0x03821466, 0x67200782, 0x6720e782, 0x68256382, 0x690100d4, 0x82038248, 0x82692047, 0x826a2013, 0x826a20d7, + 0x826b20d7, 0x826c2063, 0x246c249b, 0x826c0100, 0x826d201f, 0x826e201f, 0x826e20f7, 0x826e201f, 0x826f201f, 0x826f2093, 0xa4702473, 0x82710100, + 0x82722003, 0x82732097, 0x82742003, 0x4474245f, 0x82740100, 0xf07430db, 0xec750100, 0x4c770100, 0x40780100, 0x82790100, 0x827a2003, 0x827b2037, + 0x827d2013, 0x827e2023, 0x1c7f24bf, 0x827f0100, 0x807f2117, 0x98200782, 0xbc240382, 0x00800100, 0x33820382, 0x007c8125, 0x829c8101, 0x20138203, + 0x204b8281, 0x248b8282, 0x01006082, 0x20838283, 0x280f8283, 0x0100b084, 0x01007485, 0x250f8286, 0x0100a086, 0x03822c87, 0x88204382, 0x8824a782, + 0x890100c0, 0x89205782, 0x89211f82, 0x230b82a8, 0x8b0100dc, 0x8b255782, 0x8c010090, 0x82038270, 0xd08c212f, 0xe0200782, 0x4b820382, 0x039a8c20, + 0x00848d2d, 0x006c8e01, 0x00388f01, 0x82049001, 0x00d82303, 0x67829101, 0x6f829220, 0x43829220, 0xa7829320, 0x00209425, 0x85ac9401, 0x82952003, + 0x8295202f, 0x82962017, 0x829620bb, 0x30972413, 0x82970100, 0x6897218b, 0xe8240782, 0x58980100, 0xc8240382, 0x50990100, 0xd4200382, 0xf4240382, + 0x149a0100, 0xab820382, 0x5b829a20, 0xcf829b20, 0x00949b24, 0x17829b01, 0x005c9c29, 0x00a49c01, 0x821c9d01, 0x82642003, 0x21238203, 0x0782b49d, + 0x9e201b82, 0x9e203382, 0x9e202b82, 0x9f208b82, 0xa0204b82, 0xa0202382, 0xa1245f82, 0xa20100bc, 0xa324e782, 0xa301003c, 0xa4200f82, 0xa5201f82, + 0xa5200b82, 0xa5205382, 0xa6207782, 0xa620c382, 0xa6254382, 0xa70100fc, 0x20038280, 0x230382b0, 0xa80100e4, 0xa820a382, 0xa920b382, 0xaa20af82, + 0xaa20db82, 0xab2c2b82, 0xab010008, 0xac010054, 0xad010038, 0xad206f82, 0xad24bb82, 0xae0100a4, 0xae200b82, 0xaf20e782, 0xaf250782, 0xaf010024, + 0x82038278, 0x82b0206b, 0x82b02043, 0x82b120fb, 0xacb12857, 0xf0b10100, 0x82b20100, 0x82b220a3, 0x82b220fb, 0x82b2200f, 0x82b3200f, 0x70b52477, + 0x82b50100, 0x82b520a3, 0xc0b5257b, 0x48b60100, 0xcc230382, 0x82b70100, 0x82b72077, 0xecb724e3, 0x82b80100, 0x82b82037, 0x82b82037, 0xf8b82523, + 0x44b90100, 0x0b820382, 0x1382ba20, 0x4782ba20, 0x005cbb24, 0x9f82bc01, 0xfb82bc20, 0x00a0bc29, 0x004cbd01, 0x821cbe01, 0x82882003, 0x203f8203, + 0x201782bf, 0x241782bf, 0x0100bcbf, 0x200f82bf, 0x201b82c0, 0x9cc782c0, 0x20938203, 0x24ff82c1, 0x01009cc1, 0x202b82c2, 0x200f82c2, 0x208782c3, + 0x244782c3, 0x01003cc4, 0x20a382c4, 0x24e382c5, 0x0100a4c5, 0x254f82c6, 0x0100a8c6, 0x038204c7, 0x03826020, 0xc8246782, 0xc8010018, 0xc9280782, + 0xc9010058, 0xca0100d8, 0xca240782, 0xcb0100e8, 0xcb20ef82, 0xcd204382, 0xcd202782, 0xce243382, 0xce010000, 0xce24bf82, 0xcf0100d0, 0xd020d782, + 0xd0201782, 0xd1205b82, 0xd1257382, 0xd20100d4, 0x82038264, 0xacd324b3, 0x82d40100, 0xb4d4248f, 0x82d50100, 0x82d62023, 0x82d6206b, 0x82d7203f, + 0x82d72007, 0x82d7202b, 0x82d72027, 0x82d720a3, 0x82d72073, 0x14d82467, 0x82d80100, 0x6cd8219f, 0x98200782, 0x53820382, 0x00f8d825, 0x8224d901, + 0x82502003, 0x827c2003, 0x203f8203, 0x206382d9, 0x208382da, 0x205b82da, 0x258782da, 0x010088da, 0x0382b8da, 0x0100e423, 0x20d782db, 0x206b82db, + 0x203f82db, 0x209f82db, 0x282782dc, 0x010048dc, 0x010084dc, 0x283b82de, 0x0100d4e2, 0x0100e0e4, 0x243b82e5, 0x0100c4e5, 0x20e382e6, 0x281382e6, + 0x010054e7, 0x0100dce7, 0x219382e8, 0x07829ce8, 0xe9201382, 0xe9247382, 0xea0100fc, 0xeb24bf82, 0xec010068, 0xec209f82, 0xed206382, 0xee200382, + 0xef245f82, 0xef010018, 0x23820783, 0x7382f020, 0x5f82f020, 0x00f0f024, 0xc382f101, 0x828cf121, 0x20378207, 0x240f82f1, 0x01004cf2, 0x20bb82f2, + 0x201f82f2, 0x202b82f2, 0x205782f3, 0x20f782f3, 0x249f82f3, 0x010010f4, 0x210f82f4, 0x0782acf4, 0x0100f424, 0x03823cf5, 0xf520cf82, 0xf6257f82, + 0xf6010008, 0x20038234, 0x82038294, 0x82f72047, 0x82f7201b, 0x82f82037, 0x82f82017, 0xa4f825d3, 0x04f90100, 0xbb820382, 0x5b82f920, 0x1782fa20, + 0xbf82fa20, 0xd782fa20, 0x0024fb24, 0x3782fb01, 0x1f82fc20, 0x0078fc29, 0x00c0fc01, 0x825cfd01, 0x00bc2303, 0xc782fe01, 0x8270fe21, 0x20278207, + 0x200b82ff, 0x25db82ff, 0x0200bcff, 0x03820800, 0x03828020, 0x0200fc24, 0x03822801, 0x02007c24, 0x03821002, 0x03201382, 0x03290782, 0x04020090, + 0x05020098, 0x82038230, 0xd806242f, 0x82070200, 0x5c072133, 0xb0240782, 0x04080200, 0x58200382, 0xa4240382, 0x14090200, 0x2f820382, 0x000c0a28, + 0x008c0a02, 0x27820b02, 0x82380b21, 0x82482007, 0x82742003, 0x82842003, 0x21278203, 0x0782c40b, 0x0200ec24, 0x03821c0c, 0x03824c20, 0x03827820, + 0x0200c024, 0x0382000d, 0x03825420, 0x03829420, 0x0200e824, 0x0382440e, 0x0e254782, 0x0f0200cc, 0x20038220, 0x23038260, 0x100200b4, 0x10209782, + 0x10217382, 0x240b82a0, 0x110200d0, 0x82038218, 0x8211200f, 0x821120a7, 0x8212202b, 0x82122047, 0xc8122573, 0x64130200, 0x17820382, 0x00f01325, + 0x826c1402, 0x829c2003, 0x205b8203, 0x25eb8215, 0x02006815, 0x0382a815, 0x1620d382, 0x1620a782, 0x16209f82, 0x17204f82, 0x17200b82, 0x17257782, + 0x180200e0, 0x82038240, 0xec18253f, 0x50190200, 0xb8230382, 0x821a0200, 0x241a215f, 0xbb820782, 0xab821a20, 0x3f821a20, 0x00041b24, 0x37821b02, + 0x82801b21, 0x00f82407, 0x82901c02, 0x20e78203, 0x209b821d, 0x204b821d, 0x2037821d, 0x2017821d, 0x20c3821e, 0x24c3821e, 0x0200081f, 0x257f821f, + 0x0200bc1f, 0x03821020, 0x03827420, 0x0200dc23, 0x20438221, 0x25438221, 0x0200d421, 0x03821422, 0x22202382, 0x2320a382, 0x23205f82, 0x23206f82, + 0x2320f382, 0x24259782, 0x24020034, 0x82038274, 0x1c2524af, 0x82250200, 0x82252027, 0x8226206f, 0x5c26244b, 0x82260200, 0x82272063, 0x8227200b, + 0x82272017, 0x18282d17, 0xb0280200, 0x3c290200, 0x782b0200, 0xb3820382, 0x4f822c20, 0x00c02c25, 0x82482d02, 0x28878203, 0x0200442e, 0x0200cc2e, + 0x2433822f, 0x02009c30, 0x205b8231, 0x20038232, 0x208b8233, 0x20078234, 0x24c38235, 0x02004036, 0x21bb8237, 0x07827037, 0x03829820, 0x0200e827, + 0x0200ec3b, 0x2443823c, 0x02000c3f, 0x82038340, 0x82412013, 0x8242205b, 0x54432413, 0x82440200, 0xfc44248f, 0x82450200, 0x8246202f, 0x9446245b, + 0x82460200, 0x824720eb, 0x82482007, 0x8248202f, 0x8249208b, 0x824a201b, 0x824b2083, 0x824c2077, 0x824c20eb, 0x7c4d2873, 0x60510200, 0x82550200, + 0x6c5524b3, 0x82560200, 0x825620e7, 0x8257209f, 0xe45b240f, 0x825f0200, 0x826420d7, 0x8268205f, 0x826a2017, 0x306b24d3, 0x826b0200, 0x8c6e2417, + 0x826f0200, 0x8272209f, 0xa87625cf, 0x38790200, 0xfb820382, 0x5f827a20, 0xab827b20, 0x53827c20, 0x0b827c20, 0x00807d25, 0x82187e02, 0x20238203, + 0x2023827f, 0x2087827f, 0x207b8282, 0x203b8282, 0x20e38283, 0x20938283, 0x24c78285, 0x02000086, 0x207f8286, 0x28fb8287, 0x0200b487, 0x0200f489, + 0x20c7828a, 0x2c7f828a, 0x0200888d, 0x0200e08f, 0x0200c090, 0x28138293, 0x02006496, 0x02001099, 0x204f829c, 0x2543829d, 0x0200909f, 0x038258a0, + 0xa3259782, 0xa302002c, 0x20038da4, 0x20a382a5, 0x20d382a6, 0x202b82a8, 0x202782a8, 0x20bb82a8, 0x208782a8, 0x206b82aa, 0x259b82ab, 0x020084ab, + 0x0382a0ab, 0xac245f82, 0xad020074, 0xad245b82, 0xae020094, 0xaf205782, 0xaf203382, 0xb0294f82, 0xb0020050, 0xb102009c, 0x82038220, 0xb8b12583, + 0x28b20200, 0xf8230382, 0x82b30200, 0x30b4243f, 0x82b40200, 0x5cb525b7, 0x24b60200, 0x4f820382, 0x2f82b720, 0x00b0b829, 0x0060b902, 0x8234ba02, + 0x827c2003, 0x20638203, 0x207382bb, 0x245b82bb, 0x0200ecbc, 0x246b82bd, 0x020070bf, 0x242782bf, 0x02000cc0, 0x200782c0, 0x24c382c2, 0x020078c3, + 0x20ab82c4, 0x205382c6, 0x253b82c7, 0x02004cc7, 0x03826cc7, 0xc724bb82, 0xc80200ac, 0xc824d382, 0xc90200c8, 0xc920c382, 0xca202382, 0xca209782, + 0xca255f82, 0xcb0200e0, 0x8203823c, 0x04cc257f, 0x54cc0200, 0x0b830382, 0x0200f023, 0x211782cd, 0x078288cd, 0x0200d423, 0x20df82ce, 0x243b82cf, + 0x0200e4cf, 0x247f82d0, 0x0200d8d0, 0x20a782d1, 0x25cf82d1, 0x020074d2, 0x038200d3, 0xd3248382, 0xd40200d0, 0xd5203782, 0xd5209b82, 0xd620f382, + 0xd6248782, 0xd70200fc, 0xd7208b82, 0xd8200782, 0xd920e382, 0xd920cf82, 0xda20cf82, 0xda20f782, 0xda208382, 0xdb206b82, 0xdb242782, 0xdc0200a8, + 0xdd207b82, 0xde201b82, 0xdf200782, 0xe024b782, 0xe002001c, 0xe120af82, 0xe1205382, 0xe1208782, 0xe1247f82, 0xe20200f4, 0xe221bf82, 0x82078284, + 0x82e22027, 0x82e32013, 0x2ce32453, 0x82e30200, 0x82e32047, 0x82e3209f, 0x82e320af, 0x82e32037, 0x82e4209f, 0xa4e4253b, 0xc4e40200, 0xb7820382, + 0x1382e420, 0x0038e524, 0x2782e502, 0x6b82e520, 0x4f82e520, 0x0058e624, 0xbf82e602, 0xb382e620, 0x1f82e620, 0x0b82e720, 0x00cce724, 0x9b82e702, + 0x0014e824, 0x5782e802, 0x828ce821, 0x20138207, 0x253b82e9, 0x0200c8e9, 0x03825cea, 0xeb207f82, 0xeb248b82, 0xeb020088, 0xeb21af82, 0x820782bc, + 0x82eb2063, 0x82ec2053, 0x82ec2093, 0x82ec207b, 0x82ec205b, 0xd0ec258f, 0x34ed0200, 0x50200382, 0x6c200382, 0x33820382, 0x8298ed21, 0x82c02007, + 0x82e82003, 0x20778203, 0x201382ee, 0x204782ee, 0x202b82ee, 0x202382ef, 0x207382ef, 0x240f82ef, 0x020010f0, 0x240b82f0, 0x020008f1, 0x24f782f1, + 0x020000f2, 0x208382f2, 0x245782f3, 0x020030f4, 0x249782f4, 0x0200fcf4, 0x202782f5, 0x216382f5, 0x0b8248f5, 0xf5207782, 0xfc314382, 0xff02007c, + 0x00030084, 0x090300a4, 0x0a030088, 0x2403821c, 0x0b0300ac, 0x240382d4, 0x0c0300f4, 0x20038230, 0x24038250, 0x0d03008c, 0x20038208, 0x3a038424, + 0x07000001, 0x00cb0141, 0x00780060, 0x0102000a, 0x00580280, 0x0200008d, 0x82150ebb, 0x0004274b, 0x01260000, 0x258200ce, 0x00220982, 0x05825600, + 0x01220b85, 0x0d820900, 0x02240b85, 0x5f000600, 0x03242386, 0x65001a00, 0x04240b86, 0x7f001000, 0x05240b86, 0x8f000d00, 0x06240b86, 0x9c000f00, + 0x07240b86, 0xab003400, 0x08240b86, 0xdf003600, 0x09240b86, 0x15013600, 0x0b240b86, 0x4b011100, 0x0c200b86, 0x5c200b82, 0x0d240b86, 0x6d019000, + 0x0e240b86, 0xfd011a00, 0x0122b182, 0xa3820904, 0x1702ac22, 0x01240b86, 0xc3022000, 0x02240b86, 0xe3020e00, 0x03240b86, 0xf1023400, 0x04240b86, + 0x25032000, 0x05240b86, 0x45031a00, 0x06240b86, 0x5f031e00, 0x07240b86, 0x7d036800, 0x08240b86, 0xe5036c00, 0x09240b86, 0x51046c00, 0x0b240b86, + 0xbd042200, 0x0c200b86, 0xdf200b82, 0x0d240b86, 0x01052001, 0x0e240b86, 0x21063400, 0x10240b86, 0x55061200, 0x11240b86, 0x67060c00, 0x01250b85, + 0x062c0000, 0x240b8673, 0x06540001, 0x240b869f, 0x062a0002, 0x240b86f3, 0x072e0003, 0x240b861d, 0x07260004, 0x240b864b, 0x071c0005, 0x200b8671, + 0x20238206, 0x080b868d, 0x38000751, 0x6f43bb07, 0x69727970, 0x20746867, 0x34313032, 0x3230322d, 0x68542030, 0x69462065, 0x43206172, 0x2065646f, + 0x6a6f7250, 0x20746365, 0x68747541, 0x2073726f, 0x74746828, 0x2f3a7370, 0x7469672f, 0x2e627568, 0x2f6d6f63, 0x736e6f74, 0x832f796b, 0x20338334, + 0x303d8829, 0x69746552, 0x2e35616e, 0x3b323030, 0x42445443, 0x2022873b, 0x8819852d, 0x85202028, 0x6556270f, 0x6f697372, 0x3184206e, 0x4d352b93, + 0x206f6e6f, 0x61207369, 0x61727420, 0x616d6564, 0x6f206b72, 0x25b28466, 0x697a6f4d, 0xb5836c6c, 0x6f707225, 0x82746172, 0x432e2547, 0x6f727261, + 0x43212e82, 0x3c13856f, 0x45202c65, 0x736e6564, 0x6b656970, 0x616d7265, 0x41206e6e, 0x4e202c47, 0x74696b69, 0x24ea8361, 0x6f706f6b, 0x4135b576, + 0x0c410717, 0x6d2e2205, 0x21109065, 0x8a826854, 0x6e6f462c, 0x6f532074, 0x61777466, 0xca836572, 0x63696c22, 0x65359182, 0x6e752064, 0x20726564, + 0x20656874, 0x204c4953, 0x6e65704f, 0x202c8420, 0x2120854c, 0x1d41202c, 0x2e312307, 0xf2822e31, 0x3b864c82, 0x61384683, 0x6c696176, 0x656c6261, + 0x74697720, 0x20612068, 0x20514146, 0x203a7461, 0x3a358683, 0x63732f2f, 0x74706972, 0x69732e73, 0x726f2e6c, 0x464f2f67, 0x3d19994c, 0x6f004300, + 0x79007000, 0x69007200, 0x68006700, 0x20007400, 0x30003200, 0x34003100, 0x09842d00, 0x20220d83, 0x1b825400, 0x1b826520, 0x27824620, 0x61007222, + 0x39830982, 0x83006421, 0x82502013, 0x006f223d, 0x200b826a, 0x223f8463, 0x82750041, 0x82682007, 0x00722259, 0x20298273, 0x20578428, 0x24678274, + 0x003a0073, 0x2001822f, 0x20458267, 0x26158274, 0x00620075, 0x8263002e, 0x826d2029, 0x82742015, 0x826e2007, 0x826b2031, 0x002f218f, 0x67876987, + 0x11882920, 0xb5842020, 0x52207b85, 0x74207582, 0x6e204d82, 0x0b839382, 0x7b826720, 0x0b826c20, 0x35007222, 0x30225982, 0xc3823000, 0x2f823b20, + 0x44005426, 0x3b004200, 0x2d215590, 0x93418b00, 0x201f8bdd, 0x206d8256, 0x20a18272, 0x20a98469, 0x8f638a20, 0x205797ad, 0x2239844d, 0x8220006f, + 0x827320b3, 0x82612005, 0x00742203, 0x83b18272, 0x846d20cf, 0x826b20b9, 0x006f2213, 0x20058266, 0x06754154, 0x7a243583, 0x6c006900, 0x7b410182, + 0x00722207, 0x204b8270, 0x83318272, 0x006f22ff, 0x20ef826e, 0x203f8443, 0x20178272, 0x20a58269, 0x20f78220, 0x895b826f, 0x00652227, 0x2155822c, + 0x6b830045, 0x21826e20, 0x53827020, 0x6b006522, 0x7b83d584, 0x45826e20, 0x41002024, 0x27844700, 0x1d824e20, 0x03826b20, 0x55827420, 0x50002022, + 0x6f204982, 0x6f202b82, 0x76207784, 0x61205b82, 0x6be51182, 0x74006822, 0x70200182, 0x3f42b182, 0x0b294205, 0x6d002e22, 0x21a1bf82, 0x68005422, + 0x22067341, 0x826f0046, 0x007424e7, 0x82530020, 0x82662009, 0x82772059, 0x827220e1, 0x07954145, 0x29826c20, 0x0f826320, 0x71826e20, 0x64006522, + 0x75202982, 0x64203182, 0x72201182, 0x74200b82, 0x24069541, 0x00490053, 0x220f824c, 0x8470004f, 0x0020212b, 0x4c205989, 0x2c20418c, 0x3b422582, + 0x0031230f, 0x0383002e, 0x41055b43, 0x778d05af, 0x20092342, 0x229f8276, 0x826c0069, 0x82622005, 0x82652005, 0x8277204d, 0x2087835f, 0x83138220, + 0x00412277, 0x20158251, 0x20cb8261, 0x4107823a, 0x2d41070d, 0x00732805, 0x00720063, 0x82700069, 0x8273201d, 0x82732075, 0x826c200b, 0x826f2007, + 0x00672415, 0x824f002f, 0x434c20b7, 0x33ab08a3, 0x43112f43, 0x53200b2d, 0x6e229b82, 0x8f827300, 0x65007322, 0x66208184, 0x6c240b82, 0x77006f00, + 0x63200f84, 0x19831f82, 0x1b822020, 0x11824c20, 0x2b847320, 0x89825420, 0x6e006122, 0x47209782, 0x65201782, 0x74202382, 0x72201b82, 0x83060d43, + 0x82202019, 0x0069213f, 0x6820fd85, 0x72204d82, 0x7a20cf82, 0x2206d341, 0x826c0061, 0x82622029, 0x00722235, 0x06574354, 0xb1432b83, 0x261d8505, + 0x006d0041, 0x82650070, 0x8473201d, 0x006422a1, 0x08fd444c, 0x17827720, 0x20090945, 0x20558244, 0x2051826c, 0x222b8261, 0x84530020, 0x9a6e2025, + 0x82742057, 0x8873207b, 0x82682025, 0x866e2009, 0x0063228d, 0x20dd826b, 0x206f826c, 0x44df8273, 0x652205a9, 0x1d827800, 0xe1846d20, 0x15826320, + 0xf5826920, 0x11826720, 0x9d866f20, 0xe3826120, 0x79826f20, 0x21824720, 0x3d827020, 0x4f862020, 0x95826420, 0x42007521, 0x2d200509, 0xdb412382, + 0x826c2005, 0x822020b9, 0x00712203, 0x202f8275, 0x242f826c, 0x02000000, 0x23008400, 0x3200b5ff, 0x8208bf49, 0x25028708, 0x00004107, 0x25820201, + 0x24000328, 0x0301c900, 0x5682c700, 0x01ad8008, 0x00050104, 0x00ae0063, 0x00060190, 0x00260025, 0x00ff00fd, 0x01070164, 0x00270008, 0x010901e9, + 0x0028000a, 0x010b0165, 0x00c8000c, 0x000d01ca, 0x010e01cb, 0x0029000f, 0x01f8002a, 0x01110110, 0x012b0012, 0x00140113, 0x0015012c, 0x001601cc, + 0x00ce00cd, 0x01cf00fa, 0x01180117, 0x012d0019, 0x012e001a, 0x012f001b, 0x011d011c, 0x001f011e, 0x003000e2, 0x01200131, 0x01220121, 0x82660023, + 0x290e07ab, 0x002401d0, 0x006700d1, 0x012501d3, 0x01910026, 0x00af0027, 0x003300b0, 0x003400ed, 0x01280135, 0x002a0129, 0x002b0136, 0x01fb00e4, + 0x012d012c, 0x0137002e, 0x0130012f, 0x00320131, 0x01d40038, 0x00d50033, 0x01d60068, 0x01350134, 0x01370136, 0x00390038, 0x0139013a, 0x013b013a, + 0x003b003c, 0x01eb003c, 0x01bb003d, 0x013d003e, 0x01e6003f, 0x01410140, 0x01430142, 0x01450144, 0x00470146, 0x01690044, 0x006b0048, 0x016a006c, + 0x004a0149, 0x006d006e, 0x004b01a0, 0x00460045, 0x000001fe, 0x014c016f, 0x0047004d, 0x014e01ea, 0x00480001, 0x014f0170, 0x00720050, 0x00510173, + 0x01520171, 0x00490053, 0x01f9004a, 0x01550154, 0x014b0056, 0x00580157, 0x00d7004c, 0x00590174, 0x01770076, 0x0175005a, 0x015c015b, 0x005e015d, + 0x015f014d, 0x014e0060, 0x00620161, 0x0163014f, 0x01650164, 0x00e30066, 0x01510050, 0x01680167, 0x016a0169, 0x0078006b, 0x01790052, 0x007b006c, + 0x017a007c, 0x006e016d, 0x006f01a1, 0x00b1007d, 0x00ee0053, 0x01550054, 0x01710170, 0x01560072, 0x00e50073, 0x017401fc, 0x00890075, 0x01760157, + 0x01780177, 0x00580079, 0x007a017e, 0x00810080, 0x017b017f, 0x017d017c, 0x007f017e, 0x015a0059, 0x01810180, 0x00830182, 0x005c005b, 0x008401ec, + 0x008501ba, 0x0086015d, 0x018701e7, 0x01890188, 0x018b018a, 0x018d018c, 0x018f018e, 0x01910190, 0x01930192, 0x01950194, 0x009d0096, 0x0197019e, + 0x01990198, 0x019b019a, 0x019d019c, 0x019f019e, 0x01a101a0, 0x01a301a2, 0x01a501a4, 0x01a701a6, 0x01a901a8, 0x01ab01aa, 0x01ad01ac, 0x01af01ae, + 0x01b101b0, 0x01b301b2, 0x01b501b4, 0x01b701b6, 0x01b901b8, 0x01bb01ba, 0x01bd01bc, 0x01bf01be, 0x01c101c0, 0x01c301c2, 0x01c501c4, 0x01c701c6, + 0x01c901c8, 0x01cb01ca, 0x01cd01cc, 0x01cf01ce, 0x01d101d0, 0x01d301d2, 0x01d501d4, 0x01d701d6, 0x01d901d8, 0x01db01da, 0x01dd01dc, 0x01df01de, + 0x01e101e0, 0x01e301e2, 0x01e501e4, 0x01e701e6, 0x01e901e8, 0x01eb01ea, 0x01ed01ec, 0x01ef01ee, 0x01f101f0, 0x01f301f2, 0x01f501f4, 0x01f701f6, + 0x01f901f8, 0x01fb01fa, 0x01fd01fc, 0x02ff01fe, 0x02010200, 0x02030202, 0x02050204, 0x02070206, 0x02090208, 0x020b020a, 0x020d020c, 0x020f020e, + 0x02110210, 0x02130212, 0x02150214, 0x02170216, 0x02190218, 0x021b021a, 0x021d021c, 0x021f021e, 0x02210220, 0x02230222, 0x02250224, 0x02270226, + 0x02290228, 0x022b022a, 0x022d022c, 0x022f022e, 0x02310230, 0x02330232, 0x02350234, 0x02370236, 0x02390238, 0x023b023a, 0x023d023c, 0x023f023e, + 0x02410240, 0x02430242, 0x02450244, 0x02470246, 0x02490248, 0x024b024a, 0x024d024c, 0x024f024e, 0x02510250, 0x02530252, 0x02550254, 0x02570256, + 0x02590258, 0x025b025a, 0x025d025c, 0x025f025e, 0x02610260, 0x02630262, 0x02650264, 0x02670266, 0x02690268, 0x026b026a, 0x026d026c, 0x026f026e, + 0x02710270, 0x02730272, 0x02750274, 0x02770276, 0x02790278, 0x027b027a, 0x027d027c, 0x027f027e, 0x02810280, 0x02830282, 0x02850284, 0x02870286, + 0x02890288, 0x028b028a, 0x028d028c, 0x028f028e, 0x02910290, 0x02930292, 0x02950294, 0x02970296, 0x02990298, 0x029b029a, 0x029d029c, 0x029f029e, + 0x02a102a0, 0x02a302a2, 0x02a502a4, 0x02a702a6, 0x02a902a8, 0x02ab02aa, 0x02ad02ac, 0x02af02ae, 0x02b102b0, 0x02b302b2, 0x02b502b4, 0x02b702b6, + 0x02b902b8, 0x02bb02ba, 0x02bd02bc, 0x02bf02be, 0x02c102c0, 0x02c302c2, 0x02c502c4, 0x02c702c6, 0x02c902c8, 0x02cb02ca, 0x02cd02cc, 0x02cf02ce, + 0x02d102d0, 0x02d302d2, 0x02d502d4, 0x02d702d6, 0x02d902d8, 0x02db02da, 0x02dd02dc, 0x02df02de, 0x02e102e0, 0x02e302e2, 0x02e502e4, 0x02e702e6, + 0x02e902e8, 0x02eb02ea, 0x02ed02ec, 0x02ef02ee, 0x02f102f0, 0x02f302f2, 0x02f502f4, 0x02f702f6, 0x02f902f8, 0x02fb02fa, 0x02fd02fc, 0x03ff02fe, + 0x03010300, 0x03030302, 0x03050304, 0x03070306, 0x03090308, 0x030b030a, 0x030d030c, 0x030f030e, 0x03110310, 0x03130312, 0x03150314, 0x03170316, + 0x03190318, 0x031b031a, 0x031d031c, 0x031f031e, 0x03210320, 0x03230322, 0x03250324, 0x03270326, 0x03290328, 0x032b032a, 0x032d032c, 0x032f032e, + 0x03310330, 0x03330332, 0x03350334, 0x03370336, 0x03390338, 0x033b033a, 0x033d033c, 0x033f033e, 0x03410340, 0x03430342, 0x03450344, 0x03470346, + 0x03490348, 0x034b034a, 0x034d034c, 0x034f034e, 0x03510350, 0x03530352, 0x03550354, 0x03570356, 0x03590358, 0x005b035a, 0x035c039b, 0x035e035d, + 0x0360035f, 0x03620361, 0x03640363, 0x03660365, 0x03680367, 0x036a0369, 0x036c036b, 0x036e036d, 0x0370036f, 0x03720371, 0x03740373, 0x03760375, + 0x03780377, 0x037a0379, 0x037c037b, 0x037e037d, 0x0380037f, 0x03820381, 0x03840383, 0x03860385, 0x03880387, 0x038a0389, 0x038c038b, 0x038e038d, + 0x0390038f, 0x03920391, 0x03940393, 0x03960395, 0x03980397, 0x039a0399, 0x039c039b, 0x039e039d, 0x03a0039f, 0x03a203a1, 0x03a403a3, 0x03a603a5, + 0x03a803a7, 0x03aa03a9, 0x03ac03ab, 0x03ae03ad, 0x03b003af, 0x03b203b1, 0x03b403b3, 0x03b603b5, 0x03b803b7, 0x03ba03b9, 0x03bc03bb, 0x03be03bd, + 0x03c003bf, 0x03c203c1, 0x03c403c3, 0x03c603c5, 0x03c803c7, 0x03ca03c9, 0x03cc03cb, 0x03ce03cd, 0x03d003cf, 0x03d203d1, 0x03d403d3, 0x03d603d5, + 0x03d803d7, 0x03da03d9, 0x03dc03db, 0x03de03dd, 0x03e003df, 0x03e203e1, 0x03e403e3, 0x03e603e5, 0x03e803e7, 0x03ea03e9, 0x03ec03eb, 0x03ee03ed, + 0x03f003ef, 0x03f203f1, 0x03f403f3, 0x03f603f5, 0x03f803f7, 0x03fa03f9, 0x03fc03fb, 0x03fe03fd, 0x040004ff, 0x04020401, 0x04040403, 0x04060405, + 0x04080407, 0x040a0409, 0x000c040b, 0x00140013, 0x00160015, 0x00180017, 0x001a0019, 0x041c001b, 0x040e040d, 0x0410040f, 0x04120411, 0x04140413, + 0x04160415, 0x04180417, 0x041a0419, 0x041c041b, 0x041e041d, 0x0420041f, 0x04220421, 0x04240423, 0x04260425, 0x04280427, 0x042a0429, 0x042c042b, + 0x042e042d, 0x0430042f, 0x04320431, 0x04340433, 0x04360435, 0x04380437, 0x043a0439, 0x043c043b, 0x043e043d, 0x0440043f, 0x04bc0041, 0x04f40042, + 0x00440443, 0x04f600f5, 0x04460445, 0x04480447, 0x044a0449, 0x044c044b, 0x004e044d, 0x000f0011, 0x001e001d, 0x000400ab, 0x002200a3, 0x00c300a2, + 0x040d0087, 0x0006004f, 0x043f0012, 0x04510450, 0x04530452, 0x04550454, 0x04570456, 0x04590458, 0x045b045a, 0x045d045c, 0x045f045e, 0x04610460, + 0x000b0062, 0x005e000c, 0x003e0060, 0x04630440, 0x04650464, 0x04670466, 0x04690468, 0x046b046a, 0x046d046c, 0x046f046e, 0x04710470, 0x04730472, + 0x00750474, 0x00760410, 0x04b300b2, 0x04780477, 0x007a0479, 0x047b0442, 0x047d047c, 0x047f047e, 0x04810480, 0x00c40082, 0x00b400c5, 0x00b600b5, + 0x00a900b7, 0x00be00aa, 0x000500bf, 0x0483040a, 0x04850484, 0x04870486, 0x04890488, 0x048b048a, 0x048d048c, 0x048f048e, 0x04910490, 0x04930492, + 0x04950494, 0x04970496, 0x04990498, 0x049b049a, 0x049d049c, 0x049f049e, 0x04a104a0, 0x04a304a2, 0x04a504a4, 0x04a704a6, 0x04a904a8, 0x04ab04aa, + 0x04ad04ac, 0x04af04ae, 0x04b104b0, 0x04b304b2, 0x04b504b4, 0x04b704b6, 0x04b904b8, 0x04bb04ba, 0x04bd04bc, 0x04bf04be, 0x04c104c0, 0x04c304c2, + 0x04c504c4, 0x04c704c6, 0x04c904c8, 0x04cb04ca, 0x04cd04cc, 0x04cf04ce, 0x04d104d0, 0x04d304d2, 0x04d504d4, 0x008400d6, 0x040700bd, 0x00d804d7, + 0x04d904a6, 0x00db04da, 0x04960085, 0x04dd04dc, 0x04df04de, 0x04e104e0, 0x04e304e2, 0x04e504e4, 0x04e704e6, 0x04e904e8, 0x04eb04ea, 0x04ed04ec, + 0x04ef04ee, 0x04f104f0, 0x04f304f2, 0x04f504f4, 0x04f704f6, 0x04f904f8, 0x04fb04fa, 0x04fd04fc, 0x05ff04fe, 0x05010500, 0x000e0002, 0x00f000ef, + 0x002000b8, 0x0021008f, 0x0095001f, 0x00930094, 0x006100a7, 0x004100a4, 0x05030592, 0x05050504, 0x00070506, 0x0008059c, 0x0099009a, 0x000905a5, + 0x050a0598, 0x050c050b, 0x050e050d, 0x0008000f, 0x051005c6, 0x05120511, 0x05140513, 0x05160515, 0x05180517, 0x051a0519, 0x051c051b, 0x051e051d, + 0x0520051f, 0x05220521, 0x05240523, 0x05260525, 0x05280527, 0x052a0529, 0x052c052b, 0x052e052d, 0x0530052f, 0x05320531, 0x05340533, 0x05360535, + 0x05380537, 0x053a0539, 0x053c053b, 0x053e053d, 0x0540053f, 0x05420541, 0x05440543, 0x05460545, 0x05480547, 0x054a0549, 0x054c054b, 0x054e054d, + 0x0550054f, 0x05520551, 0x05540553, 0x05560555, 0x05580557, 0x055a0559, 0x055c055b, 0x055e055d, 0x0560055f, 0x05620561, 0x05640563, 0x05660565, + 0x05680567, 0x056a0569, 0x056c056b, 0x056e056d, 0x0570056f, 0x05720571, 0x05740573, 0x05760575, 0x05780577, 0x057a0579, 0x057c057b, 0x057e057d, + 0x0580057f, 0x05820581, 0x05840583, 0x05860585, 0x05880587, 0x058a0589, 0x058c058b, 0x058e058d, 0x0590058f, 0x05920591, 0x05940593, 0x05960595, + 0x05980597, 0x009a0599, 0x059b05b9, 0x059d059c, 0x059f059e, 0x05a105a0, 0x05a305a2, 0x05a505a4, 0x05a705a6, 0x05a905a8, 0x05ab05aa, 0x05ad05ac, + 0x05af05ae, 0x05b105b0, 0x05b305b2, 0x05b505b4, 0x05b705b6, 0x05b905b8, 0x05bb05ba, 0x05bd05bc, 0x05bf05be, 0x05c105c0, 0x05c305c2, 0x05c505c4, + 0x05c705c6, 0x05c905c8, 0x05cb05ca, 0x05cd05cc, 0x05cf05ce, 0x05d105d0, 0x05d305d2, 0x05d505d4, 0x05d705d6, 0x05d905d8, 0x05db05da, 0x05dd05dc, + 0x05df05de, 0x05e105e0, 0x05e305e2, 0x05e505e4, 0x05e705e6, 0x05e905e8, 0x05eb05ea, 0x05ed05ec, 0x05ef05ee, 0x05f105f0, 0x05f305f2, 0x05f505f4, + 0x05f705f6, 0x05f905f8, 0x05fb05fa, 0x05fd05fc, 0x06ff05fe, 0x06010600, 0x06030602, 0x06050604, 0x06070606, 0x06090608, 0x060b060a, 0x060d060c, + 0x060f060e, 0x06110610, 0x06130612, 0x06150614, 0x06170616, 0x06190618, 0x061b061a, 0x061d061c, 0x061f061e, 0x06210620, 0x06230622, 0x06250624, + 0x06270626, 0x06290628, 0x062b062a, 0x062d062c, 0x062f062e, 0x06310630, 0x06330632, 0x06350634, 0x06370636, 0x06390638, 0x063b063a, 0x063d063c, + 0x063f063e, 0x06410640, 0x06430642, 0x06450644, 0x06470646, 0x06490648, 0x064b064a, 0x064d064c, 0x064f064e, 0x06510650, 0x06530652, 0x06550654, + 0x00570656, 0x00090023, 0x00860088, 0x008a008b, 0x0683008c, 0x005f0058, 0x005906e8, 0x06c20082, 0x065b065a, 0x065d065c, 0x065f065e, 0x06610660, + 0x06630662, 0x06650664, 0x06670666, 0x06690668, 0x066b066a, 0x066d066c, 0x066f066e, 0x06710670, 0x06730672, 0x06750674, 0x06770676, 0x06790678, + 0x067b067a, 0x067d067c, 0x067f067e, 0x06810680, 0x06830682, 0x06850684, 0x06870686, 0x06890688, 0x068b068a, 0x068d068c, 0x068f068e, 0x06910690, + 0x06930692, 0x06950694, 0x06970696, 0x06990698, 0x069b069a, 0x069d069c, 0x069f069e, 0x06a106a0, 0x06a306a2, 0x06a506a4, 0x06a706a6, 0x06a906a8, + 0x06ab06aa, 0x06ad06ac, 0x06af06ae, 0x06b106b0, 0x06b306b2, 0x06b506b4, 0x06b706b6, 0x06b906b8, 0x06bb06ba, 0x06bd06bc, 0x06bf06be, 0x06c106c0, + 0x06c306c2, 0x06c506c4, 0x06c706c6, 0x06c906c8, 0x06cb06ca, 0x06cd06cc, 0x06cf06ce, 0x06d106d0, 0x06d306d2, 0x06d506d4, 0x06d706d6, 0x06d906d8, + 0x06db06da, 0x06dd06dc, 0x06df06de, 0x06e106e0, 0x06e306e2, 0x06e506e4, 0x06e706e6, 0x06e906e8, 0x06eb06ea, 0x06ed06ec, 0x06ef06ee, 0x06f106f0, + 0x06f306f2, 0x06f506f4, 0x06f706f6, 0x06f906f8, 0x06fb06fa, 0x06fd06fc, 0x07ff06fe, 0x07010700, 0x07030702, 0x07050704, 0x07070706, 0x07090708, + 0x070b070a, 0x070d070c, 0x070f070e, 0x07110710, 0x07130712, 0x07150714, 0x07170716, 0x008e0018, 0x004300dc, 0x00df008d, 0x00e100d8, 0x00dd00db, + 0x00da00d9, 0x07e000de, 0x071a0719, 0x071c071b, 0x071e071d, 0x0720071f, 0x07220721, 0x07240723, 0x07260725, 0x07280727, 0x072a0729, 0x072c072b, + 0x072e072d, 0x0730072f, 0x07320731, 0x07340733, 0x07360735, 0x07380737, 0x073a0739, 0x073c073b, 0x073e073d, 0x0740073f, 0x07420741, 0x07440743, + 0x07460745, 0x07480747, 0x074a0749, 0x044c074b, 0x6c6c756e, 0x72624106, 0x07657665, 0x63616d41, 0x076e6f72, 0x6f676f41, 0x076b656e, 0x63614541, + 0x0b657475, 0x72696343, 0x666d7563, 0x0a78656c, 0x746f6443, 0x65636361, 0x4406746e, 0x2d826163, 0x72250682, 0x0674616f, 0x21438445, 0x14844506, + 0x88450a21, 0x45072126, 0x45205586, 0x0b215585, 0x294d8947, 0x696e7507, 0x32323130, 0x2e88470a, 0x62480426, 0x480b7261, 0x02242389, 0x49064a49, + 0x07215b84, 0x20498649, 0x28498549, 0x69744906, 0x0b65646c, 0x23508f4a, 0x4c063633, 0x0621b984, 0x858d844c, 0x42332366, 0x66824c04, 0x854e0621, + 0x8a4e201a, 0x3534271a, 0x676e4503, 0x66844f06, 0x684f0d2f, 0x61676e75, 0x6c6d7572, 0x07747561, 0x2674854f, 0x6c734f0b, 0x85687361, 0x8652203b, + 0x23428a06, 0x53063635, 0x0b211584, 0x228e8e53, 0x83383132, 0x45312580, 0x54044539, 0x0621dc82, 0x21368a54, 0x9c843236, 0x41313224, 0x7d855506, + 0x7d8c5520, 0x7d855520, 0x85550721, 0x550523f2, 0xa8826972, 0xf8845520, 0x85570621, 0x89572070, 0x57093270, 0x72656964, 0x73697365, 0x72675706, + 0x0b657661, 0x211c8959, 0x12845906, 0x845a0621, 0x5a0a2136, 0x21087341, 0x1184430e, 0x6f6c2e28, 0x4c506c63, 0x21410e4b, 0x200e8805, 0x851d8d4f, + 0x851d88e6, 0x2a0e874d, 0x732e4608, 0x65636170, 0x86540872, 0x61062108, 0x20055c42, 0x20c98661, 0x22c98561, 0x84656107, 0x630b2156, 0x0a21a089, + 0x28928863, 0x61636406, 0x066e6f72, 0x05554265, 0x0d846520, 0x88650a21, 0x6507211f, 0x65204e86, 0x0b214e85, 0x0e754167, 0x33323124, 0x2e88670a, + 0x62680426, 0x680b7261, 0x06212389, 0x21588469, 0xb8846909, 0x4b525427, 0x076a6902, 0x20538669, 0x26538569, 0x69746906, 0x4165646c, 0x332305a0, + 0x8f6a0b37, 0x37333062, 0x72676b0c, 0x6c6e6565, 0x69646e61, 0x846c0663, 0x6c0621d1, 0x230adf41, 0x6c044333, 0x06218582, 0x2d1a846e, 0x70616e0b, + 0x7274736f, 0x6568706f, 0x268a6e06, 0x03363427, 0x06676e65, 0x2194846f, 0x02426f0d, 0x856f200c, 0x6f0b2195, 0x200a8042, 0x214e8472, 0x428a7206, + 0x06373523, 0x21158473, 0xa78e730b, 0x39313224, 0xff827404, 0x8a740621, 0x3336212e, 0x3123d785, 0x85750642, 0x8c752075, 0x85752075, 0x75072175, + 0x23050b41, 0x69727505, 0x7527a082, 0x646c6974, 0x85770665, 0x89772068, 0x77092168, 0x27087842, 0x61726777, 0x790b6576, 0x06211c89, 0x21128479, + 0x36847a06, 0x417a0a21, 0x0e210896, 0x0d5a4263, 0x42052541, 0x6f20085a, 0xde851d8d, 0x4d851d88, 0x0a370e87, 0x756d2e78, 0x7069746c, 0x690a796c, + 0x6c61732e, 0x6f6c5f74, 0x896a0a77, 0x886c200a, 0x6608210a, 0x20069b42, 0x42138208, 0x772005ad, 0x06271186, 0x73732e72, 0x890f3130, 0x742e274d, + 0x0a66736f, 0x01825f77, 0x696c2e2c, 0x75076167, 0x3032696e, 0x07834637, 0x31343023, 0x20078630, 0x43078631, 0x342105cf, 0x055e4131, 0x86303421, + 0x87392007, 0x86342027, 0x85352027, 0x86302007, 0x87302017, 0x8536203f, 0x37312117, 0x38200786, 0x39200786, 0x30210785, 0x21078544, 0x07854138, + 0x07863120, 0x86433021, 0x8642200f, 0x860f8707, 0x4531212f, 0xb7861786, 0x77863220, 0x77863220, 0xb7863220, 0xaf863220, 0x2f863020, 0xaf863220, + 0xaf863220, 0x97863220, 0xa7863220, 0x9f863220, 0x9f873220, 0x7f865f87, 0x9f863220, 0x97863220, 0x27873020, 0x30201786, 0x30205786, 0xaf866787, + 0x5f863020, 0x6f863020, 0x67863020, 0x47863020, 0x9f873220, 0x30206f86, 0x3621bf86, 0x45e78530, 0x34210657, 0x20578636, 0x204f8636, 0x20478636, + 0x207f8636, 0x20a78636, 0x204f8636, 0x203f8637, 0x204f8637, 0x203f8637, 0x203f8637, 0x203f8637, 0x201f8639, 0x201f8639, 0x201f8639, 0x861f8739, + 0x8639205f, 0x8639205f, 0x3041215f, 0x41209f85, 0x41203f86, 0x41203f86, 0x35203f85, 0x20076f41, 0x20478641, 0x20478641, 0x20478641, 0x21478641, + 0x47853042, 0x47864220, 0x47864220, 0x47854220, 0x86423421, 0x8542203f, 0x4135203f, 0x422007af, 0x42204786, 0x43214786, 0x21478530, 0x07863143, + 0x2006ff41, 0x06974143, 0x7f414320, 0x41432006, 0x432006b7, 0x20067f41, 0x06a74143, 0x3f864420, 0x87864420, 0x87864420, 0x87864420, 0x87864420, + 0x87854420, 0x86443421, 0x8644207f, 0x3045217f, 0x45207785, 0x45203f86, 0x45203f86, 0x45203f86, 0x45203f86, 0x45203f86, 0x45203f86, 0x46213f86, + 0x203f8530, 0x203f8646, 0x203f8646, 0x203f8646, 0x203f8646, 0x203f8646, 0x203f8646, 0x203f8546, 0x067f4335, 0x3f423520, 0x42352006, 0x35200687, + 0x20067f42, 0x06774235, 0x85303521, 0x4335203f, 0x35200667, 0x20061f43, 0x06ff4335, 0x85313521, 0x3135217f, 0x35217f85, 0x207f8531, 0x05fb4735, + 0x43353021, 0x352106a7, 0x207f8531, 0x068f4335, 0x87433520, 0x43352006, 0x3820077f, 0x34211f85, 0x439f8638, 0x3520065f, 0x21064743, 0x1f853235, + 0xff423520, 0x30332107, 0x3321ff85, 0x85078631, 0x33342187, 0x2006c741, 0x20078635, 0x851f8739, 0x3334219f, 0x2006df41, 0x203f8635, 0x851f8735, + 0x333421b7, 0x2006f741, 0x063f4133, 0xff413320, 0x41352006, 0x382006f7, 0x20060742, 0x05174133, 0x85353421, 0x33342197, 0x0f871787, 0x33202f86, + 0x3421cf85, 0x06af4333, 0x77863420, 0x77863420, 0xb7863420, 0xaf863420, 0x2f863520, 0xaf863420, 0xaf863420, 0x97863420, 0xa7863420, 0x9f863420, + 0x9f873420, 0x7f865f87, 0x9f863420, 0x97863420, 0x27873520, 0x35201786, 0x35205786, 0xaf866787, 0x5f863520, 0x6f863520, 0x67863520, 0x47863520, + 0x9f873420, 0x35206f86, 0x3621bf86, 0x05874131, 0x21065e47, 0x5f863634, 0x47863620, 0x7f863620, 0x47863620, 0x6f863620, 0x47863620, 0x3f863720, + 0x07413720, 0x86372006, 0x8637203f, 0x8637203f, 0x8639203f, 0x8639201f, 0x8639201f, 0x8739201f, 0x205f861f, 0x205f8639, 0x215f8639, 0x9f853141, + 0x3f864120, 0x3f854120, 0xdf453520, 0x86412007, 0x86412047, 0x86412047, 0x86412047, 0x86412047, 0x31422147, 0x42204785, 0x42204786, 0x34214785, + 0x203f8642, 0x203f8642, 0x203f8542, 0x07374635, 0x47864220, 0x47864220, 0x07874320, 0x20063f41, 0x06874143, 0x7f414320, 0x41432006, 0x43200677, + 0x2006af41, 0x06d74143, 0x7f414320, 0x31442106, 0x44208785, 0x44208786, 0x44208786, 0x44208786, 0x44208786, 0x34218785, 0x207f8644, 0x21778644, + 0x3f853145, 0x3f864520, 0x3f864520, 0x3f864520, 0x3f864520, 0x3f864520, 0x3f864520, 0x3f864520, 0x85314621, 0x8646203f, 0x8646203f, 0x8646203f, + 0x8646203f, 0x8646203f, 0x8646203f, 0x8546203f, 0x4735203f, 0x352006f7, 0x20062748, 0x060f4735, 0xf7463520, 0x47352006, 0x3521062f, 0x203f8530, + 0x06ff4735, 0x86303521, 0x3131213f, 0x35217f84, 0x217f8531, 0x7f853135, 0x85313521, 0x3135217f, 0x35217f85, 0x203f8631, 0x217f8531, 0x3f863135, + 0x2006ff47, 0x07f74735, 0x1f853820, 0x87383421, 0x473f861f, 0x352106bf, 0x211f8532, 0x1f853235, 0x46373333, 0x706c4105, 0x42046168, 0x05617465, + 0x6d6d6147, 0x2c908461, 0x07343933, 0x69737045, 0x046e6f6c, 0x211a825a, 0x1e824503, 0x82685421, 0x49042209, 0x080a826f, 0x70614b2f, 0x4c066170, + 0x64626d61, 0x754d0261, 0x02754e02, 0x4f076958, 0x7263696d, 0x50026e6f, 0x68520369, 0x6953056f, 0x03616d67, 0x07756154, 0x254a8555, 0x69685003, + 0x03824303, 0x69735022, 0x41226685, 0x7f840a39, 0x6e6f7425, 0x860c736f, 0x200c8471, 0x84718208, 0x83092008, 0x20098470, 0x855f860c, 0x8453860c, + 0x4f0a250c, 0x6167656d, 0x0c200a84, 0xcc4a2e83, 0x860f2007, 0x850f8724, 0x06244874, 0x24483320, 0x48332006, 0x3320061c, 0x2006ec46, 0x06ec4633, + 0xec463320, 0x46332006, 0x332006ec, 0x2006ec46, 0x06f44233, 0x34473320, 0x42332006, 0x332006bc, 0x20063c47, 0x06c44633, 0x44423320, 0x42332006, + 0x33210644, 0x05044346, 0x44423320, 0x46332006, 0x332006c4, 0x21054c42, 0xac464631, 0x20078205, 0x82a78339, 0x822f8407, 0x86422007, 0x8643200f, + 0x86442007, 0x86452007, 0x85462007, 0x052c4807, 0x43463121, 0x078205b4, 0x17863820, 0x3c484f86, 0x46312205, 0x20178638, 0x4a178638, 0x1782058c, + 0xc4466786, 0x860f8205, 0x05cc4667, 0x67860f82, 0x21051447, 0x9c424631, 0x86078205, 0x05a442a7, 0xa7860f82, 0x2105ac42, 0x04444631, 0x86078205, + 0x0514476f, 0x4a463121, 0x07820574, 0xa4423f86, 0x860f8205, 0x05ac423f, 0xe7860f82, 0x8205b442, 0x482f8647, 0x0f8205cc, 0xbc492f86, 0x46312105, + 0x82054445, 0x20278607, 0x49d78639, 0x178205cc, 0xd449d786, 0x860f8205, 0x052c47d7, 0x47463121, 0x0782052c, 0x14473f86, 0x860f8205, 0x86332067, + 0x0514473f, 0x3f861782, 0x21053742, 0xac444631, 0x41078205, 0xc4440667, 0x46312105, 0x8205ec46, 0x06074107, 0x8205dc46, 0x209f860f, 0x205f8634, + 0x485f8634, 0x312205fc, 0x2f864646, 0x21053c49, 0x04474631, 0x86078205, 0x05d44737, 0x87860f82, 0x21056c49, 0xf4444631, 0x86078205, 0x050c4587, + 0x4b463121, 0x07820544, 0x36205786, 0xd446e786, 0x86178205, 0x05dc4687, 0x7f410f82, 0x05e44606, 0x2f868f82, 0x82051445, 0x4a2f860f, 0x312105f4, + 0x057c4646, 0x27860782, 0x82058446, 0x8627870f, 0x050c4bdf, 0x46391782, 0x706c6105, 0x62046168, 0x05617465, 0x6d6d6167, 0x65640561, 0x0761746c, + 0x05374465, 0x827a0421, 0x82032018, 0x74052203, 0x22058268, 0x826f6904, 0x616b2a27, 0x06617070, 0x626d616c, 0x06b34464, 0x02434229, 0x7802756e, + 0x446f0769, 0x03230587, 0x436f6872, 0x432d05f1, 0x69730532, 0x03616d67, 0x07756174, 0x25548575, 0x69687003, 0x03826303, 0x05260e82, 0x67656d6f, + 0x57830961, 0x83054444, 0x07344409, 0x0c8b1120, 0x42861e85, 0x0f200c84, 0x2e870c86, 0x0f8e1420, 0x0c202484, 0x0c849286, 0x6d840a20, 0xf8840a85, + 0x8605fd44, 0x05fd44ec, 0x0884e682, 0x5648bf85, 0x48332006, 0x33200656, 0x22064e48, 0x86423733, 0x8643201f, 0x85442007, 0x05714207, 0x42333021, + 0x07820589, 0x46201787, 0x36471f85, 0x47332006, 0x33200666, 0x2006064c, 0x068e4733, 0x86473320, 0x4c332006, 0x33200606, 0x2206a64b, 0x85314633, + 0x06ae4b3f, 0x36473320, 0x47332006, 0x33200636, 0x2105b142, 0x19423330, 0x84078205, 0x46312197, 0x8205a64b, 0x823f8407, 0x44322007, 0x36470599, + 0x200f8205, 0x200f8634, 0x20078635, 0x20078636, 0x45078537, 0x312105b1, 0x05074146, 0x4d463121, 0x07820526, 0x1f853020, 0x57864220, 0x86334221, + 0x4d5f860f, 0x31220556, 0x27863846, 0x27863820, 0x1f863820, 0x2f863820, 0x7f863820, 0x7f863820, 0x7f863820, 0x7f863820, 0x21051649, 0x2e4c4631, + 0x86078205, 0x05364c47, 0x47860f82, 0x82053e4c, 0x4647860f, 0xb7820561, 0x2e4c1f86, 0x46312105, 0x8205b647, 0x47878607, 0x0f8205be, 0x32208786, + 0xf64d3f86, 0x86178205, 0x05ce4e87, 0x1f864f82, 0x22056649, 0x86434631, 0x8643205f, 0x0586494f, 0x50463121, 0x078205b6, 0x3920af86, 0x7e4a1f86, + 0x86178205, 0x05864a6f, 0xf7860f82, 0x82058e4a, 0x4c778657, 0x312205a6, 0x47863346, 0x47863320, 0x8205a64c, 0x41342017, 0x33200577, 0x33209786, + 0x864c4786, 0x86af8205, 0x05b7420f, 0x42463121, 0x07820557, 0x42069741, 0x0f820577, 0x51475786, 0x860f8205, 0x056e4c7f, 0x4c463121, 0x0782056e, + 0x6e4c2786, 0x860f8205, 0x05664c7f, 0xf1446f82, 0x056e4b06, 0x4e463121, 0x07820596, 0x364d9f86, 0x46312105, 0x8205364d, 0x4d4f8607, 0x0f82056e, + 0x5e4c4f86, 0x860f8205, 0x054e4cbf, 0xd9445f82, 0x057f4306, 0x1f865782, 0x82052148, 0x0627410f, 0x8205164f, 0x069f410f, 0x2105964a, 0xe6504631, + 0x86078205, 0x05ee5027, 0x27860f82, 0x8205f650, 0x50af860f, 0x0f8205fe, 0x20060f41, 0x06574337, 0x41443721, 0x2e4f0577, 0x46312105, 0x82058f43, + 0x48cf8607, 0x31210589, 0x05b65046, 0x6f860782, 0x8205be50, 0x506f860f, 0x0f8205c6, 0xce506f86, 0x860f8205, 0x05c9486f, 0x50463121, 0x33210676, + 0x21ff8537, 0x2f853034, 0x41303427, 0x44317506, 0x05384735, 0x30313222, 0x07827e84, 0x32229e84, 0x26843131, 0x39200782, 0x0782ae83, 0x07823e84, + 0x32271f86, 0x657a0934, 0x832e6f72, 0x24098504, 0x66736f74, 0x2013880e, 0x230e832e, 0x656e6f08, 0x74220885, 0x08846f77, 0x68740a24, 0x13856572, + 0x6f660924, 0x14847275, 0x69660923, 0x23138576, 0x78697308, 0x0a251284, 0x65766573, 0x240a856e, 0x68676965, 0x220a8474, 0x86696e09, 0x83688550, + 0x84818463, 0x443020a3, 0x32210532, 0x05324430, 0xd3850782, 0x32443020, 0x200f8205, 0x85278634, 0x443020db, 0x17820532, 0x17863720, 0x07863820, + 0xd1853920, 0x6f6e6423, 0x84c2846d, 0x83c28308, 0x83c28608, 0x85c2850a, 0x84c28309, 0x84c28327, 0x84c28527, 0x84c2850a, 0x84c28428, 0x657a2809, + 0x6e2e6f72, 0x84726d75, 0x83088463, 0x86088363, 0x850a8363, 0x83098563, 0x83278463, 0x85278463, 0x850a8463, 0x84288463, 0x85098363, 0x058a45cf, + 0x4e303021, 0x30200621, 0x2006c152, 0x057a4530, 0x44303221, 0x078205a2, 0x4b061741, 0x0f82055c, 0x53061741, 0x0f820581, 0x21060b42, 0x57844635, + 0x7a433120, 0x31322105, 0x8205c94f, 0x203f8507, 0x05c94f31, 0x3f850f82, 0xc94f3120, 0x870f8205, 0x0941243f, 0x84656e6f, 0x0c6825af, 0x65726874, + 0x73220b86, 0xe182660b, 0x73211785, 0x86da840c, 0x206f840c, 0x05e15130, 0x3430323c, 0x78650f41, 0x6d616c63, 0x6e776f64, 0x7361632e, 0x75711165, + 0x69747365, 0x11886e6f, 0x6f630c24, 0x1c826f6c, 0x746e6527, 0x610b7265, 0x2c058273, 0x2e6b7369, 0x700d636c, 0x6f697265, 0x067c5664, 0x40592686, + 0x73102405, 0x85696d65, 0x20108537, 0x8666850d, 0x870f202b, 0x880f8764, 0x2a2d8555, 0x6d756e11, 0x73726562, 0x866e6769, 0x730c2521, 0x6873616c, + 0x10240c86, 0x6b636162, 0x0e20108b, 0x7323108a, 0x89143630, 0x6874260e, 0x2e6b6369, 0x20148273, 0x218e8508, 0x01416375, 0x052b4e05, 0x4b303221, + 0x332305de, 0x83433030, 0x43078217, 0x37200595, 0x2105e941, 0x74473732, 0x30322105, 0x82056c44, 0x0e453007, 0x65726170, 0x66656c6e, 0x61632e74, + 0x840f6573, 0x6972230e, 0x0f856867, 0x72620e25, 0x89656361, 0x890e841e, 0x8310201e, 0x656b220f, 0x20208874, 0x89108611, 0x21888322, 0x15454646, + 0x21078205, 0x70891033, 0x84051e41, 0x85628543, 0x20438410, 0x85418565, 0x8b122011, 0x20128566, 0x85688c13, 0x216a8313, 0x1f513030, 0x30322e05, + 0x660a3531, 0x72756769, 0x73616465, 0x211a8368, 0xfd4b4532, 0x29078205, 0x6e750d41, 0x73726564, 0x1e826f63, 0x0b6c6227, 0x68707968, 0x05324265, + 0x6e750c23, 0x27448369, 0x7361632e, 0x6e650b65, 0x0b863d83, 0x0b886d20, 0x30860920, 0x0d636c22, 0x81850986, 0x56891120, 0x2806dd41, 0x69756712, + 0x6d656c6c, 0x0923416f, 0x12881320, 0x84092541, 0x69732326, 0x2b82676e, 0x84068a41, 0x89128426, 0x0aad4126, 0x6f6e6423, 0x0bad416d, 0x12200f83, + 0x5f208c85, 0x2e250685, 0x6167696c, 0x8b128c19, 0x86162019, 0x73612319, 0x5e5b6963, 0x20308405, 0x08f14112, 0x61625f23, 0x20128472, 0x0a7e4114, + 0x1c201488, 0x200b8041, 0x0ae2425f, 0x12207583, 0x8b054c43, 0x8512876e, 0x20578419, 0x200b8519, 0x84068c5f, 0x8c182019, 0x655f2512, 0x6c617571, + 0x17201884, 0x6c23188d, 0x84737365, 0x86142017, 0x088a4317, 0x11208583, 0x3e891486, 0x6f631026, 0x5f6e6f6c, 0x37840584, 0x108a1620, 0x3e901697, + 0x18201089, 0x20081944, 0x8409885f, 0x44122057, 0x5f200521, 0x12840685, 0x128c1920, 0x1984f486, 0x19871120, 0x118be689, 0x1420fe8a, 0x3e8bdf87, + 0x14881620, 0x1320fd8c, 0xaf891688, 0x9a441620, 0x445f2007, 0x6c2408a3, 0x1f616769, 0x1f8d1690, 0x1f881520, 0x65726725, 0x42657461, 0x13200516, + 0xbd441588, 0x20498305, 0x09084219, 0xe8435f20, 0x42198f09, 0xfe840862, 0x338a1b20, 0x840a6942, 0x8a15201b, 0x0ab5411b, 0x6141158a, 0x8a18200a, + 0x0c0a4116, 0x0c41458b, 0x8a1a2009, 0x0ab7432e, 0x2420ac83, 0xd18e1a94, 0xf6841320, 0x200d2941, 0x41138512, 0x10200b26, 0x23411285, 0x8a162009, + 0x895f2010, 0x84142016, 0x455f200a, 0x888309ed, 0x8a09fc45, 0x0b644129, 0x23091441, 0x6d65725f, 0x820a1f44, 0x447220c1, 0x0f830b1f, 0xf2431120, + 0x696d2a06, 0x656c6464, 0x7165732e, 0x24118610, 0x72617473, 0x20108374, 0x2210860e, 0x83646e65, 0x061f430e, 0x75716525, 0x895f6c61, 0x42172036, + 0x17890c9f, 0x37411220, 0x4141860a, 0x28890b7b, 0x288a1420, 0x50417b88, 0x866c8506, 0x062c413e, 0x1520808f, 0x85052c41, 0x20408816, 0x0b594119, + 0x1c20468c, 0x8c891991, 0x1c911b20, 0x12205288, 0x20091942, 0x2092865f, 0x89128a15, 0x8a142044, 0x203d8815, 0x06274116, 0x230a6345, 0x37307373, + 0x820df043, 0x41382011, 0xba840d50, 0x17832e20, 0x6e750725, 0x5b373269, 0x0782057a, 0x61093929, 0x65746f6e, 0x5169656c, 0x37210627, 0x20218445, + 0x05a45630, 0x30303223, 0x210f8338, 0x254c3030, 0x2c0f8205, 0x70730a42, 0x2e656361, 0x63617266, 0x824c830a, 0x742e222a, 0x21258366, 0xad544546, + 0x30322805, 0x45044641, 0x856f7275, 0x057a544a, 0x58303221, 0x0782051f, 0x640d3927, 0x616c6c6f, 0x06d14672, 0x0d870b20, 0xa15b7320, 0x32322105, + 0x2105624c, 0x324e3232, 0x32322205, 0x05cf4931, 0x48303221, 0x3320057d, 0x8205395d, 0x05074a17, 0x2c523220, 0x20378205, 0x23718443, 0x07424132, + 0x6d23d282, 0x85746e65, 0x4c30200f, 0x30200553, 0x3505bc54, 0x43373032, 0x7571650b, 0x6c617669, 0x65636e65, 0x6978650b, 0x2c827473, 0x6c616922, + 0x41272f85, 0x72670839, 0x82696461, 0x690a2413, 0x8265746e, 0x626c220c, 0x210a8874, 0x26847074, 0xcb523320, 0x33322105, 0x8205db52, 0x05864a07, + 0x414d3320, 0x200f8205, 0x20278633, 0x20078431, 0x05585b30, 0x42207e82, 0x32200f84, 0x82059059, 0x05e64ab6, 0x7b553220, 0x32322105, 0x24057b55, + 0x43303232, 0x059c410a, 0x3622c989, 0x12820932, 0x62757324, 0xdb866573, 0x82059650, 0x08442644, 0x74706d65, 0x2b188279, 0x676f6c0a, 0x6c616369, + 0x09646e61, 0x6f220a86, 0xc8830c72, 0x6573722a, 0x6f697463, 0x6e75056e, 0x85850582, 0x41363021, 0xe65905e1, 0x33322105, 0x82050955, 0x066c4107, + 0x82052155, 0x20a5850f, 0x06094233, 0x21553320, 0x30322105, 0x82052156, 0x056441d5, 0x36333229, 0x6665720c, 0x8578656c, 0x870e20a5, 0x6570210c, + 0x74247d82, 0x7665720d, 0xc8829386, 0x33208184, 0x20066049, 0x05085f33, 0x54333221, 0x07820513, 0x2005de41, 0x060e4233, 0x894e3320, 0x24ea8205, + 0x72700c32, 0x414f836f, 0x412a0b07, 0x63757308, 0x61687468, 0x1d870e74, 0x64847285, 0x7c413220, 0x88322006, 0x059c4144, 0x34303226, 0x65687409, + 0x6f22a482, 0x29856572, 0x26075d42, 0x75093841, 0x8276696e, 0x081742b6, 0x690d352f, 0x6e69666e, 0x2e797469, 0x65736163, 0x0796450e, 0xfd4b6320, + 0x656c2405, 0x852e7373, 0x7007280b, 0x2e73756c, 0x840b636c, 0x70732607, 0x72656361, 0x0686430c, 0x3b880c84, 0x0b201b85, 0x0b853b84, 0xdd431120, + 0x202c840b, 0x63118412, 0x35430575, 0x700e2306, 0x6a837265, 0x07260e86, 0x6f727261, 0x99427577, 0x39312305, 0x0f840a37, 0x67697223, 0x05274268, + 0x38393123, 0x23128409, 0x6e776f64, 0x3122e784, 0x11853939, 0x66656c22, 0x36202387, 0x62231185, 0x8568746f, 0x70752209, 0x512d8664, 0x32210526, + 0x05455b31, 0x42313221, 0x312006fc, 0x2105ad60, 0x66533132, 0x4f078205, 0x3120050b, 0x2006f34d, 0x050e5437, 0x50373221, 0x3f82057e, 0x20052443, + 0x06824431, 0x78563120, 0x20178205, 0x20958436, 0x06034433, 0x2d613320, 0x42322105, 0x82059e42, 0x20378507, 0x05565042, 0x30204f82, 0x37212f84, + 0x055c4346, 0xce503720, 0x42178205, 0x37200534, 0x8205f650, 0x2037850f, 0x057e5437, 0x4b440f82, 0x59372005, 0x0f820570, 0x20058c43, 0x053d6037, + 0xf6420f82, 0x59372005, 0x0f820580, 0x2005f642, 0x055d5d37, 0x4f353221, 0x352106f3, 0x2ae78538, 0x07333835, 0x6c626e64, 0x846b636f, 0x3835218f, + 0x35207f85, 0x2306f34f, 0x05373835, 0x70201d86, 0x3921258a, 0x852d8634, 0x4d35205d, 0x5d820567, 0x6c074423, 0x42278a66, 0x352006b5, 0x25066443, + 0x07393835, 0x1f8a7472, 0x21059c53, 0xa3623532, 0x85078205, 0x583520ed, 0x0f8205ee, 0x3521ed85, 0x059c4339, 0xcc433520, 0x43352006, 0x352006e4, + 0x8205435e, 0x05f64527, 0x4639352b, 0x73746c07, 0x65646168, 0x22058405, 0x856b6407, 0x6e752c07, 0x43353269, 0x69630646, 0x436c6372, 0x35200528, + 0x2105285d, 0x21563532, 0x41078205, 0x3520058a, 0x8205fb5a, 0x0562430f, 0xd1533520, 0x860f8205, 0x0541569c, 0x41353221, 0x352006b2, 0x82052156, + 0x0502420f, 0x86463521, 0x05986227, 0x45247682, 0x766e6909, 0x4d59798b, 0x41518205, 0x352005bc, 0x22055b53, 0x87453532, 0x05084681, 0x125e3520, + 0x86278205, 0x051a5ede, 0x69865182, 0x69864320, 0x0a45412b, 0x6c6c6966, 0x65726465, 0x050b4363, 0x94443520, 0x41352106, 0x2006a141, 0x55528630, + 0x322005c6, 0x82061d62, 0x41382007, 0x332005c9, 0xc5611f86, 0x35322205, 0x06e14133, 0x17873120, 0x95620f86, 0x62322005, 0x32210695, 0x05556035, + 0x4f420782, 0x06d35006, 0x5e543520, 0x41178205, 0x8e540644, 0x35322105, 0x82056654, 0x05a74207, 0x9d613520, 0x410f8205, 0x5d61060a, 0x860f8205, + 0x413520b7, 0x3b5106f9, 0x60352006, 0x578205a5, 0x54060241, 0x2f82056e, 0xc7853020, 0xaf863620, 0x8205d560, 0x54df8627, 0x0f820576, 0x5a06df42, + 0x37820568, 0x25611f86, 0x860f8205, 0x05305aaf, 0x41212f82, 0x055a4109, 0x786f6222, 0x49436185, 0x06264707, 0xaf603520, 0x35322105, 0x20069945, + 0x05b76035, 0xa1860f82, 0x20062647, 0x06664735, 0x79443520, 0x45352006, 0x352006a7, 0x20062e46, 0x05405535, 0x44353221, 0x35200659, 0x20065944, + 0x05f25a35, 0x21411782, 0x05b05806, 0x44353221, 0x35200639, 0x2806a144, 0x07334635, 0x61697274, 0x06444567, 0x36423522, 0x01450f85, 0x43352206, + 0x210f8530, 0x07857472, 0x85666c21, 0x061145cf, 0xd0553520, 0x41678205, 0x31450601, 0x57352006, 0x32200520, 0x20064764, 0x062f6132, 0x30353222, + 0x5f069442, 0x322105af, 0x05c05635, 0xb9411f82, 0x05ff5f06, 0xc3430f82, 0x06fd4806, 0x20583520, 0x422f8205, 0x125c06bc, 0x860f8205, 0x05785637, + 0x57353221, 0x77820580, 0x30208f86, 0x30211f86, 0x53b78531, 0x3520066d, 0x6006f249, 0x9782068f, 0x20062741, 0x06394237, 0x60067145, 0x322106b7, + 0x05385735, 0x27865f82, 0x07863120, 0x82053769, 0x2097866f, 0x63778630, 0xc782059f, 0xd0582786, 0x42af8205, 0x32200649, 0x4906c942, 0x352006ed, + 0x8205425d, 0x0611435f, 0x87863320, 0x8205125d, 0x5a578637, 0x8f8205f0, 0x8b522786, 0x5d352006, 0x2782052a, 0x58065f41, 0x27820558, 0x57068143, + 0xe7820520, 0x4a06b942, 0x3520061d, 0x20068d54, 0x06814635, 0x82062766, 0x52a78637, 0x352106e3, 0x06974234, 0x5f863220, 0x0f863320, 0x8205f25d, + 0x065f41b7, 0x2006f156, 0x05bf6435, 0x7f868f82, 0x8205b058, 0x597f8627, 0x322005c8, 0x82064766, 0x20578607, 0x5e578631, 0x2f82051a, 0x66065741, + 0x2782052f, 0x66061742, 0x0f82055f, 0x6f65a786, 0x35322105, 0x82054a5f, 0x41302007, 0x9f6505ef, 0x860f8205, 0x41312027, 0xca5d0677, 0x35322105, + 0x82052769, 0x06274207, 0x2106e353, 0x3f853136, 0x8f423620, 0x31362106, 0x20056f41, 0x05b05a36, 0x42363221, 0x362006df, 0x8205005a, 0x421f860f, + 0x3620067f, 0x20060945, 0x06df4136, 0x85333621, 0x5a3620d7, 0x2f820500, 0x7309392e, 0x656c696d, 0x65636166, 0x766e690c, 0x032b0c88, 0x066e7573, + 0x616d6566, 0x8304656c, 0x73053804, 0x65646170, 0x756c6304, 0x65680562, 0x07747261, 0x6d616964, 0x84646e6f, 0x6b3720df, 0x32220597, 0x5f853034, + 0xa05b3320, 0x410f8205, 0x33200567, 0x2b067945, 0x09333131, 0x69747365, 0x6574616d, 0x31203985, 0x21066941, 0x61413034, 0x42342005, 0x342006a1, + 0x20065941, 0x06854733, 0x85313421, 0x43342049, 0x33200689, 0x6c06e142, 0x32210629, 0x06994334, 0xa25b3420, 0x34322105, 0x20062b46, 0x06394134, + 0x8206396c, 0x06322517, 0x33463175, 0x20065841, 0x06de4c34, 0x8206506c, 0x052842b0, 0x86313421, 0x0680438e, 0x68433420, 0x46342006, 0x34200652, + 0x20069246, 0x06c84134, 0x3f4c3320, 0x30342706, 0x6f680539, 0xa5477375, 0x44312005, 0x332006fe, 0x2105a665, 0x49613332, 0x41078205, 0x43200626, + 0x2005ee41, 0x062e4233, 0xbc863320, 0x2b473120, 0x62312006, 0x322105e1, 0x20fc8633, 0x059e6533, 0x9643a582, 0x31342105, 0x20054e42, 0x06b04934, + 0x66413420, 0x41332006, 0xbd880786, 0x2005d642, 0x06864434, 0xfe443420, 0x42342006, 0x34200646, 0x21069644, 0x3e423034, 0x31342105, 0x1e435f86, + 0x41342006, 0x312006a4, 0x20068c41, 0x06124931, 0x3e453420, 0x30342506, 0x74610942, 0x28060d4b, 0x706d6110, 0x61737265, 0x077e576e, 0x4e620a21, + 0x0e20086e, 0x73231b8a, 0x89153330, 0x6562270e, 0x65726f66, 0x1582732e, 0x4a830720, 0x35307330, 0x756c7009, 0x6e642e73, 0x6d0a6d6f, 0x0a876e69, + 0x8305c74b, 0x88182015, 0x885f203d, 0x6c2e2509, 0x13616769, 0x5f207082, 0x830adc56, 0x87152013, 0x656b2713, 0x67697274, 0x29847468, 0x15840c20, + 0x20061955, 0x200c8610, 0x072a555f, 0x108a1820, 0x05525f20, 0x8714200b, 0x0c1a5218, 0x108b1483, 0x5b4f1320, 0x20398c05, 0x20d3830e, 0x84d8845f, + 0x890e88a9, 0x84112013, 0x84598c13, 0x0a3954f3, 0x108a1620, 0x1220168a, 0x128a3486, 0x12871420, 0x1c204f8b, 0xa18c148e, 0x656c1e24, 0xea547373, + 0x06f25506, 0x840cf955, 0x0c70541e, 0x128c1a20, 0x0d204c8c, 0x4f411a84, 0x87112007, 0x0861410d, 0x118b1520, 0x05411592, 0x412b840c, 0x2e250553, + 0x6167696c, 0x8c108a18, 0x840e2075, 0x08644118, 0x0e881620, 0x0f20258c, 0x65201684, 0x8508a655, 0x85718b9d, 0x08965647, 0x30841320, 0xaa560488, + 0x570e8405, 0x1c200e75, 0x768c148e, 0x1c8f1f20, 0x96853c8e, 0x20094954, 0x542f8417, 0x16201189, 0x9f413789, 0x20168a0c, 0x05e44261, 0x128a1720, + 0x1a20de8b, 0x848e178a, 0x1a942220, 0x7f85c78c, 0x4205164f, 0x1a4f0b70, 0x865f2006, 0x6c2e2407, 0x43616769, 0x6e2305c9, 0x43726d75, 0x0a8406c9, + 0x83057a41, 0x0868430a, 0x230f1954, 0x72616214, 0xaf545c85, 0x05ca430a, 0xc8531888, 0x43172006, 0x46540793, 0x5517870f, 0xe453060b, 0x90478409, + 0x8e162015, 0x885e862f, 0x0f6355a2, 0xa2891120, 0x13202a86, 0x3b541189, 0x83122008, 0x0d8d5513, 0x4d8fdb84, 0x27831920, 0x20149254, 0x0f1b4110, + 0x13550d20, 0x8e0f200c, 0x432020f6, 0x3e8f0fe3, 0x2c441820, 0x0a5e410c, 0x39951d20, 0x1f20dc86, 0xe8881d95, 0x568d1720, 0x15201788, 0x4d86178d, + 0x4d8f2120, 0x20108e41, 0x90218719, 0x961e2019, 0x415a863b, 0x6a411000, 0x0800410f, 0x1620188f, 0x5086728e, 0x4405e644, 0x32410934, 0x05c6440a, + 0x430f6141, 0x308a05b9, 0x19204886, 0x42084244, 0x244106da, 0x91122008, 0x8a14202c, 0x20278812, 0x4141891b, 0xed441016, 0x45169005, 0x3784052c, + 0x8a0d8642, 0x0f0841d6, 0x8d05f044, 0x8fea852e, 0x0e794629, 0x30737323, 0x0b5e4532, 0x18200f83, 0x20120d47, 0x2018822e, 0x85518534, 0x6c2e241d, + 0x84616769, 0x451d2015, 0x1d8417dc, 0x6b411520, 0x0e895705, 0x57062243, 0x27470970, 0x2d718212, 0x756d0b38, 0x61636973, 0x746f6e6c, 0x0b8a0e65, + 0x6c626428, 0x696e7507, 0xbf523330, 0x33302105, 0x82053361, 0x84352007, 0x6b322017, 0x302105a8, 0x05555732, 0x51323021, 0x0f820524, 0x1f843920, + 0x38303322, 0x372f0786, 0x61726709, 0x6f636576, 0x6109626d, 0x84747563, 0x201b8609, 0x20078642, 0x20078632, 0x20078643, 0x25078636, 0x69740941, + 0x318b646c, 0x19863420, 0x33208585, 0x2105c449, 0x734b3330, 0x86078205, 0x05ac491f, 0x6c4a3020, 0x33302106, 0x8205f34b, 0x09362b07, 0x6f726163, + 0x6c612e6e, 0xdf840c74, 0x2e363228, 0x65736163, 0xd47a640d, 0x200d8406, 0x083e780e, 0x0a200e84, 0x0a85c184, 0x0a84c284, 0x7b681121, 0x11840ac3, + 0x8f780f20, 0x200f8409, 0x836b850a, 0x620a255f, 0x65766572, 0x09241584, 0x676e6972, 0x0a200984, 0x0a84dd84, 0x0b790b20, 0x270b8405, 0x6465630c, + 0x616c6c69, 0x0d200c84, 0x200ca078, 0x787e8912, 0x10410795, 0x056c4d05, 0x3433302a, 0x6f740535, 0x0a736f6e, 0xda8d0584, 0x2108ac69, 0x1b714631, + 0x20078205, 0x069c6544, 0x07854520, 0x21057375, 0xb0524631, 0x46312105, 0x8205644b, 0x201f870f, 0x4b278546, 0x31210594, 0x05ab7046, 0x1f870782, + 0x1f853120, 0x0c464525, 0x82696e75, 0x84462017, 0x21148582, 0x14854446, 0x8a444621, 0x30432114, 0x45211c83, 0x05ae4b30, 0x41840782, 0x32200782, + 0x33201786, 0xee570785, 0x30452105, 0x8205b551, 0x551f8607, 0x452105f7, 0x05f75530, 0x17870782, 0x62073329, 0x65766572, 0x860c7963, 0x24748407, + 0x47494c03, 0x26008200, 0xff010001, 0x820f00ff, 0x3a02a909, 0x00cb00cb, 0x05990099, 0x04000062, 0xfe00001e, 0xff7b0555, 0xff3704e7, 0x8255fee7, + 0x251b8619, 0xdf05e7ff, 0x13831e04, 0x0b821d83, 0x00231f8e, 0x89dd0500, 0x1606213d, 0xa42e3f86, 0x7d00a400, 0x00017d00, 0x0c017efe, 0x0d8272fe, + 0x7f080f84, 0x7602f804, 0x6a020405, 0x202c00b0, 0x585500b0, 0x20205945, 0x0e00b84b, 0x06b04b51, 0xb0585a53, 0x28b01b34, 0x20666059, 0xb058558a, + 0xb9612502, 0x00080008, 0x62236363, 0xb021211b, 0x00b05900, 0xb2442343, 0x43000100, 0xb02d4260, 0x20b02c01, 0xb02d6660, 0x21232c02, 0xb02d2123, + 0x64202c03, 0x151403b3, 0xb0434200, 0x60204313, 0x02b14260, 0xb1424314, 0xb0430325, 0x78544302, 0x230cb020, 0x432a0882, 0x04b06461, 0x02b27850, + 0x46820202, 0x6521b024, 0x1583211c, 0x150eb226, 0x201c4201, 0x23250a82, 0x0113b242, 0x291b8213, 0x5000b023, 0xb2596558, 0x29830116, 0x04b02d2a, + 0x2b03b02c, 0x584315b0, 0xb0236f83, 0x86434316, 0x201b3e20, 0xc0b02064, 0x2604b050, 0x0128b25a, 0x6345430d, 0x4506b045, 0x03b02158, 0x5b525925, + 0x269c8258, 0x20588a1b, 0x825050b0, 0x59402512, 0x38b0201b, 0x38240983, 0xb1205959, 0x91822d85, 0x12822820, 0x20220d86, 0x0c8230b0, 0x8330b021, + 0x50c02e29, 0x20662058, 0x20618a8a, 0x58500ab0, 0x203b8260, 0x201b8320, 0x2009830a, 0x35098336, 0x601b6036, 0x1b595959, 0xb02502b0, 0xb063430c, + 0xb0585200, 0x2c834b00, 0x0f822120, 0xb04b1b23, 0x2625831e, 0xb8614b1e, 0x82630010, 0xb8632f11, 0x59620005, 0x59616459, 0x592b01b0, 0xe2852359, + 0x64205922, 0x232dcf82, 0xb02d5942, 0x45202c05, 0x2504b020, 0x2ed38261, 0x58504307, 0x422307b0, 0x422308b0, 0x8221211b, 0x2d602432, 0x842c06b0, + 0x2b0328fe, 0x07b16420, 0x83204262, 0x20ee831c, 0x83be851b, 0x05b02805, 0xb0634560, 0x82212a05, 0x2043241c, 0x828a208a, 0x30b1386b, 0x04b02505, + 0x60585126, 0x52611b50, 0x59235859, 0xb0205921, 0x82585340, 0x211b231b, 0x8a8740b0, 0x07b02d2a, 0x4309b02c, 0x0200b22b, 0x2005e641, 0x3a0e8208, + 0x20234223, 0x422300b0, 0x6202b061, 0x6301b066, 0xb06001b0, 0xb02d2a07, 0x83202c09, 0x430e26ad, 0x0004b863, 0x82228262, 0x604022af, 0x21228359, + 0x24824460, 0x0ab02d2c, 0x0e09b22c, 0x42454300, 0x3842212a, 0x2c0b2108, 0x200d4842, 0x2245850c, 0x82232b01, 0x32fa8217, 0x8a452060, 0x64206123, + 0x5020b020, 0x00b02158, 0x8230b01b, 0x1b202157, 0xa587a482, 0x2503b025, 0x85446123, 0x960d2062, 0x24b0213e, 0x3c823582, 0x348bda88, 0x842c0e21, + 0x0db325d0, 0x4503000c, 0x1b356582, 0x2a592123, 0x0fb02d21, 0x0202b12c, 0x6164b045, 0x10b02d44, 0x29c2822c, 0x0fb02020, 0x00b04a43, 0x08825850, + 0x59422324, 0x0d8310b0, 0x0d825220, 0x0d821020, 0x11b02d22, 0x10214882, 0x24f18362, 0x0004b820, 0x08b88263, 0x4311b027, 0x608a2060, 0x2311b020, + 0xb02d2342, 0x544b2c12, 0x6404b158, 0xb0245944, 0x7823650d, 0x2c13b02d, 0x4b58514b, 0x21148553, 0x1782211b, 0x17841320, 0xb12c143c, 0x55431200, + 0x1212b158, 0x6101b043, 0x2b11b042, 0x4300b059, 0x422502b0, 0x04830fb1, 0x04821020, 0x1601b024, 0xc9822023, 0xb158502d, 0x60430001, 0x422504b0, + 0x83208a8a, 0x2a102376, 0x36822321, 0x1b200b87, 0x32831f85, 0x61250223, 0x201d82b0, 0x20c98259, 0x23bf8247, 0x02b06047, 0x210dac41, 0xc241b020, + 0xb1310814, 0x23130000, 0x4301b044, 0xb23e00b0, 0x43010101, 0xb02d4260, 0xb1002c15, 0x54450200, 0x2312b058, 0xb0452042, 0xb042230e, 0x05b0230d, + 0xb0204260, 0x20118214, 0x2d838260, 0x011818b7, 0x13001100, 0x42424200, 0x1782608a, 0x1b82a882, 0x0814b12c, 0x2b8bb02b, 0x2d59221b, 0xec8216b0, + 0x2d2b1527, 0xb12c17b0, 0x23078301, 0x02b12c18, 0x19230783, 0x8303b12c, 0x2c1a2307, 0x078304b1, 0xb12c1b23, 0x23078305, 0x06b12c1c, 0x1d230783, + 0x8307b12c, 0x2c1e2307, 0x078308b1, 0xb12c1f23, 0x24078309, 0x20232c2b, 0x058841b0, 0x6006b02e, 0x2358544b, 0x01b02e20, 0x21211b5d, 0x2c206c82, + 0x16201c8a, 0x71201c88, 0x2d201c85, 0x26201c8a, 0x72201c88, 0x20251c85, 0x0fb0002c, 0x83f0972b, 0x85b520eb, 0x8be883eb, 0x822120df, 0x822020df, + 0x822220df, 0x200783df, 0x83df8223, 0x82242007, 0x200783df, 0x83df8225, 0x82262007, 0x200783df, 0x83df8227, 0x82282007, 0x200783df, 0x83df8229, + 0x822a2007, 0x320783df, 0x3c202c2e, 0x2d6001b0, 0x202c2fb0, 0x6018b060, 0x82234320, 0xb043240e, 0x82612502, 0x2eb03507, 0xb02d212a, 0x2fb02c30, + 0x2a2fb02b, 0x2c31b02d, 0x20472020, 0x2716d641, 0x23386123, 0x58558a20, 0x1b25219c, 0xb02d5921, 0x07eb4132, 0x060eb134, 0x01b04245, 0x2a31b016, + 0x150105b1, 0x59305845, 0x2082221b, 0x1e413320, 0x2323970a, 0x35202c34, 0x3520b984, 0x47854d82, 0x2f444520, 0x01b02211, 0x1484422b, 0x00231783, + 0x8300b416, 0x3e442700, 0x34b13823, 0xeb831501, 0x202c3623, 0x94c0823c, 0xb0602f33, 0x38614300, 0x2c37b02d, 0x2d3c172e, 0x2a9f38b0, 0x4301b023, + 0x082e8263, 0xb12c3933, 0x25160002, 0x47202e20, 0x422300b0, 0x492502b0, 0x23478a8a, 0x20612347, 0x211b6258, 0x2301b059, 0x0138b242, 0x2a141501, + 0x2c3ab02d, 0xb01600b0, 0x24268217, 0x04b02504, 0x2f268425, 0x42000cb1, 0x2b430bb0, 0x232e8a65, 0x8a3c2020, 0x3b205382, 0x2021268d, 0x2428842e, + 0x2306b020, 0x3e2d8742, 0x5060b020, 0x40b02058, 0x04b35851, 0x1b200520, 0x052604b3, 0x4242591a, 0x0ab02023, 0x828a2043, 0x2581827f, 0xb0604623, + 0xb7434306, 0x2060240f, 0x462b01b0, 0x0430059e, 0x23646043, 0x614305b0, 0xb0585064, 0x1b614304, 0x60240b82, 0x2503b059, 0x6120338f, 0xb0289a82, + 0x46232604, 0x231b3861, 0x46206182, 0x0682e782, 0x4f829784, 0x88826492, 0x232b0122, 0x60207e82, 0xb0236d82, 0x82612505, 0x82558f03, 0x20612451, + 0x832504b0, 0x82032084, 0x06524505, 0x59236b89, 0x413cb02d, 0x2025070b, 0x05b02020, 0x060b4126, 0x383c2325, 0x883db02d, 0x0ab0231a, 0x1f824223, + 0x47234622, 0x23216c82, 0x201b8261, 0x0842413e, 0x6941cc83, 0x00b02905, 0x202e5854, 0x1b21233c, 0x0220bd83, 0x54821485, 0x22088a41, 0x822506b0, + 0x484920a5, 0xc4410bc4, 0x11794205, 0x41236021, 0x232106ad, 0x20a48221, 0x20898a3f, 0x25a28643, 0x20b06020, 0xf28f6660, 0x2507e241, 0x20232c40, + 0x6982462e, 0x17b04635, 0x1b505843, 0x20585952, 0xb12e593c, 0x2b140130, 0x8c41b02d, 0x1b52221d, 0x201d8c50, 0x871d8c42, 0x8f4f8b3b, 0x2c432431, + 0x9b2b3ab0, 0x2c442e70, 0x8a2b3bb0, 0xb03c2020, 0x8a422306, 0x252a9938, 0x2e4306b0, 0xa28230b0, 0xf2844520, 0xb0250424, 0x79412604, 0xb0612405, + 0x4242230c, 0xb02205a9, 0x6d82430b, 0x2e203c24, 0xd0863823, 0xb12c462a, 0x4225040a, 0xb01600b0, 0x25203283, 0x202dd242, 0x47c54247, 0x2502b024, + 0xdd826146, 0x38233c26, 0x2020211b, 0x21082f42, 0xa7865921, 0xb12c4725, 0x412b3a00, 0x48200786, 0x3b230d82, 0x4123212b, 0xcd860617, 0x24080241, + 0x00b02c49, 0x05f64315, 0x0100b22d, 0x13141501, 0x2a36b02e, 0x964ab02d, 0x2c4b2817, 0x140100b1, 0x8237b013, 0x2c4c2323, 0x068239b0, 0x2a824d20, + 0x23451629, 0x46202e20, 0x4161238a, 0x4e30072d, 0x230ab02c, 0x2b4db042, 0x2c4fb02d, 0x460000b2, 0x50200882, 0x01200882, 0x51230883, 0x8401b22c, + 0x82522011, 0x20118408, 0x211a8253, 0x23824700, 0x08825420, 0x08830120, 0x1a825520, 0x56201184, 0x11840882, 0xb32c5726, 0x43000000, 0x58202482, + 0x01200982, 0x59230984, 0x8501b32c, 0x825a2013, 0x20138509, 0x221d825b, 0x82430100, 0x825c2027, 0x84012009, 0x825d2009, 0x2013851d, 0x8509825e, + 0x825f2013, 0x4500216a, 0x60202682, 0x01200882, 0x61200883, 0x11846a82, 0x08826220, 0x63201184, 0x00211a82, 0x20238248, 0x20088264, 0x20088301, + 0x841a8265, 0x82662011, 0x20118408, 0x20978467, 0x20248244, 0x83978468, 0x84692009, 0x20098397, 0x8397846a, 0x846b2009, 0x20098397, 0x8397846c, + 0x846d2009, 0x20098397, 0x8397846e, 0x2c6f2409, 0x413c00b1, 0x702008c0, 0xb0210d84, 0x205e8240, 0x200a8571, 0x240a8241, 0x00b02c72, 0x21268316, + 0x0d8242b0, 0xb12c7325, 0x842b3c01, 0x85742023, 0x2023830a, 0x83238475, 0x20238318, 0x203c8276, 0x2055883d, 0x840d8477, 0x85782031, 0x8241200a, + 0x85792047, 0x202e830a, 0x2047827a, 0x2052853d, 0x830a857b, 0x857c2020, 0x2020830a, 0x202b827d, 0x204f883e, 0x840d847e, 0x857f204f, 0x202e830a, + 0x200a8580, 0x205a8242, 0x20398281, 0x204f853e, 0x830a8582, 0x85832020, 0x2020830a, 0x202b8284, 0x204f883f, 0x840d8485, 0x8586204f, 0x8241200a, + 0x85872044, 0x202e830a, 0x20398288, 0x204f853f, 0x830a8589, 0x858a2020, 0x0820830a, 0xb22c8b21, 0x4503000b, 0x06b05850, 0x0204b21b, 0x23584503, + 0x59211b21, 0xb02b4259, 0x03b06508, 0x47785024, 0x2d2107d0, 0x2c008200, 0xc800b84b, 0x01b15852, 0xb0598e01, 0x05fe4d01, 0x00b1702d, 0x00b64207, + 0x21314100, 0x832a0005, 0x0c402d0c, 0x0446044e, 0x08260836, 0x0a050718, 0x52291286, 0x3e024a02, 0x1f062e06, 0x30128405, 0x13be420c, 0x0dc011c0, + 0x06c009c0, 0x00050040, 0x2426820b, 0x00be4211, 0x83018840, 0x00b92f13, 0x44000003, 0x880124b1, 0x40b05851, 0x0f835888, 0xb1446423, 0x220f8328, + 0x850008b8, 0x44002510, 0x27b11b59, 0xba291283, 0x01008008, 0x63884004, 0x82298454, 0x82592018, 0x402a0800, 0x4802500c, 0x28063802, 0x05051a06, + 0x01b82a0e, 0x04b085ff, 0x0002b18d, 0x6405b344, 0x44440006, 0x00000000, 0x00000100, 0xfa050000, 0xe203260b, +};++}
+ cbits/tracy/profiler/src/font/FontAwesomeSolid.hpp view
@@ -0,0 +1,12368 @@+// File: 'Font Awesome 6 Free-Solid-900.otf' (979228 bytes)+// Exported using binary_to_compressed_c.cpp++namespace tracy+{++static const unsigned int FontAwesomeSolid_compressed_size = 593052;+static const unsigned int FontAwesomeSolid_compressed_data[593052/4] =+{+ 0x0000bc57, 0x00000000, 0x1cf10e00, 0x00000400, 0x544f5308, 0x0a004f54, 0x03008000, 0x46432000, 0x522f2046, 0x00000560, 0x0d00a4ad, 0x53479364, + 0x7f4b4255, 0x0e0007fb, 0x0000fc27, 0x534f20c9, 0x4a61322f, 0x000073e2, 0x00001001, 0x6d636000, 0x185f7061, 0x00008835, 0x00006005, 0x656824a8, + 0xa7226461, 0x1b824bf4, 0x0382ac20, 0x82683621, 0x43042310, 0x0b82b107, 0x0382e420, 0x6d682426, 0x40eb7874, 0x0e2d0982, 0x00003812, 0x616dc415, + 0x71057078, 0x21108250, 0x04820801, 0x616e0627, 0x3b16656d, 0x292f82ee, 0x00007001, 0x6f70ed03, 0x97827473, 0xad211a82, 0x22048284, 0x82010020, + 0x05012e15, 0xae39cd00, 0x3c0f5f9d, 0x020b00f5, 0x23008300, 0x675704df, 0xff250789, 0x018002c0, 0x220f82c0, 0x82020008, 0x82028305, 0xc0012237, + 0x251382ff, 0x00008002, 0x0582ffff, 0x16830120, 0x05250389, 0x50000071, 0x2d058300, 0x02020400, 0x05008403, 0x4c010000, 0x21826601, 0x07864720, + 0x1900f523, 0x23858200, 0x03090002, 0x02821582, 0x22828020, 0x07821020, 0x41290287, 0x004d5357, 0xff200080, 0x236b85ff, 0x4000c001, 0x01201b82, + 0x00240382, 0xa5013901, 0x20220782, 0x05822900, 0x0e011623, 0x82158400, 0x001a220b, 0x200b866f, 0x205f8201, 0x200b8656, 0x207f8202, 0x240b8632, + 0x001f0003, 0x200b8637, 0x22238a04, 0x82320005, 0x2447853f, 0x00160006, 0x242386b3, 0x002c000a, 0x240b86c9, 0x0017000b, 0x240b8689, 0x00130010, + 0x200b86a0, 0x245f8411, 0x04010003, 0x23438209, 0x00d30134, 0x01240b85, 0xa1013200, 0x02240b86, 0x59010a00, 0x03240b86, 0x63013e00, 0x04200b86, + 0x0524238a, 0xf5006400, 0x06241786, 0x5b022c00, 0x0a240b86, 0x87025800, 0x0b240b86, 0x07022e00, 0x10240b86, 0x35022600, 0x11200b86, 0x23085f83, + 0x73726556, 0x206e6f69, 0x2e393637, 0x35393130, 0x35323133, 0x6f462820, 0x4120746e, 0x6f736577, 0x7620656d, 0x3a2c2285, 0x312e3620, 0x5329322e, + 0x64696c6f, 0x3626208c, 0x65724620, 0x18842065, 0x24842d20, 0x432d1e98, 0x7279706f, 0x74686769, 0x29632820, 0x28268b20, 0x70747468, 0x2f2f3a73, + 0x207a8266, 0x23798561, 0x6d6f632e, 0x12834992, 0x36209b86, 0x2d207883, 0x54387884, 0x77206568, 0x73276265, 0x736f6d20, 0x6f702074, 0x616c7570, + 0x63692072, 0x2b08dc82, 0x20746573, 0x20646e61, 0x6c6f6f74, 0x2e74696b, 0x65005600, 0x73007200, 0x6f006900, 0x20006e00, 0x36003700, 0x2e003900, + 0x31003000, 0x35220782, 0x07823300, 0x35003222, 0x28221982, 0x23844600, 0x0b827420, 0x77004122, 0x73203782, 0x6d200f82, 0x20220782, 0x458c7600, + 0x21823a20, 0x43823620, 0x03823120, 0x29003224, 0x27825300, 0x61826c20, 0x419a6420, 0x33823620, 0x89824620, 0x4f846520, 0x2d203189, 0x2e208f82, + 0x2e228382, 0x3db23200, 0x79824320, 0x79007022, 0x69265782, 0x68006700, 0xc7847400, 0x93826320, 0x4d982020, 0x74282583, 0x73007000, 0x2f003a00, + 0x66200182, 0x6120f586, 0x2e22f38c, 0xfd846300, 0x8b191341, 0x412587d1, 0x36200d37, 0x72208382, 0x6522ef82, 0x23412d00, 0x8254200a, 0x826520a7, + 0x827720a7, 0x00622219, 0x22878227, 0x826d0020, 0x8473206b, 0x847020bd, 0x007524d1, 0x8261006c, 0x002022d5, 0x20878469, 0x202f826e, 0x202f8273, + 0x24078274, 0x006e0061, 0x20078264, 0x20298274, 0x2227826f, 0x8269006b, 0x002e2139, 0x04200084, 0x03200582, 0x24200382, 0x0b820382, 0x00c03e25, + 0x84010003, 0x00033c0f, 0x3e00000a, 0x3e0400c0, 0x0f00009c, 0x00000830, 0x0030070a, 0x00220021, 0x82260025, 0x00282686, 0x002b0029, 0x36aa822c, + 0x002f002e, 0x003a0039, 0x005a003b, 0x005c005b, 0x005e005d, 0x8260005f, 0x82622090, 0x8264208c, 0x00662286, 0x24c48267, 0x006a0069, 0x2080826b, + 0x2490826d, 0x0070006f, 0x83b08271, 0xe20e07c4, 0x00760075, 0x00780077, 0x007a0079, 0x007c007b, 0x007e007d, 0x0080007f, 0x00820081, 0x00840083, + 0x00860085, 0x00880087, 0x008a0089, 0x008c008b, 0x008e008d, 0x0090008f, 0x00920091, 0x00940093, 0x00960095, 0x00980097, 0x009a0099, 0x009c009b, + 0x009e009d, 0x00a0009f, 0x00a200a1, 0x00a400a3, 0x00a600a5, 0x00a800a7, 0x00aa00a9, 0x00ac00ab, 0x00ae00ad, 0x00b000af, 0x00b200b1, 0x00b400b3, + 0x00b600b5, 0x00b800b7, 0x00ba00b9, 0x00bc00bb, 0x00be00bd, 0x00c000bf, 0x00c200c1, 0x00c400c3, 0x00c600c5, 0x00c800c7, 0x00ca00c9, 0x00cc00cb, + 0x00ce00cd, 0x00d000cf, 0x00d200d1, 0x00d400d3, 0x00d600d5, 0x00d800d7, 0x00da00d9, 0x00dc00db, 0x00de00dd, 0x00e000df, 0x00e200e1, 0x00e400e3, + 0x00e600e5, 0x00e800e7, 0x00ea00e9, 0x00ec00eb, 0x00ee00ed, 0x00f000ef, 0x00f200f1, 0x00f400f3, 0x00f600f5, 0x00f800f7, 0x00fa00f9, 0x00fc00fb, + 0x00fe00fd, 0x010001ff, 0x01020101, 0x01040103, 0x01060105, 0x01080107, 0x010a0109, 0x010c010b, 0x010e010d, 0x0110010f, 0x01120111, 0x01140113, + 0x01160115, 0x01180117, 0x011a0119, 0x011c011b, 0x011e011d, 0x0120011f, 0x01220121, 0x01240123, 0x01260125, 0x01280127, 0x012a0129, 0x012c012b, + 0x012e012d, 0x0130012f, 0x01320131, 0x01340133, 0x01360135, 0x01380137, 0x013a0139, 0x013c013b, 0x013e013d, 0x0140013f, 0x01420141, 0x01440143, + 0x01460145, 0x01480147, 0x014a0149, 0x014c014b, 0x014e014d, 0x0150014f, 0x01520151, 0x01540153, 0x01560155, 0x01580157, 0x015a0159, 0x015c015b, + 0x015e015d, 0x0160015f, 0x01620161, 0x01640163, 0x01660165, 0x01680167, 0x016a0169, 0x016c016b, 0x016e016d, 0x0170016f, 0x01720171, 0x01740173, + 0x01760175, 0x01780177, 0x017a0179, 0x017c017b, 0x017e017d, 0x0180017f, 0x01820181, 0x01840183, 0x01860185, 0x01880187, 0x018a0189, 0x018c018b, + 0x018e018d, 0x0190018f, 0x01920191, 0x01940193, 0x01960195, 0x01980197, 0x019a0199, 0x019c019b, 0x019e019d, 0x01a0019f, 0x01a201a1, 0x01a401a3, + 0x01a601a5, 0x01a801a7, 0x01aa01a9, 0x01ac01ab, 0x01ae01ad, 0x01b001af, 0x01b201b1, 0x01b401b3, 0x01b601b5, 0x01b801b7, 0x01ba01b9, 0x01bc01bb, + 0x01be01bd, 0x01c001bf, 0x01c201c1, 0x01c401c3, 0x01c601c5, 0x01c801c7, 0x01ca01c9, 0x01cc01cb, 0x01ce01cd, 0x01d001cf, 0x01d201d1, 0x01d401d3, + 0x01d601d5, 0x01d801d7, 0x01da01d9, 0x01dc01db, 0x01de01dd, 0x01e001df, 0x01e201e1, 0x01e401e3, 0x01e601e5, 0x01e801e7, 0x01ea01e9, 0x01ec01eb, + 0x01ee01ed, 0x01f001ef, 0x01f201f1, 0x01f401f3, 0x01f601f5, 0x01f801f7, 0x01fa01f9, 0x01fc01fb, 0x01fe01fd, 0x020002ff, 0x02020201, 0x02040203, + 0x02060205, 0x02080207, 0x020a0209, 0x020c020b, 0x020e020d, 0x0210020f, 0x02120211, 0x02140213, 0x02160215, 0x02180217, 0x021a0219, 0x021c021b, + 0x021e021d, 0x0220021f, 0x02220221, 0x02240223, 0x02260225, 0x02280227, 0x022a0229, 0x022c022b, 0x022e022d, 0x0230022f, 0x02320231, 0x02340233, + 0x02360235, 0x02380237, 0x023a0239, 0x023c023b, 0x023e023d, 0x0240023f, 0x02420241, 0x02440243, 0x02460245, 0x02480247, 0x024a0249, 0x024c024b, + 0x024e024d, 0x0250024f, 0x02520251, 0x02540253, 0x02560255, 0x02580257, 0x025a0259, 0x025c025b, 0x025e025d, 0x0260025f, 0x02620261, 0x02640263, + 0x02660265, 0x02680267, 0x026a0269, 0x026c026b, 0x026e026d, 0x0270026f, 0x02720271, 0x02740273, 0x02760275, 0x02780277, 0x027a0279, 0x027c027b, + 0x027e027d, 0x0280027f, 0x02820281, 0x02840283, 0x02860285, 0x02880287, 0x028a0289, 0x028c028b, 0x028e028d, 0x0290028f, 0x02920291, 0x02940293, + 0x02960295, 0x02980297, 0x029a0299, 0x029c029b, 0x029e029d, 0x02a0029f, 0x02a202a1, 0x02a402a3, 0x02a602a5, 0x02a802a7, 0x02aa02a9, 0x02ac02ab, + 0x02ae02ad, 0x02b002af, 0x02b202b1, 0x02b402b3, 0x02b602b5, 0x02b802b7, 0x02ba02b9, 0x02bc02bb, 0x02be02bd, 0x02c002bf, 0x02c202c1, 0x02c402c3, + 0x02c602c5, 0x02c802c7, 0x02ca02c9, 0x02cc02cb, 0x02ce02cd, 0x02d002cf, 0x02d202d1, 0x02d402d3, 0x02d602d5, 0x02d802d7, 0x02da02d9, 0x02dc02db, + 0x02de02dd, 0x02e002df, 0x02e202e1, 0x02e402e3, 0x02e602e5, 0x02e802e7, 0x02ea02e9, 0x02ec02eb, 0x02ee02ed, 0x02f002ef, 0x02f202f1, 0x02f402f3, + 0x02f602f5, 0x02f802f7, 0x02fa02f9, 0x02fc02fb, 0x02fe02fd, 0x030003ff, 0x03020301, 0x03040303, 0x03060305, 0x03080307, 0x030a0309, 0x030c030b, + 0x030e030d, 0x0310030f, 0x03120311, 0x03140313, 0x03160315, 0x03180317, 0x031a0319, 0x031c031b, 0x031e031d, 0x0320031f, 0x03220321, 0x03240323, + 0x03260325, 0x03280327, 0x032a0329, 0x032c032b, 0x032e032d, 0x0330032f, 0x03320331, 0x03340333, 0x03360335, 0x03380337, 0x033a0339, 0x033c033b, + 0x033e033d, 0x0340033f, 0x03420341, 0x03440343, 0x03460345, 0x03480347, 0x034a0349, 0x034c034b, 0x034e034d, 0x0350034f, 0x03520351, 0x03540353, + 0x03560355, 0x03580357, 0x035a0359, 0x035c035b, 0x035e035d, 0x0360035f, 0x03620361, 0x03640363, 0x03660365, 0x03680367, 0x036a0369, 0x036c036b, + 0x036e036d, 0x0370036f, 0x03720371, 0x03740373, 0x03760375, 0x03780377, 0x037a0379, 0x037c037b, 0x037e037d, 0x0380037f, 0x03820381, 0x03840383, + 0x03860385, 0x03880387, 0x038a0389, 0x038c038b, 0x038e038d, 0x0390038f, 0x03920391, 0x03940393, 0x03960395, 0x03980397, 0x039a0399, 0x039c039b, + 0x039e039d, 0x03a0039f, 0x03a203a1, 0x03a403a3, 0x03a603a5, 0x03a803a7, 0x03aa03a9, 0x03ac03ab, 0x03ae03ad, 0x03b003af, 0x03b203b1, 0x03b403b3, + 0x03b603b5, 0x03b803b7, 0x03ba03b9, 0x03bc03bb, 0x03be03bd, 0x03c003bf, 0x03c203c1, 0x03c403c3, 0x03c603c5, 0x03c803c7, 0x03ca03c9, 0x03cc03cb, + 0x03ce03cd, 0x03d003cf, 0x03d203d1, 0x03d403d3, 0x03d603d5, 0x03d803d7, 0x03da03d9, 0x03dc03db, 0x03de03dd, 0x03e003df, 0x03e203e1, 0x03e403e3, + 0x03e603e5, 0x03e803e7, 0x03ea03e9, 0x03ec03eb, 0x03ee03ed, 0x03f003ef, 0x03f203f1, 0x03f403f3, 0x03f603f5, 0x03f803f7, 0x03fa03f9, 0x03fc03fb, + 0x03fe03fd, 0x040004ff, 0x04020401, 0x04040403, 0x04060405, 0x04080407, 0x040a0409, 0x040c040b, 0x040e040d, 0x0410040f, 0x04120411, 0x04140413, + 0x04160415, 0x04180417, 0x041a0419, 0x041c041b, 0x041e041d, 0x0420041f, 0x04220421, 0x04240423, 0x04260425, 0x04280427, 0x042a0429, 0x042c042b, + 0x042e042d, 0x0430042f, 0x04320431, 0x04340433, 0x04360435, 0x04380437, 0x043a0439, 0x043c043b, 0x043e043d, 0x0440043f, 0x04420441, 0x04440443, + 0x04460445, 0x04480447, 0x044a0449, 0x044c044b, 0x044e044d, 0x0450044f, 0x04520451, 0x04540453, 0x04560455, 0x04580457, 0x045a0459, 0x045c045b, + 0x045e045d, 0x0460045f, 0x04620461, 0x04640463, 0x04660465, 0x04680467, 0x046a0469, 0x046c046b, 0x046e046d, 0x0470046f, 0x04720471, 0x04740473, + 0x04760475, 0x04780477, 0x047a0479, 0x047c047b, 0x047e047d, 0x0480047f, 0x04820481, 0x04840483, 0x04860485, 0x04880487, 0x048a0489, 0x048c048b, + 0x048e048d, 0x0490048f, 0x04920491, 0x04940493, 0x04960495, 0x04980497, 0x049a0499, 0x049c049b, 0x049e049d, 0x04a0049f, 0x04a204a1, 0x04a404a3, + 0x04a604a5, 0x04a804a7, 0x04aa04a9, 0x04ac04ab, 0x04ae04ad, 0x04b004af, 0x04b204b1, 0x04b404b3, 0x04b604b5, 0x04b804b7, 0x04ba04b9, 0x04bc04bb, + 0x04be04bd, 0x04c004bf, 0x04c204c1, 0x04c404c3, 0x04c604c5, 0x04c804c7, 0x04ca04c9, 0x04cc04cb, 0x04ce04cd, 0x04d004cf, 0x04d204d1, 0x04d404d3, + 0x04d604d5, 0x04d804d7, 0x04da04d9, 0x04dc04db, 0x04de04dd, 0x04e004df, 0x04e204e1, 0x04e404e3, 0x04e604e5, 0x04e804e7, 0x04ea04e9, 0x04ec04eb, + 0x04ee04ed, 0x04f004ef, 0x04f204f1, 0x04f404f3, 0x04f604f5, 0x04f804f7, 0x04fa04f9, 0x04fc04fb, 0x04fe04fd, 0x050005ff, 0x05020501, 0x05040503, + 0x05060505, 0x05080507, 0x050a0509, 0x050c050b, 0x050e050d, 0x0510050f, 0x05120511, 0x05140513, 0x05160515, 0x05180517, 0x051a0519, 0x051c051b, + 0x051e051d, 0x0520051f, 0x05220521, 0x05240523, 0x05260525, 0x05280527, 0x052a0529, 0x052c052b, 0x052e052d, 0x200b202f, 0x20112010, 0x20142013, + 0x20192018, 0x201d201c, 0x20212020, 0x20302026, 0x20332032, 0x203a2039, 0x20a820a4, 0x20aa20a9, 0x20b420ac, 0x21bd20b8, 0x21902122, 0x21922191, + 0x21942193, 0x21972195, 0x21bb21ba, 0x221222c4, 0x2303231e, 0x231b2304, 0x23292328, 0x232b232a, 0x23cf2399, 0x23ea23e9, 0x23ee23ed, 0x23f323f1, + 0x23f923f8, 0x24fe23fb, 0x25a025bd, 0x25cf25b6, 0x25fb25d0, 0x260026fc, 0x26032601, 0x26112604, 0x261d2615, 0x26222620, 0x26252623, 0x262c262a, + 0x262f262e, 0x26392638, 0x2640263f, 0x265a2642, 0x265c265b, 0x265e265d, 0x2665265f, 0x26722666, 0x267b267a, 0x2680267e, 0x26822681, 0x26842683, + 0x26932685, 0x26992696, 0x26a0269b, 0x26a226a1, 0x26a426a3, 0x26a626a5, 0x26a826a7, 0x26aa26a9, 0x26b226ab, 0x26be26bd, 0x26c526c4, 0x26df26c6, + 0x26ea26e9, 0x26fa26f7, 0x270027fd, 0x27042702, 0x27092705, 0x270b270a, 0x270f270c, 0x27122711, 0x27142713, 0x27162715, 0x2721271d, 0x27442731, + 0x274c2746, 0x2753274e, 0x27552754, 0x27642757, 0x27962795, 0x29342997, 0x2b0d2b35, 0x2b1c2b1b, 0xe0502b24, 0xe00de006, 0xe041e012, 0xe086e076, + 0xe09ae098, 0xe0ace0a9, 0xe0b7e0b4, 0xe0cfe0bb, 0xe0dfe0d8, 0xe131e1e4, 0xe140e13c, 0xe163e152, 0xe16de169, 0xe185e17b, 0xe19be18f, 0xe1b0e1a8, + 0xe1c4e1bc, 0xe1d3e1c8, 0xe1d7e1d5, 0xe1f3e1ed, 0xe2fee1f6, 0xe222e209, 0xe23de22d, 0xe29ce289, 0xe2bbe2b7, 0xe2cae2c5, 0xe3ebe2ce, 0xe3afe31e, + 0xe4f5e3b2, 0xe445e43c, 0xe46ce448, 0xe477e473, 0xe490e47b, 0xe4a5e494, 0xe4b0e4ad, 0xe4cce4b3, 0xe4e6e4de, 0xe4ede4eb, 0xe503e5ee, 0xe52fe525, + 0xe558e54f, 0xe574e56f, 0xe58fe587, 0xe59de59a, 0xe5aae5a1, 0xf0b4e5af, 0xf003f002, 0xf006f005, 0xf013f00e, 0xf015f014, 0xf019f016, 0xf01bf01a, + 0xf01df01c, 0xf03ef01e, 0xf044f040, 0xf046f045, 0xf05bf04e, 0xf05df05c, 0xf066f05e, 0xf068f067, 0xf06ef069, 0xf080f07e, 0xf087f086, 0xf089f088, + 0xf08bf08a, 0xf091f08e, 0xf096f095, 0xf098f097, 0xf0a1f09e, 0xf0aef0a2, 0xf0cef0b2, 0xf0def0d1, 0xf0e3f0e0, 0xf0e5f0e4, 0xf0eef0e6, 0xf0f5f0f4, + 0xf0f7f0f6, 0xf107f1fe, 0xf10bf108, 0xf10ef10c, 0xf112f111, 0xf115f114, 0xf11df11c, 0xf122f11e, 0xf127f123, 0xf129f128, 0xf12ef12a, 0xf13af135, + 0xf146f13e, 0xf14ef147, 0xf155f154, 0xf15ef159, 0xf178f165, 0xf188f183, 0xf190f18e, 0xf195f193, 0xf197f196, 0xf19df199, 0xf1b0f1ae, 0xf1b3f1b1, + 0xf1c9f1bb, 0xf1d8f1ce, 0xf1daf1d9, 0xf1def1db, 0xf1ecf1e6, 0xf1f7f1f6, 0xf1faf1f9, 0xf201f2fe, 0xf20bf207, 0xf22df21e, 0xf239f236, 0xf24af249, + 0xf250f24e, 0xf26cf25d, 0xf278f277, 0xf27bf27a, 0xf28bf283, 0xf28df28c, 0xf291f28e, 0xf295f292, 0xf29cf29a, 0xf2a4f29e, 0xf2b6f2a8, 0xf2b9f2b7, + 0xf2bbf2ba, 0xf2bdf2bc, 0xf2c0f2be, 0xf2c3f2c2, 0xf2d3f2ce, 0xf2dcf2d4, 0xf2e7f2e5, 0xf2edf2ea, 0xf2f6f2f2, 0xf3fef2f9, 0xf30cf305, 0xf31ef31c, + 0xf332f328, 0xf35bf338, 0xf360f35d, 0xf381f363, 0xf387f382, 0xf3a5f390, 0xf3c1f3bf, 0xf3c9f3c5, 0xf3d1f3cf, 0xf3e0f3dd, 0xf3edf3e5, 0xf3fdf3fb, + 0xf406f4ff, 0xf422f410, 0xf425f424, 0xf436f434, 0xf43cf43a, 0xf441f43f, 0xf445f443, 0xf44bf447, 0xf450f44e, 0xf458f453, 0xf45ff45d, 0xf466f462, + 0xf472f46d, 0xf479f474, 0xf47ff47d, 0xf487f482, 0xf48ef48b, 0xf497f494, 0xf4a1f49e, 0xf4b3f4ad, 0xf4bef4ba, 0xf4c4f4c2, 0xf4cef4c6, 0xf4dbf4d3, + 0xf4e3f4df, 0xf509f5e6, 0xf52cf52b, 0xf531f530, 0xf536f535, 0xf541f540, 0xf59df591, 0xf5a7f5a2, 0xf5b4f5b1, 0xf5bdf5b8, 0xf5cbf5c5, 0xf5d2f5ce, + 0xf5daf5d7, 0xf5dff5dc, 0xf5e4f5e1, 0xf5ebf5e7, 0xf6fdf5ee, 0xf604f601, 0xf613f610, 0xf61ff619, 0xf625f621, 0xf630f62a, 0xf63cf637, 0xf644f641, + 0xf64af647, 0xf651f64f, 0xf658f655, 0xf662f65e, 0xf66bf666, 0xf66ff66d, 0xf676f674, 0xf67cf679, 0xf684f67f, 0xf696f689, 0xf6a1f69b, 0xf6a9f6a7, + 0xf6b7f6ad, 0xf6bef6bb, 0xf6c4f6c0, 0xf6cff6c8, 0xf6d3f6d1, 0xf6d7f6d5, 0xf6def6d9, 0xf6e6f6e3, 0xf6edf6e8, 0xf6faf6f2, 0xf700f7fc, 0xf70ef70c, + 0xf717f715, 0xf722f71e, 0xf72bf729, 0xf73df72f, 0xf743f740, 0xf74df747, 0xf756f753, 0xf75ff75b, 0xf76cf769, 0xf773f770, 0xf781f77d, 0xf788f784, + 0xf794f78c, 0xf79cf796, 0xf7a2f7a0, 0xf7abf7a6, 0xf7b6f7ae, 0xf7bdf7ba, 0xf7c2f7c0, 0xf7caf7c5, 0xf7d0f7ce, 0xf7daf7d2, 0xf7ecf7e6, 0xf7f3f7ef, + 0xf7f7f7f5, 0xf802f8fb, 0xf80af807, 0xf80cf80b, 0xf810f80d, 0xf816f812, 0xf81df818, 0xf82ff82a, 0xf84af83e, 0xf850f84c, 0xf85ef853, 0xf86df863, + 0xf87df879, 0xf887f882, 0xf897f891, 0xf8ccf8c1, 0xf8d9f8d7, 0xf8eff8e5, 0x00ffffff, 0x00200000, 0x4f230022, 0x2a200831, 0x2608314f, 0x003a0030, + 0x103c003b, 0xf80a310f, 0x0de0052c, 0x3fe012e0, 0x85e059e0, 0x314f97e0, 0xe1e32412, 0x4f39e131, 0x84240c31, 0x9ae18fe1, 0x201a314f, 0x10314f21, + 0x314fcd20, 0x4fb12006, 0x47280631, 0x73e46ce4, 0x7ae476e4, 0x0806314f, 0xafe4a83a, 0xb5e4b3e4, 0xe0e4cee4, 0xede4e8e4, 0xefe4eee4, 0x27e507e5, + 0x51e532e5, 0x71e55ae5, 0x89e576e5, 0x9ce591e5, 0xa9e5a0e5, 0xb4e5afe5, 0x03f000f0, 0x06f004f0, 0x10f007f0, 0x2006314f, 0x0a314f17, 0x40f0212c, + 0x45f041f0, 0x47f046f0, 0x314f50f0, 0x4f602006, 0x6a260631, 0x80f070f0, 0x314f83f0, 0xf08d240a, 0x4f93f090, 0x9c320631, 0xa2f0a0f0, 0xb0f0a3f0, + 0xd0f0c0f0, 0xe0f0d6f0, 0x314fe2f0, 0xf0e72206, 0x06314ff0, 0x00f1f82c, 0x09f108f1, 0x0df10cf1, 0x314f10f1, 0xf1182a06, 0xf11ef11d, 0xf123f120, + 0x06314f24, 0xf12b2208, 0xf137f130, 0xf140f13d, 0xf148f147, 0xf155f150, 0xf15bf156, 0xf175f160, 0xf185f182, 0xf190f18e, 0x08314f91, 0xabf19c2e, + 0xb1f1b0f1, 0xb8f1b2f1, 0xcdf1c0f1, 0x0808314f, 0xe0f1dc2e, 0xf6f1eaf1, 0xf8f1f7f1, 0xfbf1faf1, 0x04f200f2, 0x17f20af2, 0x33f221f2, 0x40f238f2, + 0x4df24af2, 0x51f250f2, 0x71f26cf2, 0x79f278f2, 0x200c314f, 0x08314f90, 0xa0f29d26, 0xb4f2a7f2, 0x2a10314f, 0xf2c3f2c1, 0xf2d0f2c7, 0x4fdbf2d4, + 0xf12a0831, 0xf9f2f5f2, 0x02f3fef2, 0x314f09f3, 0xf3373408, 0xf35df358, 0xf362f360, 0xf382f381, 0xf390f386, 0x4fbef3a5, 0xcd200631, 0x200a314f, + 0x0e314ffa, 0x36f43224, 0x314f39f4, 0xf45c3e16, 0xf461f45f, 0xf468f466, 0xf474f470, 0xf47df477, 0xf481f47e, 0xf48bf484, 0xf490f48d, 0x08314f96, + 0xf4b83e08, 0xf4c0f4bd, 0xf4c6f4c4, 0xf4d3f4cd, 0xf4def4d6, 0xf4e6f4e2, 0xf515f5fa, 0xf52df52c, 0xf532f531, 0xf537f536, 0xf542f541, 0xf59ff593, + 0xf5aaf5a4, 0xf5b6f5b3, 0xf5bff5ba, 0xf5cdf5c7, 0x06314fd0, 0x314fde20, 0x4ffc200a, 0x24280e31, 0x2ef629f6, 0x3bf637f6, 0x2a0c314f, 0xf658f653, + 0xf662f65d, 0x4f69f664, 0x782e0831, 0x7ff67bf6, 0x87f681f6, 0x98f696f6, 0x314fa0f6, 0x4fb62006, 0xc3200631, 0x360e314f, 0xf6e2f6dd, 0xf6e8f6e6, + 0xf6f0f6ec, 0xf6fcf6fa, 0xf70bf7ff, 0x4f14f70e, 0x28260631, 0x2ef72bf7, 0x314f3bf7, 0x51500808, 0x5af756f7, 0x69f75ef7, 0x6ff76bf7, 0x7cf772f7, + 0x83f780f7, 0x8cf786f7, 0x96f793f7, 0x9ff79cf7, 0xa4f7a2f7, 0xadf7a9f7, 0xb9f7b5f7, 0xbff7bdf7, 0xc4f7c2f7, 0xccf7c9f7, 0xd2f7d0f7, 0xe4f7d7f7, + 0xeff7ecf7, 0xf5f7f2f7, 0xfaf7f7f7, 0x05f802f8, 0x2a08314f, 0xf812f80f, 0xf818f815, 0x4f27f81d, 0x7b2a1431, 0x84f881f8, 0x97f891f8, 0x314fc0f8, + 0xe1ff260d, 0xe0ff0000, 0x25008600, 0x0000dcff, 0x0c83dbff, 0x84d9ff21, 0x83d72005, 0x03001005, 0xe021a509, 0xa7091027, 0xb9084b01, 0x28202e20, + 0xf81f2420, 0xd31fe11f, 0xc21fc31f, 0xb21fb41f, 0xa91fab1f, 0x0000a61f, 0x841f8a1f, 0x351f811f, 0x2b1f2e1f, 0x0a1f1a1f, 0x021f051f, 0xed1ef51e, + 0xda1ee41e, 0xc71ece1e, 0xb51ebc1e, 0xa81eb21e, 0xa61ea71e, 0x8c1e911e, 0x831e8a1e, 0x621e791e, 0x491e581e, 0xec1dfe1d, 0xcf1dd21d, 0xc21dc61d, + 0xa41dc01d, 0xe21c721d, 0x9f1ce11c, 0x511c591c, 0x2d1c501c, 0x251c271c, 0x0f1c231c, 0xfc1b0c1c, 0xf91bfa1b, 0xf61bf71b, 0xf41bf51b, 0xf21bf31b, + 0xf11b0000, 0xed1bee1b, 0xea1beb1b, 0xe81be91b, 0xe61be71b, 0xe41be51b, 0xdb1be21b, 0xd31bd71b, 0x00008811, 0x03828711, 0x85118622, 0x84200582, + 0x83210382, 0x27008200, 0x00008111, 0x7e118011, 0x7c200582, 0x00240e82, 0x79117a11, 0x77260784, 0x00007611, 0x03827511, 0x73117426, 0x70117211, + 0x6e2a1584, 0x6d110000, 0x6b116c11, 0x0f846a11, 0x65116834, 0x00006411, 0x62116311, 0x54115511, 0x4f115011, 0x19834e11, 0x4b221382, 0x09864a11, + 0x46114726, 0x45110000, 0x44220382, 0x13864311, 0x0d823d20, 0x3b113c22, 0x3a200582, 0x39200382, 0x38280382, 0x36113711, 0x33113411, 0x32220b82, + 0x05823111, 0x2f11302a, 0x1f112e11, 0x15111611, 0x113b3583, 0x000c110d, 0x110b1100, 0x1008110a, 0x00fa10fb, 0x10f91000, 0x10f110f5, 0x82e510ee, + 0x82e4200b, 0x10e32603, 0x10df10e2, 0x200982d6, 0x300382d5, 0x10d310d4, 0x10cf10d1, 0x10c210c4, 0x10bc10bd, 0x201382b6, 0x240382b3, 0x10a310b1, + 0x2007829f, 0x2555839e, 0x00008e10, 0x03828d10, 0x0d848b20, 0x0000832a, 0x80108110, 0x73107e10, 0x71200982, 0xf9820382, 0x846f1021, 0x006c261b, + 0x10681000, 0x3a058267, 0x10581060, 0x10551057, 0x10501053, 0x104c104e, 0x10451048, 0x10331042, 0x82291032, 0x0f1b281d, 0x0ffb0ffc, 0x83f80ff9, + 0x0f270835, 0x0fce0fd6, 0x0fa20fba, 0x0f9e0fa1, 0x0f980f9b, 0x0f8c0f97, 0x0f860f8a, 0x00730f7f, 0x0f700f00, 0x0f610f6a, 0x824f0f50, 0x422a080b, + 0x3f0f410f, 0x3c0f3e0f, 0x3a0f3b0f, 0x380f390f, 0x330f350f, 0x300f320f, 0x290f2c0f, 0x270f280f, 0x230f240f, 0x200f210f, 0x2d821e0f, 0x0f1a2808, + 0x0f180f19, 0x0f140f15, 0x0f120f13, 0x0e00000c, 0x0ef90efe, 0x0ef30ef5, 0x0ef10ef2, 0x0eea0ef0, 0x0ee40ee6, 0x82e00ee2, 0x0eca2219, 0x200582bf, + 0x200382be, 0x200382bd, 0x090382bc, 0xba0ebb11, 0xb80eb90e, 0xb50eb60e, 0xb30eb40e, 0xb10eb20e, 0xaf0eb00e, 0xa90eab0e, 0xa70ea80e, 0xa40ea60e, + 0x9f0ea20e, 0x900e9d0e, 0x8b0e8d0e, 0x7e0e800e, 0x740e790e, 0x710e730e, 0x6b0e6e0e, 0x620e650e, 0x5c0e5e0e, 0x580e5a0e, 0x530e540e, 0x500e520e, + 0x490e4c0e, 0x460e480e, 0x440e450e, 0x3f0e400e, 0x3d0e3e0e, 0x3a0e3b0e, 0x2c0e380e, 0x270e2b0e, 0x210e220e, 0x160e1e0e, 0x110e130e, 0x0e0e100e, + 0x050e0b0e, 0x030e040e, 0x010e020e, 0xfd0d000e, 0xf80dfa0d, 0xf40df70d, 0xeb0df20d, 0xe80dea0d, 0xdd0dde0d, 0xd70dd80d, 0xce0dd10d, 0xc80dc90d, + 0xbb0dc60d, 0xb70db90d, 0xaf0db40d, 0xaa0dac0d, 0xa50da70d, 0x9b0d9c0d, 0x980d990d, 0x8e0d900d, 0x8c0d8d0d, 0x830d890d, 0x7d0d820d, 0x7a0d7b0d, + 0x770d790d, 0x700d760d, 0x6c0d6e0d, 0x6a0d6b0d, 0x660d690d, 0x640d650d, 0x5f0d630d, 0x510d560d, 0x4d0d4f0d, 0x4b0d4c0d, 0x430d490d, 0x8400410d, + 0x0d3f0800, 0x0d3b0d3c, 0x0d380d3a, 0x0d330d37, 0x0d260d2a, 0x0d0d0d18, 0x0d090d0c, 0x0cfd0c07, 0x0cf00cf9, 0x0ce40ce5, 0x0ce00ce1, 0x0cd20cd7, + 0x0ca00caa, 0x00950c96, 0x0c800c00, 0x00010071, 0x82780f00, 0x0f742603, 0x0f700f72, 0x2009826e, 0x2203826a, 0x82640f66, 0x0f602205, 0x2c05825e, + 0x0f580f5a, 0x0f540f56, 0x0f500f52, 0x0801b41a, 0x160f1830, 0x120f140f, 0x0e0f100f, 0x0a0f0c0f, 0x060f080f, 0x020f040f, 0xfe0e000f, 0xfa0efc0e, + 0xf60ef80e, 0xf20ef40e, 0xee0ef00e, 0xea0eec0e, 0x0342e80e, 0xde0e3707, 0xda0edc0e, 0xd60ed80e, 0xd20ed40e, 0xce0ed00e, 0x5c0fcc0e, 0x0382c80e, + 0x0ec46008, 0x0fc00ec2, 0x0fbc0e74, 0x0eb80e2a, 0x0e960fb6, 0x0eb00eb2, 0x0eac0eae, 0x0ea80eaa, 0x0e540fa6, 0x0ea00ea2, 0x0f9c0e9e, 0x0e980e0c, + 0x0e940e96, 0x0e900e92, 0x0e8c0e8e, 0x0e880e8a, 0x0e840e86, 0x0e800e82, 0x0e7c0e7e, 0x0e780e7a, 0x0e740e76, 0x0e700e72, 0x0e6c0e6e, 0x0e680e6a, + 0x82640e66, 0x4260200d, 0xe508082b, 0x0e540e56, 0x0e500e52, 0x0e4c0e4e, 0x0e480e4a, 0x0e440e46, 0x0e400e42, 0x0e3c0e3e, 0x0e380e3a, 0x0e340e36, + 0x0e300e32, 0x0e2c0e2e, 0x0e280e2a, 0x0f240e26, 0x0e200e64, 0x0e1c0e1e, 0x0e180e1a, 0x0e140e16, 0x0e100e12, 0x0e0c0e0e, 0x0e080e0a, 0x0e040e06, + 0x0d000e02, 0x0dfc0dfe, 0x0df80dfa, 0x0df40df6, 0x0df00df2, 0x0dec0dee, 0x0de80dea, 0x0de40de6, 0x0de00de2, 0x0ddc0dde, 0x0dd80dda, 0x0dd40dd6, + 0x0dd00dd2, 0x0dcc0dce, 0x0dc80dca, 0x0dc40dc6, 0x0dc00dc2, 0x0dbc0dbe, 0x0db80dba, 0x0db40db6, 0x0db00db2, 0x0dac0dae, 0x0da80daa, 0x0da40da6, + 0x0da00da2, 0x0d9c0d9e, 0x0d980d9a, 0x0d940d96, 0x0d900d92, 0x0d8c0d8e, 0x0d880d8a, 0x0d840d86, 0x0d800d82, 0x0d7c0d7e, 0x0d780d7a, 0x0d740d76, + 0x73420d72, 0x6abe0f05, 0x660d680d, 0x620d640d, 0x5e0d600d, 0x5a0d5c0d, 0x560d580d, 0x520d540d, 0x4e0d500d, 0x4a0d4c0d, 0x460d480d, 0x420d440d, + 0x3e0d400d, 0x3a0d3c0d, 0x360d380d, 0x320d340d, 0x2e0d300d, 0x2a0d2c0d, 0x260d280d, 0x220d240d, 0x1e0d200d, 0x1a0d1c0d, 0x160d180d, 0x120d140d, + 0x0e0d100d, 0x0a0d0c0d, 0x060d080d, 0x020d040d, 0xfe0c000d, 0xfa0cfc0c, 0xf60cf80c, 0xf20cf40c, 0xee0cf00c, 0xea0cec0c, 0xe60ce80c, 0xe20ce40c, + 0xde0ce00c, 0xda0cdc0c, 0xd60cd80c, 0xd20cd40c, 0xce0cd00c, 0xca0ccc0c, 0xc60cc80c, 0xc20cc40c, 0xbe0cc00c, 0xba0cbc0c, 0xb60cb80c, 0xb20cb40c, + 0xae0cb00c, 0xaa0cac0c, 0xa60ca80c, 0xa20ca40c, 0x9e0ca00c, 0x9a0c9c0c, 0x960c980c, 0x920c940c, 0x8e0c900c, 0x8a0c8c0c, 0x860c880c, 0x820c840c, + 0x7e0c800c, 0x7a0c7c0c, 0x760c780c, 0x720c740c, 0x6e0c700c, 0x6a0c6c0c, 0x660c680c, 0x620c640c, 0x5e0c600c, 0x5a0c5c0c, 0x560c580c, 0x520c540c, + 0x4e0c500c, 0x4a0c4c0c, 0x460c480c, 0x420c440c, 0x3e0c400c, 0x3a0c3c0c, 0x360c380c, 0x320c340c, 0x2e0c300c, 0x2a0c2c0c, 0x260c280c, 0x220c240c, + 0x1e0c200c, 0x1a0c1c0c, 0x160c180c, 0x120c140c, 0x0e0c100c, 0x0a0c0c0c, 0x060c080c, 0x020c040c, 0xfe0b000c, 0xfa0bfc0b, 0xf60bf80b, 0xf20bf40b, + 0xee0bf00b, 0xea0bec0b, 0xe60be80b, 0xe20be40b, 0xde0be00b, 0xda0bdc0b, 0xd60bd80b, 0xd20bd40b, 0xce0bd00b, 0xca0bcc0b, 0xc60bc80b, 0xc20bc40b, + 0xbe0bc00b, 0xba0bbc0b, 0xb60bb80b, 0xb20bb40b, 0xae0bb00b, 0xaa0bac0b, 0xa60ba80b, 0xa20ba40b, 0x9e0ba00b, 0x9a0b9c0b, 0x960b980b, 0x920b940b, + 0x8e0b900b, 0x8a0b8c0b, 0x860b880b, 0x820b840b, 0x7e0b800b, 0x7a0b7c0b, 0x760b780b, 0x720b740b, 0x6e0b700b, 0x6a0b6c0b, 0x660b680b, 0x620b640b, + 0x5e0b600b, 0x5a0b5c0b, 0x560b580b, 0x520b540b, 0x4e0b500b, 0x4a0b4c0b, 0x460b480b, 0x420b440b, 0x3e0b400b, 0x3a0b3c0b, 0x360b380b, 0x320b340b, + 0x2e0b300b, 0x2a0b2c0b, 0x260b280b, 0x220b240b, 0x1e0b200b, 0x1a0b1c0b, 0x160b180b, 0x120b140b, 0x0e0b100b, 0x0a0b0c0b, 0x060b080b, 0x020b040b, + 0xfe0a000b, 0xfa0afc0a, 0xf60af80a, 0xf20af40a, 0xee0af00a, 0xea0aec0a, 0xe60ae80a, 0xe20ae40a, 0xde0ae00a, 0xda0adc0a, 0xd60ad80a, 0xd20ad40a, + 0xce0ad00a, 0xca0acc0a, 0xc60ac80a, 0xc20ac40a, 0xbe0ac00a, 0xba0abc0a, 0xb60ab80a, 0xb20ab40a, 0xae0ab00a, 0xaa0aac0a, 0xa60aa80a, 0xa20aa40a, + 0x9e0aa00a, 0x9a0a9c0a, 0x960a980a, 0x920a940a, 0x8e0a900a, 0x8a0a8c0a, 0x860a880a, 0x820a840a, 0x7e0a800a, 0x7a0a7c0a, 0x760a780a, 0x720a740a, + 0x6e0a700a, 0x6a0a6c0a, 0x660a680a, 0x620a640a, 0x5e0a600a, 0x5a0a5c0a, 0x560a580a, 0x520a540a, 0x4e0a500a, 0x4a0a4c0a, 0x460a480a, 0x420a440a, + 0x3e0a400a, 0x3a0a3c0a, 0x360a380a, 0x320a340a, 0x2e0a300a, 0x2a0a2c0a, 0x260a280a, 0x220a240a, 0x1e0a200a, 0x1a0a1c0a, 0x160a180a, 0x120a140a, + 0x0e0a100a, 0x0a0a0c0a, 0x060a080a, 0x020a040a, 0xfe09000a, 0xfa09fc09, 0xf609f809, 0xf209f409, 0xee09f009, 0xea09ec09, 0xe609e809, 0xe209e409, + 0xde09e009, 0xda09dc09, 0xd609d809, 0xd209d409, 0xce09d009, 0xca09cc09, 0xc609c809, 0xc209c409, 0xbe09c009, 0xba09bc09, 0xb609b809, 0xb209b409, + 0xae09b009, 0xaa09ac09, 0xa609a809, 0xa209a409, 0x9e09a009, 0x9a099c09, 0x96099809, 0x92099409, 0x8e099009, 0x8a098c09, 0x86098809, 0x82098409, + 0x7e098009, 0x7a097c09, 0x76097809, 0x72097409, 0x6e097009, 0x6a096c09, 0x66096809, 0x62096409, 0x5e096009, 0x5a095c09, 0x56095809, 0x52095409, + 0x4e095009, 0x4a094c09, 0x46094809, 0x42094409, 0x3e094009, 0x3a093c09, 0x36093809, 0x32093409, 0x2e093009, 0x2a092c09, 0x26092809, 0x22092409, + 0x1e092009, 0x1a091c09, 0x16091809, 0x12091409, 0x0e091009, 0x0a090c09, 0x06090809, 0x02090409, 0xfe080009, 0xfa08fc08, 0xf608f808, 0xf208f408, + 0xee08f008, 0xea08ec08, 0xe608e808, 0xe208e408, 0xde08e008, 0xda08dc08, 0xd608d808, 0xd208d408, 0xce08d008, 0xca08cc08, 0xc608c808, 0xc208c408, + 0xbe08c008, 0xba08bc08, 0xb608b808, 0xb208b408, 0xae08b008, 0xaa08ac08, 0xa608a808, 0xa208a408, 0x9e08a008, 0x9a089c08, 0x96089808, 0x92089408, + 0x8e089008, 0x8a088c08, 0x86088808, 0x82088408, 0x7e088008, 0x7a087c08, 0x76087808, 0x72087408, 0x6e087008, 0x6a086c08, 0x66086808, 0x62086408, + 0x5e086008, 0x5a085c08, 0x56085808, 0x52085408, 0x4e085008, 0x4a084c08, 0x46084808, 0x42084408, 0x3e084008, 0x3a083c08, 0x36083808, 0x32083408, + 0x2e083008, 0x2a082c08, 0x26082808, 0x22082408, 0x1e082008, 0x1a081c08, 0x16081808, 0x12081408, 0x0e081008, 0x0a080c08, 0x06080808, 0x02080408, + 0xfe070008, 0xfa07fc07, 0xf607f807, 0xf207f407, 0xee07f007, 0xea07ec07, 0xe607e807, 0xe207e407, 0xde07e007, 0xda07dc07, 0xd607d807, 0xd207d407, + 0xce07d007, 0xca07cc07, 0xc607c807, 0xc207c407, 0xbe07c007, 0xba07bc07, 0xb607b807, 0xb207b407, 0xae07b007, 0xaa07ac07, 0xa607a807, 0xa207a407, + 0x9e07a007, 0x9a079c07, 0x96079807, 0x92079407, 0x8e079007, 0x8a078c07, 0x86078807, 0x82078407, 0x7e078007, 0x7a077c07, 0x76077807, 0x72077407, + 0x6e077007, 0x6a076c07, 0x66076807, 0x62076407, 0x5e076007, 0x5a075c07, 0x56075807, 0x52075407, 0x4e075007, 0x4a074c07, 0x46074807, 0x42074407, + 0x3e074007, 0x3a073c07, 0x36073807, 0x32073407, 0x2e073007, 0x2a072c07, 0x26072807, 0x22072407, 0x1e072007, 0x1a071c07, 0x16071807, 0x12071407, + 0x0e071007, 0x0a070c07, 0x06070807, 0x02070407, 0xfe060007, 0xfa06fc06, 0xf606f806, 0xf206f406, 0xee06f006, 0xea06ec06, 0xe606e806, 0xe206e406, + 0xde06e006, 0xda06dc06, 0xd606d806, 0xd206d406, 0xce06d006, 0xca06cc06, 0xc606c806, 0xc206c406, 0xbe06c006, 0xba06bc06, 0xb606b806, 0xb206b406, + 0xae06b006, 0xaa06ac06, 0xa606a806, 0xa206a406, 0x9e06a006, 0x9a069c06, 0x96069806, 0x92069406, 0x8e069006, 0x8a068c06, 0x86068806, 0x82068406, + 0x7e068006, 0x7a067c06, 0x76067806, 0x72067406, 0x6e067006, 0x6a066c06, 0x66066806, 0x62066406, 0x5e066006, 0x5a065c06, 0x56065806, 0x52065406, + 0x4e065006, 0x4a064c06, 0x46064806, 0x42064406, 0x3e064006, 0x3a063c06, 0x36063806, 0x32063406, 0x2e063006, 0x2a062c06, 0x26062806, 0x22062406, + 0x1e062006, 0x1a061c06, 0x16061806, 0x12061406, 0x0e061006, 0x0a060c06, 0x06060806, 0x02060406, 0xfe050006, 0xfa05fc05, 0xf605f805, 0xf205f405, + 0xee05f005, 0xea05ec05, 0xe605e805, 0xe205e405, 0xde05e005, 0xda05dc05, 0xd605d805, 0xd205d405, 0xce05d005, 0xca05cc05, 0xc605c805, 0xc205c405, + 0xbe05c005, 0xba05bc05, 0xb605b805, 0xb205b405, 0xae050000, 0x4382ac05, 0xa605a824, 0x7b82a405, 0x9e051e2c, 0x9a059c05, 0x96059805, 0x73829405, + 0xa7820620, 0x24062022, 0x1624b782, 0x0007f006, 0x5e209782, 0xba203b82, 0xb8223d82, 0x01827a06, 0x5f828220, 0xac220383, 0x7782ac06, 0x3806dc22, + 0x8e368382, 0xa0068e05, 0x84057205, 0x74057e05, 0x6e057c05, 0x22064c06, 0x01826e05, 0xe6055224, 0x59826e06, 0xb8056028, 0x8e055605, 0xa3828c05, + 0xa8068426, 0xb4059c06, 0x782c0382, 0x98069006, 0x70069206, 0x72067806, 0x78240182, 0x92056a06, 0xc8265f82, 0x2a06c805, 0x01822e06, 0x89822220, + 0x02052422, 0xa426b982, 0xa005a205, 0x17843806, 0x22062a22, 0x222cb982, 0xb8056a05, 0x2c06f204, 0x3c052205, 0x9e20c582, 0x94200382, 0x9220cb82, + 0x9a24cd82, 0x46054805, 0x74247782, 0x3a06de05, 0x2a2e4382, 0x18061405, 0x2c06e805, 0xf2051606, 0x51820405, 0x32050026, 0x0c060205, 0x7c2aad82, + 0xe605a005, 0xa204e205, 0x0182a004, 0xe4059e3c, 0x4804ec05, 0x80058205, 0x7a059204, 0x46044804, 0x30043204, 0x36047e04, 0x8782b804, 0xe5828820, + 0x96057429, 0xe6049405, 0x98006c04, 0xc8052100, 0x18de1a98, 0x9fd20321, 0x0a042560, 0xb0030000, 0x04252583, 0x040000a2, 0x2203823a, 0x82a804a4, + 0x841c2005, 0x00922613, 0x04180400, 0x230b8314, 0xb803b803, 0x23820784, 0x83340321, 0x26038309, 0x0c040c04, 0x88030000, 0xb60323fd, 0x17837403, + 0xbc201382, 0x05870785, 0x03940425, 0x838c0388, 0x3604250d, 0xde03d403, 0x42200984, 0xaa202782, 0x3e220984, 0x45836c03, 0x03255985, 0x02000066, + 0x200382da, 0x851b83c4, 0x213b8503, 0x0d85b602, 0x03230585, 0x83f803fc, 0x54032109, 0x03850583, 0x85d60321, 0x23178407, 0x0300007c, 0x82069f4f, + 0x21998209, 0x17838602, 0x0320038d, 0x7e202583, 0x03211385, 0x22278282, 0x82e802ca, 0x827a2005, 0x00782603, 0x02420200, 0x20058244, 0x231f85be, + 0x68030000, 0x9f820382, 0x82640321, 0x02622207, 0x20058276, 0x201b835e, 0x83418603, 0x2103910b, 0x13896202, 0x029e0223, 0x910d899e, 0x87618309, + 0x84022015, 0x9f0d87df, 0x88022007, 0x203f88eb, 0x8f0987fa, 0x25838507, 0x00007001, 0x03826e01, 0x03826620, 0x238f5c20, 0x010f0010, 0x00a02402, + 0x419c008c, 0x01213307, 0x08358636, 0x0300022e, 0x05000400, 0x07000600, 0x14001300, 0x16001500, 0x18001700, 0x1a001900, 0x1c001b00, 0x1e001d00, + 0x20001f00, 0x22002100, 0x24002300, 0x200aed7c, 0x0aef7c2a, 0x31003029, 0x91003200, 0x7a01a000, 0x922c0591, 0x96019301, 0x99019801, 0xa2019e01, + 0x2006637a, 0x0e3d7abe, 0x24053b7a, 0x01d101d0, 0x08317ad2, 0xe401dd3e, 0xee01e801, 0xf601ef01, 0x0202f701, 0x17020902, 0x1d021902, 0x2f022502, + 0x32023002, 0x22069779, 0x793f023d, 0x81790685, 0x02513307, 0x02540252, 0x02590256, 0x02770271, 0x027c0279, 0x2979027f, 0x02923b0f, 0x029a0293, + 0x02a1029b, 0x02ad02a8, 0x02c002bd, 0x02cc02c5, 0x02da02ce, 0x977802dd, 0x03ff2b17, 0x03040301, 0x03070305, 0x6778030c, 0x03172805, 0x031a0319, + 0x78290327, 0x2e22063d, 0x23783a03, 0x03402406, 0x78480342, 0x592e0c03, 0x60035e03, 0x6b036103, 0x75037103, 0xcd777903, 0x0385280a, 0x0398038b, + 0x77dc03ab, 0x3f080e13, 0x04f103ed, 0x04620415, 0x04810463, 0x04980496, 0x04a604a0, 0x04b204a7, 0x04c404b9, 0x04c804c5, 0x04ce04cb, 0x04db04d2, + 0x04ec04e4, 0x05ff04f8, 0x0526050e, 0x052f0528, 0x05360534, 0x000c0039, 0x69210082, 0x82048264, 0xc7082102, 0x20200482, 0x21200382, 0x01200382, + 0x22200382, 0x32200386, 0x23200782, 0x25200382, 0x03200382, 0x26200382, 0x17830386, 0x0b822720, 0x0b830383, 0x0b822820, 0x0b830383, 0x0b822920, + 0x0b830383, 0x0b822a20, 0x03822b20, 0x03820620, 0x03862c20, 0x2d201783, 0x03830b82, 0x07820820, 0x03862e20, 0x2f201783, 0x03830b82, 0x30200b83, + 0x39200b82, 0x09200382, 0x3a200382, 0x32200386, 0x3b200782, 0x0b830386, 0x0b823c20, 0x03825a20, 0x03821320, 0x03865b20, 0x5c201783, 0x03830b82, + 0x5d200b83, 0x03830b82, 0x5e200b83, 0x03830b82, 0x5f200b83, 0x03830b82, 0x60200b83, 0x03830b82, 0x61200b83, 0x03830b82, 0x07821820, 0x03866220, + 0x07821920, 0x03866320, 0x07821a20, 0x03866420, 0x07821b20, 0x03866520, 0x07821c20, 0x03866620, 0x07821d20, 0x03866720, 0x07821e20, 0x03866820, + 0x07821f20, 0x03866920, 0x07822020, 0x03866a20, 0x07822120, 0x03866b20, 0x07822220, 0x03866c20, 0x07822320, 0x03866d20, 0x07822420, 0x03866e20, + 0x07822520, 0x03866f20, 0x07822620, 0x03867020, 0x07822720, 0x03867120, 0x07822820, 0x03867220, 0x07822920, 0x03867320, 0x07822a20, 0x03867420, + 0x07822b20, 0x03867520, 0x07822c20, 0x03867620, 0x07822d20, 0x03867720, 0x07822e20, 0x03867820, 0x07822f20, 0x03867920, 0x07823020, 0x03867a20, + 0x07823120, 0x03867b20, 0x07823220, 0x03867c20, 0x7d200b83, 0x03830b82, 0x7e200b83, 0x03830b82, 0x7f200b83, 0x03830b82, 0x80200b83, 0x03830b82, + 0x81200b83, 0x03830b82, 0x82200b83, 0x03830b82, 0x83200b83, 0x03830b82, 0x84200b83, 0x03830b82, 0x85200b83, 0x03830b82, 0x86200b83, 0x03830b82, + 0x87200b83, 0x03830b82, 0x88200b83, 0x03830b82, 0x89200b83, 0x03830b82, 0x8a200b83, 0x03830b82, 0x8b200b83, 0x03830b82, 0x8c200b83, 0x03830b82, + 0x8d200b83, 0x03830b82, 0x8e200b83, 0x03830b82, 0x8f200b83, 0x03830b82, 0x90200b83, 0x03830b82, 0x91200b83, 0x03830b82, 0x92200b83, 0x03830b82, + 0x93200b83, 0x03830b82, 0x94200b83, 0x03830b82, 0x95200b83, 0x03830b82, 0x96200b83, 0x03830b82, 0x97200b83, 0x03830b82, 0x98200b83, 0x03830b82, + 0x99200b83, 0x03830b82, 0x9a200b83, 0x03830b82, 0x9b200b83, 0x03830b82, 0x9c200b83, 0x03830b82, 0x9d200b83, 0x03830b82, 0x9e200b83, 0x03830b82, + 0x9f200b83, 0x03830b82, 0xa0200b83, 0x03830b82, 0xa1200b83, 0x03830b82, 0xa2200b83, 0x03830b82, 0xa3200b83, 0x03820b82, 0x82850221, 0x86a42007, + 0x20178303, 0x820b82a5, 0x87022103, 0xa6200782, 0x17830386, 0x0b82a720, 0x0b830383, 0x0b82a820, 0x0b830383, 0x0b82a920, 0x02210382, 0x200782ce, + 0x830386aa, 0x82ab2017, 0x2103820b, 0x07824602, 0x0386ac20, 0xad201783, 0x03830b82, 0xae200b83, 0x03820b82, 0x820e0321, 0x86af2007, 0x20178303, + 0x830b82b0, 0x200b8303, 0x830b82b1, 0x200b8303, 0x830b82b2, 0x200b8303, 0x830b82b3, 0x200b8303, 0x830b82b4, 0x200b8303, 0x830b82b5, 0x200b8303, + 0x820b82b6, 0xc0022103, 0xb7200782, 0x17830386, 0x0b82b820, 0x0b830383, 0x0b82b920, 0x0b830383, 0x0b82ba20, 0x0b830383, 0x0b82bb20, 0x02210382, + 0x20078247, 0x830386bc, 0x82bd2017, 0x8303830b, 0x82be200b, 0x8303830b, 0x82bf200b, 0x8303830b, 0x836f830b, 0x200b8303, 0x831782c1, 0x200b8303, + 0x830b82c2, 0x200b8303, 0x830b82c3, 0x200b8303, 0x830b82c4, 0x200b8303, 0x830b82c5, 0x200b8303, 0x830b82c6, 0x200b8303, 0x830b82c7, 0x200b8303, + 0x830b82c8, 0x200b8303, 0x830b82c9, 0x200b8303, 0x830b82ca, 0x200b8303, 0x830b82cb, 0x200b8303, 0x830b82cc, 0x200b8303, 0x830b82cd, 0x200b8303, + 0x830b82ce, 0x200b8303, 0x830b82cf, 0x200b8303, 0x830b82d0, 0x200b8303, 0x830b82d1, 0x200b8303, 0x830b82d2, 0x200b8303, 0x830b82d3, 0x200b8303, + 0x830b82d4, 0x200b8303, 0x830b82d5, 0x200b8303, 0x830b82d6, 0x200b8303, 0x820b82d7, 0x93012103, 0xd8200782, 0x17830386, 0x0b82d920, 0x0b830383, + 0x0b82da20, 0x0b830383, 0x0b82db20, 0x0b830383, 0x0b82dc20, 0x0b830383, 0x0b82dd20, 0x0b830383, 0x0b82de20, 0x0b830383, 0x0b82df20, 0x0b830383, + 0x0b82e020, 0x0b830383, 0x0b82e120, 0x0b830383, 0x0b82e220, 0x0b830383, 0x0b82e320, 0x0b830383, 0x0b82e420, 0x0b830383, 0x0b82e520, 0x0b830383, + 0x0b82e620, 0x0b830383, 0x0b82e720, 0x0b830383, 0x0b82e820, 0x0b830383, 0x0b82e920, 0x0b830383, 0x0b82ea20, 0x0b830383, 0x0b82eb20, 0x0b830383, + 0x0b82ec20, 0x0b830383, 0x0b82ed20, 0x0b830383, 0x0b82ee20, 0x0b830383, 0x0b82ef20, 0x0b830383, 0x0b82f020, 0x0b830383, 0x0b82f120, 0x0b830383, + 0x0b82f220, 0x0b830383, 0x0b82f320, 0x0b830383, 0x0b82f420, 0x0b830383, 0x0b82f520, 0x0b830383, 0x0b82f620, 0x0b830383, 0x0b82f720, 0x03210382, + 0x200782e8, 0x830386f8, 0x82f92017, 0x8303830b, 0x82fa200b, 0x8303830b, 0x82fb200b, 0x8303830b, 0x82fc200b, 0x8303830b, 0x82fd200b, 0x8303830b, + 0x82fe200b, 0x8303830b, 0x82ff200b, 0x8203830b, 0x4801200b, 0x00200676, 0x0c820b83, 0x03820120, 0x02230b84, 0x82010000, 0x200b8403, 0x820b8203, + 0x260b8403, 0x01000004, 0x84000004, 0x0005230b, 0x03820100, 0x06240b84, 0x06010000, 0x07231786, 0x82010000, 0x20178403, 0x820b8208, 0x200b8403, + 0x820b8209, 0x200b8403, 0x820b820a, 0x200b8403, 0x820b820b, 0x200b8403, 0x820b820c, 0x200b8403, 0x820b820d, 0x200b8403, 0x820b820e, 0x200b8403, + 0x820b820f, 0x200b8403, 0x820b8210, 0x200b8403, 0x820b8211, 0x200b8403, 0x820b8212, 0x200b8403, 0x820b8213, 0x200b8403, 0x820b8214, 0x200b8403, + 0x820b8215, 0x200b8403, 0x820b8216, 0x200b8403, 0x820b8217, 0x200b8403, 0x820b8218, 0x200b8403, 0x820b8219, 0x200b8403, 0x820b821a, 0x200b8403, + 0x820b821b, 0x200b8403, 0x820b821c, 0x200b8403, 0x820b821d, 0x200b8403, 0x820b821e, 0x200b8403, 0x820b821f, 0x200b8403, 0x820b8220, 0x200b8403, + 0x820b8221, 0x200b8403, 0x820b8222, 0x200b8403, 0x820b8223, 0x200b8403, 0x820b8224, 0x200b8403, 0x820b8225, 0x200b8403, 0x820b8226, 0x200b8403, + 0x820b8227, 0x200b8403, 0x820b8228, 0x200b8403, 0x820b8229, 0x200b8403, 0x820b822a, 0x200b8403, 0x820b822b, 0x200b8403, 0x820b822c, 0x200b8403, + 0x820b822d, 0x200b8403, 0x820b822e, 0x200b8403, 0x820b822f, 0x200b8403, 0x820b8230, 0x200b8403, 0x820b8231, 0x200b8403, 0x820b8232, 0x200b8403, + 0x820b8233, 0x200b8403, 0x820b8234, 0x200b8403, 0x820b8235, 0x200b8403, 0x820b8236, 0x200b8403, 0x820b8237, 0x200b8403, 0x820b8238, 0x200b8403, + 0x820b8239, 0x200b8403, 0x820b823a, 0x200b8403, 0x820b823b, 0x200b8403, 0x820b823c, 0x200b8403, 0x820b823d, 0x200b8403, 0x820b823e, 0x200b8403, + 0x820b823f, 0x200b8403, 0x820b8240, 0x200b8403, 0x820b8241, 0x200b8403, 0x820b8242, 0x200b8403, 0x820b8243, 0x200b8403, 0x820b8244, 0x200b8403, + 0x820b8245, 0x200b8403, 0x820b8246, 0x200b8403, 0x820b8247, 0x200b8403, 0x820b8248, 0x200b8403, 0x820b8249, 0x200b8403, 0x820b824a, 0x200b8403, + 0x820b824b, 0x200b8403, 0x820b824c, 0x200b8403, 0x820b824d, 0x200b8403, 0x820b824e, 0x200b8403, 0x820b824f, 0x200b8403, 0x820b8250, 0x200b8403, + 0x820b8251, 0x200b8403, 0x820b8252, 0x200b8403, 0x820b8253, 0x200b8403, 0x820b8254, 0x200b8403, 0x820b8255, 0x200b8403, 0x820b8256, 0x200b8403, + 0x820b8257, 0x200b8403, 0x820b8258, 0x200b8403, 0x820b8259, 0x200b8403, 0x820b825a, 0x200b8403, 0x820b825b, 0x200b8403, 0x820b825c, 0x200b8403, + 0x820b825d, 0x200b8403, 0x820b825e, 0x200b8403, 0x820b825f, 0x200b8403, 0x820b8260, 0x200b8403, 0x820b8261, 0x200b8403, 0x820b8262, 0x200b8403, + 0x820b8263, 0x200b8403, 0x820b8264, 0x200b8403, 0x820b8265, 0x200b8403, 0x820b8266, 0x200b8403, 0x820b8267, 0x200b8403, 0x820b8268, 0x200b8403, + 0x820b8269, 0x200b8403, 0x820b826a, 0x200b8403, 0x820b826b, 0x200b8403, 0x820b826c, 0x200b8403, 0x820b826d, 0x200b8403, 0x820b826e, 0x200b8403, + 0x820b826f, 0x200b8403, 0x820b8270, 0x200b8403, 0x820b8271, 0x200b8403, 0x820b8272, 0x200b8403, 0x820b8273, 0x200b8403, 0x820b8274, 0x200b8403, + 0x820b8275, 0x200b8403, 0x820b8276, 0x200b8403, 0x820b8277, 0x200b8403, 0x820b8278, 0x200b8403, 0x820b8279, 0x200b8403, 0x820b827a, 0x200b8403, + 0x820b827b, 0x200b8403, 0x820b827c, 0x200b8403, 0x820b827d, 0x200b8403, 0x820b827e, 0x200b8403, 0x820b827f, 0x200b8403, 0x820b8280, 0x200b8403, + 0x820b8281, 0x200b8403, 0x820b8282, 0x200b8403, 0x820b8283, 0x200b8403, 0x820b8284, 0x200b8403, 0x820b8285, 0x200b8403, 0x820b8286, 0x200b8403, + 0x820b8287, 0x200b8403, 0x820b8288, 0x200b8403, 0x820b8289, 0x200b8403, 0x820b828a, 0x200b8403, 0x820b828b, 0x200b8403, 0x820b828c, 0x200b8403, + 0x820b828d, 0x200b8403, 0x820b828e, 0x200b8403, 0x820b828f, 0x200b8403, 0x820b8290, 0x200b8403, 0x820b8291, 0x200b8403, 0x820b8292, 0x200b8403, + 0x820b8293, 0x200b8403, 0x820b8294, 0x200b8403, 0x820b8295, 0x200b8403, 0x820b8296, 0x200b8403, 0x820b8297, 0x200b8403, 0x820b8298, 0x200b8403, + 0x820b8299, 0x200b8403, 0x820b829a, 0x200b8403, 0x820b829b, 0x200b8403, 0x820b829c, 0x200b8403, 0x820b829d, 0x200b8403, 0x820b829e, 0x200b8403, + 0x820b829f, 0x200b8403, 0x820b82a0, 0x200b8403, 0x4b0b82a1, 0x012106ff, 0x820b82a2, 0x20178403, 0x820b82a3, 0x200b8403, 0x820b82a4, 0x200b8403, + 0x820b82a5, 0x200b8403, 0x820b82a6, 0x200b8403, 0x4b0b82a7, 0x012106ff, 0x820b82a8, 0x20178403, 0x820b82a9, 0x200b8403, 0x820b82aa, 0x200b8403, + 0x820b82ab, 0x200b8403, 0x820b82ac, 0x200b8403, 0x820b82ad, 0x200b8403, 0x820b82ae, 0x200b8403, 0x820b82af, 0x200b8403, 0x820b82b0, 0x200b8403, + 0x820b82b1, 0x200b8403, 0x820b82b2, 0x200b8403, 0x820b82b3, 0x200b8403, 0x820b82b4, 0x200b8403, 0x820b82b5, 0x200b8403, 0x820b82b6, 0x200b8403, + 0x820b82b7, 0x200b8403, 0x820b82b8, 0x200b8403, 0x820b82b9, 0x200b8403, 0x820b82ba, 0x200b8403, 0x820b82bb, 0x200b8403, 0x820b82bc, 0x200b8403, + 0x820b82bd, 0x200b8403, 0x820b82be, 0x200b8403, 0x820b82bf, 0x200b8403, 0x820b82c0, 0x200b8403, 0x820b82c1, 0x200b8403, 0x820b82c2, 0x200b8403, + 0x820b82c3, 0x200b8403, 0x820b82c4, 0x200b8403, 0x820b82c5, 0x200b8403, 0x820b82c6, 0x200b8403, 0x820b82c7, 0x200b8403, 0x820b82c8, 0x200b8403, + 0x820b82c9, 0x200b8403, 0x820b82ca, 0x200b8403, 0x820b82cb, 0x200b8403, 0x820b82cc, 0x200b8403, 0x820b82cd, 0x200b8403, 0x820b82ce, 0x200b8403, + 0x820b82cf, 0x200b8403, 0x820b82d0, 0x200b8403, 0x820b82d1, 0x200b8403, 0x820b82d2, 0x200b8403, 0x820b82d3, 0x200b8403, 0x820b82d4, 0x200b8403, + 0x820b82d5, 0x200b8403, 0x820b82d6, 0x200b8403, 0x820b82d7, 0x200b8403, 0x820b82d8, 0x200b8403, 0x820b82d9, 0x200b8403, 0x820b82da, 0x200b8403, + 0x820b82db, 0x200b8403, 0x820b82dc, 0x200b8403, 0x820b82dd, 0x200b8403, 0x820b82de, 0x200b8403, 0x820b82df, 0x200b8403, 0x820b82e0, 0x200b8403, + 0x820b82e1, 0x200b8403, 0x820b82e2, 0x200b8403, 0x820b82e3, 0x200b8403, 0x820b82e4, 0x200b8403, 0x820b82e5, 0x200b8403, 0x820b82e6, 0x200b8403, + 0x820b82e7, 0x200b8403, 0x820b82e8, 0x200b8403, 0x820b82e9, 0x200b8403, 0x820b82ea, 0x200b8403, 0x820b82eb, 0x200b8403, 0x820b82ec, 0x200b8403, + 0x820b82ed, 0x200b8403, 0x820b82ee, 0x200b8403, 0x820b82ef, 0x200b8403, 0x4b0b82f0, 0x012106ff, 0x820b82f1, 0x20178403, 0x820b82f2, 0x200b8403, + 0x820b82f3, 0x200b8403, 0x820b82f4, 0x200b8403, 0x820b82f5, 0x200b8403, 0x820b82f6, 0x200b8403, 0x820b82f7, 0x200b8403, 0x820b82f8, 0x200b8403, + 0x820b82f9, 0x200b8403, 0x820b82fa, 0x200b8403, 0x820b82fb, 0x200b8403, 0x820b82fc, 0x200b8403, 0x820b82fd, 0x200b8403, 0x820b82fe, 0x200b8403, + 0x820b82ff, 0x250b8303, 0x00000002, 0x00820002, 0x07823220, 0x03850120, 0x02201784, 0x03820b82, 0x03200b84, 0x03820b82, 0x04200b84, 0x03820b82, + 0x05200b84, 0x03820b82, 0x06200b84, 0x03820b82, 0x07200b84, 0x03820b82, 0x08260b84, 0x08020000, 0x0b840000, 0x00000923, 0x06ff4b02, 0x000a0225, + 0x860a0200, 0x000b2317, 0x03820200, 0x0c202384, 0x03820b82, 0x0d200b84, 0x03820b82, 0x0e200b84, 0x03820b82, 0x0f200b84, 0x03820b82, 0x10200b84, + 0x03820b82, 0x11200b84, 0x03820b82, 0x12200b84, 0x03820b82, 0x13200b84, 0x03820b82, 0x14200b84, 0x03820b82, 0x15200b84, 0x03820b82, 0x16200b84, + 0x03820b82, 0x17200b84, 0x03820b82, 0x18200b84, 0x03820b82, 0x19200b84, 0x03820b82, 0x1a200b84, 0x03820b82, 0x1b200b84, 0x03820b82, 0x1c200b84, + 0x03820b82, 0x1d200b84, 0x03820b82, 0x1e200b84, 0x03820b82, 0x1f200b84, 0x03820b82, 0x20200b84, 0x03820b82, 0x21200b84, 0x03820b82, 0x22200b84, + 0x03820b82, 0x23200b84, 0x03820b82, 0x24200b84, 0x03820b82, 0x25200b84, 0x03820b82, 0x26200b84, 0x03820b82, 0x27200b84, 0x03820b82, 0x28200b84, + 0x03820b82, 0x29200b84, 0x03820b82, 0x2a200b84, 0x03820b82, 0x2b200b84, 0x03820b82, 0x2c200b84, 0x03820b82, 0x2d200b84, 0x03820b82, 0x2e200b84, + 0x03820b82, 0x2f200b84, 0x03820b82, 0x30200b84, 0x03820b82, 0x31200b84, 0x03820b82, 0x32200b84, 0x03820b82, 0x33200b84, 0x03820b82, 0x34200b84, + 0x03820b82, 0x35200b84, 0x03820b82, 0x36200b84, 0x03820b82, 0x37200b84, 0x03820b82, 0x38200b84, 0x03820b82, 0x39200b84, 0x03820b82, 0x3a200b84, + 0x03820b82, 0x3b200b84, 0x03820b82, 0x3c200b84, 0x03820b82, 0x3d200b84, 0x03820b82, 0x3e200b84, 0x03820b82, 0x3f200b84, 0x03820b82, 0x40200b84, + 0x03820b82, 0x41200b84, 0x03820b82, 0x42200b84, 0x03820b82, 0x43200b84, 0x03820b82, 0x44200b84, 0x03820b82, 0x45200b84, 0x03820b82, 0x46200b84, + 0x03820b82, 0x47200b84, 0x03820b82, 0x48200b84, 0x03820b82, 0x49200b84, 0x03820b82, 0x4a200b84, 0x03820b82, 0x4b200b84, 0x03820b82, 0x4c200b84, + 0x03820b82, 0x4d200b84, 0x03820b82, 0x4e200b84, 0x03820b82, 0x4f200b84, 0x03820b82, 0x50200b84, 0x03820b82, 0x51200b84, 0x03820b82, 0x52200b84, + 0x03820b82, 0x53200b84, 0x03820b82, 0x54200b84, 0x03820b82, 0x55200b84, 0x03820b82, 0x56200b84, 0x03820b82, 0x57200b84, 0x03820b82, 0x58200b84, + 0x03820b82, 0x59200b84, 0x03820b82, 0x5a200b84, 0x03820b82, 0x5b200b84, 0x03820b82, 0x5c200b84, 0x03820b82, 0x5d200b84, 0x03820b82, 0x5e200b84, + 0x03820b82, 0x5f200b84, 0x03820b82, 0x60200b84, 0x03820b82, 0x61200b84, 0x03820b82, 0x62200b84, 0x03820b82, 0x63200b84, 0x03820b82, 0x64200b84, + 0x03820b82, 0x65200b84, 0x03820b82, 0x66200b84, 0x03820b82, 0x67200b84, 0x03820b82, 0x68200b84, 0x03820b82, 0x69200b84, 0x03820b82, 0x6a200b84, + 0x03820b82, 0x6b200b84, 0x03820b82, 0x6c200b84, 0x03820b82, 0x6d200b84, 0x03820b82, 0x6e200b84, 0x03820b82, 0x6f200b84, 0x03820b82, 0x70200b84, + 0x03820b82, 0x71200b84, 0x03820b82, 0x72200b84, 0x03820b82, 0x73200b84, 0x03820b82, 0x74200b84, 0x03820b82, 0x75200b84, 0x03820b82, 0x76200b84, + 0x03820b82, 0x77200b84, 0x03820b82, 0x78200b84, 0x03820b82, 0x79200b84, 0x03820b82, 0x7a200b84, 0x03820b82, 0x7b200b84, 0x03820b82, 0x7c200b84, + 0x03820b82, 0x7d200b84, 0x03820b82, 0x7e200b84, 0x03820b82, 0x7f200b84, 0x03820b82, 0x80200b84, 0x03820b82, 0x81200b84, 0x03820b82, 0x82200b84, + 0x03820b82, 0x83200b84, 0x03820b82, 0x84200b84, 0x03820b82, 0x85200b84, 0x03820b82, 0x86200b84, 0x03820b82, 0x87200b84, 0x03820b82, 0x88200b84, + 0x03820b82, 0x89200b84, 0x03820b82, 0x8a200b84, 0x03820b82, 0x8b200b84, 0x03820b82, 0x8c200b84, 0x03820b82, 0x8d200b84, 0x03820b82, 0x8e200b84, + 0x03820b82, 0x8f200b84, 0x03820b82, 0x90200b84, 0x03820b82, 0x91200b84, 0x03820b82, 0x92200b84, 0x03820b82, 0x93200b84, 0x03820b82, 0x94200b84, + 0x03820b82, 0x95200b84, 0x03820b82, 0x96200b84, 0x03820b82, 0x97200b84, 0x03820b82, 0x98200b84, 0x03820b82, 0x99200b84, 0x03820b82, 0x9a200b84, + 0x03820b82, 0x9b200b84, 0x03820b82, 0x9c200b84, 0x03820b82, 0x9d200b84, 0x03820b82, 0x9e200b84, 0x03820b82, 0x9f200b84, 0x03820b82, 0xa0200b84, + 0x03820b82, 0xa1200b84, 0x03820b82, 0xa2200b84, 0x03820b82, 0xa3200b84, 0x03820b82, 0xa4200b84, 0x03820b82, 0xa5200b84, 0x03820b82, 0xa6200b84, + 0x03820b82, 0xa7200b84, 0x03820b82, 0xa8200b84, 0x03820b82, 0xa9200b84, 0x03820b82, 0xaa200b84, 0x03820b82, 0xab200b84, 0x03820b82, 0xac200b84, + 0x03820b82, 0xad200b84, 0x03820b82, 0xae200b84, 0x03820b82, 0xaf200b84, 0x03820b82, 0xb0200b84, 0x03820b82, 0xb1200b84, 0x03820b82, 0xb2200b84, + 0x03820b82, 0xb3200b84, 0x03820b82, 0xb4200b84, 0x03820b82, 0xb5200b84, 0x03820b82, 0xb6200b84, 0x03820b82, 0xb7200b84, 0x03820b82, 0xb8200b84, + 0x03820b82, 0xb9200b84, 0x03820b82, 0xba200b84, 0x03820b82, 0xbb200b84, 0x03820b82, 0xbc200b84, 0x03820b82, 0xbd200b84, 0x03820b82, 0xbe200b84, + 0x03820b82, 0xbf200b84, 0x03820b82, 0xc0200b84, 0x03820b82, 0xc1200b84, 0x03820b82, 0xc2200b84, 0x03820b82, 0xc3200b84, 0x03820b82, 0xc4200b84, + 0x03820b82, 0xc5200b84, 0x03820b82, 0xc6200b84, 0x03820b82, 0xc7200b84, 0x03820b82, 0xc8200b84, 0x03820b82, 0xc9200b84, 0x03820b82, 0xca200b84, + 0x03820b82, 0xcb200b84, 0x03820b82, 0xcc200b84, 0x03820b82, 0xcd200b84, 0x03820b82, 0xce200b84, 0x03820b82, 0xcf200b84, 0x03820b82, 0xd0200b84, + 0x03820b82, 0xd1200b84, 0x03820b82, 0xd2200b84, 0x03820b82, 0xd3200b84, 0x03820b82, 0xd4200b84, 0x03820b82, 0xd5200b84, 0x03820b82, 0xd6200b84, + 0x03820b82, 0xd7200b84, 0x03820b82, 0xd8200b84, 0x03820b82, 0xd9200b84, 0x03820b82, 0xda200b84, 0x03820b82, 0xdb200b84, 0x03820b82, 0xdc200b84, + 0x03820b82, 0xdd200b84, 0x03820b82, 0xde200b84, 0x03820b82, 0xdf200b84, 0x03820b82, 0xe0200b84, 0x03820b82, 0xe1200b84, 0x03820b82, 0xe2200b84, + 0x03820b82, 0xe3200b84, 0x03820b82, 0xe4200b84, 0x03820b82, 0xe5200b84, 0x03820b82, 0xe6200b84, 0x03820b82, 0xe7200b84, 0x03820b82, 0xe8200b84, + 0x03820b82, 0xe9200b84, 0x03820b82, 0xea200b84, 0x03820b82, 0xeb200b84, 0x03820b82, 0xec200b84, 0x03820b82, 0xed200b84, 0x03820b82, 0xee200b84, + 0x03820b82, 0xef200b84, 0x03820b82, 0xf0200b84, 0x03820b82, 0xf1200b84, 0x03820b82, 0xf2200b84, 0x03820b82, 0xf3200b84, 0x03820b82, 0xf4200b84, + 0x03820b82, 0xf5200b84, 0x03820b82, 0xf6200b84, 0x03820b82, 0xf7200b84, 0x03820b82, 0xf8200b84, 0x03820b82, 0xf9200b84, 0x03820b82, 0xfa200b84, + 0x03820b82, 0xfb200b84, 0x03820b82, 0xfc200b84, 0x03820b82, 0xfd200b84, 0x03820b82, 0xfe200b84, 0x03820b82, 0xff200b84, 0x03820b82, 0x03240b83, + 0x03000000, 0x0b840382, 0x0b820120, 0x0b840382, 0x0b820220, 0x0b840382, 0x0b820320, 0x0b840382, 0x0b820420, 0x0b840382, 0x0b820520, 0x0b840382, + 0x0b820620, 0x0b840382, 0x0b820720, 0x0b840382, 0x0b820820, 0x0b840382, 0x0b820920, 0x0b840382, 0x0b820a20, 0x0b840382, 0x0b820b20, 0x0b840382, + 0x00000c26, 0x00000c03, 0x0d230b84, 0x82030000, 0x240b8403, 0x0300000e, 0x2317860e, 0x0300000f, 0x17840382, 0x0b821020, 0x0b840382, 0x0b821120, + 0x0b840382, 0x0b821220, 0x0b840382, 0x0b821320, 0x0b840382, 0x0b821420, 0x0b840382, 0x0b821520, 0x0b840382, 0x0b821620, 0x0b840382, 0x0b821720, + 0x0b840382, 0x0b821820, 0x0b840382, 0x0b821920, 0x0b840382, 0x0b821a20, 0x0b840382, 0x0b821b20, 0x0b840382, 0x0b821c20, 0x0b840382, 0x0b821d20, + 0x0b840382, 0x0b821e20, 0x0b840382, 0x0b821f20, 0x0b840382, 0x0b822020, 0x0b840382, 0x0b822120, 0x0b840382, 0x0b822220, 0x0b840382, 0x0b822320, + 0x0b840382, 0x0b822420, 0x0b840382, 0x0b822520, 0x0b840382, 0x0b822620, 0x0b840382, 0x0b822720, 0x0b840382, 0x0b822820, 0x0b840382, 0x0b822920, + 0x0b840382, 0x0b822a20, 0x0b840382, 0x0b822b20, 0x0b840382, 0x0b822c20, 0x0b840382, 0x0b822d20, 0x0b840382, 0x0b822e20, 0x0b840382, 0x0b822f20, + 0x0b840382, 0x0b823020, 0x0b840382, 0x0b823120, 0x0b840382, 0x0b823220, 0x0b840382, 0x0b823320, 0x0b840382, 0x0b823420, 0x0b840382, 0x0b823520, + 0x0b840382, 0x0b823620, 0x0b840382, 0x0b823720, 0x0b840382, 0x0b823820, 0x0b840382, 0x0b823920, 0x0b840382, 0x0b823a20, 0x0b840382, 0x0b823b20, + 0x0b840382, 0x0b823c20, 0x0b840382, 0x0b823d20, 0x0b840382, 0x0b823e20, 0x0b840382, 0x0b823f20, 0x0b840382, 0x0b824020, 0x0b840382, 0x0b824120, + 0x0b840382, 0x0b824220, 0x0b840382, 0x0b824320, 0x0b840382, 0x0b824420, 0x0b840382, 0x0b824520, 0x0b840382, 0x0b824620, 0x0b840382, 0x0b824720, + 0x0b840382, 0x0b824820, 0x0b840382, 0x0b824920, 0x0b840382, 0x0b824a20, 0x0b840382, 0x0b824b20, 0x0b840382, 0x0b824c20, 0x0b840382, 0x0b824d20, + 0x0b840382, 0x0b824e20, 0x0b840382, 0x0b824f20, 0x0b840382, 0x0b825020, 0x0b840382, 0x0b825120, 0x0b840382, 0x0b825220, 0x0b840382, 0x0b825320, + 0x0b840382, 0x0b825420, 0x0b840382, 0x0b825520, 0x0b840382, 0x0b825620, 0x0b840382, 0x0b825720, 0x0b840382, 0x0b825820, 0x0b840382, 0x0b825920, + 0x0b840382, 0x0b825a20, 0x0b840382, 0x0b825b20, 0x0b840382, 0x0b825c20, 0x0b840382, 0x0b825d20, 0x0b840382, 0x0b825e20, 0x0b840382, 0x0b825f20, + 0x0b840382, 0x0b826020, 0x0b840382, 0x0b826120, 0x0b840382, 0x0b826220, 0x0b840382, 0x0b826320, 0x0b840382, 0x0b826420, 0x0b840382, 0x0b826520, + 0x0b840382, 0x0b826620, 0x0b840382, 0x0b826720, 0x0b840382, 0x0b826820, 0x0b840382, 0x0b826920, 0x0b840382, 0x0b826a20, 0x0b840382, 0x0b826b20, + 0x0b840382, 0x0b826c20, 0x0b840382, 0x0b826d20, 0x0b840382, 0x0b826e20, 0x0b840382, 0x0b826f20, 0x0b840382, 0x0b827020, 0x0b840382, 0x0b827120, + 0x0b840382, 0x0b827220, 0x0b840382, 0x0b827320, 0x0b840382, 0x0b827420, 0x0b840382, 0x0b827520, 0x0b840382, 0x0b827620, 0x0b840382, 0x0b827720, + 0x0b840382, 0x0b827820, 0x0b840382, 0x0b827920, 0x0b840382, 0x0b827a20, 0x0b840382, 0x0b827b20, 0x0b840382, 0x0b827c20, 0x0b840382, 0x0b827d20, + 0x0b840382, 0x0b827e20, 0x0b840382, 0x0b827f20, 0x0b840382, 0x0b828020, 0x0b840382, 0x0b828120, 0x0b840382, 0x0b828220, 0x0b840382, 0x0b828320, + 0x0b840382, 0x0b828420, 0x0b840382, 0x0b828520, 0x0b840382, 0x0b828620, 0x0b840382, 0x0b828720, 0x0b840382, 0x0b828820, 0x0b840382, 0x0b828920, + 0x0b840382, 0x0b828a20, 0x0b840382, 0x0b828b20, 0x0b840382, 0x0b828c20, 0x0b840382, 0x0b828d20, 0x0b840382, 0x0b828e20, 0x0b840382, 0x0b828f20, + 0x0b840382, 0x0b829020, 0x0b840382, 0x0b829120, 0x0b840382, 0x0b829220, 0x0b840382, 0x0b829320, 0x0b840382, 0x0b829420, 0x0b840382, 0x0b829520, + 0x0b840382, 0x0b829620, 0x0b840382, 0x0b829720, 0x0b840382, 0x0b829820, 0x0b840382, 0x0b829920, 0x0b840382, 0x0b829a20, 0x0b840382, 0x0b829b20, + 0x0b840382, 0x0b829c20, 0x0b840382, 0x0b829d20, 0x0b840382, 0x0b829e20, 0x0b840382, 0x0b829f20, 0x0b840382, 0x0b82a020, 0x0b840382, 0x0b82a120, + 0x0b840382, 0x0b82a220, 0x0b840382, 0x0b82a320, 0x0b840382, 0x0b82a420, 0x0b840382, 0x0b82a520, 0x0b840382, 0x0b82a620, 0x0b840382, 0x0b82a720, + 0x0b840382, 0x0b82a820, 0x0b840382, 0x0b82a920, 0x0b840382, 0x356daa20, 0x82322006, 0x85ab2007, 0x20178403, 0x820b82ac, 0x200b8403, 0x820b82ad, + 0x200b8403, 0x820b82ae, 0x200b8403, 0x820b82af, 0x200b8403, 0x820b82b0, 0x200b8403, 0x820b82b1, 0x200b8403, 0x820b82b2, 0x200b8403, 0x820b82b3, + 0x200b8403, 0x820b82b4, 0x200b8403, 0x820b82b5, 0x200b8403, 0x820b82b6, 0x200b8403, 0x820b82b7, 0x200b8403, 0x820b82b8, 0x200b8403, 0x820b82b9, + 0x200b8403, 0x820b82ba, 0x200b8403, 0x820b82bb, 0x200b8403, 0x820b82bc, 0x200b8403, 0x820b82bd, 0x200b8403, 0x820b82be, 0x200b8403, 0x820b82bf, + 0x200b8403, 0x820b82c0, 0x200b8403, 0x820b82c1, 0x200b8403, 0x820b82c2, 0x200b8403, 0x820b82c3, 0x200b8403, 0x820b82c4, 0x200b8403, 0x820b82c5, + 0x200b8403, 0x820b82c6, 0x200b8403, 0x820b82c7, 0x200b8403, 0x820b82c8, 0x200b8403, 0x820b82c9, 0x200b8403, 0x820b82ca, 0x200b8403, 0x820b82cb, + 0x200b8403, 0x820b82cc, 0x200b8403, 0x820b82cd, 0x200b8403, 0x820b82ce, 0x200b8403, 0x820b82cf, 0x200b8403, 0x820b82d0, 0x200b8403, 0x820b82d1, + 0x200b8403, 0x820b82d2, 0x200b8403, 0x820b82d3, 0x200b8403, 0x820b82d4, 0x200b8403, 0x820b82d5, 0x200b8403, 0x820b82d6, 0x200b8403, 0x820b82d7, + 0x200b8403, 0x820b82d8, 0x200b8403, 0x820b82d9, 0x200b8403, 0x820b82da, 0x200b8403, 0x820b82db, 0x200b8403, 0x820b82dc, 0x200b8403, 0x820b82dd, + 0x200b8403, 0x820b82de, 0x200b8403, 0x820b82df, 0x200b8403, 0x820b82e0, 0x200b8403, 0x820b82e1, 0x200b8403, 0x820b82e2, 0x200b8403, 0x820b82e3, + 0x200b8403, 0x820b82e4, 0x200b8403, 0x820b82e5, 0x200b8403, 0x820b82e6, 0x200b8403, 0x820b82e7, 0x200b8403, 0x820b82e8, 0x200b8403, 0x820b82e9, + 0x200b8403, 0x820b82ea, 0x200b8403, 0x820b82eb, 0x200b8403, 0x820b82ec, 0x200b8403, 0x820b82ed, 0x200b8403, 0x820b82ee, 0x200b8403, 0x820b82ef, + 0x200b8403, 0x820b82f0, 0x200b8403, 0x820b82f1, 0x200b8403, 0x820b82f2, 0x200b8403, 0x820b82f3, 0x200b8403, 0x820b82f4, 0x200b8403, 0x820b82f5, + 0x200b8403, 0x820b82f6, 0x200b8403, 0x820b82f7, 0x200b8403, 0x820b82f8, 0x200b8403, 0x820b82f9, 0x200b8403, 0x820b82fa, 0x200b8403, 0x820b82fb, + 0x200b8403, 0x820b82fc, 0x200b8403, 0x820b82fd, 0x200b8403, 0x820b82fe, 0x200b8403, 0x820b82ff, 0x240b8303, 0x00000004, 0x84038204, 0x8201200b, + 0x8403820b, 0x8202200b, 0x8403820b, 0x8203200b, 0x8403820b, 0x202c820b, 0x84038204, 0x8205200b, 0x84038217, 0x8206200b, 0x8403820b, 0x8207200b, + 0x8403820b, 0x8208200b, 0x8403820b, 0x8209200b, 0x8403820b, 0x820a200b, 0x8403820b, 0x820b200b, 0x8403820b, 0x820c200b, 0x8403820b, 0x820d200b, + 0x8403820b, 0x820e200b, 0x8403820b, 0x820f200b, 0x8403820b, 0x0010260b, 0x00100400, 0x230b8400, 0x04000011, 0x0b840382, 0x00001224, 0x17861204, + 0x00001323, 0x84038204, 0x82142017, 0x8403820b, 0x8215200b, 0x8403820b, 0x8216200b, 0x8403820b, 0x8217200b, 0x8403820b, 0x8218200b, 0x8403820b, + 0x8219200b, 0x8403820b, 0x821a200b, 0x8403820b, 0x821b200b, 0x8403820b, 0x821c200b, 0x8403820b, 0x821d200b, 0x8403820b, 0x821e200b, 0x8403820b, + 0x821f200b, 0x8403820b, 0x8220200b, 0x8403820b, 0x8221200b, 0x8403820b, 0x8222200b, 0x8403820b, 0x8223200b, 0x8403820b, 0x8224200b, 0x8403820b, + 0x8225200b, 0x8403820b, 0x8226200b, 0x8403820b, 0x8227200b, 0x8403820b, 0x8228200b, 0x8403820b, 0x8229200b, 0x8403820b, 0x822a200b, 0x8403820b, + 0x822b200b, 0x8403820b, 0x822c200b, 0x8403820b, 0x822d200b, 0x8403820b, 0x822e200b, 0x8403820b, 0x822f200b, 0x8403820b, 0x8230200b, 0x8403820b, + 0x8231200b, 0x8403820b, 0x8232200b, 0x8403820b, 0x8233200b, 0x8403820b, 0x8234200b, 0x8403820b, 0x8235200b, 0x8403820b, 0x8236200b, 0x8403820b, + 0x8237200b, 0x8403820b, 0x8238200b, 0x8403820b, 0x8239200b, 0x8403820b, 0x823a200b, 0x8403820b, 0x823b200b, 0x8403820b, 0x823c200b, 0x8403820b, + 0x823d200b, 0x8403820b, 0x823e200b, 0x8403820b, 0x823f200b, 0x8403820b, 0x8240200b, 0x8403820b, 0x8241200b, 0x8403820b, 0x8242200b, 0x8403820b, + 0x8243200b, 0x8403820b, 0x8244200b, 0x8403820b, 0x8245200b, 0x8403820b, 0x8246200b, 0x8403820b, 0x8247200b, 0x8403820b, 0x8248200b, 0x8403820b, + 0x8249200b, 0x8403820b, 0x824a200b, 0x8403820b, 0x824b200b, 0x8403820b, 0x824c200b, 0x8403820b, 0x824d200b, 0x8403820b, 0x824e200b, 0x8403820b, + 0x824f200b, 0x8403820b, 0x8250200b, 0x8403820b, 0x8251200b, 0x8403820b, 0x8252200b, 0x8403820b, 0x8253200b, 0x8403820b, 0x8254200b, 0x8403820b, + 0x8255200b, 0x8403820b, 0x8256200b, 0x8403820b, 0x8257200b, 0x8403820b, 0x8258200b, 0x8403820b, 0x8259200b, 0x8403820b, 0x825a200b, 0x8403820b, + 0x825b200b, 0x8403820b, 0x825c200b, 0x8403820b, 0x825d200b, 0x8403820b, 0x825e200b, 0x8403820b, 0x825f200b, 0x8403820b, 0x8260200b, 0x8403820b, + 0x8261200b, 0x8403820b, 0x8262200b, 0x8403820b, 0x8263200b, 0x8403820b, 0x8264200b, 0x8403820b, 0x8265200b, 0x8403820b, 0x8266200b, 0x8403820b, + 0x8267200b, 0x8403820b, 0x8268200b, 0x8403820b, 0x8269200b, 0x8403820b, 0x826a200b, 0x8403820b, 0x826b200b, 0x8403820b, 0x826c200b, 0x8403820b, + 0x826d200b, 0x8403820b, 0x826e200b, 0x8403820b, 0x826f200b, 0x8403820b, 0x8270200b, 0x8403820b, 0x8271200b, 0x8403820b, 0x8272200b, 0x8403820b, + 0x8273200b, 0x8403820b, 0x8274200b, 0x8403820b, 0x8275200b, 0x8403820b, 0x8276200b, 0x8403820b, 0x8277200b, 0x8403820b, 0x8278200b, 0x8403820b, + 0x8279200b, 0x8403820b, 0x827a200b, 0x8403820b, 0x827b200b, 0x8403820b, 0x827c200b, 0x8403820b, 0x827d200b, 0x8403820b, 0x827e200b, 0x8403820b, + 0x827f200b, 0x8403820b, 0x8280200b, 0x8403820b, 0x8281200b, 0x8403820b, 0x8282200b, 0x8403820b, 0x8283200b, 0x8403820b, 0x8284200b, 0x8403820b, + 0x8285200b, 0x8403820b, 0x8286200b, 0x8403820b, 0x8287200b, 0x8403820b, 0x8288200b, 0x8403820b, 0x8289200b, 0x8403820b, 0x828a200b, 0x8403820b, + 0x828b200b, 0x8403820b, 0x828c200b, 0x8403820b, 0x828d200b, 0x8403820b, 0x828e200b, 0x8403820b, 0x828f200b, 0x8403820b, 0x8290200b, 0x8403820b, + 0x8291200b, 0x8403820b, 0x8292200b, 0x8403820b, 0x8293200b, 0x8403820b, 0x8294200b, 0x8403820b, 0x8295200b, 0x8403820b, 0x8296200b, 0x8403820b, + 0x8297200b, 0x8403820b, 0x8298200b, 0x8403820b, 0x8299200b, 0x8403820b, 0x829a200b, 0x8403820b, 0x829b200b, 0x8403820b, 0x829c200b, 0x8403820b, + 0x829d200b, 0x8403820b, 0x829e200b, 0x8403820b, 0x829f200b, 0x8403820b, 0x82a0200b, 0x8403820b, 0x82a1200b, 0x8403820b, 0x82a2200b, 0x06ff4b0b, + 0x82a30421, 0x06ff4b0b, 0x82a40421, 0x8403820b, 0x82a52023, 0x8403820b, 0x82a6200b, 0x8403820b, 0x82a7200b, 0x8403820b, 0x82a8200b, 0x8403820b, + 0x82a9200b, 0x8403820b, 0x82aa200b, 0x8403820b, 0x82ab200b, 0x8403820b, 0x82ac200b, 0x8403820b, 0x82ad200b, 0x8403820b, 0x82ae200b, 0x8403820b, + 0x82af200b, 0x8403820b, 0x82b0200b, 0x8403820b, 0x82b1200b, 0x8403820b, 0x82b2200b, 0x8403820b, 0x82b3200b, 0x8403820b, 0x82b4200b, 0x8403820b, + 0x82b5200b, 0x8403820b, 0x82b6200b, 0x8403820b, 0x82b7200b, 0x8403820b, 0x82b8200b, 0x8403820b, 0x82b9200b, 0x8403820b, 0x82ba200b, 0x8403820b, + 0x82bb200b, 0x8403820b, 0x82bc200b, 0x8403820b, 0x82bd200b, 0x8403820b, 0x82be200b, 0x8403820b, 0x82bf200b, 0x8403820b, 0x82c0200b, 0x8403820b, + 0x82c1200b, 0x8403820b, 0x82c2200b, 0x8403820b, 0x82c3200b, 0x8403820b, 0x82c4200b, 0x8403820b, 0x82c5200b, 0x8403820b, 0x82c6200b, 0x8403820b, + 0x82c7200b, 0x8403820b, 0x82c8200b, 0x8403820b, 0x82c9200b, 0x8403820b, 0x82ca200b, 0x8403820b, 0x82cb200b, 0x8403820b, 0x82cc200b, 0x8403820b, + 0x82cd200b, 0x8403820b, 0x82ce200b, 0x8403820b, 0x82cf200b, 0x8403820b, 0x82d0200b, 0x8403820b, 0x82d1200b, 0x8403820b, 0x82d2200b, 0x8403820b, + 0x82d3200b, 0x8403820b, 0x82d4200b, 0x8403820b, 0x82d5200b, 0x8403820b, 0x82d6200b, 0x8403820b, 0x82d7200b, 0x8403820b, 0x82d8200b, 0x8403820b, + 0x82d9200b, 0x8403820b, 0x82da200b, 0x8403820b, 0x82db200b, 0x8403820b, 0x82dc200b, 0x8403820b, 0x82dd200b, 0x8403820b, 0x82de200b, 0x8403820b, + 0x82df200b, 0x8403820b, 0x82e0200b, 0x8403820b, 0x82e1200b, 0x8403820b, 0x82e2200b, 0x8403820b, 0x82e3200b, 0x8403820b, 0x82e4200b, 0x8403820b, + 0x82e5200b, 0x8403820b, 0x82e6200b, 0x8403820b, 0x82e7200b, 0x8403820b, 0x82e8200b, 0x8403820b, 0x82e9200b, 0x8403820b, 0x82ea200b, 0x8403820b, + 0x82eb200b, 0x8403820b, 0x82ec200b, 0x8403820b, 0x82ed200b, 0x8403820b, 0x82ee200b, 0x8403820b, 0x82ef200b, 0x8403820b, 0x82f0200b, 0x8403820b, + 0x82f1200b, 0x8403820b, 0x82f2200b, 0x8403820b, 0x82f3200b, 0x8403820b, 0x82f4200b, 0x8403820b, 0x82f5200b, 0x8403820b, 0x82f6200b, 0x8403820b, + 0x82f7200b, 0x8403820b, 0x82f8200b, 0x8403820b, 0x82f9200b, 0x8403820b, 0x82fa200b, 0x8403820b, 0x82fb200b, 0x8403820b, 0x82fc200b, 0x8403820b, + 0x82fd200b, 0x8403820b, 0x82fe200b, 0x8403820b, 0x82ff200b, 0x8303820b, 0x0005240b, 0x82050000, 0x200b8403, 0x820b8201, 0x200b8403, 0x820b8202, + 0x200b8403, 0x820b8203, 0x200b8403, 0x820b8204, 0x820b8403, 0x82052038, 0x200b8403, 0x82178206, 0x200b8403, 0x820b8207, 0x200b8403, 0x820b8208, + 0x200b8403, 0x820b8209, 0x200b8403, 0x820b820a, 0x200b8403, 0x820b820b, 0x200b8403, 0x820b820c, 0x200b8403, 0x820b820d, 0x200b8403, 0x820b820e, + 0x200b8403, 0x820b820f, 0x200b8403, 0x820b8210, 0x200b8403, 0x820b8211, 0x200b8403, 0x820b8212, 0x200b8403, 0x820b8213, 0x260b8403, 0x05000014, + 0x84000014, 0x0015230b, 0x03820500, 0x16240b84, 0x16050000, 0x17231786, 0x82050000, 0x20178403, 0x820b8218, 0x200b8403, 0x820b8219, 0x200b8403, + 0x820b821a, 0x200b8403, 0x820b821b, 0x200b8403, 0x820b821c, 0x200b8403, 0x820b821d, 0x200b8403, 0x820b821e, 0x200b8403, 0x820b821f, 0x200b8403, + 0x820b8220, 0x200b8403, 0x820b8221, 0x200b8403, 0x820b8222, 0x200b8403, 0x820b8223, 0x200b8403, 0x820b8224, 0x200b8403, 0x820b8225, 0x200b8403, + 0x820b8226, 0x200b8403, 0x820b8227, 0x200b8403, 0x820b8228, 0x200b8403, 0x820b8229, 0x200b8403, 0x820b822a, 0x200b8403, 0x820b822b, 0x200b8403, + 0x820b822c, 0x200b8403, 0x820b822d, 0x200b8403, 0x820b822e, 0x200b8403, 0x820b822f, 0x240b8303, 0x00000b20, 0x06bb4120, 0x82102021, 0x8403820b, + 0x82112017, 0x8403820b, 0x8213200b, 0x2103820b, 0x0782dd01, 0x03851420, 0x18201784, 0x03820b82, 0x19200b84, 0x03820b82, 0x1c200b84, 0x03820b82, + 0x82510221, 0x851d2007, 0x52022103, 0x20200782, 0x23840385, 0x0b822120, 0x0b840382, 0x2020f782, 0x0b840382, 0x17823020, 0x0b840382, 0x0b823220, + 0x0b840382, 0x0b823320, 0x0b840382, 0x0b823920, 0x02210382, 0x2007824a, 0x2103853a, 0x07824b02, 0x0385a420, 0x82a10221, 0x85a82007, 0x86022103, + 0xa9200782, 0x02210385, 0x20078289, 0x210385aa, 0x0782da02, 0x0385ac20, 0x82840221, 0x85b42007, 0xe4042103, 0xb8200782, 0x05210385, 0x20078236, + 0x250385bd, 0x00008802, 0x03852221, 0x820d0321, 0x85902007, 0xd6012103, 0x91200782, 0x01210385, 0x200782d8, 0x21038592, 0x0782d701, 0x03859320, + 0x82d90121, 0x85942007, 0x52032103, 0x95200782, 0x03210385, 0x20078253, 0x21038597, 0x07825903, 0x0385ba20, 0x82300221, 0x85bb2007, 0x9e012103, + 0xc4200782, 0x02250385, 0x22000037, 0x21038512, 0x0782dd01, 0x03851e20, 0x00f10325, 0x85032300, 0x4c022103, 0x04200782, 0x02210385, 0x2007824d, + 0x2003851b, 0x20138303, 0x820b8228, 0x82022003, 0x2923216b, 0x03820b82, 0x82cc0121, 0x852a2007, 0xcd012103, 0x2b200782, 0x04210385, 0x20078215, + 0x21038599, 0x0782ad01, 0x0385cf20, 0x82cb0121, 0x85e92007, 0xc8012103, 0xea200782, 0x01200385, 0x2321a382, 0x820b82ed, 0xc9012103, 0xee200782, + 0x01210385, 0x830782c3, 0x2103829f, 0x0b824203, 0x0385f320, 0x82050321, 0x85f82007, 0xc6012103, 0xf9200782, 0x01210385, 0x200782c7, 0x210385fb, + 0x07829601, 0x0385fe20, 0x009b0225, 0x85bd2400, 0x98032503, 0xa0250000, 0x02210385, 0x2007821d, 0x210385b6, 0x0782c501, 0x2520a782, 0x02210382, + 0x200b8254, 0x210385d0, 0x0782be01, 0x25205382, 0x2f840382, 0x0f82fc20, 0x0b830382, 0x00002624, 0x03822600, 0x009a0225, 0x85012600, 0x17022103, + 0x03200782, 0x05210385, 0x20078234, 0x21038504, 0x0782ff04, 0x03851120, 0x827c0221, 0x85152007, 0x82052003, 0x82262040, 0x21038387, 0x13820902, + 0x03852020, 0x82ec0421, 0x85222007, 0x28052103, 0x23200782, 0x05210385, 0x2007820e, 0x20038525, 0x21c78204, 0x0b822a26, 0x04210382, 0x200782c4, + 0x2103852c, 0x0782b204, 0x03852e20, 0x82b90421, 0x852f2007, 0xcb042103, 0x38200782, 0x04210385, 0x200782a7, 0x21038539, 0x07825602, 0x03853f20, + 0x82e50221, 0x85402007, 0xe3022103, 0x42200782, 0x02210385, 0x200782e4, 0x2103855a, 0x07827b03, 0x03855b20, 0x827e0321, 0x855c2007, 0x7f032103, + 0x5d200782, 0x03210385, 0x20078279, 0x2103855e, 0x07827c03, 0x03855f20, 0x827d0321, 0x85652007, 0x8b012103, 0x66200782, 0x02210385, 0x200782dd, + 0x21038572, 0x0782ad02, 0x03857a20, 0x7b200b84, 0x03820b82, 0x7e200b84, 0x03820b82, 0x82f10321, 0x85802007, 0x83032003, 0x8281209b, 0x2103820b, + 0x0782e703, 0x03858220, 0x82e60321, 0x85832007, 0x83032003, 0x828420cb, 0x2103820b, 0x0782e203, 0x03858520, 0x82e50321, 0x85932007, 0x71022103, + 0x96200782, 0x03210385, 0x20078201, 0x25038599, 0x00009801, 0x03859b26, 0x82810421, 0x85a02007, 0xe4012103, 0xa1200782, 0x02210385, 0x20078232, + 0x210385a2, 0x0782e802, 0x0385a320, 0x82e90221, 0x85a42007, 0xea022103, 0xa5200782, 0x02210385, 0x200782e6, 0x210385a6, 0x0782eb02, 0x0385a720, + 0x82e70221, 0x85a82007, 0xec022103, 0xa9200782, 0x02210385, 0x200782ed, 0x210385aa, 0x07825402, 0x0385ab20, 0xb2200b84, 0x03820b82, 0x82ee0221, + 0x85bd2007, 0xc5022103, 0xbe200782, 0x03210385, 0x20078275, 0x210385c4, 0x07823405, 0x03821b83, 0x82d20421, 0x85c6200b, 0xf8042103, 0xdf200782, + 0x02210385, 0x20078225, 0x210385e9, 0x0782c804, 0x0382b783, 0x82dc0321, 0x85f7200b, 0x2f052103, 0xfa200782, 0x04210385, 0x200782ce, 0x200385fd, + 0x18a78203, 0x2507a240, 0x00001902, 0x03850227, 0x04200b84, 0x03820b82, 0x05200b84, 0x03820b82, 0x827c0221, 0x85092007, 0x82022003, 0x0a272153, + 0x03820b82, 0x82db0421, 0x850b2007, 0x07032103, 0x0c200782, 0x03200385, 0x0f200783, 0x03820b82, 0x82480321, 0x85112007, 0x63042103, 0x12200782, + 0x04210385, 0x20078262, 0x21038513, 0x07829201, 0x03851420, 0x15200b84, 0x03820b82, 0x82930121, 0x85162007, 0x200b8403, 0x820b821d, 0xa6042103, + 0x21200782, 0x04210385, 0x200782c5, 0x21038531, 0x07820600, 0x03854420, 0x823c0321, 0x85462007, 0x200b8403, 0x820b824c, 0x20478403, 0x820b824e, + 0x3a032103, 0x53200782, 0x00200385, 0x54206783, 0x03820b82, 0x55200b84, 0x03820b82, 0x82020021, 0x85572007, 0x200b8403, 0x820b8264, 0x8b012103, + 0x95200782, 0x00200385, 0x9620fb83, 0x03820b82, 0x82dd0121, 0x85972007, 0xe8032503, 0x34290000, 0x03210385, 0x20078261, 0x25038535, 0x00006003, + 0x03850d2b, 0x7f820320, 0x821b2b21, 0x2103820b, 0x07828503, 0x03851c20, 0x24200b84, 0x03820b82, 0x93820220, 0x82502b21, 0x2503820b, 0x00008c01, + 0x038205e0, 0x0021eb82, 0x82078233, 0x82e02047, 0x35002103, 0x12200b82, 0x00210385, 0x20078236, 0x2403823f, 0x00000041, 0x20078237, 0x20038259, + 0x820b8276, 0x82e020ef, 0x86e02163, 0x58200b82, 0xa7821382, 0x8298e021, 0x825a200b, 0x859a200b, 0x5c002103, 0xa9200782, 0x00210385, 0x2007825d, + 0x210385ac, 0x07825e00, 0x0385b420, 0x825f0021, 0x85b72007, 0x82002003, 0xbbe021cb, 0x03820b82, 0xe3820020, 0x82cfe021, 0x2103820b, 0x07823905, + 0x0385d820, 0x82620021, 0x85df2007, 0x63002103, 0xe3200782, 0xe4200382, 0x64247782, 0x31e10000, 0x00210385, 0x82078266, 0x3ce12133, 0x67201782, + 0x40200b82, 0x00210385, 0x2007826b, 0x21038552, 0x07826c00, 0xe1203f82, 0x00210382, 0x200b826d, 0x21038569, 0x07826e00, 0x03820f83, 0x826f0021, + 0x857b200b, 0x70002103, 0x84200782, 0xf3820382, 0x82710021, 0x858f2007, 0x73002103, 0xef820782, 0x829be121, 0x8274206b, 0x85a8200b, 0x76002103, + 0xb0200782, 0x00210385, 0x20078277, 0x210385bc, 0x07827800, 0x0385c420, 0x82790021, 0x85c82007, 0x7a002103, 0xd3200782, 0x00210385, 0x2007827b, + 0x210385d5, 0x07827c00, 0x0385d720, 0x827d0021, 0x85ed2007, 0x7e002103, 0xf3200782, 0x00210385, 0x2007827f, 0x210385f6, 0x07828000, 0x0385fe20, + 0x00810025, 0x8509e200, 0x82002103, 0x21200782, 0x22200382, 0x8320a782, 0x2d200782, 0x00200385, 0xe221cf82, 0x820b823d, 0x86002103, 0x89200782, + 0x00210385, 0x20078287, 0x2103859c, 0x07828800, 0x0385b720, 0x1f830020, 0x0b82bb20, 0x00210382, 0x2007828a, 0x210385c5, 0x07828b00, 0x0385ca20, + 0x828c0021, 0x82cd2007, 0x82ce2003, 0x828d206b, 0x85eb2007, 0x8f002503, 0x1ee30000, 0x00210385, 0x20078290, 0x210385af, 0x07829100, 0x0382b120, + 0x2f82b220, 0x07829220, 0x0385f520, 0x00940025, 0x853ce400, 0x95002103, 0x45200782, 0x00210385, 0x20078296, 0x20038247, 0x202f8248, 0x20078297, + 0x2103856c, 0x07829900, 0x03857320, 0x829a0021, 0x82762007, 0x82772003, 0x829b2023, 0x827a2007, 0x827b2003, 0x829d200b, 0x85902007, 0x9f002103, + 0x94200782, 0x00210385, 0x200782a0, 0x210385a5, 0x0782a100, 0x0382a820, 0x2f82ad20, 0x0782a220, 0x0382af20, 0x0b82b020, 0xb3201383, 0x03820b82, + 0x82aa0021, 0x82b52007, 0x82cc2003, 0x82ab2017, 0x82ce2007, 0x82de2003, 0x82c3200b, 0x82e02007, 0x82e62003, 0x82d4200b, 0x82e82007, 0x21ff8203, + 0x0782db00, 0x0385ed20, 0x82df0021, 0x85ee2007, 0x24778403, 0xe50000ef, 0x822f8203, 0x07e52137, 0x25200b82, 0xf5200b82, 0x27200782, 0x2f240382, + 0x14010000, 0x32200782, 0x4f200382, 0x1d200b82, 0x51200782, 0x58200382, 0x3b200b82, 0x5a200782, 0x6f200382, 0x43200b82, 0x71200782, 0x74200382, + 0x59200b82, 0x76200782, 0x87200382, 0x5d200b82, 0x89200782, 0x8f200382, 0x27820b82, 0x8291e521, 0x829a200b, 0x201f830b, 0x200b829c, 0x200b829d, + 0x20078280, 0x820382a0, 0x820121f7, 0xa9200782, 0xdf820382, 0x82840121, 0x20fb8207, 0x210382e5, 0x0b828601, 0x0385b420, 0x57820120, 0x0000f025, + 0x8202f000, 0x8288203b, 0x20bb8207, 0x200382f0, 0x21ab8202, 0x0f8204f0, 0x00000524, 0x07828b01, 0x03850620, 0x828c0121, 0x82072007, 0x000e2403, + 0x828d0100, 0x82102007, 0x82132003, 0x8295200b, 0x20db8207, 0x210382f0, 0x0b824003, 0x03851520, 0x82990121, 0x85162007, 0x8a022103, 0x17200782, + 0x19200382, 0xb7822f82, 0x821af021, 0x2103820b, 0x07825403, 0x03851b20, 0x82570321, 0x851c2007, 0x82012003, 0x1df021cf, 0x03820b82, 0x82770221, + 0x851e2007, 0x9e012103, 0x21200782, 0x3e200382, 0x9f204782, 0x6f830782, 0x03210382, 0x200b8248, 0x20038241, 0x20178244, 0x200782bd, 0x21038545, + 0x07827f02, 0x03854620, 0x827c0221, 0x82472007, 0x824e2003, 0x82c12023, 0x82502007, 0x825b2003, 0x82c9200b, 0x855c2007, 0xd0012103, 0x5d200782, + 0x01210385, 0x200782d1, 0x2103855e, 0x0782d501, 0x03826020, 0x2f826620, 0x0782d620, 0x03856720, 0x82070021, 0x85682007, 0xdd012103, 0x69200782, + 0x00210385, 0x20078206, 0x2403826a, 0x0100006e, 0x200782de, 0x20038270, 0x200b827e, 0x200782e3, 0x21038580, 0x0782f201, 0x03828320, 0x17828620, + 0x0782f320, 0x03858720, 0x82920221, 0x85882007, 0x93022103, 0x89200782, 0x01210385, 0x200782f7, 0x2103858a, 0x07828b01, 0x01210386, 0x200b82f8, + 0x2003828d, 0x2047828e, 0x200782f9, 0x20038290, 0x200b8291, 0x200782fb, 0x20038293, 0x200b8295, 0x200782fd, 0x21038596, 0x07821d02, 0x03859720, + 0x82ac0121, 0x85982007, 0x00022103, 0x9c200782, 0x9e240382, 0x01020000, 0xa0200782, 0xa1200382, 0x04200b82, 0xa2200782, 0x02210385, 0x2007823d, + 0x200382a3, 0x201782ae, 0x20078206, 0x200382b0, 0x200b82b2, 0x20078212, 0x200382c0, 0x200b82ce, 0x20078215, 0x200382d0, 0x200b82d1, 0x20078224, + 0x200382d6, 0x200b82de, 0x20078226, 0x210385e0, 0x07822f02, 0x0382e220, 0x1782e320, 0x07823020, 0x0385e420, 0x8b830420, 0x0b82e520, 0x01210382, + 0x200782e8, 0x210385e6, 0x0782f601, 0x0382e720, 0x2f82ee20, 0x07823220, 0x0382f020, 0x0b82f420, 0x07823a20, 0x0385f520, 0x823e0321, 0x85f62007, + 0x8b022103, 0xf7200782, 0x02210385, 0x200782a8, 0x200382f8, 0x054372fe, 0xe782f120, 0x8207f121, 0x0046240b, 0x8508f100, 0x5e032103, 0x09200782, + 0x0b240382, 0x4e020000, 0x0c200782, 0x02210385, 0x20078254, 0x2003820d, 0x2017820e, 0x20078251, 0x20038210, 0x200b8211, 0x20078253, 0x21038512, + 0x07826b03, 0x03851420, 0x9f820120, 0xff82f120, 0x01210383, 0x201382ef, 0x20038218, 0x202f821c, 0x20078255, 0x2103851d, 0x0782a201, 0x03851e20, + 0x825a0221, 0x82202007, 0x82222003, 0x825b2023, 0x85232007, 0x82012003, 0x24f121bb, 0x27200b82, 0x9b831782, 0x0b822820, 0x00210382, 0x20078216, + 0x21038529, 0x07826202, 0x03852a20, 0x82020021, 0x822b2007, 0x822e2003, 0x8263202f, 0x82302007, 0x82352003, 0x8267200b, 0x82372007, 0x823a2003, + 0x826d200b, 0x823d2007, 0x823e2003, 0x8271200b, 0x82402007, 0x82462003, 0x8273200b, 0x85472007, 0x79022103, 0x48200782, 0x4e200382, 0x7a201782, + 0x50200782, 0x54200382, 0x81200b82, 0xc3830782, 0x00210382, 0x200b8204, 0x20038256, 0x20178259, 0x20078286, 0x8203825b, 0x8a0221a3, 0x60200782, + 0x65200382, 0x8e201782, 0x75200782, 0x78200382, 0x94200b82, 0x82200782, 0x83200382, 0x98200b82, 0x85200782, 0x88200382, 0x9a200b82, 0x27830782, + 0x03200382, 0x90204f83, 0x03820f82, 0x63820320, 0x8291f121, 0x8293200b, 0x829e2023, 0x85952007, 0xa1022103, 0x96200782, 0x02210385, 0x20078245, + 0x21038597, 0x0782a202, 0x03859920, 0x82a30221, 0x829c2007, 0x829d2003, 0x82a4203b, 0x82ab2007, 0x82ae2003, 0x82a6200b, 0x85b02007, 0xaa022103, + 0xb1200782, 0x03210385, 0x2007823d, 0x200382b2, 0x832382b3, 0x82b8202b, 0x82bb200b, 0x82ad200b, 0x82c02007, 0x82c92003, 0x82b1200b, 0x82cd2007, + 0x82ce2003, 0x211b820b, 0x0b82d8f1, 0x02210382, 0x200782bd, 0x840385d9, 0x82da200b, 0x2103820b, 0x0782be02, 0x0385db20, 0x82540221, 0x82dc2007, + 0x82de2003, 0x82bf203b, 0x82e02007, 0x82e62003, 0x82c2200b, 0x82ea2007, 0x82ec2003, 0x2163820b, 0x0b82f6f1, 0x02210382, 0x200782cc, 0x840385f7, + 0x82f8200b, 0x82f9200b, 0x207f8323, 0x820b82fa, 0x17002103, 0xfb200782, 0xfe200382, 0xcf241782, 0x00f20000, 0x01200382, 0xd3200b82, 0x04200782, + 0x07200382, 0xd5200b82, 0x0a200782, 0x0b240382, 0xd9020000, 0x33820782, 0x821ef221, 0x82db200b, 0x8221200b, 0x822d2003, 0x82e3200b, 0x82332007, + 0x82362003, 0x82f0200b, 0x82382007, 0x82392003, 0x82f4200b, 0x82402007, 0x82492003, 0x82f6200b, 0x854a2007, 0xff022103, 0x4d200782, 0x4e230382, + 0x83030000, 0x82502073, 0x2103820b, 0x07820503, 0x03825120, 0x17825d20, 0x07820220, 0x03856c20, 0x820f0321, 0x82712007, 0x82772003, 0x82102017, + 0x85782007, 0x83032003, 0x8279208b, 0x827a200b, 0x200b8317, 0x820b827b, 0xab032103, 0x83200782, 0x02200385, 0x8b204783, 0x03820b82, 0x82190321, + 0x858c2007, 0x200b8403, 0x820b828d, 0x1a032103, 0x8e200782, 0x0b840385, 0x0b829020, 0x53829120, 0x07821b20, 0x03859220, 0xf221a883, 0x820b8295, + 0x83002003, 0x829a20a7, 0x2103820b, 0x07821d03, 0x03859c20, 0x82d20121, 0x829d2007, 0x829e2003, 0x821e203b, 0x82a02007, 0x82a42003, 0x8220200b, + 0x82a72007, 0x82a82003, 0x8225200b, 0x82b42007, 0x6bb62003, 0xf22105a7, 0x820b82b7, 0x29032103, 0xb9200782, 0x03210385, 0x2007822a, 0x840385ba, + 0x82bb200b, 0x2103820b, 0x07822b03, 0x0385bc20, 0xbd200b84, 0x03820b82, 0x822c0321, 0x85be2007, 0x200b8403, 0x820b82c0, 0x82012003, 0xc1f221db, + 0xc2200b82, 0x2d206b82, 0xc3200782, 0x03210385, 0x2007822e, 0x200382c7, 0x05cb6bce, 0x82d0f221, 0x6bd3200b, 0xf2210577, 0x820b82d4, 0x71032103, + 0xdb200782, 0xdc200382, 0x3b201782, 0xe5200782, 0x03210385, 0x2007823d, 0x210385e7, 0x07823e03, 0x0385ea20, 0x823f0321, 0x85ed2007, 0x40032103, + 0xf1200782, 0xf2200382, 0x2105536b, 0x0b82f5f2, 0x0b82f620, 0x07824320, 0x0385f920, 0x82450321, 0x85fe2007, 0x46032503, 0x02f30000, 0x05200382, + 0x21053b6b, 0x0b8209f3, 0x176b0c20, 0x1cf32105, 0x03820b82, 0x824f0321, 0x851e2007, 0x50032103, 0x28200782, 0x03210385, 0x20078251, 0x21038532, + 0x0782ae01, 0x03823720, 0x3b823820, 0x07825220, 0x03825820, 0x0b825b20, 0x07825420, 0x03855d20, 0x13830320, 0x0b826020, 0x03210382, 0x20078259, + 0x20038262, 0x20238263, 0x2007825a, 0x20038581, 0x213f8202, 0x0b8282f3, 0x02210382, 0x20078239, 0x20038286, 0x05db6a87, 0x8290f321, 0x2103820b, + 0x07825e03, 0x0385a520, 0x825f0321, 0x82be2007, 0x82bf2003, 0x82602023, 0x85c12007, 0x62032103, 0xc5200782, 0x03200385, 0xf3216382, 0x820b82c9, + 0x64032103, 0xcd200782, 0xcf200382, 0x65202f82, 0xd1200782, 0x03210385, 0x20078268, 0x210385dd, 0x07826903, 0x0385e020, 0x826a0321, 0x85e52007, + 0x6b032103, 0xed200782, 0x03210385, 0x2007826c, 0x200382fa, 0x204782fb, 0x2007826d, 0x210385fd, 0x07829604, 0x0385ff20, 0x006f0325, 0x8506f400, + 0x70032103, 0x10200782, 0x03210385, 0x20078271, 0x21038522, 0x07827203, 0x03852420, 0x82730321, 0x85252007, 0x27032103, 0x32200782, 0x34200382, + 0x74205f82, 0x36200782, 0x03210385, 0x20078277, 0x20038239, 0x059f6a3a, 0x823cf421, 0x2103820b, 0x07827a03, 0x03853f20, 0x827b0321, 0x85412007, + 0x7c032103, 0x43200782, 0x03210385, 0x2007827d, 0x21038545, 0x07827e03, 0x03854720, 0x827f0321, 0x854b2007, 0x80032103, 0x4e200782, 0x03210385, + 0x20078281, 0x21038550, 0x07828203, 0x03855320, 0x82830321, 0x85582007, 0x84032103, 0x5c200782, 0x5d200382, 0x85208f82, 0x5f200782, 0x03210385, + 0x20078287, 0x20038261, 0x20178262, 0x20078288, 0x21038566, 0x07828a03, 0x03826820, 0x17826d20, 0x07828b20, 0x03827020, 0x0b827220, 0x07829120, + 0x0382e783, 0x82940321, 0x20e7830b, 0x20178279, 0x200b8295, 0x2003857d, 0x83df8302, 0x827f20b7, 0x82982017, 0x82812013, 0x21978203, 0x07829a03, + 0x73828783, 0x829c0321, 0x8257830b, 0xa0032103, 0x8d200b82, 0x8e200382, 0xa1202f82, 0x90200782, 0x5b820382, 0x82a30321, 0x82962007, 0x82972003, + 0x82a82017, 0x859e2007, 0xaa032103, 0xa1200782, 0x03200385, 0xf4213f82, 0x820b82ad, 0xab032103, 0xb3200782, 0x03210385, 0x200782ac, 0x200382b8, + 0x823b82ba, 0xbdf4211b, 0xbe200b82, 0xb0200b82, 0xc0200782, 0xc2200382, 0xb2200b82, 0xc4200782, 0x03210385, 0x200782b5, 0x210385c6, 0x0782b603, + 0x0382cd20, 0x2382ce20, 0x0782b720, 0x0385d320, 0x82b90321, 0x82d62007, 0x82db2003, 0x21578217, 0x0b82def4, 0x0b82df20, 0x0782c020, 0x0382e220, + 0x0b82e320, 0x0782c220, 0x0385e620, 0x82270321, 0x00fa2407, 0x8209f500, 0x82c42017, 0x82152007, 0x822b2003, 0x82d4200b, 0x852c2007, 0x14002103, + 0x2d200782, 0x30200382, 0xeb201782, 0x31200782, 0x00200385, 0x32202b83, 0x35200b82, 0xef201782, 0x36200782, 0x00210385, 0x20078213, 0x20038237, + 0x20178240, 0x200782f3, 0x21038541, 0x07820500, 0x03824220, 0x17829120, 0x0782fd20, 0x03829320, 0x00009d24, 0x07824d04, 0x03829f20, 0xa762a220, + 0xa4f52105, 0xa7200b82, 0x5c200b82, 0xaa200782, 0xb1200382, 0x21055f62, 0x0b82b3f5, 0x0b82b420, 0x07826820, 0x0382b620, 0xff61b820, 0xbaf52105, + 0xbd200b82, 0x6d200b82, 0xbf200782, 0xc5200382, 0x71200b82, 0xc7200782, 0xcb200382, 0x21057b61, 0x0b82cdf5, 0x0b82ce20, 0x07827d20, 0x0382d020, + 0x3f61d220, 0xd7f52105, 0x03820b82, 0x82820421, 0x85da2007, 0x83042103, 0xdc200782, 0x04210385, 0x20078284, 0x200382de, 0x202f82df, 0x20078285, + 0x210385e1, 0x07828704, 0x0385e420, 0x82880421, 0x85e72007, 0x89042103, 0xeb200782, 0x04210385, 0x2007828a, 0x210385ee, 0x07828b04, 0x0382fc20, + 0x0425f782, 0xf600008c, 0x21038501, 0x07828e04, 0x03850420, 0x828f0421, 0x85102007, 0x90042103, 0x13200782, 0x04210385, 0x20078291, 0x21038519, + 0x07829204, 0x03851f20, 0x82930421, 0x85212007, 0x94042103, 0x24200782, 0x25240382, 0x95040000, 0x29200782, 0x2a200382, 0x97200b82, 0x2e200782, + 0x30200382, 0x99200b82, 0x37200782, 0x04210385, 0x2007829c, 0x2003823b, 0x2017823c, 0x2007829d, 0x21038541, 0x07829f04, 0x03854420, 0x82a00421, + 0x85472007, 0xa1042103, 0x4a200782, 0x04210385, 0x200782a2, 0x2103854f, 0x0782a304, 0x03855120, 0x82a40421, 0x82532007, 0x82552003, 0x82a52053, + 0x85582007, 0xa8042103, 0x5d200782, 0x5e200382, 0xa9201782, 0x62200782, 0x04210385, 0x200782ab, 0x20038264, 0x20178266, 0x200782ac, 0x20038269, + 0x200b826b, 0x200782af, 0x2103856d, 0x0782b204, 0x03856f20, 0x82b30421, 0x85742007, 0xb4042103, 0x76200782, 0x04210385, 0x200782b5, 0x20038278, + 0x203b8279, 0x200782b6, 0x2003827b, 0x200b827c, 0x200782b8, 0x2103857f, 0x0782ba04, 0x03828120, 0x67608420, 0x87f62105, 0x89200b82, 0x21054360, + 0x0b8296f6, 0x04210382, 0x200782c2, 0x20038298, 0x2017829b, 0x200782c3, 0x200382a0, 0x050760a1, 0x82a7f621, 0x2103820b, 0x0782c904, 0x0385a920, + 0x82ca0421, 0x85ad2007, 0xcb042103, 0x7b830782, 0x2f82b720, 0x0b82cc20, 0x0385bb20, 0x82ce0421, 0x85be2007, 0xcf042103, 0xc0200782, 0x04210385, + 0x830782d0, 0x82c42063, 0x82d1202f, 0x85c8200b, 0xd3042103, 0x27830782, 0x04210382, 0x200b82d4, 0x210385d1, 0x0782d504, 0x0385d320, 0x82d60421, + 0x820f8307, 0xd7042103, 0x03860b82, 0x82d80421, 0x85d9200b, 0x83042003, 0x82dd2007, 0x5fde200b, 0xf62105e3, 0x200b82e2, 0x05d75fe3, 0x82e6f621, + 0x2003820b, 0x211b8204, 0x0b82e8f6, 0x04210382, 0x200782df, 0x200382ec, 0x05cb5fed, 0x82f0f621, 0x5ff2200b, 0xf62105bf, 0x820b82fa, 0xe5042103, + 0xfc200782, 0x04200385, 0xf6253f82, 0xf70000ff, 0x05a75f00, 0x820bf721, 0x5f0c200b, 0xf721059b, 0x820b820e, 0xeb042103, 0x14200782, 0x15200382, + 0x5b821782, 0x8217f721, 0x2103820b, 0x0782ee04, 0x03851e20, 0x82ef0421, 0x85222007, 0xf0042103, 0x28200782, 0x29200382, 0xf1202f82, 0x2b200782, + 0x04210385, 0x200782f3, 0x2003822e, 0x05775f2f, 0x823bf721, 0x823d200b, 0x82f6200b, 0x85402007, 0xf9042103, 0x43200782, 0x04200385, 0xf721ab82, + 0x820b8247, 0xfb042103, 0x4d200782, 0x04200385, 0xf721bb82, 0x200b8251, 0x203b8253, 0x200782fd, 0x20038556, 0x21c38205, 0x0b825af7, 0x00005b24, + 0x07820105, 0x03825e20, 0x0b825f20, 0x07820320, 0x03856920, 0x24820520, 0x826bf721, 0x5f6c200b, 0xf7210523, 0x200b826f, 0x200b8270, 0x20078208, + 0x20038272, 0x200b8273, 0x2007820a, 0x2003827c, 0x200b827d, 0x2007820c, 0x20038280, 0x200b8281, 0x2007820e, 0x20038283, 0x200b8284, 0x20078210, + 0x20038286, 0x200b8288, 0x20078212, 0x2103858c, 0x07821505, 0x03829320, 0x17829420, 0x07821620, 0x03859620, 0x82180521, 0x859c2007, 0x19052103, + 0x9f200782, 0xa0200382, 0x2105b75e, 0x0b82a2f7, 0x05210382, 0x2007821c, 0x200382a4, 0x201782a6, 0x2007821d, 0x200382a9, 0x200b82ab, 0x20078220, + 0x200382ad, 0x200b82ae, 0x20078223, 0x200382b5, 0x200b82b6, 0x20078225, 0x200382b9, 0x200b82ba, 0x20078227, 0x210385bd, 0x07822905, 0x0382bf20, + 0x575ec020, 0xc2f72105, 0x03820b82, 0x822c0521, 0x82c42007, 0x82c52003, 0x822d2017, 0x82c92007, 0x82ca2003, 0x822f200b, 0x82cc2007, 0x82ce2003, + 0x8231200b, 0x85d02007, 0x34052103, 0xd2200782, 0x05210385, 0x20078235, 0x200382d7, 0x202382da, 0x20078236, 0x200382e4, 0x200b82e6, 0x2007823a, + 0x210385ec, 0x07823d05, 0x0385ef20, 0x823e0521, 0x82f22007, 0x82f32003, 0x823f2023, 0x85f52007, 0x41052103, 0xf7200782, 0x05210385, 0x20078242, + 0x200382fa, 0x242382fb, 0xf8000043, 0x21038502, 0x07824505, 0x03820520, 0x17820720, 0x07824620, 0x03850a20, 0x82990121, 0x850b2007, 0x91002103, + 0x0c200782, 0x17840385, 0x0b820d20, 0x05210382, 0x20078249, 0x2003820f, 0x203b8210, 0x2007824a, 0x21038512, 0x07824c05, 0x03821520, 0x00001624, + 0x07824d05, 0x03851820, 0x824f0521, 0x851d2007, 0x50052103, 0x27200782, 0x2a200382, 0x51202382, 0x2f200782, 0x05210385, 0x82078255, 0x82f820cf, + 0x56052103, 0x57830b82, 0x05210382, 0x830b8257, 0x21038257, 0x0b825805, 0x03823f83, 0x82590521, 0x8553200b, 0x5a052103, 0x5e200782, 0x05210385, + 0x2007825b, 0x21038563, 0x07825c05, 0x03856d20, 0x825d0521, 0x85792007, 0x5e052103, 0x7b200782, 0x7d200382, 0x5f208382, 0x81200782, 0x82200382, + 0x62200b82, 0x84200782, 0x87200382, 0x64200b82, 0xff830782, 0x05210382, 0x200b8268, 0x21038597, 0x07826905, 0x0382c020, 0x2382c120, 0x07826a20, + 0x0385cc20, 0x826c0521, 0x85d72007, 0x83052003, 0x82d92073, 0x2103820b, 0x07826e05, 0x0385e520, 0x820f0321, 0x85ef2007, 0x6f052103, 0xff200782, + 0x05250385, 0xf1010070, 0x2603847f, 0x00fc0300, 0x8408f301, 0x05002203, 0x20078202, 0x2203840b, 0x82090500, 0x840d2007, 0x04002203, 0x20078237, + 0x2203840e, 0x82380400, 0x840f2007, 0x04002203, 0x20078239, 0x21038410, 0x13830200, 0x0b821920, 0x00001924, 0x07829b02, 0x03842120, 0x31030022, + 0x26200782, 0x00220384, 0x0782fa04, 0x03842720, 0xf8040022, 0x29200782, 0x00220384, 0x07820705, 0x03842a20, 0x83050021, 0x822d208b, 0x002d240b, + 0x824a0500, 0x243f8307, 0x03000031, 0x200b82bc, 0x22038432, 0x82b00200, 0x84362007, 0x05002203, 0x2007824e, 0x2203844b, 0x82fe0100, 0x240f8307, + 0x0400004e, 0x200b8280, 0x8503844f, 0x8268200b, 0x8268200b, 0x202b8353, 0x200b826a, 0x2023826a, 0x2007821e, 0x22038474, 0x823e0300, 0x84772007, + 0x03002203, 0x200782c3, 0x21038478, 0x67830400, 0x0b828120, 0x00008124, 0x0782df01, 0x03848220, 0xd1020022, 0x93200782, 0x00220384, 0x0782a502, + 0x03849720, 0xba030022, 0x99200782, 0x00220384, 0x07826403, 0x03849e20, 0x8e010022, 0x9f200782, 0x00210384, 0x205b8302, 0x200b82a7, 0x205382a7, + 0x200782a3, 0x220384a8, 0x82fb0300, 0x84ad2007, 0x04002203, 0x2007829b, 0x220384b2, 0x82e10300, 0x84b52007, 0x01002203, 0x20078289, 0x220384c0, + 0x82760300, 0x84c12007, 0x02002203, 0x2007825a, 0x220384c2, 0x82330500, 0x84c32007, 0x04002203, 0x200782ea, 0x220384c5, 0x825b0400, 0x84c62007, + 0x01002203, 0x200782fc, 0x210384c8, 0xdf830300, 0x0b82ca20, 0x0000ca23, 0x20538304, 0x240b82cd, 0x020000cd, 0x200782e0, 0x220384d0, 0x82870300, + 0x84d32007, 0x03002203, 0x20078286, 0x220384d4, 0x82e60400, 0x84d62007, 0x04002203, 0x2007827b, 0x210384d9, 0xd7830400, 0x0b82db20, 0x5382db20, + 0x0782b320, 0xe0204b83, 0x9920ef82, 0xe2200b82, 0x00210384, 0x20f78302, 0x200b82e5, 0x206b82e5, 0x2007823f, 0x220384e8, 0x824e0400, 0x84eb2007, + 0x04002203, 0x20078204, 0x220384f4, 0x82a20100, 0x84f72007, 0x01002503, 0xf40100a9, 0x03821b82, 0x82040021, 0x08f42197, 0x08200f82, 0xcf206b82, + 0x09200782, 0x00220384, 0x0782d704, 0x03840e20, 0x82040021, 0x15f42173, 0x15230b82, 0x82040000, 0x1ff421af, 0x1f200b82, 0x33200b82, 0x41200782, + 0x00210384, 0x20238301, 0x240b824d, 0x0200004d, 0x82078292, 0x4ef42187, 0x93200b82, 0x51200b82, 0x00220384, 0x0782e003, 0x03845520, 0x0e040022, + 0x64200782, 0x00220384, 0x07828d01, 0x03846520, 0xca030022, 0x7b200782, 0x00220384, 0x0782dc04, 0x03848020, 0x07040022, 0x89200782, 0x00210384, + 0x21cb8203, 0x0b828ef4, 0x00008e24, 0x07825f03, 0x03849420, 0x20050022, 0x99200782, 0x00220384, 0x07828b01, 0x03849a20, 0x9b200b85, 0x9b210b82, + 0x200b8500, 0x200b829c, 0x200b869c, 0x200b82a1, 0x20a782a1, 0x20078236, 0x220384a3, 0x82c40200, 0x84a72007, 0x01002203, 0x200782bf, 0x220384a9, + 0x82460300, 0x84ac2007, 0x03002203, 0x200782ab, 0x220384b0, 0x82500500, 0x84b22007, 0x00002203, 0x20078204, 0x220384b3, 0x82020200, 0x84bb2007, + 0x02002203, 0x2007824e, 0x220384bc, 0x82130200, 0x84be2007, 0x02002203, 0x8307821c, 0x82bf2063, 0x82de20cb, 0x84c0200b, 0x03002103, 0xc1200b83, + 0xc1240b82, 0xee010000, 0xc2200782, 0x00220384, 0x0782ef01, 0xc4249f83, 0x8a020000, 0xc5200b82, 0x00220384, 0x07826a02, 0x0384c620, 0xcb200b85, + 0xcb200b82, 0x51205382, 0xcc200782, 0x00220384, 0x0782f901, 0x0384cd20, 0x15030022, 0xce200782, 0x00220384, 0x07821b02, 0x0384cf20, 0x0782be82, + 0x0384d420, 0x83010021, 0x82d620e3, 0x82d6200b, 0x82d72047, 0x84dc2007, 0x04002203, 0x200782eb, 0x220384dd, 0x824f0300, 0x84de2007, 0x01002203, + 0x200782ff, 0x220384df, 0x824d0500, 0x84e02007, 0x02002203, 0x200782a7, 0x220384e1, 0x822b0500, 0x84e22007, 0x02002203, 0x20078205, 0x210384e6, + 0xcb830300, 0x0b82f020, 0xd782f020, 0x0782c920, 0x0384f120, 0x66030022, 0xf6200782, 0x00220384, 0x07829701, 0x0384f720, 0xf3010022, 0xfb200782, + 0x00260384, 0x01006d05, 0x038400f5, 0xe7010022, 0x01200782, 0x00220384, 0x07825b03, 0x03840420, 0x41030022, 0x08200782, 0x00220384, 0x0782a501, + 0x03840a20, 0xa6010022, 0x0b200782, 0x00210384, 0x21678202, 0x0b820cf5, 0x00000c24, 0x0782c802, 0x03840d20, 0x82010021, 0x11f5219b, 0x11200b82, + 0xf4206482, 0x12200782, 0x00220384, 0x0782a101, 0x03841320, 0x83020021, 0x82142073, 0x8214200b, 0x823d203b, 0x84152007, 0x02002203, 0x200782cc, + 0x22038416, 0x82ac0100, 0x84172007, 0x02002103, 0x18201383, 0x18200b82, 0x9f202f82, 0x25200782, 0x00220384, 0x0782e101, 0x03842720, 0x10020022, + 0x28200782, 0x00220384, 0x0782dd04, 0x03842c20, 0x90040022, 0x34200782, 0x00220384, 0x07825402, 0x03843520, 0x47200b85, 0x47230b82, 0x83040000, + 0x824920d7, 0x8249200b, 0x82b7200b, 0x844a2007, 0x03002203, 0x200782af, 0x2203844b, 0x82b10400, 0x844c2007, 0x04002203, 0x200782b6, 0x2203844d, + 0x82c60400, 0x844e2007, 0x04002203, 0x200782de, 0x22038453, 0x829a0100, 0x846b2007, 0x02002203, 0x20078205, 0x2203846e, 0x82d70300, 0x84712007, + 0x04002203, 0x200782ec, 0x22038475, 0x82df0200, 0x84772007, 0x04002203, 0x200782ee, 0x2203847b, 0x82ff0100, 0x847d2007, 0x05002203, 0x2007825e, + 0x22038482, 0x822f0200, 0x84882007, 0x01002203, 0x200782f9, 0x2203848a, 0x82490300, 0x848b2007, 0x04002203, 0x20078262, 0x2203848c, 0x82d00200, + 0x84952007, 0x05002203, 0x20078247, 0x22038496, 0x820a0300, 0x84a42007, 0x01002103, 0xa5203783, 0xa5230b82, 0x83030000, 0x82a8206b, 0x00a8240b, + 0x82ad0100, 0x84a92007, 0x02002203, 0x200782cb, 0x220384aa, 0x821c0200, 0x84b12007, 0x05002203, 0x2007826c, 0x220384b4, 0x82040200, 0x84b62007, + 0x203b8503, 0x240b82b7, 0x020000b7, 0x200782a7, 0x220384b8, 0x82de0300, 0x84b92007, 0x02002103, 0xbb207783, 0xbb200b82, 0x37832382, 0x0b82bf20, + 0x7782bf20, 0x0782ee20, 0x0384c120, 0xef010022, 0x7b830782, 0x2382cb20, 0xce20eb83, 0xce200f82, 0x3b830b82, 0x0b82d520, 0xb382d520, 0x07823820, + 0x0384d620, 0x37030022, 0xd8200782, 0x00220384, 0x07829f01, 0x0384d920, 0x93010022, 0xe9200782, 0x00220384, 0x0782e801, 0x0384ea20, 0xf6010022, + 0xfa200782, 0x00220384, 0x0e831703, 0x00220384, 0x07823b04, 0x03840120, 0x54040022, 0x02200782, 0x00220384, 0x07824304, 0x03840320, 0x3c040022, + 0x04200782, 0x00220384, 0x07823d04, 0x03840520, 0x3e040022, 0x06200782, 0x00220384, 0x07824004, 0x03840920, 0xbe030022, 0x0a200782, 0x00220384, + 0x07826c04, 0x03840d20, 0x3f040022, 0x10200782, 0x00220384, 0x07825702, 0x17248783, 0x50040000, 0x18200b82, 0x00220384, 0x07825204, 0x03841920, + 0x51040022, 0x1b200782, 0x00220384, 0x07824404, 0x03841c20, 0x46040022, 0x1d200782, 0x00220384, 0x07824504, 0x03842020, 0x11040022, 0x22200782, + 0x00220384, 0x07826904, 0x03842620, 0x35040022, 0x2b200782, 0x00220384, 0x07827904, 0x03842c20, 0x3a040022, 0x2d200782, 0x00220384, 0x07826804, + 0x03842e20, 0x74040022, 0x33200782, 0x00220384, 0x07823404, 0x03843620, 0x5c040022, 0x42200782, 0x00220384, 0x07825502, 0x03844420, 0x5d040022, + 0x81200782, 0x00220384, 0x0782f003, 0x03848620, 0xf4020022, 0x8a200782, 0x00220384, 0x07828701, 0x03848d20, 0xd8020022, 0x90200782, 0x00220384, + 0x07826a04, 0x03849120, 0x40020022, 0x96200782, 0x00220384, 0x0782af02, 0x03849720, 0x88040022, 0x98200782, 0x00220384, 0x0782ae02, 0x03849a20, + 0x25020022, 0x9c200782, 0x00210384, 0x20778304, 0x240b82a1, 0x050000a1, 0x20078239, 0x220384a2, 0x82de0200, 0x84a62007, 0x04002103, 0xaa202b83, + 0xaa240b82, 0xe9030000, 0xab200782, 0x00220384, 0x0782d501, 0x0384ac20, 0x83030021, 0x82ad2043, 0x00ad240b, 0x82080400, 0x84b02007, 0x00002203, + 0x20078234, 0x220384b2, 0x82d70200, 0x84b42007, 0x05002203, 0x20078257, 0x220384b6, 0x820f0400, 0x84bd2007, 0x05002203, 0x20078237, 0x210384bf, + 0x3b830300, 0x0b82c120, 0x0000c124, 0x07823503, 0x0384cc20, 0xf3020022, 0xce200782, 0x00220384, 0x07821d04, 0x0384d020, 0xbd040022, 0xd2200782, + 0x00220384, 0x0782ed01, 0x0384e120, 0x69020022, 0xe3200782, 0x00220384, 0x07829b01, 0x0384eb20, 0x66040022, 0xec200782, 0x00220384, 0x07826504, + 0x0384f020, 0x2a050022, 0xfb200782, 0x00260384, 0x01009e04, 0x0384e0f7, 0x54020022, 0xe1200782, 0x0b850384, 0x0b82e220, 0x8500e221, 0x82e3200b, + 0x86e3200b, 0x82e4200b, 0x86e4200b, 0x82e5200b, 0x82e5200b, 0x828520bf, 0x84e62007, 0x03002103, 0xe7200b83, 0xe7200b82, 0xe8201786, 0xe8200b82, + 0xe9200b86, 0xe9200b82, 0xea200b86, 0xea200b82, 0xeb200b86, 0xeb200b82, 0xf9230b85, 0x8201000d, 0x01002203, 0x2007828b, 0x8503840e, 0x8216200b, + 0x8216200b, 0x82ff2023, 0x841a2007, 0x03002203, 0x20078207, 0x2203841d, 0x82b60300, 0x84232007, 0x04002203, 0x20078241, 0x22038429, 0x82420400, + 0x240f8307, 0x04000041, 0x830b8224, 0x0042230f, 0x43830500, 0x0f824320, 0x0b824320, 0x07821b20, 0x03844420, 0x3d030022, 0x4e200782, 0x00220384, + 0x07827503, 0x03845320, 0x3b050022, 0x55200782, 0x00220384, 0x07821305, 0x03845a20, 0x83050021, 0x82772037, 0x8277200b, 0x82ce209b, 0x84902007, + 0x00002203, 0x20078298, 0x2203849b, 0x82e10400, 0x84a62007, 0x04002203, 0x200782e8, 0x220384b4, 0x82820400, 0x84b72007, 0x04002203, 0x2007827a, + 0x220384cd, 0x82990200, 0x84e02007, 0x04002203, 0x83078284, 0x00e1213f, 0x20050741, 0x200f82e6, 0x20cb82e6, 0x200782c2, 0x220384e9, 0x82660200, + 0x84ea2007, 0x03002203, 0x200782a5, 0x220384ec, 0x82920300, 0x84ed2007, 0x02002203, 0x20078280, 0x220384ef, 0x826b0200, 0x84f02007, 0x04002203, + 0x2007820d, 0x210384f2, 0x4f830100, 0x0b82f320, 0x0000f324, 0x07823c02, 0x0384f920, 0xd9030022, 0xfb200782, 0x00220384, 0x0782ef04, 0x0384fc20, + 0x4f000022, 0xfe200782, 0x00210384, 0x23078203, 0x010079fa, 0x00220382, 0x07828903, 0xfa21cf82, 0x2047827a, 0x200b823b, 0x22038491, 0x82d00400, + 0x849b2007, 0x04002203, 0x20078205, 0x220384b6, 0x82eb0300, 0x84c12007, 0x04002503, 0x0003008f, 0x0128009c, 0x00040400, 0x17010101, 0x157baa18, + 0x633d1a83, 0x00f0061c, 0x01f1061c, 0x02f2061c, 0x03f3061c, 0x04f4061c, 0x1e0f0a1e, 0x1e0f4ae6, 0x2b078264, 0x050f8a44, 0x001d0d8b, 0x0f624800, + 0x53220582, 0x05821143, 0x1d060027, 0x8d640d00, 0x2c388212, 0xe51e000c, 0x030c2f1a, 0xffa6251e, 0x2839820c, 0x12531900, 0x1e8b8b5f, 0x2a08860a, + 0x6e05070c, 0x00010002, 0x1813000c, 0x0816bc6b, 0x37003130, 0x44004300, 0x46004500, 0x48004700, 0x4a004900, 0x4c004b00, 0x4e004d00, 0x50004f00, + 0x52005100, 0x54005300, 0x56005500, 0x58005700, 0xa8185900, 0x0a0708ca, 0x73006dc3, 0x92007e00, 0xb4009e00, 0xcf00c800, 0xe000d700, 0xfe00ea00, + 0x18010b01, 0x3d012e01, 0x61014c01, 0x7e016f01, 0x9c019001, 0xb401a701, 0xcb01bf01, 0xe001d401, 0xe801e401, 0xfe01f401, 0x1b020902, 0x2b022602, + 0x3d023602, 0x4d024102, 0x6b025d02, 0x8c028002, 0xa1029502, 0xbc02af02, 0xd202c902, 0xe902de02, 0xfb02f502, 0x10030703, 0x2b032103, 0x3f033803, + 0x50034803, 0x6e036303, 0x85037b03, 0x94039103, 0xac03a203, 0xc503bd03, 0xdb03ce03, 0xee03e503, 0x0204f703, 0x12040c04, 0x25041a04, 0x36042e04, + 0x47044104, 0x5a044f04, 0x70046b04, 0x8c048304, 0xa4049b04, 0xc004b304, 0xd804cb04, 0xeb04e104, 0xfa04f304, 0x13050005, 0x2b051f05, 0x4f053e05, + 0x65055c05, 0x7e057505, 0x9a058905, 0xc605ad05, 0xe405d905, 0x0f06fd05, 0x3c062206, 0x67065406, 0x8f067a06, 0xb306a806, 0xdb06cb06, 0xf506e806, + 0x19070607, 0x33072a07, 0x4d074107, 0x63075607, 0x7c076907, 0xa8079507, 0xbf07b307, 0xc907c507, 0xf907e407, 0x29081408, 0x43083608, 0x5e084f08, + 0x76086908, 0x89088408, 0x99088f08, 0xac08a408, 0xca08b808, 0xe508dd08, 0x0709f208, 0x15091009, 0x3d092c09, 0x5c095109, 0x70096709, 0x85097a09, + 0xab099809, 0xc509bc09, 0xe309d009, 0x080af709, 0x320a1a0a, 0x550a440a, 0x780a670a, 0x8f0a810a, 0xaf0a9d0a, 0xd90ac70a, 0xed0ae30a, 0x220bfe0a, + 0x460b2c0b, 0x800b660b, 0x9f0b920b, 0xab0ba20b, 0xc60bb90b, 0xdd0bd10b, 0xf50bea0b, 0x130c020c, 0x350c190c, 0x5f0c4b0c, 0x7d0c6e0c, 0x9c0c890c, + 0xbf0caf0c, 0xd30cc70c, 0xe50cd80c, 0xf90cf10c, 0x100d050d, 0x2c0d1e0d, 0x500d370d, 0x7d0d690d, 0x940d890d, 0xb80da50d, 0xe40dd10d, 0x0c0ef60d, + 0x310e1f0e, 0x4e0e400e, 0x730e620e, 0x9b0e830e, 0xc90eb00e, 0xe00ed40e, 0x0c0fee0e, 0x4c0f260f, 0x740f620f, 0x9e0f8c0f, 0xb30fa80f, 0xd40fc30f, + 0xfc0feb0f, 0x1d100c10, 0x35102910, 0x51104010, 0x79106810, 0x8d108210, 0x9a109010, 0xc610ad10, 0xe410d910, 0xfc10ef10, 0x10110611, 0x26111c11, + 0x48113c11, 0x61115311, 0x71116511, 0x8c117511, 0xb511a111, 0xca11c511, 0xe911d911, 0x0412f311, 0x13120d12, 0x31122012, 0x49123e12, 0x62125712, + 0x7f127512, 0x98128912, 0xb912a812, 0xdf12c312, 0xef12e312, 0x0813fa12, 0x2a131913, 0x49133f13, 0x5a135013, 0x72136d13, 0x87138213, 0x8f138b13, + 0xa4139313, 0xb913af13, 0xc313be13, 0xee13d813, 0xfd13f713, 0x06140114, 0x0f140b14, 0x1c141714, 0x3b142e14, 0x4d144914, 0x5b145114, 0x6f146514, + 0x80147a14, 0x8a148714, 0x92148e14, 0x9f149a14, 0xa914a514, 0xb314ad14, 0xc814be14, 0xde14d214, 0xf614e914, 0x0115fa14, 0x0c150715, 0x1d151115, + 0x36152f15, 0x5c154315, 0x76156915, 0x82157e15, 0x8b158715, 0x9e159215, 0xaf15aa15, 0xc815bb15, 0xdf15d315, 0xf715eb15, 0x11160616, 0x1e161b16, + 0x33162816, 0x45163b16, 0x50164a16, 0x5d165816, 0x73166f16, 0x7b167716, 0x87167e16, 0xa0169b16, 0xb416ad16, 0xc116bb16, 0xd716cb16, 0xeb16de16, + 0xfc16f116, 0x1b170a17, 0x30172417, 0x38173317, 0x49174017, 0x6a176117, 0x9a178417, 0xa617a017, 0xb017ab17, 0xc217bc17, 0xd017cd17, 0xe217da17, + 0xfd17ed17, 0x19180c18, 0x39182818, 0x5a184b18, 0x70186b18, 0x80187618, 0x8f188618, 0xa618a118, 0xaf18aa18, 0xbc18b418, 0xc918c018, 0xda18d418, + 0xe518de18, 0xf918ec18, 0x07190219, 0x16191119, 0x2a192019, 0x3c193219, 0x54194719, 0x61195819, 0x70196819, 0x86198119, 0x91198a19, 0x9e199919, + 0xbd19a719, 0xdb19cd19, 0xf119e619, 0xfd19f919, 0x0f1a071a, 0x2c1a1c1a, 0x451a371a, 0x581a4d1a, 0x6f1a631a, 0x831a781a, 0x981a8d1a, 0xaa1aa01a, + 0xbd1ab01a, 0xd41aca1a, 0xe61adf1a, 0xf61aec1a, 0x081b001b, 0x171b0f1b, 0x2d1b251b, 0x3a1b311b, 0x4c1b481b, 0x611b571b, 0x701b651b, 0x7f1b791b, + 0x951b8b1b, 0xab1ba51b, 0xc41bb31b, 0xdd1bca1b, 0x021cf11b, 0x1b1c151c, 0x311c291c, 0x4a1c391c, 0x5f1c541c, 0x711c651c, 0x8d1c7e1c, 0xa31c991c, + 0xc91cb81c, 0xe11cd01c, 0x021df01c, 0x181d0b1d, 0x2a1d221d, 0x3c1d341d, 0x4a1d401d, 0x641d581d, 0x8c1d791d, 0xa61d9a1d, 0xba1daf1d, 0xd61dc91d, + 0xf51de51d, 0x071e011e, 0x0e1e0a1e, 0x1c1e191e, 0x371e2d1e, 0x4a1e411e, 0x661e571e, 0x841e761e, 0x8f1e8c1e, 0x9c1e971e, 0xa31e9f1e, 0xaf1ea81e, + 0xb61eb21e, 0xc21eba1e, 0xd31eca1e, 0xec1edd1e, 0x011ff61e, 0x151f0b1f, 0x271f1e1f, 0x3e1f331f, 0x561f4f1f, 0x661f5f1f, 0x831f711f, 0x8d1f871f, + 0x9a1f901f, 0xa71f9e1f, 0xb51fab1f, 0xc41fbf1f, 0xd81fcd1f, 0xee1fe21f, 0x0120f81f, 0x15200b20, 0x25201e20, 0x39202820, 0x4d204420, 0x63205c20, + 0x72206720, 0x87207c20, 0x97209220, 0xa2209b20, 0xbb20b020, 0xd220c720, 0xe720dc20, 0x0621f520, 0x16210c21, 0x25211c21, 0x32212f21, 0x43213721, + 0x65214f21, 0x80217121, 0x9a218d21, 0xae21a221, 0xc721bc21, 0xda21cc21, 0xf721e921, 0x0d220422, 0x1f221b22, 0x37222c22, 0x4d224122, 0x60225722, + 0x6c226a22, 0x87227922, 0xa3229522, 0xb222ab22, 0xbf22bc22, 0xd222c622, 0xe922dd22, 0x0823f822, 0x31232023, 0x44233d23, 0x64234e23, 0x71236c23, + 0x8b237f23, 0xa1239423, 0xb923ad23, 0xcc23c423, 0xe323d323, 0x0d24fd23, 0x31242024, 0x3b243724, 0x51244224, 0x6e246024, 0x83247a24, 0x91248c24, + 0xa4249924, 0xb324ad24, 0xce24bc24, 0xea24de24, 0xf324ed24, 0xfc24f924, 0x0d250425, 0x20251625, 0x2f252725, 0x40253725, 0x51254a25, 0x67255c25, + 0x7c257325, 0x9f259025, 0xaf25a925, 0xc425ba25, 0xce25cb25, 0xde25d725, 0xf325e725, 0x17260326, 0x2a261d26, 0x41263626, 0x54264f26, 0x75266126, + 0x88267b26, 0xa1269226, 0xe326c126, 0xfc26f426, 0x12270627, 0x23271727, 0x38272e27, 0x4e274427, 0x63275927, 0x73276b27, 0x8b278027, 0xa0279527, + 0xc227b827, 0xd227cb27, 0xe227d527, 0x0428f327, 0x1b280c28, 0x3e282928, 0x46284128, 0x5e285228, 0x76286b28, 0x8a287e28, 0x9d289728, 0xb528a228, + 0xd928d028, 0xea28e328, 0xf828f128, 0x07290329, 0x15290c29, 0x26292129, 0x3a292e29, 0x4c294729, 0x65296129, 0x83297129, 0xaa299629, 0xc629b729, + 0xe329d629, 0xfd29f329, 0x082a032a, 0x1c2a102a, 0x2f2a2b2a, 0x492a3d2a, 0x5e2a542a, 0x7c2a6e2a, 0x902a862a, 0xa12a992a, 0xb82aab2a, 0xcb2ac12a, + 0xe02ad52a, 0xf22aea2a, 0x042bfa2a, 0x292b142b, 0x392b302b, 0x4d2b482b, 0x662b572b, 0x712b6c2b, 0x812b7d2b, 0x8a2b862b, 0x9c2b932b, 0xac2ba42b, + 0xbe2bb62b, 0xcf2bc42b, 0xdf2bd82b, 0xeb2be32b, 0x042cf22b, 0x162c0e2c, 0x2e2c1f2c, 0x4a2c342c, 0x6a2c592c, 0x872c752c, 0x972c902c, 0xb42ca52c, + 0xc02cbb2c, 0xd32cc52c, 0xf12ce32c, 0x022df72c, 0x122d0d2d, 0x222d1d2d, 0x342d262d, 0x462d3f2d, 0x592d4b2d, 0x692d5f2d, 0x7a2d702d, 0x8a2d7f2d, + 0x9a2d962d, 0xa92d9f2d, 0xbd2db12d, 0xdf2dd12d, 0xf02de52d, 0x0d2efb2d, 0x272e172e, 0x382e2b2e, 0x542e472e, 0x6e2e632e, 0x852e792e, 0xa92e982e, + 0xc42eb72e, 0xd12ec82e, 0xe02edc2e, 0xfb2eec2e, 0x142f082f, 0x2c2f222f, 0x412f382f, 0x5d2f4f2f, 0x812f712f, 0xa72f912f, 0xc52fb62f, 0xec2fd52f, + 0x0f300130, 0x20301330, 0x38303130, 0x51304330, 0x5b305630, 0x72306430, 0x90308630, 0xb0309f30, 0xd430bf30, 0xf030e030, 0xfb30f630, 0x1a310931, + 0x2f312231, 0x43313b31, 0x53314c31, 0x69315c31, 0x84317831, 0x9d319031, 0xb131a831, 0xcb31c031, 0xd531ce31, 0xe331de31, 0x0332f331, 0x1a321032, + 0x35322932, 0x4c324232, 0x5f325132, 0x7a326c32, 0x9c328a32, 0xab32a732, 0xbf32af32, 0xcc32c432, 0xe032d732, 0xf832e832, 0x16330a33, 0x2c332133, + 0x44333f33, 0x55334e33, 0x5f335933, 0x70336b33, 0x86337a33, 0x9c339733, 0xb333a633, 0xcd33c033, 0xe533d933, 0xf333e933, 0x04340034, 0x21341234, + 0x32342634, 0x50344434, 0x6f345b34, 0x7b347634, 0x84348034, 0x9c349734, 0xaa34a234, 0xbf34b834, 0xc734c534, 0xe434df34, 0x0835f434, 0x2c351e35, + 0x43353935, 0x73355a35, 0x8c357835, 0xaa359d35, 0xbf35b335, 0xcf35c935, 0xe335db35, 0xfa35f035, 0x07360436, 0x16360c36, 0x22361f36, 0x31362a36, + 0x3a363436, 0x4f364836, 0x60365736, 0x6b366536, 0x7d367336, 0x8f368a36, 0xa7369436, 0xb736b336, 0xcc36bf36, 0xd536d136, 0xe936e336, 0xfe36f936, + 0x10370437, 0x23371737, 0x3c372f37, 0x4b374037, 0x68375937, 0x85377237, 0x9b379337, 0xac37a337, 0xbf37b937, 0xd437cb37, 0xe537db37, 0xf937e937, + 0x12380838, 0x20381938, 0x32382d38, 0x43383638, 0x50384c38, 0x69385c38, 0x79387338, 0x8e388638, 0xa3389638, 0xb038ab38, 0xce38c138, 0xe438da38, + 0xfd38f738, 0x13390839, 0x24391d39, 0x2f392939, 0x3f393639, 0x57394f39, 0x6e396039, 0x7d397539, 0x98398b39, 0xb239ac39, 0xd039bd39, 0xdf39d739, + 0xef39e939, 0x0a3a013a, 0x203a1b3a, 0x373a2c3a, 0x523a3d3a, 0x6f3a603a, 0x7c3a753a, 0x8a3a7f3a, 0xa23a903a, 0xbc3aaf3a, 0xcb3ac23a, 0xde3ad93a, + 0xf33ae83a, 0x093bfe3a, 0x243b163b, 0x403b363b, 0x583b4b3b, 0x6d3b623b, 0x8a3b7c3b, 0x923b8d3b, 0xad3b9c3b, 0xc13bb73b, 0xdb3bcf3b, 0x033cf03b, + 0x1d3c113c, 0x313c283c, 0x4a3c3b3c, 0x5d3c583c, 0x763c693c, 0xaf3c7d3c, 0xe23cc93c, 0xfa3cf53c, 0x6c637865, 0x74616d61, 0x686e6f69, 0x74687361, + 0x6f646761, 0x72616c6c, 0x6769732d, 0x3231306e, 0x36353433, 0x6c393837, 0x2d737365, 0x6e616874, 0x61757165, 0x7267736c, 0x65746165, 0x08118472, + 0x6362612f, 0x67666564, 0x6b6a6968, 0x6f6e6d6c, 0x73727170, 0x77767574, 0x7a7a7978, 0x2d6f7265, 0x74646977, 0x70732d68, 0x66656361, 0x65637561, + 0x38058574, 0x6972642d, 0x756f6870, 0x632d6573, 0x6e6d6968, 0x772d7965, 0x6f646e69, 0x83138577, 0x6c61337d, 0x706d6574, 0x74617265, 0x2d657275, + 0x6f727261, 0x20822d77, 0x15916e20, 0x7470752b, 0x6c696172, 0x61627265, 0x21968263, 0x07866169, 0x626d752b, 0x742d786f, 0x75737369, 0x30bb8265, + 0x6f682d64, 0x6e69646c, 0x656d2d67, 0x61636964, 0x8213846c, 0x6b72249a, 0x8373656c, 0x2d73250c, 0x62627562, 0x68290c87, 0x2d656b61, 0x706d6973, + 0x2306826c, 0x6873616c, 0x15852284, 0x65220e84, 0x1f826461, 0xc2826420, 0x67756f24, 0x0e8d6868, 0x8d732d21, 0x616d2323, 0x22896b73, 0x72697624, + 0xff8d7375, 0x65737523, 0x2b118572, 0x7470616c, 0x756c706f, 0x2d73676e, 0x70212884, 0x410e8265, 0x73240603, 0x6e616c70, 0x70239086, 0x87706d75, + 0x290b84cc, 0x70616f73, 0x65696873, 0x3885646c, 0x6e697323, 0x8213846b, 0x6177274f, 0x2d686374, 0x76823032, 0x9c857020, 0x6f747323, 0x2b498672, + 0x6c696f74, 0x702d7465, 0x72657061, 0x8e831c85, 0x0a857320, 0x04848384, 0x65250f8a, 0x73657673, 0x82038374, 0x21598235, 0xa2417365, 0x72742905, + 0x2d646e65, 0x6e776f64, 0x75210f8b, 0x3e0d8570, 0x662d7075, 0x2d6d6f72, 0x63617262, 0x6174656b, 0x72747375, 0x732d6c61, 0x626e6769, 0x85746861, + 0x74692508, 0x6e696f63, 0x6f310b85, 0x6c2d746c, 0x74686769, 0x676e696e, 0x6b6f6f62, 0x3404832d, 0x6b72616d, 0x656d6163, 0x722d6172, 0x7461746f, + 0x64656365, 0x2b308469, 0x72616863, 0x6f632d74, 0x6e6d756c, 0x67280b85, 0x74746e61, 0x70616c63, 0x622eda82, 0x6472616f, 0x766f6c63, 0x6f637265, + 0x27826564, 0x98826d20, 0x0b846520, 0x826f6621, 0x28148353, 0x6c6c7570, 0x7165722d, 0x82df8275, 0x856f2048, 0x72632789, 0x69657a75, 0x65846f72, + 0x7369642a, 0x79616c70, 0x676e6f64, 0x65370f84, 0x6176656c, 0x66726f74, 0x65746c69, 0x69632d72, 0x656c6372, 0x826d782d, 0x6c6623a6, 0xcc86726f, + 0x6c6f6623, 0x291d8364, 0x65736f6c, 0x61726664, 0x3c84636e, 0x61756722, 0xbe850b82, 0x6e756728, 0x646e6168, 0xb0842d73, 0x1142f282, 0x73752205, + 0x29448265, 0x6e616964, 0x7075722d, 0x37846565, 0x70696b22, 0x6c220784, 0x3c857261, 0x74696c22, 0x6c86ca82, 0x6e616d23, 0x054f4161, 0x73616d2a, + 0x61662d6b, 0x696d6563, 0x732ad882, 0x6d6e6769, 0x79656e6f, 0x0e82622d, 0x616e7325, 0x84617269, 0x6f6e3246, 0x66656474, 0x6f6e6170, 0x616d6172, + 0x65736570, 0x82188574, 0x42f5850a, 0x75210579, 0x22828270, 0x84686169, 0x74732134, 0x733c3f82, 0x656d6974, 0x656e696c, 0x63757274, 0x72662d6b, + 0x74746e6f, 0x696b7275, 0x6c2d6873, 0x76255e87, 0x746c7561, 0x26db8277, 0x67616d2d, 0x432d6369, 0x77220777, 0xa7826568, 0x6e776122, 0x65230882, + 0x8268636c, 0x6d2d3c4f, 0x6265766f, 0x2d6c776f, 0x65636972, 0x73726570, 0x702d6e6f, 0x6e676572, 0x43746e61, 0x0c860c34, 0x63617223, 0x430a856b, + 0x632206d9, 0xfb856e65, 0x6c702a08, 0x6d2d7375, 0x73756e69, 0x6c696173, 0x74616f62, 0x74636573, 0x736e6f69, 0x6d697268, 0x61726270, 0x696c697a, + 0x722d6e61, 0x06864265, 0x43053442, 0x642b05f6, 0x72676169, 0x6e2d6d61, 0x87747865, 0x2787820b, 0x65636564, 0x726f7373, 0x73221287, 0x10856375, + 0x7261652f, 0x6f2d6874, 0x6e616563, 0x75626169, 0x052e4367, 0x6c696623, 0x07124265, 0x73288f83, 0x2d706f68, 0x6b636f6c, 0x24055243, 0x69766f63, + 0x850a8a64, 0x6e612434, 0x426f6863, 0x63240849, 0x6b636568, 0xb945128d, 0x23188d0a, 0x72616d78, 0x65832b87, 0x2d093945, 0x2d70752d, 0x6f726361, + 0x6c2d7373, 0xac826e69, 0x83075245, 0x272a8918, 0x68676972, 0x6f742d74, 0x7421b382, 0x0db64379, 0x6f72672b, 0x2d646e75, 0x65746177, 0x84198d72, + 0x702d2312, 0xe8436d75, 0x22478509, 0x44746f64, 0x73250519, 0x776f642d, 0x8857836e, 0x4412897c, 0x528405e1, 0x65239c82, 0x882d7466, 0x222d8a85, + 0x44697073, 0x73260555, 0x6c70732d, 0xd0847469, 0x6c208f82, 0x3b863082, 0x7222b684, 0xdd856c63, 0x6e837320, 0x1c898182, 0x88796521, 0x72752219, + 0x8765856e, 0x8210831d, 0x21b18a3f, 0xaf877075, 0x726f6236, 0x6f682d65, 0x6f62656c, 0x656c7474, 0x6f72642d, 0x74656c70, 0xfd840d86, 0x776f623b, + 0x6f662d6c, 0x6f62646f, 0x2d736578, 0x6b636170, 0x62676e69, 0x67646972, 0x42058565, 0x63240705, 0x6b636568, 0xce41128d, 0x23188d0a, 0x72616d78, + 0x6c212b87, 0x8536886f, 0x63752271, 0x2583826b, 0x62736775, 0xda466975, 0x44632005, 0xd284057a, 0x1a8fdd85, 0x2f8e7c85, 0x1a8e7e8b, 0x14878085, + 0x616c6623, 0x84518867, 0x2219878f, 0x886f676e, 0x05834618, 0x75210e88, 0x220a896e, 0x88726573, 0x68772f0c, 0x62746165, 0x74737275, 0x2d726163, + 0x05836e6f, 0x6e757427, 0x636c656e, 0x82cf8268, 0x6c6622bf, 0x220a8465, 0x866e6572, 0x6f6e34d9, 0x63736564, 0x6270696c, 0x6472616f, 0x6575712d, + 0x82697473, 0x6f6c2b3a, 0x732d6475, 0x65776f68, 0xa0427372, 0x6f633b05, 0x7475706d, 0x75637265, 0x2d736562, 0x63617473, 0x6564656b, 0x6c65766e, + 0x9043706f, 0x68632208, 0x24168265, 0x6f6c7078, 0x24458273, 0x72726566, 0x0baf4379, 0x8b0a1741, 0x696d2416, 0x8b73756e, 0x84868710, 0x24fd8513, + 0x65726966, 0x36dc822d, 0x6672656e, 0x2d687369, 0x736e6966, 0x73616c66, 0x69762d6b, 0x82676c61, 0x8aa78609, 0x0756420a, 0x6f726724, 0xf3487075, + 0x46732005, 0xc04806e1, 0x830c830c, 0x75632303, 0xb9486666, 0x756f2307, 0x3b46646e, 0x07e64805, 0x69686323, 0x29128f6c, 0x6c637269, 0x61656865, + 0x8c427472, 0x6f622307, 0x108c746c, 0x65686324, 0x118c6b63, 0x8c0a0541, 0x696d2417, 0x8c73756e, 0x6c702111, 0x7823108e, 0x8272616d, 0x696c2b4c, + 0x74706f63, 0x732d7265, 0x70826d79, 0x6c656828, 0x2d74656d, 0xa1826e75, 0x612d6c27, 0x616c6176, 0x8476826e, 0x6f72280d, 0x6c736b63, 0x45656469, + 0xf64105d1, 0x4a948506, 0xc3840530, 0x948b2d20, 0x7185178b, 0x66221184, 0x45867269, 0x616c6623, 0x234f8567, 0x6f6f6c66, 0x9006c144, 0x07124110, + 0x850a3d43, 0x826c2023, 0x0c604693, 0x940cc943, 0x469e9019, 0x1c48069a, 0x89398d0c, 0x737429a4, 0x6d616e75, 0x72616a69, 0x2d390282, 0x61656877, + 0x74656a74, 0x6769662d, 0x72657468, 0x6a70752d, 0x642d6775, 0x3a0b8265, 0x746e6567, 0x6374696b, 0x2d6e6568, 0x6c746573, 0x2d646e61, 0x656e696d, + 0x836e6f2d, 0x616d240b, 0x832d6b72, 0x05534a57, 0x6c224182, 0x1e826c65, 0x6c2d7328, 0x696e6165, 0xd982676e, 0x69746129, 0x702d6e6f, 0x822d6e69, + 0x826b200c, 0x73752903, 0x67616d74, 0x7966696e, 0x2d202082, 0x41059e42, 0x1b900a12, 0x61686323, 0x22318272, 0x832d7372, 0x6576287d, 0x2d73756e, + 0x83727562, 0x6b732245, 0x2e0f822d, 0x616c6974, 0x6d726f74, 0x72747461, 0x82737365, 0x6c6c2f6b, 0x6f6d776f, 0x656c6962, 0x7465722d, 0x91486f72, + 0x742d2809, 0x736e6172, 0x8c726566, 0x82652012, 0x707521d6, 0x772b128a, 0x74616568, 0x71736f6d, 0x82746975, 0x2207853d, 0x82656e2d, 0x6e752813, + 0x756f6d64, 0x8261746e, 0x696323d1, 0x0c887974, 0x6e75732a, 0x2d6c696f, 0x6c6c6577, 0x25056f46, 0x6f72672d, 0x0b867075, 0x6e696c23, 0x220a8665, + 0x826c7570, 0x8667200d, 0x6f72260d, 0x72656262, 0x210d8879, 0x9248666f, 0x0a594706, 0x2d6f7422, 0x72233f85, 0x436e6f73, 0x2d2105b8, 0x06eb4a75, + 0x622b188a, 0x73616572, 0x65656674, 0x826e6964, 0x242c845e, 0x73727562, 0x22518674, 0x486e6163, 0x632907ef, 0x6b6c6168, 0x72616f62, 0x421b8764, + 0x632405f6, 0x6b636568, 0x6a42128d, 0x24188d0a, 0x756e696d, 0x21128d73, 0x118f6c70, 0x8d07ba44, 0x6d782327, 0x66877261, 0x65726423, 0x06d14173, + 0x64242486, 0x6e776f72, 0x6621c289, 0x062f4161, 0x0d86d084, 0x86050242, 0x21cc8230, 0x47842d66, 0x72231088, 0x89737361, 0x696d2d42, 0x6174696c, + 0x702d7972, 0x746e696f, 0x72231792, 0x416c6669, 0x2c88071b, 0x2d6f7422, 0x05854f85, 0x61722d23, 0x8bef8779, 0x6873262f, 0x65746c65, 0x23248672, + 0x6b6c6177, 0xa5416082, 0x6f6c2706, 0x6c2d706f, 0x82416665, 0x231d8d07, 0x68676972, 0x6421198f, 0x244f8261, 0x696c2d64, 0x06924d6e, 0x8e056747, + 0x756c265d, 0x67616767, 0x05334b65, 0x8c0bc444, 0x0bba4111, 0x82616c21, 0x41298650, 0x1184057e, 0x636f6c23, 0x2133826b, 0x07446574, 0x82702005, + 0x07434458, 0x6c6f6223, 0x420f8b74, 0x208a051b, 0x75215e8c, 0x42378767, 0x278a0517, 0x73204482, 0x7e84488b, 0x6e617231, 0x676e696b, 0x6174732d, + 0x616f7272, 0x82622d64, 0x65692107, 0x72240b86, 0x65676469, 0xdc8b1684, 0x7c8a108b, 0x5b85168b, 0xd9834f83, 0x732c1984, 0x656b6970, 0x67757273, + 0x6b636173, 0x2505364d, 0x6f686373, 0x66456c6f, 0x8a128d0c, 0x84188d5d, 0x2312865f, 0x67616c66, 0x6c830a86, 0x6568732c, 0x702d7465, 0x7473616c, + 0xa5476369, 0x632d2305, 0x09867461, 0x676f6422, 0x682e0986, 0x74726165, 0x61757173, 0x6e2d6572, 0x09866966, 0x2106e041, 0x12826f63, 0x64656e22, + 0x76321586, 0x73757269, 0x66617473, 0x6e732d66, 0x73656b61, 0x61836e75, 0x2d746e2a, 0x746c6977, 0x70726174, 0xd8470383, 0x65742307, 0x0383746e, + 0x4a0acf50, 0x168a0761, 0x004b6c20, 0x24148a08, 0x6e727574, 0x8919832d, 0x2d732113, 0x22051051, 0x4f73746e, 0x6f2607c0, 0x62617472, 0x0e85656c, + 0x702d7322, 0x77290f88, 0x632d7265, 0x746c6c65, 0x3509836f, 0x6573626f, 0x74617672, 0x746e6f69, 0x2d656572, 0x79746963, 0x1a827274, 0x05856c20, + 0x72622d26, 0x736b6369, 0x4405d04d, 0x722405e7, 0x74686769, 0xfc4a1085, 0x240c8506, 0x6c656966, 0x220a8a64, 0x856e752d, 0x6c70240d, 0x50656e61, + 0x62250546, 0x65777465, 0x23be8265, 0x73656e69, 0x6c201285, 0x09850a82, 0x79617222, 0x72271386, 0x61746365, 0x866c676e, 0x69762735, 0x69667765, + 0xa982646e, 0x42616921, 0x76200d0b, 0x76241083, 0x73757269, 0x42083f4e, 0x1842072b, 0x6f77230a, 0x0e426d72, 0x832d2005, 0x63732a6e, 0x646c6968, + 0x6572642d, 0x220a8673, 0x82616572, 0x676e2113, 0x240bca49, 0x63656863, 0x45108b6b, 0x74260b0a, 0x756f7268, 0xac526867, 0x41e18306, 0x732c05e7, + 0x6c706174, 0x72747265, 0x2d6e6961, 0x6d270582, 0x7472616d, 0x47696e69, 0x6529063d, 0x7974706d, 0x6973756d, 0x0f3c4763, 0x21056a42, 0xc9826174, + 0x82726521, 0x746d3175, 0x656c6261, 0x6c65632d, 0x6c2d736c, 0x65677261, 0x0a85108a, 0x73696c23, 0x84a48474, 0x24508f98, 0x756c702d, 0x43149073, + 0xfa4105f1, 0x66662105, 0x22055e53, 0x52616567, 0x63200570, 0x2c078843, 0x6e776f64, 0x64616f6c, 0x6f626e69, 0x06f54178, 0x61746f24, 0x274d6574, + 0x0571510c, 0x2008ab41, 0x838f832d, 0x6c662341, 0xce826761, 0x68706430, 0x73656e6f, 0x756c6f76, 0x6f2d656d, 0x09866666, 0x776f6c22, 0x682b0986, + 0x71686769, 0x646f6372, 0x84616265, 0x61742206, 0x24028267, 0x6f6f6273, 0x07dd516b, 0x69727024, 0xe251746e, 0x6f663405, 0x6f62746e, 0x7469646c, + 0x63696c61, 0x74786574, 0x8265682d, 0x84742042, 0x6977240a, 0x82687464, 0x43672018, 0x0985051c, 0x6e656325, 0x85726574, 0x8372200b, 0x260a852a, + 0x7473756a, 0x83796669, 0x756f23b0, 0x24826474, 0x836e6921, 0x69762905, 0x696f6564, 0x6567616d, 0x440b0e49, 0x5c8206d7, 0x732d6627, 0x6b6f7274, + 0x06f74265, 0x6e657026, 0x2d6f742d, 0x2c050044, 0x6f727261, 0x752d7377, 0x6f642d70, 0x41838577, 0x6227052d, 0x776b6361, 0x82647261, 0x7065213b, + 0x66230c88, 0x87747361, 0x6c702f0c, 0x61707961, 0x73657375, 0x66706f74, 0x2d83726f, 0x2d200686, 0x0b872783, 0x6574732e, 0x656a6570, 0x68637463, + 0x6f727665, 0x0b876485, 0xaa86de84, 0x756c7023, 0x220a8673, 0x886e696d, 0x6d78240b, 0x456b7261, 0x0b860ba5, 0x48083b4d, 0x692f0559, 0x636f666e, + 0x73736f72, 0x72696168, 0x4f616273, 0x2d20056a, 0x42085c4f, 0xee820a04, 0x83051e42, 0x2f2f82f3, 0x78656572, 0x646e6170, 0x706d6f63, 0x73736572, + 0x8f437d8b, 0x6967290a, 0x656c7466, 0x69666661, 0x79233082, 0x54796565, 0x7226077d, 0x676e6169, 0xd34b656c, 0x6c70300b, 0x63656e61, 0x6e656c61, + 0x2d726164, 0x82796164, 0x66752497, 0x82656c66, 0x656d2863, 0x616d746e, 0x41656e67, 0x75210811, 0x070f4170, 0x72249183, 0x65777465, 0x612b1c82, + 0x732d7472, 0x70706f68, 0x53676e69, 0x0585057c, 0x706f2d23, 0x41dd8565, 0x7a5008b8, 0x68632110, 0x62223d83, 0x84427261, 0x05a64a05, 0x79656b27, + 0x72616567, 0x22838673, 0x82747373, 0x6168239b, 0x2245666c, 0x0ce0540a, 0x75687428, 0x6174626d, 0x2d516b63, 0x69722408, 0x85746867, 0x0a404223, + 0x22055b41, 0x556f742d, 0x74300719, 0x68706f72, 0x6c707579, 0x6c64616f, 0x6e6f6d65, 0x46055543, 0x0b840593, 0x6c6e7533, 0x636b636f, 0x69646572, + 0x61632d74, 0x73726472, 0x38b38273, 0x72642d64, 0x62657669, 0x686c6c75, 0x636e726f, 0x69747265, 0x61636966, 0x05025774, 0x696f7023, 0x065c516e, + 0x6e616823, 0x056e4964, 0x656c2d24, 0x0e8a7466, 0x8a707521, 0x6f64220c, 0x077b4f77, 0x2c83c485, 0x8c116650, 0x70752111, 0x42830e8c, 0x6f6c672d, + 0x72776562, 0x68636e65, 0x8273696c, 0x456820b1, 0x742b0566, 0x72627265, 0x63666569, 0x43657361, 0x30081144, 0x72657375, 0x6e696c73, 0x6f6c636b, + 0x6c666475, 0x736b7361, 0x73736963, 0x6373726f, 0x7079706f, 0x72657061, 0x70696c63, 0x706f6c66, 0x642d7970, 0x261f8269, 0x72617571, 0x83616265, + 0x21678237, 0x6e846c75, 0x736c6f27, 0x6b697274, 0x06c04565, 0x646e7524, 0x57827265, 0x54055d45, 0x74240996, 0x6b637572, 0x2009664c, 0x25498263, + 0x6f642d74, 0x09856e77, 0x85707521, 0x656c2307, 0x09857466, 0x67697224, 0x97457468, 0x05745605, 0x74209b83, 0x36859f82, 0x75210884, 0x07755070, + 0x830c5345, 0x61673d44, 0x626c6576, 0x73746c6f, 0x6d657469, 0x6d757061, 0x6c657262, 0x6170616c, 0x6c657473, 0x62225b83, 0xcb826c75, 0x776f7222, + 0x41062242, 0x6c230a83, 0x4864756f, 0x63200a48, 0x75250f8a, 0x65737570, 0x23b98272, 0x726f7463, 0x742a4a82, 0x63736f68, 0x7365706f, 0xb8826975, + 0x62657322, 0x6d296482, 0x732d6775, 0x65637561, 0x241c8272, 0x61746970, 0x58fd846c, 0x2a870750, 0x804e0f87, 0x6562210a, 0x3e835b82, 0x706d6524, + 0xc6427974, 0x682d2105, 0x702a0786, 0x6173756c, 0x656c676e, 0xe1832d73, 0x72200a86, 0x0b86cb83, 0x86707521, 0x6f642308, 0x0a846e77, 0xe5852989, + 0x27861485, 0x7721c582, 0x05bf4e6e, 0x6261742c, 0x2d74656c, 0x74747562, 0x3f4e6e6f, 0x240c8506, 0x746f7571, 0x85468465, 0x266f8409, 0x6e697073, + 0x4272656e, 0x6627058b, 0x2d656361, 0x82696d73, 0x21098394, 0x7c827266, 0x2a081384, 0x6768656d, 0x70656d61, 0x656b6461, 0x616f6279, 0x6c666472, + 0x632d6761, 0x6b636568, 0x64657265, 0x6d726574, 0x6c616e69, 0x82646f63, 0x6c70260e, 0x6c612d79, 0x0828466c, 0x82726121, 0x72632348, 0x1e83706f, + 0x72622d2a, 0x68636e61, 0x6b6e696c, 0x3105c655, 0x6f666e69, 0x65707573, 0x72637372, 0x73747069, 0x08856275, 0x61726533, 0x70726573, 0x6c7a7a75, + 0x69702d65, 0x6d656365, 0x22448369, 0x8a6e6f68, 0x25438509, 0x65696873, 0x0a45646c, 0x69662f07, 0x652d6572, 0x6e697478, 0x73697567, 0x7e826568, + 0x7420a682, 0x4609de45, 0x304e0921, 0x46128408, 0xdb820b28, 0xa7431384, 0x0b3d4508, 0x6f21c183, 0x055e4472, 0x656b2d37, 0x6c6f6879, 0x6c756265, + 0x7965736c, 0x6c6c6565, 0x69737069, 0x25078773, 0x7265762d, 0x9b826974, 0x2106fc41, 0x80467372, 0x6c702307, 0x19827961, 0x4b656b21, 0x6d230748, + 0x56756e69, 0x2d240509, 0x6e727574, 0x84084246, 0x6f64230c, 0x42866e77, 0x63218a82, 0x08724b6b, 0x3f451587, 0x6873240d, 0x45657261, 0x63260b44, + 0x61706d6f, 0x36867373, 0x8c09b643, 0x70752110, 0x72260e8c, 0x74686769, 0xd2597565, 0x74732506, 0x696c7265, 0x5906cf59, 0x79210964, 0x05fe5965, + 0x62757223, 0x0576596c, 0x856f7721, 0x69662311, 0x0383656c, 0x85055a4a, 0x23c6839f, 0x7a2d612d, 0x0b88ad88, 0x77221984, 0x43826469, 0x726f6823, + 0x8f208874, 0x22278412, 0x88392d31, 0x280b8220, 0x6d756874, 0x752d7362, 0x83088670, 0x236f8a23, 0x676e6f6c, 0x0c892e88, 0x74219d82, 0x840e892d, + 0x4f0f84ed, 0x652108c3, 0x062c4f73, 0x6e757334, 0x6e6f6f6d, 0x2d786f62, 0x68637261, 0x62657669, 0x2b416775, 0x0af3450c, 0x746f6422, 0x5909aa59, + 0x732508de, 0x74747568, 0x23dd826c, 0x65636170, 0xf5443a86, 0x08ef5507, 0x38062145, 0x64617267, 0x69746175, 0x632d6e6f, 0x616c7061, 0x6175676e, + 0x61666567, 0x82288778, 0x646c2882, 0x63776170, 0x83656275, 0x72733903, 0x63796365, 0x6163656c, 0x78617472, 0x65727469, 0x74616465, 0x73616261, + 0x24058141, 0x66666470, 0x237c8269, 0x64726f77, 0x65240884, 0x6c656378, 0x70290984, 0x7265776f, 0x6e696f70, 0x210e8474, 0x69836d69, 0x2b826920, + 0x70697a25, 0x84726570, 0x75612414, 0x846f6964, 0x69762309, 0x09856564, 0x646f632c, 0x66696c65, 0x69722d65, 0x5c43676e, 0x6f6e2606, 0x70686374, + 0x20368261, 0x059d482d, 0x636f6c23, 0x069e556b, 0x656c2d28, 0x65687466, 0x2e826461, 0x7261702a, 0x61726761, 0x6c736870, 0x96474f82, 0x2d652205, + 0x4251826e, 0xbf4207a0, 0x3e118405, 0x626d6f62, 0x62747566, 0x74746c6f, 0x6e696279, 0x6c75636f, 0x70737261, 0x6e67756c, 0x84737765, 0x6977266e, + 0x61636966, 0x2619836c, 0x62726f74, 0x446c6c65, 0x74340519, 0x68736172, 0x79706f63, 0x68676972, 0x65796574, 0x6f72642d, 0x7021d683, 0x22f08261, + 0x82757262, 0x6b612a1d, 0x61632d65, 0x656c646e, 0x05d24873, 0x65726123, 0x22098561, 0x85656970, 0x696c2d08, 0x6f74656e, 0x656c6767, 0x66666f2d, + 0x6e300987, 0x79636962, 0x62656c63, 0x6c637375, 0x6465736f, 0x70244782, 0x6e6f6974, 0x7324e282, 0x656b6568, 0x2405b75d, 0x74726163, 0x20ae822d, + 0x42088473, 0x64290997, 0x6f6d6169, 0x6873646e, 0x058b4669, 0x63657327, 0x6d746572, 0x84c1826f, 0x74732c56, 0x74656572, 0x6569762d, 0x84656877, + 0x6c753343, 0x65766573, 0x6d73756e, 0x6d737261, 0x75637265, 0x0a837972, 0x82095654, 0x736e27f0, 0x646e6567, 0x28847265, 0x6f642d26, 0x656c6275, + 0x0a852484, 0x40841685, 0xb74b4482, 0x821f8406, 0x6b6f256f, 0x70752d65, 0x722a0d8b, 0x74686769, 0x7475656e, 0x56857265, 0x73656c24, 0x5d837373, + 0x82757221, 0x84d78406, 0x82782008, 0x626b2335, 0x81826465, 0x846e6921, 0x732d2904, 0x61776275, 0x74616279, 0x79253c82, 0x6c75662d, 0x210b876c, + 0xda826874, 0x75712d22, 0x6522d582, 0x15877372, 0x6c616823, 0x860b8766, 0x220e871b, 0x5b706d65, 0x7021076a, 0x235f826f, 0x2d697265, 0x7328fd82, + 0x626f726f, 0x7463656a, 0x8605a854, 0x6e752a0b, 0x756f7267, 0x746f6e70, 0x3fdf8265, 0x796b6369, 0x6e6f6c63, 0x61637365, 0x622d656c, 0x6e616c61, + 0x68646563, 0x6772756f, 0x7373616c, 0x61222282, 0x0e897472, 0x0d898583, 0x896e6521, 0x61682329, 0x3f82646e, 0x2d6b6326, 0x74736966, 0x20076258, + 0x076f492d, 0x6c251e84, 0x72617a69, 0x240a8464, 0x636f7073, 0x8609846b, 0x2f0b85b2, 0x65636165, 0x64617274, 0x72616d65, 0x6765726b, 0x65254a82, + 0x74646572, 0x08cb4b76, 0x20052b42, 0x05d84b6c, 0x6e696d23, 0x23b98475, 0x7261646e, 0x8805fa51, 0x68633d28, 0x696b6365, 0x7375646e, 0x6d797274, + 0x702d7061, 0x69736e69, 0x2d736e67, 0x74736f70, 0x6d261082, 0x61737365, 0x9e436567, 0x61702306, 0x0b877375, 0x6f747326, 0x67616270, 0x2408fd4b, + 0x6b736162, 0x090c4c65, 0x696e752c, 0x73726576, 0x612d6c61, 0x06456363, 0x532d2008, 0x773007fb, 0x2d687469, 0x656e6163, 0x69647561, 0x65642d6f, + 0x2005b447, 0x06854b69, 0xc74e2d20, 0x72622705, 0x6c6c6961, 0xb7826565, 0xe5836c20, 0x2f06b95f, 0x2d6c7361, 0x65746e69, 0x65727072, 0x676e6974, + 0x64331f83, 0x68666165, 0x73646e61, 0x2d657965, 0x2d776f6c, 0x82736976, 0x6f662b4d, 0x612d746e, 0x6f736577, 0x1e84656d, 0x6b616823, 0x08a15a65, + 0x65706f26, 0x6464616e, 0x22057c55, 0x876b6f6f, 0x6163230b, 0xf2866472, 0x7228f082, 0x622d6469, 0x65676461, 0x19830782, 0x220b1e63, 0x636c7566, + 0x97420c44, 0x23298b0d, 0x666c6168, 0x9f420f8b, 0x24128b06, 0x74706d65, 0x05605b79, 0x7461622a, 0x646f7068, 0x74736163, 0x2805b563, 0x78616d2d, + 0x7a696d69, 0x210e8765, 0x0e8b6e69, 0x7421c282, 0x8304826f, 0x06166155, 0x63696d2e, 0x68636f72, 0x6e737069, 0x6c66776f, 0x732cf782, 0x6e6f6f70, + 0x6e657475, 0x736c6973, 0x2d056350, 0x66656c2d, 0x61727474, 0x632d6873, 0x13856e61, 0x6f747328, 0x74617770, 0x484d6863, 0x064d620a, 0x434d1185, + 0x4a308509, 0x5c820551, 0x616d692b, 0x70736567, 0x69636e65, 0x8205826c, 0x632d2d02, 0x6470696c, 0x2d6e776f, 0x676e6f6c, 0x47083047, 0x7521092a, + 0x24198470, 0x656c6966, 0x872f822d, 0x087e5ce5, 0x4c09a853, 0x974106ba, 0x0a334d06, 0x490a3947, 0x75210b81, 0x4e318270, 0x3847100b, 0x851a8706, + 0x2341831f, 0x65706572, 0x6f20f482, 0x2305b362, 0x6374696d, 0x6d2e0a83, 0x65677265, 0x6b736564, 0x67706f74, 0x49496d65, 0x27088408, 0x6f6c7075, + 0x6f2d6b63, 0xac4ab782, 0x6f642208, 0x09674a74, 0x4b05b848, 0x73250645, 0x65657263, 0x0c594b6e, 0x134d198c, 0x312d2409, 0x646f6870, 0x693f0781, + 0x6567616d, 0x726f702d, 0x69617274, 0x70657274, 0x6873796c, 0x646c6569, 0x6c61682d, 0x4b646576, 0x5d8c06b0, 0x74251385, 0x656b6369, 0x065f6574, + 0x65737523, 0x05ed5272, 0x24095652, 0x72616d78, 0x0953516b, 0x646e6123, 0x0832412d, 0x2d6f7428, 0x746e6563, 0x11887265, 0x2c891e83, 0x6f726623, + 0x2b21866d, 0x65736162, 0x6c6c6162, 0x7461622d, 0x6c210382, 0x4410876c, 0x1a830512, 0x776f6226, 0x676e696c, 0x63241d84, 0x73736568, 0x2d260484, + 0x68736962, 0x0b86706f, 0x72616f23, 0x200a8564, 0x862a826b, 0x696e2409, 0x85746867, 0x6170230b, 0x09856e77, 0x65757123, 0x2f0a8665, 0x6b6f6f72, + 0x626d7564, 0x6c6c6562, 0x746f6f66, 0x67236c83, 0x84666c6f, 0x742d2f69, 0x6f686565, 0x79656b63, 0x6375702d, 0x2c82626b, 0x18846d20, 0x28060442, + 0x6c6c7566, 0x6c626174, 0x28288265, 0x73696e6e, 0x6461702d, 0x05e14564, 0x6f766c26, 0x79656c6c, 0x68204e83, 0x7422f885, 0x08826273, 0x65676125, + 0x60786f62, 0xef5e057e, 0x085b4f06, 0x2807c64d, 0x65726966, 0x616c662d, 0x07db666d, 0x70616325, 0x5f6c7573, 0xc7820b53, 0x426b6321, 0x2d2208e3, + 0x9f5a696c, 0x6f642308, 0x764b7374, 0x696c2705, 0x6e64656e, 0x88826461, 0x61637924, 0x52837472, 0x65627422, 0x20057e49, 0x055f676d, 0x82696621, + 0x61772aae, 0x6f666576, 0x696b6d72, 0x43828774, 0x68200624, 0x2006b144, 0x246a832d, 0x65746f6e, 0x08cb6673, 0xde826120, 0x69707427, 0x70736c6c, + 0x097c4572, 0x6f622d26, 0x656c7474, 0x38871292, 0x2d258082, 0x736c7570, 0x05c94e65, 0x7361662d, 0x6f6d7374, 0x676e696b, 0x82727973, 0x05ee4f05, + 0x7473742a, 0x6d726568, 0x74656d6f, 0x26055a56, 0x6c616976, 0x5e617773, 0x7738062c, 0x68676965, 0x63732d74, 0x78656c61, 0x7961722d, 0x2d786f62, + 0x6e65706f, 0x2306f551, 0x746f642d, 0x49070152, 0x63240587, 0x6863756f, 0x3f69d586, 0x6f742106, 0x6f241a82, 0x766f6474, 0x5f0c7a68, 0x65230dc5, + 0x8c747261, 0x8d3c8511, 0x6f722412, 0x84656c70, 0x68732026, 0x2b4607c0, 0x612d2408, 0x846c676e, 0x68732060, 0x70290aad, 0x63617261, 0x65747568, + 0x5cb9822d, 0x632406b6, 0x79727261, 0x69220f84, 0x08826767, 0x6b6e612a, 0x62626972, 0x6f726e6f, 0x732c2882, 0x6c646565, 0x73676e69, 0x2d6e6769, + 0x67205d82, 0x2f4f0b82, 0x772d2709, 0x746b6e69, 0x55417061, 0x61722306, 0x4983706d, 0x22056341, 0x82766f6d, 0x6976232c, 0xf1836564, 0x68736122, + 0x65202c82, 0x4305f656, 0x526809d5, 0x612d2909, 0x6f727473, 0x7475616e, 0x63241d84, 0x6b636568, 0x6c210985, 0x2209866f, 0x49616567, 0x6521067c, + 0x201a846e, 0x4aa38267, 0x394c0543, 0x84652006, 0x21308816, 0x2782696d, 0x6e241284, 0x616a6e69, 0x85440984, 0x200a8505, 0x8495826c, 0x61742209, + 0x20078567, 0x21418469, 0xcc532d73, 0x6c612505, 0x6e752d65, 0x21073949, 0x0f8d6373, 0x6c662d2e, 0x6c627069, 0x65646e65, 0x6f6f6272, 0x59055145, + 0x62250545, 0x64616f72, 0x82d18263, 0x6d6f2108, 0x8909b15d, 0x832d2009, 0x6863376f, 0x68637275, 0x6e696f63, 0x6d6f6373, 0x74636170, 0x7369642d, + 0x38506363, 0x6e772505, 0x65636964, 0x2d230383, 0x86766966, 0x756f2208, 0x21118472, 0x10856e6f, 0x78697322, 0x74230f84, 0x85657268, 0x77742d11, + 0x7669646f, 0x64656469, 0x2d726f6f, 0x8405a04b, 0x706f3c0a, 0x65666e65, 0x65687461, 0x6f726672, 0x73616767, 0x6d75702d, 0x616c6770, 0x6b657373, + 0x2d270cba, 0x61757165, 0x6165686c, 0x6930079c, 0x6e69666e, 0x6b797469, 0x2d697769, 0x64726962, 0x8508f66b, 0x656d2529, 0x79726f6d, 0x410f4046, + 0x1f4605db, 0x6177220a, 0x20288276, 0x0661686e, 0x2d312d22, 0x63221089, 0x5e536568, 0x200a8407, 0x05f0422d, 0x746f6e22, 0x70256185, 0x74656c61, + 0x073f4e74, 0x72617026, 0x676e696b, 0x35097967, 0x63656a6f, 0x63657274, 0x74706965, 0x6f626f72, 0x6c757274, 0x04847265, 0x6f632d28, 0x6e69626d, + 0x0d856465, 0x726f6829, 0x6e6f7a69, 0x856c6174, 0x08a6500f, 0x6f68632c, 0x63736c6f, 0x64776572, 0x15826972, 0x6f687333, 0x72702d65, 0x73746e69, + 0x6c756b73, 0x6e61626c, 0x0732442d, 0x726f7423, 0x211f8265, 0x494c6270, 0x67612705, 0x65726567, 0x7a827364, 0x77706f27, 0x6c656661, 0x264b8274, + 0x73786f62, 0x5e726968, 0x27080e24, 0x6c6c6177, 0x61667465, 0x612d6563, 0x7972676e, 0x68637261, 0x62796177, 0x2d6b6f6f, 0x616c7461, 0x61776173, + 0x65646472, 0xb5522482, 0x65623705, 0x7265697a, 0x7275632d, 0x6f626576, 0x7262676e, 0x62687375, 0x20477375, 0x61632706, 0x62616e6e, 0x35417369, + 0x06f54c07, 0x220a625a, 0x82746963, 0x65622832, 0x632d6c6c, 0x82636e6f, 0x6567264c, 0x6b6f6f63, 0x28058669, 0x7469622d, 0x6f726365, 0x31518670, + 0x68636174, 0x6172676f, 0x642d6870, 0x74696769, 0xad846c61, 0x7a696425, 0x5163797a, 0x2d24054d, 0x66617264, 0x67246282, 0x6d757264, 0x2d270383, + 0x65657473, 0x4261706c, 0x3d56075f, 0x06f44505, 0x6e6f6326, 0x63617274, 0x4e05674f, 0x66290906, 0x2d656c69, 0x6f707865, 0x21198572, 0x0a896d69, + 0x6f766e24, 0xc24f6369, 0x85692005, 0x0610420b, 0xe7453484, 0x2710840b, 0x6e676973, 0x72757461, 0x62853185, 0x82707521, 0x836c201a, 0x20ad8203, + 0x270c8269, 0x7265676e, 0x6e697270, 0x73216d82, 0x24d28468, 0x73756c66, 0x2da48268, 0x2d656361, 0x776f7266, 0x706f2d6e, 0xa05b6e65, 0x61652b0c, + 0x2d687472, 0x69726661, 0x0b866163, 0x83656d21, 0x8673200c, 0x6973220d, 0x234b8461, 0x6d697267, 0x0b874782, 0x08886e20, 0x69772d24, 0x0d896564, + 0x61656223, 0x240d8d6d, 0x6577732d, 0x05114261, 0x6e224482, 0x5983682d, 0x23897320, 0x75717322, 0x5c82b483, 0x1f842d20, 0x2d210f85, 0x8b268274, + 0x61742225, 0x8e0e8a72, 0x6f74241d, 0x8a75676e, 0x200f8585, 0x865a8f2d, 0x69772316, 0x7f896b6e, 0x78820d83, 0x03837020, 0x5b08d553, 0x354209ce, + 0x27108306, 0x68746573, 0x6c686769, 0x74290382, 0x6f687265, 0x75742d74, 0x06876162, 0x65230d82, 0x876f6a6c, 0x696b22c9, 0x83ad8573, 0x412d2008, + 0x0d840814, 0x05417083, 0x23848405, 0x6775616c, 0x8405af41, 0x852c8909, 0x85c38a0e, 0x483e8310, 0x2d200b78, 0x2b07af56, 0x2d70616d, 0x61636f6c, + 0x6e6f6974, 0x2d2c0b8b, 0x6d746f64, 0x656b7261, 0x64656d72, 0x2606ed42, 0x2d68656d, 0x41616c62, 0x72390607, 0x696c6c6f, 0x652d676e, 0x6d736579, + 0x6d756e6f, 0x6d746e65, 0x6174726f, 0x25dd8272, 0x656c7473, 0xd8826170, 0x26832d20, 0x70726526, 0x70737361, 0x70281c82, 0x662d6e65, 0x79636e61, + 0x6e220883, 0x06836269, 0x6c757222, 0x57822082, 0x612d6529, 0x76697272, 0x84706c61, 0x8264200c, 0x74722341, 0xc2487275, 0x26fd840c, 0x2d646173, + 0x88797263, 0x6574270b, 0x61767261, 0x56532d6e, 0x09f94206, 0x2708c456, 0x6165622d, 0x6c6f736d, 0x61249c83, 0x736c656e, 0x70339082, 0x63746f6c, + 0x72707368, 0x632d7961, 0x74736e61, 0x5a706d61, 0x0b5108a2, 0x08d65706, 0x7285ed86, 0x70727529, 0x65736972, 0x82617773, 0x6f622240, 0x07fa636f, + 0x69777327, 0x6e696d6d, 0x28178267, 0x6c2d7265, 0x65646461, 0x06055d72, 0x8405f745, 0x6974293e, 0x74646572, 0x68746f6f, 0x8307bf58, 0x6863279d, + 0x74636576, 0x285d726f, 0x06564906, 0x48065d48, 0x2d200925, 0x8705584e, 0x6e2d20b4, 0x61320718, 0x656c7070, 0x6f68772d, 0x7461656c, 0x6f626d6f, + 0x7e47656e, 0x722d2308, 0x89826165, 0x61726227, 0x61636e69, 0x200e8372, 0x51078372, 0x0a84064f, 0x2807566a, 0x65646973, 0x72616863, 0x27c68267, + 0x6174732d, 0x6e6f6974, 0x56069b52, 0x722f0588, 0x74686769, 0x77617264, 0x6c6f702d, 0x586f6779, 0x2d27066b, 0x65646f63, 0x8279616c, 0x726724f7, + 0x4d70756f, 0x63200844, 0x2608235d, 0x676e756c, 0x83696d73, 0x6f633410, 0x696f6570, 0x61632d6c, 0x6f6f706e, 0x61687370, 0x82736570, 0x2d722c6d, + 0x6c2d666f, 0x67656669, 0x85677561, 0x682d2404, 0x84686769, 0x0654430e, 0x1c840b8b, 0x65657424, 0x04846874, 0x3106aa44, 0x2d736b73, 0x61656874, + 0x74726574, 0x66666172, 0x53826369, 0x23088e61, 0x736e6f6d, 0x75291984, 0x702d6b63, 0x756b6369, 0x09464d70, 0x61646134, 0x62686b6e, 0x2d6b6f6f, + 0x6c626962, 0x73756265, 0x9a826e69, 0x69742d28, 0x6963656d, 0xd54a7974, 0x6c6c2309, 0x0d867261, 0x88457320, 0x2beb8406, 0x72616864, 0x6863616d, + 0x61726b61, 0x240c9d50, 0x7865742d, 0x06525d74, 0x6e696d24, 0x0b867375, 0x826c7021, 0x0c0a710a, 0x3405e747, 0x75706f67, 0x686d6172, 0x61736d61, + 0x61686162, 0x64656a69, 0x2f9a8469, 0x72756f6a, 0x2d6c616e, 0x6c696877, 0x616b736c, 0x6b261e82, 0x646e6168, 0x04826c61, 0x72616d23, 0x3e77876b, + 0x75622d73, 0x656d6b6c, 0x61726f6e, 0x736f6d68, 0x6f657571, 0x6170736d, 0x74656867, 0x412d6974, 0x2d2d060a, 0x69796c66, 0x6570676e, 0x70656361, + 0x2904826c, 0x2d666f2d, 0x73726f77, 0x03586968, 0x6f702307, 0xbd586c6c, 0x4813840f, 0x7020093a, 0x20077970, 0x834c8361, 0x2d73238e, 0x0c847270, + 0x7120b484, 0x6e20cc82, 0x85106a61, 0x421690ea, 0x7323073e, 0x566b636f, 0x72310706, 0x2d746f6f, 0x69726176, 0x656c6261, 0x72617473, 0x28ed822d, + 0x6572632d, 0x6e656373, 0x82108474, 0x61642cb7, 0x73646976, 0x67616e79, 0x8275676f, 0x8372201a, 0x837420b9, 0x2c0482ff, 0x672d6969, 0x76657461, + 0x72616869, 0x05975261, 0x82054553, 0x792d24b2, 0x4a676e61, 0x2d2206b9, 0x40436870, 0x6b732807, 0x636c6c75, 0x6f706d61, 0x633105cd, 0x68637461, + 0x63726961, 0x64756f6c, 0x6f6f6d2d, 0x2d09856e, 0x636e7573, 0x6964776f, 0x642d6563, 0x07853032, 0x6f643625, 0x82726467, 0x646e3e88, 0x736d7572, + 0x6b636974, 0x7469622d, 0x6e756465, 0x6e6f6567, 0x656c6966, 0x7673632d, 0x2ec68368, 0x74736966, 0x736f6867, 0x6d616874, 0x8272656d, 0x6b752b13, + 0x68686169, 0x772d7461, 0xd7687a69, 0x69682e09, 0x676e696b, 0x70706968, 0x726f686f, 0x06b06b73, 0x6968633c, 0x79656e6d, 0x6172632d, 0x72686b63, + 0x696e7679, 0x69732d61, 0x616d6e67, 0xd1696b73, 0x656e2607, 0x726f7774, 0x284f826b, 0x6f646572, 0x72657474, 0x09576972, 0x6e757223, 0x250d826e, + 0x6f726373, 0xf3846c6c, 0x6f324c82, 0x6f627373, 0x7373656e, 0x6873616c, 0x64697073, 0x2a657265, 0x702d2305, 0x0b827061, 0x74216d82, 0x057d4c6f, + 0x6a6e6923, 0x23568275, 0x632d7276, 0x6221ac82, 0x2004826f, 0x44d78377, 0x7723079f, 0x82646e69, 0x2d652103, 0x4105954e, 0x6d270534, 0x62746165, + 0x866c6c61, 0x6f6f260d, 0x61722d6e, 0x06514169, 0x732c0989, 0x65776f68, 0x682d7372, 0x79766165, 0x84086e41, 0x6564232a, 0xf4826f6d, 0x6c66742a, + 0x752d6761, 0x75686173, 0x6323d482, 0x43656e61, 0x2d2a0709, 0x656d6f64, 0x6574656d, 0xa042726f, 0x6f622d06, 0x7068746f, 0x732d6f6f, 0x6d726f74, + 0x62296583, 0x6572776f, 0x6c627570, 0x23398269, 0x676f6d73, 0x220ceb53, 0x8b686769, 0x6f6c220f, 0x2d828577, 0x746c6f62, 0x6e726f74, 0x766f6461, + 0x39826c6f, 0x6e4a6f20, 0x06cb4e05, 0x74617728, 0x61627265, 0x03837962, 0x61632d22, 0x612f9782, 0x69626567, 0x7a61686f, 0x62647261, 0x55676f6c, + 0x642208ba, 0x0b887961, 0x65657723, 0x214c826b, 0x33827964, 0x83656e21, 0x746f2637, 0x68736163, 0x071d562d, 0x2d546d20, 0x75642406, 0x8273706d, + 0x39078763, 0x7269662d, 0x68746565, 0x656e7265, 0x66696774, 0x68637374, 0x61706d61, 0x604e6e67, 0x73652806, 0x73696877, 0x4e79656b, 0xab49056f, + 0x75652905, 0x65706f72, 0x70697267, 0x8905e052, 0x08ee4309, 0x69756726, 0x68726174, 0x60422f83, 0x6c6f2f06, 0x622d796c, 0x79727265, 0x73726f68, + 0x1b822d65, 0x69642208, 0x6c636963, 0x67697365, 0x6d6f6f6c, 0x65747469, 0x67756d6e, 0x746f682d, 0x69646172, 0x6f697461, 0x06f24f6e, 0x72300f88, + 0x72747365, 0x736d6f6f, 0x6c657461, 0x6574696c, 0x2d270888, 0x68736964, 0x822d6473, 0x736423fd, 0x07846d69, 0x2106bd41, 0x4b826b73, 0x0d6c6e20, + 0x6b732207, 0x09c24269, 0x2d230c85, 0x82726f6e, 0x6c73258c, 0x68676965, 0x22069f45, 0x5b6d732d, 0x2d2706bb, 0x776f6e73, 0x82616f62, 0x676e2122, + 0x6d230b83, 0x82736e61, 0x6c702312, 0xb282776f, 0xb45c6720, 0x05e44205, 0x2b0af74c, 0x6572772d, 0x6368636e, 0x656c6261, 0x16528d83, 0x75632e0a, + 0x64657672, 0x6f636162, 0x6f6f626e, 0x085b516b, 0x6165722d, 0x6c732d64, 0x63656369, 0x43656568, 0x6d200fa8, 0x5205f351, 0x75220936, 0x4d466573, + 0x2f428707, 0x74757263, 0x69646863, 0x73616573, 0x67676565, 0x32062e46, 0x65657274, 0x67727562, 0x61687265, 0x6d2d646e, 0x82646469, 0x69662294, + 0x2b11836e, 0x656d6c65, 0x61732d74, 0x79746566, 0x2007a760, 0x255b832d, 0x64746f68, 0x8d82676f, 0x82632d21, 0x606d2099, 0x41520520, 0x263b8209, + 0x70706570, 0x822d7265, 0x69702428, 0x85617a7a, 0x617323bb, 0xdc466b63, 0x32dd8406, 0x616e6174, 0x6162686b, 0x702d7372, 0x72676f72, 0x56737365, + 0x61270571, 0x776f7272, 0x5670752d, 0xd66d087f, 0x307d8308, 0x72756e2d, 0x61776573, 0x732d6576, 0x72617571, 0x06cd4165, 0x6b696222, 0x6223b782, + 0x8264726f, 0x6c612279, 0x2309866c, 0x656e6f6e, 0x74200a86, 0x230d6f6c, 0x67676964, 0x66293182, 0x63696e61, 0x70736e6f, 0x22298268, 0x466c662d, + 0x108809a7, 0x742a1a82, 0x69662d6f, 0x65746d6c, 0xcd827478, 0x68736122, 0x2309674d, 0x612d7a2d, 0x8808055e, 0x6f642e0b, 0x732d6e77, 0x74726f68, + 0x6469772d, 0x8f208865, 0x22278412, 0x88312d39, 0x240b8220, 0x6c657073, 0x0506616c, 0x696f7632, 0x616d6563, 0x61686c69, 0x6f632d74, 0x796f6277, + 0x2d210989, 0x73598273, 0x2d3e076c, 0x73756f6d, 0x64617265, 0x65726f69, 0x64726f63, 0x6e69762d, 0x61776c79, 0x65696b6c, 0x0684742d, 0x7261632d, + 0x6e617661, 0x73726556, 0x186e6f69, 0x202a08f3, 0x07ea5c43, 0x10cbf218, 0x6e6f4623, 0x3ef31874, 0x18362008, 0x920a1df3, 0x6f532518, 0x0064696c, + 0x01330082, 0x88018701, 0x06008901, 0x0c000b00, 0x8a010e00, 0x18018b01, 0x261406ee, 0x21002000, 0x10019701, 0x2e070aee, 0x3005860b, 0x32053105, + 0x34053305, 0x36053505, 0x38053705, 0x3a053905, 0x3c053b05, 0x3e053d05, 0x40053f05, 0x42054105, 0x44054305, 0x46054505, 0x48054705, 0x4a054905, + 0x4c054b05, 0x4e054d05, 0x50054f05, 0x52055105, 0x54055305, 0x56055505, 0x58055705, 0x5a055905, 0x5c055b05, 0x5e055d05, 0x60055f05, 0x62056105, + 0x64056305, 0x66056505, 0x68056705, 0x6a056905, 0x6c056b05, 0x6e056d05, 0x70056f05, 0x72057105, 0x74057305, 0x76057505, 0x78057705, 0x7a057905, + 0x7c057b05, 0x7e057d05, 0x80057f05, 0x82058105, 0x84058305, 0x86058505, 0x88058705, 0x8a058905, 0x8c058b05, 0x8e058d05, 0x90058f05, 0x92059105, + 0x94059305, 0x96059505, 0x98059705, 0x9a059905, 0x9c059b05, 0x9e059d05, 0xa0059f05, 0xa205a105, 0xa405a305, 0xa605a505, 0xa805a705, 0xaa05a905, + 0xac05ab05, 0xae05ad05, 0xb005af05, 0xb205b105, 0xb405b305, 0xb605b505, 0xb805b705, 0xba05b905, 0xbc05bb05, 0xbe05bd05, 0xc005bf05, 0xc205c105, + 0xc405c305, 0xc605c505, 0xc805c705, 0xca05c905, 0xcc05cb05, 0xce05cd05, 0xd005cf05, 0xd205d105, 0xd405d305, 0xd605d505, 0xd805d705, 0xda05d905, + 0xdc05db05, 0xde05dd05, 0xe005df05, 0xe205e105, 0xe405e305, 0xe605e505, 0xe805e705, 0xea05e905, 0xec05eb05, 0xee05ed05, 0xf005ef05, 0xf205f105, + 0xf405f305, 0xf605f505, 0xf805f705, 0xfa05f905, 0xfc05fb05, 0xfe05fd05, 0x0006ff05, 0x02060106, 0x04060306, 0x06060506, 0x08060706, 0x0a060906, + 0x0c060b06, 0x0e060d06, 0x10060f06, 0x12061106, 0x14061306, 0x16061506, 0x18061706, 0x1a061906, 0x1c061b06, 0x1e061d06, 0x20061f06, 0x22062106, + 0x24062306, 0x26062506, 0x28062706, 0x2a062906, 0x2c062b06, 0x2e062d06, 0x30062f06, 0x32063106, 0x34063306, 0x36063506, 0x38063706, 0x3a063906, + 0x3c063b06, 0x3e063d06, 0x40063f06, 0x42064106, 0x44064306, 0x46064506, 0x48064706, 0x4a064906, 0x4c064b06, 0x4e064d06, 0x50064f06, 0x52065106, + 0x54065306, 0x56065506, 0x58065706, 0x5a065906, 0x5c065b06, 0x5e065d06, 0x60065f06, 0x62066106, 0x64066306, 0x66066506, 0x68066706, 0x6a066906, + 0x6c066b06, 0x6e066d06, 0x70066f06, 0x72067106, 0x74067306, 0x76067506, 0x78067706, 0x7a067906, 0x7c067b06, 0x7e067d06, 0x80067f06, 0x82068106, + 0x84068306, 0x86068506, 0x88068706, 0x8a068906, 0x8c068b06, 0x8e068d06, 0x90068f06, 0x92069106, 0x94069306, 0x96069506, 0x98069706, 0x9a069906, + 0x9c069b06, 0x9e069d06, 0xa0069f06, 0xa206a106, 0xa406a306, 0xa606a506, 0xa806a706, 0xaa06a906, 0xac06ab06, 0xae06ad06, 0xb006af06, 0xb206b106, + 0xb406b306, 0xb606b506, 0xb806b706, 0xba06b906, 0xbc06bb06, 0xbe06bd06, 0xc006bf06, 0xc206c106, 0xc406c306, 0xc606c506, 0xc806c706, 0xca06c906, + 0xcc06cb06, 0xce06cd06, 0xd006cf06, 0xd206d106, 0xd406d306, 0xd606d506, 0xd806d706, 0xda06d906, 0xdc06db06, 0xde06dd06, 0xe006df06, 0xe206e106, + 0xe406e306, 0xe606e506, 0xe806e706, 0xea06e906, 0xec06eb06, 0xee06ed06, 0x7105ef06, 0x00000004, 0x20028201, 0x38038203, 0x01000006, 0x040000d3, + 0x08000083, 0x09000088, 0x0c0000ef, 0x0d000028, 0x08038209, 0x0000734b, 0x00004f0e, 0x00004c0f, 0x0000e210, 0x00008212, 0x0000c713, 0x00006115, + 0x00009616, 0x00007a17, 0x00002219, 0x0000501a, 0x0000431b, 0x0000121c, 0x0000081d, 0x0000ac1e, 0x00003621, 0x00005622, 0x00007f23, 0x00007024, + 0x20278225, 0x3c6f8226, 0x0000c426, 0x0000f327, 0x0000ce28, 0x0000a129, 0x00007c2a, 0x0000bf2b, 0x0000492c, 0x300b822d, 0x0000962e, 0x00005f2f, + 0x00002630, 0x0000fa31, 0x3d478233, 0x00004735, 0x0000eb35, 0x0000c636, 0x0000a637, 0x00004039, 0x0000cc3a, 0x0000b23b, 0x0382b13c, 0x0000b43b, + 0x0000a93e, 0x0000e940, 0x00007142, 0x00002c45, 0x00003d48, 0x00003c4b, 0x2433824e, 0x0000055b, 0x34178261, 0x0000be62, 0x0000ea64, 0x0000426b, + 0x00009b71, 0x00008874, 0x28cb8278, 0x0000047c, 0x0000357f, 0x24c78281, 0x00002186, 0x2c0f8288, 0x0000dc89, 0x0000b791, 0x0000d995, 0x3cd78298, + 0x00006b9a, 0x0000469c, 0x0000cea1, 0x0000e5a3, 0x00006da6, 0x0000e6a9, 0x0000fbab, 0x301f82af, 0x000094b1, 0x0000bbb4, 0x000067b8, 0x000002bc, + 0x289b82c3, 0x000087c6, 0x0000c5ca, 0x080f82cc, 0x003ecd2c, 0x00face00, 0x0024d100, 0x00b3d200, 0x00b6d400, 0x000cd600, 0x004ad700, 0x0053da00, + 0x0039dc00, 0x006ade00, 0x0031e000, 0x2b82e100, 0xbfe62908, 0x29ea0000, 0xedec0000, 0x4ff00000, 0x96f30000, 0xe4f50000, 0xcff60000, 0xc8f80000, + 0xe3fb0000, 0x8efe0000, 0x02000100, 0x2b080382, 0x01010085, 0x030100a9, 0x05010079, 0x0a01003a, 0x0c0100e0, 0x0e010080, 0x0f010062, 0x120100ef, + 0x13010091, 0x150100c9, 0x1801000b, 0x1a241f82, 0x1c010093, 0x1e342b82, 0x1f010027, 0x21010029, 0x2201004a, 0x24010092, 0x260100cc, 0x28383382, + 0x29010032, 0x2c01003d, 0x2e01001d, 0x30010023, 0x32010054, 0x3601003f, 0x3b343382, 0x3d01000c, 0x4201007d, 0x44010088, 0x46010086, 0x480100ac, + 0x49245782, 0x4b0100ba, 0x4c247382, 0x4e0100c4, 0x52205f82, 0x553c2b82, 0x59010076, 0x5a010018, 0x5c01005b, 0x5d010045, 0x5f0100b8, 0x6301002e, + 0x670100dc, 0x50085382, 0x01004069, 0x01005f6b, 0x01006471, 0x01007c76, 0x0100e279, 0x0100607d, 0x01005181, 0x01008d84, 0x0100f086, 0x0100268a, + 0x0100d28d, 0x01005392, 0x01002097, 0x0100ce9b, 0x0100099e, 0x0100f7a3, 0x01003ba6, 0x01009aa9, 0x010035ac, 0x010042b1, 0x345382b5, 0x0100c5b9, + 0x010003bc, 0x0100f4be, 0x010030c1, 0x010057c2, 0x084b82c3, 0x00eac630, 0x00d4c801, 0x0081cb01, 0x00d7cc01, 0x0038cf01, 0x00b1d101, 0x009dd401, + 0x00b5d601, 0x0056da01, 0x008cdb01, 0x0097e101, 0x002ae601, 0xdb82ea01, 0x00f9ee2c, 0x00dff301, 0x0062f701, 0x1b82fb01, 0xe0ff5808, 0xd6030200, + 0x79070200, 0x800b0200, 0x14110200, 0xa0130200, 0x24170200, 0xab190200, 0x031d0200, 0xa1200200, 0x6a220200, 0x48250200, 0xac2a0200, 0x3d2d0200, + 0xf12f0200, 0x5f320200, 0x5a350200, 0xb6390200, 0x9a3b0200, 0x203d0200, 0xd33f0200, 0x81410200, 0x82450200, 0x47500847, 0x490200bb, 0x4b0200c7, + 0x4c02001b, 0x540200ec, 0x570200db, 0x5b02004f, 0x5e02009b, 0x630200cf, 0x66020030, 0x6802002d, 0x6a0200a3, 0x6c0200ad, 0x6e0200ce, 0x70020091, + 0x730200ba, 0x7502004e, 0x78020075, 0x7b02005e, 0x7d02002b, 0x800200ee, 0x54087f82, 0x0200b982, 0x02009d85, 0x02006888, 0x0200df89, 0x0200ed8f, + 0x02003597, 0x0200a299, 0x0200669c, 0x0200419f, 0x02008fa2, 0x020082a4, 0x020067ab, 0x02004cac, 0x02009fae, 0x0200cab0, 0x020038b2, 0x0200b3b5, + 0x020006b8, 0x0200c2b9, 0x020013bb, 0x0200b1bc, 0x3c0382be, 0x020050c2, 0x0200f5c3, 0x0200e6c5, 0x020095c9, 0x020028cc, 0x020011cd, 0x02008ad0, + 0x2c9b82d4, 0x020085d7, 0x02003cdc, 0x02002ee0, 0x202782e6, 0x281782e7, 0x02006ceb, 0x0200dcec, 0x08eb82ef, 0x005ff368, 0x0012f802, 0x00e5fc02, + 0x006c0003, 0x00610503, 0x00170803, 0x00d50a03, 0x00ee0d03, 0x00b71103, 0x00351403, 0x002c1603, 0x00f41803, 0x00d41b03, 0x00551e03, 0x003d2103, + 0x00e82403, 0x003b2803, 0x00592c03, 0x008b3003, 0x00ba3203, 0x00303703, 0x00283903, 0x004a3d03, 0x00703f03, 0x00084303, 0x00664703, 0x43824b03, + 0x63824d20, 0x8e502c08, 0x0c550300, 0x40590300, 0x0b5f0300, 0x4d630300, 0xd2650300, 0x6e680300, 0x7d6b0300, 0xf66d0300, 0x36720300, 0x04750300, + 0x82770300, 0xdf793837, 0xfa7b0300, 0x7b7e0300, 0x67810300, 0xaa830300, 0x09850300, 0x82870300, 0x2b8a2873, 0x158d0300, 0x82900300, 0xdd923c3b, + 0x19940300, 0x3c960300, 0x5d980300, 0x4e9c0300, 0x5ba00300, 0xd7a40300, 0x82a70300, 0x8dab2853, 0x31ad0300, 0x82af0300, 0xb12008af, 0xb30300bb, + 0xb6030093, 0xb7030016, 0xbb0300fc, 0xbe0300a0, 0xc3030050, 0xc40300bd, 0xc60300a2, 0x24089382, 0x030038c7, 0x03004cc9, 0x030002cc, 0x030043ce, + 0x030037d1, 0x030012d3, 0x030025d4, 0x03004bd6, 0x030049db, 0x24a382de, 0x03001de1, 0x309382e2, 0x030024e5, 0x0300dbe7, 0x030023ea, 0x030068ec, + 0x08ab82f0, 0x00d1f368, 0x0087f703, 0x00dbfa03, 0x00280004, 0x00e00304, 0x00c70804, 0x00b30a04, 0x00e20f04, 0x00781504, 0x001c1704, 0x006a1b04, + 0x00651d04, 0x00921f04, 0x005f2104, 0x00b62304, 0x00202604, 0x00d32704, 0x000d2904, 0x00602c04, 0x00482d04, 0x00a12e04, 0x00f72f04, 0x00123104, + 0x00a33204, 0x00793304, 0x007a3704, 0x5b823804, 0x00393108, 0xbc390400, 0x753a0400, 0xe93b0400, 0xbb3d0400, 0x1e3f0400, 0xc2400400, 0xd9420400, + 0x76470400, 0x5a490400, 0x464a0400, 0xda4b0400, 0x064e0400, 0x33080382, 0x500400f8, 0x52040089, 0x550400f4, 0x560400b2, 0x5704008b, 0x590400ee, + 0x5a040051, 0x5c040040, 0x60040033, 0x6104003a, 0x640400cc, 0x6504003d, 0x66040023, 0x68203382, 0x69349f82, 0x6b040070, 0x6c040001, 0x6d040013, + 0x6e04006d, 0x6f0400ca, 0x21087382, 0x04005e72, 0x04000e75, 0x0400ab76, 0x04004778, 0x0400e479, 0x0400817b, 0x0400ed7d, 0x04000480, 0x03821882, + 0x0400e728, 0x0400c484, 0x03824285, 0x86249f82, 0x880400d8, 0x8c291f82, 0x8d0400d6, 0x8f0400dd, 0x28038205, 0x900400d7, 0x9104009b, 0x8203827e, + 0x8292209f, 0x8293205f, 0xf0942423, 0x82950400, 0x962408cf, 0x970400a2, 0x9804006a, 0x99040098, 0x9a04005f, 0x9c0400ea, 0x9d040001, 0x9e040022, + 0xa1040097, 0xa20400be, 0xa3245782, 0xa40400de, 0xa52c6f82, 0xa60400f1, 0xa70400ff, 0xa90400e9, 0xab200382, 0xac300382, 0xad040052, 0xaf04007a, + 0xb10400d3, 0xb30400b7, 0xb520b782, 0xb8381382, 0xb904005b, 0xbb040084, 0xbe040032, 0xc0040089, 0xc10400ad, 0xc204009e, 0xc32de782, 0xc3040035, + 0xc60400fd, 0xc8040053, 0x08038225, 0x0400992b, 0x04007dc9, 0x040013cb, 0x0400a7cc, 0x040073ce, 0x04001ed0, 0x0400a9d1, 0x040083da, 0x0400a5dc, + 0x0400b0dd, 0x04006bdf, 0x208782e0, 0x28bf82e2, 0x0400a4e4, 0x04008be7, 0x245382e9, 0x040074eb, 0x24cb82ec, 0x040042ee, 0x207b82ef, 0x204f82f0, + 0x2c4382f2, 0x040019f4, 0x0400d1f5, 0x04009af9, 0x088b82fc, 0x0070ff38, 0x00600205, 0x00460505, 0x00b10605, 0x00220805, 0x00930905, 0x00080b05, + 0x00120f05, 0x000c1105, 0x006e1405, 0x006a1505, 0x00641605, 0x00991905, 0x00511c05, 0x13821f05, 0x3b822020, 0x00c6213c, 0x00552405, 0x00482505, + 0x002f2705, 0x009d2805, 0x000b2905, 0x00402a05, 0x47822c05, 0x00ee2f29, 0x00a13205, 0x824a3405, 0x00f22b03, 0x00c93505, 0x00983705, 0x37823805, + 0x00943929, 0x00623a05, 0x82303b05, 0x00fe2b03, 0x008c3c05, 0x00ae3d05, 0x3b823e05, 0x00d33e2c, 0x00e43f05, 0x00754105, 0x0b824405, 0x00f44524, + 0x57824805, 0x5f4a4c08, 0xf84b0500, 0x354e0500, 0x37500500, 0x13520500, 0xeb530500, 0xc7560500, 0x53590500, 0x475a0500, 0xd65b0500, 0xe75c0500, + 0x7b5f0500, 0x1f620500, 0xc0630500, 0x33660500, 0x63680500, 0xa2690500, 0xde6a0500, 0x736c0500, 0x826e0500, 0xaf6f24e3, 0x82710500, 0x1c722437, + 0x82720500, 0xad73286f, 0x76740500, 0x82750500, 0x752408cb, 0x760500ff, 0x780500d0, 0x79050052, 0x7c0500dc, 0x7d0500c5, 0x7f050027, 0x8105003c, + 0x8205003d, 0x840500cb, 0x8a201382, 0x4008a382, 0x05000c8f, 0x05003690, 0x05002e92, 0x0500a893, 0x05006494, 0x0500d495, 0x0500ab98, 0x0500e89b, + 0x0500029d, 0x0500939f, 0x050024a2, 0x050005a3, 0x05009fa5, 0x050065a7, 0x05002baa, 0x05001dab, 0x241f82ac, 0x0500daae, 0x2ccf82b1, 0x050042b2, + 0x050071b3, 0x0500a0b4, 0x20fb82b5, 0x204f82b8, 0x242382ba, 0x0500e0bb, 0x242782bd, 0x050023be, 0x34f382c0, 0x050000c2, 0x05004ac3, 0x050020c4, + 0x050061c5, 0x0500a6c6, 0x089382c7, 0x0051c930, 0x00b0ca05, 0x0079cc05, 0x00f0cd05, 0x001acf05, 0x002ad005, 0x006cd105, 0x009bd305, 0x0085d505, + 0x0039da05, 0x00f5db05, 0x0054dd05, 0xdb82df05, 0x60e02008, 0x19e20500, 0x1be50500, 0x2ce80500, 0xeeea0500, 0xaaed0500, 0xdef00500, 0x06f40500, + 0x82f60500, 0xf82d08b7, 0xf905004e, 0xfa050041, 0xfb050034, 0xfc050025, 0xfe050016, 0xff050021, 0x020600de, 0x03060047, 0x04060024, 0x07060038, + 0x090600f7, 0x3f038236, 0x0c0600d7, 0x0e06005c, 0x100600c8, 0x120600aa, 0x1406001b, 0x1606004f, 0x1a0600c6, 0x1d06006c, 0x203c0b82, 0x22060062, + 0x25060003, 0x26060016, 0x29060032, 0x2c060070, 0x2f0600dd, 0x31060006, 0x3c082382, 0x0600e232, 0x0600a534, 0x06003937, 0x06004b39, 0x06002a3b, + 0x0600833c, 0x06007e3e, 0x0600ed3f, 0x06000943, 0x06005544, 0x06008046, 0x0600184b, 0x0600444c, 0x0600b64d, 0x0600af4f, 0x30178251, 0x06003752, + 0x06000556, 0x06007957, 0x06007359, 0x2457825c, 0x0600ca5d, 0x082b8264, 0x00b36524, 0x00c96606, 0x007d6906, 0x00ef6b06, 0x00077006, 0x00537206, + 0x00787306, 0x009b7506, 0x00757706, 0x7f827806, 0x00107d31, 0x008f7e06, 0x00df7f06, 0x005f8106, 0x824d8206, 0x00d63303, 0x00898606, 0x00658906, + 0x00918c06, 0x00028e06, 0xcb829006, 0x00e89224, 0x8b829306, 0x00779728, 0x00ae9a06, 0xeb829e06, 0x00c2a23c, 0x0064a406, 0x00d8a506, 0x00d5a706, + 0x0040aa06, 0x0074ac06, 0x0017b006, 0xaf82b306, 0x00b1b635, 0x002fba06, 0x0075bc06, 0x004bbe06, 0x0030c006, 0x8235c106, 0x00f93703, 0x0053c406, + 0x00f4c506, 0x0014c806, 0x0043c906, 0x00faca06, 0x9f82cd06, 0x94ce2108, 0xb0cf0600, 0xccd00600, 0xe6d10600, 0xf3d20600, 0x08d40600, 0xfbd50600, + 0xa9d80600, 0x05dc0600, 0xd42b0382, 0xaadd0600, 0x6ae00600, 0x82e20600, 0xe320081b, 0xe50600f1, 0xe7060095, 0xe8060077, 0xeb0600ff, 0xed060016, + 0xee06005a, 0xf10600a1, 0xf40600ee, 0xf824cf82, 0xf9060027, 0xfb351b82, 0xfc06009e, 0xfe060085, 0xff060037, 0x01070084, 0x03070095, 0x08038227, + 0x0700eca3, 0x07005205, 0x0700f006, 0x0700d207, 0x07007a08, 0x0700b109, 0x07007f0a, 0x0700000c, 0x07006b0e, 0x07003511, 0x07006814, 0x07008116, + 0x0700b91a, 0x07003722, 0x07007426, 0x0700132b, 0x0700eb2e, 0x0700b733, 0x0700ab36, 0x07003c38, 0x0700ff3b, 0x0700fa3d, 0x0700dd3f, 0x07004142, + 0x07006943, 0x07000345, 0x07007947, 0x07006549, 0x0700514b, 0x0700474d, 0x07003d4f, 0x0700e450, 0x07002d55, 0x07009957, 0x0700c75a, 0x07009b5b, + 0x0700015c, 0x07007b5d, 0x0700145f, 0x07006a62, 0x07005769, 0x084b826a, 0x005a6f20, 0x00d97007, 0x001d7307, 0x00667507, 0x00057707, 0x00c37807, + 0x00777a07, 0x00f77b07, 0x23827e07, 0x00588124, 0x17828307, 0x97828420, 0x009a8528, 0x00838607, 0x43828707, 0x005b883c, 0x004e8907, 0x00268b07, + 0x00628e07, 0x00d78f07, 0x00309107, 0x00769207, 0xb7829307, 0x00e09434, 0x00169607, 0x004a9707, 0x00149907, 0x00a19a07, 0xb7829c07, 0x53829e20, + 0x1aa04808, 0xc8a20700, 0xb3a30700, 0x79a40700, 0x86a50700, 0x96a60700, 0x99a70700, 0x84a80700, 0xeaaa0700, 0xccab0700, 0xa7ac0700, 0x95ad0700, + 0x70af0700, 0xa0b10700, 0xd6b20700, 0xc4b30700, 0xe7b40700, 0xcdb50700, 0x82b60700, 0x73b7281f, 0x48b80700, 0x82b90700, 0xbc49086f, 0xbe07000d, + 0xc0070037, 0xc407006e, 0xc8070093, 0xc907006c, 0xce0700ef, 0xd00700b8, 0xd10700a2, 0xd307008d, 0xd507003f, 0xd607005e, 0xd90700f1, 0xdb07007b, + 0xdd07000a, 0xe0070020, 0xe30700ac, 0xe407005f, 0xe607000b, 0x300382af, 0xe90700c0, 0xec070024, 0xf00700a5, 0xf30700fc, 0x08038206, 0x0700c12f, + 0x0700a7f5, 0x070042f7, 0x07004bf8, 0x070052fa, 0x07005afc, 0x0800f5fe, 0x08003d03, 0x0800a106, 0x08001b09, 0x0800420b, 0x0800dc0c, 0x080f820e, + 0x00071028, 0x003a1108, 0x000f1308, 0x00d71408, 0x00cb1508, 0x00801708, 0x00cd1808, 0x004c1a08, 0x002e1d08, 0x00152008, 0x07822308, 0x0051262c, + 0x00612808, 0x00752a08, 0x2b822b08, 0x2c2d2008, 0x992e0800, 0x64300800, 0x05340800, 0xfa350800, 0x14380800, 0xf6390800, 0x583b0800, 0x82400800, + 0x20432823, 0x6b440800, 0x82460800, 0x824a2053, 0x294c3427, 0xc54e0800, 0x0c510800, 0xf9530800, 0x57560800, 0x825b0800, 0x5e280893, 0x6008002b, + 0x6208000e, 0x630800e6, 0x640800ad, 0x670800eb, 0x6808004d, 0x6a08008c, 0x6d0800b0, 0x6f08008b, 0x70080025, 0x71385782, 0x750800db, 0x76080052, + 0x780800ff, 0x7e0800d9, 0x8008001a, 0x82080034, 0x84384782, 0x8608001c, 0x87080053, 0x8908008e, 0x8b080019, 0x8c080007, 0x8e080082, 0x8f24eb82, + 0x960800b5, 0x993c8b82, 0x9c08007e, 0x9e080091, 0xa008009a, 0xa5080088, 0xa608005b, 0xa70800df, 0xa90800bc, 0xab3c0b82, 0xb0080042, 0xb20800de, + 0xb40800a2, 0xb608007c, 0xba080085, 0xbc080086, 0xbe0800d4, 0xbf24bb82, 0xc2080095, 0xc3302382, 0xc50800d0, 0xc6080001, 0xc708002a, 0xc808002d, + 0x2c085382, 0x0800f6c9, 0x08007bcc, 0x080094ce, 0x0800a6d2, 0x080004d4, 0x080024d6, 0x08004fd8, 0x080083da, 0x0800e8db, 0x0800c2de, 0x080040e2, + 0x08ef82e4, 0x0049e650, 0x00eee708, 0x00e7ec08, 0x00a7ee08, 0x004ef108, 0x005ef208, 0x00b4f308, 0x00bbf608, 0x0010f908, 0x00ecfa08, 0x00c4fc08, + 0x0035fe08, 0x0073ff08, 0x00f50209, 0x00060409, 0x00ef0509, 0x00e60709, 0x008d0a09, 0x00f30c09, 0x003f0e09, 0x1f820f09, 0xb3173c08, 0xa8190900, + 0x7a1b0900, 0xc71e0900, 0xf71f0900, 0x50230900, 0x53240900, 0x2b270900, 0x182c0900, 0xe72d0900, 0xa6300900, 0x3b330900, 0x5e340900, 0x5f360900, + 0x133a0900, 0x823b0900, 0x3d5c0833, 0x3e09000e, 0x41090030, 0x43090016, 0x440900cb, 0x480900e3, 0x4b0900a7, 0x4f0900db, 0x5209005a, 0x54090060, + 0x5509008c, 0x590900e4, 0x5a09001a, 0x5c0900a4, 0x5d090038, 0x600900c9, 0x63090002, 0x660900f2, 0x69090061, 0x6b090088, 0x6c090018, 0x6f0900de, + 0x75090039, 0x7709006b, 0x79281782, 0x7b0900aa, 0x7c090082, 0x28080f82, 0x09003180, 0x0900bc83, 0x0900b788, 0x0900b18a, 0x09007c8c, 0x0900488e, + 0x09002c93, 0x09007d99, 0x09001b9c, 0x0900859e, 0x283782a4, 0x090064a8, 0x090091b0, 0x2c0b82b3, 0x0900d6b6, 0x090051ba, 0x090069bc, 0x285f82be, + 0x090052c1, 0x090009c3, 0x249f82c5, 0x09003cc7, 0x086382cb, 0x0058cf50, 0x0080d209, 0x0026d809, 0x00e5e009, 0x0042e809, 0x00d4e909, 0x0082ee09, + 0x00b6f009, 0x0095f209, 0x00d6f409, 0x000df709, 0x009ef909, 0x0040fb09, 0x00affd09, 0x00d4fe09, 0x0032010a, 0x0099020a, 0x000b040a, 0x0058050a, + 0x002a080a, 0x0f82090a, 0x17820b20, 0x180e3008, 0xbf100a00, 0x91120a00, 0xa3140a00, 0x77170a00, 0x98190a00, 0x6f1b0a00, 0xc31e0a00, 0xf1230a00, + 0x1e260a00, 0xfa270a00, 0x372a0a00, 0x822d0a00, 0x2e28081f, 0x300a00ff, 0x330a00ee, 0x340a0007, 0x360a008f, 0x390a0020, 0x3d0a00db, 0x3f0a0088, + 0x420a008a, 0x450a009e, 0x470a0016, 0x48285b82, 0x4a0a00eb, 0x4b0a003b, 0x513c1f82, 0x520a0062, 0x570a0042, 0x590a008d, 0x5b0a00e1, 0x5d0a0026, + 0x600a00cb, 0x620a0092, 0x67380382, 0x6a0a0048, 0x6d0a0029, 0x6f0a004b, 0x710a004e, 0x740a00c5, 0x760a0009, 0x78382f82, 0x7b0a00b8, 0x7d0a0096, + 0x7e0a009f, 0x800a00fd, 0x820a00af, 0x840a0039, 0x86282b82, 0x890a00ce, 0x8a0a0083, 0x8b2c0382, 0x8f0a00b2, 0x930a006e, 0x980a008e, 0x9a3c1782, + 0xa20a005a, 0xa40a005f, 0xa70a00ff, 0xa90a009a, 0xaa0a000d, 0xad0a00e7, 0xb20a0012, 0xb6380f82, 0xba0a0015, 0xbb0a00ca, 0xc20a00ab, 0xc50a00a4, + 0xc60a0049, 0xc70a002e, 0xcc24c782, 0xcf0a00aa, 0xd134db82, 0xd40a004f, 0xd90a0036, 0xdf0a007f, 0xe30a00cf, 0xe90a00df, 0xeb2c5782, 0xed0a0024, + 0xf10a0010, 0xf40a00bf, 0x64081782, 0x0b005df9, 0x0b008b00, 0x0b00f801, 0x0b00a803, 0x0b004605, 0x0b00e306, 0x0b009908, 0x0b00c90b, 0x0b004f0f, + 0x0b00c112, 0x0b00ba14, 0x0b00b816, 0x0b005519, 0x0b00b71b, 0x0b00361e, 0x0b003b21, 0x0b003a25, 0x0b00af26, 0x0b00cf2c, 0x0b00122f, 0x0b008630, + 0x0b009d33, 0x0b007537, 0x0b00b938, 0x0b00d53a, 0x084f823c, 0x00423f24, 0x0091420b, 0x0076460b, 0x00784b0b, 0x009c4d0b, 0x000f500b, 0x00d8520b, + 0x0011550b, 0x00315c0b, 0x6b82600b, 0x0061633c, 0x0068650b, 0x00ef670b, 0x00016e0b, 0x0038700b, 0x00f0730b, 0x0067790b, 0x77827c0b, 0xaf827e20, + 0x00838128, 0x002d830b, 0x6f82840b, 0x00ed853c, 0x00238c0b, 0x00928d0b, 0x0013910b, 0x0025920b, 0x00f5940b, 0x0096950b, 0xcb829b0b, 0x0b829d20, + 0x0002a324, 0x5382a50b, 0x3382a720, 0x0021ac24, 0x9b82ae0b, 0x00baaf3c, 0x00e8b30b, 0x0058b80b, 0x003eba0b, 0x00d3bd0b, 0x0032c40b, 0x0071c90b, + 0x6382cd0b, 0x00a1ce28, 0x008ed00b, 0x6b82d30b, 0xd0d62808, 0x3ada0b00, 0xe4dc0b00, 0xabe10b00, 0xe9e30b00, 0x95e60b00, 0x41e90b00, 0xd1eb0b00, + 0x15ee0b00, 0x0df10b00, 0x82f20b00, 0x82f9204f, 0xfc7c08df, 0xfe0b004c, 0x040c00a3, 0x070c00b0, 0x080c003c, 0x090c0089, 0x0d0c00d8, 0x0e0c0018, + 0x130c00f1, 0x180c009d, 0x190c0003, 0x1d0c00ce, 0x1e0c00d1, 0x220c00d2, 0x250c00f7, 0x260c00de, 0x2c0c0099, 0x2d0c00b8, 0x2e0c0087, 0x300c0055, + 0x320c00e9, 0x370c00bb, 0x3a0c00ff, 0x3b0c0052, 0x3c0c0060, 0x3d0c00b3, 0x400c00ed, 0x420c002b, 0x450c007f, 0x490c0079, 0x4c0c007b, 0x4e0c003b, + 0x28080782, 0x0c00fc4e, 0x0c000750, 0x0c00f653, 0x0c00e757, 0x0c00aa5b, 0x0c00705d, 0x0c008f63, 0x0c00bd67, 0x0c00c06c, 0x0c00c870, 0x247f8271, + 0x0c00cf73, 0x242f8276, 0x0c00f979, 0x259b827a, 0x0c00767d, 0x0382397f, 0x0c00c323, 0x206b8280, 0x38738282, 0x0c002684, 0x0c00fa85, 0x0c000b88, + 0x0c00dd8a, 0x0c00cd8b, 0x0c00168d, 0x24938292, 0x0c008e94, 0x24378295, 0x0c009498, 0x301f829d, 0x0c00979f, 0x0c0021a1, 0x0c006fa2, 0x0c0008a4, + 0x30c382a6, 0x0c00eaaa, 0x0c00a2ae, 0x0c0093af, 0x0c00abb1, 0x240382b3, 0x0c0034b6, 0x381b82b7, 0x0c005fba, 0x0c000ebb, 0x0c00f3c2, 0x0c002ec6, + 0x0c004fc9, 0x0c002fcb, 0x084382cf, 0x004bd028, 0x00ded10c, 0x00eed50c, 0x0001d80c, 0x002ddb0c, 0x0059de0c, 0x0012e10c, 0x00c6e30c, 0x0002e70c, + 0x003eea0c, 0x1382ed0c, 0x8b82ee20, 0x0098f025, 0x823df20c, 0x081b8203, 0x007cf522, 0x00fef60c, 0x00a5f90c, 0xfb80fb0c, 0xf8e4f730, 0xb4fb1554, + 0xe5ffff06, 0xff8b717d, 0x8f82eaff, 0x90200483, 0xe5260a82, 0xfc08707d, 0x09830734, 0xff008026, 0x717d1500, 0x09831982, 0x8f821a25, 0x82f7088b, + 0x1a002233, 0x82288282, 0x83702019, 0x8b70221e, 0x211083ff, 0x3383f808, 0x2e860983, 0x707d1522, 0x802d5d82, 0xff088b00, 0x0080c9ff, 0xffff154b, + 0x244682a6, 0x33b379ff, 0x2a0a8505, 0xcd4c8600, 0x0647f705, 0x8326ffff, 0x4cc62618, 0x00ff15cc, 0x20238559, 0x82238634, 0x260a822e, 0x98990c01, + 0x8300ff07, 0xb9fe2326, 0x268634b3, 0xcc213f82, 0x20318a05, 0x214a82fb, 0x3f82d900, 0x83390021, 0x8a6e8423, 0x2c0a8523, 0x6866f3fe, 0xf0fb0e07, + 0xcb30fc0e, 0x224882eb, 0x82a4b011, 0x4f0e27c0, 0x0e00ff5c, 0x0a82ec51, 0xaec71029, 0x0001ff08, 0x8207d6e3, 0xab11270c, 0xf1ffff86, 0x1c82a4b0, + 0xff0a5726, 0x5c4feeff, 0x0683ce83, 0xff241685, 0x8bf6a8f1, 0x54271782, 0xffff087a, 0x8266e600, 0xedff2333, 0x2e82f668, 0xff255082, 0xff34b3f1, + 0x22608300, 0x825b8b08, 0xe8e921fe, 0x17202b84, 0x17214883, 0x8236820a, 0x85082010, 0x21268206, 0x4782f6e8, 0xff70fd24, 0x1b821600, 0x06850820, + 0x00231685, 0x8266e611, 0x3315228b, 0x202d8234, 0x82068200, 0x25448228, 0xcccc1200, 0x4382ffff, 0x0e088b2a, 0xff34f82f, 0x66e64001, 0xc5336582, + 0xff061ec5, 0xfcc90900, 0xbd3a00ff, 0x00ff0572, 0x82f0e702, 0xa4702b47, 0x38f4ffff, 0x1000ff10, 0x3f82e07a, 0x99829320, 0xf6e80222, 0xee22b582, + 0x23825278, 0xff00e026, 0x289cefff, 0x3b262382, 0xfdffffe8, 0x23820c17, 0x824c9721, 0x78f42d1e, 0xbaffff92, 0xff05e0ba, 0x67e6a0ff, 0x332059a3, + 0x59904e82, 0x59882920, 0x59880a20, 0x87e57021, 0x19bb2359, 0x1682069a, 0x8b7b5427, 0xabf1ffff, 0x20048385, 0x06564186, 0xed2c0682, 0x00ff6666, + 0xff7b540e, 0x9a99f2ff, 0xab23ca82, 0x82088b85, 0xe13a21dc, 0xea243382, 0x14fb85ab, 0x419d9b82, 0x7a54ee22, 0x91214187, 0x27418eec, 0xff0436f6, + 0x9042c5ff, 0xfd224482, 0x85821018, 0xff5c8f2b, 0xf0c70b00, 0x85efffff, 0x262b8220, 0xffffcd6c, 0x820817fd, 0xc2012271, 0x250a824e, 0x00ffbade, + 0x1482cc01, 0x82e6ff21, 0xb3012296, 0x268c8333, 0x8b295c0f, 0x840d00ff, 0x0a172c3a, 0x9c0200ff, 0x0f00ff29, 0x8208d8a3, 0x3d8a2c4a, 0x454500ff, + 0x00ff051e, 0x82b91e5f, 0x2070a0b2, 0x267088cc, 0xffff8ccc, 0x8386abff, 0x86148270, 0x85342070, 0x84282070, 0x825e2070, 0x20708560, 0x20708928, + 0x2370873e, 0x0614ee44, 0xab21c282, 0x202b8286, 0x0503410e, 0x0a827a20, 0x20c51023, 0x08dc4208, 0x1b835e83, 0x54eeff23, 0x2059827a, 0x053f42ff, + 0x7a541524, 0xb28214f7, 0x68e64422, 0x2443418e, 0x23418208, 0xff008013, 0x2705e542, 0xff32330f, 0xcc4ceeff, 0x64254183, 0x54fb66e6, 0x072f4215, + 0xcd4c1522, 0x5f224984, 0xfc82b81e, 0x14aeea2b, 0x0e0514fb, 0x34f770fb, 0x232382f8, 0x33b31100, 0x0e224782, 0xf341cd4c, 0xffff250b, 0x07ec51dc, + 0x9921f582, 0x21ff829a, 0x09823cca, 0xff226883, 0x098220c5, 0x82999921, 0x1ec52513, 0x0a00ff08, 0xfe251e83, 0x00ff866b, 0x2814831f, 0x98f6e8fa, + 0xb5fcffff, 0x2c1a82c2, 0xff343310, 0xf6a8fbff, 0x4c0b00ff, 0x209882cc, 0x2004828c, 0x232e83fb, 0x0866e6ee, 0xb3201982, 0xee221e82, 0x198268e6, + 0xf5213983, 0x27388299, 0xffcdccee, 0xce4c0400, 0xf6251e82, 0x00ff33b3, 0x20388303, 0x240984e3, 0xffffcecc, 0x221e83f4, 0x82989901, 0xe6df221e, + 0x83298266, 0x83e42014, 0x83fd2096, 0x19ed2157, 0xf822aa82, 0x1e82cccc, 0x51b8ed2b, 0xf8ffff84, 0xfffff668, 0x221583f6, 0x8270fdfd, 0x2577843e, + 0xff5c0ffe, 0x5882f5ff, 0x78010026, 0xf9ffff52, 0x00238182, 0x8290c201, 0x323321b5, 0x0123b582, 0x8287d7e3, 0xa4b02178, 0x5982a182, 0x59070022, + 0xfb225482, 0x1a829a19, 0x82421021, 0x4cf52125, 0x1820a282, 0xff218882, 0x270482f8, 0x33332000, 0x4cf7ffff, 0x00217382, 0x290f8202, 0x3433ffff, + 0x1c00ff05, 0x7d826766, 0x22216383, 0x20f582cc, 0x204883f6, 0x84ac8319, 0x0e0022fa, 0x20eb8219, 0x22b282f6, 0x824c0d00, 0x82f320d6, 0x08002804, + 0xffff3233, 0x826666ee, 0x82082067, 0xeeff210f, 0x00240f82, 0x77cccc01, 0x34269883, 0x99ebffff, 0xd282089a, 0x9a19d922, 0xe620c982, 0xff213b82, + 0x215f82e0, 0xee84f2ff, 0x6f83f220, 0x6666fa23, 0x242c827c, 0xffff6866, 0x209583f0, 0x25cf83fe, 0x9a99deff, 0x59828b07, 0xf1212c83, 0x21ac82b3, + 0x4d82b3f1, 0xcd4cee24, 0x1583088b, 0x1b82cd20, 0x00291683, 0x8bcc4c0e, 0xb31100ff, 0x28808234, 0x0766e622, 0x99ffffff, 0x231c8299, 0x8c0080ff, + 0x04820b84, 0x1c823320, 0xccffff28, 0xff058bcd, 0x9541e7ff, 0x25dd8205, 0xffb8ded7, 0xe2820a00, 0xeee4ff24, 0x55829714, 0x9ad9ef26, 0x330700ff, + 0xf8276682, 0x00ffe1ba, 0x8266e612, 0x152e240e, 0x831000ff, 0x07002140, 0x19210a84, 0x21198298, 0x1982f6e8, 0x0026ed82, 0xff00400f, 0xcb83f8ff, + 0xcc150026, 0xf6ffffcd, 0x0021a482, 0x20d58322, 0x203d83f6, 0x28048213, 0x66e6fcff, 0xffffab08, 0x285882fb, 0xcd4c1a00, 0xcc0200ff, 0x82b182cc, + 0x826c832e, 0x821020b6, 0x06002125, 0xb3226d84, 0x1f829533, 0x82343321, 0x0100218e, 0x0a201183, 0xff265082, 0xff9a99fe, 0x79820600, 0x33feff28, + 0x0300ff33, 0xad82cecc, 0x9919fe26, 0xfcffff8f, 0x04205083, 0xf820c483, 0x0420d883, 0xff226b82, 0x3482efff, 0x39840020, 0x2f83e720, 0x32330725, + 0x83dfffff, 0xb308226f, 0x20398234, 0x281483fd, 0x05cccc00, 0x99e3ffff, 0x82c98299, 0xddff262e, 0x00ff142e, 0x20488309, 0x220983e6, 0x82991911, + 0xe3f12229, 0x831482d7, 0xc7f225ce, 0x0c00ffae, 0xff236282, 0x823dcaf7, 0x839920bd, 0xabf7221e, 0x28c88585, 0xa430feff, 0x001400ff, 0x269c8201, + 0x00ffb8de, 0x82cc4c15, 0x140725d7, 0x2600ff7b, 0x1c2cc583, 0x00ff1f05, 0xff5ccf18, 0xf6e82000, 0x8f214782, 0x201e825c, 0x2614830d, 0xff52f804, + 0x821e0e00, 0x45032233, 0x26098220, 0x00ff67e6, 0x828ec201, 0xba22221e, 0x074547e2, 0x830e0021, 0x540e22e5, 0x2d6d827a, 0x088b33b3, 0xfb0e078b, + 0x7601ff30, 0x04829a99, 0x15289c25, 0x82f3ffff, 0x0c0021b8, 0xff240482, 0x8b00c0eb, 0x14830f85, 0xd4fb0825, 0x8905d4fb, 0x821a820f, 0x83818220, + 0x8234822a, 0x47062a67, 0xf9ffffae, 0x00ff72bd, 0x21f88208, 0xaf83fcff, 0xa4300823, 0x831a828b, 0x83168206, 0x200327db, 0x0600ff00, 0x0482713d, + 0x08004025, 0x82f7d4f7, 0x0c002355, 0x4a82e27a, 0x8b668627, 0x351400ff, 0x308589c2, 0xc9feff08, 0xffff6666, 0x15d86389, 0x4c2300ff, 0x272082cd, + 0xff33b31c, 0x52b81c00, 0x23230a82, 0x8508ae47, 0xffff2206, 0x21d983e3, 0x3c82b51c, 0xd983dc20, 0x83ffff21, 0x23168506, 0xae47e3ff, 0xdc22af82, + 0x2d82e2ba, 0x0682ff20, 0x44823f82, 0x45e3ff23, 0x2454851e, 0xfb94f708, 0x22fc8214, 0x8234b3dc, 0x4ce32227, 0x853782cc, 0x52b82132, 0xb8213284, + 0x20328352, 0x83168434, 0x83cc2032, 0x4c2322d4, 0x227c82cc, 0x9534b31c, 0x84cc208e, 0x2a878316, 0x0e088b34, 0xa101ff2f, 0x82db9a19, 0x10fa2764, + 0xf5ffff20, 0x0482e2ba, 0xff3c3f24, 0x8482faff, 0xf0f4ff23, 0x235182a4, 0xf893faff, 0xfa277f82, 0x00ff8280, 0x82006001, 0x82f3201b, 0xe702345b, + 0xffff08f0, 0xffb89e8a, 0xaa514400, 0x77ffff05, 0x47076666, 0xa7470597, 0xffff2409, 0x83e13aef, 0x82068342, 0xb9de220c, 0x0cd043ff, 0x9a998826, + 0x89ffff07, 0xbb22f583, 0x4482c2b5, 0x52f8fa27, 0x17fdffff, 0x2064820a, 0x22698280, 0x829a99fe, 0x7b942109, 0x8c834283, 0x40269c82, 0x0500ff00, + 0x1682e8bb, 0xff5c0f26, 0x18440a00, 0xf7268582, 0x00ff082c, 0x0f824f0f, 0xe73b0527, 0x911300ff, 0x260e82ec, 0x00ff6250, 0x820ad708, 0x61752219, + 0x21a48248, 0x5f82ae47, 0x4c21af85, 0x220a82cc, 0x82a4b0f0, 0xcecc2120, 0xc2214982, 0x8234828f, 0x0700236a, 0x398215ee, 0x2405dc42, 0x00ffae87, + 0x2284820b, 0x82a10c00, 0xcc052c3e, 0x0c00ffcc, 0xffffd763, 0x820080fe, 0x21042553, 0xffffff48, 0x04211e83, 0x83a38219, 0x030023a8, 0xbc820bd7, + 0x82cecc21, 0x47762a1e, 0xbbffffae, 0xff0532b3, 0x25e38300, 0x1100ff8b, 0xfb8284ab, 0x837b5421, 0x487c2004, 0x11220866, 0x1b8285ab, 0x16820e20, + 0xabf1ff29, 0xffff8b84, 0x827c54ee, 0x667727d0, 0x00ff0766, 0x73824c76, 0x3e4a4422, 0x03264482, 0x00ff88d6, 0x04823602, 0xda190431, 0x530100ff, + 0x0400ff74, 0x00ff8a21, 0x82128300, 0x540c216e, 0x01275282, 0x00ff1a8f, 0x8232b30c, 0x343329d0, 0xb30500ff, 0xf4ffff34, 0x0824ac84, 0xfffff8d3, + 0xff28ef83, 0xff18c4fa, 0x146eecff, 0xaf260e82, 0xf7ffff9e, 0xc441f628, 0xbbff2306, 0x678252b8, 0x0a867283, 0xce4c0f22, 0x2e212082, 0x21498214, + 0x34823233, 0xff666624, 0x1383f6ff, 0x34b3f02a, 0xf82f0e08, 0x1554f744, 0x4f22b083, 0xbb82ff5c, 0x04828620, 0x5682ae20, 0x7a54ee2a, 0x24fb088b, + 0x0724fb06, 0x85201c89, 0x8d831c82, 0x7b54ee23, 0x836f828b, 0x05234206, 0x27070c42, 0xf708a4b0, 0x24fb0724, 0x4b0ce849, 0x11200673, 0x8b221c82, + 0x068200ff, 0x21073f41, 0x3f41cd4c, 0x82f72006, 0x8f002330, 0x6a82ffff, 0x51201f8b, 0x4109c649, 0xae210b5f, 0x26918514, 0x70ffff08, 0x84070100, + 0x8211203c, 0x00002396, 0x5a828f02, 0x83068846, 0xcd4c2d23, 0x70fb0e08, 0x34f7b4f7, 0x0694fb15, 0x8205da4b, 0xa4b021b0, 0x2307074c, 0x08a3b011, + 0xa3209384, 0x8205cd4b, 0x84ce20c7, 0x088b22a2, 0x833082f7, 0x06384c8c, 0xb3f1ff23, 0x84768633, 0x415d2006, 0xf122060a, 0x578214ae, 0x8bcc4c22, + 0x342b6984, 0xfd9f01ff, 0xffff1570, 0x8247a1a7, 0x5eb82426, 0x82ffffb8, 0x280a8204, 0x0849a1a7, 0xe680ffff, 0x82e38267, 0xff48251d, 0x48a14700, + 0xff261c84, 0xb95e5800, 0x0683088b, 0x6c82b820, 0x1b831683, 0x58220a82, 0x1682b85e, 0x281c7f22, 0x00233382, 0x82666658, 0x2304822e, 0x0a974700, + 0x992a6082, 0xeb088b9a, 0x02e0feff, 0x5e821590, 0xec11cb27, 0xf0d4ffff, 0x200482a4, 0x229082ee, 0x825c0fcb, 0xcbff2351, 0x1b82eb11, 0x1182d420, + 0x112b0023, 0x255182ec, 0x0814ee34, 0x4e8314f7, 0x2b823420, 0xff291483, 0x5c0f2b00, 0xee3400ff, 0x20308215, 0x82158200, 0x83118325, 0x823b824c, + 0xfb082948, 0xfb0e0714, 0x8b94f7b0, 0xee226883, 0x16447a54, 0x54ee260b, 0xfb088b7b, 0x0eef4154, 0x827a5421, 0xab112345, 0x06850886, 0x20082f43, + 0x06ef417a, 0xff06cb32, 0x34332401, 0xd1ffff07, 0xffff00c0, 0x053233e1, 0x45215482, 0x064c491f, 0x852bec27, 0x190400ff, 0x200e829a, 0x239b822f, + 0x089a990e, 0x33210a82, 0x2b4782f8, 0x00ff32b3, 0xff0af803, 0x66e61300, 0xfe290e83, 0xcc0900ff, 0xcbeb08ce, 0x20088205, 0x362182d3, 0xff088c06, + 0x3b9f0c00, 0xa30000ff, 0x0a00ffd6, 0xffffd763, 0x823268fa, 0x680a2214, 0x250a82f6, 0x00ff9e6f, 0x74828006, 0x6626f522, 0xf426df82, 0xfb08c235, + 0x908207f4, 0xb3110023, 0x21348233, 0x56829002, 0x82cd4c21, 0x34b3218e, 0xee281f82, 0x0e08cc4c, 0xd4f770fb, 0x8620fc8b, 0x43062843, 0x94260523, + 0xf2ffff06, 0x2c8285eb, 0x0040f42c, 0xf30700ff, 0xfbfffff8, 0x85824821, 0x08122322, 0x24210a82, 0x210a8219, 0xb782b81e, 0x1e820020, 0x82e10d21, + 0x73092119, 0x0922a982, 0x9582ae07, 0x9a99c127, 0x19b900ff, 0x25bf829a, 0xff295c1f, 0xfb831e00, 0x0a970231, 0xd43100ff, 0xe3ffff7b, 0x00ffacdc, + 0x82666621, 0x17f12148, 0x11271482, 0xffffa4b0, 0x82cd0ceb, 0x146e2bd9, 0xe3e8ffff, 0x0100ffd7, 0x1e829042, 0x6210e922, 0x2b310a82, 0xe9ffff84, + 0xffff66e6, 0xff16eef7, 0xe13aefff, 0x281a827b, 0xff71fddc, 0x3233e0ff, 0x24a88405, 0x17f4ffff, 0x2044820c, 0x228d82c0, 0x821e0501, 0x22ac830e, + 0x82de0f0d, 0x1df43129, 0x0d00fff4, 0x00ff2c07, 0xff10f800, 0xcc4c1400, 0x12310e82, 0x0b00fff2, 0xff0868e6, 0x33732200, 0x4c1f00ff, 0x3cac82cc, + 0xff85ab1c, 0x0a571b00, 0xb82700ff, 0x0e00ff52, 0x00ff1ec5, 0xff908228, 0x20c5fdff, 0x200a8208, 0x30bc8254, 0xffe0cffd, 0x5c0f2600, 0x07edffff, + 0x1a00ff2a, 0x221e8202, 0x824821e1, 0x3120081e, 0xffffcccc, 0xff32f3c4, 0x6866fbff, 0xc0a7ffff, 0xc8ffff01, 0xffff9959, 0x08ff7fca, 0x16fb1cfb, + 0xb02d6182, 0xff065138, 0x34b31100, 0xf3ffffff, 0x08d84334, 0x250c9541, 0xff8b15f3, 0xc483b5ff, 0xe2fac224, 0x0484ffff, 0x8b200e82, 0xaf28ca82, + 0xff069999, 0xf6a8d1ff, 0xd7272182, 0x00ffae07, 0x82ae871d, 0xc2352fff, 0xf32b00ff, 0xffff0834, 0xfff067fa, 0xb7831000, 0xf8130926, 0x1c1200ff, + 0x1027a282, 0x00ff19c4, 0x820a9705, 0xc01022a2, 0x210a8200, 0x1982e89b, 0xffd72326, 0x30e8f6ff, 0x94200e82, 0xef22d582, 0x1e82e83b, 0x82ec0521, + 0x3aee2242, 0x264282e2, 0xffffd98e, 0x82ea11f4, 0x00c02128, 0x00237982, 0x82cd8c4f, 0xb32728b8, 0x00ff8b33, 0x83cd4c20, 0x82cc2004, 0xb327230a, + 0x06850834, 0xdfffff24, 0x168433b3, 0xd8ffff28, 0x088bcd4c, 0x99820623, 0x82cdcc21, 0x26f432a9, 0x0800ff66, 0xffff1018, 0xff5238fb, 0xe6500c00, + 0x2b0a8708, 0x00ff3d4a, 0x991f4503, 0xb80900ff, 0x08221a82, 0x868267e6, 0x82668321, 0x6678282f, 0xffff0566, 0x43523862, 0x7c200f86, 0x11226f82, + 0x864384ab, 0x84f72117, 0x0d22a782, 0x25823433, 0x98d90b31, 0xe7f7ffff, 0x0400fff0, 0xffffaec7, 0x821aaff3, 0xc704225c, 0x260a82f0, 0xffff34b3, + 0x8228bcfc, 0x820720a1, 0x47f62119, 0xf7331382, 0xff087c14, 0x9a997cff, 0x9987ffff, 0x00ff0598, 0x82e4c515, 0x194a224a, 0x304a829a, 0x4e66e63d, + 0x0e08408b, 0x14f830fb, 0xcc7100ff, 0x0a3644cc, 0x260c3943, 0xffff066b, 0x485238ae, 0x1e8c0a6c, 0xeeffff25, 0x438b7a54, 0x0021056a, 0x0852440e, + 0x5100ff27, 0xfb07aec7, 0x223c8274, 0x82ae07f5, 0xccf5321f, 0x0500ffcd, 0xffff00a0, 0xffb81efa, 0xd8430900, 0x210a8208, 0x0a821924, 0xff184425, + 0x824cffff, 0x9f0b22c9, 0x21d982c0, 0x1382dfaf, 0x0884eb29, 0x01ff14f7, 0x8234330e, 0x860731b7, 0x0f00ff67, 0x00ff50f8, 0xff333313, 0x20c50600, + 0xe6260e82, 0xf8ffff66, 0x36825278, 0x52f80f22, 0x70200a82, 0x06271482, 0xffff5ccf, 0x83eae6ec, 0xffa4250e, 0xae07f0ff, 0x95276482, 0xffffd7a3, + 0x821e851f, 0x70ad2848, 0x00ff06a4, 0x4b34338e, 0x8421050a, 0x48b183ff, 0x86210822, 0x204c828b, 0x08a14f11, 0x240c2248, 0x07cccc71, 0x05e842ab, + 0xe4428b20, 0x9a992107, 0xee22d782, 0x7a446666, 0x00ff2505, 0x15666667, 0xb5271182, 0xffff0a57, 0x821e45c3, 0x90422604, 0x54b5ffff, 0x2957827c, + 0x9919b0ff, 0xd1ffff06, 0x2182a430, 0x0a97d631, 0xd41d00ff, 0xf1ffff7a, 0x00ff5238, 0x4268662c, 0x10310de8, 0x1200ff21, 0x00ffb81e, 0xffd1c210, + 0x0c970500, 0x210a8208, 0x3f417bd4, 0x12002805, 0xffff7b14, 0x82f0e7f6, 0xec91260e, 0x3defffff, 0x361e822e, 0xfff81306, 0x1ec5edff, 0x001100ff, + 0xf3ffff83, 0x00ff00c0, 0x82523813, 0x4f002379, 0xb88233f3, 0x295c2722, 0x2024b882, 0x00ffae07, 0x0a820482, 0x2a5c2723, 0x23068508, 0xf8dfffff, + 0x20218682, 0x22b28205, 0x82d7a3d8, 0x67ff2433, 0x82060b57, 0x18842164, 0xf726ad82, 0x00ff9603, 0x5f823304, 0xf6e8f92d, 0x460700ff, 0xffff08ea, + 0x8244ebf9, 0xfe3f300a, 0x78fdffff, 0x0900ff10, 0x00ff9a99, 0x8207b001, 0xcc4c2109, 0x20218e82, 0x277f8200, 0x053233b1, 0xc10200ff, 0x0f26cd82, + 0x00ff5e4f, 0x1482400d, 0x7a140b30, 0x7a0f00ff, 0xf7088be1, 0xffffff54, 0x2282c0fe, 0x4a147341, 0x6f4209dc, 0xba5a2d0e, 0xffff06e2, 0xffeb91eb, + 0x9dd08eff, 0x72223e82, 0xe082cd4c, 0x32b34a22, 0x3c27ce82, 0xffff34b3, 0x829919c4, 0x80b43b3d, 0xfb0e0800, 0xa700ff70, 0x01ff33b3, 0x1534331f, + 0xa64000ff, 0x4c00ff67, 0x35825c0f, 0x82780b21, 0x730d22f3, 0x21838232, 0x714c8d57, 0x88f23506, 0x0b00ff31, 0xff08166e, 0x8901faff, 0x230500ff, + 0xf8ffffd6, 0x0222db83, 0x09820080, 0x2205534c, 0x8221f0f6, 0x00f72c5e, 0xfcffff83, 0xffffc22a, 0x8214aef9, 0x028b211b, 0x6e2d3582, 0xffff3473, + 0xffcccc54, 0x14eed9ff, 0x2025826c, 0x828482b5, 0xc7a72506, 0x4700ffae, 0xff220482, 0x768238b8, 0x99415820, 0x85068305, 0x221b8316, 0x8200ff8b, + 0x82082010, 0x82552006, 0xbcff2671, 0x00ffcd4c, 0x27768345, 0xff6666ab, 0x9a190400, 0xf8205f82, 0xff291482, 0x15cccc00, 0x0fcbffff, 0x2558825c, + 0xffa4f0d4, 0x0a832b00, 0xf0340023, 0x483c83a4, 0x0f270532, 0x2a00ff5c, 0x83fff628, 0x15324815, 0x82c2f521, 0xcbff222d, 0x27c082f5, 0xff66e6d4, + 0x3e0ad4ff, 0x19295482, 0x0e088b9a, 0x01ff70fb, 0x2d83823b, 0x28dc6f01, 0xfc74fb15, 0xffff0514, 0x7e820cfa, 0x5ccff527, 0x4bf5ffff, 0x200e8202, + 0x2209824f, 0x8271fdf4, 0xfaff235b, 0x8982ef87, 0xf272fa27, 0x670100ff, 0x261b82f0, 0x00ff14ee, 0x82f8f302, 0xbaf02630, 0x0800ffe1, 0x261483e7, + 0x00ff9ad9, 0x82109813, 0x276d820e, 0x1e450f00, 0xc300ff08, 0x01230a82, 0x8266e64f, 0xc737225f, 0x1c1745ae, 0x3211ce4b, 0xff0694f7, 0x34730b00, + 0x0a00ff8b, 0xffff9899, 0x4b00e0f9, 0xf6220686, 0x5c82a410, 0x34b30524, 0x0a82ffff, 0xffffff24, 0x038232f3, 0x4b8ac121, 0xff2305aa, 0x850a17f6, + 0x800b21e3, 0xc6263182, 0xff15cdcc, 0x0a831600, 0x99191728, 0x1f00ff99, 0x52826766, 0x33b32223, 0x34068208, 0xff7c9446, 0x7b94c6ff, 0x6b3900ff, + 0xb9ffff84, 0x088b856b, 0x83a8826b, 0x82188508, 0x827c201d, 0x6bb922fe, 0x2b2f8284, 0xcd4cddff, 0xfd0d00ff, 0xe0ffff71, 0x16213483, 0x2309827d, + 0x0814eee8, 0x592f0f82, 0xe8ffff9a, 0xffffa4b0, 0xff852beb, 0x82b3daff, 0xd5ff23b8, 0x3583cccc, 0x60833c82, 0xc6201682, 0x00266f82, 0x8b7b9446, + 0xdd82cb08, 0x83827d82, 0x7e837983, 0x2f828e85, 0x332a0023, 0x82468234, 0x25002604, 0xffffcc4c, 0x230482e0, 0xcd4c1700, 0x84206582, 0x9924c783, + 0xab15a330, 0x2a4f3e82, 0xe3ff2309, 0xa482cc4c, 0x34b3dc22, 0xff233e82, 0x4f33b3dc, 0xae820713, 0xd4850e83, 0x23092c4f, 0x33b31c00, 0x40826e82, + 0x00212f82, 0x4f5f8323, 0xb3210571, 0x062c4f34, 0xfeffbb28, 0x159002c0, 0x634f064b, 0x8236820b, 0x972f83d5, 0x99d58336, 0x20d58296, 0x829183e3, + 0x4b5685ad, 0xc7210eae, 0x27c482ae, 0xff5238b8, 0x5438b8ff, 0xa7220a82, 0x6882adc7, 0xaaff3c08, 0x00ff156e, 0xffc3b543, 0x5278baff, 0x975400ff, + 0xfbffff0b, 0xff0866e6, 0x9959bfff, 0xf0b3ffff, 0xffff05a4, 0xffae87f4, 0xcc8cf2ff, 0xa80100ff, 0xebffff73, 0x00ff3eca, 0x82cf770d, 0xec913218, + 0xffff9108, 0xff00e0fa, 0x48610700, 0x81fdffff, 0x38098248, 0x088b0b57, 0x0f0900ff, 0x00ff8bdf, 0xff7dff08, 0xb0d20300, 0x510600ff, 0x211b82ec, + 0x1a82fe74, 0x767e9131, 0x33ab00ff, 0x2600ff32, 0x00ff9a19, 0x8266e61e, 0x994a2229, 0x2291829a, 0x82335800, 0x33b82dca, 0x4700ff33, 0xffff3cca, + 0x8bcdcca7, 0xff231682, 0x43900200, 0x0a2114b9, 0x221d823e, 0x820a3400, 0x0f2b2792, 0x2b00ff5c, 0xb943c2f5, 0x5c0f211a, 0xff212d82, 0x282882cb, + 0x66e6d4ff, 0xd7d5ffff, 0x08b9430a, 0x01ff3026, 0x8b9a195f, 0xfb286582, 0xff8bf833, 0xe81bfbff, 0x1821f082, 0x21098210, 0x7f827268, 0x08f04739, + 0x34f7d4fb, 0xf6ffff05, 0x00ff2406, 0xffcc6c05, 0xf027f9ff, 0x820b00ff, 0x00ff2335, 0xbe84190c, 0x48210c22, 0xd821ea82, 0x26168210, 0x00ffcc0c, + 0x8294d80a, 0xa470232a, 0x3a84f708, 0xe10f0022, 0x07271e82, 0x00ff00e0, 0x82842b13, 0x82a0203f, 0xe3072d09, 0xf0ffffd8, 0xff08a430, 0xf0e70700, + 0x19820a84, 0x78829820, 0xaec7ec22, 0xf8320e86, 0xff080a17, 0x142ef9fe, 0xa17cffff, 0x01ff0548, 0x7e82cc06, 0x9a997c2b, 0x0f00ff05, 0xffff5ccf, + 0x28a882f8, 0xf6680600, 0xc9ecffff, 0x200e8238, 0x27d88217, 0x08142ef0, 0x63faffff, 0xf4205e82, 0xf422e883, 0x588234b3, 0xff008031, 0x6666f3ff, + 0x2f0e088b, 0x1594f7bb, 0x4e06f4f7, 0x204e0510, 0xec512207, 0x2210828b, 0x850814ae, 0xffff2906, 0xffa4b0f1, 0x866b0d00, 0x21055e4e, 0x3082fb08, + 0x3c5aff20, 0xa4b0270b, 0xefffff8b, 0x3082c235, 0x47850683, 0xcaf0ff23, 0x2557853e, 0xfbf4f708, 0x35b21514, 0xce8297a0, 0x9e4e9786, 0x47302005, + 0x152505a0, 0x40f4ffff, 0x32938200, 0xff33b3f4, 0x10780600, 0x63faffff, 0x0b00ffd7, 0x41089438, 0x0f220628, 0x19825ccf, 0xfff06726, 0x52381300, + 0x24054141, 0xf6e80700, 0x05574108, 0x66830033, 0xfeff0566, 0xffc435f9, 0xb85e8300, 0xf0ffff05, 0x272f822f, 0xff66e607, 0x1098f9ff, 0x30213482, + 0x05ab41a4, 0x48820020, 0x0a820820, 0x8619e421, 0x2b132244, 0x21588244, 0x0e824861, 0x8248e121, 0xb81e2f6c, 0xffd4f708, 0x010060ff, 0x0a00ff05, + 0x8a8290e2, 0x820a9721, 0xcccc2121, 0xe621a482, 0x23a48267, 0x0866e6f3, 0x2e830683, 0xf027f922, 0xee261682, 0xf5ffff14, 0x2a826c27, 0x085c8f26, + 0x34fbd4fb, 0xfb2f8082, 0xfffff668, 0xffe2bafd, 0x291cfbff, 0x83feffff, 0x33fb228a, 0x05714633, 0x4ccc0023, 0x07974fcd, 0x33b39323, 0x0be14606, + 0x820ae64e, 0x54ee2265, 0x069e417c, 0xec91f222, 0x41069e41, 0xea260efd, 0x1000ff8b, 0x9382aec7, 0xa3110023, 0x05325cd8, 0x5c0e0023, 0x2e268228, + 0x088bf6a8, 0x4c6c00ff, 0x00ff06cd, 0x8200801c, 0x33172728, 0xe8ffff33, 0x5a825ccf, 0x6866e322, 0xff233382, 0x82ac47ec, 0xae0734bd, 0x40eeffff, + 0xecffff00, 0xffff5278, 0x08d823f6, 0x829effff, 0xc6ff23a4, 0xcd82e2ba, 0x824cf521, 0x33fa22fe, 0x83e28232, 0x80f521c8, 0x2205ad41, 0x4b630834, + 0x0028072b, 0xff5c4f0e, 0x16aef1ff, 0xec20a495, 0x2f06f74b, 0xb31500ff, 0xffdb0734, 0xffff2e00, 0x2700ff05, 0x00286d82, 0xff00c013, 0xae871800, + 0xab210e82, 0x22278285, 0x827c142c, 0x3f003298, 0xffff98d9, 0xff9a19cc, 0xa4f03300, 0x33c0ffff, 0x28cc8233, 0x33b3c3ff, 0x0290feff, 0x4ed85c90, + 0xd85c6683, 0x66e62e05, 0xff0e088b, 0xcdcccf00, 0x45ab01ff, 0x2567821e, 0xffcd8ca2, 0xd982edff, 0x82b4ff21, 0xb4ff23a9, 0x0e82f4a8, 0xff3d8682, + 0x085d8fa2, 0x5ce4ffff, 0x73ffff29, 0x00ff9b19, 0xff3e4a60, 0x30b382ff, 0x738200ff, 0x36238234, 0xff089c19, 0x8f021300, 0x1cfdffff, 0x1100ffac, + 0x00fff628, 0x82e4250f, 0x3a1322e2, 0x281a82e0, 0xff060000, 0xc0a90000, 0x30118205, 0xff70bd0f, 0x5c8ff4ff, 0x230d00ff, 0xf0ffffd8, 0x22f78299, + 0x82285c02, 0xa6ab315f, 0x0c00ff66, 0xffffe2fa, 0xff6726bf, 0x66264900, 0x58232e82, 0x8208eb11, 0xe6662106, 0x58251182, 0x00ff299c, 0x21308352, + 0x8082ca68, 0x64e6f522, 0x5b215b82, 0x320a828a, 0xff8a21f7, 0x5c0f4300, 0x9eadffff, 0xffff8b76, 0x82ce0ca4, 0xefff2335, 0x72820ad7, 0xe8e9ff26, + 0xeefffff6, 0xee211d83, 0x202c820a, 0x059255e9, 0x16820683, 0x82cc0c21, 0xc2f521b0, 0x16226382, 0x4f820a17, 0x9a197823, 0x320c8207, 0xffd6d808, + 0xc8d6f8ff, 0x2c0700ff, 0xf7ffff48, 0x828ba826, 0x05e023a2, 0x0082ff1e, 0x82051421, 0x74b3211b, 0xfa306882, 0xffff5819, 0xff0c02fb, 0x7c14feff, + 0x4ff9ffff, 0xff22ee82, 0xc88326e7, 0xff210482, 0x21b183e2, 0xd2823a04, 0x152ee022, 0xb921f682, 0x264482dc, 0xff0040d9, 0x8245f2ff, 0xa1e22149, + 0xdc2c5a82, 0xffffebd1, 0xff6666fa, 0x1f45d7ff, 0xf6311e82, 0xffff5a84, 0xff70fdba, 0x024b3500, 0x02c5ffff, 0x5eda8290, 0x1a2205b3, 0x9a82a470, + 0x1b831720, 0x448b0936, 0x281300ff, 0x0f00fff6, 0xa3080456, 0xb3e0ffff, 0x2900ff34, 0xee2c6a83, 0x00ff289c, 0xff842b2c, 0x34330b00, 0x2e2bd182, + 0x00ff102e, 0xff5cb40a, 0x82cc1e00, 0x332d22ec, 0x26c28232, 0x00ff9a19, 0x8266e62e, 0xe614221e, 0x20f08368, 0x20168395, 0x2c16837a, 0xff986e74, + 0x999966ff, 0xf0e1ffff, 0x27208220, 0xffcd4c1f, 0x166ee4fe, 0xe522c082, 0xf482ae87, 0x5278ea27, 0x8f1500ff, 0x238b825c, 0x08707d1a, 0x11820685, + 0x82ae8721, 0x5d8f2704, 0x781a00ff, 0x38828b52, 0x16850683, 0x83eaff21, 0xe5ff23b9, 0x2d828f82, 0x90230682, 0x83ebffff, 0x3c1682f1, 0x99e4ffff, + 0x0e088b9a, 0x01ff30fb, 0xff00807d, 0xcc4c0c00, 0xf834fb15, 0xffff0514, 0x268e83fb, 0xff86eb0b, 0x824cf4ff, 0xc50726b9, 0xf3ffff1e, 0x852d8219, + 0x21168506, 0xf483f8ff, 0xff272a83, 0x087a14f4, 0x83fc34fb, 0x33f92b3a, 0xeffffff8, 0x00ffa4b0, 0x4982b407, 0x9042ed2c, 0x501000ff, 0xf9ffff55, + 0x9a82c235, 0x48611022, 0x2c200a82, 0x12220982, 0x238234b3, 0xfffabf26, 0x8fc20600, 0x4c212382, 0x38148250, 0xffcdcc1f, 0x5c4f4c00, 0xc500ff05, + 0xff06cd4c, 0xcccc1f00, 0xb0b3ffff, 0x221082a4, 0x82e81b05, 0x52b82b7e, 0xe90b00ff, 0xf8ffff36, 0xb3827a94, 0x83ae8721, 0x180426f0, 0x00ff8b10, + 0x22568304, 0x8202cc00, 0xb4082609, 0xaf0100ff, 0x225182e6, 0x82404a10, 0x04d62161, 0xb3236b82, 0x8300ff32, 0xf9ff2275, 0x3f7a8233, 0x08cc4c10, + 0x99f9feff, 0x7300ff9a, 0xff1534b3, 0x67e64800, 0xccac00ff, 0xffd305cc, 0x343353ff, 0x6f2abc82, 0x0e069a19, 0x01ff70fb, 0x25821901, 0x9a99cd29, + 0x00ff9e15, 0x82cc4c16, 0x66e62181, 0x2007f044, 0x05a4481f, 0x2113db4a, 0x854b14fb, 0x0a034f0c, 0x4414fc21, 0x405709d6, 0xff862805, 0x85ab1100, + 0x82f7088b, 0x0100229a, 0x4aef8242, 0x86200caf, 0x4623df82, 0x82087a94, 0xb12e2506, 0xe6fffff2, 0x2825b783, 0xffff0080, 0x270482da, 0x66661600, + 0x3effff08, 0x92249583, 0xeb15d663, 0x262eaf4a, 0x14f7062b, 0x4a14f707, 0xfb210585, 0x9c0d8514, 0x135c4a43, 0xf4f7302d, 0x335800ff, 0x00ff1534, + 0x82c27516, 0xa3082da9, 0xecffffd8, 0xff8b5278, 0x3e8af3ff, 0xff30bb82, 0xff28dce8, 0x3e0abdff, 0xe8beffff, 0x9efffff6, 0xb7822682, 0x66e67622, + 0xad212282, 0x22fa82b3, 0x82cecc75, 0x336a2238, 0x302d8232, 0xcecc6700, 0xde4f00ff, 0x7700ffb9, 0x00ffcc4c, 0x05ec418b, 0x50836320, 0x07410023, + 0x214982ae, 0x388248e1, 0xd6e3e922, 0xff282d82, 0xffe2baf3, 0x1679f6ff, 0x42277282, 0xe9ffff90, 0x828b5a84, 0xaee0225b, 0x2c228214, 0xff2085f1, + 0x00403800, 0x4ca9ffff, 0x221683cc, 0x828f029e, 0x97c62716, 0xabffff0a, 0x0a82f468, 0x707db522, 0xb5224483, 0x288252f8, 0xff856b24, 0x6082aaff, + 0xfa620023, 0x212d82e1, 0xac825700, 0x02000024, 0x1b829990, 0xa5823320, 0x00801f28, 0xfb0e088b, 0xfc56f730, 0x14fb2306, 0xe761058b, 0x1ae94116, + 0x00ff1429, 0x05de0100, 0x827b00ff, 0x00ff244e, 0x84008064, 0x82ff8204, 0x838c8210, 0xffff2217, 0x2416849b, 0xffff227e, 0x82268284, 0x80fe2d16, + 0x2b159002, 0x07d4f706, 0x00ff06eb, 0x2309f64e, 0x5238b8ff, 0xa822c882, 0x248214ae, 0x0682ff20, 0xb8ffff29, 0xffff3333, 0x4b866bb6, 0xd5550634, + 0x54ee2122, 0x5207ab62, 0xf8220a7f, 0x94820714, 0xf6a81122, 0x2110d556, 0x456194f7, 0xf1ff220c, 0x0adf62ab, 0x7c54ee22, 0x8205ca52, 0xff842216, + 0x053a56ff, 0xff067429, 0x010080ff, 0x8434f707, 0x09425a39, 0x8215ae21, 0x832382bc, 0x0a7157bc, 0x39827482, 0x088b7b29, 0xfb0634fb, 0x82f70714, + 0x5800203f, 0x902006f9, 0xf9588e82, 0x0c205505, 0x7f01ff24, 0x4c8570fd, 0x45837f94, 0x14207c90, 0xef227c82, 0x7c835238, 0xee570682, 0xc7f02206, + 0x05d541ae, 0x34207c84, 0x5a12225c, 0xb5531215, 0x05354108, 0x20c51022, 0x20163541, 0x21b582b3, 0xc0840e00, 0x23083541, 0x54f82f0e, 0x2b059b5a, + 0xff9a9970, 0x666689ff, 0x19b1ffff, 0x95290982, 0x088b9a99, 0xb37bffff, 0x26a88233, 0xff3333a6, 0x83336a00, 0x4374203f, 0x7c200529, 0x002b2882, + 0xff67e664, 0x00806300, 0x827a00ff, 0xff08371b, 0x0ad75400, 0x5200ff8b, 0xffffc2f5, 0x8b52b8c8, 0x14dfffff, 0x0682087a, 0x54b8ed22, 0x0c26e182, + 0xf2ffffcc, 0xe182ac47, 0x8334f321, 0xf5e0225b, 0x211b82c2, 0x3f8240f0, 0xf8283825, 0x50a6ffff, 0xa8220590, 0x16820a57, 0x5c8fb827, 0x57b9ffff, + 0x220a8208, 0x832adca6, 0x30dd2506, 0x1b00ffa4, 0xff280482, 0xff8e0284, 0xf6e88300, 0x00224482, 0xa082734f, 0x26410026, 0x3700ff66, 0x0021b782, + 0x228e830d, 0x829a9947, 0xe67922bb, 0x0c0e4566, 0x590a6042, 0x0d220c33, 0x635c146e, 0x00a82308, 0x0c820602, 0xff34b326, 0x0ad70000, 0x8208ef41, + 0xeeff2363, 0x7055cd4c, 0x7f012406, 0x431570fd, 0xff220967, 0xe452abf1, 0x1454550e, 0x0754f727, 0xfb0694fb, 0x34d54154, 0x62821120, 0x7b20bf82, + 0x54209182, 0x8507e159, 0x05ec41b4, 0x250a0843, 0xf70714fb, 0x815a0694, 0xab112105, 0x43202555, 0xab43073f, 0xa4b0210f, 0x24064b43, 0x8b5c4fee, + 0x10da5b08, 0x21117e5a, 0x9c875c4f, 0x8ba4b029, 0xf706eb08, 0x5c2b07d4, 0x54200e0f, 0x830c2c57, 0x2034859a, 0x170f5c7c, 0x2208e65d, 0x43ffff8b, + 0x968505dd, 0x084e8420, 0x062b2206, 0x059544fb, 0xdc421120, 0x0d545a0a, 0x25059d43, 0x99fcfeff, 0x4582079a, 0xd6a3a933, 0x38b8ffff, 0xb9ffff52, + 0xffff90c2, 0x8baec7a7, 0x85068508, 0x46002f16, 0xff8b9042, 0x0a575600, 0x2300ff08, 0x6b56f668, 0x4c862005, 0x705605b2, 0x83112005, 0x0bb24cdf, + 0x240a7c41, 0x9edcffff, 0x2d3382b8, 0x84ebccff, 0x0f2b00ff, 0xd6ffff5c, 0x0e503473, 0x29002312, 0x6782cc8c, 0x7c143327, 0x0301ff08, 0x2033835e, + 0x05e44100, 0x960d4741, 0xfb0e3067, 0x3a01ff70, 0x00ffcc4c, 0x15343312, 0x830a00ff, 0x78f12169, 0xfc25d682, 0xffffc460, 0x260e84ec, 0xffffd077, + 0x82a4f0f5, 0x70fa2fdf, 0xfcffff20, 0xfffff027, 0xffeaa6f9, 0x0984feff, 0x8352b821, 0xd7f52dfa, 0xffff8b0a, 0xff3e0af6, 0xe0cf0400, 0xc7262082, + 0x0800ffae, 0x3582cef7, 0x8c6c7a32, 0xf0c000ff, 0xffff0520, 0xff66e6bf, 0x6666beff, 0x92200a82, 0x25059d69, 0xff7a54ee, 0x2542f1ff, 0x0dfd5d0d, + 0x450e9844, 0xdda405ce, 0x48ffff33, 0xff0734b3, 0x9a19c900, 0xb3cd00ff, 0x00ff0534, 0x2c38830c, 0xff289c0c, 0xec511400, 0x400000ff, 0x27138200, + 0xffffb89e, 0x08d8a3f3, 0xa8210a87, 0x261982f4, 0xffff9042, 0x82e2baeb, 0x211e8419, 0xc9822a5c, 0xcdcc7627, 0xb373ffff, 0x28488232, 0xff65a68c, + 0x2adc34ff, 0x1ef04205, 0xbb427420, 0x076f5d0f, 0xa40b9c46, 0xf4fb24cd, 0x4454f707, 0xfc5c0855, 0x5ccc2005, 0x2f220cfc, 0xa64254f8, 0x0b544405, + 0x08245a41, 0x1601ff20, 0xff075c4f, 0x9a997aff, 0xe637ffff, 0xffff0568, 0xffb81ef4, 0xa430eeff, 0x80e2ffff, 0x7a5c8b00, 0xcf112306, 0x2582085c, + 0xff66a62b, 0x9819c800, 0xe9feff05, 0x0a5e46b3, 0xf7856aa4, 0x0a170e37, 0x380900ff, 0x0c00ff10, 0x00ffc275, 0xff42800d, 0x7c140400, 0x210a8208, + 0x0a825278, 0xfff02725, 0x829e0e00, 0xb3fa2781, 0x0700fff8, 0x8082ecd1, 0x82d04221, 0x5ea5211e, 0x07271482, 0xff0534f3, 0x8266a500, 0x19f82286, + 0x270a829a, 0xffe0cf07, 0xe2ba0b00, 0xa8263482, 0x0500ff72, 0x4882cc4c, 0xbb827020, 0x9ad9fb22, 0x0d273482, 0xffff707d, 0x8298d9fb, 0x34332672, + 0x8cf3ffff, 0x22d082ce, 0x45f4e8f1, 0xf2271188, 0xffffae87, 0x82e08ff7, 0x52f82124, 0x59210482, 0x21388216, 0xf482f668, 0xd663fc26, 0xb3feffff, + 0xfc253e82, 0xffff6866, 0x217c82ff, 0x9449fcff, 0xb0f62205, 0x214f8220, 0x5f82eef6, 0xf8130427, 0xcaf9ffff, 0x30b3823e, 0xff082671, 0x0a97f8fe, + 0x143c01ff, 0xfeff057c, 0x0bac63d8, 0x2c2a2a41, 0xff52780d, 0x21700800, 0x070c00ff, 0x260482ae, 0x00ffeaa6, 0x420a9704, 0x002306ad, 0x82188404, + 0x823820f5, 0x3bfc22ac, 0x372882e8, 0xfffff6a8, 0x0818a4f5, 0x680701ff, 0xc3fefff6, 0xff0544eb, 0x9a992701, 0x45058144, 0x1944112c, 0xf6a8210d, + 0xee27c982, 0x0e087a54, 0x5174f72f, 0x84220789, 0x15820080, 0x00809b24, 0x0482ffff, 0x10820a82, 0x06850820, 0x6400ff22, 0x0e4a1686, 0x4a958205, + 0x32832215, 0x450b154a, 0x47220c39, 0x0559aec7, 0x82582009, 0x820020d8, 0x00ff2411, 0x4a48e146, 0x62820535, 0x251e3c4a, 0xb7ffff34, 0x5482ec51, + 0xeb61cc20, 0x05d74c0d, 0x825c4f21, 0x077144ba, 0x3043ed86, 0x06ae5109, 0x5186ab21, 0x8b4414ae, 0x4aeb2008, 0xa3830ec4, 0x5723b582, 0x8508ec51, + 0x05c44a06, 0x94490023, 0x0df9557a, 0xff062b26, 0x70fdbf00, 0xc2613e84, 0x55918214, 0xd42109d5, 0x22cb82f3, 0x669a19cb, 0x89300536, 0x00ff9a19, + 0x1500802d, 0x1e2200ff, 0x2700ffb8, 0x0028e482, 0xff5ccf14, 0xf6283300, 0x38227682, 0x7d831e05, 0x91417b20, 0x83642008, 0x66852609, 0xff088b66, + 0x240683ff, 0xab99ffff, 0x1dc4418c, 0x9b997a22, 0x00232d82, 0x8233732c, 0x5c292750, 0x0d00ff28, 0x6f82f628, 0xd8e32508, 0x6b1600ff, 0x00ff0886, + 0xffe2ba2e, 0x84ebc7ff, 0x0600ff05, 0xfffff853, 0xfff067f8, 0x8e170900, 0x12fcffff, 0x2b210983, 0x22408384, 0x829a5915, 0xa10a2740, 0x1200ff48, + 0x0a829042, 0x00c00d22, 0x07369c83, 0xffff1639, 0xff2691fd, 0x5a440700, 0x03fbffff, 0x0500ff96, 0xa082e2fa, 0x3c6bd130, 0x0a3900ff, 0xffff053e, + 0xff66e656, 0xe883f2ff, 0x57a7ff21, 0x1e5b08ee, 0x2d18420d, 0x3ecadb2f, 0x73f3ffff, 0xdeffff34, 0xffff14ee, 0x239682eb, 0xf628e5ff, 0xb9277582, + 0x00ff1e85, 0x82b89e54, 0xa9f92275, 0x2b958278, 0xffffd498, 0xffe4e5f6, 0xdaee0300, 0xd4210982, 0x2ccd827b, 0xe1baeaff, 0xf5ffff8b, 0xffff5c4f, + 0x229084ed, 0x823433f2, 0xff2208cd, 0xffeac6f8, 0xd96e0200, 0xbbf8ffff, 0x0400ffa6, 0xffff6bfc, 0x081e05fa, 0x874700ff, 0xaaffffae, 0x5782862b, + 0xfa9ee822, 0x9720cd82, 0xe5266c82, 0xffff3333, 0x8682b3f7, 0xf154e320, 0xb3e43e08, 0x8a00ff33, 0xff15cc4c, 0xcd4c3500, 0x191500ff, 0x00ffb19a, + 0x8bcdcc33, 0xcc3c00ff, 0x266582cd, 0xf6684f00, 0x82bfffff, 0x40002b04, 0xffff0a97, 0x8b0a97b0, 0xb865fb08, 0x24a34f0d, 0x4a0be949, 0xf7370ac5, + 0x00ff0714, 0x06146e5d, 0x806800ff, 0x6dffff00, 0xff056666, 0x82400600, 0x82f7200a, 0x09002204, 0x247482d7, 0x957a54fb, 0x21d7828b, 0x91836c06, + 0xee7c0626, 0xec0100ff, 0x05220f82, 0xf782d6a3, 0x82180421, 0x630e350a, 0x0a00ffd8, 0x00ff1e45, 0xff0a5703, 0xe2fa1300, 0xc1f5ffff, 0x18825582, + 0xaa2bfc82, 0x00ff61a5, 0x05f4bd77, 0x835bffff, 0xb0d525e8, 0x04f715a4, 0x2c221e82, 0xeb82291c, 0xd7e3232b, 0x1cdcffff, 0xffff8b2a, 0x05184fd3, + 0x11830682, 0xffff2925, 0x839002dd, 0x82d72015, 0x083083f6, 0x9a199f2f, 0x30fb0e07, 0xe65d01ff, 0x4400ff66, 0xff1566e6, 0x10b8f9ff, 0x5edbffff, + 0xecffffb8, 0xffff1a64, 0xff2a9ce3, 0x3233e1ff, 0xe8eeffff, 0x217c82f4, 0xc38217e7, 0x862bf22c, 0xd4e2ffff, 0xfaffff7b, 0x098298d9, 0x82995921, + 0xc2ff2dd1, 0xff8bd723, 0x5c0fc0ff, 0x6b1600ff, 0xe0202082, 0x0c229c83, 0x3582c2f5, 0xb89eef26, 0xac0600ff, 0xf8270982, 0x00fff628, 0x8202ab12, + 0x85ab270e, 0x5c1000ff, 0x0a82082a, 0x8419a421, 0x2019820a, 0x22c782a1, 0x8284eb07, 0x836e200e, 0x1e45218c, 0x4d351e82, 0xffff5c8f, 0xff2a5ce0, + 0x3e0a4900, 0x40f8ffff, 0x2300ff00, 0x22048280, 0x8232b313, 0xd40d251e, 0x0700ff7a, 0x00325c82, 0xff0cd707, 0x7ebf0b00, 0x050300ff, 0x1100ff1e, + 0x1e825c8f, 0x2e830720, 0x824f2a21, 0x8ce63142, 0x0e00ffcc, 0xffffa470, 0xff0180aa, 0x48a11800, 0xb9269082, 0x00ff4861, 0x57824a14, 0x09839f20, + 0x67e61b22, 0x21208582, 0x69221382, 0x3d82ff7f, 0xe87b0523, 0x241082ab, 0x00fff027, 0x2081831b, 0x2277831b, 0x82f6a811, 0x972d261a, 0x1d00ff0a, + 0x217c8254, 0xd4826845, 0x3e8a022d, 0x665b00ff, 0xe7ffff66, 0x820868d1, 0x0a17307d, 0x78fbffff, 0x0a00ff10, 0xffff142e, 0x82247bee, 0xe27a210e, + 0xeb210982, 0x20778284, 0x200a85fb, 0x260f8286, 0xffffc275, 0x829ad9f5, 0x14ee2609, 0x7a0400ff, 0x221e82e0, 0x82e2baa4, 0xb83324a1, 0x83d4ffff, + 0x5cf52b52, 0xebffff28, 0xffff6766, 0xd482cff2, 0x73f3ff2b, 0xf7ffff33, 0xffff20f0, 0x2db582f8, 0xe08ff4ff, 0x82fdffff, 0xf1ffff8f, 0x3d820080, + 0xe7bbf82c, 0xb0d5ffff, 0x1900ffa4, 0x1482bd74, 0xff5c8f24, 0x1e835500, 0xb85ee722, 0x46209a82, 0xff270f82, 0xff15aeeb, 0x82996000, 0x33e42176, + 0xed214c82, 0x22b982e6, 0x47666696, 0xe54b0bca, 0x05504d08, 0x2308c34f, 0xf4fb0614, 0x210e364d, 0x294f16ae, 0x4f068506, 0x00200540, 0x26057974, + 0x0884ab11, 0x5307f4f7, 0x00210e0d, 0x117e4c0e, 0x210d626a, 0x2362d4f7, 0x09264f0e, 0xf830fb23, 0x05a24914, 0x1effff24, 0x8c83ce4c, 0xc0839720, + 0xb8dea92e, 0xcca9ffff, 0x96ffffcc, 0x088b4821, 0x11820685, 0x002f1682, 0x8b486155, 0xeb6800ff, 0x00ff0884, 0x4734b3e1, 0x862105c7, 0x26c64dff, + 0xba226788, 0x5e5e7a54, 0x5ec72306, 0x5e5effb8, 0x20068305, 0x075c5e7c, 0x84ab3822, 0x45220a82, 0x679048a1, 0x0e203882, 0x63052e4e, 0xf74d111d, + 0x068f5509, 0xab730124, 0x54551584, 0x05645506, 0x55482121, 0x33210778, 0x0f8f5534, 0xff0a5731, 0xcac10700, 0x07fbffff, 0x0b00ffae, 0x55084aec, + 0xf92706ca, 0x00fff833, 0x825c4f10, 0x05b4261e, 0xbd1200ff, 0x058f5570, 0xca060024, 0x0a82083e, 0xff486126, 0xe8db0600, 0x22061955, 0x551638f8, + 0xff23058f, 0x82b0b3ef, 0x7882271e, 0xc6feff52, 0x398268e6, 0x00808227, 0x193901ff, 0x220a829a, 0x8218c406, 0xcc4c2139, 0xb4213482, 0x2158823a, + 0x0e823eca, 0xffb85e25, 0x8321f9ff, 0x421022f4, 0x210a8290, 0x72553233, 0xedff2305, 0x0e831e45, 0xef35b282, 0x0e0814ae, 0x3d02ffaf, 0x01ff9819, + 0x1500c074, 0x14fc24fb, 0x21b38205, 0xcf82084c, 0xff276a82, 0xff7208f4, 0x82c2f7ff, 0x4df2203f, 0xff28050e, 0xff8b0498, 0xfc97ffff, 0xf0250584, + 0x030000ff, 0x222c82fe, 0x82e23af2, 0xfe83350a, 0x1cf4ffff, 0x0900ff28, 0xffff0a48, 0xffd823fc, 0xa63b0d00, 0xaf271e82, 0x01ffca96, 0x82a6ac16, + 0xb8ae215b, 0xe922c182, 0x0a82cc4c, 0x1924fc26, 0xc5f2ffff, 0xf4278d82, 0xffffe71b, 0x82c4b5f6, 0xe13a210e, 0x7d215e82, 0x22348270, 0x820040f2, + 0x0488210a, 0x6b268a82, 0x0800ff85, 0x99820c50, 0xfff6282a, 0xf0e70c00, 0xf824fb08, 0xf922a983, 0xea8208cc, 0x82cc8c21, 0x1964211e, 0x6e21fe82, + 0x260e8216, 0x00ffc18a, 0x84523806, 0x82cd2019, 0xf428210a, 0x70261982, 0xf7ffffa4, 0x1984a4b0, 0xefffff24, 0x1e823473, 0x33336e32, 0xe6dafeff, + 0x00ff0566, 0xff7b1455, 0x34b32301, 0x04210a82, 0x204e820c, 0x2396820c, 0x00800c00, 0x6624cb82, 0x0e00ff66, 0x8305c051, 0x217f8206, 0xad82ae87, + 0xffa09a26, 0x70fd0300, 0x5821b282, 0x254b8294, 0xff7a1455, 0xd783dcfe, 0x336e0026, 0x2501ff34, 0x21059941, 0x9f861038, 0x74731222, 0x4f21a482, + 0x260e825e, 0xffffb087, 0x82b8def9, 0x99102734, 0xfaffff98, 0x198284ab, 0xff68662b, 0x5c8fedff, 0xe6f8ffff, 0x319f8564, 0xff30fb0e, 0x9a997801, + 0x801400ff, 0x00ff1500, 0x1d824f0b, 0x866bf22c, 0x2cfeffff, 0xebffff8c, 0x7b827ad4, 0xff086c26, 0xa4b0f4ff, 0xfa250582, 0xffff1804, 0x270483fb, + 0xffe8bbf8, 0xe08ffdff, 0xbe4f4b82, 0xd3f62305, 0xb1828bf8, 0x82eae621, 0x82ec20b1, 0xaef9272a, 0x0700ff14, 0x0a821699, 0xd28d782a, 0x5ca300ff, + 0xffff05ac, 0xff236a83, 0x8200805d, 0xacf9210a, 0xf8221a82, 0x3482f067, 0xff73e826, 0xf212fcff, 0x22083148, 0x82f0c7f8, 0xbdf8274b, 0x0200ff2f, + 0xbd822070, 0xff8f0226, 0xe8fb0400, 0xf2223082, 0xa586856b, 0x822bfe21, 0x2b142209, 0x260e8286, 0x00ffe550, 0x827a940d, 0xe68e25ec, 0xab00ff66, + 0x71275f84, 0x00ff7413, 0x8254a3aa, 0xaff4226a, 0x252083df, 0x0100ff7c, 0xea82f8d3, 0x82842b21, 0x4095210e, 0x34824884, 0x2105ea76, 0x19830a57, + 0xf9828520, 0x820e2d21, 0x7b542119, 0x6325f982, 0x00ff08d8, 0x24728287, 0xb4885dff, 0x200a8205, 0x205e8266, 0x235e83a2, 0xcc4c0b00, 0x34827484, + 0x82162e21, 0x0cd72158, 0xff230e85, 0x828aacf4, 0x248e8234, 0xb0f4ffff, 0x241982a4, 0xffff7cd4, 0x220483eb, 0x821aaff4, 0x846b2153, 0x7125c682, + 0xffff9a19, 0x22488454, 0x822ef28e, 0x4c772e0a, 0x30fb0e05, 0x01ff0ef8, 0x15d8636d, 0x221282fb, 0x825c4f28, 0x336a21ba, 0x220e234e, 0x79ec91f2, + 0x002312bb, 0x74fe7f0d, 0x952d0876, 0xff0734b3, 0x10f865ff, 0xb0d700ff, 0x2c4482a4, 0xffcfb7f5, 0x46610e00, 0x580300ff, 0x055c481e, 0x600e0028, + 0x0a00fff9, 0xab82ae47, 0xfa830e20, 0x82450a21, 0x0a142719, 0xfcffff3e, 0x1982eaa6, 0xff004026, 0x00a0f1ff, 0x85271e82, 0xffffc2f5, 0x82b05245, + 0x828520ff, 0xbb0021b6, 0x3a82b684, 0x5e225382, 0x54829fb8, 0x827c5421, 0x8259200a, 0xc0f522d1, 0x223082c4, 0x82b85e0e, 0xa2e530fb, 0x330400ff, + 0xecffff32, 0xffff1e05, 0x8234b3f5, 0xba9e214f, 0x20056a46, 0x05aa558b, 0x2811bd50, 0xff06d4fb, 0x0a97f3ff, 0x063c418b, 0x2030072d, 0xc0faffff, + 0x0b00ff00, 0x8208663b, 0x82b8200a, 0x820b20d4, 0x0100219b, 0x0d2b0983, 0x00ffae47, 0xffdfef07, 0x82870900, 0x140126c9, 0x01ffcc4c, 0x239f834b, + 0x864b04ff, 0x54173d50, 0x3a500879, 0x82f7200d, 0x0c00237b, 0x1e82f668, 0x19820b20, 0xcff8ff26, 0x0500ffe0, 0xff236b82, 0x829ac4f4, 0x470522d6, + 0x829582f0, 0xfeff218b, 0xf2260983, 0xffff54b8, 0x9f8210f8, 0x5078f62b, 0xebfeff08, 0xfeff7cb4, 0x237b83b4, 0x33b3fb00, 0x530ec546, 0xfc2c090f, + 0xf4f70eb0, 0xff1554f7, 0xc275d9ff, 0xf02ca182, 0x00ff723d, 0xff00800d, 0x3233ecff, 0x27050768, 0x9a19eaff, 0xe60400ff, 0x0028f082, 0x0700802f, + 0x0300ff6b, 0x6b235782, 0x84fcffff, 0x82d020da, 0x83ff2013, 0x83862024, 0xff332534, 0x6666f6ff, 0x2106ab76, 0xa98299f2, 0x8089ff23, 0x23598200, + 0x8b0020f7, 0xe020a182, 0xf8225a82, 0x0a8266e6, 0x9a19f725, 0x85072b08, 0x00ff2308, 0x18852007, 0x0800ff25, 0x828b00e0, 0xc75c22df, 0x36b582ae, + 0xffb89e14, 0x3433daff, 0x992b00ff, 0xe5ffff9a, 0x8bbecccc, 0x828bbe08, 0x0a97360e, 0x401a00ff, 0x1400ff00, 0x00ff2a9c, 0x0800c025, 0xcc0c00ff, + 0x223382cc, 0x82b89e11, 0x610e2720, 0xf1ffff48, 0x6082c2b5, 0x4861ee23, 0x22068508, 0x830e00ff, 0x87f12a9c, 0x1100ffae, 0x088b9a99, 0x232f8ccb, + 0x5c4f0e00, 0x11213a82, 0x262f83a1, 0x285c5800, 0x82b8ffff, 0x4700232f, 0xfb6f34b3, 0xfeff3106, 0xff48a1f1, 0x9a196000, 0x8e00ff15, 0x059ab85e, + 0x66220682, 0x06827c66, 0x00800923, 0x21bd828a, 0xcc829a19, 0x8bcccc23, 0x288f8295, 0x0734331e, 0xffff958b, 0x2df582f7, 0x70bd0700, 0x81f6ffff, + 0xff088a48, 0xd68391ff, 0x2a5cf422, 0x1b233682, 0x8207cccc, 0xe1082173, 0xf822ae82, 0x3c8266e6, 0xf2821e20, 0x8219f721, 0x066b219c, 0x08823a82, + 0x83ffff21, 0xf8ff2318, 0xc58248e1, 0xb81ef729, 0xe4ffff08, 0x82070040, 0x47a12746, 0x9c0b00ff, 0x58820528, 0x8c008022, 0xde202d82, 0xf8243b82, + 0x818b723d, 0xe1222382, 0x59828ec2, 0x2105c853, 0x5e832108, 0xff343323, 0x26a68200, 0xf80e088c, 0x41156b34, 0x61200812, 0xf1201b82, 0x00249182, + 0x8bb89e11, 0x4041b682, 0x0e002209, 0x83738261, 0x82082017, 0x231782a3, 0x2e00ff6b, 0x8b281282, 0x6b8b8b08, 0x99d1ffff, 0x2207326b, 0x10b4f74b, + 0x08014302, 0x720b3241, 0x99210a3f, 0x0e43429a, 0x42b81e21, 0xc2211c43, 0x05434290, 0x42e03a21, 0x72200b43, 0x2c0e4342, 0xff056666, 0x00c01b00, + 0x00ff8b07, 0x065c4308, 0x42064d43, 0xe0271443, 0xffff8b00, 0x420020f7, 0x40211f43, 0x05434200, 0x0720c524, 0x5a82818b, 0xff482126, 0x703df8ff, + 0x08073f42, 0x02ffaf21, 0xffcccc3f, 0x0080c000, 0x7c798b15, 0xe6f1ffff, 0x088b7a66, 0x00ff066b, 0xff34b300, 0x83e65fff, 0x19002c97, 0xdcffff98, + 0xffff0080, 0x82ce4ce3, 0x82332004, 0x99dc2a19, 0xff088b9a, 0x9a99bffe, 0x211b8206, 0x8e8266a6, 0x0a57e323, 0x0a6a68ff, 0xa000ff2a, 0xff076666, + 0xc3f5dfff, 0xed222282, 0x228252f8, 0xe1faf132, 0x190e00ff, 0x089d8b9a, 0x00ff948b, 0x93060103, 0x012fe582, 0xff089289, 0xd6630001, 0x7bdf00ff, + 0x829205e8, 0x94032112, 0x013b1882, 0x8b928400, 0x938b9208, 0xfefdffff, 0x0600fffa, 0xffff9a19, 0x0870fdfa, 0x836a00ff, 0x50a2288d, 0x00ff0562, + 0x4b34b324, 0x84200581, 0x2a05d559, 0x7c540e00, 0xb31100ff, 0x6e088b34, 0x75580f1a, 0x0dfb2508, 0x3400ff07, 0xff25f982, 0x050080d1, 0x30398293, + 0x839c1904, 0xe6feffff, 0x8b088264, 0xfeff058b, 0x29e482b8, 0x00803f00, 0xf2ffff15, 0xba8233b3, 0xcd4cf524, 0x0482ffff, 0x10820a82, 0x823b0821, + 0x25198273, 0x0a00ff34, 0x188333b3, 0x00ffcc29, 0x8bcd4c0d, 0x8306db08, 0x8bcc2108, 0x1d841883, 0x0a823420, 0xcc4c0d24, 0x3182db08, 0x2c862283, + 0xf2203684, 0x3b23a583, 0x57af0e06, 0x013205f3, 0x159683b7, 0x4c0c00ff, 0x0b00ffce, 0x00ffa450, 0x4883cc12, 0xff2b0f83, 0x085caff4, 0xffff64f7, + 0x826afc3f, 0xb30930f4, 0xf7ffff34, 0x00ff9a19, 0x7d303303, 0x82fbffff, 0xf3ff24ae, 0x870833b3, 0x82cc200a, 0x83f420ad, 0xe6f72514, 0xf2ffff66, + 0x08244782, 0x04fb066b, 0x07b54218, 0x80eaff24, 0x0485ff00, 0x0080e523, 0x2636828b, 0x06666658, 0x83e8ffff, 0x8362207a, 0xb3b2261b, 0x4e00ff32, + 0x233c8266, 0xfff6a89d, 0x2605c76a, 0x1f850100, 0x820500ff, 0x030023f0, 0x0982b81e, 0xff676625, 0x82990400, 0x33042185, 0x00297a82, 0xffffffcf, + 0x9603c000, 0x069a4705, 0x6a7c4823, 0x22a68215, 0x828b3433, 0x22878305, 0x83cdccf8, 0x202c820a, 0x2089834b, 0x21a082f7, 0xc5820800, 0xccf8ff26, + 0x0800ffcc, 0xcb21a583, 0x22088506, 0x830700ff, 0x2004821d, 0x2110848b, 0x3182cb08, 0xcd212282, 0x222c85ff, 0x85333307, 0x4b08265a, 0xbcfb5b06, + 0x22578215, 0x8234b3f2, 0x05a74178, 0xb741cc20, 0x41082005, 0x00220bbe, 0x8c41b30a, 0x20538207, 0x26b78265, 0x9999adff, 0x835200ff, 0x539a20e5, + 0xf2220594, 0x498200c0, 0x0040f523, 0x212d8dff, 0xa0824c0d, 0x85c00a21, 0x00ff2b16, 0x8b00400d, 0x8000ff08, 0x49829a19, 0xda836720, 0x0a839820, + 0xe67fff27, 0x94fb0866, 0x5e8d8293, 0x0e22055b, 0x95427b54, 0xab112206, 0x77318385, 0xbf470b8b, 0x052b7508, 0xf1ffff23, 0x202478ab, 0x0834b324, + 0x5e83f38b, 0x4b229095, 0x9082291c, 0xd7e33c25, 0x84c3ffff, 0x68b42090, 0x1a410502, 0x99302f2d, 0xd8ffff9a, 0x00ff9999, 0xff666627, 0x1a41cfff, + 0xff0e2c1a, 0x9a199f00, 0x197d00ff, 0x82ff159a, 0xfff33900, 0x86eb1200, 0x0000ff05, 0x00ff0d00, 0xff46e108, 0xccccf9ff, 0xf7ffff93, 0x08208e82, + 0x20210682, 0x21ed8200, 0x5682c6f9, 0x90e2f822, 0x2008c444, 0x2e4382ff, 0xa430ecff, 0xffff7505, 0xff0020f8, 0x82c0f2ff, 0x7ee92904, 0x08748fb8, + 0xd90300ff, 0xe82e8f82, 0xff9f48e1, 0xcc4cefff, 0x661700ff, 0x16828b67, 0xb85e1729, 0x00ff9f8b, 0x82c2b510, 0x48e12122, 0x1e211782, 0x2c1682b8, + 0xff33f303, 0x54f81600, 0xe6f1ffff, 0x39098267, 0xff750080, 0x66e60700, 0x00ffeb08, 0x1566e6d2, 0x3d00ff8b, 0xffffb8de, 0x4a82ccce, 0x48213225, + 0x85c2ffff, 0x21c2229b, 0x20908247, 0x821b83cd, 0x220a8204, 0x824821c2, 0x805927b2, 0xffff0700, 0x908240ec, 0x3433e725, 0x83f3ffff, 0x4ce1259a, + 0x08698bcc, 0xb0252382, 0x00ff0080, 0x21048240, 0x0482bfff, 0x804f0023, 0x839a8300, 0x00ff2406, 0x849a993f, 0x8271821b, 0x8b082210, 0x213c85ad, + 0xac821e00, 0x00225084, 0xb1839e18, 0x6184a620, 0x8f82dc20, 0x99e6fe27, 0xffff159a, 0x206783f4, 0x29ea82df, 0xcc4ce2ff, 0xddffff76, 0x55829a99, + 0x9eddff23, 0x217182b8, 0xea8261e1, 0x0ad7152c, 0x1ef5ffff, 0x2000ffb8, 0xa48200c0, 0x4721f52a, 0xb51f00ff, 0x0b00ffc4, 0x0026a882, 0xff66e623, + 0x90831b00, 0x9a991429, 0xc000ff08, 0x8207cc4c, 0x831a2085, 0x88152011, 0x820e8204, 0x83002056, 0x00ff2106, 0xff222882, 0xbe82eaff, 0xe5ffff23, + 0x2b528380, 0x0734b33f, 0x661c00ff, 0xebffff66, 0x00280482, 0xff33330b, 0x9a19dcff, 0x09837782, 0x6666df26, 0x1701ff08, 0x0023a982, 0x82666632, + 0x3af222b4, 0x217d82e2, 0x2e82ae07, 0xff98d926, 0x52b8fdff, 0xf325c882, 0xf2ffff34, 0x2b4e8340, 0xffb8def9, 0x3433f7ff, 0x2401ff05, 0x20052c49, + 0x07735911, 0x2205e257, 0x7b7a54ee, 0x7a200518, 0x2306b874, 0xa4b0f1ff, 0xee270a82, 0xff085c4f, 0x8233dbfe, 0xf8ff218d, 0x00247e82, 0x05cccc08, + 0xf8265a82, 0x0d00ff52, 0x6e825ccf, 0xff0ad725, 0x82380200, 0x83f2206e, 0xf8f42304, 0x74820852, 0x82a43021, 0x82f02023, 0xc2fd2204, 0x82238290, + 0x0b00237d, 0x1884cc0c, 0x3bcb0826, 0x0600ff05, 0xff214082, 0x2cd983f8, 0xff323309, 0x9a99fbff, 0xb30900ff, 0x84838234, 0x820c8206, 0x0400234d, + 0x2a82f067, 0xff5c0f29, 0x10980700, 0x82dbcb08, 0x050b2238, 0x2079821e, 0x204b82cc, 0x210482fd, 0x93821400, 0x4cf1ff23, 0x22fc82ce, 0x43089a19, + 0x002d0c10, 0x0766e6d2, 0x0800ff8b, 0xffff66e6, 0x202c83f9, 0x432c8307, 0x144a070b, 0x084b4b0a, 0x2dffff25, 0x10079a19, 0x68010603, 0xff908223, + 0x12064300, 0x8b707d22, 0x3a2c0643, 0xff34331c, 0x66660d01, 0x05db4b15, 0xe1f3ffff, 0x0f00ff48, 0xffffa430, 0x82ae47e6, 0xdef32a48, 0xf0ffffb8, + 0x4b085ccf, 0x251d823b, 0xff34f3f4, 0x1d82f2ff, 0x3c020023, 0x069942ec, 0xe0cf0d2d, 0xf0f4ffff, 0x00ff08a4, 0x4200c00d, 0x142006dc, 0x3f212384, + 0x055543be, 0xc70d0023, 0x231e82f0, 0xff66e607, 0x21050143, 0xc64fdbfe, 0x614f2006, 0xff2706a0, 0xffa4b0f1, 0x54ab1100, 0x0e4d0e13, 0x82b02007, + 0x2401255d, 0x9207cccc, 0x22068743, 0x824f0600, 0x18f82c75, 0x0900ff10, 0xffff484c, 0x82f0e7fb, 0xd8632209, 0x2b66838b, 0xff8b1804, 0x62100700, + 0x470200ff, 0x05271682, 0x00ffd8e3, 0x5710b804, 0x0b220726, 0x19829a19, 0xfe42f582, 0x83f42005, 0xcc0d2a0e, 0xef0e08cc, 0x34f884f8, 0x05544115, + 0x1500ff23, 0x2dcc8280, 0x8b9082ea, 0x7de5ffff, 0x84fb0870, 0xc44ecb07, 0x08044717, 0xff34b324, 0x0483f1ff, 0xcc4cee22, 0xfe278a82, 0x0666e6be, + 0x83f8ffff, 0x4c36256b, 0xd1ffffcc, 0x00210482, 0x20208329, 0x051645c7, 0x9999c722, 0xd1253c82, 0xffffcd4c, 0x2f1b82d6, 0xe13af8ff, 0xb3c9ffff, + 0xffff0834, 0x06b8deee, 0x0bc24b18, 0xd7829083, 0x00801a26, 0x0794f708, 0x82210983, 0x21a58290, 0x0483717d, 0xb5827020, 0x8b8f8235, 0x0654f808, + 0x153b44fc, 0xcc67ffff, 0x00ff07cc, 0x4e7bd409, 0x0a250610, 0x00ff52b8, 0x2dea8307, 0xff33730b, 0xcdcc0500, 0x8300ff08, 0x48833333, 0x82cc0821, + 0xd7f8229a, 0x05b7480a, 0x28f7ff23, 0x84bb82f6, 0x82bb8206, 0xf8ff2316, 0xa582cccc, 0x3433f72a, 0xf7078b08, 0x1504fb04, 0x66214082, 0x20828266, + 0x22b88305, 0x82cdccff, 0x8209840f, 0x00ff239b, 0x558ab370, 0x07201b83, 0xff21ff82, 0x05596ef7, 0x55820683, 0x558a1682, 0x8fffff24, 0xae82cd4c, + 0x00234e83, 0x85008000, 0x0000224e, 0x82a98333, 0xdb082668, 0xccecffff, 0x257682cd, 0xff66660b, 0x1783faff, 0xcecc0a22, 0x2105954e, 0xbe830900, + 0x66e6f728, 0x9800ff08, 0xd0893433, 0x00201682, 0x34207a86, 0x3321d084, 0x82c58234, 0x883782cb, 0xffff2cd0, 0x07cdcc7c, 0x8300ffeb, 0x65153333, + 0xe7820508, 0x49060941, 0xd84909da, 0x54f72116, 0xf7236eae, 0x4a158b14, 0x0b4a0514, 0xff342208, 0x987182ff, 0x2393b3a0, 0xb4fb14fc, 0x2c276683, + 0x00ff3433, 0x83cdcc23, 0xffcc2504, 0x33332c00, 0x06846682, 0xff2a1685, 0x8b3433dc, 0xccd3ffff, 0x068508cc, 0x1182ff20, 0x04833320, 0xd3229482, + 0x2d82cdcc, 0xcd201c82, 0xdc221b82, 0x44843333, 0x5482bb82, 0x6bdb0824, 0x4918ff15, 0x42180ade, 0xb3210706, 0x82478234, 0x213d8217, 0x3082b3f1, + 0xcc4c0e24, 0x4818ffff, 0xff211012, 0x0f3d4af1, 0xcd203f82, 0x84053843, 0x0e082554, 0x7302ffef, 0x00233b82, 0x8233b3dc, 0x70093668, 0x0200ff64, + 0x00fff0c7, 0xfff85e05, 0x76de0900, 0x30fdffff, 0x3b0982a4, 0xff08d763, 0x04f6fcff, 0x350a00ff, 0xf5ffffc3, 0x00ff1078, 0xff5d4f04, 0x146ef7ff, + 0x6e212382, 0x221e8213, 0x82e0baf4, 0x85ab2223, 0x2a158205, 0x00fffce9, 0xff66260f, 0x8267f3ff, 0x660c214d, 0xf0280982, 0x00ffac47, 0x0848e107, + 0xe32c6282, 0x0b00ff54, 0xff055c0f, 0xf4dd0100, 0x28211582, 0x20398274, 0x2868823b, 0xff30080f, 0xd8a3f0ff, 0x2d4f828b, 0x8b7c14f8, 0xc7f8ffff, + 0xfaffffac, 0x658246b6, 0x82f8e821, 0x0c02210e, 0xfd221a82, 0x84829022, 0x82ae0721, 0x4cf82c6a, 0x0000ff8c, 0xffff8047, 0x820ecdec, 0x845e2409, + 0x83eaffff, 0xb8f12279, 0x272982b4, 0xffba53f7, 0x72bd0800, 0xfc2c2982, 0x00ff1639, 0xff7edf03, 0x4656f4ff, 0xe726e282, 0xf6fffff0, 0x04820040, + 0x82109721, 0xf0f82629, 0xf9ffff20, 0x2158822d, 0x6d82d6ff, 0x32c8f427, 0xda0600ff, 0x2772829a, 0xff0852f8, 0xd8230900, 0xa0212982, 0x27488284, + 0xff3e0af4, 0x6526edff, 0xb021bd82, 0x261482a4, 0xffff5278, 0x82d663fa, 0x1fc52113, 0xf7224882, 0x67821cfa, 0x820cc221, 0x409521d2, 0x2f21ec82, + 0x561e825c, 0xf92205ab, 0xd2829e4f, 0x5899f922, 0x3c201b82, 0xfc22d782, 0x7382c2f5, 0x82b09221, 0xcffb2735, 0xf7ffffe0, 0x3a82dd24, 0x82fed321, + 0x9d6f21dc, 0xe725b782, 0xfbffffe8, 0x22f182d7, 0x83cc0800, 0x90e22123, 0xf1277e82, 0xffff0a17, 0x8234f3e9, 0x707d21f1, 0x7a20cc82, 0xff273882, + 0xffff0c97, 0x8270bdff, 0x13fc2224, 0x213982f8, 0x2982e2da, 0xa019fc22, 0xe6210a82, 0x274e82a2, 0x00ff0080, 0x82981904, 0x19227882, 0x0683089a, + 0x827e0a21, 0x86eb215b, 0x89211b82, 0x217482fc, 0x7e820af7, 0x89820720, 0x83040021, 0xdff62219, 0x2240827c, 0x82b89eef, 0xe6702124, 0x73266582, + 0x0000ff34, 0xe482c836, 0xffaec726, 0xae67f3ff, 0xf6276a82, 0x00ff0601, 0x82120309, 0x07f92729, 0x0600fff0, 0x2982924d, 0x8262b021, 0xe8062129, + 0x2126d882, 0xf8ffff48, 0x29825e6f, 0x1864f922, 0xbd210a82, 0x21198270, 0x2382568e, 0xff3eca26, 0x024b0700, 0x6e222382, 0x43820814, 0x8288b621, + 0x763e217d, 0xf7274882, 0xffff9082, 0x82ecd1f1, 0x00c03077, 0x68efffff, 0x0100fff6, 0xffff9819, 0x829899ee, 0x23f42248, 0x21c282d8, 0x2982ee7c, + 0x6e92f636, 0x34fdffff, 0xfafffffe, 0xffffc5a0, 0xff0c22f6, 0x5dcf0200, 0x9c210982, 0x2253822a, 0x82f0c702, 0x829d200a, 0xe8092272, 0x212382b4, + 0x6782ceac, 0x82c27521, 0x1ec52123, 0x0b221e82, 0xf5820a57, 0x05e85b2a, 0x490800ff, 0xf0ffff78, 0x00237782, 0x82f8b30c, 0x46a125db, 0x630f00ff, + 0xf8226782, 0x72823e4a, 0x3829fd27, 0x26f5ffff, 0x22728266, 0x829c84fd, 0xe4852653, 0xb40500ff, 0x210982bc, 0x53822651, 0x82a88621, 0x828a2086, + 0x09002329, 0x0a82e690, 0x00232382, 0x821aaf09, 0x234d8223, 0x52780200, 0x78222382, 0x78820810, 0x0023d582, 0x82aec70a, 0x82052772, 0xffffff0c, + 0x248200d0, 0xff1c9a26, 0xfe560000, 0xa3210982, 0x200982d8, 0x219c84f3, 0xf582b85e, 0xff9ce426, 0x2adc0a00, 0x2e21a682, 0x20098256, 0x221382de, + 0x827e2a03, 0x61032248, 0x217c8206, 0x4882868b, 0x144e0322, 0xc6210a82, 0x261f8266, 0xffffec31, 0x82721dfb, 0x8240206d, 0x59032257, 0x22298298, + 0x82184409, 0x6c47263e, 0xd50400ff, 0x26238282, 0xffff8a21, 0x82c2b5fc, 0x703d2223, 0x210a8208, 0x0a828480, 0x82c0ca21, 0x680f2648, 0x0600fff6, + 0x212982a7, 0x1482ab0e, 0x82ce0721, 0xde0d2272, 0x211e82ba, 0x48822a1c, 0x2e520627, 0x92f7ffff, 0x2629822e, 0xff18e405, 0x8228f8ff, 0x280b2c2e, + 0xfeffffb4, 0x00ffa265, 0x8248e107, 0x4cd721c0, 0x07222982, 0x0a8290e2, 0x82eedc21, 0xec9c2bc0, 0x1b0b00ff, 0xfaffff64, 0x2382781e, 0x829ad921, + 0x8bf92772, 0x0800ff04, 0x48826a9c, 0xf4a80c22, 0xc7219282, 0x212482ae, 0x048288ab, 0x3882c220, 0x82a10a21, 0xca0c2248, 0x2748823c, 0xffe4d008, + 0x4696f9ff, 0x07222982, 0x448298ee, 0x827a3421, 0x54232124, 0xb8215882, 0x20628294, 0x225d82d1, 0x82d4ed07, 0xcf052229, 0x215e821c, 0x8c8272e8, + 0x1e824320, 0x28310a22, 0x0d21a082, 0x21cf82d0, 0x728284ab, 0x701df722, 0x77210a82, 0x2548820a, 0xff9ce408, 0xac830d00, 0xa0a50727, 0xa30e00ff, + 0x261982d6, 0x00ff3473, 0x82d8630f, 0x780a2748, 0xfcffff50, 0x2982f668, 0x80550922, 0xd0210a82, 0x20a18262, 0x216d8218, 0xa682e704, 0xc4350327, + 0x450900ff, 0x21298260, 0xc6823603, 0x0c420927, 0x0cfbffff, 0x252382cc, 0xffff8e17, 0xcf82b2f6, 0x142e0322, 0xf5277282, 0x00ff84ab, 0x827e8a03, + 0xbe052748, 0x1400ff78, 0x0f820080, 0xff14ae22, 0x2705e85a, 0xfffce9fe, 0x33731100, 0x0b214882, 0x2e14828f, 0x05d87803, 0xb32cffff, 0x43ffff34, + 0x1815cd4c, 0x58169941, 0x5420083e, 0x4923db5d, 0xff22172b, 0xb0824c70, 0x9a99bd23, 0x26d68215, 0xff81f503, 0x82140400, 0x760a224f, 0x26ef8204, + 0x00fff608, 0x8252f808, 0xfcfb22c1, 0x21eb822a, 0xc182291c, 0x48611022, 0x8f212482, 0x2fbc829e, 0xffffcc8c, 0xffb4c8ff, 0x52381200, 0x980c00ff, + 0x00232982, 0x82fafe09, 0xeefc21fb, 0x06272982, 0xffff10f8, 0x82f2b2f9, 0x9e4f2129, 0xf92b2982, 0x0600ff99, 0x00ffb8de, 0x82df8f07, 0x9b0622eb, + 0x210a82e8, 0x19828e42, 0x82aa7121, 0xc4352623, 0xb4f8ffff, 0x212382fe, 0x7282ec91, 0x7849f622, 0xc1217d82, 0x27488288, 0xff707d08, 0x162e0e00, + 0x40307782, 0x1000ff00, 0xffff0a97, 0xff68e6fe, 0xf6681100, 0x0b274882, 0x00ff28dc, 0x82d08203, 0x6d092c29, 0x0200ff92, 0x00ff02cb, 0x823a5f05, + 0xf4dd21b1, 0x2008b346, 0x225382d8, 0x821038fd, 0x82622014, 0x17f62272, 0x2123824c, 0xab823453, 0x823e8a21, 0xe23a2123, 0xf4221e82, 0xf582f6a8, + 0x059aa430, 0xc1f7ffff, 0x0f00ffcc, 0xffff6a7c, 0x09824cf3, 0xb85e0c23, 0x05b776ff, 0xc4b50722, 0x02277282, 0x00ff88d6, 0x8298d90a, 0x76022272, + 0x24538246, 0xffff5278, 0x222983fa, 0x82a4b009, 0x00802153, 0x75218682, 0x2253827c, 0x821a6ff6, 0x647b210a, 0x50211482, 0x212382e6, 0x6d82c64b, + 0x82ae8721, 0x3288210e, 0xfd271e82, 0xffff142e, 0x825238f5, 0x70fa2772, 0x0000ffa4, 0x2482ec30, 0xff666625, 0x82a8ffff, 0x66fa22bb, 0x21098268, + 0x2982ce0c, 0x9999f422, 0x1c26f582, 0xf4ffff28, 0xa682cd4c, 0x81ecd122, 0xd4210582, 0x201a827a, 0x231a82fc, 0xc4750900, 0xfc224482, 0x864e33b3, + 0xf5ff2805, 0x00ffcdcc, 0x820ce204, 0x67e6215e, 0xa8212982, 0x20298230, 0x222982f7, 0x82b8fcff, 0x33fb22ac, 0x24198233, 0x00ff2adc, 0x224e8303, + 0x821ec5f6, 0x7f0322d6, 0x2198827d, 0x4882fe34, 0x8380f02b, 0x57f9ffff, 0xf1ffffd0, 0x263e8266, 0xff3233f8, 0x8219f2ff, 0xe1f62282, 0x20488248, + 0x226783f9, 0x82146e08, 0x19fa2629, 0x0700ff9a, 0x206882d7, 0x257283f4, 0xff989901, 0x5d83f8ff, 0xf628fa22, 0xf8202982, 0xfa223483, 0xf682d823, + 0x82008021, 0xd6e326bc, 0xb30600ff, 0x21238234, 0x72826626, 0xfe740627, 0x63f7ffff, 0x22488296, 0x82ce57f3, 0xe6302192, 0x5c212482, 0x066f6029, + 0x4761f527, 0x33f3ffff, 0x22488234, 0x82142ef7, 0x66662139, 0xf8272982, 0x00ff6811, 0x8284cb05, 0x1cda2b24, 0x47feffff, 0xfaffff6e, 0x5382a430, + 0x822c1221, 0x30fa2c29, 0xf8ffffe5, 0x00ff8e17, 0x822fbd01, 0x72e82123, 0xf121a082, 0x212382ec, 0x7282e23a, 0x90e20822, 0x8821da82, 0x214882f6, + 0x68821cf7, 0x0a17f222, 0x72832e82, 0x6666f122, 0x8c261982, 0xf0ffffcd, 0x48829a99, 0x1f85f527, 0x990300ff, 0x2229829a, 0x827faaf6, 0x9e2f210a, + 0xe429a182, 0xfbffffdd, 0xffffcf17, 0x23ef82fc, 0x22bbf6ff, 0xfc2c2982, 0xffffc7cb, 0xffa4b0f6, 0x39f40400, 0xe6252382, 0x0900ff66, 0x2248824c, + 0x8267e6fc, 0x540a2272, 0x212e827b, 0x48828175, 0x8f42fa27, 0x70ebffff, 0x210f82e5, 0x9c82eb51, 0x8234b321, 0x821420a6, 0x06d2461e, 0x82856b21, + 0x00802119, 0xf62c2982, 0xffff1b8f, 0xffce4cfd, 0x48a1faff, 0x19255d82, 0x0200ff9a, 0x221382ce, 0x829899f6, 0x0a032253, 0x2668827f, 0x00ff3eca, + 0x826d870a, 0x227c8391, 0x82ec9108, 0xea912123, 0x0b211e82, 0x27bb8345, 0xff057a54, 0x04160800, 0xd920d182, 0x0c263e82, 0xffff1198, 0x098299f3, + 0xc3b50f27, 0x1ef8ffff, 0x22bb82b8, 0x82ed1cfd, 0xa4f02187, 0xfe217282, 0x229c8222, 0x8210d8f8, 0x5ac42cea, 0xf7f0ffff, 0x0f00ff4c, 0x828ba65b, + 0xeb072d4f, 0x00ff8b85, 0xff523807, 0x78490500, 0x17216582, 0x220e820a, 0x820836fe, 0xeedc210a, 0xf8218482, 0x2c6a8252, 0xff75b307, 0x02b9ffff, + 0x321300ff, 0x2b0982f2, 0x00ff7ca1, 0xff29dc15, 0xca460e00, 0x08272982, 0xffff0a97, 0x82e630f7, 0xc6032229, 0x2ae882e9, 0x00ff8420, 0xffbba90b, + 0x8218faff, 0xc0092774, 0x0900ff00, 0x2982ee68, 0xdf0f072c, 0xd20600ff, 0x0000ff6e, 0x2382bb29, 0xffd03726, 0x6625f9ff, 0x07217282, 0x20b382ae, + 0x225383f6, 0x827c5f09, 0xf50b2548, 0x1200ffc3, 0xff23dd82, 0x825c4ffe, 0xae87213e, 0x9c20a182, 0x12207282, 0x2105ed41, 0x67826606, 0x82763e21, + 0x3e6a26d2, 0xd0fdffff, 0x211e8222, 0xd2835238, 0x62b00622, 0x0622d282, 0x1b82a866, 0x8212c321, 0x3e0a2104, 0x6d217382, 0x277e8292, 0xff182604, + 0xeae50800, 0x33213a82, 0x21dc8233, 0xb7820080, 0xff991924, 0x8b420400, 0x34332105, 0x19210a82, 0x217e8299, 0x9482e60e, 0x9a191622, 0x2482f182, + 0x830b0021, 0x66002104, 0x00221382, 0x48823333, 0x82ec0321, 0x24f722ad, 0x222982dd, 0x825ffa03, 0xf0272144, 0x7f274e82, 0xfbffffff, 0x829466e6, + 0x67e62173, 0x6f282082, 0xffff34b3, 0x156666e2, 0x2205b84b, 0x4bf1ffff, 0xcd2005c8, 0x12239f82, 0x82089999, 0xab112206, 0x08306485, 0x77ff7b21, + 0xf77105b1, 0x8b85210e, 0x54213e82, 0x232d827b, 0x6766edff, 0x49844485, 0x21050d4c, 0x5e82ebdb, 0xfc29f722, 0xf8252582, 0x00ff04d6, 0x230a8307, + 0x04d60800, 0x06823082, 0x11848820, 0x78210483, 0x210e82ff, 0xbd828b04, 0x7a821c82, 0xff242882, 0x88d6f8ff, 0xf7223882, 0x2d827829, 0x82f7ff21, + 0xf8ff21ff, 0x82064e4e, 0x33332cd4, 0xaf0e088b, 0x01ffb3f8, 0x829a1959, 0x49fc2c65, 0x0c00fffc, 0xffff8e82, 0x4f80caf2, 0xff280501, 0xffd463f3, + 0x5c4ffcff, 0xf022ee82, 0xff8248e1, 0x501e8521, 0x003706db, 0xff68a614, 0xea11efff, 0x7d1000ff, 0xebffff70, 0x00ffe27a, 0x823e4a0a, 0xc8032280, + 0x27f58272, 0xff05c275, 0x1a4f0300, 0xa3215382, 0x218a82d8, 0x09825a64, 0xfff4e826, 0x1c4ff3ff, 0x47211882, 0x225382ae, 0x82703df3, 0x230f820a, + 0x0a17f3ff, 0x65212382, 0x216d8260, 0x2382c4b5, 0x82006021, 0x82fc201e, 0xf1ff231e, 0x728248a1, 0x920df627, 0x560000ff, 0x307282fc, 0xffff1cba, + 0xff028fff, 0xce8cd7ff, 0x38f4ffff, 0x222982ba, 0x82f2b2fb, 0xae07215d, 0xfb222982, 0x0a821098, 0x82cc4c21, 0x564e2644, 0x820600ff, 0x20d08290, + 0x210482c2, 0x728487fb, 0x8266a621, 0x06a124c6, 0x83f9ffff, 0x7df2273e, 0x0400ffb2, 0x2d82d663, 0x8214ae21, 0x4d0422bb, 0x210a8292, 0x4882c4f5, + 0x8266eb21, 0x1cf73129, 0xecffff6a, 0xffffa470, 0xffbe3ff5, 0x5278edff, 0xcf221e82, 0xac82085c, 0x82c21521, 0x9a9921f0, 0xf7222982, 0x0a823433, + 0x7d347327, 0x230200ff, 0x05ab4bd8, 0x35f8ff23, 0x222582c2, 0x820080f5, 0x142e252a, 0xccfdffff, 0xf1279282, 0x00ff3233, 0x8267e607, 0xb0872123, + 0x07226e82, 0x0a829af9, 0x82b85e21, 0x06ef2144, 0xec826e82, 0xf0ffff2f, 0xff7b0080, 0xcdccf1ff, 0xe6eeffff, 0x26448266, 0xff66e6f4, 0x83190800, + 0x234f836a, 0x32b30700, 0x19211f82, 0x21548299, 0xb84534b3, 0x66f52106, 0xf8222983, 0x4f828340, 0xffc47526, 0xec510200, 0x35212382, 0x219882c0, + 0x23828e97, 0x82ce4c21, 0x170b276e, 0xf7ffff0a, 0x6e821bef, 0x6025f422, 0x7e21ce82, 0x202e82f9, 0x21148297, 0x938266ec, 0xd763f727, 0x66ebffff, + 0x27728267, 0xffeb11f3, 0x566e0400, 0xf3222982, 0x0a82cd8c, 0xff7d3f35, 0xae87f2ff, 0x75f9ffff, 0xfbffff81, 0xffff70bd, 0x829ca4f3, 0xb5fb2229, + 0x250a82c2, 0x00ff769e, 0xcc829906, 0x0482f220, 0x660c0022, 0xfb22cb82, 0x728232b3, 0xcd0c0d22, 0x86212e82, 0x214882a8, 0x5e8223f4, 0x86abd526, + 0xd70000ff, 0xf2227282, 0x0982ea91, 0xff48a126, 0x7cd4f5ff, 0xf0204882, 0xff236782, 0x821a6ffb, 0x68f32729, 0xfcfffff6, 0xb7827e4a, 0x5383d920, + 0xffcad626, 0x71bd0300, 0x7d216782, 0x2b538270, 0xff920d04, 0xd863f2ff, 0x0c0e00ff, 0xfa273882, 0x00ff0040, 0x82856b0b, 0x146e2123, 0x0f221e82, + 0xb0821f05, 0x05e67022, 0x26059b4a, 0x3ecaebff, 0x821000ff, 0xefff2804, 0x00ffe07a, 0x82c3f514, 0x727d2172, 0xfc273982, 0xffffe325, 0x820040f1, + 0x7dfd2b72, 0xf7fffff3, 0x00ff3854, 0x72821905, 0x0482eb20, 0x66140024, 0x4f828b66, 0x5c8f0a26, 0x0900ff8b, 0x0028a982, 0xff8c0c07, 0x3dca0200, + 0xa6215982, 0x221a82a8, 0x82e5d003, 0x48a12184, 0x332a6a83, 0xffffff33, 0x00ff7c9f, 0xfd82a619, 0x8281ff21, 0x281d271e, 0x1300fff6, 0x0a82020b, + 0x82730b21, 0x42f4221e, 0x2b298290, 0xff790905, 0x04d6faff, 0x8d0f00ff, 0xf827c882, 0x00ffbe1f, 0x8270fd0c, 0x3e8c2104, 0x09222982, 0x6d827e6a, + 0xff941826, 0x8e370000, 0xf6265d82, 0xf6ffffc8, 0x138272dc, 0x82b85e21, 0xcff322b3, 0x2029825c, 0x23b38280, 0x14ce0700, 0x4a200a82, 0x0527dd82, + 0x00ff48c1, 0x820ad70d, 0xcc8c219c, 0x452c5782, 0x00ff081e, 0xff9e2f01, 0x641b0700, 0xe5260982, 0x0600ff60, 0x1e82d0d7, 0x82741321, 0x00c02109, + 0x0a2f1e82, 0xfffff6a8, 0xff1203fb, 0x00800400, 0x83fdffff, 0xf5062228, 0x22f183c2, 0x8208ec08, 0x890827f1, 0x0500ffba, 0x20829c04, 0xffce0c26, + 0x6e920800, 0x05273582, 0x00fffe94, 0x82cccc0b, 0x80e521c1, 0x17269d82, 0xf4ffff0c, 0x28821c1f, 0x825c8f21, 0x45f4229d, 0x210a821e, 0xe6826a7c, + 0x0a17142a, 0x9e1d00ff, 0x1900ffb8, 0x00232e82, 0x82d8230f, 0x828c20d1, 0x59002348, 0x2482089a, 0x82e23a21, 0xa4302139, 0x05222982, 0x0a82e445, + 0x0d221f83, 0x5882c0ea, 0x00238e82, 0x82d6230c, 0x8e422123, 0x0b222982, 0x0a829a19, 0x826c4721, 0x0a5721b8, 0xf021e682, 0x212382e6, 0x8682c2b5, + 0x82c2f521, 0xa4fa2772, 0x0c00ff56, 0x48835a2d, 0x82207021, 0x828320ec, 0x6c0522d2, 0x21098208, 0x3882e690, 0x0023e682, 0x8268f100, 0x8310200f, + 0xcc022187, 0x0f220982, 0x4d827c14, 0x8279a921, 0x2267834d, 0x82bd1409, 0x540d2714, 0xf3ffff7a, 0x4882e1fa, 0xfc49092d, 0x9af7ffff, 0x0f00ffe1, + 0x82ffbc14, 0xffbc2a9c, 0x862b0900, 0x160a00ff, 0x22298246, 0x8262d008, 0x14ae210f, 0x42301982, 0x0e00ff0c, 0xffffa4f0, 0xff2646f6, 0x90c20800, + 0xf3229182, 0x9c82cc0c, 0x8214ae21, 0x510b2748, 0x1200ffec, 0x878266e6, 0x3e82ab20, 0xb81e162c, 0x87feffff, 0x1700ffac, 0x4882c435, 0x5ccf0f27, + 0xae0400ff, 0x2c298256, 0xff64900c, 0x70bd0300, 0x190700ff, 0x2597829c, 0xffff3433, 0x48824cfc, 0x00800c2b, 0xfff3fb08, 0x66e6f6fe, 0x08e55415, + 0x18008021, 0x540b7460, 0x168608e2, 0x8506e254, 0x21288206, 0xf4590b97, 0x828b200b, 0x08185e45, 0x0983ea20, 0x6666e527, 0xf7db088b, 0x5d5f821c, + 0x5421061a, 0x21eb827b, 0x588200c0, 0x00400d23, 0x21068308, 0x11828f42, 0x8285ab21, 0x0bd721f7, 0x22081a5d, 0x8290420d, 0xd709271b, 0xf5ffff0a, + 0x58828f42, 0xd7a3f322, 0xff282d82, 0xff33b3f2, 0x3233f6ff, 0x4c221682, 0x0e82ffcd, 0x088b3437, 0xf714f80e, 0xf7cb1534, 0xffff0554, 0x069a9992, + 0xcce1ffff, 0x203282cc, 0x22e982e5, 0x82571300, 0x66f62842, 0x1c00ff66, 0x8208f6a8, 0x210a843b, 0xaa8286ab, 0x54211e84, 0x822e857a, 0x8272201a, + 0xfbcb2b3b, 0x94f705b4, 0xfb14fc06, 0x42821554, 0x09d85e18, 0x3282f120, 0x21056747, 0x6b7c54f8, 0x0a786f0c, 0xfc07cb2a, 0x074b0694, 0x94f774f8, + 0xd72ff082, 0xff065c0f, 0x86abeaff, 0x00ff054b, 0x5e1e450e, 0x79550c99, 0x2066820a, 0x054147f7, 0x83ffcc21, 0x54ff2016, 0xfb21058b, 0x223d82f4, + 0x82f628f7, 0x0717561e, 0x2005b554, 0x24068508, 0x280700ff, 0x820482f6, 0x08002a3a, 0x088b0ad7, 0x380f00ff, 0x25338252, 0xcbaec7f1, 0xe27a5a05, + 0xf1ff220c, 0x07aa7ab3, 0x0714fb23, 0x08067af8, 0xff33b322, 0x34201a82, 0x4c2d9e82, 0xeeffffcd, 0x088bcc4c, 0x02ffaf0e, 0x22538338, 0x8234b36f, + 0xe1f231c4, 0x1100ff48, 0xffff5ccf, 0xffe0fae6, 0x9ad90300, 0x352b2782, 0xf2ffffc4, 0xff081acf, 0x824c88ff, 0xd4a729b3, 0xffff057c, 0x06666687, + 0x4021ba82, 0x22b08284, 0x82e2a5f9, 0x00402199, 0xbd21a983, 0x21b08470, 0x118400c0, 0xd9210487, 0x23b0839a, 0x0600404e, 0x1921b682, 0x2528829a, + 0xff66a60f, 0x6e830a00, 0xb89e0222, 0x37821482, 0x40266f82, 0xffff9f00, 0x8483a1f0, 0xff486126, 0x0080ecff, 0xff233782, 0x8248215f, 0xe6e5226b, + 0x256b8266, 0xffe2fae4, 0x5e82f6ff, 0xffeaff2f, 0xff087aff, 0x0080d1ff, 0x42daffff, 0x20938290, 0x224983c8, 0x82a6e600, 0x26f8280a, 0xffff8ba8, + 0x82bebff8, 0xcecc21a3, 0xf7220a82, 0x2c82cc4c, 0x1e05a023, 0x210c8307, 0x9983162e, 0x80414220, 0x07002305, 0x668258d9, 0x195a0123, 0x229e829a, + 0x82ae0716, 0xe315229e, 0x372182d6, 0x00ff2030, 0xffb0c711, 0xfe140d00, 0x8700ff08, 0x00ff9819, 0x051e8563, 0x2206ef49, 0x822a1c0d, 0xcccc27b3, + 0xf2ffffa4, 0x2a8268e6, 0x08cecc2f, 0xcc67feff, 0xa000ffcc, 0xcb15cc4c, 0x06b76006, 0x4a823320, 0x83333321, 0xffcd256c, 0xcdcc0800, 0x22058266, + 0x82cccc08, 0x06b76068, 0x0a823320, 0x08231982, 0x82cb07cb, 0x097a4983, 0x600aa849, 0xd62105d2, 0x49478288, 0x782005c1, 0x2925db82, 0x4b088bfc, + 0x831a8a06, 0x2907217c, 0x33211a83, 0x821a8334, 0x82332023, 0x06b0495c, 0x2308c749, 0x064b074b, 0xd7221a8d, 0x10828b0a, 0x08f62822, 0x20096c61, + 0x82b48507, 0x25b484ce, 0x54f8ef0e, 0xa882159b, 0x00400e22, 0x8c30c782, 0x0d00ff08, 0x00ffd8e3, 0xffa6bb0c, 0xf4680600, 0x27320f82, 0x00ff5c8f, + 0x055c8f10, 0xa30f00ff, 0x2500ffd6, 0x0a821e85, 0x04760427, 0x090900ff, 0x21258278, 0x048230fd, 0xff40552b, 0xe0fa0700, 0xdc0300ff, 0x2834822a, + 0xff0c1700, 0xd823c400, 0x255a8205, 0xff84ab11, 0x0482f1ff, 0x540e0028, 0xeeffff7c, 0xe55d7c54, 0x827c2005, 0x1816839c, 0x240cd051, 0xfb02fcff, + 0x28358204, 0xfc29f7ff, 0xdaf8ffff, 0x051a411c, 0x2bf7ff23, 0x83358302, 0x21118206, 0xee4a12c3, 0x00ff260b, 0xf7cc1000, 0x216b8a44, 0x6b87ff86, + 0x6410515e, 0xff250802, 0xbeefffff, 0x863583fb, 0xdee4216b, 0x2a216b87, 0x826b847e, 0x21118206, 0x6b82cebc, 0xcc413320, 0x236b8207, 0x64f79a19, + 0x1c7e6b85, 0x206b8206, 0x91d7837a, 0x4486206b, 0x08200580, 0xe6226b82, 0x3583fb66, 0x33f7ff23, 0x21548233, 0x3a4266e6, 0x0eb45805, 0x9132b321, + 0x20d78b6b, 0x20d78885, 0x0543417b, 0x07624118, 0x2f0b4341, 0x9a99e8fe, 0xc4ffff07, 0x00ffcd4c, 0x0532b33b, 0x73826982, 0xcc07002b, 0xf5ffffce, + 0x00ff33b3, 0x227d8303, 0x83cdccf5, 0xaeea2242, 0x22a38214, 0x82eb51ed, 0xcccc21c0, 0xe9230a82, 0x82083433, 0xc5f52206, 0x2128821e, 0x3282f0e7, + 0x8290c221, 0x63d02194, 0x26084682, 0xff08a430, 0x9a197100, 0xe68effff, 0x00ff0566, 0xffaec725, 0x142edaff, 0x4c3200ff, 0xebffffcc, 0x00ff3433, + 0x82666635, 0x00240857, 0x0634b325, 0xb82a00ff, 0x00ff8b52, 0xffa43027, 0xec510f00, 0x7d1e00ff, 0x1900ff70, 0xff08f668, 0x74f3f6ff, 0xc5216082, + 0x229e82e4, 0x82c03ff1, 0xa0652b61, 0x66f7ffff, 0x0d00ff66, 0x3482cecc, 0xcc4c0e22, 0x9d2b2582, 0x00ffcccc, 0x1566663c, 0x82e2ffff, 0xf4ff235d, + 0x30820080, 0x7a94f322, 0x38210f82, 0x300a8252, 0xff2085fe, 0x48e1fdff, 0x4cffffff, 0xffff8acc, 0x05115cfe, 0x0c820683, 0xff566e26, 0x7efe0000, + 0x64261c82, 0x0100ff18, 0x52829239, 0xf893f322, 0xae218882, 0x273c8256, 0xffc235e2, 0x866b0c00, 0xfd220a82, 0x2a82d8e3, 0xff215783, 0x228382e6, + 0x8234b300, 0x82022083, 0x21068283, 0xb5825d01, 0x00fe0022, 0x9a214182, 0x2104821e, 0x2a828237, 0x08289c2b, 0xca1d00ff, 0x0b00ff7e, 0x83c48285, + 0x210f8346, 0x4685053e, 0x1c020023, 0x212a8228, 0x0e829a99, 0x04821920, 0x16410120, 0x82068305, 0x28912116, 0x02209282, 0x6a204684, 0xc521a682, + 0x214b82f0, 0x9c826c0c, 0x8e37e222, 0x1d244082, 0xffff3eca, 0x0a82e482, 0xa2820120, 0x6bffff24, 0x26828c86, 0x36824282, 0x08008023, 0x22f2828b, + 0x848a34b3, 0x211782f3, 0x0482cccc, 0xff2f1682, 0x3433f2fe, 0x999300ff, 0x00ff159a, 0x82ea4602, 0xaa0222ba, 0x216e827f, 0x0482f0a7, 0x82190421, + 0x020b2114, 0x14276982, 0x00ff33b3, 0x8248a131, 0xa631215e, 0x1422ec82, 0x0a82c2b5, 0xe9060222, 0x03212582, 0x21048296, 0x2a82afa7, 0x0982ae20, + 0x06010022, 0x43210982, 0x22998214, 0x82e21aff, 0x904d210a, 0x33207482, 0x02233e82, 0x82899a99, 0x9a192129, 0xce211a82, 0x27448366, 0xff059a99, + 0x8f42ebff, 0xb3215a82, 0x220a8232, 0x82e1fafe, 0xce0c2130, 0x5721ab82, 0x822a820a, 0xfdff2469, 0x828b52b8, 0x82068330, 0x7b542116, 0x5921b782, + 0x2104829a, 0x0e8270fd, 0x8232f321, 0x4ceb271a, 0xceffffcd, 0x40826866, 0xe15ace22, 0x4c215082, 0x220a82cc, 0x8217f9fd, 0x66e62125, 0x57210482, + 0x822a82fd, 0x24878270, 0xfeffff00, 0x22808299, 0x82010000, 0xbcfd220a, 0x216582ee, 0x1e8279a8, 0x821a4f21, 0xa8062179, 0xfc221e82, 0x8f82086a, + 0x82ec9121, 0x7c542148, 0x1422e482, 0x5e821fc5, 0x827b5421, 0x0301220a, 0x06d94aa3, 0x85ab0222, 0x78822a82, 0x47020023, 0x269f82ae, 0x98192f02, + 0x821564fb, 0x00ff2161, 0x46204882, 0x58217683, 0x210982d0, 0x318250ad, 0x8250f821, 0x18042166, 0xce27ab82, 0x00ff146e, 0x8286ab14, 0x3aeb22a0, + 0x216782e0, 0x0a8284ab, 0xbcd3ff22, 0xfd212082, 0x212a82f4, 0x09826466, 0x8234b321, 0x34b32109, 0x1021f785, 0x200c828b, 0x22ed8252, 0x821659fe, + 0xe8fb2173, 0xf4210e82, 0x20f784fe, 0x219882cc, 0x4082b85e, 0x285cce22, 0x4a21ae82, 0x87f7843e, 0x58fe2225, 0x212a8252, 0x94823e55, 0x82fafe21, + 0x8fb92009, 0x823820f7, 0xd84e2114, 0x0620a482, 0xfc21ae83, 0x20f7896c, 0x20f7847a, 0x205e8220, 0x220a8354, 0x82301301, 0x44002179, 0x99212a82, + 0x2109829c, 0x0982cc4c, 0x82cc4c21, 0x0200249f, 0x828be846, 0xf0a7210c, 0x20083342, 0x09334218, 0x33423420, 0x82682009, 0x053342f6, 0x82400021, + 0x9e0f252a, 0xcc0000ff, 0x99214683, 0x0635439a, 0xf8af0e29, 0x1514f834, 0x181100ff, 0x2008b757, 0x05a57500, 0x1ec51022, 0x2005fe50, 0x9c581884, + 0x457c2008, 0x8421153c, 0x2017838b, 0x242d827c, 0xe23aefff, 0xe04418ff, 0x69842007, 0xff3206db, 0x98196700, 0xff15a4fb, 0x68e660ff, 0xfbffff06, + 0x3082fe94, 0x026bfc25, 0x830300ff, 0x0400230a, 0x3b82026b, 0x11840683, 0x15820486, 0xf7088b24, 0x4f820614, 0x825ccf21, 0xae0b32ad, 0x0d00ff14, + 0xffff866b, 0xffce0cfd, 0x0a570f00, 0x360a8208, 0x00ff1acf, 0xff66660b, 0xdc59f5ff, 0xd70700ff, 0xf4ffff0a, 0x828b6666, 0xe638221a, 0x223b8266, + 0x820a172f, 0x5c0f2786, 0x0c00ff05, 0x2945f6a8, 0x07002105, 0x0d251483, 0xffff1a6f, 0x220983fc, 0x82a4b00c, 0x0ffc222f, 0x262382e0, 0xffffb89e, + 0x8272a8f2, 0xec11264a, 0x40f3ffff, 0x21238200, 0x1e826626, 0xcd4c942b, 0xc5deffff, 0xffff051f, 0x05d54fcc, 0xff696726, 0xccccd0ff, 0xcb22cb82, + 0x21820080, 0x9a59e637, 0x2400ff07, 0xffff5278, 0xffe690f8, 0xae871b00, 0xafdfffff, 0x2220821a, 0x82b85ed9, 0xf5ff23e1, 0xb2823e4a, 0x8298ce21, + 0xcccc21ad, 0x292c5882, 0xf6ffff78, 0xff08f6a8, 0x8a211200, 0x1434b882, 0x1500ff7c, 0xffff9919, 0xffcc4cf9, 0xcdcc1600, 0x64f7088b, 0x22380041, + 0x4166e6a0, 0x8020696d, 0x34206cb1, 0xf882d994, 0x3a06da41, 0x00ff90c2, 0xffa4700b, 0x6866f5ff, 0xcc0700ff, 0xf4ffffcc, 0x088b6466, 0x8330ffff, + 0x999d2d10, 0x00ff159a, 0xff0c8205, 0xf6a80100, 0x7b260982, 0x0000ff64, 0x09829ccf, 0x82908221, 0x06002425, 0x828b78a9, 0x702b080c, 0xfeffff22, + 0x00ff80aa, 0xff48e106, 0x1cdafdff, 0x0f00ff08, 0x00ff285c, 0x052a9c30, 0x760400ff, 0x0e00ff04, 0xffffb81e, 0x8210b8f6, 0x162e2619, 0x7df0ffff, + 0x21548272, 0x6a825ccf, 0x5278f422, 0x58210a82, 0x2b858210, 0xffffec51, 0xff8636f8, 0x0080fcff, 0xee218a82, 0x271e82da, 0xff9a19eb, 0x7ad4bdff, + 0x10224882, 0x4d829819, 0x8294f821, 0x83b8200a, 0x66d22220, 0x189f8266, 0x200c5f6e, 0x238f8271, 0x08299c19, 0x2a240684, 0x82eaffff, 0x1627e282, + 0xffffd663, 0x82707de5, 0x850684b2, 0xebff2316, 0xe34d6666, 0x212d8205, 0x5082e5ff, 0xa1630020, 0x22098305, 0x8200801a, 0x6dfe282d, 0xffff66a6, + 0x8234b35d, 0xcc002766, 0x0000ffcd, 0x04823233, 0x8271bd21, 0xce4c2104, 0xcf210482, 0x8213845c, 0xb01923ef, 0x748207a4, 0x862b4336, 0x072b00ff, + 0x3b00ffae, 0x00ffad87, 0xffec1140, 0xcd4c1500, 0x49212082, 0x223a82b3, 0x828ec216, 0x262227bc, 0x6c00ff66, 0x0a829a19, 0x82750431, 0x1e0e00ff, + 0xf6ffffba, 0x00ff92b8, 0x41142e0f, 0x7a260d1b, 0x0100ffe2, 0x276d0a57, 0xf8ff2305, 0x1b41c235, 0x08162408, 0x82deffff, 0x95ff2eaa, 0xff055c8f, + 0x02abfeff, 0xc9fbffff, 0x2604827a, 0xffff8981, 0x82fca9fd, 0x38c92109, 0x54213d82, 0x222982fc, 0x820ad7fb, 0x2851210a, 0x99211982, 0x05ca509a, + 0x66010022, 0x04238682, 0x82083233, 0xb95e26b1, 0xcc8900ff, 0x13ad41ce, 0xf1829184, 0xad410120, 0xffeb2510, 0x0436f8ff, 0xef219187, 0x2067825c, + 0x22f082d0, 0x824c68ff, 0xfeff2348, 0x82829999, 0x82cccc21, 0x22a68304, 0x8234b3fd, 0xcdcc2109, 0x4c218682, 0x202982cc, 0x200a85fb, 0x833e82ce, + 0x82042009, 0x02002323, 0x9b823333, 0x26259184, 0x00ff5c8f, 0x0623417a, 0x3f428120, 0x41932008, 0x918e0823, 0xff9a5926, 0xcd4cf5ff, 0x35219182, + 0x082341c4, 0x67821420, 0x3d0ac428, 0x3342ffff, 0xfa820533, 0xff85eb26, 0xffff3100, 0x0022e582, 0x3c500a17, 0x51f53106, 0x0a00ffeb, 0xffff66e6, + 0xffe1baf2, 0x9a190000, 0xf2283482, 0xff8b1ec5, 0x8f82f4ff, 0x66205482, 0xff211a82, 0x22eb82d1, 0x8234b3f2, 0x4c8f231a, 0x268207ce, 0xffc3b53e, + 0xfe7fd3ff, 0x0c1800ff, 0xd8ffffcd, 0x00ffcecc, 0xffd7e324, 0x0080eaff, 0x1200ff08, 0xe2238e83, 0x4215cc4c, 0x16820577, 0xfb654a83, 0x63e62305, + 0x5c8208d6, 0xff2c0682, 0x717d1500, 0x9ce9ffff, 0x1a00ff2a, 0x42055143, 0x14230acc, 0x828b9a99, 0x854f8217, 0x825b8406, 0x00802132, 0x80335482, + 0x0e088b00, 0x6601ffef, 0x00ff9a99, 0x156666fc, 0x829100ff, 0x89ff230a, 0xdd8266e6, 0xb81e0c35, 0x02f6ffff, 0x0700ff0c, 0xffff4861, 0xff8480f2, + 0x829e0200, 0x82f12213, 0x289d828e, 0x06b89e51, 0x991100ff, 0x20588298, 0x234e820d, 0xd8630e00, 0x10820a82, 0xa0221c82, 0x70180c97, 0xab2009cb, + 0x0e283882, 0xffffea51, 0x8be43aef, 0xa03cfc82, 0xff0668e6, 0x1e05d7ff, 0xf52800ff, 0xc8ffffc2, 0x00ff866b, 0xff200517, 0x5c0fc6ff, 0xf7222083, + 0x20821263, 0x38060d75, 0xffff5278, 0x857cfffc, 0xa1faffff, 0xffff0808, 0xff5c8fa2, 0x146eaaff, 0x26c08205, 0x00ff9ba4, 0x824a2c13, 0xcc5027ac, + 0x4900ffcd, 0x1582d6e3, 0x6666f927, 0x020000ff, 0x280a8290, 0x8b1f85d4, 0x4ad6ffff, 0x2bbe823d, 0xffff0a57, 0xffd763dc, 0x5238e8ff, 0x85274682, + 0x00ff9919, 0x827c5460, 0x9cfb2625, 0x0300ff29, 0x267f8270, 0xffaec7fa, 0x82ac0100, 0xd7fa221e, 0x2289830a, 0x8200e0f8, 0xeff82140, 0xfc2c7282, + 0xffff10d8, 0xffae47fb, 0x10f8f9ff, 0xf7252182, 0xffff21d0, 0x2c8c82f5, 0xdfcf0100, 0xe8f0ffff, 0x0a00fff6, 0x2d09826f, 0x087cd4f7, 0x045002ff, + 0x2ffeff9c, 0x9b82acfc, 0x00800a2c, 0xccf7ffff, 0x0f00ff0a, 0x5f825c0f, 0xff00e026, 0x48210800, 0x67222e82, 0x0a8208ee, 0x82e02f21, 0xa470260a, + 0x30feffff, 0x20238220, 0x21a88217, 0x098290f5, 0x862b0822, 0x78206782, 0x00233d82, 0x8232336a, 0xd3ff2ca8, 0x0900fffe, 0xffff0416, 0x820662fc, + 0xaaf12938, 0x66f8ffff, 0x0600ff24, 0x6a272984, 0x00ffcccc, 0x18333379, 0x2207045a, 0x82717df5, 0x55e6210a, 0x14226e82, 0x888296ee, 0x90824127, + 0xd93b00ff, 0x200a829a, 0x22558306, 0x82fade05, 0xb81e2c79, 0xa0ffffff, 0xffff9100, 0x826c67fa, 0x1905228f, 0x20e3829a, 0x22608281, 0x82666600, + 0x42e021e2, 0x66221982, 0x8b828566, 0x52f8e42b, 0x5ee6ffff, 0xfeff05b8, 0x2d1b82b9, 0x00804400, 0xeeffff15, 0xff8b6666, 0x5182f2ff, 0x99f1ff23, + 0x220a829a, 0x82f668ee, 0x3360232c, 0x0c850732, 0x230b5d76, 0x8b33b310, 0x72276482, 0x00ff3333, 0x823a1200, 0x835a208a, 0x26ae2238, 0x2b0a8266, + 0xff01801b, 0x48a1e9ff, 0x402800ff, 0x0420b582, 0x15270483, 0x00ff9859, 0x82b85e1b, 0x83122034, 0xc0f022aa, 0x21298200, 0xb582de0f, 0x66e6f325, + 0x821700ff, 0x0100233e, 0x25829a99, 0xfade0f22, 0x27082582, 0xff1e050d, 0xae071000, 0x8efeff05, 0x01ffba9e, 0x05523a22, 0x11f8ffff, 0x0e058beb, + 0x1f02ffef, 0x01ff9819, 0x15cccc3f, 0x00277f82, 0x20ffff0c, 0x75053433, 0x708208f1, 0x83f1ff21, 0xd910227f, 0x05815098, 0xd6e3ff29, 0xa0ffff07, + 0x82ff5ce6, 0x056622f9, 0x823084bb, 0x40f722f4, 0x21358200, 0xa682c0f8, 0x42400729, 0x0800ff8b, 0x83082ebd, 0x84e02006, 0x22048211, 0x829a3906, + 0x00c02115, 0x0820ee83, 0xff220682, 0xca820600, 0xe0f8ff23, 0x213883c4, 0xaa82a205, 0x68e6002c, 0x35f7ffff, 0xf9ffffc4, 0xa3829c99, 0xffcccc26, + 0x6466f6ff, 0xfd263182, 0xff88e6b0, 0xa683df00, 0x4c00ff29, 0x00ff07ce, 0x829a193f, 0x96f42182, 0x1120fc82, 0x0e204d84, 0x0023ac82, 0x82ae470e, + 0x84108274, 0xff46254d, 0xbc03b400, 0xc827ed82, 0x00ffe13a, 0x82c2b52b, 0xc5d7230a, 0x7082063f, 0x70fdff22, 0x3f28f182, 0xffffdfff, 0x15343330, + 0xf7211182, 0x83fd8242, 0xf8ff23c0, 0x7c8284c0, 0x82662621, 0xf8ff2177, 0x0c820682, 0x0720d79f, 0x8305ad52, 0x05bf5206, 0xb3f9ff23, 0x05b65332, + 0xffcb0824, 0x6282f0ff, 0x1200ff27, 0xff060040, 0x0cdf4100, 0xdf410020, 0x419a2012, 0xe62738df, 0x00ffd8a3, 0x822426de, 0x4c642ae6, 0x01ff07ce, + 0x8034336f, 0x062b6415, 0xdc19092c, 0x5dfcffff, 0x0800ff0e, 0xd282f0f2, 0xff4e6229, 0xa4300600, 0x43ffff08, 0x19210528, 0x0e28439a, 0xfff66831, + 0xeb111400, 0x4100ff05, 0x00ff7c54, 0x433eca3b, 0x40200d28, 0xff2cbc82, 0x00ff00a0, 0xffb8de05, 0x0681f9ff, 0x23162c43, 0x850080f9, 0xe5276582, + 0xffff48e1, 0x824821e8, 0x0a554544, 0x82e00221, 0x81fd2545, 0x0200ff06, 0xff224a82, 0x4f8280fd, 0x83600221, 0x83412013, 0x57c2234f, 0x1b45078c, + 0xc475210c, 0x21071b45, 0x1b451e05, 0x1a0f310a, 0xf8ffff8b, 0xffff0e4d, 0xffae07fd, 0xd823faff, 0xa4210482, 0x2e768218, 0xff0b82a2, 0x8c8ca9ff, + 0xe6ffff05, 0x829f9a99, 0xd950277d, 0x4900ff99, 0x118286eb, 0x9a59f923, 0x202882ff, 0x220a82e0, 0x82ae87d4, 0x4fd62c42, 0xf2ffff5c, 0xffffec51, + 0x82295cdc, 0xe03a21ae, 0x85274282, 0x00ff291c, 0x824c5760, 0x99fb2125, 0x03223b82, 0x3482e06f, 0x21101b45, 0x408248e1, 0x9eeff824, 0x1b45ffff, + 0x45f02006, 0x91220d1b, 0x1b45ff28, 0x66e63606, 0x700a00ff, 0xf7ffff21, 0xff087ad4, 0x98194f02, 0xe630feff, 0x091b4568, 0x1b450820, 0x45f02012, + 0x7931211b, 0x00ff3448, 0x05786969, 0xf4f8ef0e, 0xe65800ff, 0x09555766, 0xff004026, 0x0040f5ff, 0xf223a282, 0x850800c0, 0x20858206, 0x571685c0, + 0x22830955, 0x820a0021, 0x57048316, 0x3f840a83, 0x86cc4c21, 0x4ef22032, 0x7d210570, 0x08708233, 0x9a195427, 0x00ff7615, 0xff48212f, 0x9082e4ff, + 0xab6800ff, 0xe7ffff84, 0x08ae4861, 0x82d9ffff, 0x3600ff8e, 0xffffec91, 0x21f583c0, 0x2482a121, 0x9a99bb23, 0x2a1a828b, 0x8b66e6d5, 0x358b2105, + 0x83218b35, 0x82c7208f, 0x18002161, 0xff267882, 0xff6626cd, 0x0e822700, 0xb3dcff23, 0x361a8334, 0x0566e64e, 0x19df00ff, 0x07ab069a, 0x024000ff, + 0x00ff0690, 0x82486123, 0x9e1c249d, 0x8200ffb8, 0x220a8204, 0x82e27a22, 0xe3a02654, 0x0000ffd6, 0x212f82e6, 0x6618eeff, 0x066513a0, 0xfa5f2418, + 0x82ff06e2, 0xab3c2100, 0x1f226a82, 0x628270fd, 0x0c221722, 0x0f252e82, 0x00ff0080, 0x33bc8217, 0x9a99f6ff, 0x191500ff, 0xffff089a, 0xbecccc72, + 0xeeffff15, 0xff218483, 0x7b8483f1, 0xff210f01, 0x86118200, 0x102f7b04, 0x707c3283, 0xf1ff210d, 0x49845c82, 0x66eeff2a, 0xf7088b66, 0x78ffff24, + 0x220abf41, 0x416626f6, 0x0c261dbf, 0x088b9a59, 0x068300ff, 0x0b00ff24, 0x435966a6, 0x12bf410f, 0xbb14f723, 0x05f84115, 0x31942c84, 0x00223682, + 0x2f75c00a, 0x205f8205, 0x06a359ff, 0x21164d42, 0xa484cccc, 0x33255482, 0x4b088b34, 0x087e428b, 0x6826f622, 0x9820be9f, 0x9821be85, 0x20be838b, + 0x428c9468, 0x8b210d7e, 0x215edc2b, 0x3c435bcb, 0xef0e2b5c, 0x195f02ff, 0x8800ff98, 0x854166e6, 0x590c2613, 0xff8b089a, 0x22068200, 0x41f5ffff, + 0x54411585, 0xa6f3220a, 0x202d8266, 0x240682ff, 0xb30a00ff, 0x26328634, 0x8b64660c, 0x8e2b8b08, 0xaec7215e, 0x830fd643, 0xd909275e, 0xf2ffff9a, + 0xe44100c0, 0x5238210f, 0x2b0a3244, 0x00ffcccc, 0xff9c990b, 0x9a19f6ff, 0x5e839b82, 0x1700ff29, 0x154d34b3, 0x8341ffff, 0x1995291c, 0x00ff059a, + 0x06666607, 0x1e211782, 0x083e43b8, 0x82b8de21, 0x48a13033, 0x3a1400ff, 0xffff08e2, 0xff66e6eb, 0x821e2f00, 0x9ce32d14, 0x6800ff2a, 0xffff7a94, + 0xae4661e7, 0xd9251a82, 0x00ffc675, 0x17304437, 0xffff0625, 0x8266e6d5, 0x99d93691, 0xf1ffff9a, 0xffff70bd, 0xff4761e0, 0x52f8e8ff, 0xd6ffff08, + 0x22ea82ee, 0x45562e20, 0xc44a25a8, 0x0ea84509, 0x4518c44a, 0x662006a8, 0x3021a845, 0xff3c1f09, 0x4e820900, 0x19feffff, 0x0f00ff9c, 0x2ead8219, + 0xff9899f5, 0x32330800, 0xc9feff08, 0x69c13433, 0xf22008a8, 0x225cec82, 0xc5102606, 0xff8b0820, 0x24068200, 0x660d00ff, 0x21098266, 0x8e524621, + 0xc2053208, 0x0000ff0c, 0xff053a00, 0xea66ccfe, 0x32f000ff, 0x2ce882fa, 0xff9378f4, 0xcc4ce7ff, 0x5ef9ffff, 0x05c44c9e, 0x4e456e20, 0x82ff201b, + 0xffd82200, 0x095245ff, 0x1f226f82, 0xd2829a19, 0x90024022, 0xff211b82, 0x220a82be, 0x82004021, 0xf31a3c16, 0x1900ff34, 0x00ff4861, 0xff842b03, + 0x66662000, 0xf8ffff08, 0x00ff6811, 0x828e3706, 0x73a9237a, 0x268206b6, 0x6ce70029, 0xdf00ff15, 0x42c39819, 0x0e205c68, 0x2531fc82, 0x0701ff81, + 0xff159a99, 0x00b0fdff, 0x33c4ffff, 0x24a08233, 0xffff0e2d, 0x270983ca, 0xffe2fa28, 0x9a19dbff, 0x22073246, 0x820634f7, 0x8f022633, 0x80c300ff, + 0x21af8200, 0xad82ac23, 0xcc4ca022, 0xfe2c0a82, 0xffff6f32, 0xffceccf6, 0x04a6feff, 0x99210982, 0x21fa829a, 0x098283a0, 0x0129e483, 0xff7eda4f, + 0x666648ff, 0x21428215, 0x2f82bb9b, 0x66e60022, 0x04274b83, 0x0554fb8e, 0x849100ff, 0x8c1b220d, 0x324f82cc, 0xff347318, 0x48a11100, 0xb50800ff, + 0x1a00ffc2, 0x82084821, 0xe4782674, 0x3d0400ff, 0x52398270, 0x46650561, 0xb38a222d, 0x236d8232, 0xab86ab0a, 0x6a204082, 0xff200c83, 0xb3824094, + 0x82b00721, 0xcccc2178, 0x8409cc7c, 0x828b200e, 0x33ad2483, 0x4315e834, 0x2123076a, 0x43ffff48, 0x9b47056a, 0x83bd2025, 0xadff28e1, 0xff8b9919, + 0x8261b5ff, 0x6ecd2c3c, 0xe2ffff14, 0xffff1fc5, 0x82b8deb6, 0xf3e12f5d, 0x5bffff33, 0xff0534b3, 0x98991001, 0xee828b06, 0x82cc4c21, 0xce4c218f, + 0x66260982, 0xfeffff68, 0x13849a19, 0xffff0823, 0x392c4762, 0xe27a0d23, 0x122c47ff, 0x22055c4d, 0x47ffb89e, 0x0e22052c, 0x868264f7, 0x6666e621, + 0xff2a0caf, 0x8b86d6f8, 0x29f7ffff, 0x0684087a, 0x00fffc2a, 0xffba2907, 0x6abcf9ff, 0xef220982, 0xc5828be0, 0x06820720, 0x0800ff24, 0xee5b2010, + 0x66e6270e, 0xf8ffff92, 0x1b82cdcc, 0xff27c682, 0x8b3333f7, 0x884bcb08, 0x2342835e, 0x46d6f8ff, 0xba205784, 0x2a215e89, 0x2135823e, 0x358204d6, + 0xcb62d520, 0x82068205, 0x5d168259, 0xff220a93, 0x5382ffff, 0x22058965, 0x82ccccf8, 0x9919212c, 0x3321a682, 0x27908334, 0xff3433ed, 0x9a19dcff, + 0xeb226a82, 0x54495c0f, 0xe27a3b07, 0x916800ff, 0xe7ffffec, 0x00ff285c, 0x08981923, 0x99d9ffff, 0x3600ff9a, 0x58492a9c, 0x0a972607, 0x80bbffff, + 0x29448200, 0x66e6b5ff, 0x95ffff06, 0x9f8233f3, 0xcd0caa27, 0x0caaffff, 0x220a82cc, 0x8334f395, 0x33c725aa, 0x1800ff33, 0xff21db82, 0x217882cd, + 0x0e822700, 0xe6dcff23, 0x251a8368, 0x05cccc4e, 0x3b8294f7, 0xe0feff2a, 0x00ff05cb, 0x0670fd3f, 0x572c6f82, 0x00ff8b0a, 0xff90c21b, 0x66a61c00, + 0x222e0a82, 0xff083473, 0x66e64000, 0x1f00ff07, 0x2282e2fa, 0xce081822, 0x0f251782, 0x00fffe7f, 0x27d28217, 0x9c99f6ff, 0x331500ff, 0xff242682, + 0xaecccc72, 0xf322cd82, 0x578248e1, 0x707de322, 0xf13c8882, 0xffff52b8, 0xffae87dd, 0xf6281400, 0xd7ebffff, 0x00ff080a, 0xff749308, 0x8c6cf7ff, + 0x07875018, 0x00c0f922, 0xf5242a82, 0xffffb8de, 0x04820a82, 0x0890c227, 0xe0fcffff, 0x2c048600, 0xfff0e7fb, 0xe06ffeff, 0xe8fbffff, 0x83f583b4, + 0x250c8206, 0x00ff2ce7, 0x16828f01, 0xc4e0fc27, 0x200300ff, 0x82358240, 0x20608456, 0x866c8405, 0x23808376, 0x94b8f1ff, 0xe3226582, 0x25822e7d, + 0x0720a282, 0xf7210c82, 0x24588227, 0xff10d8f8, 0x820484ff, 0x835d830e, 0x23118506, 0xf0270700, 0x0822ec82, 0xb58210d8, 0xb81e0c22, 0x00233382, + 0x8690821c, 0x470e22d1, 0x856485ae, 0x83d182d6, 0x9cd68352, 0x6de721bb, 0xfb222682, 0xbb8872e8, 0xbb87c520, 0x0023fc83, 0x82004006, 0x210a2372, + 0x0a83ff48, 0x3d210482, 0x227c8270, 0x86b69308, 0x140023d6, 0xd6822526, 0xac611f82, 0x80222705, 0xe3ffff00, 0xb983ff7f, 0x66e6f328, 0xf7ffff06, + 0x6182ef27, 0xbf8ad183, 0xff24c685, 0x31280700, 0xf7820482, 0xd7080023, 0x263382cf, 0x9a190c00, 0x83ff058b, 0x832282d6, 0x220023d2, 0x3c415278, + 0x82082009, 0x240f824f, 0xec910800, 0x059e4105, 0xb782a196, 0xff21ac84, 0x22bb8400, 0x85900200, 0x82ff20c0, 0x21c083d5, 0x4982eb91, 0x82e07a21, + 0x0609426a, 0x84ff0c21, 0x0e002369, 0x79826c47, 0xd0821c22, 0x0c232582, 0x8807ec11, 0x20a483a9, 0x21a98407, 0xa98310d8, 0x06820820, 0x2026bb82, + 0xf8ffff42, 0xe2820ad7, 0xf628f722, 0x2209cb41, 0x85707de3, 0xf1ff2550, 0x00ff52b8, 0x04836483, 0x08225482, 0x3b417493, 0x21a48507, 0xa4840040, + 0x0f836882, 0x0a87a086, 0x22128942, 0x82c876f7, 0xde6427bb, 0xebffff05, 0x0482cecc, 0x5a66e621, 0xdd270642, 0x00ff0080, 0x8300801c, 0x1e0c279e, + 0x0000ffb8, 0xe1821a00, 0x0622a985, 0xa9838a41, 0xa984cf20, 0x85083121, 0xffff2406, 0x8314aef9, 0x44b52016, 0x0e2c0608, 0xff01ffaf, 0x00ffcccc, + 0x156666a0, 0x45184082, 0x7920f92a, 0x09334618, 0xff058b30, 0x343320ff, 0x99ffffff, 0x00ff159a, 0x7d184c23, 0xb3220981, 0x10848b34, 0x06850820, + 0xe3ffff28, 0x00ffcc4c, 0x2c82b31c, 0xa94edc20, 0xb3dc2305, 0x16838b33, 0x1b84cd20, 0x5a4e0a82, 0x18068206, 0x8307107e, 0x4c232a32, 0x2b088bcd, + 0xf71514fb, 0x0c8c6554, 0x44180020, 0x62820926, 0x85832c20, 0xb679dc20, 0xffcc2505, 0xccccd3ff, 0x21053663, 0x8579ccd3, 0x79ff2007, 0xf7200cb3, + 0x19632a83, 0x00ff2510, 0xffcd4cda, 0x08924518, 0x18ffcd21, 0x261e9245, 0xff32b306, 0x82ccf9ff, 0x99032727, 0xf7ffff9a, 0xc6820080, 0x3333f72b, + 0x0624fb08, 0xe6ecffff, 0x220e8266, 0x82ceccee, 0x201e8319, 0x29ce82f4, 0x33b3f2ff, 0x2500ff08, 0x441833b3, 0xd16319da, 0x3e45180d, 0x2db78e12, + 0x193f00ff, 0x14fb069a, 0x60ffff07, 0x788266e6, 0x707de522, 0xea257882, 0x00ff8f82, 0x28928315, 0x00801a00, 0x0704f708, 0x221b826b, 0x827bd4f2, + 0x2af4221b, 0x0648477f, 0xb633fb25, 0x820c00ff, 0xffff21b2, 0x4c200a85, 0x3627cd83, 0x00ff99e9, 0x827daf09, 0x66e63524, 0xff64f708, 0x9603c000, + 0x7500ff05, 0xffff33b3, 0x156a7c08, 0x074a6318, 0x61438b20, 0x099a7a06, 0x0734fb23, 0x0ca841ab, 0x200d3567, 0x0e6b68e5, 0x08239f82, 0x82dffeff, + 0xffff24c0, 0x826666e6, 0x99e9229b, 0x82b78b9a, 0x47082061, 0x16820593, 0x3433072e, 0xe60700ff, 0xab088b66, 0x0734f706, 0x11211b82, 0x221182b3, + 0x8532330f, 0x82002087, 0x088b350e, 0xfb155b9b, 0x54f70724, 0x0724f706, 0x0e0654fb, 0xc300ffef, 0x002e7682, 0x15008003, 0x4aedffff, 0x1200ff3e, + 0x3c8252b8, 0xa4701e22, 0xb6200a82, 0x12235882, 0x8208c2b5, 0x759321ec, 0x26068244, 0xb3ebf3ff, 0x18ffff06, 0x210b3a69, 0x3182ae87, 0x52781a23, + 0x82068508, 0xae8721a3, 0x15820486, 0x27095a44, 0xff056801, 0x4861f7ff, 0xa6214982, 0x900a8206, 0xc2b5216f, 0x6f827f84, 0x82190921, 0x0509287a, + 0x0c00ff1e, 0x82909919, 0xcdcc2105, 0x09224783, 0x63827593, 0xdd240927, 0x33fdffff, 0x82f08274, 0xfaff23ff, 0x318222d0, 0x820a0021, 0xc01b23bc, + 0x20820500, 0x63822420, 0x94e0ff39, 0x1d00ff7b, 0xffff0a57, 0x8bb85ed9, 0xff8b5f08, 0xae07f2ff, 0x82e3ffff, 0xe9ff2ff0, 0xffff48e1, 0x08b85edd, + 0xb8ffff5d, 0x0b82b81e, 0xff299c31, 0x7c14b2ff, 0x63eaffff, 0xaeffffd7, 0x8208cccc, 0x46562b63, 0x3ef6ffff, 0xfefffffa, 0x098235be, 0x8b9a1923, + 0x26e48281, 0x00c0c2ff, 0x833e00ff, 0x84d32047, 0xcdcc2609, 0xe11000ff, 0x20858248, 0x2414823b, 0x66e60f00, 0x26ff8205, 0x00ff71bd, 0x82f4dd05, + 0x852b21d2, 0x8521c182, 0x210482e2, 0x29829999, 0x830c5721, 0x6f72265b, 0x95ffffff, 0x216582fe, 0x09827f6a, 0x82aea721, 0xed5c2109, 0xff2de582, + 0xfffc29f3, 0x900c0000, 0xe6f3ffff, 0x23058267, 0x9466e6f6, 0x93255b82, 0x01ff9a99, 0x05fd5625, 0xff66e626, 0x34b38600, 0x0820ec83, 0x12214b18, + 0x18067b21, 0x20075c46, 0x211d84f8, 0x461800e0, 0x79220d5c, 0xa182cc4c, 0x88160736, 0x220400ff, 0x0800ff0c, 0x00ffca21, 0xffc28a02, 0x48e10700, + 0x06848282, 0x0a00ff24, 0x9482ead1, 0x6b828620, 0x34330627, 0xccfbffff, 0x288682cc, 0xff32b34e, 0x68e6f0fe, 0x051e4715, 0x20074d47, 0x06fc481e, + 0xc6480f83, 0x0e002316, 0xe2466c47, 0x1c002305, 0x6683d282, 0x60250c23, 0x477d8206, 0x2e470517, 0x053e4706, 0x06850820, 0x8209c648, 0xf02721d0, + 0xff203382, 0x470f9d49, 0x2e470584, 0x49b62011, 0xa096069d, 0x2a07ab48, 0xdef5ffff, 0xffff8bb8, 0x8290c2f9, 0x00c02104, 0xff28bb86, 0x054a6cf7, + 0xdeebffff, 0xeb28d682, 0xfffff2d2, 0xff0080dd, 0x2106957e, 0x2582801c, 0x4e490020, 0x49082006, 0x0023077d, 0x888a4106, 0x098249a4, 0x83f8ff21, + 0xf8ff23dd, 0xea47560e, 0x4971200b, 0xff230582, 0x4851b8f1, 0x6e260daa, 0x0800ff15, 0xaa48af87, 0x87a0920a, 0xffff24ab, 0x8270fdff, 0x49e1201f, + 0x0948066b, 0x93082206, 0x83888275, 0x480020bf, 0x0b2506aa, 0xb8f1ffff, 0x23738693, 0x8b2f7de3, 0xdf228b83, 0xaf8506be, 0x86056441, 0x20b982a8, + 0x06594a08, 0x4a070021, 0x0020075e, 0x3382e582, 0x062bf383, 0x821c00ff, 0x00ff8b8f, 0x86af470e, 0xd7eb2250, 0x20c4840a, 0x204e8208, 0x08424a6c, + 0x4b05094b, 0xa08e0519, 0x4b200321, 0x00230619, 0x4b101804, 0x00230519, 0x834c1704, 0x20068361, 0x201682ff, 0x055d4ad5, 0x1f030023, 0x065d4a3b, + 0xd6830020, 0x34210482, 0x053d4a05, 0x2d140027, 0x2200ff8e, 0x454a8280, 0xe3220563, 0x194b0080, 0x83bf910d, 0x063d4ac6, 0x4216194b, 0x0e21054d, + 0x14f04b47, 0x7a82cc20, 0x1721bba1, 0x21bb82d0, 0xb6820ca2, 0x83981921, 0x829a2004, 0x337a2795, 0x7600ff34, 0xf54d32b3, 0x0700240c, 0x828b7829, + 0x22f0228e, 0x4f068508, 0x08220619, 0x194f44f6, 0x09456b08, 0xe6f7ff27, 0xffff8b66, 0x053350f8, 0x745a0682, 0x49168206, 0xf54d0689, 0xd6f8220a, + 0x214c8204, 0x57827e2a, 0x82d50822, 0x06825e83, 0x29261182, 0x0600fffc, 0x04751844, 0x82d52114, 0xf7225e82, 0x2d827e2a, 0x0682ff20, 0xf9225e86, + 0x5e86e8bb, 0x1c01ff25, 0x82749819, 0x61ea2bc1, 0x5100ff48, 0xffff0040, 0xe18299dd, 0x9ad94d2c, 0x05d2ffff, 0x4700ff20, 0xeb8266e6, 0x82e1e921, + 0xa122221e, 0x056f4548, 0x801c0025, 0x828b5f00, 0x61d92216, 0x265f8248, 0xff289ce0, 0x83a6e2ff, 0x9edb22c9, 0x231682b8, 0x079042e4, 0xcb259882, + 0x0500ff86, 0x2c438230, 0xff1e2509, 0x4acc0200, 0x940900ff, 0x2337827a, 0xecd10c00, 0x0c27c582, 0xffff5c0f, 0x824200fb, 0xec113616, 0xedf6ffff, + 0x00ff08d2, 0xffc2b512, 0xae47edff, 0xe1ffff8b, 0x221f828f, 0x843e4aed, 0x08c3430f, 0x05d26d2c, 0x1b0c00ff, 0xffffff24, 0x0a829cf9, 0x0bc26f18, + 0x82c27521, 0x8ae52236, 0x27ee833e, 0xffae87e5, 0x5278eaff, 0x0e820486, 0x4d086944, 0x6f900bec, 0x82664821, 0x3e4a216f, 0xf6226f82, 0x95821aef, + 0xf3220483, 0xa9822ef2, 0xff8a0126, 0x142ef3ff, 0xfd224683, 0x6982ee5c, 0x0e6dfd2c, 0x580000ff, 0xfdffff04, 0x09826e72, 0x82fc6921, 0x990c27c0, + 0xefffff9a, 0xca82f6a8, 0x82842b21, 0xe27a2b30, 0xbd1500ff, 0xfaffff72, 0x1e824621, 0xfe7f3b27, 0x19f0ffff, 0x22b9829a, 0x82c8be3e, 0x04142129, + 0x35057746, 0xcc4c2c00, 0x3d00ff8b, 0x8b083433, 0xfeffff95, 0x00ff34b3, 0x8c82e609, 0x6466fd22, 0xcc2b0982, 0xaf0e08cc, 0x8f00ffeb, 0x821566e6, + 0x280c2126, 0x042c6082, 0x00ff94f8, 0xff84ab0b, 0x44ab0800, 0x2e210482, 0x27608216, 0xff472148, 0x7b144400, 0x012c6082, 0x00ff66a6, 0xff148e01, + 0x7d1f0200, 0xc1219f82, 0x210e828a, 0x048287d6, 0x825a4421, 0xb8f52adf, 0x1700ff12, 0xffffcba1, 0x246782e9, 0xcccc1000, 0x05474a70, 0x66a6dc27, + 0xe3ffff8b, 0x20c88259, 0x269483e3, 0x34b3dcff, 0x82072b08, 0x0e6d7013, 0x1fc51023, 0x2572828b, 0xfb66e600, 0x1e910514, 0x85ab1122, 0x8305b55d, + 0x080d7808, 0x03597a20, 0x33378205, 0x07d86360, 0xa3cdffff, 0x2f00ffd7, 0xff05ae87, 0xc275f6ff, 0x1423c683, 0x83fbffff, 0xb30b2291, 0x242b8232, + 0x089a190c, 0x23c382f8, 0x159a19b0, 0x23127759, 0x08486123, 0x06822582, 0x612bb282, 0x1c00ff48, 0xffffb89e, 0x82b89edc, 0x85068499, 0xe3ff2316, + 0xa1824861, 0x2d821782, 0x28821783, 0xe0839920, 0x23273283, 0x088b6666, 0xa08b14fc, 0x6666215f, 0x435a5f87, 0x82dc2005, 0x825f8206, 0x215f9316, + 0x7b8548a1, 0x5e230022, 0x01218d83, 0x2627835c, 0x1534b358, 0x83b7ffff, 0xff4322df, 0x31f482ff, 0xff9082fc, 0x024b0300, 0xe2faffff, 0x0000ff0c, + 0xfe8266e6, 0xffd49827, 0x231bfeff, 0x210a8208, 0x0a822a9c, 0xffdc1925, 0x8219fdff, 0xb3fb22af, 0x2ac68233, 0x083333fb, 0x14fb0767, 0x8207af06, + 0xcb0422fb, 0x261d8285, 0x00ff9c24, 0x82875604, 0x52982631, 0xe50100ff, 0x213c83a2, 0x0a82df8f, 0x82b8de21, 0x66e6215b, 0xfc223782, 0x1f820080, + 0x82cdcc21, 0xe6b7271a, 0xbcffff67, 0x81820100, 0xeb31fb22, 0x77211582, 0x2020820a, 0x213b83f7, 0xa182ce04, 0x5278fb27, 0x4800ff08, 0x233b821e, + 0x0514eebb, 0x7d30a282, 0xfcffff71, 0x00ff82b5, 0xfff31d05, 0x9819ffff, 0x67216f82, 0x215f822b, 0x2982dee4, 0xb95e0422, 0xd6240a82, 0x0200ff46, + 0x0022c182, 0x6f826604, 0xcc040023, 0x2b1a82cc, 0x079a1924, 0xff0614f7, 0x28dcdbff, 0xff23af82, 0x827a34fb, 0x64db2125, 0xa8217482, 0x204483f6, + 0x20e182ae, 0x226e8318, 0x82f06704, 0x641b210a, 0xf4246383, 0xe60000ff, 0x0322d382, 0x7c82ac7c, 0x868c4a21, 0x4400238d, 0x8d82ec11, 0xdace0422, + 0x82213982, 0x22fe82d2, 0x82666608, 0x32332149, 0x99210f82, 0x2925829a, 0xff9a9943, 0xcc4c8700, 0x72824b15, 0xf784e520, 0xc683e820, 0xe03aef25, + 0x82f6ffff, 0xe8ff231c, 0x27829b59, 0x8ed70122, 0xba216c82, 0x218b82a0, 0xd0828220, 0x82773e21, 0x6ca721c0, 0x70211382, 0x21fa8862, 0x6c82a4f0, + 0x14a30831, 0xdef7ffff, 0xffff9034, 0x8bce4cf4, 0x84f3ffff, 0x000022d7, 0x210a8284, 0x7d820ad7, 0x36820720, 0x7c54f422, 0x54212582, 0x32048238, + 0xff08ead1, 0xd8a3cdff, 0x82d0ffff, 0xffff0590, 0x439a999f, 0x7a220a3e, 0xac73ffff, 0x43862006, 0x8420071f, 0x0e20c782, 0x63183f82, 0x11210f24, + 0x201992ab, 0x234b82eb, 0xcc4c2300, 0x3610674e, 0x00ffef0e, 0xff9a19ee, 0x34b31e01, 0xd7ffff15, 0x00ff33b3, 0x8266e68c, 0x19fd2c80, 0x0a00ff99, + 0x00ffe03a, 0x8234b307, 0x8c2b2109, 0x99220482, 0xe7828b99, 0x33333828, 0x0b00ff06, 0x82820080, 0x9a990a2a, 0xd8f9ffff, 0x0500ffce, 0xff232682, + 0x827408f6, 0x80642d20, 0x50ffff00, 0xff05b81e, 0x98997400, 0x22222b82, 0x2b823433, 0x00803b33, 0x08688b6e, 0xffff678b, 0x6f0080c4, 0xccddffff, + 0x234f82cc, 0xce4cb6ff, 0xbe252382, 0xffff3233, 0x277b836a, 0x68660a00, 0xccf7ffff, 0x01275482, 0xffff64e6, 0x8366e6f0, 0xffd0260e, 0x9a99f5ff, + 0x820a8308, 0x99f522c8, 0x82198398, 0x19fe221e, 0x3019839c, 0x0800ff9c, 0xff083233, 0xf8feaffd, 0x02d001ff, 0x22c4828e, 0x826891f5, 0x162e2b15, + 0x2bfeffff, 0x0f00ffc7, 0x0e827a14, 0x82502d21, 0x1a6f21c9, 0x0822a782, 0x0a82912d, 0x83da6e21, 0xff7b2519, 0xf8d30100, 0x2206c863, 0x82b0d2f7, + 0x4ac7271e, 0x63ffff3e, 0x4882e0cf, 0xa4703b32, 0x992000ff, 0x01ff1598, 0xffc2f540, 0x9a1903ff, 0xbe201582, 0x8d22f283, 0x0a8234b3, 0x824cfa21, + 0x19f62293, 0x2089829a, 0x21ad8266, 0x0e82ccf9, 0x0080f422, 0xc723de83, 0x8306cdcc, 0x8b672416, 0x82f8ffff, 0x0a002826, 0x00ff3433, 0x8267e602, + 0x28b0836c, 0x99193100, 0x80ac00ff, 0x22468200, 0x829a1999, 0xccd4252b, 0xc5ffffcd, 0xfc2c1084, 0xff87e1fa, 0x8f42fbff, 0x99fdffff, 0xfa225d82, + 0x5383c2f5, 0xae07d622, 0xf8222782, 0x53820040, 0x52b8f928, 0x4c0600ff, 0xdb828bcc, 0x089a9922, 0x00200682, 0x00238282, 0x82152e00, 0xce4c26d2, + 0x5c0000ff, 0x066f6729, 0x751f0025, 0x8203f7c3, 0x8ae02667, 0x6d00ff3d, 0x22b98333, 0x84d7a3ff, 0xffff241d, 0x84ebd1ff, 0x20418231, 0x05e86f01, + 0xd0820620, 0xeb820020, 0x0500ff22, 0x0622b883, 0x2082a470, 0x0866e62a, 0xfb0e078b, 0x7b01ff30, 0x012e1482, 0x15a4f061, 0xaed4ffff, 0x2b00ff14, + 0x5b82ec51, 0xba1ef326, 0xf0ffff97, 0x0028ad82, 0xff70bd06, 0x9819efff, 0xbd23b283, 0x45060040, 0xff2505c8, 0x85abf1ff, 0x072472ff, 0x1c837b20, + 0xcd0cbf22, 0x180edd75, 0x82089062, 0x67e625bf, 0x14f7052b, 0xff2a2082, 0x05abf3ff, 0xc04200ff, 0x6d820601, 0x825c4f21, 0xa4b02177, 0x062c1082, + 0xffff7c3f, 0xff84c0f9, 0xcc210a00, 0x20061153, 0x25148200, 0x1600ff08, 0x0484b89e, 0x4a262583, 0x0600ff4a, 0x20823e4a, 0xd8820a20, 0xb3f9ff23, + 0x2c0f8232, 0xff08703d, 0xce4c70ff, 0x0fbeffff, 0x08c9825c, 0x1ec56822, 0xdeffff06, 0xff8b66e6, 0x295ce4ff, 0xcce6ffff, 0xffff88cc, 0x080100df, + 0xa3ebffff, 0x1fffffd7, 0x2b058545, 0xffff4c97, 0xff0080da, 0x4e821d00, 0xb3261f82, 0x2500ff34, 0xcd82d7a3, 0x19bf0023, 0x229f829a, 0x8248a125, + 0x821d2569, 0x2000ff8e, 0xfc22aa83, 0x21829a99, 0x84e27a21, 0xf7d62d46, 0xffff0574, 0xfff6e8fd, 0x8e022100, 0x80826982, 0x33190023, 0x82798534, + 0x820320b7, 0x52ff2459, 0x821534b3, 0xa3f82786, 0xfaffff12, 0x04826d07, 0xff74082c, 0x18a4f8ff, 0x0663088b, 0x1a890763, 0x1a87f020, 0x8295a321, + 0xe5ff2480, 0x82067b54, 0x12a32127, 0xfa272182, 0x00ff7308, 0x8294f805, 0x5b072a8b, 0x07b308e6, 0xe3d8ffff, 0x201e8ad7, 0x241e8b72, 0x991a00ff, + 0x23588298, 0x705d0700, 0x04821784, 0xff0af72a, 0xe85b0700, 0x06b3088b, 0xff283d83, 0x00ff52f8, 0x91204508, 0x19201a82, 0x0722d282, 0x73826666, + 0xab1a0023, 0x22f48285, 0x82ee5c07, 0xf7052268, 0x2190828d, 0xa084f007, 0xff089528, 0xffffd7ff, 0x1e95b307, 0x1e829620, 0x2a5ce522, 0xff2e9682, + 0x158bec11, 0xff30fb0e, 0x9a99eb00, 0x8b41b4f7, 0xb3ff2588, 0x94fb0080, 0xdd228e82, 0x93539999, 0x1a002306, 0xe782cc4c, 0x66202908, 0xa48b0868, + 0x142600ff, 0x3200ff7b, 0x00ff5278, 0xff856b11, 0xcccc1500, 0x0400ff08, 0x00ff0040, 0xffdf4f05, 0x00800800, 0x0f832c82, 0xb0faff23, 0x271a8221, + 0xff666611, 0xe23aeaff, 0x19243982, 0xcdffff9a, 0x72211f82, 0x2f5a8208, 0xff9899df, 0xcd4ce3ff, 0xb3e5ffff, 0xdbffff34, 0x2505f050, 0xff3233dc, + 0x66434101, 0xf70e25c1, 0xc000ffb4, 0x1811f55a, 0x210b7741, 0xa04cfc29, 0x05f55a05, 0x18d60821, 0x240ea541, 0xba290700, 0x2221828b, 0x8308e0ef, + 0x66e62106, 0x2305a04c, 0x9a190800, 0x2106a04c, 0x5e4dcb4b, 0xf8ff240c, 0x828b87d6, 0x7929211a, 0xff213082, 0x4d5e88f7, 0xef23051b, 0x83088b9e, + 0x829e204d, 0x1008224c, 0x10545b62, 0xe6211082, 0x08585b67, 0x47829920, 0x83333321, 0x80f23331, 0x6b00ff00, 0xfb15866b, 0x5000ff54, 0xff059002, + 0x8182fbff, 0x07020023, 0x2b23826c, 0x00ff32b3, 0xff18a401, 0xceccfaff, 0xff232d82, 0x839999fa, 0xcdcc2682, 0x5bfeffff, 0x242a85e8, 0x10f8fdff, + 0x233d8208, 0x70fdafff, 0xee223d82, 0x66820a17, 0xffac9c2b, 0x5c4ff4ff, 0x78eeffff, 0x22318252, 0x820080ed, 0xfdfe21b4, 0x002ce582, 0xff3333bd, + 0x343381ff, 0xb33200ff, 0x34228284, 0xb4821e05, 0x7c14bc27, 0x338000ff, 0x220a8234, 0x82ccccff, 0x1300232d, 0x44826666, 0xffcc4c26, 0xae871100, + 0x32834982, 0xd8630726, 0xadffff08, 0xff23b482, 0x5a7a9454, 0xec2208dc, 0x6582c2b5, 0xe23af326, 0x38f0ffff, 0xef217083, 0x2242838c, 0x8223f8ff, + 0xeb0222d5, 0x2bca8202, 0x00ff64fb, 0xff9c8406, 0xe27af9ff, 0x4f0df35a, 0x01220902, 0xd3822090, 0x5a32e821, 0x83820510, 0x79f7ff23, 0x21318216, + 0x04829022, 0xff506d27, 0x70ddf6ff, 0x227f828b, 0x83f0e7fb, 0xf0e72122, 0x221cef5a, 0x83227bf9, 0x82de2072, 0x30fd2b7c, 0xea0200ff, 0xf8ffffc0, + 0x40834821, 0x40829e82, 0xff21aa82, 0x82b482ff, 0x82c0820a, 0x3a065b57, 0x3e4a1322, 0xff29fb84, 0x1ec50c00, 0x8cefffff, 0x826783cd, 0x275c82ff, + 0xfff4fdf7, 0x4015fdff, 0x7a21c482, 0x210482e1, 0xda50227b, 0x1ad95b0d, 0x6bdcf622, 0xf9284082, 0x00ff9523, 0x8b167907, 0xa0220582, 0x06820884, + 0x10180422, 0xdf2afb83, 0x170400ff, 0x0300ffd0, 0x04824220, 0x557c1f21, 0x00230c5a, 0x41dd8406, 0xfb820500, 0x00ffc125, 0x82d00208, 0xde072239, + 0x224083b8, 0x83347310, 0xffe12afb, 0xadc70f00, 0xb5ecffff, 0x22af83c3, 0x5babdcf3, 0x865a2030, 0x5111200a, 0xff8209c4, 0xfb835c82, 0xae205082, + 0x10220a82, 0x67833373, 0xacdc0722, 0x1421fb82, 0x217e82fe, 0xfb839c04, 0x92826420, 0x081e8527, 0x74f7ffff, 0x27ce82bd, 0xff0588ab, 0xcdccfcff, + 0x2305de50, 0x0080feff, 0x1921d282, 0x2240829a, 0x839a1904, 0x86082240, 0x213182ea, 0x048271dd, 0xffb09226, 0x8f220900, 0x0a4b7e18, 0xff111826, + 0x2270feff, 0x1f213c82, 0x2246823b, 0x8208bcdf, 0x0a972667, 0x63f8ffff, 0x06b16954, 0x66f9ff24, 0x82829368, 0x82981921, 0x67e6216d, 0x9a823c83, + 0x0f275f82, 0x00ffaec7, 0x8220c50c, 0x4c13220a, 0x233882cc, 0x07ae070d, 0x08220c82, 0xd35112d8, 0x54ee2008, 0x1c82054d, 0x2409ea51, 0x12d8f8ff, + 0x21be828b, 0x3142ee27, 0xb5ec2309, 0xf783ffc2, 0xf3ffff29, 0x00ff5238, 0x83347310, 0x83fb8267, 0x22f7824f, 0x82ea0200, 0x85062220, 0x21c5821e, + 0x835bdc84, 0x52b62009, 0x00220601, 0xf7832003, 0xff101825, 0x82900100, 0x06bd52ce, 0x96230922, 0x06224082, 0xd0826adc, 0x82e88621, 0x5ff82374, + 0xf942087c, 0x43f78206, 0xf783052c, 0x0482c020, 0x5082e021, 0x6c2708a7, 0xffff054c, 0x86227bf9, 0x15fd2204, 0x21af8240, 0x39822efd, 0x4821f822, + 0xef224083, 0xa842ce8c, 0x83f02006, 0x4a1322af, 0x09c9413e, 0x1020e98c, 0xf020e984, 0x1c5e3383, 0x24c62105, 0xf3214a82, 0x06224532, 0x84f80e2b, + 0x2b1534f7, 0xcb07ab06, 0x200082ff, 0x22ce82f2, 0x8288d608, 0x290722b3, 0x07024578, 0x9eef0722, 0x0f23f082, 0x82079a19, 0xd6082217, 0x21cb8287, + 0x1c8388d6, 0x44827920, 0x8b782924, 0xf4823b08, 0x82dacc21, 0x09b568b1, 0xabf1ff22, 0x07a14718, 0xd0ffff26, 0x4b0766e6, 0xff245d82, 0x54f705e0, + 0x11274483, 0x00ffd6a3, 0x83285c0e, 0xff2a2504, 0xd8a31100, 0x0683bd83, 0xff231685, 0x82d6a3f1, 0x5cee24b7, 0x827b082a, 0x0fab452f, 0x04d60828, + 0x06ab088b, 0xaa9000ff, 0x08211982, 0x0831829b, 0x333b002c, 0xcaffff34, 0x00ff6626, 0xffcccc2e, 0x00c0c2ff, 0x23f4ffff, 0xffff08d6, 0xff6766d2, + 0x2240f6ff, 0xb3e0ffff, 0xd5ffff33, 0x69829a59, 0xea91d122, 0x43221a82, 0xa784cecc, 0x0570fd23, 0x21a684bb, 0x9f4a85ab, 0xff7b2508, 0x7b54eeff, + 0x8b20eb82, 0xd062e782, 0x0a534609, 0xf0ffff22, 0x4c82e782, 0xcd4cf627, 0x280700ff, 0x072c46f6, 0x8b0ad729, 0x00ffcb08, 0x820d0000, 0xffdf263a, + 0x062b07f3, 0x0a1363ff, 0x04204282, 0x53823582, 0x976b0821, 0x74f821ec, 0x2017257f, 0x213282ab, 0xe3830800, 0x5618f820, 0xfc240d8d, 0x1514fb64, + 0xca275782, 0x00ffe2fa, 0x82e1fa2a, 0x1e052aea, 0x053500ff, 0xf7088b1f, 0x234e8294, 0x8b1e0535, 0x1e841983, 0x0a82e220, 0x08321082, 0x54fc07ab, + 0x0e076b06, 0x54f7d4f7, 0x2300ff15, 0x18829a59, 0x66a61c23, 0x063e61ff, 0x08201082, 0x06821182, 0x8305e351, 0xffff2616, 0x8b66a6dc, 0x85068508, + 0xe3ff2116, 0x17833883, 0xff232d82, 0x5c33b3dc, 0xe32206d0, 0x5482cd4c, 0x8bcc4c27, 0x6b34fb08, 0x20318915, 0x82368499, 0x844982ad, 0x20718531, + 0x85168467, 0xf7082286, 0xabb48254, 0x54fb2690, 0xf774f706, 0x79c68274, 0x11221068, 0x668284ab, 0x17820020, 0x21064d4f, 0xa57e540e, 0x239b821e, + 0xff7c54ee, 0x210f6879, 0xc68244fb, 0x801a0027, 0x00ff8b00, 0x5c441815, 0xeaff2114, 0xa4181686, 0xe52008ce, 0x16842d83, 0x0074ff20, 0x7de52205, + 0x208d8270, 0x180682ff, 0x2009135a, 0x245484ff, 0x2b64f708, 0x307a8215, 0xff142ee4, 0xe2faf3ff, 0x23e7ffff, 0xedffffd8, 0x26ad8314, 0xff085278, + 0x82a32400, 0x82f2220f, 0x222f828e, 0x8268cc4c, 0x6cd6202a, 0xca200576, 0xd5222c83, 0xf6411e05, 0x82ff2005, 0x088b250e, 0xff0654fb, 0xe1200982, + 0xd5262582, 0x00ff1f05, 0xf641fa2a, 0x05fd4107, 0x83052742, 0x06274216, 0x5800ff24, 0x3382f6e8, 0xa4b0f02c, 0xe61100ff, 0xf6ffff66, 0xa3826666, + 0x82676621, 0xb3182530, 0x14fb0833, 0xdf68518c, 0x19ca2206, 0x2019829a, 0x177c4207, 0x7c42d420, 0x14f72117, 0x00243382, 0x6066e635, 0x192b8982, + 0x088b569a, 0xa8f72f0e, 0x821554f7, 0x9906256d, 0x0500ff9a, 0x04847d83, 0x8b200e82, 0x0683fd82, 0xff231685, 0x829a99fa, 0x66f92270, 0x056c5466, + 0xff200882, 0x04861383, 0x2f820e82, 0x0683ff20, 0x4b831185, 0x08265685, 0xf78707eb, 0xaa681594, 0x08e04105, 0x81188620, 0x7c250b26, 0xb3f1ffff, + 0x29048234, 0xffff84ab, 0x8bcc4cee, 0xf7827b08, 0xcc8cdd28, 0x2500ff07, 0x51820080, 0xff004025, 0x82332200, 0x33f02422, 0x8274a734, 0xb3152b99, + 0x1500ff32, 0xff059a99, 0x21820c00, 0x14220485, 0x73823433, 0xff230f83, 0x820080f3, 0x820a8725, 0xcceb236c, 0x1583ffcc, 0x08250484, 0xe6e7ffff, + 0x21048266, 0x4082cecc, 0x58831520, 0xff7fdf22, 0x4c204a82, 0xd9222482, 0x2f829919, 0x3433d623, 0x25068208, 0xff9a198d, 0x2b83a2ff, 0x0e820484, + 0x8d20e783, 0x11832284, 0x195d0023, 0x2d73829a, 0x0866e672, 0x00fff38b, 0xffec514c, 0x4f825600, 0xae630022, 0x0f22f282, 0x85829859, 0x34732223, + 0x22d08307, 0x82cd4cee, 0xb3f12451, 0x1800ff33, 0x200e3572, 0x18118286, 0x280d809f, 0x9b058beb, 0xff1560fb, 0x05e455ff, 0x82b3e821, 0xb3e821fb, + 0x4106a760, 0x19820582, 0x1700ff22, 0x1d83b183, 0xb31c0023, 0x849a8234, 0x83168506, 0x829a821b, 0xeb082217, 0x22088407, 0x84ffff33, 0x8217202a, + 0x2758846b, 0xff08fb08, 0x0080cbff, 0xfd226782, 0x248234b3, 0x66fcff26, 0xfeffff66, 0x127aa282, 0x99fd2105, 0xfd22fe82, 0x2682cc4c, 0x82e6d821, + 0x19d42619, 0xffff059a, 0x203f83f2, 0x271a83f0, 0xff0080f8, 0x9a19ecff, 0xeb22d782, 0x25820080, 0xcc4cf03b, 0xff808b07, 0x9a190800, 0x0b00ff82, + 0x088b67e6, 0x8b9606cb, 0x968b9494, 0x22838208, 0x8266e60b, 0x201c8216, 0x33ab8280, 0x3333d4ff, 0x0000ff06, 0x00ff67e6, 0xff343309, 0xcccc0300, + 0xb3333982, 0x0600ff32, 0x08923433, 0x192700ff, 0x2b00ff99, 0x820566e6, 0x28258316, 0x8f9a190a, 0xe60c00ff, 0x224a8266, 0x8268660d, 0x83022021, + 0xffa8246f, 0x7466e9ff, 0x6e2005df, 0xe9275783, 0x778bcd4c, 0x83f1ffff, 0x82f8209c, 0xeaff2353, 0x9b829a99, 0xdb84ff20, 0x82333321, 0x83fc20c1, + 0x82f5201a, 0x05002104, 0xf420eb83, 0x00210482, 0x230e820a, 0x6666fdff, 0x0a845582, 0xe082fb20, 0x4c0b0024, 0x2382ffcd, 0x02209c82, 0x0a220e83, + 0x1e82ff7f, 0x29820120, 0xb3010022, 0x05834882, 0x21069b4f, 0x2982cc04, 0x52840320, 0x2005a54f, 0x26a68406, 0xff34b304, 0x8266faff, 0xf9ff22b1, + 0x82858219, 0x8b6639ee, 0xffef0e05, 0x48214a00, 0x339f01ff, 0x00ff1534, 0xffb99e07, 0x846b0b00, 0x0d27e787, 0x00ffa65b, 0x8233f30e, 0x600526f6, + 0x191000ff, 0x24d6829a, 0x98998c01, 0x200c8306, 0x27fd829c, 0xff64e60e, 0xa0faf7ff, 0xe6262182, 0xf2ffff68, 0x97825aa4, 0x98994b2c, 0xae8effff, + 0xff8f0514, 0x1682f9ff, 0x33020022, 0xf8217c82, 0x277c83e6, 0x0832b3f8, 0xebffff8b, 0xef208e83, 0xff20a582, 0x0e820484, 0xfe225982, 0x598319ba, + 0x1b832a20, 0x0080de22, 0xe1828582, 0x06cb072f, 0x4cccffff, 0x14f707cc, 0x999cffff, 0x2215829a, 0x849a1997, 0xcc352c15, 0x00ff07cc, 0xffcccc36, + 0x8319d5ff, 0x6e455418, 0x45549820, 0x3ad42107, 0x3e0c4554, 0xffeb5123, 0xe04fe4ff, 0xb5ffff05, 0xffffb8de, 0x15989985, 0x0700ff8b, 0x00ffce4c, + 0x822b2702, 0x9a193609, 0x080400ff, 0x0600fff6, 0xff089819, 0xc1ca0e00, 0x331600ff, 0x25db8234, 0xffecd164, 0xfc83b0ff, 0x0aabff23, 0x2dfa823d, + 0x8bf6a8eb, 0x80efffff, 0x1000ff14, 0x46820080, 0xcc4c1424, 0x0082ff08, 0xf706ec35, 0x1bffffd4, 0xff153433, 0x66e62300, 0xffffcb07, 0x829a99cd, + 0x80be2273, 0xe2681800, 0x74fb2117, 0x27180d63, 0x06cb0784, 0xf70734fb, 0x27051e62, 0xff85eb5e, 0xf6e88e01, 0x16225b82, 0x6082aec7, 0x82c2f521, + 0x8305209c, 0x260827b7, 0x0900ff66, 0xc1829919, 0x82b4fa21, 0x34b32909, 0x01ff088b, 0x06cccc64, 0x05820c85, 0xff2d2682, 0xff8e05fb, 0x98190500, + 0xd9f7ffff, 0x27e38258, 0xffcc4c39, 0x7c54a5ff, 0x1d254682, 0xffff34b3, 0x201a83d1, 0x300983e5, 0xff67e6be, 0x0080c8ff, 0x99f8ffff, 0xffff089a, + 0x231983fc, 0x870080ff, 0xb326e482, 0xfbffff33, 0x6182d0cc, 0xffe5ff31, 0xffff8bfe, 0xffcecce8, 0x66660b00, 0x82f0ffff, 0x11002126, 0xf0203184, + 0xee207083, 0x1e831483, 0x99f4ff28, 0xe5ffff9a, 0x358466e6, 0x35830682, 0x3588cc20, 0x86ff9a21, 0x83fa2035, 0xe6f92172, 0xf9204a82, 0xfa208683, + 0xf9200483, 0xb321ba84, 0x21b08233, 0xb082ccb2, 0xcdcc7322, 0x6423b082, 0x82073333, 0x8233203f, 0x99fc21b6, 0x0b20f882, 0xfe203483, 0x00232a82, + 0x82ce4c0c, 0x05002465, 0x828b9899, 0x686626ed, 0x660000ff, 0x063b5566, 0x34b30025, 0x828b8b08, 0x6603223e, 0x82178264, 0x0400226d, 0x232183e6, + 0x8c8fcccc, 0x6b22e782, 0x55820080, 0xcccc5623, 0x42238247, 0x382786ba, 0xffff291c, 0x82a205d4, 0x47112891, 0x51ffffae, 0x8215d7e3, 0xf6282110, + 0xf483d382, 0xc275e63d, 0x332a00ff, 0x0600ff33, 0x00ff7b14, 0x089a9928, 0x666a00ff, 0xacffff67, 0x48059a19, 0xbc450538, 0x99f52905, 0xffff899a, + 0x8b9919f5, 0xfb23ea82, 0x5b8b66e6, 0x002a06b0, 0xff87cd4c, 0x00800000, 0xfd828b08, 0xcdcc2f38, 0x335fffff, 0x00ff1533, 0x060080cd, 0x669500ff, + 0x8affff68, 0x4b82cc4c, 0x64e6f52f, 0x80f9ffff, 0xf4ffff00, 0xffff9a19, 0xa77718fc, 0xd4fb2208, 0xda951806, 0x00ff2416, 0x826666c3, 0xde032756, + 0x00ff8ab9, 0xc1820704, 0x3682ff20, 0x82030021, 0xffff21b1, 0x8c217382, 0x20d9828b, 0x23128205, 0xcc4cffff, 0x5d83d382, 0x9a99ff22, 0x99200982, + 0x26059b74, 0x978b6766, 0x820100ff, 0x0b0021eb, 0x00213482, 0x35348203, 0x997affff, 0xef0e079a, 0xfa3f00ff, 0x0001ffe1, 0xff1566e6, 0x054c53ff, + 0xe1d62205, 0x20f58248, 0x26a48240, 0xffb85eea, 0x829eeaff, 0xd9bf2304, 0xaf82089a, 0xf5255b83, 0x00ff00c0, 0x2d048207, 0x6626f6ff, 0xe10a00ff, + 0xff088b48, 0x5e831801, 0x82010022, 0x0d2b8b82, 0xff8bb8de, 0xe23a0b00, 0x820800ff, 0x05002926, 0x00ff1e45, 0x08b81e0d, 0x14242c82, 0x1e00ff7a, + 0x2f083683, 0xff486109, 0x34731b00, 0xa30300ff, 0x2400ffd8, 0xff08142e, 0xf628c4fe, 0xbef500ff, 0xffff0580, 0xffd763fe, 0x9819f2ff, 0x14ffffff, + 0xf1ffff7b, 0x7d2ccb82, 0x3602ff08, 0xaafbecd1, 0x92ffff15, 0x0023ef82, 0x821e0556, 0x8330206e, 0x24093263, 0x2600ffde, 0x00ffa430, 0x8b560e52, + 0xe66300ff, 0x2eaf8266, 0xfff428ff, 0xe2fa6900, 0xffffe160, 0x820200cb, 0x290684a7, 0xffd4ffff, 0xff8b35fe, 0x258296ff, 0xce200682, 0x5c304184, + 0xd3ffffac, 0x00ff5238, 0xff0c420f, 0xae07deff, 0xc7204082, 0x2c22a583, 0x66824861, 0x42010028, 0xa65300ff, 0x5d820566, 0xb89e5325, 0x831700ff, + 0xe1452104, 0x2420c682, 0x25220483, 0xc1829a99, 0xbe7ee328, 0xe8ffff06, 0xb7829919, 0x52f82008, 0x80e9ffff, 0xedffff00, 0xffffec11, 0xff1f05ef, + 0xc235e1ff, 0xc7ffff08, 0x00ff0a17, 0x736a9c2c, 0xf57d1e30, 0xaad1241a, 0x78f5ffff, 0x092942d9, 0x00fff81e, 0xff128309, 0x133073ff, 0x4c68ff26, + 0x15aaf7ce, 0x2321f082, 0x20f0825e, 0x2104830e, 0xf082a11c, 0x48a11129, 0x00ff088b, 0x82ba9e11, 0x610e2e1b, 0xe3ffff44, 0xff8bb85e, 0x48a1dcff, + 0x7d068508, 0x16820689, 0x8021fe82, 0x232d8202, 0xcc4cefff, 0xf0271b82, 0x00ff34b3, 0x8234b31b, 0x4c242f38, 0xef0e08cc, 0xb4f794f8, 0x2c00ff15, + 0x1282142e, 0xecd12324, 0x048200ff, 0x10820a82, 0x17834b82, 0x33205782, 0x16823482, 0x8206f469, 0xecd12106, 0xdc224b82, 0x1b82142e, 0xff233883, + 0x82ecd1d3, 0x8206832d, 0xcccc213f, 0x54821684, 0x83343321, 0x19ea2779, 0xff156b9a, 0x0d82f3ff, 0xeb300582, 0xfcffff84, 0xffff87f6, 0xff1e05f5, + 0x08ccfaff, 0x0022c982, 0x0a825c8f, 0x8c71bd22, 0xe6210582, 0x225a8266, 0x839a99fa, 0x4ade224f, 0x0557513e, 0x80e1ff2d, 0xebffff00, 0xffffb89e, + 0x82c235e8, 0xb3c72831, 0x00ff0632, 0x8290c209, 0xe60726aa, 0x0800ff68, 0x23378266, 0xce4c0a00, 0x00323782, 0xffff7f33, 0x9899d8ff, 0xcc2900ff, + 0xcfffffcd, 0x8783d04c, 0x8233c221, 0xa2ff2133, 0x04824983, 0x00ff1523, 0x2da98210, 0xcc4c1200, 0x660a00ff, 0x1800ff66, 0x4d82ce4c, 0x66e61a22, + 0x392a4283, 0xffffa470, 0xffc275d1, 0x9c832e00, 0xa470c722, 0xdc214283, 0x27f88311, 0xff28dce0, 0x5278edff, 0x7a320482, 0xe4ffffe2, 0xff08e23a, + 0x72fdd5ff, 0x332000ff, 0x96820532, 0x82cc4c21, 0x9905277a, 0x0f00ff9a, 0x53822adc, 0x703d1122, 0x220a4c41, 0x4100ff33, 0xcd20064c, 0xe7225383, + 0xf182cdcc, 0x51b8ea2a, 0x07f5ffff, 0xf1ffffae, 0xef227983, 0x53821e05, 0x82d9e221, 0xd7162142, 0x2134837b, 0x4082d0f7, 0xdfcff722, 0x912a5582, + 0x0100ff68, 0xffff21d0, 0xe682e6f0, 0x826f0a21, 0x30837b13, 0x48203021, 0xfe220690, 0x4018e02f, 0x1638119f, 0x00ffdaae, 0x0544b6b6, 0x8081ffff, + 0xbdffff00, 0xff150080, 0x0080b1ff, 0xc027d982, 0xffff6666, 0x82cc4cc4, 0x66b6230a, 0x06820868, 0x3233f127, 0xb30c00ff, 0x05864533, 0x0f002008, + 0x088b33b3, 0x334701ff, 0x00ff0634, 0x8bb89e0b, 0xeb0900ff, 0x0600ff86, 0x00ff4095, 0x82f66804, 0x8260210e, 0x4821cc82, 0x22bd8226, 0x823e0a90, + 0x66c83464, 0xff370666, 0xcdcc6c00, 0xbfffff15, 0x00ffff7f, 0x82333333, 0x7ade2817, 0xffff06e1, 0x82295ccf, 0x8fd82765, 0xd6ffff5c, 0x0a823333, + 0x0180cc22, 0xf5217783, 0x277782b3, 0xff12e307, 0x9a99f7ff, 0xbb215582, 0x237782a6, 0x0080c700, 0xf12f3382, 0x00ffae47, 0xff343311, 0x6766f5ff, + 0x821400ff, 0xfaff322a, 0x00ffcd4c, 0x0867e616, 0xffb4f70e, 0x34739401, 0x314b8215, 0xff281cce, 0xcc4c3c00, 0x0ae7ffff, 0x2300ff3e, 0x0482ce4c, + 0x08004025, 0x830800ff, 0x2b0822d6, 0x29b94d84, 0x4daec721, 0x80650cb9, 0xcecc2105, 0xdc21c882, 0x268982b3, 0xa432b3dc, 0x82c3ffff, 0x3100230a, + 0xab8366e6, 0xab830b20, 0xb3110022, 0x099a8e18, 0x5218b320, 0x601807c0, 0xf42018bc, 0xce24df84, 0x728b9a19, 0x23204c86, 0x5c82bd83, 0x1924b383, + 0xf7ffff9a, 0x00207283, 0x221a524e, 0x860080f3, 0xcceb22a8, 0x836882cc, 0x202f830f, 0x823b8408, 0x9a1921f9, 0x3222b384, 0x5b8400ff, 0x7220b282, + 0x73822682, 0x7f822182, 0x9c980720, 0x200b394e, 0x835a824c, 0x829682db, 0x833382e7, 0x26b283f5, 0xffffa433, 0x8333b3dc, 0x84342004, 0x82cd2072, + 0x66e62177, 0x988a7282, 0x8daec721, 0x25a38798, 0x1400ff8b, 0x4c4f3433, 0x225d8209, 0x82852b08, 0x323322b3, 0x21ae8205, 0xc3410040, 0xe7ff2305, + 0xd7413d0a, 0x1cce2306, 0x66828b29, 0x3373f422, 0x690c4e5e, 0x112306b3, 0x820834b3, 0x4e112053, 0x7b2005ec, 0x2206df4e, 0x8285ab11, 0x0b002933, + 0xff06cd8c, 0xd7e33100, 0x18222182, 0x5086c3f5, 0x85c0dc21, 0x82082064, 0x82d420b6, 0x83082031, 0x8bff207a, 0x523821a0, 0xf84fa08c, 0x5238210a, + 0x220df84f, 0x83333308, 0x837c2045, 0xcd4c23bb, 0x5b84ffff, 0x09823c20, 0xf5180023, 0x222a82c2, 0x82d8e331, 0x8c0b23e1, 0x275f07cc, 0x00af1806, + 0x16ae500f, 0xf4ffff2c, 0x4b073473, 0x8c7bffff, 0x715215cc, 0x52ff2005, 0x8021066a, 0xdc481800, 0x0cc6521e, 0x10832d83, 0x46180820, 0xdb27166b, + 0xff152cfb, 0x184c0d00, 0x8212cb75, 0x30178231, 0x4cf5ffff, 0x0a00ffcc, 0xffff34b3, 0x8b34b3f2, 0x85068508, 0x821b8316, 0x8217828d, 0x861e835f, + 0x82328428, 0x088b2d3c, 0x00ffef0e, 0xff33b386, 0xe2ba6f01, 0x01226882, 0x8b643333, 0x01002305, 0x09826766, 0xffaec726, 0xcdcc0000, 0xa3220982, + 0x878208d6, 0x41666621, 0x14220679, 0x69413333, 0x833b2022, 0x17694144, 0x32330f2c, 0x540e00ff, 0x1000ff7a, 0xb782cecc, 0x99120023, 0x08bd6f9a, + 0x24098b60, 0x3473f4ff, 0x79494407, 0x0b239a85, 0x42069899, 0x49440d0a, 0xb3dc2227, 0x20bc8234, 0x31eb82e9, 0x66e6e1ff, 0x190200ff, 0xff086d9a, + 0xcc4c9a00, 0x764c0dfb, 0xe35f2789, 0xb4ffffd7, 0x91828ed7, 0x67e68132, 0x2b9affff, 0x00ff1584, 0xff32b345, 0x6766c9ff, 0x012e1582, 0xff8f9a19, + 0x9a990000, 0x4c0400ff, 0x05828bcd, 0x42666621, 0x240817b3, 0x80f7ffff, 0xff838b00, 0xccccfdff, 0x19f9ffff, 0xfcffff9a, 0x8b089a19, 0x62ffff07, + 0xffff66e6, 0x159a19d6, 0x0842829a, 0x33b30c26, 0x660500ff, 0x0900ff66, 0x00ff0080, 0x089a9908, 0x660001ff, 0x35ffff68, 0xff05cc4c, 0x0080e6ff, + 0xe8ffff88, 0xff212082, 0x245082ea, 0xb3e0ffff, 0x18214534, 0x6666ed23, 0x291c828b, 0x8b3233ef, 0xccf0ffff, 0x8044ffce, 0x00ff210a, 0x220b2145, + 0x459999c4, 0xcc202321, 0xff21e582, 0x22f083f2, 0x8200800c, 0x42f42059, 0x214506fb, 0x870b2007, 0x4594201a, 0x4c27081d, 0x2300ffcc, 0x4472ce4c, + 0xce2206c8, 0x92839a19, 0x9999f328, 0xefffff06, 0x9883e13a, 0x8b1ec521, 0x07194598, 0xe23a0f22, 0x69061945, 0x0c3606ad, 0x0e066766, 0x5a01ffef, + 0x00ff0080, 0x1533b3ea, 0x281000ff, 0xc88206f6, 0x820ad721, 0x83092034, 0x82048216, 0xcc0b230a, 0x068308cd, 0xff3cca30, 0x8075f6ff, 0x8a0900ff, + 0xf4ffff40, 0x7a830636, 0x0ad7ef22, 0xd9227a82, 0x7a8270fd, 0xc4f5ec2c, 0xf52d00ff, 0x1a00ffc2, 0x048446e1, 0x4e820820, 0x84a47021, 0x82052004, + 0xfe5421c3, 0x55220482, 0x0082ff00, 0x00ffbe2a, 0xff7c7f0d, 0xf6aaf7ff, 0x57221382, 0x0a83080a, 0x08275b82, 0xffff8255, 0x820681f2, 0x83ff2022, + 0xf4a8211e, 0x08201884, 0x97217082, 0x2704825a, 0xff05de8f, 0x9819e5ff, 0x1e2b0482, 0xd2ffffb8, 0x00ff0100, 0x82ae0713, 0x0526229f, 0x826e8220, + 0x820720c3, 0xc90b220c, 0x84ac82ba, 0xc08a21c3, 0x33213682, 0x20ac8333, 0x850682f4, 0x20c88216, 0x22b18240, 0x824636f4, 0x82c38259, 0x82ff2033, + 0x235082c4, 0xffff3d0a, 0xff21c883, 0x835f82e5, 0x222082c8, 0x823d8af4, 0x146e21c3, 0xf7227a82, 0xaf827faa, 0x0023a487, 0x82840000, 0xf6a8219f, + 0xaa210482, 0x2229827e, 0x8402abf7, 0x23e2850a, 0x787ef2ff, 0x54212d82, 0x211382f1, 0x9d8284ab, 0x636e0b22, 0x91238c82, 0x82ff0568, 0x83482059, + 0x22a682c3, 0x8346f6ec, 0xff3e2577, 0xedfcd9ff, 0x22095341, 0x820436f4, 0x50f82145, 0x7521b082, 0x83b58481, 0x052b56b0, 0xc335f427, 0x8a0900ff, + 0x2116827f, 0x9a82c275, 0x82fcc921, 0x06bf4137, 0x90022626, 0x1300ff8b, 0xd220c783, 0xc7830483, 0xba20cc82, 0xf4229d82, 0x7e83ec91, 0xc783ea20, + 0x0024a887, 0xff060100, 0x5521a886, 0x31a88712, 0xff022b04, 0xfed4fbff, 0x730500ff, 0xfdfffff8, 0x098286eb, 0x83817521, 0x82052065, 0x250c8206, + 0x00ff0476, 0x20821402, 0xf6280424, 0x2f8200ff, 0x6f21de83, 0x218c828a, 0xde86d077, 0x0025e384, 0xffc3f52d, 0x82e382ff, 0xfcd922bd, 0x066e41ec, + 0x0000ff24, 0x8b82ae07, 0x43482121, 0xff23059a, 0x820080f6, 0x051a633a, 0x06820b20, 0x87211682, 0x210482ae, 0xcc82028b, 0x78c90b22, 0x8209da41, + 0x84ff20df, 0x21e38254, 0x6382ff3c, 0x85ff4621, 0x0b0023de, 0x5282146e, 0x82ec9121, 0x21bf8a7e, 0xbf83fe74, 0xb2820220, 0x847a7421, 0x830682bf, + 0x837c200c, 0x837a20bf, 0x878420ba, 0x540821bf, 0x0484cf82, 0x42000022, 0x2607a042, 0x00ff0eab, 0x820c5708, 0x89f422b8, 0x22a382f2, 0x8205e866, + 0x34332170, 0xe6227a82, 0x8a829e68, 0xb1ffff22, 0xff215782, 0x23c18345, 0x15cd4c15, 0x0e0d6518, 0x82074449, 0x181120c7, 0x492917b4, 0x332109a0, + 0x05b258ff, 0xcd4cee26, 0x6bdb088b, 0xf7225e82, 0x1e823333, 0xcdccf825, 0x180700ff, 0x8208b259, 0x8608205e, 0x82168411, 0x054d41b4, 0x1b821582, + 0xff212882, 0x977c18ff, 0x05b37709, 0x59181184, 0x332608a2, 0x14f8088b, 0x496214fb, 0x07267d08, 0x71ff5421, 0x1423053a, 0x7afff428, 0x638219b7, + 0x29740a20, 0x0c88730e, 0x0000ff24, 0x8c73c400, 0x5f082008, 0x8c200920, 0x21088c73, 0x8c73ced8, 0x06ad5e13, 0x07b66518, 0xf25ef283, 0x83068506, + 0x8bcc20bf, 0xffff21db, 0x82063c62, 0x255082c0, 0xffffae87, 0x377cb8f1, 0x8c6c210e, 0x8a07f476, 0x48e121a4, 0xc021a487, 0x20a98200, 0x83a483c0, + 0xf9ff221e, 0x2cae82c0, 0xff3cffff, 0xb0def5ff, 0x3f0600ff, 0x201e83f8, 0x0d3b6300, 0x32271426, 0xe0ebffff, 0x2107615a, 0x438280dd, 0x2c6ae320, + 0xe6f32305, 0x90730666, 0x8b902637, 0x470e00ff, 0x73c886ae, 0x8c200c90, 0x7e06aa7e, 0xb483069a, 0xc883a485, 0xd563a48a, 0x18042d09, 0xfeffffd4, + 0x00ff1a6f, 0x8b181904, 0x0683bf82, 0x17200c82, 0x01270a82, 0x00ffe08f, 0x823c1f03, 0x40202104, 0x0029da86, 0x05749308, 0x1f1400ff, 0x21048284, + 0x94732c27, 0x05235313, 0x8a62f720, 0xf8ff2307, 0xa96110d8, 0x17ae7e12, 0x78220023, 0x23df8550, 0xf8281400, 0x8b12857f, 0x155074bb, 0xffd01725, + 0x828f0100, 0x200322d2, 0x20bb8340, 0x7dbb8200, 0x002b094c, 0x00ffc400, 0xff48210a, 0x85c0f9ff, 0x0ec27618, 0x82ccd821, 0xbe1f21da, 0x4c208482, + 0x22204882, 0x210b357d, 0xc2769819, 0x82cc2020, 0x8207203d, 0xf7ff28fb, 0x088b3433, 0x186b24fb, 0x255cf86e, 0x01ff2f0e, 0x72824cb5, 0x9a19d022, + 0xca286882, 0x00ff34b3, 0x0566e64f, 0x5f056e5d, 0x6b271303, 0xfbffff06, 0x828b0040, 0x60260805, 0xfeffff00, 0xffff1098, 0xffa410fc, 0x0060fdff, + 0xffff7208, 0x050a57ef, 0xf8dcffff, 0xe8ffff52, 0xffffba9e, 0x2b83c0d2, 0x48e1dc27, 0x611700ff, 0x23218246, 0xf6a81000, 0xfc262182, 0x00ff281c, + 0x4282a002, 0x6766fb27, 0x670100ff, 0x235182f0, 0x088b3333, 0xee206083, 0x08039f18, 0x9e18ff20, 0xfb2609cf, 0xffff0714, 0x3182c0ca, 0x9a19b022, + 0xf8264182, 0xffff71fd, 0x0f8280f5, 0x8f42fc27, 0xb3f3ffff, 0x28948232, 0x08ce4cf3, 0x6633ffff, 0x0a166f66, 0x83ff7b21, 0x00ff2b45, 0x8b85ab11, + 0x0634f708, 0x1c8274f7, 0x7003002d, 0x0000ff62, 0x00ff018e, 0x82806a03, 0x9b162180, 0x432c0982, 0x00ff08d6, 0xff717d0d, 0xe17a2800, 0xc7296382, + 0x00ff2611, 0x050bd7aa, 0x206082a2, 0x2dc38221, 0xffcd4c19, 0x142ef9ff, 0x801900ff, 0x2c828b00, 0x0c820683, 0xff3e4a26, 0xf2d20600, 0x0526e482, + 0x0c00ff1e, 0x8582b2dd, 0xa430b62c, 0x8f22ffff, 0x74fb055c, 0x6318f707, 0xff24183a, 0x9a99cc00, 0x0c279083, 0xffff32b3, 0x82cc4cfc, 0xce4c323e, + 0x0a00ff84, 0xfb080080, 0x7cffffc6, 0x5b159a99, 0x228c825b, 0x82d7e3fc, 0x66e62420, 0x83fbffff, 0x66fe2104, 0xe8210983, 0x218582f6, 0x0682fbff, + 0xe9201683, 0x44113467, 0x4118078e, 0x30231268, 0x78bb0000, 0x72820af9, 0x82482121, 0x3d062226, 0x078d4471, 0x703d0622, 0xff290a84, 0xce0c0000, + 0xd7f5ffff, 0x210e828e, 0x048233b3, 0x82cecc21, 0xffff24fc, 0x83155bff, 0x91682093, 0x66e62198, 0x210ac457, 0x988f7ae9, 0x79825b20, 0x9b9aff20, + 0x14624118, 0x08228d86, 0xb6835bbb, 0x823e4a21, 0xc2ca2287, 0x2197828b, 0x0a82cccc, 0x2105477e, 0x021008ce, 0x3a9f01d4, 0x338afeff, 0xdfffff34, + 0xff156666, 0x1058fbff, 0xb00400ff, 0x00ff8b20, 0x823c9f07, 0xf0a7210a, 0xb0220482, 0x058308a4, 0x04862120, 0x3b9f0722, 0x04221f82, 0x2f82a4b0, + 0x82df4f21, 0x800f2a1a, 0xf0ffff00, 0xff050080, 0x830a8300, 0x210a8204, 0x3098b004, 0x56820420, 0x4ffbff29, 0xffff8be0, 0x85c460f8, 0x210f8276, + 0x4684085c, 0x56864b8b, 0xfd26309a, 0xffff33b3, 0xc282b3fd, 0x66e6fc29, 0xccfeffff, 0x82ffffcc, 0x828b2009, 0x8206834b, 0xaaf1260c, 0x270100ff, + 0x262582f0, 0x00ffefa7, 0x86105802, 0x83a78566, 0x23718661, 0xf6a8fdff, 0xf0214b91, 0x824b84a4, 0x214b8206, 0x4b916ce7, 0x411a3441, 0x6684090e, + 0x00377185, 0xff008020, 0x008048ff, 0xe9ffff15, 0xff8bf6e8, 0x0a17eeff, 0x831100ff, 0x1600260a, 0x8b080a17, 0x840683ff, 0x82048611, 0x83848215, + 0x821b8215, 0x21328228, 0x38829a19, 0x66e6e922, 0xff202d82, 0x11830682, 0x16849920, 0xe6215482, 0x282d8266, 0x34330701, 0x337800ff, 0x20668234, + 0x367183cf, 0x05ccccff, 0x66fbffff, 0x8e888b66, 0xe60000ff, 0x0300ff66, 0x820834b3, 0x3e37270a, 0x873000ff, 0x0a8205ae, 0xfffe2425, 0x82660e00, + 0x620c271a, 0x0b00ffb0, 0x0e827b94, 0xff14ae26, 0xa5b0feff, 0x0c222982, 0x0a823eca, 0xff88d62c, 0x0a570900, 0x8af4ffff, 0x7382ffc0, 0xf3231e82, + 0x82083233, 0xbef1260a, 0xecfaffff, 0x2248828c, 0x82aa1105, 0x7e0e214d, 0x0c220a82, 0x0a827ad4, 0x82020921, 0xf6682a4e, 0xb0f6ffff, 0x0100ff98, + 0x22098228, 0x82ec31f3, 0x4d012153, 0xf1224982, 0x4e82c251, 0xf323a583, 0x61ff9899, 0xff2b0570, 0x0e0868e6, 0xd201ffaf, 0x82eb34b3, 0x4c6d27c3, + 0x9200ffcc, 0xc38233b3, 0x9a999625, 0x8496ffff, 0x1a2a550a, 0xd5f85f24, 0x2d8234f7, 0x0681f327, 0x800c00ff, 0x08995400, 0x84fa7e21, 0x227b820f, + 0x827d7f0c, 0x1e85260a, 0x421400ff, 0x088e528f, 0x82e27a21, 0x7888251a, 0x76ffff52, 0x00216383, 0x2279836a, 0x56cd4c69, 0xa9271d68, 0xffff6666, + 0x8232b356, 0x46532025, 0x10250543, 0x00ffcdcc, 0x223c830e, 0x5133330f, 0x588205fc, 0x2e0a4d56, 0x8bcdccf0, 0x33efffff, 0xffff0833, 0x559a195f, + 0xfb2217b6, 0xcd640634, 0x25691805, 0x0b744c08, 0x8634b321, 0x83698464, 0x2b64825d, 0x8b34b352, 0xf8af0e05, 0x15b4f714, 0xf7203bad, 0xf1566c82, + 0x4c34200d, 0x082205ac, 0xa09734fb, 0xff2a6196, 0x33b35200, 0x56ffff07, 0x04829a99, 0x201fae41, 0x2dc88395, 0x05ce4c69, 0x8777ffff, 0x76ffffae, + 0x715632b3, 0x71bd210d, 0xf3228882, 0xbc418380, 0x41ff2006, 0xa0241ad7, 0x34f72b07, 0x251dae41, 0xff666669, 0x638396ff, 0x83920021, 0x99932279, + 0x2f6e829a, 0xffcc4cad, 0x9a19ffff, 0xf82f0e05, 0x4b15eb14, 0x5420f184, 0x2306ca77, 0x86abf1ff, 0x5425ea82, 0xfb088b7a, 0x0eab5694, 0xff261482, + 0x86ab1100, 0x0856cb08, 0x11307507, 0x84144849, 0x2dfb6962, 0x8620628b, 0x18089375, 0x2010b867, 0x07b841b3, 0x49ffff22, 0x0128ec82, 0x1500a056, + 0x14fb14fb, 0xf324e682, 0xffff707d, 0x002d0483, 0xff1f0500, 0x00c0ebff, 0x7d0c00ff, 0x21138271, 0xed669082, 0x00ff240a, 0x43004014, 0x7f580616, + 0x49002805, 0x00ff9a59, 0x82345349, 0x4c2d2244, 0x23eb82cc, 0x5c4feeff, 0x04828382, 0xb0f1ff23, 0xdd9e18a4, 0x5c4f2114, 0x11224382, 0x5982a4b0, + 0x34b3d223, 0x263f8207, 0xffff4861, 0x41b89eb6, 0x9a5706a1, 0x576a9005, 0x3c820795, 0x9b821b82, 0xa5838020, 0x08008025, 0x84f714fb, 0x527821c4, + 0x8e21b582, 0x59bf8214, 0x4a830825, 0x2f0e082e, 0x4c4501ff, 0x1574f7cc, 0xb35a00ff, 0x5910cf42, 0x4b271ec1, 0x0d00ff06, 0x826bcc4c, 0x9132209c, + 0x0753413c, 0x20166159, 0x203c8273, 0x23a78215, 0xcc4cccff, 0x06304082, 0xffffcccc, 0xff34b3ef, 0xce4cf8ff, 0x4cedffff, 0x322a0e84, 0x33f9ffff, + 0xffff0834, 0x1482ccee, 0x09820a82, 0x081e9818, 0x00230e83, 0x82ce4c10, 0x33e0251e, 0x4c00ff34, 0xff2f4883, 0x0699993a, 0x3de0ffff, 0xb3ffff70, + 0x830534b3, 0x83332040, 0x224a8259, 0x861f45ed, 0xaeef245e, 0x8200ff14, 0x82082072, 0xa4b02119, 0x19820a84, 0xffae4724, 0x82821200, 0xcd211982, + 0x295982ff, 0x00ff08cc, 0xff3e8a15, 0x48823300, 0xff20af82, 0x59099642, 0x7e820f72, 0x10fa8b18, 0x85ab3222, 0x0d25e382, 0x05ab7b54, 0x0e03434b, + 0x5408505a, 0x3c860795, 0x11237682, 0x828b85ab, 0xb35a2277, 0x213c8233, 0x1182cc47, 0x5c4fac2d, 0x0400ff05, 0x00ff66e6, 0x8286eb0b, 0x27a28304, + 0xff1ec507, 0x66e60c00, 0x06832b83, 0xff231685, 0x85e23af8, 0xf4ff232a, 0x46827a14, 0xcc472008, 0x53ffffcc, 0xff05a4b0, 0x34b3baff, 0xffff158b, + 0xff9a19df, 0xcccc4c00, 0xffff6b05, 0x823433b3, 0xe6402959, 0xffff0666, 0x4bcd4ca5, 0xf1231e82, 0x826bcdcc, 0x84902013, 0xb3f22313, 0x3982ab34, + 0x99998a30, 0x70fb0e06, 0x34f844f7, 0xff076b15, 0x76823d00, 0x3200ff22, 0xff214882, 0x280a83cd, 0x9a19c2ff, 0xffff8b08, 0x22ad82e7, 0x824cf8ff, + 0x99e92871, 0xffff7e99, 0x8234b3ed, 0x991f2a82, 0xecffff9a, 0x00ff3233, 0x22318315, 0x82ceccdc, 0x47d7202a, 0x3882058e, 0x4383ff20, 0x0e820486, + 0x6b088b24, 0x3d456b06, 0x0cf4510a, 0x26165052, 0xffff07ab, 0x8271bdb9, 0xf3e822c4, 0x255c8233, 0xff5c4fed, 0xee821200, 0xff08a226, 0x32b33001, + 0x00284e82, 0xffaec714, 0xecd11000, 0x14230486, 0x828b00c0, 0x6e4a249b, 0x5aab0615, 0x4e821b8f, 0xcd180020, 0x8b300e8b, 0x152b4b07, 0x072b065b, + 0x07eb06bb, 0x155b04f7, 0x21164e5a, 0xf06c072b, 0x05006d05, 0x5a150021, 0xfb23087e, 0x8804fb04, 0x2beb2140, 0x0c3b8718, 0x5696268a, 0x79826b20, + 0x0e06ab27, 0xf8bb70fb, 0x207a8334, 0x50aa1811, 0x076b2229, 0x2cedb0ab, 0xff8b076b, 0xc275feff, 0xe6ffffff, 0x21098266, 0x0982e27a, 0x82cdcc21, + 0x1e852f09, 0x2e00ff08, 0xffff6766, 0xff7c54f2, 0x1e832100, 0x281cd522, 0xcd202e82, 0x424c0e42, 0x4042300c, 0x85ab210c, 0x25050a48, 0x7b54eeff, + 0xf170088b, 0x07017105, 0x24088543, 0xffff07ab, 0x344042f9, 0x156e0a29, 0xf707ab06, 0x4154fb14, 0xfb2b2ec6, 0x072b0604, 0xfb0604f7, 0x82154b04, + 0x06242108, 0x42162c42, 0xfb381605, 0xfb0e0624, 0x7d01ff30, 0x01ff3433, 0x15343313, 0xe6fbffff, 0x0700ff66, 0x20054c7e, 0x060444cc, 0x1659f720, + 0x66632205, 0x2d5f8266, 0xff0ad732, 0x9a197f00, 0x0200ff05, 0x2b8210f8, 0xff00602b, 0xd017ffff, 0x670800ff, 0x273f82ae, 0x00ff3088, 0x089a9906, + 0x983d0a88, 0xbbf7ffff, 0x0300ffea, 0xffff86eb, 0x8b66e6f8, 0x0644fb08, 0xf8f3ffff, 0xffff8b52, 0x324d82f5, 0x1018f7ff, 0x68feffff, 0xf4fffff6, + 0x6b08e610, 0x820584fb, 0xe60f2651, 0x23f9ffff, 0x216582d6, 0x935a0a18, 0x04002905, 0xffffdf8f, 0x08ceccfa, 0x0a859782, 0x0623a182, 0x82880a97, + 0xf6e82271, 0x2216828b, 0x82cd4c92, 0x38d6275a, 0x3dffff52, 0x468266e6, 0x8298fd21, 0xc7f4265a, 0x0500ffae, 0x27a782e0, 0xfff6a8f4, 0xf0870a00, + 0x78219c82, 0x272f8252, 0xff7b1403, 0x3ecafdff, 0x33219d82, 0x20748233, 0x22fc8266, 0x83333303, 0xb807234a, 0xdd828b10, 0x82428021, 0x00c0211b, + 0x97217182, 0x2666820a, 0xf708a4b0, 0x82c4f764, 0xfd0422fc, 0x211e8270, 0x635b285c, 0x80092106, 0xfb225e82, 0x1382cecc, 0x0868e62c, 0x54f82f0e, + 0xf71504f7, 0x438207b4, 0x90821a22, 0x10bbd518, 0xa6825b20, 0xeb534020, 0x82f22005, 0xf0ff3d58, 0xffffe27a, 0xffae87f8, 0x846bf6ff, 0x630800ff, + 0xffff08d7, 0xff9a19c9, 0x0b972b00, 0x0a83c782, 0x80d3ff23, 0x200a8200, 0x22a482f6, 0x82b3f7ff, 0x82f020ae, 0x07003173, 0xff8b6766, 0xcc4c0e00, + 0xbf00ff08, 0x2b079a19, 0x2a0e7870, 0xff8b1e05, 0xe2facaff, 0x70d4fb08, 0x0a721c78, 0x4d44180c, 0x2c598207, 0xff52b80b, 0x9c64f9ff, 0xcc0900ff, + 0x269e82cc, 0x00ff649b, 0x827c9405, 0x5c51236d, 0x1585072a, 0xbd08002d, 0x0600ff70, 0x00ff3433, 0x8298990c, 0x330e2934, 0xfb4b0834, 0xb4fb1504, + 0x490eb246, 0xbd5f08b6, 0x18542008, 0x2b0cc4ae, 0x4b06b4f7, 0x64f80e07, 0x3315f4f7, 0xf3273a82, 0x00ffb89e, 0x8248e120, 0xfaf825f6, 0x1200ffe2, + 0xff236782, 0x823233ee, 0x48612f67, 0xff088b77, 0x008082ff, 0x798b7706, 0x2a82ffff, 0xffff8425, 0x829042ed, 0xb3f32814, 0xdfffff34, 0x8305b81e, + 0x0b557243, 0x5f008021, 0xfb2106ea, 0x07f06bb4, 0x68180020, 0xf8210eca, 0x17444334, 0x2106cd41, 0x66180080, 0xff2d105f, 0x66e694ff, 0x33f1feff, + 0xffff1534, 0x312083e7, 0xff32b3e0, 0xce4cdbff, 0x19eeffff, 0xd8ffff9a, 0xac83cc4c, 0x5238e022, 0xe2317f82, 0x00fff668, 0xffa4f00b, 0x3dcae8ff, + 0xab1400ff, 0x27b28284, 0xff52b8ec, 0xc2b5ecff, 0xf732e982, 0xffff5c0f, 0xff7c14f7, 0xcdccf0ff, 0x4c0600ff, 0xef828bce, 0x08989927, 0x664c00ff, + 0x28b78268, 0xf8730500, 0x5b0400ff, 0x2b0482e7, 0x00ff9062, 0xff7f6a05, 0xe8260000, 0xfa212083, 0x21be82e2, 0x7382590c, 0x82b2ff22, 0x1e263c82, + 0xf1ffffb8, 0x50826008, 0x821b2f21, 0x142e2104, 0xba216b83, 0x2f6b82e1, 0xff0552b8, 0x37290e00, 0x47f4ffff, 0x1100ffae, 0xff266b82, 0xff6666f9, + 0x0f481200, 0xcc182205, 0x227782cc, 0x82e2fa16, 0x523824ac, 0x820f00ff, 0x130023cd, 0x65825c8f, 0x822c0821, 0x700a2204, 0x201482a4, 0x22898213, + 0x650ad701, 0xf722063c, 0x198652d8, 0x0a82ff20, 0x0100ff24, 0xc582d6e3, 0xff34f32b, 0xccccf7ff, 0x80f5ffff, 0x2d1e8200, 0xff9a191b, 0x98196b00, + 0xffff8b15, 0x8f828cfa, 0x18a4fb27, 0x9dfbffff, 0x310e8270, 0xffff8295, 0x0818d9ff, 0x05b3ffff, 0xffff061e, 0x9082a6f3, 0x7e4d0027, 0xe1f9ffff, + 0x26ae8248, 0x00ffa1f7, 0x82e6d008, 0xebd12104, 0x13284a82, 0x00ff1e45, 0x05ae4713, 0xd621e482, 0x22a882ca, 0x42ff52b8, 0x0625051f, 0xffff9a99, + 0x05b844ed, 0x3333e722, 0xe9226a82, 0xea821f05, 0x82aec721, 0x33b32190, 0x7022ff82, 0x968208a4, 0xff235582, 0x827b94f5, 0x66e62614, 0x19feffff, + 0x82a58499, 0x3433215f, 0xf5201e82, 0x00214582, 0x83148308, 0x0f002119, 0x0822b983, 0xed823433, 0x182ac984, 0x00ff0080, 0xffcd4c1f, 0x52822400, + 0x82110021, 0x27002442, 0x828b33b3, 0xc71f2899, 0x00ff8bae, 0x820a971d, 0x5c0f2b73, 0x351700ff, 0xebffffc4, 0x1a827b54, 0xb482af82, 0x053d4a22, + 0xf0216582, 0x240482a2, 0x00ff86eb, 0x2155820f, 0xc555f9ff, 0x68662105, 0xb3317a82, 0x0e079899, 0x74f770fb, 0x577d01ff, 0x00ff150a, 0x2e5d821e, + 0xecd1faff, 0x4c1c00ff, 0xf3ffffce, 0x82a33273, 0x72fd21e1, 0x0e225182, 0xb6823233, 0xff666625, 0x82cc0200, 0x83eb201a, 0x82f52029, 0xf1ff230e, + 0x7f5f66e6, 0xffff2205, 0x251983f1, 0xffccccec, 0x2d83fdff, 0xc5821982, 0x829a9921, 0x82f2201e, 0x09002119, 0xf0203383, 0x00261e82, 0xff686607, + 0xf883efff, 0xcc4c0422, 0x08261e82, 0xff0766e6, 0x4e821000, 0x83030021, 0x820f2004, 0x212484a9, 0x48820d00, 0x81833883, 0x849a1921, 0x82d8824e, + 0x2362841e, 0x00800b00, 0x1e827684, 0x4e820a20, 0x7c868c83, 0x90848684, 0x0080f429, 0xff797308, 0x82b3e3ff, 0x82f320c1, 0xe1ff215e, 0xff234982, + 0x8268e6fa, 0x4cdd2179, 0x2005f04c, 0x21b4824c, 0xc349b3f1, 0x00ff2d23, 0x0734b322, 0x30a5ffff, 0x0f00ffa4, 0xff2b9e82, 0xda5ccfba, 0x5f00ff8b, + 0x85089a19, 0x00ff2206, 0x271c8345, 0xff8e024f, 0x5ccf5a00, 0x3d212682, 0x22a18272, 0x4966a622, 0xff312ec1, 0x0a57ddff, 0xffff4b07, 0x15f6a8be, + 0xccc8ffff, 0x82ed83cd, 0x33d721aa, 0xcd28aa82, 0xff8bcecc, 0xcc4cc5ff, 0xff267682, 0xff0080c3, 0x20832800, 0xff221682, 0x20833700, 0x32b3f222, + 0xf7287682, 0x0e079a19, 0x1534f8ab, 0x1805a057, 0x1808bdb3, 0x2107c670, 0x9818e4fb, 0x387908f1, 0xffcc2906, 0x0ad70800, 0x24f8088b, 0x4d0fdf62, + 0xfc201e2a, 0xff233082, 0x82ebd1d3, 0x2edc2f96, 0x2300ff14, 0xff8bcccc, 0x34332c00, 0x6483f708, 0x4d5d0020, 0x06924813, 0x0b4dd818, 0x20084663, + 0x2e52494b, 0x2105454f, 0xe38233b3, 0x86cd4c21, 0x24588304, 0x2b14f708, 0x16de4d15, 0x2116aa4b, 0x7b8234f7, 0x51110021, 0x4b840589, 0x82ffcc21, + 0x8b33210e, 0x180dee51, 0x220c5154, 0x7614f7cb, 0xc9880eca, 0x67512b20, 0x85eb202e, 0x82c9847d, 0x830e2078, 0x208c82ce, 0x21c9828b, 0xca9b14fb, + 0xe682cc20, 0x50629482, 0x058e590b, 0x20057b41, 0x214c834c, 0xb9527c54, 0xabf12113, 0x20081142, 0x9b304274, 0x822beb21, 0x149941ff, 0xae42eb20, + 0x062b212e, 0x2117fc41, 0xc8414b74, 0x848b2017, 0x06aa4b32, 0x33b3f122, 0xcc240e83, 0x14fb088b, 0xcd204b8f, 0x6805314f, 0x914209e8, 0x8206200f, + 0x0e3e66c8, 0x201e5e43, 0x2e33544b, 0x0e06cb29, 0x194601ff, 0x82b4f79a, 0x667f24cd, 0x8200ff66, 0xff052a04, 0x3433feff, 0x350000ff, 0x200983c2, + 0x21098232, 0x0982d863, 0x2305c746, 0x06a4f0a9, 0x29055052, 0xf6285c00, 0x8b34fb06, 0x9a51f715, 0xcca32205, 0x321988cc, 0xff063433, 0x9a994b01, + 0xcf6700ff, 0xffff155c, 0x82323398, 0xa4302a04, 0x7600ff05, 0xcb069a19, 0x2ffb8207, 0xff48210f, 0x0080faff, 0xb80d00ff, 0xf7ffff52, 0x0a267383, + 0xff08c2f5, 0x898394fe, 0xa4301822, 0xb9223882, 0xd38266e6, 0x0bb64e18, 0x2e08bb7c, 0x00ff074b, 0x06df0f06, 0x098000ff, 0x8214f7bb, 0xe67925b6, + 0x1514fc66, 0x2005a87c, 0x05fc7cff, 0x8259e321, 0x82232083, 0xf8082233, 0x17a17c14, 0x0774f72d, 0xfb0694fc, 0x2f0e0774, 0x82d800ff, 0x8e0122b4, + 0x23b4820f, 0x33330100, 0xc221f682, 0x20b48290, 0x28918203, 0x7a94fcff, 0x990500ff, 0x83bb829a, 0x0300250f, 0xff08866b, 0x00232584, 0x82703d01, + 0x830b2025, 0x7d0b25cc, 0x0f00ff70, 0x00294582, 0xff347306, 0x34331000, 0x2225828b, 0x8266e621, 0x831b2036, 0x94e42246, 0x29a2827c, 0x08842bde, + 0x21fbffff, 0x0c820748, 0x1e05f42b, 0xb3fcffff, 0xf4ffff34, 0x27048233, 0xff66e6f9, 0xccccf5ff, 0xed272082, 0xffff3233, 0x8234b3e0, 0xe6fe22dd, + 0x218e8268, 0x2f823233, 0x2a82fe20, 0x19000023, 0x210f8298, 0x5d8266e6, 0x35830020, 0xceccfe27, 0xb30000ff, 0x21148234, 0x978232b3, 0x01221e89, + 0x14829a19, 0x00223e82, 0x23834c01, 0x00215382, 0x21048201, 0x3d84feff, 0xff201e84, 0xcc201e85, 0x38824282, 0xcc010024, 0x58828cce, 0x824c1f21, + 0xcc122210, 0x20dc82ce, 0x2163820a, 0x49820600, 0xcc0b0022, 0x03231482, 0x8397cc4c, 0xcc0425d8, 0x00ff06ce, 0x9921de8b, 0x23a1829a, 0x089919de, + 0xef230682, 0x74ffcdcc, 0xf020050c, 0xf421fa83, 0x22888299, 0x820080f4, 0xb3fe22d8, 0x21938232, 0xd882cdcc, 0x1583fc20, 0x2f820482, 0x6766fa24, + 0x6c4100ff, 0x98992105, 0xaf837f82, 0xd882ff20, 0x0b207f82, 0x80244084, 0x0600ff00, 0xff200482, 0x5f844f82, 0x6683cc20, 0x9682de20, 0x83e4ff21, + 0x82048446, 0x259a820e, 0x3233fbff, 0x60657f06, 0x82548205, 0xf5ff21c9, 0xc382b983, 0xe0247f82, 0x00ff34b3, 0xff22d984, 0x2e4133fe, 0x34b32108, + 0xfe272f82, 0xffff66e6, 0x8268e6ff, 0x827a8225, 0x2035820a, 0x20af84ff, 0x844483ff, 0x85fe201e, 0x68e6211e, 0x2e84c482, 0xd3831984, 0x2d84ff20, + 0x82cecc21, 0x8443823d, 0x07b1411e, 0x98190122, 0x33210f82, 0x82d88232, 0x06d74179, 0x8f820020, 0x9985ff20, 0x44830320, 0x3433f424, 0x3c827f8b, + 0x0720bd82, 0xda953882, 0xccccef22, 0xf0221b82, 0x0d416666, 0x80f42706, 0x0b00ff00, 0xb2846666, 0x00ffcd25, 0x41ce4c01, 0x4d410658, 0x66fa2205, + 0x412f8266, 0x25860768, 0x2582d383, 0x7c773b83, 0x414f8305, 0xef2305ad, 0x828bcdcc, 0x19de2225, 0x25368299, 0xff9a99e4, 0x41831b00, 0xe6210022, + 0x002a6282, 0x07cecc04, 0x00ff978b, 0x6a824c03, 0x53410b20, 0x00ff2406, 0x8434330a, 0x241482d9, 0x05cc4c1f, 0x2586828c, 0x00ffcecc, 0x3e821900, + 0xda830120, 0x82e6ff21, 0x190122af, 0x2259829a, 0x8267e6fe, 0x3233211e, 0x33211e82, 0x22af8433, 0x8ffeffff, 0x9819211e, 0xb3201482, 0xd5421e82, + 0x82cc2005, 0x83002058, 0x42298563, 0xb32105ff, 0x20a18233, 0x824382fe, 0x82682014, 0x82e02058, 0xedff232f, 0xd8823233, 0x8fc2f525, 0x82f9ffff, + 0xf4ff2354, 0x5f43703d, 0x1f052107, 0xfb28d883, 0xff064721, 0x852bdeff, 0xe4223c82, 0xde8b7b94, 0x00ff8b2a, 0xff343310, 0x39740600, 0x2706c743, + 0xff6b7c0b, 0x00800b00, 0x0122dc82, 0xb684713d, 0xfc820520, 0x82856b21, 0x68662104, 0x05222f82, 0x5e829999, 0x03204683, 0x82058241, 0x01002378, + 0x83823333, 0x9583f422, 0x88823b84, 0x84c78b21, 0x215f844f, 0x06820833, 0x67e62122, 0x46837882, 0x66661b27, 0xd42100ff, 0x249a827b, 0xb9de0400, + 0x21328206, 0x2182e1fa, 0x90c20b22, 0x0021b785, 0x8378820a, 0x238382cb, 0xffcd4c1f, 0x0024e185, 0x8acdcc01, 0x10838f82, 0x2605bf43, 0x00ff9a19, + 0x44981900, 0x7a410896, 0x222f8205, 0x82ceccff, 0x99192128, 0x1e840483, 0x04821984, 0xccffff22, 0x87052f42, 0x3233211e, 0xb3413d82, 0x201e8405, + 0x229a82e6, 0x83cc4c01, 0xcecc2267, 0x25798308, 0x1f00ff33, 0xdc82cc4c, 0x1b83f920, 0x34330a22, 0x1482a383, 0xcccc0b22, 0xfa21b383, 0x234082e2, + 0x07b8de04, 0x21220c82, 0xe2827cd4, 0x1b22dd83, 0xe282846b, 0x8367e621, 0x331022e2, 0x271b8233, 0xff9a990f, 0xcc8cf9ff, 0x31061f41, 0x089082f4, + 0x63d4f70e, 0xffff8b15, 0xff0080f6, 0x3682faff, 0x88f7ff21, 0x33fc2204, 0x227d8234, 0x82ce4cf7, 0x9a19226d, 0x21ae8280, 0x3f829899, 0x3f82cc20, + 0x6866062a, 0x05d33b08, 0x0400ff86, 0xfd203883, 0x0023b782, 0x82008006, 0xcc062363, 0x068508cc, 0x0200ff22, 0x1682ad83, 0x26849020, 0xd3db0823, + 0x062e5005, 0x96203e82, 0x00234e85, 0x8432b308, 0x20c1825e, 0x829e8308, 0x00ff2274, 0x82098305, 0x24988588, 0x9b076308, 0x24601806, 0x00ff2e16, + 0x0734b3a6, 0xb3e3ffff, 0x0d00ff34, 0x214b8233, 0x9f824cec, 0xce4c1b22, 0x20208482, 0x2c208b85, 0x8206f74a, 0xecd12442, 0x462c00ff, 0x0683051f, + 0x8209d675, 0x06ed7569, 0x3433df24, 0x4483ffff, 0x83e4ff21, 0x2a58839a, 0xceccf2ff, 0x59ffff08, 0x8207cc4c, 0x82b92027, 0xc6ff2160, 0x04856f82, + 0x8b2d0e82, 0x63067b08, 0xff1cf707, 0x66e69801, 0x25788215, 0xff2a5c0c, 0x2782f5ff, 0xa30b0023, 0x13ef6fd6, 0x2a5cf422, 0xf3234982, 0x8208d6a3, + 0xd9f12206, 0x06ef6f9a, 0x6626f622, 0x4c23c582, 0x70088bcc, 0x09220c4b, 0x54829ad9, 0x66260e2a, 0xff9cfb08, 0x9a193700, 0x09226383, 0x2841e27a, + 0x08002d05, 0x00ff8696, 0xff999908, 0x24db0300, 0x08223982, 0x0a8333b3, 0x54822220, 0xff9a1929, 0x1e66feff, 0x830700ff, 0xa8f93009, 0xffdb08fc, + 0x4200b8ff, 0xffff9005, 0x413473fb, 0xff2305a2, 0x828e82f9, 0x6bf92086, 0x06820515, 0xfdffff22, 0x80222e84, 0x26828600, 0x0800802d, 0xff05433b, + 0x66e6f8ff, 0x82f9ffff, 0xf5ff2166, 0x22088a63, 0x82cd4cf7, 0x67e6276a, 0xf7ffff08, 0x0a826766, 0xffcccc25, 0x8266faff, 0x990821c5, 0x0920b383, + 0xb3253c82, 0xff067b07, 0xb46118ff, 0x05534114, 0x1c00ff22, 0xff224682, 0x8f82b3f3, 0xbb821320, 0xcce3ff23, 0x208f82cc, 0x208f85df, 0x225283d3, + 0x183333dc, 0x4c0e249b, 0xf24113d1, 0x00ff2405, 0x8200c013, 0x82332053, 0x401c214e, 0x0c230982, 0x4208cc4c, 0x20820527, 0x65834620, 0x6f823920, + 0x4c390033, 0x4600ffcc, 0x088b33b3, 0x07b3069b, 0x2cfc1cfb, 0x05837115, 0x0a00ff22, 0xbf414082, 0x400d2305, 0x3c828b00, 0x16850683, 0xa6180020, + 0x0d200c17, 0xff214382, 0x826483f5, 0x736d1816, 0x834c2014, 0xb3f229ca, 0x2f0e0834, 0x04f834f7, 0xd8826283, 0xecffff22, 0x61428282, 0x42db8207, + 0xd9200561, 0x20056142, 0x581b82ee, 0xb3210639, 0x06e24c33, 0x830e305e, 0x06cd4a1e, 0x2600ff22, 0x84680243, 0x60562aa0, 0x088b5660, 0xffff065b, + 0x25af82b9, 0x4c1c00ff, 0xbd41ffcc, 0xff342107, 0x8214bd41, 0x33dc2116, 0xd3250482, 0x088bcccc, 0xe29c18ff, 0x08bd4115, 0x1c20f383, 0x58822d82, + 0x00ffcd22, 0x2005bd41, 0x83e28246, 0xfaca2c71, 0xffff8be1, 0xb61e05d5, 0x8808c08b, 0x00c021f9, 0x2007fc43, 0x43098240, 0xd12012fc, 0x2405017a, + 0x2e2c00ff, 0x18808215, 0x210c919d, 0xfc43142e, 0x3b072207, 0xf66c1873, 0x00c0210e, 0x135f6f18, 0x29447118, 0x1e429882, 0x400d2705, 0xf7088b00, + 0x5f838bb4, 0x24744c20, 0x185f9109, 0x740d1771, 0x43820d24, 0x73181082, 0xb3220bf2, 0x5f86ff34, 0x08255482, 0xc4fb24fb, 0x18218215, 0x420b83aa, + 0xda42077e, 0x18b32008, 0x240c81aa, 0x4c0d00ff, 0x20e382cd, 0x4216820a, 0x4c2113da, 0x069a44cd, 0x5482f220, 0xff0e082b, 0xcccc3101, 0xecbd01ff, + 0x45c8828c, 0x242105af, 0x058644dc, 0x69f7ff23, 0x2264827a, 0x451e85f6, 0x462206af, 0x588234b3, 0x2d453920, 0x05384506, 0x42064545, 0xca833533, + 0x3433dc22, 0x420bc350, 0x16820933, 0x20063342, 0x073342cc, 0x34b3a622, 0x17dc5718, 0x63067b22, 0xf5461a82, 0x80992621, 0x990100ff, 0x08f5469a, + 0xf5466720, 0x727d2e28, 0x0400ff90, 0xdb08cc8c, 0xff4700ff, 0x08f946be, 0x96125722, 0x92215283, 0x06f946ff, 0x08de242b, 0x000000ff, 0x00ff0742, + 0x23db827e, 0x74133afe, 0x210e2342, 0x417634b3, 0x76082005, 0xfb264448, 0x6100ffd4, 0x6382cc4c, 0x26637445, 0x076866cd, 0x43e3ffff, 0xd220269f, + 0x20159f43, 0x109c472e, 0x45ffcd21, 0x322b103a, 0x6b079899, 0xb32e01ff, 0x18ff1534, 0x431ed974, 0x75180d94, 0x8b222d35, 0x5f8ef4fb, 0x4608e045, + 0x0e22443c, 0x114f70fb, 0x707e2406, 0x59ff15a4, 0xfe20057d, 0x0028b182, 0xff008009, 0x9002feff, 0x4c3c1382, 0xfdffffcd, 0xff080a57, 0x67e60a00, + 0x382f00ff, 0x00ff0552, 0xff9a1905, 0xa2251100, 0x66210482, 0x21198266, 0x09828a6c, 0xff323326, 0xbcb6fbff, 0x11202982, 0x0a821e82, 0x19829420, + 0xff231e82, 0x823c9fee, 0x34b32a19, 0xdceeffff, 0xffff0828, 0x2c1e83f0, 0x0590c2c3, 0xffffff8d, 0x00ff3433, 0x23108301, 0x8c3233ff, 0x40820f84, + 0x2a1e6d56, 0xff66e6f9, 0x68e6f7ff, 0x83f6ffff, 0x99fb2509, 0xf5ffff98, 0x00235f82, 0x829a9900, 0xb3ca275f, 0x26ffff33, 0xa8826666, 0xbe820c20, + 0x66040026, 0x0b00ff68, 0x00218982, 0x28a38206, 0xcc4c0a00, 0xb30700ff, 0x3e535634, 0xe6ffff22, 0xff214882, 0x297782ec, 0xcd4ce1ff, 0xdeffff7e, + 0xe7829999, 0xf5288284, 0xffff9a99, 0x050080d6, 0xcc211082, 0x83f882cd, 0x83ee20a7, 0x2019841f, 0x231382ee, 0xcc4c0400, 0xee27ac82, 0x00ff67e6, + 0x82343304, 0x211e82c1, 0x04571100, 0x29138205, 0x08323311, 0x1c00ff93, 0x44826866, 0xcc4cf623, 0x82ed828d, 0x0200236b, 0x098232b3, 0xffffff26, + 0x00800300, 0xf2204082, 0xcb225a83, 0x6a8dcecc, 0x837a9421, 0x22848250, 0x8229dcee, 0x216a855f, 0x6a879ad9, 0xff7b9422, 0x04226a85, 0x09823e4a, + 0x05826a82, 0xffa4b024, 0x48844600, 0x8230d721, 0x3323210a, 0xe62b6882, 0x00fff628, 0x8b9a1934, 0x563a00ff, 0x5b2005e0, 0x0036da82, 0xff0a1740, + 0xcc8c4c00, 0xcf5500ff, 0x1300ff5c, 0xff08c235, 0xc5820a00, 0x832c0021, 0x050023af, 0x20429919, 0x20cb8208, 0x0520420a, 0x20423320, 0x83992009, + 0x8294200a, 0x67662233, 0x072042ff, 0x20421e82, 0x99f92105, 0xe622b882, 0xd2823433, 0x8299aa21, 0x42b22b29, 0xffff1590, 0xff52f8d7, 0x9483ebff, + 0x7bd4e42e, 0xccd4ffff, 0xffff8bcd, 0x08cd4ccf, 0xe5210682, 0x208a82cc, 0x27df8207, 0x34b3e7ff, 0x780d00ff, 0xb3212a83, 0x2b948234, 0xff48e12d, + 0x0080b700, 0x2400ff05, 0x11296b83, 0xc9159899, 0x19f800ff, 0x205d829a, 0x253683f6, 0xffcecc02, 0x1b82f6ff, 0x82065a41, 0xffff28ba, 0xff08cecc, + 0x82e6c2ff, 0x660b229c, 0x2d3b8266, 0xffcdcc08, 0x9a19fcff, 0x4c0900ff, 0x058288cc, 0xff2c6682, 0x089819fe, 0xfb0e078b, 0x9f00ff30, 0x2d261a83, + 0xff15cc4c, 0x0a469200, 0xb3112605, 0x0f00ff33, 0x25048233, 0xffcd4c0e, 0xae821000, 0x08248e82, 0xff8b9999, 0x2005214b, 0x271683fd, 0xff008005, + 0x6666fbff, 0x0a201a82, 0x04203083, 0x0b200483, 0x00226c82, 0x6c829902, 0x046f0c20, 0x33112205, 0x20358233, 0x28ad8210, 0x66e6faff, 0x660e00ff, + 0x83b28468, 0x98192635, 0x4cf9ffff, 0x20a382cd, 0x2093830e, 0x207183f6, 0x21248203, 0x0982ecff, 0x33f6ff28, 0xf1ffff34, 0xcd823433, 0x3233f622, + 0x4c240a82, 0xebffffcc, 0x2206664d, 0x84f2ffff, 0xcccc29d1, 0x00ff8108, 0x0534b306, 0x9823e383, 0x840200ff, 0x22808395, 0x83666601, 0x8b67219f, + 0xf3214082, 0x21bb8219, 0x1682f5ff, 0x8b250483, 0x19f3ffff, 0x2c16829a, 0x07cc4c97, 0x192800ff, 0x00ff8b9a, 0x21638226, 0x33820f00, 0x821c0021, + 0x190023a2, 0xa282ce4c, 0xa2820d20, 0x20055652, 0x20788314, 0x229c82fe, 0x82b30b00, 0xccf2218c, 0x0b221e83, 0x8882cecc, 0xff201482, 0xff211983, + 0x821985eb, 0x84f520a6, 0x82d8205e, 0xdbff2148, 0xcb20da83, 0xea201983, 0xff235c82, 0x839a99c6, 0x4c842290, 0x278582cd, 0xff33b39b, 0xcc4c6400, + 0x7b207e82, 0x8205597e, 0x20118306, 0x221684cd, 0x5b7b00ff, 0x3922052f, 0x22826666, 0x82833420, 0xf668ea2c, 0x992700ff, 0xdcffff98, 0xa183cc8c, + 0xff343326, 0x723df4ff, 0x84068a44, 0x82f42082, 0xf2ff23ca, 0xe18266e6, 0x3383f420, 0xff20ac82, 0xa6849c85, 0x68e6f223, 0x82d483ff, 0x82e3201e, + 0x22ea8348, 0x82d9ffff, 0x23fe84ca, 0x66e6d7ff, 0xa720a183, 0xff27a882, 0xff7fb7ff, 0x83b8ffff, 0x82ff207e, 0x82082010, 0x82be20b3, 0x28003fc5, + 0xffff6766, 0xff0080c8, 0x9a993700, 0x66e6ffff, 0x078b0866, 0xa4f8af0e, 0xfc1554f8, 0x427e0674, 0x05645f16, 0x3683e520, 0x260e575e, 0x7b0654f7, + 0x8243055b, 0xccf22238, 0x276482cd, 0xff3333f5, 0x3433f5ff, 0xf2220a82, 0x7683cccc, 0xff240682, 0xcdcc0a00, 0xff291684, 0x33330d00, 0xa4f7088b, + 0x2d964606, 0x7b064324, 0x6b8205bb, 0x23160862, 0x8b07d4f7, 0xc35e1a84, 0xfb7b3510, 0x54fc15f4, 0x07b4f706, 0xfb0654f8, 0xfb0e07b4, 0xf8d4f730, + 0x580f3359, 0xb0590886, 0x94fb2116, 0x20174b59, 0x2831827e, 0xff66e6f4, 0x34b30700, 0x052843ff, 0x98190b2c, 0xecffff08, 0xffff9a99, 0x048219f4, + 0x0483e920, 0x0483f920, 0x0080e723, 0x221a828b, 0x82cd4cb9, 0xb3c62735, 0x3900ff33, 0xb882cc4c, 0x42424620, 0x85462005, 0x83cd2011, 0x82048216, + 0x212d820e, 0x2d831700, 0x82150021, 0xf9ff3563, 0x00ffcccc, 0xffcdcc12, 0x9a19f5ff, 0x3100ff08, 0x6b079a19, 0x780f0458, 0x4c201049, 0x0e204b82, + 0x24057f59, 0xab088b33, 0x08627806, 0x25249859, 0xfb4b078b, 0x33821574, 0x47822320, 0x82e3ff21, 0x1c002104, 0xff22a782, 0x4c82b3dc, 0x830ef64e, + 0x201782d6, 0x18dd8208, 0x2113ab70, 0x438200ff, 0x3f834982, 0x34204482, 0xcc245484, 0x34fbeb08, 0x580ff958, 0xfb211e94, 0x0e7f61d4, 0xc96c4c20, + 0x18542010, 0x2f0c6ab4, 0x0e06d4f7, 0x15f4f7da, 0xff0616f7, 0x8df70500, 0x052c7982, 0x00ff2b67, 0xffea6603, 0x48610200, 0x42221482, 0x0a82088e, + 0x828f6221, 0x4322080a, 0xfeffff14, 0x00fffce9, 0xffc42006, 0x6ff2fbff, 0x330400ff, 0xff4a0834, 0x08574300, 0xfaffff05, 0x2582e550, 0xff8ae126, + 0xbf5ff5ff, 0xfa27eb82, 0xffffeb51, 0x82761efa, 0xbcff2321, 0x2182f8a8, 0xaaf1fb22, 0xcc213882, 0x26478248, 0xffff85eb, 0x85b8def9, 0xfaff2366, + 0x668372bd, 0x0a827182, 0x45827020, 0xff676626, 0x9a99fcff, 0xf8250982, 0xf7088b52, 0x226a82aa, 0x8215f668, 0x9eaf210e, 0xff245384, 0xbe9f0a00, + 0xae21ae83, 0x21738414, 0x8583cc08, 0x82050a21, 0x920d2127, 0x32260482, 0x0100fff2, 0xab828015, 0xfffa1e26, 0xf49dfdff, 0x45222582, 0x0a82081e, + 0x82f0a721, 0x0c42210a, 0xb3217d82, 0x28e98534, 0x66e6faff, 0x16fb088b, 0x21598206, 0xb8837208, 0x83d69821, 0x8216207d, 0xb89e212d, 0x9c831482, + 0x70204382, 0xbc210a82, 0x205783ec, 0x213d8282, 0x6b853cdf, 0xccfbff23, 0x31bb82cc, 0xff7cff40, 0x7aa9bcff, 0xffffe605, 0x150a97db, 0x4d5914fc, + 0xd755180a, 0x8cdd2108, 0xff242b82, 0x0766e600, 0xda226682, 0x3b5968e6, 0x824c2007, 0x1a3b59be, 0x34732225, 0x8501ff08, 0xb4641836, 0x682b2014, + 0xff240611, 0x66e6ffff, 0x23053c68, 0x9a99eaff, 0x0ae94218, 0xff3e8a26, 0xae87eaff, 0x8f260482, 0xe5ffff5c, 0x2a845278, 0x0a820820, 0xff008026, + 0x9a190000, 0x21072244, 0x32446666, 0x85082005, 0x224c8506, 0x82661500, 0x861a2056, 0xfb08232a, 0xba668b54, 0x276fe605, 0x1574fbdb, 0xbb0634fb, + 0x2107cd44, 0x72451500, 0x82002007, 0x088b2893, 0x00ff06cb, 0x828f821a, 0x7d1522b1, 0x21c88271, 0xf9839082, 0x08707d25, 0x82f7075b, 0x213a88aa, + 0xce829082, 0x86707d21, 0x821a2004, 0x823a8626, 0x1500212f, 0x56181882, 0x5b2d0a89, 0xffaf0e07, 0x5eda0300, 0x21a901ff, 0x3aee8248, 0xfff49d06, + 0x4cf70d00, 0x110e00ff, 0x0800ffec, 0x00ff6ce7, 0x8bc3750f, 0x8244f808, 0x800f347e, 0xff998b00, 0x9418f7ff, 0x990600ff, 0xf2ffff9a, 0x8208b408, + 0x32b3210a, 0x26080a82, 0xffffae07, 0xff68e6fd, 0x5278efff, 0x66f5ffff, 0xf4ffff66, 0xff083c0a, 0xcc4c96ff, 0xba7dffff, 0xffff05e2, 0x82ceccaf, + 0x22d7821f, 0x82e6c2ff, 0x19b9251f, 0x08368b9a, 0x2d071358, 0x71323307, 0x330b00ff, 0xe8ffff34, 0x388266e6, 0x3882fe20, 0xcc000022, 0xfe253d82, + 0xff8c0080, 0x240582ff, 0x190100ff, 0x241a829a, 0xbb0100c0, 0x30898205, 0xff9166e6, 0xcd4cfbff, 0x800900ff, 0x00ff8b00, 0x2e1d830a, 0x9a194f00, + 0x49ffff07, 0x00ffc00a, 0x82ea91df, 0x36f62227, 0x21598287, 0xa182c4f5, 0xffe1fa26, 0xae871000, 0x9e21b582, 0x21ea8277, 0x4d8252f8, 0xbeffff2e, + 0x1b01ff06, 0xfeff3c3f, 0x15b8dea6, 0x4f204782, 0x0021a382, 0x21c38241, 0x09834000, 0x0cccb618, 0xff211183, 0x236e83bf, 0x0080b0ff, 0x0682be83, + 0x1183ff20, 0x0e820486, 0x55828b20, 0x59820683, 0x0dfab618, 0xcc00ff2a, 0x00ff3233, 0x1534b324, 0x4c218282, 0x210482ce, 0x70823233, 0xf6830a20, + 0x82b3f921, 0x3306221a, 0x213c8232, 0x1a83ccf9, 0xff261f82, 0x8bccccf5, 0x0f83ffff, 0x1f82ff20, 0xdb271a82, 0xffffcc4c, 0x82ce4cdb, 0x820a83d7, + 0x8232204b, 0x82309a0a, 0x82408436, 0x854c8246, 0x20508376, 0x20878308, 0x204b8332, 0x204b84cc, 0x9a0a87ce, 0x829d8230, 0x82a7834b, 0x83b782b1, + 0x0600230f, 0x4b84ce4c, 0x50843420, 0xde840520, 0x0020a286, 0x3682309a, 0xde82fe97, 0x4b844584, 0x26052f41, 0x30fb0e05, 0x46f8f4f7, 0xbe470f2f, + 0x1854200c, 0x2611bd57, 0xb3daffff, 0x827e0634, 0x66f432fb, 0xf8ffff66, 0xff863433, 0x9819f4ff, 0xd2ffff08, 0x241082e6, 0x0534b393, 0x0fc85fdb, + 0x3e1edf6f, 0x4c95ffff, 0xffff06cd, 0xff9999c8, 0x9a197bff, 0xf1ffff05, 0xffff9a19, 0xff3233dc, 0x8219ddff, 0xb3e82914, 0xd9ffff34, 0x088be13a, + 0xab217f82, 0x2eb24685, 0x2500ff24, 0x93827b54, 0x85eb0c32, 0x0b00ff8b, 0x00ff67a6, 0xffcccc07, 0x52f80400, 0xe62e0e82, 0x00ff0868, 0xff48212d, + 0xcc4c6c00, 0x5b9c3b05, 0x7e633320, 0x0e002105, 0x0825f318, 0x6a00ff24, 0x5b8233b3, 0x82663721, 0xeb842955, 0xff990584, 0xb0c72300, 0x61830482, + 0x824c1721, 0xcc262266, 0x24b782ce, 0xcc4c2500, 0x05b76806, 0x0654fb27, 0xfb05cb4b, 0x17224a34, 0xf8073b25, 0x499b0694, 0xfc241786, 0x15e4fb64, + 0x4505a545, 0xff240568, 0xff0080ea, 0x6805d444, 0x842c1a9a, 0x0694fc07, 0x0e0784fb, 0xb4f770fb, 0x2230f641, 0x6c0644fb, 0x2c75063d, 0x18f1200a, + 0x250d3047, 0xf1ffffcd, 0x048334b3, 0x23085661, 0x074b0624, 0x6e050d42, 0xb32009e0, 0x65119148, 0x3b200cb8, 0xbc183382, 0xcb222db8, 0xb5417b07, + 0x1134711c, 0xf7069b23, 0x05cc6594, 0xd1418420, 0x7c542107, 0x2b056065, 0x0664f708, 0xf730fb0e, 0x1534f874, 0x2c05c065, 0x802700ff, 0xf9ffff00, + 0x00ff2a5c, 0x22098323, 0x5b1e45ed, 0xff2c0537, 0x084821e5, 0x990c00ff, 0xf3ffff9a, 0x00280482, 0xff343300, 0xccccebff, 0xb3210e82, 0x22048232, + 0x85086666, 0xf3ff2319, 0x1982ce4c, 0x8a82b320, 0x19860020, 0xb55cff20, 0xf0ff2605, 0x00ff3233, 0x2057830f, 0x322382ec, 0x66660b00, 0xe6e9ffff, + 0x0500ff66, 0x2f0834b3, 0x4314f707, 0xa0201a4d, 0xff272782, 0x3cccccba, 0x83a5ffff, 0xccf0227a, 0xa01567ce, 0x4b068b23, 0x170d6727, 0x6666c426, + 0xffff8b08, 0x0d670682, 0xffcb351a, 0x66e608ff, 0x2c00ff15, 0x00ff9a19, 0xff34b30a, 0xcc4c2400, 0x0e840486, 0x08261882, 0xe6a4ffff, 0x05840666, + 0xaf0e0732, 0x14f8b4f8, 0x93067b15, 0x00ff8b07, 0xff90420d, 0x2205b159, 0x5b70bd0a, 0xf5221371, 0x84829042, 0x70bdf22a, 0xff078308, 0x842b4bfe, + 0xe8224682, 0x1382f628, 0x85abec27, 0xabecffff, 0x280a8284, 0x084821e8, 0x57a6ffff, 0x2052820b, 0x241d82ff, 0x541300ff, 0x2b1c827b, 0x00ff33b3, + 0x8b0ad717, 0x1500ff08, 0x002d4783, 0xff9a590f, 0x66a6ebff, 0x28faffff, 0x210982f6, 0x37825c8f, 0x5c4fd728, 0x9961ffff, 0x1583059a, 0x1582f520, + 0xff0a9722, 0x99202986, 0x1522d482, 0x40838f42, 0xcecc6728, 0x0e00ff06, 0xb5823d4a, 0xcd8c0c2b, 0x780900ff, 0x0300ff10, 0x33fb82ee, 0x08b2bd0d, + 0xcf1b00ff, 0x6800ff5b, 0xff053eca, 0x7a945e00, 0x18202b82, 0x0023a683, 0x820a5715, 0xf668364d, 0xa10700ff, 0x1600ff48, 0xff08b8de, 0x727d1800, + 0xb84900ff, 0x222b8252, 0x829a1924, 0x7c08222b, 0x2257826a, 0x824e2208, 0x775e2652, 0x020600ff, 0x21048290, 0x2b820601, 0x84ab1622, 0xa0233682, + 0x82cb0583, 0x83112027, 0x0e0023ef, 0x8a827c54, 0x827b5421, 0xab112432, 0x43db0885, 0xff23073e, 0x8334b3f1, 0xff7c2518, 0xcc4ceeff, 0xff2ab582, + 0xff008028, 0x666615ff, 0x1150ff15, 0xccfc2b05, 0xffff88ce, 0xffccccfd, 0xb54dfcff, 0x33ae2205, 0x23578234, 0xcb66e610, 0x5c2d8c82, 0xff061e05, + 0xe27aecff, 0x66c5ffff, 0x20108266, 0x333f8297, 0x9a998a00, 0x0634fc15, 0x34f807ab, 0x0e076b06, 0xf4f7d4f7, 0x6318f582, 0x4218099f, 0xcb200adf, + 0x19828a83, 0xf8ffff22, 0x18836382, 0x14ae4418, 0x8b10d822, 0x27231782, 0x824b08f0, 0xf7ff282f, 0x00fff628, 0x82343307, 0x0ad72534, 0xcc0800ff, + 0x0024ba83, 0x8b66663f, 0x05226682, 0xe6820020, 0x82080521, 0x73022622, 0x0300fff8, 0x29228217, 0x08209004, 0x8f2000ff, 0xa382bb5c, 0xa0da012c, + 0xbe0200ff, 0x0000fffa, 0x2082d6e3, 0x82761e21, 0x16032330, 0x06820806, 0x6ef20822, 0xba215582, 0x215f821c, 0x7282ce17, 0x8b924d27, 0xfaffff08, + 0x325382e0, 0x7af4faff, 0x88fdffff, 0xfcfffff6, 0xffff68e6, 0x82ec71fb, 0x70df291a, 0xff055ba4, 0x6025feff, 0x40261b82, 0xffffffc4, 0x20829a19, + 0x8248e121, 0xe8fc22b0, 0x215382f6, 0x8183f7ff, 0x824c0721, 0xe1f8224e, 0x21ae8248, 0x538232b3, 0x99000029, 0xfafeff9a, 0x82150080, 0xe6a32375, + 0x06820566, 0x1a040622, 0x532b5682, 0x1b00fff8, 0xffff8aac, 0x8208ace4, 0xfaea1828, 0xb89e2607, 0xabf1ffff, 0x22568286, 0x82e03aef, 0x110027cc, + 0xb2ffffec, 0x7c82f6e8, 0x33336927, 0xcc9600ff, 0x2b0a82ce, 0xffcd4cfb, 0x32b30400, 0xccf9ffff, 0x02200982, 0xf9207583, 0x22050f51, 0x823d4af2, + 0xb5f5273c, 0xf4ffffc3, 0x0a823cca, 0xc435f322, 0xf9279e83, 0x00ffe6db, 0x82105802, 0x6adc2132, 0xaf213c82, 0x218482e0, 0x62825c4f, 0x4c825920, + 0xb3a6ff24, 0x1f820534, 0x8276de21, 0x862b26df, 0x800100ff, 0x21df8200, 0x40823333, 0x3333fc22, 0x06824083, 0xfeffff24, 0x1684cd8c, 0x19212582, + 0x210483db, 0x0a88089a, 0x1982dc20, 0x83f23221, 0x84cc2023, 0x82d58323, 0x82418534, 0x34732151, 0x65823084, 0x8224e621, 0x66942735, 0x6b00ff66, + 0xce839a99, 0x87dd4421, 0x29dc21ce, 0xce841f82, 0x8329dc21, 0x20ce8740, 0x20ce83c2, 0x20ce843e, 0x20ce8ac2, 0x20ce8311, 0x213c826c, 0xce87dfaf, + 0xff215282, 0x835c82ff, 0xd3ed21ce, 0x11217282, 0x827c82ec, 0xfcff236c, 0x40823233, 0x9a19fd22, 0x8e82ce85, 0x3220ce86, 0x9a20ce93, 0x8d21ce87, + 0x27cea30e, 0xffa0baa6, 0x67665800, 0x4f21ce83, 0x2191825c, 0x9b8333b3, 0x7b83ce83, 0xce92f920, 0xce843d20, 0xce85c320, 0x9d41e720, 0x8c6b2008, + 0x0b9d41ce, 0x8367e621, 0x82dc20a8, 0xf27221ce, 0x32219382, 0x204082f0, 0x05575ffc, 0x9d410682, 0x41ce9408, 0x9920259d, 0x27079d41, 0xff3954cb, + 0x84ab3400, 0x3420ce89, 0x4c21ce87, 0x410984cc, 0xb8260a9d, 0xf4ffff52, 0x6c4270bd, 0x82e8200b, 0xfe542148, 0xe9212882, 0x21ce8236, 0x9d4121b0, + 0x91692b07, 0x96ffffec, 0x00ff5278, 0x5182b326, 0x3433ca23, 0x2e4882dc, 0xcdcc5500, 0x4100ff8b, 0x00ff66e6, 0x829a1947, 0x6653330a, 0xffff0866, + 0xffcd4c73, 0x1e850c01, 0x0300ff15, 0x43829919, 0x90166e2a, 0x8cfdffff, 0x0500ffcc, 0x2205f761, 0x8212c308, 0x3a07272d, 0x0700ff5e, 0x0a82f41d, + 0xbae90823, 0x27068208, 0xff861603, 0x021cffff, 0x1d263882, 0xfefffff4, 0x90828825, 0x43fcbe21, 0xbb2605ca, 0xfcffff05, 0x9882fbe9, 0xff1a8f26, + 0x67e6faff, 0x7a221b82, 0x888285e0, 0x56f7ff23, 0x27c68204, 0xff1baff8, 0x10edf8ff, 0xf7220a82, 0x4f822406, 0xfc242e82, 0xe30000ff, 0xfc27d182, + 0x00ff8ae1, 0x8279da01, 0x06413987, 0x2100ff08, 0xffff9d6f, 0x054000d0, 0xb3ec00ff, 0xb8ffff33, 0xff15e2fa, 0x2207ce43, 0x18ffa4b0, 0x250ce4a4, + 0x0728dcb3, 0x7e82ab6b, 0x9a998623, 0x255d8207, 0xff70fda1, 0x2583c0ff, 0x8282d021, 0x83f020d9, 0x4cf5220e, 0x215682ce, 0xc0826b07, 0x0ad7fe22, + 0x8021d782, 0x53c08200, 0x32200575, 0x20052c41, 0x132c41ce, 0x00f0ff28, 0x99a500ff, 0xf882059a, 0xff66f626, 0x9a991100, 0xcc267c82, 0x0e00ffce, + 0xfa45cc4c, 0xaf0e2106, 0xb7f6c918, 0xc383ff20, 0x96831f23, 0xb2c91805, 0xff062b0f, 0x3433e0fe, 0x805f00ff, 0xa1531500, 0x53cc200e, 0xa153059a, + 0x2222821b, 0x82b31c00, 0x5304823e, 0x068506a1, 0x8418ff20, 0x6b220fa9, 0x5f8234fb, 0xcdccd322, 0xc0625483, 0x200a8206, 0x05f755d3, 0x8418f720, + 0x84181248, 0x0e2932a9, 0x00ff70fb, 0xf8900000, 0x05d07914, 0x00ff8425, 0x47eb530e, 0x002705bc, 0x8b85ab11, 0x4a94f708, 0x0e4e0e6c, 0xccc72221, + 0x343382cd, 0xff999909, 0x9a99f1ff, 0x190700ff, 0xefffff9a, 0x00ffcccc, 0x05345b03, 0xff089a26, 0x9a992300, 0x054c588e, 0x113a4c0d, 0xdcffff24, + 0x0a576666, 0xffff2805, 0xff34b3c5, 0x824ccfff, 0x19d32625, 0xc3ffff98, 0x220982cc, 0x82ce4cf8, 0x83902058, 0xcc992b14, 0x00ff05cc, 0xff00800d, + 0x7382f4ff, 0x33040024, 0x515c7732, 0x20928305, 0x05bf6908, 0x83f2ff21, 0x00ec271f, 0xfbffff01, 0xac83cecc, 0x00ff9933, 0x08cc4c0a, 0x34f774fb, + 0xf4ffff05, 0x00ffd9ae, 0x233e8208, 0x7533fbff, 0xcb834d82, 0xb83e0422, 0x23820982, 0x8400ff21, 0x820e200a, 0x0c0023db, 0x2882e550, 0x0d250983, + 0x088bf6e8, 0x2cd882db, 0x8bcdcc20, 0x331c00ff, 0x1300ff33, 0x200482b3, 0x2395820c, 0xcd4c1c00, 0x66217a82, 0x435718b3, 0x15ac220a, 0x0a8c63ff, + 0xa0703282, 0xeb532105, 0x41054543, 0xff280583, 0xcd4c9900, 0xf3ffff06, 0x1c254983, 0xffffcc4c, 0x82ef82e3, 0xff342758, 0x3333dfff, 0xa24e088b, + 0x2150840a, 0x49837c54, 0x5a84ab21, 0xb62407cb, 0x74f70080, 0xa9226982, 0x74410080, 0x20884f0f, 0x33845620, 0x75839e20, 0xcc4c7823, 0x30fd8205, + 0xffff6866, 0xff0080f4, 0x98990100, 0xccebffff, 0x230e85ce, 0x9a99f2ff, 0x20073874, 0x201988f2, 0x822d83fe, 0x07db4c19, 0xcccc542b, 0xb39200ff, + 0xffff0532, 0x05934485, 0xaa73ee20, 0x18542015, 0x5609d4e9, 0xf7210880, 0x05915734, 0xcf7e1b93, 0x06ab2116, 0x94573482, 0x7b542108, 0x650bdb42, + 0x1182051c, 0x45cd4c21, 0x99830d36, 0xab00ff24, 0xaa863433, 0x660d0023, 0x29c08466, 0x331400ff, 0xfeffff32, 0x0e85a470, 0x94f2ff24, 0x0a87087c, + 0x820a9721, 0x29ee8319, 0xff3ecaeb, 0x9899f2ff, 0x3b6dffff, 0xb3612e05, 0x78ffff34, 0x0e05cc4c, 0x24f730fb, 0x056051f8, 0x4309fe4e, 0xff240851, + 0x0a57dfff, 0x0857c318, 0x05206383, 0x00299982, 0xff523800, 0x66660500, 0x8369828b, 0x820c8206, 0xffff2316, 0x0987aec7, 0x825c8f21, 0xa820221a, + 0x09c04ef6, 0x700d9658, 0x6f8a0d95, 0x9a99ce22, 0x362a6f82, 0xffff66e6, 0xffcccce6, 0x09832800, 0xae82cd20, 0x830c0021, 0x4cc322c8, 0x255882cc, + 0xff008003, 0x0483efff, 0x2382f420, 0x4ceeff26, 0xeeffffce, 0xff242382, 0x086666fc, 0xe8830a82, 0x1e83fc20, 0x00271983, 0xff32330b, 0x824cfdff, + 0x4c11274c, 0xff8508ce, 0x53831d00, 0x00213e83, 0x07b0591a, 0x83120021, 0xbcff2158, 0x194e4518, 0x2916c771, 0xe65f00ff, 0xffff0766, 0x236bccfa, + 0xfaff2806, 0x00ff9999, 0x82cc4c00, 0x05425c13, 0x0682fa20, 0x99230c83, 0x83ffffff, 0x232a83a4, 0x32330000, 0xa020a982, 0x62506f8c, 0x206f980c, + 0x386f8443, 0xff70bde2, 0x9a99e8ff, 0x42edffff, 0xdbffff8f, 0xff8b66e6, 0x9a99d7ff, 0x20068208, 0x227c82b9, 0x824c3900, 0x82c62090, 0x0513686f, + 0x200e6f67, 0x095574ff, 0x5917035b, 0xff2b2f74, 0xd7e31000, 0xe1ffff06, 0x82ad9a99, 0x8f822c95, 0xcc2c00ff, 0x00ff8bcc, 0x82343331, 0x4d002d95, + 0x00ff0080, 0xff67e62d, 0xcccc4200, 0x19270482, 0x1e00ff9a, 0x8208ce4c, 0x66662120, 0x08172742, 0x0e078b21, 0x14f730fb, 0xb3fc00ff, 0x00ff1533, + 0xff333377, 0x99192200, 0x1100ff05, 0x00ff0100, 0x82cecc04, 0x32b32609, 0x33f6ffff, 0x220e8232, 0x827a66e6, 0x2115834f, 0x1f82efff, 0xff3d1584, + 0x7acd4cee, 0x19fbffff, 0xffff0899, 0xff343377, 0x67e6d8ff, 0x65ffff05, 0xf70766e6, 0x0f7d4474, 0x1811f851, 0x200c91c7, 0xc14518fb, 0x0809440f, + 0xa700ff22, 0x0d7b5082, 0xf9ff2305, 0x6182ce4c, 0x8f02ef22, 0x98827782, 0x49eeff26, 0x0900ff79, 0xff24ac82, 0x9c1f25fb, 0x06828782, 0x1000ff24, + 0x1582ffff, 0x83c9d621, 0x22d782c2, 0x8377fe10, 0x826720c2, 0xca2826c1, 0x0b00ff3e, 0x22e78399, 0x529a9995, 0x2d441705, 0xb37c2318, 0x1f520733, + 0x15143d05, 0x59ddffff, 0x00ff079a, 0xffcccc5a, 0x00c0f0ff, 0x334500ff, 0xff8b3c34, 0x66e6a0ff, 0x319c4718, 0x2a05ba44, 0xff9a993b, 0x3433d7ff, + 0x833200ff, 0x82c820dd, 0x0e00265a, 0xfb083433, 0x2e4d77b0, 0x07b0f722, 0x21167378, 0x9d8d66c4, 0x24bb4018, 0x5f229d85, 0xe4829a19, 0xdaa43022, + 0xcf29f482, 0x0f00ff5c, 0xff080040, 0x081a7900, 0x5e458420, 0x052c5005, 0x33b31123, 0x781c828b, 0x8c440b1a, 0xef0e2f08, 0x668c01ff, 0x6801ff66, + 0xff1548e1, 0x56822500, 0x38e7ff24, 0x51820552, 0x2206067c, 0x6e1200ff, 0x9e200667, 0x613c4583, 0xff063433, 0x68e61e00, 0x1900ff8b, 0xffff9819, + 0x8b66e6e6, 0x19e1ffff, 0x0736089a, 0xc82c0882, 0xffff66e6, 0x5b0080da, 0x99caffff, 0x9e461e82, 0x00942705, 0xff057002, 0x5e83ddff, 0x6e82ea20, + 0x83d6ff21, 0x83f22004, 0x66d3220e, 0x20578266, 0x200683ff, 0x231682ff, 0x0d00ff67, 0xdd2e4283, 0x00ff9919, 0x089a9915, 0x0094ffff, 0x3c82a600, + 0x7b94ca22, 0x37831b82, 0x1f85da23, 0x207e82bb, 0x20738237, 0x827382e0, 0x8266208d, 0xec11218c, 0x51820482, 0xee1e0023, 0x22a98515, 0x829e0633, + 0x23be8326, 0x9a990500, 0xcd26d283, 0x800a00ff, 0xe8850800, 0xc7180023, 0x20e882ae, 0x831a8416, 0x821a203d, 0x080026b0, 0x00ffcc0c, 0x05774c1b, + 0xff210683, 0x25168300, 0x34f3f7ff, 0x2a8300ff, 0xeef0ff32, 0xfeff0814, 0xff68e6f7, 0xecd1fcfe, 0xe9ffff15, 0x2321aa83, 0x82ec8419, 0x192a22b4, + 0x2075829a, 0x2e9c822d, 0x066307bb, 0x94fbffff, 0xffff8b7b, 0x82856bfc, 0x82eb8204, 0x20d58210, 0x21b78236, 0xe882deff, 0x7d160027, 0xe3ffff71, + 0x235d8233, 0x83900220, 0x1d2c9a82, 0xffffcdcc, 0x059a99f8, 0xb3cb01ff, 0x4d231682, 0x8415cc4c, 0x830420e6, 0x66fc25fb, 0x0300ff68, 0xff28b282, + 0x8b9899fb, 0x5b066308, 0xd2204983, 0xfb464982, 0x83d52005, 0x19e92709, 0xdcffff9c, 0x4d8468e6, 0x0725ce82, 0xab056666, 0x26bf8293, 0x00ff0080, + 0x82cccc1c, 0x8221209f, 0x068b2a9f, 0x15b814fc, 0xff0674f7, 0x93871800, 0x59571809, 0x06ce5111, 0x51333321, 0xfb2006ce, 0xff203082, 0x098a5718, + 0x115c5718, 0xc2824283, 0x5782c782, 0x088bcd24, 0x57186b8b, 0x30820cbb, 0x41828182, 0x8b083422, 0xff205284, 0xaa823087, 0x82cc0821, 0x20929130, + 0x82b28234, 0x823082a3, 0x83cc2052, 0x222b825c, 0x89343307, 0x2bab2492, 0x8f34f715, 0x82369fc9, 0x9ec98d30, 0xfb0e3b98, 0x1a01ff30, 0x01ff66e6, + 0x1552785f, 0xcc3800ff, 0xfaffffce, 0x00ffae87, 0x95824c2c, 0x8233d021, 0xc5ff2670, 0xfb08cccc, 0x175d6164, 0x1805a34d, 0x2010af4c, 0x223083f7, + 0x18801a00, 0x2113b240, 0x5683b3fb, 0x7682fb20, 0x66ffff2d, 0xfcffff66, 0x088a9a19, 0x83dcffff, 0x199c2872, 0xffff059a, 0x44008065, 0xf3241995, + 0xff8b9a99, 0x20056855, 0x27438307, 0xff34b3fa, 0x66660900, 0xea204282, 0xc3226f83, 0x428268e6, 0x9919fa25, 0x83efffff, 0xb3ed265e, 0xf7ffff33, + 0x20d9824c, 0x236182ef, 0xfeff0500, 0xef252982, 0x00ffd763, 0x253e8305, 0xff7b54f7, 0x1e821200, 0xf005002d, 0x1000ffa4, 0xff0832b3, 0x82234e00, + 0xb3da261e, 0x00ff0534, 0x968b842a, 0x18e520ca, 0x2008ad90, 0x827b82ff, 0x80e52296, 0x0c2c4100, 0x20250345, 0x09557cb4, 0x250d1561, 0xde0a00ff, + 0xde828bb8, 0xff299c26, 0x9a99faff, 0xc721b382, 0x84cd82ae, 0xf30f22a4, 0x83198233, 0x51122614, 0x0400ffec, 0x231e8219, 0x8b527813, 0x82052e74, + 0x831c2035, 0x83f320fe, 0x4c142716, 0xebffffcd, 0x1a82cc4c, 0x66e60423, 0x82468290, 0x04002310, 0x36820080, 0x8f67e622, 0x22271682, 0x00ffcccc, + 0x822adc5e, 0xe6052af1, 0x1000ff67, 0x00ff1ea5, 0x22258312, 0x828cac08, 0x32b3210e, 0x0e218082, 0x20298256, 0x37718210, 0x560efaff, 0xb30800ff, + 0xedffff34, 0xff8562b0, 0x285cefff, 0xecffff08, 0xff2a4482, 0x05e23aca, 0xf7ebef0e, 0x828215f4, 0x82592321, 0xb31c2194, 0x1c22a882, 0x5d6266a6, + 0xf8082205, 0x0c4a7334, 0x0a997618, 0x0774fb22, 0x2405fd4e, 0x4ce3ffff, 0x250486cc, 0x8b34b3dc, 0x3382fc08, 0x620ac071, 0xf7280a9b, 0xfbcb0774, + 0x06cb1574, 0x2109024f, 0x1f83ffcd, 0x2f84ff20, 0x074b0828, 0x1574f78b, 0xda62074b, 0x064b2616, 0x34fb34f8, 0x202c8315, 0x877b8234, 0x27868576, + 0xcb06cb08, 0x34f74b07, 0x4c82c982, 0x8505704f, 0x23002595, 0x088bcc4c, 0x06231c82, 0x826b24fb, 0xccd3223d, 0x203283cc, 0x05657033, 0x2109624f, + 0x8c82ccd3, 0x82cc2321, 0x33dc22cb, 0x12f87333, 0xcc230023, 0x23b882cd, 0x0833332c, 0x3f850684, 0x3283ab82, 0x08245483, 0x7cfbd4fb, 0xd8207f83, + 0x00265b82, 0xff713d20, 0x1b82dfff, 0xc2270028, 0xf8088b90, 0xa5730624, 0xf5ff210b, 0x830f096c, 0x052b4311, 0xb3f2ff26, 0xfc088b34, 0xff233082, + 0x82e1babd, 0x45ca25a0, 0x3500ff1f, 0xff281482, 0xcc4c4200, 0x0784f708, 0x2406dc6d, 0x00c00a00, 0x05ff58ff, 0x8a107a72, 0x84fb3461, 0xff2f0e07, + 0x00800601, 0xff1554f7, 0x00803900, 0x4854f706, 0xb96409f6, 0x54fb2224, 0xf3da1807, 0x0dc04f0f, 0xfb5bcc20, 0x44342008, 0x08240568, 0x14fb066b, + 0xff276582, 0xff66e6f1, 0x82ccf6ff, 0x99f32d20, 0xf2ffff9a, 0xffff0080, 0x0866e6fb, 0x3a820a89, 0xff686625, 0x82330500, 0x33f8273a, 0x0b00ff32, + 0x1e8234b3, 0xcdcc9e2d, 0xcc9100ff, 0xffff05cc, 0x86cdcc9b, 0x2b3e4e4d, 0x3e4e1420, 0x11165c1e, 0x1941ab20, 0x190e2f06, 0x0900ff9a, 0x00ffe23a, + 0xffa4700c, 0xb3820d00, 0x17040024, 0x0a82080a, 0xff527829, 0x7a140400, 0x830e00ff, 0xc5fa25cd, 0x0700ff20, 0xff23a882, 0x821e45f4, 0x838b201e, + 0x402e2aec, 0x00ff0500, 0x4b9a992a, 0x83268215, 0xb3e92211, 0x23118234, 0x07cc4c16, 0x192ceb82, 0xffff069a, 0xcb666688, 0xc6ffff15, 0x56215983, + 0x23e3834c, 0x0734b3a9, 0x29059d41, 0xf730fb0e, 0x1554f8e4, 0xd218b4fb, 0x67620c62, 0x34fc220a, 0x08005e07, 0x63717d21, 0x1a250685, 0x088b8f82, + 0x243382f7, 0x90821a00, 0x06af628b, 0x707d1522, 0x10820a82, 0x83f80821, 0x861a8333, 0x2b19822e, 0x80e5ffff, 0xff088b00, 0x0080c9ff, 0xff21ab82, + 0x258d82a6, 0x33b379ff, 0x0a84ff05, 0x4c860028, 0x47f705cd, 0x1e19ff06, 0xef3a7125, 0x334202ff, 0x7d01ff34, 0xff15a4f0, 0x989957ff, 0x75cdffff, + 0x4cffffc2, 0xf8826766, 0x9a995738, 0x8a3200ff, 0xffff083e, 0xff3333e1, 0x703d0900, 0xe8ffff6c, 0x1b82a4f0, 0x48e1df26, 0xc0feff08, 0x2105fb4d, + 0x2882d9df, 0x9a191e22, 0xff241c84, 0xa4b01f00, 0x08252c84, 0x66a800ff, 0x2c428266, 0x00ffae87, 0x8b34b3b2, 0x4ca900ff, 0x216282cc, 0x1a82d678, + 0xf4e81d27, 0xabf6ffff, 0x2c2f8200, 0x00ff68e6, 0x8b9a1917, 0x01ff08ac, 0x2452843f, 0xb81e2000, 0x2114826c, 0x7b835c0f, 0x28823420, 0x8290c221, + 0xcc3d216f, 0x62223e82, 0xac825c0f, 0x0ccf6918, 0x0c454018, 0x24116f42, 0xae1100ff, 0x227d8214, 0x50ec510e, 0xc6820b92, 0x7b54ee22, 0xb3211182, + 0x21048233, 0xae4e85ab, 0x20838205, 0x22a5835a, 0x8266665b, 0x82cd2066, 0x080026d5, 0xffffce4c, 0x20ca83cc, 0x24198304, 0x8b3433cc, 0x21c68208, + 0x4182cc8c, 0x01c0cd2a, 0xf4fbffff, 0xcefffffe, 0xff232082, 0x82ee1cf8, 0xdcf1271a, 0xfdffff29, 0xb78206c1, 0xfb820720, 0x9e6f0f25, 0x820800ff, + 0x0b00236a, 0xfa8266a6, 0x152e312e, 0x8f4400ff, 0xff8e055c, 0x48210400, 0xd7820482, 0x82020021, 0x0500233f, 0x5b829a19, 0x16820684, 0x82e5d021, + 0x1a8f2646, 0x030300ff, 0x21658295, 0x3c82f4dd, 0xc275202b, 0x7dd3ffff, 0x00ff0570, 0x2397825d, 0x9a198b00, 0x03270a82, 0x00ff9002, 0x82b54805, + 0x82022005, 0x050023ce, 0x4784cc4c, 0x17820682, 0xbf820c20, 0xf853fd26, 0xf50200ff, 0xfb223c82, 0x4782088c, 0xd9826d20, 0xe65aff23, 0x293c8266, + 0xffa4b007, 0x3453f4ff, 0x1062ff81, 0x33f22205, 0x292a8232, 0x0e083233, 0x54f730fb, 0xad8234f8, 0x66664d2b, 0x3f00ff8b, 0xffff34b3, 0x26d284c9, + 0xffff32b3, 0x8252f8b6, 0x33032148, 0x10685218, 0x540c814e, 0xfc331374, 0xff06cccc, 0xce4cf0ff, 0xc0ffff42, 0xff54cc4c, 0x8299b2ff, 0x062b21f8, + 0x0a014418, 0x24252a48, 0xffff0774, 0x0bba52ee, 0x201e0b42, 0x17894eeb, 0x0614f73c, 0x805a00ff, 0x1514fb00, 0xe6f2ffff, 0x2500ff66, 0xffffcc4c, + 0xff6766dc, 0xf7831a00, 0x3333d62d, 0x062b088b, 0x00ff074b, 0x820080ba, 0x804527be, 0x4b154b00, 0x3782eb07, 0x83cc2921, 0x99232276, 0x232b8599, + 0x9a190d00, 0x08223f84, 0x2582ffff, 0x0e062608, 0x44f730fb, 0xff1534f8, 0x66664400, 0x3b00ff8b, 0xffffce4c, 0xff70fdd8, 0x98191d00, 0x02c7ffff, + 0x00ff0890, 0x1e474113, 0x2411fb45, 0x4cffffff, 0x2c7d82cc, 0xff008000, 0x33b3faff, 0x330000ff, 0x18098434, 0x2209d970, 0x829a99fa, 0x82cc2026, + 0x2120833c, 0x2a86ffff, 0x00206f82, 0x11e35318, 0x2120b754, 0x6f82ccec, 0xe6e2ff23, 0x26b48268, 0xffff66e6, 0x8232b3c4, 0x25ec82c8, 0x9a99bbff, + 0x5362088b, 0x34f72131, 0x6b0fbf41, 0xd2820c17, 0x0e4a5318, 0x2f9cab20, 0x2011fb43, 0x18ef41cb, 0xff060436, 0x66664e00, 0xffff152b, 0xffcdcceb, + 0xcccc1300, 0x4ce4ffff, 0x0c270982, 0xffff3433, 0x830080e1, 0x076b2ed0, 0x669e00ff, 0xffff0666, 0x4b9a9961, 0x210e8315, 0x0e82e6be, 0xb3000022, + 0x05216c82, 0x28a18233, 0xff666600, 0x67660500, 0x2105838b, 0x06850866, 0xffffff24, 0x16849a99, 0x4c210982, 0x270982cc, 0xff083333, 0x9a1941ff, + 0x50827682, 0x51827683, 0x076b0623, 0x201082db, 0x236c821e, 0xb31b00ff, 0x7c834d82, 0x83140021, 0x29908257, 0x54f70e08, 0x516201ff, 0x558215ec, + 0x66262239, 0x3b00ffa8, 0x8baeae87, 0xa78baf08, 0x78c4ffff, 0xffff8b52, 0x829ad9dd, 0xaebd2258, 0x20a98214, 0x2cc383b1, 0x05008089, 0xe60800ff, + 0xfaffff68, 0x22838319, 0x4c81cc4c, 0x27820521, 0xce4cc723, 0x240c8307, 0xffff9819, 0x239782f5, 0xce4cf8ff, 0xab830982, 0xcc4c0422, 0x55292082, + 0x05c49a19, 0x19afffff, 0x204f829a, 0x29178239, 0xccccd4ff, 0xff888f05, 0x9c4c0200, 0x823e8206, 0x202a8257, 0x052c6bd6, 0x1783f720, 0x34b3f924, + 0x0484ffff, 0x8b200e82, 0xfe821c82, 0xfe222882, 0x954232b3, 0x82fe2006, 0x00002120, 0x91256284, 0x00ff66e6, 0x20a5831f, 0x210a83ff, 0x0a84e0ff, + 0x5d542083, 0xb3fe2205, 0x70421833, 0x83332008, 0x4cf8224b, 0x204b82cd, 0x241682f9, 0xcc4c0600, 0x20dc828b, 0x21f38299, 0x2b462900, 0x83052005, + 0x289c834e, 0x66e60300, 0xff088e8f, 0x27b68300, 0x34332b00, 0x5000ff05, 0xff25a382, 0x5c0f55ff, 0x22d48252, 0x75d7a3f5, 0xf5270662, 0x00ffcd4c, + 0x8232b307, 0xe60a224b, 0x23328268, 0x0732b338, 0xa5830c83, 0xd5580523, 0x26638295, 0x00ff2be7, 0x8266e605, 0xc0b1251c, 0x7600ff00, 0x2182a582, + 0xec514224, 0xd3820e05, 0x59140021, 0x54220bdf, 0x8d51ff67, 0x85ab2106, 0x2205ac58, 0x8200804f, 0x8040272d, 0xbfffff00, 0xbe82ae87, 0x5278b023, + 0x21068208, 0xdc8233c5, 0xcdccdc27, 0x80cdffff, 0x82048301, 0x99e92220, 0x27658298, 0xff666633, 0x9a997fff, 0x062bb582, 0xffff9a99, 0x839a99ef, + 0x83edffff, 0x99ef2615, 0xf9ffff99, 0x838b8266, 0x200a8315, 0x20198468, 0x820a8393, 0x8210207a, 0xff53251a, 0x66e68b00, 0xd522e582, 0xc64933b3, + 0x2448450c, 0x7b82d186, 0xecff3f28, 0xbb1554fb, 0x927bff06, 0x14964b0a, 0x964b3320, 0x8bcd2b08, 0xfb065b08, 0xe4f70734, 0x561815eb, 0xc221194f, + 0x22d48219, 0x8266e6cd, 0x820483f4, 0x1836830e, 0x202ff349, 0x0a1c4ef7, 0x18cc4c21, 0x240b2a9e, 0xfbbb06db, 0xbe551804, 0x065b2317, 0xd383072b, + 0x0b088318, 0x8b008024, 0x108200ff, 0xaf0e0826, 0x14f8d4f8, 0xff263a82, 0xff7c54ee, 0xf15df1ff, 0x05015e06, 0x95460820, 0x7b542107, 0x85201a88, + 0x7a201a8f, 0x86201a88, 0xfb221aa1, 0x24850614, 0x93183485, 0x51180a14, 0x4f21088c, 0x2bd9825c, 0x00ff7a54, 0x8ba4b011, 0xeb06eb08, 0x2005c644, + 0x96158286, 0x8884201a, 0x8f7c201a, 0x661a9135, 0x315410ed, 0x34f72a0a, 0xf71574f7, 0x00ff06d4, 0x68c47e36, 0xcc4cc923, 0x59de1807, 0x1e8d4610, + 0x0694fb24, 0x3883ffff, 0x2365ba7c, 0x0734b336, 0x5b193a57, 0xd3831628, 0x7b064541, 0xec202670, 0x7f15707b, 0xff210810, 0xab4018ff, 0x4cc92619, + 0xf36b07cc, 0x1a407e15, 0xff004028, 0xcd4cf5ff, 0x2f7f00ff, 0x33b32405, 0x18ff088b, 0x7e0c20e9, 0xb3210ccf, 0x1ee91834, 0x14f82310, 0x017f15bb, + 0x2031851a, 0x20648334, 0x364318cc, 0xa9411813, 0x34b1180d, 0x54fb2312, 0x6c7d04fc, 0x8b0e2d5c, 0x8b1504f8, 0x2e2c00ff, 0x2300ff14, 0x0d844018, + 0x06f4f722, 0x44059250, 0xdc2006d8, 0x08874018, 0x07b4fb32, 0xe5ffff8b, 0xffffcccc, 0xff6666f3, 0xcecce8ff, 0x24062f75, 0x086666f1, 0x170c545b, + 0x1805e974, 0x23126c4e, 0x94fb07ab, 0x19175b18, 0x0d7b6818, 0x0a9b5c18, 0x8207bb21, 0xeb912175, 0x2106154f, 0xc2826ef3, 0x32331722, 0x1a2acd82, + 0xf7083433, 0x00ff07b4, 0x9d82e681, 0xccccb731, 0xeeffff15, 0xffff9a19, 0x053433b8, 0x8506b4f7, 0x4700270d, 0xff05cccc, 0xc182fcff, 0x830f0021, + 0x33f3251d, 0x0900ff34, 0xf1230983, 0x488bcc4c, 0xff23079e, 0x823333f2, 0x33f323ed, 0x397cff33, 0x29308305, 0x66e6f0ff, 0xff068b08, 0x2e83deff, + 0x34337822, 0x774b6183, 0x118b5b08, 0x540e0023, 0x05ac507b, 0x58076e5f, 0xd18a09a0, 0x1120bb82, 0x6207cc6c, 0xcd2507e2, 0xd4f7088b, 0x0c60754b, + 0xbb823194, 0x55091463, 0x8d930b77, 0x82050f5f, 0x266e8232, 0xfb0e088b, 0x5ef8eb30, 0xdc231a32, 0x5b07c2b5, 0x0f2107aa, 0x08aa5b5c, 0x5b9ad921, + 0x282b07aa, 0x0400fff6, 0xffff66e6, 0x5b9002ef, 0x022208ae, 0xae5bff8e, 0x7ace2607, 0x19fbffff, 0x09ae5b9a, 0xff056626, 0x9999e2ff, 0x005c5588, + 0x00ff2f49, 0x06cdcc3f, 0x334400ff, 0x00ff8b33, 0xe3823338, 0x00803527, 0x660300ff, 0x83148266, 0x00002483, 0x82936666, 0x820020c4, 0x110023b0, + 0xc5829a99, 0x99990d22, 0x3425ca83, 0x33ffffff, 0x82c08233, 0x200a8215, 0x2b198419, 0xffff7c98, 0xffce4cfe, 0xcc4ceeff, 0x00231a82, 0x82830080, + 0x82fa20bc, 0x99ff223c, 0x2a1682cc, 0xff9a99ab, 0xccccafff, 0x4499ffff, 0xa0210540, 0xc0781833, 0x38525c18, 0x5c0ad721, 0x35240852, 0xe60400ff, + 0x230e525c, 0x0700801d, 0x202aa85c, 0x08a45c9c, 0x00ff3222, 0x2006a45c, 0x09a45c66, 0xff059a24, 0xa45c3500, 0x8b8b3419, 0xf7af0e05, 0x1564f724, + 0x2c00ff8b, 0x00ff3333, 0x86cdcc23, 0x4fe21804, 0x82342008, 0x07d8541b, 0xffff8b26, 0x08cdccd3, 0xcc230684, 0x55dcffff, 0x7e180606, 0x806409d6, + 0xfc531808, 0x04f8240a, 0x181584f7, 0x560b5349, 0xf4200b08, 0x2b170856, 0x6b7b067b, 0x7b064b05, 0x74fb05ab, 0x7b200a88, 0x210ae076, 0x1c56ff9a, + 0x2047830b, 0x05845600, 0x7666a621, 0x0e8305e2, 0xf8088b28, 0xb4fb0654, 0x808224fc, 0x66665822, 0x4721ca82, 0x82388299, 0x820a8204, 0x20ca8210, + 0x23068200, 0x66b8ffff, 0x16823582, 0xa7ffff22, 0x83051960, 0x7b168506, 0x17820dba, 0x8400ff21, 0x82328428, 0x088b283c, 0x00ff94f7, 0x8233b3b2, + 0x83122063, 0x8306205d, 0x830d2004, 0xcc112250, 0x226782cd, 0x8366e614, 0x15245967, 0x143c5a18, 0xffff8b24, 0xa78219eb, 0xff254483, 0xff3333ee, + 0x4b588300, 0x8d220628, 0x5518cd4c, 0x332309b2, 0x18ffff34, 0x3120c9e4, 0xb37200ff, 0xaf0e0733, 0xccf800ff, 0xbb01ffcd, 0xaa828a01, 0x99190131, + 0x010300ff, 0x0200ff06, 0x00ff67e6, 0x826afd01, 0x3333220e, 0x05f9508b, 0x0227b682, 0xffff66e6, 0x829602fe, 0x238b821b, 0xfafefcff, 0x0e2c1a82, + 0xffff9819, 0x05f252da, 0xb32500ff, 0xf1247b82, 0x8e0546e1, 0xde2d2682, 0xffff8dba, 0x8b4621fd, 0xcafcffff, 0x83ee823e, 0x84892006, 0x84882012, + 0x8208201e, 0xcc4c2336, 0x3083ffff, 0xe6210582, 0x220f8268, 0x82057c54, 0x66e6211b, 0xfd222182, 0x2d829a19, 0xccccfc22, 0xff237f82, 0x82cdccfc, + 0x19fd2347, 0x1e838d99, 0x828e6721, 0x82f1203b, 0x2500238c, 0x308284ab, 0x8266d921, 0x1e0e24ae, 0x828805ba, 0x46212199, 0xc4824184, 0x82bade21, + 0x350322b3, 0x207b82c2, 0x85068200, 0x020024b5, 0x848ebade, 0x21bb8226, 0xf1829926, 0xff223883, 0xd1820e00, 0xad250023, 0x20c6820e, 0x291582b2, + 0x1aeff6ff, 0x1200ff15, 0x0482cecc, 0xfffabe26, 0x66661e00, 0x12274d82, 0xffff32b3, 0x820641ed, 0x9922263b, 0xddffff9c, 0x237f826b, 0x30b31200, + 0x42271582, 0xffff8b90, 0x829a99e1, 0xd04c210a, 0x47270482, 0xfeff08ae, 0x83989982, 0x829a2004, 0x4ced22a5, 0x211582cd, 0x2482ce4c, 0x827a9421, + 0x42ed222a, 0x215b828f, 0xcb8232b3, 0x856bdd26, 0x992200ff, 0x40212584, 0x82158400, 0x8272826c, 0x83c0200a, 0xcecc270f, 0x7d01ff08, 0x04840a57, + 0xffad0531, 0x00c0d2ff, 0x96ffff15, 0xffff66e6, 0x82900297, 0x831720b4, 0xb3e82958, 0xfff40532, 0x1e056900, 0xe8326f82, 0x00ffcccc, 0x05204517, + 0x173afeff, 0xc6ffff4c, 0xd182281c, 0x4e823827, 0x331500ff, 0x26328234, 0xffa43015, 0x83823800, 0xb001213d, 0x042c0a82, 0x00ff8e82, 0xff5d4f04, + 0xe2fa0200, 0xcf220982, 0xe7828b5c, 0xcdcc0422, 0x04208b82, 0xfd2cbc83, 0x00ff1e05, 0xff34b301, 0x727dfbff, 0x15271a82, 0xffff3333, 0x82707dc7, + 0x8038274b, 0xeaffff00, 0x0a82cccc, 0x0a830420, 0xce4cfe23, 0x2126828e, 0xe88232b3, 0x3433fb23, 0x20068508, 0x82128488, 0x82228604, 0x88c720fa, + 0x203e8238, 0x4f4e82cd, 0x4c210521, 0x222586cc, 0x8333b3fb, 0x33332135, 0xff238b82, 0x83a430fb, 0xa3b02148, 0xfe225b82, 0xa3825c4f, 0x82008021, + 0xcfea2143, 0x81820a82, 0xc722f482, 0xde86b27d, 0x7efbff23, 0x25ad8377, 0xfdffff32, 0x2a82d703, 0x83ce4c21, 0xcccc21c7, 0x00238b82, 0x82cccc04, + 0x29fc21e5, 0x04821684, 0x84898121, 0xff082a2a, 0x4e026001, 0xff1594fb, 0x414e8200, 0x33210827, 0x820f8434, 0xb30127db, 0x0500ff32, 0x37866666, + 0x9a190222, 0xcc210982, 0x052741cc, 0x5f83cc20, 0x82ce4c21, 0x82e6206f, 0x242a8320, 0x9a99faff, 0x86468408, 0x415684d8, 0xcc204127, 0x82092741, + 0x80fb286e, 0xfbffff00, 0x828832b3, 0x05b05505, 0x0682fb20, 0x8e231284, 0x82feffff, 0x04002191, 0x83052741, 0x062741f5, 0x06423382, 0x055c5c05, + 0xfd20ad84, 0x0420b783, 0x84112741, 0x844683e5, 0x242a82f9, 0x01ff0e08, 0x271582a0, 0x66e63f01, 0xf7ffff15, 0xff224c82, 0x8a82ccf5, 0xccccf02e, + 0xf6ffff8b, 0x00ff9a99, 0x0832330a, 0xb32b0a82, 0x0800ff34, 0xff8b0080, 0x82330f00, 0x4c092f0a, 0x0900ffcc, 0xe308b85e, 0x005800ff, 0x0c820542, + 0x82666621, 0x3a5f2104, 0x26822084, 0x36822c82, 0x08c6a022, 0x0a824284, 0x8206a121, 0x20588252, 0x366285ff, 0x0848a1f6, 0xa8ffff33, 0xff05b8de, + 0x32b39cff, 0x785900ff, 0x83ff1552, 0x21f282e2, 0x0982e27a, 0xff269982, 0xffc235fb, 0x7d820300, 0x02fbff23, 0x204b8290, 0x22db832d, 0xb6a8e62d, + 0xffff2271, 0x23d482c6, 0x1ec5c5ff, 0x05224082, 0xf3583233, 0x05645405, 0xfe83e920, 0x5f82f920, 0xb3eaff23, 0x286a8234, 0xffce4c14, 0xcccc0500, + 0x05217cff, 0x38820120, 0x82140021, 0xfaff2104, 0x3b211e84, 0x2219824c, 0x8866663b, 0x0a572189, 0xa821fb8d, 0x21fb88f6, 0xfb8c9a99, 0x0080f729, + 0xd2ffff08, 0x825c32b3, 0x8405203c, 0x217682dc, 0x80830500, 0x7584fb20, 0xff343326, 0x66e6faff, 0x0b204082, 0xff236682, 0x8233b3f4, 0x83062029, + 0xb3f92215, 0x254b8233, 0xff67e6f5, 0x9b82f9ff, 0x99faff23, 0x204b8299, 0x264483f4, 0x05cdccf3, 0x83daffff, 0x80da2845, 0xc3ffff01, 0x858b3233, + 0x2500230f, 0x2582ff7f, 0xceccf326, 0x330c00ff, 0xff244b82, 0x6c9819e0, 0x1c205282, 0xfc252c83, 0x00ff6666, 0x8241841b, 0x15002104, 0xff238b82, + 0x843433ea, 0xffce257c, 0x9899f4ff, 0x32207c84, 0x8308dc7a, 0x82f92020, 0xf9ff224b, 0x822582b3, 0x221a829d, 0x8932b3f4, 0x8300207c, 0x8834207c, + 0x20ee847c, 0x82ad82f3, 0x8234207c, 0x19e02325, 0x8182ff9a, 0x56829a20, 0x82991b21, 0x82fd200a, 0x1c0026e3, 0xffff9999, 0x268084f3, 0xffffcdcc, + 0x849819ea, 0xffcc2380, 0x6152f5ff, 0x824c2005, 0xe6f8228b, 0x20558266, 0x847b85f5, 0x87cc2090, 0xb3f421fd, 0xfd865a83, 0x4c218083, 0x54808ecd, + 0xa68305ac, 0x4821bb26, 0x19bbffff, 0xff228082, 0x2b8280f3, 0x0280f325, 0x18ebffff, 0x210ab56c, 0x5682fe7f, 0x1ab56c18, 0x02eb4427, 0xe64400ff, + 0x27cc8266, 0xff0a97f5, 0x00800a00, 0xda260a82, 0x00ff8f82, 0xa2826625, 0x823c0021, 0x250023a2, 0x0f82717d, 0x08ff7f27, 0x510b00ff, 0x067a41ec, + 0x3d060022, 0x05221582, 0x74186766, 0x3a220836, 0xc641ffe2, 0x0b002205, 0x28f9824c, 0x05cdccf3, 0x001500ff, 0x82928201, 0x0c002804, 0xffff3333, + 0x4b9899e5, 0xff230520, 0x829a99e4, 0x831e204f, 0x841e203f, 0x99f52275, 0x204a8299, 0x838b8366, 0x250025fd, 0xff8b0180, 0xcd208082, 0xdc827b82, + 0x30829083, 0x00215a83, 0x2125830b, 0x65820600, 0x33060023, 0x21358234, 0x2a829919, 0x21055742, 0x9118cccc, 0xf4240704, 0xa0059a99, 0x19227c82, + 0x7882989a, 0x03234283, 0x82ff6666, 0x84992078, 0xff662578, 0x01801e00, 0xf522ee82, 0x788e9a99, 0x4d820020, 0xaec73c22, 0x7d217887, 0x20788470, + 0x82fe84cc, 0x4c0623d3, 0xfe82ffce, 0x35827020, 0x829a1921, 0x4c06272a, 0xf9ffffcc, 0xe64290c2, 0x14ae2a08, 0xf82f0e05, 0x1524f834, 0x2179828b, + 0x9e43707d, 0x82ea2206, 0x21888490, 0x4518088b, 0x00200b3b, 0x8209c35c, 0x821a204b, 0x2e961823, 0x7aff2008, 0x441805f5, 0x255d0bc9, 0xffff240a, + 0x82cdcc0c, 0x9a992578, 0x0900ff15, 0x072cdf83, 0x00ff281c, 0xff99990c, 0x3e4a0100, 0xb3269d82, 0xfaffff34, 0x978234f3, 0x1e827420, 0x26c9ff23, + 0x25bd8266, 0xff32331d, 0xb282f2ff, 0x82070021, 0xdaff23f8, 0x9e869a19, 0x9a19e822, 0xd9209882, 0xd5213483, 0x23298366, 0x0666e674, 0x99205982, + 0x0920e383, 0xfb272683, 0xff9133b3, 0x8299f8ff, 0x06002327, 0x0a839819, 0x02206b82, 0xf6255b83, 0xffff3433, 0x202483fe, 0x251e82f6, 0x0534fb6b, + 0x466bffff, 0x32b32405, 0x83efffff, 0xccf4251d, 0xeeffffce, 0x00237382, 0x82666603, 0x82ee2069, 0x03002119, 0x19833c83, 0xcc100023, 0x051a42cc, + 0x83110021, 0x1700211e, 0x00221982, 0x4883b379, 0x9a99ba27, 0x0800ff06, 0x25718299, 0xff6666ec, 0xa3830400, 0x6666ea26, 0xe9ffff8b, 0x2105cd47, + 0xc58299a7, 0x1b82b820, 0x0484ff20, 0x8b200e82, 0xa7226182, 0x228247a1, 0xb85eb824, 0x514b00ff, 0x47002310, 0x168448a1, 0x080a2f19, 0x9a190b24, + 0xad49958b, 0x4c0b2b06, 0xfdffffcc, 0xff08cdcc, 0xbb823600, 0x33200482, 0xcd27d082, 0x00ff3333, 0x8266e617, 0x83cf200a, 0x99db226b, 0x250a829a, + 0xff67e6f1, 0x0f83f5ff, 0x82e6eb21, 0xe602229c, 0x230e8568, 0x98190e00, 0x19838482, 0x3405cf49, 0xff29dc02, 0x9a191400, 0x230e00ff, 0x0a00ffd7, + 0xcb089a99, 0x204082bb, 0x2d5682f3, 0x666676fe, 0xb68bc015, 0x08c08bb6, 0x9618ff8b, 0xff240ce9, 0x9919caff, 0xd520c782, 0xff205d82, 0x0a820482, + 0x9a19ca2b, 0xff568b08, 0x9a192a00, 0x282c8360, 0x0e088b67, 0x1cf844f7, 0x223a8215, 0x8200400d, 0x82b3205b, 0xc00a21a9, 0x0d260982, 0x088bcd4c, + 0x9b52069b, 0x30c5180b, 0xf5ff2311, 0xb482cd4c, 0xff273982, 0x8b33b3f2, 0x52067b08, 0x00200b9d, 0x58854882, 0x5bb30822, 0x610ce552, 0xcd2014e8, + 0x9208e861, 0xc14f1849, 0x0a00210f, 0xb321a984, 0x82a08534, 0x24fb22a9, 0x21638343, 0x72829042, 0x71bd0a22, 0xf2824c84, 0x34b3f223, 0x20068408, + 0x21118233, 0x04828f42, 0xf222b283, 0xad8670bd, 0x8200c021, 0x86f5201d, 0x823a82fb, 0x255018f7, 0x0f486207, 0xdd829b20, 0x4100b828, 0x9994ffff, + 0x2a82159a, 0x9a190f27, 0x470c00ff, 0x2e04826d, 0x00ffcc4c, 0x8b66260f, 0xc901ff08, 0x8206862b, 0x9a19210c, 0x0c202182, 0xff211782, 0x51bb83f3, + 0x2608058e, 0x80b9ffff, 0xd3ffff00, 0xffff9a99, 0xffccccc3, 0x32b3c1ff, 0x99e8ffff, 0xffff089a, 0xff3433fe, 0x6666f2ff, 0x847b8905, 0xffff2207, + 0x215f82f3, 0x6178efff, 0x66182405, 0x84ff0667, 0x251c850c, 0x66e60c00, 0x36849b89, 0x00ff3326, 0x059a990d, 0xa8264c82, 0x1700fff6, 0x60826666, + 0xffd7a326, 0x34333c00, 0x46288282, 0xff080080, 0x42000000, 0xdf279482, 0x00ffbeff, 0x83666653, 0x820d20bc, 0x1144419a, 0x211b8d63, 0x805aff33, + 0x18f52005, 0x410847de, 0xb3210fee, 0x06404133, 0x9d8b2b21, 0x82cd2062, 0xb30a2127, 0xa3415085, 0x865d830f, 0x13074262, 0x83216287, 0x335142eb, + 0x180bed41, 0x410e1352, 0xf72211ed, 0xc68a2b5c, 0x18453420, 0x0d002305, 0x1843cc4c, 0x84541807, 0x0fce4207, 0x82172941, 0x832a8371, 0x97c68e48, + 0x06995549, 0x01653584, 0x05734105, 0xc690498a, 0x8707d355, 0x40f320a9, 0x2b21c4c5, 0x0c6656d3, 0x20148b44, 0x088b44cc, 0xdd433420, 0x41b32006, + 0xc0200928, 0x0e875618, 0x44052166, 0xcc2c06eb, 0x069b088b, 0xf770fb0e, 0x1524f804, 0x472d4e47, 0x73302daa, 0xe6b1feff, 0xffff1566, 0xff3333f2, + 0x34b30200, 0xcc25b282, 0x0c00ffcd, 0x359e8380, 0x0866e60e, 0x193700ff, 0xffff079a, 0xff146efb, 0x6666f8ff, 0xd455ff05, 0xe6f02705, 0xecffff66, + 0x19820a57, 0xff9a192c, 0x9ad9f0ff, 0x190900ff, 0x0a83089a, 0x0a847f20, 0x72251983, 0x991300ff, 0x260e8298, 0x00ffa01a, 0x8234330f, 0x463a264e, + 0x6000ffea, 0x324882e6, 0x71fd0e00, 0x1900ffa4, 0x00ff295c, 0xff9a9910, 0x824c1c00, 0x8404207a, 0x83042074, 0xccff2554, 0x0400ffce, 0x00229983, + 0x0984cc4c, 0x2b05ea42, 0x8b666601, 0x660100ff, 0xffffff67, 0x00218682, 0x20378201, 0x822c82ff, 0xb3232a5d, 0xfdffff33, 0x00ff9819, 0x2009831d, + 0x205683e5, 0x22098306, 0x82cd4cdc, 0x8306201e, 0x99df2656, 0x00ff059a, 0x2534832c, 0xff6666f7, 0x04822100, 0x19d9ff27, 0xffff8b99, 0x18a282d1, + 0x700b6f72, 0x53200cf9, 0x180b5e62, 0x2224c668, 0xb07b07eb, 0x23d98233, 0x0566e661, 0x1764be18, 0xfd21a482, 0x22968233, 0x82ccccff, 0x21b983e8, + 0x0e82b3ff, 0xce4cfd29, 0xefffff08, 0x8207cccc, 0xe6e92220, 0x05b15766, 0x8205c457, 0x057f420e, 0x66e6fe22, 0x05821d82, 0x0000ff23, 0x252282e6, + 0xff68e6fe, 0xf282ffff, 0xfeffff24, 0x14829899, 0xfe225383, 0xca559a99, 0x21138205, 0x4c508b9a, 0xff062205, 0x854483ff, 0x11002154, 0x00254683, + 0x089a1916, 0x216d82e3, 0x7f831100, 0x0482f120, 0x200a637a, 0xa34d184b, 0x0a50570c, 0x9f973320, 0xc8ffff24, 0x35829a19, 0xff7ffe22, 0x4a18a383, + 0xfe2008ba, 0x08250986, 0xccfeffff, 0x05f041cd, 0xfc820982, 0xc284ff20, 0x85cdcc21, 0xe8e921db, 0x09107c18, 0xf7219f88, 0x846e8204, 0x000029eb, + 0xff8cae07, 0x5c0f0000, 0x0827fb84, 0x994500ff, 0x19ff079a, 0x18b29e04, 0x420c73bf, 0xe4821725, 0x19981921, 0x3516b505, 0x66e685ff, 0xd9ffff06, + 0x05cb9a99, 0xcc5000ff, 0x4300ffcc, 0x0a82cc4c, 0xcecc072e, 0x990600ff, 0xffffff9a, 0x839766e6, 0x4c3c0b82, 0xffff08ce, 0xff9a198a, 0x98995c00, + 0xf0ffff05, 0x00ff0080, 0xff01800b, 0x33b3edff, 0x99220482, 0x14829699, 0x0866e626, 0x333c00ff, 0xad221082, 0x25823433, 0x2582aa20, 0xccb8ff2d, + 0xff8505cc, 0x68e6faff, 0x83fdffff, 0x33f82653, 0xffff9032, 0x265283f8, 0xcc4c1f00, 0x82cbffff, 0xffff2421, 0x5634b399, 0x5721096d, 0x0b6d560a, + 0xa000ff24, 0xa3416666, 0x184b7c57, 0x200a5f41, 0xd42a7d06, 0x3308ff2b, 0x1700ff34, 0xc3150080, 0x05377107, 0x20103071, 0x4ae4185b, 0xcccc210e, + 0x23058a71, 0x53075308, 0xcd201a8f, 0x33201a84, 0x7d05c55c, 0xc3221302, 0x48575306, 0x8633200a, 0xcc08256c, 0xbb088bcd, 0x22179171, 0x97c307c3, + 0x85bb201a, 0x88cd20b4, 0x825182b4, 0x088b2b76, 0xfb0e0653, 0xf854f770, 0x15761554, 0x8286200e, 0x54ee29a1, 0xffff087a, 0x070a57dd, 0x5a806f18, + 0x9a99ea2c, 0x191000ff, 0xe5ffff9a, 0xcc4e0080, 0xe3ff2305, 0x53189a19, 0xff230d01, 0x8234b3c6, 0x4cb92290, 0x17a878cc, 0x1c00ff28, 0xff8b66e6, + 0x44871a00, 0x66150023, 0x18588466, 0x183e4c59, 0x217fa06f, 0xc082e23a, 0x127b2220, 0x72a31807, 0x41522009, 0x1c8205b0, 0x2800002c, 0x30fb0e07, + 0x158bf4f7, 0xe562d4fb, 0x19ff200c, 0x21090d04, 0x7d18ff8b, 0xf2220a3b, 0xaf620a97, 0x82f72006, 0x11002930, 0xff8ba4b0, 0x5c4f0e00, 0x0a820484, + 0x3eca1023, 0x5e068508, 0x0f22064e, 0x3f82c235, 0x8bcc4c2a, 0xf7c4fb08, 0x04f71584, 0x90206682, 0x18058966, 0x8909917d, 0x905c8555, 0x00ff2552, + 0x079a196f, 0x728c3c83, 0x82ec5121, 0x8383826b, 0xb0112272, 0x217282a2, 0x3b82a4b0, 0x84ce4c21, 0x217282b2, 0x93460604, 0x87238205, 0xec51211c, + 0xd4631c86, 0xf1ff230b, 0xe783f6a8, 0x08ea5126, 0xfb0704fb, 0x9d82a483, 0x5c641182, 0x23e58305, 0xec51eeff, 0x06826782, 0x9e85eb20, 0xaef1ff23, + 0x27ae8515, 0xf7af0e08, 0x1544f894, 0x06228c82, 0xc65564fb, 0x06002e05, 0x00ff502d, 0xff34b306, 0x80190200, 0x200a8308, 0x380a8332, 0x0700ff72, + 0xffff3433, 0x8f7889fd, 0x47faffff, 0x74f7086e, 0x06c0feff, 0xb26b18a8, 0x19fb2a07, 0x0000ff98, 0xffff6866, 0x071e54f9, 0x23057455, 0x3233fdff, + 0xb3203182, 0xf9200482, 0xff215682, 0x220483fc, 0x8266e6fa, 0x050376e6, 0xaf823420, 0x75ccf821, 0x6944058a, 0xf7083405, 0xffff07d4, 0xff9a19d4, + 0xc275afff, 0xffff9215, 0x82d823fe, 0x66e6219f, 0xb3215d82, 0x242f8332, 0xfb0834b3, 0x07304474, 0xccf8ff22, 0x2306e843, 0x3333f7ff, 0x14215882, + 0x21718206, 0x2882cd4c, 0x51b8fa25, 0x830300ff, 0x23fd2238, 0x224282d7, 0x82089a19, 0x830a84c4, 0xfaff2214, 0x82e282e1, 0x02002368, 0x61847bd4, + 0x7f24f282, 0x74f771fd, 0x9921d783, 0x211c8299, 0xfa820a57, 0x82676621, 0x7c142145, 0xd6228984, 0x9d828b08, 0x359e3128, 0x3dccfeff, 0x4e821572, + 0xff482124, 0xe5820a00, 0xac070023, 0x83098208, 0x990a2a4e, 0xff088b9a, 0xb0c71502, 0x21118206, 0xd8829899, 0xf8830720, 0x8a84f520, 0xff98192b, + 0xceccf5ff, 0xffff8708, 0x053247f1, 0xff68662e, 0xceccc8ff, 0xb3cdffff, 0xd9ffff32, 0xc6202583, 0xfe294284, 0x069a19c9, 0x85c7ffff, 0x25cd821e, + 0xff66a6cd, 0x5f822600, 0xf0ff2708, 0x00ff1d7a, 0x08323337, 0xf8fbffff, 0x0e00ff93, 0x0e056866, 0x00ffb0fb, 0xff0080e0, 0x9a996e00, 0x0f00ff15, + 0x1882f6a8, 0x82ae4721, 0x146e2680, 0xd71200ff, 0x27c4820a, 0x00ffc3b5, 0x0834b316, 0x75201982, 0x58310a82, 0xffffa470, 0xffb8deb0, 0xc2f51700, + 0xabcbffff, 0x21378285, 0x5682cccc, 0x8266f321, 0xe103286b, 0xffff0548, 0x8252f8c4, 0xcc4c213e, 0x2e826b82, 0x820b0021, 0x030022a7, 0x221382b8, + 0x82289c16, 0x87013b48, 0x0900fff0, 0x00ff1258, 0xff1b2f04, 0x92d80600, 0x7e0700ff, 0x0500ffb9, 0x1e82b85e, 0x71bd0e22, 0x8f268182, 0x1900ff5c, + 0x81823333, 0x09824f20, 0x3e4a1d22, 0x28214c82, 0x201e82b6, 0x221e820a, 0x8240feff, 0x9e0d31b5, 0xfcffffb8, 0x00ff6210, 0xffcd4c11, 0xeea7f9ff, + 0x10221e82, 0x92827b94, 0x8c831220, 0x22700822, 0x0f205d82, 0x10223e82, 0x1a823a9f, 0x820f0621, 0x9710276d, 0xf7ffff0c, 0xa0825879, 0xff486126, + 0xc06aefff, 0x17212382, 0x22c0820a, 0x82299cea, 0x8cd72187, 0x0a211482, 0x2b9b823e, 0xffff2cc7, 0xffeb11f1, 0xa4700200, 0xd1221e82, 0x1e82ae87, + 0xfff0c725, 0x825ed6ff, 0xc0f82577, 0xe3ffff12, 0xff23a082, 0x825a47eb, 0x82ea201e, 0xf0ff27df, 0xffff94b8, 0x578281f2, 0x4621ea22, 0xb826b082, + 0xe5ffff93, 0x1e82f6e8, 0xcb21f93b, 0xe1d5ffff, 0x0f00ff48, 0xffff6005, 0xff9a99e4, 0x89a11500, 0x4cedffff, 0x201e82cc, 0x21af82f0, 0x1482f2ff, + 0x89f5ff26, 0xecffff37, 0xfc27cf83, 0xffffae47, 0x82cd4ce9, 0xb9f1261e, 0xa8ffff58, 0x31338299, 0xff33f34f, 0x3233e7ff, 0x572600ff, 0xf4ffff0a, + 0xd8829a19, 0x71fd0c2d, 0x08fcffff, 0x00ff0572, 0x82c3b540, 0xa4702b3e, 0x350c00ff, 0xf6ffffc2, 0x9c5b5278, 0x80e42206, 0x20488200, 0x229183fe, + 0x82e04ff8, 0x6370212e, 0xf0213e82, 0x82ed8220, 0xf8ff23f7, 0x1e820a97, 0xe1baf031, 0x18f9ffff, 0xeaffff10, 0xffff9042, 0x820080fe, 0x289c266c, + 0xef0300ff, 0x301e82e0, 0xff8f42ef, 0xf0a70200, 0x6bebffff, 0x0700ff85, 0x252882d8, 0xff7bd4ed, 0xe3840600, 0x1d3af622, 0xb8272982, 0xffff0510, + 0x82e17aef, 0x82272015, 0x91ed2629, 0xf7ffffeb, 0x22298298, 0x823dcaf9, 0x22868418, 0x82e5d0f9, 0x2fa5830a, 0xffb85e08, 0xc275eeff, 0x8d1000ff, + 0xf8ffffd3, 0x00234883, 0x82877609, 0xf06721a0, 0x1528cf82, 0xff83cd0c, 0xd7e31700, 0xe121cb82, 0x21098248, 0x1a827b14, 0x83b85e21, 0x823520f5, + 0xf8fd27ea, 0x0b00ff10, 0xac8215ee, 0x82beff21, 0x66662209, 0x371a828b, 0x8b852b17, 0x1c1500ff, 0x0400ff29, 0x00ff3228, 0xffb81e12, 0xd82e0800, + 0x1f251a82, 0x00ff33f3, 0x217a830e, 0xb9829414, 0x5c4f1a2a, 0x7d0500ff, 0x2100ff71, 0x062b5484, 0x00ff2bdc, 0xffbce929, 0x82b3f1ff, 0x4c1b2528, + 0xe9ffffce, 0x12270983, 0xff0866e6, 0x825460ff, 0x99603733, 0x00ff1599, 0xff924d03, 0xae471400, 0xea1100ff, 0x0700ffc1, 0xc382ecd1, 0x6782de20, + 0xa3f00222, 0x00276782, 0xffff01ed, 0x82feb5ff, 0x5be2276c, 0x6ffbffff, 0x99838be5, 0x26149f41, 0xffff5278, 0x825178e4, 0xb5fc3b5f, 0xebffff81, + 0xffffcccc, 0xffc72bee, 0x4821f8ff, 0x30efffff, 0xfdffffa4, 0x1e82ae07, 0x1283fa2c, 0xbe0100ff, 0xe8fffffa, 0x73827dff, 0x830c0221, 0xc4ff2354, + 0xe38251f8, 0x436a5121, 0x992e116f, 0xf70e0899, 0x1514f7b4, 0xfb0754f7, 0x56820674, 0x8b0a5727, 0xa8f1ffff, 0x229782f6, 0x828b6666, 0x9a9922bc, + 0x82068508, 0x0a572111, 0x15821684, 0x8bf6a828, 0x0604f808, 0x4d1800ff, 0xc6181475, 0xfc201654, 0xff233082, 0x8252b8dc, 0x47e32261, 0x75cb18ae, + 0x82b82014, 0x4ce32eea, 0x2300ffcc, 0x088bae47, 0xe10200ff, 0x36648206, 0xff90420f, 0xe23aa5ff, 0xc04e00ff, 0xbaffff01, 0x00ff1ec5, 0x830a175f, + 0x05202520, 0xf32b0660, 0x0c4b6318, 0x820a7255, 0x820d2088, 0x2411833b, 0xbd0a00ff, 0xd3da1870, 0x18ff2012, 0x5509d14f, 0x7e530822, 0x00ff290d, + 0xff9a9921, 0x9a9948ff, 0xfb276682, 0xffff0040, 0x42d8a3f3, 0xf22c06be, 0x00ff281c, 0xffbe5f0c, 0xe23afbff, 0x0537af82, 0xffff21b0, 0x05e0cffd, + 0x3bf4ffff, 0xfeffff64, 0xffff0a82, 0x8233b3f6, 0xce4c2104, 0xf3225f82, 0xdb18cccc, 0xd3201768, 0x462ee882, 0xff07ae07, 0xb89ec0ff, 0x611800ff, + 0x69820548, 0xff15ae30, 0xa4b00400, 0x19f2ffff, 0xfaffff99, 0x6982cccc, 0x82343321, 0x34b3250e, 0x1d01ff08, 0x00239882, 0x8232b370, 0x73ff2798, + 0x0500ff82, 0x738206c1, 0x820a5921, 0x94582109, 0xe3210982, 0x2a098212, 0xff08cc8c, 0x666683ff, 0x83a5ffff, 0x00002253, 0x27c2825f, 0xff9498fd, + 0x025e0000, 0x9721ad82, 0x2398820a, 0x08f47dfd, 0xfe270682, 0xfffffc29, 0x8280a9ff, 0x9042213b, 0xcc210982, 0x2609827e, 0xff081038, 0x82265a00, + 0xf0d73340, 0x00ff05a4, 0xff2e2a1b, 0x80352200, 0x2c00ff9a, 0x90826866, 0x00230482, 0x82981930, 0x83602066, 0x998122a0, 0x0890829a, 0x86ebbd21, + 0x2500ff07, 0x00ffe23a, 0xffee5c03, 0x5ccf2100, 0xef0e00ff, 0x1a00ffde, 0x00ff66e6, 0x82f6e816, 0xa8af272f, 0x2300fff6, 0xea82c2b5, 0x9a19fb22, + 0x28244a82, 0xf9fffff6, 0xff211f82, 0x20b083fc, 0x220483f9, 0x829a99fd, 0x8291207f, 0xaf002314, 0x59826766, 0x3433e42c, 0x4c4100ff, 0xbcffffcd, + 0x838332b3, 0xffff6626, 0x8b9a99b5, 0xf7334f82, 0xfb066290, 0x069b0754, 0x470c00ff, 0x00ff8bae, 0x827a140b, 0x84402b55, 0x7d0800ff, 0xf8ffff72, + 0x4b82026b, 0x04168230, 0xa15e00ff, 0xf80e0547, 0xbf01ff24, 0xb767ecff, 0xf1ff230c, 0xbc4b9aab, 0xc7ed2208, 0x26c582ae, 0xff00800c, 0x82b3fdff, + 0x820c2076, 0xfbff227b, 0x207682f3, 0x2213830b, 0x822045fa, 0x190a2d4f, 0xfaffff98, 0xff0584eb, 0xcecc0f00, 0xca826582, 0x83060021, 0xc7ec22bb, + 0x230e85ae, 0x3433f0ff, 0xf8209f82, 0x0a821982, 0x7bff3221, 0xf9210566, 0x82f38299, 0x00ff2419, 0x8266e607, 0xccf52b1e, 0x0500ffcc, 0xff059a19, + 0x2982f6ff, 0x82040021, 0xf5ff21f4, 0x02200983, 0xf4202983, 0x2c050757, 0x06cc4cfe, 0x33e2ffff, 0xffff8b34, 0x822183e7, 0x820a8204, 0x8b082510, + 0x0d00ff75, 0x33247884, 0x1400ff33, 0xf729a283, 0xbf08cdcc, 0x33ebffff, 0x209e8233, 0x2b9e832c, 0xff9919ee, 0xcc4c1d00, 0xb3d4ffff, 0xcf294383, + 0xff08cccc, 0x9a99fcff, 0x21458207, 0x1782cccc, 0x4283de20, 0x7283d420, 0x0483d120, 0x8366f121, 0xb3ea229c, 0x17336a34, 0x2816407e, 0x661300ff, + 0xffff0766, 0x20c183f0, 0x208c8303, 0x230482f2, 0x34330600, 0x2305d857, 0x9a990800, 0xe8207982, 0x0f221483, 0xf58232b3, 0x9582f120, 0x83090021, + 0x83fc20a4, 0xb3142333, 0x0e82ff32, 0xd482cc20, 0x8282e620, 0x00231984, 0x8234b30e, 0x21a68258, 0xfc820300, 0x820e0021, 0xf6ff2909, 0xff083433, + 0x68661700, 0x66216c82, 0x20e88266, 0x2139820a, 0x1a82f8ff, 0x820c0021, 0xfcff212e, 0x00247282, 0x8b66e60c, 0x1b202582, 0xff220682, 0xd8821600, + 0x8b220483, 0x108200ff, 0x03201682, 0x8b24aa82, 0xf2ffffa1, 0x13201883, 0xeb208283, 0x08299783, 0x57083233, 0xcc1400ff, 0x219e82ce, 0x8f8233d3, + 0x75821120, 0x82e2ff21, 0x2b002355, 0x3e82cc4c, 0x7b823020, 0x33200682, 0x00211682, 0x25328321, 0xff90022c, 0x09832e00, 0xaec70f22, 0x16225982, + 0x096fc235, 0x2be08309, 0xff7a540e, 0x34b31100, 0xff8b088b, 0xec2a0082, 0x70feff05, 0xffff1400, 0x4b1800c0, 0x31100a7d, 0x1805019d, 0x2008ee6e, + 0x13dd5d00, 0x5d06ab21, 0xfb2116df, 0x92ad18f4, 0x066b2117, 0x210d405e, 0xf44e0080, 0xf7082805, 0x34fb07f4, 0x851554fb, 0x00ff240e, 0x82717d15, + 0x00802104, 0x82236182, 0x8f088b8f, 0x2537836a, 0x0080e5ff, 0x707bfb08, 0xeaff2108, 0x04852d82, 0x8b211882, 0x216a8408, 0xd118717d, 0x3426120a, + 0xf724f807, 0xbc8d1544, 0xb86d5189, 0x844c8805, 0x84518956, 0x18138327, 0x720aa887, 0x1a200560, 0x5e183282, 0xab260fcb, 0x94f80e06, 0xd682b4f7, + 0xb3dcff24, 0x937fff33, 0xffcd2107, 0x342d0e82, 0x3cfb088b, 0xff074b06, 0x9a192e00, 0x18ed8206, 0x3108526e, 0x9a19e6ff, 0xe6f0ffff, 0xf1ffff66, + 0xff08cccc, 0x0f83b9ff, 0x05200482, 0x21062364, 0x1f8399f6, 0x2364cc20, 0x66092208, 0x23258666, 0x66e64600, 0x36822582, 0x0e00ff24, 0x315a3433, + 0x82192006, 0x1500214a, 0x08205f82, 0xcb216c85, 0x82798207, 0x66a62283, 0x2f93828b, 0x00ff9a59, 0x8b33b31c, 0x4c2300ff, 0x07cb08cd, 0x08744018, + 0x200eef69, 0x74401814, 0x32c38217, 0x9a9938ff, 0xff1594fb, 0x66668700, 0xff07cb06, 0x8399b8ff, 0x800726d3, 0x0800ff00, 0x27928266, 0x66e61000, + 0x0300ff9b, 0x0021b982, 0x26988215, 0x6666faff, 0x821200ff, 0x8ebc20b8, 0x82a68256, 0x34b3239a, 0xc16a4b08, 0x8e611817, 0x0cad6a0c, 0x4c21bc85, + 0x06a76acc, 0x34b31c22, 0x5922d482, 0xf7828b9a, 0x82193021, 0xfbff2690, 0xffffcd4c, 0x268483ed, 0xff33b302, 0x82cceaff, 0xe610232a, 0x20827b67, + 0xff25a682, 0x9a99f7ff, 0x82bc8505, 0x24cc84d4, 0xefffff9c, 0x27c083e6, 0xff67e615, 0xce4ce9ff, 0x66265182, 0x00ff8b67, 0xc082e615, 0x32b3162d, + 0x00ff9c08, 0x059a1910, 0x186bcb0e, 0xa50afdb7, 0x41f82096, 0xfca40f53, 0xcb14f82a, 0xfc07cb15, 0x074b0614, 0xfb234082, 0x4294f734, 0x69551860, + 0x26e6410a, 0x70c4f721, 0x7b2417d2, 0x2600ff07, 0x210caa42, 0xaa42ff32, 0x42682007, 0x6c8353aa, 0xb0549b20, 0x823b2017, 0xf80e23fd, 0xfa85ab94, + 0x42183420, 0x631811ef, 0x8d410bb3, 0xb4fb2541, 0xfb1554f7, 0x21dd4e41, 0xa544ff8b, 0x078b2914, 0x15cb34fb, 0xcb0634f7, 0x06320882, 0x8b0e074b, + 0x8b1554f7, 0x668d00ff, 0x7200ff66, 0x04869a99, 0x8b210e82, 0x82158408, 0x2016831b, 0x211183ff, 0x0a82ffff, 0x59820820, 0xff201187, 0x15841683, + 0x1c832d82, 0x49871b82, 0x44825485, 0x0080d72b, 0x6697ffff, 0x00ff1566, 0x25658219, 0x9a99efff, 0xba48ff05, 0x82fb2005, 0x0900260f, 0xffff9a19, + 0x227a83fd, 0x82666608, 0x0d002147, 0xff240682, 0x34b30c00, 0x00212585, 0x22258307, 0x8298990a, 0xe60c214b, 0x0f22a682, 0x40826866, 0xcccc0523, + 0x211a85ff, 0x29823303, 0x32330922, 0x09227182, 0x9f826866, 0x82090021, 0xfcff2131, 0x16822083, 0xfaffff22, 0x07202083, 0xff221a82, 0x6c82eeff, + 0xe6160029, 0xffff0566, 0x833233fb, 0xff322360, 0x1483fcff, 0x81820720, 0x83fdff21, 0x66062629, 0xffff0866, 0x226a83f5, 0x8267e619, 0x82fe2029, + 0x0400294e, 0xff879a19, 0x33b30200, 0x224b3982, 0x80fc2205, 0x24ef8200, 0xffcdccfc, 0x202182ff, 0x21c48289, 0x38833433, 0xff999926, 0xccccf1ff, + 0xfb213882, 0x2e1b824c, 0x830080fa, 0xf8ffff87, 0x00ff3333, 0x829a9901, 0x21328321, 0xea5c0000, 0x849a2005, 0x82892053, 0x83b3201a, 0x80fb223c, + 0x21948200, 0x3c829919, 0x5882f820, 0x83090021, 0x82f42095, 0x05002751, 0x8b7f33b3, 0x71827f08, 0x1383f420, 0x5a83fa20, 0xff212283, 0x23ae84f6, + 0x8433b3fa, 0xfe203482, 0xff233f82, 0x8267e6fd, 0x20bf828c, 0x829782ff, 0x21698309, 0xd483e6fe, 0x0a83dc20, 0x3433ef22, 0xeb262982, 0xffffe17a, + 0xfe8233f6, 0x52b8f726, 0x19e7ffff, 0x0a258982, 0xffffec91, 0x372983eb, 0xae470300, 0xccf9ffff, 0x00ff05ce, 0xff1f0509, 0xcccceeff, 0x071400ff, + 0xf72a1482, 0x00ffcecc, 0xff676612, 0x29840500, 0x66660f25, 0x830400ff, 0x060021ef, 0x00217d82, 0x20498302, 0x5d048207, 0x138305dd, 0xccfdff2a, + 0xffb208ce, 0x0080f2ff, 0x02204f82, 0xff213082, 0x7c7982ff, 0x99820553, 0x3484ff20, 0x99feff31, 0x068b089a, 0x4c3a00ff, 0xda00ffcc, 0x82159a19, + 0x205183a0, 0x2730830a, 0xff0180f2, 0x34330300, 0xcc214582, 0x84d482cd, 0x82d920f5, 0xf8ff231e, 0xcf82cc4c, 0xda83f020, 0x68e6fc22, 0xeb27ef86, + 0x00ff9819, 0x8233330e, 0x34b325c4, 0x2a00ff08, 0xec223483, 0x7f8266e6, 0x15830520, 0xc0829182, 0xfe203e83, 0x0523d983, 0x828b9a99, 0xe61d2225, + 0x237f8267, 0x8b32330e, 0x21055655, 0x70831100, 0x82e6f521, 0x190a26e1, 0xffff0898, 0x222c83e9, 0x82343316, 0x82f62070, 0xcefe251a, 0x9b150080, + 0x5917eb58, 0x7b20169e, 0x590f8359, 0x4b18079e, 0xff221630, 0x6a82a700, 0x19950024, 0xdc82159a, 0xff323326, 0xcc4c0800, 0x2605c75f, 0x9a990400, + 0x42f7ffff, 0x082006ba, 0xb3210a82, 0x23238534, 0x6666fbff, 0x02202386, 0x2383b382, 0x73930822, 0x0222fd82, 0x2685cecc, 0x20057843, 0x214a82fc, + 0x2b820800, 0xe6010024, 0x5a850866, 0x23830020, 0x82030021, 0x2223854a, 0x829a19fe, 0x66662418, 0x82a38308, 0x19ec26f7, 0xafffff98, 0x228c8299, + 0x184c0600, 0x21310b66, 0x43826b6b, 0x33ac6518, 0x05abab27, 0x00ffef0e, 0x248c82ef, 0x34331d01, 0x2a928215, 0x00ff9999, 0x9332b302, 0x840000ff, + 0xcd4c23a2, 0xd457088b, 0x9a192305, 0xcb59ff8b, 0xe6fb2105, 0x073bde18, 0x34b3f822, 0x0021e082, 0x22cc8299, 0x8232b300, 0x20098533, 0x86098234, + 0xcb08280e, 0x00ff05cb, 0x8200800c, 0x1e852604, 0x331400ff, 0x83468232, 0xf3ff230f, 0xbd18e27a, 0xc0231d0f, 0x434b0200, 0xff220780, 0x5482cd4c, + 0xff323326, 0x6766ffff, 0x4c210482, 0x210482ce, 0x40826666, 0x9a190626, 0x0300ff7f, 0x1e4d9382, 0x82012005, 0xf1ff22b7, 0x221a83e6, 0x18cc4c40, + 0x222ecb51, 0x4e8b064b, 0xff2105de, 0x274683ff, 0xff6666f6, 0xcc4cfeff, 0x99211382, 0x206b829a, 0x220f8399, 0x82cccc87, 0xa4b718d2, 0x4ac82786, + 0x62ffff3e, 0x9182e04f, 0x66e6b02e, 0xcc4200ff, 0xffff15cc, 0x07a470fc, 0xf025c882, 0xffff9042, 0x84be83f3, 0x4cf02f04, 0xff088bce, 0xcccc78ff, + 0xf0ffff06, 0x2182cd4c, 0xcd4cf32d, 0xb30c00ff, 0x00ff8b34, 0x8270bd0f, 0x8f0322e1, 0x2839825c, 0x1e053500, 0x192a00ff, 0x3004829a, 0x00ffa0fa, + 0x8b66e635, 0xb68bc008, 0x05d5ffff, 0x2b368260, 0x08e2faca, 0xffff078b, 0xfbcd4c00, 0x0818f718, 0x7f830a20, 0x33330226, 0xcc0800ff, 0x03235582, + 0x82946666, 0x82892050, 0x93ff2961, 0xff05cdcc, 0xcc4c70ff, 0xdd2b3382, 0x00ff0080, 0xff686603, 0x82b3e0ff, 0x660e252b, 0xe7ffff66, 0x152a1383, + 0xff08cccc, 0x67e6c0ff, 0xb582054c, 0xff251182, 0xff0280f3, 0xb8b018ff, 0x05f76c0b, 0x82e17a21, 0x008021b3, 0x08859b18, 0x841f8521, 0x276c820f, + 0xcb000040, 0x0100ff05, 0x01207f83, 0xc2838e84, 0x82990121, 0x190222c7, 0x20188299, 0x2062834c, 0x251483f6, 0xffcecc14, 0x6582faff, 0xf1790020, + 0x99182505, 0x064b089a, 0x0efb4418, 0x0c3b4318, 0x110b4318, 0x4000ff28, 0xff06cd4c, 0xc882af00, 0xcc20ff34, 0x00ff15cc, 0x07008076, 0xcc5e00ff, + 0xb5ffffcc, 0xc882ce4c, 0x68e6e622, 0xcc27df82, 0xff7b6acc, 0x824cdbff, 0x66fc2a16, 0x078b0866, 0xf88baf0e, 0xc04c1814, 0x0d4b4c09, 0x1834f721, + 0x270a6f40, 0xcd4c0e00, 0xb3f1ffff, 0x11267e82, 0x088b33b3, 0xa58214f7, 0x6666d926, 0xb6ffff07, 0xff21c882, 0x200483eb, 0x27ec82c9, 0x9a19bcff, + 0xafffff8b, 0xff225f83, 0x1182c4ff, 0x831d0021, 0x82cb201b, 0x2c0028e9, 0x086b9a99, 0x82fcffff, 0xffff2315, 0x09829899, 0xff32b324, 0x5582ffff, + 0xb3fcff27, 0xfb088b34, 0x09746094, 0x2f050a4b, 0x00ff8b34, 0x08cc4c23, 0xf70714f8, 0xf7154b94, 0x14290682, 0xfb0514fb, 0xfbab0614, 0x25b98384, + 0xff00804f, 0x04884000, 0x8b230e82, 0x1800ff08, 0x180ba641, 0x20271c6b, 0x824486bf, 0x213e8271, 0xea82f708, 0x66e64022, 0x07206383, 0xf825af83, + 0x00ffcccc, 0x21ca8308, 0xaa8233f7, 0x83ffff21, 0xffff2106, 0xff231683, 0x8266e6f7, 0x19f825f3, 0x075b089a, 0x8205a45f, 0x821a8fb7, 0x4cf62221, + 0x057f46ce, 0x82f9ff21, 0x080029f8, 0x088bcccc, 0x075b06bb, 0x6f821a96, 0x31852182, 0x4c060023, 0x259982ce, 0x0832b309, 0xa05f07bb, 0x821a890e, + 0x2bac9321, 0x07bb065b, 0xff8bef0e, 0xcccc2401, 0x1df8bd18, 0xdf8f4b28, 0x547100ff, 0x7b82057c, 0xff67e629, 0x58590d00, 0x180e00ff, 0x2d2b70bf, + 0xff08a8a6, 0x98994b00, 0xab8effff, 0xbf180584, 0xec261970, 0xffff34b3, 0x048233f1, 0x0483f020, 0x8219ed21, 0x66fe3531, 0xffff0866, 0xffcccceb, + 0x32b31300, 0x66e4ffff, 0x0c00ff68, 0x08b74518, 0xe1ffff25, 0x828b0080, 0xcc4c2416, 0x82f3ffff, 0x2c2a8225, 0xecffffce, 0xff083433, 0x703d63fe, + 0x213b8206, 0xbe18f6a8, 0xf829179c, 0xbbffff14, 0xfb153433, 0x17f95084, 0x8274fb21, 0xec501841, 0x0b3d5009, 0xcb07842b, 0x0734fb06, 0xf70654f7, + 0x230a8234, 0x15ab24f7, 0x210d547e, 0x77823333, 0xcdccd325, 0x52075b08, 0xe11805b9, 0x14201176, 0x20171c54, 0x109f18fb, 0x83f72018, 0x11002133, + 0x12139f18, 0x4c82bb20, 0x2007b57a, 0x08b57acc, 0x088b3425, 0x7d155b8b, 0x41180e35, 0x5b200771, 0x3684b882, 0x33b31122, 0x11a00819, 0xf854f723, + 0x17e16d3c, 0x4f18db20, 0x40180e80, 0xc0220c4f, 0x796aff00, 0x40f52105, 0xf2210982, 0x065569b3, 0x4861de26, 0x1e00ff07, 0xff31ba82, 0xffecd1fb, + 0x98191c00, 0xebf3ffff, 0x1700ff84, 0x23278280, 0x08142eee, 0xcc210a82, 0x2c0482ce, 0xff0500c0, 0x32b3f4ff, 0x4f0b00ff, 0x2d0a825c, 0xff9a99f6, + 0x48610900, 0x0f00ff8b, 0x0a82a430, 0x82666621, 0xb85e2104, 0x09223082, 0x1a846866, 0x33211982, 0x261f8232, 0xffce4c09, 0x839ef6ff, 0x9938211a, + 0xc7236082, 0x82056866, 0x22258220, 0x18b3f6ff, 0x2107f9b0, 0x1a83f6ff, 0x08200482, 0x5b822b82, 0x9a260f82, 0xccf0ffff, 0x0f828bce, 0x9b517683, + 0x82f42005, 0x0b00231a, 0x8182ce4c, 0xcc4ce827, 0x33e8ffff, 0x204b8232, 0x21a28211, 0xb282e8ff, 0x190c0022, 0xe32c3582, 0x00ff67e6, 0xff323304, + 0xcd4ce1ff, 0x21259082, 0x9b069a99, 0x05d16c07, 0x2206c951, 0x1833b30a, 0x23122541, 0xcd4cf5ff, 0x0fa62a19, 0x0fb85018, 0xf2ffff22, 0x6e0a8b6a, + 0x9b2a08cd, 0xdeffff07, 0xff066666, 0x8c83fbff, 0x9c83e120, 0x66e6f32a, 0xe6e3ffff, 0xeeffff68, 0xa0828c83, 0x17228c82, 0xb68734b3, 0x66660b23, + 0x23cc85ff, 0xce4c0900, 0x20064341, 0x0533410f, 0xff231a82, 0x419a99f6, 0x0a82064e, 0x98829820, 0x5a83f020, 0x26052841, 0xff0832b3, 0x8266c7ff, + 0x2004825b, 0x05234105, 0x82054341, 0x832a8224, 0x09002325, 0x4e416866, 0x230a8206, 0x00ff8b66, 0x66865c82, 0x5b827082, 0x76830b20, 0x40828682, + 0xa282e820, 0x9c820020, 0x80210a83, 0x84b28600, 0x84c684bc, 0x82da82d0, 0x20e6824f, 0x054f7007, 0x5282cc20, 0xcf830a20, 0x20ee5118, 0x4f703b20, + 0x2105700e, 0x2100ff2a, 0xff079a99, 0xcd4ce1ff, 0x2306cc41, 0xff66e6e3, 0x2005e041, 0x29a082e8, 0xcecc1100, 0xe8ffff08, 0x4e413333, 0x24298208, + 0x34b3f4ff, 0x21e28305, 0x5c42ff67, 0x8299200d, 0x9a99210f, 0x23095c42, 0xf0ffff98, 0x2105f853, 0x2f8333b3, 0x1a826820, 0x8266c721, 0x99382360, + 0x2b820598, 0x82b89e21, 0xce4c2115, 0x21083341, 0x25864861, 0x5e090022, 0x2a831a83, 0x33330f22, 0x09221f82, 0x5b86b95e, 0x4f0b0024, 0x8182ff5c, + 0x81823220, 0x00c01727, 0xcc1700ff, 0x224b82ce, 0x43142eee, 0xf3220650, 0x644385eb, 0xd1fb2706, 0x1e00ffeb, 0x758234b3, 0x4761de2b, 0x8b077b06, + 0xb3f2ffff, 0x06f66c34, 0xcc4cf522, 0xc0220e82, 0x1e828b00, 0x0682f220, 0x82181685, 0xdb200a92, 0x8309cd42, 0x05cd4267, 0x0f9d8518, 0x2c0acd42, + 0x00ff077b, 0x06b99e21, 0x2e0400ff, 0x82788315, 0x140c22f3, 0x258c837b, 0x1100ff99, 0xa084ecd1, 0xe8216d82, 0x22b68840, 0x86a4b0f4, 0xf6ff23cc, + 0xe284b89e, 0xf0ffff24, 0xa9825ccf, 0x48a1f624, 0x904300ff, 0x821a8305, 0x4168200a, 0x4c270d28, 0x00ff08ce, 0x839a9938, 0x05982104, 0x4c212b82, + 0x260482cd, 0x00ffb85e, 0x8234330f, 0x823b822a, 0x48a12150, 0x09222582, 0x0a846766, 0x2009de42, 0x200f8399, 0x228c8246, 0x8233b3f4, 0xa4b02181, + 0x17244082, 0xffffcdcc, 0x0a839c82, 0xa2828020, 0x1c21b284, 0x22608219, 0x867c140c, 0x2e0422d0, 0x234f8214, 0x07b89e21, 0x210fce70, 0x435d70bd, + 0x8b082505, 0x2cfb8b07, 0x5cfbb818, 0x8304f721, 0xfcb81860, 0x29f8825f, 0x842b7001, 0x2100ff15, 0x04823333, 0x41482121, 0x33200e64, 0x2c4a6441, + 0x0c00ff99, 0x00ff7c14, 0xffcecc1d, 0x0d644100, 0x9a99f32b, 0xf4ffff8b, 0x00ff6666, 0x0964410a, 0x0d00ff29, 0x00ff0040, 0x829a990b, 0xecbf2116, + 0x66283e82, 0xff088b66, 0x66e65000, 0x200fa446, 0x233e8214, 0x0800c0f2, 0xbd210683, 0x07a44670, 0xff904223, 0xa1a446ff, 0x13439c20, 0x06474407, + 0x13433220, 0xa2a44607, 0xceccfc34, 0xb3e8ffff, 0xf8ffff34, 0xffff3233, 0xff9819ea, 0x0e83f4ff, 0x0080ec27, 0x9e00ff08, 0x221482b3, 0x4e9a9983, + 0x5f2789be, 0xffff3e4a, 0x823048b5, 0x190f2b91, 0x7affff99, 0xff157c54, 0x0a83fc00, 0xcc4c392c, 0xeeffff05, 0xffff6866, 0x0482e6f6, 0x5667ec20, + 0x20c18205, 0x099c51eb, 0x2733b446, 0x19afffff, 0xffff069a, 0x460be542, 0xe54210b8, 0x34b32105, 0x2106e542, 0xb846069b, 0x33e22207, 0x08b84632, + 0xb8466720, 0x8bcd214e, 0xb846eb82, 0x21f28215, 0xb8460900, 0x6666210a, 0x2008b846, 0x20868266, 0x05b84609, 0x458b3421, 0x63480594, 0x800a2206, + 0x06eb4500, 0x99180023, 0x08b84699, 0x82333321, 0x211a830a, 0x3a82e6f3, 0x98191c28, 0xccfbffff, 0xb846ffcd, 0x7fdd2206, 0x0ab846ff, 0x2c82f620, + 0x4cf5ff2f, 0xf1ffffcc, 0x088bcccc, 0xa3f3ffff, 0x23a582d7, 0xff295cf4, 0x2214b846, 0x83d7a30b, 0x22618218, 0x82295c0c, 0x0e00212f, 0x82051946, + 0x0eb8465f, 0x01802224, 0x8a70ff06, 0x4c062105, 0x01207d82, 0x00266982, 0xff991906, 0x9b820100, 0x9a2a0982, 0x058b8b08, 0xf4f7ef0e, 0x0361a4f7, + 0xc359180e, 0x061d4f0d, 0x9718ff20, 0xff2b0916, 0x9a19dfff, 0x0764fb06, 0x821400ff, 0x00ff2308, 0xe382990c, 0xc582e720, 0x3312002b, 0xebffff34, + 0x00ff9a99, 0x22098316, 0x8266e6ee, 0x19f821d3, 0xfe2c1e82, 0xffffcecc, 0xff68e6f7, 0x6666ffff, 0xee830982, 0x0634fb27, 0x99a7ffff, 0x20f18299, + 0x7a1482b8, 0xff200a6d, 0x0733a083, 0xf8f8ffff, 0xf9ffff52, 0xff05cccc, 0x48a1f6ff, 0x83f5ffff, 0xccf02245, 0x213182cd, 0xdf82a1f6, 0x32330a23, + 0x211a8208, 0x4018c5a0, 0x5f210d9f, 0x0655443b, 0x00380025, 0x8205c342, 0xb95e210c, 0x2005ba41, 0x0b7e4800, 0x0833b328, 0x213700ff, 0x21825348, + 0x33330a22, 0xaa7f4882, 0x7ff8820b, 0x411805aa, 0x84201819, 0x3321a682, 0x239b8234, 0x0766e6f9, 0x260b587a, 0xbb088b66, 0x1864f706, 0x18113a80, + 0x2010ed55, 0x859a184c, 0xe60a230e, 0xd75a0666, 0x11003005, 0xff7a3433, 0x66661d00, 0x2100ff8b, 0x82086666, 0x0b375206, 0x3752e220, 0x521e200d, + 0xff280737, 0x9a99deff, 0x19eeffff, 0xe2230482, 0x82729a99, 0xcccc210a, 0x5985e782, 0x9a19bf27, 0x00ff15bb, 0x22e88312, 0x54660d00, 0x59820569, + 0x34b31122, 0x11226083, 0x066184ab, 0x540e2506, 0xedffff7c, 0x08247c82, 0x33efffff, 0x2008704c, 0xfa6b18f1, 0xcc4c3a0c, 0x330f00ff, 0xf1ffff32, + 0x00ff34b3, 0x8bcecc10, 0x6001ff08, 0x84fb66e6, 0x228e8215, 0x180080b0, 0x5018b07b, 0x9a500e93, 0x27ef5005, 0x9cffff22, 0x2b266f83, 0xff15cc4c, + 0x8482c3ff, 0xce240482, 0xe3ffff05, 0x00220a82, 0x7b18b31c, 0xb32137a8, 0xe9401863, 0x7a7b1808, 0xd3d32112, 0x61831d83, 0x18330621, 0x820a4b7c, + 0x2f0f82f7, 0xf9ffff08, 0x00ffcccc, 0xffce4c06, 0xd0ccf5ff, 0x0f83fd82, 0xb3f9ff26, 0x068b0832, 0x02650310, 0x40002152, 0x20066543, 0x59275400, + 0x152b2422, 0x0c449418, 0x0d0d5118, 0x4acc4c21, 0xc4180578, 0xff283890, 0x9a19efff, 0x3b1544f7, 0x54077c6f, 0xf82f0584, 0x00ffcccc, 0x8b66e607, + 0x0900ff08, 0x438b32b3, 0xf5180554, 0xdb200a72, 0x2208945f, 0x8232b3f9, 0x3433242a, 0x57f6ffff, 0xf828057b, 0xff8b9a19, 0x66e6f7ff, 0x0b2e3019, + 0x027d0310, 0x00ff25b5, 0xffcc4ccb, 0x08c28218, 0x76460a82, 0x060f592e, 0x8218db20, 0x3420a9c2, 0x08f38218, 0xff8b3026, 0x34330600, 0x4c220482, + 0x058308ce, 0xdb20fe98, 0x24062441, 0x2400ff05, 0x823082b3, 0x40d44a04, 0x66e63028, 0x0500ff06, 0x85826666, 0xff240582, 0x00800000, 0x8f830f82, + 0xcccc0026, 0xdeffff08, 0x25050e6b, 0xff66e6f5, 0x75820200, 0xccf4ff29, 0x0400ffce, 0x828266e6, 0x18f8201c, 0x2a086f9e, 0xff9a19f8, 0x6666ffff, + 0x10088b83, 0xd401e90a, 0xe6f00024, 0x2d594b66, 0xffaf25cf, 0xb85e2900, 0x66270482, 0xffff1566, 0x5e8f82f3, 0x7d210d0c, 0x600f8471, 0x79600659, + 0x42142205, 0x21cc188f, 0x5e292f0d, 0xd6ffffb9, 0xff0532b3, 0x9a997300, 0xf75d2b07, 0x660d220d, 0x202e8266, 0x055d7212, 0xcdcc103c, 0x540e00ff, + 0x0f00ff7b, 0x00ff3333, 0x8b85ab11, 0x06f4f708, 0xcc7100ff, 0x448207ce, 0x869a9921, 0xc9dd1849, 0x0db25e08, 0x08008022, 0x8305cd5e, 0x08b25e8a, + 0x85008021, 0xffeb25a5, 0x2a076000, 0x26082161, 0x00fffa7e, 0x88343314, 0x068121ac, 0x5f27c782, 0xfffffeff, 0x86d6f89f, 0x18678325, 0x20123cde, + 0x855282f3, 0xcceb2282, 0x50cf18ce, 0x82d6200d, 0x29002aa3, 0xff05ce4c, 0x32338eff, 0xafa61807, 0x05ac4e0e, 0x3333ef23, 0x22358208, 0x4d6666ed, + 0xff21052b, 0x263482f2, 0xcc4ceeff, 0x82fb088b, 0x8cff27ed, 0xff076666, 0x1e822900, 0x58414985, 0x820c2005, 0x83b08c74, 0x941a84ed, 0x2b2b21a5, + 0x231dd95f, 0xeb52f89f, 0x5638e582, 0x01ff48a1, 0x15008057, 0x1000ff8b, 0x00ff1ec5, 0xffcd4c0e, 0xe23a0f00, 0x1808157b, 0x2309fa58, 0x1ec5f0ff, + 0xef33b782, 0xfb08e23a, 0x064b0714, 0xf70714f7, 0x1594fbd4, 0x187fffff, 0x180c4775, 0x700cb742, 0x80311812, 0xcb0766e6, 0xffef0e06, 0x67666900, + 0x66c9ffff, 0x22488266, 0x8216f99f, 0x20d08295, 0x0d6942c5, 0x423b7f21, 0x0a860869, 0xbb18ff20, 0x80270cfc, 0x00ff0800, 0x42b85e29, 0x0023061f, + 0x829a9973, 0x0c6160a0, 0x20216942, 0x4e694294, 0x00ff9125, 0x5f420006, 0x0023054e, 0x50fa5e03, 0xa8820596, 0x00800823, 0x2716858b, 0xc4a0fcff, + 0xeb088591, 0x202e7442, 0x1c7442cc, 0x4a00ff2e, 0xff06cccc, 0x9a19f9ff, 0x99f0ffff, 0xfc200482, 0xef220983, 0x368233b3, 0x08230582, 0x82fb077b, + 0x636742eb, 0x86828b20, 0x9999f628, 0x803701ff, 0xe65d1500, 0x30654205, 0x14fb9422, 0x223c6242, 0x82f744f7, 0x2c002340, 0x58183433, 0xdb2807e5, + 0xff8bcd4c, 0x33b3d4ff, 0x220fc65e, 0x82ceccf0, 0x4cee2418, 0x5efb08cc, 0x0f2242c6, 0x245f3233, 0xbb082205, 0x2c7a8207, 0xffcd4c2b, 0xcccc2300, + 0xb32400ff, 0x05565f33, 0x4410c65e, 0xc65e0920, 0xcc102108, 0x23067453, 0x33330f00, 0x24054d43, 0xf7ef0e08, 0x9c4718b4, 0x71eb2019, 0x2424180d, + 0xd306b307, 0x091b6e18, 0x0d1d4918, 0x180bde4d, 0x220ac549, 0x8ea30743, 0x09a0704f, 0x63607420, 0x06942118, 0x25165e71, 0xcb0734f8, 0x2b68154b, + 0xdb581809, 0xb001190c, 0x0ae64d0d, 0x6882ab20, 0xd7080025, 0x4effff0a, 0x28260511, 0xf7fffff6, 0x5b713433, 0x0aa26205, 0x0ad7f822, 0x28275a83, + 0x076b08f6, 0x62155b9b, 0x39820cbe, 0x1b827685, 0x33200884, 0x27062f4e, 0xffcdccf8, 0xcccc0800, 0x8305dc71, 0x82188508, 0x8b33217f, 0xcd211983, + 0x07e81808, 0x066b2418, 0xb624fb7b, 0x18cc20ce, 0x21112c74, 0xb298066b, 0xbb44f722, 0x3420cf9e, 0xcc20cf88, 0x3420cf97, 0xcc20cf84, 0x2b83cf40, + 0x99f6feff, 0xa600ff9a, 0xff159a99, 0x2119c646, 0xc6463b3b, 0x47002009, 0xff242bed, 0xcd4c1900, 0x66210482, 0x22408266, 0x48cd4c8d, 0x0e200d76, + 0x08377a18, 0x00ff8b24, 0x6918b311, 0xff2411aa, 0x33b37200, 0xe6203382, 0x19201b83, 0xd7184484, 0xe6181a2b, 0xdb2b1883, 0xaf0e053b, 0x00ff94f7, + 0x8266e680, 0xccd126e6, 0xffff07ce, 0x23f782e6, 0x32b3e6ff, 0x8728d9b3, 0xffdb08ae, 0x7cff4f00, 0x241bc748, 0xb0ffffdb, 0x61d91800, 0xf3ff2307, + 0xc3485278, 0x0e4e461e, 0x00239f83, 0x82ce4c19, 0x332e239f, 0xaa480732, 0xb3f1210c, 0x07bc7118, 0x2d12d847, 0x089a9912, 0x800d00ff, 0x99ffff00, + 0xef823433, 0x9a190b2b, 0xe60700ff, 0x0e00ff66, 0x206482cc, 0x220f8300, 0x8319f8ff, 0x99152f25, 0xf0ffff9a, 0x00ff0080, 0xff66661c, 0x0482f5ff, + 0x801b0024, 0x40828b00, 0x66e61a23, 0x8316828b, 0xcc0a281b, 0x00ffa1cc, 0x82ce4c0f, 0x19002316, 0xf5828b9a, 0x4e830b20, 0x1c830820, 0x5d821020, + 0x4cffff27, 0x0b00ffcc, 0x22958233, 0x820080f6, 0x660e2525, 0xf4ffff64, 0x00261982, 0xff9c1912, 0x2d83f6ff, 0x76591220, 0x26448305, 0x87343311, + 0x840a00ff, 0x32b322c5, 0x22c48287, 0x8408cecc, 0xffcc2406, 0x82e6edff, 0x82f5203b, 0xefff2550, 0x088f9c99, 0x27062b69, 0xffcecc05, 0x32b3ebff, + 0xcc203682, 0xf2202482, 0x0025b882, 0x08666608, 0x21bf856e, 0x8b82dfff, 0xb3f5ff24, 0xbb826a34, 0x82e0ff21, 0x067b56a4, 0x7a820920, 0x33ecff24, + 0x48829434, 0xbb79fa20, 0x82fa2008, 0x05274e43, 0x3782fb20, 0x82020021, 0x067a7f48, 0x5882fd20, 0x2005d97b, 0x838283fd, 0xfdff2132, 0x44821e84, + 0x54858220, 0x82f6ff21, 0x82648448, 0x84de2054, 0x66e02d6b, 0x0a00ff66, 0xff6ecc4c, 0x00800f00, 0xf2221682, 0x546d47a1, 0xa8eb2706, 0xf5fffff6, + 0xc8823433, 0xffe17a26, 0x3233faff, 0xee221e82, 0xef833dca, 0x4144cb21, 0xfb270606, 0x00ff29fd, 0x82343311, 0xfdfb221a, 0x830a8336, 0x75b321e9, + 0x4c210982, 0x260482ce, 0x088ffe34, 0x821200ff, 0x04002277, 0x07247f33, 0x0e830920, 0x9a590e27, 0xe60b00ff, 0x251e8266, 0xff67260b, 0xd0830900, + 0xd7231027, 0xb30000ff, 0x23198334, 0xf7ffff67, 0x00209283, 0x2006ba41, 0x22358216, 0x82b3f0ff, 0x661c2144, 0x99831b82, 0xe61a0024, 0x40828b66, + 0x00801b25, 0x8200ff8b, 0x20958205, 0x20568299, 0x834b8316, 0x068b24cf, 0x83b2ffff, 0x6605260c, 0xffff1566, 0x834282ec, 0xffff244e, 0x4233b3ea, + 0xff27055b, 0xff9919ee, 0x82660c00, 0xe8ff2287, 0x20148233, 0x227d8210, 0x82e8dfff, 0x82fe20fb, 0xe9ff2e4a, 0xffff1ec5, 0x08cc4ced, 0x66f5ffff, + 0x25928266, 0xffff3433, 0x1e8268f2, 0xcf82f920, 0xe6f2ff24, 0x1a828866, 0x4e82f920, 0x82feff21, 0xfaff2668, 0xffffd122, 0x254383fd, 0xff8bacfa, + 0xe084fcff, 0x66e6b923, 0x20a08207, 0x78508219, 0x16200511, 0x00334a82, 0x8b8f821a, 0x0624f708, 0x991effff, 0x14f8079a, 0x82b100ff, 0x4dfb25a5, + 0xfaffff07, 0x00214082, 0x2a6a8302, 0xff9819fa, 0xcc4c0200, 0x83f9ffff, 0x41012013, 0xe62205a4, 0x85828e68, 0xff646626, 0xcecc0600, 0x68249983, + 0xcc0800ff, 0xe925a483, 0x00ffcccc, 0x24c38412, 0x00ff66e6, 0x22688201, 0x824ce8ff, 0x82ef2023, 0xff7923c3, 0xd484f3ff, 0x83cccc25, 0x82088b78, + 0x66e12392, 0x82830566, 0x6a180020, 0xff23091d, 0x829a99e9, 0x66e635b9, 0x8b8b0866, 0xffaf0e05, 0x9a19ef00, 0xff1554f8, 0x66661b00, 0x14203282, + 0xed184183, 0xfb2d091c, 0x00ff0764, 0x0666e680, 0xb39200ff, 0x46a04434, 0xa0443c20, 0x3a7f2108, 0x2c0d684d, 0xff08c680, 0xfeff4f00, 0x00b0ffff, + 0x442586c4, 0xd02022a4, 0xf328d182, 0x00fffe7f, 0x0800800c, 0x44054445, 0x6d2206a4, 0x6b18cc4c, 0xff210e1e, 0x08a348ea, 0x8b072b33, 0xffff8983, + 0xff6666f8, 0x9899fcff, 0x66f9ffff, 0x283e8266, 0xff3433fc, 0x34b30100, 0x06604187, 0x34b3fb23, 0x2016828c, 0x459641f2, 0xecffff24, 0xaf826666, + 0xceccea2a, 0xb30700ff, 0xedffff34, 0x002d7a82, 0x0832b30c, 0x0f00ff75, 0xffff0080, 0x25a184e2, 0xff67e6e9, 0xd084f0ff, 0xcdccee25, 0x82f4ffff, + 0xebff2696, 0xffff3333, 0x23b083f7, 0x8bcdccea, 0xec2a9582, 0xff8b9a19, 0x33b3eaff, 0xec42ff93, 0xc7fb3045, 0xffff8aae, 0xff10f8fb, 0x9a99feff, + 0x83fcffff, 0x4cfe2271, 0x256b82cc, 0xffa886fc, 0x14830600, 0xf608fe22, 0x9925bc82, 0x08938b9a, 0x689418eb, 0x0f0d7b07, 0xf7069b23, 0x211b8464, + 0x297b9082, 0x707d2607, 0x821a00ff, 0x2cb78290, 0x9a197f00, 0x9000ff06, 0x54fc66e6, 0x45148215, 0x4c233cd6, 0x45ffffcc, 0x332105d6, 0xf5d64534, + 0x45b89e21, 0xab2107d6, 0x19d64585, 0xd6450220, 0xff3c2108, 0x2008d645, 0x11d64522, 0x45403521, 0xff217cd6, 0x331b4800, 0x0e068b26, 0x1f01ffaf, + 0x5e06cc44, 0x0e2605b7, 0xffffcc4c, 0x4d18abf1, 0xb84d0767, 0x10ba5e14, 0x004a0020, 0x00ff2d09, 0x0734b332, 0x8737ffff, 0x36ffffae, 0x180f9549, + 0x210a085e, 0x5e180080, 0xc93d1d08, 0x00fff853, 0x056666c9, 0x66ccffff, 0xffff0667, 0x8b3333ef, 0xccf0ffff, 0x0e00ffcc, 0x80891854, 0x00ff2908, + 0xff86ab11, 0x34330f00, 0x7a251683, 0xcc1000ff, 0x056970cd, 0xe6200125, 0x82153b66, 0x7de52032, 0x4e4d12f2, 0x9f551816, 0x14fb232d, 0x60b214fb, + 0x7e124e7e, 0x2b2016b2, 0x00205f84, 0x9613807e, 0x20eead31, 0x22bfdeeb, 0x418b14f7, 0xff265c1f, 0x9a199ffe, 0x401814f7, 0x1623085c, 0x7fff6666, + 0x192005a9, 0x4705c277, 0xa31805a0, 0x1c4107f5, 0x41082005, 0xe4201123, 0xff232d84, 0x826666e6, 0xa810191b, 0x00ff240e, 0x4166e660, 0x359b1427, + 0x41ff8b21, 0x91a505b5, 0x1fffff25, 0x8a8b9a19, 0x936720c6, 0x056748c6, 0x87088a47, 0x82eb20c6, 0xeaff25f4, 0xffff0080, 0x9920908e, 0x0b6f1119, + 0xe001ff25, 0x42f766e6, 0x8a415eae, 0x4215200a, 0x1a2008e5, 0x1806864c, 0x480876f6, 0x8a410a4e, 0x84e52011, 0x18ff202d, 0x7109e369, 0x0e240a50, + 0xabb4f8af, 0x181c5065, 0x21111879, 0xaa4e94fc, 0x1119751c, 0x3083f820, 0x9a99b622, 0x8208a657, 0xf3ff21c8, 0xce750483, 0x0080240b, 0x4eeb2b08, + 0x1e570671, 0x5be51814, 0x0eae4909, 0x84080021, 0x075a5559, 0x34b3d223, 0x3e8d1807, 0x19801808, 0xffff2524, 0x07cc4c2d, 0x68204483, 0x4c210482, + 0xe2cf18ce, 0x5830200e, 0xe7180d2f, 0xa0281a61, 0x052b0200, 0x15eb74fb, 0x500bdc56, 0x46561315, 0x21eb8d47, 0x8818ffcd, 0xeb8921b4, 0xeb936620, + 0x57096e58, 0x8b351dbd, 0xffef0e06, 0x9a19a700, 0xff153cf8, 0x66e689ff, 0x1700ff07, 0x225282e6, 0x189a1917, 0x22086566, 0x6effcc4c, 0x082a060c, + 0xffff0080, 0x0834b3f6, 0xba6600ff, 0x4b4b2118, 0x07b34318, 0xcdccf522, 0x2108ba6f, 0x32849a99, 0xffff0826, 0xcbae07c0, 0x1807b66f, 0x6f0bde67, + 0x662005b6, 0x09255a82, 0x00ffb95e, 0x6f758509, 0x758409b6, 0x48211627, 0xe6e8ffff, 0x249b8266, 0x079a1976, 0x0cbf6c8b, 0xff00c027, 0x67660c00, + 0x2042828b, 0x05ef6f0e, 0xf5208083, 0x32095e73, 0xfb54f707, 0xff8b1544, 0x66e6e9ff, 0xeeffff7a, 0x82749a19, 0xeaff232c, 0x1382cccc, 0x3433ed23, + 0xf55918ff, 0x215a820a, 0xb4821916, 0x82cc1221, 0xe6112cfd, 0x1500ff66, 0x088b3433, 0x189c8ba2, 0x220b5ed5, 0x992b44fb, 0x9533204f, 0x84cd204f, + 0x224f9516, 0x828ba4f7, 0x9300204f, 0x00ff2479, 0x8dfeff16, 0x82c98b7d, 0x020021d4, 0xfb23cd98, 0x824cfb94, 0xeeff3258, 0xffffcc4c, 0xff9999f2, + 0x34b3f1ff, 0x66edffff, 0x22328367, 0x48ffffcf, 0xb6520e46, 0x00ff3a08, 0x07008026, 0x07e6ffff, 0xceffffae, 0xff059a19, 0xc2b5f9ff, 0x66f4ffff, + 0x20438266, 0x05e67f73, 0x54270e82, 0x0600ff7b, 0x8808cc4c, 0xffce2a0a, 0x48a1fbff, 0x800e00ff, 0x37198200, 0x00ff3e4a, 0x0832b30b, 0xde2500ff, + 0x4600ffb9, 0xff05ce4c, 0x99590f00, 0x2c067e51, 0xff5dcf1d, 0xcccc1100, 0x4c2000ff, 0x279182cd, 0x9a991300, 0x1000ff06, 0x26820c82, 0xfb20ae83, + 0x0d204683, 0xff230482, 0x8266e6f7, 0x82212046, 0x3e00210a, 0x66214685, 0x4e468767, 0x322005d1, 0xce204683, 0x98204685, 0x20264682, 0xff8bce4c, + 0x1c821d00, 0x4cedff23, 0x835082ce, 0x80e322bb, 0x23468600, 0x32b3c1ff, 0x5c838d82, 0x19080023, 0x201f829a, 0x20048299, 0x20608304, 0x82398210, + 0x99132125, 0xcc204685, 0xd0254684, 0x33eeffff, 0x23268234, 0xffff6466, 0x25204685, 0xb9205b83, 0x06214684, 0x201f824c, 0x266682f4, 0x9899fbff, + 0x82f1ffff, 0xf4ff2646, 0xffff6866, 0x21fe83f9, 0x9f4ff4ff, 0xf1ff2107, 0x00213e82, 0x378a8304, 0xffd0ccf9, 0x9a990b00, 0xe4ffff08, 0x00ff3033, + 0x0566e631, 0x80d9ffff, 0x09cf8818, 0x9c99f222, 0x2008b141, 0x24d88264, 0x0200d0ff, 0x0b226906, 0x200c674a, 0x20398226, 0x08ad4171, 0x4132b321, + 0x8a8307ad, 0xdb82fb20, 0xce208482, 0x8208ad41, 0x0540688f, 0x82b3fb21, 0x05ad41d3, 0xad411383, 0x82242005, 0x430021c8, 0x08586d18, 0x83010021, + 0x82fe203e, 0x01002648, 0xffff66e6, 0x230482fe, 0x34330200, 0x3e82b984, 0xc920b985, 0x9a20b98c, 0x6623b988, 0x995b088b, 0x893620b5, 0xff892ab5, + 0xccccfdff, 0x66ffffff, 0x20638266, 0x22418219, 0x82cd4cfe, 0x66662509, 0x2400ff08, 0xbc200a83, 0xb7829283, 0x6b412482, 0x41248206, 0x3382066b, + 0x82076b41, 0x82f92034, 0xf1ff24d6, 0x41ff6766, 0xcc20076b, 0x86096b41, 0xff8b23b1, 0x4f84d9ff, 0xce82d720, 0xe6470124, 0x6c181566, 0x8084177d, + 0x95820920, 0x20079e44, 0x766c1834, 0x34b32308, 0x9a44a208, 0x4466201f, 0x3220059a, 0x09203482, 0x9a44df83, 0x097b4509, 0x00ff6822, 0x82077b45, + 0x0605450a, 0x668b3020, 0x0a00ff24, 0x366c3433, 0x53cc200e, 0x7b450501, 0xff022206, 0x137b45ff, 0x05cb4b27, 0xf8abef0e, 0xbec71814, 0x79d42018, + 0x7d180952, 0xf720240f, 0xc7183083, 0xff27148a, 0x9a99d600, 0x57b6ffff, 0xff241d74, 0x33b3d6ff, 0x99280482, 0x00ff059a, 0x066766e5, 0xb3240b82, + 0x2900ff32, 0x25380757, 0xff5f00ff, 0x555f2bfe, 0x00a0221d, 0x5f218202, 0x9a8234da, 0x87ce4c21, 0x991a239f, 0x0b820699, 0x87cd4c21, 0x1a5148c1, + 0x2b49f320, 0xffff2917, 0xeb0000a0, 0xf3ffff05, 0x2019017f, 0x5f218460, 0x8b2b199d, 0x8901ff07, 0xfeff6666, 0x456666e9, 0xf12108e4, 0x231e5fb3, + 0x490bc141, 0xfb342463, 0xff0e07d4, 0x9a190101, 0x786001ff, 0xffff1552, 0x8b33b3f4, 0xe6260582, 0xfeffff66, 0x09825ccf, 0xff676633, 0x00c0fdff, + 0xff07cc08, 0x33b30b00, 0x9c0100ff, 0x2609822a, 0x00ff9919, 0x827ad400, 0x34332d09, 0x00ff088b, 0x8b32333a, 0xe9ffffc0, 0x00283382, 0xff68e627, + 0x2a9cdbff, 0x1d201682, 0x0027c782, 0x05846b1d, 0x820a00ff, 0x0a002d64, 0x00ff7c14, 0xff323311, 0x28dcf8ff, 0xf1206882, 0xff245982, 0x9a9996ff, + 0x8305bf69, 0xcecc2117, 0x04831c82, 0x5282f720, 0x1c840820, 0xda700620, 0x21178505, 0xd9831100, 0x95204d82, 0x1e2b5f82, 0x00ff32b3, 0x0534b31e, + 0x82e3ffff, 0x18003233, 0xff66cccc, 0xec110f00, 0x66d7ffff, 0x8b088b66, 0x2819828b, 0xff3d0a60, 0xae0760ff, 0x22708215, 0x82ccccf4, 0x482129c2, + 0x33f5ffff, 0x0200ff34, 0x80280984, 0xffff0800, 0x06eb11bf, 0x7521f482, 0x25aa82c2, 0xffff9a99, 0x098335ff, 0x08077f58, 0xff8b0825, 0xcd4c3900, + 0x911500ff, 0x3400ffec, 0x00ff6766, 0xff527823, 0x98992700, 0xe2ffff08, 0x00ff8f82, 0x8290821d, 0xebf5226c, 0x83408285, 0x820720e6, 0x1100265b, + 0x00ffe03a, 0x0567710d, 0xcd4c6a25, 0x1800ff06, 0x5c0bc3e7, 0xe6820876, 0x0714ae23, 0x065b458b, 0x34b3ee22, 0xe622eb82, 0xe2828166, 0x66e1ff22, + 0x1e22d182, 0x5b829a99, 0x9919e823, 0x2022826f, 0x22ce828a, 0x8233b3db, 0x4cd83e2d, 0x078b08cd, 0xf55400ff, 0xa3ffffc3, 0x6e15cc4c, 0x19e3ffff, + 0x73a7059a, 0x4c2400ff, 0x822b82cc, 0x270025c9, 0x088b34b3, 0xc482d584, 0xcc4c0a29, 0x00ff958c, 0x8266e601, 0x33bf28b7, 0xffff0734, 0x5366e6f5, + 0xf52006d0, 0xff207883, 0xf5223883, 0x33820080, 0x84c6ff21, 0x99cb2566, 0x1600ff99, 0xff218782, 0x22f883d8, 0x829a9922, 0xe3e0273b, 0xe0ffffd7, + 0xf38666e6, 0xee234585, 0x5dff8fc2, 0x0e22067f, 0x74823433, 0x66666922, 0xf482d682, 0x1782cc20, 0x84852b21, 0x00ff241c, 0x827bd408, 0x6900315d, + 0xff067b54, 0x67660d00, 0xffff938b, 0x81ccccee, 0x08218b84, 0x2a14828b, 0x9b9a19a6, 0x056ea815, 0x821800ff, 0x1c00259d, 0xb09a9a19, 0x2820bd82, + 0x06827a82, 0xcdcc0a23, 0x24d0828a, 0xffff0080, 0x221e83fd, 0x8233330a, 0xe640226b, 0x20398266, 0x27158301, 0xff33b3f5, 0x34b30000, 0xc8825082, + 0x4c310582, 0xff8b08cd, 0xccccc5ff, 0xcce9ffff, 0xffff56cc, 0x251c83db, 0x089a19d8, 0x9c426caa, 0x20c18506, 0x222283f8, 0x73ceccee, 0x9622084d, + 0x5d5d9a99, 0x20de820c, 0x22828232, 0x89cecc08, 0x24eb82de, 0x331100ff, 0x20de8334, 0x05ea4232, 0x082f4d83, 0x0e058b8b, 0x99f600ff, 0x2901ff9a, + 0x18156666, 0x4c083343, 0x275c137c, 0x21806418, 0x23480762, 0xcc4cedfe, 0x07b34e18, 0xb31c0023, 0x053d5a34, 0x4c230026, 0xcb088bcc, 0x30a74518, + 0xb9ffff22, 0xff223882, 0x4882c6ff, 0x18390021, 0x820b43b3, 0x08697150, 0xdc296482, 0x088b34b3, 0x4c8dffff, 0x438145cd, 0xe1fa9f2a, 0xffff05eb, + 0x8bcdecff, 0xfa2c0682, 0x00ff1f45, 0xffcecc05, 0x6e73fcff, 0x3d06f959, 0xff72f9ff, 0xcccc0800, 0x0200ff08, 0x00ff7e6d, 0x05ce4c0c, 0x8f0100ff, + 0x0400ffdf, 0x148232b3, 0x82a45021, 0x23b58304, 0x8e271103, 0x60222582, 0x52822b07, 0x5e19b245, 0xff201a89, 0x22051447, 0x820080d7, 0xb3722262, + 0x37e18233, 0x8bcd4c17, 0xe61500ff, 0xf8ffff67, 0x00ff66e6, 0xffcccc12, 0x9a19f5ff, 0xa3206882, 0x2d0fb166, 0xff666609, 0x34b376ff, 0x0000ff15, + 0x9f823303, 0x82cc4c21, 0xc6dc2109, 0x19210982, 0x2cb3829a, 0x00ff988d, 0x0834b303, 0x64feffff, 0x21e382b6, 0xf9823233, 0xffd83024, 0xf283fbff, + 0xe0fcff22, 0xe6230982, 0x828b0866, 0xcccc2415, 0x82078c15, 0x34332107, 0xcc2f0583, 0xef0e07cc, 0x5f0900ff, 0xb601ff3b, 0x8215c4a0, 0x7d7f21c2, + 0x7e210482, 0x0d2265fa, 0x82068121, 0x78682796, 0x96ffff52, 0xc28208ac, 0x9a991323, 0x07f46507, 0x82330f21, 0x3a0f2291, 0x068c54e2, 0x9921c982, + 0x211b8299, 0xd982660d, 0x2009f465, 0x222f822b, 0x82ccfaff, 0x209482f3, 0x21a882cd, 0xa8820080, 0x83cd4c21, 0x26dd83b3, 0xff9919fd, 0x4cb3fdff, + 0x8820057b, 0xaf821a82, 0xe620a682, 0xff234482, 0x840567e6, 0x22168210, 0x869a99fb, 0x20308426, 0x058f59fe, 0x50874c20, 0x6084fb20, 0x57826683, + 0x014d9f20, 0xe13a2105, 0x8882f782, 0x84056344, 0x8208209e, 0xcc10229f, 0x06ab66ce, 0x32330f22, 0xc521bb82, 0x055c4c1f, 0x84069a21, 0x00ff21e4, + 0xe218ee82, 0x42210e4a, 0x061a4190, 0x7c7f0c2f, 0xff078b08, 0xc4a07601, 0x5f09ffff, 0xbc4f183c, 0xffff2417, 0x8234b3dc, 0x74e3207d, 0x0a82054e, + 0x4c230023, 0x207d83cc, 0x24b28223, 0x34b31c00, 0x210482ff, 0x5b43ff33, 0x027d1805, 0xcd4c210d, 0xdc273882, 0xfb0833b3, 0x66152bb4, 0x7f600c8c, + 0x11d4510e, 0xff06eb25, 0x82190000, 0x620020c8, 0xe62e068f, 0xfcffff67, 0x00ff6666, 0xffcdcc05, 0x115ffaff, 0xff992706, 0x66e6ffff, 0x1b828e05, + 0x1b82e620, 0x92820220, 0x80fcff24, 0x104cff00, 0x33fc2305, 0xe2770834, 0xfcff2105, 0x0020be83, 0xff232382, 0x82ccccfb, 0x99fc2695, 0xffff089a, + 0x0cb7679f, 0x25ff9c18, 0x34b31228, 0x96ffff07, 0x048248a1, 0x180b2d57, 0x250a3675, 0x0c00ffc5, 0x5f82fe7f, 0x6780f321, 0x693318c7, 0x00ffb653, + 0x05666669, 0x4cedffff, 0xf7058bcd, 0x53b4f7f4, 0x5d760e29, 0x21228308, 0x2e8307cc, 0x04826820, 0x5cb85321, 0x40520e5a, 0x82c6200a, 0x06ee49ef, + 0xe582c420, 0x70bdeb22, 0x0c3bfa18, 0x34b39622, 0x4082ba84, 0x0745c682, 0x11e9781c, 0x3d462b20, 0xff833c06, 0x9a990300, 0x33faffff, 0x0500ff32, + 0xff0833b3, 0x66e6ffff, 0x190000ff, 0x82880599, 0x8219201b, 0xccfc221b, 0x06d84cce, 0xcc4cff27, 0xe60200ff, 0x22258267, 0x820080fe, 0x33b3211e, + 0x23822f82, 0x19040024, 0x24828b9a, 0x08cc4c23, 0x21db828c, 0x9c18195f, 0xf2490a67, 0x828b200d, 0x4c4d25a8, 0x15b4fbcc, 0x1a82fd82, 0x9996ff23, + 0x1d4a4b9a, 0x6982f320, 0x07d14918, 0x418bd021, 0x92410502, 0x99962806, 0x6900ff98, 0x4105ce4c, 0x9e180554, 0xdc61167d, 0xb3112212, 0x05075c34, + 0x66e60022, 0xff253582, 0x8b8b3433, 0x21c08508, 0x138200ff, 0xd583ca82, 0xe4850120, 0x82083421, 0x34b32114, 0x25068745, 0xff323303, 0x0e830200, + 0x9a190323, 0x201a828e, 0x2d0b8305, 0x93cccc05, 0x990300ff, 0x0800ff9a, 0x4c82cccc, 0x4e845686, 0x6b088b21, 0xf1200e3b, 0x550d897a, 0xd0841138, + 0x0e058b2f, 0x01ffb4f7, 0x1590426d, 0x660900ff, 0x20048266, 0x092f425e, 0x54707d21, 0x82210ddb, 0x154d1890, 0x1ec5210e, 0x210a2f42, 0xa1634b4b, + 0xcb4b211b, 0x210e4d55, 0x4255e23a, 0x21568609, 0x71940c00, 0x2005ae53, 0x2297839e, 0x5500c032, 0x8625054d, 0x330f00ff, 0x0b125a33, 0x5a079879, + 0x8b300ee0, 0x42cdffff, 0x00ff0590, 0xff9a9996, 0xd623fcfe, 0x901b8d48, 0x183320a4, 0x180be4fb, 0x6c0a2f4e, 0xff292d5c, 0x32b3f6ff, 0x80f7ffff, + 0x6fe31800, 0x20e56c13, 0x4c2cc182, 0x00ff06cc, 0xffce4c09, 0x34b3f5ff, 0x2b1bcc42, 0xffff078b, 0xff666669, 0x9a995600, 0x271b444d, 0xffff8bcd, + 0xff33b3f1, 0x650a7151, 0x4c2108da, 0x821683cd, 0xb3112304, 0xd5188b33, 0x48180fdd, 0xff270737, 0x9a9996ff, 0x4f1600ff, 0xbf221f1a, 0x1742ffff, + 0x1fc5210e, 0x6f0d8e6b, 0x09221a27, 0xf6824861, 0x05666627, 0x40cdffff, 0x1ce85700, 0x22139366, 0x8271bd32, 0xa1f62133, 0x6a9a4488, 0x210a9366, + 0x6257e13a, 0x0040220d, 0x27c28301, 0xffccccf2, 0xcccc32ff, 0x58064042, 0x22421415, 0x82cb201d, 0x19bb6746, 0x2b1c254b, 0xff9a99f6, 0xce4c0900, + 0xcdffff05, 0x2105ab4a, 0xd3434cee, 0x4cee2113, 0x5d12d941, 0x448307b3, 0x5df6ff21, 0xcc200fb3, 0x570ccf66, 0x0f28054a, 0x01ffae07, 0x1552f8b0, + 0x5e217482, 0x220482b8, 0x7dff7c5f, 0xa0250cfe, 0x00ff0884, 0x2925823f, 0x52f8c0ff, 0x2600ff05, 0xc6565c0f, 0xb30a2a08, 0x0b00ff33, 0x00ff66a6, + 0x0506550d, 0xff210683, 0x2b168300, 0x9a59f4ff, 0xf2ffff8b, 0x2b0800c0, 0x09814618, 0x77184c20, 0x2b210cbf, 0x82208406, 0x7f2c8226, 0x8b200bca, + 0xcc205083, 0x0a225a86, 0x0e8234b3, 0x8b004022, 0x7c828782, 0x88823382, 0x05259284, 0xa0f6ffff, 0x18b88483, 0x2108747f, 0x0f847d5f, 0x078b082c, + 0x787600ff, 0x1bffff52, 0xdb824821, 0x9a191926, 0x4c3200ff, 0x40265382, 0x00ff9919, 0x0e829951, 0xb3856120, 0xcc4c6122, 0x40203d82, 0xff222082, + 0xca8266ae, 0xff232a83, 0x8234b3cd, 0xcc03256e, 0xf8ffffcc, 0xff261f83, 0xff3433f7, 0x0483fcff, 0x08260f82, 0xe6e6ffff, 0x2583ff66, 0xbfffff22, + 0x39830983, 0x4b9eff21, 0x9e2205e5, 0xd28233b3, 0x67e6bf22, 0x2a846785, 0x35827b83, 0x3333fc25, 0x820700ff, 0x00ff2226, 0x235b8208, 0xcdcc0300, + 0xae840f84, 0x0080ba27, 0xe6b3ffff, 0x2f861866, 0x1800200c, 0x200efeaa, 0x08564ccd, 0x81493320, 0x49558205, 0xff210988, 0x085a49e3, 0x17828282, + 0xe44cff20, 0xa3f7240f, 0x413001ff, 0x662105ee, 0x08ee4168, 0x2109af53, 0xf78284a0, 0xe7830a20, 0x48a1f622, 0x09917f18, 0xffffcc22, 0x6b820f82, + 0xd0ccc123, 0x070942ff, 0x18981921, 0x210e7345, 0x7718cc4c, 0x34210ba8, 0xe04a18ff, 0x062b210f, 0x16e24a18, 0x5242eb20, 0x4234200a, 0xcf180852, + 0x52420e9f, 0xffff260a, 0x07a4f0d9, 0x060542ca, 0x07c0fd29, 0x40feffb0, 0x8415ae07, 0x05ca2110, 0x5c421e84, 0x84eb202e, 0x747818cb, 0x18be4212, + 0x0dc67a18, 0x08bd4318, 0x2600ff35, 0xff079a19, 0x52f8c0ff, 0xccc1ffff, 0xffff05cc, 0x1847a1f6, 0x260e9541, 0x0a00ff48, 0x42083233, 0x565a06c0, + 0x7d5f340b, 0x660900ff, 0x078b0866, 0xf80002ff, 0x1d00ff50, 0x82159a19, 0x66e621d0, 0x200a4643, 0x065a41cc, 0x7142f220, 0x364c1805, 0x05534114, + 0x18cc4c21, 0x2508964c, 0x0d00ff34, 0x3f48cc4c, 0x85088305, 0x0ad16e18, 0x4105bc41, 0x7c8310b5, 0xff066828, 0x30333e00, 0xcc55054c, 0x18ff201a, + 0x200c1d83, 0x294c18d0, 0x20e78307, 0x283d834c, 0x2f0e0534, 0x662901ff, 0x088f4d66, 0x4c008021, 0x6f740674, 0x21ee4f0e, 0x501fe85c, 0x1155186b, + 0x4c2d220c, 0x715218cc, 0xff99250a, 0xcc4ce3ff, 0x6f053743, 0x7945050a, 0x245a5605, 0x8b07ab2c, 0xb34600ff, 0x3900ff34, 0x04825c4f, 0x82cc4c21, + 0xa4b0280e, 0x00ff088b, 0x5634b3d2, 0x5e210828, 0x0e1c49b8, 0x49904221, 0x7f21071c, 0x292b823c, 0x07400000, 0xfffeff2b, 0xfc6dd6f8, 0x74002006, + 0xeb2013de, 0x741c3156, 0x1b411fe1, 0x56cd201c, 0x6d20072d, 0x200e1a6e, 0x09674aff, 0x0a8b7718, 0x27291b41, 0xff66e635, 0xe1fa2a00, 0x19270482, + 0x3500ff9a, 0x828b1f05, 0xb39223ef, 0x40500633, 0x1f445705, 0x0e078b2c, 0x66f900ff, 0xa601ff66, 0x1c4148a1, 0x14464a08, 0x2006e84c, 0x12e84c00, + 0x32b3e634, 0x87e7ffff, 0x00ff05ae, 0x0634b392, 0x60b68bc0, 0xec41568b, 0x66ed2205, 0x08767667, 0xe74b9920, 0x4b082005, 0x0d230cee, 0x4f8b6766, + 0xab210562, 0x06644f07, 0xb3f1ff27, 0x0f00ff34, 0x22548233, 0x82cc4cee, 0x6dff2cd0, 0xff06cc4c, 0xce4c1900, 0x49e5ffff, 0x05481dc0, 0xdb3b211a, + 0x4a0e2542, 0xdb240c9d, 0x075000ff, 0x5d20c183, 0xfe231682, 0x7052f8af, 0x0c426127, 0x4159706b, 0xa900ff26, 0xffff6666, 0x20065d58, 0x07e553dc, + 0x4ce3ff23, 0x123347cc, 0x200f6147, 0x053347cc, 0xbc501683, 0x07224415, 0xf714fc23, 0x091d5194, 0x3e445920, 0x21608205, 0x1a1966a6, 0x608e0d95, + 0x189a5921, 0x2107fa62, 0x608266a6, 0x829a5921, 0xf11a192d, 0xff672208, 0xc31a19ff, 0xaf0e2409, 0x51f4f7ab, 0x2f670e1f, 0x81bd180d, 0x94f82111, + 0x180ebd4f, 0x200c8a46, 0x94c01854, 0x83fc2011, 0x66492130, 0xd6207882, 0x4408e14b, 0xcd423274, 0xffff211a, 0x2606fc79, 0xffff05cd, 0x5bcd4c2d, + 0x7b1809b4, 0xff2524ae, 0x33b3d200, 0x21448207, 0x048248a1, 0x4e33b321, 0x87680d7b, 0x0760292a, 0xf705eb2b, 0xeb152b74, 0x5b1eea54, 0x47502192, + 0xff002406, 0x50ccebff, 0x80230947, 0x82ff0800, 0xff9827eb, 0xcd4c2900, 0xec848b05, 0xc04b0683, 0x43941817, 0x7bec8812, 0xec8e05d2, 0x7b0dc04b, + 0x8b261ad2, 0x94f70e06, 0x375254f8, 0x7377180f, 0xf7fe2f08, 0xff076666, 0x9a191300, 0x0c00ff80, 0xc78266e6, 0x82ce4c21, 0x4ce823b0, 0x004708cc, + 0xac631805, 0xffff2410, 0x8233b3dc, 0x53e3201b, 0x8b2106dd, 0x07ef53ff, 0x34b31722, 0x00234485, 0x8432b314, 0x08962454, 0x550801ff, 0x11220546, + 0x191986ab, 0x2b2510c4, 0xfb1514fb, 0x0b4a1874, 0x8bc02b0f, 0xc08bb6b6, 0x0774f708, 0x587704f7, 0xf9671818, 0x34fc2218, 0x6d611906, 0x8f822108, + 0x200b2f67, 0x673383f7, 0x681805c3, 0x67820eb2, 0x70fb0e2a, 0x54f874f7, 0x0d00ff15, 0x0023d783, 0x4cff1400, 0xf52205be, 0xec827c42, 0x0a39da18, + 0x82f5ff21, 0xf6ff2620, 0xffff6626, 0x06aa52f2, 0x8b830837, 0xa3ffff05, 0xff079a19, 0x9a992a00, 0x4cebffff, 0x1d00ffcc, 0x22228266, 0x823433d4, + 0x66cd253e, 0x54fb0866, 0x17236718, 0xc818fb20, 0x26440db2, 0x83f7200a, 0x32002133, 0x00275282, 0xffb85e1d, 0x82cc2b00, 0xa12a2e57, 0x1400ff48, + 0xff0834b3, 0x66e65c00, 0x187b8407, 0x180bc153, 0x24082451, 0x19ffffff, 0x26d08299, 0x00ff0040, 0x82d7a30b, 0xdabe2bd0, 0x5c0c00ff, 0x0000ff29, + 0x3e821200, 0x66e68022, 0x01250a82, 0xfc4b0514, 0x63691814, 0x8b9b300b, 0xab8b08ab, 0x8b8bbb5b, 0x5b8b8b08, 0x696b8b5b, 0x00260760, 0xff008015, + 0x0482eaff, 0x801a002a, 0x0e088b00, 0x5cf770fb, 0x20073541, 0x0731418b, 0x2108b764, 0xda820763, 0x254eb320, 0x180a200d, 0x29082f86, 0x3cfb06db, + 0x4c68ffff, 0x398215cc, 0xe3830f20, 0x3e0a0927, 0x330e00ff, 0x20048234, 0x22998226, 0x829a9906, 0x681822a4, 0x22be82f6, 0x82050080, 0xe2fa255e, + 0x210500ff, 0x0c27fe82, 0x00ff1f05, 0x8284ab02, 0x9a1922ce, 0x2325828b, 0x069a995a, 0x992d0c83, 0xffff978b, 0x967c54fd, 0xdefaffff, 0x251882b8, + 0xff666618, 0x3e84f4ff, 0xce4c0d25, 0x82f9ffff, 0x0900210f, 0xff29f882, 0x8bccccf1, 0x66f0ffff, 0x20dd8366, 0xad1b19f1, 0x84f32008, 0x210e8430, + 0x408268e6, 0xed820b20, 0x33f7ff26, 0x0700ff32, 0xf2221983, 0x35823433, 0x1f43f120, 0x66ee2105, 0x2805c173, 0x4cf1ffff, 0xffff7ecd, 0x231682f8, + 0xf6ffff98, 0x00213282, 0x82048208, 0x82ce2016, 0x33f0222d, 0x20638332, 0x203f83ee, 0x821686f7, 0x82f7202d, 0x822d827a, 0x8bff2006, 0x85ef202d, + 0x4b06825b, 0xf1220648, 0x2da0ce4c, 0x2013116d, 0x180a43fb, 0x00ff8b25, 0x8234b310, 0x1f852575, 0xb30e00ff, 0x0c22db82, 0x0e82a4f0, 0x089a9927, + 0x0ff3ffff, 0x820a845c, 0xe17a217d, 0x2e851e84, 0x35afc282, 0xc45c1120, 0xcc0f2205, 0x226b90ce, 0x87008009, 0x8207206b, 0xf7ff218a, 0x33206b85, + 0x11226b82, 0x6b839999, 0x16820e20, 0x6607002d, 0x0d00ff67, 0x00ffcccc, 0x8252780b, 0xcecc2144, 0xf42a3582, 0x00fff6a8, 0xff981907, 0x1483f8ff, + 0x9a990c22, 0x0e2e3582, 0x8b086666, 0xffdb058b, 0x34b397ff, 0x7f5eeb15, 0x0aa87a0c, 0x08222982, 0x3982cdcc, 0x16830482, 0x3325e582, 0x2b088b33, + 0x85088506, 0x16af1818, 0x152b2122, 0x6318308e, 0x90901ee5, 0xaf183420, 0xcd201015, 0x3321d482, 0x29908834, 0xd4f7cb0e, 0x0000ff15, 0x2982ae87, + 0x3e8a0022, 0x0b820583, 0x25820820, 0xff67662a, 0x90822400, 0x4c2000ff, 0x1b263482, 0x00ff707d, 0xc582b326, 0x0e00ff30, 0x998b9a19, 0xe6fbffff, + 0x0c00ff66, 0xce82cccc, 0x829ad921, 0x830d2031, 0xb3192627, 0x1a00ff34, 0x283b82e6, 0xffcc8c11, 0x66e61e00, 0x831a828b, 0x2f168306, 0xeeffff66, + 0x00ffa470, 0xffce4c0d, 0x5c4fe6ff, 0x0b201a82, 0x07294583, 0xff996626, 0x9a190400, 0x212d839a, 0xb783b326, 0x82661f21, 0x83e4202d, 0x4c082180, + 0xdb226382, 0x2d82707d, 0x00800022, 0x9921a283, 0x8205839a, 0x2212820b, 0x82cc4c23, 0x075e5d0c, 0x20055046, 0x20068208, 0x218e82f4, 0x5d82fcff, + 0x19f5ff22, 0xfa26ad82, 0xffff0080, 0xa88299f6, 0x2911fe2c, 0xffff06ba, 0xff148efa, 0x64830900, 0x20e2fc27, 0xe60a00ff, 0x22468267, 0x5a33b30b, + 0xbb820555, 0xa1a81c22, 0x25069d49, 0x8b0a5723, 0x33828b08, 0x4100c026, 0x9964ffff, 0xb36c8918, 0xf7ef0e23, 0x19ad7e94, 0x47b4f721, 0x82280e05, + 0xffff8b90, 0x08707de5, 0x09c2aa18, 0x0f516f18, 0x2dffff24, 0x3682cc4c, 0x34b3012e, 0xe60500ff, 0x00ff8c66, 0x8b008004, 0x992a0b82, 0x00ff089a, + 0x0733b3f2, 0x971800ff, 0xab2118a7, 0x18298207, 0x2f13a997, 0xdb0604fb, 0x3b01ff07, 0xfeffcc4c, 0x1534b3d4, 0x1a6c4818, 0x18cb4b21, 0x211b00cc, + 0x66184b4b, 0x48183625, 0x322008b8, 0x86214082, 0x064d6399, 0x1811d87d, 0x210c3361, 0x6c433307, 0x00ff2407, 0x82666679, 0xb32422fa, 0x0ccc1834, + 0x49491809, 0x068b2416, 0x82c4fdff, 0xab002127, 0x2705a246, 0xffcccc08, 0xfc290700, 0x2805a543, 0x04d60800, 0xf4f7088b, 0x20698b06, 0x12427fff, + 0x55441383, 0x82f72006, 0xfb082187, 0x27193282, 0x437f0a7e, 0xf4f7230c, 0xc357c4fb, 0x6efb2017, 0xf72c18f6, 0xd4f70774, 0x0774fb06, 0x34f764fb, + 0x23619644, 0xf8b4f8af, 0x2ff1cc18, 0x4b066333, 0xfb06d307, 0xffff0714, 0x8b9819ca, 0xe6d5ffff, 0x20048368, 0x240a8266, 0x089a19ca, 0x1361184b, + 0x649f1817, 0x82cb2018, 0x35002c31, 0xff6066e6, 0x9a192a00, 0x83088b56, 0x189a2059, 0x1811c18e, 0x85183fef, 0x123b5759, 0x9f825987, 0x841f0521, + 0x255a825d, 0x088be1fa, 0xc38214f7, 0x6307cb22, 0x4d0e9558, 0x332e2289, 0x063b154b, 0x06db074b, 0x64fb07cb, 0x0985158b, 0x5b063b23, 0x2316888b, + 0xd4f8ef0e, 0x39365541, 0xccb7ffff, 0xffff07cd, 0xff9899e1, 0x99191900, 0xe6d8ffff, 0x0f00ff68, 0xc1829a19, 0x8b00802e, 0xbaffff08, 0xff8b66e6, + 0x3433c4ff, 0x332b1b82, 0xe3ffff33, 0xffff3233, 0x7d9919c6, 0x01200778, 0xf9262b83, 0x00ff66e6, 0x35829900, 0x34b3f922, 0x20564f41, 0x674f411e, + 0xfb2cf823, 0x555510a4, 0x02100e01, 0x234d0160, 0xa4fb0cf7, 0x5d786818, 0xc8505418, 0x01780210, 0x4b5310ae, 0xab213c01, 0x997c18f8, 0x777b200b, + 0xab230710, 0x55088b85, 0x63303091, 0x83074b06, 0xc2ffff06, 0xff8b9a19, 0x66e6cdff, 0x0a820484, 0x08351082, 0x66e7ffff, 0xffff0766, 0xff9a19f6, + 0xce4cfaff, 0xb3f7ffff, 0x21048232, 0x0e829899, 0x81686622, 0xee2c2082, 0xff9f6666, 0x3233e6ff, 0x990d00ff, 0xe3212582, 0x0dd64733, 0x7c496020, + 0x0ce26612, 0x21242249, 0x1e49b61e, 0x6e0d281c, 0x00ff8b16, 0x82ea9112, 0x19ff2c90, 0x0cf8079a, 0x06db152b, 0x823b07cb, 0x8b5b22dc, 0x24088515, + 0x64fb06db, 0x2216888b, 0x186b0cf8, 0x24d22752, 0xf7140000, 0x33ca18f4, 0xb57e1809, 0x191b420d, 0xdcffff2c, 0x8b076666, 0x4cf0ffff, 0x7118ffce, + 0xcc270c3f, 0xffff088b, 0x829c99da, 0xcce1241b, 0x82ffffcc, 0x220a8204, 0x829a99da, 0x19832316, 0x2d82079a, 0x829a1921, 0x19f32e11, 0xfcffff9a, + 0xff803433, 0x3233f8ff, 0x20451808, 0x80002311, 0x30190500, 0x4f4b11fb, 0x14fb2116, 0xff205882, 0xff205283, 0x78213682, 0x6b4618ff, 0xe6f4261a, + 0x0700ff67, 0x26b683cc, 0x00ff9919, 0x8366e603, 0xff992a92, 0x66e6ffff, 0x7c00ff08, 0x22d783e6, 0x82662500, 0xc0e12716, 0x1e00ff00, 0xd0823433, + 0x83a4b021, 0x4cf022d7, 0x21ba83cd, 0x72188f42, 0xb3210811, 0x2f338232, 0xff140000, 0x9a992300, 0x7f01ff05, 0xd4fbecff, 0x40354318, 0x010c4910, + 0x354318ce, 0xeb2f3338, 0x5b15b4f7, 0x8b079306, 0xf35300ff, 0x4400ff34, 0x04829a19, 0x82cc0c21, 0x67e6250e, 0x06bb088b, 0x66200883, 0x18831d82, + 0xf3bbff2c, 0xffff8b34, 0x08cc0cac, 0x35860783, 0xa4703931, 0x66d1ffff, 0x2e00ff66, 0xffff5c8f, 0x789a99c6, 0x08830535, 0xff231885, 0x82a470d1, + 0x8fc62235, 0x2635825c, 0x00a0ffff, 0x67154b13, 0x54220882, 0xdb18ff67, 0xf8210a11, 0x0ebd5b14, 0xb118b320, 0xcd210c2f, 0x25da18ff, 0xffff3f0f, + 0x0666e6fa, 0x99e9ffff, 0x0569fb9a, 0x99fcffff, 0xe7ffff9a, 0xffff0080, 0xffcc4cec, 0x0983edff, 0x6666e72a, 0xffff088b, 0x06676616, 0x73201b82, + 0xeb205183, 0x1220af83, 0xfd281c83, 0x00ff146e, 0x08008018, 0x91224382, 0x4383f7eb, 0x18f3fa21, 0x1810f9ab, 0x33079163, 0x000000ff, 0xaf0e0614, + 0x4cbb00ff, 0x3801ffcd, 0x9c1566e6, 0x043cb182, 0x00ff3333, 0x05cecc13, 0x990200ff, 0x00ff989a, 0xff99990c, 0xa4700800, 0xfdffff98, 0x8205ed56, + 0x26118206, 0xffff6766, 0x84285cf3, 0x087e2315, 0xb1826383, 0x82ccfd21, 0xccf428d5, 0xf6ffffce, 0x51ff9919, 0xf3260535, 0x088b34b3, 0xad82066b, + 0x07cdcc27, 0xb32600ff, 0x211d8233, 0x5e829a99, 0xb3840920, 0x07205d83, 0x33242d84, 0x0100ff34, 0xf6255583, 0x9308cc4c, 0x20218253, 0x224f8301, + 0x8266e6f2, 0x20048331, 0x845983f3, 0x19fe270e, 0xffff089a, 0x8282e6f2, 0x3233fe22, 0x28828782, 0x07087918, 0x0d20ad82, 0xfa231e84, 0x82b3cd4c, + 0x99ed2794, 0x0400ff9a, 0x0a829999, 0x6783f520, 0x3333ec23, 0x056e5b76, 0xe6e6ff24, 0x47828b66, 0x33b3e827, 0xeaffff8b, 0x20f882f3, 0x2793830c, + 0xffb81ef5, 0xcdcc1300, 0xed271a82, 0xffff299c, 0x826766fb, 0x47fa223c, 0x20e383ae, 0x821c82fe, 0x21938279, 0xe382d9f3, 0x9883f620, 0x48e1f222, + 0xcc21ba82, 0x223082ce, 0x82bedff2, 0x24b2840a, 0x00ff0ce2, 0x259d820c, 0xd2df0100, 0x938400ff, 0xff070024, 0xd883c3ec, 0x30826120, 0x82b30921, + 0x160737f0, 0x0700ffc9, 0x00ffcccc, 0xff527809, 0x67660200, 0x2400ff08, 0x0f8285eb, 0x82666621, 0x33182e29, 0xffff0733, 0x060000e0, 0x75f5ffff, + 0x22a782c2, 0x526626f6, 0xff2e05be, 0xffc5c0fd, 0x32330b00, 0xf7ffff08, 0xeb83ecff, 0x7a66fd28, 0x0800ff98, 0x7982d36d, 0x82d8a321, 0x7dff2104, + 0x99225382, 0x1582089a, 0x9a990222, 0xa3211082, 0x212c82d7, 0x15845c8f, 0x6a827e20, 0x82230421, 0x33ec2210, 0x266a8232, 0x06e2fa10, 0x180400ff, + 0x2208679f, 0x82900208, 0x82e62085, 0x260a226d, 0x21728267, 0x68829a19, 0x4082de20, 0x7a490029, 0xffff05e2, 0x821e85fa, 0xea112a50, 0x570500ff, + 0x0e00ff0a, 0x215f8339, 0x0e82ec11, 0x08e27a22, 0x0a841983, 0x1982e020, 0x82523821, 0x74a8212d, 0x87261982, 0xf3ffffae, 0x1e8250ed, 0x9a191a27, + 0x6bc6ffff, 0x83788284, 0x3900230a, 0x0a827c94, 0x00800522, 0x12213982, 0x213482b0, 0x2f82cc4c, 0x978c5722, 0x85213a82, 0x22308220, 0x8634330b, + 0x33062773, 0xf1ffff33, 0x0e8266c6, 0x82999921, 0x16ee214f, 0xde829883, 0x85b6ff23, 0x071f751e, 0x66e6f823, 0x055a4993, 0xff2ad284, 0x08cc4cf5, + 0xff058b8b, 0x47833a01, 0x66664423, 0x20638215, 0x205282b3, 0x05585af7, 0xff64e626, 0x68e60f00, 0x08233e82, 0x8295d0cc, 0x9819290b, 0xe60000ff, + 0x0900ff66, 0xff210982, 0x2d3e82f7, 0xcc0a00ff, 0xf7ffffd0, 0xff8c3433, 0x1a82f0ff, 0x63821583, 0x0866e626, 0xe0ffff70, 0xff214783, 0x22c082f8, + 0x8266f7ff, 0x66f3279b, 0xfdffff64, 0x208268e6, 0x829c1921, 0x32b321ca, 0xe425a582, 0x059bcc4c, 0x05c17eff, 0x66e6eb27, 0xffffa705, 0x287482e4, + 0xf9ffff92, 0x00ff3233, 0x209b8302, 0x209583f5, 0x204283fc, 0x225982f6, 0x83eaffff, 0x84cb2069, 0x19fb225d, 0x23ef829a, 0x857d34b3, 0x90200684, + 0xf3215182, 0x283782b3, 0x8566e604, 0x00ff9099, 0x23a5820c, 0x2500ff9a, 0xf2202c84, 0x00234282, 0x8234330d, 0xcceb226f, 0x247482ce, 0xffffcc4c, + 0x204c83e7, 0x200483fe, 0x254b82eb, 0x9a190c00, 0x37827608, 0xff210b82, 0x7fba82f4, 0x002005fd, 0x99210984, 0x205e829a, 0x225e83ed, 0x82323305, + 0x83e72044, 0x84e02024, 0x83f7204f, 0x99f5214f, 0x07368518, 0xbb82fe20, 0x0e83ff20, 0x18080021, 0x21085f7f, 0x2e830800, 0x9919fe22, 0x82064a41, + 0x00ff2819, 0x0800800a, 0x822200ff, 0x2c00217e, 0x0021a383, 0x2a248206, 0x9a990700, 0x0300ff95, 0x58ffce4c, 0x4e820530, 0xc4822582, 0x6625b382, + 0x00ff0566, 0x2369820b, 0x9a191400, 0x40418482, 0x83f62006, 0x83052037, 0x83fb2085, 0x830b20ab, 0xb3032251, 0x21618234, 0x3b82cccc, 0x98190d26, + 0xb32600ff, 0x0021fa82, 0x086f6304, 0x45830d20, 0x33b30622, 0x0982ee82, 0xccfbff23, 0x06c16ecd, 0x83fbff21, 0x82052014, 0xf2ff2343, 0x78456666, + 0x83f32006, 0xf8ff24aa, 0x82776666, 0x830f2080, 0x80f72230, 0x270a8201, 0xffcccc09, 0x32b30700, 0x30829582, 0x82040021, 0x0c002119, 0xa4783582, + 0x07002105, 0x00219382, 0x21b5844f, 0x29824c01, 0x82330d21, 0x830b2094, 0x83092099, 0x330d2704, 0xfeffff32, 0x798232b3, 0x0a821983, 0x19831e82, + 0x82059c7f, 0xffff2819, 0x08ceccf2, 0x82f9ffff, 0xc0ff2348, 0x7282ffff, 0xe2833320, 0xcdcc2422, 0x0a200a82, 0xc3827d85, 0x68e60e25, 0x83fdffff, + 0x82072019, 0xf5ff2313, 0x5382cd4c, 0x63820720, 0x33f5ff23, 0x21198433, 0x0a82ff7c, 0xffff3023, 0x241a83f8, 0x0280bdff, 0x2c40825c, 0xff9a1906, + 0xccccf4ff, 0xf3ffff8d, 0x20418266, 0x29a482fe, 0x9899f3ff, 0x0e078b08, 0xc1588bef, 0x717d2a0b, 0x7d1500ff, 0x1a00ff70, 0x50c31882, 0x00802208, + 0x7396198b, 0xffff2e10, 0x07cdcc47, 0xe6d8ffff, 0xdfffff66, 0x207b82b3, 0x266383e7, 0x8b3433cf, 0x5dc9ffff, 0xce200508, 0x1421a783, 0x20208266, + 0x246f82d3, 0x66e62000, 0x22e2826b, 0x823433f7, 0x212c83a2, 0x958299f2, 0x0983f920, 0x66e6f027, 0x062b088b, 0x17be58db, 0x164dec18, 0x2b073b22, + 0x2b173360, 0xdb0734f8, 0xff1544fb, 0xf628f7ff, 0xf8269182, 0xffff0ad7, 0x9918ccf8, 0x6b200754, 0xff206882, 0x00238883, 0x83f62807, 0xffcc2518, + 0x0ad70800, 0x07265718, 0x00242682, 0xff333307, 0x10a65718, 0x23127f5c, 0x5bdb066b, 0x0a255718, 0x4d873320, 0x08216b82, 0x0fcb5cab, 0x0ea45618, + 0x2011cd5c, 0x17cd5c6b, 0xf7076b23, 0x25571804, 0x18ce9210, 0x180d51b1, 0x851e7558, 0x83fb82ce, 0xf7ff2aec, 0x088b3433, 0x64fb066b, 0x41cf89db, + 0xcc202d1d, 0x5d089d5d, 0xcf84070c, 0x5d0b8141, 0xcf89076c, 0x5d8b3321, 0x1c8908ba, 0x9a181382, 0x504113f3, 0x4180931f, 0x59180c9e, 0x58182b93, + 0xf8232dc4, 0x5674fb14, 0x6c285eb7, 0x00ff34b3, 0x1534b32c, 0x2509136e, 0xa6ffff05, 0xfc7b9899, 0x0aca5a0c, 0x8c094541, 0x00ff24f7, 0x82686659, + 0x4ce32433, 0x82ffffcc, 0x36d15b04, 0x18c3c321, 0x201b296c, 0x201d8253, 0x47e818ff, 0x078b2733, 0xe4f7ef0e, 0x8c1854f8, 0x3b5d0e3b, 0xa2794408, + 0x08ba4e18, 0x23104d45, 0xa4fba4fb, 0x44375d43, 0xdf44162d, 0x072d4415, 0x440a5d43, 0xae44132d, 0x395d4340, 0x7b44ce84, 0x225c180e, 0x22b1890e, + 0x45f744fb, 0x2d4410cc, 0x41ae4412, 0x1d41cf8c, 0x137b442c, 0x45166962, 0xce9214cc, 0x182dcc45, 0x2113735d, 0x1b1004f8, 0x1010014d, 0x48035b04, + 0x1d10db20, 0x10280147, 0xa8037204, 0x01411f10, 0x1be5443c, 0x5119f06a, 0x0d104ff5, 0x2289027b, 0x75eb44f7, 0xf72117be, 0x0e7d6c24, 0x8b0ad72a, + 0x28f7ffff, 0x14fb08f6, 0x5b079a54, 0xf8220548, 0x144fcccc, 0xfb082a05, 0xd4fb0624, 0xf8064b07, 0x6a9f1874, 0xaf0e2117, 0x321b8243, 0x666effff, + 0xffff0766, 0xff3433ec, 0xcdccebff, 0x83f3ffff, 0x4ce4225b, 0x227a82cd, 0x620080e1, 0xec230898, 0x828066e6, 0x9a19211c, 0x850b5376, 0x4cf42597, + 0x0300ffcc, 0xf5201983, 0x00210482, 0x08fe6f05, 0x66a7ff23, 0x4ebe5566, 0x02c80310, 0x2b54218a, 0x26cfd664, 0xd4f730fb, 0x5915e4f7, 0x6c440807, + 0x0b88530f, 0x20110559, 0x797b19cc, 0xcc082312, 0x16858bcc, 0x220a8056, 0x5504f79b, 0x081017c6, 0x22bb0111, 0x7264f733, 0xbf460ead, 0x18332008, + 0x2207e344, 0x19b30a00, 0x200c3f11, 0x9d4518ab, 0xf587180c, 0x18a3200a, 0x2108e780, 0x4877ccf8, 0x163c550c, 0x7b077b25, 0x5a07cb06, 0x28280f09, + 0x00ff8bf6, 0x080ad708, 0x525a0685, 0x05dd5b05, 0x3333f72f, 0x065b088b, 0x8b153be3, 0x80e5ffff, 0x37fe1800, 0xbf651810, 0x1500220b, 0x2ea51880, + 0x054c7507, 0x129c2819, 0x580d8d5c, 0x6b360898, 0x3dffff07, 0x00ff5c4f, 0x1548e148, 0x17fcffff, 0x0500ff0a, 0x8a8228dc, 0xffc2b531, 0xb89e0200, + 0x40f9ffff, 0xfdffff00, 0x820834f3, 0x8f42210a, 0xf5260a82, 0xfbffffc2, 0x0e824861, 0x82aec721, 0x82f8209d, 0x5c2b201a, 0xdf84179b, 0x0722de82, + 0x995cf628, 0x00ff3a0b, 0x0734332b, 0xb02200ff, 0xcbffffa4, 0xff0566e6, 0xf6e80300, 0x33faffff, 0x21268232, 0x6582cd4c, 0xffce4c26, 0x33b30600, + 0x19228482, 0x0a82089a, 0x8dcdcc23, 0x05c35eff, 0x32330623, 0x8225828b, 0x18eb2016, 0x200a8774, 0x821282cd, 0xf7ff2464, 0x828b3333, 0x410683aa, + 0x7a190550, 0xd4220c6e, 0xf182cccc, 0xf183dd20, 0x7c143425, 0x5eaf0e05, 0xfb213448, 0x29448233, 0x7a9a99d5, 0xbaffff05, 0xca5a6666, 0x0702580f, + 0x9e824b20, 0x18ffff21, 0x2008226f, 0x20dc83ff, 0x830e8200, 0x2bd28213, 0xffcc4c02, 0x66e6c5ff, 0xcc1500ff, 0xa9200982, 0x4a35f183, 0xffff9a99, + 0x08cc4cc7, 0x33faffff, 0xfdffff34, 0xffff0080, 0x201483f9, 0x220483fe, 0x10cc4cf9, 0x2001731e, 0x14f72b22, 0x5937ad5a, 0x0b5e160e, 0x00ff3ae4, + 0xff9a19a7, 0xcd4caeff, 0x0500ff15, 0x00ff32b3, 0xffcd4c02, 0x68660600, 0x300f858b, 0x33b3fdff, 0x7800ff08, 0xffff0200, 0x05ffffcf, 0x056e64ff, + 0xce4cfc2f, 0xf7ffff91, 0xff8b3233, 0x3433f6ff, 0x3a068208, 0xff34b3c0, 0x9819e6ff, 0x8096ffff, 0x93ffff00, 0xffff9c19, 0x089899d2, 0x83faffff, + 0x99fd2114, 0xf9200f82, 0x0f845783, 0x66020023, 0x201a8264, 0x237d8293, 0x68662d00, 0x9a253983, 0x806900ff, 0x22778200, 0x82cc4c3f, 0x09002350, + 0x8382cccc, 0x08302083, 0xff95cecc, 0x32b30300, 0xff0cf708, 0x01003000, 0x08228682, 0x918266e6, 0x1567e633, 0x1944ffff, 0x00ff0798, 0xac343344, + 0x4c1700ff, 0x27bf82cc, 0xff68e603, 0x9a993300, 0xa02b6182, 0x00ff9899, 0x05ce4c25, 0x4c30fb0e, 0x07101b74, 0x27bb01e5, 0x4cedffff, 0xc800ffcd, + 0x2105cd46, 0xcd469919, 0x34b32107, 0x2107cd46, 0xcd46cc4c, 0x34332108, 0x2107cd46, 0xcd466666, 0x24a11916, 0x655e180d, 0x0a614a0b, 0x8208cd46, + 0x07cd4665, 0x5182e620, 0x8306cd46, 0xce4c2470, 0x840600ff, 0x06cd4684, 0xcd46cc20, 0x46cc201d, 0x342008cd, 0x1805cd46, 0x1808db9d, 0x2109537b, + 0xcd46ffff, 0x2ef18306, 0x057c1434, 0xb382ffff, 0xf7ffff33, 0x4815b81e, 0x5a641651, 0x0800490d, 0xe8184b20, 0x4318099c, 0x65480d72, 0x47cb2016, + 0x5f842e77, 0x195ef720, 0xc3b91805, 0x0b2e490c, 0x200a5041, 0x1f4e61cb, 0x33c0fe31, 0xffff0734, 0xffccccd9, 0x9899eaff, 0x83e6ffff, 0x33d7295c, + 0xffff8b34, 0x089a19d1, 0x28068870, 0x9a990300, 0x0600ff7f, 0x2826824c, 0x08ccccf5, 0x19a6ffff, 0xf20f109a, 0xc423d902, 0x181544fb, 0x201a28da, + 0x201b82cc, 0x611d19dc, 0x332c2710, 0x2300ff33, 0x0483cccc, 0x00ffcd22, 0x123f2319, 0xa0183320, 0xfb260765, 0x32ffff74, 0x638266e6, 0x66330028, + 0x2900ff66, 0x048634b3, 0x8b280e82, 0x6500ff08, 0xff06cecc, 0x64211b82, 0x2217858b, 0x834cd6ff, 0x99cc2374, 0x7b82089a, 0x2e82ec20, 0x66f0ff24, + 0x0482ff68, 0xffff6625, 0x8230b3ec, 0x25ff2133, 0x0c823383, 0x21823420, 0x5583f020, 0x9a990f22, 0x13223e82, 0xe869cc4c, 0x69c14739, 0x02af2910, + 0x155b2e6f, 0xff8b077b, 0xcdccd3ff, 0x33dcffff, 0x20048334, 0x250e8333, 0x7b088bcc, 0xa3189b06, 0x9b25179e, 0x64fb3b06, 0x20208815, 0x08f04334, + 0xf043cc20, 0x069b2106, 0xde185686, 0x8b221162, 0x39b604fb, 0x829b5b21, 0x067b21ac, 0xae859e85, 0x0aa3de18, 0x9b079b22, 0x0e4fb218, 0x84343321, + 0x08cc24d9, 0xb215eb7b, 0x82072034, 0x14f721df, 0xcd217293, 0x21e6838b, 0x72920833, 0x2307da44, 0x1584f79b, 0x0d718518, 0x08574c18, 0x57182320, + 0xf3202e01, 0x0d555818, 0x00c00a22, 0x08235885, 0x18152beb, 0x1818eb56, 0x20144b57, 0x964997ab, 0x076b24a9, 0x97c33cfb, 0xae6b20c6, 0x2a7c98c6, + 0xc800ff0e, 0x01ff66e6, 0x82cccc4b, 0x4c20326b, 0x6300ffcd, 0xff059a99, 0x33330300, 0xe40900ff, 0x2d0482de, 0x00ff3433, 0xff7ab406, 0x66660a00, + 0x0685088b, 0xff231685, 0x83864bf9, 0xff32252a, 0x221bf6ff, 0x22271a82, 0xffff0080, 0x82008095, 0x82462040, 0x1900230a, 0x0a8266a6, 0xcecc0822, + 0x30212582, 0x303482a4, 0xffffcccc, 0xff7cd4fd, 0x34b30500, 0x6ef9ffff, 0x20348214, 0x28298207, 0x6666f9ff, 0x190200ff, 0x8249829a, 0xfcff216f, + 0xff289482, 0x083233f7, 0x4ce6ffff, 0xb9223382, 0x48820180, 0x29836a20, 0x5e84dd20, 0x20830920, 0x82ccfc21, 0x830620af, 0xccf62649, 0xffff8bcc, + 0x059b46f5, 0x5b820682, 0x16823683, 0x55835082, 0xceccfc22, 0x98204b82, 0xde223583, 0x4b829899, 0x68e63427, 0x669bffff, 0x200a8268, 0x25158304, + 0xff32b3f6, 0x3483feff, 0x8299f421, 0x84f72085, 0x6666219f, 0x9a833482, 0x0f84ff20, 0x23841984, 0x00202d83, 0x1e823782, 0xff214382, 0x224d8200, + 0x82ffff05, 0xffff2159, 0x0a826382, 0x79866f82, 0xf9208384, 0x97825883, 0x30828b20, 0x1b820683, 0x4ccccc21, 0xff200545, 0xcf82c584, 0x23064d74, + 0x9a196700, 0x9b274082, 0xffffb85e, 0x829819cb, 0xb3f6250a, 0xfbffff33, 0xf425c583, 0x00ff0a97, 0x279a8301, 0xffeb91f8, 0xcc4c0800, 0x0a843482, + 0xb4830620, 0x1f45fe32, 0x660b00ff, 0x0400ff66, 0x00ffd7e3, 0x08ce4c09, 0xf0249a82, 0x6400ffa4, 0x9a83f383, 0x2100ff22, 0xff23f383, 0x41e11af6, + 0xf92206b9, 0x2a82994b, 0x8b343325, 0x820a00ff, 0x820685ef, 0x67b4219a, 0x04821684, 0x5582e520, 0x33330322, 0x63204b82, 0x00236582, 0x82cd4c20, + 0x02902794, 0xa300ff0c, 0x0a827a54, 0x4676f922, 0x87212582, 0x269a82ae, 0x00ffdf2f, 0x820ad70c, 0x4a2c219a, 0x2b210482, 0xed5c1986, 0x8c2c2108, + 0x01221986, 0x2d859c2f, 0x3782ff20, 0x43821e82, 0x82ffff21, 0x0e05264d, 0xf78cf72f, 0x0a5643ec, 0x5a18cd20, 0xe81808a2, 0x9d180e8f, 0xd61810b2, + 0xd6181253, 0x3b3a1651, 0xa1ffff07, 0x1553cdcc, 0x668c00ff, 0x00ff0667, 0x8b66e620, 0xeaffffaa, 0x3a4134b3, 0xe0ff2305, 0x95823233, 0xcc4c1c35, + 0xb3b0ffff, 0x00ff0534, 0xff9a1914, 0x0080f7ff, 0x830e00ff, 0x19ec2b09, 0xffff8b9a, 0x08cccce8, 0x48181cfb, 0x7b21177b, 0xf6571806, 0x9266180c, + 0xe0e71809, 0xfc58180f, 0x1836840d, 0x18083ce7, 0x200a6e61, 0x226983f7, 0x82331700, 0x140e27a3, 0x1300ff7b, 0x978266e6, 0x08220983, 0xad830080, + 0x14825420, 0xcc4c4f22, 0x0b2fad82, 0x00ffb95e, 0xffcecc1f, 0xd7231e00, 0x821500ff, 0x21002fc7, 0x088bcdcc, 0x4b8b068b, 0xf9ffff15, 0xbe82cd4c, + 0x4082f920, 0xb3fbff28, 0xfdffff33, 0x1482cdcc, 0x0833b325, 0x83ecffff, 0x99ca2214, 0x2345829a, 0x069999d0, 0x68291083, 0x663500ff, 0xffff0566, + 0x221b82fc, 0x824c0600, 0xccfa252b, 0x0400ffcc, 0xf9270983, 0x088bce4c, 0x8473ffff, 0x33c6252b, 0x153cfb33, 0x410b7541, 0x8b200aa5, 0xcc231783, + 0x82f5ffff, 0x23168336, 0xb3f2ffff, 0x2105d341, 0x8d8200c0, 0x0040f522, 0x5d181b83, 0x00200efa, 0x0edb2b19, 0x1894f721, 0x180f63ea, 0x850f2c5e, + 0x83f5205a, 0x820d20f2, 0x9a2d191b, 0x5599180d, 0xa7fe2321, 0x5e186c07, 0x5e2108da, 0x13a618fa, 0x82332008, 0x5e092bbe, 0xf6ffffb8, 0xbb0848a1, + 0x1885055b, 0xbb820d83, 0x82ccf021, 0x251882d7, 0x80f7ffff, 0x5d180800, 0x472513a8, 0x330a00ff, 0x281a8232, 0xffbeffcf, 0x48212f00, 0x21258205, + 0x6018c5a0, 0x3b200e74, 0x08746018, 0xf88f0124, 0x65188b94, 0x78180a62, 0x82820d89, 0x8d844f84, 0xf5227f87, 0x0f84cecc, 0xff5b0826, 0xb8ded0ff, + 0x098d7818, 0xe0181682, 0xbb342965, 0xff0e05bb, 0xcdccbe00, 0x80aa00ff, 0xff8c1500, 0xcc4c0300, 0x19260482, 0x0200ff99, 0x09823433, 0x8b008029, + 0x7300ff08, 0x85063433, 0x2c05820c, 0xffff9a19, 0x8cccccfd, 0xb3fcffff, 0x271c8234, 0xff66e60c, 0x0080d5ff, 0x62228382, 0x278266e6, 0x4f830d20, + 0x10842a20, 0x3333d128, 0x8095ffff, 0xfb181500, 0xf5790842, 0xfd611808, 0x41f52011, 0xff210fdd, 0xfb6118f5, 0x3c5f180d, 0x74f72216, 0x2e9a478b, + 0xbd188d89, 0x3d42074a, 0xe25e1810, 0x24f7240a, 0x181514f7, 0x25199255, 0x94fb064b, 0x5e184b06, 0xba180a13, 0xf7220c95, 0xb9180754, 0xfb222d53, + 0x7119fb14, 0x15440de1, 0x83f3200a, 0xcc14264b, 0xf4ffffcc, 0x30b982b3, 0xff9a1912, 0x9819efff, 0xb30900ff, 0xffff0834, 0x2c0f82eb, 0x32b34000, + 0xf8ffff05, 0x00ff0080, 0x210f8217, 0x0983eaff, 0x82990f21, 0xb3e72329, 0x25828b34, 0xcccc8c25, 0x83ffff06, 0x84ff200c, 0x05cf4d1c, 0xff213083, + 0x05077ae8, 0x0082ff20, 0xce4cbf22, 0xef264682, 0xffff3333, 0x70844cf6, 0xed230982, 0x828b66e6, 0x34332366, 0x08452308, 0xe5b11807, 0x09cb190f, + 0x07ab2316, 0xec1854f7, 0x348209e7, 0xf1205282, 0x1120c383, 0x8b289483, 0x00ff0e06, 0xf89a194f, 0x0959b218, 0xb1821d20, 0xa61c0028, 0x2200ff52, + 0xb6826766, 0x3324002e, 0x00ff8b33, 0xffcdcc1b, 0xae59e3ff, 0xdc238682, 0x850866a6, 0xffff2206, 0x21a783e4, 0xe48259e3, 0xcdccdb22, 0xff232d82, + 0x829999dd, 0x66e2231b, 0x4482ff66, 0x002db482, 0x089a5923, 0x00ff078b, 0xfc67e618, 0x1f5b1854, 0x087a180e, 0x80b3280a, 0xffff0700, 0x820a17f3, + 0x008022e6, 0x37fc8205, 0xff7c7b94, 0x713decff, 0x80fbffff, 0xf1ffff00, 0x00ffcd0c, 0x08666609, 0x0a210a82, 0x820a8465, 0xe5812619, 0xcc1300ff, + 0x080e82ce, 0xff3d6a21, 0xcccc0f00, 0x3300ff08, 0x00ff50ad, 0x05343351, 0x911100ff, 0x00ffa7ec, 0xffe2ba1e, 0x82e61000, 0xe6202192, 0x0c24d284, + 0xac066666, 0x1e20d482, 0xff23eb82, 0x829a19ef, 0x99992228, 0x263a836f, 0xffff34b3, 0x82ccccae, 0x236a823a, 0x33f0ffff, 0x7e840f82, 0x3233ec22, + 0xf6228e82, 0x7f839a99, 0xff203182, 0x9e820a82, 0x0021fe82, 0x219e8304, 0x1a8499f6, 0x1a82f320, 0x84140021, 0x184c20c0, 0x200aa878, 0x3c5b18f1, + 0x14f72424, 0x63067b07, 0xfd18057d, 0x8b2c13fe, 0xf8dcf707, 0xffff1584, 0x0734b38b, 0xbc83f182, 0x7b82fa20, 0x6606002e, 0xf5ffff66, 0xff8b9899, + 0x3433f4ff, 0x9220a082, 0x9b282082, 0x4c0500ff, 0x07c305cc, 0x0825e782, 0x00ffcdcc, 0x82cb8207, 0xff332704, 0xcccc0800, 0xb918088b, 0x30790d31, + 0xffff220a, 0x20b985ab, 0x21cb82f9, 0x6583fbff, 0x82e6f921, 0x82f92060, 0xfdff236a, 0x5f8266e6, 0x0f83ca20, 0xce4cee29, 0xe5ffff05, 0x1807cc4c, + 0x600de2b2, 0x7b200a13, 0x2b17e064, 0xffa2065f, 0x66e6a3ff, 0x0200ff05, 0xf5206083, 0xf8255083, 0xffffcc4c, 0x82a582f6, 0x8b9a21cb, 0xc4226682, + 0x235c0080, 0x0aea540c, 0x4707eb21, 0xf72118f8, 0x22758224, 0x19b31100, 0x2011933e, 0x2c1883ab, 0xffcccc0b, 0x66660600, 0x660a00ff, 0x05454168, + 0x80050027, 0x00ff0800, 0x20ca8264, 0x2ab418ff, 0x0700210a, 0x210c695e, 0x434104d6, 0xfc292107, 0x79064341, 0xff240d73, 0x8b04d6f8, 0x29294082, + 0x078b08fc, 0x00ffef0e, 0x1358435f, 0x58437882, 0x439a2013, 0xff343458, 0x66e6f8ff, 0xdb1534fc, 0xeeffff07, 0xff063333, 0x7b14f5ff, 0xf8224982, + 0xdf823d4a, 0xff34b326, 0x33730300, 0x34056d4a, 0x231f00ff, 0x5d00ffd7, 0xff056666, 0x0a57e3ff, 0x33daffff, 0x310a8234, 0xffeb51f5, 0x66e6f1ff, + 0xeeebffff, 0xfdffff14, 0x0e823233, 0x8485eb21, 0x8208203e, 0x86ea200a, 0xfdff2849, 0x00ff713d, 0x82981914, 0x91ad3319, 0x00ff0899, 0xffa2e53a, + 0x9a994e00, 0x1600ff05, 0xa878a470, 0x23002705, 0x00ff5d0f, 0xe5826611, 0x9a192523, 0x2425828b, 0x8b333325, 0x219d82ae, 0x26829a99, 0x82676621, + 0xcc4c217b, 0x3a201682, 0xb1207183, 0x00248c83, 0x7d34b30a, 0xeb227886, 0x8c8668e6, 0x2582f520, 0x06821582, 0x15829882, 0xcc020023, 0x26dd82ce, + 0x00ffcc4c, 0x829a190e, 0x84e32098, 0x32b32163, 0x1e267d82, 0xffff3433, 0xcd82b3a2, 0x4b040021, 0xff2306fd, 0x864cf8ff, 0xf5ff242f, 0x828b9919, + 0x33ee2430, 0x183b0633, 0x222ece5e, 0xb07b07db, 0x068b2633, 0x34f8dcf7, 0xf5c31815, 0x34b32608, 0xa61c00ff, 0x9e601866, 0x41592014, 0xa7790ff6, + 0x9a592105, 0x14fa6018, 0x4f45a620, 0xfbc32309, 0xf71815d4, 0xff212fb7, 0x06644500, 0x5e821920, 0x0080eb2e, 0xf6ffff05, 0xff7c9a99, 0x3233ecff, + 0x21066445, 0xac8233f0, 0x20066445, 0x82b282e6, 0x4519850a, 0x66200664, 0x64451382, 0x45d68306, 0x992c0664, 0x00ffa79a, 0xff32b31e, 0xcccc1100, + 0x2505e74b, 0x0c00ff08, 0x64456866, 0xff982306, 0x5883eeff, 0x9c991122, 0x20056445, 0x09644530, 0x64456820, 0x45368219, 0x94820664, 0x28066445, + 0xff089a9c, 0x9819f3ff, 0x146445ff, 0x60193420, 0xcc2108d0, 0x0e64188b, 0x09174c0d, 0x7b07eb30, 0xff0e058b, 0x9a997c01, 0x665200ff, 0x4a841566, + 0x00213885, 0x2af4820e, 0x9a99e7ff, 0xe4ffff8b, 0x5608cc4c, 0x082a3015, 0x00ff6666, 0xffcc4c01, 0xf0830800, 0x68660226, 0x990700ff, 0x6e20b383, + 0x7f261983, 0xff056666, 0x644ef5ff, 0xf5682409, 0x82fdffff, 0xf3ff232e, 0xb1833dca, 0x3719d320, 0x7f510bc1, 0xff8b2307, 0x4d832c00, 0xecd12322, + 0x22068152, 0x82152e2c, 0x1500232d, 0x1b8267e6, 0xcdcc1323, 0x05e07eff, 0x00800e22, 0x3224c783, 0xb700ff08, 0x00241482, 0x057c9449, 0x2b228e86, + 0x3b823c0a, 0xffce4c29, 0xe27a2200, 0x502b00ff, 0x5682055f, 0x23244082, 0xffffcccc, 0x0969f518, 0xda2af482, 0xffff9a19, 0xff34b3e5, 0x9c83e0ff, + 0x32b3dc22, 0xb3256182, 0xffff0834, 0x238882da, 0xcc4c30ff, 0x1f20c682, 0x0033c682, 0x15676685, 0x999100ff, 0x80ffff99, 0x90059999, 0x830200ff, + 0x82052064, 0x01002626, 0x00ff66e6, 0x23938205, 0xcc4c0100, 0x25209382, 0x00236782, 0x8234b3cf, 0xccfb213b, 0x02208982, 0xff260f82, 0xff3233fc, + 0x2e820300, 0x66fcff22, 0x03222e82, 0x65820080, 0x43824720, 0x66b6ff23, 0x20bd8266, 0x205a8300, 0x214482f8, 0xd282feff, 0x4df8ff21, 0x192e0948, + 0x078b089a, 0xff30fb0e, 0x00801a01, 0x868214f8, 0x00802523, 0xbb741806, 0x085f430d, 0x18d4fb21, 0x1818d85f, 0x2018c7ba, 0x183383f7, 0x2114aaf1, + 0x6a8500ff, 0x9a190d22, 0x4a210a82, 0x2074823e, 0x28098299, 0xffc2b51a, 0xcdcc2900, 0x19ec828b, 0x21098f00, 0x2083e5ff, 0xff232a83, 0x82c2b5da, + 0x80a523dd, 0xad824b00, 0x09929c18, 0x280a684a, 0x1100ff8b, 0xffff84ab, 0x27e782f1, 0x7c540e00, 0x4ceeffff, 0x06844f83, 0x08280319, 0x828b8421, + 0x7c542217, 0x22068308, 0x4affcc4c, 0xff29100a, 0xff6666a9, 0x008099ff, 0x05bd4315, 0x80f3ff26, 0x0600ff00, 0xff21a382, 0x202f83f2, 0x2209830b, + 0x820080fb, 0x660d22a7, 0x82238267, 0x0d00210f, 0x06207283, 0x04202883, 0x00211382, 0x201e840c, 0x05be4100, 0xff05cd2c, 0x99190100, 0x330300ff, + 0x3d528e33, 0x03002105, 0x26051e4a, 0x06cc4c3a, 0x820800ff, 0x266182a5, 0xffffcdcc, 0x823333f9, 0xb3f72297, 0x209e8333, 0x243f82fa, 0x9a19fdff, + 0x82648286, 0xfdff2e79, 0xff08ce4c, 0x34b3d3ff, 0x99e6ffff, 0x062f4b98, 0x83fbff21, 0x83fb200f, 0x19f822b3, 0x213c839a, 0x25826666, 0x8648f220, + 0x18f22005, 0x221204f9, 0x830d00ff, 0x0a002128, 0x0a20b383, 0xff226383, 0x1484cd4c, 0x2127d282, 0x00ff3333, 0x82008012, 0x991321b3, 0x0b32b382, + 0x00ff3233, 0xff9a190c, 0x68e61400, 0x1600ff8b, 0x9a8232b3, 0x83220021, 0x83e320ac, 0x821c2040, 0xddff213b, 0x7482b682, 0x34b3c528, 0xe8ffff06, + 0x8682cc4c, 0x67e6ea31, 0x19f1ffff, 0xffff839a, 0x089999e9, 0x82ffffff, 0xfeff234e, 0x5982cdcc, 0x9a995628, 0x8066ffff, 0xa1411500, 0x079a4105, + 0x0fde7318, 0x20109a41, 0x18f64100, 0x7118e682, 0x548508fb, 0xaf0e082f, 0x19df00ff, 0x1554f89a, 0x802700ff, 0x22bb8200, 0x82cc4c21, 0x142e2b8c, + 0x4c0f00ff, 0xdfffffce, 0xf082b81e, 0x00800e27, 0xa10e00ff, 0x2be08248, 0x00ff9819, 0xffec1109, 0x34331600, 0x0f0a5e18, 0xff1e8524, 0x3f830800, + 0xe27adb22, 0x01223582, 0x2d439a99, 0x4f6b180e, 0xb8c61808, 0xfeff2316, 0x338219bf, 0x8cddff23, 0x232182cd, 0xff3373e2, 0x0ae7ca18, 0x23209c82, + 0x00235c82, 0x48cd8c1d, 0x2224060a, 0x088b3373, 0x07e2ad18, 0x01002b28, 0xfa2a00ff, 0x9582c0e2, 0x7a7dff2c, 0x8bfeffe1, 0xff1534b3, 0xcb82f9ff, + 0x99f4ff2c, 0xf1ffff98, 0xffff8f42, 0xd5824cfc, 0xca83f420, 0xcccc062c, 0xf4ffff08, 0x00ffd7a3, 0x1482cc06, 0x5c4ffc22, 0xcc21e482, 0x200e82cc, + 0x26df82d1, 0x08cc4c0b, 0x8205dbbb, 0xaec7350d, 0x660b00ff, 0x0d00ff68, 0x00ff67e6, 0xff32b303, 0x34330c00, 0x33215982, 0x22e58234, 0x8366660b, + 0x2714820a, 0xff33b303, 0x9a19f2ff, 0xff241984, 0xceccf3ff, 0xcf2f5f82, 0x053be1fa, 0xb87701ff, 0x7000ff50, 0x851566e6, 0xf9ff224a, 0x20308433, + 0x20308f32, 0x842c825b, 0x83b2861c, 0x21b28567, 0x8a8234b3, 0xcc82b285, 0xcc82b286, 0x840e0021, 0x890483b2, 0x87cf82b2, 0x886620b2, 0x206c82b2, + 0x24b282f9, 0xfeff078b, 0x243882f8, 0x9a198fff, 0x82ab8315, 0x051f41b5, 0x09823320, 0x33206c86, 0x9a206c89, 0xce250a83, 0x4cfcffff, 0x071f41cd, + 0x17826c8e, 0x82101f41, 0x836c834a, 0x1a1f41ee, 0x0023ee83, 0x4132b397, 0x00288a1b, 0xff34b31b, 0x666643ff, 0x40555018, 0x028b9310, 0xf8ef2407, + 0x6e34f824, 0xfb2117ba, 0x07e36394, 0x11bd6118, 0x34b37a2d, 0x0a00ff06, 0x056b9899, 0x194a00ff, 0x2011cb07, 0x059e4734, 0x2007a547, 0x348518ff, + 0x2b60180e, 0xff8b2419, 0x18b31100, 0x83114d7d, 0x84332064, 0xab9a2671, 0x7affff05, 0x210c82b3, 0xd118e5ff, 0xb5831492, 0x181a0021, 0x380fce96, + 0xf7088b8f, 0xe4fb06f4, 0x74fb154b, 0x06d4f707, 0xfb0774f7, 0xa4f806d4, 0x18fd98cb, 0x201878d2, 0x19a1184b, 0x83f72017, 0xded21832, 0x06cb2314, + 0x9f184b5b, 0x461817fb, 0x5f4f16bd, 0x0afe4f0d, 0x19ff8b21, 0x2414a514, 0x2b8b066b, 0x1834b115, 0x180e8a44, 0x96079d43, 0xfb9b2294, 0x0ceb7564, + 0x200ebd49, 0x06844cb3, 0x21056a53, 0x894c4cee, 0x9971180e, 0x051e420a, 0x2885ff20, 0x23099353, 0x54f72f0e, 0x0ba05818, 0x8f184c20, 0x82180cb1, + 0x6e180ff7, 0x61180831, 0x4b21189d, 0x0ba24806, 0xcb2bad8a, 0xcaffff07, 0xffff9a19, 0x8266e691, 0x4c0f26d1, 0x00ff93cc, 0x20bf8312, 0x350482fa, + 0x33b30900, 0xb3f0ffff, 0xffab0832, 0x9a99c8ff, 0x0800ff05, 0x1183cdcc, 0xfa26e082, 0xffffcccc, 0x04824ced, 0x2a82f020, 0x4cf6ff24, 0x248308ce, + 0x056b9922, 0x37822083, 0x3233f72c, 0x66ecffff, 0x0500ff67, 0xc9543433, 0x0f002305, 0x2582cc4c, 0x29dce027, 0x663700ff, 0x23298267, 0xfff628f7, + 0xdf821582, 0x00400527, 0x991300ff, 0x820e8699, 0x8208207a, 0x156e2224, 0x227582ab, 0x8266e6d5, 0x9a1921c0, 0x220c7441, 0x18b3f1ff, 0x9e076c53, + 0xb76d18f8, 0x52cb2012, 0xcb241720, 0x34fbcb06, 0xc643678f, 0x2067b807, 0x05e24134, 0x4c0e0030, 0x1100ffcc, 0x088b34b3, 0x94fb06cb, 0xe643156b, + 0x31b71808, 0x0fe1410d, 0x9e08524a, 0x25631880, 0xab4b2114, 0x420c694c, 0x63180a7d, 0x4b201873, 0x0e3a6318, 0x4108a455, 0x98440636, 0x06cb2611, + 0x64f8ef0e, 0x9e6c18f8, 0x6834190c, 0xff8b280b, 0x66e6f0ff, 0x83f8ffff, 0xccf12504, 0xf3ffffce, 0xf6230983, 0x490866e6, 0xf5270660, 0xff059a99, + 0x8266bdff, 0x99f93624, 0xc8ffff98, 0xffff3433, 0xff6766d4, 0x9a19e8ff, 0x33c4ffff, 0x23298233, 0x609a99c6, 0xf4202582, 0xf7222083, 0x54820080, + 0x82676621, 0x99f4275a, 0x0800ff9a, 0x21820080, 0x40822620, 0x33a30023, 0x25258234, 0xffbae9f3, 0x3c830900, 0x12e3f82e, 0x330e00ff, 0x00ff8b32, + 0x089a190f, 0x25166b78, 0xff0634f8, 0x3f8256ff, 0xccecfe27, 0x00ff15cc, 0x230a821a, 0xcecc1300, 0xff204a82, 0xfa206b83, 0xff210483, 0x829682b3, + 0x22758209, 0x826666fa, 0xd5ff214a, 0x56831682, 0xd8ffff22, 0x0021d282, 0x27708319, 0x089a99e1, 0xccd7feff, 0x0bae7618, 0x240d9a58, 0x00ff0764, + 0x33b682d9, 0xcccc5cff, 0x1600ff05, 0xffffcccc, 0xff68e6ee, 0x34331f00, 0x0f839f82, 0x19110027, 0x01ff0898, 0x23258259, 0x34330300, 0x5e6e4c18, + 0xae7cb818, 0xffaf2a08, 0x9a99f301, 0xaeb401ff, 0x00ff1514, 0xff32b306, 0xa8b90a00, 0xcc0d00ff, 0x0300ffcc, 0x00ffc8b8, 0xff34330b, 0x1a0ffaff, + 0x210a8208, 0x0a839c19, 0x00ff5c2a, 0xff30b304, 0x1a6ff2ff, 0xcc320e82, 0xf4ffffd0, 0xff08e27a, 0x64e676ff, 0x3dcffeff, 0xd64e0570, 0xfdff2105, + 0x22066e6c, 0x82fdffff, 0x05286162, 0x9899fd22, 0x61274882, 0x00ff9a19, 0x829a9936, 0x800a2a29, 0x0500ff00, 0x00ff66e6, 0x2668830d, 0xffce4cfd, + 0x82330700, 0x66f6225d, 0x21298266, 0x5e824c07, 0x0080f623, 0x826e828a, 0xf6ff2129, 0xf8207883, 0xff2b1a83, 0x34cecca9, 0xb8ffff05, 0x82069a99, + 0x2541831c, 0xff666624, 0x0482dcff, 0x821b0021, 0xd6ff2670, 0x088b3433, 0x210682ff, 0x16838b33, 0xffff6723, 0x211b82e4, 0x2a82f2ff, 0x99dbff23, + 0x2d1a829a, 0x06cd4cb0, 0x8ab4ffff, 0x3300ff3d, 0x4c826666, 0x8240f621, 0x8307208d, 0xa3fc233c, 0x988297d7, 0xff333324, 0x2b830a00, 0x35050023, + 0x830a82c3, 0x830c20d2, 0x33052c14, 0x0b00ff32, 0xffffec51, 0x820080fc, 0x3d6125a8, 0xe1ffff70, 0x0225d284, 0x00ff67e6, 0x21658203, 0x29830300, + 0x82cc0321, 0x830985d2, 0xc1ff22fc, 0x2c5382b3, 0x0567e667, 0x00ff9585, 0x989a1902, 0x05d95294, 0x99240684, 0x330d00ff, 0x0021af82, 0x23448208, + 0xcd4cf8ff, 0x66205a82, 0xa827b583, 0xff053333, 0x82800100, 0x8200209f, 0x2009870f, 0x82138968, 0x820d2029, 0x8e0023b9, 0x298332b3, 0x0c219f83, + 0x207a824c, 0x2304850a, 0x0c00ffcc, 0x8305ab52, 0x82ca8206, 0xf5ff2116, 0x0120cf83, 0xff232a82, 0x8332b3f3, 0x235f8240, 0x9a1972ff, 0xae274082, + 0x01ff3433, 0x82ae4718, 0x822c200a, 0x4cfe2370, 0xcf455238, 0xccf0280d, 0xffff8bce, 0x183233ef, 0x1817bcae, 0x200fb998, 0x247e820d, 0x991200ff, + 0x2330829a, 0xcecc1000, 0x08dbaf18, 0x00ff3231, 0x8b85ab11, 0x0694f808, 0x01ff94fb, 0x64c81abf, 0x41210e43, 0x25698262, 0x08d6a3f3, 0x0882075b, + 0x9ad9f122, 0x1805bf56, 0x21079672, 0x7c198b34, 0x00240cee, 0x8b9ad909, 0x26235c82, 0x82bb0866, 0x0c00232f, 0xee822a5c, 0x0a2fe983, 0x00ff9ebe, + 0x8bcc4c0d, 0x0e078b08, 0x18f4f7af, 0x301a2a74, 0x9a194b00, 0x1400ff06, 0x968b9a99, 0xb5e7ffff, 0x068042c2, 0x727df022, 0xea226c82, 0x1482cccc, + 0x05cccc25, 0x83affeff, 0xebff2927, 0x00ffe1ba, 0x05343318, 0x6b2b2682, 0x0f00ff85, 0x00ff8e82, 0x821f050b, 0x3e4a2114, 0xa1214682, 0x24a38248, + 0x34334a00, 0x21998206, 0x8318ab11, 0x802313dd, 0x828b66e6, 0x19ff274f, 0x1514fb9a, 0x0e8201ff, 0x11227f82, 0x308234b3, 0x5c4c0e21, 0xe748056b, + 0x207f8205, 0x09d05184, 0xccfbff2e, 0xffff7ecc, 0xffce4cf8, 0x9819f5ff, 0xcc271c82, 0xffff9a99, 0x829a19b8, 0x19fe2a8b, 0xfeffff98, 0xffff66e6, + 0x211f83fd, 0x2482ccfe, 0x13826082, 0x82cccc21, 0x80f02229, 0x83348200, 0x66ed2119, 0xf8232382, 0x827a9899, 0x3433211a, 0xef261a82, 0xff060080, + 0x3a82eeff, 0x83010021, 0x19ee25ec, 0x0800ff9a, 0xff240482, 0x953233f0, 0x19b6a218, 0x2283f120, 0x6783f520, 0x5284ee20, 0xff323326, 0xcdccedff, + 0x192a5682, 0xffff089a, 0x066666ef, 0x5285ff7a, 0x6766ed31, 0x660700ff, 0xf0ffff68, 0x00ff9999, 0x8232b30a, 0x33fe2220, 0x831e8234, 0x19fe2192, + 0x01201482, 0x5382c084, 0x84010021, 0x9ecc273f, 0x4700ffb8, 0xdb8266e6, 0x0040f822, 0xe6273482, 0xfbffff68, 0x5f987bd4, 0x0825050f, 0x807b00ff, + 0x05944800, 0x31115d47, 0x19ffffff, 0xfbab0699, 0x01ff1534, 0x0666e640, 0x875107eb, 0x072b2605, 0xe60001ff, 0x20178366, 0x6ca81800, 0x090f103d, + 0xd2100702, 0x181b0161, 0x41c7e869, 0xf722bae3, 0xc318fbd4, 0x3b285d84, 0xe61000ff, 0x14fb1566, 0x190c7560, 0x200d43ad, 0x05ea49f6, 0x078e7218, + 0xcccc0825, 0x82f7088b, 0x18002030, 0x20091441, 0xe3d31800, 0xcbd51020, 0x69431c01, 0xf74b225e, 0x09e77c1c, 0x0d755518, 0xc441ff20, 0x8f74180b, + 0x66062e0b, 0xff8b0766, 0xce4c0500, 0x4c0400ff, 0x820486cc, 0x088b2c0e, 0x802800ff, 0x00ff0600, 0x1932b307, 0x260a7904, 0xf8ffff8b, 0x8208ce4c, + 0xccfa2a06, 0xfdffffcc, 0xffff9a19, 0x643d82fb, 0xfd2f05ca, 0x6b080080, 0x33efffff, 0xffff0532, 0x8232b3fa, 0x22888320, 0x8234b3fc, 0x9a99210e, + 0x19273583, 0xffff0898, 0x193433f1, 0x3e303f0d, 0x079a1905, 0x801700ff, 0x0c00ff00, 0xff05cc4c, 0x9a190f00, 0x0900ff93, 0x00ff6666, 0x82008010, + 0x331022a3, 0x21988234, 0xc7821900, 0x83ebff21, 0x99142716, 0xe6ffff9a, 0xcc8234b3, 0x82d7ff21, 0x187420cc, 0x24072bb1, 0x8b6666ed, 0x23878274, + 0x079a99f9, 0x243cb242, 0xffff075c, 0x22e283a3, 0x82cdccda, 0x83ea20f2, 0x82f720f2, 0x058e59a2, 0x6766eb22, 0xe9207182, 0x0682f282, 0x1682c720, + 0xe6120026, 0xa4ffff66, 0x4b2a0983, 0xffffce4c, 0x08ceccc3, 0x976dff82, 0x83f52005, 0x83fd203b, 0x19f522bb, 0x85d8189a, 0x7dff202d, 0x9e2005aa, + 0x35e3aa7d, 0xfff1f7ef, 0x90828201, 0x0700ff15, 0x00ff66e6, 0xff48e109, 0x09830800, 0x68d90a21, 0x0e8205b6, 0x0820c527, 0x990500ff, 0x2104829a, + 0x0f82b81e, 0xffcccc26, 0xe0faffff, 0xff231385, 0x822adcfa, 0xb3182a1e, 0xe9ffff34, 0x00ffec51, 0x2d3d8214, 0x1e05e2ff, 0xb30e00ff, 0xe3ffff32, + 0x1e82707d, 0x9a990e23, 0x825d826f, 0xe3ff2a43, 0xff8bce4c, 0xccccebff, 0x25068208, 0xff3433a8, 0x3b83b8ff, 0x3683b520, 0xcc4ca729, 0xffff088b, + 0x82cd4ca6, 0xb3b92b1b, 0x4a00ff33, 0xff8b3433, 0x8a5d5700, 0x661a2105, 0x0c20a282, 0x20201683, 0x00213782, 0x2d098313, 0x08e2fa1f, 0x2000ff9f, + 0x00ff285c, 0xa382191c, 0xe2ba212c, 0x4c2100ff, 0x1d00ffcc, 0xb8872cb2, 0x78fe0422, 0x6783e182, 0x64fbff25, 0x820600ff, 0xfaff2348, 0x1e8228fc, + 0xcd831320, 0x1839ee2f, 0x801200ff, 0xecffff00, 0x00ff5ccf, 0x085d8211, 0x40ebff2e, 0x078b0800, 0x8dffffb4, 0x8915d663, 0x888f898f, 0x6167088f, + 0x518b8b05, 0x089087d5, 0x767c666d, 0x8b08738b, 0xff6eaf5a, 0x9a192c00, 0x0035b682, 0x8b66e612, 0x959a909b, 0x93a0a908, 0x08ac79b5, 0x03fbfafb, + 0x4ebd8215, 0xab21130d, 0x0b886906, 0x6e4eff20, 0xff332513, 0x9a99f2ff, 0x2508d95f, 0x079a19bf, 0x368254f8, 0x66e64023, 0x0ccc6e07, 0x83127a4e, + 0x330f22fe, 0x22638332, 0x85088b34, 0x086b4d6c, 0xff226c89, 0x55829fff, 0xd8182585, 0x475410dc, 0xd4fc2118, 0x2230fa53, 0x826000ff, 0xb4f724b5, + 0x553fffff, 0x16570ea1, 0x14f7224f, 0x2cd918cb, 0x0e60590f, 0x8b0f4857, 0x218da1fe, 0x946194fb, 0x129d5f1c, 0x3f2df95f, 0x01ffaf0e, 0xffcccc60, + 0xd8635f01, 0x3600ff15, 0xffff68e6, 0xff8e02fc, 0x98992e00, 0x2300ff74, 0xe53b6083, 0xff083433, 0x34332700, 0x99e2ffff, 0x1c00ff9a, 0xffff9819, + 0xff32b3dc, 0x82660e00, 0x84e7202e, 0xb305271e, 0xff8b8134, 0x4b82f3ff, 0x4cfaff29, 0xff0881cc, 0x8299f1ff, 0x221d8227, 0x83e3ffff, 0x21318356, + 0x1f83d8ff, 0x2c194582, 0xe52007c7, 0xd1295583, 0xff746866, 0x9819c9ff, 0x20168287, 0x295383b2, 0x05ccccc5, 0x66f5ffff, 0x46838366, 0xffff992b, + 0xff0080ff, 0x33b3f4ff, 0x28218292, 0xffcdccf4, 0x9a190700, 0x826882ff, 0x4c0d2809, 0x0200ffcc, 0x82989a99, 0xb30927a4, 0x3000ff33, 0x3c829a99, + 0xcdcceb2d, 0xefffff94, 0x00ff6666, 0x8266e60a, 0x22ba8309, 0x829a990b, 0x82f12040, 0x0b00214c, 0xff200482, 0x0c200984, 0xff282382, 0xff9919f5, + 0x68660c00, 0xa2221e82, 0x8d8285eb, 0x8232b321, 0x7df32644, 0xf8ffff71, 0x23f982b3, 0x8d6626f0, 0xb7219182, 0x214e820a, 0x25823233, 0x6db6f522, + 0x1a820a83, 0xe9d7fd25, 0x820f00ff, 0x070023d8, 0x44829e2f, 0x00276383, 0xff73c82d, 0x83195000, 0x37d22289, 0x220a878d, 0x8462d0f8, 0x21b08220, + 0x34861728, 0x93490a22, 0x08204884, 0x48210582, 0x825e84f6, 0x9ad92119, 0x0c223482, 0x7e848f82, 0x5d221a82, 0x94867b14, 0x6720ce82, 0xff22aa84, + 0xc3820e00, 0xe282b482, 0xd2820984, 0x10202982, 0x0020ce82, 0xff22e882, 0xf2831000, 0x0024fc83, 0x94333314, 0xf627b382, 0x00ffcd4c, 0x82b89e30, + 0x83fd20d9, 0x020d3025, 0x0500ff90, 0x00ff33b3, 0xff1e450d, 0x82330b00, 0x11072209, 0x204482ec, 0x2229830b, 0x827a1407, 0x67662563, 0x68ffffff, + 0x4e829883, 0x0af8ff23, 0x321e823e, 0xff98994d, 0x3ecac5ff, 0x3f00ff05, 0xffff3433, 0x43289c80, 0x6c180f06, 0xcc200c75, 0x43104f5a, 0xdc181b06, + 0xef22125b, 0xa98234f7, 0x82008021, 0x19f52565, 0xfcffff9a, 0xff26be82, 0xff9919f6, 0x0e83feff, 0xcdccf423, 0x32df828b, 0x8be1faca, 0x05d5ffff, + 0xc08bb61e, 0x07b4f708, 0x73eeffff, 0x7b180a4d, 0x86200d6d, 0x54219282, 0x8204837b, 0xab1126e4, 0xf7088b85, 0x0d254554, 0x09f8b018, 0x6405d864, + 0x254509e8, 0x190a3a08, 0xff5a079a, 0x0080b0ff, 0xf6ffff05, 0xff7b3333, 0xcdccfaff, 0x99edffff, 0x2733829a, 0x08cc4ced, 0x1a01ff4b, 0xcb2ab682, + 0x4b07eb06, 0xf8072b06, 0xca59f734, 0x5eb1180f, 0x19658908, 0x220cb0a1, 0x8269ffff, 0x00ff2365, 0x1682b375, 0x32b34033, 0x0600ff05, 0xff8034b3, + 0x98990300, 0x80f3ffff, 0x23378200, 0x089a19f3, 0xd9200682, 0xe0342283, 0xffff68e6, 0xff66e6e0, 0x30b3d9ff, 0xfeff088b, 0x06ceccca, 0x34260c83, + 0x00ff6b8b, 0x9982191f, 0x82260021, 0xff8b2399, 0x25820c00, 0x80040023, 0x83098200, 0xb3062704, 0xff089633, 0xc1827400, 0x4cbf0023, 0x246882ce, + 0x0766e696, 0x96d018ff, 0x1800200a, 0x19136cb1, 0x2b0e7390, 0x8b66e6c0, 0x4b14fb05, 0x0734fb15, 0xfa269382, 0xffff9a19, 0x8e8266fe, 0x3333fa25, + 0x82fcffff, 0xfaff2872, 0xff0866e6, 0x8233cfff, 0xccb026d0, 0x3ff705cd, 0x240d8506, 0x33334f00, 0x21238505, 0x37870500, 0xcc050023, 0x20ab82cd, + 0x27338205, 0x4b0734f7, 0x30fb0e06, 0x20066d54, 0x22698208, 0x820800ff, 0xfcff29ba, 0xff91da4e, 0x8280f9ff, 0x0620bf82, 0xf9203983, 0x00211582, + 0x30098303, 0xff1e45f7, 0xcc4cffff, 0x23f7ffff, 0xffff08d8, 0x287682e3, 0x7a946cfe, 0xffff8805, 0x292083d6, 0xff3233dd, 0x9a99dfff, 0x1d828b61, + 0x67665923, 0x21178206, 0xba821f05, 0x852bdd25, 0x832000ff, 0x02fd25ba, 0x2900ff8f, 0xe327b584, 0x01ff6a2e, 0x82866b93, 0x5dff22a7, 0x267e82f4, + 0x00ff28dc, 0x82261403, 0xe2ba2609, 0x0d0600ff, 0x21048291, 0x87830080, 0x82cd0c21, 0x7e7f210a, 0x7d211982, 0x20238271, 0x262383b1, 0x088b48e1, + 0x828bd4f7, 0x3001353d, 0x57ffffa4, 0xff156666, 0xf6681300, 0x4cf6ffff, 0x1600ffce, 0x1327eb84, 0x00ff6766, 0x8232b309, 0xe6142544, 0x0a00ff66, + 0x1823cc83, 0x488b9a99, 0xf52006ef, 0x13205f84, 0x35872582, 0x1a82cc20, 0xa9821320, 0x18203586, 0x0024e382, 0x059a190c, 0x99268082, 0x5c00ff9a, + 0x71820080, 0x1ec50423, 0x21108506, 0x1083a3ff, 0x38180031, 0xf3ffff52, 0x0e0566e6, 0x94f730fb, 0x821590f7, 0x82de20f4, 0xe3ff2970, 0xffffcd4c, + 0xff9a19e5, 0x111c5319, 0x2306d553, 0x089a1921, 0x18207382, 0x00262d82, 0xff33b321, 0x72832d00, 0xa8831220, 0x66661722, 0x28068541, 0xe2ba0700, + 0x660b00ff, 0x20298266, 0x224d8306, 0x821e45f8, 0x2125831a, 0x9783e8ff, 0xff223983, 0xbd82ccd2, 0x82e7ff21, 0xf7eb2550, 0x00ff1558, 0x23bbd641, + 0xc4fb94fb, 0x1420c282, 0xf527ec83, 0x00ff66e6, 0x82cdcc17, 0x210f83fc, 0xe1820a00, 0x8700ff21, 0x821a830a, 0x200f84f7, 0x202a82ff, 0x831a8508, + 0x861a8b0a, 0x820c2035, 0x06002c50, 0xff050080, 0x00801100, 0x41e900ff, 0x10250ad0, 0xffff15ae, 0x251b8416, 0xff33f30c, 0x0a82f9ff, 0x00ff0e2a, + 0xff33b39f, 0x66266601, 0x00218e82, 0x2d168233, 0xffe2fafd, 0x3433ffff, 0xf0fdffff, 0x05828ba4, 0x1814ee21, 0x7308a88b, 0x4c2d0530, 0xdbffffcc, + 0x088bcccc, 0xd1feffff, 0x822283eb, 0x0000234e, 0x2c829a19, 0xffe1fa26, 0x32330000, 0xf8251a82, 0xffff707d, 0x201483f3, 0x211e82f9, 0x0983f2ff, + 0x66a6fb27, 0x66f1ffff, 0x331e8266, 0x7ac2f5fa, 0x2eeeffff, 0xf6ffff14, 0xffff6766, 0x90eb11ef, 0xef271682, 0x00ff5c0f, 0x82991905, 0x1d5a2115, + 0xcc21c482, 0x260e82cd, 0x00ffba09, 0x8267e610, 0x680625fa, 0x1500fff6, 0x0931d983, 0x00ffd723, 0xff666614, 0x717d0b00, 0xb31200ff, 0x233d8234, + 0x934861fc, 0x14218482, 0x071d427b, 0x6b820920, 0x6bff8b21, 0xdb670506, 0x23818205, 0x33732200, 0x0023bc82, 0x82cd4c0a, 0xe608211b, 0xf4827d82, + 0xfc223882, 0x63824661, 0x33b31222, 0x7a215482, 0x215e86e2, 0x63822609, 0x06227284, 0x1e826866, 0x92828882, 0x85420b21, 0xf6ff239c, 0xb086245b, + 0x0821ba82, 0x21c88290, 0xd2865c0f, 0xe282dc82, 0x9982e882, 0xff25f482, 0x68a6fbff, 0x050841ff, 0xc2f5f925, 0x83f3ffff, 0x7df835e6, 0x078b0870, + 0x00e600ff, 0x3400ff01, 0x9315c235, 0x9e0300ff, 0x0821f082, 0x227782e6, 0x821e0502, 0x008021ca, 0x2005ca74, 0x22ae8232, 0x18cecc1b, 0x200bb88f, + 0x276b828b, 0xff899a99, 0x9a19f7ff, 0x4c22f982, 0xa28283cc, 0x66660b22, 0x2205e060, 0x824c0800, 0x99eb2c2d, 0x0700ff9a, 0xffffcc4c, 0x840080ea, + 0x207883a2, 0x222483f6, 0x833333ee, 0x67e621a2, 0xef24a282, 0xff869a19, 0x2405eb6e, 0x86999909, 0x2012829c, 0x263983fb, 0x859a990e, 0x820d00ff, + 0xf8ff218e, 0x00243382, 0x0866e60c, 0xff227082, 0x0583cecc, 0xfd221683, 0xa08266e6, 0x18a5a118, 0xec110226, 0x190000ff, 0x02228482, 0x09825c0f, + 0xff323323, 0x82d88200, 0x83f3205f, 0x82072214, 0x05154190, 0x0a060026, 0xf1ffff3e, 0x04276383, 0x7a089859, 0x830500ff, 0x29a88310, 0xecd11100, + 0x1000ff90, 0xde82a4f0, 0x35830520, 0xff290a82, 0xcecc1100, 0xa40900ff, 0x831982dc, 0xf4fa2287, 0x2a1e82be, 0xff008015, 0x9899f9ff, 0x831300ff, + 0xd9f62209, 0x8209829a, 0xf4ff32c8, 0x8b081e85, 0xfeff058b, 0xff6626d4, 0x0c57c5fe, 0x20878315, 0x2191871f, 0xa586cd0c, 0xa06e0120, 0x33242205, + 0x083a7634, 0x820b5c6a, 0x212882ed, 0xfd83cccc, 0xffcdcc22, 0x24055574, 0x67e60c00, 0x053f77ff, 0x66e60d26, 0x0e00ff85, 0xfb257183, 0x9c089a99, + 0x28a28286, 0xffff9999, 0x863433ee, 0x20f4827a, 0x202983fa, 0x82c382ef, 0xff332211, 0x24de83ff, 0x9919efff, 0x201a8290, 0x41b082ea, 0xeb2005a9, + 0xbd413e82, 0x4ced2105, 0x0b249782, 0x83086666, 0x4c256a82, 0xf7ffffcc, 0x204c8219, 0x203f83fd, 0x051c7bf5, 0x180cd16a, 0x220a1da3, 0x82666609, + 0x82eb20e0, 0xe608218c, 0x03230982, 0x8293b89e, 0x82f42263, 0x060f418f, 0x29dcf622, 0x27062341, 0xff0a97f9, 0x00801500, 0xfa221e82, 0x4d4146f6, + 0x09002305, 0x6141e3a5, 0xf0102806, 0x0500ffa4, 0x82089a19, 0x15ee2219, 0x21158290, 0xb885ecd1, 0x0a050023, 0x23d3823e, 0x9a590400, 0x2506b941, + 0xffcd0c06, 0xd741f2ff, 0x82f32008, 0x8b8b2635, 0x8001ff05, 0x23ba828c, 0x159899da, 0xb3239282, 0x838d8334, 0x429a20c7, 0x5e4405bd, 0xff32230a, + 0x5e44e3ff, 0x8bce2105, 0xf7228c82, 0x22820080, 0x4d83f720, 0x66e60223, 0x823a8483, 0x82ec2016, 0xf4ff22d8, 0x22728299, 0x820080ec, 0x19b32048, + 0x2207391a, 0x4234b3f8, 0x32200ac8, 0x2006db4f, 0x25fd83fa, 0x0866e610, 0x11859c86, 0xcc110025, 0x50909ccc, 0xff220500, 0x4d820400, 0xe60d0024, + 0xe8489166, 0x80072206, 0x22448200, 0x82ceccff, 0x9a19246e, 0x848b8d8a, 0x188a1807, 0x05627808, 0xff34b32e, 0x66662200, 0x8b8e088b, 0xffffff8d, + 0x02206183, 0xff20a682, 0x57823682, 0x4c844282, 0x58825282, 0x0e246286, 0x90089a99, 0x7c828182, 0x93828686, 0x9c088624, 0xa084ffff, 0xcf830920, + 0x3233ee28, 0xefffff86, 0x81829a19, 0xff20cc82, 0x2005b767, 0x84e083f7, 0x34f485ea, 0x8b086666, 0xe6feff06, 0x00ff6866, 0x1568e684, 0xe7ffff8b, + 0x22ed8233, 0x8299190e, 0x27ce8331, 0xffcdcc14, 0x6866f5ff, 0x0b208b82, 0xf9200a83, 0x042da083, 0xffff33b3, 0x859a99f1, 0x33f4ffff, 0x22618232, + 0x8367e6f9, 0x8334200a, 0x22398215, 0x83cc4cfb, 0x9133210e, 0xdb201a82, 0x7b503582, 0x82e72005, 0x250027d6, 0xff8b34b3, 0x475e2b00, 0x831c2005, + 0x830a204c, 0x4c1a2804, 0x00ff9dcc, 0x4d66e613, 0x0b26076e, 0xff059a19, 0xca82f8ff, 0x80070026, 0x0500ff00, 0x0a220483, 0xf082ce4c, 0x8bcc4c22, + 0x3c238d82, 0x82060080, 0x844e8416, 0x8274828f, 0x4cfa22be, 0x234282cc, 0x070180c3, 0xf7210c82, 0x208c8299, 0x218082f4, 0x4118faff, 0x062008f2, + 0x9d657a82, 0x0f002305, 0x4018cd4c, 0xf42007ec, 0xff228482, 0xc58266fa, 0x28055165, 0x08ce4cf0, 0x00ff078b, 0x27418252, 0x66e65a00, 0x0600ff15, + 0x0b32be83, 0x00ffcccc, 0xff66660e, 0x34b30400, 0xcc0b00ff, 0x8b8285ce, 0x32332425, 0x82edffff, 0x18002162, 0xda204783, 0xff25a182, 0x6766d4ff, + 0x26838208, 0x809919e3, 0x82e5ffff, 0xeeff21c8, 0xff234182, 0x823433ec, 0x24de8231, 0xccf4ffff, 0x062f49cc, 0x63f9ff21, 0x1482085c, 0xf7ffff24, + 0xe3829a99, 0x83c3ff21, 0xfaff21e3, 0xfb214e84, 0x2079824c, 0x82178204, 0xcecc21f4, 0x82050041, 0x090021e3, 0x0b211783, 0x828c8233, 0x83a5821c, + 0x82318268, 0x820f2020, 0xefff2319, 0x6382cecc, 0xce4c0922, 0x1921ac82, 0x203b8298, 0x28048299, 0x8bce4c0e, 0xb30f00ff, 0x27a08233, 0xcdcc1800, + 0xccf1ffff, 0x15202082, 0xff21ec82, 0x613582eb, 0xff210535, 0x215583f4, 0xd0411906, 0x20f68306, 0x34f28491, 0x0e078b08, 0xb34801ff, 0x8b01ff34, + 0xf21552b8, 0x7abcffff, 0x2d6582e2, 0xffcccc11, 0x66e6f2ff, 0xcc0300ff, 0x0a8372cc, 0xffff6826, 0x083233ee, 0x0a821585, 0x15823420, 0x3333fc22, + 0xff241584, 0x99190d00, 0xa8201a82, 0x39269b83, 0xff059a19, 0xef8496ff, 0x9919f828, 0xf7ffff8b, 0x048367e6, 0x0a826620, 0x9a19f822, 0xff22a882, + 0x598266f6, 0x8e830820, 0xe482f920, 0x7a070021, 0x3f2805c4, 0xff069919, 0x01001000, 0x0d20d182, 0xb5857b82, 0x00800328, 0x4cf0ffff, 0x8b8208cc, + 0x77323322, 0xad820b82, 0x83efff21, 0x99eb2c15, 0xfb088b9a, 0xffff0604, 0x82ffffe4, 0xc5e62d5d, 0x0800ff1f, 0x9c766766, 0xd1ffff08, 0x00232182, + 0x82999926, 0xbaf7258c, 0xffffffe1, 0xf8219784, 0x26868426, 0x00ff00c0, 0x82cc4c07, 0x99092268, 0x2359829a, 0x072a1c5f, 0x08220c82, 0x178270bd, + 0x1c834020, 0xd9200484, 0xf7215f82, 0x2194828f, 0x3682e616, 0x83150021, 0xcff82f94, 0x1100ff5c, 0xffffcecc, 0x08f6e8f2, 0x5f828b8b, 0x99994e32, + 0x9468feff, 0xffff157a, 0xff52f878, 0x00806300, 0xee2d1582, 0x00ff9338, 0xff9a190d, 0x3934fcff, 0x210a82a4, 0x3884a61b, 0x0d226e82, 0x0a838320, + 0x00ffcc25, 0x828f0219, 0x82cc20d7, 0xcc112709, 0xf2ffffcd, 0x1e8268e6, 0xf5a8772c, 0xcca7ffff, 0x00ff05cc, 0xa8189978, 0x33210a6c, 0x189d8234, + 0x8308558c, 0x34b324af, 0x83f8ffff, 0x69cc823d, 0xf98205f4, 0xcdccb12b, 0xff8b7b06, 0x3333f1ff, 0x05c050ff, 0x6666fd27, 0xb30f00ff, 0x231c8234, + 0x9fcdccfc, 0x20069468, 0x28158311, 0x8b008013, 0x0614f708, 0x204e82a6, 0x24ac831a, 0xa034b3f6, 0x2684827a, 0xff00802e, 0x834cdaff, 0x66172284, + 0x23e68266, 0x34b30800, 0x69842482, 0x0a83f820, 0x4cf7ff26, 0x072b08cc, 0x5006556a, 0x8c8305eb, 0x8b2b1783, 0x06affb08, 0x19e9ffff, 0x84768b9a, + 0xffff22b4, 0x2c8e83ee, 0x0898190d, 0xef0e078b, 0x34f8c4f7, 0x18b54e15, 0xa218ee20, 0x7a4f0a5d, 0xcd4c2111, 0x18077a4f, 0x4f1137a4, 0xfb220811, + 0x80185b24, 0x716a09f6, 0x0ccf540d, 0x6f6af120, 0x18a94f08, 0x5b208d95, 0x20178768, 0x2c5a1893, 0x0afd7f0c, 0x82077b21, 0x82fe2062, 0xffff258b, + 0xffffcdcc, 0xb3210985, 0x35098333, 0x00ff08cc, 0xffcccc38, 0x0080e7ff, 0xb32700ff, 0xc7ffff34, 0x2e826666, 0x3433be23, 0x27068208, 0xff9a99a7, + 0x6666b8ff, 0x0e820486, 0xff088b23, 0x041c19ff, 0x82412017, 0x27002349, 0xe81871bd, 0x6d8207a9, 0x46180021, 0xa62405c1, 0x0100ff66, 0xff225e83, + 0x09835ccf, 0x848b3321, 0x9b082105, 0x00249b82, 0xffcc4c0d, 0x0f701919, 0x69069321, 0x8b2716d5, 0xc015d4fb, 0x19b6b68b, 0x2237d51b, 0x82b100ff, + 0xa90024d4, 0x48159a19, 0x202e065c, 0xffa7cccc, 0xcd4c1a00, 0x0e00ffad, 0xe08233b3, 0xa982ff20, 0xd283ae86, 0x83b30121, 0x990222ae, 0x21ae8599, + 0xcc82660c, 0x22830a20, 0x49830b20, 0x8b21bd82, 0x56ae8408, 0x595605c6, 0x0c3a560d, 0x41095756, 0xcc2005ac, 0x4883e382, 0x66f4ff2c, 0xffff8b66, + 0x089a99f3, 0x0882077b, 0x6766fd25, 0x82ffffff, 0x07ac417a, 0xac413420, 0x4168202a, 0x982108ac, 0x22cb828b, 0x829a19c1, 0x19cb2551, 0x2300ff9a, + 0xff219a82, 0x20bd83e5, 0x20698233, 0x05f845ff, 0xc3831620, 0x1e830520, 0x2305ad4f, 0x0866e619, 0x06829682, 0x82060c48, 0xffff2216, 0x82ee83f6, + 0x8b08252a, 0x8e00ff07, 0x16234283, 0x181566e6, 0x18163583, 0x410eeee2, 0xfb2315ad, 0x4374f724, 0x86230529, 0x190e00ff, 0x410dff02, 0xd3520c34, + 0x0e6d5213, 0x6c4cee21, 0xb743099c, 0x43db2008, 0xcc200b88, 0x08acbd18, 0x188b3421, 0x430ef2a7, 0x5ea31288, 0x2906977e, 0x332f01ff, 0x00ff1534, + 0x34823346, 0x9999a328, 0x0400ff05, 0x7e4bcdcc, 0x820b2006, 0xfdff24d6, 0x7aff66e6, 0x042205c5, 0xf055cdcc, 0xb3052807, 0x0200ff33, 0x82986666, + 0x67e62129, 0x1a831f82, 0x66e4ff22, 0x23272a82, 0xff056666, 0x8233f5ff, 0xb30c2520, 0x0100ff34, 0x13231f83, 0x43ff32b3, 0x0b220527, 0x44823433, + 0x6e820d20, 0x190b002c, 0x1300ff9a, 0xffffcccc, 0x098299fe, 0x00800b27, 0x19f3ffff, 0x201e8298, 0x2338822e, 0x6866cbff, 0x0f208d82, 0x2b081583, + 0x949999ed, 0x4ce8ffff, 0xffff8bcd, 0x08cc4ce7, 0x19a2ffff, 0x00ff079a, 0x0666e640, 0xe65d00ff, 0xff8b0766, 0x34b31800, 0x1700ff94, 0x10209983, + 0x12228883, 0x4a866766, 0x99340023, 0x834a8298, 0x0c002360, 0x748568e6, 0x83010021, 0x23888324, 0x66e6f4ff, 0x0d202982, 0xf420ed83, 0xb2828e82, + 0xffff6628, 0xffce4cec, 0x0483f4ff, 0x7184f320, 0x1e83e520, 0x9a99dc22, 0xf821dc82, 0x201f82e6, 0x26e183f7, 0x7e686602, 0x820900ff, 0xfaff23dd, + 0x4482cd4c, 0xd8820820, 0x83fbff21, 0x830a201a, 0x8302205e, 0x820520e2, 0x070023cd, 0x1e820080, 0x44824520, 0x665c0023, 0x228d8267, 0x83cccc70, + 0xab1121b5, 0x22283f42, 0x824affff, 0xff8b21f5, 0x2005a57f, 0x21c882fa, 0x6982f2ff, 0x18f6ff21, 0x2108167c, 0x8983aaff, 0x00809c22, 0x03255f82, + 0xff069a99, 0x32a41800, 0x14fc222b, 0xe0451806, 0xae451816, 0xff332309, 0xce830a00, 0xcd4c0d23, 0x84cf828b, 0xaaff2364, 0xbd47c2b5, 0xc2f62207, + 0x050b458f, 0xeefaff23, 0x217e8214, 0x3b82cdcc, 0x9a190e22, 0xb5202b82, 0x8505a641, 0x0d0756f0, 0x56054169, 0xc618051e, 0xff3a0afd, 0x9919ffff, + 0x338fffff, 0xffab0534, 0xccccb0fe, 0xf3ffff15, 0xff8b9999, 0xc344f4ff, 0x20988506, 0x20068508, 0x058357ff, 0x0c229f84, 0x9f826766, 0x41068668, + 0x6b2d2b04, 0xfb076b06, 0x07ab0614, 0x19bfffff, 0x2d0c899a, 0x06ffffdf, 0x01ffef0e, 0xf89a1917, 0x7082152c, 0x0a171627, 0xcc1200ff, 0x21bb82cc, + 0xbf18f6e8, 0x0d820867, 0xff66e625, 0x1a17eeff, 0x4a0e745d, 0x168205fa, 0xbf187420, 0x95190f3d, 0xff2f0872, 0x32b36000, 0xff1569fb, 0x34b30100, + 0x82f2ffff, 0xf6ff2b5a, 0x7d7f9a99, 0x66feffff, 0xfa820868, 0x8232b321, 0xcc4c250a, 0x0900ff7f, 0x1583ff82, 0x16829920, 0x9899fb2c, 0xffff05ae, + 0x066866f8, 0x0c82ffff, 0x0c826820, 0x7d223082, 0x3e83ff7f, 0x52834885, 0x2306844a, 0x98990100, 0x97201984, 0x00226885, 0x8f4b330d, 0xff982505, + 0x34b35800, 0xec273c82, 0xffff3433, 0x823233f0, 0x83f5200a, 0x80f622cc, 0x210f8200, 0x2f82cdcc, 0xffce4c24, 0x0e82f7ff, 0x190a0023, 0x254f8298, + 0xff6766f7, 0x2e820a00, 0x4c010028, 0x0f00ffcc, 0x0e829a19, 0x08260483, 0xff089a99, 0x3d821b00, 0x99170027, 0x00ff0598, 0x270a8312, 0xa368e60f, + 0xcc0800ff, 0x18232a82, 0x5e8b34b3, 0x8b210555, 0x835282a3, 0x21228342, 0x5783f0ff, 0xff223884, 0xc98266e8, 0x9a206882, 0xee821f82, 0xff216284, + 0x214782f0, 0x0e82f7ff, 0xccf5ff23, 0x05d64ecc, 0xf5ffff24, 0xa08368e6, 0xfe229b82, 0x0e8332b3, 0x00ff6625, 0x82008009, 0x23ca831e, 0xcecc0f00, + 0x0b218182, 0x36f68219, 0x05cc4ca7, 0x4caffeff, 0x1551f7ce, 0xfd1600ff, 0x00ff8b71, 0x418f0211, 0xff330bb0, 0xcccc5fff, 0xff7a8b07, 0xd7a30700, + 0xb3efffff, 0x827f9734, 0x0f3327a9, 0xccffff5d, 0x498266e6, 0xcd4c0822, 0xb3219282, 0x214f8234, 0xcb82ccfe, 0x33b30927, 0x660600ff, 0x20258266, + 0x289e820c, 0x34b30800, 0xcc0100ff, 0x82f582cd, 0xf5ff24d7, 0x82969a19, 0x83d0208a, 0x332f252a, 0xffff0532, 0x1acba518, 0x1a580c20, 0x5da71808, + 0x28cb830b, 0x99994800, 0x80b7ffff, 0x26818200, 0x76010015, 0x820b00ff, 0xe3ff2951, 0xff8b0080, 0xcc4ce2ff, 0xb1206282, 0x18051e44, 0x27135e9c, + 0x4cbdffff, 0x8b7a06cd, 0xad83d083, 0x7f34b323, 0x25318297, 0xffb81e9c, 0xd5836300, 0xfdedff34, 0xffff9d70, 0xffd7e3f5, 0xcc4c1900, 0x1800ff8b, + 0xd1829a99, 0x906add20, 0x17162205, 0x06e8420a, 0xf6e81124, 0x0e8200ff, 0x3e828b20, 0x9919ff2e, 0x02ff058b, 0x6368e658, 0x22ffff15, 0xff232a84, + 0x416666e7, 0xe6240692, 0x797934b3, 0x9c272682, 0xffff9819, 0x839a199c, 0x9a192dfa, 0xf0ffff7f, 0xffff9a99, 0x7acc4cf9, 0xbd224483, 0x4476cc4c, + 0x00ff2217, 0x0534444e, 0x34b31d22, 0x0029ef85, 0xa000801c, 0x00ff08a0, 0x23428248, 0x00804800, 0x0e7ec518, 0xb8823420, 0x00800c27, 0x80f3ffff, + 0x22258200, 0x84fe7f0c, 0x0590600a, 0x02200a83, 0x8f410f84, 0xd0ff2306, 0x9482cecc, 0x9a19f523, 0x07d56b80, 0xffcccc2b, 0x68e60c00, 0x4cf7ffff, + 0x224082cc, 0x8232b309, 0x9a9922a9, 0x201f8298, 0x25838233, 0xffce4c08, 0x1a840800, 0xd5823320, 0x82330021, 0x979724d5, 0x830600ff, 0x4c1024a0, + 0x829c8bcc, 0x19a12334, 0x8782079a, 0xa4301525, 0x821100ff, 0x1200284b, 0x00ff5ccf, 0x82981916, 0x850684ee, 0xedff2316, 0x9882a430, 0x5ccfea23, + 0x20068208, 0x294982ff, 0x00ffef0e, 0xf79a19bf, 0x3e8215d4, 0x82b04621, 0x333a263e, 0x3900ff33, 0x223e824f, 0x83cdcc45, 0x9947223e, 0x261b829a, + 0xffcc4c39, 0x83b0c6ff, 0x4fb9213e, 0xb9223e84, 0x1182cd4c, 0xff288582, 0xff33b3c6, 0x6666b8ff, 0xff232d82, 0x823333ba, 0xccc5275a, 0x3900ffcd, + 0x3882cd4c, 0x33b34626, 0xcb2cfb08, 0x02fc0210, 0xf7af3794, 0x8b15db94, 0x4cdcffff, 0x0a00ffcc, 0xffff9a99, 0xffceccde, 0x0e821200, 0x4ce4ff25, + 0x52ff08cc, 0xfa3505c4, 0x7e05ce4c, 0x19f3ffff, 0xebffff98, 0x7f8b9a19, 0xe60c00ff, 0x081d8268, 0xc2353e23, 0xccc700ff, 0xffff05cc, 0xc5eb11c8, + 0xfd0200ff, 0x5f00ff71, 0x00ff66e6, 0xff15ee3e, 0x86eb3500, 0x83058208, 0xf32e320f, 0x5200ff32, 0xffff67e6, 0xbd9002f7, 0x0ccdffff, 0x201a82ce, + 0x2f1a8213, 0xac07ebff, 0x00ff9e05, 0x0554f814, 0x3200ffbd, 0x51202883, 0x002b1782, 0xff70fd08, 0x68e63700, 0x84d1ffff, 0x822a202c, 0xdaff2614, + 0x00ff7a94, 0x25aa830e, 0xff0080c6, 0xaa83f2ff, 0x67e6cc22, 0xe9208c82, 0xb32ac484, 0xe6ffff33, 0xff910080, 0xce73e5ff, 0xcc9e2205, 0x24e182cc, + 0xff3433b1, 0x820482ff, 0x2210820a, 0x828bab08, 0xedea18f6, 0x00ff3059, 0xffccccb0, 0x9a995100, 0x05432b15, 0x83fbffff, 0x83fc20c4, 0x66fd25be, + 0xfaffff66, 0x0021be82, 0x26be8302, 0x089a19fb, 0x820100ff, 0xfbff300f, 0x00ff9819, 0xff989904, 0x34b3fcff, 0x840500ff, 0x230027bd, 0xff069a99, + 0x3a83e1ff, 0xccccc922, 0xfd204a82, 0x2b82e582, 0xff8c9a26, 0xceccf9ff, 0x4c213182, 0x213182ce, 0x4682cc4c, 0x1a830420, 0xe882fc20, 0x82060021, + 0x00002314, 0x1e8232b3, 0x6a836582, 0xd3eb0823, 0x830d8205, 0x19032263, 0x0687489a, 0x8c830520, 0x0482fe20, 0xe6040026, 0xffff0866, 0x68200a86, + 0x6624b082, 0x0300ff68, 0xfa204f83, 0x26052b5b, 0x066666dc, 0x831e00ff, 0x3336223a, 0x204a8234, 0x82a48302, 0xff8a2536, 0x32330600, 0x6d843182, + 0xce829920, 0x83fbff21, 0x8302201a, 0x83f920b2, 0x18002014, 0x2008c94d, 0x221e82fc, 0x420e078b, 0xf722f875, 0x4d788bd4, 0x0a0719d8, 0x068b2131, + 0x44f90942, 0xf7205e7f, 0x205ec96d, 0x6def18ff, 0x2a041067, 0x70715801, 0x6308106a, 0xf7235601, 0x1900ff34, 0x43cc7907, 0x0c46f8eb, 0x6e7f185e, + 0x31a8470e, 0xdbffff24, 0x0483cc4c, 0x8505ce21, 0xbf74190a, 0xf7af3be9, 0x7d01ffd4, 0xff150a57, 0xceac4000, 0x7300ff07, 0xffffcccc, 0xffa290f1, + 0x09835b00, 0x38a42a08, 0x0e00ff52, 0xffff6866, 0x0834338c, 0x4cbfffff, 0xffff06cc, 0xff9a99f2, 0x66665000, 0x80c0ffff, 0x3f00ff00, 0xffff3473, + 0x2b1383af, 0x08707d0d, 0xff8b078b, 0xf6a844fe, 0x99215283, 0x8352829a, 0x0d002128, 0x04882884, 0x3c820d20, 0x08254183, 0xb34000ff, 0x22528234, + 0x849899f1, 0xffff2363, 0x4d8233a4, 0x3233a422, 0xf1220e86, 0x52829a99, 0xe1feff26, 0x72f7e2fa, 0xab275383, 0x00ff0685, 0x8633730d, 0x803f2272, + 0x84868601, 0x80f22a90, 0xffff0800, 0x076666bf, 0x20b282ff, 0x82bc8333, 0x22c684a6, 0x82cecc5b, 0x5c8f21da, 0x7882e484, 0x1f05de28, 0x041e01ff, + 0x2f821518, 0x82f25221, 0x23c2832f, 0x9082f2ff, 0x7f214f82, 0x240482ff, 0xffffcc8c, 0x832f82f2, 0x215483db, 0x7982eb51, 0xa4700e22, 0xff244084, + 0xaec75b00, 0x73220486, 0x6882cdcc, 0x825e6f21, 0x00002c54, 0xff7b0740, 0xe8fb21ff, 0x1806eb15, 0x190ad644, 0x590dcd4c, 0xb3200dce, 0x21076d70, + 0x561854fb, 0x54180a44, 0xcb232371, 0x18062b07, 0x70186d45, 0xa4700b44, 0x83f7200a, 0x11002364, 0x981934b3, 0xcc200822, 0x13cbee18, 0x09e6b918, + 0x0e074b26, 0x74f774f8, 0x0dec4018, 0x09244718, 0x2005837f, 0x834a18ff, 0x06043710, 0x8051ffff, 0x00ff0700, 0xff008001, 0x0080feff, 0x5600ff05, + 0x42580080, 0x822b202e, 0xe6f92246, 0x21658266, 0xb28233f9, 0xcc4c0230, 0x66fcffff, 0x0400ff66, 0xff08ce4c, 0x0a837fff, 0x66667927, 0x80ffff05, + 0x235b82c0, 0x0a97cfff, 0xd8342b82, 0x00ff8fc2, 0x8b343327, 0x803000ff, 0x00ff0800, 0x07cc4c38, 0x84200c82, 0x00218a82, 0x8204886b, 0x828b200e, + 0x827f201c, 0xfff32828, 0x0a179dff, 0x830800ff, 0xe8823b60, 0x00ff08f6, 0x06008000, 0x154b34fb, 0x66d2ffff, 0xffff0666, 0xff34b3de, 0xc784c8ff, + 0x66e64e27, 0x4cb6ffff, 0x26d282cc, 0x07343381, 0x82ddffff, 0xb8002336, 0x2c8266e6, 0x9a19fc2a, 0xd70500ff, 0xf8ffff0a, 0x00263082, 0xffb89e02, + 0x1e82f9ff, 0x07b27718, 0xff26c682, 0xffc2f5fd, 0xbb82fbff, 0xd4f9ff23, 0x22af827c, 0x5f66e6f8, 0x332007c0, 0x08ff7a18, 0x8d82cd20, 0x83cccc21, + 0x0a017aa0, 0x33330722, 0x0822c782, 0xa082cdcc, 0x7a832b20, 0x82220021, 0xe4701865, 0x8442830d, 0x824c2070, 0x84062042, 0x99192184, 0x06272f82, + 0xff8dcccc, 0x82990400, 0x8406209f, 0x18072046, 0x2008b277, 0xf78d18cc, 0xbb4a1811, 0xe4701816, 0xffcc2909, 0x9a193400, 0x82ffff05, 0xff246282, + 0x159a19f7, 0x75189984, 0x498311b3, 0x12a09318, 0x35e47018, 0xd882a985, 0x18330721, 0x9b071f94, 0xe470185f, 0x00ff342e, 0xff6666a1, 0x846b6401, + 0xffffff15, 0x00ff9a19, 0x72c4b503, 0x002305ba, 0x8248e103, 0xfd0322e0, 0xe9471870, 0x00802109, 0x07e89618, 0x8b008023, 0x210b8208, 0x228266e6, + 0x6766122d, 0x61f1ffff, 0x0500ff48, 0x8277cdcc, 0x820e2016, 0x14002653, 0x00ff84eb, 0x26b48218, 0x34b30d00, 0x651b00ff, 0x57180573, 0xf8221728, + 0x17719a99, 0xccf82806, 0xffff8acc, 0x829a19f9, 0x831d2048, 0x83f420fd, 0x1915274d, 0xff8b6e9a, 0xc763deff, 0x83e32005, 0x82f1202d, 0xe7ff215b, + 0xff23b382, 0x8232b3e9, 0xcccc2180, 0x51203182, 0xff276b82, 0x05cc4cae, 0x830f00ff, 0x66f02724, 0x1900ff68, 0xa6826466, 0x9c990f22, 0x98201483, + 0x0f222582, 0x1f849899, 0x19201582, 0xff205d82, 0x2f822584, 0x82ff0821, 0xff64230a, 0xe8821000, 0x99e6ff24, 0x0f838b9c, 0xffff6625, 0x820080ef, + 0x247c821a, 0xe62100ff, 0x255b8266, 0xffcc4c22, 0xf7822200, 0xcc370023, 0x834582cc, 0xddff230f, 0x5b829999, 0x71822220, 0xb3ddff23, 0x203b8234, + 0x20a183c8, 0x826b82dd, 0x8232200f, 0x83e12040, 0x2004849c, 0x081072d1, 0xceccdd25, 0x821700ff, 0xfeff22d6, 0x27c682c9, 0xea513601, 0x5e01ff05, + 0x0023bb82, 0x627c941b, 0xf25e1baa, 0x88dd1812, 0x2b6b212d, 0x0a394b18, 0x00ffcc23, 0x564b180e, 0x16b04508, 0x7716fb44, 0x44820c6a, 0x8205b861, + 0x82e820ef, 0xe4fe27e5, 0xff15cc4c, 0x0a821a00, 0x82e6ff21, 0xeeff36eb, 0xffff9819, 0xff66e6d4, 0x6866dcff, 0xfeff088b, 0x06cc4cc3, 0x449e19ff, + 0x01ff2515, 0x0734b33c, 0x23274f82, 0x00ffb89e, 0x820a172b, 0x98d92798, 0x351900ff, 0x4d83ffc3, 0xff082208, 0xcccc6301, 0x549bfeff, 0xaf0e057a, + 0x66fc00ff, 0x5801ff66, 0xff153433, 0xcd4cfdff, 0xd40400ff, 0x273c827a, 0xffa4f005, 0x33b30200, 0xde250f82, 0xbba608b8, 0x820d8205, 0x05002689, + 0x00ff3e0a, 0x22328205, 0x821e0300, 0x4405205e, 0x3523057c, 0x82063433, 0x850c8216, 0xfcff231c, 0x308548e1, 0xf5faff26, 0x5ba608c2, 0xb32c3e83, + 0xfbffff32, 0xff8b4821, 0x5c0ffaff, 0xce206c83, 0x2b230f82, 0x82700886, 0xfdff221d, 0x201d8233, 0x23e183fa, 0xff9a99fa, 0x21063e72, 0xeb823433, + 0xcccaff22, 0xfa20eb83, 0x39820c82, 0xee711c82, 0x25308305, 0x9a190500, 0x9b837008, 0x34b3ab27, 0x19acfeff, 0x51354198, 0x41a43021, 0xd1210835, + 0x053541ec, 0x2000ff2a, 0x00ff9a19, 0x159a1943, 0xb3829182, 0xcc020022, 0xfc20cb82, 0x052f0983, 0xff8b6666, 0xcccc0500, 0x3500ff08, 0x85073433, + 0x84ff200c, 0x053741b3, 0xff20b382, 0x08283083, 0xff05a6bb, 0xcccc0400, 0xb3210d82, 0x21338232, 0x2c839819, 0xff26c882, 0x08ce4cfd, 0x1d8270bb, + 0x9c190524, 0xe984ffff, 0x98190322, 0x27089e7d, 0xff083433, 0xcccccaff, 0xff285c82, 0xff3433fa, 0x68e6fcff, 0x04821c84, 0x8464e621, 0x5b082130, + 0xff213e82, 0x05e145fa, 0xfa269b82, 0xff8b68e6, 0x2c82fbff, 0xb3020025, 0x825b0832, 0xf7fe217a, 0x01247a82, 0x159a9938, 0x242e4c65, 0xab1100ff, + 0xa9bb1884, 0x487c2008, 0x1f621419, 0x34f72308, 0xa21854fb, 0xe24809c2, 0x83cd2005, 0x10526232, 0x08524f18, 0x252d3143, 0xd4f7ef0e, 0x501815eb, + 0x4e180d66, 0x33200a68, 0xe3af3819, 0x9899d429, 0x1d45ffff, 0x5fff0530, 0x01220527, 0x09823333, 0x83050057, 0x9a192c09, 0xffff088b, 0x8b3433a4, + 0x83b4ffff, 0xb3b9222b, 0x26208234, 0xffff68e6, 0x82cc4ca6, 0x4cff271a, 0xf7058bcc, 0x9a557bd4, 0xffcc24d8, 0x19330600, 0x10316506, 0x46015902, + 0x157bab22, 0x2d900819, 0xffff8b25, 0x190080b0, 0x5527ec08, 0x0410c8ea, 0x424801ca, 0x4e525e70, 0x315c440e, 0x18b14e52, 0x231601bb, 0x4c0600ff, + 0xdb20fe98, 0x24221a83, 0x041934b3, 0xb42d0e4b, 0xe66100ff, 0xff8b1566, 0x9a19feff, 0x41b01805, 0xefb9470d, 0xcccc8932, 0xe986ffff, 0xffff05fc, + 0xff9a99f3, 0x66e60000, 0x66200982, 0xfc200482, 0x08237518, 0x3433f726, 0xdcffff08, 0xff211e82, 0x201983e0, 0x203383e1, 0x222883db, 0x82ce4cea, + 0x67e62118, 0xeb321e82, 0xffff9819, 0xff3333de, 0x34b3efff, 0x99d9ffff, 0x1a828b9a, 0x08cccc34, 0x71f7068b, 0x998000ff, 0x00ff159a, 0xff68e607, + 0x39820900, 0xe6080028, 0x0a00ff64, 0x0e82cdcc, 0x00342e82, 0x0833b309, 0x990500ff, 0x0400ff98, 0x00ff3433, 0x8bd0cc08, 0xff230f85, 0x1866e6fa, + 0x20088845, 0x262f824c, 0x6d64e614, 0x820e00ff, 0xe3ff2335, 0x1a82ff7f, 0x9c990e23, 0x8246826f, 0x18ff203b, 0x20248445, 0x209882cc, 0x183e82b9, + 0x82148445, 0x8320207b, 0xb3132880, 0x9f08ab32, 0x832000ff, 0x191c2572, 0x2100ff9a, 0x2127ac83, 0x00ffcc4c, 0x8432b31d, 0x909a21ac, 0x4882d182, + 0x83ffff21, 0x660623d6, 0x45188666, 0x332e0878, 0x1200ff32, 0xffff0080, 0xff67e6ec, 0x51821100, 0x33ebff2c, 0x078b0833, 0x8dffffb4, 0x45186666, + 0xff240878, 0x9a19d5ff, 0x087c4518, 0xdbffff38, 0xff7c66e6, 0x9a19eaff, 0x8b08738b, 0xb86eaf5a, 0x8b9d088b, 0x7e82909b, 0x66e60a2c, 0x00ffa908, + 0x939a1914, 0x8d8279b5, 0x0e230e82, 0x1874f8ef, 0x22190d53, 0x180604f7, 0x180df7bd, 0x20237991, 0x79911804, 0x078b2a1f, 0x1594fc4b, 0x190000ff, + 0x2a5e829a, 0x8b32b300, 0xbfffff05, 0x4e063433, 0xeb21164f, 0x05584e07, 0x19ffff21, 0x1827e043, 0x200bd769, 0xd1681833, 0x8bcd2208, 0x99591808, + 0x54f72718, 0xdfffff07, 0x83829919, 0x8f82f335, 0xf4ffff8b, 0x00ff6005, 0xffcc4c08, 0xa05afbff, 0x610c00ff, 0x0a860511, 0x0300ff2e, 0x00ff7faa, + 0xff9a190e, 0x3d2a0a00, 0xb32e2882, 0x00ff0833, 0xffae07e0, 0xffffbf00, 0x16829705, 0xff20452d, 0x99991100, 0xffff978b, 0x82e0baf5, 0x338b3b1d, + 0x88ffff34, 0xfb0534b3, 0xaf0e07f5, 0xcce201ff, 0x3901ffcc, 0xff1566e6, 0x1a830b00, 0xceccf726, 0xb30400ff, 0xf1222482, 0x76829899, 0xff32b327, + 0xceccf2ff, 0x200a8308, 0x058c6a34, 0x82f3ff21, 0xf7ff2133, 0xff217682, 0x050f4bf2, 0x6666ef33, 0x0000ff06, 0xffffce4c, 0x05ccccb6, 0x66feffff, + 0x05d05166, 0x80feff24, 0x0f828a00, 0x8a9a9922, 0x0f0cb318, 0xf618ff20, 0xfe256496, 0x00ff6766, 0x19411801, 0xe6012208, 0x208d8266, 0x05df7a4c, + 0x07d40824, 0xd382067b, 0x8bd7232a, 0xb8f3ffff, 0x0800ff52, 0xfb231e83, 0x6bffc2b5, 0xff200555, 0x322f0a86, 0xb00400ff, 0x0e00ffa4, 0x00ff6866, + 0x82c3350b, 0x32332d28, 0xb000ff08, 0x00ff2005, 0x05e2fa7f, 0x33201582, 0x08282482, 0x00fff628, 0x8b34330f, 0xff370f85, 0x080ad7f7, 0xffff44f7, + 0x051e0580, 0xb32affff, 0x50ffff34, 0x18153433, 0x203538b1, 0x1d5410ff, 0x44306601, 0xb30a00ff, 0xfbffff34, 0x00ff15fd, 0x08343311, 0x08200a83, + 0x90b3f618, 0xff068b28, 0x66e6bf00, 0xc34404fb, 0x188b2005, 0x10228cfe, 0x04021f56, 0x27164644, 0xef0e068b, 0xc4f7b4f7, 0x2c1ab750, 0xff8b5278, + 0xae87bfff, 0x804000ff, 0x05854e00, 0x06830820, 0x78211184, 0x26168252, 0x00ff4478, 0x19ae874f, 0x210f0d28, 0x3882bc87, 0x5278b031, 0x6cffff08, + 0x00ff33b3, 0x15a4b02c, 0x821c00ff, 0xe3ff2a0a, 0xff055c4f, 0x9a99a6ff, 0x9b891806, 0x18cc200d, 0x1810bc63, 0x240d27a8, 0x665900ff, 0x23338266, + 0xffcd4ce3, 0x080fab18, 0xffff3325, 0x82ceccf9, 0xccf5256b, 0x0600ffcc, 0xf9231a83, 0x8208cdcc, 0x8333200a, 0x236f821a, 0x34330a00, 0x0620b282, + 0x1f830f82, 0xffc30827, 0x01003800, 0x502c8505, 0xa7820dd7, 0x32330624, 0x21825308, 0x82900221, 0x824982a3, 0x00402326, 0x5d82ffff, 0x0f836382, + 0xc0f9ff27, 0xffff0800, 0x835982f9, 0x2215820a, 0x85b8def5, 0xf9ff294c, 0x8b0890c2, 0xa000ff07, 0x00238682, 0x82d8e322, 0x335027f1, 0x3a00ff34, + 0x2e46cc4c, 0x168e4724, 0x8e473420, 0x47302009, 0xd021088e, 0x078e47ff, 0x828b9821, 0x66ef2d8f, 0x00ff0668, 0xffcc4c00, 0x9a99abff, 0xfd23bb82, + 0x6affcccc, 0x09860517, 0xffff9825, 0x8268e6fd, 0x34b32113, 0xe9202f82, 0x12201e83, 0xdf22c483, 0x148266e6, 0xff676625, 0x184ce8ff, 0x4715e3ff, + 0x682b2ab5, 0x80f0ffff, 0x85810800, 0x82f4ffff, 0xf9ff2361, 0x09826666, 0xff33332a, 0x6866fcff, 0x2a00ff08, 0x00346782, 0xff991920, 0x00801a00, + 0xe63200ff, 0x00ff8b66, 0x08cd4c39, 0x1c2f0682, 0xffff9a99, 0xff9a19fa, 0x7a141b00, 0x82f3ffff, 0x17002d3f, 0x8b0868e6, 0xff07f707, 0x846bf0fe, + 0x98366a18, 0x00ff3423, 0x24ad820a, 0x9899f2ff, 0x990319ff, 0x99992b9d, 0x99f7ffff, 0xebffff9a, 0xfd18a4b0, 0x3e2613c2, 0xeeffff87, 0xcf823dca, + 0x20050e47, 0x090e4771, 0x32200a84, 0x33201983, 0x4c211482, 0x2c0482ce, 0x088fc335, 0x191200ff, 0x0400ff99, 0x311a8233, 0xffb91e12, 0x9a190900, + 0x570e00ff, 0x0b00ff0b, 0x1e8266e6, 0x82330b21, 0x8009252f, 0x1000ff00, 0x00201983, 0x19835882, 0x10990319, 0xf0219982, 0x214482b3, 0x0319661c, + 0x53492799, 0x068b2435, 0x82b2ffff, 0xaaff278e, 0xff159a19, 0x06191500, 0x79475706, 0x6c021057, 0x8b2b9101, 0xf8ef0e06, 0x8b156b14, 0x18f4ffff, + 0x2218799f, 0x116666ff, 0x2e014752, 0x33b52208, 0x60ffff34, 0xff05cab6, 0x0080d4ff, 0x99f0ffff, 0xe0ffff98, 0xffffcccc, 0x8b0180d6, 0x33cfffff, + 0x0ca11833, 0xfb8b271d, 0x24f70514, 0x9e18b4f7, 0xef2acf15, 0x804001ff, 0x4200ff00, 0xda820080, 0x9a19043d, 0x1c00ff55, 0xffff6666, 0xff66e6d0, + 0xcccc2900, 0x99e2ffff, 0xfeff089a, 0x19ce4cf5, 0x5b745d52, 0xd53a2551, 0xff8b9a99, 0x9a19d9ff, 0xe1ffff7c, 0x08729899, 0xb3ffffff, 0x53058b34, + 0x9c18c306, 0xcc300a6b, 0x330700ff, 0xf6ffff34, 0x088bce4c, 0xffff065b, 0x0a694518, 0x090dd018, 0x53075322, 0x9a181a8f, 0x5b200792, 0x07b64318, + 0x19080023, 0x203e8299, 0x265183cc, 0x088b67e6, 0x975306c3, 0x06bb2c1a, 0x00ff8b8f, 0xff66e602, 0x82e60000, 0x80022a04, 0x0100ff00, 0x8b089a99, + 0x838e8206, 0x8045230c, 0x12821500, 0x829a1921, 0x99ff2576, 0xfeffff9a, 0xbf822782, 0x09823220, 0x82cecc21, 0x291386c9, 0x0300ff08, 0xf7076666, + 0x654b53cc, 0x0080221a, 0x05ad598b, 0x830e654b, 0x19402068, 0x20247333, 0x832219ff, 0xc30210b0, 0xa321b101, 0x871c1053, 0x02102601, 0x101002da, + 0x3c01f11c, 0x2085265a, 0x06265afe, 0x0a295b18, 0x085c7318, 0x276ec259, 0x193fffff, 0x1594f79a, 0x20180c49, 0x19d6486b, 0x22180c49, 0x19ff06ab, + 0x2615df26, 0x00ff07bb, 0x5b66e630, 0x77180c8e, 0x18190acd, 0xff261897, 0x9a19cfff, 0xc949bb06, 0xffcd2605, 0x32b3f9ff, 0x203782ff, 0x06c94933, + 0xae496b20, 0xaf0e3019, 0x66b800ff, 0x15f4f766, 0x00ff8ba2, 0x6867e615, 0x12210626, 0x294682cc, 0x08ceccf6, 0xf8ffff9b, 0x4d829899, 0xffcccc26, + 0x68e6ecff, 0x802c0e82, 0xff087b00, 0x34b3f7ff, 0xedffff7b, 0xf9231683, 0x827b9819, 0x68662121, 0xf4231682, 0x7cff34b3, 0xf32d0563, 0x00ffcc4c, + 0xff9a1902, 0x0080f2ff, 0x821a828b, 0xff8b28a3, 0x9999d7ff, 0x82d8ffff, 0xffff2711, 0x080080cf, 0x9e52648b, 0xdeff2105, 0x00264982, 0xff018023, + 0x1682f4ff, 0xffff9524, 0x498233fd, 0x6f800c21, 0xff22056d, 0x44840b00, 0xe6000023, 0x24a88266, 0x8b9a1900, 0x2153828b, 0x1f821b00, 0xff201383, + 0x09200985, 0x16257d83, 0x00ff6666, 0x5044820f, 0xc05535b3, 0x00ff2116, 0x18107483, 0x220c0105, 0x613333fe, 0xff26051a, 0x66e60000, 0x0f82ffff, + 0xffffff25, 0x82083433, 0xcd4c2105, 0xcc211482, 0x230985cc, 0x9a19ffff, 0xcc210983, 0x221a828b, 0x826766f1, 0xccf12135, 0x1d422082, 0x99992605, + 0xcc0300ff, 0x341a82cc, 0xa1ec51a7, 0x7bcaffff, 0x5000ff08, 0xff8b0080, 0x9a995b00, 0x31068208, 0xff900270, 0xed2d5f00, 0xfd5700ff, 0x7100ff70, + 0x4882ecd1, 0xcc170034, 0xffa28bcd, 0x502dfcff, 0x661500ff, 0xf8ffff67, 0x39824aec, 0x75831020, 0xc275fa25, 0x830900ff, 0x83ed2075, 0x80fa2799, + 0xefffff00, 0x63825238, 0x8266fa21, 0x210a82a9, 0x1984ffff, 0xd8e3f622, 0x4c261982, 0x0500ffce, 0x1e823e8a, 0xa782f020, 0xf304002d, 0xeeffff32, + 0x00ff67e6, 0x8252b802, 0x66e6211e, 0xff236f82, 0x829a99c7, 0x4cd021b8, 0xe22cd482, 0xffff142e, 0xfff5e8e7, 0xec51d5ff, 0x1b257382, 0x00ffa430, + 0x216e8219, 0x5e822400, 0x660f002b, 0x088bb366, 0x00ff068b, 0x320e83f4, 0x15ec9131, 0x660b00ff, 0x0800ff68, 0x00ffcc8c, 0x8298990f, 0xe2fa2165, + 0xff231385, 0x82146ef7, 0x835f2042, 0x11b827a2, 0xff9305ec, 0xb382f9ff, 0x2805245e, 0xff9a99f6, 0x98190000, 0x25218281, 0xfbcc4c00, 0x82820524, + 0x6882fd20, 0x99ffff22, 0x2106706b, 0x8418ffff, 0xfb220930, 0xa36b9819, 0x83ff2005, 0x057d43f1, 0x3433fa27, 0x660100ff, 0x19dc8266, 0x2221f014, + 0x56ffff33, 0xff223ca3, 0xc782feff, 0x105e0020, 0xce4c2105, 0xca827882, 0x66feff24, 0xc582ff66, 0xc4829a20, 0x66e67927, 0x00ff8b07, 0x21948309, + 0x9982b304, 0x2f830920, 0x98190835, 0xffeb0891, 0x52f84700, 0x2000ff05, 0xfeff9a99, 0x10ae8788, 0x4802791b, 0xab70fb28, 0x8b1534f8, 0x4d1800ff, + 0xf721135c, 0x89751854, 0xec53180e, 0x48541808, 0x82fb2016, 0xc6631830, 0xfb6b2215, 0x27658314, 0xffcc4c23, 0x66a61c00, 0xb3280482, 0x2300ff34, + 0x088b9a59, 0x18826584, 0x1142e418, 0x18b4fb21, 0x83187289, 0xa6dc2268, 0x21878266, 0x7b1859e3, 0xb4250d19, 0x4b94f707, 0x19898215, 0x2008c041, + 0xd4e4400e, 0x34fb5424, 0xb419ff15, 0x5b2015da, 0x0aec241a, 0x6959cd20, 0x4cf42106, 0xf2250982, 0xff0832b3, 0x080a83ff, 0x4c0d0026, 0xeeffffce, + 0x00ffcdcc, 0xff666608, 0x66e6ecff, 0x065b088b, 0xdcffff8b, 0x00ff34b3, 0xff67a61c, 0xcc4ce3ff, 0x2306a241, 0xeb8b06cb, 0x33216c8f, 0x827d848b, + 0x853d8534, 0x05d6594d, 0x33206caa, 0x8a826c88, 0x9a592324, 0x6c82088b, 0x8f54fb21, 0x8434206d, 0xbfcc206d, 0x21da916d, 0xa74a069b, 0x33072109, + 0x0cc3c518, 0x0800ff24, 0x7782cdcc, 0x6b4a1683, 0x069b2d0c, 0x01ffaf0e, 0xffcccc5a, 0x66664f01, 0x0326aa82, 0xff836866, 0x10820100, 0x66f7ff3d, + 0xffff8b66, 0x08ce4cf7, 0x19b3ffff, 0x24f70799, 0x00acffff, 0x00ff0501, 0x18cccc12, 0x820af355, 0xb30a2189, 0x0d200482, 0x0ffb9818, 0x0abf5618, + 0x8204fb21, 0xf2ff2130, 0x14832682, 0x6d19ff20, 0xff200af1, 0x153a4219, 0xfb079334, 0xffff0624, 0x07cc4cdf, 0x803a00ff, 0xcdffff00, 0x7a829a99, + 0x00800330, 0xffff8d88, 0x8b34b3fa, 0x66fbffff, 0x93180866, 0x2b221856, 0xf554cb06, 0x73f72012, 0x068305c4, 0x2005ba54, 0x09f354ff, 0x18074b21, + 0x410d54e9, 0x9b200a29, 0x04264a83, 0x00ff9a99, 0x04821901, 0xcc4c0529, 0x660400ff, 0x85088e66, 0x3200239c, 0x9c826666, 0x34b32022, 0x8320b683, + 0x4020eb89, 0x4019b882, 0xf72120b8, 0x094d4104, 0x24dc9319, 0xedffff2c, 0xf7073433, 0x5300ff24, 0x7782ffff, 0x67e64c22, 0xb321ea84, 0x259f8232, + 0x00ffcdcc, 0xa4829908, 0x66660323, 0x279f8293, 0xff99192c, 0x2ce76600, 0x02272782, 0x00ff0080, 0x820ce205, 0xcecc2c04, 0xd00300ff, 0x0600ff62, + 0x828b6666, 0x85068325, 0xfcff2516, 0x00ff9e2f, 0xff232a83, 0x84f41dfa, 0xff982a40, 0xd41899ff, 0x30fb0e05, 0x6b4519eb, 0x8bcd211f, 0x2005d05c, + 0x710d19ff, 0x07732109, 0x0fd65818, 0x19004021, 0x820ae13e, 0xf5ff24f1, 0x83ffcd4c, 0xffff2931, 0x8b33b3f2, 0x0624fb08, 0xc0200982, 0x07a39b18, + 0x830a0021, 0x0d00240a, 0x82080040, 0x8206825d, 0x83358262, 0x83ff2016, 0x088b2915, 0x07a30693, 0x157cfb2b, 0x46201e82, 0x12c9f618, 0x0614f724, + 0x188200ff, 0x08344e18, 0x8234b321, 0x4cb92280, 0xe3ee18cc, 0x0a8f181b, 0x07542419, 0x822b94f7, 0xeeff226b, 0x616a184c, 0x06f96828, 0x11636a18, + 0x200b2969, 0x09a37cff, 0x0e072b26, 0xc4f7dbaf, 0x21096946, 0x694633b3, 0xcd4c2307, 0x2e45088b, 0xfbf7180b, 0x06f4440a, 0xd1611182, 0x18ff2005, + 0x20124867, 0x21fc831c, 0xfc822300, 0xcc00ff39, 0x156b6666, 0x80f1ffff, 0xbfffff00, 0xffff66e6, 0xff9a99c6, 0x8219d0ff, 0x80bb2204, 0x21668200, + 0xb062b0ff, 0x62522022, 0x442008b0, 0xff233482, 0x82663900, 0x21d02549, 0x0e00ff48, 0xde215884, 0x22af82b8, 0x4ececc47, 0xff2705f2, 0xcccc0900, + 0x830c00ff, 0x33062204, 0x24248234, 0x088b3433, 0x191c82f3, 0x200aee20, 0x234883ea, 0x0080e5ff, 0x12291919, 0x8b231582, 0x82062308, 0xcccc21b6, + 0xf320f082, 0x48834383, 0x83f7ff21, 0x2d5c8209, 0xb8ffff08, 0xff063233, 0x9a9973ff, 0xdf8214f7, 0x08a06b18, 0xd5ffff24, 0x33821e05, 0xe2faca33, + 0xff568b08, 0xe2fa2a00, 0x3500ff60, 0x088b1f05, 0x8f5a18c0, 0x1e052109, 0x1a821482, 0x088b562a, 0x6cfbacf7, 0xeb078315, 0x212e027e, 0x7d8284fb, + 0x34b3f222, 0xf5216a82, 0x18ec824c, 0x2010049e, 0x20118200, 0x2e0485ff, 0x8bcc4c0d, 0x9306eb08, 0x00ff8b07, 0x18cd4c0d, 0x2008f4fa, 0x820e8333, + 0xbf56181a, 0x82cd200e, 0xb3f22e53, 0x1cfb0833, 0xf7155cfb, 0x74f70704, 0x055c4506, 0x13f15218, 0x8214fb21, 0xc7181987, 0x04fb2314, 0x881824f7, + 0x72410ee9, 0x067b211f, 0x6b090a77, 0xdb20258a, 0x0824d383, 0x00ffcccc, 0x07bbb518, 0x0800ff2b, 0x088b0ad7, 0x9b0614f7, 0x177b7d5b, 0x6b067b24, + 0xd2189b07, 0x93211741, 0x21b5822b, 0x66444c0d, 0xae9d1809, 0x44fb211f, 0x180e4b44, 0x2408eefc, 0x0d00ff8b, 0x209b824c, 0x0d73450a, 0x0644f728, + 0xccf7af0e, 0x9f82acf7, 0x212bb146, 0xa51824f7, 0xfb262e6a, 0x2cfb0724, 0x66822cfb, 0x14db4018, 0x2010b24a, 0x744118b3, 0x076b3b07, 0xab0694fb, + 0xb2ffff07, 0xffff70bd, 0x150080a5, 0x210800ff, 0x1000ff48, 0x04823433, 0x0982a120, 0xd8830a20, 0x3333122e, 0x01ff088b, 0x06989944, 0x331200ff, + 0x00273e82, 0xff9a9910, 0x82b3f5ff, 0x33082826, 0xefffff32, 0x5108cccc, 0xff240555, 0x05ccccc8, 0x21057b42, 0x2483ebff, 0x0080f026, 0x19e6ffff, + 0xe8202e82, 0x08363982, 0x9467feff, 0xffff067a, 0x8bc335e8, 0x87f0ffff, 0x1900ffae, 0x308266e6, 0xffd7a326, 0x66661400, 0x94314683, 0x3700ff7b, + 0xff053433, 0x6c87b1ff, 0x331001ff, 0x22988234, 0x827f8a07, 0x222a8325, 0x4ec3f50e, 0x002805b7, 0xffd7e30a, 0x6866f8ff, 0x68273482, 0xffff3d0a, + 0x83ffffb7, 0xf266187b, 0xb3022308, 0x20837c33, 0xffff6626, 0x089a19f5, 0x8c830a82, 0x9919f522, 0xfd221582, 0x1584cd4c, 0x0700ff23, 0x201a8399, + 0x21408298, 0x40834700, 0x1af5ff23, 0x054c5c6b, 0x48fdff24, 0x0a829a24, 0x83448b21, 0x0868297a, 0x02ff078b, 0x91f00716, 0x0a228e82, 0x188268e6, + 0x82989921, 0x4cfd22d7, 0x842e86ce, 0x204f8264, 0x82598398, 0x4cfd2204, 0x226982cc, 0x849c19f5, 0x23082679, 0x00b8ffff, 0x21d68201, 0x1c8219f5, + 0x6666f823, 0x058b7c7c, 0x82f8ff21, 0x0a002396, 0xa18367e6, 0x57826620, 0xe6830a20, 0x32b30222, 0x0a847b82, 0x00800727, 0x00fff308, 0x243c8248, + 0xf8f4f70e, 0x187f8254, 0x18091741, 0x250a219b, 0xff8b074b, 0x9c67f7ff, 0xf8ff2307, 0x0e820ad7, 0x8b343327, 0x6b063b08, 0x19074207, 0x2317997a, + 0x9a195ffe, 0x0aa8fc19, 0x18ff1f21, 0x2311f073, 0xe13a0f00, 0xff261684, 0x1fc51000, 0x6482088b, 0x27058548, 0xff04d608, 0x99190800, 0x0738ee18, + 0x8b67e63f, 0x6000ff08, 0xff0666e6, 0x9a19dffe, 0xcb1574fb, 0x0754fb06, 0x002800ff, 0x54f70601, 0x200d8607, 0x87208230, 0x85b3200d, 0xffff2417, + 0x8234b33b, 0x99002928, 0xffffff9a, 0x00ff32b3, 0x00230983, 0x83008000, 0xff983209, 0x34b3feff, 0x056bbb08, 0xb30b00ff, 0xf8ffff34, 0x21218233, + 0x09823305, 0x6866f12d, 0xe6fbffff, 0xf2ffff66, 0x89080080, 0xffff230a, 0x4a8299f3, 0xccccf627, 0xe6f1ffff, 0x21978266, 0xe8843ffe, 0xcdccf223, + 0x241c828b, 0x00ffd98e, 0x25408309, 0xfffce9fb, 0x3b850d00, 0x84bae921, 0x00ff220a, 0x21f08405, 0x6e829899, 0x8229bc21, 0xcecc24dd, 0x82abbb08, + 0x9100277c, 0x0100ffec, 0x9482cc4c, 0x827b9421, 0x829e82a8, 0x823320ad, 0xce4c210e, 0xc429f982, 0x0e07cc4c, 0xf754f7ef, 0x0af047f4, 0x0c515219, + 0x4b06eb28, 0xff066b07, 0x8919d3ff, 0xff220845, 0xaa1833dc, 0xfb270713, 0xffff0704, 0x829a19eb, 0x33ee259f, 0xf2ffff33, 0xf921c183, 0x28db8266, + 0x086666ed, 0x4c8dffff, 0xc9d718cd, 0xd4f72417, 0x18ff8b07, 0x2615b78e, 0x072b0624, 0x8244fbbb, 0x05f56791, 0x1e191520, 0xf7210de8, 0x174c4794, + 0x0724fb23, 0x0c7856ab, 0x0f9f9e18, 0x34b3dc22, 0x21052d4d, 0xfc18e3ff, 0xfb210872, 0x18a282d4, 0x201442f9, 0x09df459b, 0x0021dc82, 0x05ab7307, + 0x8bcd3708, 0xf706ab08, 0x7bcb0724, 0x0714fb15, 0xf70674f7, 0x74fb0714, 0x54f79b06, 0xeb062b15, 0x052beb07, 0xff30fb0e, 0x295c3e00, 0xe6f5ffff, + 0xffff1566, 0xfff668fa, 0x3d82efff, 0xe1edff24, 0x0a828248, 0xffe13a27, 0x00800500, 0x210a8208, 0x0a826a3c, 0xff9a992b, 0x21f0f6ff, 0x331200ff, + 0x320e8232, 0x00ffc996, 0x0834b310, 0xf47f00ff, 0x8001ffff, 0x82051e05, 0x99992115, 0xc2211582, 0x25248390, 0x0900ff33, 0x2484ec11, 0xf4205d83, + 0x23083154, 0xff94f668, 0x15826483, 0x82008021, 0xe23a215d, 0x7f246382, 0xfeffc3f5, 0xc63c4485, 0x01ffa3f0, 0x15f6a8a9, 0x661100ff, 0xfdffff68, + 0x00ff9a19, 0xffcccc0b, 0x8e82efff, 0xff2b0e85, 0x08ec91ee, 0x7ffeff4b, 0x8305c4f5, 0xff992511, 0x9899eeff, 0x50832082, 0xc483f420, 0x0982ee20, + 0xe6020023, 0x205a8266, 0x83b982ee, 0xffff230a, 0x948233f4, 0x19861020, 0xdd825d82, 0x01ffcb22, 0x20824484, 0x11826720, 0x82146e21, 0x222083b0, + 0x82aec70b, 0xff7f210e, 0x172e5d82, 0x068b080a, 0xb35a00ff, 0x0000ff34, 0x4618a470, 0xd67e0ed1, 0x19fc2008, 0x7318db32, 0xf8201688, 0x387f3083, + 0x58611807, 0x078b300c, 0xa800ff0e, 0xffffcd4c, 0x15cccccc, 0x82cbffff, 0x400021fc, 0x8b2ed683, 0x00ff66e6, 0x8b9a999b, 0x665700ff, 0x06820866, + 0x3e0a6a27, 0xf55500ff, 0x220483c3, 0x8200ffc2, 0x088b260e, 0xb35f00ff, 0x251b8234, 0xff66664e, 0x2083baff, 0xd3820f20, 0x75a4ff23, 0x2ba118c2, + 0x83f72007, 0x83d7204c, 0xe6d12614, 0xffff8b66, 0x184c82c8, 0x18071ce8, 0x371483c5, 0x33a1ffff, 0xffff0734, 0xff33b3f0, 0x6666ebff, 0xff80797d, + 0x3233f2ff, 0xf3205082, 0xf0261283, 0xffff34b3, 0x758233e9, 0x0f83ff20, 0x4c0f0029, 0x068b08cc, 0x821700ff, 0xf300221c, 0x105c5033, 0x9e823320, + 0x226b2320, 0x4c232505, 0xe3ffffcc, 0x0021ed82, 0x2044831c, 0x93c519dc, 0xf1b11912, 0xff33210c, 0x8306726d, 0x24438232, 0x64f7088b, 0xcf0e65cb, + 0xdcf7af24, 0xd48234f8, 0x9a198836, 0x6f00ff8b, 0x03fb66e6, 0x081dfb8b, 0xff8b0763, 0x66e6ffff, 0x6821058a, 0x27118208, 0xff5fcccc, 0xcc4cdcff, + 0xd3230486, 0x828b68e6, 0xf3220816, 0xff069a99, 0x32331900, 0xe6d3ffff, 0x00ff0566, 0xff9c9906, 0x0080f4ff, 0xfffbffff, 0xf1fffffe, 0x0e86ce4c, + 0x0080f923, 0x210a8708, 0x19846666, 0xffff8f22, 0xff221582, 0x1a840b00, 0x4482d920, 0x83430021, 0xaeff2e44, 0xff0634b3, 0x9a99d0ff, 0x4cbaffff, + 0x329b18cc, 0x19f52607, 0xffff7c9a, 0x285183fd, 0xff9819f5, 0x98990700, 0x07244808, 0xfd237083, 0x839acd4c, 0x48992015, 0xff22050e, 0x2a821d00, + 0x842a0021, 0x80b52c40, 0xffff0600, 0xff3333cc, 0x84ccb9ff, 0x200a8351, 0x222082f5, 0x82e6f0ff, 0xb3fd218d, 0xf522c182, 0x3f826766, 0xee83e620, + 0xe882f520, 0xcc070022, 0xfd26ed82, 0x00ff33b3, 0x5983190f, 0x00272882, 0x089a990a, 0x822800ff, 0x37002a6f, 0x60059819, 0x4c1000ff, 0x27a182ce, + 0xffd7a3b0, 0x00809bff, 0xf7250a82, 0xffffaec7, 0x25bc83f5, 0xfff6e8f0, 0x4a82feff, 0x00240e84, 0x08343308, 0x98221982, 0x0a82ff93, 0xfe216f82, + 0x84558239, 0x3608225a, 0x21b48287, 0x5a826666, 0x3709f028, 0xff05c4f7, 0xa0820500, 0x82060021, 0x08002645, 0x00ff6666, 0x22048303, 0x82686608, + 0x83e6204f, 0x83082026, 0xe6fe2255, 0x21b08268, 0xe7443433, 0x23238405, 0xcc4cf8ff, 0x15204582, 0xcd22cf83, 0x48823333, 0x24832820, 0x01803722, + 0x05230a82, 0x82929819, 0x2345827b, 0x98990300, 0x99220982, 0x2c828a98, 0xcd820820, 0x84ffff21, 0x581a82e2, 0x6f83056f, 0x19f8ff22, 0x2920ec83, + 0x9e204b83, 0x0024da83, 0x06343340, 0x3327a882, 0x00ff8b34, 0x82cccc09, 0x9a19278c, 0xfcffff94, 0xd8820080, 0x9a99ef26, 0xaeffffe9, 0x47204783, + 0xff23ad82, 0x19cc4c9d, 0x1811c17e, 0x4f0805fe, 0xb32108e3, 0x06e84f34, 0x2f830d20, 0x828b9b21, 0x190428a7, 0x1564fb9a, 0x182f00ff, 0x2d09db8a, + 0x0566e628, 0x99e1ffff, 0xd7ffff9a, 0x0a829a19, 0x9582b520, 0x8029002c, 0xffff1500, 0xffce4cdf, 0xa084d6ff, 0x32333022, 0x0120a082, 0x0021d082, + 0x24318201, 0x2700ff7a, 0x262d8299, 0x3433ee00, 0x8376ffff, 0xf082182d, 0x204a1815, 0x07386709, 0x211b4252, 0x854eff8b, 0x18072005, 0x240e4c83, + 0x7cd468fe, 0x2db782eb, 0x06b8de25, 0x33b2ffff, 0x9effff33, 0xac8234b3, 0xf668f522, 0x9582e482, 0xb0f9ff28, 0x0e00ffa4, 0x70820080, 0x00800f23, + 0x27068208, 0xff66661f, 0x33731900, 0x09830482, 0x48611f2c, 0x078b088b, 0xf734f80e, 0x68821584, 0x8219d221, 0x83f120f2, 0x99d52c04, 0xffff719a, + 0x089899dd, 0x837f00ff, 0x4c81254b, 0x00ff05ce, 0x1af85f18, 0x2583f320, 0x1980f321, 0x8213205c, 0x8245843b, 0x8251829c, 0x99d52157, 0x71826787, + 0xff088b26, 0xb81e8dff, 0xa2277e82, 0x00ff47e1, 0x829a195d, 0xe67222a8, 0x22af8366, 0x8248e172, 0xb91e2111, 0xb8220483, 0x0e8200ff, 0x00202d82, + 0x22821c82, 0xff242882, 0x48e1a2ff, 0x3e823882, 0x50274482, 0x15e49a19, 0x82f7ffff, 0x09002888, 0xffffcc4c, 0x82ccccf0, 0x83f6201c, 0xb3f6226c, + 0x24218234, 0xff33b3f6, 0x820f82ff, 0x201b8215, 0x202582ff, 0x822f84cd, 0x831f20e4, 0x19e022f5, 0x22a3829a, 0x1866e689, 0x220cb165, 0x4f4cf5ff, + 0x38820722, 0x4382f220, 0x820a0021, 0x19168304, 0x2208ec0d, 0x829a1976, 0xe6e02333, 0x40826c66, 0x0928669a, 0xffff6666, 0xffceccf5, 0x20068f78, + 0x28ac8308, 0x0832330a, 0xff05d3d3, 0x21088200, 0x128200ff, 0x0f22dd82, 0x28863433, 0x08233282, 0x4105d343, 0xfb22c4a4, 0x034f43cc, 0x07434107, + 0x4341cc20, 0x09834f08, 0x34201b82, 0x22054b4f, 0x8407cb08, 0x18cd2008, 0x210872af, 0xd153ff33, 0x53671805, 0x0aa1410b, 0xdb074b23, 0x2162ae8b, + 0x638534f7, 0x6388cc20, 0x63953420, 0x838bcc21, 0x08342317, 0x648d34fb, 0xaf182e82, 0xeb2020aa, 0xbe51638a, 0x204b8405, 0xa490188b, 0x0ade560c, + 0x0e072b37, 0x5f02ffef, 0x54f89819, 0x1200ff15, 0xff8b9c99, 0x64660d00, 0xc76718ff, 0x1833200a, 0x19082851, 0x22106224, 0x423433ef, 0x4b1807e3, + 0x00380a7a, 0x0734b30a, 0x80dcffff, 0xdbffff00, 0x98059899, 0xe6e8ffff, 0x0600ff68, 0xe5221083, 0x32823233, 0x9a99e323, 0x25068208, 0xff9a99b2, + 0x1b82c9ff, 0x4cc0ff27, 0xb6ffffcc, 0x220e8219, 0x82ce4cf0, 0xccec25ac, 0x069b07cc, 0x9a209183, 0x66209184, 0xa1189182, 0x934c0f95, 0xb3f12c05, + 0xedffff34, 0x088b6666, 0x8a7b067b, 0x532419aa, 0x937d180c, 0x08ae630d, 0x7b079b22, 0x176c2419, 0x2506ee7d, 0x32330f00, 0xdc8200ff, 0x1000ff26, + 0x088bcecc, 0x132d9383, 0x42073433, 0xb30f00ff, 0x00ff5432, 0x2195833f, 0x564a4d00, 0x66582505, 0x4800ff66, 0x0021e682, 0x29d98247, 0x00805700, + 0x00ff088b, 0xc3839925, 0x82e62121, 0xa1f328c3, 0xffffa648, 0x82a430eb, 0x82212016, 0x210029ed, 0xff05142e, 0x6666ecff, 0x7018878e, 0x87851000, + 0x867a5421, 0x00ff2587, 0x8bfeff5f, 0x30393a82, 0x14fb0200, 0x608b5615, 0xe6d5ffff, 0xffff8b66, 0x089a19ca, 0x60b6568b, 0x207a83c0, 0x23128335, + 0x9a192a00, 0x09b16e18, 0xff202784, 0x2b841383, 0xff332582, 0xff33334d, 0x34f32300, 0x3c00ff15, 0x00ff9919, 0x82703d12, 0xe6d32f59, 0xddffff67, + 0xffffc2b5, 0xffcdcce2, 0x5d84c8ff, 0x3433c329, 0xffff8b08, 0x4bccccd2, 0xff2605f2, 0xff6866d6, 0x40821a00, 0x33dfff2c, 0xffff0832, 0xff33b3fa, + 0xfd82feff, 0x82faff21, 0x01002614, 0xffffcc4c, 0x234982fb, 0xcecc0300, 0xc4271e82, 0x00ff0080, 0x82cccc35, 0x83c6205f, 0x33ca221a, 0x200a8234, + 0x212a82fb, 0x1a82fbff, 0xe6f8ff24, 0x44828a66, 0xff472126, 0xcccc0200, 0xfa223082, 0x0a829a19, 0xff66e629, 0x856bfcff, 0x830600ff, 0x7800220e, + 0x2c098252, 0xff089a99, 0x0a970500, 0x664f00ff, 0x21448266, 0x0a8257b1, 0x4f840c20, 0xae87f923, 0x2545828c, 0x00ffbac9, 0x8082cc04, 0xc08afe22, + 0x66213082, 0x224f8267, 0x837f8afe, 0x8266200a, 0x46962154, 0xae820982, 0x6605003e, 0x0300ffe9, 0xff0834b3, 0x5c8f4100, 0x192d00ff, 0xffff059a, + 0xff8f82d8, 0xb81e4500, 0xfc210a82, 0x2cb582c0, 0xffa4b005, 0xcd8c0000, 0x190700ff, 0x21588298, 0x7e827b14, 0x82ba1e21, 0x17042234, 0x200a820a, + 0x204e8321, 0x221e82cc, 0x822a1c02, 0x1f452558, 0x19feffff, 0x4c21a383, 0x2dbd8226, 0x0548e1e8, 0x661d00ff, 0x4900ff67, 0xd258c2f5, 0xfd062207, + 0x21398270, 0x6982cccc, 0x34b30524, 0x5b82088b, 0x8b008022, 0x87201284, 0x2206ca58, 0x829002f9, 0x30388316, 0x3e0ab6ff, 0xf7ef0e05, 0x1534f8d4, + 0x193400ff, 0x2a28829a, 0xff9a992f, 0x3433d6ff, 0x832200ff, 0xccc922e8, 0x282c82cc, 0x06008081, 0xe61e00ff, 0x20208268, 0x27ab8219, 0x66e6e6ff, + 0xe1ffff8b, 0x1d7cb419, 0x6866b825, 0x84eeffff, 0x19e921fa, 0xe1205582, 0xde315a83, 0xffff0080, 0xff9899e8, 0x66e6daff, 0x66f3ffff, 0x265f8268, + 0x0798994c, 0x821300ff, 0x1000211f, 0x00283482, 0xff66660c, 0x32b31700, 0x1a236e82, 0x820834b3, 0x83312006, 0x82d42036, 0x55002104, 0xcb209683, + 0x0828d482, 0xff608b56, 0x3433aaff, 0xce218982, 0x051e5780, 0x0c223783, 0x6182cd4c, 0x00327082, 0xff33b313, 0x9a99efff, 0xb3ffff08, 0xff076666, + 0x6183d9ff, 0x45820c20, 0x4cdfff23, 0x826182cc, 0xe9ff210e, 0x00212e82, 0x223f821e, 0x82b8ffff, 0x11002c2f, 0xff05cccc, 0x7b94caff, 0x190d00ff, + 0x2629f4b4, 0x069a1981, 0x832200ff, 0x33362740, 0x2f00ff34, 0x2e719999, 0x34003005, 0x088b9a99, 0x9cfb078b, 0xff1524fb, 0x1994fbff, 0x212d94b4, + 0xcc82cc1f, 0x9a19f822, 0xfb2a9282, 0x00ff66e6, 0xff98990e, 0x0983fcff, 0x00800f29, 0x0f00ff8b, 0x820868e6, 0x19242506, 0x0c00ff98, 0x2d23c983, + 0x82ff0180, 0x228282f8, 0x8233332b, 0xe6982af8, 0x01ff0666, 0x8b34b3a8, 0x23178315, 0xd4ffff32, 0x00215282, 0x26fa830b, 0x8bff7fd2, 0x83dbffff, + 0xff7b2642, 0xccccfdff, 0x050873ff, 0xceccfb2e, 0x4cf1ffff, 0x00ff08ce, 0x9366e61f, 0x13c2b419, 0x8207e021, 0x66042275, 0x248c8266, 0x00ff6866, + 0x234e8303, 0x8b9899fb, 0xb3277183, 0xffff0634, 0x82cc4c3f, 0x07f444f0, 0x184c0e21, 0x2f239151, 0x4b0754fb, 0x0754f706, 0x94f7ef0e, 0x54fb158b, + 0x60096072, 0x94200e0e, 0x9b197d83, 0xf728132c, 0x14fc0654, 0xeb54fb07, 0x2009a252, 0xed9e1954, 0x06cb210c, 0x0bb77418, 0x14595718, 0xb3f1ff23, + 0x05a14533, 0x4ceeff22, 0x105e4318, 0x7c561d82, 0x26ae8207, 0xb4f774f7, 0x18b4f715, 0x290e30a7, 0xff8b9a59, 0x66a6dcff, 0xa883fb08, 0x4952ff20, + 0x06b42714, 0x0e0714f8, 0x651970fb, 0x54201bbd, 0xfc215797, 0x31436114, 0xcb226e82, 0x62483cfb, 0x22df8205, 0x4800c00a, 0x0d260636, 0x088b0040, + 0x6b8224f7, 0x200cc848, 0x05bf4833, 0x48db0821, 0x9a5c1764, 0x0a03480e, 0x9b073b25, 0x5c150cfb, 0xb74c0590, 0x10f65906, 0x40f5ff23, 0x211b8200, + 0xde5c34b3, 0xc95e1905, 0xce14190c, 0x86002011, 0x85cc20ae, 0x8b082254, 0x0d7b196b, 0xad30a10c, 0xabdb218c, 0x490c5a59, 0xb9180ad6, 0xe2191947, + 0xbd852a48, 0x6a4a30aa, 0x55761805, 0x20858509, 0x408c9608, 0xfb24bdbd, 0x15e4f704, 0x0d145818, 0x08a04718, 0x6b061b58, 0xf82a05eb, 0x00ff0ad7, + 0x8bcdcc08, 0x225bcb08, 0x1828200e, 0x2e1e09d2, 0xef0e064b, 0x01ffabf8, 0x1552f8b8, 0x190900ff, 0x2b154319, 0xffcb08c6, 0x4e02c0ff, 0x0500ff05, + 0xff232182, 0x470080fb, 0xe3210740, 0x238882d6, 0x08d8a3f9, 0xa1240683, 0xfdffff48, 0xff301b82, 0xff28dcf9, 0x9899faff, 0x66fcffff, 0x4b4b0866, + 0x0e03ba18, 0x2c82d020, 0x1d82f620, 0x1c699a19, 0xff243882, 0x98191700, 0xe6210482, 0x23408266, 0x8b68e651, 0x3f5d0682, 0xe609280a, 0x00ff8b66, + 0x60c4350d, 0xb3200900, 0x220c1c50, 0x83ae00ff, 0xe300223f, 0x273882d6, 0xff68e6e8, 0x48211600, 0xf6200a82, 0x09222683, 0xa34db85e, 0x09002306, + 0xba18cc4c, 0xfe3308f0, 0xff9a1951, 0x14ee8efe, 0xe9ffff15, 0xffff0ad7, 0x829a19e8, 0x28ad26f7, 0x0000fff6, 0x238882e6, 0x32330e00, 0x09233882, + 0x18ffcecc, 0x820add77, 0xe6f127d1, 0xf6ffff66, 0x04823233, 0xff2d4282, 0x8bceccf1, 0x52ffff08, 0xffff99d9, 0x234384ff, 0x74672616, 0x2e194a82, + 0xff24183d, 0x0080f7ff, 0x0e581919, 0x41ff4721, 0xbf230624, 0x82cbbeff, 0x7ffb22ba, 0x066246be, 0xc178fd23, 0x06b249ff, 0xff140027, 0xcc4c0700, + 0x20968208, 0x23418205, 0x6d870200, 0x04291a86, 0x00ff4280, 0x08008004, 0x233c82cb, 0xb95e0900, 0xec83e782, 0x33330f22, 0x26d22e19, 0x82068b3b, + 0x193801ff, 0x00ff159a, 0x06ccccf2, 0x33fcffff, 0xf8ffff34, 0xffffecd1, 0x22f083fd, 0x820ad7f7, 0x3df823fb, 0x06820870, 0x6666e225, 0x821700ff, + 0xe9ff2260, 0x06b56699, 0x00ff0826, 0x8b9a1961, 0x0320f782, 0xed201783, 0x0a241783, 0xff7c0080, 0x22050660, 0x829a99f6, 0xb3012121, 0xfd205382, + 0x01221a83, 0x5882feff, 0xff32b326, 0x9c190200, 0xcc210982, 0x201e82ce, 0x23398314, 0xac32b3eb, 0x0b83b382, 0x4c140022, 0x13201683, 0x00298982, + 0x05cc4c13, 0x8029ffff, 0x17064600, 0x0effff2d, 0xff069a19, 0xcccc0300, 0x830700ff, 0x83012032, 0x19082204, 0x204d8298, 0x827e8209, 0xcc1b2306, + 0xb285ffce, 0x32331824, 0xc682ffff, 0xff088b24, 0x31829fff, 0x2105ba41, 0x9b83fcff, 0x0080112b, 0x99f5ffff, 0xffff9a9a, 0x230a82f1, 0x66660900, + 0xfe202582, 0x00219c82, 0x27f88202, 0x0000feff, 0x4c0200ff, 0xfd224a82, 0x098266e6, 0x82323321, 0xb3eb231e, 0xaf83ff33, 0xdfffff2a, 0xff8b3d0a, + 0xa4b0ebff, 0xb3200482, 0xde2a1a84, 0xecffffb8, 0xff0534b3, 0xbf84d600, 0x14428618, 0x8b078b2a, 0xff1514fb, 0x34332400, 0xcd21a984, 0x591119ff, + 0xffff310a, 0x06ffffbf, 0x01ff074b, 0xfb66e6c0, 0x07cb1554, 0x0bc72619, 0x270a0362, 0xffff06cb, 0xab9a191f, 0x35224882, 0xd56066e6, 0x66e62209, + 0x0baf4c60, 0x3115eb4c, 0xd601ff0e, 0x01ff34b3, 0x151a8fb6, 0xfcffff8e, 0xdd8276f3, 0xff28f682, 0xff707dfc, 0x9a990100, 0x40221382, 0x0a820800, + 0x84008021, 0x23e7820a, 0xff66e6fb, 0x2a051b6e, 0x0834b3fb, 0xe6ffffff, 0x182b0766, 0x242e1660, 0xb31200ff, 0x20d18234, 0x28618396, 0x0532b396, + 0x33f4ffff, 0x20048232, 0x20718219, 0x2c0483ed, 0xffcd4cff, 0xce4cf3ff, 0xe60a00ff, 0x21658266, 0x7582e6a3, 0x33334e22, 0xa5272982, 0xffff51b8, + 0x82cdccb1, 0x97f2220a, 0x064a560a, 0x3dcaeb22, 0xf420b086, 0x0022aa82, 0x3483660d, 0x67200a86, 0x8f241982, 0x1400ff5c, 0x00236282, 0x56f6680d, + 0x00240668, 0xebae0770, 0x0af14b18, 0x4b189a20, 0x592109f1, 0x28d7827f, 0x05ce4cb3, 0x665400ff, 0x20048368, 0x226d8266, 0x18cc4ced, 0x4e0ee94c, + 0x7b181070, 0x5f3d1015, 0xff069a19, 0x32b30900, 0xffff938b, 0xff2e72fc, 0xcecc0500, 0x3ffaffff, 0x00ff08be, 0x2ce98400, 0xff052edd, 0xcc4c29fe, + 0x70d9feff, 0x09e45be6, 0x7c197d20, 0xf8210cb5, 0x18e45b34, 0xab183420, 0xfc2017a6, 0xab183382, 0x34271624, 0x34fbbb07, 0x1906bb15, 0x2708470d, + 0x00ff8f82, 0xff008015, 0x702f2f82, 0x075b088b, 0x1534f78b, 0x00ff075b, 0x8290821a, 0x86152023, 0x272e858c, 0xf8065b08, 0x1504fb34, 0x80252c82, + 0xffff8b00, 0x633783ea, 0xbb2609c2, 0x5b07bb06, 0xc98204f7, 0x1486d818, 0x06231c82, 0x827b34fb, 0x09645c3d, 0x690acf42, 0xb32208c8, 0x1683ff33, + 0x2300ff22, 0x20070165, 0x227e82cc, 0x4334b31c, 0x11820b26, 0xd3592320, 0x84cc2005, 0x05244316, 0xf70e0824, 0x8084f894, 0x2106655f, 0x655fffcd, + 0x8b332207, 0x0bbb5d08, 0xd1230023, 0x234382ec, 0x08142e2c, 0x08270682, 0x00ff04d6, 0x82333307, 0xfc292104, 0x24067747, 0x332c00ff, 0x211b8233, + 0x4482cc23, 0x0929b618, 0xcb2cfb22, 0x670c3e49, 0xec660a00, 0x66ff2005, 0x5b200fe5, 0x660e9862, 0xbb231fe4, 0x9b43ab06, 0x055c6962, 0x0cbdc418, + 0x8e04fb21, 0x0cfc6263, 0x67004021, 0xf7251048, 0x2b230604, 0x16196315, 0x2d4bbb20, 0x0f7e4a0c, 0xe0873320, 0x20059e6b, 0x055c7e33, 0xd583f220, + 0x4b07f64a, 0xf723075d, 0x833cf784, 0x065e4164, 0x5e413420, 0x8bcc2408, 0x1800ff08, 0x41175f60, 0xcc2006ba, 0x2008ba41, 0x05ba4134, 0xff8bcc25, + 0x8233dcff, 0x09ba4144, 0x4b64f722, 0x52615f82, 0xffff2314, 0x3192ccd3, 0xa309ec41, 0xfb3b228d, 0xbdad1824, 0x130f190c, 0xa0b8180a, 0xcccc2408, + 0x832300ff, 0x82cf8304, 0x0bf961d6, 0x0b994918, 0xbf858e82, 0x9d84c484, 0xeb5b0822, 0x9f0e2a62, 0xf9621830, 0x228ca10b, 0x4a2b44fb, 0x31940c6c, + 0xbe88cd20, 0x848b3321, 0x07406cbe, 0x180a3360, 0x200913ba, 0x27c38633, 0x8bcdccd3, 0x3b44fb08, 0x01b60410, 0xffef3846, 0xcc4cae01, 0x33c8ffff, + 0xc35b1534, 0xfcffff05, 0x00ff9a19, 0x49666604, 0x00360593, 0x8b32b305, 0x00ff0891, 0x07686637, 0xcce6ffff, 0x1f00ffce, 0x27829899, 0x68e6c027, + 0xffff8b07, 0x5e8c19ee, 0x99f12308, 0xe055ff9a, 0x0dc55505, 0x080b8a19, 0x3f00ff24, 0x44829819, 0x2883e820, 0x6866e022, 0xc8254482, 0x8b079899, + 0x236a8585, 0xce4cfaff, 0xff2a7e85, 0x089a99fb, 0xffcfffff, 0x238253ff, 0x6766f72f, 0xff8a7c81, 0x3333f6ff, 0xe60800ff, 0x87198266, 0x5cff200a, + 0x0f20053a, 0x00318382, 0x9533b308, 0x00ffb508, 0x059a1931, 0xb33600ff, 0x2b9d8234, 0x00800500, 0xcc0100ff, 0x0500ffcd, 0x0021e482, 0x22288303, + 0x82cc4c04, 0x824120cf, 0x56002184, 0x00238483, 0x82cc4c00, 0x827b2095, 0x86ff232a, 0x71823433, 0xe1fac62f, 0x33c4ffff, 0x9effff32, 0x00ff986b, + 0x8235822a, 0xffec2369, 0xe2495400, 0xe62f3105, 0x2200ff66, 0x00ff1f05, 0xff676628, 0x7b542d00, 0xe6215f82, 0x22558267, 0x4c34f398, 0xd7200763, + 0x3a5cae83, 0x83f82005, 0xcc07210a, 0xfe20dd82, 0x0c202f83, 0x99848a83, 0x34b30922, 0x17203482, 0x29224e83, 0x798270bd, 0x82ccd921, 0xe13229aa, + 0xff830548, 0xd6a30a00, 0x2305f874, 0xae470f00, 0x4c200e82, 0x08221a82, 0x3082ca36, 0xef840a20, 0xff4c3724, 0x2f820e00, 0x09feff29, 0xffff9378, + 0x82305df5, 0x0030281a, 0xc0ffff01, 0x8305c816, 0xff662991, 0x4821f8ff, 0xb30000ff, 0xf530ca82, 0xffff5238, 0xff9a19fb, 0xd663f7ff, 0xe9ffff08, + 0xff238a82, 0x829a99d8, 0x82312029, 0xcdff225a, 0x25fa82b3, 0x32332600, 0x57828b07, 0x0b209283, 0x00262c82, 0xff00800c, 0x0e830c00, 0xfc820320, + 0x3900ff24, 0x2083862b, 0x846b0425, 0x830400ff, 0x9403251b, 0x0300ff7c, 0x22054157, 0x82cc4c05, 0xb302283c, 0xfcffff34, 0x828b846b, 0x7c94216f, + 0xc6236a82, 0x82077ad4, 0x20858353, 0x25ba83fc, 0xffce4c09, 0x3282f3ff, 0xf1ffff24, 0x20829a19, 0xceccd922, 0x33202082, 0x32236f83, 0x8305cc4c, + 0xff66259c, 0x66662700, 0xb2830a82, 0x9c080023, 0x23c6852a, 0xaec70a00, 0x0031da85, 0x08b8de07, 0x3f00ffbb, 0x930538e9, 0xa20a00ff, 0x266282d0, + 0x00ffcecc, 0x8246f601, 0x2467820e, 0xb4c8f7ff, 0x210a8208, 0xf382cc4c, 0x8278c921, 0x68e62c19, 0xb5f0ffff, 0xffff83c4, 0x84b85ef5, 0x261a8277, + 0x05b81ecd, 0x821700ff, 0xd6ff23e2, 0x0a829042, 0xd6820520, 0x83f6ff21, 0x83fe2035, 0x66f32045, 0x4166053c, 0x21348205, 0x0a8233d7, 0x9a19d722, + 0x98222982, 0xd44d64e6, 0x832c2007, 0x19fa2534, 0x2200ff99, 0xd7226583, 0xfe829999, 0xdd82d020, 0xab200682, 0x9e214683, 0x2c7c8266, 0xff9a99d5, + 0xfeffc6ff, 0xcc3b00ff, 0x204b82ce, 0x225b8279, 0x83cc7900, 0xb3ff26f2, 0x00ff0734, 0x222a8343, 0x829899a9, 0x8303205c, 0x83fb200a, 0x82012020, + 0x70ff20d6, 0xfa220590, 0x36820080, 0xcc4cc929, 0xffffb507, 0x8266e6ce, 0xb3082327, 0x08438132, 0xf0ff2105, 0xf6205e83, 0xf7209f83, 0xff207982, + 0x8205414e, 0x8c7c310a, 0x66f7ffff, 0x8b089566, 0xef0e058b, 0xcca800ff, 0x23056066, 0xf8ffff15, 0x0320b283, 0xfc20fc83, 0x002a1482, 0x8f32b309, + 0xe60700ff, 0x04570868, 0x843c2006, 0x192d2d8b, 0xff8b079a, 0xce4c0300, 0x990200ff, 0x0424e482, 0x8e8e9819, 0x3a222382, 0xcb826766, 0x82ce4c21, + 0x33172687, 0xffff0733, 0x2c4f828c, 0x99199bff, 0xccffff05, 0xffffb89e, 0x27bb83cb, 0xff142ea8, 0x66662400, 0x48204282, 0x20054243, 0x21268229, + 0x20821e00, 0x83220021, 0xca28254e, 0x0500ff3e, 0x0026b383, 0xffd7e39f, 0xd9831700, 0x80ceff26, 0x2900ff00, 0xff215c83, 0x27a182fa, 0x32330400, + 0x0600ff89, 0x02220a83, 0x09829a19, 0x82ce4c21, 0x830d2082, 0xae292b0f, 0xff6e0514, 0xec113a00, 0xbf838705, 0xac826620, 0xff333326, 0xee9c0900, + 0xa4820e83, 0xb6f30322, 0x07202c82, 0x0a822c83, 0xb3251982, 0xfcffff33, 0x2ed082cb, 0xff67e603, 0x8c18f8ff, 0xffffab08, 0x824200c0, 0x820120ca, + 0xfcff3025, 0x00ff3233, 0xffcd4c00, 0x2a9cfbff, 0x83feffff, 0xf8fb262f, 0xffff0852, 0x23f482f3, 0x285cdaff, 0x2c202982, 0xff23a282, 0x823433da, + 0x9916230a, 0xe082079a, 0xcccc0e24, 0x3643ff96, 0xb30d2105, 0x04224182, 0x77820080, 0x166e2a22, 0x31431c83, 0x34b32105, 0xa8219d82, 0x220482f4, + 0x828b9a99, 0x6605221c, 0x20388266, 0x24168203, 0x0c57fcff, 0x8370828b, 0xd5ff2733, 0xff07ea91, 0x44820d00, 0x22052551, 0x43343309, 0x33210836, + 0x22878234, 0x826666e9, 0x4c2e2820, 0x2500ffcc, 0x8205cccc, 0x8266201c, 0xa32522f7, 0x200a82d8, 0x234d82fe, 0xae070400, 0x1f82c283, 0xd6630422, + 0x2605ff42, 0xcecc0300, 0x82cbab08, 0x820320af, 0x070026e4, 0x00ff44e7, 0x2d628209, 0x20340300, 0xe60700ff, 0xfcffff68, 0x29414a0c, 0x200a8206, + 0x33a5828c, 0xffff3233, 0x87d062f6, 0x19f8ffff, 0xff6e089a, 0x14eec5ff, 0x0d204082, 0xd6222c83, 0x0a82ec51, 0x98190228, 0xb3f9ffff, 0x05828932, + 0xff9a1924, 0x1a83faff, 0x6982fb20, 0xceffff29, 0xffff0080, 0x8232b3d6, 0x829f2025, 0x06035171, 0xa9821620, 0x33fdff27, 0x1300ff33, 0x2a728266, + 0xffcd4cf4, 0x64e60c00, 0x82efffff, 0x82ff2061, 0x56e21819, 0x99fd2107, 0xfd225982, 0x13829919, 0xcc219b84, 0x22f882cd, 0x826866f7, 0x83f12015, + 0x830920f8, 0x4cef2348, 0x16828bcc, 0xff240683, 0xce4cf1ff, 0x9920ae82, 0xf7238582, 0x847e6666, 0x8466202d, 0x0f03192d, 0x202d8607, 0x233482ea, + 0xb3edffff, 0xf0226982, 0xb382cdcc, 0xec22b883, 0x31823333, 0x5982f520, 0xccfcff22, 0xb2834783, 0xdd84f920, 0x8268e622, 0xd6201a82, 0x002d1082, + 0x05010023, 0xcce8ffff, 0x00ff07cd, 0x222b8321, 0x829a99df, 0xb3ff2210, 0x61941834, 0xffff250b, 0x08ccccfe, 0x23062347, 0x00800800, 0x8a829b84, + 0xcc4cf827, 0xffff8708, 0x201183fc, 0x23bf83fc, 0x8834b3fc, 0x66210f82, 0x2a608266, 0xff3433d4, 0x66e62a00, 0x83075905, 0x20cc833a, 0x22cc83f2, + 0x4732b3f1, 0x4c30145e, 0x00ff8bce, 0x0832b311, 0xffff07bd, 0x6b66e6e0, 0xd7228882, 0x3c830080, 0x3783fc20, 0x6083ff20, 0x0983fd20, 0x67e6fe25, + 0x82fdffff, 0x4b6b2129, 0xfc252382, 0xffff9919, 0x21f383f8, 0xfd824cf6, 0x0e82ed84, 0x8b088f26, 0x5701ff07, 0xcf228483, 0x244a3233, 0xcc7b190d, + 0x077b2409, 0x829b06bb, 0x07002462, 0x51ff66e6, 0x08200509, 0x00214a82, 0x9b6d1808, 0xcea7180f, 0x077b220a, 0x0d196a9b, 0xe8824e89, 0xe883f620, + 0xccccf825, 0x83f9ffff, 0x33f727e8, 0x7b088b34, 0x33e65b06, 0xcb827b20, 0x8293ff20, 0x180cf64a, 0x220969a8, 0x5e5b079b, 0x33e005c4, 0xa9187b20, + 0xa8180c1d, 0x7c4111ec, 0x069b230f, 0x33e507bb, 0x4231ff41, 0x8b2f1a33, 0x04fbcb07, 0x5b07bb15, 0xbb075b06, 0x883b8b06, 0x14fb240a, 0x831514f7, + 0x821b8313, 0x080a8717, 0xffaf0e27, 0x9a199000, 0xcc0c01ff, 0x00ff15cc, 0xff33b31d, 0x00803300, 0xcc3600ff, 0x1f00ffcd, 0x00ff34b3, 0x8b66663b, + 0x83068508, 0xffce2516, 0xcc4ce0ff, 0x32252a83, 0x80ccffff, 0x2b1a8200, 0xff02806c, 0x343343ff, 0x0c00ff05, 0xff231a82, 0x5b9a99ea, 0xe52706ab, + 0xffff6666, 0x826866e7, 0x3efe2440, 0x8206289c, 0xd763220c, 0x241c828b, 0x00ff299c, 0x2826821a, 0x8f420c00, 0x661500ff, 0x20468366, 0x288c8287, + 0x05ccccbc, 0x44f8ef0e, 0x5f0119f8, 0x24fb2218, 0x4a5d1907, 0xffff2a66, 0x06343386, 0x800000ff, 0x20048200, 0x85f482cc, 0x34b32109, 0xd9820e82, + 0xcc000023, 0x20b782cc, 0x21c7830b, 0xf3821915, 0x9899ff25, 0x821900ff, 0xf3ff211e, 0x14273283, 0xff080080, 0x8233b6ff, 0x667a222e, 0x05147966, + 0x790cbb43, 0xc0660ce2, 0x066b2616, 0xccfcffff, 0x694018cc, 0x20678308, 0x275d82fd, 0x6666feff, 0xb8ffff08, 0x76207c83, 0x5c205d84, 0x19055d48, + 0x2413a58f, 0x4b058beb, 0x0c094f4b, 0x58f8ff21, 0x8d7a08b7, 0xff34230b, 0xe883f8ff, 0x71820820, 0x826e0820, 0x21ac900d, 0x2c860ad7, 0x5e190720, + 0x7b230a13, 0x191524fb, 0x444ae25d, 0xcf4e0b38, 0x076b240a, 0x852b34f7, 0xa11f1967, 0x82b69e11, 0x21e385de, 0xed823307, 0x3433f722, 0x11ca5e19, + 0x7884fc82, 0x076b0822, 0x20ca5e19, 0xaa297fc7, 0xffff66e6, 0x159a1995, 0x053964ff, 0x3233f533, 0x4c0000ff, 0xf2ffffce, 0xffff0080, 0x8066e6f9, + 0x55068508, 0xf9200638, 0x2607c748, 0x84feff08, 0x8206c2f5, 0xd7a32728, 0xf5ffff8b, 0x42826666, 0xf924e583, 0x08966de7, 0xe7223382, 0x4a82962b, + 0xffbe3f24, 0x4a820d00, 0x002f5e84, 0x08cecc0a, 0x8bbd00ff, 0x3a01ff44, 0x82053233, 0xcc4c2631, 0x660a00ff, 0x82048268, 0x06002158, 0x0c2b0e83, + 0x088b66e6, 0x00ff8b97, 0x829a190b, 0x82b32047, 0x231783eb, 0x9899f5ff, 0x4c823c83, 0xccc5fe2f, 0xffff05ce, 0xf7343324, 0xffff15a2, 0x233582b7, + 0x9a1986ff, 0x17204f82, 0xff262d82, 0x05ccccd6, 0x0d82cbbb, 0x32b33d26, 0xc3ffff06, 0x0021ce82, 0x251e8263, 0x74f8ef0e, 0xbf1904f8, 0xad820950, + 0xd1230023, 0x055352ec, 0x511a5a52, 0x28521383, 0xcccc210d, 0x2c2aae82, 0xfc083433, 0x87feff74, 0x638366e6, 0xa8820a20, 0xf6020026, 0x0a00ffc9, + 0x05228083, 0x014f4696, 0xd8002806, 0x01ffbfbf, 0x82d66359, 0x990622a1, 0x211f8299, 0xec820c97, 0xff9a9929, 0x846b0600, 0x4d0c00ff, 0x0683058f, + 0xff231685, 0x827c94f9, 0x32b3261b, 0x68f5ffff, 0x27a882f4, 0xff68e67d, 0x5c4f37ff, 0x30274082, 0x00ff3233, 0x8201004f, 0x3303220a, 0x83258234, + 0x19082150, 0x04204b82, 0x07200483, 0x8305d347, 0x05ea4706, 0xe6fbff25, 0x8300ff66, 0xf9ff231b, 0x4b826766, 0xfeff8327, 0x9927ffff, 0x25408299, + 0xffd0cc05, 0xb683f6ff, 0x98190328, 0xe6f4ffff, 0x05828b66, 0x08cecc22, 0xde260682, 0xffffcc4c, 0x168299e4, 0xa882e420, 0x4cdeff30, 0xff088bd0, + 0x8c02f5fd, 0xe1ffff06, 0x2182b81e, 0x79f8e625, 0x821900ff, 0x08a92233, 0x330082ff, 0x0e058bd9, 0x3902ffaf, 0x00ffcccc, 0x153333e8, 0x660b00ff, + 0xd52ab582, 0xffffcd4c, 0xff34b3e6, 0x9f82d4ff, 0x83d5ff21, 0x99f42256, 0x2032829a, 0x837882f0, 0x7a05269d, 0x66fbffff, 0x059d5066, 0x830a0021, + 0x220e8325, 0x83191100, 0x83e62025, 0xff5d2c4f, 0xfeff05ff, 0xffceccad, 0x8280a8ff, 0x60ff34fa, 0xff07cccc, 0x34332a00, 0x3500ff06, 0x00ff9919, + 0x8234b397, 0x824920d0, 0x14002467, 0x82053233, 0x99992672, 0x19b4ffff, 0x2315829a, 0x06999942, 0x9a25cb83, 0x664e00ff, 0x20108266, 0x2163823e, + 0x1b851000, 0xff233182, 0x82008041, 0x4c892215, 0x204d82cc, 0x9fb71811, 0x165a7513, 0x0f0fb918, 0xcc4c0e25, 0x8200ff8b, 0x85082041, 0x00ff2306, + 0xf519540e, 0x9b230c37, 0x7d9cf706, 0xd92230dc, 0xeb826666, 0x33338426, 0x332200ff, 0x0d23e583, 0x82b29a99, 0x800427af, 0x0c00ff00, 0x0482cccc, + 0xff991925, 0x82990800, 0x231a82df, 0x00ff088b, 0x16830683, 0x2105564b, 0x2a8300ff, 0x33f3ff23, 0x271a8234, 0xffcc4c06, 0x66e6edff, 0x6c274082, + 0x05a7cc4c, 0x83e7ffff, 0x755b2247, 0x220a82c2, 0x826866fb, 0xec1126bf, 0x190a00ff, 0x20098298, 0x225c828c, 0x829a1911, 0x70922140, 0x0f203b82, + 0x04222983, 0x3b821824, 0x6d832a20, 0x9e6f0b31, 0xe62b00ff, 0xe6ffff68, 0x00ffc6ab, 0x1864660b, 0x20071c47, 0x3b298229, 0xe17a65ff, 0x93feff05, + 0xffffce4c, 0x15cdcc17, 0xcc8500ff, 0xffff06cc, 0xabceccf4, 0x90226b82, 0x0c849999, 0x056bcd2d, 0x4cf7ef0e, 0x8b15fcf7, 0x82e1ffff, 0xe6ff236c, + 0x518266e6, 0x0e820483, 0xff23ce82, 0x82eb11e1, 0xeee62b1b, 0x1900ff14, 0xff8b9a19, 0x616c1e00, 0x841e2005, 0x20ae8311, 0x22048319, 0x8215ee1e, + 0x821c832d, 0x82288222, 0x14ee2144, 0xe1223882, 0xbc82ec11, 0x82661821, 0xb3932b55, 0xffff1533, 0xffcd4ce2, 0xc182e5ff, 0x83edff21, 0x7fd92309, + 0xb8828bff, 0x22058467, 0x8234b3dd, 0x208683c9, 0x21c382e0, 0x86831400, 0xcc4ce726, 0xeaffff08, 0x2205a74b, 0x18cc4cee, 0x2009d1ca, 0x131e63ff, + 0x2b0a5163, 0xcc1a00ff, 0xffff07cc, 0x9df628da, 0xd7267282, 0x2600ff0a, 0x9e820080, 0xd2652c20, 0x823d2005, 0x3200265e, 0x00ffd723, 0x2a728232, + 0x29dc3d00, 0x06ab088b, 0x841700ff, 0x191723e6, 0x5578ff99, 0x33122905, 0xf3ffff33, 0x8b083333, 0x6f204c82, 0xce22b983, 0xc9829a99, 0x3d0af626, + 0xccf4ffff, 0xf922ce82, 0x9682c2f5, 0xff243683, 0x08ccccef, 0x0682d082, 0x0600ff24, 0x16843e0a, 0x0900ff24, 0x2a83c3f5, 0xff08ce32, 0x99995400, + 0xff14f807, 0x33b355ff, 0x1500ff15, 0x9f29d782, 0xb31800ff, 0x00ff9734, 0x209d841f, 0x82f08222, 0xcc2a21a4, 0xed20ea82, 0xb482ef82, 0xffff0125, + 0x82ce4ce2, 0x666621cf, 0x12254182, 0x00ff3233, 0x2977820c, 0x34331600, 0x800700ff, 0xb885a300, 0x68e63d22, 0x322b3882, 0xffff9819, 0x8b66e6cd, + 0x51c2ffff, 0xd3200555, 0xff214582, 0x2e4f83e5, 0xff0080d9, 0x3433daff, 0xffff0879, 0x5c3433e5, 0x4b201719, 0x430e4a5b, 0xf726085a, 0x5500ff14, + 0xb88234b3, 0x65820920, 0x830b0021, 0xe6062589, 0x0e00ff68, 0x00246f83, 0x08343310, 0x06828182, 0xf9ffff22, 0x16822083, 0xf6ffff22, 0x0b2f2083, + 0xff083333, 0x6766abff, 0x00ff8307, 0x42cc4cf2, 0x68200a70, 0x21087042, 0x23828b98, 0x9a19e123, 0x4211858b, 0x19231370, 0x4200ff9a, 0x71820570, + 0x13680820, 0x0870420d, 0x83ccfb22, 0x32e7d218, 0x5a126f77, 0xeb5a05b2, 0x7f1c2006, 0xf72308ad, 0x8264fb54, 0x41ff2060, 0xd5201558, 0x22325841, + 0x422a00ff, 0x332705ab, 0xffff9d33, 0x42cdcce5, 0xfc8314ab, 0x8305ab42, 0x06ab24fc, 0x823d00ff, 0x05bf4208, 0x340af241, 0xffff54fb, 0x1534b3d5, + 0x995400ff, 0xff810798, 0xceccf4ff, 0x11a04285, 0x12849120, 0x1e849520, 0x14f70822, 0x15292d84, 0x66abffff, 0x00ff0768, 0x236b8309, 0xffcc4c0b, + 0x22054552, 0x41cccc0e, 0xdf4105d8, 0xff9a220a, 0x06df4100, 0x00ff6634, 0x0832330b, 0xfcf7ef0e, 0x8b150cf8, 0xe8e9ffff, 0x9418fff6, 0x0e820862, + 0x0820a582, 0x16850685, 0x18110021, 0x82086694, 0x17162656, 0x1100ff0a, 0x824582e6, 0x00ff2616, 0x8b9a1916, 0x18068508, 0x2210be94, 0x192b94fb, + 0x22082a54, 0x8567e611, 0x1a31931f, 0x20120b2a, 0x217b859a, 0x8d8de9ff, 0x44849920, 0x19268683, 0x8cf8089a, 0xd9778cfb, 0x10a46d0e, 0x18b3f121, + 0x180c5d7f, 0x46199db0, 0xf8261688, 0x2cfb06d4, 0xc78a8cf7, 0xfe83f983, 0x9820f988, 0xe6203a83, 0x2105bd6a, 0xb183ff8b, 0x06850820, 0x9820c283, + 0x6821c788, 0x0e55418b, 0x081eaf19, 0x5419fb20, 0xd9180bfa, 0x5b200ee5, 0x1778c718, 0x00ff2408, 0x07008026, 0x21e5ffff, 0xceffff48, 0xff059a19, + 0x52b8f9ff, 0x66f4ffff, 0xf1ffff66, 0xffffa470, 0x829a99fb, 0x7b54270e, 0x4c0600ff, 0x0a8808cc, 0x18f65419, 0xff48e13e, 0xce4c4600, 0x0f00ff05, + 0x00ff0a57, 0xffff7f1c, 0x5dcf1d00, 0xcc1100ff, 0x2000ffcd, 0x21053c5e, 0x54199913, 0x112238f6, 0x4683cccc, 0x15f65419, 0x3433ee22, 0x54197782, + 0x332042f6, 0x64294683, 0x80e3ffff, 0x00ff0801, 0x22738225, 0x4bb3b9ff, 0x54190550, 0x802227f6, 0x2a5aff00, 0xb3f92105, 0x0b299482, 0xff089a99, + 0x9819e5ff, 0xf65419ff, 0x0e5e4212, 0x1805ad41, 0x19099d7c, 0x2210a456, 0x419a19e5, 0xb32108ad, 0x07ad4132, 0xad417082, 0xce4c2106, 0x2007ad41, + 0x211482f3, 0x0f820600, 0x83fcff21, 0x850e2009, 0xffcc250e, 0x32b30b00, 0x2420d882, 0x54191982, 0x728325f6, 0xc920b986, 0x430c9847, 0xff240c18, + 0x9a19cfff, 0x8a0e0570, 0xfa5419bd, 0x0a6f415c, 0xdf823320, 0x089a9927, 0x33e4ffff, 0x066f4134, 0xe600002f, 0xd9ffff66, 0x0e050080, 0x24f8abaf, + 0x16dc7d15, 0x6519ff20, 0xea290bf5, 0xff8b9082, 0x707de5ff, 0x21068508, 0x5a61ffff, 0x32bd1905, 0xf3cc180b, 0x707d210a, 0x08295485, 0x00ff078b, + 0x3bcd4c56, 0x21868215, 0xfa71cdcc, 0x83fd2007, 0xb30b26a0, 0xfbffff33, 0x369b8219, 0x99198600, 0x33c8ffff, 0x00ff0532, 0xffce4c0d, 0x9a191400, + 0x411100ff, 0x162108a5, 0x290e8299, 0x0834b309, 0x0400ff96, 0x258266e6, 0xcccc1425, 0x830900ff, 0x831520d1, 0x8304201b, 0x5717200e, 0x2c220524, + 0x66829899, 0x1b822820, 0x82e5ff21, 0x11002c04, 0xffff9819, 0x0866e6d6, 0x820e00ff, 0xdbff2351, 0x40823333, 0x1a821620, 0x4cf5ff23, 0x200a82cd, + 0x583c820f, 0x062505de, 0xffff6866, 0x05f26dec, 0xf0243482, 0xff083433, 0x9c251982, 0x33f0ffff, 0x23198332, 0xf9ffffcc, 0x0e826f82, 0x00ff3423, + 0x22538307, 0x824ce5ff, 0x4c0d2789, 0xffff05ce, 0x1582b3f5, 0x29830520, 0x66e6f725, 0x820800ff, 0xfbff210e, 0x00222e82, 0xe482990a, 0x66f6ff22, + 0x16221482, 0x2982ffff, 0x82b3ec21, 0x80be224e, 0x207d8201, 0x20938331, 0x20d484c9, 0x207e8305, 0x20fa83fa, 0x213f8203, 0x0482f8ff, 0x84010021, + 0x32332409, 0x822fa208, 0x8204202c, 0xeeff236c, 0x6b82cecc, 0x95829920, 0x5c82ee20, 0xe6eeff28, 0xfbffff64, 0xaa82cccc, 0xfb201984, 0x19837683, + 0x820a0021, 0xfaff2170, 0x00204082, 0x2005cf4c, 0x23e882ea, 0x32335800, 0xb9208082, 0x00231a82, 0x829a194d, 0x33f1210a, 0x1020b582, 0xda847582, + 0x4f160021, 0x15210840, 0x21b58219, 0x3f831000, 0x837f3f21, 0x52ff20b5, 0x9a250501, 0xffffff8a, 0x05616899, 0x9a220983, 0x80828008, 0xf0204b84, + 0xf926d783, 0xff7f3333, 0x2183f3ff, 0xaa83f920, 0x0080f022, 0xfe209b82, 0xff235782, 0x823433fc, 0x23928371, 0x3233f3ff, 0x14832482, 0x824cf821, + 0x84f220cf, 0x834c20ec, 0x822482c5, 0x59958256, 0xb5820659, 0x82fcff21, 0x01002223, 0x21908299, 0x588289ff, 0x4c310027, 0x00ff05cd, 0x23348239, + 0x9819fbfe, 0x03230a82, 0x41ff67e6, 0x19200619, 0xee209a82, 0xff241982, 0xff33b3ee, 0x7d824383, 0xcdccee22, 0x19210a82, 0x8223829c, 0x0a002328, + 0x0e8264e6, 0xff33332d, 0xce4c1100, 0x00ff6d08, 0x8266e686, 0x4cf02d98, 0x00ff06cc, 0xff018014, 0xcc4c85ff, 0x02205582, 0x80244684, 0xf4ffff00, + 0xff212c82, 0x260983ef, 0xff9a99ee, 0x8319fdff, 0x87ee228a, 0x270a84ae, 0x82efffff, 0x0b00ff8f, 0x1982a983, 0x66215582, 0x27748268, 0xfff5e8e7, + 0x00809000, 0xfa255982, 0xffff4821, 0x25f283f9, 0xff1f45f7, 0x4383fbff, 0x0040f623, 0x1825828b, 0x250ba1b3, 0xff8bcc4c, 0xe6821200, 0x0714f722, + 0x22260982, 0x00ff6666, 0x0482a61c, 0x30821d20, 0x59230023, 0x2230829a, 0x824c3600, 0x19ff29cb, 0x01ff059a, 0xdb34b329, 0x1809be43, 0x180f5083, + 0x430bc548, 0x306522be, 0x19002008, 0x340af1c0, 0xc4ffff07, 0xfeff34b3, 0x15ccccd7, 0xb32800ff, 0xd3ffff32, 0x217a8299, 0x6d82f1ff, 0xccdbff23, + 0x20dc82ce, 0x209c82fd, 0x50a719ff, 0x83fa2009, 0x82fb2019, 0xfbff23ba, 0xe0820080, 0xce4cc227, 0x4cc2ffff, 0x792982cc, 0x9b181aec, 0x3b201a85, + 0x00284082, 0x0566663b, 0x3e00ffa4, 0xff250682, 0x98190200, 0x26058288, 0xffff6866, 0x823433fd, 0x31728309, 0x083233fd, 0xaf0e068b, 0x19f001ff, + 0xa701ff9a, 0xb18290c2, 0x0a820520, 0x2511002d, 0x1100ffa2, 0x00ff6466, 0x828a6c0a, 0x24328209, 0xbcb6fbff, 0x220a8208, 0x82ff9c19, 0x8294200a, + 0x201e8219, 0x6a0c1aff, 0x4cf7320f, 0xddffffcc, 0x80054821, 0x07d4ffff, 0xe2ffffae, 0x20cb82cc, 0x2ddb83dc, 0xff66e6d9, 0x68e6ebff, 0xcefeff08, + 0x4a4ccc4c, 0xf4401817, 0x18f72016, 0x461052e2, 0xa2180e3a, 0x34460b83, 0x31012609, 0xff0734b3, 0x237a83ff, 0x98191400, 0x003e8e85, 0xff9a9923, + 0xfffff4ff, 0xf82b00ff, 0xffff0852, 0xff6766f6, 0xb8de2200, 0xfcffff05, 0xe3829999, 0x83d82321, 0x221482de, 0x82c46011, 0x9a19260e, 0x490400ff, + 0x0371186c, 0x49042207, 0x83148244, 0x93f522d2, 0x20198276, 0x228a8233, 0x825edaee, 0xcc08211e, 0x2322fd83, 0x3e8205d6, 0xff263482, 0xff9082d7, + 0x29832400, 0x707de425, 0x742900ff, 0x068305e0, 0x00211685, 0x2020831b, 0x232a820a, 0x707d2800, 0x23061a5c, 0x2adc2200, 0x6f318982, 0xffff66e6, + 0x15d623e9, 0x1900ff8b, 0x00ff2a9c, 0x05ad4215, 0x00ff9823, 0x1263191a, 0x68822811, 0xe6ffff8b, 0x8208d663, 0x97e42206, 0x066c460a, 0xf668eb22, + 0x139fc319, 0x0a971422, 0x1b2f5482, 0x8b08f668, 0xc0feff07, 0xffff9002, 0x469a19ff, 0x902114d5, 0x2295828b, 0x19717d1a, 0x46114d1d, 0x822112d5, + 0x202d828f, 0xcc9419ff, 0x0cd5460b, 0xa4b04829, 0x00ff153b, 0x8267661b, 0x80192d4d, 0x00ff7d00, 0xff99990e, 0x66e6e8ff, 0x252d6482, 0xffff6766, + 0x059a19c5, 0x661e00ff, 0x0fdc5166, 0x0e1bb818, 0x0fff8918, 0x80065b22, 0xf5358f82, 0x00ff66e6, 0xff9a9905, 0x3433f9ff, 0x4c0900ff, 0xffff08cc, + 0x271483f3, 0x05676614, 0xb31cffff, 0x4a09c979, 0x1b500ee3, 0xb44c1905, 0x10764210, 0x8314ae21, 0x82342023, 0xeb51212e, 0x210a8b44, 0xcb82cdac, + 0x30097642, 0x6666bf00, 0xffffff07, 0x00ffb8fe, 0x05008001, 0x0a9b44eb, 0x00ff6722, 0x220b9b44, 0x8233b320, 0x29f68228, 0x02ffef0e, 0xf700806f, + 0x4a8215b0, 0xff989925, 0x8266f7ff, 0x800625cd, 0xecffff00, 0xf6200483, 0xf0220483, 0xd2829a99, 0xd04cf822, 0x1e828582, 0xf9201985, 0x98201985, + 0x8037f182, 0xfeff0800, 0xff9a99ee, 0x727d9600, 0xf0feff05, 0xffffa470, 0x828e8269, 0x8cf022fc, 0x053f54cd, 0x85ecff25, 0x8400ff1f, 0x6af72258, + 0x836c833d, 0x6af72253, 0x05fc4ac0, 0x90050026, 0x1300ffe5, 0x00265382, 0xffb6730f, 0x72830800, 0x0a200129, 0x9f00ff3e, 0x820516f9, 0x275e8364, + 0xff785e05, 0xcccc0b00, 0x2c059d6d, 0xa1faffff, 0xb4f70888, 0x0660ffff, 0x237682ea, 0x679a99a7, 0x2308ae4c, 0xffcccc12, 0x2105ad4d, 0x62193315, + 0xa64c111b, 0xff7a2505, 0x9a19eeff, 0x105ba218, 0x20099e4c, 0x09c64d44, 0xcdcc1222, 0x62194fb3, 0x07260d67, 0xffaf01ff, 0x62198bfe, 0xff240c96, + 0x0200e9ff, 0x0fdea218, 0xf04d8288, 0x00ff2105, 0xff20ce8e, 0x11706219, 0xcbfeff2a, 0xffffcecc, 0x159a993c, 0x200b444a, 0xab6019ff, 0x4299200d, + 0xed220648, 0x73836766, 0x015d6211, 0x0af64b75, 0x2208664d, 0x4d3033e4, 0xfa7d1366, 0x00d02210, 0x19ac4c02, 0x2b5d6219, 0x4c48664d, 0xff2009b0, + 0x210b664d, 0x097e99f2, 0x995b200c, 0x6e624db5, 0x0e068b25, 0x4d24f7ef, 0x90490b4f, 0xff733052, 0x9a192fff, 0xe3ffff15, 0xffff146e, 0x196666d0, + 0x2823b6c2, 0x0900ff99, 0xffff9a19, 0x230482fb, 0x98991300, 0x002d0e85, 0x0834330f, 0x473a00ff, 0x6000ffae, 0x354882e6, 0x9a591100, 0xe61c00ff, + 0x1f00ff66, 0x00ff3333, 0xff34b311, 0xe5472100, 0xcc1d2305, 0x0c8506cc, 0x32251c83, 0x4ceeffff, 0x212182cc, 0x89826866, 0x839a1921, 0x82332046, + 0x199f2314, 0x5c85059a, 0xccf0ff23, 0x217085cc, 0x2483ecff, 0xd618f020, 0x1984095a, 0x0f83f620, 0x00211983, 0x22198604, 0x830f00ff, 0xe3ff2248, + 0x217f8266, 0x4882992f, 0xe640ff26, 0xecf70766, 0x180f3c47, 0x470e5fc2, 0x90520f3c, 0x06e32530, 0xbf00ff8b, 0xdb21b982, 0x277183ff, 0x7b07eb15, + 0x9b072b06, 0xc1207682, 0x79228a83, 0x52196666, 0x6a191bc4, 0x19201cda, 0xff2a4082, 0x0532b3e6, 0xb3f200ff, 0x8d180734, 0xff2a2d51, 0xcc4c0dff, + 0x1900ff07, 0x04826866, 0x82ce4c21, 0x8fa61844, 0x1830200b, 0x210e5ba5, 0xa5180080, 0x0f850e5b, 0x3b3b0823, 0x69a51805, 0xffff2509, 0x8bcccceb, + 0xb8842884, 0xdb3b0823, 0xb5021005, 0x012ace01, 0xff98998e, 0x9a994601, 0x5519ff15, 0xd020273e, 0x220b1142, 0x82e6ffff, 0x19002440, 0x4205ce4c, + 0x815c0581, 0x16da4c16, 0x8305e942, 0x829a2044, 0x32b32104, 0x2009f54d, 0x107c4200, 0x1a7ba918, 0x00ffdb25, 0x42ae0750, 0x7d2708f2, 0x1400ff70, + 0x188b3433, 0x2d074a48, 0xdb089082, 0xf8afffff, 0x2f0e0552, 0x685f24f7, 0xffcd210c, 0x2007685f, 0x1bc37133, 0x2017685f, 0x22ee82cd, 0x823333dc, + 0x08685f44, 0x2401ff32, 0xfeffcccc, 0x153433d1, 0xb3c0ffff, 0xb1ffff34, 0xef25d784, 0xffff6666, 0x250483ea, 0xffcecce1, 0x1983fcff, 0xcc4ceb2b, + 0x801000ff, 0xffff0800, 0x241982ee, 0x9a190e00, 0x058351ff, 0x09821820, 0x33090028, 0x1300ff34, 0x1e829899, 0x0a83ff20, 0x9a190031, 0xd9ffff05, + 0x00ff9919, 0xff008005, 0x8299dcff, 0x99132109, 0xe6203382, 0x00260482, 0x0834b31d, 0x7d8200ff, 0x82180720, 0x1c7f09ad, 0x0be84b0c, 0x200a1a7f, + 0x202f825b, 0x826082ff, 0x33ff23cb, 0xcd75ff32, 0x83332006, 0x8265204c, 0xcdff2c95, 0xff05cc4c, 0x33b31700, 0x83f4ffff, 0x82092086, 0xe3ff2276, + 0x20768219, 0x220483f4, 0x82cc4ce8, 0x201983a0, 0x200a82ff, 0x261982ff, 0xf6ffff99, 0x82ff6866, 0xffcd250e, 0x66e60b00, 0x60261e82, 0x00ffc2b5, + 0xbf83994f, 0x66e6fe22, 0x99266382, 0xfeffff98, 0x0982f6e8, 0xfe22c983, 0x098214ee, 0xff30bf83, 0xff0a17fb, 0xcccc0200, 0xc0fbffff, 0x0300ff00, + 0xff24d982, 0x908f82fc, 0xfb254482, 0x00ff986e, 0x24108404, 0x00ff8fc2, 0x238c8206, 0xe530feff, 0xb3210982, 0x2b1e8232, 0x97b2bdfc, 0x650100ff, + 0x0d00ff18, 0x00231a82, 0x82dea306, 0x0080227e, 0x215a8208, 0x198296a3, 0x0024ad82, 0x8c91ad00, 0xb6210f82, 0x200f8387, 0x251a8298, 0xff2d1243, + 0x99836400, 0xbd1a0027, 0x00ffb371, 0x209f832c, 0x232b8318, 0x8b333330, 0x4b2c2182, 0xff063433, 0x00802e00, 0x2b00ff8b, 0xe9207d83, 0x0022b282, + 0xc182191b, 0x3333da22, 0x32282082, 0xffff34b3, 0x059919b9, 0x3322b882, 0x59828834, 0xfc22be83, 0x0982cecc, 0x27058869, 0xff8e0832, 0x6866f9ff, + 0x4c241082, 0xf8ffffce, 0xff216282, 0x820483fe, 0x20408209, 0x20558300, 0x832a84f5, 0x99f52e55, 0xffff849a, 0x0834b3f7, 0xffff078b, 0x2ecb835f, + 0x15cccc5e, 0xb3e7ffff, 0xffff8b33, 0x83cd4cec, 0x82cc2004, 0x83e7200a, 0x25178323, 0x1300ff34, 0x168433b3, 0x1800ff24, 0xb783cd4c, 0x824c1821, + 0x84168222, 0x8234201b, 0x201082bc, 0x86068508, 0x83132028, 0x284382b8, 0xef0e088b, 0x19af01ff, 0x0a8f489a, 0x8e821620, 0x7d150025, 0x1900ff70, + 0x210c1074, 0xf6829914, 0x2011df55, 0x20db82eb, 0x201682ff, 0x497319ff, 0xff9a210f, 0x220a2052, 0x8264fc93, 0x33ef22c5, 0x22ba8232, 0x4ececcf0, + 0xdf220d37, 0xed829a19, 0xcc4ce422, 0x8312a948, 0x19fb2d5d, 0xf0ffff9a, 0x00ffcccc, 0x089a1909, 0xe6210a82, 0x1ca94866, 0x48323321, 0x3e8208a9, + 0x8207a948, 0x13a94814, 0x00239182, 0x4834331f, 0x148213a9, 0x8207a948, 0x228083fa, 0x8219fbff, 0x06a94809, 0xffff6825, 0x8366e6f6, 0x839a828f, + 0xffff210a, 0x200ba948, 0x07a94864, 0x0080e224, 0xa94800ff, 0xe6202205, 0x08025266, 0x18105a4b, 0x41075549, 0x8b4f0c1d, 0x0ed64a0f, 0x058b8b3c, + 0x3325ffff, 0xa301ff33, 0xff1534f3, 0x99194c00, 0x1e1700ff, 0x00ff05b8, 0x48824c06, 0x66e60122, 0x9f830982, 0xd6e3fd2d, 0x190400ff, 0xfaffff9a, + 0x8708bade, 0x46e1210a, 0x21068743, 0x5618e6f8, 0xfa2207c3, 0xd3825c4f, 0x6666d927, 0xe1baffff, 0x27488248, 0xff343337, 0xffffd9ff, 0xe7216982, + 0x22fe8299, 0x820080d7, 0x80cd270a, 0xf8ffff01, 0x20823333, 0x99990527, 0x99b0ffff, 0x200a829a, 0x20368300, 0x200483f9, 0x53f582fc, 0xfa2005ed, + 0x09557483, 0x830a8505, 0xe6f8264f, 0xffff8c66, 0x230a82fb, 0x00800400, 0x01214810, 0x30fb2644, 0x24f884f7, 0x12a25215, 0x111e7619, 0x2109a252, + 0x276900ff, 0x16d45913, 0x44fc8322, 0x60625f83, 0x0b624613, 0x420a5e62, 0x81520fbf, 0x00ff2125, 0x4c051344, 0x7f202bbd, 0x21081344, 0xbd4cff72, + 0xa01a2206, 0x07bd4cff, 0x4cea4621, 0x342013bd, 0x080dbd4c, 0x66e62328, 0x1c00ff06, 0xff8b9a99, 0x99191b00, 0x4cf3ffff, 0x1200ffcc, 0x08753333, + 0xb34900ff, 0xa7ffff34, 0xff059a19, 0x16820b00, 0x66f2ff2e, 0xfeffff66, 0xffff9a19, 0xff68e6eb, 0xf4230e85, 0x880832b3, 0x832e820a, 0x059b5919, + 0xff241982, 0x9a990d00, 0xd0311e82, 0x00ff9a99, 0x05991939, 0x0bffff8b, 0xe305cd4c, 0xb85d18eb, 0x0793212e, 0x1e259f82, 0x00ff66e6, 0x857e8219, + 0x6a4c1904, 0x0559640c, 0x08fc4918, 0x6418fb20, 0xf7202fcb, 0x895d3083, 0x82fc2005, 0x030021e5, 0xff24b182, 0x8b9a99fb, 0x0683bd82, 0x83ffff21, + 0x82048316, 0x221082c2, 0x4c078308, 0x4346621d, 0x4cee2205, 0x217482cd, 0x6119b3f1, 0x2f420c66, 0x12ed4e33, 0x42291c21, 0x4521082f, 0x132f421f, + 0x240eed4e, 0x0666e68e, 0xf45a18db, 0x05c74f09, 0x3b435c20, 0xf7082205, 0x0eef7e74, 0x43a48221, 0x0822059a, 0xef7e74fb, 0x82fb2017, 0xc6791933, + 0x07bb3115, 0x076b06cb, 0xf70654f7, 0x54fb0754, 0x9b074b06, 0x242eef4e, 0xfb061cfb, 0x087c46b4, 0x43258643, 0x8b261ebc, 0xaf0e058b, 0x734464f7, + 0xfb53235e, 0xfb1815c4, 0x76441956, 0x33104216, 0x50424044, 0x33200dfe, 0x26085448, 0xe3ffff67, 0x4a089a19, 0xff250562, 0x05cd4cb5, 0x201b827a, + 0x28168266, 0xffcc4cf4, 0x3233ebff, 0x053b73ff, 0x68e6e823, 0x05554408, 0x2a053644, 0xff0080fd, 0x9a190200, 0x84ffffff, 0xcc4c2109, 0x073cf918, + 0x41115048, 0x8b2329d3, 0x183cf805, 0x18d9ab98, 0x21319da6, 0x0210068b, 0x23b701c7, 0x157b1cf7, 0x011a9910, 0xa7051024, 0x3b221602, 0xe11800ff, + 0x08106734, 0x45b50128, 0xb0186060, 0x0b10d182, 0x42b40110, 0xb71860e7, 0x4b205e4e, 0xec18e518, 0xff939a27, 0x00800900, 0x14e518ff, 0x9206103e, + 0x85181502, 0x4e4e0eab, 0x9da21831, 0xff3223b1, 0xae19f9ff, 0x44581262, 0xf9a71806, 0x8232200c, 0x32332214, 0x26e38308, 0x2400ffce, 0x830534b3, + 0x83158205, 0xef0e260a, 0x190f02ff, 0x0a115298, 0x70251e5a, 0xff210505, 0x257a5a00, 0x67ffff3f, 0xfeff68e6, 0x159a19c5, 0x4c2600ff, 0x7200ffcc, + 0xff05cccc, 0x9a19deff, 0x99c7ffff, 0x0deb629a, 0x2632415a, 0xff9a9935, 0x83335900, 0x331421da, 0x2121da82, 0x250482b3, 0xff008024, 0x19831400, + 0xce4c272f, 0x00ff088b, 0x0698990b, 0x4c2700ff, 0x83bd82cc, 0xebff231c, 0x21826666, 0x82343321, 0xce4c2189, 0x35252082, 0xffff9c99, 0x229a83a6, + 0x5a190900, 0xde303b41, 0x00ff9c19, 0x05666638, 0x662500ff, 0x8dffff64, 0x042c9a84, 0xffffd04c, 0xff9a99f5, 0xcc4cf8ff, 0x04840982, 0x82981921, + 0xedff249a, 0x1806cc4c, 0x5a09d154, 0xcf622569, 0x07c55f05, 0x180e675a, 0x690d824d, 0xeb2108f3, 0x22188207, 0x82069a19, 0x8378827d, 0xffce2a88, + 0x34b30a00, 0x660300ff, 0x2f098266, 0x8b086666, 0xffff058b, 0xffcd4c65, 0x9ad90e01, 0x01a11a10, 0xaf4a08fe, 0x19bf00ff, 0x5f01ff9a, 0x8b150ad7, + 0x5ccbffff, 0xffffae2a, 0xff6666d1, 0x32333200, 0xffb3087b, 0x3333f3ff, 0xcc2900ff, 0xffffffce, 0xffb49919, 0x00800800, 0x6900ff08, 0x00ffcccc, + 0x05cdcc17, 0x331100ff, 0x0300ff32, 0x9e6f67e6, 0x83f52006, 0xe603272f, 0xeeffff68, 0x2982cdcc, 0x64e60322, 0xcc250a83, 0x33f5ffff, 0x86148434, + 0x19fc2e0e, 0xffff089a, 0xff020097, 0x9919e8ff, 0x251f8205, 0xffff0080, 0xf71899fd, 0xfe2007d6, 0xf5252e83, 0xffffce4c, 0x052373fe, 0x43824c20, + 0x66669e22, 0xf2202982, 0x0320a083, 0xf2201f83, 0x00211f82, 0x23818206, 0x9899f3ff, 0x99229c82, 0x9919089a, 0xf822334b, 0xfd8233b3, 0xcd4cf825, + 0x830100ff, 0x83f82056, 0x190229c4, 0xffa00898, 0x34b39200, 0xd9207282, 0x22201b83, 0xff2e7782, 0xff9999e7, 0x66e63100, 0x3600ff8b, 0xe1823e0a, + 0x1a282021, 0x2009511d, 0x293d820f, 0x7c540e00, 0xcc1000ff, 0x1c828bcd, 0x99991222, 0x0d252882, 0xffff6766, 0x6b7118f1, 0xffff2c08, 0x070ad7df, + 0xe1ffffcb, 0x82155c0f, 0x7322221e, 0x068d6d34, 0xcc8c1d22, 0x13d80e19, 0x3473e222, 0xdd239f82, 0x8208cc8c, 0xccdb2a06, 0xe3ffffce, 0xffffcc4c, + 0x22f883e4, 0x8234b3dc, 0x83ff2068, 0xffff2206, 0x23a182e2, 0xcecc1b00, 0x24225482, 0x7f823233, 0x66e68028, 0x19dffeff, 0x8810159a, 0x202901ae, + 0x419f19de, 0xb89e2b16, 0x99f7ffff, 0xebffff9a, 0x9b1885ab, 0x3d2613a7, 0xeeffff87, 0x9b1802cb, 0x3c2008a7, 0x09a79b18, 0xa2182220, 0x8a1890b6, + 0x8b2635f3, 0xf72f0e06, 0x6f19f894, 0xff39195b, 0x07f628f6, 0xc9ffff8b, 0xffffd663, 0xff9a19e4, 0x34f3cdff, 0x66d3ffff, 0x076f5966, 0x33330032, + 0x99ffffff, 0x00ff059a, 0xffcdcc38, 0x32b3b0ff, 0x57220a82, 0xf2190080, 0x0e260813, 0xff833233, 0x3c830900, 0x66e6f327, 0x2b00ff08, 0x22428233, + 0x826866c6, 0x990a2127, 0xf1215282, 0x324d82e6, 0xff9819fd, 0xccccecff, 0xe6f1ffff, 0xf4ffff68, 0x83080080, 0xff66230a, 0x6c83f5ff, 0x2382eb20, + 0x83020021, 0x230e8319, 0x98190e00, 0xd9201e82, 0x00223d82, 0x7b821934, 0x999eff23, 0x2170829a, 0x3f824c5c, 0x00807022, 0x21064e70, 0x7483f1ff, + 0x82b3fb21, 0x83ec206e, 0x33f12673, 0xf6ffff32, 0x85838266, 0x820a8219, 0x21198273, 0x38830400, 0x00230e83, 0x82cecc0e, 0x825f2059, 0xf8002773, + 0xff053333, 0x4383fdff, 0xda83f620, 0x827ffd21, 0x4cf622e9, 0x051272cc, 0xb7232582, 0x82079a19, 0x82ed200c, 0xf2ff242c, 0x82ff9999, 0x51551804, + 0xe13a210a, 0xf0241b82, 0x00ff1ec5, 0x09a8ee18, 0x4800ff24, 0x338266e6, 0x83410021, 0x80282575, 0x3a00ff00, 0x3c300483, 0x00ff0180, 0x08343318, + 0x332400ff, 0x0e00ff33, 0x16201483, 0x00287482, 0x8b8e0223, 0xf32600ff, 0x09221a83, 0xba6a0ad7, 0x69fc1805, 0xff662709, 0x33b31100, 0x2382088b, + 0x14000026, 0x3b74fb05, 0x21146f73, 0x59828b8f, 0x82188676, 0x06457a6c, 0xe5200983, 0x7a06cc60, 0x11820a45, 0x8200ff21, 0x0e08293e, 0xff94f7ef, + 0xf6289601, 0x14426582, 0x99462430, 0x829b069a, 0x591042a8, 0x34b3d823, 0x061042ff, 0x0080af22, 0x23571042, 0xffffeb11, 0x21051042, 0x0982ae87, + 0x20171042, 0x2c268291, 0xff9a99f2, 0x146eedff, 0xffff088b, 0x061042ef, 0x10421f20, 0xcd8c211a, 0x20071042, 0x42c98273, 0x7a203310, 0x2c15aa46, + 0xffff8b86, 0x087a54ee, 0xe60000ff, 0x2ab48266, 0xfb05f628, 0xdaffff34, 0x821570bd, 0x83e42019, 0x82ea26a6, 0xebffff8f, 0x221d8266, 0x75707de5, + 0xda190571, 0x142008ce, 0x2205b161, 0x76086666, 0x7d2a0836, 0x1600ff71, 0x00ffd663, 0x5d42821a, 0x90822105, 0x15201b82, 0xff231682, 0x822a9ce9, + 0x63e62c54, 0x04f808d6, 0xff1563fb, 0x82b3d8ff, 0xe6db266b, 0xffff0566, 0x436082fe, 0xfe2305c8, 0x82ff3233, 0x226f8209, 0x8268e6fd, 0xcccc2209, + 0x82908208, 0x3000249d, 0x5d05ce4c, 0x00230594, 0x8232b311, 0x99ed2234, 0x210f8298, 0x0a82cdcc, 0x8266f121, 0x4c0d252b, 0xecffffcd, 0x08232a83, + 0x83766666, 0x80ed26ab, 0xffff0600, 0x231282ff, 0x6766ffff, 0x00208882, 0x0f832283, 0x33000027, 0xffff0833, 0x218282fd, 0x75180600, 0x0625081d, + 0x00ff33b3, 0x270e8405, 0xff0834b3, 0x9a994100, 0x089e6c18, 0x18008021, 0x21089e6c, 0x2582cccc, 0x65a4b021, 0x002305c2, 0x65981907, 0x002205d6, + 0xe1651e05, 0x05002607, 0x00ff4621, 0x22288306, 0x4d2a1c02, 0x6c1805cf, 0x1923079e, 0x18ffff9a, 0x21079e6c, 0x6c18ff66, 0xff22139e, 0x24820300, + 0x99060023, 0x84c4829a, 0x826f8206, 0xfcff214b, 0x0021c982, 0x23898202, 0x9002f9ff, 0x1d209f82, 0xff29aa82, 0x053e0ab6, 0x194c00ff, 0x0981669c, + 0x81669f82, 0x66982010, 0x9c200981, 0x81660a82, 0x8264200f, 0x06816613, 0x81666820, 0x99412107, 0xd2223482, 0x5e8266e6, 0x82660521, 0x4cfc2115, + 0x7e855882, 0xffcd4c24, 0x1e83feff, 0x9a99f923, 0x840a8208, 0x99992193, 0xcc214482, 0x055f66d0, 0x80f9ff24, 0x1a828a00, 0x8266b121, 0xccf3225a, + 0x204483cc, 0x66798299, 0x158207b0, 0x8210b066, 0x07b0661e, 0xfd287982, 0xffff3433, 0x8c68e6f8, 0x30215083, 0x06b066ff, 0x8982c520, 0x82350021, + 0xfb0e244f, 0x7104f770, 0xc3275ecf, 0x00ff153b, 0x7166e606, 0x5d600a5c, 0x713a2012, 0xb268525c, 0x2561600b, 0xf4f78b2d, 0x92ffff05, 0xffff142e, + 0x8234b3c9, 0x132208b7, 0x00ff48e1, 0xff981921, 0xa4702300, 0x661400ff, 0x2600ff68, 0x00ff0080, 0x08cccc00, 0xcc9ffeff, 0x1c4307cc, 0x82ee2006, + 0xf1ff2f1a, 0xffff34b3, 0xffccccf1, 0x6666eeff, 0xe161088b, 0x82eb2016, 0x19ee2033, 0x221f341b, 0x508f4226, 0x2621081c, 0x121c5066, 0xff0a572a, + 0x9a19fbff, 0xd9f0ffff, 0x27bff519, 0x659b352a, 0x335900ff, 0xaf0e0534, 0x2060c673, 0x28e4828b, 0xff1f857f, 0x9a99f4fe, 0x62a48315, 0xe46642a3, + 0xffff226e, 0x877a190b, 0x1e776430, 0x63161142, 0x8b2b2ff3, 0xd001ff06, 0x00ffe27a, 0x1966664b, 0x215c71a1, 0x5e82237b, 0xb0670020, 0x18682017, + 0x3011ad71, 0xe699ffff, 0xff8b0766, 0x9a99dbff, 0x80e2ffff, 0x82048600, 0x088b210e, 0x802ffd82, 0xffff8b00, 0xff3233ef, 0x66e60600, 0x82f3ffff, + 0x0c002325, 0x1a826666, 0x6666c930, 0xb33600ff, 0xffff0534, 0xffcecce3, 0x0a84c7ff, 0x8219f821, 0x9b421846, 0x21198319, 0x49830700, 0x4983f920, + 0x34331323, 0x2b0e84ff, 0xcccc0f00, 0x05ebbb08, 0xb30300ff, 0x09201282, 0x09201783, 0x06202183, 0x0a206583, 0x01267f83, 0xff0834b3, 0x5f820a00, + 0x83010021, 0x820a2019, 0xfcff2219, 0x209982b3, 0x212d8207, 0x1e84f8ff, 0x14832920, 0x32b3d622, 0x3a284882, 0xfb0734b3, 0x15bcf744, 0x0822f482, + 0x67820ad7, 0x28286c84, 0x0800fff6, 0x088bcccc, 0x0df5f219, 0x0a9b5318, 0x166f8418, 0x56185320, 0x07220dce, 0x5885f628, 0x00ff0823, 0x2459822f, + 0xcc4cb6ff, 0x21cc8515, 0xa483fcff, 0xb4820320, 0x4cf6ff2b, 0xffff87ce, 0x089819f8, 0x821584ff, 0xff9a210a, 0x0e821583, 0x84cecc21, 0x088f2419, + 0x8305a35b, 0x829a2009, 0x66e621fc, 0x5c181885, 0x03200ccd, 0x00241582, 0xff28dc07, 0x24821583, 0xe621c784, 0x34298268, 0xbb08cc0c, 0xfde7ffff, + 0xff0e0570, 0x34b36e01, 0x8ebe01ff, 0x28858298, 0xffcc4c09, 0xf6c60000, 0x21578293, 0xd08288a3, 0x12a3f622, 0xe2238182, 0x83073e4a, 0x9042210c, + 0xcc2c1782, 0xf9ffffcc, 0xffff70bd, 0x8b3433f7, 0x68281c82, 0xff069a19, 0x9919f3ff, 0xf4272182, 0x00ffcdcc, 0x823e4a0a, 0xcf0d23e1, 0x0683085c, + 0x2607086f, 0x14ee0900, 0x820d00ff, 0x0100233d, 0xfc827c14, 0xc7829720, 0xa50c0023, 0x20c382a2, 0x24768261, 0xce5792ff, 0x21308215, 0xcf829904, + 0x04830020, 0xcc4c0528, 0x0600ff8c, 0x2c829a19, 0xcccc9c26, 0x0100ff06, 0x09a17019, 0xff008026, 0x34b3faff, 0xfb227382, 0x68826666, 0x82d2ff21, + 0xdcff2168, 0xff21e282, 0x222583dd, 0x18ccccd3, 0x220e8466, 0x8266e622, 0x822d205e, 0x078b284e, 0x336900ff, 0x8204fb34, 0x660e27f1, 0xff998b66, + 0xb883fcff, 0x86830d20, 0xcdccfb26, 0x5dffff08, 0x04824383, 0x00ff0531, 0x07cc4c5a, 0x0268ffff, 0xffff068f, 0x82f6e8e9, 0x16ee2571, 0xa28b9c73, + 0x00217482, 0x236f8215, 0x8de91100, 0x22067d7c, 0x820a1716, 0x11012374, 0xac82a430, 0x98197527, 0x4cbcffff, 0x206482ce, 0x224d834c, 0x8298197f, + 0x4c0b234d, 0xc95678ce, 0xe7ff2305, 0x0a820080, 0xceccf423, 0x058a4908, 0xb3f4ff24, 0x1583ff32, 0x4c23f482, 0x82ffffce, 0x00ff2219, 0x24af8213, + 0x66caffff, 0x20888266, 0x23408299, 0x34b3d1ff, 0x56228e82, 0x62829a99, 0x5782ab20, 0x04820020, 0x829d0521, 0x9a99242d, 0x820f00ff, 0xf0ff2127, + 0x00220482, 0x4b82330b, 0xec85ed20, 0xff253383, 0xcccc62ff, 0xab831915, 0x18b3200a, 0x210ca741, 0x4a1814fb, 0xab2b174b, 0x0654f707, 0x14f72f0e, + 0x41152df8, 0x002026cf, 0x234f4642, 0xae00ff07, 0xff24d482, 0x1566e6c7, 0x73490542, 0x002005ae, 0x28166b42, 0xff343347, 0xcecc92fe, 0x0c7d4115, + 0x34b39129, 0xffff8b07, 0x4834b3fe, 0xfe22060e, 0x0987cccc, 0x0834b325, 0x8251ffff, 0xf8003119, 0xff0566e6, 0x9a991000, 0x190700ff, 0x1200ff99, + 0x04220483, 0x098233b3, 0x2905a74a, 0x06666632, 0xe60f00ff, 0x05828b67, 0xff008029, 0xcd4cfcff, 0x830e00ff, 0xe6fa33e3, 0x00ff0867, 0xff66e65e, + 0xa430a400, 0xf8ffff05, 0xa982ce4c, 0xfff66824, 0x1f82fdff, 0xca090023, 0x830e823c, 0xa6072209, 0x20298268, 0x240a8504, 0x0900ff66, 0x222882cc, + 0x8246a102, 0x32b32674, 0x94fbffff, 0x231e827c, 0x7b34b31b, 0x07208b82, 0x11838b82, 0x0200ff29, 0xffff9899, 0x82c235f6, 0x22138320, 0x829a59f8, + 0x82c720b5, 0x9fff21b5, 0x07fc7718, 0x30828a20, 0x824c0f21, 0x33f721d7, 0x073f8818, 0x6766ec24, 0x0e83ffff, 0xb3f0ff23, 0x06595933, 0x99c0ff25, + 0x4f8d059a, 0x0a6a05df, 0x82192006, 0xcc0123f1, 0x788288cc, 0x243ef342, 0xffff078b, 0x23da8392, 0x1532338d, 0x0bae8d18, 0x024fe683, 0x82082005, + 0x820c2006, 0xf5ff2122, 0x0021ab82, 0x20cd830b, 0x05fa53f2, 0x7318f220, 0xf4200911, 0x0841e818, 0xffff8b2d, 0xffceccf1, 0x33b30a00, 0x83f6ffff, + 0x4c0d2bd9, 0x23088bcd, 0x193fffff, 0xb047159a, 0x4c6e2218, 0x2d8a82cc, 0xffa470ca, 0x6866a5ff, 0xf4ffff05, 0xaf431ec5, 0x78e72206, 0x06ca4352, + 0xe1faec28, 0x4c0b00ff, 0x198208ce, 0x8265fa21, 0x285e820a, 0x62b1f9ff, 0x801800ff, 0x2c0e8200, 0x089eee3c, 0x214c00ff, 0x8000ff89, 0x2d4482e6, + 0x295c0900, 0xb31000ff, 0x0c00ff32, 0x04820b57, 0x0023bc82, 0x84cd4c0e, 0x2729829d, 0xff6766b5, 0xccccfcfe, 0xfc206e82, 0x6f424082, 0x82fc2005, + 0xffff21e6, 0xfc340483, 0x088b9a19, 0x058b14fb, 0xb600ff0e, 0x01ff3333, 0x1574e6bf, 0x25066e5e, 0xff9e0d01, 0x4a820800, 0x94f8ff23, 0x22f382a2, + 0x824c77f6, 0xdef12395, 0x0c8207b8, 0x8238f721, 0xe6f831b1, 0xf8ffff66, 0xffff2adc, 0xff3433f7, 0x84ebffff, 0x902d2082, 0xff06d6a3, 0x71bdf6ff, + 0x170000ff, 0x271f820a, 0x00ff1f85, 0x8b208507, 0x47225682, 0x068208ae, 0x98990825, 0x820600ff, 0x070023f2, 0x6282e23a, 0xad828c20, 0x34f30022, + 0x6f21ad82, 0x237c822e, 0x05365c0c, 0xcc272b82, 0xa0ffffcd, 0x18158c19, 0x21193591, 0x1b8266a6, 0x9959e322, 0x0e616c18, 0x8b820620, 0xe100002d, + 0x00ff9148, 0xff67a601, 0x82ab0500, 0x7a002496, 0x820652f8, 0x9a992610, 0x54faffff, 0x229b827c, 0x828566e6, 0xccf9293e, 0x078b08cc, 0x34fb34fb, + 0x00216882, 0x21748212, 0xb5820800, 0x82100021, 0x0c0028da, 0x00ff48e1, 0x8233b30b, 0x3a902699, 0x0503fbe1, 0x2eea18ff, 0x20a0820c, 0x252682ff, + 0x3333feff, 0xf744088b, 0x2fa11805, 0xab8b2113, 0xbe32ce82, 0xffff3333, 0x150080d5, 0xd976ffff, 0x6900ff9a, 0x15829a99, 0x5c8f0322, 0x99208982, + 0x0322c182, 0x9d82f6a8, 0x00262482, 0x8be2ba03, 0xab82cb08, 0xcd4c2323, 0x2eda838b, 0xe2ffff33, 0xff8b6766, 0x9999ddff, 0x46076b08, 0xff2605a8, + 0x6666ffff, 0xd341ffff, 0x21b58205, 0x4777fcff, 0x61002105, 0x00210c82, 0x826882ca, 0x5923223b, 0x2240839a, 0x5600ff34, 0xdc231cfc, 0x190866a6, + 0x201a9d83, 0x221b8234, 0x41cc4ce3, 0xeb220b65, 0x4b57152b, 0x22148405, 0x83e3ffff, 0xdcff23aa, 0x9f8533b3, 0x46063273, 0x4e181317, 0xab2012b5, + 0x0020d282, 0x4b85ec82, 0xb31c0023, 0x395b8533, 0xff06cb08, 0xccccf7fe, 0xe6c5feff, 0xff811566, 0xce4cf7ff, 0xe6f0ffff, 0x0a828c66, 0x95333323, + 0x2f068208, 0x8c95cc4c, 0x190f00ff, 0x00ff9598, 0x08cecc08, 0xe62f0b82, 0x0d00ff67, 0xff0566e6, 0xffff8eff, 0x840000ff, 0xa3f3220a, 0x27c582d7, + 0xff7c42f5, 0x66e60900, 0x00261582, 0x0e00ff14, 0x30829a19, 0x0a830020, 0x82660c21, 0xbf0a2714, 0x0b00ffec, 0x3f829a99, 0x8b004022, 0x70221a82, + 0x42829a19, 0x829a1921, 0x19f0224b, 0x20568599, 0x20688481, 0x8274848a, 0x34b3210a, 0x7a828782, 0x8082cd20, 0x9a190f24, 0xa684958c, 0x53cb082d, + 0x0500ff05, 0xffff3333, 0x826666fb, 0x66f92587, 0x08858b66, 0xf8258282, 0xff883433, 0x240e82ff, 0xccfaffff, 0x211e84cd, 0x2c834b08, 0x82669021, + 0x335c26b7, 0xc3cb1534, 0x224b8205, 0x8432b308, 0x82688262, 0x828120d7, 0x2111828c, 0xff838a81, 0x82816821, 0x32332163, 0xf023fe82, 0x827e9a19, + 0x20a68267, 0x2806828b, 0x8bcc4c0d, 0xb30a00ff, 0x0f751834, 0x4cf52513, 0xf6ffffcc, 0xd944cf83, 0xe68f2206, 0x27348366, 0xff66e60f, 0x3433f1ff, + 0xff247382, 0x8c3233f7, 0x5f826084, 0x82ce4c21, 0x82118373, 0xe6f0236c, 0xf6838a68, 0x0832b325, 0x8205c34b, 0x7a3382bd, 0xfd2005a0, 0x06220983, + 0x77829a99, 0xcccc0728, 0xff918b08, 0x44510200, 0x00ff2206, 0x28098306, 0x089a9904, 0xf70e068b, 0x0a265fc4, 0x11254f18, 0x14664b18, 0xac75ff20, + 0x3d38712b, 0x79666621, 0x6723098d, 0x82f0ffff, 0xecff21d6, 0x2e4f1483, 0xcdcc2105, 0x21088d79, 0x7975b8de, 0xff992508, 0x98991300, 0x21210e82, + 0x08497348, 0xff343322, 0x07374218, 0x42183e82, 0xda508b37, 0x0c9a430d, 0x3016b57e, 0x7b0714f7, 0xffff058b, 0xff6d070f, 0x94f85801, 0x21ea8215, + 0x0482fa5e, 0x833a5f21, 0x003319ef, 0xc6a03009, 0x4f00ff08, 0xffff4821, 0x05beffaf, 0x190a00ff, 0x2313e691, 0x080080f7, 0x1c587718, 0x45843b82, + 0xf6217182, 0x083319a0, 0x08fa2714, 0x01ff078b, 0x3319f8cf, 0x8a850a08, 0x77183420, 0x8a840843, 0x32330a32, 0xa1f6ffff, 0xffff8b06, 0xffccccf0, + 0xceccf5ff, 0x48270f83, 0xffff3b08, 0x18b8deb0, 0x180e0479, 0x1807d786, 0x2e1c0479, 0xdb08b85e, 0x005000ff, 0xfeff0542, 0x846c0730, 0x84152004, + 0x82db2010, 0xcf7718f0, 0x208a8433, 0x228b823b, 0x1848a1f6, 0x210e6b78, 0x8b87ff06, 0xffc5a023, 0xc3861800, 0x09003609, 0x00ff3b5f, 0x08666609, + 0x01ff078b, 0xff94f87f, 0x66e62e00, 0x1adb8215, 0x82142214, 0x822d8427, 0xcc4c2104, 0x0d2f3419, 0x0834b323, 0x837b82db, 0xc4871866, 0x0529410b, + 0x4111a941, 0x2b080c22, 0x0e05db3b, 0x0901ffaf, 0x94f73433, 0x1900ff15, 0xff8b6666, 0x66661800, 0xe6f8ffff, 0xffffa066, 0x083433f3, 0xe6d3feff, + 0x54fb0766, 0xae20c982, 0x2130f548, 0x734cffe1, 0xb0f92205, 0x07f548a4, 0x48713d21, 0x482005f5, 0x2507f548, 0xff008018, 0x74822900, 0x832c0021, + 0x35848209, 0x193000ff, 0xff088b9a, 0x67663200, 0x00ff058b, 0xf7cccc36, 0x71181504, 0x34210902, 0x05d34dff, 0x2011ce4d, 0xd4401823, 0x27c88208, + 0xff142e2c, 0xcdcc2300, 0xd1240482, 0x2c00ffd8, 0x18051b7f, 0x200cf472, 0x27548328, 0xf708ecd1, 0xff15cb24, 0x6ee13019, 0x7d459820, 0xf9ff2105, + 0xff2bf582, 0x0866e6fd, 0xe6caffff, 0x11ffff68, 0x1e01e130, 0xef01ff2a, 0x01ff66e6, 0x15cccc3b, 0x21050048, 0xdd60faff, 0xff342605, 0x6666f5ff, + 0x05e45c8b, 0x18d4fb21, 0x3a2eb250, 0x662d01ff, 0x54fb0766, 0xbd6d00ff, 0x54fb0572, 0x4292ffff, 0xfeff058e, 0x899a99d2, 0x85ab2249, 0x05e555ff, + 0x7b54ee22, 0x14db5218, 0x34b31124, 0x7a83f708, 0x800b002d, 0x0600ff00, 0x00ff2b27, 0x829a990a, 0x8df733a8, 0xb30500ff, 0x00ff0832, 0xffe2fadf, + 0xe8fb7f00, 0x11829405, 0xfffa9e25, 0x82e60c00, 0x090021b5, 0xff2bd582, 0x080661fa, 0xffff74f7, 0x82180480, 0x19e8277b, 0xdcffff9a, 0x5a183433, + 0x9a241b4b, 0x1100ff8b, 0xee203a83, 0x29135b18, 0x32828f82, 0x16293882, 0x93089a19, 0xff15ecfb, 0x091c4dff, 0x0a8d8018, 0xae00ff27, 0xff070080, + 0x835818ff, 0x1833200c, 0x20128358, 0x24ea82cd, 0xff08cc4c, 0x1c4b18ff, 0xff7f210a, 0x21066f5d, 0x1e824c06, 0xfa840b20, 0x82cc2521, 0x4c462b0a, + 0x00ff05ce, 0xff67660f, 0x24831c00, 0xcccc1d27, 0xb31200ff, 0x315a1833, 0x0699210a, 0xce200c83, 0x1c83a182, 0x83edff21, 0x660f2241, 0xa3591866, + 0xffce2109, 0x08a35918, 0x8f82cc20, 0x0f824c20, 0x9a99fb24, 0xad19ffff, 0x1982112e, 0x34b3f922, 0x00211985, 0x27438304, 0xff32b3f9, 0x9a990b00, + 0x5818ae82, 0x51200ae9, 0x0a251a19, 0x824cf521, 0x4e048454, 0x9c18083a, 0xe3241260, 0x33067b07, 0x0980a018, 0xff20a382, 0x33283386, 0x078b088b, + 0x34f7ef0e, 0x295e5c59, 0xffff078b, 0xff33b3d0, 0x655762ff, 0xc3b52505, 0x33f9ffff, 0xf4220f82, 0x56188f02, 0xcd2508a1, 0x80f0ffff, 0x28ec8200, + 0xff707dfe, 0x3433fcff, 0x2c248205, 0xffffa470, 0xff9a99ef, 0x4761edff, 0x260a8283, 0x00ff0a97, 0x82989906, 0x85ef2025, 0x251a820a, 0xff1f05f8, + 0x24821200, 0x06002808, 0x00ff5c8f, 0x08666610, 0x820100ff, 0x0300ff8f, 0xff05cdcc, 0xd7630c00, 0xe61e00ff, 0x1700ff67, 0x00ff71fd, 0x8266e618, + 0xe27a270e, 0x990d00ff, 0x5818089a, 0xd72209c9, 0x5818ff0a, 0x992b11c9, 0x00ff088b, 0x8b9a992c, 0x832800ff, 0x33e526b0, 0x1100ff34, 0x18758219, + 0x2112c958, 0x5818ff32, 0xce2508c9, 0x19f8ffff, 0x25ab8299, 0xffff6666, 0xdb82ccec, 0x2256f820, 0x82342005, 0x1e2d56ba, 0x0cc95818, 0x00ff3324, + 0x58823305, 0xbf83f720, 0x34b30826, 0x99fbffff, 0x58185782, 0xd48207c9, 0x07c95818, 0xffff3322, 0x12c95818, 0xfa207e82, 0x00217982, 0x203f8203, + 0xc95818ff, 0x21d5821e, 0x048399ee, 0xfb222b83, 0x5718cccc, 0xfb2007af, 0xee207683, 0xce837684, 0x1e82fa20, 0x13c95818, 0x18ff6721, 0x8208c958, + 0x821020b5, 0xf9ff2175, 0x58183483, 0x298211c9, 0xff7f3f28, 0xffffff05, 0x04829919, 0x58189920, 0x0f850ac9, 0x07c95818, 0xffff7f2b, 0x15323375, + 0xb32800ff, 0xf0561833, 0x182e8214, 0x211af056, 0x56187b54, 0xbd2c12f0, 0xffff8b71, 0xff8380f3, 0xfe7f0c00, 0xf322e282, 0x0a820681, 0x8b008022, + 0x23055a6a, 0xfa7e0c00, 0x08250f84, 0x5b3b00ff, 0x270482a6, 0xff056666, 0xc3f51800, 0x08f45618, 0x88662625, 0x830200ff, 0x33fd225c, 0x33098234, + 0xffffae87, 0x083233fd, 0x01ff068b, 0xff34b304, 0x9a99e1ff, 0x1baa4c18, 0x18dbdb21, 0x200e424c, 0x424c1834, 0xffff2426, 0x8232b3e6, 0x9a992104, + 0x12234082, 0x180634b3, 0x200aa2a0, 0x468819e6, 0x05165009, 0x18cc4c21, 0x18110a46, 0x2207f84c, 0x1832330f, 0x270b3af9, 0xff0614f7, 0x68665800, + 0x47271e82, 0xffff9899, 0x826666b8, 0x99a7233b, 0xfc18089a, 0xfa18092d, 0xed220e80, 0x3382cc4c, 0xce4c1922, 0x0c208e87, 0x17f74c18, 0x21056c45, + 0x1f83f3ff, 0x14f44c18, 0x037d0410, 0x11022849, 0x00ff64e6, 0x18cecc6e, 0x211b724e, 0x4e183b3b, 0xd0260e0a, 0xf3ffff8b, 0xf444fe7f, 0x86f71806, + 0x4c19271b, 0x1900ffce, 0x40826666, 0x82186d20, 0xb36e10e8, 0xff8b2208, 0x5e3c1900, 0x00ff2513, 0x0634b392, 0x8605c244, 0x6b5c1844, 0x800c221a, + 0x23908402, 0x331400ff, 0x0c615118, 0x053bdb22, 0x03b10810, 0xe633444c, 0x11ffff2a, 0x00ff6866, 0x156666e9, 0x0d3ea918, 0x0879ac18, 0x18075b21, + 0x27099585, 0xf5ffffcc, 0xffff0040, 0x2212564d, 0x828b00c0, 0x00402340, 0xa718bb08, 0xa32017dc, 0x075e9018, 0x45823420, 0x2024a14d, 0x3baf189b, + 0x077b222e, 0x3eed1973, 0x1806190e, 0xc0b8820f, 0x41c7b17c, 0xf2820512, 0x0fccaa18, 0x240d7241, 0xff8bcc4c, 0x25a182ff, 0x0e075b08, 0x7b4ef4f7, + 0xffff245e, 0x4e9a99d0, 0xcc230879, 0x18ffffcc, 0x22201765, 0x4e6666f9, 0x66220775, 0x0a858366, 0x2207754e, 0x82ff9999, 0x839a210a, 0x8207714e, + 0x07714e5b, 0x4e008021, 0x40820871, 0xe61e0025, 0x4effa367, 0x8021066d, 0x0f6d4e01, 0x6d4e8882, 0x4e9a2011, 0x6718056d, 0x6d4e0f37, 0x37671869, + 0x096d4e6b, 0x67186620, 0xff237f37, 0x83e6f4ff, 0x9a192284, 0x200a8205, 0x4e998219, 0x65180775, 0xff38a066, 0x6666baff, 0x194600ff, 0x00ff159a, + 0xff999908, 0x0080fbff, 0x990200ff, 0x20077065, 0x2d1383fb, 0x083233f9, 0x33d4ffff, 0xb3ffff34, 0xe482ce4c, 0xcc4cff25, 0x83fdffff, 0xe6fe2204, + 0x83098767, 0x80fd2229, 0x27298200, 0xff0000c0, 0x9a1991ff, 0xf7212982, 0x21538219, 0x3982b3f0, 0xa470ec26, 0xccfaffff, 0xf0223882, 0x6c8233b3, + 0x82cecc21, 0x91c82329, 0x2582abeb, 0x6fb2f022, 0xe6211182, 0x24208266, 0x00ff83c1, 0x38838313, 0xff0bd608, 0xcc4c0f00, 0x3f00ff08, 0x00ffdb19, + 0x0566e66e, 0xbd0900ff, 0x20158371, 0x212482ce, 0xdc505d8f, 0x51248205, 0x29820520, 0x82663621, 0xb3df298e, 0xffab0534, 0xcc4c3800, 0x07e37418, + 0x82cc0621, 0x83092030, 0x99022676, 0x0600ff98, 0x203082cc, 0x05e65bfb, 0xd4f7ef32, 0x516201ff, 0xffff15ec, 0x074861ab, 0x194d00ff, 0xd320fb82, + 0xff216c83, 0x228782d1, 0x8266e0ff, 0x83e12096, 0x99ca2604, 0xffff8b9a, 0x057265c3, 0xc982c920, 0x83180021, 0x82cf2020, 0x26002204, 0x20358299, + 0x225282e0, 0x83fdffff, 0x82f920c7, 0xfaff2171, 0xfc210983, 0x20f2824c, 0x052e66f9, 0x4184ff20, 0x32b3fe27, 0x330000ff, 0x054a6334, 0x4c000022, + 0xff20e382, 0x6b343e1a, 0x66e64626, 0x54ffff07, 0xce20d383, 0xf522e884, 0xb7821fc5, 0xf52bf883, 0x00ff7bd4, 0x8b34b307, 0x830a00ff, 0x410024cd, + 0x82070080, 0x8305200c, 0x130325ee, 0x0500ff75, 0x0039cf82, 0xff6bfc04, 0xcecc0200, 0xb700ff08, 0x00ff21f0, 0x059a1969, 0x9e5400ff, 0x262b83b8, + 0xa8662622, 0x1a3b00ff, 0x2813c83f, 0xd4f7068b, 0xaeedfeff, 0x6bc91014, 0x02100e01, 0x206e0184, 0x078342ab, 0x804f0025, 0x1800ff00, 0x2225c1cb, + 0x18ffff8b, 0x10f6b4e5, 0x6c012005, 0x18629b42, 0x180e4143, 0x2118e0e4, 0x1a83ccf9, 0xffce4c23, 0xa2f019ff, 0x18ff200e, 0x18b02ef8, 0x1a4adfe5, + 0x4826b146, 0x652c054d, 0xffffcccc, 0x0566e6c5, 0x33fcffff, 0xf43a8482, 0x7f89cccc, 0xf3ffff8b, 0xff089a99, 0x6666e7ff, 0xeeffff07, 0xffff9a19, + 0x1d82b3f5, 0xff2e1582, 0x3233edff, 0x80feffff, 0xeaffff00, 0x24823433, 0x4282bf20, 0x66120022, 0xb9274283, 0xff079a19, 0x82993900, 0xccd42a2f, + 0x888f05cc, 0x660200ff, 0x215a8266, 0x53829a19, 0x8319fa21, 0x70d62053, 0xf720059a, 0x8405035c, 0x820482f7, 0x828b200e, 0xdc80484b, 0x00ff8b2f, + 0x05b89e54, 0xffffe4f7, 0x1514ae9d, 0xf89318ff, 0x33332a0c, 0xd3ffff8b, 0x5b08cdcc, 0xc9f21807, 0xc4561816, 0x0c6d640c, 0xe418fb20, 0xf722187f, + 0x79180714, 0x4c20081f, 0x0c9ca118, 0x1883bb20, 0x33332c23, 0xc76219ff, 0x5b8b220f, 0xa2bb1815, 0x075b2316, 0x368406cb, 0x18b31121, 0x2611d6bb, + 0xf794f70e, 0x827b15e4, 0x05b96a55, 0x19ccf821, 0x180eb466, 0x83092eb4, 0x24958271, 0x0834332c, 0x212f829b, 0xc8710800, 0x208a8205, 0x05c87107, + 0x088bcd22, 0x18749618, 0xff15bb26, 0xcd4c0d00, 0x1175bd18, 0x1805744f, 0x20089395, 0x054c5fcc, 0x185b0821, 0x182e1096, 0x4f127496, 0x629608d0, + 0x9618fb20, 0x4c201c74, 0x1271b918, 0x09749618, 0x9618cd20, 0xb3200791, 0x0d24fe82, 0x088b0040, 0x10749618, 0x0eddab18, 0x5ef5ff21, 0xcd2005e2, + 0x9618e097, 0x4c200a74, 0x42172773, 0x2e210d7b, 0x067f6314, 0x240bbe41, 0xf8ffffcc, 0x720482cc, 0x96180649, 0xdd630b44, 0x079b2408, 0x414b64f7, + 0x35a50cf4, 0x9616bd73, 0x2b8b2195, 0x21057464, 0x6f64ffcd, 0x33dc2405, 0x64ffff33, 0xc0180674, 0x871809d7, 0x9b200a56, 0x1817db42, 0x830d11e8, + 0x82ff20c6, 0x7b082640, 0xab14fb07, 0x431c9815, 0x7cc00598, 0x8a6b2b21, 0x86c182c6, 0x8bcd23c6, 0x8582ff08, 0x65823320, 0xcdccf823, 0x82c696ff, + 0x83232018, 0x063d651d, 0x18cc0821, 0x08129c96, 0xff077b20, 0x757303ff, 0x6674ffff, 0xffff1566, 0xffc12afe, 0x34b30e00, 0x6e0b00ff, 0x0c00ff98, + 0x0e8266e6, 0x821fc521, 0xc801296e, 0xff064861, 0x66e60d00, 0x08d4321a, 0x829a1921, 0x34332630, 0x4cf1ffff, 0x398f82cc, 0xff32b3f9, 0xcecccdff, + 0xe6d9ffff, 0xd8ffff68, 0xffffcccc, 0x82cccccf, 0xcf638908, 0xfffe2818, 0xff069a19, 0x8333efff, 0x82f020c9, 0xc55f1830, 0x828d200a, 0xbdd02399, + 0x4e829471, 0xff4ee224, 0x68832700, 0xdbb9f936, 0x333200ff, 0x00ff0832, 0x06420000, 0xf8ebaf0e, 0x00ff1554, 0x09214d19, 0xabf1ff22, 0x2407d77d, + 0x064b072b, 0x1c4018eb, 0x190e2008, 0x220d4714, 0x188b54f7, 0x970e4c7e, 0xb0171937, 0xfbcb220d, 0x18378e34, 0x290b847e, 0xff33b3fd, 0x34b3ffff, + 0x0985ffff, 0x82989921, 0xcdcc2a09, 0xb6ffff08, 0xffff0080, 0x201e83eb, 0x29c783ca, 0x8b6666bb, 0xb3afffff, 0x06820834, 0x9a99f435, 0x190100ff, + 0xf4ffff9a, 0xff8d66e6, 0x3433f5ff, 0x4fff8008, 0xf4210568, 0x20518233, 0x201b83fc, 0x503c83f3, 0x9c22058a, 0xdb82cccc, 0x6300ff25, 0x82073433, + 0x52f82b5a, 0xb30f00ff, 0xc9ffff32, 0xac18ae07, 0xab200b24, 0x0e632b19, 0x8bcd4c27, 0xb31100ff, 0x86851833, 0xd4f72617, 0x64fb4b06, 0xda581815, + 0x00ff215b, 0x01600c11, 0xcd02101c, 0xf7234e01, 0x5164fb74, 0x5018d893, 0x8b203122, 0x012f0510, 0x25f718b1, 0xa80710c8, 0xda444f01, 0xa45d1860, + 0xf506106a, 0xc3494e01, 0x18f7205f, 0x10d03d5d, 0xae018002, 0x490ee955, 0xe9553108, 0x2b5918b1, 0x9601344a, 0x01ff9a19, 0x159a5982, 0x4c0900ff, + 0xfeffffcc, 0x188f5c8f, 0x3b0bd596, 0x08142ef9, 0xdbffff65, 0x94055c4f, 0x00ff0557, 0xff008000, 0x9a99f6ff, 0x33f7ffff, 0xdf518782, 0x68662a05, + 0x4c0400ff, 0xffff08ce, 0x241e82d1, 0x00801800, 0x260a8205, 0xffff9819, 0x823233e7, 0x82f7200a, 0xfbff2320, 0x398234b3, 0x00286382, 0xff343307, + 0x66660100, 0x082d7284, 0x3400ff94, 0x65059a19, 0xfd2400ff, 0x202c8270, 0x241d83f9, 0x8fecd106, 0x057a73ff, 0x00249683, 0x08a47001, 0x4c262782, + 0x0700ffce, 0x87823e8a, 0x98991727, 0xc72f00ff, 0x820a822a, 0x00ff2779, 0xfffa9e08, 0x92830c00, 0x18a4ff27, 0xe60300ff, 0x21a18268, 0x3482eebc, + 0xff232983, 0x82d638d0, 0x82342029, 0xf8ff233f, 0x6582c275, 0x66e6e927, 0xa63dffff, 0x17bf4f66, 0x19a50d19, 0x194b4318, 0x19740d19, 0x0614f724, + 0x3e1974fb, 0xff210d1f, 0x082b50f1, 0x180c9655, 0x7e0c26ce, 0x965519bf, 0x1854200b, 0x820c3f95, 0xb4f7216b, 0x18e30819, 0x1c561d82, 0x514b2016, + 0x84851797, 0x0a6b2819, 0x2708c86a, 0xef0e07cb, 0x1534f8ab, 0xab255182, 0x00ff8b85, 0x1889820e, 0x360af655, 0x00ff076b, 0x06333355, 0xccaaffff, + 0x55ffffcd, 0xff0534b3, 0x184c4aff, 0x750a8386, 0xf8202486, 0x21058156, 0x608584ab, 0x7c206582, 0x20087085, 0xff078b08, 0x34331501, 0xff1594fb, + 0x9999b5ff, 0x5f00ff06, 0x54f7ffff, 0x4a00ff05, 0x2b066866, 0x240983fb, 0xf7989995, 0x88a18254, 0x22298211, 0x83eb0698, 0x00ff2425, 0x848b0100, + 0x8267201a, 0xff9f22a3, 0x823083ff, 0x859a201e, 0x7501281e, 0xffff3433, 0x82cc4cea, 0xb3352122, 0x2f147d18, 0x305fc818, 0x0734f727, 0xccaaffff, + 0x20c582cc, 0x2d788255, 0xcc4caa00, 0xf7ef0e05, 0x1554f8f4, 0x6f1894f7, 0x9e520e6a, 0x19fc2008, 0x20184c10, 0x203382fb, 0x9d8718ff, 0x83f82014, + 0x19002033, 0x25134028, 0x1574fbf3, 0xa356074b, 0x0a002206, 0xf7bf18b3, 0xbfc01823, 0xffcc210b, 0x33203482, 0x21121568, 0xc218f5ff, 0xbb240861, + 0x8b1534fb, 0x08647019, 0x66823184, 0x67104768, 0x91b10aaf, 0xd4f75b22, 0x4021c7b6, 0x05156800, 0xc00a0022, 0x2013dd68, 0xa2d518ff, 0x3cfc2909, + 0x94f7156b, 0x63074b06, 0xb3230382, 0x19072b06, 0x4316152c, 0xdb430b56, 0x186b200c, 0x2c179247, 0xff8b07cb, 0x66e63500, 0x05d5ffff, 0x7fb2181f, + 0xe1fa2807, 0x07eb088b, 0x82cb06d3, 0x18ff206f, 0x6e0c65db, 0x34200d56, 0x21072443, 0x2443cc4c, 0x3cf72406, 0x823b154b, 0x82db20a3, 0xef0e2e3b, + 0x33d500ff, 0x1534f833, 0xcc4a00ff, 0x561219cd, 0xfb421909, 0x07cb2126, 0xcc263783, 0x1b00ff06, 0xa5829a19, 0x9a191822, 0xeb248c82, 0x0900ff84, + 0xe6230983, 0x82083473, 0x32b334b0, 0x6e87ffff, 0xffff0515, 0xff9c19f5, 0x99190200, 0x82f4ffff, 0x54002014, 0x663105d6, 0xff088b66, 0x0080c4ff, + 0xcbffff8b, 0xffff6666, 0x200483e2, 0x224083e0, 0x83ceccd2, 0xcccc2240, 0x059c5407, 0x08f4fe18, 0x505acd20, 0x42378205, 0xff2409d2, 0x8b33b3f1, + 0xcd211783, 0x08644108, 0x0222c791, 0x4b82cc4c, 0xce4c0227, 0x4c0000ff, 0x218d82cc, 0x09823233, 0x82686621, 0x18fb204a, 0x20081ca1, 0x210983fd, + 0xd28299ef, 0x19efff24, 0x5582089a, 0x1182fa20, 0x2005c164, 0x26b983fa, 0xff008000, 0x82b3faff, 0xffff21de, 0xda825082, 0x8118878c, 0x4b2c07e9, + 0x36ffff07, 0xff06299c, 0x0ad7e1ff, 0xe7254582, 0x00ffcd8c, 0x21e98318, 0x57841e00, 0x83060021, 0x0f01237e, 0x0982ff5c, 0x8d823420, 0xffec1126, + 0xcccc0500, 0x752cf582, 0x01ff1ec5, 0x05ec914c, 0x330800ff, 0x19381a82, 0xffa4cc8c, 0x7c141100, 0x191b00ff, 0x8b088b99, 0xaa01ff06, 0xe4fbcccc, + 0x5fd8c452, 0x8b2131a5, 0xd1021006, 0x0025be01, 0xfbcdcc8a, 0x5c6558e4, 0x10c83553, 0xbd01bb05, 0x2b62e942, 0x99a600ff, 0xff158b98, 0x34b32400, + 0x05210484, 0xdc0919ff, 0xfb24101b, 0x0e230701, 0x18b4f7ef, 0x200cabd6, 0x067648cc, 0x34b31123, 0x3535198b, 0x0a8f5e0c, 0x35240949, 0xff66661e, + 0x4821aaff, 0xc7ffff05, 0xffff9a19, 0xff34b3fa, 0x1483d3ff, 0x9919d028, 0xc5ffff8b, 0x226533b3, 0xc6d31808, 0x14fb2314, 0x1c196b07, 0xff210960, + 0x483f82f1, 0xee2105e1, 0x1764194c, 0x5b844819, 0x4900ff30, 0xff0667e6, 0x66e60000, 0xfbcb054b, 0xa7491514, 0x53a41848, 0x0c654109, 0xab44f722, + 0x08cfe664, 0xffcbef30, 0x34334b01, 0x00ff8b15, 0xffcccc0f, 0xae871400, 0x350600ff, 0x0800ffc2, 0xffffaec7, 0x08a4b0f3, 0xb06200ff, 0x0528fba4, + 0x4c8a00ff, 0x288807ce, 0x87008021, 0xcdcc2128, 0xb3212888, 0x20289c33, 0x202889cc, 0x2028a534, 0x23668281, 0x66e63cff, 0x0e267d82, 0xffff3433, + 0x0482b3ea, 0xa982f020, 0x66e4ff30, 0xe6ffff66, 0x088b6866, 0xccfbfdff, 0x988206cc, 0xce4cea2a, 0xffb4f805, 0x32b3f5fe, 0x200d4a51, 0x285f19f0, + 0x06d42120, 0x180cc84c, 0x82090462, 0xcc102156, 0x12285f19, 0x0e06d42b, 0x14f8dbef, 0x0714fc15, 0x1b936553, 0x24122f65, 0x07b30693, 0x2033b083, + 0x65339eab, 0x9321117a, 0x65339f06, 0x9ba011cb, 0xbc184020, 0xc33a1174, 0x158bab06, 0xfc0634f8, 0x34fc0714, 0x0714f806, 0x155b8cf8, 0x07630683, + 0x4a760693, 0x06d54f16, 0x4518ff20, 0x83220e12, 0x33916b06, 0x770c2f66, 0x339411a4, 0x9807b276, 0x209bb167, 0x20d88353, 0x78d08ec3, 0x6896088e, + 0x00ff0e38, 0xff9a9990, 0xb81ea701, 0xf8ffff15, 0x00ff66e6, 0xffd8a30a, 0x14820700, 0x3d0e002f, 0x0c00ff70, 0x088bcccc, 0x33c400ff, 0x835a8234, + 0x231c850c, 0x90c2f1ff, 0xff243085, 0x08285cf5, 0x26061677, 0x0548e1b8, 0x850614fb, 0x47002f0d, 0xff05b81e, 0x0080bb00, 0x7a90ffff, 0xa86a15e2, + 0xb3db2c06, 0x7a00ff32, 0xffffcc4c, 0x82ceccb1, 0xe65a2c96, 0x568b0866, 0x8b566060, 0x82d4fb08, 0xfaca223a, 0x2c1582e1, 0xb61f05d5, 0x8b08c08b, + 0x19a500ff, 0x242f839a, 0x4e00ffcd, 0x27398233, 0xff33b338, 0xce4c2400, 0x04209382, 0x0320ae83, 0x04211e83, 0x261e824c, 0xffcccc02, 0x83cc0300, + 0x00802309, 0x8682f708, 0x66820d82, 0x8082fd20, 0x4c04002c, 0xfdffffce, 0xff8f3433, 0x7083fcff, 0x08820720, 0xcc4c6823, 0x65d31815, 0xffff221a, + 0x213983f7, 0xf8194c09, 0xff250cfa, 0x0833b3f6, 0x22e1825c, 0x820566e6, 0x227d8305, 0x829a192f, 0x202c980a, 0x183283ff, 0x821768d4, 0x8245843b, + 0xe6d02340, 0xd4185c66, 0xff30362e, 0x66e62f00, 0x332e00ff, 0xffba0534, 0xccccd1ff, 0x07527d19, 0xceccf522, 0x105bd418, 0x3b82f29c, 0x3c82ba20, + 0x53844982, 0xef0e053e, 0xccdc01ff, 0x5d01ffcc, 0xff15a4f0, 0x9c997d00, 0xf5e4ffff, 0xffa105c2, 0x3433faff, 0x23085b82, 0xffff9899, 0x8b9a99ec, + 0x80e9ffff, 0x072d0800, 0x19e0ffff, 0x2d00ff98, 0xffff3233, 0xff6866cb, 0x00801e00, 0x2505bf50, 0xd9ffff08, 0x28820080, 0xcc4cdc31, 0xb3f2ffff, + 0xe3ffff34, 0x08769a19, 0x820900ff, 0x0e003022, 0x00ff9919, 0x9c9a9905, 0x1300ff8b, 0x82083333, 0x832f2006, 0x99d82523, 0x2800ff9a, 0xcf203283, + 0x83050b51, 0xffff2106, 0xff231683, 0x8234b3d7, 0x4cd0224f, 0x212d82cc, 0x4583ceff, 0x66662722, 0xff226684, 0x94823000, 0x0f205b82, 0xff2f0682, + 0x9a990e00, 0x0c00ff8f, 0x00ff32b3, 0x82343306, 0x80e82689, 0xffff7000, 0x206083f0, 0x216082dd, 0x0483fcff, 0x4882da20, 0xffffff25, 0x82069899, + 0x205a8205, 0x01c51805, 0x072b2616, 0xfb058bcb, 0x192582a4, 0x2514106e, 0x332301ff, 0xbf820734, 0x91831620, 0x48a10f22, 0x9682d082, 0xf5150023, + 0x21e182c3, 0x9582cccc, 0x299c7d32, 0x0a1b00ff, 0x00ff053e, 0xff01008b, 0x9eaf5c00, 0x09270a82, 0x00ff66e6, 0x823c2a07, 0x66e621af, 0x0a3d3f82, + 0xffffcccc, 0x08c4d5f8, 0xffff1ff7, 0x056250a3, 0x3383feff, 0xa2ffff34, 0xff155c0f, 0x80b719ff, 0x184b2014, 0x220849f6, 0x6af62807, 0x00260551, + 0x8b0ad708, 0xc918ab08, 0x43190ecd, 0xcb2008aa, 0x00213182, 0x053d6c08, 0x7e82cd20, 0x82333321, 0x3333285a, 0x066b088b, 0x8f14fb8b, 0x8bcc2167, + 0x34201d83, 0x19054352, 0x862ce8b7, 0x82d18367, 0x0700216c, 0xf720c883, 0xf7236785, 0x6a54f774, 0xb618190e, 0xf8200e36, 0x8508466a, 0x6be4858a, + 0x6b200a3b, 0x0e635e18, 0xf618e988, 0x7c8408f9, 0x08200485, 0x08204d82, 0x60eb5e19, 0xff34fb29, 0x9a99eeff, 0x1affff15, 0x20956222, 0x05231aff, + 0xf0031009, 0xab21e402, 0x22371afb, 0x3d7c185e, 0x19ff205e, 0x10678c33, 0xe302fd07, 0x105f0c44, 0x37016814, 0xb4f7af25, 0x191554f8, 0x2010571c, + 0xf68719d6, 0x075b2107, 0x16646818, 0xff063b38, 0x5278f0ff, 0x5a00ff07, 0xffffcc4c, 0x05ae87bf, 0xb36500ff, 0x5f180634, 0xcc200ef0, 0xdc253f82, + 0xfb0834b3, 0xf0d11874, 0x44fb2417, 0x8204f706, 0x1a00261c, 0xffff0080, 0x210482ea, 0x04821500, 0x7218ff20, 0x802007d4, 0x128cce18, 0x0704fb22, + 0xff233682, 0x18a6dcff, 0x831372f9, 0x1800206a, 0x8313daf9, 0x823320a1, 0x4c5a27a1, 0x4000ffcd, 0xb2825278, 0xae873f22, 0x73098373, 0x8b240d4b, + 0x54fb8b07, 0x170ecf18, 0xa719d682, 0xcf182a8d, 0xdd8d0890, 0x6b64fb22, 0x200ffb4b, 0x225882cd, 0x4b3333f7, 0xbf1939fb, 0xf8221368, 0xbd183b04, + 0xb24c300f, 0x4ccc200b, 0xbd1808b2, 0xb289130f, 0x5b04fc22, 0xcb4ccf8f, 0x14f82254, 0x2267838b, 0x4c8b3433, 0x334d0998, 0xbde51811, 0xf8bd180d, + 0x0b334d18, 0x0c1de618, 0x0e066b28, 0xf7e4f7ef, 0x1c4d15b4, 0x18a67761, 0xdeffff22, 0x0026c682, 0x1542a09a, 0xba4e00ff, 0x203b5021, 0x9dffff34, + 0x8b0732b3, 0xcdffffc8, 0xffbe68e6, 0x9819c2ff, 0x0683088b, 0x838b9a21, 0x58662312, 0x0e824e8b, 0x0080e625, 0x57ffff07, 0xff2414ff, 0xcc4cc0ff, + 0x2421ba4f, 0x8ba4fb06, 0x11e71905, 0x37ba4f16, 0xcc21ff28, 0xf5feffcc, 0xcb42be5f, 0x417e4f09, 0x2119e24f, 0x67b714fb, 0x8e137e4f, 0x09164367, + 0xf784f724, 0x4951151c, 0x00ff2405, 0x84666627, 0x848b2004, 0x85082010, 0x05875106, 0xff201b84, 0x24119e51, 0x8b9a99d8, 0x821783ff, 0x8406832d, + 0x2032863f, 0x231b8230, 0xd364f708, 0x21cfaf58, 0xde1830fb, 0x94201b7b, 0x180e8346, 0x2309d3de, 0x14fb07b4, 0x680ce364, 0xfb210df2, 0x461c8234, + 0xf82f1452, 0x00ff0714, 0xffcd4cab, 0x5c4f0b00, 0x19ffff15, 0x251a021b, 0xff71fd9f, 0x376a9fff, 0x00c02105, 0xce2a2a83, 0xf5ffff8b, 0x00ffcccc, + 0x0f854006, 0x0a820820, 0x25823d20, 0x32b3f928, 0x210a00ff, 0x1a858b48, 0x4c060023, 0x201a82ce, 0x2140825f, 0x40835f00, 0x71821082, 0x703d0622, + 0x26822082, 0xb3214b82, 0x212a8433, 0x8e828b08, 0x82ff5f21, 0x63c92300, 0x841815d8, 0x2b210d91, 0x82278386, 0x20378258, 0x197e8408, 0x8317ac1b, + 0x82ff2068, 0x82052004, 0x20a98525, 0x21a99dcd, 0x8882852b, 0x34330622, 0xa9827084, 0xff9f2408, 0x0534f7ff, 0xb37400ff, 0xebfeff34, 0xfb15cc4c, + 0x0514fb14, 0xf70714f7, 0xff0e0614, 0x9a19c700, 0x821544f7, 0x83082032, 0x190823fc, 0x0e52ff99, 0xe6072305, 0x3d828b67, 0x33b30922, 0x06241b82, + 0xffffcd4c, 0x20116e52, 0x52e982f9, 0xf622056e, 0x2d82cd4c, 0x19f8ff21, 0x7c084958, 0xff250a4c, 0x66e67000, 0x07a6438b, 0xdf7d2f85, 0x14487d0b, + 0x07209087, 0x0484c883, 0x62829f82, 0xd3180020, 0xff3414db, 0xcc4cc8ff, 0x011001ff, 0x00ff15be, 0xff9a9905, 0x3c0b0000, 0x66300982, 0xfeffff66, + 0x00ff3690, 0xffcecc04, 0xea51fdff, 0xcc20d182, 0xa9261483, 0xff053889, 0x5c820b00, 0x42fbff23, 0x26f28290, 0xffff0080, 0x82842bf6, 0x32b32238, + 0x2525827e, 0xff34b305, 0x1583a0ff, 0x9a19dd25, 0x832fffff, 0xcc3d2b0e, 0xaaffffcc, 0xff083233, 0x1483fbff, 0x3e83fd20, 0x2383f920, 0x6866fe22, + 0x33211382, 0x213e8232, 0x1e829819, 0x1983fa20, 0x82e6ff21, 0x82fa2014, 0x0100236d, 0x24569899, 0xcc022206, 0x251e82cc, 0xff33b33e, 0x92835500, + 0x6626dd25, 0x82d000ff, 0x050028bb, 0x00ffb89e, 0x8200805f, 0xb500237b, 0x928298c3, 0xffcd8c26, 0x7cd40900, 0x3521a682, 0x21c182c3, 0x1a8270bd, + 0x285ccc27, 0x765600ff, 0x21bc82c8, 0x1f82cc04, 0x16ae0222, 0x8282e682, 0x6f010023, 0x2d0982ca, 0xffff9999, 0x08c4f4ff, 0xffff068b, 0xf382ccde, + 0x42fe2f2c, 0x05cb4b15, 0x8b0714fb, 0xe718b656, 0xb6350962, 0x08c08bb6, 0x4b0714f7, 0xffff054b, 0x069a19bf, 0xf7b4f70e, 0x05a34184, 0xae473320, + 0xffcd2508, 0x3433f7ff, 0x09d1a819, 0x82e6f721, 0x330729ad, 0x00ff8b33, 0x08cdcc08, 0x0b820685, 0x489a1921, 0x1582057a, 0x0e913819, 0xccf8ff22, + 0x22077848, 0x83e0ffff, 0x10d020e7, 0x0c01a301, 0x9a99a03e, 0xcbe1feff, 0xffff150e, 0xff3433ee, 0x3433deff, 0x8000ff05, 0x054b66e6, 0x06bb07cb, + 0x0b964018, 0x0abb4218, 0x4306be55, 0xa8560593, 0x8b342408, 0x41064b08, 0x002705bb, 0x05cc4c0e, 0x82faffff, 0x0a00265d, 0xffff68e6, 0x4da118f4, + 0xe6f32908, 0xff088b68, 0x66e6d2ff, 0x2105c569, 0x7682b3dc, 0x3333e422, 0x23059055, 0xcdccdbff, 0xfb231e83, 0x828b33b3, 0x2035833f, 0x21448200, + 0x2082fbff, 0x33010026, 0x068b0832, 0x0026a985, 0x1534336e, 0x4769075b, 0x00ff2205, 0x231f820f, 0x33b3f1ff, 0x12247d18, 0x327e8b82, 0x07cb2207, + 0x3a0d195b, 0x0762470f, 0x01ff0e28, 0xffcc4c00, 0x0210c001, 0x080b011e, 0xcc090028, 0x94feffce, 0xff15dc97, 0x9a196200, 0xcc6300ff, 0xffa705cc, + 0x67e61c00, 0x4cfeffff, 0x3000ffcc, 0xffff9919, 0x1a8299df, 0x9a191b30, 0xe5ffff08, 0x00ff32b3, 0xff34b317, 0x0483d7ff, 0x9899fb25, 0x82e6ffff, + 0x2018821e, 0x201e8234, 0x2e3382f6, 0x6666f6ff, 0xf5ffff05, 0x00ff0080, 0x829a9909, 0x83e7200a, 0x831a200a, 0xccd62a1a, 0x0400ffcd, 0xffff6866, + 0x230982e4, 0xcc4ce8ff, 0xe0203482, 0xff231e82, 0x8366e6e4, 0xffcd3072, 0x67e6cfff, 0xe3ffffa7, 0xff089919, 0x82666000, 0x339c2715, 0xff920534, + 0x2182f9ff, 0x99295082, 0x0500ff8b, 0x00ffce4c, 0x27908206, 0x2f0e078b, 0x15f4f78b, 0xe7181382, 0xd420144d, 0x20180448, 0x18884ed4, 0x514e3382, + 0x07d42616, 0xfb153bcb, 0x17f75934, 0x0800ff24, 0x89820ad7, 0x10dcb419, 0x33336627, 0x4200ff07, 0x26dc824c, 0x05999991, 0x830200ff, 0xccf921fc, + 0x082dc482, 0xffff3333, 0x929a19fd, 0xe60100ff, 0x20f18266, 0x82e58306, 0x00ff240a, 0x8267e603, 0xcc4c21e4, 0x33235183, 0x83f70834, 0x08002377, + 0x0048cccc, 0x33072406, 0x47ffff34, 0x44471016, 0xffff340a, 0x07cccc99, 0x9ebeffff, 0x6e00ffb8, 0xff056866, 0x6a4cfcff, 0xff2405ca, 0xd7a3f8ff, + 0x6b828682, 0x11f9ff29, 0xfeffffeb, 0x82089a19, 0x220a8657, 0x83fbffff, 0xb3f92196, 0x2606594d, 0xf7078b08, 0x4b34fb34, 0x1d830908, 0x8982f820, + 0xcd208e82, 0x0d50da18, 0x230a9647, 0x06bb07db, 0x180bd14c, 0x200d99da, 0x05065b08, 0x220c534e, 0x91ab065b, 0x82838233, 0x46cc2066, 0xfc82050c, + 0xcb187784, 0x4b210997, 0x62441806, 0x21fe8a0b, 0xb48234fb, 0xb483f720, 0x8e053441, 0x35cc1837, 0x0bdd4116, 0x8e0d394e, 0x289687ca, 0x0e0734f7, + 0xf814f82f, 0xe3701834, 0x096e4a0e, 0x42356942, 0xfb2219d1, 0x8e504b44, 0xffab255c, 0xcc4c2dff, 0xd6286282, 0x00ff9a99, 0x05ce4c29, 0x2506f345, + 0xffcc4c07, 0x1483f5ff, 0xcd4c0322, 0xe6270982, 0xfeffff66, 0x82086766, 0x82cc200a, 0x43fe200f, 0x672305fb, 0x82f9ffff, 0xfcff2123, 0xcc210e84, + 0x231e82cc, 0x2b71fdcf, 0x17354483, 0xf0ffff0a, 0x00ff3433, 0xfff66806, 0xccccecff, 0xcf0f00ff, 0x225d825c, 0x82089a19, 0x2144830a, 0x738219f8, + 0x33331322, 0x66262382, 0x0700ff66, 0x188367e6, 0x1e82ce20, 0x14831c20, 0xcc4c382b, 0x3600ff05, 0xffff9999, 0x210a84c9, 0x6f82660c, 0x6f82f320, + 0x83100021, 0x83f9203e, 0x8011233e, 0x30828b00, 0x66662428, 0x1d00ff8b, 0x04840080, 0x10820a82, 0x66221682, 0xa4189a19, 0xff210724, 0x21c282e6, + 0x33821900, 0xc818ff20, 0xc61807ac, 0x1b83083b, 0x83ff8b21, 0x29c08217, 0x07cc4cc5, 0x34f72f0e, 0x576674f7, 0x0e002407, 0x85ffcd4c, 0xb3112204, + 0x058d6733, 0x63823320, 0xff6f1683, 0x06be460a, 0xff201183, 0xee200485, 0x0ff69419, 0x220abe46, 0x184b0cf7, 0x821befa4, 0xf5ff215f, 0xea187683, + 0x0023108b, 0x1933b30a, 0x20088204, 0x208d83cd, 0xde71180d, 0x83f52009, 0xf2ff270a, 0xf30834b3, 0xa54294f7, 0xffff2968, 0xffcdcc47, 0xcc4caaff, + 0xe225d283, 0xffffcecc, 0x26a482dc, 0xcc4cf1ff, 0x83ebffff, 0x821420c5, 0xffff2e91, 0xff9999f6, 0x66660900, 0xccf0ffff, 0x34f618cd, 0x9a992208, + 0x831a8208, 0xb3f6222f, 0x20158232, 0x213f82f0, 0x35820900, 0x1a822f82, 0x83140021, 0x83eb201a, 0x83f1204a, 0x99dc273a, 0xe2ffff9a, 0xf982c2b5, + 0xbdf2ff29, 0xffff8b70, 0x828f42f5, 0xde4a1804, 0xcccc260c, 0xbd0a00ff, 0x26168271, 0x00ff3433, 0x8290420d, 0x1d00272d, 0xff8b3e4a, 0x3f830e00, + 0x99834484, 0x66ebff23, 0x217e8866, 0x7e849a99, 0x7e8a3b82, 0xf620af84, 0x00233482, 0x8233330f, 0x6609223f, 0x21c48467, 0x9984ff08, 0x32230482, + 0x832300ff, 0x4cf122ae, 0x233f82ce, 0x08cccce2, 0x2108bd74, 0x9984cdcc, 0x3b828282, 0x4b183182, 0x6b1809f2, 0x54820a18, 0xa6831d20, 0x59832320, + 0x82b30e21, 0x8214204e, 0xebff2304, 0x3182ce4c, 0x34207e8b, 0x09212982, 0x839e834c, 0x090023b4, 0x89846866, 0x0f201582, 0xff233f82, 0x849899f6, + 0x20cf820f, 0x201a83eb, 0x20b48314, 0x2514830e, 0xff666623, 0x9e821d00, 0x0d225082, 0x30823233, 0xcecc0a27, 0xcc0a00ff, 0x220a82cc, 0x8234330d, + 0x0d0021b0, 0xff225882, 0x7d8233f5, 0x34b30a28, 0xccf2ffff, 0x48828bce, 0x82b3e221, 0xf1ff212d, 0x44844e83, 0x4e831420, 0x34b31422, 0x7e8a9984, + 0x86ff3221, 0x21b4837e, 0x4182f6ff, 0x1807e841, 0x41072270, 0xd58305cd, 0x0482ff20, 0xffffcc29, 0xff9999dc, 0x83b30e00, 0x331d22d4, 0x21828532, + 0xf542ffce, 0x00c02106, 0xb3218282, 0x23828333, 0x8bcdccf2, 0x33211682, 0x21048233, 0x0a820040, 0x82b3f221, 0x0e06342d, 0x00ff30fb, 0xf80080de, + 0x00ff1524, 0x06008041, 0x19b68bc0, 0x290d2708, 0x8b566060, 0xdb066308, 0x9b46b307, 0x1e67460f, 0xff06472c, 0x0080fbff, 0xff0524fb, 0x59882800, + 0x8266e621, 0x19ca227b, 0x0756659a, 0x59827b20, 0x470d2754, 0xd3180a10, 0xff2416bd, 0x9a19d4ff, 0xfc225d82, 0x5d836666, 0xb3ffff22, 0xf725d582, + 0xffff9a19, 0x2a0983f8, 0xff66e6f8, 0x3433f6ff, 0x8283088b, 0x2112836b, 0x1c830700, 0x002b2683, 0x0866e608, 0xff05ab8a, 0x8399d8ff, 0xccea2242, + 0x212382cc, 0xba1833ed, 0xff220ddb, 0x30821600, 0xcc120026, 0x1100ffcd, 0x00214d82, 0x214d8315, 0x388206af, 0x77827820, 0x47e1cb22, 0xd4233482, + 0x66b6b81e, 0x2f2a0505, 0x00ff9a99, 0xff008023, 0x04832700, 0x01802c2b, 0x990700ff, 0xffff089a, 0x052279a1, 0x3433f725, 0x190800ff, 0x820d2f22, + 0x66662159, 0x21052241, 0x8f8224f7, 0x9999d627, 0xffff8206, 0x267882ed, 0x70bdecff, 0x82f2ffff, 0xe9ff2678, 0x088bf6a8, 0x1826827b, 0x222d14ce, + 0x82008069, 0x83fe2033, 0x05102997, 0xff8b051e, 0x68a60000, 0xa3210583, 0x2e0584d6, 0x00ff08d8, 0xff666601, 0xb89e1000, 0x830d00ff, 0x6e0d2227, + 0x220e8214, 0x828b66e6, 0x8210201a, 0x23168506, 0xec91f2ff, 0xd6823c82, 0x61efff24, 0xf6820848, 0x285cff22, 0x2a200584, 0x59250583, 0xffff0898, + 0x211d84ff, 0xc482e2fa, 0x9a997024, 0x6182155b, 0x0ad70825, 0x82f9ffff, 0x070028c5, 0xfffff628, 0x828f42f6, 0xf8ff2356, 0x34825c0f, 0xa4f0f723, + 0x8c8118ff, 0x3433260e, 0x0f0800ff, 0x2616825c, 0x00ffcccc, 0x82a4f007, 0x0900232d, 0x498271bd, 0x90420622, 0x0b064d18, 0xf7ef0e25, 0x18b4f754, + 0x822e37ac, 0x19112046, 0x28293f49, 0x1534f76b, 0x4c0600ff, 0x353682cd, 0xff33b305, 0xc04afcff, 0x990200ff, 0xfaffff9a, 0xff08b23d, 0xa4821800, + 0x93c8ff27, 0x00ff05b6, 0x22568338, 0x82f6a815, 0xe605220a, 0x21258266, 0x3a820040, 0xff2d1482, 0xff7c94fe, 0x66660400, 0x8afbffff, 0x2234823e, + 0x83008004, 0x413c200a, 0xff260577, 0xff7c54f9, 0x4883fdff, 0x281cfa2d, 0xeaffff08, 0xffffce4c, 0x82ae47c7, 0x83372048, 0x33e72234, 0x200a8234, + 0x25208305, 0xffcc4cfe, 0x53830300, 0x6666f929, 0xf9ffff8b, 0x850834b3, 0x829a8206, 0xfaff211b, 0x33210484, 0x21508234, 0x4b826666, 0xaa83c820, + 0x15224085, 0x568232b3, 0x82cc4c21, 0x8302204b, 0x19fa2120, 0xfe20c582, 0xf9201f83, 0xfb203483, 0x99219484, 0x0741779a, 0x19840f84, 0x2d832384, + 0x37820020, 0xc7201e82, 0x00202e82, 0x05224d82, 0x5982ffff, 0x82ffff21, 0x200a8263, 0x20aa83fd, 0x215884fa, 0x8d86cd4c, 0x6f44f920, 0x82068305, + 0x676621ab, 0xc584bb86, 0x4b82cf82, 0x3333e724, 0xe58200ff, 0xf1824082, 0x0a82fb84, 0x291cfa22, 0xf083c082, 0x7b54f922, 0x27062541, 0xff3d8afb, + 0x00800400, 0x0a853482, 0xfe216f83, 0x221e8294, 0x4134b306, 0x0521066d, 0x28f382e6, 0xf6a81500, 0xb33800ff, 0x26488234, 0xffb693c8, 0x82cc1800, + 0xfaff23f3, 0xb941b23d, 0x4afc2e06, 0x0500ffc1, 0xff8b34b3, 0xcc4c0600, 0x82068508, 0x3fb5219a, 0x99211082, 0x211b829a, 0x74824ec2, 0x0834b322, + 0x6c219a82, 0x2240874a, 0x820a57ea, 0x52b82156, 0xfd225682, 0x258200c0, 0x82d8e321, 0x856b2125, 0xab213482, 0x219a8284, 0x0483c375, 0x8808c421, + 0x83c2200a, 0x211e8219, 0x1e826b01, 0xd7e30522, 0xc020d282, 0x0023be82, 0x8252b838, 0x0a5722e8, 0x20598305, 0x826384cd, 0x8301200a, 0x830520c5, + 0x99062279, 0x208d8399, 0x05784240, 0x078b0829, 0x1574fb8b, 0x182300ff, 0x2208a37c, 0x19b31c00, 0x204db903, 0x206082ec, 0x0e8c7cf3, 0x2c78cd18, + 0x0e20b082, 0x2212b17a, 0x8200ff67, 0x06b17a16, 0x063cf824, 0x017a44f7, 0xffff252e, 0x079a99ea, 0xcc314582, 0xf8ffffcc, 0x00ffcc4c, 0xff343309, + 0x9a99f0ff, 0x221a828b, 0x82080080, 0xb3ec2106, 0xea2a1182, 0xffff0080, 0xff3233df, 0x0983e5ff, 0x9a19e623, 0x230a8508, 0x66e61900, 0xff2a2a84, + 0x00802000, 0x1300ff8b, 0x35829a99, 0x82150021, 0x234c8426, 0x66660f00, 0x00296085, 0x0834b307, 0x4c1600ff, 0x25a583cc, 0xffcd4c2b, 0x77822300, + 0xb3240023, 0x05e95133, 0x0b211c82, 0x05ef6866, 0xffffce23, 0x217782fc, 0x20820900, 0xb3fbff23, 0x221a8233, 0x85999917, 0x88ce2037, 0x88322037, + 0xd5761837, 0x4cdb220a, 0x22b582ce, 0x8232b3d4, 0xb3c922a1, 0x20ddee34, 0x21dd8536, 0xc182cc10, 0xc183f120, 0x1a330f21, 0x7a09f906, 0xe86f0afd, + 0xfeff2c09, 0x079a19ef, 0xd4f8af0e, 0x571534f7, 0x7e1806fb, 0xfb57075a, 0x57f4200e, 0xf72117fb, 0xb2f71894, 0x18f82017, 0x2518e5f6, 0xfc0734fb, + 0x5118eb74, 0x0b190cf9, 0xf71811be, 0x7b700fad, 0x209c8a0b, 0x2717828b, 0x00ffcc4c, 0xff7b540e, 0x29056f73, 0x8b85ab11, 0xfbf4f708, 0x6b571594, + 0x14fb3005, 0x0e0514fb, 0xf774f7af, 0xff8b15f0, 0x820c1800, 0x2121082d, 0x00ff34b3, 0xff20052e, 0x00801200, 0x701700ff, 0x00ff08a4, 0xff981906, + 0x4cb70700, 0x660b00ff, 0x83298268, 0xf8ff230f, 0x1a82b448, 0xff252583, 0xff5c8fe8, 0x23398300, 0xe0fad1ff, 0xe7237782, 0x820834f3, 0xe6de2206, + 0x06c35366, 0x9a19e522, 0x2005ae6b, 0x20068308, 0x271b8233, 0xffcd4ce3, 0x66e61a00, 0x21284d82, 0x8b089a19, 0x6f34fb07, 0x8526f782, 0xff060080, + 0x2e830d00, 0x8983da20, 0x99992325, 0x83e5ffff, 0xcc2923c6, 0x6f828bcd, 0xcccc2922, 0x23223282, 0x3d829a99, 0x2a832083, 0x4c250023, 0x851a82cc, + 0x4c23213b, 0x1c202083, 0xee181b82, 0xfb210a46, 0x07c15934, 0x8336c541, 0x191c2081, 0x240def19, 0xfbab078b, 0x0faa4114, 0x0c8a5218, 0xc6183320, + 0xcd20080d, 0x08bd7d19, 0x8118ee20, 0xf44d08c2, 0x07aa4111, 0x3d443320, 0x11aa4106, 0x0d01ff29, 0x01ff6666, 0x82fc09ba, 0x190b2b78, 0x0700ff9a, + 0x8b9ab0f2, 0x0b8300ff, 0x0df8ff2f, 0x00ff0850, 0xfffeffdf, 0x6adc60ff, 0x211c8205, 0x05536866, 0xcc043906, 0xf7ffffcc, 0xff8ccecc, 0x66e6f6ff, + 0xb4fbab08, 0xff828c05, 0x9c19fdff, 0x25831084, 0x04826420, 0x08ce4c23, 0x21068285, 0x2c823233, 0xff21f282, 0x826282fc, 0x8b683030, 0x0614fb08, + 0x74f714fb, 0x0774fb05, 0x840694fb, 0x828b2034, 0x7b542624, 0xe60300ff, 0x27338266, 0x00ff0eed, 0x08cecc06, 0xee210a82, 0x200a8214, 0x254382b3, + 0xffce1afd, 0x43820900, 0x01010024, 0x9b82944e, 0x13012023, 0x867982f7, 0xcc042514, 0x0800ffcd, 0x00236c82, 0x82676607, 0x9a192f32, 0xff74f708, + 0x96239f00, 0xffef0e05, 0x1e82f100, 0x19500123, 0x20ea829a, 0x20628308, 0x214882f6, 0xd655ffff, 0x225c8205, 0x823433f6, 0x26b18286, 0xb7ffff3b, + 0x8205ffff, 0x26e4840c, 0xffff33b3, 0x823433f2, 0x82f6209d, 0x08002e0f, 0xff08cd4c, 0x3d0ab0ff, 0x004800ff, 0x21258301, 0x7f826626, 0x4b839e83, + 0x4c0e0022, 0x0822a382, 0x1382b8de, 0x8266e621, 0x830a85a2, 0x2b0f2639, 0x0000ff85, 0x221e82cc, 0x829ad909, 0x981921eb, 0x272b1e82, 0xffffcd0c, + 0x059a19dc, 0x507a00ff, 0x0d2b0517, 0x00ff0040, 0xff9a990b, 0x82c00a00, 0x660c2209, 0x19291a67, 0xffff2818, 0x0766e685, 0x832800ff, 0xe623225e, + 0x21448266, 0xf982e609, 0x68e60822, 0x82051a50, 0x823220de, 0x82c28388, 0x8b0822de, 0x20658206, 0x237082cc, 0x156666e9, 0x80206482, 0x08285f82, + 0x00ff34b3, 0x8bcccc0f, 0xff230f85, 0x82cc4cf7, 0x00a82496, 0x8214fb02, 0x9906224e, 0x06245798, 0x68660425, 0x83f8ffff, 0x33012296, 0x21bd8230, + 0x268234b3, 0xd0cc1827, 0x4c5bffff, 0x202982cc, 0x214c8211, 0x8883ffff, 0x82190e21, 0xccf12933, 0xffff8bce, 0x086666ee, 0x167bbe18, 0x30e3c118, + 0x7f00ff24, 0xc0829a99, 0x63831820, 0x34b3a422, 0x01217382, 0x25bb8233, 0xffcc4c08, 0x7d820300, 0x66070023, 0x05e75a66, 0x19050027, 0x3cf7089a, + 0x20c183f7, 0x23148213, 0x0080c6fe, 0x4c28ef82, 0xff06cccc, 0x3433b3ff, 0xfb341882, 0xaf0e0714, 0x193802ff, 0x7101ff98, 0x90150ad7, 0x73fbffff, + 0x02214d82, 0x22e682e6, 0x828e82f9, 0x33f922b5, 0x82bc8334, 0xffff2206, 0x242782fd, 0x0080f9ff, 0x36268286, 0xff080080, 0x0200b0ff, 0xffff0543, + 0xff9a19f6, 0x9919f7ff, 0x83f0ffff, 0xcc002296, 0x190e82cd, 0x20093916, 0x613682f7, 0x0021052e, 0x059c71cc, 0x0900ff22, 0x08332883, 0xff08cccc, + 0x9a992100, 0x331e00ff, 0xfeff0534, 0x823e0a6d, 0x8f2125db, 0xe1ffff5c, 0x8805d271, 0x8354844a, 0x8268825e, 0x8272826d, 0x4cf6227f, 0x827d82cc, + 0xf1ff2469, 0x42ff33b3, 0xf62705c6, 0x00ffd723, 0x8267e608, 0x01b0231e, 0x9e82d347, 0x68f1fa27, 0x800400ff, 0x27c08200, 0x00ffac1c, 0x8b008006, + 0x7b820582, 0xff240685, 0x54e30200, 0x7d261082, 0x0500ff72, 0x2a82980e, 0x96838c20, 0xb9fe4f28, 0xff4700ff, 0xac8205be, 0x8229dc21, 0xf4dd2152, + 0x20084e42, 0x21138276, 0x7a8234b3, 0x82e22521, 0x054743c0, 0x86202521, 0xd4f02280, 0x2019827a, 0x228f8233, 0x824821f7, 0x70de2285, 0x2dce82a4, + 0xff050ad7, 0xc2f59201, 0xdeffff06, 0xf0826666, 0x82f62821, 0x82f6209a, 0x080023bb, 0x3a83b8de, 0x00ff3225, 0x82862b0f, 0x82e62068, 0xda0922ae, + 0x215983e0, 0x6982cccc, 0x821eda21, 0x22288319, 0x828acc00, 0x66e6260e, 0x22f7ffff, 0x271e820c, 0xfffeff4f, 0x4200b8ff, 0xa3284882, 0xffffce4c, + 0x15f6a827, 0x2105794a, 0x2582faff, 0x82040021, 0x07ad4268, 0xf726ad82, 0xa30834b3, 0xd08234fb, 0x18830120, 0x5c82f620, 0x4cfdff23, 0x83ac82cc, + 0x82f920cb, 0xf8ff2676, 0x850866e6, 0x245f8284, 0xffff9819, 0x264382fb, 0x34b3f6ff, 0x822b088b, 0x199f2db5, 0x0534f79a, 0xff0734fb, 0x66e640ff, + 0xf6231082, 0x828b14ae, 0x82262029, 0x190429cc, 0xf9ffff9a, 0x089285eb, 0xff200684, 0x22051a4f, 0x82cd4cfd, 0x236082ae, 0x48610100, 0x33200982, + 0x42827e82, 0x0100ff24, 0xe682713d, 0x04221883, 0x2c82d863, 0x00248d82, 0xffb89e06, 0x200bb142, 0x1796430b, 0xfb3cf73d, 0xaf0e0514, 0x8a5600ff, + 0x150cf83e, 0x757101ff, 0x00ff06c2, 0x8bcc4c42, 0x833500ff, 0x83ca20c9, 0xbdff210a, 0x6321ed82, 0x22a18207, 0x1833b3f2, 0x2008ca6d, 0x7c4618cd, + 0x0a002212, 0xd05c18b3, 0x82b32007, 0x2700262f, 0xffffcccc, 0x2e0482df, 0x34332000, 0x33d8ffff, 0xff088b34, 0x428a8efe, 0x8427dd9a, 0xffff28dc, + 0x42008021, 0xd120ea40, 0x2d3b0a47, 0xffff8b33, 0xff0ad7f6, 0xcd4c0800, 0x06473b08, 0x2b272108, 0x21080647, 0x0647ff75, 0xb2dd2106, 0x211c0647, + 0x064729dc, 0xa4f02108, 0x21130647, 0xe079c00a, 0x400d2307, 0xaa548b00, 0x7048180c, 0x0706470a, 0x66e62724, 0x064700ff, 0xf4f72324, 0x6e44158b, + 0x05c14505, 0x4845ff20, 0x82322005, 0x303321d8, 0x24050548, 0x00b0ffff, 0x20094802, 0x4182fe89, 0x48090021, 0x32200505, 0xe621fe87, 0x21fe8868, + 0x0a82cccc, 0x0f200483, 0x00222883, 0x1984cecc, 0xb982fe88, 0x21120548, 0xfe18b30a, 0x54570e97, 0x08ee790b, 0x6e82fe89, 0x6420fe87, 0x0024de85, + 0xffcc4c0e, 0x20070548, 0x2ed98234, 0x8b083433, 0xa9ffff06, 0xffff9a99, 0x42666649, 0xef23e7f3, 0x828c01ff, 0xb90123f2, 0xf8483a74, 0x5eba2108, + 0x210df848, 0xf848a245, 0xffff2405, 0x48c60b80, 0x4d461ffb, 0xff682207, 0x2a4d46ff, 0x6dffff38, 0xff060080, 0xccccf9ff, 0x802900ff, 0xffff0500, + 0xff0080fd, 0x04821000, 0x33f7ff26, 0x0e00ff34, 0xff211982, 0x280482f2, 0x9a190a00, 0xf73cfb08, 0x25238214, 0xffceccf7, 0x1e820600, 0x8f206b83, + 0x66267182, 0x0100ff67, 0xaf82cccc, 0xcdcca027, 0x8d7a00ff, 0x83af82d4, 0xe0fe233a, 0xd341c60b, 0xffff2655, 0x069a199f, 0x1e08472b, 0x474aec21, + 0xc7200508, 0x20080847, 0x0808474a, 0x0847d820, 0x00ff2405, 0x47edfe17, 0xd720100c, 0x21070c47, 0x0c4748a1, 0x00ff2405, 0x8371fda7, 0x470020fd, + 0xfb251e0f, 0x34f88b70, 0xaa271915, 0x1f4e1817, 0x076b2c18, 0xab06d4fb, 0x4bd4f707, 0x471cfc15, 0xcf7d052c, 0x05334711, 0x20054347, 0x09f45a00, + 0xfb079325, 0x19830674, 0x212e9823, 0x6c821cf8, 0xfb4b0623, 0x79ab8324, 0x465e1383, 0x12816d0e, 0x2524f55e, 0xaf0e07cb, 0x611874f7, 0xf88219ef, + 0xf8829420, 0x28173041, 0x74fb0654, 0x94f7152b, 0x0c154106, 0x0c08fc18, 0x20050459, 0x0f0a5cff, 0xfb079323, 0x34154134, 0x24fb4423, 0x0acb7a15, + 0xc082e5a6, 0x232a4541, 0x84f704f8, 0x0d864118, 0x09016318, 0x6f0f1141, 0xf7200d7e, 0x20151141, 0x772619cc, 0x0c114125, 0x24d17718, 0x071cf823, + 0x0f1141f7, 0x0cf1ec18, 0x6f160760, 0x68601828, 0x0757420e, 0xffaf0e36, 0xb89e3e00, 0xa9bd01ff, 0x00ff1538, 0xffe17a0f, 0x765ef9ff, 0xcd255d83, + 0x57edffff, 0x260e830a, 0xefffffb8, 0x8208b89e, 0x852208eb, 0xe6ffff1f, 0xffff2a1c, 0xffc235fa, 0xf6a8e3ff, 0xe2ffff8b, 0x8b08703d, 0x33e2ffff, + 0x0500ff34, 0x16823eca, 0xff32b331, 0xe17a0a00, 0x00ff0872, 0xff48a106, 0x82b3eeff, 0x33f722ba, 0x24508233, 0xffff6666, 0x224583f0, 0x82cd4cf9, + 0x9cef2250, 0x21608229, 0x19826766, 0xff9a5925, 0x82e60700, 0x5ef9271e, 0x1000ffb8, 0x1e826666, 0x5e7af225, 0x832100ff, 0x92f82d33, 0x2400ff6f, + 0xff8b0080, 0x9a192600, 0x00236f82, 0x82482126, 0x916d2130, 0x7a261682, 0x0d00ffe0, 0x2a83a285, 0x73866820, 0x60100028, 0x1200ffc4, 0x238266a6, + 0x82aee721, 0xd763214f, 0x5e2a6882, 0x078b0836, 0xc7c201ff, 0xec828bb0, 0x64661022, 0xca20a083, 0x99262782, 0xf8ffff9c, 0x0e825218, 0x8230b321, + 0x3c9f21ec, 0x0d274682, 0xffff0080, 0x829899de, 0x68662c41, 0x85dbffff, 0xffff8b20, 0x82b8ded9, 0xd9ff217c, 0xf820a883, 0xff211b82, 0x202583db, + 0x202a85f2, 0x22b2829a, 0x82d04cf9, 0x9a992140, 0x5e82d182, 0x19f8ff22, 0xef200982, 0x00235e82, 0x82999906, 0x82ef201e, 0x06002333, 0x6e8233b3, + 0x00211982, 0x82288212, 0xff9a2519, 0xcc4c1100, 0x0a2d7382, 0xffa40080, 0xcccc0500, 0x4c1c00ff, 0x20ec82ce, 0x05a64d1d, 0x90c21d23, 0x057e7fff, + 0x0a571c22, 0x2206d464, 0x82d6e319, 0x66f92250, 0x21dd8266, 0x3c414861, 0x12002305, 0x0e8238a9, 0x0023af82, 0x8288a106, 0xffff231e, 0xbb8207c0, + 0xff32b326, 0xfc892ffe, 0x0723f482, 0x827bcc4c, 0x66e6227c, 0x20a68278, 0x23d782e6, 0x0832b3f8, 0xb3221183, 0x43827832, 0x829c1921, 0x232d821c, + 0x98191000, 0xeb203e82, 0x2d335d83, 0xff053433, 0x676623ff, 0xebffff06, 0xffff6766, 0x82ccccd2, 0x83f82010, 0xe6ef22c5, 0x23488268, 0x7b64e6f8, + 0x4c223c82, 0x548208ce, 0x84b8de21, 0x2247820a, 0x829ed7e3, 0x5d4f220a, 0x27d9829b, 0xffae0789, 0x98992d01, 0x80233883, 0x8200ff00, 0xffff22e9, + 0x21fe83fb, 0xe883cc0c, 0x66e60d23, 0x086c6208, 0x00225982, 0xd882a61c, 0xcd4c2323, 0x533c828b, 0xd1620b7e, 0xff8b2508, 0x9a19f2ff, 0xff234485, + 0x823233f3, 0x2b588270, 0x0080f5ff, 0xff1df708, 0x6866d2fe, 0x94206b82, 0x002a2182, 0x15cccc52, 0x80f1ffff, 0x1182ab00, 0x99997a23, 0x240c8406, + 0x00ff056b, 0x29d484a2, 0xeb323389, 0x4b00ff15, 0x19823433, 0xf283da20, 0x33b35222, 0x0a832a82, 0x4cadff23, 0x250a82cd, 0xf79a999d, 0x72821534, + 0x9a99ec26, 0xedffff8f, 0x0722b883, 0xee82cd4c, 0x82666621, 0x830520a0, 0xe6f3250a, 0xfaffff66, 0xf1218383, 0x221982cc, 0x83ccccf3, 0x0899299c, + 0xe6f3ffff, 0xf9ffff67, 0xf1201483, 0x00211482, 0x20238305, 0x22e483fa, 0x1833330c, 0x2007ddfc, 0x84528216, 0x1800273d, 0xff8b66e6, 0xe6421a00, + 0x20068205, 0x263084ff, 0xa4f01800, 0x820900ff, 0x16002344, 0x7386ea91, 0x230c0028, 0x0e00ffd8, 0x23823433, 0xffcc8c26, 0x99190c00, 0xb0218282, + 0x201e82a4, 0x2214820c, 0x83b3faff, 0x226e8319, 0x829ad9f1, 0x23738219, 0x9ad9f3ff, 0xbd417382, 0x46612205, 0x21cc8287, 0xd88548a1, 0x078b0825, + 0x838bd4f7, 0x88e520e5, 0x19e721ca, 0xf6203782, 0xe9204b83, 0x5182e983, 0xcf823220, 0xce20ca85, 0xf883ee86, 0x84060021, 0x22f483ca, 0x82660400, + 0x82fa20ee, 0x20998275, 0x21998233, 0x9983ce4c, 0x00267582, 0xff666606, 0xe9821000, 0x82040021, 0x12002261, 0x20e98366, 0x82588213, 0x220682f0, + 0x82fbffff, 0x1200266e, 0xffff2a5c, 0x222583f9, 0x8248a110, 0xb3fa22ab, 0x20408232, 0x203a8226, 0x21548405, 0x0e82d623, 0x4f21f384, 0x83e9835c, + 0x4f052333, 0x6e82ff5c, 0xfa219c82, 0x82f38373, 0xf3ff2373, 0x1e8228dc, 0xcccc0926, 0x6ee9ffff, 0x2306406c, 0x5c0fe7ff, 0xe082ed82, 0x0e38ed82, + 0xb3f100ff, 0xbc01ff33, 0x94153c9f, 0x810400ff, 0x0a00ff06, 0x948b9999, 0x7e2c8882, 0x34f708fa, 0xffafffff, 0x00ff057c, 0x1ea9851a, 0xd682fa20, + 0x83f4ff21, 0xb3f42167, 0x0e853382, 0x76824c20, 0x9a19ff24, 0x3d6a3b08, 0xf1ff2107, 0x70831c83, 0x4ceeff24, 0x5e6d8bcc, 0xab062305, 0x608254fb, + 0x66e64422, 0x2a2e365a, 0x80a0ffff, 0xffff0600, 0x8234b3ff, 0x99ff22cf, 0x20058498, 0x2256839a, 0x83343301, 0x83c88218, 0x8433201e, 0x83992018, + 0x56318518, 0x0658092d, 0x0e002111, 0x0d2d5918, 0x4400ff24, 0x998267e6, 0x00002023, 0x23a782f7, 0x9a19fbff, 0xc7185a82, 0x9d560ce2, 0x07db2b07, + 0x45f4ffff, 0x0000ff1e, 0x098266e6, 0xffc3b53b, 0x9a990500, 0x66faffff, 0x0b00ff66, 0xff083433, 0x0a17f8ff, 0xcc0f00ff, 0x057a65cc, 0x38130023, + 0x080e8252, 0xff5dcf28, 0x66e60700, 0xa000ff08, 0x00ff8f02, 0x05840050, 0xcc4800ff, 0x43feffcd, 0xff15c460, 0x0080c5ff, 0xcc3000ff, 0x0a8505cc, + 0x33cfff2a, 0x09f70534, 0x86ffff06, 0x00275d82, 0x1534b3a3, 0x833e00ff, 0x80cb2272, 0x83398200, 0x3400210a, 0xff270a83, 0xffce4cfb, 0x834c1c00, + 0x998b2239, 0x27318299, 0xffcd4cfb, 0x34b3e3ff, 0x2207d655, 0x829819c9, 0xe6f42760, 0xbdffff67, 0x3c829a19, 0x33b32d25, 0x832600ff, 0xddff210a, + 0x1c20b683, 0x00217683, 0x2268826d, 0x8333e3ff, 0xb32d2768, 0xd9ffff34, 0x418266e6, 0x7382f420, 0x84420021, 0x832b830a, 0x24158220, 0xf700808a, + 0x21548284, 0x6c1833f7, 0x5070076f, 0x07002111, 0x210ddd48, 0x056234f7, 0x34fb252e, 0xf7ef0e06, 0x02dd5312, 0xfb6508c0, 0x1584f7b4, 0x868a858b, + 0x9f08868a, 0x8b73997d, 0x5e8b0871, 0x8b5f6867, 0xfb067b08, 0x798b0734, 0x8b7a7d7c, 0x7d8b7908, 0x089d8b99, 0x7b0734f7, 0x688b5e06, 0x08b88bae, + 0xa398a58b, 0x8a08999f, 0x8b908b90, 0xc08b0891, 0x8bc1b6b5, 0xb68bc008, 0x08568b60, 0x5701ff0e, 0x00ff66e6, 0x159a99ea, 0x669dffff, 0x2b048367, + 0x00ff0566, 0xffcd4c41, 0x9a99beff, 0x07200a82, 0xff382082, 0xff9a19f8, 0xcc4c0300, 0x80f4ffff, 0xfdffff00, 0xffffce4c, 0x083233f5, 0x14820a83, + 0x1e82f520, 0xccf7ff22, 0xf7201482, 0x2208b14b, 0x8234b3fc, 0x0c00241e, 0x82053bcd, 0x48a12b35, 0x66fcffff, 0xf3ffff68, 0x4982299c, 0xff98192b, + 0x3f95f7ff, 0x660800ff, 0x22258266, 0x846095f7, 0x2423820a, 0x00ff54f3, 0x3028820c, 0x0e8d0300, 0x4c0b00ff, 0x00ff08cc, 0xf7830050, 0x238a8294, + 0xff0b5703, 0x22053769, 0x8215ae08, 0x33332130, 0xeb240e82, 0x0200ff85, 0x00236b83, 0x61cdcc0a, 0x0021056c, 0x22a4830b, 0x6accccfc, 0xbd83058d, + 0x41224582, 0xd3826666, 0x8232b321, 0x99622148, 0x0482ce82, 0x084e871a, 0x00200f83, 0x0021c482, 0x21248217, 0x04840e00, 0x82008021, 0x825f2034, + 0x5f002349, 0x3482866b, 0x66e61a2d, 0xe81a00ff, 0x2b00ff72, 0x828b9a99, 0x230f820a, 0x8e17e5ff, 0x1a2d2582, 0xffff68e6, 0x8b7a14e5, 0x5ed4ffff, + 0x830a82b8, 0x21e522df, 0x20da8248, 0x235a82a0, 0x0080a0ff, 0x4b826a83, 0x83f1ff21, 0x83e8200f, 0x83ff2004, 0x84f1203f, 0x3433216a, 0x20056047, + 0x23c182f0, 0x9438bb01, 0x0920dc82, 0xfa2c2c83, 0x00ff442b, 0xff33b305, 0x32b3f5ff, 0xf42a5c82, 0x4308f6e8, 0xff06e407, 0x41820300, 0x830d0021, + 0x820c20e1, 0x0a002b28, 0x00ff3433, 0x8b66e60e, 0x1c82e308, 0x0b7cb018, 0x7c008021, 0x082005f0, 0x95600685, 0xeaff2105, 0xff213482, 0x261b82e5, + 0xff063308, 0x8219f1ff, 0xf3ff21cf, 0xff214887, 0x829483fc, 0x3208245c, 0x82074306, 0x83f42037, 0x4cfa22a9, 0x238683cd, 0xf6ffff34, 0x33229a84, + 0x0a820833, 0xff999925, 0x8219faff, 0x82f42004, 0x05886581, 0x9919f623, 0x231a8290, 0xeb71fd3f, 0xf522f482, 0xc2827328, 0xff245082, 0xffe926f9, + 0x0e03c91b, 0xff9a1926, 0x17d90600, 0xff241684, 0x8dd70a00, 0x6b2c2a82, 0x00ff0884, 0xff8f02c0, 0x84006000, 0x22079f5b, 0x8280f504, 0x28ee8224, + 0x5278ffff, 0x660900ff, 0x2e768267, 0x8b08862b, 0x2f00ff07, 0xffff3333, 0x6b6cc704, 0xcc200ae7, 0x2408e76b, 0xf7088b34, 0x0f2d4834, 0x10ea5b18, + 0x82076d48, 0x4cee24dc, 0x18088bcc, 0x2319c276, 0x34fb07cb, 0x5f0e745e, 0x5d180af1, 0x2b2018a0, 0x0d9f5018, 0x2009b662, 0x059b62cb, 0x116a5d18, + 0x5506eb21, 0x52180572, 0x679609cb, 0x0d7b7718, 0x71489420, 0x66cc200f, 0x0820057b, 0x4c23688a, 0x8200ffcd, 0x00ff2981, 0x8b33b311, 0x0694f708, + 0x1d8c031a, 0x5142d420, 0x55e9180e, 0x075b2808, 0xb33200ff, 0x829c0634, 0x660f3162, 0xf9ffff66, 0x00ffcc4c, 0x7f66e60c, 0x4d00ff08, 0xff2a0b82, + 0x0534b3b2, 0x00ff7f97, 0xa582b306, 0x6d82ef20, 0xff087a26, 0xcd4c8dff, 0x17547818, 0x2716f95c, 0x568b066b, 0x8b566060, 0xca223c82, 0x24829a19, + 0x66e6d528, 0x08c08bb6, 0x188b14fb, 0x18899920, 0x4c187b20, 0xf72e177c, 0xb4f807d4, 0xff1564fb, 0x33b31200, 0xa083ff07, 0xcd2eaa83, 0xcdffff05, + 0x2b06cc4c, 0x0614f707, 0x208414fc, 0x21094443, 0xb3181500, 0x40180893, 0xff20160e, 0x0ae6d018, 0x43eaff21, 0x3f830f72, 0x20057743, 0x23548300, + 0xebd4f708, 0x295c0d70, 0x1920ffff, 0x1001ff9a, 0x668252f8, 0x0080f72b, 0x5e0900ff, 0xf0ffffb8, 0x09c36bcc, 0x0848a127, 0xb3f6ffff, 0x21048233, + 0x2d6d48a1, 0x232f820c, 0x2700ff08, 0xff294082, 0x059a19d8, 0xe659ffff, 0xec521866, 0x780e190c, 0x0a002211, 0xd71919c0, 0x00ff240c, 0x829a19a6, + 0xe6d82333, 0x4f186466, 0xdb2236b2, 0x4f1805db, 0x3b261a88, 0xf84f00ff, 0x02100552, 0x33ce01b6, 0x15eba4fb, 0xcc2700ff, 0x00ff8bcd, 0xff333320, + 0x9a991d00, 0x25200a82, 0x08052d69, 0x9a191a2a, 0x99d8ffff, 0xffffc39a, 0xff0080eb, 0x3e4a1b00, 0x00ff8408, 0xff842b08, 0x66e6f4ff, 0xf9ffff8b, + 0xffff66e6, 0x087cd4f7, 0xff232185, 0x84c2b5e4, 0x4e532031, 0xff2407c2, 0x34b3daff, 0xff235b85, 0x856666e2, 0x8b08256b, 0xabef0e07, 0x210c8f76, + 0x5051ff67, 0x9a592b06, 0x74f7088b, 0x1700ff06, 0x898234b3, 0x32b31433, 0x21f3ffff, 0xffff9648, 0x08b8deec, 0xcc3300ff, 0x221c82ce, 0x82cc4c19, + 0x8316201c, 0x82f1207d, 0x0a0028a4, 0xffffce4c, 0x8266e6e8, 0xcc343120, 0x89ffffcc, 0xff053333, 0x9899ffff, 0xe6feffff, 0x01285b82, 0xff8ad04c, + 0x64660000, 0xcc211482, 0x212582cc, 0x45183304, 0xe2210e7c, 0x0da61866, 0x61671809, 0x62f0200c, 0x4c210523, 0x172362cc, 0x20302945, 0x1798466b, + 0x2508b26c, 0x00ff7b54, 0xb619330f, 0x77180761, 0x57180efa, 0xeb210968, 0x6a571807, 0xff270816, 0x9a191f00, 0xb501ff07, 0x14fb66e6, 0xd5ffff15, + 0x05ebce4c, 0xccd4ffff, 0x072b06cc, 0xe65500ff, 0xfeff0666, 0x459a19ca, 0x2219be74, 0x2b4208d2, 0xe6fe2257, 0x132b4266, 0x0b99a718, 0x200c2b42, + 0x1f4b6bf1, 0x6b562b42, 0x2b42097b, 0x09f4480e, 0xf448eb20, 0x69ab2017, 0x85430ab0, 0x058b240e, 0x42152bcb, 0x45420830, 0x74fb230b, 0x4f4764fb, + 0xd4f7245c, 0x18ff152b, 0x480a17f6, 0xff294f0f, 0xcd4c1dff, 0xe62801ff, 0x31c68266, 0xff9919fc, 0xcecc0500, 0xb3f8ffff, 0x0200ff34, 0x574932b3, + 0xfdff2405, 0x820866e6, 0x3433270a, 0xfbffff89, 0x0a826666, 0x8bcecc22, 0x16822582, 0xde7a2b20, 0xff332105, 0x21072c51, 0xe679ffcd, 0x07a47f14, + 0x2b00ff28, 0xff073333, 0x61822200, 0xe6cbff28, 0x00ff0567, 0x5182e603, 0x8333fa21, 0xcc4c2442, 0x82fdffff, 0x06002190, 0x19248084, 0x00ff0899, + 0x4e087819, 0x34239f82, 0x19059a19, 0x2007ede8, 0x08781919, 0xff332596, 0xcdccf8ff, 0xf7230486, 0x188b3333, 0x410f1b7f, 0xcb320750, 0xf7ef0e07, + 0x6901ff94, 0x8b15a4f0, 0x289fffff, 0x068205f6, 0x66e6fe22, 0x1c2be282, 0xff070080, 0x9a190000, 0x83ffffff, 0x01003c10, 0xffff3233, 0xffcecce9, + 0x00800c00, 0xe6ecffff, 0x1200ff66, 0xffff3433, 0x820080f5, 0x66df2360, 0x3c820766, 0x1d67fa20, 0xffcc2905, 0x68e6faff, 0x990100ff, 0xfc223f82, + 0x20823233, 0x0a82a520, 0x331d0023, 0x275b8234, 0xff9919a5, 0x32b3e1ff, 0xfb200a82, 0xfe220a83, 0x2f826866, 0x82b89e21, 0x32b3272f, 0xd1fbffff, + 0x30828eeb, 0x7bd4fb31, 0xfdffff8e, 0x8b8fae87, 0x190500ff, 0x82ab089a, 0x04002160, 0x02257783, 0x00ffc335, 0x32508304, 0x8e3eca03, 0x05b3bd08, + 0x335100ff, 0xffff0734, 0x83999984, 0x26fb25bd, 0xfeffff66, 0xfa22a783, 0xae548fc2, 0xf0fb2506, 0x0300ff62, 0x61824782, 0x8327f121, 0xe79b215a, + 0xb3214582, 0x205e8632, 0x205e83cb, 0x25548305, 0xfff2f202, 0xef820500, 0xd104002e, 0x0200ffaa, 0xff0868e6, 0x643b8800, 0xcc216482, 0x226a82cc, + 0x83a4706a, 0x611f322b, 0x1900ff48, 0x00ff6666, 0xff14ae36, 0x9a991e00, 0x2227828b, 0x8200801f, 0x83182050, 0x51c9327b, 0xffff8bec, 0x08b89ee0, + 0xffab078b, 0x5c0fa6ff, 0x06894b15, 0x19150021, 0x20287c37, 0x2b6a8274, 0x9a19ebff, 0x99f2ffff, 0xeeffff98, 0xff279682, 0xff6866ed, 0x8266f9ff, + 0xd5ff2396, 0xd45ecc4c, 0x067b2117, 0x2416d65e, 0x34fb07b3, 0x06386606, 0x98110b5f, 0x00ff2636, 0x0734b32a, 0x827d82ff, 0x830620f2, 0x99f2278c, + 0x1100ff9a, 0xd582cecc, 0x66e61435, 0x0774f708, 0xcc4f00ff, 0xb1ffffcc, 0xff15cd4c, 0x8233f0ff, 0xb3ce255d, 0x74f70533, 0x0d838a82, 0x4c310024, + 0x0e7005cd, 0xb3083106, 0xff918333, 0xccccf6ff, 0xffff088b, 0x06989968, 0xce230c83, 0x8385838b, 0xff322b20, 0xcd4cf7ff, 0xff068b08, 0x4683c800, + 0x33b36e23, 0xd75d1815, 0x0aa55f0b, 0x2d4b6d18, 0x1bff8b21, 0x2214093b, 0x82bb64fb, 0x3d2219b1, 0x0f2f4c09, 0x18ff3421, 0x96260d6e, 0xef0e258d, + 0x153cf88b, 0x5e181c83, 0xf82112cb, 0xe25d18e4, 0x05a64c1b, 0x9618cc20, 0xfc200b6f, 0xff203082, 0x0b251b19, 0x08729618, 0x64fc8b22, 0x17891b19, + 0xb47a6590, 0x42b3200c, 0x65901109, 0x8534b321, 0xff0827dd, 0x3333d300, 0x6982dcf7, 0xb3dcff28, 0xe3ffff33, 0x0486cd4c, 0x8b200e82, 0x210aac6f, + 0x8073ffcc, 0x20118211, 0x82168334, 0x08fc5b04, 0x0852b018, 0x9484e320, 0x34b3dc22, 0x4c244482, 0x34fbcdcc, 0x4f186382, 0x6720075b, 0x592a3587, + 0xeb088b9a, 0x0c00ff06, 0xce6c3333, 0x99fc2807, 0x0900ff9a, 0x828533b3, 0xccda2137, 0xf0228d82, 0x928266e6, 0xff211582, 0x200983df, 0x221383f5, + 0x829a99d8, 0x66aa221e, 0x183e4a66, 0x01ff0723, 0x242e827f, 0x66663700, 0x2b4f8215, 0x00ff6666, 0x96008005, 0x190300ff, 0x0b225f82, 0x788534b3, + 0x880bad5c, 0x160650b0, 0xadffff24, 0x70829a99, 0x8b82f520, 0x82280021, 0xe1ff2146, 0x20376183, 0xffff0080, 0xffccccda, 0xcccc0e00, 0xe7ffff08, + 0xffffce4c, 0x823433e6, 0x19202b76, 0xf8ffff98, 0xffa59a99, 0x2582e8ff, 0xcc0a0022, 0xe1211a82, 0x2725824c, 0x9a990300, 0x0100ff81, 0x3325d184, + 0xffff8b34, 0x893c82f4, 0xff322178, 0x27051352, 0x8bce4cee, 0x0674fb08, 0x1642ad18, 0x00ff8b25, 0x8534330b, 0x825d8247, 0x21578283, 0xb25d0895, + 0x1d002205, 0x251a82b3, 0xff33b318, 0x88821700, 0xcc1e002c, 0x0800ffcd, 0x92089a19, 0x3282948d, 0x0023c082, 0x41008008, 0x07220507, 0x4b826666, + 0x7b660720, 0x2f358205, 0xff68e606, 0x6666feff, 0xff40f708, 0x66668200, 0x200a2042, 0x082042cc, 0x20423420, 0x82322005, 0x82e320b6, 0x142042f4, + 0x20423220, 0x18c88208, 0x2516e251, 0x66befeff, 0x62827b66, 0x832c0021, 0x192320cc, 0x210f3b1d, 0x6282332c, 0xcc230028, 0xdcffffce, 0xdb1a3433, + 0x11820dbf, 0x16833220, 0xffff3323, 0x056b7cd3, 0x0c9b8718, 0xd582cd20, 0x33332c25, 0x42ef0e08, 0xf42005e9, 0x1aeeb318, 0x9672b320, 0x84cc2005, + 0x223782b1, 0x5ecc4c23, 0x34200ae6, 0x5e07954d, 0xe94207e6, 0x08e65e09, 0x42ffff21, 0xcd200ae9, 0x67203083, 0xb3210482, 0x42f78233, 0xbb828de9, + 0xb3dcff23, 0x17c64d33, 0x2738e942, 0xffffa599, 0xff0180e8, 0x217be942, 0xe942ff99, 0x42992007, 0x332220e9, 0xe94200ff, 0x42672006, 0x34200de9, + 0x2006b774, 0x073f19e3, 0xffff2308, 0xe942b3dc, 0x4234200a, 0x32201020, 0x42082042, 0x204210e9, 0x09e94209, 0xff142e23, 0x05e94200, 0x77ecd121, + 0xe9420a31, 0x878a1809, 0x63ae1808, 0x18322009, 0x830863ae, 0xca201962, 0x858a180c, 0x01ff2608, 0xfb66666e, 0x0e3a65c4, 0x711f8c4d, 0xf82e30dc, + 0xef0e06d4, 0x197000ff, 0x7001ff9a, 0x6e8252f8, 0x3595b118, 0xbeffb72a, 0x214700ff, 0xffff0548, 0x1895b118, 0x1c17b218, 0xff213b82, 0x2a4582ff, + 0xe601ff05, 0x00ff66e6, 0x19420048, 0x2509e02a, 0x0f00ff3a, 0xb1183033, 0x34200fbd, 0x0ebdb118, 0x0f83cc20, 0x43084825, 0x18b8ffff, 0x2110bdb1, + 0x1c828bd0, 0x1a989921, 0x20202cc5, 0x237984d3, 0xb0fdff05, 0x09bdb118, 0xd3208a82, 0x38bdb118, 0x43208a82, 0x39bdb118, 0xf8070226, 0x2600ff94, + 0x21bdb118, 0x00ff6825, 0x41cc4c09, 0xb3230d26, 0x82d30834, 0x4100207b, 0x421805d1, 0xff2508ce, 0xffccccf5, 0xbdb118ff, 0x0c224111, 0x05d34327, + 0x00ffa3fb, 0x05534df0, 0x5a832320, 0x48b31c21, 0xcc200925, 0x470f2264, 0x81480b74, 0x10604606, 0xb8183420, 0x33270920, 0x2300ff8b, 0x8208cd4c, + 0x00802bb5, 0x809effff, 0x00ff1500, 0xc082cc00, 0xa66d0020, 0x33002408, 0x828c8b32, 0x82042021, 0xffff2416, 0x828fcecc, 0x28878321, 0x8b9a1904, + 0xff06db08, 0x23088300, 0xffffff8f, 0x03229783, 0x1e8266e6, 0x82323321, 0x9918262f, 0x00ff869a, 0x222a8214, 0x8266efff, 0x82092015, 0xeaff2304, + 0x1a829a99, 0x9a990027, 0xccfdffff, 0x832a82ce, 0x18fe2076, 0x20084775, 0x201e84fe, 0x21498202, 0x1982f8ff, 0x83010021, 0xe6f72233, 0x20b18266, + 0x4a1a82f7, 0x681806a3, 0xfb220fa9, 0x92690644, 0x20de8216, 0x84428208, 0x08002547, 0x00ff9a19, 0x00235b83, 0x82008007, 0x82082085, 0x1700219a, + 0x14206683, 0x1121ec83, 0x20a482e6, 0x2f048318, 0x089a1905, 0xffff078b, 0xffcd4c76, 0x00807100, 0x50179d4c, 0x27580b45, 0x17cc1811, 0x42591812, + 0x0b735008, 0x00ff072c, 0x3b66e65a, 0x0900ff15, 0xb0839a19, 0xff33b327, 0x34b3fdff, 0x2da683ff, 0xe6fbffff, 0xffff0866, 0xff9a99df, 0xc082f4ff, + 0x33e7ff22, 0xe4261e82, 0xff836666, 0x1a84ddff, 0x66e6c729, 0xf1ffff06, 0x838b3333, 0xff992521, 0x66e60b00, 0x0e234682, 0x8208cecc, 0x831d2006, + 0xe61725fe, 0x1700ff67, 0x1d20da83, 0x21054d77, 0x33826645, 0x992a0123, 0x28768298, 0x68e6c7ff, 0x00ff8306, 0x235d8522, 0x1b00ff32, 0xde206c83, + 0x4a828183, 0xca5d0820, 0x04002105, 0x00211e82, 0x22148308, 0x83cc4c02, 0x8b9821ab, 0x45281a82, 0xff066866, 0x64661d00, 0x17256a82, 0xffff68e6, + 0x21c383e8, 0xac41e2ff, 0x33f12205, 0x20938332, 0x25ba8698, 0x8b3433f1, 0xac828b08, 0x34b39a24, 0x554134f7, 0xef0e285c, 0xccdf00ff, 0x18a4f7cd, + 0x285c3cc5, 0x3380ffff, 0x7affff33, 0x41cc84b3, 0xda411a6a, 0xff062b52, 0x9a192b01, 0xe62e00ff, 0xa2411566, 0x42ff204e, 0x8b3c1f12, 0xe8ffff06, + 0xffff66e6, 0x15cc4ce6, 0xfaffffa5, 0x00ff34b3, 0xffcc4c15, 0x32b3edff, 0x99278c82, 0xe7ffff9a, 0x430834b3, 0xca43056e, 0x99992463, 0x821800ff, + 0x14002e80, 0x00ff6766, 0xa5ce4c12, 0x4c0500ff, 0x30b644cc, 0xf7078b28, 0x7000ff20, 0x37429a19, 0x94fb225c, 0x09be4d7b, 0x2452ce45, 0x54f7b4f7, + 0x79471815, 0xd4fb220e, 0x06765d07, 0x1854fc21, 0x200f796c, 0x291b82f7, 0x053500ff, 0x2a00ff1e, 0x0483e1fa, 0x0e83e220, 0x088b1f29, 0xfc0654f8, + 0x1834fc74, 0x7e072045, 0x1e820ffc, 0x200ba556, 0x09145600, 0x11225285, 0x794d84ab, 0x20388205, 0x05744d7c, 0x7e840820, 0x18098867, 0x820a1580, + 0xef0e24a2, 0x83ccf7bb, 0xb3f2226d, 0x06d84f34, 0xcc4cf527, 0xc0f2ffff, 0xaa941a00, 0x18f32018, 0x2009385e, 0x0cbc1954, 0x06f3210c, 0x1ace9518, + 0x20053d50, 0x083d50cd, 0x088b332c, 0x07330633, 0xcc4f00ff, 0x9b4463cd, 0x458b205c, 0xaa23f2f1, 0x417334b3, 0x077009d6, 0x37be470d, 0x4447f343, + 0x7b2235c0, 0x25424cf7, 0x7b6b215c, 0x491b2450, 0x8b2212c3, 0x1f4a00ff, 0xf7eb212a, 0x770a7553, 0x45180d66, 0x82180fc5, 0x23200852, 0x55175155, + 0xe322164f, 0x6a553307, 0x088e530e, 0xfc44fc25, 0x43e3154c, 0x77530e9f, 0x0c777312, 0x9e522320, 0x82f32017, 0x19002098, 0x26137e52, 0x400d00ff, + 0x60ff8b00, 0xcc2007d2, 0x2505404a, 0xf8073308, 0x7e828b5c, 0x3789e320, 0xc854b320, 0x18468306, 0x2018be4f, 0x222f8223, 0x1a4ceeff, 0x83118753, + 0x09235599, 0x18118355, 0x220fd4a9, 0x1af88b0e, 0x22182834, 0x180654f7, 0x190ea996, 0x210b94e5, 0xc0197c54, 0x553712c2, 0xff073433, 0xcdccebff, + 0x66e3ffff, 0xf4ffff66, 0xffff3333, 0x829a19dd, 0x4cda23ee, 0x068208cc, 0xcccce625, 0x190500ff, 0x2c08d63e, 0xff008009, 0xce4ceaff, 0xeeffff08, + 0x222b82b3, 0x829819e7, 0x9a192b3a, 0xb3efffff, 0xdfffff34, 0xc1196666, 0x07302b8a, 0x1514fbeb, 0x07eb06cb, 0x072b064b, 0x44fb34f8, 0xd8878018, + 0x31438a18, 0x0e068b26, 0xf894f7af, 0x0f0d9818, 0x0800dd18, 0x16315f19, 0x90ffff31, 0xff0766e6, 0x66e6fcff, 0xffff8889, 0x5b9a99fd, 0xff2805c5, + 0x08cd4cfd, 0x19eaffff, 0xea220f82, 0x3d829919, 0x0080dc27, 0xe61500ff, 0x2c148266, 0xff083433, 0x33330000, 0xccffffff, 0x201a82cc, 0x201582ff, + 0x06aa5a00, 0x8b086824, 0x4c19058b, 0xca18096c, 0xff2108bc, 0x233482b3, 0x67e6ffff, 0x04833484, 0x0483cd20, 0x8b8bce22, 0x40836682, 0x66211b82, + 0x22128205, 0x828b9a19, 0x33b3215c, 0xcc214383, 0x201d83cd, 0x207f84e1, 0x203a83e6, 0x206f84e7, 0x828082e0, 0x19e1271e, 0x1900ff9a, 0x39829919, + 0x1e228083, 0x2d8267e6, 0x1b829783, 0xcd4cff22, 0xe6214683, 0x82128466, 0x4e938253, 0x33210770, 0x8360828a, 0x86938436, 0x32b321b8, 0xce207084, + 0xd2553583, 0x19ff2205, 0x828f839a, 0x3f4d195a, 0x21b78709, 0xb58268e6, 0x82ccf421, 0xccf42cc2, 0xfaffffcc, 0xffff9a99, 0x41cc4cf1, 0xf1210615, + 0x221e8366, 0x4a0080ee, 0xff2905a7, 0xff33b3e6, 0x9a19f3ff, 0x218c826f, 0xcd84caff, 0x21068a66, 0x9918b4f7, 0x54210e13, 0x2380827c, 0x0884ab11, + 0x08ff0419, 0x20056a48, 0x5a46187c, 0x06542507, 0x1534fb4b, 0x24050243, 0x00ff06cb, 0x287f82bf, 0xcc4c0200, 0x0d00ff15, 0x25bd834c, 0xff32b30a, + 0x0a83f5ff, 0x54f2ff21, 0xe220052a, 0x0023a782, 0x86686623, 0x821420a2, 0x18002020, 0x4f07c451, 0x0022062f, 0x5218330f, 0xff20075e, 0x0bab9f1a, + 0x8b33b325, 0x82f0ffff, 0x2115823f, 0x1a85ff98, 0x83ebff21, 0x83eb204a, 0x990e21ed, 0xdc201482, 0x0023fc82, 0x82cc4c1d, 0x0d0021dc, 0x0a204684, + 0xbf599382, 0x2111840e, 0x99823433, 0xf2200483, 0x2105735a, 0x7482b3e2, 0x83f1ff21, 0x2044844e, 0x204e8314, 0xdd5218eb, 0x846e8308, 0x51cc207e, + 0x7e8605cb, 0x82b3f621, 0x83a48246, 0x81c21898, 0x83092008, 0xebff2435, 0x82ffce4c, 0xff3223da, 0x4a83dcff, 0x10925318, 0xce209482, 0x25828282, + 0xb3f2ff23, 0x23b08232, 0xceccf2ff, 0xf5256282, 0x00ff3233, 0x2911820a, 0x4c0d00ff, 0xff8b08cc, 0xa6831d00, 0x6982dc20, 0xb30e0022, 0xed834e82, + 0x08205d83, 0x12d2a11a, 0x09775318, 0x00209983, 0x3f828982, 0x3f820f20, 0x53180020, 0x14200aad, 0x14234a83, 0x82ff9a99, 0xff6627ee, 0x66662300, + 0xfe83ffff, 0xf2225082, 0x8284cccc, 0x53183420, 0x1c581292, 0x830a2005, 0x330d223c, 0x22b08234, 0x824c1d00, 0x0e00212d, 0x44854982, 0xcd419983, + 0x8cff2005, 0xff33217e, 0x75517e86, 0x68662105, 0x22064d59, 0x8232330f, 0x84a4829e, 0xff0821c9, 0xff203b83, 0xcc20da82, 0x2206d547, 0x8434b30e, + 0x083321fe, 0x0d220682, 0x9483cd4c, 0x0482ce20, 0xff32b324, 0x3b820d00, 0x068b0825, 0x82e0ffff, 0x5dff22dd, 0x0d6c44b3, 0x2011e972, 0x2d7e18ff, + 0x45e21925, 0x83cb2116, 0x295e105c, 0x19a001ff, 0x3f01ff9a, 0xf06866e6, 0xf5ff2306, 0x5542cecc, 0x330a230c, 0xc5180832, 0x5e291746, 0xffe308b8, + 0x42005800, 0x06594105, 0xc6180920, 0x333b2d74, 0xdea8ffff, 0xffff05b8, 0xff32b39c, 0x52785900, 0x0400ff15, 0xffff0080, 0x82e27afb, 0x69d91a09, + 0x22f084e5, 0x82ceccfc, 0x6c1a19f0, 0x83042008, 0x19fc29fa, 0xffff0899, 0xff9899d2, 0x3105d477, 0xff3433d8, 0x6666e8ff, 0x99e4ffff, 0xdeffff9a, + 0x1e829a19, 0x66e6f822, 0x19213882, 0x24238299, 0x85906666, 0x20128291, 0x2d4b83f3, 0x0533330c, 0x19e0ffff, 0xff056c98, 0x39831100, 0x0080fd26, + 0xfaffff9c, 0x0f271c83, 0xffff0080, 0x826666f7, 0x83f0202c, 0x83e52069, 0xe6f6240f, 0x828b6c66, 0x66e62456, 0x618a8b08, 0x8b210583, 0x2021828a, + 0x216182e2, 0x2183fbff, 0x9a19e126, 0xe9ffff94, 0x00237c82, 0x84008016, 0xffcc2569, 0x34330c00, 0x9a206984, 0x9a206e83, 0x1b206d82, 0x82054047, + 0x991c211a, 0xf3269782, 0x00ff34b3, 0xd912cc15, 0x35dc013c, 0x00ff0040, 0x8b9a190a, 0x4c0600ff, 0xf9ffffcc, 0xff0800c0, 0x0a830b00, 0x14aef42d, + 0x2300ff05, 0xfeff3433, 0x1048a1b6, 0x25016288, 0x6b94f721, 0x24520554, 0x9a192105, 0x49072452, 0x262a05c9, 0xff066666, 0x00803100, 0xca5fff8b, + 0xe1d72f05, 0xffff8b48, 0x081e85ce, 0x99e1feff, 0x0c82079a, 0x66e6b425, 0x82c3ffff, 0x82048539, 0x088b230e, 0x0683ffff, 0x00211685, 0x264b823c, + 0x194b00ff, 0x82db089a, 0x1600212f, 0xee202a83, 0x00210482, 0x20398311, 0xf32119e9, 0xff9a220d, 0x821b82ff, 0x22178256, 0x823cfb08, 0xe5ff2130, + 0x298ce318, 0x3083f720, 0xff246a83, 0xd7e33c00, 0xe6210482, 0x21798266, 0x9182291c, 0xc5821583, 0x96848c82, 0xc97ab885, 0x206a8205, 0x88c718ff, + 0x19ff2008, 0x8311b322, 0x823a821b, 0xf70827b8, 0x066b074c, 0xdf70ffff, 0x0cf7220c, 0x0e3947ab, 0x0fb18018, 0x212a4a63, 0x90180040, 0x0e23108e, + 0x4cf4f8ef, 0xa95c3068, 0x1fe94a10, 0x06d4f825, 0x5d14fc8b, 0xff26620f, 0x6c07a7fd, 0xce188df7, 0x4c2108c6, 0xc6ce18cc, 0x34b32e0d, 0x3700ff08, + 0xffffae07, 0x0566e6c8, 0x210b82c2, 0xf3479a19, 0x182c8508, 0x840968ce, 0x330a222c, 0x3ecd1833, 0x5bcd200e, 0xc9220780, 0x4782cccc, 0x36234084, + 0x82543433, 0x222c9a47, 0x180080f7, 0x4a0802ce, 0x0a2608e9, 0x54083233, 0x3d8200ff, 0x49820520, 0xff52f823, 0x5c5382ff, 0xcb823671, 0xc2f00722, + 0x10204784, 0xde820b82, 0x1806ce5d, 0x22175cce, 0x8294f838, 0x66e62274, 0x25064115, 0x06413220, 0x41ce200e, 0x2c981b06, 0x21220641, 0x06419a19, + 0x822c9807, 0x33b3228a, 0x36cf18ff, 0xcd4c270c, 0x660900ff, 0xfa820866, 0xc29a1923, 0x41d98405, 0x2c990806, 0x7d5d3282, 0x0ef94108, 0x66e63722, + 0x05224584, 0x54841bf7, 0x60841520, 0x4d412da0, 0x16d85d0a, 0xd55dff20, 0xccc9221b, 0x095442d0, 0x54423020, 0x05234d05, 0x09ead018, 0x4221025e, + 0x4d410954, 0x41342026, 0x60180e4d, 0x3720089a, 0x96124d41, 0x078b2c2c, 0xff70fb0e, 0x9a19df00, 0x821514f8, 0xa6dc2dad, 0xe4ffff66, 0xffff3333, + 0xff9a59e3, 0x07436a18, 0x1a99dd21, 0x22139201, 0x822300ff, 0x1d002323, 0xc2619a99, 0x5c222006, 0x24280574, 0xff8b3333, 0xcdcc1b00, 0x54854484, + 0xffff082b, 0xfb991967, 0xffff15e4, 0x5ffe11f5, 0xdb2c8001, 0xeeffff07, 0x0e063333, 0x94f730fb, 0x680af741, 0x592105c5, 0x006b199a, 0x66a62714, + 0x2300ff8b, 0xdb659a59, 0x6533200a, 0x9b2c24db, 0xffff33b3, 0x15cccc95, 0x990b00ff, 0xfd295b82, 0x00ff9a19, 0xffcd4c0c, 0x280985ff, 0x088b9999, + 0xe62700ff, 0x2b5f8267, 0xff323325, 0x34331400, 0xb31500ff, 0x21220482, 0x1a826666, 0x0f831220, 0x28dc1b37, 0x0900ff05, 0x00ff9899, 0xff5ccf0e, + 0xcecc1300, 0x300400ff, 0x260e82a4, 0xffff66e6, 0x822a5cf6, 0xcc0e2229, 0x200a83cc, 0x82198228, 0xecff2333, 0x0e825238, 0x13824c20, 0x9a19f12e, + 0xedffff08, 0xffff68e6, 0x053433e4, 0xb3240a82, 0xe3ffff32, 0xe6203983, 0xff264882, 0xff9919ea, 0x3d83e2ff, 0x33b3f126, 0xfdfeff08, 0x5605ca48, + 0xdc181302, 0xeb231647, 0x18066b07, 0x8209edf4, 0xffff2245, 0x20c282f1, 0x856618ff, 0x73cc2013, 0x082305a5, 0x820201ff, 0x21878267, 0x7e8247a1, + 0x824fe721, 0x055c5dd6, 0xa714ee22, 0xec27ae82, 0x00ff0080, 0x82ce4c1c, 0x33f622ae, 0x82e88233, 0x0300239f, 0xfc8252f8, 0x82ecd121, 0xc3b5260e, + 0xcf0900ff, 0x20f7835c, 0x201e82b3, 0x271e8309, 0xffb8de13, 0xae07fcff, 0xcc211982, 0x218282cd, 0x1e823e4a, 0x48821320, 0xc0e2ff24, 0x34820500, + 0xff486124, 0x0f82eaff, 0x82140021, 0xf0ff2633, 0x00ff9a19, 0x24098317, 0x089a99f7, 0x051b548c, 0xe6000023, 0x06e66167, 0x66e60022, 0x99250982, + 0x078b0898, 0xf7e3110e, 0xff211b01, 0xffee19ff, 0x35ab5679, 0x1bd07518, 0x18063421, 0x22098f9e, 0x194c0e00, 0x260cb867, 0xff0614f7, 0x1a66d9ff, + 0x10da0aba, 0x3d014ea2, 0x19bf0025, 0x61d4f79a, 0xeb220855, 0x6f446666, 0x99151905, 0xff99210f, 0x23118f75, 0x67661600, 0x15191684, 0x9a2010f5, + 0x8b384484, 0x80e5ffff, 0x00ff0800, 0xfb66e6c1, 0xffff1564, 0x060080b5, 0x195400ff, 0x812b1e82, 0xff05cccc, 0xcccc0900, 0x52f2ffff, 0x148205c0, + 0xce4ceb26, 0x4cf1ffff, 0xf6231382, 0x82083233, 0x3433230a, 0x0a82ffff, 0xecffff22, 0x00230982, 0x8568e603, 0x0e00230e, 0x1e8234b3, 0xceccde25, + 0x833100ff, 0xfbfe2348, 0x8c7ecccc, 0x07f42118, 0x16852c19, 0x7fb4f821, 0xcb1a1773, 0xff24197f, 0x66e655ff, 0xd5236a82, 0x82cbce4c, 0x822d20c0, + 0xbb633077, 0xbefeff05, 0xa4f79a19, 0x07d4fb15, 0x848b06cb, 0x22f68200, 0x18cccc49, 0x210a18f3, 0xf318ff01, 0x00200718, 0x0918f318, 0xf3183220, + 0xce210818, 0x22a582ae, 0x82c2f526, 0xd7092d37, 0x74fb070a, 0x2001ff06, 0x158b66e6, 0x2821f282, 0x294782f6, 0x0a57c9ff, 0x19e4ffff, 0xf418599a, + 0x4c250dad, 0xffffffcc, 0x22538280, 0x88ce4c00, 0x26138509, 0xffffb408, 0x82ccccc1, 0x194722a7, 0x62eb829a, 0x0d200506, 0xff332c82, 0xffceccf8, + 0x9a190900, 0x00ff0880, 0xff66e64e, 0x834ca1ff, 0xb3432527, 0xd4f70634, 0xff257d84, 0xfb0080a9, 0x257e82d4, 0xff3333bb, 0x1e836700, 0xe6fcff23, + 0x05df5567, 0x54fdff21, 0x8b250606, 0xe6f4ffff, 0x39f41866, 0x828b2007, 0x19ff220e, 0x054a5a9a, 0x4a215982, 0x82598266, 0x0e052910, 0x154bb4f7, + 0x9cf7064b, 0x30616e18, 0x66e6f337, 0x1d00ff07, 0xffffcd4c, 0xff3433f5, 0x33b31200, 0x66e7ffff, 0x28698266, 0x086666dc, 0xffff6f8b, 0x27a082dc, + 0x9a99ccff, 0xccd3ffff, 0xda222682, 0x8f820080, 0x7bd4d325, 0x832500ff, 0x2bdc25a5, 0x3200ff85, 0x1d209584, 0x2005ad58, 0x222b8223, 0x82ab1200, + 0x83182016, 0x541d2109, 0x0a222a82, 0xb082cccc, 0x9a190c22, 0x4225a183, 0x00ffcc4c, 0x82698235, 0x20738204, 0x050c6f42, 0x33331422, 0x1326d982, + 0xff869a19, 0x1c821000, 0x33f7ff23, 0x20338234, 0x05e64115, 0x1e454222, 0x2e823383, 0xe2ba3524, 0x428200ff, 0x1c828b20, 0x0b045b18, 0x821e4521, + 0xbabd22b4, 0x879d82e2, 0x88cc20d5, 0x913420d5, 0x861282d5, 0x862682d5, 0x82cc20d5, 0x20d58598, 0x92698233, 0x82b320d5, 0x83d58516, 0x2ed58cc3, + 0xff14ee1e, 0x66e6e6ff, 0x111900ff, 0x18ffffec, 0x1912d96f, 0x2f08e735, 0x0e071cfc, 0xff14f9ef, 0x34b39400, 0x7bffff15, 0x5105b575, 0xfc2113c9, + 0x17fd5fa4, 0x7a0cdb7c, 0xf82609af, 0x07bb0614, 0x3597f4fb, 0x7400ff25, 0x82079a99, 0xcdcc379d, 0x660500ff, 0xffff0566, 0xffa470ec, 0x00800300, + 0xc2f1ffff, 0x56829c8f, 0xcccc1323, 0x2c068208, 0xff68e608, 0xc5e00200, 0x990800ff, 0x082c8298, 0xffb05221, 0x9a190700, 0x2300ff08, 0x00ff06a1, + 0x0500802f, 0xd72000ff, 0x2b00ff0a, 0x00ff7cd4, 0x82ae8733, 0x1ec529f9, 0xb33600ff, 0xa6088b33, 0x1a364182, 0xffff34b3, 0xffc2b5f9, 0x9a191800, + 0xeef3ffff, 0x01ff0816, 0x14823346, 0x28dc5c22, 0x57823c83, 0x83efff21, 0x83142089, 0x99df3a7e, 0xffff8b99, 0x08ceccda, 0x54fb068b, 0x4c0b00ff, + 0xd4fb15cc, 0x193900ff, 0x32a6829a, 0x0766e6b6, 0x9b06d4f7, 0xff2f0e07, 0x90c25600, 0x821524f8, 0x83d92052, 0x82f43232, 0xfaffff8f, 0xffffe27a, + 0xfff668f8, 0x8e82f6ff, 0x261a8208, 0xffffc335, 0x822005f0, 0xb8f7273a, 0xf5ffff52, 0x0f8266a6, 0x0482e620, 0xec51fe22, 0xa5210e82, 0x21d882a2, + 0x2982ae47, 0x002b1983, 0xffae4708, 0x6f52feff, 0x820f00ff, 0x290e84ab, 0x98590a00, 0x0c00ff08, 0x1482f0c7, 0x05e2fa22, 0x23059642, 0x48e11400, + 0x4a21e882, 0x2719823d, 0x00ff6626, 0x8be2ba1a, 0x1223d682, 0x8206a470, 0x66e62116, 0x3321f783, 0x217f8232, 0x36829ad9, 0xffcecc26, 0xb81eebff, + 0x0d224682, 0x7f829a99, 0x821e0521, 0x4c082246, 0x218082cc, 0x708268a6, 0xf0200983, 0xf4209483, 0xa8822983, 0xf6248f82, 0xffff0080, 0x1983b384, + 0xae010023, 0x220e8214, 0x82ffcccc, 0x829a208f, 0x33f3221e, 0x21588234, 0xd882e0fa, 0x8266f821, 0x7d092580, 0xf4ffff72, 0x00233382, 0x821e8505, + 0x05c07277, 0xcccc8e27, 0xb3075b06, 0x050f6706, 0xff2b9683, 0x089a19ca, 0x8b0734fb, 0x82e1ffff, 0x05904b37, 0x7683e420, 0x82b3e921, 0x66ee22af, + 0x20a58266, 0x27478241, 0x0080beff, 0x86849205, 0x59744b82, 0x23768207, 0x063233d9, 0x80218782, 0x203f8200, 0x293582f7, 0x66660300, 0xff089185, + 0x4c82c9ff, 0x99360027, 0x14fb059a, 0x830d8506, 0x239d8212, 0x8552f8f9, 0xdc243182, 0xfcffff29, 0xf72ffc83, 0x088b8f82, 0x4cd8ffff, 0xffff06cd, + 0x821f05f6, 0x00fb2d48, 0x0c00ff00, 0x00ff9a19, 0x925c0f07, 0x7a237f83, 0x8200ffe1, 0xff052884, 0x33b3e9ff, 0x831100ff, 0x83f12038, 0x331b2a09, + 0x00ff8b32, 0x089a991e, 0x21c383f7, 0x9b823500, 0x832a0021, 0x3504843a, 0x8b67e635, 0xbb06b308, 0x8effff07, 0xff068fc2, 0x713d4900, 0xe81804fb, + 0x46180ce7, 0x6b200a7b, 0x2105d262, 0xd049ffcd, 0x246a8307, 0x088b33b3, 0x23c382f7, 0x34b31100, 0x0e226a82, 0x1e84cc4c, 0x11220a82, 0x6f7a33b3, + 0x20198205, 0x0f475cff, 0x8b22f682, 0x699734fb, 0xee20e482, 0x9b184886, 0x67820845, 0x5c0beb62, 0x908214aa, 0x314d8083, 0x14f72205, 0x0c7a544b, + 0xfe1a3194, 0xf8263b3c, 0x8601ff8a, 0x6482b85e, 0xac831520, 0x00401536, 0x2400ff7c, 0x8b6d4861, 0x43feff08, 0xff06866b, 0xb2fde1ff, 0x2208cb82, + 0xffbefff0, 0xb89edbff, 0x401500ff, 0xeaffff83, 0xf70800c0, 0x056afb6a, 0xa14fffff, 0xffff0748, 0x48ba09d0, 0xf11a0c29, 0x3d820a55, 0xfc29f725, + 0x820700ff, 0xf8ff2d04, 0x00ff04d6, 0x8b04d608, 0x0674f708, 0x19850985, 0x8b201e83, 0x08201084, 0x83065748, 0x266e8242, 0xffff707d, 0x82d663e6, + 0xd0ff2390, 0x338266e6, 0x6666b027, 0xd400ff07, 0x3bf78233, 0x0552f8d5, 0xffff8afb, 0x15ae8764, 0xe66affff, 0x9500ff66, 0xff059a19, 0xcc4c2a01, + 0x6a228e82, 0x1584cecc, 0xff0e052c, 0x9a19ff01, 0xe65000ff, 0x8e821566, 0xecd1d331, 0x05d5ffff, 0xdcffff1e, 0xffff142e, 0x8348e1cb, 0x8506835d, + 0x23002316, 0x8482ecd1, 0xae472b22, 0x2c208b83, 0x002d2382, 0xffe2fa2a, 0x86eb2200, 0x1e3400ff, 0x232d82b8, 0xae470b00, 0x0a3c2282, 0xffff86ab, + 0xff7a14fe, 0x5c0f0a00, 0x05fdffff, 0x00ff08a2, 0x07b0b291, 0xfdfffeff, 0xb420b882, 0xff298d83, 0xff69ffff, 0x66e62fff, 0x24098205, 0xffff311a, + 0x21a882d3, 0x0483d5ff, 0xc582dc20, 0x19caff23, 0x09926199, 0xcdccd623, 0x197d18ff, 0x8663820a, 0x9ee1207f, 0xcd0c217f, 0xe7237f87, 0x82074a4c, + 0xf80c2237, 0x3b968352, 0x0d00ff5d, 0x00fff6a8, 0xff99590c, 0xd8e30300, 0x3f01ff08, 0x00ff9819, 0x05707d5e, 0x7d2b1082, 0x0000ff72, 0x00ff18d4, + 0x82323305, 0x58a92609, 0xb30200ff, 0x238f8234, 0xf6a81100, 0x0e214582, 0x20d7824f, 0x284083f1, 0xffae0700, 0x9a59eeff, 0x36c58208, 0xfeff9a19, + 0x05d6e3b0, 0xf401ff0e, 0x00ffcc4c, 0x15cc4c04, 0x8388ffff, 0xb377220a, 0x21578234, 0x7c82381b, 0x82682821, 0x6e0d3177, 0x3200ff14, 0xffff707d, + 0xff5ccff8, 0xcecc3500, 0xf3214082, 0x327682bd, 0x408e825b, 0x784a00ff, 0xa4ffff52, 0x00ff6766, 0x82d6980b, 0x8377201a, 0x3b112725, 0x8dffffa6, + 0x0483e17a, 0x00ffe02b, 0xffe83b11, 0x5dcf77ff, 0x21248208, 0x2e829a99, 0x82295c21, 0xe27a2e38, 0xf0b4ffff, 0x5b00ffa4, 0xffff1f85, 0x825883f3, + 0x83cd205e, 0x829e2068, 0x01802172, 0x6c20f982, 0x28279c82, 0x00ff6466, 0x8258391b, 0x839c823d, 0x82ce20a6, 0x9e0f2ca1, 0xf0ffffb8, 0x00ff4861, + 0x827c5419, 0x200f83e8, 0x82048200, 0x9b0f2725, 0x0f00ff24, 0x1582d4a3, 0x68661922, 0x40832582, 0x98990f2e, 0x5afeff08, 0x00ffcecc, 0x1534b3eb, + 0x46271b82, 0x00ff7c94, 0x83856b39, 0xff842204, 0x200e8200, 0x833c828b, 0x22118506, 0x8294c6ff, 0xb9ff2658, 0x8b08846b, 0x200683ff, 0x201182ff, + 0x2004837a, 0x200e837c, 0x822d8286, 0x82862015, 0x94c6221b, 0x21328279, 0x54836666, 0x089a992d, 0x01ff8b0e, 0x159a1901, 0x490500ff, 0x45220504, + 0xd08266e6, 0x0021e582, 0x22b5823b, 0x82e14400, 0x7a0b22b5, 0x086d82e2, 0x34b32c22, 0x970700ff, 0x2f00ff0a, 0xffffcc4c, 0xffd823f1, 0x9a992000, + 0x59dfffff, 0xff97089a, 0x1e05f4ff, 0x0b27eb82, 0x00ff9a19, 0x82e2fa0b, 0x8021220a, 0x20218200, 0x214f82a6, 0x0482662e, 0x28dc0e25, 0x832d00ff, + 0x68f82630, 0x00ff08f6, 0x23698244, 0x1e85f4ff, 0x28826e82, 0x61c4ff23, 0x299e8248, 0x089a19ba, 0x33faffff, 0x0c820734, 0x1783d620, 0x82ccee21, + 0x83d8206c, 0x83e12071, 0xb3e3223b, 0x36208234, 0xffce4c4b, 0xcc4c57ff, 0xf8ffff05, 0xff840080, 0x9819f6ff, 0x82fcffff, 0xf5ff237b, 0xed8334b3, + 0x33b3f522, 0xf6204182, 0x00211182, 0x82688303, 0x83922026, 0x3d4a2638, 0xb3a800ff, 0x25388234, 0xffd7a3e1, 0x58831c00, 0x32c5ee25, 0x822700ff, + 0x00ff2437, 0x82008029, 0xffff3425, 0x0e058bec, 0x7d01ffaf, 0x01ff3433, 0x1534b329, 0x828f00ff, 0xeaff22fe, 0x2c7282cc, 0x64e60b00, 0x4cfeffff, + 0xffff95cc, 0x219382f7, 0xa2830300, 0x3983f420, 0xd0250a82, 0x66f4ffff, 0x838c8267, 0x82f32024, 0xf7ff23f8, 0x28826866, 0x82676621, 0x83972058, + 0x84992029, 0x82182044, 0x6dff2939, 0x8d056666, 0xfbffff7f, 0xff24a782, 0x81ceccf3, 0xe621cf82, 0x84288266, 0xe6f821cf, 0xf2203882, 0xff200483, + 0xf520de83, 0x0021ab82, 0x20ff8405, 0x233c827f, 0x00804400, 0x7f25c682, 0xffff33b3, 0x210a84bb, 0x0a8233f5, 0x2582fa20, 0xe6f2ff27, 0x0000ff66, + 0x203e82e6, 0x235982f6, 0x98190700, 0x99215384, 0x250a82ff, 0x00ff869a, 0xf182330c, 0x9a190223, 0x054e7497, 0x9200ff24, 0x4b829a99, 0xaec79727, + 0x336600ff, 0x270a8234, 0xffd763f7, 0x99990800, 0xf021c882, 0x843082a4, 0x221e83e7, 0x8299990b, 0xc5032c34, 0x0b00ff1f, 0x00ff0080, 0x7152f809, + 0x0b250625, 0x00ff71fd, 0x269f8301, 0x7b948f00, 0x831500ff, 0x40002248, 0x288a8266, 0x057a5484, 0x4c0500ff, 0x213482ce, 0x04821804, 0x06227f83, + 0x58823cfe, 0x2205e563, 0x7ccc4c0c, 0xff230623, 0x83c401f9, 0xffcc252a, 0xe8fbf4ff, 0x40206a82, 0xff303582, 0x0586ab7b, 0x74f72f0e, 0xff1554f7, + 0x34b34600, 0x39202c82, 0x0023e882, 0x825c4f39, 0xb046230a, 0x068508a4, 0xc6ffff25, 0x83ff34b3, 0xffff2216, 0x825382b9, 0x4cb923f6, 0x16838bcd, + 0x04823320, 0x82a4b021, 0x86cf190a, 0x5c4f2107, 0x4c212882, 0x831684cd, 0x8b332154, 0x322d6d82, 0x155b34b3, 0x999affff, 0xffff0699, 0x285d83a0, + 0xd763b2ff, 0x66b2ffff, 0x223a8266, 0x82ce4ca0, 0xecff3268, 0x00ff28dc, 0xff1f850f, 0x5478f0ff, 0x231300ff, 0x243a82d7, 0x34b37a01, 0x250c8306, + 0xffffffd6, 0x208250f8, 0x84008021, 0x22998204, 0x82343313, 0x5f002337, 0x498432b3, 0x4d00ff24, 0x5e829a99, 0x8bce4c2d, 0x01ff0e08, 0xf89a19cf, + 0x82fc1534, 0xe6ff233d, 0x6682d763, 0x8982ea23, 0x0ad646ff, 0x2606cc4e, 0x00ff707d, 0x84717d15, 0x00ff2719, 0x8b299c19, 0x3382f808, 0x821a0023, + 0x20628290, 0x191e8515, 0x28075b3b, 0xff07f4f7, 0x06000000, 0x241e83ff, 0x66ebffff, 0x06e04666, 0x9a99e429, 0xf4fb088b, 0x82150cfc, 0x94fb2768, + 0xfcfffffe, 0x0486026b, 0x8b220e82, 0xf8825b08, 0x13850883, 0x94030023, 0x255d82fe, 0x08026b04, 0x088507bb, 0x1383ff20, 0x17820486, 0x0023fa82, + 0x829a192f, 0x850c8369, 0x85538317, 0x8208205e, 0x67e62685, 0xf78b055b, 0x2070e614, 0x23f8835b, 0x158b67e6, 0xe38672e9, 0xfb84f723, 0x20e4838c, + 0x077e48f7, 0xd6f8ff25, 0x82ffff04, 0x088b240e, 0x850634fb, 0x84ff2009, 0x0a834814, 0x8b07eb27, 0xd60800ff, 0x089c4888, 0x0e837820, 0x088b0423, + 0x823282f7, 0x82042018, 0x06d0481e, 0x838b8821, 0x08782643, 0xf78b072b, 0x2369e654, 0x5cfb04f7, 0x2017b941, 0x052749ff, 0x2e42ff20, 0x51fd2305, + 0x2e42ff68, 0xbb8b220a, 0x332f4205, 0xff075b26, 0x9a19ffff, 0x8d1cbe41, 0x6bfc2277, 0x42778b02, 0x5b2135a6, 0x1a2e4207, 0xe7946f9c, 0x9c840322, + 0x421e1743, 0x662605a6, 0xf80e158b, 0x8118f854, 0xfc213262, 0xcf731814, 0x18d42018, 0x200a1e4a, 0x07325a66, 0x8b9a5938, 0x0614f808, 0xfb154b8b, + 0x14fb0634, 0x0634f707, 0x8b0714f7, 0x0f8c54fb, 0xcb74fb23, 0x88168215, 0x34fb2122, 0x2a852082, 0xaded1385, 0x4bbcfb2e, 0x4b063315, 0xcb06e307, + 0x154bc307, 0x0e830683, 0xcb84f722, 0xfc211688, 0x88a18214, 0x897c2018, 0x89cb2018, 0x64fb212f, 0x0e2046a0, 0x1a6b8518, 0x0614f822, 0x0d114218, + 0x8b9a5929, 0xa6dcffff, 0x18fb0866, 0x41180183, 0x9a821c9e, 0xd182cb20, 0xd9824b20, 0xcb14f825, 0x8294fb15, 0x94f72108, 0xcc841182, 0x0e291ab0, + 0xb601ff2f, 0x01ff9a99, 0xd82f1956, 0x94fb241d, 0x180594fb, 0x261afae4, 0xf87fffff, 0x8314f7d5, 0x18812022, 0x2c187fe6, 0xff7d7f0c, 0x00800c00, + 0x421400ff, 0x23e6188f, 0x7868320d, 0x96ffff52, 0xff0532b3, 0xcc4cea00, 0x4ce900ff, 0x840a82ce, 0x850c222b, 0xa42f191e, 0x2c3b8208, 0xe27af3ff, + 0x0e068b08, 0x01ff70fb, 0x20b98236, 0x21b99100, 0xa98900c0, 0xffff0824, 0x6a66ccf9, 0xffff2905, 0xffceccf7, 0x66e6fcff, 0xcc210983, 0x231a828b, + 0x8bccccf7, 0xd1250c82, 0x0300ffec, 0x27358220, 0xff90c2f9, 0x00400600, 0x96271a82, 0x00ffb89e, 0x82345369, 0xa19622d2, 0x219c8648, 0x5b83f9ff, + 0x34b3f922, 0xcf213482, 0x214b875c, 0x4b845ccf, 0x16820682, 0x82ebd121, 0x9a19214b, 0xbe207682, 0x06224082, 0x4b82cc4c, 0x0b18e218, 0xfe824020, + 0x8020d785, 0x00236682, 0x82676669, 0x66662166, 0x99216683, 0x210a8299, 0x67419a59, 0x82002006, 0x828b2025, 0x87308ef9, 0x4119843b, 0x69210d44, + 0x23c28260, 0x05cd8c96, 0x04835184, 0xe7186720, 0x40210d99, 0x83308d00, 0x82ff204b, 0xff8b239c, 0x3441ebff, 0x9996210e, 0x0482c282, 0x69214082, + 0x210a8359, 0x474d66a6, 0xc5290839, 0x5b00ff1e, 0xffffcc8c, 0xff34f3b4, 0x34734a00, 0x61a4ffff, 0x0b00ff48, 0xff089899, 0xcdcc77ff, 0x3d1100ff, + 0x8dffff72, 0x22c08280, 0x82e27a8d, 0xcd4c210e, 0xe1211882, 0x0d4b4d47, 0x4d527821, 0x8726074b, 0xf3ffffaf, 0x1e82cccc, 0x5ccf3527, 0xcff8ffff, + 0x05be4d1a, 0x6d0d002d, 0x2800ff0e, 0x00ff6866, 0x4d9a391b, 0xa420244b, 0x0f272582, 0x00ffec91, 0x4d508a0f, 0xff22114b, 0xb282b32b, 0x34b3d336, + 0xc7ffff15, 0x53069a19, 0xffff8b07, 0xff70bdf2, 0x8f42f5ff, 0x90200483, 0xa3228882, 0xc7828bd7, 0x18b3f221, 0x21128b84, 0x378307c3, 0x82069921, + 0x99992125, 0xf5203a82, 0x7018d882, 0x386e0ae2, 0x71bd2208, 0x241683ff, 0x5c0c00ff, 0x254c8229, 0x67e63800, 0x6b82c306, 0x420d0023, 0x84198290, + 0x8775821e, 0x2425831e, 0xa30b00ff, 0xcf8318d7, 0x0753280b, 0x00ff06c3, 0x8232330e, 0x820a2055, 0x82ff20b6, 0x7072826c, 0x711806da, 0x194f1378, + 0xc6d14138, 0x9a195f22, 0x212e9941, 0x624134f7, 0xb4f7212f, 0x60057049, 0xf7212aa0, 0x093e7b74, 0xffcd4c2b, 0x7a540e00, 0xb31100ff, 0xdfae1833, + 0x18ff200d, 0x3a092d6a, 0xfb0774fb, 0x8b158b64, 0xcc9effff, 0x4e00ffcc, 0xffffcdcc, 0xff3433b1, 0x84336100, 0x33612334, 0x16838b34, 0xcc201b84, + 0x10820a82, 0x06820820, 0x66663626, 0x4ce7ffff, 0x30251682, 0xffff34b3, 0x263283d9, 0x08cc4c20, 0x82f2ffff, 0x0b002e19, 0xffffce4c, 0xff9a19fe, + 0x842b1400, 0x820e82ff, 0x970d2328, 0x0a83080a, 0x00ffce22, 0x19820a82, 0xff323325, 0x82d90100, 0x990d2723, 0xf4ffff9a, 0x1e8234b3, 0xcecc3426, + 0x2100ff5f, 0xff238b82, 0x829a99bd, 0xb3b62296, 0x216f8232, 0x22837aff, 0x00809424, 0x0484ffff, 0x00807b22, 0xff20d282, 0x11850683, 0x826b0021, + 0x00ff2411, 0x82666685, 0x4900212d, 0x00267e82, 0xff00c021, 0x8d834200, 0x9ad93423, 0x06aa56b7, 0x14228a85, 0x9e823333, 0x83662621, 0xffcd258e, + 0xf668f2ff, 0x0a221e82, 0x0a846766, 0xffff8a25, 0x857cd4eb, 0x209582c8, 0x20d38232, 0x202f83d9, 0x27e883df, 0xffcd4ce7, 0xcc4ccfff, 0xc92f9982, + 0x0e089a99, 0xf8b4f8af, 0xffff1554, 0x827c54ee, 0xabf12212, 0xd87a1984, 0x3aef2707, 0xfeff08e0, 0xf218193f, 0xb818088c, 0x8f5511b2, 0x7a542b0b, + 0x1000ff8b, 0xff0820c5, 0x1451c101, 0x550c8205, 0x0e220659, 0x6d7d7a54, 0xfb142207, 0x139155b4, 0x3233ef22, 0x20060257, 0x5fef83ed, 0x94550ecd, + 0x2169890d, 0x6986a100, 0x83cecc21, 0x0c9a5569, 0x2b14fb22, 0x7b20d584, 0x8520d584, 0x0a828984, 0x4b216883, 0x85088207, 0x3c7d1867, 0xc5102408, + 0x83088b1f, 0x831f20c0, 0x482122c6, 0x0aca55ff, 0x4000ff24, 0x561866e6, 0xff230781, 0x8485abf1, 0x26d1821c, 0x088b7b54, 0x84f714f8, 0x829583d1, + 0x8286201b, 0x84ab2168, 0xef265f82, 0xff08e23a, 0x3e419ffe, 0x8c612032, 0x0c3d56d4, 0x4c20d486, 0x0ae67c18, 0xd4843320, 0xfb083323, 0x20d58994, + 0x18b2184c, 0x093d411a, 0x87010121, 0x18cd2068, 0x3d10beba, 0xef01ff0e, 0x01ff66e6, 0x15666619, 0x4c0300ff, 0xf7ffffce, 0xffff6666, 0xff3233fd, + 0x0e83f6ff, 0x3433f938, 0xb3f9ffff, 0xffff0832, 0xff32b3d4, 0x9a99d8ff, 0x0100ff05, 0x29829a19, 0xb482b320, 0x83990021, 0x00802109, 0x39829e82, + 0x06850820, 0xffffff22, 0xf7254583, 0xffff0080, 0x275f82fe, 0x34b3f7ff, 0x2b00ff08, 0x40855083, 0x82cc0621, 0x235682bb, 0xcc0200ff, 0x6a847482, + 0x5f83fc20, 0x20058b71, 0x205583fb, 0x206483f4, 0x296482fa, 0x0080f4ff, 0xf5ffff85, 0x85829819, 0xf583fb20, 0x68e6f723, 0x25968205, 0xff806666, + 0x2b83f8ff, 0x9899f522, 0x6a839082, 0x9a19f623, 0x202c8208, 0x830b84f8, 0x83fd2070, 0x82f72085, 0x826a83d0, 0x82c82040, 0x11002314, 0x4082cccc, + 0x3583f220, 0x6183f520, 0xfa88f020, 0x7583f120, 0x6666f922, 0x2706d448, 0x66e6c6ff, 0x84828905, 0x67836d82, 0xb783f620, 0x9a99fd22, 0xf2251d82, + 0xffff3433, 0x203c83fd, 0x201483f1, 0x230483fe, 0x8b9a99f0, 0x24055a44, 0xf1ffff8b, 0xce1619cc, 0x33f22207, 0x21e88233, 0x1a82cc4c, 0x1483f620, + 0x6666022a, 0x0600ff84, 0x94896666, 0x645b6686, 0x83f02006, 0x83062028, 0x83f12068, 0x83082009, 0x82f22009, 0x0a002104, 0xc8273c84, 0xffff0a57, + 0x823433ee, 0x28f722ba, 0x07a641f6, 0x73194020, 0xfa2307df, 0x5cff7b14, 0xff320522, 0xffd7e3f7, 0x66e60900, 0x99f8ffff, 0x0a00ff99, 0xc0826866, + 0x96666622, 0xfb276e82, 0x00ffeb51, 0x82981908, 0xeef92244, 0x201b8214, 0x221b82e6, 0x5252b8fa, 0xff2205b2, 0x1e8291fb, 0x83e60b21, 0xc2fc22ff, + 0x8329828f, 0xba02227e, 0x264e82e1, 0x00ff32b3, 0x8229dc06, 0xce4c2604, 0x2b00ff08, 0x221e8242, 0x82666627, 0x82fe2048, 0x08002769, 0xffffcc4c, + 0x52826eff, 0x8205306c, 0x8b0821bd, 0x00224086, 0x0982ec91, 0xa9828020, 0x9a190122, 0xce840982, 0x71bdd424, 0x408500ff, 0x8223f921, 0x4c0622af, + 0x24d382ce, 0x00ff1f45, 0x21748309, 0x1e823d03, 0x32b30822, 0x04226a82, 0x9e82156e, 0x05226483, 0xa8853e4a, 0x0f060023, 0x83bc845c, 0x85ab211e, + 0x0029d286, 0x96299c06, 0x660700ff, 0x22f48567, 0x821c0800, 0xd90922af, 0x21258298, 0x2582eb05, 0x68260722, 0xc0205e82, 0x02228882, 0x3482e07a, + 0x820ad721, 0x142e2172, 0x372d1e82, 0xfffff6a8, 0x05723dee, 0x660d00ff, 0x263e8266, 0x00ff0a57, 0x86cdcc0e, 0x830f20c1, 0x87062409, 0x4bff08ae, + 0x392405e0, 0x8d059a19, 0x14224a82, 0x6f82927a, 0x82c23521, 0x3333240a, 0x840100ff, 0x830d2021, 0x4f02222c, 0x8440821c, 0x74332114, 0x80220982, + 0x3c828b00, 0x06820e20, 0x33260c82, 0xfeffff34, 0x6b828ccc, 0x82cccc21, 0xe4b02181, 0x09201a82, 0x782d1484, 0xffff9252, 0x8d3ecaf8, 0xebf6ffff, + 0x236e8686, 0x66e6c6ff, 0x0e269882, 0xffff66e6, 0xd31878f9, 0xf7200752, 0x0d27a783, 0xffff6866, 0x82f6a8f5, 0xb3372729, 0x1100ff32, 0x29828ec2, + 0xcecc0827, 0xd10200ff, 0x05b641ec, 0x85fdff24, 0x55829120, 0x8298d921, 0x19082225, 0x215a829a, 0xb6826826, 0xff293f82, 0xff9899f5, 0x9a990600, + 0x211a8280, 0x9682b304, 0x68e6f723, 0x212c8205, 0x178219f5, 0x824c0521, 0x80f4259d, 0x0400ff00, 0xf4282b83, 0x8b089a19, 0x10ffff07, 0x56224283, + 0x9c189a99, 0x2e590c5a, 0x832d2006, 0x00ff2723, 0xffcd4c2b, 0xd182dcff, 0xb3240023, 0xdcd61833, 0xccd32308, 0x16838bcd, 0xdb211182, 0x230a834c, + 0x0833b3d4, 0xd2201182, 0x3f82d882, 0x22083287, 0x8b33332c, 0xffaf0e08, 0xcccc3f02, 0x80c000ff, 0x798b1500, 0xf1ffff7c, 0x8b7a66e6, 0xff066b08, + 0x82b30000, 0xe65f23a8, 0x3b820566, 0x6482fd20, 0x82ffff21, 0xfdff2128, 0xff20a383, 0xfd241a83, 0xff08ce4c, 0x01fc0213, 0xff2c0887, 0xffffcc4c, + 0x0596831f, 0x00ff8493, 0x839c1904, 0xe6feffff, 0x8b088264, 0xf70e058b, 0xff154b94, 0x9a9972ff, 0x8dffff8b, 0x00ff6666, 0x00200a84, 0x08220a82, + 0x0683ff8b, 0x04861184, 0xea1a1582, 0x733e2f42, 0x8b1594f7, 0xffff8f83, 0xff0080f8, 0x33b30600, 0x66fcffff, 0x00ff0866, 0x4b010060, 0x314f9605, + 0x0e002405, 0x828e66e6, 0x0080221d, 0x25198296, 0x96323308, 0x1383ff88, 0x00ff8023, 0x2f2c8307, 0x34b3aaff, 0xcc3800ff, 0x00ff05cd, 0x0733337b, + 0x11555618, 0xf55ff120, 0x99f32205, 0x22c78299, 0x4c6766f4, 0xff2a0bb4, 0x66e60000, 0x0e051cfb, 0xce74f7af, 0x74981905, 0xd7b9182b, 0xcc752d24, + 0xb3feffce, 0x8d05146e, 0x33faffff, 0x0128aa82, 0xffff9819, 0x8bccccf9, 0xce210583, 0x27068208, 0xff66e6e1, 0x0080e7ff, 0xe12a0486, 0x088b68e6, + 0x9936ffff, 0x65180698, 0x585f08d4, 0xae54180f, 0x3766180b, 0x53c2180c, 0xb0122d2f, 0xcc0500ff, 0x00ff08cc, 0xff5ac475, 0x1b53c218, 0x70ceb918, + 0x74f80e2f, 0xffff15eb, 0x0600807a, 0xc0d2ffff, 0x25048400, 0xf3ffff05, 0x048634f3, 0x66e6ef2a, 0x4cf9ffff, 0xeeffffcc, 0x83050b76, 0xffff2906, + 0xffa4f0ef, 0xf0a70600, 0xe8272582, 0x0c00fff6, 0x84081018, 0x00ff243b, 0x8200402d, 0x18518540, 0x210c7048, 0x43828b86, 0x087a5422, 0x2105986d, + 0x87187a54, 0xab2b07d4, 0x1100ff86, 0x088b85ab, 0x830654f8, 0x4d278209, 0x0e23050f, 0x848b7a54, 0x18082010, 0x4108ec5e, 0x5b240fa3, 0xffff1523, + 0x2618337e, 0x00ff3433, 0x86cccc0a, 0x06337e04, 0x210b957f, 0x93823433, 0x08203e82, 0xff220685, 0x957ff5ff, 0x6639280f, 0x5100ff66, 0x82156666, + 0x211b83ed, 0x5382b3f9, 0x33330826, 0xe6fcffff, 0x09821982, 0xff088b24, 0x48830800, 0x2e080023, 0x05655214, 0x3d060023, 0x05655270, 0xf714f728, + 0x00ff0514, 0x0f827d0c, 0x2309ed51, 0x9082f3ff, 0x0fbdf418, 0xebffff24, 0x868270bd, 0xff291a83, 0x080080f3, 0xa1b6ffff, 0x21048248, 0x40823493, + 0x304ea382, 0xf1ff2307, 0x304e86ab, 0xeeff2305, 0x7d827a54, 0x7118ff20, 0x1b83091d, 0x21066541, 0xe882ffff, 0x3f820720, 0xff9a9928, 0x66664900, + 0x7582ff05, 0x75848f20, 0x71206a83, 0x65822682, 0x6a841482, 0x8f82f322, 0x27520a84, 0x20b08206, 0x820f8471, 0x0c8024db, 0x82ffffcc, 0x0e052904, + 0x01ff53f8, 0x1500c087, 0x8021fb82, 0x21828200, 0x23820040, 0xff343330, 0x66e60a00, 0x4cf1ffff, 0xfb088bcc, 0x098206d4, 0x825c4f21, 0x38f32347, + 0x29828152, 0x82a47021, 0x83c02010, 0xbec226ce, 0x06ffffb8, 0x23ce8273, 0x3188fdff, 0xfe271b82, 0xffffc5c0, 0x8232b3f5, 0xb3f5282c, 0xffff0834, + 0x82ae879f, 0xe5ff21e5, 0x220dcc5a, 0x5a8f821a, 0xff241bcc, 0x52786000, 0x00283682, 0xffec510a, 0xc4c0feff, 0x47228f82, 0x6382ffae, 0x09823220, + 0x828e0221, 0xc2250857, 0x00ff0ab7, 0x05d8a3f8, 0xd8feff2c, 0xfb150040, 0xcb6b0654, 0xc8ffff05, 0xff0652f8, 0xae073000, 0xf70554f7, 0x210a85a2, + 0x188654fb, 0x824b6b21, 0xf88425f1, 0x24fb1524, 0xff235d82, 0x825c4fee, 0x83b020c8, 0x820483cd, 0x22ed820e, 0x83ff0624, 0x20c08218, 0x211482f1, + 0xf8830e00, 0x5c110021, 0x06820570, 0x1183ff20, 0x0e820486, 0xff088b26, 0xd8633f00, 0xe2363382, 0x00ffae07, 0xff34b327, 0x52b8d0ff, 0x141800ff, + 0xcdffff7a, 0x208266a6, 0xe8a7ff23, 0x274e82f5, 0xffcd4cb8, 0xec51b8ff, 0xa7230a82, 0x850866e6, 0x00ff2206, 0x26658247, 0xce4cb8ff, 0x795800ff, + 0x222b0536, 0xff8b47e1, 0x68262100, 0x830b00ff, 0xd91b2753, 0x1400ff98, 0x6982f6e8, 0x82380e21, 0x870a2659, 0xffff9fae, 0x210a84fd, 0xc0820a97, + 0x8200e021, 0x840a201a, 0x82d7200a, 0x28fd260f, 0xebfffff6, 0x25d583f0, 0xffff00e0, 0x398268f5, 0xf8d8ff26, 0xe2ffff52, 0xff279882, 0xff86abd1, + 0x826bf0ff, 0x28cf2204, 0x319d83f5, 0xffc39584, 0x46010000, 0x809bffff, 0x6400ff00, 0x7e820080, 0xcc4f7b20, 0x84068205, 0x82048611, 0x2331820e, + 0x66264500, 0x40262282, 0xffff9ad9, 0xf58287df, 0x82192a21, 0x59ca2209, 0x2386829a, 0x07523846, 0x28411b82, 0x61158215, 0xb02e08f6, 0xffff8ba4, + 0x085c4fee, 0xf864f80e, 0x0b821544, 0x880a864e, 0xffff281c, 0x07f6e8b5, 0x82d8ffff, 0x37003061, 0xffffec91, 0xffcc4cbf, 0x1e852200, 0x4cb8ffff, + 0xa1200598, 0xff22af83, 0xf98217ad, 0x82a8c321, 0xe22108f9, 0xffff71fd, 0x08d623a6, 0x8ffaffff, 0xefffffdf, 0x00ffa530, 0xff293c09, 0x14eeedff, + 0xd01000ff, 0x20188221, 0x22ab8399, 0x82d7e310, 0x20f3830a, 0x28338211, 0xdf4f0900, 0x6b0500ff, 0x21238285, 0xca822bc7, 0xf5681427, 0x633f00ff, + 0x06056cd7, 0x28832a20, 0x73844220, 0x83320021, 0x2d002d73, 0xffff90c2, 0xff3473e7, 0xd6231c00, 0x8c21a382, 0x237382cc, 0x069a99d3, 0xf085cc96, + 0x2706e743, 0xffa4b0f1, 0x86ab1100, 0x82071f66, 0x42198509, 0xf7210a71, 0x074b4124, 0x21062345, 0xc0465c4f, 0xff082b05, 0xcccce9ff, 0x66eefeff, + 0xe1821566, 0x827a1421, 0x207021b8, 0x0a261b82, 0xf6ffff3e, 0xd68200c0, 0x827c9421, 0xd6382118, 0xeb252982, 0xffff9a99, 0x216e82c0, 0xc282c5ff, + 0x83d5ff21, 0x66bd2304, 0x1a828b66, 0xc783cd20, 0x40d2ff32, 0x1800ff00, 0xffffcc8c, 0xff9ad9e3, 0x34732700, 0x2c23fd82, 0x45066666, 0xd34505c3, + 0x11084305, 0x84064e50, 0x7b542593, 0x14fb088b, 0x1b0c216a, 0x430aca06, 0x0023096d, 0x437b540e, 0x1e460572, 0x25619605, 0x174a00ff, 0x8a82070a, + 0xff67e62e, 0xf668c8ff, 0xb34000ff, 0xddffff34, 0x0021ba82, 0x05734c46, 0x32735e33, 0x5200ff8b, 0x00ff34f3, 0xa80a573c, 0xdc5900ff, 0x26b6822a, + 0xff666606, 0x82cc1000, 0x82f620cb, 0x12003031, 0xffff66e6, 0xff3233ef, 0x00800400, 0x59af0e08, 0x8e181bf4, 0xf45919fb, 0x21338219, 0xad18dcff, + 0xd42014b2, 0x07679e18, 0xb3110022, 0x146e8d18, 0x8bcd4c25, 0x86f1ffff, 0x220a821b, 0x18cd4cee, 0x7207f65a, 0x44520f12, 0xda91180d, 0x15eb2109, + 0x2d094819, 0x212e3868, 0x5fdc54fb, 0x6cf7cb22, 0x0c4b0519, 0x18f5ff21, 0x240fb64c, 0x33b30a00, 0x241683ff, 0x4c0d00ff, 0x06d767cd, 0xff840d20, + 0x34b30a23, 0x1d4c18ff, 0x832b8511, 0xf2ff2a1b, 0x088b34b3, 0x8b0674fb, 0x20648f2b, 0x0b5d57cd, 0x64ab4584, 0x8118cd20, 0xcf1808c3, 0x64940784, + 0x07204d18, 0x64b06b84, 0x6488cc20, 0x07b7cf18, 0x0e326482, 0x94f7db2f, 0x8b07bb15, 0x874f00ff, 0x4000ffae, 0x04820080, 0x82527821, 0x0512430e, + 0x06824f20, 0xff231685, 0x82ae87bf, 0x78b02679, 0x075b0852, 0x0ecc5c9b, 0x82cd4c21, 0xb3dc251a, 0x54fb0833, 0x3238a218, 0x00283383, 0xffcd4c23, + 0x66a61c00, 0x0b445e18, 0xcb069b27, 0x34f7158b, 0x22a08406, 0x4f142e2c, 0x23220629, 0x294fecd1, 0xa17e1913, 0x075b2509, 0x155bcb0e, 0xf7219282, + 0x30ec8233, 0xff00c0f8, 0xccccf8ff, 0x40f7ffff, 0x6b088b00, 0x82088506, 0x21188213, 0x93490700, 0xcccc2405, 0x8264f808, 0x110021bb, 0x0e211483, + 0x06b84840, 0x8b220e83, 0x0684ff08, 0x2206ca48, 0x8200c0f1, 0x40ee3359, 0x64fc0800, 0x9c01ff07, 0x84f8cc4c, 0xf9ffff15, 0x168290a2, 0xe05af925, + 0x82feffff, 0xf9ff38c5, 0xffff86ab, 0x08f41dfd, 0x4fd2ffff, 0xebffff5c, 0xffffd823, 0x824821de, 0x84eb2676, 0xc2e3ffff, 0x2357828e, 0x3e0ac4ff, + 0xdd213582, 0x2cf68226, 0xff2adc1f, 0xf6e8baff, 0x020000ff, 0x2135828e, 0x3082a3e7, 0x82ffff21, 0xb3e2213a, 0xfb22c582, 0xfe824270, 0xff666624, + 0x5483f5ff, 0x80a1fe39, 0xffab0700, 0xe8fb0900, 0xde1b00ff, 0x0400ffb8, 0x00ffb21d, 0x82e2fa18, 0x49003356, 0xff8b48a1, 0x1e453300, 0x38e0ffff, + 0x4900ff52, 0x168334b3, 0xf6e81f22, 0x242c1682, 0x00ff281c, 0xff94f805, 0x7c142b00, 0x1e21da82, 0x22e08276, 0x82cc8c0d, 0xa4f02542, 0xe60700ff, + 0x0b218c82, 0x2ae48280, 0xcc4c0c00, 0x2d01ff08, 0x8207b85e, 0xa1132136, 0xef21bb82, 0x2626824c, 0x789a190b, 0x830e088b, 0x19a02241, 0x30fb829a, + 0xfbecfeff, 0xffff0504, 0xffae1aff, 0xccccd3ff, 0x21a98268, 0x0a829a19, 0x22050a4c, 0x82ae87e5, 0x78ea21e4, 0x15228882, 0x4a825c8f, 0x00801a22, + 0x7f227282, 0x57830ad7, 0x3f740c82, 0x99152406, 0x8200ff9a, 0x22aa830e, 0x827ad40a, 0x820a2028, 0xfdff23a0, 0xe782ea46, 0xffd6633e, 0x840bfcff, + 0xf3ffff08, 0x00ff6866, 0xfff89367, 0x6666a8ff, 0xf84e00ff, 0x95ffff52, 0x06836985, 0x63251682, 0xb1ffffd7, 0x278b8207, 0xfff668f3, 0x666698ff, + 0x092d6d82, 0xff8fd763, 0x7b140a00, 0xb30200ff, 0x21098234, 0x67837bd4, 0x097a7218, 0x66eaff23, 0x20a68266, 0x219b83e5, 0xa95680ff, 0x82e52005, + 0xeaff2491, 0x83ff0080, 0xffff211c, 0x33821b82, 0xe3d3ff23, 0x212882d7, 0x4f8202dd, 0x48e12322, 0x2c22a682, 0x9782142e, 0x9919ff28, 0xf06f00ff, + 0x118205a4, 0x82338d21, 0xcc722a62, 0x7200ffcd, 0x00ffcccc, 0x057d598d, 0xa5828c20, 0x7e821182, 0x2005e15c, 0x235983ff, 0x08343373, 0xff224e82, + 0x0585cccc, 0x0000ff38, 0xffff66e6, 0x08ceccff, 0xf770fb0e, 0x1514f8d4, 0xe680feff, 0x1e820766, 0xf827cf84, 0xffffbaa9, 0x827a94f4, 0x3c7f2604, + 0xd9faffff, 0x267c829a, 0xffa4f0fa, 0x8228fdff, 0x4cfc22ee, 0x263d82cc, 0xffff9a19, 0x839a99fb, 0x4ff822ae, 0x223a82e0, 0x827268f8, 0xf0c721f9, + 0x02263082, 0x0500ff90, 0x35822050, 0x26827920, 0xe6770029, 0xffff0566, 0x6d842bac, 0x00230c12, 0x82707d15, 0x9c1928c8, 0x00ff082a, 0x82f0e760, + 0x1a00227e, 0x28398282, 0xff717d15, 0x0a971400, 0x200e82ff, 0x275f828f, 0x0ad75300, 0x8600ff06, 0x4a85b482, 0x6c09002d, 0x0800ff08, 0x00ff0060, + 0x820c820d, 0x34132174, 0x23058b54, 0x1acffaff, 0x0b2a1982, 0xffffb087, 0xff18a4fc, 0xaa830700, 0xa4b0f322, 0x0832d985, 0x01ff2f0e, 0xff9a999c, + 0x9a190a01, 0xf5ffff15, 0x468252b8, 0xff10582a, 0xb8def0ff, 0x87feffff, 0xf721bb82, 0x27e182a8, 0x0810b8f5, 0x98f7ffff, 0xf5211982, 0x226582c0, + 0x82008001, 0x48e12523, 0x470a00ff, 0x985a2383, 0x66462905, 0xaff6ffff, 0x0600ff9e, 0xf2221e83, 0x6b569999, 0x83082005, 0x5ccf2406, 0x84f9ffff, + 0xec912616, 0xb0f4ffff, 0x212a82a4, 0x548200c0, 0x59857383, 0x5484fe20, 0x8242e021, 0xae672182, 0x1e838c82, 0xb8040022, 0xfa227382, 0x54822030, + 0x88a8e622, 0xf0220582, 0xd1828ba4, 0x1058052c, 0x0500ff8b, 0x00fff067, 0x0482c701, 0xa4700426, 0xa00300ff, 0x00325082, 0xfff68816, 0xbc741200, + 0xe60c00ff, 0x1a00ff66, 0x298266e6, 0x34b31c22, 0x00208682, 0xff240682, 0x9a19f3ff, 0xff221684, 0x7182e9ff, 0x80120022, 0xff223582, 0x14829990, + 0x5c0f9323, 0x07327115, 0xffde2f2b, 0x707df2ff, 0xedfdffff, 0x21ab82d4, 0xff827c94, 0x2983a020, 0xad07792c, 0x1988ffff, 0xffff0558, 0x301a33ac, + 0xfd670d19, 0x63e62206, 0x20d882d6, 0x054042a0, 0x2109334d, 0x988268eb, 0x41821a21, 0x4a820ec1, 0x82059a21, 0xc4f527ca, 0x0700ff83, 0x70829899, + 0x82343321, 0x053f4409, 0x20700422, 0x042cbd82, 0x00ff6085, 0xff6aee00, 0x76330400, 0xe727f182, 0x00ff08dc, 0x823e8a0b, 0xba292136, 0x2205d441, + 0x83660b00, 0x990c26e7, 0x14f8089a, 0x21338207, 0xe519970c, 0x0c220772, 0xd4865c4f, 0x9042042c, 0xffef0e08, 0x9a999c01, 0xef419ef7, 0x80552108, + 0x2107ef41, 0xe4827488, 0xfff6a826, 0x24bbf5ff, 0x2108ef41, 0x71828ec2, 0x82008021, 0xd7e32123, 0x2107ef41, 0x8083299c, 0xff664626, 0xf4bdf6ff, + 0x5e0cef41, 0xf12206f1, 0xef417ad4, 0x7c942107, 0x2107ef41, 0xef4190c2, 0xa09a2308, 0xef41ffff, 0x82e52005, 0x670822da, 0x837382ae, 0x06ef411e, + 0x82aa3121, 0xa8e62654, 0x01fdffff, 0x15f34106, 0x00ff6c22, 0x2105f341, 0x8a82b89e, 0xf6881627, 0x921100ff, 0x0cf341b0, 0x00801d26, 0x00ff8b08, + 0xf3410682, 0x33192206, 0x07f34134, 0x82666621, 0x823c2035, 0x490024d5, 0x8215cccc, 0xaec7267c, 0x550800ff, 0x05d54282, 0x90feff28, 0xf7ffff62, + 0x18825c8f, 0x4114c321, 0xd6251309, 0x400a00ff, 0x21238200, 0x48822a9c, 0x9eef2132, 0x2ee5ffff, 0x1300ff14, 0xffff6666, 0x8bcdccd6, 0x33210582, + 0x267e8233, 0x3233d6ff, 0x83ecffff, 0xb3d7224a, 0x068f4634, 0x6866e322, 0xf5215482, 0x414083c0, 0xf0200f09, 0x83080941, 0x39fa221e, 0x21ff829a, + 0x0941b8de, 0x0060210e, 0x0531d882, 0x00ff0060, 0xff6cc701, 0x52780400, 0xa60300ff, 0x318a82ea, 0xfff2122d, 0xe0fa2300, 0xcc1900ff, 0x3500ffcc, + 0x298266e6, 0x66e63922, 0x00208a82, 0xff270682, 0x3433e6ff, 0x823400ff, 0xd2ff2804, 0x00ff66e6, 0x82cccc24, 0x4c3d2835, 0x4a00ffce, 0x8215cecc, + 0xb0c7307c, 0x550800ff, 0xf0ffff80, 0xffff46e1, 0x417488fe, 0xcb210709, 0x13094102, 0x0941d820, 0x82282008, 0xef373048, 0xd2ffff9e, 0x00ff162e, + 0xff981920, 0x8266bcff, 0xb8ff217e, 0x8b216382, 0x2e0683ff, 0xe8dfffff, 0xbbfffff4, 0xffff0280, 0x82b007c8, 0x3233212a, 0x31220941, 0xffff38b4, + 0xff0a57f9, 0x68e60600, 0x088b9288, 0xfb8200ff, 0x200e0141, 0x07014150, 0x7c144330, 0xf83600ff, 0x2600ff10, 0x00ff0080, 0xa2191951, 0x57200a54, + 0x0822c618, 0x2a5c4f22, 0xe6219e82, 0x212a8268, 0x8282a4f0, 0xcccc1622, 0x6b21ec82, 0x08ff4384, 0x43562e21, 0xe52107ff, 0x07ff4320, 0x824ea221, + 0x05ff4329, 0x43842b21, 0x852114ff, 0x22e8821e, 0x822085e5, 0x14a02327, 0x0c84077c, 0x006c1e20, 0x20852107, 0x2312c145, 0x323388ff, 0x2405ff43, + 0xbdfaffff, 0x1f034470, 0x03442082, 0x44522006, 0x2a210803, 0x0d03443e, 0x08008027, 0xc77f01ff, 0x2d7e82ae, 0xec910c00, 0xb3f8ffff, 0x0b00ff34, + 0x0644846b, 0x26052a06, 0x2f0e0866, 0x34f824f7, 0x05fd4715, 0x6c050d48, 0x2b200abb, 0x17404a18, 0xb1462b20, 0x3b7a180e, 0x46eb2008, 0x15210dad, + 0x34a8827d, 0x8b8f821a, 0x7b06eb08, 0x064b154b, 0x06cb074b, 0xfb9b07cb, 0x18728e54, 0xb7084e7a, 0x00802172, 0x21055e41, 0x09831500, 0xf7247291, + 0x15a4f714, 0x85063174, 0x189b8523, 0x48079b6a, 0x7b180b8e, 0x8c9d08fc, 0x13b76218, 0xcb07eb24, 0xe283153b, 0xab2eea83, 0xab15b4fb, 0x6b076b06, + 0xeb07ab06, 0x0683156b, 0xf7210e84, 0x23168254, 0x2b0714fb, 0x6b2d1782, 0x4b072b06, 0x0754f706, 0x076b06eb, 0x241082cb, 0x34f8b30e, 0xa1591815, + 0x00402a0d, 0xf2ffff8b, 0xfc0800c0, 0x6b5a1824, 0x00402609, 0x4cf5ffff, 0x221884cc, 0x187b088b, 0x4d0cbe7a, 0xf8200a4c, 0x00203283, 0x13d0b019, + 0xe3069b26, 0x34fc157b, 0xad4b5183, 0x3ef41805, 0x18f7200f, 0x4b08b184, 0x30830bab, 0x163ff418, 0xf1180820, 0xd7210a22, 0x25b3820a, 0x08f628f7, + 0xcd839bd3, 0x133ef418, 0x4c20cd8b, 0x23068a4d, 0x33b3f2ff, 0xcb65cd86, 0x26cd8b13, 0x00ff33b3, 0x4e00c00a, 0x9b23064e, 0x848beb06, 0x65cc2068, + 0x3641087a, 0x4d4c2014, 0x534e068e, 0x067b2105, 0x16a45b18, 0x9318688c, 0x9b250c6e, 0x732cf706, 0x9a6f1815, 0x245c1808, 0x9ef51a0d, 0x2182be0f, + 0x6883934b, 0x13752719, 0x0800ff23, 0x25e983cc, 0xff343307, 0x6c41f8ff, 0x0cce4108, 0x0e18f418, 0x146eb618, 0x0734f82f, 0xf8bb2f0e, 0x00ff1534, + 0x06008095, 0x08d7829c, 0x33331029, 0x42f9ffff, 0xffff9790, 0x0870fdf3, 0x00b000ff, 0x50ffff01, 0xa405cd0c, 0xffff8b72, 0x726766d7, 0xffff0872, + 0x8498997a, 0x72052204, 0x22148472, 0x82a4728b, 0x22268215, 0x820544f7, 0x35fe2139, 0xf9293f82, 0x00ffcb41, 0x8b343310, 0x8246829c, 0x171c445f, + 0x058b8b25, 0x1824fbcb, 0x830fe59e, 0x491120df, 0x577905b0, 0x0c596306, 0x2305f862, 0xabf1ffff, 0x23085563, 0x08cc4cee, 0x18081751, 0x2a0d90a0, + 0xd801ff0e, 0x01ffcccc, 0x829a9917, 0x4c342367, 0x288256cc, 0x1182aa20, 0xb3cbff2c, 0xfb085634, 0x8effff04, 0xb98234b3, 0x0cb05718, 0xffffff2c, + 0xffff66e6, 0xff9a99f6, 0x5c820900, 0x80210a82, 0x260a8300, 0x00ff8bce, 0x8432330f, 0x2104820a, 0xe0820080, 0x2a826f20, 0x33710022, 0x00214482, + 0x220a8321, 0x82cc4c22, 0x33372625, 0xdeffff34, 0x82408219, 0xff082a0f, 0xcc4c80ff, 0x3a8100ff, 0x846a83e2, 0x146e2556, 0x190000ff, 0x0f221f82, + 0x4a84a430, 0x51210482, 0x224f82ec, 0x84666609, 0x2069830a, 0x24898234, 0x00fff4e8, 0x22138208, 0x8391f6ff, 0xb380261e, 0x7effff32, 0x284882ba, + 0x483327fe, 0xe6c2ffff, 0x05c54166, 0x200a6541, 0x0537725d, 0x4107304c, 0xa82518e2, 0xffff0100, 0x18e24158, 0xe7ffff2a, 0xff720100, 0x6666d7ff, + 0x8205e641, 0x3cf7212a, 0x2e15e641, 0x8b140000, 0x6f00ff05, 0x00ffedff, 0x64008075, 0xa64113fc, 0x171d531a, 0x34201783, 0x1b105c65, 0x2120eb90, + 0x6318c4fb, 0xff2a0bd4, 0x1e05d5ff, 0xcaffff8b, 0xfc6de2fa, 0x24098206, 0xfa2a00ff, 0x281984e1, 0x053500ff, 0xf7088b1f, 0x13e55ad4, 0x20c51027, + 0x00ff8b08, 0x92901b0b, 0x0728261a, 0xcc0900ff, 0x210482cc, 0x8d5ad8a3, 0x0c002305, 0x34829899, 0x34330e2d, 0xcffeff08, 0x64f79a19, 0x8254f715, + 0xb309225d, 0xd06b1a32, 0x08355111, 0xf8184282, 0x3f220c07, 0xc5829a19, 0x9919f822, 0xf6182182, 0x45820eaf, 0x2e820820, 0x19070021, 0x26081bad, + 0x8b67e607, 0x924b8b08, 0xe1911867, 0x18678407, 0x9213ebb8, 0x84332067, 0xf1b81860, 0x22678609, 0x8400ff33, 0x00ff2967, 0xfb66e6f0, 0xb4fb1594, + 0x200c2d56, 0x09185c00, 0x174f9418, 0x4b06b42b, 0x30fb0e07, 0x1554f8bb, 0x074418f7, 0xfeff2518, 0x07cc4c48, 0xf226af82, 0xffff9a99, 0x048719f5, + 0x8b220e82, 0x17828608, 0x9819fb22, 0x3306944c, 0xff68e6fb, 0x66e60200, 0x66ffff08, 0x00ffcc4c, 0x059a996b, 0x47260a82, 0x94ffffae, 0x0a826666, + 0xf6e8fb25, 0x83fdffff, 0x21fb2242, 0x06744c48, 0x8f02fb23, 0x2230828b, 0x825c8ff2, 0x1cf5274b, 0x0a00ff29, 0xb18266e6, 0x82660d21, 0xb7012347, + 0xaf4434b3, 0xf80e2517, 0x1594f754, 0x190e2570, 0x5d0a3f24, 0xab211841, 0x421a9806, 0x11261576, 0xeb0886ab, 0x9142ab07, 0x821a8513, 0x4c2323ae, + 0x7c82ffcd, 0x1c3df582, 0xffff33b3, 0x8b34b3dc, 0x94fb4b08, 0x0694fb15, 0x94f707eb, 0xbb072b06, 0xff152cf7, 0x017618ff, 0x00ff2415, 0x471e450d, + 0x0a220649, 0x7948e2ba, 0x48082005, 0x45220d80, 0x3e828b1e, 0x08e2ba22, 0x176a6c18, 0x7cf7c428, 0xe500ff15, 0xa8820080, 0x00801a2f, 0x7de5ffff, + 0xffff0570, 0x079082ba, 0x231282cb, 0x0700c052, 0x082ea882, 0xffffe87b, 0xff00a0fc, 0xd0220800, 0x905e9185, 0x06fa300d, 0x0600ff66, 0xffff4801, + 0xffceccf7, 0x82600300, 0x99f72f45, 0xff088b98, 0x3433edfe, 0xeeffff06, 0x7e820a57, 0xf6a8f122, 0x2507196a, 0x087a54ee, 0x608214fb, 0x0e07eb29, + 0x99c200ff, 0x8234f89a, 0xcc7a2284, 0x227182cc, 0x8234b314, 0x4c122270, 0x21b782cc, 0x9a4eaec7, 0x66ec2206, 0x2cd88266, 0xff66660a, 0xecd1e0ff, + 0x4a00ff05, 0x948018b3, 0x4ce3220e, 0x226382cc, 0x6834b3dc, 0x9e1906c7, 0xf6411361, 0x3f97190e, 0x94f7210a, 0x2320e583, 0x4f557482, 0xff342507, + 0x9a592300, 0x6a82c382, 0x96823320, 0x67660a27, 0x2e1f00ff, 0x297b8214, 0xff008006, 0x9a991300, 0xa58300ff, 0x380d0025, 0x8300ff52, 0x8b0821b5, + 0x3d252782, 0xf4fb6666, 0x8c171915, 0x37e51815, 0x568b2716, 0x192a00ff, 0xec4d609a, 0x08300805, 0x34f82f0e, 0xffff15ab, 0x06a430e6, 0xe876ffff, + 0x6b01fff6, 0xff05703d, 0xdf4ffbff, 0x780c00ff, 0xf4ffff52, 0x00ff351e, 0xff3e4a08, 0xf6a8f2ff, 0x0684a382, 0xffff7f25, 0x8204b6f7, 0xeb513126, + 0x87f3ffff, 0xffff086c, 0xffd7a378, 0x90c294fe, 0x4d853c82, 0x5b0b3560, 0x105b08dd, 0x0c145a09, 0x785aeb20, 0xffff242e, 0x833333fe, 0x9a192833, + 0x00ff05bb, 0x859b999f, 0x825b200c, 0x5b1b827d, 0x7d852e8e, 0x5d09b060, 0x8a5b0fff, 0x33082f11, 0x1504f733, 0xcc3700ff, 0x9400ffcd, 0x838266e6, + 0xecd13727, 0x196bffff, 0x0881829a, 0x47619028, 0x30fb0e06, 0x194101ff, 0xcd00ff9a, 0x9e159a99, 0x4c1600ff, 0x0b00ffcc, 0x00ff66e6, 0x8b00801c, + 0x991f00ff, 0x0682089a, 0x0a97463a, 0x94c6ffff, 0x3900ff7c, 0xfffff668, 0x8b846bb9, 0xff54fb08, 0x70fdffff, 0x43414982, 0xff5e2219, 0x06585b00, + 0x515ba220, 0x9b082605, 0x07d4fb06, 0x0c62457b, 0x410a905b, 0xf7241678, 0x00ff0674, 0x8309647e, 0x83948584, 0xb52e269b, 0xe6ffffc4, 0x25c38299, + 0xff008028, 0x0482daff, 0x66160027, 0xffff0866, 0x25c7832e, 0x15d66392, 0x6a5804f7, 0xae47270e, 0xdcffff8b, 0x3f8252b8, 0x72440683, 0xe3ff2305, + 0x7244ae47, 0x04fb2f06, 0x0714f706, 0xfeff24f7, 0x159002c0, 0x0d8524fb, 0x4a21448e, 0x2244823e, 0x83289cdd, 0x86068244, 0x7de12244, 0x2a448672, + 0xf830fb0e, 0x7f01ff14, 0x861570fd, 0x5ce983d7, 0xff240565, 0x8b5c4fee, 0xc530a282, 0xff067c54, 0x33b37aff, 0xff05d4fb, 0x51f83f00, 0x8d5e6382, + 0x21419614, 0x3e8254fb, 0x56854b83, 0x60110c5d, 0x3a221115, 0x648285ab, 0xcd4c8523, 0x237282f7, 0xae07c0ff, 0xb71941ae, 0xae211060, 0x299c8314, + 0x0e08ec51, 0xffb4f7af, 0xef829f01, 0x4194fb21, 0x4b2017e1, 0x5d07df60, 0xab262671, 0xfb06cb07, 0x841807d4, 0x31420df6, 0x43142022, 0x6b232eab, + 0x82d4f706, 0x8a6b206a, 0x417a209e, 0x11240653, 0x088b86ab, 0x430d2c64, 0xd065087b, 0x14ae2105, 0xb3262a82, 0x0e00ff34, 0x085fec51, 0xe9002907, + 0xfeff6866, 0x152a9cb6, 0x09436318, 0x00ff052b, 0x070080e5, 0x600900ff, 0x21158200, 0x108200a0, 0x9839062c, 0xc6f9ffff, 0x0800ff66, 0xe9633433, + 0x63342008, 0x59631ce9, 0x0ad27505, 0x1376ff20, 0x4b082207, 0x0af075cb, 0xebffff24, 0x7c6300c0, 0x4b4b210b, 0x630a7677, 0x8020087f, 0x40828c82, + 0x8407fe6a, 0x7514204b, 0x668308dd, 0x09221a82, 0xb7824861, 0x82345321, 0x831a2040, 0xf6ff23c3, 0xc88400a0, 0x39776f9b, 0x206c9009, 0x238a82cb, + 0x9a390600, 0x3220fc88, 0x1e22fc99, 0xe664ff36, 0x82cb2009, 0x05166ce1, 0x820be464, 0x41a885c3, 0xfc82080a, 0xffb0c726, 0x64fbffff, 0x08248589, + 0x34f82f0e, 0x2005a242, 0x181560fc, 0xc0ffff24, 0xa64268e6, 0x14f72430, 0x4414fb06, 0xef2315d9, 0x8208c235, 0x450682ff, 0xf022060e, 0x0e453eca, + 0x21d44506, 0xff86ab27, 0xf6680d00, 0x058065ff, 0xf7067b24, 0x6a820714, 0x2226a742, 0x828bec51, 0x14ae2768, 0x3f00ff08, 0xd3829819, 0x42110021, + 0xff2913ab, 0xff9a99d6, 0x2a9cf6fe, 0x052a4115, 0x800c0023, 0x103b4200, 0x421acb41, 0xff240bd0, 0x0600801a, 0x00251085, 0x05cc6c09, 0x204c82ff, + 0x20048301, 0x067e7800, 0x7ff3ff23, 0x200f84ff, 0x86518208, 0x426c900a, 0x3b421da8, 0xae472305, 0x2267ffff, 0x822e2005, 0x052267b7, 0x8ba43022, + 0x0820eb82, 0xff210682, 0x22058200, 0x420300ff, 0x7120053b, 0x43052267, 0xff201a38, 0x490ad042, 0x108405fd, 0x33430483, 0x3a06221d, 0x218782e2, + 0x708264bb, 0xc3423320, 0xfabf3147, 0x3f00ffe2, 0x0e0564fb, 0xf794f72f, 0x74fb15f4, 0x230c4f45, 0x7c540e00, 0x1ead6818, 0x49183082, 0xff200adb, + 0x098f4719, 0x168e6a18, 0x94fb8b22, 0xd1616591, 0x05b34e09, 0x0f409918, 0x658ff720, 0x5034b321, 0x7d1805b2, 0xfb231727, 0x6134f794, 0x4c8f07bb, + 0x4a18f820, 0xff200d8e, 0x0e0f8918, 0x11129b1a, 0x180ec143, 0x230ae4bd, 0xb4fb34f8, 0x4805d24c, 0x7c74099a, 0x4e4e180a, 0x90891819, 0x2f0e262d, + 0xf4f7d4f7, 0x05834715, 0x41083663, 0x4c22139c, 0x1683ffcd, 0x20051150, 0x10414708, 0x1f2b6c18, 0x14fbeb22, 0xcd20ce92, 0x0319c784, 0x4f4118c4, + 0xfb342231, 0x369c4174, 0x22061c75, 0x18b3f1ff, 0x41079193, 0x0253119c, 0xd4f72207, 0x113241eb, 0x18116942, 0x200ef492, 0x13941854, 0x1e69420f, + 0xf82f0e23, 0x08384334, 0x422b9b41, 0x9b410fd2, 0x0938431f, 0xcea0658a, 0x3843658f, 0x34fc211f, 0x23cd3843, 0xf4f734f8, 0x4411d242, 0xd2421fd5, + 0x239c4110, 0x44198942, 0x9c414707, 0xf8e322ce, 0x17e65824, 0xb3595b20, 0x0de55809, 0xb3595b20, 0x82bb2017, 0x14b25931, 0xf806bb24, 0x4f187b1c, + 0xa4460ce9, 0x8473180e, 0x059b5312, 0x21176743, 0xfe1984ab, 0xf72310d6, 0x198b06b4, 0x1911a709, 0x9d1ed87c, 0x33b32165, 0x4c216587, 0x07cf45cd, + 0xa0446594, 0x20659e1e, 0x20658834, 0x286589cc, 0x2cf764fc, 0x00ff8b15, 0x257a830d, 0xff00c00a, 0x8e830a00, 0x1df80d19, 0x2233b341, 0x421cfbd3, + 0x02690e02, 0x844eb308, 0xfce818b2, 0x06bb2211, 0x4ea91a0e, 0x0f0f481b, 0x431fec43, 0x4e4410e8, 0xf7072409, 0x4614fb54, 0x5b4609db, 0x1178482c, + 0x2010f047, 0x078a474c, 0x2b74f722, 0x450ed242, 0x4b911fd8, 0x210e2a5a, 0xad900e00, 0xfb34fc22, 0x47374549, 0x8b342ba8, 0x0000ff07, 0x00ff713d, + 0x156666b3, 0xc2f7ffff, 0x0600ff8f, 0x24059263, 0x00ff6766, 0x331a8308, 0x08676606, 0xf56500ff, 0x4f00ffc2, 0xff05cc4c, 0x00800a00, 0x2105c94e, + 0xb7820f00, 0x80f8ff2f, 0xffff8b00, 0x0832b3f2, 0x6661ffff, 0x053e4468, 0xffff3226, 0xff33b3f0, 0xff221c83, 0x3086f5ff, 0x9a222082, 0x46853e0a, + 0x8b2f0e22, 0x193d7718, 0x42300446, 0x02101917, 0x27330115, 0xd11900ff, 0x6400ffec, 0x3d055d67, 0xffff717d, 0xffccccf7, 0xa4b0f0ff, 0x800700ff, + 0x00ff8b00, 0x08ce4c0d, 0x999e00ff, 0x0c850798, 0x0f00ff24, 0x1c845c4f, 0x0a00ff24, 0x30848f82, 0x65282082, 0xffffe2fa, 0x0534b3b0, 0x4c311a82, + 0xf9ffffcd, 0xff8b9999, 0x9999f3ff, 0xb3f8ffff, 0x260f8333, 0xffff089a, 0x851e059a, 0xaf0e2825, 0xe4f714f8, 0x82b4fb15, 0xe5ff2855, 0xffff707d, + 0x869082ea, 0x230e8204, 0xb4fb088b, 0x200ec861, 0x824e187d, 0x68338308, 0x2d610a77, 0x8f822305, 0xaf59088b, 0x54f72119, 0x8027d382, 0xfeff1500, + 0x839a19ff, 0xe6210872, 0xffff0080, 0xff7cd4e2, 0x2a1cf1ff, 0xc7eaffff, 0x0e00ffac, 0xff089899, 0xd86392ff, 0x7d4b00ff, 0x28c88270, 0x0768669d, + 0x996d00ff, 0x21108298, 0x10825c8f, 0xd04c1522, 0x9c262682, 0x1d00ff28, 0x3a829819, 0x8bae0730, 0x99e6ffff, 0xff0e089a, 0x9a19bf01, 0x044934f8, + 0x8add2205, 0x2517823d, 0xffd559e3, 0x4918e3ff, 0xa6240fd3, 0x1c00ff66, 0x19830482, 0x2200ff29, 0x088b3373, 0x570614f8, 0x1985058c, 0x8b201e83, + 0x08221084, 0x7f82d4f7, 0x56020022, 0xff240d84, 0x3233e4ff, 0xff2a2285, 0x8bceccdb, 0x4be4fb08, 0x4f18ff15, 0x712008a6, 0x0bda4f18, 0xe5277e82, + 0xffff707d, 0x846666eb, 0x223b8216, 0x828b9999, 0x82e420dd, 0xb64f1806, 0x05756209, 0x06850820, 0x1600ff24, 0x955d4861, 0x9e192f06, 0xf7088bb8, + 0xc8feffe3, 0xff156666, 0x7882fdff, 0xccfaff2d, 0xfaffffce, 0xffff9a99, 0x82ccccfc, 0x9a192109, 0xfe295082, 0x069002a2, 0xfaf9ffff, 0x2672829f, + 0xffb27dfa, 0x82610300, 0x45fd280f, 0x0500ff1e, 0x8208fa5e, 0x2b0a843b, 0x00fff45d, 0xffd88300, 0x68710600, 0x8c202382, 0x04267282, 0xd108b8de, + 0x0d8205eb, 0xff190426, 0x862b0400, 0x58820482, 0x82020021, 0x050021b3, 0x06845d84, 0xd0211682, 0x214782e5, 0x2a821a8f, 0xff950331, 0xf4ddfbff, + 0x2000ff08, 0xffffc275, 0x82707dd3, 0x4c5d2740, 0x8b00ffce, 0x0a829a19, 0x90020322, 0x48217882, 0x220582b5, 0x8233b302, 0xcc4c210a, 0x0021a582, + 0x82068205, 0x820c200c, 0x53fd26c1, 0x0200fff8, 0x273c82f5, 0x08088cfb, 0x54fb14f7, 0x4a213683, 0x2157823e, 0xa4820020, 0xdb824c20, 0x34b3f922, + 0x2c05e568, 0x32b3faff, 0x30fb0e08, 0x94f714f8, 0x27e18215, 0xfb9a99a8, 0x64ffff09, 0xff21a282, 0x235f82cc, 0xccccbfff, 0xf320e382, 0xf0200a83, + 0xe9223483, 0x26823433, 0x00220f83, 0x1a834c0f, 0xd283cb20, 0x82334021, 0x41c8194f, 0x8bf52725, 0xaaffffe1, 0x45823e0a, 0xc2f5952a, 0x0e068b08, + 0x54f794f8, 0x72227b83, 0xe87b9a99, 0x8dff2105, 0x0e827e83, 0xff7bd982, 0x83fb2043, 0x14fc2260, 0x317a8207, 0x08f58be1, 0x6a00ff8b, 0xff3566e6, + 0x9a195500, 0xfd838b21, 0x00ff9b25, 0x8266e680, 0x49002183, 0x0036c882, 0xffcd4c66, 0x52789c00, 0x993000ff, 0x4600ff99, 0xff084821, 0x14830c00, + 0x0ab71127, 0x991900ff, 0x8342829a, 0xeeff240f, 0x8308f648, 0x23b88225, 0xffb8deb9, 0xcc253982, 0x8763ffff, 0x20dc82ae, 0x057267b6, 0x66e69d25, + 0x82b1ffff, 0x22048555, 0x83cccc9e, 0xcc9e22d4, 0x252282cd, 0xff3333b1, 0x11824e00, 0x6200ff27, 0xeb089a19, 0x2081838b, 0x21308307, 0x8182ccf8, + 0x82190821, 0x33f72256, 0x22308333, 0x82f628f7, 0xd7f82730, 0xf7ffff0a, 0x0a8366e6, 0x06823082, 0x5982c120, 0x83320021, 0x82cd2028, 0x3d002137, + 0x90821b82, 0x64090d64, 0xb3820a3e, 0x82cc0821, 0x205b849e, 0x20378207, 0x205b86ff, 0x08787fd3, 0x84230021, 0x822d208c, 0xff0e355b, 0xcc4cea01, + 0x999701ff, 0x00ff159a, 0xff68e615, 0x4821eaff, 0xdc227182, 0x0a823c8a, 0x84981921, 0x6d08310f, 0xe6e1ffff, 0xff290566, 0xe2fa6100, 0x1e00ff05, + 0x00238a82, 0x825c0f1e, 0x8315200a, 0xdf152790, 0x2300ff9e, 0x7c826866, 0xff230f83, 0x826220ea, 0xb3122b9f, 0xedffff32, 0xff059042, 0x3082c2fe, + 0xb336ff23, 0x33648233, 0xffce4ca7, 0x295ca700, 0xffffed05, 0x053e0a9e, 0x9958ffff, 0x58226682, 0x0a8232b3, 0x8183f920, 0xceccf922, 0x25068647, + 0xff6666fb, 0x4683f7ff, 0x3233fd26, 0xa7ffff08, 0xe222cf83, 0x29826866, 0x0080f622, 0x2006d043, 0x212482f7, 0x19830200, 0x1382f920, 0x4c070023, + 0x252982cc, 0xff9a99f9, 0x04820500, 0xccfdff26, 0x0900ffcc, 0x02271983, 0x00ffcdcc, 0x829a9908, 0x821d209a, 0x58002319, 0xc082cccc, 0x4c201585, + 0x04251a82, 0x00ff9999, 0x29298307, 0xff333306, 0x9a190600, 0xbd198b08, 0xb22207dc, 0x3d639999, 0xf0ff290c, 0xff8b1ec5, 0xe23aefff, 0x0a76531a, + 0xffff3323, 0x255882f2, 0xcd4ceeff, 0xa318088b, 0xff230dac, 0x83ceccf0, 0x45c6832f, 0xee2107bc, 0xd6c3184c, 0x50942012, 0x1f520c52, 0x00ff220a, + 0x9c461860, 0x20178309, 0x051f63ff, 0x1013f818, 0xff236a8b, 0x189a199f, 0x20077f85, 0x215a82fb, 0xf118caff, 0xff220bf9, 0x52830001, 0x00ffc026, + 0xb6e1fa2a, 0x2a069d61, 0xf80e06eb, 0xc000ff94, 0x821566e6, 0xcff730b0, 0xfcffffe0, 0xffff00e0, 0xff2ac7f7, 0x82c0f9ff, 0x23048209, 0x05434308, + 0x22052357, 0x82dcf8ff, 0x754e1817, 0xb8ed2210, 0x2e3d8252, 0xffae47f2, 0x34f30e00, 0x1100ff8b, 0x8208cc0c, 0x30083006, 0x0300ff20, 0x00ff0020, + 0xff283108, 0x82400600, 0x3d062309, 0x20820870, 0x82cc6c21, 0x48612104, 0x8d255782, 0xff063433, 0x200582ff, 0x84118407, 0x82052004, 0x5238212c, + 0x51210482, 0x05d354ea, 0x19030023, 0x2109839a, 0x3c828b34, 0xae471222, 0x0d275c82, 0xffff52b8, 0x82cc0cf1, 0xf3ee2279, 0x206e8234, 0x21be8aff, + 0xbe87d8ce, 0x8a90c221, 0x83f920be, 0x18be9033, 0x2118344f, 0x9f82d343, 0x25583383, 0x05df5505, 0x82323321, 0x3308217c, 0xe7837183, 0x0d00ff24, + 0xf784e1ba, 0x1200ff24, 0x9f831f45, 0x21300822, 0x31212283, 0x054c4127, 0xf2820020, 0xba828d84, 0x48611127, 0x93eeffff, 0x29e08234, 0x07cccc72, + 0x4c8dffff, 0xf28406cd, 0x9e211682, 0x24f786b8, 0xaec7f9ff, 0x20f284ff, 0x82ac82ff, 0x83a182e0, 0x24e782e0, 0x45f2ffff, 0x24f7841f, 0xbaedffff, + 0x826e82e1, 0x83df20f6, 0xd9ce2122, 0x29056b41, 0x8fc2f9ff, 0x400600ff, 0xbe850800, 0x82b8be21, 0x9a39210d, 0x08208b86, 0x0922be84, 0x4f829a19, + 0x06820020, 0x00213385, 0x06c17d07, 0xd3203885, 0x002df782, 0xff484106, 0xf6680500, 0x2e0800ff, 0x238d8515, 0xa4300800, 0x201d8041, 0x216685df, + 0x8d82f7ff, 0x22063f42, 0x820890c2, 0xcdac21db, 0x7222e087, 0xf18233b3, 0x34b37222, 0xee21fd82, 0x20978299, 0x050c44ee, 0xc346cc20, 0xccf72107, + 0xfc232b82, 0x82ff66e6, 0x82cd20fc, 0x42ff206e, 0xbe852f5e, 0xc385f282, 0x33330822, 0xbe7ee586, 0xfcff2210, 0x059242e0, 0x27059f41, 0xff0543d3, + 0xae470600, 0xbe210d82, 0x24f285b8, 0xecd1f7ff, 0x2189828b, 0x80415ccf, 0x411e200a, 0xe2200880, 0x20058041, 0x212283e0, 0x8041d8ce, 0x74511808, + 0x9eee2108, 0x11314782, 0xff053453, 0xcc4c8dff, 0x7200ff07, 0xff06cccc, 0x211685ff, 0x16824861, 0x16aef922, 0x7f05ec42, 0xff210961, 0x82a88200, + 0x075e426e, 0x5e42e220, 0x421e2008, 0x2021055e, 0x0551438b, 0xc621be99, 0x083f4266, 0x9b82cd20, 0x33b3f830, 0x70fb0e08, 0x191f00ff, 0x7f01ff9a, + 0x476652f8, 0x91f22208, 0x0b0062eb, 0xc0feff22, 0x20056b4a, 0xb04018ee, 0x00ff2912, 0xff85ab11, 0x7ad40000, 0x2305445a, 0x00800d00, 0x12298982, + 0xff080080, 0xec113f01, 0x220c8207, 0x6886ab11, 0x00210543, 0x2341820e, 0x156eedff, 0xec2fb283, 0xffff6666, 0x15b89ef8, 0xffff54fb, 0x8266e660, + 0x51f821f7, 0xf82c7882, 0xffffc3b5, 0xff142efc, 0x67e6f6ff, 0xf622a782, 0xf78266e6, 0xe7f6ff23, 0x21be82f0, 0x1682ecd1, 0xfffce92d, 0xb99e0700, + 0x8ff9ffff, 0x87f7085c, 0x1400283d, 0xffff48a1, 0x8248e1ee, 0x220483d1, 0x82b85e0e, 0x5e1b227b, 0x2d8883b8, 0xff0766e6, 0x6626ffff, 0x8a1a00ff, + 0xaa826c3e, 0x2b826120, 0x8183eb20, 0xb8deee24, 0x28820e08, 0x66e62023, 0x82b18c15, 0xff7b2aac, 0x146e0d00, 0xc51000ff, 0x22b1831f, 0x82eb9112, + 0x82e620e9, 0x053d6044, 0x8286ab21, 0x54ee3e9e, 0xffff087a, 0x0733337c, 0x80ab00ff, 0x9c00ff00, 0xff05ff7f, 0x9a991400, 0x0c1100ff, 0x828c82ce, + 0xf1ff2230, 0x238c829e, 0x48a1e4ff, 0x19212b83, 0x212b889a, 0x2b880080, 0x1f209c83, 0x79412b8e, 0x27388207, 0x1ee0ffff, 0xf1ffffb8, 0xeb20e483, + 0x0022bd82, 0xd9821e11, 0x8354ff21, 0x599b2672, 0xffff0598, 0x05c9657d, 0x51212b9f, 0x822b89ec, 0x059941bc, 0x91f2ff28, 0xefffffec, 0xe782e13a, + 0x82edff21, 0xffff23f3, 0x1a8568e6, 0x230ad141, 0xcb01ff0e, 0x01256f82, 0x150a9778, 0x237a84ff, 0x9a1971ff, 0xac224e82, 0xd286cc8c, 0xfe841085, + 0xf5eeff23, 0x29fe85c2, 0x68660e00, 0x1c00ff8b, 0x14423233, 0x5e1b2109, 0xe022cd82, 0x8b419a19, 0x94fb220f, 0x275b828b, 0xffa4f03f, 0x900260ff, + 0xf02b5b82, 0xffff00c0, 0x8b4821f3, 0x82e8ffff, 0x0f00227c, 0x410f8540, 0x472016f9, 0x5e215082, 0x226d82fa, 0x41765e1b, 0x67250af9, 0x8f1a00ff, + 0x11f9415c, 0xf730fb26, 0x157df7fd, 0x4c303482, 0xf7ffffcc, 0x00ff3333, 0xff34b308, 0x0080f0ff, 0xef207082, 0x2005647c, 0x831b84ef, 0x20168204, + 0x054e58ff, 0x9a19f82a, 0xe0feff08, 0x44fbae07, 0xf125a482, 0xffff142e, 0x28cd82f6, 0x3373edff, 0x99ffffff, 0x2142829a, 0x4c8229dc, 0x08008022, + 0xdb210a82, 0x820a8464, 0x7d9f2223, 0x269c829b, 0x08666611, 0x8307f4f7, 0x285c3009, 0x600900ff, 0x1000ff83, 0x00ff9002, 0x849c240f, 0x82082029, + 0xd723210a, 0x7d260a82, 0x1200ff70, 0x5382cd8c, 0x8268a621, 0xecd121a5, 0xf3214382, 0x34d98232, 0xff52f81f, 0x3e0a50ff, 0x70fb0e05, 0x01ffa4f7, + 0x1566e680, 0x73e7186b, 0x0667700d, 0xd663e623, 0x09a04e08, 0x0a235d18, 0x8f821a2b, 0xffab088b, 0x3433feff, 0x09804d05, 0x15207082, 0x2812a44e, + 0x0080eaff, 0x631600ff, 0x062b78d6, 0x8b54fb22, 0xe5226f96, 0x6f86707d, 0x9a99e423, 0x836f86ff, 0x826f853c, 0x0aec4da3, 0x24068b77, 0x0890821a, + 0x08104ff7, 0xb94c6b8f, 0x15d42b05, 0xe600ffff, 0xff8b0766, 0x794edcff, 0xe3ff2307, 0x0e849a59, 0xfb088b24, 0x09850694, 0x1482ff20, 0x4eff9921, + 0xff210a7e, 0x052d4f00, 0xde180020, 0x36821429, 0xb8180020, 0x0e2b14ed, 0x823400ff, 0x0700ff8f, 0x43156666, 0x8e2906dc, 0xff0566e6, 0x67665300, + 0x05ff4207, 0xe38e002e, 0xffff05d7, 0xffb85eeb, 0x48211100, 0x4307a443, 0xc14309ed, 0x1f00220b, 0x272182e1, 0xff9899f1, 0x48a11400, 0x19223082, + 0x9a82089a, 0x8b71fd2a, 0xff54f715, 0x9a199f00, 0x0f315b82, 0x00ff0040, 0x8bb8de0c, 0x801700ff, 0xf0ffff00, 0x220f84c0, 0x84fb08b9, 0x889b2022, + 0xb81e216d, 0xb92c6d83, 0xa1f1ffff, 0xffff8b06, 0x0888a1e4, 0x2805a945, 0x020000ff, 0xe6ffff8f, 0x44628261, 0x71840550, 0x859a9921, 0xf80e2871, + 0x5f01ff94, 0x451552f8, 0xff240cd7, 0xff86abf1, 0x2b070544, 0xff088be0, 0x6666edff, 0xeeffffff, 0x45074362, 0xf72109d7, 0x23fc8617, 0x008063ff, + 0x28838e83, 0x82e6ee21, 0x05ce432d, 0x9008eb43, 0x20918228, 0x822885ff, 0x171444bc, 0x451f0021, 0xff2306bd, 0x829e1400, 0xe1ee23e3, 0x7d410848, + 0x64ff3005, 0xff05299c, 0x1fc58200, 0x00ff8b07, 0x45b85e1b, 0x2b9e09e9, 0xdc821120, 0x540e0023, 0x08cf457a, 0xe1822020, 0x99120023, 0x07cf459a, + 0x46cc4c21, 0x0e260bf1, 0x01ff70fb, 0x1d85191f, 0x63631520, 0x6e0d2307, 0x776bff14, 0x0c2c460a, 0x4618ff20, 0x54221191, 0x50418b7a, 0x821b8206, + 0x3aef220a, 0x06a041e0, 0xed200c82, 0x0f224b83, 0x21823233, 0xff008026, 0xcecc1000, 0xff289082, 0xfff56815, 0x00800600, 0x210a0e42, 0x1e82a007, + 0x9e6f0626, 0xce0300ff, 0x09228982, 0xfa821018, 0x0a170923, 0x30068308, 0xffff1018, 0xffe530fc, 0x04160900, 0x61f8ffff, 0x213d8207, 0x2942a470, + 0x429a2006, 0x12210729, 0x329742e1, 0xff2f0e37, 0x8f023000, 0xe68000ff, 0x01ff1566, 0x069a195f, 0x9e2900ff, 0x267682b8, 0xffb8de15, 0x82a13100, + 0x82e32054, 0x1e003059, 0xff0800c0, 0x66e650ff, 0x19c000ff, 0x4178059a, 0xdf29068a, 0x788b0040, 0x61ebffff, 0x821d8348, 0x3fff2349, 0x92821e05, + 0xff223383, 0x2d8266e1, 0x7ddf1527, 0x19cfffff, 0x2157829a, 0xfe82f49d, 0x175f0135, 0xbfffff0a, 0xff159a19, 0xf6e8a0fe, 0xe5ffff06, 0x7c8b299c, + 0xea22069e, 0x0a82f668, 0x289ce528, 0xffffff08, 0x1b82e0fd, 0xff7c9426, 0x2a991500, 0x00231f85, 0x8466661a, 0x22a78442, 0x83d6631a, 0x829920a7, + 0x9915225a, 0x820a829a, 0x83082010, 0xf6682106, 0x4c219182, 0x2f3883cc, 0xe4ffff9a, 0x088b34b3, 0xf770fb0e, 0xff156b74, 0x4912324b, 0xfb2306b1, + 0x6154f754, 0xdb64066b, 0x08eb630a, 0x84f70821, 0x180f881f, 0x2112b35a, 0xca64800c, 0x825a1805, 0x9e562d12, 0x56ffffb8, 0xff0500a0, 0x6666a900, + 0x99210a82, 0x9a0a829a, 0x07804d30, 0x134bb082, 0x20c8820d, 0x4bc795eb, 0xff2006fa, 0x0c263e19, 0x0e715b18, 0x866ba922, 0x60208182, 0xff238782, + 0x827a9456, 0xb85e210a, 0xb162f39b, 0x23ee9009, 0x54fb54f7, 0xfb20c29b, 0xff281f84, 0xff1ec5f9, 0xe2baf9ff, 0xcc20c783, 0x4b056365, 0x0e2405db, + 0x1554f78b, 0x44f84d18, 0x16544e18, 0xfb94f723, 0x0cc77404, 0xc4180020, 0xcb220960, 0xa318cb07, 0x1a8a0cf9, 0x0d209282, 0x82075d5c, 0xff332a16, + 0x34b3f2ff, 0x064b088b, 0x0c4e18cb, 0x181a8412, 0x180b1b9a, 0x230aad43, 0x064b074b, 0x43181a8e, 0xcb221e63, 0xa2584b06, 0x19431805, 0x612d4111, + 0x18a33c21, 0x202f1144, 0x2e424144, 0x0644fb22, 0x4326c6e1, 0xe62f00ff, 0x05821566, 0x5c9a1928, 0xd0ffff05, 0x048266e6, 0x829a1921, 0x19f6200a, + 0x2119a2d6, 0x25826609, 0xceccf526, 0x330f00ff, 0x07da7f18, 0x330a002b, 0xffba0832, 0x34332e00, 0x19548405, 0x84400c02, 0x824b8245, 0x18ba2051, + 0x281bb0b2, 0x80f7ffff, 0x0900ff00, 0x68d7194c, 0x19d02213, 0x21d5849a, 0xe3845c05, 0x2c9ad782, 0x8b21f298, 0x608a4107, 0x7301ff2f, 0x00ffcccc, + 0x1533332c, 0xe60a00ff, 0x24048368, 0x00ff8b67, 0x23158211, 0x9819f5ff, 0x66210f83, 0x058d7208, 0xff241f84, 0x8b3433ee, 0x1f830f85, 0x93201a82, + 0x93222a83, 0xe482cecc, 0xcdccd322, 0x0a824b84, 0x9919f522, 0xff203b84, 0x99203088, 0x4b863584, 0x99203b82, 0x4c824682, 0xf5262586, 0xcb089a19, + 0x7f84054b, 0x79822883, 0x89828382, 0x67e60a22, 0x08259984, 0xff7f00ff, 0x250484ff, 0x94f70e05, 0x521854f8, 0xff230ca7, 0x8266668d, 0x9972234f, + 0x0685089a, 0x5600ff21, 0x002008da, 0x10a75218, 0x11d55218, 0x08ec5218, 0x3205a744, 0x24fc8b08, 0x7d8b7915, 0x089d8b99, 0x00ff9d8b, 0x829a190d, + 0x551220ce, 0x112205e9, 0x97829a19, 0x66e60e2e, 0x08798b7d, 0xffff798b, 0x7d9a19f1, 0x1d85e782, 0x9a194524, 0x9b8222f7, 0xe6d22908, 0x89056f66, + 0x807e8b07, 0x088b7e80, 0x96808b7e, 0x9b08988b, 0x8f938b07, 0x08909393, 0x9205adc4, 0x8b928f8f, 0x978b0893, 0x9a2dee83, 0x088b7f95, 0xe6ccffff, + 0xffff0666, 0x276083f3, 0x66e6f6ff, 0x087f8b81, 0x8b26408d, 0xffaaaab2, 0x20822600, 0x00ff083c, 0x069a1933, 0xcc2800ff, 0x6caa8bcc, 0x8b08648b, + 0xff747e73, 0x9a19eaff, 0x2041087e, 0x14fb2162, 0x23088c49, 0xff7a540e, 0x210e9961, 0x11837c54, 0x16848620, 0x1806976a, 0x670b594c, 0xc35e1369, + 0xfbb3300d, 0x063b1594, 0xccf2ffff, 0xffff8bcd, 0x183333f5, 0x7b123249, 0x0a22050f, 0xbe7334b3, 0x9b082505, 0x8307cb06, 0x180e6562, 0x7a086c96, + 0xcc2108c2, 0x06fe73cd, 0x33330d26, 0x06ab088b, 0x7a0dfb73, 0x332208c2, 0x1a979b07, 0x82059e7c, 0x184c2095, 0x220c77aa, 0x4774f70e, 0x1120052d, + 0x68120062, 0x5f620e36, 0xffff211e, 0x09445118, 0x220a2b41, 0x6094f7ab, 0xf6500e3b, 0xa6f5330a, 0x00ff0766, 0xff34b35d, 0x7c14f2ff, 0xb5ffffd5, + 0xdb8252f8, 0xff66e627, 0xcc4ca2ff, 0x21f48208, 0xce566666, 0x2bd9180c, 0x11f85f0f, 0x9922e282, 0x4f82069a, 0x849a1921, 0x41412144, 0x10840684, + 0x1c840820, 0xa9180720, 0xba18095e, 0xc0960cb4, 0x07208484, 0xcd204483, 0xa4829a86, 0xf222aa82, 0xba847b14, 0xa6205483, 0x1980aa18, 0x4100ff21, + 0x5420055a, 0x0e212d82, 0x2342824c, 0x8b85ab11, 0x5920d983, 0x0023a582, 0x8485eb0d, 0x00ff2444, 0x86ae074a, 0xb35d2204, 0x21688233, 0x248584eb, + 0x17e46018, 0x6b078b2d, 0x666bfeff, 0x00ff1566, 0x849a9914, 0x63b32025, 0xc241115d, 0x07bc630e, 0xebffff2a, 0xff076666, 0xcc4c3a00, 0x24068949, + 0xffcecc2d, 0x22048400, 0x8400800c, 0x82d78218, 0x18062024, 0x430bc255, 0xa7820f02, 0x07627518, 0xb2826885, 0x33828c82, 0x4486f320, 0xd2ffff24, + 0x58853233, 0x83c5ff21, 0x855d829f, 0x30854158, 0x07215882, 0x204482ff, 0x05874a33, 0x09825882, 0xff205d83, 0x18826c83, 0x7d873420, 0x2f190020, + 0xb3200b2e, 0x8211b642, 0xca821837, 0x20e5840b, 0x83988200, 0x8334205d, 0x86cd20ac, 0x4c3a21b6, 0x5d820982, 0x7b5c0820, 0xff300861, 0x008063fe, + 0x336f00ff, 0xffff1534, 0xff66a6e9, 0x32b3e0ff, 0xd9f2ffff, 0xd9ffff99, 0xff8b9a99, 0x0080d6ff, 0xff218b08, 0x9a195500, 0x6a00ff35, 0x3305b945, + 0x8b008029, 0x662600ff, 0x0d00ff66, 0x00ff9a19, 0xffce4c1f, 0x2c052674, 0xcc4cf4fe, 0xb30b01ff, 0x01ff0534, 0x245a825c, 0xcccc90ff, 0x0ed25c15, + 0x5a825484, 0x6a836082, 0x74839a20, 0x7e843320, 0x3a840820, 0x4483ff20, 0x50840520, 0x64845a86, 0x48826e82, 0x082b7a82, 0x2f0e078b, 0x19bf01ff, + 0x8254f79a, 0xeeff215b, 0xdc197282, 0x0e820a48, 0xff088b2f, 0xcc4ccdfe, 0x6900ff06, 0xffff6766, 0x209d4c96, 0xf922f483, 0x9d4c00c0, 0x82108410, + 0xd1f722aa, 0x0f1157eb, 0xf734fb22, 0x9c4ce482, 0x84f72019, 0x365f4d1f, 0x85ab9622, 0xa027b682, 0x01ff0500, 0x4434b332, 0x0d23088b, 0x44ff6666, + 0x6a180a8b, 0x00270721, 0x156666a9, 0x83fb34fb, 0xccf9218f, 0x18097c58, 0x18295169, 0x251b0569, 0x00ff846b, 0x8a826069, 0x33cdfe22, 0xff208a82, + 0x2007056e, 0x826218ee, 0x09fd690b, 0x16841220, 0x4400ff21, 0x01240570, 0x06cccc32, 0x9921ca82, 0x2144829a, 0x9c4d6666, 0x2cdb8437, 0x34730c00, + 0x73f3ffff, 0xffff8b34, 0x83e683eb, 0x82ff20b5, 0x0e082604, 0x01ff30fb, 0x25638376, 0x156666c9, 0x0441ffff, 0x566a1835, 0xcdfe2109, 0x22059456, + 0x565c4fee, 0xff23054d, 0x560a97f2, 0xef220868, 0x8182e13a, 0xb9deef27, 0x660d00ff, 0x26f98566, 0x3201ff08, 0x820734b3, 0x48a121e9, 0xb3210482, + 0x83e98632, 0x0b8f719e, 0x89440020, 0x186f4105, 0x201f3542, 0x060941f7, 0x41527821, 0x89201f09, 0x5a151342, 0xf7220e90, 0xde42cdcc, 0x1a4a4f35, + 0x6900ff30, 0xffffb85e, 0x05349396, 0xcc3201ff, 0x561807cc, 0x5426082a, 0x0d00ff7b, 0x9a58f668, 0xc5102208, 0x271b821f, 0xff472110, 0x0a97f2ff, + 0x26059577, 0xcdfeff08, 0x18073433, 0x2008276b, 0x06954f66, 0x75054943, 0xff200949, 0x230e6475, 0x34f3ffff, 0x36101742, 0xb3f701ff, 0xdd00ff34, + 0xfb15cdcc, 0x68ffff44, 0xff0567e6, 0x829ef0ff, 0x82f2209d, 0xe7ff2817, 0x00ffa4b0, 0x8246c10a, 0x14240884, 0xff087cb4, 0x3c0a5700, 0x64ffff07, + 0xffffd6e3, 0xffceccfd, 0xf628bdff, 0x80d9ffff, 0x2d00ff00, 0x25fb0b57, 0x05262182, 0xfffff007, 0x1682e8ef, 0x1b8fec22, 0x87217382, 0x2bbb82ae, + 0x00ff9959, 0x08a4f009, 0x40d4ffff, 0x1f252b82, 0xffffead1, 0x22e783d8, 0x82cecc3c, 0x803d235b, 0x06820800, 0x82339821, 0x667f318a, 0x2000ff67, + 0x00ff3233, 0xff9a99a0, 0x66e60100, 0x4f235482, 0x8207e2fa, 0xab142720, 0x1800ff84, 0x9382ae47, 0xff3eca24, 0x41820f00, 0xa782ff20, 0x84f70821, + 0x642408ba, 0x0b00ff05, 0xffff281c, 0x8b5e8ff5, 0xcceeffff, 0xf4ffffcc, 0xffff68e6, 0x086766f6, 0x14f72f0e, 0x2b1534f8, 0x770c7e78, 0x2b200ad9, + 0x22098275, 0x83ff5c4f, 0x00ff2518, 0x8ba4b011, 0x21797c82, 0x0af07809, 0x94055150, 0x06cd411a, 0xb3f1ff24, 0x3183ff33, 0x2305c048, 0x8bb4f708, + 0x8a7a7e99, 0x507c8d08, 0xee200621, 0x49851582, 0xa4b0f122, 0xeb20979d, 0x172b5718, 0xfcb4fb24, 0xd5501514, 0x79b68206, 0x9e8209c1, 0x825c4f21, + 0x79ff20e7, 0x174109d8, 0x7aeb2023, 0x19410c3b, 0x21fe980a, 0x6a8515eb, 0x096c5a18, 0x0820f585, 0x94053951, 0x1617417e, 0x5d187c98, 0x0e25184e, + 0xf714f72f, 0x68804114, 0x8234b321, 0x18b320e5, 0x410c7545, 0x7e421cff, 0x42342054, 0xcc23087e, 0x822b088b, 0x183641fd, 0x2108b341, 0x3387a4b0, + 0x535c4f21, 0x2e420804, 0xcc4c2130, 0x2205e346, 0x82b3f1ff, 0xb3112983, 0xfb088b34, 0x1534f754, 0x420bca4b, 0xff410a63, 0x0fc76c11, 0x8406fc42, + 0xa4b0234d, 0xc898088b, 0x430bfe42, 0x0e230c7d, 0x8224f82f, 0xf4fb2181, 0x230c0044, 0xec510e00, 0xa321fb84, 0x85068508, 0x0e0023fd, 0x6643ce4c, + 0x82f72006, 0x43002030, 0x5c4809e6, 0x604f2007, 0x4f220523, 0xe384ff5d, 0xaef1ff23, 0x21dc8314, 0x2f4f8bcc, 0xfb732162, 0x2605966f, 0x00ff3433, + 0x83cdcc0a, 0xffcc2704, 0x33330d00, 0x0683088b, 0xc9823420, 0x4ecc0a21, 0x5e4e054e, 0xfb082305, 0x684e0714, 0x00402408, 0x83f5ffff, 0x02a91804, + 0x14f7261b, 0x8cfba307, 0x21d28215, 0x3982d7a3, 0x85ebf127, 0x140e00ff, 0x2359827a, 0x082a5c11, 0x28200684, 0x11211182, 0x260482ec, 0x00ff7c14, + 0x83b85e11, 0x8506837c, 0xf1ff2316, 0x388286eb, 0xd6a3ee24, 0x6f82ff08, 0x4982c220, 0x7df6a827, 0xe6f1ffff, 0x340a8266, 0x088b9a99, 0xf82cf70e, + 0x00ff1554, 0x06333302, 0xe61f00ff, 0x3d558267, 0xff99991d, 0x0a17efff, 0x331000ff, 0xe4ffff33, 0xff08c275, 0x9a191800, 0xfdd6ffff, 0x0a850572, + 0x02290023, 0x2c0a828e, 0xff323310, 0x3e8a1b00, 0x991d00ff, 0x212f829a, 0x4483f6e8, 0x85836620, 0x34330222, 0x30205182, 0xff236482, 0x82662700, + 0x83d8206f, 0xcfff230a, 0xb9826666, 0x82f1ff21, 0xfcff2b2e, 0xffff0080, 0xffcc4cf3, 0x9083f9ff, 0x9a19f322, 0x29226882, 0x484a9a99, 0x830e2008, + 0x0913781b, 0x83074b21, 0x6f4c20cc, 0xfc21119c, 0x0e2a7954, 0x20089c6f, 0x09fb4dcb, 0x2005634e, 0x07f249cc, 0x68840020, 0xdcf9ff26, 0x0c00ff29, + 0xfc227e83, 0x09823d8a, 0x8b34b325, 0x840e00ff, 0x820020a4, 0x20bb83bc, 0x19c08567, 0x20078e15, 0x26b58326, 0x155238bb, 0x82f8ffff, 0x0c002bd7, + 0xffffb8de, 0xff3433f2, 0xfe820700, 0x19f1ff23, 0x23fe8299, 0xcdccfdff, 0xe9229382, 0xb28366e6, 0xff9a1926, 0x0a17eeff, 0xe9230a82, 0x8308f6e8, + 0x18708206, 0x21117398, 0x33834c49, 0x3333dd2b, 0x383b00ff, 0x00ff0552, 0x236a82a9, 0xaec71400, 0xfd226a82, 0x4f82cccc, 0x9a19f122, 0x6c833d82, + 0x17f8ff23, 0x2780850a, 0x4821f3ff, 0xddffff08, 0xff238182, 0x82aec7c4, 0x4c492136, 0x00212b82, 0x842b8316, 0x82048364, 0x821082d5, 0x1600217b, + 0xee203883, 0x00219282, 0x83af8311, 0x8b082fa2, 0xfbdcfb07, 0x54f71584, 0x0774fb06, 0x546d24fb, 0x1d4f180e, 0x44f72a08, 0xfb94f707, 0x74f71574, + 0x202a8307, 0x5e4f1844, 0x28418217, 0xff94f80e, 0x9a991a01, 0x20af8215, 0x2d6c8280, 0x34f3b9ff, 0x9994ffff, 0x96ffff98, 0xae8400c0, 0xffff0825, + 0x82c2f5eb, 0xe00f25c4, 0x35eaffff, 0xfb280982, 0xffff5e7a, 0x8bd823e9, 0xbf201a82, 0xc331ea84, 0x00ff33b3, 0xff908224, 0x0080e1ff, 0xf53900ff, + 0x341a82c2, 0xffb8dec9, 0xec11ceff, 0x6bf1ffff, 0xc6ffff85, 0xffff14ee, 0x225483ff, 0x8266e6fe, 0x5efd2c1e, 0xf4ffffb7, 0xffff70fd, 0x826626f6, + 0x9a99265e, 0x26f5ffff, 0x22548366, 0x82f027fe, 0x1dfe2b8f, 0x0000fff4, 0xfffffc37, 0x548220fe, 0x00700022, 0xf3273582, 0x00ff291c, 0x82161903, + 0xcd0c2630, 0xfb0c00ff, 0x210e8264, 0x09820a17, 0x0848e12a, 0x990900ff, 0x2700ff17, 0x502c8383, 0x00ff3cdf, 0xff66e6ba, 0x7ad4f400, 0x00235482, + 0x82fed408, 0xdcfb267f, 0x330700ff, 0x18048334, 0x230e7548, 0xccccf8ff, 0xff241684, 0x3433f7ff, 0xff233182, 0x829a9994, 0x66b22186, 0xdd209d82, + 0xc9240483, 0x08623d4a, 0x31359282, 0x0a00ff83, 0x00ffecd1, 0xff710c01, 0x1e050b00, 0x4b0200ff, 0x21098203, 0x1e82c335, 0x52780d2b, 0xcf4100ff, + 0x3400ff5d, 0x22238291, 0x82a43035, 0x825c200e, 0x330f22b5, 0x2b1e8232, 0xff7a541c, 0xde8f0600, 0x591b00ff, 0x2708f182, 0xff7673ff, 0x00401900, + 0xfef9ffff, 0xffc3080e, 0x14aef2ff, 0x333e00ff, 0x1400ff32, 0x00ff64bb, 0xff9c191f, 0xf8d33500, 0x05223982, 0xe082fca9, 0xfff8d326, 0x225b0e00, + 0xb02bca82, 0x0400ff22, 0xffffd8a3, 0x82e2a7f5, 0x9510261e, 0xdbffffc2, 0x27f5822c, 0xffcc4c09, 0x2adcd2ff, 0xd430bc82, 0x0e080080, 0x4301ff2f, + 0x01ff0080, 0x1500c08c, 0x2205fb5b, 0x82c0ecff, 0x33ed2271, 0x830e8234, 0x83ef2009, 0xa6eb3fde, 0xffff0866, 0xff34b3e4, 0xe27a2500, 0x19deffff, + 0x2600ff99, 0xffffb81e, 0xffcdccd9, 0x4a822300, 0x9dffff22, 0xa4252e83, 0xffff48e1, 0x22b483ba, 0x82b81e89, 0x66b82365, 0x06820866, 0x3a838020, + 0x3333642d, 0xe698ffff, 0x7b00ff66, 0x828bcdcc, 0xcc7b2697, 0x00ff8bcc, 0x236b8264, 0x9a196700, 0x7f220a82, 0x2d82cc4c, 0x33350027, 0x00ff5734, + 0x2829826d, 0x0080b7ff, 0x404300ff, 0x277e8200, 0xff9a99ec, 0x9a59abfe, 0xea20a882, 0xf020c683, 0xe5261f83, 0xff826766, 0xb243e3ff, 0xdeb72105, + 0xc5277283, 0x00ffe23a, 0x82e2ba2f, 0x784d224f, 0x2f4f8352, 0xff48a126, 0x713d1800, 0x022200ff, 0x3000ff8f, 0x3a285383, 0x9208f528, 0x5b00ff83, + 0x8a23b083, 0x838b9a99, 0x833a2090, 0xe1422b28, 0x00ff0548, 0xff002004, 0xc882f9ff, 0xbd030023, 0x260982f4, 0x00ffe13a, 0x827c5f03, 0xb99e2109, + 0x1b2aba82, 0xfffff668, 0xffead1cb, 0x4d82f4ff, 0x82bdff21, 0xceff21c3, 0xff29e482, 0x080080dd, 0x01ffaf0e, 0x22ad8217, 0x82991f01, 0x020027ad, + 0x00ffcccc, 0x04824c00, 0xcecc0222, 0x19220982, 0x1383ff9a, 0xc0088b25, 0x19ffb68b, 0x180c8aeb, 0x20137ecd, 0x202c838b, 0x833688cd, 0x204a8509, + 0x258682cc, 0xffcd4c09, 0x8182fbff, 0xcc0a0022, 0xfc200982, 0x0b225a83, 0xb6180080, 0xbc180d7e, 0x1e820db1, 0x84ffff21, 0x820a2028, 0x2e3c8597, + 0x08ce4c09, 0x00ff5df7, 0x15cccc2f, 0x822e00ff, 0xd4ff21a5, 0x0021bf82, 0x2669821f, 0x66e6ccff, 0x830e00ff, 0x66db222b, 0x20738267, 0x26148303, + 0x8b9919f8, 0x83f7ffff, 0x83fc20f6, 0x19f826f6, 0xffff089a, 0x200f83f1, 0x201f83dc, 0x831483e0, 0xd1ff2839, 0xffff3233, 0x8234b3d3, 0x82d0201e, + 0xd4ff2149, 0xbf200f83, 0xdb202383, 0xaf202d83, 0x22055043, 0x823333af, 0x82bf204f, 0x240021ce, 0xd0276a83, 0x00ff85eb, 0x82cecc2b, 0x33d12535, + 0x2c00ff33, 0xb8245484, 0x3300ff52, 0xff26e382, 0xfffa1ef1, 0x54842300, 0xf0b7fc2b, 0xe60700ff, 0x00ff8b66, 0x23398208, 0x10480300, 0xa9830f83, + 0x06e10e2c, 0x992400ff, 0x1f00ff99, 0x3985ae47, 0xcd20dc82, 0x66215882, 0x22c88266, 0x827b142f, 0x90c2250a, 0xb34000ff, 0x24256282, 0x00ff0ad7, + 0x05994250, 0xcccc5022, 0x40204f82, 0xdb25c483, 0x00fff628, 0x3574832f, 0x08703dd4, 0xffff078b, 0xff66663f, 0x9a990000, 0xb0ffff15, 0xb6830080, + 0xff008024, 0x0a84bfff, 0x08201082, 0x06821182, 0x4000ff22, 0x5f181686, 0x191a1252, 0x3f8311b2, 0x3c823286, 0x0e088b26, 0x9600ffef, 0x01249682, + 0x15e23a63, 0xb682ff83, 0x50822220, 0xcc380022, 0x1a250982, 0x00ff1e45, 0x05aa4844, 0x9822ab91, 0xab83ffff, 0xec82ff20, 0x0a82d020, 0x2133c941, + 0x448299f2, 0x32b3df2a, 0x19e5ffff, 0xd2ffff9c, 0x22087982, 0x6466d8ff, 0x66d7ffff, 0x00ff0866, 0xff343369, 0x9a99adff, 0x0a00ff05, 0xffff6866, + 0xffceccf7, 0x82e60100, 0xe6f0221f, 0x820e8366, 0x99f52377, 0x0a83089a, 0xffffcc23, 0x204d83f5, 0x201e83f0, 0x334d83fe, 0xff9c99f5, 0x32330800, + 0xaffdff08, 0x01fff8fe, 0x058e02d0, 0x91212482, 0x2b158268, 0xffff162e, 0xffc72bfe, 0x7a140f00, 0x2d210e82, 0x21618250, 0x72821a6f, 0x912d0822, + 0x6e210a82, 0x20198398, 0x216c827b, 0x0e823ad4, 0x82a47021, 0xb0d22161, 0x6f261e82, 0xffffd7e3, 0x488257a8, 0x6648002d, 0xc7ffff67, 0xff151e45, + 0x824c5a00, 0x33b9227d, 0x20a78233, 0x21b28204, 0xc7820800, 0x6602002f, 0x0900ff66, 0xff8b9a99, 0x99190b00, 0x22068208, 0x439a990a, 0xff201413, + 0x200dbb43, 0x09b7438c, 0x568b6022, 0xff213882, 0x2a4a82f1, 0x9a19fdff, 0xffff857e, 0x823433f4, 0x82272087, 0xe1ff2361, 0x7182cccc, 0x9a190b26, + 0x661400ff, 0x0620d582, 0x00238682, 0x82666617, 0xcc19226a, 0x213882cc, 0x71834e00, 0x2b82bf20, 0x83410021, 0x80b03242, 0xff088b00, 0x34b3daff, + 0xddffff8b, 0xffff66e6, 0x200483f0, 0x222082e6, 0x83b3e8ff, 0x82602057, 0xb5fe260f, 0xff150080, 0x102b43ff, 0x2b431a82, 0x52382107, 0x20122b43, + 0x082b43b8, 0x1e82b820, 0x210b2b43, 0x2b43ae47, 0x8a092507, 0x1600ff3e, 0x10214983, 0x2209824a, 0x8299991d, 0xcdcc240e, 0x841d00ff, 0x4f5e2b7e, + 0xb5ffff5c, 0xff0533b3, 0xd682ffff, 0x66f9ff23, 0x83098267, 0x4cf9249e, 0x82858bcc, 0xafff21d2, 0xf342d282, 0x83122011, 0x110021d2, 0x03205883, + 0x10202083, 0x002eee82, 0x08008006, 0x334900ff, 0xc6ffff34, 0x53826666, 0x32b3db25, 0x82ecffff, 0xd5ff211a, 0x2f06484a, 0x33d0ffff, 0x8b088b34, + 0x01ff0e06, 0xaacc4cfa, 0x2a24f782, 0x00f834b3, 0xef362c82, 0xffa786ab, 0x3ccad6ff, 0xefffff8b, 0x086f5c8f, 0xcc2affff, 0x1a84fccd, 0xff0b9724, + 0xa082e4ff, 0x70140026, 0xdcffff62, 0x00374c82, 0x8b19e420, 0xaa01ff08, 0xff069a99, 0x90c22000, 0x1400ff8b, 0x82aefe7f, 0x34b32a3b, 0xfeff08a7, + 0xf734b3ed, 0xeac4188d, 0x0d8a5a17, 0x080d6c18, 0x2214094c, 0x8266a6f3, 0x83ff2068, 0xffff2406, 0x5b3473f3, 0x094c0b1f, 0xffaf2b63, 0xcc4ce201, + 0xff1594f7, 0xa9832200, 0x803b0032, 0x688b6e00, 0xff678b08, 0x0080c4ff, 0xddffff6f, 0x34057773, 0x0668668b, 0x809bffff, 0x50ffff00, 0xff059a19, + 0xcc4cfaff, 0x059f69ff, 0x6666f526, 0xccf9ffff, 0xf4200e82, 0x22059242, 0x82cdccc7, 0x66f5262b, 0xffff8b67, 0x222682f8, 0x82330a00, 0xe60222d8, + 0x2bdd8267, 0xff083233, 0x99193100, 0x99ab00ff, 0x99224683, 0x2b829a19, 0xcdccd422, 0x2d07d641, 0x87e1fafc, 0x42fbffff, 0xfdffff8f, 0x67829a99, + 0x8bc2f529, 0xd6ffff08, 0x8206ae07, 0x0641214d, 0xf9285382, 0x00ff4cb7, 0x8bcc4c06, 0x82057a72, 0x82002006, 0x00002d82, 0x00ff8a2e, 0xffce4c01, + 0xa65b0000, 0xcc200983, 0x1f256a82, 0x00ffd075, 0x22b1846e, 0x87308ae0, 0xa4ff220a, 0x2420845a, 0xd1ffffff, 0x82348476, 0x48012044, 0x07210549, + 0x22ac82b3, 0x84b44806, 0x00ff2462, 0x82fabe07, 0x2900297f, 0xff0652f8, 0x3e0a0500, 0x04222882, 0x9c8571bd, 0x05030024, 0x6482871f, 0x33332b22, + 0x0023be86, 0x8266e666, 0x83ce20a7, 0x20e085eb, 0x22eb83fd, 0x82e03a0a, 0x27588349, 0xff862b0a, 0x99990a00, 0x38225383, 0x53823333, 0x00800b22, + 0x22074e44, 0x82d4d8f9, 0x23268263, 0x7408f6ff, 0x643c5782, 0xffff0080, 0x05b81e50, 0x997400ff, 0x2f0e0698, 0x34f834f7, 0xf7076b15, 0x07ab0614, + 0x08a55218, 0xffcc4c22, 0x72058967, 0x276711b6, 0x54ee2605, 0x076b087a, 0xb99618bb, 0x075b2517, 0xbb0654fc, 0x17365218, 0x6a8cbb20, 0x6a88cd20, + 0xc1833320, 0x5c0b565a, 0xfb2908c4, 0x1534fb34, 0xfb0654f8, 0x182a4ca4, 0x6c4cf420, 0x07a42518, 0x1504fbcb, 0x1a062748, 0x752f8dd9, 0x6b2011a3, + 0x01766882, 0x150f190a, 0x076b2409, 0x898b14f7, 0xcade1867, 0x7422190d, 0x8a211918, 0x76ff2008, 0x67840e0b, 0x82333321, 0x821883b7, 0x85cc201d, + 0x820820c2, 0xbb242167, 0x17591519, 0x88076b21, 0x183320e8, 0x850c17e7, 0x2b591880, 0x0a8a7607, 0x1519808b, 0xfb230e59, 0x4144fba4, 0xd0866538, + 0xd089ed94, 0x4dff3321, 0x08220503, 0xa05fcdcc, 0x145b7705, 0x211a5141, 0x671804f7, 0x00210895, 0x411f4107, 0x0e3be818, 0x3c09a041, 0xa801ff0e, + 0x35f79a19, 0xf0ffff15, 0x00ffb8de, 0xffb81e0f, 0xae07e7ff, 0x4ef5ffff, 0x08cf8256, 0xa09aea22, 0xcfffff08, 0x5b0752f8, 0x49ffff06, 0x00ff9a99, + 0x053433f3, 0xffff9385, 0xff0080f6, 0xcccc0400, 0xe6212a82, 0x069f7666, 0x825c4f21, 0xb0f12333, 0x4818ffa4, 0xcc200fd8, 0x8305e152, 0x06e15216, + 0xff06db2d, 0x6666b600, 0xcc0cffff, 0x829105cc, 0x68e624a0, 0x820900ff, 0xfbff2253, 0x202d824c, 0x0520620a, 0x52f83f22, 0xd0237782, 0x82075c0f, + 0x9cea2758, 0x1900ff28, 0x71822adc, 0x82204521, 0x462121ab, 0x0824b084, 0x194f00ff, 0x4f239882, 0x8205e2fa, 0x14632142, 0x12210483, 0x211b828b, + 0xa682f833, 0x82ec9c21, 0x4861270f, 0xb0ffff08, 0x2a823e0a, 0x0570fd2d, 0xe6a7ffff, 0x1513f766, 0x842f00ff, 0x84df835f, 0x8229205f, 0xb8de215f, + 0x4c215f82, 0x21b082cd, 0x5f94e23a, 0x4f821220, 0xff1a6422, 0x7c200082, 0x32211f82, 0x216382f0, 0x63881c9d, 0x8266e621, 0x41898363, 0xe6220a50, + 0x5382d823, 0x83604521, 0xe89b2163, 0xd0298982, 0xff07ea11, 0xdaebc0ff, 0x21178206, 0x1782a4f0, 0xf984f620, 0xff004036, 0x52f8f9ff, 0xf0f7ffff, + 0xffff08a4, 0xff0a97d7, 0x281ccaff, 0x2720d682, 0xff23e182, 0x8234b3ca, 0xe62a2a0a, 0xfb05c366, 0x1554fb74, 0x0c55543b, 0x560ada54, 0x0a231abf, + 0x418b5c0f, 0x00320568, 0xff00c004, 0xae070600, 0x0f0800ff, 0x00ff085c, 0xbb826628, 0xb8de3536, 0xd8ffff05, 0x00ff9002, 0x05ec5135, 0x0e055361, + 0x34f894f7, 0x2609ab64, 0xffff5d6d, 0x8266e6a2, 0x198d2362, 0x0682089a, 0xb85ece2b, 0x591500ff, 0xd2ffff9a, 0x284082a6, 0xffb89e23, 0xae47dcff, + 0x06995f08, 0x48a1cd2a, 0x3ad6ffff, 0xd3ffffe1, 0xff20c383, 0x0482e883, 0xfd201e82, 0xff207f82, 0xff210484, 0x28f88260, 0xff1884fc, 0x00600100, + 0x378a8288, 0xff764001, 0x0601fdff, 0xc50200ff, 0xfeffff60, 0x00ff3433, 0x8b004003, 0x42201a82, 0xff280682, 0x9ad93000, 0xc21f00ff, 0x1927a582, + 0x00ff0180, 0x8248a113, 0x9920221a, 0x2a748299, 0x00ffc2b5, 0xff676624, 0x82e6f8ff, 0x6626228e, 0xe2771866, 0xb3712109, 0x5d284782, 0xff8b4821, + 0xb8de7200, 0x0683bc82, 0x8effff26, 0x00ffcc4c, 0x3a651682, 0x2f0e2806, 0xb4f714f7, 0x18072b15, 0x2b0ea255, 0xb6b68bc0, 0xeb08c08b, 0x0614f707, + 0xff221c82, 0x378284ff, 0x829bff21, 0x82048553, 0x826a820e, 0x8bcd2215, 0x251182ff, 0x6400ff33, 0x6a82cc4c, 0x34b37b22, 0xfb233485, 0x1815eb14, + 0x201679b5, 0x46ea82cb, 0x84200c51, 0xee2d4382, 0x4b087c54, 0x0614fb07, 0xd4f707cb, 0x463a898b, 0x7c2005f5, 0x85066561, 0x8234203a, 0x053e5458, + 0x08424418, 0x0e293a86, 0xeb34f82f, 0xf7ffff15, 0x184476cf, 0xb89e562d, 0x53a900ff, 0xffff0534, 0x839a9956, 0x5d982004, 0xbe6c3728, 0x1fcf6b1e, + 0x4d49ff20, 0xccf92205, 0x7b8818ce, 0x2f0e2410, 0x6dab74f7, 0x1b5d3b5a, 0x5ea9221c, 0x27f782b8, 0xff053493, 0x6666a900, 0xe15c0484, 0x10866d25, + 0x2007926c, 0x05db7ac0, 0x2b10bc60, 0x02ffef0e, 0xff343366, 0x34337100, 0xfc23ce82, 0x8294cc4c, 0x3a108323, 0xff32b306, 0xcc4cf6ff, 0x065b088b, + 0x198f00ff, 0xff8b079a, 0x9a192c00, 0x82dcffff, 0x23002804, 0xffff66e6, 0x1866e6d3, 0x2008ed71, 0x237b827a, 0xff86abf1, 0x2013f943, 0xd9531854, + 0x14f7210c, 0x08215082, 0x075547cc, 0x250aa447, 0xe670ffff, 0x6f820766, 0x08207882, 0xf72c4f82, 0xffffc440, 0xfff027fa, 0xae47fcff, 0x06229782, + 0x0a890824, 0x00ff2008, 0xff621002, 0x9eaff5ff, 0xdb0600ff, 0xf9ffffe8, 0xdb084821, 0xfaafffff, 0x00ff05e2, 0x82c2aa04, 0x6666213a, 0x33201b82, + 0xfd21c882, 0x20e382b3, 0x05c74506, 0x98190622, 0x0622ca82, 0x4182182e, 0xff105826, 0xa0b00400, 0xaf210482, 0x233c82e0, 0x1e055000, 0x06223c82, + 0x37827cd4, 0x8258d921, 0x9c192620, 0x4c0a00ff, 0x2f7682ce, 0x0894cc4c, 0xccc9feff, 0xeeffffcc, 0xfb15cccc, 0xff20c582, 0x14e56218, 0x0724f723, + 0x22e182bb, 0x82f8b309, 0xbf082666, 0x0500ff3b, 0x2a6682d8, 0xff52b803, 0xdcf90800, 0x8700ff08, 0xffff240a, 0x829eeffd, 0x8250205f, 0x24f921c7, + 0x06238f82, 0x8208b8de, 0x2385842f, 0x4055fbff, 0xa8219782, 0x21d982f6, 0x8a82cdcc, 0x820a5721, 0x66e62309, 0x0685088b, 0xff211685, 0x272083fd, + 0xffcd4cfb, 0x5c4ffbff, 0xff853c82, 0x2bf9ff23, 0x21208285, 0x62826626, 0xffa4f026, 0x32b3f5ff, 0x82207684, 0x82207d85, 0xc0398982, 0xfaffff00, + 0x00ff3433, 0x8b33b309, 0xfb06bb08, 0xff8b0724, 0x66e6d3ff, 0x05dc41ff, 0x9a19dc27, 0x192c00ff, 0x9774189a, 0x08345b1b, 0x685bb320, 0xaf0e270c, + 0x1554f8eb, 0x524b00ff, 0xe6092705, 0xf7ffff67, 0xc2825ccf, 0xff333326, 0x14aef4ff, 0x01218482, 0x2e7e8280, 0x059082f3, 0xb3a401ff, 0x00ff0632, + 0x82cc4c14, 0x8210204d, 0xebff2190, 0x4c369a84, 0xebffffcc, 0x55080a97, 0xf53fffff, 0xffff05c2, 0xff9c19fc, 0x2083f2ff, 0x8266f321, 0x83f620d7, + 0xb3f12941, 0xff088b32, 0x68e6c2fe, 0x09234282, 0x825b3333, 0x1934224f, 0x0ca66d9a, 0x114e7218, 0xff201183, 0xce6e0485, 0xb7fe2105, 0xff243383, + 0x8b6666f5, 0x21054c4d, 0x67830800, 0xccccfd22, 0x4c2cc482, 0xffff08cc, 0xff71bdc3, 0x00803c01, 0xcb228782, 0x166929dc, 0x69c18220, 0x0d2a054f, + 0x088b0040, 0xfcab06d3, 0xd5181564, 0x67181690, 0x80210d3e, 0x8de41800, 0xffff221d, 0x202284e5, 0x18fd82ea, 0x200ad6a3, 0x05444bf8, 0xff211b82, + 0x851a83ff, 0x67221904, 0xad318a10, 0xf80e258d, 0x15c4f794, 0x82066a77, 0x22648f7a, 0x960634fc, 0xf4f72299, 0x276a9607, 0xcb0634f7, 0x54f7054b, + 0x410e0f4d, 0x0e2e0801, 0x9300ffaf, 0x94f7cdcc, 0x4c01ff15, 0x1a4d3433, 0x49231906, 0x34fb2512, 0x05cb4b06, 0x82820582, 0x8b717d27, 0x82eaffff, + 0x6a45188f, 0xff32080b, 0x9a99b7fe, 0x5a00ff07, 0x00ff3e8a, 0x059a19b5, 0xdc0a00ff, 0x1500ff29, 0xffa132b3, 0x9a990d00, 0x661800ff, 0xff088b67, + 0xcc4c8b01, 0xfeff156b, 0xce83b374, 0x66e6f322, 0xf42b4b82, 0xffff66e6, 0xff3333f9, 0x6d99faff, 0x882d0874, 0xffffcdcc, 0x0533b311, 0x19bf01ff, + 0x22c0829a, 0x82b81e0c, 0x140b2ce5, 0x0600ff7c, 0x00ff1cda, 0x82846b05, 0x88d62964, 0x5f00ff08, 0x54f7feff, 0x0b227282, 0x7282e47a, 0xff5c4f34, + 0x0080f0ff, 0xe7ffffa4, 0x088b6466, 0xffb0fb0e, 0x8183f600, 0x9a995623, 0x05ea4e15, 0xccf9ff24, 0x0f7fffcc, 0x82f72012, 0xfcff2816, 0xffff00e0, + 0x82ecd1f7, 0x82c02093, 0xc2f92509, 0x2b2b0890, 0x211b1f47, 0x5065eb2b, 0x00ff2336, 0x61826029, 0xec91d622, 0x2528e582, 0xff070080, 0x48a1d6ff, + 0xb8640482, 0x82eb2038, 0x19ec668a, 0xc682eb20, 0x45060023, 0xaad9851e, 0x06db49ff, 0x5718f320, 0x45650d42, 0xa0d62206, 0x20c88200, 0x21c38251, + 0xc383dafe, 0x61290023, 0x27108248, 0xff054861, 0x1e850c00, 0x14230486, 0x478b3433, 0xff200591, 0x082d4682, 0xf601ff0e, 0x00ff9a99, 0x156666a9, + 0x6696822b, 0xc165362c, 0x21808218, 0x0482846b, 0x05006023, 0x209683ff, 0x24918406, 0x9ed6ffff, 0x06e747b8, 0x16d68f18, 0x52b8f922, 0x65085a74, + 0x8f2420a5, 0x400600ff, 0x12832f1b, 0x410c1f75, 0x01201093, 0x28639018, 0x85abd622, 0xa020b282, 0x0124c382, 0x06008025, 0xc884be84, 0x21367042, + 0xfc832beb, 0xff146e26, 0x5278f3ff, 0x2009bf67, 0x270f8202, 0x0e080080, 0x1534f8ab, 0x0b257a18, 0x210a236f, 0xc04fe4fb, 0xf6282209, 0x06ef4eff, + 0x8b0ad725, 0x5e24f808, 0x6a6d17cf, 0x82fc2016, 0xd3ff2330, 0x1e82ebd1, 0x142edc22, 0x0b259f18, 0x6483f720, 0x19110021, 0x21121949, 0x4e182beb, + 0x236e36e9, 0x9d4e1811, 0x34f72219, 0x0ead6e4b, 0x5f0d3f6c, 0xfb221198, 0x386e0614, 0x18cd200e, 0x180bc056, 0x23125651, 0x14f70614, 0x304f4f18, + 0x1850e918, 0x7008ef69, 0xf7290d8b, 0xcb0e0694, 0x9b1514f8, 0x27208207, 0xff0ad708, 0xf6280700, 0x0e820486, 0xcb088b25, 0x5000ff06, 0x6a1809a3, + 0x7b220aa0, 0x1a82ab07, 0x00803228, 0x3d1900ff, 0x25820570, 0xff66e630, 0x34730400, 0xcc0900ff, 0x0200ffce, 0x09825c4f, 0x8b66e628, 0xb000ff08, + 0x2b8266e6, 0x1814fc7c, 0x2034ba95, 0x7dad83b4, 0xff2f1364, 0x9a999c00, 0xccc6ffff, 0xffff15cc, 0x5b9919f7, 0x230805d3, 0x3333f6ff, 0xb3fdffff, + 0xf6ffff34, 0x088b9a19, 0x4b0614fb, 0x7200ff07, 0xa106cdcc, 0x190f00ff, 0x1a00ff9a, 0x0820c783, 0x1c22c183, 0xb28333b3, 0x34b31c23, 0x8216858b, + 0xa19a2647, 0xe6f0ffff, 0x2ec98266, 0x06cccc72, 0xffff07eb, 0x069a194f, 0x82cdffff, 0xe6ff2335, 0xfd82cccc, 0x66662327, 0x33a1ffff, 0x26778234, + 0x8b6666cf, 0x83d8ffff, 0x0ce96188, 0x00621782, 0x61ff2009, 0x17620744, 0x27002109, 0x17833883, 0x7a820820, 0x44851782, 0x82053362, 0x088b2b3c, + 0x1a01ff0e, 0x00ffcc4c, 0xdf834c68, 0xceccdd2b, 0x99dfffff, 0xffff059a, 0x207d83fc, 0x207183fa, 0x21c382f9, 0x9783fdff, 0x8299f921, 0x186320ea, + 0x180cefdd, 0x9a0c9a6d, 0x493b201a, 0xb3210e52, 0x25908234, 0x08cc4c0d, 0x088207db, 0x6c820620, 0x0c4bfe19, 0x00ff002b, 0x08008004, 0x45a100ff, + 0x21048260, 0x9182cd4c, 0x9999fa25, 0x841000ff, 0x9a19268c, 0x191200ff, 0x2239829a, 0x8333b312, 0x336127da, 0x4e00ff34, 0x0483cdcc, 0x9118cd82, + 0xff221057, 0x708233b1, 0xcc9eff23, 0x832d82cc, 0xf24a1806, 0x4ced2b12, 0xffff8bcc, 0xff68e6ed, 0x65830200, 0x9819ef27, 0x660500ff, 0x21858266, + 0x5e82b35d, 0x34b3a725, 0x6100ff15, 0x938218f9, 0x82eeff21, 0x7bbb1804, 0x16a36221, 0xffef0e2b, 0xcc4c1e01, 0xe62401ff, 0x20688266, 0x214b8201, + 0xd783f9ff, 0x9a990023, 0x20338284, 0x29bc83f9, 0xffffff83, 0xff846666, 0xb748feff, 0x82342005, 0x8216209d, 0xecff2a24, 0x92053333, 0xb3f9ffff, + 0x20be8633, 0x322083f6, 0xffce4cfc, 0x6766f6ff, 0xfdffff08, 0xffff32b3, 0x829999fb, 0x00802109, 0xe6212882, 0x83098267, 0xfffa2239, 0x201e82ff, + 0x202e83fc, 0x05fa41fa, 0x869a1922, 0x21057857, 0x2083fbff, 0x2f83fc20, 0xcc4cfb22, 0xfa202582, 0xff249f82, 0x816666f8, 0x82214584, 0x2012828e, + 0x2b7183e3, 0x05ce4c09, 0x4cf5ffff, 0xf7ffffcd, 0xf321b783, 0x200982cc, 0x235283f8, 0x8633b3f2, 0xf9232582, 0x826e9a19, 0x83fe2021, 0x83f62012, + 0x84f82089, 0x9a992121, 0x93839e82, 0xceccfe22, 0x40832583, 0x8233ff21, 0x33f921a8, 0x078c4218, 0x8b203982, 0x8b204085, 0x2305a849, 0x66660000, + 0x2a820982, 0x84000021, 0x82f62035, 0x01002140, 0xf7203583, 0x00215e82, 0x831e8307, 0x82002068, 0x21398495, 0x7a82a899, 0x9999f325, 0x83ffff90, + 0x07002198, 0xf527a283, 0x00ff0040, 0x8266e608, 0xc7e32221, 0x218682ae, 0x258232b3, 0x8f02f723, 0x24c88288, 0x00ffe1fa, 0x20f68302, 0x226683fa, + 0x829a9907, 0x75fc2a25, 0x0400ffc3, 0xffff34b3, 0x20f283fc, 0x246b8204, 0xc3f5fcff, 0x831a8390, 0x4c05222f, 0x214082cc, 0x258235fd, 0x0100052a, + 0x76fdffff, 0x0500ff46, 0xfd22c783, 0x098264bb, 0x83cd4c21, 0xc74b2429, 0x830900ff, 0xd60222b0, 0x82098287, 0x07002689, 0x00ffdf0f, 0x281e8306, + 0x152e1600, 0xcc1300ff, 0x224882cd, 0x8248e1fe, 0xcccc2b15, 0x85feffff, 0x938b921f, 0x0e828b08, 0xff343327, 0xe17a0100, 0x21058292, 0x1e84b81e, + 0xe9225382, 0x3483ebd1, 0x3482ce20, 0x21f0f827, 0x330700ff, 0x217d8232, 0x5e867929, 0x39b40322, 0xb322e882, 0xd2820834, 0x829c4421, 0x231e8234, + 0xba890200, 0x4f21cc82, 0x8213825c, 0x050023fc, 0x1e82ae07, 0x3d0a0322, 0x4027a782, 0x00ff0500, 0x82ae0703, 0xce0c210a, 0x4c210982, 0x202982cd, + 0x21cb82e1, 0x1e828a03, 0xa4b00422, 0x05222982, 0x678233b3, 0x1e828c20, 0x1f050a22, 0x82214382, 0x2162828e, 0x768271fd, 0x823e0a21, 0x381c271e, + 0xf6ffff52, 0x488234b3, 0x00c00a22, 0xd7251a82, 0x0c00ff0a, 0x83338333, 0x660c22b6, 0x22528267, 0x8208e2fa, 0x82e6208c, 0x111d220a, 0x222982ec, + 0x829a1901, 0x824720b1, 0x83082077, 0x6e072209, 0x830e8214, 0x23012229, 0x83298396, 0xd0002272, 0x20338220, 0x229182cc, 0x82026b00, 0x050c4609, + 0x06820620, 0xff231685, 0x82fe94ff, 0x232a8209, 0x2030ffff, 0x09203582, 0xff234082, 0x822adcfe, 0x257e82ad, 0xec91f8ff, 0x688300ff, 0xb8f6ff23, + 0x257e8452, 0xe2ffff66, 0x7e8214ee, 0xe7820d20, 0x05fbff23, 0x24a8851e, 0x48e1f8ff, 0x052c7dff, 0xf628f722, 0x1c202982, 0x00251e82, 0x05cc4c09, + 0x22ee8294, 0x8295c2f5, 0x727d2bea, 0xb30500ff, 0xf8ffff34, 0x21823273, 0x00800327, 0x54fbffff, 0x201f827c, 0x26558266, 0xffd823fb, 0x82e60300, + 0xfafa2209, 0x821e83e0, 0xfaff23d4, 0x6a82289c, 0xcccc0226, 0xfdfaffff, 0x63423e82, 0x0ad72105, 0x4c213382, 0x221382ce, 0x820834b3, 0x32b32534, + 0x4cf7ffff, 0xfd202382, 0xf6233383, 0x828466e6, 0xcecc2563, 0xe9ffff08, 0xec2a3983, 0xff053233, 0x34b381ff, 0x944d15a7, 0xe9ff270b, 0xff8b9a99, + 0xd663e6ff, 0x99e42505, 0x1500ff9a, 0xeb209283, 0x00238d82, 0x1800801a, 0x210d587d, 0x2d831400, 0x841b0021, 0x1900212d, 0xff212d82, 0x212d82ea, + 0x2d821600, 0x584eff20, 0x44012105, 0xfe23bd82, 0x82cecca0, 0x33f92566, 0xfeffff34, 0xff208984, 0xf8222183, 0x4f8266e6, 0x0683ff20, 0x00ff8426, + 0xff9a9900, 0x2205ab44, 0x829a1901, 0x84a182a6, 0x22a682ab, 0x82ceccf8, 0x21c382bd, 0xcd84ffff, 0x0023d783, 0x8232b303, 0xb3fa2225, 0x82f78734, + 0x020024d6, 0x82860080, 0xcccc210f, 0x50821a83, 0x19030024, 0x1182059a, 0x85820320, 0x82fbff21, 0x0200217f, 0xfb277983, 0x00ffcc4c, 0x82008003, + 0x82f82025, 0x0581410f, 0x0080fd2a, 0x08948e95, 0x4c0900ff, 0x08c5f918, 0x9a19f725, 0x820a00ff, 0x059c5563, 0x34330c22, 0x0d294c82, 0x6e08cc4c, + 0xe60600ff, 0x229b8266, 0x4232b3f6, 0xf820060d, 0x07206f83, 0xcc20e384, 0x09224082, 0x5e826666, 0x8233ff21, 0x8206201e, 0xffff2123, 0x06231e83, + 0x848bcecc, 0x85082039, 0x83f68206, 0x8216827f, 0x82358309, 0x2081822a, 0x82358301, 0x00ff2240, 0x201e8307, 0x84858308, 0x19012495, 0x84a8089a, + 0x90052440, 0x830c00ff, 0x8307201c, 0x2298821c, 0x820800ff, 0x82ac83e4, 0x28958476, 0x05cc4c1c, 0x00ff9488, 0x82d88202, 0x227f8349, 0x8233b305, + 0x8204205e, 0x22fe83d0, 0x830400ff, 0x33042232, 0x224c8233, 0x82343302, 0x4c05231a, 0x5a838ecc, 0xcccc0222, 0x4c211d82, 0x823d84ce, 0x22908370, + 0x82cd4c02, 0x84082021, 0x33b3213c, 0x21051944, 0x7e83fdff, 0x32330723, 0x201a8284, 0x24c18213, 0xcdcce9ff, 0x83308205, 0x1901233f, 0xd7829299, + 0xa5827883, 0x21828b20, 0x92230683, 0x85ffffff, 0xffcc25f4, 0x67e6feff, 0x00233886, 0x83333316, 0xcc4c2138, 0x09223382, 0x82469819, 0x09002605, + 0xffff9c99, 0x827984fc, 0xffff229b, 0x227983fd, 0x82343305, 0x00802209, 0x87058290, 0x058821b6, 0xb6840d83, 0xff68e626, 0xcdccfbff, 0xb321c082, + 0x213c8230, 0x62820080, 0x47830720, 0x824cfa21, 0x80022914, 0x82888100, 0xf6ffff08, 0xff23c982, 0x8234b3e3, 0xe6082b75, 0xf5ffff64, 0x00ffcc4c, + 0x6f821907, 0xccccf322, 0xf3294c82, 0xa8089a99, 0x19f9ffff, 0x2021829a, 0x211c8209, 0x1b46feff, 0x202b8205, 0x200983f7, 0x20868301, 0x822582f6, + 0x237882e4, 0xce4cf9ff, 0x66200982, 0xf9237d82, 0x848b3233, 0x85082039, 0x21f28206, 0x10829899, 0x82323321, 0x82358309, 0x2081822a, 0x823583fe, + 0xffff2240, 0x209e83f8, 0x830e84f8, 0x21688295, 0x40846e08, 0xff860524, 0x8042f2ff, 0x82768205, 0xffff2298, 0x82a283f7, 0x84d582ac, 0x27c28395, + 0xffff828e, 0x810080fd, 0x66204982, 0xfa222782, 0x5e82cc4c, 0xd04cfb22, 0xff24fe84, 0x3033fbff, 0x99221f82, 0x0f82869a, 0x829a1921, 0x83fa201a, + 0xe6fc226f, 0x205e8366, 0x209084fd, 0x823682e6, 0x832b8241, 0xb3fd221a, 0x20258232, 0x474b83f6, 0xd24805ff, 0xb3f92308, 0x9e439234, 0x16002e06, + 0xff053433, 0x9a191b00, 0x4c7e00ff, 0x07bd52cc, 0x20050444, 0x1df71815, 0x0c604408, 0xbd52ea20, 0xd8f3180f, 0x0beb520f, 0x250a8b52, 0x34f8ef0e, + 0x6283a4f7, 0xae836120, 0x66e6a222, 0x2405a749, 0x9a198dff, 0x838f828b, 0xffff2106, 0xa7491683, 0x6ed82c0d, 0x0f00ff14, 0xffffb89e, 0x822a9cdb, + 0xcd0c265b, 0x8fe2ffff, 0x3631825c, 0xff299cef, 0x703ddfff, 0x28e9ffff, 0xe7fffff6, 0xffffa470, 0x83d7a3ff, 0x82d82004, 0x82fd201e, 0xfdff2361, + 0x0f8286cb, 0xff2e4282, 0xffe0bafc, 0xa03a0100, 0x1efdffff, 0x0a8208fa, 0x82d14221, 0x4e22300a, 0xb30200ff, 0xfeffffb6, 0x00ffcc4c, 0x82d90e03, + 0x2600388a, 0xff8b9a59, 0xf6682000, 0x1e0b00ff, 0x1800ffb8, 0x00ffe1fa, 0x8286eb0c, 0xcc1e2135, 0xf0277e82, 0x00ff28dc, 0x489a9923, 0x002105e7, + 0x05e76526, 0x66e67222, 0x5d223582, 0xd7849a19, 0xe7820a82, 0xb72b3182, 0xfeff9899, 0x15cc4cf4, 0x821900ff, 0x1d0023f8, 0xcf82cecc, 0x25220983, + 0x2582cc4c, 0x9a992822, 0x2105bc4a, 0x38833533, 0x8221cd21, 0xffff2481, 0x828b7caf, 0x06b221b7, 0xf5210482, 0x21048280, 0x04827eaf, 0x827eff21, + 0x6f002b4f, 0xfaffff00, 0x00ff36be, 0x09838000, 0x8232b321, 0x84fa2029, 0x9dff3744, 0xffff4861, 0xffec51b0, 0x846badff, 0x9495ffff, 0xeaffff7a, + 0x358234b3, 0x75821420, 0x66b3ff26, 0x4a00ff66, 0xff210482, 0x20a583c7, 0x82b0825a, 0xb021221a, 0x318682a4, 0xff48a11f, 0x0c020800, 0x871b00ff, + 0x0d00ffac, 0x1a82d6f8, 0x9c591832, 0x05f4ffff, 0x1e00ff1e, 0xff8164e6, 0x34332400, 0x00239d82, 0x821c0f03, 0xb3022631, 0x0100ff74, 0x27ee82b9, + 0xff904201, 0x48e10200, 0x01223182, 0x0a83a03a, 0x6d2bb783, 0x0300ffe0, 0xffffde44, 0x829ce6fd, 0xbc342213, 0x20c28208, 0x222982b8, 0x824a5700, + 0xd04c3596, 0x661700ff, 0xefffff68, 0x00ff30b3, 0x0898991f, 0xb4f7af0e, 0x33278382, 0xffff1534, 0x18cdcc7f, 0x2cacf7aa, 0xff9af90a, 0x98190b00, + 0xfb0600ff, 0x2709825e, 0x00ffce4c, 0x085c0d00, 0xe6310582, 0x48feff66, 0xff053229, 0x34339100, 0xccb7ffff, 0x20df82cc, 0x221582fe, 0x82e6ffff, + 0x210982fe, 0x9844ff8b, 0x19002205, 0x29308298, 0x06ce4c03, 0xab34f70e, 0x736f4b15, 0x7a542a0e, 0x1100ff8b, 0xf70886ab, 0x05906294, 0x11bf5919, + 0x5106cb21, 0x00200b3d, 0x10d16818, 0xb3f1ff24, 0x1683ff33, 0x20053450, 0x22628308, 0x82e1faca, 0x05d52280, 0xfd76181f, 0x2462830c, 0xe2facaff, + 0xfd7618ff, 0x8762900f, 0x2a511895, 0x20628508, 0x3a62867a, 0x995601ff, 0xb600ff9a, 0xfb159a99, 0x0514f714, 0x7df3ffff, 0x0c00ff70, 0x58ff9082, + 0xff220504, 0x1382e0fa, 0xf3220e83, 0xc45d9082, 0xf1a21807, 0x0c002309, 0x1f820080, 0x0800802c, 0x734900ff, 0xb6ffff32, 0x448266a6, 0x34332d22, + 0x7f0cf950, 0x4c73119a, 0x00ff240f, 0x82ccccd2, 0x9eb62233, 0x214482b8, 0xc152b89e, 0x0a855306, 0x75876a8b, 0x0b204818, 0x08211f83, 0x23c484f7, + 0x146e0c00, 0x8721c482, 0x22f582ae, 0x83343314, 0x820220a0, 0x23a5820f, 0xab30fb0e, 0x33580c19, 0x16426a18, 0xe2ffff34, 0xff060080, 0x66660b00, + 0xcc6bffff, 0x00ff05cd, 0x6f82b324, 0x9919ec26, 0xe61c00ff, 0xde201482, 0x00210e82, 0x2009830d, 0x217e82d6, 0x2182888c, 0x91830320, 0xcc4cf623, + 0x05b24fff, 0x3433f52d, 0xf7ffff85, 0xff0832b3, 0x82ccfaff, 0x99f72515, 0xf6ffff9a, 0xfb215183, 0x2d098219, 0x8b34b3f5, 0x06d4fb08, 0xb5f5ffff, + 0x19828bc2, 0x480a5721, 0xff2e0559, 0xff71fdf9, 0x66660800, 0xf9ffff08, 0x0a8264fc, 0xffce4c29, 0xf45cfeff, 0x820a00ff, 0x03002f47, 0x00ffc540, + 0x0834b309, 0x000100ff, 0x79828e83, 0x75d30d27, 0x802900ff, 0x249b8200, 0x00ff33f3, 0x28838221, 0x52b82400, 0xe61300ff, 0x2d258267, 0xff67660b, + 0x33339400, 0xe2ffff05, 0xdf42c275, 0x7e6b180f, 0x54f72507, 0x2b15f4fb, 0x7f0aa27f, 0x41180e32, 0xeb2814e9, 0x0e06cb07, 0xf894f72f, 0x0a21d818, + 0x260db75e, 0x197f00ff, 0x848b069a, 0x238b8200, 0x8b323305, 0x332ae682, 0xffffff34, 0x00ffd823, 0x0982b303, 0x146efe22, 0x02271a82, 0xffff66e6, + 0x823273fe, 0x8266201e, 0xb5fd2209, 0x281e82c4, 0xffff9a19, 0x0852f8fc, 0x202f828b, 0x233a82f3, 0x34f3ffff, 0x2305f66d, 0xc2f5ffff, 0x062a3582, + 0xffff3233, 0xffaec7f9, 0x54830200, 0x48e1f722, 0x2005fd43, 0x840982ff, 0xc2f52135, 0xf8213b83, 0x22058552, 0x7314fb08, 0x4018176e, 0xd2530ef5, + 0x00ff2107, 0x5f055b7c, 0xa2570532, 0x19cc200f, 0x180cddd9, 0x820d2e4b, 0x0894578f, 0xa92ea982, 0x00ffce4c, 0x056666a9, 0x4ccdffff, 0x6e8d06cc, + 0x0ae06318, 0x4b94fb23, 0xcf2b1915, 0x60eb2016, 0x7355173f, 0x0cb54109, 0xfb062b27, 0xb4f707b4, 0x08b97806, 0x161a0020, 0x2b212599, 0x18508207, + 0x21136577, 0x5118b4fb, 0x361a0a2f, 0x0e240fb3, 0x34f834f8, 0x5e064045, 0xa86009b4, 0x066b4308, 0x540e002d, 0xf1ffff7a, 0x00ff84ab, 0x5486ab11, + 0x08830594, 0x56057767, 0x94200b7b, 0xee208583, 0x86202d85, 0x04823283, 0x8b210e82, 0x05a34508, 0x8620628a, 0x7a215b84, 0x88068508, 0x8a862049, + 0x05352662, 0x00ff8b1e, 0x055b452a, 0x0a82e220, 0xd3451082, 0x20098206, 0x2a1a8460, 0xff088b56, 0x9a99b6ff, 0x4536ffff, 0x71200b38, 0x22123845, + 0x45ffff8f, 0x33202238, 0x20093845, 0x0ec56333, 0x650d6356, 0xff241139, 0xcdccd200, 0xb6223382, 0x3845b99e, 0x45002054, 0xaf390638, 0x193c02ff, + 0x6d01ff98, 0xff15b89e, 0x6866fdff, 0xca0a00ff, 0xf6ffff3e, 0x3393824c, 0xff0a9707, 0x68e6f4ff, 0xffff088b, 0x0634339b, 0x3e0000ff, 0x732b3883, + 0xffffff34, 0x00ff98dd, 0x8200400b, 0x7ebc2609, 0x510900ff, 0x2b2482ea, 0xff4e8eff, 0x9a591100, 0xe6f1ffff, 0x0d274982, 0xffff48a1, 0x839899ee, + 0x6600233f, 0x0c830667, 0x838b9a21, 0xff66251c, 0xb85ef2ff, 0x27062d6d, 0x0866a6ee, 0xe6feffff, 0xf6221482, 0x648216ae, 0x5f82b320, 0x82c0f421, + 0x4c002769, 0xf3ffffcd, 0x1e82cc8c, 0xf5289b23, 0x208c8306, 0x273f8266, 0xff8360f6, 0xf668f8ff, 0x6020b082, 0xf5238082, 0x8208c235, 0x2130254a, + 0x99fcffff, 0xed367b82, 0xffffa430, 0xff7a94ae, 0xaec73400, 0x4cb1ffff, 0x00ff08ce, 0x14827025, 0x142ec826, 0x283f00ff, 0xd8203882, 0x0028e482, + 0xff67e656, 0x48a1e9ff, 0x122c1e82, 0xffff33b3, 0xffec31fb, 0xc3b50c00, 0xbe21a782, 0x226782b8, 0x82a4b0ec, 0x05002b1a, 0xe8ffff1e, 0xffff842b, + 0x6d8280ec, 0xe8200484, 0x22053f4b, 0x696666fb, 0x852009e8, 0xea202682, 0x08a58418, 0xf7273e82, 0x00fffc29, 0x82ba2907, 0x04d621ab, 0xef220982, + 0x4e828be0, 0x9b19df22, 0x083bb918, 0x96430622, 0x29211782, 0x3bb918fc, 0x284a820f, 0x707d1500, 0x7de5ffff, 0x23338272, 0x225bfbff, 0xe8226782, + 0x5582d823, 0x00237f83, 0x82008013, 0xd9172333, 0x0682089a, 0x5c4f1322, 0xc22fb683, 0x421100ff, 0x1200ff90, 0x00ff34b3, 0x82cccc04, 0xf556216b, + 0x16221482, 0xf4820a57, 0xffd82325, 0x82352700, 0x6625250e, 0x3700ff68, 0x05823982, 0xff54792a, 0x14ae4e00, 0x33edffff, 0x513c3382, 0xffff866b, + 0xff3033ff, 0x66660300, 0x11feff08, 0xffff5e4f, 0x157b9476, 0x0fe4ffff, 0x293c6282, 0xffff3333, 0xff3d8afd, 0x66e62a00, 0x5e0100ff, 0x1700ffb9, + 0xff0834b3, 0xd7635000, 0x052fd382, 0xffffe75b, 0xff4861c4, 0xb3fd0e00, 0x83b8ffff, 0x512527c5, 0xff0851eb, 0x8883ceff, 0xff27b482, 0x0080dbff, + 0x821b00ff, 0xe8ff3a6e, 0x00ff8f82, 0x08999922, 0x30a501ff, 0xff158ba4, 0x5c8fe8ff, 0x66ddffff, 0x23258567, 0x9ad9e4ff, 0xf0263982, 0xecffffa4, + 0x6582ac87, 0xcc4c252b, 0xeb3900ff, 0x00ff9a86, 0x27458347, 0xffce4c05, 0x9a993b00, 0xd8208084, 0x00228082, 0x44828c82, 0xff242582, 0x606866fe, + 0x2805f46e, 0x67e6d6ff, 0x00ff0e08, 0x26568269, 0x66660901, 0x4800ff15, 0x7d830566, 0x90421422, 0xfd21f182, 0x21138271, 0x0482707d, 0x82be7f21, + 0x5949214b, 0x49286082, 0xff05104d, 0xcc4c0dff, 0x20078444, 0xc0591800, 0x086a7907, 0x1809b544, 0x290be253, 0x34b3f200, 0x4900ff07, 0xb7434861, + 0x0c002106, 0xff215a82, 0x206e86f3, 0x827e858b, 0x82b32014, 0x821a836a, 0x8272200a, 0x42142315, 0x2582ff8e, 0x1f849020, 0xb5490820, 0xc5f92b06, + 0x0600ff1e, 0xffffd24d, 0xeb82ccf7, 0x00200322, 0x0fa2ad18, 0xba5e1682, 0xccf92c05, 0xf9ffffcc, 0xff0800c0, 0x820080ff, 0xf97f2226, 0x22c0829a, + 0x82e17af3, 0x00802155, 0x2306f55b, 0x1f850c00, 0x08230f84, 0x667601ff, 0x9a240503, 0x0634fb15, 0x161e5718, 0x091b5718, 0x18ff9a21, 0x820a1b57, + 0x18ff2030, 0x22088944, 0x6dffff85, 0x7f180984, 0xf8201847, 0x90a49c18, 0x2f0e4408, 0xe6ab01ff, 0x8b01ff66, 0xff1566e6, 0xb8deebff, 0x3a1400ff, + 0xe4ffffe2, 0x00ffce8c, 0xff3e0a05, 0x32f3edff, 0x80f5ffff, 0xffff0800, 0xffb85ecc, 0x84ebe1ff, 0x0795ffff, 0x4c00ffae, 0xffffec91, 0x849a9985, + 0x221e8204, 0x83999985, 0x8498200a, 0x83202019, 0x82852029, 0x68662133, 0x3f821a82, 0x34204983, 0x07215382, 0x205d836d, 0x216782cc, 0x7184b23d, + 0x0a820820, 0x82482121, 0x90c22f0a, 0x731b00ff, 0xfaffff34, 0x00ff52f8, 0x23820c12, 0x77830a20, 0xa133002b, 0x1e00ff48, 0x00ff7a14, 0x2819826a, + 0x146eb3ff, 0x667a00ff, 0x82048366, 0x210a875c, 0x1983ff66, 0x2983f620, 0x00ff7c25, 0x829a9933, 0x870a2258, 0x214982b0, 0x53823c0a, 0x0023e582, + 0x82c2751b, 0x82cc2067, 0x21142a58, 0x6cfb0848, 0x99b4ffff, 0x21f7829a, 0x7582b3d3, 0x1782f420, 0x19c3ff22, 0xc321c382, 0x24d38219, 0xff7bd4f4, + 0x059d76ff, 0xf628fe2f, 0xb3f8ffff, 0xf9ffff33, 0xffff0080, 0x232383fc, 0x8bf5e8f7, 0xfe32d882, 0xff8b10b8, 0xdfaffeff, 0x270000ff, 0xfefffffd, + 0x098221b0, 0x82005021, 0x56f8271a, 0x0100ff04, 0x7b82373b, 0xff5ccf24, 0x3f820800, 0x82020021, 0x080023e8, 0x9a829999, 0x54820e20, 0x47380027, + 0x4500ffae, 0x2cca8226, 0xffb81e45, 0x3e4a3800, 0x330e00ff, 0x261e8234, 0xfff0a708, 0x82070200, 0x98082204, 0x21428210, 0x0e8230e8, 0xffa43026, + 0x2871f7ff, 0x02221e82, 0x0a82a330, 0x82846b21, 0xcdcc2119, 0x66210982, 0x32048368, 0xfdffff66, 0x0e08cccc, 0x33ff01ff, 0xff15c834, 0x82c0e8ff, + 0x339b23af, 0xb5820534, 0xffe8bb24, 0x0f83f1ff, 0xda79f327, 0x07f6ffff, 0x210e82b0, 0xc4837c54, 0xc1b50322, 0x0524b482, 0x32ffff1c, 0x00274c82, + 0x8b3433cd, 0x71fc00ff, 0x0e2b0527, 0x00fff6a8, 0xff10f809, 0x838a0c00, 0x4240259c, 0x400300ff, 0x0021df82, 0x232b8364, 0x05004017, 0xae21b282, + 0x2b158214, 0xff9ae866, 0x4861f8ff, 0x190600ff, 0xf2220982, 0xa8821619, 0x1f852e27, 0x8093ffff, 0x27258202, 0xff217005, 0x5038f3ff, 0x54218b82, + 0x217c82fe, 0x287f2a1c, 0x38f72d06, 0xffff0852, 0xfff528ca, 0x1ec5d4ff, 0x21372982, 0xffffe1fa, 0xffaec7ba, 0xaf473800, 0xb8c7ffff, 0x4500ff52, + 0x8269703d, 0x142c274f, 0x3500ff7c, 0x2582cccc, 0x20b00825, 0x830a00ff, 0x000f2225, 0x217f8284, 0xa482e2ba, 0xff230e82, 0x820a77fa, 0x806c2129, + 0xd122fb82, 0x2982707d, 0xcc0c0d2b, 0x22f9ffff, 0x0800ff90, 0x2779827f, 0xffceccf0, 0x9c99fcff, 0x662b8382, 0x2f0e0866, 0x34f814f8, 0x49d4fb15, + 0x69180cd5, 0x23251fb8, 0x088b9a59, 0x203382f7, 0x24098300, 0xa61c00ff, 0x0b1d4466, 0x07d4f722, 0x2306be4a, 0xcc4ce3ff, 0x25081984, 0xb3dcffff, + 0xff088b34, 0x9a99dfff, 0x80defeff, 0xffff1500, 0xff4861f4, 0x289ccdff, 0xfeffff05, 0xfffff45d, 0xb382e0f8, 0xa6bbf927, 0x03fbffff, 0x210e82d8, + 0x3083f6a8, 0x66e68134, 0x99ffff8b, 0x00ff6766, 0x8b9a9966, 0x337e00ff, 0x06820832, 0xf8530736, 0xfb0400ff, 0x0600ffe8, 0x00ff1443, 0xff422007, + 0x48a10100, 0x3220fb82, 0x00235782, 0x8248a10b, 0x580722fb, 0x20158210, 0x222982b3, 0x82388907, 0x20302bf6, 0x0c0300ff, 0xf9ffffcc, 0x2982080c, + 0x1f451727, 0xb8c9ffff, 0x22298252, 0x8210b802, 0xe79b2115, 0x29218b82, 0x2b7c82ef, 0xffff9e8f, 0xff0da0fa, 0x299cfbff, 0xe527b682, 0xffffde0f, + 0x8278e9e9, 0xfd102729, 0xddffff71, 0xd782d863, 0xff66262c, 0x28dce3ff, 0xa12200ff, 0x4f827a48, 0x1e051627, 0xe81a00ff, 0x202582f6, 0x22798304, + 0x82186405, 0x8a812199, 0xdb208382, 0x6326a883, 0xfdffffd6, 0x2982e83b, 0x703d3627, 0xc0e8ffff, 0x22298200, 0x8216ee06, 0x88012115, 0xcc209982, + 0xf8219982, 0x22548266, 0x82ce4cfe, 0x34b32b83, 0xf72f0e08, 0x1594f724, 0x715f84f7, 0xcd4c210e, 0x565f9818, 0x9818bb20, 0x393719fa, 0xff8b0080, + 0x00803100, 0x4fdeffff, 0x1700ff5c, 0xffff9a19, 0x82866bcf, 0x990721ce, 0xf02a0a82, 0xffff3c0a, 0xff3233f9, 0xd283ecff, 0x3433ef22, 0x6623c382, + 0x847b0866, 0xffff2206, 0x21de82ed, 0xe3860600, 0xff089b24, 0x4082f3ff, 0x111b0026, 0xe4ffffec, 0x00265482, 0xff48a112, 0x5649e0ff, 0x76681805, + 0xdcff2209, 0x937f192e, 0x5b8b2907, 0xf8af0e05, 0x1534f894, 0x1639b618, 0xfc076b23, 0x05cb73d4, 0x46592321, 0x7c4205af, 0x82002005, 0x088b280e, + 0xcb0654f8, 0x4c1514fc, 0xfc2116d8, 0x0c024354, 0x32600020, 0x4c233105, 0x54f708cc, 0x06d4f807, 0xfc0754fb, 0xff15cb64, 0x190a986a, 0x61213012, + 0xe4720d6f, 0xff8b220a, 0x6f691800, 0x064b2513, 0x156b14f7, 0x940ec56b, 0x0c197336, 0xa10e306b, 0x2f0e2b97, 0x911900ff, 0x0f01ffec, 0xd28266e6, + 0x0ad7f222, 0x3107734b, 0xffff6f80, 0xff3233f6, 0xfe23ffff, 0xccf2ffff, 0x0a8808ce, 0x00ffcd29, 0xff4b080a, 0x828cf4ff, 0x370d2209, 0x3018828d, + 0xff086626, 0x9a197800, 0x20f8ffff, 0x6900ff00, 0x2c098299, 0xffce2c97, 0x66e60700, 0x1987ffff, 0x271e8298, 0xff92db00, 0x3433f3ff, 0x80213d82, + 0x275c8200, 0x00ffcc4c, 0x8b34b30b, 0x88221a83, 0x78828b04, 0x82dc8721, 0x04082104, 0x88210482, 0x21048230, 0x1a82fc07, 0x52380d22, 0xd8200a82, + 0x0a221482, 0x3082ae07, 0xffaa6f22, 0xd6229282, 0x188200ff, 0xf72f9282, 0x00ff1a84, 0xff342390, 0x991983ff, 0x837c00ff, 0xde6f276e, 0x0900ffb8, + 0x3d82cc4c, 0x156e0622, 0x19211e82, 0x18db829a, 0x20072f4d, 0x153e6d85, 0x16847b20, 0x2208d149, 0x829a19c2, 0x839d2091, 0x8362204e, 0x3dff240a, + 0x710866e6, 0x6c6d0866, 0x4681180d, 0x213f8216, 0xfd8266e5, 0x04824520, 0x99ba0028, 0x1affff9a, 0xed839a99, 0x9a191f25, 0x84c0feff, 0x87dd2294, + 0x275482ae, 0xffb85ee3, 0xcc4ce3ff, 0xdc220a82, 0x66839a99, 0xff240682, 0x48a11c00, 0x3d831682, 0x52782222, 0x06833883, 0x1d00ff24, 0x1b82299c, + 0x82b89e21, 0x6123225f, 0x202d8248, 0x24068200, 0x30e4ffff, 0x2e1682a4, 0xffff52b8, 0x8be1badb, 0x64f80e08, 0x6a1534f7, 0xf3180e33, 0x2b200aee, + 0x2407b076, 0x00801500, 0x581883ff, 0x08220538, 0x2c6a34f8, 0x0a42580c, 0x656aeb20, 0x0fa05807, 0xfb24fb32, 0xffff1514, 0x8b4861ee, 0x9ef1ffff, + 0x0e00ffb8, 0x00230a83, 0x83b89e11, 0x8406829e, 0x82048611, 0x83cc830e, 0x83118506, 0x82388232, 0x832d823e, 0x21448245, 0x49859a99, 0x66eeff27, + 0xeb088b66, 0x225edc8b, 0x4114f8bb, 0xff3f1a29, 0x9a993fff, 0x0d00ff07, 0x00fff668, 0xff9a190a, 0x8f821000, 0x4c0600ff, 0x1200ffcc, 0x418b7b14, + 0x12230531, 0x838b7a14, 0xff902519, 0xfabef9ff, 0xff292d85, 0x0810d8f5, 0x68c000ff, 0x173941f6, 0x74f80e28, 0x660c01ff, 0x4a821566, 0xf722f283, + 0x3a823433, 0xff66662a, 0xcc4ce8ff, 0xe4ffff8b, 0x82057273, 0xffff2206, 0x822083f2, 0xffff2216, 0x822083ed, 0xff08252a, 0x66666cff, 0xff215b82, + 0x219682f3, 0x3c82f8ff, 0x4cf4ff25, 0x82867fcc, 0x19f42518, 0xfbffff98, 0xf2201683, 0x002d1682, 0xff34b302, 0x66e6f6ff, 0x330900ff, 0x2d1e8232, + 0xffce4cd4, 0x00802c00, 0xffbb5b05, 0x1783beff, 0x2b831a20, 0x9919bc23, 0x231d828b, 0x06cd4cf7, 0x19c47119, 0x830f1857, 0x110027a9, 0xf70834b3, + 0x274c0714, 0x34b3290d, 0x2300ff8b, 0xeb08cc4c, 0x0883a482, 0x08c89e18, 0x2322e682, 0x6b829a59, 0xb3880029, 0x00ff0633, 0x8267e643, 0x19412f2a, + 0xffbba69a, 0xe2fa2f00, 0x2b00ff08, 0x048232b3, 0x05a2a522, 0x2c05295d, 0xc8260900, 0xcc0d00ff, 0x0200ffcc, 0x220482bc, 0x8268e60b, 0x080c23e0, + 0x06849708, 0x0700ff22, 0xff291a82, 0x8b7c54f4, 0x0ff3ffff, 0x061b415c, 0xe8feff22, 0xf325f983, 0xff159a99, 0x24d683ff, 0x00ff072b, 0x22728408, + 0x82cdcc4f, 0x834c2072, 0x33e2211e, 0x3a208f82, 0xca283f83, 0xff080080, 0x98990601, 0xc520c982, 0xff201582, 0xff261082, 0xcc4cb3ff, 0x2483ffff, + 0x33b0ff3a, 0x8b088b33, 0x94f70e07, 0x8a8a01ff, 0x00ff153e, 0xff9a192c, 0xf2322e00, 0x0627a682, 0x00ff66e6, 0x821c3a06, 0x22148361, 0x820a7702, + 0x233a83ba, 0x0820c0fd, 0x66261482, 0xfdffff66, 0x238222c0, 0xff008026, 0x9663f9ff, 0x2882ca82, 0x94f7ff23, 0x201e8238, 0x2a3d820f, 0x0080c1ff, + 0x00ffc905, 0x82ae8711, 0x6608224f, 0x22218268, 0x82942a5c, 0xf6a82136, 0x19213682, 0x21368298, 0x2c8228dc, 0xce4c0522, 0xd9200a82, 0x03227a82, + 0xd9823233, 0x828e0221, 0x9a992123, 0xa3210982, 0x20fa82d8, 0x226083ee, 0x8270fdc1, 0x833e2044, 0x19f0220a, 0x834f849a, 0x83a48480, 0x82f9202a, + 0x02002119, 0xf7224883, 0x53829a99, 0x83053655, 0xb3fc2119, 0x28825383, 0x84faff21, 0x82192028, 0xd1ff241e, 0x825ecccc, 0x332e2744, 0xd3ffff34, + 0x0a8266e6, 0xd0830520, 0xc182f920, 0x84030021, 0x27308345, 0xffccccfd, 0x34b3f6ff, 0x8207ed64, 0x84a8825a, 0x206e8228, 0x220e84ff, 0x8266e6fd, + 0x21ea821e, 0x9885ffff, 0x00801123, 0x204f824d, 0x21268302, 0xe48299f7, 0xceccfc26, 0xfaffff82, 0xf9228683, 0x2c8268e6, 0x0f840582, 0x1b821582, + 0x2582e682, 0x2f820020, 0xff4d0823, 0x203d8200, 0x21498405, 0x5382ffff, 0x5f820a82, 0x9a202183, 0x2006aa4c, 0x825685f9, 0xb3fd220e, 0x07b75e32, + 0xf720a784, 0xbb85b182, 0xcf82c584, 0xdb821e82, 0x8200ff21, 0x5e0522e5, 0x82f383ff, 0x411c834f, 0x30830509, 0x1d41ff20, 0x9a992505, 0x330200ff, + 0xf722e783, 0x0a829999, 0x85ce4c21, 0x0600216e, 0xff271982, 0xff67e6fd, 0x83660800, 0x19f027e7, 0x3e00ff99, 0x48820080, 0x71fdc125, 0x84eeffff, + 0xa3f7220a, 0x07b141d7, 0xff8f0226, 0x32330300, 0x2206cf41, 0x82ce4c05, 0xdcf92284, 0x06ef4129, 0xf6a8fd23, 0x205e8294, 0x230f825c, 0x08686608, + 0x8722ee82, 0x4b83c9ae, 0xff008026, 0x66e60f00, 0xf7220a82, 0x21823994, 0xe0821920, 0x9563f922, 0x22065d42, 0x8727c0fd, 0xc0fd2280, 0x0587421a, + 0x77020023, 0x069b420a, 0x1d3a0622, 0xe6202882, 0x00289f82, 0xfff2322e, 0x9a192c00, 0xd1234882, 0x82b80ecd, 0xc5f92206, 0x821c84e3, 0xf68821a0, + 0x02223086, 0x4f86e63f, 0x3f020023, 0x820a84d9, 0x6b9c2123, 0x00236e85, 0x84c76b08, 0x84082082, 0x229887ea, 0x825278ee, 0x9002210f, 0xfd205382, + 0x0023ef82, 0x73285c08, 0x00230564, 0x8272fd08, 0xd7232139, 0x26200482, 0x06228483, 0x0a826626, 0x82d82321, 0x71fd2158, 0xf3822387, 0xa3fdff23, + 0x235383d6, 0xffff8f02, 0x05204d82, 0x67205983, 0x0a826384, 0x99190222, 0x6b212f82, 0x228386c8, 0x826a9c06, 0x8266200e, 0x3f02221e, 0x066f43de, + 0xe020ac82, 0xff21c185, 0x2bcb83fd, 0xff66e606, 0xe4c5f9ff, 0xffffb808, 0x0526ed82, 0xf774f70e, 0xd8471514, 0x0c064809, 0x21056b5b, 0x46568b86, + 0x7c501805, 0x86ab2113, 0x4f211b82, 0x219b825c, 0x8d567a54, 0xc97d1806, 0x0a137b08, 0x2b00ff2c, 0x15cb9a99, 0x665400ff, 0x2e480666, 0xb0112519, + 0xf1ffffa4, 0x3b23538d, 0x82076306, 0x80f7329e, 0xfeffff00, 0xff83cc4c, 0xce4cfdff, 0x80f8ffff, 0x26e18200, 0xeb666604, 0xae64f715, 0xffff2252, + 0x05c1552f, 0x82cc4c21, 0x0a57214d, 0x2206ca5e, 0x822a5cfd, 0x4cfd2968, 0x075308cc, 0x1594fbbb, 0x8d087874, 0x0dfd4590, 0x41148a76, 0xb3201144, + 0x1807ae78, 0x3a0a445a, 0x198affff, 0x3c00ff9a, 0xff153433, 0x66e6f9ff, 0x330a00ff, 0x00ff8732, 0x6ace4c0c, 0x06820697, 0x18c4052c, 0x140100ff, + 0x0500ff7b, 0x09825879, 0x82146e21, 0x5c4f3009, 0xdaffff08, 0x00ffd7e3, 0xff9ad902, 0x8299e2ff, 0x841e2046, 0xe6252962, 0x00ff0866, 0x0766e648, + 0x07203b82, 0x07205383, 0x0d799318, 0x0700ff24, 0x1b8267e6, 0xff234082, 0x18ccf8ff, 0x200710a2, 0x056747f8, 0xae47ba29, 0xffff8b05, 0x82b99eef, + 0x25388286, 0x9919e6ff, 0x3b6c00ff, 0x08756a06, 0x3f829c20, 0x08220c82, 0x658314f7, 0x136e4c18, 0xc0ffff2a, 0xff069a99, 0x66e6deff, 0xe02e4e82, + 0xff7bae87, 0xa470ecff, 0x33e5ffff, 0x05820834, 0xffcd8c27, 0x9899dbff, 0x2c6a8205, 0xffff4616, 0xff34b3e8, 0x9ce4f6ff, 0x222c826f, 0x823333e3, + 0x4ca72221, 0x7ce618cd, 0x3c002107, 0xff22e882, 0xe38219c3, 0x291c4b23, 0x2dde828b, 0x0648e120, 0x85faffff, 0x0900ff1e, 0xe9566666, 0x0a002105, + 0x00246a83, 0x0834b30b, 0x1b2b9d82, 0xff9d66e6, 0x00801700, 0x831800ff, 0xcc082738, 0xf70e08ce, 0x9359f794, 0x827b2007, 0xabf12168, 0x4323094b, + 0xbb822102, 0x2a05ea5d, 0x8bcc4cee, 0x15c37b08, 0x5e3b07b3, 0xcd221c1a, 0x405500ff, 0x33b32105, 0x22086e4b, 0x82f66854, 0x4afd2533, 0x0700ff3d, + 0x2105e942, 0xc78293cd, 0x00800827, 0x14f78b08, 0x200a8215, 0x20678302, 0x271b8200, 0xd6a30200, 0x4c0000ff, 0x02284682, 0xff08f6a8, 0x33332fff, + 0x430cc95c, 0xe6820a77, 0x6f889582, 0x6f863420, 0x0664f728, 0xfb7b07c3, 0xdda115ec, 0x822ffb42, 0xf1ff2396, 0x6882a4b0, 0x8b33b326, 0xab14f708, + 0xff3fbb82, 0xffae47f4, 0x769efcff, 0x2bf5ffff, 0xfaffff86, 0xffff8480, 0x08cc8cf6, 0xe12000ff, 0x18ff0606, 0x180abbe7, 0x250a4de8, 0xb35800ff, + 0xf9820733, 0x8fc21c22, 0xe4252e82, 0x1c00ff9c, 0x08478207, 0x4616ef23, 0x451700ff, 0xffff0820, 0xffcc8ce5, 0xf4682400, 0xebffff05, 0x00ffec91, + 0xff7cd41a, 0x6666e1ff, 0x0579429b, 0x86422182, 0xe8e92805, 0xffff8bf6, 0x180a17ee, 0x490ba54f, 0x1a8205df, 0xe821ab82, 0x271982f6, 0x00ff70fd, + 0x8ba43015, 0x1c229682, 0x7882e2ba, 0x1e450b22, 0xb8215382, 0x210a8252, 0x4b618f0f, 0x45002407, 0x430552b8, 0x3422095c, 0x511900ff, 0xf8221c04, + 0x86829a19, 0x9a19b722, 0xff28c982, 0xff4821da, 0x66a6e2ff, 0x4720a482, 0xda21c982, 0x229082d7, 0x82d623fd, 0x68012170, 0xfa2d8182, 0x00ff68a6, + 0xff9a1901, 0x9899faff, 0x2205828b, 0x82083433, 0xb8f23606, 0xfbffff52, 0xfffff8f3, 0xff14aef3, 0xb613f9ff, 0xc5f5ffff, 0x3135821e, 0xffec1118, + 0xe23af7ff, 0xe61200ff, 0xe8ffff66, 0x324b0080, 0x2f0e2606, 0x34f7b4f7, 0x21d98215, 0xab82a4b0, 0x5c4f0e24, 0x961800ff, 0xcb2009f3, 0x4107be61, + 0x0e2205a9, 0x56187c54, 0xae5c149c, 0x824b2008, 0x42ff202f, 0xbd180547, 0x4b250d31, 0x992b00ff, 0x05d6459a, 0xb32053a5, 0x07835f18, 0xb3073b26, + 0x0800ff06, 0x9325b182, 0x4cfeffff, 0x06f742cd, 0xcd4cfd2c, 0x00ff2b08, 0x15666604, 0x528564f7, 0x984e8620, 0x95bf8206, 0x07f25ca6, 0x2fffff2a, + 0xff073333, 0xf6a80200, 0x21071f43, 0xdb459a99, 0x02002b05, 0x088b71bd, 0x94f706c3, 0x571815bb, 0xab220d1d, 0x10828b85, 0x087b5422, 0x5421e485, + 0x06cf467a, 0x86abf122, 0x14015818, 0x41080463, 0xb3200544, 0x2106645e, 0xc2820e00, 0x4ceeff2c, 0xff088bcc, 0xccccc3ff, 0x678209fb, 0xceccf522, + 0x2305d845, 0x32b3f3ff, 0x21078c4c, 0x228334b3, 0xe83bfa22, 0xfa2c7782, 0x00ffa886, 0xff7a1401, 0xa4b0faff, 0x6e210982, 0x2c3d8216, 0xff6626fd, + 0xd6e3daff, 0x4ce1ffff, 0x05dc45cc, 0x52daff21, 0xb725050c, 0xff069919, 0x689918ff, 0x00ff252b, 0xff53b845, 0xfa310082, 0x0f00ff05, 0xff8b1f85, + 0x8fc21a00, 0x4a0b00ff, 0x230a823e, 0x08c2b51c, 0x16220682, 0xf682a019, 0x09aeeb18, 0x8214fb21, 0x0b334365, 0xff377d82, 0x66e6e9ff, 0xc0ffff08, + 0x8b070a97, 0xdedeffff, 0xffff9bb8, 0x82ec91e0, 0x5ccf314f, 0x6eecffff, 0x00ff0814, 0xfff66824, 0xcc8ce5ff, 0x17286b82, 0xffffae47, 0xa70c17ef, + 0x2206754d, 0x82cdcc1c, 0x580029f7, 0xff0633b3, 0x281c4b00, 0x3c247682, 0x00ffd8e3, 0x0a820482, 0x3e821082, 0x48e12023, 0x212e8207, 0xdc459a99, + 0xf5ff2205, 0x20098219, 0x200e83fc, 0x055841f4, 0x8884e420, 0x0080e822, 0x2f06f042, 0xff3233f7, 0x9a191800, 0xf72f0e08, 0x1554f794, 0x4635c341, + 0x25450607, 0x18ee2006, 0x5e11a559, 0x532508a0, 0x0663157b, 0x09065b3b, 0xf9824f20, 0x24202842, 0x665400ff, 0x20d78266, 0x3ab682f8, 0xce4cfdff, + 0xfeffff83, 0xffffcc4c, 0x8b0080f7, 0x8b14fb08, 0xfdffff15, 0x828b8f42, 0x66662105, 0x2305ad42, 0x0a57fdff, 0x4c270982, 0xffff08cc, 0xae34332f, + 0x64f7286f, 0xf7065307, 0x42157bec, 0xdda005a1, 0x4e2f0143, 0x230808ed, 0x1514f76b, 0xb80b00ff, 0x00ff8b52, 0xff7ad40a, 0x789efcff, 0x730900ff, + 0xfaffff34, 0xff088280, 0x06e12000, 0x0024bb82, 0xff281c4b, 0x2805bf47, 0xffd8e33c, 0x66e6b4ff, 0x2bd8828b, 0x8bcd4ca7, 0xe3ffff05, 0x6f8b3333, + 0x2805de45, 0x33b3e8ff, 0x16efffff, 0x221d8246, 0x42299cdb, 0xff320649, 0xffa430e5, 0xa470ecff, 0xe0ffff7b, 0xff8bae87, 0x8842deff, 0x9a992105, + 0xff235c82, 0x4566e6e9, 0x192607bf, 0x1600ff9a, 0x4b7e0a17, 0x82098306, 0x90022119, 0xa2821e84, 0xa4301523, 0x22068208, 0x82e2ba1c, 0xae472159, + 0x4526b982, 0xf0ffff1e, 0x8d83a470, 0xae47ba22, 0xf8298d83, 0x00ff9919, 0xff66e600, 0xc79c18ff, 0x00ff2a25, 0x0667e648, 0xde2500ff, 0x225a82b8, + 0x4552b81e, 0x003305de, 0xff2adc02, 0x0ad7daff, 0x0500ff08, 0x00ff9859, 0x82f66801, 0x45662009, 0x002306de, 0x82cccc05, 0x0d002174, 0xff247482, + 0xec510c00, 0x2205de45, 0x823a0a00, 0x13f9229a, 0x343582b6, 0xff1ec508, 0x52f81800, 0x801700ff, 0x00ff9d00, 0x8b66e61b, 0x23681808, 0x14f72961, + 0xff15b4fb, 0xcd4c4dff, 0x3128d482, 0xffff4861, 0x05b89ece, 0x7f22a382, 0x2e7affff, 0x1801200d, 0x2008f8b7, 0x250a8580, 0xbfebffff, 0x15848bff, + 0x0805b75d, 0x97ffff21, 0x00ff51f8, 0x05ae0768, 0x0700ff83, 0xffff66e6, 0xff9999fe, 0xcecc0900, 0x0400ff8b, 0x830866e6, 0x0ce22606, 0x640100ff, + 0x26168219, 0x00ffeac6, 0x82cb0108, 0x70fd272a, 0x6700ff08, 0x04849a19, 0x1e944218, 0xcf279899, 0xffff508d, 0x820080cf, 0xb3b22240, 0x20cf8233, + 0x080b4711, 0x42f1ff21, 0xf66608f4, 0x616a4116, 0x9600ff2f, 0xfeff9a99, 0x156666e9, 0xe698ffff, 0x7d048466, 0x51651b64, 0x0c607b0d, 0x3000ff24, + 0x0482cc8c, 0x82347321, 0x684d2040, 0x714c0e99, 0x082d790a, 0xff5c4f22, 0xe1461683, 0xccb22d08, 0xffff06cc, 0xffb89ece, 0x48613100, 0x24365b7b, + 0x196700ff, 0x2cc6869a, 0x7cd40800, 0x2bf7ffff, 0x0100ff85, 0x26db8266, 0x8b3333f6, 0x4cfbffff, 0x06820565, 0xfeffff22, 0xff27fd82, 0x833233f6, + 0x82f8ffff, 0x63704116, 0x72837e20, 0x15208e82, 0x2b1ccd7d, 0xff66a6ce, 0xcd4c3100, 0x4dffff05, 0x2005854c, 0x07e745ee, 0xb0f1ff23, 0x06ea4ea4, + 0x0d1b6b18, 0x4e5c4f21, 0x0829052c, 0xb3b200ff, 0xffff0733, 0x226a83ce, 0x4133b3ce, 0xfe4238d0, 0xd9082c0a, 0x0800ff99, 0x00ff9ad9, 0x41cdcc09, + 0x0024054f, 0x8b66e604, 0x04226c82, 0x78828ae1, 0xdcc4092d, 0x9bfeffff, 0xffff93e8, 0x4334fef7, 0xff2e063b, 0x0567e698, 0x590d00ff, 0xf2ffff9a, + 0x64181799, 0x6d1811ab, 0xff276091, 0x9a997e00, 0x42d1feff, 0xf7220fe1, 0xa8823433, 0x97821920, 0x3233f622, 0x20060842, 0x05e048fb, 0x771efb22, + 0xf622a882, 0xe682233b, 0x83186422, 0x012cf682, 0xffff08cc, 0xffcc0c98, 0x82006800, 0x21389842, 0x6d825931, 0xce8cce26, 0xb200ff05, 0x0f086418, + 0x5c4f0e22, 0x2308864d, 0x8b84ab11, 0x22069f6c, 0x51a4b0f1, 0x7f820515, 0x34334d28, 0x3100ff07, 0x04844861, 0x201e9144, 0x052e6c80, 0xffffff29, + 0xffff52f8, 0x42ead1eb, 0x0826096d, 0xf7f4f70e, 0x57821554, 0xc618e920, 0xea2008f1, 0x20052d53, 0x212a8268, 0x6b829a99, 0x9999462d, 0xfdffff06, + 0x00ff66e6, 0x83666614, 0xff672509, 0x66661500, 0x16239782, 0x84083433, 0xff332506, 0x99190200, 0x1b821683, 0x9a190222, 0x08262a84, 0x66b900ff, + 0x1a830667, 0x4c849820, 0x0100ff29, 0xffff3433, 0x849999ea, 0x82cd2070, 0xe6972920, 0xff15cb66, 0xce4c0500, 0xa8822182, 0x83020021, 0x83828287, + 0x66e62121, 0xff215d82, 0x217982e9, 0x3885fdff, 0x54ff9a21, 0xeb280582, 0xff080080, 0x66e684ff, 0x6e835d84, 0x0021b482, 0x22788301, 0x82cc4c16, + 0x19152892, 0xa18b089a, 0x82feffff, 0x87ac833c, 0x08d183c0, 0x197b0024, 0xffff069a, 0xab0080f5, 0x8bffff15, 0x8106ce4c, 0xdc3f00ff, 0xecffff28, + 0x00ff3233, 0xff208535, 0x8b83e6ff, 0x922d2222, 0x4e20a282, 0xeb22f483, 0x23821c5a, 0x7f829920, 0x6626c72f, 0xb5ffffa9, 0xff08a4f0, 0x66e66aff, + 0x2042828b, 0x20e5844f, 0x207d8306, 0x212c8224, 0x04830900, 0x52382025, 0x830b00ff, 0x071a2246, 0x204682ae, 0x220a830a, 0x822a9c17, 0x33b32614, + 0x211100ff, 0x26098248, 0x00ffcd4c, 0x82cccc0a, 0x330b211e, 0x0a251482, 0x00ffcaa1, 0x28148309, 0xff922d03, 0xcd4c0700, 0x201a828b, 0x27d18407, + 0xffce4c09, 0x6ed2fcff, 0xa5823582, 0x5ef5ff23, 0x201a8236, 0x2214830b, 0x823433f5, 0x32b32614, 0xdeeeffff, 0x824f82b8, 0xe8ff2368, 0x1e83d663, + 0xe5210a83, 0x398882f8, 0xff686609, 0xaec7dfff, 0x190600ff, 0xdbffff98, 0x8b089a99, 0xbafeff06, 0xc0825c4f, 0xfa1d0028, 0x4a00ffe1, 0xe2825c0f, + 0xff299c30, 0x9ad93800, 0x664e00ff, 0x1400ff67, 0xe682e4a5, 0x4683e620, 0x7a82dd20, 0x82ecff21, 0xcaff29a5, 0xff81e07a, 0xd823c0ff, 0x8b2a1a82, + 0xff065c4f, 0x0a977000, 0x1942156b, 0xebff2105, 0xff22fc82, 0x0082fffd, 0x9a99ea34, 0x8b08758b, 0xe6eaffff, 0x0200ff66, 0xffff0100, 0xaa82b3e9, + 0x99190227, 0x66ebffff, 0x273e8266, 0x0671dd84, 0xbcfaffff, 0x14207482, 0xfd206483, 0x5b425f82, 0x82192007, 0x00ff23a2, 0x8b821916, 0xcdcc0223, + 0x241683ff, 0x430500ff, 0x219582d7, 0xdc820080, 0x8f227b22, 0x3f207a82, 0x42453683, 0x80f42705, 0xffffa500, 0x308299f6, 0x34332022, 0x2105e84c, + 0x67832400, 0x99b00023, 0x22678299, 0x8468e6f9, 0x272483fa, 0xdfffff98, 0xffffcccc, 0x71203482, 0x22070964, 0x82ce4ce8, 0x20048310, 0x28b182ee, + 0x32b3f4ff, 0x33f5ffff, 0x211e8232, 0x1982ccf4, 0x8266f521, 0x83f6203e, 0x83fc2014, 0xccf72339, 0x1a828bce, 0x9999f922, 0xf625e282, 0x00ff33b3, + 0x20758303, 0x22ab83f4, 0x8298990a, 0x83f4201a, 0x830a2014, 0x4cf4213a, 0x1120c082, 0xff21ca82, 0x32af82f5, 0x32b31700, 0xff068b08, 0x67e6fbff, + 0xffff1552, 0x829999b1, 0x34b325d4, 0x63c0ffff, 0x3820de82, 0xe2275d83, 0x00ff1f05, 0x829a194a, 0xb07424e8, 0x829506a4, 0x213e821b, 0x5d821300, + 0x83caff21, 0x82192043, 0xddff2f04, 0x8b08cccc, 0x8200ff07, 0x158bcccc, 0x138300ff, 0x82220021, 0x2b278285, 0x3500ffce, 0xff950080, 0x66e63f00, + 0xb3264483, 0xff6d0632, 0xd883b5ff, 0x6666c025, 0x82c7ffff, 0x24798226, 0xebffff9a, 0x2a44834c, 0xfb01ff0e, 0x01ff9a99, 0x82343345, 0x18fd3692, + 0x0c00ff94, 0xffff0817, 0xff6ca7f0, 0x3e0a0400, 0x35f7ffff, 0x200483c2, 0x21148240, 0xac8273b3, 0xa470b326, 0xacffff05, 0x002f5182, 0x050d0000, + 0x5300ff8b, 0xff059919, 0x828c4c00, 0x8f4c227b, 0x270a825c, 0xff80ca08, 0xfcc90800, 0xf520ea82, 0x0f2a0982, 0xffffdc59, 0xfffce9f3, 0x94830200, + 0x4fe8ff3c, 0x0500ff5c, 0xffff68b1, 0xff9a59e6, 0x026b0000, 0x6be5ffff, 0xf9ffff86, 0x6582fea3, 0xcd8cc22b, 0x4cf1ffff, 0xd0ffffce, 0x2c09820c, + 0xffcccccb, 0x3333f6ff, 0x99c1ffff, 0x221e829a, 0x82c4cbfa, 0xfa112138, 0x80214d82, 0x25098200, 0x00ff9819, 0x2882cc07, 0x1e84e820, 0x98824d20, + 0x0482ff20, 0x07a47a18, 0x48e1e338, 0xd2ffff8b, 0x00ff146e, 0xffb81e1c, 0xd8e3e3ff, 0x0d00ff08, 0x6382f628, 0x002e2a82, 0xff676612, 0x9a19f8ff, + 0x8a1100ff, 0x1a828b3d, 0x3e8a1122, 0x1322d382, 0x5682cd4c, 0xfff00726, 0xeb110e00, 0x0f210482, 0x271a821a, 0xff9919b2, 0x9a19b200, 0x1722e282, + 0x3682c275, 0xff96432a, 0x9ad91900, 0x7efdffff, 0x1a278f82, 0x00ff28dc, 0x826a3c04, 0x683e3129, 0x0900fff6, 0x00ff0ad7, 0xffa43034, 0xc2f52f00, + 0xb3364382, 0x3d00ff32, 0xff086766, 0xbc1e0800, 0x831b00ff, 0xffffff95, 0x42829899, 0x42829920, 0xf182fa20, 0x2805bb69, 0x666654fe, 0xccb2feff, + 0x8ba618cc, 0x9042261b, 0xc00a00ff, 0x21048200, 0xa61870bd, 0x4221148b, 0x23f78290, 0x0870bdf2, 0xb3210683, 0x06dd6434, 0xcc4cf52d, 0xc0f2ffff, + 0x0e088b00, 0x829800ff, 0x990124f6, 0x82150ad7, 0x82cc20ab, 0x21f72f17, 0x0000ff48, 0xffffcdcc, 0xff7ad4f0, 0x1e82f7ff, 0x23f6ff34, 0xffff08d8, + 0xff3d0ab8, 0xc2f5afff, 0xfbffff05, 0x04820a97, 0x50823320, 0xaec7f922, 0x2483f982, 0x856bf922, 0xb3213882, 0x83298232, 0xfeff2b0a, 0xffff66e6, + 0xffd7a3f9, 0xda830200, 0x0a57fb27, 0x800500ff, 0x231e8200, 0xb3beffd7, 0xf6224482, 0xf618c5a0, 0x5f210d66, 0x2283823b, 0x8308b85e, 0x84fa2005, + 0x00ff230a, 0xc819330f, 0xa1210975, 0x321a8248, 0xff291c16, 0x14eee9ff, 0x3700ff05, 0x00ffb81e, 0x82f6283d, 0x8208200a, 0x090023b0, 0x30849ad9, + 0x2305c178, 0x67e60900, 0x2124bf82, 0x078b0848, 0x5f22fe82, 0xe288c3f5, 0x87333321, 0x863682e2, 0x991921e2, 0x3b20e285, 0x6621dedd, 0x21de8866, + 0xde8dcd4c, 0x8833b321, 0x66e621de, 0x3321de88, 0x21de8834, 0xde88cccc, 0x86ffce21, 0x2bb682de, 0x00ff078b, 0xff66e647, 0x33336600, 0x0aa75018, + 0x0d119c18, 0x46187420, 0xff6f0e17, 0xcc4c260c, 0xb3f1ffff, 0x25048634, 0x8bcc4cee, 0x3082fb08, 0x5c72ff20, 0x078b2414, 0x8434fb8b, 0x18b32067, + 0x8f125245, 0x0f506f67, 0x4b2067a9, 0x73186587, 0xf721114b, 0x18cd8eb4, 0x900f3c68, 0x95308265, 0x34fb22cd, 0x07ea798b, 0x7d15002f, 0x1500ff71, + 0x00ff0080, 0x8b8f821a, 0x21068308, 0x82188b90, 0x4c1809f5, 0x82240fa8, 0xeaffff8f, 0xff232d82, 0x82707de5, 0x2006822d, 0x20228271, 0x611682ea, + 0x28080aa7, 0x0300ff0e, 0x01ff5eda, 0x15482189, 0x9d0600ff, 0x0d00fff4, 0x00ff52f8, 0xffec110e, 0x66e60800, 0x750f00ff, 0xf8088bc3, 0x24d18244, + 0x8b00800f, 0x05724399, 0x2205b85c, 0x82ae07f2, 0xb3062485, 0x82ffff32, 0xffff370a, 0xff68e6fd, 0x5278efff, 0x66f5ffff, 0xf4ffff66, 0xff083c0a, + 0x448249ff, 0x6e20ff26, 0xffff0516, 0x077fbb18, 0xf9221183, 0x21823433, 0xf5270983, 0xffff9819, 0x829a99fa, 0x83f5202b, 0x250a8214, 0x0100ff7e, + 0xf7639a19, 0x4c072206, 0x231a82cc, 0xbb0100c0, 0xf72b4282, 0xff9166e6, 0xcd4cfbff, 0x820900ff, 0x00ff238e, 0x3882190a, 0x194f0024, 0x6a82079a, + 0xffc00a26, 0xea91df00, 0xf6272782, 0x00ff8736, 0x82c4f50b, 0xe1fa2694, 0x871000ff, 0x21dd82ae, 0xdd84779e, 0xff2b4d82, 0x058bbeff, 0xf7d4f70e, + 0x828b1504, 0xf02726d1, 0xd8f8ffff, 0x26048610, 0x8bf027f7, 0x65062b08, 0x4e650bb5, 0x07bb270a, 0xfb0654fb, 0x37820724, 0xe582e620, 0x6816002d, + 0xe9fffff6, 0x00ff9a99, 0x610a9719, 0x098306e0, 0x1984ff20, 0x8b200483, 0x08221a84, 0x398324f7, 0xf7075b29, 0x1584f724, 0x82bb063b, 0x86328341, + 0x8246843c, 0x088b2350, 0x7a8234fb, 0x19850983, 0x82e9ff21, 0xffff2856, 0x08f668e6, 0x833b075b, 0xf668211a, 0x15827b82, 0x86851f84, 0x04fb0828, + 0x0694f807, 0x548404f7, 0x91858c82, 0xa0821620, 0x5485ff20, 0x158b1422, 0xbb265882, 0x0634f707, 0x7418075b, 0xf93008a5, 0xfffff833, 0xffe81bfd, + 0x5a84f9ff, 0xf3faffff, 0xfb2b0e82, 0x3b08a470, 0xffff0543, 0x82ba89fb, 0xa4f02104, 0x33211782, 0x05a64a32, 0x33faff2a, 0xff088b34, 0x20b0fcff, + 0xfc277882, 0x00ffe0af, 0x8200b000, 0xe8db260f, 0x630100ff, 0x271a82f8, 0xffb25df7, 0x6ed20300, 0x7d823582, 0x99080023, 0x2aff829a, 0x08008009, + 0x062b07b3, 0x82b3072b, 0x56002731, 0x0900ff05, 0x1882e87b, 0x74930822, 0x6c212882, 0x26328208, 0xffff2adc, 0x8a1659f7, 0xffff290a, 0xffd663fe, + 0x3cdff5ff, 0xac209f82, 0xf8255b82, 0x430834f3, 0x219a833b, 0x36823e75, 0x826cf521, 0x82802017, 0x19fd277e, 0xf8ffff9a, 0x9a83ce4c, 0x1b820683, + 0xff846b26, 0xd8e30200, 0x7026c082, 0x0500ffa4, 0x3e82080c, 0x66e6b823, 0x203c82db, 0x224a82f9, 0x820c0700, 0x63fe2710, 0x0a00ffd7, 0x7d837e1f, + 0x00ff2925, 0x84f4a808, 0x820a857d, 0x7b94210f, 0x91213a82, 0x21ac82ee, 0x5b82e17a, 0x19270024, 0x0082ff99, 0xbe82aa20, 0x1a016028, 0xa0ffff07, + 0x735de4e5, 0x84f62205, 0x23c78518, 0x8c6cf7ff, 0x1725c783, 0x23fcffff, 0x226382d6, 0x827ad4fc, 0xba9e21c7, 0xb3210f82, 0x213c8233, 0x0984cc4c, + 0xff244e82, 0x8b2130fa, 0x40213582, 0x21aa8283, 0xaa82e81b, 0x0021cb82, 0x21aa8204, 0xa682d33b, 0x75f3fa30, 0x8b0400ff, 0xfdffff44, 0x00ffe71b, + 0x4d198006, 0xe42110d9, 0x21168219, 0xde84e27a, 0x8f232a82, 0x82db085c, 0x07002338, 0x1782df0f, 0x822a5c21, 0x9a1924da, 0x830100ff, 0xb3082255, + 0x21768234, 0xdf823233, 0x9a990822, 0x34200a83, 0x09833682, 0x6666f722, 0xf62c8482, 0x63080080, 0x5f00ff07, 0xeb069a19, 0xd827d882, 0x00ff66e6, + 0x82540000, 0x84f62287, 0x22208219, 0x828b6cf7, 0xf8932130, 0x23263a82, 0x0800ffd7, 0xdb83eaa6, 0x64820a86, 0x827b9421, 0x7020216e, 0x66207882, + 0x07223982, 0x6982cc0c, 0x99194729, 0x00ff05db, 0x82002009, 0x0a17261b, 0x6f1100ff, 0x2a45825c, 0xff482109, 0xf6e8f5ff, 0x823bd308, 0x5306211d, + 0xf8225382, 0x4382f8f3, 0x82289c21, 0x84e02117, 0xd8256283, 0x57f7ffff, 0x84628408, 0x6d0c200a, 0x6e2a07bc, 0xf6ffff14, 0x088b1e85, 0x0082ff63, + 0x9f82ac20, 0x5400a022, 0x6025b882, 0xb3061eda, 0x215d8307, 0xa885e87b, 0x93080023, 0x25a88474, 0xdc0300ff, 0x0a820828, 0x82f0a721, 0xe0cf210a, + 0x1d378c82, 0xfeffff2e, 0x00ff3a74, 0xff5c0f07, 0xeea7f9ff, 0xffffdb08, 0x820100b8, 0x0a052c8f, 0xfbffff3e, 0x00ff4075, 0x8266e602, 0x0080211b, + 0xf932fd82, 0x0e083333, 0x3f01ffef, 0x14f766e6, 0x3900ff15, 0x6a82f668, 0xa4b02d26, 0x8f2e00ff, 0x3923d383, 0x8208a470, 0x24068211, 0x75d1ffff, + 0x221684c2, 0x55c7ffff, 0xc6220531, 0x43820a97, 0x824fd221, 0x82d1206a, 0xffff2411, 0x825c8fc6, 0x19ff22da, 0x210a829a, 0x2c829a99, 0xff230482, + 0x826666d1, 0x66662f58, 0x6bbd088b, 0x9cffff15, 0xff063433, 0x7e84b1ff, 0x1a82c020, 0x4cc4ff23, 0x234582cc, 0x086866b6, 0xf12a0682, 0x00ff3233, + 0xff33b30c, 0x4582f4ff, 0xb30f0028, 0xff088b33, 0x33834701, 0x32200c82, 0x0c248a82, 0x00ff34b3, 0x0c281b19, 0x98994924, 0x4a83ffff, 0x823b0021, + 0x275a841b, 0x8e00ff08, 0x54f79a19, 0x2c22d282, 0x3582142e, 0xecd12324, 0x048200ff, 0x10820a82, 0x00206982, 0xff230682, 0x8233dcff, 0x2416824c, + 0xccd3ffff, 0x236982cc, 0xecd1d3ff, 0xdc228582, 0x1b82142e, 0x82096b6b, 0x213f841e, 0x1684cccc, 0x2c00ff24, 0x2d823433, 0xe6b7fe25, 0x82155366, + 0x72052c52, 0x0000fff2, 0x00ff7ffb, 0x82562e05, 0x68a02109, 0x47270982, 0xffff08ae, 0x824d17f5, 0x70fd210a, 0x02201a82, 0xff21d082, 0x05c558f3, + 0x152ec228, 0xcfffff06, 0x6c82295c, 0x5c8fd827, 0x33d6ffff, 0x220a8233, 0x820180cc, 0xf5ff329a, 0x00ff32b3, 0xff12e307, 0x9a99f7ff, 0xbb0900ff, + 0x236c82a6, 0x0080c700, 0xeb253382, 0x00ff7b94, 0x27888317, 0xff3333f3, 0x01801e00, 0x21297f82, 0xff0833b3, 0x9a19c8ff, 0x82f0a1c3, 0x20f08634, + 0x18f085cd, 0x6c07834e, 0xf0870b5c, 0x1683f582, 0x2e21f082, 0x302d8215, 0x68e6a701, 0xffff156b, 0x06f628c2, 0x33f3ffff, 0x27b38234, 0xff84ebf3, + 0x87f6fcff, 0x052ceb82, 0xfaffff1e, 0xff0808cc, 0x98990000, 0xbd220a82, 0x05828c71, 0x8266e621, 0x69fa2025, 0xde2205d3, 0x37823e4a, 0xff523830, + 0x0080e1ff, 0x9eebffff, 0xe8ffffb8, 0x3182c235, 0x32b3c723, 0x21ea8206, 0xce8290c2, 0x68e60726, 0x660800ff, 0x00243782, 0x08ce4c0a, 0x33251182, + 0xffffff7f, 0x2f5482d8, 0xcdcc2900, 0x4ccfffff, 0x0e088bd0, 0xac00ffef, 0x01234582, 0x8266e63c, 0x99372af6, 0x3700ff9a, 0x00ff0a97, 0x8339845c, + 0xc8ff340f, 0xbd08f668, 0x0700ff59, 0xffff6666, 0xffce4cb0, 0x82e6d6ff, 0x80c62309, 0xa9500800, 0xfeff2405, 0x82056666, 0x34b327ba, 0xb3f1ffff, + 0xca827732, 0x0a824782, 0x84ff3421, 0x8315827b, 0x4c0a2275, 0x201984cc, 0x2415849f, 0x4c0e00ff, 0x2be582cc, 0xff981901, 0x9a990100, 0x1600ff05, + 0x2022b283, 0x25829a19, 0x00216a82, 0x2065832b, 0x230e82e4, 0x66e61b00, 0xe0206a82, 0x1f2b4483, 0xffff6866, 0x8b67e6cc, 0x82e0ffff, 0x82ff20b7, + 0x201a8214, 0x22d0838f, 0x8234b38f, 0x7de02585, 0xe1ffff70, 0xff21bd83, 0x223b83cc, 0x8490821f, 0x206a822a, 0x8225831b, 0x84b72050, 0x83ab2060, + 0x82578270, 0x8d99217c, 0x0e287d82, 0x00ff6766, 0x9f666609, 0xc9821d82, 0x330a0023, 0x20b88333, 0x8438829a, 0x83f120b9, 0xb3fc22d3, 0x84de8234, + 0xb3f5220a, 0x82798232, 0xffff23fa, 0xff83e6fe, 0x2083c520, 0xc382d620, 0x19b2ff26, 0x0600ff99, 0xff28ae82, 0xff8f02ce, 0x68e63100, 0xc72b2982, + 0x00fff087, 0x8b008038, 0x825b00ff, 0x3800231a, 0x0f821078, 0x82676621, 0x4a70335f, 0x7100ff3e, 0xf7053333, 0x07ffffbb, 0xff159a19, 0xdc83c7ff, + 0xa4200484, 0x0f843283, 0x08253d83, 0xffffbd59, 0x211c82f9, 0xcd824e00, 0x83290021, 0x803922e2, 0x20448200, 0x22748301, 0x82999901, 0x830920ca, + 0x4c0e2fca, 0x00ff9fce, 0xff666603, 0x32330f00, 0xaf84ffff, 0x660e0026, 0xf6ffff68, 0x1983a982, 0x1582ca82, 0xf0ffff24, 0xa082cdcc, 0xba83fe20, + 0x6766fe2d, 0xe9ffff05, 0xffff9819, 0x82cccce0, 0x262a823f, 0x3433d3ff, 0x411b00ff, 0x6a82068e, 0x44831f20, 0xc483e020, 0x98193322, 0x1f20cf82, + 0x14828f83, 0x00ff0823, 0x222a8370, 0x82cc4c70, 0x84158585, 0x833320f0, 0x83e0203b, 0x991e2225, 0x206a829a, 0x225084e4, 0x825fb8de, 0xd8a32260, + 0x2170826b, 0x4c410a17, 0x0662410d, 0xff773424, 0xbd840400, 0x0d228c83, 0x25821e85, 0x82b3f521, 0x610e228d, 0x203b8248, 0x23a1824c, 0xff72fd13, + 0xe682d682, 0x82450a21, 0x0100211e, 0x0023b182, 0x82b81e01, 0x83392081, 0x16292571, 0x4e00ffca, 0xff2d3e82, 0xbd227bf9, 0x02ceffff, 0x00ff0890, + 0x291a8238, 0x3c8ac7ff, 0xa4ffff8b, 0x6f416766, 0x99992107, 0x8f205f82, 0xff205f82, 0x05350482, 0x00ffef0e, 0xff333360, 0x66e6f700, 0xffffff15, + 0x00ffb8de, 0x221c8302, 0x8314eeff, 0x82332009, 0xb30223fa, 0x06820833, 0x82665821, 0x8347207f, 0x82048479, 0x828b200e, 0x4c3b2264, 0x201b82cc, + 0x25328333, 0xff00c0df, 0x09831b00, 0xcc0cd022, 0x0f201a82, 0x0026d482, 0xff9a190b, 0x3a831200, 0x09830520, 0x34b31328, 0x8bc0088b, 0x6c18ffb6, + 0xff270bac, 0xcdccf3ff, 0x83fdffff, 0x82f4203a, 0xfbff282a, 0xffff64e6, 0x823333f5, 0x663a2b44, 0xf4ffff68, 0xffb73433, 0x6a83ccff, 0x19c2ff23, + 0x268d829a, 0xcc4cb9ff, 0x83c6ffff, 0x82048431, 0x088b290e, 0xff0604fc, 0x5278b0ff, 0xbf23f082, 0x18ffae87, 0x300d196b, 0xffcccc3e, 0x852b2800, + 0x663500ff, 0x3800ff67, 0x20208207, 0x30d98213, 0x01ff2f0e, 0xff3433b5, 0x00802c00, 0x89ffff15, 0x32e582e6, 0x050080bc, 0x052bf78b, 0x190700ff, + 0x00ff069a, 0x8200400d, 0xd90921e4, 0x0a21ca82, 0x820a83c0, 0xff082110, 0xf2220082, 0x1882059b, 0xba4f0d82, 0x82002005, 0x22cc821d, 0x828b66a6, + 0xcc31241d, 0x18ff06da, 0x2107e282, 0x2184c235, 0xf2229982, 0x3a8400c0, 0x827bf321, 0x82ff203a, 0x0523500d, 0x40f5ff26, 0x0c00ff00, 0x8505e76b, + 0xca012375, 0x8382fb4b, 0xcc8aff26, 0x43ffffcd, 0xff279282, 0x52b8e2ff, 0x83d0ffff, 0xc02126a2, 0xc2ffff00, 0x22918299, 0x82b89e37, 0x3201236e, + 0xa9823433, 0x289c3722, 0x21209082, 0x3d21eb83, 0x27218280, 0xba34b3e2, 0xd3feff08, 0x53203283, 0x0022e083, 0xe0822630, 0x48a14d22, 0x042cdc82, + 0x00ffcd8c, 0xffeb1105, 0x99190200, 0x28096149, 0x00ff08cd, 0xf7aa1000, 0x23228234, 0x0671fd3f, 0xf023e782, 0x8334fba4, 0x20f921ae, 0x0221a482, + 0x2111823f, 0x0982a0f9, 0x04820320, 0xdefaff23, 0x263082b8, 0xff422130, 0x8261b2ff, 0x53ff2156, 0x0e238982, 0x828c01ff, 0x25048384, 0x1c00ff15, + 0x0482ce4c, 0xffae4726, 0xcccc2d00, 0x0f839f82, 0xb8e3ff23, 0x2d378252, 0xff981907, 0x16eef8ff, 0xf4ffff8b, 0x0a823c8a, 0x8468e621, 0x24b4820f, + 0xffcc4ce5, 0x820482fe, 0xcc042686, 0xf3ffffcd, 0x27b98266, 0xff33b302, 0x6666f2ff, 0xf1232f82, 0x820834b3, 0x19c22506, 0xcdffff9a, 0x0485e082, + 0x8b260e82, 0xc2ffff08, 0x1b82d723, 0x29dccd27, 0x193200ff, 0x2273829a, 0x8266e63d, 0x8200202d, 0x27118206, 0xffbed723, 0x29dc3d00, 0x00232982, + 0x82cd4c0e, 0x990d251e, 0xfcffff99, 0x0c216183, 0x224f8299, 0x823433fb, 0x8226209c, 0x2800270a, 0xff056666, 0x1a83d9ff, 0x0a820f82, 0xff228783, + 0x878433fb, 0xffff672a, 0xffcd4cfd, 0x33b3f1ff, 0xdc21759c, 0x83758428, 0x88d82004, 0x828b8279, 0x829e8279, 0x28dc21bf, 0xc222ae82, 0xa382d823, + 0x34204c82, 0xe8825686, 0x6a85ff20, 0x90867482, 0x05298a83, 0xb38d00ff, 0x8b00ff32, 0x219b83e6, 0x2f823313, 0x9a19c423, 0x224d8215, 0x4e2a9c19, + 0x002805f6, 0xffd66316, 0x0080e5ff, 0x2005fb4e, 0x06fb4e70, 0x9ce9ff23, 0x220a822a, 0x83d663e6, 0x83e42069, 0x7d1525e0, 0xebffff71, 0x1a22df83, + 0x2d829082, 0x821a0021, 0x06694f34, 0x9a991422, 0x1b275482, 0x5b086666, 0x82affeff, 0x32491862, 0x82248216, 0x18798635, 0x200c8e49, 0x1879887d, + 0x83128e49, 0x82168279, 0x20798554, 0x258f83a6, 0x15666669, 0xe282cbcb, 0x0d829c20, 0x6663ff22, 0x0020e282, 0x21052642, 0xba8268e6, 0x9899f422, + 0x27072642, 0xff0868e6, 0x32b3e3ff, 0xd2220486, 0x1f823433, 0x00230f83, 0x82ce4c1c, 0xcc89341a, 0x7600ffce, 0x0e053233, 0xf4f714f8, 0x05eb8b15, + 0x180604fb, 0x2216955b, 0x8207b4fb, 0x0ed6183c, 0x54f72213, 0x096b5006, 0x0db39318, 0xff076426, 0x66e6a0ff, 0xed225382, 0x3e820080, 0xb182f120, + 0x660e0032, 0x00ff8b66, 0x089a9911, 0x2b15ebab, 0x2b06eb07, 0x74257782, 0xf715f4fb, 0x4f751874, 0x7eff200f, 0x7fb309f9, 0x05bb8b23, 0x227b826b, + 0x8233b3dc, 0x4ce3227b, 0x882d19cd, 0x2f0e260b, 0x336c01ff, 0x2f048434, 0xe7ffff15, 0x00ff9899, 0xfff46818, 0x6866d8ff, 0x0f832d82, 0x97e7ff31, + 0xffff080c, 0xfb010048, 0xffff054c, 0x45f5e8d5, 0xbb270796, 0x00ffcccc, 0x840b172a, 0x8208200f, 0x9919210a, 0x68250a83, 0x334400ff, 0x20dc8234, + 0x230f822a, 0x98192a00, 0x982a1a82, 0x2cf70100, 0x0a00ff05, 0x048366e6, 0x11222282, 0x2282cccc, 0xff210f83, 0x232284f5, 0xff68e60a, 0x9a200a82, + 0xee207682, 0x0a829182, 0x0f849820, 0x2cfb0823, 0x293a82fb, 0x0100c0ff, 0x98ffff4b, 0x20826666, 0x0000c023, 0x239382cb, 0xcbcd0cc0, 0x67204482, + 0x3f2fb583, 0x00ff33f3, 0x08010040, 0x00ff4cf7, 0x82ffffb7, 0x832e206c, 0x472e23eb, 0x2382d6ae, 0xcc4c2e27, 0xb8d1ffff, 0x228b8252, 0x84ce4c2e, + 0x2247820a, 0x82e2fab4, 0x32b3210a, 0x33200483, 0x50245082, 0xffff0100, 0xe7820482, 0x6666e324, 0x0484ffff, 0x8399d121, 0x230a8393, 0x9a991c00, + 0xe3232582, 0x82ffd763, 0x8398200a, 0x82662056, 0x9c1c22ca, 0x820f8429, 0x0090245b, 0xb624f701, 0xffff25e7, 0xfb010070, 0xff213d82, 0x82b882f9, + 0x8bcc2804, 0x0600ff80, 0x83ff33b3, 0x865c820b, 0x96ce210a, 0x0b837882, 0x32201b82, 0xb0201682, 0x44207382, 0x18207382, 0x0023b182, 0x82686618, + 0x9927281d, 0xe7ffff98, 0x83ff9a99, 0x8b08320f, 0xff2f0e07, 0x9a19b101, 0xe63e01ff, 0xffff1566, 0x230a82ac, 0x66e65300, 0xf922e682, 0x63829819, + 0xff48e126, 0xceccf0ff, 0x51230982, 0x828b80ec, 0xe60322e2, 0x0cb47766, 0x273eb77a, 0x19fc00ff, 0x968b079a, 0xb321c982, 0x06864934, 0xae83f720, + 0x9a99082d, 0x2effff08, 0xfeff66e6, 0x829a19e1, 0xa8dc2b9a, 0xffff8bf6, 0xff0a57e3, 0x0a831c00, 0x57230024, 0xd182080a, 0x11840682, 0x0e820486, + 0x1c83a682, 0x28821b82, 0x38823284, 0x2d823e82, 0x0682ff20, 0x4c211182, 0x2a1684cc, 0xb3dcffff, 0xeb088b34, 0x821564f7, 0x33f72621, 0xf8ffff33, + 0x261a82cc, 0xffcdccf8, 0x8233f7ff, 0x74fb211a, 0x0ce96b18, 0x33070023, 0x25568233, 0x08cdcc08, 0x088407eb, 0x00ffcc25, 0x82f62807, 0x82332004, + 0xd70825bd, 0xf7088b0a, 0x00213282, 0x0f641808, 0x072b2313, 0xd5182f0e, 0xdc7b1aa8, 0xcc4c2105, 0x1c225782, 0xa08234b3, 0x829a5921, 0xa6dc2195, + 0x1b9def18, 0x447cfb20, 0x7900200d, 0xd4200a41, 0x5b186d89, 0xa91813e5, 0x32561d06, 0x14fc2112, 0x610cfa6b, 0xca550beb, 0x66332007, 0x1a8205d8, + 0x077e8918, 0x30566590, 0x2465991f, 0x54fb34f8, 0x251e9915, 0x1100ff8b, 0x808834b3, 0x079b7b18, 0x166a8091, 0x06b06c07, 0x20052d47, 0x2a3a82f1, + 0xcc4ceeff, 0x9b0e088b, 0x8215f4f7, 0x821a234c, 0x3256ff90, 0x707d2106, 0x18143256, 0x250b7444, 0xff0080e5, 0x3256eaff, 0x64f82224, 0xf95c18ab, + 0x20ac570e, 0x1818de56, 0x2008f168, 0x0d0e584c, 0x1450ae18, 0x119f8918, 0x9c0d1258, 0x130c5865, 0x5e416594, 0x9dfb201e, 0x140c5865, 0x6b64fc22, + 0x225cc457, 0x8234f7eb, 0x41ff205f, 0x64182ac3, 0x52580802, 0xaf0e2b24, 0x193700ff, 0x8701ff9a, 0x6882c2f5, 0x420d003b, 0x0b00ff90, 0x00ffd7a3, + 0xff70bd0a, 0x295c0c00, 0x06ab088b, 0x330e00ff, 0x25588234, 0xffcdcc09, 0xda5bf5ff, 0xffff2608, 0x073e0a88, 0x201e849b, 0x181e8833, 0x250c0ce0, + 0xffff33b3, 0x048233f6, 0x824cf521, 0xccf12f3a, 0xff088bcd, 0xffffafff, 0xf3ffff06, 0xb71bd7a3, 0x3e830900, 0xcd4c0d23, 0x22458208, 0x8734330d, + 0xcccc2182, 0x63838286, 0xc2f55f24, 0x378e8307, 0x2108b14c, 0x2961078b, 0xe2fe3105, 0xff150ad7, 0x6666f9ff, 0x660700ff, 0xf4ffff68, 0xff267783, + 0xffff0080, 0x048240fa, 0x66e6f723, 0x2a148208, 0xffff47e1, 0x050080f0, 0x83f8ffff, 0x33f52a1f, 0xf1ffff32, 0xffff8f02, 0x222983fd, 0x82c235f5, + 0x34b3213d, 0x0a872982, 0xfdffff25, 0x839a8f82, 0xff332615, 0x32b30a00, 0x30a28208, 0x00ffb81e, 0x059a990f, 0xbd1700ff, 0x2100ff71, 0x25ad824c, + 0xffec9130, 0x78820200, 0xe61a0027, 0xe1ffff67, 0x20298333, 0x20638315, 0x845983e8, 0x99da2b88, 0xeaffff9a, 0xffff9919, 0x638333e8, 0x8219dd21, + 0x4cda220f, 0x294882cc, 0x06333321, 0x4c0d00ff, 0x65838bcd, 0xffff3322, 0x109fd918, 0x5d181182, 0x2f820ce8, 0x78f6ff28, 0xffff8b52, 0x8f825ef7, + 0x5b830520, 0x142efc27, 0xcc0800ff, 0x22bf82cc, 0x82852bfc, 0x34b3260a, 0xb50100ff, 0x825382c3, 0x060024e8, 0x8292c375, 0x0a4823bf, 0x7282d93e, + 0x9c820520, 0xcc050027, 0x0000ffce, 0x33e08219, 0xffcccc08, 0x66e6faff, 0xe60500ff, 0x8b8b0866, 0x8901ff05, 0x0123d882, 0x44343315, 0x94202f1a, + 0x670cff71, 0xb2180e80, 0x942313d1, 0x8ffb8b06, 0x1f944565, 0x659cfb20, 0x94131a44, 0x1f1a4465, 0x1a44659d, 0x06942612, 0x4c01ff0e, 0x08198233, + 0x9a198022, 0x1100ff15, 0xffff5238, 0xff7ad4f3, 0x281c0500, 0xa8f1ffff, 0xfcfffff6, 0xffffae47, 0x08ce4cea, 0xf8250a82, 0xeeffff10, 0x2b148268, + 0xffa826f8, 0x0040f4ff, 0x28f2ffff, 0x59210e83, 0x251e829a, 0xff5c8fdc, 0x1483ecff, 0xa4f0b631, 0xca0700ff, 0xb2ffff3e, 0x00ff0080, 0x82d6a31f, + 0x82ef201e, 0x0600274d, 0xffff9eaf, 0x28824fed, 0x7228f825, 0x83f9ffff, 0xa0ef2209, 0x871e8242, 0x2138820a, 0x2382c5e0, 0xfff25226, 0x8d571000, + 0x57222382, 0x4382080a, 0x6c82c020, 0xec11f325, 0x823f00ff, 0xe9ff215c, 0x00246b82, 0x8bf6e83d, 0x1d271a82, 0xff8bb89e, 0x82301d00, 0x27052c73, + 0x1800fff0, 0x00fff6e8, 0x82d2cd0d, 0xcf1e221a, 0x2ed5825c, 0x00ff0a17, 0xff48a113, 0xb85e1c00, 0x820600ff, 0x240033d0, 0xff0868a6, 0x7cff0300, + 0x451700ff, 0xfeffff1e, 0x2382862b, 0xff5e4f26, 0x1058faff, 0x78217882, 0x23928250, 0x067ebfb1, 0x002d5982, 0xff158e02, 0xcccc9b00, 0xffff15db, + 0x2dd0834f, 0x05e90700, 0x26f0ffff, 0x0500ff66, 0x0982ee9c, 0xff20052b, 0x1cba0400, 0x21f1ffff, 0x21098246, 0x3d82ae47, 0xae87aa22, 0x9e258b82, + 0xe6ffffb8, 0x21b68291, 0x44826e0e, 0x33330725, 0x832a00ff, 0x0200211e, 0x0e204883, 0x07212383, 0x25af82a8, 0xff146e0b, 0xd5830c00, 0xec110822, + 0x14229a82, 0xc4825278, 0x2b266183, 0x00ff0a97, 0xdd82b00a, 0x09575b28, 0xd0e7ffff, 0xd38508f2, 0x78fbff22, 0x1120aa82, 0x0a214783, 0x22e7822f, + 0x823e8a04, 0x04162118, 0x04221e82, 0x0a82f087, 0xff0c1725, 0x82d0f5ff, 0x2223839a, 0x82e7eeff, 0x87042113, 0xa4209a83, 0x18364d83, 0xffff142e, + 0xff299cba, 0xa470fdff, 0x66d2ffff, 0xe2ffff66, 0xb982dab9, 0x0280e42f, 0x4eeeffff, 0xedffff92, 0xffffcccc, 0x23c383e4, 0x6b707dfa, 0xf72f1a82, + 0xffff852b, 0xff9a99cc, 0xd7a31200, 0x83dfffff, 0x4c1d27cf, 0xe9ffffcd, 0x1e826766, 0xcdcc8e24, 0x3c61058b, 0xffff2405, 0x840040f5, 0xff8b2604, + 0x66a6f3ff, 0x057b5108, 0x20066d51, 0x26d983f6, 0x8b00400d, 0x5164f808, 0xab6108e0, 0x00c02705, 0x0c00ff8b, 0x30829a59, 0x180c0021, 0x2d09879a, + 0xffffcdcc, 0x8b34b3f2, 0xf82f0e08, 0xc8488b34, 0x5c4f2106, 0x08d47318, 0x18080368, 0x48166072, 0x576c05c8, 0x13217908, 0x6c18b320, 0xfc2c0cb5, + 0x7f01ff04, 0x9b1570fd, 0x0734fb06, 0xa7255482, 0x00ffaec7, 0x2a048247, 0xb81eb9ff, 0x385800ff, 0x85088b52, 0x83168506, 0x27b9821b, 0x08ec5157, + 0x9b0734f7, 0x230cc56c, 0xec510e00, 0x11221b82, 0xd58314ae, 0x28730682, 0x6b0d2206, 0x05e37286, 0xff2b0827, 0x40010000, 0x0df17205, 0x8216ae21, + 0x51ee2277, 0x233482ea, 0xec51eeff, 0x2107ef72, 0x0d6c16ae, 0x23648206, 0xffff5fff, 0xcb319d83, 0xffff5d0f, 0xffa4f0d4, 0x0ad7d5ff, 0x0fcbffff, + 0x849d825c, 0x23168506, 0xb4e72b00, 0x34228182, 0x9d939a19, 0x825c4f21, 0xcbe4181b, 0xf1ff210a, 0x0df68818, 0xffff2b25, 0x8ebefeff, 0xa4b0219d, + 0xef229d82, 0x9d83c435, 0xc235ef22, 0xef229d86, 0x9d8688e2, 0x6e21fc18, 0x74fb7431, 0xfb07eb15, 0x072b0634, 0xfb0634f7, 0x84154b34, 0x23128408, + 0x152b74f7, 0x1e881482, 0x8a34f721, 0x820e202a, 0x5c0f37b9, 0xb3f0ffff, 0xffff1534, 0xff0641ed, 0x32b31200, 0x1e00ff8b, 0x0a826666, 0x82fabe21, + 0xcecc2704, 0x7d01ff08, 0x04840a57, 0x10840520, 0x24821a86, 0x30822a82, 0x082a3a84, 0x992200ff, 0xddffff9a, 0x2583846b, 0x8232b321, 0x90422515, + 0xe1ffff8b, 0xed221583, 0x0f82ce4c, 0x08ae4725, 0x8282feff, 0x2004830f, 0x82108405, 0x221a8304, 0x829999e1, 0x42ed222a, 0x2081848f, 0x20468308, + 0x31508485, 0x4d01ff05, 0x01ff3e8a, 0x1532b313, 0x6900fff4, 0x37821e05, 0xcccce827, 0x451700ff, 0x270a8220, 0xff66e696, 0x900297ff, 0x17207382, + 0xe8284883, 0x0e0532b3, 0xf804f8ef, 0x0f1bd518, 0x2808734b, 0x00ff075b, 0x0634b332, 0x8b50199c, 0x16574cac, 0xd4f72608, 0x34fbbb06, 0xf7072b15, + 0x00ff0614, 0x0733b312, 0xb3b2ffff, 0x4d00ff34, 0xff05cd4c, 0xcc4ccdff, 0xfb94fb06, 0xfe601864, 0x120e530d, 0x0d5d4418, 0x222d6a53, 0x182bd4f7, + 0x620c87d6, 0x9c530ae4, 0xbb6f1819, 0xa0ff2008, 0xaf0e258d, 0x14f894f8, 0x17454818, 0x1894fb21, 0x2117fc54, 0x6e5054fc, 0x0be14e0c, 0x00203383, + 0x16754818, 0xfb14fc24, 0xb88215d4, 0xcc4c2328, 0x59e3ffff, 0x3883ff99, 0xdcffff2d, 0x088b66a6, 0x06cb074b, 0x8354f74b, 0x9a59218b, 0x1c222382, + 0xf95267a6, 0x064b2a0b, 0x54f8074b, 0xcb1554fb, 0x05205007, 0x45844082, 0x8bcc4c22, 0x08281084, 0xf78b06cb, 0x064b1594, 0x3b840e85, 0x00202385, + 0x8b276e82, 0xfb07cb08, 0x1874fb74, 0x3e3db2cc, 0x01ff70fb, 0xff9a9936, 0x6666c900, 0x80ffff15, 0x14fb66e6, 0xf8ffff05, 0xffff66e6, 0x1834b3f9, + 0x8410f974, 0xd7921810, 0x00c0270d, 0x400600ff, 0x3d840800, 0x3d83f720, 0x54f4f53c, 0x200900ff, 0xfdffff00, 0x00ff7542, 0xffcdcc0d, 0x39f40400, + 0xe60b00ff, 0x0a890866, 0xad2c0f82, 0x0700ff91, 0x00ff67e6, 0x8b15ee0c, 0xff231a82, 0x82069a19, 0xa4f0220c, 0x211c828b, 0x888214ae, 0x82103821, + 0xc2f52630, 0x07f4ffff, 0x202082f0, 0x270a8604, 0x28feffff, 0xf2fffff6, 0xff261e82, 0xffceccf6, 0x5a82f6ff, 0xcd820e20, 0x6309002e, 0xb600ffd7, + 0xff159a99, 0x9a197f00, 0x00238f83, 0x82291c07, 0xcc4c2aa2, 0x330800ff, 0x0300ff33, 0x82ef8219, 0x83708309, 0x20168206, 0x21fb822e, 0xc885e0fc, + 0xc020f882, 0x3d83cd82, 0xcd82fb20, 0x27090023, 0x205e82f0, 0x228782d8, 0x8276be02, 0xfa3e2672, 0x0bfbffff, 0x20918302, 0x87f482ae, 0xffff240a, + 0x821a2ff5, 0x9a3921b0, 0x33212382, 0x2a5c8234, 0xf5e800ff, 0xf3ffff06, 0x828b5c0f, 0xeb51212c, 0xc720ea82, 0xfb224a82, 0xdc823d0a, 0x0810f822, + 0x0a864682, 0x0200ff27, 0x00ff68c3, 0x391e820d, 0x1e280900, 0x190900ff, 0xfb0e089a, 0x8900ffb0, 0x00ff6666, 0x15666629, 0xcf8414fb, 0x9d820520, + 0xbe82b920, 0xc3820720, 0xb184ff20, 0x32330823, 0x8530858b, 0x20df8206, 0x22c88220, 0x82ae4707, 0x854020f3, 0xf70821d2, 0xcd843d87, 0x0d220485, + 0x778206c1, 0x0023d282, 0x8452f80b, 0x830820d2, 0x820a8597, 0x66c621ab, 0x4821b582, 0x20bb82b4, 0x258d82f3, 0xe600ffff, 0x0c830766, 0x415c0f21, + 0xff230596, 0x82ec51f4, 0x84072021, 0x823e20d2, 0x86f420cd, 0x0596410a, 0xd7010024, 0x4618ff0a, 0xcd84099f, 0x01197620, 0x8f820774, 0xe680ff24, + 0x96410566, 0xf8ff2205, 0x20e582e6, 0x22d28303, 0x82cdccf7, 0xb3f82363, 0x06840833, 0x84ff3221, 0xf6ff23e4, 0xb21886eb, 0xfb220a6a, 0x3d85ff14, + 0xd8f6ff23, 0x059b4110, 0x3ef2ff28, 0xfdfffff9, 0x91838a41, 0x00ffae25, 0x84fef404, 0x820a8591, 0x9a392cb0, 0xea0900ff, 0x00ff8b80, 0x42cccc0d, + 0xcd820569, 0xf00c0023, 0x059641a4, 0xae0b0023, 0x20fe8314, 0x213b8211, 0x2082c4f5, 0x84f80b21, 0x41c2200a, 0xff230596, 0x82e03afd, 0x23a28340, + 0x087cd4f6, 0x6dfd0219, 0x15d4fb33, 0xf70634f7, 0x34fb0794, 0x0794fb06, 0x94f714f8, 0x850a8515, 0xfb0e3516, 0x1b00ff70, 0x74f7f6a8, 0x0801ff15, + 0xff0634b3, 0x9a991800, 0x3108ea82, 0xff3c4a0c, 0xaec71d00, 0xa6eeffff, 0x1100ff68, 0xff080a57, 0x33b37bff, 0xcc8800ff, 0xffff05cc, 0xff1098fa, + 0xf0670500, 0xeff8ffff, 0x0200ff9e, 0x098276b3, 0x8ba4f022, 0xf8232582, 0x828becf1, 0x0af7260c, 0x4cfdffff, 0x212a828a, 0x2f84d7a3, 0x7b271a82, + 0xffffbd7f, 0x82162e77, 0xa6ee2540, 0xeeffffe9, 0x0c265083, 0xffffb448, 0x5a8233e2, 0xe19a1822, 0x013b4082, 0x4bd6a308, 0xf7feff15, 0xff062a5c, + 0x6666e7ff, 0xf3ffff8b, 0xffffc3b5, 0x82e23ae2, 0x9a592189, 0xa62d3782, 0x00ff0866, 0xff008084, 0x343377ff, 0x20898205, 0x27a98247, 0xffb89efa, + 0x34330600, 0xcc257783, 0xe60700ff, 0x234d8266, 0x910d0700, 0x0722cf82, 0xa5832711, 0x2a82f820, 0x84f66821, 0x214083b9, 0xcf86ce4c, 0x5e110022, + 0x11223b82, 0x6a82804a, 0x8232b321, 0xcccc21f9, 0x08327a85, 0xff70fb0e, 0x66e63701, 0xe67000ff, 0xffff1566, 0x7f82997b, 0x32337722, 0xfa20c282, + 0xfa230a83, 0x85849c99, 0x18ff2070, 0x85078267, 0x5cef21ff, 0xb6207083, 0xa620fa82, 0x05233c82, 0x85083268, 0x0640413c, 0x18a4ee22, 0x7082cc82, + 0xff830020, 0x821d0021, 0x87002070, 0x058741ff, 0x823c8a21, 0x820c20b7, 0xe2ff21a2, 0xee20d383, 0xff209782, 0x91840482, 0x248eb341, 0xf864f80e, + 0x0c9c4714, 0x250af759, 0xf0ffff8b, 0x194666e6, 0xccf12506, 0xf3ffffce, 0xf6380e83, 0xff0866e6, 0x686626ff, 0xcc5cffff, 0xffff05cc, 0xff9899f4, + 0x0080f7ff, 0x66212e82, 0x27348267, 0xff9a99f4, 0x00800800, 0x66252584, 0x33a300ff, 0x22258234, 0x43bae9f3, 0xf82e064d, 0x00ff12e3, 0x8b32330e, + 0x190f00ff, 0xb948089a, 0x34f82516, 0x09ffff06, 0xfe234a82, 0x82ccccec, 0xcc162ca2, 0xeeffffcc, 0x00ff68e6, 0x8234331f, 0x270f8333, 0x98191100, + 0xd900ff08, 0x65842582, 0x4764fb21, 0x142018eb, 0x2118eb47, 0x41850764, 0x0e22cd84, 0xdb7474f8, 0x82842005, 0x9bff2153, 0x0484d483, 0x8b260e82, + 0xcfffff08, 0xe082d723, 0x85abd122, 0x942bba82, 0xd8ffff7a, 0x00ff71fd, 0x82b0471d, 0xdcf1311a, 0x0a00ff29, 0xffff0a97, 0xffd723fd, 0xec111400, + 0x9b210e82, 0x21e982e8, 0xa3826626, 0x829c0a21, 0x170e221e, 0x2619820a, 0x00ff7b14, 0x8248e102, 0x291c2b19, 0x67f5ffff, 0x00ff08ae, 0x3882d71b, + 0x1e83eb20, 0xf628212c, 0xf8f4ffff, 0x2200ff52, 0x7382d7e3, 0x1958002d, 0xffffffda, 0x00ffb8fe, 0x8334b347, 0x82322004, 0x415820fd, 0x06820538, + 0xb8ffff24, 0x16847c54, 0xa7ffff24, 0x3182b8de, 0xb3cdff23, 0x24318232, 0xffffe2fa, 0x243182d0, 0x86ebe7ff, 0x21aa826d, 0x6782cc4c, 0x66663f28, + 0x1100ff06, 0x438285ab, 0x7b540e22, 0x12454f18, 0xb3f1ff23, 0x28168433, 0x4ceeffff, 0xfb088bcd, 0x0e9c5724, 0x2208114d, 0x4d0724f7, 0x1a57051b, + 0x0c837607, 0xff3a6192, 0x1ec5b9ff, 0x2a00ff07, 0x00ff9a19, 0xff66a635, 0x01004000, 0x782000ff, 0xb682d154, 0x667b0023, 0x374f8266, 0xff008064, + 0x8e829bff, 0x84ffff8b, 0x0e089a99, 0x00ff94f8, 0x1533b3e7, 0x06211a82, 0x241a8220, 0xfff0a7fd, 0x38098400, 0xff2050fb, 0x15ae0400, 0xe9ffff08, + 0x00ffbc54, 0x05ec9116, 0x4ffbffff, 0x301582e0, 0xffff9caf, 0xff16d9f9, 0x8e570200, 0xbdfaffff, 0x84608270, 0xffff2e06, 0xff34f3f8, 0x32a8fdff, + 0x35fcffff, 0x212f82c2, 0x4082a450, 0x8260fa21, 0x8204825a, 0x208d2d40, 0x7100ff02, 0xff051e25, 0x00a00500, 0x0a820484, 0x83af0421, 0x82b02056, + 0x57022271, 0x218082ce, 0x9082ea26, 0x90420523, 0x82068408, 0x23518363, 0xce0c0700, 0x25825183, 0x3eca0322, 0xe9225682, 0x97824861, 0x82b89e21, + 0x4bfb2256, 0x21368284, 0x9782b27d, 0xf982e620, 0x10580222, 0x68200983, 0xf9229783, 0xed8268e6, 0x82f3f921, 0x82dd8392, 0x845c20c2, 0x27408245, + 0xff095783, 0xf08783ff, 0x66214083, 0x21158267, 0xbc82cc4c, 0x85999921, 0x2105823b, 0x8182cccc, 0xccf9ff23, 0x84ea82cc, 0x20dd8252, 0x83ac8300, + 0x84082045, 0xffff217c, 0xc2838682, 0x8221b021, 0xdf4f2140, 0x26218682, 0x214582e9, 0xdc8231a8, 0x82904221, 0x06002381, 0xc782f027, 0x6c270622, + 0x00204585, 0xff20bd82, 0x40824583, 0x210a0341, 0x77821971, 0x66e68e22, 0x2f418c82, 0x06612105, 0x82067041, 0x83e0206c, 0xff302551, 0x16d9f9ff, + 0xfa20cc82, 0x82053a72, 0x21518506, 0x9788f8ff, 0xc235fc22, 0x2020978f, 0x2206b641, 0x853c1f06, 0x06002345, 0x97844821, 0xae820682, 0x85b81e21, + 0x04002345, 0x9787a4b0, 0x00807c27, 0x997c00ff, 0x22d8829a, 0x828c8c06, 0x42e0211f, 0x4c220482, 0xc88391cc, 0x08333331, 0xcce3feff, 0xeaffffcc, + 0xff153333, 0x8299c5ff, 0xb3c422b9, 0x22ae8234, 0x4834b3f9, 0xf7200682, 0x00201f82, 0x20088248, 0x08e74a08, 0xff66e624, 0x0d4bfcff, 0x82332005, + 0x34b321cf, 0x8d271a82, 0xffffcd4c, 0x83ce4c8d, 0x00c02140, 0xc0211582, 0x06a74884, 0x68d1f722, 0xf723ef82, 0x85085ccf, 0x058c4906, 0xd1f7ff23, + 0x058c49ec, 0xc0f9ff23, 0x21ef8200, 0x3582402d, 0x00c0d222, 0x3821ae83, 0x26408252, 0x00ffa2b0, 0x85a43008, 0x8309836a, 0x821082ef, 0x2e0822be, + 0x21458515, 0x35820600, 0x2105694b, 0xb7837200, 0x40830482, 0x24831586, 0x3487f482, 0x81821420, 0x2f080023, 0x8598855c, 0xc0f92109, 0x45822082, + 0x3a248182, 0x00ff146e, 0xc2820482, 0x49ccd232, 0x272e00ff, 0xfb0e05ae, 0xf000ff30, 0x74f70080, 0x6f2f7182, 0xff060080, 0xcc4c0d00, 0xffff978b, + 0x8233b3f7, 0xcecc265e, 0x99f3ffff, 0x213d829a, 0xbf828005, 0xff7ff322, 0x09835c82, 0x68e6f123, 0x26248281, 0xfb083233, 0x8274fb94, 0x58f42052, + 0x3225052a, 0x78efffff, 0x21258251, 0x39823433, 0x8285eb21, 0xcecc22e3, 0x210a8208, 0x0a83f5e8, 0xffffcc2b, 0x9b9a99fb, 0xe30500ff, 0x216a82d7, + 0x598234b3, 0xf6e84c27, 0x66b300ff, 0x23448266, 0x0699998f, 0x91272b82, 0xffff8beb, 0x822110f4, 0x834c2031, 0x9e4f2731, 0x660c00ff, 0x3c820868, + 0x7f210a84, 0x2b9a82ff, 0x00ff168a, 0xff9a190e, 0x1d090a00, 0xcc212882, 0x354a82cd, 0xff52f8ff, 0x64fbdf00, 0x0b00ff05, 0x00ffce4c, 0xff88d609, + 0xaf821000, 0xbf000023, 0x214382be, 0xb3829819, 0x828c3721, 0x820c2029, 0xf7ff3039, 0x00ffca36, 0xff666604, 0xae07f0ff, 0x83faffff, 0x42f22213, + 0x20678290, 0x290a83b3, 0x05289c4c, 0x64f7af0e, 0xb55b04f8, 0x224b8309, 0x4f707d15, 0x08210500, 0x645318cb, 0x0a3a470c, 0x71074b21, 0x7e1805f3, + 0x83251063, 0xf7076306, 0x2636822c, 0x8b66e61e, 0x831900ff, 0x83e62067, 0xe1ff270a, 0x6b089a19, 0x518e9307, 0x85008021, 0x98082048, 0x064b2151, + 0x164f7e18, 0x7e18cb20, 0x9322174e, 0x1a83ab06, 0xfc20f884, 0x002cfd82, 0xff9a9903, 0x9a99fbff, 0x2cfb088b, 0x83e59f82, 0x8207b321, 0x2076836c, + 0x83e18299, 0x36331a86, 0x3807410a, 0x48737d20, 0x0a074112, 0x410d535b, 0x1e270607, 0x00ff66e6, 0x41ec1119, 0x002b058d, 0x8b15ee1e, 0x062cf708, + 0x418307b3, 0x0e321959, 0xff00ffaf, 0x00ff9a19, 0x15cc4c92, 0xb37dffff, 0xc5820734, 0x9e2ff727, 0xcff8ffff, 0x280482df, 0xffff62d0, 0x8b2130f7, + 0x210b8208, 0x1b829e2f, 0xbe9ffa26, 0x500500ff, 0xfe221682, 0x09820a17, 0x82426021, 0x18fa3b1a, 0x1000ff10, 0xffff52b8, 0xff56ceed, 0xa4b00800, + 0x4aefffff, 0xfaffff3e, 0x1e820a17, 0x5c4fef22, 0x20210a82, 0x214a8200, 0x2382ae47, 0x825caf21, 0xf6e82138, 0x66282382, 0x00ff0866, 0x6b291c0c, + 0x22058a53, 0x8299eaff, 0xe620298b, 0xb8088b67, 0x2300ff8b, 0x0482d183, 0x82b88b21, 0x4c823225, 0xffff07ce, 0xfff0e7f6, 0x72e80700, 0x48f5ffff, + 0x264582b4, 0xffffb6b3, 0x835ccff3, 0xb3f3259f, 0xffffff34, 0xff219482, 0x223782f5, 0x8233fbff, 0x80f5210e, 0x33257483, 0x01ff0832, 0x225a8340, + 0x82cecc14, 0x66e32ae6, 0x8800ff64, 0xffff6666, 0x26248292, 0xd8e35100, 0x828affff, 0x0c00223d, 0x232982b3, 0x66e61100, 0x55071048, 0x51210625, + 0xec4818ec, 0xcaf0210e, 0xf122dc82, 0x215fa4b0, 0x22e28205, 0x820c17ee, 0x338b229d, 0x838e8233, 0x2e9331ed, 0xaeffff14, 0xffff281c, 0xff9dd0e2, + 0x9a9977ff, 0xfd222482, 0xc18273c7, 0xffcccc27, 0x93b80a00, 0x2605827f, 0x00ff5c2f, 0x8266e609, 0x003427dd, 0x3700ff00, 0x04828f02, 0x4382b320, + 0x4861fd2c, 0xe63200ff, 0xa6ffff67, 0x1e829999, 0xdf4f0522, 0x7f213982, 0x2a2e827c, 0x00ff1799, 0xff84e000, 0x82cf0400, 0xa008223d, 0x201e8200, + 0x26778214, 0x5e4f2300, 0x821800ff, 0x2500213d, 0x0024ff82, 0x8b67e62c, 0x3a2b1a82, 0xff8b0080, 0xa4b01d00, 0x82bbffff, 0x02002893, 0xffff0080, + 0x82b89efb, 0xcf04261a, 0xf7ffffe0, 0x26788260, 0xff169909, 0x821fffff, 0x8205205e, 0x09003ebc, 0xbe088480, 0x855900ff, 0x3800ff1e, 0x00ff9a19, + 0xffb9de01, 0xfe7f3300, 0x9ec9ffff, 0x213982b9, 0x4e82300b, 0x70fdf522, 0x9924c282, 0x0c00ff9c, 0xff222382, 0xd782ccfd, 0x3433092b, 0xd4f70e08, + 0x9b15f4f7, 0x060f4b07, 0x82eaff21, 0x15002371, 0xde43707d, 0xff082905, 0x6666c7ff, 0xf4ffff06, 0x0028dd82, 0xff281c13, 0xcd4cebff, 0xe3264382, + 0xe8ffffd8, 0xb3826666, 0x16850684, 0x83f3ff21, 0x82f42020, 0xecff23cf, 0x3b88d8e3, 0x1f43e520, 0x0aab4408, 0x44d4fb21, 0x6d8207ac, 0xb1447120, + 0x05c77605, 0x7324f721, 0x8b260553, 0x001001ff, 0x98820556, 0x34332c26, 0xcc2300ff, 0x23207782, 0x2c2bb683, 0x088b3333, 0x34fb06bb, 0x18ff1593, + 0x5d0c32ad, 0xff2409d8, 0x00400d00, 0x3383ef82, 0x82c00a21, 0x7b9e1809, 0x82332008, 0x820a204f, 0xf5ff2316, 0x01590040, 0x85082005, 0x5dff2006, + 0x37820624, 0xb3f2ff22, 0xf7226182, 0xad666394, 0x2b6b2107, 0x54092b67, 0xab661322, 0x64f72d33, 0xa0ffff07, 0xff069002, 0xd663eeff, 0x2d112b67, + 0xff30fb0e, 0x9a197000, 0xb3f9ffff, 0x1f821534, 0xf8b3f927, 0xd00100ff, 0x3a1082e6, 0x00ff64db, 0xffcf7703, 0x00c0faff, 0x1100ff08, 0xffffd723, + 0x055c4fe6, 0x830500ff, 0x20f821be, 0x0b22f182, 0x298285eb, 0xff529827, 0x52780900, 0x2325828b, 0x0685ab3d, 0x70260c82, 0x00ff8b21, 0x1082ec0b, + 0xa8660622, 0x00233085, 0x8206e107, 0x1411270f, 0x1900ff7b, 0x468214ae, 0x20f00226, 0x700400ff, 0x02270482, 0x00fff668, 0x8298ee07, 0x54052234, + 0x2a25827c, 0xffc62000, 0x32332700, 0x8234fb05, 0x8300204e, 0xccd822a0, 0x3c3382ce, 0xffcd4c4f, 0x6a49c601, 0x9affff15, 0xffff3e0a, 0xff00b0ff, + 0x5c8fb6ff, 0x5badffff, 0x23bf8210, 0x08b8dea3, 0xd3360682, 0x00ffb89e, 0xffa47010, 0x3e8ad7ff, 0x1e1b00ff, 0xe1ffffb8, 0x59823c0a, 0xae871026, + 0x28edffff, 0x19216f82, 0x223582cf, 0x82289cd8, 0x48e126ae, 0xc7deffff, 0x221e82ae, 0x82040800, 0x82c02054, 0x100021da, 0xff275982, 0x00ffc0bb, + 0x82fd0700, 0xfcbb2113, 0xa0221e82, 0x8f833233, 0x00252482, 0xfffe4300, 0x23248300, 0x42400000, 0x07210982, 0x210482fc, 0x24820444, 0x82e00921, + 0x3821223e, 0x21e78252, 0xc682a4d0, 0x82d66321, 0x2376828b, 0x0cd71200, 0x1b271e82, 0x00ff6826, 0x829c191e, 0x66662614, 0x662800ff, 0x22f68266, + 0x82cc4c2d, 0x600023b7, 0xd282727d, 0x1682e620, 0xc8e44e26, 0x809effff, 0xb3218383, 0x273582fe, 0xff9a9900, 0xd200a0ff, 0xd322f882, 0xe282b8de, + 0x8221dc21, 0x1cdc22b4, 0x220a822a, 0x823ecad4, 0xf6ff223c, 0x2ed0824f, 0xffcdccf8, 0xccccf8ff, 0x33f7ffff, 0x78088b33, 0x7182164f, 0x90c23d26, + 0x403200ff, 0x3127aa82, 0x00ff0a57, 0x8200c03d, 0x0800232d, 0x1b8210d8, 0xf0270722, 0xd7214482, 0x225b824c, 0x83b428f7, 0x8206825b, 0x225b8311, + 0x8522bbf9, 0x0e083054, 0x15a4f7ab, 0xcc7201ff, 0xffff06cc, 0x84b89ec6, 0x18052004, 0x18094d43, 0x2e107ddc, 0x2e0600ff, 0xf9ffff16, 0x00ffe2ba, + 0x4a323308, 0x3321071f, 0x77dd1834, 0x04f7231c, 0x431804f7, 0x9e820ad2, 0xb5821420, 0x80f3ff22, 0x0c24ba82, 0xfb080080, 0x0f881f84, 0x0b45a918, + 0x08201483, 0x3922909c, 0xb682146e, 0x0500a027, 0x338dfeff, 0xf86a1834, 0x205d5c0e, 0x34fb5423, 0x27388215, 0xff06cc4c, 0x48613900, 0xaa9b0484, + 0x00208a85, 0xa590b582, 0xfb04fb22, 0xc584e582, 0x0ac84918, 0xea822a85, 0x84f70821, 0x06002d1f, 0xffff852b, 0xff52b8f9, 0x34330800, 0x20084041, + 0x0dfc5533, 0x20030028, 0x0600ff00, 0x0482703d, 0x08004023, 0x834584ff, 0x103b4104, 0xae21fb82, 0x27b68215, 0xff050060, 0x34b37201, 0x5c0ebf5c, + 0x2d5d1121, 0xef0e250d, 0x156b24f7, 0x7031fe6f, 0xf725c2f3, 0x5700ff33, 0xb55b19e6, 0xf5ff2307, 0xb718cecc, 0xdb211044, 0xedb618db, 0xff642536, + 0x66e6d8ff, 0x86293c82, 0x8b079a19, 0x4c0d00ff, 0x02fc18cc, 0xffff2110, 0x143c5e19, 0x79ffff25, 0x820766e6, 0x9a19273f, 0x192700ff, 0xbe52059a, + 0x09002105, 0xf0284283, 0xff8bcccc, 0x9a99f6ff, 0xb3220482, 0x05830834, 0x0f843320, 0x1b821582, 0x2582ff20, 0x2f84cd20, 0x3bdb0823, 0xfadb4105, + 0x6df7da23, 0x1a1c4115, 0x0900ff23, 0x37b91866, 0x00ff2a16, 0xff66e627, 0x34332600, 0x05894105, 0xffff8b28, 0xff34b3f2, 0x04820a00, 0x8d1aff20, + 0xff2c20d2, 0x9a198600, 0xffffb207, 0x05ccccd9, 0x0a22669c, 0x42183233, 0x7f420b27, 0x22968205, 0x41db3b08, 0x3b331bf2, 0x2f0e053b, 0x15d4f7eb, + 0x4600ff8b, 0x00ffa4b0, 0x82cd4c39, 0x5c4f2104, 0xb3230e82, 0x83088b33, 0x82342006, 0x4c39261b, 0xc6ffffcc, 0x2f2119b0, 0x7328820b, 0x332307fa, + 0x19b9ffff, 0x830f5d21, 0x08388249, 0x33b34622, 0xffffab08, 0x1534b30d, 0xe6e8ffff, 0xf9ffff66, 0xffff9819, 0xff9919ef, 0x9a99eaff, 0xe6ffff8b, + 0x22056c78, 0x4e9a19e1, 0xff220923, 0x9a4a1e00, 0x093a4e05, 0x19190022, 0x17822d82, 0x82086621, 0x66192156, 0xef204982, 0x15203283, 0x58830983, + 0xe6060023, 0x28af8268, 0x07666641, 0x0000ff91, 0x204e8299, 0x20208306, 0x22ba8200, 0x84330600, 0x665b24cc, 0x82ff0667, 0x8232200c, 0x33052742, + 0xffffff34, 0x0f8234b3, 0xff239683, 0x82086666, 0x66e625e2, 0xe4ffff07, 0xf8205383, 0xeb201583, 0xff204682, 0x2405b44e, 0x083433e2, 0x52881863, + 0x6c332009, 0x002506e6, 0x8bcdcc08, 0x0a991908, 0x82a3202f, 0x06696b48, 0x0e209e83, 0x11230483, 0x828b34b3, 0x180683c0, 0x4c0926aa, 0x7320063d, + 0xf7229582, 0x0d823433, 0xccccf824, 0x0482ffff, 0x10820a82, 0x06850820, 0x9718ff20, 0x8f980f83, 0x7883b320, 0x43831d20, 0x944fda83, 0x23ee8305, + 0x9a190700, 0x32397c82, 0xff07cccc, 0x9a194900, 0x4ceaffff, 0x3600ffce, 0xffff66e6, 0x8b9a99bb, 0x2269833a, 0x429899ef, 0xff2505be, 0xff34b3f2, + 0x820e82ff, 0x7bfe24b0, 0x8206f668, 0x0a97210c, 0xf2308b82, 0x00ff33b3, 0x8bcc4c0d, 0x661000ff, 0xdc8b0868, 0x05264282, 0x4400ff1f, 0x56826666, + 0xffe1fa34, 0x32b31500, 0xc4ffff08, 0x830768e6, 0x4ccaffff, 0xd81815cc, 0x3a830896, 0x57820a20, 0xcd203f82, 0x5b685782, 0x2096832c, 0x247f8233, + 0xffcd4cf5, 0x85448200, 0x0e082854, 0xf774f8af, 0x7cff15e4, 0xdf361829, 0x00fff628, 0xff5ccf13, 0x29dce3ff, 0x4c1c00ff, 0xf3ffffcc, 0xa18285ab, + 0xcc4cb123, 0x25508207, 0xff00c0c6, 0x0483cdff, 0x8240d121, 0x40c22509, 0x4f088b00, 0xce201782, 0x2c37ad83, 0xffff9a19, 0xff6766fd, 0x48213700, + 0x4700ff08, 0x00ffd8e3, 0x82e2fa0e, 0x82e6200f, 0x804022ef, 0x21878200, 0xf082334e, 0x829a0023, 0x334e8290, 0x48610b00, 0xd9f7ffff, 0xffff959a, + 0xffb8def4, 0xb81e0200, 0xc1296b82, 0x00ff7a14, 0x05cc9c0c, 0x2011827e, 0x226682a0, 0x82c275f3, 0xe89b2426, 0x83fdffff, 0xfef22230, 0x282582fa, + 0xff90c2fc, 0xec41f0ff, 0x21158205, 0x2a820060, 0xdf6f082c, 0x68f3ffff, 0x0c00fff4, 0x14827dff, 0x82ba5e21, 0xb01e2883, 0xf9ffffa4, 0x8205e6f0, + 0x918622a4, 0x250683a8, 0xffb91ecb, 0x6e82d5ff, 0x40d4ff29, 0xffff5601, 0x820080ff, 0x9eca224e, 0x290a84b8, 0x91d4ffff, 0x2b00ffec, 0xac825c0f, + 0xb85e3522, 0xff341a82, 0x00ff15ee, 0x05ae877a, 0xb81e00ff, 0x0600ff52, 0x9805ac1c, 0x80269a82, 0x0800ff00, 0x6f82f668, 0x8366a621, 0x98b8216f, + 0xfc212c82, 0x221082e8, 0x83eebc0f, 0x00802296, 0x21918298, 0x26849959, 0x22847e20, 0xc1222182, 0x15824721, 0x829a9921, 0x22f48321, 0x82c0fdff, + 0xd9f727e2, 0xf6ffff99, 0xa6826626, 0x8f84f420, 0x9a996423, 0x200c8207, 0x271c82b2, 0x291c3700, 0x40bfffff, 0x48276e82, 0xffff71fd, 0x823433f1, + 0x990221d9, 0xa53b3182, 0x00ff707d, 0xff67e64d, 0xcc4cb7ff, 0x665f00ff, 0xec088b66, 0x00ffda8b, 0x82b85e4b, 0xa15c22bf, 0x28298248, 0x0734b34e, + 0x3a1c00ff, 0x26a982e0, 0x00ff295c, 0x8220c513, 0x9919210e, 0x20232082, 0x82083eca, 0x822c2006, 0x064f7e5b, 0x7ecccc21, 0x8b21064f, 0x46481823, + 0x2230821b, 0x18b30a00, 0x420cb8f5, 0xcb4507e9, 0x22bd8207, 0x8234b3f2, 0xf2ff235e, 0xa04733b3, 0xf5ff2205, 0x08b1664c, 0xf814f724, 0x7b82151c, + 0x14ee1e22, 0x1a05e944, 0x210a9e67, 0x275324f7, 0x14ee210e, 0xe1344d82, 0xfc08ec11, 0x94fb073c, 0x073cf806, 0xf71563bb, 0x07b30634, 0x04224182, + 0x2677846b, 0x94032206, 0x07ce527c, 0xff234182, 0x529a99fb, 0x6b210861, 0x2f0a8284, 0x087c94fb, 0x04fb0763, 0x06ab158b, 0x6b0714fc, 0x2018195a, + 0xef641894, 0x14f82a17, 0x6b1514fc, 0x0714f806, 0xc96b18ab, 0x61cc200f, 0x082005b9, 0x37197662, 0x94f72f0e, 0xff1534f8, 0xccccecff, 0xffffd407, + 0xc2862bf1, 0x6ebfffff, 0xb228dc83, 0xff089a99, 0x3333edff, 0x26087982, 0x67e6d0ff, 0x4c1100ff, 0xd2ffffcc, 0x00ff32b3, 0xff34331f, 0xceccdcff, + 0x0700ff08, 0xffff6666, 0x0532b3f7, 0x830800ff, 0x80f62b0a, 0x0200ff00, 0xffff9a19, 0x048299f2, 0xceccfa24, 0x4042ffff, 0xccfa2105, 0x0a823e82, + 0x19830f82, 0x0483f820, 0x6666f329, 0x14fc088b, 0x83ffff06, 0x21198209, 0x52862d92, 0x87d6fa2a, 0x800b00ff, 0xffff0800, 0x57820a87, 0xff901024, + 0x66820d00, 0x5f080026, 0x0900ff4f, 0x00231e83, 0x827f6a07, 0xce4c217b, 0x1f268182, 0x00ff713d, 0xa1823323, 0x8f42112d, 0x4c2d00ff, 0x00ff8bce, + 0x8299192f, 0xcc1222a7, 0x21c882cd, 0x3c834d00, 0x9e823620, 0x91400026, 0x4900ffec, 0x0e22d783, 0x20827ad4, 0x34331322, 0x11272083, 0x00ff86ab, + 0x82cd4c0e, 0x7a542104, 0xa319f382, 0xab201153, 0x071f5b18, 0x6b068b39, 0x7a1574fc, 0xefffff8b, 0x00ff33b3, 0x7f34b306, 0x977f0897, 0x83f9ffff, + 0x3311223e, 0x267c8232, 0x089a1910, 0x830614f7, 0x66e62123, 0xcc2a1983, 0xcceeffff, 0x087f7fce, 0x09847f7f, 0xef2d1386, 0x088b66e6, 0x94f8ef0e, + 0xfc1534f8, 0x578b181c, 0x0a94500c, 0x00ff2108, 0xfb900200, 0x568b057c, 0x002b00ff, 0x8bc06001, 0x0654f708, 0xfd3400ff, 0xb6b68b70, 0xab08c08b, + 0x46220c82, 0x788248a1, 0xb85e3926, 0x613900ff, 0x46230a83, 0x8208b89e, 0x24068211, 0x99c6ffff, 0x2d168498, 0x66b9ffff, 0x8b088b68, 0x6b1554fb, + 0x3c42f706, 0x00402106, 0x1c252682, 0xffff00c0, 0x230a83e3, 0x00c0dcff, 0x06833882, 0x4c201182, 0x1682b982, 0x4d74ff20, 0x82bb2005, 0xb4fc2138, + 0xf722a782, 0xdc82fc29, 0x04d6f822, 0x200ef546, 0x053252e5, 0x210cc451, 0x237874f8, 0x06657417, 0xccf8ff22, 0x0c7e6c18, 0xf7ef0e25, 0x5624f854, + 0xf72117f2, 0x0ea15634, 0x23083767, 0x3b0764fc, 0x324e551b, 0xf8063b28, 0x0cf70764, 0x9e18157b, 0xd7210dee, 0x26e1820a, 0x08f628f7, 0x83730773, + 0x13e747f1, 0x79487b20, 0x1834200a, 0x2508bc9f, 0xa3088bcc, 0x1a977306, 0x22180448, 0x82a307a3, 0x095d75d9, 0x0a584818, 0x90759b20, 0x0f2a4107, + 0xa3067322, 0xd7211a84, 0x227d860a, 0x85f62807, 0x7b0829c6, 0x6b2cfb06, 0x0734fc15, 0x2e0ed779, 0x00801500, 0x1a00ff8b, 0xf7080080, 0x83db0724, + 0x75ea8372, 0x944108ea, 0x41082005, 0x5a82089b, 0x2705c748, 0x8bf628f7, 0xcb063b08, 0x37763391, 0x20338407, 0x858982cd, 0x82332033, 0x20338589, + 0x090958bb, 0x250d0157, 0xf80604f7, 0xff5f8b44, 0x0872580e, 0x3b075b22, 0x180f7941, 0x850eddf6, 0xccf82c99, 0x0800ffcd, 0x088bcccc, 0x914b06db, + 0x49cc2033, 0xdb231d95, 0x5924fb06, 0xfb20172d, 0x34219f82, 0x10a58207, 0xce01b129, 0xf704fc24, 0xa31815b4, 0xbb221678, 0xbb435b06, 0xff332305, + 0x504c0700, 0xffcd2805, 0xcdcc0800, 0x18ab088b, 0x830cef92, 0x05f2421d, 0x07bb0823, 0x17bb43bb, 0x187fa418, 0xbb065b22, 0x820abb43, 0x06bb4362, + 0x088b3322, 0x0f1ba518, 0x22088b44, 0x185b075b, 0x4c0c7c4c, 0x6b280a73, 0xf78b0e07, 0xb4fb15c4, 0xff215482, 0x7e4c18e6, 0x069b2512, 0x7b0714f8, + 0x17254c18, 0xbb64f829, 0xfc067b15, 0x829b0714, 0xa44c18c8, 0x21598315, 0x4c181900, 0x3b241241, 0xff8b15bb, 0x30b04c18, 0x6d836b20, 0x83d4f721, + 0x066b2e95, 0x64fb07bb, 0x34f7158b, 0xfb075b06, 0x230d8234, 0x9cfb44f7, 0xff215482, 0x5b6e83fb, 0x5449079c, 0x06532206, 0x26e38353, 0xff00a0fb, + 0x8760fcff, 0x220e8204, 0x825b088b, 0x096e49de, 0x99030023, 0x2698829a, 0x08666604, 0x975307c3, 0x82bb201a, 0x8200204c, 0x83ff2023, 0x8204862e, + 0x088b240e, 0x97c306c3, 0x06bb221a, 0x823283ff, 0x8262825c, 0x66662285, 0x239c848b, 0xc3075308, 0x5b271a97, 0xf7ef0e07, 0x823cf834, 0x069258d6, + 0x7133b321, 0x00270572, 0x8bcd4c0d, 0x8204f708, 0x05a54d39, 0x34b30a23, 0x149558ff, 0x1684cc20, 0xf2ffff31, 0x088b34b3, 0xfbf3067b, 0x00ff0524, + 0x82666674, 0x82072039, 0x00ff2712, 0xff9a9907, 0x0482feff, 0x2f051945, 0x08cc4cfd, 0x196600ff, 0xd9ffff98, 0x940534b3, 0x9927aa82, 0xffff9199, + 0x826766f7, 0x66f623b0, 0x06850866, 0x12838520, 0x83826621, 0x089a261e, 0xe699ffff, 0x46308568, 0xff200555, 0x09824682, 0x85666621, 0xf8ff215a, + 0x24055650, 0x069a998b, 0x20818223, 0x82b78e9b, 0x4ba1841d, 0xc9830573, 0x19534c20, 0x20b78506, 0x82e882fb, 0x12194e09, 0x2916754e, 0x24f70693, + 0xff066b07, 0x8283c9ff, 0x05250482, 0xf8f9ffff, 0x553a1952, 0x1e85280d, 0xffff088b, 0x640040ed, 0x8d830e2d, 0xb3110026, 0x07cb0834, 0x0b637c18, + 0x880e0021, 0x18758218, 0x20135ec5, 0x090d50cb, 0x4f7b5421, 0x002305fb, 0x8285ab11, 0x12002265, 0x236582c0, 0xe27a0800, 0x08313a82, 0xffffd723, + 0xff9a99fc, 0xae070600, 0x00ff0885, 0x830b8236, 0xab0521a9, 0x8320b683, 0xf2218e82, 0x5aeb89b3, 0x07240998, 0x156cfb3b, 0x47052247, 0xff220532, + 0xde46ccf8, 0xff34210c, 0x0fcda918, 0x1dff7518, 0x4682cd20, 0x44cdcc21, 0xf72f06b4, 0x088b3333, 0xf80e064b, 0x15f4f744, 0x84ab065b, 0x84ab26cc, + 0xabf1ffff, 0x28cc8286, 0xffff7c54, 0x8b7a54ee, 0x05b47a08, 0x69185420, 0xb17b09ca, 0xf4fb2108, 0xff2c3382, 0xff66a6dc, 0x67a61c00, 0x59e3ffff, + 0x2323e382, 0x7e8b9a59, 0x79180506, 0xff3014aa, 0x7c142000, 0x5000ff07, 0x00fff6a8, 0x05a4f023, 0xd72b3b82, 0x0c00ff0a, 0x00ff46e1, 0x82008012, + 0x9a99290e, 0x1f00ff8b, 0xee080080, 0x00245e82, 0xff34332c, 0x2a0ff24d, 0xa4fba4fb, 0xffff8b15, 0x829a19f7, 0x66e621d1, 0x0e820486, 0x84088b21, + 0x201b8215, 0x221682f8, 0x83190700, 0xe608224b, 0x83918266, 0x8209824c, 0x833582fd, 0x00ff2119, 0x30820e82, 0x16850684, 0x3582ff20, 0x08255785, + 0xcb0774fb, 0x2164e98b, 0xc4820020, 0x0487e020, 0x0020f722, 0x0682c984, 0xc9be1685, 0xe834f722, 0xf921ca83, 0x216082c0, 0x048240fc, 0x0488fa20, + 0x4861fd27, 0xc9ffff08, 0x28148280, 0x0552b8e7, 0xe69900ff, 0x05ab4666, 0x8b66e622, 0x23101541, 0x2f0e0728, 0x6cc07b18, 0xdcfb5b22, 0xf220b983, + 0x9376b983, 0xffff2107, 0x8b200e82, 0x0683b582, 0x5205ef44, 0xdb260a3c, 0x0614fb07, 0xd54f073b, 0x761d8205, 0xff230785, 0x8433b3f2, 0x0a6b4334, + 0x4434b321, 0x08220550, 0x308264f7, 0x180d0021, 0x5e1683bc, 0x7a7c0907, 0x073b2308, 0x4a4c14f7, 0x24348605, 0x0a00ffcc, 0x190482cc, 0x5e12bc1c, + 0xfb21083c, 0x073e4164, 0x164f7a18, 0x2205e85e, 0x7134b3dc, 0x584d0975, 0xd4fb2106, 0x20180350, 0x72ba83d4, 0xf7281309, 0x34fb06d4, 0xff15e4fb, + 0x410a9353, 0xcb210a28, 0x45d21807, 0x05b2533d, 0x2005c253, 0x0bc95308, 0x45f5ff21, 0x4b2008e0, 0x4c45d218, 0x00ff2f27, 0xf700404d, 0x24d18254, + 0xff666689, 0x5b048200, 0x342237a6, 0xe25c34fb, 0x84f7201b, 0x06002b1f, 0xffff3433, 0xff34b3f9, 0x1e190800, 0x33201149, 0x5b0d0767, 0x762224a6, + 0xb68248a1, 0x82006021, 0x0cc023b6, 0xc8e98bcc, 0x88682621, 0x27b05dc8, 0x221c6f5c, 0x8514ae76, 0x2f0e2cc8, 0x99f600ff, 0xd600ff9a, 0x18159a99, + 0x5d0e24c9, 0xc35d101d, 0x7389281c, 0x76ffff33, 0x820566a6, 0x23508205, 0x9a9976ff, 0x241ba241, 0x3a0600ff, 0x057f71e1, 0x2e080023, 0x14a56815, + 0x19a43021, 0x2008e71f, 0x05445d71, 0xf734f724, 0xd9820534, 0x82e27a21, 0x66862704, 0x1400ff8b, 0xcf5d3433, 0xf7082309, 0xc5bf8b54, 0xc5ae3220, + 0xf9227f83, 0x634200c0, 0x82342014, 0x2e0822a0, 0x5ec58814, 0xc59f060a, 0x30fb0e27, 0xa13600ff, 0x06417548, 0x5e890028, 0x8900ffb8, 0xf982ce4c, + 0x66668922, 0x99219f82, 0x420a8299, 0xcc2105dd, 0x2bc55fcd, 0x411a1442, 0xfb201ffc, 0x851e7343, 0xf3ff2d5a, 0x00ff0080, 0xff904214, 0x66060000, + 0x082b6e89, 0xf89f00ff, 0x0d00ff52, 0x5f153433, 0x64ab1b7f, 0x18004021, 0x21081b87, 0x60820080, 0x21055444, 0x26419a59, 0x410a8309, 0xcc200626, + 0x24462641, 0xfa5fffff, 0x21cc82e2, 0xdb6a9af9, 0x66a92105, 0x0482e582, 0x44ff1521, 0xca18346e, 0x1a600e41, 0x80f32212, 0x05464100, 0xc0ebff22, + 0x9b60f082, 0xff082508, 0x48a176ff, 0x93220482, 0x0a850533, 0x6b890023, 0x91fe1885, 0x00ff2c36, 0xff1e05a0, 0xae0760ff, 0x4134f705, 0x762007a5, + 0x4409c643, 0x662105f8, 0x455eb666, 0x3821078f, 0x07f14352, 0x41288f45, 0xc7222c20, 0x6082ffae, 0xa7449a20, 0x0e082609, 0x54f7b0fb, 0x1eae188b, + 0x1834201c, 0x275a19ce, 0xffb89e76, 0x00a076ff, 0x220d9242, 0x8400800c, 0x23ae18a2, 0x098f7610, 0x82102479, 0x95cb20c8, 0x458f20c7, 0x6a18051a, + 0x89221cf8, 0xef45866b, 0x218d8205, 0x7a477b94, 0x0dcf1806, 0x12af1819, 0x06ca411a, 0x2644c298, 0xbff92206, 0x05b146ff, 0x19f7ff21, 0x250dde37, + 0xf730fb0e, 0xb018ebf4, 0x76221d77, 0xa282b89e, 0x46335321, 0x9920094a, 0x180a4a46, 0x4153a0cd, 0xcc211a90, 0x23c882cc, 0xffffcecc, 0x0ebee918, + 0x5421c883, 0x3b5942cb, 0x821a6541, 0xb85e26fe, 0x9376ffff, 0x06394234, 0x210e2c49, 0xcd1800ff, 0x5442185a, 0x07914110, 0x1978b018, 0xf714f738, + 0x14f815f4, 0x0794fb06, 0xa4f706cb, 0x00ff8b07, 0xff48611a, 0x0482eaff, 0x9e150022, 0xe5298882, 0x088bb89e, 0xff0634fc, 0x830983ff, 0x84472019, + 0x826c821e, 0xfb082210, 0x2b3883a4, 0x84f80794, 0xe6e0feff, 0xf4fc1566, 0x0c231e19, 0xc0f8ff23, 0x24298200, 0x080040f7, 0x215c827b, 0x8a82dcff, + 0x91580020, 0x00ff2907, 0x8b004023, 0x0694f808, 0xff200985, 0x04831984, 0x1a828682, 0x829b0821, 0x07002432, 0x57ff66e6, 0x0822051c, 0x01579a19, + 0x2f0e2506, 0x54f814f8, 0x1a8c8818, 0x4e14fc21, 0x3f820ae1, 0x180ae14e, 0x20188c88, 0x223383f8, 0x82592300, 0x4ce32164, 0x0c8c8818, 0xfc34fb27, + 0xffff1564, 0x27ad82ee, 0xc0f1ffff, 0x0e00ff00, 0x00240a83, 0x0800c011, 0x0682aa82, 0x04861184, 0x8b220e82, 0x1c83ff08, 0x28821b82, 0x8b203284, + 0x2d823e84, 0x11824583, 0x84cdcc21, 0x28158216, 0x088b3333, 0xf730fb0e, 0x22d083d4, 0x18ff0694, 0x6b0ab261, 0xfc210a49, 0x18496b34, 0x00233382, + 0x1990821a, 0x20118442, 0x833383f8, 0x6bff201a, 0xfb210ff0, 0x29d0df14, 0x74f7eb2f, 0xf4ffff15, 0xf98252b8, 0x7b54f52b, 0xb3fdffff, 0xf5ffff33, + 0x260482f3, 0x086766fc, 0x6d0500ff, 0x232505d2, 0x00ffcc4c, 0x821b821c, 0xff342604, 0xcd4c2300, 0x201c828b, 0x08457611, 0x99180020, 0xff242023, + 0x856bb9ff, 0xc6216582, 0x22658294, 0x829a99c6, 0x66b9250a, 0x072b0866, 0xca220882, 0x9918e2fa, 0xff251020, 0x1f053500, 0x2316858b, 0xe2fa2a00, + 0x35230a82, 0x85081e05, 0x18602006, 0x2207dd93, 0x8a8b94f7, 0x827a20bf, 0xecb121bf, 0x3425bf83, 0x6dfcffff, 0x22a2820e, 0x5d06e105, 0xb32009c3, + 0x1c20ba82, 0xce820483, 0x8620bf85, 0x0e234f82, 0x93ff7a54, 0x0da751bf, 0x8420bf83, 0x7c23bf84, 0x19c6ffff, 0x8b084948, 0xffe225bf, 0x1e05d5ff, + 0x1e20b883, 0xae825d83, 0xdb84bf84, 0x0e24bf96, 0xf4f7eb2f, 0xca21c182, 0x3d9a18fa, 0x66e62109, 0xca226682, 0xeb829a19, 0x0682ff20, 0x23050241, + 0x66e6d5ff, 0x82051241, 0x470b22d4, 0x375982ae, 0xff85ab0a, 0x144e0200, 0x0c0a00ff, 0x0300ffcd, 0xff08f292, 0xfa1efaff, 0x200a0179, 0x06e84ecd, + 0x9b4fdc20, 0x3b871805, 0x094f5d0b, 0x18ffff21, 0x2215d3eb, 0x827b9446, 0x50491965, 0x240a8207, 0x087c9446, 0x245d82eb, 0x66e63500, 0x28968260, + 0x8b569a19, 0x2bf4f708, 0x221b8215, 0x86200535, 0xfa2a28fd, 0xcaffffe0, 0x828be2fa, 0x8506838d, 0xd5ff2316, 0xd6832005, 0x84e0fa21, 0xe1fa21d6, + 0xfa213f82, 0x201b83e2, 0x0830411f, 0x8620d687, 0xcc20d688, 0xcc20d695, 0x3420d688, 0xbe826583, 0xf1225a82, 0x901886ab, 0x96180bb8, 0xff211639, + 0x84c58200, 0xff8425d6, 0x846b3900, 0x0e20d688, 0x6075321a, 0x34fc8b22, 0x090a4e18, 0x43008021, 0xff2005ee, 0x07055718, 0x2008cb6e, 0x091f5c00, + 0x160db218, 0x0b7c4318, 0x84eaff21, 0x23458238, 0xf7c4fb08, 0x0a39b318, 0x180de75b, 0x22449066, 0xdc8b94f8, 0xfeff31c0, 0xfbe2fa4a, 0xffff1549, + 0xff0040ed, 0x34b31200, 0x08684618, 0x0f83c020, 0x08cccc22, 0x0a841582, 0xff34b326, 0xb85e1e00, 0x12221f82, 0x2f82cdcc, 0x1a844c20, 0xff221582, + 0x358233ed, 0x07524618, 0x1a86cc20, 0x33201582, 0x33270a82, 0xe1ffff34, 0x878b48a1, 0x2b508260, 0x00ff078b, 0xff85eb43, 0x9a192601, 0x33207883, + 0x4c202783, 0x278b3782, 0x0834b322, 0x42213282, 0x217d828f, 0x7382cccc, 0x0a827982, 0x8471bd21, 0x8393888d, 0x21938b98, 0x1a830040, 0x40219384, + 0x82738200, 0x848e8451, 0x201a8288, 0x238e83e2, 0x15cccc1d, 0xef845684, 0x6621d482, 0x82608266, 0x20d488fa, 0x8b8c82cc, 0x203583d4, 0x20ef83ed, + 0x840582ff, 0x21d4824b, 0x60829a99, 0x4a842582, 0xc282ac83, 0x820c4041, 0x12002186, 0x6618ef84, 0x72200860, 0x5782f718, 0xf78b0e24, 0xe5181554, + 0xff325bbc, 0x9a19a400, 0x80baffff, 0xffff1500, 0xff3333fa, 0xdf820600, 0xe6f5ff2d, 0x0000ff66, 0xffff32b3, 0x83cd4cf9, 0x08342118, 0x14820a88, + 0x1483ff20, 0x68e6f527, 0xcc0500ff, 0x271883cc, 0x00ff08cc, 0xff343316, 0x2005ad5b, 0x20148326, 0x265782e4, 0x34333600, 0x82c3088b, 0x822620c0, + 0x1b00214b, 0x16255583, 0x00ffce4c, 0x05077919, 0x6f852782, 0x1483ff20, 0x98190a22, 0x55834b84, 0x6f84ce20, 0x6086cc20, 0xff206a83, 0xa2822383, + 0xcc269384, 0xffff7908, 0x7b824ceb, 0x0080e125, 0x83eaffff, 0xb3d3217a, 0xff296b82, 0x0080d5ff, 0xe1ffff8b, 0x20c08266, 0x215f8215, 0x8783eeff, + 0x34b31428, 0xff068b08, 0x32820c00, 0x84950021, 0x566b18ec, 0x1e811809, 0x4353190f, 0x00ff2411, 0x829a9911, 0x830e20c5, 0x4c0e2155, 0x0cd1b018, + 0xffff3428, 0xff9a99f1, 0x5a820e00, 0x66eeff29, 0xf7088b66, 0xad154b34, 0xffff2431, 0x82ce4cee, 0xb3f122b5, 0x38c01832, 0x208d8410, 0x201683ce, + 0x23548233, 0x088b32b3, 0x27621442, 0xffcd4c9f, 0xcc4c7bff, 0x0c21c782, 0x25778233, 0xffce4c27, 0xfd832600, 0x04831d20, 0x9a192e26, 0x00ff088b, + 0x16850683, 0x99e2ff2d, 0x0c00ff9a, 0xffff3433, 0x8232b3d8, 0x99022b1a, 0xf7ffff98, 0xff940080, 0x3b83fbff, 0x68660827, 0x990200ff, 0x221a829a, + 0x83008008, 0xff98250a, 0x32b30400, 0xfd201f82, 0x1f825183, 0xffff0823, 0x291a83ef, 0x58323335, 0xc4ffffb2, 0x63823433, 0x4cc4ff2a, 0xffff8bcd, + 0x6466e6cc, 0xff231e85, 0x82ceccca, 0x21348329, 0x6482f7ff, 0x34234482, 0x8300ff82, 0xfdff2354, 0x5f836866, 0x0a824f82, 0x84946621, 0x84758460, + 0x8b082f1f, 0x1100ff06, 0x00ff9919, 0x1534b3d4, 0x0210ffff, 0x231c0100, 0x9b6666b0, 0x2132c442, 0xa8428bcd, 0x21524305, 0xcb34f723, 0x2df64215, + 0x242f5243, 0xfb9a994f, 0x95921834, 0x54f7212e, 0x6517fb60, 0xfb3716e0, 0xef0e0654, 0x14f854f8, 0x0694fb15, 0xf595ffff, 0xffff8bc2, 0x823d0aaa, + 0x66e62104, 0x95200a82, 0x82057c4a, 0x00ff2406, 0x84c3f555, 0x00ff2c16, 0x8b3e0a6a, 0x0694f708, 0x83e18bf5, 0x83338216, 0x82082012, 0x20198263, + 0x2e128435, 0xff088b21, 0x9a1937ff, 0x6b156cfb, 0x19076b06, 0x21084d36, 0x75195238, 0xcd2008e3, 0xf2222283, 0x1b82cdcc, 0x142ef527, 0xcc0a00ff, + 0x314182cc, 0x0834330d, 0xffff07ab, 0xff66e6e0, 0x66e60000, 0x4d78ff05, 0x4cf42506, 0x0900ffcc, 0x00209583, 0x2a842383, 0x35823320, 0x829ad921, + 0x5ccf2204, 0x201582ff, 0x2a518233, 0x34f31f00, 0xfdffffff, 0x5aab0571, 0xd1210969, 0x08345aec, 0x0d222384, 0x3f823333, 0xaec70a22, 0x9c858c84, + 0x076b0824, 0x458306ab, 0x1a833420, 0x83ead121, 0x8325821a, 0x22ca827d, 0x83e2faff, 0xffcc2588, 0x9a19f6ff, 0xff223584, 0x8c82f1ff, 0x4cf70829, + 0xffff154b, 0x8248e1e9, 0x05ef2745, 0x1100ff1e, 0x4082b8de, 0xe23a1523, 0x84068508, 0x00ff2311, 0x1b82c512, 0xa2831582, 0x16850683, 0x1eeeff22, + 0x3e832d82, 0x06832d82, 0xefffff22, 0xff20f882, 0x74244982, 0xebcb088b, 0x16225ab0, 0x7682ba1e, 0xe0fa1023, 0x205a94ff, 0x825f8264, 0xe9ff2da4, + 0x088b0200, 0x94f8af0e, 0x54fc158b, 0x1727f318, 0x4c18f720, 0xff241bfa, 0x98592300, 0x1c236a82, 0x18ff68a6, 0x180b9d5d, 0x2519624d, 0x15a0f714, + 0x328207b3, 0x9a990634, 0x99faffff, 0x0500ff99, 0xffff6666, 0x8b6666f9, 0x84826308, 0x4761f923, 0x2118828b, 0x0482b89e, 0x829a9921, 0x2119820a, + 0x31826308, 0x2c822283, 0x84486121, 0x00ff2818, 0x8bb99e06, 0x8206b308, 0x82268308, 0x84672045, 0x225a854a, 0x8c8beb08, 0x909a2066, 0x856f8266, + 0x92848248, 0x20938366, 0x20a282fa, 0x8da78200, 0x10662066, 0x40016600, 0x2b14fc22, 0x100c9c41, 0x5b020302, 0x44b4f721, 0xfb221a08, 0x7944067c, + 0x29094405, 0x3282f720, 0x44060021, 0x0a440671, 0xaf0e2c73, 0x80fd01ff, 0xbf01ff00, 0x821502fa, 0xe2da22bd, 0x2605828b, 0xffff709d, 0x82f0a7fe, + 0xe3210809, 0xfdffffd6, 0xff08f41d, 0xd8e3d3ff, 0x23ebffff, 0xdfffffd6, 0xffffcc4c, 0xff86ebf8, 0xc2b5e4ff, 0x221a828b, 0x822a1cc6, 0x5cde3135, + 0x1f00ff28, 0xffff2adc, 0xff7b54bd, 0x8e020000, 0xde221a82, 0x0a82a570, 0xff060036, 0xcd4cd6ff, 0xfff7ffff, 0xc6ffff0e, 0xffff33b3, 0x08aaf1e7, + 0x61281982, 0xff8b0748, 0x00c01100, 0x22050a55, 0x82400e00, 0x40ee2209, 0x55568300, 0xff23096b, 0x5500c0f1, 0xff27063d, 0xc2f5ffff, 0x560564fc, + 0xff220551, 0x30830700, 0x3f82f820, 0x7d080021, 0x2024053d, 0xff063e0a, 0x1c850c84, 0x2b0a686d, 0xff0704f7, 0x71bd3300, 0xdc1700ff, 0x2822ab82, + 0x228251f8, 0xffc4f526, 0x0b972300, 0x00237082, 0x820b1747, 0x82312a8c, 0xe0ffff8e, 0x00ff5238, 0x05d34b47, 0x5ccf1e22, 0x22201682, 0x05273283, + 0x00ff10f8, 0x82146e2a, 0xfa1e21b2, 0x0c26bf82, 0x00ff3433, 0x2b82f804, 0x82b30721, 0x800b2109, 0x0029a682, 0x08cc4c0c, 0x5c2d01ff, 0x2fda832a, + 0xffe0ba12, 0xccccefff, 0xfc0b00ff, 0xedffff92, 0x2105914d, 0xe68280e2, 0x32397223, 0x21698215, 0xfb829002, 0xffc2f53b, 0x142ee6ff, 0x73f9ffff, + 0xe9ffff32, 0xffff5ccf, 0x089a19fe, 0xcaafffff, 0x3bb4823e, 0xffa47019, 0x1d7a0100, 0x261a00ff, 0x0500ff66, 0x00ffdb79, 0xfff6681c, 0x12630a00, + 0xae232482, 0x82079042, 0x862b3535, 0x8ff8ffff, 0xeaffff1a, 0xffff66e6, 0xff6c5cfc, 0x66e6ebff, 0xff2ed982, 0x8b928dfa, 0xbcfaffff, 0x0000ffac, + 0x0982026d, 0x8270bd21, 0xfc762109, 0x4a22c282, 0x3b82e296, 0x6290fb2b, 0xbeffffff, 0xfbffff01, 0x211f828b, 0x04829bff, 0x5e9afb22, 0x96823b83, + 0xea213b82, 0x21e48278, 0x6c828c04, 0xd8a3ec22, 0x88218182, 0x220a8273, 0x820a17bd, 0x30e8213b, 0x06219c82, 0x20bc820e, 0x261a84e5, 0xffffe25a, + 0x82842be2, 0xec9121b0, 0x4b226082, 0x2482fce6, 0x3333fc22, 0x66216082, 0x21978267, 0x7b82cd4c, 0x87666622, 0xec265c83, 0xff8bcd4c, 0x1282e8ff, + 0x20050c6a, 0x22b983e6, 0x829999f8, 0xe6ba225c, 0x20378266, 0x223783eb, 0x82ceccfa, 0x82b320d4, 0x99f92241, 0x2609829a, 0xffff9919, 0x826666f7, + 0xb33f335c, 0x00ff0733, 0xff1fc518, 0xd7630a00, 0x0e00ff05, 0x9d82ae07, 0xff5ccf25, 0x82cc0c00, 0x82042067, 0x0c00282f, 0x00ff6666, 0x82cccc04, + 0xb351222f, 0x20548234, 0x206583ec, 0x840483fa, 0x4cf9255e, 0xe7ffffcc, 0xf5220e83, 0x248268e6, 0x00803f22, 0xd6205489, 0xe3205488, 0x5485f782, + 0x82cc8c21, 0x2254835e, 0x8234f303, 0x97bd22a9, 0x2a2f820a, 0xffd7631a, 0xf8f30600, 0x821600ff, 0x030028a9, 0x00ff8c37, 0x82d86313, 0x72fd21f5, + 0x04285482, 0xff8b6f12, 0x9f9a0300, 0x8e211082, 0x21098202, 0x098211d8, 0x82fcc621, 0xe844221a, 0x213f8272, 0xd5829912, 0x146efe26, 0xcc0f00ff, + 0xfb258f82, 0x00ffce0c, 0x22f88312, 0x4e50b8f9, 0xff280623, 0x943433fd, 0x2efdffff, 0x09202482, 0xfd22b483, 0x7f837c54, 0x8214ee21, 0xca142c3f, + 0xf9ffff3e, 0x00fff628, 0x82f6a814, 0x46e12709, 0x421900ff, 0x3b828b8e, 0xfe340422, 0x042c7b82, 0x00fff292, 0xff047a00, 0x4e820400, 0x62210982, + 0x221a8200, 0x4226c044, 0x1e20095f, 0x20085f42, 0x0c5f42da, 0x6866c030, 0xff84fb07, 0x66e60700, 0xafffff15, 0x3282c2f5, 0x289c1224, 0xae85ffff, + 0xff90c226, 0x090cfbff, 0xdc21ae82, 0x2178822a, 0x578216b9, 0x52780822, 0x2321a882, 0x23ae83d7, 0x00ff3433, 0x4c21ae85, 0x281a82cc, 0x0766e652, + 0x19e8ffff, 0x2650839a, 0xe7ffff68, 0x4eff0080, 0xe02a05ad, 0x00ff6666, 0x0866e601, 0x3182af0e, 0xff3b5f26, 0xb85e6901, 0xf3237182, 0x7fff0681, + 0x4221073b, 0x210a8290, 0x0f84fa7e, 0x0c224c82, 0x0a827d7f, 0x82707d21, 0x8f4221f5, 0x23061160, 0x9082f3ff, 0xbf211a82, 0x238282f8, 0x0552f83f, + 0x18099c60, 0x2610e185, 0x0740ffff, 0x5c54fbae, 0xbd210d60, 0x22278271, 0x848380f3, 0xff082237, 0x837e8bff, 0x890c20cb, 0x53a9277e, 0xa900fff8, + 0x40826666, 0x82ac5621, 0x5ea92d73, 0x02ff05b8, 0xffc4a016, 0x48a1b6fe, 0x0e136118, 0x390d7c18, 0x08236618, 0x0ec2c118, 0x0e06b435, 0x9e01ffef, + 0x01ffcccc, 0x15c23597, 0xfeff14fb, 0x8272fd3f, 0x19fb2b8c, 0xffff7a9a, 0xffce4cee, 0xb282f6ff, 0xffeeff23, 0x050243ff, 0x06827a20, 0x8366e621, + 0x053b5115, 0xcc220e82, 0xb9829ccd, 0x01008025, 0x83bf01ff, 0x0400213c, 0x00342082, 0xff76fe10, 0x32b31100, 0xd70900ff, 0xffff9c0a, 0x08de24fb, + 0x25210683, 0x2011821e, 0x215782cc, 0x618249ee, 0x3233fb2d, 0x02efffff, 0x068b088e, 0x826700ff, 0xafff2887, 0xf715d863, 0x4104fb04, 0x41181b75, + 0x02200868, 0x2105b75e, 0xaf18ebff, 0x59202a18, 0x0023d482, 0x82666659, 0x83a620e5, 0x610a859e, 0x8b230728, 0x181400ff, 0x210e49af, 0x4361800c, + 0x82198306, 0x7f0c221f, 0x267684fe, 0xff078b08, 0x8200a0fe, 0xccd22883, 0xffff15cc, 0x8266a6a6, 0x9a992104, 0x5922b982, 0x0a879a59, 0x180beb5e, + 0x600cc8ec, 0xff200967, 0x8f25bf91, 0x04f7d5f8, 0x1c3a4205, 0x2b077022, 0x0c544318, 0xc142b884, 0x18802008, 0x18073342, 0x8c078942, 0x078b327b, + 0x00ffaf0e, 0xffcd4c88, 0xcdccdd00, 0xaf00ff15, 0x220082ff, 0x8267e668, 0x610f31bb, 0xf2ffff48, 0x00ff34b3, 0xff5c4f18, 0x46c10a00, 0x142e5482, + 0xff087cb4, 0x3c0a5400, 0x6c00ff07, 0x98820080, 0xff866b25, 0x82992a00, 0xcad125e6, 0xd9ffff3c, 0x84321383, 0xff08d8e3, 0x10f8faff, 0xe8efffff, + 0x1300fff6, 0x2882e670, 0xffae872b, 0x66a60d00, 0xf00900ff, 0x264382a4, 0xff02c02b, 0x82cf1f00, 0x97272159, 0x3c220e82, 0x5e8248e1, 0xf6683d23, + 0x31068208, 0xffce4c83, 0xd823a1ff, 0xe62900ff, 0x7effff64, 0x7f8228dc, 0x08ce4c24, 0x1c8207dd, 0x84ab1427, 0xb8e7ffff, 0x26128252, 0xffff3eca, + 0x840a97f0, 0x367182a6, 0xff010050, 0xc2f567ff, 0xf4ffff05, 0xffff66e6, 0x8b0080f6, 0x82eeffff, 0x0b0022f1, 0x22a18219, 0x826766f6, 0x02802825, + 0xf7158b8f, 0xa0ffff44, 0xd40f38e6, 0xffff077a, 0xff7b5462, 0x5c4f8700, 0x9d00ff05, 0x00ff33b3, 0x82343388, 0xc70f220a, 0x208c9bae, 0x205f84fb, + 0x22898364, 0x18ffd7e3, 0x230abeeb, 0x7b140b00, 0x89829982, 0xff2f0e2d, 0x9a991d01, 0xe60300ff, 0x55ff1566, 0xf127057e, 0x837ccecc, 0x82f1ffff, + 0x020026c8, 0x7c0866e6, 0x26ca828e, 0x00ffcd4c, 0x829a190d, 0x4c0f29fa, 0x44f708cc, 0x0644fb07, 0x9c212382, 0x2edc8229, 0xff0ad7f2, 0xcdcc0a00, + 0x0cfdffff, 0x85089acd, 0x00ff2406, 0x827b1408, 0x260e3258, 0x0500ff67, 0xff08cdcc, 0x1e056001, 0x059000ff, 0x27b9821e, 0xff66e60b, 0x48e10400, + 0xb3215482, 0x26308234, 0x00ff703d, 0x829a1909, 0xd8e32294, 0x830a8708, 0xcc02261e, 0xf2ffffcc, 0x2004824c, 0x281e83fb, 0x08ec11f4, 0xfeff24fb, + 0x264582a0, 0xcb54f80e, 0x1806ab15, 0x7e16f3f3, 0x811805f8, 0x6c511072, 0x18ee2006, 0x21125a6b, 0x1582ffff, 0xf1203682, 0x736f9182, 0x01ff2a0a, + 0x0734b332, 0x4c2dffff, 0x200483cd, 0x27bd82cc, 0x0633b3b2, 0x74fb074b, 0x2c0e1850, 0xff8b34b3, 0xcc4c2300, 0x0794f708, 0x17db6f6b, 0x082c6a18, + 0xff7b5426, 0x7c540e00, 0xab24be82, 0xab088b85, 0x2007f76e, 0x21541886, 0x7a542107, 0x06821a86, 0x8233b321, 0x830e2036, 0x6fac1880, 0xfeff2809, + 0x07cc4ccd, 0x83d200ff, 0x270482ae, 0x4dffff05, 0xcb06cc4c, 0xf2281282, 0xff0634b3, 0x32b33600, 0xa0210482, 0x08996ac4, 0x43fa7e21, 0x81240d96, + 0x00ff0806, 0x20064044, 0x26f88284, 0xff70bdeb, 0x4480f3ff, 0x082005c7, 0x2507c370, 0xff057c54, 0x6a82edfe, 0xf72f0e26, 0x1504f834, 0xdf252882, + 0xffff3433, 0x208e83ec, 0x286382e4, 0x33b3e3ff, 0xccf2ffff, 0x223282ce, 0x823233a8, 0xcc12367f, 0x0a00ffcd, 0x00ff67e6, 0xff66e615, 0x33330600, + 0x4c1700ff, 0x7ba019cd, 0x1c00210f, 0x2322d784, 0x8782cd4c, 0x34b30624, 0x4a82ff07, 0x00ff3425, 0x8332330d, 0xffcc255e, 0xce4c1b00, 0x2023f882, + 0x8208cccc, 0x2e2c2606, 0x2300ff14, 0x221682cc, 0x18ecd123, 0x2307957b, 0x34332c00, 0x16831b82, 0x0dd27a18, 0xcc22a386, 0xa386ffff, 0xa3873420, + 0x997ff920, 0x83b92005, 0xb3c621bf, 0xc6201682, 0xb925bf83, 0x088bcc4c, 0x8771182b, 0xe3ff210c, 0xff231382, 0x59b3dcff, 0xcc20051d, 0x1c20d982, + 0xf3203483, 0x00213482, 0x22348313, 0x41cccce3, 0x9f82050e, 0x82d3ff21, 0xdcff219a, 0x0482eb82, 0xd3215582, 0x23f082cc, 0xd1d3ffff, 0x12f6c918, + 0xff28d485, 0x00c01300, 0x331c00ff, 0x1c21f382, 0x2c098240, 0x08cc4c0c, 0x66cd00ff, 0xffff0768, 0x411a83e3, 0x1a830509, 0x23120941, 0x00ffecd1, + 0x22050941, 0x828b152e, 0x332c2237, 0x22578233, 0x18cdcc23, 0x230ccd7c, 0x15733b07, 0x0bb4de18, 0xc00a0023, 0x22268200, 0x8200400d, 0x820020b3, + 0x07b76e06, 0xce6e6f82, 0x11da7311, 0x32863f83, 0x8b243c82, 0xbbb4f708, 0x1b2d8119, 0x00205582, 0x82072374, 0xcc4c2186, 0x3a74a983, 0x228d9309, + 0x85ffcc4c, 0xb3f22864, 0xfb088b34, 0x8e24fcb4, 0x082c6fc0, 0x6f05336f, 0xff200978, 0xe373c093, 0x205b850f, 0x846583f5, 0xef0e2bc0, 0xb3b900ff, + 0x4701ff33, 0x688234b3, 0xcdcc383e, 0x7a2c00ff, 0x5200ffe0, 0xffff3433, 0xff0a17fc, 0x66663300, 0xa1ccffff, 0x5fb70848, 0xcc359a82, 0xbfffffcc, + 0xffff0080, 0xffcecce7, 0x9a19caff, 0x1f00ff08, 0x262182e6, 0x059a19e7, 0x825f00ff, 0x1804830a, 0x2828587a, 0x6bae8704, 0x33e8ffff, 0x587a1834, + 0x18882059, 0x2308587a, 0xffffbd64, 0x20587a18, 0xdd83a520, 0xc2820482, 0x0a838d20, 0xd8849120, 0x68660a22, 0x83d8e318, 0xd7e39227, 0xcf8cffff, + 0x329c82e0, 0xff676634, 0x3233d7ff, 0x7300ff15, 0xffffcc4c, 0x826766a5, 0xe6052a15, 0x1a00ff66, 0xffff3333, 0x2db182f8, 0xcd4c1c00, 0x1300ff77, + 0xff08ffff, 0x1a83e6ff, 0x9a191925, 0x82daffff, 0x05002fd7, 0xff6c9a19, 0x66e6f1ff, 0xff078b08, 0x1c821800, 0x1925ff27, 0xffff159a, 0x212282e2, + 0x0f831d00, 0x9999f12a, 0x4c2800ff, 0x0200ffce, 0x00335182, 0x08cccc27, 0xb3b900ff, 0x6dffff34, 0xff059a99, 0x82ccceff, 0x66f12a77, 0xc8ffff66, + 0x00ff0080, 0x2138820c, 0x0482d9ff, 0x85260021, 0x22268355, 0x83c000ff, 0x32002255, 0x22788299, 0x829919d8, 0x4cc22436, 0x82ffffcd, 0x077e1804, + 0x382408b6, 0x00ffd763, 0x05676638, 0xf7f0fb0e, 0x6b158b34, 0x0774f706, 0x1100ff8b, 0xffffa4b0, 0xff85abf1, 0x5c4f0e00, 0x2205c376, 0x828b4b08, + 0x0b4f63e4, 0x11054d18, 0xff7b5426, 0x0a97f2ff, 0x21080a47, 0x3f4754fb, 0x18ff200e, 0x18099c91, 0x83089869, 0x86168234, 0x14f72234, 0x18098506, + 0x1809605b, 0x260f8c68, 0x00ff33b3, 0x82f6680d, 0xcd4c2796, 0xf74b088b, 0xeb6115d4, 0x1900200b, 0x1809c40b, 0x210d5552, 0x5218e07a, 0xd5180855, + 0xc9660925, 0x2390820a, 0xff727de5, 0x71253f82, 0x85eaffff, 0x2954851e, 0x74f80e08, 0xf715b4f7, 0x4d820714, 0x0a170b37, 0x40faffff, 0x0a00ff00, + 0xffffae47, 0xff7a94f6, 0x9ad90500, 0x210a8208, 0x0a82ec91, 0xfff8d32b, 0x3433f4ff, 0x800000ff, 0x06405900, 0xde0ffb34, 0x057b6b08, 0x30f0ffff, + 0xf8ffffa4, 0xffff1218, 0x458297f9, 0x36c9ec27, 0xe80700ff, 0x271882f6, 0xff08162e, 0xc2b50400, 0xc7263b82, 0x0c00ffae, 0x23823233, 0xff3c8a2a, + 0x34b30b00, 0x073b088b, 0x5421e882, 0x08ee637a, 0x22127541, 0x41ffff7a, 0x86200640, 0x0f8bba18, 0x18d86a18, 0x82ec5121, 0xcc4c2756, 0x34fb088b, + 0xa31815ab, 0x6b202dd8, 0x0021df82, 0x22d2829e, 0x825c8ff5, 0x35f62196, 0xfa37b982, 0xffff24e6, 0xff9002fa, 0xe670f7ff, 0xaaffff08, 0xffff5238, + 0x82257585, 0x230a8325, 0xaf877a00, 0xfa290a82, 0x00ff8f02, 0xff5c8f08, 0x253483ff, 0x98190500, 0x4483ffff, 0x426b0821, 0xae210f5b, 0x23598214, + 0x08ec51ee, 0x0c420685, 0xf1ff2305, 0x4b4914ae, 0x570f2608, 0x00ff060a, 0x224c8359, 0x82900280, 0x66a6245c, 0x8214fb66, 0xb3f02207, 0x0cb34933, + 0x42177342, 0xd0860aa8, 0x700a002e, 0x00ff8ba4, 0xff3dca09, 0x04160500, 0xfd210482, 0x2daf8271, 0xff086290, 0xaec75500, 0xa57900ff, 0x0a8505ca, + 0x8085ff23, 0x220a8200, 0x821e0506, 0x666621f1, 0xcc253482, 0xfaffffce, 0x260982e6, 0x8b66660a, 0x82ffab08, 0x82622000, 0x19112021, 0x220fb14d, + 0x823eca10, 0x820020d4, 0x79ff2006, 0x0f220518, 0xe141c235, 0xff082805, 0xf6a8f0ff, 0x82ffff06, 0x82f720c9, 0x590028c9, 0x00ff9a99, 0x829a197f, + 0x82ed8346, 0xcd01279a, 0xf80e156a, 0x8f428b74, 0x3e4a2111, 0x22078f42, 0x82080ad7, 0xf893210a, 0xe02bbe82, 0xf4ffff00, 0x00ff082c, 0x82107800, + 0x2a1c2613, 0x0ffbffff, 0x0c8f42e0, 0x8f421782, 0x42382006, 0x1420088f, 0x05223182, 0x8f42e89b, 0x470b2606, 0xf9fffff0, 0x22fe8287, 0x42e0ba0b, + 0xa221298f, 0x1bbd18ff, 0x188f4213, 0x42645021, 0xf721088f, 0x900210d4, 0xab20b001, 0x2a2e5452, 0x99b6feff, 0xffff069a, 0x189919ef, 0x3e0dd546, + 0xf8afffff, 0xff05db52, 0x3302e7ff, 0x00ff8ba4, 0xff989928, 0xcdfd1800, 0x00ff08a4, 0x847c54e9, 0xa4052104, 0x70201283, 0x8b211c84, 0x202a83a4, + 0x271d8290, 0xffce4c89, 0x85ab76ff, 0x0d4b3e19, 0xcc4c7d24, 0x0482ffff, 0x00ff0524, 0x7183197c, 0x66662923, 0x20ac828b, 0x232d8243, 0xcc4c4300, + 0x76276982, 0x00ff9999, 0x82676689, 0x5483270a, 0x83ffff7a, 0x2d82cd4c, 0x53f84f23, 0x2a06823b, 0x8bcccc72, 0x94f80e05, 0x821534f7, 0xa6dc38a8, + 0xeaffff66, 0xffff9082, 0xff9a59e3, 0x707de5ff, 0xffff088b, 0x82ec91df, 0xb50028a9, 0xffffabc2, 0x837a14e8, 0x8af22212, 0x212e823e, 0x248219f5, + 0x0a820482, 0x0080f222, 0x78232982, 0x69076666, 0xff2006a5, 0x4307bc69, 0xb82508fb, 0xff06285c, 0x213989ff, 0x03600a00, 0x82398205, 0x8018225e, + 0x225e8200, 0x8234b3fe, 0x6620230b, 0xdb460866, 0x25888307, 0x707d1500, 0x9c82ffff, 0x06837a83, 0x7e189f86, 0x748209ce, 0xab22a582, 0xa58200ff, + 0xa5820b82, 0x6b834082, 0x87ffff21, 0xffff21a4, 0x4083a382, 0x3f45a482, 0x7fa4180c, 0x00ff240a, 0x829a9987, 0x0d0028c1, 0x00ff0080, 0x82f6e80a, + 0x66e62604, 0x730d00ff, 0x23398233, 0xa4b01700, 0xff285c82, 0xff6bcd8c, 0x67662000, 0x0ebc8018, 0x564f1c20, 0x055d4f08, 0x23050d6a, 0x9a991d00, + 0x22089747, 0x82eb91df, 0xb500281b, 0xffff6bc3, 0x827b14e8, 0xf2ff2340, 0x5382cd8c, 0x0a17f523, 0x82198295, 0xff082576, 0xd6a34700, 0x09404918, + 0x827b5421, 0x166e217e, 0x82081646, 0x820620a0, 0x229f8311, 0x848ec201, 0x8239879f, 0x82a18240, 0x8cff225a, 0x0b4541ce, 0x1c212582, 0x27c582a6, + 0xff0c9714, 0x9a592300, 0x06847682, 0x8300ff21, 0xeaff2316, 0x81828e82, 0xd863e623, 0x22068208, 0x82ea91df, 0xb50022dc, 0x0a4541c4, 0x41ce8c21, + 0xff20050b, 0x7a82a582, 0x83327321, 0xa3472240, 0xdcaa18d8, 0x19ff200c, 0x230a0d11, 0x295cb8ff, 0xdb83c182, 0x45413992, 0xabcc2607, 0x662000ff, + 0x06454168, 0xffffff27, 0x00ffc2f5, 0x23d88215, 0x6766e2ff, 0xdc2f7e82, 0x0e0833b3, 0x54f730fb, 0x00ff15eb, 0x82ae0735, 0xf82a24d2, 0x8200ff52, + 0x820a8204, 0xae7a1910, 0xae072407, 0x82d5ffff, 0x24198304, 0xf8caffff, 0x84528252, 0x83168506, 0x824e821b, 0xfb082417, 0x198b0734, 0x230dec39, + 0x34f72cf7, 0x210e164e, 0x2d82cd4c, 0x9999f328, 0xd7ffff08, 0xc7839a19, 0x84abb625, 0x82c2ffff, 0xc4ff2d61, 0xffff16ee, 0xff85abb5, 0x32b30400, + 0xbd212082, 0x210a83eb, 0x7682442b, 0xff486126, 0xc66b3e00, 0x42239a82, 0x4e08c335, 0x052005e0, 0x0c220682, 0xf84d6766, 0x4d332008, 0x708915f8, + 0x84d9df21, 0x57a62570, 0x3f00ff0a, 0xff26ec82, 0xff5c0fb0, 0x7a835800, 0x66e6f322, 0xdc2a7082, 0x630734f3, 0xedffff06, 0xa5825ccf, 0x9a59f12c, + 0xd1f0ffff, 0x0000ffec, 0x148248e1, 0x08289c22, 0x633a0a82, 0xf7ffffd7, 0x00ff20c5, 0xffb95e07, 0xccccf9ff, 0x330800ff, 0xf7088b33, 0x09820634, + 0x82d43821, 0x59072794, 0x0600ff18, 0x2d834c37, 0x1482d620, 0x83c83621, 0x0ad73738, 0x5e1200ff, 0xf1ffffb8, 0x00ff6866, 0xff34330f, 0xccccedff, + 0x7082088b, 0xc5210032, 0x00ff071e, 0xff34b355, 0xe2ba0b00, 0x4c4200ff, 0x49225682, 0x4c829a99, 0x99835820, 0x70280021, 0xee850556, 0x0a211c83, + 0x31ee83b3, 0x088b34b3, 0x01ffef0e, 0x7b9a197f, 0xd8ffff15, 0x738266e6, 0x05060023, 0x2c5186ff, 0xff9a9914, 0xf2d20200, 0x611300ff, 0x31938248, + 0x00fff893, 0xffc2b511, 0x68510900, 0xd4ffff08, 0x298270bd, 0x05f6e822, 0x57249482, 0xfbffff0a, 0x2982f184, 0x78fdff26, 0xefffff94, 0x01223d83, + 0x2982f408, 0x33f3bd31, 0x240400ff, 0xc9ffffd8, 0x00ff6766, 0x8200803e, 0x33422f9a, 0x00ff0834, 0x0733b303, 0x2500ff5b, 0x768233b3, 0x0700002e, + 0x63d9ffff, 0xff8b05d7, 0x9959a6ff, 0x20076741, 0x26ce820c, 0xff492157, 0x83e6f3ff, 0xd9dd2577, 0xff63079a, 0xfa200082, 0x1908144c, 0x220a3e1b, + 0x82e03aef, 0xffff2c71, 0xf6fffff8, 0x00ff9642, 0x82991908, 0x82cc200c, 0xe6072342, 0x71828b67, 0x9a199f23, 0x21168206, 0x838288d6, 0x12430627, + 0x290700ff, 0x220a82fc, 0x829eef07, 0x8301201c, 0x82122028, 0xf2ff21b9, 0x2208b069, 0x836666ed, 0xb3f73237, 0xfaffff32, 0xff1566e6, 0x34b360ff, + 0xe67c00ff, 0x31b28266, 0xffb85e0f, 0xa4f01900, 0x280900ff, 0x1d00fff6, 0x4b8252f8, 0xcc4c2022, 0x27234b82, 0x820772fd, 0x0e1e510c, 0x83a6f321, + 0x7fff204d, 0x1e5109ed, 0x22d4840a, 0x82d8ffff, 0xff8b2559, 0x48e1eaff, 0x70267082, 0xecffffe6, 0xcd829a59, 0xfffcc926, 0xae87eeff, 0xe627dd82, + 0x00ffae47, 0x82f62814, 0x3b05317f, 0x0b00ffe8, 0x00ff14ae, 0xff4e4203, 0x72bd0c00, 0xa8217283, 0x282582f5, 0xffbeffff, 0x99199b00, 0x36118205, + 0xffec9134, 0xe27ad7ff, 0xd72d00ff, 0xcbffff0c, 0x00ff3273, 0x825c8f01, 0xa1c92225, 0x2e0a8248, 0xfffff29d, 0xffa470d3, 0xda6ed4ff, 0x8208558b, + 0xc0c92d7d, 0xffff0500, 0xffcae045, 0x761e9100, 0xfb220a82, 0x64829999, 0x82207021, 0x82c72093, 0xac01227e, 0x2209824a, 0x828b0ad7, 0xe1f82243, + 0x31318248, 0xffd3edf8, 0x8ed7fcff, 0x47fbffff, 0xf9fffff0, 0x1a8210f8, 0x21d0f727, 0x8ff5ffff, 0x2a63825c, 0xffff27d1, 0xfff6e8f0, 0x82700a00, + 0xd4f72b13, 0x02ff087a, 0xff98194f, 0xef8230fe, 0x802b1582, 0xf7ffff00, 0x00ff08cc, 0x82ec110f, 0x00e0262e, 0x1e0800ff, 0x211882b8, 0x1482f067, + 0x3c1f092c, 0x820900ff, 0xfeffffd2, 0x23829c19, 0x829a1921, 0x98992157, 0x33352382, 0xf70e0832, 0xc001ff94, 0xff150002, 0x34b30400, 0x000000ff, + 0x83098212, 0xfbfe2150, 0x0422f382, 0x36823233, 0x82521821, 0x4cbc3146, 0xb0ffffce, 0xa1057c1f, 0xabf6ffff, 0x1000ff86, 0xea2c2583, 0xffffec51, + 0xffccccff, 0x32b3e6ff, 0xff20b582, 0x9b2b1483, 0xffff67e6, 0xff3433d7, 0x827f4aff, 0xb353271d, 0xadffff32, 0x1e820080, 0x4483ef20, 0x8183f820, + 0x9999ec22, 0xef27f982, 0x00ffcd4c, 0x8266e607, 0xa653251a, 0x5200ff66, 0xd7273e83, 0x00ff703d, 0x820180b5, 0x299c2679, 0x196400ff, 0x257e8299, + 0xff1fc500, 0x3e821900, 0x73100028, 0x1500ff33, 0x048214ae, 0x82e1fa21, 0x7a5421d9, 0xbc211e82, 0x233d8266, 0x0584e04f, 0x5e82bd82, 0xe7010023, + 0x260982ae, 0x00ff9999, 0x831e0401, 0x2ef48209, 0x08eeffff, 0x2f0e078b, 0x1534f8eb, 0x1800ff8b, 0x232acb4f, 0x14f7076b, 0x210b2256, 0x5018cc4c, + 0x55180800, 0xb07210f5, 0x17f01808, 0xf4f7233c, 0xc47044fc, 0xf4fb2117, 0x710cd775, 0xf72b0a88, 0x54f807a4, 0x07a4fb06, 0x836bcb0e, 0x0e30733d, + 0x1fc51028, 0x00ff088b, 0xb218e6a0, 0x0d210915, 0x2718196e, 0xffff390d, 0x05abfaff, 0xe620ffff, 0x6b8b066c, 0xb701ff05, 0x01ff6666, 0x15a470da, + 0x8c201882, 0x04273c82, 0xfffff087, 0x42d0d7f8, 0xff2e0567, 0xffa2f0f8, 0x30c8feff, 0x50ffff08, 0x308266e6, 0x97f4ff27, 0xfdffff0a, 0x2d2582e7, + 0xffc2b5f7, 0x6210f6ff, 0xf4ffff8b, 0x21826666, 0xee11bf2b, 0x000000ff, 0xa38b0584, 0x06804105, 0xaf50ff20, 0x7a542105, 0x08670719, 0x9a19df23, + 0x0d3f6c06, 0x83085141, 0xff0d253c, 0xa430e5ff, 0x2408a182, 0xfffd96c5, 0x707df5ff, 0xe8ceffff, 0xd6fffff6, 0xffff52b8, 0xff29bcec, 0x3433c6ff, + 0xfbffff08, 0xffff21d0, 0x22bc82f3, 0x82cc0600, 0x83f2200e, 0x900c2209, 0x211882a4, 0xc682cdcc, 0xae870222, 0x3326ea82, 0x0200ff33, 0x09823d8a, + 0x829a9921, 0x1f852209, 0x221a828b, 0x82cd0c0a, 0x5e092b9c, 0x0600ffb8, 0x00ff1058, 0x1b825903, 0xe6100a22, 0x0c341a82, 0x00ff15ae, 0xff0a1726, + 0x1f051f00, 0xb31b00ff, 0x2500ff34, 0x00244982, 0x08cccc09, 0xe022e682, 0x9982cccc, 0x1e45da23, 0x26a58279, 0xffffe1ba, 0x82ceccd9, 0x82d32016, + 0xfb8b25fd, 0x00ff0544, 0x0026dc84, 0xf7060000, 0x64820544, 0x76822c20, 0xbae5ff23, 0x205482e2, 0x279a8230, 0xff842bdb, 0x8e021200, 0xff27af82, + 0x00fffaff, 0x82343323, 0x193f2133, 0x00227f82, 0x30828400, 0x68f4ff27, 0x0800fff4, 0x3020824c, 0xff5c0ff6, 0x2c670b00, 0xe8fdffff, 0x00ff08f6, + 0x232582af, 0x66e6e0ff, 0x01223082, 0xd1822070, 0xff00c026, 0xe06f0100, 0xe0200982, 0x6c210983, 0x22db8308, 0x82f89305, 0x73052276, 0x261b82b6, + 0x00ff22f0, 0x820a5704, 0xbe9f26e0, 0x0500ff08, 0x22eb8278, 0x82e08f04, 0xf027210f, 0xbf21fa82, 0x2229827c, 0x82482107, 0xfd6f281a, 0x00ff07b2, + 0x8272e800, 0xe23a2116, 0xb3217182, 0x82098232, 0xfaff2160, 0x0027c082, 0x085c8f04, 0x82b8feff, 0xa5ff230a, 0x146c5c8f, 0x0700230c, 0x4682f628, + 0x0ad70823, 0x1ae01808, 0x33332208, 0x821683ff, 0xcdcc21c7, 0x08209383, 0x4e820682, 0xffcd4c2c, 0x04d6f8ff, 0xf7ffff8b, 0x2d82fc29, 0xff240683, + 0x33b3f9ff, 0x15821684, 0x8b333327, 0x00ff0e08, 0x2367829c, 0x9a193f00, 0xe1286782, 0x00ff9919, 0x05cccc1f, 0x80201d82, 0x0734e482, 0xff889a99, + 0x66660c00, 0xe60200ff, 0x0b00ff67, 0x8e08ce4c, 0xe6226782, 0x0c828f66, 0x052e3783, 0x00ff34b3, 0x08cc4c0d, 0x3396ffff, 0x37820633, 0x82486121, + 0x08f82271, 0x062344b4, 0x64bbfb22, 0x80279d82, 0xffff0800, 0x8423bbfb, 0x25f9820a, 0x00ffbc14, 0xf4823309, 0x25660422, 0x662d1382, 0x00ff0867, + 0xff177934, 0x01805800, 0x22718205, 0x59ffc3f5, 0x172c056c, 0x00ff3e8a, 0xffcc4c0e, 0x52781900, 0x5220dc83, 0x00216583, 0x22928302, 0x829a1903, + 0x82662097, 0xb3032197, 0x13858582, 0x82989921, 0x8351204a, 0xc57823ac, 0xde82f720, 0x6e12042c, 0xcc4800ff, 0xf2ffffcc, 0x1b824095, 0x2b820b20, + 0xdcfdff29, 0xffff946a, 0x82e8fbf6, 0x23458240, 0xb85ef4ff, 0x0d341a82, 0xffff6466, 0x87f628b7, 0xffff0efb, 0xff343387, 0x9a19aeff, 0xfc27b882, + 0xffff0080, 0x829899fd, 0xce4c21c2, 0x9a280983, 0xe6fcffff, 0xfeffff66, 0xac23d784, 0x820766e6, 0x83e620f3, 0x99f22125, 0xe8201b82, 0xea230983, + 0x827e9a19, 0x83a7203b, 0x99cb280b, 0xffff059a, 0x829999f8, 0x27208341, 0xffcdccf6, 0x68e6ffff, 0x1e821382, 0x33040023, 0x20298232, 0x200a84f8, + 0x28a8824c, 0x936666fb, 0x0800ff8b, 0x277c8299, 0x34336b00, 0xf1ffff07, 0xfb256e83, 0xffff3233, 0x20bf83f3, 0x230e83fb, 0x8833b3f6, 0xf4203782, + 0xfc214c83, 0x264c8266, 0xffccccf3, 0x82190300, 0x82f720a7, 0x08003624, 0x8b08ce4c, 0xe300ff07, 0x00ff6666, 0x15ccccd9, 0x191600ff, 0x2658829a, + 0x9c66e611, 0x8208a28b, 0x83152009, 0x19ee25e4, 0x1200ff9a, 0xff213b82, 0x059264e9, 0xff210683, 0x751683ff, 0xea270655, 0x8b08cccc, 0x8200ff74, + 0x857a2038, 0xccab1844, 0x00ff2962, 0xff9a9936, 0x9a99a6fe, 0x08e8c918, 0x7d008021, 0xea5f1044, 0x83c0200c, 0x076e601f, 0x07f96218, 0x00c0f927, + 0x400600ff, 0x05b34100, 0x33080023, 0x22f88232, 0x83343308, 0x230682ff, 0x200300ff, 0x08222082, 0x2585142e, 0x3d060024, 0x63180870, 0xd57d0e54, + 0xffff242b, 0x82cdaca6, 0x48a12604, 0x5900ff05, 0x220a834c, 0x18059a99, 0x20631faa, 0x90ab1866, 0x08c36107, 0xf321f382, 0x18048280, 0x2309a042, + 0x00800c00, 0x1dae7719, 0x32735922, 0x5922b782, 0xc382059a, 0xce615082, 0x0bc36106, 0xb3614020, 0x834b8407, 0x85ff2051, 0x0efa7e04, 0x20066a62, + 0x222f8206, 0x82c0f9ff, 0x19032234, 0x6a6f189a, 0xcdcc2308, 0x0c838b08, 0x09fd1b19, 0xffffce25, 0x8234b3f9, 0xcccc2104, 0x20645d42, 0x24dd8286, + 0x6666c9fe, 0x1a424215, 0xa6ffff29, 0x00ff66a6, 0x41cd4c59, 0xff23060e, 0x6433b3a6, 0x73420d91, 0x654b850d, 0x29410710, 0x0653420c, 0x14830620, + 0x7a180484, 0x4618129f, 0xff2e0797, 0xff00e0fc, 0x703d0600, 0xc0f9ffff, 0x49410800, 0x7a0c2206, 0x215f82e2, 0x2a659a79, 0x635d4210, 0x9a998628, + 0x6609ffff, 0x5d421566, 0xccf92106, 0x31211119, 0x0e8b6618, 0x00ff8b23, 0x0c224114, 0x1c784118, 0xb85e592d, 0x93a6ffff, 0x00ff0534, 0x84486159, + 0xcaaa1804, 0xf7af243b, 0x53a4f7f4, 0xe8181cb0, 0x6b3b112e, 0x0764fb06, 0x8bc006bb, 0xc08bb6b6, 0x0600ff08, 0xff079a19, 0x9a19f8ff, 0x47f9ffff, + 0xff320835, 0xffceccf5, 0xccccf0ff, 0xf6ffff8b, 0x00ff9a99, 0xbe18330a, 0x002307b5, 0x82008008, 0x670f20f4, 0x00260775, 0x08666609, 0xc682c3c3, + 0xff260882, 0xcd4c0900, 0x1c8200ff, 0x08222282, 0x3d82fe7f, 0x0833b324, 0x1d8253c3, 0x30820a20, 0x51824b83, 0xff205782, 0x24c3b919, 0x9e828420, + 0x05343322, 0x9e469982, 0x82a72005, 0xb8ff248a, 0x85ff6666, 0x290e8204, 0x34fb088b, 0xa7ffff06, 0x57829999, 0x00211983, 0x05a94f47, 0xdb889482, + 0x8752f821, 0xa1f622db, 0x84798348, 0x82cd20db, 0xa1f62231, 0x18db8806, 0x841496a5, 0x00382246, 0x21df8442, 0xdf88b95e, 0xdf823320, 0x0f820920, + 0x82f6ff21, 0x00ff24df, 0x85482137, 0x6c6518e3, 0x26e3820c, 0xf7ffffcd, 0x84080080, 0x41798805, 0xe38d0c55, 0x230db351, 0x64f706bb, 0x2005775b, + 0x24ad834c, 0xff33b3f1, 0x100c7900, 0x5f481183, 0xb3112406, 0x82088b33, 0x66e632d0, 0xe6ffff06, 0x00ff9a19, 0x7a343311, 0x661d00ff, 0x20af8266, + 0x82cc8221, 0x05352506, 0x2a00ff1e, 0x2a381c83, 0x00ffe2fa, 0x8b66e635, 0xb68bc008, 0x05d5ffff, 0xffff8b1e, 0x08e2faca, 0xde220682, 0x3e479a99, + 0x99e22306, 0x0a82729a, 0x86cccc21, 0xbb4b2159, 0x820c7142, 0x20cf827e, 0x84531900, 0x19ab2007, 0x6311b6b4, 0xff210bc5, 0x225218f1, 0x22648208, + 0x19cc4cee, 0x2a103e0d, 0x74f72f0e, 0xff1514f8, 0x83ccd3ff, 0x05bd61f3, 0x82142e21, 0xd1d3262d, 0x075b08ec, 0x7eca18f7, 0x068b24ed, 0x41d4fbab, + 0xb3211b70, 0x05516534, 0x4c0e0023, 0x056941cc, 0x4d4b0821, 0x186a0e2b, 0x442a820f, 0x002d0617, 0x8b33b311, 0x0e06cb08, 0x54f7b4f7, 0x16a06515, + 0x410b784d, 0x8a180eed, 0xfc6512e2, 0x8433200e, 0x08cd2454, 0x828b44fb, 0x4f00265f, 0x00ff0080, 0x82048840, 0x088b220e, 0x201583ff, 0x2316858b, + 0x0080bfff, 0xb0233182, 0x85080080, 0x61ff2006, 0x168205d8, 0x82ffff21, 0x842d8215, 0x18168506, 0x230a899a, 0x153b24f7, 0x64058164, 0xcc210791, + 0x205382cc, 0x0523492c, 0x03642c20, 0x23002207, 0x20fa82cc, 0x201b82d3, 0x0d614208, 0xa8833320, 0xd147d320, 0x831e8205, 0xc8731944, 0x94f7220c, + 0x28bf82db, 0x9a9972ff, 0x668dffff, 0x82048666, 0xfa35190e, 0xffff244b, 0x829a1995, 0xe6aa21f7, 0x04826082, 0x10820a82, 0x19190820, 0xf5240e74, + 0x8be1e18b, 0x111d3619, 0x0cf72f22, 0x2105c341, 0xa38219e1, 0x14eee625, 0x83e6ffff, 0x11e12247, 0x83a383eb, 0x82118206, 0x77671816, 0x181e200d, + 0x23124074, 0xee1e00ff, 0x0023ed82, 0x84ec1119, 0x82878244, 0xf7082354, 0x15828b34, 0x5f85ff20, 0x5f863682, 0x0821b282, 0x821583ff, 0x07ce6126, + 0x42828b20, 0x0866e622, 0x63180685, 0x9782071b, 0x6e820020, 0x06848d82, 0x10407618, 0x5e83bb20, 0x30a71a83, 0xa2849785, 0x9b820486, 0x9382ec84, + 0x85095b62, 0x0e082685, 0xe3cb30fc, 0x88db9615, 0x3b37414a, 0x34f78b22, 0xbb235fdd, 0x41ffff15, 0xb98218c8, 0x11190024, 0x0485ffec, 0x15ee1e24, + 0xec8d088b, 0x08816418, 0x5518ec96, 0x572117bf, 0x2630820a, 0x08f6a8dc, 0x8507d4fb, 0x06505909, 0x0a57e322, 0x18066759, 0x221080d1, 0x828bf6a8, + 0x0a57231a, 0x3383f708, 0x82230021, 0xe3ff2329, 0x3882cc4c, 0xfff6a824, 0xa772dcff, 0x99162605, 0xa9feff9a, 0xa7191966, 0x4ccd200f, 0xff2305e6, + 0x82cdccf7, 0x2a0684c2, 0xd1f7ffff, 0x0300ffeb, 0x4bfffa1e, 0x06210587, 0x0f034c40, 0x18904221, 0x290c1150, 0xffe13a06, 0xdc440600, 0x204d00ff, + 0x18192005, 0x21154385, 0x324d06e1, 0x20558305, 0x26408208, 0xffff5278, 0x4a9478f3, 0xee30109e, 0xb3f6ffff, 0xffff1534, 0xff6666ff, 0xcccc0000, + 0x80210982, 0x82048200, 0xfeff2357, 0xa8839a99, 0x5278f322, 0xf5263782, 0x00ffa470, 0x1b83c009, 0x82852b21, 0xa4b02651, 0xfdffff08, 0x20bd8251, + 0x20fa8336, 0x21f382d0, 0x44822f00, 0x4cc9ff23, 0x21d182cc, 0x1e829a99, 0xaec7f222, 0xd82b5482, 0xf5ffff03, 0x00ff52f8, 0x82ab6f0b, 0x29dc260e, + 0x380d00ff, 0x22958252, 0x8202dc00, 0x0040210a, 0x8c211982, 0x215c82f4, 0x0e825c8f, 0x82291c21, 0xec91217d, 0x4d201e82, 0xff362982, 0xff21f0fa, + 0xa5704300, 0x8fbcffff, 0x0500ffdf, 0xffff9819, 0x5c8219b2, 0xde00002c, 0xf2ffffb8, 0xff8150b8, 0x7c82f4ff, 0xccf2ff23, 0x213982ce, 0x39823433, + 0xcc865f20, 0xb321d783, 0x22cd8634, 0x829899ff, 0xccfe22c6, 0x21d384ce, 0x0c823433, 0x4661f527, 0x170a00ff, 0x2121820a, 0xd3823473, 0x82f6e821, + 0x78fc21b4, 0x6a20aa82, 0xff224182, 0xc982cca5, 0x82335a21, 0x82952040, 0x05002360, 0x1e82cc4c, 0xcdccf222, 0x55832e82, 0x85abf522, 0x1921b982, + 0x21d3829a, 0xb982cd8c, 0x00231e83, 0x825d8f00, 0x2333820a, 0xec510b00, 0x99215c82, 0x820e8298, 0xffff2123, 0x822a9984, 0xffff33b3, 0xfff087fa, + 0x47836e00, 0x432b9122, 0x22068c51, 0x8233337e, 0x830120b8, 0x83f12076, 0x82f520c8, 0x05d76d7b, 0x6b82f220, 0x4c000023, 0x2c1f19cc, 0xe4fb2b62, + 0x44fb15e3, 0xffff8b07, 0xfa824cf7, 0x33b30426, 0x0700ff83, 0xff23fb82, 0x82ceccfb, 0x8007289e, 0xfbffff00, 0x4bff32b3, 0x0020050f, 0x0720e683, + 0x0028b282, 0x08008004, 0x05e324f7, 0xeb822d82, 0x84040021, 0x26048313, 0x8b34b307, 0x490800ff, 0x068205a2, 0x20056551, 0x24168200, 0xe6f8ffff, + 0x82fc8266, 0x83fb201a, 0xf8ff2139, 0x00216782, 0x28348205, 0x33b3f6ff, 0x4cffffff, 0x058351ce, 0x08207083, 0x19830a82, 0x41828682, 0x83cd4c22, + 0x0838a285, 0xaf0e078b, 0xb4f714f7, 0x06d4f715, 0xfb0754fb, 0x54f706d4, 0xeb14f807, 0x17778a18, 0xff073b23, 0x0b5b65ff, 0xfa188020, 0xbe5c0eaf, + 0x82ea2005, 0x1a0021e6, 0x08221b82, 0xd218073b, 0xdb2630ca, 0x1a00ff07, 0xf5828f82, 0x717d1522, 0x12bb9e19, 0x82eaff23, 0x8216848f, 0x717d2489, + 0x18db088b, 0x2617cb58, 0xfc0654f8, 0x48b4fb34, 0xdd4807be, 0xd4f7210f, 0x480c906e, 0xf7210ac1, 0x19528354, 0x82148f97, 0xae421833, 0x54fb2115, + 0x70a75918, 0x5cfb8c26, 0xf2ffff15, 0x089b5a18, 0x4cf5ff24, 0x10848bcd, 0x70180820, 0x6e19097b, 0x44200dd2, 0x0c555f18, 0x0ad85918, 0x16032c19, + 0x0644fb2d, 0xff30fb0e, 0x9a995601, 0x450901ff, 0xce211090, 0x052b54ff, 0x5b53f620, 0x24068305, 0xb8f8ffff, 0x05775252, 0xc2f9ff25, 0x4500ff90, + 0xb72b0590, 0x00ff1e85, 0x05345349, 0x6dbdfeff, 0xd32705d4, 0xffffb8de, 0x82291cdc, 0x48212a04, 0xe3d3ffff, 0xfb088bd7, 0x0e976004, 0x0f857418, + 0x540e0023, 0x05b1687b, 0xab110026, 0xf7088b85, 0x00203082, 0x23051356, 0xff333307, 0x290a7479, 0xb34201ff, 0xffff0734, 0x66829eb6, 0x32b3b622, + 0x2036d850, 0x7b8b18ff, 0x0ace7308, 0x08035618, 0x80f3ff2d, 0x14f70800, 0xff0514fb, 0x82610d00, 0x73f321c5, 0x16792019, 0x9a995622, 0x6623ff82, + 0x84fb1566, 0x50ff202d, 0xd6460b61, 0xe6f62607, 0xff088b67, 0x240683ff, 0xb8f8ffff, 0x07454151, 0x11978c18, 0x8233b152, 0x2fa1837e, 0x053493b6, + 0xcc4201ff, 0xff8b07cc, 0x5ccf0800, 0xcc2b6982, 0x0700ffcd, 0xffffa430, 0x413333f7, 0x2c223783, 0x4f829a19, 0x66e62334, 0x1edcffff, 0xffff8bb8, + 0x0848e1d3, 0x33bdfeff, 0x78820734, 0x84b85e21, 0x28d2507d, 0xffe2fa26, 0xead1ebff, 0x2009bc52, 0x06824808, 0x67035d18, 0xcc2cbf82, 0x4cffffcc, + 0xff153333, 0x68e60a00, 0x67200483, 0x1120e082, 0xf5221583, 0x0f839819, 0x19086621, 0x213ec92b, 0x40838b33, 0x45849920, 0x11214b83, 0x820f84eb, + 0x33ee2215, 0x21618234, 0x1a8515ee, 0x054bcb22, 0x0d837f84, 0x83827982, 0x0a228982, 0x998467e6, 0x00ff0825, 0x84ffff7f, 0x41052004, 0xc5277024, + 0xffffcccc, 0x82cc4c94, 0x4cf02ca8, 0x0f00ffce, 0xffff9a99, 0x8232b3e6, 0x66f027c2, 0xf0ffff68, 0xd8826666, 0x8299ea21, 0x99ea22e3, 0x23c5829a, + 0x4467e646, 0x15270682, 0x00ff6666, 0x82676615, 0xb30f220a, 0x26378232, 0xff8b33b3, 0x824c1900, 0x8247874d, 0x83f12037, 0x660e2d1a, 0xffff0566, + 0xff34b329, 0x68e65bff, 0xfa266883, 0xc4ffffe1, 0x158232b3, 0x47a1fe25, 0x82f9ffff, 0x0100211a, 0xfa217883, 0x2d4a8233, 0x8771fd03, 0xffff8f08, + 0xff9a19fc, 0x1b820500, 0x83feff21, 0x80052b6c, 0x0100ff00, 0xff08ce4c, 0x19833c00, 0x83190f21, 0x8205208e, 0x01002136, 0x33251f84, 0x0200ff33, + 0x279682e6, 0xff991904, 0x9a190400, 0x692b2982, 0x00ff3433, 0x05333369, 0x8200ff44, 0x207182b9, 0x20f08396, 0x267c8497, 0x8666e6fb, 0x82fdffff, + 0xfaff212d, 0xff213782, 0x22e583fe, 0x426866fa, 0xfb2007aa, 0x0d7d5f18, 0x4be3ff21, 0x632e562d, 0x8b15acfb, 0x4feeffff, 0xf1ffff5c, 0x5a19a4b0, + 0x15820dee, 0x16831b82, 0x280a9669, 0xb34200ff, 0xffff0733, 0x82fd8286, 0x82992004, 0x058e44d7, 0x18cecc21, 0x56100158, 0xd12008d3, 0x09dd2619, + 0x23fb5718, 0x866b7927, 0x607900ff, 0x215b8200, 0xe61833bd, 0x206a0d55, 0x45118311, 0xb02807d5, 0xf7088ba4, 0x00ff0624, 0x0b12c418, 0xe1841482, + 0x24fb083a, 0xffaf0e07, 0x68e63802, 0x803001ff, 0xffff1500, 0xff9a1969, 0x34338a00, 0xf2316882, 0x00ffcacc, 0xffb0120c, 0x3433ebff, 0x30f6ffff, + 0x28fb8220, 0x08f232ed, 0xd7b5ffff, 0x31f0820a, 0xff333371, 0xb85efeff, 0xcc8effff, 0xe3ffffcd, 0x2082ae87, 0x00807923, 0x25068208, 0xff34b3c9, + 0x20832300, 0x3233ca27, 0xe12600ff, 0x22208248, 0x820868e6, 0xd7232651, 0x38f7ffff, 0x2b928210, 0x00ffae47, 0xffde040b, 0x1f85fbff, 0x3821b082, + 0x255a82d4, 0xff14aed7, 0x23828000, 0x4c450029, 0x1c00ffcd, 0x82f73333, 0xe6002210, 0x231b8266, 0x07ceccb5, 0xed215b82, 0x2211822e, 0x820ad714, + 0xe23a2493, 0x830d00ff, 0x140c220e, 0x225b827a, 0x8666e696, 0x09002ebd, 0x00ffe47a, 0x8b5ccf07, 0x990f00ff, 0x262a8298, 0x00ff0080, 0x8234b308, + 0x19672146, 0x0f200f82, 0xee20ee84, 0x5e0a276e, 0xff3309ea, 0x0766e6e0, 0x00ffd4fb, 0x05560000, 0x193f01ff, 0x6fab0744, 0x51210e64, 0x225882ec, + 0x8214ae11, 0x820020eb, 0xffff2106, 0x6e053454, 0xcd220524, 0x7218088b, 0xff230d2f, 0x699a59e3, 0x0823050d, 0x82c0feff, 0x18de4d5c, 0x4e677386, + 0x1800200a, 0x22096da4, 0x821f00ff, 0x06457c8a, 0x34207182, 0x2406d553, 0x8bcc4cee, 0x625b5208, 0x188bb421, 0x345db24f, 0x9a194501, 0x4ccdffff, + 0x00ff15cc, 0xff008037, 0xce4c9000, 0x06075e05, 0xcc4c142c, 0xe6ecffff, 0x1200ff66, 0x09823433, 0x29829920, 0x0080f82d, 0x6fffff08, 0xffff33b3, + 0x5e0080c8, 0xff220689, 0x2982ccfc, 0xcd4cf924, 0x0484ffff, 0x0e83fc20, 0x82051c56, 0x822e8424, 0x853a8229, 0x834e8644, 0x21628358, 0x53830700, + 0x82847883, 0x08207d82, 0x03208883, 0x00247382, 0xff32b306, 0x0e840485, 0x08211882, 0x07a54a8b, 0x41109e44, 0xcc4f08f0, 0x1859203a, 0x2211c058, + 0x83d9ffff, 0xb33729f9, 0xff231533, 0x010090ff, 0xfb27cb82, 0xffff6666, 0x829819fb, 0x33b324f0, 0x82fdffff, 0x21fa83ab, 0x1082088b, 0x8bcd4c22, + 0xab260582, 0x0200ff85, 0x2582f0c7, 0xffa4702a, 0x00e00400, 0x04f72308, 0xf92c3982, 0xff920080, 0xef47feff, 0x300a00ff, 0x032c1982, 0x00ffe0cf, + 0x0800c008, 0xcc0300ff, 0x08220482, 0x0f8239b4, 0x00215482, 0x2d048305, 0x8b008009, 0x0664f708, 0x870900ff, 0x19828bf0, 0xffb4a826, 0x1058faff, + 0xe8265c82, 0xf7fffff6, 0x3382fa3e, 0x32b30422, 0x35210a82, 0x255782c3, 0xffffce4c, 0x9c82e6f5, 0x84206782, 0x4118c845, 0xdd2b5829, 0xfeff9a19, + 0x156666ee, 0x82fdffff, 0xf7ff210a, 0xf7228f83, 0xb382cc4c, 0xf6200483, 0xfb20cd83, 0xff24cd82, 0x8b1078f6, 0x572bb382, 0x0500ff4b, 0xfffff0a7, + 0x82a430fc, 0x06c122dc, 0x310a8708, 0x00ff3eca, 0xff52b801, 0x98190a00, 0x7d0600ff, 0xe8829271, 0x0000682a, 0xff0504f7, 0x00200900, 0x24058850, + 0x5cef1000, 0x290a828b, 0xffff4821, 0x080040f6, 0x1e83fbf3, 0x90820623, 0x263d8284, 0xffff32b3, 0x6068e6f5, 0xf7220617, 0x0f413233, 0x83b82071, + 0x660e27f5, 0x04fb1566, 0x88820523, 0x82018021, 0xcecc2b04, 0x19faffff, 0xfdffff99, 0x0983cccc, 0x838b9a21, 0x00c022f5, 0x20fb828b, 0x22d882c0, + 0x82fca700, 0xf0e72109, 0x5821c282, 0x251a8204, 0xff434bf7, 0x2b840300, 0xffcd4c26, 0x34b30800, 0x8025f283, 0x64f70800, 0x20098307, 0x21298287, + 0x0482a705, 0xb4a80822, 0xc1211e82, 0x222d8206, 0x82085ccf, 0x204d830a, 0x2f048303, 0xffa4300a, 0xe04ffeff, 0xf9ffff92, 0xf7083088, 0x00238d83, + 0x829ad904, 0x564e2467, 0x830200ff, 0xccf8225c, 0x238182cd, 0x08cd4cf9, 0x9a820684, 0x2105d642, 0xea4234b3, 0x66fb2906, 0xfb0e0866, 0x64f7cb30, + 0x0cf0df18, 0x1813b759, 0x220f196c, 0x823e4a1c, 0x9c1d3995, 0x5300ff29, 0x00ffd8e3, 0xff34334f, 0x281c3c00, 0xe65e00ff, 0xa3088b66, 0x590cc74e, + 0x54210e49, 0x0506587c, 0x06581683, 0x06732606, 0x19c6ffff, 0x26a7829a, 0xff33b3cd, 0x8299dfff, 0x4ce625c8, 0xd0ffffcd, 0xff24a282, 0x66e67d00, + 0x2758508e, 0x113a5c0d, 0x70ffff24, 0x54823333, 0x67e6ff2b, 0x66fdffff, 0xffffff66, 0x220482e6, 0x82cd4cfd, 0x22058263, 0x84077b08, 0xffcc2408, + 0x82190000, 0x4cfd226c, 0x200983ce, 0x252c8499, 0x8f00ff08, 0x719ccdcc, 0x1b7ecc20, 0xffff2410, 0x829a1982, 0x83192033, 0x22b682c0, 0x833200ff, + 0x21ca83c0, 0x13413900, 0x91c28d13, 0x82732050, 0x19a122be, 0x22a6829a, 0x4accccb0, 0xff2e0523, 0xffd763e2, 0x66e65300, 0xe3ffff08, 0x994ec2b5, + 0xe86d180e, 0x7434200d, 0x002205be, 0x3c824c0e, 0x85ab1123, 0x22d5828b, 0x82672610, 0xe6ff2c33, 0x0200ff66, 0xffff34b3, 0x8233f3ff, 0x98992209, + 0x220f848b, 0x84079b08, 0x22138208, 0x82cd0c00, 0x9a992112, 0x82051d41, 0x0833352c, 0xd9efffff, 0xfb0e0699, 0xff04f770, 0x66e6e000, 0x0604f715, + 0x220c5c7e, 0x82cdccf0, 0x33ef23ab, 0x06820833, 0x6666ed22, 0x2105cf47, 0x4582f2ff, 0x4ceeff23, 0x06c64dcd, 0x9a99d22d, 0xff6e8b07, 0x9919f8ff, + 0x84e4ffff, 0x22098325, 0x823433e6, 0x51ff2d61, 0xfeffffeb, 0xff0566e6, 0xe27ac700, 0x252e8041, 0xff0694fb, 0xd754f4ff, 0x2f5d2505, 0x330600ff, + 0xfa29e182, 0x0895ec51, 0x51faffff, 0x067844aa, 0xf027003c, 0x4c0c00ff, 0x0500ffce, 0x00ff56ee, 0x0866e609, 0xc21d00ff, 0x3100ff8f, 0x77829a99, + 0x82f30821, 0xe60e27fe, 0x0400ff66, 0xdf82e1ba, 0x8b9a1922, 0x66200582, 0x2c242583, 0x7b070080, 0x831c7341, 0x0529433a, 0x1b70cd20, 0x829b2006, + 0x703f20c4, 0x462705be, 0x00ff14ee, 0x82008039, 0x52782704, 0xe64600ff, 0x7a828b66, 0xcdcc0d22, 0x0d276082, 0xffff33b3, 0x82aec7fd, 0x29b5839a, + 0x0848a1fb, 0xe4ffffdd, 0x918232f3, 0xcccc1022, 0x6827c082, 0xffff94f6, 0x8248e1ed, 0x2442820a, 0x0040efff, 0x240a8208, 0xffff6666, 0x05126eef, + 0x8282ce21, 0xcc4c210a, 0x8020d782, 0xae211a83, 0x218282cc, 0xd282191b, 0x82f9ff21, 0x02002d30, 0xffff142e, 0xff9a19f9, 0xb81e0100, 0x99200983, + 0xff287d82, 0x8b6766dc, 0x33e3ffff, 0xe3227d82, 0x0a823433, 0xe983dc20, 0x4cc1ff2d, 0x2f0e07cc, 0x000000ff, 0x6a14f814, 0x8425056b, 0x540e00ff, + 0x74401867, 0x82db200b, 0x804f22da, 0x080d5b00, 0x82ae8721, 0x78b0233f, 0x06820852, 0x5183c520, 0x8282dc20, 0x80cdff24, 0x0482ff01, 0xffff0025, + 0x829899e9, 0x833320ef, 0x997f21b2, 0x00239782, 0x829a9906, 0x9a9922b2, 0x84d88283, 0x999921c8, 0x80849882, 0x1a83ef20, 0x6866f922, 0x93201984, + 0x7a821583, 0x1a821020, 0x00ff532f, 0x0566e68b, 0xb3d5ffff, 0x14fb0633, 0x08075c07, 0x4385ab21, 0xee220691, 0xd9837b54, 0x5309337a, 0xd1860a45, + 0x00ff0529, 0xfbecff3f, 0x82bb1554, 0x09f87ec2, 0xcc230023, 0x82cd82cd, 0x26c28210, 0x34332c00, 0x82dcffff, 0x201682c7, 0x05805bcc, 0x065b0829, + 0xff0734fb, 0x82cc0001, 0xcce52310, 0x4f8215cc, 0xd9828020, 0x68e6fe22, 0x04820982, 0x82feff21, 0x057c450e, 0x32b3fd22, 0x0720ed82, 0xfa254483, + 0x00ffce4c, 0x0866550b, 0x32331322, 0x4c21d082, 0x201e82ce, 0x23198201, 0x0080ffff, 0x10259082, 0xffff9819, 0x211a82fb, 0xfb831600, 0x3882f720, + 0x82100021, 0xf1ff2304, 0x29820080, 0x66660a2a, 0xe6f7ffff, 0x0800ff66, 0xf5200983, 0x00284d82, 0xff9a1905, 0xcc4cf2ff, 0x0a861e82, 0xff8cce24, + 0x4382f1ff, 0x7d82ff20, 0xf0ffff22, 0xff213983, 0x209783fb, 0x210483e3, 0x7882b3ef, 0x0483eb20, 0x34b3e825, 0x84f3ffff, 0x82e9201e, 0x05935653, + 0x324ee520, 0x729a2405, 0x840400ff, 0xccff211a, 0x0026b782, 0xff059a19, 0x3582f6ff, 0x83010021, 0xccf42335, 0x4a568fce, 0x33032106, 0xff21e282, + 0x213682f9, 0xc8830200, 0x20056742, 0x20c78299, 0x283983fa, 0x089a1902, 0x80fdffff, 0x20948200, 0x202483fd, 0x27158200, 0xcc4cfeff, 0xb30000ff, + 0xef253983, 0x00ff0080, 0x23d88506, 0x1200ff67, 0x09820e85, 0xf2841020, 0x00201983, 0x19860a82, 0xed820820, 0xff220e84, 0x588299f9, 0x99020025, + 0x82ff8a9a, 0x83982005, 0x23998305, 0x0866e6fe, 0xcc24ba82, 0xfeffffcc, 0x05262b83, 0xff899a19, 0x55820500, 0x7e82ff20, 0x08201a82, 0xfc207f83, + 0x00212a82, 0x20148306, 0x212982fe, 0x7e830300, 0x6f84fe20, 0x9a990f22, 0x2405e448, 0x98190b00, 0x053f448d, 0x83030021, 0x040021c4, 0x3482e384, + 0xff280f83, 0x9a990300, 0x8c08928c, 0x17822282, 0x33ffff23, 0x20128434, 0x056f59ff, 0xdb840120, 0xe683ff20, 0x96860120, 0x0100ff22, 0x20057c46, + 0x22b082ce, 0x4308cc4c, 0x05200688, 0xf4228f83, 0xb48232b3, 0xed207a83, 0x06244783, 0x88089899, 0x19252f82, 0xffff059a, 0x207183f0, 0x20a18305, + 0x200983ea, 0x24048207, 0x32b3efff, 0x20408298, 0x261088f6, 0x95ce4cf6, 0x82fbffff, 0x0d002325, 0x1a826866, 0x4c82fa20, 0x880d0021, 0x990e22e1, + 0x82758398, 0x840f207a, 0x66082ccb, 0x00ffc566, 0x9f9a993a, 0x833100ff, 0xe6f62c96, 0xff910867, 0x33b3feff, 0x821500ff, 0xfbff21b6, 0x002c3b82, + 0xff9a1908, 0x6666fdff, 0x1000ff08, 0xfa252583, 0x00ffcdcc, 0x68658209, 0xfa2005a8, 0xef22bb83, 0x6f839919, 0xff21c182, 0x202e83ef, 0x200483ee, + 0x847e82f6, 0x0500230e, 0x1e823233, 0x5282fb20, 0x82010021, 0xeeff2a52, 0xff8f6866, 0x6666faff, 0x8416828c, 0xb30225db, 0xf5ffff34, 0xfd203f83, + 0xf8250983, 0xffffce4c, 0x207383fc, 0x21c483ff, 0x1984fcff, 0xfc207383, 0xff205483, 0xfa220983, 0x3d8234b3, 0x9a19ff28, 0x0000ff85, 0xa382cccc, + 0x82323321, 0x66662b09, 0x068b088a, 0xff70fb0e, 0x85829f00, 0xb3f90027, 0x00ff1533, 0x237b8366, 0x05cd0c98, 0xb082ba82, 0xb50e0026, 0x1300ffc2, + 0x00263582, 0xff52f803, 0x09820e00, 0x33f6ff22, 0x00215082, 0x257f830e, 0xffa430f6, 0xed830300, 0xd623ec23, 0x241983ff, 0x4af1ffff, 0x276f823e, + 0xff3333a1, 0x66a672ff, 0x34224882, 0x98463333, 0x13f7460d, 0xf746d682, 0x8bcc2706, 0x6b063b08, 0x338fdb07, 0xb944ce20, 0x44082005, 0x808308c0, + 0x0483f120, 0x844cee21, 0x444b2033, 0xb32009db, 0x1a847c82, 0x6766ed23, 0x228d828b, 0x643333ef, 0xdb44069a, 0x07cb230a, 0x846e063b, 0xffff2405, + 0x821fc5f0, 0x100f48dd, 0xe13a0f31, 0x330f00ff, 0x1000ff32, 0x088b1fc5, 0x8fab06db, 0x660d2833, 0x00ff8b66, 0x829a9912, 0x10002397, 0x2e82cdcc, + 0x33203385, 0xff243386, 0x9a193500, 0xa1216782, 0x2827822c, 0x059a598d, 0x32f6ffff, 0x2b6c826f, 0x00ffc2b5, 0xff17f903, 0x2adc1300, 0xb4270e82, + 0x0900ffbc, 0x82085ccf, 0x82b3200a, 0xcc09223b, 0x261982cc, 0xffffb8de, 0x82ae07fc, 0x41598219, 0x00310559, 0xffe27a64, 0x33f367ff, 0x30fb0e05, + 0x34f884f7, 0x0d626115, 0x230b5446, 0xff0080b0, 0x260f6261, 0x6b0604fb, 0x4134f707, 0xf1200d5d, 0x211f5a49, 0x358234fb, 0x18097941, 0x210cfaf9, + 0x3a46ffff, 0x18ab2014, 0x620e5440, 0x6e490f5d, 0x06ab2111, 0xe85933b3, 0x84ab2106, 0x1807be49, 0x2808e447, 0xdb0624f7, 0x8b1524fb, 0x4c7618ff, + 0x06042715, 0xf70734fb, 0x59620604, 0x07d1460e, 0x00ff0e2d, 0xf79a1977, 0x00ff1574, 0x8267e63f, 0x19292d25, 0xa700ff9a, 0xff0590c2, 0x66660400, + 0x402b6d82, 0x0c00ff00, 0x00ffcdcc, 0x8270fd09, 0x059f650e, 0x34b30e22, 0x0c347082, 0xffffcccc, 0xff9002f6, 0x00800300, 0xc0f1ffff, 0x00ff0800, + 0xff234083, 0x82703d58, 0xcc402240, 0x275182cc, 0xff34b338, 0xb81eaa00, 0x05211082, 0x215c8299, 0x3082c210, 0x32331222, 0x11245182, 0x1000ffec, + 0xff231e82, 0x82f468fa, 0x8310203a, 0x68fa224f, 0x211982f6, 0xd6480200, 0xfe7f2b07, 0x3aefffff, 0xff5908e2, 0x44846aff, 0x9a991322, 0x630fd741, + 0x354307a2, 0xffff2316, 0x338219d7, 0x4cc7ff22, 0x5526af82, 0xff0566e6, 0xb083fbff, 0x0484f220, 0xff343324, 0xf582f7ff, 0xb3f2ff22, 0x01239382, + 0x82086666, 0xcecc24ca, 0x83ffffff, 0x82f32099, 0x09002193, 0xff210482, 0x230e82fb, 0xcecc0d00, 0xd6271e82, 0x00ff66e6, 0x82cccca7, 0x84d12048, + 0x23108359, 0x343358ff, 0xfc201082, 0xff21e382, 0x20de82f2, 0x443a83ff, 0xcc26062d, 0x0000ffcd, 0x5984cc4c, 0xffffcd23, 0x202383fe, 0x217382f3, + 0x49820800, 0x00238c84, 0x8200800d, 0x57c7271e, 0xaa00ff0a, 0x48829a19, 0x5c0fd722, 0x200a554a, 0x10b943c7, 0x11823320, 0x82395421, 0x4a4c2004, + 0xff230755, 0x83991300, 0x0bce27e7, 0x9500ff02, 0x448248e1, 0x3769fa31, 0xc51000ff, 0x0900ff1e, 0x00ff9e0f, 0x82b81e12, 0xd7c3270e, 0x970500ff, + 0x0a82080a, 0x831fc521, 0x850c200a, 0xf6ff2319, 0x198414ee, 0xefffff24, 0x1e82703d, 0x71bd3825, 0x8355ffff, 0x15003948, 0x154bcd4c, 0x330f00ff, + 0xd2ffff34, 0xff056666, 0x66660b00, 0x992d00ff, 0xe529aa83, 0xff066666, 0x34b36b00, 0x272282cb, 0x0666e60e, 0x1c00ff84, 0xf820c484, 0xff25e482, + 0x0566e6e3, 0x223d83eb, 0x87cc4c0c, 0x8648833d, 0x80e42c3d, 0xfb0e0600, 0x14f88b30, 0x18ff8b15, 0x2114f5a7, 0xd44934f7, 0x101d5d0a, 0xfb061423, + 0x17bc5db4, 0x1894fb21, 0x27175976, 0xf70714f8, 0xf7154b94, 0x14250682, 0xfb0514fb, 0x25838314, 0x54f894f7, 0x1283fb15, 0xf7247082, 0xfb6b0514, + 0x07829382, 0x7444fb21, 0x43180c9b, 0x6a180aa9, 0xb4211a73, 0x0b441806, 0xff702209, 0x0b441800, 0xc4f72709, 0x80ffff07, 0x538266e6, 0x6766ed25, + 0x54ffff8b, 0x984505e1, 0xfbbb2508, 0x34fb15b4, 0x0ce97e18, 0x260a2f5c, 0x0800ff8b, 0x82ffcccc, 0x05465c11, 0xcd230e83, 0x82f7088b, 0x08002330, + 0x1e8204d6, 0xfc290727, 0xd6f8ffff, 0x23598288, 0x087829f7, 0x33210683, 0x4f118234, 0xcc2905fd, 0x33f7ffff, 0x8b088b34, 0x2264e2cb, 0x9615db9b, + 0x18e0b67e, 0x34137db9, 0xef00ff0e, 0x00ff9a99, 0x1566e64a, 0xf00b00ff, 0x0d00ffa4, 0x2ce6820c, 0xffb81eff, 0x90421400, 0xf8f2ffff, 0x22188294, + 0x8208c2f5, 0x33733a0a, 0x6b0c00ff, 0xebffff86, 0xffff3eca, 0xff9819fe, 0x3d8af4ff, 0x81f3ffff, 0x2d1e82cc, 0xffc896df, 0xf8b3dbff, 0x2e01ff05, + 0x5d5fec11, 0x85ab2109, 0x20051b77, 0x10484cff, 0x106aff20, 0xce4c3006, 0x07c2fb08, 0x99dfffff, 0x2300ff99, 0x8205d663, 0x3d0a2157, 0x8f826b82, + 0xc0ebff24, 0x7b828c00, 0x7f71fd22, 0xf2226382, 0x1b8252f8, 0x2121a184, 0x21878248, 0x9c82e2ba, 0x8256ee21, 0x34f32d1f, 0x5700ff08, 0xffff9a19, + 0x05f6e89f, 0x1e213b82, 0x271582b9, 0x00ff70bd, 0x8ba4f016, 0x2f820f82, 0x420d0023, 0x27258290, 0xff25e658, 0xc2f56000, 0xd0332582, 0xffff6666, + 0x159a19d5, 0x40cdffff, 0x00ff0600, 0x84486149, 0x241b8204, 0xfff02709, 0x2b048400, 0xffe8bb02, 0x06c10d00, 0x0cfbffff, 0x0b231e82, 0x890852f8, + 0x268f820a, 0x00ffb648, 0x821ec507, 0x34332c6f, 0x14fb088b, 0xefffff06, 0x508b3233, 0x9a4809d1, 0x0e00230d, 0x1b857a54, 0xab110024, 0x91828b86, + 0x82c03221, 0x06c65e7b, 0x82b89e21, 0x2aa818fe, 0x44fd2209, 0x26578218, 0x00fffa3e, 0x82b8f304, 0xae07216b, 0x0a872f82, 0xb727fc82, 0xf8ffff4a, + 0x8397e23a, 0x197f2246, 0x22c2829a, 0x82008013, 0x6b0e20ef, 0x0a82065e, 0x6a079e6b, 0xff34122d, 0x9a992c00, 0xb3ce00ff, 0xffff1533, 0xff9002b0, + 0x9919a000, 0xf52c7f82, 0x00fff628, 0xff5ecf15, 0xa470dcff, 0x0f83bd82, 0x30eaff24, 0x258208a2, 0xffac0726, 0x67e65fff, 0xf8362582, 0xffff1018, + 0xff0a17f0, 0xf0670600, 0xabecffff, 0x0f00ff85, 0x90825ccf, 0x08cd0c22, 0xde200a82, 0xf827b082, 0x00fff713, 0x82862b13, 0xec712623, 0xe30700ff, + 0x211882d6, 0x1e8283e0, 0x6c27072d, 0x630e00ff, 0x00ff05d7, 0x82146e58, 0x231083b8, 0x299cf1ff, 0x062c1082, 0xffff8c2c, 0xffeb91f3, 0xc6cb1100, + 0x8f2bf582, 0x1200ff5c, 0x00ffc2f5, 0x82537809, 0xca0f223a, 0x204a83c4, 0x215482d7, 0x5e826666, 0xd4186620, 0x0f2207cb, 0xa28266e6, 0x32338332, + 0xe62900ff, 0x00ff1567, 0xff343310, 0x32b32000, 0x10275382, 0xffff5238, 0x82b85edf, 0x94df23b8, 0xd582067a, 0x16eeff2f, 0x00ff0e15, 0xff9a9997, + 0xcc0c9601, 0x2b728215, 0x00ff48e1, 0xff90420d, 0x5c0fe9ff, 0xf3202182, 0xf222c283, 0x548270bd, 0x66e6a827, 0xe89fffff, 0x303e82f8, 0xffba29f3, + 0xa2f0f2ff, 0xe00000ff, 0xebffff00, 0x226382b3, 0x8231080d, 0x9a1921a7, 0x0d229d82, 0xa4421f05, 0x051d7005, 0xf6e80027, 0xf30b00ff, 0x21588233, + 0x1e825403, 0xad822020, 0x6d230027, 0xc2fb0550, 0x20628207, 0x21ac83ee, 0x946b4c0e, 0x0b06520c, 0x4c0e0023, 0x06424acc, 0x2d01ff28, 0xff073433, + 0xf4822000, 0x99dcff23, 0x22d4829a, 0x82c3750b, 0x8e8226b5, 0x351400ff, 0x06a74dc2, 0xcd8c0d27, 0x6a0c00ff, 0x226b82c0, 0x83ae070d, 0x209f827b, + 0x23c98200, 0x1e451400, 0x11219982, 0x218a82aa, 0xd383ce0c, 0xffd2022a, 0x900d6000, 0x2801ff05, 0xfe235382, 0x4334f389, 0x52213d09, 0x05e24170, + 0x11f3ff24, 0x60828bec, 0x8e177f22, 0x24050c43, 0xfaffffff, 0x05f442e2, 0x99f1ff23, 0x1003109a, 0xaf259b01, 0x34f734f8, 0x83c31815, 0x148c5c07, + 0x18a36e18, 0x9a195f22, 0x0c2f4318, 0x0a754418, 0x2108df7b, 0x0f4634b3, 0xcc4c2707, 0x14f7088b, 0x6c8294f7, 0x66e62025, 0x8cffff06, 0x8484206c, + 0x087c2165, 0x33860685, 0x84abf123, 0x073545ff, 0x6c86df20, 0x67822882, 0x71187c20, 0x6c85140b, 0x15577c20, 0x54fb2506, 0x6b1514fc, 0x8d18688f, + 0x808408a0, 0x86206888, 0xab206886, 0x1b7dd188, 0x22d1870e, 0x929a99f2, 0x9e6020d1, 0x887b20d1, 0x88852068, 0x419f20d1, 0x7b20113e, 0x85216584, + 0x71068408, 0xfe2a125f, 0xff6666e0, 0xcc4c55ff, 0xe557ff15, 0x99dc2205, 0x0b81479a, 0x49ff3221, 0x54210623, 0x23de827c, 0x088bcd4c, 0x470bd26f, + 0x54361581, 0xffff057a, 0xff21b0f9, 0x0ce20600, 0x5ff7ffff, 0x0300ff3b, 0x09823c7f, 0x2d050a54, 0x8bef47f8, 0x3ff8ffff, 0xfdffffbe, 0x2a821038, + 0xff29dc26, 0xf45dfaff, 0x213ea047, 0xa047ff47, 0x19572806, 0x6000ff9a, 0x48050a17, 0xf4222092, 0x23829cc4, 0xff1cef2f, 0xccccebff, 0x19ffffff, + 0x087e7f98, 0x6dc1420e, 0x42fb4b21, 0xcb22ce53, 0x914314f7, 0xfeff2768, 0xff9a9977, 0x7d47f6ff, 0x3d2a212b, 0x21117d47, 0x7d47ae07, 0x24063107, + 0xfaffff19, 0x00fff85e, 0xffbfbf07, 0x0c37fdff, 0xb8290982, 0xff088b52, 0x08ac0800, 0x2b05828b, 0x00ffc5a0, 0xff048103, 0x5c4f0600, 0xe2210482, + 0x089447d2, 0x478c6c21, 0x54212894, 0x0659497a, 0x4705ed4a, 0x97200a94, 0xff2d9d82, 0x1400ffff, 0x988a3433, 0x000c00ff, 0x09884701, 0x00ff3222, + 0x2d158847, 0x00fff007, 0x057a1460, 0xf7d4f70e, 0xba181594, 0xf2220cee, 0x29630a97, 0xcb082105, 0x19225682, 0x3763059a, 0x1168630b, 0xb918ff20, + 0x57820ee6, 0x071e0522, 0x0b26ac82, 0xffffa430, 0x688227fa, 0x0a570a2d, 0x76f6ffff, 0x0500ffc8, 0x82085ccf, 0x1078210a, 0xc7260a82, 0xf4fffff0, + 0xa182fa1e, 0x82326821, 0xec112113, 0x22082d82, 0x6b08bedf, 0x68efffff, 0xffff05f6, 0xff5c4ff0, 0x00e0f7ff, 0xe1f9ffff, 0xecffff48, 0x00ff5caf, + 0x84b81e08, 0x82082018, 0xc2b5213f, 0xff263f82, 0x0b00ff7e, 0x23829a19, 0xeb82b320, 0x1b6f0b20, 0x99d02305, 0x0876079a, 0x084f520d, 0xffffd329, + 0x156666c0, 0x19cfffff, 0x2116de1e, 0x66828fdb, 0x6626162a, 0xbde0ffff, 0x1f00ff72, 0xff230e82, 0x8246a1f2, 0x51f822b5, 0x2c8f8268, 0xff05fafe, + 0xae47f5ff, 0xd7f4ffff, 0x20bb820a, 0x209a8261, 0x220e82ee, 0x82270b00, 0x51f523e4, 0x9a8208ec, 0x82a27521, 0x82d52dcb, 0xfdffff92, 0x00ff6666, + 0x8b68e606, 0x072b1682, 0xff8b1058, 0x42600700, 0x820200ff, 0x050023d6, 0x2b825278, 0x8200c021, 0x9c452b1a, 0x4800ff28, 0x00ffae87, 0x7582fd13, + 0x2adc0c22, 0x2a222982, 0x1a82f468, 0x8e020026, 0x793100ff, 0xd827e282, 0x00ff9a99, 0x85008026, 0x8b0823bc, 0xc78204fb, 0x1ec5f223, 0x2490828b, + 0x00ffe23a, 0x240a830a, 0xe23a0d00, 0x823c8208, 0x86118406, 0x830e8204, 0x85068382, 0xf5ff2311, 0x3882e23a, 0x2d823e82, 0x0682ff20, 0x33214482, + 0x2c498534, 0xccccf2ff, 0x44fb088b, 0x4c2f00ff, 0x226382ce, 0x82f853f7, 0x5ff7252a, 0xfcffff3b, 0xf9327e83, 0xffffa4b0, 0x08b81ef9, 0x9cdfffff, + 0xdcffff29, 0x02467a94, 0x0cf43b44, 0x0d00ffcd, 0xffff9002, 0xff00c0eb, 0x66e60000, 0xfaf2ffff, 0xf4ffffe1, 0xeb451a0f, 0xabfb3171, 0x0500ff02, + 0xffff8aa1, 0xff3333f8, 0xcecc0200, 0x4c230982, 0x10088bcd, 0x1a023303, 0x9ffeff2a, 0x00ff70fd, 0x1566e6af, 0x220dfe45, 0x45ff0080, 0xe12206fe, + 0xbc450848, 0x23002305, 0xfe45866b, 0xcc4c2107, 0x23052d56, 0x86abf1ff, 0x2808a857, 0x8b1fc510, 0x3a0f00ff, 0x451b83e2, 0xf72507fe, 0x00ff07c2, + 0x242f8221, 0x9a99dcff, 0x0afb4505, 0xffffff2a, 0xff989a19, 0x67e60b00, 0x2227ff45, 0x4e050a17, 0xf6202382, 0x2a272583, 0xf2ffff3d, 0x4eff14ee, + 0xcc270682, 0x0d00ffce, 0x827fae07, 0x2306316a, 0xfaffffd7, 0x00ff6666, 0xff00c007, 0x3233fdff, 0x20060047, 0x06b4680e, 0x74f71523, 0x23c88207, + 0xff85ab11, 0x8520df82, 0x6e203882, 0x7a06ae62, 0x5422053d, 0x18858b7b, 0x0a821d83, 0xe13aef26, 0x20ffff08, 0x18052168, 0x22094148, 0x5fec91f2, + 0xcb210693, 0x26088206, 0xffff33b3, 0x553433fe, 0x0d220655, 0x62820080, 0x00801228, 0xf714f808, 0x0b821573, 0x82801a21, 0x85ea2d8c, 0x1500ff1e, + 0xffffe27a, 0x8be27ae5, 0x6d225582, 0x3c820080, 0x82c51621, 0xe8252516, 0x0b00fff4, 0x0023b282, 0x8252f82a, 0x230f2230, 0x2a2082d8, 0xffe2faff, + 0x7c941700, 0x82edffff, 0x18002440, 0x836c1e85, 0xdec02237, 0x312282b8, 0xff20c524, 0x9ad9b3ff, 0x28aeffff, 0xbefffff5, 0x3182cc8c, 0x33b3ef28, + 0xffff057e, 0x908233f4, 0x0080f622, 0xf221e482, 0x23218219, 0x7d67e6ff, 0x022a4f84, 0xfaffffff, 0x0000ff02, 0x0484fe05, 0x4f838b20, 0x66e6ff25, + 0x820534fb, 0xe6f02aec, 0x0700ff66, 0xffffee1c, 0x085c82f1, 0x160c0023, 0xf6ffff45, 0xff08a2f0, 0xd7232200, 0x68e6ffff, 0x00ff05f6, 0xfff6a81b, + 0x162eebff, 0xb32100ff, 0x216a8234, 0x1e82cccc, 0x82989921, 0x3a002348, 0xd08234b3, 0x1e851a22, 0xe8839e82, 0x78150022, 0x1a23cc83, 0x82089082, + 0xa2032211, 0x207d8290, 0x22788284, 0x820c8203, 0x823c2009, 0x68032257, 0x2d058230, 0xfffa3e13, 0x1e450600, 0x1100ff99, 0x2a82cecc, 0x0e741520, + 0x25093105, 0xfdffffe4, 0x00ff924d, 0xff447608, 0xd88efbff, 0x45219e82, 0x27318220, 0xff303d16, 0xb81e0400, 0x23054f5c, 0x00801300, 0x17203582, + 0x0c223585, 0x2b820080, 0xff641b2b, 0xae470b00, 0x2cf8ffff, 0x213f824a, 0x35823e8a, 0x86eb1827, 0xae0100ff, 0x06b65b14, 0x9a991422, 0x19203582, + 0x0e283582, 0x9f01ffeb, 0x4b15c2f5, 0x300c9061, 0x16aef1ff, 0xefffff8b, 0xff085038, 0x68e620ff, 0x09fa4d07, 0xffff7b22, 0x210e0242, 0x4b8285ab, + 0x2105bd71, 0x0a827a54, 0x83c51021, 0x35de22a7, 0x056e42c2, 0x8a4c8620, 0xea512207, 0x05c062ff, 0x7301ff2a, 0xffffcc4c, 0x150bd72f, 0xcc21d582, + 0x82a482ce, 0x051d5eb8, 0xcd4c0b22, 0xc8824282, 0x06820820, 0x52781722, 0x21218482, 0x26b58248, 0xffff3473, 0x82e0bae9, 0x842b21fa, 0x0422cf82, + 0x3a82a470, 0xffc23526, 0x34b30200, 0x8b213f84, 0x2e318395, 0x7dec5115, 0xdc1100ff, 0xecffff28, 0x72ff00c0, 0x002205a2, 0x0a82c000, 0x828c0221, + 0x83002068, 0x82032268, 0x225c8290, 0x1846a103, 0x20088853, 0x201683ea, 0x236d8315, 0x8b0080e5, 0xc528f382, 0xff065c4f, 0xd863ddff, 0xde32f882, + 0xffff7a54, 0xffaec7f4, 0x5c4fe4ff, 0x3debffff, 0x1a820870, 0x4229dc21, 0xff2d0616, 0xff67e6f3, 0xa4f0f6ff, 0xe6f8ffff, 0x21ec8266, 0x3482e2ba, + 0xccccf122, 0x0026a682, 0x34fb7f1b, 0x0f828b05, 0x210c7b42, 0x0e82ffff, 0x11201e83, 0xf2220982, 0xa7829002, 0xff7e0d2b, 0xcc0cf2ff, 0xc90b00ff, + 0x214d8279, 0x1e827a94, 0xcd4c103a, 0xf8f2ffff, 0x00ff0552, 0xfff2e151, 0x0c97bdff, 0x33dbffff, 0xb3ffff32, 0x00236882, 0x829a193f, 0x1e0023aa, + 0xcd82c2f5, 0x82821221, 0x85182245, 0x220a821e, 0x830a9717, 0x260f21d8, 0xf4318c82, 0x00ff703d, 0xff52f82a, 0x723de9ff, 0xe62500ff, 0x22578266, + 0x42cc8c92, 0x2a081aac, 0xffd86319, 0x3433ecff, 0x991400ff, 0xe7ffff9a, 0x00ff9819, 0x0833b301, 0xff70fb0e, 0x00600900, 0x997600ff, 0x00ff159a, + 0x838f820c, 0x22768204, 0x82004014, 0xe0fa21c7, 0x7d260e82, 0xf3ffff71, 0x64829082, 0x29824920, 0x99b6ff27, 0x01ff059a, 0x05927272, 0xc4181120, + 0x146e0788, 0x830e8205, 0x140c6ebe, 0x8dfeff25, 0x55073433, 0xa4730c97, 0x05027a18, 0x18f3ff21, 0x20126547, 0x059173fb, 0x95821a82, 0x12514618, + 0xf714fb29, 0xffff0514, 0x82b87ef3, 0xea912144, 0x10e96718, 0x0121f283, 0x09207536, 0x707df322, 0xe3832d82, 0x21051949, 0xed841e05, 0x0825f784, + 0xa6b6ffff, 0x22b28266, 0x8205ce4c, 0xcc4c22be, 0x2eba6f07, 0xb3720122, 0xff23f282, 0x8248a1b6, 0x38d57449, 0x07a81a19, 0x4618ed82, 0x142115dd, + 0x21f282fb, 0x54190c00, 0xe3411842, 0x99d62306, 0x4b9f159a, 0x821a7941, 0xcdac21c2, 0xa6210482, 0x82aa1866, 0xd45b1812, 0x10de7011, 0x4c8dfe29, + 0x00ff06cc, 0x82476149, 0xb89e2144, 0x0efa6918, 0x7400c021, 0x0a820a3f, 0x418f8221, 0xff210587, 0x221983eb, 0x41e0faff, 0x002405a5, 0x0890820c, + 0x2107e341, 0xae82ec71, 0x41ae8721, 0xff2711e3, 0x9a99f601, 0x75a900ff, 0xe64109c1, 0x4b702006, 0x05210700, 0x08e64120, 0x48187020, 0x49221d85, + 0xb4823273, 0x189a5921, 0x551278ac, 0x83820ad0, 0x72831220, 0x5c4f0e22, 0x20054241, 0x050b4300, 0xcc720122, 0xff23f482, 0x82b89eb6, 0x48612144, + 0x1806d776, 0x18149547, 0x761a7246, 0x0c2206b4, 0xb582146e, 0x8b527822, 0xcc21c582, 0x210a82cc, 0x04830280, 0x0e080026, 0x04f770fb, 0x192f9f18, + 0x0dad8118, 0x082c9f18, 0xe5274682, 0xffff707d, 0x820080ea, 0x90822104, 0x20052b7a, 0x0b327a08, 0x2e0ab05b, 0x15e4fb73, 0x33eeffff, 0xffff0633, + 0x827b14f5, 0x4af82c3c, 0x0a00ff3d, 0x00ff34b3, 0x82337303, 0x66662909, 0x2600ff08, 0x00ff8f42, 0xe982f482, 0x6626de27, 0x99c7ffff, 0x210a829a, + 0x0a82e6f6, 0x0483f020, 0x0a57ec32, 0x19fbffff, 0xf0ffff9a, 0x00ff9ad9, 0x089a1909, 0x7f200a83, 0x19830a84, 0x00ff7225, 0x82989913, 0xa01a260e, + 0x330f00ff, 0x29538234, 0xff659b35, 0x34335900, 0x8757ff05, 0xb3212705, 0x2400ff32, 0xce445278, 0x27002405, 0x828bcd4c, 0x990b2425, 0x84ff069a, + 0x831c820c, 0x66eb22d2, 0x26218266, 0xffff3233, 0x82ce4cde, 0x99352120, 0xa6227582, 0x4682cccc, 0x75827682, 0x6818cc20, 0xec2207fd, 0x0e826866, + 0x8205f163, 0xf0ff21c4, 0xb3841983, 0x00211983, 0x82198604, 0x27ae848f, 0xff9919de, 0x66663800, 0x25254882, 0xffff6766, 0x219a848d, 0x4e824c04, + 0x6383f520, 0xce4cf825, 0x84f5ffff, 0x9919210e, 0xff259a82, 0x063333ee, 0x12b4622b, 0xc553ee20, 0x0a3a610f, 0x7b07eb22, 0x8b2a33b0, 0xfb0e05eb, + 0xf864f770, 0xdc411524, 0xff8b252d, 0x90821a00, 0x2005a77b, 0x5bb81800, 0x16384209, 0xc4fb5323, 0x0b606815, 0x9b088463, 0x00ff2fcf, 0x079a19df, + 0x6ee3ffff, 0xd0ffff14, 0x15426666, 0x463a2640, 0x6000ffea, 0x314882e6, 0x9a591100, 0xe61c00ff, 0x1f00ff66, 0x00ff3433, 0x0482b311, 0x34b3212c, + 0x00ff088b, 0x06cccc1d, 0x0c8300ff, 0x33251c83, 0x4ceeffff, 0x212182cc, 0x89826766, 0x829a1921, 0x333a2720, 0x9fffff32, 0x15429a19, 0x66e32140, + 0x2f217f82, 0x4b488299, 0x6a820861, 0x41f1ff21, 0xf739241d, 0x8b7b0714, 0x94f70e05, 0xe62001ff, 0xffff1566, 0x8be1faca, 0xebd5ffff, 0x21048285, + 0x0a821f05, 0x47e1cb23, 0x23068408, 0x2900ff48, 0xff28e582, 0xff5238d3, 0x66e63500, 0x0683e583, 0x00291685, 0x8be2fa2a, 0x1e3400ff, 0x832d82b8, + 0x203f8206, 0x239882e6, 0x56aec72c, 0xfd202983, 0x44229383, 0x62829a19, 0xceccc027, 0xe65b00ff, 0x21f98266, 0x2282263f, 0x90025b22, 0x2b080a82, + 0xfffc5406, 0x00200900, 0xc5faffff, 0x0c00ffa4, 0xffff729d, 0xffec11f5, 0xe0fa0100, 0xff01fb08, 0x34b31300, 0xecffff05, 0x01f7cc4c, 0xfe210782, + 0x08398206, 0x14ee0a21, 0x62f3ffff, 0x0500ff90, 0xffffe03a, 0xffb8def6, 0xfca9f9ff, 0xa4ffff08, 0xfffffafe, 0x82bcf4bf, 0x19a42729, 0x3f00ff9a, + 0x0a826e27, 0x00e0f627, 0x540600ff, 0x203483fe, 0x2668828f, 0xffff66c6, 0x831f05fe, 0x82aa2068, 0x38ed2734, 0x92ffff51, 0x2982c2f5, 0x6b830582, + 0x0a82ce20, 0xb012f522, 0x19212582, 0x212f8298, 0x398260c5, 0xbd824c20, 0xf7234384, 0x8308cccc, 0x826d2059, 0x9a19216e, 0xc0222982, 0x0a8299d9, + 0x8270fd21, 0xabf9220a, 0x838f8202, 0x3a05226e, 0x22a3861d, 0x82d3ed0a, 0x1e052448, 0x8401f708, 0x23f482c7, 0xfb33b313, 0x0023cd82, 0x869af901, + 0x9d0c22ed, 0x20688370, 0x0570711e, 0x56060023, 0x22638204, 0x8619045b, 0x5b0027c2, 0xffff9002, 0x6e82d9c0, 0x20090023, 0x35ee8284, 0x00ff80aa, + 0xff7c9f0c, 0x1c3a0500, 0xf80100ff, 0x0a00ff52, 0x3482d2ed, 0x34b31325, 0x820501f7, 0x0539416b, 0xf80a0023, 0x211f8250, 0x298292ed, 0x82323321, + 0x32b32133, 0xb3213d82, 0x21688234, 0xfc829a19, 0x0a820220, 0xe6dbff32, 0xffff1566, 0x8b5c4fb9, 0x97c7ffff, 0x3900ff0a, 0x00250a83, 0x083eca45, + 0x10ae188b, 0x5c4f2707, 0x683800ff, 0x1583fff6, 0x85088b21, 0x24288406, 0xb3c6ffff, 0x22388232, 0x823433ba, 0xb9ff232d, 0x4482cc4c, 0x869a9921, + 0x260e8204, 0xab0e088b, 0x821554f7, 0xcc7b2749, 0x6400ffcc, 0x0482cd4c, 0x81823320, 0x00807b22, 0x0b224983, 0x1b82295c, 0x0a57122a, 0x54feffff, + 0x0b00fffe, 0xff231b82, 0x8208ecfd, 0x9d092264, 0x351482b2, 0x00ff1639, 0xff4e2202, 0xa225f3ff, 0x87f7ffff, 0xfbffff6c, 0xbc82a430, 0x6005c931, + 0xafe0ffff, 0xdeffff9e, 0xffff3333, 0x8266e6c5, 0xccc02287, 0x208783cd, 0x25668392, 0xffc3b563, 0xe282acff, 0x836c0021, 0xb31422d6, 0x3a548332, + 0x00ff9e8f, 0xff14ce01, 0x10b80600, 0xdef4ffff, 0xf9fffffa, 0xffff7ad4, 0x82be5ff8, 0x4ad62c54, 0xccffff3e, 0xffff3473, 0x8266e6c0, 0x22ca835e, + 0x820100bb, 0x84ff23a9, 0x6082cd4c, 0x16829b20, 0x66640022, 0x00236b82, 0x829a997b, 0x829b20dc, 0x18ff20db, 0x211388a6, 0x8f62f4f7, 0x07a42b18, + 0xfb0654fc, 0x14f707a4, 0x3e8258f7, 0x82060021, 0x05002466, 0x85ff6666, 0x230e8204, 0x3cf7088b, 0x79183e82, 0xff230989, 0x829a99fa, 0x66f9257e, + 0x07830866, 0xff200885, 0x04861383, 0x8b221782, 0x3282fb08, 0x0983ff20, 0x4c831485, 0xe7828b20, 0x9326a682, 0xf7d4f707, 0x75821560, 0x79ffff21, + 0x484909f9, 0x185b200a, 0x2f093fa6, 0xffff2130, 0xffccccf8, 0xdfcf0800, 0x74f8088b, 0x176d8118, 0x3282bb20, 0xb0110024, 0xbe77ffa4, 0x5c4f2106, + 0xbe775b82, 0xf7f42805, 0xffff15f4, 0x82a470fc, 0xf0ff2822, 0xffff9042, 0x86cc4cf3, 0x4cf02f04, 0xff088bce, 0xcccc78ff, 0xf0ffff06, 0xcb82cd4c, + 0x6766f227, 0xb30c00ff, 0x28ac8234, 0x0870bd0f, 0x8f0300ff, 0x2a39825c, 0x1e053500, 0x2a00ffb6, 0x44c0e2fa, 0x4c180777, 0xff270c73, 0xb85ec9fe, + 0x18f6ffff, 0x23082a53, 0x1e850c00, 0x0d767518, 0x82e27a21, 0xf83f2e4d, 0xff054b53, 0x33b30000, 0x66ffffff, 0x21098266, 0x09829999, 0x00239182, + 0x839a9900, 0x82ce2009, 0x4c0e2525, 0x0700ffcd, 0x10201483, 0x2406e77b, 0x331000ff, 0x20798334, 0x05f77270, 0x829a1921, 0x191021a0, 0xfb213182, + 0x204582e6, 0x232b820e, 0x34b3f8ff, 0x46833b82, 0x32205f82, 0x9a205a83, 0xb3210482, 0x85048334, 0xcb08220e, 0xf1ca19cb, 0x0d044b1b, 0x0c537318, + 0xb5824b20, 0x80feff23, 0x82a18300, 0x3300229b, 0x21098232, 0xb0846766, 0x7982c984, 0x9a190626, 0x0300ff7f, 0xff218f82, 0x21cb82f2, 0x9e830100, + 0x66e6f122, 0x40221a82, 0xb767cc4c, 0x5f34200f, 0xff210d41, 0x0ded6af1, 0x82064b21, 0x66e7221f, 0x06dc7066, 0xcecce825, 0x83f6ffff, 0x33eb2250, + 0x20508232, 0x200a8302, 0x263282fe, 0x98190200, 0x82feffff, 0x01002128, 0xfe242383, 0xcb089a19, 0x0021ac82, 0xb892180c, 0x4bca8c0a, 0x0220086f, + 0x0d9a7418, 0x08fe7f2c, 0xe6c0ffff, 0xff05ca66, 0x3c83e7ff, 0x3433ea25, 0x84e0ffff, 0x9a992496, 0x83ddffff, 0x99fc2213, 0x297d8298, 0x073433ef, + 0x0800ff8b, 0x9e42cdcc, 0x33072206, 0x429e8233, 0xf822054d, 0xba829919, 0x67e6f722, 0xcd201b83, 0x33210a83, 0x2d598233, 0x07cccc10, 0x66deffff, + 0x0300ff66, 0x58836866, 0x00ff3323, 0x840e820e, 0x1500236c, 0x2482cccc, 0x14eec023, 0x062b4b4c, 0x80f3ff22, 0xbd21a083, 0x20418271, 0x217a82f3, + 0xa0840c00, 0x8f82f322, 0x08ed7718, 0x00239f82, 0x84717d0c, 0x2795820f, 0xcbae0740, 0x0100ff05, 0x00229582, 0x6782e601, 0x9a190222, 0xbb820e82, + 0x09850020, 0x62834c20, 0x9919f627, 0xcc1400ff, 0x055841ce, 0x33170023, 0x22c98232, 0x539a9918, 0xcc6a0e39, 0x00ff2521, 0x06cd4c40, 0x14216082, + 0x83c8827b, 0xeb03256a, 0x0d00ff86, 0x0024d282, 0x979a1906, 0xff20ce82, 0x200ad742, 0x07eb42cd, 0x00221f83, 0x1e8233b3, 0x52f8bf22, 0xff20b082, + 0x8b21d298, 0xd3491806, 0x56dc7817, 0xdcfb2b2d, 0xffff8b15, 0xff1078f6, 0x8258faff, 0x57f72c04, 0xf7ffff4c, 0xfffffa3e, 0x82a430fc, 0xe8fc27b1, + 0xfefffff6, 0x0f8234b3, 0xffcccc23, 0x24df83ff, 0x34b3fcff, 0x221a828b, 0x82e00ffa, 0x20fa263a, 0x0200ffc4, 0x313a8238, 0xff5278fb, 0xe02f0400, + 0xf304fb08, 0xfbffff05, 0x0e82d723, 0x18829820, 0x3333fd28, 0x4c0600ff, 0x05828bcc, 0x0834b322, 0x34820685, 0x82f0c721, 0x7a542110, 0xe0212582, + 0x23048200, 0xf7085c8f, 0x00223983, 0x18830707, 0x002d9282, 0xff62300a, 0xe0af0100, 0xb80800ff, 0x22828252, 0x82080040, 0x38b4210a, 0x34240a82, + 0x0500ff3a, 0xf7209783, 0xff295883, 0x080080f6, 0x0e0764fb, 0x05ee468b, 0x66668d27, 0x997200ff, 0x8204869a, 0x20b1820e, 0x85068300, 0x84ff2011, + 0x82ff200a, 0x188e8221, 0x292b254e, 0x152b94f7, 0xb6b68bc0, 0x3882c08b, 0xe6350022, 0x099c9018, 0xcaffff25, 0x498b9a19, 0x56190584, 0xff200c82, + 0x0cc39d19, 0xfe01ff2e, 0x00ffcc4c, 0x159a191a, 0x67faffff, 0x1026e982, 0xffff00c0, 0xe98210ee, 0x0a17093b, 0x0fefffff, 0xfaffff5c, 0xff084861, + 0xb89eecff, 0x8ff9ffff, 0xffff05e0, 0x223483d6, 0x8252f863, 0x26fb360a, 0x0d00ff68, 0xffff480c, 0xffce4cf4, 0x9a190700, 0xe6f2ffff, 0x30e08266, + 0x52389eff, 0xf5ffff06, 0x05bb9a99, 0x1c4100ff, 0x0caf7f2a, 0x2322775c, 0x1e05b1ff, 0xfe304082, 0x00ffcc8c, 0x05cccc06, 0x33fcffff, 0x1b00ff33, + 0xe7286283, 0x00ff6666, 0x71ce4c11, 0x4c271482, 0xffff08cc, 0x8467e6e4, 0x3bbc820a, 0xffff9999, 0xff34b3e7, 0xcdcc0300, 0xb3e5ffff, 0x00ff0834, + 0xff14ae17, 0x989973ff, 0x01228982, 0xd782b99e, 0x829a9921, 0x201f83b6, 0x210983f3, 0xb1836610, 0x668d0023, 0x27a48266, 0xff2adc2c, 0x9a1994ff, + 0x05242b82, 0xffff3c0a, 0x97232182, 0x83f8ffff, 0xb30c22f3, 0x24d98234, 0x10580300, 0x265e828b, 0x00ffe06f, 0x82048800, 0xc8562909, 0x1f0100ff, + 0x9bbb08ec, 0x103f3482, 0x00ffaec7, 0xff448b05, 0x02000900, 0x191200ff, 0xfaffff98, 0x00ff6466, 0x08cecc10, 0x82a1feff, 0xd5ff349a, 0xff1566e6, + 0x713dc2ff, 0xcdffff8b, 0x00ff8fc2, 0x82703d32, 0xc23d2352, 0x06820890, 0x00403625, 0x832600ff, 0x4c2d2646, 0x3300ffcd, 0x22508247, 0x8200400a, + 0x0af838e6, 0x2f00ff3e, 0xff053333, 0xc2f5b5ff, 0xc7ffff7d, 0xffffa4f0, 0x829a19bf, 0xe6b12247, 0x263c8266, 0x48a1a7ff, 0x824700ff, 0xb8ff2804, + 0x00ffb85e, 0x83b95e58, 0x824d20b2, 0x00ff23e1, 0x58828040, 0x52f8362c, 0xe60e00ff, 0x4900ff66, 0x5382ae07, 0x82e6ce21, 0xf1ff26f5, 0xffff3433, + 0x211582d1, 0xa083d5ff, 0x9a19de22, 0x34829982, 0xf8ab0824, 0x49181504, 0x7d200d6c, 0x07c38919, 0x0d596f18, 0x0aafc118, 0x0bfd4918, 0x210ff84f, + 0x84821500, 0x82eaff23, 0x22548290, 0x548b0080, 0x6f20050d, 0x01236e82, 0x8266e600, 0xe6702269, 0x1cc67867, 0xffff672a, 0xff33b3f1, 0x9999f2ff, + 0x27089062, 0x0699198f, 0x00ff076b, 0xce263b92, 0xefffff8b, 0x02793233, 0x83f1200d, 0x06364ee2, 0xcdcc8e2c, 0xfdffff06, 0xffffcc4c, 0x0482cce9, + 0x5c83f820, 0x8299ea21, 0x66f425fe, 0xecffff66, 0x7905de72, 0x05258107, 0x00ffec91, 0x2da68209, 0xa4f00300, 0x190a00ff, 0x0200ff9a, 0x0982142e, + 0x08008027, 0xfdf1ffff, 0x0c785771, 0x22214146, 0x79ab069b, 0xcd27113d, 0x1100ff8b, 0x180833b3, 0x27169aa8, 0x00ff069b, 0x079a991f, 0x3d791e82, + 0xff3a08aa, 0xffff9919, 0x05cc4ce1, 0x00ffef0e, 0x6b9a1981, 0xfeffff15, 0xeb0666e6, 0x0674f707, 0x3395ffff, 0xbfffff33, 0xff0566e6, 0x3333ddff, + 0xd8ffff77, 0xffff3433, 0xff9a19f4, 0x9a4cd6ff, 0xe6de2705, 0x15f4f766, 0x318274fb, 0x0100ff28, 0xff069a19, 0x19822900, 0x2700ff24, 0x2982cccc, + 0xff52f82f, 0xcdcc2200, 0x1cebffff, 0x00ff082a, 0x300a836a, 0x0584ebbf, 0x158b8cfb, 0x331a00ff, 0x00ff8b33, 0x26648317, 0xff6666f3, 0x82990e00, + 0x99ec2558, 0xb4f7089a, 0x45224782, 0x1d82cc4c, 0x82b34121, 0x4ce92371, 0x4a72ffcc, 0x19c52205, 0x2547829a, 0xff646606, 0x6783f7ff, 0x83f4ff21, + 0x99f92291, 0x230f849c, 0xd3ffff08, 0x25827783, 0xbeffff22, 0xff203482, 0xff263983, 0x8b34b3ba, 0x5382fb08, 0x82f1ff21, 0x82ff2066, 0xffff2261, + 0x208a83e8, 0x290e83f3, 0x8bcdcce5, 0x2b068308, 0x4f6f7b07, 0x1800200c, 0x22097495, 0x829307bb, 0xe8e92d1a, 0xffff8bf6, 0xff0a17ee, 0x66e61100, + 0x16209a82, 0xf7228b82, 0x09850744, 0xe3211482, 0x221984d7, 0x691600ff, 0xf82405a2, 0xbb063d0a, 0xe5181e83, 0x9b2013dc, 0x55827082, 0x66740128, + 0xff153b66, 0xa282fcff, 0xfeffff24, 0x048466e6, 0x10826782, 0xffff0825, 0x82cccca8, 0xfdff2140, 0x2606b64a, 0x0300ff89, 0x4e8bcc4c, 0x778205c4, + 0x2f820f20, 0x04820020, 0x13220a82, 0x168234b3, 0x2f841820, 0x0c820020, 0xf0ffff25, 0x83ff9a19, 0xffff221c, 0x483383ec, 0xa1210cb2, 0x24628247, + 0xffb85ee3, 0x820482ff, 0xa1dc220a, 0x86521848, 0xb89e2407, 0x821c00ff, 0xe3ff2d04, 0x00ff4861, 0x8b486123, 0x06d4f708, 0x19850985, 0x71821e83, + 0x19821a82, 0x00219e82, 0x21488423, 0x1e826666, 0xff48a12c, 0x9a99dcff, 0xfb8b088b, 0xd15a15c4, 0xca6d1806, 0x94fb210f, 0x210e8f43, 0x4e827a54, + 0x86ab1122, 0x6e3cc082, 0xff079a19, 0x00808a00, 0xbabaffff, 0x00ff05e2, 0xffcdcc06, 0x84abfcff, 0x4c0700ff, 0xfe220982, 0x0982cc4c, 0x20059446, + 0x82068207, 0x8259200c, 0xb00122e6, 0x262a8220, 0x00ff52b8, 0x82e85b03, 0x878a2d46, 0x4500ffae, 0xff05c640, 0x66e691ff, 0x0682a383, 0xffff152a, + 0xff333367, 0x7a94b3ff, 0x21076d73, 0x6882c0fd, 0x21b0fa22, 0xfb28a982, 0x00ff8380, 0x08004002, 0x1c262582, 0x4c00ff29, 0x7e82866b, 0x8f820e20, + 0xe4749c84, 0x69942012, 0x40180c90, 0xff220a39, 0x7482f1ff, 0x00ff0e2c, 0xff6666f3, 0xba69bd01, 0x98829315, 0xff127328, 0x34330900, 0xcf82938b, + 0x08ee8c30, 0xffff74f7, 0x053cff9f, 0xf9ffff99, 0xc78270fd, 0x7ccecc22, 0xe6211982, 0x233d8264, 0x88083433, 0x32480682, 0xff682f05, 0x3233f6ff, + 0xe6efffff, 0xffffff66, 0xdb4e9a19, 0xb3f22205, 0x22178634, 0x82cc4cf5, 0xcecc262b, 0x24fc088b, 0x83e51806, 0x8234200e, 0x4c0d25bb, 0x079308cc, + 0xb5212282, 0x076962c2, 0x82e3e521, 0xcecc218a, 0xf1276e82, 0x0e00ffde, 0x830866e6, 0x82f9200a, 0xcccc210a, 0x22088982, 0xff9abcd4, 0x04f60d00, + 0x020600ff, 0x00ff0890, 0xff8f02e0, 0xc4006000, 0x0c00ff05, 0xffff9a99, 0x18469682, 0x181b3b59, 0x1816ac5a, 0x18095391, 0x6d12ac5a, 0xff250da4, + 0xfb9a197f, 0x306382b4, 0x06010028, 0xcb0754f7, 0x0754fb06, 0xe63000ff, 0x200d8866, 0x240985b3, 0xb33bffff, 0x201a8234, 0x21978300, 0x5d4eb3ff, + 0x00802108, 0x9929eb82, 0xfeffff98, 0xbb0834b3, 0x26b9826b, 0xff34b30b, 0x8233f8ff, 0x33052121, 0xf12c0982, 0xffff6866, 0xff66e6fb, 0x0080f2ff, + 0x0a87fe82, 0xf3ffff22, 0xf62e4a83, 0xffffcccc, 0x8b66e6f1, 0x3ffeff08, 0xf3189a19, 0xf325081a, 0x00ffd98e, 0x23408309, 0xfffce9fb, 0x22062075, + 0x84bae9fb, 0x00ff270a, 0xffe13a05, 0x77820e00, 0xbc0b002b, 0x0700ff29, 0xbb08cecc, 0x277c82ab, 0xffec9100, 0xcc4c0100, 0x97249482, 0xffffff0a, + 0xff239e82, 0x82a4b0ff, 0xce4c270e, 0xc400ff08, 0xe385cc4c, 0xffef0e2f, 0x98196f02, 0x193701ff, 0xfeff159a, 0x233183e5, 0x05323365, 0x4526a582, + 0x0400ff1e, 0x9582f6e8, 0x8bae0722, 0x20200f83, 0x1721bf82, 0x279f820a, 0xff7c14e6, 0xcecc9aff, 0xf6222582, 0xb9645463, 0xdf8f2307, 0xc582ffff, + 0xf5232a82, 0x85089a99, 0x00ff2406, 0x82217006, 0x00c02116, 0x9c21c482, 0x212a82ac, 0x7e825c8f, 0x1f053c27, 0x7deaffff, 0x31408270, 0xff291cf4, + 0x3333f0ff, 0xa1f7ffff, 0xedffff47, 0x6582d7a3, 0xffc3b52c, 0xc235ecff, 0xf4ffff08, 0x0f82ae87, 0x82682621, 0x82f3201e, 0x99f42223, 0x2258829a, + 0x83ccccf2, 0x0cf6215f, 0x04224a82, 0x1b8262d0, 0x82887621, 0x422026fb, 0x21faffff, 0x24358248, 0xfb852be7, 0x225c8229, 0x82b85efe, 0x8e42217c, + 0x85201c82, 0xf7227182, 0x86829a19, 0x8bd7e322, 0x3a233782, 0x83065238, 0x8b13210c, 0xe4271c83, 0xe10800ff, 0x83ffff06, 0x09002330, 0x438542c0, + 0x4382f720, 0x2107002d, 0x0500ff48, 0x00ffb8de, 0x825ccf04, 0x66662131, 0x09213182, 0x23e18319, 0x3e4a0a00, 0xd3217282, 0x263d8275, 0xffff70bd, + 0x823974f8, 0x2adc212a, 0x04275e82, 0x00ff8340, 0x688fc211, 0x102506a3, 0x00ff5d0f, 0x2004830c, 0x2ed6830d, 0x9a99be00, 0xc5bbffff, 0x00ff051e, + 0x82e2ba0d, 0x0a1726e1, 0xf80e00ff, 0x225a8252, 0x82e0ba0d, 0xf6e82c6a, 0x1a01ff08, 0x00ff34b3, 0x82343365, 0xa6092625, 0x0300ff64, 0x22c98282, + 0x82686606, 0x34332185, 0x0a202a82, 0x82052160, 0xffff2406, 0x849899f9, 0xffff2416, 0x820080f5, 0x0080302a, 0xf0feff08, 0xffff0200, 0x1500804e, + 0x83f6ffff, 0x4cfc2271, 0x211f82cc, 0xe8823233, 0x80821920, 0x9a19f523, 0x23e9828b, 0x8b7a14f5, 0x23059d66, 0xf4dd0100, 0xb0210982, 0x214082a4, + 0x1a8220b0, 0xcdcc6e30, 0xf13300ff, 0xffff05ec, 0xff3333f1, 0x8c8271ff, 0xd6252b82, 0x00ff32b3, 0x20428355, 0x235682de, 0x66e66a00, 0x00214782, + 0x294e8269, 0xe65600ff, 0x2100ff66, 0x9f826666, 0x1e452922, 0xf1274382, 0x00ff5238, 0x8266e68e, 0xe16d3543, 0xccffff48, 0x0e05b007, 0xf754f8ef, + 0x8b9615b0, 0xf7ffff94, 0xff293d82, 0x9a19f4ff, 0xc7078708, 0x28128e06, 0x8282808b, 0x89088b80, 0x82b28206, 0xfbff23f8, 0x47820080, 0x9819f738, + 0x66e8ffff, 0xf2ffff66, 0xff746666, 0xcecceeff, 0x33edffff, 0x6f440834, 0x80ff2206, 0x23098500, 0xcc4c0000, 0xff230985, 0x829a99fe, 0x8212201e, + 0xf4ff279d, 0xff0534b3, 0x24820900, 0x4cfaff29, 0xffff8ecc, 0x1834b3f3, 0x2009b447, 0x830a8208, 0x83f6206a, 0x2219821f, 0x83ffff88, 0x0500230a, + 0x1a8232b3, 0x7a82ed20, 0x4c0b0023, 0x208582ce, 0x22fb83fb, 0x8232b302, 0x213f822f, 0x84830200, 0x9a99fc23, 0x2025828e, 0x203b83f5, 0x210483f8, + 0xaa8299f4, 0x0080f923, 0x2125827f, 0x1a829899, 0x824cfc21, 0x66fe22ab, 0x20408268, 0x828c83f5, 0x24fd82d1, 0x00ff3433, 0x832a8304, 0x0a00230e, + 0x29829a19, 0x19850a87, 0xcc0b0022, 0x1982ca82, 0x80210e82, 0x20ca8200, 0x227e8303, 0x829a9901, 0x660625ca, 0x0200ff66, 0x00214d82, 0x24488406, + 0x00ff9a19, 0x820e8305, 0x20488293, 0x220a83f3, 0x8232330c, 0x83f82072, 0xcc07261a, 0x00ff8bce, 0x216e820c, 0x1a830700, 0x4f820f82, 0xff200582, + 0x19820f85, 0x0f831f82, 0x2f82ff20, 0x0e201a82, 0xff236a82, 0x820080f1, 0x8300206a, 0x4c002235, 0x220a82cc, 0x8268660c, 0x27708345, 0xff98190a, + 0x33330f00, 0xdd823f82, 0x99110023, 0x23758299, 0x0666e694, 0x1925d982, 0xffff8b9a, 0x206683f7, 0x280a8308, 0x66e60b00, 0xff968b08, 0x210d8200, + 0x0d83ff94, 0xbf088b25, 0x8e078f06, 0x31338212, 0x059a19ff, 0xffffb4fb, 0x15cdccba, 0xd5ffff9e, 0xbf823333, 0x9a19d926, 0x1300ff06, 0x2a2a4e83, + 0xfb05cdcc, 0x6900ff34, 0x32793333, 0x94f82117, 0x23222c82, 0xcd82cc4c, 0x34b31c24, 0x4d18ffff, 0xfb210926, 0x172c7994, 0x3382fc20, 0x7518ff20, + 0x002009b3, 0x09257518, 0x0794f72a, 0x94fbd4f7, 0x0694f715, 0xfb220a82, 0x44820694, 0x72ffff2e, 0x00ffcd4c, 0x159a19d0, 0xccfcffff, 0x07220a82, + 0x0b533233, 0x83042006, 0x43f82072, 0x06830563, 0xff231685, 0x85cc4cfb, 0xff25082a, 0x08ceccf8, 0x05c0ffff, 0x0524fb1f, 0x85fbffff, 0xf6ffff1e, + 0x00ffcccc, 0xff3e8a04, 0xce4cf3ff, 0x190a00ff, 0x2218829a, 0x82080080, 0x0b17210a, 0xff240a84, 0x7bd40b00, 0x22061242, 0x84008004, 0x291e8223, + 0xa066e608, 0x4900ff05, 0xf2829a99, 0x76200c82, 0x1e830c82, 0xe6f5ff23, 0x82328266, 0xfbff2399, 0x2d846866, 0x22074042, 0x8499190a, 0x2504820a, + 0x00ff9a99, 0xb882b30c, 0x5183fb20, 0x34330932, 0x24f74b08, 0x54f70e05, 0xff1514f8, 0x0080c500, 0x1a205482, 0xff231a82, 0x82707de5, 0x82ba24aa, + 0x82cb0790, 0xc0522312, 0xaf190700, 0xff2339ec, 0x1834330d, 0x200ee260, 0x07c071ab, 0x8214fb21, 0x07eb2660, 0x154b14fb, 0x2723836b, 0xff8b4861, + 0xb89ef1ff, 0x99210482, 0x220a829a, 0x4a6666ee, 0xee25063f, 0x00ff4861, 0x8404820e, 0x1100261e, 0x088bb89e, 0x229b82ab, 0x82b99e11, 0x8318839a, + 0x820a821d, 0x063e4a19, 0xee821120, 0xa1f1ff23, 0x25378247, 0xffff6666, 0x32825eee, 0x4b34f828, 0x06f4fb15, 0xd082b4fb, 0x5d82ff20, 0xf1201b86, + 0x00202a82, 0x934a2f82, 0x85098306, 0xc6f61819, 0x94f7210a, 0x24833382, 0x1e859c84, 0x8b264283, 0xfb54fb08, 0xad821584, 0x1820f721, 0x8311fbb3, + 0x19f721d6, 0xf820cb83, 0x0dc7b418, 0x4d83ab20, 0x13860820, 0x0700ff26, 0x00ff9a19, 0xd5850e82, 0x00e00822, 0x0720ca82, 0x5a854f86, 0x196b0821, + 0xca0713e5, 0x66e62167, 0x7b826783, 0x9e82ff20, 0x19216783, 0x2367829a, 0x14fb14f7, 0x2020d09c, 0xff239e82, 0x8200e0f8, 0x200a83b7, 0x20af8200, + 0x86d08508, 0x82188413, 0x22c782d0, 0x8506ab08, 0x83138508, 0x25d0f036, 0xf730fb0e, 0xe718f8e4, 0xfc221886, 0xd7180734, 0x2b221643, 0x1a82db06, + 0x801a0023, 0x053f6100, 0x66054b51, 0x5b180669, 0x3b221472, 0xef4d2b07, 0x7fa71817, 0x15002409, 0x82ff717d, 0x51702004, 0x082805e7, 0xfb06b4f7, + 0x15a4fba4, 0x08a7bc18, 0x44f62821, 0x00230546, 0x420ad708, 0xcc220612, 0x087d8bcd, 0x220a8209, 0x41cccc08, 0x96570673, 0x0eb81805, 0x826b200c, + 0x28f72283, 0x224f82f6, 0x570ad7f8, 0x6b240b98, 0xbb04f707, 0x0ce06f18, 0x83f8ff21, 0xf7ff2559, 0x6b083333, 0x2009895a, 0x5ec91833, 0x0dbd180c, + 0xa1342010, 0x5bdb2180, 0x6019ce89, 0x65582da0, 0x33f7240c, 0x84088b34, 0x7d0882ce, 0x675808d8, 0x076b2507, 0x44f744fb, 0x0f5bb918, 0x4741cc20, + 0x41cf8b05, 0xcc202d50, 0xcd236883, 0x830700ff, 0x33f722b8, 0x8c818333, 0x2c1d41cf, 0xff204d93, 0x150d3019, 0x20099e41, 0x20c38234, 0x6bca18f8, + 0x0b9e410d, 0x0c83c218, 0x82059e41, 0x19b084f5, 0x27251163, 0xf770fb0e, 0x1514f874, 0xdc276682, 0xffff66a6, 0x82cd4ce3, 0x9a592104, 0x4bfc021a, + 0xd4fb3b23, 0x1b0f6315, 0x827b5421, 0xaef1227d, 0xef411814, 0x00ff3b0b, 0x073433c0, 0x14ebffff, 0xdeffff7b, 0xff05cccc, 0x7b94f6ff, 0xecffff7c, + 0x19470040, 0xf1ff2a05, 0x00ff3d0a, 0x08666609, 0x200a82ff, 0x820a84a6, 0xe5812619, 0xcc1300ff, 0x200e82ce, 0x331e826a, 0x08cccc0f, 0xdd2700ff, + 0x3e00ffb2, 0xff050080, 0x15ee1800, 0x992d0f82, 0x2b00ff9a, 0xffa3e17a, 0xcdcc2e00, 0x8321828b, 0x22128206, 0x82730080, 0x67e62422, 0x83d8ffff, + 0x27002657, 0xffff66e6, 0x823884c1, 0xffff2468, 0x863433f0, 0x33ec227c, 0x21768232, 0x96829a19, 0x089a9922, 0xf6209782, 0xff205382, 0x00221583, + 0xa1828004, 0x9a200e82, 0xeb209882, 0x00232182, 0x82343321, 0xcc3f22be, 0x301364cc, 0x058b6b26, 0xe200ff0e, 0x01235082, 0x82662663, 0x4c0e26b9, + 0xd5ffffcd, 0x21958226, 0x048266f1, 0x7483d420, 0x33b3df25, 0x83f5ffff, 0xdfff23af, 0x0a8234b3, 0xff018029, 0x3333daff, 0x821a00ff, 0xf1ff2104, + 0x00231e82, 0x8266e62a, 0xb0f12c8d, 0x2a00ffa4, 0x00ff0ad7, 0x82299c0e, 0x0c5724ee, 0x822000ff, 0x0a002451, 0x83087a94, 0xffcc290a, 0xec910a00, + 0xcc2500ff, 0xe5226682, 0x28825ccf, 0x1c217084, 0x213d8228, 0x7182e681, 0x00409622, 0x12208682, 0xdf201f83, 0xfb207c83, 0xff299b82, 0xffcc4cda, + 0xc375e7ff, 0x2a25827d, 0xff707de7, 0x68e6f1ff, 0x84dcffff, 0x22348368, 0x82d723ed, 0x0080215d, 0xed211e82, 0x20738222, 0x2e2f8221, 0xb0920400, + 0xcc2400ff, 0x1800ffce, 0x82990681, 0x8218227e, 0x266f828f, 0x00ff9819, 0x41f62823, 0x0026055c, 0xffd7e312, 0x3984dfff, 0x8e82e020, 0x6635ff23, + 0x217e8266, 0x4f826334, 0x824c8d21, 0x195d223a, 0x822e829a, 0x29002463, 0x828bcd4c, 0x4c292544, 0x00ff8bcc, 0xff211683, 0x271b83dc, 0xff666634, + 0x32b372ff, 0x2106424b, 0x3583f6ff, 0xb9830120, 0x9a99f528, 0xf5ffff8b, 0x95829899, 0x6866fe23, 0x250c8207, 0xff3233e6, 0x3682ebff, 0x0e820485, + 0xff235282, 0x820080f4, 0x82f4201b, 0x01002133, 0xf4204d83, 0x25076b4b, 0xff05a133, 0xc183efff, 0xcccc0327, 0xe6f0ffff, 0x2a278266, 0xff33b3f0, + 0x3433fcff, 0x82753308, 0xe6f4251d, 0xfdffff67, 0xf4255683, 0xffff9999, 0x844482fe, 0x2273824f, 0x82e13ae6, 0x11eb252e, 0x1400ffeb, 0x00233983, + 0x82cecc19, 0x990122a5, 0x238a8298, 0x68660a00, 0x2006c45c, 0x2673820a, 0x299c0300, 0x820900ff, 0x068b31c6, 0x976001ff, 0x7600ff0a, 0xff150080, + 0x0080e7ff, 0xfb2a5682, 0x00ff0080, 0xff34b325, 0x8d831200, 0x66662022, 0x2106fc4c, 0x19832000, 0x82332321, 0x830e2019, 0x821820b5, 0xf1ff230e, + 0x1e8268e6, 0x7d200a82, 0x6c05104a, 0xed200590, 0xde22a483, 0x998234b3, 0x9a19ed25, 0x83dfffff, 0x83dc202a, 0x83f120d7, 0x2468820e, 0x190e00ff, + 0x231e8298, 0xe8ce4c90, 0xdf257a82, 0x00ff32b3, 0x20d0830a, 0x20ab83f1, 0x27a6832b, 0xffcc4c0e, 0x9ad92a00, 0x0a855f82, 0x82d8e321, 0x22938398, + 0x42a4301a, 0xff230560, 0x82146ef5, 0x4c20271e, 0xf5ffffce, 0x5482866b, 0xff989929, 0xf4a8d4ff, 0x82f1ffff, 0xd5ff23c1, 0x6382f628, 0x78830a85, + 0x9783da20, 0xcdcce522, 0x1e829182, 0x7f0a0028, 0xff0e08ff, 0x9d82ea00, 0x4aba0127, 0x00ff157e, 0x28d8830d, 0xffa8f804, 0x34330f00, 0x2f0f858b, + 0x5807fbff, 0xff54f708, 0xd46dbbff, 0x1800ff05, 0xf620a583, 0x11202783, 0xff290482, 0x8b48e1e7, 0xe6e4ffff, 0x23688266, 0x0734330d, 0xff220c85, + 0xe884eeff, 0xcc822184, 0x3082ff20, 0x83fb0821, 0x68662d43, 0xf2ffff05, 0xff869a19, 0xccccf0ff, 0x0b822d82, 0x3b829020, 0x52f83f27, 0x994400ff, + 0x281d8298, 0xffae87e6, 0x9a190900, 0x216c827a, 0x85829a19, 0x9a191b22, 0xf222e582, 0x5d82cccc, 0x0c820020, 0x18829c20, 0xffb81e25, 0x82781900, + 0x82288233, 0x07c0211c, 0x44223382, 0xa0822c92, 0xce821520, 0xbac3ff2e, 0xffff15a0, 0xff0a5752, 0xe2fac1ff, 0xad231582, 0x834df6a8, 0x34b32206, + 0x086282c9, 0xcc4c522a, 0x053e00ff, 0xffab051e, 0x48618ffe, 0xff34f715, 0x34333900, 0x0750f705, 0xffff34fb, 0x05ccccc6, 0x0e0750fb, 0xac00ffaf, + 0x012ac782, 0x150ad797, 0x2400ffeb, 0x42826666, 0x82cc0c21, 0xd904263b, 0x0e00ff58, 0xc6481833, 0x26fb2908, 0xffeb08a8, 0x9a99dbff, 0x15212182, + 0x224382b3, 0x8200c0f7, 0x22fb8321, 0x82f628eb, 0xbae822e7, 0x23e682e2, 0x07ebd18f, 0x23055e52, 0x9999ffff, 0xce210983, 0x200982ff, 0x2313859a, + 0x66660000, 0x6027cc82, 0xffff0200, 0x8434b3da, 0xff30234a, 0x7183f7ff, 0x68660e27, 0x19ebffff, 0x214a839a, 0x4a82cccc, 0xcecc8823, 0x200c8207, + 0x221c82e9, 0x83e6f2ff, 0x66e6211c, 0x99212182, 0x28308298, 0x2b089a19, 0xccd5ffff, 0x20eb82ce, 0x208d83f1, 0x221683f9, 0x829899ef, 0x230f8330, + 0x68660600, 0x8e214282, 0x20a38280, 0x21ec8231, 0x0a83ffff, 0x33ceff22, 0xff257382, 0xff33b3f1, 0x203086ff, 0x2130849a, 0x3086ff33, 0xc2f59f27, + 0x332a00ff, 0x25568232, 0xff85abeb, 0x72830800, 0xb8def225, 0x831400ff, 0x16002399, 0xbf823433, 0x32337722, 0x00289982, 0xff343317, 0xd7630e00, + 0x26821c82, 0xc2150023, 0x84308290, 0xf35f2120, 0x25221982, 0xe082cc4c, 0xcc4c0122, 0x29080041, 0x0000ffcd, 0x00ff6666, 0x09844c01, 0x4a826720, + 0x152e7022, 0x45214a84, 0x834a821e, 0xd714251b, 0x1500ff0a, 0x002bd282, 0x08004008, 0x00ff078b, 0x8232b376, 0x1e8523f1, 0x7a73ff15, 0xb0002505, + 0xfdffffa4, 0xff238e83, 0x829a19ff, 0x5c4f215c, 0xb127ea82, 0xffff9999, 0x823e4ae2, 0x82502072, 0xe0ff235e, 0x0a829ad9, 0x20825220, 0x261f0023, + 0x27cf8266, 0xff9899b1, 0xc2b51d00, 0x65201582, 0xff2eb882, 0x153e0a5e, 0x995900ff, 0xffff079a, 0x478299ad, 0x8366e021, 0xcca62226, 0x207382cd, + 0x228a8352, 0x8233331f, 0xcc122737, 0xd7ffffcd, 0x7e8434b3, 0xc1823320, 0x8933b321, 0x2273827e, 0x83cd4cff, 0x299c217e, 0xf1847e82, 0x82305121, + 0xe6e0219f, 0x00224c82, 0x30823351, 0x82191f21, 0xb1ff2189, 0x00236282, 0x8234b31d, 0x2251847e, 0x829a9933, 0x2267847e, 0x82323324, 0xe65f2215, + 0x20898966, 0x22788268, 0x8200809b, 0x33a92789, 0xae00ff32, 0x2c8232b3, 0xb6835120, 0x34225887, 0x588700ff, 0x5883d783, 0x8b061e41, 0x86d6829f, + 0x21fd829f, 0x9f84e2ff, 0x4683b920, 0xd0837a20, 0xb35a0023, 0x20739332, 0x22ab834d, 0x82981922, 0xe6022295, 0x05c44264, 0xe6010035, 0x0200ff68, + 0xff8bcccc, 0x34330300, 0x0e078b08, 0x83b400ff, 0xe6cc22df, 0x259c8266, 0xffcdcc04, 0x5a83ebff, 0x1482e920, 0xb3efff31, 0xedffff32, 0x00ff67e6, + 0x0868660b, 0x82e7ffff, 0x0f002195, 0xff28e883, 0xff9919cd, 0xec91aeff, 0x2308e282, 0xff85abf2, 0x14aeeaff, 0x550f00ff, 0xe4ffff81, 0x00ff0a57, + 0x8b612519, 0x2000ff08, 0xff061f05, 0xd7a31100, 0x0e206f82, 0xff2a1782, 0x8b14aef1, 0x5ceeffff, 0x0685082a, 0xf1ffff24, 0x0482f6a8, 0x830a9721, + 0x82292015, 0xe0ff2733, 0xff067a14, 0x3383b4ff, 0x0fd2ff36, 0x5200ff5c, 0x00ff0ad7, 0xff7bd427, 0xc4f53f00, 0x3200ff08, 0x51220a83, 0x7a82836b, + 0xd7a3e722, 0x4c217582, 0x210a82cd, 0x0a82e3ed, 0x66660b2a, 0x9e0400ff, 0x1b00ffb8, 0x1422fd83, 0x0e82ecd1, 0x82cccc21, 0x6e5b2134, 0x1526de82, + 0xff056826, 0x6c820800, 0xd9010023, 0x82098298, 0xfaff30cf, 0xff8dcecc, 0xcc4cf7ff, 0xffffa008, 0x820080a4, 0x83662021, 0x23a422f2, 0x273282d8, + 0xff004029, 0x28dcbdff, 0xe7216182, 0x220a82c0, 0x8286ebf0, 0x82ed200a, 0xf4ff2392, 0x5d82a4b0, 0xff2d4c82, 0xffb75ee4, 0x16d91400, 0x2bfbffff, + 0x826c8385, 0xeaff2386, 0x4a829ad9, 0x3c9f0827, 0x01feffff, 0x2b6c8248, 0x00ffa69b, 0xffca6105, 0xe0fa0100, 0x9f210e82, 0x2429827d, 0xff3e0a15, + 0x829b8200, 0xc9042229, 0x084482fc, 0xff5ccf20, 0xd042e9ff, 0x3d1000ff, 0xedffff70, 0xffff48e1, 0x08c2b5f4, 0xa3e7ffff, 0xf0ffffd6, 0x7d82cecc, + 0x52cdd63a, 0xf54100ff, 0xffff05c2, 0xff866bda, 0xd8233c00, 0x61a8ffff, 0x0000ff47, 0xff214e82, 0x227d83da, 0x82b6e1c3, 0x99f82234, 0x213f829a, + 0x2982a62d, 0xeb83f620, 0x6626f122, 0x1483b282, 0x842bec2c, 0xcc0e00ff, 0xf6ffffcd, 0x888216ae, 0x85eb0e22, 0xa4260a82, 0x1300ff18, 0x23829ad9, + 0xff167926, 0x0a570900, 0xed2c2382, 0x00ff0810, 0xff277107, 0xd6e30b00, 0x0c22a782, 0xa7827dbf, 0xffd66335, 0xcc4c1d00, 0x40ffffff, 0x0c00ff00, + 0xffff3433, 0x82ba5eec, 0x33d63229, 0x21ffff32, 0xff15f6a8, 0x9002efff, 0x421b00ff, 0x207d8390, 0x22dc82a9, 0x82e2fa0e, 0xa8462125, 0x94265e82, + 0xf1ffff7a, 0x72821e05, 0x8266a621, 0x0ff121a7, 0xf625f682, 0xffff98ae, 0x23d082fb, 0x022becff, 0xff237d85, 0x82ec11f1, 0xfd102753, 0xe4ffff70, + 0x7d829ad9, 0x82590d21, 0xaeea27d1, 0xf0ffff14, 0x14827eaa, 0xffec5127, 0x12d8e6ff, 0x3444828b, 0x069002a0, 0x050000ff, 0x1c00fffe, 0x8b0570bd, + 0x611500ff, 0x831d8248, 0xb50a22f3, 0x203182c2, 0x220e82e1, 0x8248e1f0, 0x97bd272b, 0xbdffff0a, 0x9a82ec91, 0x2bc7f932, 0xc6f9ffff, 0xffff8bea, + 0xff20d0f5, 0xf5390600, 0xc7210f82, 0x207782ae, 0x228c8342, 0x82f6a8bd, 0x1e0f2277, 0x2b4082b8, 0x00ff66e6, 0xff7cd419, 0xcab60a00, 0x5d215f83, + 0x214b82b2, 0xad82faff, 0x14ae1c22, 0x5f222582, 0x82822adc, 0x44654b2b, 0xfdffffff, 0x00ffb96e, 0x3f318252, 0x9819d8ff, 0xe63f00ff, 0xff0e0868, + 0x299c2700, 0x33fb00ff, 0x00ff1533, 0xffa43023, 0x8f826400, 0x0d2c3782, 0x00ff5278, 0xff908226, 0x7b542400, 0xc7246282, 0x2800ffae, 0x2205a74b, + 0x823433b5, 0xcc282252, 0x226f82cc, 0x82ce4c24, 0x823820cf, 0x800d272b, 0xd9ffff00, 0xa482707d, 0x32332327, 0x7d9bffff, 0x31468271, 0xff343317, + 0x6766f6ff, 0x661000ff, 0xe9ffff66, 0xd4829919, 0xcd4ce525, 0x4b54fb08, 0x23820a88, 0x096c5218, 0x18066b21, 0x2516bd98, 0xd4fb07bb, 0x36895b06, + 0x0d645718, 0x7d793684, 0x0a016008, 0x6983f720, 0xb31a0023, 0x20838233, 0x21ea825c, 0x8d82e616, 0x0040173a, 0x990900ff, 0x078b0899, 0x7d4500ff, + 0x0400ff71, 0xff15cdcc, 0xcccc2501, 0xe5287e82, 0x00ff66e6, 0x059a994a, 0x3705684c, 0xcccc0c00, 0xe6f3ffff, 0x0800ff68, 0xffff9a99, 0x8b6666f2, + 0x4affff08, 0xf2222b84, 0xd2826766, 0x3182f320, 0x83f7ff21, 0x80fb22e2, 0x212b8200, 0x20823433, 0xff234683, 0x826666b5, 0xe6f22346, 0x277a4b66, + 0xffff2206, 0x68b986f1, 0x00230d86, 0x497b540e, 0x0023057f, 0x8285ab11, 0x11002160, 0x082b9918, 0x1811d060, 0x6208bc4d, 0xf7210607, 0x195f82d4, + 0x940a60b9, 0x5e621831, 0x0b65410c, 0x0f04ad18, 0x7618cc20, 0xaf24115d, 0x54f8f4f7, 0x820c135c, 0x5d8620c7, 0xdd4f05ff, 0xff210805, 0xff059ad9, + 0x9a992600, 0xd7fdffff, 0x2100ff0a, 0xffff32b3, 0xffecd1e6, 0x68e60c00, 0x30dbffff, 0x081b42a4, 0x82ff7f21, 0x33172129, 0x1b421f82, 0x221f8206, + 0x829a19e9, 0x4ce5224d, 0x431b42cc, 0x420d0170, 0x3420201b, 0x22081b42, 0x4200ff66, 0x1043081b, 0x01802107, 0x0c21ad82, 0x221a82e6, 0x835ccf24, + 0xff3325d7, 0x142e1900, 0x002deb85, 0x08f62802, 0x0000ff8b, 0xab056626, 0x22088207, 0x4d86ab11, 0x003805b2, 0xff7a540e, 0x33b31100, 0x14f7088b, + 0xffff058b, 0xfb666665, 0xffff1514, 0x211c3242, 0x3242ff67, 0x328a4205, 0x9a99ba25, 0x181574fb, 0x1812ff4a, 0x190dc44c, 0x180c7286, 0x180dd046, + 0x180faa54, 0x2110f450, 0xbf82cbd4, 0xcc4cee22, 0x1a9f4d18, 0x42cc4c21, 0x306607c5, 0xc4db1805, 0x21934209, 0xff2f0e2b, 0xcccc9d01, 0xe60000ff, + 0x28688266, 0xff343362, 0x9a19ffff, 0x226e8205, 0x839002e0, 0x4aee2206, 0x205e823c, 0x064c5ecc, 0xc764ff20, 0x43ee2006, 0x912d05f8, 0x0e00ffeb, + 0xff8bec51, 0x84ab1100, 0x28068208, 0x0570fd1f, 0x1961ffff, 0x2151829a, 0x0a828802, 0x0080e322, 0xf03c4b82, 0x00ff5ccf, 0xff707d22, 0x00001300, + 0xe81500ff, 0x00ff08f6, 0xffe2fa44, 0x0a974f00, 0xf0282582, 0xff067ad4, 0x0a97e6ff, 0xf2252b82, 0x00ff8f42, 0x2193831d, 0x20827a10, 0x7c541322, + 0x3c272b82, 0x00fff668, 0x829ad946, 0x3ff5222b, 0x222b82ff, 0x8252b8ea, 0x83f4202b, 0x80162116, 0x0d225282, 0x8a820a97, 0x085ccf37, 0xcc8600ff, + 0x9200ffce, 0xff050080, 0x66660a00, 0x4c0b00ff, 0x209f82cc, 0x83a583d1, 0xf4ff230f, 0x25830cb4, 0xff66e624, 0x25846dff, 0xb89e0d22, 0x3029e282, + 0xf4ffffa4, 0xffff8a61, 0x354f82e9, 0x10b8eaff, 0xffff088b, 0x06e23af5, 0x593c00ff, 0xb9ffff9a, 0x5182d623, 0xc275102b, 0xa8ecffff, 0xf2fffff6, + 0x222b8241, 0x825238e2, 0xa09a21b7, 0xf0222b83, 0x2b82cccc, 0xff23d583, 0x82f668b0, 0x0c13222b, 0x244d82cc, 0xffff26e8, 0x228782f0, 0x8299deff, + 0xb3e22d45, 0x0e088b32, 0xf854f82f, 0x075b1504, 0xd320c282, 0xff27e982, 0xff34b39b, 0x8233dcff, 0x4c842204, 0x0af46fcc, 0xff33b32e, 0xcccc2300, + 0x2c00ff8b, 0xbb083433, 0x00242f82, 0xff142e2c, 0x2705ce70, 0xffecd123, 0x33b37b00, 0x06822f82, 0x24823420, 0xe9826420, 0x0ac99c18, 0xc9ffff22, + 0x79235283, 0x5a15cd4c, 0x07230650, 0x5c9f6666, 0x00210516, 0x23ff820e, 0x33b30b00, 0x9a22e482, 0x89ae9a19, 0x6500ff2f, 0xff0766e6, 0x15ee0e00, + 0x4cf4ffff, 0x225e82cd, 0x5cff0a17, 0x14280544, 0xffff7bd4, 0x089a99f8, 0xcf26b482, 0x00ff7b5d, 0x1a83d73b, 0x4022ca83, 0xac830080, 0x16820683, + 0x0021f882, 0x303b8309, 0x9b68e62c, 0xff078b08, 0x66a6adfe, 0xff5fffff, 0x20ae82ff, 0x223a8b2c, 0x9300ff34, 0x82cc203a, 0x883a8361, 0x8e6820dc, + 0x823220dc, 0xb2aa20dc, 0x8b5520dc, 0x92ce20dc, 0x08982fdc, 0xe330fb0e, 0x831524f7, 0x9307bb06, 0xca18ff06, 0xca180a9b, 0x8b260a37, 0xb3f2ffff, + 0x1182ff34, 0x0c8b0619, 0x15bbf322, 0x70183283, 0xff220924, 0x8d1accf8, 0x138210ba, 0x18823482, 0xf7ffff2d, 0x088b3333, 0x07eb0683, 0x7694f7ab, + 0x2a440a93, 0x1f551810, 0x188b2038, 0x22198d55, 0x5674fb34, 0x7e560f60, 0x14fb2107, 0x17e36819, 0x0800ff24, 0x54820ad7, 0xf6280723, 0x0c9055ff, + 0x1e22f683, 0x1a8267e6, 0x9a191923, 0xdd7918ff, 0x18ff2011, 0x2909639b, 0x8b9919e1, 0xeb067308, 0x495724fb, 0x0c79560a, 0x7706a321, 0x5a660bba, + 0x58cb200a, 0x732017b5, 0x0c6a5518, 0x820afb57, 0x14f723ca, 0xe98324f7, 0x8b136857, 0x0dcd57e9, 0x5418e982, 0xe98a08a8, 0x5607bb21, 0x3b581895, + 0x084a7005, 0xffff3422, 0x2006e457, 0x203391ab, 0x212c8433, 0x068508cd, 0x33203388, 0x5b3a3386, 0x74f76b06, 0xfb14f715, 0x14fb0514, 0x0714f706, + 0xf730fb0e, 0x15d4f774, 0x1182f78b, 0x6cc95618, 0x3900ff32, 0x04fb0080, 0x1700ff15, 0xff06b85e, 0x8eb70700, 0x0522b482, 0xb48286b6, 0xffecd126, + 0x9042feff, 0x7a2d0982, 0xffff08e1, 0xff3e8ad5, 0xffff47ff, 0x21158205, 0x4b74cccc, 0x19fb2506, 0xfcffff9a, 0xfa230483, 0x828b0080, 0xbde22325, + 0x1b820671, 0x8bf2922c, 0x3efbffff, 0x0300fff9, 0x308218a4, 0xff0b9731, 0xf43d0500, 0xe2ffff08, 0x00ff9959, 0x825a046e, 0x63e22746, 0x92ffffd7, + 0x0a8266e6, 0xc3b5fd27, 0xccf9ffff, 0x204c83ce, 0x21048299, 0x60846666, 0xb3225184, 0x0c820633, 0x8b796922, 0x25215182, 0x215182e3, 0x5182e8db, + 0x8200c021, 0x2c722151, 0x3d229884, 0x43824cf7, 0x5c4ffe22, 0x7e21c082, 0x821782b9, 0x0700234d, 0x0e823333, 0x82c3b521, 0x20dc8243, 0x22dc82b9, + 0x82879605, 0xda0422dc, 0x2660821d, 0x00ff1924, 0x82004001, 0xd98e2258, 0x31fd8208, 0xfffff6a8, 0x050e4d99, 0xcc1b00ff, 0x6700ffcd, 0x0a829a19, + 0x86820120, 0x4c050027, 0x0400ffcc, 0x201482cc, 0x06757503, 0x1d225183, 0x5183299c, 0x830e6d21, 0x06c12151, 0x5b215182, 0x205182e7, 0x22468268, + 0x820dc2fa, 0x23468351, 0x0ce298ff, 0x17214682, 0x228982b3, 0x8233b366, 0x3301220a, 0x229e8234, 0x828f6766, 0x66e624c6, 0x4b0600ff, 0xe6240520, + 0x84f70080, 0x0bd75818, 0x2b7b1142, 0xff9a1930, 0x9a9977ff, 0xcfffff15, 0xff23a382, 0x826666b0, 0xfd3027b9, 0xb0ffff70, 0x0a82d863, 0x2a9c062f, + 0x4ff5ffff, 0xf8ffff5c, 0xffffcc4c, 0x200483f2, 0x05fe41f3, 0xec91e529, 0xfaffff06, 0x828b6871, 0xd5d83c05, 0xe20200ff, 0xfdffff0c, 0x00ff7b14, + 0x08e8bb04, 0xa8e4ffff, 0x2c00fff6, 0x82050c62, 0xa4b0260a, 0x9ed3ffff, 0x270a82b8, 0xff291cfd, 0xae47fbff, 0xcc213482, 0x422f82cd, 0xe5280a50, + 0xff06ff7f, 0xe17af3ff, 0xf8225182, 0x94647a54, 0x06003505, 0x00ff5d8f, 0x08f6a80a, 0x073100ff, 0x4f00ffae, 0x5a05289c, 0x99210682, 0x224d829a, + 0x826666f9, 0x33b3241c, 0x830700ff, 0x830d2004, 0x840c2004, 0x1a002a9f, 0xff06156e, 0x988e0500, 0x2105828b, 0x6a822b27, 0x82f41d21, 0x85eb21a4, + 0x45217e82, 0x224d821e, 0x820a571b, 0xee9c2194, 0x1b20e682, 0x0023e182, 0x82d7632c, 0xe302220a, 0x21c082d7, 0x3482c3b5, 0x71183320, 0x052007dd, + 0x14205187, 0x0c225182, 0x5182ec91, 0x34b3073c, 0x4cf2ffff, 0xf8ffffcd, 0xffff0080, 0x08cd4cf5, 0xe6efffff, 0x0801ff66, 0xde416666, 0x1894200f, + 0x2783c95a, 0x993700ff, 0x4bffff9a, 0x83054152, 0x83d2200a, 0x4cdc2504, 0xd9ffffcc, 0xd320c383, 0x5f22e583, 0x32466306, 0x0fde4607, 0xff067b25, + 0x1829f7ff, 0x21076ddf, 0x0a830700, 0xd6080024, 0x0c6c0804, 0x20098205, 0x861483ff, 0x380e8204, 0x00ff088b, 0x06908247, 0xca2700ff, 0x00ff8b3d, + 0xffcd4c24, 0x0080e3ff, 0x06c55a8f, 0x6688ff2a, 0xdcffff66, 0xb7159a19, 0x0f222382, 0x2382a470, 0x5c8f0c24, 0x048200ff, 0x10820a82, 0x06850820, + 0xf3ffff22, 0x16832982, 0xf0ffff29, 0x088b9a99, 0x4553065f, 0xfb267a49, 0xff152b14, 0x46181100, 0xff20089c, 0x137d3619, 0x82ff3321, 0x18842016, + 0x4b122153, 0x002311f0, 0x4e7b540e, 0x5484055b, 0x00ff082c, 0xff9a19de, 0x008028ff, 0xa359ff15, 0xb3fa2305, 0xd179ff34, 0xccfc2205, 0x260982cc, + 0x088b9a19, 0x830674fb, 0x8b992109, 0x94200582, 0x03223f82, 0x2d827c3f, 0xffc23527, 0xf8330500, 0x210a8208, 0x0a838d37, 0x00ff7434, 0xffd34d00, + 0xaa510600, 0x460300ff, 0x0400ff1e, 0x628268e6, 0x7b543529, 0x00ff05db, 0x82c91502, 0xd26d2211, 0x820a8290, 0x06002164, 0x2305d678, 0x8b333306, + 0x26211782, 0x20478267, 0x27428253, 0xffc2f502, 0x8c8cfbff, 0x0d273882, 0xffffd763, 0x82cceceb, 0x592d273c, 0x4400ff9a, 0x0a82ae07, 0x33f30222, + 0x78212f82, 0x23478752, 0x8b666605, 0x06832c82, 0xf3201782, 0xfd20be82, 0x5524478e, 0x14fb7b54, 0x03223982, 0x5a829042, 0x82002021, 0x824c20a7, + 0x82f920db, 0x82f48285, 0xccfa2230, 0x27c682cc, 0xff66e6c1, 0x0080b701, 0x2d945343, 0x15eb14fb, 0x076b06cb, 0x07ab064b, 0x0a934b8b, 0x2000ff26, + 0xffffcd4c, 0x0805ba4d, 0xa470d725, 0xe1ffff8b, 0x00ffcccc, 0xff347324, 0x15ee0700, 0xff2600ff, 0x00ff08fe, 0xffae871e, 0x68a67300, 0x8206cb05, + 0xa4f0270c, 0x198bffff, 0x2282059a, 0xff8fc226, 0x3233d9ff, 0xcd283683, 0x99dcffff, 0xd7ffff9a, 0x29057252, 0xff33b30f, 0x9a194f00, 0x33496b15, + 0x07a94a0f, 0x2408ae61, 0xfffffc29, 0x227683f8, 0x6104d608, 0xf8481aae, 0x0c5b6009, 0x2379a146, 0x15a8fb5b, 0xf52cc482, 0xffff0040, 0xffb81ef3, + 0x1ec5faff, 0x6133c982, 0x0700ff48, 0xff08fa7e, 0x0080dcff, 0x7b2400ff, 0x185f05e8, 0x7c0c3fbb, 0xc3210ade, 0x25d58207, 0xff9a9906, 0x36830500, + 0x6666052e, 0x9e0600ff, 0xb7088bb9, 0x2300ff06, 0x80223e84, 0x4f820500, 0x07202283, 0x0c210483, 0x069148e6, 0xf5ffff34, 0xfb08cc4c, 0xffbb071c, + 0x34331000, 0xfbffff15, 0x8e82e79b, 0x19a4fb32, 0xd50100ff, 0xfcffffc2, 0x00ff0ad7, 0x08328803, 0x18219982, 0x20588210, 0x27048298, 0xff098c00, + 0x94180a00, 0x93210e82, 0x227682f7, 0x820866e6, 0x82e4200a, 0x24062133, 0x03278682, 0x00ffcdcc, 0x82008008, 0x33092396, 0x06850834, 0x33214a82, + 0x261682f8, 0xffff707d, 0x82641bf9, 0xa430212f, 0xf9215482, 0x263a826c, 0xfff0e705, 0x8273ffff, 0x830a201e, 0x230e8363, 0x0a970600, 0xec201983, + 0x06200482, 0x0a277383, 0x00ffc520, 0x82008000, 0x3d8a2138, 0x20218c82, 0x27198200, 0xffdd840d, 0x9ecff3ff, 0x7382dc82, 0xb3eeff23, 0x20bc8234, + 0x05b56ced, 0xff2e0682, 0xe73bf8ff, 0xabeeffff, 0xf2ffff86, 0x2a82bd74, 0x5482d720, 0xe8fcff28, 0xfdfffff6, 0x5d773e4a, 0xfeff2305, 0x09849a99, + 0xeb088b28, 0xcc3300ff, 0x438215cc, 0xa430d625, 0x82ebffff, 0xd8ff276d, 0xffff34b3, 0x3182a8dd, 0x8e02e822, 0xfd27b082, 0xffff1038, 0x82e00ffe, + 0x02cb2132, 0x1021b582, 0x22098220, 0x828bd0d7, 0xf3fa221a, 0x273a82f8, 0xff5a04fb, 0x00600200, 0xe3261682, 0x0400ffd7, 0x1a851078, 0x4020a382, + 0x0127bd82, 0x00ff18c4, 0x8652f809, 0x0f05220e, 0x38c7825c, 0xff89c119, 0x76f31100, 0x660f00ff, 0x1d00ff66, 0xff8b0080, 0x66661f00, 0x24068508, + 0x9ef0ffff, 0x201682b8, 0x22948270, 0x82713de6, 0xc2f5212a, 0xf8215482, 0x224f82c0, 0x82df0f05, 0x1739218f, 0xf7255482, 0x0500ffcf, 0x224e820c, + 0x82004007, 0x210a8505, 0x1982f047, 0xff68f126, 0xefc70100, 0x47267382, 0xfaffffae, 0x1e8231e8, 0x82592221, 0x0de825f6, 0x1400ff10, 0x3220e785, + 0xd626bc82, 0x4b083433, 0x8a44e4f7, 0xfb8b2294, 0x0a787294, 0x72ff8521, 0xee25057d, 0x088b7b54, 0x1777722b, 0x9a53eb20, 0x7b542209, 0x069a53ff, + 0x8b85ab25, 0x4606eb08, 0xd3540edf, 0x072b2d07, 0x6300ffeb, 0xff159a19, 0x32b399ff, 0xff273e82, 0xff146ef3, 0x822ef2ff, 0x57f82504, 0xf5ffff0a, + 0x00360482, 0x08f6a806, 0x7ad8ffff, 0x1800ffe2, 0xdb0520c5, 0x2700ff07, 0x0c821e85, 0x0534b33d, 0xae0a00ff, 0x0600ff16, 0x00ff32b3, 0xffcccc0d, + 0xce4cf8ff, 0xf3ffff8b, 0x44086666, 0xff2f7967, 0x9a19baff, 0x331effff, 0x00ff1534, 0x82dfcf07, 0x20302195, 0x4f219583, 0x200a83e0, 0x20048321, + 0x2fd282a4, 0xff9919fc, 0x8e02fcff, 0xe6faffff, 0xfeffff67, 0xfa233483, 0x828b66e6, 0x8206831a, 0xb9de2616, 0xf00100ff, 0x2a258220, 0x00ff0a17, + 0x08f0e703, 0x8505bb5b, 0x26588243, 0x00ff8be0, 0x8520b00c, 0x220f8263, 0x82bb085c, 0x8571841d, 0xa80c2204, 0x22228273, 0x845ccf07, 0x83082032, + 0x820a8428, 0x00002532, 0xf3ffff83, 0xde2d908e, 0xfffff628, 0x05f027de, 0xcc2100ff, 0x250a82cd, 0xf7053433, 0xc584bb2c, 0xc58aba84, 0xf8259482, + 0x5b08a430, 0xb38f825b, 0x82c59ac8, 0x0bd7217d, 0xd8210482, 0x225b8294, 0x82d723de, 0x0ad7210a, 0x0141f69b, 0x00ff2109, 0xff21f382, 0x23dd8300, + 0x5dcf0700, 0xf7826484, 0x82fa2f21, 0x0cd022be, 0x274482ce, 0xff66e6cd, 0xcccc3101, 0x280c7643, 0x99d601ff, 0x1600ff9a, 0x0b951899, 0xcccc210f, + 0x0dc04b18, 0x86008021, 0x18eb200f, 0x220fb6b5, 0x8234b3f2, 0x6666217c, 0xd5206282, 0xde252583, 0xffffce4c, 0x215582c9, 0x7182ebff, 0x41c3ff21, + 0xc52305d7, 0x838b33b3, 0xff992a16, 0x9a191400, 0x9ed4ffff, 0x22dd82b8, 0x820832b3, 0x299c2156, 0x99210482, 0x2140189a, 0x206b8209, 0x214018eb, + 0x0080210a, 0x40182583, 0x0c271921, 0x00ffd763, 0x82cc4c0d, 0x4fde2540, 0x2a00ff5c, 0xeb2b8683, 0x00ff14ee, 0x8b666636, 0x713c00ff, 0x3a2205df, + 0x7c82cd4c, 0x83ec1121, 0x82672016, 0xa4b0267c, 0x612b00ff, 0x23818648, 0xd6630c00, 0xb57f4082, 0x9042210b, 0x4018d882, 0x0c200988, 0x00225682, + 0xb8187d0c, 0x81831376, 0x9cf3ff24, 0x51840528, 0x36215b86, 0x20658266, 0x826f8314, 0x088b2179, 0x8d828784, 0xff219382, 0x849d84ff, 0x82b182a7, + 0x82bd821a, 0xd863216b, 0x08c74218, 0xcb616684, 0x23768205, 0x9082f3ff, 0x41182582, 0xbd210bfc, 0x0da04170, 0x829a9921, 0x2a9c210f, 0x21224082, + 0x5f4132b3, 0x19142106, 0xc9291482, 0xff8b9999, 0x33b3c5ff, 0x22068208, 0x8266e6c3, 0x2004837c, 0x273083c9, 0xffce4cde, 0x0080d5ff, 0x66205b83, + 0xf2261982, 0xff0534b3, 0x40825eff, 0xe6460027, 0xffff1566, 0x204183f0, 0x201a83f7, 0x203483ed, 0x220e83fb, 0x82cecceb, 0xedff21cd, 0xed215784, + 0x20e482e6, 0x2e1b8304, 0xff9919f0, 0x9a990800, 0xc6ffff08, 0x82519a19, 0x4c1f2588, 0xe9ffffcd, 0x00216782, 0x825c8426, 0x28002325, 0x3c829a99, + 0x662a0025, 0x84ff8b66, 0x0d002116, 0x00215382, 0x2388821f, 0x66661600, 0x98213c84, 0x283c82c5, 0xff34b38a, 0x66666300, 0x82278215, 0xffff2234, + 0x843e83f2, 0x82528448, 0x51082131, 0x99206a83, 0x76822c82, 0x8082ab83, 0x94828a84, 0xffff8b23, 0x20f285ec, 0x204882ec, 0x84b884ff, 0x82cc84c2, + 0xc50821d6, 0x98203c83, 0x76823c82, 0x8085ff20, 0x26208a84, 0x29349a84, 0xff080080, 0x66e60000, 0x3fffff07, 0x54f79a19, 0xd7ffff15, 0xff211983, + 0x28d082d9, 0xc2f5f1ff, 0xb3e0ffff, 0x21df8233, 0x2882d8a3, 0x66e63922, 0x0f24f183, 0x00ff67e6, 0x00228c83, 0x8c821912, 0xcccc0527, 0x661200ff, + 0x22f18367, 0x82323314, 0x821220c9, 0xfaff22ec, 0x20da8233, 0x06d55b0f, 0x68203c84, 0x4e82f182, 0x00ff3226, 0xff285c16, 0x00236284, 0x7b3e0a0e, + 0xff2e0727, 0x069a19ff, 0x669effff, 0x09ffff66, 0x8a82cecc, 0x0020c583, 0x4c844284, 0x5c825682, 0x08206282, 0x70820682, 0x8500ff21, 0x0692417a, + 0x2a82ff20, 0x51086728, 0xe63900ff, 0xb2830567, 0xbc83d720, 0x85ff3221, 0x20d082c6, 0x82dc848b, 0xd5ff213c, 0x7a85dd82, 0x8e831682, 0x2a842920, + 0x83c50821, 0x0568243c, 0x836100ff, 0x33662220, 0x22848232, 0x826666e6, 0x82e92038, 0x82ff2010, 0x820a8204, 0x20438310, 0x211182e4, 0xac831600, + 0x0482eb20, 0x41190021, 0x1b2005f2, 0x00262d83, 0xff008015, 0x11821400, 0x7419ff20, 0x3c8216de, 0x088b2708, 0xde00ff0e, 0x01ff33b3, 0x159ad99f, + 0xefffff90, 0xffffea11, 0xff6766f6, 0x162eeeff, 0xfaffff7a, 0xff08c2f5, 0x2182b0ff, 0x63e8ff2f, 0xc6ffffd8, 0xffff3333, 0x8b3273b6, 0x227e8335, + 0x749a1995, 0xaa2306cf, 0x74ff66e6, 0xf52205cf, 0x1384e18b, 0x0f848b20, 0x0d820820, 0x34253482, 0x8c4900ff, 0x2c4883ce, 0x1700ff32, 0x7a08289c, + 0x0a0500ff, 0x826a833e, 0xd1112937, 0x00ff90ea, 0x0816ee10, 0x52831582, 0xa4f0102c, 0xcc1100ff, 0x0900ffce, 0x1982e2a5, 0xff235c82, 0x8246f6fa, + 0xcc692a1e, 0xe0ffffcc, 0x00ffae87, 0x2628824d, 0x52f89eff, 0x8308fb8b, 0xb3712b8a, 0x8dffff34, 0xffff6666, 0x22824c8e, 0x11999018, 0x8b222082, + 0x1c8200ff, 0xf78b0822, 0x4d264882, 0x00ff6726, 0x48820761, 0x00c06927, 0x781f00ff, 0x21148252, 0x1482e610, 0xba090522, 0xcd207c83, 0x5a219c82, + 0x0890831e, 0xffff9920, 0x085c0fef, 0xff0e078b, 0x9a99ff01, 0x239b01ff, 0xff4b15d8, 0x64e660fe, 0xfeffff05, 0x29820080, 0xff184425, 0x8220faff, + 0x83f72d09, 0xf7ffff96, 0xffffae67, 0x08862bfb, 0x27250582, 0xfdfffff0, 0x27048247, 0xfff292fa, 0x3c9ffeff, 0x97222882, 0x1a838b0a, 0x8be0cf22, + 0xde302082, 0x0000ff76, 0xffffbed0, 0xff6c07fc, 0x16a80100, 0x85201a82, 0x0023c882, 0x829a1933, 0x23cd275f, 0xb3ffffd7, 0x0a82c2b5, 0xf283fc20, + 0x8253f921, 0x83f920e8, 0x80fc2374, 0x55698400, 0xb3f62709, 0x0900ff33, 0xe482cc4c, 0x00800b22, 0x6023cc82, 0x8207142e, 0x1d07310c, 0x0200ff70, + 0x00ff3b5f, 0xff3eea06, 0xb95e0400, 0x9c21d382, 0x3220822a, 0xff0c42d9, 0x48611701, 0xdafeff05, 0xfeffcc4c, 0x8234b3f7, 0x63992764, 0x2a00ffd8, + 0x0a82cccc, 0x7dbff422, 0xb3203082, 0xf8316f82, 0x00ffdf5f, 0xff98990a, 0x0040ffff, 0x190d00ff, 0x87a4829a, 0x2159820a, 0x1e821038, 0x82b89e21, + 0x4c972104, 0x0c270e82, 0x54f808cc, 0x83ff00ff, 0x0a0023c0, 0x1282a4b0, 0x82e81b21, 0xa4302136, 0x70214082, 0x26268220, 0xffffb81e, 0x82080cf9, + 0x860a2085, 0x2795820a, 0xffffec41, 0xff78def3, 0x2a05a648, 0x082adcf3, 0xf894f70e, 0x18ff1554, 0x2d2e6944, 0x8b33b3c9, 0x80cdffff, 0xffff9c00, + 0xaf8280d6, 0x66e61c22, 0xf127af82, 0xff960080, 0x8270fcff, 0x1913228e, 0x2684829a, 0x00fff628, 0x8300800e, 0x820f8384, 0x00ff270a, 0xff67e613, + 0x34830300, 0xff210e83, 0x293983f5, 0x99191f00, 0x4ceaffff, 0xce6bffce, 0x4cf32205, 0x064661cc, 0x188bf521, 0x24138b92, 0x19caffff, 0x2281829a, + 0x8266e6d0, 0x3e8a2636, 0x33ddffff, 0x21048233, 0x6a828e42, 0xcdcc1e2b, 0x33e1ffff, 0x00ff0534, 0x2175820f, 0x2483f0ff, 0x5182f520, 0x83e6ff21, + 0xb3ea230e, 0xab828b34, 0x66e69124, 0xa518ff06, 0x00210ad7, 0x2417820a, 0x4c0d00ff, 0x234282cc, 0x075c0f6e, 0x22068562, 0x83d91900, 0xc2b521c9, + 0x1e264d82, 0xf0ffffb8, 0x208248e1, 0x90022222, 0xfd216e82, 0x2c638270, 0xffec512e, 0x3e4a2e00, 0x1c00ffcb, 0x20f982b0, 0x058a4f45, 0x66e60028, + 0xfb8b058b, 0x53841514, 0x5f824c82, 0x0cf0041a, 0xe6a1ff27, 0x00ff0766, 0x20938340, 0x05c741bf, 0x18323321, 0x290b4afd, 0xceccf5ff, 0x80f7ffff, + 0x97180800, 0x43211add, 0x077c61d3, 0x9a99032c, 0x80fdffff, 0x0600ff00, 0x6f829a19, 0x66660624, 0xc583f308, 0xff20d282, 0x3320dd82, 0x34200483, + 0x2805f35a, 0x0e078b08, 0x8b54f82f, 0x35561815, 0x86ab2408, 0x82f1ffff, 0xeeff23be, 0x1e4c7a54, 0x49b21807, 0x87451807, 0x05174c11, 0x5c4f0e35, + 0xab1100ff, 0x9b088b86, 0x0724f706, 0xfb0674fb, 0x4c9b0724, 0x85180e27, 0x6a890872, 0x6a888520, 0x2012894c, 0x511c194f, 0x0609530e, 0x85206a85, + 0xd4226a84, 0xbe4c7b07, 0x4c349f0e, 0x949f0fbc, 0xfb067b29, 0x74f70704, 0x8604f706, 0x290a416a, 0x86226a85, 0xb882ff8b, 0xe8847a20, 0x0820f885, + 0x82166a41, 0x41d4206a, 0xb3200534, 0x09ee8e19, 0xff2e0a83, 0x08cc4cee, 0x54f82f0e, 0xe68001ff, 0x3e821566, 0x166eed22, 0x54053260, 0xcc270746, + 0x066b088b, 0x8207f4fb, 0x19ee201b, 0x260d386e, 0x8be03aef, 0x83ffff08, 0x21058206, 0x8d82bade, 0x82cc4c21, 0xb3112693, 0xf4f70834, 0x2c35b207, + 0xffff07eb, 0x0666e6e6, 0x6eacffff, 0x08708214, 0xb85eb535, 0x1c3d00ff, 0xf8ffff28, 0x00ff9919, 0x08a53053, 0xdcf6ffff, 0x5f00ff2a, 0x00ff6766, + 0xffaec74a, 0xcc4c5000, 0xa85c00ff, 0xf7088bf6, 0x00ff0674, 0x829a9912, 0x820e2082, 0x82c08314, 0x3aef2643, 0x8b0e08e2, 0x19db82ab, 0x24144228, + 0xa83600ff, 0x253782f6, 0xff0a570c, 0x36821c00, 0x331c002b, 0x1300ff33, 0x00ff34b3, 0x05654320, 0xff270683, 0xcd4c1b00, 0x83ecffff, 0x820d2020, + 0xe3ff2120, 0xff24e482, 0x33b3f600, 0x2ed04c18, 0x09ffff2b, 0xff06cd4c, 0xcdccf2ff, 0x244483ff, 0xb3e4ffff, 0x26588533, 0x3333dfff, 0x84ff088b, + 0x821b8206, 0x23868420, 0xf6a8f3ff, 0x1a829a84, 0x0a57c922, 0x410e9542, 0x8b240871, 0x8b54f707, 0x9164e587, 0x2d59620f, 0x2f16b562, 0x84f734f7, + 0x2000ff15, 0xff8bcccc, 0xce4c1b00, 0xcd25b583, 0x330d00ff, 0x25ad8232, 0xff0833b3, 0xaf193600, 0x82410adb, 0x33b32205, 0x187b848b, 0x2417cd78, + 0x4cc9ffff, 0x21d282cc, 0x4e82ccf2, 0x34b3e327, 0xb3e4ffff, 0x080e4132, 0x0e413420, 0x82342005, 0xcce32243, 0x059541cc, 0x82f3ff21, 0x1c002725, + 0xff08cc4c, 0x3b8409ff, 0x21067062, 0x804285ab, 0x3746180b, 0x00ff2216, 0x21a384f6, 0x4e824c0c, 0x824c1c21, 0x331c22be, 0x20588334, 0x22d88533, + 0x413bab08, 0x33200543, 0x19050543, 0x630c8f53, 0xd88e0c6b, 0x6b632882, 0xf7eb2123, 0x1810b765, 0x820b1e6c, 0x014f1895, 0xffff220f, 0x10214129, + 0x201f3042, 0x41cd82b3, 0xa9220521, 0x3042cd4c, 0x00ff2218, 0x4c781811, 0x00ff2f12, 0x0633b356, 0x4c0c00ff, 0x1c00ffcd, 0x04820040, 0x4e823320, + 0x82c01321, 0x12104309, 0x01422083, 0x00c02b05, 0xd600ff08, 0xfb0634b3, 0x92186bd4, 0x594217c6, 0x05246416, 0x24e06b18, 0x087c5436, 0x01ff2f0e, + 0xff66661d, 0x66e6fa00, 0xa1ffff15, 0x055c67e6, 0x5e058554, 0xff200527, 0xff2cb982, 0x8b66e6fc, 0x19fbffff, 0x878b089a, 0xb3221c82, 0x1283ff33, + 0xffffff24, 0x16820080, 0x82343321, 0x195e22ab, 0x2a388399, 0xff343311, 0x32b31000, 0x821700ff, 0x0a00211b, 0x19200e83, 0x094f9e18, 0x090cde18, + 0x60605625, 0x18088b56, 0x230ad14c, 0x08c08bb6, 0x0421ba82, 0x208b82e6, 0x22368300, 0x859a1903, 0x03002388, 0x298266e6, 0x66e6a131, 0xffff05ba, + 0xffccccee, 0xce4cefff, 0x82e8ffff, 0xf5ff2161, 0xe6220e83, 0x4b849919, 0x82e1fa21, 0x05d522a6, 0x3b4d181f, 0x00ff2409, 0x82e1fa2a, 0x224b8304, + 0x821f0535, 0x19002325, 0x678267e6, 0x3c849e83, 0xb2830020, 0xc4845083, 0x62839a20, 0x0021d683, 0x20588304, 0x200482ff, 0x21888200, 0x9b838f8b, + 0x1e053522, 0x20279f18, 0xe622d787, 0x8b829a19, 0x0023a283, 0x8533330a, 0x100030b6, 0x8b0833b3, 0x2f0e058b, 0x34f814f8, 0x7e00ff15, 0xd420154f, + 0x18174f7e, 0x7e0eb989, 0x33830b4f, 0x15ea7718, 0x4b06d429, 0xffff154b, 0x8234b3dc, 0x4ce3248f, 0x82ffffcc, 0x820a8204, 0x48d38210, 0x0027057f, + 0xffff9a19, 0x599a99fd, 0x098206be, 0xffff0823, 0x231483ae, 0x05cc4cd3, 0x27067964, 0xffcd4c0c, 0x0080efff, 0x2405a65d, 0x33b3edff, 0x7e25828b, + 0x992007de, 0xcd205783, 0xe3825784, 0xff246f84, 0x67a61c00, 0xe9826e84, 0x829a5921, 0x1200222d, 0x2122824c, 0x44851000, 0x00ff3435, 0xff33b30b, + 0x32330d00, 0x5100ff08, 0xffff66e6, 0x826666d2, 0xb3ff226e, 0x218e8534, 0x1483ffff, 0x57828e82, 0x0080fd22, 0xb682af83, 0x20835782, 0x4141c682, + 0x413c8205, 0x14410948, 0x848b200a, 0x2080861e, 0x8232831c, 0x2385823c, 0x9a99f0ff, 0xf1205082, 0xfa205b83, 0xff21f482, 0x220983f4, 0x8266e6f6, + 0x82aa20ce, 0x2e002a26, 0xff050080, 0xcc4c5500, 0x240a86ff, 0xff9a190b, 0x222082ff, 0x830e00ff, 0x23348309, 0x66660f00, 0xc2414b82, 0x2079820a, + 0x20728433, 0x83a782cd, 0x25799017, 0xff0e078b, 0x4182cb01, 0x9c8b012e, 0x00ff1528, 0xff32b32d, 0x862befff, 0x042d6c82, 0xffff3433, 0x8ea470fe, + 0xa8fbffff, 0x229d82f6, 0x823473fb, 0x05c97f46, 0x3282fc20, 0xc5fbff26, 0xfcffff1e, 0xfe223183, 0xa982cc8c, 0xce4cd222, 0x21223c82, 0x94410548, + 0xd2ff2305, 0x7a4d3433, 0x83fb2007, 0x200484d4, 0x20d983fc, 0x20a984fb, 0x820683ff, 0x20e0835d, 0x26508303, 0xff0080fe, 0x83660400, 0x33ef22f5, + 0x218d8232, 0x4082cccc, 0x00235683, 0x82b8de10, 0xccfb280a, 0x0100ffcc, 0x82883473, 0xe23a2126, 0x0422da82, 0x7882e27a, 0x3c82ff20, 0x8c040024, + 0x16828ecc, 0x4e0a5721, 0x0129069e, 0xb9085c8f, 0xd41000ff, 0x20cc827a, 0x22598310, 0x828ed72d, 0x8201200a, 0x03002380, 0x2b82ceec, 0x02226383, + 0x09827c9f, 0x8bce4c23, 0x837a8408, 0x22f88353, 0x828460fd, 0x232a8269, 0x3213fcff, 0x40831a82, 0x28d2ff23, 0x20848272, 0x234b82cb, 0x72fd7aff, + 0x0e2da918, 0x200e2154, 0x235c82fd, 0x9a19fdff, 0x07237182, 0x827568e6, 0xcc4c275c, 0x33e8ffff, 0x05838b34, 0x82083221, 0x838c2006, 0x83a22068, + 0x22048463, 0x829a198d, 0x8dff2384, 0x1b82b81e, 0x47e1a225, 0x825d00ff, 0x00ff2811, 0x08cccc73, 0x8206f78b, 0xb91e270e, 0x7200ffe9, 0x268248e1, + 0xb3180023, 0x2dab8233, 0xffcdcc17, 0xceccfaff, 0xf8ffffa1, 0xa7829819, 0x4e820220, 0xcc020023, 0x005618ce, 0x3bdb211b, 0x3820c582, 0xf922c583, + 0xc5826666, 0x4a840920, 0xcd4c0623, 0x0ac864ff, 0x2207b45b, 0x8433b3f9, 0xffff2d16, 0x8bcd4cf6, 0xff068308, 0xccccb5ff, 0xc225a182, 0xffff3333, + 0x25a183c3, 0x66e6b4ff, 0x12668308, 0x0f082208, 0x218d825d, 0x3682cccc, 0x83a4f021, 0x9a9d1aaa, 0x82932014, 0x39002f2f, 0x00ff6666, 0xff01802f, + 0x9a992e00, 0x938200ff, 0x93088b28, 0x00ff0e06, 0x0e8219b1, 0x9d84db20, 0x49821e20, 0x99a4ff23, 0x2dd1829a, 0x06008060, 0x9e1d00ff, 0x5b00ffb8, + 0xc4824861, 0xe2fab122, 0x85213582, 0x820a831e, 0xc7ff3031, 0xd9050080, 0x99e400ff, 0xffff159a, 0x82008073, 0x668d23a6, 0x5218ff6d, 0x002311f8, + 0x84939972, 0x05b54e16, 0x06850820, 0x7100ff25, 0x82ff34b3, 0x829a201b, 0x808c23fd, 0x06850800, 0x2105ad50, 0xac827400, 0x2082ff20, 0xa126d283, + 0xfeff0080, 0x66831997, 0xb983aa20, 0x084c0122, 0xe6278382, 0xffff9ad9, 0x82f668ae, 0x0cf02b0a, 0xfbffffcc, 0xffff68b1, 0x09824cef, 0x2f82fd20, + 0x99eeff23, 0x843b829a, 0x37168206, 0x00ff5c4f, 0x7be48502, 0x560400ff, 0xffff0804, 0xffd7e3e6, 0x7e8a5100, 0xaa273c82, 0xffff9999, 0x82f8b3fe, + 0xe1ed310a, 0x1b00ff47, 0xfffff6a8, 0xff52f8f4, 0x289c2000, 0x45261982, 0x2300ff1f, 0xb5823e0a, 0xaec74527, 0x2f3100ff, 0x202982e0, 0x3b6782e4, + 0xcccc5000, 0x1500ff05, 0x00fff628, 0xffc2351a, 0x15ee1b00, 0x661400ff, 0x1f00ff68, 0x0c223e83, 0x3482e03a, 0x0a574427, 0xc2ccffff, 0x27298290, + 0xff3e4a44, 0x52383300, 0x1f270a82, 0xffffe2fa, 0x821ec5f3, 0x84eb2634, 0x97ebffff, 0x2348850c, 0xcccce5ff, 0xe4219e82, 0x20db8259, 0x832984af, + 0xceff2374, 0x748266e6, 0x51fe2b08, 0xdcffffea, 0xff8066e6, 0x6666dfff, 0xccedffff, 0xe4ffffce, 0x0e08ce4c, 0x190f01ff, 0x6315df9a, 0xffff8b07, + 0xff0060f9, 0x04820500, 0xa0faff22, 0x06280982, 0x088b00a0, 0x00ff06b3, 0x18850883, 0x8b201d83, 0x08211084, 0x833182b3, 0x85ff2019, 0x8236842c, + 0x088b2340, 0x12820663, 0x83323321, 0x1865834f, 0x21099d5a, 0x66e48beb, 0x00f72f23, 0x83838315, 0x839c858c, 0x20de85a1, 0x20e78b08, 0x2a1d8542, + 0xbe9f0600, 0x00ff088b, 0x999a1927, 0x00ff24eb, 0x8266e600, 0x9a9930f8, 0x80fbffff, 0x0500ff00, 0xffff6666, 0x820080f8, 0x40ff2539, 0x54fb28dc, + 0x002073a5, 0x5b417387, 0x226b8322, 0x8647a1fa, 0x5ef9226b, 0x236b82b8, 0xd8235b00, 0x2652ad41, 0xffff8b33, 0x82cdccf9, 0x4b5c189c, 0x58f72108, + 0x21264741, 0xd3863c5f, 0x5eba0522, 0x22224741, 0x41cccc01, 0xeb211547, 0x2442418b, 0x86765e21, 0x9e06226e, 0x226e90fa, 0x42ff9062, 0xb6410ca2, + 0xfb2b261a, 0x7cfb1554, 0x21f78206, 0xfd820060, 0x41a0fa21, 0x2742059a, 0x0cb34112, 0x3282f720, 0x421b1043, 0xfb221220, 0x1d42f754, 0x48612125, + 0xb820da88, 0x0422da8f, 0xda8f9a79, 0x21184941, 0x8e42b4f7, 0x0ffa4257, 0xdc7cfe23, 0x1a8e4228, 0x2800ff24, 0x54430000, 0x05494419, 0x22144044, + 0x184861f9, 0x20110cdd, 0x2691428f, 0x430c6221, 0x83200865, 0x210cc144, 0x4341715d, 0x061b620d, 0x6543ff20, 0xa4013d0f, 0x00ffa4f0, 0x159a1999, + 0xcc76ffff, 0x8900ffce, 0xffffc235, 0xff999920, 0x90020000, 0xc8211382, 0x27048272, 0xff08aec7, 0x6606f8ff, 0xea210483, 0x052a61ff, 0xc4c0f322, + 0xfb376282, 0xf6ffffe7, 0xff08e07a, 0x852b2a00, 0x87bcffff, 0x00ff05af, 0x82192406, 0xf0273515, 0x540c00ff, 0xfbffff3a, 0x00ffc8f6, 0xff48e10a, + 0x7d3f0400, 0x54272982, 0x00ff295c, 0x8270bd21, 0xed092729, 0x0300ff92, 0x3382eae6, 0x969a1922, 0xe6265982, 0x0900ff66, 0x6e82cecc, 0x6fb2fa27, + 0x453500ff, 0x2c25821e, 0xff672638, 0x862b1300, 0x403d00ff, 0x27c98200, 0xff323338, 0xf8d2ecff, 0xb3272583, 0xcafffff8, 0x820564bc, 0x6adc263b, + 0x68f5ffff, 0x214b82f4, 0x0982d222, 0x825ccf21, 0x86f6254a, 0x0cfcffff, 0x00284f82, 0xff9a5954, 0x1f45deff, 0x0a224f82, 0x95827ad4, 0x0c225f83, + 0x9582d863, 0x5e822420, 0x281c0622, 0xc6212e82, 0x289f829b, 0xff142e2a, 0xe27a4300, 0x21df8205, 0x1582e2fa, 0x68827720, 0x9c99fe22, 0x4c2ece82, + 0xf7ffffce, 0x0893feff, 0xf834f80e, 0x8b821524, 0xb8de0825, 0x83f8ffff, 0x210722b6, 0x251c8248, 0x088b9a19, 0x0885064b, 0xff241885, 0x8bb8def8, + 0x21291082, 0x075b0848, 0x0a6000ff, 0x281e823e, 0xbbc2f5ff, 0x9ffeff05, 0x363382e1, 0x1566e68f, 0x75fdffff, 0xa2ffffc2, 0xffff3433, 0xfff628c6, + 0x8299ebff, 0x80fc29ae, 0x7effff00, 0x5f08cc4c, 0x18264918, 0xff061424, 0x82521100, 0x66662205, 0x264918ff, 0x07d4260b, 0xe19fffff, 0xce491847, + 0x17f22508, 0xf1ffff0a, 0xff2e5183, 0xffffae87, 0x086666ee, 0x388001ff, 0x7c828b52, 0x1682ff20, 0xff224683, 0xd256f2ff, 0x21208307, 0x4282088b, + 0x0666e624, 0x7fb1d4fb, 0x7e82b720, 0x0022bf83, 0xd383b381, 0x0021d882, 0x21a18214, 0x0482fdff, 0xcc5d0023, 0x365a82cc, 0xff66e61f, 0x9a1980ff, + 0xf706cb15, 0x064b0734, 0x5b0734fb, 0x411594f7, 0x9921053e, 0x103e418b, 0xffffff26, 0x055bc2f5, 0x20054341, 0x209282bb, 0x137d4100, 0x30fb0e24, + 0xf450f8eb, 0x18332005, 0x20116dd0, 0x6267822b, 0xf722180e, 0xe4768b54, 0x21378e17, 0x0a55cc4c, 0x11002805, 0x088b34b3, 0x8e34fbcb, 0x0d4b7537, + 0x2807b074, 0xff33b3f1, 0xcc4ceeff, 0x0533778b, 0x9a99b234, 0xc0ffff54, 0xff42cc4c, 0xce4cf0ff, 0x9cffff08, 0x9f82cccc, 0x6300ff31, 0xff073433, + 0x52f8b6ff, 0xb30f00ff, 0x1affff32, 0x274141f3, 0xf874f80e, 0xf4fb1534, 0x0f014c18, 0x22070c52, 0x1807e4fb, 0x21083485, 0x2e4b0ad7, 0xf7ff2605, + 0x088bf628, 0x820684ff, 0x4b168211, 0xf7220a8e, 0x597707c4, 0x0a46780d, 0x83b4fb21, 0xa6dc254c, 0x1c00ff66, 0xff230482, 0x4e9a59e3, 0xf82206de, + 0x09850614, 0x1e831985, 0x10848b20, 0xf4f70822, 0x1805a463, 0x2511a97d, 0x14fc64fb, 0xfb672b15, 0x11164c0c, 0x0f9a8618, 0x6782eb20, 0x2c998618, + 0x62b5eb20, 0x73087271, 0x48410a38, 0xcccc2108, 0x26074841, 0x088b3433, 0x852b34f7, 0x135b6c63, 0x00ff8b25, 0x6c88d608, 0x07220653, 0x0e837829, + 0xa0640420, 0x18c6b405, 0x4107b648, 0x34201429, 0x33206782, 0x08200482, 0x0822bd82, 0x6b8206eb, 0x9b23c6aa, 0x841504f7, 0x060173e1, 0x20053e6d, + 0x21e183f7, 0xa54194fb, 0x0736720f, 0x4d07eb21, 0xa74106be, 0x82f7200f, 0x83002032, 0x41928587, 0x2b2f0a45, 0xffef0e07, 0x9a193f01, 0xe66000ff, + 0x18ff1566, 0x230a2550, 0x0a57e3ff, 0xdc238282, 0x850866a6, 0x00ff2506, 0xfff6a81c, 0xff221683, 0x1b822300, 0x06850820, 0x1b831685, 0x85066442, + 0xffff2406, 0x853233e4, 0xdbff241b, 0x608bcecc, 0xf7210547, 0x22638234, 0x8200c0b9, 0x59bc2a51, 0xe6ffff9a, 0xffff6666, 0x240483cb, 0x08ec91d1, + 0x054057ff, 0x146ef326, 0xb3feffff, 0xeb25fa82, 0x00ffcecc, 0x2209830b, 0x8232b3f2, 0xcc0b2341, 0x2382ffcd, 0x14211482, 0x211e8233, 0x6182b3fe, + 0x09820d20, 0x34202382, 0x28251e82, 0x00ff67e6, 0x2ccc8324, 0xff999934, 0x66e61300, 0x993600ff, 0x837b839a, 0x00ff2206, 0x26308234, 0xb81eecff, + 0x822800ff, 0xdbff2359, 0x358248e1, 0x4a510620, 0x99072308, 0x3b45ff98, 0x80072205, 0x22358300, 0x8210d808, 0xd00832cd, 0x0300ffe6, 0x00fff0a7, + 0xff0a5706, 0x6c270700, 0x25958308, 0x0d00ff34, 0xa9823e4a, 0xffcccc24, 0xec821400, 0xb3f2ff22, 0x0b211382, 0x848a82b3, 0x2e0021d3, 0xbc20d883, + 0x00280482, 0xff00801a, 0x34b3b9ff, 0x01225482, 0x25823336, 0x6666223c, 0xacffff15, 0x00ff9819, 0xff866b50, 0x68e691ff, 0x472c00ff, 0x8bffffae, + 0x2582cccc, 0x16820684, 0xffd8e326, 0x52b8d3ff, 0x272b2a82, 0xafffff6c, 0xff087a94, 0x8240f3ff, 0xc0f3214c, 0xff250482, 0xffff0a97, 0x230982eb, + 0xf6380c00, 0x01201883, 0x0c219982, 0x202e8238, 0x210482f3, 0x28831400, 0xf6a8ff27, 0xc70c00ff, 0x210482ae, 0x1e82b82e, 0x89f1462f, 0xc94500ff, + 0x5f00ff99, 0x00ffcd4c, 0x21fd8225, 0x24416300, 0x28068305, 0x7f5d00ff, 0xdafffffe, 0x20308207, 0x23cf8248, 0xec11bbff, 0x06263582, 0xffffcc4c, + 0x358219fa, 0x68e60724, 0xa1829388, 0x67080025, 0x82ff8bf0, 0xff6c2a05, 0xf0470300, 0x470600ff, 0x210482b0, 0x2d822090, 0xc0350c22, 0xc1296e82, + 0xffffff89, 0x00ff9c99, 0x21638215, 0x4182f3ff, 0x670b0021, 0xe4310699, 0xfb1554f8, 0xffff06b4, 0x8b4861e6, 0x9ee9ffff, 0x820484b8, 0x2310820a, + 0x0734fc08, 0x24054761, 0x611600ff, 0x29198248, 0x00ff9a99, 0x8bb89e19, 0x3382f708, 0x19850984, 0x83821e83, 0x08211a82, 0x833383f8, 0x842e861a, + 0x66e62938, 0xfb088b66, 0x1564fba4, 0x08212582, 0x23ee82cc, 0xff333307, 0x19051e43, 0x1812f90a, 0x21111d4e, 0x7943ff33, 0x82f82005, 0x0597773b, + 0x7d436b20, 0x07ab2317, 0x66852b8b, 0x11c38b18, 0x20051d76, 0x838482cd, 0x0a7f437f, 0x10466b20, 0x23618309, 0xffccccf8, 0x4e186696, 0xf7230984, + 0x8214fb34, 0xf7ff2368, 0x9d82f232, 0x860ecd21, 0x820e8204, 0x8f1420eb, 0xbc4e189e, 0x209b910e, 0x233282f7, 0x0ecd0800, 0x51869c83, 0x84828b20, + 0x08f23222, 0xeb209c82, 0x06416897, 0x4167a010, 0x66851b03, 0x6d413320, 0x00ff212d, 0x222ed141, 0x9d54fbeb, 0x827420ce, 0xccf828f8, 0x0700ff8c, + 0x828bf232, 0x0ecd245e, 0x8507ab08, 0x21138208, 0x18847433, 0xcc211782, 0x06f76e8c, 0x98353541, 0xcccc2166, 0x2105a045, 0x38460700, 0x0d577808, + 0x410d3942, 0xcc200b35, 0x1806a842, 0x82124150, 0x0721464d, 0x0743cd85, 0x43342005, 0xcc200807, 0x9f46cd86, 0x7350180b, 0x868b2009, 0x688e1866, + 0x74fb2111, 0x20176c42, 0x188946cb, 0x89463282, 0x4b2b0815, 0xf7ef0e07, 0x4701ff4e, 0xa2150080, 0x1e2300ff, 0x2400ffb8, 0x00ff6666, 0xff3e8a19, + 0x9a992a00, 0xa30800ff, 0x00ff08d6, 0x6c343313, 0x4c250969, 0x0e00ffcc, 0x20258254, 0x0f0a7f11, 0xabf1ff23, 0x05dd5e9a, 0xffff082c, 0x07ccccec, + 0xf1ffffd4, 0x1619862b, 0x68263111, 0xb3f7ffff, 0x7e820532, 0x7c646621, 0x023106f1, 0xffff9c19, 0xff9a99f2, 0xccccfaff, 0x80f4ffff, 0x21638200, + 0x1e82e6fe, 0x1482ff20, 0xb300002b, 0x0000ff34, 0xffff6666, 0x221e83ff, 0x8234b3fe, 0x335a27b6, 0xb9ffff34, 0x4882cc4c, 0x861bd718, 0xa4309338, + 0x9c8cffff, 0xff7105ac, 0x33b395ff, 0x0400ff15, 0xff0733b3, 0xa983f600, 0x9a193e28, 0xe9feff05, 0x1619cccc, 0xf32508cd, 0x00ff33b3, 0x25d58307, + 0xffc2b5fb, 0xf4840b00, 0x0ad7fa22, 0xff270a84, 0x5c0f0200, 0x820d00ff, 0x0800261e, 0x00ffd763, 0x821e8309, 0xff67252e, 0xce4c0800, 0x1f21f482, + 0x283e8233, 0xff323323, 0xcd4c1100, 0xcd1619ff, 0x078b330a, 0xfeff34f7, 0x15cccce2, 0xffff8b7a, 0xff34b3ef, 0x16190600, 0xcc200a7c, 0x332b3082, + 0x00ff8b32, 0x089a1910, 0x830614f7, 0x66e62923, 0x4cf9ffff, 0xeeffffcc, 0x187c1619, 0x00ff2f23, 0x23718287, 0x5c4fae01, 0x0521d882, 0x22878266, + 0x828ed70a, 0x991921ab, 0xd92e5f82, 0x0c00ff16, 0x088b9a19, 0x667800ff, 0x0c830667, 0x62829820, 0x9a190b22, 0x26225882, 0x8f53ffea, 0x28f52205, + 0xd39b1872, 0xb0f12407, 0x60eb05a4, 0x5f180e14, 0x54210c81, 0x1060617c, 0x5d14fc21, 0x54210ea4, 0x3741187c, 0x13a45d09, 0x07206083, 0x2108b482, + 0x5c4f0e00, 0x0301ff05, 0xfeff9899, 0x150a973f, 0x66feffff, 0xe5ffff68, 0xffffcecc, 0xff9819eb, 0xfb83ecff, 0x8399e621, 0x0aff23bf, 0x66823433, + 0x66a6e623, 0x261c828b, 0x00ff1f05, 0x8234b313, 0x856b3130, 0x331a00ff, 0xffff0832, 0xfff6e8e9, 0x9a195201, 0x802e5182, 0xff0666e6, 0xcccceaff, + 0xe6adfeff, 0xbe180566, 0xff2162d7, 0x2ccf82c7, 0x6666c7fe, 0x0e00ff15, 0xffffa4f0, 0x340482f0, 0x29dc1300, 0xaef7ffff, 0x1500ff14, 0x088b0a17, + 0x080000ff, 0x24be8203, 0x8bfdf7ff, 0x230e838b, 0x8b5c0f15, 0xdc26c882, 0x0800ff2a, 0x3982e04f, 0xfff4e826, 0x68110f00, 0x09242982, 0x00ff0060, + 0x0f220484, 0x3882ae27, 0x82101821, 0x8270200e, 0xaff62258, 0x261e83ec, 0xfffff067, 0x82f0a7f6, 0x20102119, 0xd0216d82, 0x210e8262, 0x0482ecaf, + 0x085c8f3a, 0xe7ffff73, 0xffffaec7, 0xffcc0ce0, 0xf6a8f2ff, 0x00deffff, 0x8b088b01, 0x80896b82, 0x15820820, 0x82ae0721, 0x05e02d8d, 0x0d00ff1f, + 0xff730a57, 0x52381800, 0xce2d1682, 0x00ff5c8f, 0x8b48e131, 0x1e5100ff, 0x820a82b8, 0x31002576, 0xa30866e6, 0xff242184, 0xe1fa1f00, 0xff243184, + 0x52f82100, 0x2220d692, 0x25826d82, 0x8432f321, 0x84a3207d, 0x82b3838d, 0xf6ff24e2, 0x82ffde8f, 0x21b383af, 0xae826ad1, 0x18049821, 0x22072749, + 0x85e08ff6, 0xf0ff23d2, 0xd78216d9, 0x82ef2721, 0x829e200e, 0x5809227f, 0x3095821e, 0xff0a17f1, 0x5b0f0f00, 0x23ecffff, 0x0800ffd8, 0x22ec8251, + 0x92a3f0ea, 0xe8ea22d6, 0x2cd682f6, 0xffd723ec, 0x22b0f7ff, 0x0ff1ffff, 0x2171825c, 0x448297ee, 0x9b19e127, 0xbae0ffff, 0x271f8245, 0xff3433cd, + 0x66e61e00, 0xcc380f82, 0xff0e08cc, 0xcccce201, 0xc5a201ff, 0x00ff151e, 0xff68e626, 0x2005d9ff, 0xc0212682, 0x233c82cf, 0x649819d9, 0x9a213d82, + 0x20168266, 0x3f54189a, 0x84f62009, 0xa36f180a, 0xff002121, 0x0f3ee418, 0x0e8c0719, 0x18ff8b21, 0x2021d2e4, 0x05926f80, 0x00ff0823, 0x260a8309, + 0x059a99f6, 0x826500ff, 0x6500250a, 0xb205ea91, 0xf928b482, 0x3f00ff58, 0xb28b3233, 0x062fbb82, 0x8b8b08a8, 0x54feff05, 0xfeff48a1, 0x8216eed9, + 0xab7827d4, 0x7800ff86, 0x368232b3, 0xcc4c2d2d, 0xb3d2ffff, 0xffff0534, 0x83cd4c87, 0x82cc2004, 0xfdfc290a, 0xffff8871, 0x875c4ffe, 0xfb22f782, + 0xf18234b3, 0x66e6db37, 0x2400ff07, 0xff069a19, 0xcc4c0400, 0x00ff8f8b, 0x8e34b301, 0x2285828e, 0x9b34b378, 0x7c7c214e, 0x9924f482, 0xf7ffff9a, + 0xea230483, 0x828bcdcc, 0x97d52d4e, 0xffff060a, 0xff5c0fd8, 0x6666e5ff, 0xf3217282, 0x270a824f, 0xff0280f7, 0x9919efff, 0x302b5b83, 0x36f5ffff, + 0x0a00ff87, 0x8308cecc, 0x84c9200a, 0x2195820a, 0x836bb653, 0x08002805, 0x00ff0476, 0x8232b30c, 0xa01a2782, 0x2700ff00, 0xd18268e6, 0x66662a2d, + 0x00ff8b07, 0xff323315, 0x5a6e0800, 0x9a2e0515, 0x8b8b089a, 0xf7af0e05, 0xb800ff74, 0x148234b3, 0x3333002a, 0xff1d00ff, 0x0e00ffff, 0x1c280983, + 0xffa39a19, 0xffff1100, 0xec204b82, 0xb122ce83, 0x4b825298, 0xb1821220, 0xf50d0028, 0x1900ff40, 0x7a8264e6, 0x82ac9c21, 0x9c192724, 0x22f0ffff, + 0x06830890, 0xffd62335, 0x98190300, 0x38e6ffff, 0xf3ffff52, 0xffff6866, 0x825278ec, 0x4c5e26af, 0x05ffffcc, 0x224482f8, 0x82ccf0ff, 0x66e8270a, + 0xe7ffff66, 0x3a82ce4c, 0xff008022, 0x22051c64, 0x829a19fc, 0x838c2029, 0xcc672f6e, 0xffeb05ce, 0xcc4c77ff, 0xffff8b15, 0x551919c2, 0xfb2111ec, + 0x0e5a4524, 0x82093065, 0x7b438393, 0x04231005, 0x82065ccf, 0x48a12b1b, 0x0b00ff8b, 0x00ffc3f5, 0x8482e612, 0x8330fe21, 0x008022e9, 0x21fc8208, + 0xbe82299c, 0x9482cc20, 0xcdccff22, 0xe6210982, 0x23298266, 0x0866e603, 0x3c200682, 0x0021b082, 0x2130822f, 0xb5823100, 0x833b0021, 0x33023220, + 0x00ff0832, 0xff991974, 0x9a9997ff, 0x0000ff05, 0x20a88219, 0x842983fe, 0x99fc2609, 0xffff8b9a, 0x305b82fd, 0x2f0e078b, 0x01fff4f7, 0x1566e650, + 0x171600ff, 0x2251820a, 0x82f6e811, 0x83e1208d, 0x2010828d, 0x31118208, 0x630c1716, 0x0a3100ff, 0x088b8b3c, 0xff638b8b, 0x2883ceff, 0xe8e9ff23, + 0x831d82f6, 0x822f8206, 0xeeff2381, 0x448270fd, 0x8b9a1926, 0x8b14fb08, 0xff264fcc, 0x9a199f00, 0x538204fb, 0x68820020, 0x193f0024, 0x9782059a, + 0x04d60825, 0x82f8ffff, 0x07002804, 0xfffffc29, 0x18fc29f7, 0x1812a25a, 0x2109ce44, 0xfc49064b, 0x21359805, 0x534d8b33, 0x1835a908, 0x870bdd5b, + 0xffff2535, 0x07ae07c0, 0x2509b250, 0xe3ffff99, 0x5d829a59, 0x8cdd2908, 0xffff08cc, 0x07cc4cbb, 0xd00900ff, 0xf9ffff62, 0x00ffe4e5, 0xff75930b, + 0xa2c5faff, 0x9c0a00ff, 0xff088b29, 0xd7a31400, 0x182cde82, 0x00fff668, 0xffe2ba13, 0x66a60700, 0x99210482, 0x221a8298, 0x6d004006, 0x17210739, + 0x8324820a, 0xf9ff230f, 0x1a83f0c7, 0xff5dcf30, 0x5478f7ff, 0x4c1900ff, 0xedffffcd, 0x49823233, 0x849a9921, 0x24068250, 0x731800ff, 0x2050b833, + 0x825095cc, 0x20a18662, 0x20a1a468, 0x8ea1885c, 0x9c0a2250, 0x2ccd8228, 0xff7c940b, 0x1c3a0500, 0xcf0900ff, 0x21e7825c, 0xd7825e1a, 0x86ab4423, + 0x2a1b8207, 0xff008022, 0xcc4ce3ff, 0x831d00ff, 0x05b95109, 0xe6e0ff2d, 0x69ffff66, 0xff15cecc, 0x8240f2ff, 0x0cf52120, 0xe72e5882, 0xffff52b8, + 0xff3e4af0, 0xae07e6ff, 0x0685088b, 0x83ffff21, 0x0f002316, 0x2a8534b3, 0xf50a0023, 0xd01a82c2, 0xbaf43735, 0xffff8be1, 0xff142ef5, 0xfa1e0300, + 0x17f6ffff, 0x0400ff0a, 0x6b828a41, 0xb89ea822, 0xff25c982, 0xff5243ee, 0xf14d1800, 0x14f8210e, 0x0c6e6a18, 0x6b181e82, 0x57230935, 0x85074861, + 0xfbff2347, 0x5b8576be, 0xe1fcff30, 0xf4ffff06, 0x088be2ba, 0x0000ff71, 0xde82a2e5, 0x82cccc21, 0xcecc2156, 0x332ade82, 0xfb089634, 0x0601ff94, + 0x87433233, 0xf6e8223e, 0x06d743ff, 0x8b0a1727, 0xbbcb0e08, 0x1c5f1815, 0x24f82116, 0x570e844a, 0xaa180d03, 0xfc201155, 0xe6183082, 0xf7211556, + 0x05464de4, 0xa0188420, 0xff201079, 0x0d8e4018, 0x230abd56, 0xdf15dbcb, 0x23083583, 0xff33b307, 0xcdcc0200, 0x800700ff, 0x0500ff00, 0x00ff9919, + 0x0833b306, 0x664f00ff, 0x5900ff67, 0x980566e6, 0x21052541, 0x1b821700, 0xb3ffff2d, 0x0b00ff32, 0xffff34b3, 0x8268e6f0, 0x19282925, 0x94055c9a, + 0x19f5ffff, 0x102e2682, 0xffff6666, 0x95ce4cff, 0xa0a00895, 0x0a75ff05, 0x190d2505, 0x1500ff9a, 0xff223682, 0x3b8233ff, 0x0e820c20, 0xe6f1ff23, + 0x213b8266, 0xe582cc41, 0x3433b328, 0xffff9005, 0x878333fa, 0xf8275783, 0xff8b9a99, 0x8266f8ff, 0xbbff2321, 0x5018cdcc, 0xff2717fa, 0x9a19dffe, + 0x18ffff06, 0x361452a3, 0xe60000ff, 0x0e058b67, 0xffc4f7af, 0x866baf01, 0x00ff8b15, 0x82660609, 0x237d82da, 0x148e0700, 0xe6220e82, 0x83828b66, + 0x34b37b22, 0x64211b82, 0x2089824c, 0x260a839b, 0xcc4c84ff, 0x83828b08, 0x84682280, 0x31218282, 0x989920ff, 0xdf00ff06, 0xfb07866b, 0x00ffffa4, + 0x4c837a94, 0x30827920, 0x835a0021, 0x5c642c4c, 0x7400ff2a, 0x00ff0100, 0x820a1710, 0x190a2c50, 0x0100ff99, 0x00ff9042, 0x82cdcc07, 0x48a12146, + 0xf634cd82, 0xff0800c0, 0x289c11ff, 0x9c00ff07, 0xffff0080, 0x05008063, 0xef838d82, 0x4a82f920, 0x80ffff24, 0x2c828000, 0xfa210a83, 0x212b8380, + 0x9182ccd8, 0x9a19e423, 0x26e1825b, 0xffff9a99, 0x833433cc, 0x807b228c, 0x204e8200, 0x23428294, 0x66666b00, 0x842ab982, 0xff089a99, 0x68660e02, + 0xd382157b, 0x82303321, 0x66072212, 0x244a8268, 0xffff3433, 0x224483fe, 0x82ccccf6, 0x83f8207b, 0x19c8265a, 0xffff709a, 0x310a83ce, 0xffceccd8, + 0xce4cdbff, 0xffff8508, 0xff3233fb, 0x6583f6ff, 0x0483ff20, 0x3a82fa20, 0x84050021, 0x82612035, 0x9e00232a, 0xab8234b3, 0x6866ee23, 0x99ce4206, + 0x1601ff22, 0x0023ba82, 0x18666679, 0x790da5cc, 0xc6200fdc, 0x39202583, 0x1aa5cc18, 0xf327308f, 0x00ffe17a, 0x4a00800c, 0x852108c0, 0x260f841f, + 0x7000ff08, 0x19f70000, 0x220b5132, 0x781400ff, 0x80210ae0, 0x2b228200, 0xff666639, 0x33b3c6ff, 0x6900ff05, 0x00210a82, 0x83798369, 0x2143824e, + 0x308d1e85, 0x79e27a21, 0x90660e11, 0x14fb290c, 0x0e0514fb, 0xeb54f7af, 0xca28e082, 0xff8b9a19, 0x66e6d5ff, 0x210c956a, 0x4a6a9a19, 0x6b352006, + 0xf726191d, 0xfb152b54, 0xfe180654, 0xe1200ad2, 0x08e5c518, 0x5500ff24, 0x0482c3f5, 0x6a2a4783, 0x088b3e0a, 0xf50654f7, 0xfe18e18b, 0x21280cf3, + 0x8b213535, 0xd4f78b08, 0xb9224585, 0x8882cd4c, 0xe583e082, 0x0a823420, 0xcc4cb923, 0x24068508, 0x4c3900ff, 0x241684cd, 0xb34600ff, 0x194d8433, + 0x820b162e, 0x8bcc211e, 0x30821084, 0x34202182, 0x39242b86, 0xffffcc4c, 0x8b284682, 0xf8af0e08, 0x1514f814, 0xc4ab8295, 0xb4fb8b22, 0x3dfe7818, + 0x01ffef2d, 0xf834335b, 0x00ff1534, 0x8266e60a, 0x0b2c08b5, 0xffff32b3, 0xff5c8ff9, 0x9a990500, 0xa8f5ffff, 0x00ff08f6, 0xff66e661, 0x14ae4bff, + 0x0c00ff05, 0x988e3433, 0x190200ff, 0x0d00ff9a, 0x22058058, 0x1934b346, 0x8308102f, 0x41e3830a, 0xff22072a, 0xfe86b3c6, 0x0041f985, 0x09104105, + 0x20092741, 0x2b638228, 0x66661200, 0xcc2200ff, 0x1c00ffce, 0x00393782, 0x08ff7f17, 0x4ceaffff, 0x2800ffcc, 0xff059a19, 0xce4cabff, 0x7f70ffff, + 0x250a82ff, 0xff9899fb, 0x2582f8ff, 0x33f8ff22, 0xfb256282, 0xffff0080, 0x219083f7, 0x1782065a, 0xff219e82, 0x265182c0, 0x3333caff, 0x83cfffff, + 0x6bbe200e, 0xb9230583, 0x828b5c4f, 0xa4b0227f, 0x11a741ff, 0x4f390022, 0x3920f882, 0x46236f83, 0x828ba4b0, 0x820a20f9, 0x00ff2234, 0x235c830a, + 0x9533b3fe, 0x23052b4b, 0x991a00ff, 0x3522fe82, 0x87829919, 0x6582e920, 0xb31e0023, 0x220a8234, 0x82cd4cd4, 0x83f2207b, 0xf5ff2232, 0x772d194c, + 0x74e7820c, 0xc32413a8, 0x0700ff06, 0x06286284, 0xffff6766, 0xff3e4afc, 0x2205d651, 0x82289cfa, 0x661b257d, 0xd9ffff66, 0x0023f983, 0x82666695, + 0x66dd235b, 0x6882cb68, 0x0c84e520, 0x9a99f322, 0xf420c982, 0x00212382, 0x02ed180a, 0x0b00210f, 0x1682a183, 0x0c00ff24, 0xc9836666, 0x2505084e, + 0xfbcccc5c, 0x368215d4, 0x3433d825, 0x822000ff, 0xdfff2804, 0x00ffcccc, 0x83cccc27, 0x85068324, 0x821b8316, 0x201082b4, 0x20068508, 0x842885ff, + 0x823c8232, 0xfcff232d, 0x49823433, 0xcc4cfc27, 0xb3ffffff, 0x84be8234, 0x66662109, 0x2020b982, 0xc42a0a83, 0xff05cc4c, 0xd04c0600, 0xa583ffff, + 0xb3fbff28, 0xf1ffff30, 0x0e826866, 0xf9231383, 0x820832b3, 0x6466240a, 0x83f9ffff, 0x2119833e, 0x38830400, 0xff201982, 0x21052e5b, 0x1982dfff, + 0xb33b0023, 0x84f58232, 0x33f32743, 0xffff8434, 0xfa8319ef, 0x6a82ed20, 0xff078b24, 0xc183b4fe, 0x66661731, 0x1800ff15, 0x00ffcd4c, 0x05666630, + 0x82feffff, 0x00002349, 0x09839a19, 0x09841482, 0x6666fd22, 0xd922b883, 0xb882d723, 0x29dcde22, 0x0d41d484, 0x20e68205, 0x24d782ff, 0x232100ff, + 0x241684d7, 0xdc2600ff, 0x212d8229, 0xe6832300, 0x991c002b, 0x1700ff99, 0x00ff66e6, 0x2a638307, 0x089a1920, 0xffff064a, 0x8266e6ea, 0xb5f3253f, + 0x1500ffc2, 0x08257083, 0x00ff71fd, 0x2b1c8212, 0x00ff068b, 0xffff7fb5, 0x9a990800, 0x7e839882, 0x98828d83, 0x9382b720, 0x33650023, 0x200a8233, + 0x224a82cd, 0x82b39aff, 0x7b00230a, 0x4e82ff7f, 0x9a19df24, 0x2e8214f7, 0x82993b21, 0x33ad23b7, 0xcd820534, 0x52227383, 0x2e82cccc, 0x00809329, + 0xf7af0e06, 0x8254f8b4, 0x82862022, 0x00ff22cb, 0x22288359, 0x82ccccdc, 0x33d32584, 0x075b0834, 0x0e40cc18, 0x07e58018, 0x6d484b20, 0x11806005, + 0x34fb8b23, 0x203c8205, 0x72bc82ee, 0x6b200f00, 0x1817a148, 0x23189c59, 0x54fb07ab, 0x19c6aa18, 0x74183685, 0x4a18071e, 0xab220a16, 0xaa18ff07, + 0x8b2215e1, 0xf68234f7, 0x820c6673, 0x1100253e, 0xcb0833b3, 0x57759c82, 0x83bb2014, 0xcc2c2218, 0x051b41cc, 0x3323002f, 0x8600ff34, 0x088b6666, + 0x94fb34fb, 0x18ea8615, 0x2610a752, 0x34f70604, 0x6104fb07, 0xb94a0e15, 0x072b2608, 0x156b44f7, 0x181f82f7, 0x20155d59, 0x228d87eb, 0x18b3f1ff, + 0x820c5f59, 0x82fb2052, 0xfb342258, 0x92571804, 0x62b4205d, 0x4b180db0, 0x988f1173, 0x2df85918, 0xe4f74b22, 0x0fb0a718, 0xd7f8ff2a, 0xffff8b0a, + 0x08f628f7, 0xff210685, 0x05385c00, 0xff0ad72a, 0xcdcc0800, 0x34f7088b, 0x200c5160, 0xb8da1800, 0xf8ff2310, 0x3582cccc, 0x82f62821, 0x34332d46, + 0xaf0e088b, 0x34f894f8, 0x0654fc15, 0x2009314f, 0x07314f9a, 0x6019dc20, 0x4f6209b1, 0x29338213, 0x98592300, 0x1c00ff8b, 0x048368a6, 0xe35f6620, + 0xf7082305, 0x098507d4, 0x4c204882, 0x1c206e82, 0xff203d82, 0x3805dc70, 0x9a99a8fe, 0x19fefeff, 0x00ff159a, 0xffa4b012, 0xae47edff, 0x801e00ff, + 0x22308200, 0x8214ae12, 0x52b82114, 0x210dcf55, 0x1a825c2f, 0x48610927, 0xa0f6ffff, 0x861a8300, 0xffff280a, 0xffb8feff, 0x82d0f0ff, 0x82198244, + 0xb89e221e, 0x844f8508, 0xe7ff2254, 0x27198370, 0xffffd8a3, 0x8bf668e7, 0x06831a82, 0x6e200c82, 0x09226582, 0x2a82e85b, 0x833e4a21, 0x8292206f, + 0xd4ed221a, 0x270a827a, 0xff813e0a, 0x32331800, 0x19237082, 0x85089a99, 0x00ff2406, 0x829a1909, 0x66262616, 0x051300ff, 0x2126821f, 0x86824821, + 0x5d822520, 0x04840020, 0xb8de3c22, 0x25212982, 0x22688263, 0x865c8fda, 0x20ac83bc, 0x879d918b, 0x221985a8, 0x83010000, 0xb89e21d6, 0x60206382, + 0xff23db82, 0x825c4fed, 0x52b8265f, 0x80e1ffff, 0x223e8200, 0x84ec51ed, 0x22a182d1, 0x8270fdf6, 0xc2f527e2, 0xf3ffff86, 0x1b8267e6, 0x3333f322, + 0xff24a182, 0x903433f3, 0x9d821283, 0x8221a782, 0x05476508, 0x20b35a41, 0x9f5a411e, 0xf72f0e26, 0x1534f854, 0x2c0b784a, 0xa4b0c6ff, 0xb9ffff8b, + 0xfb085c4f, 0x17bb4534, 0x440bf743, 0xf7200a25, 0x00283083, 0xffcc4c23, 0xcd4ce3ff, 0x27057f49, 0x33b3dcff, 0x14fb088b, 0x8307847b, 0xabf1211c, + 0x23d4b618, 0x4f14f821, 0xf72617b7, 0xfc6b0634, 0x167a1554, 0x20858b0b, 0x09d54594, 0x0e208583, 0x00217282, 0x77858311, 0x60660bbf, 0x0774230b, + 0x741814f7, 0xd3740c6c, 0xb4f7210a, 0x845d8589, 0x837c2005, 0x5ee21846, 0x083d5011, 0xff213083, 0x4a2b82b9, 0xfb240fb7, 0xaf0e0634, 0x26054d68, + 0x8b00800b, 0x110900ff, 0x0201aec7, 0x44f72208, 0xb71548fb, 0x8b075f06, 0x0800ff80, 0xff829a19, 0x66e60b00, 0x8b96088b, 0x968b9494, 0xb707b708, + 0x200a8606, 0x8219848b, 0x2625821f, 0x5f088b80, 0x8307b706, 0xcc0c2112, 0xf3211283, 0x2a128234, 0x19f4ffff, 0xffff8b9a, 0x8266e6f7, 0xcc0c2104, + 0xf4260a82, 0x5f0834f3, 0x76185f07, 0x78180ccc, 0x748e0ab5, 0xfb24fb24, 0x548215b0, 0x00801a25, 0x881500ff, 0x230e8204, 0x00ff088b, 0x16850683, + 0x80eaff22, 0x0e8ccd18, 0xff201183, 0x72180485, 0x59181047, 0xf8220ac1, 0x5f828b14, 0x2282ff20, 0x48822c86, 0x14b99318, 0x70835f83, 0x8dad0820, + 0x8baf0e23, 0x909c1af8, 0x06d32318, 0x784200ff, 0xbe003224, 0xff0666e6, 0x66e699ff, 0xe8ffff07, 0x00ff9a19, 0xe33e1917, 0x4bcb2c38, 0x0900ff05, + 0xffff6666, 0x18cdccf5, 0x290896da, 0x00ff0080, 0x0833330a, 0x1d82cbcb, 0x19330a21, 0x2216653d, 0x83f7ffff, 0x4c092628, 0xf0ffffcc, 0xb2d918cc, + 0xf6ff2507, 0x740834b3, 0xe6219882, 0x283c8266, 0x079a1966, 0xccb500ff, 0x21dc82cc, 0x23824c14, 0x33100023, 0x052b6634, 0x83faff21, 0x97eb3238, + 0xff55080a, 0xc2f53fff, 0xfcffff05, 0xffff9c19, 0x202083f2, 0x2d9283f3, 0xff0080f6, 0x32b3f1ff, 0xfeff088b, 0xca19e6c2, 0x072486d8, 0x4cfc74f7, + 0x7f5c2542, 0xe542066a, 0xff0e3b58, 0xcc4cf401, 0x4cdc00ff, 0x00ff15cd, 0xff9c990f, 0x6666f0ff, 0xe6ffff8b, 0x0a839999, 0x04836420, 0xfb086826, + 0x056cfb6c, 0x14860a84, 0x24821e82, 0x34842a82, 0xffff0826, 0xf71f0528, 0x60212284, 0x26128300, 0x00ff8b98, 0x82676619, 0x84a0200a, 0x089a260f, + 0xfad700ff, 0x200484e1, 0x21158205, 0x1a869a99, 0x2a822482, 0x98990f22, 0x60245882, 0x6cf70800, 0x05244a84, 0x54f7af0e, 0x1963e818, 0x5614f721, + 0x78180e72, 0x6b2208d0, 0x1a82bb07, 0x180bfe43, 0x2c088d87, 0xff0714fb, 0x68662c00, 0x33f1ffff, 0x27838233, 0xff303317, 0xcd4cf8ff, 0x2806b24e, + 0x793433e2, 0x99efffff, 0x27cc8298, 0xfffeff9a, 0xce4ca3ff, 0xef31f282, 0xffffcecc, 0xff32b3f6, 0x0080edff, 0x33faffff, 0x22248234, 0x828bcccc, + 0x66ec2625, 0xffff8b66, 0x222082ea, 0x82b30700, 0x82ed2016, 0x0c0025c4, 0x750832b3, 0x2c83db82, 0x0080e222, 0xe9222082, 0xdb8267e6, 0x82008021, + 0xccee2531, 0xf4ffffcd, 0xeb284283, 0xffff3333, 0xff6666f7, 0xcd203f82, 0xef224c83, 0x2b82cdcc, 0x00236383, 0x83cccc05, 0x22988263, 0x82686609, + 0xfd9a2735, 0x5c00ff70, 0x8d829899, 0x8f02ee25, 0x821000ff, 0x060026c3, 0x00ff9a59, 0x2429821d, 0xd7231700, 0x218082ff, 0xdd820833, 0x82f66821, + 0x33b32b7a, 0x0714f705, 0x1900ff8b, 0x04452a9c, 0x16002305, 0x1445d663, 0xbb083205, 0x1f00ff06, 0x6b079a19, 0x4c45ffff, 0x00ff15cd, 0x2243836b, + 0x56ffff23, 0x042707e5, 0x00ffce4c, 0x8234330e, 0x190d253f, 0xfbffff9a, 0x2585d082, 0x00dcff23, 0x33258201, 0x0733b35a, 0xff0694fb, 0xcd4ca5ff, + 0xff74f707, 0x33b31aff, 0x1a224782, 0x328266e6, 0xf7821c20, 0xcc0a0024, 0x8782a1cc, 0x82ce4c21, 0x19002392, 0x34828b9a, 0x66e60b25, 0x830800ff, + 0x8310201c, 0x4cff2c54, 0x0b00ffcc, 0xffff3433, 0x820080f6, 0x820e2025, 0xf4ff210f, 0x00211982, 0x83148412, 0x1912222d, 0x207d8298, 0x274483cc, + 0x87343311, 0xb30a00ff, 0xee262f82, 0xff8732b3, 0x1682eeff, 0xcc280684, 0xe6edffff, 0xf5ffff64, 0xef274083, 0x088f9c99, 0x83e7ffff, 0xcc052766, + 0xebffffce, 0x368232b3, 0xff23e082, 0x829a99f2, 0x6666267f, 0xffff6e08, 0x211f82f0, 0x0483dfff, 0x34b3f524, 0x31828b6a, 0xa482e020, 0x20062e4c, + 0x247a8209, 0x3433ecff, 0x20168294, 0x209083fa, 0x21398202, 0x4382faff, 0x83020021, 0x82fb207f, 0x02002137, 0x9b824882, 0xff210a82, 0x087265fd, + 0x8283fd20, 0xff213283, 0x821e84fd, 0x85822044, 0xf6ff2154, 0xff204882, 0x54826483, 0x6b84de20, 0x6666e02d, 0x4c0a00ff, 0x00ff6ecc, 0x8200800f, + 0x9ef22316, 0x805fffb8, 0xabeb2205, 0x20cf8285, 0x27eb8233, 0xffe17ae7, 0x3233faff, 0xee221e82, 0xef833dca, 0x4102cb21, 0xfb270606, 0x00ff3cfd, + 0x82343311, 0xfdfb221a, 0x830a8322, 0x75b321e9, 0x4c210982, 0x260482ce, 0x088f4035, 0x821200ff, 0x04002277, 0x221a8233, 0x4cb81e12, 0x0e27064b, + 0x00ff9a59, 0x8266e60b, 0x260b221e, 0x82148267, 0x100028c5, 0x00ffd723, 0x8334b300, 0xff672319, 0x9283f7ff, 0xba410020, 0x82162006, 0xf0ff2244, + 0x214482b3, 0x1b82661c, 0x9982f520, 0xe61a0024, 0x40828b66, 0x00801b25, 0x8200ff8b, 0x20958205, 0x20568299, 0x844b8316, 0x0b0021cf, 0x00223582, + 0xe582e607, 0xcccc0e22, 0x2207c764, 0x829a19f8, 0x82152035, 0xf0ff282a, 0x00ff0080, 0x8266661c, 0x830482ea, 0x088b2843, 0x2f0e068b, 0x837901ff, + 0x336d2786, 0x00ff1534, 0x3f822625, 0xb8de5c26, 0x0400ff05, 0x0a270a83, 0xffffae87, 0x82cc4cf8, 0x233482a6, 0xceccf3ff, 0xff318582, 0x061e85c6, + 0xe10600ff, 0x0e00ff48, 0x00ffcdcc, 0x24d18403, 0x9c8b3333, 0x27788208, 0xfff41d04, 0x022affff, 0xf0211782, 0x210982a4, 0x4c82709e, 0x82e40521, + 0xea272a87, 0x0800ffc2, 0x00ffead1, 0x20528319, 0x824d820c, 0xcc4c2141, 0x10273583, 0xffff7c14, 0x820040e0, 0x32332610, 0x70cfffff, 0x2f2a82a4, + 0xff08c2b5, 0x281cf4ff, 0xdc2b00ff, 0xedffff2a, 0x2d20e283, 0xff239782, 0x830080e4, 0x9ef52888, 0xffff8bb8, 0x4290c2f6, 0xf823061b, 0x8285703d, + 0xc0f02231, 0x24368200, 0xffffb81e, 0x212782ea, 0x0f83ffff, 0xe10b0023, 0x231a8248, 0x91af47f8, 0xb5833182, 0xb5820420, 0x99f5ff23, 0x83488399, + 0x265f824f, 0xffff3333, 0x820ad7d2, 0x9919263c, 0x2ed4ffff, 0x27318214, 0xff7b54cf, 0xce4cf7ff, 0x2b269d82, 0xf1ffff85, 0x7282aec7, 0x66e6ef22, + 0xff23b482, 0x82f6a8f1, 0x5c4f25cb, 0x35f3ffff, 0x2722da82, 0x2a82f6e8, 0x82c43521, 0x9eff2135, 0xfc227d82, 0xff821e05, 0x87f62822, 0xfb203182, + 0x7a253183, 0x780300ff, 0x066b4452, 0xae070622, 0x33214e82, 0x232d8233, 0x061f85c6, 0xae217482, 0x22288214, 0x828f42f8, 0x9a99240a, 0x830400ff, + 0x80f5238e, 0x97410800, 0xa3ff2805, 0xff054821, 0x828fd5ff, 0x5ee0216e, 0xe4235e82, 0x82594821, 0x19c72230, 0x278b839a, 0xffccccec, 0x1f850f00, + 0x23056e43, 0xd7231300, 0x012ad882, 0x06d6a37a, 0x331300ff, 0x1c828b34, 0x82062c42, 0x8210820a, 0x38002933, 0xffff66e6, 0xbd9a19e4, 0x71835682, + 0x991f2c08, 0xffff089a, 0xffcc4c36, 0x32b373ff, 0x00ff5b15, 0x059a19bf, 0x9b056bcb, 0xff6b056b, 0x66e680ff, 0x5f00ff05, 0x158b9a19, 0x82e0ffff, + 0x7f00213b, 0x9b241e82, 0xabcb05ab, 0xcf259882, 0xffff9a19, 0x20228440, 0x2f1b8230, 0x9a192501, 0xff768b15, 0xcccceeff, 0xeaffff7a, 0x23053a42, + 0x0686abf3, 0x8a21ff82, 0x2fb8823e, 0xff842bf2, 0xd7630a00, 0xa8faffff, 0x0e00fff6, 0xfe227c84, 0xf982c275, 0xff291c24, 0x8682fcff, 0x82020021, + 0xfbff2349, 0xcb829a99, 0x16850684, 0x83fdff21, 0x82fe206b, 0xfbff24cf, 0x820866e6, 0x22bd8240, 0x8266f1ff, 0x33f225cd, 0xf5ffff33, 0xef200e83, + 0xf3233585, 0x820685ab, 0xe1ba217e, 0xee327182, 0x8b9ccdcc, 0x00ff08a0, 0x07008010, 0x4c1c00ff, 0x4083ffcd, 0x1f00ff23, 0x200982cc, 0x213582fd, + 0x68432300, 0x82068305, 0x0ad72616, 0x620200ff, 0x212a820c, 0x96829042, 0x080c1722, 0x862cbc82, 0xef0e07e8, 0x805601ff, 0x1534f800, 0xb325b782, + 0x00ff8b34, 0x258c830d, 0xff34f3f7, 0xb2830600, 0xea11f323, 0x831a8208, 0x0ce626a6, 0x00ff05ce, 0x239c822f, 0x90822700, 0x05220a82, 0x4b82cccc, + 0x07210483, 0x272f8233, 0xffb89e02, 0x00800700, 0x0023e282, 0x47666614, 0x3b4d0f68, 0x182c5407, 0xc2ffff24, 0x35823433, 0x98193727, 0xe69affff, + 0x75445866, 0x9a99f02b, 0x991c00ff, 0xffff059a, 0x34ea82d8, 0xcdcce2ff, 0xe6e7ffff, 0xd1ffff66, 0xff8b9a99, 0xcccccbff, 0x20068208, 0x261182f5, + 0x9a190100, 0x82f4ffff, 0x02002125, 0xf5280983, 0xff0834b3, 0x9899b9ff, 0x1083c482, 0x4c0a002b, 0x0000ffcc, 0x00ff3433, 0x233b830b, 0x9a190a00, + 0x00213b82, 0x21318258, 0x1b83b9ff, 0x82994721, 0xb3a62740, 0x2b088b33, 0xd14eab06, 0x3a0f2508, 0x0e00ffe1, 0x10381f83, 0x088b1fc5, 0x666600ff, + 0x8b9c0667, 0x331000ff, 0xf9ffff33, 0x7f97cc4c, 0x2c221482, 0xdf656766, 0xffee2505, 0x34b35100, 0xef20af82, 0x00234d82, 0x82cc4c1e, 0x57c5200a, + 0x3f2932f8, 0x058b6666, 0x806900ff, 0x05f95700, 0x82b3dc21, 0x181c20b8, 0x203d1444, 0x46f783fd, 0xff2c05ea, 0xffff66e6, 0xff32b3fd, 0x34b3ffff, + 0x1c21bf82, 0x210a8233, 0xf957cccb, 0xcce32741, 0x3400ffce, 0xf6823233, 0xccf62108, 0xf4ffffcc, 0xffff68e6, 0xff0080fa, 0xccccf1ff, 0xf0ffff8b, + 0x8b080080, 0x3dffff07, 0x1573cdcc, 0xb3351e82, 0xc4ffff33, 0xff57cccc, 0x3433d3ff, 0x80c1ffff, 0xff088b00, 0x2dee59ff, 0x34823e20, 0x4085bf20, + 0x4c0b0023, 0x825084cd, 0x80bd3144, 0xffff0600, 0xff9999f6, 0x00801700, 0x1000ff74, 0xe5228683, 0x45189a19, 0x988310d4, 0x34b3dc23, 0x419f8208, + 0x45180567, 0x1a240fd4, 0xa28b66e6, 0x00234085, 0x84676609, 0xff082350, 0x61844200, 0x33336227, 0xff8b15a3, 0xe4df1a00, 0x09ba572a, 0x0f31c218, + 0x68574c20, 0xf70e2412, 0x8214f8d4, 0xdcff2361, 0x8a4866a6, 0x59e32306, 0x0e55ff9a, 0x20068206, 0x204f8233, 0x77f882e3, 0x3c550a8f, 0x1c002306, + 0x811a33b3, 0xed820f5e, 0x85181682, 0x6b210ce0, 0xaa47182b, 0x414c200e, 0x5b200712, 0x3e199152, 0x063433fe, 0x9cffff80, 0xff050080, 0x3233feff, + 0xccefffff, 0xf2ffffcc, 0xffffce4c, 0x8234b3f3, 0x32b3260e, 0xffff088b, 0x832782d9, 0x20a5830c, 0x21a583f2, 0x26824c0c, 0x8233fe21, 0x33102798, + 0xff800834, 0x42866300, 0x52063321, 0xbb201661, 0x00218582, 0xd2281923, 0x82cb2012, 0x451f2d31, 0x01ffff1f, 0xff15cc4c, 0xebd1fcff, 0x2106d26c, + 0x361a61fd, 0xfd2207cc, 0x138229dc, 0x08989922, 0x5e2a1e82, 0xfdffffb8, 0x00ff9a99, 0x33820500, 0x3433fb26, 0x9e0300ff, 0x08281385, 0xcf0800ff, + 0xfaffff5c, 0x0029c882, 0x857b540e, 0xd91300ff, 0x210f829a, 0x1a820080, 0xb85e272c, 0x3700ff81, 0xffffcdcc, 0x3f8219f8, 0x00803e22, 0x0020da82, + 0x16830683, 0x49ffcc21, 0x27230524, 0x82956866, 0xcc13212d, 0x05281082, 0x00ff0080, 0x9166660e, 0xcc265882, 0x0500ffce, 0x1a82cecc, 0x98990328, + 0x660200ff, 0xac458b66, 0xfcff2305, 0x0f846866, 0xfd209d82, 0x01203583, 0xff260f82, 0xff6666fd, 0x3f820100, 0x83fcff21, 0x84012039, 0xb3f022bc, + 0x82498232, 0xe8ff21bc, 0x00261982, 0xffce4c06, 0x5884e1ff, 0xf2211e84, 0x203382e6, 0x203d8302, 0x203d83f7, 0x8223830c, 0x83f68267, 0x8474826e, + 0xb3082811, 0xffff9832, 0x829a99fd, 0x8220208a, 0xfaff2122, 0x1c20cd83, 0x5f833684, 0x82191521, 0x66f5221e, 0x201e8268, 0x831e840a, 0x82092014, + 0xf9ff2165, 0x00217982, 0x205a8207, 0x05fe49ff, 0x0f820720, 0x83f7ff21, 0x66062a74, 0xff8b8066, 0x0080f2ff, 0x20068208, 0x07164aea, 0x4cf1ff23, + 0x831582cc, 0x19f72131, 0x0f826f82, 0xf620b182, 0xec200f83, 0xc0834684, 0xf382e920, 0xe6f9ff23, 0x20fe8266, 0x201483d3, 0x216f82f3, 0x6f83c3ff, + 0x34b3f828, 0x66beffff, 0x1a828b66, 0xff200683, 0xcd231682, 0x830700ff, 0x5ed32754, 0x0c00ffb8, 0x1a82ce4c, 0x82dee921, 0x8206200a, 0xecff23c4, + 0x1e829a59, 0xf1253f83, 0x00ff7b54, 0x26e38309, 0x0a57f2ff, 0x820800ff, 0xf0ff23a5, 0x55473d8a, 0x66152207, 0x21a98266, 0xe0820d00, 0x60060024, + 0x36829642, 0x82819521, 0x23a58326, 0xe17a0700, 0x2106cc41, 0x6f82cc09, 0xff22dc82, 0x13830a00, 0x6f830520, 0x07150023, 0x260f82ae, 0x00ff9899, + 0x82717d1c, 0x26c48233, 0xc3752000, 0x820500ff, 0x05da41c4, 0x59829a82, 0x83f7ff21, 0x66022d1a, 0xff087e67, 0x00800100, 0xf8ffff7e, 0xf320bb83, + 0xf2271b83, 0xffff67e6, 0x829899fd, 0xcce12fc0, 0xfaffffcc, 0xffff6866, 0xff5278e8, 0xc083f9ff, 0x4eb3f021, 0x083a0556, 0xaf0e068b, 0x666001ff, + 0xcc00ff66, 0xff153333, 0x862bceff, 0x809cffff, 0x29820501, 0x7fb2fd2c, 0x99eeffff, 0x0000ff58, 0x43824861, 0x82707d21, 0xb83e2179, 0xc7215382, + 0x22b9820c, 0x82ff5f7e, 0xf3e12125, 0xb8214a82, 0x22308340, 0x8267e69d, 0xcc0c262a, 0xb000ff05, 0x217f8266, 0x0a83cc49, 0xf6a80c2d, 0xeef2ffff, + 0x1400ff14, 0x828b32b3, 0x86ab2641, 0x110d00ff, 0x20b582ec, 0x227783b0, 0x823433b6, 0xe68f2746, 0xffffff66, 0x0a82acfe, 0xb81ee927, 0x342c00ff, + 0x27468287, 0xffcecc8e, 0xa5f0b400, 0xc9379882, 0x00ffd8a3, 0xffe0fa2e, 0x28dcacff, 0x85f7ffff, 0xffff5920, 0x82a470cc, 0x83ec208d, 0xabeb22f6, + 0x833b8284, 0x1400230a, 0x0a827c54, 0x0100ce27, 0x8f3300ff, 0x8230825c, 0x0800225b, 0x273a827a, 0xff299cc9, 0x2005d1ff, 0xc6203482, 0xce211983, + 0x254a825c, 0xff5278f9, 0x2383aaff, 0x0a572b27, 0x99c5ffff, 0x269a829a, 0x06000069, 0x832300ff, 0x405622b6, 0x228a8200, 0x820c8205, 0x48e126bb, + 0x261200ff, 0x24e682ea, 0x00ff703d, 0x230e8205, 0x4841f3ff, 0x3a272f82, 0xffffc235, 0x829a997e, 0x11312329, 0x0682edec, 0x4ee2052c, 0xc00b00ff, + 0x1000ff00, 0xf78260e5, 0xd8e30527, 0x40f4ffff, 0x262c8200, 0xff86ab1b, 0x83c0c8ff, 0x80792156, 0x23086783, 0xff146e2b, 0xcc6c3a00, 0x66f9ffff, + 0x5500ff64, 0xffff9a19, 0xff9c99c6, 0xd8a33100, 0x30fb0e08, 0xa4f704f8, 0x08e1c919, 0x3433b126, 0xcc4e00ff, 0x9e202c82, 0x28056050, 0x8bcdcc9e, + 0x33b1ffff, 0x20048333, 0x820a8234, 0x82082017, 0xbda92106, 0x3e20a382, 0xb82c4b83, 0x00ff2a5c, 0xff67e651, 0xccccf1ff, 0xdc28fc82, 0x5b0734f3, + 0xf7ffff06, 0x18086a7c, 0x210a9bc3, 0x3b82076b, 0x6c7c1982, 0x2a188205, 0x0800ff04, 0x088b04d6, 0x975b06bb, 0x06ab211a, 0x87202383, 0x0722e682, + 0x38847929, 0x34820a82, 0x07bb0823, 0x201a84bb, 0x201a8488, 0x201a8b78, 0x824c82ab, 0xff882158, 0x88206282, 0x78201883, 0x78229083, 0x9982088b, + 0x0c230024, 0xb28307cc, 0x00ff6623, 0x83ef830e, 0x470023c6, 0x46829a99, 0xcc4c562c, 0x2b44fb08, 0xcbffff15, 0xaa82ec11, 0x14eed425, 0x832b00ff, + 0x3400230a, 0xf88214ee, 0xf0340023, 0x821184a4, 0x5c0f2204, 0x211583ff, 0x0682088b, 0x82a4f021, 0x822b203d, 0xd4ff2111, 0xff230a83, 0x825c0fcb, + 0xcbff282d, 0xffff9a19, 0x8666e6d4, 0x260e8204, 0x2f0e088b, 0x82af01ff, 0xa0012317, 0x688266e6, 0x66668f29, 0xffff058b, 0x827a94ea, 0x45f5266f, + 0xe6ffff20, 0x20998226, 0x2304820f, 0x48e1f0ff, 0x1d275c82, 0xffff289c, 0x82a470e2, 0x59c72125, 0xc7224f82, 0x0a823473, 0x52f8e136, 0xa81400ff, + 0xdcfffff6, 0x00ff70fd, 0xff0a570a, 0x3e0addff, 0xff328d82, 0xff8f02d0, 0x84000000, 0x07d0ffff, 0xecffffae, 0x2482d88e, 0x4482dc20, 0x0cd92108, + 0xffff08cc, 0xffd723c3, 0x727dbcff, 0x350200ff, 0x94ffffc3, 0x00ff8e82, 0xffe4653f, 0x68e6beff, 0x232a6e82, 0xffff518d, 0xff5078db, 0xeb822d00, + 0x33eeff23, 0x4c098234, 0x2d220503, 0xe682b81e, 0x52382d2c, 0x2e1100ff, 0x2200ff14, 0x0482c275, 0x82b85e21, 0x1c3d2535, 0x3c00ff28, 0x06278983, + 0x00fff6a8, 0x822a9c5e, 0x68a6267d, 0x804400ff, 0x211e8200, 0xd382a638, 0xce8c3825, 0x8900ff05, 0x040031ce, 0xffff86eb, 0x91f428fb, 0xccfdffff, + 0x0500ffce, 0x0c226685, 0xbe57ce4c, 0x00ff2405, 0x829a9909, 0x660e220a, 0x23438266, 0x07cc4c71, 0x07200c82, 0xf82a9583, 0x00ffcccc, 0xff5c0f08, + 0x2c82f6ff, 0x442dd482, 0xfeff6666, 0x153433ab, 0x40edffff, 0x26048200, 0xffff3e4a, 0x82b85ee7, 0xd6a32120, 0x61220982, 0x25828b48, 0x8b201082, + 0x59820c84, 0x82e25a21, 0x703d2625, 0xb71200ff, 0x271a820a, 0xff0080da, 0x146e2500, 0x3c216182, 0x20ac82e6, 0x210f8425, 0x78825378, 0x82c01221, + 0xb512271a, 0x1800ffc3, 0x398248a1, 0x84285c21, 0x83508209, 0x21308210, 0x67839e18, 0x829ca421, 0x232a824b, 0x7849edff, 0x40833582, 0x82daff21, + 0xff4e22bf, 0x835c83ff, 0x0570430b, 0xe000ff25, 0x821566e6, 0x51373637, 0xe6ffffec, 0x00ff146e, 0xffae4731, 0x7c14d8ff, 0x4c2000ff, 0x213c82cc, + 0x98827d14, 0x1e821120, 0xb510002b, 0x1500ffc4, 0x00ff3cca, 0x2296830a, 0x829a1919, 0xa704221e, 0x300f82f0, 0xffff52b8, 0xffaa71f8, 0x862b0c00, + 0x73f4ffff, 0x29918232, 0xa4b0c9ff, 0xfaffff06, 0xe88276be, 0x7653fb2b, 0x2cfdffff, 0xfcffff08, 0x222b82f8, 0x82d6a3fb, 0xe8ee220a, 0x2c7482f5, + 0xff6f9e84, 0x84abf0ff, 0x33e0ffff, 0x22378333, 0x826626e0, 0x11e42a31, 0x1000ffec, 0xffffe23a, 0x226d83ee, 0x827a9418, 0xfafc3131, 0x0300ffe1, + 0xffff4676, 0xffcd4cfb, 0xf8d30200, 0x1f446082, 0xa3c92305, 0x7a8306d7, 0x3b823320, 0xa470f832, 0xd4f3ffff, 0x0400ff7a, 0xfffff6a8, 0x08ae47f5, + 0xe630a482, 0xe7ffff67, 0x00ff3eca, 0xff5ccf0f, 0x5c4fe9ff, 0x6321cd82, 0x225f82d7, 0x830816ae, 0xff7b25f2, 0xc2b5dfff, 0x23050641, 0x32b3ceff, + 0xc9224882, 0x63449a99, 0x33eb241d, 0x446b0734, 0x04200f63, 0x20055a44, 0x083c7c08, 0x21061c60, 0x1c60cccc, 0x06ab2206, 0x974d187b, 0x18072008, + 0x2012dc8a, 0x126344d6, 0x44079b21, 0x6344057e, 0x44042019, 0xfc200863, 0x82066344, 0x13002199, 0x24096344, 0xffce0c0f, 0x0a634400, 0x3233572a, + 0xff44fb08, 0x9a199fff, 0x22246744, 0x44f6282a, 0xf5211a67, 0x186744c2, 0xff74f826, 0xf2ffbf01, 0x8f236482, 0x82ff9a99, 0x05fa2c00, 0x9eeaffff, + 0xffff8bb8, 0x443e4af5, 0x5b180767, 0x1d220983, 0x67445c8f, 0xe3e42707, 0xe4ffffd8, 0x3082d6e3, 0x1e05e52a, 0xca1400ff, 0xdeffff52, 0x00224582, + 0x4a82d90c, 0xcc4cdb2f, 0xffff088b, 0x8b48a1a7, 0x5eb8ffff, 0x820484b8, 0x8310820a, 0x83b2208d, 0xf8362128, 0xbf2c3282, 0x00ff0080, 0xffae0749, + 0x9a19f1ff, 0xec223182, 0xb841aec7, 0xb8c91811, 0xffff2407, 0x4666e6e0, 0xc0851805, 0x41184046, 0xab2a1aa6, 0x000000ff, 0x00ff0506, 0xc641d608, + 0x00ff2412, 0x469a191f, 0x6b27172e, 0x1300ff06, 0x85075238, 0x0e0025c4, 0x00ff7ad4, 0x0029d883, 0x8b3e8a40, 0x6e4d00ff, 0x3def8215, 0x48611c00, + 0xfbf7ffff, 0x1a00ff64, 0xffff1f45, 0xffba09f3, 0xb81e1700, 0x1e00ff08, 0x04843473, 0x5d417c82, 0x0f002709, 0xffffec11, 0x1f82d7f0, 0x66e61927, + 0xb30a00ff, 0x224b8234, 0x82666615, 0x74702010, 0x5d720599, 0xcccc2605, 0x290700ff, 0x3b5b82ee, 0x088b3433, 0xfeff74fb, 0x150e00d0, 0xe3d3ffff, + 0xffff8bd7, 0xff291cdc, 0xd8e32300, 0x2c223b82, 0x8783281c, 0x11830682, 0x1684d720, 0x2c00ff25, 0x828b291c, 0x82158252, 0x83288222, 0x82282032, + 0xe3d32238, 0x212d82d8, 0x7b82d3ff, 0x19dcff23, 0x8316829a, 0x2c0e8204, 0xff0e088b, 0x9a99f201, 0xffbf01ff, 0x276782ec, 0x0648a1a1, 0x0aeeffff, + 0xff2dea82, 0xff8e02f7, 0x3e4aeaff, 0xb30c00ff, 0x21e38234, 0x5a82cc4c, 0xb81e1522, 0xcc271482, 0xffff05e2, 0x8470fdbc, 0x270a8204, 0xffc2b5e6, + 0x52b81000, 0x2006e24b, 0x22678309, 0x826666df, 0x83ff208b, 0x23168306, 0xf6ffffcd, 0xe6257483, 0xffff33b3, 0x7a4b83ef, 0x102805e2, 0xff05ce4c, + 0x9e0f0600, 0xde200483, 0x40210a83, 0x210a8200, 0xc1827e3f, 0xca210a25, 0x18f9ffff, 0x280816b6, 0x95a3f4ff, 0x440b00ff, 0x8571829c, 0x7e3f2615, + 0xdef5ffff, 0x83e182b8, 0x262a820f, 0xffff0882, 0x82ad07fa, 0x14ee2135, 0xef222582, 0x97823333, 0x6183cc20, 0x0a831520, 0x32331522, 0x0c206182, + 0xd385ce82, 0xc400f725, 0x821500ff, 0xeeff23bc, 0xad83080c, 0x0a97a129, 0xf8ffff06, 0x82ff7593, 0x82ec2000, 0xe7fb2646, 0xfbf9ffff, 0x296182fc, + 0x087493f8, 0xa1a1ffff, 0x0c820748, 0x3c0aee22, 0xc3263883, 0x02f7ffff, 0x4c82ff90, 0x56826782, 0x14820820, 0x34206785, 0x10216782, 0x20f482cc, + 0x237283ef, 0xa3f0f9ff, 0xf5214782, 0x82b986c2, 0x828420a9, 0xdef52245, 0x82ea8234, 0x200f82ef, 0x273b8200, 0xff5c4f0b, 0xa4b0f4ff, 0x82060541, + 0xff842515, 0x48210a00, 0x23067873, 0x7c3f0600, 0x2b412582, 0x82a02006, 0x3f102725, 0xefffffbf, 0x5682d2ad, 0x824cef21, 0xb3e62c6c, 0xf6ffff33, + 0xffff9919, 0x82cdcce1, 0x66df2260, 0x1e9d4366, 0x071ec528, 0x0000ff7b, 0x42825c00, 0x210bbf49, 0x3e82c2d5, 0x3e2af722, 0xf020f282, 0x2619a243, + 0xffffff9b, 0x4505ec20, 0x29210564, 0x10e349fc, 0x2005a243, 0x20bf8204, 0x491d8607, 0x9b2206c8, 0xa2439b07, 0x221f9209, 0x430f00ff, 0x042007a2, + 0x83107475, 0x60e621b0, 0x1322fe82, 0xa743e23a, 0x9920351e, 0xf6ffff99, 0x00ff0c22, 0xff00401e, 0xcc41efff, 0x4a1900ff, 0x0024d582, 0xff900243, + 0x46820483, 0x34331525, 0x4ceaffff, 0xb335055e, 0xf3ffff30, 0x00ff5238, 0x9434b315, 0xff089d8b, 0x285c5e00, 0x2bb58207, 0xff8c6c07, 0x9a19f9ff, + 0x040600ff, 0xf92e9282, 0x088b0080, 0x660dffff, 0xb0feff66, 0xa2431400, 0x4329201c, 0xd72008a2, 0x2615a243, 0xffff8b29, 0x43d7e3d3, 0xef2018a2, + 0x01b10b10, 0x44f82270, 0x19214deb, 0xfad83608, 0xffff8be2, 0xffea11dc, 0x6626f3ff, 0xd9e2ffff, 0xeaffff9a, 0xff089082, 0x48611200, 0x4cecffff, + 0x0e00ffcc, 0xffff5c8f, 0xff3ecae8, 0x14ae0900, 0x54e6ffff, 0x221e827c, 0x8216ae10, 0x82172019, 0x83152009, 0xd4082723, 0x1700ff7c, 0x4f4c0080, + 0xec11261c, 0xf0d4ffff, 0x200482a4, 0x224782ee, 0x825c0fcb, 0xe8ff242d, 0x828b146e, 0xf6a82b73, 0xde0800ff, 0xefffff76, 0x5882ae47, 0x08a92627, + 0x6df6ffff, 0x266e8292, 0xffffcd8c, 0x823a9ff1, 0xf6e82682, 0xb8edffff, 0x21968252, 0x78825c4f, 0xc4f51434, 0x82f0ffff, 0x1800ff8e, 0xffff3233, + 0xff34b3f4, 0x04821a00, 0xe6fbff23, 0x223d8266, 0x4d9a19dc, 0x854753cb, 0x3fcb4d12, 0x00ff6822, 0x21066749, 0xcb4dff98, 0xef0e240a, 0x824001ff, + 0xf30026cf, 0xff1533b3, 0x06854c00, 0xff05cd26, 0x2a9c1d00, 0x2a06ec48, 0xd6230f00, 0xcff0ffff, 0x4700ff5c, 0xcc27058e, 0x00ff8bcc, 0x4cce4c15, + 0x08390972, 0xffff88d6, 0xfff2d2f8, 0x12430600, 0x25f7ffff, 0xff088b60, 0x146e8fff, 0x1eb84d06, 0xff226387, 0x638263c7, 0x146ec730, 0xb8ffff05, + 0x00ff3eca, 0xff72fd30, 0x73829cff, 0xf8f6ff2d, 0xc3ffff50, 0xffffcc4c, 0x4d68a6bc, 0x7020099d, 0x20089d4d, 0x089d4d90, 0x91826420, 0x33b34436, + 0x6eb9ffff, 0x7100ff14, 0xffff9a19, 0xff4861ff, 0x00804500, 0x57210482, 0x271e82d0, 0xff500d3d, 0xe0ef3c00, 0x9924a982, 0x5e00ff9a, 0xff280482, + 0xff34b3d0, 0x99994400, 0xb2215c82, 0x236782cc, 0x15676658, 0x2707924c, 0xffffec91, 0x8b70fdc2, 0x82200f82, 0x25226882, 0x2582146e, 0x0a86da20, + 0xfd205e82, 0x0e4d8782, 0x05194d0f, 0xff156e2c, 0x90023d00, 0x2500ff8b, 0x3e82707d, 0x4ceb9121, 0x992109f3, 0x0bf34c8b, 0x7b01ff27, 0x01ff9899, + 0x07ee4e53, 0x2e283441, 0xffd8e3d4, 0xae07d4ff, 0xf2ffff05, 0x82070a17, 0x1ce125a4, 0xe6ffff2a, 0xe62ac483, 0x8b6c66e6, 0xfdffff08, 0x17826866, + 0x6666fd27, 0x660000ff, 0x850f8366, 0x271a8209, 0x075423fa, 0xec0600ff, 0xfb220a82, 0x098275f3, 0xff72a830, 0xa65bfbff, 0xee0500ff, 0xfaffff16, + 0xb188bc14, 0x82eb9121, 0x19c32244, 0x0716419a, 0x82ae8721, 0x1a474e34, 0x16b9fd22, 0xfd223082, 0x758206c1, 0x82027d21, 0x5eba2175, 0x28210982, + 0x363582fc, 0xffe85bf6, 0x5c4fedff, 0x8af3ffff, 0xeeffff7e, 0xffff3473, 0x82c475f0, 0x52782104, 0xf9241e82, 0xffffe6f0, 0x91210485, 0x218482aa, + 0x0e826c87, 0x82285c21, 0xcccc2109, 0x142c8e82, 0xffff7a74, 0xfff617f8, 0x00801500, 0xb321ad82, 0x21098234, 0xe9829a99, 0x7c4f0020, 0xfff82126, + 0x20077c4f, 0x097c4f64, 0x00ff6822, 0x21117c4f, 0x6082e4e5, 0xff6a1c26, 0xa0050600, 0xd026c282, 0x0500ff62, 0x6a83f8e8, 0x3c4a0c22, 0x0820ce82, + 0x0b228582, 0x844f68e6, 0x07a04a0d, 0x07a84f18, 0x28070030, 0xf6fffff6, 0x088bcc4c, 0x94f7ef0e, 0x615115cb, 0x0ffd4c0e, 0xdc5e5620, 0x33612405, + 0x52ffff34, 0x072acc6d, 0xffff32f3, 0xffccccf8, 0xdb830700, 0x3433f72d, 0xf73b088b, 0xffff1504, 0x52eb11cb, 0x1520254a, 0x521cfa45, 0xf823124a, + 0x4da4f754, 0x062005de, 0x3c27d94d, 0xff3473e7, 0x3273e7ff, 0xe2ffff05, 0x00ffae07, 0xfff8a814, 0xf628ddff, 0x630a00ff, 0x210982d6, 0x8482ec11, + 0xf0ff3308, 0xff8becd1, 0x8ec2f0ff, 0xc6fdffff, 0xf1ffff66, 0xffffe23a, 0x08d017fc, 0x8c0d00ff, 0xe9ffffcc, 0x00ff3233, 0xff204509, 0xa470e6ff, + 0xe4ffff8f, 0x1a82a4b0, 0x88160631, 0x2f0100ff, 0x0600ff1a, 0x00ff962e, 0x83dc9900, 0x82162009, 0x18003450, 0xff8b7a94, 0x0a971800, 0xa4f6ffff, + 0x1200ff9c, 0x51ffc4b5, 0x6e250727, 0xdaffff14, 0x22708391, 0x849819c3, 0x2204820a, 0x5108b087, 0xed2206c4, 0xb1823e4a, 0x51f66821, 0x6b2107c9, + 0x23508284, 0x3473e8ff, 0xe820a182, 0x00235082, 0x82fed408, 0x289c262a, 0x2d1100ff, 0x22358292, 0x827a14f0, 0x2cd2820f, 0x72fdecff, 0xbdefffff, + 0xeaffff70, 0x2264822e, 0x8200c0f3, 0x730b35a5, 0xfaffff34, 0x00ff1c1a, 0xff52b808, 0x1899f5ff, 0xcc0300ff, 0xf322d482, 0x1e82e07a, 0x64a61d2d, + 0x25ecffff, 0x2200ffa2, 0x82813433, 0xcc4c2105, 0x00236f82, 0x823e0a2d, 0x520582c0, 0x6b2107fa, 0x07fa5284, 0x70fd3c22, 0x8207fa52, 0x067d436a, + 0xfa520983, 0x8c182205, 0x52f982cc, 0x614f05fa, 0x04002308, 0x7d4394e3, 0xd4022b07, 0xcffdffff, 0x0500ff9e, 0x6a8364e6, 0xf0510c2a, 0x090000ff, + 0x0b00ffba, 0x02539682, 0x121e4e0c, 0xfffffc2a, 0x8b3433f7, 0x84f80e08, 0x3238ee4f, 0xff86abe7, 0xf6a8e7ff, 0xdeffff05, 0x00ff5c0f, 0x82a4f021, + 0xc0f9210a, 0x0628e282, 0xffff0040, 0xff34def5, 0x7c200082, 0x20057f4d, 0x251882ff, 0xe9ffff08, 0x0484b85e, 0x2109c54c, 0x2a838b00, 0xc54cb820, + 0x844a820c, 0x24258254, 0xff3e0aed, 0x820482ff, 0x75bb2c0a, 0x2f00ffc2, 0xffff524a, 0x826666a1, 0x32332655, 0x0cc3ffff, 0x210482cd, 0x5a829a19, + 0x1e45bb24, 0x0482ffff, 0x90274f82, 0x00ffae87, 0x82e2ba44, 0xce4c220f, 0x200a8308, 0x251a84e1, 0x786f00ff, 0x0f828b52, 0x8434b321, 0x411a821f, + 0x72200b87, 0x41070545, 0x12210987, 0x827382f5, 0x84052004, 0x229486df, 0x843f0600, 0xff8325d5, 0xcc210a00, 0xff21e382, 0x23be857d, 0x00400600, + 0x16245382, 0x00ff48a1, 0x34820482, 0x2e822983, 0x410a8a4e, 0xaf82051e, 0x28093441, 0x0a571800, 0x541800ff, 0x0ef14f7a, 0x485c0f21, 0xf14f0c62, + 0x44882013, 0x2921073e, 0x06d2416a, 0x23ffff2a, 0xfeff66e6, 0x15a8198c, 0x27071643, 0xffffec91, 0x8b9919c3, 0x87230f82, 0x4700ffae, 0x912106af, + 0x0dba54eb, 0x82156e21, 0x5378220f, 0x84058208, 0x2304830a, 0x8b66e63c, 0x78210f82, 0x08ab4752, 0x82666621, 0x4799200a, 0x992105ab, 0x320b839a, + 0xfb0e089a, 0xf774f730, 0x079e15b1, 0x00ff06a3, 0x82026b04, 0x94032733, 0x0300fffe, 0x0a83f893, 0x82a28521, 0xe6102354, 0x0c820766, 0xff311d82, + 0x026bfcff, 0xae0200ff, 0xfbffff98, 0x088bfe94, 0x83358273, 0x00ff241e, 0x8348a118, 0xf668210b, 0x08272982, 0x00ffc235, 0x600ad713, 0x0b2306e3, + 0x82089a99, 0x820720c6, 0xf83c23c0, 0x3a820552, 0x827b3421, 0x02cb256c, 0x39f8ffff, 0xfb22db83, 0x1483c335, 0x2582fe20, 0xe2fac222, 0x25822a84, + 0xb083f420, 0x002e0483, 0xff8d3708, 0xf628ecff, 0x671000ff, 0x91828b2c, 0x14ae1826, 0xf0ffff06, 0x80829782, 0x99858984, 0x8b209e83, 0x7b220a82, + 0x1e830864, 0xb6826820, 0x93fbff23, 0x82ce82f8, 0xfdff23d3, 0xe3856c52, 0xec820820, 0xf3ecff29, 0xffff0734, 0x829919ab, 0x48612429, 0x83c0ffff, + 0x9cb3226e, 0x26228228, 0xffffcdcc, 0x829082a5, 0xc8042268, 0x2e0a8273, 0x00ff5c4f, 0xff978e4d, 0x0a97b5ff, 0x5d5a00ff, 0xd38205a4, 0x4c620023, + 0x2bb882cc, 0x00ffcc0c, 0xff343350, 0xce4c4f00, 0x6220fd82, 0x2105ac61, 0x45824c56, 0x66e6c12f, 0x994700ff, 0xaeffff99, 0x00ff9a19, 0x271a820f, + 0xf3feff6b, 0xff1566e6, 0x0c238a19, 0x825c0f21, 0x0a342338, 0x0685083e, 0x21066d58, 0x78820f2b, 0xa4f03422, 0x3422f283, 0x1b8214ee, 0x104c2b20, + 0x20e48206, 0x060a54cb, 0xffc2f522, 0x21067258, 0x5482a4f0, 0x8b9a1928, 0xffef0e08, 0x9a826b02, 0x4ccb0023, 0x226882cd, 0x82f4a8ad, 0x299c22bf, + 0x21e98205, 0x858248e1, 0x54b81e21, 0xff23050d, 0x823e4af5, 0x9eea3649, 0xffff08b8, 0x07c2f5d8, 0x1cdfffff, 0xffffff2c, 0xbb059a19, 0x05535807, + 0x0c4b0020, 0x04d62105, 0x26065659, 0x8bde0ff8, 0x18066b08, 0x750baa57, 0x5b200aa7, 0xec224282, 0x1e8234f3, 0x14eef022, 0x23057459, 0xb85eb8ff, + 0x22051055, 0x8299aaff, 0xffff249c, 0x5a33f39d, 0x9e271464, 0x00ffcccc, 0x48cdcc4e, 0x61220629, 0xf8833333, 0x90425622, 0x4722f882, 0x4485d6a3, + 0x2805c359, 0x0866e651, 0x0c1300ff, 0x0c475acc, 0x2d507820, 0x21b28206, 0x7e50088b, 0x43062209, 0x0b2c5a96, 0x3000ff24, 0xdd8266e6, 0x00c02122, + 0xfb82ea85, 0x07cc0c22, 0x24050841, 0xd91900ff, 0x05305598, 0x1e0f0022, 0x0482b882, 0x52216982, 0x28048257, 0x052a9c4d, 0x4a0600ff, 0x21048240, + 0x9482c235, 0x34330a27, 0xb3f9ffff, 0x250f8234, 0xff083333, 0x0a8264fe, 0xb394ff23, 0x0edc4133, 0x44084f5a, 0x535a066f, 0xdf0f2105, 0x4106e541, + 0x2a240ce0, 0xffff862b, 0x2509535a, 0xe60000ff, 0x575aff66, 0x51cb5b15, 0x9a196c22, 0x21303157, 0x5c5b27f7, 0x190f2207, 0x0cf8569a, 0x562b5c5b, + 0xa22118f4, 0x21fd828b, 0xf456c4f5, 0x30fb2b18, 0x04f854f7, 0x9effff15, 0x2a827bd4, 0x852bb122, 0x270eb95c, 0xff7cd49e, 0x7bd44e00, 0x2b281682, + 0x6100ff84, 0x088b852b, 0x84210683, 0x8416838b, 0x827c201b, 0x2b61220a, 0x20638284, 0x13a74a00, 0xa4fb8b22, 0xcb225f82, 0x5f82cd0c, 0x33f3d427, + 0x0c2b00ff, 0x223182cc, 0x8334f334, 0x85342031, 0x83cd2011, 0x82048216, 0x835f830e, 0x20118506, 0x823282ff, 0x893e8238, 0x08da49c3, 0x66e6cb28, + 0xf80e088b, 0x9278f774, 0x61ee2206, 0x242b8248, 0xffb89ef1, 0x820482ff, 0x2310820a, 0x0714fb08, 0xa7180985, 0xf827100d, 0x00ff0654, 0x82b89e11, + 0x0ea7188d, 0x2333830f, 0x9a991100, 0x11b9a618, 0x0cfb1422, 0xf222ce82, 0x548200c0, 0x0040f523, 0x12da7dff, 0x85c00a21, 0x00ff2416, 0x8300400d, + 0x840683ce, 0xffff2128, 0x38823282, 0xce833e82, 0x086d0682, 0x28168206, 0xb3f2ffff, 0xcb088b34, 0x235edd8b, 0xfc150cf8, 0xff20f782, 0x214f2b41, + 0x2b41b89e, 0x48612907, 0x66eeffff, 0xfb088b66, 0x21232b41, 0x1941cccc, 0x0d002205, 0x20fd8233, 0x820684ff, 0x21168211, 0x5a19f5ff, 0x8b230872, + 0x84f2ffff, 0xcc4c2211, 0x411683ff, 0x5ebb292b, 0xf7ef0e25, 0x7754f774, 0x002a0cc1, 0x8b5c4f39, 0xb04600ff, 0x068508a4, 0xc6ffff25, 0x83ff34b3, + 0x18ff2016, 0x18094041, 0x77099942, 0xf67708ef, 0x21288205, 0x3282cd4c, 0x82a4b021, 0x05357743, 0x34b3322d, 0xffff155b, 0x0699999a, 0x83a0ffff, + 0xb2ff285d, 0xffffd763, 0x826666b2, 0x4ca02233, 0x1a9b6bce, 0x0634b327, 0x231300ff, 0x149b6bd6, 0x32b35f22, 0xff244584, 0x9a994d00, 0x4c2e5a82, + 0xff088bce, 0xcc4c5501, 0x065b15f3, 0x338207bb, 0x34330d22, 0x23057e42, 0xcccc0a00, 0x85065241, 0x09954206, 0x2206ac42, 0x825b075b, 0xccf2229e, + 0x200f82cc, 0x213684f5, 0x0a823333, 0xcdccf222, 0x06829e83, 0x2305c441, 0x3333f5ff, 0x6006f542, 0xf22206a2, 0xcd4134b3, 0xcc4c2107, 0x2005dd41, + 0x0be44108, 0x520a3e43, 0x0d2105d4, 0x2163824c, 0x36840a00, 0x6382b320, 0x4c0d0022, 0x06836383, 0x1b829585, 0x0b8e1e19, 0x34b31224, 0x404124f7, + 0xcdff2469, 0x42bbcc4c, 0x01285d12, 0xff68e661, 0x66e62000, 0x2f2d6682, 0x00ffb007, 0x05ae072f, 0x600900ff, 0x29048400, 0x0f00ff8b, 0xffff5c2f, + 0x0f83a0f6, 0x08486122, 0xff200a89, 0x2205df7c, 0x82b8feff, 0x839e2013, 0x00a02104, 0xd1251e82, 0xffff8c02, 0x234483d0, 0x52f8d0ff, 0x3f864f86, + 0x34835482, 0x308c8b20, 0x3b86f620, 0x0000ff24, 0x54854801, 0xff207e84, 0x08201882, 0x4f823f84, 0x0552f822, 0x04840584, 0x8f830a82, 0x8b0ac77c, + 0x5f092230, 0x215f827c, 0xb98384a0, 0xffffe025, 0x82f2fdff, 0x486121c9, 0x8a200483, 0x00234f86, 0x822a1c2f, 0x83ef83e4, 0x9e0a82a4, 0x1a0e4134, + 0x14eed022, 0xe327a482, 0xef0e05d6, 0x1834f8ab, 0x6d0f188b, 0xfb27070f, 0x74f70794, 0x6b34f706, 0x0e2308fe, 0x6bffcc4c, 0x112405fe, 0x088b34b3, + 0xc0231c82, 0x18ffb68b, 0x210a9abe, 0x2b8274fb, 0x4118ff20, 0xff201388, 0x8b201583, 0x08177418, 0x07ea7618, 0xfc07ab23, 0x6d411894, 0x3e9a7b0b, + 0x44fbcb2e, 0x00ff8b15, 0xff34332c, 0xcdcc2300, 0xb1820483, 0xe7492c20, 0x85068305, 0xdcff2316, 0x8b823433, 0x306dd320, 0x82d32005, 0x21118228, + 0x0485ff33, 0x8b230e82, 0x83ffff08, 0x83118506, 0x28548449, 0x2f0e0833, 0x54f8f4f7, 0x2c111915, 0x94fb210e, 0xd022f583, 0x2f8266e6, 0xffcccc25, + 0x8266d7ff, 0x19d23109, 0xf8ffff9a, 0xb908cecc, 0x8492055d, 0xf3ffff86, 0xf5201f83, 0x5c827882, 0x3233d928, 0xf7ffff06, 0x85820080, 0xceccf72d, + 0x660300ff, 0x08918566, 0x82c9ffff, 0x3600273a, 0xfb059a99, 0x0d850614, 0x05261283, 0xf8f9ffff, 0x31828552, 0xff29dc25, 0x8299fcff, 0x85f72259, + 0x22a5831e, 0x823d4ad8, 0x05f62227, 0x2548821f, 0xff0000fb, 0x76820c00, 0x0f07002b, 0xff08925c, 0x1f052e00, 0x273a82b9, 0xff3d0ad2, 0x32330700, + 0xd1269d82, 0x2800ffeb, 0xcd829a99, 0x9a192f24, 0xb783f708, 0x05350028, 0x2a00ff1e, 0x0483e1fa, 0x82ffe221, 0x8b1f210e, 0x06251982, 0x54fbb4fb, + 0x31558215, 0xffcd4cee, 0x7b540e00, 0xb3f1ffff, 0x1100ff33, 0x1e8485ab, 0x0ba34318, 0x190e0021, 0x20089e4b, 0xf86218eb, 0x18942018, 0x210c4a52, + 0x5718f1ff, 0x2b2308d6, 0x8234f707, 0x7494186a, 0x20aa8216, 0x28ad181a, 0x20af8229, 0x542d82e5, 0xea2005eb, 0x3c820983, 0xb6418b20, 0x417420ee, + 0xdb2017b6, 0x0c92bf18, 0x1a10b541, 0x2012c721, 0x0eb4413b, 0x0b4c4418, 0x14f76422, 0x7e0c037f, 0x2b200ad2, 0x21050544, 0x4418ffcd, 0x332707a3, + 0xb31100ff, 0x85088b33, 0x467b1881, 0x18819607, 0x250c7c44, 0x44fb063b, 0x9e1874fb, 0x94205d71, 0x5f719e18, 0xf754f834, 0xf4fb1514, 0x0714f706, + 0xfb06f4f7, 0x54fc0714, 0xa84424f7, 0xecd12109, 0x2607a844, 0x088b152e, 0x180614f8, 0x440b6cf0, 0x7b200aab, 0x0f194718, 0x07467918, 0x75454b20, + 0x837b2017, 0xccd32318, 0x4583ffcc, 0x0e820486, 0xfc088b22, 0x50186482, 0x342416af, 0x159bdb07, 0x220d7d4f, 0x828bcccc, 0x34332410, 0x4d34fb08, + 0x282109be, 0x065f52f6, 0x0ad70822, 0x7019b586, 0x3f46147d, 0x561a8205, 0x848210cd, 0xf7af0e34, 0x1514f7f4, 0xf70694fb, 0x94f70714, 0x0714fb06, + 0x0110f4fb, 0x3109011b, 0x1514f7b4, 0xf70654fb, 0x54f70714, 0x0714fb06, 0x0110b4fb, 0x2e09011b, 0x1514f754, 0x14f7062b, 0xfb06eb07, 0x10fb0714, + 0x09015103, 0xf764f823, 0x091719f4, 0x7242440c, 0x49ff8b21, 0xdb440684, 0x24fc2410, 0x181584fb, 0x20177655, 0x6d491814, 0x3433210e, 0x08234882, + 0x4408cccc, 0xac441c44, 0xfb0e2f19, 0x1700ff70, 0x34f8a430, 0x0500ff15, 0x4d8285ab, 0xe17a053d, 0xebfdffff, 0x0400ff84, 0xffff0040, 0x085438fc, + 0x021201ff, 0x0cffff90, 0x8205c275, 0x32b32b15, 0xccfbffff, 0x0200ffcc, 0x308234b3, 0x75f9ff21, 0xf320050b, 0xff231282, 0x669a19f6, 0x0e820668, + 0xff088b26, 0x67e689ff, 0x3827b282, 0xffffcdcc, 0x82cc4c8e, 0xe6072b3e, 0xf0ffff66, 0xffff3433, 0x2b8299f9, 0x3583ec20, 0x3333f023, 0x052872ff, + 0x0a851982, 0xecffff22, 0x00223382, 0x2d826606, 0x9919f827, 0xcc0f00ff, 0x204e82ce, 0x201483c5, 0x29488374, 0x4861adff, 0x80a1ffff, 0x8d820500, + 0x82ebd121, 0x21538404, 0xbc82c2f5, 0x82cc4c21, 0x66a6215d, 0xf3237f83, 0x828b52d8, 0x1f252891, 0xe60900ff, 0x82988b66, 0xeb7123cb, 0xe7820786, + 0x79820c20, 0x820a0021, 0x22048544, 0x82cdcc0c, 0x00002b2f, 0x0e068f02, 0x94f7b0fb, 0x8218156b, 0x852a09ee, 0x97f2ffff, 0xeeffff0a, 0x23827b54, + 0x97d9ff23, 0x261b820a, 0xffd8e3dd, 0x82591100, 0x85e827c3, 0x1a00ff1e, 0x9f8248e1, 0x1f85e82c, 0x1ee5ffff, 0xddffffb8, 0x3082d7e3, 0xbe82a620, + 0x1a822e83, 0xff293c83, 0x85abf1ff, 0x4f0e00ff, 0x2080825c, 0x1c351910, 0x0e002309, 0xe2827b54, 0x4ac23521, 0xff24063f, 0xcd4c2300, 0x1c262282, + 0x00ff33b3, 0xc282b81c, 0x47230025, 0x18eb08ae, 0x180e856d, 0x760a5547, 0x48830851, 0x097b0119, 0xeb06ab22, 0x3c82eb83, 0x75ffff21, 0xb82605f3, + 0xdcffff52, 0xc78333b3, 0x11209190, 0x82059350, 0x05d14a06, 0x9188a883, 0xf6682622, 0x22226482, 0xd685291c, 0x7a170023, 0x21ea84e2, 0x0a82ff08, + 0x00ffe127, 0xff48e11a, 0x251e8300, 0x9a591100, 0x2e8300ff, 0x98181a82, 0xb0210b50, 0x488418a4, 0x48851810, 0x8598850c, 0xe3ff23a8, 0x2d82ae47, + 0x52b8dc27, 0xab072b08, 0x0a581806, 0x22489f0d, 0x822b066b, 0x82ff20f5, 0x00ff243c, 0x8233b31c, 0xae472151, 0x83055241, 0x49fc8291, 0x4f180877, + 0x0e25073a, 0xf714f7af, 0x179777b4, 0x107a4218, 0x770ae649, 0x3422099c, 0xa818ffff, 0xfb2109db, 0x179d7614, 0xf707eb24, 0x7e18fb34, 0x48180dec, + 0xab220acf, 0x7d7bcb07, 0x24ae830e, 0xcd4ceeff, 0xd4b51808, 0x206b930b, 0x133d4ecc, 0xfb06ab3d, 0xc800ff94, 0xff159a99, 0xb8deecff, 0xf3ffff96, + 0x00ff4821, 0x8bc2b514, 0x411700ff, 0x6c1905ef, 0x1c8413fd, 0x14222282, 0x3284c3b5, 0x3e823882, 0x01ff082a, 0x06343351, 0x1300ff96, 0xb3264584, + 0x0c00ff32, 0x2c82b8de, 0x1834b321, 0x230dfc7d, 0x9a59e3ff, 0xdc238f82, 0x820866a6, 0x4fe82206, 0x2645825c, 0xffff9819, 0x823e4aeb, 0x68e62988, + 0xfeff0880, 0x07ccccee, 0x19224982, 0x45828098, 0x8268e621, 0xce4c211c, 0x4c212c83, 0x213383cc, 0xe482b3dc, 0xcc4ce324, 0x0484ffff, 0x61820e82, + 0x4ce8ff23, 0x222282cc, 0x83ce4ceb, 0x82662032, 0x19132238, 0x244a829a, 0x06ccccae, 0x20588380, 0x21458266, 0x6c833d4a, 0xffff9a22, 0xbd797682, + 0xff9a210b, 0x820a6841, 0x821720db, 0x20be8561, 0x82c88314, 0x829620d2, 0x331122e0, 0x22958234, 0x82676657, 0x666626d5, 0xfaffff15, 0x20548266, + 0x218883f6, 0x0982e6f7, 0xa983f720, 0xcd4cf622, 0xc5881884, 0x33b30922, 0xff231084, 0x82190800, 0x22248379, 0x82990500, 0x41388209, 0xff200635, + 0x00211084, 0x22758309, 0x83981908, 0x84048229, 0x8729820e, 0x82ff2079, 0x20298530, 0x834484ff, 0x83828429, 0x25e98638, 0xffabef0e, 0xd3414801, + 0xd1002148, 0x823ad341, 0x06d341e2, 0x08806625, 0x418effff, 0x9a2606d3, 0x0c00ff80, 0xd34166e6, 0x2eff213a, 0x2748d341, 0x34337100, 0x158bcb07, + 0xac419e87, 0x41672006, 0x662008ac, 0x29067141, 0x08cd4cf6, 0x33d100ff, 0xac410634, 0x41332008, 0x082306a7, 0x41ff9a19, 0x052205bb, 0x24829999, + 0xff205283, 0x841eac41, 0x1e4042c2, 0xff078b2c, 0x6666d700, 0x6697feff, 0xc2421566, 0xce4c2108, 0x2307c242, 0x088bcc4c, 0x420b1845, 0xe62013c2, + 0xc242bf82, 0x9a192205, 0x279b8296, 0x079a9928, 0xffff06cb, 0x5d825782, 0x34b30922, 0x21089a42, 0x5542ff98, 0x099a4205, 0x3220ed82, 0x9c20ed84, + 0x9a42de86, 0x9b002013, 0xff642ced, 0x9a990a00, 0xd1ffff08, 0x820668e6, 0x9a992e69, 0x800e00ff, 0xf6ffff00, 0x00ffcccc, 0x2109830d, 0x138219f4, + 0x34b30a22, 0x19229b82, 0x9382cc4c, 0x9899482c, 0x00ff9606, 0xff343312, 0x9f821400, 0x830d0021, 0x4417202b, 0xe2261045, 0xff8b6666, 0x9e72ddff, + 0x66e72205, 0x07454467, 0x44cd4c21, 0x71420745, 0x33454408, 0x0c219f82, 0x084544e6, 0xcc2eff2d, 0x2f0e06ce, 0x34f824f8, 0x82f4fb15, 0x7de522ca, + 0x257d8271, 0xff8f82ea, 0x4818eaff, 0xf4200952, 0x07b7be18, 0x7d150023, 0x82198271, 0x1a0024e0, 0x828b8f82, 0x80f529dc, 0x00ff0600, 0x8b52f810, + 0x472b0582, 0x0600ffae, 0x00ff76be, 0x8290020c, 0x8a012104, 0x5a212082, 0x820a8282, 0x82052004, 0xac072110, 0x0a210482, 0x2124823c, 0x2e8234b3, + 0x8b343323, 0x8242859c, 0x2050825f, 0x2f5a8690, 0xff707d15, 0x0080e5ff, 0xe4fb088b, 0xd4f7154b, 0xff2a9782, 0x74fbbeff, 0xc0ffff05, 0x0d824200, + 0x7a54ee22, 0xf121a582, 0x1f6319ab, 0x074b2c0c, 0xf70674fb, 0x8b0e07d4, 0x821574f7, 0x050e7d8d, 0xff66a624, 0x6d831c00, 0x9a59232a, 0x06cb088b, + 0x8b0714fb, 0x0d4f2519, 0x0614f723, 0x207f824b, 0x137d45ff, 0xff205182, 0x0a987318, 0x270a8942, 0xf70774f7, 0x1514fb74, 0x8216a842, 0x2182831e, + 0x8e479a59, 0x1c002105, 0x23268783, 0x088bcd4c, 0x4f1874f7, 0x35460cd8, 0x0529550a, 0x0e2b8696, 0x2a02ffef, 0x01ff68e6, 0x82008025, 0x61ee3474, + 0x2300ff48, 0xffff0040, 0xff0080cd, 0x48210000, 0x83eeffff, 0x9edc270e, 0xff3408b8, 0xf28351ff, 0x82e60221, 0x660826fc, 0xffff8b66, 0x05976ff0, + 0xb8ded325, 0x843900ff, 0x26318227, 0x02c04600, 0x82ff088b, 0x82002006, 0x593822ac, 0x21528298, 0x0a8248e1, 0xb81e2c3a, 0xffffff08, 0x00ffe811, + 0xff9a1910, 0xd04c0200, 0x99f8ffff, 0xa9ffff9a, 0xac226d83, 0x1e82cccc, 0x32338c25, 0x835affff, 0x47002c8d, 0x24f7c2f5, 0x4800ff05, 0x82fb842b, + 0x6fff2b07, 0xff06bade, 0x66e648ff, 0x4d82157b, 0x821e1021, 0x60012174, 0xf821ab82, 0x21a682a1, 0xba8281a9, 0x00c0ac23, 0x89b18208, 0xff7f21c5, + 0x6722c599, 0xc59b00ff, 0x9ad94522, 0x0683c583, 0x3a00ff24, 0xc582d623, 0xf382e620, 0x192c0023, 0x2563829a, 0xf766e67f, 0x9b821534, 0x85343321, + 0x28dc279b, 0x4700ff06, 0xb183a4f0, 0x826f0121, 0x15a43015, 0xe670ffff, 0x01ff0666, 0x0734b326, 0x831700ff, 0x4c0a25e3, 0x1100ffcc, 0x0026f282, + 0xff343315, 0x0e830500, 0xf7831920, 0x99710024, 0x1a82069a, 0x8284ab21, 0x6e0d25da, 0x0e00ff14, 0x0f5d6c18, 0xabf1ff23, 0x24168484, 0x3aefffff, + 0x219b82e2, 0x33837fff, 0x83f1ff21, 0x821320ee, 0xe9ff2d04, 0x00ffb81e, 0xffb89e0c, 0x48e1e5ff, 0x06832083, 0xe8ffff27, 0xffff723d, 0x202083f3, + 0x236f82f2, 0xb89eecff, 0x3b84c083, 0x184cee21, 0x211680cc, 0x6a827c54, 0xffcd4c22, 0x10207485, 0x8505d34b, 0x400525a3, 0xe6ffff00, 0x00280482, + 0xffb99e11, 0x00c0eaff, 0xff2adc85, 0x0800c0f5, 0x40d9feff, 0xf9820700, 0x0614ee22, 0x7d228682, 0x7d438b70, 0x0af74305, 0x3205ec76, 0x2a0700ff, + 0xf8ffff3e, 0x00ff04d6, 0x8bc3d508, 0x1834f808, 0x180c7c78, 0x260a41a4, 0x020000ff, 0x5500ff90, 0xe4280e9d, 0x088b9a99, 0xf730fb0e, 0x1a64b118, + 0xee206a82, 0x12c86d18, 0xf5ffff25, 0x82071e05, 0x94d5341c, 0xefffff7c, 0xffff9a19, 0x6dcc4cd7, 0xffff086d, 0x823333bc, 0x9a192604, 0x4300ff05, + 0x20fe82cc, 0x260a82bc, 0x00ff6da9, 0x8466e610, 0x23348324, 0x80089a99, 0x4a0f2053, 0xc54a07ff, 0x54d42017, 0x6f4c0cdf, 0x82962021, 0x2a00239e, + 0x79826666, 0xff29dc29, 0x34b32800, 0x8208a9a9, 0x0ad72193, 0xe6220482, 0xa4820566, 0x85f62821, 0xa96d210a, 0x2321c382, 0x2b2484d7, 0x2a00ff8b, + 0xff08846b, 0xe2fa0a00, 0x0e275a18, 0x200d4e42, 0x07984c86, 0x4c7a5421, 0x08210512, 0x20a283f7, 0x24e682a3, 0x66e68efe, 0x215f8215, 0x5f829a19, + 0x83cecc21, 0x9919216a, 0x33270f82, 0x79790532, 0x82f5ffff, 0xe7ff2322, 0xe9820080, 0x9a99e628, 0xf7078008, 0xad840654, 0xad821920, 0x00281d84, + 0x79008018, 0x078b089d, 0x019d0110, 0x190f354f, 0x1514fb9a, 0xe6a000ff, 0x00ff0666, 0xff66660a, 0x9a990f00, 0x24066149, 0x8b846b12, 0x06f9419e, + 0x0654fb22, 0x2006e342, 0x281d8578, 0x7c94edff, 0x800900ff, 0x06b34500, 0x8794fb21, 0xfcff2146, 0x00281482, 0x87cc4c05, 0xfbffff90, 0x04235283, + 0x41089a99, 0x208515fe, 0x87212583, 0x260b8286, 0xffff9999, 0x1034b3fa, 0x5201e801, 0x9a191c33, 0x1971ffff, 0x00ff159a, 0xff67e643, 0x3333bcff, + 0x200a8305, 0x27048266, 0x9d05cdcc, 0x0a00ff9d, 0x00272282, 0x8b008018, 0x431900ff, 0xf74108f1, 0xffff2409, 0x857c94e6, 0xe7ff2a25, 0x799d0080, + 0x30fb0e08, 0x1452188b, 0x1854200b, 0x210cd3a1, 0x2d4fd4f7, 0x1452180e, 0x43051008, 0xeb221401, 0x4446156b, 0x0f684108, 0x2331b341, 0x1514fc8b, + 0x43174545, 0x88451589, 0x2f0e2514, 0xc4f754f8, 0x87329882, 0x8b079a99, 0x33ceffff, 0xe6ffff32, 0xffff9a99, 0x048219d4, 0x6666d922, 0x19250e82, + 0x14fb089a, 0x05065907, 0xffff2608, 0xff5ccfca, 0x84ab2600, 0xe5ffff05, 0x00ffa430, 0x7bb08713, 0x801f00ff, 0x00ff8b00, 0x08981921, 0x334500ff, + 0x354b8234, 0x7c940e00, 0xa00600ff, 0x0d00ff00, 0x00ffcccc, 0xff9a790a, 0x20840900, 0x67e61e27, 0x051800ff, 0x22428220, 0x590080d2, 0xff2417b5, + 0x0ad70800, 0x0851b218, 0x091cac18, 0x30821420, 0x851a0027, 0x1500ff1e, 0x255c8280, 0xffe27a15, 0x7e821a00, 0x19227982, 0x30824861, 0x7a941426, + 0x3aecffff, 0x01271682, 0xffffc3b5, 0x823c0ae7, 0x8708261a, 0x0700ffae, 0x2a9282d4, 0xffcd4c0b, 0x66e60400, 0x850c00ff, 0x853c8335, 0xeaff244c, + 0x828b1e85, 0xe27a28d7, 0xfaffff08, 0x82071078, 0x82992083, 0xf60c27b6, 0x0e00ff04, 0x0e8232b3, 0xffec9124, 0x2b4d1000, 0x78172205, 0x276d8252, + 0xff527813, 0x4821efff, 0x2b265382, 0xe9ffff84, 0x6d82e0ba, 0x3e4a0722, 0x70210f82, 0x833082a4, 0xb30222a3, 0x20fb8334, 0x2a59189a, 0xf80e2718, + 0x15d4f774, 0xda8264fb, 0xf39eff28, 0xb1ffff34, 0x0486cc0c, 0x36820e82, 0x47daff29, 0xffff06ae, 0x827b94ca, 0xb8cd269f, 0x1400ff52, 0x202182cc, + 0x26cb83da, 0x08b0c725, 0x838effff, 0x197128d1, 0xffff059a, 0x824120f8, 0xead12beb, 0x18fcffff, 0x0a00ff10, 0xae69cc4c, 0x82082005, 0x4c152606, + 0x1100ffcc, 0x20fd8226, 0x20948312, 0x05b24a16, 0xe13a0a22, 0x0a221b82, 0x3286713d, 0x5ccf0722, 0x2f214682, 0x20ca829e, 0x296c823b, 0xec51c4ff, + 0x1701ff05, 0x5c186666, 0x24541777, 0x083f5f0d, 0x0000ff27, 0x44fbaa12, 0x26078205, 0xfffff006, 0x823333f7, 0x99192198, 0xcc245b82, 0x0800ffcd, + 0x8305234a, 0x21168206, 0xa76a1f45, 0xffff260c, 0x64f714ee, 0xebb91805, 0x0d7c4408, 0x2507f74a, 0xff7c540e, 0x7944f1ff, 0x22678208, 0x83fb640c, + 0xf7ff2335, 0x4f82fc29, 0x4a6a1c21, 0xd6220730, 0xcd828bca, 0x06820820, 0x29211682, 0x2004829e, 0x6bb31833, 0x44f72108, 0x84256785, 0x540e00ff, + 0x05314b7a, 0x82110021, 0x19318255, 0x6009584b, 0xd7870a17, 0x2108984a, 0x67884c17, 0x6785c820, 0xb982c820, 0x82280721, 0x8807204c, 0x04f72167, + 0x9a0a3e41, 0x08e25466, 0x94f80e2a, 0xff1594f7, 0x66e690ff, 0xff283982, 0xff34b3af, 0x6666bfff, 0xb02b0486, 0x088b9a99, 0xffff063b, 0x82e27ae5, + 0x85ea2588, 0x1500ff1e, 0x00240a83, 0x088e821a, 0x09317e82, 0x00ffea26, 0xff6fb202, 0x3e750800, 0x710400ff, 0x2cf58227, 0xff08b047, 0xd0c2e9ff, + 0x050500ff, 0x05ca4a1e, 0x82120021, 0x00ff2449, 0x83008017, 0xb8102235, 0x2b308252, 0x00ff9e8f, 0xff14ae0e, 0x81f50c00, 0xb3213582, 0x23358234, + 0x06e17a42, 0xe8203b82, 0x0fbfdb18, 0x830b1721, 0x17162737, 0x1100ff0b, 0x0482f6e8, 0xff8e022d, 0x0a171600, 0x00ff088b, 0x820080e5, 0x802e2c33, + 0x4300ff00, 0xff05289c, 0x82eeeeff, 0x66052c54, 0xf5ffff68, 0x00ff5c0f, 0x8232b30f, 0x6e1120a9, 0x03270535, 0x00ff16f9, 0x82c19800, 0x800a2cab, + 0x410100ff, 0x0300ff1a, 0x8208fafe, 0x9a5921ab, 0x11215782, 0x2e3082ec, 0x00ffe1ba, 0xff50f80a, 0xe2fa1000, 0x828f088b, 0x1204273d, 0xffffff2d, + 0x36823a64, 0xffdd0432, 0x32b8feff, 0x1701ff08, 0xffff3433, 0x05aec7a8, 0x9b214782, 0x201f82e6, 0x21518375, 0x09829a99, 0x82cecc21, 0x82f28213, + 0xcf062257, 0x224082e0, 0x82d84e06, 0x8260203b, 0x260227a3, 0x0600ff66, 0x1a82e0da, 0x707f0022, 0x96212682, 0x21918288, 0x09829e3c, 0x82649b21, + 0x94012229, 0x27eb83fc, 0xff98ce06, 0xac9cfbff, 0x50312b82, 0xf9ffff22, 0x00ff7228, 0x08462102, 0x75b7ffff, 0x21fb82c2, 0x768286ab, 0x3e4a0e22, + 0xd921b382, 0x210a829a, 0xaf821309, 0x605a0b22, 0x25060b45, 0xff46a106, 0x81830e00, 0x8206bb21, 0xd86321cc, 0x0a265982, 0xffff0a17, 0xf182a4fc, + 0xea510822, 0xc4215282, 0x27838258, 0xfff66826, 0xc435e3ff, 0x19204282, 0xed20cf83, 0x00322482, 0xff7a540f, 0xa4f0e2ff, 0x050300ff, 0xe0ffff1e, + 0x298214ee, 0x72bd0022, 0x8f213e82, 0x21ad82e0, 0x09820080, 0x8b008022, 0x662e0582, 0xf80e0866, 0x7600ff94, 0xff1566e6, 0xe16c99ff, 0xfc292106, + 0x2c05ac42, 0x04d6f8ff, 0x29f7ffff, 0xfb088bfc, 0x61441814, 0x0a4a4d0c, 0xff079b2d, 0x84abaaff, 0xffff05cb, 0x82166e54, 0x87ef2225, 0x225a82ae, + 0x82ae07f1, 0xa4702ccc, 0x7affffff, 0x1000ffe1, 0x8208c275, 0x82ba200a, 0x4c24250a, 0x1d00ffce, 0x1d28a883, 0x00ffcccc, 0x8bd72323, 0x68229f82, + 0xea8267e6, 0x1fc50d22, 0x0c21ea82, 0x2726823a, 0xff9ecf08, 0x285c0400, 0x11214582, 0x232082aa, 0xab86ab0a, 0x072ae682, 0x00ffb8de, 0xff52b814, + 0xc782f0ff, 0x66150028, 0xeaffff66, 0x42823433, 0x804bff29, 0xffff0600, 0x829ad9dc, 0xebe2247e, 0x8400ffc7, 0x2a01245f, 0x8200ff09, 0x22428273, + 0x84fd8600, 0x00ff2389, 0x9d86f70e, 0x910f0023, 0x233b82ec, 0x34330f01, 0x1a227e82, 0x7e829042, 0x7a941826, 0x1ef3ffff, 0x0e226782, 0x5d8234f3, + 0x82f66821, 0x8280203b, 0x46ff23ab, 0x828266e6, 0x281c0a28, 0xc5f1ffff, 0x83829020, 0x82981921, 0x99f0306c, 0xaf0e089a, 0x991f02ff, 0x3f01ff98, + 0x82156666, 0xff083144, 0xf9ffffbe, 0x00ff90e2, 0xffbc9417, 0x5c6fe6ff, 0xff236682, 0x8266e6f1, 0x14f32c2f, 0xf6ffff7c, 0xffff10ad, 0x829819fc, + 0x94c3324a, 0xddffff08, 0xffffd6a3, 0x0568e682, 0x51feffff, 0x2b3b8268, 0xffff0ad7, 0xff3268fa, 0xe2bafbff, 0x9d210e82, 0x22408370, 0x82de04f8, + 0xd2f92740, 0x0600ff2c, 0x67829c84, 0xac9c0723, 0x2c068208, 0xff02fc00, 0x781a0000, 0x000100ff, 0x210982aa, 0x09826037, 0x824e0221, 0xb52327b8, + 0xa600ffc2, 0xb8829a99, 0xf6850027, 0x710200ff, 0x211f8228, 0x09822e41, 0x82107821, 0x73022239, 0x22408374, 0x82d8e30d, 0x144e2b93, 0xf81200ff, + 0xe9ffff50, 0xaf84b8fe, 0x82c23521, 0xabf2276e, 0xf5ffff86, 0xaf8272bd, 0x82aec721, 0x52f821f4, 0xda21af82, 0x2295823a, 0x82cccc4f, 0x31fd21af, + 0xf226af82, 0xffff66e6, 0x3b826df4, 0x82a3f621, 0x9cf2224a, 0x2140832a, 0x4083f5f2, 0x1182f420, 0xde080023, 0x824082fa, 0x0c0023d5, 0x408225a6, + 0xd7e3cb27, 0x7fd000ff, 0x294082ff, 0xfff338fc, 0x58e40d00, 0x4583ffff, 0x330b0028, 0xf1ffff8a, 0x40839a19, 0x3e4ae522, 0xfa278182, 0xffff14ee, + 0x823c4ae6, 0xbaf9220a, 0x23af82e2, 0x566efdff, 0x4f26c682, 0xfdffffab, 0x09829663, 0x8287a621, 0xdc642109, 0x3227f082, 0xffffcd8c, 0x83cecc35, + 0x8c3b26f0, 0x11ffffff, 0x211f82e5, 0x0982491c, 0x82f81221, 0x17ff2240, 0x3140838d, 0xfff2f2f9, 0xc916fbff, 0xc7faffff, 0xf9ffffef, 0x6e836a9c, + 0xa01afb22, 0xfb312282, 0x00ff79a9, 0xff6d2703, 0x767efeff, 0xa80400ff, 0x27af8272, 0xffe443d1, 0x66499000, 0xfb32af82, 0x00ff0080, 0xffcccc0e, + 0x9a19f3ff, 0x140900ff, 0x3c837d7c, 0xeb51f022, 0xf0213c82, 0x227f820c, 0x82842bf3, 0xdcec220a, 0x226a832a, 0x821cbafc, 0x83812181, 0xab26fe82, + 0x0100ffc8, 0x09826910, 0x82ceb721, 0x834520ab, 0x4c2822d7, 0x21ab83cc, 0xa182514a, 0x82e81a21, 0x34222129, 0x21210982, 0x22408200, 0x83022bff, + 0x7afb2240, 0x213182a0, 0x04825c0f, 0xff229b26, 0x2dd2fbff, 0xfe226e83, 0x22826f12, 0xa105fe22, 0xb8213282, 0x21ab82ce, 0x5c824055, 0x8286aa21, + 0x99c327ab, 0x3c00ff1d, 0xab822666, 0xfca9f72c, 0x560800ff, 0xf4ffff04, 0xcb82bcb4, 0x82b48821, 0xebd12109, 0xe8224083, 0x4082a470, 0x707df027, + 0x4fecffff, 0x220a825c, 0x83d823ec, 0xc5f5226e, 0x30fe821e, 0xfffff0e7, 0xff90c2f5, 0x63d00700, 0x30f8ffff, 0x27af82a4, 0xff01807a, 0x008085ff, + 0x1f21af82, 0x318e828f, 0xffc275e0, 0x33b32a00, 0x4ceeffff, 0x2c00ffcc, 0x57829999, 0xfa320028, 0x00ff06e2, 0xc1828017, 0xe6540032, 0x0e00ff66, + 0x00ffec91, 0xff9a1918, 0x146e5800, 0x49274682, 0x01ffc4f5, 0x8234330f, 0xdc002346, 0xbf828e28, 0x82646621, 0x98192271, 0x2d05838b, 0x2f0e089a, + 0x74f724f8, 0xf6ffff15, 0x96821cda, 0x2c87f727, 0x4dfdffff, 0x21858291, 0xfe82e0ba, 0x82d38d21, 0xcafb27e2, 0x1600ff3e, 0xbb82363e, 0x58829920, + 0x67821020, 0x82e8ff21, 0x221a8272, 0x82b89eee, 0xebf02235, 0x2b408286, 0xffff85ab, 0xffea91f7, 0xf628f2ff, 0xfa221a82, 0x358272fd, 0xff1f4526, + 0x6666edff, 0x86068351, 0xa6f32235, 0x22358266, 0x8229dcf4, 0xf8332161, 0x7d213582, 0x21708271, 0xaf824456, 0xc4759423, 0x229a8207, 0x820a1716, + 0x2ac683e8, 0xfff6e811, 0xcccceaff, 0x8274088b, 0x82ee2033, 0xeeff2312, 0x0a820a17, 0x82e8e921, 0xbdfe2965, 0x5307cc4c, 0xb34a00ff, 0xff22e182, + 0x688226f8, 0x00800a2a, 0xfaf3ffff, 0x0500ffe1, 0xd7230984, 0x82088b0a, 0xaec72141, 0xed213382, 0x221b8240, 0x82a4f0ee, 0x0ae9230a, 0x0682083e, + 0xdea4f727, 0x9b0200ff, 0x218482a6, 0x32827493, 0x82a26521, 0xcccc2189, 0x5b308982, 0xffff5238, 0x05666686, 0x931900ff, 0xddffff34, 0x0035f682, + 0xff33b328, 0x34b3ebff, 0x802a00ff, 0xeb088b00, 0x4f00ff06, 0x24cc8266, 0x9a994000, 0x820483ff, 0x211082bb, 0xc483eb08, 0x200ef352, 0x243183e5, + 0x44fb34fb, 0x21778315, 0x6882f027, 0x8610d821, 0x27f72204, 0x83a583f0, 0x21118506, 0x11820700, 0x0800ff24, 0x4b8510d8, 0xe17b0820, 0xff332405, + 0x82330700, 0x0daf497d, 0x94823320, 0x10d8f822, 0x08215685, 0x748c192b, 0x8262b507, 0xf084185d, 0x21818209, 0xd382cccc, 0xff201183, 0x0e2b62ee, + 0x00ff94f7, 0x159a99a0, 0x4aff00ff, 0x862507ee, 0xb0f1ffff, 0x051b4aa4, 0x4feeff26, 0xff088b5c, 0x16850684, 0x2f0b7e4a, 0x33b327ff, 0x1a00ff07, + 0xffff33b3, 0xa467e6ff, 0x4c2b2182, 0x0c00ffcc, 0xffffcd4c, 0x8234b3e7, 0xccaa2737, 0x2400ffcd, 0x5f823333, 0x9583022c, 0xc50000ff, 0x0200fffe, + 0x09826d87, 0x82eb4021, 0xea862109, 0x7d210982, 0x2c298230, 0xff3d0aab, 0x424bc600, 0xfaffff05, 0x304483cc, 0xffffd823, 0xff4721f4, 0xae470700, + 0xa1f3ffff, 0x2a878348, 0x8bae07eb, 0xedffff80, 0x828b70fd, 0x52f8226c, 0x22068208, 0x8202cbfb, 0xbcd52b44, 0xb9fbffff, 0x0100ff58, 0x09829cc3, + 0x080ee237, 0xf85100ff, 0x40ffff52, 0xff0532b3, 0x233b3600, 0xb51000ff, 0x250a82c3, 0xff3333f5, 0x93831b00, 0x8520d68d, 0xee254b82, 0x4b087b54, + 0x25088407, 0x0e00ff7a, 0x65825c4f, 0xff86ab26, 0xa4b01100, 0x06847e82, 0x79181685, 0xcb200a48, 0x00222f82, 0xa118b311, 0x2b221169, 0xf78214fb, + 0x0946fd18, 0xeb20338a, 0xab213384, 0x086a4185, 0x63417b20, 0x0f6a4105, 0x915f9387, 0x0e002208, 0x9fa1184c, 0xffbb290c, 0x9a19f6ff, 0xf4ffff15, + 0xf22a1783, 0xffff9a99, 0xff68e6ee, 0x0e83f7ff, 0xccccec22, 0xff23b582, 0x820a97e4, 0xcae822d1, 0x21c7823e, 0x3082ec51, 0xffd6e326, 0xe03a1800, + 0xf82c6c82, 0xffffe5f0, 0xff0a97ea, 0xb528efff, 0x2e2b3a82, 0xe8ffff14, 0xffffebd1, 0x82badef8, 0x0ad0221e, 0x2ca1823d, 0xff05703d, 0x2170feff, + 0x84ffffff, 0x200982f0, 0x2214826a, 0x822cc5ff, 0xa4702109, 0xf9225f83, 0x5f82cfb7, 0x1d1afa30, 0xb90300ff, 0xfdffff16, 0x00ffa370, 0x5f830f06, + 0xf823ff27, 0x090200ff, 0x213a82ba, 0x09827298, 0x8b641b22, 0x11220582, 0x0682086a, 0x90830620, 0x6b5c0422, 0x5e212b82, 0x210482b8, 0x1a8262f0, + 0x08d6232d, 0x732e00ff, 0x0e00ff33, 0x82053e4a, 0x823320b0, 0x4b052c0a, 0x0c00ff02, 0x00ff5c8f, 0x82e0af0f, 0xa6112239, 0x2c408366, 0xffa43022, + 0xc275dfff, 0xe10500ff, 0x21b28248, 0x8d831f85, 0x291cfc22, 0xfc228d82, 0x7382c00a, 0xffc66d26, 0x8816fcff, 0xcc24a982, 0x6b230898, 0xed2cc682, + 0xffff1fc5, 0xffde64fa, 0xe1faf5ff, 0x6521f582, 0x222c8260, 0x8270fdef, 0xfbff324f, 0x00ffe8bb, 0xffb8ae00, 0xd4b8fbff, 0x600100ff, 0x21098221, + 0x9082bedf, 0x0f221227, 0xa7c9ffff, 0x2f90828e, 0xff1f8512, 0x0080c8ff, 0xfd3300ff, 0xdaffff71, 0x3a220983, 0x79820080, 0xcc4a0029, 0x00ff06cd, + 0x823e8a52, 0x424526a2, 0x3900ff8e, 0x2d9b8235, 0xff68e612, 0x3eca4c00, 0xf7ffff08, 0x8f8266e6, 0x8234332c, 0xccfdffff, 0xf6ffffcc, 0x37826666, + 0xccecff23, 0x208482cc, 0x222783ee, 0x4134b308, 0x200805ca, 0x66660d00, 0xffef0e08, 0x98196a02, 0x545e01ff, 0xffff157c, 0xffe0faf2, 0x00600400, + 0x91f1ffff, 0x269a82ec, 0xffff0278, 0x82e4baf7, 0x06ff2130, 0x89215d82, 0x22b9829e, 0x82482162, 0x998927e5, 0x9d00ff9a, 0x0a82cccc, 0xd483f720, + 0xb0070b22, 0xa0213482, 0x213e8242, 0x4882ac87, 0x8284eb21, 0x9c99213e, 0xf2203482, 0xbd210a84, 0x20498270, 0x207a8233, 0x238a84f3, 0x083433f2, + 0x2205496f, 0x185c4fee, 0x20099ca7, 0x11244eff, 0x2e066064, 0x08a4b011, 0xff0734f7, 0xf6685600, 0x838cffff, 0x0c002f78, 0xffff5c0f, 0xff48e1ef, + 0xec111b00, 0x0f84ff8b, 0x1e100024, 0x258208b8, 0xff666627, 0x34337300, 0x05c46a05, 0x7c206486, 0x23060c43, 0x8b84ab11, 0x06832482, 0x64069b4e, + 0x648405c5, 0x82079421, 0xcc0d224a, 0x21af85cc, 0xb4830c00, 0x64e6f222, 0x542fd882, 0xfeff087c, 0xff68e675, 0xf4a80100, 0x5854fb15, 0xff220c4f, + 0x1264b0f1, 0x6f00200e, 0xb0210548, 0x23d583a4, 0xcb088b85, 0x20202f82, 0x8605784e, 0x827b208f, 0x34b3218f, 0x64089564, 0x9c58095f, 0x25f48207, + 0x1cdf00ff, 0x3b82072a, 0x1e8b0020, 0x825c4f21, 0x0ae264a4, 0x0fc6a618, 0x94f70e30, 0xff1554f8, 0x9a9972ff, 0x8dffff8b, 0x9d186666, 0x9a2015b9, + 0xff211684, 0x21208200, 0x0685088b, 0x8200ff21, 0x82048433, 0x20178261, 0x86068508, 0x841b8328, 0x3b2d8254, 0xffcccc5d, 0x3433a2fe, 0x0500ff15, + 0xffff1098, 0xff52f8f3, 0xf0d7faff, 0xb8f1ffff, 0xf4220982, 0x0e82a400, 0x08b85e2b, 0xb0fcffff, 0xfeffff20, 0x26238278, 0xffe08ffc, 0x8247ffff, + 0x8ffc2523, 0x82088b5c, 0xf7229c82, 0x40820a57, 0xff00202b, 0xf6e8fbff, 0xaf0800ff, 0x3031825c, 0xff3e8ad9, 0xa4305200, 0xc4ffff05, 0x4306f628, + 0x05787507, 0xf5ffff23, 0x84288240, 0xc0f22204, 0x20b38200, 0x147a78ff, 0xcf00ff24, 0x338270fd, 0x820d0021, 0x7800202e, 0xe3200e80, 0xfe278182, + 0x00ff05e0, 0x8248212c, 0xde2327dc, 0xdcffffb8, 0x6182b81e, 0x48e1d322, 0xff23ee82, 0x8214aee3, 0x48212ac3, 0x3ae7ffff, 0xe9ffffe2, 0x2d7282c0, + 0x08aec7f1, 0xeb2200ff, 0xb5ffff84, 0x9682b083, 0x3433b22b, 0xccad00ff, 0x064b15cc, 0x059e414b, 0x82f6a821, 0x830e204d, 0x820482cd, 0xa811220a, + 0x204d82f6, 0x41068200, 0x168206e6, 0xeeffff2f, 0x088bcc4c, 0x94f8ef0e, 0xfeff158b, 0x387d187f, 0x45f1200a, 0x878206df, 0x3233ef22, 0xff203982, + 0xff2f0682, 0xcd4c0e00, 0xe6efffff, 0x1000ff68, 0x6e8bcdcc, 0x5e500530, 0x190e2005, 0x2624ef17, 0x1554f8db, 0x5f06b4fc, 0xff200576, 0x083b6c18, + 0xe5266582, 0xfb080080, 0x467107d4, 0x82f82016, 0x866c1833, 0x586c180a, 0x83f7200a, 0x851a8333, 0x8519834d, 0x7b08335d, 0xfc15f4fb, 0xb4f70694, + 0x0694f807, 0x0e07b4fb, 0xee56eb2f, 0x52c9820b, 0x6f18050e, 0x71521221, 0x076b2508, 0xab0614f7, 0x2105bc46, 0xfe82ff86, 0x9618cc20, 0x89720bb0, + 0x0a27480b, 0x69186b20, 0x5b231935, 0x7754fc07, 0x1a2705df, 0x00ff9082, 0x83717d15, 0xff702104, 0x2005e660, 0x196a82bb, 0x293e6751, 0x54f78cfb, + 0x53075315, 0x3919ff06, 0xcc210db4, 0x2010838b, 0xb4391934, 0x06c32217, 0x82e48253, 0xff342932, 0x33b30a00, 0x4cf5ffff, 0x0d26e982, 0x088bcd4c, + 0x068300ff, 0x1b821685, 0x838b3421, 0x08cc2510, 0x06c307c3, 0x0f820984, 0x10780a20, 0x851a8705, 0x83438621, 0x053c7b1b, 0xc3065322, 0x4d826382, + 0x1a83cc20, 0x5183cd20, 0xa5853420, 0xac960820, 0xf72f0e26, 0x1534f834, 0x54718441, 0x24420896, 0x34fb2924, 0xf81534fb, 0xa4fb0654, 0x1807be42, + 0x620f146f, 0xbe420ef3, 0x07a4260b, 0x4cfbccf7, 0x2d4a4115, 0x4144fb21, 0xf7212edf, 0x51441a44, 0x01ff2ce6, 0xff9a1930, 0x66e68fff, 0x1800ff15, + 0x26335f6f, 0xd0ffff5c, 0x820566e6, 0x23478205, 0x9a192f00, 0xf7240a82, 0x00ff0080, 0x138c6f18, 0xf6ffff24, 0x048233b3, 0x8b9a9927, 0xccf0ffff, + 0x222583cc, 0x82ffffcd, 0xff08212f, 0x45843b83, 0x51824082, 0x06825c20, 0x09272c9a, 0xffff6666, 0x18ceccf5, 0x200e2870, 0x2d478332, 0x00ff66e6, + 0x0534332e, 0xd1ffffba, 0x7018cccc, 0x2c930955, 0x3b82f29a, 0x3c82ba20, 0x9b824982, 0x5d43e282, 0x01ff22e5, 0x3d104248, 0xffff2c23, 0x431042a0, + 0x0b0f7218, 0x2a11b941, 0x04f704f7, 0xf7af0e05, 0x1834f814, 0x580cea7a, 0xff330b95, 0x079a9968, 0x999c00ff, 0x5400ff9a, 0x9b056666, 0x830800ff, + 0x6613330b, 0xf4ffff66, 0xff8b6666, 0xccccedff, 0xc0ffff08, 0x278bcecc, 0x0f00ff24, 0x2b88feff, 0x2b8c6820, 0x33e8fe23, 0x17b54434, 0x6734fc21, + 0xb5440ca9, 0x04f8210a, 0x2917295a, 0xfb0e06cb, 0xf7d4f770, 0x8d8215c4, 0x1980b021, 0x2411df27, 0x78b0ffff, 0x231b8252, 0xffae87bf, 0x0a424919, + 0x00ff8b23, 0x2111844f, 0x16825278, 0x0e820483, 0x82088b21, 0x00802115, 0x40201b82, 0x87214984, 0x823882ae, 0xfb08233e, 0x5f82db14, 0xd7080023, + 0x066b5a0a, 0x0981a219, 0xcaffff24, 0x26829919, 0x66e6d522, 0x0e554c19, 0x3433f724, 0x288400ff, 0xccccf822, 0x82057e5c, 0x069e5a5f, 0x05513320, + 0x236a8205, 0x08cccc08, 0x2008d667, 0x671682b3, 0x0a4705d6, 0x212d8b05, 0x2682f628, 0x082a8282, 0x1534fc5b, 0xe6a200ff, 0x83610766, 0xfeff2105, + 0x22069469, 0x82ffffff, 0x0a002385, 0xc98366e6, 0xf4460683, 0x00002105, 0x662a2084, 0x0100ff66, 0xff0866e6, 0xba575dff, 0x06bd7c05, 0x2106594f, + 0x7384eeff, 0xff200684, 0x8208524b, 0xb3112973, 0xff0e0834, 0x9a19df00, 0x200acf48, 0x22c1830f, 0x497a540e, 0xff200699, 0x2206f559, 0x5bcc4c0e, + 0x99280d41, 0xff066666, 0x34330400, 0x04204882, 0xff398682, 0x8e5c4ffe, 0x5bbb0888, 0x0600ff05, 0xffff3233, 0x8b90c2f9, 0xd4f5ffff, 0x210a827a, + 0x0484cecc, 0x5b5b0828, 0xff888805, 0xcd82fbff, 0x83feff21, 0xccfb2951, 0xff088bcc, 0x34b385fe, 0x17a22a19, 0x26052550, 0x00ff84ab, 0x4ce13a0f, + 0x103006d7, 0x088b1fc5, 0x058b34f7, 0xe60001ff, 0x15b4fb66, 0x24161c65, 0xa186feff, 0x22588248, 0x8200c0fb, 0xeefb2d21, 0x0100ff15, 0x8e8834b3, + 0x05bb5b08, 0xc1219082, 0x82aa8448, 0x330a22c0, 0x210a8234, 0x0f84b83e, 0xffbb0829, 0x01003000, 0x828e8e05, 0xeb1126df, 0x990200ff, 0x21098299, + 0xa9820040, 0x7898002f, 0x07ab0652, 0xe64000ff, 0x076b0666, 0x18b682f7, 0x230a8a7e, 0xcdccf0ff, 0xef336882, 0xff083333, 0x9a19bfff, 0x1fffff07, + 0x54fb9a19, 0x82ffff15, 0x82198213, 0x20c2821f, 0x073a7e4c, 0x4886eb20, 0x2308a550, 0x34b3f1ff, 0x0805564b, 0x66edff31, 0x0e088b66, 0xff14f8af, + 0x66e6e3ff, 0xff54fb15, 0x66e63600, 0x8101ff05, 0xf7072045, 0xc9ffff54, 0xff05d623, 0xa4b07efe, 0x01ffab07, 0x82e2ba83, 0x197f2ddc, 0x3200ff98, + 0xff050ad7, 0xd0cc0f00, 0x4c24cc82, 0x1100ffcc, 0xff231482, 0x82d863f4, 0x05ef297e, 0xfeff081e, 0x075238b1, 0xf6320c82, 0xff853433, 0x3233f7ff, + 0xe6f6ffff, 0xfcffff68, 0xb582ce4c, 0x2d836f20, 0x9a19c622, 0x822d6882, 0xff07146e, 0x0a176ffe, 0x3df9ffff, 0x275e8270, 0xfff6e890, 0xc4f53900, + 0x7d227682, 0xdc82ea91, 0x10828020, 0x83cdff21, 0xf0ff232c, 0x2682713d, 0xee2fbd83, 0x00ff9ad9, 0x8b98990b, 0x01ff089c, 0x82cecc4e, 0x0900226b, + 0x218882cc, 0x1882f905, 0xecd10838, 0x1d0900ff, 0x0300ff71, 0x8b0866a6, 0x01ff0e07, 0xff9a19ff, 0xe3828001, 0xe0feff22, 0x2205484e, 0x8200c0dc, + 0x824020f5, 0x26e42404, 0x82ffff66, 0x088b270e, 0xff0624fb, 0x2a8283ff, 0x51a2ff28, 0xffff05ec, 0x1e8220f8, 0x0240fa2d, 0xc1f4ffff, 0x0500ff48, + 0x828b44b3, 0xeebf2958, 0x5300ff08, 0x2b07e2fa, 0x37832d82, 0x00234785, 0x8200c01c, 0x5922221e, 0x2293829a, 0x8398191f, 0x82232093, 0x2217835f, + 0x831b00ff, 0x4c0e82b1, 0x24220687, 0x2b82b81e, 0x82e61b21, 0x40e32179, 0xff213682, 0x4ea982dd, 0x6b28617a, 0xe640ffff, 0x14fb1566, 0xff229c82, + 0x7d8266ed, 0x18073b4d, 0x241dcdcb, 0xe68000ff, 0x23338266, 0xcecc1000, 0x4c05584d, 0x1020055e, 0x8305365f, 0x00ff3306, 0xff991910, 0x34b3f1ff, + 0xefffff8b, 0xf7083233, 0x688d8b14, 0x180cad72, 0x8f16e840, 0x83cc2068, 0x8204826d, 0x088b2177, 0xcc226282, 0x05828bce, 0x8b981921, 0x61364168, + 0xdcfbeb23, 0x39461815, 0x82332008, 0x83f520c7, 0xccf22204, 0x063242cc, 0xcdccf222, 0xf5251e82, 0x00ff3333, 0x2814820a, 0x330d00ff, 0x24f70834, + 0x82ab8207, 0x20148309, 0x831984cd, 0x8b332118, 0x86191982, 0x4618098c, 0xfb280d9e, 0x2f0e0724, 0xe4f704f7, 0x00286e82, 0xff28dc3d, 0x9a193200, + 0x23240482, 0x3d00ffd8, 0x83059945, 0x23168506, 0x28dccdff, 0xc2267682, 0x5b08d823, 0x7618cb07, 0x7a180efb, 0xfb2708fa, 0x568b0764, 0x82566060, + 0x069421aa, 0x08f40a19, 0xb61f0527, 0xf708c08b, 0x07a65764, 0x6e06dd4d, 0xcb2808c4, 0xbb07bb06, 0x14f7155b, 0x2205004e, 0x189a5923, 0x23115381, + 0x33b3dcff, 0xe3227f82, 0x1b82cd4c, 0x2408e773, 0x2b73075b, 0x0e874d15, 0x117d4518, 0xa34dcd20, 0xf2ff2105, 0x83058376, 0x05684d06, 0x4cf5ff23, + 0x825482cd, 0x05fe4d10, 0xe34d3320, 0x20328208, 0x241b820d, 0xbb44f708, 0x5c461815, 0x2031920d, 0x234d8534, 0xcc4c0d00, 0x1805154e, 0x2a2a0b46, + 0xab00ffaf, 0x01ff33b3, 0x8266e600, 0xe82208c8, 0xff069999, 0x6866aeff, 0x079c00ff, 0xffff05ae, 0xff66e6f9, 0x90c20b00, 0x990400ff, 0x0e00ff9a, + 0x0e822e7d, 0xff32b327, 0x721d0600, 0x210a8208, 0x0a83cecc, 0x19827020, 0xff008026, 0x8c6cfbff, 0x19260e82, 0xf4ffff98, 0x1e82ac3c, 0x9a195d2b, + 0xd44dffff, 0x00ff057a, 0x612e1955, 0x09d9450f, 0xffff8b26, 0xff6766ed, 0x2205aa45, 0x439999f2, 0x0823052d, 0x83ccffff, 0x992f273e, 0xff83059a, + 0x5f83e3ff, 0xcc4ce728, 0xe2ffff77, 0xe6829a99, 0x19e3fe24, 0x1782069a, 0x8bff7f33, 0x66e6ffff, 0xffff9f66, 0xff47e1f8, 0x00801c00, 0x263a8208, + 0x00ffb81e, 0x826666d0, 0x54ee22c2, 0x2e21827b, 0xff85abf1, 0x67660d00, 0x1200ff8b, 0x82089999, 0xcc102206, 0x26b682cd, 0x00ff7b54, 0x5333330f, + 0xa785085c, 0x0023b883, 0x82862bb2, 0x820620b8, 0x0b002384, 0xe28554c3, 0x93040023, 0x25f68374, 0xf9ffffcd, 0xe28290e2, 0x33b30b22, 0x8e230a83, + 0x830400ff, 0x82f122b9, 0x200e82d2, 0x22cd82e6, 0x82703df4, 0x66ae2787, 0x63ffff66, 0x488252f8, 0x67661327, 0x8b1504fb, 0x211f8293, 0x058233b3, + 0x4448f620, 0x19f82205, 0x259e8299, 0x8367e6f7, 0xef76838b, 0x4cf62705, 0x0800ffce, 0x28839919, 0x00ff3225, 0x8267e607, 0x090023ee, 0xb48233b3, + 0x824c0621, 0x4c0622b4, 0x2a0a82ce, 0x0832b309, 0x8bdb07eb, 0x82072b15, 0x20348640, 0x2034889a, 0x20348566, 0x24298232, 0xff343307, 0x83348b00, + 0xccf82284, 0x208484cc, 0x232782ce, 0x9a19f8ff, 0x66208484, 0xff258483, 0x66e69000, 0x85a9848b, 0x60f72024, 0x06830507, 0x82ffff21, 0x83a98d12, + 0xf9ff225d, 0x22a982b3, 0x82cccc08, 0x7f00204c, 0x748b0af1, 0x2161b944, 0x92183b8b, 0x3a5c0c0b, 0x22dc820a, 0x5cf6e8e9, 0x16830564, 0xe9ffff22, + 0x0820e282, 0x16850685, 0x82110021, 0x00ff2211, 0x05116316, 0xff200682, 0x04861183, 0xd9830e82, 0x9a99762b, 0xe678ffff, 0xffff1566, 0x2cf082c4, + 0x9a19efff, 0xfcffff05, 0xffffce4c, 0x055157fe, 0xffff3225, 0x820080ff, 0x34332113, 0x33210982, 0x36628234, 0x0714aec1, 0xa31e00ff, 0xa8ffffd8, + 0xff05f6a8, 0x18640400, 0x83f3ffff, 0x6bf92725, 0xf2ffffc8, 0x0e825c4f, 0xff7c7f26, 0x9a99fbff, 0xfd222f82, 0x3a829859, 0xffcc0c24, 0x5883fdff, + 0x7383ff20, 0x9f57fd20, 0x18f62205, 0x27c98210, 0xff4cb7f6, 0x20300600, 0x8c266582, 0x0900ffcc, 0x35823cdf, 0x6626e627, 0xa64600ff, 0x2c8f8266, + 0xff2070fd, 0x84000700, 0x1af6ffff, 0x272f821d, 0xff156efd, 0x7cfff8ff, 0xff222586, 0xb58459b9, 0x82ed9121, 0x82232020, 0xb3f62695, 0xf9ffff33, + 0x207082cc, 0x051b60f6, 0xe75bfd22, 0x54253683, 0x0000ff3a, 0x82cc8270, 0x2109820f, 0x408210e8, 0x0023b683, 0x82f06704, 0x856b2630, 0xaf0d00ff, + 0x27cf821a, 0x00ffd763, 0x0800800c, 0xa426e582, 0x5700ff9c, 0xe582b25d, 0xce4c3e23, 0x21a18207, 0x3a823333, 0xfc205b83, 0xf5830984, 0xcd4cfc26, + 0x190100ff, 0xc420eb83, 0x00227a82, 0xb583e610, 0x1583f320, 0x34b30322, 0x21056772, 0x2e830d00, 0xfb820320, 0xcc0c0023, 0x865982cd, 0x82ce200a, + 0x82662073, 0x660722e9, 0x83738264, 0x4cfc222d, 0x211e82ce, 0xa782403b, 0x5c0fef22, 0x1e2d7882, 0xffff852b, 0xff8360f7, 0xe1fa1f00, 0x2693828b, + 0x00fff628, 0x867d9f08, 0x10002325, 0x6318a4f0, 0x03220791, 0x4f82f0c7, 0x82ea5121, 0x28988273, 0x68a60300, 0x3ff3ffff, 0x222982be, 0x82b89e03, + 0x2749830a, 0xff9899f8, 0xcdccf2ff, 0x4c210e82, 0x28d082ce, 0x0e08cc4c, 0xbd01ff2f, 0x26a98233, 0x1566e6d9, 0x828affff, 0xac002486, 0x82059a99, + 0x7cff261d, 0x78fbffff, 0x21098294, 0x0982245b, 0x8282e021, 0xa8862104, 0xa6220e82, 0x0a8208ea, 0x82049621, 0x82ae200a, 0x1dfb3150, 0xfdffff70, + 0xffff06a1, 0xff78defa, 0xca61feff, 0x74207482, 0xff23d982, 0x8234b354, 0x1803229e, 0x262e8210, 0x00fff873, 0x82740805, 0xfc892129, 0x17220982, + 0x25828bce, 0x00200322, 0x0331d582, 0x00ff3c1f, 0xfffee500, 0x00c00200, 0xdf0100ff, 0x211a82e6, 0x14825507, 0x58240422, 0xe6270f82, 0x0900ff68, + 0x828668e6, 0x32332afa, 0xd1feff08, 0x1bf866e6, 0xee051915, 0x22ee8308, 0x82727d15, 0x9c192348, 0x06850828, 0xebffff2e, 0x00ffd763, 0xffd86316, + 0x0080e5ff, 0x06846b82, 0x22131572, 0x69707de5, 0xeb2706b9, 0x00fff668, 0x839a9919, 0xe8d0302d, 0x1591fbf5, 0xf8e0ffff, 0x83ffff52, 0x8205cecc, + 0x21b02bc2, 0xd7eeffff, 0x0a00ff0a, 0x0982df6f, 0xff48a126, 0xae271100, 0xb8221882, 0xbb820852, 0xff9a9926, 0xf468ffff, 0x9e210982, 0x210982b9, + 0x098234b3, 0x825c8f21, 0x0e00234c, 0x96820b57, 0x3d0a0d22, 0xb324c782, 0x0300fff8, 0x00232082, 0x82ea860e, 0x0a162735, 0x5800ff3e, 0x5f82142e, + 0x14eeca27, 0x173500ff, 0x2d0a820a, 0x076666fe, 0x97d900ff, 0x4f00ff0a, 0x8682ce4c, 0x5238b327, 0x666600ff, 0x261b8266, 0xffe1faed, 0x82191800, + 0x4ce32a6c, 0x0e00ffcd, 0xffffcc4c, 0x050144e1, 0x8282e720, 0xe6000022, 0xdb322583, 0xff8bf668, 0x0a17dfff, 0xabebffff, 0xefffff86, 0x0e8247a1, + 0x081e452c, 0xa8d1ffff, 0xa2ffff31, 0x4b82c275, 0x8218f821, 0x33f021dd, 0x0621a982, 0x26c88267, 0xffccccec, 0x82d00f00, 0x19f82be6, 0x00ff089a, + 0xff109804, 0xb183fdff, 0x00e00426, 0xecfeffff, 0xcf211383, 0x22d2839e, 0x8200c00b, 0x470b31d2, 0x0600ffae, 0x00ff1078, 0xff48a105, 0x94380b00, + 0x23212182, 0x220a8261, 0x8290c246, 0x8cc7235f, 0x868207cc, 0x1884f722, 0x6020f482, 0xf7284282, 0xff9130dd, 0x70fdf9ff, 0x56202782, 0xa9229283, + 0x2782b85e, 0x0040ad22, 0x232e1f5e, 0xc05200ff, 0x00213383, 0x21e28311, 0x828258f9, 0xec11102c, 0xe7f3ffff, 0x0c00fff0, 0xe7820a17, 0x9ab9d231, + 0x2f2d00ff, 0x00ff055e, 0x07ff7f5d, 0x824600ff, 0xa2ff2398, 0x1082b91e, 0x0a970a2b, 0xe3f1ffff, 0x1400ffd8, 0x2cf88207, 0xff4621fd, 0xf6280e00, + 0x920a00ff, 0x229a82f2, 0x82d6230e, 0x0496260a, 0xe60200ff, 0x26238268, 0xffff9a19, 0x826666f5, 0x9a193723, 0xffaf0e08, 0xcdccaa00, 0xff153cf7, + 0x66662a00, 0xeaffff06, 0x0a82cdcc, 0x82cd4c21, 0x2b0a83c9, 0x33b3d5ff, 0x5501ff05, 0x8cf73433, 0x69298b18, 0xb312ff2f, 0xc2feff34, 0xff150080, + 0x9899fcff, 0x05434fff, 0xce4cfc27, 0x33ffffff, 0x45138234, 0x22080577, 0x8b2130f7, 0x88f7ffff, 0x0400ff31, 0xffffe8db, 0xffaec7fb, 0x36690800, + 0xf6ffff08, 0x00ff33b3, 0x82e2ba12, 0x99ad23c6, 0x1082069a, 0xff0ca226, 0x1e45edff, 0xfa2c1082, 0xffff1018, 0xffd823f4, 0x9498f1ff, 0x28213582, + 0x270e82f4, 0x00ffb81e, 0x0852f805, 0xf0210a87, 0x26198220, 0x00ffa330, 0x82ea660e, 0xa4f02b19, 0xdc0b00ff, 0xf7d3082a, 0x63820524, 0xff002025, + 0x82401000, 0xaf1a2304, 0x0f828b5c, 0xff48212a, 0x00c0efff, 0x4700ff08, 0x22833682, 0x8ef70522, 0x28214a82, 0x830e82f6, 0x99f122b1, 0x220e829a, + 0x82859a19, 0x4c6d2522, 0xfdffffcc, 0x5321dc82, 0x34c71806, 0x5691180d, 0x0cb64b08, 0xb64bcc20, 0x8b342408, 0x1806c308, 0x211a7070, 0x57185c0f, + 0x8b2810fd, 0x6b1524f7, 0xab072b06, 0x1a223782, 0xab825278, 0xae871524, 0x048200ff, 0x10820a82, 0x06850820, 0x83054c44, 0xffff2a16, 0x8b0080e5, + 0x01ff0e08, 0x29b2821c, 0x9a190a01, 0xf5ffff15, 0xe48252b8, 0xff10582f, 0xb8def0ff, 0x87feffff, 0xf7fffff0, 0x23db82a8, 0x0810b8f5, 0x8c200a82, + 0xf527d082, 0x00ffbcb4, 0x82008001, 0x67e62123, 0x4c21b282, 0x211882cd, 0xef829999, 0x5d4f0b2a, 0xc0f6ffff, 0x0600ff00, 0xf2281e83, 0xff8b5c8f, + 0xecd1f1ff, 0xff227b82, 0xb382cff1, 0x1684f920, 0xffec9126, 0xa4b0f4ff, 0x54822a84, 0xff227383, 0x738298f7, 0x5484fe20, 0x8242e021, 0xae672182, + 0xc0218c82, 0x21548200, 0x1982b804, 0x2030fa22, 0xe6225482, 0x058288a8, 0x8ba4f022, 0x05221682, 0xd1821058, 0xf0670522, 0xc7208b82, 0x04260482, + 0x00ffa470, 0x3183a003, 0xf8831620, 0x0f831220, 0xf6e80c27, 0xf51a00ff, 0x222982c2, 0x8267a61c, 0x82002086, 0xffff2406, 0x82c215f3, 0x0eed2416, + 0x82e9ffff, 0x12002271, 0x20358380, 0x230a833c, 0x15cccc4a, 0xc7217882, 0x218282ae, 0xe1821258, 0xff48e126, 0x2090feff, 0x8f20e182, 0xf520bf82, + 0xab859183, 0x05410a82, 0x23238207, 0x00400a00, 0x97212382, 0x2099820a, 0x330f8221, 0x5238e4ff, 0x6e1300ff, 0xd7ffff14, 0xff8b9a99, 0xae47d5ff, + 0x06837e82, 0xecffff22, 0xd7214a83, 0x215982a1, 0x048221de, 0xa430e423, 0x82ec8408, 0x0f054140, 0x0541f020, 0x82c02008, 0x38fa225f, 0x21ff8210, + 0x0541b8de, 0x0060210a, 0x0522db82, 0x05410060, 0x82782007, 0xa8032276, 0x3a868230, 0xff9a192d, 0xc60b2400, 0xcc1900ff, 0xc58bc1cc, 0xffc58b08, + 0x3433e6ff, 0x823400ff, 0xd2ff2804, 0x00ff66e6, 0x82cccc25, 0x4c3d2729, 0x4900ffcc, 0xf98934f3, 0xf9871020, 0x80828720, 0xf984f720, 0x82eec721, + 0x83f720a4, 0x20f9959f, 0x2a48820c, 0xff9eef37, 0x8a2cd2ff, 0x822000ff, 0xbcff237c, 0xf982ce4c, 0x32b3b822, 0x0682f983, 0xdfffff2e, 0xfffff6e8, + 0xff6866bb, 0xae07c8ff, 0x33212a82, 0x37f9d334, 0xffbe1f43, 0x7e1f3600, 0x802600ff, 0x5100ff00, 0xff8b3233, 0x00805700, 0x06838682, 0xd9ffff22, + 0x4f281683, 0xffff3473, 0xc266e6bc, 0x00328282, 0xffff67e6, 0x15cc8c72, 0xcc0900ff, 0xff968acd, 0xc0820600, 0xe6030023, 0x21108266, 0xda8266e6, + 0x82c02121, 0x61542749, 0x00ff0548, 0x0a824004, 0xb8de0a25, 0x83fbffff, 0x820d2024, 0xf7ff280e, 0x00ff9919, 0x82723d05, 0x87bc2d4b, 0x2a00ffae, + 0xff05842b, 0x5278f6ff, 0xfa311582, 0xf3ffffa0, 0xffff33b3, 0x83029bfe, 0x06f8ffff, 0x21258288, 0xff82c776, 0x00320483, 0xff8f0200, 0x989920ff, + 0x358900ff, 0x76ffffc3, 0x6e82cecc, 0x65fb0722, 0x04262982, 0x0c00ff1a, 0x3982ee3c, 0x82e09a21, 0x22588388, 0x821cfa05, 0x7a43221e, 0x216382e2, + 0x8d82a430, 0x82c60921, 0x1a0622a3, 0x209782a0, 0x2c978220, 0xffb25d0c, 0xb0b2fbff, 0xd40a00ff, 0x2767827a, 0xffa245de, 0xe04f5400, 0xfc228d82, + 0x4482140e, 0xff88f625, 0x82cef5ff, 0x250621e8, 0xf5229782, 0x5d82f668, 0x822adc21, 0xc2ca2129, 0xfa228782, 0x29829eaf, 0x29dcec32, 0x243800ff, + 0x00ff8bdc, 0xffce4c3d, 0x852b1300, 0x19210f82, 0x3279829a, 0xff713d35, 0x32b3faff, 0xf7ef0e05, 0x15f4f714, 0x7dffff8b, 0x5921052f, 0x05b34f99, + 0xa6dcff24, 0x4e828b66, 0x11820683, 0x20057f7d, 0x21498234, 0x3d564c23, 0x20118405, 0x20b482a6, 0x2204831c, 0x829a5923, 0x8300202d, 0x43ff2006, + 0xe320059c, 0x2208dc4f, 0x7e34fbab, 0xcd200546, 0x2107c37d, 0x451833b3, 0x4e820852, 0x1c225482, 0x648234b3, 0x84cd4c21, 0x18332086, 0x5019c243, + 0x417e093c, 0x7bcb240a, 0x5600ff15, 0x178217e5, 0xf8ffff23, 0x277a82cc, 0xff333307, 0x3333f7ff, 0x0684a782, 0x1b831685, 0x17827582, 0xf7247583, + 0x00ff3433, 0x0e6e7218, 0x24fb2b22, 0x21321e41, 0xec82cc4c, 0x337fa620, 0x21f3820c, 0xc2449a59, 0x38c41805, 0x184b200b, 0x1818114e, 0x7416c949, + 0x33210d58, 0x09d25734, 0xcccc0822, 0xd721d582, 0x20c3830a, 0x26ec8234, 0x088bf628, 0x897b74f7, 0x124518be, 0x144f410f, 0x41181b58, 0xcc200cab, + 0xdc239d82, 0x850834b3, 0x183320be, 0x881212a3, 0x183320be, 0x410c03e7, 0xbe831bab, 0x8305ab41, 0x245482be, 0xf774fb08, 0x093d4224, 0x20055041, + 0x05494133, 0x50410820, 0x103d420e, 0x2224cb42, 0x42f734f7, 0x4018059e, 0xc6181262, 0x2c431655, 0x244e4108, 0x8bd4f722, 0x201b8041, 0x204d8234, + 0x424882e3, 0x8b200ad0, 0xff20d884, 0x44421183, 0x52232006, 0x80410591, 0x085e430b, 0xdd34f721, 0x06e0415f, 0x09dffe18, 0x820ad721, 0x28f722b2, + 0x4bc919f6, 0x50ff2017, 0x07200bb9, 0x5a0c9f42, 0x951805ce, 0x4b220cd4, 0xdf4144fb, 0x34b32109, 0x92062244, 0x231d44f0, 0x44124c41, 0x8f6b061d, + 0x8d002007, 0x21191990, 0x0fa0510d, 0x1d44ff20, 0xcaff1814, 0x44cb200c, 0x0f420b1d, 0x43909211, 0xec84095e, 0xec930482, 0x410e5e43, 0xcc20097d, + 0x072f5218, 0x8c095e43, 0x1a7d4190, 0x18cccc21, 0x43102652, 0x01100d5e, 0x2d70017e, 0xa000ff0e, 0x14f79a19, 0xeeffff15, 0x6018295c, 0xa121083d, + 0x230a8248, 0x081e45ef, 0x60180685, 0xa128073a, 0x1100ff48, 0x088bd7a3, 0x16850685, 0x5e0e0029, 0x00ff8bb8, 0x82e2ba10, 0x2406832d, 0xaef1ffff, + 0x211b8214, 0x9e59b85e, 0x8fb62708, 0xd6ffff5c, 0x66829a99, 0x707df325, 0x820c00ff, 0xebff2304, 0x5e8271bd, 0xda18f320, 0xff250894, 0xff717df3, + 0x820f82ff, 0xb8eb2215, 0x21258252, 0x0f828f82, 0x82908221, 0xf53f286e, 0xc0ffffc3, 0x83059002, 0x84902015, 0x00ff2415, 0x82904214, 0x820c2078, + 0x0c002340, 0x2582ec7c, 0x30820c20, 0x0f820020, 0x14221582, 0x2582ae47, 0x6b835082, 0x3b820820, 0xff3d0a31, 0xf4fd3f00, 0xc9ffff05, 0xffff295c, + 0x8e6666a9, 0x9a9921f3, 0xee227782, 0xc5826666, 0x0682ff20, 0xff23dc85, 0xa69a99f1, 0xb89e26f3, 0x2b1000ff, 0x05484184, 0xff278c82, 0x01ff15ae, + 0x82a4b079, 0x19912166, 0x1d364482, 0xffff4861, 0xff33339b, 0x0a17b3ff, 0xe6f4ffff, 0x98ffff66, 0x9b8248a1, 0x3233fd27, 0x4fedffff, 0x203f825c, + 0x282382a1, 0xffccccf0, 0x0ad71200, 0x2244828b, 0x82299c10, 0xa30c2ccc, 0x0d00ffd7, 0x00ffec11, 0x8271fd01, 0xe17a2125, 0x06371a82, 0x00ff1bef, + 0xff513839, 0xa7463200, 0x142c00ff, 0x3b00ff7c, 0x8288a4b0, 0xb547351a, 0xfcffffc2, 0x00fff067, 0xffd8632d, 0x24c6b6ff, 0x66f1ffff, 0xb9226f82, + 0x6f8286eb, 0xf272f927, 0x59e2ffff, 0x2c14829a, 0xffffa826, 0xffaec7e4, 0x1e05eaff, 0x221a8275, 0x82862bef, 0xea512dc0, 0xf2ffff05, 0x8b0700c0, + 0x99e0ffff, 0xe9312782, 0xffff3e4a, 0xffead1e5, 0x4721e2ff, 0x99faffff, 0x2a2b829a, 0xffe1faf0, 0xe23afdff, 0x83f3ffff, 0x66f22623, 0xffff8b68, + 0x05a54bf0, 0x5238ec26, 0xe11100ff, 0xd72bcd83, 0x1300ff0c, 0x00ff0080, 0x82cc4c03, 0xeb372c9b, 0x0900ff84, 0x00ff6871, 0x82c4b52b, 0x46d629a0, + 0x450600ff, 0x3800ff1e, 0x00329b83, 0xff2a1c28, 0x14ae2800, 0xc71600ff, 0x3500ffac, 0xf4822045, 0x8290c221, 0x32f3211e, 0x02213d82, 0x25578278, + 0xff70bd50, 0xcf82cbff, 0x824b0021, 0xb1ff2204, 0x224c82e6, 0x82a4b014, 0x4cd02892, 0x7effffcc, 0x82155c4f, 0x5c0f273e, 0x1100ff8b, 0xcf82a4f0, + 0xff240a83, 0x08a4f0e9, 0x1906556a, 0x210f528d, 0x621800ff, 0x621809a2, 0x30250dd0, 0xffffae87, 0x210482d8, 0x79822700, 0x78cfff24, 0x66828b52, + 0x16850683, 0x80d8ff23, 0x22548200, 0xa50080cf, 0x33b3215b, 0x0d229482, 0x2d82cd4c, 0x9a560020, 0x9d210815, 0x00ffcccc, 0x1500e0c4, 0x17f0ffff, + 0x0700ff0a, 0xffff1098, 0xff2adcec, 0xf43ff9ff, 0x63f8ffff, 0x211882d6, 0x8582f210, 0xf067f822, 0x07260a82, 0x0600ffae, 0x238212c4, 0xfff6e826, + 0xb6f20f00, 0x66362382, 0x00ff0866, 0xff723d2f, 0x0a77e9ff, 0x801e00ff, 0xccffff00, 0xa8829082, 0x42e6c621, 0x846d05df, 0xf45b1820, 0x08af8208, + 0x34b35123, 0x33d3ffff, 0x4a00ff34, 0xffff281c, 0xff9899ba, 0xa4102100, 0xf7ef0e08, 0x1564f75c, 0xf01000ff, 0x262682a4, 0xff66260f, 0x8247f5ff, + 0xa305228f, 0x369982d7, 0xff08cc0c, 0x19e40500, 0x57efffff, 0x1200ff0a, 0xffff6c47, 0x822045f7, 0x86ab212e, 0xe3221882, 0x0a8208d6, 0xb482a820, + 0x18e40527, 0xba0800ff, 0x232383e2, 0xfaffff6e, 0x00236482, 0x8284ab10, 0x21f522e2, 0x24be8248, 0xffff49a1, 0x2c7483e7, 0xff991917, 0xce4ce2ff, + 0x190a00ff, 0x283d829a, 0xff14ae4f, 0x90c21600, 0x20488205, 0x263e82fa, 0xffe6db04, 0x82d90900, 0xb311289e, 0xfbffff76, 0x829cd823, 0x82fb2044, + 0x10002697, 0xffffe0fa, 0x233a83ee, 0x7a9ad909, 0x1c211b82, 0x271a822a, 0xffcccc9c, 0xd6a3e3ff, 0x50274082, 0x00ffecd1, 0x82ae4745, 0x6b0d210a, + 0x0b2a9f82, 0x00ff0080, 0xffcc8c01, 0xf9821400, 0x7ff4ff27, 0x0d00ffbe, 0x2294836b, 0x79d082f4, 0xeb2206b9, 0x2382cecc, 0xff229025, 0x8299f2ff, + 0x7bf42299, 0x205382e6, 0x220a839b, 0x82f8e8a9, 0x54162648, 0x3000ff7b, 0x225e8363, 0x82196407, 0x820c20a4, 0xfff8316e, 0x1300ffe5, 0xffff9002, + 0xff0cf3ef, 0xf6680700, 0xef223482, 0x0a8215ee, 0x78e05a26, 0x10f9ffff, 0xf8224f82, 0x1f823d8a, 0x82ccec21, 0xfaab391a, 0x0550fbe1, 0x29f6ffff, + 0xffff7579, 0xff02ebfa, 0x9a19e8ff, 0xe7ffff8b, 0x2205cb41, 0x8234b3c4, 0x9a193764, 0xe6cfffff, 0x3b00ff66, 0x088bcd4c, 0xe66300ff, 0x0000ff67, + 0x8582a401, 0xb8de1f31, 0x490200ff, 0x1d00fffc, 0x00ffaf47, 0x829e0f11, 0xe0fa2604, 0xd41a00ff, 0x2c29827a, 0xfff8d309, 0xa4b00e00, 0x10fcffff, + 0x82998220, 0xf1ff222d, 0x22138253, 0x829ad909, 0x59f12a7e, 0x0900ffdc, 0xffffb8cd, 0x206383ec, 0x260483fc, 0xff3333f6, 0x834cf1ff, 0x80f82a9d, + 0xf4ffff00, 0xffff68e6, 0x20f783f3, 0x063372f9, 0xff298282, 0x8ba4f0e9, 0x0feeffff, 0x836e825c, 0x1600230a, 0xf7425c0f, 0x4c012918, 0x04f79899, + 0x9cffff15, 0xff226083, 0xf182fafe, 0x4821e02c, 0xb6fdffff, 0xe2ffff04, 0x498252b8, 0x8262f021, 0x1e052604, 0x2be5ffff, 0x21998286, 0x04822cf6, + 0x824ff121, 0xef03225e, 0x829e82e0, 0x0e00222d, 0x221382ac, 0x826626f6, 0xa80e27d7, 0xf6fffff6, 0xd2822130, 0xffd6e326, 0xefe70300, 0xdc21c782, + 0x21eb822a, 0x1e82e0af, 0x6470072f, 0x1c0b00ff, 0x0c00ffed, 0x00ff6666, 0x23bd8207, 0x66660d00, 0xa783b882, 0x82143a44, 0x24cf85d0, 0xc2f5eeff, + 0x82df84ff, 0x0fef2b6d, 0xffff8b5c, 0xff9ad9f0, 0xa6830a00, 0x285cfa27, 0xf30f00ff, 0x221a8233, 0x42e81bfa, 0xff3205e2, 0xff92b8ed, 0xe1ba0800, + 0x54efffff, 0xfaffff7c, 0x1e82291c, 0x0a57ef22, 0x1b250a82, 0xf7ffffe7, 0x27d58245, 0xff94b8ed, 0xd8e30500, 0x7a202383, 0x0a21a182, 0x261e82d7, + 0xff2a5ce1, 0x82631800, 0xdee82614, 0x1d00ffb8, 0x22e982ba, 0x8252f8f5, 0x51b0223d, 0x228382ec, 0x8205703d, 0x8205202f, 0x24fb223e, 0x21ef8218, + 0xa2826826, 0xff8c4c26, 0x28dc0400, 0x04224483, 0x1f8510d8, 0xb7110023, 0x221f824c, 0x829cb81e, 0xd8e3211b, 0x63275f82, 0x00ff3433, 0x820a571c, + 0x2eaf2740, 0xbaffff14, 0x0a8252b8, 0x7a94f23b, 0x80f4ffff, 0xfeffff00, 0xffff3473, 0xffcccceb, 0x42800b00, 0x94f2ffff, 0x2134827c, 0x6a82850b, + 0xff240a82, 0xc4351400, 0x70262382, 0x0d00ffa4, 0x23826666, 0x82d08221, 0x8364201e, 0x1756210a, 0xe9275383, 0xffff86ab, 0x822a9ccf, 0x9bf82253, + 0x208482e8, 0x316e82f3, 0xff1a0007, 0x70fdecff, 0x0c1000ff, 0xf8fffff4, 0x34820a97, 0xbe831020, 0x1aa4f831, 0x071300ff, 0x0600ffb0, 0x00ffe4ef, + 0x82846b07, 0x68122123, 0x542a1e82, 0x50f72005, 0x0900ff05, 0x7583c8d6, 0x00ff8231, 0xff981905, 0x66e61700, 0x1800ff8b, 0x82089a19, 0x4c3b2206, + 0x216c82cc, 0x094368e6, 0xb3c43206, 0x0e088b30, 0x00ff54f7, 0x1566e680, 0xccf9ffff, 0x823582cd, 0xf7ff219b, 0x03230983, 0x82ff9a19, 0x8bcc2209, + 0x83068508, 0xffce2505, 0x66e6fcff, 0xe0462a85, 0x99762106, 0x04822682, 0xf922c182, 0xad8257b9, 0xfc221f83, 0x2e8442e0, 0x3a848b20, 0xff227b82, + 0xd882b3ed, 0xc3f50e27, 0x33f3ffff, 0x21b48232, 0x5782d723, 0x30080023, 0x27978221, 0xff273108, 0xbe1f0300, 0x3d21d582, 0x21048271, 0xd0823c3f, + 0x88828920, 0x04820020, 0x0622d382, 0x15843b3f, 0xbf252483, 0x310800ff, 0x21348368, 0x5782142e, 0x2e08002d, 0xfdffff14, 0x00ff1bcf, 0x823a5407, + 0x33b32198, 0xee820982, 0x00ff9326, 0x159a194f, 0x16202882, 0x24065b43, 0xf01100ff, 0x05f246a4, 0x15825e82, 0x2214be42, 0x1800c0f2, 0x2007a666, + 0x18098240, 0x46109c69, 0xff2866f9, 0x9a193701, 0xe6d000ff, 0x2605067e, 0xffff2230, 0x8342e0fc, 0x822620fb, 0xc4c027e4, 0x3d0600ff, 0x0a880870, + 0xffff722a, 0xff98cef7, 0xca210300, 0xcf220982, 0x1a828b5c, 0x0682f720, 0x3a850c84, 0xc2f9ff23, 0x202f8390, 0x281a8282, 0xff6085d7, 0xe2bad5ff, + 0x20108305, 0x22048684, 0x8240e0fc, 0xd8ce222e, 0x2034848b, 0x20068408, 0x215282e0, 0x16847c1f, 0x83058141, 0x87082045, 0x84c0210a, 0x68209083, + 0x40205f83, 0x30210982, 0x05d241a4, 0x848ba421, 0x203a830c, 0x212a82c0, 0x04820040, 0x827c3f21, 0x61292435, 0x8200ff48, 0x82052004, 0x12432110, + 0x02221a86, 0x2e843433, 0x092a3482, 0x2b087a14, 0x802dffff, 0x0d821500, 0xaec73922, 0x1729a482, 0x7700ff0a, 0xffffecd1, 0x2dd5857b, 0x8b666666, + 0x66eaffff, 0x69ffff67, 0x0a823333, 0x6766f622, 0xee31ab83, 0x00ff14ae, 0xff71fd0e, 0x71bdf1ff, 0xc21100ff, 0x10194a90, 0x194aeb20, 0x08e22108, + 0xb6357c82, 0x3700ff04, 0x00ffd863, 0xff1b4f2f, 0x5c0f2b00, 0x2e3900ff, 0x21358314, 0x58827350, 0xc01e0028, 0xb4ffff00, 0x6382a370, 0xc3f5d322, + 0xc6206383, 0xff212382, 0x279683d9, 0xffceccd7, 0x9ad9f7ff, 0xd7270482, 0xffff0808, 0x84142eef, 0x3f114a04, 0xcc0cee22, 0xb821c582, 0x21c58252, + 0xc5822adc, 0x835c4f21, 0xce04288f, 0x00ff8b14, 0x82ecb15f, 0x5720081b, 0x0a00ff0a, 0x00ff32b3, 0x082a5c62, 0x5e3d00ff, 0x3e00ffba, 0x00ffa430, + 0xff008002, 0x66664800, 0x15282982, 0x0e08cccc, 0xcc4a01ff, 0xcd2d4c82, 0xff1533b3, 0xce4c94ff, 0x332100ff, 0x2c9f8233, 0xff3333f3, 0x67e60300, + 0xb3f2ffff, 0x07ae4333, 0xc9821920, 0x6766f322, 0xfc2ac982, 0xffff9919, 0xffcc4cf3, 0x14830700, 0x9a99f226, 0x990c00ff, 0xfc221382, 0x6f829a19, + 0x14832f20, 0x66e6ee22, 0x382e4882, 0xff0666e6, 0xd763f4ff, 0xf5ffff8b, 0x4a82295c, 0xfff02726, 0x5ccffdff, 0x9a221482, 0x0a8208a0, 0xffcd0c2d, + 0xd6a3f0ff, 0xae0b00ff, 0x84ffff14, 0xcf0e214a, 0xf725d182, 0x00ff0614, 0x20aa8404, 0x215f8203, 0x0a83fcff, 0x99fbff24, 0x4a82089a, 0xff200682, + 0x04861183, 0x8b200e82, 0x60204b82, 0xd9206cab, 0xce256c87, 0xf7088b98, 0x206cb034, 0xbf6cab80, 0xaba020d9, 0x4115206c, 0x64200c46, 0x4228d982, + 0xff8bae47, 0x52b83500, 0xba210482, 0x290a82e2, 0x081e4542, 0x072000ff, 0x0c8207ae, 0x5e353608, 0xddffffb8, 0x00ff9a19, 0xff34332f, 0x32b3cdff, + 0x191100ff, 0xffff0899, 0xffce4c7a, 0xcdcc3e00, 0x0500ff15, 0x00ff6afc, 0xffe42502, 0x82550600, 0x550100ff, 0x22098280, 0x828bf5a8, 0x82052246, + 0x2745820c, 0xff657b05, 0x8430ffff, 0x82262a82, 0xfeffff8f, 0x1a82e856, 0x291c1032, 0x06fbffff, 0xffff0568, 0xff8f02eb, 0x94434200, 0xfc320a82, + 0xff960080, 0x6766f5ff, 0xcf0700ff, 0xf4ffff5c, 0x30826666, 0x8268a621, 0x7df02271, 0x350a8271, 0xffff6831, 0xff51b8f6, 0x28d1f0ff, 0x750400ff, + 0xf1ffffc3, 0x4f8246e1, 0x826e0f21, 0x59cf26dc, 0xb6f7059a, 0x220982ae, 0x82e2baf2, 0xfce62173, 0x51214c82, 0x260482ea, 0x00ff0e30, 0x820a1700, + 0x00c021ff, 0xfd224c82, 0xce8202eb, 0x82c2f521, 0x05c42772, 0xbd00ff1e, 0x0a82cccc, 0x0681fc27, 0x110b00ff, 0x212f82ec, 0x8182e650, 0x823eca21, + 0x52782181, 0xa6217682, 0x20818466, 0x82818870, 0x20818614, 0x208183c4, 0x21818248, 0xb0828f26, 0x66e68528, 0x0100ff05, 0xdc82fe54, 0xff7ac925, + 0x82a9fdff, 0x81fb2282, 0x210e8288, 0x3d82f6c8, 0x82c0aa21, 0xc9fb2248, 0x210a8278, 0x148204ab, 0xff8a8125, 0x82560200, 0xaafe2709, 0x0400ffc0, + 0x1e828636, 0x8182d020, 0xb3970023, 0x2691c032, 0xffb85e2b, 0x823376ff, 0x82918248, 0x8efb208c, 0x820e8391, 0x2691a177, 0xff3e8ade, 0x82666a00, + 0xfcff29da, 0x00ffe07a, 0xfff0270b, 0x22055b75, 0x483eca07, 0xa82107c9, 0x1da541f6, 0xff08482a, 0x67262200, 0xe693ffff, 0x23084882, 0x32b34900, + 0x3de9ffff, 0x00ff0571, 0xff162e3f, 0x289ceaff, 0xe62b00ff, 0xc4ffff66, 0xff8b0180, 0x66e6bcff, 0x21084f82, 0x070a17e4, 0x452600ff, 0x1500ff1e, + 0x00ff862b, 0xff900219, 0xea112800, 0xb80000ff, 0x2d00ff52, 0x5582c475, 0xc2b57029, 0xffffff07, 0x75ffcccc, 0x20080596, 0xff0080f4, 0x9a990a00, + 0xccf2ffff, 0x0e088bce, 0x9600ffef, 0x01ff33b3, 0x15e23a63, 0x4c2c00ff, 0x838882cd, 0xcc382122, 0x1a200982, 0x44235b83, 0x828b3333, 0xcc503748, + 0x00ff8bcc, 0xff34b340, 0xf628dbff, 0x192f00ff, 0xd4ffff98, 0x1a82703d, 0xd0cc2e22, 0x53820a82, 0x4c1f0023, 0x826b82cc, 0x0e0021a8, 0xff237182, + 0x826766db, 0x8303201e, 0x19f82214, 0x06af5399, 0x83fcff21, 0x19f82243, 0x21c2829a, 0x448299f2, 0xed83df20, 0x9c19e525, 0x82d2ffff, 0xd8ff2779, + 0xffff6466, 0xe18266d7, 0x33690022, 0xad236d82, 0x82059a99, 0x68662ab2, 0xccf7ffff, 0x0100ffce, 0x201f82e6, 0x826382f0, 0x2177820e, 0x488399f5, + 0x6e83f720, 0x4d83f520, 0x1e83f020, 0x4d83fe20, 0x9c99f522, 0x2e06b462, 0xf8feaffd, 0x02d001ff, 0xffff058e, 0x826891f5, 0x162e2b15, 0x2bfeffff, + 0x0f00ffc7, 0x0e827a14, 0x82502d21, 0x1a6f2161, 0x0822ac82, 0x0a82912d, 0x83986e21, 0x827b2019, 0x3ad4216c, 0x70210e82, 0x217b82a4, 0x1e82b0d2, + 0xd7e36f26, 0x57a8ffff, 0x002c4882, 0xff676648, 0x1e45c7ff, 0x5a00ff15, 0xb922e183, 0xa7823333, 0xb2820420, 0x82080021, 0x02002fc7, 0x00ff6666, + 0x8b9a9909, 0x190b00ff, 0x06820899, 0x9a990a2a, 0x19fcffff, 0x0a00ff9a, 0xfb20ae83, 0x09222583, 0x5682ce4c, 0x0f820220, 0x4c000029, 0x0200ffcc, + 0x838ccecc, 0x8bcc2805, 0xb68bc008, 0x82568b60, 0x053b5138, 0x9a19fd29, 0xffff857e, 0x823433f4, 0x82272030, 0xe1ff233b, 0x7182cccc, 0x50830b20, + 0x82661421, 0x830620d5, 0x66172240, 0x206a8266, 0x05e27019, 0x71834e20, 0x2b82bf20, 0x82410021, 0xb0ff338d, 0x088b0080, 0xb3daffff, 0xffff8b34, + 0xff66e6dd, 0x0483f0ff, 0x2082e620, 0xb3e8ff22, 0xaa205783, 0xfe2e0a82, 0x159a19c0, 0x0cadfeff, 0x0901ffcc, 0x628234b3, 0x33f30727, 0x990d00ff, + 0x26cf8299, 0x00ffe27a, 0x82ce4c0e, 0x8f0221d3, 0xcc310983, 0x6b01ff08, 0xb2fb2a1c, 0xefffff05, 0xffff9899, 0x218e82f7, 0x4682eeff, 0x83f8ff21, + 0x82ed207c, 0xfaff2e2b, 0x8b086666, 0x98feff07, 0x00ff28dc, 0x245d83c9, 0xae47fdff, 0x055d5fff, 0x8287ff21, 0x83072009, 0xcf0122ba, 0x2113825c, + 0x528233b3, 0xb81e2828, 0x0018ffff, 0x154b0501, 0xe6ff2306, 0x6b718866, 0xfcff2305, 0xc48366e6, 0x3333af22, 0xbf2ac482, 0x00ffcd4c, 0xffcccc24, + 0xc982d0ff, 0xcc2b0023, 0x25df82ce, 0xff5238d1, 0x51822c00, 0xb8e0ff22, 0x33200982, 0xf1209183, 0x29085082, 0x34b32300, 0x0e068b08, 0xf854f82f, + 0xe4fb1524, 0xc0ffff07, 0xfffff6e8, 0xffc275e9, 0x00c0ecff, 0x8af6ffff, 0xdaffff3e, 0x60830ad7, 0x142ec122, 0xe8286082, 0xffab5238, 0xcd4cc1ff, + 0xeb241283, 0x7b8b6766, 0x66249182, 0xf1ffff66, 0xfb200483, 0xcb24d882, 0x0e00ff07, 0x0027ea82, 0x9b9a9904, 0x830300ff, 0x9914220a, 0x2f2f8299, + 0xe1ba3e00, 0x1700ff8b, 0xff6baec7, 0x3eca3e00, 0x14221283, 0x12826666, 0x34330f26, 0x1300ff8e, 0x0626b283, 0xf708cc4c, 0xde4e0764, 0xb3f92706, + 0xf0ffff34, 0xec82cccc, 0x9a99eb22, 0xcd208696, 0xe725fa84, 0xffff67e6, 0x2c8583eb, 0xff33b3d7, 0x66e6f7ff, 0xccfeff08, 0xd8aa18b3, 0x18ab200a, + 0x22238aaa, 0x6e8001ff, 0xc52106a4, 0x06c66a1e, 0x7c540e27, 0xc51000ff, 0x847e821f, 0x210c8206, 0xf1824821, 0x8b84ab2d, 0x3aefffff, 0xffff08e2, + 0x82a470f2, 0x4c2836f6, 0x0800ffcd, 0x00ffae07, 0xff991918, 0x48a11400, 0xcc3200ff, 0x22fa96cd, 0x82343325, 0x331334fa, 0x0900ff32, 0x00ffc275, + 0xff9a193f, 0x3e8a1600, 0x82ef0e08, 0x19402f17, 0xffcb159a, 0xa8f5ffff, 0x1100ff05, 0x128200c0, 0x00400e22, 0x4a219182, 0x330a823e, 0x0870bd11, + 0x9cdf00ff, 0x8b2b0744, 0x00ffff05, 0xbb076666, 0xcc224182, 0x808215cc, 0x07202c84, 0xff232c82, 0x82cae1f8, 0x20f723a2, 0x068308c6, 0xff0c4226, + 0x00c0f8ff, 0x84250483, 0x40f7ffff, 0x84988200, 0x23168506, 0xae470700, 0x08225a82, 0x2d8232b3, 0xe6080025, 0x8300ff66, 0x07002144, 0x08209783, + 0x08285482, 0xcc2c01ff, 0x0001ffcc, 0x32829a82, 0x821a0f21, 0x47f82654, 0xfdfffff0, 0x32048207, 0xffd823fa, 0x18a4faff, 0x9dffff08, 0xffffb89e, + 0x822c07a6, 0xe6ff2799, 0xffffff67, 0x2a82cccc, 0x0a830582, 0x7583cd20, 0x6666ef31, 0x66f0ffff, 0x0000ff68, 0xffffcd4c, 0x829919e7, 0x333321d9, + 0x80211382, 0x20d88200, 0x20a5830c, 0x2a8183f2, 0xff48a11a, 0xe27afbff, 0x821000ff, 0x0e002313, 0x1e82b8de, 0x842b0022, 0x26203882, 0x8a82a082, + 0x0582b282, 0x19210f82, 0x281a829a, 0xff48e14f, 0x99194900, 0x054d4305, 0xde050024, 0xc461fffa, 0xa0ff2305, 0x0e82ff00, 0xf9269982, 0x91080681, + 0x0682ffff, 0x80268f82, 0xf5ffff00, 0x0e8242e0, 0x85008022, 0xe520bb82, 0xff234082, 0x824821e8, 0x83912040, 0xe38922c6, 0x210a82d6, 0x2682e002, + 0x0681fd25, 0x820200ff, 0xfdff2146, 0x00223582, 0x13836002, 0x82064121, 0x57c23075, 0xffff078e, 0xff1e05d7, 0xc2f52800, 0x83c8ffff, 0xeb16271f, + 0xc6ffff86, 0xef837c14, 0x3253f722, 0x38336b82, 0xffff0552, 0xffceccf1, 0x9a9966ff, 0xffff6d15, 0x828f82e4, 0x40e22111, 0xe4224882, 0xf045d7e3, + 0x02002105, 0xe5277683, 0x00ff3373, 0x836bdc1c, 0x82332091, 0x511d220a, 0x297b82aa, 0x00ff9a19, 0xffff7f2d, 0x13831d00, 0xcecc1a22, 0x51277b82, + 0x00ffcdcc, 0x8266e64a, 0x66f92348, 0x72820666, 0x8b333322, 0x66268282, 0xe8ffff67, 0x968284eb, 0x82991921, 0x162e2204, 0x82818208, 0x20ff232b, + 0xd1829a19, 0x74831220, 0x8ef6ff22, 0x5a200a82, 0xff23ad82, 0x82142eae, 0x831b200a, 0xa1e9220a, 0x82c78248, 0x0512611f, 0x09831620, 0xb25d1b22, + 0x12276b82, 0xffffb81e, 0x8290c2f0, 0xe10f2a29, 0xf3ffff48, 0x00ff66e6, 0x29338217, 0x9a990100, 0x0f00ff98, 0x2582fade, 0x82611f21, 0x9926213f, + 0x05276583, 0xffffbe5f, 0x828480fb, 0xc00d2730, 0x00ff8000, 0x1b822114, 0x7cff0125, 0x820b00ff, 0x8200204b, 0x22308214, 0x82ba8909, 0xaec7210f, + 0x15872582, 0xfdffff23, 0x262e83ea, 0xffffae07, 0x821e45f2, 0x6626211e, 0x6a27c082, 0x00ff84c0, 0x82e45179, 0x66d12a29, 0xff15e466, 0x666620ff, + 0x20ee8207, 0x207383ee, 0x29a9820e, 0xec91f1ff, 0xd91000ff, 0x58828b98, 0x68e64027, 0x0c0000ff, 0x2b2e82cc, 0x0766e6ff, 0xffffff2b, 0xbb0534b3, + 0x3b823584, 0x0040f722, 0xf82e3a82, 0x00ff00c0, 0x8bfa3e07, 0xbe0800ff, 0x06830876, 0x1183e020, 0x00234c82, 0x43701d07, 0x4c820550, 0x57430820, + 0xecd1210a, 0xf7223882, 0x2d829a19, 0x4cf7ff26, 0xf8ffffce, 0x2d074b5b, 0x3433f7ff, 0xff0e088b, 0x9a99ed01, 0x6482b1f7, 0xe783e720, 0xb89e1325, + 0x83ebffff, 0x820f20a3, 0x89ff286d, 0x00ff3233, 0x82e23a56, 0x66ef21d1, 0x0c2da282, 0xff6aa430, 0xc2351d00, 0xb3e8ffff, 0x24b98232, 0x3433ffff, + 0x330c8306, 0xff6a8b33, 0x3ecae2ff, 0x4cefffff, 0xf3ffffcd, 0xff087ad4, 0x33233e82, 0x83a9ffff, 0x66eb2748, 0xf1ffff67, 0x42436826, 0xebff2305, + 0x1e820080, 0x8273f421, 0xfaf6291e, 0xf9ffffe0, 0x8b7d0040, 0x33242082, 0xfeff0833, 0x4018a282, 0x6018096c, 0xf8200d6d, 0x00236c82, 0x8290821a, + 0x7d1521fb, 0x08fe5b19, 0x2a9c1926, 0x0801ff08, 0x21058474, 0x7e82cc0e, 0xcc4cf929, 0xf4ffff99, 0x8294ce4c, 0x99412266, 0x21a6829a, 0xe3820080, + 0x66e6f123, 0x26a18280, 0xffff6666, 0x820080fa, 0x05584709, 0x0682ef20, 0x70260c82, 0x0500ffa4, 0x8782e87b, 0xff66e626, 0x6afc0a00, 0x6f313c82, + 0x00fff628, 0x0548a170, 0x662e00ff, 0x00ff0766, 0x08108315, 0x0a971021, 0x511900ff, 0x1300ffeb, 0x00ffec11, 0xff85eb6d, 0x0ad74f00, 0x0300ff08, + 0x00ff142e, 0x82f85302, 0x82b62009, 0xdb022733, 0x0400ffe8, 0x0e82c816, 0x827e2a21, 0x8505221e, 0x210f821f, 0x5e82fe34, 0xff67e626, 0x52780800, + 0x33210482, 0x21778233, 0x1e824821, 0x19820820, 0xdefaff23, 0x261e8276, 0xffffdaee, 0x82f087f7, 0x50782619, 0xc2fbffff, 0x271e8290, 0xff0a1704, + 0x80d5fcff, 0xb6264d82, 0xfdffff04, 0x09829623, 0x82585921, 0x8c8c2109, 0x6d271e82, 0xffffd823, 0x8272a8b0, 0x34b3269a, 0xccecffff, 0x83ae82cc, + 0x33ef22eb, 0x27ca8234, 0x0714aed1, 0x336fffff, 0x8f2e1a82, 0x0e05ec51, 0x54f814f8, 0x06b4fb15, 0x2b63ffff, 0x72992007, 0xfc230bda, 0x848b0714, + 0x63ff201a, 0xff270817, 0x9a592300, 0x82f7088b, 0x5f098433, 0x1c2206e4, 0xf95f66a6, 0xf8082105, 0x1a833383, 0x24103f73, 0x14fb24fb, 0x853f8515, + 0x63ff2035, 0x66860967, 0x80841183, 0x8b217584, 0x21068208, 0x1b82f6a8, 0x0a57e322, 0x63863284, 0x11820685, 0x9f18b320, 0xeb270cb7, 0xfb1594fb, + 0x63ff0654, 0x325f0a22, 0xff75180d, 0x06cb2613, 0x2e2c00ff, 0x21528314, 0x6f82ecd1, 0xff240a83, 0x08ecd1d3, 0x18e1d618, 0x15d4f726, 0x072b067b, + 0x1871e119, 0x8207cb21, 0x06fd7a4c, 0x200c2e60, 0xa2ff828b, 0x12d75f39, 0xd621398c, 0x205f8204, 0xd9901807, 0x5f73850d, 0x0e221224, 0xb618f8af, + 0xfb226b77, 0xe2412be4, 0x66a62231, 0x05f4418b, 0x46420020, 0x20e24109, 0x0892c618, 0x2013e241, 0x397318d1, 0x30e2410c, 0x15cb7427, 0xff0614fb, + 0x08ed72ff, 0x648dff20, 0xcccc0822, 0x04861184, 0x8b220e82, 0x6e18f708, 0xff210da3, 0x0fec60f8, 0x200f7745, 0x2064938b, 0x23f78233, 0x08cdcc08, + 0x092fd518, 0x64833420, 0x00ff3322, 0xcd206496, 0x200b0066, 0x08dc4533, 0xbc85cd20, 0x64940820, 0x830e7565, 0x73c9bcdb, 0xfb3262d5, 0x00ff1514, + 0x8b1ec527, 0x3a2000ff, 0xdfffffe2, 0xf88290c2, 0x703dd823, 0x20068408, 0x21118271, 0x0482cccc, 0xff8fc224, 0xaa74d8ff, 0x3dd82205, 0x201b8271, + 0x211182df, 0x0a832000, 0xc2270023, 0x822d828f, 0x82902006, 0x33332144, 0x3d210482, 0x2c548270, 0x088bcdcc, 0x15d4fb8b, 0x11cbffff, 0x213182ec, + 0xb36c07d0, 0xffff2205, 0x262483dd, 0x0890c222, 0x831000ff, 0xcf29310a, 0x00ffb35c, 0xff66e61d, 0x00802f00, 0x06cb088b, 0x8a280882, 0xffb38b3e, + 0xb81ee2ff, 0x28272482, 0xd6fffff6, 0x8308862b, 0x8232203a, 0xc2352704, 0xeaffff5b, 0x5a820080, 0x8b9a1928, 0x30fb0e08, 0x7045e4f7, 0x18e52007, + 0x19136467, 0x20091c26, 0x64671800, 0xb4f7210e, 0xf6466c82, 0x22108210, 0x1834f808, 0x22183867, 0x4334fb24, 0xb3203c8d, 0x210b3469, 0x0269cc4c, + 0xff342708, 0xcd4c2300, 0x7045088b, 0x839f1809, 0xbd561808, 0x188b200a, 0x4315707b, 0x5b232f8d, 0x1815d4f7, 0x190f19dd, 0x211f2696, 0xa96706eb, + 0x2686180b, 0x05fd650a, 0xf8ffff24, 0x0482cdcc, 0x460ad721, 0x082c052b, 0xa4f8af0e, 0xfc1534f8, 0xffff0674, 0x25149841, 0xd4f8077b, 0x68419b06, + 0xa4fc2317, 0xb31824fc, 0xb841071a, 0x82f8200f, 0x11af4853, 0x90821a31, 0x07c4f708, 0xfb06d4fc, 0x04f807c4, 0x441584f7, 0xda43113f, 0x11a1441e, + 0x211e3c44, 0x64924b8b, 0x440e9165, 0x64910fa4, 0x881e3c44, 0x08a54664, 0x83f8ff21, 0xf7ff260a, 0x8b08fc29, 0x440683ff, 0xd62107a4, 0x06a44404, + 0x19005918, 0x00ff8b23, 0x44268208, 0x292106a1, 0x060645fc, 0xf754fb22, 0x210f4948, 0x5c820a57, 0xf6a8dc23, 0x46068508, 0xff23054f, 0x480a57e3, + 0x66460949, 0xf6a8210a, 0x23225982, 0x2d820a57, 0x06820020, 0x2107d842, 0xd842f6a8, 0xfb4b2206, 0x052b4134, 0x18097143, 0x83111267, 0x84cb82d8, + 0xfc2923c6, 0x7a48088b, 0x16974605, 0x00801a27, 0x7d1500ff, 0x83048271, 0x2e578309, 0x70fb0e08, 0x00ff44f7, 0x159a197d, 0x4fd200ff, 0x082005ca, + 0x4b05f44e, 0xf94e06d4, 0xf8ff2311, 0xe28200c0, 0x0040f73c, 0x2dffff08, 0xff079a19, 0x4761edff, 0x60f9ffff, 0xf2ffff00, 0xffffb89e, 0x208360ee, + 0xb81eeb22, 0xff21dc82, 0x827684e5, 0xeaff2104, 0x5f187684, 0x44180f75, 0x8b240a36, 0xee1400ff, 0x2207b757, 0x829a9911, 0x66662d58, 0x990600ff, + 0xffeb089a, 0x66662c00, 0xa623a482, 0x82070080, 0xde3d2127, 0xcd2d6782, 0x00ff48e1, 0xff482132, 0x1e05c3ff, 0x838d828b, 0xffff2906, 0xff7c14cc, + 0xb8decdff, 0xc222a482, 0x16824821, 0x33825920, 0xecffff23, 0x209f8240, 0x200483e7, 0x25e183f3, 0x8b0040e1, 0x23820869, 0x9683b020, 0x04824020, + 0x83c0ff21, 0x854f206d, 0x210683a0, 0x168300ff, 0x993f0023, 0x8271829a, 0x8b082c10, 0xf3ffffad, 0x00ffcccc, 0x8266e61e, 0x34332450, 0x821800ff, + 0x04fb2a9c, 0x8056ffff, 0xffff1500, 0x207584d3, 0x219282dc, 0x0a832300, 0x3a2b0023, 0x216382e2, 0x5e821900, 0x820c0021, 0x1700227b, 0x20b38261, + 0x099d4f13, 0xce4cc022, 0x9c41cf83, 0x072a4105, 0xb9180020, 0xff271b58, 0x32b33fff, 0x8300ff07, 0xf1ff2144, 0x58835383, 0x82e8ff21, 0xffff22b7, + 0x05cb63e6, 0xccccd423, 0xf09c18ff, 0x0beb4110, 0xeb41a220, 0x105d2032, 0xb601eb01, 0x0d00002b, 0xe67200ff, 0xff8b0566, 0x1bdc4300, 0x66a6f923, + 0x0cdc43ff, 0x8d19ff28, 0x198dffff, 0x0310059a, 0x27b301e1, 0xff0d0000, 0x48e13200, 0x2235f541, 0x10b81ecd, 0xab01f501, 0x00ffa425, 0x100080a9, + 0x3c011e07, 0x14f78b23, 0x167a4b15, 0x17838b20, 0x3c497020, 0xeaff2a05, 0x00ff9082, 0x8b8f821a, 0x85068508, 0x15002416, 0x838b707d, 0x08902110, + 0x74180685, 0x0e231043, 0x82cbb4f7, 0x54ee2160, 0x12337418, 0x08605b18, 0xff7a5426, 0x86abf1ff, 0x14595818, 0x00233883, 0x8386ab11, 0xb3112260, + 0x82288234, 0x05447e04, 0xcc4cee26, 0x14f7088b, 0x60d9c184, 0xbf90cb20, 0x078e5b18, 0x7b23bf84, 0x850e00ff, 0x306819bf, 0x3e671809, 0x211b8209, + 0xd7838b7b, 0xbf858520, 0x111e5c18, 0xfb54fb24, 0x22841514, 0x04418620, 0x834e8406, 0xff0822cf, 0x20d69eff, 0x0837417b, 0x59188520, 0x4b180f2c, + 0xab210896, 0x0f7f41eb, 0x7a20bf8c, 0x7f41bf88, 0x22bf9123, 0x41158bcb, 0x478505b7, 0xab21f08e, 0x20d48884, 0x8fcd857c, 0x8b8421d4, 0x7c211783, + 0xd9881808, 0xcc4c2108, 0xb3213282, 0x25548233, 0x088b34b3, 0xbd8f2b6b, 0x30848620, 0x30847a20, 0xbdad5420, 0x22113d42, 0x82fbffff, 0xe400236f, + 0x6682a4b0, 0xa4b0f428, 0x4f0b00ff, 0x8266055c, 0x06002205, 0x22b3823f, 0x8234def5, 0xc0f92270, 0x82148400, 0x5ef922bd, 0x210a8276, 0x2582785e, + 0x9ad9dc3b, 0x4a1a00ff, 0xd1ffff3c, 0x00ff0a57, 0xffb8de02, 0xc235daff, 0x9eebffff, 0x27298278, 0xfffc5eef, 0x1c9a1000, 0xd9202982, 0x2620d083, + 0xff226a82, 0xda8273bb, 0xba9e042c, 0x54d6ffff, 0xcbffff7b, 0x2982842b, 0x820cf121, 0x0ced2c04, 0xf8ffffce, 0xffff17f9, 0x6c5ccfe7, 0xff22062b, + 0xbb58bafe, 0x33f72605, 0x0700ff34, 0x82141929, 0x0ad72111, 0x082e6c18, 0x25083575, 0x194c01ff, 0x1782079a, 0xaec71322, 0x17208182, 0x10209b82, + 0x13200483, 0x22054f5d, 0x82217009, 0x40092a1b, 0xfcffff83, 0x00ff082c, 0x23f78206, 0xf853f9ff, 0x2405bb70, 0x63efffff, 0x22b282d6, 0x8248a1eb, + 0x723d21cd, 0xcc21d782, 0x82e182cd, 0x1a0022bc, 0x2209824c, 0x8267e6dc, 0x66f927ad, 0xf9ffff66, 0x2982cd4c, 0x82c0f921, 0x82048249, 0xdef522b3, + 0x214f8235, 0x1a827d3f, 0x8200c021, 0x4f0b284f, 0xf4ffff5c, 0x8905a4b0, 0x00ff2415, 0x18cb210a, 0x2008e2a6, 0x20258340, 0x204b82a9, 0x83048200, + 0x90422125, 0x3d212a82, 0x22208270, 0x82d8230a, 0x32b32146, 0x25820f82, 0xcbab0e23, 0x36608215, 0xff14aee3, 0x717d0c00, 0xcce6ffff, 0x1300ffce, + 0xffff9082, 0x82146eee, 0x17d72290, 0x20f2820a, 0xcf5018ff, 0x82e71813, 0x0a52540d, 0x0f00ff2d, 0xf7079a19, 0xffff0694, 0x8466e6f0, 0xd6a6183e, + 0x00ff222b, 0x85358228, 0x11002385, 0x2473ec91, 0x19002305, 0xbe823233, 0x511c2608, 0x00ff08ec, 0x07900220, 0x6b0654fc, 0xf764f807, 0x24fc1514, + 0xb200ff06, 0xff0700c0, 0x52f8ffff, 0xcc0a00ff, 0x218282cc, 0xe282ae07, 0x0e823820, 0x9a990722, 0x59211782, 0x2937829a, 0xffcdcc0d, 0x5238f2ff, + 0xd182ff05, 0xffff3328, 0xff5c0fe5, 0x14830500, 0x9a19e625, 0x830e00ff, 0x4ced2709, 0xffff08cc, 0x1e82b3f9, 0x34b3f922, 0xe6245282, 0xf5ffff67, + 0x00220982, 0x13833306, 0x1e82cc20, 0x81410020, 0x41832011, 0x3f210d81, 0x246e827d, 0xff666669, 0x20048200, 0x21898205, 0xa9187c3f, 0x9b180e90, + 0x20430805, 0x827e2011, 0x0b204370, 0x90828220, 0xcd4ced22, 0xb522a082, 0xb08271c2, 0x70c4b522, 0x2321c082, 0x201682d6, 0x239382f2, 0x1ec50d00, + 0xf120d182, 0x0023e782, 0x5fd8630e, 0x002905c0, 0xff004008, 0x33b3ebff, 0x2825828b, 0x8b295cd5, 0x57ddffff, 0x8204840a, 0x68d5220a, 0x241682f6, + 0x0734334d, 0x06a65b7b, 0x52f7ff21, 0xec5508f4, 0x416b200a, 0x254309fc, 0x74f8250d, 0x0800ff06, 0x2013bb57, 0x203282ab, 0x05fe7a00, 0x31075756, + 0x3433f7ff, 0x2f0e088b, 0x54f874f7, 0x84ffff15, 0x8282cd4c, 0x33b39b27, 0xb39bffff, 0x230a8234, 0x08cc4c84, 0xa3310682, 0x00ffaec7, 0xff1fc537, + 0xecd1b0ff, 0xa14f00ff, 0x21ae8247, 0xa88232b3, 0x1f85fc26, 0xc01400ff, 0xfd22d082, 0x09825c4f, 0xff0ad72b, 0x082cffff, 0x8f1000ff, 0x361e825c, + 0xff92adcf, 0x34731f00, 0xebdfffff, 0x3600ff85, 0xff8bce4c, 0x83cc3d00, 0x61002854, 0x00ffcc0c, 0x8333f34e, 0xff342104, 0xcd210e82, 0x8237828b, + 0x21228215, 0x3282f34e, 0xcc0cb122, 0x9e227b82, 0x828334f3, 0xc235c222, 0x84284483, 0xb0c9ffff, 0xcfffffa4, 0xe0220483, 0x63820080, 0x7e2aff26, + 0x80efffff, 0x4b2b8283, 0xebffff04, 0xffff4821, 0x828881fc, 0x82332009, 0x4f0028a1, 0x00ff02a0, 0x82ba5e22, 0x22f583c0, 0x8232334f, 0x335c215f, + 0x00225483, 0x6682b37b, 0xff24e982, 0xcc4c6400, 0xcc26fe83, 0xfb8b088b, 0x698215cc, 0x82b81e21, 0xe1e0217b, 0xf7224b82, 0x0a820060, 0x00e0dc22, + 0xde258683, 0x00ffb8de, 0x2a16830c, 0xff7cd4b8, 0x70bd0700, 0x83e3ffff, 0x05002286, 0x3136822e, 0xff32f3ec, 0xcd4c1300, 0x99fbffff, 0x1200ff9a, + 0xd38366e6, 0x16820683, 0x11825920, 0x00600425, 0x820500ff, 0x130023a2, 0xee824801, 0x52b80725, 0x831c00ff, 0xe60c2904, 0x4700ff66, 0xac8b9a19, + 0x00266782, 0xff323323, 0x1283e0ff, 0x48820820, 0x82dfff21, 0x8b082817, 0x00ff15ab, 0x8233f31e, 0x0c1924bf, 0x8200ffcd, 0x820a8204, 0x82308310, + 0xffff2306, 0x628219e6, 0x46181682, 0xe1200870, 0x16848082, 0x6c8b722e, 0xa46c8b08, 0x088baa72, 0x15c324f7, 0x4f253782, 0xffffae87, 0x260482bf, + 0x52784000, 0x74b0ffff, 0x55180536, 0xff200996, 0x0c079f19, 0x842bd336, 0xeb1400ff, 0xd8ffff85, 0x00ff3473, 0xffb91e20, 0x7c94e5ff, 0x0434c182, + 0x00ff64db, 0xff66a60c, 0xe4450900, 0x3a0d00ff, 0x1100ffe2, 0x00232882, 0x82f62809, 0x0200271e, 0x0000ff8f, 0x04825a0f, 0x82cc4c21, 0x57002076, + 0xe9220534, 0x2682cc4c, 0xf120da83, 0x1b20b383, 0xdb821582, 0x8366e621, 0x053522ca, 0x10901820, 0xffe02608, 0x1f053500, 0x8248828b, 0x2d3e8215, + 0xffe0fa2a, 0x2005d5ff, 0xcaffff8b, 0x2d82e0fa, 0x14e1ff2f, 0xf1ffff7b, 0xffff4821, 0xff3dcae4, 0x235883ff, 0x3473eeff, 0x00273182, 0xffff8221, + 0x8280f9ff, 0x7e60217a, 0xfa210982, 0x21048202, 0x138480f7, 0x11271e82, 0xffff14ee, 0x820ad7f6, 0x904231b8, 0xc7f2ffff, 0x0400ffae, 0xffff28dc, + 0x080a57f3, 0x2526e282, 0x1a00ff3a, 0xf682ea64, 0xdc82e620, 0x9a992722, 0x2c297e82, 0x0e08cccc, 0x34f854f8, 0x16f67c15, 0x0319fb20, 0xfc21184c, + 0x0afd5c14, 0x7cff9a21, 0xd1180aca, 0x0021095d, 0x2c40181c, 0x14f8250d, 0x4bf4fb06, 0x2e7c8e18, 0x7518f720, 0x00210db3, 0x081a490e, 0x524ac082, + 0xd4fb2613, 0x8b8b0e06, 0xe2861815, 0x54f82116, 0x0e027618, 0x7a18b320, 0xfc201ed4, 0x0d846218, 0x0e277f8a, 0x14f844f8, 0x5d74fb15, 0x34570c39, + 0x077b220a, 0x05fb564b, 0x142e2c27, 0xcc2300ff, 0x290482cd, 0x00ffecd1, 0x8b33332c, 0x3682f708, 0x15d8c519, 0x0774fb25, 0x18ffff8b, 0x2213658e, + 0x5dcb067b, 0xf720193e, 0x58183683, 0x3f5d073d, 0x44fc210c, 0x1805a34a, 0x2113d47f, 0x7f1894f7, 0x4c200e51, 0x2107857c, 0x7f1894fb, 0x338218d8, + 0x4108f85e, 0x94250dfa, 0x154beb07, 0x0d6241f7, 0x760e0021, 0x67180bd9, 0x63181363, 0xb32110e7, 0x054f4a33, 0x1809564a, 0x230d3093, 0x14f82f0e, + 0x2133b442, 0xb442d4fb, 0xd4f73131, 0xff85fb06, 0x66e64fff, 0x2f00ff15, 0x055c9a19, 0x23057967, 0x9a19d0ff, 0x36fe5c18, 0x00ffba26, 0x0534332e, + 0xe6214e82, 0xfe5c1866, 0x1a458440, 0x358829c4, 0x15eb34f7, 0xf70654f7, 0x54fb0754, 0x0754fb06, 0x44f7b4f7, 0x8c18bb15, 0x8b211786, 0x06c047ff, + 0xff88d62e, 0x34330700, 0x29f7ffff, 0x5b088b78, 0x22053643, 0x5e9a5923, 0x8f5809df, 0x067b2306, 0xdd5807bb, 0xf8ff2306, 0x544bcccc, 0x45f72006, + 0x59480585, 0x083c590b, 0x4b075b22, 0x4218339c, 0x33980ac6, 0x6788cd20, 0x104a4418, 0x7b20338a, 0x20170f62, 0xa4ad187b, 0x0fe45e10, 0x220f1b4c, + 0x914b06bb, 0x0cd85a33, 0x94114f4c, 0x0ea75a33, 0x7b206791, 0x2217aa62, 0x495b069b, 0x43180993, 0xd62310ce, 0x82ff8b87, 0x8379204c, 0x41fc2004, + 0x08230590, 0x86cb07bb, 0x12854b33, 0xb518ff20, 0x33b515dd, 0x63069b21, 0xfe600b0f, 0x189b200a, 0x421972bc, 0xd6210835, 0x42b48488, 0xcb20086b, + 0x6d183385, 0xb36008be, 0xf8ff2111, 0x260f9f42, 0xfb4b07cb, 0x5b8b1554, 0x1e820797, 0x2405d55a, 0x8b7829f7, 0x0e114608, 0xa3454f8a, 0xcccc2106, + 0x33208182, 0x0ca26e18, 0x4374f721, 0x194b0c23, 0x74fb380a, 0x01ff0e07, 0xff9a99db, 0x66e63f00, 0xfaffff15, 0xffff9a19, 0x82ceccf5, 0x32332104, + 0x4c240e82, 0x088b80cc, 0x83210782, 0x278f8212, 0xffb072fa, 0xf0670100, 0xe8260f82, 0x0200fff6, 0x1a8210f8, 0x0a83e620, 0xd8a30e2d, 0x0500ff05, + 0xffff0661, 0x82c2b5eb, 0x6403310a, 0xf3ffff9c, 0xffffa430, 0xffda59f8, 0x0ad7f2ff, 0x2d240e82, 0xfcffff10, 0x2b05227f, 0xffff9eef, 0xff0070ff, + 0x5ceffdff, 0xc0200982, 0xf7210983, 0x226a830a, 0x82b85ef5, 0x45f6226a, 0x20c68220, 0x3d308218, 0xff6626fd, 0xfabe0a00, 0xeeffff08, 0x00ff9042, + 0x0586eb42, 0x22c4ffff, 0x2200ff8e, 0x6a82acf7, 0x0e000027, 0x80b9ffff, 0x270a8200, 0xff486130, 0xb81ecfff, 0x09270a82, 0xffff8856, 0x82e08ff6, + 0xeee7265c, 0xd1f0ffff, 0x210e8268, 0x04828a91, 0x8214ae21, 0x4efb2c4a, 0xfbffffaa, 0xffffec51, 0x8266e6f9, 0x34b32185, 0x80830984, 0x98cef922, + 0xf9218082, 0x216b82cd, 0x97826002, 0x5e4ffb27, 0xc00400ff, 0x28358200, 0xffaec7f1, 0xb85e0e00, 0x22208205, 0x834881e2, 0x4fee2106, 0xf126bf82, + 0xfffff6a8, 0xed82b0f1, 0x0d0d6f18, 0x00201682, 0x099a6a18, 0xff248a82, 0x1d00fff3, 0xff20aa83, 0xff234a83, 0x8248a1f1, 0xadf622cb, 0x22aa8691, + 0x82c1caf0, 0x20f02124, 0x5c240e83, 0x500900ff, 0xf6227483, 0x0a826891, 0xc9834f20, 0xff32e826, 0x20300f00, 0x56210e82, 0x24048266, 0xff08a470, + 0x22f38300, 0x83e13000, 0x28ff2748, 0x4600ff5f, 0x53829889, 0x4821c427, 0x11ddffff, 0x270a82ec, 0xff8f42ee, 0x7c14bdff, 0xfd260a82, 0xffffe926, + 0xd48240f5, 0x9c44f626, 0xe8f8ffff, 0xf522b682, 0xf583b85e, 0x0af7fd22, 0xfd21d482, 0x207682ef, 0x26208300, 0xff9deffd, 0x83900000, 0x2ef32680, + 0x0300ff14, 0x27358260, 0xff9959f8, 0xae270d00, 0x63260e82, 0x0c00ffd7, 0x80825ccf, 0x06610527, 0x4a1400ff, 0x275f823e, 0xfff5e8e6, 0x285cf1ff, + 0xfb210a82, 0x2c5b82c8, 0xffccfcfc, 0x3373faff, 0x99feffff, 0x2109829a, 0x6a838f82, 0x70fdf422, 0xf5266a82, 0x00ff1f45, 0xeb82b005, 0xcc0cfa2c, + 0x310a00ff, 0xffff0828, 0xeb8211f7, 0x7f820f20, 0x25050028, 0x1300ffa2, 0xf0820a97, 0xfff6482c, 0xf6e80800, 0x1900ff08, 0x0f82c3f5, 0x82662621, + 0xabeb225f, 0x213e8285, 0x0a820c82, 0xa430f322, 0x69219082, 0x82d0827a, 0x0d00236a, 0x0e823233, 0x82527821, 0xcecc219f, 0x03203482, 0xb9820a86, + 0xb4822320, 0xfe7f0722, 0xdc261982, 0xfcffff29, 0x1e829a99, 0x82e84121, 0x19ee2da8, 0x00ff059a, 0xff00803c, 0xcc4c2300, 0xc3205382, 0xcd200a85, + 0xbe270a82, 0xffff0a17, 0x829919ee, 0xe3fd220a, 0x07b64295, 0x82d1e221, 0xfdb72609, 0xebfdffff, 0x22d48385, 0x82146ef5, 0x4cf627d4, 0x0700ffcd, + 0x1682f007, 0x82291c21, 0x62b021d4, 0xfc22d482, 0x71826786, 0x82e5d221, 0x828c2019, 0x190d221e, 0x210e8299, 0xa4825ccf, 0x82008021, 0x54142280, + 0x20c9837b, 0x225f820d, 0x823e0ae6, 0x263121df, 0xf0210a82, 0x21c082b8, 0x4982e708, 0x82d9fa21, 0x9813272f, 0x0800ff10, 0x1e8215ee, 0x34834020, + 0x8fe20822, 0x47260a82, 0x1300ffae, 0x3e82719d, 0x82f62821, 0x5c4f260e, 0x0ff7ffff, 0x2053825c, 0x22b38319, 0x822a5cf1, 0x9efa2748, 0x1400ffb8, + 0x0a823c4a, 0x829cfc21, 0xca0c2193, 0x07256382, 0x00ffa4b0, 0x2134830d, 0x9c82e60b, 0xb85e0322, 0x20065750, 0x052d4100, 0xff343324, 0x5d83f8ff, + 0xcc4c0427, 0x38f3ffff, 0x321e8252, 0xff71bd11, 0x7a14bdff, 0x3a00ff05, 0xffffc3f5, 0x82af07dd, 0x241d8253, 0x804600ff, 0x270a8201, 0xff0d80d0, + 0x84eb3000, 0x2406b848, 0xa4700900, 0x2095828b, 0x266a8230, 0xff008009, 0x834f0900, 0x6609229a, 0x210a8266, 0x19829a59, 0xff333325, 0x82deffff, + 0x6609279e, 0xf6ffff67, 0x65820a97, 0x52380e23, 0x061743ff, 0x7b14ff22, 0x82052d43, 0x83112045, 0x570e25b0, 0x0e00ff0a, 0x0020e582, 0x8b220e82, + 0x0684ff08, 0x18056978, 0x290abe6d, 0x000000ff, 0xe2ffff0e, 0xa9820080, 0x00234e83, 0x82b85e0e, 0x4e09220a, 0x21788298, 0x7883f067, 0x2482f820, + 0x92832020, 0x82c27521, 0x10a82178, 0x09224b82, 0x0a82986e, 0x8220b021, 0xce172619, 0xcff0ffff, 0x210e82e0, 0x04829aa9, 0x21059d4f, 0x5a44b89e, + 0xd7002707, 0xb9ffffa0, 0x53826776, 0xbd833b20, 0x15ee2222, 0x11250a82, 0x00ff70bd, 0x32fd8342, 0x1e650300, 0xc70c00ff, 0x0d00ffb0, 0x00ff3e2a, + 0x8250b807, 0xecd1260e, 0x87fcffff, 0x206982b0, 0x200a840c, 0x277e82a0, 0xff66a607, 0x50d8f2ff, 0x9c311982, 0xf3ffff28, 0xff08a430, 0xfa9efaff, + 0xb5ebffff, 0x225382c4, 0x820a1719, 0xd8a321de, 0x0f2c0a82, 0x00ffae47, 0xffeee708, 0x48a11300, 0xd8212482, 0x200e8212, 0x223e82e6, 0x8200c0f0, + 0xee0821bd, 0x0a82bd82, 0xda261982, 0xecffff5e, 0xc282f468, 0xff0ab726, 0x0c17f7ff, 0xe6225382, 0x0f823e0a, 0x8298d921, 0x54142248, 0x2124827a, + 0x0a82f57d, 0x5ccf0c22, 0x87217982, 0x20a282f0, 0x2209828f, 0x821acff2, 0x1e85210e, 0x2706f041, 0xe21afdff, 0x4ff5ffff, 0xf6271982, 0xffff144e, + 0x8252f8f8, 0x146e220e, 0x274f828b, 0x8b86ebfd, 0xe3fdffff, 0x00228482, 0x09830348, 0x2d445420, 0x36bd2c07, 0x1100ffcc, 0xff0527ef, 0x8266c4ff, + 0xb3dc229f, 0x276a8233, 0xffc2753c, 0x52b8dcff, 0x41220a82, 0x208232f3, 0x82b8de21, 0xe30c2c0a, 0x0300ffd8, 0x00fff668, 0x829a190d, 0x00802161, + 0x04820e82, 0x33f3ff23, 0x22d48234, 0x84167903, 0x2419828b, 0xffffec71, 0x22ae83f2, 0x822831f3, 0xae8721a4, 0xeb228482, 0xc98386ab, 0x4882f420, + 0x82f51921, 0xd9f0225e, 0x220a829a, 0x828e420f, 0x161924f5, 0x830500ff, 0x83ec2053, 0x83f72083, 0x7af02009, 0xc120056b, 0x00245f82, 0x15cdcccd, + 0xe6205082, 0xf0259f82, 0xffff6766, 0x272583ef, 0xffccccf3, 0xce4cecff, 0x7e836e82, 0x84eeff21, 0x32332493, 0x82ebffff, 0xfcff2233, 0x211982cc, + 0xbc82b3eb, 0x49820120, 0xf0ffff22, 0x00210f82, 0x25198302, 0xff9899f1, 0x2d830600, 0x34b3f327, 0x4c0900ff, 0x289d82cc, 0xff3eca18, 0xcecc18ff, + 0x21d78505, 0x2983f8ff, 0xebd1f525, 0x83fbffff, 0x63f52367, 0x25828bd7, 0xff290683, 0x7bd4f5ff, 0x330400ff, 0x262a8234, 0x00ff717d, 0x82008007, + 0x80f8221a, 0x820a8442, 0xfcc82630, 0x330a00ff, 0x05f37432, 0x2307fa74, 0x04370400, 0x25821684, 0x84be7f21, 0xff08252a, 0x3d4ae700, 0x33340482, + 0xffff0534, 0xff33b3f6, 0xcd4c0c00, 0xe6f9ffff, 0x0e00ff67, 0xfd20e883, 0x00238582, 0x8232330f, 0x33fe215f, 0x14201e82, 0x0021ee82, 0x21098403, + 0x43826666, 0xffcdcc26, 0x66e61200, 0x07204882, 0xc7210a84, 0x834282ae, 0xa8102c1e, 0x0f00fff6, 0x00ff9999, 0x820a170d, 0xe643211e, 0x43252e82, + 0x00ff32e8, 0x2c42835f, 0xffced70e, 0x9a993100, 0x5eceffff, 0x221e82b8, 0x82989931, 0x2c52820a, 0x9c19f1ff, 0xc0a0ffff, 0xbcffff00, 0x28138219, + 0x080100bc, 0x00ff2f0e, 0x3b2b82dd, 0xcc4c2b01, 0x0300ff15, 0xffff9919, 0xff6866f3, 0x9a190000, 0xccf2ffff, 0xfdffffcc, 0xf322b683, 0xa782cc4c, + 0x7e82fd20, 0x83f4ff21, 0x84fa2019, 0x34332614, 0xf5ffff83, 0x201a83cc, 0x52cd82f1, 0xed2005ce, 0xff218e82, 0x230e83f5, 0x869a19ea, 0x26243582, + 0x8b079a19, 0x82832782, 0x33b3fc22, 0xcc210982, 0x098941ce, 0xf8202082, 0x04842c83, 0xff204b82, 0x23059441, 0x8b0080f4, 0xf6221a82, 0x3a83cd4c, + 0x41ebd121, 0x70200894, 0x20099441, 0x240a8400, 0xe3faffff, 0x0b9441d7, 0xd900ff3b, 0xff0766e6, 0x29dcebff, 0x00ff788f, 0xff34330b, 0x0a57f2ff, + 0x801000ff, 0x20528200, 0x822d85f7, 0x56fa2287, 0x831e82c9, 0x39fd27ae, 0x0c00ffdb, 0x1e82cdcc, 0xcc240a86, 0x300000ff, 0x0d206082, 0x00233d82, + 0x826f2203, 0x34b32d1e, 0x1e00ff08, 0x00fffe34, 0x05985988, 0xd92a1f82, 0x0300ff9a, 0x00ff1eda, 0x29824002, 0xa8660322, 0x35210e82, 0x210e82c3, + 0x2982084c, 0x33330322, 0x4a200a83, 0xf3201482, 0x01220982, 0x09821c08, 0xff85eb26, 0x5691ffff, 0xee211e83, 0x210a8215, 0x14828892, 0xffd7a326, + 0x9020feff, 0x09832d82, 0x440bfd22, 0x02201e82, 0x862a0a85, 0x700100ff, 0xfcffffa4, 0x2d828a2c, 0x82e1fa21, 0x3e0a2b09, 0x0724fb08, 0x5e1100ff, + 0x058206b8, 0xff0b1726, 0x0a179400, 0x66218f83, 0x204c8266, 0x22048246, 0x827b9401, 0x96032109, 0x80205182, 0x02229982, 0x5183e02f, 0x82676621, + 0x9e2f210f, 0x99831982, 0x38350122, 0x66220e82, 0x1a828b67, 0x34330423, 0x2316858b, 0xc8cafeff, 0xff241684, 0x62d0fdff, 0x02201a82, 0x0a824082, + 0xee822020, 0x8233b321, 0x6afc217d, 0x4c219182, 0x210982cd, 0x1e829ab9, 0x9a191127, 0xe86bffff, 0x267e82f6, 0x069a9910, 0x830724f7, 0x14ee2148, + 0x4c214382, 0x215282cc, 0x2e8250cd, 0x8234b321, 0x76f3210e, 0x03202e82, 0xf3218e84, 0x21198274, 0x19829999, 0x7e5ae421, 0x00230556, 0x83ae7800, + 0x82e6201e, 0x6d0022bc, 0x831482c6, 0xf4fe2757, 0x0400ff6e, 0x8b829919, 0x41d8ae21, 0xff230651, 0x82daaefd, 0x3433214d, 0x93208182, 0x00204782, + 0xff233282, 0x828420fc, 0x191e211e, 0x77228b82, 0x8b8298d9, 0x6666e228, 0xb3bcfeff, 0x77421534, 0x05e84307, 0x201a7742, 0x067742ce, 0x6666f526, + 0xffff088b, 0x05820683, 0x0c443082, 0x44b88306, 0x7742070c, 0x44548307, 0xf72d0a0c, 0xffff070c, 0x063433ef, 0x99f7ffff, 0x22798298, 0x829a99f7, + 0x21fd82e3, 0xaf82f8ff, 0x33030029, 0xffff0832, 0x82cc4cf8, 0x824c20de, 0x82f8206f, 0x040025ba, 0x918532b3, 0xfa231682, 0x82919a19, 0x21178282, + 0xc7830700, 0x1c83fb20, 0xcccc0722, 0xfd251a82, 0x00ff32b3, 0x268a8207, 0x6866feff, 0x820800ff, 0x820584a1, 0x83ff201a, 0xcc712225, 0x20f282ce, + 0x200a8300, 0x20048324, 0x213f820b, 0x04832400, 0x39831420, 0x1e851e26, 0x1400ff08, 0x00268682, 0xffec911e, 0x80831d00, 0xf6a81725, 0x832200ff, + 0xb60d246d, 0x828f0804, 0x20f021a6, 0x2d053845, 0xa0b80000, 0x330500ff, 0xffffff32, 0x3982d270, 0xbb820520, 0xe0290a82, 0xfeffff90, 0x00ff9e2d, + 0x233f8204, 0xf212fdff, 0x04201a82, 0x0a834082, 0x9929d082, 0xfcffff98, 0x00ffde0f, 0x23a38202, 0x4861fbff, 0x02221e82, 0xd2820080, 0xffd6632b, + 0x66660000, 0xdcfaffff, 0x8209822a, 0xfaff36a1, 0xfc08aec7, 0xf80e074c, 0x1554f774, 0x84ffff8b, 0xffff9a99, 0x842d839b, 0x200e8204, 0x22dc828b, + 0x82f628cf, 0xabd12c1b, 0x0f00ff85, 0xffff7a94, 0x8252f8d8, 0xb04721bd, 0xf12c1a82, 0x00ff47e1, 0xff0a970a, 0x6626fdff, 0x1120dc82, 0x0a21d782, + 0x221e8298, 0x8266260e, 0x23198378, 0xb81e0e00, 0x07211982, 0x209282ae, 0x271e82d1, 0xffa4300e, 0x5c6ff5ff, 0x1b211e82, 0x2a3882d7, 0xff0a17eb, + 0xf6282100, 0x83f4ffff, 0xe1222257, 0x23738247, 0xc2155800, 0xfe20f782, 0x472e3982, 0x00ff34b3, 0x8b32b347, 0x195800ff, 0x0685089a, 0xb8ffff24, + 0x16845c4f, 0xa7ffff24, 0x3182d8e3, 0x8adaff23, 0x35a5823e, 0xffb85edc, 0x9082f2ff, 0xcae3ffff, 0xe8ffff3d, 0xff089ad9, 0x81822d00, 0xdcd2ff3d, + 0x00ff052a, 0xff8f0211, 0xe0faeeff, 0xf1f3ffff, 0xe2ffffec, 0xffff86eb, 0x83ebf1e7, 0x406e2340, 0x99820600, 0x89826820, 0x2083ff20, 0x826bf721, + 0x990822f0, 0x0662469a, 0x9100ff25, 0x820728dc, 0x0a18220c, 0x83fe823e, 0x0a0c23e9, 0x4d829c3e, 0x8270fd21, 0x992f2763, 0xd0ffff9a, 0x6382b85e, + 0xe13a282a, 0xe32200ff, 0x3300ffd8, 0x2305a979, 0x3600ff9a, 0x25824782, 0x66667b22, 0x64214182, 0x632f1a80, 0xff2f210d, 0xbf85fe18, 0xe697ff2f, + 0x91ffff66, 0xff15a4b0, 0x66e68001, 0x19c75606, 0xfffeff30, 0xff069a19, 0xcd8cddff, 0xe2ffff8b, 0xca563373, 0x3bdb240e, 0x5174fb15, 0x08280808, + 0xffff9a19, 0xffccccf8, 0x095a6418, 0xff8b3426, 0xcd4c0600, 0x4f0bea70, 0xcd2407e6, 0xb3f9ffff, 0x07295082, 0xffff3333, 0x8bcc4cf6, 0x7e3c8208, + 0x9e830515, 0x51ccf821, 0xff2507d1, 0x01006000, 0x20688d8b, 0x20688f99, 0x83688233, 0x124f5049, 0x4c826882, 0x82055450, 0x8bcd2068, 0x18672068, + 0x820bd152, 0x66e62168, 0x0720688c, 0x24293c19, 0xfd85d18a, 0x5318d183, 0x0e231b3a, 0x82c101ff, 0x980129e3, 0xff153e0a, 0x0080cfff, 0x782f0482, + 0xffff0552, 0xff9a19d9, 0xcc4c2300, 0x82ccffff, 0x1500281f, 0xffffa430, 0x839a99c8, 0xa12308b1, 0xff8b0080, 0x0a17adff, 0xa8c3ffff, 0xe2fffff6, + 0xffff71fd, 0x08d623a6, 0x8ffaffff, 0xefffffdf, 0x1bffa530, 0x21168722, 0x238252f8, 0x00236482, 0x82d7e311, 0xdf4f3523, 0x700500ff, 0x1000ffa4, + 0xff082bc7, 0xf5681400, 0x633f00ff, 0x3a201982, 0x2a202383, 0x42200483, 0x00247384, 0x8bc2f525, 0x0a308f82, 0xf1ffff3e, 0x00ffecd1, 0xff34331b, + 0x4861e8ff, 0xd2207382, 0xff259f82, 0x05ccccd3, 0x827a827b, 0x0b0032ef, 0xffff32b3, 0xff6766e3, 0x9a991700, 0x66ffffff, 0x305b8266, 0x0666e692, + 0x660a00ff, 0x0000ff68, 0x00ffcd4c, 0x45da8208, 0x0a22068a, 0x20826766, 0x2107a543, 0xd182ce0c, 0x00295282, 0x7a3c0a0c, 0xfdeeffff, 0x20638272, + 0x241082f7, 0x285c06ff, 0x21628215, 0xb4835c0f, 0x1a822020, 0xff230982, 0x8200c0f6, 0x7c9421d2, 0x38211882, 0x202982d6, 0x257283eb, 0xffa4b0c0, + 0xbe82c5ff, 0x83d5ff21, 0x46bd2004, 0xda310593, 0xff8b3e0a, 0xc2f5dcff, 0x2e0e00ff, 0xe4ffff14, 0x228782cc, 0x82b89e17, 0x832c207c, 0x332c26b7, + 0x00ff0534, 0x266a8210, 0xcccc1000, 0x83f4ffff, 0x831c20a7, 0x83e8204f, 0x990022cc, 0x285f829a, 0x065c0f6d, 0xa8f5ffff, 0x25d882f6, 0xffff34b3, + 0x4982aef7, 0x2005ae46, 0x202084f5, 0x05ad496e, 0x6683e720, 0xec111d2d, 0xf5f3ffff, 0x00ff9cc2, 0x82900211, 0x82302067, 0x3000238e, 0x6782ae87, + 0x82ee2621, 0xbddc2acc, 0x3300ff72, 0xffff9a19, 0x247182ea, 0x00803600, 0x3325828b, 0x8b32735e, 0xf35200ff, 0x3c00ff34, 0xffa80a57, 0x2adc5900, + 0x06221682, 0x9e826666, 0xff212782, 0x217982f6, 0xa8821200, 0x33efff30, 0x0400ff32, 0x0e080080, 0xf8a4f72f, 0x68821554, 0x2419b320, 0x8f18092e, + 0x7b201fb6, 0xdd26ca82, 0xff07cc8c, 0x98822500, 0x40faff27, 0x2200ff00, 0x24d58233, 0xa73433f0, 0x21728274, 0x5e82b315, 0x9a991522, 0x0c20af82, + 0x00202182, 0x14210484, 0x83618333, 0xf3ff210a, 0xff207982, 0x0a831584, 0xffff8b23, 0x829e83eb, 0x83f68215, 0xe7ff211a, 0xe722a483, 0x4082cecc, + 0x58831520, 0xff7fdf22, 0x4c262f82, 0xd9ffffcc, 0x2f829919, 0x3433d623, 0x24068208, 0xff9a198d, 0x351b19ff, 0x83228411, 0x5d003416, 0xff8b9a19, + 0x66e67200, 0xfff38b08, 0xec514c00, 0x825600ff, 0x6300224f, 0x22f282ae, 0x8298590f, 0x732223ab, 0xd0830734, 0x09c59618, 0x540e0023, 0x2235827c, + 0x8284ab11, 0x11002863, 0x00ff86ab, 0x63cd4c0e, 0x112b06c1, 0x088b33b3, 0x73058beb, 0x821554fb, 0x830d2024, 0x83f52093, 0xb30a211d, 0x1e997818, + 0x1814fb21, 0x2a2e2e79, 0x0e0714f7, 0xcb156beb, 0x8300ff06, 0x5b858775, 0x332012a0, 0xcc221b83, 0xc383ffff, 0x184b0821, 0x820cd57d, 0x847a20cc, + 0x088623cc, 0x808294f7, 0x8420cf82, 0x10dbf918, 0xff8d628f, 0xffff8424, 0x6283b3f1, 0x8a7c5421, 0x19ca2062, 0x1807ce20, 0x200b3273, 0x266282fb, + 0x2a00ff56, 0x5d60e1fa, 0x013f078a, 0xffcccc98, 0x0080f100, 0x6fffff15, 0x1cf766e6, 0xf9ffff05, 0x00ff6606, 0xfff89306, 0x82c6f5ff, 0xcc012c09, + 0xf7ffff08, 0xffff3433, 0x831038fc, 0x6e32210a, 0x33200a82, 0xfa221e82, 0x1982024b, 0x8bb65327, 0x6bf6ffff, 0x2b1a8286, 0x4380e8ff, 0xff14fb05, + 0x42000000, 0xee224882, 0x1a825c4f, 0x85abf122, 0xab20a282, 0x129c8218, 0x650a5721, 0x11270661, 0x088b15ae, 0x82ff14f7, 0x05be2100, 0x17273d82, + 0xb8ffff80, 0x820566e6, 0x6cf6273d, 0x0500ff08, 0x6883feb4, 0x00fff825, 0x8392cd08, 0x8234207c, 0x280a8514, 0x00ff1038, 0xff1c3a0a, 0x23a68300, + 0x52f80600, 0x1e82ba84, 0x9a199022, 0x0023cd83, 0x829c9909, 0xac1c2236, 0x0766438b, 0xff646630, 0x9a190900, 0x01ff0e08, 0xff34b358, 0xfc8dd100, + 0x82991921, 0xae872141, 0xb321fc82, 0x20558333, 0x20fc88ce, 0x22e18250, 0x823333f7, 0x6826267f, 0x4cfaffff, 0x211982cd, 0xa3836666, 0x0866662b, + 0xffff0743, 0x0685eb7f, 0x928318ff, 0x5bf58407, 0x4b2108cb, 0x22278207, 0x41ec51ee, 0xff2305dc, 0x1814aef1, 0x24089283, 0x069a1980, 0x901e8343, + 0x899120ea, 0x850a83ea, 0x9a1d20ea, 0xea9121ea, 0x0e21da82, 0x20ea8956, 0x27ea8568, 0x4c4700ff, 0xce00ffcc, 0x7f42e982, 0x0ad16805, 0x210bc466, + 0x51677c54, 0x82842008, 0x86ab219f, 0x6805af76, 0xff210913, 0x2a9018f1, 0x05225d08, 0x3f68ee20, 0x06ff6705, 0x0e82ff20, 0xe2428b20, 0x66628a06, + 0xcb261ef6, 0x3500ff06, 0xb5821e05, 0xe2fa2a24, 0x048200ff, 0x10820a82, 0x82061243, 0x84602009, 0x8b563315, 0x01ff0e08, 0xff66e6d4, 0xd8e39f01, + 0x0d00ff15, 0x2982b8de, 0x5c4f0d30, 0x3af5ffff, 0xffff8be0, 0x08e2baef, 0xac45ffff, 0x68f52706, 0xf7fffff6, 0x04827e6a, 0x82856b21, 0xfc692221, + 0x221c838b, 0x8206cc4c, 0x52b82128, 0xf5222e82, 0x44825238, 0x83eb5121, 0x48e12244, 0x31068208, 0xff4ea206, 0x04760200, 0xc40600ff, 0x0500ff18, + 0x0482be7f, 0x4a008021, 0x003306b6, 0x05d8232d, 0xc7e3ffff, 0x1700ffae, 0xffffd623, 0x82b85edc, 0x00802640, 0x8cdaffff, 0x285d83cd, 0x8bf6e8a7, + 0x4ab8ffff, 0x2104823d, 0x0a825c4f, 0xd6e3a722, 0xff205782, 0xff240682, 0x89ab4700, 0x59261682, 0x5800ff9c, 0x2d829919, 0x23490023, 0x257382d6, + 0xffce4c10, 0xc4822600, 0xa8190023, 0x221683f6, 0x82e27a12, 0x7d0d2716, 0xf0ffff70, 0x4482c2f5, 0x7c14ef22, 0xdc254483, 0xffffc2f5, 0x27d583ae, + 0xff48a1dc, 0x0a97beff, 0xff232d82, 0x829a9984, 0x829b2022, 0x64002384, 0x38820080, 0x66667b22, 0x00202d82, 0xff230682, 0x82876400, 0x836420aa, + 0x820e82e6, 0x3600212d, 0x00322d83, 0xff9a9933, 0x2a9cebff, 0x332800ff, 0xddffff32, 0x344b4621, 0x2f002406, 0x840548a1, 0x2a0486f2, 0xffcccc06, + 0xc4750200, 0x820600ff, 0x0e082f39, 0x66c301ff, 0x4e00ff66, 0xff1566e6, 0x0a831100, 0x9a190d22, 0x21054e50, 0x5b841400, 0x7e851720, 0x00c02725, + 0x82dfffff, 0x20002204, 0x22098240, 0x820040d8, 0xf1ff297e, 0xff0648e1, 0x846b0d00, 0xcc273282, 0x0800ffcd, 0x829c34b3, 0x191422b2, 0x20b28399, + 0x20298323, 0x220482e3, 0x82d91b00, 0xc0dc21a0, 0xfa223384, 0x33820020, 0x82ac0321, 0x830a2088, 0x3302276b, 0x0a00ff34, 0x378232b3, 0x9a190c28, + 0x60c08b08, 0x5b8356b6, 0x2e82fa20, 0xffff8623, 0x233f82ff, 0x4821fbff, 0xd6820984, 0x856b0927, 0xfaf1ffff, 0x28d082e2, 0x8b7b33b3, 0x85efffff, + 0x216c821e, 0x9b82d3ff, 0x83dcff21, 0x8204842c, 0x088b220e, 0xab74187b, 0x18ff200c, 0x82097474, 0xc0ec2236, 0x22af8201, 0x827a00c0, 0xb95e27bf, + 0x40f4ffff, 0x58820800, 0x0647e124, 0xdd82ffff, 0x19216e82, 0x23f18599, 0xceccdeff, 0xd8223082, 0x6783cc4c, 0xb89ee822, 0x6783ec82, 0x4861eb25, + 0x831100ff, 0xdef2303b, 0xffff08b8, 0xff47a1dd, 0xae87faff, 0x83e5ffff, 0x80e2228b, 0x20358200, 0x82d283dc, 0x20e48351, 0x21358320, 0xf882ccdf, + 0xdb822720, 0x04f80825, 0x8300ff06, 0x00ff2109, 0x04831983, 0x10848b20, 0x00236682, 0x8266e623, 0x222b8347, 0x8200801d, 0x9a99215b, 0x8020f082, + 0xfe21a282, 0x230a83fc, 0x159a1971, 0x0b674518, 0x82f1ff21, 0xffff2251, 0x82c482ee, 0x82068274, 0x828483ca, 0x20158416, 0x829f828b, 0x831b8215, + 0x0e002311, 0x6a823433, 0xec651120, 0x20068205, 0x067347ff, 0x1122a583, 0x2d8233b3, 0x809f0029, 0x151ffb00, 0x82f4ffff, 0xe4ff276e, 0xff5b9a19, + 0x9383e6ff, 0x66e6db22, 0xff231e82, 0x828f02db, 0x02d02a4c, 0x1900ff8f, 0xffffb81e, 0x23a582f5, 0x48e11b00, 0xfd226782, 0xab82e2fa, 0x82343321, + 0x8305201a, 0xcc0522c0, 0x233182cd, 0xff7faf00, 0x052aef82, 0x8f8b34b3, 0x33faffff, 0x05828934, 0xff258082, 0x0080e0ff, 0x8b6882d6, 0x0040219e, + 0xc0229e83, 0x06850800, 0x40219e82, 0x20048600, 0x20e88211, 0x82fa9f08, 0x85ff2076, 0x79e882fa, 0x142608d9, 0xe5ffff06, 0xa218707d, 0x942112d7, + 0x13616e07, 0x088b9023, 0x793382f8, 0x338316b9, 0x676e1a83, 0xfeff2610, 0x4b9a19cf, 0x21a38215, 0xbf8214ae, 0xec510e23, 0x0a6745ff, 0xee276882, + 0xffff7c54, 0x849999f2, 0xffff2416, 0x186766ed, 0x480f92aa, 0x00220f12, 0x1248330f, 0x10003706, 0x088bcdcc, 0xffffa3f7, 0x15666628, 0x33fdffff, + 0xfaffff32, 0x4219cecc, 0xb420114e, 0xf922ed82, 0x6f821dfa, 0x357efa26, 0x610300ff, 0xfd280f82, 0x00ff1f45, 0x08fa5e05, 0x0a843882, 0xfff45d2b, + 0xd7830000, 0x710600ff, 0x2a238268, 0x00ff088c, 0x08b8de04, 0x8205ebd1, 0x2b07210d, 0x2b210d82, 0x26048286, 0x00ffcccc, 0x82666602, 0x9a19213b, + 0x0023ab82, 0x826a1c05, 0xce0422d9, 0x21478216, 0x2a821b8f, 0xff940326, 0xf3ddfbff, 0x16273e82, 0xffff9a59, 0x820a57e1, 0xbd3e2740, 0x5e00ff70, + 0x0a82281c, 0x7c140222, 0x6c224682, 0x4782908c, 0x2005156a, 0x21478432, 0x47831659, 0x82f4fd21, 0xf8532147, 0xf8211b82, 0x21478252, 0x4782088c, + 0x34b36a24, 0x398234fb, 0x3e4a0322, 0x20211282, 0x24a78200, 0xffffcc4c, 0x823d82f9, 0x823420f4, 0x32b321ef, 0xd930c682, 0xffff66e6, 0x159a9987, + 0xff06e4fb, 0xcd4cd8ff, 0xdf27ef82, 0x00ff33b3, 0x82cc4c20, 0xb327265a, 0x84f70834, 0x21098207, 0x3382330d, 0x8240f521, 0x820a2047, 0x18ff20cd, + 0x23100e86, 0x3433f5ff, 0xf2243b82, 0xfb08cccc, 0xff213083, 0x262682bd, 0x7bd43500, 0x82caffff, 0x4200263a, 0x088b852b, 0x186482f7, 0x2018ec5b, + 0x215c820d, 0xa482f5ff, 0xc00a002e, 0xf2ffff00, 0x088b34b3, 0xa501ff0e, 0x0027b182, 0x1533b3e3, 0x8216ffff, 0x16ff2e52, 0xff0567e6, 0x9a19deff, + 0xe62100ff, 0x20e18366, 0x22948280, 0x82008003, 0xe6d12215, 0x0c806566, 0x280c1f6c, 0x079a192e, 0x82fcffff, 0x8404828f, 0x45fb272d, 0xfbffff1e, + 0x0f823233, 0xffae8724, 0xa682faff, 0x1cfeff33, 0xf9ffff29, 0xff089a99, 0x1f05e9ff, 0xccb1ffff, 0x236282cc, 0xa2f6284e, 0x29070746, 0xff66e601, + 0x33b30600, 0x738200ff, 0x0400ff24, 0x0482cdcc, 0x0834b322, 0x98848e84, 0xf5248882, 0xffff9a99, 0xf3250484, 0xffff9919, 0x23d582f8, 0x67e6f1ff, + 0xe6216e82, 0x275a8266, 0xff85ab87, 0x9a99dcff, 0xf7252982, 0xffff7b94, 0x26c282fd, 0xd7e3f6ff, 0x830200ff, 0xcaf92629, 0x0700ff3d, 0x27848319, + 0xff30caf9, 0xce4c0500, 0xad262382, 0x0900ff9f, 0x23829819, 0xff5e7a26, 0x00800800, 0x23277282, 0x00ffdd64, 0x82ce4c78, 0x2804279c, 0x0e00fff6, + 0x39829a19, 0xff48a124, 0xa6830c00, 0x82680a21, 0x660a2113, 0x00227282, 0x148221e9, 0x28e92008, 0x16f705f6, 0x0a7effff, 0xffd2053d, 0xcd8ca100, + 0xffffa415, 0x8b9002e7, 0x70d7ffff, 0x827272a4, 0x99cf2f9b, 0xcfffff98, 0xfb059999, 0x8100ff16, 0x5a82e1fa, 0x68663034, 0x663000ff, 0xffa40566, + 0x7eff1800, 0x992800ff, 0x38838b98, 0x82820021, 0x82272083, 0xd8ff2f1d, 0x0e05ec91, 0xb36a01ff, 0xac01ff34, 0x568214ae, 0x74ac299b, 0xffffc625, + 0x411f0537, 0x5f410dfe, 0xff0e2aa2, 0x34b3ec01, 0x408501ff, 0x11644100, 0x66e6cb24, 0x0482ffff, 0x27056441, 0xff0552f8, 0x9a193400, 0x1c210482, + 0x1e644128, 0x03ffff23, 0x2b3b8266, 0x159ad9c7, 0x80f7ffff, 0x0900ff00, 0xf0280f83, 0xff8bcccc, 0x9a99f6ff, 0x082b0484, 0x1999ffff, 0x9affff99, + 0x8505cccc, 0xf5ff2825, 0xffffcdcc, 0x83cdccf0, 0x47a12625, 0x330a00ff, 0x2d258233, 0xff48a1f6, 0x00800800, 0x0f00ff8b, 0x4b823433, 0x84b85e21, + 0xff082550, 0xec116600, 0x07210482, 0x209a82ae, 0x224b821c, 0x821e1c00, 0x992d221a, 0x832a829a, 0xe3ff290f, 0xf70848e1, 0x70ffff23, 0xff21bd83, + 0x28798343, 0x05008043, 0xffff5b5b, 0x256b83c2, 0xffcc4cdf, 0x9b83bdff, 0x34b3f222, 0xe7236a82, 0x82868f02, 0x21f8278c, 0xfeffff48, 0x96826866, + 0xff29dc30, 0xfe7f0200, 0x54faffff, 0x0600ff7b, 0x25820080, 0x7553fa2c, 0xcc0400ff, 0xfdffffce, 0x9a827989, 0xff98192b, 0xbd920100, 0xe60700ff, + 0x23948268, 0xa4b1ff04, 0x0d269082, 0x00ffa450, 0x1b829942, 0x71bd2025, 0x833d00ff, 0x053023ba, 0x2182bb1f, 0x5c8f9a25, 0x829a00ff, 0xff7d2c88, + 0x9a190d00, 0x70fb0e05, 0x821901ff, 0x3700249d, 0x821534b3, 0xe68f22af, 0x3c868266, 0xff8380f6, 0x8ec2f5ff, 0xceefffff, 0xffff8bd9, 0xff0080f6, + 0x723d0a00, 0x00ff2308, 0x24368270, 0x84f9ffff, 0x21948218, 0xad82f4fd, 0x82d74321, 0x2030251b, 0xd00300ff, 0x08227782, 0x678290c2, 0x9ecf0322, + 0xc2219e82, 0x2604820c, 0x00ff96a3, 0x827aa905, 0x66a62209, 0x281a828b, 0x06dde448, 0xf03f01ff, 0x03451aa2, 0xc0fe2c2f, 0xd3079a19, 0x0900ff06, + 0x828b088c, 0x9ca4264e, 0x57faffff, 0x2777820a, 0xffff5ccf, 0x08703df7, 0xcc210a82, 0x210a82cc, 0x96825238, 0x82ce4c21, 0x82cc20c2, 0x80f92704, + 0x0e088400, 0x285794f8, 0x4cee2105, 0xf1202182, 0x20075f75, 0x820e82ff, 0x235a8394, 0x05438b06, 0x7321ea83, 0x235685f8, 0x645bf7ff, 0x3d274b82, + 0xfcffff71, 0x8208a430, 0xfa3e210a, 0x20200a83, 0xcd305682, 0x0100ffd3, 0xffff2abc, 0xff8f02f9, 0xe87b0600, 0x8f241e82, 0x05f366e6, 0xc2201b82, + 0x09221182, 0xa1820080, 0xa4301025, 0x820a00ff, 0x82002040, 0x229c820f, 0x829a1970, 0x06002321, 0x3384f4fd, 0x30211b82, 0x21478222, 0xcc82e6bb, + 0x66823582, 0x25822220, 0x51b80822, 0x32246682, 0x0500ff6e, 0xf722a583, 0x9582cc4c, 0x6666f722, 0xff29f382, 0x059a19b7, 0xe63f01ff, 0x0f996b66, + 0x23823320, 0xcd4cee27, 0x01ff0e08, 0x26e082f8, 0x6666ae00, 0x82ffff15, 0x82232092, 0x02f92292, 0x05b0410c, 0xcff5ff28, 0xfeffffe0, 0xcc821a44, + 0xff703d26, 0xdecf0300, 0xf721b882, 0x208f823d, 0x22198303, 0x828656fa, 0x54a3218a, 0x0822bb82, 0x8b8266a6, 0x5e0f002d, 0xe74800ff, 0xfeff05f0, + 0x509a19c0, 0x92210a8c, 0x06dd6bff, 0x9a991222, 0x00209882, 0x11820682, 0xb4825420, 0x00800c29, 0xab1100ff, 0x85088b85, 0xd38b22a8, 0x214e8205, + 0x4d828c09, 0xf6a80522, 0x2305b641, 0x90c20800, 0x5c207d83, 0x08211482, 0x27cb82c1, 0xff1acf03, 0x2e320a00, 0x00239c85, 0x8270fd06, 0xd68321b0, + 0x82053341, 0x0a0028c2, 0xffff6e3d, 0x829082f6, 0xccef27e6, 0xf5ffffcc, 0x0f8234b3, 0x0800802f, 0xff70fb0e, 0x9a191d01, 0x4c2e01ff, 0x22f282cc, + 0x83a430fc, 0x82f420dc, 0x285c2604, 0x56faffff, 0x29098288, 0x088b9a59, 0x0000ff43, 0xc8851e05, 0x46820720, 0x5c4fee24, 0x6d50ffff, 0x82b02005, + 0x1ca61932, 0x0bea6410, 0xe63f012b, 0xffff0766, 0x8b9919b7, 0x21768205, 0x3f82f873, 0x645bf729, 0xa80500ff, 0x83ffff72, 0x08002472, 0x830814c3, + 0x4262200a, 0x012206f6, 0xd18229bc, 0x41263121, 0x062f06e9, 0xf30872fd, 0x197000ff, 0x00ff0598, 0x827d7f09, 0x723d271b, 0x311000ff, 0x0f828b27, + 0x82008021, 0x8ec221d1, 0xff232182, 0x8268e68f, 0x66072c21, 0xf9ffffea, 0x00ff3c0a, 0x4232b301, 0xfb2206c6, 0xca82ce4c, 0x08323328, 0xf88baf0e, + 0x37821514, 0x135eb218, 0x0634f722, 0x22059c52, 0x4bcc4cee, 0xff230577, 0x5234b3f1, 0x08270575, 0xff0614f7, 0x836674ff, 0x82a120cb, 0xa1ff231e, + 0xcf82ce4c, 0x83ccf721, 0xcccc2558, 0x33faffff, 0x03496c83, 0xb3f42d08, 0xffff0832, 0xff66e6f0, 0x66e6c3ff, 0xfd202982, 0xf62d1a83, 0x00ff9a99, + 0xff999900, 0x6666f6ff, 0x05ef5eff, 0x3433f722, 0x3d232982, 0x18063433, 0x2716c7ac, 0xf70714f8, 0xf7154b94, 0x14240682, 0xfb0514fb, 0x012c8882, + 0xff981934, 0x66e685ff, 0x0f00ff15, 0xf0265883, 0xff8b6666, 0x0a84e6ff, 0xf0289d83, 0xff08cc4c, 0x9c99e2ff, 0x9a200483, 0xb9297e82, 0x05d29819, + 0x661d00ff, 0x20048368, 0x220a8267, 0x8298990f, 0x248b823c, 0xcc4c1900, 0x2147888b, 0xfa830867, 0xf122d082, 0x37829999, 0xcecc0324, 0x65823afb, + 0x34338125, 0x838000ff, 0x460025f3, 0xfffffeff, 0x1d824f82, 0xfe837e20, 0x0a820482, 0xea83fb20, 0xfa200484, 0xfd251483, 0xffff9a19, 0x23e482fa, + 0x9a99feff, 0xc3208a82, 0xf0221e83, 0x298266e6, 0x0080fa27, 0xb3feffff, 0x2f1f8232, 0x00ffce4c, 0x879a9901, 0xe60300ff, 0x8f870866, 0x32821782, + 0x82050021, 0x01002141, 0x06200983, 0x9a23c782, 0x843b00ff, 0x20118478, 0x21b68305, 0xf14ae602, 0x00ff2d05, 0x909a1904, 0x0e078b08, 0xbf01ff2f, + 0x00307282, 0x1566e680, 0xe678ffff, 0xff8b0766, 0x70bdf2ff, 0x2707e566, 0xfffff628, 0x8b66a6f3, 0x1c828a82, 0xffff0625, 0x825c0ff3, 0x54f42b21, + 0x0700ff7a, 0xfffff0c7, 0x8b820cfb, 0x10f80b23, 0x240a8208, 0x00ff1018, 0x2c4d830b, 0xfff8b302, 0xb89e0e00, 0x230900ff, 0x270482d8, 0xff086626, + 0x5c0f1e00, 0xca820484, 0xbaa9b727, 0xb84400ff, 0x280a8254, 0xffec91b8, 0x5c8fb8ff, 0x241b8405, 0xf0e1ffff, 0x210a82a4, 0x5a822709, 0x82d8f621, + 0xc102224f, 0x21908206, 0x5e82fa3e, 0xffe90627, 0x3e0af4ff, 0x210a8208, 0x0a827308, 0x82ea1121, 0xcc4c2404, 0x82f9ffff, 0xf3ff2773, 0x088b9a19, + 0x76181cfb, 0xf6210810, 0x28eb8226, 0x8b70bd0a, 0x5c0c00ff, 0x227f822a, 0x829a1987, 0x0c0023dc, 0xba85a4f0, 0xab0b0023, 0x20af8286, 0x226482f8, + 0x8232f304, 0x11032a20, 0x0200ffec, 0x00ff3e8a, 0x23f68204, 0xcccc0000, 0x1e210982, 0x23fb82b8, 0xdf4f0800, 0x082c4782, 0xffff2130, 0xff0cc2fc, + 0x48210600, 0xe0217682, 0x86d68600, 0x704726b5, 0x4700ffa5, 0x83c08270, 0x210a82d1, 0xe1821263, 0x6d20d182, 0xcd830682, 0x0484ff20, 0xcd83f220, + 0x0483fd20, 0x3d0af422, 0xf9226282, 0xc8820817, 0x82ba0921, 0xdfef260a, 0x34f8ffff, 0x2196820b, 0x708234b3, 0xcccc0d22, 0x0d2cb889, 0x00ff9042, + 0xff00c00a, 0x0ad70900, 0x5920d482, 0xff21ef82, 0x20d58200, 0x210c8206, 0x2e82a4f0, 0x85ab0b22, 0x38203e82, 0x3320d084, 0x07275282, 0x00ff08f0, + 0x824e7003, 0x14ee2cb4, 0xe6ffffff, 0xfbffff67, 0x828b9ad9, 0x1ec5220f, 0x22068208, 0x8222b0f7, 0x54c3260b, 0xcff7ffff, 0x82d084de, 0xbade2104, + 0xe2288e82, 0xffffacdc, 0x05ac07e1, 0xa141d084, 0x6e472207, 0x850f8414, 0x00ff24d5, 0x865c0f1e, 0x090025d9, 0xfffff027, 0x0022d483, 0x9082c10d, + 0x16f90422, 0xf521c482, 0x228082c4, 0x82e0ef04, 0x32f3210a, 0xae260482, 0x0700ffd8, 0xaf85cecc, 0x2b82d985, 0xbc82d882, 0xff23d483, 0x820040f5, + 0xa6f32296, 0x056f4266, 0x0c830720, 0x855c0f21, 0xf4ff23d4, 0xd4847b54, 0x0c21c482, 0x222082cd, 0x4266e6f4, 0xff320574, 0xff4861f1, 0xf8b30200, + 0xd9f6ffff, 0x0900ff9a, 0x1e82d723, 0xa4f0e122, 0x5b20a183, 0x21086442, 0xcd8dec91, 0x84099042, 0x840485bd, 0x830220bd, 0xf50b22c2, 0x215e82c2, + 0xa782ea06, 0xfeb40d2a, 0x41f9ffff, 0x0600ff8a, 0xf4347383, 0x7f8bcc4c, 0x30fb0e08, 0x14f8e4f7, 0xcaffff15, 0xff06b81e, 0x3305d373, 0xff343325, + 0xcdccdcff, 0xcc1a00ff, 0xd6ffffcc, 0x088bcd4c, 0x16830685, 0xe5201182, 0xf2202083, 0xff232082, 0x82ccccda, 0x19ca221a, 0x9b921899, 0x1e85210e, + 0xe524f582, 0xfb08e27a, 0x0a9cb218, 0x71198020, 0x1a25073e, 0x088b0080, 0x9b9218f7, 0xe27a220f, 0x2371828b, 0xf7081e85, 0x00233383, 0x4f1e851a, + 0x7a2407c4, 0xe5ffffe2, 0xfb223383, 0xc6188b24, 0xc14f17fa, 0x059a4607, 0xff84ab23, 0x129a46ff, 0x820c3758, 0x06605123, 0x457c5421, 0xdb2506e8, + 0xfb1534fb, 0x0fec4d34, 0x11bd4918, 0x2006715d, 0x71061900, 0x5dff2013, 0x93820974, 0xd76ef720, 0x20168307, 0xd75318ff, 0x19f73108, 0xae00ff9a, + 0xfb156666, 0xff052304, 0x1804f9ff, 0x26076948, 0xffff62d0, 0x82d843fe, 0x0040272a, 0xd00300ff, 0x0a890820, 0x2e056049, 0x14a30800, 0x0900ff8b, + 0xc308cc8c, 0x5754fb07, 0xff2406cf, 0x07cc01c8, 0x21088749, 0x35821058, 0x49645b21, 0xa420087c, 0xff2d4586, 0xff2030fc, 0x5ccff5ff, 0xbb0100ff, + 0x2a7382e8, 0x00ff1f05, 0x08e87b06, 0x82f304fb, 0x38f62287, 0x21588210, 0x5e821018, 0xfafe1022, 0xc7210a82, 0x230482f0, 0xf7089a19, 0x00231e83, + 0x84e8fb06, 0x00ff242d, 0x829e2f0a, 0x28bc2c41, 0xc00800ff, 0xfcffff00, 0x8208e02f, 0x82a32028, 0x32fc27b6, 0x0500ffb0, 0x7a8233b3, 0x4bcc4c21, + 0x7b820502, 0x66e6c828, 0xc000ff07, 0xb5580100, 0x82c32005, 0x82c082a9, 0xa7052133, 0x08226182, 0x48829ca4, 0x4806c121, 0xa4820edb, 0xff226783, + 0x1e8244fe, 0xe2fa0622, 0x8421ae82, 0x218a8218, 0x6b820523, 0xff1cc528, 0x4801f6ff, 0xce827a8b, 0x82ce4c21, 0x66e6240b, 0x82fb0e08, 0x4bf9207b, + 0xfb210895, 0x21d28304, 0x1c82f0e7, 0xff23d782, 0x830601ef, 0x66e6218f, 0x9482d784, 0x66e69823, 0x222283f7, 0x821984f9, 0x23db82d6, 0xd743feff, + 0x0322db86, 0xdb8421d0, 0x0a87a282, 0x0700ff24, 0xdb82a6bb, 0x8246a121, 0xcd8c2a40, 0x06c3088b, 0x530754f7, 0x215e8206, 0x59823373, 0xac5cf722, + 0x22067b4a, 0x82df2ffc, 0x32b3263c, 0xfcffff08, 0x26478330, 0x00ffcecc, 0x8222bc01, 0x9819215b, 0x7b246a82, 0xf30892ee, 0x00237a83, 0x84111809, + 0x00ff258d, 0x8bfafe10, 0x19210a82, 0x21ad8499, 0xbc83f308, 0x7b060028, 0xf9ffffe7, 0x354b1a04, 0xd0f52206, 0x82518262, 0xf7ff235c, 0x5c830040, + 0xffb03226, 0xec51f7ff, 0x4c260482, 0xfaffffcd, 0x3c82cc4c, 0x8b008029, 0xfb065308, 0x4bc30754, 0x58260ef2, 0x0300ff10, 0x2c825ccf, 0x83fa3e21, + 0x290a86d6, 0x4afeffff, 0xf5ffff3e, 0x6a8230dd, 0x84008028, 0x94f70e08, 0x9818154b, 0x98182e47, 0xff282da3, 0xff333381, 0x9a19f600, 0x02286682, + 0xff910080, 0xcdcc0500, 0xe6249c82, 0x0600ff66, 0xcb22bf83, 0xa75beb06, 0x82ab2017, 0x142a59d5, 0xcb072b22, 0x06231a82, 0x828b1078, 0x4cd7304e, + 0x1bfcffff, 0x0200ffe8, 0xffff5278, 0x821804fa, 0x7b0222f0, 0x820a84e8, 0x00a021f0, 0x1f26eb82, 0xfbffffc0, 0x0482086c, 0x08846b27, 0x04fb04fb, + 0x21148205, 0x048684c0, 0x2106d67f, 0x928290c2, 0x827c3f21, 0x83f7201f, 0x68fb271f, 0x0400ffb4, 0x4382709d, 0x82999921, 0xcecc2119, 0xc1826282, + 0x8b0e0822, 0x2405264d, 0xff9a9972, 0x22048300, 0x82668dff, 0x939918cd, 0x154b4133, 0xf600ff23, 0x245a8219, 0x15cccc7e, 0x05da5191, 0xe6030023, + 0x22d08266, 0x828b3433, 0x008025b2, 0xeb074b08, 0x5c0f1b41, 0x6b21070e, 0x5a238207, 0x2b221345, 0x1a834b06, 0xf087f927, 0x1bfcffff, 0x214e82e7, + 0x0482b428, 0x82190421, 0xae872262, 0x350a8708, 0xffff1884, 0xffbe1ff9, 0x00600100, 0x6bfbffff, 0x0400ff85, 0x1441f893, 0xc0f92d07, 0x0600ff83, + 0xff8b7c3f, 0xcc210a00, 0x2905c87f, 0x703d0600, 0xf704f708, 0x2a820504, 0x82719d21, 0x4c972104, 0xcc211982, 0x214382cd, 0xc1856666, 0x20085c4e, + 0xdb9a1800, 0x063a4107, 0x10084919, 0x2082ff20, 0x1782c182, 0x06850820, 0x2f276341, 0xe609ffff, 0x81ffff66, 0x85153433, 0x800200ff, 0xfc27bd82, + 0x00ff9a19, 0x82cccc05, 0x800626ad, 0x07cb0800, 0x0a9f4d2b, 0x0e202482, 0x08504418, 0x8342ab20, 0x20138405, 0x05535c7b, 0x2205a14d, 0x83cb06eb, + 0x7806271a, 0x0300ff10, 0x6f4218e4, 0x05002205, 0x056f42fb, 0x0f820820, 0x7b200a84, 0x06340f82, 0xffff40e0, 0xfffe9ffe, 0x7c940400, 0x6cfbffff, + 0x04f7080a, 0x2005db43, 0x220f823f, 0x8283c0f9, 0xdef522d0, 0x06754235, 0x90c2f922, 0x22078a42, 0x829062fb, 0xb468212f, 0x33211982, 0x21438232, + 0xc1859a99, 0x075f4819, 0x41152642, 0x9c182d1e, 0x7e2f1816, 0xffffcccc, 0x1566e609, 0x80fdffff, 0x54ff8500, 0xfc2205c6, 0x8d829a19, 0x8b008026, + 0x2b064b08, 0x19175242, 0x5f0d972f, 0xeb230a7b, 0x85064b07, 0x204e833e, 0x05ef4333, 0x91215e83, 0x25658408, 0x0100ff91, 0x24426766, 0x99043006, + 0x0400ff99, 0xf7089a99, 0x6f00ff04, 0x4205ffff, 0x3f260756, 0x0a00ff7e, 0xb982ca21, 0x723d0622, 0xc0214e82, 0x23228382, 0x010090ff, 0x04272282, + 0xffff7a94, 0x836666fb, 0x82662049, 0x3333211c, 0x85235984, 0x18f80e08, 0x261a0546, 0xb4fb072b, 0x43b4f706, 0x8520063e, 0x0e275a82, 0x00ff7b54, + 0x82ec510e, 0xae11230a, 0x06850814, 0xf1ffff24, 0x168485ab, 0x22065b48, 0x4d058b2b, 0x591809b6, 0xfb230c9e, 0x828b07b4, 0xf6a8251a, 0xa61c00ff, + 0xe3238882, 0x18ff0a57, 0x18169e59, 0x4408f050, 0x461805f1, 0xf32512c0, 0xfb15d4f7, 0x09b64c1c, 0xffec5126, 0xf833f8ff, 0x0f27e882, 0xf4ffff5c, + 0x8208080c, 0xf007210a, 0x073a0a82, 0x0200ffae, 0xffff00c0, 0xff0040f2, 0x30280900, 0xd7f6ffff, 0x00ff080a, 0x23826c29, 0x48a1d622, 0x3624af82, + 0xffff9a99, 0x0a820482, 0x8280f321, 0x8204822a, 0x82eb20aa, 0x088c6235, 0x06253082, 0xffff3433, 0x291483f9, 0xff333308, 0x66e6fcff, 0x098200ff, + 0x1a828b20, 0x0c820683, 0xff152e25, 0x82200300, 0x3d062766, 0x0600ff70, 0x1a820040, 0x4861c928, 0x53c900ff, 0x71820534, 0xff230a82, 0x4db89ed6, + 0xdb310807, 0x0d00ffe6, 0xffff58b9, 0x970f4dfd, 0xe60400ff, 0x3b3082e9, 0xffa4f00b, 0x9c040500, 0xcc0700ff, 0x0b00ffcc, 0xff8b34b3, 0x66e60c00, + 0x071cf708, 0x0d230982, 0x57ff9042, 0xbd2106bb, 0x82d58270, 0x0e08271e, 0xf814f82f, 0x677b1534, 0xe3ff230e, 0xc6829a59, 0x66a6dc23, 0x06886708, + 0x20137b41, 0x0ed477d4, 0x7e087b41, 0xff220950, 0x88824ce3, 0x0f191c20, 0xff2909ae, 0xff0080ca, 0x9a19dcfe, 0x2c5f8215, 0xffea86f9, 0x6a1cfcff, + 0x2cfaffff, 0x2104824a, 0xcf821203, 0x081e8522, 0x05210a82, 0x300a8260, 0xffff1884, 0xff781ef9, 0x06610100, 0x6bfbffff, 0x32e88284, 0xff08f292, + 0x00c0d2ff, 0x402d00ff, 0xffff0500, 0x837b14bc, 0x417c2004, 0xff330a80, 0xaec7ebff, 0x0a0000ff, 0xf3ffff3e, 0x00ff8f82, 0x8248800c, 0x5ee92734, + 0x1600ffb8, 0x298348a1, 0x002e7882, 0xff86820c, 0x66e6ffff, 0x331400ff, 0x2482ff34, 0x0d285382, 0xff086666, 0x85eb4300, 0x29820484, 0xafc7d227, + 0x612c00ff, 0x210a8249, 0x2a8266fb, 0x9899042c, 0x99feffff, 0x0600ff9a, 0x024568e6, 0x05002205, 0x273483e6, 0xff1d7a02, 0xe6fb0500, 0xd4260482, + 0x0300fffe, 0x23821ae4, 0x8b937822, 0x9e294f82, 0xff066566, 0xc2d50800, 0x2612828b, 0xffffd843, 0x8246d6f8, 0x10f822fe, 0x23968220, 0x079ab960, + 0xeb28ac82, 0x0e158b86, 0x15b4f7ab, 0x8205af52, 0x40142111, 0x23080954, 0xeaa60500, 0x2405814a, 0x0cc20800, 0x050954ff, 0xc1080023, 0x2b0a8306, + 0x0a00ff20, 0x00ff0e2d, 0x92e8bb01, 0x7b225f82, 0x5e4a08e8, 0x3d0a2405, 0x5400ff70, 0xff230902, 0x8490c2f5, 0x069c4a0f, 0x0c02f922, 0xff242d84, + 0x6ed2f5ff, 0xa6203d83, 0x3d216182, 0x20518372, 0x068e53e4, 0x2ffcff28, 0xfaffff1c, 0x19821659, 0x82225b21, 0x75f622b1, 0x271a82c2, 0xffc0ebff, + 0xfafeb7ff, 0x21098e53, 0x1c825c4f, 0xa4b0f122, 0x0bbc9118, 0xef221182, 0x5b743433, 0xefff2f05, 0x00ff66e6, 0x8ba4b011, 0xfb54f808, 0xc7531554, + 0x83ff2007, 0xe6482216, 0x079b5366, 0x17206b82, 0x28059b53, 0xf33df7ff, 0xcf0300ff, 0x276f825c, 0xff5c4ff7, 0x67e60200, 0xcc2ca982, 0xfeffffcd, + 0xff84cd4c, 0x0080f9ff, 0x2321c882, 0x21148205, 0xa7498fc2, 0xffff2305, 0x2982cfef, 0x713d0a22, 0xda4a0f84, 0xfd062206, 0x262d82f4, 0x00ff1a84, + 0x82922d0a, 0xd443213d, 0xc2216182, 0x225c8290, 0x820822d0, 0x1ec5210a, 0xcb260a82, 0x0500ffc6, 0x0e829a99, 0x5334b321, 0x1a82050a, 0x9a190023, + 0x09e754d3, 0xcc85bc82, 0x750a9253, 0xff220644, 0xe887b3f1, 0xcc4cee24, 0x0e6d088b, 0x4d4a1805, 0x2f3e830d, 0x5c4feeff, 0xffff8b08, 0xff5c0fcb, + 0xa4f0d4ff, 0x0e820486, 0xfb088b27, 0xb38b0634, 0x26508205, 0xff107809, 0x826cfaff, 0x9708277f, 0xf7ffff4c, 0x9f821759, 0x0848e122, 0x54210a82, + 0x820a827b, 0xf5ff23ba, 0xc98266e6, 0xff008024, 0x0983f8ff, 0x9899f926, 0x05433b08, 0xfd203682, 0xfb20fa82, 0xfd221783, 0xf582291c, 0x82008021, + 0x33f9226d, 0x82748334, 0x00ff2406, 0x8219e402, 0x82852016, 0x0c0529f2, 0xfbffff09, 0xdb08a470, 0x00233882, 0x82457604, 0x2691820d, 0xcdcc0500, + 0x82fdffff, 0x20098355, 0x2285828b, 0x82df4f03, 0x4d032795, 0x0000ff92, 0x808200b0, 0xff182426, 0xe05f0100, 0x08221a82, 0x0f82dda4, 0x4186d621, + 0x9921073b, 0x063b419a, 0xf727c982, 0x00ff0634, 0x82523858, 0xc7472411, 0x8200ffae, 0x820a8204, 0x584c1810, 0xd4fb2917, 0xff1514f7, 0x9a199f00, + 0x00243882, 0x056366e6, 0xf622bb82, 0x5c82f087, 0x82f89321, 0xb4682bfc, 0xa60800ff, 0xfcffffea, 0x7b82b81e, 0x842b0327, 0xa3feffff, 0x258082d8, + 0xffffce4c, 0xbd5d4cff, 0x22b18305, 0x82e0cf05, 0xc205226a, 0x20ef820c, 0x21b18220, 0x04838004, 0x08f00725, 0x8205d3db, 0x14ee264d, 0x8b0400ff, + 0x4b1c8244, 0xff240720, 0x32b30700, 0x07229783, 0xfc8234b3, 0x82e81b21, 0x7a942625, 0xf3faffff, 0x232a82f8, 0x3b085c8f, 0xff213882, 0x2c0d83f8, + 0xffe04f06, 0x64dbf5ff, 0x900100ff, 0x21958220, 0x90822a5c, 0x08123822, 0x5e200a82, 0xfb253b82, 0xffff5e3a, 0x236f82f9, 0x7268f7ff, 0xae20bf84, + 0xcd84ab82, 0x0634fb27, 0xc7a7ffff, 0x271582ae, 0xff5238b8, 0x3433b8ff, 0xa7220a82, 0x7882cccc, 0x4feeff2d, 0x0e00ff5c, 0xffff7b54, 0x56a4b0f1, + 0xa41807b8, 0x342018dd, 0x2b24b883, 0x00ff9a19, 0x21080484, 0x8b67e634, 0xffef0e08, 0xccccdc01, 0xff1534f7, 0xce4cf0ff, 0xc0ffff42, 0xff54cc4c, + 0x9a99b2ff, 0x0685088b, 0xbfffff25, 0x82c26666, 0x33332262, 0x221282d4, 0x49cdcc7c, 0xcf4f0eaa, 0x33b3210c, 0xd44f9185, 0x054a5705, 0x33830024, + 0x16820633, 0xffcdcc24, 0x84834900, 0x82994021, 0x83362084, 0x664d2289, 0x20678266, 0x27068300, 0xb33f00ff, 0xc9ffff34, 0x0f292083, 0xffff32b3, + 0x089a19b6, 0x183b82ff, 0x200eef98, 0x086966f1, 0x18ff8b21, 0x221633d7, 0x82cccc7c, 0x336323a3, 0xcd185b34, 0x00210cd0, 0xdae41923, 0x82cc2023, + 0x33dc2556, 0xdcffff34, 0x12dae419, 0x1683cc20, 0x00ff3430, 0x8b34332c, 0xf72f0e08, 0xd000ff64, 0x658266e6, 0x83b35621, 0x4c0c2aa6, 0x1b00ffcc, + 0x00ff6766, 0x2641821c, 0x99991400, 0x822000ff, 0x83c78274, 0x83ff2031, 0xffff2481, 0x82cd4cdb, 0xb3d42363, 0x06820833, 0xef82d220, 0x6f846a82, + 0xd3200482, 0xff212d84, 0x235f82df, 0xcce3ffff, 0x13214e82, 0x201682b3, 0x280482f3, 0x32331d00, 0xa9ffff08, 0x22dc834c, 0x829a19db, 0x99df2d3c, + 0xffff9699, 0xffcd4ce5, 0x9a191400, 0x091a1c85, 0xff29b4da, 0x6666dfff, 0x80ecffff, 0x20f58200, 0x200982e6, 0x310483e3, 0x080080f3, 0x990400ff, + 0xcfffff9a, 0x00ffce4c, 0x09821929, 0x1982d920, 0xe6310024, 0x22438b66, 0xfb072605, 0x151cf714, 0x0b7a60ff, 0x9ad90929, 0x0e00ff8b, 0x82086626, + 0x5c0c2d06, 0xf5ffff2a, 0x00ff0040, 0xffd6a30b, 0x2812dc60, 0x8b2a5cf4, 0xa3f3ffff, 0x2d2d82d6, 0x9ad9f1ff, 0xc00a00ff, 0xf6ffff00, 0x54856626, + 0xfe231682, 0x8d9a199f, 0xb30a2162, 0x1030a418, 0x16826283, 0xf5216293, 0xc2a4184c, 0x82628310, 0x21628616, 0x4742b4f7, 0xf2ff2106, 0xff205883, + 0xff231983, 0x836666f4, 0x9a992198, 0xcc209884, 0x5e84ff82, 0x3233f622, 0x51823582, 0x0d20ff82, 0xaf820682, 0xff34b326, 0xcecc0900, 0x0e22ed82, + 0xf4843233, 0x49666621, 0x0b2206b3, 0xb3499a99, 0xf8af2707, 0x1554f8a4, 0x255474fc, 0x1998180e, 0x18d42009, 0x2617c1a6, 0x7b0654f7, 0x8243055b, + 0xccf22238, 0x229382cd, 0x823333f5, 0x6233205e, 0x11820714, 0xccccf222, 0xcc218782, 0x821684cd, 0x3333269e, 0xa4f7088b, 0x0c964106, 0x8d180a20, + 0xa8820853, 0x21051162, 0x6d410040, 0x82f22006, 0x4308251b, 0x05bb7b06, 0xff206b82, 0x312da718, 0xfc15b43b, 0x74f70654, 0x0654f807, 0x0e0774fb, + 0xb37a01ff, 0x1534f834, 0x990affff, 0x21858299, 0xb082b37a, 0xcc4c6925, 0x8200ff05, 0x00ff2418, 0x8234b396, 0x4c85230a, 0x2383fbcc, 0x9a999425, + 0x828d00ff, 0x07fb241d, 0x8472ffff, 0x66de281a, 0xfeff0666, 0x8266666b, 0x7c542118, 0x94224782, 0x1b829999, 0x8284ab21, 0x221b8436, 0x82008dff, + 0x548d22bb, 0x3810827c, 0xff66e688, 0x1ec557fe, 0xffff8e15, 0xff32b3fc, 0xcd4c0400, 0x33feffff, 0x44098234, 0x042005df, 0x0c820682, 0xffc6402b, + 0xf8d30100, 0x040300ff, 0x3204825a, 0xff08e83b, 0x14eef200, 0xf0fa00ff, 0xfeff0520, 0x82d6c302, 0xeff22eab, 0x05ffff5c, 0x0e059a19, 0x01ff30fb, + 0x0e485339, 0xff00802b, 0x20c5f5ff, 0xcfefffff, 0x08db5e5c, 0x08e03a27, 0x0504f723, 0x06d85eff, 0x22224453, 0x530ca208, 0xd3290b44, 0x07a4f706, + 0x0800ff8b, 0x307b82cf, 0xffcdccf8, 0xa4300700, 0x33f7ffff, 0xfb088b33, 0x0eef4504, 0x78824f20, 0xd0180020, 0xf7201a14, 0x00233082, 0x829a192c, + 0xe623224f, 0x11aa1866, 0xa4fb210b, 0x5310025f, 0xfb29280f, 0xffd2f730, 0x66662e01, 0x05bd4a15, 0x40f7ff23, 0x21a18200, 0x8f55ac5c, 0xf6ff2305, + 0x275d3473, 0x90022205, 0x25678205, 0xd3ffff8b, 0x7c82b8de, 0x82291c21, 0x48212104, 0xe3210e82, 0x22ccb7d7, 0x73cdcc08, 0xa4271294, 0x00ff4307, + 0x5d66e600, 0xa7210e55, 0x26a083f0, 0x0800ffa4, 0x890806c1, 0x00ff2e0a, 0xffe1ba01, 0x6a3c0900, 0x7d0600ff, 0x087b5471, 0xff7d7f26, 0xe23a0a00, + 0x210d4e5d, 0x7b541ec5, 0x00802207, 0x07475d84, 0x8268e621, 0x3433214d, 0x3330f482, 0xaf0e0832, 0x94f7f4f7, 0xff06ab15, 0xcc4c2300, 0x11678b18, + 0x0754fb22, 0x16cb8818, 0x180eb44d, 0x830bd14b, 0x204e8233, 0xdf8a18cd, 0x4f332008, 0x74220730, 0x4f82bb06, 0x874f0028, 0x4000ffae, 0x04820080, + 0xff527823, 0x8e5e1800, 0xbfff2310, 0x7682ae87, 0x5278b024, 0x2f825b08, 0x4ceeff27, 0xf1ffffcd, 0x23b382b3, 0xff33b3f1, 0x8406af60, 0x21168506, + 0x4a180e00, 0x5f840833, 0x142e2c22, 0x24066047, 0xffecd123, 0x060c47ff, 0x16850683, 0x18dcff21, 0x27087f68, 0xfb0e075b, 0xa800ff30, 0xcc286183, + 0xff15cccc, 0xcccccbff, 0x33209782, 0x8b2e6c82, 0x00ff66e6, 0x8b9a999b, 0x665700ff, 0x06820866, 0x3e0a6a27, 0xf55500ff, 0x220483c3, 0x8200ffc2, + 0x088b290e, 0xffe18bf5, 0x3e0aaaff, 0x9522b082, 0x2582c2f5, 0x99a8ff2d, 0xff09fb9a, 0x666664ff, 0x83ccffff, 0xccbf26b0, 0xffff08cc, 0x200a83f3, + 0x22c583f0, 0x823433e9, 0x290f832d, 0xcc4c0f00, 0xff068b08, 0x1c821700, 0x33f30027, 0x00ff1534, 0x20cc8423, 0x8210831c, 0xe44e1904, 0xffcd2310, + 0x44831c00, 0x33b3dc23, 0xbccd188b, 0xe3ff230c, 0x5682cc4c, 0x34b3dc22, 0x1e828483, 0x33212883, 0x821682ff, 0x20548332, 0x22ea8208, 0x82eb54f7, + 0x07352262, 0x245782ae, 0xff52f82a, 0x82048200, 0x2110820a, 0x2b593b08, 0x06db232e, 0x339007ab, 0x11b86218, 0x0cb84618, 0xea82db20, 0x66e62022, + 0x64183785, 0x082716ce, 0x00ff04d6, 0x86fc2907, 0x280e8204, 0xffdb088b, 0x9a19ffff, 0x24a98505, 0x07d5ffff, 0x26b984ae, 0xf8caffff, 0x85088b52, + 0x83168506, 0x848b201b, 0xfb082310, 0xcc180734, 0x2c220f80, 0x9d1834f7, 0xf32213e5, 0x44829999, 0x1219d721, 0x45018403, 0xf730fb26, 0x1554f8c4, + 0x0cd1cd18, 0x180c5253, 0x201af16c, 0x0ed65174, 0x23f16c18, 0x74fc0422, 0x344fdd6c, 0xf1ffffcd, 0xffff00c0, 0x8b3333ee, 0xf804f708, 0xd4fb1534, + 0x26d08207, 0xf707d4f7, 0x820e0674, 0x83d420e1, 0x499420e1, 0x68181704, 0x2a5d0b62, 0x4833820e, 0xf8241598, 0xff8b0734, 0x2a5d1a83, 0x32388307, + 0x8b0080e5, 0xfeff3b08, 0x1566e640, 0xf6ffff8b, 0x5cffce4c, 0xf822057d, 0x5947cccc, 0xffff2406, 0x829a19bf, 0x19f82288, 0x47218299, 0x33200576, + 0x201e8743, 0xba6718cb, 0xcccc210e, 0x19223a83, 0xda40089a, 0xffcb26da, 0x9a193f00, 0x08c54115, 0x07d4fb34, 0x90f7af0e, 0x8b1584f7, 0xe60b00ff, + 0x0800ff66, 0x04869a19, 0x8b350e82, 0x96069b08, 0xffff948b, 0x8b66e6f7, 0x19f4ffff, 0x0747089a, 0x28128f8f, 0x8282808b, 0x5b088b80, 0x82218406, + 0x232d8227, 0x08968b94, 0x8f2a5296, 0x3000ff06, 0xff076666, 0x7083f6ff, 0x67e60128, 0x19f9ffff, 0x2e82939a, 0x33b30927, 0xf798f708, 0x5c531824, + 0x47942018, 0xfc21178a, 0x17726454, 0x3383f720, 0x23650020, 0x54f82613, 0xfb14fc06, 0x27fa83d4, 0xffcc4c23, 0x9959e3ff, 0x2a075746, 0x088b66a6, + 0x06cb074b, 0x1854f74b, 0x200ad76a, 0x0be97c67, 0x4b064b29, 0xfb54f807, 0x82cb1554, 0xb3dc22c9, 0x20f78234, 0x464584e3, 0xcb200881, 0x218a761a, + 0xff157b26, 0x9a19c2ff, 0xcd243b82, 0xffff66e6, 0x0a820482, 0x08201082, 0xff240685, 0x9a193200, 0xa4181684, 0x1b8312a4, 0x17848b20, 0x00212d82, + 0x863f863d, 0x50438232, 0x0f200592, 0x00234082, 0x82008050, 0xccd42568, 0x3500ffcc, 0x0805ec6a, 0xffdf4f30, 0xaec70a00, 0xfff0ffff, 0x0300ff7d, + 0xffffe2ba, 0xff5238f3, 0xc876faff, 0x93ffff08, 0xffff0080, 0x05707dd1, 0x17f2ffff, 0xffff850a, 0x04826bf8, 0x5ccff022, 0x612b2a82, 0xf1ffff48, + 0xff086666, 0x82401700, 0x339b2325, 0x15820532, 0x82014021, 0x78d32d15, 0x7a0c00ff, 0x00ff81e2, 0x8b33b30e, 0x6b222182, 0xa1826666, 0x34b3622a, + 0x752500ff, 0x4e00ffc2, 0x3e228c83, 0x6282a430, 0x3c82a720, 0x8f450023, 0x2062835c, 0x27fa82a6, 0x7dd8e3f6, 0x99f7ffff, 0xf020ee82, 0xf82d7d83, + 0xff08cccc, 0x32b36701, 0x669affff, 0x27bd8266, 0xff666660, 0x9a197d00, 0x41226d82, 0x4b82ae07, 0xff52f82f, 0x84ab2700, 0x876400ff, 0x02f78bae, + 0x27698208, 0xfff6a80e, 0xf007f6ff, 0x8a218682, 0x2190823e, 0x9a83c0bf, 0x6e820020, 0xec519b22, 0x3c21b082, 0x216e82cc, 0xc6834ff1, 0x82f06721, + 0xc2f521fb, 0x6125da82, 0xf9ffff88, 0x223882e8, 0x82d017f2, 0x7ad12729, 0x93ffffe2, 0x29820080, 0xe08ffa27, 0x38f3ffff, 0x21448250, 0x4e82c0aa, + 0x4d2a1c21, 0xf7220663, 0xdd825238, 0xecd13527, 0xebd3ffff, 0x27298285, 0xffb2bdf3, 0xcddce7ff, 0xb1835382, 0x82e6e721, 0x4cee32d1, 0xeaffffce, + 0xff08cecc, 0x289ca4fe, 0x491001ff, 0x222982fc, 0x829999fb, 0x2070254e, 0xc7faffff, 0x0122c582, 0x09824aac, 0x8b0ad722, 0xf8237982, 0x828b48e1, + 0x14ee248f, 0x1afcffff, 0x250f7407, 0xffffdfcf, 0xb8828ff5, 0x68d10122, 0xae826482, 0x700a0034, 0xf7ffff21, 0xff087ad4, 0x98194f02, 0xe630feff, + 0x9f820566, 0x82008021, 0x82cc2015, 0x110f219e, 0x0127f282, 0x00ff00e0, 0x82b81e08, 0xf0672118, 0x09311482, 0x00fff81e, 0xffd28209, 0x9c19feff, + 0x190f00ff, 0x2157829a, 0x23829899, 0x08323322, 0x72366e18, 0x0f5d6b18, 0x1808f658, 0x1819a773, 0x210a5d6b, 0x1a4a33b3, 0x4a00200d, 0x6e180631, + 0x27086c36, 0x0800ff0e, 0x01ff5c4f, 0x159a1902, 0x00ff44f7, 0x059a1997, 0x680f00ff, 0x0d00fff6, 0x00ffcc4c, 0xffae4718, 0x8235f5ff, 0xeb3dd182, + 0xff08bc54, 0x32f3afff, 0xa000ff07, 0xffff9a99, 0xff2a1cff, 0x66667f00, 0xccdfffff, 0x232082cc, 0x08cecc67, 0xc2250682, 0xffff5c8f, 0x2d4182d8, + 0xd823c3ff, 0x40d4ffff, 0xe0ffff00, 0x3b823233, 0x57f22708, 0xf6ffff0a, 0xffffe00f, 0xffec91ec, 0x10780c00, 0x070500ff, 0x1000ffae, 0xff08c816, + 0x0a572d00, 0xffff25f7, 0x7c8228bd, 0x82802621, 0xe6642735, 0x0200ff66, 0x3a82ce4c, 0x7c14a823, 0x205b8207, 0x239382eb, 0xa4b0e7ff, 0x2305ca51, + 0xb89ef0ff, 0x4a23a782, 0x87fb083e, 0xf4ff28ba, 0x00ffdfef, 0x82265c0a, 0x82f8209e, 0x3311265e, 0x0b00ff34, 0x30098218, 0x08008009, 0xff94f70e, + 0x0002c001, 0x0400ff15, 0x221882b3, 0x82120000, 0x226a8309, 0x82e2fbfe, 0x32332109, 0xcf98091a, 0xfeff8b25, 0x82343143, 0x198931ef, 0x4200ff9a, + 0xffb1cccc, 0x66e69300, 0xe60000ff, 0x582b0482, 0xfb0834b3, 0x4a00ff44, 0x820548a1, 0xf8852c29, 0x2f0e0552, 0x01ff14f8, 0x5bfaffbf, 0xfe490dd5, + 0xff662519, 0x0040e4ff, 0x5b07204e, 0xa62b0fd5, 0x00ff8b66, 0x08347322, 0x820714f8, 0x59232209, 0xf07618a0, 0xff602e08, 0x34b3dcff, 0x34fb088b, + 0x0020feff, 0x5d014a06, 0x83eb3421, 0xd4f728cf, 0x06d4f707, 0x8307d4fb, 0x54f821e5, 0x9a20e28d, 0xc1439982, 0x0ce14a08, 0xe322e282, 0xe29c9a59, + 0x9a592322, 0xab18e288, 0x2b201113, 0x220fff49, 0x49ffffcc, 0x342506ff, 0xffff088b, 0x2bff499f, 0x67e60731, 0x06eb088b, 0xb30900ff, 0x00ff8b32, + 0x84343307, 0x07ff494c, 0xf78baf22, 0x83051548, 0xa61c22b1, 0x35c71a66, 0x0d27500e, 0x3b26ef88, 0xe5ffff07, 0x44820080, 0x6880ea21, 0x0a820519, + 0x6f181082, 0x3b20171d, 0x2131cb48, 0x661807db, 0x6d830d8c, 0x801a0023, 0x4b628200, 0x82240634, 0x1500ff8f, 0xe5317e83, 0x088b717d, 0xf70e07db, + 0x1534f794, 0x874f00ff, 0x24e882ae, 0xff527840, 0x82048200, 0x8310820a, 0x045e1835, 0xe27a2116, 0xbf23bb82, 0x50ff1e85, 0x8d500a86, 0x05b45005, + 0xb4501683, 0x195f2f08, 0xff156b9a, 0x66e640ff, 0xa7ffff06, 0x2882d7a3, 0x295cb827, 0x5eb8ffff, 0x410d19b8, 0x54ee2209, 0x05ce587a, 0xabf1ff2d, + 0x1000ff86, 0x088b1fc5, 0x70c001ff, 0xab2105c2, 0x22918286, 0x83146e0d, 0x827a2021, 0xab11220a, 0x05925686, 0x5800ff24, 0x49826666, 0x00290482, + 0xff9a9947, 0x34b3a6ff, 0x805d188b, 0x10a5206f, 0x2801cb5a, 0xd700ff26, 0x44f79a19, 0x210cde61, 0xde615c4f, 0xeb112107, 0x2108de61, 0x0a8314ee, + 0x61ffcc21, 0x332a06de, 0x0900ff34, 0xffff6626, 0x956ee6f6, 0xe1ff2907, 0xff05a4f0, 0xa4f0b1ff, 0xee210482, 0x13de6114, 0xffb17f23, 0x05d758ff, + 0xb89e1628, 0x61e9ffff, 0x45600548, 0x26158205, 0x1400ff02, 0x858b8f42, 0x0c00290f, 0xff08a87f, 0x5d0f4e00, 0x11210482, 0x0dd66eec, 0x00200622, + 0x2205656d, 0x822f0800, 0xc2fc28aa, 0x0800ff0c, 0x828bec51, 0x20042230, 0x26418200, 0xff6d2704, 0x82ca0000, 0xf8032751, 0x0100ff93, 0x1a8212a4, + 0x52f80b31, 0xf30400ff, 0x0700fff8, 0x00ffaec7, 0x82c0aa0b, 0xf00c2229, 0x281a82a4, 0x07e4f787, 0x19ffffff, 0x05ff47e8, 0x33f6ff2d, 0x0a00ff33, + 0xffff34b3, 0x83cdccf1, 0xe6502656, 0xf715ab66, 0x09226e1c, 0x82a4b021, 0x82cc2046, 0xee04223a, 0x214b8214, 0x0a83f8f3, 0x8210f821, 0x2365820a, + 0x0040fdff, 0xc0204982, 0xf627a582, 0x00ffd0d7, 0x6d662609, 0x5c200948, 0x4e22cb82, 0xd6875c0f, 0x82800c21, 0x8204822a, 0x4214298b, 0xf3ffff8e, + 0x00ff0e80, 0x30820f82, 0x4861e927, 0x9e1600ff, 0x064841ba, 0xff251583, 0x70bdebff, 0x8225838b, 0x80f3215b, 0x6e41d682, 0x6e162007, 0x2431134c, + 0xf2ffff18, 0x00ff3849, 0x7ff2b202, 0x18fbffff, 0x225682d4, 0x82ae07f4, 0x0a0c2b0a, 0x38f8ffff, 0xf4ffff52, 0x1e6e3e55, 0x241a8205, 0x0766e678, + 0x200082ff, 0x21f8826e, 0x02417fcd, 0x4cf52206, 0x2ccc82cd, 0x088bcc4c, 0xff64f70e, 0x9a99a600, 0x87808515, 0x89712090, 0x82842090, 0x0aff4144, + 0x82063b6e, 0xf9ff22f2, 0x21e782e0, 0xb6822006, 0xa4d0f72d, 0x3d0300ff, 0xf7fffff4, 0x828b15ae, 0xe0fb2230, 0x22418200, 0x8293d8fb, 0xfe352b79, + 0x07fcffff, 0xfeffff6d, 0xab89ee5b, 0xab860982, 0xab8d4020, 0x02000023, 0x21ab82e4, 0xab82bcd4, 0x59abbf21, 0x0d2406f5, 0x088b0040, 0x2035ac41, + 0x23ac41cf, 0x8b707d2c, 0x421400ff, 0xf3ffff90, 0xac418380, 0x42603108, 0x991600ff, 0x01ff059a, 0xff9a1917, 0x66661901, 0x20175343, 0x213265ec, + 0x719ad921, 0x53430c12, 0x71bd2117, 0x20083d43, 0x43308200, 0x00201153, 0x5343a884, 0x83802008, 0x067c4225, 0x5343eb20, 0x2709370d, 0xf6fffff0, + 0x00ffe8db, 0xffc8b60d, 0x0e4dfdff, 0x0400ff97, 0x56822ae7, 0x1eda0c22, 0xf4210a82, 0x0c2265fe, 0xcccc0d22, 0x5c062265, 0x4c290563, 0x0a00ffcc, + 0xffff70bd, 0x7f8a18f1, 0xe3393207, 0x3200ffd7, 0xff15cccc, 0xedbcf9ff, 0x9d0800ff, 0x216182b2, 0x4b82f43d, 0x82f29221, 0x9a193309, 0xffff088b, + 0x8b85abe8, 0x59f7ffff, 0xebffff9a, 0x0a82ec51, 0x66a6f423, 0x27068208, 0xff5e7af9, 0xacfc0100, 0x6c203c82, 0x04278382, 0xffffc520, 0x82ec51fa, + 0x852e230a, 0xbb824b1f, 0xd7430622, 0x6b273782, 0x0900ff86, 0x67ff00c0, 0x09220572, 0x5382f6e8, 0x4a170023, 0x22f2823e, 0x8215ae08, 0xf6a821fd, + 0x0b220a82, 0x5382b85e, 0x8506002d, 0xfeffffa2, 0x00ff1203, 0x82f89306, 0x7ddf2632, 0xae0500ff, 0x32858214, 0xff287cd1, 0x70fd3f00, 0xb601ff05, + 0x00ffc435, 0x1834332d, 0x26093376, 0xfffff668, 0x820040dc, 0xc0d32294, 0x20478200, 0x240682ff, 0x972300ff, 0x2416840a, 0x212c00ff, 0x22758348, + 0x8246212c, 0xc723226a, 0x201b82b0, 0x222d82c0, 0x83402c00, 0x8206832d, 0xa4302128, 0xff241684, 0x66e6d3ff, 0x8f282d83, 0x00ff66e6, 0x15b89efc, + 0x0d223382, 0x8d822a9c, 0xfff4dd26, 0xe2ba0d00, 0x6926d482, 0x0b00ffbc, 0x978228dc, 0xb85ee831, 0x802000ff, 0xffff0500, 0xff5c8ff2, 0x82801200, + 0xabeb22ea, 0x26f48284, 0xffff142e, 0x8268a6eb, 0xf2ff234b, 0x9c82281c, 0x9c19f222, 0xb8264582, 0xf4ffff10, 0x4582ac47, 0x82247b21, 0xc7352140, + 0x6d220a82, 0x40829819, 0x6866d237, 0xe6deffff, 0xd6ffff67, 0xffff3233, 0x6667e6d9, 0x80d5ffff, 0x31258200, 0xffaec7e7, 0xb81ee4ff, 0x0addffff, + 0xdbffff3d, 0xa782d8e3, 0x6082ae20, 0x825cdc21, 0x38002285, 0x28ea8257, 0x05e27ab2, 0xca3500ff, 0x2ac7823e, 0x00ffd863, 0xff285c2d, 0x82e81300, + 0xf31b22b4, 0x31af8234, 0xff0852f8, 0x48e13300, 0x3100ffa1, 0x00ff866b, 0xba82de1b, 0x98992d22, 0x3a21bf82, 0x271a82e2, 0xffcc4cca, 0x34b39200, + 0x11274482, 0x00ffc4f5, 0x827a140e, 0x36cf82c5, 0x66661400, 0x1400ff8b, 0x0e08b89e, 0x99ad01ff, 0xaf00ff9a, 0x82159a19, 0x42102b12, 0x1000ff90, + 0x00ff2a5c, 0x3c828c00, 0x46a10d22, 0x0024ed82, 0xff56ee02, 0x42200082, 0x10224882, 0x2683d8a3, 0xff234482, 0x82aaf1fd, 0x5c0f262b, 0x38fcffff, + 0x27d282d4, 0xffa0faff, 0xe4060200, 0x78833b82, 0x66e60125, 0x6a088d8b, 0xff21176c, 0x241e82fd, 0x33fdffff, 0x26588234, 0xffff00be, 0x82ccccfe, + 0x00f42109, 0x0327b782, 0xffff73a8, 0x82707df0, 0xf773214d, 0x2b2a0982, 0xffff8b84, 0x08ceccef, 0x2282858b, 0xfffdb726, 0x52f8f9ff, 0x84830982, + 0xae07fa22, 0x5e277a83, 0xf7ffffcd, 0x82849aa7, 0xa4b0211a, 0xb3210a82, 0x23b78233, 0xb4e8f9ff, 0xf6273982, 0x00ff9e0f, 0x8214ae04, 0x4a0b228a, + 0x2291833e, 0x82a6bb01, 0x04b725a4, 0x6b0500ff, 0x00235b82, 0x837a8909, 0x820f2016, 0xfdff27fc, 0x00ff6b9c, 0x4982eb0e, 0xfb29fc22, 0x82210982, + 0x225f8290, 0x82dd2391, 0x285c2681, 0x99a8ffff, 0x21048299, 0x0e82727d, 0xff7b9426, 0xffff90ff, 0x0e21b082, 0x22738270, 0x82562efc, 0x82f0202e, + 0x07fe2709, 0x0f00ff6d, 0x8282ec11, 0x820a0021, 0x21668206, 0x70821f85, 0x8782cf20, 0x7bd40122, 0x06221683, 0x8e82a03a, 0xd1420a27, 0x57fbffff, + 0x22a482cf, 0x82c0aaf4, 0xefff2382, 0x5982d7e3, 0x82b8de21, 0x0a5726dd, 0x66f2ffff, 0x232d8266, 0x3373fcff, 0x09223e82, 0x1b8205fc, 0x8285ab21, + 0x14f0312d, 0x0200ff7b, 0xffffec71, 0xff6666f0, 0xfba90300, 0xff27a482, 0xffffa3f2, 0x827fcafe, 0x01be263b, 0x33fdffff, 0x22298234, 0x6d66e6fd, + 0x0222193d, 0x8582e610, 0xfafe0122, 0x42215d82, 0x21518200, 0x0982140e, 0x82000d21, 0x62fc224c, 0x21c3820c, 0x4782cc7d, 0x19828020, 0xcecc0f22, + 0x10202982, 0x2205ed5f, 0x8220b005, 0x82402026, 0xb1052216, 0x21098228, 0xe182fc77, 0x3005027b, 0x00ff48b2, 0xffba8908, 0x30970700, 0x120600ff, + 0x210e826e, 0xc382f833, 0x19070023, 0x2041829a, 0x22d58308, 0x82e00ff9, 0x04f72299, 0x2299839a, 0x825aa4fd, 0xfc5826b0, 0x7afcffff, 0x2216825e, + 0x83f628f6, 0xc0f02116, 0x02205e82, 0xff238482, 0x820a17f1, 0x76d325e1, 0x80f1ffff, 0x00279982, 0xffcecc6e, 0x82a11000, 0x66572768, 0x5700ff64, + 0x0e825278, 0x6e20a383, 0x2482ea82, 0x82347321, 0xdcd9212e, 0x2305b852, 0x1e050200, 0xd9210982, 0x2382829a, 0xae87f5ff, 0xfa226082, 0x7082e23a, + 0x04821a20, 0x281cfe22, 0xfd221683, 0x1082c443, 0xffeafb25, 0x824cf2ff, 0x6602225a, 0x2ba88266, 0x089a990d, 0x9940ffff, 0x1524f799, 0xe4313482, + 0xffff5238, 0xff33b3b1, 0x14aeafff, 0xb3e1ffff, 0x22398334, 0x825463f7, 0x9af8221b, 0x21ea821c, 0x358287f6, 0x5a040922, 0x0023bc82, 0x82830006, + 0xdd642683, 0xbf0500ff, 0x0804827d, 0xffdec420, 0x71bd0200, 0x5000ff08, 0x00ffcd4c, 0xff7a1426, 0xf6e8fbff, 0x6b3800ff, 0x1700ff86, 0x4c82142e, + 0x8e0c0023, 0x82868297, 0x0300219c, 0xff23cd82, 0x829899f4, 0x4cfb225b, 0x203582ce, 0x2335829f, 0xcc4c5eff, 0xfa2b8983, 0xfffff608, 0xffd0a2fc, + 0x8248faff, 0x3bfa2709, 0xfdffffa6, 0xac820040, 0x142eb127, 0x6edaffff, 0x2b6b8214, 0xffff66e6, 0xffec91c6, 0xe2fae8ff, 0xff235b82, 0x82866bf3, + 0x91fc274c, 0x0b00ffea, 0xa8823e8a, 0x707d0434, 0xffa78b08, 0x3e4a4e00, 0x665100ff, 0x1d00ff66, 0x29825ccf, 0x47090023, 0x271e82f0, 0xff34b306, + 0xce4cf8ff, 0xf7273482, 0x0e0832b3, 0x829400ff, 0x012d08fb, 0x1534b314, 0x82abffff, 0x5400ff8f, 0xff055078, 0x299ce3ff, 0xd7dfffff, 0xebffff0c, + 0xffff707d, 0xffaec7d8, 0x9a99f6ff, 0x94d4ffff, 0x20b7827a, 0x20c8830d, 0x21d283fc, 0x3882ee0d, 0x6783fd20, 0xf6a80e23, 0x221a828b, 0x820a5726, + 0xc2222a67, 0x0e00ff90, 0x00ff9a19, 0x2335821b, 0x9a991600, 0x2d2b1a82, 0xffffcdcc, 0x156666ff, 0x833d00ff, 0x80c22840, 0x00ff0500, 0x833433a9, + 0x82322004, 0xccd22a75, 0x2700ffcc, 0xffff7cd4, 0x26e882c4, 0xb85e1800, 0x46bfffff, 0xf82205db, 0xb3829a99, 0x9999f822, 0x82264182, 0xf7ffff00, + 0x098267e6, 0x82126121, 0x82042056, 0xf0ff2cc1, 0x00ff88f6, 0xff333302, 0x8359f0ff, 0x66ef2029, 0xd02505d8, 0xffff5ccf, 0x227783ee, 0x823ecad4, + 0x222a83d6, 0x860080de, 0x7b0024c2, 0x551566e6, 0xfd2c0738, 0x00ff8360, 0xff14ee0d, 0xfc49fcff, 0x25830982, 0x88d4ff23, 0x20f886b4, 0x419182d7, + 0xe022050c, 0x4982e1ba, 0x822a9c21, 0x7a542144, 0xab220a82, 0xc6821e85, 0x0a971622, 0x0483ec82, 0x2222f684, 0x588290c2, 0x0a572626, 0xdbffff08, + 0x6d253a83, 0xff150080, 0x867b82ff, 0x848f8485, 0x20a38299, 0x2225828b, 0x82cdccef, 0x82bd82e1, 0x6a3c21c7, 0xf526c782, 0x0300ffc3, 0x1a8286cb, + 0xd861ff27, 0xc4f8ffff, 0x20f182dd, 0x22038281, 0x829999f8, 0x99f82329, 0x0682089a, 0xec11bf23, 0x052941ff, 0xbb82c420, 0xd7270026, 0xd2ffff0a, + 0xff24fc82, 0xa430a900, 0x332c0482, 0xffff0534, 0xff0080c2, 0x00803d00, 0x9128a782, 0xffff9a99, 0x1566666e, 0xff24158b, 0xffcdcc56, 0xce200482, + 0x2c212082, 0x260a824c, 0xc73233d8, 0x82e7ffff, 0x4000232b, 0x9e8266e6, 0x70070023, 0x26d08220, 0xffe04f07, 0x827e0000, 0x4707224d, 0x210982ae, + 0x9e82ee9e, 0x862bfc2c, 0x160f00ff, 0xfdffff46, 0x0982cccc, 0x82989921, 0x33102229, 0x269e8234, 0x34332f00, 0x831100ff, 0x332b2604, 0x1c00ff32, + 0x2620824c, 0x08008021, 0x822d00ff, 0x060d422b, 0xe27a5424, 0x4641ffff, 0x631c3b05, 0x2000ffd6, 0x00fff628, 0xff908214, 0x52382700, 0x660900ff, + 0x2b00ff66, 0x6a82866b, 0x2085f22f, 0xc70300ff, 0xf2ffffae, 0x00ff9a19, 0x23a08202, 0xcc4cf1ff, 0xff27a082, 0x8b34b3d9, 0x82ddffff, 0xf1ff2665, + 0xffff66e6, 0x233582e4, 0x6666e9ff, 0x54206a82, 0xfd22fe83, 0xf382b8de, 0xcecc5622, 0xd421e882, 0x27e8827c, 0xff1e853d, 0xe27ac2ff, 0x21200a82, + 0x00238082, 0x82ea511c, 0x853f8266, 0x82b982af, 0x82002056, 0x21cd82c7, 0x5182a60f, 0x96c3fd22, 0x0a26dd82, 0xfcffff3e, 0x56827a34, 0x289c002c, + 0x3b0700ff, 0x0000ff24, 0x09820080, 0x82666621, 0x60072029, 0x40200527, 0xe7268283, 0xffc79a99, 0x5283d8ff, 0x1e452c22, 0x7028be82, 0xfeff3433, + 0x157cd486, 0xf122a982, 0xc0820a57, 0x827c9f21, 0xec1121ca, 0xb621d482, 0x22098206, 0x82080080, 0xc2752183, 0x2722f486, 0x0841c435, 0x21202b06, + 0x1c00ff48, 0xff08d663, 0xb782abff, 0x83540021, 0xe9ff23b7, 0xe8822c72, 0xfff66822, 0xfc82f285, 0xd9225882, 0x557234b3, 0x04fb2362, 0xfc1864fb, + 0x00210c7f, 0x514a180e, 0xcd4c2211, 0x251683ff, 0xb31100ff, 0xd9828b33, 0x09f55118, 0x134c4b18, 0x8233b321, 0x00c02cc7, 0x4ceeffff, 0xeb088bcd, + 0x821514f7, 0xf6a82738, 0x0e00ff8b, 0x1a843e4a, 0x4b18dd82, 0xb5210c7e, 0x821684c2, 0x0b572131, 0xff215f82, 0x820682ee, 0x289c2111, 0x4a187684, + 0x73210fdf, 0x82168432, 0x9a992654, 0xfb8b088b, 0x18bfb234, 0x21095354, 0x8d8f00c0, 0x8834b321, 0x8bcc31bf, 0x00ff0e08, 0xf790024a, 0x06811584, + 0x20f7ffff, 0xf8212d83, 0x82dc82e0, 0x82388204, 0x7b082210, 0x26088507, 0x1f0700ff, 0x82ffff3c, 0x24098218, 0x088b5efa, 0x2131829b, 0x2b82c0ff, + 0xb8ded42c, 0xc0faffff, 0xffff6000, 0x0f8280f5, 0x4821d625, 0x8214f708, 0x230d831d, 0x48e12900, 0xb6221d84, 0x2d83ffff, 0x1e2b002e, 0x00ff08b8, + 0x069a190f, 0xe00800ff, 0x00237082, 0x82002007, 0x837b8352, 0x251c8210, 0x9b3dca01, 0x1e848b05, 0xc5207083, 0x09821d84, 0x8ba10523, 0x21a78208, + 0x52822100, 0x615a0024, 0x52820548, 0xffecd124, 0x04830100, 0xcc4c002c, 0xb30200ff, 0x088c8b32, 0x2c82948b, 0x829a9921, 0x9a192136, 0xc548d582, + 0x82c72005, 0x07ab2171, 0x0023b482, 0x8210d808, 0x2707225c, 0x212082f0, 0x0a82f027, 0x08201082, 0x37820685, 0x8466e621, 0x24378216, 0x088b9a19, + 0x22a5827b, 0x85d80000, 0x10d8218e, 0xd7211f82, 0x231f870a, 0x088bf628, 0x06822682, 0xff211685, 0x2c5883f8, 0xf027f7ff, 0xff077b08, 0xb701f0ff, + 0x221e8206, 0x828bef27, 0x883a841e, 0x8211821e, 0x21478225, 0x1b856726, 0xd9080022, 0x9b226c82, 0x37826b06, 0xb81ec722, 0x80213783, 0x27258200, + 0xffa470f8, 0x3433f9ff, 0x8205447a, 0xfeff2da4, 0x00ffea11, 0xff035a00, 0xa410feff, 0xb5210982, 0x2609829b, 0xff086e27, 0x82e12100, 0x9ca53e36, + 0x01ff056a, 0xffd6e309, 0x3433a2ff, 0xfcffff15, 0xffff34b3, 0x05ccccad, 0xcc7e00ff, 0x272182ce, 0xff00c0fc, 0x00405200, 0x18211082, 0x210a8280, + 0x0a83c014, 0xfe3f072a, 0x190600ff, 0x0400ff9a, 0x08280483, 0xff8b66e6, 0x00800900, 0x3a235782, 0x82070080, 0x6603250c, 0xfdffff66, 0xcf440482, + 0x48fb2005, 0xe5220583, 0x538348a1, 0xac83a020, 0x0060fd22, 0x60202182, 0xfc240a83, 0x710800a0, 0xe725cb82, 0xa5060040, 0x23a68207, 0x00ff84eb, + 0xfc20418e, 0x2005746d, 0x822282ca, 0x91419da6, 0x223d867f, 0x83b89ee5, 0x7c94227f, 0x839c858b, 0x820a82a1, 0xff08251d, 0x4861c5ff, 0xff22b982, + 0xe682a0f6, 0x82200421, 0x82f7209c, 0x07002804, 0xffff4841, 0x82b8def9, 0x85182bda, 0xebffff1e, 0xff053433, 0xf6822c00, 0xccfdff24, 0x6a8215cc, + 0x3b42fd82, 0x07002105, 0x82070c41, 0x0513412c, 0xff231183, 0x8266e6f8, 0x19f72864, 0x076b089a, 0x82ab066b, 0x827720e8, 0x64ff3028, 0xff156666, + 0x66e6e8ff, 0x990b00ff, 0x829b059a, 0x8200207c, 0x07544235, 0x33822283, 0xfb088b29, 0xffff0634, 0x824821f7, 0xdef82243, 0x861e84b8, 0x827b204e, + 0xe1e8214a, 0xf4279f82, 0xff054861, 0x827efaff, 0x51fd251d, 0xfcffffec, 0xff2bc382, 0x8b6666fa, 0xffff0885, 0x8266e6e9, 0x82ff205a, 0x0719434b, + 0x08267283, 0x088b00e0, 0x564374f7, 0x1e162219, 0x233682b8, 0xe2fa0500, 0x99244f82, 0x0500ff9a, 0xff2c0482, 0xff0080fa, 0x32b30200, 0x8b94f708, + 0x0b44bd91, 0x21678606, 0x628220f7, 0x4414fb21, 0xfd82192a, 0x8523bd8a, 0x85ffff1e, 0x8e6884bd, 0x432020bd, 0x524405f5, 0x20bd8506, 0x25bdb854, + 0xf770fb0e, 0xcc638ba4, 0xb4891805, 0x0080210b, 0x1809e157, 0x2113af7a, 0x7718b4f7, 0xe4621789, 0x9cfb2716, 0x19a000ff, 0x5682159a, 0xb85ecc2b, + 0x1e1600ff, 0xe9ffffb8, 0x20cc82c0, 0x2afa8321, 0x080040f5, 0x87d4ffff, 0x83f707ae, 0x802b24cc, 0x44ff0700, 0x0a2105b0, 0x832382c0, 0x1600222d, + 0x24948240, 0x48a13300, 0x21638208, 0x3f829e1e, 0xff2a3582, 0x90822400, 0x2300ff7b, 0x4082b85e, 0x2c829b20, 0xc59bff29, 0xffff051e, 0x865c6ffe, + 0xf4fd2904, 0xfffffffe, 0xffff4c37, 0x8b200982, 0xfd222582, 0x8682c9f6, 0x0af7fd27, 0xc70000ff, 0x26258258, 0x00ffe570, 0x82708f01, 0xa6f4261a, + 0x0b00ff66, 0x21408445, 0x1583a470, 0xff274582, 0x00ff9338, 0x82560e02, 0x83058276, 0x1002227d, 0x213b8220, 0x1682aec8, 0x25831020, 0x82aa9021, + 0xa490272a, 0x6b00ff08, 0x048367e6, 0x81826620, 0x9438eb3c, 0xc62500ff, 0xe6ffff6a, 0x00ffcd4c, 0xffcc4c22, 0x9999e7ff, 0x801400ff, 0x06820800, + 0xb85e032e, 0x990a00ff, 0x0c00ff9a, 0x9a8b4821, 0x11205783, 0xf120d583, 0x002c0482, 0xff48610e, 0x4861eeff, 0x064b088b, 0x66210882, 0x20b18266, + 0x203c82f1, 0x821d82ff, 0x2219820a, 0x827c8b08, 0x9e21083e, 0xf3ffffb9, 0xff9948e1, 0xb89efcff, 0xcbffff08, 0xffff4721, 0xff34b3d3, 0x0040c4ff, + 0x4c94ffff, 0x322d82cc, 0x089a99b6, 0x54f72f0e, 0x4b1574f7, 0xcb074b06, 0x8207cb06, 0x1be15a0c, 0x21069a77, 0x205a66a6, 0x5aff2005, 0x9a7723e1, + 0xfb8b2219, 0x21788614, 0x8085074b, 0xcb200783, 0x4b200b84, 0x13838c82, 0xcb200783, 0xcb200b84, 0x0f85a084, 0xcb20ac85, 0x0783b486, 0x8354fb21, + 0x2122874c, 0x458515cb, 0x8b06cb24, 0x3e85154b, 0x0e074b2f, 0x6f01ff2f, 0x158b9a19, 0xdee0feff, 0xb45218b8, 0x00802f09, 0x82eaffff, 0xffff8b90, + 0x08d663e6, 0x008200ff, 0xf6ffff38, 0x00ffce4c, 0xff852b07, 0xccccf8ff, 0xd40800ff, 0xf7088b7b, 0x701806f4, 0xba210ea2, 0x2010838b, 0x21348346, + 0xc6653e0a, 0x99e43210, 0xbc088b9a, 0xfb15b4f7, 0x07bb0634, 0x021000ff, 0x20408290, 0x24158211, 0x610e00ff, 0x21048248, 0x40826666, 0x08271082, + 0x02ffffff, 0x8200ff8e, 0xffff220a, 0x239082f2, 0x66660e00, 0x8205df41, 0xfdef241a, 0x829b0671, 0x0200223f, 0x2222868f, 0x849a99f1, 0xffff253d, + 0x8b0080ed, 0x4c212283, 0x24bf82cc, 0xff34b3f0, 0x821b82ff, 0x83ee200a, 0xf0ff25ca, 0x7b079002, 0x21092842, 0x1e880b97, 0x83666621, 0x215082b4, + 0x6982eeff, 0x4c0f0023, 0x821a84cc, 0x34b321a4, 0xab825082, 0x5b068f23, 0x82b88207, 0xe13a218f, 0xa8245083, 0xf4fffff6, 0xff256d82, 0x0080ebff, + 0x29118208, 0xffcdccfc, 0x37790000, 0x0985ffff, 0x82a8f621, 0x83e62009, 0x05492d57, 0x29ffffe4, 0xff050080, 0x9a192b01, 0x4925f382, 0x00ff1e05, + 0x271083d6, 0x86eb0000, 0x190300ff, 0x0020bf82, 0x0323e783, 0x828b3333, 0x3333210f, 0x00215182, 0x83f48414, 0x990b3a1b, 0x088b7d9a, 0x9e30fb0e, + 0x80af00ff, 0x00ff1500, 0x79b89e28, 0x0400ff05, 0x6f868228, 0x7822051e, 0x0f828a52, 0x8b527824, 0x42828f08, 0x42000422, 0xc1218d82, 0x264c821a, + 0x00ff6dc7, 0x82e28801, 0xc00c26e0, 0x0500ff00, 0x22888220, 0x82200900, 0xa003210a, 0x06210482, 0x220482e0, 0x59b87e07, 0x0023058b, 0x82486109, + 0x33092729, 0x1e00ff33, 0x62820396, 0xd7830120, 0x67e60622, 0x2205e55f, 0x82b30500, 0x82062019, 0x20b58299, 0x20298299, 0x369f8416, 0xff059a19, + 0xb89ecdff, 0xffff8b07, 0xff48e1ed, 0x9a99f5ff, 0x82efffff, 0xefff2d26, 0xffffcccc, 0x0866e6f7, 0xd9c6ffff, 0xe3221482, 0x2b82ce4c, 0xb8dee425, + 0x84f2ffff, 0x222e83e0, 0x826666e4, 0x99e12239, 0x2325829a, 0x070080f1, 0x82068379, 0xf7542347, 0xcf820554, 0x66826920, 0x2baaff2e, 0x5600ff86, + 0xffff66e6, 0x8bad0796, 0x6b282a82, 0xff0613f1, 0x0060f9ff, 0xfa203c82, 0xff23cc82, 0x82b89efa, 0x82f9200a, 0x210682c3, 0xd98260fd, 0x16830020, + 0x01200984, 0xff23f282, 0x8200a0fd, 0x400e2ab4, 0xe3ffff00, 0x820500a0, 0x218b8282, 0x0d8280fb, 0xfd200484, 0xf9220983, 0x3c8248e1, 0xb89ef928, + 0x76ffff08, 0xd283cdcc, 0xcd4cf325, 0x830700ff, 0x82f4201c, 0x0b002104, 0xff210482, 0x2dd282fa, 0x9000ffac, 0x96150080, 0x8b82948b, 0x07670880, + 0x8b803d06, 0x968b9482, 0x94968b08, 0x088b9694, 0xd4fbb0f7, 0xdffeff15, 0xff069a19, 0xd763e6ff, 0xea265a82, 0xffff8f82, 0xb48380ea, 0x6666e623, + 0x06d26808, 0x29070023, 0x6f9519ba, 0x43462008, 0x4620085e, 0x1983fc82, 0x5e431e83, 0x163c4606, 0x70fb0e2a, 0x196900ff, 0x1574f79a, 0xe6216982, + 0x226f8266, 0x82b81ef7, 0xe1f8225d, 0x0b074847, 0xd1836b20, 0x3f05ad48, 0xffff0020, 0xff66c6f9, 0x00e00800, 0xff9b088b, 0x9a19ffff, 0xfaffff05, + 0x8b070080, 0xfbffff5f, 0xd52f3883, 0xffff6666, 0xffb81eec, 0x9a19dcff, 0x8244f708, 0x19ec2656, 0x2300ff9a, 0x201782e6, 0x290482fb, 0x9a992a00, + 0xff08b78b, 0x36820500, 0x00ff9b26, 0x05060000, 0x24127e4b, 0x089af907, 0x237a82ab, 0xc6cc0900, 0x2d10b548, 0xe1e6ffff, 0x00ff0648, 0xff856b1d, + 0x71821200, 0xb3130028, 0x2000ff33, 0xec826666, 0x484f2520, 0x80392105, 0xd120ad82, 0x00210482, 0x2104822e, 0xe249c5ff, 0x26068305, 0x4cd3ffff, + 0x82ffffcc, 0x20ed821b, 0x058e43c6, 0xccccda2b, 0xbd1300ff, 0xdfffff71, 0x27ad8299, 0xff295c1d, 0x9a99edff, 0xa628a682, 0x74fb66e6, 0x1fffff15, + 0x47319241, 0x924105cf, 0x94f7292a, 0xff15e4f7, 0x48e11e00, 0x1924c782, 0x00ffb81e, 0x0a820482, 0x08201082, 0xf9820685, 0x8466e621, 0xffff2216, + 0x05e951e1, 0xb7820683, 0x3483e620, 0x1ee1ff23, 0x832982b8, 0x82a52006, 0x48e1212a, 0xe6224c82, 0xc6828b66, 0x9a198f26, 0xfb15e4fb, 0xff209282, + 0x106e5818, 0x8206b945, 0x1bb9452d, 0xff22c792, 0xa483ffff, 0x00801a26, 0x66ebffff, 0x15209782, 0xe42c0983, 0x088b9a99, 0x00ff04f7, 0x159a99fa, + 0x2208b682, 0xff912d05, 0xb27dfdff, 0x050500ff, 0xfbffffa1, 0x00ffba69, 0x085c0f03, 0x65e4ffff, 0x0f00ff60, 0x8205a4f0, 0xe650261f, 0xc90100ff, + 0x260982fc, 0x00fffe14, 0x82bcd400, 0xe01a2109, 0xff24ba82, 0x8baec7ee, 0xd42b6982, 0xe5ffff7c, 0xffff48a1, 0x835078dd, 0xa6e22216, 0x21168266, + 0xe38261ed, 0x48611922, 0x19226782, 0x53820040, 0x8216ff21, 0x51072310, 0x748285ec, 0xdf45f920, 0x40d92405, 0x82850600, 0x5efa272b, 0xffff87b8, + 0xad82c0fe, 0x8320fa21, 0x3afb272b, 0xe9ffffe2, 0xff7666c6, 0x19f02506, 0xe8ffff9a, 0x2205a34d, 0x820040e9, 0x82ec2031, 0x0f0022cf, 0x277482e1, + 0xff0040fb, 0x703d1600, 0x99216183, 0x83ca8299, 0x80fa2814, 0xffff8f00, 0x8367e6f9, 0x2665838f, 0xc0f7ffff, 0x83858b00, 0x066e526c, 0xce8ced2c, + 0x45f2ffff, 0xdfffff1f, 0xbb827ad4, 0x4282cb82, 0x836bdd21, 0xb5ff2822, 0x1a00ffc3, 0x837ad663, 0x17fd223e, 0x2270824c, 0x82a01afd, 0xa82a21ea, + 0x5f21fc82, 0x21ab827d, 0x2d823a30, 0xb85ee329, 0xffff057b, 0x827e4afc, 0x32132116, 0x21054c41, 0x7682faff, 0x0583ff20, 0x09268119, 0x82fa8e21, + 0x229d831b, 0x82582901, 0x33b33309, 0x6600ff08, 0xffffe17a, 0x059a992c, 0x802f01ff, 0x10820600, 0xd32dd383, 0xff056666, 0x32330100, 0x4c0200ff, + 0x217282cd, 0x098234b3, 0xf3828020, 0x6602002d, 0xfb0e0867, 0xf804f830, 0x4b531534, 0x5b25175f, 0xbb065b07, 0x09184f07, 0x2307404b, 0x8b0020f7, + 0x4f051671, 0x5b2613c0, 0xd0ffff07, 0x398bb81e, 0x3988c020, 0x39824020, 0xc7ffff24, 0x738e47e1, 0x8b48e12e, 0x1ef7ffff, 0x44fb08b8, 0x056bcb07, + 0xcf220c82, 0x4e7db89e, 0x61d12c06, 0xf4ffff48, 0x084a0040, 0x831a01ff, 0x200c83dd, 0x231c85cc, 0x34332f00, 0x2f28a082, 0xcb08cccc, 0x44f705ab, + 0xe120ad84, 0xf8262f82, 0x00ff66e6, 0x43821e07, 0x2605024d, 0x15b4fb24, 0x83cb064b, 0x4a11201f, 0x62480726, 0x230e8205, 0x00ff088b, 0x18190683, + 0x8082096a, 0x4861ee29, 0xf7074b08, 0x4514fb04, 0xef2666ab, 0x15f4f7f3, 0xe278065b, 0xffff2405, 0x820040f5, 0x08067804, 0xff072324, 0xce18eeff, + 0xff210849, 0x0ca77bf1, 0x25134863, 0x66e60000, 0xc8820523, 0x34b3f223, 0x057579ff, 0x27091279, 0x00ff06bb, 0x8bcd4c0d, 0xb3211882, 0x20048333, + 0x230a8234, 0x08cc4c0d, 0x2205a976, 0x8234330d, 0xcd4c217b, 0xcc211982, 0x829082cc, 0xf708236c, 0x9d85cbf4, 0x82cccc21, 0x84f52054, 0x00402121, + 0xf22c0a82, 0xfb0800c0, 0x14fb073c, 0x073cf706, 0x84087c78, 0x82c0203c, 0x83f220c2, 0x20d6843c, 0x09dd78cc, 0xfc223888, 0xa2880724, 0x83cdcc21, + 0x82cc2074, 0x33332399, 0xa299088b, 0xf7073c24, 0x71820614, 0xdb877b85, 0x79004021, 0x3885050f, 0xf4846083, 0x94850483, 0x83f80821, 0x7900206b, + 0x5b18051b, 0xf7250d2d, 0x1554fb2c, 0x84bc84f3, 0x851d84d7, 0x8b3422f9, 0x89bc8508, 0x089341f5, 0x84a4fb21, 0x9fb018bc, 0x93bc8412, 0x07f32683, + 0xab1100ff, 0x22918284, 0x647c540e, 0x11820bdb, 0x13d57f18, 0x00ff0e2b, 0xff852b10, 0x00806e00, 0x08ef8215, 0x1e05d329, 0x900700ff, 0xd9ffffa4, + 0x00ffa470, 0xff3d6a06, 0xd8a3e7ff, 0x0500ff08, 0xffffec11, 0xff9a19ed, 0x713d0f00, 0x83e0ffff, 0x707c23c2, 0x1a828ba4, 0xe5900922, 0x0a2c5d82, + 0x00ff2506, 0xff807800, 0x00400a00, 0xcc370982, 0xffff08e0, 0xff0b9744, 0xd46dbb00, 0xffffff05, 0xffff3333, 0x8232b3f5, 0xd7a32609, 0xe6f5ffff, + 0x2a6f8266, 0x083433f6, 0xa1df01ff, 0x8237f746, 0x2c00377e, 0xffffe0fa, 0xff5c6ff8, 0xce8c2600, 0x95f9ffff, 0x1800ffc2, 0x4882b85e, 0xe04ffb22, + 0x8a2ad882, 0xf2ffff3e, 0x00ff1659, 0xa282b00d, 0x8383ee20, 0x52b80422, 0xf5341e82, 0x00ff54b8, 0xff70bd02, 0x6666d5ff, 0xe80b00ff, 0xc8fffff6, + 0x2205da46, 0x829e6ff6, 0xf9f52268, 0x21788258, 0x78828087, 0x8200c021, 0x20332109, 0xbb21b882, 0x200a8280, 0x05144b44, 0x820ad721, 0xfa5e26b8, + 0x4c0000ff, 0x820982cc, 0xff26083b, 0xcccc0900, 0x2afeff08, 0xffff52f8, 0x1533b3b5, 0x4cec00ff, 0x13ffffcd, 0xf70533b3, 0x2400ff22, 0x00ff9a19, + 0x6e82e63d, 0x32837220, 0xce4c1226, 0xb34600ff, 0xff2ecf82, 0xff46a113, 0x4821ed00, 0xff22fb05, 0x8b83dbff, 0x852bc23a, 0xc28dffff, 0xedffff8e, + 0xffff33b3, 0x086766b8, 0x3ae500ff, 0xa9ffffe1, 0x9f825882, 0xe8dbf622, 0x8621f982, 0x27f482a8, 0xffff1824, 0x8b5879f7, 0xfb22d682, 0x1b82f0e7, + 0xefe7fb31, 0x900100ff, 0xfcffff62, 0x00ffc5e0, 0x82002003, 0x02c0281a, 0x3f00ff8f, 0x82056c1c, 0x67e62115, 0x19241582, 0xfeffff98, 0x0420fc83, + 0x9031bb82, 0x00ff8b08, 0xff6c8708, 0x71dd0600, 0x780700ff, 0x21cd8294, 0x53828f22, 0x18040023, 0x221b8252, 0x82101804, 0x2070212e, 0x1e213882, + 0x214282fa, 0x9082c0df, 0x90024024, 0x1182054b, 0xff7a1426, 0xeefcfbff, 0x99217482, 0x2109829a, 0x848266e6, 0xccccfc26, 0x15bbbb08, 0xf020aaa0, + 0xc420aa88, 0x6b20aa8e, 0x5582aa89, 0x9921aa86, 0x22aa848b, 0x82192409, 0x177921a5, 0xdb21af82, 0x21b982e7, 0xaa85e986, 0xaa841020, 0xaa831120, + 0x4e822120, 0x833b1f21, 0x85be20aa, 0xffff24aa, 0x8371fdbf, 0x142e21ae, 0xff21a482, 0x2178827e, 0xae8b0080, 0x04f75b22, 0x0023af82, 0x831a2409, + 0x8316205b, 0x83e6205b, 0x8bea205b, 0x8310205b, 0x8322205b, 0x833c205b, 0x89bc205b, 0x8372205b, 0x8220205b, 0xe0fc2251, 0x215b8200, 0x5b822090, + 0x37058f41, 0x8b08b4e8, 0xddf6ffff, 0xf8fffff4, 0xffff3288, 0xff0c22f9, 0xce77f7ff, 0x200bb241, 0x213282ae, 0x5282df8f, 0x8206e121, 0x4220225c, + 0x26ae8308, 0x4000ff70, 0x82058f02, 0x7ae92615, 0x350200ff, 0x0cb241c2, 0x30fb0e28, 0x3000ffeb, 0xb58266e6, 0x45eeff21, 0xf2270873, 0x00ffec91, + 0x8285ab11, 0x6806845d, 0x848209d3, 0xe03aef26, 0xcb075b08, 0x22050d47, 0x8586ab11, 0x0d00231c, 0x338a146e, 0x390e0e44, 0x0820c510, 0x54fb079b, + 0xeb077b06, 0x198f01ff, 0x8b211594, 0xa9ffff35, 0x5082ea51, 0x7b149522, 0xbe3cdc83, 0x00ff5138, 0xffecd120, 0xb047c6ff, 0xb33100ff, 0xddffff33, + 0xff089819, 0x9a19da00, 0x3227d182, 0x00ff7c94, 0x826ee622, 0xcccc2c24, 0xb33900ff, 0x00ff8b34, 0x82cccc41, 0x6a00343b, 0xff3586eb, 0x0eae5600, + 0x7e088b21, 0xe632ffff, 0x7d8f156c, 0x09820951, 0xff66e626, 0x9a990400, 0x8721d084, 0x223882ae, 0x84c3350e, 0x220a82b8, 0x831fc510, 0xb0042243, + 0x21288222, 0x288296e3, 0x82bc5f21, 0xfd342109, 0x02210982, 0x317f820e, 0xffae070b, 0xe6fbfaff, 0xbd0700ff, 0xf4ffff71, 0xb582a0ef, 0x8e02f322, + 0xff323582, 0xff7b54ee, 0x3dcaf1ff, 0x91f2ffff, 0xeeffffeb, 0x63825278, 0x3bf2ff23, 0x202282e8, 0x287583f5, 0x86cdcc07, 0x190b00ff, 0x29488299, + 0x2933b32c, 0xf3ffff15, 0x1d83b81e, 0x821f0521, 0xe0cf2450, 0x82fbffff, 0x0b00235f, 0x2182341e, 0x1dfa0322, 0x30207a82, 0x04226a82, 0x0982c856, + 0xf882e120, 0xdea40422, 0x7a20b790, 0x2020b784, 0x2120b785, 0xe4212882, 0x21ad8219, 0x0982be5f, 0x827a3421, 0x0d022109, 0xe720b789, 0x9f20b788, + 0xff24b786, 0x62100000, 0x4c21ac82, 0x26bb82cc, 0xffffcdcc, 0x829a99f2, 0x6666210e, 0x3f226783, 0x3f750180, 0x20a88905, 0x21418220, 0xa888dfcf, + 0xa8843520, 0x6b821c20, 0x82e53021, 0xca56216b, 0xe1210982, 0x21098207, 0xa88adca4, 0x41343321, 0xe4211460, 0x08604118, 0x6041fe20, 0xc00a2108, + 0xee215c82, 0x28668214, 0xffff32b3, 0x8b66e6f4, 0x20da827e, 0x050e7cff, 0x82cecc21, 0x33b321a5, 0x8030a082, 0x0e088b00, 0x15b4f78b, 0x00ffc08b, + 0xb69a9972, 0x113fe918, 0x568b602d, 0xff568b08, 0x66668dff, 0x82ffff60, 0x84918223, 0x22128406, 0x82c08bb6, 0x19ff21bb, 0x2408ed82, 0x1566e670, + 0x4c9dffff, 0xffff8bcc, 0xff7b549c, 0x34b31300, 0x45c7ffff, 0x2900ff1f, 0xff083333, 0x333392ff, 0x83498207, 0x91602067, 0x23498567, 0x07cdcc6d, + 0x4c263482, 0xd6ffffcc, 0x4882cdcc, 0xab824c20, 0x0e83ec20, 0xab849b20, 0x01ffef23, 0x216c82ef, 0x6c846000, 0xecd1d322, 0xdd276c82, 0xffff7a14, + 0x82ae47dc, 0xcfd3220a, 0x82e6835c, 0x00ff2417, 0x82ecd123, 0x0a172416, 0x822b00ff, 0x8508201b, 0x29168506, 0xf6e82300, 0x2c00ff8b, 0x1682142e, + 0x64e60022, 0x4f2a1b82, 0xddffff5c, 0x00ff9c19, 0xcb829924, 0x66e6d222, 0x0327e683, 0x00ff9999, 0x8234b386, 0xd7e122d7, 0x265f820a, 0xff8f42b7, + 0x82d9fbff, 0x80d12521, 0xdaffff01, 0x75296e82, 0x80eeffff, 0xedffff00, 0x200482c0, 0x220483d9, 0x82b89ef1, 0x004021bd, 0x3c2d5b82, 0x00ff4861, + 0x05b81e16, 0xbc0000ff, 0x2104827e, 0x04828245, 0x8245b921, 0x0c202104, 0xb0210482, 0x236682e6, 0x7b540300, 0x02278d82, 0xffffe19a, 0x82701dfd, + 0xd8fc2366, 0x06820894, 0xf2b2fe2c, 0x8effffff, 0xfeffffb2, 0x04826ca7, 0x8208fb21, 0x80ca2104, 0xa12b0582, 0xffff7453, 0x0514eb8f, 0x83f8ffff, + 0x83df2072, 0x40fc21b4, 0xe8208182, 0x8b22b982, 0x4f828b08, 0x82111b21, 0x33fe27ff, 0x2500ff34, 0x66834861, 0xa4f04131, 0x6100ff8b, 0x00fff628, + 0xffbe7f05, 0x82192700, 0x641e27dd, 0xffc7081a, 0x45822f00, 0x23054362, 0x8b9a5966, 0xff282d82, 0xff0040a9, 0x33336d00, 0xff226282, 0xab8252f8, + 0xff281c26, 0x66e6faff, 0x4c260982, 0xf7ffffcd, 0x2582cd4c, 0x666c012e, 0xd800ff64, 0xff158264, 0x1423f9ff, 0xf922b382, 0xc5823c15, 0x82d8ce21, + 0xf828262b, 0x79fbffff, 0x27ae8216, 0xff54381f, 0x2a6d50ff, 0xe2224b82, 0x9082b81e, 0x8284ab21, 0xc0fc270a, 0x0400ff84, 0x25821018, 0xff225b26, + 0xc8f60100, 0x64210982, 0x2356825a, 0xe81bfaff, 0xfa264b82, 0xffff3629, 0x1682cbfc, 0xa430fd22, 0xf1216082, 0x2b4b82aa, 0xff1e05ea, 0x64bbd0ff, + 0x5600ff05, 0xff23b482, 0x8266e692, 0xe132270a, 0x0a00ff48, 0x0a8252b8, 0x0ce20722, 0xa8204c82, 0x0427e582, 0x00ff46d6, 0x82d0e206, 0x290723f5, + 0x068208fc, 0x7869032c, 0xe7feffff, 0x0300ff6c, 0xa7825879, 0x82369e21, 0x08012109, 0xe3275682, 0x00ff0ad7, 0x82008023, 0x33e12740, 0xaf00ff32, + 0x0a823433, 0x1c1a0822, 0x4f214182, 0x26a782de, 0x00ff7c3f, 0x82227009, 0x8a092244, 0x0830823c, 0x24f0ff37, 0xf31000ff, 0xf2ffff34, 0x00ffcc4c, + 0xffc0ee0e, 0xccccecff, 0x8b0e088b, 0xf81554f8, 0x94fc0694, 0x0694fc07, 0x0e0794f8, 0x00ff34f8, 0x1566e6a0, 0xfd1b00ff, 0x21408270, 0xcd82b019, + 0xfabef62d, 0x141500ff, 0xf0ffff7c, 0x820876be, 0xae072940, 0xd11d00ff, 0x0700ffec, 0x20220983, 0x29825c4f, 0xcc4c2022, 0x672fb683, 0xffff9a19, + 0xf748a1b0, 0x76ffff07, 0x828bb8de, 0x0fc4217e, 0xff271f82, 0xff3e8ac3, 0x824ae8ff, 0xe6d22704, 0xd2ffff66, 0x1a828ec2, 0x0a57c925, 0x83c9ffff, + 0xfeff23bf, 0xe5823373, 0x82b08721, 0x52f824f4, 0x82ffffff, 0xfeff23d9, 0x13825c8f, 0x829a9921, 0xb3e62173, 0x19221e82, 0xe982cc4c, 0xc2f51427, + 0x00ffb6b5, 0x2369821e, 0x34333200, 0x82376283, 0x1522cc4c, 0x6611ffff, 0xee00ff66, 0xff059a99, 0x3f0af3ff, 0x82e9ffff, 0xf9ff21ee, 0xe8234483, + 0x828bcecc, 0x0539510f, 0x5278e131, 0xb50b00ff, 0xe2ffffc3, 0x00ff0a97, 0x827b9416, 0x2a5c221a, 0x06514308, 0x6583db20, 0x9ea3ff28, 0xaeffffb8, + 0x4b8214ae, 0x82d2f821, 0xbef92195, 0xfc280f82, 0xfffff45d, 0x8b2a3cf7, 0x35210582, 0x28ef82c2, 0x16f9f7ff, 0x080300ff, 0x2b108231, 0x00fffef4, + 0xffcb2106, 0x7cd4f9ff, 0x22264b82, 0xffffcd0c, 0xb183ccdd, 0x1f250622, 0xd7301582, 0x0800ff0a, 0xffffd703, 0xff7cf4fc, 0x71fd0700, 0x0024b982, + 0x8bbfbf08, 0xb8211682, 0x21458294, 0x408224a6, 0x82e13a21, 0x04362b1b, 0x5100ff08, 0x00ffae07, 0xcd82d95c, 0xf3230022, 0xdb22fd82, 0xfd82c2f5, + 0x97831720, 0xec51e82c, 0xca1e00ff, 0xf4ffff3d, 0x09823273, 0x83c4f521, 0x8804224b, 0x2c4b8232, 0xff48ac04, 0x88440000, 0x830400ff, 0x2c0982d8, + 0xff08f47d, 0xa470f5ff, 0x9c1200ff, 0x83868228, 0x47152209, 0x222982b0, 0x8284eb16, 0xfcff221a, 0x2171826a, 0x2a8266d8, 0x829a1921, 0x82992009, + 0x33022104, 0x08225582, 0x85826666, 0xcecc7c36, 0x194800ff, 0xffff159a, 0x8b9002cb, 0xd5ffff60, 0x568b66e6, 0xcb21fb83, 0x283482e6, 0xff70fd2a, + 0x2a1cd4ff, 0x228183c0, 0x829a1934, 0xe32b2557, 0x2a00ffd6, 0x35220a84, 0x4382d6e3, 0x90020024, 0x1b8200ff, 0x56b6602c, 0xff0e088b, 0xcd4cc800, + 0x5082eaf7, 0x9919f13a, 0xc21900ff, 0xebffff90, 0x00ffcdcc, 0xff0a571a, 0x3333e4ff, 0xa31800ff, 0xff233682, 0x829a59ae, 0xc4352f6d, 0x40c8ffff, + 0xaaffff00, 0xff8b66a6, 0x50549dff, 0xabea2705, 0x0200ff86, 0x3a82e3e5, 0x6d826320, 0x7fea0427, 0x30ecffff, 0x266c82a4, 0xffa8c62d, 0x82a68700, + 0x8265219a, 0x39257682, 0x00ff3433, 0x2154832d, 0xcf83e612, 0x6766b532, 0xe650ffff, 0x00ff1566, 0xff703d01, 0x16390900, 0x2c260982, 0x0c00ff8c, + 0xbc8264db, 0xec910f22, 0x0022db82, 0x7b82193b, 0xec11ef25, 0x836200ff, 0x6ea12509, 0x5500ff14, 0xff297a82, 0x6a7cfaff, 0x5c0000ff, 0x21098244, + 0x09820080, 0x82567d21, 0x66662109, 0xff25fe82, 0x8b0080e1, 0x210d826e, 0xc782b468, 0xff66e626, 0x243bf6ff, 0x5d319182, 0xffff7ad4, 0xff98d9a5, + 0x20c50800, 0xa693ffff, 0x82368267, 0xdeff2396, 0x1e82cdcc, 0x98990f2a, 0x28f7ffff, 0x2700fff6, 0xff2e5082, 0xffccccec, 0x68663600, 0xffff0885, + 0xc6826672, 0x9a992228, 0xff9d8a15, 0x1883fdff, 0xcccc2b28, 0x3200ff75, 0x1d829a19, 0x34b3d622, 0x8e205882, 0xff221682, 0xd582e6c3, 0x1e45de27, + 0x7f62ffff, 0x3a5383ff, 0xfffff6a8, 0xff285ce0, 0x29dc1500, 0xfae3ffff, 0x1a00ffe2, 0xffff33b3, 0x82146ee9, 0x1c1f2a1e, 0x7e00ff29, 0x00ff7c54, + 0x2d728259, 0xcecc3d00, 0x991c00ff, 0x1000ff9a, 0xf118cccc, 0xec2c07c7, 0xff15146e, 0x3eca4a00, 0x19abffff, 0x0e271a82, 0x8b30c2b5, 0x68c5ffff, + 0xf02c0594, 0xffffcc8c, 0xff40f5fe, 0xd8e3f2ff, 0xc5260982, 0xf5ffffa2, 0x3c8234f3, 0xd48c0023, 0x2a0082ff, 0x00ff05e0, 0x8b3e8a1d, 0x822000ff, + 0x04002d8b, 0x00ff3453, 0xffc2f522, 0x3caa0b00, 0x282a2583, 0x0300ffee, 0x00ff2a97, 0xe3826600, 0x00800322, 0x03232982, 0x82089a99, 0xe6742506, + 0xb1ffff66, 0x62258e83, 0xffff4861, 0x230e8294, 0x66a61e00, 0x2608f182, 0xff3333b9, 0xec91f7fe, 0xf0ffff15, 0xffffeb91, 0xfffce9f6, 0x3e8adbff, + 0x74e7ffff, 0xdfffffbc, 0xffffec91, 0x8220c5d3, 0x571a375f, 0xebffff0a, 0x00ff86ab, 0xff862b43, 0x5c0fd5ff, 0xfd5f00ff, 0x1a828b70, 0x7cd42022, + 0x24316482, 0x00ffa230, 0xff600505, 0x7c142700, 0xab0c00ff, 0x2b1a8244, 0xff7a1413, 0x0a971c00, 0x540d00ff, 0x202c1482, 0x00ff00c0, 0xffcc4c06, + 0x48212300, 0xde227e82, 0x73825ccf, 0xffb65e2e, 0x0080e0ff, 0x19fcffff, 0xe3ffff9a, 0x2205fa41, 0x413433b0, 0x3f82051c, 0x8234b321, 0x23a9827a, + 0xcccc0b00, 0x99273582, 0xffff6766, 0x82343397, 0x17f121b4, 0xe6219582, 0x2aaf824a, 0xff3d4af3, 0x4661e1ff, 0x82f8ffff, 0xdbff316e, 0xff082a9c, + 0xae872800, 0xd1e6ffff, 0x2e00ffea, 0xff2bf382, 0xff3433f1, 0x00803200, 0x82d0088b, 0x823e20b0, 0x1b002972, 0xffb9146e, 0xd8632c00, 0xe6275782, + 0xffff7a94, 0x821ee5fa, 0xc4b52bfc, 0x6ffdffff, 0xe9ffffe0, 0xe2827a54, 0x7a99ff2b, 0x0000ffe2, 0xffff4a0c, 0x234882b6, 0x32b32d00, 0x28062556, + 0x08cecc16, 0xf754f80e, 0x839918f4, 0x8284200f, 0x54ee26bd, 0x04fb087c, 0x045d1807, 0xc3ab1816, 0xb8de2108, 0x0be18b18, 0xffffff24, 0x021914ee, + 0xfc740979, 0x540e2205, 0x8516827c, 0x82ee208b, 0x84ff2006, 0x87048216, 0x239d8366, 0x0544fbc0, 0x29266b83, 0xf8fffffc, 0x0482f0c7, 0x8204d621, + 0xb4282164, 0x20051862, 0x221b82b4, 0x8e18e4f8, 0xd0f5216b, 0x094d0319, 0x00205484, 0x205c9b18, 0x12236b82, 0x1964fbaa, 0x230bbd03, 0x33b3f8ff, + 0xcc216f82, 0x216f82cd, 0x6f843333, 0x11820682, 0x8267e621, 0x240a836f, 0xcdcc0800, 0x21db8208, 0xdb8c66e6, 0x82ff8521, 0x20db846f, 0x6c6e187b, + 0x2fdb8b0d, 0x9a99e8fe, 0xc4ffff07, 0x00ffae47, 0x0532b33b, 0x30215782, 0x2b5782a4, 0xffffcecc, 0xff8fc2f5, 0x66e60300, 0xc5210982, 0x2242831f, + 0x8214aeea, 0x51ed27e8, 0xeeffffeb, 0x0a82cccc, 0x3433e922, 0x14ddfc18, 0x46846220, 0x00ff082a, 0xff9a1971, 0x66e68eff, 0x2536d082, 0xffffafc7, + 0xff142eda, 0xcc4c3200, 0x33ebffff, 0x3500ff34, 0x57826666, 0xb3250026, 0x00ff0634, 0x096b9618, 0xf34e0024, 0x10848b34, 0x64f70823, 0x18098207, + 0x24142793, 0x15d4fb94, 0x8e9718ff, 0x0700210a, 0x08b10619, 0x08213282, 0xa58c18cc, 0x00ff2411, 0x82cdcc08, 0x3307221b, 0x21a08233, 0xc18288d6, + 0x7829f722, 0xf720c183, 0x42188d82, 0xcb210fc6, 0x225e9b6b, 0x83ff88d6, 0x20048370, 0x21578278, 0xc88304d6, 0x97180820, 0xff2108e8, 0x795e92f8, + 0x8b210c25, 0xde5edceb, 0x4bab21bd, 0xab20bddc, 0x285d1c41, 0x74f8ef0e, 0xeb15f4f7, 0x0d3d7a06, 0x082c4218, 0x19654a18, 0xf7062b2a, 0xfb6b07d4, + 0x94fb15d4, 0xf7290983, 0xd4fb0694, 0xf744fb07, 0xc547187c, 0xb3f22613, 0xff8b0833, 0x280682ff, 0xb30a00ff, 0xf5ffff34, 0x0770754c, 0x0d00ff22, + 0x09e34e18, 0x33b30a23, 0x1910838b, 0x2218b72b, 0xad155beb, 0x20748330, 0x227a8234, 0x84cc4cf5, 0x97858575, 0x822b208c, 0x8aa5825e, 0xd74f1830, + 0x20bd8510, 0x188585cc, 0x180da14f, 0x82123350, 0x24f08575, 0x8b34b3f2, 0x18bd9108, 0x8d106450, 0x9ebd8e30, 0xc4fb2a8c, 0xeb157cf7, 0x07d4fb06, + 0x7644182b, 0x07542518, 0x2300ff8b, 0x417c6583, 0x39ce8205, 0x9a592300, 0x2f0e088b, 0xba3200ff, 0x8501ffe1, 0xff155278, 0x48210800, 0x9c7200ff, + 0xb99e2c05, 0x450a00ff, 0x1200ff1e, 0x828ba430, 0x547229f1, 0x14fb067b, 0x0664fb07, 0x00373185, 0x05527865, 0x45bd00ff, 0x9affff1f, 0xf715ae87, + 0x00ff0714, 0x82cc4c72, 0x3312211e, 0x1027e083, 0xffff9a99, 0x82e2baf5, 0x32332655, 0xbdefffff, 0x20458270, 0x83798232, 0x8205202e, 0x64f72847, + 0x8b1594fb, 0x83dcffff, 0x82e32013, 0x84ff209c, 0x05447e04, 0xcb98d420, 0xf807742d, 0x74fb0654, 0xf7af0e07, 0x8224f834, 0x1a002840, 0x00ff9082, + 0x82008015, 0x707d2b04, 0x801a00ff, 0xbb088b00, 0xf3823b06, 0x2205ab49, 0x68343307, 0x002605b8, 0x8bcccc08, 0xa282ab08, 0xff210883, 0x24188300, + 0xf6280700, 0x25a3828b, 0xdb080ad7, 0x1a82bb07, 0x4e853e83, 0x23067a62, 0x08707de5, 0xa982f982, 0x6382e520, 0x88eaff21, 0x660e8204, 0x6a7d06e3, + 0x5f878309, 0x08270513, 0x4b0714f7, 0x851584fb, 0x82828287, 0x8233206e, 0xcccc2187, 0xcc216d82, 0x458787cd, 0x72180790, 0x87910af8, 0xff21d182, + 0xa06482ff, 0x717d2187, 0x8d06d35f, 0x82918587, 0x187d20d5, 0x27098aad, 0xbb088b8f, 0x8bd4f706, 0x3420a08c, 0x2841a088, 0xc4481812, 0x84a0ba08, + 0x80ea22c9, 0x7e8b8200, 0xf7210830, 0x68491814, 0x06c54107, 0xc5411e83, 0xf80e2606, 0x15f4f764, 0x05c6543b, 0x15690219, 0x17f34918, 0x3b075b22, + 0xfb211a97, 0x135318b4, 0x34f82117, 0x410c0242, 0x33830b46, 0x140e4a18, 0xbbb4fb25, 0x6334f715, 0xbb260593, 0xfb54f707, 0x2c49159e, 0x04d62108, + 0x26072c49, 0x088bfc29, 0x83550655, 0x29f72278, 0x201586fc, 0x241f84f8, 0x088b6210, 0x22ab8257, 0x823d2af7, 0xd5f82238, 0x0c4949c3, 0x19350029, + 0xffff079a, 0x839a19c9, 0xa44d1822, 0x82bf2013, 0x08002354, 0x924787d6, 0x47792008, 0x3b820892, 0x3622d082, 0x228566e6, 0x22828820, 0x473d2a21, + 0xd52407b5, 0xbf088bc3, 0xb7471e82, 0x43062205, 0x0b164896, 0xff075526, 0xcccc3700, 0x07201e88, 0x8720b485, 0x2108da84, 0x07570879, 0xff30fb0e, + 0x9a19cb00, 0xa2bb01ff, 0xffff1590, 0xffb0d2f9, 0xead10500, 0x1df6ffff, 0x0082fff4, 0x1382c020, 0xff7bd43b, 0x842efaff, 0x95ffff08, 0xffff65a6, + 0xff42dd9b, 0xe17ab5ff, 0x667effff, 0x23498266, 0x089a19b2, 0x82230682, 0x82da9a19, 0x66e62517, 0x088b05f7, 0xda2b0382, 0x0c4a00ff, 0x00ff8bcc, + 0x8234f37d, 0x4e002c1f, 0xff409a19, 0x32b38100, 0x8296ffff, 0x63002370, 0x5182c4d5, 0x66e6f427, 0x5d54feff, 0x227b8270, 0x820080c7, 0x80d82746, + 0x2500ff00, 0x388290c2, 0xe0fa3522, 0x0c3c3883, 0x00ff5278, 0xfffe3404, 0x9ad92a00, 0xa94f00ff, 0x5700ffba, 0xff0814ae, 0x62500600, 0xf3260482, + 0x0b00fff8, 0x3082d1a2, 0x5c4f0622, 0x0c21ae82, 0x271a8208, 0xff85ab4f, 0x2a5ca8ff, 0x33263982, 0xd5ffff34, 0x5b829a19, 0x9050f320, 0x19ca2405, + 0x83ffff98, 0xdaff2167, 0x77831b83, 0xaf0e0839, 0x4c2b02ff, 0x9300ffcc, 0xfb1566e6, 0xbb00ff17, 0xff05ce4c, 0x8299e9ff, 0xcc1f2a71, 0xdcffffcc, + 0x679c0080, 0x22b1828b, 0x82b85ee9, 0x21e9224a, 0x236a8248, 0x7d770040, 0xec2f1282, 0xffffcd4c, 0x7d0040f2, 0xf8ffff78, 0x82763333, 0x83fd2012, + 0x403b25e2, 0xceffff00, 0x2f204283, 0xc3220983, 0x4083ffff, 0x831ec221, 0xc7ce2740, 0xcdffffae, 0x4b8284eb, 0xe2fac222, 0xff213182, 0x235182ff, + 0x059a191f, 0x1e241183, 0x3200ffb8, 0xff280482, 0xff48e1cd, 0x48e13d00, 0x06843882, 0x00231685, 0x82482132, 0xde3d22ef, 0x243883b8, 0x00ff521a, + 0x82388295, 0x991927eb, 0x66f7ffff, 0x05828f66, 0xff008024, 0x04820500, 0x19f8ff27, 0x00ff089a, 0x26a38383, 0x059a9944, 0x821600ff, 0xe0ff21e7, + 0x00250482, 0x7a008023, 0x225a83af, 0x8200c016, 0x2605824f, 0xc00600ff, 0x82999f00, 0xb3332a30, 0x2400ff34, 0x00ff6626, 0x0845820c, 0x4c470021, + 0xdbffffce, 0x00ffcccc, 0x0832b333, 0xcc73feff, 0x2c00ffce, 0xff159a19, 0xd7e3a0ff, 0x4304f706, 0x561817ff, 0xa5640b32, 0x80e53506, 0x04fb0800, + 0xffffff07, 0x158b291c, 0xb3c300ff, 0xd3ffff32, 0xbe204b84, 0x5d2d6b83, 0xff0548a1, 0x0040f8ff, 0x00ff8896, 0x2211830d, 0x82006002, 0x48212109, + 0x0a859782, 0x0f824020, 0x14830720, 0xb89e0b27, 0x0700ff96, 0x211a83a1, 0x93826c08, 0x3c0a0623, 0x06026795, 0xcc4c0a22, 0x1021dc83, 0x26dc8380, + 0x8348610f, 0x820900ff, 0xf2ff214d, 0xff227f82, 0x0a834100, 0x0040a22f, 0xadffff05, 0xffff1e85, 0x059a59c6, 0xef6b180e, 0x34b321fa, 0x093e8418, + 0x36085f72, 0xff66e65a, 0x343339ff, 0x04fb3315, 0xfbffff05, 0xfffff8f3, 0x8210d8fa, 0xe9063104, 0xb7fcffff, 0xf9ffffd0, 0xffff717d, 0x084060ff, + 0x22069377, 0x5e12c300, 0xff220610, 0x09849a19, 0x1a828b20, 0x084cfa23, 0x2635828b, 0x00fff873, 0x82f00702, 0x48a12949, 0xc00300ff, 0xbb530800, + 0xf5315782, 0x00ffa4f0, 0xff00a008, 0x0ad7feff, 0x270f00ff, 0x260e83ae, 0x0a00ff42, 0x82085c0f, 0xe89b210a, 0x19820a84, 0xff372926, 0xf6280100, + 0x11260e82, 0xf7ffffec, 0x1e82be5f, 0xe1fa2432, 0x4fe0ffff, 0x00ff055c, 0xff1f8548, 0xae475c00, 0x08220a82, 0x25822130, 0x58827020, 0xab1c0f22, + 0xc7203482, 0x0a275382, 0xffff6866, 0x828dd7f7, 0x790a2234, 0x210a8256, 0x198240d5, 0xffcecc26, 0x67e6f0ff, 0xcc270e82, 0xf5ffffcc, 0x42089a99, + 0x8423af07, 0x6115dcfb, 0xb8600bfb, 0x05bf600a, 0x1183ff20, 0xd1180486, 0xff241004, 0x8b0040f5, 0x08203e84, 0xff240685, 0xcd4cf5ff, 0x26064562, + 0x8b33b3f2, 0xbceb8b08, 0x8f5a185e, 0x235e860f, 0xffff3433, 0xeb235e84, 0x5c157cf7, 0xff2505d2, 0x7b540e00, 0x0ade4fff, 0x83052851, 0x84852011, + 0xffff2116, 0x32b76e18, 0xfb04f726, 0x14fb15d4, 0x0f8c5518, 0x644f3420, 0x20f48205, 0x136b4f00, 0x3082f720, 0x15e09019, 0x6e4f9482, 0x0f0f4f06, + 0xcc2164b6, 0x4a8a82cc, 0x0a8305e3, 0x5d82ff20, 0x8c0ad34f, 0xaf0e2e64, 0x19cf01ff, 0x1554f79a, 0xc00800ff, 0x26378200, 0xff9a5906, 0x83400700, + 0x8210820a, 0x20178337, 0x052c71ff, 0xff291682, 0x6666f6ff, 0xffff088b, 0x222283f7, 0x18a6f9ff, 0x830caeb3, 0x004021ca, 0x2205474b, 0x83c0f8ff, + 0x82e62009, 0x44fb222d, 0x215f82db, 0x54838030, 0x82992621, 0x8427205f, 0x2010820a, 0x82718208, 0xffff2406, 0x55cc4cda, 0xce220643, 0x5f839a99, + 0x16850683, 0x0d21da18, 0x8280cf21, 0x473f8255, 0x00210574, 0x232d852f, 0x3b66e630, 0xab83c29f, 0xbb85d983, 0xa683c288, 0xb3f8ff23, 0x21bb8333, + 0x9082cd4c, 0x4cf7ff24, 0x2885ffcd, 0x17411682, 0x272d8205, 0xfff6e8fb, 0x66e688ff, 0x00216682, 0x368382a1, 0xff827500, 0xb9fd2800, 0xcd1c00ff, + 0x3a00ff0e, 0x00ffe27a, 0x823cca14, 0xfdff2a29, 0x95ffff70, 0xff05ce0c, 0x05596b00, 0xe6ffff27, 0xcc6a00ff, 0x221082cc, 0x51ec513a, 0x293c06eb, + 0xffffa430, 0xff5c4fe3, 0x0a970000, 0x94ffffff, 0x00ff087a, 0xff806609, 0x9002faff, 0xb3260982, 0xfdffff32, 0x09829a19, 0x8b9c9922, 0x0e291a82, + 0xff8be0fa, 0x00c00e00, 0x26128292, 0x00ff4861, 0x820a170d, 0x680f3716, 0x1500fff4, 0xff860a97, 0x52f81d00, 0x6eeaffff, 0x0f00ff18, 0x8782f668, + 0x840bfe2c, 0x640100ff, 0xecffff18, 0x2f82e4da, 0xff62702b, 0x1c45e1ff, 0x051000ff, 0x2f1e8220, 0xffe07af7, 0xd6e3f2ff, 0x33f1ffff, 0xf7ffff34, + 0xee200483, 0x2305dc41, 0x8b00c0e5, 0x2621a682, 0x835a8266, 0x1a00240a, 0x82080040, 0x8c03217d, 0x00270482, 0x00fffe76, 0x82697103, 0x90c021b8, + 0x56210982, 0x264c8287, 0xff0c62d9, 0x82780c00, 0xccd32280, 0x24a082cc, 0xffff3333, 0x059b41d1, 0x48a1c422, 0xc92c4c82, 0xffff1e45, 0x5d71fdf0, + 0x57eeffff, 0xff22b882, 0x2282b3ff, 0xeb11e622, 0x6621b282, 0x22048266, 0x82719a99, 0xf5ff23e6, 0x2d821e05, 0x85ebf523, 0x2692828f, 0x00ff29dc, + 0x82cc4c06, 0xe3ed2a5f, 0xf5ffffd7, 0xffffcc8c, 0x281482f4, 0xe23af8ff, 0x8cfeffff, 0x210482cd, 0x1e82c2f5, 0xa470ea22, 0x972a5d82, 0xffff860a, + 0xffae07e2, 0x52840f00, 0x08f66822, 0x63210a82, 0x215d82d7, 0x1f41166e, 0x19fb2206, 0x20d4829a, 0x2058829c, 0x2658830f, 0xa4300301, 0x181f00ff, + 0x230af75f, 0xff9ad909, 0x2113c344, 0x16840040, 0xf3ffff24, 0xa88366a6, 0x00c0f229, 0xf6ffff8b, 0x45ff6626, 0xb320131f, 0x2106e966, 0x51410c00, + 0xe6a02805, 0xff15eb66, 0x82400d00, 0x96002034, 0x33f62262, 0x0b264533, 0x9cffff21, 0xe6092262, 0x82798467, 0x33332154, 0x012c9082, 0xfb98193f, + 0xfdff156c, 0x0668e6e0, 0x20169f43, 0x220082ff, 0x43057b97, 0xd38308a6, 0x2105a643, 0x42829ad9, 0x191f0224, 0x08440698, 0x44982009, 0xff250b08, + 0xd0e60000, 0x213a829b, 0xdb820800, 0x99f9ff23, 0x261d829c, 0xffffcc4c, 0x506466f6, 0x002d0536, 0xffff8a1e, 0x1566e6d1, 0xe0feffff, 0x21188200, + 0x22820080, 0xffdf6f2b, 0x48a1f7ff, 0xa00900ff, 0x236282c5, 0x5c0f2000, 0xef228482, 0x678205be, 0x8b002022, 0x15272182, 0x0500ffc3, 0x828c40d5, + 0x3aff220a, 0x24678208, 0x00ff07c0, 0x31418204, 0x711e0100, 0x4b0600ff, 0x0100ff86, 0x089200a0, 0x9c82ccf7, 0xff230982, 0x8220f9ff, 0x4701225a, + 0x2109826c, 0x3182a490, 0x6e82a020, 0x4821fb22, 0x01203c82, 0xff231982, 0x8266e6f8, 0x0ab72137, 0x28211e82, 0x206782f6, 0x227e8221, 0x82b81e00, + 0x7520221e, 0x212e82c2, 0x7d820010, 0x84a00921, 0xb87e217d, 0x5f212082, 0x20b382be, 0x270982de, 0x08fa7e09, 0x60fbffff, 0x25205e82, 0xff210f82, + 0x268683ea, 0xffe23a5a, 0x82a6a2ff, 0x994f2253, 0x201e829a, 0x21d882ee, 0xd382f3ff, 0x85ecff25, 0x50ff7f1e, 0xf4210500, 0x217e83e1, 0x89834006, + 0x05213e83, 0x22e7824f, 0x825238fb, 0x212e83db, 0x1e8241fb, 0x7280ff23, 0x20c2829f, 0x22248215, 0x821e1200, 0xc719316e, 0x1100ffae, 0x00ff9082, + 0xffb99e1f, 0x00c00f00, 0xac25a382, 0x00ff9a19, 0x28348255, 0x98991f00, 0x4c8500ff, 0x204382ce, 0x220482cc, 0x8666e62f, 0x05794ae1, 0xf893f822, + 0x6127bb82, 0xf6ffff48, 0x828b8260, 0xabdf2298, 0x26dd8286, 0xff057814, 0x82e0f7ff, 0xf9ff28dd, 0xfffff648, 0x82022bfa, 0x82e120dd, 0x00f82226, + 0x26258284, 0xfffa3fff, 0x8220fbff, 0xe1fe27a8, 0xf9ffff90, 0x1e827ab4, 0x1a838020, 0x78c7fe24, 0x0c84060e, 0x0700ff24, 0x3f494200, 0x30062906, + 0xffffffa4, 0x08900040, 0xe1211082, 0x211a8247, 0x36823cff, 0x821f4521, 0xdeef2196, 0x5a836a82, 0x82e0ff21, 0xdfff23ba, 0x2a8270bd, 0x8202de21, + 0x60f62180, 0xf8218083, 0x26808288, 0xff60a5f7, 0x82210100, 0x81f62280, 0x20c18206, 0x207b8305, 0x320f82d5, 0x3e2a1a00, 0x1191ffff, 0x8000ffea, + 0xffff289c, 0x8234b3ab, 0x827f2263, 0x260a8290, 0xffffa8c8, 0x82ebb1e5, 0x98192b1e, 0xdffaffff, 0xd5ffffd2, 0x3d829a19, 0xdcc7df35, 0x661201ff, + 0xffff1568, 0xff67e6e6, 0xcdcc0d00, 0x82eaffff, 0x0e002d04, 0xffff9a99, 0xff9919ee, 0xcc4c0f00, 0x80232982, 0x82060180, 0x32332610, 0xb3f0ffff, + 0x83248234, 0x83f1201f, 0xe6e6270e, 0xf2ffff66, 0x24826766, 0x3433832b, 0xb37b00ff, 0xffff1533, 0x219783fa, 0xa782a1f5, 0x76fef821, 0xff21069a, + 0x25dc83f7, 0x081e05f6, 0x4b8271fb, 0x00c0f72c, 0xde0a00ff, 0xf8ffffba, 0x098233f3, 0x828ec221, 0x83402035, 0xb85e2813, 0x0701ff08, 0x70ffcc0c, + 0xfe2105a5, 0x286182f9, 0x66e6c0fe, 0x0500ff15, 0x672085e0, 0x0a220661, 0x924290c2, 0xde0a2106, 0x00243482, 0x066666db, 0x602b1082, 0xf5ffff00, + 0x00ff4821, 0x82e21a07, 0x703d2109, 0x6d823882, 0x8f82ff20, 0xfeff082b, 0x060080fa, 0x01ffaf0e, 0x22ad8326, 0x823433aa, 0x19113056, 0x00ff869a, + 0xff1e8511, 0xb89ef7ff, 0x830e00ff, 0xc2f422a9, 0x21d38290, 0x718280a1, 0x00c03523, 0x21578505, 0x81830200, 0x82810421, 0x0109215c, 0xfd21dd82, + 0x202e821e, 0x2eb18308, 0x9899c3ff, 0x2bb500ff, 0xffff0584, 0x828440fd, 0x84802b2e, 0xdef6ffff, 0x0400ff34, 0x58827c7f, 0xff20ab82, 0x082a2e82, + 0xdec2ffff, 0xebffffb8, 0x538248a1, 0x3f822120, 0x9e9cff23, 0x203482b8, 0x22fc82c3, 0x83deebff, 0x82de200a, 0x6300227f, 0x23208261, 0x6766c2ff, + 0x80202b82, 0xff237f82, 0x8383a0f7, 0x22dc825a, 0x83c580fb, 0x227a825a, 0x843bdf02, 0x2ba9825a, 0xff7eff34, 0x347360ff, 0x1801ff05, 0xff2cda82, + 0x1566e6df, 0x67faffff, 0x1000fff0, 0xed2cfd83, 0x00ff8cec, 0xfff62809, 0xa430efff, 0x51211882, 0x208a82ec, 0x23de8235, 0x707dbcff, 0xee2d7f82, + 0x00ffaec7, 0xff900216, 0x66a6e5ff, 0x058975ff, 0x8207e221, 0x8f002213, 0x2729825c, 0xffe9d1a3, 0xc2751401, 0xf7372982, 0x00ff3333, 0xff862b1a, + 0x9a99e7ff, 0x941100ff, 0xe4ffff7a, 0x828b6666, 0x19b72225, 0xfa621899, 0xf1ff2a0c, 0xff8b86ab, 0x7a54eeff, 0x20068408, 0x09474a7c, 0x2d082a67, + 0x06a4f048, 0x385c00ff, 0xebfeff52, 0x5f82cc4c, 0x3d8ae922, 0x99833282, 0xcd4cf122, 0xe6215a82, 0x223b8268, 0x83cc4ce1, 0xfaca2c42, 0x2a00ffe2, + 0xffffe1fa, 0x181e05d5, 0x2107a790, 0x7d823400, 0x70211682, 0x840482a4, 0x082583b2, 0x862b3427, 0xca00ff08, 0x00ffcc4c, 0x05a47043, 0xc71000ff, + 0x0500ffb0, 0x00ff5c8f, 0xff303308, 0x32331200, 0x4cfbffff, 0x2d1882d0, 0xff0834b3, 0x9899c1fe, 0xe675ffff, 0x936d1566, 0x0e00240b, 0x838b7a54, + 0x188620aa, 0x22095092, 0x67ff7b54, 0xff2316eb, 0x829a99f2, 0x85ee20ab, 0x7a8218ab, 0xef0e2813, 0x14f784f7, 0x82d4f715, 0x661a21f2, 0x0021d882, + 0x82768215, 0x27378204, 0x66661a00, 0x0754f708, 0x09826f82, 0xeaffff25, 0x83ff6866, 0xffff3519, 0x8b9899e5, 0x0604fb08, 0x5b0714fb, 0x6b5b05ab, + 0x0714f705, 0x18830e82, 0x28823782, 0x2d836620, 0x7a826620, 0x9a99e523, 0x05625808, 0x3d860982, 0x6666ea23, 0x285b83ff, 0x04f8088b, 0x74fc154b, + 0x069b7806, 0xff34333d, 0x3333e3ff, 0xcc1c00ff, 0xdcffffcc, 0x088bcdcc, 0x19dfffff, 0xffff0699, 0x82cd4cef, 0x99f1224c, 0x0b39779a, 0xee201182, + 0x0e204a83, 0xff200482, 0x00231b83, 0x8233b310, 0x10002333, 0xce8266e6, 0x0ad70822, 0x0723b982, 0x18fff628, 0x240ae9ad, 0xe6b0feff, 0x20d18266, + 0x203986ff, 0x24508467, 0x991100ff, 0x3239839a, 0xff85eb42, 0x3a000000, 0xfeffff05, 0xffff152e, 0x826019fa, 0x82e62009, 0x82fa20ce, 0x600f8220, + 0xc21805e6, 0x05222d74, 0x834618a4, 0x54052206, 0x2c09823a, 0x00ff8736, 0x08ae0705, 0xe6c500ff, 0x22dc8265, 0x828836fe, 0x16f92159, 0xdb211a82, + 0x210982e6, 0xd982c2aa, 0x285cfa24, 0x9c82ff08, 0x18ffee21, 0x2117e2c2, 0xde829082, 0x82070a57, 0x9c19230a, 0x0682082a, 0xe1216d85, 0x85638248, + 0x8788206d, 0x8242206d, 0x21528214, 0xee8205c6, 0x82f09d21, 0xa0e626e7, 0x660e00ff, 0x20048368, 0x22398266, 0x83008012, 0xb3102240, 0x21778234, + 0x16849899, 0xeeffff3e, 0x088b6866, 0xf730fb0e, 0x1554f894, 0xf70714fb, 0x14fb0614, 0x6b0514f7, 0x8b1514fb, 0xfb220782, 0xa2820644, 0x47ebc718, + 0x07c4f727, 0xe680ffff, 0x23538266, 0x8b6766ed, 0x18056668, 0x2c0ac9af, 0x52ffffcb, 0xff15cc4c, 0x146edbff, 0x271e8207, 0xffba5ef8, 0x66e6f9ff, + 0xf8200486, 0x2005f643, 0x29c282cd, 0x66e60000, 0xcdffff05, 0x2783c2b5, 0x727df722, 0x6722278d, 0x4482088b, 0x68836620, 0x6884f820, 0x4482f920, + 0x1906002f, 0x00ff8b9a, 0x089a9907, 0x333300ff, 0x228b8232, 0x4533b3cd, 0xff2306f8, 0x826666f8, 0x22279071, 0x82989924, 0x20348361, 0x863f83ff, + 0x82438204, 0x32002561, 0xff06cd4c, 0x22850583, 0x228d9920, 0x22839920, 0xeb912422, 0x07222282, 0x798248a1, 0xa6847f82, 0x95826782, 0x7e82a182, + 0x3f820720, 0x833e4a21, 0x289c2122, 0x6625228f, 0xf72f0e08, 0x1c9841d4, 0xf9777020, 0x90822108, 0xe5270a82, 0xfb08707d, 0x565b0744, 0xff200c5f, + 0x096b7d18, 0xb5186b20, 0xf72117de, 0x22828214, 0x82df0f06, 0x05200882, 0xffff2b87, 0xffe08ffc, 0x52b80200, 0x98faffff, 0x00ff0810, 0xffa4b011, + 0xdca4dcff, 0x3100ff05, 0x2f460a82, 0x05002805, 0x00ff2170, 0x825ccf0a, 0x83c0211f, 0x6e263a83, 0xf5ffff14, 0x3082a430, 0x0a971b27, 0xd1c8ffff, + 0x223082ec, 0x829a1946, 0xc342185c, 0x75421809, 0x23b2820a, 0xfff027f7, 0xcc20a182, 0xd8260482, 0xf7ffff10, 0x19743433, 0xf0f92205, 0x361d8220, + 0xffd678fa, 0x20700300, 0x47fdffff, 0x0500ffae, 0xff08f067, 0x824feeff, 0x5b232671, 0xffff0524, 0x460a82ce, 0xfd2206d2, 0xad823e4a, 0x4e7a9421, + 0xff2305f3, 0x419a99fc, 0x3082056c, 0x66e6f922, 0x82214b83, 0x274b9190, 0xfff668e4, 0xf0273700, 0xb9254b82, 0xfb0666e6, 0x094f5824, 0x4a717d21, + 0x00250522, 0x8b90821a, 0xc1ca1808, 0x0cd54219, 0xf1206883, 0x0dd5791a, 0xcbaf0e2b, 0xab1534f8, 0x0754fc06, 0x9aae186b, 0x1c00210c, 0x0f5b7518, + 0xff0a5723, 0x05d85b00, 0x9682a820, 0x9a592329, 0x8bcb088b, 0x83d4f715, 0xd4fb293b, 0x0754f806, 0x158efbbb, 0xf722cb82, 0x23583e2a, 0xf8ff2305, + 0x2358c2d5, 0x0897580c, 0x2a070023, 0x059c583d, 0x58080021, 0xcf180d1f, 0xc1240e7c, 0x3600ff07, 0x5f055445, 0x3c8208f6, 0x828b3e21, 0xc2d52257, + 0x06935808, 0x4b864620, 0xba290722, 0x2305ac60, 0xc1065508, 0x19058b58, 0x59116c60, 0xc9180d03, 0x55220a42, 0x9b425507, 0x46d6210e, 0x292ace83, + 0x075708ba, 0x8ef7e4f7, 0xeb836b15, 0xff06ab26, 0x98592300, 0x1c238182, 0x41ff68a6, 0xff231427, 0x84cc4ce3, 0xffff2519, 0x8b34b3dc, 0x629a4718, + 0xfb04f724, 0x1a5315fc, 0x08564e08, 0x00c0f222, 0x2009564e, 0x201682f5, 0x09485e00, 0xfb07db26, 0x073b0614, 0xb3203483, 0x2106365f, 0xb782f5ff, + 0x11470519, 0x2a62348a, 0x330d2605, 0x0a00ff34, 0x064075cc, 0x330d0023, 0x84658233, 0xc86d1806, 0x28578309, 0x3b08cccc, 0x0614f707, 0x826582db, + 0x2034841e, 0x057575cc, 0x34850e83, 0x858b3421, 0x0a1f4f11, 0x0764fb2a, 0x94f7af0e, 0xcb15d4f7, 0x0c107d18, 0x540e0022, 0x07d49a18, 0x2105eb76, + 0x496486ab, 0x0af46305, 0xff064b24, 0xb447eeff, 0x33b32105, 0x89821d84, 0x7a54ee24, 0x84824b08, 0x88181982, 0xa426121c, 0x24fb15cb, 0x5d435b06, + 0x0f7c5d07, 0xe05b2b20, 0x0aac5b0c, 0x8207bb21, 0x16824636, 0x0b368318, 0x240aac43, 0xf8088b8f, 0x18d38274, 0x1809fcca, 0x210a60c1, 0xcd18f4f7, + 0xfb231705, 0x1834fb84, 0x250a9663, 0xe3ffff66, 0xd7820a57, 0x4895cb18, 0x74fbeb25, 0x4254fb15, 0xea630cfe, 0x801a210d, 0x20054d5d, 0x053d5dff, + 0x8b230e82, 0x8c14f708, 0x0ac95ec9, 0x2d167e54, 0xf774f80e, 0x84fb15c4, 0x052b2b07, 0x564184fb, 0x5df72017, 0xa95d0803, 0x05e7440f, 0x48008021, + 0xac59067e, 0xfb2b230a, 0x1582150c, 0x66660425, 0x82fcffff, 0x03002e04, 0xffff9a99, 0x8b9a99fb, 0xc3065308, 0x201a9607, 0x8382825b, 0x83338523, + 0x82b88238, 0x53082310, 0x1a975307, 0x4c825b20, 0xff205883, 0x6c846285, 0x8b247682, 0x5306c308, 0xa0211a84, 0x821a8200, 0xfcff2204, 0x22098260, + 0x77006004, 0x088305ec, 0x00221885, 0xc183a003, 0x08261082, 0x06c307c3, 0x3e8300ff, 0x53834e85, 0x0828ab85, 0x14fc07bb, 0x84f7152b, 0x00285382, + 0xff842b42, 0x7bd43500, 0x7c210483, 0x240e82ff, 0xf7088b85, 0x62398284, 0x3d4309df, 0x0806440a, 0x51cc4c21, 0x342308fa, 0x82fb088b, 0xd8ff2330, + 0x1e82cd4c, 0x33b3df27, 0xb3dfffff, 0x220a8234, 0x82cc4cd8, 0x09054419, 0x78004021, 0xff2005a5, 0x241b3a44, 0x04f9ef0e, 0x081a55cb, 0x33820720, + 0x200add55, 0x554c82ab, 0x055205df, 0x271d8205, 0x0040f7ff, 0xf4fc088b, 0x55084252, 0x8083061f, 0x8082f720, 0x830afa47, 0xccf8222d, 0x053052cc, + 0xb4180820, 0x3f8208af, 0xa7ffff21, 0x82f82035, 0x06795668, 0x5b2b9ba7, 0xbb07cb06, 0x4be4fb06, 0x8234fb15, 0x34f7270a, 0xf7074b06, 0x0d8a8b74, + 0xf7af0e31, 0x1534f804, 0x1ec2ffff, 0xffff8bb8, 0x8448e1cd, 0x260a8204, 0x081e05c3, 0x4b20ffff, 0x1d8205dd, 0x185dff20, 0xc7ce2205, 0x14185dae, + 0x002c3e83, 0x08e2fa3c, 0x19df00ff, 0xff8b079a, 0x4b820c83, 0x8666e621, 0x19c22938, 0xbb088b9a, 0x2b1574fb, 0x2835b45c, 0xcccc8b00, 0xcc1d00ff, + 0x2bac82cd, 0xff0080fc, 0x00800300, 0xffffff85, 0xff280a82, 0xffb81efd, 0x0020fcff, 0xd22bb082, 0xffff00c0, 0xffff7fc1, 0x82de0400, 0x66a82c14, + 0x3800ff68, 0xffff9042, 0x8234b3c7, 0x6138219b, 0xc720e082, 0x00272382, 0x86b89e57, 0x823e00ff, 0x2d00263e, 0x8f08b85e, 0x05fb4fff, 0xc03f0022, + 0x23058750, 0x4080fcff, 0x54826484, 0x82402d21, 0xe7d2296f, 0x00ff05ad, 0x9e34b3e5, 0x42848182, 0x823f3821, 0x59a8227f, 0x206b829a, 0x205682e1, + 0x2a4b82c1, 0x70bdd2ff, 0xffff8708, 0x820120fd, 0x82a0201b, 0x82a783a1, 0xb87e219c, 0xd2277d82, 0xffff66e6, 0x82cd4c2d, 0x82bd8247, 0x50318215, + 0x002105f4, 0x21618260, 0x0482e002, 0x82e00321, 0x2d0022c6, 0x2aec826c, 0xff5c8f3e, 0x9c19fbff, 0x825700ff, 0xc7ff2328, 0xcb829899, 0x2605047e, + 0x1594f7ab, 0x680604f7, 0xcc200d96, 0x0755a518, 0xffff8b26, 0xff3333f7, 0x69079668, 0xfb2407ff, 0x074b0604, 0xcc203591, 0x34202e84, 0xb817cc68, + 0x076b2135, 0xdc215882, 0x21c882cc, 0x8282cc1c, 0x3433e32b, 0x332300ff, 0xf7088b33, 0x26b88254, 0x8b343323, 0x851c00ff, 0x8282821e, 0x0834261a, + 0xfb07d4f7, 0x26a483d4, 0x1554f7dc, 0x5b06e4fb, 0x0b440b5b, 0x7b5b200a, 0xf72017c2, 0x1e673282, 0x6075180c, 0x7cbb2008, 0x91820ae5, 0x00c00a22, + 0xb3295b82, 0x0e088b34, 0x8bab30fb, 0x25a9b615, 0xcb07d4fb, 0x3d8224f7, 0x2114c85a, 0x758406bb, 0xfd820820, 0x33070024, 0xac19ff33, 0x5b2123c7, + 0x33ba1807, 0xf8ff210d, 0x2008985a, 0x054a4c6b, 0xffff7425, 0x820ecdf8, 0x8ccc2b04, 0x32f7ffff, 0x5b088bf2, 0x1a975b06, 0x7b5b6b20, 0x4cbb2017, + 0x0f6c05b2, 0x5ba08505, 0xab250796, 0xf79cf707, 0x677e41c4, 0xa0f8ef26, 0xe71514f8, 0x491bf645, 0xcc2005c8, 0x2407c245, 0x088b34b3, 0x4ed78223, + 0xf822053f, 0x654666e6, 0xfbff3b05, 0x08910080, 0xe6e7ffff, 0x2000ff68, 0x5c050a17, 0x1c9cffff, 0xffff0528, 0x3b824cfc, 0x9a19f824, 0x3282ffff, + 0xfaffff2e, 0xffffcecc, 0xff6666f7, 0x6666ffff, 0xf7213082, 0x200f824c, 0x252383ff, 0xff32b3f7, 0x28830400, 0x7466fb20, 0x82342005, 0x83d7201e, + 0x4c3d220a, 0x234882cc, 0x06cccc84, 0x19053a5d, 0x2609f31c, 0x0d00ff8b, 0x8308cc4c, 0x05894a06, 0x5dff3321, 0x0d2805f3, 0x088bcd4c, 0x93061cf7, + 0x07271a82, 0xffff0080, 0x8670fdfb, 0x51f926a9, 0x00ff08ec, 0x26728319, 0x05d863db, 0x832d00ff, 0x856122c4, 0x270a821e, 0xff9a9903, 0xf49d0700, + 0x97820482, 0x2e050026, 0x0800ffb2, 0x0023ac82, 0x8222db00, 0x82082034, 0x200a8234, 0x82148224, 0xfcff2697, 0x00ff5267, 0x22b18305, 0x82d643f9, + 0xcc28211e, 0xc930ea82, 0xfb059a99, 0xff152b60, 0x34b30c00, 0x1400ff06, 0xff23d682, 0x8266e6e0, 0x830b205d, 0x82ef2034, 0x13002104, 0xff235382, + 0x829999f6, 0x233e821e, 0x00800100, 0x142c3e82, 0x00ff3233, 0xff676601, 0xcecc1100, 0x6c833e82, 0x90830820, 0xce4c1222, 0x0b201e82, 0x17221e83, + 0x4882cccc, 0x9a195232, 0xb68bc006, 0xe6d5ffff, 0xffff8b66, 0x089a19ca, 0x7fb35319, 0x2916c95e, 0xf70794fb, 0x34f70674, 0x20828b07, 0xff34b324, + 0xd5830e00, 0x11230484, 0x828b34b3, 0x153b21b6, 0x2c271a82, 0x00ff3333, 0x86cdcc23, 0x200e8204, 0x83f1828b, 0x20118506, 0xfc7c18ff, 0x20118310, + 0x220482ff, 0x19ffff34, 0x2013ea53, 0x285484cc, 0xef0e0834, 0x54f804f7, 0x4d9e1815, 0x435b2016, 0x29270587, 0xffff8bba, 0x8246d6f8, 0x08ef4304, + 0x20059645, 0x504818ff, 0x69942010, 0x20440c84, 0x169f4a0a, 0x0674fb22, 0x0d825218, 0x28216191, 0x247884f6, 0xd70800ff, 0x069f450a, 0xef6e0820, + 0x2058460a, 0xc38b6184, 0x870e8946, 0x82cd20c3, 0x46d62161, 0x84466193, 0x0624231f, 0x751814fb, 0x672c0c02, 0x8bc0088b, 0xc08bb6b6, 0x0614f708, + 0x0e1b7518, 0xab271886, 0x1100ff06, 0x418b34b3, 0x024209f2, 0x39811805, 0xff310817, 0x33b37200, 0xff9c8b07, 0xcc4cf9ff, 0x4c1000ff, 0x08977fcd, + 0xb3b2ffff, 0x4d00ff34, 0xff05cc4c, 0x9a19f3ff, 0xf0ffff97, 0x00ff9a99, 0x7a34b306, 0x221d828b, 0x45cc4ccd, 0x1a2205e6, 0xbd509082, 0x15240806, + 0xffff707d, 0x8b0080e5, 0x0694fb08, 0xffff44f8, 0x1533b312, 0x4cedffff, 0x14fb07cd, 0xff07eb06, 0x34b33200, 0x53829b82, 0x33285d83, 0xff14fc05, + 0xcd4c1dff, 0x0d6b2382, 0x08826a14, 0x2008ad4c, 0x655c831a, 0x6c6b16e1, 0x04f82216, 0x8c8d19bb, 0xef0e275c, 0x15eb44f8, 0xff4c14fc, 0x0acb4c0c, + 0xe6514b20, 0x83c68209, 0x21bf8518, 0x3282f808, 0x6a15d74a, 0x082105dc, 0x07596bb3, 0xcc4c0722, 0x3206ae52, 0x1504fb6b, 0xcb0644fb, 0x0644f707, + 0x1cf7074b, 0x4c1504f7, 0x605218f5, 0x4cfb2005, 0xf7212bc0, 0x0a5b4d24, 0xb4456820, 0x99fb2606, 0xeb088b98, 0x2668868b, 0xffff8b98, 0x836866fc, + 0x4d662004, 0x68cc065e, 0xb1ffff22, 0x0127ed82, 0x15b8de08, 0x82faffff, 0x0300230a, 0x728548e1, 0x2106002f, 0x00ff8b48, 0x08b8de06, 0x403e00ff, + 0x21ab8400, 0x1c860060, 0xe8820320, 0xab84ff20, 0x210f1141, 0xa8830060, 0x0800a026, 0xc0c1ffff, 0x75243582, 0x400a00ff, 0xea283682, 0x00ff0080, + 0x7fb85e12, 0x2a264e82, 0xffff142e, 0x1082c0e4, 0x34331926, 0x80d1ffff, 0xcd223383, 0x338233b3, 0xcdcce122, 0x200a244e, 0x256e8398, 0x0400ff66, + 0x094e6866, 0x24088206, 0x990300ff, 0x20048398, 0x06ee4d9a, 0x1e00ff24, 0x35823333, 0x80410026, 0xdfffff01, 0x3c2b1c83, 0xffffcccc, 0xff34b3c9, + 0x825e2400, 0xbeff22c0, 0x2c828280, 0x15ae87c9, 0x1000ff73, 0xffff9a99, 0x257882f0, 0x00c01900, 0xde90a88b, 0xde866f82, 0x088b9a22, 0xbd22de9a, + 0x7482b89e, 0x47d4ff26, 0x1800ffae, 0xda2c5383, 0x00ff9a19, 0xff32b323, 0x66e6e6ff, 0x16205682, 0xf0257483, 0x00ffcd4c, 0x216d820d, 0xe684e6ff, + 0x0080e422, 0x8f82e690, 0x21090b4f, 0xef8506bb, 0x2b26e699, 0xff766766, 0x6d822800, 0x82dcff21, 0x180028e7, 0x0e0832b3, 0x82f801ff, 0x78013010, + 0x4b1552f8, 0xffff05cb, 0xff00a0f6, 0x82600900, 0xd0f028f6, 0xffff8ba4, 0x84b89ef6, 0x877c8214, 0x00ff260a, 0xff480100, 0x861f82ff, 0x82188229, + 0xf00f22b6, 0x211482a4, 0x448252f8, 0x66e6d927, 0xf0d9ffff, 0x270a82a4, 0xff52f8c8, 0xae073700, 0xf7245a9d, 0xffff7288, 0xff2c0484, 0xffff1298, + 0xff3cfff2, 0x74d30600, 0x9c217982, 0x205a8228, 0x24a28295, 0x67e66aff, 0x26e28205, 0xffff8c37, 0x82d7e3fc, 0xcecc2409, 0x82feffff, 0x04002419, + 0x828b66e6, 0x24062325, 0x36828b18, 0xff962326, 0x10580200, 0xb0212082, 0x210482a4, 0x1a82e0af, 0xd583d083, 0x0f211f82, 0x335d192f, 0xeec8220d, + 0x20a08314, 0x205b826c, 0x224c8326, 0x825c0f26, 0x070f220a, 0x28cc86ae, 0x86ab0400, 0x45fbffff, 0x265a821e, 0xffff3233, 0x8234b3fd, 0x9a192109, + 0x06827184, 0x2e200c82, 0x71904182, 0xff7a5426, 0x06610900, 0x1f827183, 0x82f5ff21, 0x240f82ad, 0xfeff0848, 0x2e4182d8, 0x14eeacff, 0x3a00ff15, + 0xffff5d8f, 0x82a470c5, 0x40062d71, 0xf9ffff00, 0xff8b00c0, 0xb8def5ff, 0x04820a84, 0x0890c222, 0xd721ee82, 0x2104820a, 0x868248e1, 0x8266e621, + 0x826620f3, 0x84fb2004, 0x83ff20f3, 0x25168306, 0x0100ff67, 0x25829a99, 0x00232082, 0x82991903, 0x66c52135, 0x3a281482, 0xff050180, 0x33b3d6ff, + 0x32200483, 0x3a216682, 0xacfe828f, 0xa4672071, 0x849a2071, 0x82662071, 0xff7f21d2, 0xd8217182, 0x22a382a6, 0x8233b3d8, 0xfdf3230a, 0xc9827f70, + 0xff8f4228, 0x34b3efff, 0x28827a8b, 0xec51a728, 0xc7ffff07, 0x0484ae07, 0x19061a42, 0x2216335e, 0x82a4b004, 0x3c4a26e0, 0x230600ff, 0x077e41d7, + 0x8bd72323, 0x20108408, 0x4105848b, 0x382711f0, 0x00ff52f8, 0x8210f838, 0xb05823f1, 0x491906a4, 0x8f2513ce, 0x010c00ff, 0x2746828a, 0xff9999bb, + 0x9a99bb00, 0x6a218782, 0x21c182e6, 0x0a831995, 0xf768c23e, 0x73c2ffff, 0xef0e0532, 0x199f00ff, 0x0001ff9a, 0xff1566e6, 0x66e6aeff, 0xbdffff8b, + 0xff2d3382, 0xff717dc5, 0x9a99f3ff, 0xb5b3ffff, 0x2c4882c1, 0xffcd0a00, 0x6866faff, 0x1f0400ff, 0x21b482f3, 0x09820080, 0x827dff21, 0x2f0123aa, + 0x8482cc4c, 0x7cff0422, 0x0322b082, 0x17827eff, 0xff231c82, 0x828240ff, 0x00c02209, 0x26468208, 0x00ffae7c, 0x8200404c, 0x34b3275a, 0x663b00ff, + 0x37823966, 0x6698002f, 0x4fffff66, 0xff159a19, 0x70ddd0fe, 0x21548206, 0x7e828300, 0x82e0fb21, 0x82fb2028, 0x00002142, 0x40200984, 0x00234282, + 0x827d5f0c, 0x82c02089, 0x63422574, 0xc5ffffd7, 0x50221e83, 0x46835338, 0x52385022, 0x43257882, 0x00ff142e, 0x2016833a, 0x22a4830c, 0x82cc4c4c, + 0xcc0122b4, 0x828382cc, 0xfbff2173, 0x80220984, 0x31838600, 0x78823320, 0x422e0123, 0x2af18290, 0xff7c7ffc, 0x82800300, 0x82f9ffff, 0xffff22b9, + 0x217b82c0, 0x8b8341fd, 0x087eff2d, 0x7ad2ffff, 0xc1ffffe2, 0x6f90703d, 0x3820065b, 0xff223982, 0x918380c7, 0x1e85382c, 0x7dc7ffff, 0x5700ff70, + 0xbb8214ae, 0xffba1e2b, 0x68e63d00, 0x822d00ff, 0x227a828e, 0x50840004, 0xf88207d8, 0x82060021, 0x85ff200e, 0x7c5f216c, 0x2d205882, 0x002e3d82, + 0x05ae47d3, 0x80e600ff, 0x1300ff02, 0x8d824821, 0xe07ac727, 0x823800ff, 0x216d828e, 0xdc50ec51, 0x19c22206, 0x2187829a, 0x34822a9c, 0x7cfffb26, + 0x1ffdffff, 0xa7820482, 0xb7838520, 0xffff8425, 0x8284a0fc, 0x4cd3276e, 0x2cffffce, 0xe0509999, 0x7d7f2508, 0x010600ff, 0x00201982, 0x02227e83, + 0x4e82f8be, 0x82830021, 0xb32c270f, 0x3e00ff30, 0xe050c3b5, 0x32b32107, 0x8021c682, 0x26778200, 0x0e08727d, 0x82e301ff, 0x1d01236f, 0x8e826666, + 0x33b30232, 0xb302ffff, 0xffff0534, 0xff47219c, 0x06000000, 0xa7270a82, 0xffff8f02, 0x82e2faa6, 0xc0f62d0a, 0xf6ffff41, 0xffff7e9f, 0x8bbebff0, + 0xa1260a82, 0x0900ff48, 0xab828260, 0x42a0f622, 0x40270a82, 0x00ff8b84, 0x820c420f, 0xbe5f210a, 0x5e210482, 0x278182b8, 0xff71fd58, 0x1e055900, + 0x0027ab82, 0x00ff1400, 0x8266e664, 0x0c31270a, 0x3100ffcd, 0x0a82d763, 0x82993321, 0x68cc22f2, 0xb24818f5, 0x82df2008, 0x1704273b, 0xfeffffcf, + 0xc7822270, 0x8b8d1722, 0x04204682, 0x0c820682, 0xff52182a, 0x20900100, 0x1f0300ff, 0x0322f282, 0x1a820020, 0x823f0621, 0x84062030, 0x200a267c, + 0xf9ffffc4, 0x218c82c0, 0x1a824006, 0x45ccff22, 0x33228c82, 0x5b820497, 0x823d2921, 0x85292187, 0x33278783, 0xffff5dcf, 0x8ea530cc, 0x83ce2071, + 0x82212071, 0x8e172164, 0x8e207185, 0x0420ce82, 0x16827185, 0x7c1f0322, 0x718b7682, 0x1f828320, 0xc5200a22, 0x2126718d, 0x3300ff46, 0x7184c3f5, + 0x00ff7022, 0x34277185, 0xffff1e05, 0x89e2facb, 0x83bc2071, 0x84718467, 0x827191e3, 0x20719116, 0x20718482, 0x27718cc6, 0xfff6e8cb, 0x08173400, + 0x31275b82, 0x00ff14ae, 0x82200532, 0x5e24280a, 0x2400ffb8, 0x82c59082, 0x360a8367, 0xffae8725, 0xb85ee1ff, 0x3100ff08, 0xffff186e, 0xff3433d7, + 0x82b3f8ff, 0x4fbd3e04, 0xdcffff5c, 0xffff3233, 0x083233dd, 0xf601ff0e, 0x01ff9a99, 0x159a9916, 0x34f734fb, 0x306b8205, 0x00ffcccc, 0xff664606, + 0xceccf7ff, 0x200300ff, 0x22098300, 0x85088bcc, 0x25058206, 0xffffecd1, 0x1682e0fc, 0x90c2f925, 0x44f9ffff, 0x92180506, 0xf9211a5e, 0x2925829a, + 0xff05e405, 0x9a99f0fe, 0x6382a3fb, 0x8240d921, 0x3104843d, 0xffb89ef9, 0x00c0c0ff, 0xc12300ff, 0xd6ffff48, 0xb2820080, 0xff7f142d, 0x1ae8ffff, + 0x1c00ff1c, 0x827f15ae, 0x71bd2105, 0x002a7e82, 0x06837200, 0x611a00ff, 0x05828b48, 0x0930e583, 0x00ff9a19, 0xff482114, 0x1e051500, 0x1301ff08, + 0x0129e582, 0x059a9912, 0x5d0700ff, 0x21f08270, 0x0a820ca2, 0x2c350622, 0xbf247f82, 0x0800ff3c, 0xfc22f683, 0x098366e6, 0x51833420, 0x34330822, + 0x08224b82, 0xe785142e, 0x3d060022, 0x08de9218, 0xe07a0c27, 0x860c00ff, 0x271f8266, 0xff343314, 0x0280f3ff, 0x9e820f82, 0xff54fb2c, 0x6666a9ff, + 0x91ffff15, 0x8f829999, 0xcd4c9522, 0x2007b172, 0x37488237, 0x48e1c8ff, 0xa1ffff05, 0xffff86eb, 0x051e05a2, 0xf85cf70e, 0x44fb1534, 0x270e7553, + 0xff8b9042, 0x70bdf2ff, 0x2207a36e, 0x69c00a00, 0x002a06df, 0x8b00400d, 0xfb069308, 0x228207d4, 0xad83d320, 0x48e12325, 0x83dcffff, 0x1e2c22ec, + 0x22b783b9, 0x82b81e2c, 0x22168397, 0x83e62300, 0x192c27a2, 0xd4f7089a, 0x50189307, 0xa8530ecc, 0x222d8208, 0x7a90420d, 0x0a2206f0, 0x6f5170bd, + 0x53083205, 0x4b1574fb, 0x0744f706, 0x44fb06cb, 0xf7ecf707, 0x18a98674, 0x20091d8a, 0x23a9a8f5, 0x00ffb8de, 0x2123a985, 0x8300ff48, 0x850820a2, + 0x83168506, 0x8286821b, 0x20a98917, 0x201082cc, 0x06aa6a0a, 0xf9820a82, 0xa9890820, 0x00ffcc22, 0x3421a986, 0x2aa98e8b, 0x638bef0e, 0x3c01ff15, + 0x820734b3, 0x191a3a2f, 0x0f00ff98, 0x00ff15ee, 0xff9a9917, 0xcd4c1800, 0xb30900ff, 0x01ff0834, 0x2693830b, 0x05a2256b, 0x830700ff, 0x0d03271a, + 0x0800ff0e, 0x34829899, 0xff240f83, 0x08f2f2fc, 0xe6262582, 0x94ffff66, 0x25825eda, 0xcc4c1825, 0x82f6ffff, 0x0f003404, 0xffff68e6, 0x8b6666e8, + 0xe6e5ffff, 0xfeff0868, 0x58cc4cc3, 0x218209fa, 0x1807005d, 0x41071651, 0x025d0832, 0x01ff240a, 0x8266e608, 0x10002635, 0xffffcdcc, 0x2be983f1, + 0xff33330f, 0xcc4ceeff, 0x14fc088b, 0x220d7e5c, 0x82cdccf0, 0x33ef226c, 0x226c8233, 0x899a19f7, 0x0d67596c, 0x49425b20, 0x236c8a0c, 0x15732cf7, + 0x23164753, 0x14f807c3, 0x2005725a, 0x12f653f2, 0x06e4fb26, 0x1544f773, 0x4b212282, 0x24948207, 0xf78b07cb, 0x200d8304, 0x250d833b, 0xff0e07db, + 0xef823601, 0xc05e0126, 0xff831500, 0x25057957, 0xff0080f6, 0x9883fcff, 0x0983fc20, 0x00c0f732, 0xdeffff08, 0xffff0180, 0x0500c0b1, 0xffffff75, + 0xee206783, 0x7521eb87, 0x25d98208, 0xff48e1e9, 0x04821100, 0x1eeeff2a, 0x1600ffb8, 0x088bb81e, 0x16850685, 0xe6110024, 0x10828b66, 0x829a1921, + 0x0a00212d, 0xfb225783, 0xe57400c0, 0x82f92006, 0x0700236b, 0x3182b81e, 0x14832120, 0x48a14e23, 0x268b8205, 0x00ffcc8c, 0x82662608, 0x9a19218b, + 0x4c262982, 0xf7ffffce, 0x188466e6, 0x89202982, 0x23088482, 0x00402100, 0xc7ffff15, 0xff061ec5, 0xe2badfff, 0x172700ff, 0xcfffff0a, 0x00ff3433, + 0xfff6e818, 0xcc4cc9ff, 0x06848782, 0xff211685, 0x282083e7, 0xff33b3df, 0xf6e8d8ff, 0x213b8208, 0xb218cdcc, 0xdc2013c5, 0xa443f482, 0x22098205, + 0x821c00ff, 0xe3ff2196, 0x2323a683, 0x4f8b0040, 0x09830580, 0x1e831985, 0x1082dc82, 0x48660820, 0x5f298206, 0x388306fb, 0x34b3dc28, 0x54fb088b, + 0xab8284fb, 0x856bb92b, 0xc6ffff8b, 0x00ff7b94, 0x240a8339, 0x7b944600, 0x223c8208, 0x847c9446, 0x21048311, 0x1583ff84, 0x0682b882, 0x1b827c20, + 0x846b3922, 0x0a823283, 0x6bb9ff23, 0x822d8284, 0x82852006, 0x9a992111, 0xff294985, 0x8b6666b9, 0x64f70e08, 0x206082eb, 0x08a056f7, 0x7c11e752, + 0x0c590f14, 0x201b820b, 0x0d657234, 0xcd213f82, 0x211683ff, 0x5483ffff, 0x6beb0823, 0x05c56115, 0x2008f979, 0x213083fc, 0x918204d6, 0xd6080023, + 0x087c6188, 0x30827820, 0x82fc2921, 0x304218bf, 0x508c940a, 0x082807a6, 0x088bcccc, 0xb4f754f7, 0x61726083, 0x0a2c7d08, 0x21054b5c, 0x62820ad7, + 0x82cccc21, 0xf628217e, 0x2006d650, 0x054753fc, 0xff238882, 0x6704d6f8, 0xfb570b67, 0x20288205, 0x054b7a00, 0xa4823c82, 0x088b0428, 0xd4fb069b, + 0xe25e7b07, 0x649c8a0c, 0xf820187d, 0x1e5cda18, 0x04827d84, 0xf7206e85, 0x7b2aff83, 0x07d4f706, 0xfb3b069b, 0x0219150c, 0xfb25165f, 0x076b061c, + 0x0cfa5df3, 0x200a7d5e, 0x073d507b, 0xff201383, 0xfb250485, 0x088b9a99, 0x24358223, 0x544500ff, 0x3839827c, 0x8b5c8f19, 0x3d0f00ff, 0xe3ffff70, + 0xffff1e85, 0xffecd1f1, 0xe2baeaff, 0x2e058208, 0x056b86ab, 0x14faffff, 0xf7ffff7a, 0x8281cc0c, 0x34b3270a, 0x66f4ffff, 0x1d828b66, 0x2205e366, + 0x82cd4cf5, 0x02f6279b, 0x0500ff8f, 0x2182d458, 0xffec1126, 0x2ce70800, 0x85213e84, 0x273e82ab, 0xff99d9f1, 0x00401500, 0x33256482, 0x1c00ff34, + 0x22098280, 0x82999919, 0x45002742, 0xab06cd4c, 0x225f2307, 0x0300210c, 0xff26a182, 0x66660400, 0xbf829b08, 0xd35e0883, 0x22178409, 0x82f3088b, + 0x22fa8235, 0x82fbffff, 0x09a85f47, 0x3699c782, 0x088b6724, 0x6db61cf7, 0x8897a320, 0x7a419b20, 0x41732017, 0xa2823695, 0x410bc75f, 0x0e370ccc, + 0x4b00ffef, 0x01ffe23a, 0x159a999e, 0xc5f400ff, 0xe2ffff1e, 0x8205cc4c, 0xcccc260a, 0xb31d00ff, 0x2c0a8234, 0xff34b306, 0x0ad70000, 0x800600ff, + 0x06ef5c00, 0x9819032b, 0xf0f9ffff, 0x00ff08a4, 0x231e8229, 0xb89eacff, 0x08272982, 0xffff68e6, 0x719a19ee, 0xff26050c, 0xffcc4cea, 0x1e83ecff, + 0x0080fa31, 0x5cffff08, 0xffff32b3, 0x05cd4cd1, 0x83f2ffff, 0x83fc2024, 0x82f12004, 0x05002d49, 0xffffcdcc, 0xff9a99f8, 0xcc4c0d00, 0xac242982, + 0x1ff79a99, 0x07822682, 0x0783fb20, 0x9999f825, 0x83f2ffff, 0x83f12049, 0x33fa2233, 0x260e8233, 0x00ff9919, 0x8266e603, 0xab5c272e, 0x2e00ff86, + 0x318233b3, 0x71bdec25, 0x830500ff, 0x79f625a7, 0x1500ff17, 0x00263382, 0xfffef408, 0x29831100, 0x3325ac82, 0x615300ff, 0x22ac8248, 0x82ae0703, + 0x5c0f21d1, 0x87200482, 0x03200982, 0x003a3382, 0xffe2ba06, 0xf628ffff, 0xff068b08, 0xb8def500, 0x66a1ffff, 0x00ff1566, 0xc982cc36, 0x9a99a422, + 0x0e253682, 0xffff66e6, 0x218082e7, 0x5b821d00, 0x83f5ff21, 0x821b2085, 0x07002713, 0xff089a19, 0xc4837f00, 0x66662422, 0x59298a82, 0x8b079a19, + 0xffff7c75, 0x263d83ec, 0xff9899ea, 0x8299faff, 0x33ff2423, 0x825868e6, 0x83f5201f, 0x66fd2116, 0xf5254e82, 0xff8b6866, 0x210f83ff, 0x21860200, + 0x82be6621, 0x97ea2221, 0x83cc820a, 0x02f13021, 0x1300ff8f, 0xa18b3433, 0xa600ff08, 0x850766e6, 0xdbff2169, 0x7f839384, 0x21050572, 0xdf82b31d, + 0x67e60a25, 0x830e00ff, 0xcc182204, 0x832f82cd, 0x5b0021bd, 0x002b9383, 0x06343302, 0xff94f70e, 0x82e6a001, 0x72ff23d7, 0x78829a99, 0x824c8e21, + 0xe1a222dd, 0x230a8248, 0x08b81e8d, 0x2a080682, 0xff4861ce, 0x9a591500, 0xa3d2ffff, 0x2300ffd6, 0xffffb99e, 0x08b047dc, 0x80f3ffff, 0xcdffff00, + 0xffff48a1, 0xffe13ad6, 0x8219d3ff, 0x83ff2023, 0x82048213, 0xc0fd211e, 0x04841e82, 0x8260ff21, 0x84fc2809, 0x0100ff18, 0x82880060, 0x3f013385, + 0x00ff88be, 0xffa2c502, 0xe83bfeff, 0x400300ff, 0x16828b00, 0x06824220, 0x3000ff2e, 0x00ff9ad9, 0xff90c21f, 0x01801900, 0xa121e982, 0x201a8246, + 0x20668320, 0x2d5182f3, 0xd6632400, 0xdcf8ffff, 0x2600ff28, 0x3c194861, 0x71260988, 0x00ff34b3, 0xb882215d, 0xf8710023, 0x83b88252, 0xffff2a06, + 0xffd26d8d, 0x66e65e00, 0x82df84ff, 0x197f2495, 0x1884fb9a, 0x22139081, 0x839ad910, 0x2d068235, 0x400e00ff, 0x0f00ff00, 0x00ff6626, 0x9984c011, + 0x01c01123, 0x1816858b, 0x26121e6e, 0xff9999f2, 0x82a6f2ff, 0x66ed2263, 0x23918366, 0x8b66e680, 0x18836288, 0x3f825083, 0x15826295, 0x06833483, + 0xb3216299, 0x22628632, 0x833433ee, 0x89c6822d, 0xc0f12162, 0xb382ae82, 0xc5886298, 0xc59b0020, 0xc58b9a20, 0xef0e2608, 0x074000ff, 0xd000ffae, + 0x8b1566e6, 0x68ceffff, 0x1500fff6, 0xffff4861, 0xff707dd3, 0x0b972300, 0x66dbffff, 0x08064268, 0xff289c26, 0xa430d6ff, 0x17211e82, 0x06c5610c, + 0x26060642, 0xffff21d0, 0x82f8b3fd, 0xef672d14, 0x98fcffff, 0x0100ff10, 0x0888f047, 0x4f250682, 0x00ff88df, 0x27208302, 0xfff833fe, 0xdf2f0300, + 0x4222db83, 0xa6825c4f, 0xa4b03127, 0xcc1f00ff, 0x05f155cc, 0x9c130023, 0x2531822a, 0xff52b820, 0x1983f3ff, 0xcd4c2423, 0x05e742ff, 0x22060642, + 0x82d86325, 0x63233d35, 0x0600ffd6, 0x00ffbaa9, 0xff1e0520, 0x6eb20b00, 0xaafeff08, 0x01ffc420, 0x053c0a0b, 0xe12a3b82, 0xe7ffff47, 0xffffcecc, + 0x4a8238f9, 0x9999e522, 0x2008db82, 0x083333e5, 0xc53602ff, 0x157afb20, 0xe689ffff, 0x5c00ff68, 0xff050a97, 0x64662600, 0x822400ff, 0x83838290, + 0x992f2214, 0x2362829a, 0x08666634, 0x72270682, 0xffff66e6, 0x8266668d, 0x3433262b, 0x8073ffff, 0x23bb8200, 0x9042bcff, 0xc2265082, 0xffffd6a3, + 0x168273ea, 0x1b83d220, 0x7a14dd2d, 0x94ffff08, 0x00ff5ccf, 0x82c44054, 0x83f52085, 0x45083636, 0xf0ffff60, 0xffff33f3, 0xff28f1fd, 0x7bf4f7ff, + 0xb6f5ffff, 0x222982c8, 0x8221d0f7, 0x828f200a, 0xd201222e, 0x272382b0, 0x00fff6e8, 0xffdf6f0a, 0x0d558818, 0xa0826820, 0x00800a22, 0x88181582, + 0xde210955, 0x076073b8, 0x08f06727, 0x1c0900ff, 0x240482ac, 0xffff5a84, 0x558818fe, 0xf8ef2412, 0x5a74f7e4, 0xde590ca3, 0x073b230a, 0x116954fc, + 0x831a2005, 0x82ea2563, 0x1500ff8f, 0xe5220983, 0xe883707d, 0xe3820683, 0x348a1682, 0x2005c970, 0x48f382f7, 0xf8220567, 0x9349cccc, 0xcb082105, + 0x083b4318, 0x96430622, 0x0dd24318, 0x67e6002a, 0x54f8059b, 0x8b077b06, 0xd918cb82, 0x3b891270, 0x210e766b, 0x328254f7, 0x14864418, 0x5b64fc27, + 0xf8075b15, 0x05c95b14, 0x48a12631, 0x871b00ff, 0x2000ffb0, 0x00ffeb51, 0x82507824, 0x156e2781, 0x2100ff08, 0x4283b89e, 0xa4b04625, 0x82c6ffff, + 0x39002804, 0xffff5c4f, 0x825c4fb9, 0xfffe24e2, 0x85069a19, 0x831c850c, 0x82a28221, 0x2839821d, 0xff66e600, 0x6666deff, 0x244f8205, 0xffff0080, + 0x210482f8, 0x04821b00, 0x3006b166, 0x086666d9, 0x4601ff0e, 0x00ff34b3, 0x15cc4c2c, 0x2a228275, 0xffff9a19, 0xff9819e8, 0x8299fbff, 0x33e72209, + 0x23658234, 0x3333e7ff, 0xe8205482, 0x00241b82, 0x75666604, 0xe62c9982, 0xffff0866, 0xffcdccfe, 0x9a190000, 0x99210482, 0x21098599, 0x1386ffff, + 0xe1311e82, 0xff9666e6, 0x3333e5ff, 0xcc1100ff, 0xeaffffcc, 0x222e824c, 0x829a9916, 0x23dc261a, 0x2500ffd7, 0x2b9e8266, 0xffc2f5e9, 0x34b33200, + 0x3700ff8b, 0x06825482, 0x48e17225, 0x835d00ff, 0x1e5d2755, 0x7200ffb8, 0x828266e6, 0x16850684, 0xfa45ff20, 0x82c8200c, 0xe9ff2128, 0xcd260483, + 0xff68cc4c, 0x5f82daff, 0x8a8a8a22, 0xe6239c82, 0x828a8a66, 0x83ea206a, 0xea2808c7, 0xff7134b3, 0x3233efff, 0xf5ffff6e, 0x8b080080, 0xffff058b, + 0xff3233a5, 0x9a992401, 0xf9ffff15, 0xff079a19, 0x6766faff, 0xaa833782, 0xc582f920, 0x4cfeff2d, 0xfbffffce, 0xffff66e6, 0x82ccccfd, 0x83f12049, + 0x33f92665, 0xffff7e34, 0x20ba83f3, 0x222983fc, 0x8234b3ed, 0x33fe221a, 0x25588234, 0xff8ccccc, 0x2582f6ff, 0x82040021, 0xf7ff22f4, 0x86ea8219, + 0x486a820a, 0xf920058e, 0x00215982, 0x20938306, 0x248782fb, 0x990b00ff, 0x05754199, 0x4c0f0023, 0x826e82cd, 0x0b002658, 0xffff33b3, 0x201e84fc, + 0x23488302, 0x056766ff, 0xfb202582, 0x00211682, 0x82798409, 0x05002394, 0x2f8268e6, 0x0833b327, 0x800200ff, 0x26b88200, 0x00ff3433, 0x8266e600, + 0x26538209, 0xcc4c0000, 0x84ffffff, 0x83002082, 0x82ff2033, 0x00002349, 0x1e829a99, 0x4c225384, 0xb88287ce, 0x4e84ff20, 0x19253e84, 0xffff889a, + 0x200a83fa, 0x715483fd, 0xfd200591, 0xd2831f83, 0xb3feff22, 0xf325e282, 0x088d3233, 0x20e58285, 0x21ac82f5, 0x4d830300, 0x3182f620, 0x33030022, + 0xff218682, 0x20db83fd, 0x86048200, 0x33b32209, 0x84918289, 0x84f5204c, 0x21048225, 0xc582f4ff, 0x82faff21, 0x24e1833e, 0x7ff5ffff, 0x208682ff, + 0x841983fc, 0x83052023, 0x82f4201e, 0x05e24e6b, 0xdf827f82, 0xb1830120, 0x00218083, 0x06bb4701, 0x0100ff22, 0xff282382, 0x086666ff, 0xfdffff92, + 0x0021eb82, 0x2304820d, 0xceccfbff, 0x4106124f, 0xf93c05b3, 0x8b079a99, 0xe6f4ffff, 0xff829466, 0x34330a00, 0x8b97088b, 0xff8b9494, 0x9a190b00, + 0x05295982, 0xff070080, 0xcc4c0500, 0x2405828c, 0x00ff3433, 0x23f08202, 0xcccc0400, 0x33216082, 0x20208234, 0x3250830f, 0xff32b306, 0x98990c00, + 0x0300ff98, 0x00ffce4c, 0x82010013, 0x8301201a, 0x410a2025, 0x3422055b, 0x77828795, 0xff275283, 0x949a19fc, 0x83f9ffff, 0x99062232, 0x83098299, + 0xcc042231, 0x2ae682cd, 0xff66e6f3, 0x67e60800, 0x83efffff, 0x2066833b, 0x201384ff, 0x05454203, 0x002b2983, 0xff053233, 0x33b3f2ff, 0x820400ff, + 0xf6ff240f, 0x828e6666, 0x23348244, 0x32330400, 0xfd204482, 0x00217182, 0x22968201, 0x8233ffff, 0x33012424, 0x43ffff32, 0x80210575, 0x851e8200, + 0x6866210a, 0x28841482, 0x00231e82, 0x829a9900, 0x666621b9, 0x0023b482, 0x828d6666, 0x008021db, 0x0622ca86, 0xf482cd4c, 0x82cccc21, 0x8305201a, + 0x83022025, 0x840a20a2, 0x230e83ff, 0x8a34330c, 0x04201a82, 0xff214a82, 0x210482fe, 0x39820d00, 0x82fdff21, 0x0300235e, 0x1a8366e6, 0x26820a20, + 0x19fdff27, 0x00ff9698, 0x20168306, 0x213b8302, 0xa982b30a, 0xe6020025, 0x8400ff68, 0x99f9211f, 0xff211f82, 0x20cf82f5, 0x821f8200, 0x82fb20a5, + 0x01002535, 0x8d813433, 0xa785db82, 0x67823420, 0xcc4c0623, 0x059b4107, 0xff948227, 0x66e6f4ff, 0x832b828b, 0x82822106, 0x4405c541, 0x073905d5, + 0x1944ffff, 0x0fffff9a, 0xff159a19, 0xe1fa0f00, 0x1300ff06, 0xffff3373, 0x261582e6, 0xec911800, 0x83eaffff, 0x331c21f7, 0xef211382, 0x2a5982b3, + 0xcdccb7ff, 0xf8076b06, 0x82ab0614, 0xccb7223c, 0x203182cc, 0x258e831b, 0xffcc4c10, 0xd4821900, 0xcc150023, 0x834582ce, 0xe619248b, 0x189b0866, + 0x600c574a, 0xdc6e1353, 0x34fc210f, 0x6e0c4475, 0xcb200add, 0x18070246, 0x2c0c5bf9, 0x8b088b8f, 0xb4f70e06, 0xcc1801ff, 0x22c682cc, 0x829a191c, + 0xe325089a, 0x00ff00c0, 0xff486124, 0xb81eedff, 0xe82a00ff, 0x00ff84f6, 0x08f4e82d, 0xd4fdffff, 0x0d00ff7b, 0xffffa07e, 0x36e683ef, 0xffe66c05, + 0xcd4cf7ff, 0x7ff5ffff, 0xff7508c0, 0xfa1ee7ff, 0x82f0ffff, 0xe2ff27cf, 0xfffff4a8, 0x1a82ccf4, 0x48a1df2d, 0x2200ff08, 0xffff3333, 0x8220c5d9, + 0x25148349, 0xff9899e5, 0x09833200, 0x0080f53b, 0xff04f708, 0xe23a6700, 0xd3ffff15, 0xff8b00c0, 0x6626ddff, 0x2edcffff, 0x220a8214, 0x8272bdd3, + 0x0022083d, 0xffff5c00, 0x055b8fc4, 0x9997ffff, 0x0600ff9a, 0xffff4240, 0xff6666a7, 0x81354000, 0x5b00ff63, 0x9d82703d, 0x1f94f93b, 0x8a0c00ff, + 0xeeffff3e, 0x00ffae47, 0xff86ab00, 0x0040faff, 0xbff3ffff, 0x221e82fe, 0x82b85eef, 0xbade2b55, 0xa1f6ffff, 0xd8ffff47, 0x5f828ec2, 0x9a99d623, + 0x22068208, 0x82703db9, 0x291c28a3, 0xdcbdffff, 0x825abe2a, 0x820d2072, 0xf3ff21fb, 0x00233d82, 0x8290020d, 0xe27a21e0, 0xc0205b82, 0xf6204c82, + 0xff22b082, 0x1e8370ff, 0xea11dc22, 0xf5209182, 0xff212482, 0x200483fd, 0x226c84fb, 0x8291f6a8, 0xb89e2162, 0x11254482, 0xffff4861, 0x372a82e5, + 0x3d0a2b00, 0x57d2ffff, 0x5c00ff0a, 0xffffaec7, 0x080040fc, 0xffffff93, 0x00285082, 0xff71fd07, 0x0ce20200, 0x2124d682, 0x0500ff47, 0xff2f1a82, + 0xe13a4100, 0x1e3800ff, 0x00ff05b8, 0x820ad74c, 0xa4f12129, 0x58280a82, 0xff8b4861, 0xb89e4700, 0x7d210482, 0x230a8270, 0x08f66858, 0x0026e982, + 0xa000ff56, 0x21823233, 0x9a191f2d, 0xfd3f00ff, 0xffff0572, 0x8282e390, 0x00f42237, 0x28df8205, 0x15b8de9f, 0x40f7ffff, 0x210b8200, 0xeb82bdf8, + 0x4e420722, 0x08223e82, 0xfd8240c0, 0xe0080028, 0x0700ff44, 0x0482d042, 0xff8a2c27, 0xc0bf0800, 0x8355828b, 0x26118206, 0xffffb03d, 0x822eddf8, + 0x20f72238, 0x22168244, 0x84900200, 0x21158249, 0x0482cccc, 0x5132b321, 0x0e2b06c6, 0x2f02ffaf, 0x00ff34b3, 0x82cccc37, 0xe678256c, 0x9cffff66, + 0x2005847b, 0x2528824c, 0xfff8e8f2, 0x9e82eaff, 0x83f8ff21, 0x19e92737, 0xfb088b9a, 0x3c8206ef, 0x82424021, 0xa6f9225c, 0x216c8225, 0x9583fa3e, + 0x8376be21, 0xfd5f2295, 0x82ba8270, 0x827c208d, 0x00402118, 0x45210482, 0x200482a2, 0x823782d9, 0xb95e2163, 0xf921dc82, 0x21f282e8, 0x1b82802e, + 0x70bd2522, 0x14200a82, 0x00215e82, 0x28048310, 0xff1e051b, 0x66260a00, 0x27c983a6, 0x069a199f, 0x801300ff, 0x0037fd82, 0xffb85e0f, 0x48a1eeff, + 0xc0fcffff, 0xff087700, 0x0060fdff, 0x82f0ffff, 0xf1ff225f, 0x23158241, 0x7b4821f5, 0xff233382, 0x8af6a8b2, 0x8224209b, 0x83c020e8, 0x26f822a6, + 0x209b8224, 0x850682ff, 0xf8ff2394, 0x948842c0, 0x83997821, 0xb3772767, 0x5800ff34, 0x8f82862b, 0xe9821120, 0x300d0028, 0x1900ffa4, 0x71829002, + 0xffea2625, 0x831e0d00, 0xe4302280, 0x260a8208, 0xffff50f8, 0x82bc6bec, 0x34332219, 0x29968272, 0xffff3433, 0x0866e6f2, 0x2b59af0e, 0xc5002505, + 0x92150080, 0xa0207b82, 0x0b20e282, 0x9220bf82, 0x60216b82, 0x203a8200, 0x22e4836c, 0x82343372, 0x831f2064, 0x832120ff, 0x38fe2a55, 0x3600ff52, + 0xffffe0fa, 0x27e082dc, 0x9a991e00, 0xe1ffff08, 0x00221982, 0xe482c01a, 0x8221d221, 0x26fb2cdf, 0xe3ffff66, 0xffff9ad9, 0x824260e2, 0xd9f4321e, + 0xf4ffff98, 0xff05fc69, 0x32b3f5ff, 0xa10b00ff, 0x370a8248, 0xff67e6e3, 0x00a01d00, 0x0400ff5d, 0xffff58d9, 0xff6766e0, 0xfa3ee5ff, 0xdd223082, + 0x54829999, 0x89486125, 0x82c8ffff, 0x1f003c6a, 0xffff33b3, 0x0868e6de, 0xcc6c00ff, 0x8dffffce, 0xf705cccc, 0xaaffffb9, 0x82153433, 0x48e129cd, + 0xcf1100ff, 0xe6ffff5c, 0x03202c83, 0xee227883, 0x1882c435, 0x821acf21, 0x4c88274c, 0xa7ffffcc, 0x72827cd4, 0x6666872e, 0xf7ffff06, 0xff8b8440, + 0xe2a5f9ff, 0x4022e882, 0x05828b00, 0x2205704e, 0x84fabe08, 0x00ff2411, 0x41a05a06, 0x4e280870, 0xff060040, 0x9a190f00, 0x0f2b2882, 0x00ff66a6, + 0xffb8de0a, 0x829e0200, 0xc00f2204, 0x26918200, 0xff004003, 0x82191300, 0xa1f021ed, 0x12258882, 0xffff1e45, 0x05834cec, 0x48215f22, 0xe5226f82, + 0x6f8266e6, 0xe2fae432, 0xc0f6ffff, 0xeaffff00, 0x087affff, 0x80d1ffff, 0xda220b82, 0x97829042, 0x3883c820, 0x7a060022, 0xf7220a82, 0x9c848340, + 0xffffe324, 0x7382b9f8, 0x41f7ff23, 0x282c8248, 0xff77fdff, 0xb0cba1ff, 0x06896805, 0x40070023, 0x051d433b, 0xd907002a, 0xff088b58, 0x9a195a01, + 0x1622a782, 0xa782ae07, 0xd6e31522, 0x2f2bbf82, 0x1100ffe0, 0x00ffb0c7, 0x82ce170d, 0x198726a7, 0x6300ff98, 0x216f8282, 0x7a821300, 0x1c0d002e, + 0x0300ff28, 0xffa4cccc, 0x68e6f2ff, 0xcc2d2a82, 0xaf0e08ce, 0x333802ff, 0x6f00ff34, 0x445941b3, 0x70bd0823, 0x208f8208, 0x82f68208, 0x820020b1, + 0x83402094, 0x055f4304, 0x21115941, 0x594148e1, 0x82378207, 0x0040269c, 0xf0ffff9f, 0x221582a1, 0x41486111, 0x9e2d3155, 0x0000ffb8, 0xff05a6e6, + 0xa826f8ff, 0x2605828b, 0xffffbebf, 0x82ceccf7, 0x4cf7290a, 0xffff08cc, 0x071e05a0, 0x2e210c83, 0x20998316, 0x1f504142, 0xff203022, 0x21065041, + 0x5041fe14, 0x1e852308, 0x5041ff05, 0x412a2007, 0xff2a1050, 0x9819dffe, 0x4ca100ff, 0x5d8215cc, 0xff686627, 0x9a190100, 0x05e85481, 0x33f7ff23, + 0x21098232, 0x89823233, 0x9a19fb22, 0xb3211a82, 0x2bab8234, 0xff0080f3, 0xcc4c0500, 0x4cf2ffff, 0x28068053, 0x9999fbff, 0x66f4ffff, 0x86298366, + 0x00ff330a, 0xff618506, 0x6766f1ff, 0x780c00ff, 0xfbffff10, 0x94825c8f, 0xaea70427, 0x58feffff, 0x2c948210, 0xff6a7c08, 0x62f0fcff, 0x640900ff, + 0x210982de, 0x09824cf7, 0xff8e8226, 0x73c8fdff, 0xf3224882, 0xfc8340b5, 0x82c0f221, 0xba0a266e, 0xf5ffffe2, 0x23098240, 0x8b00400d, 0x06834682, + 0x09614b18, 0x8206965b, 0x66662710, 0x1900ff07, 0xa1821e45, 0xff17b925, 0x829c1100, 0x201022f2, 0x26c68283, 0x00ff5238, 0x82b8de17, 0xb008263b, + 0x3200ff20, 0x21c0820c, 0x0e826cd0, 0x23820d20, 0x78e6ff28, 0x0700ff54, 0x77823e4a, 0x7ab4fa22, 0xd421ea82, 0x22ea827a, 0x8234b3e5, 0xc2752115, + 0x2007aa49, 0x27248238, 0xff32b300, 0x281c0400, 0x01223982, 0xe582f027, 0xff18c426, 0xdc240e00, 0x4b266282, 0x1000ff44, 0xc082f6e8, 0x82bc5421, + 0xf004271e, 0xffffff20, 0x2382fc37, 0x82986e21, 0x823b20f4, 0x47082109, 0xfd22fe82, 0x1e820020, 0x82870c21, 0xb8fb270a, 0x0d00ff10, 0x238214ae, + 0x82d09721, 0x5c4f2657, 0x870c00ff, 0x201e822c, 0x250a8504, 0xf9ffff2a, 0x23828a61, 0xff7aa925, 0x8278f3ff, 0x5704222d, 0x27a58208, 0xffe465f8, + 0x84a00200, 0xae211e82, 0x269f8296, 0xffff24bb, 0x829a19fa, 0xec5c2109, 0x0b203d82, 0x18051c68, 0x711359a6, 0x45220859, 0x5971ff1e, 0x270b820a, + 0xff07e27a, 0x93c2e6ff, 0x4a314982, 0xeeffff3c, 0xffffcd4c, 0x86e2faef, 0x1ee8ffff, 0x247383b8, 0xffffcc4c, 0x2db682ce, 0xce4c3000, 0xccf1ffff, + 0x1200ffce, 0x2e823233, 0x82989921, 0x7f062273, 0x2ce5827c, 0xff050020, 0xf6a81f00, 0xf0f6ffff, 0x24ff8222, 0xffff707d, 0x27d082fd, 0xa430ffff, + 0x40fbffff, 0xff22fa82, 0xfa82dcfe, 0x0a37f922, 0xe6264382, 0xfcffff66, 0x6d8234b3, 0x4bcccc21, 0x0e2e0502, 0x1f01ffaf, 0x54f79a19, 0xff8bc015, + 0xd3832a00, 0x48212a22, 0x322d0a82, 0x8b0852f8, 0xc6ffffb3, 0x00ff48e1, 0x287c8250, 0xb8dee5ff, 0xcc2200ff, 0x2b9b82cc, 0xff00a0f9, 0x00800800, + 0x41f3ffff, 0xff272c82, 0xffb89ef9, 0x8380f7ff, 0xa6e7216d, 0xde3d6382, 0xff51cc0c, 0x0040afff, 0x8b08638b, 0x19ccffff, 0xffffb69a, 0xc066e6d5, + 0x01ff088b, 0x21648219, 0x5244afff, 0x0ca845cd, 0xf282dc20, 0x0641f72d, 0x0000ff08, 0xffff0700, 0x45b81e9f, 0x57442ba8, 0xef0e3a32, 0x194f00ff, + 0xb700ff9a, 0x8b15cccc, 0x0700ff7a, 0xffffd7a3, 0x9734b3ef, 0x0884827f, 0x5d0f3322, 0xe6ccffff, 0x00ff0566, 0xffcd4c08, 0x34b3f7ff, 0xfeffff98, + 0x00ffcccc, 0xff33b309, 0x66660600, 0x0c222582, 0x1f8266e6, 0xff34b335, 0xcdcc0100, 0x331200ff, 0xf5ffff34, 0x08969a19, 0x83d0ffff, 0x332f222a, + 0x078e4432, 0x00800c22, 0x20060361, 0x610a8200, 0x05840503, 0x14200486, 0x0fe6d618, 0x99994827, 0x80b7ffff, 0x26818200, 0x76010015, 0x820b00ff, + 0xe3ff2151, 0xff234683, 0x82cc4ce2, 0x19b12262, 0x17407b9a, 0xbdffff27, 0x7a06cd4c, 0x83d0838b, 0x34b323ad, 0x3182977f, 0xb81e9c25, 0x836300ff, + 0xedff24d5, 0x829d70fd, 0xd7e326ac, 0x4c1900ff, 0x229a82cc, 0x829a9918, 0x80dd22d1, 0x28538200, 0x0a171600, 0xe81100ff, 0x820486f6, 0x088b220e, + 0x821583ff, 0x29168328, 0x0a17eeff, 0xe9ffff8b, 0x5582f6e8, 0x8219ff21, 0xcc5f2ea9, 0x01ff05cc, 0xff66e6e0, 0x3433a000, 0x85278215, 0x68e62143, + 0x19214387, 0x82438498, 0x82118206, 0x20438c16, 0x23778422, 0x6666e7ff, 0x1c839482, 0x34b3e624, 0x5c827979, 0x98199c27, 0x199cffff, 0x05e06e9a, + 0xffff7f2b, 0xff9a99f0, 0xcc4cf9ff, 0x824d827a, 0x6dcc20e5, 0x4c4d0cd3, 0x00ff220a, 0x0534604e, 0x34b31d22, 0x25053c41, 0x00801c00, 0xc782a0a0, + 0x42824820, 0x80480024, 0x80410500, 0x7f0c271c, 0xf3fffffe, 0xd8180080, 0x02200967, 0xdc410f84, 0xd0ff2306, 0x9482cecc, 0x9a19f52b, 0x0100ff80, + 0xffffcccc, 0x210482ed, 0xbc830c00, 0xcc4cf722, 0x09226682, 0xa98232b3, 0x989a9922, 0x33201f82, 0x08258382, 0x00ffce4c, 0x201a8408, 0x21d58233, + 0xd5823300, 0xff979724, 0xa0830600, 0x4c102308, 0x089c8bcc, 0xa000ff8b, 0x0e053433, 0xff7cf8ef, 0x66e60001, 0x062cfb15, 0x000000ff, 0xccffff06, + 0xaf82d723, 0x2b080a84, 0xff0b57da, 0x80ebe4ff, 0xa8ddffff, 0xdafffff4, 0xffffac87, 0x08e23afc, 0xe8d4ffff, 0xfbfffff6, 0xffffc0aa, 0xffd7a3db, + 0xc6c02100, 0x2a225182, 0x8d82c235, 0x34b3782d, 0xe7ffff07, 0xffff717d, 0x821e45f1, 0xb5d327b9, 0xe5ffffbd, 0x4a827c54, 0xff0ad727, 0x9919d0ff, + 0x2865828b, 0x3b083333, 0xb3d1ffff, 0x31218234, 0xff00c0f0, 0xbe3ff7ff, 0x9efaffff, 0xecffffb8, 0xbf82fa5e, 0xff48e123, 0x261882ff, 0xffffdb08, + 0x82666675, 0xe0082192, 0x11822582, 0x1300ff23, 0x270982a0, 0xfffebffa, 0x01400f00, 0xc0212a82, 0x27778202, 0xff666667, 0x00c03b00, 0x88222982, + 0xcd829a99, 0x2114cd5f, 0x9f7d00ff, 0x00ff2414, 0x63ae0730, 0x4021058f, 0x23ca8200, 0xff02c00a, 0x0aa74d18, 0x0000ff25, 0x82bb0800, 0xf5ff2ca9, + 0x0d00ffb8, 0xffffcd4c, 0x53cc4cf5, 0xf223062c, 0x828b34b3, 0xb393247f, 0x5300ff34, 0xb02105bd, 0x221b820c, 0x829a998a, 0x20f72230, 0x82a58300, + 0x60ec21af, 0x05210982, 0x2dc38640, 0x0040f7ff, 0x98ffff08, 0xffff9a99, 0xb48240c4, 0x6ec1ff2a, 0xffff0614, 0x8b6626da, 0xeb210582, 0x36618286, + 0xffffd663, 0xff7ad4df, 0xe2faebff, 0xf6ffff08, 0xffff1fc5, 0x824821fa, 0x23808404, 0x808bcccc, 0xff251682, 0xffffe6ff, 0x826c8281, 0xdee92137, + 0xb3619e82, 0x61278205, 0x212108b3, 0x20d28248, 0x821b8611, 0x1e16310a, 0x00ff08b8, 0x0766e658, 0xff064cf7, 0x16ee1e00, 0x19221482, 0x4a82ec11, + 0x8214ee21, 0x11e12246, 0x275882ec, 0x070080e3, 0x2e00ffdb, 0x00279d83, 0xffe44c0f, 0x82f30700, 0x330521e2, 0x13200482, 0xf720b783, 0x0f280983, + 0x0e08cc4c, 0x4e01ffef, 0x002a1182, 0x159a99e6, 0xe4ffff6d, 0xfa828f82, 0x6666d73b, 0xcadaffff, 0xd1ffff3d, 0x00ffcdcc, 0xffce4c19, 0x9919f1ff, + 0x331000ff, 0x275e8232, 0xff9a19e5, 0x67661d00, 0x32f51619, 0xcc0ce925, 0x82d7ffff, 0xd7ff234a, 0x4a826826, 0x5f829f20, 0xb3ffff23, 0x22748232, + 0x186666ee, 0x2108d447, 0x0a822a9c, 0xf468ee22, 0x60232182, 0x84073433, 0xfff6230c, 0x97830e00, 0xcc8cf122, 0xb3268882, 0xff088b33, 0x99827200, + 0x0f00002b, 0x00ff0576, 0xff00805a, 0x291719ff, 0xff013207, 0x48a1e9ff, 0x402800ff, 0x0400ff00, 0x00ff9042, 0x22098316, 0x82705d1b, 0x1e122734, + 0xf0ffffb8, 0x348200c0, 0x48e10f23, 0x053653ff, 0x3e821720, 0x17190020, 0x76200729, 0x1f212582, 0x193f8261, 0x262c2917, 0x00ff7493, 0x827ad40b, + 0x140b2f56, 0x0d00ff7a, 0xffff34b3, 0xff26e6fd, 0xf4831400, 0xec51f222, 0x1c211e82, 0x2bd2822a, 0xff2c926b, 0x9a5d7900, 0x1101ff05, 0x002cd182, + 0x15cc4c59, 0x0000ff2b, 0xff052e20, 0x0ba91819, 0x82866b21, 0x86eb26b7, 0x0fc6ffff, 0x21ed825c, 0x2c83f7ff, 0x24180028, 0xff8b8305, 0x9f82f8ff, + 0xcdfcff29, 0xffff8592, 0x8206a1fa, 0xb89d2755, 0xa6ffff52, 0x43829c44, 0x66e6ff27, 0xccffffff, 0x210482cc, 0x098467e6, 0x3f838b20, 0x3333ef22, + 0x3321f882, 0x826a8234, 0x05ca5d49, 0x0e820e20, 0x99f0ff23, 0x2bf1829a, 0xff00a009, 0x0080f5ff, 0x601900ff, 0xf4260982, 0x00ff48e1, 0x04822115, + 0xb8de1224, 0x34828b08, 0x1a822020, 0x00400022, 0x20260a88, 0xffdb0800, 0x19194900, 0x1e290fd1, 0xffffffb8, 0xff9100a0, 0xcd1919ff, 0x9a992a28, + 0xe689ffff, 0x00ff0566, 0x253d830c, 0xff0c02f6, 0xe0830700, 0x8480f222, 0x2305ad4c, 0x8e82f1ff, 0x5121a382, 0x21d483ac, 0x298252f8, 0x98991122, + 0x0e278982, 0x00ff6866, 0x8248610e, 0x8411200a, 0x589f20c5, 0x651805e3, 0x0e2b1338, 0x94f7a4f7, 0x0714fb15, 0x829206ab, 0xb306262f, 0xfeffff34, + 0x22a88380, 0x82cc4cfd, 0x1978335c, 0x8400ff98, 0xff053433, 0x34b3e3ff, 0x0000ff06, 0x254ccc4c, 0x00002305, 0x09833433, 0x3682ce20, 0x66660523, + 0x26068208, 0xff66e63f, 0x82cce9ff, 0x42392c20, 0xddffff90, 0x00ff9a19, 0x82662626, 0x825b2046, 0xdfff270a, 0x00ff866b, 0x2382662b, 0x84abb622, + 0x6622a182, 0x1a825866, 0x72830220, 0x0080f625, 0x83f7ffff, 0x19f730f2, 0x088b829a, 0xffff0685, 0xff32b373, 0x82b365ff, 0x0300267a, 0xffffce4c, + 0x212382f9, 0x62830100, 0xe683f820, 0x33f8ff25, 0x472b0834, 0x9f2219ca, 0x44829a19, 0x6666e623, 0x8293828b, 0x0ae44659, 0x3582eb20, 0x83070021, + 0x830220a7, 0x66072304, 0x6282ff68, 0x00ffcd26, 0x08008006, 0xb8267882, 0x9a00ff52, 0xf382cc4c, 0x52f8f928, 0xf6ffff06, 0x4482291c, 0xa67bf825, + 0x820800ff, 0x0200267f, 0x00ffb0b2, 0x242b8309, 0x81750e00, 0x31d482be, 0x00ff7b54, 0xff7c5449, 0x48215b00, 0x942000ff, 0xfe83087a, 0xffff9925, + 0x829ad9d9, 0xcdcc267e, 0xbdc6ffff, 0x23448270, 0x089a19c0, 0xfa200682, 0x00259083, 0xfffff628, 0x23e582fa, 0x5c4f0000, 0x34200983, 0xe3263582, + 0xff0633b3, 0x46827800, 0xcc7bff2d, 0xff9105cc, 0x34b30200, 0x820500ff, 0x01003642, 0x8b920080, 0xf706ab08, 0xffff0714, 0x06666691, 0xb3ffffff, + 0x241c8233, 0xffffcc4c, 0x219983fe, 0x8e414c05, 0x20968208, 0x23348310, 0xff70fd2c, 0x23059668, 0x087c941f, 0x8a250a87, 0x1f00ff3c, 0x22f2824c, + 0x84d8e310, 0x828b2009, 0x1921231a, 0x0c838b9a, 0xef224d82, 0x2a83281c, 0xe0220982, 0x3584c475, 0xffffce28, 0xff846be0, 0x67820f00, 0x02d3ff25, + 0x87588b90, 0x055643c8, 0x7967c883, 0xb3fa2105, 0x902dc883, 0x0e060080, 0xff14f7ef, 0x66e66001, 0x05197615, 0x1400ff22, 0x22098941, 0x829a9919, + 0x82002041, 0xffff2706, 0xff6666eb, 0x04821600, 0x50e5ff21, 0x068305c1, 0x220c5c5c, 0x826666e6, 0x82ff202d, 0x00ff2406, 0x41717d15, 0x357706d3, + 0x5f012005, 0x0023050b, 0x82fe7f1a, 0x991422bf, 0x8222829c, 0x83ff2046, 0x2262885b, 0x86cc4cec, 0x99e42262, 0x18ed829a, 0x8b1111a0, 0x208b8462, + 0x82ac83e9, 0x212d829f, 0x9c835c00, 0xcecc5c3d, 0xedffff15, 0x00ff0080, 0x05482150, 0x60fbffff, 0xffff9f00, 0xff4801f2, 0x56e11000, 0x93210555, + 0x23218408, 0xecffff93, 0xfe223283, 0x0f8200c0, 0x81e2fa22, 0xe9211682, 0x23228261, 0x7ab89ef2, 0x2d83d982, 0x4882f720, 0x1ee7ff23, 0x201a82b8, + 0x222683f4, 0x82b81ede, 0xe6f02753, 0xf5ffff66, 0x0a8200c0, 0xa430fe28, 0x0c6000ff, 0x0c1905cc, 0x60211838, 0x055952e6, 0xff8b0024, 0x4383f8ff, + 0x0a820482, 0x0040f722, 0xff23f882, 0x8266e6a0, 0x82ef2045, 0x0a00226b, 0x20508340, 0x222282f4, 0x83e12100, 0xa0f733ba, 0xffffa400, 0xa0b8feee, + 0x42e9ffff, 0x0d00ff90, 0x88824861, 0x00c0ee2c, 0xebffff95, 0x00ffb89e, 0xba834001, 0x83908222, 0xed231682, 0x8283b81e, 0x820020e8, 0x1eef2211, + 0x22f882b8, 0x83774861, 0x47a12516, 0xdeafffff, 0xfb2db683, 0xff770060, 0x27600500, 0xc0eaffff, 0x2a4e8200, 0xffff919e, 0x080080f0, 0x834300ff, + 0x83b42048, 0x0a0021dc, 0xa3213c83, 0x2330825e, 0x70bd0100, 0xcf217f82, 0x2c2a825e, 0xffffcdcc, 0xffccccf3, 0x33331000, 0x8230828b, 0x8c8b2179, + 0x82065d45, 0x8209840b, 0x84112016, 0x82e02095, 0xa10c325c, 0x0f00ff48, 0xff89b8be, 0x48a11100, 0x00ff8108, 0x0530415c, 0x98008022, 0x4505665b, + 0xf7210535, 0x21278261, 0xd883e109, 0x48a1d424, 0x2e8205bc, 0x46224383, 0x0a824861, 0x42e00622, 0x0521e984, 0x207d828f, 0x25558280, 0x80b8de07, + 0x5b8300ff, 0xdef6ff2a, 0xffbe08b8, 0x0080dfff, 0x04262882, 0xffff7d9f, 0x218320fd, 0xff3b7f24, 0xce82feff, 0x21050027, 0xffffff48, 0x23de83a0, + 0x069a199f, 0x1f83f982, 0x83600021, 0xb87e2524, 0xc00100ff, 0x04200982, 0x0222a683, 0x4a8200e0, 0x84200021, 0x830c204a, 0x8309207e, 0xe107212a, + 0x0a239a82, 0x848f00e0, 0x20dd8271, 0x20d88306, 0x82998414, 0xffff27d3, 0x05b89eb9, 0xb682ffff, 0x06825a20, 0x5882f720, 0x82f6ff21, 0xfaff2237, + 0x20788281, 0x242b82f3, 0x0080feff, 0x28fa827e, 0x0040a3ff, 0xffff8905, 0x20eb83ee, 0x2376820c, 0x703df0ff, 0xd182e882, 0x21feff22, 0x0023fa82, + 0x82381402, 0x9ad922ab, 0x2405828c, 0x00ff66e6, 0x05a46200, 0xb81e1023, 0x217c828b, 0x6246e2fa, 0x02002205, 0x211b82a6, 0x31836110, 0xba1e0a27, + 0xa15c00ff, 0x26fc8248, 0xff442144, 0x82de4b00, 0x0d00268b, 0x00ff9c99, 0x3d57820f, 0x64660500, 0x331500ff, 0xfbffff34, 0x089f6866, 0xc2d2fdff, + 0x9cffff90, 0x5f153233, 0xae8202fb, 0x2482f920, 0x9eefff27, 0xffff93b8, 0x829683ed, 0xffff2455, 0x82b85ef9, 0x831020e6, 0x80f92fa1, 0x1200ff02, + 0x00ffb85e, 0xfffe3f08, 0x2e820600, 0x84100021, 0x9e1b27ab, 0x4500ffb9, 0xd1824821, 0x82120021, 0xffff28d8, 0xff48e1d6, 0x825e2e00, 0x4f022c80, + 0x02fba470, 0xd4ffff15, 0x83f768e6, 0xded62766, 0xd1ffffb8, 0x2c82b89e, 0xc0edff23, 0x21ad8200, 0x11829e1b, 0xad84ba20, 0x281c0433, 0x75f3ffff, + 0xffff97c4, 0xff6666f8, 0x64e60b00, 0x2f7f828b, 0x8b7cff03, 0x0000ff8f, 0x00ff00c0, 0xff3cdf03, 0x2206277f, 0x82e43a11, 0x66a62287, 0x21978293, + 0x6d469a99, 0x66102906, 0xaf0e0866, 0xf4f724f8, 0xff217482, 0x22168219, 0x820a57ff, 0x82fb20de, 0x00002421, 0x45ffa470, 0x382106be, 0x08098252, + 0x8b9a9923, 0x0614fb08, 0x80efffff, 0xff7b8b00, 0x84ebfdff, 0xb3f0ffff, 0xfcffff33, 0xff087c14, 0x67e6ffff, 0x0680418d, 0xe2fa0129, 0x0200ff8b, + 0x82081e05, 0x05352206, 0x070e511e, 0xffe2fa3a, 0x66e63500, 0x8bc0088b, 0xd5ffffb6, 0xff8b1e05, 0xe2facaff, 0x156b7b08, 0x5682ac82, 0x7a823482, + 0xcf824a82, 0xcc4c0422, 0xcc214e82, 0x22d382ce, 0x82ce4c04, 0x32b3260a, 0x330400ff, 0x82098232, 0x04002123, 0xc082ae84, 0x1100ff22, 0x14210f83, + 0x20f08280, 0x211e821a, 0x19820d00, 0x331d0032, 0xab088b34, 0xedffff06, 0xffff3433, 0x0566e6b4, 0x2006da45, 0x280f82f1, 0xcecc0c00, 0x0800ff79, + 0x226182cc, 0x8266e6eb, 0x4c0d2261, 0x0c7a7dcc, 0xb3f1ff23, 0x229c8233, 0x47cd4cee, 0xee200583, 0xf1218c83, 0x844a82b3, 0x220e8204, 0x826b088b, + 0xe6f6225d, 0x054d4a66, 0x82f5ff21, 0x20048557, 0x821383f3, 0x18082018, 0x8208e94a, 0x8339904d, 0x84ff2042, 0x0e002418, 0x828bcc4c, 0x34b329c5, + 0xfb07ab08, 0x076b0614, 0x9b827984, 0x22858482, 0x8882ff20, 0x4b187085, 0x368a0952, 0x4707cb21, 0x0021058e, 0x3984831a, 0xb33333e8, 0x7dfbffff, + 0x2d00ff70, 0xff08cccc, 0xc235e3ff, 0xdaffff06, 0x5782a470, 0x5c8fe127, 0x661e00ff, 0x20708266, 0x05a04625, 0x11820682, 0x84a47021, 0x00ff2816, + 0x8b5c8f25, 0x18068f08, 0x210bf5b9, 0xa083f5ff, 0x82f2ff21, 0x214182a0, 0x5a18b3f2, 0xf52a07c9, 0xffffcd4c, 0x8b00c0f2, 0x5f828708, 0x33f3f422, + 0xf7261d82, 0xffffcd0c, 0x5f82e6f7, 0x19f4ff38, 0x808b089a, 0xf30800ff, 0x00ff8233, 0x8bcd0c0b, 0x1f00ff08, 0x5b823333, 0x9a190c27, 0xcc3b00ff, + 0x24a182cd, 0x00ff9999, 0x2252822f, 0x82993a00, 0x4c0f2113, 0x0035b082, 0xff66e60c, 0x68660300, 0xb30c00ff, 0x0100ff34, 0x00ffcccc, 0x2653820e, + 0x0614f708, 0x1804fbb3, 0x821c7e6c, 0x820a202f, 0x05f24d34, 0xb8820d20, 0x1cc06b18, 0x20071b4e, 0x8381820a, 0x088b26e0, 0x00ff2f0e, 0x23c48206, + 0x34b30300, 0xf6316882, 0xffffbe5f, 0xff4821f5, 0x00200200, 0x40efffff, 0x21948200, 0xe3824200, 0x82b8de21, 0xc2442c59, 0xe4ffff90, 0xff054821, + 0x82e00900, 0x83f92015, 0x810d211f, 0x0228e282, 0xff9368a6, 0x98d90700, 0x5b202582, 0x002e2582, 0x0566e665, 0xbfb0ffff, 0x5700ffff, 0x0a8252f8, + 0x9ad98a34, 0xff0516fb, 0x00c0b301, 0x8b8b158b, 0x01ffb8fb, 0x63828044, 0x9a99fc27, 0x990400ff, 0x2138829a, 0x7882610f, 0x14820820, 0xde180026, + 0x0800ffb8, 0x25231983, 0x828b9042, 0x2006831a, 0x211684ff, 0x2083f6ff, 0xff282a83, 0x086666f8, 0xc0fcffff, 0xfa204582, 0xff251482, 0x50713dcb, + 0x272d838b, 0xff47214f, 0x0040a8ff, 0x2220a782, 0x2522cc83, 0x0a829a19, 0x28821c20, 0x831f0021, 0xa1042159, 0x2e206882, 0xff220e82, 0x68821eea, + 0x52462420, 0x7a542605, 0x544b00ff, 0x20ab827a, 0x211a82fb, 0xdc820700, 0x5ffaff2c, 0xffff91be, 0xff4220f9, 0xdc830300, 0x82d7ff21, 0x1b002615, + 0xffffba9e, 0x280983a9, 0x5f462102, 0x40e2ffff, 0x22888200, 0x82cd0cf9, 0x6826308d, 0x66faffff, 0xffff8566, 0xff33b3fb, 0x83c0f8ff, 0x68d4271a, + 0xb6fffff5, 0x5b8252b8, 0xa983fe20, 0x0483fd20, 0xb85edc2a, 0x66c4ffff, 0x3000ff66, 0xff238f82, 0x829919ca, 0x19f827e8, 0xecfeff9a, 0xaf82cccc, + 0x42000830, 0x20f7ffff, 0x0d00ff00, 0xffff0661, 0x098260fe, 0xbe830920, 0x53830620, 0xe1440022, 0x1b22c482, 0x2982b8de, 0xc2f50b2a, 0xfa0700ff, + 0x0200ffe2, 0x00363e82, 0xffcccc10, 0x3233f6ff, 0xcc0a00ff, 0xf70e08ce, 0x1554f7d4, 0x0b1affff, 0x34200c97, 0x20057443, 0x22068508, 0x430e00ff, + 0x002607f1, 0x8b34b311, 0x4418eb08, 0x8b2f0f3b, 0x56606056, 0xfeff088b, 0x069a99eb, 0x820800ff, 0x090022da, 0x22ba82e6, 0x4299990a, 0x0a2206b7, + 0x478234b3, 0x60323321, 0x2382059a, 0x46686621, 0x0920060b, 0x06218a83, 0x221e8233, 0x829a9909, 0x66e3221e, 0x0c7e4466, 0x180adb43, 0x20161172, + 0x27ff822b, 0x8b9a19ca, 0xc08bb660, 0x0025b382, 0xb666e635, 0x057556ff, 0x97820a82, 0x23820b83, 0xfe83ea20, 0x00801e2a, 0xccebffff, 0x2400ffcc, + 0xff243282, 0x66661d00, 0x99453384, 0x4b8b2c21, 0x8b8b2b2b, 0xeb062b08, 0x181514f7, 0x211a9b42, 0xa84484ab, 0x0e002305, 0xba187c54, 0x63181223, + 0x4c200ea6, 0x5f418982, 0xfeff220e, 0x251582d6, 0x343398fe, 0x704bff15, 0x05cc4e05, 0x8dcdcc21, 0x08ce2c0e, 0xb3fbffff, 0xffff8633, 0x839919fc, + 0x8232200a, 0x22248309, 0x820080fc, 0x99ff211a, 0xff221482, 0x34829a99, 0xb3210989, 0x200e8333, 0x211e829a, 0x4e824cfa, 0x66e6f922, 0x80213382, + 0x82048400, 0x8b8b2adc, 0xcb8beb2b, 0x00ff8b08, 0x24198235, 0xe1fa2a00, 0x2b0a82b6, 0x088b1f05, 0x60b68bc0, 0xcaffff8b, 0x2005d44c, 0x205683e2, + 0x206b83eb, 0x212782db, 0x7f83eaff, 0x7584e120, 0x3433f42a, 0xccf0ffff, 0xf5ffffcc, 0xf2257583, 0xffffce4c, 0x202d83f6, 0x243983f5, 0xffff058b, + 0x291c82e8, 0xcccc6700, 0x1200ff15, 0x6a829a99, 0x67660d23, 0x12e541ff, 0x3f82f220, 0x6b057a42, 0xff230569, 0x82e13aef, 0xc5f02681, 0xf1ffff1e, + 0x0fa342b3, 0xe23a0f22, 0xff231684, 0x82c51000, 0xcb0e21ae, 0x21058c4c, 0x3282064b, 0x93828420, 0x83640021, 0x839b20ef, 0xb37b277b, 0xfb088b33, + 0x19820714, 0x9018ed20, 0xf12008d7, 0x0021a382, 0x05115310, 0x47820683, 0x82323321, 0x66662196, 0x20065b4f, 0x203083f7, 0x3d3b8200, 0xb39bffff, + 0x6500ff33, 0xffff3333, 0x8bcd4c84, 0xff14f808, 0x9a193f00, 0xabffff15, 0x548200c0, 0x9ad9b622, 0x20067a5d, 0x31c282d9, 0x3433bbff, 0x1b00ff08, + 0xffff01c0, 0xff48e1e1, 0x73821400, 0x3ddbff2d, 0x0a00ff70, 0xffff00c0, 0x824761d7, 0x8370201e, 0xb30b2798, 0x00ffe333, 0xdb82335f, 0xe673002d, + 0x064b0866, 0x54f8eb0e, 0x1800ff15, 0x180bb09a, 0x2308b35b, 0xf4f7076b, 0x420c2943, 0x6c471159, 0xf4fb240f, 0x47f4fb06, 0x5b181752, 0x87470d59, + 0xf4f72308, 0x5c186b07, 0xaa410c36, 0x84ab260e, 0x540e00ff, 0x2004837b, 0x26a9827c, 0x088b85ab, 0x82ab06ab, 0x11002364, 0x1a8886ab, 0x1a867a20, + 0xfbf4f723, 0x0c3c4334, 0x200aca41, 0x05ea52fb, 0x21125e48, 0xc27694fb, 0x18818a0c, 0x200c1948, 0x826e82cd, 0x1100383d, 0x088b33b3, 0x0e0694f7, + 0x1554f78b, 0x8d00ff8b, 0x00ff6666, 0x869a9972, 0x3fd11804, 0x09d01810, 0x6b118311, 0x4a6e05f0, 0x05316f07, 0x54854987, 0x00ff082f, 0xff9a19a4, + 0x0080baff, 0xfaffff15, 0x05485833, 0xf5ffff23, 0x276f82e6, 0xff32b300, 0xcd4cf9ff, 0x34211883, 0x820a8808, 0x83ff2014, 0xe6f52714, 0x0500ff68, + 0x1883cccc, 0x4882cc20, 0x34331623, 0x05f24eff, 0x14832620, 0x5782e420, 0x33360026, 0xc3088b34, 0x26206b82, 0x00214b82, 0x2255831b, 0x4ece4c16, + 0x3c8505eb, 0xb3060022, 0xff203682, 0x0a221483, 0x4b849819, 0xce201883, 0xcc206f84, 0x8e822385, 0xffff6822, 0xa2822383, 0xcc269384, 0xffff7908, + 0x7b824ceb, 0x0080e125, 0x83eaffff, 0xb3d3217a, 0xff296b82, 0x0080d5ff, 0xe1ffff8b, 0x20c08266, 0x20878315, 0x288783ee, 0x0834b314, 0x00ff068b, + 0x2132820c, 0xec849500, 0x43097b49, 0xcd230f8b, 0x830e00ff, 0xb3f122e0, 0x106b1833, 0x99112208, 0x20c5829a, 0x8255830e, 0x220a821b, 0x1833b311, + 0x2109c747, 0x32839a99, 0xee278d82, 0x088b6666, 0x827c00ff, 0xc6ff2427, 0x4a156666, 0x172006ce, 0x0023a482, 0x43343323, 0xff240588, 0x0080e8ff, + 0x05202582, 0xff2c8c82, 0x9567e6f8, 0x99feffff, 0x0700ff99, 0x0522a983, 0x1a82cd4c, 0xff240a87, 0x66660100, 0xfa221f82, 0x1f8432b3, 0xd9820820, + 0x28206c83, 0xff215082, 0x215083c3, 0x0f82e1ff, 0x83d7ff21, 0x83ff2050, 0x05646e25, 0x81203582, 0xff203084, 0x33201482, 0x0a835086, 0x51839520, + 0x85516720, 0x27708205, 0xaf0e0899, 0x54f7b4f7, 0x17cc7318, 0xdcffff2e, 0xff8b33b3, 0xcd4ce3ff, 0xb31c00ff, 0x2322c083, 0xf883cc4c, 0x11852320, + 0x16833320, 0x0e820482, 0x1c82f883, 0x11f9c018, 0x4394f721, 0x1c4b1931, 0x0c534b09, 0x06d4fb22, 0x44059a44, 0x642206aa, 0x5782cc4c, 0x34b37b22, + 0x06827a83, 0x6400ff22, 0x16827f83, 0x7b00ff22, 0x82054a56, 0x83228215, 0x73101911, 0x4cc1250d, 0xe6ffffcc, 0xc72a0483, 0xffff6866, 0xff0080d6, + 0xc382d7ff, 0xa300ff2c, 0xfb063433, 0xc015cbd4, 0x7747b68b, 0xff602609, 0x9a192a00, 0x23cc8256, 0x9a19caff, 0xd5239e82, 0x18ff66e6, 0x180a654c, + 0x2f0eea49, 0x14f9ef0e, 0xffbf01ff, 0xfeff15ec, 0x07140070, 0xc2273082, 0xffff9a19, 0x8368e6cd, 0xff662804, 0x9819c2ff, 0x824e088b, 0x82ce2017, + 0x30002179, 0x2a06b354, 0x993c00ff, 0xfeff0898, 0x82f66890, 0xcecc2be2, 0xeeffff05, 0xffff33f3, 0x328266fb, 0xf668ee23, 0x270a8295, 0x00ff235b, + 0x089a1911, 0x5a270a82, 0x00ff9ca0, 0x825c0f0a, 0x9a992110, 0x0c2a0482, 0x0400ffcd, 0xff0832b3, 0x40824001, 0x4c570022, 0x01234082, 0x82cccc21, + 0x2300227f, 0x20218259, 0x2d67821c, 0x66a61c00, 0x4c2300ff, 0xf7088bcc, 0x0082ff74, 0xfb05ec28, 0xa0feff04, 0x456f1400, 0x18a58217, 0x182d0b5f, + 0x2913d673, 0x1c07feff, 0x9000ff28, 0x6682cd4c, 0x146efb22, 0x1921ae82, 0x21bd8299, 0x09824821, 0x82008021, 0xec112104, 0x9920bd82, 0x002cd882, + 0xff295c2e, 0x66660c00, 0x1400ff05, 0xff23b182, 0x8234b3b2, 0x4c02250a, 0xf7ffffcd, 0x08212a83, 0x220982cc, 0x5fccccfb, 0x00290555, 0x08676601, + 0xe61e00ff, 0x210f8267, 0x2982cd4c, 0x24830820, 0x824c0221, 0x8305201f, 0x202e8463, 0x204882fd, 0x20188200, 0x05214408, 0x844d0021, 0x662e2129, + 0x69853482, 0x2a831120, 0x9a990422, 0xff218e85, 0x825e83f5, 0x827a200e, 0x6629275a, 0x65ffff66, 0x5a826866, 0xff231182, 0x82e6eeff, 0x2920830f, + 0x0080eeff, 0xfbffff7a, 0x56826666, 0x4b826520, 0x99d6ff24, 0x2082059a, 0x84a4f021, 0x26098215, 0x00ffc275, 0x8234330a, 0x856b220e, 0x2e25829c, + 0xff0a97d6, 0x99999a00, 0xf8ef0e05, 0x1834f834, 0x2e178cbc, 0x00ff075b, 0x06cccc30, 0xcc1000ff, 0x7dff8bcc, 0xf820054e, 0x0a2dd783, 0x087e34b3, + 0xe63900ff, 0xb8ffff64, 0x456d8219, 0xf820052b, 0x002a9382, 0x82343303, 0xf6ffff8b, 0x6982cccc, 0x46b3a521, 0xff291877, 0x6866feff, 0xffff8c06, + 0x22e583fa, 0x82989900, 0x34b32109, 0xfa233982, 0x82080080, 0x82d32006, 0xdcff2116, 0x0484b583, 0x8b200e82, 0xc3185082, 0xcb1809df, 0x05200da1, + 0x00229683, 0x266d9a99, 0x202d820a, 0x89bd825c, 0x959a2061, 0x18332061, 0x220daa4e, 0x82cdcce5, 0xcce8257d, 0x0c00ffcd, 0xff284f82, 0xff6666f1, + 0x66661300, 0x0a834e82, 0x83ecff21, 0x211e8314, 0x1982f3ff, 0x2e83ff20, 0xd3221a82, 0x3582ebd1, 0x142edc23, 0x21978aff, 0xf542c4f7, 0x439b1809, + 0x23003307, 0x088b9a59, 0xf706f4f7, 0x5dffff0b, 0xff159a19, 0xbb83feff, 0xee830120, 0x34b3fd26, 0x190100ff, 0xfd22a882, 0xee839899, 0x3433cf3c, + 0xff074b06, 0x98196800, 0xceffff06, 0x00ff68e6, 0x059a193d, 0x12ffff84, 0xeb4766e6, 0x0ab7470c, 0x4c16ca4b, 0xfb222d88, 0x9a82cbd4, 0x20198a46, + 0x088a46cc, 0x1120b282, 0x4905e844, 0x8d94094a, 0x32833320, 0x8683cc20, 0x088bcd25, 0x184b14fb, 0x930c616f, 0x85ab2131, 0x54203187, 0x106e7f18, + 0x2210a44a, 0x4a7b540e, 0x112706a4, 0x088b85ab, 0x18abef0e, 0x2208dd8c, 0x56707de5, 0x240806ed, 0xfff668eb, 0x299c1900, 0x01ff088b, 0x069a191f, + 0x911300ff, 0x00ff8bec, 0xff1ec510, 0x00c00b00, 0x780700ff, 0x080e8252, 0x085ccf29, 0xfd85feff, 0x2701ff70, 0x8b050cd7, 0xb3eafeff, 0x02ff0532, + 0x45cccc56, 0xa6ffff15, 0x00ff3cca, 0x0586eb45, 0x820f00ff, 0xf4ff2323, 0x0a82e2fa, 0x50381522, 0x60838082, 0xa4301d22, 0xe321b882, 0x22588218, + 0x82be8019, 0xe600236a, 0x0c830766, 0xff231c82, 0x8214eee2, 0xc2f5261c, 0xaeeaffff, 0x2c308214, 0xff08d863, 0x666692ff, 0x70b4ffff, 0x294682a4, + 0xff060000, 0x00806bff, 0xa9826b05, 0x867a1421, 0xbc002111, 0x42828082, 0x90821a22, 0x04823882, 0x97140028, 0xe6ffff0a, 0xca82d663, 0xff00ff23, + 0x213482fa, 0xdc82e8b4, 0x1ccf3b25, 0x18ffff05, 0x2b3684bd, 0xffff21d0, 0xff1a8ff5, 0x27d10100, 0x1884bd18, 0x18132e75, 0x221484bd, 0x75ff1283, + 0x3008142e, 0x7cf770fb, 0xffff157b, 0x0671fdd7, 0x4c7500ff, 0x00ff07cc, 0xff8f8244, 0x48e10f00, 0x7d3100ff, 0x3f00ff70, 0xffffe0fa, 0xff6866f9, + 0x723d4a00, 0x268a8208, 0x00ff281c, 0x829a19b2, 0x4cff27da, 0x0800ffcc, 0x1f820040, 0xff9a1924, 0x09830600, 0x66e6f723, 0x2925828b, 0x06156e20, + 0xdef7ffff, 0x1c828bb8, 0x82b81e21, 0x82c02004, 0x84ff2026, 0x00c02221, 0x26468208, 0xffff4821, 0x8266e64d, 0x5ff92546, 0xb5ffffbe, 0x00281f82, + 0xff8a8131, 0xce0cc0ff, 0x85228482, 0x25827b1f, 0x82cc8a21, 0xd7ff2791, 0xff06e1fa, 0x4c84e9ff, 0x4c83ee20, 0x57820482, 0x48e1e923, 0x2b068208, + 0xff00a0fb, 0x42a00300, 0x60fcffff, 0x04220982, 0x80824260, 0x00d00023, 0x83d18201, 0x821c850c, 0x8b002521, 0x600400ff, 0x00267c82, 0xffa60600, + 0xb3821600, 0x82eeff21, 0x11002304, 0x5e8266e6, 0x652ab885, 0x34f852b8, 0xa400ff15, 0x3f829a99, 0x7a140724, 0xa782053b, 0xcd822e20, 0x23070032, + 0x0e05dbd7, 0x1c01ffef, 0x14f766e6, 0xc3ffff15, 0x00223c83, 0x21820e00, 0x108ab818, 0xae87a822, 0x24071263, 0xff5866ed, 0x0eb84d00, 0xbf01ff2a, + 0x00fffeff, 0x05000100, 0x03210582, 0x21c78280, 0xa083f9ff, 0x0b820020, 0xf1223882, 0x1782b8de, 0x82560021, 0xee0b2b5a, 0xbf00ff16, 0xff05aafe, + 0xa8835901, 0x66e66a22, 0x06217b82, 0x21eb8280, 0x3e8380c3, 0x70bd3022, 0x0024cd85, 0xbdf6e821, 0x3923e482, 0x82080080, 0x874f2506, 0xbfffffae, + 0x00290482, 0xffec913f, 0xb85eb1ff, 0x2259828b, 0x82295cba, 0x57c6316c, 0xceffff0a, 0xffff146e, 0xff33b3f2, 0x1e45beff, 0x72271a82, 0x00ff5e8f, + 0x424c176f, 0x6f2a08b5, 0xfaffffe0, 0x00ffaec7, 0x1e82ac01, 0x0ad7fa22, 0xf8224083, 0x408248e1, 0x5ceff831, 0xd8fcffff, 0xfbffff10, 0xffff3148, + 0x7710f8f9, 0xcf210de4, 0x07b542df, 0x2b05e477, 0x02ff087c, 0xffd00250, 0xacfc2ffe, 0x2509e477, 0x0f00ff0a, 0x5f825c0f, 0xcd82e020, 0x4821082d, + 0x670a00ff, 0x00ff08ee, 0x82c03508, 0x826c200a, 0x13e47752, 0x44f72f29, 0xffff158b, 0x83cd4cf7, 0x22bf8388, 0x8234b3f8, 0x4cf7290a, 0x075b08cc, + 0x07bb06ab, 0x082cfd82, 0xffff34b3, 0xffcdccf8, 0xcc4c0700, 0x33242c82, 0xeb088b33, 0x40203684, 0x21155a5a, 0x838240f7, 0x6f180720, 0x08200843, + 0x8305257b, 0x86428206, 0x05b55a1b, 0x8207886b, 0x85cc205e, 0xf7ff2a1b, 0x088b3433, 0xa8f700fb, 0x26bc8215, 0xffff7b34, 0x824861e7, 0x37012ce6, + 0xfcffff0a, 0x00ffe15a, 0x82f62805, 0x230f833c, 0x1fa50300, 0x2582e283, 0x9e180023, 0x822582b8, 0x21358205, 0x0a82f833, 0x60a50327, 0x380100ff, + 0x222b8210, 0x83f02705, 0x84a0203b, 0x8408200f, 0x21258651, 0xd683f7ff, 0x9a991829, 0xfeffff05, 0x82fff6c8, 0xffe22651, 0x0ad7faff, 0x820f858b, + 0x821e2071, 0xcaf72230, 0x2135823d, 0x25826666, 0x6666e723, 0x203582ff, 0x220a82cc, 0x82a05afc, 0xf0c72125, 0xfa222b82, 0x3b8310d8, 0x0f846020, + 0x51829282, 0xcb212582, 0x2c878244, 0xff9a19ac, 0x9a9970ff, 0xdfffff15, 0x253b82e6, 0xffcccce8, 0x1483d9ff, 0x8299f221, 0x43d62019, 0x0683052c, + 0x11261682, 0x0d00ffec, 0x2a82146e, 0xff14ee26, 0xf6281700, 0xbe217c82, 0x2f3582a6, 0xffc235e7, 0x3373d1ff, 0xe6c0ffff, 0x08418b68, 0xec207382, + 0x002e4882, 0xff1f850f, 0x0080f0ff, 0x231300ff, 0x79828bd7, 0x0a575d25, 0x8207cb06, 0xc01121f4, 0x0e211482, 0x82048740, 0x088b240e, 0x7c0614f7, + 0x4a7c05b4, 0x074b2310, 0x3a8300ff, 0x28214782, 0x203d82f6, 0x8252830f, 0x250a8204, 0x08343313, 0xa050d58b, 0x3f002605, 0xffff9819, 0x27b882be, + 0xcecc1800, 0xeffeff08, 0x0024d282, 0x1566665b, 0x8023b782, 0x82ff0600, 0x18cd2016, 0x2407da4b, 0xffff9919, 0x224783d8, 0x839a9941, 0x2706839a, + 0x333800ff, 0x2700ff32, 0x18221683, 0x0e8234b3, 0x08008022, 0x21423b87, 0x42eb2014, 0xcc200a82, 0x20088242, 0x21508234, 0x7183f2ff, 0x4ce7ff22, + 0x38201682, 0xff235082, 0x85ceccc7, 0xf3d2195a, 0xe6c7220d, 0x23888567, 0x3333e7ff, 0x08219c84, 0x203b86ff, 0x0ac142f7, 0x2008f842, 0x2171822b, + 0x2a82f7ff, 0x2405b455, 0xffcdccf8, 0x249a8300, 0x15e3b308, 0x061f448b, 0x6f821520, 0x83110021, 0x801a26fc, 0xf7088b00, 0x0db47424, 0x21095645, + 0xec540773, 0x065b2206, 0x05705456, 0x0e07a33a, 0x1201ffef, 0x24f734b3, 0x9affff15, 0xff069999, 0x5c4fa0ff, 0xb2ffff8b, 0x279eb019, 0x82d6a321, + 0x3313226e, 0x12a84134, 0x5f00ff24, 0x4a8232b3, 0xff666626, 0x9a994d00, 0x4c2d5a82, 0xff088bce, 0xcc4ccdff, 0x00ff15bb, 0x26e58346, 0xcc4c3900, + 0x833900ff, 0x46002473, 0x8208a4b0, 0x05e37a46, 0x8434b321, 0xffff2416, 0x83cc4cb9, 0x4cb92234, 0x239682cd, 0xff33b3c6, 0x7a0add7a, 0x288205e4, + 0xb1194c20, 0x01210d70, 0x22558398, 0x829a9979, 0x4cf632d5, 0xffff9408, 0xff04cbf0, 0xf873ffff, 0xfdf6ffff, 0x21048270, 0x8882ee47, 0x34f3a832, + 0x40a2ffff, 0xffff0501, 0xff289cd9, 0xd7632600, 0x53180a82, 0xc3303725, 0x00ff0553, 0xff008004, 0x4c77fbff, 0x190600ff, 0xfd20f182, 0x00210e82, + 0x051a5006, 0x00700023, 0x26168206, 0x00fff087, 0x82002000, 0x60302609, 0xc40200ff, 0x21348218, 0x0482a470, 0x08f0c725, 0x8204f7f3, 0x00092143, + 0x09220e82, 0xb0825eba, 0xff686625, 0x82330f00, 0x4cf62aa5, 0x0e0894cc, 0xf784f8ef, 0x22d38274, 0x82b85eb0, 0xa1bf26fa, 0xbfffff48, 0x230a839e, + 0x084861b0, 0x06821182, 0x4000ff23, 0x22168561, 0x824f00ff, 0x8508201b, 0x83168506, 0x848b201b, 0x832d8210, 0xffff241e, 0x859899bf, 0xb0ff281b, + 0x088b6866, 0x8234fbbb, 0xc0c9215f, 0xff23aa82, 0x8266a6fa, 0x99fb2253, 0x829c829a, 0x00ff24c2, 0x82ce4c05, 0x7746204e, 0x0824059e, 0x00ff04d6, + 0x2107e77c, 0x0e8200ff, 0x1c828b20, 0x88d60822, 0x07236082, 0x18ff7829, 0x230a0968, 0x06ab075b, 0x0be9a518, 0xf8221a86, 0x86826210, 0x0682ff20, + 0xcc262c82, 0xf7ffffcc, 0x04823809, 0x8b343327, 0xf7d4fb08, 0x5c224214, 0x04fbeb23, 0x2ca88215, 0xffcc4c13, 0x94380300, 0x851200ff, 0x24e08220, + 0x00ff70bd, 0x05606011, 0x8262f021, 0x9899260f, 0xb3edffff, 0x21238234, 0x09823433, 0x829a1921, 0x122743e3, 0x8bcc4c27, 0x4ca0ffff, 0x23ce83ce, + 0xff66e6ec, 0x27100b45, 0x0a576801, 0xd2ffff06, 0x1f204a83, 0xe220ea83, 0x34227883, 0x83829a99, 0x9a993b3a, 0xffef0e08, 0x9a19a901, 0x66ddffff, + 0xffff1566, 0xff6eb2fd, 0x00400100, 0xbb210982, 0x21098224, 0x09821a4f, 0x8254c321, 0xfa5e2609, 0xf8ffff08, 0x2d96822e, 0x05ca81fb, 0xfff9ffff, + 0xfcffff7c, 0x0982fa7e, 0xff0a2c26, 0xea26feff, 0x14210982, 0x22a6837a, 0x823e4af5, 0x94f52795, 0x0400ff7a, 0x3582f47d, 0xfff62826, 0x0c420800, + 0xed264082, 0x00ff0a97, 0x30821714, 0xb81ef227, 0x0f1800ff, 0x261e825c, 0x00ffec11, 0x8200c019, 0xa5fa251e, 0x1200ffe4, 0x00231482, 0x82eab107, + 0x5ccf2109, 0x7c21d182, 0x223d82ac, 0x8208b85e, 0x9c042105, 0xab215282, 0x277e8244, 0xff00efff, 0xfa9e0200, 0x0582c682, 0x0000ff23, 0x210f8311, + 0x4482f49d, 0x5258f822, 0x76212582, 0x20258204, 0x22f683f3, 0x82f8f306, 0x66e63064, 0xb40c00ff, 0xfffffffe, 0x00ff8ec2, 0x8252b80d, 0x83f12729, + 0x0300ff96, 0x7b57bef4, 0x02002305, 0x0982cc4c, 0x44052a44, 0x6a411192, 0xa37a2821, 0x00ff06d6, 0x821cba05, 0x2c052794, 0x0100ff4a, 0x89821cba, + 0x8290c221, 0x047621a9, 0xfd226f82, 0x0f82a0ba, 0xffe8fb26, 0x3869feff, 0x50212982, 0x212983e4, 0xda8290c2, 0xea260926, 0x36ffff07, 0xe222a583, + 0x81429a99, 0x01ff295c, 0xff008082, 0x34b38aff, 0x02236682, 0x829900a0, 0x830e2084, 0x60fd2311, 0x8a829900, 0x00c01925, 0x828e059a, 0x00a021bd, + 0x60200482, 0x03280482, 0xff8a0080, 0x00600300, 0xf921c382, 0x20108240, 0x202e8315, 0x280482f4, 0x48a11300, 0x1000ff7c, 0x211a8340, 0x1a82c0fd, + 0x15820220, 0x83fcff21, 0xa0002324, 0xe9828800, 0xe6201a84, 0xff2c1082, 0x05b81ef1, 0x1ef5ffff, 0x0900ffb8, 0xf3200f83, 0x5e462a82, 0x83f22005, + 0xc0042109, 0x00244482, 0x07ffdf1d, 0x6c829082, 0xfdffff28, 0xff8e0080, 0x5683fcff, 0x7c824c82, 0x00c0e926, 0xe9ffff90, 0xff213c83, 0x20c382e0, + 0x221a82ea, 0x8220fbff, 0x21258437, 0xad82ffff, 0x82fdff21, 0x828b2077, 0x83a02036, 0x1ee22516, 0xffff07b8, 0xff215f83, 0x217387fb, 0x3683f8ff, + 0xff238783, 0x8201c0f6, 0x28e62756, 0x0e00fff6, 0x9d8214ee, 0x8220fd21, 0x830120c3, 0x88c3831f, 0x248b8450, 0xffff7c08, 0x831a83ef, 0xecff26f9, + 0xffffb85e, 0x240483f9, 0x080080ea, 0x2470848a, 0x600100ff, 0x83098206, 0xdf0222ce, 0x20fd82fa, 0x24848260, 0x00c01900, 0x225b837c, 0x827d0080, + 0x84f12098, 0x240b821d, 0xe6ffff08, 0x20198240, 0x82278488, 0x22768404, 0x848c0080, 0xff08244b, 0x18a00600, 0x2107ab5a, 0x6675810b, 0x829a2005, + 0xb89e2181, 0x02201a82, 0x4983e984, 0x24830320, 0x8e20f882, 0xc0207c82, 0xe1216d84, 0x25cd8248, 0xff0548e1, 0x0a820a00, 0xd282e382, 0x2a820c20, + 0x427df784, 0x40fb2105, 0x41071c41, 0xff210529, 0x24508200, 0x0300ff88, 0x82718240, 0x2c61824c, 0x86486116, 0x9e1600ff, 0x0000ffb8, 0x26418220, + 0xff024015, 0x82e00400, 0x22258437, 0x41a00000, 0x8e2005ed, 0x8205ad41, 0xe11d2431, 0x84ff0748, 0x0400215f, 0x0020ca82, 0x00217383, 0x84518207, + 0x09002187, 0x00217383, 0x42198219, 0x00220509, 0x6c82e002, 0x1f83fe20, 0x09820320, 0x0e835086, 0x00800227, 0x00ff9a08, 0x200b8310, 0x0665420b, + 0x0600ff22, 0x00213982, 0x201a8215, 0x83a7828c, 0x9ffe22fe, 0x820982f8, 0xfdff211f, 0x01219583, 0x2c0582a0, 0xc035e6ff, 0xf40e00ff, 0xffff057c, + 0x281a838d, 0x15cccce4, 0x40e5ffff, 0x20e88200, 0x215083ea, 0x0a82c015, 0xc01a0024, 0xb8820800, 0xff210682, 0x86118200, 0x200e8204, 0x83c8828b, + 0x20118506, 0x823282ff, 0x823e8238, 0x2445832d, 0x4ceaffff, 0x820482cc, 0xe5ff3449, 0x088b3433, 0x00ffef0e, 0xf79a19df, 0x00ff1554, 0x8232b346, + 0x4c392253, 0x245848ce, 0x3333ba22, 0x22235848, 0x83cdcc45, 0x99332393, 0x2a495b9a, 0x21974414, 0x66661e32, 0xfeffff06, 0x00ff06c1, 0xfff08705, + 0xe6d0ffff, 0xc7260982, 0x0100ff6c, 0x09829425, 0x82e2ba21, 0x470e28f3, 0x4700ffae, 0x8205f668, 0x68f13615, 0xb90900ff, 0x0400ff16, 0x00ffa6bb, + 0xff46d608, 0x06010700, 0x24258292, 0xff52b82d, 0x2e048200, 0xe0ffff05, 0x00ffdcd7, 0xffb8de1d, 0x82e6d5ff, 0x6612272f, 0xd1ffff66, 0xab830080, + 0x32b36025, 0x468bffff, 0x7c260550, 0xfdffff6a, 0x7f82ee7c, 0xff7a4926, 0x08ccfcff, 0x4d217f82, 0x21098290, 0x0a821283, 0x4f82f120, 0x97b8ff23, + 0x274f820a, 0xfff4bdfe, 0x04b6f9ff, 0x8d2a9082, 0xfaffff0e, 0x00fff072, 0x73824c06, 0x02400122, 0x47270582, 0x00ff866b, 0x823e4a0e, 0x7b03279f, + 0x0000ff64, 0x1c47feb2, 0x01002805, 0x00fff2b4, 0x82548302, 0x18842104, 0x7d242982, 0x00ffcc4c, 0x53820482, 0x70fdb727, 0x024800ff, 0x360a8290, + 0xff82b582, 0x56ae82ff, 0x0201ff05, 0x00ff9a19, 0x1567e6a4, 0x83eaffff, 0x1c1522ba, 0x22208229, 0x82a4f0f1, 0x5c0f2960, 0x35e9ffff, 0xffff8bc4, + 0x04830f83, 0xd920a582, 0xd922e583, 0x7b822adc, 0xff214c82, 0x825682ff, 0x2126240a, 0x8200ff48, 0x220a8204, 0x82fcff0d, 0x281c283b, 0x1600ff8b, + 0x827dcccc, 0x0100260b, 0xf7ef0e08, 0x06164274, 0x18823420, 0x23546f4a, 0x34b33200, 0x210a1642, 0xb8821e45, 0x146eb227, 0x66b2ffff, 0x0a194866, + 0x2013254d, 0x05ae4601, 0x382c414b, 0x6666cc00, 0xffff157b, 0x066626b6, 0xf32d00ff, 0xdaffff34, 0x00ffcc4c, 0x2360821c, 0x9a99c7ff, 0xc0237282, + 0x8208cecc, 0x33f32a06, 0xfcffff32, 0xffff3433, 0x200483f4, 0x252083f9, 0x0866e6f5, 0x7d5d1ef7, 0x0e00210c, 0x0023a783, 0x82008012, 0x57003f34, + 0xffff0080, 0xff6866b8, 0x9a994700, 0xb3a6ffff, 0xff088b32, 0x66e6d0ff, 0x00ff15cb, 0xd182e63d, 0x19320024, 0xd218ff9a, 0xff24213e, 0xd8e3e6ff, + 0xe92b8582, 0xffffea11, 0xffec71f7, 0x8251edff, 0x0bf23004, 0x00ff0884, 0xff1e850b, 0x48e1e9ff, 0x830700ff, 0x3ae7229a, 0x222982e2, 0x826666e5, + 0xdcff2381, 0xb182e07a, 0x2b821120, 0x4961df2c, 0x57ecffff, 0xe5ffff0a, 0x3582156e, 0x3e4a1427, 0x82ebffff, 0x38ec828f, 0xffff9819, 0xff3333f3, + 0x34331f00, 0xff0e088b, 0x48a12d00, 0x407001ff, 0x3aa58200, 0xffb85e06, 0x0080feff, 0xc5ffff05, 0x84070080, 0xd9fbffff, 0xffff869a, 0x509a99f8, + 0x06830652, 0xff00a024, 0x04820400, 0xfef8ff27, 0x0600ffb8, 0x2233827e, 0x8248a1fb, 0x61f026eb, 0xc1ffff48, 0x213e83c0, 0x095340fe, 0x82032007, + 0x05635bab, 0x5f430520, 0xc0292505, 0x00ff0600, 0xff230c83, 0x82e00300, 0x2007214b, 0x22074945, 0x839af905, 0xff5f2446, 0x573f00ff, 0x802005bf, + 0x04221f82, 0x70826666, 0x92b99e26, 0x0800ff8b, 0x002ae984, 0x8600c008, 0x5e0700ff, 0x198284b8, 0x7b822120, 0x9e340025, 0x82bf07b8, 0x29bc83d9, + 0x42000000, 0xa1c3ffff, 0xae820548, 0x8982b920, 0x82390021, 0xc6ff2204, 0x204c82c0, 0x05ca5046, 0xff250683, 0x9a593800, 0x821b83ff, 0x2e108258, + 0x0000ff08, 0x00ff24e6, 0x0548613c, 0x825200ff, 0x13002332, 0x0a82b8de, 0x0a831220, 0x00600422, 0x16202682, 0xed20f783, 0x04224883, 0xab820080, + 0x9a99412b, 0x8e7e05b9, 0x61f2ffff, 0x236c8248, 0x8870fdf2, 0x66261583, 0xff055d66, 0xfa83edff, 0xb89efb22, 0xe9201882, 0x12264283, 0xffff4821, + 0xae82a1fb, 0x9139012e, 0x16ffffec, 0xff1534f3, 0xcccc98ff, 0x30820484, 0xcdcc9827, 0x336700ff, 0x310a8234, 0xffeb11ba, 0x34b3e9ff, 0x21cdffff, + 0xbfffff47, 0x45829819, 0x34b3b222, 0x21093750, 0x3750ae87, 0x7a01280c, 0xff0634b3, 0x82211300, 0x05c66987, 0x230afc4f, 0x4c4d00ff, 0xcd216582, + 0x25ef8219, 0xff66e640, 0x0983baff, 0xce4c162b, 0xf8ef0e08, 0x1534f7e4, 0x233a827b, 0x07cd4c4b, 0x2936e282, 0xffff0bd7, 0xff50f8e1, 0x32332600, + 0x5ed6ffff, 0x0400ffba, 0xd682e23a, 0xf628d022, 0xd4340a82, 0xd7ffff7a, 0xffff0080, 0x8b0080da, 0x19d1ffff, 0x073b089a, 0xff233f82, 0x829a99e5, + 0x66ea210f, 0x0dfc7a18, 0x53821420, 0xff261a83, 0x9a991500, 0x1e83ffff, 0x661a0027, 0xf7088b66, 0x737b1854, 0x83338318, 0x737b1824, 0xfb2b2710, + 0xffff1524, 0xe38261ee, 0x9ef1ff23, 0x080871b8, 0x08b89e22, 0x1120b982, 0x16841186, 0x1800ff21, 0x821b74aa, 0x244582a8, 0x99f1ffff, 0x82048298, + 0xeeff2c37, 0x088b6866, 0x1524f7ab, 0x82db064b, 0x863d83b2, 0x610e2247, 0x244c9d48, 0xc4fb073b, 0x5cf54aab, 0x153beb22, 0x083bdf82, 0x00ff08ac, + 0xffeebc01, 0xb0320800, 0x900200ff, 0x0700ffa4, 0xff087cd4, 0x824cf0ff, 0xb3042719, 0xefffff32, 0x1982cc4c, 0xff9a9926, 0xcecceeff, 0x3737764d, + 0x0634b32d, 0xf0f5ffff, 0x0d00ffa2, 0xffff6666, 0xff34b3f9, 0x00801000, 0x12258382, 0xf7089a19, 0x41005114, 0x2105ac42, 0x0051d623, 0x1cf8258b, + 0x24fb15c3, 0xf223f982, 0x828bcccc, 0x343321ff, 0x33200483, 0xf2230a82, 0x8508cdcc, 0x63ff2006, 0xf52605c2, 0x00ff3333, 0x3852400d, 0xe1951807, + 0xcb0e272b, 0xff1594f7, 0x3c821b00, 0x1800ff27, 0x00ff0080, 0x2004830b, 0x2a048311, 0x08004012, 0xffbc559a, 0x8240d8ff, 0x823a2017, 0xff082286, + 0x14ab4400, 0x2005b244, 0x05d444ff, 0x2d823920, 0x26baff2a, 0xff088b66, 0xb89ecdff, 0xd431a982, 0xffff00c0, 0xffb89ee2, 0x4821ebff, 0xa1d5ffff, + 0x2f1a8248, 0xa3cd8cee, 0xe6e3ffff, 0x0f00ff66, 0x8b6b00c0, 0xde27d283, 0x00ff48a1, 0x85b91e11, 0x1a00282d, 0xffff9002, 0x8200c0ee, 0xffe5212d, + 0xee220082, 0x0f8234b3, 0x4782de20, 0x32b3e22c, 0xdeffff8b, 0xf7089a99, 0xbf82eb24, 0x9a195f24, 0xce65ff06, 0x630e2006, 0x208206c0, 0xcc4cee26, + 0x0634fb08, 0x2206ec5b, 0x634c0e00, 0xff2e0ca1, 0xcccc8100, 0x192dffff, 0xffff159a, 0x5b8233ae, 0x66e69223, 0x250a8305, 0x6d00ff33, 0x0a829a19, + 0xf628af25, 0x83f1ffff, 0xa3c22750, 0xb9ffffd7, 0x55826666, 0x68e6aa22, 0xec22ac83, 0x245028dc, 0x54782107, 0x48073055, 0x2321070a, 0x227482d8, + 0x831e850f, 0x821e2021, 0x2613350a, 0x00ff0866, 0xff3e0a00, 0x98195500, 0x99c2ffff, 0x4600ff9a, 0xff2e0482, 0xff3233af, 0x34b30e00, 0xffef0e08, + 0x6a826e02, 0xe6b00023, 0x27908266, 0xff66e68c, 0x8f022d00, 0xfb2b8582, 0x00ff00e0, 0xff06a101, 0x6a81f7ff, 0xf63207fd, 0xffffb85e, 0x08fa3efc, + 0xd98cffff, 0xd2ffff9a, 0x298271fd, 0xc583f520, 0x66e6fb2a, 0xf6ffff84, 0x818b9a19, 0x9021a783, 0x25488266, 0xff00c044, 0xee82b2ff, 0x26400028, + 0xe6ffff66, 0x8e8268e6, 0x82a00921, 0x40fc2114, 0x08215c82, 0x21048260, 0x04822002, 0x0e830420, 0x00a00122, 0x33221e82, 0xd6820240, 0xa8821920, + 0x98995125, 0x834500ff, 0x7d002afc, 0x8b086666, 0x00ff8495, 0x6b9f8209, 0x042205d9, 0x85829a19, 0x34b38132, 0xb340ffff, 0x00ff1534, 0x073233bd, + 0x805f00ff, 0xda225d82, 0x9682b89e, 0x6866fa2f, 0xc7a8ffff, 0xc8ffffb0, 0xffff30b3, 0x218782cf, 0x1383ddff, 0x9a99ef29, 0xffa4fb08, 0x8266ce00, + 0x5b4d54f2, 0x99600026, 0xc9ffff9a, 0xff279e83, 0x8fcc4cf1, 0x82f0ffff, 0x06a750af, 0x49391252, 0x032d05f8, 0xff8b9c24, 0xf2d20200, 0x010100ff, + 0x3a098206, 0x00ffdce4, 0x08f6c800, 0x89cbffff, 0x2800fffe, 0xffff3869, 0xff6666d2, 0x68804500, 0xe52705ea, 0xffef0e08, 0x82195f00, 0x82e22093, + 0xff8b2293, 0x164d42ff, 0x8234b321, 0xa005224f, 0x225f8200, 0x82e01a05, 0x82a6205f, 0xb0042245, 0x3c6482a4, 0xff080661, 0x1e05fdfe, 0xa4cb00ff, + 0xffff0518, 0xff6766a2, 0x9899fdff, 0xccb3ffff, 0x210482cc, 0x56829a99, 0xcecca126, 0x1702ff08, 0x0827eb83, 0xff153233, 0x82e6eafe, 0xe6d92640, + 0x00ff0566, 0x22468336, 0x825c8f0e, 0x707d26a0, 0x633100ff, 0x226582d8, 0x8200403b, 0x38fe25b6, 0x4600ff54, 0xff2e1f82, 0xff9a99c7, 0x5c4f3900, + 0x66b8ffff, 0x1a828b66, 0x9919bb22, 0xc7205782, 0xc825c883, 0xffffec11, 0x232082fe, 0xae87baff, 0x66201a82, 0x00230a82, 0x82cc4c78, 0x82fb278c, + 0x0300ff8f, 0xa65a926d, 0xef230894, 0xcc5f01ff, 0x5000ffcc, 0xff1534b3, 0x9a192c00, 0xe8ffff07, 0x00ff34b3, 0xfffe7f0c, 0x66e6e5ff, 0x820600ff, + 0xe4ff210e, 0x4c0cc052, 0x592f0a11, 0xffff8b9a, 0x080040a0, 0x000000ff, 0x54ffff21, 0x8420052f, 0x3b593c82, 0x0603490a, 0x28dc0b28, 0x0900ff8b, + 0x5482c4f5, 0x5d465621, 0x003f058c, 0x08ce1709, 0x59c2ffff, 0x3d00ff9a, 0xff05ec91, 0x84ebedff, 0x191200ff, 0xf6ffff9a, 0x82a39819, 0x99192230, + 0x2121829a, 0x95823380, 0xcc4c6f22, 0x375ccf47, 0x999601ff, 0x93ffff98, 0xff153433, 0x34b3a5ff, 0x977f05e5, 0xb3efffff, 0x06217a82, 0x05c67fcc, + 0x1ec5b028, 0xeeffff06, 0xf7820040, 0x90c2f123, 0x985618ff, 0x00ff2c0a, 0xffc40300, 0xccccb0ff, 0x827a8b05, 0xa2a521de, 0xd9203b82, 0x0c29d882, + 0x087fc400, 0x4f5a00ff, 0x2155825c, 0xcb7fe2ba, 0xf3ff2806, 0x00ff0080, 0x82703d14, 0x674118e3, 0x7d5c270a, 0x5c00ff70, 0x25830080, 0xff849d26, + 0x1e850c00, 0x14232082, 0x85ffce4c, 0x252a8230, 0x49ffff08, 0x3b823433, 0x1866e621, 0x210ed790, 0x2b82b89e, 0x48610d23, 0x20068308, 0x215e8240, + 0x0487c00a, 0xb2820d20, 0x1c828482, 0x0a221b82, 0x4418b89e, 0xcb820bae, 0x2882f220, 0x83f5ff21, 0x82f52065, 0xf2ff2c37, 0x088b32b3, 0xf4f72f0e, + 0x8215d4f7, 0x4cb9271d, 0xc6ffffcd, 0x048334b3, 0xc5583320, 0x39002312, 0x5682cd4c, 0x33b34622, 0x8307f358, 0x052e4311, 0x15820020, 0x79828b20, + 0x58092159, 0xff290af3, 0x9a1971ff, 0xcc18ffff, 0x2cc982cc, 0xff66e6de, 0x34333700, 0xff06eb05, 0x270c83ff, 0xccccc8ff, 0x2100ff05, 0x84229683, + 0x0a829a19, 0x82802721, 0x82a120cf, 0x00ff2822, 0x7f32334d, 0x833b00ff, 0x33bd223e, 0x22a48232, 0x826866af, 0xefff277d, 0xffff9819, 0xab8233f2, + 0x0e820484, 0xfe237d82, 0x82866b7d, 0x07ef2254, 0x202882ae, 0x23e182f2, 0xcccc0d00, 0x1021b182, 0x233383e6, 0x98995000, 0x17264a82, 0x4200ff0a, + 0x5a82cecc, 0x97c33523, 0x06f15a08, 0x82865e20, 0x00ffcd32, 0x0566e67b, 0x94f8ef0e, 0xff15b4f7, 0x142e2c00, 0x23243f82, 0x00ffecd1, 0x0a820482, + 0x7e821082, 0x22641783, 0x18168305, 0x210969e8, 0x7882ecd1, 0x142edc22, 0x38831b82, 0xd1d3ff23, 0x832d82ec, 0x213f8206, 0x1684cccc, 0x33265482, + 0xfc088b34, 0x5fa18b14, 0x76843320, 0xcd205f83, 0x4782de82, 0x20075164, 0x826482ff, 0x825f8c6a, 0x821683a4, 0x152e215f, 0x00252d82, 0xfb66e6bf, + 0x22638234, 0x82f66839, 0xb02d27b8, 0x2e00ffa4, 0x0a825c8f, 0xa4703922, 0x00209582, 0xff240682, 0xc275d1ff, 0xff241684, 0xa470c7ff, 0xff233582, + 0x820a97c6, 0x4fd22258, 0x821b825c, 0xffff2a11, 0x085c8fc6, 0x19ffffff, 0x210a829a, 0x2c829a99, 0xff280482, 0xff6666d1, 0x66663900, 0x00253182, + 0x3b9a1930, 0x20568215, 0x31618310, 0xffe46503, 0x1ec50f00, 0x380500ff, 0x0e00ff92, 0x3c8266e6, 0x56aefd2c, 0x230000ff, 0xfdffffd8, 0x098268e6, + 0x82008021, 0x05a24f09, 0x34339c28, 0xb1ffff06, 0x74820080, 0x5482c020, 0x4cc4ff23, 0x200a82cc, 0x05e541b6, 0x3233f12a, 0xb30c00ff, 0xf4ffff33, + 0x00237f82, 0x8233b30f, 0x0a012670, 0x6a069a19, 0x06a34cff, 0x00234b82, 0x829a1928, 0x802d2a7f, 0xffff0800, 0xf766e647, 0x228e834c, 0x82f27205, + 0x7ffb256a, 0x2e0500ff, 0xa0217e83, 0x21098268, 0x2282ae47, 0x4d17f522, 0xfd210a82, 0x201a8270, 0x21568202, 0x7282f3ff, 0xc2281682, 0xff06152e, + 0x295ccfff, 0xd8217f82, 0x22ff828f, 0x823333d6, 0x80cc230a, 0x06820801, 0x82b3f521, 0xe3072c8a, 0xf7ffff12, 0x00ff9a99, 0x82a6bb09, 0xc700238a, + 0x33820080, 0x7b94eb27, 0xcc1700ff, 0x06dc4fcc, 0x01801e22, 0x212f8e82, 0xff0833b3, 0x02007001, 0xffff15a3, 0x82f628c2, 0x33f32227, 0x32498234, + 0xff84ebf3, 0x87f6fcff, 0x05f5ffff, 0xfaffff1e, 0x820808cc, 0x989921a8, 0xbd220a82, 0x05828c71, 0x7c66e621, 0x768305c7, 0xae87ea22, 0x60301182, + 0xecffff00, 0xffff0a17, 0xff9af9f6, 0x3e0aeeff, 0x15273182, 0x00ffce0c, 0x82a4f00b, 0x66e62579, 0x660700ff, 0x19200482, 0x1a823a82, 0xe07a2a22, + 0x25318082, 0xffff40ca, 0xff9042ed, 0x78541a00, 0xbde2ffff, 0x231a8270, 0x0688c103, 0xbe21bd82, 0x26208278, 0xff68e607, 0x82660800, 0x0a00236d, + 0x6d82ce4c, 0x7f330026, 0xd8ffffff, 0x00288a82, 0xffcdcc29, 0xd04ccfff, 0x4227e483, 0xffff3033, 0x82cc4c51, 0xfa2b08c7, 0x00ff98f9, 0xff900210, + 0x5c6ff7ff, 0x9c0e00ff, 0xf4ffff28, 0x00ff0cd7, 0x080a170c, 0x53feffff, 0x0100ff74, 0xffff6adc, 0x820035fd, 0x827720d4, 0xc4fd22b2, 0x2018829c, + 0x237c82b2, 0x7cd4ecff, 0xee222e82, 0x3e820514, 0xff6ce726, 0x12e30600, 0xb225d282, 0x0500ff2c, 0x26248264, 0xff34f3f5, 0x838a0300, 0x1d1723dc, + 0xa18207f4, 0x96830222, 0x23263b82, 0x0200ff94, 0x5482643b, 0x837c9421, 0x828e2054, 0x70ef2169, 0x0327f882, 0xffff16b9, 0x825c0fef, 0xf0e72bb4, + 0x2ef0ffff, 0xfcffff14, 0x1e82fa5e, 0x5278fe22, 0xaf213882, 0x210482de, 0x38823433, 0x8b34b322, 0x66210a82, 0x251a8266, 0x0790c2e9, 0x6b83ffff, + 0x76fcff23, 0x267f8288, 0xffffa2b0, 0x82e09afa, 0xf6e82693, 0x1cf9ffff, 0x272482ac, 0xff70bdec, 0xec110b00, 0xfd20a982, 0x0023ce82, 0x82924d01, + 0xfe342145, 0x88216982, 0x214982ee, 0x04822a3c, 0x829c2321, 0xd4f42729, 0xf3ffff7a, 0x3e8266e6, 0xff299282, 0xffd863f1, 0xec11fbff, 0x221a827b, + 0x828241ff, 0xee7c2534, 0x050100ff, 0xfd223982, 0xc7821e65, 0x82062421, 0x80ca2939, 0x1300ff08, 0xffff862b, 0x63823e82, 0x1824fe22, 0x94219282, + 0x22a4827a, 0x82c435f5, 0xe8db212f, 0x91250f82, 0xffff08ec, 0x855f83ec, 0xc4fd2125, 0xfe222582, 0x84827eca, 0x82ec1121, 0x9c642659, 0xbe0000ff, + 0x82638476, 0xee04264f, 0xefffff98, 0x21b882fd, 0x84828e08, 0x727df122, 0x6383c282, 0x5ccff322, 0x01201e82, 0x23213d84, 0x20838212, 0x223382b3, + 0x82f688ff, 0xe03a2109, 0x4d216c82, 0x221e8292, 0x86904213, 0x080027f1, 0xffff1018, 0xb7821cf9, 0x564e0931, 0x9bfaffff, 0x0a00ff64, 0xffffce0c, + 0x41c275fc, 0xa8820640, 0x6a7cfd22, 0xc5213b82, 0x207e821e, 0x228882c4, 0x82026b02, 0xf6882197, 0x10224a82, 0x2b82f6a8, 0xffea4625, 0x82d71000, + 0x8200200e, 0x0f00284e, 0x00ffecd1, 0x8206a103, 0x6b02220f, 0x21b78284, 0x3d82fe76, 0x826cdc21, 0x703b2183, 0x8205e941, 0x3d16231a, 0x6b830770, + 0x2b82cc20, 0x09319f83, 0x00ff5c4f, 0xffa26505, 0x0c170800, 0xe30600ff, 0x22248254, 0x42842b13, 0x00280645, 0xff182402, 0x6eb2feff, 0xe2214582, + 0x20548250, 0x22dd8277, 0x8388ac01, 0x82e62059, 0x820b2029, 0x0c002329, 0x3e829a19, 0x48828f20, 0x82990e21, 0x05052209, 0x21978220, 0x1e828e02, + 0x7cbe0022, 0x83213882, 0x20428212, 0x203382fa, 0x23e78202, 0xe8c3fdff, 0x35213d82, 0x21e78282, 0x1e82d4ec, 0x862b0b23, 0x21108205, 0x9682f8f3, + 0x82866b21, 0xcc0a22a8, 0x202f82cc, 0x223e820c, 0x86866b0a, 0x8500208d, 0x41022125, 0x0023a382, 0x828c5659, 0x98992155, 0x66212582, 0x21098264, + 0x4b820080, 0x68e69528, 0xb3beffff, 0xf9181534, 0x00200b9f, 0x134f8d18, 0x83ff7a21, 0x00ff2516, 0x8b86ab11, 0x11225e82, 0x748288ab, 0x78540e25, + 0x82f1ffff, 0x203e8411, 0x16876e08, 0xe0ef0e2c, 0x80c500ff, 0xff341500, 0xa68251ff, 0x6c020021, 0xce20057b, 0xf0222f82, 0x86826666, 0x7f1aff33, + 0xe6d3ffff, 0x3900ff66, 0xffff1b3f, 0xff9a19dc, 0x0c945300, 0x00403927, 0xe12300ff, 0x22738248, 0x8252382b, 0x10002368, 0xff82b81e, 0xff006025, + 0x82a1f8ff, 0x81a927f9, 0xac00ff48, 0x4c827cbf, 0x856bee2b, 0x192400ff, 0xcdffff99, 0x22358280, 0x82333300, 0x2204839d, 0x829a99dc, 0xf5e2251e, + 0x5affffc2, 0x23088d82, 0xfa4700ff, 0x8f00ffe2, 0xff059a19, 0x66264800, 0xe670ffff, 0xffff0566, 0x06b8de6f, 0xf0f201ff, 0x2501ffa6, 0xff222683, + 0x5b8261ee, 0x81822320, 0x8acdff28, 0x0000ff3c, 0x5082b81e, 0xdc230e83, 0x870848a1, 0x820120d3, 0x08002256, 0x82d3874c, 0xe1d321da, 0xb8833682, + 0x05ddff23, 0x21cf831e, 0xb84f8b02, 0x8298200a, 0xb8de21cf, 0x3a21cf83, 0x259582e2, 0xff50f8ff, 0xf7831000, 0xd04c0222, 0x9924d382, 0xa9ffff9a, + 0xb919be83, 0x48221071, 0xb4883e0a, 0x887c1421, 0x46e126b4, 0x34fbc306, 0x080f8415, 0x01ff062f, 0x0734b326, 0xd41400ff, 0x0900ff7a, 0x00fff41d, + 0xffd8e30f, 0x20d01100, 0x0f0700ff, 0x1500ff5c, 0xff080ad7, 0xce4c7e00, 0x1c2a00ff, 0x21ff822a, 0x1a82c510, 0x10980522, 0x1f832e82, 0x40201227, + 0x66faffff, 0x21938264, 0x9e8290c2, 0x086cfa22, 0xba260a82, 0xedffffe2, 0x238240f5, 0xff482126, 0xd623efff, 0x5e212382, 0x2b1e82b8, 0xff32b38e, + 0x703ddaff, 0xf2ffff05, 0x17273e83, 0xffff707d, 0x8266a6e6, 0x86eb2677, 0xb5e2ffff, 0x052648c2, 0xff8bec26, 0x7a14ddff, 0x2c0e8648, 0xfffc09fd, + 0x078f0000, 0x30fdffff, 0x210982a4, 0x09820050, 0x827c1f21, 0x2d842757, 0xd7ffffc9, 0x57820c02, 0x3333ef22, 0x66256d82, 0xf6ffff68, 0x210982f3, + 0x5c82e6ed, 0x0a970522, 0x4c218682, 0x259b82cc, 0xff117804, 0x0f82f2ff, 0x7b0c002d, 0xf7ffff23, 0x00ffae87, 0x82f6680d, 0x03002976, 0xff8b1058, + 0x8c6c0300, 0x84215a82, 0x260982c2, 0x00ffac5c, 0x821c2001, 0xab872b35, 0x2d00ff84, 0xff056a3c, 0x5a830400, 0xceccfc22, 0x5a821f82, 0x33fdff26, + 0x0500ff32, 0xcc270984, 0xfeff08ce, 0x64cc4ca9, 0x3424053f, 0x330700ff, 0x0c256818, 0xdf00ff24, 0x94619819, 0x0700230c, 0x7282fc29, 0x9eef0723, + 0x25068208, 0xff66661b, 0x5e82ebff, 0x80150022, 0xe42bd982, 0x088b9a99, 0x02ffef0e, 0x4368e62a, 0xff200516, 0x21066142, 0xb242b85e, 0xffff2305, + 0x614248e1, 0x00c02607, 0xa9ffff08, 0x2219829e, 0x82cc4c53, 0x0a5721b6, 0x4c227f82, 0xf7828bce, 0x8266e621, 0x1cff221a, 0x06394328, 0xb1823a20, + 0x21063943, 0xf24a34b3, 0x66382209, 0x0f394364, 0x00218582, 0x267c8202, 0x32b3f7ff, 0x82a8ffff, 0xae002309, 0x4c823433, 0xfeff8c22, 0x22071a43, + 0x42662648, 0x47220765, 0x1a43e0fa, 0x82ba2009, 0x19482ae8, 0x1574f79a, 0x680d00ff, 0x2cde82f4, 0xffe47a0c, 0x94780800, 0x780400ff, 0x34148350, + 0x00ff08b4, 0xff109805, 0x90c21000, 0xeff6ffff, 0x1200ffe0, 0x22d08221, 0x82303def, 0x08972118, 0x85216882, 0x235d82e6, 0x059a1928, 0x2305ed41, + 0x84e00200, 0x8f200982, 0x02225b82, 0x53825ccf, 0x04f60222, 0x2109cd4a, 0x6d4aa430, 0x42d42006, 0xe2200546, 0xff330682, 0xd8a3e6ff, 0x14f0ffff, + 0xf2ffff7a, 0xffffeb11, 0x829082e8, 0xb38e3157, 0x2500ff33, 0xff0590c2, 0xfb60edff, 0x810600ff, 0xed207782, 0xff2d6c82, 0xff00e0f6, 0xa470faff, + 0x43efffff, 0x22298212, 0x82f668fa, 0x703d260a, 0x0c0900ff, 0x212d82cd, 0xaf8248e1, 0x0982cc20, 0x6666fa22, 0x23061943, 0xd8e3d5ff, 0x072fa082, + 0xffff9e0f, 0xfff428ea, 0x96e30f00, 0x83eeffff, 0xd414218e, 0xf6387782, 0xff0848e1, 0xcc4cd9fe, 0x70ffff07, 0xff061e05, 0x707de5ff, 0xebffff8b, + 0xea225a83, 0x0a829082, 0xd663e633, 0xffffff08, 0xffff9919, 0xff9242f6, 0x33330700, 0x051469ff, 0x035d0820, 0x19df2205, 0x2461189a, 0xef073813, + 0x01ff089e, 0x079a9957, 0x0b0500ff, 0x0200ff02, 0x00fffc34, 0x8288b604, 0x0cc22109, 0x6f260982, 0x0300ff1a, 0xa9826826, 0x34b38727, 0xc5d2ffff, + 0x27a98220, 0xff281c05, 0x3ceafeff, 0x80201a82, 0xff20ed82, 0x002b0482, 0x8bcc4c03, 0xfb94fb08, 0x828b1504, 0xb89e35c0, 0x190100ff, 0xf7ffff9a, + 0xffffcca1, 0xffaec7a9, 0x7c3fae00, 0xe244a282, 0xb85e2605, 0x8acdffff, 0x42b1823d, 0xe6442780, 0xd9452311, 0x96828b9a, 0x99d94522, 0x3b237082, + 0x82ae3e0a, 0x192c2d06, 0x14fb089a, 0xff1534f7, 0x3e0a4800, 0x21084c42, 0xfb8247e1, 0x7b144822, 0x24056842, 0xf8e4f70e, 0x22218214, 0x8200809e, + 0x80112916, 0xfc05cb00, 0xffff0664, 0x0be4cd18, 0x09ad8f18, 0x73073421, 0x7d200866, 0x09708e18, 0x7a838f20, 0xcd4c6722, 0x08264082, 0x052b33b3, + 0x098294f7, 0x707d1129, 0xffff05cb, 0x8290829e, 0x33f7224d, 0x22388234, 0x19ccccf8, 0x820bf12a, 0x860820a2, 0x21168411, 0x0e8200ff, 0x6a224a83, + 0x40899a19, 0xf6688422, 0x842240b0, 0x40896666, 0x2a1c6a22, 0xfb2c40ae, 0x1514fba4, 0xff0714f7, 0x48e14500, 0x0b244882, 0x14fbb89e, 0xae29cb82, + 0xf7060080, 0x1554fbf4, 0x23e082fb, 0xb89edcff, 0xe324d382, 0xffff4861, 0x0a820482, 0x08211082, 0x220082ff, 0x82056bf9, 0x82ee200d, 0x0e002118, + 0x1d590482, 0x9e112605, 0xf7088bb9, 0x204d82d4, 0x84378311, 0x3b4a1819, 0xb89e2807, 0x0000ff08, 0x82ab1400, 0xffff2763, 0x2300fff2, 0x54826666, + 0x002d0482, 0xff9a991c, 0x9a99dcff, 0x14fb088b, 0x4f6f592b, 0xf1355a82, 0xffffb89e, 0x8b6666ee, 0xffaf0e08, 0xcd4c9000, 0xf59f01ff, 0x226882c2, + 0x829999da, 0x00c02a93, 0xccd4ffff, 0xf5ffffcd, 0x212c82d9, 0x9682e6d2, 0x6626ec22, 0xf431e582, 0xffff7b94, 0xff58f9fa, 0xebd1f8ff, 0x5bf4ffff, + 0x2af28224, 0x081e85f3, 0x9afeff8b, 0x82056666, 0x73f4310d, 0x0b00ff34, 0xff8371fd, 0xc3750a00, 0xe60400ff, 0x2905e243, 0x3b00ffcd, 0x00ffd823, + 0x5c82805d, 0x28dcb92c, 0xfcffff8f, 0xff0870fd, 0x63830200, 0xceccfd25, 0x820300ff, 0xfeff21fa, 0x00216d82, 0x05a85c03, 0x6f190c20, 0x002408aa, + 0x8b48610b, 0x24068275, 0xe0fa7f01, 0x270c8207, 0xfff83305, 0x1078fdff, 0xe0271682, 0xfbffff84, 0x828e00c0, 0x14fe36a2, 0x0100ffbc, 0xffff4661, + 0xff6766d1, 0xe23a2000, 0x99b7ffff, 0x2c13829a, 0xff085c4f, 0x9c199d01, 0xc0e2ffff, 0x21eb8200, 0x8e82e3d2, 0x3eca1322, 0xa12feb82, 0x0900ff46, + 0xffffecd1, 0xffaec7da, 0x82a6ffff, 0xb7ff32b2, 0xffff5c8f, 0xff20b0fe, 0x0a57d2ff, 0xc3dfffff, 0x216d8212, 0x13823433, 0x8248a121, 0xb3fb2267, + 0x20c18332, 0x83148272, 0x21fb2ed1, 0xffff8b46, 0x083ecafa, 0xe680feff, 0x239f8266, 0x72bdfaff, 0x20061c44, 0x21d882f4, 0xd3850c00, 0xe87b0322, + 0x0322bb82, 0x91823874, 0x82002021, 0xd0d721fe, 0x33220482, 0x2b8208f8, 0x82ccec21, 0x9c042504, 0x835d00ff, 0x462c9a82, 0x00ff5a24, 0xff285c7e, + 0x0ad7c4ff, 0x0a221e82, 0xe582c475, 0xffa01a2b, 0x70fd0b00, 0x000800ff, 0x22488242, 0x82848b0b, 0x0000281a, 0x6501ff08, 0x82059a99, 0x821120bc, + 0x730c2220, 0x06335ab6, 0xf6a80b26, 0x99f4ffff, 0x05305382, 0x0e081e05, 0xa000ffaf, 0x01ff66e6, 0x1570fd84, 0x66251782, 0x0600ff67, 0x20218268, + 0x22a182f1, 0x82d7fbff, 0x99f922e7, 0x2118829a, 0xe282b85e, 0xcc4cf527, 0xcaecffff, 0x83d7823e, 0x33ea251e, 0x08758b34, 0xec37e582, 0x00ff52f8, + 0xfff00704, 0x0a97edff, 0xf20700ff, 0xeefffff2, 0x8208ecd1, 0x820c2014, 0x39f72236, 0x219d8216, 0x3682d9ae, 0xffd6d827, 0xec110900, 0x221a828b, + 0x82006003, 0x6c0321ae, 0x00220a82, 0xe782fdb7, 0xffc54026, 0x13800100, 0x0c270f82, 0x00ffeb11, 0x82ef8705, 0x34332604, 0x190f00ff, 0x29718599, + 0x34330b00, 0x00ff8608, 0x8782cc0a, 0x0080fd22, 0x9921f882, 0x2244829a, 0x829a190c, 0x0d002386, 0x468214ee, 0x40828c20, 0x90c20d22, 0xb325c782, + 0x0c00fff8, 0x23b8821e, 0x33730600, 0x8c202b82, 0xfb273582, 0x00ffcdcc, 0x82ba9e0e, 0x82c282d2, 0x82f420eb, 0xb59d2da0, 0x3800ffc3, 0xff15a2a5, + 0x5c8fefff, 0xae213982, 0x27ca82da, 0xfffff668, 0xff0601f8, 0x2c059465, 0x08f0a7ef, 0x18f2ffff, 0xddffffd5, 0x261983a8, 0xfffff8f3, 0x8284abdb, + 0x97db22fe, 0x237e820a, 0xceccd9ff, 0xf083fb82, 0x9999db27, 0xe70d00ff, 0x212a822b, 0x8e8233b3, 0xae070522, 0x2206c153, 0x8271fd0b, 0x21b98354, + 0x1e49a80c, 0xe1fa2105, 0x0426c082, 0x00ff7b14, 0xa482b300, 0x85eb0327, 0x990100ff, 0x2535829a, 0xffd76310, 0x14830600, 0xf6e80727, 0x991200ff, + 0x268a829a, 0x00ff285c, 0x82666610, 0x33f5218a, 0x1a2c2e82, 0xffff34b3, 0xffae87fa, 0x32331c00, 0x1d204882, 0x21050941, 0xc5820f1d, 0x11780522, + 0x3d2b1682, 0x0a00ff70, 0x00ff0fcd, 0x82a4b01a, 0xa3062154, 0x10225482, 0x8582b85e, 0x820a1721, 0xeaa62154, 0x9c21f382, 0x2d688229, 0xff0800a0, + 0xd863ec01, 0x57eeffff, 0x6a8215d0, 0x82186421, 0xf668266a, 0x61edffff, 0x21d88208, 0x298266e6, 0x82ec9121, 0x82592018, 0xefff239d, 0x0a82289c, + 0x83006021, 0x820c2048, 0x50582123, 0xa3214382, 0x212382d6, 0x2e8248a1, 0xead10a26, 0x4fe5ffff, 0xed828683, 0xc0e3ff30, 0xffff8b00, 0x0834f3e2, + 0xe2ffff8b, 0xb483a4f0, 0x83fff021, 0xffff2916, 0xfff232f5, 0xc235e6ff, 0xf920d382, 0xee209883, 0x0021d382, 0x226e8307, 0x826666ed, 0x68662182, + 0x4c216882, 0x255482cd, 0xff64e603, 0x1483feff, 0x9c190429, 0x4cffffff, 0x828b8fcd, 0xa80c2216, 0x22fa82f4, 0x82e4fa0b, 0xdf8f2ba5, 0x070500ff, + 0x0c00ffac, 0x1a822170, 0x0a830d20, 0xcd4c2222, 0xe6261982, 0x2400ff68, 0x29826766, 0x32332622, 0x00218682, 0x22db8324, 0x829819f8, 0x7c542416, + 0x83f2ffff, 0x57222220, 0x2d86820a, 0xff343379, 0x3ccad9ff, 0xf3ffff15, 0xab8252f8, 0x82227021, 0x82c02004, 0xc0f122eb, 0x215f8282, 0x18845c8f, + 0x05225f82, 0xc0821e05, 0xff862b24, 0xe6830200, 0x6666f423, 0x211a828b, 0x5f8266e6, 0x0ff2ff28, 0xfcffff5e, 0x5a82f873, 0x3a824020, 0x824cf921, + 0xe1f32259, 0x21058246, 0x148293f9, 0x7e82f420, 0x33040022, 0xf1200982, 0x0023f582, 0x8210980b, 0x9a9921e6, 0x032c5482, 0xffff20b0, 0xff10f8fd, + 0xe8fb0300, 0x0721e682, 0x210982f0, 0xea8320f0, 0x20700822, 0x0827c082, 0x00ffb833, 0x82527804, 0x46612104, 0x6620da83, 0x0a273582, 0x00ff20a5, + 0x82904213, 0x9a99289f, 0xcc1500ff, 0x82a18bcc, 0x13002686, 0xffffae07, 0x2c4d83fb, 0xff686612, 0x0e0df8ff, 0x301100ff, 0x268682a4, 0xffe27afa, + 0x82170c00, 0x83f12009, 0x30052731, 0xf4ffffa4, 0xea829a19, 0x82527821, 0x99892214, 0x2f2e8298, 0xff15aec7, 0x34b3d6ff, 0xab0800ff, 0xdbffff86, + 0xe021e683, 0x22e683a6, 0x824821d8, 0xe8ff215f, 0x0c27bd83, 0xffff33f3, 0x820a97eb, 0xcd0c2181, 0xeb314582, 0xfeff0886, 0x079a19d7, 0xeeffff8b, + 0x00ff7a54, 0x2304820e, 0x84abf1ff, 0x200ac24e, 0x83c98286, 0x0af04e16, 0x2801ff2f, 0xff0786eb, 0x00401700, 0x8a0d00ff, 0x2037823e, 0x2232822b, + 0x82846b1b, 0x2a9c2589, 0x381e00ff, 0xfa209983, 0x17257283, 0xffff9002, 0x20b883ec, 0x35048212, 0xcccce8ff, 0xdc0400ff, 0xef0e0828, 0x215d00ff, + 0xbe00ff48, 0xba82cc4c, 0xb81eea22, 0x21838282, 0x00c0ed25, 0x83d9ffff, 0xa1f12209, 0x2cd38248, 0xff086666, 0xb85e3c00, 0x00ff05a1, 0x201b8205, + 0x05fa5b00, 0xffb9de2d, 0x4220f9ff, 0x01fcffff, 0x68ffff47, 0xa12105d8, 0x223a8260, 0x1824e68f, 0x20079bc0, 0x204583e0, 0x27a482fc, 0x66e6e7ff, + 0x8b088b8b, 0xce20ca82, 0xf2291383, 0xffc74861, 0x70bd2f00, 0x24068308, 0x00ffb8de, 0x236b8210, 0xe23a6600, 0xff2a2582, 0x1e45a9ff, 0x476d00ff, + 0x308205af, 0x8298ff21, 0x07002b30, 0xffff9999, 0xffad07c4, 0x8f83cfff, 0x111c023e, 0xf500ffec, 0xff152a5c, 0xf428f5ff, 0xe80d00ff, 0xebfffff6, + 0x00ff18ee, 0x7d3c8a02, 0x2c2c1482, 0xffff088c, 0xffcc4c1e, 0x666650ff, 0xdd278f82, 0x00ff9002, 0x825c0f2c, 0xe6fa2c0a, 0x0600ff64, 0xff81245b, + 0x82ccfeff, 0x80fc2120, 0xf822b582, 0x30829a99, 0x0f83e620, 0x3083ca20, 0x82560021, 0x92ff23ea, 0xf582cecc, 0x0a823a20, 0x800c0038, 0xff930500, + 0x00a00100, 0x610300ff, 0x0900ff48, 0xffffb87e, 0xbb82fefa, 0x48610622, 0xde273b82, 0x00ff5ccf, 0x823eca29, 0x33e12730, 0xaf00ff34, 0x0a823233, + 0x3cea0d22, 0xee212a82, 0x05f94214, 0x1c140023, 0x089c822a, 0xff9c193b, 0x14ee0d00, 0xebaf0e08, 0xf815f4f7, 0xb4fb0614, 0xf706cb07, 0xa18b07cc, + 0x19edffff, 0xffff9d98, 0x8b68e6ea, 0x0644fc08, 0x19e9ffff, 0xffff8b99, 0x7966e6ee, 0xfb08758b, 0x282883cc, 0x64f807b4, 0xfb15d4fb, 0x06247524, + 0x12437618, 0x8234fb21, 0x18f7203a, 0x2313d376, 0x64fb075b, 0x50191b83, 0xb4202d22, 0x2308014c, 0xfffc2907, 0x25063b4e, 0x0804d608, 0x984a07ab, + 0x05324c06, 0xfa820720, 0x33f7ff2c, 0x0e088b34, 0xf8e4f8ef, 0x87181554, 0xe9220fa7, 0xce8200c0, 0xb89ee42e, 0xd1ffff08, 0xff0748a1, 0x856b1700, + 0x15274282, 0xffff15ae, 0x821038f9, 0xf8f433fb, 0x00ff0894, 0x075ccf31, 0xff5f01ff, 0xb4fb06fe, 0xe9994b07, 0xcc8e2b20, 0x8288d621, 0x29f72a5f, + 0x075b0878, 0x33a0ffff, 0x35b88234, 0xffec1116, 0x1e85efff, 0x781100ff, 0xe9ffff52, 0x00ffe2fa, 0x0982380b, 0x0080e622, 0xfd226982, 0x248264e6, + 0x408a1a22, 0x80248683, 0x1600ff00, 0xff2abf82, 0x66661b00, 0x3c01ff08, 0xe1831ec5, 0x48611b25, 0x84eaffff, 0x0040321c, 0x80e5ffff, 0xfc088b00, + 0x15d4fb44, 0x053500ff, 0x2738821f, 0xffe1fa2a, 0xe2fa2a00, 0x35230a82, 0x84081e05, 0xff202506, 0x1f05d5ff, 0xe0271683, 0xfacaffff, 0x82088be1, + 0x99192106, 0x1d6a4018, 0x088b672c, 0x4b156bab, 0xb9ffff06, 0x2a825c4f, 0xa4b0c623, 0x0a0e5aff, 0x25092944, 0xf1ffff7b, 0xd38286ab, 0x8b85ab25, + 0x1894f708, 0x200fe997, 0x2282827a, 0x8386ab11, 0xb3462289, 0x059b5a34, 0x4c390023, 0x069b5acc, 0xf7ef0e27, 0x1524f8ec, 0x623682ab, 0x5f180903, + 0x67820a9f, 0x8206f05a, 0x06f05a31, 0x088b3423, 0x2697826b, 0x079a99d1, 0x837000ff, 0x66bc3154, 0x00ff0566, 0xff00800e, 0xcd4cf7ff, 0xcc0800ff, + 0xf0222d82, 0x3d826666, 0x9a19ef2d, 0xfbfeff08, 0x2b073433, 0x8207eb06, 0x8323208c, 0x82e3207b, 0x1c002104, 0xdc213a83, 0x214e82b3, 0x0683ffff, + 0x83ffff21, 0x82048316, 0x21108237, 0x33822b08, 0x0401ff24, 0x3783cccc, 0x66e61022, 0x5d825883, 0x9a990f22, 0x00246c85, 0x0833b308, 0x33258283, + 0x994300ff, 0x2382829a, 0x0766662e, 0xf2229b83, 0x438233b3, 0x8b83f520, 0x00c00a22, 0x0d237582, 0x5b080040, 0xb32008ea, 0x16822f82, 0x0d00ff29, + 0x088bcd4c, 0x83a306ab, 0x2221825f, 0x820a00ff, 0x86002092, 0x8bcc211a, 0x0c7b4c18, 0x3e0a1441, 0xfeff0773, 0xffb8dec0, 0x34b3e5fe, 0x6700ff15, + 0x00ff4821, 0x0532b338, 0x9911ffff, 0x4e3b079a, 0x00220c08, 0x7f838015, 0x00801a22, 0x5b204d82, 0x85821e82, 0x00801127, 0x870900ff, 0x064553ae, + 0x0a570f22, 0x2082d982, 0xff078b24, 0x4c823702, 0x4c4aff24, 0x468215cc, 0x82ee0021, 0x265f82ce, 0xffff9819, 0x82ce4cc7, 0x660f25df, 0xf7ffff68, + 0x04823e84, 0xe6efff23, 0x20e68266, 0x223a82ee, 0x82a4ffff, 0x06674e2b, 0x18eaff21, 0x270df7b6, 0xf80e078b, 0x1504f894, 0xed251e82, 0xffff70fd, + 0x31e582f1, 0xf668efff, 0xe6e7ffff, 0xf2ffff66, 0xff089a99, 0x0a83e2ff, 0xff225082, 0x1e83d4ff, 0x9a99f425, 0x83ceffff, 0x84fc2079, 0x82fc201e, + 0x01002979, 0xffff32b3, 0xff3233fc, 0x34200982, 0x34200983, 0x77067e49, 0x10200565, 0xcb227683, 0xdc829999, 0x57826620, 0xcdccc723, 0x2d58828b, + 0x8b33b3f7, 0xe6f7ffff, 0xffffff67, 0x0983cccc, 0xff201b82, 0xfe205484, 0x00247382, 0x059a9900, 0x67218983, 0x05ac65ff, 0x33b3f12d, 0x971000ff, + 0x00ff8b0a, 0x51900212, 0x002b075b, 0xff9a1955, 0xecd12300, 0x826a00ff, 0xf50824f5, 0x5bffe18b, 0x07230bc1, 0x83a0feff, 0xe6ae27b7, 0x00ff1566, + 0x4382330a, 0x0f820020, 0x660a0022, 0x00205782, 0x00218e82, 0x2487820a, 0x3e00ff08, 0x218e8233, 0x20823700, 0x83f3ff21, 0x82232020, 0xecff2357, + 0x1a8266e6, 0x9e831820, 0xc482f220, 0x820e0021, 0xefff2119, 0xff232983, 0x8233b3ed, 0xfcff2183, 0xff22aa82, 0xbf824cff, 0x8233fb21, 0x99fe22fa, + 0x20ff839a, 0x20df8233, 0x245c82fb, 0xcdccf2ff, 0x210482ff, 0xc758ffce, 0x83ee2005, 0xb3f52449, 0x848b0834, 0x20258200, 0x23b482ff, 0xccffffff, + 0x0a822182, 0x4f840982, 0x8b227682, 0x0d82058b, 0xff206f83, 0xff223483, 0x0e8232b3, 0x8968e621, 0x82082013, 0x83ec200b, 0x84c8206e, 0x206d83b3, + 0x829982c1, 0x66c42b53, 0xffff8b66, 0xfff6a8ca, 0x99830b00, 0xaec7dc27, 0xcc1100ff, 0x2b1a82ce, 0x8c4821fe, 0x2efeffff, 0x0100ff14, 0xfe275683, + 0x00ff703d, 0x829a1900, 0xe3e7221a, 0x076941d7, 0xff52b828, 0x9a991000, 0xe1829d8b, 0x82220021, 0x350030c2, 0x00ff156e, 0xff33b31d, 0xec914a00, + 0x820a00ff, 0x210582a0, 0x46820080, 0x0f838282, 0x33210982, 0x20708334, 0x215082cd, 0xe18232b3, 0x00ff0523, 0x229a83e7, 0x820080e6, 0x4c1c253c, + 0x0400ffce, 0x2406495b, 0x00ffa192, 0x21758309, 0xa0821000, 0x82060021, 0x0f0026fe, 0x00ff9a19, 0x06d34d08, 0x4c215c82, 0x239482cc, 0x079a99dc, + 0xec20cb82, 0xff217982, 0x216e82ef, 0x5183eeff, 0x5eb3e421, 0x2082059c, 0x3f82f120, 0x99f8ff26, 0xeeffff99, 0xf9290983, 0xff77cdcc, 0x3333fbff, + 0x83858208, 0x82012050, 0x82e08339, 0xcdcc229e, 0x8305848b, 0xe6152bd4, 0xf5ffff66, 0xff9d6666, 0x5682f2ff, 0x800d0033, 0x078b0800, 0x19f8ffff, + 0x6affff9a, 0x8b159a99, 0x070f4379, 0x0f439182, 0x33fe220b, 0x06a54132, 0xef82fe20, 0x0487ff20, 0x8b828a20, 0x82b3dc21, 0x83ee201a, 0x83ca201f, + 0x83f420a0, 0x66c42304, 0x1a828b66, 0x3333c122, 0xc826c682, 0x00ff5238, 0x6282990c, 0x82f8dc21, 0x66132209, 0x0e774166, 0x77416620, 0x00ff2507, + 0x07666623, 0x73212c82, 0x82a78220, 0x0f002648, 0xffff852b, 0x283b82f7, 0x5c4f1000, 0x33f9ffff, 0x25e28232, 0xff908227, 0xc083efff, 0x295c3425, + 0x83f6ffff, 0x8238201e, 0x831a826a, 0x00ff2706, 0xff676634, 0xc2820900, 0x2005d87a, 0x27e68210, 0xcc0700ff, 0x0300ffcc, 0x0021bd82, 0x203a8307, + 0x24b68203, 0x9a190700, 0x2035828f, 0x26ff8206, 0x68660300, 0x830500ff, 0x83032015, 0x66052229, 0x201a8368, 0x202b8301, 0x201f8301, 0x204f8301, + 0x20e78201, 0x22098500, 0x82089a19, 0x99dc30dc, 0xffab059a, 0x66e63900, 0x1200ff15, 0x82909a19, 0x20288305, 0x20378304, 0x2099830f, 0x417d8406, + 0xcd2106f1, 0x07f141ff, 0x0c20a182, 0x0a202383, 0x230bf141, 0x860080f5, 0x1782f982, 0x82f6ff21, 0x20048373, 0x82ea8208, 0xefff2194, 0xe3250483, + 0xffffce4c, 0x215582f2, 0x0e83dbff, 0xce4cf722, 0x2009f141, 0x07fb4132, 0x8bcecc27, 0xcc0100ff, 0x821a82cc, 0xfb072796, 0x56ffff74, 0x9e829a19, + 0x421a1c41, 0xd32a2590, 0xff35cccc, 0x3433dcff, 0x96828b21, 0xc2f59528, 0xaaffff8b, 0x4418510a, 0xc2410b8e, 0xf70e273f, 0x1554f894, 0x4b18ffff, + 0x4b1809ae, 0x002011dc, 0xff201c82, 0xff201683, 0x34deb619, 0xb850ff25, 0x8294fb52, 0xe8fe2863, 0xffff06f5, 0x8208ecf6, 0xadf832c6, 0x0800ff91, + 0x00ffd102, 0xff0bd700, 0x39540900, 0x300f8208, 0x00ff3e4a, 0xfff6a85c, 0xd7234a00, 0xf04900ff, 0x240e82a4, 0x0893cdcc, 0x2b268294, 0x00ffaec7, + 0xff33b307, 0xae87f8ff, 0xf6224082, 0x4783f6a8, 0x66a6f727, 0xc8f9ffff, 0x310482f6, 0xffffec11, 0xffebf1f7, 0x3e4affff, 0xb2ffff08, 0x148252f8, + 0xff142e25, 0x8266c2ff, 0x99c22223, 0x210e829a, 0x1882cd0c, 0x21050f58, 0x2e820040, 0x50cccc21, 0xf9200633, 0xf7231e83, 0x828b33f3, 0x47af2786, + 0xa0ffffae, 0xb28266e6, 0xe1faca22, 0xd5296b82, 0x8bb61f05, 0x193400ff, 0x8372829a, 0x00ff2906, 0xffe1fa2a, 0x66e62b00, 0x82057a49, 0x05352234, + 0x30228220, 0x60e0fa2a, 0x8b08568b, 0xffff6056, 0x5666e6d5, 0x2230838b, 0x829a197f, 0x7645184a, 0xcdcc210b, 0xee225582, 0x1d823333, 0x33eeff23, + 0x76451834, 0x208d8207, 0x76451800, 0x82342008, 0x4c0e224e, 0x211b82cc, 0xcf7e0040, 0x222d8205, 0x82c01100, 0xb3f121b6, 0xc0833283, 0xcc4cee2d, + 0xef0e088b, 0xe60b02ff, 0x8401ff68, 0x320029b3, 0xff069819, 0x68661d00, 0x182d3582, 0xffff30b3, 0x932a1ceb, 0x82e3ffff, 0x20a6828e, 0x08278203, + 0x61f1ff27, 0x732b0548, 0x8b074305, 0xc4ffff33, 0xff4066e6, 0xce4cafff, 0x4ce9ffff, 0xffb508ce, 0x66e699ff, 0xffff9005, 0x248e82f3, 0x3233faff, + 0x820a827d, 0xfaff2470, 0x840866e6, 0x7d862515, 0xcc0500ff, 0x11822f82, 0x0c00ff24, 0x1682cc4c, 0x6866d12d, 0xff0506f7, 0x66e6feff, 0x62ff8a8b, + 0x0b83056d, 0xd7221a82, 0x8f829a19, 0x9a192727, 0x19a1ffff, 0x2259b39a, 0x827100ff, 0xffff2f38, 0x0666e67a, 0x68b5ffff, 0xc6fffff6, 0x6d829a99, + 0x71fdf127, 0x4cf5ffff, 0x25e382cc, 0x00fff6e8, 0x63829902, 0x5e3af524, 0x15820899, 0x99583922, 0x9e241182, 0x1400fffa, 0x00277a82, 0xffcb010e, + 0x82cc0a00, 0x630133ab, 0x01ff9082, 0x05666611, 0x331d00ff, 0xff8b0734, 0x38823000, 0x66270024, 0x0485ff66, 0x8b260e82, 0x1b00ff08, 0x1b82cc4c, + 0x68661822, 0x8a2bf582, 0x1000ff3e, 0xffff3433, 0x82c275ec, 0xe6002c1a, 0xffff0766, 0x3b9819bc, 0x4a00ff15, 0x002309bb, 0x19cecc09, 0x210a8511, + 0x9d852a5c, 0xa30b0026, 0xf2ffffd6, 0x83056c4a, 0x21168506, 0x1219f4ff, 0xcc210c7a, 0x05024ace, 0x33f6ff23, 0x2b548532, 0xf8af0e08, 0x15ccf7d4, + 0xe9ffff8b, 0xff24df82, 0xff0c17ee, 0x0a200482, 0xf4200e83, 0xff23a182, 0x8284c0ff, 0xcaff261b, 0x0000fffc, 0x22a68220, 0x8280c0ff, 0x00012109, + 0xcd32ff82, 0xfeffe27a, 0x059a19ea, 0x39fdffff, 0xf0ffff1e, 0x828298de, 0xffcccc26, 0x66e6f4ff, 0x80210e82, 0x24408200, 0x6866b5fe, 0x210c8206, + 0x46823d8a, 0x70bdf227, 0x0f0b00ff, 0x2530825c, 0x00ff713d, 0xe882350f, 0x7dcdff28, 0x1501ff70, 0x46827cd4, 0x00c0ff22, 0x3d206c84, 0x21079946, + 0x428299d9, 0x16829983, 0x0a17ee27, 0xe81100ff, 0x23fd82f6, 0x080a1716, 0xc67b0685, 0x24168206, 0x301500ff, 0x842d82a4, 0x83168506, 0x82d885c8, + 0xff23082d, 0xff8400f7, 0x9f7afcff, 0x1bf8ffff, 0xfaffffa4, 0xffffe7fb, 0x08ec51f9, 0xa15900ff, 0xb8ffff48, 0x8205cd4c, 0xf6e83592, 0x45f3ffff, + 0x1700ff1f, 0x00ff0a97, 0xff9d2f05, 0x291c0900, 0x392c4f82, 0x00ff0859, 0xff999939, 0x32337300, 0xf421ab82, 0x24cb82b2, 0x83ce0c07, 0x21898297, + 0x908a570e, 0x84cccc21, 0x00ff24a7, 0x839a1916, 0x21068390, 0x8c8dff9c, 0x82a8f121, 0x09f82867, 0xffff7f78, 0x82bca9f4, 0xa4f02192, 0x9a255e84, + 0xcc8cffff, 0x278882cc, 0xff6a1c09, 0xaec7edff, 0x99218882, 0x21ad8258, 0x9c82ecd1, 0xff66e626, 0x52b80c00, 0x0022b286, 0x8883b347, 0x28dcfb27, + 0xae0600ff, 0x26dc8216, 0x00ff0080, 0x82cccc08, 0x44082090, 0x7a820548, 0xe6218b82, 0x82048368, 0x1816203b, 0x8211cf68, 0xffff2fa2, 0x0866e6e9, + 0x01ffef0e, 0xf79a19bf, 0x3e821574, 0x5c8f0c27, 0x38fbffff, 0x3b6e8210, 0xffffec91, 0xff566ef6, 0x48a10900, 0x51ffff08, 0x00ff9a19, 0x0564e6ae, + 0x40f7ffff, 0x09266e82, 0xffffd48d, 0x5c8266f3, 0x38c90426, 0x99f2ffff, 0xff22f283, 0x84824cf4, 0x82f3ff21, 0xfbff238f, 0x4082c836, 0x82cd4c21, + 0x9e6f2104, 0x26214083, 0x21458267, 0x40826626, 0xd96ef622, 0x4c211582, 0x216a82ce, 0x45824537, 0x8b008023, 0x203a83ff, 0x27068208, 0xffa470f3, + 0xf6c80400, 0x63211682, 0x217c82d7, 0x2a82a490, 0x82b95e21, 0xe6ae22fa, 0x20868466, 0x21158205, 0x158200a0, 0x82207021, 0x221f83a6, 0x824636fb, + 0x5c8f2209, 0x8225828b, 0x21c783c1, 0x4583ec91, 0x2a827220, 0x82b89e21, 0x28912104, 0xc2824086, 0x002b8182, 0xff168d09, 0xcccc0800, 0x820300ff, + 0x0c002155, 0x002a8183, 0x089a990c, 0xe6a0feff, 0x54697366, 0x26f62108, 0x694de082, 0x590c2205, 0x209f829a, 0x20068200, 0x05494dff, 0x75821682, + 0xf7835920, 0x75821583, 0x82a60b21, 0x70b982e2, 0xff330d98, 0xffcd4cf5, 0x3333f5ff, 0xb3f2ffff, 0xf7088b33, 0xb614fb14, 0x4d728360, 0xf32206af, + 0x8e8266a6, 0x0682ff20, 0xf6ffff22, 0xc44e5b83, 0x21608206, 0x5fb7f78b, 0x66a60b22, 0xff214d82, 0xb9c09dff, 0x41bfa55f, 0x32225320, 0xe54fffff, + 0x00ff3209, 0xc39819ef, 0x89ffff15, 0x058bcc4c, 0x6b0400ff, 0x261e8202, 0x00ffe1ba, 0x829e2f02, 0x1f052209, 0x2005848b, 0x31068208, 0xffcd4ceb, + 0x9022f8ff, 0x51ebffff, 0xf0ffffec, 0x0482283c, 0x08703d27, 0xcc77ffff, 0x200484cc, 0x07e95105, 0x78d30028, 0x70e5ffff, 0x6460ffa4, 0x80ea2a05, + 0x1a00ff00, 0x088b0080, 0x069d60ff, 0xff240c83, 0x98991400, 0xd96c2184, 0xe0002907, 0xff0766e6, 0x68e60000, 0xa7602e84, 0x8298200d, 0x90ff253d, + 0x4cfb0200, 0x204b3242, 0x060d4182, 0x66e6f12f, 0x2f0e088b, 0x34f814f8, 0x06d4fb15, 0x15c65cff, 0x07d4fb22, 0x2e05d05c, 0x9e1c00ff, 0xe3ffffb8, + 0x00ff4861, 0x5c486123, 0x098306c2, 0x1e831985, 0x1082d582, 0x83f70821, 0x82248333, 0x6666212e, 0xff201e85, 0x2205ba5c, 0x82f4fb94, 0x61ee22cb, + 0x76548247, 0xb924222b, 0x00ff088b, 0x2009265d, 0xcaea18ff, 0xffff210a, 0x5c062b76, 0x8b220cbb, 0x5f8354f7, 0x83666621, 0x9999215f, 0x0b385818, + 0x11229c82, 0x11829a99, 0x0e20c183, 0x11219783, 0x215fb09e, 0x5e8a2beb, 0x69834c83, 0x57820020, 0x5e930820, 0xbeafb820, 0x49775e85, 0x131d414b, + 0x02105fd8, 0x232f014d, 0x54fb54f7, 0x435cca5f, 0xf041060e, 0xfb3422c8, 0x5c7f4394, 0x20d0c042, 0x5c0d45eb, 0x5edd8b20, 0x84611e43, 0x581d43bf, + 0xd8051e41, 0x71ac425e, 0x4d423420, 0xbd5b475c, 0x43cf8d41, 0x0e2d607c, 0xf724f82f, 0xf4fb1574, 0xeeffff06, 0xb329194f, 0xa4b02809, 0xefffff8b, + 0x8508c235, 0x00ff2c06, 0xff5c4f0e, 0x3ecaf0ff, 0x821100ff, 0xf708211b, 0x09843082, 0x1e831985, 0x1a848b20, 0x17833082, 0x2305fa56, 0xf6680d00, + 0x4c2c5782, 0xfb088bcc, 0xff15db44, 0x52781a00, 0x15242682, 0x00ffae87, 0x0a820482, 0x31831082, 0xff240682, 0x5278eaff, 0xff261684, 0xae87e5ff, + 0x0685088b, 0x1b831685, 0x17828982, 0x1e832d82, 0x80212882, 0x4b1b8500, 0x8b2305e1, 0x9f1574fb, 0x85768231, 0x826e8264, 0x828d9e5f, 0x5da4835f, + 0x0e2f068b, 0x8bc4f8af, 0xff063b15, 0x00408d01, 0x5da78b07, 0xc02007ac, 0x2207ac5d, 0x8506b4fb, 0x2c19852a, 0x0040e9ff, 0xff086f8b, 0x00c072fe, + 0x23368207, 0x0020f7ff, 0xf821c182, 0x222f82e0, 0x8266e6f8, 0x19f7240a, 0x186b089a, 0x2017d9f8, 0x204d82f8, 0x30fc1800, 0x050f5f14, 0xff66e636, + 0x68e6f8ff, 0x190700ff, 0xf7ffff9a, 0x088b9819, 0x34f744fb, 0x415cc748, 0x5b260502, 0x4e01ff06, 0xb8820080, 0x401b0022, 0xb35ecc82, 0x04fb360e, + 0xfdffffff, 0xffff0570, 0x079002c0, 0x14fc06eb, 0x0604f707, 0x28cb91ff, 0x089af907, 0x191f00ff, 0x2249839a, 0x9032b30a, 0xff2708cf, 0xcc4ce8fe, + 0xfebe01ff, 0x54fb1536, 0x40ceffff, 0xffff0500, 0xffcdccf0, 0x3a3ffcff, 0xe6f6ffff, 0xf2ffff66, 0x828b00c0, 0x48e12814, 0x92feff08, 0x820748e1, + 0x0c68419c, 0x1e83e020, 0x6606f826, 0xe0ffff08, 0x2605fc67, 0xffce4cf5, 0x41200700, 0x96850585, 0xc4f70828, 0xde01ff06, 0x8983b8de, 0x82801521, + 0x82ec201a, 0x0f002d04, 0xffff7edf, 0xffcccceb, 0x00c0faff, 0xcf274082, 0xfeff34b3, 0x79ca01e1, 0x0e290def, 0xff8bb85e, 0xe2ba1000, 0x22068208, + 0x50b89e11, 0x0d24069a, 0x00ffe27a, 0x10db7f18, 0x66f3ff23, 0x2ea51966, 0x059a500d, 0x9a99f122, 0x2a069a50, 0xe301ff0e, 0x00ff6666, 0x82cdcccb, + 0x827c2067, 0xd5ff2a87, 0xff059919, 0x70bd6100, 0x26f48206, 0xffff4220, 0x824861f5, 0xbe9f215b, 0xbe260482, 0xceffffb8, 0x04829002, 0x08480125, + 0x826cffff, 0xceff233a, 0x2f8248e1, 0x833d6221, 0x83b5202f, 0xe1b6271b, 0x88ffff48, 0x2262d663, 0x82ff2005, 0x21b0825a, 0x2f821e85, 0x29dcbd28, + 0x02beffff, 0x59820590, 0x8341a021, 0xff402504, 0x25c6f0ff, 0xf620a382, 0x0922ca83, 0x2582c05f, 0xff2d0a87, 0x89010000, 0x390f00ff, 0x0900ffda, + 0x217e825f, 0x74826109, 0x82030121, 0x030128a4, 0xff053433, 0x823f0600, 0x40062715, 0x00ff8b00, 0x9a821e0a, 0x42c0f922, 0x40211482, 0x85448200, + 0x231f820a, 0x06e1f5ff, 0xf9245f82, 0xffff00c0, 0x1a821482, 0xfd834d20, 0xcecc4d22, 0xf9278582, 0x00ff162e, 0x82de7a3b, 0x7bd42b60, 0x665900ff, + 0x3c00ff67, 0x0482717d, 0x08676627, 0xbd5500ff, 0x21048270, 0x6a8214ae, 0x9f835a20, 0x63200484, 0xff263382, 0xff66a6fd, 0x89823e00, 0x82c1ff23, + 0x25298290, 0xfff4a832, 0x0f82cdff, 0x190b002d, 0xb5ffff9c, 0xffffd6a3, 0x82fe7fd2, 0x01803809, 0xf8af0e08, 0xff15aba4, 0x14eedfff, 0xa5ffff06, + 0x00ff14ae, 0x820a5760, 0x998c2754, 0x4f00ff98, 0x0a82ae07, 0x48611222, 0x402ec482, 0x0b00ff00, 0x00ffb85e, 0x8bb85e13, 0xbf6108a0, 0xf4ff2106, + 0x13201783, 0xff215d82, 0x200983ed, 0x20e1840a, 0x08bc61d7, 0x826ec521, 0x2e132551, 0x088b8b14, 0x3533e382, 0x2500ffc6, 0xffffd823, 0xff32b3df, + 0xa4301c00, 0x56d8ffff, 0x0683052d, 0x87211682, 0x068167ae, 0x4c82f920, 0xc0daff23, 0x25358200, 0xff51385d, 0x5182f0ff, 0xcc80ff27, 0x76ffffd3, + 0x20de82e6, 0x220e8300, 0x829a1959, 0x20002cde, 0xddffff00, 0x00ff9a19, 0x8241011d, 0x261e833d, 0x8bb9de22, 0x43c4f708, 0x0822136b, 0xbb8300e0, + 0x098b5c18, 0x707d1522, 0x088b5c18, 0x6666cb22, 0x17213382, 0x22b382ee, 0x82486120, 0x821820fa, 0x24002686, 0xffff4821, 0x2b0482f2, 0xb81e3400, + 0xfdd3ffff, 0x1200ff70, 0xe836e784, 0x00ff3533, 0xff1e050a, 0x3333e4ff, 0xb3faffff, 0xebffff34, 0xae826666, 0x82666621, 0x33df21b9, 0xe7270f82, + 0xff050080, 0x82e0f8ff, 0xa0fa21a5, 0xf6260482, 0x00ff4801, 0x09826001, 0x82bdfa21, 0x20072148, 0x1983e383, 0x0a820020, 0x00231985, 0x43b8fe09, + 0x00230599, 0x82904205, 0xc02227e3, 0x1a00ff00, 0x9182b81e, 0x82de2421, 0x9e1b211a, 0x33280482, 0xff8b0080, 0xe2ba2400, 0x61217d82, 0x21258248, + 0xa782e10a, 0x00e0f72e, 0xe1ffffae, 0xff860020, 0xb8dec9ff, 0x76211682, 0x21908286, 0xce830182, 0x46615a22, 0x24171341, 0x050000ff, 0x06f35120, + 0x1880ea21, 0x29070051, 0x8b0080e5, 0xf74cfb08, 0xd76115c4, 0x10c27d08, 0x8205e342, 0x13d16216, 0xe7824020, 0x2005eb52, 0xdebb18c0, 0xab0e2319, + 0x608314f8, 0x9a592327, 0xa61c00ff, 0x22048367, 0x8200ff66, 0x088b230e, 0xb18234f7, 0xcc4c2322, 0x08006518, 0x8b9a592c, 0xa6dcffff, 0x54fb0866, + 0x1b829307, 0x82993021, 0x27002210, 0x20e48266, 0x230a83d8, 0x6666cfff, 0x21054c46, 0x6e18b3f2, 0xff2828e8, 0x66e69a00, 0xe4ffff07, 0x00274682, + 0xff343306, 0x8299ebff, 0x1919218b, 0x1d2b5b83, 0xcb08cccc, 0x05ab6b07, 0x82f7ffff, 0x0800231a, 0x8d820ad7, 0xec510e22, 0x8206b555, 0x8908200f, + 0x00ff240a, 0x8268660e, 0xcc08221f, 0x212f82cc, 0x1a82f628, 0x824c4d21, 0xb3b2280a, 0x7f970534, 0x820600ff, 0xefff2c95, 0x7a8bcccc, 0x22ffff08, + 0x82070080, 0x82d820ce, 0xdfff2156, 0x04843083, 0x8b200e82, 0x06831c82, 0x1684ff20, 0x33200023, 0x20528234, 0x20888227, 0x182f82ab, 0x200a895d, + 0x30348312, 0x8b66e6e9, 0xff068308, 0x9a196fff, 0x1100ff07, 0x182c83b3, 0x770e6e45, 0xfb21168a, 0x223682b4, 0x827b54ee, 0xabf1221e, 0x18bb8285, + 0x1808df69, 0x21089c45, 0x16847b54, 0x2606fc64, 0xcb0714f8, 0x821504fb, 0x82f7202f, 0x0fc072b4, 0x0614f722, 0x16b09d18, 0x8f19eb20, 0xcd2d0a0e, + 0x280700ff, 0xf7fffff6, 0x088b3333, 0x843282fb, 0xffff2409, 0x82cdccf8, 0x0ad72104, 0x33085c83, 0x2b08f628, 0xffaf0e07, 0x98193e02, 0x99a700ff, + 0xffff159a, 0xffb89ed2, 0xceccb500, 0xfaffff05, 0x00ff0020, 0xff46a117, 0x4841f0ff, 0x5e1400ff, 0xeaffffba, 0x0b231e83, 0x480800c0, 0x00200576, + 0xff280a82, 0x6666e7ff, 0x610200ff, 0xe7222882, 0x5d829ad9, 0x82ba3e21, 0xc0f0221e, 0x21428200, 0x488200e0, 0x82a0f721, 0x40fd210a, 0xfb260482, + 0xffff4881, 0x6282def6, 0x04820220, 0xa1f7ff25, 0x82900848, 0xb8de225e, 0x83408205, 0x222a8330, 0x82210900, 0x7efb2125, 0x08212582, 0x2004825e, + 0x226e8302, 0x821e0d00, 0x6004210a, 0x00224f82, 0x8e82e10a, 0x54820320, 0x1e0c0024, 0x37458bb8, 0xfaff2205, 0x219482a0, 0x65830a00, 0x8305e943, + 0xe0f62109, 0x0220c282, 0xff212e82, 0x214484f4, 0x59826126, 0x9a196622, 0xe9209482, 0x00211582, 0x211f8206, 0x6483e4ff, 0x4e820520, 0x9ee0ff24, + 0xba828bb8, 0x5583dd20, 0xc7d9ff2d, 0xffff84ae, 0xff3433d6, 0x8240ecff, 0xb6ff395b, 0xff067cd4, 0x9a19d7ff, 0xc81300ff, 0xd8fffff4, 0xff9266e6, + 0x9a19ddff, 0x3a833383, 0xe4ffff28, 0xffff4761, 0xe98260fa, 0x82e1e921, 0x20f92109, 0x00203782, 0x00237483, 0x8366e699, 0x216f82e3, 0x99820b00, + 0x3e070024, 0xe884ffb9, 0x820a0021, 0x05002493, 0x8208b85e, 0xd82329c8, 0x540500ff, 0x0c00ff7c, 0x0f825582, 0xff66e626, 0x4861fcff, 0xfe831a82, + 0xa0fbff22, 0x0820fe83, 0xfd205f83, 0x09214483, 0x21de8220, 0x04828004, 0x82c00221, 0x82082004, 0xff902529, 0x46210f00, 0xd4206a83, 0x08254682, + 0xffff725d, 0x222083fb, 0x65b81e09, 0x2a820670, 0x22069e41, 0x82200500, 0xe8ff264f, 0x00ffb8de, 0x21408207, 0x8a82e6ff, 0xa0fdff22, 0xea25be82, + 0xffffb89e, 0x21f684f4, 0xc982a1ea, 0xff220a82, 0x7382f0ff, 0x83ebff21, 0x83fa2019, 0x82e8204d, 0xffff336e, 0xffada7d2, 0x52384aff, 0xfeffff05, + 0xff8607c0, 0x9e83ffff, 0xccccfa28, 0xfaffff8b, 0x6a8234b3, 0x00c0b923, 0x320c8207, 0xffcc0cc2, 0x41a13300, 0x19ccffff, 0x3f00ff9a, 0x828b85ab, + 0x212531d7, 0x00ff0648, 0x8b00403c, 0x263200ff, 0x00ffb967, 0x3b22cf84, 0x1c826666, 0x82e00221, 0xa12622d5, 0x22ce8248, 0x8200c023, 0x23108327, + 0xb85ed9ff, 0x04251082, 0xffff5078, 0x20da83c5, 0x214e8232, 0x0482d1ff, 0x333c0023, 0x22538934, 0x82ba9e3f, 0x94332353, 0x0682be78, 0x83e63e21, + 0x33462d4f, 0x00ff0734, 0xffec1100, 0xcc4c0500, 0x6621aa82, 0x82098268, 0xfeff2339, 0x098430b3, 0xfeff0830, 0xffce4c8d, 0x32b3a6ff, 0xff718915, + 0xed83e9ff, 0x00c0eb27, 0x61e5ffff, 0x295b8248, 0xcdccdaff, 0xe3ffff06, 0x4782cdcc, 0x749ad923, 0x061667ff, 0x00801b22, 0x2522af82, 0x5f820080, + 0x821e1221, 0x830620c5, 0x42192499, 0x8400ff90, 0x3d1d2209, 0x233d8270, 0x48e11700, 0x17268c82, 0xffffb85e, 0xdb82a0fb, 0x48a11626, 0x60f7ffff, + 0x97653b82, 0xe6d63505, 0x01ff0566, 0xff9a9934, 0x9a990300, 0xffff8b15, 0x740080e4, 0xe3208686, 0x2205de45, 0x82b8deda, 0x858e8381, 0x14002a17, + 0xa5890040, 0xfcffff08, 0x265182e0, 0x05482129, 0x821600ff, 0x080021b6, 0x17216183, 0x21828282, 0x19826004, 0xb8de1725, 0x82a8088b, 0x6119217e, + 0xf9207482, 0x12219f83, 0x8288821e, 0x203c8209, 0x08ba84da, 0x48010025, 0x2f0e158b, 0x472200ff, 0x7400ffae, 0xff159a19, 0x19040500, 0x78f3ffff, + 0x0c00ff52, 0xffff9603, 0x82f668f8, 0x05826609, 0xf8f30322, 0x04274f82, 0x00ff1904, 0x82fcb700, 0x37e92eb3, 0x8f0100ff, 0xd4f708f4, 0x197f00ff, + 0x2289829a, 0x822a1c0c, 0x2ebd2742, 0x0b00ff93, 0x2d82cccc, 0xb05c0d20, 0x82068205, 0xf007214b, 0xc0211682, 0x305f8200, 0x00ffe8db, 0x08b8de04, + 0x14f7d4fb, 0xefffff05, 0x2d7f8287, 0xff109806, 0x856bedff, 0xf9ffff83, 0x1482a470, 0x82e69021, 0x70f922a9, 0x059270a3, 0xfa070023, 0x821f82e1, + 0x100021cd, 0x23829482, 0xff08a22b, 0x33b3f500, 0xb89dffff, 0x22448252, 0x82cd4c0a, 0xc4b5210a, 0xef220a82, 0x44820a97, 0x82666621, 0x1f052173, + 0x09823482, 0x8f060023, 0x2f48825c, 0xff089a99, 0x52b87d01, 0xe6abffff, 0x14fc1566, 0x2a0cab45, 0xa4b0f1ff, 0xeeffff8b, 0x8508ec51, 0x00ff2506, + 0xff7b540e, 0x2307d26e, 0xf8088b85, 0x00223082, 0xd56eab11, 0xec512109, 0x2213994e, 0x82cc4c0e, 0x06616146, 0x197f0026, 0x1534f89a, 0x2405d06a, + 0x330f00ff, 0x26568334, 0x1000ff7a, 0x828bcdcc, 0xe680228d, 0xde521866, 0x0eed7d0c, 0x4e7c5421, 0x858405ee, 0x83eeff21, 0x34fb2554, 0xab074b06, + 0x58223482, 0x56826666, 0x9a994725, 0x83b8ffff, 0xa7ff210a, 0x4b21df82, 0x16994607, 0x0fffff24, 0xf0829a19, 0xccccf638, 0xf6ffff8b, 0x00ff0080, + 0x8534b304, 0x190800ff, 0xffff0898, 0x9882b3a8, 0x3433732d, 0x70ffff05, 0x00ff0a17, 0x8266e639, 0x75f62c0a, 0x0300ffc3, 0xffffcdcc, 0x82b8def8, + 0x3333272a, 0x82fdffff, 0x3082958f, 0xa4f0e827, 0x385c00ff, 0x26258252, 0xff9a79fd, 0x82190a00, 0xa2072704, 0x0900ff8f, 0x0e82aec7, 0x22051b7c, + 0x82299c1a, 0xf80a22a9, 0x31a98252, 0xff717d09, 0x9042fbff, 0x0a0600ff, 0xf7ffff3e, 0x4643a4f0, 0xffff2a05, 0x05cccccc, 0xcb0664f7, 0x21db8207, + 0xc268ffff, 0xccf02705, 0x0e00ffcc, 0x38827c54, 0x84ab1131, 0xff078b08, 0x66e60001, 0xf715b4fb, 0x1bab0614, 0x340f585c, 0x14fb066b, 0xf600ff07, + 0xffff9899, 0x15666669, 0x19fcffff, 0x2604839c, 0x7373059a, 0x82dfffff, 0xf2ff2ced, 0x8b690080, 0xe6feff08, 0x890666e6, 0x47cd2064, 0x0f2013a3, + 0x0023e782, 0x41cc4c0e, 0x192408a5, 0x9c069a19, 0x10208982, 0x06241383, 0x979734b3, 0x032bba82, 0x00ff68e6, 0x0566e603, 0x820c00ff, 0x22048560, + 0x82303314, 0x230f8327, 0x0080f3ff, 0x0a872582, 0x4dff8b21, 0x158205f1, 0x1a84ff20, 0x058b8b2e, 0x01ffef0e, 0xff66e6ee, 0x70fd5f01, 0xd922b382, + 0x25825238, 0x5c8fdb2c, 0xe8f0ffff, 0xe4fffff6, 0x0482b89e, 0x080a9727, 0xb3b7ffff, 0x22048234, 0x8205c3b5, 0x82cc2005, 0x4c4822b3, 0x260a82cd, + 0xff0a97e4, 0x82681b00, 0x91db2c2a, 0x0f00ffec, 0xffff0a17, 0x82713dd9, 0xafff2de5, 0xfffff5e8, 0xff70fdff, 0xd7e3beff, 0xe8230482, 0x823b8bf6, + 0x40e22347, 0x63820700, 0x52f8af27, 0x1c4100ff, 0x25188229, 0x00ff14ee, 0x3383fd4f, 0xc7260023, 0x22bb82ae, 0x85a47024, 0x1b00234a, 0x5e844861, + 0x00ff0823, 0x22f88348, 0x82682648, 0x3a4822eb, 0x218482e2, 0x0a8200c0, 0x84847a84, 0x146e2422, 0x0023b485, 0x8290c226, 0x5000227f, 0x22908211, + 0x82cc0c00, 0x98192166, 0x9a220483, 0x4782db8b, 0x83c01d21, 0x5000217f, 0xff231882, 0x8268e6be, 0x22b38318, 0x82feffaf, 0xdbfe2933, 0xffff9a99, + 0x15c4b517, 0xb0214a82, 0x2c0486a4, 0xffb89eeb, 0x5c8ff7ff, 0x4feaffff, 0x2525825c, 0xae47d3ff, 0x598300ff, 0x99dbff28, 0x2400ff99, 0xb4826666, + 0x34b32c22, 0x2c215d89, 0x22dd82b8, 0x82f66824, 0x2204831c, 0x82e1ba2c, 0x15002337, 0x2882a4b0, 0x845e1421, 0x82de204e, 0xec5121e2, 0x22206283, + 0x48223782, 0xd286e13a, 0xc0b7ff23, 0x2f0a8200, 0xff0552b8, 0x00807501, 0x663900ff, 0xff8b1566, 0xff247484, 0xff0c97db, 0x0a200482, 0x45210e82, + 0x8452821c, 0xffff2991, 0xff48a1eb, 0x20700800, 0xae214d82, 0x22578214, 0x8208e04f, 0x1ec52642, 0x404800ff, 0x06304100, 0x0f220a86, 0x20835c4f, + 0x14210482, 0x21348461, 0x9784ffa4, 0x2c228382, 0xd68270bd, 0xdb820720, 0x68662422, 0x99216682, 0x2176839a, 0x4b82cc4c, 0x3433e233, 0xf7af0e07, + 0x2a00ff94, 0xff1566e6, 0x9a19cdff, 0xbbc71807, 0x00ff2d2d, 0x0734b328, 0xb3faffff, 0xffffff33, 0x0986d782, 0x82cccc21, 0x05dd6113, 0x6666ef22, + 0xef275382, 0x00ff67e6, 0x829a1902, 0x222a82cb, 0x83cc0400, 0xb2d1207f, 0x8441206f, 0x9cc6316f, 0x2100ff29, 0xffff3233, 0xc9d763d9, 0x4700ff8b, + 0x27051146, 0xff66e66a, 0xc3f55500, 0x6b820482, 0x0a6a002a, 0xff088b3e, 0xcd4c2400, 0x21202282, 0xff2da182, 0xff84ebf5, 0x68e61c00, 0x7aeeffff, + 0x201a82e2, 0x2243831f, 0x82f628ed, 0x22bd834d, 0x41a470ee, 0x1a8205f9, 0x34b33723, 0xa1631806, 0xc6ff230b, 0xc98234b3, 0x184cb921, 0x2007ddc4, + 0x216c82f9, 0x3683fbff, 0x0983f820, 0x824cf921, 0xe6fd27f4, 0xffff0868, 0x608266f9, 0x1483fd20, 0x34b3f822, 0x8027f782, 0x00ff8700, 0x8232b305, + 0xb3aa281a, 0x7900ff32, 0x490568e6, 0x34410553, 0x21448405, 0x3f82ccff, 0x6666fb22, 0xff24b182, 0x06cc4cc8, 0x2007ab41, 0x2d9884de, 0xffff6666, + 0xffcecce0, 0x3433edff, 0x62828008, 0xf4206d83, 0xfa20bd83, 0xf3221a83, 0x50829a99, 0x089a9929, 0x00ff54f7, 0x669a199d, 0x0a290d06, 0xff8b33b3, + 0xcd4c0d00, 0x22068508, 0x82f5ffff, 0x1800203e, 0x2109297c, 0x0666ffff, 0x4cf5220a, 0x77e818cd, 0x0e22081d, 0x3400ff2f, 0x00ff291c, 0x15cd4ce2, + 0xffffd4f7, 0x05ffff7f, 0xe30300ff, 0xfeffffd8, 0xff8f6866, 0x5e83ffff, 0x62190321, 0xb32105e6, 0x38758234, 0xff1e050c, 0x10980700, 0x020500ff, + 0x0c00ff90, 0xff08a886, 0xe08f0600, 0x057747ff, 0x1804f82c, 0x9e1200ff, 0xefffffb8, 0x18838e97, 0xff085c2b, 0x31330bff, 0x4a6200ff, 0x225b823e, + 0x8233b3f5, 0xae47210a, 0x10220a82, 0x2083f668, 0x4e82de20, 0x3e82fa20, 0xc6a01227, 0x70f9ffff, 0x214882a4, 0x34826666, 0xff290a87, 0x166eedff, + 0x0c0800ff, 0x052c6cce, 0x78f9ff25, 0x83fb0852, 0x66e626ac, 0xf3ffff05, 0x2c6b82de, 0xff281cfb, 0xae07f8ff, 0x4cf4ffff, 0x77f383ce, 0xe621067e, + 0x215c8266, 0x168352f8, 0xab82cd20, 0xffd7232a, 0x9a19fbff, 0x6b01ff08, 0x3d22e283, 0xe34733b3, 0x0c7d5616, 0x827b5421, 0x222f8278, 0x47ab1100, + 0x4f2113e3, 0x14e3475c, 0xff5c4f22, 0x25058e47, 0x8b8baf0e, 0x9246db15, 0x18082005, 0x2016b5ec, 0x22428287, 0x82792907, 0x08e173c3, 0xeb076b22, + 0x641833d1, 0x0a820acf, 0x29f7ff24, 0x67a00878, 0xdb363394, 0xfc07eb06, 0x072b06d4, 0x01ffd4f8, 0x159a192d, 0xe62200ff, 0xc6820766, 0x2605e851, + 0x00ff0080, 0x56707d15, 0x08220595, 0x3d7274fc, 0xeaff210c, 0x08464018, 0xddffff2a, 0xff075c0f, 0x9a991200, 0x2e06fc41, 0xff66660d, 0x6666eeff, + 0xebffff8b, 0x85089a19, 0x6dff2006, 0x1682052c, 0x2905ae49, 0x6666f9ff, 0xadffff08, 0x80829a19, 0x00ff0623, 0x837b8252, 0xff682319, 0x49830600, + 0x9899f227, 0x991100ff, 0x228f829a, 0x8266e614, 0x82002044, 0x00ff2306, 0x2082660d, 0x6f831682, 0x2a822082, 0x14fc0827, 0xe6a2ffff, 0x055f4f66, + 0x4fff3321, 0xcc290612, 0xf7ffffcd, 0x088b3333, 0x0c69766b, 0x82070021, 0x00ff2513, 0x08cdcc08, 0x22055e4f, 0x83ffcccc, 0x20048313, 0x22178434, + 0x4fab088b, 0x4f820c90, 0x0793bf18, 0xf7072b24, 0x678a8b14, 0x6c86cc20, 0x3433f722, 0x41186787, 0x33200a19, 0x678fba82, 0x07216282, 0x20678433, + 0x826787cc, 0x2080825c, 0xf14a8334, 0x0e310867, 0x7f01ffef, 0x157b9a19, 0xe6d8ffff, 0x0000ff66, 0xff050600, 0x1ec52100, 0x1400ff07, 0x00ff9a99, + 0xfff2d202, 0xd6631300, 0x930600ff, 0x1100fff8, 0x28bc82b3, 0x08685109, 0xbdd4ffff, 0x39298270, 0xff05f6e8, 0x0a57f1ff, 0x59fbffff, 0xf0ffff9a, + 0xffff4861, 0xff9478fd, 0x3d83efff, 0xf4080122, 0x24082982, 0xff33f3bd, 0xd8240400, 0x66c9ffff, 0x3e00ff67, 0xff8b0080, 0x34334200, 0x0300ff08, + 0x5b07e9c6, 0x9f2500ff, 0x5c37137d, 0x36081601, 0xffff6871, 0xff9a59ec, 0x7ac9f6ff, 0x87eeffff, 0xffff08ae, 0xff1e45e6, 0xf6281400, 0x0500ff05, + 0x00ffe83b, 0xff14ae0b, 0x4e420300, 0xbd0c00ff, 0x00ff8b72, 0x82f5a80d, 0xeec62325, 0x0082ff14, 0xff05d927, 0xcc8cddff, 0x222c82a6, 0x82fce902, + 0x820e2027, 0x8304202c, 0xf1013b04, 0x0400ffaa, 0x088b0e8d, 0x194f00ff, 0x00ff069a, 0x07021a1f, 0x13afffff, 0x34828bbe, 0xfc29f729, 0xf9ffff8b, + 0x18ff6abc, 0x220d8a47, 0x849eef07, 0x00ff2411, 0x82621008, 0x9eef2109, 0x6c824086, 0x82aaff21, 0xe6202266, 0x204582bc, 0x054e42b0, 0x49a46220, + 0x8305b479, 0xffdb3c49, 0x12000000, 0xffc18b05, 0xa470d3ff, 0x912b00ff, 0xc9ffffec, 0xffff48a1, 0x824861fe, 0x54cc22d5, 0x2921827a, 0xfffff43b, + 0xff9a99d6, 0xa484d2ff, 0x3473cb22, 0x0027c382, 0xffff2700, 0x8220c5cd, 0xb5472771, 0x9100ff9b, 0x7318761e, 0xcf21391a, 0x1a7318df, 0x4a682008, + 0x301906f5, 0x6820119f, 0x09647018, 0x0f2c7f82, 0x00ffec11, 0xff00e001, 0xb81e0800, 0x0d9f3019, 0x73188320, 0xaf35161a, 0xa83000ff, 0x7001fff6, + 0xff15b8de, 0x70bd4f00, 0x3aeaffff, 0x260982e2, 0x00ffcdcc, 0x875c4f14, 0x0a572209, 0x22158208, 0x83842b16, 0x162e2705, 0xdfffffe2, 0x72821e85, + 0x82e61021, 0xb0f9229c, 0x336d82a4, 0xffff9819, 0x8bec11ef, 0xf5edffff, 0xfeff08c2, 0x07f628ca, 0xe8260c82, 0xffff9a19, 0x268266e6, 0x3233f037, + 0xe6e8ffff, 0x0600ff64, 0xff08ce4c, 0xce4cb0ff, 0xcc1500ff, 0x830982cc, 0xb3eb2219, 0x82098334, 0xb3eb2204, 0x201e8232, 0x263883a8, 0xffcecce9, + 0x82ffa8ff, 0x83e92000, 0xdea92128, 0x2022d782, 0x1e820080, 0x0a17ef22, 0xff234884, 0x82f0f5ff, 0xe6102c7e, 0x00ff8b66, 0x089a1912, 0x793501ff, + 0x24080517, 0xfff6e817, 0x299c1900, 0xc20f00ff, 0x1700ff8e, 0xffffcd0c, 0x0834b3f9, 0xff058b8b, 0xa470ee00, 0x21effeff, 0x22f58248, 0x829a192d, + 0xcc23233a, 0x0682b6cc, 0x66e6352e, 0xffc08b08, 0x3433dcff, 0xd2ffffb6, 0x6b825582, 0x33b3d422, 0xdb26c982, 0x8b60cd4c, 0x09820856, 0x9a82ca20, + 0xb3240031, 0x00ff6033, 0x8bcd4c2b, 0x4b74fb08, 0x8206cb15, 0x4c23213d, 0xe425cd82, 0x00ff0040, 0x29cd831c, 0x8b00c0db, 0x8b074b08, 0x9e8201ff, + 0x074b1527, 0x402400ff, 0x21268200, 0x2182c01b, 0xcecc1b22, 0x242d0a82, 0x4b083233, 0xc001ff06, 0x34fb66e6, 0x0cee7915, 0x8266e221, 0xdcff21d2, + 0xcb2bb182, 0x4000ff06, 0x4b0766e6, 0x821564f7, 0xccdb227e, 0x246086ce, 0xff3233e4, 0x2a748200, 0x07cb088b, 0xaf0e064b, 0x83fb00ff, 0xe6f02b9a, + 0x968b1566, 0x8b969494, 0x3a829b08, 0xc5820b20, 0x8b82942a, 0x07470880, 0x8b96068f, 0x46820a84, 0x9a19f42a, 0xf7ffff82, 0x8b8066e6, 0xcf2be382, + 0x80069a19, 0x00ff828b, 0x829a1908, 0x20338297, 0x20428608, 0x2342828f, 0x0700802f, 0xcc2c2b82, 0x0100ffcc, 0xffff67e6, 0x933433f8, 0x0a222582, + 0x3a829999, 0x5c8f3527, 0xf87f00ff, 0xed414252, 0xa4704e28, 0x21affeff, 0xf7411548, 0x06cb2818, 0xc000ff4b, 0x411566e6, 0xcd200ef7, 0x24293182, + 0x4b083333, 0xff074b06, 0x24208201, 0x197fffff, 0x2325829a, 0x0766e640, 0x23180242, 0x0001ff8b, 0x4b214b82, 0x18014206, 0x1fffff2d, 0x155b9a19, + 0x58608b56, 0x82084e8b, 0x33c13226, 0xffffb634, 0xc066e6cd, 0x00ff088b, 0x8b66e635, 0xa56418b6, 0xcc3e3407, 0xc88b08cc, 0xffffbe60, 0x8b9a19ca, + 0xf8af0e08, 0x8214f894, 0x15b55982, 0x7c079421, 0x887c0578, 0x23a68509, 0x0654fc08, 0xa6210982, 0x221e8266, 0x189a59e3, 0x200b187f, 0x203383f7, + 0x061d5a00, 0x1d5a6620, 0x54f8260b, 0xfb24fc06, 0x53b61834, 0xa8c8180f, 0x49332010, 0x0023064a, 0x5acdcc08, 0x08210653, 0x07ac48cc, 0x480a4649, + 0xff2205e5, 0x4949f8ff, 0xf7ff2e07, 0x088b3433, 0x8b0634fb, 0xf71514fb, 0xa4c918f4, 0x2037820c, 0x82308434, 0x05ff59fe, 0x200f977f, 0x583082fb, + 0x73830cdb, 0x34211082, 0x173f5908, 0x54f79c22, 0x0fba8918, 0xff25a682, 0x0834b3f2, 0x05434f5b, 0x00ff3323, 0x3bf6180a, 0x7edb200d, 0x1d820c57, + 0x2007944d, 0x233182bb, 0xcc4c0d00, 0x2108964d, 0x4983ff34, 0x3b088b23, 0x6ea44106, 0xfb84fb23, 0x20d78214, 0x6c4b18f7, 0xf8ff2208, 0x11a441cc, + 0x16829e82, 0x0800ff28, 0x088bcccc, 0x6c4174f7, 0x07834a0f, 0x2017a441, 0x05a44174, 0xa4413790, 0x2030821f, 0x4a998cff, 0xa44107ba, 0x20998409, + 0x279986cc, 0x1994ffff, 0x1534f79a, 0x0b2a8782, 0x94829a19, 0xff088b7f, 0xda41f5ff, 0x00002205, 0x2a358282, 0x0866e6f4, 0xffff0785, 0x186666fa, + 0x2008efac, 0x200982cc, 0xefac184c, 0x5c0f250e, 0x33f9ffff, 0xf3255c82, 0xffff8f02, 0x272d83f3, 0xff0ad7fc, 0x33b3edff, 0xfe225282, 0x5783e13a, + 0x00ffcd35, 0xffa4f000, 0x9a19f6ff, 0x3d0400ff, 0xf7ffff71, 0x82089919, 0x6726210a, 0x33260a82, 0x0600ff33, 0x4782ae87, 0x2882cc20, 0x48a10627, + 0x80fbffff, 0x2c1e8201, 0xffec910b, 0x9819f8ff, 0x4c0f00ff, 0x281482cd, 0x00ff6866, 0xff33b30b, 0xf7ac18ff, 0x0566220c, 0x251b8299, 0x00ff32b3, + 0x4e826609, 0x82e6fc21, 0xe6052125, 0xfb22b582, 0x448232b3, 0x00800222, 0x08f7ac18, 0xfe261e82, 0x00ff9a99, 0xca824c00, 0x9819ff22, 0x00201e82, + 0xff203383, 0x0022c082, 0x47829900, 0x0982fe20, 0x4cffff24, 0xbc8287cd, 0x4e84ff20, 0x19253e84, 0xffff8899, 0x200a83fa, 0x225483fd, 0x82e6f9ff, + 0x83fd204a, 0x19f621ec, 0xb3213583, 0x21fb8234, 0xac183333, 0x868216f7, 0x83fdff21, 0xcc0023db, 0x0986ffce, 0x8932b322, 0xb3218782, 0x25678234, + 0xff3d8af5, 0x5c830300, 0x85abf422, 0x9c836682, 0x8f82fc27, 0x80f5ffff, 0x871e8200, 0x00ff220a, 0x201e8305, 0x236b82f4, 0xe27a0a00, 0x66214882, + 0x22c08266, 0x82c33501, 0x201483df, 0x20428301, 0x260482ff, 0x52b80100, 0x84ffffff, 0xfd06221e, 0xfbac1871, 0xffcd2308, 0x8182fbff, 0x84090021, + 0xcccc21c8, 0xac185c82, 0xff2809fb, 0x00000900, 0x0a00ff82, 0x33ffac18, 0x00ffcd2b, 0xff32b306, 0x9a990c00, 0x22cb8298, 0x189ecd4c, 0x2009fbac, + 0x238a8268, 0x87953433, 0x19216082, 0x28728298, 0x949919fc, 0xb3f9ffff, 0x06594e33, 0x824cf921, 0xcc04223d, 0x251a82cd, 0xff67e6f3, 0x04820800, + 0xccefff26, 0x0400ffcc, 0xff200482, 0x03221384, 0x1e8234b3, 0x2983fe20, 0x33330023, 0xfbac1805, 0xffcd2208, 0xfbac18ff, 0x82662007, 0x3333212f, + 0xfd212582, 0x210a8266, 0x1a82cc01, 0x8233ff21, 0x82012063, 0xffff2104, 0x00230e82, 0x82008000, 0x820a851e, 0xffff2123, 0x1e822884, 0x99000023, + 0x21b5829a, 0xac186766, 0x98820ffb, 0x73830620, 0xcccc0222, 0x05201a82, 0x02202583, 0x00229d82, 0x9d82cc0a, 0x99990122, 0xac18f082, 0xbd820cfb, + 0x00800d24, 0x8284ffff, 0x66e60323, 0x2035828a, 0x2435820a, 0x9a19fdff, 0x83ee8296, 0x83022070, 0xb30a218a, 0x0022a982, 0xa982e602, 0xf9211f84, + 0x211f8299, 0x6b88f5ff, 0x83fbff21, 0xfbac185c, 0x82578208, 0x8b08210b, 0x4c344282, 0x2f0e05cc, 0x04f744f8, 0xffff8b15, 0xff5c4fee, 0xa4b0f1ff, + 0xae210482, 0x200e8414, 0x31e1828b, 0x06cdcc2b, 0xd9beffff, 0x9effff99, 0xff059042, 0x0a83f9ff, 0x66a6f725, 0x82f5ffff, 0xfaff237c, 0x09829a19, + 0x8385ab21, 0xe7f9222b, 0x264782ef, 0xff10d8f9, 0x82c00100, 0x87fa28b9, 0x0300ffae, 0x820800a0, 0x82472052, 0xcf09260a, 0xfcffffe0, 0x2c098207, + 0xff16d913, 0xa4d00900, 0xb80e00ff, 0x27d78252, 0xff717d29, 0xe23a3e00, 0xc1225f82, 0x70688f22, 0x0e00210c, 0x210fa559, 0xa9820e00, 0x2205de57, + 0x82a4b011, 0x69002a78, 0xff060080, 0x9a193f00, 0x224082eb, 0x95666657, 0x83a22040, 0x823182f3, 0x22408574, 0x8600ffce, 0x33d42240, 0x28408234, + 0xff142e41, 0x1ec56100, 0x219b8205, 0x2682f0c7, 0xa082b020, 0xc8d61322, 0xf821c482, 0x830e8252, 0x37f622d3, 0x82af820a, 0xffff24b5, 0x852230f6, + 0xecff2319, 0x0e82ea26, 0x835c2f21, 0x08ac2ae7, 0x7dd6ffff, 0xc1ffff70, 0x23ce82ba, 0x90e23e00, 0x66835982, 0xa55a7685, 0x5aea2008, 0x734107a5, + 0x86ab2106, 0x20087341, 0x23c18496, 0x2b66e6c0, 0xa8218982, 0x279a83b3, 0xff34b311, 0x1e050000, 0x09648e18, 0x2305265a, 0x94f80e08, 0x82050849, + 0x056f440f, 0xff9a1926, 0x9a19ffff, 0x94440f82, 0x00802406, 0x83dbffff, 0xccde2504, 0xe8ffffcc, 0x0e821f83, 0xa7828b20, 0x9a199e22, 0x200e9968, + 0x22378399, 0x830080e5, 0x99fc229c, 0x2673829a, 0xffff6666, 0x8232b3fc, 0x230e8209, 0xceccfcff, 0x0225fe82, 0xffff3433, 0x274d82f5, 0xcc4c0400, + 0x0400ff82, 0xf5282483, 0x9108ce4c, 0x33f2ffff, 0x06202b82, 0xf2226483, 0x8482ce4c, 0x4c85f120, 0x9819e025, 0x83eaffff, 0x83e32027, 0x83e0203c, + 0xb3fe2304, 0x5c820834, 0xff219a83, 0x836683e6, 0x2109851e, 0x9f830080, 0x20099d7e, 0x230a8400, 0x66668d00, 0x06839982, 0x27a88a18, 0xe628b782, + 0x34fc0766, 0xffff158b, 0x2209d761, 0x83ccf0ff, 0x33ef229b, 0x214e8232, 0x7782edff, 0x540e0023, 0x82bc827b, 0x054754e3, 0x1800ff21, 0x280a0183, + 0x8b66660d, 0x991200ff, 0x2b2d829a, 0xcecc1000, 0xb3f1ffff, 0x0f00ff33, 0xff28ea82, 0x8bcd4cee, 0x15cbab08, 0x8c8230ad, 0x47853782, 0x4c218c93, + 0x278c87cd, 0x088b33b3, 0x14f714f7, 0x280d4a7e, 0x8b1ec5f0, 0x3aefffff, 0x8dbf89e2, 0x208e8332, 0x24b48234, 0xffcc4c0e, 0x21bf8d00, 0x935c1ec5, + 0x0f002305, 0x0455e23a, 0x05d57706, 0x8e0a2963, 0x20f28532, 0x22f28834, 0x18088bcc, 0x410c8284, 0x7782124e, 0x99f2ff23, 0x2a87859a, 0xf72f0e08, + 0x1554f754, 0x5dbb07cb, 0xde820e2d, 0xcd204983, 0xee20c783, 0x4a19c283, 0x5b210e36, 0x20388206, 0x183d4b74, 0x2105fd76, 0x3d4b34b3, 0xd4fb2110, + 0x83183d4b, 0x143d4b33, 0x06d4f726, 0x1554fb5b, 0x2905aa4e, 0x2a00ff60, 0x8b569a19, 0x48824308, 0x66e6e923, 0x21a6828b, 0x04849a19, 0x10820a82, + 0x4cfb0822, 0x1796e018, 0x200c0b42, 0x0842640e, 0xfd82ab20, 0xb68bc02b, 0x08c08bb6, 0xf88baf0e, 0x27698304, 0xff90821a, 0x717d1500, 0x26058f55, + 0x8f821a00, 0x18eb088b, 0x550d557d, 0x7b25098e, 0x0654f707, 0x07c6559b, 0x18150021, 0x980dd2fe, 0x182b2036, 0x2017129e, 0x0cfd432b, 0x0a354818, + 0xfb079b25, 0x837b0654, 0x4cfe2c36, 0xffffffcc, 0xffff66e6, 0x82ce4cfe, 0xcdcc2109, 0x4c260482, 0x00ff08cc, 0x0a824c50, 0x9a199423, 0x27778f05, + 0xff8b0080, 0x0080e5ff, 0x198a9e18, 0xeb207798, 0x00297282, 0xff34b301, 0x9a190000, 0x200982ff, 0x21098232, 0x09823333, 0x089a9929, 0xb3afffff, + 0x8405f633, 0x3ae8183c, 0x3eb48a08, 0xfb0e07eb, 0x0d00ff30, 0x01ff52f8, 0x15d2cdbd, 0x850800ff, 0x0300ff1f, 0x00ff80ea, 0x828f020a, 0xf6992bc1, + 0x1e0700ff, 0xf9ffffb8, 0xc1828ce6, 0x48612832, 0x63ddffff, 0x00ff0554, 0xff676628, 0xac9c2200, 0x09270a82, 0x00ff0000, 0x823ab407, 0x34332849, + 0xffff948b, 0x83c64bf8, 0x6666212c, 0x66202c89, 0x94202c85, 0x278228a7, 0x0623cf83, 0x82957419, 0x0a6621cb, 0x80279a82, 0xfcffff00, 0x88088015, + 0xff40230a, 0x14830500, 0xa67bf72c, 0xf6ffff8b, 0xfc0848a1, 0x09830764, 0x4a9a9921, 0xf720062e, 0x38841e84, 0x089a1922, 0x24052264, 0x9819fcff, + 0x20538381, 0x20a88268, 0x229782e6, 0x82981906, 0x82d7201a, 0x22002634, 0xff059a99, 0x250a83ff, 0x6666ddff, 0x21828205, 0xffcc4c28, 0xccccf2ff, + 0x9182828b, 0xa234b321, 0x21658228, 0x2c890000, 0xf8829920, 0x9e225585, 0x5584ffb8, 0xe1255482, 0xf9ffff48, 0x278082e6, 0xff71fdf5, 0x9899feff, + 0x7a263482, 0x0300ffe1, 0x618268e6, 0x6a7cf722, 0x66200a83, 0x8b21c482, 0x27ed8444, 0x0900ff8b, 0xf8086666, 0x0023de83, 0x82b85e09, 0xbc7421f8, + 0x84211982, 0x2104829c, 0x2d829683, 0x087eea2f, 0x00ff078b, 0xffae0752, 0x2e3272ff, 0xdad71815, 0x0acf4e34, 0x271ff24c, 0xfb8b0654, 0x54f71574, + 0xa10f624d, 0x2299ad37, 0x8f14f78b, 0x0cf64dcb, 0x68ff3421, 0xf8260509, 0x00ffcccc, 0xd818d708, 0xcb9709a6, 0x9b4fcd20, 0x06543511, 0x00ffef0e, + 0xff006009, 0x9a99d600, 0xff858515, 0x00a0fcff, 0xe622a782, 0x05828b66, 0x08008025, 0x850714fb, 0x00ff2209, 0x28268203, 0x48e1f7ff, 0x91088591, + 0x20728285, 0x22288220, 0x41b89efc, 0x082705a6, 0x54f706ab, 0x84066b07, 0x21318335, 0x4b8248e1, 0xff9a992b, 0xb8fef9ff, 0x01ff0885, 0x265782c6, + 0x66668900, 0x1904fb15, 0x2009c11c, 0x07377cff, 0xeeffff22, 0x83058765, 0x84ff2006, 0x82048316, 0x22108248, 0x82074b08, 0xffff2434, 0x82cdccd3, + 0x33dc2710, 0xdcffff33, 0x0a823433, 0xccccd325, 0x7ca4fb08, 0xb9200ad4, 0x8326d47c, 0x2c002333, 0x48823433, 0xffcc4c26, 0xcccc2300, 0xb3365d82, + 0xfb088b34, 0x15d4fb64, 0x07ab064b, 0x076b06cb, 0x150cf76b, 0xcf45ffff, 0x11002409, 0x188b66e6, 0x2308e5c8, 0xff9a1916, 0x04861183, 0x42180e82, + 0x1185072b, 0x19eeff23, 0x06fd459a, 0x14460685, 0x24548509, 0xfb14f708, 0x216c880c, 0x778f8beb, 0x8248e121, 0x1eee2237, 0x834e82b8, 0x1600240a, + 0x8308b81e, 0x2111847e, 0x168466e6, 0x77af8d84, 0xd600ff36, 0x00ff9899, 0x159a993e, 0xffff9185, 0xff68e6f7, 0x66660300, 0x802a0982, 0x6b088b00, + 0x0754fb06, 0xd64106ab, 0x83058205, 0x6003276e, 0x08919100, 0x27829191, 0x82486121, 0x00202113, 0x08228882, 0xc2820080, 0x09850720, 0xfcffff22, + 0x08295383, 0x91859a19, 0x00ff0e08, 0x29a082b1, 0x66e6d1ff, 0xedffff15, 0x0483cd4c, 0xffffce25, 0x829a99e1, 0x4ced33d2, 0x1200ffcc, 0xff0832b3, + 0x0ad7a3ff, 0x335c00ff, 0x20820534, 0x842d4121, 0x214e8215, 0x9082661e, 0xd3be1222, 0x08250f84, 0xc03200ff, 0x28048200, 0xff05cecc, 0x8f023000, + 0x2c06825b, 0xff343306, 0x32b3f9ff, 0x330a00ff, 0x23318234, 0xff333306, 0x8205ce56, 0x82cd2005, 0x3233210a, 0x1b821582, 0x2007ef4d, 0x236d8333, + 0xbb8f02d0, 0x292e3c82, 0x00ffd763, 0x05676629, 0xd0ffffbb, 0x4e840100, 0x4eae3320, 0x5b083322, 0x66214a84, 0x224a8866, 0x89ffffcf, 0x878e824a, + 0x22a48299, 0x82cd4c06, 0x4c0622c6, 0x209983ce, 0x83998933, 0x2199851a, 0x4e850100, 0x4e826720, 0x84d86321, 0x90022199, 0x32204e84, 0x4e84998e, + 0x4e89ce20, 0x4e86e88a, 0x00ff5b23, 0x213c8430, 0x7082cc32, 0x00c03222, 0x12214782, 0x271c82b3, 0xffdabe12, 0x68661e00, 0x0f838082, 0x41edff23, + 0x27478226, 0xff34335c, 0x0ad7a3ff, 0xff292586, 0x8bce4ced, 0x99e1ffff, 0x06b44198, 0x08250f82, 0xccc3feff, 0x260484cc, 0x7b8b0e05, 0x4834f815, + 0x8e480957, 0x745b2026, 0x531805bd, 0xcf5313e9, 0x06db2216, 0x4533914b, 0x33230c01, 0x540700ff, 0x33940d9d, 0x18119252, 0x220c3860, 0x823b06db, + 0x6dff20cd, 0x8f6d1392, 0x07db2216, 0x52338ccb, 0x00200de1, 0x210c1d55, 0x44838b34, 0xb508cc21, 0x49bb2033, 0x2e490edd, 0xfc270821, 0xffff0634, + 0x8b6626e7, 0x8eebffff, 0x1200ff56, 0xffff66e6, 0xffad8afd, 0x34331800, 0xffffff08, 0x00ff0bd6, 0x829a9901, 0x8cea2109, 0x98200983, 0x0129a082, + 0x0e0834b3, 0xa4f78bef, 0x190c8215, 0x221067b5, 0x88088b8f, 0x117241ef, 0x540e2341, 0xef8a0768, 0xd35433b8, 0x5667830c, 0x678f1275, 0xde1833db, + 0xfb21165f, 0x17334b34, 0x61b4fc21, 0x7f4a0c2c, 0x34f7280a, 0xb0fb0e07, 0x4b24f88b, 0xf72017d7, 0x0d3b0819, 0x430a6761, 0xb1439b49, 0x207d4312, + 0x3d415b20, 0x34fb2117, 0x29173d41, 0x0e0734f8, 0xf7d4f7ef, 0x154215d4, 0xf8ff210b, 0x22082258, 0x499b077b, 0x1a8a0c9e, 0x83066d44, 0x050f4911, + 0xb561ff20, 0x07b84315, 0x9e82ab20, 0x62180020, 0x9c2715d1, 0x00ffcccc, 0x82a4f01d, 0x997d3885, 0xe4ffff9c, 0xa105c2f5, 0x33faffff, 0x0f00ff34, + 0xffff9899, 0x829a99ec, 0x80e9286e, 0xfeff0800, 0x97ccccdc, 0x192642e8, 0x2301ff24, 0x36823433, 0x80160023, 0x08538200, 0xff48a126, 0x66661300, + 0xf51500ff, 0x0500ffc3, 0xff08cccc, 0x299c7d00, 0x0a1b00ff, 0x00ff053e, 0xff01008b, 0x9eaf5c00, 0x09210a82, 0x2b2582e6, 0xff3c2a07, 0x66e60e00, + 0x0a00ff8b, 0xff2eaa82, 0x08c4d5f8, 0xffff1ff7, 0x056250a3, 0x5982ffff, 0x62feff27, 0xf7155c0f, 0xf8561814, 0x34fb2332, 0x9e4ad4f7, 0x454b2017, + 0x2821094f, 0x056441f6, 0x6305a04a, 0x035a0d50, 0x41cb200a, 0xcd200564, 0xcd202c83, 0x2006d545, 0x05b463f7, 0x3b24f822, 0x450a3173, 0x4e850c6a, + 0x8b12ee4a, 0x06d6634e, 0x5913e541, 0x4b240a48, 0x5b24fc07, 0xba42cf8f, 0x64cfb807, 0xe8830617, 0x8082ff20, 0x088b3324, 0xcfba066b, 0xcf844e84, + 0x4e833420, 0x42106b64, 0x4b250ae5, 0xf744fb07, 0x28d082cc, 0x8b6666cf, 0x99d8ffff, 0x8204849a, 0x2010820a, 0x20068508, 0x08f975ff, 0x3000ff26, + 0x088b9a99, 0x16850685, 0x8b201b83, 0x2d821084, 0x3f841e83, 0xff201b85, 0x8b294382, 0x14f70e08, 0x66a900ff, 0x2d648266, 0xff66e68a, 0x9a198bff, + 0xf1ffff05, 0x04820080, 0x82486121, 0x54e82562, 0x0e00ff7a, 0x80210f84, 0x215c8200, 0x1a82c034, 0x0040cb23, 0x26158705, 0x00fffe7f, 0x8285ab17, + 0x9e0e2266, 0x201483b9, 0x27258202, 0xffc2f574, 0x3e0a7500, 0x1d242582, 0x00ffb81e, 0x20820482, 0x48212f27, 0xe1e2ffff, 0x220f8248, 0x89086626, + 0xffff290a, 0xffecd1d0, 0x34f3ffff, 0x85831382, 0x82e6e221, 0x3f012c1e, 0x01ff9a19, 0x159a9916, 0x822b14fb, 0xe6002a48, 0x38054d66, 0xe6acffff, + 0x270d8266, 0xffcdcc06, 0x34b3fbff, 0x2d05c271, 0xcc4cfbff, 0xb30500ff, 0xfaffff33, 0x80829a19, 0x82e00521, 0x40fa26a6, 0x0400ff00, 0x054671be, + 0x42260982, 0xf9ffff90, 0x1e820040, 0x52385223, 0x2a4482de, 0x0670fd3d, 0x195f00ff, 0x8214f79a, 0xe8c030f5, 0x0e05cbf6, 0xff54f7ef, 0x66e62001, + 0x828bab15, 0x197f2421, 0x826b079a, 0x8b491808, 0xdd240811, 0x8b081e85, 0x85ddffff, 0x1c00ff20, 0xffff9a99, 0xffe07ae2, 0x66662300, 0x54fb088b, + 0x8b1594fb, 0xa1dcffff, 0x1c21ea82, 0x227f829e, 0x82285ce3, 0x4861291b, 0xffab088b, 0xa4020000, 0x0c825987, 0x82200021, 0x82dc207a, 0x00002e24, + 0xffff32e6, 0xff4861e3, 0x0080e2ff, 0x205a828b, 0x27aa8280, 0x00805101, 0x681514f7, 0xd6210f82, 0x21d382c0, 0x1f82e1f2, 0x8273e321, 0x05ee30e8, + 0xffff081e, 0xffcd4ce7, 0xceccedff, 0x83ecffff, 0x4cf12709, 0xc3ffffcc, 0x848233b3, 0xff071425, 0x82803900, 0x05f02232, 0x216f821e, 0x0a82401a, + 0x4282f820, 0x821a0021, 0xfaff2604, 0x00ffb81e, 0x266c831b, 0x08b81efe, 0x822000ff, 0xfdff2dab, 0xffac00a0, 0xcaa10100, 0xde1f00ff, 0x06211f82, + 0x088182e0, 0x856d0020, 0x1600ff1e, 0x00ff0ec2, 0xbf9a1927, 0x2e00ff8b, 0x8b089a19, 0xabffffcb, 0xffab66e6, 0x7542a5ff, 0xe6992b05, 0x1701ff66, + 0xff1516d9, 0x5b83e0ff, 0x6a203b82, 0x20061658, 0x826683df, 0x26ae825b, 0xff9a99e4, 0x8220feff, 0x83e5208a, 0x84fa20a9, 0x34b32609, 0xc0f8ffff, + 0x291e8284, 0x7b0080c6, 0x80ffff05, 0xbc8266e6, 0x20057774, 0x20ad8313, 0x224182f0, 0x82cc1800, 0x85f021db, 0x0021f582, 0x25d7831c, 0xff4821ed, + 0xd6832900, 0x82c5f321, 0x0c2323a1, 0xc8828bcc, 0xd04c5a22, 0x332a6182, 0x5400ff34, 0x8bab9819, 0xb08208cb, 0x82592c21, 0xe6d83475, 0xffffbf68, + 0xfffe7f92, 0x7c7f1700, 0x34f80e08, 0x454b15bb, 0x5b2217cd, 0xcd44bb06, 0x11ae4305, 0x4505b543, 0xac430511, 0x075b220a, 0x18338c4b, 0x440c96d5, + 0xcd680538, 0x07934408, 0x5b075b22, 0x20179053, 0x227e83cb, 0x82666600, 0x4c0027bd, 0x0000ffce, 0x04829002, 0x08666627, 0x78c5ffff, 0x20f78252, + 0x27d28219, 0xff1f85da, 0x98193f00, 0x46222482, 0xe98334b3, 0x82b37b21, 0x997227f8, 0x6400ff9a, 0x5518cc4c, 0x9e1812c6, 0xb9200dc4, 0xff2b2382, + 0xff0080da, 0x68e6c0ff, 0x82c4ffff, 0xd6ff2337, 0x488266e6, 0x82ffff21, 0x0000290b, 0xffff66e6, 0x8b32b3ff, 0x992b0582, 0x078b089a, 0x64f794fb, + 0x18ffff15, 0x2309bd9f, 0xcd4ce3ff, 0x10821d82, 0xdc203483, 0x1c227d83, 0x9c5533b3, 0x23002105, 0x08211b82, 0x210684ff, 0x168300ff, 0x11eb9f18, + 0x1b853f83, 0x08245484, 0x14fb54f7, 0x940cfb55, 0x84d98232, 0xd65d1865, 0x568e9113, 0xdb63062b, 0xeb0e2305, 0x8a4624f7, 0xcd4c2109, 0x2105c741, + 0x33750800, 0x80752905, 0xeb2b0600, 0xeaffff05, 0x96180882, 0x33200e2f, 0xf729e782, 0x4b08cd4c, 0xf734f707, 0x4a5718c4, 0xfc8b225c, 0x225f8254, + 0x829a1996, 0xe6a92e72, 0x5600ff66, 0xff8b4821, 0xb8de6900, 0x30068208, 0xff486129, 0x00400d00, 0x5e2600ff, 0x1600ffb8, 0x2d098280, 0x089a591f, + 0x660b01ff, 0xf4feff66, 0xc0829a99, 0x66a6e025, 0x82e9ffff, 0xd9ff2b1a, 0xffff9a99, 0xffccccf2, 0xa943d6ff, 0x332d2305, 0x5f82f734, 0xcc52003d, + 0x076b06cc, 0x30cdffff, 0xffff06a4, 0xab9002e0, 0x6f00ff05, 0xffff9819, 0x8266e690, 0xe6d0267f, 0x2f00ff68, 0x214d8219, 0x2a822200, 0x0800ff24, + 0x7e8200c0, 0x96180720, 0xcb210dd9, 0x21138207, 0x8d4db308, 0x4c072207, 0x052043cd, 0xffff0830, 0x0634337d, 0xb383ffff, 0x7c00ff32, 0x5c820040, + 0x67661f22, 0x2620af86, 0xc3852682, 0x66662924, 0xdb82088b, 0x8266e621, 0x19562147, 0xf182ab82, 0xfd82f782, 0x1868ec82, 0x84bd8405, 0x2dd184c7, + 0x0832b3e0, 0x4ca4ffff, 0xef00ffce, 0xa9829a19, 0x4382f020, 0x00ff7e2d, 0xff34330b, 0xcc4cfdff, 0x840e00ff, 0x82ff2021, 0x0300210f, 0x8205c55a, + 0x80022714, 0xfcffff00, 0x6e823433, 0xc0efff25, 0x82860600, 0x60fc2165, 0xfb201382, 0x00221882, 0x0983a000, 0x82002021, 0xa6042a8b, 0xe1ffff66, + 0x00ff3413, 0x203c831a, 0x205183e8, 0x05736f20, 0x32b30f28, 0xffff988b, 0x1c82b3f4, 0x04820220, 0x66f1ff23, 0x22318266, 0x82cccc00, 0x6666245a, + 0x840300ff, 0x22508383, 0x82cccc03, 0x10002569, 0x9006862b, 0x0325da82, 0x00ff40b5, 0x23188204, 0x0040ffff, 0xe0200982, 0xff276982, 0xff3a5ffb, + 0x82ec1e00, 0x82e5203c, 0x17002119, 0xdf295183, 0x088bcecc, 0x01ffaf0e, 0x221283ef, 0x82cdcce0, 0x19fc28e0, 0xffffff9a, 0x82870080, 0x33b32405, + 0x83fbffff, 0x8271205b, 0xcce825bf, 0x0b00ffce, 0xff2a7882, 0xff9819f0, 0x9a991100, 0x0a82ff08, 0xee202d82, 0x1e831483, 0x83f4ff21, 0x67e520c4, + 0x0683057d, 0xe8ffff22, 0x3587ae82, 0x35929a20, 0xff82e620, 0xcc233585, 0x85088bcd, 0x88cd2067, 0x22318a67, 0x86ffff99, 0xffcd2167, 0xdc216786, + 0x23f58229, 0xa4f0fbff, 0xfb269d82, 0x00fff5e8, 0x1b824c00, 0xae07fc22, 0x80200982, 0xc825f383, 0x00ff14ae, 0x269d8307, 0xff33d3e5, 0x82334100, + 0x951d3604, 0x2e00ffc3, 0xff08cecc, 0x7b543900, 0xab5a00ff, 0x00ff0584, 0x2df58205, 0xa8260800, 0x1c0900ff, 0x0400ff29, 0x0982a0fa, 0x82e1ba21, + 0x6401245f, 0x8206cccc, 0x34b3220c, 0x8205828b, 0xfbff2326, 0x3083a205, 0xffff9825, 0x8316d9f7, 0xcc4c2646, 0x54a5ffff, 0x2646827c, 0xff34b31d, + 0x8219d1ff, 0x83e5201a, 0xe6be2e09, 0xc8ffff67, 0xffff0080, 0x089a99f8, 0x2146828b, 0x20823304, 0xcd4ce023, 0x05415315, 0x80000023, 0x216d8200, + 0xb18266e6, 0x8fcccc29, 0xffff088c, 0x659a993c, 0x775a17b5, 0xf6a82105, 0xe322ee82, 0xb5650a57, 0x00ff250b, 0x076666c3, 0xde225382, 0x05828ab9, + 0xff71fd24, 0x6982ffff, 0x82040021, 0xffff24cc, 0x82080080, 0xb81e225f, 0x22a1828b, 0x82904205, 0x23b1821b, 0xe27a0500, 0x99210982, 0x21cb829a, + 0xe882ae87, 0x700c0028, 0xff978ba4, 0x8d830100, 0x33330b22, 0x38834782, 0x827aff21, 0xd4f72190, 0x8522bb82, 0x6282cd4c, 0x57820b20, 0x99fcff26, + 0x0b00ff99, 0xff222882, 0x408219fe, 0xcc4c0c22, 0x05234083, 0x828b9a99, 0x8366204d, 0x220483cd, 0x82ce4c05, 0x05ba6977, 0x8bef0e28, 0xcc2401ff, + 0x218215cc, 0x17830720, 0x2b270225, 0x830700ff, 0x0804273d, 0x0600fff6, 0xa4829819, 0xdf8f4b27, 0x547100ff, 0x2ba8827c, 0xff67e608, 0x58590d00, + 0xf30e00ff, 0x08278b82, 0x00ff6005, 0x829a1910, 0x8c012367, 0x8e829899, 0x9c191022, 0x0e314b82, 0xffff64e6, 0xffa0faf7, 0x68e60800, 0xa6f2ffff, + 0x2b4683a8, 0xffff9899, 0x0584ab8e, 0xf9ffff8f, 0x00211682, 0x29b48302, 0x8b66e6f8, 0xb3f8ffff, 0x06820832, 0x34b3eb27, 0x80efffff, 0x82048600, + 0x2959820e, 0xd8a3c9fd, 0xebffff06, 0x2182f6a8, 0x1480ef22, 0x80217182, 0x24648200, 0x08cc4c14, 0x330082ff, 0xffcb06ec, 0x3433bbff, 0xfb06cb15, + 0x54f70734, 0x0734f706, 0x84200a82, 0x2017da47, 0x05fc70fb, 0x4d827020, 0x07cfd318, 0x26053051, 0x0784f708, 0x838b54f8, 0x79942047, 0xee221994, + 0x3982cc4c, 0xa982f120, 0x0af5a018, 0x0794f726, 0xf4f78b0e, 0x2105357a, 0xa918ff84, 0x877a0ff7, 0x34b32105, 0x23069e5d, 0x84abf1ff, 0xee224382, + 0xf4837c54, 0xff215082, 0x06045dff, 0x0e82fe82, 0x079ae018, 0x13954018, 0x34fbcb22, 0xb3216584, 0x21658733, 0x4018cd4c, 0x6a5d0899, 0xaacc201c, + 0xf4f72365, 0x8a7354fb, 0x82ee8a0f, 0xb31122c7, 0x20808834, 0x188098cc, 0x8f0e8cac, 0xff0e30e6, 0x9a19bc00, 0x33ed00ff, 0xffff1533, 0x8300c0d2, + 0x05012504, 0x402d00ff, 0x00200a84, 0x0f830a86, 0x20850520, 0x3f2d0023, 0x201582ff, 0x21368371, 0x3687b316, 0xbf212087, 0x8f2584ff, 0x84012041, + 0x21418251, 0x20827fa5, 0x34337823, 0x88628e15, 0xe6d12220, 0x211a8266, 0x2b82cc4c, 0x9999d322, 0xb3214c82, 0x264c8334, 0x01ffcd4c, 0x8266e633, + 0x807b27a4, 0xffff8b00, 0x9f828094, 0x0a820482, 0x08201082, 0xff220685, 0x16866b00, 0x8400ff22, 0x08202682, 0x16850685, 0x8b201b83, 0x2d821084, + 0x44851e83, 0x43823285, 0x2d828b20, 0x9a99ba26, 0x66e8feff, 0xf4216683, 0x826082c0, 0x21878204, 0x0a82e0fc, 0xfa210484, 0x327b83e0, 0xffb8defc, + 0x00200300, 0xe3ffff08, 0x00ff7ad4, 0x4100401c, 0xff2a061b, 0x0500c0d2, 0xdeffffad, 0xb482b81e, 0x48e11024, 0x048200ff, 0x2d820a82, 0xff243284, + 0x42200500, 0x03248582, 0xffff0621, 0x73825282, 0x87400b21, 0x84538368, 0x82cd8215, 0x820a8469, 0xb8de2704, 0xefffff08, 0x0484b81e, 0x7a205685, + 0x42835286, 0xbb952c92, 0x82bedf21, 0xdefc222a, 0x858884fa, 0x059c2252, 0x834a827a, 0x906c8645, 0x204a83e0, 0x41a28200, 0xa2830606, 0x0522be82, + 0x45840020, 0x212b0482, 0x9c9c0848, 0x00ff6905, 0x4148e121, 0xff220b05, 0xd8831c00, 0x00c0e322, 0x6741abb3, 0x82c02010, 0x05674170, 0xf7a8e327, + 0xc2e3ffff, 0x1d984190, 0xa285b7a3, 0x420abe41, 0xde2306c4, 0x4169b81e, 0x72410567, 0x82032007, 0x2c6b41ef, 0xef22bf8f, 0x0a42f728, 0xefff2306, + 0x568666e6, 0x85407741, 0x9c7a2152, 0x241b9c41, 0x400b00ff, 0x42048400, 0x00270e86, 0x0300ff8b, 0x42ff4821, 0x10230686, 0x827a9a19, 0xe1212321, + 0x4e82ad48, 0x51b8d227, 0x3d2d00ff, 0x240a8270, 0xff00c0e3, 0x410482ff, 0xcc211e6f, 0x846486cd, 0x142742d5, 0x820c6f41, 0xc30f8451, 0x0a6942bb, + 0xec832d20, 0x05210482, 0x22c68369, 0x42b81eef, 0xff2542df, 0x48e11000, 0x82a8829c, 0x990b844e, 0x434620b3, 0x324306d0, 0x43002005, 0x6f410bf6, + 0x48e1240f, 0x829c057a, 0x44249b55, 0xba22211b, 0x4d427a08, 0x69ad2105, 0x270daa45, 0xff52b8e3, 0xc2351c00, 0x4820ab99, 0x5f41aba8, 0x430a830a, + 0xb7bd0531, 0xff08b823, 0x095942ff, 0x23096e46, 0x7a05adad, 0xa71e6341, 0x419c20b7, 0x4d840518, 0x41468745, 0x9c20066b, 0x20497f45, 0x07b64169, + 0xc0d2ff24, 0x21430500, 0x4c5f410b, 0x210ac141, 0xc5821403, 0x2adcfc2b, 0xfaffff8b, 0xffff66e6, 0x270486fc, 0xff38fb08, 0x9a992700, 0x210f9947, + 0xfc47ff00, 0x0deb460c, 0x01ff0e2a, 0xff9a99f6, 0x66660901, 0x86063f48, 0x0cfa2a2c, 0x0500ffcc, 0xffff34f3, 0x5f5f82f7, 0xff240a17, 0x3433cdff, + 0x1805a751, 0x211364ae, 0x8f5134fb, 0x94d7180c, 0x075b210a, 0x40213a82, 0x0a1a6100, 0xbc824720, 0x8500a029, 0xffff0885, 0x82b8bed2, 0x66c62204, + 0x097b6105, 0x61cdcc21, 0x1d820571, 0xcd4c9d26, 0x0614f707, 0x83058358, 0x1907228e, 0x06654b9a, 0x66e60822, 0x8206397a, 0x20138508, 0x05114bff, + 0x9a19f724, 0x36ba6b08, 0x6200ff24, 0xd65f33b3, 0x2471820a, 0x85333308, 0x288f8291, 0xff666659, 0x9a993600, 0x2aed8215, 0x34f707bb, 0xbb075b06, + 0x831584fb, 0x002025af, 0xe0f8ffff, 0xf7220487, 0x097b0020, 0xaf521806, 0x07002108, 0x23053560, 0xab0800e0, 0x0887bc18, 0x3682ab82, 0xbb83d982, + 0x82ffff21, 0x2136860e, 0x54829a19, 0xd984cf82, 0x00ff8b22, 0x3685ee82, 0x8204fb21, 0x18ff209a, 0x2410877b, 0xf8088bb8, 0x877b1854, 0x04f72117, + 0x0e287085, 0xff14f9ef, 0x34331d01, 0xf936b183, 0xffff3e15, 0xfffcb4fd, 0x7a09f9ff, 0x47fbffff, 0xfafffff0, 0xe582142e, 0x3c0ace28, 0x5ec2ffff, + 0x1a8205b8, 0x8214ae21, 0x3934269f, 0xb3f6ffff, 0x21248234, 0x09822df2, 0x8b289c22, 0xf8222582, 0xa28370fd, 0xffa4f026, 0x12430200, 0x19263b82, + 0x0400ff9c, 0x1a8232a8, 0xb8f3c52c, 0xc22d00ff, 0xfeff05d1, 0xf6594cfb, 0x707d2605, 0x82eaffff, 0x24048690, 0x8b707de5, 0x054d4c08, 0x82008021, + 0x80ea2345, 0x1d5cff00, 0x01ff2f0a, 0x0734b304, 0x19c5ffff, 0xd2ffff99, 0x88823333, 0x33f3fa22, 0x66217e82, 0x258d8267, 0xffffa3f0, 0x198299fe, + 0x71fdf822, 0xf6228883, 0x4282ac9c, 0xb0b2f622, 0x0e217e82, 0x23b38598, 0x02cb0700, 0xc025c984, 0xc03c00ff, 0x27408200, 0xffae47fb, 0xcccc0500, + 0xb529f382, 0xff8b922c, 0x68e60600, 0x22068208, 0x82104309, 0x6b1c2b37, 0x2d0900ff, 0x0700ff94, 0x1a8225e6, 0x08703d33, 0x00ff1bf7, 0x059a996a, + 0xca0c00ff, 0x0a00ff51, 0x223e8207, 0x8266e60f, 0x23ca8243, 0x67660f00, 0x00247a82, 0x06008022, 0xb3213382, 0x25a68233, 0x00ffd8a3, 0x09823327, + 0x285cdd25, 0x4a2f00ff, 0x068305c5, 0x3a241682, 0x2200ffe2, 0x072d2083, 0x00fff6a8, 0x08285c2d, 0x992100ff, 0x223b829a, 0x829a5910, 0xde0f2784, + 0xfaffffb8, 0x6c829082, 0xff1ec526, 0x84ebf5ff, 0x86272082, 0xfffffeff, 0x82686695, 0xeb072282, 0x82d78288, 0x0400221a, 0x22e18219, 0x83ccccf6, + 0xcecc2af1, 0x70fb0e08, 0x24f894f7, 0x200e8215, 0x239782e5, 0x0080eaff, 0x18076241, 0x820c09c5, 0x15002316, 0xd47e707d, 0x69f68305, 0x1469054b, + 0x0ddf5d0d, 0x200ad87e, 0x2927827e, 0x33b368ff, 0xffffff15, 0x04829919, 0x8a9a9922, 0x0a830583, 0x082c0f86, 0xfbffff80, 0xff059a19, 0xc3b5f0ff, + 0x332aab82, 0xf4ffff33, 0xffff8f02, 0x258299f3, 0xcdccf92b, 0x80f0ffff, 0xffff0800, 0x22a683fe, 0x823433fc, 0x70f92d29, 0xefffffa4, 0xffff9a99, + 0x834761ed, 0x97260a82, 0x0600ff0a, 0x25829899, 0x0a85ef20, 0xf8251a82, 0x00ff1f05, 0x08248212, 0x8f060028, 0x1000ff5c, 0xff086666, 0x8f820100, + 0xcc0300ff, 0x00ff05cd, 0xffd7630c, 0x67e61e00, 0xfd1700ff, 0x1800ff71, 0x0e8266e6, 0xffe27a2d, 0x9a990d00, 0x00ff9608, 0x8266e604, 0xd7142a25, + 0x0900ff0a, 0x00ff3433, 0x224a8315, 0x82cccc04, 0x99992c2f, 0x00ff088b, 0x8b9a992c, 0x832800ff, 0x83e520b0, 0x19112120, 0xd6217582, 0x206683e6, + 0x22f7830e, 0x823333db, 0x33162640, 0xf5ffff32, 0x2571834c, 0xffcecc0f, 0xf782f8ff, 0x66060026, 0xecffff66, 0xf820db83, 0xf0223483, 0xba823433, + 0x2e820a86, 0x6582ec20, 0x82f9ff21, 0x82ff206f, 0x00ff2219, 0x22538307, 0x824ce5ff, 0x4c0d227a, 0x25ff82ce, 0xff33b3f5, 0x58830500, 0xbf83f720, + 0x34b30823, 0x057f70ff, 0xba820a20, 0xf6ffff23, 0x22d48266, 0x82ffff16, 0xb3ec2729, 0xbeffff33, 0x88820180, 0x93833120, 0xd484c920, 0x7e830520, + 0x7982fa20, 0x82030021, 0xf8ff213f, 0x0120fa83, 0xff260482, 0x083233f8, 0x2c822fa2, 0x6c820420, 0x83eeff21, 0x83f520af, 0x84ee2086, 0x222b8304, + 0x82ccccfb, 0x83ee20aa, 0x83fb20ba, 0x99ee2576, 0x0a00ff99, 0x1e824f84, 0x19110023, 0x211e829a, 0xaa82ccea, 0x32335822, 0xb9208082, 0x4d228b83, + 0x0a829a19, 0x8233f121, 0x821020b5, 0x82da8275, 0x82162034, 0x0600218f, 0x15200483, 0x00213483, 0x213f8310, 0xb5837f3f, 0xe13ac632, 0x4c39ffff, + 0x00ff15cd, 0xffc3f518, 0x66663e00, 0x022d9382, 0xff886626, 0xec510200, 0x33fdffff, 0x21098234, 0x09833d8a, 0xff083224, 0xe6832800, 0x8499d321, + 0x23518265, 0xceccdbff, 0xfd207082, 0xff219b82, 0x20d783f9, 0x83a084fc, 0x83fb2019, 0x80fb2209, 0x27a58200, 0xff7b54c2, 0xcc4cc2ff, 0xf3202982, + 0xf3321a83, 0xffff0280, 0x8b71bdeb, 0x80f3ffff, 0x0c00ff83, 0x2582fe7f, 0x0681f322, 0xfd500a82, 0x22758305, 0x84fa7e0c, 0x2575820f, 0xffa65b3b, + 0x9b823b00, 0x54f80e24, 0xac8234f8, 0x0b045118, 0x180c6e50, 0x2212a14a, 0x680604fc, 0xf8202dd6, 0x00203082, 0x0c95b718, 0xa982cc20, 0x34b3dc25, + 0x5374fb08, 0xfc211728, 0x31a06d14, 0x0614f825, 0x8cc4fb6b, 0x118650cd, 0xb3f1ff24, 0x1683ff34, 0x6e05a16e, 0x1b820da8, 0xee229982, 0x6a51cc4c, + 0x84288507, 0xb3112a32, 0x0e088b34, 0x54f794f8, 0x27238215, 0xff9a9972, 0x66668dff, 0x3c190486, 0xff200f82, 0x22399170, 0x82e653ff, 0xb38a2655, + 0xffff1534, 0x210a82ef, 0x04821100, 0xe6e3ff26, 0x1300ff68, 0xd8236f83, 0x828bcc4c, 0x4cd822b5, 0x208682cd, 0x201b83e3, 0x228b83ec, 0x8267e6ef, + 0x9a1921d1, 0xfa251a82, 0xffff9919, 0x2b2b82f9, 0x00800000, 0xccf6ffff, 0x0600ffcc, 0xf9232383, 0x83083433, 0x221e820a, 0x449a19fa, 0x2383061d, + 0x85060021, 0x82982023, 0xb30b231e, 0x6a829834, 0x00265882, 0xff34b30d, 0x07581b00, 0x661d2305, 0x16858b66, 0x4cf2ff22, 0x0b235082, 0x827e34b3, + 0x8205202d, 0x826b8227, 0x560a209c, 0x6b850675, 0x18820020, 0x4b826b84, 0x66845c84, 0x34330924, 0x7a84ffff, 0x08258f82, 0xffff068b, 0x27a1825c, + 0xcc4c6500, 0x1100ff15, 0xff226882, 0xb7830e00, 0x8209146f, 0x82012073, 0xffff2122, 0x0020de82, 0xcc260985, 0x0100ffcd, 0x5d826666, 0x48570a20, + 0x05672505, 0x660800ff, 0xfe20fe82, 0x0021f882, 0x20048309, 0x20b98303, 0x22298302, 0x82cc4c08, 0x83012029, 0x2023843e, 0x83bc83fc, 0xf7ff2123, + 0x082f2386, 0x2000ff2b, 0xff050100, 0x9999f7ff, 0x830200ff, 0x83f62054, 0x82fb20d6, 0xfdff238a, 0x18823333, 0x0834b323, 0x830a86ff, 0x99042523, + 0xf6ffff9a, 0x4c215384, 0x821884cd, 0x821e2063, 0xf5ff236e, 0x4882cdcc, 0x3483fa20, 0xfc240484, 0x8b830080, 0x33214082, 0x0a524233, 0x52423282, + 0x8b332106, 0xb6203882, 0x002ae082, 0x15cdcc36, 0x331e00ff, 0xcd839534, 0xbe84a483, 0xae84c884, 0x9a19fe22, 0x8884e684, 0x0a823220, 0x83822382, + 0x00ff6622, 0xf7208d84, 0xfd229283, 0xcd823433, 0xffdfff23, 0x838482ff, 0x84b385df, 0x84ae84c8, 0x82e682dc, 0xcc022275, 0x22d884ce, 0x820900ff, + 0xfcff2159, 0x00214e82, 0x23f18208, 0x67e60100, 0x0b201e82, 0x00234f82, 0x8266e603, 0xccff2548, 0xfeffffcc, 0x20058541, 0x21098266, 0xd1826766, + 0x6666fe22, 0x4a82d18a, 0x3220d186, 0xca41d183, 0xe6082117, 0xfc223f82, 0xbd82ce4c, 0xfa217383, 0x28c78233, 0x08cdcc05, 0xf80e068b, 0x31884474, + 0x4f185420, 0x00200ce1, 0x0a4e4e18, 0x1100ff22, 0x1251bf18, 0x0654f826, 0x152b54fc, 0xfb210682, 0xf95518b4, 0x0614232f, 0x4e1814f7, 0xff210f97, + 0x9ebb18ff, 0x14fb2414, 0x8e14fb07, 0x2856189a, 0xb4f7311f, 0xf72f0e07, 0x5e01ff84, 0xff1500c0, 0xcd4cf8ff, 0x73260482, 0xff707e34, 0x0b83fdff, + 0xccccd328, 0x2e00ff08, 0x578248e1, 0xea51fd23, 0x05ca6cff, 0x0100f323, 0x252782a6, 0x00ff3333, 0x20838c07, 0x66665e26, 0x40b1ffff, 0xfa3b4283, + 0x00ff00c0, 0xff00401f, 0x48a1ebff, 0xe11900ff, 0xe4ffff48, 0x00ffb85e, 0x8200400d, 0xa607214a, 0xed2e2982, 0xff901e05, 0x9a99e7ff, 0x800100ff, + 0x16827000, 0x9a192725, 0x826b8b06, 0xded82281, 0x206a82b8, 0x201582fe, 0x21218286, 0x6682b89e, 0x78486122, 0x1b202182, 0x00283882, 0xffae470d, + 0xce4c1400, 0xcc265782, 0x0500ffcd, 0x6b82cc4c, 0x08cd4c24, 0x3a828b44, 0x4382d120, 0x0200ff23, 0x28c282cc, 0x9833b3d3, 0x00e5ffff, 0x06324a01, + 0x8480f821, 0x2b1a827b, 0x00800700, 0xff0c00ff, 0x1a00ffff, 0x02200483, 0x2c208483, 0xff224282, 0x1983bfff, 0x66666622, 0xe4274a82, 0xffff6766, + 0x8234b3f2, 0x999929c4, 0x19e6ffff, 0xfaffff9a, 0xe0210e83, 0x23ee83cc, 0x06482127, 0x9126ba82, 0xff90a6eb, 0xfb821800, 0x99070024, 0xa4829e99, + 0x2883f920, 0x9a991925, 0x18b4f715, 0x2117d648, 0xdf82c4fb, 0x08c97318, 0x18ffff21, 0x21093cca, 0x3382d4fb, 0xfacaff28, 0x2a00ffe2, 0x1d19e1fa, + 0xf7210b86, 0xcb7c18d4, 0xb80b361a, 0xf9ffff52, 0x00ff9c64, 0xffcccc09, 0x649bf6ff, 0x940500ff, 0x238d827c, 0x072a5c51, 0x00281585, 0xff70bd08, + 0x34330600, 0x9932fa82, 0x00ff8b98, 0x0834330e, 0xa4f764fb, 0x4600ff15, 0x108200c0, 0x00403925, 0x83c6ffff, 0xb9ff260a, 0x8b080040, 0x840683ff, + 0x82048611, 0x088b2115, 0x1b821584, 0xff212882, 0x82328200, 0x823e8238, 0x8245832d, 0xcd4c2111, 0x54821684, 0x8b33b328, 0xfc24f708, 0x58181514, + 0x542010bb, 0x0a877d18, 0x1464c218, 0x4b06b435, 0x46ffff07, 0x00ff66e6, 0x159a99a9, 0x66f8ffff, 0x41869e67, 0xff240568, 0xa60080fe, 0xd8238682, + 0x8206cdcc, 0x824c20e6, 0xb3e02bf0, 0x1400ff33, 0xffff6766, 0x098233e6, 0x99991b32, 0xb3f2ffff, 0xfb0e0834, 0xffb4f730, 0x34b35900, 0x0d36e482, + 0x00ffe2fa, 0xff881608, 0xcc8c0300, 0xf31500ff, 0x0b00ffb6, 0x04849a59, 0x0a890820, 0x32201983, 0x87212382, 0x262d82ae, 0x00ff0c17, 0x8270fd0d, + 0x8307201e, 0xca0d223d, 0x218a823e, 0x6c82902f, 0xff00c02c, 0x0a350400, 0xc00f00ff, 0x0b4d0800, 0x0f002a05, 0x00fffe3f, 0x99666610, 0x2206828b, + 0x85080080, 0xffff2306, 0x7982baee, 0x20050e27, 0xeefbffff, 0x21318214, 0xbe82c035, 0x02cbfb22, 0xff243c84, 0xaad10700, 0xff235085, 0x82e405f8, + 0x3eca216f, 0xf7221e82, 0x0a82fce9, 0xff237482, 0x82560eea, 0x3c8a268e, 0xa6f4ffff, 0x20a78366, 0x3c58199c, 0x98592608, 0x75fcffff, 0x20b283c2, + 0x82f18234, 0x08002361, 0x1e820a17, 0x8235f221, 0xfa072714, 0xebffffa0, 0xb2830040, 0xffff4823, 0x230982f0, 0x18360400, 0xf1301e82, 0x00ff1ea5, + 0x7d341304, 0x451100ff, 0xefffff1e, 0x8305be4c, 0x857d2006, 0xf0ff23ae, 0xae84cdcc, 0xf0222d82, 0x0a823333, 0x82cccc21, 0xcd4c214c, 0xcf26ae82, + 0xf2ffff5c, 0x5682142e, 0x82ae0721, 0x05f2211e, 0xf7224182, 0x8a85f6e8, 0x0ceaff23, 0x23a985ce, 0xf4a8f4ff, 0xf4211e82, 0x271982a8, 0xff68a6f4, + 0x3d0aeaff, 0x2d842386, 0x1e823782, 0x1f05f822, 0x9a834d82, 0xecd10722, 0x33206182, 0xfb21c882, 0x222882ca, 0x82cc4cf0, 0xebfb221e, 0x20b98285, + 0x241482b3, 0x7d16bbee, 0x20aa848b, 0x83068508, 0x223b82bb, 0x82e1faf1, 0x821120cb, 0xcaf0233b, 0x0a82083e, 0x82fe3421, 0x23508231, 0x912df8ff, + 0x40215082, 0x21b28201, 0x6482dbf9, 0x82c23521, 0x1908221e, 0x820a8224, 0x15002db2, 0xffffa4f0, 0xff0080fc, 0x0a570b00, 0x9921b282, 0x0605429a, + 0x22056741, 0x823e8a03, 0x28cc82b2, 0x71fd0d00, 0xe6f7ffff, 0x421e8266, 0x05260500, 0x1400ff60, 0x578270bd, 0x4120d221, 0xff2305c3, 0x820acafb, + 0x420f2b1e, 0xfbffff90, 0xff990ef8, 0xb382eeff, 0x80100024, 0x16828b00, 0xff220683, 0xe9820e00, 0x45110023, 0x2131821e, 0xb2845238, 0x0f221a82, + 0x0a828fc2, 0x82f62821, 0x21308250, 0xfe82f8ff, 0xcc0d0032, 0xfb0893cc, 0xa600ff44, 0x8b15cc4c, 0x452c00ff, 0x23276582, 0x00ff5ccf, 0x82e0ba23, + 0xa430210e, 0x2c205483, 0x11820682, 0xff2a1682, 0x8b2045dc, 0xbad3ffff, 0x068308e0, 0xff7bd425, 0x8230dcff, 0x2bdc22db, 0x21158285, 0x2d825ccf, + 0x82d3ff21, 0x23168506, 0xcdcc2300, 0x33325483, 0xffff0833, 0xff10b891, 0xcccc0eff, 0xfcffff15, 0xe58200c0, 0x6082cf20, 0x82780121, 0xb5f62c14, + 0x0500ff3e, 0xfffff0a7, 0x82e23af9, 0x260a85a8, 0x00ff0040, 0x82bfdf08, 0x1cda212d, 0x972a0982, 0x0100ff0a, 0xff0800c0, 0x70822d00, 0x08090028, + 0x00ff05f6, 0x4d826e15, 0xe2bad522, 0x04220a82, 0x53824220, 0x8240d521, 0xd723272a, 0x0900ff86, 0x8c829a19, 0x58000023, 0x27818204, 0xffff5100, + 0xfe020000, 0x58210482, 0x2004820a, 0x21478304, 0x61828009, 0x82600021, 0x26082204, 0x20808267, 0x201e82b4, 0x08668303, 0x4acc082c, 0x2100ff08, + 0x00ff7b94, 0x057a1452, 0x4acaffff, 0x0400ff3d, 0xffff96a3, 0xffc2b5cf, 0x227b1700, 0xccdbffff, 0x2300ffcd, 0xd9827cd4, 0x1864df2d, 0xdcadffff, + 0x01ff05d8, 0x828ae15b, 0x9a192134, 0xdb279682, 0xffff9ad9, 0x82862bdc, 0x34b32634, 0x85e8ffff, 0x2448821e, 0xffffff3f, 0x052550fb, 0xff235e82, + 0x8286ebad, 0x980322ba, 0x2aba8210, 0x00fff833, 0xff602508, 0x824cfaff, 0x239c837d, 0xb89effff, 0x00220a82, 0xb2824861, 0x82f6e821, 0x28b1823a, + 0x9a19ffff, 0x330100ff, 0x22dd8332, 0x82101809, 0x220822dd, 0x219e82d2, 0x048216f9, 0x82b81e21, 0xc22a2144, 0x15273582, 0x00ff146e, 0x82ae472a, + 0x302d275f, 0xf6ffffa4, 0x0a820af7, 0x6a830820, 0x8340fe21, 0x42e026f3, 0x250300ff, 0x26f882e4, 0x00ff66a6, 0x4100c006, 0x00230679, 0x8218c406, + 0x10782660, 0x4b0900ff, 0x05ac4144, 0x30080023, 0x21e883a4, 0xdd82c455, 0x05f21d28, 0xd4f8af0e, 0xde4c15cb, 0x10757a05, 0xcdfeff25, 0x1806cc4c, + 0x2e102edf, 0xff3b5f69, 0x32b39600, 0xf9ffff05, 0x8291beff, 0x06a12158, 0x1921ac82, 0x44c1839a, 0x082005c1, 0x0021df82, 0x24278303, 0x919a1908, + 0x22908291, 0x82c5a096, 0x66a62d34, 0x00ff9705, 0xff90020c, 0xcd4c1000, 0xbd22ac82, 0xfe829c70, 0xb3320122, 0x19086018, 0xfb079422, 0xaf2d3a82, + 0xff1566e6, 0x9a192f00, 0x19d0ffff, 0x237a829a, 0x5c66e6d0, 0xf6260682, 0xffff34b3, 0x7b8299f6, 0xccf0ff23, 0x24e982cc, 0xffffcc4c, 0x828582f7, + 0x66662b0a, 0xccf5ffff, 0x0f00ffce, 0x9b853433, 0x0a00ff24, 0x8d823233, 0x1ae62f21, 0x8455d12b, 0x0797745f, 0x7f867582, 0x66660922, 0x2106e078, + 0x9f830900, 0x8b20a982, 0x0482b584, 0x0834b323, 0x21d3825c, 0xcc8266e6, 0xe384d982, 0xc2820a82, 0x2c8ecc86, 0xf2953284, 0x0e078b28, 0xf8f4f7ef, + 0x26521534, 0x07872716, 0x667600ff, 0xa5820668, 0xff646626, 0x5c4f1500, 0xe62e0482, 0x0e00ff68, 0x00ffa4b0, 0x8bcc4c19, 0xf84eff08, 0x1859200c, + 0x42078d61, 0xff231720, 0x8234b3e6, 0x19ea221b, 0x26448298, 0xffff34b3, 0x829c99f5, 0xcc4c2153, 0xbd22ee82, 0x69829819, 0x66e63a2c, 0x66d8ffff, + 0x2800ff66, 0x2b490200, 0x82052006, 0xb4ff232e, 0x6d829a19, 0x00800422, 0x68174072, 0x4b2018be, 0x540cc656, 0xcb210a94, 0x081c7207, 0x0f760f19, + 0xcc4c0322, 0xfa263582, 0xffce9a19, 0x8d83d5ff, 0x66663823, 0x26f38250, 0xff0834b3, 0x824cf7ff, 0x4cf32515, 0xf1ffffcc, 0xff2a3782, 0xff9a99f7, + 0x6666efff, 0x6983088b, 0x18850883, 0x82080021, 0x232c8238, 0x0c00ffcd, 0x50233782, 0x83e6ffff, 0x66d52533, 0xc7ffff67, 0xfa233383, 0x82489919, + 0x4c0322d3, 0x7cd3b5cd, 0xd38a1306, 0xff717d22, 0x2305247d, 0x8b8f821a, 0x04226782, 0x6782ae87, 0xae07052f, 0xe64b00ff, 0x2800ff66, 0x00ff3e0a, + 0x21c18240, 0x0e833a00, 0x9a992722, 0xbd2ddb82, 0xff069919, 0x9999f5ff, 0xb3eaffff, 0x20048234, 0x20dc8219, 0x22b783f1, 0x8233b3e6, 0xdcff2145, + 0x13934918, 0x7eff8b21, 0xff241452, 0xcd4c1900, 0x15201b82, 0xff265f82, 0xff5c4ff1, 0xfc830a00, 0xa4b0ea22, 0x76248e82, 0x8f066766, 0x3317cd7d, + 0x235306cb, 0xbb06bb15, 0x5b065b07, 0xfb64fb07, 0x075b1584, 0xf8230e85, 0x85155b64, 0x06bb2e16, 0x4e01ff0e, 0x154b0080, 0x1e1700ff, 0x296783b8, + 0x00ff9042, 0xffb89e0c, 0x04830b00, 0x90021422, 0x10206782, 0x0023bc82, 0x50842b1c, 0x2022060f, 0x29826866, 0xcccc2223, 0x22068208, 0x82482124, + 0xd8e324ec, 0x822100ff, 0xeeff2130, 0x00230482, 0x8248e11c, 0x802b2835, 0x2b00ff00, 0x8205b85e, 0x42602636, 0xa0f6ffff, 0x260a8200, 0xff004006, + 0x82c0f9ff, 0x210a221a, 0x833f8248, 0x8200200f, 0x22308204, 0x82b2480b, 0x87602076, 0x82158325, 0x86268220, 0x3d062730, 0xffff0870, 0x9c825ecb, + 0x82c03421, 0x84468525, 0xdef52150, 0x0f84bc82, 0x25820483, 0x5e8ff428, 0xa1f4ffff, 0x3b850548, 0x8b201583, 0xde20a782, 0x30843b82, 0x83c2f921, + 0x660922d8, 0x20978266, 0x21a2829e, 0xb882d8ff, 0x30820483, 0xb883f420, 0x82610b21, 0xfdf222d7, 0x82bc8270, 0xf1ff2834, 0x00ff48e1, 0x82004008, + 0x010021a6, 0x9a254482, 0x9b059a19, 0x16c36806, 0x0000ff2a, 0x00ffd800, 0x051ec51f, 0x0820c082, 0xf82d3f83, 0x00ff66e6, 0xffd82307, 0x9a19f7ff, + 0x27a0828b, 0xff9a191f, 0x54d5ffff, 0xf7226f82, 0x9b820040, 0x8fc2f827, 0xe3f8ffff, 0x220a82d6, 0x83b81ef7, 0xd7e32567, 0x28e0ffff, 0xff234383, + 0x820020f7, 0x4220213e, 0x27054e59, 0xbfdf0800, 0x069b088b, 0x66202a82, 0xff318782, 0x47a1c6ff, 0xccdeffff, 0xd9ffffcc, 0xffffb85e, 0x216282c2, + 0x1d820844, 0x8240dd21, 0x40092536, 0xdfffff83, 0x1026d383, 0xffff7d3f, 0x5c83dee3, 0x82a10b21, 0xfaeb25de, 0x1500ffe2, 0xff222382, 0x9e8266f3, + 0xb91e172a, 0x71f7088b, 0x49ffff06, 0xfc392d83, 0xff159a99, 0x52f81700, 0xde0d00ff, 0x00ff05b8, 0x070080b5, 0x076000ff, 0x21df82ae, 0x1082ae47, + 0x4e040027, 0x334affff, 0x830a8233, 0xf2ff2326, 0x0a824721, 0x94b6182b, 0x9ef1ffff, 0x1300ffba, 0x2591824c, 0xff32b3ea, 0x50820c00, 0x19e7ff2a, + 0xfeff089a, 0x069002ff, 0x7d201082, 0x22079756, 0x82cd4c13, 0xce4c3684, 0xb31800ff, 0x0e00ff33, 0x0e086666, 0x74f730fb, 0xf71554f8, 0x0ed54304, + 0x27087e57, 0xfc0764fb, 0x64f70614, 0x28177278, 0x4bab069b, 0x05cbab05, 0x250786ab, 0xb4fb34f7, 0x4a546b15, 0x064b2217, 0x201a8a4b, 0x069547cd, + 0xad43dc20, 0x83068206, 0x2ca58211, 0x8b34b31c, 0x4c2300ff, 0x07cb08cc, 0x177d544b, 0xf807ab29, 0x54fb0614, 0x771544fb, 0x0b7e0e05, 0x23d36d11, + 0x78ff8b21, 0x0e251485, 0xf874f72f, 0x22628254, 0x82cccc7c, 0x33632593, 0xdcffff34, 0xff260a83, 0x083433d3, 0x7066e4fb, 0x986b2017, 0x66cf8218, + 0xab24148b, 0x0654fb07, 0x3320368b, 0x2206f865, 0x5bcd4cee, 0x66180597, 0xad1a14ee, 0xf72018a1, 0x002b9b83, 0xffcccc2c, 0xa4306300, 0x822300ff, + 0x7c002aba, 0x088b5ccf, 0x94fb34fb, 0x055d5515, 0x55050b66, 0x11200589, 0x09238c18, 0xf266b320, 0x0ab55507, 0x22057451, 0x8534b311, 0x0ab85596, + 0x5194fb21, 0x4d830c62, 0x08265d85, 0x9b0714fb, 0xc81824fb, 0xf7225c73, 0x67568bb4, 0xf8af2a5d, 0x4900ffb4, 0x8b159a99, 0x05684a85, 0x9efaff2e, + 0xfaffffb8, 0xffff00c0, 0x089042fd, 0x80200582, 0xfe210a82, 0x200482a0, 0x201483c5, 0x230983e1, 0x8b0040b7, 0xf9231a82, 0x828b42e0, 0xbe1f252b, + 0x200000ff, 0xfa202082, 0x09832a82, 0x00ff0828, 0xff48610b, 0x3082e9ff, 0x1e050024, 0x1f827bb8, 0x1f824020, 0xb81eff22, 0x01211a82, 0x200a82e0, + 0x200f83fa, 0x452f82fe, 0xfb20056e, 0xff232982, 0x8248e1fb, 0x83fb2054, 0x210f841e, 0x8982bef9, 0xfa232384, 0x4cff9042, 0xff3c057b, 0xff765efe, + 0xfe760000, 0xb0e0ffff, 0x0a00ffe6, 0xfffff831, 0xffa4b0db, 0x66661700, 0xd5273d82, 0xff07a430, 0x82feffff, 0xb8f22739, 0xf5ffff52, 0x0486cc4c, + 0x8318f220, 0x00200f00, 0x09b47f18, 0x2a00ff24, 0x37825ccf, 0xff234883, 0x839a99e8, 0x82a4205c, 0x5ccf2137, 0x5e204a82, 0xff224b82, 0x5c82ae87, + 0x7a46b485, 0x83012008, 0x24b482be, 0x400400ff, 0x831e8200, 0x820a83b4, 0x23198233, 0x48210600, 0xcd82b482, 0xbd050023, 0x22f78270, 0x82b83e00, + 0xe2ba350f, 0x190500ff, 0x1000ff9a, 0x00ff3233, 0xff66660b, 0x9a191600, 0xfa223d82, 0xb882be7f, 0xff232e82, 0x868a21fa, 0xdef92309, 0x1a828bb8, + 0x0040b727, 0xc6ffff8b, 0x252b82a6, 0xff48611e, 0xa182fcff, 0x5e010023, 0x271a82b8, 0xff00c0fa, 0x34b30200, 0x2705bc41, 0x66660500, 0x8b08918b, + 0x48826282, 0x82030021, 0x050022aa, 0x20868281, 0x20098305, 0x21868402, 0x3182a001, 0x1e830020, 0x82c11e21, 0x01102119, 0x2c200482, 0x0022e382, + 0x5083de08, 0x5083bf20, 0xba824b20, 0x83ecff21, 0xab562233, 0x228b8286, 0x828fb81e, 0xe1fe226b, 0x21588247, 0xc582e03a, 0x0520df83, 0x03218583, + 0x223e82e1, 0x8266e603, 0x1e0324df, 0x7c8f8eb8, 0x00210501, 0x82b18204, 0x20012112, 0x0020b882, 0xcf850582, 0xc0210986, 0x201a8200, 0x37778204, + 0xcc2cffff, 0xb85100ff, 0xedffff52, 0x00ffce4c, 0xff66e64a, 0xccccc3ff, 0x662e1e83, 0xff8b0766, 0x66e67600, 0x5e00ffc7, 0xe48268e6, 0x8f00802a, + 0x00ff8e08, 0x90cc8c04, 0xa6830d82, 0x714f0520, 0x2a068305, 0xfdffff90, 0xff8e0040, 0x8360fbff, 0x8202205d, 0xfbff2fa0, 0xffc7b8fe, 0x7c14a1ff, + 0x89ffff8b, 0xc1823233, 0x9a99fb2b, 0x4900ff07, 0x00ff9a19, 0x25dd833c, 0xfffe7f53, 0x4a831200, 0x62830320, 0x99840020, 0xcc4c0127, 0x400000ff, + 0x21ca8200, 0x09829c19, 0x01232d83, 0x838b9819, 0x24d68295, 0xfeffff8f, 0x231c8260, 0x88482103, 0x03201282, 0xff223d82, 0x108220fc, 0x00a00125, + 0x82faffff, 0xfeff221a, 0x830983e0, 0xffff384c, 0xff870020, 0x4841ecff, 0x5ea9ffff, 0xbfffffb8, 0xffff70bd, 0x827ad4b4, 0x612c2139, 0xf7201482, + 0x1e203983, 0xef224383, 0x7182b8fe, 0x23829e20, 0x4821ff22, 0x05201e82, 0xff288682, 0xff3453fd, 0x34330300, 0xeb825882, 0x19280582, 0x2f0e089a, + 0x99b600ff, 0xc925c282, 0xff156666, 0x06995bff, 0xeb217182, 0x598318cc, 0x0c002307, 0xee820080, 0x52f8af24, 0x218205db, 0x5b8f8221, 0x7d210da0, + 0x820f8471, 0x71641864, 0x8f42220a, 0x2115828b, 0x51845278, 0x382b1a82, 0xffff0180, 0x0532b3c6, 0x828a00ff, 0x8900238a, 0x0a827c54, 0x7d233085, + 0x1800ff70, 0x210be1ed, 0x64189082, 0xe5830ea2, 0x08219887, 0x26be82fb, 0x05ae0760, 0x9d74fb8b, 0xf87f24af, 0x8314f7d5, 0x19515cb0, 0x7d7f0c22, + 0x7f82bb84, 0x8020b085, 0x6982f882, 0x68207f82, 0x9620bb83, 0xea20b084, 0xe922b083, 0x6518ce4c, 0x34200e53, 0x3089e183, 0xed18cb83, 0x4b860d11, + 0xfb94fb37, 0xaf0e0594, 0x157bb4f7, 0x00ff065b, 0x07cc4c7d, 0xcca800ff, 0x210482cc, 0x538234b3, 0x43820f20, 0x04820020, 0x00ff8023, 0x350a821a, + 0x9a19eaff, 0xfeff088b, 0x06e23a91, 0x1eeaffff, 0xff808bfa, 0x2386e5ff, 0x9c5fff20, 0xa8002805, 0xffff33b3, 0x82cc4c57, 0xb38228de, 0xffff0734, + 0x468b0cd0, 0xab280e58, 0xffff8b86, 0x087a54ee, 0xf7200682, 0x0d6c0119, 0x9eef0722, 0x00216182, 0x87a018bf, 0xd6082215, 0x24ff8204, 0xff32b302, + 0x13c14600, 0xf824f729, 0xffff1564, 0x82b85ec1, 0x3acb2658, 0xd7ffffe2, 0x27e982c0, 0xffcc4cec, 0x0040c8ff, 0x342b3a82, 0xff060080, 0xb89e1000, + 0x831c00ff, 0xa11e25b7, 0x1300ff48, 0x23200983, 0x20833482, 0x8b48e13b, 0x382a00ff, 0x568b6052, 0xff568b08, 0x48e1d4ff, 0xccffff60, 0x088b1e05, + 0x2055827d, 0x225082f2, 0x82400300, 0xe1f32155, 0x05213a82, 0x21558260, 0x1482dcff, 0x05230483, 0x821500ff, 0x84ff2015, 0x5e192624, 0xf7ffffb8, + 0x206982de, 0x225a851b, 0x8200804f, 0x993f255a, 0x4000ff9a, 0x10820a84, 0x11820820, 0xff230682, 0x8261c0ff, 0x8140254d, 0xb0ffff48, 0x08301b82, + 0xffacf70e, 0x34b32e01, 0x2100ff15, 0x9b07cc4c, 0x0d22b482, 0x2c82cc4c, 0x34b30a23, 0xf40e19ff, 0x1811820a, 0x2a136055, 0x19afffff, 0xffff069a, + 0x829999f3, 0x4cf526b3, 0xf5ffffcd, 0x207d8240, 0x298518ff, 0x2045820a, 0x20218233, 0x204f8273, 0x0589620c, 0x66e61022, 0xde373382, 0xff0714ae, + 0x99998fff, 0x05f4ffff, 0xa8ffff20, 0xffff6666, 0x8266e6a0, 0x668c2648, 0x54f80866, 0x20748206, 0x84c58273, 0x5f002319, 0x2d839a19, 0x08979a2c, + 0xffff64f7, 0x15cc4c01, 0x458264fc, 0x83c0f221, 0x8274826e, 0x82b88379, 0x829a208a, 0xf1ff23ec, 0xbf82cecc, 0x8400c021, 0x00ff2716, 0x8b9a590c, + 0x3082f808, 0x830d0021, 0x0a00219f, 0xae461982, 0xe600270c, 0x0e00ff66, 0x56183233, 0x0e2b1043, 0x80ee01ff, 0xc100ff00, 0x82153333, 0x48a12fa9, + 0x7a4700ff, 0xffff05e1, 0xffe4e5fb, 0x36821900, 0xcff3ff26, 0x1700ffde, 0xed320983, 0x00ff727d, 0x08208512, 0xabccffff, 0x3300ff84, 0x29827a54, + 0xe27aed22, 0xff241584, 0x5238e8ff, 0x2e2b8b82, 0xe6ffff14, 0x00ff9819, 0x829a1904, 0x82b82029, 0x0b0023d9, 0x29820a57, 0xcd4ce622, 0x1c211582, + 0x05ed4228, 0xc7fbff23, 0x213382ae, 0x7782cdcc, 0x82f62821, 0x33bf2729, 0xdeffff33, 0x298234f3, 0x8287e821, 0x2bf4271a, 0xedffff86, 0x04824721, + 0x828e0221, 0x820c2024, 0xa6e82229, 0x27298266, 0xff9919df, 0x0080bfff, 0xf4222982, 0x4482f628, 0x825d8f21, 0x8fc226b1, 0x66e5ffff, 0x84788467, + 0xff082b82, 0xb85e0b00, 0x85b8ffff, 0x1583051e, 0x1583db20, 0xa2829a20, 0x82633021, 0x82212033, 0x821221eb, 0xed223382, 0x2982285c, 0x7b543322, + 0x2982d684, 0x1f851222, 0x99207382, 0x17202982, 0xf322a283, 0x0a413eca, 0xe3fb2206, 0x222982d6, 0x820ad747, 0x48a1218d, 0x19222982, 0x2a41afc7, + 0x7d1a2206, 0x26628270, 0x00ff2438, 0x82323317, 0x2cd52177, 0x40272982, 0x00ffcccc, 0x82cc0c21, 0x51172229, 0x821582ec, 0x12002439, 0x82ffe0fa, + 0x82e22004, 0xc4f5210e, 0x51212e82, 0x272982ea, 0xff5ccf20, 0xec914000, 0x0b222982, 0x158272fd, 0x82a87021, 0x3433214e, 0x22063144, 0x8266e6fb, + 0xffff3d82, 0xc1feff08, 0xffff0080, 0x1533b38f, 0x61eeffff, 0xffff8b48, 0xff1e85f2, 0xb85e0e00, 0x0eb57718, 0xff231182, 0x827a0d00, 0xba102366, + 0x62828be2, 0x28840683, 0xf1ffff23, 0x223883a1, 0x821e45ef, 0x82002016, 0x05ff745a, 0xf182f120, 0x83f2ff21, 0x66ee2a5e, 0xab088b66, 0x199f00ff, + 0x82669a9a, 0x214f8250, 0x54854861, 0xb8100023, 0x98841852, 0x8a788309, 0x82a68266, 0x83ab826d, 0x827d825d, 0x266283bb, 0xffff34f7, 0x9a66e680, + 0x9e112263, 0xbb5e86b8, 0xff0e23ca, 0xdc82ee01, 0x84c00021, 0x5ebe21cf, 0x00385382, 0xffffffd1, 0xffae07cb, 0xd8513500, 0x4100ff8b, 0xff088fc2, + 0x9042beff, 0xca27aa82, 0x00ffd6a3, 0x8252f834, 0xce4c2121, 0xa1211a82, 0x3b1a8248, 0xff0a57e6, 0xf4dd0300, 0xdce5ffff, 0xfbffff29, 0xfffffce5, + 0xffaf07e9, 0x242af4ff, 0xbf2d1e82, 0xffff1d45, 0x055c0fdf, 0xa6e8ffff, 0x26158266, 0xffffce0c, 0x428f02ed, 0x302112bc, 0x08bc42a4, 0x42cd0c21, + 0xc72107bc, 0x215882ae, 0xbc421f85, 0xfae52206, 0x0ebc42e0, 0x5e821a20, 0x9a19e627, 0x300c00ff, 0x83338221, 0x05a64209, 0x29837a20, 0x825c3321, + 0x9ccc2792, 0x00ff052a, 0x49828712, 0x166eed2c, 0xb31700ff, 0xf3ffff33, 0xbc4266e6, 0x66e62107, 0x210ebc42, 0xc78267e6, 0xff24e626, 0xb85e1a00, + 0x37217882, 0x263382dc, 0x00ffec51, 0x8234d50b, 0xcf402229, 0x12bc425c, 0x4270fd21, 0xd42107bc, 0x08bc427c, 0x4214ee21, 0xca2108bc, 0x2015823c, + 0x2239820f, 0x82343304, 0xce4c2458, 0x83fcffff, 0x80192dac, 0xfeff0800, 0xff6666c1, 0xcccc90ff, 0x0ed67b18, 0x420bbc42, 0xbd180e55, 0xbc4212d9, + 0x07554208, 0x9a99f124, 0x5542ffff, 0x0eb84209, 0x4242f120, 0x091f4306, 0xb84262c1, 0x2b63d30f, 0xcb14f70e, 0x0674f715, 0x74fb074b, 0x0e293519, + 0x22081150, 0x180794f7, 0x184abedf, 0x210b0052, 0x5e48f1ff, 0xf4fb2708, 0xf794f707, 0x86821594, 0x8207cb21, 0x56ff2090, 0xfb23153b, 0x75ab0794, + 0x34200fbb, 0x8506fa4e, 0x052b4f06, 0xb3f1ff2b, 0xeeffff34, 0x088bcc4c, 0x0ce24f6b, 0x85064b4f, 0xa853181a, 0x0b774f0b, 0x0e07f430, 0xf8d4f8ef, + 0x94fc1514, 0xdcffff06, 0x5a82cdcc, 0x3333e326, 0x33e3ffff, 0xdc236c83, 0x8208cccc, 0x82148288, 0x00ff2409, 0x84cdcc1c, 0x24b28219, 0x088b3333, + 0x213382f8, 0x28832300, 0xcc201982, 0xcc211e83, 0x241a838b, 0x94f70834, 0x86098507, 0xcc1c222e, 0x05da50cc, 0x94fc0825, 0x82157cfb, 0x6604271b, + 0x0300ff66, 0x048248a1, 0xff9a9929, 0xb95e0400, 0x829b088b, 0x610422ef, 0x231d8248, 0xffb99e03, 0x0c831119, 0xfb208182, 0xff232782, 0x844761fc, + 0xffff2718, 0x8bb89efb, 0xb4827b08, 0x47a1fb22, 0xfc221d82, 0x4a84b85e, 0x08275a85, 0xa4f7079b, 0x82fb1533, 0x18ff20a0, 0x2109849e, 0xab840700, + 0xd4820820, 0x06822682, 0x1182ff20, 0x04833320, 0x04823420, 0x8b67e622, 0x8282b782, 0x0ecd0822, 0x07251e82, 0xfffff232, 0x230a83f8, 0xf232f7ff, + 0x2207d945, 0x7f3433f7, 0xff2009e5, 0x34265b82, 0x64fb088b, 0x131915d3, 0xd3841832, 0x080ea718, 0x6621d395, 0x24141966, 0x21d3840b, 0xd3839a99, + 0x00211882, 0x260a8303, 0x66660400, 0x408bcb08, 0xeb22cb66, 0xd441158b, 0x26004108, 0x23356441, 0xcd4c4a00, 0xf5256a83, 0xffffcdcc, 0x2f6a83f8, + 0xff66e6f7, 0x0080f6ff, 0xffff088b, 0x06862b02, 0x87210c82, 0x208c82ae, 0x301c82f8, 0x9a190800, 0x0a00ff8b, 0xff083333, 0x67665b00, 0x290c8407, + 0x0700ff32, 0x00ff9a99, 0x04821908, 0x52780922, 0x00293982, 0x0666e6fd, 0x6e0900ff, 0x20218214, 0x231c8207, 0x66e6f7ff, 0xf5394482, 0xff08cecc, + 0x9999a4ff, 0xff64f707, 0x33b36dff, 0x0634fb15, 0x32f7ffff, 0x221c82f2, 0x820ecdf8, 0x74332149, 0x08233282, 0x83088ccc, 0x21118406, 0x1682f232, + 0x08220483, 0x61180ecd, 0xcd21078a, 0x221e8210, 0x42f03207, 0x48180b85, 0x0e2216e3, 0xe318f78b, 0xf7225dbb, 0xde18fb94, 0x41180d55, 0xcc260f82, + 0x4ce3ffff, 0x9f18ffcc, 0x33200e59, 0xe321af82, 0x058b554c, 0x18050b5b, 0x27181142, 0x33b364ff, 0xb30401ff, 0x24206683, 0xff250a82, 0x05cc4cdb, + 0x820582ff, 0x4cdb223d, 0x270a82cd, 0xff71bdf9, 0xcdccf9ff, 0xf5214882, 0x226a82cc, 0x848f4206, 0xff08250f, 0x34330600, 0x35820a82, 0x330a0022, + 0x0f847382, 0x4c060023, 0x831a82cd, 0x8200204b, 0xff052104, 0x50840583, 0x14cc4f18, 0x45823320, 0x36823084, 0x46840a82, 0x56880a20, 0x33330623, + 0x843b8408, 0x824b8645, 0x82342050, 0x1830860a, 0x82139750, 0x234b82ad, 0xffffce4c, 0xb782b182, 0xff230f83, 0x8632b3f9, 0x20dd824b, 0x82e386ce, + 0x8232204b, 0x84f9200a, 0x833085d8, 0x860f83e8, 0x20fe8630, 0x20fe8ece, 0x24e382ce, 0x8b0100c0, 0x20998315, 0x41a38332, 0x73820536, 0x20063641, + 0x411582b3, 0x5d830b36, 0x37820f82, 0x83330621, 0x0536411a, 0x828b3421, 0x410f82a9, 0x34200836, 0x3420ea89, 0x98093641, 0x03511830, 0x05364116, + 0x4b89ce20, 0x0a833220, 0x82053641, 0x82818215, 0x06674177, 0x0f821a82, 0xffff0824, 0x1a83ccf9, 0x820b3641, 0x073641cd, 0x8c83cc20, 0x20053641, + 0x20f384cc, 0x82309c05, 0x411f8436, 0xfe850836, 0x0e08ce27, 0xf4f7f4f7, 0x2b168215, 0xff34b3f1, 0x66e6fcff, 0x66f2ffff, 0xfa200482, 0xf3272083, + 0xff0832b3, 0x82cc3400, 0xcca4216c, 0xe8206c83, 0x2c06fa5b, 0x99e1ffff, 0xedffff9a, 0xffff3333, 0x223883dd, 0x820080f6, 0x66cc23b1, 0x8782e466, + 0x9a19ff26, 0xbcffff06, 0x8a283683, 0xff050080, 0x00801500, 0x33267d82, 0x1600ff34, 0x658267e6, 0x00244582, 0x8b33b317, 0x46225c82, 0xfa8234b3, + 0x98193f25, 0x822000ff, 0x29002348, 0x71829a19, 0x08323326, 0x0c00ff96, 0x00212c82, 0x25368314, 0xff991903, 0x50830d00, 0x9a19f422, 0x0d253582, + 0xffffcecc, 0x26ac82f4, 0x32330200, 0x82ebffff, 0x270e8409, 0x3433f2ff, 0xcbffff08, 0xbe26bc83, 0xff393433, 0x3483d5ff, 0x66e6a522, 0xff266b82, + 0x8b9a99dc, 0xd56fff69, 0xb3e02605, 0x0b00ff33, 0x272d83b3, 0xff9959c7, 0x32339eff, 0xfb20b982, 0xff239982, 0x8268e6f7, 0x1f0521ad, 0x66280482, + 0xf7ffff66, 0xffff299c, 0x27054f6f, 0xff7b94c8, 0xce4ce4ff, 0x0a212983, 0x0695563d, 0x291cfa27, 0x4c0000ff, 0x262482cc, 0x00ff2b47, 0x8266e602, + 0x48fb2281, 0x820a8473, 0x06212523, 0x330500ff, 0x0522e583, 0xbb820080, 0x54543720, 0x82082005, 0x0200265b, 0x00ff5e3a, 0x27ad8208, 0x643b0400, + 0x660700ff, 0x00283b82, 0xffae073c, 0x9a996700, 0xf3226582, 0xa582852b, 0xf4255b83, 0x00ff142e, 0x2829820c, 0x0a57f5ff, 0x4c0d00ff, 0x226582cc, + 0x4133f3f4, 0x00280516, 0xffc33502, 0x9a191400, 0xca210e82, 0x4132823e, 0xca210525, 0x210a823d, 0x198266e6, 0xffd72326, 0x67e6fcff, 0x0f270e82, + 0xf3ffff5d, 0x82089919, 0x85ab2694, 0x0600ff83, 0x22d38214, 0x82cd4cf9, 0x52782109, 0xb321f282, 0x211a8233, 0x4e827545, 0x66e67722, 0xfa208282, + 0x78841a83, 0x4983fc20, 0x9a990d26, 0x0e00ff8b, 0x06827e82, 0x18053521, 0x24209bf2, 0x2b058b8b, 0x1b3d586b, 0x16faec18, 0xff8bcd26, 0x33b3f1ff, + 0xa16f0482, 0xcc4c210c, 0x526c7c83, 0x8274200e, 0xf6fe23f7, 0x66829a19, 0x82662121, 0xcc0c26ed, 0x00ffa9cc, 0x20ae8311, 0x2230831a, 0x82343316, + 0xb32b2bd3, 0xb4ffff34, 0xff050080, 0x15820400, 0x99f8ff27, 0x0200ff9a, 0x22148233, 0x8232b3f7, 0x99f7296d, 0xffff089a, 0x079a99c8, 0xfa250c82, + 0xffff0080, 0x265782fd, 0xccccfaff, 0x83fbffff, 0x820e8230, 0x4cfb2220, 0x271987ce, 0xffff9819, 0x8634b3ff, 0x80214682, 0x273b8500, 0xb31b00ff, + 0xffff0532, 0x66824c82, 0xf9205c83, 0x906e4482, 0x33fb2705, 0x0800ff32, 0x29829819, 0xceccd630, 0xcc4500ff, 0xff0e05ce, 0x9a19af01, 0xba82daf7, + 0x1e054627, 0xe82d00ff, 0x2a9f82f6, 0xff0c170b, 0xe4450700, 0x820300ff, 0x0e002d63, 0xfffff2dd, 0xff4cb7f8, 0x2a1c0b00, 0xf8223d82, 0x0a82f0c7, + 0xffec1126, 0x0621f1ff, 0x28262382, 0xf4fffff6, 0x2382b8de, 0x82aab121, 0x8295201e, 0xbaff23d8, 0x86821e45, 0xa430ce22, 0xc92a7282, 0xd0ffff78, + 0x00ff48a1, 0xcb82e100, 0xaec7f023, 0x2325828b, 0x8b7cffff, 0x01211182, 0x83ed8208, 0x2212820b, 0x82767edb, 0x1cfa24d0, 0x8324ffff, 0x66fb22fe, + 0x221b8266, 0x82cd4c94, 0xe65f231a, 0x0c820765, 0xe2bae122, 0x1c83e182, 0x0a97e425, 0x832b00ff, 0xd4eb2869, 0x00ff087a, 0x8266e665, 0x0d002220, + 0x52c48245, 0xc2220528, 0x8718ff90, 0x09270dda, 0xffff9ad9, 0x82703df5, 0xbaf22247, 0x315482e2, 0x079a1989, 0xcc2200ff, 0xf6ffffcd, 0x00ff9cd9, + 0x20821926, 0x9a19fa28, 0xfeffffb3, 0x5482cc4c, 0x9a996722, 0x00225499, 0x49828300, 0xfafeff22, 0x0b82c683, 0xa7522f82, 0x22678c09, 0x82666698, + 0xee282767, 0x0100ff14, 0x678202ab, 0xa4820520, 0x6ef2052b, 0x262000ff, 0x0900ff68, 0x218c821a, 0xc0a17600, 0x588cd783, 0xc0849a20, 0x707d2c31, + 0x2b1400ff, 0x1a00ff86, 0x00ff2a9c, 0x82f4681b, 0x451e2291, 0x22908220, 0x824721a0, 0xcc012779, 0x2b00ffcc, 0x6b826766, 0x00801a32, 0x1000ff5e, + 0xfb086666, 0x69ffff44, 0x8b150080, 0x08250084, 0x198dffff, 0x20cf829a, 0x222b83a3, 0x8252f81c, 0x6b232342, 0x06850885, 0x5d00ff24, 0x5982b81e, + 0xc182ae20, 0xe2fa7123, 0x9259828b, 0x801122fd, 0x272e8200, 0xff52f810, 0x3e49ffff, 0x3d266582, 0xfeffff70, 0x5b8276bf, 0x71fdc032, 0xe0d7ffff, + 0xffff0542, 0xfff6e8f4, 0x1dbaf8ff, 0x2706ec45, 0xff0c22f1, 0xb4480700, 0xe3211882, 0x225782d7, 0x82239b04, 0xcd0c211e, 0xb3211482, 0x21238233, + 0x09823333, 0x83cdcc21, 0x84042072, 0x8f04315f, 0x0100ffe0, 0x00ffd743, 0xffd80e04, 0x73a80200, 0x6d213582, 0x28e1824c, 0x0584ab47, 0xc53300ff, + 0x2b4b821e, 0x00ff9c59, 0xffe2ba21, 0x1c45edff, 0xea22d582, 0x8582c4b5, 0x162eff29, 0x93dcffff, 0x83ffffb6, 0xe3ff36e5, 0xffff9a19, 0x8b34338c, + 0xf7af0e08, 0x1534f8b4, 0xfb8b33fb, 0x0b0f6c15, 0x0754fb22, 0xb9233c82, 0x85f70040, 0x33f72316, 0x0382088b, 0x066c0d82, 0x83f7200a, 0x46002324, + 0x3b8200c0, 0x45821683, 0xff380826, 0x9a9961ff, 0xfb2d3482, 0xffff0080, 0x814861ef, 0x1ef2ffff, 0x220482b8, 0x82810040, 0x73b32189, 0x0d26d682, + 0xffff6666, 0xea82cccb, 0x34b31a26, 0x1e00ff8b, 0x2005104d, 0x2127821e, 0x04833200, 0x90421a2c, 0xe14900ff, 0x0c00ff48, 0xe58252b8, 0x829e1921, + 0xc0d32241, 0x20e58200, 0x27158209, 0x00c0efff, 0x990200ff, 0xec23c582, 0x7bff3233, 0xec2905b4, 0xde08cecc, 0x66ceffff, 0x227d8266, 0x8248e1ea, + 0xbdeb26bf, 0x0000ff70, 0x82268319, 0x0200238d, 0xdc6b66a6, 0x261a2507, 0x1800ff66, 0x00211982, 0x23048313, 0x8bcccc1c, 0x06831a82, 0x142c1682, + 0xecffff7c, 0xff9348e1, 0xb8dee5ff, 0xec26b382, 0xffff1e85, 0xcf8240fe, 0x34b3eb2e, 0xeaffff8a, 0x088b66e6, 0x1524f7cb, 0xdc206282, 0xff218982, + 0x841b83e3, 0x820e8204, 0x83ff2048, 0x84ff2006, 0x85002016, 0x33232853, 0x07980834, 0x821400ff, 0x010021f9, 0x0021c282, 0x83098415, 0x331622ec, + 0x20338234, 0x24068300, 0x6e1500ff, 0x206b8214, 0x21de82e0, 0xf3825e14, 0x0020fe24, 0x37827e08, 0x66e62e27, 0x1979ffff, 0x20da829a, 0x216c82f2, + 0x21820900, 0xdef5ff2b, 0x0e00ffb8, 0xffff4801, 0x21de83fb, 0xac839e10, 0x1982fa20, 0x21130027, 0x0200ff48, 0x204582a0, 0x82238313, 0x419c202d, + 0x00290645, 0x0500802c, 0x484a00ff, 0x056e48f6, 0x33320023, 0x21e78234, 0xcb8234b3, 0xcccce123, 0x25068308, 0xffff9a19, 0x048299cb, 0xa382e520, + 0x4cb3ff23, 0x262a82cc, 0x0e089a99, 0x82d301ff, 0xce002b1a, 0xfb1566e6, 0xd1ffff08, 0x49829a19, 0x0a575e2c, 0xf8ffff06, 0xfffffc49, 0xa48226f1, + 0xc66bf722, 0x91260982, 0xf6ffffec, 0x3882866b, 0x081e4525, 0x827bffff, 0xcbff239f, 0x2f829002, 0x66a65527, 0xc4ffff06, 0x2a7f82a8, 0xff3e4acb, + 0x703dabff, 0x83e4ffff, 0x828720eb, 0x1b002272, 0x202f8385, 0x20b582bb, 0x200482ff, 0x21458205, 0x0486b89e, 0xecd1f027, 0x010000ff, 0x240e8588, + 0xc05f0900, 0x830a8208, 0x60092ae4, 0x00ff8b00, 0xff5c2f0f, 0x820a8200, 0x48612104, 0xfd27ee82, 0x00ff6566, 0x826666fd, 0xd8042674, 0x0600ff94, + 0x219e8246, 0x1982ccff, 0x82ea0821, 0x3efa2778, 0x0500ff76, 0x44828fc2, 0x00c0f922, 0x3f231e82, 0x64ffffff, 0xc2260602, 0xf9ffff90, 0x1a8201c0, + 0x82665721, 0x66572234, 0x3c898267, 0xffd057d5, 0x90423301, 0x575601ff, 0x3100ff0a, 0x04f7cae1, 0x080800ff, 0x00ff088e, 0x27b08212, 0xa05a0100, + 0x8a0f00ff, 0xf02c5b82, 0xffffbc74, 0xffd6a3fe, 0xd823edff, 0xfc274582, 0xffff02c0, 0x82c69ad2, 0xcccc2960, 0xbaacffff, 0xe0ffffe2, 0xff32ee82, + 0x0832b3b0, 0xf730fb0e, 0x1554f894, 0xf70714fb, 0x4a190614, 0xfb297aa1, 0x8b15c334, 0x5e0400ff, 0x071951b8, 0x8348a121, 0x8bb9240e, 0x8206db08, + 0x0a455008, 0x8bb85e2a, 0xa1fbffff, 0x077b0848, 0x9e260883, 0xfcffffb8, 0x04826666, 0x82486121, 0x9a992417, 0x513b088b, 0x9e200e19, 0x00283182, + 0x08486104, 0x4b8b079b, 0x8f178051, 0x23718366, 0x9a99fbff, 0x99216686, 0x8366879a, 0x9117826b, 0x08ac5066, 0xf7079b2b, 0x158cfb84, 0xe00800ff, + 0x25d48200, 0xff002007, 0x0a83f8ff, 0x20f7ff24, 0x577e0800, 0x82e62008, 0x651682b4, 0xd0220851, 0xb88200c0, 0xad83ef20, 0x21f1ff22, 0x0920fe82, + 0xe0823884, 0xc10e0027, 0xffff0848, 0x220f82fd, 0x82e00500, 0x82fa204d, 0x00002204, 0x230982a0, 0x8b48e1fd, 0x06821a83, 0xfaffff28, 0xffffb8de, + 0x168360ff, 0x04824020, 0x0080fa22, 0xf8201a82, 0xf0230a83, 0x8205b89e, 0x82592040, 0x86fa21c5, 0xf9217782, 0x201f8280, 0x20d483fc, 0x05264bfa, + 0x66e6fe25, 0x83ffff06, 0x00002216, 0x293b8580, 0x400400ff, 0x00ff8900, 0x46834006, 0x9a19ef27, 0x663200ff, 0x27468266, 0xff6666f5, 0x9a19e0ff, + 0xfa200a82, 0xf2571582, 0x83ef2005, 0x83f42035, 0x61ed220e, 0x22928347, 0x82b89ef3, 0x21f72251, 0x20f08247, 0x239882f8, 0x9a190700, 0x1906f37e, + 0x8308598b, 0x241682e5, 0xde0800ff, 0x243382b9, 0x48610c00, 0x21768206, 0x218200e0, 0xb7820420, 0x83030021, 0x7e0122f2, 0x831482b9, 0x120021cc, + 0x36261483, 0xff0548a1, 0x0a830300, 0x52d80925, 0x490900ff, 0x0023076d, 0x8366660a, 0x85068346, 0xf9ff2316, 0x2a850060, 0x20f6ff22, 0x0028c682, + 0xff48e10d, 0xb85ed6ff, 0x13214082, 0x201a82c0, 0x21458310, 0x86186122, 0x0b200764, 0xff2aa882, 0x084821e8, 0xff8f878d, 0xd382fdff, 0x1e040023, + 0x235383b8, 0x0600402f, 0x20089582, 0x15cc0c00, 0xf830fb0e, 0x15d4f714, 0xf70614fb, 0x14f70714, 0xfb0514fb, 0xf7156b14, 0xc4fb0614, 0x08b47d07, + 0x180e177f, 0x2118355b, 0x046634f8, 0x44f72b17, 0x0000ff06, 0x14fb0001, 0x0082ff05, 0xffff0023, 0x120a4bee, 0x1bfb8a29, 0xffff6415, 0x8266e6d8, + 0x196621d3, 0x82053c49, 0xf5ff21d5, 0x00210482, 0x23e4820a, 0x00c0f2ff, 0x0684c282, 0x1684ff20, 0x33f5ff23, 0x29a88233, 0x08cdccf2, 0xe699ffff, + 0x3f820766, 0xff9a1926, 0x9a192700, 0xfc2f6a82, 0x00ff3333, 0xff34b304, 0x66e6f9ff, 0x820200ff, 0xf9ff2374, 0x4283cdcc, 0x25054c4f, 0xff85ebf9, + 0x2083fdff, 0x5c4ffb27, 0x4cfbffff, 0x060e45cc, 0xa0f6ff23, 0x19578200, 0x210dd136, 0x98823bdb, 0x82600921, 0x2a1d82be, 0x2f0f00ff, 0x00ff8b5c, + 0x82486109, 0x00602404, 0x86dbdb08, 0x4500201d, 0x4683094a, 0x65452284, 0x282d8208, 0x14cef0ff, 0xebffffff, 0x0a066d84, 0xf7af0e26, 0x151cf754, + 0x0d274f82, 0x00ff3433, 0x83cdcc0a, 0xffcc2304, 0xdf820d00, 0x3cf70824, 0xa876f706, 0x92851812, 0x14f72409, 0x1844fb05, 0x180c8f5b, 0x200a925c, + 0x015d18fc, 0x15002d08, 0xffff717d, 0xff0080ea, 0x8f821a00, 0x1cb24c19, 0x3c206e82, 0xf2205082, 0x2105aa51, 0x8e823333, 0x5e34b321, 0x08230513, + 0x45ccf7cb, 0xff2a0b68, 0x98193801, 0x3b15bbfb, 0x4b4605db, 0xffff2509, 0x8ba4d0f0, 0x24056646, 0x00a0f6ff, 0x240a8908, 0x010000ff, 0x211f8448, + 0x4d4100ff, 0xb89e2c05, 0x2700ff08, 0xffffa6f0, 0x82a4f0d8, 0xe6912b44, 0x075b0666, 0x196e00ff, 0x1382069a, 0x8452f821, 0x27188204, 0xffe03afb, + 0x7a54fbff, 0x2206b441, 0x8268e6f9, 0x47f92062, 0x06820572, 0x0200ff2d, 0xffff1058, 0xff86ebf9, 0x83af0400, 0x5c4f212a, 0xb2415982, 0x3854211e, + 0x5e218782, 0x6edc82b8, 0xcc2006b5, 0x66250f82, 0xf80e0866, 0x1b514614, 0x82008021, 0x80ea237b, 0x6a41ff00, 0x84fb210a, 0xae20b582, 0x0023b588, + 0x41ae0727, 0x5f470a13, 0x076a4712, 0x0f00ff29, 0xffff5c2f, 0x82b8feff, 0x4861277b, 0xa0f6ffff, 0x6f420800, 0x068d420c, 0x1d821883, 0x08b89e24, + 0x5a863b3b, 0x6e411285, 0x82002009, 0xff082a54, 0xe03afbff, 0xab0400ff, 0x052b4186, 0x19060023, 0x237f8298, 0x08343306, 0x2b410685, 0x06002305, + 0x2b417a14, 0x04002905, 0xff08a4b0, 0xaa112700, 0xb6840482, 0x66e65125, 0x1814fb06, 0x84097dc0, 0x6da318ea, 0xee4e1908, 0xdcfb2539, 0xff1534fb, + 0x200cc443, 0x0a76184c, 0x07076107, 0x31190a20, 0xf3250db4, 0x2307bb06, 0x12e44706, 0x94fbab32, 0x0654fb15, 0x54f7074b, 0x4b07cb06, 0x8b1514f7, + 0x24510b43, 0xffff07c4, 0x94521980, 0xcff24719, 0xc4fb942d, 0xffff8b15, 0xff00a0fb, 0x8760fcff, 0x480e8204, 0xd6580629, 0x05d55713, 0x00212c82, + 0x85368203, 0x60042204, 0x06f44800, 0xff200882, 0x4f831384, 0x08285a85, 0xf78b077b, 0x072b155c, 0x20084548, 0x9d4618e0, 0x74fb210c, 0x20177347, + 0x263282eb, 0x66e60800, 0x470700ff, 0xf7200d75, 0x18833282, 0x19828b20, 0xff9a1922, 0x0a6f4718, 0x238de746, 0x15d354fb, 0x2706f049, 0x48a10300, + 0x61fcffff, 0x2115224a, 0xf0490300, 0x05544a0b, 0x66fcff22, 0x2006735b, 0x12bb49ff, 0x4afcff21, 0x93220a54, 0x0b4a1543, 0x0a865a0d, 0x8205af41, + 0x214f864a, 0x724a9a99, 0x13ea5a14, 0x3b82b386, 0x2d05f05b, 0x807d00ff, 0x63ffff00, 0xff153433, 0x4882f9ff, 0x9901002f, 0xffff0598, 0x923333e9, + 0x800000ff, 0x21b88200, 0x09829a19, 0xffcdcc22, 0x08248183, 0x600100ff, 0x07271482, 0x00ffe0cf, 0x820a370f, 0x30e8250e, 0xae0d00ff, 0xfd373e82, + 0xff08f0e7, 0x10980500, 0x27ffffff, 0x0600fffc, 0xffffd122, 0x822408fe, 0x29dc2613, 0xf7fdffff, 0x2c1e82d0, 0xffd7630a, 0xf067fcff, 0x700b00ff, + 0x201982a4, 0x273d8288, 0xffb89e03, 0xea660a00, 0x03211e82, 0x205c82a0, 0x2319820a, 0xe77bfaff, 0xa8822382, 0x8ff5ff23, 0x267b829e, 0xff0848a1, + 0x82c7f8ff, 0x7b022638, 0xfaffffe8, 0x201e821b, 0x216b8301, 0x9a828cfa, 0xeb310122, 0x06243d82, 0x8b07d1a2, 0x07253582, 0xf7ffffae, 0x2810820c, + 0xff52f808, 0xf8f3f4ff, 0x833b828b, 0x24168506, 0xf007f7ff, 0x2117828b, 0x168210f8, 0x0c02fa23, 0x2cef8207, 0xffff7b94, 0xff2831fb, 0x3333f0ff, + 0x06644b7d, 0x9819eb22, 0xf8202082, 0xd5276483, 0x00fff628, 0x82949828, 0x0a172635, 0x541100ff, 0x2282827b, 0x8208f6e8, 0xdfcf21c1, 0x4f26e582, + 0x00ff05e0, 0x7783471d, 0x8200a021, 0x1f8526ff, 0x2ffdffff, 0x2109825c, 0x2986b81e, 0x83feff21, 0x30f82219, 0x21638220, 0x3382f6c8, 0xffe00f24, + 0x3282f2ff, 0x20020023, 0x2c678200, 0xffdf0ff9, 0xf0070100, 0x20f7ffff, 0x83f082c5, 0x26f82728, 0x0200ff66, 0x1e82e0cf, 0x8287fb21, 0xa00128fa, + 0xffff0500, 0x820a97f5, 0x2096831f, 0x20b683f4, 0x210983fa, 0x6c824ffc, 0x8e97f522, 0xfc222982, 0x2386f853, 0x82730521, 0x91f42709, 0x0a00ffec, + 0xd482436b, 0x085c4f27, 0x440400ff, 0x207c8219, 0x23488280, 0x0cc20700, 0x3626a682, 0x0800ff04, 0x09823c9f, 0x82f23221, 0x14ae2109, 0x13211e82, + 0x294882f8, 0x072e3df9, 0xf4ffff8b, 0x168252f8, 0x4a82f320, 0xae07f728, 0x0c0b00ff, 0x46828b08, 0x16850683, 0xf8080024, 0x17828b10, 0x82f00721, + 0x41062816, 0x00ff0706, 0x82295c16, 0x02cb2b68, 0xd90f00ff, 0x0d00ff9a, 0xb082acbc, 0xffb89e26, 0x66e61400, 0x072c2482, 0x00ff7473, 0xffe6502b, + 0x0180d6ff, 0x37052756, 0x33b3e9ff, 0x4c0600ff, 0xfb0e08ce, 0xf744f730, 0x065b1564, 0x06bb076b, 0x4b186282, 0xbb4b0884, 0xf8ff2311, 0x304466e6, + 0x19f72706, 0xdb088b9a, 0x454e84f7, 0x00ff2681, 0xff008044, 0x200482ff, 0x26db8215, 0xffff4861, 0x7300c0f4, 0x8b290ab3, 0xdef5ffff, 0xf9ffffb8, + 0x302582c0, 0x0890c2f9, 0x1ee2ffff, 0xa9056db8, 0xf8e1ffff, 0x82289d52, 0x214e8249, 0x9073b89e, 0x224d820a, 0x858b00c0, 0x06002d4e, 0x6d080040, + 0x191e00ff, 0x6d6d059a, 0x42202484, 0xff281985, 0xffddc4f5, 0xe8fbffff, 0x1a202888, 0xf4227782, 0xa282e1ba, 0x84ca5021, 0xff002129, 0x830a2b74, + 0x270f820a, 0xff08703d, 0x9a191d00, 0x1e205282, 0xc5277483, 0x00ff33b3, 0x8290423b, 0x33ed2730, 0x00ff0633, 0x55820100, 0x70fdcf23, 0x160a4605, + 0xefffff24, 0x268201fe, 0x32830220, 0x8320f721, 0xe0f821a8, 0x4c186982, 0xf72109b1, 0x17134634, 0x5f82db20, 0x0939ab18, 0x61e3ff23, 0x23648248, + 0x08b89edc, 0xe7270682, 0xffff00c0, 0x7d4861f2, 0xec2706f3, 0xffffb81e, 0x82b81ef5, 0x802121ad, 0xde231982, 0x8205e27a, 0x48e121b8, 0x0a820484, + 0x52380622, 0x0483ce82, 0x32330a23, 0x080a828b, 0xff343320, 0xccccf9ff, 0xffaf0e08, 0x34b32401, 0xb36900ff, 0x88881534, 0x4cfeffff, 0xfbffffcc, + 0x648266e6, 0x32b3fb2e, 0xc1ffff08, 0xff0734b3, 0x0a573e00, 0x04228e82, 0x3c829643, 0x0416042d, 0xb30100ff, 0x00ff8ef8, 0x82240603, 0xe69c2873, + 0x0532f764, 0x82bcffff, 0x43002386, 0x0a8248e1, 0x74fd613d, 0x1763ffff, 0x01ff05d0, 0xffcccc13, 0x66e6ae00, 0xe0ffff15, 0x00ff9819, 0x8266e61f, + 0x20f62b20, 0xffff9500, 0x8b00e0ef, 0x65828181, 0xd083e420, 0xab820482, 0x4a844082, 0x1b240a82, 0x00ff0040, 0x0a820482, 0x20050a27, 0xfa0900ff, + 0x237f82e2, 0x819a1910, 0xe6250b82, 0xfeff0866, 0x23ee82c7, 0x6666a700, 0x220bf742, 0x8254fc8b, 0xeeef2b6b, 0x0000ff14, 0xffff0249, 0xdf8273f1, + 0xe612092c, 0xbdf8ffff, 0x0e00ff70, 0xc74f6085, 0xff42223a, 0x07c74fff, 0xffff5822, 0x2261c74f, 0x828b3373, 0x8cf322ad, 0x175348cd, 0x2119c74f, + 0xc74f6766, 0x1d3a2209, 0x06c74fff, 0x4f7d7f21, 0xff2970c7, 0xb8de0100, 0x59fcffff, 0x26848298, 0xffff33b3, 0x829a99fd, 0xcdcc2d09, 0xb3ffffff, + 0x00ff0834, 0x0766e644, 0x8521c783, 0x2b1682e4, 0x00ffea66, 0xff502d08, 0x8a0c0600, 0x02210482, 0x2d20828e, 0xff8c8c76, 0x3eca7500, 0x2e00ff05, + 0x44180080, 0x4e4e11f7, 0x839b205a, 0x12be4b6d, 0x4bfb6b21, 0xff2d73b0, 0x9a194000, 0xe627ffff, 0xffff1566, 0x119018fc, 0xe6f92208, 0x052b4d68, + 0xccf9ff23, 0x052350cc, 0xff8bcc22, 0x38054d4e, 0xff105802, 0x5c4ffbff, 0xaf0400ff, 0xffff08e0, 0xff52f8d8, 0xaa112700, 0x05755005, 0x5006b64c, + 0x40210692, 0x05dd4c00, 0xac6c2782, 0x067b6c09, 0x00400d29, 0x6600ff08, 0x4e079a19, 0xf6210cd8, 0x843382a0, 0x10c74d04, 0xb89ef627, 0x600900ff, + 0x05364f00, 0x500ea155, 0xff200c74, 0x4e0a9250, 0x54260a40, 0xf6ffff7a, 0xa3820a97, 0xccccf03b, 0xccf5ffff, 0xf7ffffce, 0x0e080080, 0x01ff3cf7, + 0x15904265, 0x193500ff, 0x2704829a, 0xff057a14, 0x99191c00, 0x1e270482, 0x2d00fffa, 0x828b9999, 0x231a820a, 0x06e1e3ff, 0x9727b582, 0xffff6666, + 0x835c8f68, 0x34332625, 0xe6e3ffff, 0x22548267, 0x826766d2, 0x2259830a, 0x8266e6e3, 0x99412cf2, 0x41ffff9a, 0xff050080, 0x8280daff, 0x7fda28d5, + 0xc3fffffe, 0x858b3433, 0x2500230f, 0x25820280, 0xad878a25, 0x857500ff, 0xcb812225, 0x201582ff, 0x206c8200, 0x2346823c, 0x357e2500, 0x71820f84, + 0xec115c23, 0x274782e8, 0xff85abae, 0x52785000, 0x210e8871, 0xbe789042, 0x7f0c2206, 0x712c827c, 0x7e200557, 0xb119b982, 0xff220983, 0xb98381f3, + 0xb95e5127, 0xa1aeffff, 0x2d4082cc, 0xff47e1a3, 0x0a5749ff, 0xfbffff15, 0x04825ccf, 0xff297282, 0x86c235fd, 0x9efeffff, 0x2b0f82b8, 0xff080080, + 0x162e3f01, 0x2a00ff06, 0x0023f082, 0x82676629, 0x190329f0, 0x0300ff9a, 0x908b3333, 0x83057a5a, 0x20c6820b, 0x23ec8268, 0xd7639700, 0xfc205882, + 0x00244882, 0x86b81e03, 0x0b83e882, 0xe1fcff23, 0x27218248, 0xff0100cb, 0xf6e8caff, 0x31274382, 0xffffcd4c, 0x719a99ce, 0x37710652, 0x1c8c7214, + 0xff243b82, 0xce4c3100, 0xa330c687, 0x0e0566e6, 0x2900ffaf, 0x01ffb85e, 0x15c4a0b6, 0x2006d771, 0x1e04410c, 0x2ec3ef41, 0x00ff078b, 0xffae07b0, + 0xa2c522ff, 0x41ffff15, 0xe141131a, 0x99fa2216, 0x0de1419a, 0xcd4c2a22, 0x2185e141, 0x87828b8b, 0x9a99e631, 0x9926ffff, 0xff8b159a, 0x34331900, + 0x822000ff, 0x36002610, 0x00ff6666, 0x21098312, 0xbe82191d, 0x19060026, 0x0900ff98, 0x0d221483, 0x29826866, 0xff210f83, 0x82d983f6, 0xff9c2425, + 0x82e6e2ff, 0x99202e2f, 0xc9ffff98, 0xff8b9a99, 0xcccce6ff, 0xc9401808, 0xb3dc2218, 0x651b8234, 0x597b07fb, 0x068b2906, 0x0001ff0e, 0x5ef79a19, + 0x0c13b518, 0x280aee71, 0x200100ff, 0xb7ffff00, 0x2c0482c0, 0xff42c0f6, 0x9a59baff, 0x5fecffff, 0x3a0982be, 0xff086666, 0x3373fcff, 0x4cf5ffff, + 0x0400ffce, 0xffff67e6, 0xffcc4ceb, 0x56e61400, 0x802105d9, 0x37678200, 0xffb89e09, 0x00e00600, 0x0a00ff8e, 0xff0800a0, 0x00800d00, 0xde2f00ff, + 0x10201582, 0x4d25eb83, 0xffffae87, 0x20e583ff, 0x23f58363, 0xe2faffff, 0x33212382, 0x07b37134, 0xffcccc24, 0xbc82f2ff, 0xff276b82, 0x00ff9919, + 0x8234b351, 0x82c120ac, 0x0000266c, 0xffff3233, 0x271482d6, 0xcdccd0ff, 0xe60000ff, 0xc9228082, 0x638267e6, 0xaf830020, 0x5b21d021, 0x5b2405f2, + 0x61f6ffff, 0xd1220a82, 0x4482b85e, 0x8240fd21, 0xe6f325ca, 0x0800ff66, 0xf221c583, 0x246e827a, 0xfffafe0c, 0x821882ff, 0x190c2139, 0xfd21df82, + 0x22a28260, 0x821e850d, 0x212d8223, 0x4d820200, 0xfe0c0022, 0x00223d82, 0xb7825e0a, 0x821e3221, 0x83042004, 0x82332014, 0xffff213d, 0x32212383, + 0x2ddb8280, 0x299cffff, 0xf31a00ff, 0x1300ff32, 0xc4706766, 0x23002105, 0xff23db82, 0x82cdccff, 0x821f205c, 0xffff213d, 0x1920ff83, 0xff21ff82, + 0x22a082e7, 0x82610000, 0xdee1229a, 0x211e82b9, 0x8682df00, 0x9a82d020, 0x60fcff27, 0xceffff06, 0x208a82d9, 0x222382f8, 0x83c0d0ff, 0xe0fd215c, + 0xdf25b988, 0xf2ffffbe, 0x21b982ba, 0x32821e0d, 0x1e83fd20, 0x83130021, 0x83fc2052, 0xe1062595, 0x1200ff48, 0x00226b82, 0xc882c000, 0x5c82a982, + 0xbe3f0825, 0x823100ff, 0x03002bdd, 0xffbffade, 0x4821ffff, 0x068208bd, 0xff7c142b, 0x98d93800, 0xffffb95c, 0x230e82c6, 0xcecc0000, 0x91201682, + 0x1331be83, 0xff15cccc, 0x9999f5ff, 0x660800ff, 0xffff7c66, 0x21ba82fe, 0x0483f7ff, 0x34b3f522, 0xe6252582, 0xffffcd8c, 0x260f83e0, 0xff4721f2, + 0x8219d8ff, 0x9e002129, 0xd7224982, 0x72826766, 0x829f0021, 0x83da209c, 0x00fd26df, 0xdaffff06, 0x2cbf8240, 0xff4160f9, 0x1e45dbff, 0xfdffff08, + 0x20cf88a0, 0x2c90829f, 0xff9a99f2, 0x42000d00, 0xa1fdffff, 0x213d8248, 0x48821e14, 0x0080fc23, 0x23cb8592, 0xe1faffff, 0x25079149, 0xffbf1f07, + 0xef822700, 0x60030026, 0x2800ff42, 0xff21e582, 0x22df83ff, 0x82aec728, 0x82002039, 0x1d003391, 0x00ffcdcc, 0xa79a9909, 0xe61100ff, 0x1700ff67, + 0x1a820100, 0xcc4c0927, 0x660a00ff, 0x20cb8466, 0x21dc829a, 0xdc8434b3, 0x6c201a82, 0x3e223583, 0xf282285c, 0x0a83f120, 0xba5e0025, 0x82f0ffff, + 0x05d35e09, 0xdc82f120, 0x61fcff23, 0x22b88246, 0x824821f3, 0x68e629a4, 0xff8e7e83, 0xe03af2ff, 0x03213c82, 0x82cb8320, 0x0b002217, 0x245682f9, + 0x98b81ef8, 0x2b16828e, 0xff51f80b, 0xc4750200, 0x4c0b00ff, 0x01208e82, 0x0b277d83, 0xffff33b3, 0x8266e6ff, 0x5e4b221e, 0x2a8882b8, 0x00ff00e0, + 0xffe23a3e, 0x82a0c3ff, 0x21238309, 0x1e84b6ff, 0xff21c783, 0x215482da, 0x5e83feff, 0x1ec5da2c, 0xc0fbffff, 0xd9ffff42, 0x86820080, 0x9b83fe20, + 0x48e1f222, 0x7f28e682, 0xf5ffffbe, 0x00ff1e05, 0x21050f42, 0x5c829a99, 0x82c01021, 0xe6fe2592, 0x0800ff66, 0x00240982, 0x8c52f80c, 0x40202982, + 0x00213982, 0x20688304, 0x23158327, 0xb3beff01, 0x60208d82, 0x27227882, 0x548332f3, 0xff164e29, 0x18ae6200, 0x82acffff, 0x5100275e, 0xff25f4a8, + 0x6f820100, 0xff91f727, 0x3e8a86ff, 0x06da5b15, 0x82190c21, 0x5df322e6, 0x23528270, 0xffff6626, 0xff238683, 0x824821fd, 0x82f32041, 0xfdff2172, + 0xf621b083, 0x20d482fa, 0x220982f3, 0x82de0200, 0x83f320e8, 0x0400211e, 0x9f587682, 0x20002305, 0xf17a7b00, 0xe7ff2205, 0x213983e1, 0xfb75e0ff, + 0x00ff2405, 0x82fa9f0a, 0x22f982d0, 0x82400d00, 0xdeff22c5, 0x24d082b8, 0x8bb81e0d, 0x241b8296, 0x00ffb89e, 0x821b8600, 0x21002716, 0x1600ff46, + 0x14823d0a, 0xa1343323, 0x059568ff, 0x33331c29, 0x00ff6208, 0x8234b35a, 0x82cf20b0, 0x45002243, 0x2c82825e, 0xff9a59b0, 0x7a542a00, 0x19abffff, + 0x27d78299, 0xff083433, 0x8f42baff, 0xe0203b82, 0xbf2b6782, 0xffff3e8a, 0x5bf648e6, 0x84cfffff, 0xa1d13791, 0xd1ffff48, 0xffff46a1, 0xffae07e7, + 0xba5ec2ff, 0xbeffff8c, 0x35826666, 0x3083ff20, 0x0080ea23, 0x263b8205, 0xfffff97f, 0x82f6a8f2, 0x0760239b, 0xb386ff80, 0x839a9921, 0x21be849c, + 0x248266e6, 0x8b004022, 0x65440585, 0x220c8205, 0x821f850b, 0x23978332, 0x98e17aff, 0x00271682, 0x00ff0020, 0x83b89e17, 0x82252053, 0x8234261b, + 0x1300ff90, 0x21ef82de, 0x42826631, 0x67262527, 0x192500ff, 0x2629829a, 0xffb9de26, 0x82c02600, 0x8034212e, 0x14200482, 0x38272383, 0xffff7b54, + 0x820040ff, 0x20ec841e, 0x207683ff, 0x2cec8341, 0xffe27adc, 0x68e62700, 0x3fc7ffff, 0x221e82fe, 0x41be9f07, 0x0e25065e, 0xffff42e0, 0x218282fd, + 0x42830a00, 0x83a00721, 0x820a203d, 0x070026eb, 0x00ffceac, 0x205c8303, 0x064d4a0e, 0xe627ab82, 0xaf0e0866, 0x82b400ff, 0x32012416, 0x82150080, + 0x33332655, 0x3400ffac, 0x209982e6, 0x2115821c, 0xd55c3f00, 0x83068305, 0xff662316, 0x1683e3ff, 0x3433272e, 0x6ab2086a, 0xcc1b00ff, 0xd9ffffcc, + 0x0e22cd83, 0x1c829c19, 0x82cdcc21, 0x8304208f, 0xccf63814, 0xff808bcd, 0x3433fbff, 0xccf6ffff, 0xffff08cc, 0xff64e6f1, 0x82b3e4ff, 0x83e4200f, + 0x80d82414, 0x826a6400, 0xccd82816, 0xffff6acc, 0x859a19cb, 0xc0ff245b, 0x828b9a99, 0x83068316, 0xff992216, 0x24898300, 0xcdccd8ff, 0x231682ac, + 0xffcdccef, 0x24059969, 0xff33b3f1, 0x20cc8400, 0x221383f3, 0x829a990e, 0x51a6221e, 0x2a3482eb, 0xff0532b3, 0x717df3ff, 0x83f8ffff, 0x26f0286e, + 0xffff8d66, 0x82c9b6f5, 0x323321f2, 0xf5222582, 0x0a8373b6, 0xfd258982, 0x00ffe2d7, 0x26af820f, 0x9e2f0700, 0x830c00ff, 0x2d002844, 0x00ffb4c8, + 0x829a1950, 0x37d22244, 0x220a874c, 0x8462d0f8, 0x00ff2420, 0x861e2802, 0x490a2234, 0x8248848d, 0x490a22f4, 0x825e8437, 0x9ad92119, 0x0c221582, + 0x7e848f82, 0x59221a82, 0x948615ae, 0x330c0022, 0x9921b483, 0x20b9829a, 0x83c8824c, 0x100021be, 0x0d301383, 0x8b08cccc, 0x00ff058b, 0xff0080eb, + 0x0080adff, 0xee203282, 0x08df6818, 0xec82ff20, 0xffff8b26, 0x08cd4cee, 0xcc200684, 0xcc213f83, 0x261682ff, 0x1100ff34, 0x828b34b3, 0x65581865, + 0x0a697209, 0x1e838b20, 0x28863320, 0x72820e20, 0x25059772, 0xf74cf70e, 0x4a821574, 0x82b3f221, 0x83f5201c, 0x82048417, 0x204a820e, 0x210683ff, + 0x1183ffff, 0x0ac18f18, 0x0d204a82, 0x11832882, 0x3782e882, 0x0e820020, 0x06842d82, 0x32831185, 0x08235485, 0x8a8b54f7, 0x86aa825f, 0x82aa835f, + 0x8234205f, 0x4cf52126, 0x0a22c682, 0x9d1833b3, 0x5f820db6, 0x1682d382, 0x5882ff20, 0x5f85cc20, 0x8b07ec7a, 0x6b1c215f, 0x5c295818, 0xfbd4fb28, + 0x14f71524, 0x7c18ff06, 0xb382157e, 0x18cc0821, 0x20119072, 0x723082fb, 0x79180af9, 0x00221126, 0x7d183307, 0x6b270c2c, 0x00ff15f3, 0x82cdcc27, + 0x8220204f, 0x5cab1819, 0x2011820a, 0x23618327, 0xffcdccdf, 0xff261683, 0x3333d8ff, 0x0685088b, 0x83ffff21, 0x21048216, 0x10838bcc, 0x85083421, + 0x82288306, 0x82df205e, 0x25548437, 0xf754f708, 0x21841524, 0x16832082, 0x34203294, 0xcc204e83, 0xcc208783, 0x39826082, 0x72845582, 0x28828e94, + 0x82332021, 0x33d82432, 0x71088b34, 0xff256002, 0x6666b000, 0xc058189b, 0x19cd200f, 0x221e9f13, 0x6b4ceeff, 0xb32009d0, 0x200cbf75, 0x057a43cd, + 0xb3f1ff2f, 0x1100ff33, 0x088b33b3, 0x15cb34f7, 0x223182ff, 0x82ff8bce, 0x83322015, 0x20319104, 0x841683ce, 0x8b322231, 0x4e591808, 0x278da00e, + 0xff0080b3, 0x9a993eff, 0x1c22c682, 0xbb8266e6, 0x68661b31, 0x33faffff, 0x1800ff32, 0xffff6666, 0x8234b3f5, 0x4c0c2253, 0x291482cc, 0x00ffcccc, + 0xffcecc0d, 0x23840900, 0x2382b320, 0x32330c26, 0xefffff08, 0x00262982, 0xff343326, 0x1e83d8ff, 0x28821b20, 0x4cd2ff23, 0x238d82cc, 0x6766d2ff, + 0xd826bb82, 0xffffcdcc, 0xa9824ce4, 0x4983ef20, 0x83b3d921, 0xb3fa2135, 0xf3263082, 0xff98cecc, 0x4b83f6ff, 0x82330d21, 0x330521c4, 0x7a836f83, + 0x820a0021, 0x1b00262a, 0x00ffcd4c, 0x20298205, 0x2b9e8300, 0x058b8b08, 0xff8af80e, 0xb85e8601, 0x1520b182, 0x15292183, 0xff7c0040, 0x48612400, + 0x296f826d, 0x866b43fe, 0xe1ffff06, 0x7582b2fd, 0xfff02208, 0xdbffffbe, 0x00ffb89e, 0xff834015, 0x00c0eaff, 0xfb6af708, 0xffff056a, 0x0748a14f, + 0x23cfffff, 0x08e66054, 0xf568eb22, 0x7f0b7b5f, 0x082411f1, 0x088b04d6, 0x8205155c, 0x00ff2109, 0x0e74d418, 0x00ff8b25, 0x8490821a, 0x266e8242, + 0xffff707d, 0x82707de5, 0xd0ff2f90, 0xff0666e6, 0x6666b000, 0xd500ff07, 0x04829a19, 0x8252f821, 0x829f2081, 0xf9ff2a0a, 0xff1548a1, 0x70fdbfff, + 0x2211824b, 0x825ccf55, 0x00c02a8d, 0xff05cb00, 0x34332a01, 0x735c1806, 0xfe250862, 0xffccccb1, 0x5ccfc000, 0xffff9515, 0x05ec91ee, 0xb30200ff, + 0xfbffff33, 0x00fff628, 0xff008001, 0xae87faff, 0x2805828b, 0xff08146e, 0x9a99d6ff, 0x200c8207, 0x28ba82fc, 0x9a990100, 0x33fcffff, 0x28308632, + 0x08ce4cfd, 0x4c0600ff, 0xc28218cd, 0x85332008, 0x05002440, 0x82910080, 0x990d231a, 0x5d829c99, 0x34b3042b, 0xe60500ff, 0x0800ff66, 0x21218333, + 0x3582cecc, 0x3582cc20, 0x9a99fc22, 0x0f202582, 0xff235082, 0x826666f8, 0x66032729, 0xfeffff68, 0x6082cc4c, 0xff212e82, 0x237483ff, 0x8b32b304, + 0x06232582, 0x828b0080, 0xce4c2136, 0x2105726a, 0x8b820400, 0x1a820483, 0x2b820320, 0x04820020, 0x02204082, 0xdf830a84, 0xc8830420, 0x0e84ff20, + 0xff222982, 0x6a8319fe, 0x5a821d20, 0x84f1ff21, 0x8207206a, 0x84ff2094, 0x820420d5, 0xf8ff2324, 0xe5829a19, 0x6666f723, 0x20068208, 0x203b83f5, + 0x201683f8, 0x52ab82f6, 0xfd3105ef, 0xff080080, 0x9899dcff, 0x19f7ffff, 0xffff0598, 0x215684f8, 0x09823433, 0x00209483, 0x82053a71, 0x660228e4, + 0xff6b0868, 0x83990a00, 0x99fd2525, 0x0100ff99, 0xff21c782, 0x2b5482fc, 0x9a990000, 0x99fcffff, 0x84088b9a, 0xf8226782, 0x2f54cd4c, 0x83fb2006, + 0x0564713d, 0x2283d820, 0x0080e222, 0xf5206282, 0x66249984, 0xfaffff66, 0xf4224183, 0x34823433, 0xa382f320, 0x53616f20, 0x817d1817, 0x0aef450d, + 0x4a185b20, 0x5e18072c, 0xa8820fe4, 0x0021fa83, 0x2c9e8309, 0x9134b304, 0x190800ff, 0x00ff0898, 0x24878219, 0x9a192200, 0x25108205, 0xff97cc4c, + 0x21830400, 0xbb820c20, 0x0d00ff24, 0x664acccc, 0x21558205, 0xa5820300, 0x83020021, 0x66032c2d, 0x0300ff68, 0x00ffcccc, 0x8266e600, 0x4c052220, + 0x21fc82ce, 0x4282cc4c, 0x66e60b23, 0x8248828e, 0x0a0022cb, 0x26c682b3, 0xcc4c0c00, 0x82938b08, 0x423320fe, 0x8625051c, 0xffff0890, 0x226283de, + 0x82018021, 0x83fb20fb, 0x9904262a, 0x00ff8b99, 0x21fc8205, 0x60840400, 0x8333b321, 0x32b32156, 0xb3211482, 0x254f8433, 0x0700ff8d, 0x478234b3, + 0x82676621, 0x820e201a, 0xfbff232a, 0x7182cd4c, 0xff226082, 0x8c83fcff, 0x4a840d20, 0x00222482, 0x9082cc05, 0x99990b22, 0x03232982, 0x83920080, + 0x204a823a, 0x204a8303, 0x231a8206, 0x0080feff, 0x1c271a82, 0xffffcc4c, 0x820080fa, 0x83e62085, 0x82572035, 0xb0ff2104, 0x40204483, 0xff210482, + 0x053278a0, 0xcd4ce428, 0xe4ffff8b, 0x2b82cdcc, 0xff219b82, 0x234582e8, 0xc235f6ff, 0x1805ae44, 0x33603960, 0xc2b539fe, 0xe63f00ff, 0x00ff1566, + 0xff295c09, 0x34b3eeff, 0x082ff582, 0xffff3e4a, 0xff0080f1, 0x48a10d00, 0x82f5ffff, 0x100022ca, 0x221e821c, 0x826766fb, 0x003925da, 0xefffff01, + 0x0026da83, 0xff991912, 0x0482fbff, 0x830b0021, 0x4cf022c3, 0x31ce82ce, 0x089819ee, 0x19d8ffff, 0x808b079a, 0x330600ff, 0x5d828133, 0x87cdcc22, + 0x09203a82, 0xfa222583, 0x16853433, 0x08808b24, 0x30820764, 0x6666f032, 0xe60e00ff, 0xf4ffff66, 0xff9acccc, 0xce4c0400, 0x10202b82, 0x04212683, + 0x200f8299, 0x221f830c, 0x8232b30d, 0x82192019, 0x660f220e, 0x261e8266, 0xffcccc02, 0x83330b00, 0x830420af, 0xe6102329, 0x45829666, 0x0f20b583, + 0x08222583, 0x258234b3, 0x98190822, 0x99263582, 0xff9a059a, 0x1b830800, 0x2b830920, 0x66e60f28, 0x1100ff8b, 0x2183cc4c, 0x82343321, 0x0c002183, + 0xff214e82, 0x258382fa, 0x34330c00, 0xc0829482, 0x2983fc20, 0xcccc032b, 0xff948205, 0x32b3f3ff, 0x82058291, 0x5f0838df, 0xf5ffff06, 0x808bcccc, + 0xf6ffff8d, 0x00ffcd4c, 0x08008005, 0x83ddffff, 0xcc13365d, 0xffff05cd, 0xff33b3fb, 0x67660200, 0xb3fcffff, 0xffff8f34, 0x051643fe, 0x25823320, + 0x6682fc20, 0x99090023, 0x83948299, 0x660a233a, 0x0a829467, 0x08999923, 0x25318291, 0xff0566e6, 0xf1830600, 0xce4c0325, 0x830700ff, 0x83002026, + 0x8206200e, 0xfdff238a, 0xae829899, 0x99191827, 0x4cf8ffff, 0x202982ce, 0x23e68208, 0xcc4cfdff, 0xff24d982, 0x0300ffff, 0x00230e82, 0x82cecc04, + 0x9a192138, 0x04222982, 0x0a8432b3, 0x7f831b82, 0x28820920, 0x84faff21, 0x20af844d, 0x2e9f82f2, 0x34331000, 0xff978105, 0x99190000, 0x831100ff, + 0x820a2026, 0x0b00236a, 0x4082cccc, 0x40830f20, 0x48611222, 0x56836a83, 0x1e450a2f, 0x660100ff, 0x0e00ff66, 0xffffa4b0, 0x235082f9, 0x72bd0b00, + 0xfd20d582, 0x04225683, 0xfb84f428, 0x4e823420, 0xff862b24, 0x2983fdff, 0x0a170025, 0x42fcffff, 0xa32605ec, 0xff8b9a19, 0x3682b1ff, 0x82c3ff21, + 0xe5ff26ab, 0xffff5c4f, 0x306a82ac, 0xff058b8b, 0xd8e37b01, 0x992500ff, 0xffff159a, 0x063f48e6, 0xf0204e82, 0xf9202d83, 0x51768882, 0x83ee2005, + 0x83052068, 0xe6ef2213, 0x27a28266, 0xff66e610, 0xcd4ccdff, 0x0320a282, 0x0852bd82, 0x20098306, 0x216182f8, 0x2e820a00, 0x6146ff20, 0x821d2005, + 0xf8ff23d7, 0x2982cccc, 0x3233012e, 0x0000ff94, 0x00ff9a99, 0x8b343309, 0x4c220582, 0x068208cc, 0xcdcc2425, 0x82f6ffff, 0x2200267b, 0xffff9999, + 0x253182ef, 0x9a191e00, 0x50478b08, 0xae333264, 0xd8ffff14, 0xff1566e6, 0xe2ba1f00, 0x99f9ffff, 0x25ab829a, 0xff29dc07, 0x9383feff, 0xd8230825, + 0x820200ff, 0x050028da, 0x00ffa4b0, 0x8234b305, 0x660f27ff, 0x0f00ff67, 0x29826666, 0x1a830b20, 0x29830c20, 0x9a99132d, 0x0700ff87, 0xffffcc4c, + 0x82ce4cf1, 0x4c092125, 0xed22d882, 0x25820080, 0x67e60322, 0x0a29e386, 0xffff33b3, 0xffccccfa, 0x20098200, 0x2025828b, 0x05a87a0f, 0x00212082, + 0x6567180d, 0x05814e08, 0x9a19fa26, 0xe61300ff, 0xff216682, 0x834b82fb, 0x00ff2471, 0x8299990b, 0x2275837b, 0x839a1910, 0x4c022c40, 0x00ff06cd, + 0x8b00800c, 0x830d00ff, 0x82062088, 0x07002162, 0x0b220983, 0x61829a19, 0x56820a20, 0x19100023, 0x21878299, 0x51829905, 0xbd820820, 0xb3ffff23, + 0x214b8232, 0x1d6b9919, 0x33082106, 0xff26d782, 0xff68e6ef, 0xb1831500, 0x83f5ff21, 0xb30d231f, 0x81829232, 0xffcecc24, 0x44831000, 0x32330429, + 0x00ff9c08, 0x829a1905, 0x8007264b, 0x00ff8c00, 0x21a38306, 0x21824c05, 0x66e60222, 0x2182fe82, 0x4c272c82, 0x2800ffcc, 0x6a05f6e8, 0x0725066f, + 0xffffec91, 0x304683e8, 0xffb81e04, 0x66e6e6ff, 0x06fb088b, 0xa1ffff8b, 0x200082ff, 0x220e82a2, 0x828dffff, 0x201182ab, 0x25a183f2, 0xfff62802, + 0x4f83f2ff, 0x856b023e, 0x66f3ffff, 0x8b8b0866, 0x8e01ff05, 0xffff52b8, 0x1534b3fa, 0x33f0ffff, 0xfbffff34, 0xf920aa84, 0xff246d82, 0xff3233fe, + 0x2005cd61, 0x21a98202, 0x9183fcff, 0xcccc0527, 0x00ff8908, 0x28ae8203, 0x0900ff85, 0xffff6666, 0x205e83f5, 0x21048206, 0xe65bf4ff, 0x84f42005, + 0x83f4207c, 0x83f92033, 0xccfa2320, 0x4a57ffcc, 0xf9ff2105, 0xff218082, 0x206284f6, 0x203183fe, 0x21c082fd, 0xef82feff, 0x98210482, 0x05396cff, + 0x9a99ff29, 0xdaffff08, 0x827666e6, 0x83ee20eb, 0x05f8473b, 0xe9202f83, 0x00215482, 0x20098307, 0x22db82ed, 0x830600ff, 0x99f3265f, 0x00ff059a, + 0x20158308, 0x212e82ec, 0x4f831600, 0x2983f620, 0x6e821220, 0x82070021, 0x82b182ea, 0x01002329, 0x2982cccc, 0x1f820a20, 0x83020021, 0x830b201a, + 0x66fe22e1, 0x843d8268, 0x32b322ad, 0x05b24908, 0xe6feff23, 0x2a298266, 0xff343325, 0x00801d00, 0x831a00ff, 0xe629212e, 0x0a342982, 0x00ffcc4c, + 0x08981930, 0x0000ff88, 0xff88ce4c, 0xccccffff, 0x33270583, 0x068b0834, 0x83d9feff, 0xe6bc2549, 0x83ab1566, 0x99209584, 0x9583d682, 0x4bb30821, + 0xff2205da, 0x7f830200, 0x6b82ae82, 0x82330221, 0x22b98414, 0x83cdccfa, 0xff322385, 0xa983f7ff, 0x08232382, 0x8305936b, 0x8267200d, 0x23878231, + 0xcd4cf7ff, 0x2105e642, 0x8c82fdff, 0x08202683, 0x14825a83, 0x05203184, 0x23824a82, 0x0941ce20, 0x25238206, 0xff078b08, 0x4d835000, 0x66662723, + 0x872b9e15, 0x23aa8536, 0x0500ff32, 0xaa897382, 0x82ab9321, 0x830220cc, 0x20ad8612, 0x9ead8fcc, 0x6b8321aa, 0x55204082, 0xcf304083, 0x7b15ce4c, + 0xff87056b, 0x9819f8ff, 0x330300ff, 0xf625f382, 0x00ffce4c, 0x23d68307, 0x089a19fc, 0x68250a83, 0x0900ff87, 0x838782b3, 0x0554491f, 0x08241f82, + 0x8f05ab9b, 0xff231e84, 0x82ccfcff, 0x82228333, 0x829a2047, 0x66e62247, 0x22528408, 0x83ffff8f, 0x201f844e, 0x834e82ff, 0x089a2314, 0x0c4f078b, + 0x8f013f61, 0x1523cc4c, 0xb3c8ffff, 0x07630634, 0x00ff0693, 0x8bcccc17, 0xb31300ff, 0x1100ff34, 0x0d4acc4c, 0xb3162206, 0x25a98234, 0xc334b3d0, + 0x27828315, 0x3700ff25, 0x8206cc4c, 0x823320cf, 0x221b8225, 0x83ecffff, 0x2b2f832a, 0x3433e8ff, 0x6373088b, 0x4b07b315, 0xcb232982, 0x88538b06, + 0x24fb270a, 0x076315eb, 0x1a8306cb, 0x0a871682, 0x829b7b21, 0x82832021, 0x33e8234e, 0x4a838b33, 0xffffcd23, 0x297f82ee, 0x3333fcff, 0x4ce9ffff, + 0x6f8308cc, 0x4985cd20, 0x3320aa83, 0x0321a682, 0x822582cc, 0x82aa831b, 0x822f8325, 0x8bcd22ba, 0x24c38308, 0xf7666608, 0x63991874, 0x2b6a180d, + 0x11b44f0e, 0x222d824f, 0x504b34f7, 0x10503242, 0x62f94129, 0xcc4c0036, 0x33b4ffff, 0xffff1534, 0x8b9a99d0, 0x33d3ffff, 0x0600ff34, 0x08b05c18, + 0x190c2208, 0xffff089a, 0xff33b3f3, 0xcccc0300, 0xf5ffff7f, 0xff90cc4c, 0x3433f4ff, 0x1800ff08, 0xffff67e6, 0x222b82c4, 0x824c3a00, 0x99d62546, + 0x4300ff9a, 0x3105d65b, 0x8b68e643, 0x333a00ff, 0x2900ff32, 0xffa46666, 0x48823b00, 0x00ff9023, 0x2344830b, 0x34b30a00, 0x04825483, 0x4883fc20, + 0x83d8ff21, 0x82f3203e, 0xd3ff2848, 0xffffce4c, 0x839a19f9, 0x8b98278e, 0xff068b08, 0x0d82b0ff, 0xcc9b0023, 0xca0110cc, 0xaf25c201, 0x00ff34b3, + 0x0fca41cb, 0xcc4ce322, 0x5e05915e, 0x33280598, 0x4c0e00ff, 0xe3ffffcd, 0x4a530482, 0x84ff2005, 0x29168506, 0x33b31c00, 0x2300ff8b, 0x2d82cd4c, + 0xcc240682, 0xb3f1ffff, 0x1c203282, 0xff295a82, 0x8bcd4cee, 0xfb34f708, 0x0daa7f14, 0x88823293, 0xcc233286, 0x82ff088b, 0xf47f1839, 0x91778207, + 0x8665828e, 0x649d548e, 0x96430120, 0x33e237a2, 0x6400ff34, 0xff153233, 0xcd4c0300, 0x190100ff, 0x0200ff9a, 0x0e823333, 0x8b9a1922, 0x66220582, + 0x06820866, 0x66e61125, 0x41f9ffff, 0x342b05ca, 0x19f6ffff, 0x0d00ff99, 0x82083233, 0x3433250a, 0xf1ffff98, 0x00211f82, 0x214b820a, 0xa34cf0ff, + 0x85068305, 0xf5ff2316, 0x2684cccc, 0x2d837e20, 0xff233882, 0x85ceccf2, 0x06af414c, 0x284aee20, 0x99fc2105, 0xff217a86, 0x834d83fc, 0xfeff248e, + 0x820866e6, 0x828f8284, 0x8267200a, 0x20238309, 0x21448201, 0x04840200, 0x08cdcc29, 0xff058b8b, 0x82330000, 0x4c0022c6, 0x820a84cd, 0x830020bc, + 0x83ff2031, 0x821482af, 0x220e82d5, 0x82660000, 0xffff224b, 0x20e582cc, 0x20048300, 0x20978201, 0x20ef8400, 0x203d8301, 0x4c1e8301, 0x02210518, + 0x216a83e6, 0x6f820080, 0x4c82b320, 0x3d830420, 0x99990422, 0x08208982, 0x06203883, 0x0a201e83, 0x06207f83, 0x13821983, 0x1a858b20, 0x00ff8b22, + 0xff211683, 0x822583f9, 0x20e58216, 0x20358319, 0x22268204, 0x8666fbff, 0xfcff2154, 0x02209783, 0xff215e82, 0x831e84fd, 0xfeff227e, 0x20fd8299, + 0x82f88200, 0x826620e8, 0x237882d0, 0x3333ffff, 0xc1835882, 0x84ffff21, 0x2047831e, 0x821982ff, 0xff3322ef, 0x83ca82ff, 0x20bc821e, 0x221482ff, + 0x828b8b05, 0x820220fd, 0xfdff2296, 0x20b58233, 0x41318203, 0x0e830634, 0x6a820120, 0xff078b25, 0x82199700, 0xcc022367, 0x094a15cd, 0x212b8705, + 0x2b87ff98, 0x00ff3422, 0xfb822b83, 0x42cc4c21, 0x1482080f, 0x0f420320, 0x25208212, 0xff34b311, 0x5483f6ff, 0x21350f42, 0x0f42ff9a, 0x43cc2007, + 0x0f4207bf, 0x425e820d, 0x2082060f, 0x82070f42, 0xe6fe2214, 0x21a38267, 0xae849899, 0x0020cc85, 0x0f42d782, 0xff322112, 0x21062f41, 0x0982ce4c, + 0x82cd4c21, 0x83332031, 0x060f4213, 0x0f421483, 0x423d822e, 0x3d82070f, 0x22060f42, 0x4200ff9a, 0xcc20060f, 0x25050f42, 0x00ff8bcc, 0xe082190a, + 0x20060f42, 0x090f42ce, 0x42ff3221, 0x3421300f, 0x080f42ff, 0x0a82cc20, 0x83050f42, 0x050f4214, 0x0f423220, 0xf80e3113, 0x15d4f764, 0x80e5ffff, + 0xffff8b00, 0xa00080ea, 0x192a9282, 0x8b0870fd, 0x0100ff90, 0xb182cccc, 0xff204526, 0xcecc0200, 0xde270982, 0x00ff08b8, 0x82cc4c00, 0x34b32104, + 0x4c210482, 0x210482ce, 0x0482c2b5, 0x82666621, 0x52b82104, 0x08211e82, 0x250a82e6, 0xffe03a14, 0x80831100, 0x68a61823, 0x05ac54ff, 0xf6930c22, + 0x03271e82, 0x00ff3233, 0x82006004, 0x8266204d, 0x00002319, 0x614bff42, 0xa0fb2c05, 0xff980800, 0x8aa1eeff, 0x821c00ff, 0xd7ff2339, 0x918248a1, + 0x8e02ec23, 0x30068208, 0xff5c4fea, 0x9a19f1ff, 0xe6edffff, 0xebffff68, 0x26cc82b3, 0x080080fa, 0x83fbffff, 0x82fe200f, 0xfbff2174, 0xff201483, + 0xff358982, 0x8b9a99fb, 0x058b8b08, 0x00ff64fb, 0x15ecff7f, 0x663300ff, 0x20d78266, 0x2526832f, 0xffaed9f0, 0x4a832800, 0x84ebe522, 0x2c073861, + 0xfff6e8fc, 0x0080feff, 0xe3fcffff, 0x820982d8, 0xfcff23de, 0x1e8266e6, 0x5583fc20, 0xc2f5f722, 0x33221982, 0x8a828034, 0x5c8ff422, 0xd3259183, + 0x00ff2a9c, 0x20a88324, 0x217282dd, 0xe95e2b00, 0x82092005, 0x83ef8279, 0x820120e4, 0x08002143, 0x00232082, 0x82981903, 0x4c0d25f9, 0xe1ffffce, + 0x2f507782, 0xe6dd2205, 0x224c8267, 0x833333dc, 0xb174184c, 0xffff2442, 0x4107ecff, 0xfe23059d, 0x494833b4, 0x06109ae7, 0x18de0350, 0x205fd550, + 0xa3344bff, 0x0100c72b, 0xb3ca00ff, 0xffff1532, 0x934018ee, 0xb3ed2a08, 0xf5ffff33, 0xffff0080, 0x821382fb, 0x08322118, 0xb32e0a82, 0xefffff34, + 0x7a0568e6, 0x4c0400ff, 0x0c8205cc, 0x82991921, 0xcccc230a, 0x3085ffff, 0x82686621, 0x703d2125, 0x30844983, 0x4c260a84, 0x0a00ffcd, 0x23851f85, + 0xcc110023, 0x272382cd, 0xff083433, 0x9a194100, 0x99212982, 0x08db5399, 0x002e7482, 0x9034b308, 0x4c0200ff, 0x0800ffcc, 0x25829a99, 0x85821120, + 0xe6410023, 0x07ee5d66, 0x66e61022, 0x00239a85, 0x82ce4c12, 0x27b3843f, 0x8b08cccc, 0x9a00ff06, 0xff236b82, 0x826666e8, 0x33fb26cb, 0x1100ff32, + 0x202182cc, 0x21b682ed, 0x45820a00, 0x33eeff22, 0xfb22c082, 0xcb82cc4c, 0x1e82ee20, 0x0f82db82, 0xed21e584, 0x202d82b3, 0x20df8404, 0x23748719, + 0x9a19beff, 0x8a837482, 0x82054854, 0x8486209a, 0x209f8395, 0x20c084cd, 0x21638298, 0x25826766, 0x00226983, 0xb582cc04, 0x00216983, 0x82888312, + 0x211e8269, 0x6e8233b3, 0x7982fb20, 0x69828d87, 0x98990a22, 0x7d82b983, 0x1e821882, 0x1448ef20, 0x05342105, 0x24056441, 0x98191000, 0x69111005, + 0x20080501, 0xff343385, 0x9819b900, 0xf8ffff15, 0x00ff9919, 0xffce4c04, 0x6666f6ff, 0x33faffff, 0xffff8b32, 0x056e4df7, 0x2683fd20, 0xfa5a0020, + 0xb3023008, 0xfdffff34, 0xaf08cecc, 0xccd4ffff, 0x836705cc, 0x05cd2106, 0x4c211382, 0x06bc55cc, 0x82e6ff21, 0x4cfd2243, 0x824382cc, 0x8508203c, + 0x00ff244a, 0x849a9909, 0x00ff245a, 0x8467e607, 0xff08236e, 0x2b825900, 0xe62f0027, 0x00ff0566, 0x2759820a, 0x33b30500, 0x0f00ff8b, 0xf5208583, + 0x0f835082, 0xffff0823, 0x857e82a6, 0x06012625, 0xffff0080, 0x05276ff5, 0x3c820820, 0x0022b184, 0xbb82cc05, 0x2582f820, 0xb3fbff23, 0x23308632, + 0x9a19d0ff, 0x46839782, 0x4cfaff23, 0x208682cd, 0x848182f0, 0x860f8366, 0x8225857c, 0x82b38292, 0x83a6853b, 0x051c764f, 0x0026bd82, 0x8acccc02, + 0xf88400ff, 0x3433fe22, 0x33220982, 0xc0820833, 0x33332b29, 0x00ffaf05, 0x8234332b, 0xcc0122bc, 0x211883cc, 0x28848c32, 0x34823b82, 0x078b0826, + 0xaa01ff0e, 0x01271982, 0x15ecd1b1, 0x831300ff, 0x3913253d, 0x1f00ffda, 0xff22c583, 0x13825899, 0xff239382, 0x825c6fec, 0x7f13318e, 0xecfffffe, + 0x00ff166e, 0xff686600, 0x3c8ae0ff, 0x3d820e82, 0xc5ecff28, 0xffff0820, 0xe3824cf8, 0xf628f92f, 0x4cf2ffff, 0xfaffffcc, 0xffff146e, 0x21f284f0, + 0x1e82a4b0, 0x4883ef20, 0x0483fb20, 0x1e83ee20, 0x66e6fc22, 0x22067453, 0x823233fe, 0x66fe211e, 0xff220f82, 0x417634b3, 0xffff2105, 0xff205783, + 0xcc218584, 0x201e82ce, 0x830a84f9, 0x82fc204d, 0x056e4304, 0x42820020, 0x99050023, 0x209a829a, 0x25578201, 0xc2350b00, 0x446eff8e, 0x82042005, + 0x1100234d, 0x094c6866, 0x82012007, 0x25b58272, 0x0100ff66, 0x134cae47, 0x82098206, 0x8304201e, 0xf00f2519, 0x0400ffa4, 0x00217c82, 0x2e48830e, + 0xff32b307, 0x0ad70600, 0x058b8b08, 0x83d3ffff, 0x02ed23ec, 0x785b1590, 0xfbff2305, 0x0982c235, 0xff222282, 0xb38226fb, 0x82ccfe21, 0x4afb22f6, + 0x27a4823e, 0xff3233fb, 0x5c0fedff, 0x23055557, 0xf668ecff, 0x5f822882, 0x42f4ff23, 0x831e828e, 0xe5ff22b9, 0x206a8230, 0x21b98216, 0xc883e9ff, + 0x74831a20, 0x66e60322, 0x0b208982, 0x00211482, 0x200f8301, 0x058f4b13, 0xcc829a20, 0x04201383, 0x9e841e84, 0x61820120, 0x0f820020, 0x4c21c782, + 0x82b283ce, 0x800122a8, 0x203d8200, 0x26a58337, 0x7d66669e, 0x8281ffff, 0xacff2343, 0x4c5dcccc, 0x82058405, 0x84148304, 0x19f22919, 0x9effff98, + 0x00ffcd4c, 0xa9593382, 0x05504106, 0x66660122, 0x38825382, 0x33010023, 0x21098233, 0x1e8234b3, 0xcdcc0426, 0x0300ff9e, 0x14201083, 0xa1841f83, + 0x92840a20, 0xff22b782, 0xff831a00, 0x9919e924, 0xd58400ff, 0x3d4ae522, 0x1921fe82, 0x22ef829a, 0x867b14f4, 0x6bec22ff, 0x82148285, 0xedff26cb, + 0xffffeb11, 0x201e84fb, 0x208282fb, 0x053d41ff, 0x1e822b20, 0x32b3fe22, 0x38211982, 0x83328252, 0xc8ff36d0, 0x00fff5a8, 0xff9a9961, 0xecf10d00, + 0x4c7e00ff, 0x5300ffcc, 0x220e8239, 0x82523853, 0x82058296, 0xa63b210f, 0xca821983, 0xe0ef0d22, 0xe3832d82, 0xd8a3c829, 0xff078b08, 0x82332200, + 0xde56234f, 0x558215b7, 0xff34332e, 0x67e60b00, 0xff858a7b, 0x33b3f4ff, 0xec259b82, 0xffff0080, 0x208183db, 0x202783e5, 0x200e83db, 0x620486de, + 0xff200633, 0xdb240f84, 0xffff0180, 0x2d832385, 0x1e823782, 0x85224382, 0x53837b8a, 0x5d846620, 0x3b268f82, 0xffff6766, 0xa482cce7, 0x46824620, + 0x68286d82, 0x193000ff, 0xbb08bb9a, 0x98200783, 0x00202b85, 0x25851b83, 0x20082f82, 0xff068b08, 0xae07befe, 0xcca9ffff, 0x00ff15cd, 0xffec1138, + 0x66e6faff, 0x0500ff05, 0xffff9a19, 0x250a84c7, 0xff333300, 0xc183fdff, 0x80830120, 0x5d83fd20, 0x66e60123, 0x21738289, 0x7e826606, 0x9a99f92c, + 0xcc0a00ff, 0x0200ffcd, 0x048232b3, 0x3e470e83, 0xb31d2705, 0x6100ff33, 0x4f820080, 0x15830220, 0x00800c27, 0xffff9581, 0x223583f4, 0x826766fc, + 0x8c9e2dc7, 0xe2ffffcd, 0xff056766, 0xf568f7ff, 0x1a836682, 0x6683fd20, 0x8233f521, 0x5706244b, 0x82ffff0a, 0x236a825f, 0x8952f801, 0x97265c82, + 0xfeffff0b, 0x0982cecc, 0xff1fc532, 0xccccffff, 0xff078b08, 0x1e458d00, 0xffff15ee, 0x5d845382, 0xff819523, 0x846b8200, 0x823a828b, 0x00ff2281, + 0x0548621d, 0x02228683, 0xab869899, 0x49820a20, 0xff215f83, 0x20c98200, 0x825f8208, 0x848482d7, 0xce4c21e1, 0x0022f586, 0xa9823233, 0x66e6c723, + 0x05de5dff, 0x83faff21, 0x1138220a, 0x82b482ec, 0x214a8280, 0x94871ec5, 0x830a9721, 0x52f82144, 0xb6823082, 0xc0835682, 0xff21ca83, 0x834f84fd, + 0x68f722de, 0x821e82f6, 0xffff24f4, 0x82cc8c9e, 0xd4473644, 0x23ffff7b, 0xff156666, 0xe27a1200, 0x1400ff90, 0x00ff3e4a, 0x27308203, 0x9a190c00, + 0xb30100ff, 0x00218082, 0x20ba8305, 0x227a8300, 0x82cdcc04, 0x281982eb, 0x9919ffff, 0x80f9ffff, 0x204f8200, 0x083358fe, 0x33b3fc2b, 0xccebffff, + 0xffff86ce, 0x221a84ed, 0x8285abfb, 0x73fa2160, 0xf2201682, 0xf9272583, 0xfffff628, 0x82ce4cf8, 0x83ec2035, 0xccec26ba, 0xe0ffffcc, 0x2c73828a, + 0xff686600, 0x146eecff, 0x7f1300ff, 0x211e83fe, 0x80455c6f, 0x99ff2206, 0x05944558, 0x39130023, 0x221382db, 0x82083433, 0x0ad72cdd, 0xb30700ff, + 0x0e00ff32, 0x44ff7b94, 0x0f2105bf, 0x25c682ee, 0x08cc4c04, 0xf567078b, 0x97ff2962, 0xffff6666, 0x150080b4, 0x59314c59, 0x8b2f63e2, 0x01ffff06, + 0x00ff6766, 0x1566e6ce, 0x83efffff, 0x4cdd29ad, 0xffff05ce, 0x86d7e3d9, 0xfc2c0682, 0xffffa4f0, 0xff9899ff, 0x3373fdff, 0xe6210482, 0x230e8268, + 0x08883d0a, 0x0c210682, 0x301082cd, 0x00ff9819, 0xffecd100, 0xceccfcff, 0x3a0200ff, 0x331382e2, 0xff0866e6, 0x48e11b00, 0x80e5ffff, 0xff840500, + 0x3333daff, 0xfe224b82, 0x26829999, 0x6d82e620, 0x9a190223, 0xc3681988, 0x82332008, 0x80022b2c, 0xfeffff00, 0x00ff9919, 0x55824c03, 0xad43ff20, + 0x05d86805, 0x20201e82, 0x12273483, 0xff05cd4c, 0x82b32200, 0xb3ed2186, 0x00214f82, 0x200a8302, 0x843982fe, 0x00002234, 0x832f8233, 0x01002348, + 0x538667e6, 0x83010021, 0x33012349, 0xd4638e33, 0x19032806, 0xff840899, 0x83cc2500, 0xe61b254b, 0x1a00ff66, 0x5e05ff43, 0x00220886, 0x8582cccc, + 0x82323321, 0x9a192130, 0xe623a482, 0x828a0868, 0x05b4563d, 0xff21ed82, 0x292083fd, 0x08686600, 0xe6d9ffff, 0xd8829067, 0x8266ef21, 0xb3222247, + 0x200a8232, 0x229382fe, 0x43cc0200, 0x0124079b, 0x8b87cccc, 0x33822882, 0x82054c49, 0x206982e5, 0x342683ff, 0x3233fdff, 0xff078b08, 0xffffbf00, + 0xffff158b, 0xff6866ef, 0x067c41ff, 0x8666e622, 0xfc204c82, 0x7c419f82, 0x25e58206, 0x68e6fdff, 0x4c82888a, 0x9782ff20, 0x82fdff21, 0x8300208a, + 0x067841ab, 0xfd205583, 0x83057841, 0x0e784135, 0x78419a20, 0x82cc2023, 0x057841f2, 0x00ff3422, 0x24053447, 0xffcccc21, 0x05784100, 0xff200a83, + 0x20077841, 0x41c78234, 0x1f820578, 0x201b7841, 0x57784134, 0x78416620, 0xff682205, 0x07784100, 0x41ff3221, 0xf2830d78, 0x088b6622, 0x2b450685, + 0xfeff2105, 0x20057c41, 0x3d0e8332, 0x068b0832, 0x02ffef0e, 0xff989924, 0x9a994c00, 0xd5ffff15, 0xffffcecc, 0xff9a99ac, 0xdd82a9ff, 0x82c6ff21, + 0x9bff27fd, 0x088b3433, 0x12858b28, 0x83390021, 0x82d52040, 0x53002a17, 0xff086666, 0x52780400, 0x2705828e, 0x00ffe13a, 0x8f666603, 0xe6200582, + 0x08281683, 0xff949a19, 0x9a190500, 0x24068e4a, 0xffcd4c03, 0x82148200, 0x82032031, 0x0800225e, 0x21ad83b3, 0x1e8267e6, 0x8234b321, 0x221e83b7, + 0x829a1909, 0x8304201e, 0x3312221e, 0x20558232, 0x200a8313, 0x20048301, 0x826b820a, 0x801a2f5b, 0xe9ffff01, 0x00ffcc4c, 0xff33b316, 0xa383e5ff, + 0x3333fc22, 0xf92be282, 0xff8aa330, 0x0a97f6ff, 0x82feffff, 0xf5ff2430, 0x8289f5a8, 0x78122f4c, 0x7b00ff52, 0x00ff3333, 0xff3e4a6a, 0x30825e00, + 0x807f0024, 0x1a828b00, 0xcc4c8123, 0x2016828b, 0x20f0824c, 0x201683a1, 0x23048212, 0xcdcc84ff, 0xf5234c82, 0x828d9899, 0x9c992c4c, 0x660100ff, + 0xf9ffff66, 0x828c3033, 0x216e8316, 0xc25f0300, 0x23358205, 0x8fcd4ce9, 0x7f218382, 0x204c82ff, 0x27c48200, 0x9a99f5ff, 0xecffff8e, 0x00213182, + 0x224c8305, 0x82cecced, 0x4c02211a, 0xf6222b82, 0xe48266e6, 0x8264e621, 0x20bd8355, 0x225a8203, 0x834cf7ff, 0x6b03201e, 0x052208c0, 0x1e829819, + 0x08243d83, 0x08829c19, 0xc84a5b82, 0x30332405, 0x82fcffff, 0x040031d3, 0x08880080, 0xffff078b, 0xffceccb2, 0x66e62700, 0x279a5345, 0xff343342, + 0x33b36600, 0x212b7c59, 0xd6824c01, 0x21117c59, 0x6e1833fa, 0x7c5907db, 0x75ef201a, 0xf123052e, 0x5b8b6666, 0xf8221c8c, 0x7c596766, 0x19032313, + 0x8c5bff99, 0xe60729ae, 0xff088b67, 0x33b30900, 0x590e8c5b, 0xff2a717c, 0x66e6a800, 0x33fdffff, 0x1b101533, 0x5dc4014c, 0x8b2b1e30, 0xa7feff07, + 0xffff9a99, 0x660080e9, 0xea3107ee, 0xffff0080, 0xff14aef7, 0xce4ccfff, 0xd9f1ffff, 0x28048299, 0xff0866e6, 0x5c0fffff, 0x2105828a, 0x04821f05, + 0x34821920, 0x70fdfe22, 0x33210982, 0x3b1a8232, 0xffe17aed, 0x6666f0ff, 0x07e4ffff, 0x0100ffae, 0xffff3433, 0xff8f42ee, 0xcccc1100, 0x49251e83, + 0x1200ffba, 0x251482b3, 0xfff49dff, 0x3d821e00, 0x60120023, 0x20138200, 0x261e824c, 0xd7a30800, 0x820800ff, 0x1500211e, 0x00217c82, 0x25048306, + 0xff295c14, 0x1e840500, 0x52f80c22, 0xe6275282, 0x0c00ff67, 0x828d9082, 0xf6682129, 0x33220f82, 0x20820833, 0x00222583, 0x5c70cdcc, 0xfbff2105, + 0xff293982, 0xffcc4cfe, 0x9999faff, 0x24dd8208, 0x6666c701, 0x20d98234, 0x229082ff, 0x83990000, 0x646626b4, 0xb30000ff, 0x21048234, 0x04829c19, + 0xbe83b320, 0xccccff22, 0x23820a82, 0x0986ff20, 0xd8823220, 0x4c211384, 0x25be82ce, 0xffd0ccf1, 0xb4820e00, 0xb3f7ff27, 0x3000ff30, 0x201e82b3, + 0x06a56afc, 0x5c841e82, 0x82660521, 0x8204209f, 0x8400207f, 0x82052004, 0xffff2166, 0x8c20a382, 0x20068948, 0x236d8201, 0x66e6ffff, 0x3420b983, + 0xbe821384, 0x30330828, 0xccfeffff, 0x058296cd, 0xff333322, 0x2205be54, 0x826666fe, 0x8315201a, 0x41fa208d, 0xff210713, 0x205983f9, 0x056c4608, + 0x1e82cc20, 0x5f831220, 0x1e82ed20, 0x83ffff21, 0x82e12014, 0xedff2158, 0x0482f883, 0xed209282, 0xee201e83, 0xe4204283, 0x6282a782, 0xffffcc23, + 0x344283ed, 0x089a990f, 0x0e058b8b, 0x54f894f7, 0x8d00ff15, 0xff8b6666, 0x07ec5b00, 0xffff8b22, 0x08200a82, 0x8f200682, 0xb620ec83, 0xa02c5483, + 0xffff3233, 0xff9a999a, 0x68e6ddff, 0x09207882, 0x00265482, 0xffcccc0e, 0x6e820500, 0x84110021, 0x82122040, 0x00ff2855, 0x0766e62e, 0x841800ff, + 0x2b308216, 0xce4c1300, 0x0b00ffa3, 0x08a7cccc, 0x2565324c, 0xff34b30b, 0xa083e4ff, 0x04821220, 0x82e8ff21, 0x180021ba, 0xee29c483, 0xff086666, + 0x34b3d0ff, 0x22db8207, 0x836666ed, 0xffcd23bc, 0x066eeeff, 0xff332505, 0x3433f1ff, 0x9a382082, 0x00ffeb91, 0xff981922, 0x14eeb6ff, 0xcc5f00ff, + 0x00ff8bce, 0x0866e670, 0x8d200682, 0x72203583, 0x72223083, 0x38418699, 0x2a168305, 0x05140000, 0x66b0ffff, 0x6784fb66, 0xd3773290, 0x99af268b, + 0x15e4fb9a, 0x80ab18ff, 0x1c00210a, 0x08d16e18, 0x2d00ff2b, 0x8b076666, 0xb30e00ff, 0x06de5034, 0x66e60b22, 0x8b230e84, 0x82068d08, 0xcc4c2112, + 0x092e1d82, 0xffffcdcc, 0xff9a19f8, 0x00800200, 0x06820880, 0xf3211083, 0x20298266, 0x058a6111, 0xff32b322, 0x8206947c, 0xff962821, 0xcecc0900, + 0x830700ff, 0x820b204a, 0x824a8441, 0x834a8262, 0xf4ff215e, 0xff293483, 0x08cc4cf1, 0x99d2ffff, 0x987f189a, 0xffcc240a, 0x824ce3ff, 0x82dc2004, + 0x8b0822a2, 0xcf021007, 0x76284e01, 0xffffcdcc, 0x1534336b, 0x202d5857, 0x08585799, 0x57ff3321, 0xcd200758, 0x20095857, 0x0f585767, 0x74ff6721, + 0x0520055f, 0x57082757, 0x03580558, 0x078b2434, 0x83a900ff, 0x33e223b7, 0x58851532, 0x4cfaff28, 0xffff8bce, 0x988299f0, 0x34b30a23, 0x0d6a57ff, + 0x8e829920, 0x66e60726, 0xb3fbffff, 0x092dae82, 0x00ff9a99, 0x8bcdcc05, 0xe60800ff, 0x3d6a5767, 0x57824283, 0x6666f622, 0x0d585283, 0x82df2018, + 0xb2fe231f, 0x74439a99, 0xf7cc2ab9, 0xff8b1584, 0xcd4c0d00, 0x26e67eff, 0xffff8b25, 0x4133b3f2, 0xf520069e, 0x0e823782, 0xa27f3420, 0x12427f05, + 0x76ffff2c, 0xfeff0080, 0x153433dd, 0x9d45ffff, 0x459a2027, 0xdd46069d, 0xffa322e1, 0x11d946ff, 0x33330622, 0x3f0fd946, 0xff058b8b, 0x9a192b00, + 0xff159af7, 0x99190700, 0x4c0500ff, 0x0100ffcd, 0xff956766, 0x33b3faff, 0x9a251483, 0xe1ffff08, 0x281a8299, 0xff008028, 0x3433c3ff, 0x230f858b, + 0x0080d7ff, 0x25831a82, 0x2305d972, 0x81156e01, 0x11213082, 0x203a84ec, 0x843b8408, 0x8495200a, 0x825b8651, 0x201a8265, 0x20508311, 0x21508217, + 0x50832300, 0x0f830020, 0x83e8ff21, 0x19818450, 0x27164a52, 0xff666676, 0xcdccdcff, 0x9a18ac82, 0x7d6b0907, 0x29701812, 0x444a1812, 0x124a6b07, + 0x34b31c23, 0x05d96bff, 0x08275483, 0x7dffff7b, 0x46156666, 0x0c471c57, 0x64997197, 0x29a1086c, 0xce4c8900, 0xff5e00ff, 0x844215ff, 0x42002005, + 0x662406d5, 0xfaffff95, 0x27060079, 0xe1ffff08, 0x00ff9a99, 0x210cd542, 0xd542ff9a, 0x07af7508, 0x66660123, 0x09ca4281, 0x2014d542, 0x201f83cc, + 0x201a8299, 0x42508311, 0x50820cd5, 0x2107d542, 0xd542ffcc, 0x26ff2215, 0x221a82cc, 0x4acdccfc, 0x0e265c26, 0xf714f72f, 0xc418159c, 0x9924094f, + 0x19eeffff, 0xe9279e82, 0x088b66e6, 0x19ff065b, 0x820c6a07, 0x00ff2813, 0x089a1916, 0x848b07bb, 0x00ff2408, 0x82f6e811, 0x66e62104, 0x17250e82, + 0xbb088b0a, 0x82178406, 0xe611221d, 0x854a8467, 0x5b08255a, 0x54fb8b07, 0xab2067e4, 0x82056346, 0x209886a6, 0x219d8411, 0x9d8d9a19, 0x9d8e6620, + 0x2782e982, 0x0141fc85, 0x7fcb180e, 0x82002008, 0x26f8854a, 0xf707bb08, 0x8a84fb14, 0x419a20d0, 0x36951038, 0x82083841, 0x414f836d, 0x3841052f, + 0x409a8e0c, 0x0e25d0d0, 0xebe370fb, 0x19284215, 0x42088a41, 0xf722408c, 0x678a8b54, 0x420e5741, 0xbb4109f4, 0x84fb2340, 0x2a4315ab, 0x1701414b, + 0xf784f723, 0x85d04014, 0x430a1721, 0xe82107fb, 0x16fb43f6, 0x8b0a1722, 0xe824c782, 0x075b08f6, 0x92185f44, 0x413694d0, 0x9a842ba1, 0x8666e621, + 0x4316209f, 0x0e2a05f8, 0x34f894f7, 0x70ffff15, 0x8c8266e6, 0xbaa99325, 0x8288ffff, 0xfbff2a23, 0xffffdf6f, 0x089a1977, 0x22a48323, 0x1834b3f2, + 0x25109083, 0x590c00ff, 0x05828b9a, 0xb44a8c20, 0x240a8205, 0x08cc4c0d, 0x212f82f3, 0x2f837200, 0x0a575d2e, 0x195d00ff, 0x7200ff98, 0x088bf6a8, + 0xb3210682, 0x27248234, 0xffcc4c5d, 0x68e6a2ff, 0x8d206e82, 0x5f8a2f82, 0xc74c3482, 0x18478205, 0x210ddf49, 0x3a840a00, 0x46821782, 0x66e6682d, + 0xfbffff07, 0x1cf76666, 0x8293ffff, 0x82002034, 0x2cc185a7, 0x94fb2b08, 0x058b7b15, 0xa8dcffff, 0x206082f6, 0x488282e3, 0x912707c2, 0xffff08ec, + 0x820040c0, 0xdcff299f, 0x00ff7c94, 0xff33b31c, 0xff271c83, 0xcd4c2300, 0x829b088b, 0x11002136, 0x00213683, 0x8336820e, 0x22ad8204, 0x82c2b511, + 0x827f2072, 0x220c8372, 0x74ff02c0, 0x0e2005ab, 0xab74c483, 0x8b642105, 0xee227185, 0x71820a57, 0xf6a8f122, 0xae212282, 0x220a8214, 0x82ae47ee, + 0x19802271, 0x2071839a, 0x843082ee, 0xf1ff2457, 0x84ff68a6, 0x9b082767, 0xfdffffff, 0x7f820570, 0x00213a83, 0x503a821c, 0x6e21072a, 0x21758214, + 0xac83c03f, 0x6b230023, 0x20a78684, 0x28ec821c, 0x34b3dcff, 0xff0e088b, 0x820c1900, 0xb8112208, 0x83728252, 0x510e243c, 0x83ffffec, 0x22778287, + 0x8266e6f0, 0xc2f5215e, 0x840e0b41, 0x94dc22a4, 0x2221827a, 0x83c235d0, 0x91dc2299, 0x110b41ee, 0xa2850620, 0xb284ff20, 0x5c0e0023, 0x21fd8328, + 0x695c34b3, 0x6f002306, 0xb682a4f0, 0x79e64021, 0x3b42059e, 0xd9ae2106, 0x21073b42, 0x3b421470, 0x26808205, 0x0563adfa, 0x42ffff8b, 0xb3202a40, + 0x212e4042, 0x308224fb, 0xe8e9ff23, 0x21fa82f6, 0x0f190a17, 0xf6210893, 0x26ac828b, 0x06cc4c91, 0x18f7ffff, 0x20087ba4, 0x200983f0, 0x05677609, + 0x2083cc20, 0xcdcce122, 0xe8222082, 0xa3823dca, 0xc3b5ea30, 0x4ff0ffff, 0xfbffff5c, 0xffff48a1, 0xee8333e9, 0xeb11fa30, 0x4ae1ffff, 0x1700ff3c, + 0xffff6666, 0x757633e5, 0x2d3b8205, 0x66e62000, 0x1100ff06, 0xff8b52b8, 0x36820f00, 0xb6090026, 0x0800ff04, 0x0e2e0983, 0xff08fc49, 0xf6a86e00, + 0x3000ff06, 0x20829a99, 0x3d822720, 0x04820020, 0x10820a82, 0x24f70822, 0x2305c242, 0xe68800ff, 0xc5425682, 0x04f7240e, 0x421504fc, 0x2f221816, + 0xf1821ec5, 0x66230023, 0x08164267, 0x42ff3321, 0x7b220516, 0x0042058b, 0x05104205, 0xa8f1ff23, 0x23d882f6, 0x08cc4cee, 0x90230682, 0x8205d823, + 0x33ee2206, 0x244e1832, 0x069b2a10, 0x00ffaf0e, 0xf79a198f, 0x22778214, 0x8333b347, 0x5c0f2060, 0x992005a0, 0xcd232d83, 0x830c00ff, 0x1909310e, + 0x01ff0899, 0xff9a1911, 0xb633c900, 0x0700ff05, 0x0522d783, 0xf8827c74, 0x02281483, 0x00ff68f1, 0x8b9a190a, 0x0b22fe82, 0xed826666, 0xdf830a20, + 0x0476fb22, 0xff232085, 0x8244ebf7, 0xcc36271a, 0xc9ffffce, 0x4082703d, 0x98190823, 0x241582ff, 0x0300ff86, 0x22098299, 0x823e0af5, 0x94f422a3, + 0x23b1837a, 0x890ad7f6, 0x41831c82, 0x0080fa22, 0xb3240982, 0xffff0834, 0xfe233c83, 0x8266e6ee, 0x67f620ea, 0xf0200810, 0xf8225183, 0xf882cccc, + 0x2605f75a, 0x066666b7, 0x83e7ffff, 0x99e62236, 0xb3a7189a, 0x198c1809, 0x33cd2713, 0x3200ff33, 0x2586cccc, 0x79190020, 0x182615ce, 0x00ff0180, + 0x77826619, 0x4c5a0137, 0xdc00ffcc, 0xff157c14, 0x34b3e2ff, 0x541d00ff, 0xffff057a, 0x228d8328, 0x820a9761, 0x195525d5, 0xaaffff9a, 0x0021a383, + 0x342b839f, 0x05162ed6, 0xa12dfeff, 0x91feff48, 0xff15b89e, 0xae073f00, 0x252782ca, 0xffd7a346, 0x5382b9ff, 0xffff6c23, 0x208084e1, 0x21b183fb, + 0x3e8299fa, 0x4e83f920, 0x0e83fd20, 0x9999f92b, 0xffff088b, 0x06cd4cbb, 0x6c6918ff, 0x0c15450a, 0x34b30433, 0x00ff8b07, 0xff323307, 0xae870200, + 0x4c0500ff, 0x05cd57ce, 0x8004002a, 0x078b0800, 0x9e01ff0e, 0x01268a82, 0x1566660e, 0x1443ff8c, 0xcc052405, 0x82ffffce, 0x82932067, 0x1000295e, + 0xff064821, 0x00800900, 0x76824683, 0xa0080024, 0x10828a00, 0x0848c12f, 0x91fcffff, 0x2700ffea, 0xffffb81e, 0x2d3382ed, 0x48612300, 0x66e4ffff, + 0x1600ff66, 0x1e82b89e, 0xb89eee25, 0x830e00ff, 0x83f4201e, 0x82162039, 0xfcff29e8, 0x00ff48e1, 0x08b85e19, 0x08214482, 0x202f8241, 0x247e82f9, + 0x00200600, 0x226d8283, 0x82e1efff, 0xf6ff216d, 0xff216d83, 0x254d83f8, 0xff0060f7, 0x42830100, 0x823ef621, 0x04002152, 0xff210f82, 0x214383d8, + 0x3c820112, 0x829edc21, 0xc01b2561, 0xe9ffff00, 0xff2c5282, 0x3e4a1100, 0xe8f1ffff, 0x0b00fff6, 0xff218682, 0x208b83e9, 0x27608203, 0x9a99e6ff, + 0x8b00fb08, 0x2b84e340, 0xff067bd4, 0x5378f6ff, 0xf8ffff8b, 0xff20a082, 0x1921e385, 0x8514829a, 0x821483e3, 0xff9d22e3, 0x21df85ff, 0xdf82cccc, + 0x08486122, 0x4c21df82, 0x21df82ce, 0xdf9466e6, 0xad00ff2c, 0xffff34b3, 0x159a99b1, 0x628274fb, 0x52829120, 0x33530029, 0xff7f0534, 0x824c0800, + 0x82f32043, 0x04003058, 0xffff0080, 0x8b9919f2, 0xd5ffff08, 0x84066666, 0x278a8264, 0xff4861e3, 0x6666e3ff, 0xdc260a82, 0xfb089a99, 0x09830774, + 0xffb89e22, 0x0fad0e19, 0x0614f824, 0x631800ff, 0x0e190973, 0x34200bad, 0x00223382, 0xc9829911, 0x0482f120, 0x820e0021, 0xeeff216f, 0x08245282, + 0x4cfbf4fb, 0x14498218, 0x7b208682, 0xfb228282, 0x6d82b89e, 0x4761fc30, 0x990300ff, 0x00ff8b9a, 0x08666604, 0x4e8304f7, 0x14820982, 0x84b99e21, + 0x24188219, 0x088b4861, 0x2281829b, 0x82676604, 0x222d8227, 0x84fcffff, 0x83fb20b5, 0x070421b5, 0x32b28218, 0xb783688b, 0x81835483, 0x66206887, + 0x6b18689b, 0x84181245, 0x6886181c, 0x82006021, 0x213782cc, 0x04830300, 0x00600422, 0x6b186886, 0xfb201346, 0x68e1d188, 0xf7f4fb24, 0xdb4115cc, + 0x848b2016, 0xffff2417, 0x424761e3, 0xdc240611, 0x088bb89e, 0x20093d42, 0x181b8347, 0x820a7d65, 0x103a421e, 0x74f80e24, 0xc37d54f8, 0x18ff200c, + 0x2a097287, 0xeeffff8b, 0xffff7c54, 0x8234b3f1, 0x84ab2104, 0x4c260e82, 0xfc088bcc, 0xfe180714, 0x44292e18, 0x2b07cb06, 0xfb074b06, 0x3c901844, + 0xe754180c, 0x06bd180f, 0x82072013, 0x7b542174, 0x0852fe18, 0x827c5421, 0xab1123f6, 0x06840884, 0x00ff8625, 0x837b540e, 0x827a2004, 0x85ab2f91, + 0x54f8088b, 0x2b04fc06, 0xf7ffff15, 0x34823333, 0xcdccf827, 0xccf8ffff, 0x250a82cc, 0x083433f7, 0x9818076b, 0x4e181652, 0x00200d06, 0x09f08618, + 0xc618ab20, 0xcd210aba, 0x851883ff, 0x6b08265a, 0x5b04f706, 0x184e9c15, 0x191288cb, 0x21187525, 0xb298066b, 0xbb24f722, 0x3420cf84, 0xcc20cf84, + 0x3420cf97, 0xff221884, 0xed820800, 0xcf850820, 0xfb2380ad, 0x8524fba4, 0x833320d0, 0xe5e618e8, 0x101f410c, 0x838b3321, 0x08cd2169, 0xcc18d086, + 0xd08e13a8, 0xbe82cd20, 0x3333f725, 0x87076b08, 0x0aa041d0, 0x25851c89, 0xd08a8096, 0xcc188093, 0xa0410eda, 0x18cf8408, 0x410c08d1, 0x4ea2101f, + 0x8341cf83, 0x26b2890a, 0xff155b2b, 0x8233d3ff, 0xff2d0842, 0xffcd4cda, 0xcc4ce1ff, 0x99f4ffff, 0xd6ffff9a, 0xff080080, 0x9999fdff, 0x19f3ffff, + 0xffff969a, 0xff9a19f5, 0xcd4c0d00, 0x24f7088b, 0x31098306, 0xff968bcc, 0x66e60a00, 0xb3fcffff, 0x0c00ff34, 0x308266e6, 0x0080f525, 0x822900ff, + 0x824f8204, 0x821e20d3, 0x2b5f8219, 0x0e088b34, 0xbc01ffef, 0x01ff6666, 0x15233182, 0x821600ff, 0xf0ff210a, 0x00227282, 0xde82330d, 0x9a99e627, + 0xe4ffff8b, 0x23428366, 0x07cdcce1, 0xfb200c82, 0x21073c45, 0x2b82fcff, 0x20054145, 0x237882bb, 0x8b686604, 0x4505c949, 0xff240add, 0x33331e00, + 0x002a3582, 0x7600402b, 0x402800ff, 0xee46ff01, 0x99182205, 0x25958298, 0xffae47e8, 0x8b831000, 0xc583f020, 0xb89e1922, 0x1d254282, 0xff084821, + 0x63ae1900, 0x4566200d, 0xff20054b, 0x83537c82, 0x82088305, 0x188182e0, 0x240a8d70, 0x9ebdffff, 0x216d82b8, 0x5783d4ff, 0xed841820, 0x23265783, + 0xffff66e6, 0xc483e6e6, 0xbd820620, 0x194eff2c, 0xffff159a, 0xff9919ba, 0x1a83f4ff, 0x82a6be21, 0x4ce72c1f, 0xc4ffffce, 0xffff0040, 0x82ccccda, + 0x9e532c80, 0xcbffffb9, 0x00ffcccc, 0x5f7b9460, 0x62230613, 0x828bcdcc, 0x8058391a, 0xffff0600, 0xffcd4c8f, 0x00808300, 0xf1ffff05, 0x00ff3333, + 0xffcc4c11, 0x21058c48, 0x4a82cc07, 0x6983e920, 0x8266fc21, 0x66012174, 0x01271982, 0x1548e10f, 0x82faffff, 0x0300230a, 0xbb83b8de, 0x00ff6825, + 0x82482106, 0xde0622f1, 0x82f190b8, 0xa003211c, 0xfb228c82, 0xf19c9899, 0x00c0c122, 0xe920f183, 0x00225282, 0x57821e0a, 0x48a1ea28, 0x801200ff, + 0x52827f00, 0x142e2a22, 0xc034b982, 0x1900ff00, 0xffff3433, 0x8b0080d1, 0xb3cdffff, 0xffff0833, 0x200dcd41, 0x258f8398, 0x0400ff66, 0x13546866, + 0x1dcd4105, 0x9999412b, 0x99dfffff, 0x3c00ff98, 0x205782b3, 0x230482c9, 0x48612400, 0x3f205682, 0xfe23f582, 0x82b81ef7, 0x9edd21ea, 0xff218d82, + 0x20c382e0, 0x209282cb, 0x200984ff, 0x828182fe, 0xe6753097, 0x76ffff66, 0xff059a99, 0xce0c0c00, 0x83f1ffff, 0xcc1125a2, 0xf7ffffcc, 0x00241982, + 0x8b34b312, 0x582b2582, 0xff064661, 0x9a198aff, 0x838900ff, 0xf3ff232b, 0xbf4cecd1, 0x33ee2206, 0x06554c34, 0xcc4ced22, 0xff2b2b83, 0x158b9a19, + 0xff064cfb, 0x82197500, 0x667623cc, 0x06820566, 0x9883f120, 0xd0cc1122, 0x30205788, 0x11222b83, 0x27826866, 0x09a88118, 0x0ad46718, 0x2005bb47, + 0x505d820d, 0x0a20058e, 0x089b6218, 0x20626476, 0x29fb821f, 0x34b3d3ff, 0xf2ffff15, 0x604dcecc, 0xeeff2605, 0x00ff32b3, 0x20198304, 0x05dd4cee, + 0x22050749, 0x6fcdccfc, 0xff2005fa, 0x0982f982, 0x08666626, 0xfbffff8a, 0x2805236a, 0xfcffff99, 0x00ffcc4c, 0x82c78303, 0x8b08291f, 0x00ff058b, + 0x8a333300, 0x80260683, 0xffffff00, 0x0a8334b3, 0x20054474, 0x830a8332, 0x84ff204f, 0x3333213e, 0x39821f82, 0x66010023, 0x2b098267, 0xff089a19, + 0xcccc0200, 0x33feffff, 0x03208a82, 0x4c217884, 0x05a949ce, 0x20054f7f, 0x20148400, 0x21a482fc, 0x52830300, 0x0482fd20, 0x83020021, 0xb3fb2267, + 0x203d8234, 0x21578201, 0x9183fdff, 0x23820120, 0xce219b82, 0x22b2828b, 0x8508cccc, 0x21598206, 0x10829a19, 0xff217382, 0x213a82fe, 0xcd82fcff, + 0xfc20dd86, 0x04853a83, 0x8206df6a, 0x66e622db, 0x05af4208, 0x09827e83, 0xfd21b183, 0x06656d4c, 0x1e82a683, 0x9999fe22, 0x5c82bc84, 0x5c83da84, + 0xda84ff20, 0xd0829920, 0x84ffff21, 0x989922db, 0x20248205, 0x21f083b3, 0x0a83cecc, 0xe6242a84, 0x8b8b0566, 0xfd200d82, 0xfe207183, 0x7705f164, + 0x19210902, 0x18b6849a, 0x84088b57, 0x22ec84d7, 0x410080ff, 0x6e840d69, 0x0021f182, 0x05c66e00, 0x00ffce23, 0x06724100, 0x0a820820, 0x204b7241, + 0x41a682fc, 0xfc200572, 0xff218582, 0x14724100, 0x32b3fe22, 0xfc20bb83, 0xff219282, 0x717241fe, 0xff23a282, 0x4132b3ff, 0x09820971, 0x82cdcc21, + 0x66e62204, 0x250a8508, 0xcccc0000, 0x0b828b05, 0x059a1925, 0x42fcffff, 0x34250574, 0x66feffff, 0x220e8267, 0x828ccc4c, 0x20de8405, 0x82c28300, + 0x00ff24e9, 0x83333303, 0x8266201f, 0x9a992109, 0x3005dd43, 0x00ff8b66, 0x8fce4c11, 0x330d00ff, 0x0700ff32, 0x215e8266, 0x7d820600, 0x18030021, + 0x2d080559, 0xff008004, 0xce4c0400, 0x330500ff, 0x0a820834, 0x05222983, 0x46829819, 0xff9a1926, 0xce4c0600, 0x07254482, 0x8b08cccc, 0x82738291, + 0x2312836d, 0xccfbffff, 0x19213183, 0x20af8298, 0x83c982fb, 0xffff223c, 0x253183fa, 0xff666605, 0x0482f9ff, 0xcc020023, 0x201e82ce, 0x255b83fd, + 0xff989901, 0x5583fdff, 0x68660122, 0x68254783, 0x330200ff, 0x206f8232, 0x20148303, 0x202e8400, 0x831482e6, 0x0200211e, 0x32825183, 0xaded1e82, + 0x058b8b2b, 0x8090ffff, 0x7c00ff00, 0xa94b104c, 0x05102001, 0x267d04a5, 0xff9a99c2, 0x10b34400, 0xd703b84d, 0xcd01ff3d, 0x00ffcccc, 0x15666671, + 0x4cf2ffff, 0x2100ffce, 0xffffcecc, 0xff6666db, 0x50801400, 0xff2d059b, 0x9899f5ff, 0xd7ffff08, 0xffff68e6, 0x391e83f4, 0xff3233ea, 0x9a19d6ff, + 0xff086495, 0x66e61600, 0xb3a6ffff, 0xff8d0532, 0x3783f8ff, 0x9a990325, 0x83f9ffff, 0x8304204b, 0x99fa222c, 0x273c829a, 0x7e6666e1, 0x4cdeffff, + 0x2505fb53, 0x99dcffff, 0x16828b9a, 0x06827220, 0x6fffff21, 0x8b2207a8, 0x0a8200ff, 0x6a0fba6f, 0xe226211c, 0xffff34b3, 0x768219fb, 0x8c83e320, + 0x0483f620, 0x32b3e522, 0xf4205f82, 0x00210a82, 0x26908305, 0x8c9a99f3, 0x83f3ffff, 0x4dfe2080, 0xff290637, 0xff34335a, 0x9a990200, 0x20788215, + 0x21298206, 0x784bfcff, 0x5b3a4f32, 0x4f6ad04d, 0xd04da343, 0xffff2121, 0x4f484c4f, 0x052a0642, 0x990000ff, 0xffffff99, 0xb6509899, 0x24434f4f, + 0xb650fd20, 0x2b72417d, 0x013f0f10, 0xffff2b32, 0x079a19ff, 0x6688ffff, 0x656ae766, 0x00ff295c, 0xff3433d9, 0x33330300, 0x28a3796b, 0xcccc2d00, + 0x8077ffff, 0x2bac8201, 0xff9a1914, 0x32b30500, 0x1600ff05, 0x0620c283, 0x162e0483, 0xffff66e6, 0x913233f2, 0xcce8ffff, 0x208208ce, 0xe8221083, + 0x158232b3, 0xe8203a83, 0xff263482, 0xffcecce9, 0x1e82f9ff, 0x25823620, 0x40823320, 0x66f7ff22, 0xfd253682, 0xffff9a99, 0x825584f7, 0xfdff2104, + 0x00273482, 0x0832b308, 0x82e9ffff, 0x5900240f, 0x5105ce4c, 0x17250663, 0x00ffcc4c, 0x206f830d, 0x825e8217, 0xff32227e, 0x827e8200, 0x4c16226e, + 0x820a84ce, 0x82cc2093, 0x828982a9, 0x863d8282, 0x4c06238d, 0x4c1876cc, 0xf7366126, 0x1544fb94, 0x194c00ff, 0x00ff8b9a, 0xbd9a1940, 0x4300ff9e, + 0x9e8266e6, 0xae830320, 0x34b30d25, 0x83f4ffff, 0x830c20dd, 0xccf130f6, 0xff088bce, 0xccccecfe, 0xf1ffff06, 0x828bcccc, 0x52b8301c, 0x99f3ffff, + 0x0300ff9a, 0xffff0bd7, 0x82cc4cf2, 0x0a13253b, 0xbcffff3e, 0x5282cb82, 0x85599921, 0x8b08295e, 0xb0ffff07, 0xa4f76666, 0x01575d10, 0x6e91411d, + 0x0080e228, 0x66d800ff, 0x5b101566, 0x252c0155, 0x0a00ff66, 0xbe439919, 0x5b082006, 0x06830561, 0xff251685, 0xffccccf9, 0x270f8200, 0x19f9ffff, + 0x00ff089a, 0x01555b10, 0xff6625e0, 0x9a190a00, 0x18080f42, 0x2511555b, 0x0800ffcc, 0x0f42cecc, 0x555b1809, 0x04551867, 0x6ead445f, 0x00808527, + 0x4c3d01ff, 0x305218cc, 0x29d77a64, 0xff8b3226, 0x68660f00, 0x1816d77a, 0x7a383052, 0x982305c5, 0x7a0a00ff, 0xce2a05c5, 0x5900ff08, 0xffff66e6, + 0xc57a19d0, 0x5e072059, 0x33426035, 0x6173486e, 0xad478b19, 0x02ffef30, 0x8b34331d, 0x0000ff15, 0x8d8664e6, 0xe819ffff, 0xff241062, 0xff0080ea, + 0xe5300485, 0x088b6866, 0x80e5ffff, 0xffff8b00, 0xff9a99ea, 0x0af9c318, 0x00ff8b23, 0x21118305, 0x16821901, 0x66660522, 0x662b5083, 0x59fb0890, + 0x0100ff06, 0x8286cccc, 0x9d198205, 0x8957825e, 0xedd8185e, 0x825e910d, 0x82902054, 0x19bd292d, 0xff058b9a, 0x6666eeff, 0xf1259382, 0x00ff9999, + 0x270a830e, 0x9a991100, 0x07e4f708, 0x08253782, 0xffff0ad7, 0x2c0482f8, 0xf6280700, 0x28f7ffff, 0x7b088bf6, 0x82328906, 0x823289af, 0x8439822f, + 0x82048644, 0x088b220e, 0x22c582ab, 0x82333323, 0xcc1c241d, 0x18ffffcd, 0x230ad1ae, 0x74f807d4, 0x11221c82, 0x1c829899, 0x68660e22, 0x8405c46d, + 0x8208205d, 0x83978291, 0x84982011, 0x27158316, 0xff088b68, 0x3433bdff, 0x9228b483, 0x54f8cccc, 0x1a00ff15, 0xff22f882, 0xf1821500, 0x0a11dc18, + 0x07a4fb27, 0xf70654fb, 0x82c283a4, 0x841f8520, 0x322f8424, 0x2b06eb08, 0x06eb152b, 0x062b07bb, 0xfb3b075b, 0x976b1574, 0x6af720d3, 0x002008f0, + 0xd68de882, 0x0774fb28, 0x54f7d4f7, 0x2383fb15, 0xad93ff20, 0xf7066b24, 0xff830774, 0x2308e294, 0x01ffaf0e, 0xff343311, 0x66e68800, 0xdfffff15, + 0x00ff66e6, 0x41343327, 0x4c6100ff, 0x00ff8bcc, 0x089a9936, 0x42220682, 0x0b831e45, 0x00ff9931, 0xffe2ba35, 0x67664100, 0x00ff088b, 0x82323343, + 0xb3352d1b, 0xcaffff34, 0xff8b1e45, 0xe2babdff, 0xff262d82, 0xff6666c9, 0x4a82b6ff, 0x839eff21, 0x2f54831b, 0xccccd8ff, 0xf8ffff08, 0xffffce4c, + 0xff0080f5, 0x8306704c, 0x0a00360f, 0x8b080080, 0x8e00ff07, 0xffffcccc, 0x159a1940, 0x992e01ff, 0x2010829a, 0x21288203, 0x47820600, 0x83030021, + 0x820620a2, 0x0200211f, 0x06220e83, 0x831868e6, 0x012a0783, 0x00ff3233, 0xff008000, 0x23830100, 0x4c200985, 0x00316b82, 0xfffeff73, 0x66662e00, + 0x0f00ff05, 0x00ffd0cc, 0x317b8206, 0x98191100, 0x66f4ffff, 0x087a8b66, 0x33f1feff, 0xb5820734, 0x3233f626, 0xf7ffff85, 0xff263e82, 0xff68e6f6, + 0x3e83fcff, 0x836fff21, 0x19c63429, 0xfeff059a, 0xff0a176f, 0x34b33b01, 0x7a00ff15, 0x82bc9082, 0x4d022050, 0xcc210540, 0x051963ff, 0x9483f120, + 0x84820520, 0xccf2ff23, 0x259982ce, 0xff67e602, 0x4082f9ff, 0x20051d60, 0x215a82f9, 0x1e830300, 0x9a19f926, 0x04ffff08, 0x2508dd83, 0xf6e880ff, + 0x19cdffff, 0xffff0598, 0xff713df0, 0x9a99faff, 0xd9eeffff, 0x0a00ff9a, 0x9c8b34b3, 0x0e01ff08, 0x9f82cccc, 0xcc090027, 0x0500ffcd, 0x2a1882f9, + 0xff33b309, 0x711d0900, 0x820200ff, 0x068b2d67, 0xe87001ff, 0x15d1fbf6, 0x193fffff, 0x36211e82, 0x26ec83e6, 0x076666c2, 0x831500ff, 0xb3e022a1, + 0x82098234, 0xe3ff263e, 0x00ff32b3, 0x2ca6820d, 0x0080efff, 0x1400ff08, 0xffff0180, 0x249282e5, 0x98992600, 0x05db558b, 0x841a0021, 0xe60d251a, + 0x1000ff68, 0x15211a83, 0x22e082cc, 0x86ce4c1c, 0x711f201e, 0x062c05cb, 0x0e0534b3, 0xf72cf8af, 0xff8b15dc, 0x4233eb41, 0x25420966, 0x126a4205, + 0xe8833520, 0xe2ba3528, 0x4c4200ff, 0xaf828bcd, 0xcc4c4222, 0x22116a42, 0x776b0cfb, 0x0b7a0c79, 0x272c820a, 0xff0a1716, 0x9a19eeff, 0x23057476, + 0x66e6e9ff, 0x06844882, 0x41191685, 0x1e820deb, 0xe6212882, 0x231b8566, 0x9a191600, 0x00282d82, 0xff9a9989, 0x3433e4ff, 0x59426682, 0x616d4205, + 0x2424fb42, 0xccccecfe, 0x4294828b, 0xf6426568, 0x068b2b25, 0x66b100ff, 0x68ffff66, 0x9a8232b3, 0x291c4642, 0xb306ffff, 0x54fb0734, 0xb34200ff, + 0x8014240b, 0x42ffff00, 0x290832b3, 0x0e058b8b, 0x19e001ff, 0x1f01ff9a, 0xff1566e6, 0x32335cff, 0x665affff, 0xffff0566, 0xff01007e, 0x01008200, + 0x7300ff05, 0x0482cdcc, 0x0533b328, 0x0d00ff7d, 0x1c820a17, 0x7082f720, 0x5e090025, 0x18ffffb8, 0x250b22cc, 0xff0848a1, 0x4d82a9ff, 0xcfaaff23, + 0x2325865c, 0xceccf5ff, 0x0023258b, 0x8232330a, 0xb3f63125, 0x0800ff33, 0xff8b0080, 0x34330f00, 0x4c0900ff, 0x09266282, 0xff086666, 0x40825600, + 0x07560023, 0x0c8f18ae, 0xf41d2108, 0x0d0c8f18, 0x820ce221, 0x820d2025, 0xf2ff2525, 0x9a05f6e8, 0x2c844182, 0x66e62333, 0xe12300ff, 0x3a00ff06, + 0xae8b3433, 0x1edcffff, 0x202882fa, 0x087f8324, 0xb81edc21, 0xc5ffff8b, 0xffff5ccf, 0x683233db, 0xff078b08, 0x666605ff, 0x9903ffff, 0x5b5b159a, + 0x82c2ffff, 0xdfff26e2, 0xffffcc4c, 0x221683bd, 0x8234b3f2, 0x02e723a4, 0xc682868f, 0x4821f83b, 0x66feffff, 0xf7ffff68, 0x00ff29dc, 0xfffe7f02, + 0x7b54faff, 0x800600ff, 0x25258200, 0xff7553fa, 0x65830400, 0x7989fd22, 0x192bd482, 0x0100ff98, 0x00ffbd92, 0x8268e607, 0xff04237f, 0xca82a4b1, + 0xa4500d26, 0x994200ff, 0x20251b82, 0x00ff71bd, 0x23f4833d, 0xbb1f0530, 0x40272182, 0x00fff628, 0x82333340, 0x00822725, 0x7effff01, 0x75820100, + 0x82ccbf21, 0x2804828c, 0x00ff0e05, 0xff33b3df, 0x28328201, 0xb5ffff15, 0x00ff6766, 0x20f0827b, 0x24748289, 0xffff2cd2, 0x232782fa, 0xf2f20200, + 0x66220982, 0x8f828b67, 0xe1ba8728, 0xf3ffff06, 0xf182cd0c, 0x856bf827, 0x6bf1ffff, 0x208c8286, 0x223c826e, 0x826666f5, 0x4c6f276f, 0x61ffffcd, + 0x6f829a19, 0x85ab1d32, 0xae1b00ff, 0x2500ff14, 0x00ffcdcc, 0xb59a1913, 0x0021d686, 0x22258320, 0x82cccce2, 0xc09e2236, 0x244b8200, 0xff0040b1, + 0x820482ff, 0x2010820a, 0x22068508, 0x824e00ff, 0x24168338, 0x336100ff, 0x827f8233, 0x8b342106, 0xcc201683, 0x38830482, 0x40610023, 0x832d8200, + 0x203f8206, 0x2216854c, 0x6a9effff, 0x5c21052a, 0x22558280, 0x8234b362, 0x1eda2366, 0x938266b8, 0x82e00821, 0xc0cb2211, 0x210a8200, 0x0a82a001, + 0x83c0f621, 0x82202004, 0x83f82004, 0x9ef72c09, 0x0400ffb8, 0xff080080, 0x821ed1ff, 0x9e18230a, 0x0a8205b8, 0xff721d26, 0x146ee7ff, 0xf7200a82, + 0xfb203483, 0xf6205683, 0x00213482, 0x21b68207, 0x34830100, 0x87820920, 0x8300ff21, 0x3400225e, 0x205e8240, 0x207082ff, 0x223082b0, 0x829022f9, + 0x66a625f4, 0xe60300ff, 0x0b260482, 0x00ff9a99, 0x09826609, 0x6666012c, 0x3400ff08, 0x00ff4861, 0x3082a007, 0x6b17002a, 0x2f00ff85, 0x8d059a79, + 0x57838282, 0x61830420, 0x04830220, 0xfc830982, 0x01200425, 0x8200ff8b, 0xffff2a0c, 0x8d33d3fd, 0xccfbffff, 0x204382cd, 0x218e8317, 0x438380d0, + 0xff224e83, 0x0a8360f8, 0x1e850925, 0x82feffff, 0x030026ae, 0xffffcccc, 0x287382f4, 0x9a19f9ff, 0x4cf9ffff, 0x203482ce, 0x4d888292, 0x882906e6, + 0xff069a99, 0x0661faff, 0x2105828b, 0x5c8280ca, 0x820e0d21, 0x281c2104, 0x2d2e6082, 0xffff08d4, 0xff703db6, 0x66e685ff, 0x3d82b505, 0x00266c82, + 0xff48e125, 0x0482ecff, 0x9e1d0028, 0xe4ffffb8, 0x5182703d, 0xce4c6f25, 0x829e00ff, 0x21d08225, 0xe582e07a, 0x5c20c521, 0x0e29066a, 0xffff7a94, + 0x8b3433f2, 0x4d591808, 0xb0fe2462, 0x10db6666, 0x1e01ff14, 0x04fb5422, 0x7217b872, 0x86181667, 0xfa2535df, 0x00ff3333, 0x05f954ca, 0xff9a9929, + 0xceccfaff, 0x820200ff, 0xf9ff2314, 0x698232b3, 0x9a19f923, 0x22068208, 0x7dcd4cee, 0xff250545, 0xff33b3f1, 0x210e82ff, 0x0f19088b, 0x00220b7a, + 0x85184c0e, 0x06220a38, 0x448566e6, 0x20053b4a, 0x23588203, 0x32330500, 0xe9263182, 0xff8133b3, 0xf14bf0ff, 0x225f850a, 0x7c34b3dc, 0xe37d10d0, + 0x18168505, 0x200d2bb7, 0x845f821a, 0x15002144, 0x54824983, 0xff08952b, 0xcdcca500, 0x9985ffff, 0x3a47189a, 0x8b34210f, 0xcc204983, 0x0020c682, + 0x34203890, 0x03223883, 0xf8889899, 0x94ff3421, 0x861682f8, 0xb77218f8, 0x82f8940e, 0x6d0620cb, 0x98210568, 0x20f888ff, 0x82f89b34, 0x4ce3225f, + 0x2ea784cc, 0xfb0e088b, 0xb400ff30, 0x01ff33b3, 0x826250bb, 0x33062bcd, 0x0600ff33, 0x00ff7e3f, 0xcc83330a, 0xff230f83, 0x8282c0f9, 0xff4f21f3, + 0xaf240082, 0xff05fafe, 0x3105436c, 0xff707dfd, 0x9a990100, 0xb8fcffff, 0x0000ff52, 0x09820080, 0x82c47521, 0x33283829, 0xbefeff34, 0xff051e05, + 0xaec7effe, 0x2800ff06, 0x01ff713d, 0x82e2fa41, 0x7300213a, 0x03226082, 0x3a853c8a, 0x47030023, 0x068f7aae, 0x90820236, 0x00ffdb08, 0x05060150, + 0x4ce3ffff, 0xf4feffcd, 0xff159eaf, 0x0a538a18, 0x4cf5ff23, 0x052b7ecc, 0x06850820, 0x083c8a18, 0x0d25cd82, 0x088bcd4c, 0x836b82db, 0x20188508, + 0x15401800, 0xe2c41809, 0x83cd2009, 0x8534201b, 0x3b082656, 0xfb5cf706, 0x0e867644, 0x8718b320, 0xcc210cc4, 0x068676ff, 0x2108157e, 0x4c76d4fb, + 0xd4f72d2e, 0x01ff0e06, 0xff0080f5, 0x48218301, 0x40296d83, 0x1100ff00, 0xffffb81e, 0x250983fb, 0xff48211d, 0x0983eaff, 0x48e10a29, 0xf3ffff08, + 0x829148e1, 0x829e2075, 0xc0fe251f, 0xf5ffff00, 0xf7222983, 0x1a8200e0, 0xe23a3438, 0x0368ffff, 0x00ff05d6, 0x06666697, 0x6200ffee, 0xff05e23a, + 0x5c82faff, 0xc57dff29, 0x74fc151e, 0x18ffff06, 0x1809399d, 0x760ac3ab, 0x20200583, 0x07207982, 0x18830482, 0x0800ff36, 0x088b00e0, 0x190f00ff, + 0xffffff9a, 0x8b059a19, 0x3200ff3a, 0xff278882, 0xff66e6ba, 0x82d94600, 0xb3e32316, 0x92820834, 0xef261483, 0xff82b81e, 0xad83ecff, 0x9783fc20, + 0xb81eea22, 0xff211a82, 0x20258299, 0x291482f6, 0x66660700, 0xe6f6ffff, 0x53839566, 0x0180df2d, 0xff8b9506, 0x90820700, 0x830900ff, 0x82fe2071, + 0x090021d0, 0x3e83c684, 0xe1150028, 0x00ff8248, 0xe682de13, 0x5e82f320, 0x83100021, 0x460034fc, 0x00ff50f8, 0xff1e451c, 0xce4c3100, 0x194500ff, + 0x82dc8b9a, 0x831020a2, 0xe6002190, 0x8306b447, 0x18528257, 0x260cc9ea, 0xffff938b, 0x8266e6f8, 0x82f72005, 0x0e082533, 0x1514f88b, 0x23222782, + 0x4f829a59, 0x1d19a620, 0xf7210c71, 0x8f3719b4, 0x93d01817, 0xfa50180b, 0x82fb200c, 0x44d41832, 0x07cb2515, 0xb4fb34f7, 0x11276a83, 0x00ff34b3, + 0x83cd4c0e, 0xffcc2904, 0x33b31100, 0x079b088b, 0x2c218382, 0x21188233, 0x1882cc23, 0x82cc2321, 0x332c2118, 0xf7211882, 0x82838224, 0x211e8231, + 0x14824c0e, 0x2809d444, 0x8a7a00ff, 0x00ff073e, 0x26168225, 0xead1f2ff, 0x821a00ff, 0xdcff2758, 0xff8ba470, 0x4d78d6ff, 0x60562805, 0x088b5660, + 0x760624fb, 0xcc200e1c, 0x2105b045, 0x29797b08, 0x14fb2117, 0x178cd018, 0x4b824b20, 0x09fd8a18, 0x080a2279, 0x0714f735, 0x00ff2f0e, 0xf79a9981, + 0x00ff1584, 0xff004005, 0x00c0e0ff, 0x5e1400ff, 0xe6ffffb8, 0x00ffb81e, 0xff48a11b, 0x00c0f2ff, 0xf8ffff08, 0x00ff3373, 0x18e2fa12, 0x211291de, + 0x3e82ab8b, 0x48212722, 0x012ff882, 0x90a60080, 0x611800ff, 0x0700ff48, 0x829eb89e, 0x82e42038, 0xf2ff2638, 0xffff52b8, 0x54e018eb, 0x665e2713, + 0x91ffff66, 0x42823433, 0xcdcc0722, 0x802a3582, 0x00ff9800, 0xffffff1a, 0x2f820200, 0x4c2c0023, 0x224482cd, 0x829a19d1, 0x1802205d, 0x2719e4e0, + 0xff9a1929, 0x3233b500, 0xb3234683, 0x18907832, 0x830e67e1, 0xfaff289c, 0x00ff86ab, 0x8234331f, 0x32b32589, 0xe61900ff, 0xe42b7982, 0x00ffce4c, + 0x08cc4c0d, 0x827600ff, 0x6900260f, 0xfb159a99, 0x98c218d4, 0xff9a230a, 0xd818e3ff, 0xfc260848, 0xff8b0714, 0x7542dcff, 0x22198307, 0x822300ff, + 0xf708211e, 0xc1183382, 0xf8201583, 0x1a833383, 0x7b824882, 0xcc1c0023, 0x264282cc, 0x088bcccc, 0x7d34fc5b, 0xf72205c6, 0x5682cd4c, 0x33b3f822, + 0x14e76919, 0x84cd4c21, 0x00ff2816, 0x8b33b308, 0x1874f708, 0x230c29d5, 0x00c0f8ff, 0x0950af19, 0x0040f725, 0x83f8ffff, 0x05e74a60, 0x8b34332b, + 0xeb04fb08, 0xb9ffff15, 0x25268340, 0xff00c0c6, 0x0a833900, 0xe0180020, 0x36820cc0, 0xff201683, 0x8b211583, 0x1ce11808, 0x835f831f, 0xb9ff2149, + 0xff245f83, 0x9a192900, 0x992a0482, 0x00ff159a, 0xffb89e1b, 0x4e830d00, 0x48611426, 0xe11900ff, 0x05200482, 0x1f340e83, 0xff080040, 0xb8ded8ff, + 0xfeffff06, 0xffff7a94, 0x861e05e5, 0x2605a441, 0xce4cf8ff, 0x18ff0878, 0x330a88e2, 0x48e12e00, 0xfdffff06, 0x00ff5138, 0xff34332c, 0x9a19f3ff, + 0x0c79e318, 0xcd203282, 0x7320e882, 0xf2231a82, 0x827066e6, 0x6766332a, 0xccd3ffff, 0xff0e08cc, 0x00807501, 0xe3a401ff, 0x958215d8, 0x98391131, + 0xb31500ff, 0x0900ff34, 0x00ff90e2, 0x83cccc16, 0x992b34de, 0x00ff8b9a, 0xff666623, 0xd8a3dcff, 0xd4ffff8b, 0x82084661, 0x2ee92506, 0xf6ffff16, + 0xff38cd82, 0xffcc4cea, 0xcccceeff, 0xffff087c, 0xffcecc30, 0x00804bff, 0xaaffff05, 0x00273282, 0x0533b354, 0x83b500ff, 0x30cf220a, 0x2c1582a5, + 0xff9a9989, 0xf468c5fe, 0xecffff15, 0x243782cc, 0x059a99ac, 0x2a3e8287, 0xff7e66e6, 0x6866f2ff, 0x83efffff, 0x4cfb2253, 0x274d82cc, 0xff9a594e, + 0x3433ceff, 0x5f204282, 0x00230a82, 0x8266665f, 0x8202200a, 0xffff21a2, 0x00267482, 0xff33b302, 0x5182ffff, 0xe6020023, 0x19ac8367, 0x220afa18, + 0x82cc4c0e, 0xb31122b7, 0x18ac8234, 0x2007e3cc, 0x5ee91833, 0x49cd2008, 0xff200d4e, 0x0c327f18, 0x8182fd20, 0x61000026, 0xfdffff48, 0x00206583, + 0xfd226f83, 0x9082ce4c, 0xdda4a027, 0xb3a0ffff, 0x25858232, 0xfffabe31, 0xe983b200, 0xbd040039, 0x00ff9b71, 0x980b970d, 0x191100ff, 0xff088f9a, + 0x67665300, 0x841300ff, 0xcc5439b9, 0xabffffcd, 0x0e053233, 0x667001ff, 0xad01ff66, 0xff15f6a8, 0x66e61500, 0xdd260482, 0x2300ffb2, 0xd9186866, + 0xea220768, 0x3c824e22, 0x7f822e20, 0xf0d1ff23, 0x2d6582a4, 0xffcccc15, 0x4821eaff, 0xdcffff8b, 0x0a82ea91, 0x82343321, 0x9a192104, 0xc8328b82, + 0xffff3233, 0x05cd4cc8, 0xcc82ffff, 0x7d00ffce, 0x3082713d, 0x32b3373f, 0xb83700ff, 0xffbc0552, 0x0a5732ff, 0xffff5d15, 0x0534b366, 0xecffff85, + 0xffff9819, 0x212982f0, 0x4483f0ff, 0xda82ec20, 0x66f9ff2e, 0xfeff0866, 0xff84abf7, 0x6666a7ff, 0xf4254982, 0xfffff6a8, 0x221f83fc, 0x76707df3, + 0xf72506cd, 0x00ff856b, 0x28ff8308, 0x5c8f9900, 0x999900ff, 0x2768829a, 0x88cd4c06, 0xfeffff92, 0x00244682, 0x8b008006, 0x1b22b782, 0xc8826666, + 0xaf571420, 0x801a2510, 0xebffff00, 0x7119fa82, 0xff220a27, 0x2d83e6ff, 0x82e9ff21, 0x0a8c562d, 0xf820e782, 0x002a1182, 0x84999902, 0xf9ffff8e, + 0xe98232b3, 0x82686621, 0x66662294, 0x229f8268, 0x82f2b2f7, 0x8299208b, 0x26fd25c9, 0x0c00ffa8, 0x00285982, 0xff14ce03, 0x68660b00, 0x58278182, + 0x01ff00a0, 0x82cc4c08, 0xb5052a9f, 0x1300ffc3, 0x00ff34b3, 0x22048310, 0x8232330f, 0x66e6220e, 0x23258291, 0xb9676698, 0x82202182, 0xff21ba82, + 0x23cc827e, 0xec01ff0e, 0x012a2382, 0x15004095, 0xe7ffffa4, 0x86829002, 0xa470d724, 0x7c827272, 0x6c83c720, 0x05270482, 0x00ff06fb, 0x82e2fa71, + 0x66383438, 0x3800ff68, 0xa4056666, 0xff1800ff, 0x2800ff7e, 0x838b9899, 0x82002138, 0x17205d82, 0xff341d82, 0x05ec91e8, 0x3040feff, 0xc9feffa4, + 0xff15cc8c, 0x5dcffe00, 0xdc290482, 0x06f7052a, 0x0a8effff, 0x27cb823d, 0xff991901, 0x333301ff, 0xf9220a82, 0xec82cd4c, 0xffce4c2a, 0x33b3f7ff, + 0x19fbffff, 0xf621e082, 0x421382cc, 0x97250576, 0xffff70fd, 0x32d683e2, 0xb89ef7ff, 0x99fdffff, 0xf6ffff9a, 0x00ffe1fa, 0x82666602, 0x0ad72338, + 0x06820892, 0xff3fd624, 0x44830500, 0xc1a9fd23, 0x261b8294, 0x00ffea64, 0x82666608, 0xb91d2393, 0xb882f3ce, 0x299c022c, 0x330900ff, 0x0400ff32, + 0x1b8267e6, 0x00222b82, 0x4682ba06, 0x32b30622, 0xcc2c2582, 0x00ff8f82, 0x15ceccf9, 0x26fb26fb, 0xa8279582, 0x00ff9999, 0x82008057, 0x41ed270a, + 0x1200ff48, 0x131932b3, 0xb8200910, 0xbd210f82, 0x24358270, 0xff5c0f4e, 0x82048200, 0xbd12225f, 0x20158271, 0x221a82be, 0x8266661e, 0x8312202a, + 0x823a82cc, 0x83132025, 0x3dec22cd, 0x08467870, 0x43c4b521, 0xff2305ba, 0x82a4b0ff, 0x28298309, 0x0884abff, 0xbfffff4b, 0x202583fd, 0x821183f9, + 0x04c1188c, 0x82cd2009, 0xcecc21e2, 0x06214b82, 0x05354c33, 0x9f4bff20, 0x0600280a, 0xcb08ce4c, 0x833f00ff, 0x0000283c, 0x00ffcd4c, 0x82ec5100, + 0x00802158, 0x57250982, 0x0100ff0a, 0x2dcd8219, 0x089a5900, 0x332d00ff, 0xd2ffff33, 0xb28266e6, 0xce4ccc28, 0x9933ffff, 0x2a82159a, 0x8232b321, + 0xcccc2104, 0x41689787, 0x84342005, 0x4b082218, 0x20b9824b, 0x8c2183f9, 0x06a76593, 0x0600ff24, 0x9e823233, 0x93881f82, 0x14823220, 0xcb209383, + 0x00206582, 0x00216582, 0x20228301, 0x208f82ff, 0x820483ff, 0x829a208f, 0x22218299, 0x831300ff, 0x33ec2274, 0x27298232, 0xff34b312, 0xce4cedff, + 0xe122f682, 0x0a839899, 0x0f828f82, 0xffff0825, 0x8466e6b1, 0x82888204, 0x821a8610, 0x832a8224, 0x8200200f, 0x2025823a, 0x286082a8, 0x66665700, + 0xf726f705, 0x22508226, 0x829a192d, 0xcecc24eb, 0x82ef0e05, 0xb840256e, 0x191901ff, 0xca26ed84, 0x6200ff30, 0x4d82f6e8, 0x6bfaff31, 0x400a00ff, + 0x0900ff00, 0x00ffb97c, 0x8248a107, 0x8300310e, 0xc5fdffff, 0x00ff081e, 0xff5c8f23, 0x9a19f8ff, 0x0a204c82, 0xfd270a83, 0x00fff4a8, 0x82f6a808, + 0x54782b14, 0xcc0300ff, 0xf5ffffcd, 0x2982b8de, 0x90021127, 0x23d1ffff, 0x212982d6, 0xc7823380, 0x0080d922, 0xd6205e82, 0x91229183, 0x0a823433, + 0x9919fd22, 0x38215a82, 0x82648252, 0x0a0023e7, 0x0e82d22d, 0x8b999922, 0x28293b82, 0xff069a19, 0x00800b00, 0x2912828b, 0xffff33b3, 0xffd8c3f9, + 0x26820500, 0xedf5ff2b, 0x01f7080e, 0x1c3effff, 0x25598229, 0xffcc4c6b, 0xe082e0ff, 0x0f00ff2e, 0xffff66e6, 0xffcd4cfb, 0xcecc0e00, 0x33228e82, + 0x8a829833, 0x82999921, 0x6622254e, 0xe4ffff64, 0x002c7f83, 0xff9c1918, 0xceccecff, 0xd9ffff85, 0xe3283083, 0x08803433, 0xccd6ffff, 0xf0234782, + 0x435e6666, 0xd522064f, 0x7f826666, 0x089a192b, 0x99d5feff, 0x4d00ff98, 0x21f18299, 0x3182f4ff, 0x82020021, 0xf5ff2104, 0x00210482, 0x087a7d05, + 0x34330822, 0xad254482, 0x00ffd122, 0x2ee68453, 0x91eb11fa, 0xaafcffff, 0x0800ff2a, 0x82ff9a19, 0x436b2098, 0x8b2b057e, 0x5f02ff07, 0xfeff48bf, + 0x4d66e6e6, 0xfc202e66, 0x2b2f664d, 0xfc06d4f8, 0x8b15db34, 0x4ceeffff, 0xf123de82, 0x4dff33b3, 0x415005ba, 0x0e204713, 0x180fb64b, 0x4e0d0bcc, + 0xab210811, 0x17e74b7b, 0x34203083, 0x4706cb4b, 0x02190d51, 0xce50131b, 0x3c8c870e, 0x01ffef0e, 0xf89a99e4, 0xff9d1516, 0x34330900, 0xff1300ff, + 0x0400fffe, 0x00ffcccc, 0x05434914, 0x6866392e, 0xff8ba606, 0x34b31200, 0x0ce5ffff, 0xf62be782, 0xffff0080, 0x0800c0e6, 0x82edffff, 0xcfff2c28, + 0xffffce4c, 0x6364e6db, 0x83d1ffff, 0xb3e8261a, 0xfeff0833, 0x274d82ef, 0x999977ff, 0xfbffff05, 0xfd211583, 0x292582cc, 0xff9a19fb, 0xccccfeff, + 0x3c828b86, 0xcd4c762e, 0xf6ffff06, 0xff8b33b3, 0x9919f7ff, 0x1d837682, 0x85ebf92b, 0x190700ff, 0xffff089a, 0x220a83b6, 0x82323355, 0x38f92242, + 0x251582d5, 0x00ff67e6, 0xa0827402, 0x33330c22, 0x4f21af82, 0x8333829e, 0x20002a6c, 0x059bf628, 0x8f0800ff, 0x2711825c, 0x00ffcd4c, 0xff8f020a, + 0x2e059844, 0xff71bd08, 0x9919fcff, 0x3900ff08, 0x8272cd4c, 0x82632025, 0x3100238e, 0x56826666, 0x3d0a6d27, 0x805e00ff, 0x270a8200, 0xffeb91f5, + 0xc4b50600, 0xd73a3682, 0x0f00ff0b, 0x00ff8e82, 0xff0a170b, 0xce8c0500, 0x2d00ff08, 0x00ff29dc, 0x8b82f316, 0x820f0021, 0x070022a6, 0x222982f5, + 0x82666613, 0x52f8252e, 0x991000ff, 0xf922d882, 0x298200c0, 0x66e6c222, 0xe620ba82, 0x00215e82, 0x21158267, 0x0a833400, 0x661bfe25, 0x4136fc66, + 0x441909cb, 0xd4200e1e, 0x410c9a4d, 0xaa4221ce, 0x2f0e2419, 0x82b801ff, 0xffff28a0, 0xff159a99, 0x82b89fff, 0x3560229c, 0x27f682c2, 0xffb8de5f, + 0x34f35f00, 0x09280a82, 0x00ff7c5f, 0x8b896109, 0x3526e782, 0xf6ffff81, 0x0f8384a0, 0xff084826, 0x4861e9ff, 0xa322e782, 0x158805d7, 0xffff8926, + 0x8b90cdf0, 0xa1210f82, 0x21048248, 0x2582779e, 0xf382a020, 0x07a0ff23, 0x272582ad, 0xff6666bc, 0x9a994300, 0x2e225682, 0x3b8228dc, 0xff85eb25, + 0x82e11d00, 0x8a342c45, 0xf4ffff3d, 0x00ffc435, 0x82d8a339, 0x73f43734, 0x3800ff32, 0xfffff628, 0xff67e6cb, 0x70bd2600, 0xccc6ffff, 0x1a828bcd, + 0x00807a28, 0xefffff06, 0x6682e13a, 0x85abf123, 0x274e18ff, 0x5c4f2807, 0xf7feff08, 0x820766e6, 0x82f22017, 0x0a002d2f, 0xffff00c0, 0xff0040f5, + 0x9a590c00, 0x00213982, 0x21eb841f, 0x7e823eea, 0x00400d22, 0x0923d082, 0x18ff9ad9, 0x22073a41, 0x82081e45, 0x49012b71, 0x2a00ff07, 0xff069a19, + 0x2d837000, 0xffff8f22, 0x9f27b782, 0xffff66e6, 0x84cecc9f, 0x838320e8, 0x827620d8, 0xcaf02764, 0x0900ff80, 0x0f837d5f, 0x3c82b820, 0xb89e1627, + 0x5ce9ffff, 0x875e8228, 0x00ff2415, 0x836f320f, 0xb85e2168, 0x22063441, 0x82216000, 0x056541ee, 0xae476022, 0xca205682, 0x09228f83, 0x46837c5f, + 0x30837820, 0x30897020, 0x56868820, 0xa3160023, 0x845683d8, 0x52782146, 0x0f222082, 0xdc823233, 0x82cecc21, 0xce4c2d56, 0xfffdfb08, 0x0a577001, + 0x5700ff15, 0x1622bb84, 0x23825c0f, 0x3d0a1127, 0x0ceeffff, 0x23ab82cc, 0x0886ebe9, 0x11820685, 0x845c0f21, 0xffff2b16, 0x8b0ad7ea, 0xa8ffff08, + 0xef8267e6, 0x5c0f503b, 0xf4f70e07, 0x99d2ffff, 0xffff159a, 0x7f6666e2, 0x80dfffff, 0xf9ffff00, 0x22fe8266, 0x839a19de, 0x8506832b, 0x06002316, + 0x26849a99, 0xa4829720, 0x6666cd22, 0x17134818, 0x18ffff21, 0x39147548, 0x3342ffff, 0xffff0734, 0xffe17ab3, 0xcc4c2c00, 0x85ccffff, 0x5200ff1f, + 0xb98234b3, 0xcccc5e22, 0x2231b373, 0x823433a1, 0x20b08344, 0x204e83ad, 0x220983b3, 0x8234b3d3, 0x5fbd209d, 0x9c180506, 0xa25013db, 0xffff2416, + 0x829a9932, 0x8279209d, 0x000124e3, 0x18159899, 0x23a3325d, 0xff323363, 0x18068f6f, 0x20349d5a, 0xbeaf1900, 0xffff2b69, 0xff343393, 0x9a9979ff, + 0x46608b15, 0x80152106, 0x21066564, 0xb54c1a00, 0x62068305, 0x8b2109f4, 0x211783ff, 0x0d63ab08, 0xeaff2107, 0xb74c2f82, 0x64e52005, 0xb74c0f36, + 0x186b200a, 0x18201564, 0x2841e482, 0x15f4fb8b, 0xe62200ff, 0x25a38266, 0xffce4c20, 0xdb82f0ff, 0x1919002a, 0xe4ffff98, 0x910866e6, 0x2e06895a, + 0xff9a190a, 0x32b3ffff, 0x800600ff, 0x85089100, 0x00ff2606, 0xffce4c00, 0x201b8200, 0x29108485, 0xe1ffff08, 0x00ff66e6, 0x2c829920, 0x8266d721, + 0x80142409, 0x828b5e00, 0x14454316, 0x20055153, 0x809f18ff, 0x068b290f, 0x8b157a5b, 0xe3ffff9f, 0x00214682, 0x28468228, 0xccccf2ff, 0x4c1100ff, + 0x254982ce, 0xffcdccfc, 0x14830400, 0x9a99f922, 0x0f834182, 0x99fbff28, 0xff7e089a, 0x9f82eeff, 0x83e3ff21, 0x82d7201b, 0x0877291b, 0x00ff718b, + 0x76008015, 0x08db5e19, 0x2c089541, 0x08a58ba0, 0x00ff068b, 0xf79a995f, 0x05d84835, 0x0d225682, 0x1f590080, 0x12002305, 0xf94f0080, 0x8b322405, + 0x830e00ff, 0x094554e4, 0x83050050, 0xce531828, 0x4cee2207, 0x212d82ce, 0x3482edff, 0xf2ffff22, 0x34204485, 0x22052d49, 0x478b2b08, 0xff22070c, + 0x2a50b3f1, 0x8430940e, 0x208c9537, 0x828c8433, 0x288c891b, 0xe4f8ef0e, 0x067b15cb, 0x05b7548b, 0xf518ff20, 0xb62509a1, 0xfb08c08b, 0x20188b14, + 0x225a8299, 0x8366e6d5, 0x067b2418, 0x18e5ffff, 0x22132eea, 0x82077cf7, 0xc2272764, 0x2000ff90, 0x0483713d, 0x00ff7025, 0x828fc227, 0x890125df, + 0x9d069a19, 0x28081d82, 0xffcccc12, 0xf6a8f7ff, 0x330c00ff, 0xf1ffff32, 0xf7085c8f, 0x7cffff02, 0xff05ae47, 0x9c990a00, 0x66f5ffff, 0x0500ff66, + 0x2226824c, 0x820080f0, 0xe6f02875, 0xffff0867, 0x8233b393, 0xe5ff215c, 0x20089167, 0x820983ea, 0x088b310e, 0x54f7a4fc, 0xeb06eb15, 0xff063307, + 0x7b94fbff, 0xfc273382, 0xffff856b, 0x82846bfc, 0xfb20080a, 0x33087c94, 0xe101ff07, 0x158b9819, 0x00b0ffff, 0xff05eb02, 0x66e6aeff, 0xff072b06, + 0x9819a100, 0x1e273482, 0x158b68e6, 0x822b07eb, 0x06eb2512, 0x24fb34f7, 0x0b808718, 0x0c50ff20, 0x6672820d, 0x1c4209b0, 0x0e186811, 0xdb431a20, + 0x88152008, 0xd4fb22af, 0x0cf9662b, 0x930d4a68, 0x08786831, 0x440d2767, 0x0e251640, 0xf754f7ef, 0x2e714bb4, 0x8b07ab24, 0xcd1800ff, 0xff242290, + 0x3433f8ff, 0xff292b82, 0xff3233eb, 0xccccfeff, 0x180982ff, 0x3607ca7c, 0x08cc4ceb, 0x667a00ff, 0x2400ff66, 0xff05cecc, 0x68660b00, 0x830300ff, + 0x820c200f, 0xfcff2104, 0x00212e82, 0x22c48307, 0x826666f7, 0x83092029, 0x83f72043, 0xcc022523, 0xf3ffffce, 0xfc211983, 0x2552824c, 0x0832b3f4, + 0x40825679, 0x9a995322, 0x220df549, 0x82ceccf0, 0x33ef22f6, 0xad2b1932, 0x054c4c07, 0x9a99f231, 0x4ceeffff, 0xfb088bcc, 0xffff0614, 0x8234b3f5, + 0x66f62725, 0xffff8f66, 0x8e82e6f9, 0x6f820820, 0x82053352, 0x218a82b4, 0x8a830a00, 0x34330327, 0xb30900ff, 0x208a8234, 0x277b820c, 0x00802500, + 0xa1ffff05, 0xe3224b83, 0x0a8232b3, 0xa083f420, 0x9c52cb20, 0x20a08205, 0x2e9b83cd, 0x5c9919e5, 0xf2ffff08, 0xffff9919, 0x8234b3e7, 0x19f32125, + 0xe9237c82, 0x83736666, 0x719a2415, 0x8263088b, 0x99de297c, 0x2000ff99, 0xb38b0080, 0x47275d82, 0x8b0766e6, 0x832a00ff, 0xb31c2179, 0x25257482, + 0x00ff6766, 0x22228328, 0x829a190c, 0x83542020, 0x6619220f, 0x2af28266, 0xffcdcc04, 0x33331b00, 0x830100ff, 0x991b2293, 0x2039829a, 0x20a4841b, + 0x05ce4707, 0x41821120, 0x83f2ff21, 0x830e203c, 0x61ed2090, 0xef2205f5, 0x76823333, 0x3d82f020, 0x320a1a4b, 0xe60000ff, 0x6b056b66, 0x6650ffff, + 0xffff1566, 0x829a19b8, 0xfbff2188, 0x264f3782, 0x82fc2005, 0x040026dc, 0x088b33b3, 0x2266828e, 0x8266e602, 0x85ff8276, 0xb302227b, 0x219b8232, + 0xab82e60d, 0xce4c1822, 0x11209b82, 0x1e259183, 0x00ffcccc, 0x83fe820e, 0x00ff22de, 0x24ba830a, 0x08cecc21, 0x22fe825a, 0x44053233, 0xfb2c06c5, + 0xffff9a19, 0xff33b3f6, 0x0080f3ff, 0xf1349882, 0x8b0866e6, 0xff1cfb07, 0x9a99dfff, 0xff06b315, 0x0080d8ff, 0xdb548b83, 0x291c2605, 0x33fdffff, + 0x21af8232, 0x0983e13a, 0xff083426, 0xf6a8d7ff, 0x17395718, 0x2306395c, 0x00c00a00, 0xb3358182, 0x0d00ff34, 0x088b0040, 0x155be4f8, 0x80b3feff, + 0x00ff0600, 0x20d98308, 0x271a830f, 0x9b008007, 0xb30600ff, 0x10285d82, 0xff08cc4c, 0x9a193601, 0x0c75e118, 0x8311c25c, 0x85ff2011, 0xb3f22104, + 0x647a9018, 0x19a4002e, 0xbaffff9a, 0xff150080, 0x3333faff, 0x3420af83, 0xe6288182, 0x0000ff66, 0xffff32b3, 0xcdd7b919, 0x82663e21, 0xe65d21d7, + 0x016e3510, 0x7567202e, 0x3322086e, 0x6e7500ff, 0x75cd2013, 0x9920086e, 0x016e3510, 0xff6725e3, 0x9a190a00, 0x92c49018, 0x02ffef32, 0xff68663f, + 0xae47a601, 0x00ff8815, 0xffa4f00e, 0x3505874b, 0xffaec70a, 0x64e6efff, 0xfeff088b, 0x0668e640, 0xc0f0ffff, 0x1c828b00, 0x29dc2808, 0x38f5ffff, + 0xfdffff52, 0xffff8f02, 0x085c0ff1, 0xe6c0ffff, 0x05d4fb66, 0x1bfeffff, 0xf6ffffe7, 0x00ff1098, 0x821a7002, 0xfa3e2109, 0x1327f282, 0xf8fffffe, + 0x89089a99, 0x00ff2e0a, 0xffd82f08, 0x14aefbff, 0x970900ff, 0x2f62820a, 0x9a19ff00, 0xbfffff06, 0xff0700c0, 0x33b3d0ff, 0xe5220b82, 0x6e8271bd, + 0x8282ea21, 0x82ea2264, 0x230a8290, 0x0870bde5, 0xf7270682, 0x00fff027, 0x82022b07, 0x80d52154, 0xd7264982, 0x0000ff8d, 0x5e829002, 0x9a19df22, + 0x2a220a82, 0x158205ac, 0x82f8d321, 0x8202210a, 0x29212982, 0x21048378, 0x14828b04, 0x087ad42f, 0xf3ffffff, 0x1a00ff34, 0xffff5455, 0x099e4deb, + 0x829a9921, 0xcfff2884, 0xcb0652b8, 0x8201ff07, 0x8206204f, 0x10982199, 0x09273482, 0x00ff7413, 0x82e04f04, 0x7c1421bd, 0x68214982, 0x20698272, + 0x820a8606, 0x9c6f21e7, 0xc0212982, 0x20fb8384, 0x210982e8, 0x62826666, 0xe01ac036, 0xff05d4f7, 0x6466c6ff, 0xb8d9ffff, 0x00ff1552, 0x2b343313, + 0x9e291182, 0xff061e05, 0x162ef6ff, 0x22a482eb, 0x82989958, 0x4c76230c, 0x20828bce, 0xf49d0922, 0x74222083, 0x7a837248, 0x837cdf21, 0x3a782120, + 0x56222d83, 0x208233b3, 0x33f6ff23, 0x21418433, 0x20829919, 0x152e1322, 0x85214184, 0x2441821f, 0xfb295c74, 0x24428294, 0xf7ae4716, 0x22578204, + 0x8233b366, 0x75f42315, 0x0d82fbc3, 0x8f8eff23, 0x2230825c, 0x82d7a3a2, 0x0b002344, 0x2284b85e, 0x22839520, 0x540b0023, 0x2122847c, 0x53839953, + 0x9999dd22, 0xff232282, 0x840080f4, 0xb3662222, 0x22378232, 0x84b04716, 0x8e330822, 0x0e061e85, 0x3802ffaf, 0x94f7cc4c, 0xffff6e15, 0x2100e0ff, + 0x00faffff, 0xb1ffff42, 0xffff9a19, 0x082406b4, 0xccdeffff, 0xe1ffffce, 0xffff6666, 0x82cccceb, 0x6866220e, 0x2829827e, 0x7e086666, 0xa11f00ff, + 0x26168248, 0x00ff00c0, 0x82b89e21, 0xb8de261b, 0x9e1d00ff, 0x213582b8, 0xbd822eb1, 0x7bd44c2e, 0xf395ffff, 0xff6e9133, 0x33330000, 0xfb281682, + 0xff8b00a0, 0x00a0fcff, 0x99210482, 0x230a829a, 0x080080fb, 0x40201c82, 0xe4211082, 0x213d821e, 0x0982e006, 0x16ae9d25, 0x835100ff, 0xe6b62224, + 0x361e8264, 0xffcd0c54, 0x3433aeff, 0x335300ff, 0x0100ff33, 0x8bab66e6, 0x838bab08, 0xff342a0e, 0x9af9feff, 0x195400ff, 0x20328298, 0x254c83e0, + 0xff9c9951, 0x51824800, 0xe6060028, 0x6200ff64, 0x6082cd4c, 0x1b233c83, 0x8208cdcc, 0x80042134, 0x2f827d84, 0xd5830320, 0x34b3fb28, 0xfeff088b, + 0x4a82b3e7, 0x66669122, 0x0c20b682, 0x1220d083, 0x0e20cb83, 0x10310483, 0x00ff48e1, 0xff908210, 0x00c00e00, 0x00ff9e08, 0x21eb8212, 0x45821400, + 0xff221083, 0x2e831400, 0x48e10b22, 0xef20de82, 0x46201483, 0xff210482, 0x281483dc, 0x5e00803e, 0x4c2700ff, 0x201a82ce, 0x71d882fb, 0x2021064c, + 0x82f88300, 0xfcff2155, 0x5e23fd82, 0x82d8ffff, 0x2531842c, 0x66a6c1ff, 0x4583ffff, 0x7fb9ff23, 0x25f982ff, 0xffb85e14, 0xcb83f4ff, 0x48211426, + 0xa1f1ffff, 0x12208a82, 0xed202d83, 0x95828a82, 0xff70fd26, 0xb99ef0ff, 0x2606af64, 0xff32b3ee, 0x82e60c00, 0x19ed2e42, 0xff0e089a, 0xcc4c5d01, + 0x9e9001ff, 0x2ed482b8, 0xff9a9912, 0xae47bbff, 0x0600ff05, 0x827134b3, 0x261083c5, 0xffcecceb, 0x82661800, 0x19f72231, 0x276f8298, 0xff32333a, + 0xcecceaff, 0x15272582, 0xffff34b3, 0x829919f8, 0x22d083f6, 0x82cd4ceb, 0xcce823b5, 0x068208cd, 0x6766ee23, 0x2df918ff, 0x26968208, 0xffffcccc, + 0x829a99f5, 0x83ad20e6, 0xb3c4262b, 0xffff0532, 0x215683f2, 0x458333f5, 0x82686621, 0xcccc27a6, 0xeeffff8c, 0x6682ce4c, 0x98190327, 0x66cdffff, + 0x25668266, 0xffce4c02, 0xa782daff, 0x19e2ff22, 0xe020a182, 0xda232f83, 0x828b3233, 0x66f0274b, 0xff7c8b66, 0x52830500, 0xce4cf32b, 0xff5e0895, + 0x32332600, 0x20138205, 0x8292840d, 0x07002176, 0xeb205b83, 0x28052654, 0x069a99f7, 0x80f9ffff, 0x20a28200, 0x205283fb, 0x202683ff, 0x29ac83fa, + 0x0866e6fe, 0x02bdffff, 0x99827e8f, 0x8f02e824, 0x2084ffff, 0xc2b5e725, 0x830b00ff, 0xe1f32778, 0x1500ff48, 0x25823433, 0xe1faf528, 0x991100ff, + 0x10828b98, 0x00234082, 0x821f050a, 0x0080210f, 0x1b27b882, 0x00ff33b3, 0x82008030, 0xe10521b8, 0x0a203082, 0x0023bd82, 0x82991903, 0x9a992144, + 0x0b202f82, 0x06826682, 0x51830d20, 0x713dfc2d, 0xb30c00ff, 0xf8ffff32, 0x8296a4f0, 0x86d32757, 0x4500ffa8, 0x81823433, 0x4c77f027, 0x331800ff, + 0x27dd8232, 0xffab9378, 0x50ad1600, 0x99216282, 0x2a62829a, 0xffc3b50a, 0x9a590800, 0x820d00ff, 0x040023b8, 0x0982b81e, 0xffcd8c26, 0xb81effff, + 0x47221e82, 0xbb82e2ba, 0x059a592d, 0xfeffffa8, 0x00fff628, 0x82cd4c1b, 0x0a972666, 0xcc1200ff, 0x254982cc, 0xff08e2fa, 0x3a831f00, 0x1e452822, + 0x0c20a782, 0x0f229d83, 0x1f82ea86, 0x0928cc83, 0x00ff8e13, 0x8b34b313, 0x1c222582, 0xac8266e6, 0xcc4c1928, 0x96ecffff, 0x1d4eff2c, 0x17e42b05, + 0x078b080a, 0xf854f70e, 0xf3591554, 0xffe5180d, 0x072b2608, 0xeb0614fb, 0xf75d1807, 0x22818308, 0x857a540e, 0xcb08272d, 0xfb54fb06, 0x1d821594, + 0x66e63527, 0xfa2a00ff, 0x200482e1, 0x2dcf8219, 0x8b1f0535, 0x0614f708, 0xffb68bc0, 0x7b83d5ff, 0x19caff26, 0x64fb089a, 0x21175c50, 0xed5074fb, + 0x07642818, 0x158b34f7, 0x19d3ffff, 0x20137733, 0x2f17838b, 0x2300ffcc, 0xffffcdcc, 0xff3433dc, 0x33332c00, 0x0683f083, 0x1b821685, 0xa182cc20, + 0x34332c23, 0x83068508, 0x83332028, 0x85cc201b, 0xf7082454, 0x8254f734, 0x765f18c4, 0xffff2314, 0x3e824cee, 0xb3f1ff22, 0x0e205b82, 0x0d085f18, + 0x00ff8424, 0x7c824c0e, 0xb4181682, 0xff23124f, 0x8284abf1, 0x54ee249e, 0x52ab087c, 0xab200560, 0x601830a8, 0x8c961603, 0x8334f721, 0x21bed95f, + 0x1f532b4b, 0x83ef8607, 0x421120f4, 0xc4670558, 0x0a0e4f09, 0x2009855c, 0x08855c34, 0x5b11ce6b, 0xcb2007f8, 0xff205e83, 0x4117295c, 0xd763097c, + 0x06a7530d, 0x9305bb5c, 0x8433208c, 0x08cd2485, 0xdceb34fb, 0xff0e3cbe, 0x34336e01, 0xff1554f7, 0xcccc2100, 0x3d00ff06, 0xff8b66e6, 0x9a193200, + 0x83cdffff, 0xc2ff210a, 0x20057a6d, 0x211183eb, 0x168299f2, 0x3233ee2d, 0x66edffff, 0xf9ffff66, 0x82086866, 0xcc4c2126, 0x20181843, 0x171843f4, + 0xb3226282, 0x47820734, 0xff295c30, 0x98990600, 0xa3f2ffff, 0x1100ffd7, 0x7d82cecc, 0x9d441420, 0x828a8205, 0x82232026, 0x258e8316, 0x29dc3d00, + 0xa683088b, 0xa682cd20, 0xa6841d20, 0xcd4c1824, 0x048200ff, 0x10823382, 0x06820820, 0x01801126, 0xccf6ffff, 0x0f251682, 0xffffcccc, 0x262083f5, + 0x0834b30d, 0x82f3ffff, 0x100022b1, 0x2614824c, 0xff0080f8, 0x83661400, 0x841620e7, 0x23d352dc, 0xffff8b24, 0xf382e6e9, 0xff233c83, 0x859a99eb, + 0xefff2150, 0xf5225b84, 0xc082ce4c, 0xf6205b83, 0xf0227583, 0x2e823433, 0xff7fee22, 0xff239182, 0x839a19e2, 0x277782a3, 0xff33b3e7, 0x68e61d00, + 0x3134c583, 0x34fbcccc, 0x06d4fb15, 0xd4f7076b, 0x0e07ab06, 0xcf01ffaf, 0xff292982, 0x15cc4ce5, 0xffff7f8d, 0x280c83fb, 0x81ceccf3, 0xe6f8ffff, + 0x22bf8266, 0x839819f6, 0x8268200a, 0x82e62068, 0x83ff2004, 0x82f5200e, 0x05002172, 0x7f208284, 0x00279282, 0x05008044, 0x827fffff, 0xbbff2167, + 0xf5250a84, 0xffff3333, 0x272582fa, 0x66e6f2ff, 0xe60000ff, 0xf6203982, 0x00235982, 0x84981907, 0xff992153, 0x9a210a82, 0x05695586, 0x19020025, + 0x8208979a, 0x224b83ad, 0x829a9992, 0xc797274b, 0x6600ffae, 0x0a823433, 0xd763f72c, 0x990800ff, 0xfcffff99, 0x3082a4f0, 0x03202483, 0x0b221e83, + 0x34829999, 0x1fc5032c, 0x800b00ff, 0x0900ff00, 0x288252f8, 0x6f826620, 0x71fd0b25, 0x830100ff, 0x8f00269f, 0x00ff7b94, 0x21488315, 0x1a834000, + 0x7a548428, 0x0500ff05, 0x3482ce4c, 0x82180421, 0x32332604, 0xfe0600ff, 0x5f58823c, 0x0c23052e, 0x838bcc4c, 0xff342516, 0xc401f9ff, 0x2206ed55, + 0x82e8fbf4, 0x8240206a, 0x7bff2335, 0x408286ab, 0x82b38f21, 0xccea221f, 0x280a82cc, 0xff64e60b, 0xcc4cfeff, 0x05f24795, 0xcc030028, 0xf4ffffcc, + 0x30820080, 0xd0cc0322, 0x66210a82, 0x83ba8267, 0x82f32024, 0xf7ff2380, 0x28826866, 0x08676625, 0x8397ffff, 0x84992029, 0x82182044, 0x6dff23d5, + 0xef826666, 0x82e65021, 0x4c6228c1, 0x00ff15ce, 0x849a1900, 0x20658204, 0x2020836f, 0x212084c4, 0xb282b3ea, 0x834c7e21, 0xcc5a217b, 0x5922c782, + 0x3682cdcc, 0x98998227, 0x661200ff, 0x200a8267, 0x22a782c8, 0x828c7200, 0xffff2120, 0xff374c82, 0x05c2b5ff, 0xbddefeff, 0x2f0e0772, 0xd4f704f8, + 0xd0ffff15, 0x8206cc0c, 0x2603235a, 0xc35905db, 0x59ff2005, 0x2b210fba, 0x16d95506, 0xffffff27, 0x053b0ef0, 0x211f975b, 0xb21894fb, 0xff2417c1, + 0xcd0c1000, 0xff233682, 0x827b33f3, 0xf7ff2176, 0x23051142, 0xf8ffff9a, 0x0026a682, 0x8b67e608, 0xcd18ab08, 0xad821791, 0x9b9a1925, 0x8314f705, + 0x66e62140, 0x9b6e4085, 0x18408412, 0x6d0891da, 0x40820aef, 0x9b980c28, 0x0f00ff05, 0xfe1868f3, 0xe3560cb0, 0x83f7200a, 0x560020bb, 0x403615e6, + 0x15db9a19, 0x073b06eb, 0x07db062b, 0xe69f00ff, 0x15e4fb66, 0x651874fb, 0x00220c0d, 0xfe183307, 0xec180e3f, 0x08220a7f, 0x646bcdcc, 0x7fec1807, + 0x06355a13, 0xccf8ff22, 0x073c5118, 0x4c82f720, 0xf78b0823, 0x23659214, 0x00ff8b33, 0x08204f82, 0xff200685, 0x7a516587, 0x05ca6b07, 0x6418cc20, + 0x53820784, 0x07036418, 0x33216584, 0x226587ff, 0x84ffffcd, 0x180e2065, 0x185f8444, 0x24c45cb9, 0xfb9a99af, 0x1ac07384, 0x184c2321, 0x243f25eb, + 0x34f88b0e, 0x08384a15, 0x0d306818, 0x0614f722, 0x2216704a, 0x5b0714fc, 0xfa3e0927, 0xffff8be1, 0xb61f05d5, 0xf808c08b, 0x14f70714, 0x064b156b, + 0x06cb074b, 0xfb4b07cb, 0x07841554, 0x074b0625, 0x824cfbab, 0x2bfa72c9, 0x1a95d718, 0x7318b320, 0x0d300ccc, 0x088b0040, 0x15a314f7, 0xff079af7, + 0x66664b00, 0x5e220482, 0x5f1905b8, 0x4c210c7f, 0x2be582ce, 0xff00800c, 0x0080f3ff, 0x5a00ff08, 0xa5220a83, 0x2586ae87, 0xc6821583, 0x5882eb20, + 0x25860a83, 0x822cff21, 0x2cff234b, 0x25820080, 0xcc4c0028, 0x330300ff, 0x2545ff32, 0x66032205, 0x24508268, 0x08cc4c03, 0x2373828b, 0xebcccc96, + 0x6922dd82, 0xa1593433, 0x09b86c0d, 0x2419d570, 0xccd6feff, 0x2e3682cc, 0xf7ffffbf, 0xaf0e0554, 0x66c000ff, 0x8214f766, 0x613f224e, 0x2c938248, + 0xffc2b5f6, 0x84ab2700, 0x3d2900ff, 0x217d8270, 0xbe829a59, 0x3e8a2a26, 0xa2ffffff, 0xf52dce82, 0xffff1e45, 0xffe258d8, 0x9a194000, 0x311a828b, + 0x8b1e4527, 0x731000ff, 0x1200ff34, 0x00fff668, 0x35827d06, 0x846b062d, 0x73ffff08, 0x00ff9a99, 0x829a1974, 0x4a032cce, 0x0100ffc0, 0x00ff62b0, + 0x82365e1c, 0xd282242e, 0x522b00ff, 0x0c220528, 0x4082ec91, 0x289c0c31, 0x9afeffff, 0x0c00ff5c, 0xffff9a59, 0x82e02ffd, 0x9726225b, 0x21a5820a, + 0x4082f027, 0x78690222, 0x70268182, 0x0200ffd8, 0x09827a69, 0x8264bb21, 0x42602109, 0x0f228183, 0x4082f6e8, 0xcc0c1022, 0xcf213b82, 0x230a825c, + 0x08e23a13, 0x0e210682, 0x2a288294, 0xff52f8f5, 0xa4300d00, 0x82f1ffff, 0x03002304, 0x9882d863, 0xa883d920, 0x10d8082d, 0xeeffff05, 0x00ffa4f0, + 0x826ce703, 0x22ad8309, 0x82daee01, 0x66a62109, 0xff2e5782, 0x8b66e687, 0xb3c6ffff, 0xaaffff34, 0x73824821, 0x82cc4c21, 0x9ad92198, 0xe82a4082, + 0xffffc475, 0x051797e3, 0xaa586f76, 0x80df2206, 0x063a6801, 0x9819de22, 0x2306d45a, 0xce4cf8ff, 0xcc2beb82, 0xfbffffcd, 0x00ff6666, 0x82991912, + 0x7f012557, 0x153e9a99, 0x0f229f82, 0x3c82d823, 0x82142e21, 0x3273269f, 0x91f0ffff, 0x21d282ec, 0x5e827cd4, 0xe27acf27, 0xe30800ff, 0x29998254, + 0x00ff1e05, 0xff8e9714, 0x8d82e7ff, 0xe6221a82, 0x9482e2fa, 0x82d4f921, 0x35e027da, 0xbfffffc2, 0x53829002, 0x68cfff23, 0x271682f6, 0xffb8dee7, + 0x5c0f1600, 0x5726ab82, 0x0000ff0a, 0x31825c8f, 0xe8dbf926, 0x280600ff, 0xf7226182, 0x518288e1, 0xffee0724, 0x8463f7ff, 0x40e72205, 0x27358200, + 0xfff628f9, 0xa430e0ff, 0x63214c82, 0x204c8ad7, 0x22b282e6, 0x82ae0716, 0xae47214c, 0xe0214c88, 0x214c8700, 0x4c8233d3, 0x88861621, 0xedf7224c, + 0x314c8291, 0xffb6f3f7, 0x58f9fcff, 0xbdf9ffff, 0xfaffff71, 0x82820020, 0x70fde22c, 0xc0e5ffff, 0xd3ffff00, 0xee828f42, 0x82c2b521, 0x75d82329, + 0x068208c2, 0x86ebef31, 0xc50c00ff, 0xf0ffff1f, 0x00ff8e02, 0x82a4f012, 0x09002482, 0x658b1fc5, 0x072006a6, 0x1826ca83, 0x00ff299c, 0x4c82800e, + 0x8f13002b, 0xf4ffff5d, 0x00ffd277, 0x28a1821f, 0x32b3f3ff, 0x992c00ff, 0x8335839a, 0x27168506, 0xb81e0d00, 0x801300ff, 0x0b27ad82, 0xff083e8a, + 0x82871300, 0x78f422c8, 0x201e8252, 0x20e982f0, 0x230482f2, 0xae872c00, 0x97213584, 0x216b820a, 0x1b82f81f, 0x0a170d22, 0x87303587, 0x00ff08ae, + 0xffc2b518, 0x146ef1ff, 0x071e00ff, 0xf8273f82, 0x00ff72bd, 0x83008009, 0xe6122735, 0xffffff68, 0xbc82d623, 0xffcccc26, 0xcecc0f00, 0x102b4482, + 0xff08cc4c, 0x9a191ffe, 0x721541f7, 0xff2005df, 0x08fa6c19, 0x20057a75, 0x20068508, 0x050173ff, 0x66a61c25, 0x42dcffff, 0x0683056e, 0x1b831685, + 0x82052d73, 0x00002c82, 0xdcffff00, 0x00ff33b3, 0x82cd8c1d, 0xcd4c2f1f, 0x732200ff, 0x0e088b33, 0xf7d4f7af, 0x288215d4, 0x82a0ff21, 0xcdff2222, + 0x218f8202, 0x048284b0, 0x827efc21, 0xe4a02104, 0x03213c83, 0x260a824c, 0x00ff3228, 0x82343300, 0x32332109, 0x19212e83, 0x2a1a829a, 0x079a9903, + 0xffff14fb, 0x8266e600, 0x195f31aa, 0x54f7079a, 0xa0ffff06, 0xff079002, 0x9a992700, 0x25253282, 0x0e00ff12, 0x26098259, 0xffd0d511, 0x820c0a00, + 0xd90822e6, 0x233b8298, 0x07f628e5, 0x1122c782, 0x2082b89e, 0x86486121, 0x200e8204, 0x831c828b, 0x23118506, 0xb89ef1ff, 0xee236f82, 0x4e084861, + 0x002d06bc, 0xff7c540e, 0x84abf1ff, 0xab1100ff, 0x822d8484, 0x822d8206, 0x831b8316, 0x84ab2954, 0xffc08b08, 0x68e6d5ff, 0x23053850, 0xfeffcaff, + 0xff212982, 0x20c182c3, 0x29ad8200, 0xe6dbffff, 0xceffff66, 0x54825c0f, 0x0a57ce26, 0xa3ffff08, 0x5420cb83, 0xb3069350, 0x887a2094, 0x84862094, + 0xcc4c2194, 0x0d208982, 0x0d278183, 0x00ff3cca, 0x820a9700, 0x682621b0, 0xfe276a82, 0x00ffe4c5, 0x82900231, 0xac3c2985, 0x0c3000ff, 0xc6ffffcc, + 0x2205b052, 0x829a19ca, 0x83d52091, 0x09de509c, 0x1affff2f, 0xff07cccc, 0x00800a00, 0xccf6ffff, 0x06a153ce, 0x9a99ee25, 0x832800ff, 0xb3002a04, + 0x14f80832, 0x19c2ffff, 0xc214449a, 0xff8fe226, 0xfc090300, 0x300f1444, 0xffff5ae4, 0xff2406fd, 0xe1baf9ff, 0x1ffaffff, 0x191444c0, 0x1444c420, + 0x00803735, 0x78f4ffff, 0x2000ff52, 0xffff8f02, 0xff0ad7f2, 0xec912c00, 0x0685088b, 0x1f00ff25, 0x44ffd6e3, 0xfd211b14, 0x21358270, 0x2e82f6e8, + 0x443e8a21, 0xeb210a14, 0x44359186, 0xeb261b14, 0xffffff88, 0x1444eafc, 0x0e2a0810, 0xd700ffef, 0x01ffcd4c, 0x159a9930, 0x331c00ff, 0x3000ff33, + 0x00ff7a54, 0xff34b31e, 0xaec72d00, 0xb31400ff, 0x1d00ff32, 0xb28272fd, 0xce4c0c2d, 0xb71100ff, 0x1900ff0a, 0x828b9899, 0x240f824c, 0xf648eeff, + 0x37348208, 0xffff9a99, 0xffb8deb9, 0xcc4c6600, 0x8763ffff, 0xffff8bae, 0x08ccccb6, 0xf1220682, 0x62616666, 0xf2ff2105, 0xfd212583, 0x222a8219, + 0x823433f3, 0x838b2035, 0xcc922c2b, 0x00ff05cc, 0xff68660a, 0x82ccf7ff, 0xe6012760, 0xf0ffff64, 0x0e8366e6, 0xc155d020, 0xccf72107, 0xf5225582, + 0x19839899, 0xfe221e82, 0x19839c19, 0x00ff9c31, 0x08323308, 0xfeaffdff, 0xd001fff8, 0x82058e02, 0x68912115, 0x2e211582, 0x25728216, 0x00ffc72b, + 0xcd82140f, 0x502d0822, 0x6f216182, 0x2272821a, 0x82912d08, 0x986e210a, 0x7b251983, 0xd40100ff, 0x210e823a, 0x6c82a470, 0x82b0d221, 0x7db0271e, + 0x75ffff71, 0x488246b6, 0xcdccb728, 0x4c50ffff, 0xe98215cc, 0xb8821620, 0x330b0023, 0x06c54533, 0x1a820e20, 0xb3220022, 0x0121c282, 0x22dc8312, + 0x82008028, 0x33e02a30, 0xe0ffff34, 0xffff32b3, 0x351483d4, 0x5a34b3ec, 0xffff088b, 0x8b33b39f, 0x4cb0ffff, 0x4e00ffcd, 0x4c82cccc, 0x9a196227, + 0xeb078b08, 0x2058838b, 0x21e78307, 0x5882b3f9, 0x9a190827, 0x4cf6ffff, 0x223283cd, 0x829919f8, 0xe6f72232, 0x21968267, 0x0a8266e6, 0x3283f820, + 0xc1ffff2b, 0xffbe3433, 0x66e6cdff, 0x232582c8, 0x32b30900, 0x07204d82, 0x004d7582, 0xf8ff2411, 0x83ffcccc, 0x20538316, 0x212d82ce, 0x2d83d4ff, + 0x4cdbff24, 0x6554ffce, 0x842d2006, 0x62824c86, 0xfa828a20, 0xe693ff27, 0xffff1566, 0x20ee83f9, 0x278382f4, 0xcdccfbff, 0x66f3ffff, 0xf423dc83, + 0x82086666, 0x83fa20e3, 0x99022ab1, 0x00ff869a, 0x88cc4c04, 0x82068308, 0x19fd2223, 0x066d579a, 0x3782ff20, 0x62051474, 0x14370585, 0x00ff9999, + 0x05cecc06, 0xe61a00ff, 0x0a00ff67, 0x00ff9819, 0x8200801c, 0x3433212e, 0x1b780982, 0x33032305, 0x0c850634, 0xff201c85, 0x1a206784, 0x20052d71, + 0x22658268, 0x829a9914, 0x32332198, 0x04204682, 0xfd201583, 0x05206683, 0x00224683, 0x848332b3, 0x00ffce25, 0x8466e602, 0x8ecc218f, 0x99230b82, + 0x848b909a, 0x21b58263, 0x3d830b00, 0xccccfb22, 0x82052251, 0xff6826e0, 0x32b30b00, 0x23528208, 0x829732b3, 0x20062443, 0x295882f4, 0x98190b00, + 0xffa17508, 0xd183e0ff, 0x37831320, 0x9a99da23, 0x8329828b, 0x27168306, 0xecffff99, 0x75756666, 0xf4201282, 0xff27d082, 0x8268e6f4, 0x82f3ffff, + 0xf9ff3185, 0x087f33b3, 0xffff068b, 0xff3333fb, 0x6666d900, 0x64e75118, 0xa4189a20, 0x2f24f618, 0x198a01ff, 0x2208fc82, 0x153333eb, 0xf5ebffff, + 0xe4ffffc2, 0xffff7b54, 0xff52f8f7, 0x1e85dfff, 0xe3fcffff, 0xdeffffd8, 0x82083433, 0x84402b0a, 0xa8d6ffff, 0xfafffff6, 0x098286f6, 0xff48e12b, + 0x20e5f6ff, 0xa8d7ffff, 0x371e82f6, 0xff0040f9, 0x285ce2ff, 0xfdffff05, 0xffffec51, 0xff28dcf3, 0xd663f5ff, 0x5c214d82, 0x250e822a, 0x088b66e6, + 0x12828b7f, 0xff289c26, 0x9e4f0800, 0x7a832682, 0x44eb0b22, 0xe2273c82, 0x00ff146e, 0x82343379, 0x11fc283c, 0x0f00ffec, 0x537da2f0, 0xef200626, + 0x2205784b, 0x82ecd1ef, 0x83f1203c, 0xbdf42698, 0xfcffff70, 0x22598223, 0x86ae07f0, 0x86ff233c, 0x3c82cccc, 0x641bfd27, 0x14f4ffff, 0x2166827a, + 0x7982c580, 0x82a4b021, 0x9919220e, 0x2225828b, 0x823dcaf3, 0x80f52240, 0x217d8200, 0x7d8296a3, 0xffc23526, 0x18240c00, 0xf9271a82, 0x00ff645b, + 0x82d8a31d, 0xe5f62640, 0x2800ff1e, 0x27ba825c, 0xff0af7fa, 0xba1e2900, 0x0a212982, 0x2109823d, 0x2982ea51, 0x5f1afc27, 0xbd2200ff, 0x05224172, + 0x991f0023, 0x0536419a, 0xb31b0023, 0x211e8233, 0x5d8240ed, 0x85eb1922, 0xa3211e82, 0x212882d7, 0x6c82e23a, 0x15ae2408, 0x6b2400ff, 0x00ff0884, + 0xff926d09, 0x0a972700, 0xf61e00ff, 0x2000ff46, 0x00fff628, 0xffc37526, 0x82470a00, 0x140022c7, 0x20338223, 0x26428305, 0xff676613, 0x8230fbff, + 0xc7112b4c, 0xf6ffffae, 0xff084a7c, 0xf1835600, 0xc275c728, 0x0600ff05, 0x1f829ca4, 0x1f82a020, 0x8c77082c, 0x830200ff, 0x0300ffd8, 0x18829ad9, + 0x82be1f21, 0x11042229, 0x260a82ec, 0xffff3a74, 0x82142efe, 0xd0a22581, 0x91f9ffff, 0x04221382, 0xa5822045, 0x3ecae72e, 0xdc0f00ff, 0xff8e0528, + 0xf0870100, 0x37213a82, 0x2109820a, 0x49823a34, 0x9282c820, 0xf8130227, 0x1600ff08, 0x37548263, 0xff0ad710, 0x285c1a00, 0xcf0b00ff, 0x1b00ff5c, + 0xffffd8a3, 0x0814aef8, 0xc225b783, 0xb8f5ffff, 0x24cb8252, 0xffff52f8, 0x277d83df, 0xff866b09, 0x6666d8ff, 0x08351e82, 0xffff66a6, 0xff1e85db, + 0x32b3f7ff, 0xb3ddffff, 0xedffff34, 0x28048233, 0x083333e6, 0x00ffef0e, 0x2ee28273, 0x34333701, 0x6600ff15, 0xffff9a19, 0x8266a6da, 0x21232bd8, + 0x5100ff48, 0x00ffb89e, 0x04821e33, 0xfd823e20, 0xc0340022, 0x1d22e782, 0xb982cc4c, 0x1483a020, 0x00e00436, 0x14a3ffff, 0xd6ffff7b, 0xffff3e2a, + 0xffcd4cc4, 0x9042b5ff, 0xf9221e82, 0x6f823333, 0x8fcc8c2a, 0x66f3ffff, 0x0a00ff66, 0xfc227083, 0x8f826866, 0x0a838420, 0xcccccf22, 0xee216e82, + 0x223f8280, 0x834821a9, 0xfebf246e, 0x827900ff, 0xeeff262a, 0x00ffbade, 0x2024836e, 0x206e83c2, 0x216e8416, 0x7982a0f8, 0x04820220, 0x41f8ff22, + 0x01249782, 0x8b83e06f, 0xc62a6682, 0x00ffcc0c, 0xff2a0700, 0xd683b9ff, 0x3082ba20, 0x83d3ff21, 0x219a2754, 0x01ff0848, 0x7a82e611, 0x707d7c22, + 0x06216a82, 0x206a8240, 0x211f82ef, 0x1f830400, 0x82a1ed21, 0x61022745, 0xebffff48, 0x9482b85e, 0x19820520, 0x82ceff21, 0xf8ff2df2, 0xffffc0df, + 0xff20c5c5, 0xf87eeeff, 0x33210982, 0x261e8234, 0xff989966, 0x83a1daff, 0x830a20a8, 0x82fc2024, 0x0b00274d, 0x00ffb81e, 0x98822007, 0x0e830020, + 0x83be0a21, 0x73022a48, 0x5f00ff34, 0xffff5acf, 0x219182d3, 0x04825b00, 0x82b3ff21, 0x39002371, 0x746ed6e3, 0xfeff2805, 0x1590827c, 0x820663fb, + 0x80b227ba, 0xffff0500, 0x4882dec3, 0xb8de1522, 0xb7200a82, 0xff235382, 0x829a9937, 0x0233280a, 0xffff0690, 0x83717de5, 0xffae25e1, 0x8f82eaff, + 0x210e056c, 0x6b8233f7, 0xba290722, 0x2905e453, 0x46d60800, 0xb4f8088b, 0x0982ff06, 0x828b4421, 0xbc29219a, 0xba200483, 0xef220a83, 0x068208e0, + 0x66661b22, 0x2410fe55, 0x34f82f0e, 0x512819f8, 0x184b2018, 0x22171242, 0x760754fb, 0x329816d7, 0xce824b20, 0x5a0b2e5c, 0xfb2208b1, 0x99770654, + 0x18328416, 0x880a6a7b, 0x82cb2032, 0x11002297, 0x20ff82b3, 0x0da0750e, 0x9782f720, 0x99eeff21, 0x19ab2032, 0x2011be39, 0x0f6d53cb, 0x2007985c, + 0x219783f7, 0x32841100, 0x300dc95c, 0x5b5b06cb, 0xab076b15, 0x6b07ab06, 0x3ba4fb06, 0x060e4115, 0xdf6e3320, 0x0aed5b06, 0xaa844486, 0x1e5c4484, + 0x19aa8508, 0x41136f3a, 0x5b221910, 0x778884fb, 0x6bf4f724, 0x7f82ab15, 0xfb238783, 0x88d4f7d4, 0xff0e230c, 0x6583fe01, 0x9a190232, 0x01ff4215, + 0x059a1924, 0x33fcffff, 0x0f00ff34, 0xff211682, 0x4d0482f3, 0xf1200585, 0x31050c48, 0x0634b3c3, 0xa00300ff, 0x0900ff00, 0x00ff9a19, 0x09824002, + 0x66a60b22, 0x0b22cc82, 0x834e0040, 0xb6662806, 0x19caffff, 0x6f088b9a, 0x062a08a1, 0x568b6066, 0xffff8b08, 0x2f82c0f4, 0xff213483, 0x823983f5, + 0x82812048, 0x9fc42425, 0x4eff06ff, 0xf32006f8, 0xff231782, 0x820080f5, 0x2d098386, 0x0800c0f0, 0xfdb6ffff, 0xdbfeff70, 0x9c8266e6, 0x25a6f725, + 0x83deffff, 0x00172546, 0xdfffff42, 0x1f258583, 0x088b48a1, 0x229983f8, 0x822a9c1f, 0xff162b8a, 0x2000fffe, 0xffff66e6, 0xca82b3f7, 0x34332122, + 0x01204382, 0x01280a82, 0x1566e63d, 0x66eeffff, 0xff21b082, 0x201082f0, 0x4f561800, 0x83f88311, 0x00ff2216, 0x21f38411, 0x5d821100, 0x0e00ff24, + 0xa287b85e, 0x21079b4f, 0x11824861, 0x849a9921, 0x26548516, 0x70fb0e08, 0x827b7cf7, 0xd7230862, 0xff0671fd, 0xcc4c7500, 0x4400ff07, 0x00ff1f85, + 0xff48e10f, 0xe07a3100, 0xfa3f00ff, 0xf9ffffe0, 0x19ff6866, 0x265915db, 0xffff0060, 0x8200c0b5, 0x82812070, 0x0cc022a3, 0x258484ce, 0xffff087b, + 0x9182cc8a, 0xfad7ff2a, 0xffff06e1, 0x8bb8dee9, 0x1e20b782, 0xee21d882, 0x230a831e, 0x0848e1e9, 0xfb211182, 0x203982a0, 0x21048203, 0x4882fcff, + 0x60040023, 0x15db1983, 0x8b84210b, 0x82060042, 0x2d0a8221, 0x08006004, 0x060000ff, 0x1600ffa6, 0x4e829a19, 0x00230482, 0x8266e611, 0x0503485e, + 0x6666cc37, 0xcca300ff, 0xffff15cc, 0xff295cf2, 0x0ad7fcff, 0xccf1ffff, 0x213482cd, 0x13851203, 0x03003208, 0xff08642f, 0xc2f5d0ff, 0xf60a00ff, + 0xe0ffff80, 0x00ffc335, 0xff01002c, 0x3d4a0400, 0x193000ff, 0x00ff0899, 0xffec510d, 0x9a199500, 0xa400ff05, 0x05106d99, 0xffffcd25, 0x82cdcc6a, + 0x47042710, 0xcfffff6c, 0x3a8271fd, 0xff943830, 0x7a14d4ff, 0x0ad1ffff, 0xf5ffff3e, 0x59824821, 0x8e42ff2a, 0xccffffff, 0xeb0e05cc, 0x610b4b57, + 0x4a570f84, 0x06bb6116, 0xfb14f724, 0x88611514, 0x19e86145, 0x94fb4b23, 0x21fa8215, 0x22823333, 0xcdcc2322, 0x61070e4d, 0xd0611a74, 0x74f72b2d, + 0x8b1504f8, 0xa3feffff, 0x05828ad8, 0x82d66321, 0xcccc3204, 0x63ffffff, 0xffff08d6, 0xff3433e2, 0x7c94f3ff, 0x21058205, 0x0f829a99, 0x82523821, + 0x80fe220a, 0x21258200, 0x2582aec7, 0x83cc4c21, 0x9a992235, 0x202c828b, 0x820682fe, 0x66662217, 0x2618828c, 0x00ff6666, 0x82523801, 0x82f32016, + 0x1d002338, 0x3882aec7, 0x00234e83, 0x82846b0c, 0xe6fd210a, 0x00222082, 0x2a822a9c, 0x01220983, 0xe0822a9c, 0x285c0123, 0x26068308, 0x00ff4861, + 0x829a1900, 0x0a972441, 0x830200ff, 0x232a8209, 0x1d00ff08, 0x40859a82, 0x830c0021, 0xc71d2361, 0x2a8205f0, 0x01226183, 0x2f821038, 0x8c9a9922, + 0x66210582, 0x218f8266, 0x06820100, 0xb3221c82, 0x8a708a34, 0xfeff2305, 0x4382f0c7, 0xff233883, 0x821038e2, 0x854e8338, 0x010021de, 0xf482e983, + 0xfe23bb82, 0x828bf668, 0xb89e21c7, 0x4c202c82, 0xff246582, 0x155238d2, 0x40050041, 0xdf41b6c7, 0x05b64f5b, 0x7b949b25, 0x4100ff15, 0x3321055a, + 0x085a4133, 0x829a9921, 0x055a410a, 0x8c666627, 0x66feffff, 0x228b8366, 0x85089a99, 0xff8a2506, 0xcc4cffff, 0xcc201782, 0x80210483, 0x08724200, + 0xff283883, 0xff9a99f3, 0x3433e2ff, 0x83087242, 0x422f8225, 0x33211b72, 0x08724234, 0x42cccc21, 0x66210872, 0x07724266, 0x00800122, 0x28067242, + 0x8b34b300, 0x660100ff, 0x838b8266, 0x42ff2006, 0x74820672, 0x82067242, 0x077242a6, 0xde844083, 0xcc1d0023, 0x087242cd, 0x42333321, 0xcc212072, + 0x288f82cd, 0xff6666ec, 0x33333200, 0xb9f54015, 0x88aec721, 0x523821f5, 0xc721f5a0, 0x096843ae, 0x0d425220, 0x0e290822, 0xf7e4f72f, 0x8b6b15d4, + 0xfacfffff, 0xefffffe2, 0xffff52f8, 0x7b1e05e0, 0xdfffff08, 0xff9b71fd, 0xf5e8d0ff, 0x051000ff, 0x2616821e, 0x00ff0000, 0x82900200, 0x19af221a, + 0x31318299, 0xffd569e0, 0x0080adff, 0x97ffffff, 0xb2ffff04, 0x1a820080, 0xfd77ff2f, 0x079cffff, 0x4000ffae, 0xffff7485, 0x35508283, 0x291c5f00, + 0x8bab088b, 0x8b9b9b9b, 0x9b8b9b08, 0x088bab7b, 0x20828beb, 0xff666630, 0xcccc7a00, 0xb3feffff, 0x6500ff34, 0xbc823433, 0x287f0125, 0x824c00ff, + 0xe0ff3219, 0x00ffcc4c, 0x3b9a9953, 0xeb7b088b, 0x6b07ab15, 0x0d614506, 0x82142e21, 0xd1d32c83, 0x076b08ec, 0x00ff06ab, 0x8234332c, 0x82232053, + 0x2300234e, 0x0a82ecd1, 0x142e2c28, 0x94f70e08, 0x684874f7, 0xf1ff230c, 0x37829a99, 0x6666ee23, 0x49068508, 0x16820661, 0x23126848, 0x48610e00, + 0x82052b58, 0x1100232d, 0x6848b89e, 0x21168305, 0x4382ffff, 0xb1828b20, 0x3433d623, 0x206282eb, 0x07b359f5, 0xe2ff2108, 0x00ffb85e, 0xff00401f, + 0xc435b4ff, 0x21f7ffff, 0xffff0848, 0xfffe7fea, 0x703d3300, 0x33dfffff, 0x2227ec82, 0xffff48e1, 0x826666d4, 0x85068440, 0xddff2116, 0xff224482, + 0x3a8280ea, 0x90c2cc22, 0xb4203582, 0x00223082, 0x3582bd08, 0xff215483, 0x833583e0, 0xecff2368, 0x1e820080, 0x9083ef20, 0x0482e220, 0x78010032, + 0xd4ffff52, 0x00ff9042, 0xffd72328, 0xb81ec9ff, 0xd7211e82, 0x82af82de, 0xffff240a, 0x821f85fe, 0x2292821e, 0x82611000, 0xa1e22178, 0x00229282, + 0x0a82211d, 0x3d83cb20, 0x3d824820, 0xc0080027, 0x0e00ff00, 0x219c82b3, 0x5c82c001, 0x82150021, 0xccff3214, 0x00ffaec7, 0xffcccc20, 0x9a19ddff, + 0x992b00ff, 0x84b1829a, 0x23168206, 0x00ff3eca, 0x0023c883, 0x828e8215, 0x834020dc, 0x990e2235, 0x246e829a, 0x00ff1e45, 0x20c68348, 0x20ec83f7, + 0x2404831d, 0x08666634, 0x217e84ff, 0x83831d00, 0x8287fe21, 0x822b2059, 0xd7ff2773, 0x00ff28dc, 0xb182de36, 0x82280021, 0x36002492, 0x44ff66e6, + 0x2b200518, 0xff218d82, 0x210482ef, 0x3d831d00, 0x2389fe2e, 0x1574fbd6, 0xfffbffff, 0x0700ffbe, 0x0325ce83, 0x00ff3be0, 0x27698211, 0x07200f00, + 0x801700ff, 0x06258383, 0xffff42e0, 0x221483f9, 0x82064107, 0x48a12609, 0xc00700ff, 0x84098201, 0xa00125d8, 0xf2ffff00, 0x02213d83, 0x31288260, + 0xffb89ef2, 0x00c00200, 0xffff087e, 0xff3954e7, 0xe982ffff, 0xcaf0ff23, 0x065f643d, 0x2983fc20, 0x9a990622, 0x2427bd82, 0x00ff29dc, 0x8266e6a2, + 0x4cf82282, 0x824f82cd, 0xf8ff239a, 0x098233b3, 0x82999921, 0x20388304, 0x232983f9, 0x85ebf0ff, 0x66258d82, 0xfcffff67, 0x235e821e, 0x8f989911, + 0x33218382, 0x20448234, 0x28748203, 0x00200600, 0x010d00ff, 0x20638206, 0x23098260, 0x8b018015, 0x01231a82, 0x828b00c0, 0x8220208b, 0x82ff2095, + 0x010023a4, 0x168200e0, 0x21fdff2b, 0xf2ffff06, 0xffffccac, 0x276b83fd, 0xff9a99f2, 0x6666feff, 0xee841382, 0xcdcc7b2d, 0x197d00ff, 0x00ff159a, + 0x82848009, 0xbf0c2240, 0x221b847c, 0x820b00ff, 0xe8ff29fa, 0xff080040, 0x52b8f4ff, 0x2106ca4b, 0x4982ccf4, 0xba83fb20, 0x4983f420, 0x3233fb22, + 0x0a821e83, 0xcc040023, 0x822882ce, 0x0400221e, 0x2023824c, 0x232382f4, 0xcccc0300, 0x0b209982, 0x0021df82, 0x200f8317, 0x216d830c, 0xb482800d, + 0x82800921, 0xfc8b2e9d, 0xffff1514, 0x8b7d7ff6, 0x40f3ffff, 0x82d48283, 0xf4ff221a, 0x21f4825e, 0x7782c017, 0x470b0027, 0x0300ffae, 0x232f82c0, + 0xff34330b, 0x00215884, 0x83bc820b, 0x2558836c, 0xffff4861, 0x1e8320fb, 0x82004021, 0x70bd2109, 0x0983b582, 0xb83efc22, 0x6b269683, 0xe8ffff84, + 0x5c823e4a, 0xe77c3d82, 0x84f62005, 0x04f72177, 0xd3227782, 0x7782b8de, 0x2a1cdc27, 0xe12300ff, 0x23fa8248, 0x08b81e2c, 0x11820685, 0x8484eb21, + 0x00ff2516, 0x8b9a192c, 0x06836b82, 0xff221685, 0x38831edc, 0x674bd320, 0x24068205, 0x14dcffff, 0x2604827c, 0xffffb81e, 0x8366e6d3, 0xb3a0232d, + 0x62827b34, 0xbe5ffc26, 0x60f9ffff, 0xf0269b82, 0xffff42a0, 0x2182befa, 0xde83e720, 0x3c820020, 0x0200ff29, 0x00ff42c0, 0x829a190c, 0x21238209, + 0xed830e00, 0x82a00121, 0x840d20ce, 0xc00721fd, 0x06208382, 0x0026cf82, 0xff7c3f07, 0xed820600, 0xe1060023, 0x21098248, 0x9182707d, 0x56190f22, + 0x8c32de82, 0x0300ffcc, 0xffff68e6, 0x876866ee, 0xccf8ffff, 0x2b8208cc, 0xcdcc8f22, 0xf9227e82, 0x2c82be1f, 0x7e828020, 0xfabef822, 0x79820982, + 0x83f8ff21, 0x3f06264f, 0xffff08ff, 0x207483fe, 0x211e830d, 0x2882bffd, 0x5f820d20, 0x20fdff22, 0x5e217e83, 0x215f82b8, 0x5042e001, 0x00002207, + 0x22158260, 0x8300c001, 0x801521da, 0x0d221683, 0xcf829002, 0x0320ab83, 0xf9245583, 0x8f0800e0, 0xc1267d82, 0xfcffff48, 0x8d849819, 0xf0ffff22, + 0xe8289783, 0x0e089999, 0x1602ffaf, 0x002c0c82, 0x150080b4, 0x331900ff, 0xf3ffff30, 0x00217882, 0x2714820f, 0x3433e6ff, 0xe3ffff8b, 0xff25b982, + 0xee9cfbff, 0x220c8207, 0x823473dc, 0x828220db, 0x33df2563, 0xddffff32, 0xff23b482, 0x825278f8, 0xd1d934b4, 0xf7ffffec, 0xffff6abc, 0xff5238db, + 0x78fe1500, 0x82f4ffff, 0x23002323, 0x1e82f468, 0xfef6ff28, 0x1a0000ff, 0x2482ff7e, 0x09838020, 0x09838020, 0x09820420, 0x82021b21, 0x67fa271e, + 0x1100ff4a, 0x9b82501d, 0xffce4c27, 0x34b30b00, 0x24d38279, 0xcccc30ff, 0x21b38206, 0x7a82291c, 0x8f42f022, 0x6e215182, 0x27de8214, 0xffff6766, + 0x089002ef, 0xd4214282, 0x2204827b, 0x8205c275, 0x3333261a, 0x97dcffff, 0x2280850a, 0x8202eaff, 0xd1d926a4, 0x0800ffeb, 0x83298342, 0x070023aa, + 0xbe833c8a, 0x00ff8f31, 0x8bcecc20, 0x802300ff, 0x00ff0800, 0x82126304, 0x1c002ddb, 0x00ff8836, 0xff48e10f, 0xcccc1900, 0xdb820482, 0x840c0021, + 0x60092220, 0x21258200, 0x318200c0, 0x00800d26, 0xa0f6ffff, 0x80820f85, 0x82c0e621, 0x8225820a, 0xb81e21b8, 0xb3213482, 0x22248233, 0x83cd4c1c, + 0x66662156, 0x23275683, 0x00ffce8c, 0x45717d17, 0x00210572, 0x22308322, 0x82ae8707, 0x2e262220, 0x2b9d8214, 0x00ff9643, 0xff5ccf24, 0x7eeae9ff, + 0xcc21f982, 0x82c584cd, 0xab05221e, 0x21fb8285, 0x94829ad9, 0xda82b320, 0x9a19f424, 0x16828b9d, 0x3233cf28, 0x1100ff06, 0x6882d8e3, 0x70bd0f22, + 0x91253282, 0x0500ffec, 0x22278299, 0x8270fd10, 0x2b002820, 0x0000ff86, 0x82053e8a, 0x22c8831a, 0x82f66823, 0xb0c72561, 0xfd1500ff, 0x75832e82, + 0xbdf7ff22, 0x22202983, 0xff233e82, 0x82c475f8, 0x23d6839f, 0x8b3233df, 0xf2837c82, 0x2207ef41, 0x82dfafe3, 0x981925d9, 0x4ce6ffff, 0xe6259882, + 0xffffd0cc, 0x212084f3, 0x148299f6, 0x8233fb21, 0xf2ff2fee, 0x00ff0180, 0xff686609, 0xcc4cfbff, 0x97820e08, 0xcdcce429, 0x2bffff15, 0x8207ff7f, + 0x83f12050, 0x9e0b2df1, 0x00ff7fb8, 0xff48e10e, 0x0040ffff, 0x3025a582, 0xffffecd1, 0x217682fd, 0x14836800, 0x68e6f525, 0x833b00ff, 0x66d731fc, + 0x01ff0866, 0x0734b30a, 0x66c5ffff, 0x2700ff66, 0x9a25fd83, 0x00ff0a97, 0x2109830a, 0xe982d9cd, 0xcdcc0226, 0xefffff08, 0x00255983, 0xffff66e6, + 0x83e382f2, 0x226e8298, 0x826766f0, 0x33e2273f, 0x1b00ff34, 0x86823333, 0xf6e8cd22, 0x26376982, 0x9affffe9, 0xffff3eca, 0xffc560f5, 0x3233c6ff, + 0x61d8ffff, 0x828a0848, 0xd7e3218f, 0x8205c54a, 0x826620e4, 0x83ff2040, 0xf5fe335b, 0xff070080, 0x3e0a3c00, 0x632800ff, 0x6800ffd8, 0x8082f6a8, + 0xffb85e2c, 0xcccc3000, 0x850200ff, 0xcf82081e, 0x00297b82, 0xffecd100, 0x9a990b00, 0x22f88297, 0x8232330e, 0x80d42216, 0x23f88201, 0x99990f00, + 0xc2839982, 0xe7820c20, 0xccefff23, 0x216782ce, 0xb8829a19, 0xcccc7d37, 0xc08b15eb, 0x8b56b660, 0x608b5608, 0x08568b60, 0x60b6568b, 0x963c1ac0, + 0xf70e2908, 0x1554f84c, 0xe61e00ff, 0x00239182, 0x829a1919, 0x14ee219b, 0xe1259c82, 0xfc08ec11, 0x215d8224, 0x1484e1ff, 0xff218082, 0x820483e6, + 0x828b200e, 0x19e32259, 0x2d25829a, 0xff3333e8, 0x66e61500, 0x1c00ff88, 0x16823433, 0xb382fa20, 0x99feff22, 0xfa204682, 0xff258a83, 0xffffcc4c, + 0x05a948fa, 0x2007e561, 0x182b8299, 0x8208e4a8, 0x830720ca, 0x450127b8, 0x0700ff1f, 0xf0823433, 0xe5825120, 0x83990621, 0xd7e122bd, 0x82f0820a, + 0xeaff281e, 0x00ffeb91, 0x8232331d, 0x7022202e, 0x1f2005b9, 0x00268b82, 0xffc3b512, 0x6d821b00, 0x0f1b0028, 0x0c00ff5c, 0x8282cdcc, 0x4861f725, + 0x820a00ff, 0xfaff221e, 0x226b82d9, 0x8233b30e, 0x190e2335, 0x0682089a, 0x82b31e21, 0x97152161, 0x82055e5e, 0x83d12087, 0xce4c216b, 0xfe223582, + 0x035c146e, 0xf6282107, 0xe6230982, 0x83918b66, 0xf01d2531, 0x1400ffa4, 0x19226283, 0x6c82d823, 0x06244083, 0x8e0870fd, 0x11203d82, 0x17273d82, + 0x00ffcdcc, 0x8228dc15, 0x05f9450e, 0x2182c720, 0x11ceff24, 0x2c8315ec, 0xffff3225, 0x859002f9, 0xe6ff2f40, 0xff8b28dc, 0x5c0fe2ff, 0xff858b08, + 0xec82ffff, 0x19faff24, 0x8d47ff9a, 0x80fa2305, 0x43820800, 0x82cccc21, 0x32b32131, 0x72825282, 0x66e6ff28, 0xffff8b68, 0xe35e4ce1, 0x83d28405, + 0x4cf12a04, 0xf7ffffcd, 0xffffce4c, 0x82d682f5, 0x98192967, 0x33f3ffff, 0x1200ff33, 0xe4227c83, 0x35826666, 0xf184e020, 0x83ddff21, 0x83ea2051, + 0xcce2214c, 0xe1203082, 0xf4220e83, 0x6b829a99, 0x40830220, 0x6666f92c, 0x4c0100ff, 0xf8ffffcc, 0x3582cccc, 0xe54df820, 0x83dc2005, 0x83e32047, + 0xf1a91816, 0x05c84109, 0x80260582, 0x0000ff00, 0x098234b3, 0x00295182, 0x08666601, 0xe3ffff88, 0x254382cc, 0xff3233e8, 0xd383eaff, 0x9a19e324, + 0xba82088b, 0xff220682, 0xb482e6ff, 0x83190021, 0x1e002e0a, 0xf80866e6, 0xff8b0724, 0x14ee1e00, 0x821483ff, 0xec112104, 0x3d410e82, 0x05997305, + 0x58821720, 0x23eaff24, 0x57828ed8, 0x0814ee34, 0xa500ff0e, 0x34f86666, 0xb500ff15, 0xff063433, 0xab832800, 0x83240021, 0x38e622c0, 0x06364852, + 0x707dd922, 0x2320d582, 0x9b308283, 0xff05717d, 0x34331700, 0x66f6ffff, 0x1000ff67, 0xff23e582, 0x829919e9, 0x4ce524e0, 0x823b08cd, 0xe8ff217f, + 0xf320dd83, 0xeb20ab83, 0xec234783, 0x828066e6, 0x66c722b0, 0x17015766, 0xce566b20, 0x07bb2417, 0x180694fb, 0x2108abdf, 0x4e18f1ff, 0x36840d6c, + 0x36139f56, 0x993800ff, 0xffff079a, 0x96b8deec, 0x21f3ffff, 0x1400ff48, 0x828b32b3, 0x34b323b7, 0x8582db08, 0x821a0021, 0x10002749, 0x00ff295c, + 0xc582e616, 0x00401727, 0x990900ff, 0x26e58399, 0x00ffa430, 0x828f8264, 0x0d2208e5, 0x00ff5278, 0xff908226, 0x7b542400, 0xc71900ff, 0x2800ffae, + 0x088bcdcc, 0x4b8b078b, 0xf2ffff15, 0xf6826766, 0x66e6f326, 0x66f7ffff, 0xfb220482, 0x6d820080, 0x08343325, 0x83e5ffff, 0x66b52914, 0x01ff0566, + 0x06cccc25, 0x00261085, 0x059a994a, 0x2683ffff, 0xcc0c0023, 0x262b82cc, 0x00ff68e6, 0x839a9908, 0x8b66254a, 0x4affff08, 0x00252b83, 0xfb9a992a, + 0x185f8244, 0x20142847, 0x19be826b, 0x2014372b, 0x0ce718eb, 0x82ab2017, 0x18002031, 0x2613324a, 0x1cfb062b, 0x82ab156b, 0x2bd26a37, 0x41186b20, + 0x41180cc3, 0x0022116a, 0x2219c00a, 0xd46a0732, 0xbbe42105, 0xf221cb82, 0x10a918b3, 0x22319307, 0x83ff34b3, 0x00ff2416, 0x6ecc4c0d, 0x088305cf, + 0x0a00ff22, 0x5e181882, 0xcc20145f, 0xff201b85, 0x08265683, 0xdb0e066b, 0x026cf4f7, 0x2a935805, 0x6606eb21, 0x5c750519, 0x05c55810, 0x09675018, + 0x20085e75, 0xd05c189b, 0x22ac820e, 0x19dcffff, 0x2137cb41, 0x7f820774, 0x824c2321, 0xa61c25ca, 0x1c00ff66, 0x2329eb83, 0x088b9a59, 0xc4f7069b, + 0x41ce832b, 0x4b1813b4, 0x6b2216e7, 0x5c186b07, 0xbe6e0fa5, 0x0700220e, 0x24931833, 0x0b4a420e, 0x8a821a84, 0x8b227282, 0xe918ff08, 0xab211555, + 0x58931807, 0x23c98218, 0xffcdcc08, 0x2007b862, 0x28a58533, 0xab066b08, 0x4bb4fb07, 0x059b4215, 0x746f9082, 0x0d8b6f08, 0xcd213782, 0x261b84ff, + 0x3333f7ff, 0x832b088b, 0xf62822cb, 0x2150828b, 0x04820ad7, 0xcb90cc20, 0x84f62821, 0x2fa98216, 0x088b0ad7, 0x44f7ef0e, 0xff154cf8, 0x9a990600, + 0x05315982, 0xffffcccc, 0xff66e6fc, 0x00800200, 0x02f9ffff, 0x32d28290, 0xff67661d, 0x3e0ab6ff, 0x4c00ff05, 0x00ff9919, 0x82b81e17, 0x4c06250a, + 0x0100ffce, 0x06202a83, 0xfd2c3483, 0x00ffd6e3, 0xff9a1904, 0xbadefaff, 0x00203482, 0xff2a3f83, 0x00ff846b, 0xff666600, 0x0482ffff, 0x5e250986, + 0xffff08b8, 0x233882ee, 0x90c2f7ff, 0x3c068f4b, 0xffd863f3, 0x32b3f4ff, 0xa1efffff, 0xff620848, 0xccccc4ff, 0xe4ffff05, 0xffff34b3, 0x205483f7, + 0x284e83e9, 0x8366e6e9, 0x19e2ffff, 0x2340829a, 0x419919ec, 0xdc272182, 0xffff33b3, 0x820080df, 0x33fb210a, 0xfb200a82, 0xf8232783, 0x828a66e6, + 0xd7232187, 0xcc21c682, 0x222c82cc, 0x820a17fa, 0x2272830a, 0x82146efc, 0x235182eb, 0xc3750000, 0x082af584, 0x970500ff, 0x4f00ff0a, 0x44826666, + 0x8259b121, 0x330c22e0, 0x230a8234, 0x8c1f85f9, 0xca214582, 0x26d7827f, 0xffffcccc, 0x82c18afe, 0x67662130, 0xfe214f82, 0x2214828a, 0x82666606, + 0x04962154, 0x84821482, 0x83050021, 0xb303380e, 0x00ff0834, 0xff5c8f41, 0x9a192d00, 0xd8ffff05, 0x00ff8f82, 0x82b81e45, 0xc0fc220a, 0x2b6a8200, + 0x00ffa4b0, 0xffcd8c00, 0x98190700, 0x98835882, 0xba1e0522, 0x04223482, 0x1e827b14, 0x82462121, 0x82cc204e, 0x1c02221e, 0x2109822a, 0x77821f45, + 0x0033ef83, 0xff66264c, 0x48e1e8ff, 0x1d00ff05, 0x00ff6766, 0x82c2f549, 0x8202200a, 0x060023ee, 0x398270fd, 0x0021a282, 0x26d88303, 0x8b9a9906, + 0x828b8b08, 0x33d0321d, 0xa4ffff34, 0xff157c54, 0x98998700, 0x91dcffff, 0x211582ea, 0x1582b320, 0xad83f620, 0x14831720, 0x9a99e322, 0x1383c682, + 0xcd4cde22, 0x06278782, 0xffff68e6, 0x829919ac, 0x4e112029, 0x002907a1, 0xff646608, 0x3433e9ff, 0x22058285, 0x82089a99, 0x216e824a, 0x95457cff, + 0x68662505, 0xedffff7a, 0xf62c4b83, 0xffff32b3, 0xffd0ccef, 0x34b30300, 0xf0202582, 0x00231482, 0x829a1904, 0xe6ee22fd, 0x82ee8266, 0xf5ff210f, + 0x11200983, 0x04237583, 0x829c0080, 0x4c082371, 0x2182aace, 0x33b30827, 0x334200ff, 0x250a8234, 0xffcdccf7, 0x3784e1ff, 0xe182fa20, 0x23052d42, + 0xffcc4cef, 0x7a203c83, 0x83834783, 0x1a82f020, 0x67205d88, 0x19845d8c, 0x11216283, 0x22298219, 0x82332300, 0x6683285a, 0xff910567, 0x82661600, + 0x83122088, 0x830f206b, 0x83152025, 0x84032025, 0xe62f2125, 0x45224482, 0xf9823333, 0x32331325, 0x831b00ff, 0xb3222aa8, 0x0c00ff34, 0x00ff16ae, + 0x26298220, 0x0040f7ff, 0x828b8b08, 0x82ef20a2, 0xc2ff273c, 0xff15842b, 0x5183f9ff, 0x82cc0121, 0x19f92a9d, 0xfdffff9a, 0xffff6866, 0x204082fc, + 0x23bb82ff, 0xdfffff08, 0xff234182, 0x82cc4cd1, 0x7fc92356, 0x3b8255fe, 0x2182fb20, 0x66390023, 0x200a8266, 0x214682ff, 0x78820500, 0x82fbff21, + 0x050023de, 0xc15b9999, 0xcc012206, 0x203b82cd, 0x221e8378, 0x82cd4c24, 0x999c2829, 0x6cffff98, 0x821534b3, 0xcecc218e, 0x0f826182, 0x820d0021, + 0x07002166, 0x5383c284, 0xcecc0c26, 0x0300ff08, 0x0c203483, 0xf8208f83, 0x0d209983, 0xf3209483, 0x18822883, 0xf2225382, 0x2382ce4c, 0xff251982, + 0xff33b3f3, 0x212383ff, 0x7783fcff, 0x3433f322, 0xfc201e82, 0xff203d82, 0x57832e84, 0x82f2ff21, 0x0573476b, 0x9a99fc26, 0x0301ff08, 0xec22cd83, + 0xf7829819, 0x48832f82, 0xf222ed82, 0x488766e6, 0x48833d86, 0x48829682, 0x82ff3421, 0x83ba82a0, 0x21488623, 0xa5820080, 0xd0cc0c22, 0x9a21c483, + 0x20c482ff, 0x82238330, 0x85032009, 0x82cc20c4, 0x200a861e, 0x205783ce, 0x21238364, 0x4c85ff32, 0x6666032a, 0xf9ef0e08, 0x1514f714, 0x7a0bdf48, + 0xde230ec6, 0x850634b3, 0xd2ff213a, 0xd8208783, 0xdd209783, 0xd02cf483, 0x088b6866, 0x66d0ffff, 0xffff8b66, 0x00211683, 0x20208322, 0x211b82f8, + 0x5b822d00, 0x7dffff24, 0x3b846766, 0x91ff6721, 0x8a66203b, 0x3d8a223b, 0x223b86ff, 0x86ffd763, 0xabde223b, 0x7d651885, 0x04f72717, 0x00ff8b07, + 0xe782191b, 0x5ccf1027, 0x191700ff, 0x26048299, 0x00ff00c0, 0x82676609, 0xa32921f1, 0x68324582, 0xff05cc0c, 0x7b940e00, 0x732400ff, 0x2300ff34, + 0x2482ec51, 0xff66e624, 0x357d2700, 0xe6b52105, 0x00239c82, 0x8232331d, 0xb31a214b, 0xf225f582, 0x00ff70bd, 0x2c558213, 0xe23ae9ff, 0xffffef08, + 0x05ae0783, 0x83fb82ca, 0xcc302734, 0xc9ffffcc, 0xea82cd4c, 0x33b3bf36, 0xffffff08, 0xff079a19, 0xcc4c2bfe, 0xff1574f7, 0x66e6f2ff, 0xf4221982, + 0x2e85cd4c, 0x19fbff24, 0x24827e9a, 0x33b3e127, 0x19b4ffff, 0x0889829a, 0x33b37020, 0xff07eb06, 0xcd4ccbff, 0x6400ff06, 0x152b33b3, 0x66ad00ff, + 0xffff0666, 0xdfceccbc, 0xb9418505, 0x05d44305, 0x66660425, 0x4bf7ffff, 0xae2c0565, 0x2b06cccc, 0xfd00ff07, 0x64fbcc4c, 0x01203382, 0x0029ab82, + 0x8c66e605, 0x800400ff, 0x23bc8200, 0x089a9905, 0x78160d78, 0xaa82160b, 0x6182fa20, 0x19000023, 0x060b4a9a, 0x82990221, 0x19fa2b09, 0x00ff089a, + 0xff989906, 0x1e83edff, 0xcecc1125, 0x82f2ffff, 0x14002119, 0x8305bf4b, 0x00ff2106, 0x00211683, 0x8320830d, 0x1200212a, 0xfb227e82, 0x99848bd4, + 0xddff3321, 0x86a48299, 0x95cd2099, 0xffcd2199, 0x9a219987, 0x259984ff, 0x94f7af0e, 0xfc7554f8, 0x0a86700c, 0x0754fb28, 0x00ff069b, 0xa5189930, + 0xff210799, 0x210a83d8, 0x9d19cfff, 0x7b303495, 0xff0733b3, 0x0080dfff, 0x330a00ff, 0xe8ffff33, 0x1e290983, 0xff8bcd4c, 0xcdcc2300, 0x08044b08, + 0x33070024, 0x0485ff34, 0xcccc0828, 0x069b088b, 0x238207bb, 0x0ad70822, 0x07241586, 0x00fff628, 0x2d100649, 0x0ad7f8ff, 0xf7ffff8b, 0x5b08f628, + 0x33b2ab07, 0x5583ea83, 0x134e6585, 0x33f72406, 0x826b0834, 0xdcff217e, 0xff21b287, 0x060a48e1, 0xf5ffff22, 0xff24b682, 0xcd4c84ff, 0xd8202083, + 0xff23b582, 0x82ccccdf, 0x820483e2, 0xf79d190e, 0x096b6027, 0xfb067b23, 0x176a6424, 0x2116497f, 0x0744b4fb, 0xff8b2117, 0x21143464, 0xad8214f8, + 0x59230022, 0x159e9f19, 0xc5ff2808, 0xffff9a99, 0x156626ac, 0xfd8fffff, 0x9fffff70, 0xff0534f3, 0xf6e8faff, 0xb3fbffff, 0xfeffff32, 0xffff852b, + 0x5068e6f8, 0xff2405ac, 0x0832b3f9, 0x542b0a82, 0xf9ffff7b, 0x00ffcdcc, 0x82e2fa05, 0x22098428, 0x828bcdcc, 0xb33a291a, 0xff720634, 0x9a19b5ff, + 0xfd224682, 0xec5733b3, 0x02002105, 0xf8246683, 0x87910080, 0x05272382, 0xff8766e6, 0x82190700, 0x80002a92, 0x0600ff00, 0x00ffcc4c, 0x23598204, + 0x05eb04f7, 0x18835382, 0x824c0421, 0xcc01215d, 0x27831882, 0xb3fdff23, 0x22278334, 0x86ff08cd, 0x3233220a, 0x21338285, 0x5f823433, 0x82cc4c21, + 0xc6ff2a78, 0xa4063333, 0xe64a00ff, 0x20428266, 0x223d8302, 0x822adc06, 0x6666212d, 0x80216a82, 0x212d8300, 0x3e821e05, 0x3382f920, 0x02040023, + 0x069a4490, 0x3e8aff22, 0x9d83ee82, 0xea51fb29, 0x0e078b08, 0x83f101ff, 0xe6e1277f, 0xffff1566, 0x3d82e62f, 0xcb84d020, 0xd0a2f62c, 0x5d0900ff, + 0xf3ffff30, 0x7a8278be, 0x820ead21, 0xe1ba2209, 0x206282ff, 0x22568270, 0x820a97f4, 0xf8f5210a, 0xcc291482, 0xfbffffcd, 0xffffbc52, 0x225683f6, + 0x82f0a7f6, 0xee2f221e, 0x224d8214, 0x820514ee, 0x60a52115, 0xfb211a86, 0x20328252, 0x2a2e82f3, 0x0d000000, 0x99f4ffff, 0x85ff0899, 0xbdf3220a, + 0x20628370, 0x214d8201, 0x768272bd, 0x82a05a21, 0x66a62132, 0x8c821e82, 0xe4829684, 0x9e5e0931, 0xc5f5ffff, 0x0c00ff20, 0xffff3333, 0x823233fc, + 0xcd4c2209, 0x2325828b, 0x8b90420c, 0x42210c82, 0x2045838e, 0x21408250, 0x04829a59, 0x865e5a21, 0x84002040, 0x090023d2, 0x15841c5a, 0x92202483, + 0x41212e82, 0x823485cc, 0x19ff21af, 0x0b223082, 0x56876766, 0xf5226083, 0x2e82cecc, 0x85826620, 0x66a9ff2b, 0xe2ffff66, 0x2b159a19, 0x22d18237, + 0x82c235f5, 0x7a742b9e, 0x42f0ffff, 0x0800ff90, 0x47820890, 0x2c030d22, 0x33296d82, 0xff0752f8, 0x4821bfff, 0x22ea8206, 0x825bf9ff, 0x000025b6, + 0xeeffff07, 0x5c069559, 0xff230526, 0x820080ed, 0x590684b6, 0xe6640690, 0x07db2109, 0x7b184d82, 0xff261338, 0x9a195f00, 0x1e83bf06, 0x82d90d21, + 0x63102aae, 0x0700ffd8, 0x00ffd623, 0x2504820a, 0x3e0af7ff, 0x9e82eb08, 0x45050023, 0x24c6821e, 0x00ff52f8, 0x27d58201, 0x9a99fbff, 0xfbffff8b, + 0x8205d75c, 0xffff2406, 0x8266e6fe, 0x9a992110, 0x80312582, 0x0e088800, 0x8001ff2f, 0x15ebcc4c, 0x332300ff, 0x29b78234, 0x00ffcccc, 0xff00801c, + 0xa682e3ff, 0x82055f4e, 0x15375241, 0xcc4ce822, 0xeb381b82, 0x00ffce4c, 0x8066e60c, 0x191300ff, 0xffff089a, 0x06cccc2e, 0xecffff80, 0xeb256983, + 0xffff3d4a, 0x238a83f3, 0x8b5c4fe8, 0x2d541c82, 0x20c38207, 0x0b2d541c, 0x2605465a, 0x00ffb8de, 0x8232b314, 0x48212849, 0x00ff0896, 0x513433d1, + 0x6b181749, 0xff2416f7, 0xa4b01700, 0x14221b82, 0x7882c3b5, 0x88824582, 0x85b8de21, 0x9606214a, 0x62865884, 0x6c830c20, 0x95827682, 0xb7180020, + 0x2246091b, 0x41f7880a, 0xb14b060e, 0x00002305, 0xc78232b3, 0x3433d928, 0x33bbffff, 0x99430534, 0x82f72006, 0x02002824, 0xffffcc4c, 0x820080f6, + 0xe6f52339, 0x06850866, 0x8305c543, 0xffff2316, 0x2082ccfb, 0x8f822a82, 0x0a832620, 0x9a19bc27, 0xdffeff05, 0x3b4b82b3, 0x156666f7, 0xb30900ff, + 0xfaffff33, 0x00ff6666, 0xff9a1908, 0x68e6f7ff, 0x990500ff, 0xf6220982, 0xc486cc4c, 0x0020dc82, 0x20611b82, 0x84098205, 0x8298200f, 0x83db2092, + 0xcc3f2b82, 0xffff05ce, 0xff9899fe, 0xb3550000, 0x19ff2108, 0xfe224182, 0xea829a99, 0x1593be18, 0x23254382, 0x00ffcd4c, 0x857e821c, 0x630e8204, + 0x012209b6, 0x21826666, 0x68660125, 0x82ffffff, 0x00ff22d7, 0x826a8924, 0x216a8210, 0x7582cc4c, 0xcccc2e23, 0x20bd8506, 0x83ae82ff, 0x836620bd, + 0xff682104, 0xcd200e82, 0x08231884, 0x82ffff8b, 0x0e053225, 0xf714f7ef, 0x14f815f4, 0x0794fb06, 0xa4f706cb, 0x255f8207, 0xffb85e1a, 0x6482eaff, + 0xa115002c, 0xe5ffff48, 0x088b9899, 0x518234fc, 0x47a1e522, 0xea203782, 0x5e211e84, 0x250a82b8, 0x0848a1e5, 0x3883a4fb, 0xf8079428, 0x15b4fb84, + 0x2682f4fc, 0x0040f722, 0x5c1a1b82, 0x7b200ed1, 0xff235982, 0x8200c0dc, 0x220482db, 0x8240e3ff, 0x82232009, 0xf8082528, 0x00ff0694, 0x19850983, + 0xc01c0022, 0x10833d82, 0x829b0821, 0x08002432, 0x50ff34b3, 0x4c210650, 0x065050cc, 0xfdfeff2d, 0x00ff66e6, 0x15cccc61, 0x820300ff, 0xfcff230a, + 0xc3459a19, 0xfeff2105, 0x8b210986, 0x82108408, 0x210527ce, 0x0100ff48, 0x2a8220f0, 0x82f6e821, 0xf0e72a04, 0x05bbbb08, 0xcf0700ff, 0x210482e0, + 0x228221d0, 0xdfaf0c22, 0x30206482, 0x07242282, 0x5b085ccf, 0xff211d82, 0x260d84f8, 0xffff20d0, 0x838e57f3, 0xa43021ce, 0x2f222282, 0x288508e0, + 0x2ff8ff23, 0x211582e0, 0x338450f3, 0x1483e020, 0x7182a420, 0x2adc2128, 0x28deffff, 0x058205f6, 0x87d82321, 0x23f8220a, 0x212082d4, 0x3083d022, + 0x82ce4c21, 0x22b28374, 0x823233f8, 0x33a4284b, 0x7c00ff34, 0x8515ce4c, 0x07002356, 0x718e22d0, 0x5b08de23, 0x224e825b, 0x822130f8, 0xdf2f2122, + 0x21207484, 0xcf204382, 0xa422b284, 0x1d82bb08, 0xfa030028, 0xfcffffe1, 0xf383281c, 0x41ff9921, 0x01412504, 0x8b202508, 0xaf0c00ff, 0xcd84c384, + 0x97825c20, 0xf528de28, 0xd82100ff, 0x05820594, 0x8229dc21, 0x0ad72104, 0x06220a82, 0x3582a4f0, 0x8390c221, 0x32b32230, 0x310b8284, 0x0e08cecc, + 0x80e800ff, 0xba01ff00, 0xff153ad4, 0xdb820e00, 0xe3060028, 0x1100ff94, 0x27823433, 0xff2e0f83, 0x086c1cf9, 0x99da00ff, 0x9affff9a, 0x488292f8, + 0x30820820, 0x2606b441, 0xffff6666, 0x820080f7, 0x200582d7, 0x22068208, 0x47ceccf5, 0x1082061d, 0x87201b84, 0x25209082, 0x3f822783, 0xffff0524, + 0x078219f1, 0x8219f921, 0xccee22e7, 0x833082cc, 0x0600230f, 0x258367e6, 0xff146e26, 0x01006500, 0xf7232582, 0x828f0c82, 0xdf8f2347, 0x6d8200ff, + 0x0a228982, 0x5e823233, 0xff230c83, 0x856f0500, 0x261b8216, 0x00ff357e, 0x8366e603, 0xec91219f, 0x07253c82, 0x01ff056e, 0x22aa8309, 0x8293f81a, + 0x20aa86d0, 0xa9348299, 0x892620aa, 0xff9822a6, 0x20a68cff, 0x20a68568, 0x82a2b0f0, 0x350033df, 0x00ff3333, 0x05999918, 0xf89700ff, 0xb9ffff52, + 0x0a82cecc, 0x98831720, 0x9819f523, 0x83e582a6, 0x0a002b0b, 0xf70868e6, 0x4600ff2c, 0x1e823233, 0x34333527, 0x66e7ffff, 0x28718267, 0xffcccc32, + 0x676652ff, 0x201d9015, 0x37954166, 0x6622ead3, 0xea87ff08, 0xeaa29a20, 0x0e078b27, 0x54f744f7, 0x27fe8215, 0xff33332c, 0xcdcc2300, 0x4b180486, + 0x7e64089e, 0xdcff2a07, 0xff8b3333, 0xcdccd3ff, 0x21068408, 0x1182ffcc, 0x04863420, 0xccccd324, 0x1c84088b, 0x28821b82, 0x220b576a, 0x1894f7db, + 0x210e5467, 0x258286ab, 0x7a54ee22, 0xdd373182, 0xff079a59, 0x66665000, 0x82f2ffff, 0x3f00ff8e, 0xffff0080, 0x4d3e8ac0, 0xff23050a, 0x829a99af, + 0xb32223d0, 0xe26f0634, 0x218a830e, 0x8a844cee, 0x184cee21, 0x2511fd74, 0x4cddffff, 0x538206cc, 0xff9a9922, 0x53824483, 0x04835884, 0x18845382, + 0x24840820, 0x21175359, 0x5e82ffff, 0xf125a682, 0x00ff33b3, 0x08ed6f0e, 0x8200ff21, 0x8507208c, 0x0d002153, 0xc022b683, 0xb6863d8a, 0x8f82f222, + 0xd684ca84, 0xf84b9920, 0x7053831c, 0xcd20052d, 0xab22d882, 0xe5838b85, 0x8267a621, 0x7d0d22e5, 0x82448471, 0xc3752153, 0xc2200483, 0x0d220e86, + 0x2484727d, 0x4d186620, 0xfb2417e4, 0x1594fb14, 0xb931b182, 0x00ffcc4c, 0xffcd4c39, 0x34b3c6ff, 0xb34600ff, 0x205d8333, 0xa7021a46, 0x82cd840a, + 0x8b082110, 0x34201e83, 0x39202886, 0xff203782, 0x2d823c82, 0xcd200682, 0xc6204982, 0x4483fb82, 0x08295485, 0x14f9ef0e, 0x331c00ff, 0x26658334, + 0xff00c0c2, 0x8280c1ff, 0x84d32004, 0x82332009, 0x1022086a, 0xff08b8de, 0x5278c4ff, 0xe10f00ff, 0xffff0548, 0xff48e1d5, 0x48610b00, 0xdee2ffff, + 0x2400ffb8, 0x7182b81e, 0x48212922, 0x002bc882, 0x00ff7a14, 0x051e8557, 0x825500ff, 0xc6ff2325, 0x0a8200c0, 0x82a00321, 0xa0fd2450, 0x628c9000, + 0x10820678, 0x08212c82, 0x05fa61e0, 0x8207eb54, 0x908a2215, 0x053e6eff, 0x00600222, 0x58217482, 0x225f825e, 0x82e1ba6f, 0x66582774, 0x90ffff66, + 0x0a823333, 0x8240fe21, 0x82fe204e, 0xfeff213c, 0xfe21a483, 0x230e8220, 0x8900a0ff, 0x06823082, 0xfdffff22, 0x00221a82, 0x15826000, 0x01200984, + 0x40202e84, 0x00204f82, 0xff227183, 0xc482a1f2, 0x83010021, 0x21498335, 0x49860100, 0xffff8d22, 0x97823e82, 0x50860220, 0x0982ac82, 0x20088b62, + 0x823383ff, 0xd955271e, 0x3900ff9a, 0xb682ec51, 0x04080031, 0x80a8ffff, 0xff8b0500, 0xb8ded6ff, 0x83e2ffff, 0x83db20f4, 0x83d52004, 0x9ef4210e, + 0x23073a41, 0xb81ef0ff, 0xc127ba82, 0xffffaa3f, 0x412a1cef, 0x002c0564, 0x8bcc4c2c, 0x333d00ff, 0x958b0834, 0xa8825e82, 0x82090021, 0x0200273c, + 0x00ff00a0, 0xb283c009, 0x0a831520, 0x1e455136, 0x682200ff, 0x4d00fff6, 0x00ff66e6, 0xff71fd2d, 0x66e64700, 0x16228c82, 0x1982b91e, 0x9948a129, + 0x801c00ff, 0x828bb700, 0xae262212, 0x26c98214, 0x00ff52f8, 0x82cd4c1f, 0x9a993192, 0xdbffff8b, 0xff089a99, 0x66e6c3ff, 0x2000ff07, 0x15226283, + 0xc08252f8, 0x82850421, 0x07032658, 0x0200ffae, 0x22d58299, 0x8266e604, 0x6605218f, 0xaa235983, 0x82079a99, 0xe008210c, 0x07218a82, 0x211c8219, + 0x09822007, 0x21820820, 0x069b0824, 0x231900ff, 0xff2214ab, 0xcf5c55ff, 0xa0fa2105, 0xc5832b82, 0x23052d65, 0x88008004, 0x20209982, 0xff234b82, + 0x82cd0cea, 0x193c2278, 0x225d8399, 0x82486124, 0x0a572ba6, 0x5e1d00ff, 0x2600ffb8, 0xc18348a1, 0x82192b21, 0x0e0021b2, 0xff22ea82, 0x488280e3, + 0x4621162d, 0x5eddffff, 0xffb908b8, 0x821eb8ff, 0x68222b27, 0xb2fffff8, 0x00ff7c14, 0xd6829715, 0xccccae23, 0x06e75608, 0x162ef62a, 0x330100ff, + 0xf6ffff34, 0x812a4482, 0x34f70e08, 0x971514f7, 0x6d827b06, 0x83f7ff21, 0x18c683c1, 0x200a8178, 0x18cb8cb3, 0x220ae549, 0x8297079b, 0x6241181a, + 0x0a5d6909, 0x8274f721, 0x0660694d, 0x8e829e20, 0xc5820e20, 0x61eeff22, 0xa249bb82, 0x20e68305, 0x83bd82f8, 0xffff224d, 0x228882f7, 0x85064b08, + 0xffff2108, 0x7f831883, 0x10828b20, 0x08002029, 0xffff077b, 0x826666ee, 0x99f1210d, 0x82051472, 0x214b820a, 0x6483fb08, 0xff241a83, 0x66660e00, + 0x7205a34d, 0xf729055c, 0x1514fbc4, 0xc0feffff, 0x31a08200, 0xad34731e, 0xcc1200ff, 0x2c00ffcc, 0xff8bcccc, 0xaf603100, 0x82692005, 0xa9ff227f, + 0x219d82de, 0x57821956, 0x82219621, 0x074b269d, 0xa14600ff, 0x27248248, 0xffb85e39, 0xb89ec6ff, 0xb9236b82, 0x85084861, 0x86118406, 0x23158204, + 0xa4fb088b, 0x179a4b18, 0xd6823082, 0x84059d76, 0x080027d1, 0x088b00e0, 0x4d4174f8, 0x160d5417, 0xabfcfb25, 0x8264f715, 0x18042034, 0x200875b2, + 0x09217200, 0x72079b21, 0x1344052a, 0x23188206, 0xa0fbffff, 0xfb206782, 0xff233282, 0x8247a1fb, 0x83fc2086, 0x7ab318c9, 0x187b2009, 0x210901ae, + 0x378248a1, 0xff666636, 0xb95e0400, 0xef0e088b, 0xd4f7b4f7, 0xff076b15, 0x66e65000, 0x09227182, 0x5d8266e6, 0xcecc0922, 0x2305074d, 0x66e60800, + 0x80325d82, 0x00ff0800, 0xff008032, 0xcccce6ff, 0xff3bf705, 0x07822300, 0x1200ff2f, 0x00ff9819, 0xff68e603, 0x9c990c00, 0x05f56aff, 0xccccf334, + 0x19f2ffff, 0xffff0898, 0xff9a9949, 0x686631ff, 0x11827e05, 0xff323324, 0x7882efff, 0x19f8ff22, 0xed271582, 0x088b9a99, 0x83fcfeff, 0xf0ea1874, + 0x00ff2109, 0x2005d666, 0x2f70841a, 0x07cc4c15, 0x82bcffff, 0xff05a98f, 0xf6a8eeff, 0x2906ff5e, 0xff7bd4f4, 0xce4c1000, 0x94829e8b, 0xcccc4022, + 0x0020db82, 0x3b823082, 0x4e197d20, 0xf7260ca8, 0x07ab0644, 0x3a82066b, 0x46cd4c21, 0xcf5d11dc, 0xffcd2e09, 0x7c540e00, 0xb31100ff, 0xf7088b33, + 0x0e7d4714, 0x5208d05d, 0x6b2716f5, 0x54fb058b, 0x825b153b, 0x33bf3967, 0xffbb0734, 0x32b3eaff, 0x5600ff05, 0x0e079a19, 0x00ff94f8, 0x1566e607, + 0x94533b82, 0x34b32b05, 0xe6dfffff, 0xd7ffff66, 0xff836666, 0xecd19022, 0xd8223882, 0x21820040, 0xd783df20, 0x34332022, 0x27239982, 0x8208cccc, + 0x23200806, 0x00ff48e1, 0xffa4301a, 0x52781d00, 0x5e2200ff, 0x0500ffb9, 0xff080080, 0x00c0eeff, 0x260d00ff, 0xf4214882, 0x051963b0, 0x8305d449, + 0x233c8235, 0x402000ff, 0x4c822082, 0x2700ff22, 0x33052f68, 0x0671fd0d, 0x82f2ffff, 0x0b00ff8f, 0xffffcdcc, 0x9c0080f7, 0x13223382, 0x69843333, + 0x69826120, 0x5c8f1c35, 0x9e1c00ff, 0x2300ffb8, 0x088b4861, 0x00ff069b, 0x82f6282c, 0x82232024, 0x0d9c69b1, 0x2f821120, 0x37faff2d, 0x0f00ff4c, + 0xffff52f8, 0x82be9ff6, 0xb81e2c8e, 0x0400ff08, 0x00ffc3f5, 0x822ec100, 0x991921a9, 0xc6210982, 0x05614d80, 0x8bc00823, 0x0ab876b6, 0xb6fdff26, + 0xf5ffff46, 0xff24a582, 0x810060fc, 0x05223882, 0x708206e1, 0x80552322, 0x1c2d7082, 0xffff34b3, 0x8b6666e3, 0x99dcffff, 0x21a0829a, 0xf082ecff, + 0x68f7ff24, 0x84517af6, 0xf4ff2305, 0x33820040, 0x0a170e22, 0xf0823382, 0xec833382, 0xccdfff23, 0x056b41cc, 0xe8203383, 0xff21ca82, 0x220483f4, + 0x41b85eeb, 0xff220533, 0xa483def2, 0x7c542232, 0x8afaffff, 0x1a00ff3e, 0xffffcc4c, 0x8bce4ce2, 0x332f6982, 0xff0e0832, 0x66669b01, 0x801001ff, + 0x82911500, 0x07b94fd7, 0xb3f3ff23, 0x5b318233, 0x0820068f, 0x66220a82, 0x87608168, 0xfaff2105, 0xf4291a83, 0x088b0080, 0xff0654fb, 0x830983ff, + 0x82cd2019, 0x4f4c20f7, 0x95210547, 0x82308208, 0x0a00210b, 0x30080950, 0x91cd4c0c, 0xe60900ff, 0xffeb0866, 0xc2f59f00, 0x212d8205, 0x118232b3, + 0xff9ca426, 0x00800a00, 0xe5270e82, 0x0b00ffa2, 0x828b3433, 0x850683e7, 0xfaff2316, 0x2a851c1a, 0x5bf6ff23, 0x2c3c82a6, 0x3e0a60ff, 0x84ffff05, + 0xffff9a99, 0x18b58277, 0x211695c3, 0xc41824f7, 0x66250acf, 0x19eeffff, 0x20f2829a, 0x227f82e9, 0x850724fb, 0x86148409, 0x82188204, 0x183382ce, + 0x180af989, 0x260a278a, 0xfb0724f7, 0x821543b4, 0xb346276b, 0x3900ff34, 0x04825c4f, 0xffcc4c26, 0xa4b04600, 0x20058049, 0x491b8233, 0x52490797, + 0x21068506, 0x6949ffff, 0xffff2407, 0x82cd4cb9, 0xb9ff232d, 0x1b825c4f, 0xa4b0c622, 0x54854484, 0xff0e0836, 0x9a19e901, 0xb35400ff, 0xffff1534, + 0xff52f8e7, 0xf668d6ff, 0xf931e982, 0xffff705d, 0xff1e85f4, 0x164ef1ff, 0x11fcffff, 0x310e82ec, 0x00ff8e82, 0x0848a106, 0xe67effff, 0x4a00ff66, + 0x29825c8f, 0x281c6b22, 0xf222da83, 0x694200c0, 0x40f52106, 0xf2220982, 0x7483e2ba, 0x52f8cf28, 0xf2ffff06, 0x7a82e1ba, 0x18191783, 0x942d0c22, + 0xff0766e6, 0x3eca7fff, 0x66b5ffff, 0x274a8266, 0xff8f82f4, 0xfa5ef9ff, 0xe6837482, 0x56ee0322, 0xb8260e83, 0x7a0b00ff, 0x9e85085e, 0x97290023, + 0x209e840a, 0x2a158371, 0x0300ffe2, 0x00ffc1ea, 0x82f6a80e, 0xf47d210e, 0x46269e83, 0x8100ff08, 0x9e83221b, 0x29825e20, 0x67e67e22, 0x80210a82, + 0x220a8200, 0x820080f4, 0x34b32120, 0x1726ce82, 0x0e00ff0a, 0xce849899, 0x80283982, 0x00ff0800, 0xffae0718, 0x0c215e82, 0x21158205, 0x158290a2, + 0x82e07a21, 0xecb12124, 0xee216382, 0x210e8214, 0x8d83717d, 0x2982fa20, 0x9a198122, 0x7021b282, 0x2c5382a4, 0xff4821ff, 0x96e39400, 0x00ff8b05, + 0x83f8820d, 0x85ff20e0, 0x450d2304, 0x2c828b1f, 0x3d0a3023, 0x211b8206, 0x21821e45, 0x26058863, 0xff8b0040, 0x83c0f2ff, 0x00002773, 0x6bffff20, + 0x73829a19, 0x52415483, 0x0b002305, 0x8382707d, 0x3682a120, 0xad840e20, 0x85aa1121, 0xf4ff23a8, 0x5182a285, 0x1e051822, 0x2306a641, 0x12a30600, + 0x2706a641, 0xffbc14fc, 0x0c57f1ff, 0x82210e82, 0x26a8830e, 0xffff08b8, 0x82e6c07f, 0xe07a21a8, 0xff235e86, 0x825278b5, 0x800b220a, 0x21208200, + 0xd8827a54, 0x8266e621, 0x68662434, 0x83f8ffff, 0x80f42213, 0x9b861800, 0x7cfb2d62, 0x4cdbffff, 0x00ff15cc, 0x0734b3cc, 0x64063741, 0x0a21056c, + 0x239982c0, 0x8b34b3f2, 0xf222bb82, 0x471933b3, 0xf2220d7e, 0x168200c0, 0xcc4c3323, 0x054b5a07, 0x99f6ff29, 0xefffff9a, 0x82740080, 0x18e52027, + 0x201de384, 0x06ee44cc, 0x5f550020, 0x831a200c, 0x204082fe, 0x2b5085a2, 0x66660900, 0xff1cfb08, 0x34b37400, 0x11209d82, 0x21054c69, 0xad4dcd4c, + 0x2347820b, 0xff34b311, 0x112d6c18, 0x7d09db4d, 0xcd460a1f, 0x0e002106, 0x16834482, 0x2306fe46, 0xff155b5b, 0x820ac77d, 0x0e7c4e19, 0x540e0023, + 0x2063837b, 0x08ca4d34, 0x33208c99, 0xcd208c88, 0x4c265482, 0xf7088bcd, 0x1e4f4bd4, 0x0a6c4e0c, 0x3184be84, 0x95845a82, 0x3d59ee20, 0x3a0f1905, + 0xf75b222b, 0x7dbf8344, 0xf09408dc, 0x0f19cc20, 0x3420276c, 0x0e212886, 0x8432824c, 0x1e89188d, 0x94fb2361, 0xc28454f7, 0x2007b248, 0xb15b18ff, + 0x16b34109, 0x410b2d50, 0xab210e50, 0x23c28784, 0xffff7c54, 0x8b22c284, 0x645df4fb, 0x0d77420c, 0x6666112b, 0x19f9ffff, 0x0f00ff9a, 0x22fe82b3, + 0x44ccccf4, 0x3f300783, 0x00ff3433, 0x0532b391, 0x330600ff, 0x0c00ff32, 0xff260f82, 0xff0080fa, 0x2e820e00, 0xe6f3ff2c, 0x0500ff68, 0xff086666, + 0x3483f3ff, 0xcc4c0522, 0xc2187a82, 0xfa220807, 0x18829a99, 0x8268e621, 0x83bf201e, 0x4c6e2814, 0xffff05cc, 0x826666ff, 0x4cff26d3, 0x0000ffce, + 0x837882e6, 0x2221820f, 0x8233b3dc, 0x4ce32516, 0xe2ffffcd, 0xdc232184, 0x570834b3, 0xae8206de, 0xffff3323, 0x2b5d82e3, 0xcd4c2300, 0x078b088b, + 0xc4f704fb, 0x210e3141, 0x2a4134b3, 0x61111905, 0x204b820a, 0x49d182f1, 0xff2005e4, 0xb9820684, 0x22244143, 0x4344fb5b, 0xe6421c73, 0x2d424311, + 0xcbd4f722, 0x430fb442, 0xef821074, 0x2207a543, 0x41088b34, 0xb3201af1, 0x42114243, 0x374562b4, 0x08ffe19c, 0x30ffff2e, 0xffff34b3, 0x159a99c9, + 0x994c00ff, 0x9300ff98, 0xff05cc4c, 0x9a190600, 0xcc0b00ff, 0xfbffffce, 0x00ff6666, 0xff00800e, 0xce4cf4ff, 0x98211883, 0x210a8208, 0x23853233, + 0x83f1ff21, 0x23238319, 0x68e6f9ff, 0x1e822384, 0x3382b320, 0x996cff2e, 0xff89059a, 0x32330000, 0x8b888c89, 0xdd281582, 0xff8b9999, 0x6766e2ff, + 0x22131c43, 0x4399991d, 0x2222061c, 0x2d826766, 0x33240023, 0x145f4632, 0x66e60f27, 0x33faffff, 0x20948634, 0x307f82f6, 0x34330b00, 0x058b8b08, + 0x74f8af0e, 0xfc1534f8, 0xf6651914, 0x07942a18, 0xcaffff8b, 0x00ffe2fa, 0xf665192a, 0x82f8200d, 0x35002333, 0x72822005, 0xe0fa2a22, 0xe2201e83, + 0x35240a82, 0xf7081e05, 0x1a823383, 0x84601e21, 0x8b562615, 0xfbe4fb08, 0x067518c4, 0x05384e07, 0x09d57118, 0x4e0b0d63, 0x97610a11, 0x24b98205, + 0x48210700, 0x05a55fff, 0xb8de0825, 0x4fcb088b, 0x89180c5f, 0xeb200d61, 0xf7246483, 0xffff9a19, 0x82056250, 0x0a7b503e, 0x82482121, 0x573419ca, + 0x6d75180e, 0x207a8308, 0x260485ff, 0x8b00801a, 0x1800ff08, 0x20080774, 0x82b283ff, 0x80e5283a, 0x076b0800, 0xb92b14f7, 0x869a82ca, 0x66e621ca, + 0xff24ca9d, 0x33b35d00, 0xf8256883, 0xffff6766, 0x84c983f9, 0x66f82104, 0xff233882, 0x6566bbff, 0x978206c4, 0x1c82f920, 0x19060029, 0x00ff8b9a, + 0x82999907, 0x4c4222b9, 0x529918cd, 0x21d68d17, 0x3e82c275, 0x3e8ae528, 0xbdffff08, 0xda8233b3, 0xa2ffff24, 0xde40cd4c, 0x146e2783, 0xf8ffff06, + 0xde40ba5e, 0x0b8842b6, 0x8d426820, 0x19f72306, 0x04538b98, 0x59291905, 0x31884213, 0xf8af0e2b, 0x1534f794, 0xff0654fc, 0x07ba5fff, 0x5fff9921, + 0x6b200a24, 0x8431ba43, 0x18232085, 0x2212795b, 0x423b04fc, 0xc0433916, 0x14f72228, 0x4365b98b, 0x65b7285b, 0x5300e021, 0x002005ed, 0x21050656, + 0xc14300e0, 0x2265e51c, 0x45e4f75b, 0x4b221abd, 0x8b188b07, 0xf82d1507, 0x00ff0654, 0x8b985923, 0xa61c00ff, 0x20048368, 0x05b46166, 0x82cb0821, + 0x0fbb4532, 0x56454420, 0xffff2264, 0x72f144fd, 0x63458b20, 0x5684441a, 0x45020021, 0xa8460563, 0x581f4406, 0x00ffef3f, 0xff66e6ce, 0x66e6ca00, + 0xdcffff15, 0xffff9a19, 0xff0080f5, 0xcdcce7ff, 0x33e1ffff, 0x06057134, 0x9a19df24, 0xe27dff08, 0xcc0c3005, 0x1100ffcc, 0xff966766, 0x33331500, + 0x840700ff, 0x9907321a, 0x2b00ff99, 0xff05cc4c, 0x48e190ff, 0x33ceffff, 0x274f8234, 0xff7b54e0, 0x6666b300, 0xff2f1582, 0x00ff48a1, 0xff9a9901, + 0x48a10000, 0x828b8b8c, 0xc0392b4e, 0x2000ff00, 0x00ff4621, 0x17825941, 0x2adc1022, 0xe6210982, 0x231a8366, 0x8b00a001, 0x7c262e82, 0xffffffee, + 0x0982eeec, 0x31820f82, 0x9f820d20, 0x820d0021, 0x1200229f, 0x21b482a6, 0x40824009, 0xb8de1327, 0x400300ff, 0x261e8200, 0x8eb8de12, 0x831300ff, + 0x83012015, 0x21132124, 0x00217382, 0x311a82c0, 0x4200f6ff, 0xf1ffff99, 0x00ff6c87, 0xff1e450a, 0x8e83eeff, 0x1a840220, 0x2583e820, 0x00e00322, + 0x2406b551, 0xff64db01, 0x821382ff, 0xb3ff2986, 0xff8b9042, 0x0a57b4ff, 0x8c2c8582, 0xbcffffce, 0xffffcc4c, 0x084861da, 0xc03a2b82, 0xf2ffffc4, + 0xffff847b, 0xff4220f3, 0xec11e4ff, 0xdf0400ff, 0xe3ffffbe, 0x8a8266e6, 0xbfbf1f2b, 0x994cffff, 0x00ff059a, 0x218f820e, 0x8f83afff, 0xcd0c7a25, + 0x83c2ffff, 0x33442209, 0x575f8233, 0x032706c3, 0x00ffe926, 0x83444c00, 0x82c520c6, 0x83602009, 0x83f220b0, 0x82112026, 0xf1ff229a, 0x2bea8266, + 0xffb85e17, 0x9a99f4ff, 0x211b00ff, 0xd0307e83, 0x00ffcd4c, 0xffa8e50c, 0x9999c5ff, 0xcc2600ff, 0xfa279882, 0x00ff7b14, 0x829a1921, 0x9e612d7e, + 0x8900ffb8, 0xff15cc4c, 0x3433ffff, 0x04829982, 0x83feff21, 0xb3032752, 0xfeffff32, 0x6c823333, 0x67838020, 0x82c0f721, 0x20f721bd, 0xf325fd82, + 0xffff06a1, 0x200983f9, 0x206c83f1, 0x25e684fd, 0xff4861f1, 0x3882fdff, 0xdef1ff22, 0x02225282, 0x3a53c01f, 0x05002205, 0x233d83a0, 0x870080ff, + 0xe0206282, 0xfc2c3982, 0x00ff8200, 0xfffabf00, 0xc6e0fbff, 0x03218282, 0x255382c0, 0xffff3fea, 0x09831400, 0x8f82f125, 0x821500ff, 0x03002309, + 0x1e82b9de, 0x82ac1521, 0xb60326c0, 0x0e00ff03, 0x268c82b3, 0xffcecc14, 0x8219fcff, 0xb31526ca, 0x01ff0832, 0x22f4839d, 0x829a9924, 0x21a725c0, + 0x3100ff48, 0x992f8783, 0xff9d5278, 0x00809bff, 0xffff087b, 0x829a99e4, 0x1e852531, 0x4ceaffff, 0xe923fc82, 0x82860040, 0x83c02014, 0x83e02095, + 0x994b2bed, 0xffff059a, 0xff48a1f0, 0xba83a8ff, 0x34b36e2d, 0xd492ffff, 0x3e00ff7c, 0x828050f8, 0x193e2181, 0xf4204082, 0x8e201a83, 0x402c6c83, + 0x00ff5ccf, 0xff64660f, 0xb81e5700, 0x1f201e82, 0xb32bab83, 0xff050080, 0x38f30400, 0x831c00ff, 0x19f32254, 0x05147198, 0xcce7ff2c, 0x0d00ffcc, + 0xff086666, 0x5983eefe, 0x33339f28, 0x0300ff15, 0xe58600e0, 0xb8be1422, 0x8021da82, 0x210e8501, 0x5384fcff, 0xff22ff83, 0x238240fc, 0x00800e27, + 0x42ebffff, 0x82c2828e, 0xeaff230e, 0xd282b95e, 0x0640ff25, 0x82fbffff, 0xfeff2342, 0x1983fa7f, 0xffff8324, 0x288220fe, 0x7d5ffc31, 0xf7ffff08, + 0xff9442c0, 0x06a1f3ff, 0x820600ff, 0xf1ff229c, 0x2162825e, 0xac829e02, 0x82f1ff21, 0x02002944, 0xff7d00a0, 0x3bc0fdff, 0x2305a241, 0x0780faff, + 0xfe223582, 0x9782e29a, 0xff6de727, 0xcccc0000, 0x2105828f, 0xd1829a99, 0x82991921, 0x824520e2, 0x39ff2c0a, 0xff15cd4c, 0x4861c8ff, 0x830900ff, + 0x21da217a, 0x31210982, 0x2034825a, 0x22a38204, 0x82de3400, 0x1400275f, 0xffffb89e, 0x6f825ee6, 0x48a12322, 0x632ab882, 0x2b00ffd8, 0xffff703d, + 0x1e835ef8, 0x7e822b20, 0x60f8ff22, 0x2831d782, 0x00ff707d, 0xff343f07, 0xf6281c00, 0xff1000ff, 0x2a828284, 0xff34b3f2, 0x32f3ccff, 0x82cbffff, + 0xdeff2852, 0xffff6866, 0x826666c7, 0xcccc2170, 0x83278682, 0x00ffce4c, 0x82cc4c97, 0xc0f72586, 0x0800ff40, 0xf3258683, 0x00ffc07f, 0x20098306, + 0x869a83f1, 0x200a84e6, 0x20e68480, 0x20e683e0, 0x2196821e, 0xe68360fa, 0x0080ff26, 0xffffff8f, 0x00233082, 0x827dff03, 0x82c020e6, 0x1f04228d, + 0x415f823b, 0xa3411094, 0x0c944106, 0x94412020, 0x82622008, 0x83fc2047, 0x40ea2258, 0x2abc8200, 0xff7834ff, 0xd5edfbff, 0x83feffff, 0x33fc21bc, + 0xfe2bc682, 0xffffd04c, 0x080080fc, 0x6e70fb0e, 0xb42a1ca5, 0xffff8b07, 0xff9a99a7, 0xef82b8ff, 0x0e820485, 0x57828b20, 0x47a1a722, 0xb82f1b82, + 0x00ffb85e, 0x8b9a9947, 0x665800ff, 0x83f70866, 0x6d002030, 0x66240601, 0xa61c00ff, 0x0e820482, 0xf7088b27, 0xfb2b0654, 0x8b7e18d4, 0xab8b225c, + 0x0bfa4b15, 0x5c0a684d, 0xa4701696, 0x187f1819, 0xf78b2213, 0x22be8e74, 0x828b9082, 0x707d2242, 0xbc7e1808, 0x2b8d9a16, 0xffff9082, 0xff0080ea, + 0x707d1500, 0x082c8685, 0x01ffef0e, 0xff3433a3, 0x6666a601, 0x4c29c882, 0xffffcccc, 0x059a9999, 0x0ec05bdb, 0x20080c52, 0x0fcf6e4b, 0x2c0e6551, + 0x34b3f1ff, 0x99f2ffff, 0xeeffff9a, 0x264c824c, 0x089a19ff, 0x82e2ffff, 0x26002657, 0xffff66e6, 0x217f83d1, 0x1e821919, 0x0756cb20, 0x85068305, + 0xe6ff2116, 0xe1202083, 0xd9200483, 0xc0233584, 0x8d0666e6, 0xff01223b, 0x263b8600, 0xff088b33, 0x83b3cbff, 0x7ad1227d, 0x05977de1, 0xcfe2ff25, + 0x85ffff5c, 0x54ee233b, 0x0f53ff7b, 0xaef12a05, 0x0d00ff14, 0xff8b6666, 0x3a921800, 0x114d6308, 0x19945318, 0xdb063423, 0x223b8207, 0x4e90821a, + 0x152206c6, 0x6441707d, 0xeb083105, 0x1400ff06, 0x9e8b9a19, 0x84f6ffff, 0x0c00ff18, 0xef28d783, 0x8b084ee2, 0x7cffff06, 0x2f064b41, 0x0614f715, + 0x3b05cb5b, 0xfb074b06, 0x1514fb0c, 0x8b242684, 0xf7ffff95, 0x00332d82, 0xff33b301, 0xcc4cf4ff, 0x0700ff08, 0xffff9999, 0x82ceccfd, 0xcd4c2209, + 0x054e79ff, 0x83cc0621, 0x221e8409, 0x82666609, 0x22338319, 0x4667660d, 0x082006a2, 0xf7223283, 0x3d820080, 0xce4c0b22, 0xb3214882, 0x075b6632, + 0x2e83f720, 0x83830020, 0x4f99f221, 0xf62207b7, 0x29829a99, 0x34b3032a, 0x33f9ffff, 0x0300ff34, 0xff2d4d82, 0xff32b3f8, 0x32330200, 0x66f8ffff, + 0x201e8266, 0x201e830b, 0x244d82fe, 0x66e60800, 0x056f7d81, 0x077b0822, 0xb5840885, 0xb1848120, 0x82ffff21, 0x85082024, 0x853a83b1, 0x234e84b1, + 0xcc4cfcff, 0x4e826284, 0x63830720, 0xb1857882, 0x82051942, 0x834882b1, 0x05bc796d, 0xb683f420, 0x83f7ff21, 0x201a84d6, 0x20d683f2, 0x20a182ff, + 0x493883ff, 0xff23052d, 0x823333f9, 0x21588362, 0x0983b3f8, 0x8366e621, 0x846720b1, 0x22868280, 0x84cd4cfe, 0x279c8296, 0x7e9a19f7, 0x067b088b, + 0xcc240f82, 0xff818bcc, 0xad83c883, 0x00ffcd22, 0x0820dc82, 0xf287e884, 0x06414a82, 0x82f92005, 0x0300235e, 0x1e8234b3, 0x0a97f622, 0x26065a4e, + 0xff299cf2, 0x82cc0000, 0x73f722cc, 0x21478233, 0x1e820080, 0x14aef422, 0x4c224882, 0xc38205ce, 0x99211584, 0x2edc829a, 0x00ff0040, 0xff66660d, + 0xcd0c0700, 0x840900ff, 0x45fc25dc, 0x0600ff1e, 0xfc223e83, 0x1982c3f5, 0x82ce4c21, 0x8fc221ad, 0x99210982, 0x3248839a, 0x00ffb85e, 0xff32b301, + 0xf628f6ff, 0x00ff8b95, 0x6b9a190c, 0x08820589, 0xd7224382, 0x6882950a, 0x8448a121, 0x82082024, 0x713d21b1, 0xff243a84, 0x3d0a0300, 0x00234e85, + 0x84e2ba03, 0x214e8262, 0xa282f3f8, 0xc7457882, 0x218c8406, 0x8c828c08, 0x6d830820, 0x510b0023, 0x20b686ec, 0x20158500, 0x21b18380, 0xe085d763, + 0x68090023, 0x82f484f6, 0xcc062167, 0x03223482, 0x884234b3, 0x03002305, 0x76869a19, 0x32330222, 0x01211e82, 0x226782b3, 0x8234b30b, 0x8209209c, + 0x075e5ddb, 0x66e6102b, 0x19ffffff, 0xfb83059a, 0x5c134544, 0x2001ff23, 0x229b8233, 0x8266669b, 0xb3012266, 0x84d58232, 0x8208208c, 0x0c002380, + 0x745f9a19, 0x43088305, 0x32200964, 0x20096443, 0x0864439c, 0x4107b37c, 0x644305a1, 0x43682006, 0x64200864, 0x82086443, 0x07644332, 0xf4203382, + 0x221a6443, 0x43ffff68, 0x30200764, 0x82086443, 0x0664433e, 0x64433420, 0x431e8209, 0x68200664, 0x21136443, 0xb1838198, 0x6443d020, 0x26788209, + 0xff6666f8, 0x82e6fcff, 0x224e8397, 0x824cfcff, 0x33f9231e, 0xb1830834, 0x78849820, 0x82186443, 0x22b68478, 0x8266f7ff, 0x0664433e, 0x64439782, + 0x84982006, 0x063d73f4, 0x2105bd43, 0x3382b3f8, 0x6443fc20, 0x22328205, 0x82ceccfd, 0x4cfe221e, 0x0a6443ce, 0xf3ffff24, 0x684366e6, 0x43088305, + 0xce200968, 0x20136843, 0x066f4432, 0x43057944, 0x99440568, 0x82f22008, 0x06684309, 0x0021e482, 0x05684308, 0x3382b320, 0x68430b20, 0x00802105, + 0x8306b862, 0x066843b1, 0x439a1921, 0x4c220868, 0x6843ffcc, 0x21b18206, 0xa6830700, 0xceccfd22, 0x83086843, 0x8201201e, 0xf7ff234d, 0x68439a19, + 0xe6082311, 0xb1849566, 0x7b086843, 0x6383091e, 0x00234e83, 0x4334b303, 0x63830868, 0x5f450920, 0x828c8507, 0x45a084b1, 0x00200689, 0x0021b684, + 0x84d68308, 0x880d201a, 0x2338832e, 0x66e6f8ff, 0x06232982, 0x85ffcccc, 0x43628558, 0x8b250c68, 0x00ff058b, 0x2321821f, 0x9a99c4ff, 0x210e0448, + 0xfd470080, 0x32044805, 0x48008021, 0x87180704, 0x0e2f084f, 0xf8a4f7ef, 0x00ff1534, 0x069a9960, 0x831300ff, 0x1200215d, 0xff24b082, 0xfff628f7, + 0x2205d546, 0x82ecd1f0, 0xcc6c27b0, 0x78ffffce, 0x99821e05, 0x98993022, 0x480f2348, 0x2348070a, 0x0e495a10, 0x0f79a018, 0xdeffff24, 0x4c8268e6, + 0x30b30025, 0x82faffff, 0x000023f1, 0x09826866, 0x829a9921, 0x62fa20e5, 0xc22605ba, 0xffff9a19, 0x1682e6cd, 0x66e6cd29, 0x19c2ffff, 0x83088b98, + 0x83228306, 0x32002211, 0x240a8219, 0x66e63d00, 0x05666808, 0x4482ff20, 0x00ff6624, 0x04826605, 0x34b30022, 0x33210982, 0x22318234, 0x84ccccbd, + 0x88342069, 0x95662069, 0x86168269, 0x859a2069, 0x82992069, 0x2169978c, 0x6987d763, 0x8771bd21, 0xdede2269, 0x1cd16bb8, 0x11ff5b18, 0x48068348, + 0xf722119c, 0x057c0634, 0x13844805, 0xcf828b20, 0x9a99602f, 0xffff154b, 0x066666af, 0x00ff072b, 0x2d07829d, 0x33b3ffff, 0xff05eb34, 0x66663fff, + 0x9045d4fb, 0xb4f7225c, 0x285fdc8b, 0x64f7af0e, 0x4cd200ff, 0x276582cd, 0xff333315, 0x33b3d5ff, 0xd522d882, 0xfa829a99, 0x00241083, 0x05cd4c2a, + 0x18832382, 0xff8b1527, 0x34b3f2ff, 0x808618ff, 0x8215840f, 0x4cf5231b, 0x4418ffcc, 0x441811e1, 0xff2608f8, 0xcc4c0d00, 0x0685088b, 0x49842884, + 0x08235485, 0x5d8cf7eb, 0x14560cf7, 0xd4fb220a, 0x083c7507, 0x0d6c4818, 0x760c4856, 0xf7200c03, 0xb94c3383, 0x54f83a14, 0xe5feff06, 0xffff0080, + 0x1534b372, 0xe6fbffff, 0x0800ff66, 0xffff3233, 0x28db82f7, 0x9a190500, 0xe6f6ffff, 0x84a88266, 0x21168506, 0x2582faff, 0xff2d2a84, 0x08ceccf7, + 0x0524fb43, 0x19faffff, 0x06245b99, 0xcdcc0422, 0x2306ea69, 0x8567e60b, 0x0b20e282, 0xfa211083, 0x21928219, 0x5e82660e, 0xcccc0428, 0x0b00ff91, + 0x1a8266e6, 0xcd4c0522, 0x0528fc84, 0x665a00ff, 0x00ff0666, 0xff251083, 0x05cc4cf5, 0x874d8291, 0xfbff2332, 0x9b5b3433, 0x05002105, 0x3c823684, + 0x48824282, 0x586aff20, 0x205c8405, 0x208b830b, 0x218b82f7, 0xd083ba00, 0x3233d922, 0xf820d082, 0x00210a82, 0x21cb8202, 0xb482f7ff, 0x82010021, + 0xf7ff2380, 0x637b9a99, 0xdfff2a0d, 0xff8bcdcc, 0x3333d8ff, 0x82068408, 0x07a0666c, 0x2700ff24, 0x2d82cccc, 0x190b0027, 0x00ff8b9a, 0x834e840a, + 0x82092004, 0x05435f49, 0x82040021, 0xfaff230a, 0xb282cecc, 0xcc4cfd25, 0x840600ff, 0x1800205f, 0x2214e946, 0x820724f7, 0x201a8246, 0x18e583ff, + 0x420bec46, 0x1b830b38, 0x2c060a42, 0xe6e3ffff, 0xfb0e0766, 0xf7bcf770, 0x2cd08254, 0x06b85ed3, 0x211500ff, 0x00ffad48, 0x2288830f, 0x82666628, + 0x99252251, 0x32bb829a, 0x48615800, 0xccc6ffff, 0x3700ffcd, 0xffffb89e, 0x823333b9, 0x850684bb, 0xc8ff2316, 0x58824861, 0xb89ea722, 0xff212d82, + 0x84b882da, 0xd7ff2344, 0x54849a99, 0xff086923, 0x196184ff, 0x210c744a, 0x33823433, 0xccccf222, 0x2205d27c, 0x6400c0f2, 0xff22059a, 0x098240f5, + 0x00400d28, 0x06eb088b, 0xd8822cfb, 0x2482ff20, 0x7f821b82, 0x33f5ff26, 0x0d00ff34, 0xab207f83, 0x1808d618, 0xeb072c22, 0xab201b97, 0x3e824d82, + 0x85ff3421, 0xcc0a2348, 0x5c83ffcc, 0xfb088b2b, 0x1544f71c, 0x9e1d00ff, 0x20f582b8, 0x22ee8312, 0x820080e7, 0x80d8229e, 0x20d28300, 0x311183dd, + 0xff48e1e4, 0x0080d4ff, 0x1eebffff, 0xe9ffffb8, 0xd6825238, 0x8219eb21, 0x831620e2, 0xe6e42547, 0x2b00ff66, 0x00213583, 0x05364122, 0x2b822720, + 0x66120022, 0x18201682, 0x1d2b0983, 0x088b9a99, 0x54f82f0e, 0x4f1504f7, 0x1a2005f5, 0x2112d34e, 0x745dc4fb, 0x59d42018, 0x831917b9, 0x1022156b, + 0xbb8220c5, 0x190b0021, 0x241a6b83, 0x00ff0728, 0x24bc8209, 0xd8a30900, 0x6b8319ff, 0xf7c42310, 0xe86e1554, 0x00202108, 0x39202082, 0x082cec82, + 0x088b00e0, 0x0000ffbb, 0xbb0566e6, 0x00209182, 0x8d05086f, 0xffab211f, 0xc4210082, 0x0d0d6f05, 0x8b48e130, 0x05f8ffff, 0xffff081e, 0x073c00d0, + 0x1f8f8bbb, 0x1f840620, 0x10426020, 0x82f72005, 0xf8ff2351, 0x328200e0, 0x0e820483, 0x5b088b22, 0x2105a34b, 0xb46e04fb, 0x20208f07, 0x2497826b, + 0xff050e00, 0x852e83ff, 0x07002339, 0xc5838420, 0x087cdf29, 0xff6f00ff, 0x825b07f2, 0x251f9577, 0x84f707ab, 0x8319c4fb, 0x0e2b36fe, 0xf784f8ef, + 0xffff1574, 0x826666b0, 0x99bf24c7, 0x82ffff9a, 0x820a8204, 0x85082010, 0x00ff2406, 0x84486140, 0x00ff2116, 0x5de7331a, 0xffcccc23, 0xba401800, + 0x18ff200e, 0x180aa649, 0x220a5040, 0x1aab075b, 0x230c5212, 0x88d6f8ff, 0xf722ad82, 0xb4837829, 0x13ab6519, 0x20ffff25, 0x82ab9a19, 0xe68f25e9, + 0xffff0666, 0x141b6619, 0xfb07bb24, 0x576a0654, 0x66e63805, 0x1600ff66, 0xfffff668, 0xff9a99e9, 0x0a971900, 0x01ff088b, 0x82343338, 0xe6e6213b, + 0x1e201b82, 0xff212082, 0x280983f0, 0x8b9a1927, 0x802a00ff, 0x09064900, 0xff008029, 0xce4c0500, 0x83ffffff, 0x4c052b3c, 0x00ff08cc, 0xf766e6af, + 0x17821534, 0x82ea6621, 0x5105222e, 0x211d8268, 0x0f827fab, 0x82ae4721, 0x04862109, 0x30232282, 0x82077dce, 0x8219201b, 0x20768534, 0x82648316, + 0x088b248a, 0x84bb063b, 0x0a97211a, 0x9b849186, 0xfb201a84, 0x66219384, 0x83ff8266, 0xe9ff21ab, 0xff28ab82, 0xf668e6ff, 0x3b075b08, 0x6821ae83, + 0x861a83f6, 0x820a8239, 0xfb082635, 0x01ff0704, 0x25ce8368, 0xcc4c2000, 0xc48200ff, 0x3000ff23, 0x200982cc, 0x28d38318, 0x8b34b336, 0xeb34fb08, + 0x15941915, 0xef0e2909, 0x94f774f8, 0x0604f715, 0x4b0d785f, 0xfb210818, 0x777f1874, 0xb4fc2117, 0x93188682, 0xd420157e, 0x056f3382, 0x069b2214, + 0x6a1a83d3, 0x40210f01, 0x05294800, 0xff8bcd29, 0x33b30a00, 0x82f5ffff, 0xffff2811, 0x0800c0f2, 0x8bcb0743, 0x6a1c8233, 0x4c210635, 0x20339ccd, + 0x1b6b52bb, 0x540b3961, 0xfb250807, 0xfbeb0724, 0xbd4c1844, 0xa44c1817, 0xbbe11810, 0x8b4c1813, 0x724c180c, 0x82342010, 0xcc082ddd, 0x07ab08cc, + 0x155be4fb, 0xcc0800ff, 0x0a574c18, 0x25851c89, 0xf8ffff28, 0x00ffcdcc, 0x53823307, 0x3333f724, 0x8085088b, 0x2d3ce218, 0xbb04fb22, 0x4e91cf8a, + 0x0ba84c18, 0x2821cf92, 0x208583f6, 0x23a982cc, 0x088b0ad7, 0xb294cf85, 0xf724f824, 0x4d181504, 0xc61918df, 0x1f411662, 0x0902411a, 0x2a063b44, + 0x3433f7ff, 0x066b088b, 0x9cdba4fb, 0x413320d0, 0x3320191f, 0x16bbe118, 0x12db4d18, 0xfb07ab24, 0xcf839b44, 0x831a1f41, 0xca4d184e, 0x101f410d, + 0x0ebbe118, 0xd241cc20, 0x44f72312, 0xd0b704fb, 0xd0883420, 0x4b42cc20, 0x1ba14105, 0x4224fb21, 0x02413671, 0x4280831a, 0xf7210f22, 0x0b7142c4, + 0x420ebd41, 0x5b224a21, 0x704264f7, 0xe546180e, 0x076b2108, 0x21357042, 0xed420ad7, 0x83072006, 0x067042d4, 0x9f41bb20, 0x20cfac0c, 0x06bd4333, + 0xcdccf822, 0x17fde418, 0x27092142, 0xff94f70e, 0x66e6a001, 0x7222d482, 0xc0829a99, 0xcc4c8e27, 0xe8a2ffff, 0x230a82f6, 0x080a178d, 0x26080682, + 0xfff668ce, 0xb85e1500, 0x7dd3ffff, 0x2300ff70, 0xffff9a99, 0x086866db, 0x80f3ffff, 0xcdffff00, 0xffff289c, 0x82a430d6, 0x0c17241e, 0x83ffffff, + 0x82048213, 0xf0fc211e, 0xfc211482, 0x394f82cc, 0xfffd67ff, 0x9899fcff, 0x480100ff, 0xff088803, 0x9a690000, 0x0300ff88, 0x308287b6, 0x829a1921, + 0xdf2f2209, 0x2816828b, 0x8b5c4f42, 0xb03100ff, 0x053851a4, 0x82180021, 0x1300236b, 0x1a822a9c, 0x52b82022, 0x19837082, 0xa1832420, 0x66e6f827, + 0x612600ff, 0x22358348, 0x8266668d, 0xb3712735, 0x5d00ff34, 0x0a820a17, 0x90027223, 0x21068508, 0xcf83ffff, 0xe35e0025, 0x83ffffd6, 0x204882df, + 0x2290833d, 0x82cecc04, 0x60fc35f1, 0xebffff84, 0xffff0a17, 0xff2a27f0, 0x1e45f2ff, 0xa3e9ffff, 0xfb222a82, 0xbf82c435, 0xe0baf523, 0x21ff8207, + 0x7982f8f4, 0xd20df72c, 0x07f7ffff, 0xf4ffffae, 0x7482bdf4, 0x11820684, 0x94641024, 0x5582968b, 0x1ec50a23, 0x210e8207, 0xe2826851, 0x3b82ec20, + 0xcb61f72c, 0xcd0200ff, 0xf8ffff0e, 0x0982713d, 0x82fcc921, 0xbbfb2214, 0x271e82e7, 0xff050080, 0x42a0f5ff, 0xb727f582, 0xfaffffd0, 0x60ff0080, + 0x03270564, 0x00ff33b3, 0x8266660a, 0xb003224e, 0x210a8221, 0x1982f668, 0x0e826c20, 0x82660521, 0x820a20ed, 0xfcff230e, 0x0f82f668, 0x10780426, + 0x60feffff, 0x00224882, 0x0a82d807, 0x2030fd31, 0xe00800ff, 0xfcffff42, 0x00ffe0cf, 0x82a4f006, 0x10f8211e, 0x0d262982, 0xffff51b8, 0x6282e0fd, + 0x52380f22, 0xf0207c82, 0x01270982, 0x00ffba5e, 0x8200d007, 0x8300201e, 0x18052719, 0x0000ff10, 0xa682e87b, 0xff233d82, 0x8293b8e2, 0xbe5f214c, + 0xfa22b082, 0x33823629, 0x8224bb21, 0xabee24b0, 0x8300ff85, 0xd7ff2129, 0xe7219684, 0x834382f0, 0xd72a2296, 0x3048820a, 0xffb99e03, 0x2adc1400, + 0xcc0f00ff, 0x00ff99cd, 0x221a8316, 0x8232b305, 0x1909241a, 0x828b079a, 0xae0721c8, 0xf6215682, 0x20048204, 0x238982f8, 0x8b8c0c0b, 0x0b221c82, + 0x1b828c0c, 0xe4f0082b, 0x07f7ffff, 0xffff8bf0, 0x24b683f4, 0xb85ef5ff, 0x216e8207, 0xc782f873, 0x8214ce21, 0x12e32109, 0x67200982, 0xc6827383, + 0x84fdff23, 0x213b8218, 0xe682700a, 0x8260fc21, 0x820522d1, 0x21398290, 0xff825498, 0xff466126, 0x5c8ff5ff, 0x1983bc82, 0x97f5ff23, 0x20198209, + 0x22288290, 0x825278fa, 0x289c2619, 0x990300ff, 0x221e829a, 0x821824fa, 0xf00725f0, 0xdbf9ffff, 0x0125fa82, 0xffff10f8, 0x22da83fa, 0x8210d800, + 0x59f2221e, 0x261e829b, 0xffffaa11, 0x8267e6ef, 0x9a19217b, 0x2206db42, 0x823333f8, 0x33ff221e, 0x826c8233, 0x05f042e4, 0x2382fb20, 0xcc160024, + 0x968284cd, 0x828c0521, 0x67fe281f, 0x00ff05f0, 0x822a2717, 0xa9b1265e, 0x802900ff, 0x05774f00, 0x83f8ff21, 0xb3d42a09, 0xef0e0834, 0xa4f734f8, + 0x32fe8215, 0xff343361, 0x66e6a2ff, 0xcc4e00ff, 0x8dffffcc, 0x828b9a19, 0x85068342, 0xb1ff2a16, 0xff8b3433, 0xcccc9eff, 0x34068208, 0xff146ed8, + 0xb89e0f00, 0x9cdbffff, 0x1a00ff2a, 0xffffcd0c, 0x30f184e2, 0xff299cef, 0x703ddfff, 0x28e9ffff, 0xe7fffff6, 0x22f68270, 0x82d7a3ff, 0xd8a321b8, + 0xfd205082, 0xff236182, 0x8286cbfd, 0x2d42820f, 0xe0bafcff, 0x3a0100ff, 0xfdffffa0, 0xb782fa1e, 0xd1420122, 0x22210a82, 0x21f6824e, 0xf182b6b3, + 0xffcc4c26, 0xd90e0300, 0x00238a82, 0x829a5926, 0x682031a6, 0x0b00fff6, 0x00ffb81e, 0xffe1fa18, 0x86eb0c00, 0x1e213582, 0x227e82cc, 0x4428dcf0, + 0xf7270618, 0x00ff9a19, 0x83333326, 0xe6722235, 0x20358266, 0x8211835d, 0x820a82d7, 0x208682e7, 0x2be3836d, 0x1533b3d5, 0x66fcffff, 0xebffff68, + 0xff282082, 0xff3233f0, 0x9919f3ff, 0x23058f4a, 0x6666faff, 0xf5222982, 0x804334b3, 0x820c2009, 0x05804310, 0x82f8f321, 0xf4ff215d, 0xff220682, + 0x1682f7ff, 0xf8080023, 0x225d8210, 0x82f0070b, 0xcc0a228f, 0x138843cc, 0x88430f20, 0x43fb2008, 0xb0211388, 0x12884322, 0x88436720, 0x43212033, + 0xdf200888, 0x360d8843, 0xffffa8a6, 0xff04d6fd, 0x33330f00, 0x0100ff8d, 0x00ff6666, 0x82cdcc07, 0xe6003663, 0x0500ff67, 0x00ff9a19, 0xff008000, + 0xcccc0200, 0xb3e2ffff, 0x20488233, 0x22828266, 0x8233faff, 0xb301220a, 0x2e844333, 0x0e00ff24, 0x88433c0a, 0xc5042206, 0x22678220, 0x4370fd09, + 0xf3210988, 0x088843f8, 0x88430820, 0x8b082105, 0x16821182, 0x21378843, 0xc5822c67, 0xff23c082, 0x439a99f4, 0xf523061b, 0x83080080, 0xff67230a, + 0x1483f5ff, 0x1e83f420, 0x0483fa20, 0x9999f527, 0x990300ff, 0x221e8298, 0x431924fa, 0xe7220888, 0x884300ff, 0xd7632110, 0x0e211e82, 0x08884358, + 0x88439820, 0x43342008, 0x66201388, 0x8843f382, 0x66062805, 0xfeffff66, 0x82056866, 0xcd4c2a11, 0xb3f9ffff, 0x2900ff32, 0x213e827f, 0xa18219f4, + 0x39068843, 0x01ff0833, 0xffcccc49, 0x99991eff, 0x1900ff15, 0x00ff3433, 0xffcecc1d, 0x09830f00, 0xcc4c2529, 0x2800ff8b, 0x82089a99, 0x33612a06, + 0x00ff3533, 0x21cdcc4e, 0x2279838b, 0x828b7caf, 0x06b2214b, 0xf5210482, 0x21048280, 0x04827eaf, 0x087eff2c, 0x6f0000ff, 0xfaffff00, 0xd14136be, + 0xfaff2305, 0x085732b3, 0x619d3509, 0xb0ffff48, 0xffffec51, 0xff846bad, 0x7a9495ff, 0xb3eaffff, 0x0021ca82, 0x21758214, 0xb482b3ff, 0x824a0021, + 0xc7ff2104, 0x0023a482, 0x8266e65a, 0x2100236b, 0x7f82a4b0, 0x48a11f31, 0x020800ff, 0x1b00ff0c, 0x00ffac87, 0x82d6f80d, 0x5918306b, 0xf4ffff9c, + 0x00ff1e05, 0x8164e61e, 0x792400ff, 0x0322052c, 0x31821c0f, 0x74b30227, 0xb90100ff, 0x2604829a, 0x00ff9042, 0x8248e102, 0x3a012231, 0x830a83a0, + 0xe06d2bb7, 0x440300ff, 0xfdffffde, 0x13829ce6, 0x08bc3422, 0xb820c282, 0x00222982, 0x96824a57, 0xffd04c3e, 0x68661700, 0xb3efffff, 0x1f00ff30, + 0x0e089899, 0x01ff30fb, 0xf79a197f, 0x074b15b4, 0xee20d482, 0xf120cd83, 0xff239782, 0x82b89ef1, 0x1e452527, 0x062b088b, 0x8505bc4d, 0x8516831b, + 0xae47211b, 0xff26ca82, 0x069a19bf, 0x1b82ffff, 0x17833d82, 0x200d3b7f, 0x211b832b, 0x1b83b85e, 0xff13a122, 0x0a4c7118, 0x7f055b57, 0x34830751, + 0x1100ff27, 0x088bb89e, 0x708018eb, 0x6ab92016, 0xa47f0584, 0x7a0d2205, 0x6b7118e2, 0x072b2e0b, 0x00ff06eb, 0x8b348012, 0x800d00ff, 0x211a8200, + 0x72829a99, 0x6666ee29, 0x83f80e08, 0x821573f7, 0x90c22fa0, 0xe0feffff, 0xffff0542, 0xff00c0fa, 0x26832700, 0x707df032, 0x212400ff, 0xe8ffff48, + 0x00ffb8de, 0x081e451e, 0x24055e59, 0xb85e0b00, 0x05ba6305, 0x20060022, 0x00212e82, 0x21048260, 0x5a82a00a, 0x3882f920, 0x27069579, 0xffaec7eb, + 0x10181500, 0xf9205382, 0x06201f83, 0xff211a82, 0x210982f5, 0x2984ffff, 0xff285382, 0x080020f9, 0xa1f4ffff, 0xf3226382, 0x298268e6, 0x7d83e120, + 0xb81e1725, 0x82dbffff, 0x0f00261f, 0xffff1e85, 0x22ce82d8, 0x82400500, 0x01002829, 0x00ff6626, 0x820a5710, 0x8200207d, 0x0900224e, 0x25738240, + 0xff34b3f8, 0x38820700, 0xccf6ff2b, 0x6d088bcc, 0xf6ffff06, 0x684a18c0, 0x20228209, 0x832c8300, 0x22c08214, 0x84be1f01, 0x216c82ef, 0x3d8280d8, + 0x6c84ef83, 0xef83ff20, 0xbae1ff23, 0x20ef84e1, 0x22968208, 0x82980fad, 0x05576f25, 0xa282e120, 0x7a54f526, 0x5e0000ff, 0xe6839c82, 0x0482ff20, + 0xea202582, 0xea227883, 0x298348e1, 0xf9224f83, 0x24864861, 0xec51f525, 0x830600ff, 0x41428238, 0xeb82063a, 0x29824620, 0xdc82e820, 0xc5e1ff28, + 0xf1ffff20, 0xeb82d763, 0x4166e621, 0xff200578, 0x53829282, 0x8fc2ee27, 0x190100ff, 0x8229829a, 0x065743c9, 0xeb85f820, 0xff8b3322, 0xcd23e782, + 0x83076d08, 0x857c8208, 0x83f820fa, 0x82092009, 0x82eb8322, 0x3d11226c, 0x25428271, 0xff05be1f, 0x15820500, 0xff245883, 0x90820f00, 0x21065841, + 0xcf822117, 0xe2bae122, 0xf3206c82, 0xf4217c83, 0x25c084a1, 0xffff0020, 0x0482e0f9, 0x82a0ff21, 0x41f52004, 0xea8408b6, 0x83150021, 0x82ef8248, + 0x84062053, 0x220482ea, 0x83a10a00, 0x212984ef, 0xef82b91e, 0x8200e021, 0x5e0b217d, 0x0c200a82, 0x0021c083, 0x2134831e, 0x2482e1e8, 0x73832420, + 0xe27af027, 0x852700ff, 0x82ef841f, 0xf3fd277d, 0xefffff33, 0xea829caf, 0x4e82ff20, 0xcc33da82, 0x4c0700ff, 0xf8ffffcd, 0x00ff3433, 0x8b333309, + 0x8206a908, 0x00402208, 0x8218828b, 0x83ef854c, 0x8200202c, 0x274282ef, 0xff42e0fe, 0x703d1100, 0x27209682, 0xef844282, 0x6c830020, 0x0025ef84, + 0xff1e451e, 0x84ef8200, 0xffb82296, 0x82ef82ff, 0x84062029, 0x210482ea, 0xea830a00, 0x0021ef83, 0x82ca8306, 0x232982d9, 0xffb81e15, 0xea86ef83, + 0xef840020, 0xef832484, 0x83f9ff21, 0x1e062238, 0x063e41b8, 0x20061043, 0x83348317, 0x0f0022ef, 0x84738285, 0x83052082, 0x852722b1, 0x2753821e, + 0xff645010, 0x34f3fdff, 0x09225382, 0xd745cc4c, 0x07002205, 0x22e582b3, 0x82cc4c07, 0x330925dc, 0x07a90834, 0x33200884, 0x2282fe82, 0x20050841, + 0x202282f6, 0x05644cff, 0xe62a2208, 0x7e00ff66, 0xff15ec51, 0x00c01800, 0x1600ff87, 0xffff2adc, 0xfff468f6, 0x46a11300, 0xe1f1ffff, 0x21928248, + 0x14825cd5, 0x3ecacf26, 0xf7ffff05, 0x05227e83, 0x24820060, 0xd1825e20, 0xca21042c, 0xc2f5ffff, 0x0200ff90, 0x92827e5f, 0x82050421, 0x0a4021a7, + 0xcc232983, 0x828b3433, 0xfe032756, 0xbffffffa, 0x3b82a4f0, 0xd2cdf527, 0xa3fdffff, 0x223b82d6, 0x59ff6766, 0x332006a9, 0xfa229a82, 0x65839a99, + 0x8b826620, 0x34333022, 0x1326ce82, 0x00ff9a99, 0x0482190e, 0xa0831620, 0x98990922, 0xb5829f82, 0x05040023, 0x20298220, 0x23ca8298, 0x14aebfff, + 0x30275e82, 0xffff9a59, 0x181f85d5, 0x83072dbd, 0xfbff269f, 0xffffdde4, 0x221983f6, 0x8242a0fd, 0x00c0219f, 0xbf273482, 0x00fff5e8, 0x82ad0704, + 0x0504225e, 0x224f861f, 0x82008009, 0x226383f3, 0x8234330e, 0x838020f3, 0x47e42729, 0x89ffffae, 0x5e829a19, 0x5c0f4024, 0xc28200ff, 0x02223482, + 0x4a822a5c, 0x0021c282, 0x2cb38304, 0xffce4cf6, 0xcd4c0500, 0x4cf7ffff, 0x225e82cc, 0x821fc5cf, 0xd8632188, 0xf1228882, 0x4a8214ee, 0x82289c21, + 0x83d28383, 0xfbff23c2, 0x7284e1fa, 0x00ff0829, 0xff866b83, 0x82997cff, 0xe7ff335e, 0xff8f0040, 0xd723e9ff, 0x970900ff, 0xecffff0a, 0xf782b95e, + 0x82b81e21, 0x942a2725, 0x3000ff7b, 0x79827a54, 0x00c00823, 0x05e84cff, 0x66a6092b, 0xe4fbffff, 0x0a00ffde, 0x22138240, 0x8240a0fd, 0x02fc2179, + 0xbf224382, 0x2982a6f0, 0xc9831920, 0xcc4c7d23, 0xf9441815, 0x5377180b, 0x610e2212, 0x83678248, 0x9e11239c, 0x86188bb8, 0x28821bef, 0x99f1ff24, + 0xa046ff9a, 0x66ee2205, 0x832d8366, 0x82ff2366, 0x668234b3, 0x0601fc27, 0x0f4000ff, 0x837c825c, 0x02002392, 0xcb820060, 0x0025a682, 0xffe21a04, + 0x23ba8300, 0x00800500, 0x2a286282, 0xffffe27a, 0x0566a6cf, 0x7721e682, 0x2150824c, 0xfa825ccf, 0x5a821920, 0x8280f621, 0x4ce723cb, 0x258287cc, + 0x34b36722, 0xc1844f82, 0xf682cf20, 0x802a0023, 0x205a8200, 0x84558305, 0x2104224b, 0x205f82ca, 0x27be82a1, 0xff7e5f02, 0x703d0a00, 0x7f823482, + 0x82ffff21, 0x295a8289, 0xff8e02fc, 0xa846e7ff, 0x5584ffff, 0x5f83e920, 0xceccf122, 0x84837382, 0xb3dbff28, 0x7200ff32, 0xb98266e6, 0x82a0fd21, + 0x23b383a9, 0x1ee5fbff, 0x6441b385, 0x82678205, 0x47302753, 0x2a00ffb0, 0x7d823473, 0x48210e22, 0x24823f84, 0xb3838f20, 0x8fb81e22, 0x40206382, + 0xff21d482, 0x296e83c0, 0x05ae07fc, 0xff94f70e, 0x58841e00, 0xb89eef26, 0xefffff8b, 0x002ed482, 0x7d9a1904, 0x050b00ff, 0xffff081e, 0xb482e12e, + 0x7c149722, 0x2a22a482, 0x911866e6, 0xf821177f, 0x0cd25534, 0x80150023, 0x05855600, 0x6af70823, 0x29448207, 0xffff66e6, 0x0566e668, 0x6285817d, + 0x2005f45c, 0x05da5bef, 0x9a99ed27, 0x19fe00ff, 0x26dd829a, 0x923233f7, 0x83f7ffff, 0x82062010, 0xf3ff2189, 0x09220983, 0xd9826666, 0xb81e2c22, + 0x00207d82, 0x15419118, 0x2c83b220, 0x98ffff22, 0xfc31a582, 0x00ff00e0, 0xff004002, 0x0040fdff, 0xfcffff8d, 0x820f85c0, 0x39ef21cb, 0x0c366882, + 0xffff025a, 0xff32b3de, 0xd2801d00, 0xb3e8ffff, 0xffffff34, 0x1e8200a0, 0xcdcce826, 0x600000ff, 0xde273982, 0xffff9999, 0x822e7fe2, 0x823320ac, + 0xa1f3221e, 0x831e8248, 0xfdff2148, 0xff244d82, 0x890040fd, 0x68825882, 0x1a820f83, 0x6686b223, 0x207a828b, 0x9b6719e5, 0x08d3560a, 0xd3ffff27, + 0xff0748e1, 0x244482ff, 0x9ef6ffff, 0x83de82b8, 0x83f92004, 0x21f723b1, 0x3e828448, 0xb85ef42f, 0xf9ffff82, 0x8b7d0040, 0x33f1ffff, 0x38128233, + 0x074861f5, 0xbaffffeb, 0xff0547a1, 0x3ecab800, 0x06d4f707, 0x4c47ffff, 0x231582cc, 0xb85e4500, 0x0a271582, 0x8b07af87, 0x820e00ff, 0xf9ff3eb5, + 0xff99cc4c, 0xce4cf4ff, 0xfeff0894, 0xff6666c2, 0x66e6a3ff, 0x0634f715, 0xd60800ff, 0x24258204, 0xfffc2907, 0x83048200, 0x9eef220a, 0x27068208, + 0xff87d608, 0x04d6f8ff, 0x79201683, 0x29249482, 0xfb088bfc, 0xff213082, 0x850982f7, 0x201e8219, 0x22918287, 0x597929f7, 0x33200512, 0x21060454, + 0x9218b3f9, 0x8b21070d, 0x826496cb, 0x20648575, 0x234a8586, 0x14430600, 0x88206498, 0xf8226482, 0x3082de0f, 0x4cf6ff23, 0x206488ce, 0x06695432, + 0x64f80e2b, 0xfb15f4f7, 0xcb4b0654, 0x41a18405, 0xfb211467, 0x2d9c42f4, 0x00801a22, 0x4206846c, 0xfb201352, 0x282ead82, 0xff1566e6, 0x9a195fff, + 0xf3ffff06, 0xa4829999, 0xcd4cf527, 0xcc0900ff, 0x05745ece, 0x0028af82, 0xff90420d, 0x71bd0a00, 0xd72f1682, 0x0c00ff0a, 0x088b295c, 0xff0634f7, + 0x82330e00, 0xe60022be, 0x108d6066, 0x200ce960, 0x252582f6, 0x34b3f2ff, 0xe4fb088b, 0x53065326, 0xffffff07, 0x84087444, 0x4cf52395, 0x9a85ffcc, + 0x072b4418, 0x852bf622, 0xbd21cd82, 0x28fd8270, 0x082a5c0c, 0xcc3900ff, 0x213782cc, 0xef8233c6, 0x212c2041, 0x3b8606c3, 0xe6000028, 0x0c00ff66, + 0x57826766, 0x8633b321, 0x590d2004, 0xcc20076c, 0x078e4918, 0x8f42f52f, 0xf3ffff8b, 0xff08d7a3, 0x9a19c7ff, 0x223f8307, 0x8232330e, 0xb30a211e, + 0x41053362, 0x08200554, 0x08175b41, 0x00ffaf28, 0xff5eda03, 0x4821a901, 0x0600ff15, 0x00fff49d, 0xff4cf70d, 0xec110e00, 0xe70800ff, 0x0f00ff6c, + 0x088bc375, 0x988244f8, 0x00800f29, 0xffff998b, 0x829418f7, 0x9a992129, 0x0821fc82, 0x22eb82b4, 0x8232b306, 0xae07350a, 0xe6fdffff, 0xefffff68, + 0xffff5278, 0xff6666f5, 0x3c0af4ff, 0x962d9682, 0xffffcc4c, 0x05e2ba7d, 0xccafffff, 0x06e444ce, 0xdd82c220, 0x19b9ff25, 0x83368b9a, 0x82e42099, + 0x07002e4c, 0xff713233, 0x34330b00, 0xe6e8ffff, 0x20388266, 0x673882fe, 0xfe250543, 0xff8c0080, 0x240582ff, 0x190100ff, 0x241a829a, 0xbb0100c0, + 0x2c898205, 0xff9166e6, 0xcd4cfbff, 0x800900ff, 0x83f48300, 0x4f002e1d, 0xff079a19, 0xc00a49ff, 0x91df00ff, 0x222782ea, 0x828736f6, 0xc4f52159, + 0xfa26a182, 0x1000ffe1, 0xc082ae87, 0x82779e21, 0x52f821ea, 0xff374d82, 0xff06beff, 0xa0253c02, 0xdea6feff, 0xff8b15b8, 0x0080b0ff, 0x88bfffff, + 0x200e8204, 0x8327828b, 0x832b8206, 0x844020ac, 0x5c4f206e, 0x06820596, 0x4100ff22, 0x0020f182, 0xff211682, 0x820e8200, 0x2006842d, 0x831184ff, + 0x29548549, 0xff37fb08, 0x66e62400, 0xe050ff15, 0xcc012505, 0x0700ffce, 0x00216782, 0x253e8301, 0xff323306, 0xfc83ffff, 0x8205f267, 0x00ff240a, + 0x82cccc09, 0x824c20fb, 0x33092228, 0x25c18234, 0xff0832b3, 0x84820800, 0xe6fdff23, 0x20098266, 0x062f7eb3, 0x19020023, 0x214c829a, 0x1e8234b3, + 0x29820220, 0xfa202385, 0x08251e83, 0xffff9899, 0x826683f7, 0x20c88218, 0x826c83fa, 0xff852371, 0x58820100, 0xb3f9ff26, 0x0000ff34, 0x09207784, + 0x0cbeb418, 0x580c6857, 0xff261636, 0x0080f6ff, 0x7a7cff07, 0x83fe2005, 0xccf923ac, 0x0f8289ce, 0xff256482, 0x0868e6fc, 0x056a5080, 0x83f4ff21, + 0x83f3201b, 0x820120b3, 0xedff299e, 0x8c083433, 0x0a00ff7b, 0x176da182, 0xe6092405, 0x82ffff68, 0x20c082b0, 0x21268208, 0x9b82fbff, 0x830a0021, + 0x84fc2009, 0x223f83e9, 0x826666fe, 0xcc01281e, 0xfeffffce, 0x82059a99, 0x3233243e, 0x83fdffff, 0x830620fa, 0x41fd2014, 0x7a84070e, 0x0400ff22, + 0xfd25fa83, 0xffffcc4c, 0x204d82ff, 0x203e82ff, 0x2139848b, 0x35828c08, 0x829a9921, 0x20a68316, 0x833582fe, 0x820e824f, 0x00ff2295, 0x06884100, + 0x93832a82, 0x8387fd20, 0xccfeff27, 0xffff08ce, 0x247384fc, 0xffff0080, 0x841e83f8, 0x82f9203d, 0x42002063, 0xf520059d, 0xf7205788, 0x00213882, + 0x20238302, 0x511382f4, 0xfe2006e0, 0x0020ac83, 0xff230f82, 0x829819fe, 0x9a99226b, 0x82058489, 0x05a34158, 0x829a9923, 0x82fc82ff, 0x66fd27b3, + 0xf7ffff68, 0x1a829a99, 0xa783fd20, 0xd2820a82, 0x8232b325, 0x830800ff, 0x2114821a, 0x726dff08, 0x82ff2005, 0x0100218e, 0x00215582, 0x20898400, + 0x203e82cc, 0x203982fe, 0xb34d1892, 0x20758207, 0x422f82ff, 0xfe22063b, 0x5482cc4c, 0x07209582, 0x089f4e18, 0x83343321, 0x186620cf, 0x2412bb60, + 0x9a190700, 0x2117828b, 0x515466e6, 0x05196207, 0x53820120, 0x4c060024, 0x67188dcc, 0x08240977, 0x0600ff97, 0x0a208583, 0x6a694e82, 0x22858205, + 0x831200ff, 0x0000226f, 0x205e8266, 0x21358210, 0x1e83f6ff, 0x09830a20, 0xccccf523, 0x208a8291, 0x253483f6, 0xff989905, 0x1582f4ff, 0x4c03002d, + 0xf6ffffce, 0x00ff32b3, 0x8232b302, 0xe6ff2a1e, 0xff058b66, 0x0080f5ff, 0x06f84d8e, 0x41820220, 0x66faff24, 0x1d828e66, 0x0b82fb20, 0x99020022, + 0x0124a483, 0xff8b6666, 0x08226883, 0x30828c8b, 0xccccff24, 0xa78400ff, 0x00800022, 0xe6201782, 0x85848082, 0x34b30022, 0x0022cc82, 0x14869a99, + 0x42830120, 0x02200484, 0x0230a483, 0x8b083233, 0xf70e058b, 0x1554f80c, 0x4c0d00ff, 0x2512135f, 0x06b30783, 0x49180793, 0xb3220849, 0x135fff33, + 0x07832221, 0x20338cbb, 0x67338834, 0x7b5f10a5, 0xa3678f08, 0x72232033, 0xb36a0fd7, 0x10cc6a07, 0x2007e56a, 0x2031972b, 0x2156182b, 0x064b2817, + 0x6b0734f7, 0x8214f706, 0x82eb2004, 0x072b2503, 0x14fb06ab, 0x34210483, 0x06526107, 0x74134048, 0x5b201631, 0x4f823382, 0x4f83ab20, 0x8506ab21, + 0x836b204f, 0x2104824f, 0x86180734, 0xeb20187d, 0x00259d82, 0xff34b311, 0x7d861800, 0x6a18860e, 0x3a53117d, 0x20319205, 0x17cb41f3, 0xfb1cf722, + 0x189ce518, 0xcb075b22, 0x19053d62, 0x2513a492, 0xcb15bb6b, 0xa187ab06, 0x84f1ff21, 0xcc4c2374, 0x4818ffff, 0x471808c6, 0x927409d1, 0x076b3108, + 0xfd01ff0e, 0x00ff6666, 0x15cccc8c, 0xe6faffff, 0x0b200a82, 0xff233a82, 0x460080f4, 0x2608052e, 0x3433f3ff, 0x064b088b, 0x000000ff, 0x0564f706, + 0x1500ff8b, 0xff799a19, 0x66e61200, 0x75088b75, 0x8b79798b, 0x82ff0875, 0xfbfa2200, 0x211d821a, 0x3982faff, 0x88fbff21, 0x230e8204, 0x0677088b, + 0x80235b82, 0x84ff8b00, 0x04002118, 0x00290a83, 0x089a9904, 0xe6ae00ff, 0x82b48366, 0x83aa8253, 0x2457877e, 0x33ecffff, 0x215b8334, 0x208242fb, + 0xfc205685, 0x4284aa82, 0x99f9ff23, 0x2256859a, 0x556666fb, 0x661805e1, 0x802408e5, 0xf78b0800, 0xa88e8a83, 0xedffff24, 0x5083ffff, 0x64fb8b28, + 0xc0ffff05, 0x9582d7e3, 0x8340f321, 0x80f42395, 0x1e5affc5, 0xe0fa2905, 0xf4ffff00, 0x8608cc4c, 0xce280683, 0x3f0200ff, 0xf2fffff3, 0x00247782, + 0xff0dc008, 0x3c06a270, 0xfb9a9966, 0x00ff0502, 0xffcbe122, 0xccccd9ff, 0xb33500ff, 0xeaffff33, 0x00ff9a19, 0x05825938, 0x34333826, 0x3300ff8b, + 0x152cd183, 0x00ff48e1, 0xff32b324, 0x00402600, 0x3d82f282, 0x3d83f720, 0x12830820, 0xb85e0922, 0x4c346482, 0x0d00ffd0, 0xffff9a99, 0xfffefffa, + 0x32b30b00, 0x02ffff08, 0x93240f83, 0x56153433, 0xd42ae082, 0x8bcb70fd, 0x8b8b088b, 0x6c82cbb6, 0x8b900222, 0x35204782, 0xb6210682, 0x2115844b, + 0x2082ffff, 0x82564b21, 0x15eb2420, 0x55eeffff, 0x482006c6, 0x560b7955, 0x00220632, 0x1685610e, 0x8506c455, 0x84ff2006, 0x0a105616, 0x7e18bb82, + 0x0e2413aa, 0x4cf001ff, 0xf52eee82, 0xfb150080, 0x0f00ff02, 0xff054861, 0xe0832900, 0x66666822, 0x06260a82, 0x00ff00a0, 0x6282a110, 0x82beed21, + 0x9e0f28d8, 0xffff7cb8, 0x824861f6, 0xf3a12ccf, 0xc4ffff34, 0xff050a17, 0x82deddff, 0x196b221b, 0x2b0a829a, 0xffe23afd, 0x66a60800, 0xccf8ffff, + 0x04275882, 0xffff0040, 0x8234b3f7, 0xf9ff23df, 0xb4820080, 0xff221683, 0x1682c0fb, 0x8233fd21, 0x5ef72240, 0x214b82b8, 0x3082e6dd, 0x48e19427, + 0x00ff2d05, 0x2406823b, 0x0900ff7c, 0x22228280, 0x82aec7ed, 0x66662cf3, 0x9e0600ff, 0xeeffffb9, 0x82085278, 0x9ad9259e, 0x9997ffff, 0x91266d83, + 0xffffc2f5, 0xa982a6f0, 0x80eeff26, 0xfdffff41, 0xfb273483, 0xffffbedf, 0x823333e8, 0x47bd82ce, 0x00280504, 0xffd72362, 0xb95ecbff, 0xb527a282, + 0xffff707d, 0x820080ac, 0x1ef5250a, 0xf3ffffb8, 0x00228c82, 0x54821909, 0xad82ed20, 0x210f0023, 0x22ad8248, 0x82400100, 0x01002cad, 0x00ff3168, + 0xff004000, 0x82600100, 0x82098204, 0x996c2780, 0x1700ff99, 0x408248a1, 0x8f206b84, 0xff264b84, 0xffff0781, 0xf4824cf4, 0x67660922, 0xb583fe82, + 0x4b83c482, 0x83200521, 0x4105254b, 0x0200ff48, 0x03234b83, 0x8290b8de, 0x21442147, 0x58201082, 0xff2aee82, 0xe23a4400, 0x1ea7ffff, 0x218205b8, + 0xffd6e329, 0x34f3faff, 0x830600ff, 0xccfd2193, 0x05225182, 0x47833233, 0xff234e83, 0x82610900, 0x83072036, 0x82ff20da, 0x0b002cee, 0xff0800a0, + 0xcef7fbff, 0x837000ff, 0x6c002188, 0xff221582, 0x4b835ee8, 0x2a821120, 0x83fcff21, 0xde0b2372, 0x9e82a0b8, 0x0d217183, 0x25308340, 0xff707db5, + 0x30845300, 0xd8236227, 0xb83400ff, 0x277c8252, 0xff5ca40f, 0x295c0800, 0xe6215082, 0x24e48264, 0xffffcdcc, 0x224f82ee, 0x83800200, 0x33622b34, + 0x92ffff34, 0xff1566e6, 0x9c82ccff, 0x330b0031, 0xff8d0534, 0x0040caff, 0xdfffff05, 0x51ffb85e, 0x0a8405a4, 0x82d5ff21, 0xff8d245c, 0x83c03500, + 0x28cc221c, 0x217e82f6, 0x6382cccc, 0x82a12321, 0xde2721bf, 0xff289f82, 0xff52f8d0, 0x48211900, 0x34331582, 0x00ff9999, 0x05676607, 0x3100ff77, + 0xb805cdcc, 0x84e3ffff, 0x660f27c3, 0x3300ff67, 0x2382e23a, 0xc9821020, 0xbfccff23, 0x231c82ff, 0x49a11c00, 0xec277382, 0xffff9ad9, 0x825138ce, + 0x8234201c, 0xf8ff2a56, 0x5c0500a0, 0xdee6ffff, 0x321182b9, 0xff84ab23, 0xe01ad8ff, 0xffaf0e05, 0x68e62a02, 0x849a00ff, 0x1ec521ba, 0x04825c82, + 0xb3052308, 0xd5ffff06, 0xffff142e, 0x2c48e1a1, 0x90ffff4a, 0xffff66e6, 0x089a19ff, 0xb391ffff, 0x0000ff33, 0x1b820002, 0x4126e883, 0xffff48df, + 0xa28219d6, 0xb81e5e23, 0x27378308, 0xff4721c5, 0x66e63a00, 0xfc268482, 0xff9db89e, 0x9c82feff, 0x8010002a, 0x00ff8b00, 0x08676611, 0x05220682, + 0x438200c0, 0x09850483, 0x09822083, 0x06ba0822, 0x16834b82, 0xff3f2922, 0x0e20a682, 0x0032b882, 0xff9a9941, 0xe17a2600, 0xba3900ff, 0x3600ffe2, + 0x0e8271bd, 0x08b8de32, 0xc00200ff, 0x00ff8d00, 0xff604503, 0x48010100, 0x40220982, 0x16828b42, 0x69820520, 0xffff902b, 0x8e0040fd, 0x80fbffff, + 0x21128200, 0xae822003, 0x83a0fb21, 0x82802074, 0x3efa2e09, 0x088689b8, 0x80f9ffff, 0xefffffc4, 0x20c082c1, 0x216482fc, 0x3882eeff, 0x0583ff20, + 0xff27a282, 0xffb8ded2, 0x82211500, 0x82d6201b, 0x24002832, 0xffffb89e, 0x827ad4e4, 0x0c04274c, 0xfdffffcc, 0x80825338, 0xff231982, 0x82cd4cfb, + 0x9a1921cb, 0x33216b82, 0x231e8233, 0x86004000, 0xff211f82, 0x241082be, 0xffff7d3f, 0x23dc82fc, 0x83c0fcff, 0xdf206f82, 0xe2250a83, 0xffffb99e, + 0x280983f1, 0x944661d3, 0xe6d4ffff, 0x25358268, 0xff42c009, 0x6482cfff, 0x21270026, 0xd9ffff06, 0x00221f82, 0x7d826130, 0x48a1f622, 0x02201e82, + 0x00246982, 0x05b85e41, 0x98828482, 0x80edff23, 0x057c5200, 0x65828920, 0x82bedf21, 0x23308280, 0x4240fdff, 0x08209484, 0x0a82fd84, 0x21080a43, + 0xfb822004, 0x82e00121, 0x40032204, 0x204f8200, 0x22d88214, 0x83c02100, 0x82d52044, 0x0800234f, 0x4f8384a0, 0x20826020, 0x25820020, 0x2a854982, + 0x00ff8b26, 0x0800c003, 0x50820685, 0x1685c020, 0x5a821582, 0x2a820020, 0x2a204b82, 0x08204b83, 0xeb274b84, 0x00ff7fea, 0x82f6b321, 0x19fe224b, + 0x21258299, 0x9a829a19, 0x0420bb83, 0x02220983, 0x7b4a34b3, 0x02002106, 0xd5844983, 0x82200421, 0x830020b4, 0x1f032279, 0x20b882be, 0x209f83e0, + 0x20fa831e, 0x29ef83eb, 0x707d0b00, 0xcc1f01ff, 0x498205cc, 0xff7a5426, 0xac510400, 0x66215882, 0x21048268, 0x04820672, 0x82666621, 0xfe032118, + 0x04278882, 0xffffac3c, 0x8202fcff, 0xa2852114, 0x8d210882, 0x061741fa, 0x0ca2fb22, 0x48831e82, 0x33e0fe23, 0x83488234, 0x1400235e, 0x0a8248a1, + 0x00200322, 0x04839382, 0xff218883, 0x21d783ff, 0x8883bf02, 0x88838020, 0xff21a783, 0x209d83fd, 0x26c68200, 0x00e0fbff, 0x82feffff, 0xfcff212d, + 0xff28a783, 0xffb8deeb, 0x0040deff, 0x2a254882, 0xffff4821, 0x200a84f7, 0x21448203, 0x5884ffff, 0xff24e682, 0x8b00c0fc, 0x40228e82, 0x06850800, + 0x83059d41, 0x82158216, 0x232a835a, 0xd5ffff08, 0xf7224b83, 0x4b827c5f, 0x4b831420, 0x01205685, 0x41827183, 0x8505b958, 0x40fd2180, 0xfd218582, + 0x209f8260, 0x450a85ff, 0xff2008dc, 0xe0226f84, 0x4f828d42, 0x4f82e420, 0x80120022, 0x02209b83, 0xbe202083, 0x3025ef84, 0x00ff4861, 0x21758209, + 0x64822700, 0xc1260022, 0x35820e83, 0x5e300024, 0x198208b8, 0xff420024, 0x19822b00, 0x3ff1ff27, 0x2c00ffbe, 0x20df829e, 0x236e82df, 0x9a591d00, + 0xfc205382, 0x03200a83, 0xff207e84, 0x04221e82, 0x624183c0, 0x04002305, 0x3d827dff, 0xf3830020, 0xb1820420, 0x80020022, 0x04234782, 0x5e8f00a0, + 0x24210711, 0x206882a1, 0x2f58821b, 0xb81e1500, 0x802900ff, 0x00ff8b00, 0x08862b2d, 0x11200682, 0xfc249e83, 0x00ff00a0, 0xf9200984, 0x00260e82, + 0x08004010, 0x3d429089, 0x83052006, 0x840320a0, 0x4661265c, 0x00ff8e08, 0x20228304, 0x20ab8305, 0x231a8302, 0x8bbe7f05, 0x03217e82, 0x27548340, + 0xff583903, 0xa00bffff, 0x2305ae42, 0xe6fffdff, 0x36201a82, 0xff212682, 0x2a7983d9, 0xffb08726, 0xc435c6ff, 0x830e00ff, 0x83be20dc, 0xd6ff21f6, + 0xd6251e83, 0xba05ffbf, 0x20728206, 0x20e98240, 0x25e482fa, 0x14bf0000, 0x0982ffff, 0x05848b20, 0xff271582, 0xffffd4fe, 0x826f9dee, 0x34332160, + 0x24067751, 0x799c99fc, 0xaa717008, 0xc5feff2b, 0x00ff9a19, 0x159a99af, 0x0b5d5cff, 0xd6420320, 0x8b902306, 0x0b8300ff, 0x3b450483, 0x210a8306, + 0x8456908b, 0x33168505, 0xb89ee5ff, 0x801a00ff, 0xff950500, 0x00c01400, 0x401000ff, 0x11200482, 0x20080483, 0xff482114, 0x00400b00, 0xffff7a08, + 0x9148e1e4, 0x5edcffff, 0xffffa4b8, 0x08b81eec, 0xe6f1ffff, 0x27048266, 0xff86ae47, 0x66e6eaff, 0xec221c82, 0x66829a99, 0x00e00522, 0x54832182, + 0x87831020, 0x4883f120, 0x48e11325, 0x60fbffff, 0x60200550, 0x202d5d82, 0xff0500c0, 0x1ea5f5ff, 0xe6f8ffff, 0x220a8266, 0x6e6766ff, 0xff2305b2, + 0x829919ff, 0x33b32109, 0x33270482, 0x8a088b34, 0x57ff8a8b, 0xff20055c, 0x00224883, 0x798200a0, 0x67830a85, 0x0080ff23, 0x23e5828c, 0x08002001, + 0x00210682, 0x205b82a0, 0x83278400, 0x830985c8, 0x08002131, 0x00285082, 0x05cd4c0e, 0x0300ff79, 0xfe207c84, 0x60202684, 0xfe20ab82, 0x01223583, + 0x408200c0, 0x84e00121, 0x49068247, 0x0120060d, 0x83841b86, 0x879d0821, 0x4cf7273c, 0x0e00ffcd, 0xb9839a39, 0x82333321, 0x9999212b, 0x09832182, + 0x0e840220, 0x82666621, 0x34332213, 0x86058208, 0x00ff240a, 0x829a1902, 0xcc4c2123, 0x80201382, 0x6a827583, 0xffff972a, 0x0500e0f7, 0x990400ff, + 0x6e221b82, 0x0a821ec5, 0x92180020, 0x012108d8, 0x212b83cc, 0x3a8448a1, 0x4b828b20, 0x9a190222, 0xc624a383, 0xfeffff66, 0x0022b882, 0x47822000, + 0x00c0fd22, 0x04201a82, 0xff23ef82, 0x8233b38f, 0x1e0e2740, 0x0900ffb8, 0x0a8201a0, 0x82050f41, 0x0000236d, 0x7c8200e0, 0x00222f82, 0x0985c000, + 0x01213482, 0x20f38480, 0x41458240, 0x1a820551, 0x84feff21, 0x2325834f, 0xffbffeff, 0x39820082, 0xff216e84, 0x842883ff, 0xf7ff271e, 0xffff4881, + 0x6e83d3f1, 0xaf821120, 0x40fcff22, 0x0120c583, 0xff213f83, 0x205f82a0, 0x839e8201, 0x828b2034, 0x002022a9, 0x82068508, 0x211b820b, 0x4684feff, + 0xa0207484, 0xff22ba82, 0xcf82e6ee, 0x3453fc22, 0x07cb4018, 0xb89ef122, 0x80850a82, 0xde54ab86, 0x87808b05, 0x8419828b, 0x82538474, 0x051c42ce, + 0xff206f82, 0x6584eb84, 0x00228b82, 0x6a836000, 0xcd6cf327, 0xa70800ff, 0x845f82ae, 0xc0dd21a1, 0x1325b683, 0x00ff47e1, 0x2b2f8304, 0xffb81e10, + 0x48c10e00, 0xe10500ff, 0x132d0482, 0x9108b85e, 0x611300ff, 0x00ff8648, 0x204b8315, 0x241683f1, 0x08b89e0e, 0x211682a4, 0x1c8248e1, 0xb89e232c, + 0x1b00ff7a, 0xff084821, 0x22831400, 0x8f82f420, 0x2110002d, 0xeeffff48, 0xff9500c0, 0x8340ebff, 0x9ee52579, 0xe5ffffb8, 0x2507eb47, 0xe0fcffff, + 0x54828b00, 0x4307a943, 0x1683069d, 0x830eb443, 0x06495f76, 0x0af70226, 0xdef5ffff, 0x0222a282, 0x09829a19, 0x8021ee82, 0x21ea8308, 0xa6410080, + 0x82ff2006, 0x200a8212, 0x20718380, 0x212882da, 0x7184dfff, 0xe25afe2d, 0x66feffff, 0xffff8a66, 0x82cdccfd, 0x66e62120, 0x75820984, 0xf6820020, + 0x82feff21, 0x00002304, 0x2482e69f, 0x59210984, 0x470982b4, 0x5a830534, 0x9a59fe28, 0x330200ff, 0x05838a32, 0x3e843420, 0x01233982, 0x828b9a19, + 0x66c62610, 0xbf0000ff, 0x062e43f9, 0xa1590022, 0x17201a82, 0x9447ec82, 0xf4ff2d05, 0xffff146e, 0xff1e45cf, 0xceccd3ff, 0xca267582, 0x088b66e6, + 0x0683ffff, 0xe62c1282, 0xffffb067, 0xffcd4cf4, 0x9a993100, 0xff203886, 0x22052c48, 0x827b9401, 0xe1ba2184, 0xb2845882, 0x82676621, 0x22b78309, + 0x8266e6ff, 0x60032229, 0x207d8300, 0x07f247e0, 0x00400123, 0x2016828e, 0x20bf8301, 0x47048203, 0x032205b4, 0xe88200a0, 0x0023c382, 0x82002002, + 0xd9da2176, 0x2023c982, 0x82050080, 0x8200203b, 0x82ff2016, 0x20be824c, 0x824b8380, 0x8b08220f, 0x20d18296, 0x27238219, 0x8e00800a, 0x190a00ff, + 0xfa209483, 0xfe237582, 0x746666e0, 0xaf2337e7, 0x821601ff, 0xbe01256b, 0xff15028b, 0x21061a54, 0x09824ef1, 0x82989921, 0x33062286, 0x08e78234, + 0x08b20e20, 0xffff94f7, 0x053cffaf, 0x660d00ff, 0xfbffff68, 0x00ff7ad4, 0xff981909, 0x48a1f3ff, 0xbc837d8b, 0x07cccc33, 0xcce4feff, 0xa7ffffcc, + 0xff050180, 0x68e6fcff, 0x8305828a, 0x210b8346, 0x1d83088c, 0x00fff425, 0x82ff7f58, 0x33252345, 0x5f820734, 0x70fd0d22, 0x18264782, 0x0c00ffae, + 0x5b824861, 0xffee5c31, 0x862b0400, 0x0001ff08, 0x00ff3e0a, 0x82c40050, 0x8209202b, 0x42ff239f, 0x9f82ca41, 0x7282e320, 0x33470023, 0x275f8234, + 0xff68e61c, 0x703d4700, 0x2b820a83, 0xc2b8ff23, 0x272b8290, 0xffc2f5e3, 0xccccb8ff, 0x0e210a82, 0x2d8b824c, 0x1568e6b2, 0xb31101ff, 0x5500ff34, + 0x2b820080, 0x9999d126, 0xcbffff07, 0x82065547, 0x99f72710, 0xfdffff98, 0xd482cd4c, 0xffce4c2b, 0x9a19f7ff, 0x990200ff, 0x4209829a, 0x3a820563, + 0x2383ff20, 0xe6080023, 0x21238564, 0x90820800, 0x08232383, 0x822b00ff, 0x0d002148, 0x76225984, 0xd282cccc, 0xe6f2ff26, 0xf6ffff66, 0xfa7b9c82, + 0x83f22005, 0xe6fb265e, 0x94fb0866, 0x296d823b, 0x89ccccf9, 0x66f9ffff, 0x05828b68, 0x8dcccc29, 0xfffeff08, 0x82dbc2f5, 0xa2f22219, 0x82fb82d1, + 0xf6ff2a7d, 0x00ff6de7, 0x8bcc4c0d, 0x23608299, 0x07ce4c88, 0x3a246682, 0xf2ffffe1, 0x00236683, 0x82a47008, 0x666621af, 0x2206f368, 0x8232b304, + 0xd7a321af, 0x66210e82, 0x222f8268, 0x8248a102, 0x21a0820a, 0xff82fbff, 0x8d82b482, 0xeb91f722, 0xb3222382, 0xf8820833, 0xff523824, 0x48841000, + 0x67662e23, 0x051a4107, 0x84aaff21, 0x82092010, 0xfdff2d30, 0x00ff9819, 0x8b9a1909, 0x330a00ff, 0xe6245a83, 0x8b8b0868, 0x46229f82, 0x44820180, + 0x15989923, 0x068e58ff, 0x829a9921, 0xeb112109, 0x23051341, 0x295cfdff, 0x99210e82, 0x22638298, 0x86b85efd, 0xb3042223, 0x06514134, 0xb0820820, + 0x4cfdff26, 0x77cb08ce, 0x20074945, 0x21c384fd, 0xf58267e6, 0xb321c384, 0x21c38833, 0xc3889999, 0x0982cd20, 0xc383e620, 0x002f6e82, 0x0832b302, + 0xf7059f4b, 0xe1fffff4, 0x84156866, 0x8394822f, 0x8304203e, 0x83082004, 0x21578529, 0x89830080, 0x85ce4c21, 0x05d64123, 0xbc842383, 0x2382ff20, + 0x824b0821, 0x41ff2089, 0xce2006fd, 0x2018fd41, 0x86d58432, 0x84fb2084, 0x0080214f, 0x992d7382, 0x9fcb089a, 0x20ffff05, 0xffff0100, 0x0f1641f6, + 0x86991921, 0x4cfd2250, 0x081641cd, 0x07534618, 0x82040021, 0x419185ea, 0xff250816, 0x01802600, 0x073c647f, 0x83138441, 0x97002121, 0x08222182, + 0xf3b86866, 0xd9ffff24, 0x66829899, 0x82129d43, 0x97993319, 0xffaf0e05, 0x34b3bf01, 0xe67e01ff, 0xffff1566, 0xeb82c0f9, 0x00800322, 0xf52dc382, + 0xfeffffc2, 0xff86dcd9, 0x00a0faff, 0x20058208, 0x821582e0, 0xffff2c0a, 0xffc04aff, 0x4601f8ff, 0x830300ff, 0xdef92613, 0x00ff08ba, 0x20348310, + 0x2d3e83e5, 0xffe2ba08, 0xf6e8e1ff, 0xe0ffff8b, 0x398248e1, 0x1582ff20, 0xbfcaff22, 0xe52a3882, 0xffff9082, 0xff67a6ce, 0x2e83d3ff, 0x3233e222, + 0xb3271e82, 0xffff4861, 0x8266a6ca, 0x1e142dea, 0x00ff07b8, 0xff90022c, 0xb81e2400, 0x60831082, 0x26050c47, 0xffa61b01, 0x82010600, 0x82fd202a, + 0x05002274, 0x22598321, 0x82261cf8, 0x82552179, 0x21262982, 0x00ff48e1, 0xbe824013, 0x5c0f172a, 0x00ff8baf, 0x0800c029, 0x28200682, 0xe92a7c83, + 0x00ffa4f0, 0xffb85e23, 0x7782dfff, 0xa1130022, 0x00283c82, 0xffa82605, 0xd8630b00, 0x02213c82, 0x20378260, 0x231a8205, 0x869bfeff, 0x29836682, + 0xde7ffb22, 0x3a21e082, 0x21a182e0, 0xeb8216c5, 0xacc0352d, 0xc4ffff05, 0xffff33f3, 0x82e03acb, 0x8cfb310a, 0xfbffffcd, 0xffffe6c1, 0xff34b3fd, + 0x66a6f9ff, 0x19312f82, 0xfaffff99, 0xff080080, 0xf8330500, 0xaef4ffff, 0x25298214, 0xff6fb2de, 0xe683ecff, 0xccccea2d, 0x9cdcffff, 0xffff8b28, + 0x829a19d8, 0xd6ff219f, 0x1426b284, 0x00ff677b, 0xa082de21, 0x82c0ec21, 0xf7ff283c, 0xffff0140, 0x8266e6ed, 0x83fe203c, 0xccfa2332, 0x58828cce, + 0x8f323322, 0xb3217282, 0x265e8234, 0xff9a192b, 0x82e3dbff, 0xecff2ebd, 0xff070a17, 0x3333b4ff, 0x6b3500ff, 0x20328284, 0x21f382d3, 0xce831d00, + 0xae87e52a, 0x663100ff, 0xffffff66, 0x35221383, 0x73823433, 0x1e1f002d, 0x0800ffb8, 0x00ffe1ba, 0x417c141e, 0x002205ba, 0x7782401a, 0xd7030023, + 0x20fe820b, 0x202f8226, 0x243e82fe, 0x66a60700, 0x82c98286, 0x8306831a, 0x82f720c0, 0x0000224b, 0x25a882de, 0xff9a99f9, 0xea83fcff, 0x8ab1ff26, + 0xd5ffff3d, 0xd9263583, 0xffff7d5f, 0xcc8266a0, 0x83a02333, 0x33a5ffff, 0x79920833, 0xe10a00ff, 0xefffff48, 0x2075829e, 0x2304820c, 0x4861f1ff, + 0x372dc182, 0xffff85eb, 0x05b89ebe, 0xe00400ff, 0x21dd8200, 0x95820040, 0xff0a3726, 0x9c84feff, 0x21057f54, 0x5f830300, 0x834f0021, 0x402a2219, + 0x30298200, 0xff90421d, 0x48a1ebff, 0xd0ffff05, 0xfffff6e8, 0x221583df, 0x8260feff, 0x8200203a, 0x05785e04, 0x82a00021, 0x06ff254e, 0xff088b66, + 0x2107b37e, 0x2179ae47, 0x2889190b, 0x52b82408, 0x82f6ffff, 0x0d0023b8, 0x2d820040, 0x210c0029, 0x00ff8b48, 0x82299c09, 0x42202404, 0x820100ff, + 0x0b0023ae, 0xae82be9f, 0x99992825, 0x841c00ff, 0x17e2236e, 0x3782070a, 0xfa206583, 0xf9217483, 0x215d8267, 0x3a8241f6, 0x4ff4ff21, 0xee27058d, + 0x00ff4861, 0x82b85e0e, 0x1e85267f, 0xba1000ff, 0x215d83e2, 0x2282a111, 0x780d0023, 0x821b8452, 0x20178268, 0x21068208, 0xaf82c00b, 0x1058f922, + 0xc5217482, 0x8258831e, 0x9e052279, 0x277482ba, 0x07b81e1e, 0xde2800ff, 0xe3224882, 0xff821e85, 0x74830120, 0x5882f420, 0x9a090023, 0x202a82e2, + 0x226782e1, 0x83b81e0c, 0x24c2835d, 0xba0a00ff, 0x07de60e2, 0x5d831082, 0xfb820682, 0x86824520, 0x67830a20, 0x83c0f221, 0xfeff28e9, 0xff8b0020, + 0x8280feff, 0x83ff2079, 0x83fe20c3, 0xa0ff2304, 0x58410800, 0x20002305, 0x6e8200c0, 0x00401d27, 0x5e1400ff, 0x250a82b8, 0xff90424f, 0x1584d5ff, + 0x84830620, 0x3a82fc20, 0x3708002b, 0x0100ff0a, 0x00ff647b, 0x22a38204, 0x82c00500, 0x3400273f, 0x00ff9082, 0xae83453d, 0x46e11223, 0x3fec82a1, + 0x00ff5438, 0xff707d19, 0x68260800, 0x1e1c00ff, 0x00ff08b8, 0xff388a16, 0xc6b55200, 0xe6d9ffff, 0x532c1482, 0xffff32b3, 0xff3433b6, 0x9a192900, + 0xa0288482, 0xffff9819, 0x159a1991, 0xe920a582, 0xf430b783, 0xffffcc8c, 0xff0a57ec, 0x48a1eeff, 0x80f4ffff, 0xff2a6a82, 0xff1263fa, 0x146e0c00, + 0x1c69ff05, 0x84182005, 0x62f026cf, 0x9c1a00ff, 0x826e822a, 0x82002038, 0x266e8213, 0xff7cbf07, 0x831e1100, 0x251022c9, 0x253f8264, 0x00ff9a59, + 0x6482990a, 0xcc4ced22, 0xea216382, 0x23758399, 0x8b010080, 0x00237182, 0x82486115, 0x85ab2c1d, 0xc71200ff, 0x00ff9bae, 0x8348a10b, 0x16d92143, + 0xd4207d82, 0x23081668, 0xffb85ee7, 0x3c250082, 0x85e5ffff, 0x2481821f, 0xfffff23f, 0x269785e7, 0xffff9d62, 0x820b97f3, 0xb3ee2297, 0x833f8233, + 0x66f42897, 0x1300ff67, 0x828b33b3, 0x333334fc, 0x00ff0e08, 0xff9a19f0, 0xb4c8bb01, 0x00ff9415, 0x82fa9e05, 0x66e621ca, 0x09271d82, 0xffff66e6, + 0x820661fa, 0xb3ab2b72, 0x9dffff34, 0xff05e6d0, 0x43830300, 0x6666fe22, 0xff2d5382, 0xff079a19, 0xcccc3000, 0xb3e4ffff, 0x2b1b8232, 0xff9a990c, + 0xceccf8ff, 0x190600ff, 0xf129d282, 0xffff3233, 0x7dce4cfc, 0x82068508, 0x824c208b, 0x33f6312b, 0xf0ffff34, 0x088b9a99, 0xff0654fc, 0xd763f2ff, + 0xf323f882, 0x60ff144e, 0xfc2405b8, 0x0899a846, 0x06823082, 0x2d244782, 0x0e00ff50, 0x0c215183, 0x229d8298, 0x82323307, 0xfa2e278d, 0x1b00ffe1, + 0x7182ce4c, 0x66e60022, 0x05278282, 0x00ff1f45, 0x829a9901, 0xbaab2710, 0x6200ffe2, 0x9e821a2f, 0xbf834f20, 0x4c37242d, 0xfb06cb15, 0x06b30754, + 0x840754f7, 0x88bb2009, 0x24138609, 0xb33bffff, 0x20468234, 0x24be8300, 0xff32b3ff, 0x05e45d00, 0x0982e982, 0xfe25c882, 0xbb0834b3, 0x215d826b, + 0xba82b30b, 0xd682f820, 0x83050021, 0x66f123c4, 0xc36aff68, 0x80f22205, 0x20b38200, 0x827183fb, 0x25e8820a, 0xffff9a99, 0xed82ccf6, 0x66e6f122, + 0x0983e886, 0x8f211982, 0x83e8825c, 0xe9fb253d, 0x0d00ffba, 0xe9213885, 0x230a84fc, 0x3a0500ff, 0x0e2fdb82, 0x00ff9899, 0xffa6bb0b, 0xcecc0700, + 0x82abbb08, 0x91002279, 0x21e282ec, 0x9b82cc4c, 0xff0a9724, 0x9b84ffff, 0x002f0982, 0x08ce4c00, 0x4cc400ff, 0xef0e07cc, 0x83bf00ff, 0x66ff2381, + 0x7d821566, 0x8be73b22, 0x492b0582, 0x0200ff38, 0xffff10f8, 0x8233b3f7, 0x08ec215e, 0x7b2ea782, 0x00ff48e1, 0x054e8263, 0x3374ffff, 0x525a0734, + 0x94f72216, 0x16555a06, 0x8b00ff2f, 0xff07cccc, 0x33337cff, 0xb39cffff, 0x20478234, 0x619082f7, 0xf62305d0, 0x82889a19, 0x99192277, 0x2e97828b, + 0xff9a1900, 0x9a990001, 0x00ff8b15, 0x18004023, 0x84097579, 0x088b240e, 0x5d0674f7, 0x9e230575, 0x70ffffb8, 0xff2907cc, 0x4861eeff, 0xd4fb088b, + 0x09c36a06, 0x035b9920, 0x54fb2b0b, 0xab06eb07, 0x4b14f707, 0xa482fb15, 0x210a0b71, 0x8770f1ff, 0xffff2b08, 0x07ecd1f3, 0xffff2bf7, 0xa182338e, + 0x82050021, 0xfcff277e, 0x00fff047, 0xb6827307, 0x28fcff2c, 0x910500ff, 0x0300ffec, 0xa982e8fb, 0xe1ba962c, 0x877100ff, 0x00ff05ac, 0xf718330c, + 0x4f8308f3, 0x2305266b, 0x6666eeff, 0x9422af82, 0x978c15eb, 0xfa709a20, 0x826b200b, 0x00ff2496, 0x82004021, 0x611b25ed, 0xe6ffff48, 0x0022d682, + 0xf1471e03, 0x20648205, 0x25838300, 0x0548e179, 0x5b4154f7, 0x54f72217, 0x213d8207, 0x58849911, 0x7b889820, 0x088b6835, 0x1514fb6b, 0x07cb064b, + 0x074b06cb, 0xb4f8ef0e, 0x6115c4f7, 0xff240562, 0x68e6f8ff, 0x1920d682, 0xf7223382, 0x717e9819, 0x9a192206, 0xac60188b, 0x05b26109, 0x24fb0830, + 0xf706cb07, 0x14fb0724, 0xe63000ff, 0xdf411566, 0x33568216, 0x6bba9e11, 0x7a2d00ff, 0x088b8be0, 0xff6b8b8b, 0x48a1d1ff, 0xef234482, 0x85081e45, + 0x22998606, 0x82e2baf0, 0x9a992944, 0xffab088b, 0x9a19cfff, 0x6620928a, 0x1d829288, 0x71186b20, 0xe6210ea2, 0x21928e66, 0x92c434f7, 0xffff6822, + 0x98259286, 0xb4fb088b, 0x21e2cc8b, 0x4fce54f7, 0xffff0428, 0x159a19df, 0x2965066b, 0x24fb2216, 0x05557307, 0xf1ffff24, 0x04839899, 0xffff9a25, + 0x826866ee, 0x065423da, 0x8f1844f7, 0x4f991765, 0xfb074423, 0x0c554354, 0x210a196e, 0x4f8924f7, 0xff0ad726, 0x34330700, 0x28219682, 0x064f42f6, + 0x210ac96a, 0xa87dcccc, 0x85082005, 0x18ca209f, 0x2612c363, 0x4b0654f7, 0x1804fb07, 0x821be272, 0x2463825e, 0xf8ffff33, 0x07077fcc, 0x6bf4f721, + 0x082c1364, 0x8b0804d6, 0x821a00ff, 0xeaffff90, 0x002a0482, 0xff707d15, 0x707de5ff, 0x6182088b, 0x8207cb21, 0x18ff206b, 0x8a162f64, 0x856483d2, + 0x343326d2, 0x64fc088b, 0x1daa427b, 0x3d439920, 0x42cb2019, 0x662044a9, 0x2008a942, 0x42c7829a, 0xb9200659, 0x0e23e782, 0x5fff4861, 0x8c430fc2, + 0x42348221, 0x9e2406f9, 0xeb088bb8, 0x2040a842, 0x219e8b67, 0xdc4314f7, 0xef0e273d, 0x54f824f8, 0xdd829015, 0xcc042508, 0xfdffffcc, 0xff8e06a1, + 0x94f8fbff, 0x2200ff08, 0xffff34b3, 0xff32b3d1, 0x66662b00, 0x5ce3ffff, 0x3700ff2a, 0xdb220983, 0x1e82a470, 0x82330521, 0x80fc291e, 0x0500ff00, + 0xffff6866, 0x64200986, 0x66260982, 0xffa80866, 0x4f82ecff, 0x83100021, 0x80df2943, 0xffff8b00, 0x089a99dd, 0xe3200682, 0xff213182, 0x2f1683f4, + 0xff9a19e6, 0x0080edff, 0xfeff0878, 0x0698999b, 0x9e210c84, 0x251c82ff, 0x1900ff33, 0x938266e6, 0x00801c22, 0x00213382, 0x82758222, 0x2816824a, + 0xa8008020, 0x331300ff, 0x26808334, 0x00ff6766, 0x839a9903, 0x48662080, 0x002205ff, 0x24823305, 0x2005154c, 0x221e8337, 0x855c8f24, 0x1c0023be, + 0xd285d6a3, 0x4c2e002a, 0xff8e08ce, 0x6c070400, 0xe6203482, 0x02223982, 0x4382fa5e, 0x08277082, 0x04fb078b, 0x18154cfc, 0x181a6e4b, 0x2109196e, + 0xcd82cc4c, 0x34b3f226, 0x5b074308, 0xee21bb82, 0x07ff634c, 0x0aa36b18, 0x0714f722, 0x11204b82, 0x12a5ee18, 0x1834f821, 0x200fa250, 0x244e8234, + 0x08cc4cee, 0x203383fb, 0x220982ff, 0x82f1ffff, 0x82048538, 0x088b240e, 0x18d3065b, 0x222e094c, 0x824b0743, 0xe63a3966, 0x9e8b0766, 0x99f7ffff, + 0xffff9d9a, 0xff0080f0, 0xce4c0b00, 0xe7ffff08, 0x142afd83, 0x7205cccc, 0x33ebffff, 0x71820534, 0xff666626, 0x32b3f4ff, 0x79222c84, 0x2482788b, + 0x9a19c522, 0xd3244582, 0x26ffff07, 0x01331c82, 0x15ccccb2, 0xb00500ff, 0x0400ffa4, 0x00ff4044, 0x82ecd107, 0x3b0f83e2, 0xc0bbfbff, 0x057f9b08, + 0x332200ff, 0xe6ffff34, 0x00ffec51, 0xff333314, 0xa4b0d7ff, 0xd529db82, 0x8908a430, 0x0634fb07, 0x22c4838d, 0x825ccf2a, 0x6626251d, 0x4f2800ff, + 0x22210982, 0x25948240, 0x0814ae19, 0x8582979b, 0x9999b930, 0x3365ffff, 0x34f71534, 0x77ffff06, 0x7c826666, 0x66e6ec28, 0xf3ffff80, 0xaa829a19, + 0x82ce4c21, 0x41e8204f, 0xf620082b, 0x00289782, 0x829a1902, 0xb30300ff, 0xf7216f82, 0x20dc83cc, 0x21e782f9, 0xca83fcff, 0x4e83f820, 0x3983fe20, + 0x9919f825, 0x824b088b, 0x64471853, 0x07c42915, 0x6801ff0e, 0x17f89a99, 0x012be282, 0xffff66e6, 0xffb81efe, 0x82b30200, 0xe1fe22ce, 0x23098248, + 0x088bcccc, 0x05820685, 0xff349327, 0x00200100, 0x2105828d, 0x168200e0, 0x71821520, 0x9e150024, 0x1b8205b8, 0x83660621, 0x24738216, 0x48a10200, + 0x2210828b, 0x850800c0, 0x20548206, 0x2fec82e0, 0x8900a002, 0xffff088d, 0xff6686ea, 0x00a01500, 0xfb2bf682, 0xff8f00e0, 0x0060f9ff, 0x8387878b, + 0x82592019, 0x61ea2beb, 0x89890548, 0xfdffff8a, 0xf482b85e, 0x3f4efd20, 0x20068205, 0x2412828c, 0x898d0060, 0x203d8208, 0x20288399, 0x21428260, + 0x82823300, 0xe67dff33, 0xffff1566, 0x8b0040e5, 0xf5ffff72, 0xffffb89e, 0x23c682ed, 0x4821edff, 0xe7245582, 0xffff00c0, 0x6f820482, 0x8240f921, + 0x2304820a, 0xfcffff82, 0xf6230a83, 0x828b4861, 0x26d12621, 0x00ff0666, 0x2149820a, 0x37821600, 0x9e030024, 0x9682a5b8, 0xff82a120, 0x42841b20, + 0x9ad9f52f, 0xa62900ff, 0xdbffff66, 0x00ffcccc, 0x277e8321, 0xffcdccd4, 0xe2fa0600, 0xdb293f82, 0xff9100c0, 0x0040ddff, 0x207e8280, 0x29b082e8, + 0xa0f8ffff, 0x00ff8400, 0x6f826000, 0x8221f421, 0x20082347, 0xb8828500, 0xcd2c1a2b, 0x57ecffff, 0x00ff050a, 0x28968305, 0xff00a0fb, 0xb9de0700, + 0x830f828b, 0x8004227e, 0x22258200, 0x82e17a08, 0x82f9205a, 0xb30a2273, 0x061d5434, 0x04660b20, 0x821a2005, 0x83ff82b1, 0x80ea21e2, 0x0e785418, + 0x66eaff22, 0xe920a182, 0xff213282, 0x05ef64e4, 0x66e6e022, 0xcc218482, 0x23fa82cc, 0x8bb81ef4, 0x21269682, 0xf3ffff47, 0x6e82b85e, 0xffb95e26, + 0x4861f5ff, 0x10276e82, 0xffff152e, 0x829ad9de, 0x66022394, 0x1b828666, 0x88343322, 0xff219085, 0x229084ff, 0x189a1921, 0x220cac84, 0x8340e3ff, + 0xc0dc237b, 0x54820800, 0xff200682, 0x04861183, 0x8b260e82, 0x9fffff08, 0x1b8247e1, 0x52b8e531, 0x193500ff, 0xe9ffff9a, 0x00ff3333, 0x8266e626, + 0x73fb211a, 0x07210a82, 0x23148299, 0x8700c0f5, 0xf7222582, 0x16823233, 0x00e0ff26, 0x33c9ffff, 0x2928f182, 0xff2bb83e, 0x48e17600, 0x00214882, + 0x21e78346, 0x2e823800, 0x70390029, 0x00ff8ba4, 0x82f6a846, 0x17003176, 0xffff4861, 0xff4220f9, 0x14ae1500, 0x01f5ffff, 0x1221a282, 0x22d083e1, + 0x8200c015, 0x9e1a210b, 0x0026f182, 0xff482119, 0x2a820a00, 0x1b820020, 0x1200ff24, 0xf182b8de, 0x00401824, 0x048200ff, 0x0621f182, 0x820a82c0, + 0xff942304, 0x0a830300, 0x82760920, 0xab142d05, 0x0000ff84, 0x00ff28dc, 0x7a9a1910, 0xec22a282, 0xa2823433, 0x66e69b23, 0x062b5107, 0x82edff21, + 0xf5ff2144, 0x41500483, 0x82d82006, 0xffff233a, 0x7082a1e4, 0xff285b82, 0xb8def0ff, 0xa11200ff, 0xff2b9182, 0xffae47fb, 0x84eb0500, 0x82f6ffff, + 0xfcff23c7, 0x45829a99, 0x0080f822, 0xda295282, 0x8b079a19, 0xeb4b8b8b, 0x2098828b, 0x21eb8430, 0xa47c802f, 0x82eb8205, 0x20168210, 0x33238364, + 0x193700ff, 0xd3ffff99, 0x00ffcc4c, 0xff33b32d, 0xceccc8ff, 0x2a2b3383, 0x00ff3233, 0x159ad97b, 0x82aaffff, 0xbeff2138, 0xff217682, 0x230982ac, + 0x06613e00, 0x2906a646, 0x0842a002, 0x0400ff85, 0x985600a0, 0xffff2105, 0xff27eb82, 0xffb85efa, 0x8320fbff, 0x3afa2285, 0x240a84e2, 0x66feffff, + 0x82238267, 0x0300221e, 0x226e8299, 0x82b85ef9, 0x99012b80, 0x00ff889a, 0xff34b326, 0xdf83baff, 0x98994e23, 0x2216828b, 0x8248e14f, 0x821220a3, + 0x1f002270, 0x21f68261, 0x9b820c03, 0x82400621, 0x00002c50, 0x00ff68e6, 0xff842b02, 0x82800000, 0x4c0222cd, 0x222982ce, 0x82666602, 0x80232335, + 0x0c820700, 0x82400d21, 0xe6f0258c, 0x0700ff66, 0xff2a2182, 0x836666f5, 0xffef0e08, 0x0d827002, 0x4c640023, 0x20cf82cc, 0x21a082df, 0x0f820c00, + 0x83e7ff21, 0x42ef2d2c, 0xffff794e, 0x0842c0f3, 0xf4ffff7a, 0xf9201683, 0xff23a782, 0x824821fd, 0xb8de23b1, 0x0682088e, 0x6c82e020, 0x00200332, + 0x3efdffff, 0x0600ffb8, 0xff86a63b, 0x82001400, 0xfc201a82, 0x0022fc82, 0xf2831e0d, 0x10212483, 0x05a45b59, 0x8200ff21, 0x23958288, 0x8e004002, + 0x6782b182, 0x83020021, 0x8301201f, 0xc0022104, 0x0a27cb83, 0xffffd843, 0x82e25af6, 0xcc4c242a, 0x82f8ffff, 0x12002479, 0x828b3433, 0x19212235, + 0x25ca8298, 0xff20c511, 0x8b821900, 0x3a0a0028, 0x1100ffe0, 0x1a824821, 0x26830b20, 0x6f821020, 0x66040025, 0x18929068, 0x230dc754, 0x33b30a00, + 0x0d233882, 0x8508cd4c, 0xffff2206, 0x827a83f5, 0x05a25316, 0x8b690825, 0x82efffff, 0xe6ff213d, 0xff221782, 0xe382e1f4, 0xb8deee22, 0xf522c782, + 0x19826866, 0xfb240f83, 0x84869899, 0xff235782, 0x8200c0ee, 0x83eb202d, 0x613d2180, 0xc4202882, 0x00233282, 0x821e8528, 0x83112085, 0x8022260a, + 0x00ff0500, 0x06354621, 0x1a00ff2b, 0x00ff9a99, 0x8bae871b, 0x257d83ad, 0xffb85e23, 0x1c83e3ff, 0x17821c20, 0x99dcff23, 0x8353839a, 0x83168506, + 0x2a5e821b, 0x0848a1dc, 0xff8f7e8b, 0x82d9f3ff, 0x9e06213d, 0xf5203482, 0xed209084, 0xdb278b83, 0x7a0500c0, 0x830400ff, 0x84ed2041, 0x66e62568, + 0x19ebffff, 0x06834b84, 0x83ffff21, 0xfdff2916, 0xff7a9a19, 0x6666fbff, 0xed20c982, 0x00222282, 0x9b834024, 0x37820620, 0x1e0a002b, 0x00ff8fb8, + 0x8bf6280c, 0x2097af98, 0x26d48269, 0xffff0080, 0x825278e4, 0x210983e8, 0x6282e6fd, 0xfe830020, 0x83ddff21, 0xc4ff26fe, 0xffff9a59, 0x266782d7, + 0xff7febff, 0x83c2ffff, 0xe6ee2524, 0x84088b66, 0xfb2ddc82, 0xff90a4b0, 0xb85ef5ff, 0x1e1000ff, 0x209b82b8, 0x30d482f4, 0x7b141100, 0x28eeffff, + 0x1900fff5, 0xffffcdcc, 0x051d5dde, 0x00c0f222, 0xf5213182, 0x226e8240, 0x823333f5, 0xccf2220a, 0x20af82cd, 0x230682ff, 0xc00a00ff, 0xff201685, + 0x32054155, 0x00ff8b92, 0x86b85e04, 0xba0900ff, 0xefffffe1, 0x820848e1, 0x1f052ae1, 0xd1eeffff, 0x0f00ffec, 0x281482fa, 0xffcc4ce6, 0x67e62200, + 0x211a828b, 0x5b824012, 0x15433a83, 0x0a002105, 0x00226582, 0x91829e09, 0xd9010022, 0xfd25bf82, 0x00ffae47, 0x72308202, 0x02230536, 0x82883433, + 0x83f520ac, 0x229682cb, 0x82fbffff, 0xefff31b6, 0xfffff6a8, 0xffb89efc, 0xb8def2ff, 0xff778608, 0x2605bd64, 0xff1ec5f9, 0x82def7ff, 0x82fc2016, + 0x270a8216, 0xff8800e0, 0x47c1f9ff, 0xde275182, 0x00ff7a5c, 0x825c800b, 0xe1ed214c, 0x0c201082, 0xff267782, 0xffb85ee7, 0x47831000, 0x0982df20, + 0x83f3ff21, 0x82058386, 0x221e8366, 0x828fc2f9, 0xd8232161, 0xbd26e182, 0xf3ffff71, 0xc08246a1, 0x82a00421, 0x232982ff, 0xfe0d00ff, 0xf9226982, + 0xef8290c2, 0x828f4221, 0x00c02123, 0x08201e82, 0xf82fbf84, 0x0600ff54, 0xffff4821, 0xff3433fd, 0x821e1100, 0x80f42128, 0x0d201e83, 0xf622c883, + 0x148200e0, 0xf4286183, 0x00ffd643, 0x8b48a115, 0x07303982, 0xff8b0020, 0x48c10700, 0x3f0100ff, 0x0800ff7c, 0x22633582, 0x20002205, 0x201482a1, + 0x213a820c, 0xa7820700, 0xd71c0026, 0x0500ff0a, 0x00233f82, 0x43b81e15, 0x2e8205d9, 0x5482c020, 0x04830120, 0x70bd0523, 0x218e828d, 0x1a82ba5e, + 0xdc831020, 0x8261f221, 0x8214203e, 0xf3ff2104, 0x1820ad83, 0xff214d82, 0x35cc83f7, 0x3d0af6ff, 0xffdaffff, 0xe9ffff3e, 0xffffcdcc, 0xffcc4cca, + 0x0442e3ff, 0x90422511, 0xf2ffff8b, 0x82050c47, 0x00ff2206, 0x272d830a, 0xff703df5, 0x33330d00, 0x4221bc83, 0x20bc83c0, 0x2293831e, 0x82cc8c58, + 0x66662620, 0x8c2800ff, 0x208282ce, 0x6ef51806, 0xcc062108, 0xff225e82, 0xe5829a99, 0x849a1921, 0x290682f2, 0xc70600ff, 0x0000ffae, 0x09827a78, + 0x5182bd20, 0x1aa00022, 0x0a203582, 0xd725ae83, 0x00ff0681, 0x2094831e, 0x224f83a7, 0x5634b342, 0xea830af6, 0x70bd0a22, 0x56056845, 0x2d8209f6, + 0x820a0021, 0xf2ff21e6, 0x6f202d83, 0x25064c56, 0x70bd3500, 0x5782b081, 0x36831820, 0x00600822, 0x28052d61, 0x5c2f0c00, 0xa11000ff, 0x27c88248, + 0x8d0848a1, 0xa0fbffff, 0x26064641, 0xd843faff, 0x820200ff, 0xf7ff23d1, 0x39820040, 0x34820520, 0xe1eaff22, 0x072a2a82, 0xffffb83e, 0xfff628e3, + 0x39822000, 0x80f3ff22, 0x08201e83, 0xfc212983, 0x203d82e0, 0x22148307, 0x8284c0fe, 0x05a757e6, 0xb89e1522, 0x1125a582, 0x00ffc435, 0x20e1830b, + 0x2520820d, 0xba1e0900, 0x10829c08, 0x31828020, 0x3c4a0622, 0xde276a82, 0x0800ffb8, 0x82884821, 0x830c206b, 0x82fb20fd, 0x0d002151, 0x06251583, + 0x00fff43d, 0x22358304, 0x82c4600c, 0xb5042c1e, 0x0c00ffc0, 0xffffec5c, 0x8268e6f9, 0xcccc22ba, 0x828583ff, 0xcccc2523, 0x4ffeff08, 0x01245382, + 0x15e2ba0b, 0x0e575518, 0x85820020, 0x00e00823, 0x82068508, 0x9a19219e, 0x1d210482, 0x22768270, 0x828b66e6, 0x82082057, 0x24168506, 0xcce1f8ff, + 0x203e838b, 0x282d82c4, 0xc420f7ff, 0xe6f8ffff, 0x21048266, 0x15823cdf, 0x8b9a192b, 0xff94f708, 0x70fd1f00, 0x203c8215, 0x225883e0, 0x82002007, + 0x2035911e, 0x841683e0, 0x00202135, 0x55186382, 0x919e0dc9, 0x94f70e24, 0x4d1854f8, 0x8d2108ed, 0x82808266, 0x20978204, 0x05794e72, 0x50190682, + 0xff210910, 0x821b8300, 0x202284c5, 0x821b8700, 0x821082ec, 0x211e83c5, 0x0b82ffff, 0x20823286, 0x6b088b27, 0xe642feff, 0x3b628266, 0xffd7a3db, + 0x18240600, 0x28dfffff, 0x1000fff6, 0xffffca56, 0xff299ce5, 0x5c8f1700, 0x5f345382, 0x00ff0a97, 0x05c2754c, 0x8085ffff, 0xffcb0700, 0x00807a00, + 0x1783fb82, 0x87b3ff23, 0x271782ae, 0xff2a9ce5, 0x5278e8ff, 0x33254182, 0xf0ffff32, 0x24f88280, 0x849a99db, 0x252b8408, 0xff74fb07, 0x9d554200, + 0xf35e3005, 0x4500ff34, 0x00ff0a57, 0xff98d94e, 0x82a85a00, 0x4c0f3370, 0xffff08ce, 0x07cd4c52, 0x4c78ffff, 0x93ffffcd, 0x54826766, 0x5c8ff02b, + 0x991b00ff, 0xf7ffff98, 0x22a08223, 0x82cecc1f, 0xcc212ecf, 0x01ff08cc, 0xff34b367, 0xcccca2ff, 0x2c308315, 0x6c00ffcc, 0xff059a99, 0xc2b5ad00, + 0x83528207, 0xb0f0301b, 0x4500ffa4, 0xffffcc4c, 0x8b9a19b1, 0x5ca1ffff, 0xde21057f, 0x25378233, 0xff9a19f7, 0xa784e0ff, 0x09829920, 0x6666e42f, + 0xffef0e08, 0x6666e900, 0x5e6901ff, 0x27d982b8, 0xffce4c4b, 0x5c4f4b00, 0x06205382, 0x00282782, 0xffc64006, 0x34330a00, 0x0f837f82, 0xbff9ff24, + 0x2082083a, 0xff292582, 0x05a4b0b4, 0x00ff8591, 0x233d8203, 0x7cd4f7ff, 0xf7226b82, 0xce820080, 0x32b39322, 0x28208c82, 0xe7208c83, 0x0e229d84, + 0xc9820080, 0x0022de82, 0x9782cc08, 0x6766f022, 0xef222b82, 0x2b829819, 0x1a331b21, 0x2017b458, 0x82f482db, 0x99dd2120, 0xe220c483, 0xe3226383, + 0x3782cc4c, 0x34b3dc2d, 0x2b072b08, 0xe400ff06, 0x8207cccc, 0xe6102e97, 0x0900ff68, 0x00ff33b3, 0xff99990f, 0x236c8300, 0x33b30800, 0x2727a682, + 0x00ffcdcc, 0x82666618, 0x4c6c22cc, 0x202b83ce, 0x37898208, 0xcc4c0400, 0x2b0800ff, 0x08919184, 0xffff068b, 0xff52782f, 0x7c540cff, 0x672ffd82, + 0x00ff4821, 0x0532b338, 0x9911ffff, 0x4e3b079a, 0xff221760, 0x1e825b00, 0x2806796a, 0xae870900, 0x191000ff, 0x2180829a, 0x59820a57, 0x08008027, + 0x02ff078b, 0x244c8237, 0xcc4c4aff, 0x2e468215, 0x6666ee00, 0x6700ff07, 0xffff9819, 0x82ce4cc7, 0x660f2290, 0x05b34a68, 0x22058f71, 0x8266e6ef, + 0x82ee20db, 0xffff223a, 0x822b82a4, 0x82e5200c, 0xeaff21ab, 0x0e820488, 0x57828b20, 0xf82f0e25, 0x1834f814, 0x2131215e, 0x7418d4fb, 0x5e180a6a, + 0xf7292621, 0x94fb06d4, 0xff1554fb, 0x091451ff, 0xb3f1ff23, 0x829c8233, 0x76082010, 0x00200884, 0x0e9c7e18, 0x7b18ff20, 0xfd7515b6, 0xfa7e1808, + 0x85cd2007, 0xcb082458, 0x841514fb, 0xffcc2153, 0xc3574aa6, 0x05565106, 0x35833320, 0x4b86cc20, 0x8c51ab8e, 0x07542308, 0x7b1814f7, 0x1d8710be, + 0x89076b21, 0x2048827e, 0x825782f1, 0xc07b18c2, 0x183e7619, 0xf82f0e24, 0xcb83ab54, 0x13d99518, 0x20368241, 0x469518ff, 0xd4fb2615, 0xf754fb07, + 0x836c8294, 0x41ff20aa, 0x07410753, 0x522b2007, 0x1d820cca, 0x0e206318, 0x200f6841, 0xe5bd18eb, 0x0afa520c, 0x4b14fb22, 0x41170042, 0xf72116b3, + 0x0c125354, 0x0eea7e18, 0x5333b321, 0x8085050f, 0xcc4cee27, 0x54fb088b, 0x05024206, 0x6b20c994, 0xab20c9ae, 0x0e3ac997, 0x00ff30fb, 0xf79a19ff, + 0x00ff15d4, 0x8b486123, 0xb81b00ff, 0x1c00ff52, 0x0a82b89e, 0x08201082, 0xff240685, 0x4861e3ff, 0xff261684, 0x1e85ddff, 0x0685088b, 0xe2ffff24, + 0x1b84e27a, 0xffff8b25, 0x82b89edc, 0x2006832d, 0x058161ff, 0x22223284, 0x2d830080, 0xcc4ce233, 0x3356ffff, 0xff991534, 0x0040efff, 0xfdffffa4, + 0x3f5082a1, 0xff900211, 0xb8de0d00, 0x5800ff08, 0x05d39002, 0x00ff999c, 0xff008002, 0x00401900, 0x20f2ffff, 0x11240982, 0x7d084821, 0x21063a4a, + 0x1082c0e6, 0x89820220, 0xdeeeff23, 0x821f84b8, 0xa2c63788, 0xd1ffff8e, 0x6405840b, 0x402e00ff, 0xffff0500, 0xffb89ef0, 0x26831200, 0x4682e820, + 0x21054d44, 0x30821ee7, 0x0080fd22, 0xe7203082, 0x0a823b83, 0xeaffff24, 0x458248e1, 0xff212382, 0x211383f4, 0x1e8340eb, 0xb89ece23, 0x2644822f, + 0xff9b99e8, 0x825ed4ff, 0x820e2049, 0xcbff2675, 0x00ff3433, 0x222f832a, 0x8232b3e4, 0xbd2c27ae, 0xddffff71, 0x29829a19, 0x0080a42c, 0xe9ffff06, + 0xff8b48e1, 0x6683eeff, 0x09a08618, 0xe9221182, 0xbd8266e6, 0x16823883, 0x1600ff2d, 0x088bb81e, 0xff0664f7, 0x82212200, 0x13002330, 0x578248a1, + 0xe6226183, 0xf782707d, 0x9221a184, 0x21338226, 0x5c82d96d, 0xe622003e, 0x4000ff67, 0xff0566e6, 0x99191800, 0x33e3ffff, 0xef0e0534, 0x01ffa4f7, + 0x159a1900, 0x0b924d18, 0xa6f1ff23, 0x296f8266, 0x084861ee, 0xf8afffff, 0x0c820752, 0x5e18f720, 0x0b49128b, 0x00ff2216, 0x05ad4f4c, 0xf3831120, + 0x91820420, 0x21110029, 0x00ff9448, 0x82b8de0e, 0x834d20ef, 0x9e812310, 0x118205b8, 0xe4830f20, 0x5a82fb20, 0xa313002c, 0xf0ffffd8, 0x00ff00e0, + 0x25821e09, 0x99f0ff28, 0x0800ff9a, 0x978248c1, 0xff33b332, 0x66a5fbff, 0x4cf6ffff, 0xf2ffffcd, 0x8a08b87f, 0x21068a63, 0xa7836600, 0x63e6ff21, + 0xac82059a, 0x34b38a2c, 0x2150ffff, 0xffff0548, 0x158266f5, 0x9a19f023, 0x05b479ff, 0x9999ed24, 0x2182788b, 0x8fc2af2d, 0xa5ffff07, 0xffffb8de, + 0x8266e6e2, 0xe1f22227, 0x21228247, 0xcc8272bd, 0xff004027, 0xccccf3ff, 0x2164828b, 0x2b823433, 0x9002a022, 0xf520fa83, 0x0022a482, 0x1c828008, + 0xaec7eb28, 0x801700ff, 0xc6828b00, 0x00c00227, 0x0200ff8b, 0x20b182a0, 0x86388200, 0x00c02109, 0xb3201a82, 0x0021a782, 0x2ce1822e, 0xcc3100ff, + 0x0d00ffcd, 0x00ffb85e, 0x22a58222, 0x79332e00, 0x0820068f, 0x2106f456, 0x165b9999, 0x0e002305, 0x2e5e6766, 0xff082b05, 0x98195a01, 0x4c5effff, + 0xa88215cc, 0xa968e62b, 0x5000ff05, 0x8b073433, 0x21ca859e, 0x4e821200, 0x61f5ff28, 0x0f00ff48, 0xf48648e1, 0x84af0021, 0xe0ff21cc, 0xff248e86, + 0xfffa7fff, 0xaa200082, 0xe0230382, 0x8200ff06, 0x212982a2, 0x1e8260f6, 0xc9830d20, 0x82beed21, 0x59042292, 0x837d829a, 0x61f7220e, 0x251e8206, + 0xff48e1f0, 0x4282f6ff, 0x82fbff21, 0xecff27f2, 0xff94725d, 0xd284f0ff, 0x82c04d21, 0x807e22fe, 0x208b8200, 0x289d8309, 0xff4408f1, 0x34b30400, + 0x0858477a, 0x9082b322, 0x22302742, 0x18d6e350, 0x830e2d8f, 0x55ee2091, 0x06830561, 0x9e219e82, 0x820484b8, 0x47ef2267, 0x20a482ae, 0x054e5380, + 0x8221cc21, 0x832220ff, 0x82d120b0, 0x3100229a, 0x262683de, 0xff0852b8, 0x8240b300, 0xbace22aa, 0x2caa82e2, 0xff989902, 0x6666ffff, 0xcc0200ff, + 0x210982d0, 0x09829a99, 0x26058652, 0x8b008017, 0x820800ff, 0x150022fc, 0x220a8340, 0x829ad909, 0xfd5f223c, 0x2a918370, 0xff2a9c0e, 0xcc4cf7ff, + 0x820c00ff, 0xf2ff2204, 0x2c0982cc, 0x08666604, 0xf4f72f0e, 0xfb1554f8, 0x0cbc48c4, 0x82eaff23, 0x259f8290, 0x08707de5, 0x3e82b4fb, 0xd7f1ff2b, + 0x0600ff0a, 0xfffffa3e, 0x217c83f3, 0x2e82c109, 0x8238f721, 0xaeff339c, 0xff07d6a3, 0x649bf6ff, 0x66faffff, 0xf9ffff68, 0x0e829c64, 0x82343321, + 0x33f5233e, 0x06820832, 0x3183ed20, 0x095f8618, 0x1fc5102c, 0xd4f7088b, 0x3500ff06, 0xb1821e05, 0xad5c2a20, 0x52801805, 0x07d42508, 0xe60000ff, + 0x1e82e182, 0x80186020, 0xff220756, 0xb182e4ff, 0x9955ff29, 0x00ff159a, 0x828a0103, 0xfe9130fa, 0x490100ff, 0xfcfffffc, 0xffff9446, 0x8280b5fd, + 0x60da2704, 0xebffff08, 0x04826265, 0x050ecd2c, 0xde0400ff, 0xe3ffff76, 0x0a820080, 0x006e0022, 0x90212082, 0x210482e5, 0x04838cfe, 0x0482b920, + 0x8bdad922, 0xff223082, 0xa6827e6d, 0x646dff22, 0x24217882, 0x215a82fe, 0x09820e6d, 0x82034921, 0x60e6321a, 0x0d00ff00, 0xff056182, 0xb85ee6ff, + 0x8af2ffff, 0x820a823d, 0x21258230, 0x0482fdb6, 0x82636d21, 0x02db2104, 0x6d210482, 0x224b830f, 0x82a0dafd, 0xfefd274b, 0x0200ff77, 0x46828901, + 0x82d26d21, 0xd96e2209, 0x828c8308, 0x831c2014, 0xebff288c, 0x00ff4861, 0x82a43014, 0xb5fd224b, 0x20208281, 0x83e98225, 0x030023cc, 0xe0829ab9, + 0x820c0221, 0x146e2139, 0x1c223482, 0x3982d7a3, 0x82ea2621, 0xe30c27c1, 0x1900ffd8, 0x0a8284eb, 0x44960022, 0x6321fc82, 0x21048242, 0x2a826866, + 0x8232b321, 0xcc4c2109, 0x00218082, 0x82068201, 0xc86b210c, 0x48219282, 0x261b8280, 0xfffff292, 0x829e91fe, 0x2340834b, 0x7a14e6ff, 0x1c274082, + 0xffff6e9d, 0x8236defb, 0x33933780, 0x6200ff34, 0xff156666, 0xf6a81700, 0x1600ff8b, 0xffff32f3, 0x30820cf9, 0x00c01322, 0xdc21f282, 0x270a82ee, + 0xff103803, 0xe8dbfdff, 0x09835a82, 0x28dcfb2d, 0x77feffff, 0xfcffffd0, 0x8208e06f, 0xf873210a, 0x04840a82, 0x28831820, 0x1e82fc20, 0xf047fc22, + 0xf7217e82, 0x221e82ce, 0x82bcb4f8, 0x60ba2138, 0xaf845782, 0x82cccc21, 0x83cc2009, 0xcfff28af, 0xff8b0080, 0x8280d8ff, 0x82048269, 0x2010820a, + 0x22068508, 0x862700ff, 0x00ff2216, 0x05a34430, 0xe83b0622, 0x0622a182, 0x59827493, 0xfffed326, 0xae470700, 0xb3215882, 0x21a183f2, 0x148210b8, + 0xfffcf726, 0xf0e70300, 0xfb20ab82, 0x01220982, 0x9684088c, 0x01211e82, 0x22148287, 0x822070fc, 0x82c820ab, 0x82fb20a1, 0xfcff21ca, 0xfd220983, + 0x2482e8db, 0x783eec22, 0xe82dea82, 0xe9ffff30, 0xff849919, 0xcd4ce8ff, 0x2216828b, 0x82cdccbd, 0x33ca258b, 0x3500ff33, 0xff22af82, 0x2b694200, + 0x83068205, 0x84cd2011, 0x34158316, 0xf7088b33, 0x150cfc1c, 0xcb06b4fb, 0x06b4f707, 0xab1100ff, 0x25aa8286, 0xff7a540e, 0x9818f1ff, 0x0349082d, + 0x0fe25b06, 0x01ff0e2e, 0xffcc4cf4, 0xcc4c0400, 0x88ffff15, 0x773c0a83, 0xff0534b3, 0x52381b00, 0x682800ff, 0x0d00fff6, 0x00ff146e, 0xff707d32, + 0x5ccff8ff, 0xce207683, 0xf33b9e82, 0x00ff1ec5, 0xffcc8c5b, 0x34f3b4ff, 0x734a00ff, 0xa4ffff34, 0x00ff4861, 0x8298990b, 0xcc77211e, 0x1127a082, + 0xffff723d, 0x8200808d, 0xe27a2104, 0x4c279682, 0x77ffffcd, 0x830847e1, 0x829a2024, 0x295c212e, 0x78213882, 0x21428252, 0x4c82a4f0, 0xffaf8726, + 0xccccf3ff, 0x35201e82, 0x6c826782, 0x76851a20, 0x6d0d0023, 0x218a820e, 0x94826866, 0x829a3921, 0x83a0821e, 0x82ce20aa, 0x9e0f25a5, 0xf0ffffb8, + 0x19227783, 0xf4827c54, 0x00230f83, 0x829e9e0f, 0x910f2725, 0x0f00ffec, 0x1582568a, 0x3b821920, 0x66f0ff23, 0x840f8264, 0x821d209d, 0xbd00230f, + 0xf18267e6, 0x9819fc30, 0x66e9ffff, 0xeeffff67, 0xffffcecc, 0x988219f1, 0x6666e727, 0x33fbffff, 0x22c78232, 0x189a19f8, 0x22223659, 0x82968b94, + 0xcc082970, 0xffff07cc, 0x8d3333f6, 0xff230584, 0x824c0300, 0x33f72251, 0x20098234, 0x82b78219, 0xff332b52, 0x32b30100, 0xf5ffff05, 0x15829999, + 0x4634b321, 0x0b220686, 0x0e850080, 0x07b35c18, 0x0a201e83, 0x00218682, 0x219a820b, 0x04830500, 0x23820a20, 0x66fcff23, 0x2c698266, 0xffdf0f05, + 0x2130feff, 0x0800ff05, 0x310a828f, 0xfff0e7fc, 0x21b00900, 0x88fcffff, 0x0700ff31, 0x1e82f6a8, 0x82cfd721, 0x3a102529, 0xfdffffe1, 0x00283982, + 0xff713d11, 0x04880200, 0x86828183, 0xdbc70922, 0x01221e82, 0x2e821038, 0xff101826, 0xed2fffff, 0x86268182, 0xdfffffa8, 0x4c8236cb, 0x82523821, + 0xc2f922fd, 0x212e820c, 0xb0826dc7, 0x9a99ed2b, 0x4c0600ff, 0xd4ffffcc, 0x223e82b3, 0x82cdcc0b, 0x22048338, 0x8299192d, 0xe6032548, 0x1600ff66, + 0x11212383, 0x2519824c, 0xffcecc0e, 0x76831800, 0xcccc0424, 0x59189308, 0xe627252a, 0xffff8b66, 0x829a19f4, 0x4ef72378, 0x6e820714, 0x82834021, + 0x1cba21c7, 0xce210982, 0x210982d9, 0xef82f833, 0xdb826820, 0xf813fd22, 0x0a227382, 0xf082866b, 0xff006026, 0xae870500, 0x12b35c18, 0xff686626, + 0x968ef5ff, 0x99201982, 0x8205046d, 0x2192830e, 0x62849903, 0x0221b183, 0x20d082cc, 0x28b683f9, 0x86cecc01, 0xb30000ff, 0x317d8232, 0xffd7e3ef, + 0x10980200, 0xbaeeffff, 0xfdffffe1, 0x7c82ee5f, 0x2008d682, 0x2438f6ff, 0xffff8a08, 0xff2230fa, 0xf047ffff, 0xcffbffff, 0x1b00ffde, 0xffff436b, + 0x0852f8f7, 0x2f268291, 0xff05f047, 0xe17a1900, 0xc2f8ffff, 0x2a00ffd0, 0xff235b82, 0x82cdccf3, 0x34332d0e, 0x66d2ffff, 0xf70e0866, 0x15a4f780, + 0xf027ea82, 0xffff3c8a, 0x83c375f3, 0xffc42604, 0x3d8af0ff, 0x837c828b, 0x27168506, 0x00800c00, 0x0f00ff8b, 0x82059260, 0x83ff2006, 0x82048611, + 0x832d820e, 0x8222821c, 0x83328228, 0xf0ff212d, 0xff2a2d82, 0xcc4c0801, 0xb3bbfeff, 0x1c431534, 0xf0ff2805, 0xffff4861, 0x8384abe6, 0x230a8275, + 0xb89e0f00, 0xed436a82, 0xd7ff3c09, 0xffff0a97, 0xffaec7e4, 0x9082cdff, 0x91f2ffff, 0xcaffffec, 0x00ff3333, 0x82a43007, 0x73a42129, 0x0c340a82, + 0xffffe23a, 0xffcd8cb5, 0xcc0c4b00, 0x66f4ffff, 0x5b00ff66, 0xee254884, 0x00ff8fc2, 0x28e08288, 0xae877200, 0x807200ff, 0x270e8200, 0xffff281c, + 0x0832b3ee, 0xa3212482, 0x222e86d7, 0x825c0f4b, 0x20238342, 0x232d820c, 0x5278a4ff, 0x62821e82, 0xff236c85, 0x82f292f2, 0x01802180, 0xc6268a82, + 0xd7ffffa8, 0x1e829899, 0x32b37724, 0xaa82ffff, 0x00ff0525, 0x824ca10f, 0xc47521d0, 0xe622c682, 0x0a829899, 0x83646621, 0x82682004, 0xcc3131a1, + 0x3e01ffce, 0x8b159819, 0xb32f00ff, 0xd9ffff34, 0x26208483, 0xff240482, 0x8b0080cf, 0xd1222182, 0x3782cc4c, 0x1b831683, 0xd0230a82, 0x8208cc4c, + 0xa6d93606, 0x3800ff68, 0xffff3e4a, 0xff98d9b9, 0x7b941500, 0x80e6ffff, 0x25798200, 0xffae0702, 0x4c82fdff, 0xe6020026, 0xfeffff66, 0x00234c82, + 0x82676602, 0x0300234c, 0x6882fe34, 0x910d032c, 0x750100ff, 0x0200ff82, 0x0482020b, 0x82fc5421, 0x65162735, 0x1900ffa2, 0x54824e82, 0xffcd4c26, + 0x34334600, 0x26202982, 0x0e316b82, 0x3f01ffaf, 0x34f89a19, 0xff968b15, 0x00200300, 0x055e58ff, 0x82e00421, 0x21092209, 0x27a38248, 0xffcc4cfe, + 0x76bf0000, 0x2506b343, 0xff42df00, 0x4082fcff, 0x6505ab49, 0xf02008ae, 0xff219382, 0x8ada18f1, 0x28328208, 0x056b1301, 0xff9f00ff, 0x272382ff, + 0xabeefeff, 0xb7ffff05, 0xfe2aae82, 0x1566e6e9, 0x5c4900ff, 0x1e82c22a, 0xaa000022, 0x19242382, 0x34fb059a, 0xed252684, 0xe650ffff, 0x272a8266, + 0xff295ca9, 0xd663bfff, 0xd8250a82, 0xffffb89e, 0x323a82e2, 0x1f85f1ff, 0x19c9ffff, 0x1800ff9a, 0xffffb99e, 0x596666d5, 0xff2e051f, 0x4861e0ff, + 0xd92000ff, 0xefffff9a, 0x09829042, 0x8bb9de24, 0xe4829f08, 0x8f421426, 0x390600ff, 0x11213182, 0x22d28240, 0x82b8fe0c, 0xde152731, 0x1000ffb8, + 0x5b824861, 0xed2be227, 0x783600ff, 0x830f8252, 0x664625e7, 0x3400ff66, 0x0023ca82, 0x82008028, 0x80682729, 0xff15b200, 0x3082a9ff, 0xa1218c87, + 0x218c8748, 0x8c878f82, 0x8c851383, 0xf5281327, 0x68dfffff, 0x218282f8, 0x8c82ce4c, 0x20225483, 0x8c8666e6, 0x06208283, 0x8c820483, 0x5e829820, + 0x32337325, 0x835600ff, 0x20002388, 0xd5823433, 0x9eec1127, 0x192600ff, 0x22b98298, 0x829a1929, 0x19cf2921, 0x54fb079a, 0xffffff06, 0x1a41f582, + 0xa0002b05, 0x01ff66e6, 0x159a190f, 0x5b1814fb, 0x7e410c6a, 0x2830820b, 0xff056bec, 0x1400c000, 0x05715106, 0x67b89e21, 0x002205a6, 0xc182610e, + 0x6866ee2e, 0xaf0e088b, 0x01ffd4f8, 0x1570fd9f, 0x11226f82, 0x2082a4b0, 0xff84ab35, 0xf6680d00, 0x54eeffff, 0xfb088b7c, 0x0000ff74, 0x82054201, + 0x5c4f2d18, 0xf3ffff8b, 0xff81c235, 0x166efcff, 0xc02c1082, 0xffff0800, 0xff32f3a4, 0xe8da94fe, 0xb6272182, 0x00ff33b3, 0x82999992, 0x99fa220a, + 0x06f05899, 0xaa82f420, 0x82060021, 0xf3ff2704, 0x088b66e6, 0x1d828b4b, 0x7b54ee22, 0xf1224a82, 0x448285ab, 0x82a4b021, 0x35ef230a, 0x068508c2, + 0x0e00ff29, 0xffff7b54, 0x183ecaf0, 0x2d087991, 0x0652382c, 0x336700ff, 0x31ffff33, 0xd18232b3, 0x1078053c, 0x17f5ffff, 0x0b00ff0a, 0xffff8a21, + 0xffe23af9, 0x8f020c00, 0x00ff088b, 0x47822c01, 0x26010023, 0x21b582a8, 0x0f84be0e, 0x20200982, 0x0023a882, 0x825c4f0d, 0x10782d0f, 0x0900ff96, + 0x00ff4c97, 0x98004003, 0x69203182, 0x01239a82, 0x82cccca7, 0x03c72257, 0x266882d8, 0xff34b311, 0x8207ffff, 0x4c0e2209, 0x838e82cc, 0x110023f6, + 0xeb82a4b0, 0x9899f629, 0x9c36ffff, 0x58ff152a, 0x0c270539, 0xffff0080, 0x8200c0eb, 0x83f320ba, 0x8204820a, 0xa6d62725, 0xd6ffff68, 0xe8829a99, + 0xb89ed627, 0x5e2900ff, 0x820a82b8, 0x0524451b, 0x3b873091, 0x8407ad5d, 0x234b8456, 0x48612900, 0x9e204b82, 0x4b834083, 0x0482ff20, 0x81834b86, + 0x062f3092, 0xffffe23a, 0xff3ecaf9, 0x32330800, 0x82fcffff, 0x210982dd, 0xe9828b34, 0x34330823, 0x2116828b, 0xfb82142e, 0xff002026, 0x703d0600, + 0x40210482, 0x831a8200, 0x29002466, 0x82053453, 0x237188ad, 0x50380600, 0xc7224b82, 0x4183ffae, 0xbd834ba8, 0x22062446, 0x41004014, 0x08200929, + 0x6084c884, 0x5c216683, 0x210a8228, 0x0a821e65, 0x3321308b, 0x24308a34, 0x5401ff0e, 0x28418280, 0x159a99ed, 0x80feffff, 0x75ef8200, 0x1583055a, + 0x00a0fd22, 0xff23d582, 0x8233b38b, 0x82a12016, 0x5e002311, 0xe08248a1, 0x1e457423, 0x22068508, 0x865e00ff, 0x00ff2416, 0x82cd4c74, 0x0200222d, + 0x22448260, 0x82600500, 0x83ff2055, 0x8201201b, 0x08465c54, 0x00200625, 0x8200ff90, 0x82922012, 0x82012012, 0x07002523, 0xff870040, 0xff290583, + 0x0020f9ff, 0x9e0200ff, 0x27c682b8, 0x96b8dee2, 0xc0e1ffff, 0x20070d75, 0x827782e1, 0xe6722216, 0x24898266, 0xff9a198d, 0x820482ff, 0x8210820a, + 0x82ff2089, 0x00ff2406, 0x8467e672, 0x00ff2116, 0x5f821b83, 0x00401e24, 0x4f63a98b, 0x1d002805, 0x00ff4821, 0x8248e10a, 0xe0052616, 0x00ff8d00, + 0x207c8304, 0x24e08205, 0xa00600ff, 0x225b8200, 0x8252f8ff, 0x34f32187, 0xb3228782, 0x8d6b9232, 0xf7083d05, 0xfc00ff37, 0xff150080, 0xb89eb3ff, + 0x1e0b00ff, 0xffff05b8, 0xffaec7dd, 0xae474500, 0xfe260a82, 0x00ff3433, 0x8f829903, 0x6666fc22, 0x8206897b, 0x828b202f, 0x4806834f, 0xff2105a6, + 0x85d882fe, 0x60fc2104, 0xdd276a83, 0xffffb8de, 0x8200c0ba, 0x23568340, 0x48e1f4ff, 0xf7250a82, 0xffff00e0, 0x210483fe, 0x1f82befc, 0x0982f520, + 0xe1050027, 0xfaffff48, 0x22348240, 0x82403700, 0x82ca201e, 0x3f7e2180, 0x27842c82, 0x0080f922, 0x3920c882, 0xfa217d82, 0x220982c0, 0x8266a606, + 0x7e002078, 0xa02006be, 0x00201182, 0x0f82e483, 0x0000ff23, 0x254383e0, 0xff486144, 0x6d832300, 0x83440021, 0x82dc204e, 0x82b5824e, 0xffff212a, + 0x3a83a382, 0xffffff22, 0x00230e82, 0x8300a001, 0xc005274b, 0x00ff8b00, 0x36822105, 0x30830520, 0xb982fe20, 0x80060028, 0xd77e0800, 0x9284ff05, + 0x84350021, 0xe705224e, 0x212782b0, 0xf1821ec5, 0x9632b327, 0xe6f7ffff, 0x31748266, 0x0e083433, 0xb3ea01ff, 0x6600ff34, 0xff159a99, 0x1683c8ff, + 0x66665922, 0x19253c83, 0x5900ff9a, 0x21f98261, 0x55830e00, 0x5f831820, 0x9082ed2b, 0x5c1e00ff, 0xe2ffff28, 0x22808380, 0x836691ff, 0x82012047, + 0xc6ff2125, 0x5d228583, 0xfd829a19, 0x0a97f831, 0xe60c00ff, 0xf3ffffea, 0x00ff3233, 0x82c40006, 0x9a192109, 0xff21b182, 0x820682f3, 0x3333370c, + 0xfff9ffff, 0xf8ffff3c, 0xffff9999, 0x08c400f4, 0x19c6ffff, 0x3c822d9a, 0xd7639123, 0x2a5f8206, 0xff8b4861, 0x48a1edff, 0x82e1ffff, 0x26838204, + 0xe7ffffb9, 0x820800c0, 0x239982d6, 0xb89ea6ff, 0xaf832b82, 0xf1220a86, 0x20824721, 0xffaec722, 0x25053b52, 0xff0080e2, 0xb4641d00, 0x996e2605, + 0x00ff0699, 0x22c58239, 0x83e6a2ff, 0x700722db, 0x829084a5, 0xcdcc21a4, 0x50828882, 0x6620ae82, 0x00229f82, 0x7782e10c, 0xdc0c0023, 0x2ab68328, + 0x0700ff84, 0x00ff4861, 0x827cff0b, 0xd4392477, 0x8400ff7c, 0x6e0023e0, 0x518234b3, 0xcc8c1d26, 0xcc0100ff, 0x12220482, 0xc6556666, 0x83f12006, + 0x3318384b, 0xffff0834, 0xffcc4c15, 0x48a10f01, 0x1700ff15, 0xffff0a97, 0x821ec5d9, 0xe8d022b2, 0x213a82f6, 0x9e828017, 0xe23a2622, 0x59271082, + 0xfeffe27a, 0x8284abf2, 0x97143126, 0x2100ff0b, 0xff059a59, 0x33731400, 0xa6deffff, 0xff24ad82, 0x06c2f5d6, 0x852c1082, 0x8d00ff1f, 0xff15cdcc, + 0xe17aebff, 0x4c212682, 0x232682cd, 0x063e0a29, 0xff2b1085, 0x0533b3de, 0xffff26f7, 0x82991913, 0x68e82723, 0x2600fff6, 0x23820040, 0x7a142f22, + 0xe8222382, 0x82829082, 0x1083c020, 0x82e63921, 0x195f22ad, 0x2226829a, 0x829a198c, 0xccc9261b, 0x5700ffcd, 0x22778319, 0x87523836, 0x0074220a, + 0x26778201, 0xffac4736, 0x83e6a8ff, 0x99c92288, 0x250a869a, 0x66664300, 0x9482158b, 0x8286ab21, 0x3e4a2189, 0x14226582, 0xb0821e85, 0x82c2b521, + 0xcfd622d1, 0x2238825c, 0x88cecc13, 0x707d21b0, 0x3d202683, 0x7821b089, 0x2d2c8352, 0xef0e05c3, 0xcc3501ff, 0xbc01ffcc, 0x4f82c04a, 0x68e6052f, + 0xf10400ff, 0x0800ffaa, 0xff8b9899, 0x2b0f8300, 0x560efbff, 0xff0df708, 0x40359bff, 0x12254082, 0xffffcc4c, 0x293282f0, 0x00800a00, 0x80e9ffff, + 0x05828b00, 0x089a192a, 0x19a5feff, 0x062b079a, 0x20057554, 0x20268323, 0x200482e3, 0xc1741a00, 0x14fb2120, 0xff253582, 0x66e65a01, 0x23728207, + 0xff66e616, 0x00215a84, 0x335f8216, 0xcd4c1200, 0x330f00ff, 0x00ff0834, 0xffffff78, 0xc0ca6400, 0x102b8482, 0xffffce4c, 0x15746887, 0x83fdffff, + 0x6605278a, 0xf8ffff66, 0x8a823433, 0x3f82fc20, 0x99faff22, 0xff338f82, 0xff3433f0, 0x66e6e3ff, 0xdfffff05, 0x00ff32b3, 0x82cc4c00, 0xccf9220a, + 0x242683ce, 0xffff9919, 0x214682f9, 0x09830300, 0x9899fa22, 0x10206182, 0xe5224683, 0x25829a19, 0x9a99ef22, 0x4c213b82, 0x230a82cd, 0xff67e6fc, + 0xff225183, 0x09830300, 0x9183f920, 0x32330623, 0x2030828b, 0x84408320, 0x0f002156, 0x6c858782, 0x3b825182, 0xff248282, 0xcccc0700, 0x0220d282, + 0x00208782, 0x3082a282, 0x87831020, 0x61831c20, 0x3b830020, 0xb3ffff23, 0x05a95d34, 0x03282682, 0x00ff68e6, 0xff33b306, 0x84053347, 0x83ff2030, + 0x1c002387, 0x258233b3, 0x00219d83, 0x84ce831a, 0x06ed6d61, 0x83981921, 0x82322034, 0x056f5dcc, 0x5685e983, 0x83efff21, 0x2b6c859d, 0xff66e6b9, + 0xcccc87ff, 0x1c00ff15, 0x1f243183, 0x8e053333, 0x6625d082, 0x0400ff67, 0x20778266, 0x23208201, 0x00800400, 0x0683d583, 0xff241685, 0x8e9a19fe, + 0x99218f82, 0x20bb8299, 0x22e1833f, 0x829919b9, 0xe607278a, 0xf8ffff64, 0x25869a19, 0x34b3f322, 0x2208a24e, 0x18cc4c7c, 0x2e17e47a, 0x01ff064b, + 0x0700800b, 0x158b14fc, 0x82f4feff, 0x20118209, 0x3e9118ff, 0x0cd35c07, 0x8300ff24, 0x478234b3, 0x840b0021, 0x96632b97, 0x4c0c00ff, 0x0700ffcc, + 0x048256ee, 0x0866e62c, 0xca3f00ff, 0x4600ff3e, 0x8e8267e6, 0xae070322, 0x5121cb87, 0x056646ec, 0x8a040023, 0x82cb843e, 0x82a58206, 0x82cb8316, + 0x212a8225, 0xcf84fcff, 0x291c1c36, 0xcce0ffff, 0xef0e05cd, 0x00ffd4f7, 0x15008051, 0xc01100ff, 0x2605b744, 0xdcffff05, 0x82ff0080, 0x82b82000, + 0x23158360, 0x9061e2ff, 0x3e230a82, 0x82c20080, 0x83242027, 0x00002227, 0x27278248, 0xffb89eed, 0x00c01e00, 0xa1250a83, 0xe1ffff48, 0x2132823f, + 0x3d82b1fe, 0x80370122, 0xff205382, 0x0a405c18, 0x21099c4c, 0x557654fc, 0x82152008, 0x05da752a, 0x80411a20, 0x21068305, 0x168300ff, 0x660e0024, + 0x95828b66, 0x089a9923, 0x213083f8, 0x6c821100, 0x82eaff21, 0x05424b30, 0x08275a83, 0x337301ff, 0x85ffff34, 0x33db236c, 0xa6828b32, 0x22821220, + 0x35e1ff23, 0x210a83c2, 0x9f82ce4c, 0x823eca21, 0x9939249f, 0x8303fb99, 0xb9de26bd, 0x000000ff, 0x2012824e, 0x222882ed, 0x82de1e00, 0xedff23b2, + 0xbd8247a1, 0x82fa2021, 0x4c422333, 0x27828bcd, 0xcccc4122, 0x21244c83, 0x00ff0040, 0x2e825e82, 0xf783de20, 0xbe220a85, 0x1c823433, 0xccdeff27, + 0xc8ffffcc, 0x21fe8280, 0x86832100, 0x01240a84, 0xff66e630, 0x6121fec3, 0x21fe8348, 0xfe9ab89e, 0xfc64fc3e, 0x14f81574, 0x0754f806, 0xfc0614fc, + 0x00ff0754, 0xffcdcc42, 0x9a192601, 0x0300ff15, 0x0621b083, 0x26c082a0, 0xffb81e07, 0x63200400, 0x8b2b05ea, 0x3b00ff08, 0x00ff6766, 0x82cc0c00, + 0x831d20ef, 0xab30221b, 0x2c0a8286, 0xffaec703, 0x7a540700, 0x00ff8e92, 0x058f4106, 0x82600721, 0x83002034, 0xe0063139, 0xfbffff00, 0x00ff82f5, + 0xff9ad902, 0xfabef9ff, 0x1d214782, 0x22148240, 0x824621cf, 0x803b213c, 0x00212983, 0x200a827e, 0x053c4907, 0x82b8fe21, 0x42e02130, 0xc2218882, + 0x21308290, 0x3082be5f, 0x0a860320, 0xffffff27, 0xffffb2dd, 0x231e82f7, 0xec1ffcff, 0x80251e82, 0xffff0800, 0x23b282e2, 0x4821cfff, 0x1d294482, + 0xffff4861, 0x0566e6cf, 0x821c848f, 0x420021ae, 0xe1203082, 0xfc221582, 0x1384e63f, 0xfc203082, 0xf9208083, 0xff21a482, 0x201983f8, 0x22a483fb, + 0x82b85ef8, 0xc4ff21e3, 0x2105c442, 0x56820584, 0xcf221b83, 0x0a827c54, 0x1a833085, 0x8321f921, 0x862b244a, 0x84f8ffff, 0xb8de2129, 0xf8204f82, + 0x6f4aba83, 0xdf032205, 0x05946ebe, 0x60060023, 0x239b8642, 0xb8de3000, 0x5a8a4482, 0x0060f823, 0x258c828b, 0x00ff4801, 0x30881f04, 0x3083a020, + 0x002c6a83, 0xff42a006, 0xdbf20100, 0x370700ff, 0x03250982, 0x00ffcdcc, 0x21eb8306, 0xba821d00, 0xe2274f86, 0x00ff66a6, 0x82ae0731, 0x19fc225a, + 0x2320849a, 0xe6ffffff, 0x08201482, 0x348a0e83, 0x824c7c21, 0x6628263f, 0xffff1566, 0x2b1a82ef, 0x6666e2ff, 0x2300ff05, 0x00ffb85e, 0x26069243, + 0x00ffae87, 0x8252991d, 0x66c2234a, 0x27825466, 0xcd4cdb23, 0x2123828b, 0xee826112, 0x852be122, 0x51380a83, 0x1e00ffeb, 0x0e057bd4, 0x1504f88b, + 0x00ff07db, 0xffb95e47, 0xc235e8ff, 0x102b1c82, 0xffff5c4f, 0xff5c8ffa, 0x821e1100, 0x3afd2514, 0x1000ffe2, 0x08264282, 0xe60c01ff, 0x16820666, + 0x8b343322, 0x19260582, 0x0200ff98, 0x1c831ec5, 0x00ffce26, 0x08a47005, 0x66204682, 0x1728b282, 0x3b053eca, 0xffff8b07, 0x28130562, 0x074b067b, + 0x07cb064b, 0x19078e2b, 0x2218f40b, 0x1864fbab, 0x5f0c2ea0, 0x00241192, 0xff7b540e, 0xcd201682, 0x2006b44e, 0x0dc35ff8, 0x560af561, 0x6b2316f0, + 0x8354fb06, 0x4cee21af, 0x57064061, 0x57180511, 0xcc200854, 0xf1223782, 0x638334b3, 0x00290a82, 0x0834b311, 0xfb0754f7, 0x60368d94, 0xff27061b, + 0x8bcd4cee, 0x18ffff08, 0x8214a8de, 0x066b3336, 0x01ffef0e, 0xff9a1918, 0x52f8a901, 0x1900ff15, 0xb88232b3, 0x05765e2c, 0x4c0100ff, 0x0000ffce, + 0x09832ef2, 0x0982cc20, 0x8298ce21, 0x00802109, 0xa9260982, 0x00ff0878, 0x83823303, 0xde830122, 0x14840982, 0x5fdabb21, 0xff230584, 0x8242ffff, + 0x8204201e, 0x000023be, 0x1e85be00, 0x44ffff23, 0x23328526, 0x227cfeff, 0x01201e82, 0xff233382, 0x854656ff, 0xffff235c, 0x70856831, 0x0effff23, + 0x211e8214, 0xfc82cc18, 0x8aa1ee22, 0x21208682, 0xff269c82, 0xffe23ae8, 0x9b822600, 0x47eeff30, 0xffffb3ae, 0x089a19f5, 0xf9ffffa2, 0x2182c2b5, + 0xcecc0122, 0x8a217482, 0x8341823e, 0x57ff2136, 0x8205906e, 0x68262113, 0xff22a886, 0xbd8359fe, 0xff66e627, 0x86abfdff, 0x2105828e, 0x1a83e23a, + 0xfb215183, 0x22dd820c, 0x8268e601, 0x14ae214e, 0x19213482, 0x07ce4398, 0x9a99ff25, 0x83feffff, 0x82ff207f, 0xfcff21ec, 0xfe20b383, 0xfd233283, + 0x82089a99, 0x82662019, 0x83fc2033, 0x99fd2172, 0x28843382, 0xce4cfd23, 0x201a8288, 0x202583fb, 0x209783fc, 0x2b0483f9, 0xff3233fe, 0x6666fbff, + 0x190000ff, 0xf8333983, 0xff060080, 0x66e6c7ff, 0x0b00ff07, 0xffff34b3, 0x82cdccf6, 0x831520c8, 0x4cef257a, 0x1700ffcd, 0xf3205583, 0x00227982, + 0x88189919, 0x1c2208d0, 0x298264e6, 0x82cc4c21, 0x83012029, 0x82ff2015, 0x060a4d8f, 0x41676621, 0xff23059b, 0x833333ff, 0x254883d7, 0xff3333fe, + 0x28830200, 0xc782fd20, 0x84020021, 0x99192613, 0xffff8d08, 0x206383fc, 0x82be8501, 0xb300226d, 0x21138230, 0x39826666, 0x53820020, 0x85fdff21, + 0x207882a9, 0x83f783fd, 0x82ff2067, 0x7d082009, 0x0a8205cc, 0x26413220, 0x4cfd2206, 0x05f849ce, 0x99fdff23, 0x201e8398, 0x22338219, 0x8268e6fc, + 0x9a5e1814, 0x20388208, 0x831a8289, 0xffff2206, 0x20c283fb, 0x238e82fe, 0xd04cfdff, 0x4c214482, 0x211a82cc, 0xd78266fe, 0x34b3ff24, 0x361affff, + 0xd0210b34, 0x2c1a828b, 0x069899d8, 0x19beffff, 0x00ff079a, 0x259a8314, 0xff3233e9, 0x61831a00, 0x34b3ef26, 0xf8ffffa9, 0x0a20b584, 0x992d6d84, + 0xffff939a, 0x8b6666f6, 0x99f4ffff, 0x1562189a, 0x4cf52b0d, 0xf2ffffcc, 0x088b34b3, 0xa4640663, 0x0f6b5a08, 0x18ffff21, 0x43097aa3, 0xab230ad9, + 0xc134fb07, 0x23914334, 0x6307ab22, 0x3f6eee82, 0xfb841809, 0x660b340d, 0x0700ff66, 0x00ff46f6, 0xff9a9909, 0x02ab0a00, 0x840200ff, 0xfa1d22ff, + 0x831982e1, 0xe61a2514, 0x1000ff67, 0x0034ec82, 0xff717d14, 0xcecc1600, 0x4100ff08, 0xff0766e6, 0xcd8cd8ff, 0xfe2d5c82, 0xff8beb51, 0x7b54feff, + 0x190000ff, 0x2109829a, 0x0982b85e, 0x08cc4c27, 0x75fcffff, 0x210a82c2, 0x098234b3, 0x3b82bd20, 0x6e820120, 0x30fdff24, 0x1a828da4, 0x3333fd28, + 0xfdffff8d, 0x7182299c, 0xfe272083, 0x00ff8f42, 0x82981903, 0xa8fe221a, 0x261482f6, 0xffff6866, 0x82eb11ff, 0x32b32109, 0x8c210982, 0x830982cd, + 0xffff237b, 0x0a833d8a, 0x5982cc20, 0x14840c20, 0x82200983, 0x02223d82, 0x9a829a99, 0x3d830020, 0xb9830320, 0xa4700122, 0x33215282, 0x212d8233, + 0x09821f05, 0x8233b321, 0x8302201e, 0x8301200a, 0xa30222d3, 0x82ed84d7, 0x82262019, 0xcc0122e2, 0x841e82cd, 0xcc002133, 0x01225782, 0x61823e8a, + 0xff999925, 0x839e0100, 0x008021d0, 0x1c211e82, 0x290a82de, 0x0534b309, 0x971900ff, 0x0160ff0b, 0x83172005, 0xe60c252e, 0x1500ff66, 0x0021ff82, + 0x21678410, 0x7782b30b, 0x33330922, 0x38252982, 0xff079a19, 0x05a143ff, 0x0080fa22, 0x2105f946, 0x2083faff, 0xcecc0125, 0x83fbffff, 0x33032209, + 0x26fa8232, 0x8ecd4cfd, 0x84fdffff, 0x225082bd, 0x8266feff, 0x33032255, 0x201a8234, 0x202583fe, 0x230f8202, 0x3433ffff, 0x4884b382, 0xe6219e84, + 0x201e8266, 0x207a83ff, 0x21148206, 0x38820100, 0x51060023, 0x23f184ec, 0xf30400ff, 0x00213d82, 0x221e8302, 0x821ec502, 0x22ad83f1, 0x827a5402, + 0x834c2009, 0x68a621e6, 0x0220d782, 0x00223883, 0xec8298d9, 0x82cccc21, 0xf8a821f6, 0x1e820983, 0xc275002e, 0x00ffa208, 0x053e4a06, 0x0a00ffb3, + 0x25205a83, 0x11254083, 0x00ff52b8, 0x35548321, 0x081ec517, 0xff52068b, 0xae0796ff, 0xff074b15, 0x66e6c000, 0xf082cb06, 0x9a193f2a, 0x74fb4b06, + 0x4001ff15, 0xfe211185, 0x251183bf, 0xffaf0e07, 0xc2822d01, 0x269d0127, 0xffff1566, 0x277a83f4, 0xff223005, 0xe27af2ff, 0xef2bfb82, 0xf6ffff1a, + 0xffff7a94, 0x8200a0f7, 0x0a792dd7, 0x88ffff3d, 0xff055e1a, 0x3333acff, 0x3f133861, 0x08d663e6, 0xe6a0ffff, 0xff8b0766, 0x707de5ff, 0x7d1500ff, + 0xebffff71, 0x00fff668, 0x8b8f821a, 0x5326de82, 0xff060ad7, 0xbd828600, 0x1988ff33, 0x00ff059a, 0xffe8fb05, 0x20b0faff, 0x980700ff, 0x21748292, + 0x0982d037, 0x8316ae21, 0x70042d2b, 0x00ff8b20, 0xffb48804, 0x00f00000, 0x32260982, 0x0100ffb2, 0x5f7310e8, 0x27052207, 0x262b82f0, 0x00ffec51, + 0x826c670b, 0x990c2829, 0x01ff089a, 0x823e4a7d, 0x1cff2cf2, 0x0c00ff28, 0xffff0a97, 0x829a99f9, 0x86828220, 0x662621df, 0xd42d3f82, 0xffff34b3, + 0x1500c023, 0x072f00ff, 0x200483b0, 0x218b82ae, 0x65826009, 0x4b820482, 0x5c2f0f22, 0xa020fc82, 0x61210f83, 0x20d48248, 0x290a86f6, 0xd0f0ffff, + 0xffffffa4, 0x1e82b8fe, 0x04839e20, 0x8200a021, 0x02d1261e, 0xd0ffff8c, 0x22448207, 0x8219d0ff, 0x832f206f, 0x85ff20db, 0x83548234, 0x8c8b2034, + 0x86f62030, 0x20da823b, 0xc1d21901, 0x072f2212, 0x224f82ae, 0x840552f8, 0x82048405, 0x834f830a, 0x834a8254, 0x82002085, 0x825484aa, 0x5f0922d0, + 0x260a827c, 0x00ff84a0, 0x82e02f0f, 0xf2fd269f, 0x610900ff, 0x20048348, 0x221e828a, 0x8266e62f, 0x3e0a21e4, 0xef83e482, 0x83d0ff21, 0x9e00205a, + 0x1a0e4134, 0x14eed022, 0xe3274f82, 0xf70e05d6, 0x68d4f794, 0x42180efa, 0xa78208fb, 0x8266ee21, 0x4c0e2d78, 0xf1ffffcd, 0x00ff9a99, 0x8b33b311, + 0x09f0a518, 0x7e1e4521, 0xb8201061, 0xba212882, 0x451684e2, 0x082305b1, 0x6e14f78b, 0x8b215ce6, 0x225f83fc, 0x82ec51ee, 0xb5f122ad, 0x239192c2, + 0x1f450e00, 0xbf921684, 0x820a8a59, 0x61ee223f, 0x83bf8548, 0x22bf8c16, 0x82c2f5ca, 0x02d5381f, 0x568b6090, 0xff568b08, 0x48212a00, 0x3500ff60, + 0x088b66e6, 0x8295ffff, 0xe1352d06, 0x8b08f58b, 0xffe1e1f5, 0x9a196a00, 0x00241582, 0x8b3e0a35, 0xfd212882, 0x08338670, 0xf8d4ff30, 0x8b566052, + 0xffaf0e08, 0x33b39e00, 0xe67100ff, 0xffff1566, 0xff6766e5, 0x66663e00, 0xfeffff05, 0x00ff9919, 0x849a9907, 0x660300ff, 0x6e4cff66, 0x34332806, + 0xffff5e08, 0x8242a0fb, 0xc0ee2f21, 0x2e00ff00, 0xffffb8de, 0xffb89eff, 0x09823400, 0xa1110029, 0x2f00ff48, 0x82082adc, 0x77258415, 0xff2c0594, + 0xff927c3f, 0xcc4c0400, 0xe60100ff, 0x06246282, 0xff0834b3, 0x2305e976, 0x0500403f, 0x0c201a82, 0x072d1a82, 0xffffd663, 0xff3433fc, 0x00800800, + 0x21148285, 0xd0820040, 0x82ccd821, 0x1f18221a, 0x2271827e, 0x820a97f1, 0x5476821b, 0xfc2305e8, 0x69ff26a0, 0xf322055b, 0x29825c80, 0x825ea321, + 0x68983875, 0x0000fff6, 0xffff48a1, 0xe99a1964, 0x00ff0824, 0xff00e009, 0x8240f5ff, 0x411321ac, 0xfe201682, 0x0c220983, 0xdd82b99e, 0x5f82c020, + 0x61270022, 0x1822b282, 0x8582b81e, 0xe2fa0522, 0x3a207582, 0x03210482, 0x82fd8299, 0x82882085, 0x4c23086f, 0x01ff08cc, 0xff686640, 0x9a19ceff, + 0x00ffff15, 0xff0666e6, 0xb89edcff, 0xe4ffff8b, 0xffffae47, 0x824861e3, 0x85dd2a0a, 0xffff081e, 0x6babfeff, 0x06be4105, 0x10a84a18, 0x1a3f0123, + 0x212182f0, 0x6b823433, 0x46a11124, 0x2184ff8b, 0x830e0021, 0x1000233f, 0xac8252b8, 0x7c000027, 0x191f00ff, 0x27ed829a, 0xff84ffff, 0x32332500, + 0x4c2c6582, 0x1c00ffd0, 0xffff9a99, 0x8b32b3db, 0x2005445d, 0x4e61182b, 0x87f22208, 0x884882ae, 0x057f4f43, 0x0d215a86, 0x22cc827a, 0x82e2ba10, + 0x83002034, 0x20168506, 0x05d650ff, 0xae47ef22, 0xe6217183, 0x05735c66, 0x83f1ff21, 0x22048461, 0x836666ee, 0x2f200831, 0x34f89a19, 0x9e00ff15, + 0xff06fe7f, 0x68661200, 0xfd3f00ff, 0xfeff05f4, 0xff9a197f, 0x82000000, 0x6926a584, 0xe6a0feff, 0xb2630566, 0x707d2205, 0x311482cb, 0x0690829e, + 0x32f7ffff, 0xffff8bf2, 0xff0ecdf8, 0x0a830700, 0xe6070024, 0x9e8208a8, 0x8ccc0822, 0xff231184, 0x824d0600, 0xcd08221b, 0x226c830e, 0x829a196a, + 0x7d112264, 0x84648272, 0x668422ff, 0x8444b066, 0x11002333, 0x4487707d, 0x898d5584, 0x8282f020, 0xc1828983, 0xffb40529, 0xbc340e00, 0x830800ff, + 0x330722d0, 0x20978234, 0x25fa82e6, 0xa4f72f0e, 0xf982c4f7, 0xcccc0822, 0xf4182d83, 0xc0211660, 0x822f8200, 0xf7ff231b, 0xc2820040, 0xf0820684, + 0xff231682, 0x8234b3f8, 0x4cf722fb, 0x20f082cc, 0x820682ff, 0xcc4c2128, 0xb3201b82, 0x08206282, 0x08241b82, 0x54fb44f7, 0xa5f08a18, 0xa4f7642c, + 0x2c00ff15, 0xff8bcc4c, 0xbf822300, 0x270db57d, 0xffb81eeb, 0x0040f3ff, 0x20067c58, 0x2dfc83ec, 0x08b85ef4, 0xe1f2ffff, 0xff8b0748, 0x1b83f7ff, + 0x1683f820, 0x0e820484, 0x4b088b23, 0x21178206, 0x1d82cd4c, 0x33b3f827, 0x330700ff, 0x335b8233, 0x08cdcc08, 0x190d00ff, 0xffff079a, 0xffcdccec, + 0x9a990b00, 0x2305fa58, 0x66661200, 0x14232082, 0x820866e6, 0x82232006, 0x23002150, 0x1c202083, 0x00215582, 0x233c822c, 0x89ffff08, 0xff244882, + 0x15cd4c51, 0xe0305982, 0x0300ff00, 0xffffe77b, 0xff0a37fc, 0xf0670900, 0x78270e82, 0x0800ffd5, 0x83084821, 0x8211200a, 0x1018210a, 0x78211982, + 0x210e8294, 0x0e8219c4, 0x825c0f21, 0xdf8f212d, 0x692b1e82, 0xffffeebc, 0x050cc2d2, 0x826900ff, 0x2d0023ed, 0x0a82c235, 0x83070821, 0x21702144, + 0x7f213482, 0x212a82be, 0x3982e13b, 0x82527821, 0xf6e7216c, 0x10205384, 0x72827785, 0xfffff024, 0x198398f6, 0x82e0df21, 0x8f822128, 0xb2279c82, + 0xffff846b, 0x82ebd1de, 0x944d2248, 0x200a837c, 0x220a82ec, 0x82002008, 0x18842120, 0xc8214982, 0x823483f6, 0x87fc2243, 0x2148822a, 0x6a18bade, + 0xf92707ed, 0xffff78e9, 0x829a19fa, 0x68662428, 0x67f9ffff, 0xfd2705f2, 0xff8bf0e7, 0x82d8fdff, 0x670022c3, 0x200982fc, 0x210983f8, 0x3582f4df, + 0x82479621, 0x382d28a8, 0xffff0510, 0x82cd4c96, 0x3eca28c9, 0xffff8905, 0x82281cff, 0x82cc2026, 0x99ff2110, 0xfd204c82, 0x22052c46, 0x82efc7f9, + 0x19fa2247, 0x21828258, 0x208218a4, 0xff666626, 0xe00f0600, 0xfc274782, 0x00ff1f85, 0x823aff08, 0x4b358219, 0x08200513, 0x00228782, 0x16828003, + 0x944d0028, 0x2100ff7b, 0x6682142e, 0x856bb222, 0x382c0a82, 0x01ff0553, 0xffcc4c06, 0x33b32eff, 0x36445718, 0x4344fb21, 0xcd260674, 0x0700ff8b, + 0x04833333, 0x0a823420, 0xcccc0822, 0x82053744, 0x83f8205d, 0x3307218d, 0x078a8818, 0xf7ffff23, 0x68871833, 0x12744309, 0xf820f182, 0x3c057443, + 0x0e088b33, 0x4801ffaf, 0xe4f79a19, 0xeb00ff15, 0xfeff9a99, 0x059a99da, 0x00ff8193, 0x28b88304, 0x8b32b3f3, 0x4cf3ffff, 0x20fe82ce, 0x191374e8, + 0x4a74fc21, 0x00230cb0, 0x82008015, 0x801a26a3, 0x00ff0800, 0x05a67417, 0x32b30c22, 0x53265382, 0x0c00fff8, 0xc582ce4c, 0x9527f122, 0x23081c82, + 0xffe1baea, 0x66662501, 0x00ff5b05, 0x0590023c, 0x19f4ffff, 0x0d00ff9a, 0x00ffcccc, 0xff991903, 0xd8231400, 0xcd250e83, 0x090b00ff, 0x20308278, + 0x22eb830d, 0x823e0a0b, 0x261e8219, 0x12c3fdff, 0x830a00ff, 0x33f222fa, 0x2f1e8274, 0xff66e627, 0xe23acfff, 0x00ffb205, 0x051ec530, 0x4f853682, + 0x30838c20, 0x02225982, 0x8182ee3c, 0xf4222583, 0x3082c2f5, 0x96820e20, 0xf6f4ff26, 0x0200ff88, 0xeb224583, 0x828528dc, 0x33f2ff2a, 0xff5b0834, + 0x70fdc3ff, 0x4f2f4482, 0xe4fb6666, 0x88ffff15, 0x00ff0080, 0x82cc4c9c, 0x300a83a7, 0x34b363ff, 0x0683f705, 0x01ffaf0e, 0xf79a9942, 0x39228294, + 0x8bcccceb, 0x66a9ffff, 0xffff8967, 0x373333c8, 0x8b07e108, 0x56b660c0, 0x3b70088b, 0x11c6490d, 0x49486121, 0x735c07c6, 0x38bd1805, 0x0a064909, + 0x0794fb22, 0xc6185e82, 0xf72113f5, 0xd9ac1844, 0x0700290c, 0xff8b0020, 0x9af90700, 0x1022e582, 0x416e66e6, 0x2c6c830e, 0x8b4861ee, 0xf7066b08, + 0xfb05eb14, 0x221f8224, 0x8220f7ff, 0x233782de, 0xe0f8ffff, 0x08250982, 0x088b00e0, 0x825593ab, 0x2c558219, 0x079a19ce, 0xc0f5ffff, 0xfdffff00, + 0x23048260, 0xffb85ef5, 0x2105045f, 0x5982e1f4, 0xc2ffff24, 0xac823433, 0xcc4ccc23, 0x055441b7, 0x663a0023, 0x08378266, 0x66669d24, 0x064b15eb, + 0xff05cb4b, 0x9a9979ff, 0xb6568b07, 0xe6d5ffff, 0x088bc066, 0xffb68bc0, 0x9a192a00, 0x2782c08b, 0x66668628, 0x054b4b07, 0x4e7a3b43, 0x20b78720, + 0x7ab28400, 0xc4820d18, 0xd983ff20, 0x9e710820, 0x66e62108, 0xff21e085, 0x226882f7, 0xdc8bdb08, 0x2f0e2b5e, 0x19bd01ff, 0x6d00ff9a, 0x68826666, + 0xe23af123, 0x2bf682ab, 0xff1ec5fa, 0xce4c0b00, 0x99f4ffff, 0x07211b82, 0x05477b4c, 0xff088b2c, 0x5c8f9dfe, 0xf3ffff06, 0xaf821f85, 0xf6a8f422, + 0x23052047, 0x8fc2faff, 0xb3282b82, 0xffff0832, 0x6be13af1, 0xfb2b4282, 0xffffdf6f, 0xff1018f6, 0x82cc0000, 0x6ff42715, 0x0500ff9e, 0x138200e0, + 0x615ccf21, 0x0a840503, 0x0a00ff29, 0xffff0e2d, 0x823473fa, 0x8f022109, 0x00266182, 0xfb420000, 0x5e820504, 0xfc29f725, 0x820700ff, 0xf8ff2804, + 0x00ff04d6, 0x4104d608, 0xd62206ef, 0x18838b87, 0x1d847920, 0x19820a82, 0x04f70829, 0x0694f707, 0x960704fb, 0x00ff2538, 0x069a191f, 0x88204583, + 0x78203c84, 0xff273c8b, 0x8acc0100, 0x820504f7, 0xf6e82183, 0x0a221e82, 0xad82842b, 0x82e08f21, 0xbade2604, 0x300900ff, 0x86b28320, 0x24d1820a, + 0x00ffacc7, 0x231e820b, 0x0080fbff, 0xe62a1e82, 0xe2fb0866, 0x99d200ff, 0x3c82159a, 0xe07a1d26, 0x331000ff, 0x1821d082, 0x283c829e, 0xffcdcc17, + 0x1ec50e00, 0x24988208, 0x0548213b, 0x248482bb, 0xf75b0200, 0x24098364, 0xa5fdffff, 0x280984fb, 0x62020000, 0xe6c400ff, 0x31848266, 0xffd0b018, + 0x9a19f2ff, 0x4c0f00ff, 0xe6ffffce, 0x3b82e27a, 0xad4ae220, 0x98fd2305, 0x228214fb, 0xae07302b, 0xffffff06, 0x14f7dafc, 0x25738205, 0xffa4b046, + 0x0482c6ff, 0x4f390035, 0xb9ffff5c, 0x088b5c4f, 0xfdbfffff, 0xffff06e0, 0x823333ba, 0xaec6223e, 0x82218414, 0x821d820a, 0x040022ce, 0x2249840c, + 0x8252f82f, 0x22ff2224, 0x2549825a, 0x01ffaf0e, 0xb982b356, 0xcc4c5f23, 0x20fc8215, 0x20dd83c0, 0x200482a0, 0x24e78303, 0x8b00200b, 0x07cf4797, + 0x40e3ff22, 0x1c201782, 0xff232182, 0x8366a6dd, 0xc0ee226d, 0x205c8200, 0x232982f0, 0x0020f9ff, 0x08055150, 0x01f5ff36, 0xffff0848, 0xffccccee, + 0xb99e1d00, 0xcce0ffff, 0x1500ffcd, 0xffff9919, 0x8b67e6da, 0x608b5608, 0xf0d4ffff, 0x08568ba4, 0x00ff898b, 0xffbe8000, 0x2050feff, 0x20220982, + 0x38828900, 0x0080da28, 0xe4ffff7e, 0xbe4b47e1, 0x21d62107, 0x002d4f82, 0xff26e300, 0x3cffcaff, 0xfe2a00ff, 0x274082ab, 0x00ff9a19, 0x8b000035, + 0xef27d682, 0xff069a19, 0x82402c00, 0x2200228b, 0x201782d9, 0x83968323, 0x271c8210, 0xfff6e800, 0x66e62900, 0x99208782, 0x21241a82, 0xff6266e6, + 0x20061e47, 0x25b782de, 0xce4c3600, 0xae822e15, 0xff21da82, 0x281083aa, 0x8bb85e47, 0xfa5d00ff, 0x20f683e2, 0x83f18436, 0x8231206b, 0x300028f6, + 0x00ff1e05, 0x8266e61a, 0x60072557, 0x0400ff00, 0xff24b282, 0xb8fe0a00, 0x23055748, 0x90820100, 0xf436c182, 0x00ff7a54, 0xff1e2502, 0xce4cf4ff, + 0x200100ff, 0xf3ffff00, 0xaa826666, 0x1996ff29, 0xff358b9a, 0x821eaaff, 0x95ff2363, 0x638248e1, 0x80f7ff22, 0x00214982, 0x202482a0, 0x206383f7, + 0x822e8301, 0x07314309, 0x1483fb20, 0x82be0521, 0x83fb2062, 0x21052772, 0xfaffff48, 0x1e8200a0, 0x66660b22, 0x1e838282, 0xa1830d20, 0x47830220, + 0x83e60b21, 0x34002367, 0xc48248e1, 0x52382a26, 0xded4ffff, 0xcb216b83, 0x206b8421, 0x214282fc, 0x3282ffff, 0x0985ff20, 0xfc207583, 0x20051447, + 0x2061829e, 0x20ee83f5, 0x201e8312, 0x230983ed, 0x7448210b, 0x36256782, 0x00ff4861, 0x27398203, 0xec513100, 0xe01900ff, 0x2127af82, 0x00ff6866, + 0x82b81e29, 0x0607271e, 0x0600ff64, 0x9682e27a, 0xffcc4c37, 0x9a990900, 0xb3f7ffff, 0xfeffff34, 0x0e086666, 0x84f7ebef, 0x328b8215, 0xff28dc3d, + 0xd7233200, 0x3d3100ff, 0x3c00ff72, 0x828bc3f5, 0xa634223b, 0x211b8266, 0x3282d92b, 0xcc8cdb28, 0xcfffff97, 0x1682ae07, 0xcf831320, 0x52380926, + 0x0500ff9f, 0x14210a83, 0x22d58466, 0x82649b04, 0x8b04272d, 0xffffff86, 0xfb827c9e, 0x822a8721, 0x848f2109, 0x18213182, 0x23a38221, 0x0590c222, + 0x252a3182, 0x0700ff1e, 0xfffffc69, 0x9982c0fb, 0x88410a22, 0x1e398f82, 0x0100ff96, 0xff089c99, 0x2646a8ff, 0x021000ff, 0xff7b05a2, 0xec915800, + 0x28a78405, 0xe20800ff, 0xf5ffff8e, 0x22c082cc, 0x4f783e04, 0xfa220649, 0x3082e0da, 0x8182b620, 0xafccff23, 0x8329829e, 0x3300230a, 0x0a82a450, + 0xff7ff822, 0x20206a83, 0xcd203483, 0xc1216a82, 0x2e488506, 0xb21df7ff, 0xefffff08, 0xffffe1fa, 0x82146ea7, 0x83058229, 0x82e2200f, 0x861b820a, + 0xc0fb2225, 0x21398283, 0x438332b3, 0x6e821f20, 0x829a9921, 0x4c3321c4, 0xb6224982, 0x29825c0f, 0x75b3cc27, 0x23b6ffff, 0x210a82d8, 0x4a82dafa, + 0x0496f822, 0x3f21ef82, 0x2134825c, 0xad8276be, 0x8368e121, 0x82682048, 0x92582234, 0x215e82b0, 0xf98250f8, 0x90021022, 0x6b217482, 0x260a8284, + 0xffa09a01, 0x821ef7ff, 0x410a222a, 0x269e828a, 0x00ff42c0, 0x83f66807, 0x82e4206e, 0xb50a2234, 0x210f82c3, 0x2982986e, 0x9ab90234, 0x262300ff, + 0x1100ff66, 0x00ff0020, 0xff2a5c1f, 0xbd821900, 0x97150023, 0x21c8820a, 0x148280ca, 0x166e0826, 0xe6d6ffff, 0x2d322382, 0xff8b66e6, 0x66e63700, + 0x158bab08, 0xd3ffff8b, 0x3d82ecd1, 0xff290482, 0xff142edc, 0x142e2c00, 0x225e828b, 0x82a0ba09, 0x33092725, 0x0100ff74, 0xae82fafe, 0xff48a126, + 0x142e0300, 0x07261a82, 0x00ff8300, 0x4a82a621, 0x2b87122f, 0x331d00ff, 0x1a00ff34, 0x00ff3e0a, 0x2c6e8414, 0xff84abfb, 0x82152800, 0x66deffff, + 0x218d8267, 0x7882cc4c, 0x82cdcc21, 0xad161954, 0x01ff2215, 0x2a4182bf, 0x66668aff, 0x0000ff15, 0x828d0020, 0xcc9e2105, 0xbe217682, 0x43661876, + 0x61232309, 0xbc44ff48, 0xb89e2606, 0xa6ddffff, 0x224f8368, 0x824861f3, 0x5ef421c0, 0xfc261182, 0xffff4240, 0x09821ef6, 0x00c0f922, 0x23051649, + 0xe12600ff, 0xd9203582, 0x00281482, 0xff52381a, 0x9a99d2ff, 0xc2223583, 0x35820040, 0x00c0cd26, 0xe1cdffff, 0xc3254083, 0x8b081e05, 0x26768288, + 0xffff90c0, 0x84ca41fd, 0x20098286, 0x20488320, 0x825d85ce, 0x83d8202c, 0x02d72231, 0x213c8390, 0x6382b85e, 0x9849fe2a, 0xf7caffff, 0xc060b6d0, + 0x01245782, 0x06feff0f, 0x24056b48, 0xc08b70fd, 0x3dbc8208, 0xff2a1c2a, 0x9c99e5ff, 0x4c2300ff, 0xdaffffcc, 0x08980080, 0x0ef9ef0e, 0x33ab00ff, + 0xaf821534, 0xff400028, 0x48e10d00, 0x0082ff05, 0x00ffc026, 0x0550384d, 0x0b203682, 0xf326b683, 0x00ff0080, 0x40829c07, 0xfb83f520, 0x839efa21, + 0x82f52071, 0xfaff22cb, 0x208c82a0, 0x211483f7, 0x0982e0f7, 0x1383f920, 0x8380f621, 0x40be21ab, 0x5a223382, 0x4f8286eb, 0x9ad9ed30, 0xf51800ff, + 0xe3ffffc2, 0x00ff3233, 0x0982b50e, 0x3433e12c, 0xd3fb088b, 0xcfffff06, 0xc582b85e, 0x48a1d827, 0x99d8ffff, 0x290a829a, 0x086666cf, 0x9ea9ffff, + 0x967807b8, 0x47f42206, 0x829f82ae, 0xeeff2183, 0xff293582, 0x66e6ebff, 0x93076b08, 0x21ca8206, 0xa3824861, 0xb89e1c22, 0x200c617c, 0x20b883f3, + 0x64b88210, 0x0e2205a4, 0x7482703d, 0x05220e83, 0x598248e1, 0xa483ff20, 0x66e6fb22, 0x5383e782, 0x7484fb20, 0xb483fb20, 0x00000025, 0x82c4fb0d, + 0x07294a3d, 0x4aff4221, 0xdf280629, 0xff088bbf, 0x99193f00, 0x26192d4a, 0xf7270000, 0x55ff0504, 0xa0200656, 0x0a22fd82, 0x3f8600e0, 0x82c00b21, + 0x05364109, 0x224fe520, 0x82202006, 0x40072220, 0x22208683, 0x837dbf08, 0xe0082260, 0x24cf8200, 0xff9a3906, 0x05de4a00, 0x77821082, 0x00401131, + 0x0900ff07, 0xff8a0120, 0x46c10300, 0x82feffff, 0x1300284f, 0x00ffba1e, 0x82006002, 0xa0ee23d2, 0xfe490700, 0x07002206, 0x22758740, 0x8900c008, + 0x097a1b54, 0x1e1a2210, 0x2c5482b8, 0xff64990d, 0x48610500, 0xcc0a00ff, 0x217582ce, 0x6882cc4c, 0x82666621, 0x34332104, 0xff235882, 0x49fbb2ff, + 0x3a4b054a, 0xf907280d, 0xcb088b9a, 0x8300ff06, 0x82368263, 0x21b18a73, 0x598244f7, 0x9a191f2f, 0x00ff056b, 0xff280000, 0x3473d6ff, 0x209f8205, + 0x306783f3, 0xff84c003, 0x84abf3ff, 0xff0600ff, 0xf5ffff7c, 0x24c08280, 0x02402900, 0x262c824d, 0xffbc990a, 0x82e6f2ff, 0xb30e237e, 0xbe64ff34, + 0xe60f2205, 0x26c58368, 0x8b008016, 0x831300ff, 0xe10f2141, 0x0425ae82, 0x00ffb85e, 0x5aae1816, 0x6c002308, 0x40829a99, 0x30b30122, 0x99229382, + 0x0582899a, 0xff234682, 0x8268e6fa, 0x9a19259d, 0xfffeff08, 0xa44ada83, 0x1ee92c05, 0xe9ffffb8, 0xff050040, 0x8214eaff, 0x59ea2583, 0xe2ffff99, + 0xff28f582, 0xffcdccf3, 0x3433e1ff, 0x06847182, 0x33261682, 0x0c00ff32, 0x2a823333, 0xff9a1927, 0x33b31500, 0x823b8208, 0x1600230f, 0x408234b3, + 0x0a83f020, 0x82990f21, 0x820d201a, 0x17002640, 0x00ffcccc, 0x05936218, 0x3233a623, 0x200c8306, 0x83b88202, 0xe8ff221c, 0x20d48233, 0x278782f0, + 0x6666f0ff, 0xc600ff08, 0x4722e483, 0xa04b6666, 0x4b68204f, 0x982d08ff, 0xff0e088b, 0x3e0a1400, 0xb38200ff, 0x25678234, 0x8bc2f5fd, 0x616bff89, + 0x80022206, 0x23858200, 0x07cccca2, 0x0222a182, 0x1782dc59, 0x82f6e821, 0x36a92704, 0x170200ff, 0x1c828b4c, 0x2eb00022, 0x002c1b82, 0xffff32b5, + 0xffecd1ff, 0x7faa0000, 0x9a210982, 0x321a82ee, 0xffb89e4c, 0x66e6d2ff, 0xb4ffff05, 0xffff52b8, 0x8232b385, 0x2fff2a0a, 0xfdffffdf, 0xffffb0a9, + 0x221483fe, 0x820080ff, 0xe1ba2109, 0xd3274b83, 0xffff285c, 0x829819a8, 0xcc2f2786, 0x1600ffcd, 0x30825c0f, 0xe1bafb22, 0x7b215682, 0x2635826a, + 0x00ffa225, 0x828aa203, 0xe0032370, 0x068208c4, 0xa8660122, 0x5f211b82, 0x2193825c, 0x0982da6e, 0x8200d021, 0xb6532109, 0x69307c82, 0x00ff2170, + 0x054ee29b, 0xb36c00ff, 0x41ffff33, 0x37288784, 0xffff34b3, 0x159a19f1, 0x02223b82, 0x2c82fc09, 0x820c8221, 0x6c0721ca, 0x6c210482, 0x21cf8408, + 0x1b82582a, 0x712b0022, 0xfd21c582, 0x21528292, 0x09827e2c, 0x82fafa21, 0x99cb2752, 0xe9ffff9a, 0x9382a4b0, 0x0a57be23, 0x2e168207, 0xffff0bf6, + 0xff5e6efb, 0x9919fdff, 0x83fcffff, 0x46fb201f, 0xfe23053d, 0x828b12e3, 0xa6db21d7, 0x3d214182, 0x2109821c, 0x09825ae4, 0x088e842c, 0x9c3dffff, + 0x5700ffee, 0x4682bca4, 0xa470fe22, 0xcc211582, 0x211f82ce, 0x8c82f668, 0x82666621, 0x4c01227b, 0x256c82cc, 0xf70ad702, 0x188215c3, 0x8204b621, + 0x9cc32122, 0x59216d82, 0x212282db, 0x2283ec52, 0x843a5421, 0x824720fd, 0x9a002249, 0x21168216, 0x04823849, 0x820b3621, 0x08cc212a, 0x96273d82, + 0x00ffcdcc, 0x820a9762, 0x7c0022fd, 0x21158229, 0xe182bebf, 0x82333321, 0x0a572109, 0x4c212982, 0x21eb83cd, 0x4c835104, 0xd9ae0322, 0x4721bb82, + 0x22af826e, 0x82f2b2fb, 0xfeff2357, 0x6e82f89e, 0xe1829f20, 0x9e8ffe22, 0x24210982, 0x2187824d, 0xbb82a09a, 0x8222b021, 0x1371220a, 0x20bb8276, + 0x22bb83ae, 0x8232b330, 0xdc702862, 0xff155129, 0x82975f00, 0x66a8225a, 0x21118266, 0x74821c03, 0x862b0425, 0x830500ff, 0x87022574, 0x0400ffae, + 0x20055e74, 0x32e48404, 0xff9a1906, 0x5278fdff, 0x1e0300ff, 0xfaffffb8, 0x8508f0e7, 0x57ff2340, 0x5d829a99, 0x717d2623, 0x22e88206, 0x828aec00, + 0x99d12858, 0xff156b99, 0x82999bff, 0x4c502233, 0x831e82ce, 0xaf00210a, 0xc82a7c84, 0xff06cccc, 0x34b37700, 0x2a8264fb, 0x826c0221, 0x010023c0, + 0x5d820c82, 0x8294f821, 0xf6fd22d2, 0x21d28404, 0xc8823c9f, 0x828a4f21, 0xf49d21c8, 0x6f210482, 0x210e82f2, 0xd282ac3c, 0x55833d20, 0x0a57a822, + 0xfe225582, 0x1582a2e5, 0x82a67d21, 0xacdc211f, 0xc3210982, 0x220982d0, 0x828b18e4, 0xccfb2225, 0x224c82cc, 0x82be34fc, 0xfa5e21b0, 0x04229982, + 0xb1827c9f, 0xa4b04126, 0xcb00ff07, 0x00234282, 0x82ae4716, 0x100022f8, 0x263882e6, 0x00ffde21, 0x82323300, 0x06236e04, 0x00224282, 0x1082b312, + 0x34332c22, 0x0022a582, 0x5982cecc, 0x00223583, 0x09836666, 0x5c829820, 0x9a99fe22, 0xfc22a983, 0xbb82c420, 0xffb4282b, 0x7e5ffcff, 0xb6fbffff, + 0x21508288, 0x8382dc84, 0xcccc2f27, 0xf0e9ffff, 0x206682a4, 0x223b836c, 0x829a19be, 0x87692b0a, 0x64ffff2a, 0xff05d823, 0x56824dff, 0x075c0124, + 0x318215ae, 0xff542426, 0x1e650100, 0x9f210982, 0x21098200, 0xb3826270, 0x48610122, 0x00236182, 0x820e4d04, 0xdaae21c5, 0xb8260482, 0x0400ff94, + 0x9e83ea51, 0xda4e0122, 0x5d212283, 0x213282f2, 0x3282aea8, 0x820c5721, 0x2a3b2109, 0x9620e582, 0xff235782, 0x82f6689d, 0x3601226d, 0x21158204, + 0xda82e433, 0x821c9a21, 0xa6b821b9, 0xb921b983, 0x22578216, 0x82acfeff, 0x59ff22d5, 0x211682e8, 0x04820ead, 0x82f8b521, 0x5238212a, 0xae27b982, + 0xffffa871, 0x82e650cf, 0x19b027a3, 0x8e00ff9a, 0x4b8214ee, 0x0080ae28, 0x5e84ffff, 0x4c4415b8, 0x055c4405, 0x56feff23, 0x225282c8, 0x8226a6fd, + 0x335d2337, 0x0c830732, 0xff5a8425, 0x83fbfdff, 0x827a2058, 0xf6fd2274, 0x23b08286, 0xe2bafeff, 0xfe221b82, 0x8b8292b8, 0x82869721, 0x2e32216a, + 0x51214282, 0x273782f2, 0xff52b8b4, 0xcd4c7a00, 0x4c276482, 0x00ffb89e, 0x8299192d, 0x9001220a, 0x212082a4, 0x2f82584e, 0x8232b321, 0x34332104, + 0xcc2f3482, 0x0e088bce, 0x0700ff2f, 0x01ff77fe, 0x82008026, 0x5301238c, 0x28828b75, 0x826b5c21, 0x82a6201e, 0x49012228, 0x320982ba, 0xff08563b, + 0xf007c400, 0x1e8bffff, 0xffff0578, 0x83343320, 0x42f6319b, 0xf8ffff4e, 0xffff1058, 0xffee07f9, 0x61a5f7ff, 0xfd229b83, 0x9b82df4f, 0x823dfd21, + 0xb8002258, 0x21bc82a0, 0x51822566, 0x82f29421, 0xcc67279b, 0x5c00ffcd, 0x42825278, 0xd763ec2d, 0xef0b00ff, 0xf3ffffe0, 0x82a1b8de, 0xcc172273, + 0x206482cc, 0x05366bc5, 0xa4830520, 0x27d1032c, 0x990200ff, 0x0400ff9a, 0x5982502d, 0x34a20129, 0x2400ffbe, 0x8315cc4c, 0xce2c265f, 0xa5feffff, + 0x215f82e4, 0x0482922d, 0x820e4d21, 0x2466210e, 0x39276482, 0xffffdad9, 0x8216d989, 0xe1392764, 0x7600ff48, 0x0a823433, 0x5c4ffd22, 0x4c828582, + 0xa8feff28, 0x0300fff6, 0x738232b3, 0x66e60123, 0x22068208, 0x82cecc02, 0xec51211b, 0xcd216d82, 0x21048292, 0x0e821fa5, 0x82349e21, 0x19a5218e, + 0x642d7d82, 0xff0568e6, 0xf5c80a00, 0x0e0600ff, 0x21b58254, 0x40823333, 0x82e40521, 0x054d5c09, 0x06820b20, 0x2b300c82, 0xfcffff85, 0x00ff1cfa, + 0xff33f309, 0xf8f3f9ff, 0xff234086, 0x829a199b, 0x7a032140, 0xfe22ec82, 0x5b82b85e, 0x82686621, 0x343321b1, 0x3321c683, 0x28258232, 0xffcccc0d, + 0x34b3dbff, 0x83ea8215, 0x03002116, 0xfd221083, 0x21826666, 0xce4cfa22, 0x3a20d482, 0x3205966c, 0xff0040e8, 0x48e1f3ff, 0xecffff75, 0xffff0a57, + 0x825c0ff4, 0x8267201c, 0xa3ff23bf, 0xe6830080, 0x63216484, 0x235f84d8, 0x4cffffff, 0xfd235882, 0x828bcc4c, 0xb3f72225, 0x234e8233, 0x92cd4cf8, + 0x0921f282, 0x2ade83b3, 0x07ccccdf, 0x00ff58f7, 0x8266e674, 0x820120a0, 0x0000232c, 0xa085cecc, 0x4c000023, 0x830982cc, 0xaf0e2b3b, 0xb34c01ff, + 0xac01ff34, 0xa2826626, 0x66e60122, 0x7421ed82, 0x83e8827c, 0x65082209, 0x210e821e, 0x63829a99, 0x8007002a, 0xff928b00, 0xe27afcff, 0x8020c982, + 0xfa21ab82, 0x06825404, 0xe9ffff24, 0x64828480, 0x9a193428, 0x0c00ff06, 0x848232b3, 0xce4c0c2d, 0xf0faffff, 0x088294a4, 0x821100ff, 0xeeff254b, + 0xc3055c0f, 0x0d201f82, 0xff227682, 0x73820a00, 0x0a6fa018, 0x18077321, 0x231863d7, 0x0634b3ba, 0x42834a82, 0x0080e126, 0xcb04fb05, 0x17266a82, + 0x00ff9a19, 0xda83a68a, 0xcb827320, 0xd9d3ff23, 0x989c189a, 0x2c588217, 0xfff628f7, 0x34330700, 0xd7f8ffff, 0xf082180a, 0xf6282114, 0x0823b382, + 0x85080ad7, 0x21288206, 0x3282cccc, 0xff2b3782, 0x8b3433f7, 0xffff6b08, 0x8266e63f, 0x19202262, 0x178a689a, 0xa6826b20, 0x28142d65, 0x337300ff, + 0xffff0734, 0x26b482e7, 0x32b3f3ff, 0x83e5ffff, 0x83f92004, 0x49e3200e, 0xe3220573, 0xa7823333, 0xcdcce433, 0xe60600ff, 0x00ff7366, 0x08ce4c0c, + 0xcc8cffff, 0x656d8acc, 0x6d840c2f, 0x22082a78, 0x684c0e00, 0xff2407fa, 0x3333e600, 0xe32b6d82, 0x00ffe13a, 0xff67e60a, 0x8268e9ff, 0x661822fe, + 0x26d58266, 0x00ff2d32, 0x8234331f, 0x1efc325a, 0x0f00ffab, 0xff050080, 0x94b6fbff, 0x331100ff, 0x202e8232, 0x2080826c, 0x29298211, 0x60251100, + 0x190500ff, 0x1982089a, 0xffd72324, 0x14840300, 0xff486131, 0x9a99f5ff, 0x4a0400ff, 0xeeffff3e, 0x820866e6, 0x82e12019, 0x66f02314, 0x0a820568, + 0xff5c8f26, 0xccccf1ff, 0xc982be82, 0xe6f6ff29, 0x0e00ff66, 0x828b15ae, 0xd4cd3625, 0x00ff067a, 0x4a343370, 0xffef0e05, 0x156e1200, 0x33c000ff, + 0x22058233, 0x82ec91ad, 0xcdcc2193, 0xa4208882, 0xbb223583, 0x0a826666, 0xb8def522, 0xcc256a82, 0x0700ffce, 0x205f8221, 0x225483ee, 0x8333330e, + 0xb3de394a, 0xffff0634, 0xff4280f6, 0x00801a00, 0xbffaffff, 0xff8ba7be, 0x48e11c00, 0x2a226782, 0xfb82856b, 0x99598827, 0x665700ff, 0x22488267, + 0x823333e8, 0x84eb24e7, 0x83e0ffff, 0x83fe202c, 0x4cea2b4d, 0xedffffcd, 0xff08cc8c, 0x14838aff, 0x9a998b22, 0xf3222982, 0xdd8654a3, 0x7dff0823, + 0x20348277, 0x380482fe, 0x08333302, 0xc52c02ff, 0xddffff20, 0xff1567e6, 0xcc4c9bff, 0x403200ff, 0x26308200, 0xff00c0ef, 0x82200800, 0x83f52082, + 0xa0102209, 0x22868200, 0x82004012, 0xa6242886, 0x00ff0766, 0x8270fd3f, 0x1e1c21f4, 0xe928ca82, 0xff054861, 0x70fd0500, 0x0521af82, 0x2636821e, + 0xffff9c19, 0x829a99fc, 0x05344b09, 0x98191e22, 0x0b222b82, 0x43829819, 0x20050c26, 0xe00600ff, 0xa14c5d82, 0x83e02005, 0x5e0e2152, 0x8305ed4d, + 0xc05f2546, 0xde0a00ff, 0xfe2b5682, 0x00ff40e0, 0xff48e10c, 0x82c0f8ff, 0xc0092109, 0xff282982, 0xff9082b5, 0xb85e6300, 0xf922a282, 0x618244eb, + 0xff90022d, 0x6866f7ff, 0xc00400ff, 0x828b8100, 0x801223f5, 0x32820600, 0x8b66e622, 0x80208482, 0xf722c082, 0x23820060, 0x4801fb22, 0x3c26bb82, + 0xffff34b3, 0x3e839ecd, 0xec82c520, 0x84e7ff21, 0x20fa23ec, 0x2d828842, 0x48a1f722, 0xdf22c682, 0x288288be, 0x28833a20, 0x831ee721, 0xffff2128, + 0x93288c82, 0x8b056666, 0x2300ff43, 0xbc2ee583, 0x63c79a99, 0x3cffff08, 0xffff6666, 0x638240f9, 0x82336b21, 0xc0dd2157, 0xa6200982, 0xec225683, + 0x1e82b81e, 0x42e0f725, 0x83feffff, 0x41fa221e, 0x21928206, 0x648300c0, 0x1a829e20, 0xed000027, 0xf6ffff6b, 0x28cb8242, 0x83abff07, 0xbe0900ff, + 0x32bb82b8, 0x9a19f301, 0x3f00ff06, 0xff8b703d, 0x285c3800, 0x822f00ff, 0x020021c0, 0x3f220483, 0x9682cc4c, 0x5c4f0322, 0x6c831482, 0xcce62108, + 0x2b00ffcc, 0xffff9a19, 0xa09c19d6, 0xa9ffff08, 0x00ff66e6, 0x1566a6df, 0xbd2d00ff, 0xf4ffff72, 0xfd23e584, 0x82800040, 0x21848369, 0xc7821ef8, + 0x8261f421, 0xa10022e3, 0x24308248, 0xffe0faf2, 0x3d0a8200, 0x19f3ffff, 0x0b00ff98, 0x00ffb8de, 0xffce4c04, 0x48211100, 0x94f80e08, 0x191701ff, + 0xb282159a, 0xe63bfe2c, 0xfaffffff, 0xfeffff24, 0x0982385e, 0x8232f221, 0xe63b2109, 0xef224282, 0xbb820a17, 0xffca2125, 0x8266edff, 0xa004227d, + 0x210982c4, 0xca82ce8c, 0x59adff23, 0x273a829a, 0xff6626e9, 0x7cd4b5ff, 0xe0230a82, 0x82081ec5, 0xf5e42206, 0x303282c2, 0xffff4aec, 0xff2a9ce4, + 0xfeb41300, 0x2eeaffff, 0x304c8214, 0xffe27aec, 0xfa5ef9ff, 0x87ebffff, 0xfcffffae, 0x225682a1, 0x83b85eeb, 0xd1a8224c, 0x277782ec, 0xff0506ff, + 0xf668d7ff, 0x82210482, 0x220a8290, 0x8260e5f9, 0xa2e52b30, 0x2efdffff, 0xf8ffffd9, 0x5f82ce17, 0x0ad7f722, 0xf2276683, 0x00ff1e05, 0x82773e07, + 0x48e12147, 0xec231682, 0x8208ec11, 0xe41225ed, 0x3edeffff, 0xe4255d82, 0xffff0080, 0x23b482e5, 0x9919dfff, 0xf0206283, 0xff236982, 0x8285f0ff, + 0x0e062c36, 0xf4ffff14, 0x00ffd763, 0x82b8be0b, 0x73f42298, 0x2a0a8233, 0xffffc275, 0xffe1bafa, 0x82d90e00, 0x0e0023d9, 0x678234f3, 0xf2040023, + 0x205682b0, 0x2c208293, 0xff7cf404, 0xb91e0100, 0xd80400ff, 0x2b3582d4, 0xff7228fb, 0xd8e3feff, 0x0cfbffff, 0xff228082, 0x0982d26d, 0x83b01221, + 0xd9d5226b, 0x2d118299, 0xff1f05ef, 0xd6a32400, 0x1600ff8b, 0x4c832adc, 0x146e2131, 0x261b00ff, 0x1a00ff66, 0x00fff6e8, 0x82713d21, 0x1200252d, + 0x8f8b52f8, 0xc725de82, 0x0d00fff0, 0x221284fd, 0x82b42808, 0xe1072c35, 0x0200ff8a, 0x00ff9ecf, 0x829a1906, 0x5e1a2104, 0x2828e282, 0x00ffec91, + 0x05527828, 0x08209682, 0x56234482, 0x820518c4, 0x833f202b, 0xca1b2621, 0x2b00ff3e, 0x275f82e6, 0xff476123, 0x66662300, 0x21213082, 0x220a8221, + 0x825c0f21, 0x90422619, 0x871000ff, 0x210982ae, 0x79835c4f, 0x06822b20, 0x7a260c82, 0xefffffe2, 0x90825278, 0xff281c26, 0xa4f0deff, 0x07213583, + 0x210a82ae, 0x30823433, 0xff235982, 0x82ccccd4, 0xccd439d1, 0xff0e08ce, 0x9a995001, 0x802301ff, 0xffff1500, 0xff32b3f6, 0x66660800, 0x4c24fa82, + 0x0b00ffce, 0x00231982, 0x82008004, 0x34332109, 0x1e204582, 0x4c200a83, 0x8205b463, 0x0c002146, 0x0f25f683, 0x00ff9819, 0x22098305, 0x8268e60b, + 0xe0ba21f7, 0x15262982, 0xff7e3233, 0x24821300, 0x02f0ff22, 0x3982a683, 0x99edff23, 0x201a829a, 0x24858209, 0x5ccff5ff, 0x05aa6cff, 0x824ff021, + 0x82f42009, 0xf8ff2168, 0xff2ddf83, 0x5e6666bc, 0xf5ffff05, 0xffff34b3, 0x213f83f9, 0x938233f2, 0xcc4c0222, 0xbf829d83, 0x89830820, 0x82feff21, + 0x0100211e, 0x09821982, 0x01201e82, 0x13852883, 0x089a1927, 0xffff068b, 0x231182d9, 0x66e62b00, 0xfb20d482, 0xf5207b83, 0xf3220483, 0x548232b3, + 0xff22d982, 0xde82ccf3, 0x08283f82, 0xe6fbffff, 0x0000ff66, 0xb34af384, 0xb3fb2308, 0x1a838b34, 0x8b33b322, 0xb3252082, 0xffffff33, 0x228082cc, + 0x8267e6fb, 0x82c58309, 0xffcd2340, 0x4582feff, 0x82f3ff21, 0x0600211e, 0x485a3a82, 0x800a2205, 0x27398200, 0xffcdcce0, 0xaec74b00, 0xfb20c982, + 0x0c201f83, 0x24822982, 0x00ff3328, 0xff44960e, 0xef820c00, 0x0f030028, 0x00ff081c, 0x14823313, 0xc62b0422, 0x19260982, 0x0200ff99, 0x0982f833, + 0x2005e648, 0x41068213, 0xfd210644, 0x212a82cc, 0x83834c12, 0x823ad421, 0x830d200a, 0xf0fc23ce, 0x5482ffe4, 0xffff3428, 0xffbc69f1, 0xa283faff, + 0x3233f322, 0xe1217e82, 0x221482b3, 0x825238b4, 0x9950217e, 0x4a265582, 0xff1552f8, 0xe9830b00, 0x20450727, 0x190f00ff, 0x242f829a, 0x00ff0a17, + 0x23748205, 0x0a17f3ff, 0x2406dd41, 0x48e1b3ff, 0x06544905, 0xf284f420, 0xe7824c20, 0x6666f425, 0x82f6ffff, 0xf7ff21c7, 0xfe20fc84, 0xfe205e83, + 0xff214d82, 0x8a1483fe, 0xcecc2109, 0x29857d82, 0xf2203d83, 0xff21dc82, 0x202d83fd, 0x230482f5, 0x66e60600, 0xbc231e82, 0x82b8846b, 0x9cf42698, + 0x0700ff29, 0x22888299, 0x82a430fd, 0x82b02092, 0x23092704, 0x0a00ffd7, 0x8d82a430, 0xae871025, 0x821200ff, 0x13002278, 0x2f28821c, 0xff70fd0f, + 0x34331500, 0x068b0898, 0x330101ff, 0x4726df82, 0xff15ae87, 0x6782fcff, 0x660b002b, 0x0300ff67, 0x00ff6866, 0x20ee830c, 0x26138309, 0x08008006, + 0x824400ff, 0x2d002360, 0xd482cecc, 0x0a830b20, 0x32b30722, 0xba836b82, 0x4382fc20, 0x82050021, 0xf3ff2313, 0x29823233, 0x6b820a20, 0xe6e7ff22, + 0x06204382, 0xff233e82, 0x71ffffe5, 0xe4220632, 0x1e82cdcc, 0x3233012a, 0xccf2ffff, 0xf5ffffcd, 0xff2c3882, 0xff9919f6, 0x34b3f2ff, 0x063b088b, + 0x18820885, 0xff008031, 0x67e60900, 0x99fdffff, 0x0d00ff98, 0x82089919, 0xce4c2144, 0x14829a83, 0xcc4cff22, 0x4c210982, 0x211382cd, 0x09839a19, + 0x8b08cc2b, 0xff95fb07, 0x00801e00, 0x83388215, 0x83f9205b, 0x83032042, 0x82f32089, 0x82dc82d2, 0x99f4212d, 0x33824784, 0xb3fcff23, 0x823d8234, + 0x20098247, 0x82098333, 0x84fc201e, 0x83fd201e, 0x83f220c8, 0x82f5207b, 0x82a38242, 0xb3f2221e, 0x229e8633, 0x828b00c0, 0xb121249e, 0x820a00ff, + 0x01002365, 0x9e82b439, 0x82333321, 0x870231d6, 0x1b00ff6d, 0x00ff3333, 0xff44cb06, 0x01001a00, 0x63262382, 0x1800ffd7, 0x1e829819, 0x3e8a0527, + 0xcc0c00ff, 0x053341ce, 0xcc030027, 0x0b00ffcc, 0x22cc82a6, 0x82ce4cf8, 0x97442b1e, 0xd2ffff0a, 0xff053233, 0x7683edff, 0x9a999f22, 0x0eb28c18, + 0x08766618, 0x18075b21, 0x82090892, 0x83f520b5, 0x21a08fc4, 0x7c820040, 0x8b34b322, 0x4c239c82, 0x82bb08cc, 0x0d002131, 0x00222782, 0x1885c00a, + 0x40281782, 0xdb088b00, 0x8b14f806, 0xcc206784, 0xbe4b2a82, 0x20679405, 0x85f482cc, 0x0da74167, 0x67935384, 0x8434b321, 0x837f8480, 0x14fc2367, + 0xd04014fb, 0x6cfb2ccc, 0xff8b155b, 0x3433f7ff, 0x19f8ffff, 0x830d7928, 0x82332015, 0xccf8221b, 0x0b0164cd, 0x07a4f722, 0x83050b64, 0x84332014, + 0x00ff2619, 0x8bcdcc08, 0x05bd4c08, 0x4c831185, 0x08255785, 0x4b07a4fb, 0x20648a8b, 0x226986cd, 0x193333f7, 0x230d4243, 0x34330700, 0x08225a85, + 0x648584f7, 0x64847984, 0x07cc9618, 0x7b856b85, 0xcd206482, 0x33266484, 0x0784fb08, 0x658b14f7, 0x6588cc20, 0x65853420, 0xe1845a82, 0x34206597, + 0xf1185385, 0xf918132e, 0x658208b2, 0x30fb0e28, 0x54f874f7, 0x6818fb15, 0x561808e6, 0xf7240f52, 0xb4fb0614, 0x2317cc7b, 0xff0694fb, 0x2015bb7b, + 0x285083f8, 0x9a592300, 0xa61c00ff, 0x6bc31866, 0x06342b0c, 0x74fb24fb, 0xe9ffff15, 0xef82f6e8, 0x0a17ee24, 0x5418ffff, 0x3b20097f, 0xe9216b83, + 0x223282e6, 0x84f6e811, 0x00ff2818, 0x8b0a1716, 0x82069b08, 0x9a192708, 0x1100ff8b, 0x048367e6, 0x0a826620, 0x9a191624, 0x5c419308, 0xffcc2105, + 0x0f51ae18, 0x410bf241, 0x83200ac1, 0xff282f82, 0xff9a99fb, 0x6666fcff, 0xfb250486, 0x088b9999, 0x22cc827b, 0x827b94fb, 0x6bfc2693, 0x0300ff85, + 0x246c8399, 0x08666604, 0x203182db, 0x82088200, 0x7b942113, 0xff241884, 0x856b0400, 0x1a7d9319, 0xf7216384, 0x06854133, 0x0aba6d18, 0x410bf041, + 0xc3840abb, 0xf083cc82, 0xdc849920, 0xe9ffff24, 0x938466e6, 0x835f0021, 0x66a92ea6, 0x00ff1566, 0xff676619, 0x0080f1ff, 0x83808205, 0x82fd2015, + 0x02002804, 0xffffcdcc, 0x823433fb, 0xe6fa28b8, 0x838b0866, 0x83f9ffff, 0x280482de, 0xff088b83, 0x6666e6ff, 0x160b4106, 0xa5953282, 0x9a991923, + 0x256e8206, 0xff8b9999, 0x5f821400, 0xcc200482, 0x16820a82, 0x06820820, 0x00801122, 0x19245082, 0x0e00ff9a, 0x90820983, 0x3322d782, 0x6b820834, + 0xbe829920, 0x05201482, 0x83829182, 0x82020021, 0xfdff2304, 0xaf823333, 0x4083cc20, 0x9a190528, 0xff938b08, 0xb8830600, 0x93200482, 0x0021a082, + 0x206c8411, 0x2eb01808, 0x07bb690b, 0x17826c82, 0x2008da41, 0x82c78533, 0x84ee2068, 0x66e622d4, 0x20c28267, 0x205f82eb, 0x820482ff, 0x8210820a, + 0xefff21a0, 0x08255e83, 0xffff66e6, 0x858082f0, 0xccf726a5, 0x00ff08cc, 0x200f8368, 0x05066346, 0xcc205986, 0x50052b43, 0x2841057f, 0x0791430e, + 0xe0ffff25, 0x82076666, 0x4cdd2b60, 0x0a00ffce, 0xff69cc4c, 0x0a821300, 0x46e3ff21, 0x19210548, 0x23a3829a, 0x8e05ce4c, 0x0420f786, 0xfd257b83, + 0x00ffcc4c, 0x050b6005, 0xff220683, 0x16820400, 0xb3020024, 0x0a828e34, 0x82666621, 0x8205208e, 0x07002438, 0x850532b3, 0x1c00234e, 0x5e8468e6, + 0xf882ad20, 0x32b32222, 0x1f202182, 0x9705fd67, 0x070844ab, 0x860a3d44, 0xff742aab, 0x0080faff, 0x66e9ffff, 0x05bc4766, 0xb3ebff24, 0x0a850834, + 0x4c140023, 0x251e85cc, 0x9a991600, 0x6786a28b, 0x84f7733b, 0xfb14f715, 0x14fb0514, 0x0714f706, 0x74f72f0e, 0x990b01ff, 0x00ff159a, 0x33fe8494, + 0x86ab1100, 0xb0f1ffff, 0x0e00ffa4, 0xffff7a54, 0x8b5c4fee, 0x06835282, 0x51181685, 0xfb240a54, 0x06b30724, 0x2305754f, 0xfeffff93, 0xb76f7082, + 0x4cfd2405, 0x842b08ce, 0xf71523ff, 0xe7820704, 0x84ab1122, 0x7c205388, 0x84215395, 0x2117828b, 0x6a827c54, 0x34338f2d, 0x0200ff07, 0x00fff6a8, + 0x82cc4c00, 0x9a992109, 0xe7820982, 0xbd02002a, 0xc3088b71, 0x7b34f706, 0x1122ae82, 0x5982a4b0, 0x5c4f0e22, 0x7c20a883, 0x08216485, 0x206daeeb, + 0x515c182b, 0xebeb2217, 0x88a78515, 0x20a087f4, 0x2132844b, 0x76827b54, 0xff257b82, 0xff85abf1, 0x208b8300, 0x85068508, 0x0e002316, 0x92830a57, + 0x8216ae21, 0xfa3f2216, 0x209684e0, 0x00db18b3, 0xffff2911, 0xff66e6de, 0xcdcc69ff, 0xf3356e82, 0x00ffec91, 0xffe3a507, 0x707df6ff, 0xa90b00ff, + 0xfbffff79, 0x34df820f, 0x08a4f00d, 0xaef5ffff, 0xf9ffff16, 0xffffcd0c, 0x879899f3, 0x05bc49ff, 0xf8ffff25, 0x828be85b, 0x60c52605, 0x800100ff, + 0x26218283, 0x00ffc235, 0x827b7402, 0xc2022778, 0xf7ffff90, 0x0f82ce57, 0xf6226583, 0x29820080, 0x9a19f623, 0x27068208, 0xffe23ad8, 0x00c0dfff, + 0xc52a0482, 0xd8ffff1e, 0x088b0040, 0x2e820643, 0x08de7218, 0x83070021, 0x0800230a, 0x2f8204d6, 0xcc080022, 0x23064443, 0x34330700, 0x2205e344, + 0x4506d308, 0xf98205b9, 0x84f6e821, 0x22f38204, 0x830a1716, 0x2406822f, 0x19eeffff, 0x4416849a, 0xfb2106ea, 0x46608214, 0xff251413, 0x0a97c0ff, + 0x32968207, 0x9bb8dede, 0x91e0ffff, 0x1a00ffec, 0xffff5ccf, 0x82146eec, 0x303530c8, 0xd9ffffa4, 0xff050a57, 0x3433b2ff, 0x8274f707, 0x17552778, + 0x00ff070a, 0x96824c26, 0x0a171826, 0xb31900ff, 0x2a229682, 0x82827c54, 0xe07a302e, 0x4000ff08, 0xff07f6e8, 0x9a99f6ff, 0x21050643, 0x8c82f5ff, + 0x83fcff21, 0x55f4200e, 0xf32205e9, 0x718234b3, 0xd883f420, 0xcdcc0322, 0x66292a82, 0x0e089166, 0x00ff30fb, 0x322a82ba, 0x94e5bf01, 0x96ffff15, + 0xffff66e6, 0xffc0dffc, 0x82ffaeff, 0x60a42200, 0x25338240, 0x089bd996, 0xaf839cfb, 0x00c0f122, 0x4c20e182, 0xf8283d82, 0xff95b8de, 0x48210a00, + 0x182c7a82, 0x00ff33f3, 0x05008012, 0xa00600ff, 0x05392082, 0x00ff4200, 0x8a006009, 0x800500ff, 0xf9ffff00, 0xb608bebf, 0xb0cfffff, 0x202183a4, + 0x20118440, 0x213c82c0, 0xbd82b81e, 0x0f820620, 0x40060023, 0x27478240, 0xffb89e28, 0x5ccf2d00, 0x60202583, 0x07214782, 0x21478240, 0x25843e0b, + 0xff486124, 0x4782f8ff, 0x2800ff23, 0x210a82a1, 0x4b8e30d2, 0x83482121, 0x703d214b, 0x4b828282, 0x00ffb624, 0x47834f30, 0x5d827f83, 0x09234782, + 0x828c4861, 0x2362821c, 0xbefffaff, 0x3423b584, 0x82edffff, 0xff9524b5, 0x82def5ff, 0x4c112779, 0x0700ffcc, 0x4882c420, 0x400e2108, 0x01ff0884, + 0x07d00010, 0x020000ff, 0x6c00ff90, 0xffff1e05, 0xff66e6a6, 0x84205700, 0x3393ffff, 0xfc263b82, 0xff08f2bf, 0x1482c5ff, 0x1a20ff2e, 0xffff156c, + 0x8b4761ee, 0x85f2ffff, 0x8205bc74, 0xa1112346, 0x06840848, 0x00ff4623, 0x85c1820e, 0xb8102304, 0x7f828b52, 0xff240683, 0xae470f00, 0x08e27818, + 0x82ba5e21, 0xeeff232d, 0x1182b85e, 0x849a9921, 0x26548216, 0x088b6666, 0x848b14f7, 0x21e4825f, 0xc282f1ff, 0x95060d73, 0x6c11205f, 0x5f99172c, + 0xffaf0e2b, 0x98193802, 0xb3fb00ff, 0x20688233, 0x37ab83e9, 0x05b99e16, 0x77fbffff, 0x0400ff8c, 0xffff7288, 0xff18f9f9, 0xfa7e0200, 0x97210982, + 0x21c0820c, 0x0682f9ff, 0xf8260c82, 0xfdffff50, 0x2a820681, 0x82527821, 0x8e772704, 0xfaffff08, 0x04839458, 0x40821020, 0x48e1eb28, 0x1e1400ff, + 0x468205b8, 0xff949834, 0xc2751700, 0xc0f8ffff, 0x1800ff82, 0xffffa470, 0x75822eef, 0x7ad41022, 0xd2273482, 0x00ff00c0, 0x8200402d, 0x27e13234, + 0x1f00ff6c, 0xffff1ac4, 0xff66e6d4, 0x52781100, 0x3271835f, 0x8b9a19d3, 0xccd5ffff, 0xeeffffcc, 0xffffae87, 0x82cd4ce0, 0x90422104, 0xf8223c82, + 0x56823333, 0x05f62828, 0xcfffffeb, 0x438232f3, 0xa430f223, 0x082d8207, 0xce0ced21, 0xb00700ff, 0xedffff20, 0x00ff3273, 0xffea660d, 0x0a97f2ff, + 0x3100ff08, 0xfffff628, 0x822adcce, 0x830d2099, 0x8cf2228a, 0x216a82cd, 0x478234f3, 0xff0a9726, 0x66261300, 0x00247382, 0x8b0cc204, 0xc126ba82, + 0x0000ff06, 0x0982fd76, 0x8202ab21, 0x15ec2209, 0x24d58408, 0xe1ebffff, 0x866c8247, 0x829420f0, 0xa4f6240a, 0x82ffff9c, 0x277b8204, 0xffeac6f0, + 0xe05a0900, 0xa3210f82, 0x273082d6, 0xffb89e16, 0x4861e9ff, 0x04217182, 0x2c7c8288, 0xff8e77fb, 0x66060600, 0x80fdffff, 0x21098282, 0x7183f668, + 0x06820620, 0x07260c82, 0x0200ffae, 0x71827c7f, 0x0023ea82, 0x82748804, 0x835a2040, 0x805a220a, 0x22408200, 0x82a84609, 0x8d77215b, 0x0f209c82, + 0xf522fb83, 0x0f82cccc, 0x08cd4c32, 0xccd6feff, 0x0300ffce, 0xff1567e6, 0x6c27fcff, 0xd8210a82, 0x21098292, 0x4a8226a6, 0x825c4421, 0xb6d32109, + 0x602c0982, 0xffff0884, 0xff008010, 0xcccc2eff, 0xe324b682, 0xffff48e1, 0xff2c0484, 0xffffc3f5, 0xff6666d2, 0x761f1c00, 0xeb211382, 0x32798286, + 0xff8a200e, 0xf4e8f1ff, 0x701200ff, 0x00ff84a4, 0x833d8a11, 0x8a1122ab, 0x2c80823e, 0xffcd4c13, 0xf0070700, 0x110e00ff, 0x210482eb, 0x31821a0f, + 0x9919d127, 0x66ef00ff, 0x225b8266, 0x82e8dbfb, 0x9e0f2685, 0xf4fbffff, 0x210982fe, 0x85825e3a, 0x82424b21, 0xfeb42109, 0xcf348582, 0x00ff16ae, + 0x05301d31, 0x00ffef0e, 0xff9a19e7, 0x9a192001, 0x8022bc83, 0xcf4a8b00, 0x4cfc2206, 0x2a0a82cc, 0x089a99fb, 0xab070cfb, 0x4a0cf706, 0xff2107c1, + 0x22a883fc, 0x829a9903, 0x9a99215b, 0xff219282, 0x264082ef, 0x9a190000, 0xc18b4b05, 0x00ff2743, 0xff66e6e0, 0x9952ffff, 0x4b608205, 0x8f920964, + 0x82006021, 0x2204821e, 0x83af0300, 0x00a024eb, 0x827b088b, 0x62f0233c, 0x8b83cb05, 0x4b053765, 0x3fac07a4, 0x1583e326, 0x0400ff8b, 0xfe836099, + 0x52829820, 0x6866fc22, 0x5d8ea284, 0x47feff27, 0x00ff9a19, 0x05574108, 0x821f8521, 0x61fc221e, 0x41298247, 0x99202457, 0x2a055741, 0x0000ff99, + 0xff059a19, 0x82e60802, 0x05134164, 0x2005e028, 0xf7ffff06, 0x5182bc29, 0x94cef827, 0xd1f8ffff, 0x230a8268, 0x087829f7, 0x24053a45, 0x200590ff, + 0xcd7a1805, 0x0754211a, 0x0822d882, 0x398246d6, 0xff58d926, 0x4a2c0700, 0x38204e83, 0xdf227183, 0x5b820a17, 0xb883f820, 0xd6e30022, 0xcc212082, + 0x211b82cc, 0xe44b66e6, 0xfb082205, 0xd57a1854, 0x247c821a, 0x04f7aa01, 0x21078205, 0xf882e600, 0xf8203a83, 0x09de7a18, 0x84852b21, 0xe1fa2160, + 0xba20bc84, 0xf8205182, 0xcc218284, 0x205c87cc, 0x20978204, 0xe27a18ff, 0xffff2418, 0x829a198f, 0x66e6213b, 0xea248d83, 0xffff0080, 0x3b820482, + 0x08201082, 0xf6220682, 0x044fce4c, 0x82cc2008, 0x67e62909, 0xf4f7088b, 0x0900ff06, 0x00216183, 0x82d38307, 0x21fa8304, 0x308266e6, 0x1493a718, + 0x1fe57a18, 0x0021a283, 0x48d98408, 0x342105ae, 0x07f34bff, 0x9819ef2d, 0x192000ff, 0x00ff159a, 0x829c190e, 0x830a2066, 0xe60b2121, 0x0023ad82, + 0x839a990e, 0xc70e3371, 0x00ff73ae, 0x8bb89e26, 0x8b8b088b, 0xd9ffff73, 0xb9824861, 0x703df122, 0xff231d82, 0x514861f1, 0x7e73055b, 0x660c2705, + 0xfc088b64, 0x4f838bd4, 0x44832620, 0x00c00a24, 0x4fa400ff, 0x84523821, 0x6666214f, 0x34824f82, 0x592a4f86, 0xf7088b9a, 0x2f00ffb4, 0x5382c2f5, + 0x00400d22, 0x5384a383, 0x82a4f021, 0xa10e220a, 0x06757948, 0xc00e0023, 0x22a79a00, 0x86ae47f2, 0x28f333a7, 0x0c00fff6, 0x088b6666, 0xe630ffff, + 0xcfffff66, 0x5a8ba4f0, 0x56839720, 0x84b89e21, 0x90c221fa, 0xaa855294, 0xcc4cf222, 0xf322aa86, 0xc3529a19, 0x83cb2006, 0xaea588f9, 0xcdcc234a, + 0x4a85ffff, 0x8b333323, 0x214aca08, 0x96af34f7, 0x4105dc41, 0xcc210534, 0x209688cc, 0xe496b234, 0x0e24084a, 0x15d35cf7, 0xc5ceffff, 0x1000ff1f, + 0xff05f668, 0x04b6f8ff, 0x6f0200ff, 0x00ff8b1a, 0xffe6500a, 0xfc490700, 0x6e270f82, 0x00ff0814, 0x86e13a31, 0x832b8325, 0x05e2210f, 0x6f211b82, + 0x2225861b, 0x82e5500a, 0x6e022235, 0x82458414, 0x83518230, 0x821e205b, 0x3a312725, 0xefffffe2, 0x0a820a97, 0xff295183, 0x8be690fd, 0xaff5ffff, + 0x252b841a, 0x91fdffff, 0x2b8408ec, 0x832f2585, 0x64f70563, 0xa9ffff06, 0x00ffb89e, 0x829a99c9, 0xc7f92a98, 0x0e00ffae, 0xffff6666, 0x240482ff, + 0x34331000, 0x210f8290, 0x678266e6, 0x34333827, 0xe6a800ff, 0x20258266, 0x231b8244, 0x34b394ff, 0xe82f0a82, 0xffff6766, 0xff0080f2, 0xcd4cecff, + 0x83ebffff, 0xe6f53119, 0xfb087266, 0x06ffff03, 0xf7056666, 0xb3830624, 0x1f309082, 0x00ff3333, 0x159a99cb, 0xcc1800ff, 0x0c00ffcd, 0x05821b82, + 0x82866b21, 0x83d7200f, 0x7a0122b1, 0x26e7821c, 0x00fff2f2, 0x82f83304, 0x790122e2, 0x21b182dc, 0x7a820e0d, 0x8a6c0c27, 0x28e7ffff, 0x274682f6, + 0xff0ad718, 0x7c94f3ff, 0x02200a82, 0xff232b82, 0x82e285fe, 0xccfb21e2, 0xfd281582, 0xffff0e0d, 0x082486fe, 0x25822b84, 0x05749322, 0x94210582, + 0x820f847a, 0x85fe220a, 0x245184e4, 0xccfbffff, 0x82358208, 0x8271842b, 0x93f32230, 0x21878676, 0xa883e7ff, 0x88209d83, 0x23072f69, 0x8e343304, + 0x082d0b84, 0xcc0801ff, 0xecfeffcc, 0xfc156666, 0x0c794d74, 0x820aca52, 0x80e52a59, 0x1500ff00, 0xffff717d, 0x2c0983ea, 0x8b8f821a, 0x0634f808, + 0x821a00ff, 0x22da8290, 0x83707d15, 0x8270201e, 0x4d10820a, 0x3a5407aa, 0x06004508, 0x30fb0e27, 0xf4f784f7, 0x21358215, 0x2a820080, 0x54841520, + 0x82088278, 0x821a2011, 0x83618511, 0x82ff201b, 0x088b2175, 0x166fa218, 0x32889488, 0x2d833c82, 0x90026027, 0xe640ffff, 0x22668266, 0x825c4f07, + 0xa8062754, 0x0400fff6, 0xf18212c3, 0xff67e637, 0x16190700, 0x2900ff08, 0x00ffb81e, 0x05723d9e, 0x580000ff, 0x211a82c8, 0x0982804a, 0x826b2a21, + 0x834c2009, 0x470122bf, 0x2b06832a, 0xffd20207, 0x9503fbff, 0x6d0600ff, 0xf8220982, 0x20829498, 0x82a4b021, 0x47f92294, 0x260a820a, 0xffffbe9f, + 0x82cc4cf9, 0xaec7213a, 0xe7440982, 0x59db2205, 0x319d8299, 0xff66a6de, 0xf628e8ff, 0xaef6ffff, 0xdcffff14, 0x35825c4f, 0x5ebbe62e, 0xd49dffff, + 0xffff057b, 0xffd6a6ff, 0x2205fa59, 0x837ad5ff, 0x82342009, 0xb3fe2234, 0x23768232, 0x3cfff8ff, 0xf621b282, 0x21528204, 0xb2823e95, 0x82256621, + 0x5e4f2c20, 0x3f00ff08, 0xffff0ba7, 0x825ccff0, 0x570122b7, 0x2145820a, 0x868234b3, 0x660b5721, 0x012f062c, 0x088bec51, 0xfd1f01ff, 0x7f00ff70, + 0x82159a19, 0x66e6272b, 0xf7ffff06, 0x5d820020, 0x82c6f921, 0xe0f82192, 0x10820a83, 0x077b0827, 0x40ddffff, 0x271e8200, 0xff0040d1, 0x00c02e00, + 0xf3269682, 0x00ff9a19, 0x2882260b, 0x8233f121, 0x8206205a, 0xf0ff260e, 0x088bcc4c, 0x25408270, 0xff9a99e8, 0x7282edff, 0x66f9ff22, 0xe5262182, + 0xff08cccc, 0x2283e5ff, 0x34339422, 0xff203c82, 0xfd221583, 0x97820080, 0xfd202983, 0xff243782, 0x6666fdff, 0xf727d383, 0x00ffccac, 0x82d74303, + 0x90e2268c, 0x160600ff, 0x21dd82c9, 0xd382f6e8, 0xb89e5627, 0x5ea9ffff, 0x234082b8, 0x079042ad, 0x0c824018, 0x1b82f120, 0x40180020, 0x0f200c05, + 0x0d2f4318, 0x5200ff24, 0x338200c0, 0x1e110022, 0xf9214582, 0x26c88260, 0xff900210, 0x82e0f3ff, 0x1e0c2209, 0x22a082b8, 0x824821d1, 0x48e126dd, + 0x0000ff05, 0x20158240, 0x86a08200, 0x212e8309, 0x13852000, 0x22076173, 0x8200804f, 0x5e162129, 0xe9214e82, 0x2b94829e, 0xdad90700, 0x06faffff, + 0x0800ff66, 0xe561ea83, 0x192f250b, 0x84fb069a, 0x8209b36e, 0x05696f4a, 0x9af90723, 0x2050828b, 0x261f820f, 0x990b00ff, 0x48ff8b98, 0xf7210f5e, + 0x263682d4, 0x66e60800, 0x82f8ffff, 0x221e8404, 0x8319f7ff, 0xe1fe2136, 0xfe2cc182, 0x1534b3c7, 0x53ffffff, 0xfdfffff8, 0xff228c83, 0x0982d3ad, + 0x8bee5c22, 0x68220582, 0x43180832, 0x092d07a8, 0xff7ebfbf, 0xb27d0e00, 0x66fcffff, 0x22738266, 0x829ca402, 0x82402036, 0x990222d4, 0x2409829a, + 0x00ffcccc, 0x05946202, 0xb95e0e22, 0x0d218882, 0x211b8200, 0x0482c009, 0xe2ba0227, 0x800e00ff, 0x27358200, 0xf0004019, 0xcbffff05, 0x34223783, + 0x0a8200c0, 0xf568de37, 0xb375ffff, 0xef0e0534, 0x01ff2bf8, 0x1552f890, 0x660900ff, 0x82048266, 0x0f00218e, 0x26057858, 0xffff0080, 0x8248a1f6, + 0x19122141, 0xee266d82, 0xff05ecd1, 0xd0830100, 0xd6230022, 0x11210987, 0x830982ec, 0x06ab24da, 0x820c00ff, 0x061d4808, 0xa4b0fd22, 0xb3264d82, + 0xfbffff30, 0x42827ad4, 0x68660f27, 0x730f00ff, 0x20428234, 0x200a8309, 0x20688509, 0x20b48230, 0x22688908, 0x8434330a, 0xff8b2373, 0xdc82f0ff, + 0x83f5ff21, 0x27838404, 0x68e6f3ff, 0x11f3ffff, 0x07228383, 0x0a829899, 0x00211a82, 0x223a8303, 0x830080f1, 0x9a99222f, 0x83068208, 0x08002631, + 0xffffd04c, 0x5c6684f7, 0x3220050c, 0x1b2d8182, 0xffff64e6, 0xff9a99f2, 0x00801200, 0x222a826f, 0x830080df, 0x82e52031, 0xf4ff2148, 0xe8253183, + 0xffffcecc, 0x25b383eb, 0x086666f1, 0x9a4a076b, 0xffff2305, 0x0e5ab3f9, 0x4cf62b07, 0x6b088bcc, 0xf8ffff06, 0x1d839c19, 0x84575282, 0x079b280a, + 0x00c0ffff, 0x8a7b0602, 0x82322039, 0x21c4842b, 0x3987ce4c, 0x39849a20, 0x455a6620, 0x00ff240b, 0x829a9911, 0x19f5213d, 0x022b9e82, 0xffff6666, + 0xff9819f5, 0x83e60500, 0x25958209, 0x9a190600, 0xe846ff08, 0x82012005, 0xfeff2123, 0x0121c783, 0x865d8233, 0x08342509, 0x0e00ff7a, 0xff211582, + 0x293e82f4, 0x32b31500, 0x1800ff8b, 0xb1453433, 0x83cd2005, 0x4b3220c4, 0xf6200621, 0x96828a83, 0x88871920, 0x820afa55, 0x4cd3259a, 0x1b00ffcc, + 0xd9286483, 0x00ff0080, 0x7966e624, 0xf5227a82, 0xd5833433, 0x1c83ee20, 0x77830f20, 0x34b3f126, 0xcc1000ff, 0xab21d582, 0x05b45406, 0xff211a82, + 0x838183f2, 0xedff2b1a, 0x088b6666, 0xffff064b, 0x8a8233ef, 0x83f0ff21, 0x09fa66c5, 0xec82d720, 0xf356ed20, 0xffcc2305, 0x5e60eaff, 0xff342705, + 0x0080e8ff, 0x1082088b, 0x82cc4c21, 0x66ea2289, 0x06047f67, 0xcd4ceb22, 0xb323bc82, 0x873f0834, 0x22698284, 0x86ffff99, 0x83672069, 0xffbf2833, + 0xffff06ff, 0x82e13aef, 0xc5f02439, 0x8900ff1e, 0x00ff246d, 0x8266e676, 0xd4ee3071, 0xd7ffff7b, 0xff056666, 0xb89efaff, 0x82f3ffff, 0xf1ff2394, + 0x0e825ccf, 0xf328b783, 0x00ffd7e3, 0x08666605, 0xe3211982, 0x820a8454, 0x858b2119, 0xaa824a82, 0x62050031, 0x0c00ff4e, 0xff089a19, 0x73081500, + 0x833100ff, 0x06002248, 0x251f822b, 0xff66e60b, 0x5d820100, 0xcc0c002f, 0x08988bcc, 0x6b00ff8b, 0x00ff0080, 0x25378356, 0xff16ae57, 0x60826a00, + 0xe3030023, 0x205b82d6, 0x2ecc83ff, 0x05482100, 0xe64000ff, 0x00ff0666, 0x8234b329, 0xb3292230, 0x24778232, 0x00ff14ee, 0x22968321, 0x820a57f2, + 0x82012068, 0x20588214, 0x825d827c, 0x01002214, 0x225482c0, 0x82cccc01, 0x84ab210e, 0xfc204a82, 0x03226483, 0xd0829082, 0x34b3f627, 0x5e0900ff, + 0x214982b8, 0x0a83330f, 0x25824c20, 0x08210f82, 0x2061828b, 0x24878230, 0xae075fff, 0x2c618215, 0xff8b9a99, 0x6666f4ff, 0x4cf5ffff, 0x220a82cd, + 0x8233b3f2, 0x82ff20af, 0x00ff2206, 0x83a5820b, 0x22e78216, 0x828b6666, 0x330e227f, 0x20508232, 0x187b8309, 0x2411d47d, 0xff3233f6, 0x24168200, + 0xccf1ffff, 0x282d83ce, 0x5bfeff6f, 0x0e00ff15, 0x20cf8333, 0x93a68309, 0x869c8234, 0x82cc2034, 0xf3ff2334, 0x90849c99, 0x90956420, 0x16849c20, + 0x64209083, 0x98242d83, 0x14f70200, 0xf820c682, 0x4e0bbd42, 0xb0430744, 0x05cc4506, 0x7f83f820, 0x84e60721, 0xb30921c6, 0x0620c683, 0x8305244e, + 0xbc41189c, 0xb3f9210b, 0x0724c682, 0xffff3433, 0x24051943, 0xfeff3f00, 0x21c6826b, 0x2983b309, 0xcc4c0622, 0x13f14118, 0x82b3f921, 0x843486c6, + 0x071144c6, 0x49ff6621, 0xf7200d5f, 0x908c5882, 0x088b6430, 0x02ffaf0e, 0xff68e63f, 0xd8637301, 0x99688b15, 0xf3fc2106, 0xb7385183, 0xfaffff0a, + 0x08910080, 0x20fcffff, 0xffff8f00, 0xffb047fb, 0x00200500, 0xe0211682, 0x2b098200, 0xff080060, 0xb81e0b00, 0xc00600ff, 0x082a0f82, 0x00ff9859, + 0xff8ec20a, 0x0e830200, 0xb81e0d22, 0x00271e82, 0xff90f8ff, 0x8226fcff, 0xa4042239, 0x2039841a, 0x2350828b, 0xff220688, 0xbe2c0082, 0xb9ffff05, + 0xff8b4861, 0x52b8c6ff, 0xc0210482, 0x210a8200, 0x578240b9, 0x195fff24, 0x1d828b9a, 0x8321e321, 0x7de6261d, 0xf3ffff70, 0x27d082e6, 0xff4861ee, + 0xe2faeaff, 0x3f824382, 0x0100ff24, 0x2582b81e, 0x6666d022, 0xd8243882, 0xffff0680, 0x09e26b18, 0xf9211f83, 0x0aa07653, 0xf92ab882, 0x00ff66c6, + 0x8b9af907, 0x1e829b08, 0x059a1922, 0xdf21f182, 0x22f782be, 0x76db3906, 0x00230d46, 0x82c32100, 0x0d00223b, 0x22da8240, 0x484ee206, 0x002305af, + 0x8242e009, 0x21a18427, 0x5082e0ff, 0x26058748, 0xfffff45d, 0x82db79fd, 0x60fd2383, 0x06820800, 0xa682e420, 0xde0b002c, 0xe7ffffb8, 0x00ffff3f, + 0xb582a112, 0x8380ee21, 0x59e627d7, 0xbbffff99, 0xb582d863, 0xfc69fb22, 0xf883d582, 0x2546ff22, 0x22061046, 0x821b2f03, 0xae472c13, 0x1500ff08, + 0xffffe1ba, 0x822a1ca9, 0x5d0533a3, 0xf1ffff92, 0x00ffdcc4, 0x81afc70c, 0xb30e00ff, 0x21828b33, 0xe1fa2028, 0x1400ff06, 0xc0825ccf, 0x1f450f2c, + 0x8c1300ff, 0xfaffffcc, 0x148252f8, 0x08a4302b, 0xabeaffff, 0x5500ff85, 0x2642835c, 0xffaec717, 0x839c3f00, 0x1985210a, 0xe922fc82, 0x5882f6a8, + 0x1e050027, 0xa179ffff, 0x23e98246, 0x7a54eeff, 0x27060a5b, 0xff86abf1, 0x20c51000, 0xc77f6383, 0xab112205, 0x22638286, 0x84146e0d, 0x820a8221, + 0x27808210, 0xff400400, 0xcccca100, 0x17224982, 0xb2828c48, 0xff9a192b, 0x66660b00, 0x991a00ff, 0x2025829a, 0x82f2821e, 0x40002c06, 0xffffff00, + 0x00ffc2e5, 0x85ff2100, 0x233c820f, 0x079b7766, 0xe7266682, 0xf8ffff0a, 0x428266e6, 0x34f31227, 0x47daffff, 0x220a82ae, 0x82227b07, 0xd72335f0, + 0x991100ff, 0xf9ffff58, 0x00ff5c4f, 0xffa4700f, 0xc3350600, 0x20263a82, 0x00ff3c8a, 0x77830c0d, 0x48210c2c, 0xe00400ff, 0x0700ffc6, 0x7c82e0fa, + 0x82c0ca21, 0xe4fa216a, 0x11221e82, 0x0a8208ec, 0xff68e624, 0xeb834d00, 0xffbfff2f, 0xecfffffe, 0xff15289c, 0x0040f7ff, 0x2055828b, 0x21a882a6, + 0x0a822007, 0xe0080024, 0x98820800, 0x62820682, 0x82ce4c21, 0x0020214c, 0x4209f36d, 0xdc200621, 0xd74aa882, 0x203f8208, 0x232382f7, 0xccccf9ff, + 0x54821684, 0x439a1921, 0x1282064f, 0x80c00027, 0x798b1500, 0x2ac5827c, 0x8b7a66e6, 0xff066b08, 0x82b30000, 0x845f20df, 0x19002aea, 0xdcffff98, + 0xffff0080, 0x226d82e3, 0x8233e3ff, 0x54dc2019, 0x852d05c4, 0xff0666e6, 0x9a99d9ff, 0x00ff05cb, 0x214a8350, 0xe8834c43, 0x82cc0721, 0x99062296, + 0x22d3839a, 0x84839766, 0xff082ea7, 0x9a198aff, 0x995c00ff, 0xffff0598, 0x284f82f0, 0x01800b00, 0xb3edffff, 0x22048233, 0x82969999, 0x66e62614, + 0x3c00ff08, 0x22108233, 0x823433ad, 0x82aa2025, 0xb8ff2d25, 0x8505cccc, 0xe6faffff, 0xfdffff68, 0xf8235383, 0x82903233, 0xce4c21c7, 0x1f212c82, + 0x20d2824c, 0x242182cb, 0xb399ffff, 0x09166134, 0xff0a5722, 0x0cdfca19, 0x6666a028, 0xdfffff07, 0x2282c3f5, 0x52f8ed23, 0x08eb828b, 0xffe1fa24, + 0x9a190e00, 0x8b089d8b, 0x0300ff94, 0xff930601, 0x89010700, 0x01ff0892, 0xffd66300, 0xe87bdf00, 0x12829205, 0x82940321, 0x00012818, 0x088b9284, + 0x82938b92, 0xfafe2183, 0xca82d082, 0xfdfaff27, 0x00ff0870, 0x2fa4836a, 0x056250a2, 0xb32400ff, 0xff8b0734, 0x84ab1100, 0x99825a82, 0x540e0023, + 0x240e827c, 0x088b34b3, 0xd77718ab, 0xf1ff230c, 0x5b5d84ab, 0x0dfb2606, 0x3400ff07, 0x24c682cc, 0x050080d1, 0x33398293, 0x839c1904, 0xe6feffff, + 0x8b088264, 0xfb0e058b, 0x7300ff30, 0x012c6e82, 0x1566e647, 0x19f3ffff, 0xf4ffff99, 0xff280f82, 0xff9ad9eb, 0x34330200, 0xf5210e82, 0x227082c2, + 0x860832b3, 0xe60c220a, 0x26198266, 0x00ff713d, 0x18682614, 0x21078646, 0xac823c0a, 0x15ee0527, 0xbd0400ff, 0x30ac8272, 0xff8fc21b, 0xa2301600, + 0x662200ff, 0x0c00ff67, 0x23aa8214, 0x8b008023, 0x2b222582, 0xae826666, 0x66663e22, 0x3227cc82, 0xffff9a99, 0x82f668cd, 0x7dc223ae, 0x06820870, + 0xf083f420, 0x0483fe20, 0x0483f520, 0x8183fd20, 0x9a19f622, 0x14223782, 0xe68ecc4c, 0xff24fa82, 0xcc4ceeff, 0xee223783, 0x7b48cd4c, 0xb3f12206, + 0x82158433, 0xbcff246b, 0x82063433, 0xcc4c21ed, 0xb6820482, 0x4cfeff24, 0x0a828acc, 0x8ace4c23, 0x26778208, 0xffff6666, 0x829a19e3, 0x807b22ae, + 0x185b9c00, 0x26133a59, 0x069a191b, 0x83f8ffff, 0x66f72856, 0xffff8766, 0x859a19f5, 0x208f83c0, 0x211782e4, 0x04821500, 0x19eaff28, 0x1a00ff9a, + 0x8f823433, 0x842c0021, 0xe61422c3, 0x20fb8267, 0x217e8214, 0x1c830700, 0x67661025, 0x840d00ff, 0x820520e4, 0x04002331, 0x9382cccc, 0xae540d20, + 0x00ff2206, 0x21248214, 0x1983fcff, 0x34330a2b, 0x33f2ffff, 0x00ff0834, 0x830f820b, 0xffff220a, 0x212882fd, 0x0e83ebff, 0xce4cf122, 0xcc328682, + 0xff8608cc, 0x6666faff, 0xe4ffff05, 0xffff3233, 0x1682cce9, 0x9a99dd23, 0x053a46ff, 0x0080dc22, 0xff238b82, 0x8234b3d3, 0x7dc222bf, 0x26b48270, + 0xfff668cd, 0x82993200, 0x3e0023bf, 0xbf826666, 0x820a0021, 0x0100242e, 0x7dff717d, 0x022b050e, 0x00ff0ad7, 0x0866e609, 0x19ebffff, 0x8219ae18, + 0xb31123d5, 0xb218ff34, 0xff2a0f5d, 0xecd14300, 0x0100ff06, 0x048215ae, 0x0024cc82, 0x8c33b301, 0xb3230a82, 0x84088c34, 0x00ff2377, 0xae83e61c, + 0x00808423, 0x5d5a1806, 0x84cd200e, 0x83332054, 0x225b9593, 0x8266e6e4, 0x3306215b, 0x08207782, 0x0422b483, 0xb48266e6, 0x8266e621, 0x850c2037, + 0x821a20cb, 0x0586411b, 0x1b821520, 0x3082ff20, 0xd422ff83, 0x6b829a99, 0x9919eb22, 0xeb20ff82, 0xca413882, 0x99ef2505, 0xf2ffff99, 0xf934e884, + 0xffff3333, 0x059a19fc, 0xb4f7af0e, 0xff1514f8, 0x1f8507ff, 0xd8252c82, 0xffffe17a, 0x35608389, 0x9a99a4ff, 0xff218b08, 0xcdcc4e00, 0x80bbffff, + 0x6100ff00, 0x5c823333, 0x541b0023, 0x317f827b, 0xff47e117, 0x18840600, 0xe60e00ff, 0x1e00ff67, 0xee822646, 0x15ee1328, 0x802800ff, 0x1a820500, + 0xff8e422b, 0x281c0c00, 0xcc0900ff, 0x820e82ce, 0x090021a7, 0x0023a282, 0x82cc4c00, 0x220a8329, 0x82a1ffff, 0x231e8355, 0xbedef9ff, 0x45262382, + 0xf3ffff1e, 0x4884fade, 0xffff1423, 0x204884d7, 0x2b34820e, 0xe2bae1ff, 0xe61700ff, 0xf9ffff68, 0x1b228983, 0x8983cc4c, 0x34336122, 0x4e278982, + 0x00ffcccc, 0x82908244, 0xfd69230a, 0x06820870, 0x66665b25, 0x83d8ffff, 0x19762228, 0x27da829a, 0x088b0080, 0x94fb14fb, 0xdc22e682, 0xe68266a6, + 0x9959e325, 0x831c00ff, 0x2300220a, 0x20e68259, 0x07fa65ff, 0x1682c982, 0x60830e84, 0x4e821c82, 0xff231183, 0x829a59e3, 0x823e8238, 0x82ff2060, + 0xffff2406, 0x82cd4ce3, 0x82592004, 0xb3dc2760, 0xf7088b33, 0x5f8a8b94, 0x82054866, 0x665f8d3c, 0x66850c5a, 0x48848884, 0xcc205f90, 0x342d5f88, + 0xff0e088b, 0x3433f701, 0x333600ff, 0x37678234, 0xff66e620, 0xcc8c5d01, 0xf5ffff05, 0x00ff7a94, 0xff7a5410, 0xa5b0e4ff, 0xf5324382, 0xffff7b94, + 0x0886abef, 0xdb20ffff, 0xa2feff64, 0x25823473, 0xe3f42108, 0xeeffffd7, 0xffff0a97, 0xff295cff, 0x72fde9ff, 0x150a00ff, 0xedffff81, 0xff0850f8, + 0xd3ed0900, 0x26203482, 0x12219f82, 0x21d182d9, 0xc08219f4, 0xd763142f, 0x01ff088b, 0x0666668f, 0x631400ff, 0x83cd82d6, 0x0b00231c, 0x3082ae07, + 0xffa4f026, 0x70bd1100, 0x0a253b82, 0x00ff9202, 0x29148212, 0x6466ffff, 0xf4ffffa1, 0x1a8268e6, 0x82686621, 0xcc082980, 0x15aef7cc, 0xcc4700ff, + 0x8f21cb82, 0x25ae83cc, 0x063433b8, 0x91824b5b, 0x3333e128, 0xb33400ff, 0x63420533, 0x7b002a05, 0x0e050180, 0xf824f8ef, 0x0cd85354, 0x0a457818, + 0x53072b21, 0x801806ac, 0x5b250fa2, 0xf7076b06, 0x0fe64494, 0x14c2e918, 0x34b3f122, 0x20064245, 0x2034822b, 0x183382bb, 0x5909b962, 0xe52306e4, + 0x98080080, 0x34fb216a, 0x0cfd9418, 0x0af94c18, 0x9d82eb20, 0x4c820020, 0x1383ff20, 0x0e820486, 0xbb088b27, 0xfb07ab06, 0x216dba94, 0xf782717d, + 0x8f82ea22, 0x8b215484, 0x206483ff, 0x216d8a08, 0x1884717d, 0x82211782, 0x206d858f, 0x0f69442b, 0x3582cc20, 0x34b31122, 0x18056944, 0x21110ab7, + 0xa28294f7, 0xd89d5b20, 0xea188220, 0xf7341127, 0x24fb0634, 0x074b154b, 0xcb0614f7, 0x0614fb07, 0x1514fc6b, 0x12840884, 0xcb54f722, 0x0e271b8a, + 0xf774f7ef, 0x18ff15b4, 0x63116ec1, 0x13690a94, 0x16076826, 0xab14fb28, 0xf7ffff15, 0x1f82f628, 0x0ad7f822, 0x22131a4d, 0x84f62807, 0x23868216, + 0x088b0ad7, 0xd0770685, 0x11226405, 0x01288d90, 0xff66667a, 0x48e13f00, 0xf8206682, 0x01280a83, 0xffffcc0c, 0x853433f9, 0x57227183, 0x0682080a, + 0x800afa36, 0x300400ff, 0xfbffff20, 0x00ffe6db, 0xff92cd05, 0x72bdfdff, 0x2c2b6a82, 0xffff8235, 0xff48a1f5, 0x82cc1d00, 0x75c32836, 0x086b8bc2, + 0x820704fb, 0x27f72234, 0x219682f0, 0x048610d8, 0x9b820e82, 0x0683ff20, 0xf6511185, 0x82e7200a, 0x0e00322f, 0xffffb8de, 0xff9a59f0, 0x86ab0900, + 0xb5f2ffff, 0x318682c2, 0xff089959, 0x3e0ae3ff, 0x85f1ffff, 0xedffff1f, 0x0e824621, 0x82707d21, 0xec51267e, 0x1ce0ffff, 0x2a1e832a, 0xffff6826, + 0xffd663ef, 0x824cecff, 0x4ce12283, 0x2c7d82ce, 0x08cc4cdc, 0x34fb076b, 0x1100ff06, 0x46ca82ab, 0x542206e4, 0x10838b7a, 0xd5828620, 0x22064867, + 0x67ff85ab, 0x54210648, 0x23a0837b, 0x066666a4, 0x8a216d82, 0x2244823d, 0x820a17f3, 0x16992c8d, 0x4afcffff, 0x0d00ff3d, 0x8208d6f8, 0x3e8a2b0a, + 0xee0c00ff, 0xfeffff14, 0x3b82d723, 0x82666621, 0x050e4852, 0x9a99012d, 0x0500ff07, 0xffff9a19, 0x829919ff, 0x34332109, 0x2005436f, 0x06826800, + 0xaec70a22, 0x0a202c82, 0x02227383, 0x5b826230, 0xfff6e832, 0x3c3f0400, 0x1000ff08, 0x00ffa4f0, 0x05954307, 0xfa260a82, 0xf8ffffe1, 0x0a82a0ba, + 0x85eb0928, 0xc5fbffff, 0x447aff60, 0xccfd2205, 0x200983cd, 0x23a88233, 0x0e2d0700, 0x06314b82, 0x00ff1bef, 0xff7eed00, 0x52b80600, 0x7f0100ff, + 0x324b8290, 0xffeb910c, 0xf292d9ff, 0xb32300ff, 0x00ff6f33, 0x839a992a, 0x8f242231, 0x212b825c, 0x57825e09, 0xc4830620, 0x6e431927, 0x00ffa199, + 0x23af8213, 0x34b31000, 0xb323db82, 0x8206cccc, 0xba192554, 0x1100ffe1, 0x05222d83, 0xe28248e1, 0x8200c021, 0xd7632137, 0x11225982, 0x0a82707d, + 0x82333321, 0x23db8214, 0x33330e00, 0x11222e82, 0x4f419a99, 0x13446805, 0x626cf020, 0x2d638205, 0xfce9fbff, 0xb5efffff, 0xf7ffffc2, 0x4c82a806, + 0x7a940022, 0x2821fd82, 0x05624cf6, 0x33040023, 0x254c8232, 0x08686604, 0x0882079b, 0x1aaf0127, 0x93ffffff, 0x21d48282, 0x09826290, 0x0122e383, + 0x3782fca9, 0x34b20927, 0x7c0500ff, 0x22f382ee, 0x8295cccc, 0x5e0b202a, 0x585e0591, 0xb3f43115, 0xffff0634, 0xff66e6ed, 0x70bd2500, 0xb3d9ffff, + 0x1a2fbd82, 0xffff9042, 0x8b6666d3, 0xc0ffff08, 0x82069a99, 0x4761220c, 0x241c828b, 0xffff8fc2, 0x2d2683e5, 0xffd7e3ed, 0x9042daff, 0xf4ffff08, + 0xfe5985ab, 0x11f4221a, 0x2d8882ec, 0xff81e5d0, 0x1baf0900, 0x80faffff, 0xae820800, 0xff85eb26, 0x7a54feff, 0x94210982, 0x8209827b, 0x2205836a, + 0x827b0868, 0xecff23db, 0xc182a470, 0x820eed21, 0x98d92b97, 0x120a00ff, 0xf0fffff2, 0x37829ad9, 0xf628d522, 0x842b2083, 0x00ffcc4c, 0xffcd4c64, + 0x82b39bff, 0xb37b25ec, 0xf7088b33, 0x0028c782, 0xff68e67b, 0x7e2a0100, 0x19201d82, 0x63223982, 0xff821cef, 0x99197d22, 0xff203a82, 0x603a1a83, + 0xffff67e6, 0xff64e6b7, 0xa4f04f00, 0x99a2ffff, 0x0c00ff9a, 0xff080ad7, 0x0a8265fe, 0xd19fff25, 0x829b15ec, 0x23002860, 0x00ff6666, 0x8229dc1c, + 0x82e62004, 0x70232f09, 0xff088ba4, 0xeb513f00, 0x2300ff06, 0x5482e27a, 0x17821c20, 0x19e3ff29, 0xffff8b9a, 0x859a99dc, 0xb3e525b7, 0xeaffff32, + 0x04844883, 0x9683e520, 0xfbffff24, 0x2482e5b0, 0x98cefb2c, 0xdc0000ff, 0xfcffff5d, 0xa382c00a, 0x827cb221, 0x42de2d93, 0x0e00ff90, 0xff05c10a, + 0x04960200, 0x4e201f82, 0x0222b982, 0x0982fa9e, 0x82843c21, 0x19642113, 0x16212982, 0x277a8288, 0xff625008, 0xe8c60300, 0x08222982, 0x0a8253e3, + 0x4328b121, 0x0023054a, 0x82666607, 0x3308228e, 0x20258232, 0x05554d06, 0x18b90627, 0x01faffff, 0x26218206, 0xffff6c72, 0x82239bf8, 0xdaff29bd, + 0xff063dca, 0x34b3f7ff, 0x07215d82, 0x832082b0, 0x80fa22c1, 0x289c8200, 0x08cc4cf9, 0x4cf9ffff, 0x22fb828c, 0x82d9f7ff, 0x110522a9, 0x26388268, + 0x00ffcc8c, 0x82a20508, 0x9c5921b3, 0xff238486, 0x821639fc, 0x82022084, 0xfeff239a, 0xa4827ae9, 0xfff99e26, 0x94c3ffff, 0x96210982, 0x21098205, + 0x4a8268b1, 0xb81edf27, 0xebf1ffff, 0x27108286, 0xfff813fc, 0xc856feff, 0xff227086, 0x4e829a19, 0x83999921, 0xaee52291, 0x257c8214, 0xffb89eea, + 0xc5841500, 0xce4c1a2e, 0x94f70e08, 0xff1514f8, 0x9a196dff, 0x92201c82, 0xc220a483, 0xad220a84, 0x598266e6, 0xb8de9d22, 0xb126a483, 0x00ff48a1, + 0x4b829972, 0x0080c025, 0x828d00ff, 0x83a0823e, 0x21168506, 0xd8833f00, 0x664e0022, 0x00233382, 0x829a1962, 0x52002133, 0x91207a83, 0x00210482, + 0x2755833d, 0x8b66e66e, 0x74fb8b08, 0xcb206b82, 0x5b206082, 0x1683ea82, 0x824cdd21, 0x05d858f4, 0x5f822220, 0xb30e0026, 0x2e00ff34, 0x09200983, + 0x00211e82, 0x83698536, 0x22168506, 0x8220f6ff, 0x232a8380, 0x4841f1ff, 0x4083a182, 0x85f1ff27, 0xffff5b1e, 0x206c82f7, 0x825c83ff, 0x82b5209b, + 0x3500370b, 0x5e159a99, 0x191a00ff, 0xc0ffff99, 0x00ff3233, 0xffcd4c10, 0xee76b7ff, 0x85068305, 0xefff2d16, 0xffff33b3, 0xffe1fad2, 0x67e6e5ff, + 0xf9225382, 0x9e82b81e, 0x87cc4c22, 0xcc280582, 0x00ff8bcd, 0x08cd4c09, 0x2c250682, 0x00ff9a19, 0x20048355, 0x209c8323, 0x058d546a, 0xce826920, + 0x5600ff22, 0xff221182, 0x37191edc, 0xf6270a15, 0xff8733b3, 0x8233f7ff, 0x82f9205b, 0xf7ff2d33, 0x0e0834b3, 0xf724f82f, 0x065f1574, 0xe12b6a82, + 0x3500ff48, 0xff050040, 0x8280f3ff, 0x821920d3, 0xe9ff2104, 0x12227983, 0x1e8200c0, 0x1e82a120, 0x00c00627, 0xb8ffff08, 0x228e82de, 0x82b81e15, + 0x82f82029, 0x01002324, 0x57823eca, 0x8b829920, 0x19820020, 0x66f9ff24, 0x25828b66, 0x7b84eb20, 0x828ceb21, 0x30f927e1, 0xefffffa4, 0x5982ec11, + 0x82ae0721, 0x42d8271a, 0xe1ffff8f, 0x40823473, 0x5ccff723, 0x056f51ff, 0xf483fb20, 0x2106e56b, 0xde826666, 0xe3eeff32, 0x0d00ffd6, 0xffff85ab, + 0xff0b17f1, 0x9a591200, 0x00235782, 0x82d9ce06, 0xdc0635fa, 0x0200ffac, 0x00ff7328, 0xffcdcc05, 0x3f750400, 0x2700ff08, 0x1e23a383, 0x82054761, + 0x85eb2115, 0x7c261582, 0x0700fff0, 0x29820a17, 0xff8a4c26, 0x1f850600, 0x02224083, 0x40825a04, 0xc9f6012c, 0xc7ffffff, 0x0100ffc8, 0x098229dc, + 0x08ac8e2c, 0x9e0e00ff, 0xfbffffb8, 0x988200c0, 0xd982da20, 0x80a8ff22, 0xfc220a83, 0xdf82a07a, 0xff06f326, 0x6666feff, 0x80220982, 0x05828b00, + 0x83989921, 0xe8e936a3, 0x0b00fff6, 0xffff717d, 0xffec91ea, 0x1e051400, 0x3af4ffff, 0x274b82e0, 0xff010055, 0xb8decdff, 0xe4204b82, 0x40204b84, + 0xff274b83, 0xffff3303, 0x8274d3fc, 0x8e872171, 0xc9210982, 0x224b8238, 0x8388d6fc, 0x59f22c4b, 0x0800ff9a, 0xffffcbc1, 0x820a57f3, 0xf8b321f9, + 0xba278c82, 0x00ff08e2, 0x82861603, 0x4c0322bf, 0x823682cc, 0x0300234b, 0xc9839a19, 0xb89e0d22, 0x0c20c982, 0x0822f583, 0xef8200c0, 0x04824020, + 0x00c00d22, 0x1f243182, 0x05f000c0, 0x3621db82, 0x26168204, 0x00ff2c47, 0x82c29500, 0xd4582109, 0x04223082, 0x6e82144e, 0x82100021, 0xf7ff2db0, + 0x00ffc856, 0xffa4f00f, 0x6c1cf1ff, 0xee2b7d82, 0xffff0814, 0xffb8dec2, 0x821e2400, 0x1f0021ba, 0x4e225283, 0x4b824861, 0x0a821420, 0x80d6ff22, + 0x0031c582, 0xffb40808, 0xe2baefff, 0xf5ffff9c, 0x00ff6666, 0x05125011, 0x66e63622, 0x1710a318, 0x11217682, 0x21fa82b3, 0xe38299f1, 0xcd4c0e2d, + 0x66eeffff, 0xfb088b66, 0x4b14f704, 0x5f4b0cfd, 0x46d65f0a, 0x82cc6121, 0x8022236c, 0xe2821500, 0xff991924, 0xc183ddff, 0x19bdff23, 0x137a1899, + 0x48a51817, 0x00ff2416, 0x8200804d, 0x401322de, 0x26998200, 0xff004011, 0x82800b00, 0x83072004, 0x9e112b04, 0x00ff08b8, 0xff00e008, 0x5f841400, + 0x1f83f520, 0x00400623, 0x08e88205, 0xff66c621, 0xe23a0a00, 0x33f3ffff, 0x0f00ff34, 0xffff9a19, 0xff3333f8, 0xcc4c1100, 0xbbaf0e08, 0x601534f8, + 0x4b2116aa, 0x208b8207, 0x232f82f7, 0x00200700, 0xe6203482, 0x63824882, 0xdb088b24, 0x7c4cdb06, 0x0ff56007, 0xff64f732, 0x6666a3fe, 0x3c00ff15, + 0xf7079a99, 0x54f70674, 0x089f5818, 0x99effe23, 0x51c1829a, 0x9e240579, 0x0600ffb8, 0xff228682, 0xd08280ef, 0xe1edff26, 0xc4fb0848, 0xff225582, + 0x19821ed9, 0x1e822220, 0x83e1ff21, 0x212822c4, 0x21288248, 0xdf820080, 0xcd8c1f25, 0x830500ff, 0xb315210f, 0x1d20bf82, 0x002c3883, 0x0866e61f, + 0x1c00ffab, 0x6b159a99, 0xcb2d3e83, 0xff60b81e, 0x48e1d4ff, 0xf7088b56, 0x266e82a4, 0x8b48e13d, 0x833200ff, 0x21322155, 0x3d220a83, 0x9855b8de, + 0x06f35e07, 0xf72edd83, 0x088b0020, 0x0e06a4fb, 0xf704f82f, 0xf98215d4, 0x9a99d325, 0x83e6ffff, 0x82d82004, 0xd9ff2df9, 0xffff6666, 0x089a19e9, + 0x66eaffff, 0x18123419, 0x9fffff23, 0x23e48219, 0x3333efff, 0xf0214282, 0x5bb182cc, 0x152b0ba9, 0xff079a99, 0xcc4cdaff, 0x831600ff, 0x83e52054, + 0x192722c8, 0x22a1829a, 0x8366662c, 0xb0462f96, 0x4100ffa4, 0x00ff6766, 0xff5c4f39, 0x1e4a4e00, 0x66502205, 0x22228266, 0x18008040, 0x200b0256, + 0x294a828b, 0x5b9a1937, 0x1200ff15, 0x1f829999, 0x36830d20, 0x11826e89, 0x34b31127, 0x99f2ffff, 0x05e75499, 0x66edff24, 0xbf828b67, 0xff219c89, + 0x0df953f1, 0x0f239782, 0x83ff3333, 0x00ff2416, 0x82cdcc10, 0x70002a2d, 0x15cb66e6, 0x4ceeffff, 0x82d182cc, 0x821d842f, 0x082e540a, 0x74823482, + 0x45551684, 0x85068506, 0x91002074, 0x83448390, 0x2a548516, 0xebfeff08, 0xffffc460, 0x82cc4c5e, 0xe60731c9, 0x0f00ffe9, 0x00ffcecc, 0xff523813, + 0x66660600, 0xcf3c0e82, 0xf8ffff5c, 0xff089a19, 0x3ecab000, 0x33a7ffff, 0x00ff0532, 0xff9a99b2, 0xcecc5800, 0x0f260a82, 0x00ffcccc, 0x2a82e607, + 0x82331321, 0x83f920f0, 0x230e8319, 0x3233f0ff, 0x0a863482, 0xff211986, 0x832d82ec, 0x28538619, 0xce4c79ff, 0x99bcffff, 0x2248829a, 0x8732b386, + 0x8383830a, 0x85838574, 0x19f82334, 0x3982ff9a, 0x84083421, 0x820a833a, 0x204e842e, 0x837282f9, 0x82868419, 0x834d201e, 0x239c84b7, 0xc2354fff, + 0xff23b286, 0x86a430f0, 0xc7ec2239, 0x225886ae, 0x821719f8, 0xcecc21e1, 0xf8223482, 0x0a839318, 0x0624cb82, 0x00ff3168, 0x0023cb83, 0x861bcf0f, + 0x86002e53, 0x00ffc2b5, 0x05666643, 0x4a79ffff, 0x220a873e, 0x84e530f0, 0xffff2420, 0x86cf97f9, 0xe7072234, 0x3148846d, 0x0e078b08, 0x0500ffef, + 0x01ffac1c, 0x15d2cdb6, 0x561900ff, 0x02381d89, 0xff70fd4f, 0x120330fe, 0x0a00ff05, 0xffff6866, 0xffceccf7, 0x64e60100, 0xe621ea82, 0x250e8366, + 0xf5ffffd0, 0xab829a99, 0xccccf722, 0x98200a83, 0x1e821983, 0x5719fe20, 0xa082361b, 0x02ffaf2a, 0xffcc4c33, 0x66662e00, 0x0222a082, 0x6782a49b, + 0x57828e20, 0x383efb22, 0x0b210982, 0x26048202, 0xffff6c87, 0x82cc4cfe, 0xa6f02876, 0xfbffff68, 0x82057e4a, 0x20852615, 0x66fdffff, 0x26098266, + 0x00ff9002, 0x8230bd04, 0xd463210e, 0x7321e382, 0x27298274, 0xff34f3e7, 0xacd14c00, 0xb0272982, 0x00ffc235, 0x82cccc1f, 0x783527d5, 0xc1ffff52, + 0x0a829ad9, 0x7a140527, 0x18faffff, 0x26e08294, 0xffff5ae4, 0x829403f8, 0xa61b2164, 0x73210982, 0x273f8234, 0xff1ec5e3, 0x66e691ff, 0xfd273f82, + 0xffff58d9, 0x82146ef7, 0xf0472104, 0xca213382, 0x8209823c, 0x02002378, 0x2982d823, 0x866bf027, 0xdf0300ff, 0x2729827c, 0xff1864f7, 0x18240200, + 0xc4212482, 0x218982de, 0x0e8262b0, 0x82662621, 0xec912609, 0x1900ff08, 0x22938233, 0x821e0562, 0x7dd92629, 0x2c00ff70, 0x230a82c5, 0x24270000, + 0xcb20b982, 0x00224482, 0x09828282, 0x8be2e522, 0xc2220582, 0x0682080c, 0xe2faca2b, 0xd9d4ffff, 0xd5ffff9a, 0x238f8205, 0x8baec7ca, 0x06837182, + 0xd8281682, 0x2b00ffea, 0xc08b1e04, 0x00282982, 0xfff43d02, 0xff820000, 0x19217082, 0x21098216, 0x0982a826, 0x82f83321, 0x7dd9272d, 0xd3ffff71, + 0xf382703d, 0x33331927, 0xfa9dffff, 0x200a82e2, 0x23208202, 0x0e6df7ff, 0xc321aa82, 0x21cf82d7, 0x04826250, 0x82dd6421, 0x2adc2179, 0x8525d484, + 0x20fcffff, 0x22aa8284, 0x82a265f7, 0xe6db2115, 0x48261f82, 0x0500ff72, 0x0e828836, 0x00239282, 0x826a9108, 0xc5e32729, 0x6e00ff1f, 0x29829a19, + 0x231bfe2c, 0x8b0700ff, 0x0100ff02, 0x0982dde4, 0xffacfc26, 0x7b140500, 0xe8210482, 0x27fe82f6, 0xff527835, 0x66263e00, 0x23069241, 0x3433e0ff, + 0xe7270a82, 0xffff70fd, 0x829042b2, 0x64fd220a, 0x2164825a, 0x0482928d, 0xff0c0226, 0xca41fbff, 0x85210982, 0x21c8821e, 0x69829a99, 0x66a6f027, + 0xb50400ff, 0x22298282, 0x84a285f7, 0x26248215, 0x00ff7d3f, 0x8532f308, 0x0700230e, 0x6982ce8c, 0x82661b21, 0xb0582229, 0x26e783a4, 0x00ff9c24, + 0x8262f006, 0x142e2184, 0x99210482, 0x210e82dc, 0x2e825ac4, 0x8232b321, 0xbc682729, 0x2a00ffbf, 0x53822892, 0xcd4c9727, 0xba2900ff, 0x220a82e1, + 0x82e13af9, 0x85ab2620, 0xd4faffff, 0x212f827b, 0xf2840080, 0x84829120, 0x299ce426, 0xb35800ff, 0xae83b983, 0x71080023, 0x21948268, 0x8482cbc1, + 0x82fef421, 0x93782104, 0xb321fd82, 0x225a8234, 0x829a590f, 0x80b52119, 0x08218482, 0x204f837a, 0x220f8299, 0x8271fd08, 0xd04221b3, 0x48825e82, + 0x8cf7ff23, 0x2229828c, 0x41900218, 0x00280602, 0xff3eca4f, 0x3333e0ff, 0xca278482, 0x00ffad87, 0x82f91e3f, 0xe6fa210a, 0x0520cf82, 0xff230482, + 0x839919fe, 0x67e62660, 0x800700ff, 0x203b8200, 0x22aa831c, 0x419a196e, 0x002306d2, 0x82ec9108, 0x10b82185, 0x3521ea82, 0x820982c2, 0xfdff2374, + 0x29822adc, 0x7b940f27, 0x20fcffff, 0x22298282, 0x82b89e08, 0xcad621d0, 0x33272482, 0xf7ffff34, 0x82886250, 0x846b2105, 0xe727df82, 0xffff33b3, + 0x82c4f59d, 0x83352025, 0x66c12270, 0x270a8266, 0xff7a2700, 0xa4701800, 0xfe3b8b82, 0x00ffed3e, 0xff5c8f24, 0xcccc1600, 0xa11f00ff, 0x2000ff48, + 0x00ff0080, 0x820a570b, 0x24052765, 0x0100ff18, 0x5a8202cb, 0x82e85b21, 0xf4fd27ea, 0xfaffff8b, 0x5a82f292, 0x2c12e823, 0x292b8207, 0xff06b81e, + 0xf6e81700, 0x23828b07, 0x82687121, 0xde642204, 0x2605828f, 0xffffee27, 0x82b032fe, 0x541f2743, 0xf5ffff7c, 0x62821a0f, 0xff66662a, 0xd863e2ff, + 0xddffff8b, 0x27057c77, 0xff649bfe, 0x48d2ffff, 0xb4212b82, 0x2109823a, 0x0982eced, 0x8200a021, 0x3f002735, 0xe7ffffcc, 0xae826290, 0xf6e83527, + 0xa83e00ff, 0x20ae82f6, 0x43a483e6, 0xfd270573, 0x00ff58d9, 0x82f29208, 0x2a3c216b, 0xaf210982, 0x2604829e, 0x00ff229b, 0x82d62302, 0x940f213f, + 0x0322e382, 0x3f827edf, 0x5e9a0822, 0x2305c743, 0x8eb70800, 0xc920be82, 0x02211982, 0x228a8226, 0x82966ef7, 0x3a1c2229, 0x061b44e2, 0xe4010028, + 0xf8ffffde, 0x84820075, 0x82221b21, 0x54032109, 0xeb212e82, 0x27048286, 0xff080817, 0xae87caff, 0x27076f44, 0xff3eca4f, 0xcecc1f00, 0x18275e82, + 0x00ff8e02, 0x8270bd4d, 0x9b02220a, 0x218482a4, 0x04826e72, 0xfff4fd26, 0x36be0400, 0x7a260982, 0xfdffffe4, 0x69826666, 0x98590f22, 0x2306ef44, + 0x607a0800, 0x68201583, 0xc0252482, 0xf7ffff80, 0x22ed820c, 0x446866fd, 0xe42107af, 0x22298299, 0x825c4fa7, 0xdbfd27f2, 0xf9ffff64, 0x84829e0f, + 0x82ecd121, 0x25662104, 0x3b210e82, 0x213d82a4, 0x9382cc4c, 0xd24c9727, 0x62d5ffff, 0x277d82d1, 0xff32b368, 0x1e45d6ff, 0x06210a82, 0x271a82c1, + 0xff1a4ffd, 0x7c2a0500, 0x68253482, 0x0200ff74, 0x225e8226, 0x82b012f9, 0x6e1b3888, 0xa7ffff14, 0x0e050a57, 0x7f00ffaf, 0x54f89a19, 0xcbffff15, + 0x828b48e1, 0x0000244a, 0x82218b35, 0xe653233d, 0x0f820766, 0x48e1d62c, 0x3ff6ffff, 0xeaffffbe, 0x0482b85e, 0xfffa9e26, 0x9ad9bfff, 0x3d06d163, + 0xccccf5ff, 0xc00700ff, 0xf5ffff42, 0x00ff3433, 0x8b06e10a, 0x1801ff08, 0xff0666e6, 0x50830d00, 0x1e0c0025, 0x4c00ffb8, 0x61210552, 0x21148248, + 0x80824821, 0x55820c20, 0x80260027, 0x0b00ff00, 0x271e82de, 0x8bb8de21, 0xa13500ff, 0xff291a82, 0xff0a17ff, 0xb81eac00, 0x21118205, 0x1c829e53, + 0x04831720, 0x30834520, 0x35862420, 0xfeff082d, 0x060080e3, 0xe3e0ffff, 0x8274fbd7, 0x1ef721ba, 0xff233f82, 0x8247e1f8, 0x9a19218b, 0x08233882, + 0x850866e6, 0x21118206, 0x1684b91e, 0x90828582, 0x06850820, 0xff201685, 0x1809876a, 0x2208f061, 0x83fff6e8, 0xffff2416, 0x820a17f7, 0x3f0024cb, + 0x188b2a1c, 0x201d5356, 0x274c8293, 0x8b930020, 0x938b9308, 0x2a1d0260, 0x8b3433f6, 0x158bcb08, 0x91838b83, 0x214683a9, 0x46829a19, 0xe021a182, + 0x4bbd8200, 0x516005a8, 0x084ed31a, 0xf754f723, 0x8b561574, 0xa9ffff60, 0xff8ba4f0, 0xc2f595ff, 0xb6218b08, 0x19aaffff, 0x088bc09a, 0xff3400ff, + 0x3b9b82fe, 0xe168e62b, 0x8b08f58b, 0xd4fffff5, 0xffe19819, 0x0200cbff, 0xfb8b088b, 0xffff1594, 0x09a5cc18, 0x96180020, 0x002410aa, 0xff48610e, + 0xff211683, 0x078c7800, 0x8248a121, 0x5e0e264f, 0xe3ffffb8, 0x220a8261, 0x189edcff, 0x6f08aa96, 0x16820503, 0xedffff2c, 0x088b0080, 0xf8ebef0e, + 0x195b1514, 0x21458205, 0x048233b3, 0xff66a626, 0xcd4c2300, 0x6a239a83, 0x5e06cc4c, 0xff330553, 0x00801700, 0x11f0ffff, 0x0900ffec, 0xffffcccc, + 0x8232b3e7, 0xe62f2abb, 0x88ffff68, 0xff05e23a, 0x232b8500, 0x07cccc21, 0x18254e82, 0x00ffcecc, 0x2d278205, 0x1e851800, 0x190b00ff, 0x1600ff9a, + 0x31825238, 0x46820220, 0xf8040023, 0x21318252, 0xbd4ae607, 0x05cb4906, 0xf6680625, 0x820f00ff, 0xf8ff2333, 0x29820a17, 0x39830a85, 0x82660621, + 0xc7ec2765, 0xf8ffffae, 0x84829819, 0x08a43025, 0x82fdffff, 0xfbff2748, 0xff05ae07, 0x1f83f9ff, 0x86abf225, 0x83fcffff, 0x4ff12814, 0xffff8b5c, + 0x829819f1, 0x33de2425, 0x82c30734, 0x191622c3, 0x20968298, 0x18ae8311, 0x24092f42, 0x99d2ffff, 0x21ae829a, 0x3683efff, 0x0483f720, 0x9a99f022, + 0x26833a82, 0x8233f721, 0xd4ff28e0, 0xffff30b3, 0x8266e6e4, 0xccf12265, 0x83d382d0, 0x66f02a1a, 0x0300ff64, 0xffffcc4c, 0x051e52ef, 0x0682d820, + 0xddffff27, 0xffff3233, 0x28b082ed, 0x3433e9ff, 0xe6e2ffff, 0x23808266, 0x0666e6b0, 0x82050e4c, 0x82b32057, 0x09f35a16, 0xf7ffff2d, 0xff06cccc, + 0xce4cfeff, 0x83fbffff, 0x83fe2032, 0x83fb203c, 0xe6fc2258, 0x20138266, 0x28418266, 0x32b30600, 0x33faffff, 0x106a1934, 0x82cc200e, 0xb287187e, + 0x83e9200a, 0x52048244, 0xff200621, 0xeb221a84, 0x7b82cccc, 0x00240a83, 0x0800800c, 0xff204684, 0x25825083, 0x8266fb21, 0x21668561, 0x8482cd4c, + 0x33217a84, 0x4a8e8433, 0x6f6905c1, 0xb3f12108, 0x11d45018, 0xad184c20, 0xff251224, 0x34330800, 0x82b78207, 0x01002146, 0xfb20b683, 0x00215a82, + 0x24cb8601, 0x190300ff, 0x8284849a, 0x4cf9224e, 0x228482ce, 0x521f85f3, 0xff2305d1, 0x8d70bdeb, 0x05187baa, 0x8632b321, 0x26c083d0, 0x1400ff8b, + 0x83ff3433, 0x2504840a, 0x0500ff08, 0x04823dca, 0x82cccc21, 0xd1fd2725, 0x0400ffeb, 0xc1829a99, 0x82cd0c21, 0x34b32109, 0x4a200982, 0x04221e82, + 0x7582cccc, 0x5ccff722, 0x2017885b, 0x20e982ab, 0x15f45f00, 0xa4300828, 0x0100ff06, 0x5082c3b5, 0x82cccc21, 0x33f32109, 0x00235a85, 0x84152e02, + 0xff08246e, 0x8235faff, 0x8405201e, 0x076b4184, 0x162caa92, 0x00ffb89e, 0x0533b316, 0xf50800ff, 0x08223082, 0xc58267e6, 0x022d0983, 0x00ff9899, + 0xff52380b, 0x9a19fcff, 0x343a8208, 0x059a9980, 0x2b158bcb, 0x9000ff07, 0xff0634b3, 0x9899d9ff, 0x20e282eb, 0x240c8295, 0x1554fb9b, 0x206018ff, + 0x838b2015, 0x27a48217, 0xffcdcc23, 0x3433dcff, 0x35ce7619, 0x3cfb9c23, 0x20838215, 0x20ee831d, 0x2204830e, 0x82ce4c1a, 0x9a992ab8, 0xe60f00ff, + 0x00ff0866, 0x210f830e, 0x0f82190a, 0x0080112d, 0xe60500ff, 0x1200ff66, 0x828bcccc, 0xb302221a, 0x833a8234, 0xffff21cf, 0x02271683, 0xffff9c99, + 0x82ceccff, 0xe62c261a, 0x00ff8764, 0x23958223, 0x3233daff, 0xd220aa82, 0xff28eb84, 0xff6666cf, 0x9899d8ff, 0x9a210483, 0x200e82ff, 0x82488268, + 0x82662006, 0x83d82022, 0x66272174, 0x00280a82, 0x089a9930, 0xff1573e3, 0x1559fb18, 0x1ae7af18, 0xff249082, 0xffcc4cf5, 0x52820483, 0x34b3f223, + 0x18068508, 0x8509eadc, 0x0e082554, 0x1501ff2f, 0x01398d82, 0x151e05b4, 0xb3efffff, 0x0700ff34, 0xff79d282, 0x10780400, 0xe6ecffff, 0x22998366, + 0x82cd4cca, 0x33d22d3f, 0xdeffff33, 0xff78b8de, 0x4821d1ff, 0x5132de82, 0xff06ec11, 0x7ad45a00, 0x054400ff, 0x00ff051e, 0xcd821941, 0xe2fabb22, + 0xf8304982, 0x00ffe21a, 0xff527813, 0x283cf3ff, 0xb81000ff, 0xf0220982, 0x7682142e, 0x08ec512c, 0xfabdffff, 0xceffffe2, 0x3482707d, 0x0080662a, + 0x89ffff06, 0x44fb0080, 0x4621ea82, 0x21bc82b3, 0xbc823900, 0x4f390023, 0x22e3825c, 0x82a4b046, 0x050022bc, 0x2630827a, 0xff000eff, 0x82380500, + 0x55ff224a, 0x30098212, 0xff08cc4c, 0x173903ff, 0xffffff06, 0xffff0a57, 0x23be82fa, 0xcd0cffff, 0xcc210982, 0x22b182cc, 0x820080fa, 0xb9ff243b, + 0x82ffcd4c, 0x2c168252, 0xff33b3c6, 0x33b34600, 0xfbbb088b, 0x22a58234, 0x8229dcd2, 0xa33a27c1, 0xa2ffffd7, 0x8c82842b, 0x66e61326, 0xba0600ff, + 0x0e27bb82, 0x00ff9a99, 0x82ce4c11, 0xcc152282, 0x174379cc, 0x0200ff26, 0x04f734b3, 0x9a224a82, 0x86829999, 0x649bfa22, 0xae217783, 0x219182d9, + 0x878202ad, 0xff2e4a82, 0x08fe84ff, 0x943100ff, 0xb0ffff7a, 0x274100ce, 0x22768205, 0x8248212c, 0xde23235c, 0x1757ffb8, 0xebed310d, 0xf9ffff86, + 0xffff7cbf, 0xff707def, 0x1edaf5ff, 0x2207527e, 0x82e2ba4d, 0x2b132237, 0x24378284, 0xff00800f, 0x82048200, 0x3313220a, 0x269f8334, 0xff32b35f, + 0x8266b2ff, 0x824d20c0, 0xa0ff21bb, 0x082bbb82, 0x4cedfeff, 0x52ffffcc, 0x821534b3, 0xccec2297, 0x223382cc, 0x67ff1f85, 0x132305c6, 0x828bd723, + 0x571d3298, 0x00ff060a, 0x079a19a9, 0xf8d8ffff, 0xe0ffff52, 0x27488233, 0xffae07e7, 0x9a99cfff, 0xc9293682, 0xeb08cecc, 0xe69a00ff, 0x28e78266, + 0x07666642, 0x199900ff, 0x2bed829a, 0xff999982, 0x34b3c800, 0xf6ffff05, 0xff237782, 0x829819fd, 0x33b32709, 0x4cfcffff, 0xda57ffce, 0x80fb2c05, + 0xef0e0800, 0x14f8d4f8, 0x8294fc15, 0xccdc2233, 0x215282cd, 0x248233e3, 0x3433e322, 0xdc260a82, 0xfb08cccc, 0x09850794, 0x1c00ff26, 0xffffcdcc, + 0xff241982, 0x33332300, 0x80219e83, 0x2710824c, 0x05faffff, 0x2e1900ff, 0x003dc582, 0xff99d916, 0x1ec50e00, 0x570a00ff, 0x1600ff0a, 0xff08c4f5, + 0x8fc21b00, 0xa63d00ff, 0x26258266, 0xff00e007, 0x82801100, 0x20102104, 0x0b220482, 0x0e824821, 0x8348a121, 0x8211204b, 0x00ff2d06, 0xffb81e10, + 0xb8def4ff, 0xe10700ff, 0x2807336b, 0x00c01b00, 0x5ec2ffff, 0x264082b8, 0xff9a590a, 0x8205e9ff, 0xd9162160, 0xf1220982, 0x7a82e23a, 0x84323321, + 0xf628268c, 0x000000ff, 0x20258206, 0x82bd8323, 0x83cc20ae, 0x8bcc21b3, 0x3422af83, 0xc883f708, 0x8405f143, 0xcc1c24c3, 0x82ffffcc, 0x088b26e1, + 0x84fb34fc, 0x210b8215, 0xe982b89e, 0x8261e321, 0x841c2093, 0x5e23238c, 0x3c8308b8, 0x8e825e20, 0xb99e1c22, 0xba20c982, 0x23216e82, 0x83af8461, + 0x205e8206, 0x08d7489e, 0x1e85dd22, 0xff202d82, 0xff290682, 0x6666e3ff, 0x7ae2ffff, 0x265482e2, 0x088b9a99, 0xa18bd4f7, 0x2064825f, 0x205fa91b, + 0x085f8868, 0x088b9823, 0x0300ff0e, 0x01ff98ae, 0x1566e62a, 0xa33100ff, 0xeaffff54, 0xff056666, 0x33b31400, 0x66ceffff, 0x2a0a8267, 0xff190401, + 0xfef4fdff, 0x820200ff, 0xfeff232a, 0x0982d558, 0x8b6d472e, 0x0000ff08, 0xff8bff01, 0x02fcffff, 0x0b83ec82, 0x02221282, 0x17826045, 0x2d830320, + 0xffbba926, 0x39a50100, 0x03210482, 0x21328213, 0x1e82f608, 0x52b81422, 0xa1216782, 0x21578249, 0xb8829e31, 0xc2b51422, 0x02220a82, 0x2582e305, + 0x820c0221, 0x31a82104, 0xac212a82, 0x2143824a, 0x0982d102, 0x08184422, 0x20216082, 0x210a8243, 0x09822050, 0x82333321, 0x34b32309, 0x16828c89, + 0x9999ce22, 0x9922a882, 0x1782059a, 0x00200a83, 0xff23b983, 0x82a470eb, 0xcc4c2161, 0xfe221582, 0x2d8270fd, 0x823e0a21, 0x0a5721be, 0xa3215b82, + 0x210982d8, 0x5b82e1ba, 0x821e0521, 0xfeff223f, 0x21b78301, 0xc383fe03, 0x12820b82, 0x93b8fd22, 0xfd200c82, 0xfe276a83, 0xffffdc59, 0x8229fcfe, + 0xfcf42132, 0xeb271a82, 0xffff0e4d, 0x825c64ce, 0x5cce2557, 0xebffffac, 0xfd226284, 0x258252f8, 0x8266e621, 0x17592104, 0x66212a82, 0x453f8366, + 0xfd22059b, 0x748234b3, 0x84e9a621, 0x21888216, 0xa882ae07, 0x08cccc2d, 0x6bfb01ff, 0x25ffff02, 0x82159a19, 0x00ff2110, 0x45211a82, 0x214082e4, + 0x09828e58, 0x8250ad21, 0x92f8212e, 0x04203882, 0xce22fa83, 0xe382146e, 0x8286ab21, 0x3aeb2275, 0x84d882e2, 0xd3ff220a, 0x212082b6, 0x598674fe, + 0x68820120, 0x6d82ff20, 0xc1848b20, 0x81831020, 0x82405521, 0x16592150, 0xfb210482, 0x212582e8, 0x1a82fef4, 0xc182b182, 0x84b85e21, 0x822820c1, + 0x3e4a21c1, 0xfd210a82, 0x222587f9, 0x82d057fe, 0x3e55212a, 0x3a209483, 0xba270982, 0x00ff081e, 0x82000100, 0xeebc210a, 0xa8216f82, 0x21098278, + 0xa482d84e, 0x82680621, 0xeefc2158, 0x31221e82, 0x4882ec91, 0x057a5422, 0xc521a582, 0x215e821e, 0x0a827c54, 0x64100122, 0xff212a82, 0x212a823c, + 0x2a829a99, 0x82cc4c21, 0x055e6709, 0xea460223, 0x210c828b, 0x5082c0aa, 0x84f0a721, 0x210e82e6, 0x4b82020b, 0xa4b01422, 0xa121e082, 0x22408248, + 0x8266a631, 0xc2b52350, 0x21828d05, 0x829e0f21, 0xcecc2186, 0x8b204c84, 0x082f4884, 0xc4f7c4fb, 0x0c00ff15, 0xffff856b, 0x825238e2, 0x7a012231, + 0x826882e1, 0x01002182, 0xff227283, 0x34829002, 0x8b008022, 0x00205782, 0x36820682, 0x820a7721, 0x00fe2111, 0x9c210482, 0x22558229, 0x8208103a, + 0xcd6c2640, 0xc71d00ff, 0x224082f0, 0x82aec71d, 0x846b210f, 0x01220a82, 0x25831038, 0x04820220, 0x82fafe21, 0x109c212a, 0x01237682, 0x8308e65b, + 0xf45d2606, 0x01ffffff, 0x20168206, 0x21ef829a, 0xc382c7fe, 0xe69b0023, 0x82878408, 0x8c6c2740, 0xf4ffff05, 0x56860080, 0x83feff21, 0x3a01220a, + 0x21348210, 0x8085cc4c, 0x2108aa41, 0x508234b3, 0x32330022, 0x02211b82, 0x21048200, 0xc2836666, 0x4b82f020, 0x34b3f222, 0x10205083, 0xe3224b82, + 0x827b9919, 0xfdff2306, 0x258267e6, 0x82d66321, 0x83e62004, 0x6666222a, 0x2130828b, 0x978248a1, 0xa4feff23, 0x205d8318, 0x21108228, 0x9c82d863, + 0x829b3721, 0x18642125, 0x1c22e382, 0x4082d7e3, 0x05f8932a, 0xffff54f7, 0x1566e680, 0x2707464e, 0xff9a3906, 0x82200700, 0x08348482, 0xa7087edf, + 0x5b00ff07, 0x00ffb8de, 0x0532b365, 0xc00500ff, 0x0622c382, 0x4682fa5e, 0x08260983, 0xffffa0ba, 0xf78200fa, 0x20050722, 0xee27a182, 0x00ffda3a, + 0x828a8112, 0xe0f921a1, 0x20202983, 0xf621c182, 0x21098260, 0x09824000, 0x18a1f921, 0x27079090, 0x86ebe8fe, 0x0c05ffff, 0xd5212983, 0x14ee7966, + 0x6606f822, 0xdb295182, 0xff07b81e, 0x00808aff, 0x21538221, 0x448280f2, 0x7882f320, 0x5cffff2e, 0xeaffff29, 0x00fff6e8, 0x7eb8fe0c, 0x2927cf82, + 0xffff6766, 0x820a97d6, 0x190c22a3, 0x26da829a, 0x00ff68e6, 0x82ae0716, 0x70bd21a8, 0x3d312582, 0x0d00ff71, 0xff08347e, 0x34331701, 0x803501ff, + 0x24298200, 0x0600e015, 0x2921828b, 0x0e15d618, 0x1594f7ab, 0xc982d4f7, 0xa4f03422, 0x2b24fb82, 0x00ff5c0f, 0x0a820482, 0x08201082, 0xff240685, + 0xa4f0d4ff, 0xff281684, 0x5c0fcbff, 0x066b088b, 0x0ded4a18, 0x3a82b020, 0x4feeff23, 0x832f825c, 0x00ff2806, 0xff5c4f0e, 0x82b0f1ff, 0x82112034, + 0x05626e1b, 0x82f6a821, 0x570e224d, 0x8318820a, 0xeeff230a, 0x2f840a57, 0x16841186, 0x57255682, 0xfb088b0a, 0x21608ed4, 0x7d5934b3, 0x2360840f, + 0x00ff34b3, 0xf7266084, 0x1514fb14, 0x358e14fb, 0xf720969f, 0x00213082, 0xb397aa11, 0x1d5741f7, 0x4166e621, 0x19280757, 0xf7088b9a, 0xfc15eb94, + 0xb320c58f, 0x410e6569, 0xfb88065c, 0xc540f820, 0xff0e368f, 0xcc4cfb01, 0x6e7701ff, 0xffff1514, 0xffb81ebc, 0x48e14300, 0x05f24905, 0x4006002d, + 0xf5ffff00, 0xff8b3cdf, 0x82c0f9ff, 0x2404820a, 0xe9ffff08, 0xd947185e, 0x22158607, 0x82fffabe, 0x83be2000, 0xffbe212a, 0x1a203482, 0x29822e84, + 0x2983b320, 0x4f820482, 0x0a82d120, 0x83130021, 0x3ac82544, 0x656582e2, 0x61241d82, 0xffff9a99, 0x05220482, 0x60827272, 0x707dd73e, 0xff0872a4, + 0x90825a00, 0x7aa5ffff, 0x00ff05e2, 0x72010019, 0x822800ff, 0xa4a48b8f, 0x9e2f1982, 0x00ff6566, 0x0566669e, 0xff94b1b1, 0x82c23700, 0x82ec2027, + 0x2e0023a0, 0x1d82d6a3, 0x48a14c24, 0x048200ff, 0x08764b18, 0x00236b82, 0x1800400a, 0x2009764b, 0x20258200, 0x82258316, 0x21258304, 0xac823417, + 0x82703d21, 0x210a2220, 0x21b28248, 0x0f82cccc, 0x0800402a, 0xfeffdcfb, 0x15b85ea1, 0x7d218682, 0x82908470, 0x007a242d, 0x820ef701, 0x219e8907, + 0xf48285ff, 0x0286ff28, 0xaf0e058e, 0xa55eebdb, 0x06a36b17, 0x80150024, 0x8d5eff00, 0x181a2005, 0x8210228e, 0x8284821b, 0x17d84b17, 0x8b34f822, + 0xfb375fdc, 0xf4ffff0b, 0xff1566e6, 0x00a00400, 0x800e00ff, 0x00ff8800, 0x82486110, 0x230f8315, 0x08707d0b, 0x20061b46, 0x26c6830b, 0xff48a1ef, + 0x82e10200, 0x83f1201e, 0x7efb270e, 0xff8408b8, 0x0b830d00, 0xb85ef225, 0x840900ff, 0x00c02224, 0x2035828b, 0x210682ef, 0x1683ffff, 0x80f6ff24, + 0x0a828400, 0x82008021, 0x7af12216, 0x276c82e2, 0xffffaea7, 0x889999ef, 0x99215c82, 0x2104829a, 0x67866866, 0x83f4ff21, 0x1efd2242, 0x831f82b8, + 0x8104216c, 0x1e826c85, 0x4584f220, 0x6c86f620, 0x20828b20, 0x0800c022, 0x79860685, 0x8d828384, 0x2d828420, 0x0060fb24, 0xa582ffff, 0x27828e20, + 0x9a829e20, 0xf427bf84, 0xff089082, 0x82400800, 0xe0f7211a, 0x0a21ef82, 0x200982c0, 0x820986fb, 0x040024b4, 0x828b0040, 0x2220829e, 0x82200100, + 0x82042020, 0x01002288, 0x23b88260, 0x15ee0600, 0x8c21c382, 0x22ef82cc, 0x83ff32b3, 0x00ff22d3, 0x05e06110, 0x16820683, 0x8414ae21, 0x82922087, + 0x21ea830a, 0x41820400, 0x82feff21, 0x20568362, 0x210986ff, 0x6783b83e, 0x46187882, 0x2583070a, 0x00229284, 0x67832008, 0x4261a883, 0xe1022a05, + 0x1000ff48, 0xffffb85e, 0x7e0482fb, 0x0d200657, 0x0023ff82, 0x84e2fa06, 0x828b846a, 0x20808248, 0x86068508, 0x830d2098, 0x80f231a2, 0xf7089200, + 0x8b00ff3b, 0x8b159a19, 0x56b660c0, 0xff227a82, 0xe28260ff, 0x82ffff21, 0xffff2146, 0x09839b82, 0xee851682, 0xce7f0520, 0x66052208, 0x20508266, + 0x05a56905, 0x16822c20, 0x2005d550, 0x22318323, 0x82ccccd3, 0xe7ff2531, 0xff8b4861, 0x20054a57, 0x201683f4, 0x772583f1, 0xed2b05f9, 0xffaf6666, + 0xcdccdaff, 0x831800ff, 0xccd4221a, 0x663183cd, 0xcd2605b2, 0xffff66e6, 0x3c83e1cd, 0xb81ec222, 0xff21b782, 0x382382f8, 0x00c00000, 0x0100ff84, + 0x08840060, 0xa0d9ffff, 0xf3ffff00, 0xffff3473, 0x225583e4, 0x82cc4cdc, 0x80d5286a, 0x568b0800, 0x82c060b6, 0x2b002d4b, 0xff064861, 0xb89e0300, + 0x0400ff93, 0x07256883, 0x00ff6666, 0x25048606, 0x0d00ff08, 0x04829a99, 0x9d686631, 0xb30700ff, 0x1300ff32, 0x00ff3333, 0x83343300, 0x22fc821a, + 0x82190d00, 0x4c12221f, 0x201e82cc, 0x200482cc, 0x05ca4113, 0xff210683, 0x21168300, 0x7982f8ff, 0x2106db42, 0x3582b8de, 0x0f821320, 0xc0ffff29, + 0xffff9d00, 0x820060f8, 0x2345825b, 0x4881f2ff, 0x06201a82, 0xf921a983, 0x208082a6, 0x20dc8304, 0x237a83f8, 0x83008003, 0x2b060b75, 0xb6b68bc0, + 0x0e08c08b, 0x5e01ffaf, 0x002c3482, 0x150080de, 0x1ff9ffff, 0x2500ffbe, 0xdf255483, 0x00ff42a0, 0x2209831c, 0x8270bdd8, 0xf3ff23dc, 0xef8200c0, + 0xb85ef425, 0x83fdffff, 0xa1f53150, 0xff088648, 0x5d8feeff, 0x331700ff, 0xe3ffff34, 0x0f20f183, 0xdf201a83, 0x21061b51, 0x318271fd, 0x82ffd421, + 0x82d52000, 0x08562111, 0xff200d82, 0x00206b83, 0xf341b584, 0x26448207, 0xffd763db, 0x82d3f7ff, 0x83e42044, 0x99df225f, 0x222a829a, 0x83cc4cd9, + 0xc0d32131, 0x2320d782, 0xff220482, 0xcc8226dd, 0x90422c27, 0x94f7088b, 0xf6761806, 0xc2232407, 0x8200ff90, 0xff8b251e, 0x9a592b00, 0xff254b82, + 0x00ffe0fa, 0x24908527, 0x2000ffcc, 0x277e827f, 0xff34b3da, 0xcdcc0600, 0xd927fb82, 0x00ff6866, 0x8233b301, 0xb3b92bec, 0xf2ffff32, 0xffff33b3, + 0x29824cbf, 0x75833520, 0x80460023, 0x27758200, 0x48a12800, 0xe11500ff, 0x25200482, 0x00289182, 0xffb89e23, 0x48211400, 0x05344082, 0x00ff4280, + 0xff002003, 0x7493feff, 0x3e0800ff, 0xf9ffffb8, 0x00219e82, 0x231e8301, 0x7e5ff7ff, 0x9d215f82, 0x28cf82be, 0x00ff3233, 0x82fac000, 0x2295828b, + 0x82b81eb2, 0xc7c025d2, 0xc2ffffae, 0xff212c82, 0x219182fc, 0xb083b3ff, 0x831a0021, 0x1ef4210f, 0x15266082, 0xff759082, 0x6b820a00, 0x84e4ff21, + 0x2125256b, 0xf1ffff48, 0x00211f82, 0x228a821a, 0x82dedeff, 0x40062124, 0xd8217a82, 0x218a84a1, 0x65664220, 0xec042206, 0x268f828a, 0x00ff5efa, + 0x82004005, 0x2c00296f, 0xff8b48a1, 0x7ad42800, 0x262bb682, 0x1b00ff66, 0x00ff3c0a, 0x82b91e21, 0x420431c0, 0x0400ff90, 0xffff1cda, 0xff9c99fb, + 0x33330700, 0x8e83c082, 0xcdccfe22, 0x1c20a982, 0xff2bb682, 0x15991935, 0xff055b6b, 0x82a7f8ff, 0xf8f427b1, 0x0200ff52, 0x8b8210f8, 0xff0a1726, + 0x74080b00, 0xa8221882, 0x468208f6, 0x8c820b20, 0xae47fd22, 0x99210982, 0x8281829a, 0x03002346, 0x818334b3, 0x42c00722, 0x07258182, 0x00ff06a1, + 0x20c18303, 0x27d68204, 0xa4f00600, 0x05bbab08, 0x58207582, 0x0b215282, 0x2c5c8207, 0xfff007fd, 0xf6e80e00, 0xf7f4ffff, 0x2118828c, 0x84820a57, + 0x64dbf522, 0x54210a82, 0x2271827a, 0x82889a19, 0x34b3226d, 0x23168280, 0x8b66e69f, 0x7320979b, 0x24239788, 0x86ffff9c, 0xdb992097, 0x9a992497, + 0x922b0880, 0x41112093, 0x93d7082b, 0x2b418d20, 0x88992413, 0x83f8ffff, 0xffff2493, 0x92ae07a0, 0x09c34197, 0x17219789, 0x072b41cf, 0x4148a121, + 0x0422062b, 0xc3415c8f, 0x41ef202d, 0x978808c3, 0xdfeff422, 0x2107c341, 0x9783f628, 0x80b89e2a, 0x34f80e08, 0xff15d4f7, 0x2b39f145, 0x00ffcc4c, + 0xff00c023, 0x34b3d3ff, 0x2125f145, 0xf14567e6, 0x33b32107, 0x2305f145, 0xffff8b99, 0x2105f145, 0x0a82b8de, 0x4821c222, 0x2235f145, 0x4506d4f7, + 0xc9460646, 0xfb5b2306, 0x508215e4, 0x707de525, 0x821500ff, 0xeaff2804, 0x00ff9082, 0x8290821a, 0x46491877, 0x231e8218, 0xfdcfffff, 0x44263282, + 0x8b8b0a97, 0x41828b08, 0x9002d027, 0x66bbffff, 0x05b04966, 0xd4fb0823, 0x1857848b, 0x8c0fa149, 0x18712057, 0x860e9e49, 0x8b168257, 0x8b8f2057, + 0x34f72157, 0xaf855785, 0x87ff7121, 0xa28f20af, 0x41579baf, 0x402040e5, 0x2207f345, 0x4166a6d4, 0xf22413e5, 0xffff6626, 0x2605d747, 0xaf9a99eb, + 0x41daffff, 0x4c2710e5, 0xffff8bcd, 0x8233b3cd, 0x12e54104, 0xff844f2d, 0xf35f0100, 0xffff0884, 0x474ea2d9, 0x3e2307d7, 0x47ffffd2, 0xff260bd7, + 0x9a192a00, 0x8182c060, 0x193f0129, 0x00ff069a, 0x476acb36, 0xba480537, 0xcc262808, 0x1effffcd, 0x82159a19, 0x7bd43043, 0x380500ff, 0xf1ffff10, + 0xffffb8de, 0x82f45ffa, 0xaec72104, 0xd0211882, 0x256782f2, 0xfb66e6d0, 0x12830504, 0x1282ef20, 0x825ccf21, 0x12a4212b, 0xe1262b82, 0x0c00ff48, + 0x2b842730, 0x95820820, 0xff5d4f2b, 0xb89efeff, 0x190400ff, 0x05ce5099, 0x19030023, 0x2983829a, 0xdf4f0900, 0x0800ff8b, 0x3a82a6db, 0xff20702b, + 0xf6e80300, 0x170900ff, 0x2335828e, 0xf79a192f, 0x00225c82, 0x38821e06, 0x862b0c23, 0x058d79ff, 0x98190e27, 0xb3f4ffff, 0x21308233, 0x8382ce4c, + 0xf5a88a23, 0x84a9838b, 0x21a9847d, 0xa999d7e3, 0x4ee2f922, 0xca21a982, 0x213d823c, 0x085d19a4, 0x0c002305, 0x30825c2f, 0x8232b321, 0x14032273, + 0x062e447b, 0x33330322, 0x2821a987, 0x20a9a8f6, 0x83f782b9, 0x59fa24a9, 0x8400ff99, 0xd1f322a9, 0x23a986eb, 0xd8a3ea00, 0xd820a98f, 0xfa22a999, + 0x5341f0c7, 0x3502221b, 0x065341c2, 0x5c49a98a, 0x4f092205, 0x0e5341e0, 0x5341f420, 0x3805220f, 0x22a98652, 0x873233fb, 0xcecc21a9, 0x7522a987, + 0xa9846666, 0x417ad421, 0xe32007fd, 0xc221a988, 0x11fd4190, 0x2620a993, 0x2207fd41, 0x882a1c02, 0x413220a9, 0x02220653, 0x5341ce4c, 0x22a9a005, + 0x861e0507, 0x4cfa21a9, 0x53419f82, 0x66e62105, 0x0e3ba985, 0xff00ffef, 0x01ff33b3, 0x1566e634, 0x19f5ffff, 0x0d00ff9a, 0xffff9a99, 0x4bcdccee, + 0xff2105b9, 0x2bca82ec, 0xdeffff08, 0xff8b29dc, 0xd723e5ff, 0xd8200483, 0xdf230a82, 0x82088ec2, 0x70e63706, 0x1000ffa4, 0xffff5c0f, 0xffeb51ea, + 0x1f851600, 0x5cf7ffff, 0xb3480829, 0x0b002305, 0x518215ae, 0x4c824c20, 0x67660a26, 0x660f00ff, 0x07227882, 0x1e82cccc, 0x34330322, 0x6b822e82, + 0x2005444c, 0x270e8315, 0xff99190f, 0x32331200, 0x78286f82, 0x1567cd4c, 0x3000ff8b, 0x27202183, 0x26223683, 0x0e840080, 0x1b22f783, 0x1b82cdcc, + 0x717d1827, 0xdcf2ffff, 0x26808228, 0xffff4621, 0x82b8deeb, 0x3d152257, 0x26678270, 0x00ff86ab, 0x82e2fa19, 0x48a126c3, 0x5c1c00ff, 0x2235832a, + 0x82820200, 0xfaff22b1, 0x833b82fc, 0x2066820b, 0x235983cc, 0x05d6630c, 0x5f834882, 0x6af14a2c, 0x00ff8a05, 0xff7e4a05, 0x1b83fbff, 0x80580322, + 0x33210982, 0x233f8234, 0x16f9fdff, 0xfd2c3f82, 0xffff56ee, 0xff3e68ff, 0x1a24feff, 0xb6210482, 0x2747823a, 0xff146ec1, 0x7a94d4ff, 0xc1274782, + 0x00ffcc6c, 0x82586b2b, 0x83fe200a, 0x4a0126d4, 0xfdffff1c, 0x23f882e6, 0x89c29700, 0xfb224783, 0x4782982e, 0x436bfb27, 0xa7fcffff, 0x204c826c, + 0x220e820c, 0x82c2b5fa, 0x75f22747, 0xb5ffffc2, 0x3c82ce0c, 0xae07b522, 0x74219482, 0x220a82a8, 0x8204b6fa, 0x5e0b2125, 0xa6212f82, 0x218e82e9, + 0x3082e86a, 0x922dfb23, 0x27068208, 0xff58f9fd, 0x94970000, 0xee266382, 0x0100ff98, 0x9382f649, 0x089c2422, 0x68208382, 0x98820a82, 0xd4214082, + 0x22408296, 0x823669c1, 0xb5fe210a, 0x98836182, 0x1f82c382, 0x8b219882, 0x27478389, 0xffd92efb, 0xd5580300, 0x6b265e82, 0x0500ff44, 0x7282fc49, + 0x82490c21, 0xf34a2247, 0x27888233, 0xff05c275, 0x3d8a0d00, 0xcc209e83, 0x00240a82, 0xffff9cf4, 0x00239883, 0x82dd9404, 0x2ca72698, 0xd00400ff, + 0x29df8221, 0xe9060200, 0x0200ff8b, 0x9883aa11, 0x9382bc20, 0x82a6db21, 0x0e4a2104, 0x13224b82, 0x45825278, 0x82908221, 0xd7fc2288, 0x05935a0a, + 0x39feff23, 0x210982db, 0x3482a4f0, 0x285c0b22, 0x00238c82, 0x82862b11, 0xf007364d, 0x661000ff, 0x0700ff66, 0x00ffe71b, 0x0800c00e, 0xe4e1ffff, + 0x274082de, 0xff768dec, 0xcd4c1e00, 0x24333182, 0xff08cc4c, 0x0080a601, 0x99cdffff, 0xffff159a, 0x4c0020f9, 0x098208af, 0x2214af4c, 0x4cffff88, + 0x388207ab, 0x2118002b, 0xe3ffff48, 0x00ffb8de, 0x2e04820f, 0xb8dedfff, 0x8b56088b, 0xfdd4ffff, 0x4c8b6070, 0x61211ba3, 0x216f824a, 0x3c826686, + 0xff234682, 0x8266e6de, 0x5eda2034, 0xa34c05b5, 0x40dc2109, 0x2c258682, 0x088b9042, 0x26a482ff, 0x00ff06fe, 0x820c172d, 0xcc2325b9, 0x2200ffcc, + 0x00213383, 0x2133842d, 0xec822600, 0xb3e3ff2b, 0x2000ff34, 0xffff0180, 0x222083da, 0x8233b306, 0x83092037, 0x6642225f, 0x22df8266, 0x823c3ff8, + 0x67f82b65, 0xfcffff2c, 0xffff7c3f, 0xbc8261fb, 0xe00ff92b, 0x055b6b08, 0x44fdffff, 0x261282de, 0xffff32e8, 0x82aab1fe, 0xbe5f2109, 0xfb222c82, + 0x4382d26d, 0xc801002b, 0xaef1ffff, 0x0a00ff16, 0x20b282e6, 0x216c82f5, 0x45460d00, 0xc0072205, 0x22908200, 0x4b289c07, 0x022c1498, 0x00ff24bb, + 0xffce1704, 0x544e0100, 0xa0210982, 0x242c8242, 0x082e9204, 0x2d6082ff, 0x0d00ffa8, 0xffff846b, 0xff9819f5, 0xa6830b00, 0x68e6f226, 0x8b2b088b, + 0x7d83aa84, 0x3869f822, 0x5c23aa87, 0xa4ffff28, 0x5a0421aa, 0x0c21aa90, 0x06434c33, 0xba21aa8f, 0x09434cff, 0x22bb0222, 0x5620aa88, 0x0023aa8c, + 0x880ce200, 0x889a20aa, 0x886620aa, 0x8b3c26aa, 0x69f8ffff, 0x21aa87ba, 0xaaa6b85e, 0xa8ca0121, 0x48a121aa, 0xdf21aaa6, 0x21aa9b7e, 0xaa83763e, + 0x42f06721, 0xdd201600, 0x20190042, 0x20aa9fcb, 0x0f004229, 0x2000ff28, 0x05bb0100, 0x594100ff, 0xef0e2c33, 0x19bf00ff, 0xe0ffff9a, 0x821566e6, + 0x80ed27b3, 0x0f00ff00, 0x8582cc4c, 0xff9a9924, 0x46181000, 0x99270831, 0x00ff8b9a, 0x1966660e, 0x240d2b09, 0x4b0634f7, 0x20368207, 0x211884ee, + 0x3686f668, 0x2d821120, 0x00ff0826, 0x8b70fd1f, 0x0d839782, 0x64203683, 0xff303b8b, 0x9c020000, 0xff0514f7, 0xcce3a0fe, 0xffffff06, 0x80268483, + 0xff0566e6, 0x0a82be01, 0x33de0027, 0xffff1534, 0x278e83ec, 0x0548611d, 0xc0e3ffff, 0x2a2a9982, 0xffff0040, 0xffb8ded0, 0x09831900, 0xae47cd34, + 0xffff088b, 0x06008013, 0x99afffff, 0x5100ff99, 0x71821e45, 0x4821142c, 0x0200ff9f, 0xffaa0080, 0x2d83f0ff, 0x48e11630, 0xfcffff08, 0x00ff33b3, + 0xff0c2005, 0xdc83f8ff, 0xf4bf0025, 0x82fbffff, 0xfbff2309, 0x1e8200a0, 0x9919d627, 0x1ed6ffff, 0x266c82b8, 0xfff628d5, 0x83e12a00, 0x61fc2877, + 0x0300ff47, 0x828500a0, 0x826020a3, 0x83fd203a, 0xbffb2278, 0x203082f4, 0x2d9282f3, 0xb85eedff, 0xe6ffff8d, 0x00ff48a1, 0x9d826010, 0xb89eef22, + 0x0320fa82, 0xfc292583, 0x898f00c0, 0xfdffff8f, 0x215e83c0, 0x1d82e0fd, 0x1783fe20, 0xd582fd20, 0x0e88f782, 0xb5261e84, 0xffffb85e, 0x7d839e9c, + 0x21c0f82d, 0x5af6ffff, 0xfeffffe2, 0x827e21e0, 0x225783b2, 0x823333f5, 0x610e2757, 0xe3ffff48, 0xe4820080, 0x15840520, 0xffb81e25, 0x82200b00, + 0x21f9244a, 0x828b9748, 0xff1e2921, 0x00ff06be, 0x8b008008, 0x21200582, 0x03249582, 0x91910060, 0x26201882, 0x22210c83, 0x30d382a1, 0x3e0a3600, + 0xff93ffff, 0x01ff05ff, 0x069a195f, 0x24a282ff, 0x4d00ff64, 0x205683c0, 0x21a18310, 0xd483def3, 0x4e51fa20, 0xdfff2207, 0x21c18240, 0xc1830400, + 0x00a0f825, 0x840900ff, 0x217682cb, 0x90820700, 0x60821883, 0x2e831a20, 0x60841120, 0x202e0839, 0xfd0400ff, 0x86958d70, 0x4c0700ff, 0xe9fb08ce, + 0xb30d00ff, 0x67ff1533, 0xef2205a7, 0xc182cdcc, 0x45830320, 0x8340e921, 0x82002075, 0xfbff2155, 0xfb260f83, 0xff8800c0, 0xdc82fcff, 0xe0010022, + 0xff297582, 0xff66c6ea, 0x32b30a00, 0x050e4205, 0x4cf5ff23, 0x210a82ce, 0xf38280fb, 0x3233fe22, 0x99272a82, 0x00ff8e99, 0x8233b300, 0x9a192171, + 0x56838782, 0x83160021, 0xefff2dcc, 0x00ffcd6c, 0x05672610, 0x0200ff88, 0x00245d82, 0x9000c001, 0xb9832782, 0x2c827282, 0xff222782, 0x83840300, + 0xf9820a20, 0x83140021, 0x82268337, 0x25938215, 0x01600500, 0x8983ff8b, 0x30829384, 0x48210a25, 0x84ebffff, 0xe1162130, 0xfc200a82, 0x04263084, + 0xffffd603, 0x6d824cff, 0x9a990123, 0x26c08286, 0x083333fd, 0x888b04f7, 0xb9de21f0, 0xa121f0ae, 0x27e58246, 0xffb89eeb, 0xb85ef5ff, 0xfc210a82, + 0x82f08360, 0xfbff23b8, 0xf08300c0, 0x04229d83, 0xf08e0020, 0x82008021, 0x482121f0, 0x0020f0bb, 0xde20f0a4, 0xff249982, 0x00ffce4c, 0xe583f0c1, + 0xa10a0023, 0x9df04048, 0xff640626, 0xcc4cffff, 0x9c20f083, 0x0807e141, 0xf8af0e38, 0x8201ffb4, 0xff15b85e, 0xd8e31e00, 0xffa48b07, 0xa430e3ff, + 0xfd0c00ff, 0xe7ffff70, 0xffffd8a3, 0x080080f4, 0x7847ffff, 0xa8ffff50, 0x00ff00c0, 0xff34330f, 0x09829900, 0x801eff33, 0xa1ffff00, 0xff08b85e, + 0x48610000, 0x00ff8b07, 0x20168311, 0x220482f1, 0x82400e00, 0x40ee231b, 0x3b828b00, 0x50540683, 0x82ff2005, 0xff8b221b, 0x821082ff, 0xf5ff2516, + 0x0564fcc2, 0xf7200e82, 0x00212b82, 0x56048207, 0x072205fe, 0x35829ad9, 0xf0200024, 0x851806a4, 0x6e180d3d, 0x0426098f, 0xff5cf707, 0x32825c00, + 0xcc260026, 0x6effffcc, 0x00218982, 0x20db83bd, 0x208e844c, 0x26a3830c, 0xffe2fa04, 0x82b30700, 0x800b22ad, 0x2a9c8200, 0x08cc4c0c, 0xffff07af, + 0x821e05d1, 0x2da48282, 0x5e8fd8ff, 0x21f9ffff, 0xddffff48, 0x7382b89e, 0x82d7ff21, 0x00002215, 0x22ba8220, 0x827c14de, 0x8360207c, 0x22f98209, + 0x821e0800, 0xc2ff21e5, 0x0f2a6683, 0xffff9a19, 0xffcd4cc5, 0x5b820d00, 0xb39cff34, 0xff086333, 0x00802200, 0x00fff107, 0xff48a125, 0x26824000, + 0x1ef1ff24, 0x487effb8, 0xe0f02205, 0x20208200, 0x822c833c, 0x00ff230a, 0x4082993b, 0x6666f225, 0x836300ff, 0xe62722b1, 0x201e8266, 0x9f3f823d, + 0xff8b229a, 0x20968fff, 0x865a8220, 0x8d6f8296, 0xffff2496, 0x84ffffd7, 0x8401209a, 0x9095829a, 0x48e1219a, 0xec829a85, 0xcc21968f, 0x2b1a82cc, + 0x079ad944, 0x40c6ffff, 0xe8ffff00, 0xff223f82, 0xbb8259d5, 0x6a83f820, 0x9a99dc29, 0xffff088b, 0x823e0ac1, 0x0fc83196, 0x1b00ff5c, 0xffff0a17, + 0xff32b3fe, 0x3e4a0000, 0x212c3b82, 0xff070040, 0x66e62b00, 0x8ff4ffff, 0x3a2a1f82, 0xffff3433, 0xffd8a3ce, 0x13829900, 0xab42002d, 0x14fc0884, + 0xa1b5ffff, 0x18ff1548, 0x200a2598, 0x9c4f1800, 0x82072011, 0x4216837f, 0x5a82050e, 0x4c4a0820, 0x6f168205, 0xcc2213ec, 0x1683ffcd, 0x33255482, + 0x8b088b33, 0x245e8bcb, 0x08948b92, 0x2147848b, 0x568500ff, 0x00204482, 0x56ae4f83, 0x8353cb21, 0xcd4c2156, 0x08ae9718, 0x2111a270, 0x6382cd4c, + 0x829a1921, 0x82b3206d, 0x82068587, 0xcd4c2411, 0x82828b84, 0xf7ff2384, 0xa8823433, 0xcc21ad84, 0x24ad87cc, 0xc03f00ff, 0x28b1d400, 0x74f72f0e, + 0xe6e000ff, 0x435d8266, 0x99431492, 0x43ff2005, 0xf12905bb, 0x00ff00c0, 0x8b00c011, 0x85068508, 0x431b8316, 0xc08205e7, 0xe6100026, 0xf1ffff67, + 0x0027c082, 0xff99190f, 0x8233eeff, 0xff7b2ae6, 0xb81e7f00, 0x1800ff15, 0x23408280, 0x0572bd4a, 0x0806ef49, 0x00400b27, 0xa2f6ffff, 0x0b00ff8f, + 0xffff703d, 0xff4841f4, 0xb89efeff, 0x98ffff08, 0xffff29dc, 0x3b00c0f3, 0xc7a6ffff, 0x228582ae, 0x829a9995, 0x8dff275e, 0x00ff9a19, 0x2782215d, + 0x66e6a227, 0xde7200ff, 0x218c82b9, 0x5782e7ff, 0x45b5ff27, 0xffff051e, 0x205283fc, 0x22a883f4, 0x82715d09, 0x02c02152, 0xbe265c82, 0x0100ffb8, + 0xb6824661, 0x713d6625, 0x820c00ff, 0x50002123, 0x59223f83, 0xba823433, 0x66666a22, 0x00215b82, 0x20118272, 0x235684ff, 0xffb81e5d, 0x29086a83, + 0xff9b088b, 0x48e100ff, 0x608b5615, 0x08c08bb6, 0xb6b6c08b, 0xc0088bc0, 0x8b60b68b, 0x568b0856, 0x8b566060, 0x9cf70e08, 0xdc8254f8, 0x184c0d21, + 0x2109db74, 0xb2820040, 0x00c0f222, 0xf527c982, 0xff079a59, 0x19665000, 0x221cb357, 0x1834b302, 0x181c984a, 0x2512db4f, 0x9a197ffe, 0x5818ff06, + 0x1f24085c, 0x4c0e00ff, 0x0c2b4e18, 0x00ff3325, 0x84e13a0f, 0x00ff2516, 0x8b1fc510, 0x0322fe82, 0x6782cd8c, 0x717d0d22, 0x00249185, 0xffc3753f, + 0xc22a0482, 0x804f00ff, 0x0d00ff00, 0x2482727d, 0x66a60a24, 0x0c828b07, 0x11824020, 0x99990b26, 0xc00a00ff, 0x0c220982, 0x41836766, 0x66e61030, + 0xffff058b, 0xfb9a1937, 0x06cb15b4, 0xdc8214fb, 0x01002826, 0x0714f706, 0x30220d86, 0x0d8866e6, 0x0985b320, 0x7bffff22, 0x5e66e518, 0x3ffeff3a, + 0xff069a19, 0xcdccf2ff, 0xf3ffff8b, 0x00ffd98e, 0xff343309, 0xfce9fbff, 0x8022c982, 0x0a830800, 0x0a84ba20, 0x1800ff21, 0x230a69e5, 0x00ff29bc, + 0x1b69e518, 0xffff2808, 0x00ffa4b0, 0x08ce4c00, 0x4c8400ff, 0xff0e07cc, 0x6666ff01, 0x47ab01ff, 0xffff15ae, 0xffb85ef4, 0x0040d9ff, 0x83e9ffff, + 0xf3b63804, 0xffff7032, 0x080100b4, 0xfdffff92, 0x00ff00e0, 0xff486106, 0x8220feff, 0x83052009, 0x60fe2120, 0x00228882, 0x3082a004, 0x0482fe20, + 0xc0030022, 0xfc260982, 0x00ffbe9f, 0x2882c101, 0xbf9ffb22, 0x01206682, 0xff213882, 0x08815efb, 0xbefffa22, 0x28834c82, 0x42c0fb22, 0xe921c682, + 0x207382de, 0x200f83d5, 0x262383c3, 0xff327391, 0x8221c4ff, 0x66c2243d, 0x828a0868, 0x203e836d, 0x823483fe, 0x8a8a2662, 0xffff3f08, 0x233283b3, + 0x8b9a9984, 0xe6260a82, 0x4c00ff66, 0x48824801, 0x00271583, 0x8b48214c, 0x827b00ff, 0x820a83c7, 0x3433241a, 0x828c8c08, 0x0060218f, 0x20220583, + 0x91828c00, 0x2e723d3a, 0xd83b00ff, 0x6e00ffd4, 0x00ff6766, 0xffae873c, 0x9a992900, 0x211600ff, 0x00214882, 0x28da8204, 0x00400200, 0x0000ff90, + 0x20ea8240, 0x82f48604, 0x83042039, 0x21ff84a2, 0xea836003, 0xea833f20, 0xfb220983, 0x1e82fa7e, 0x82a00121, 0x82fa2014, 0x058c4ab0, 0xb87ef928, + 0x200200ff, 0x1a828400, 0x48e14b28, 0x4900ffa6, 0x65821e05, 0x0021ec82, 0x06b44726, 0x05201a82, 0x01200f83, 0x06200483, 0xfe23f783, 0x84ff1480, + 0xfbff2383, 0x1e83ecbf, 0xff3c2a26, 0x8ae1fbff, 0x99348d82, 0xf9ffff98, 0xffff06c1, 0xffce4cff, 0xb85efaff, 0x3fffff08, 0xfe244882, 0x15b89ed5, + 0x4626f782, 0xffff48a1, 0x75829ec6, 0xb85e3928, 0x61b9ffff, 0x21828b48, 0x0040b923, 0x8216828b, 0x821b8360, 0x2017820a, 0x24068308, 0x00ff703d, + 0x22e18239, 0x82c2c6ff, 0x454620eb, 0x47200508, 0xff25e283, 0x00ff9a19, 0x23098238, 0x34333900, 0x47265882, 0xfb0832b3, 0x6382ab14, 0x83eeff21, + 0x83f12059, 0x82048468, 0x0dff480e, 0x180e0021, 0x82080ab0, 0x83112038, 0x820e208c, 0x45168363, 0xf94c086c, 0xfcff2b09, 0x859100a0, 0xff859108, + 0x58830300, 0x9af9f622, 0xf8229982, 0xf8826666, 0xcccc2023, 0x2771833b, 0xffbe1ff7, 0xa8c6f8ff, 0xe0260482, 0xf7ffff42, 0x71830641, 0x8320f721, + 0xe0f827d5, 0x0700ff00, 0x6a828420, 0x7cdf0822, 0x0021d582, 0x21238208, 0xbf830700, 0x37820720, 0xe1080023, 0x232d8247, 0x3eca0800, 0x072b2282, + 0x8b833333, 0xaf0e0883, 0x845b54f7, 0x34332159, 0x4c213d82, 0x215982cd, 0xbc46cccc, 0xab082205, 0x21088206, 0x2d85cdcc, 0x0b965a18, 0x0744f731, + 0x44fb064b, 0xf8f4f707, 0x066b1584, 0x490784fc, 0x082311d7, 0x858b00c0, 0x08bd4741, 0x40070022, 0x0020a882, 0x08221982, 0x404a64f8, 0x4a6f8309, + 0x33260540, 0xfc088b34, 0x4418fb74, 0xf72c5d02, 0xff152b34, 0x9a19cdff, 0xd2ffff06, 0x25087b83, 0x0534332d, 0xe6f3ffff, 0x0c00ff66, 0xffff3233, + 0xff33f3ef, 0x9a990600, 0xff088b7a, 0x0040edff, 0xeeffff06, 0xe18248e1, 0xb8deef2b, 0x33f9ffff, 0x087f7f34, 0x2130827f, 0x0d8248e1, 0x82ae4721, + 0x65e62130, 0xee2e1d82, 0xff08b9de, 0x52f8ffff, 0x2600ffff, 0x5e470566, 0x0b046f12, 0xb85e0e23, 0x0a5e47ff, 0x0000ff28, 0x00ffb91e, 0x8a82b364, + 0xe0000023, 0x06725f00, 0x83c00021, 0x00202109, 0x13841e82, 0x0800a026, 0x211d00ff, 0xd5257882, 0x5305cc0c, 0x20649207, 0x05c347c0, 0x18b99e21, + 0x210874e4, 0xc3470040, 0x00ff2406, 0x82008038, 0x050f4f33, 0x194ffd20, 0x83fb2008, 0xde082209, 0x20be82b8, 0x2de282d6, 0x00403d00, 0x5000ff05, + 0xff0748a1, 0xe5831400, 0xb81eeb22, 0x092c1082, 0xffff852b, 0x9748e1f6, 0x0c00ff86, 0x2305e348, 0x06008039, 0x4c193048, 0xcc21051f, 0x48e884cd, + 0x6b2b0630, 0xfb1554f7, 0x06cb0734, 0x180754f7, 0x820f65cf, 0x052d4cba, 0x158beb26, 0x801f00ff, 0x202cfb82, 0xff0566e6, 0xb81ee1ff, 0x6665ffff, + 0xfb270a83, 0xffff14ae, 0x826866ea, 0xce4c3075, 0x4cefffff, 0x1200ffcc, 0x088b6666, 0x840f00ff, 0xbd0c27e8, 0x0900ff70, 0x38440020, 0x15002305, + 0x1a824841, 0x5c0f0122, 0x45822b82, 0x20058c58, 0x235a82f2, 0x9a191100, 0x221aed48, 0x8240eeff, 0x820e2042, 0x051b6104, 0x081b1b49, 0x0734f837, + 0x6b0654fb, 0xf72f0e07, 0xff15dbc4, 0xcd4cc8ff, 0x2600ff06, 0x00ff3373, 0x0534b359, 0xf00200ff, 0x0600ff20, 0xffffe8db, 0xffdcc7fd, 0x22fb0700, + 0xf8f9ffff, 0x22a28224, 0x8208d863, 0x6ce7210a, 0x6c200a82, 0xf7260982, 0xfffffabe, 0x28829bff, 0xf668fa29, 0x14fbffff, 0x82fb0812, 0xe69021ef, + 0xfa22fa83, 0x12828df7, 0xfe201c83, 0xf8229683, 0x598274f3, 0x82115821, 0x1ec5213f, 0x0222e382, 0x24629358, 0xf7052206, 0x212882cf, 0x7382b8de, + 0x83f0a721, 0xab372be3, 0xffff06c7, 0xffcd8cd9, 0x0b6fa6ff, 0xdf0f2105, 0x24212b82, 0x26408218, 0xffff2438, 0x82de04f8, 0xdc07212b, 0x9c213582, + 0x214a8328, 0xaa8287d6, 0xffccf024, 0xa8770300, 0x02002107, 0x23052448, 0x8bf0c703, 0xc0261682, 0x0100ff00, 0x3f82f853, 0x82beff21, 0x00a02904, + 0xff14f708, 0x9a196f00, 0x0522ed82, 0xce827208, 0x5c826420, 0x26830120, 0x8c0c0722, 0xa7214c82, 0x266182f0, 0xff08e23a, 0x8287feff, 0x2d07270a, + 0xfaffff4e, 0x28829a19, 0xff210482, 0x05716ef9, 0x824c4521, 0x668d2372, 0x2b821566, 0x959a9922, 0x00231c85, 0x8234b30b, 0x7c0c2072, 0x2324050e, + 0xffff4861, 0x2105bf71, 0xcf71b89e, 0x23538205, 0x060020fa, 0xac219582, 0x253382cc, 0xff343302, 0x33840a00, 0xcc4c0b23, 0x08445d08, 0x66e6fa29, + 0xffff868b, 0x850040ff, 0x31e78205, 0xff676609, 0x48e1f2ff, 0xb30500ff, 0xff8b7b33, 0xb77aeeff, 0xded32105, 0x98835a83, 0x8221dc21, 0x82d3206e, + 0x7b082239, 0x216d8206, 0x248247a1, 0x825ee321, 0x66e3221d, 0x200a8266, 0x05ba4adc, 0xb81ef322, 0x1d26ab82, 0xf4fffff4, 0xbb82cd4c, 0xff5f9a2c, + 0xae07f6ff, 0xd5ffff08, 0x0a828f42, 0xff00402b, 0x1f05e0ff, 0x00daffff, 0x20358201, 0x209683d2, 0x7e6e18ff, 0x00ff2a14, 0x063eca0c, 0xf7fbffff, + 0x2651828d, 0xfffffc69, 0x82707dfc, 0x6ce72609, 0xd4fdffff, 0x26a882fe, 0xff0832c8, 0x82fdf8ff, 0xa3122214, 0x080f82d6, 0xff715d2b, 0xec511500, + 0xf70e00ff, 0x0d00ff0a, 0xff085c0f, 0x67e67f00, 0xe66f00ff, 0x00ff0566, 0xff0ecd08, 0xafc70700, 0x330b00ff, 0x2b2e8232, 0x00ff9919, 0xffcecc0a, + 0x9a19ffff, 0x0a282982, 0xff8ba430, 0x90c20900, 0xd3216882, 0x262e8275, 0xffff5c4f, 0x8293f8f9, 0x3a12271a, 0xf2ffffe2, 0xcf82e1ba, 0xffae8730, + 0x852be9ff, 0x21f7ffff, 0xeaffff48, 0x8282d863, 0x86abec25, 0x84d2ffff, 0x31072863, 0x00ff06ec, 0x82d8e313, 0x0f12214a, 0xf3204082, 0x0627b383, + 0xffff50f8, 0x826866ed, 0x4307274a, 0xefffffd4, 0xd7827c1f, 0x8234b321, 0x82332014, 0x19f42204, 0x215e829a, 0x1e82cccc, 0x66e60c22, 0x17c8cd18, + 0x2d265182, 0xff6b34b3, 0xb1822500, 0x4cd5ff23, 0x27ac82cc, 0x0e0833b3, 0x3801ffef, 0x01280c82, 0x15f6e89f, 0x4c51ffff, 0xfb2dd082, 0xffffb8de, + 0xff666676, 0x86eb6cff, 0x2314838b, 0x072108cc, 0xf7200882, 0x00236e82, 0x19fc2907, 0x20089393, 0x06984604, 0x820ad721, 0x2807225e, 0x0bda46f6, + 0x6a00ff24, 0x358266e6, 0x338f0026, 0x7500ff33, 0x78230483, 0x84ffcd4c, 0xfdff230e, 0xae829a99, 0xb9838b20, 0xff290a82, 0x00807000, 0x198effff, + 0x25648299, 0x08cd4c74, 0x9f1804fb, 0xab20172b, 0x0821df82, 0x279f18d6, 0x83f72012, 0xb3002232, 0x82b583e6, 0x90002acf, 0x48fb9042, 0xc0fbffff, + 0x27688200, 0xff343301, 0xd7e33fff, 0xbb20e182, 0xff268382, 0xff9999fc, 0x9282cbff, 0xb3c4ff23, 0x28738234, 0x083233bb, 0xb393ffff, 0x83e58934, + 0xccf8221c, 0x05b747cc, 0x2219c047, 0x846d00ff, 0x22003735, 0x00ff5c0f, 0xff66a619, 0x3eca1d00, 0xfd2100ff, 0x0200ff72, 0x7c828e42, 0x8e422522, + 0x7d240a82, 0x1f00ff70, 0xe222ef83, 0x71826866, 0xcc4cdb22, 0x4826e5b9, 0xff4e34b3, 0x9d823a00, 0x80b6ff28, 0xfcffff00, 0xbe82cd4c, 0x34b3ff27, + 0x196000ff, 0x22e48299, 0x82323386, 0x66662b15, 0x99a0ffff, 0x98ffff9a, 0x7282cecc, 0x9a198622, 0x94222582, 0xe4b2cccc, 0x9a196c22, 0x00273582, + 0xffd6a356, 0x823d4300, 0xdc4926ca, 0x5600ff2a, 0x20f3828f, 0x2b7c8203, 0x0300ffe6, 0x00ff6566, 0x4234334b, 0xa5226982, 0xdcb934b3, 0xcdcc7d25, + 0x8297ffff, 0x650028db, 0xffff67e6, 0x82686681, 0x332208ca, 0xef0e0832, 0x01ffb4f8, 0x1566e600, 0x5800ff8b, 0xffffb85e, 0xff4861b8, 0xe2ba4600, + 0x85a8ffff, 0xdb828b1e, 0x34331e24, 0x0d85058b, 0x47201d83, 0x66210482, 0x3a8f8266, 0x080080a8, 0x060000ff, 0xc0ffff66, 0xff051f05, 0x98191f02, + 0x3f00ff06, 0x8207e1fa, 0x00e03316, 0xfeff158b, 0xffcc4c90, 0x34b31400, 0xecffff15, 0x04820040, 0x0548a126, 0xc00400ff, 0xe4220a82, 0x0a8200c0, + 0xf3bf0026, 0x20fbffff, 0xfa230f82, 0x4fff0de0, 0xfb260543, 0x00ff00a0, 0x5d826002, 0x80e7ff22, 0x0c2d0a82, 0xff05b8de, 0x3373e7ff, 0x33f3ffff, + 0x2a0a8233, 0xff1ec5fb, 0x9999fdff, 0x82faffff, 0x03002349, 0x708234b3, 0x05220983, 0x9282cccc, 0x00225e83, 0x5e82401b, 0x00217484, 0x05f15513, + 0x0224d783, 0x918d7c94, 0xde218082, 0x213182b8, 0x2c8232b3, 0x48611b23, 0x2087828f, 0x219d820c, 0x68831800, 0x82020021, 0x0400218d, 0x06207883, + 0xff220482, 0x8282e0ff, 0xb9fe0122, 0xa020a682, 0x00239282, 0x82e13a0c, 0x8321208c, 0x661b25c7, 0x90058766, 0x2405e34b, 0x67e60100, 0x066e7f85, + 0x8380fc21, 0xff8f2328, 0xf79a8bff, 0xf788f220, 0xf7920e20, 0xd2827320, 0x8483f786, 0x6f83f320, 0xccfbff23, 0x21f782cd, 0xf78284ab, 0xff33b322, + 0x1382f786, 0xf7860020, 0x1a231483, 0x41056666, 0xf787056c, 0xbf826020, 0x00800328, 0x0500ff8d, 0xfb827eff, 0x0022cf83, 0xfb833a9f, 0x82666621, + 0x9002210f, 0xb820ffa3, 0xe220ff89, 0x5e22ff88, 0x3b8287b8, 0xae070522, 0x20080341, 0x0b034166, 0x4124f721, 0xf8413900, 0x0a00410a, 0xff00c025, + 0x82a0fdff, 0x05f84104, 0x00220e82, 0xdf82c000, 0x00e00422, 0x4119f841, 0x5e211a00, 0x24fc41b8, 0x4020fc89, 0xe7207b82, 0x8505fc41, 0xfd0422fc, + 0x25fc8272, 0x00ff4861, 0xfc8ce601, 0x9f00ff3d, 0xffff34b3, 0x15cc4c6b, 0xff058b6b, 0x7433f7ff, 0xf9ffff8b, 0xfffff4b2, 0x820ecdf8, 0x19f8290a, + 0xffff0858, 0x079002c0, 0xf7220c82, 0x17828440, 0xff23ca82, 0x82e2a5f9, 0x68262209, 0x181c828b, 0x21072464, 0x9b4cff68, 0xd9072206, 0x2216829a, + 0x48fcf7ff, 0xfd2206cc, 0x63825bdd, 0x70fdff28, 0x60ffff05, 0x3c5c66e6, 0x66662109, 0x2006e061, 0x05094b10, 0x82da4021, 0x33fe2255, 0x09405c34, + 0x5ca47021, 0x3f2d0d40, 0xff07e2fa, 0x9919bf00, 0x040000ff, 0x864f8254, 0x058c5c99, 0x5c285c21, 0x40220d8c, 0xf6823e0a, 0x88acfc21, 0x800d224f, + 0x224f8700, 0x8334b310, 0x54f526a4, 0x026000ff, 0x20218290, 0x212c8420, 0x5482d8ff, 0x00c0d422, 0xd63aa483, 0x00ffc235, 0xfff6e81d, 0x90c2d9ff, + 0x912900ff, 0xfbffffea, 0xff0814ae, 0xe0833100, 0xc018fb32, 0xb32800ff, 0x2500ff34, 0xff8b9a99, 0xcccc2f00, 0xa1831a82, 0x07220c82, 0x2a4784eb, + 0x9a193807, 0x33f7ffff, 0x0e088b34, 0xf724f7ef, 0x00ff1534, 0x069a199c, 0x821600ff, 0xecff228c, 0x2a3f8233, 0xff32331d, 0xccccf3ff, 0x5f2000ff, + 0x0683054e, 0x0c207a82, 0x0c211182, 0x27b28240, 0xff48a116, 0x00c01300, 0x3c225f82, 0x3b82b81e, 0x68e63d22, 0x32266482, 0x00ff9819, 0x7c831932, + 0xd9493d20, 0x24068205, 0xdecdffff, 0x2b1684b8, 0x21c2ffff, 0x79088b48, 0xefffff8b, 0xff244582, 0x7c0060fb, 0x81219482, 0x2ff88248, 0xff9ad9e6, + 0x1e052e00, 0xb3d1ffff, 0x1e00ff32, 0xc920a483, 0x62207c83, 0xdb202d82, 0xee252d83, 0xffff00c0, 0x210483e5, 0x788280e4, 0xcce5ff26, 0x1b00ffcd, + 0xdb29b383, 0x00ff3333, 0x62004011, 0x2248828b, 0x820080b0, 0x83bf2031, 0x82048217, 0x2010820a, 0x57068508, 0x168206d6, 0x4f00ff22, 0x082a2682, + 0x1544fb83, 0x198fffff, 0xee820699, 0x8233b321, 0x82f52025, 0xf5ff214a, 0x10837782, 0x37833220, 0x8e83f320, 0x6b820a20, 0x66f3ff28, 0x0c00ff68, + 0x6582cd4c, 0xe6700023, 0x21f58267, 0x3382330d, 0x1c830020, 0xcc240482, 0x0d00ff8b, 0x8205357e, 0x82ff2006, 0x22958245, 0x52cccc0a, 0x082605e4, + 0x15eb74f8, 0xf252a4fc, 0x2068a508, 0x833082f8, 0x0d781854, 0x824e8207, 0x4c0c220a, 0x829982ce, 0xffce258a, 0x9c19f6ff, 0x99219482, 0x2a658398, + 0x4b088bcc, 0xfeff152b, 0xaf9a19bf, 0x400123d0, 0xd08466e6, 0x6a993420, 0x3433f522, 0x0e216a8b, 0x290e82f7, 0x159a197d, 0xe6d200ff, 0x37820766, + 0x57b30821, 0x0022060c, 0x0c574c07, 0xcb841807, 0x82b3200d, 0xf7ff325e, 0xff08cc4c, 0x9a192dff, 0xedffff07, 0xffff6666, 0x2d0483f9, 0xff9999f2, + 0x6666eeff, 0xebffff8b, 0xdf829a19, 0x80e5ff24, 0x7074ff00, 0xe6142129, 0xf2254982, 0x00ff9a99, 0x84048211, 0x06003158, 0xf7089a99, 0x4201ff94, + 0xff1566e6, 0xb81ecbff, 0xd4225c82, 0xa51848e1, 0xcb250ee0, 0x00ff4821, 0x2a04822b, 0xb8ded4ff, 0xde3400ff, 0x85088bb8, 0x83168506, 0x82dd821b, + 0x83958217, 0x823f821e, 0x2732856c, 0x8b9a19cb, 0x14fb8b08, 0x570c9057, 0x11210d62, 0x06744ec0, 0x23521683, 0x82158208, 0x400e2354, 0x515bff00, + 0x06fa4f0a, 0xccf1ff23, 0x2a1684cc, 0x33eeffff, 0xfb088b34, 0x82159b34, 0x833d202c, 0x054c43ba, 0x43b81e21, 0x0685064c, 0x20056343, 0x821b82ff, + 0x21c22941, 0xffff0848, 0x07008059, 0x2105d246, 0x6483e7ff, 0x8582f320, 0x40e1ff25, 0x43698b00, 0x1443170d, 0x05244305, 0x80400023, 0x20718200, + 0x05d3704f, 0x9a192124, 0x4083ffff, 0xc71f0023, 0x275485ae, 0xb89e1800, 0xa600ff08, 0xfb236582, 0x82e4fb04, 0xded322fe, 0x277c82b8, 0xff4821dc, + 0x48e12300, 0x2c223c82, 0x6a82b81e, 0x80190022, 0x0c20fe82, 0x00228282, 0x35446117, 0x00ff2305, 0x3c83de0e, 0xcc4cc022, 0x175e6118, 0x0b057618, + 0x73eaff23, 0x22598234, 0x540080e5, 0x0723050e, 0x831300ff, 0x83f120cc, 0x22588353, 0x8280e8ff, 0xe6ff21ac, 0xff26ac84, 0xff32f3d3, 0xb183dcff, + 0xd3240484, 0x088b66e6, 0x200aab42, 0x32ab4212, 0xb81eed22, 0x8208ab42, 0x42ff20c3, 0xeb2357ab, 0x4ad200ff, 0xea410554, 0x008021f8, 0x2109ea41, + 0xea4168e6, 0xb85e2112, 0xea412082, 0x7ad42107, 0x2310ea41, 0x54f8a4f7, 0x27bcec43, 0xfff4f70e, 0x66e66000, 0x2d08c482, 0x0600c0b8, 0x702f00ff, + 0x6900ffa4, 0xff056666, 0xe00f0300, 0xc70600ff, 0xfdfffff0, 0x00ff10f8, 0xff6c0708, 0x2010faff, 0x800400ff, 0x0a820800, 0x82f00721, 0x10782b0a, + 0xbff7ffff, 0xffffffbe, 0x1382cfd7, 0xffae4726, 0x2438fbff, 0x66281e82, 0xffff6666, 0x05010080, 0xd8201582, 0xfb252482, 0xffff20b0, 0x275282fe, + 0xeae6f8ff, 0x500200ff, 0xf9230e82, 0x8208a4b0, 0x8247200a, 0xa7f92362, 0x3a8291f0, 0x82b4c821, 0xbebf2272, 0x2116828b, 0x8f824047, 0x8fd0ff28, + 0x96ffff5c, 0x46829a99, 0x21f0fc26, 0x38f9ffff, 0x02228a82, 0x7582ef07, 0xff94f829, 0xe0ef0500, 0x83fbffff, 0x0200288f, 0xffff1ae4, 0x82def2fc, + 0x00802150, 0xe6216a82, 0x529e8266, 0x03230515, 0x828bf0a7, 0x00a025cf, 0x400100ff, 0x02200482, 0x0222cf83, 0x65821078, 0x9a999924, 0xec8214f7, + 0x83270521, 0x824f20cd, 0xf00121f1, 0x0722e282, 0xf6821619, 0x0e82af20, 0x5c4f0622, 0xfd28cd82, 0x00ffdcc4, 0x856a5c06, 0x19217282, 0x2986829a, + 0x088b3433, 0xdf00ffcb, 0x26729a19, 0xff2b08c7, 0x48a12e00, 0x8c00ff06, 0x00ff3433, 0x05cdcc74, 0x9a0800ff, 0x0700ffe2, 0x00ffec31, 0xffccec0a, + 0x0af70300, 0x3a0b00ff, 0x82088be2, 0x0a572210, 0x2605828b, 0xffff9042, 0x828195fc, 0x146e262a, 0xaef9ffff, 0x081a8298, 0xc2f51126, 0x63f2ffff, + 0x0600ffd7, 0xffff5c0f, 0xfff628e8, 0x72bdf6ff, 0x7febffff, 0xffff08ff, 0xffead1e4, 0x58b9c3ff, 0x55225f82, 0x9a72cccc, 0x2f0e2c0e, 0xcc9701ff, + 0x9501ffcc, 0x8215f6e8, 0xf087217b, 0x8f264582, 0x0200ffde, 0x6e8262b0, 0x82da8e21, 0xce77266e, 0x610900ff, 0x224a8248, 0x82ae9cfb, 0xfa5e220a, + 0x22248282, 0x82811038, 0x91fe2197, 0xff2a7283, 0x7e05fcf7, 0xf5ffff8b, 0x04820a57, 0xffba9e27, 0xf6a8ffff, 0x2c30827e, 0xff5e4aff, 0x5e17e5ff, + 0xe60100ff, 0x219a8204, 0xd5829a19, 0xff93982d, 0x703deaff, 0x6101ff08, 0x820666e6, 0x140e2650, 0x380f00ff, 0x30048252, 0x00ff0080, 0xff866b11, + 0x66661800, 0x401500ff, 0x35438200, 0xff68e6eb, 0xa43066ff, 0xe9ffff15, 0x00ffe2fa, 0xff7a5419, 0x7682efff, 0x8a130023, 0x8269823e, 0x170029fd, + 0xff085c0f, 0x9859affe, 0x0b264e82, 0xffff5278, 0x698299d7, 0xf6e81225, 0x83e1ffff, 0xc5162729, 0xe7ffff1f, 0x73820a57, 0xcccc5926, 0xf8ffff06, + 0x09235f83, 0x8283b8de, 0xcd4c217e, 0x4c200f82, 0x082de482, 0xff0867e6, 0x66e6abff, 0x99defeff, 0x226f829a, 0x8200e0fe, 0x48e12acf, 0x5f0500ff, + 0xf6ffffbe, 0x25fe8347, 0xffffe630, 0x6f828ffb, 0x42030028, 0xfeffff8e, 0xd3824661, 0xff236e82, 0x823433ff, 0x05397d09, 0x10380630, 0x0600ff8b, + 0x00fffa1e, 0xfff06702, 0x20820400, 0x98040028, 0x00ff0810, 0xc482ba2b, 0x289c2b30, 0x971d00ff, 0x2800ff0a, 0x00ff2005, 0x59820710, 0xb85e2522, + 0x6b227e82, 0xc4826666, 0xc2b50f22, 0xa483b082, 0xfe830720, 0x3e82e020, 0x82faff21, 0xd2ff2898, 0xff0834b3, 0x82198000, 0x33e626de, 0xfeff1532, + 0x21cf83b4, 0x20831a00, 0x82ccea21, 0xb31c28c4, 0xf0ffff34, 0x82ff32b3, 0xff992513, 0xceccf1ff, 0x1c222f82, 0x1482d723, 0xff70fd35, 0x67e61900, + 0x1cf2ffff, 0x1400ff2a, 0xffffa4b0, 0x828ec2ee, 0x84ba201e, 0x78022a43, 0x0a00ff52, 0x00ff0ad7, 0xc8931800, 0x82002008, 0x0a002173, 0x2005925f, + 0x20638318, 0x269383f9, 0xffcccc14, 0x824cf6ff, 0x8013326d, 0xff0e0800, 0x66663001, 0xff1574f7, 0x34339fff, 0x22198206, 0x828b9919, 0xcdcc2205, + 0x053a5dff, 0x4482f920, 0x33f8ff39, 0xffff0833, 0xffb85ec8, 0x0100b9ff, 0x0d00ff05, 0xffff0040, 0x820080ef, 0xae09210a, 0xf3203b82, 0x00275482, + 0x8b008014, 0x820900ff, 0x0c0022a4, 0x21e98333, 0xbf7ac00a, 0xff9b2305, 0x0a830700, 0x48611122, 0x40269f82, 0x00ff0800, 0x0a822111, 0x82800121, + 0x8310201f, 0x83f72055, 0x400b2309, 0x1a827e00, 0x48a11f25, 0x59dbffff, 0xc02b0503, 0xf4ffff42, 0x00ffb89e, 0x83066113, 0x82de205b, 0x610b220a, + 0x20258248, 0x2840832d, 0x05b89e34, 0x4600ff54, 0x23888240, 0x8ec2f9ff, 0xcf216782, 0x23bd835c, 0x0400ffcc, 0xff245282, 0x8b9a19f6, 0x6e29b982, + 0x15db34b3, 0xe10c00ff, 0x20448248, 0x2744830b, 0x9500e003, 0x810600ff, 0x1d204a83, 0xc520cc83, 0xcb234a82, 0x8300ff06, 0x3a00230c, 0xd9824861, + 0x32f30a31, 0x85f9ffff, 0x0b00ff1e, 0xffffcecc, 0x829a19fc, 0x66e62142, 0x00225082, 0xea834023, 0xd4831c20, 0x54820482, 0xb2181082, 0xdc201259, + 0x2005a37e, 0x212d83f0, 0x2d82f1ff, 0x20faff23, 0x83d18200, 0x7ef62209, 0x219982b8, 0x5482d9f4, 0xf1831220, 0x82cceb21, 0x830c20b4, 0x77e72019, + 0xe9210506, 0x20638280, 0x211683ff, 0xa183f3ff, 0xcdccf426, 0x5eedffff, 0xf3223583, 0xde7167e6, 0x99f22c06, 0x0500ff99, 0xffff48e1, 0x826766ef, + 0x83ff2099, 0xffff2272, 0x823083e3, 0xff8b2104, 0x99821083, 0xdc820683, 0x1b842d82, 0x84220021, 0x012b082d, 0xff66665a, 0x3433c3fe, 0x9bffff15, + 0x00ff3433, 0x059a9980, 0xd0ffff62, 0xff05b85e, 0x9819f5ff, 0x3af3ffff, 0xffff7be0, 0x829a99f8, 0x34332161, 0xef206183, 0xff230682, 0x820cf0ff, + 0x400724ae, 0x82988000, 0x59e021c5, 0x2422c582, 0x348200c0, 0x8319fb21, 0x34b32190, 0xa4833382, 0xcc4c0322, 0xc9820982, 0xff232582, 0x82069999, + 0xbe3f240c, 0x83ffffff, 0xdef822e7, 0x066152fa, 0x0040fb23, 0x07915f85, 0x0080e427, 0x00d2ffff, 0x20ba8201, 0x232882e9, 0x00801b00, 0xf7261a82, + 0x00ffbe9f, 0x96839e0a, 0x66e69b28, 0x6680ffff, 0x84820566, 0xff96232e, 0x7cd4eaff, 0x1f0f00ff, 0xe1ffffbf, 0x00231982, 0x827d5f1a, 0xbf012aa5, + 0xff0666e6, 0xcc4c1a00, 0x211c828b, 0xb84e9c19, 0x82f02006, 0x15002bd2, 0x0e089a19, 0xf874f8af, 0x1c821504, 0x14fc4719, 0x6b18b420, 0xff230c9d, + 0x829082ea, 0x7de52f8e, 0xc4fb0870, 0x0614f807, 0xff07c4f7, 0x6d829aff, 0x33a9ff27, 0xfb331534, 0x228b8204, 0x4710f8fb, 0xfa2206bd, 0xd782f007, + 0xffd0b726, 0x5278f9ff, 0x6022c282, 0x05820840, 0xffe23a26, 0x12c30000, 0x19210982, 0x224c829a, 0x826666fe, 0xfaff23a6, 0x0c82f047, 0x4e82fa34, + 0x040200ff, 0xfbffffde, 0x00ff47a1, 0x0800c003, 0x5382bb53, 0xaec7f62a, 0xbb0700ff, 0xfeffff22, 0x1d686c82, 0x99082e05, 0xff08959a, 0xf0a70800, + 0x0f0a00ff, 0x26dd825c, 0x00ff6c27, 0x82482101, 0xae07260e, 0x67f7ffff, 0x2c1e826c, 0xff51f824, 0x5c4fe0ff, 0x4800ff05, 0x22448287, 0x82ae475c, + 0x3008220a, 0x21258220, 0x3482f668, 0x823c1f21, 0x82cf2034, 0x610a223e, 0x21348248, 0x34828ed7, 0xae830a20, 0xa0daf722, 0xcc241982, 0xf0ffffce, + 0xff287382, 0xffccccf7, 0x9a99f5ff, 0x952a1e82, 0xffff9a19, 0x15cccc86, 0x7b57067b, 0xf8ff2409, 0x85ff04d6, 0x29f72704, 0xfc088bfc, 0x6c180634, + 0x6b180b14, 0xf7230a4a, 0x187b0704, 0x180cc7ba, 0x1813006e, 0x2110ad82, 0x6d790674, 0x82ff2005, 0x05827919, 0x2005b341, 0x926d1808, 0x4e468308, + 0xe529068e, 0x088b0080, 0x02ffaf0e, 0x28b58225, 0x0080d200, 0xe0ffff15, 0x22f382c5, 0x8210b805, 0xd6632bcf, 0x570e00ff, 0xffffff4c, 0x8844c2b5, + 0xf3ff2b06, 0x00ffe2ba, 0xffa4300c, 0xee83ebff, 0x0483ff20, 0x6866f329, 0x4cf4ffff, 0x828a08cd, 0x00102a2a, 0xdce7ffff, 0xe9ffff28, 0x260982f0, + 0x8bf668cf, 0x83ffff08, 0x23168506, 0x5c0f1600, 0x59212582, 0x2150829a, 0x1a825c8f, 0x5ccff322, 0x47215082, 0x825087af, 0x92ff2089, 0x88292050, + 0x85f52050, 0x8bf52150, 0xeb225082, 0x4c82a186, 0x82cc4c21, 0x9a99214c, 0xcc214c83, 0x214c82cd, 0x4c82cd4c, 0x8233f321, 0x219d8419, 0x9d82d763, + 0x1e831920, 0x9959ff22, 0x80201482, 0xf0209782, 0xf1211483, 0x250e8299, 0xff8fc2e0, 0xbc82faff, 0xeeffff29, 0xffffb89e, 0x82dfcffc, 0x717d2b2e, + 0x59efffff, 0x0300ff17, 0x1884852b, 0x0a820820, 0x84213021, 0x00ff240a, 0x828d9710, 0x3e4a2623, 0x781100ff, 0x21188252, 0x1e82b85e, 0x7b54192a, + 0xa30400ff, 0x1300ffd8, 0x00265c82, 0xff32b308, 0x1e830d00, 0x66e60722, 0x13201e82, 0xf4207683, 0x1f2c0f83, 0xffff52f8, 0xff9ad9f2, 0xec912c00, + 0x0029cc82, 0x8bcd8c2c, 0xf01f00ff, 0x213082a3, 0x3f82b81e, 0xff908226, 0xae870b00, 0x85213583, 0x8469821e, 0x16ee2135, 0xf0213582, 0x213582a4, + 0x3584cc8c, 0x837c9421, 0x50f82135, 0x17213582, 0x8235820a, 0x83358660, 0xf8ff2476, 0x82ffe00f, 0xffd62d8a, 0x6851f7ff, 0x541900ff, 0xfbffff7c, + 0x1127a984, 0xffff5c8f, 0x8200a0fc, 0x213384c8, 0xc38210b8, 0x59823020, 0x42601123, 0x210a8208, 0xd882c435, 0xf4202e83, 0x10221e83, 0xf68233b3, + 0x82989921, 0x33332818, 0xffff8b08, 0x42cccc6f, 0xc7212227, 0x072742ae, 0xfff6e822, 0x14254082, 0x66f3ffff, 0x27cc8266, 0xff084841, 0xa6f0feff, + 0x1d251482, 0xe7ffff72, 0x201482e6, 0x200483e9, 0x05e243cf, 0x16820683, 0xffb8de22, 0x84112b42, 0x00402654, 0xebebffff, 0x823f8286, 0xf3ff2323, + 0x5488f468, 0x8254f821, 0xe21a2114, 0xf02154b8, 0x833f82a4, 0x63f322ae, 0x215482d7, 0xa9820e2f, 0x0358ff22, 0x67351482, 0xf0fffffc, 0xffffde62, + 0xff60a7f1, 0x1fc5e0ff, 0x47faffff, 0x421e82ae, 0xe0200633, 0x20083342, 0x0d334216, 0x82f83321, 0xc09d2bfb, 0x981000ff, 0xf4ffffd5, 0x3342cc4c, + 0x66662707, 0x1900ff08, 0x2f49ec51, 0x06334206, 0x33423420, 0x02202516, 0xf2ffff90, 0x33429a82, 0x65e6210e, 0x0f213082, 0x0d33425c, 0x82008021, + 0xae872269, 0x263182ab, 0x00ff66e6, 0x429a992c, 0x7a26052f, 0x1f00ff8b, 0x2f4286eb, 0x99122206, 0x0765429a, 0x271e2f42, 0xfff46812, 0x48a1fcff, + 0x20072f42, 0x21a582b3, 0x04823303, 0xc4841120, 0x74820a87, 0x00217982, 0x21578210, 0x2f42eeff, 0x08322c05, 0xfafffdff, 0xe100ffe0, 0x8215ce4c, + 0x7b5421ee, 0xa021ee82, 0x07224300, 0xb882af20, 0x21052243, 0x2243a4f0, 0x43de2075, 0x6a200822, 0x202c2243, 0x22ae822c, 0x82486111, 0xe87b2ff2, + 0xa61000ff, 0xeeffff66, 0x00ffc09f, 0xc8823003, 0x43204345, 0x43451b1b, 0x442a2009, 0xf42008f2, 0x2605f244, 0xffff8bf4, 0x432adce7, 0x50892e17, + 0x21154345, 0x50824ae1, 0x451e0521, 0x94450747, 0xcdcc2605, 0x400c00ff, 0x07474500, 0x84091343, 0x054745df, 0xf4826620, 0x23054745, 0xfffff6a8, + 0x43054745, 0x31262413, 0xeeffff68, 0x134348a1, 0x43ce2008, 0x0e240a13, 0x9c00ff2f, 0x24287d83, 0xff153433, 0x52381f00, 0x052a0484, 0xf5c3ffff, + 0x3500ffc2, 0x0a820a17, 0xc2b5cb27, 0xb8cbffff, 0x2b0a8252, 0xffa4f0f1, 0x52f8f1ff, 0x70feffff, 0xe93a0982, 0x00ff32b3, 0xff15ee0b, 0x9a19f0ff, + 0x054bbb08, 0xe60700ff, 0xf5ffff67, 0xd0820080, 0xd0820020, 0x0984fa20, 0x8b9a1929, 0x0800ff08, 0x828b5258, 0x5c6f2605, 0x9b0200ff, 0x262a82e8, + 0x00ffa430, 0x82186405, 0xb011211a, 0x0d210a82, 0x21358240, 0x1e828f03, 0x7c141926, 0xc0f2ffff, 0x112a0e82, 0xff0884ab, 0x7bd4e4ff, 0xa28200ff, + 0x43275f82, 0x00ff3333, 0x8232b3fc, 0x402c22ad, 0x224f8200, 0x1870bd23, 0x820b8f45, 0x592b2611, 0xdcffff98, 0x2147824f, 0xfb82a624, 0xb04ad320, + 0x82068305, 0xcc4c2116, 0x38830482, 0xa6d4ff26, 0xff8b0866, 0x3f820683, 0xffcdcc26, 0x9a59dbff, 0x08b25818, 0x34b3b827, 0x190e00ff, 0x20da829a, + 0x259683f3, 0xffb81e12, 0x0482e7ff, 0x42040027, 0xedffff90, 0x220e82de, 0x82b85ef3, 0x5ed7219b, 0xe32e0a82, 0xff050080, 0xb85ecbff, 0xb8ffff66, + 0x5682ae87, 0xcd4ccb23, 0x211d86b0, 0x1d841c00, 0xc3f5ed26, 0xa60c00ff, 0xe7292182, 0xffff4821, 0xff9a99fb, 0x205b82ff, 0x82258279, 0x25538249, + 0x00ff66e6, 0x1a826104, 0x8219e721, 0x00122c88, 0xf3ffff00, 0xff083333, 0x75a12800, 0x0c270839, 0xffff9919, 0x829a99f7, 0x66f921e1, 0x0d212f82, + 0x20b8824c, 0x05f856fa, 0x3333da30, 0x0654f705, 0x000000ff, 0x2500ff0e, 0x0a4dc2b5, 0x05002306, 0x7982f4dd, 0xff52f826, 0xed9c0600, 0xc6830982, + 0x5d8f0822, 0x9e855986, 0x21120023, 0x211a823a, 0x838200c0, 0xffcc4c24, 0x8d821800, 0x4cf3ff26, 0x1200ffce, 0xff225d82, 0x1482a7ff, 0x9949ff24, + 0x1a42159a, 0xcaff2305, 0x5e82f6e8, 0x52381f27, 0xc7e0ffff, 0x25fc82ae, 0xffecd1e4, 0x7483dbff, 0x82f2ff21, 0xeeff3345, 0x00ff7a54, 0xff9e8f03, + 0x86ebe6ff, 0xb01100ff, 0x1883ff62, 0x07257482, 0xffff3433, 0x21fe82fa, 0xc2820800, 0x82fdff21, 0x07002404, 0x828b0080, 0x280c231a, 0x85828bf6, + 0xffae0733, 0x18840500, 0xd70700ff, 0x0a00ff0a, 0xbb08e87b, 0x256d82cb, 0xffa4f00b, 0x4d820f00, 0x70feff22, 0x16380982, 0xffffae47, 0xffa8e6f1, + 0x7a140e00, 0xccffff08, 0x00ffc896, 0x05ec5134, 0xff24fd82, 0x94f79a19, 0x013cab82, 0xff06300a, 0xe8990200, 0x194a00ff, 0x2600ff9a, 0x00ff5899, + 0xff32f340, 0xd7a33900, 0xd9250e82, 0x00ff089a, 0x22c5820d, 0x82ec0800, 0x821120eb, 0xfbff2295, 0x22798264, 0x82991909, 0x2edd21af, 0x74201e82, + 0x5622af83, 0x818286eb, 0x66e68024, 0xa18215ab, 0xcc4c2327, 0xb31c00ff, 0x82048634, 0x188b200e, 0x20109d7e, 0x095018b3, 0x19ff200e, 0x2c0e8509, + 0x074b066b, 0xe6ffff8b, 0xffffcdcc, 0x216283fa, 0x0082ffe6, 0x32b3f427, 0xb3e8ffff, 0x22cf8234, 0x84ceccf4, 0x76ff200a, 0xea260578, 0xffff66e6, + 0x1e8233eb, 0x8219ee21, 0x230a82b5, 0xeeffff34, 0xe7200f83, 0xff218d82, 0x201e83f1, 0x223283e4, 0x82ce4cf6, 0xcce4263d, 0xf6ffffcc, 0x26338266, + 0x8666e6e2, 0x43e1ffff, 0xe3220506, 0x74820080, 0x90231282, 0x82e4ffff, 0x0900227a, 0x834c8399, 0x0900212d, 0xe7277b83, 0x00ff5c4f, 0x839a190e, + 0xff33246b, 0x83cc1100, 0x33eb214c, 0x61830a83, 0x0080ef25, 0x831500ff, 0xbdf4271e, 0x1700ff71, 0x6b82cc4c, 0x77bef422, 0xc8820a84, 0xffbc3427, + 0x01001900, 0x3005828b, 0xf8083333, 0xcb8b0614, 0x9ffeff05, 0xc4fb9a19, 0x20148215, 0x223e831a, 0x82d76316, 0x29098343, 0x8b299c19, 0x1b00ff08, + 0x1b826766, 0x82991421, 0x55ea2074, 0xd05508c9, 0x83868205, 0x821682c3, 0x999921af, 0xff232d82, 0x82d763e6, 0x9ce9221b, 0x85448429, 0xff082554, + 0x66e68001, 0x08b44418, 0x2f84ff20, 0xe5200484, 0xa2825082, 0xff200683, 0x86088c4b, 0x84068534, 0x18048646, 0x4c109e4e, 0x0e240a06, 0x3f02ffaf, + 0xa43bb583, 0xff150080, 0xb8def2ff, 0x1c2700ff, 0xe5ffff29, 0x00ff48a1, 0xffb9de20, 0x825eddff, 0x5e142213, 0x207082b8, 0x202983ee, 0x080f820a, + 0x40edff22, 0x0600ff00, 0xff780040, 0x00400300, 0x00ff9108, 0x8f00c011, 0xbd1200ff, 0x00ff8b72, 0x0800c013, 0x28250682, 0xffff70fd, 0x213383f1, + 0x0982bd27, 0xff24ae82, 0x52781f00, 0xfd274882, 0xff8e0080, 0x82e0fbff, 0x9f002244, 0x054a4a7c, 0x20feff23, 0x231a8284, 0xff00c0fc, 0x04830a82, + 0x23823982, 0x00ff8424, 0x0e822001, 0x6782fc20, 0x25066450, 0xfffe3ff2, 0x14830200, 0x9082f326, 0xf3ffff8b, 0xff276f84, 0xff2045bc, 0x823dcaff, + 0xeec8286a, 0xbdffff14, 0x828b90c2, 0x85068350, 0x37002316, 0x9682281c, 0xa4b04322, 0x0c219d83, 0x21d7821e, 0x82824002, 0x829e0c21, 0x60042109, + 0x0d200982, 0x6e854882, 0x84030021, 0x23828287, 0x7e1f0400, 0x0e82a182, 0xe0010023, 0x21508200, 0x2982a0fc, 0x82df0121, 0xdffb2db6, 0xffffff7d, + 0xffff8460, 0x888380fd, 0xe5271a82, 0xffff7b94, 0x823e8ae0, 0x666626f6, 0x42d8ffff, 0x229d828e, 0x823e0ad7, 0xecff216f, 0x03206a83, 0xff29f282, + 0xff9042ed, 0x01200600, 0x063a76ff, 0x9919ed22, 0xbd206082, 0xed20b782, 0xff239382, 0x8234b3f9, 0x23798219, 0x32b3f5ff, 0xdd2a5482, 0xffffb85e, + 0xff8f82eb, 0xa882e5ff, 0x82dfff21, 0xf2ff2347, 0x5e8248a1, 0x82d7e321, 0x82fe201e, 0xfcff2199, 0x00211482, 0x29338301, 0xff8400fc, 0x00400300, + 0x06820889, 0x89006022, 0x56095e79, 0x0021057a, 0x27c48302, 0x83600900, 0xde0a00ff, 0x0925f882, 0x00ff7d9f, 0x233f8308, 0x9100400a, 0x39203582, + 0x21200b83, 0x49221a83, 0x7982cd8c, 0xff48e124, 0xa2832100, 0x9042c522, 0x21211e82, 0x237a8221, 0xffd863c5, 0xff26d184, 0xff8e82b5, 0xbc83c6ff, + 0xce4cdd22, 0xf5208e82, 0xf9258e83, 0xffff84e0, 0x294782f4, 0xc4c0fbff, 0x1ef2ffff, 0x1a8288b8, 0x7d5ffc2a, 0x20ffffff, 0xfdffff00, 0xfc231a83, + 0x828b00a0, 0x842021f7, 0x00235482, 0x82870020, 0x82a0209f, 0xc0fc211b, 0xc026c083, 0xffffff83, 0x1a820040, 0x50832720, 0x8240f821, 0x83282014, + 0xff062c89, 0x2200ff9c, 0x00ff85ab, 0x82507d14, 0x0012221e, 0x82c88201, 0x0e0031f9, 0x00ff46e1, 0xff70fd0d, 0xba5e0c00, 0x800f00ff, 0x0c213d83, + 0x23ad8261, 0x9a0080f0, 0x02258582, 0xffff9d90, 0x201684f5, 0x28308222, 0x9082ebff, 0x022900ff, 0x265a8290, 0xff0a9727, 0x79c00700, 0x002008be, + 0x00217482, 0x25248202, 0x7c3f0300, 0x9e8200ff, 0x8b088f27, 0xdf0300ff, 0x21bc827c, 0x09820060, 0x75410482, 0xe0002105, 0xe2833582, 0x1e83bf82, + 0x0021f683, 0x201e8304, 0x21af84f5, 0xfa823c1f, 0xb89ec62b, 0xde2100ff, 0xecffffb8, 0x2109825e, 0x5482544b, 0x82022121, 0x993a237e, 0x19820898, + 0xff48212b, 0xe1ba3a00, 0x784900ff, 0x2bd98252, 0x00ffb91e, 0xff646639, 0xd623deff, 0x0a211e82, 0x2138821e, 0xa782e0f9, 0x82a10921, 0x82f720ce, + 0x09002166, 0xf522d883, 0x1e824821, 0xff22a783, 0x958220fd, 0x84400425, 0x84ffffff, 0x7c3f229f, 0x261a828d, 0xfff86803, 0x82ff0100, 0x8001286d, + 0xffff8f00, 0x829899fe, 0x34b32cbb, 0xdffeff08, 0xffff9a99, 0x186666db, 0x230c8752, 0x707d1500, 0x200a4844, 0x7a7d187d, 0x80152107, 0x48445d82, + 0x9082260d, 0x82eaffff, 0x05d2448f, 0xff25e282, 0xffff70fd, 0x201583e5, 0x0add44eb, 0x828b9a21, 0xe6612885, 0xc6ffff66, 0x82150080, 0xea262b8b, + 0x3ae9ffff, 0x0900ffe2, 0x40828696, 0xffd6232b, 0xe27a1000, 0xb5efffff, 0x312982c2, 0xff34732f, 0xa4702300, 0xae1f00ff, 0x3700ff14, 0xae82d823, + 0xff52f826, 0xead13e00, 0xe93b6382, 0x00ff866b, 0xff4a2c06, 0xd6e3e8ff, 0x91fcffff, 0xecffffec, 0xffffb81e, 0x823a7ff4, 0xf3fa271e, 0xdeffff34, + 0x4d82e4fa, 0xffcccc24, 0x0483e3ff, 0xb982e820, 0x80e9ff23, 0x241e8200, 0xf7cd4c7c, 0x22838289, 0x8251381a, 0x0e8d3545, 0x261300ff, 0xffffff68, + 0x00ff1879, 0xff662618, 0x58f3f9ff, 0x15218382, 0x257982ee, 0xffeac609, 0x7e831100, 0xe4c5122c, 0x680800ff, 0x1700fff6, 0x45823233, 0x32b3e62c, + 0xe50a00ff, 0xe4ffff3a, 0x4782cc4c, 0xff3e0a26, 0xcecce2ff, 0xff24e782, 0x8becd1e2, 0x38291682, 0xfaffff52, 0xffff9603, 0x228083e6, 0x826025f5, + 0x5c082254, 0x83f78229, 0x191122d3, 0x29b48299, 0x00ffce4c, 0xff67e615, 0x5484f6ff, 0xa582a620, 0x19cefe23, 0x2c9d829a, 0xffc37510, 0x90421000, + 0x910900ff, 0x832482eb, 0x1c01278d, 0x1600ff29, 0x7e82ecd1, 0x8f82e822, 0x97211482, 0x82e3820a, 0x1d00233e, 0x6c827a14, 0xff48e126, 0x16ee2000, + 0xec311e82, 0x00ff84ab, 0xffa2300b, 0x66e6e8ff, 0xe60300ff, 0x21098268, 0xdb82b8de, 0xbc82b320, 0xf8030022, 0xc12a9b82, 0x00ff3433, 0xfff6a81f, + 0xa082c8ff, 0x822f0021, 0xdcff3f7b, 0x0e089a99, 0x99d900ff, 0x5f01ff9a, 0xff1566e6, 0xcd0cf3ff, 0xa00000ff, 0xf4ffff00, 0xa7823d4a, 0xff12382b, + 0xd723ffff, 0xc9f2ffff, 0x21688236, 0x54821eff, 0x1ec5f223, 0x821f8295, 0x0d002434, 0x828b3333, 0x874f22e7, 0x248f82ae, 0x00ffdecf, 0x25758344, + 0xff1819bb, 0x6f820500, 0x7db0ff23, 0x221e8270, 0x82fed300, 0x5c4f2659, 0x8f0a00ff, 0x835482da, 0x500c20e6, 0x0023058d, 0x828bfe83, 0x0a882170, + 0x08210482, 0x21048204, 0x0482f087, 0x48fc0721, 0x002107cc, 0x221482d8, 0x82ae070a, 0xaa6f22de, 0x258a82ff, 0x0d00ffd8, 0x8a825238, 0x5864f931, + 0xc46500ff, 0xffe4327c, 0xce4c99ff, 0x840600ff, 0x660627eb, 0x6000ff66, 0xcb829a19, 0x6518ee20, 0xff21085b, 0x975818f1, 0x7b542211, 0x241683ff, + 0xab1100ff, 0x22c38385, 0x8200807b, 0x80642189, 0x9b20fa82, 0xff280a83, 0x08008084, 0xeeffff8b, 0x0e22b783, 0x2d887a54, 0x2d838620, 0x86ab1122, + 0x16832d82, 0x4f0e0023, 0x200a825c, 0x055f4611, 0xcccc9e25, 0x827effff, 0x81002104, 0x6120ff83, 0x2705cb55, 0xffcd4ccc, 0x33331dff, 0xf1209482, + 0x02259f83, 0xffff67e6, 0x221483f2, 0x829919f4, 0x33f12263, 0x23d18233, 0x0748a1cd, 0x20080c82, 0xff00c0f5, 0x83200700, 0xe1f7ffff, 0x0900ff48, + 0xffff7d9f, 0x081e45fd, 0x211200ff, 0xf9ffff48, 0x221e8240, 0x8247210d, 0xb85e2199, 0xec222e82, 0xa683ae47, 0xb883e520, 0x0483ea20, 0x6182eb20, + 0x7de5ff23, 0x20a68271, 0x821582ff, 0x43ea2022, 0xa68206d1, 0x9a991922, 0xf6224882, 0x3177862b, 0xf5ff2107, 0x09274f83, 0xffff9ad9, 0x8370bdf2, + 0xfdcf2833, 0xffffff71, 0x82050efe, 0xaec72711, 0xe30000ff, 0x2584ff3a, 0x38f5ff23, 0x224d8252, 0x82ccccf2, 0xe60822ac, 0x21428266, 0x7182a6ff, + 0x23520032, 0xb9ffffd7, 0x00ffce4c, 0xff29dc5c, 0x00801300, 0x36216382, 0x20bc8261, 0x271e830b, 0xb7d6e32b, 0x870b00ff, 0x36224b82, 0x1a823433, + 0x66112508, 0x5100ff68, 0xfffffeff, 0xff9999c9, 0xcd4c4a00, 0x80b4ffff, 0x0e089a00, 0xf834f72f, 0x076b1534, 0xab0614f7, 0x00285e82, 0xff86ab11, + 0xcc4c0e00, 0x54260482, 0x1100ff7a, 0xa18234b3, 0x16850684, 0xabf1ff23, 0x25928286, 0x087a54ee, 0x8218076b, 0x4d560ff7, 0x075b2508, 0xbb0654fc, + 0x1a274f83, 0x00ff9082, 0x54717d15, 0x1a2506e6, 0x088b8f82, 0x206a8cbb, 0x206a88cd, 0x216a8533, 0x11828b33, 0x6a89a183, 0xfb34fb29, 0x54f81534, + 0x18a4fb06, 0x2017bb83, 0x2fda19fb, 0xa4f72418, 0x184bdb07, 0x2017d081, 0x264f832b, 0xff3433f7, 0x18280700, 0x200cd281, 0x17b474eb, 0x3182eb20, + 0xcc080024, 0x8118ffcc, 0x2b210fd6, 0xff4c4106, 0x4c414b20, 0xb4f72617, 0x0800ff06, 0x00d618cc, 0x41cb2012, 0xcc240a4d, 0x330700ff, 0x079d9e18, + 0x06b4fb3d, 0xf101ff0e, 0x01ff0080, 0x1566e664, 0x19e4ffff, 0x3900ff9a, 0xffff52f8, 0x473233c6, 0xff2505ca, 0x8b9a99c4, 0x361a8208, 0xff8bb81e, + 0x72bde3ff, 0xc0f8ffff, 0xe6ffff00, 0xffffb85e, 0x8348a1f0, 0x8278201a, 0x85f02330, 0x1082051e, 0xffcccc29, 0xe2faf5ff, 0x82fbffff, 0x0520484a, + 0x09830920, 0x82e1f021, 0x20002929, 0xffff90c2, 0x054821c9, 0x8524a982, 0xf1ffffa2, 0x00382e82, 0xff681113, 0x9899f9ff, 0x4a1000ff, 0x0900ff3e, + 0xff08408a, 0x90821b00, 0x5e210f82, 0x252982b8, 0xff002005, 0x04830300, 0x34d3052c, 0x500100ff, 0x0500ff62, 0x948246a1, 0xe10a0027, 0x00ff8b48, + 0x2a7f830a, 0x910060fa, 0x01f6ffff, 0x82940846, 0x48e12b86, 0xeafaffff, 0xecffffc0, 0x6682b087, 0x82c60021, 0x46e12c1a, 0x9efeff08, 0xfffffe7f, + 0x8394b82d, 0x21c683ab, 0xcb82e0f6, 0x821efb21, 0x81ec22cb, 0x207c8248, 0x22388221, 0x8200c0f0, 0x20ab9a81, 0x86a6828a, 0x083e2bab, 0x665b01ff, + 0xce00ff68, 0xab820080, 0x8f472308, 0x2a00ff5c, 0xffac28dc, 0x9a995a00, 0x4cdcffff, 0x4c00ffcc, 0xff086666, 0x34334eff, 0xffff157e, 0x708280fd, + 0x9a99fd22, 0xeb208082, 0x00210a82, 0x2037843d, 0x218b8209, 0x04830400, 0x81820a20, 0x60030022, 0x0a20f282, 0x02211e83, 0x218b8320, 0x9682a114, + 0x4821c222, 0xf6213482, 0x214b8217, 0x448240ff, 0x7682f620, 0xf7204e85, 0xff232982, 0x821ec5fb, 0x19522b19, 0xb8feff99, 0xff156666, 0x1582c3ff, + 0x84260021, 0xe11e215e, 0x1221db82, 0x20a18340, 0x2115823c, 0x1583d9ff, 0x1ee1ff27, 0xedffffb9, 0x201583c0, 0x2315826b, 0xcecc3f00, 0x7f223699, + 0x3691ffff, 0x67e66e27, 0xcc4200ff, 0x203687cc, 0x20d78325, 0x296d9700, 0xeeffffb8, 0xff0566a6, 0x6d831400, 0x6666c429, 0x00ffb915, 0x829a192d, + 0x82082011, 0xf9ff21f0, 0x07211683, 0x25da82a0, 0xff6666f9, 0x0e820600, 0x99f6ff23, 0x21d5829a, 0x3b825ed2, 0xa430d222, 0xfa3eff82, 0x00ff7a54, + 0x832a1c0a, 0xb30700ff, 0xf6ffff32, 0x00ffcecc, 0x08666605, 0x94ffffdd, 0x89823433, 0x3782c420, 0x84130021, 0x400322d6, 0x821c8200, 0x0200215b, + 0x00265682, 0xff9ab904, 0x09830100, 0x1e050727, 0x00ff8c08, 0x202a8304, 0x831a8400, 0x20002104, 0x042d2e82, 0xff08b87e, 0x48613c00, 0xe1ebffff, + 0x26718248, 0xffb8defd, 0x82a1f5ff, 0x83fc200f, 0xccf53670, 0xfbffffcd, 0xffffce4c, 0x083333f6, 0x2a01ff0e, 0x01ff3433, 0x2ecd8223, 0x4ccbffff, + 0x1900ffcc, 0xffff34b3, 0x433333c2, 0xdb27060d, 0xffff6766, 0x8234b3d4, 0x45372654, 0xc8ffff1f, 0x21c682b0, 0x99820600, 0xc0f9ff24, 0x5a828b00, + 0x1886eb21, 0x230cc15e, 0x887ddffc, 0xdc266182, 0xfeffff6a, 0x09821e65, 0x8b42e023, 0x24068508, 0x0efcffff, 0x21c28256, 0x0982e29a, 0x8ec4e022, + 0xce271682, 0x00ff8f82, 0x823c4a32, 0xe67f27a8, 0xf9feff66, 0x0a823433, 0x0020fd2e, 0xffffff85, 0xffff00e0, 0x8e00c0f8, 0x9e205f82, 0x0520d583, + 0xff26ef82, 0xff48e1f4, 0x09830d00, 0xb85efb27, 0x0500ff96, 0x2b1a835e, 0xff9a9985, 0x00404100, 0xceffff05, 0x00234782, 0x82904231, 0x9ff9260a, + 0x0600ff7d, 0x22a68220, 0x82410a00, 0x60062236, 0x200f8283, 0x8330831e, 0x24c684c1, 0xb81e0a00, 0x2115828b, 0xc6844821, 0x3834e782, 0xffffe1fa, + 0x051e05c7, 0x3100fff1, 0xa305d6e3, 0xa10b00ff, 0x14203d82, 0x00217482, 0x20098313, 0x2104830c, 0x4783de19, 0xa4301e34, 0xa83d00ff, 0xe6fffff6, + 0x00ff6666, 0xffce4c4a, 0x0482c2ff, 0x331e002e, 0xffe70832, 0xcecc2200, 0x1300ff15, 0x282b3a83, 0xff81cccc, 0xb81e3000, 0x83d7ffff, 0xe120272b, + 0xffff0848, 0xe582c0cd, 0x8240d621, 0xbdfd2504, 0xbeffff70, 0x00310982, 0xff90a22c, 0x9a99d3ff, 0x05839308, 0x462d00ff, 0x830d8266, 0x83412031, + 0x330223da, 0x397dff33, 0x4c322205, 0x2c4082cd, 0xff9a19df, 0x34b32700, 0xffff955a, 0x290b82d8, 0x0080ecff, 0xb4f70e08, 0x788254f8, 0x34b31122, + 0x0e23dc82, 0x47ffcc4c, 0x98180a95, 0x345209d6, 0x063b250e, 0x00ff076b, 0x06254482, 0x802000ff, 0x20398200, 0x4a71821a, 0x043205bf, 0xffff34b3, + 0x0834b3e0, 0xb31600ff, 0x6affff32, 0x9b82cc4c, 0x15830020, 0xef83fb20, 0xa0820020, 0x33fbff25, 0x82ff8b32, 0x23258205, 0x6666baff, 0x171eb318, + 0x0614fc24, 0xee18ffff, 0x452216da, 0x36829a99, 0xcc040029, 0x0000ffcc, 0x82ffb95c, 0x82ce2009, 0x86b82109, 0xb3210982, 0x267d8332, 0x00ff50ad, + 0x8234b395, 0xbd04257d, 0x1f00ff71, 0x0026dc82, 0xffd7e31a, 0xfd821700, 0xa31f0024, 0x25828bd7, 0xec113828, 0xff07ab06, 0x9918afff, 0x1f250c3d, + 0x4c0e00ff, 0x20d782cc, 0x20c88211, 0x08cc48cb, 0xe13a0f22, 0x22066148, 0x831fc510, 0xe6e0273d, 0xfb058b66, 0x13485b54, 0x0ad7210e, 0xf723dd82, + 0x8508f628, 0x07114806, 0xff0ad724, 0x1b820800, 0x34f70822, 0x180ec446, 0x281fd4c1, 0x7b0634fb, 0xf71524fc, 0x18378ef4, 0x82089146, 0x064848aa, + 0x820dfa46, 0x7e8a1830, 0xf7ab222c, 0x20cb827c, 0x05b143f2, 0x18004021, 0x21139298, 0x1685c00a, 0x0d00ff26, 0x088b0040, 0x4c210682, 0x247e82cd, + 0xff33b30a, 0x82048200, 0x4c0d220a, 0x20f982cd, 0x84068200, 0x2916843f, 0xb3f2ffff, 0xeb088b33, 0x30ad155b, 0x47853785, 0x83f5ff21, 0x82488369, + 0x8606835e, 0x85168259, 0x5b082254, 0x82bd836b, 0x21308868, 0x41838bcc, 0x6e183420, 0x33200aee, 0xcc201b83, 0x8c8e3086, 0xbd843420, 0xbd85cc20, + 0xbd88cc20, 0x85853420, 0x24f70823, 0x7b4318ab, 0x82ef940c, 0xb30a215a, 0xf2246482, 0x088b34b3, 0x82827c84, 0x854cf521, 0x208d844d, 0x82be8a33, + 0x21be865a, 0xbeb58bcc, 0x8782e182, 0x2108617a, 0xbe8b4c0d, 0xbe848c84, 0xbee68c82, 0xef893420, 0x84117d41, 0x829582ef, 0x053b42a6, 0x0e30bea9, + 0x00ff5cf7, 0x1566e6a0, 0xff061cfb, 0x5c0ff3ff, 0xf4326782, 0xffffeb51, 0xfff833f8, 0x5c0ffbff, 0x0cf4ffff, 0x0a820808, 0x82f00721, 0xae072f0a, + 0xc00200ff, 0xf2ffff00, 0x00ff0040, 0x13822709, 0x9ad9f626, 0x1e00ff08, 0xe1282983, 0xff05a4f0, 0xa4f0c1ff, 0xee210482, 0x220a8214, 0x828f82f3, + 0x82802054, 0xfdff252f, 0xebffff71, 0x00233982, 0x84b17f0c, 0x27348213, 0xffb89e16, 0x4861e9ff, 0x09807418, 0x00ff0229, 0x8b8f4214, 0x820c00ff, + 0x202a8234, 0x202582b0, 0x235a823e, 0xec113e00, 0x65892582, 0x20060022, 0xf9265582, 0x00ff00e0, 0xa4822f08, 0x5a83fc20, 0x5c4f0822, 0x0422ff83, + 0x41820020, 0x9c820420, 0xcc00002d, 0x0300ff02, 0x00ff10f8, 0x82dea301, 0xf80b2b4b, 0x0400ff52, 0x00fff8f3, 0xca82c707, 0xc0aa0b22, 0x0c222982, + 0x1a82a4f0, 0x3afd8728, 0x0000ff07, 0x7c821401, 0x42666621, 0x0b2206a6, 0xa6429a99, 0xff042c07, 0x9a193f00, 0x8700ff15, 0x82069a19, 0xa4f02123, + 0x0b213a82, 0x212e82ae, 0x3e82cc07, 0xf5820420, 0xf30b0023, 0x830a83f8, 0x2669836f, 0x0040fdff, 0x820d00ff, 0xf6ff229a, 0x268382d8, 0x08662609, + 0x83e1ffff, 0x82c98229, 0x22da8acf, 0x8402800c, 0x275482f5, 0xff8e4214, 0x1280f3ff, 0x30820f84, 0x4861e927, 0x9e1600ff, 0xb07418ba, 0xffff210a, + 0x09d67418, 0x25822a83, 0x20067641, 0x89258216, 0x21778661, 0xc5821824, 0xff38492c, 0xf2b20200, 0xfbffff7f, 0x3082d418, 0x5af2f422, 0x0d2c0a82, + 0xf8ffff7e, 0xffff3433, 0x8b7c54f4, 0x0f217682, 0x201a825c, 0x05cb4e78, 0xcdccf122, 0x08cb7218, 0x5e420982, 0x94ff2205, 0x290b824c, 0x155c8fbd, + 0x0400ff7f, 0x598252f8, 0xff333322, 0xff28ea84, 0xff66e6f6, 0x0ad7f6ff, 0xe1224282, 0xea8467e6, 0xc1278e82, 0x00ff33f3, 0x88e6103e, 0x3a7f21bf, + 0x7120bf83, 0xf2226e82, 0x7382299c, 0x18c68021, 0x21087d67, 0x3642b85e, 0x90822108, 0xe6822082, 0x0c00ff24, 0x3242e77d, 0x113e2407, 0x82ffffec, + 0x222582ea, 0x8294d6e2, 0xfce92161, 0xf9250a82, 0xffffb8de, 0x277c83f9, 0xff00c0fc, 0xccccf7ff, 0xf7233a82, 0x820834b3, 0x055e5706, 0x8202cc21, + 0x10d82ceb, 0xa40100ff, 0xfcffff1f, 0x8208f007, 0xb6f321bc, 0x0c20f682, 0x0b25cd82, 0xffff15ae, 0x24c682f8, 0x15ee0c00, 0x411a828b, 0x0d2c05e3, + 0xff8b0040, 0x9ad90900, 0xc00a00ff, 0x0c220a83, 0x1c829a59, 0x66e68823, 0x21488207, 0x9982cccc, 0x86a4f021, 0xae0b2238, 0x204c8214, 0x222a8219, + 0x82a4f004, 0x4cec2824, 0xadfeffcd, 0x431570bd, 0x0020051b, 0x2205f041, 0x43182409, 0x00280536, 0xfff2b202, 0x58b90d00, 0x19279682, 0x0b00ff16, + 0x820870fd, 0x8400210a, 0xf8210a82, 0x20498254, 0x225d824c, 0x8232b308, 0x9a1921f7, 0xff269182, 0x0666e678, 0x4446ffff, 0x26f62505, 0xf5ffff66, + 0xff239c83, 0x4166a6f3, 0xf32609af, 0x00ff5c0f, 0x1082cc07, 0xec51f422, 0xf3204882, 0x4205c243, 0xff2306f7, 0x42f007fb, 0x0023058d, 0x8200c002, + 0x23458286, 0xf0270900, 0x8606bd43, 0x823e20a1, 0x05604143, 0x800c0023, 0x267e8200, 0x00ff0280, 0x43904214, 0x30830993, 0xb89e1624, 0x048200ff, + 0x84ff0521, 0x43771825, 0x90422107, 0x0e203083, 0x85821484, 0x822ec021, 0x573b2f5b, 0xaf0e05dc, 0xb4f7c4f8, 0x0a00ff15, 0x48824861, 0x50b80622, + 0x83827e82, 0x66feff23, 0x2c148268, 0x73084821, 0x195f00ff, 0xffff059a, 0x26f884fe, 0xffff1e05, 0x820080f9, 0x45f8204e, 0x9d2a05f1, 0xff06b81e, + 0xb89e1900, 0x738214fb, 0x90426133, 0xf7b4fb06, 0xffff1514, 0x0600809b, 0x66e6ffff, 0x2c188466, 0x069a197e, 0xff0714f7, 0x00808400, 0x201d868b, + 0x830f83fb, 0x20268418, 0x243f82f7, 0x00807bfe, 0x223c82fb, 0x82406100, 0x1900233c, 0x158348a1, 0x6384ff20, 0xc0f8ff24, 0x7c848b00, 0x8c828620, + 0xff004025, 0x83e1f8ff, 0xa0ff239e, 0x9e8266e6, 0xbe7ffd25, 0x82f5ffff, 0x0700289e, 0xffff42a0, 0x823433f6, 0x006033bf, 0xb4f8088b, 0x0677154b, + 0xfc05ab8f, 0x6b8f0694, 0x94827705, 0x82057678, 0x2143824f, 0x5482cdcc, 0x3333f722, 0x0901a418, 0x84070021, 0xcccc245c, 0x820800ff, 0xa7082772, + 0x34fb9f06, 0xa34f7b05, 0x181e8d09, 0x2418a545, 0xd4f7079b, 0x18368506, 0x180d724f, 0x261d9a45, 0xf79f079b, 0x48a70534, 0xab2017fb, 0x00228782, + 0x4618cc08, 0x07220728, 0x22783333, 0x01ff2208, 0x2fb482a2, 0xcccc5701, 0xf1ffff15, 0x00ffcecc, 0x05343348, 0x2d078941, 0xff66e6ff, 0x66e680ff, + 0x3c00ff05, 0x5e821ec5, 0x7c541028, 0x661200ff, 0x05829d66, 0xff68e630, 0x32b31300, 0x991100ff, 0xffff0898, 0x3c834c6d, 0x827c1421, 0x669b2247, + 0x05c64166, 0x05213c82, 0x223c821e, 0x829a197e, 0x1900273c, 0x7f00ff9a, 0x1082e2fa, 0x3233bd28, 0xebb7ffff, 0x47821584, 0xff23e882, 0x8200c0ef, + 0x90422147, 0x22060261, 0x8248a10f, 0x48212709, 0x0500ff08, 0x048240c0, 0x827c9f21, 0x83a12004, 0x3c7f220e, 0x210a8291, 0x0b820040, 0x2f821520, + 0xfa120023, 0x204f82e0, 0x22448315, 0x822005ed, 0x2001340a, 0xffffff00, 0xff8c1400, 0x2ee0feff, 0x000100ff, 0x4d088a40, 0x00270503, 0xfff2bf00, + 0x82600000, 0xc000223b, 0x2113820e, 0x0e82f8bf, 0x08bebf28, 0x5f00ff73, 0xf68252f8, 0x8260fe21, 0x1f072687, 0xf9ffff7e, 0x2872827f, 0xff3aff04, + 0x3cbff8ff, 0x2240828b, 0x82c01f9d, 0x830c20c3, 0x80c22268, 0x32688200, 0xff98d90b, 0xae67f5ff, 0x42feff05, 0xffff34b3, 0x829a19c8, 0x836120ce, + 0x05002294, 0x272082b6, 0xffd7a319, 0x66e67f00, 0x9d235782, 0x8306291c, 0x8bbe2149, 0x80255982, 0xfbffff41, 0x2bc91800, 0xe1f83307, 0xffff0806, + 0xff77fde7, 0x0219a0ff, 0xfdffff05, 0x5782b87f, 0xff68e630, 0x83a00700, 0x33f6ffff, 0x0a00ff32, 0x8382bf5f, 0x9944012b, 0xff156b9a, 0xf668cbfe, + 0x205f828b, 0x22438304, 0x828f02e0, 0xfdeb2233, 0x21ce822f, 0x0a8271fd, 0x8340f722, 0xf8226482, 0xa8427dbf, 0xffff250b, 0x079a19e0, 0xf7221782, + 0x57828440, 0x7c824020, 0xe2a5f926, 0xbf0800ff, 0x00235783, 0x8290021c, 0x78fb263e, 0xffff9f05, 0x82b08260, 0x37ee2328, 0x068205bc, 0x4205ae53, + 0xff250dbd, 0x90022000, 0x203c8206, 0x236982c0, 0x7d3f0700, 0x3f225182, 0x05828b7c, 0x081eda25, 0x820f00ff, 0x00ff2969, 0xffcdccd0, 0x84000000, + 0xe1289182, 0x00ffb8de, 0xff70bd21, 0x2205b677, 0x822a1c2c, 0x7330222b, 0x202b8232, 0x2b788200, 0xb0b22500, 0xcc1300ff, 0x2e00ffcc, 0x00238582, + 0x8234b320, 0x33b32109, 0xd22e1e82, 0x00ff9a99, 0x15cecc1c, 0x1ef1ffff, 0xb160ffb8, 0x80f22205, 0x24098200, 0xffff4821, 0x261383f4, 0x08fffff1, + 0x82ecffff, 0x19002614, 0xffff71bd, 0x206d83e7, 0x21b1831a, 0x77829ee4, 0xb85e1822, 0xb9311e82, 0xffff28dc, 0xff2045c1, 0xd823ceff, 0x87aeffff, + 0x22db82ac, 0x829a99ce, 0x2bff2a1a, 0xa8ffff86, 0x00ff5c8f, 0x22438248, 0x8219b9ff, 0x80572372, 0x7e828b00, 0xfe7f5723, 0x2316858b, 0xb8de4600, + 0x572d0a82, 0x8c08146e, 0xb32400ff, 0x00ff6534, 0x239c824b, 0x9c19cdff, 0x1920ac82, 0xed274883, 0xffff6466, 0x8332b31a, 0x217e83ac, 0xa28261f5, + 0x8d82ed20, 0x85faff23, 0x21a1821e, 0x5382b85e, 0xfdceff23, 0x207a8270, 0x22b982d8, 0x827d2100, 0x3600240a, 0x8208727d, 0x831b205a, 0x82102011, + 0x17002181, 0x00283282, 0xff48e120, 0x2adc2800, 0x04328582, 0xffff42c0, 0xff8380fa, 0x96633e00, 0x84adffff, 0x48828b9b, 0xc2270033, 0x2e00ff90, + 0xff0570fd, 0x40e00200, 0x20fbffff, 0x21098242, 0x0982c07f, 0x82826021, 0x00602609, 0x65fcffff, 0x2f4082a2, 0xff88ab12, 0xc475d9ff, 0x33f7ffff, + 0xd1ffff30, 0xff21e182, 0x2c6982df, 0xcccce7ff, 0x94f80e08, 0xfb1584f7, 0x051c4274, 0x23052750, 0xc0f8ffff, 0xf72f0982, 0x088b0040, 0x14f7063b, + 0xfb066b07, 0x9c4b0714, 0x453b2009, 0xb16b0c23, 0x285a830b, 0xcdcc0800, 0x400700ff, 0x21048200, 0x24453333, 0x56bb2006, 0x082105b5, 0x05046ecc, + 0x34201a83, 0x86821a8e, 0x30824a82, 0x44823a84, 0xf7088b23, 0x0ce64474, 0x8206e245, 0x5b0823ab, 0x1a8ebb07, 0x21053a48, 0x1a933433, 0x3707c345, + 0x00ffef0e, 0xff0080c0, 0xf6e88801, 0x1900ff15, 0x00ff6666, 0x05008012, 0x29052c49, 0xcccc0700, 0xfdffff9a, 0x9e8248a1, 0xff24a882, 0x08ae47f5, + 0xce210a83, 0x820a83ff, 0x98992619, 0xfdf0ffff, 0x200e8272, 0x2d13824c, 0x083233f8, 0xb3e3ffff, 0xecffff33, 0x44825c4f, 0x3333162d, 0x1000ff06, + 0xff8b66e6, 0x82cc0e00, 0x83f62021, 0x83082060, 0xccf22435, 0x627408ce, 0xf021061b, 0x20658299, 0x230483e5, 0x6ccd4cfe, 0xe4264282, 0xffffcd4c, + 0x158219f8, 0x9c82eb20, 0x83e6ff21, 0xe2ff2440, 0x41089a19, 0xf42505aa, 0x00ffcc4c, 0x201e8303, 0x210482f5, 0x23530500, 0x66672209, 0x0c206d66, + 0x0a8e8f18, 0x07d4f722, 0x5805085d, 0x35820725, 0x821a0024, 0xd1828b8f, 0xff29a784, 0xff15aee3, 0x0a971400, 0x82dd8505, 0x84b182fd, 0x020f22fc, + 0x25f6838e, 0x0a00ffcd, 0x2f8252b8, 0x85cc0721, 0x00ff290a, 0xff90020f, 0xb85e0200, 0xb3821984, 0x82343321, 0x6e1b271e, 0xecffff15, 0x4882cc0c, + 0x14aef727, 0xf31800ff, 0x2a0a8234, 0xff5ccffb, 0x7a940c00, 0x830600ff, 0x960d223e, 0x260e8246, 0x00ff5d8f, 0x82e63004, 0xb30b2234, 0x2b0a8233, + 0x00ff2631, 0xff01800e, 0x3a34f9ff, 0x33260e82, 0xf3ffff33, 0x9e180e6d, 0xe2230780, 0x8205723d, 0x22298369, 0x82142e1e, 0x6604220a, 0x20448267, + 0x202a827f, 0x2214830d, 0x82808a06, 0x23d8820e, 0x3293fbff, 0x0c203482, 0x34200a85, 0x09837282, 0x3248f222, 0x2c07d365, 0xff088e82, 0x66e6f7ff, + 0xebe8ffff, 0x36488286, 0xff34b397, 0x70fdb7ff, 0x1600ff15, 0xff8b6666, 0x32331500, 0x82f4ffff, 0x0d002115, 0xff220482, 0x4f8333ee, 0x45831e20, + 0x6766d822, 0x0a833082, 0x99270023, 0x830a8299, 0x11002320, 0x3485cecc, 0x4c0b0023, 0x824485cc, 0xb3272280, 0x2a4b8234, 0x6a008020, 0x8b08648b, + 0x83f6ffff, 0x99fe224b, 0x227b8698, 0x82d04cfd, 0x666621e9, 0x04222982, 0x9c189819, 0xe9220ddb, 0x30829a99, 0x1c83e620, 0x19afff26, 0x54fb079a, + 0x60281f82, 0x6b0766e6, 0x9fffff06, 0x50201087, 0x61821082, 0x9a991922, 0x9d827d82, 0x607bbd83, 0x20538405, 0x202b829a, 0x208f83fd, 0x21208206, + 0x0482feff, 0x19080022, 0x00285782, 0x08cc4c09, 0x00ffb28b, 0xac229a82, 0xa68300ff, 0x828b0821, 0x8213205f, 0xc5ff2d2b, 0xff159a99, 0x6666fbff, + 0xf8ffff91, 0x0422d683, 0x82716666, 0x99f22208, 0x26968298, 0xff3433f5, 0x8233f4ff, 0xf3ff22dc, 0x234982cc, 0xccf1ffff, 0x2507614c, 0xff3333f6, + 0x0a780d00, 0x19312105, 0xe2208183, 0x00203f82, 0x20051656, 0x2360829c, 0x66660a00, 0xf8226082, 0x49820080, 0x67676083, 0x23708205, 0xffff0885, + 0xff262c83, 0x056666da, 0x3d8400ff, 0xff204a84, 0x2205c34f, 0x82cdcc09, 0x330e23ec, 0x06820833, 0x83830c20, 0x00258883, 0xffcccc0b, 0x839883ff, + 0xd8fe21c3, 0xfe2e1782, 0x159a19df, 0x54f707db, 0x0714fb06, 0x8b7124fb, 0x0b13430c, 0x155b7424, 0x268314f7, 0xee5a3b20, 0x06242b18, 0x02ffef0e, + 0xff68667f, 0xb7840e00, 0x40a0f72c, 0x5e1400ff, 0xe8ffffb8, 0xfd4ac09f, 0xa1eb2c06, 0xf7ffff48, 0xff080080, 0x82e1e9ff, 0xc0f62d0a, 0xffff0542, + 0xff0040d9, 0x9a196500, 0x2f30ca82, 0x00ffb8de, 0x9c9a1922, 0x194200ff, 0xe1ffff99, 0x00233082, 0x82ff7f34, 0x61a92730, 0x9600ff48, 0x30820080, + 0x4200f837, 0xde0d00ff, 0xefffffba, 0x00ff24e6, 0x7c46e105, 0xdef9ffff, 0x272582ba, 0xffcecc8d, 0x46a1d0ff, 0x8c392582, 0x00ff59cf, 0x05964330, + 0x0600ff7c, 0xff7a0020, 0x0020faff, 0xf2ffff83, 0x217f8320, 0x5e8259a9, 0x3e8a6922, 0xe1262882, 0xffff00c0, 0x848280cb, 0x94831020, 0x34b3be2c, + 0xd12f00ff, 0xddffffec, 0x52829819, 0xff219e83, 0x239e839a, 0x14eee9ff, 0x3321c982, 0x2a348234, 0xff47a1eb, 0xbe7f0800, 0x83e8ffff, 0x40f6223e, + 0x21d98442, 0xe382ffff, 0xfe203482, 0xff22d382, 0xa782e0fb, 0x82e00121, 0x60fb215d, 0x04215d82, 0x2d098220, 0x08be3ffe, 0x66a200ff, 0xbcffff66, + 0xf28248a1, 0x9a190327, 0x3ffeffff, 0x20c782fe, 0x2bcc8286, 0xff02e001, 0xfabe0100, 0x1f0400ff, 0x08222983, 0x4641be5f, 0x60f62106, 0x17204d82, + 0x6283a682, 0x46417b82, 0x09002308, 0x4882be1f, 0xb85e2727, 0x996700ff, 0x200a829a, 0x22258304, 0x820680ff, 0x223e8244, 0x833fffff, 0xfa3e224e, + 0x2379828b, 0x8b00c033, 0x9e20de82, 0x20202b82, 0x00287982, 0xffae070e, 0xd6233500, 0x14201a82, 0x0023b382, 0x82285c4b, 0x230a8340, 0xd8a3b4ff, + 0x0d200a82, 0xff2e2582, 0xff90c2cb, 0x1e853000, 0x3300ff6a, 0x4783aec7, 0x83400421, 0x82042047, 0x0000225e, 0x205e83bf, 0x2204827e, 0x82068000, + 0x82272047, 0x98ff2447, 0x41056666, 0xe02107e5, 0x410a8242, 0x422306fb, 0x83f6ffff, 0x66e9211f, 0x0820ec82, 0xea22a783, 0x3482e2ba, 0x00c00123, + 0x053041ff, 0x09830420, 0xfe1ffe28, 0x0100ff8f, 0x1a8202c0, 0x6866a227, 0x5e4300ff, 0x218c82b8, 0x0f82d703, 0xead10123, 0x83d9828d, 0x4cfe223b, + 0x370982d0, 0xff089a19, 0xfe7f94fe, 0x800f01ff, 0xffff1500, 0xff67e68f, 0x00802e00, 0x24203082, 0x00212582, 0x273b843f, 0xffff7f5e, 0x7cd4d8ff, + 0xed208b82, 0xb922d383, 0x2082cc4c, 0x34335823, 0x2732828b, 0xff4821ed, 0x70bd4600, 0x5e261182, 0x00ff707d, 0x6e831e27, 0xff233d83, 0x8248a1c0, + 0x8f250832, 0xffff48e1, 0x059082d1, 0xdf01ff0e, 0x34f89a19, 0x40feff15, 0xff06a4f0, 0x8f82ecff, 0xf1ffff8b, 0xffff4120, 0x23ba82ee, 0xf39f0200, + 0xbd211482, 0x27a98270, 0xff3cfd37, 0xf6689bfe, 0x20079241, 0x398d83e0, 0xff71fd1a, 0x9a99e8ff, 0x052000ff, 0xff088b1f, 0x68e61001, 0x1f00ff06, + 0xe24870bd, 0x61172107, 0x04208c82, 0x1f222b83, 0x46839082, 0xff289c26, 0x9a996401, 0x02214682, 0x221a82a1, 0x828e4213, 0x34332970, 0x401100ff, + 0xebffff00, 0x2405755c, 0xfb9a99c7, 0x22958254, 0x823ccab2, 0xe6eb2a95, 0x0514f766, 0x337501ff, 0x2b0d8234, 0xfb281cec, 0xf80e0514, 0x1554f794, + 0x7220ac82, 0xff247d82, 0xff66668d, 0x0e820485, 0xff208782, 0x11850683, 0x0a840020, 0x21820020, 0x93820820, 0xff200682, 0x04861183, 0x2d820e82, + 0x1b821c83, 0x54854987, 0xffff082e, 0xffcc4c0a, 0x00c0cf00, 0xdeffff15, 0xff38a182, 0x0566a6e6, 0xb3faffff, 0xfbffff33, 0xffff52f8, 0xffcdccfc, + 0x14aef9ff, 0xf9223082, 0x3082b047, 0x32f3f623, 0x220c8307, 0x47ff5238, 0xfa2005a2, 0x0622f883, 0x6483cdcc, 0x66660222, 0x02326482, 0x00ff6766, + 0x8d34b300, 0x660100ff, 0x00ff0866, 0x6482cc29, 0x0ad71b23, 0x23118305, 0x00ff0a57, 0x21822782, 0x4282b820, 0x6866022c, 0x068c088b, 0x330600ff, + 0x51828b32, 0x829a1921, 0x84ee207d, 0x90c2276e, 0xff888b08, 0x3c82feff, 0x1efdff28, 0xfdffffb8, 0x048268e6, 0x8248e121, 0x19ec2785, 0xecffff98, + 0xab83281c, 0xfb20b683, 0xf8223783, 0x3c8266e6, 0x7a34b321, 0xff2305f9, 0x820080fd, 0x66e52129, 0xf7221482, 0x29839a19, 0xff21eb82, 0x203983fe, + 0x216684fc, 0xc8839a99, 0x0866e622, 0xfc220682, 0x6a82ce4c, 0xff21ca82, 0x07196cfc, 0x82fdff21, 0x797921bc, 0xf9203882, 0x04845383, 0xf7241c84, + 0x828bcc4c, 0xfb235a82, 0x8207cdcc, 0x99ef253a, 0x0d00ff9a, 0x9d560482, 0x82102005, 0x9608211d, 0x0a20cb82, 0xd6829882, 0x00ff3323, 0x28988204, + 0xcdcc0900, 0x00ff8f08, 0x668a8308, 0x042005b3, 0x1b85d982, 0x8f820320, 0x66050025, 0x82088b66, 0x2196832c, 0x3c820400, 0x6626f082, 0xb30200ff, + 0x9482ff32, 0x1a826720, 0xa4831020, 0x3333ea23, 0x82158205, 0xfdff2231, 0x205c8233, 0x25af8303, 0xffcd4cfe, 0x39820300, 0x08202582, 0x9b414782, + 0x08002105, 0xff287882, 0xff3233fc, 0x00800700, 0xfe22b182, 0x3a8268e6, 0x82cd4c21, 0x20c982d3, 0x82328492, 0x21f68292, 0x46820700, 0x40829683, + 0x30841520, 0x0720a784, 0xac85d682, 0x70820520, 0x19070026, 0x08938b99, 0x8982db83, 0x4c080023, 0x833c82cc, 0x4c0a2204, 0x22ba83ce, 0x4a66661d, + 0x8b2317ad, 0x83f7ffff, 0x82f820d2, 0x84ff20f3, 0x820e8204, 0xebff2533, 0xff06cc4c, 0xce251182, 0xffff848b, 0x216482fd, 0xb483faff, 0x08230482, + 0x82fbffff, 0x8304825c, 0x05fc41af, 0x10421a83, 0x9a192305, 0x8982888b, 0xccf9ff22, 0x9c83f982, 0x00233784, 0x82323306, 0x0b002555, 0x9106ce4c, + 0x0520a782, 0xfd206e83, 0x0420c483, 0xfb227d83, 0xdf82cccc, 0x0f820620, 0x66f9ff31, 0x00ff0567, 0xff66e600, 0x9919ffff, 0x830100ff, 0xb3fc2209, + 0x22a88234, 0x836666fd, 0x22068259, 0x83feffff, 0x83fd2091, 0x83ff2030, 0x33fe2209, 0x22968233, 0x820080f8, 0x018025b2, 0xfcffff05, 0xfd27a183, + 0xff893233, 0x8333faff, 0x82b8833c, 0x20068243, 0x82bf828d, 0x03002333, 0x278434b3, 0x12207982, 0xed222d83, 0x798234b3, 0x8f830a20, 0x9e82f520, + 0x840d0021, 0x210e82ef, 0xa34d0e00, 0x80062405, 0x41ff0600, 0x14200590, 0x03201683, 0xde476e82, 0x4c162206, 0x229a82cc, 0x82666f00, 0x82a820b6, + 0x5a002604, 0xffffc2f5, 0x29418291, 0xd8630500, 0xff078b08, 0x7382ac00, 0x26ccfe24, 0x74831566, 0x00ffce23, 0x20bc8302, 0x204283fb, 0x27048201, + 0x3233fbff, 0x8b85088b, 0x1c82ae84, 0xff214382, 0x228583fb, 0x82343304, 0x82f120d9, 0x0e0023ab, 0xd982cc4c, 0x3233f92a, 0xcc0600ff, 0xf5ffffce, + 0x00214182, 0x20ba8304, 0x82e282f5, 0x4cf62625, 0xffff8bcc, 0x204e82f6, 0x219b8300, 0x2083f8ff, 0x9a820620, 0xe4ffff22, 0x16220a83, 0x4082cecc, + 0x3182f520, 0x82090021, 0xf1ff219a, 0x0620c583, 0xf0216a83, 0x2a7d82b3, 0x19ebffff, 0xffff069a, 0x82cd4cf3, 0xb3f32546, 0xfbffff33, 0xf5241c83, + 0x08840080, 0xff234285, 0x8234b3ed, 0x33ee2142, 0xf4201b82, 0xff24d082, 0x77cd4cf5, 0xea222c82, 0x21829a99, 0xccccfc25, 0x827a8b07, 0x283a839d, + 0x97ccccef, 0x7b9b087f, 0x05c84205, 0x83f7ff21, 0x850b2096, 0x97342aea, 0x00ff088b, 0x06cd4c15, 0x0a7049ff, 0x0d108918, 0x2a82fd20, 0x66000025, + 0x85ffff66, 0x34b32109, 0xb3210982, 0x20378234, 0x26148247, 0xcccc0500, 0x823d00ff, 0x05c54482, 0x0e832020, 0x85823b20, 0x058b8b25, 0x83eefeff, + 0x66ff25e2, 0x6b6b1566, 0xf920ad82, 0xf9228e83, 0xa782cecc, 0x2683f520, 0xcd4c0624, 0x0f82ffff, 0x06204a82, 0xf928c883, 0x00ff32b3, 0x8b34330a, + 0x0f82b982, 0x4c060026, 0xabab08ce, 0x2883b782, 0x00450020, 0x821e8205, 0x83488233, 0x22ea820f, 0x82cdccf9, 0x9042232d, 0x5282ffff, 0x0f835882, + 0xbdf9ff2c, 0x078b0870, 0x34f82f0e, 0xc75d34f7, 0x1ffa6f0e, 0x1814fc21, 0x18170b8c, 0x25165aac, 0x8b0614f8, 0x659c14f7, 0x113b5e18, 0x5e186591, + 0xac180c38, 0x658211c0, 0xf0fb0e25, 0x82158bcb, 0x5eee20e2, 0x852c0590, 0xb3f1ffff, 0xeeffff34, 0x088b7b54, 0x0eb2ac18, 0x2107a55d, 0xa65d14f8, + 0xff842505, 0x7b540e00, 0x7c200483, 0x18081e68, 0x230943a6, 0x84abf1ff, 0x54275783, 0x14fc087c, 0x8a14f707, 0x18b32065, 0x190cdf8d, 0x5e0b4129, + 0x658b0a0b, 0x87cd4c21, 0x66b32065, 0x658a116e, 0x01ff0e23, 0x27bd82f6, 0xe2fa9801, 0xe2ffff15, 0x0029d282, 0x0566a61d, 0x80f3ffff, 0x06cc4d00, + 0x90c2eb27, 0xfdffffff, 0x23138570, 0xd87ff3ff, 0xd120e682, 0xd1221483, 0x298248a1, 0x0020fc24, 0x0484ffff, 0xea06fd27, 0x5efbffff, 0x06f05578, + 0xfabefa22, 0xf3272982, 0xffff5ccf, 0x82707ddb, 0xc4b32729, 0xb3ffff9a, 0x5a187ab8, 0x0820073f, 0x2105394c, 0xe06e929a, 0x03002305, 0x30826666, + 0x9a99de25, 0x820700ff, 0xdeff2794, 0xffff6666, 0x348219f9, 0x0484e920, 0x82323321, 0xccf62e1e, 0xf6ffffcd, 0xff849a99, 0x0080f4ff, 0x82958287, + 0xff852335, 0xb082edff, 0x83eeff21, 0x83f12051, 0x0aed2221, 0x2186823d, 0x3182cd4c, 0x4761e822, 0x9920bf82, 0xde224683, 0x5c59ffb8, 0x21ef2305, + 0x1a827a48, 0x4861d225, 0x82d2ffff, 0x08002739, 0xff39713d, 0x0a823700, 0x80c8ff24, 0x0a820800, 0x2b825e20, 0xb89ec82a, 0x075200ff, 0xf7ffffae, + 0x00213a82, 0x231e822d, 0x90822d00, 0x10201e82, 0x00379182, 0xff48e110, 0x65260a00, 0xf81500ff, 0x0200ff52, 0x00ff0040, 0x4ab8de17, 0x00220677, + 0x0f82c012, 0x0a170e2e, 0x681100ff, 0x1200fff6, 0x089148a1, 0x22055441, 0x82e00300, 0x870b261a, 0x0600ffae, 0x206282fe, 0x236c8209, 0x48610900, + 0x16201e82, 0x16206883, 0x06205883, 0x21200483, 0xff267282, 0xff9a59f7, 0x1e832100, 0xa0fcff22, 0x0e213882, 0x27b682a1, 0xff28fcf8, 0x295c0d00, + 0x40219b82, 0x20568202, 0x2077831e, 0x2682834c, 0x058f424c, 0x832400ff, 0x2b0c225d, 0x07bf6584, 0x8d830120, 0xdec40422, 0xf722a782, 0x8182ff0c, + 0x04834020, 0x2e21ea83, 0x2249825c, 0x823c4a2e, 0x6b0d2229, 0x274a8288, 0xff8b5278, 0x34331400, 0x2a090642, 0xd9feff08, 0xfeffcc4c, 0x6d1e05c7, + 0x80210ee1, 0x252a7200, 0x460ebb72, 0x5d6a06d3, 0x83ea2009, 0x320e82e8, 0xff0e088b, 0x67667700, 0xe69301ff, 0x00ff1566, 0x82cd4c17, 0x48e121a7, + 0x21830982, 0x1e05fe22, 0xe6359a82, 0xf8ffff67, 0xff0820c5, 0x33b33200, 0x87b2ffff, 0xffff05ae, 0x221f83b4, 0x829999b4, 0x84fe200a, 0x2144822a, + 0x3e82feff, 0xccfeff23, 0x296f86cc, 0x0867e6fc, 0xfdffff8b, 0x108266e6, 0x839a1921, 0xff672309, 0x2e840200, 0x08008026, 0x052304f7, 0x1d820e82, + 0x82fdff21, 0x030022ee, 0x23228299, 0x8f66e6ff, 0x6e822384, 0x33820320, 0x82020021, 0x00002815, 0x00ff32b3, 0x86666604, 0x6603264c, 0xffff0868, + 0x211983c3, 0x82821962, 0xb35a0026, 0x4b00ff34, 0x2f838d83, 0x468c8e21, 0x8a8406e1, 0x34330322, 0xe9202c82, 0x3f226183, 0x71825c8f, 0x37831c20, + 0xc2b5102a, 0xcc2100ff, 0x0600ffce, 0x00218f82, 0x225b8321, 0x82146efa, 0x83442075, 0x85f42190, 0x3220f982, 0xff231982, 0x824861c4, 0x19ba22c3, + 0x2344829a, 0x073433fa, 0xd6200c82, 0x2008fd42, 0x215582d8, 0x4f82e1ff, 0xb3e3ff22, 0x4b316583, 0xffffce4c, 0x05cc4c57, 0x80f8ffff, 0xffff8400, + 0x08594af6, 0x135af520, 0xb3f52205, 0x20418233, 0x20d983f6, 0x82688303, 0x82922026, 0x4a4b2759, 0xa800ff3d, 0x388234b3, 0xd7a3e125, 0x831c00ff, + 0xc5ee2258, 0x05b0501f, 0x2900ff24, 0x9a820080, 0xcccc0522, 0x00217f82, 0x22388245, 0x82853200, 0x9e3b2c1c, 0x4400ffb8, 0x00ff48e1, 0x82727d0b, + 0xfdff2746, 0xff0e0770, 0x5e821f01, 0xe6300124, 0x6a821566, 0x2848e520, 0xffff2206, 0x21e382eb, 0x0f4a1900, 0x59ae1805, 0x06444809, 0x08221782, + 0x1e83ff8b, 0x21099674, 0x3c82ffff, 0x56828b20, 0x8d82e720, 0x02000026, 0xe9ffff90, 0xea22eb83, 0xaf51707d, 0xe6902308, 0xa3185b66, 0x14200816, + 0x85069b51, 0x844f8848, 0x70162278, 0x6c4f88a4, 0x168305d0, 0x2006cf74, 0x055d49e6, 0xff210682, 0x23448300, 0x5c8fe9ff, 0x2408db51, 0xf79a197f, + 0x85ca8224, 0x204c849c, 0x21d48215, 0xca84e4ff, 0x9675a384, 0x85988609, 0x05285206, 0xb5e8ff23, 0x75d984c4, 0x662005db, 0x2006db75, 0x052f7100, + 0x7a821b20, 0xc4ffff29, 0xffff9999, 0x8200803c, 0x830120ca, 0xe60c25c4, 0xf2ffff67, 0x00211482, 0x21048209, 0x1382f3ff, 0x99faff2d, 0xffff089a, + 0xff3333d8, 0x82b3eeff, 0x19d62604, 0xf7ffff9a, 0x27288266, 0xff85ebd6, 0x99990000, 0xf5221e82, 0x0a82f568, 0xf83c2383, 0xffff295c, 0xff66e6f5, + 0x3e4a0300, 0x4cf6ffff, 0x00ff08ce, 0xff71fd04, 0x32b3f0ff, 0x8f211482, 0x2509825d, 0x00ffce4c, 0x28821c02, 0x32b3ef22, 0x02261e82, 0xffff0d22, + 0x5782d9ef, 0xe17af422, 0xe3211e82, 0x260e82d6, 0xffff5a44, 0x82ae07fd, 0x21ef225c, 0x210a8247, 0x1482f608, 0xff852b26, 0xf49dfeff, 0x38210982, + 0x21708252, 0x1e822c32, 0x8266f521, 0x0f00266c, 0xf8ffff00, 0x223d823a, 0x8734e4f5, 0x5c4f217b, 0x0c205c82, 0xff231e82, 0x82c235dc, 0x273d8385, + 0xff2adcd8, 0xcd8cfbff, 0x3a21d282, 0x2f3d82e0, 0xffe946fe, 0x3e0af1ff, 0x6e0f00ff, 0xf5ffffd9, 0x0028b482, 0xff5c4f0e, 0xb8de0500, 0x26213d82, + 0x21678278, 0x5282f30f, 0xcd4c2830, 0xdc0700ff, 0x2700ff28, 0xffff156e, 0x9a8287ff, 0x940a0023, 0x210a827b, 0xa46000ce, 0x1a0a2106, 0xfc27a482, + 0x00ffc3b5, 0x82a4b009, 0xdbfa225c, 0x265782e7, 0xffff6626, 0x820576fc, 0x82e82009, 0xe3fd261e, 0x1000ffd7, 0x233d8247, 0xf4ddfdff, 0x282a0a82, + 0x0b00fff6, 0x00ff0681, 0x6b82f80e, 0x77de1027, 0xf50200ff, 0x227b82c2, 0x82e1ba10, 0x16f9210a, 0xd7262382, 0x0100ff0b, 0x0982e485, 0x833dca21, + 0x82142070, 0x820a201e, 0xffff231e, 0x7b8702ec, 0x82ac1b21, 0x2d7b8966, 0xffcb4cf3, 0x243b2500, 0x2800ff87, 0xcf82cecc, 0xff333326, 0xcc4c2900, + 0xfc273982, 0xffff0180, 0x8200808e, 0x38ef22c6, 0x2dc08552, 0x862befff, 0x620100ff, 0xefffff20, 0x77824621, 0x82caf621, 0x45ef22c0, 0x2882851e, + 0xe27af4ff, 0x1b0f00ff, 0x210e8264, 0x87824821, 0x82682621, 0x1d022248, 0x23cb8470, 0x8e0300ff, 0x0f21a682, 0x212d82c5, 0x1382fd04, 0x20450f22, + 0x03361e82, 0x00fffc49, 0xffe6b009, 0x6a5cf8ff, 0x1e0a00ff, 0xf5ffff76, 0x7082866b, 0x825ccf21, 0xe3d6225c, 0x2a0a82d8, 0xffff025a, 0xff9819d6, + 0x829d0800, 0x4fd82713, 0x1100ff5c, 0x0a82d743, 0x6626f922, 0xf8256c82, 0xf9ffff10, 0x27288223, 0xff0436fe, 0x703dfbff, 0xdd210482, 0x265c82f4, + 0xff0c8201, 0x8229faff, 0x98002161, 0xe7212383, 0x214c82ef, 0x2d82e23a, 0x8248e121, 0x76fb213d, 0xdb202e82, 0x03219083, 0x2133827d, 0xdd82abdb, + 0x442b0b27, 0x75dfffff, 0x273d82c2, 0xff1e6503, 0x1203f6ff, 0xa2213382, 0x2095824e, 0x224c8242, 0x82927efc, 0xc4352113, 0x0c221e82, 0x1982a470, + 0xff00802b, 0x32730c00, 0xe5feffff, 0x200982e4, 0x22858263, 0x820ecdfd, 0xde102a1e, 0xfdffffb8, 0x00ff020b, 0x2323820b, 0xea06f1ff, 0x13830e82, + 0x0ad7ef22, 0xfd267b82, 0xffff90e2, 0x8b82baef, 0x8583fc20, 0x7a14f022, 0xdd26a982, 0xf0ffff2e, 0x1e829ad9, 0x82b6fc21, 0x4ff6279a, 0x0700ff1a, + 0x7b8266c6, 0x0982e420, 0x82950a27, 0x330000ff, 0x225c8232, 0x82527827, 0x827a200a, 0x4c282c5c, 0xf8ffffcc, 0x00fff223, 0x82146e26, 0x020b213d, + 0x0e221e82, 0x4d825c4f, 0xff0c2224, 0x14820f00, 0x830a0021, 0x47fe274c, 0x0e00ffae, 0x5c82bcf4, 0x8c8cfb2c, 0xcf2700ff, 0x0400ff5c, 0x0982f42a, + 0x82d82321, 0x386726b9, 0xc02300ff, 0x213d8200, 0x67823903, 0xf2bd0922, 0x5c825782, 0x190a0023, 0x2180829a, 0xec826866, 0x0866e639, 0xfd01ff0e, + 0x00ffcccc, 0x15008073, 0x1cbaffff, 0xa400ff28, 0x5b05cc4c, 0x0026059e, 0xff004029, 0xef82dcff, 0x831d0021, 0xd52208da, 0x00ffb85e, 0x08904208, + 0x0a00ff9d, 0x00ff46a1, 0xff9a591c, 0x20451900, 0xe1f3ffff, 0x2e00ff48, 0x8e82d863, 0x00a0fe27, 0x000500ff, 0x2fb28240, 0x00ff5443, 0xff94f802, + 0x3c1ffbff, 0x20feffff, 0xff288e82, 0xff33b335, 0x0a57b4ff, 0x7d266382, 0xffffce0c, 0x2982d5d0, 0x291cdc2d, 0x808cffff, 0xffff8b00, 0x829a1960, + 0xc2ae2344, 0x0c820790, 0x8257ee21, 0x830e20c0, 0xb3f12385, 0x6b18ff34, 0xec27071c, 0xff063433, 0x82c01700, 0x0f00222e, 0x25bd828c, 0xffae0719, + 0x2682f5ff, 0x40150022, 0xd7316383, 0x00ff5238, 0x05c2b551, 0xb50000ff, 0xffff07c4, 0x20b983d2, 0x22c88203, 0x82f8d8ff, 0x331b2c1a, 0xecffff34, + 0x00ff295c, 0x8248e126, 0x60fe216d, 0x0321b282, 0x2c048220, 0xffd8b000, 0x74d30300, 0x800200ff, 0x2104820d, 0x80824260, 0x9d820c20, 0x1c0c0023, + 0x214e8228, 0x2482e003, 0x06220484, 0xd282d7c3, 0x4926d121, 0xff2305a0, 0x82c0dffa, 0xe10e2529, 0xdeffff48, 0x21256c83, 0xffff3d4a, 0x239283e8, + 0x8b014027, 0x112d1a82, 0xff8b4821, 0x84eb0f00, 0x170500ff, 0x06ea614c, 0x0621083f, 0xffffb908, 0x059a19c0, 0xf7ffff91, 0x00ffbe7f, 0xff00c009, + 0x3829fbff, 0x400a00ff, 0x22388300, 0x82ae4732, 0x800822ed, 0x223e8242, 0x82e81b08, 0x5463269e, 0x0600ff91, 0x279a8300, 0xff0a572d, 0x0ad72700, + 0x08229a82, 0x3d82fce9, 0x821e3021, 0xcecc2190, 0xed835f82, 0x6466fb27, 0xb30b00ff, 0x21e38234, 0x14824c4a, 0x66666d22, 0x2109ec68, 0x63823e4a, + 0x8200c021, 0x400d2356, 0x06850800, 0x04821184, 0x6886ab21, 0x868209ec, 0xb02c1182, 0xf5ffffa4, 0xff8b1e45, 0x00c0f2ff, 0xff204f82, 0xff23c982, + 0x8229dcf1, 0xcc4c2615, 0x33f6ffff, 0x2e198233, 0x088bcecc, 0xff01ff0e, 0x01ff6666, 0x8248219a, 0x75a8276b, 0x2cfeffc2, 0x8b5f6666, 0xf7ff3706, + 0xffff8260, 0xffc295f3, 0x30fdffff, 0x5efeffff, 0x0800ffb8, 0x5082a49f, 0xc435bd27, 0xc76b01ff, 0x202982c8, 0x23ab82d2, 0x008053ff, 0xfd270a82, + 0xffff00a0, 0x824260f8, 0x83652066, 0x9efd277c, 0x0700ffba, 0x3082be9f, 0xc1f5dd27, 0x4c8500ff, 0x272582ce, 0xff8f82d1, 0x9a193bff, 0xfe210a82, + 0x27308220, 0xff84a0f7, 0x293cf4ff, 0xfe22ad82, 0x61824821, 0x827c5f21, 0xccd22730, 0xbb00ffcd, 0x2582cc4c, 0xff7fdc24, 0x5e8810fb, 0x5e83e020, + 0xca82bc20, 0x0eedff22, 0x2106094f, 0x93831f07, 0xa2e5a827, 0x551101ff, 0x2c29829c, 0xff00e0f9, 0x707d1400, 0x600f00ff, 0x200982c5, 0x270e82c0, + 0x8bb85e15, 0x0654f808, 0x05200e82, 0x00269c82, 0xff34330f, 0x1982edff, 0x33fcff35, 0xecffff32, 0x0e084861, 0xf7d4f7af, 0xfeff15b4, 0x820080f0, + 0xb3333c27, 0x4d00ff33, 0x00ff142e, 0xff67e657, 0xecd13200, 0xe66300ff, 0xff088b66, 0x68cc0a00, 0xff230718, 0x826666ff, 0x8280200f, 0xd7fe22c8, + 0x08b8820a, 0x90c28128, 0x00ffab07, 0x1528dc78, 0xe64800ff, 0xefffff66, 0x00ff5478, 0xffce4c3e, 0x98d9d3ff, 0x4c2800ff, 0xc3ffffcc, 0x2b82ecd1, + 0x67845020, 0x072f2a82, 0xffff94fb, 0x15d82367, 0x2b0714fb, 0x82b98b06, 0x1fc52451, 0x832b00ff, 0x2b13275b, 0x2600ff85, 0x76829a99, 0x5c0f422e, + 0x14fbeb06, 0xf7064b15, 0xd4f70714, 0x2005185e, 0x1d3f596b, 0x2b834420, 0x00ff8b23, 0x20768323, 0x260482e3, 0x34b31c00, 0x49dcffff, 0xdc2805f9, + 0xff8b33b3, 0xcd4ce3ff, 0xd3820483, 0x08201783, 0xfb218482, 0x17c75c44, 0x6e83db20, 0xf707ab25, 0x8214f7b4, 0x19422be0, 0x00ff0698, 0xff9c1913, + 0xac83d9ff, 0x82cc0a21, 0x99d426dc, 0x085d8b9a, 0x2d78832b, 0x01ff2f0e, 0xab9a195f, 0xe0feff15, 0x5382d6e3, 0x6666ee22, 0xf2277082, 0xffff0080, + 0x829a99f1, 0x4cef220a, 0x35d982cc, 0xffab0000, 0x66e6e0ff, 0xfeffff05, 0xffff1835, 0xff9a99ec, 0x96830f00, 0xff222582, 0xa6821000, 0xb4f70822, + 0x11206a82, 0x0fa97818, 0x34b31024, 0x3582ff08, 0x00ffbe2b, 0x059a191f, 0x010000ff, 0x82918242, 0x83ff208c, 0x0e002165, 0xed230983, 0x828b0080, + 0xe6493565, 0xd100ff66, 0xff159a19, 0x00c0e4ff, 0x9e1600ff, 0xd7ffffb8, 0xff270982, 0xff4861fc, 0x825ee9ff, 0x8218820e, 0x1eeb234f, 0x8b8272b8, + 0xf668e22c, 0x598000ff, 0xff79059a, 0xb3834d00, 0x3182b220, 0x992f002d, 0xb2ffff98, 0xffff7b94, 0x8268e6ee, 0xa8b2222c, 0x260a82f6, 0xffff842b, + 0x82717dcf, 0x23508219, 0x06011200, 0x7a210982, 0x287582e2, 0xfffa3e3c, 0x666630ff, 0x25c08405, 0xffd82351, 0xa9845600, 0xf4a81627, 0x191c00ff, + 0x06ff529a, 0xcc4c2822, 0xa2839782, 0x9a99162b, 0x24f80e08, 0xfc1594f7, 0x26468204, 0x8b0040ee, 0x82f1ffff, 0xf1ff2256, 0x3f9018b3, 0x54fb3907, + 0xb6568b07, 0x088bc060, 0xc00654f7, 0x8bb6b68b, 0x069b08c0, 0xc03d00ff, 0x00222c82, 0xde824032, 0x8b200482, 0x08201084, 0xff250685, 0xcccccdff, + 0x2d1b84ff, 0x3433c2ff, 0xfb8b088b, 0x067b1534, 0x378307eb, 0x4a097c4b, 0xe52206fe, 0xfd770080, 0x099f4d0d, 0xdbfeff22, 0xfb2ba683, 0xff15cc4c, + 0x67660c00, 0x4ff9ffff, 0xa45005b2, 0x4bac8305, 0xf220053b, 0x0021b382, 0x2304820a, 0x285cf5ff, 0x820fa544, 0x0b002316, 0x9b823eca, 0x2d840c20, + 0x571f0023, 0x05444a0c, 0x4c1d003d, 0xe4ffffcc, 0x00ff85eb, 0x085ccf0f, 0x9cf3ffff, 0x0700ff29, 0xffff5238, 0x82cd4cf8, 0x66662147, 0x0e223582, + 0x09459a59, 0x05504607, 0xd6e30a24, 0x7282ffff, 0x31828b20, 0x2705df67, 0xff0040f5, 0x2a1cf5ff, 0x82060945, 0xa6e03d06, 0x1000ff66, 0xffff7bd4, + 0xffc4b5e2, 0xec111b00, 0x38f0ffff, 0x00ff0850, 0x8b000070, 0x6321cea9, 0x21ce94d8, 0xce908ec2, 0x87ff8621, 0xae8420ce, 0x14ee21ce, 0x1121ce94, + 0x21ce8fec, 0xce87cdcc, 0x85991921, 0xf70e27ce, 0x9000ff94, 0x054d66e6, 0x55152008, 0x1a22099a, 0x90180080, 0x0c4d1746, 0x056c4d05, 0x015fff20, + 0x0cb84c09, 0x054d1682, 0xd5ff2c07, 0x00ff9a99, 0x159a1973, 0x82b9ffff, 0x7100277a, 0xff053e4a, 0x8f82f5ff, 0x10003608, 0xffffcc4c, 0xff6666e9, + 0x9a190400, 0x59f1ffff, 0xf3ffff99, 0xff085c8f, 0x5c0fd3ff, 0xe6d9ffff, 0xe0ffff66, 0xffff00c0, 0xffae47ca, 0x1f05f7ff, 0x05c3ffff, 0x261e821f, + 0xff9e2ffd, 0x82d9ecff, 0x670f2558, 0xeeffff6d, 0x00332882, 0x8b0a5713, 0x8500ff08, 0xff06cdcc, 0x71fdffff, 0x831c00ff, 0x330f2579, 0x1800ff33, + 0x24063143, 0x4c0e00ff, 0x272482cd, 0xff3233cb, 0x00407900, 0xf1279382, 0x00ff7a54, 0x82a4700c, 0xc4752688, 0xe5fbffff, 0x829c83e4, 0xb2ef2397, + 0xb282086e, 0xff90022a, 0x0ab78eff, 0x1600ff05, 0xff224e82, 0x4e82b3f1, 0x3e820f20, 0x19e7ff23, 0x22f3829a, 0x846666e3, 0x06ce2274, 0x228184ff, + 0x830f00ff, 0x211122cf, 0x21838248, 0x1482a430, 0x82472121, 0xf8f62646, 0x3c00ff52, 0x256582f0, 0xffcecce0, 0x04823500, 0x19d3ff28, 0x2600ff98, + 0x1e82cc0c, 0x5a828920, 0x84fffe21, 0xb3f3268f, 0xf8ffff34, 0x2180824c, 0xf98280f1, 0xce4cfb27, 0x66f0ffff, 0x84da8266, 0xffff2106, 0x00251683, + 0xff74b304, 0x232a83ff, 0xf2b20700, 0xb9284082, 0xffff9919, 0x059a998e, 0xdc34bc82, 0xefffff29, 0x00ff3eca, 0xffe1fa05, 0x8e02eaff, 0x7a1100ff, + 0xf8220982, 0xaa820040, 0x7c941e2b, 0x73f2ffff, 0x2100ff34, 0x206482cc, 0x22ad83f8, 0x829a9923, 0x8300205f, 0x28168206, 0x00ffead1, 0xff6a9c07, + 0x232a8300, 0xaa910d00, 0x11223582, 0x1482e27a, 0x8384c021, 0xffe02554, 0xecfc1500, 0x2a256883, 0x351000ff, 0x2b7e83c4, 0x00ff7a14, 0x05b85e71, + 0xe200ff0e, 0xef2d5183, 0xff156666, 0x6766d6ff, 0xb34200ff, 0x2f958234, 0xffcdccfa, 0x32330800, 0xb3f4ffff, 0x0100ff33, 0x2982e584, 0xccf9ff23, + 0x2a4082cc, 0xff9a19e2, 0x68e6e7ff, 0x83ebffff, 0xe6dc24fa, 0x82638666, 0x82fe2016, 0xf6ff2235, 0x25308233, 0xffcd4c07, 0x0983f7ff, 0xcdcc092d, + 0x06da088b, 0x00ff9f8b, 0x829a990a, 0x244582db, 0xcccc0f00, 0x20a68295, 0x2410821d, 0x9a99b0ff, 0x7d168215, 0x54220a22, 0x10848b7a, 0x06850820, + 0xf1ffff24, 0x067386ab, 0xeeff2105, 0x68821b82, 0x450bac7d, 0xbe55083e, 0x0e002106, 0xf1207b83, 0x0021b182, 0x05275511, 0xf0226684, 0xe28234b3, + 0x0080f62f, 0x99faffff, 0xf6ffff98, 0xffffcccc, 0x242582fc, 0x9a19f5ff, 0x2253828b, 0x82291cf5, 0xe8f52741, 0x0300fff6, 0xbd828440, 0x0522a883, + 0x1a82e265, 0x8f42d628, 0x33bdffff, 0x3b820532, 0x82fcc921, 0x78a9211a, 0x99302482, 0xf5ffff16, 0x00ff9c44, 0xff0de208, 0xaec7fbff, 0x1322d182, + 0x5a823373, 0xff72bd24, 0x5a831500, 0x0482fa20, 0x48160021, 0x16220560, 0xcf8252f8, 0xca831520, 0x8255052c, 0x7a1300ff, 0x0900ffe0, 0x35828841, + 0x0ce20827, 0x380400ff, 0x26548210, 0x00ffd698, 0x8224bb0a, 0x30c82168, 0x57215982, 0x2a7e830a, 0x00ffd037, 0x05ecd142, 0x824100ff, 0xa50023b5, + 0xca829819, 0x6065f831, 0x250600ff, 0xf4ffff20, 0xffff76be, 0x827c5ffe, 0xecd12134, 0xb6219d82, 0x21348346, 0xb3823e4a, 0x827b5421, 0xc00f2134, + 0xf622f482, 0x81413d0a, 0xeeff2505, 0x778b9a99, 0x4e237582, 0x8206c2f5, 0x10d82181, 0x07229682, 0x6d821a44, 0x827fca21, 0x22618347, 0x82ddc409, + 0x07fb2842, 0x2700ffae, 0x51ffa4f0, 0x232505d2, 0xffff9a19, 0x230482e2, 0x32331800, 0xa0271e82, 0x00ff9a99, 0x8234337a, 0x667b288b, 0xffff8b66, + 0x83999994, 0x829a2004, 0x2010820a, 0x24068508, 0x666b00ff, 0x22168467, 0x428400ff, 0x068305b8, 0x66201683, 0x7d820484, 0x2d821082, 0x28861e83, + 0x66666b24, 0x4382ffff, 0x8b088b23, 0x225f83fc, 0x8233f39e, 0x0cb1274d, 0x4e00ffcd, 0x318270fd, 0x90026122, 0x06823183, 0x92831182, 0xff221682, + 0x69416100, 0x85068305, 0xb1ff2316, 0x3882cc0c, 0x34f39e22, 0xff202d82, 0x3c210682, 0x2b1283ff, 0x0e088b2a, 0x3f01ffef, 0x54f89a19, 0xf322bd82, + 0x248232b3, 0x3433f524, 0x0482ffff, 0xf2260a82, 0xfc08cccc, 0x09850764, 0x0a00ff24, 0x1984cccc, 0x0c00ff22, 0x83056b5c, 0x00ff2406, 0x8432b30b, + 0x2a8e821b, 0x0834330d, 0xff0764f8, 0x82e60000, 0x860d82d4, 0x2039842f, 0x279584f1, 0x999996ff, 0x3354ffff, 0xf72fce83, 0x00ff3333, 0xff32331a, + 0x9a99e7ff, 0x821100ff, 0xe4ff3004, 0x088b6666, 0x33ceffff, 0xffff0633, 0x82b85ee4, 0xe736087c, 0xffff0a97, 0xff6666ee, 0x5c4ff7ff, 0xcce5ffff, + 0xffff08ce, 0xff7348d7, 0x66e685ff, 0xfaffff05, 0xfffff067, 0xffe23aef, 0x21100900, 0xe1edffff, 0x1000ff48, 0x188242c0, 0x08f46822, 0xae20ac82, + 0xfb2fdb82, 0x00fffcc9, 0xff00400d, 0x82110400, 0x830800ff, 0x52092279, 0x20488296, 0x05645465, 0x7a54ee27, 0x540e00ff, 0x0665437b, 0x85ab1122, + 0x00208682, 0x37820683, 0x18156e21, 0x260c09cb, 0xecffffff, 0x820524f7, 0x00002265, 0x24ec8206, 0x24fb1400, 0xafa88205, 0x00ff2443, 0x8234339b, + 0x0a062746, 0xf9ffff7f, 0x97826c07, 0xffb4a826, 0x94b8fbff, 0x4c21ca82, 0x268083cd, 0x8b105803, 0x820300ff, 0x000023e1, 0x09820488, 0xdc826120, + 0xec1f0122, 0x1021d782, 0x22cd82c0, 0x82109805, 0x5c0f252b, 0x201200ff, 0xf620f184, 0xc2219582, 0x32d78290, 0xffb525d9, 0x2e1d7a00, 0xaaffff05, + 0x00ffcd4c, 0x54cccc4b, 0x32471338, 0x09eb530b, 0x10364918, 0x18113949, 0x24106463, 0x9a197f01, 0x2162838b, 0xb282fe7f, 0x22169547, 0x546866eb, + 0x4e540625, 0x25068306, 0x4cecffff, 0x629cffcc, 0x2c064755, 0xff32337f, 0x9a193aff, 0xd7ffff15, 0x22f4824f, 0x829a197a, 0x4af722df, 0x08474240, + 0x47429820, 0x8b682d08, 0xceffff08, 0xff06b81e, 0xf668e4ff, 0x21084742, 0x4742f668, 0x0ad72207, 0x21468208, 0x4742ae47, 0x42202013, 0x03211147, + 0x2c2e826c, 0xffeedcfe, 0x1a6f0300, 0xddffffff, 0x2609822e, 0x00ffde64, 0x824e0200, 0x05ef2c19, 0xcfffff1e, 0xb3051298, 0x42072b06, 0x5121080c, + 0x065042ec, 0xaec71022, 0x00208f82, 0xff240683, 0x52380f00, 0x220b5042, 0x969b07eb, 0x85ac2033, 0x8bac2133, 0x54203383, 0xff30338d, 0x98192700, + 0xf0ffff06, 0x00ff9002, 0x05e2fa2f, 0x57218e82, 0x2229828c, 0x82b06703, 0x04882194, 0x5f230f82, 0x4200ff7c, 0x2e08052d, 0xffbc5e14, 0x62900500, + 0x1200ff94, 0xffff3233, 0xff6466fa, 0x34b31000, 0x01ff0e08, 0xffccccf6, 0x66e6b700, 0xafffff15, 0x00ff48a1, 0x66b85e50, 0x2f290758, 0x980548e1, + 0x1e0d00ff, 0x235882b8, 0x7e004015, 0x21270b82, 0xffff0848, 0x820080d0, 0x00802675, 0xf2ffff05, 0x823382e1, 0xffff2421, 0x8270bdea, 0x830f83f9, + 0x21258314, 0x2a82b81e, 0x4e821e20, 0xaeafff27, 0x4f00ff16, 0x23a6827a, 0x66e6f9ff, 0xe0218b82, 0x05ab6800, 0x60030022, 0x99210983, 0x23eb829a, + 0x0080f7ff, 0xf7204182, 0xff225182, 0x1682a0fc, 0x4083fa20, 0x0020fa22, 0x9f214b82, 0x820f8240, 0x21718204, 0x56829ef3, 0x2a84f320, 0x2a82eb20, + 0x610c0025, 0x82ffff48, 0x8208200f, 0x212583bb, 0x71839eaf, 0xcd4cf62c, 0x19f6ffff, 0xff55059a, 0xae821800, 0xb3c1ff28, 0xffff8933, 0x1682cccb, + 0x5284e420, 0x8380f725, 0x83fbffff, 0x83fe207e, 0x3ef4268d, 0x0600ffb8, 0x206682c0, 0x26e383f9, 0x9a996b00, 0x8494ffff, 0x83ee20e3, 0x40ee2187, + 0xfd20ee83, 0x00222f82, 0x2582c000, 0xa182fd20, 0xe0000022, 0x80180983, 0x9e2111f0, 0x23c882b8, 0x084861ee, 0x94820683, 0x74180020, 0x9e201141, + 0x12997518, 0x00ff8b23, 0x225b8302, 0x820020ff, 0x216a8209, 0x3c83ffff, 0x00a00222, 0x1120dc82, 0x00251982, 0x0548e111, 0x219b86ff, 0x0a826666, + 0x2583b185, 0x82de0b21, 0x830120c0, 0x82042039, 0x080022ef, 0x2b348380, 0xff48e11b, 0x00403400, 0x3e00ff8d, 0xff2b2482, 0xc1b87ee7, 0x00ff9508, + 0x827cdf09, 0x8350203c, 0xa3af2212, 0x06a573d8, 0x9ef3ff22, 0x14214282, 0x26bc821e, 0xe27a0b00, 0x820c00ff, 0x00ff22c1, 0x82788360, 0x33258204, + 0xff0ce206, 0xcae10500, 0x660300ff, 0xff8b9466, 0x9a990700, 0x2408e382, 0x66660800, 0x99fcffff, 0xffff949a, 0x913233fa, 0xe4feff08, 0x00ff34b3, + 0x1534b342, 0x19bbffff, 0x4400ff9a, 0x20ad83e6, 0x22a38349, 0x8200c049, 0xdc44224a, 0x271a822a, 0xff05b81e, 0x842bb6ff, 0x3a260482, 0x38f705e2, + 0x308e38fb, 0x49207b83, 0x4420f484, 0xff22ca82, 0xff8221bb, 0x45b6ff23, 0x2730821e, 0x0e050a17, 0xecf76cf7, 0xf2253182, 0xff8bcdcc, 0x216918ff, + 0xccf2220a, 0x209782cc, 0x520682ff, 0x1b82054e, 0x0d298f82, 0x088b0040, 0x684f00ff, 0x25ba82f6, 0xff0a9740, 0x0a83bfff, 0x97b0ff23, 0x09ab7a0a, + 0x82cccc21, 0xcc4c2649, 0x330d00ff, 0x832d8334, 0x82448206, 0x06e47516, 0x2106aa52, 0xf382e669, 0x0482a920, 0x82560021, 0x96ff27e0, 0x088b9a19, + 0x8c82f393, 0x89454718, 0x66e6dc2a, 0xff15eefb, 0xb85e1b00, 0x052a0484, 0xa00200ff, 0xffffff00, 0x09820060, 0x821b6f21, 0x761e2109, 0xc0210982, + 0x20e88300, 0x24068211, 0x3d0e00ff, 0x28048271, 0xff8b9042, 0x70bd1100, 0x26068308, 0xffffb89e, 0x828fc2f1, 0xd8632516, 0x40eeffff, 0xff242d83, + 0x8b4861ee, 0xa1211682, 0x42048247, 0x5e2105ee, 0x222d82b8, 0x8220fdff, 0xcf00245b, 0x43ffff56, 0xc0210521, 0x27098206, 0xff080060, 0x0f8de4ff, + 0x9c2c0482, 0xffff056c, 0xff852b8b, 0x66e67400, 0xf8210a82, 0x212f82c0, 0x95824007, 0x4821f325, 0x82feffff, 0xfcff240e, 0x82821f05, 0x83d62030, + 0x1eb22115, 0x0b21bb82, 0x268282de, 0xff142e9d, 0x82a14100, 0x4cbe2324, 0x0a8208ce, 0xffb99e2b, 0x4661beff, 0xfa6200ff, 0x05b971e1, 0xcc4d0028, + 0x2900ffcc, 0x1e8202c0, 0x0020092b, 0x0100ff90, 0x00ff4841, 0x2054830c, 0x23c682f8, 0x00400700, 0x8a225882, 0x7e82e27a, 0x0566a635, 0xf730fb0e, + 0x1554f8d4, 0xfb0654fb, 0x0514fb14, 0x8207d4fb, 0x82dc20d4, 0x1c00212e, 0xff210482, 0x218182e3, 0xf0832300, 0x0694f723, 0x5d5f18ff, 0x059d6015, + 0xff212482, 0x058752ff, 0xdc333883, 0x088b34b3, 0x34fb34fb, 0xeb065b15, 0x2b06bb07, 0x938bdb07, 0x2580820a, 0x1514f88b, 0x77b114fc, 0x07d4f725, + 0x82f714fb, 0x065422b3, 0x5d5f18ff, 0x74f72e15, 0x4b1554fb, 0xcb07cb06, 0xeb074b06, 0x200a848b, 0x18c682ab, 0x2814486a, 0xfb4b076b, 0x06cb1514, + 0x2089836b, 0x51f782ee, 0xcd830699, 0x8b220e82, 0x48826b08, 0x828b2b21, 0x074b2221, 0x200a894b, 0x0cc8516b, 0x180e0021, 0x2608657a, 0xeb8b07ab, + 0x8294f715, 0x94fb2179, 0x8b252e82, 0xff8b15cb, 0x20798200, 0x862383ff, 0x220e8204, 0x82ab088b, 0x064b2822, 0x2f0e07ab, 0x4a8f01ff, 0xb45c068d, + 0x7dea2205, 0x13184870, 0xf6681622, 0x675c1684, 0x1674480e, 0x935dea20, 0x99e43308, 0x8b088b9a, 0xff1554fc, 0xbe3ff7ff, 0xf8ffff8b, 0x048342c0, + 0x0a820020, 0x0040f723, 0x51068508, 0x1b8205f4, 0xffff002d, 0x8b6666f6, 0x9fffff08, 0x9d0670fd, 0x07002233, 0x244a8540, 0xbf0800ff, 0x263382be, + 0x90026000, 0x5200ff06, 0x8221067d, 0xaf521890, 0xffff230c, 0x288270fd, 0x85cccc21, 0x0700236b, 0x6b863433, 0xffa2fb26, 0x9a19fcff, 0xf428a182, + 0xff8bf6a8, 0x66260000, 0xa3261982, 0xf4ffffd8, 0x56823d8a, 0xedfbff23, 0x27a6820e, 0xff37e9fb, 0x18840100, 0xf3322c82, 0x0300fff8, 0xff08e81b, + 0x1e05bcff, 0xe34300ff, 0x158205d6, 0x82dfef21, 0x82202015, 0xe5fb22c1, 0x262982e3, 0xffff2090, 0x841fe5fb, 0xe3e52140, 0x16824083, 0x70feff22, + 0xfc221682, 0x2f821bef, 0x82c0df21, 0xd7fc2240, 0x220a828d, 0x82ffecf1, 0x821a2019, 0x66e62230, 0x2005848b, 0x82068508, 0xdf8f2147, 0xe5211082, + 0x825b83a2, 0xeefc23ee, 0x718208da, 0x8448e121, 0xff05247b, 0x82600900, 0xa0f62715, 0x0c00ff00, 0x2982c936, 0x09836020, 0x82b85e21, 0x0d002376, + 0xce82e13a, 0x0b571922, 0xfd21f782, 0x220a82f4, 0x82345e10, 0x0000273c, 0x0b00ff8a, 0xe482a430, 0xff99192b, 0xcecc0400, 0xe6f9ffff, 0x2d318367, + 0xff33b32c, 0x9a19af00, 0xa2ffff15, 0x04826666, 0x82cc4c21, 0xbff922d9, 0x202182be, 0x21d982c0, 0x0482e0fc, 0x5ccff722, 0xf7229c82, 0xa383ecd1, + 0x8240e721, 0x9116216f, 0xf820bf82, 0x00212082, 0x05ec7d09, 0x42400822, 0x08226e82, 0x1141bf3f, 0x06002805, 0x00ff4821, 0x82004006, 0xe35b237d, + 0x5382e7d8, 0xb8dee127, 0x1e1e00ff, 0x210a82b8, 0x8f8201fb, 0x82060521, 0x99fb216e, 0x072e6218, 0x9a19fc22, 0x19363082, 0xffff089a, 0xffcc4cd1, + 0xcccc7400, 0x6900ff15, 0xff060180, 0xa482ecff, 0xb3eeff23, 0x2f3a8234, 0xffebd1ea, 0xc2f5edff, 0xdefeffff, 0xe8ffffb9, 0xa9827d82, 0x837a1421, + 0x11ef2299, 0x264282ec, 0xffffcdcc, 0x82c2b5ef, 0x48e126f0, 0x1ef4ffff, 0x278282b8, 0xff90424e, 0x00c0b1ff, 0xad224082, 0x7a43ce4c, 0x122e4807, + 0x83059b45, 0x096243e1, 0x5900ff24, 0x33824861, 0x9e0c0029, 0xfaffffb8, 0x49ffbedf, 0xf634050c, 0x00fffafe, 0x0848e108, 0xfdc2ffff, 0xff05c870, + 0x06800000, 0x00200483, 0xbf200482, 0x00211b82, 0x20098320, 0x82048580, 0x82522085, 0x52002385, 0x29824861, 0xf8b30732, 0xb30700ff, 0x0400ffb6, + 0x00ff980e, 0x8b022b0a, 0x61210582, 0x33c68248, 0x3e0a1600, 0x23eeffff, 0x1100ffd6, 0xffff14ee, 0x8b9ad9e9, 0x32226282, 0x5682cc8c, 0x82d60321, + 0x19ef23c2, 0x2a468b99, 0xf1ff2305, 0x0a82cccc, 0x3433ee22, 0xff203882, 0xff240682, 0x713d0e00, 0xcc201b82, 0x10302c82, 0x088b67e6, 0xb001ff0e, + 0x01ff9a19, 0x15e2fa5f, 0x08496118, 0x43e07a21, 0x82210828, 0x2639828e, 0x90821a00, 0x43eaffff, 0xd360063f, 0x85ea220e, 0x081e441e, 0x82707d21, + 0xe5ff232d, 0x3f82727d, 0x84e27a21, 0x2a548216, 0x088b0080, 0x8afeffda, 0x821584eb, 0xfa0d21c5, 0xf42c1882, 0x00ff86ab, 0xff52f809, 0xa470f3ff, + 0xed22be83, 0xa882281c, 0xf6a8ff27, 0xe3ecffff, 0x216282d6, 0x16837c14, 0x2486fa22, 0xfa271682, 0x00ff249b, 0x82bc1401, 0x4e022233, 0x32ec82da, + 0xff323378, 0x90424600, 0x3100ff05, 0x00ff6626, 0x82ecd149, 0x72052c0a, 0x0800ff2e, 0x00ffb21d, 0x82dca402, 0x8246205e, 0x0900243b, 0x5508723d, + 0xff2e0535, 0x5839fbff, 0x540c00ff, 0xf6ffff7c, 0x20829eaf, 0x82842b21, 0x9ed72c4b, 0x2800ffb8, 0xff05717d, 0x82e695ff, 0x1935224b, 0x2c0a8299, + 0xff3e8aff, 0xfadefcff, 0xccffffff, 0x210982cc, 0x8782cccc, 0xce48fc20, 0x59ef2c05, 0x0600ff9c, 0xffff4656, 0x82b7deef, 0x3f152150, 0xeb2cc682, + 0x00ff0885, 0xffad074b, 0x3ecab4ff, 0xd2274082, 0xffffb81e, 0x82703dbb, 0x003a270a, 0x6600ff02, 0x0a82e23a, 0x5278fc22, 0x2805927e, 0x3333fcff, + 0xe60000ff, 0x215b8266, 0xea833d4a, 0xb8bef122, 0xf6276282, 0xffff3353, 0x82ce4cf4, 0xb3f3220a, 0x2db98232, 0xb653f7ff, 0xbc0400ff, 0xf7ffff29, + 0xdf820ca2, 0x829a3921, 0xcecc29c8, 0xff1cf808, 0x666635ff, 0x0b27f782, 0xffff48e1, 0x82be7ffa, 0xec91268a, 0x61fdffff, 0x210982ca, 0x548246a1, + 0x0f260023, 0x3a65825e, 0xffaa1c0f, 0xcc4c1900, 0x1100ff8b, 0xfc089a99, 0x7901ff1c, 0xff153473, 0x8266f5ff, 0x73e9227f, 0x21448232, 0x7882b305, + 0x3433fd29, 0xfeffff91, 0x83919a99, 0x2709223c, 0x2731822b, 0xff6ff208, 0x32330300, 0xf526f282, 0x0500ffc2, 0xe882eae6, 0x8f422f27, 0x7de8ffff, + 0x23d28272, 0x8b00e0ff, 0x0682ad82, 0xffffff24, 0x0482f9df, 0x8200e021, 0x80722521, 0xc7ffff01, 0x0024ff83, 0x98908220, 0x06276182, 0xffff4260, + 0x7ab8deec, 0xf32207df, 0xce82b8de, 0xff06a12b, 0xb91ef6ff, 0x5e0b00ff, 0x20c582b8, 0x263b8340, 0xffd6233a, 0x83e6e3ff, 0x9b042cdb, 0xfdffffe8, + 0x00ff87b6, 0x8292d804, 0x98ee219a, 0xce210982, 0x219e8316, 0xd083cc12, 0x162e0d27, 0x6e0f00ff, 0x23a98214, 0x08008010, 0x0b270682, 0xffff71bd, + 0x82fc89f9, 0x295c2652, 0xb8f4ffff, 0x2cb58294, 0xff089999, 0x52f8cbff, 0x191a00ff, 0x26b5829b, 0xff48e1ee, 0x82263300, 0xf9ff3562, 0x00ff3e74, + 0xffce9712, 0x9a99e9ff, 0xb31800ff, 0xe0ffff34, 0x22052851, 0x828e57f8, 0xd6f731da, 0xfeffff86, 0xfffffa7e, 0xffd863f7, 0xea91fcff, 0xae224b82, + 0xee82e0ba, 0x82c09f21, 0x80c1274b, 0x1e00ff00, 0xd88250f8, 0x4e020027, 0x580000ff, 0x2104829c, 0x04822001, 0x828c5821, 0x58002290, 0x36978394, + 0xff48210e, 0x3188f8ff, 0x910d00ff, 0xf2ffffea, 0x00fff893, 0x827cd406, 0xe0f4274b, 0xeaffff69, 0x4b82de4f, 0x1f45dd27, 0x050700ff, 0x220a8220, + 0x82f6a8ff, 0xec112641, 0xb3ffffff, 0x21098233, 0x09828e02, 0x82f6a821, 0xfdff23fa, 0x97828155, 0xd763fd27, 0xd2fdffff, 0x220a82b0, 0x826ee7fc, + 0xfeff2362, 0x2882e886, 0x82e4a521, 0x7a8926ae, 0x290100ff, 0x32098279, 0xff089af9, 0x42601900, 0xefe8ffff, 0xaf0e051a, 0x18f7e4f7, 0x235dade7, + 0xd4fb6cf7, 0x0e494718, 0x58004021, 0xf2220955, 0xa35f00c0, 0xf5ff2205, 0x59098240, 0xba230652, 0x82060080, 0x008024a6, 0x42b200ff, 0x4d1805d5, + 0x082b0830, 0x00ff3e4a, 0x8b5c8f0b, 0x450d00ff, 0x11200502, 0xff341b82, 0xffb89ef1, 0x33330e00, 0x5eeeffff, 0xff088bb8, 0x9a19d4ff, 0x0a2cfd82, + 0xffff0510, 0xffd8e3e5, 0x53383500, 0xf3200a82, 0x19265283, 0xff740080, 0x31821200, 0x82e5ff21, 0x0600233b, 0x308200c0, 0xaec7b827, 0x261500ff, + 0x2c258266, 0xff6686f8, 0xaad10100, 0x65f8ffff, 0x2145821f, 0x0982bedf, 0x83717d21, 0x23eb2256, 0x31bc82d7, 0xff299ceb, 0x6025f9ff, 0x17efffff, + 0xf3ffff0a, 0x40824e22, 0xcb4cd827, 0x81e1ffff, 0x214082f8, 0x8882b3f7, 0x34b3f92c, 0xccfaffff, 0xf7ffffcc, 0x34826666, 0x0080f523, 0x20068208, + 0x22c083f1, 0x8246b608, 0xe17a2140, 0x51205c82, 0xff226682, 0x408247a1, 0xbebfca27, 0x33f1feff, 0x22408234, 0x18b81ed5, 0x22083942, 0x540040f5, + 0xfd530b00, 0x4dba8208, 0xf82b0a42, 0x00ff0674, 0x8b00c027, 0x822000ff, 0x82048330, 0x8210820a, 0x53002073, 0x4c2205f9, 0x3354ffcc, 0xb3f22205, + 0x2ecb8234, 0x9a99fbfe, 0x19d0ffff, 0xffff159a, 0x8299199f, 0x192b273e, 0x5a00ff99, 0x808252f8, 0x8f02ea27, 0x190c00ff, 0x250a829a, 0xffb8def3, + 0x53820700, 0x23f6ff2d, 0x0900ffd7, 0xffffd6a3, 0x820080f8, 0x48e12c4b, 0xc1ffff08, 0xffff1f85, 0x82cc4c7c, 0xa8e72229, 0x25d082f7, 0xff0590c2, + 0x2f823400, 0x66050123, 0x2d0a8266, 0x8c002004, 0xfc0300ff, 0x0100ffac, 0x098293d8, 0xffc5a027, 0x00c00200, 0x069e6208, 0x33731e22, 0x05272582, + 0x00ff2dd2, 0x82287c04, 0xfc09216a, 0x49211f82, 0x06cc1838, 0x60052109, 0x0127ca82, 0xffff77fe, 0x82bac9ff, 0xeedc2145, 0x8e210982, 0x27408272, + 0xffe1ba0e, 0xf49dfbff, 0xda277c82, 0xffff1283, 0x82219fa8, 0x82fc200a, 0xf7ff299d, 0xffff67e6, 0xff6666fe, 0x32067e41, 0x089a99f7, 0xe9ffff8b, + 0x00ffa4f0, 0xff856b0b, 0x82b0eaff, 0xfd132709, 0xf4ffff71, 0x4b826626, 0x53f85426, 0xd9cdffff, 0xe627f283, 0xffff1e85, 0x821ec5ae, 0x836e2097, + 0xe6ff2d4b, 0xffff1566, 0xff866bd4, 0x00200000, 0x17271582, 0x00ff9a99, 0x82e27a4b, 0x3801220a, 0x21b88294, 0x1a826250, 0x82809521, 0x42602109, + 0x0422ac82, 0x6c820a57, 0x87100023, 0x257e82ae, 0x00ff2671, 0x8882e60f, 0xe425f131, 0xe80800ff, 0xffff08f6, 0xff3ecac2, 0x82192400, 0x1f00276c, + 0x00ffec51, 0x4b833a4e, 0x90421434, 0xa3d6ffff, 0xff9305d6, 0x00c0efff, 0xdc1000ff, 0xd05cff2a, 0x40122305, 0xa4828b00, 0x104e2127, 0xf1ffffff, + 0x2ae582ec, 0xfbcecce6, 0xef0e0544, 0x753f00ff, 0x002305cc, 0x82c33503, 0x4002227b, 0x25228200, 0x00ff90c2, 0x9f662e02, 0x5c352608, 0xfbffff29, + 0x20b58219, 0x2d048232, 0x1e05e2ff, 0x331d00ff, 0xd1ffff33, 0x56823e4a, 0xcd4c0432, 0x33f9ffff, 0x4bb30532, 0x194600ff, 0xd9ffff99, 0x00212682, + 0x05cc5e4b, 0x34331e22, 0x18215782, 0x82908280, 0x820a8204, 0x23348210, 0x07cc4c29, 0x2408216f, 0x00ffcc4c, 0x2704830e, 0x8b34b311, 0xff06cb08, + 0x0ce05418, 0x311f826f, 0x568b072b, 0x8b566060, 0x4b076b08, 0xfb07ab06, 0x08850654, 0xcaffff31, 0xff8be1fa, 0x1e05d5ff, 0x08c08bb6, 0x6e0734f7, + 0x54210df5, 0x1a80837c, 0x6e074d90, 0x1f2b13f2, 0xff069a19, 0x68e64002, 0x8215fcfb, 0x18cf2048, 0x211360ba, 0x8d1817fe, 0xcc2011d5, 0x0820d985, + 0xff240685, 0xe13a0f00, 0x1029e086, 0x088b1fc5, 0xe6e801ff, 0x0c417166, 0x830a0021, 0x0d0025e4, 0x9308cc4c, 0x41171641, 0x83281614, 0x94f70e07, + 0xff1534f8, 0x2607bf76, 0xffffe869, 0x8266e6a2, 0x198d22af, 0x3582829a, 0xf668ceff, 0x631500ff, 0xd2ffffd7, 0x00ff0a97, 0xff9a9923, 0x6982dcff, + 0xf3ffff33, 0xffff0080, 0xff289ccd, 0xa430d6ff, 0x17d3ffff, 0x05af660c, 0x80ffff29, 0xffff0800, 0x826acefd, 0x34b32104, 0x673d1482, 0xfcfffffd, + 0x00ff9899, 0x88034801, 0x0000ff08, 0xff889a69, 0x87b60300, 0x33feffff, 0x21098234, 0xd782df2f, 0x4f420023, 0x2af3825c, 0xffa4b031, 0xcccc1f00, + 0x821800ff, 0x1300236b, 0x31822a9c, 0x33b32022, 0x19837082, 0xcd4c242c, 0xe6f8ffff, 0x2600ff66, 0x4a776666, 0x5d00280d, 0xff8b9a19, 0x18e67200, + 0x2109de8f, 0x2882668d, 0xdf851682, 0xa7209582, 0x10223e83, 0xf1829a19, 0x9999fc25, 0x82ecffff, 0xeeff2368, 0x5d826766, 0xd9821920, 0xcccce622, + 0xff295382, 0x8b10f8fb, 0xc7fbffff, 0x20ab82ef, 0x22e58250, 0x82f5a8fb, 0x83b02009, 0x97f822d6, 0x82c7820a, 0xf7ff24b5, 0x828ec2b5, 0x2294838a, + 0x8232b302, 0xb0f7225b, 0x32108221, 0xff8340fa, 0xf6a80900, 0xf80200ff, 0x0800ff52, 0x89085c4f, 0x00ff280a, 0xffb89e07, 0x83b80500, 0x48612619, + 0x33fcffff, 0x271e8234, 0xffa0fa06, 0x8480fdff, 0x8d211e82, 0x2509820f, 0x00ff8a0c, 0x8f825906, 0xd202ff22, 0x0b271e82, 0xffffa470, 0x82ec3cfe, + 0x21be8257, 0xa9820200, 0xcc000028, 0x0400ffcd, 0x1e829a99, 0x910d0122, 0xe9265282, 0xf4ffff78, 0x6b82651b, 0xffe87b2b, 0xae47f2ff, 0xf10300ff, + 0x229682aa, 0x8247e1f3, 0xf087260a, 0xd7dfffff, 0x2142820a, 0x2d826270, 0xff66a627, 0xae072100, 0x24438208, 0x00ffdf0f, 0x278b8217, 0x7d3f1700, + 0x870c00ff, 0x1e203882, 0xff23d482, 0x82142efb, 0xe705211e, 0xff223882, 0x90820218, 0x82b48821, 0xee0f2185, 0x26210982, 0x21a48266, 0x1e8200e0, + 0x10580822, 0x20210a82, 0x26478200, 0xffff9e6f, 0x8300e0f6, 0xff42250e, 0xf6a8f7ff, 0xfd227b82, 0x0a82aa31, 0x82399421, 0x4de62019, 0xff230647, + 0x829a99f7, 0x67e621a4, 0xfb241e82, 0x00fff0a7, 0x21050875, 0x0982ef67, 0xff21702b, 0x17d9fbff, 0xa70000ff, 0x211e82ef, 0x8b82c7f4, 0x23820120, + 0x80f6ff22, 0xf0265783, 0xffffff13, 0x23825238, 0x820d8021, 0xfdfe2c1e, 0xfaffff70, 0x00ffe04f, 0x8267660a, 0x33b32176, 0xcc260982, 0xfcffffcd, + 0x9a8266e6, 0x82001121, 0x19fb2133, 0x1f236c82, 0x828234b3, 0x33332629, 0x99deffff, 0x201a829a, 0x252a8298, 0x66e6efff, 0x9d828b15, 0x2966d918, + 0xff07bb31, 0x5ccfecff, 0x68e6ffff, 0xffff05f6, 0x8220f0f9, 0x2204833e, 0x821383f2, 0xeef92749, 0x0800ff15, 0x9a82e00f, 0x00252583, 0x050a9719, + 0xc9d9185b, 0x82eb202e, 0x06002c2f, 0x00ff00e0, 0xfff06704, 0x82390500, 0x880627be, 0x0300ffb4, 0xb8827a14, 0x82800621, 0x18022719, 0x0700ff10, + 0xf282c335, 0x2382d820, 0xf5280422, 0x7721dc82, 0x2a1e82f6, 0xffa43023, 0x291cd1ff, 0x8300ff05, 0x2e00230a, 0x0a8215ee, 0xe1820420, 0x87050022, + 0x072c2a82, 0x00ff763e, 0xfff81e02, 0x52780600, 0xf0213e82, 0x22348222, 0x823e8a06, 0xaec7210a, 0x66217282, 0x21d58266, 0xcb8366e6, 0x089a192b, + 0x00ff072b, 0xffcc4c77, 0x072f4300, 0x2f439a20, 0x20278208, 0x052f43f3, 0x2f43ce20, 0x2062820b, 0x052f4300, 0x2f43f620, 0xc0f72107, 0x012db182, + 0xffff0040, 0x8ea4b0f7, 0xaef8ffff, 0x22828214, 0x8308f0a7, 0x82202010, 0x40fa2210, 0x202f4384, 0x9ad90427, 0x610800ff, 0x068e6d48, 0x2f430020, + 0x430e200b, 0x4720172f, 0x09228d82, 0x6d820a57, 0x82101821, 0x27e0848d, 0xff082090, 0x920d0100, 0x20082f43, 0x132f4364, 0x2f434820, 0x8207201c, + 0x052f4357, 0x57823820, 0x82052f43, 0x452f43e4, 0xff002030, 0xf0a7f7ff, 0xeff6ffff, 0xfbffff5c, 0x0e82b488, 0xfc829920, 0x6ce70222, 0x820e2f43, + 0x43012085, 0x1620052f, 0x21082f43, 0xdd825ccf, 0xde413d84, 0x0d2f4305, 0xbedfff2c, 0x54faffff, 0x0a00ffbd, 0x2f436666, 0x43cc2008, 0x9c20052f, + 0x4306a447, 0x3220072b, 0x30052b43, 0xcc01ff0e, 0x00ff34b3, 0x156666c6, 0xe00500ff, 0x82268284, 0x060023ec, 0x4182ce97, 0xff64db24, 0x2f560600, + 0xc20a2d05, 0x00ff8b90, 0xff3c4a15, 0x6d670800, 0x17230a82, 0x8208e590, 0xbd092206, 0x26328271, 0x00fff893, 0x82b89e09, 0x829f20cc, 0x4a062220, + 0x2ccc823d, 0xff008090, 0xe27a5300, 0xf2ffff05, 0x200a8240, 0x2304820a, 0xc2b5f0ff, 0x2b204082, 0xef206682, 0x00232e82, 0x82b85e05, 0x57c02229, + 0x205a820a, 0x2729833a, 0xff48e1e5, 0xb81e3400, 0xfa2c3482, 0x00ff3769, 0xff862b0b, 0x63b0f4ff, 0x2306d142, 0x8b1e45f4, 0xee283082, 0xff8b3333, + 0x5ccff1ff, 0x87210482, 0x220a82ae, 0x82c275ee, 0xfbff288c, 0x00ff6e32, 0x82041601, 0x06212691, 0x490200ff, 0x260982ba, 0xff088c6c, 0x821e1d00, + 0xe1c5239c, 0xe4820548, 0xff21df82, 0x227d83f4, 0x82cdcc09, 0xae8724b1, 0x830c00ff, 0xdefb211e, 0x00288c82, 0xff347310, 0x607afaff, 0xd6218182, + 0x220482d6, 0x821e65eb, 0x33ea3105, 0xf5ffff33, 0xffff9a19, 0xff6666f2, 0x9a19eaff, 0xe7227582, 0x75839999, 0x67e6ca22, 0xb5272182, 0xffff67e6, + 0x82cc4ce7, 0x99f2220a, 0x82778299, 0xf7ff27fe, 0xffffcc8c, 0x2c8399f3, 0x254af220, 0xf3f32205, 0x27cb8234, 0xff840601, 0x75530400, 0xf5212682, + 0x27d082c2, 0xffeb51d9, 0xd8230e00, 0xe52b3c82, 0x00ff48a1, 0xff327309, 0x82e10700, 0x83182009, 0xdce6226e, 0x22f68329, 0x827b54ed, 0xb3fa2175, + 0xee228a82, 0x0a820ad7, 0xec11f923, 0x21068208, 0xf68272f7, 0x15ae0d2b, 0x3bdfffff, 0x2500ffa6, 0x26208273, 0x08a470f2, 0x836c01ff, 0x337b22b1, + 0x2ef68232, 0xff52780a, 0xec91fcff, 0xfeffff95, 0x82953433, 0x0c00244f, 0x828b0080, 0x261882fb, 0x64bb0200, 0x820b00ff, 0x050032b2, 0xff080080, + 0x16b90800, 0xff0300ff, 0x0500ff3c, 0x22aa8220, 0x8286b608, 0x0f092229, 0x286e825c, 0x86ab1200, 0xd9eeffff, 0x261b829a, 0xffff3c4a, 0x820a17f9, + 0xfcff224c, 0x284c82a0, 0x1ea5fcff, 0x3fffffff, 0x216a82e0, 0x698266bb, 0x85828020, 0xe3faff27, 0xfdffff96, 0x22048283, 0x829278fa, 0xb4c82614, + 0x6efaffff, 0x22358316, 0x82307dfb, 0x76fb26c0, 0x0000ff44, 0x324c82cc, 0xff96a3fb, 0xf4900100, 0xa5ffff08, 0x00ffec51, 0x82b81e21, 0xa00826bb, + 0x0400ff00, 0x28048220, 0xffaee706, 0x90a20700, 0x05a676ff, 0x46210a22, 0x1527ac82, 0x00ff48e1, 0x829a1965, 0xb5002229, 0x21b78266, 0x4e82c255, + 0x09845720, 0xb7824020, 0xfe540322, 0x0e22b783, 0xad82f6e8, 0xff101822, 0x2e054f69, 0xff6abcf3, 0x0a170900, 0xcbffff08, 0x82b270fd, 0x0242213c, + 0x1e225782, 0x0a820080, 0x7c7f5339, 0x03c2ffff, 0xffff0596, 0xff98996f, 0xce4cccff, 0xecffff15, 0x822f0a57, 0x94ff2211, 0x21c5825a, 0xe982c400, + 0x8206d421, 0x60052109, 0xfe22c382, 0x6482a410, 0x08fbff23, 0x26c08232, 0xffff9643, 0x82e846fb, 0xaa1121a5, 0xae260982, 0xffff0856, 0xbf828056, + 0x707d3d22, 0x22069759, 0x82400000, 0xdd02220f, 0x21aa82f4, 0x2982de31, 0x0029e383, 0xe0080ee0, 0x611c00ff, 0x21258248, 0xd682a113, 0x35830620, + 0xd7230d27, 0x3a1200ff, 0x22cb82e2, 0x8200c014, 0x14002366, 0x2182ae87, 0x43883c27, 0xb8d2ffff, 0x270a8294, 0xff9a9973, 0x5c4fcd00, 0x22132c67, + 0x83989919, 0x82192033, 0xeaff2122, 0x17224f83, 0x5e533e4a, 0x5f16820f, 0x32740696, 0x8315200b, 0xb5e82216, 0x065e53c4, 0x01ff0e2f, 0xff66e6fe, + 0x34b32701, 0xfaffff15, 0x2cc08220, 0x0500800e, 0xc0fcffff, 0xffff9300, 0x27b083f6, 0xff46e103, 0xb8def7ff, 0xbe211482, 0x25f682ba, 0xff00c0e3, + 0x2582f4ff, 0xff07a831, 0x3413ffff, 0xac0800ff, 0xf9ffffcc, 0x82929a99, 0x66662431, 0x187b088b, 0x210bf949, 0x3d828b84, 0x08486128, 0x1ed1ffff, + 0x0c8207b8, 0x8282ff20, 0x40000022, 0xff224482, 0x0f850080, 0xcf271c82, 0xffff1e05, 0x826666eb, 0xb5fa317b, 0x0c00ff82, 0xffffec91, 0xff9c4ff8, + 0x703d0b00, 0xbd275782, 0x0900ff72, 0x820872bd, 0x9a592905, 0xcf0e00ff, 0x0500ff5c, 0x11219e83, 0x2361826b, 0x5ccf1200, 0x2705d475, 0x073500ff, + 0xd5ffffae, 0x0026d582, 0xffe2fa2a, 0x1b65caff, 0x23068305, 0xccd6ffff, 0xd522a982, 0x76821e05, 0x48e1cb23, 0x22068208, 0x82a430ed, 0x42a02648, + 0x94eeffff, 0x265c827a, 0xffff9f5a, 0x82a430f1, 0xb8f6274c, 0xf5ffff52, 0x86820c57, 0x82676621, 0x32b326f1, 0xb3faffff, 0x05d97933, 0x00ff5a2a, + 0x0534b314, 0x0000ff8b, 0x0983ce87, 0xa4820f85, 0x66e62e24, 0x2a82ff07, 0x00ff3325, 0x829a9908, 0x8fc22742, 0xf7ffff92, 0x1d410040, 0x826e2016, + 0xc0e3222d, 0x22ed8200, 0x82050080, 0x82e02028, 0x4003220a, 0x20f88200, 0x07c67aa0, 0x00c0fc23, 0x21968283, 0x108220fa, 0x2584f120, 0xfabefc22, + 0xd8222a82, 0xad498f52, 0x08002305, 0x1b460621, 0x00ff2a05, 0xffd76386, 0x3433c8ff, 0x26a08505, 0x9999f3ff, 0x840200ff, 0x9a1925c7, 0x330400ff, + 0xf427c782, 0xff08ffff, 0x8238deff, 0xa8e225e6, 0xeafffff6, 0xd5296f83, 0xff8bcc4c, 0x72bdcfff, 0x2a068208, 0xfff668cb, 0xc3b51900, 0x83d1ffff, + 0x2b27279b, 0xe2ffff86, 0xdf820ad7, 0x3233be2b, 0x2700ff06, 0x00ff842b, 0x8215821d, 0xffc42b24, 0xfe3f2e00, 0x3400ff8b, 0x3b827c94, 0x83300021, + 0x3dea274d, 0x2a00ff70, 0x668234b3, 0x82e23a21, 0x9859212a, 0x04223b82, 0xe782ec31, 0x82ae0721, 0x6c672190, 0xdc210982, 0x23a48229, 0x00fff47d, + 0x2705b05e, 0xff666686, 0xcdcc3700, 0x0827ba82, 0x00ff8235, 0x82482103, 0xfeff2404, 0x820900ff, 0xfcff2cba, 0x00ffcecc, 0x089a1908, 0x82e1feff, + 0x3900230f, 0x9d183233, 0xf921087a, 0x223a82a6, 0x82004007, 0xd9072285, 0x8285839a, 0x00ff2106, 0x04871182, 0x8b9ad922, 0x15828182, 0xa1832283, + 0x82c0f821, 0xf8ff232d, 0x2d826626, 0xff250683, 0x33b3f9ff, 0x05405aff, 0x3333f727, 0xfbab088b, 0x225f9fa4, 0x82676606, 0xcc0c219c, 0x0a359e18, + 0x5f823420, 0xc8820620, 0x8b204883, 0x5f8c4e82, 0xffff322a, 0xff34f3f6, 0x3433f7ff, 0x0ceb9e18, 0x5e40be96, 0x00ff269c, 0x159a1957, 0x27e3828b, + 0xff66e6f0, 0x00401700, 0x0820f982, 0x8205d344, 0x00ff2106, 0x0722bd84, 0x1c410040, 0x5bf72019, 0x44830abd, 0xc0e8ff30, 0x088b8b00, 0x191f00ff, + 0x3800ff9a, 0x7f4166e6, 0x2ddf411f, 0x0080fa22, 0x2a06df41, 0x8b6666f6, 0xf7ef0e08, 0x8215bb24, 0xb3f227bf, 0xf5ffff34, 0x3f60cd4c, 0xf2ff2305, + 0x838233b3, 0x16850684, 0x820ab54f, 0x4c0d23e2, 0x1182ffcc, 0x04833320, 0x00ff3423, 0x05f3650d, 0x5b180683, 0xcc200861, 0x08235485, 0x828b54f7, + 0x8422825f, 0x202c8231, 0x8369820a, 0x845f820e, 0x18438506, 0x860d5741, 0x06cd608d, 0x5b188682, 0x8d8a0e19, 0x5e836b20, 0xb9862183, 0x9a82f520, + 0xbe89309c, 0xfb218ca3, 0xa3be8b14, 0x2d4c41f0, 0x0f01ff2d, 0x00ff6666, 0x15666696, 0x4a0000ff, 0x978205e8, 0xce4c002c, 0x99fdffff, 0xffffff99, + 0x098466e6, 0xffff082e, 0x0734b3e0, 0x00ff06cb, 0x07cdcc34, 0x0e3ec582, 0x00ff0080, 0xff68e604, 0x99190e00, 0x190900ff, 0x0b00ff98, 0xc4086766, + 0x334700ff, 0x0c820533, 0x0d371183, 0x00ffcccc, 0xff9c1914, 0x9a190300, 0xe60c00ff, 0xf4ffff64, 0x82089a19, 0x34b32135, 0x5e820a82, 0x33020022, + 0xeb200982, 0x19820982, 0xffff9823, 0x211e83f3, 0x5982c7ff, 0xe6b7ff2e, 0xffff0567, 0x07ff7f58, 0x993600ff, 0xc9221b82, 0x5982ce4c, 0x7a820c20, + 0xc764ff20, 0x515f8206, 0x0f82055c, 0x0582a482, 0x80274182, 0xebffff02, 0x838bd0cc, 0x22a5820a, 0x82fe7f0c, 0x4cc9211a, 0x36248a82, 0x7f059a99, + 0xd6828783, 0x1083f920, 0x66660f24, 0x8e829c8b, 0xdd823220, 0xd5ffff24, 0xe1823433, 0x8b830620, 0x6482f120, 0x83030021, 0xb3ef2209, 0x20498234, + 0x05485aee, 0xc682c220, 0x83cdff21, 0x82048416, 0x088b290e, 0xff0694fb, 0xd723c2ff, 0xcd242582, 0x00ff29dc, 0x0c958d18, 0xe7822c20, 0x281a0026, + 0x2600fff6, 0x25235183, 0x829d0ad7, 0xcc6a216e, 0x210a9453, 0xb3527b54, 0xab112d06, 0xab088b85, 0x0704f706, 0x1a00ff8b, 0x2307bb5b, 0x707d1500, + 0x2208667c, 0x8266e67a, 0x991922a1, 0x2021829a, 0x218b8317, 0x1c82bdf0, 0x09830a20, 0x5278e822, 0x57215982, 0x2eda8266, 0x050b1734, 0xfdffff8c, + 0x00ffcdcc, 0x4ccccc00, 0x002006bf, 0xff258082, 0x089999fd, 0x20af828b, 0x340c826b, 0x9a99b900, 0x95ffff15, 0x2b069a19, 0x054bcb07, 0x806f00ff, + 0x241b8200, 0xf76666bb, 0x250d8234, 0xfb9a1945, 0xde8415b4, 0x707de522, 0xea22de82, 0x385c8f82, 0x090d7208, 0x7120a082, 0xb4841684, 0xf7088b23, + 0x09c05f94, 0x61246570, 0x245406cb, 0x054f6a05, 0x540e0028, 0x1100ff7c, 0x4e8285ab, 0xa654d420, 0x84ab210e, 0xee238a82, 0x85087c54, 0xffff2406, + 0x8234b3f1, 0x84ab2904, 0x4ceeffff, 0xfb088bcc, 0xff233082, 0x827b54ee, 0xabf1221e, 0x544f8385, 0xfb22087f, 0x0b551514, 0x0d764108, 0x658ff720, + 0x2105f541, 0x6584cc4c, 0x44184c20, 0xfb251129, 0x74fb0614, 0x06366e07, 0xea728282, 0x21828305, 0x646e8bcd, 0x8f43180c, 0x74f7220a, 0x55368207, + 0xa2180d1c, 0x0e270899, 0xf844f82f, 0x18ff1524, 0x450c2f68, 0x9b2008d3, 0x00286a82, 0xff00c008, 0xccccf8ff, 0x46055247, 0xfc2105c4, 0x0bf24934, + 0xc0211e82, 0x23948200, 0x080040f7, 0x18ba5818, 0x31829b20, 0xcd4c612c, 0xebffff07, 0xffffebd1, 0x558280f1, 0x142ef427, 0x19f0ffff, 0x203b8299, + 0x05cd54ed, 0x05c32708, 0x2100ff1e, 0xffffae47, 0xffaec7c9, 0xecd13200, 0xccdcffff, 0xffff08ce, 0xfff568ec, 0xd6a3bfff, 0xfaffff05, 0x458267a6, + 0xffc47526, 0xb85e0f00, 0x2b05d06f, 0x00801500, 0x00ff088b, 0x0666e6ff, 0x2507945e, 0xff48610f, 0xbd831400, 0x70bdf922, 0x80210982, 0x2b468300, + 0x00ff3473, 0x059a5940, 0xb33300ff, 0x23220a82, 0x70823233, 0xdd824c20, 0x9a193726, 0x3c00ff8b, 0x00258784, 0xff3e0a12, 0x239e83ff, 0x5ccf1000, + 0x87826282, 0x680e0023, 0x296182f5, 0x0771bd9e, 0xe4fb069b, 0x2d821573, 0x7f820420, 0xa1030022, 0x04846782, 0xb95e0425, 0x82bb088b, 0x66042280, + 0x271d8266, 0xff9a9903, 0xb85efcff, 0xfb22de82, 0x1a4148a1, 0x9efb2105, 0xfc22b182, 0x18826666, 0xff2c9e82, 0x8b9a99fb, 0xff065b08, 0x47a1fbff, + 0x2c822682, 0x0300ff23, 0x2e31829e, 0x48610400, 0xf7079b08, 0x156cfb14, 0x82a7ffff, 0xffff2226, 0x413682b8, 0x61820ad8, 0x85ab1125, 0x834700ff, + 0x540e257f, 0x5800ff7b, 0xa2826b82, 0x16850683, 0xabf1ff23, 0x22568285, 0x427b54ee, 0xcc200551, 0xbc424485, 0x25548305, 0x01ff0e08, 0xfd82cc4b, + 0x66e6df28, 0x1c00ff15, 0x55823e4a, 0x0a971a31, 0x02f5ffff, 0x1300ff8f, 0xffffe0fa, 0x821f05ec, 0x83132054, 0x68ec3114, 0x00ff05f6, 0xff900228, + 0x70bd1100, 0x3d1f00ff, 0x232c0482, 0x00ff5d8f, 0xffb85e0a, 0x99592b00, 0x052b2982, 0x00ff9ab9, 0xff84eb17, 0x829dffff, 0x2817321e, 0xfafffff8, + 0x00fff4df, 0x08ea5115, 0x63fdffff, 0x262e8212, 0xffff48e1, 0x82da2ef2, 0x22bd82ed, 0x8217f8ff, 0x18f82271, 0x241e8210, 0xff9a19bb, 0x310482ff, + 0xb4ffff05, 0xff066666, 0xbcb44a00, 0x4400ff07, 0x048366e6, 0x7e826820, 0x78e90724, 0x048300ff, 0x5cfcff28, 0x0d00ffee, 0xad8268d1, 0xfffa1e26, + 0x2a9c0200, 0xea314082, 0x00ff14ae, 0xff002005, 0x0ad7e8ff, 0x620000ff, 0x21098290, 0x83827c14, 0x82724621, 0xb3c8221e, 0x35798234, 0xffff20c5, + 0xfff5e8d4, 0x8e02d1ff, 0x30f7ffff, 0xc7ffffa4, 0x1e82ecd1, 0x298ffe22, 0xac210f82, 0x21bc82c0, 0x098233b3, 0x002e7683, 0x08839a19, 0xc75200ff, + 0xadffffaf, 0x8282d723, 0x821e0821, 0xc20228ed, 0x0800ff8f, 0x848ccc4c, 0x828b2005, 0x33342121, 0xc9235b82, 0x86150080, 0x28172b7b, 0xddfffff6, + 0x00ff0a97, 0x09826804, 0x142ee422, 0x54217a82, 0x2566827a, 0xff727d94, 0x514c6a00, 0x023e2205, 0x20ec8290, 0x22698380, 0x8270fd5f, 0x82bf200a, + 0xc0ff277c, 0xeb0566e6, 0x1682ffff, 0x3e226f82, 0x13823e0a, 0x8208fe21, 0xb36a270a, 0x95ffff32, 0x27826666, 0x7b54f224, 0x5483ffff, 0x6b040023, + 0x22688643, 0x83382917, 0x080c267c, 0xffff09f7, 0x2e43828a, 0x9e0e00ff, 0xf1ffffb8, 0x00fffe7f, 0x470a9717, 0x0e280745, 0xff086a80, 0x00c03400, + 0x57820484, 0x4e800e21, 0x2082050c, 0x7a941722, 0x98203083, 0xa1213a82, 0x27ac8248, 0xff40e48a, 0x723c7300, 0x63207282, 0xff23a582, 0x829a99e3, + 0xccc424e1, 0x7b00ffcd, 0x6b240542, 0xffff9a19, 0xfd500482, 0xe5ff2d06, 0xff8b48a1, 0x3c4ad5ff, 0x5e1a00ff, 0x0f827c82, 0x0d316c82, 0xfffff628, + 0xff9ad9f2, 0x00401100, 0x66f9ffff, 0x22098266, 0x828b3e4a, 0x8211201a, 0x28168506, 0x8e970600, 0x2e0d00ff, 0x21048215, 0x1a822030, 0x5b827720, + 0x04820020, 0xf72a5b82, 0x00ff142e, 0xffecd114, 0x1483fdff, 0x8b821620, 0x4c050030, 0x1600ffcc, 0xff086666, 0x9a195cff, 0x988239fb, 0x6a097577, + 0x0d230d02, 0x83ff9042, 0x21048211, 0x5e8270bd, 0x83004021, 0x820d207a, 0x49168506, 0xa8831390, 0x20055f49, 0x592d82c0, 0x8b20058b, 0xab20a982, + 0x28b76f18, 0x46162f46, 0x46460536, 0x0e002105, 0x2208ac5a, 0x8915736b, 0x46332030, 0xdd450860, 0x46308810, 0x491808bf, 0xfb23246a, 0x827cfb54, + 0x23002160, 0x26082d83, 0xff67a61c, 0x33b31c00, 0x592300ff, 0xf7088b9a, 0x00ff061c, 0x07008042, 0xdc34ffff, 0xff056129, 0x1f05f3ff, 0x82fdffff, + 0xf3ff282a, 0x00ff914d, 0x82666608, 0x8a50270e, 0xe60c00ff, 0x0a830867, 0x82987d21, 0x52582115, 0xb3211082, 0x2e048232, 0x00ffa6fb, 0x0834b302, + 0xf5cf01ff, 0x8205ebc4, 0xb002221c, 0x231c85a4, 0x66a6f7ff, 0x55831c84, 0x88081e21, 0xff20250a, 0x9899f7ff, 0x51211482, 0x210482ec, 0x55829a19, + 0x82cc4c21, 0x192b235b, 0x81825f9a, 0x8e82b320, 0x23229784, 0xe982cc4c, 0x34b31c31, 0x4ce3ffff, 0xffff8bcd, 0x0833b3dc, 0x840734fb, 0x20148409, + 0x821983cc, 0x05cb6904, 0x6918d420, 0x99200a15, 0x3420e583, 0x44823e82, 0x34f70825, 0x188bcb07, 0x180e8b68, 0x2008245a, 0x526f184b, 0x06cb2117, + 0xcc20e882, 0x00247782, 0xff333307, 0x0adb5a18, 0x7018cb20, 0x4b25179f, 0x3b04f706, 0x229e8215, 0x833433f7, 0x47332030, 0x08200643, 0x08204582, + 0xd1834e85, 0x1d850720, 0x08239d83, 0x8b08cccc, 0xa568184e, 0x824b200c, 0x33f722cf, 0x224f8233, 0x18cdccf8, 0x240b23f3, 0x24f7074b, 0x20cf83db, + 0x23438233, 0xccccf8ff, 0x80891c8d, 0x80883420, 0x845dcc20, 0x206f8205, 0x97ca848b, 0x27808ecf, 0xf830fb0e, 0x8000ff14, 0x20059559, 0x24b88295, + 0x66e6a9ff, 0x200485ff, 0x05755196, 0x11850683, 0x21560023, 0x235e8248, 0x08b8de69, 0x3a310682, 0x00ff84ab, 0xffecd11b, 0x49213000, 0xc01a00ff, + 0x2c0e8200, 0xff08cd4c, 0x52f80e00, 0x991000ff, 0x2614829a, 0xffffc375, 0x820080f5, 0x4cea29b2, 0xffff08cc, 0x070080aa, 0xdc220c82, 0x2c827cd4, + 0xff212682, 0x274583e2, 0xffa43023, 0x5c8fffff, 0x23223b82, 0x0a8270bd, 0xffa47025, 0x82191d00, 0xe61c2240, 0x286a8266, 0x089a9923, 0xffffe38b, + 0x2d9b8250, 0xb81e0800, 0xf37a00ff, 0xb500ff34, 0x31827c14, 0x82800d21, 0xb8132178, 0x1e217282, 0x22ba82a6, 0x82cc0cf7, 0x33e82260, 0x206d8234, + 0x264282ff, 0x7ad498ff, 0x82a800ff, 0xe9ff2239, 0x201a834c, 0x214c8256, 0x5f82af0e, 0xff0a5739, 0x00800f00, 0xedffff15, 0x00ffa4f0, 0x05662614, + 0x98f6ffff, 0x5500ff10, 0x27210596, 0x83ca82f0, 0x8302203c, 0x590e321e, 0x00ff089a, 0xff21d002, 0xc2b50d00, 0x6a0800ff, 0x060151c1, 0x29dc0b27, + 0x7d0500ff, 0x311e8272, 0xff48e144, 0xa4f01f00, 0x2f00ff05, 0x00ff33f3, 0x9b824016, 0x82b02721, 0x8325205d, 0x281b250e, 0x3100fff6, 0x6d827f82, + 0x0a82a820, 0x8fc22522, 0x1c2b2982, 0x00ff1fc5, 0xff0a9734, 0x82352a00, 0x83282058, 0x83332097, 0xab1727e4, 0x00ff0886, 0x4382c05c, 0x70fd2a22, + 0x0e312982, 0x00ff0ad7, 0xffe0cf06, 0xec911100, 0x44fcffff, 0x31828218, 0xffffae47, 0x086c67f3, 0x142200ff, 0xd9ffff7c, 0xc68272fd, 0x34339727, + 0x70cfffff, 0x200a82a2, 0x272083c8, 0xff862be6, 0x1e05d2ff, 0x22052963, 0x82b3e0ff, 0xbac62d1e, 0xffff08e1, 0xff7814ea, 0xcff7d7ff, 0xe3262982, + 0xffff52f8, 0x4f82c7cc, 0x8207d721, 0xccd82c04, 0xceffffce, 0xffff0080, 0x821e05e9, 0x8a8e3329, 0xcbffff3e, 0xff056666, 0x285c1702, 0xd14c01ff, + 0x3f8215ec, 0xff989926, 0xb8de1700, 0x8e223f82, 0x20826666, 0x82ec5121, 0x87ce210a, 0xe9224082, 0x5a825c0f, 0xd4204a84, 0xe3229982, 0x5e82a4f0, + 0x825bcf21, 0x19ea224a, 0x2119829a, 0x2982d7e3, 0x82abe021, 0xbac62799, 0xd1ffffe2, 0x9e8270fd, 0xd8821120, 0x823dc821, 0x33e62209, 0x20298232, + 0x217f8397, 0x538291cf, 0x6e250022, 0xd6356e82, 0xff059042, 0x91820700, 0x91f7ffff, 0x0900ffea, 0xffffc375, 0x2b2482fb, 0x67660b00, 0x00ff088b, + 0x8b213005, 0x38300582, 0x0100ffd5, 0x00ff281c, 0xff85eb04, 0xd8430200, 0x220d4941, 0x82472133, 0xa4b021b5, 0x270b7341, 0xff90c21c, 0xec913400, + 0x14202982, 0x83059d41, 0x1c1b296a, 0x3100ff2a, 0x00ff5c8f, 0x2705c741, 0xffbba4f0, 0xcd4c1600, 0x2009ed41, 0x229082a5, 0x8228dc0b, 0x6a7c2b74, + 0x6b0800ff, 0x0b00ff88, 0x7482b408, 0x3482cf20, 0xc2b50d22, 0x013d2982, 0x00ff6cfd, 0x887a340f, 0xf6ffff99, 0x00ff9c99, 0x08866b0a, 0x54f82f0e, + 0xf71504f7, 0x07a54db4, 0x21050756, 0xfc827d15, 0x0080e527, 0xc4fb088b, 0x09116106, 0xffff1f22, 0x2305f454, 0x08e2faca, 0x8205256f, 0x21bf8209, + 0x1984e1fa, 0x3500ff24, 0xe44c1f05, 0x0fc67a07, 0x20c51024, 0x96828b08, 0x3868d419, 0x3ef7d423, 0x21408215, 0xdc82d608, 0xfc290727, 0x290700ff, + 0x22eb8278, 0x828b04d6, 0x193524dd, 0x83c1069a, 0x211e93c4, 0x278506bf, 0xfc333283, 0xd6f8ffff, 0xffff8b88, 0x087829f7, 0x00ff0755, 0x9766e636, + 0x8257201e, 0x84278250, 0x18042032, 0x220b468c, 0x97550655, 0x0657211a, 0xfc205a83, 0xf8226082, 0x708404d6, 0x0424b384, 0x5507c108, 0xbf281a97, + 0xfb94f707, 0xb4fb15ae, 0xeb4d2082, 0x0efe7b0c, 0x088bf718, 0x29074d4e, 0x074b06b4, 0xff94f80e, 0x3d450f01, 0x19e52f05, 0xeaffff9a, 0xff766666, + 0x34b3dcff, 0xb382088b, 0xda4ddd82, 0x7a542606, 0xabf1ffff, 0x22048686, 0x4e7a54ee, 0x7187135d, 0x0774f722, 0xe3223c82, 0x498206d7, 0x8285ab21, + 0x70ea23cd, 0xc982a0a4, 0x64611a20, 0x19402505, 0xf7dbeb9a, 0x03826182, 0x823beb21, 0x82bf201e, 0x8b0e2a17, 0xff1534f7, 0x66e660ff, 0x27118207, + 0xff0080ed, 0x48610e00, 0x99216f82, 0x26b0829a, 0x088bb89e, 0x850654f8, 0x83198509, 0x2653821e, 0x0852b810, 0x82a000ff, 0x94fc2c36, 0x2b01ff06, + 0x00ff66e6, 0x8270fdff, 0x40f8214a, 0x00204382, 0xff210482, 0x214d82f8, 0x0483fdff, 0x8221fa21, 0x26fc3652, 0xfeff0868, 0xff5238e9, 0x8e0227ff, + 0xff94f805, 0x05030000, 0x264c8205, 0xfffbfc76, 0x8219a1ff, 0xd7613271, 0x8affff0a, 0x00ffcccc, 0x08004006, 0x01ffaf0e, 0x200c83ff, 0x052052a0, + 0xff34b323, 0x9b0319ff, 0xbffe231f, 0xf0479a99, 0x0a572109, 0x820bf047, 0x0e0319b0, 0x197920b6, 0x2c09a404, 0xffff058b, 0xff343390, 0x9a992700, + 0xaf221915, 0x55221909, 0x0653220c, 0x0a8c48c3, 0x200cbc47, 0x173d485b, 0x53075322, 0xcd271a8f, 0xf7ffff8b, 0x61083333, 0xbc480518, 0x06c32212, + 0x09264953, 0x0dbaa618, 0x5006bb21, 0x33210d48, 0x24ab8434, 0x07c308cc, 0x2c1a97c3, 0xfb0e07bb, 0xf8e4f730, 0xffff1514, 0x05db68ca, 0xffaec724, + 0x79822500, 0xccdcff2f, 0x1a00ffcd, 0xffffcccc, 0x8bcd4cd6, 0x20068508, 0x821682ff, 0x83e52011, 0x82f22020, 0xdaff2320, 0x1a82cccc, 0x9919ca22, + 0x0ce15f18, 0x85eaff23, 0x25ca821e, 0x08e27ae5, 0x5f18f4fb, 0x097b07d8, 0xb4f7210f, 0x210e3552, 0xb182e27a, 0x1e851a24, 0x3383f708, 0x09820020, + 0x22066452, 0x5be27a15, 0xfb230671, 0x43158b24, 0xff2105d7, 0x06857c00, 0x27101b52, 0xffff85ab, 0xff84abf1, 0x1c8e5518, 0x2216ba4b, 0x8214fb8b, + 0x5923225f, 0x221f829a, 0x1966a61c, 0x21146500, 0x16849a59, 0xdcffff26, 0x088b66a6, 0x11850685, 0xb31c0022, 0x4a07ea4a, 0xe24b05f1, 0x2c168206, + 0x4c2300ff, 0xeb088bcd, 0xfb1594fb, 0x17e24454, 0x2c223482, 0x2a823433, 0x83cdcc21, 0xffcc2504, 0x33332c00, 0x2205304a, 0x82142e2c, 0xd123221d, + 0x836f82ec, 0xd3ff220a, 0x05bd5ed1, 0x12a95a18, 0x94f70e27, 0xe6a001ff, 0x08b86666, 0xcc4c8e2d, 0xe8a2ffff, 0xffff8bf6, 0x660a178d, 0x613009b8, + 0xd3ffff48, 0x00ff707d, 0xff0b9723, 0x6866dbff, 0x66075055, 0xfc2619b8, 0xffffa4f0, 0x4f82ccfc, 0xb866ff20, 0x4f01230f, 0x784988df, 0xfeff2605, + 0x00fff833, 0x21b86603, 0xff52b835, 0xa4b0f3ff, 0x4a2400ff, 0xf8ffff3d, 0x00ff66e6, 0x66d86326, 0x862f05b8, 0xe50000ff, 0x7200ffa2, 0x00ff9a99, + 0x8234335c, 0xcc7322fe, 0x20bc82cc, 0x82068200, 0x826620c8, 0x6616822c, 0xf72706bc, 0x15ffff04, 0x82159a19, 0x29f721e2, 0x82628b46, 0xd608248d, + 0x4700ff87, 0x79200663, 0x20556347, 0x32ce8487, 0x07570879, 0xf601ff0e, 0x01ff9a99, 0x1566e617, 0x8360ffff, 0x809f37fc, 0xffff0500, 0xffc275f3, + 0x3e8a0c00, 0xb0ebffff, 0x0000ffa4, 0x13825c0f, 0x82d86321, 0x8e862204, 0x21058208, 0x2385ec51, 0x32200582, 0x70202382, 0x0c222382, 0x0d82ba9a, + 0x08d66325, 0x829f00ff, 0x60ff2453, 0x82050180, 0x270a8343, 0xfff668f3, 0x146e1400, 0x05214882, 0x2113821f, 0x04825c8f, 0x82ffa121, 0x7e0c2729, + 0x0b00ffde, 0xf882bbb8, 0x7d821420, 0x80f3ff28, 0x0d00ff02, 0x63826666, 0xcccc5727, 0xb3b2ffff, 0x27988234, 0xffb81ebc, 0xb8de4300, 0x37264f82, + 0x00ff4821, 0x0a821e37, 0xc0d2ff22, 0x08c92019, 0xcd4c9227, 0x5c92ffff, 0x21b9832a, 0x86826766, 0x95823320, 0x9919f727, 0xfbffff7b, 0x220f82e6, + 0x826766ee, 0x33e42751, 0x87ffff33, 0x2582cdcc, 0x6c839320, 0x0a820482, 0x4682f920, 0x0482ff20, 0xffff8b24, 0x5c82e1f5, 0x00400623, 0x820f83ff, + 0xa116279d, 0xe9ffff48, 0x77824861, 0xff241587, 0x48210a00, 0x7918ad82, 0x25820721, 0x99996c27, 0x996c00ff, 0x2725829a, 0xffcc4c78, 0x00c01b00, + 0x11210a82, 0x071f6180, 0xb2831020, 0x82e00821, 0x820c200e, 0x0c00236a, 0x3482b89e, 0x9a996d27, 0xb36d00ff, 0x85808233, 0xff3f21c7, 0xc8270a82, + 0xffff5ccf, 0x8286ebc8, 0x82c9200a, 0xc9ff233f, 0xfe82cc4c, 0xceccfb22, 0x6626c783, 0x99faffff, 0x05828898, 0xff9a1926, 0x9a99feff, 0xb020d282, + 0xff215182, 0x207084ed, 0x22b78212, 0x83404f00, 0x6001217b, 0x05266c82, 0xff8e00e0, 0x0a830500, 0x82200421, 0x4004220f, 0x20778200, 0x200f8309, + 0x20258409, 0x22ed8243, 0x8221bcff, 0xf6ff34dd, 0xffffb8be, 0x05b89ef6, 0xd801ff0e, 0x00ff3433, 0x829a19fc, 0xe6bd2678, 0x1600ff66, 0x21d98219, + 0x6882ecff, 0x9f060026, 0xf1ffffbe, 0x0e220983, 0x9282fa3e, 0xffb85e2d, 0xb85e1100, 0x00ff7b08, 0x82727d3c, 0x61f43bb4, 0x2b00ff48, 0xffff70bd, + 0xff70fdbe, 0xba5e0d00, 0xa1deffff, 0xddffff48, 0xad828e82, 0x8221d021, 0x26d1220a, 0x20298266, 0x214582f2, 0xb282f2ff, 0x83ebff21, 0xe1f82509, + 0xebffff46, 0x00230e82, 0x82ba9e01, 0x02b92d29, 0x0500ff8f, 0x570566a6, 0xff0300ff, 0xdd217582, 0x25a1821e, 0xffd002cf, 0xb6831b00, 0x4821da22, + 0x2620cc82, 0xcb245a83, 0x96058f82, 0xe6249682, 0x0100ff67, 0xec224b83, 0x7e5f285c, 0xefff2305, 0x4b82b89e, 0x0080e327, 0x02c7ffff, 0x20758290, + 0x239f82eb, 0x90c2d6ff, 0x1483a482, 0x4661d428, 0x9e3200ff, 0x4b8296b9, 0x9919452b, 0x400f00ff, 0x00ff0500, 0x286b8214, 0xbe7f0400, 0x421500ff, + 0x21e68290, 0x19823c80, 0x7f829e20, 0x4e61f422, 0x36202982, 0xd7224483, 0x29824821, 0x0a832720, 0x0482e220, 0x823d0021, 0x1500221f, 0x202982ff, + 0x23598203, 0xecdc2c00, 0x04272982, 0x00ff00a0, 0x8228dc3d, 0x60012129, 0x11200a82, 0x00269e82, 0xff48810b, 0x62831000, 0x70bd1126, 0x1e0900ff, + 0x0028a382, 0xff9a193d, 0xb89e1f00, 0x2e2b2982, 0x00fff4a8, 0xff38f316, 0x82ccfaff, 0x4c3925ee, 0xcfffffcc, 0x00310482, 0x089a9910, 0xe6c6feff, + 0xc3ffff66, 0xff1566e6, 0x05017cff, 0x1e85f228, 0x5e0e00ff, 0x55828bb8, 0x08e2ba22, 0x11840685, 0x10230486, 0x828be2ba, 0x7357198c, 0x48a1270b, + 0xefffff8b, 0x2d821e45, 0xff230683, 0x8266f3ff, 0xa1f12d55, 0xedffff48, 0x088b0080, 0xffff14f7, 0x9705ea45, 0x83112063, 0x247582ef, 0x7a0d00ff, + 0x987984e2, 0x00ff2363, 0x5d82e600, 0x6283ee20, 0x0080f224, 0x0484ffff, 0x9b256784, 0x197f00ff, 0x22ca829a, 0x820020f7, 0xc6f92591, 0x0700ff66, + 0x00230a83, 0x829af907, 0x0800239c, 0x11847ddf, 0x0600ff24, 0x09821d3a, 0xfc5ff920, 0x85068205, 0xf8ff2216, 0x223883e0, 0x826606f8, 0x256682e1, + 0xf9ffff83, 0xf445cccc, 0xff220805, 0x8b3433f6, 0x30fb0e08, 0x44f854f7, 0x358b2115, 0x218b4afb, 0xff218b08, 0x9a195500, 0x6a00ff35, 0xb38367e6, + 0x9a196926, 0x5600ff8b, 0x1783a282, 0x6a310a82, 0x8b0866e6, 0xa9fffff5, 0x4af79a19, 0xe696ffff, 0x25268266, 0x9a19e0ff, 0xa9820efb, 0xc183e020, + 0x2d82d820, 0x83dfff21, 0x4cb722d0, 0x22b882cd, 0x82cdccc9, 0xf7ff23ad, 0x7a823433, 0x820ad721, 0x22848304, 0x83f628f7, 0x08051939, 0x0a655209, + 0x3f366782, 0x00ff5c8f, 0xff33b324, 0x70bd4f00, 0x852200ff, 0x2a00ff1f, 0xc88234b3, 0xdf8f0522, 0xe72bf082, 0x0a00fff0, 0x00fff813, 0x82201001, + 0x29dc260e, 0x6ffaffff, 0x221e82e0, 0x8248e106, 0x767e210a, 0x19241982, 0xf5ffff99, 0xfa228c83, 0xfa826766, 0x08343331, 0xb4f8af0e, 0xfb1534f8, + 0xab6b0604, 0x42063b05, 0xf1220725, 0x277eb89e, 0x48612108, 0x22066753, 0x4c4861ee, 0x5173050d, 0x9e112605, 0xf7088bb8, 0x13274c74, 0x08231a82, + 0x820714f7, 0x820982b5, 0x98992148, 0xee273886, 0x088b6866, 0xdab4fb8b, 0x9a992170, 0x66217087, 0x83ce8266, 0x74fc2470, 0x8215c4f7, 0xe008268c, + 0xf8ffff00, 0x21c582e1, 0x09822007, 0x821ef721, 0x826b20c0, 0x054e42f3, 0x1d84f820, 0x8b00e024, 0x1082ffff, 0x24fc0822, 0xff20bf82, 0xcb2af396, + 0x0654fb07, 0xf70774f7, 0x0a840654, 0x0e07db33, 0xe6e101ff, 0xb100ff66, 0x941566e6, 0x0500ff82, 0x22878219, 0x82ceccf3, 0x4cf3234d, 0x068508cc, + 0xfaffff22, 0xff202382, 0x82251682, 0x82820882, 0x870983ff, 0xcc4c2513, 0x14fc088b, 0xf3228d82, 0x2d831f45, 0x863dca21, 0x00f72644, 0x82089400, + 0x26278294, 0x00ffa4f0, 0x8232330c, 0xb30c22c9, 0x20528234, 0x82068200, 0x5c0f2124, 0x94251684, 0x00ff0894, 0x822c8209, 0xc335210d, 0x00263c85, + 0x8be1ba0c, 0x5682f808, 0x38832b83, 0x84323321, 0x82943970, 0xf9ffff08, 0xffff6666, 0x15666689, 0x00ff888e, 0xff34b301, 0x68e6fbff, 0xfb227b82, + 0xab5acccc, 0x83ef2005, 0x4cf92cad, 0xeeffffcc, 0x7f7fcecc, 0x847f7f08, 0x83398209, 0x4e1d8213, 0xef220698, 0x3682ae07, 0x52b8ef29, 0xb30600ff, + 0x82977f34, 0xfdf3235b, 0x27829771, 0xff8f4224, 0xb2841100, 0x9a191025, 0x82079b08, 0x33042282, 0x206d8234, 0x2ccb82b0, 0x8e981904, 0x8e8e088e, + 0x110400ff, 0x238185ec, 0x713d0400, 0x3421b082, 0x21138206, 0x2d833433, 0xff981934, 0xcc4cfeff, 0xff08888e, 0x0c1757fe, 0xe6a700ff, 0xa9821567, + 0xff3d8a2b, 0x33330200, 0x19fcffff, 0x05e85f99, 0xf0fcff22, 0x03225482, 0x7e8266e6, 0x67250a86, 0xe1fdffff, 0x214b8248, 0x45820080, 0x82c2f521, + 0xcdcc2109, 0xfe201e82, 0xdd820a84, 0x17000024, 0x7a82900a, 0x39823020, 0xf6820420, 0x1500ff3a, 0x00ff71fd, 0xff16ae56, 0x1f855b00, 0x054100ff, + 0x6d00ff1e, 0x088b0080, 0x16820685, 0xbe284b83, 0xffa1e2fa, 0xea51a9ff, 0x01201682, 0xff21d082, 0x240482fb, 0x98190000, 0x21678286, 0x9f8268e6, + 0x8a20ee82, 0xa1830682, 0x6882fd20, 0x83fbff21, 0x83fc2036, 0x82b08209, 0x19fc2282, 0x21bb839a, 0x0582889a, 0xfd201f88, 0xfb219d84, 0x211a8299, + 0xbc82e6fd, 0xfd84fb20, 0x8666e622, 0xfe247e82, 0x06b85e81, 0x0f225182, 0x05828b5c, 0x82291c21, 0x344283b5, 0xffcd8cfb, 0x99190200, 0x4201ff08, + 0x00ff5c4f, 0x15991968, 0x22548288, 0x41cc4cfe, 0x957a0bcf, 0x065c4505, 0xa182fc20, 0xcc010028, 0xfdffffce, 0xc1836666, 0x2b82cc20, 0x52820a82, + 0x66237a85, 0x830300ff, 0xccfe2213, 0x201e82ce, 0x229f8302, 0x8232b3ff, 0x20e58214, 0x821482ff, 0x237b8209, 0x98990000, 0x03201e82, 0x9a200a85, + 0x28828682, 0x82010021, 0x020022e8, 0x212d8233, 0x3d844c02, 0x82ce4c21, 0x850f8319, 0x20238319, 0x23668200, 0x9a190300, 0x43823d82, 0x57864d85, + 0x6b846183, 0x08217582, 0x841486ff, 0x845c849f, 0x8266209f, 0xcc01229f, 0x851e82cc, 0x86c983b4, 0x20c882d3, 0x062272fc, 0xff220682, 0xea82fbff, + 0x882ee583, 0x078b0888, 0xff7fffff, 0x2000ffff, 0x22419002, 0x82cd2006, 0x14ee2220, 0x2205828b, 0x820890c2, 0xd7fc2306, 0x7f46ff0a, 0xdcfc2605, + 0x0100ff2a, 0x412082cc, 0x0a850722, 0x20182241, 0x41598267, 0x33200522, 0x2241b587, 0x7c142142, 0x21122241, 0x6b865238, 0x84eb0222, 0x2c072241, + 0xff14ee02, 0x66e6fdff, 0x800200ff, 0x20098200, 0x22098266, 0x4100c001, 0xc2230822, 0x41ffff90, 0xe2820522, 0x2241ff20, 0x82cd2008, 0x82fb20f4, + 0xfdff2935, 0x8888f668, 0xfb078b08, 0xdf224682, 0x1f4170fd, 0x0812440a, 0x82094242, 0x414b85eb, 0xcd221f1f, 0x4242ffff, 0x1e1f4107, 0x00ff9925, + 0x829a9900, 0x67e621bd, 0x23057072, 0x33330200, 0x42420e82, 0x42cd2006, 0xf6431242, 0x86082005, 0x19032238, 0x826c839a, 0x42032028, 0x3d830542, + 0x0866e622, 0x42421487, 0x4271831a, 0x57420542, 0xffff2505, 0x8bcdccfc, 0xfb203982, 0xff210682, 0x051f41ff, 0x8866663b, 0x8b8b0888, 0xf82f0e05, + 0x1534f754, 0xff8b072b, 0x5c4fb9ff, 0xb0c6ffff, 0x820486a4, 0x088b290e, 0xff061cfb, 0x66a6cdff, 0x21081e82, 0xff0a97d0, 0x34b31700, 0xa8e2ffff, + 0x2800fff6, 0xff08ae47, 0xeb91f1ff, 0x3a1300ff, 0xffff05e2, 0x6f82e6f8, 0x3c4a0822, 0xa1276f82, 0x0a00ff48, 0x828b9a19, 0x82662005, 0x300023b3, + 0x60821e05, 0x940e003e, 0x0600ff7a, 0x00ff06a1, 0xff3eca0d, 0x19640b00, 0x1c0900ff, 0x00ff082a, 0xa3e1fa1d, 0xd2204282, 0x18052259, 0x2413528b, + 0xd70800ff, 0x2ab9180a, 0x48311908, 0x83eb2008, 0x801a2457, 0x1800ff00, 0x63078143, 0x551808e6, 0x852a0b7c, 0xffff8b1f, 0x08e17ae5, 0x30835cf7, + 0x0a171625, 0x831100ff, 0xe81121af, 0x1620ca82, 0x0822aa82, 0x068300ff, 0xff221685, 0x6b8217ee, 0xe8e9ff23, 0x20e282f6, 0x82948242, 0x9a99247d, + 0x830c00ff, 0xb30e2232, 0x230e8632, 0x8b34b310, 0x17223782, 0x9882e27a, 0xc2751326, 0x21efffff, 0x0427f982, 0xffff842b, 0x82e1bae9, 0x4a07211a, + 0x0422e782, 0x3082a470, 0xff666626, 0x33b30200, 0x3320f182, 0x9e8b3584, 0x83008021, 0x00802c9e, 0xf8af0e08, 0xa700ffb4, 0x82159a19, 0x2b592551, + 0xc2ffff86, 0x00294c82, 0xffe03a4c, 0xe23ab2ff, 0x208e82ab, 0x298882cb, 0xcc4ca5ff, 0x7c00ff05, 0xcd83866b, 0xb8de0926, 0x19f8ffff, 0x07209f82, + 0xff21cd82, 0x23cd84f6, 0x9999a3ff, 0x08b8a618, 0xff211c83, 0x2bd384f8, 0x084821f6, 0x9983ffff, 0xffff079a, 0x00244a83, 0x0566a65a, 0xe1255c83, + 0x07e0ffff, 0x257083ae, 0xb3ffff85, 0x9182cccc, 0xcecca622, 0xff352b82, 0xffff71fd, 0x0566e6b8, 0xff0694f8, 0x90020000, 0x194700ff, 0x387e829a, + 0xff34b31e, 0x32338fff, 0xfdffff15, 0x00ff0080, 0xff68e605, 0x3433faff, 0x056d45ff, 0x9899f92b, 0xb4fc088b, 0xf9ffff06, 0x27df83a0, 0xff0a37fa, + 0x2030fcff, 0x78212d82, 0x22288252, 0x8308f027, 0x8210200a, 0x8220200a, 0x2f01223d, 0x292982df, 0x00ff5c2f, 0xfff06704, 0x735afbff, 0xb4a82105, + 0x32322382, 0x4000ff2e, 0xffff2ffd, 0xffccccbd, 0x7c14d700, 0x0685088b, 0x2506d046, 0xffa43042, 0x82830300, 0x5ccf0222, 0x05211a82, 0x2026824c, + 0x219d8204, 0x8d830100, 0x35820620, 0xcc29a186, 0xaf0e08cc, 0x54f8a4f7, 0x1e451815, 0x23368208, 0x9082eaff, 0xe52cee82, 0xff08707d, 0x3433c0fe, + 0xd9ffff07, 0xea253383, 0xffff9899, 0x234282e6, 0x3433d7ff, 0xd1232082, 0x82089a19, 0x19f32206, 0x256e829a, 0xff7f9a99, 0x69820600, 0x82f5ff21, + 0xffff2755, 0x069a1926, 0xa119ffff, 0xdb231497, 0x5d24f707, 0x51541771, 0xffff2705, 0xffcdccf8, 0x6b830700, 0x3333f728, 0x24fb088b, 0x35b4cb06, + 0x0764f722, 0x2008f866, 0x388f187d, 0x74f7280c, 0x4b0cfb06, 0x5dffff15, 0xd7210b78, 0x26d0820a, 0x08f628f7, 0x55730773, 0xcc200f3a, 0x33211a83, + 0x053c4934, 0x55059343, 0xa3220d1f, 0x3a557306, 0x979b2017, 0x07a322ef, 0x201a97a3, 0x177c5e9b, 0xa3067322, 0x5c4c1a84, 0xffcd2505, 0xf6280700, + 0x0827c685, 0xfcf7067b, 0x821564fb, 0xccd327a9, 0xdcffffcc, 0x04863433, 0x8b230e82, 0x83ffff08, 0x22118506, 0x82cc2300, 0x2c0021d0, 0x8b21d082, + 0x200682ff, 0x060f5433, 0x82cc2321, 0x82158250, 0x2015822d, 0x821b8234, 0x20328328, 0x28548433, 0x74fb08cd, 0xe632ffff, 0x28638266, 0x66663300, + 0xb32900ff, 0x82048634, 0x2235830e, 0x82cccc65, 0x850c83d2, 0xd6ff2217, 0x2169824c, 0x6073ccff, 0x82ec2005, 0xf0ff242e, 0x82ff6866, 0xff662504, + 0x30b3ecff, 0xff243382, 0x06cecc25, 0x6f820c83, 0x00231784, 0x829a990f, 0x4c133f7a, 0x078b08cc, 0xe801ff0e, 0x01ff9a99, 0x155c8fa8, 0xf0e0ffff, + 0x1f00ffa4, 0xffffa430, 0xe2824ccd, 0x52f8ff22, 0xf5211382, 0x270482c2, 0xff0806cf, 0xf6a8a0fe, 0xab270482, 0xffff05dc, 0x82852beb, 0x3e0a2953, + 0xa3f7ffff, 0xe2ffffd7, 0x002a2e82, 0xff295c07, 0x5c0fe4ff, 0x0a88ff08, 0x1500ff33, 0xffffc3b5, 0xff3e4aea, 0x33f31b00, 0xa3f8ffff, 0x201e82d6, + 0x8367821b, 0x00ff370a, 0xff33b31d, 0x2a5c0800, 0xf51300ff, 0x1400ffc3, 0xff087ad4, 0x4d825f01, 0x05200483, 0x26218c82, 0x29048268, 0x00ff7c14, + 0xff981900, 0xe1833200, 0xcecce022, 0x67831382, 0x33ceff28, 0xa1ffff32, 0xbb823e0a, 0xf668ec22, 0x04839182, 0x1483ee20, 0xec11fd32, 0xa6f1ffff, + 0xfdffff68, 0xff088e82, 0xae07f3ff, 0xc12a0a82, 0xf6ffff06, 0xffffd8a3, 0x098261fe, 0x66a6f322, 0xa5221882, 0x058208a2, 0x04830a84, 0x4861fe22, + 0xfd222386, 0x736100c0, 0xfdff2206, 0x20148281, 0x261e83f1, 0xff0601fd, 0x8328eeff, 0x3869216b, 0x08207084, 0x04860584, 0xfd221984, 0x7b839002, + 0xfd225c82, 0x1e820080, 0x82fff221, 0xc7fd2100, 0xf6228082, 0x7b829999, 0xff21de82, 0x82c983f3, 0x217b9c04, 0x1e82ae07, 0x1e85fd22, 0xae224d82, + 0x77828814, 0x829a1921, 0x67662167, 0x66200483, 0xf520778e, 0x7785de82, 0x77861e82, 0x82e1fa21, 0xacc72114, 0xb321cf82, 0x21778233, 0xcf826866, + 0xc982a120, 0x9899f322, 0xf9243d82, 0xffff12c3, 0xf5230484, 0x828be3e5, 0x8fc2260a, 0x3c0600ff, 0x831a86ee, 0xff8b250a, 0xac1c0a00, 0x04821584, + 0x66e03a21, 0x003206cd, 0xff0a9713, 0x0bd71100, 0xfd0200ff, 0x0e00ff70, 0x09829a59, 0x08727d27, 0xf80c00ff, 0x2b0a8252, 0x00ffb83e, 0xff295c09, + 0xbe9f0100, 0x59211382, 0x20048399, 0x831e83dc, 0x830c2029, 0x9e012104, 0x28202384, 0x40212d82, 0x211e8200, 0x1e82e2fa, 0x827e0221, 0x214d8514, + 0x61833cff, 0x00ff0a25, 0x82879613, 0x0a972204, 0x830a8908, 0x828e2019, 0x71fd2138, 0x5c827b83, 0x00800222, 0x51207b84, 0x3e211482, 0x207b83fa, + 0x207b832a, 0x8557827d, 0x89db2070, 0x82db207b, 0x217b8419, 0x7b87e85b, 0x9852f821, 0x8886207b, 0x86f2837b, 0x980a20f7, 0x217b83f7, 0x61825c4f, + 0x87aa9121, 0xe05a227b, 0x07404108, 0xffee3c27, 0x3a1f0a00, 0x260f828b, 0xffffe23a, 0x8212c3f9, 0x5405221a, 0x230a827c, 0xff8b90c2, 0x21066250, + 0x0f8232b3, 0x08cecc3c, 0xa369feff, 0x34ffffd8, 0xf71566e6, 0x05b6f7b6, 0x85f4ffff, 0x0b00ff1e, 0x0a829a99, 0xcc0ce726, 0xf31800ff, 0xd9222a82, + 0x6f823433, 0xffba9e26, 0x852be9ff, 0x2c270482, 0xffff0848, 0x8253b830, 0xccc12104, 0x15852982, 0x82991921, 0x3b9f2624, 0x33d9ffff, 0x26388233, + 0xffffb0f2, 0x829a19e7, 0x744e827e, 0xff2a05a4, 0xf628c001, 0xfb1518f7, 0x6b82fbb6, 0x7a0b0023, 0x221782e1, 0x82056666, 0x33f3212d, 0x0c302d82, + 0x2600ffce, 0xffffcecc, 0xff4861fe, 0x7ad41600, 0xd3210482, 0x214182b4, 0x19824ccf, 0x824ccf21, 0x2015826b, 0x851a857c, 0x222e8424, 0x84060ce7, + 0x22958242, 0x820c62f4, 0x89763fbf, 0xff2f0e05, 0x5c0f6000, 0xb39f00ff, 0x00ff1534, 0x060ad7ff, 0xb39cffff, 0x32ffff34, 0xb3820080, 0x2105065d, + 0x434a9899, 0x66fb2d06, 0xfaffff68, 0xffff9a19, 0x0832b3fc, 0xcc211482, 0x830a82cc, 0x2414848b, 0x85cc4cfe, 0x2416828b, 0x8b9a19f9, 0x050e4f86, + 0xe6faff27, 0x0300ff66, 0x832d8333, 0x03002123, 0xff21a482, 0x213782fc, 0x56830400, 0x21054548, 0x35826866, 0xf6a89c25, 0x83cd00ff, 0x22012876, + 0x00ff703d, 0x82cc4c7c, 0x83052092, 0x99fd265d, 0x0500ff9a, 0x216c834c, 0x0c4f0080, 0x80fb2206, 0x25f38200, 0xff666604, 0x1e83fbff, 0x04820320, + 0xb3faff26, 0x0200ff32, 0xfa221383, 0x1e823433, 0xb0840220, 0xff333324, 0x14840000, 0x4d999921, 0xf820061d, 0x2505c152, 0xffcdccf9, 0x8d82feff, + 0xb3f9ff26, 0xfdffff33, 0x33214384, 0x228d8233, 0x4834b3fc, 0xff2105d9, 0x833984fd, 0x8272821e, 0x8477836c, 0x20048272, 0x82238299, 0xfcff2372, + 0x2d876766, 0x82999921, 0x867d823d, 0x83f9204d, 0x83fe201e, 0xb3f9304c, 0xff088b34, 0xaec7dffe, 0xf3ffff06, 0x828bae47, 0x22798205, 0x82190500, + 0x05f72645, 0xff08941f, 0x820683ff, 0x52f82448, 0x820d00ff, 0x00002616, 0x00ffae07, 0x82ab820b, 0x200a83b6, 0x2baf820c, 0xec110500, 0x190c00ff, + 0x0900ff9a, 0x06843584, 0x35221182, 0x058290c3, 0x8252b821, 0x00002e65, 0xff0671fd, 0x0a57ffff, 0x800500ff, 0x21098200, 0x0987f5a8, 0x82e1fa21, + 0x9a993909, 0x00ff8b08, 0xff981926, 0xf6280f00, 0x972400ff, 0x00ffa60c, 0x08e0fa1a, 0xe2200684, 0x99211182, 0x291b829a, 0x00ff6626, 0x8bcd4c25, + 0x2e82b208, 0x12822420, 0xd9f0ff29, 0xffffa69a, 0x821e05e5, 0x20068229, 0x26248220, 0xffff3233, 0x82f468db, 0xe6d922d0, 0x23578268, 0x6666faff, + 0xf4837282, 0x7c84fa20, 0x82cc4c21, 0x008029d4, 0xff068c08, 0xce4c0600, 0x06204a82, 0xfe201283, 0x0482fe84, 0x82fdff21, 0xef0e278f, 0x15cb04f9, + 0x976df4fc, 0x90bb180e, 0x077b2108, 0x51186082, 0xf821132a, 0x2a511894, 0x055e4817, 0xfd6d8783, 0x33748305, 0x8b3433f7, 0xf784fc08, 0x14f815b4, + 0x0794fb06, 0xa4f706cb, 0xe6695982, 0x66ea2605, 0x1500ff68, 0x3b2e1aa1, 0x44f72529, 0xab1584fb, 0x08227f82, 0xd6820ecd, 0xf2320727, 0x330700ff, + 0x250a8274, 0x088ccc08, 0x4f5e07bb, 0x83ab2018, 0x24348273, 0xcdf8ffff, 0x8233820e, 0xf7ff2838, 0x088bf232, 0x97bb065b, 0x066b231a, 0xbe83ffff, + 0x25673382, 0x075b210d, 0x5f101f5f, 0x6b200704, 0x2005ae49, 0x24628674, 0xff8cccf8, 0x23768200, 0x06bb088b, 0x670b1f5f, 0x0e270c5b, 0x14f854f8, + 0x8214fc15, 0xa1dc286e, 0xffff8b47, 0x84b85ee3, 0x250a8204, 0x0848a1dc, 0x548394fb, 0xb89edc25, 0x821c00ff, 0xe3ff2804, 0x00ff4861, 0x53486123, + 0x098306a8, 0x03191985, 0xf7200ac4, 0x00213383, 0x21488423, 0x1e826666, 0xff48a12e, 0x9a99dcff, 0xb4fb088b, 0x3b15c4fb, 0xf7216b82, 0x216b8321, + 0x5682def8, 0x9a190723, 0x21a7828b, 0x715366e6, 0xe6082105, 0x07213182, 0x82658221, 0x24178218, 0x088bb9de, 0x23bf82db, 0x159b14f7, 0xf7249382, + 0xffff0020, 0x2107fd54, 0x0e82ffff, 0x3b088b27, 0xdb07bb06, 0x212b8206, 0x498200e0, 0x21860720, 0x08262c85, 0x34f7077b, 0x3a8314f7, 0xba82ee20, + 0x56f1ff21, 0xff21062c, 0x820e82ff, 0x82d42090, 0x61ee218c, 0x19838c83, 0x660e0023, 0x22428266, 0x689a9911, 0x112005dc, 0x00212d82, 0x8537820e, + 0x9e112104, 0xf7208c82, 0x00203282, 0x27821882, 0x18058762, 0x33089057, 0xf80e074b, 0x3901ff65, 0xff15cccc, 0xc2751500, 0x612600ff, 0xfe32f982, + 0x00fff668, 0xff3eca30, 0xe27ae6ff, 0xee2300ff, 0xc2820814, 0xff827535, 0x7cd40a00, 0x3bf1ffff, 0x0200ff22, 0xffff32b3, 0x82281cf5, 0x74682118, + 0xf5221e82, 0x0a82e23a, 0x09826c20, 0x7a54fd22, 0x07262382, 0x0700ff2a, 0x2382448b, 0x08d82325, 0x820e00ff, 0xebff3752, 0x00ff703d, 0xff52b800, + 0xec11e5ff, 0xf7f4ffff, 0xe9ffffce, 0x338286eb, 0x7ebfee2f, 0x3d0800ff, 0xecfffff2, 0x779066e6, 0x2712828b, 0x8b1ec5db, 0x4cdfffff, 0xf2222382, + 0x8a82862b, 0x82a4b021, 0xf6e8212d, 0x4e204c82, 0xff394782, 0x051e85dd, 0x80a5ffff, 0x00ff0700, 0x065c8f5a, 0x872100ff, 0xb1ffffae, 0x221682c5, + 0x821c1600, 0x54192c7e, 0x0d00ff7c, 0x00ffcccc, 0x8232b320, 0x192523fc, 0x0682089a, 0x9a19292c, 0xb3edffff, 0x2500ff34, 0xd56a6666, 0x1a003605, + 0xfb086666, 0x66ffff25, 0xff153433, 0x66666500, 0xcbffff07, 0x2239820c, 0x82a4b016, 0x26cd2f65, 0xb2ffff67, 0xffff299c, 0xffcd4ce4, 0x048361ff, + 0x00807b22, 0xe122a683, 0xa6824821, 0xb8dee622, 0xe621a182, 0x200a8266, 0x206584e1, 0x240682ff, 0x211900ff, 0x24168448, 0xde1e00ff, 0x232d82b8, + 0xcd4cb400, 0x8b318182, 0x00ffcdcc, 0xff1e4558, 0x32334500, 0x3a5000ff, 0x21ef82e2, 0x918233e8, 0x00803722, 0x9a2d6e82, 0x0e060080, 0x666400ff, + 0x4f01ff67, 0x289182b3, 0x2f1c9cff, 0x9984feff, 0x2c1c8298, 0xff00a0fe, 0x0060faff, 0x890100ff, 0x28098286, 0x00ff6606, 0x87f31f04, 0x25068208, + 0xffff8320, 0x1a82e0fb, 0xc5000627, 0x61feffff, 0x0556458a, 0xa001002e, 0x01ff0800, 0xff9a197b, 0x9a196900, 0xfb2a4482, 0x00ffdcc5, 0xff44ebae, + 0x768389ff, 0xcc4c7526, 0xe64fffff, 0x01224982, 0x4882cecc, 0x33b31a2a, 0x4cd0feff, 0xffff15cc, 0x200b6a42, 0x24ea8261, 0x52b81000, 0x42c38208, + 0x63210568, 0x057a58d7, 0x9e110023, 0x21df83b9, 0x2283a111, 0x585e0e21, 0xef2208df, 0x4f82ae47, 0xd7e30022, 0x66214982, 0x05036566, 0x99f1ff28, + 0xedffff9a, 0x3183ff7f, 0x01003025, 0x5b9000ff, 0x5e220542, 0x21828bb8, 0x0759a120, 0x89638505, 0x8261206a, 0x7a0d2316, 0x6a82ffe2, 0x6a84b820, + 0x2d829e20, 0xd0420020, 0x826a860a, 0xedff23c5, 0x6a860080, 0x2509de5a, 0xe66000ff, 0xd1842b66, 0xff20a382, 0x91053c43, 0x0a3a43d1, 0xd18f6685, + 0x4861ee22, 0xff219482, 0x84cd88ee, 0x820e8262, 0x8eff2194, 0x01237d82, 0x829cf56e, 0xdeef2266, 0x056a53b8, 0xe1f0ff2b, 0xf5ffff48, 0xffffbeff, + 0x241382fb, 0x8a61f0ff, 0x209d8208, 0x2b23822e, 0x0598bdc7, 0x99bb00ff, 0xfaffff99, 0x0032b282, 0xff68e67e, 0x66e682ff, 0x46ffff93, 0xff080080, + 0x3a823800, 0xc00f0023, 0x82258200, 0x00ff2805, 0xff006004, 0x82c00900, 0x3e0f2b04, 0xfeffffb8, 0x00ff4821, 0x29824010, 0x30ebff26, 0xb300ffa2, + 0xff217e82, 0x3b048269, 0xc2b59300, 0x194affff, 0x1100ff9a, 0x0e08da3f, 0xf4f7d4f7, 0x0614fb15, 0x99d0ffff, 0x47221382, 0x2053b81e, 0xa30a2507, + 0x0700ffd8, 0x0e271483, 0x00ff703d, 0x82cccc0c, 0xc40024c7, 0x85063433, 0x261c850c, 0x90c2f1ff, 0x82f8ffff, 0xf5ff2459, 0x8508285c, 0xb8ff2946, + 0xfb0548e1, 0xf7156b14, 0x63515882, 0x83fd2005, 0x4c042dc5, 0xfdffffce, 0xff8f3433, 0x66e6fcff, 0x3920c582, 0xff315e82, 0xff32b3db, 0xcc4c7a00, + 0xccb1ffff, 0xffff8bce, 0x241a825a, 0x6060568b, 0x06d34456, 0xe1faca22, 0xd52a1582, 0x8bb61f05, 0xff8b08c0, 0xbc83a500, 0xcd4c7a26, 0x334e00ff, + 0x38273982, 0x00ff33b3, 0x82ce4c24, 0x8204204e, 0x057b7886, 0x1e830420, 0xcccc0223, 0x827d82ff, 0x80022c28, 0x078b0800, 0x195400ff, 0x82152b9a, + 0x190b2542, 0x7f94829a, 0xff21cf82, 0x21d682f5, 0x5f828282, 0x7582f420, 0xff07852d, 0x6766faff, 0xccfeffff, 0x49ffffcd, 0x48820565, 0x21068954, + 0xde82cccc, 0x7c82f120, 0x33f9ff25, 0x5dff7e34, 0xfc20058d, 0xff236382, 0x8234b3ed, 0x33fe231a, 0x4f83ff34, 0xffff8c23, 0x08fb7df6, 0x9a19f722, + 0x33249883, 0xf7ffff33, 0x0622ad83, 0x59830080, 0x00ffce23, 0x4afb8306, 0x0b2a050e, 0xffff9999, 0xff9819f8, 0x6e840f00, 0xff686624, 0xd6820b00, + 0x82fcff21, 0x066e59b7, 0x6666ff23, 0x21258205, 0xf282b3fb, 0x66660922, 0x24065556, 0xff68e605, 0x821382ff, 0x82e38263, 0x578382b8, 0xfe200548, + 0x00285e82, 0xffcc4c00, 0x9819ffff, 0x00201e82, 0xff203383, 0x19821e84, 0xac84ff20, 0xce4cff23, 0x82b88287, 0x834e825a, 0x19fe2398, 0x7142889a, + 0xfdff2305, 0x1a8232b3, 0x82e6f921, 0x83fd2069, 0x22d2833a, 0x82b3feff, 0x33f325e2, 0x85088d32, 0xf520e582, 0x0021ac82, 0x204d8303, 0x4b3c82f6, + 0x8678062e, 0xffce2106, 0x26069078, 0xff8932b3, 0x19b30000, 0x20089c48, 0x212a8203, 0xdc83f4ff, 0x194bfa20, 0xf5ff2107, 0xec83e683, 0x0a83ff20, + 0x0500ff22, 0xf4201e83, 0x00216b82, 0x822d830a, 0x22c0827f, 0x82333301, 0x201483df, 0x20148301, 0x210482ff, 0x0e820100, 0x66ffff25, 0x82920866, + 0x214e826e, 0x04820d00, 0xccfbff26, 0x0900ffce, 0xcc213984, 0x22c483cc, 0x41079a99, 0x942c05e1, 0x0a00ff82, 0x088b3433, 0x94948b97, 0x82050742, + 0x80052359, 0x74820700, 0x8ccc4c22, 0x33240582, 0x0200ff34, 0x0027f082, 0xffcccc04, 0x82330100, 0x0f0021b8, 0x062e5083, 0x00ff32b3, 0x9898990c, + 0x4c0300ff, 0xbe599ece, 0x0a002a06, 0xffff6866, 0x953433ff, 0x21738287, 0x6e829819, 0x9a19fc26, 0xf9ffff94, 0x06222e83, 0x09829a99, 0xffce4c22, + 0xce204d82, 0xf3251a82, 0x00ff66e6, 0x21048208, 0x5d83efff, 0xff206283, 0x03211384, 0x216782b3, 0x2983feff, 0x32330028, 0xf2ffff05, 0x348233b3, + 0xff240f82, 0x8e6666f6, 0xe6214482, 0x210f8267, 0x7b593233, 0x33ff210c, 0x01222482, 0x80823233, 0xffcdcc26, 0x00800000, 0xff201e82, 0x95840a84, + 0x1e83c683, 0x99000023, 0x21b5829a, 0x07426666, 0x448d2005, 0xc683057e, 0x0600ff22, 0x82062943, 0x5805201a, 0xa2820508, 0xfb840a20, 0x0c230e83, + 0x4c8a3433, 0xfe2007b0, 0x0d254f83, 0xffff0080, 0x235e82fd, 0x66e60300, 0x0a201a83, 0xff242682, 0x969819fd, 0x16834b82, 0x3b830220, 0x82b30a21, + 0x020025a9, 0x00ff68e6, 0xf9211f84, 0x211f8299, 0xcf82f5ff, 0xcc020023, 0x20a582cd, 0x253582fb, 0x33330100, 0xdb828d81, 0x3322a785, 0x8e848b08, + 0x2f0e0526, 0x190b01ff, 0xcb34b182, 0xff150080, 0xb8de2200, 0xeeffff06, 0x00ff48a1, 0x05b81e1d, 0x82830a82, 0x48e1e227, 0x5400ff05, 0x20ad82e6, + 0x212682f4, 0xd354c4fb, 0x0a28550c, 0x07b4fb28, 0xf1ffff8b, 0x5c820ad7, 0x43fa3e21, 0x002205b6, 0x2e82c109, 0x5238f731, 0xaeffff08, 0xff07d6a3, + 0x649bf6ff, 0x82faffff, 0xf9ff23bf, 0x0e829c64, 0x82343321, 0x4cf42234, 0x239382cc, 0xcc4ceeff, 0x25077168, 0x00ff34b3, 0xc26dc510, 0x05352207, + 0x4d9f191e, 0xf9fe2828, 0xffff4861, 0x82666682, 0x9e0322d1, 0x218c82b9, 0x0482ce4c, 0x0320d583, 0x0731c483, 0xffff1f45, 0x0866e6ff, 0x613800ff, + 0x00ff0648, 0x2ae5821b, 0x00402e00, 0x0300ff05, 0x8291b89e, 0x9a99212b, 0xc0250a82, 0x088b9200, 0x20768292, 0x231f8206, 0x0060fcff, 0x80221382, + 0x36828500, 0x00c01b27, 0x9ed1ffff, 0x853082b8, 0x40072241, 0x82278300, 0xfcff2262, 0x24278520, 0xc1f9ffff, 0x202b8248, 0x823c8303, 0x2972820a, + 0xffff70fd, 0xffb85ef8, 0xe682fcff, 0xb3f9ff27, 0xffff0834, 0x239b82e4, 0xccccd1ff, 0x558a4a82, 0x60830320, 0x82e0f921, 0xf8ff2254, 0x8430833e, + 0x82e12044, 0x2287844f, 0x82a0f9ff, 0x82f92080, 0x246e8491, 0x00c0f8ff, 0x234b828b, 0x06b89ec7, 0x2b835182, 0x82ded121, 0xfcff239c, 0x86824861, + 0x82c4f521, 0x83c28404, 0xe6f82676, 0x84088b66, 0x2112858b, 0x48830300, 0x0080fc23, 0x2c8a8491, 0x2e00ffcd, 0xff050060, 0x9999c7ff, 0x84ab8206, + 0x82f92080, 0x03002280, 0x827082e0, 0x00ff2527, 0x08b83e06, 0x8305c344, 0x00ff2b0a, 0xff291c00, 0x90a20700, 0x6b4100ff, 0x33332105, 0x1b22f482, + 0x4a8267a6, 0x82cd4c21, 0x3ae4224a, 0x210a82e1, 0x0a826666, 0x0040fc22, 0x19223f82, 0x30828b9a, 0x8234b321, 0x37948230, 0x32330600, 0x0601ff08, + 0xfeffb89e, 0x159a99bd, 0xcb06b4fb, 0x06b4f707, 0x0b7c6a18, 0x0a8c9e18, 0x2109177c, 0xe279ff34, 0x4cee3505, 0xfb088bcc, 0x9700ff24, 0xff156666, + 0x48e11000, 0x1e1c00ff, 0xde22fd83, 0x4682856b, 0x33b31027, 0xe1e3ffff, 0x277f8248, 0xff9919a1, 0x9a193400, 0x22232682, 0x420648e1, 0xe94205de, + 0x21808207, 0x2682e2ff, 0xf450f727, 0xddffff15, 0x211f8221, 0xfe421100, 0x5e112209, 0x071443b8, 0xcccc6723, 0x2222828b, 0x823333dc, 0x6612265e, + 0xe2ffff67, 0x23de82e6, 0x66661100, 0x19242282, 0x22a7059a, 0x3e226182, 0x1e820040, 0x82731f21, 0x803422e7, 0x207d8200, 0x224c82e0, 0x83a13400, + 0xccc12288, 0x837d82cc, 0xcbff2210, 0x21aa825e, 0x1b821f00, 0x83cbff21, 0x1f002826, 0x00ff9a19, 0x82b81e9d, 0x4cef2261, 0x22ba86cd, 0x82802100, + 0xefff234d, 0xdc853333, 0x64f80e24, 0xaf5814f8, 0x074b2517, 0xe5ffff8b, 0xea205183, 0x0e820488, 0xfc088b23, 0x0cb94334, 0x80150029, 0x00ff8b00, + 0x4c00801a, 0x1a2205b7, 0xa7189082, 0xf8321059, 0x4b7b0634, 0x0614fb15, 0x14f7076b, 0x9b07ab06, 0x768e34fb, 0xb808a75a, 0x23a48276, 0x717d1500, + 0x09837b82, 0x8f821a24, 0x7682088b, 0x4ba4fb23, 0x20748215, 0x2b748294, 0x0e0694fb, 0x1c01ff2f, 0x54f83433, 0x0c227d82, 0x50469819, 0xffff3005, + 0xffea26f9, 0x66660500, 0x28f5ffff, 0x59ff0872, 0xf124052c, 0xeb05a4b0, 0x212edb7e, 0xef7014fc, 0x6c7c200f, 0x082005bb, 0x83163d7f, 0x33072860, + 0x0e00ff33, 0x83055c4f, 0xff673583, 0x8ed70a00, 0x190b00ff, 0x0600ff99, 0x00ff16d9, 0x8b9a190c, 0x78229382, 0x5b826766, 0x66e6022a, 0xff1514fb, + 0x66e68001, 0xea280d82, 0xfeffcccc, 0x0566e6ad, 0x3006ec55, 0xffcecce5, 0x9819ebff, 0x4cecffff, 0xe6ffffcc, 0x23398399, 0x34330aff, 0xe6232b82, + 0x828b66a6, 0x1f05261c, 0xb31300ff, 0x31308234, 0x00ff856b, 0x0832331a, 0xe8e9ffff, 0x5201fff6, 0x80829a19, 0x66e6af26, 0x3b3b1544, 0xf6255082, + 0xffff33b3, 0x224182f6, 0x82f0ffff, 0x09002866, 0xffffcd4c, 0x820080f7, 0x6609258a, 0xf5ffff66, 0x00236b82, 0x8234330f, 0x800822d8, 0x82b58200, + 0xffb2254a, 0x34332600, 0x79233c82, 0x820766e6, 0x82f2206d, 0x0b002368, 0x2d829999, 0x00218f82, 0x054b740c, 0x33330e22, 0x0a203482, 0x43185f82, + 0xff2b0aaa, 0x9a198600, 0xffffb207, 0x82ccccd9, 0x84629887, 0x00ff2168, 0x43827282, 0x88867e82, 0x08222f82, 0x7982db3b, 0x9b82fc20, 0x82040021, + 0xf9ff2690, 0x00ff66e6, 0x240e8203, 0x34b3f8ff, 0x22e6828b, 0x820080fa, 0x21168393, 0xca49fcff, 0x05665306, 0x42078b21, 0xc674cc17, 0x7adc2005, + 0xec790501, 0xfeff310c, 0x069a19ff, 0x8cddffff, 0xffff8bcd, 0xff3373e2, 0x240a046f, 0xff07d4f7, 0xf8ff4100, 0xf774f72f, 0x00ff1524, 0x8b00c046, + 0x403900ff, 0x82048400, 0x2610820a, 0x6e00ff08, 0x8207b81e, 0x610d2c0c, 0xf7ffff48, 0xff9700c0, 0x8280f3ff, 0x9e042622, 0xffff08b8, 0x242d83ab, + 0x0548c11f, 0x056a5dff, 0x00c00222, 0x4c250982, 0x0100ffcd, 0x22098360, 0x828b6666, 0x66f82325, 0x16828b66, 0xff676625, 0x83a0feff, 0x33b32616, + 0x40fdffff, 0x201a8200, 0x232b82ab, 0xb83ee0ff, 0x56834082, 0x84fbff21, 0x33b32266, 0x2030827f, 0x226284f2, 0x8248e191, 0xb9ff237f, 0x97823333, + 0xc6212d83, 0x2b5e82cc, 0x8b33b346, 0x00ff6308, 0x15b85ee8, 0x77839d82, 0x83020021, 0x8204858c, 0xff0826ca, 0xb89e1500, 0x20058206, 0x204083a1, + 0x22229500, 0x8200c010, 0x831b8222, 0x213f8244, 0x3a82fdff, 0xea239c87, 0x84074861, 0x2222993f, 0x830040ef, 0x82cc829d, 0x82fc8334, 0x833e843f, + 0x253f82f7, 0xeaffff06, 0x2299b85e, 0x5238ef22, 0x3e822282, 0x3a83ef82, 0xcf85c483, 0x0720bf85, 0x66213f82, 0x82229966, 0x63072bbf, 0xa1a7ffff, + 0x34f71548, 0x68837b06, 0x66e6d327, 0x19dcffff, 0x8204869a, 0x838b830e, 0x23118506, 0x66e62300, 0x2c246282, 0x9b089a19, 0xb72dde82, 0xffff3433, + 0x15343367, 0xcc98ffff, 0x200484cc, 0x22058305, 0x8200ffcd, 0x260a8215, 0xffeb11ba, 0x82b3e9ff, 0x21cd2725, 0xbfffff47, 0xab82cc0c, 0x66a6b222, + 0x0025a082, 0xffff2700, 0x2d6f82ec, 0xf7840f00, 0x80f0ffff, 0x1300ff00, 0x6f82d723, 0xa37a0124, 0x0c8306d6, 0x6a82d820, 0x1e850f27, 0x750f00ff, + 0x210a82c2, 0x37822613, 0x23ffff29, 0x4d00ffd8, 0x82593e4a, 0x82ba206f, 0x16002ca9, 0x0e08ce4c, 0x6b70f8ef, 0x822cfb15, 0x1eec22ec, 0x256382b8, + 0xff48e1ef, 0x0a831000, 0xe113002b, 0xf0f70848, 0xfb062b07, 0x82e28330, 0xffff211f, 0x04851e83, 0x72820e82, 0x1983ff23, 0x223b8299, 0x82e13aef, + 0xabf1263b, 0x0e00ff85, 0x23aa824c, 0x34b31100, 0x08855918, 0x7b540e27, 0x660d00ff, 0x06184b66, 0x6000ff26, 0xf70667e6, 0x62835383, 0x04866d84, + 0x8b227182, 0x8c82f708, 0xb8821883, 0x72848782, 0x6e825b82, 0xf0fb0824, 0x389beb07, 0x3d471020, 0x00ff2305, 0x6c82e600, 0xff218882, 0x107918ff, + 0x08824909, 0x4984ab21, 0xef220682, 0xc183e43a, 0x98199f22, 0x1921e187, 0x826e829a, 0xefff213b, 0xec2b0483, 0x088b9a19, 0xf4f7ef0e, 0x181524f8, + 0x62188147, 0x7a610bfb, 0x05816108, 0x48ffff21, 0x822305c8, 0x18ffff90, 0x23100b70, 0x707d1500, 0x08285485, 0xffff14f7, 0x1566e690, 0x0c685a18, + 0xceccf022, 0xef234582, 0x82083233, 0x66ed2206, 0x32b38667, 0xff9999f2, 0xcc4ceeff, 0x064b088b, 0xb3f8ffff, 0x66848b34, 0xfa2b06f8, 0x00ffcc4c, + 0x08666605, 0x83d7ffff, 0xb31f360a, 0xffff0534, 0xff34b3c3, 0x0080cfff, 0x2a00ff05, 0xffffcccc, 0x210a84e3, 0xef5ae608, 0x05002406, 0x8281cc4c, + 0x4cf52660, 0x14fb08cc, 0x16a64a07, 0x81857185, 0x250adf41, 0xe66e00ff, 0xac180766, 0x4c2107c4, 0x276e82ce, 0xff3333df, 0x32b31500, 0x2606db4f, + 0xff34332e, 0x82b31e00, 0xb3172b13, 0x00ff0832, 0xff991953, 0x29834000, 0x80110032, 0x0d00ff00, 0x00ff3273, 0xffce4c18, 0xb8deffff, 0xb782fe82, + 0x61f2ff23, 0x21298248, 0x1482cc3d, 0x9a19d022, 0x342bb782, 0xfb06cccc, 0x1fffff74, 0x82159a19, 0x83b920a0, 0x82c62024, 0xc6ff2153, 0xb920db83, + 0x22057e76, 0x825c4fb9, 0xb0c62b1b, 0x3900ffa4, 0xff8bcc4c, 0x80424600, 0x82068205, 0x5c4f2111, 0x15821684, 0x8ba4b022, 0x46225d82, 0x228233b3, + 0xcd4c3923, 0x854483ff, 0x26ff8254, 0xffff15d3, 0x82703dd8, 0xc2df260f, 0xdfffff8f, 0x244882cc, 0x3433d8ff, 0x82118208, 0x00ff2406, 0x84713d20, + 0x00ff2416, 0x8390c227, 0xcc272248, 0x204882cd, 0x22f58320, 0x82343320, 0x7427200a, 0x06820584, 0xcd202883, 0x33213282, 0x26548234, 0x088b3333, + 0x8a4394f8, 0x861582bf, 0x82cc20bf, 0x82ff2048, 0x836482d5, 0x82bf9311, 0x841683f2, 0x83bf85d5, 0x92e8826b, 0x838683bf, 0x83bf94ba, 0x82d6828c, + 0x05ac53bf, 0xbf84a782, 0xa8843420, 0xcc20bf90, 0x342bbf88, 0x2f0e088b, 0x34f814f8, 0x1800ff15, 0x210bf141, 0xb6829a59, 0x66a6dc22, 0x4806cb7c, + 0xfb211304, 0x09007ad4, 0x489a5921, 0x72820e01, 0x14842320, 0x8266a621, 0x82048319, 0x088b360e, 0x8b06d4f7, 0x14fb154b, 0x0714fb06, 0xf70614f7, + 0xfb8b0714, 0x230f8c54, 0x15cb54fb, 0x22881682, 0x8214fb21, 0x852a8520, 0x2f0e2113, 0x30858d18, 0x160b4a18, 0x1100ff24, 0x1b8285ab, 0x21055278, + 0x254334b3, 0xcb082205, 0xa36e186b, 0x13f8440c, 0xffcd4c22, 0x40821683, 0x1833b321, 0x880fd3b3, 0x334a1847, 0xf88b2216, 0x185f8e14, 0x18365944, + 0x2316b544, 0x1534fbab, 0xff217a96, 0x7a6f18ff, 0x20d68f09, 0x84d18333, 0x200482d6, 0x20d69211, 0x25548433, 0x34f708cd, 0xc08474fb, 0x1082cc20, + 0x34b3f122, 0x18141946, 0x450d8060, 0x32820c00, 0x60514984, 0x05374f08, 0x9e831682, 0x088bcc24, 0xc085f8ab, 0x447c5421, 0xd6790599, 0x824c2006, + 0x0db0441a, 0x20123741, 0x828d82cc, 0xd6b51837, 0x07327a14, 0xbf9e6b20, 0xd1843320, 0x22060e41, 0x4134b311, 0xae1805e0, 0x7a180989, 0xbf8f0f4b, + 0x80414b20, 0x41342035, 0xc4820880, 0x42138041, 0x6b22079f, 0x0210f4f7, 0x431d0140, 0xa0420761, 0x36294209, 0x18096143, 0x220d784e, 0x8815abf4, + 0x7cab201a, 0x76911a77, 0x187b5421, 0x21220392, 0xa142f4f7, 0x86fb205e, 0xc79218c0, 0xff8b2529, 0x33b31100, 0x23050b55, 0xcd4c0e00, 0x20053a45, + 0x0e414508, 0x440a2244, 0x3c4a0fe3, 0x3b434511, 0x4174f721, 0xc0840581, 0x7a53b320, 0x0d22440c, 0x65187692, 0x99440c1a, 0x34fc2316, 0x4f18156b, + 0xfc4a0ebe, 0x820e2014, 0x18002080, 0x460c0d7b, 0x88450e4b, 0x85ab2108, 0x2806cc44, 0x8b7b54ee, 0xf734f808, 0x0aa44574, 0x41b1c040, 0x51180d80, + 0x83472313, 0x24f74108, 0x8b2f0e25, 0x8215e4f7, 0x2e2c2733, 0x2300ff14, 0x0486ecd1, 0x152e2c26, 0xe4f7088b, 0x202e4d53, 0x183082fb, 0x211570b2, + 0x1b4be4fb, 0x0da24109, 0x2616fe41, 0xf707e4f7, 0x4504fc14, 0x66420e80, 0x3a214812, 0x8b54f722, 0x205c6047, 0x0b3c434b, 0x2051bb41, 0x053c43f7, + 0x1f484c20, 0xf78b2257, 0x1c1e4154, 0x213fbf47, 0x9a434bab, 0xf76b225c, 0x20be9c34, 0x087e4834, 0x9d44cc20, 0x44082005, 0xd44d16a4, 0xaf0e2816, + 0x01ffa4f7, 0x57ec1160, 0x7d260918, 0x1500ff70, 0x5c575278, 0x24068506, 0x82eaffff, 0x21168290, 0xc44ec275, 0xeaff2312, 0xb457ae87, 0x85082005, + 0x050c5706, 0x8aeaff26, 0x1a00ff3e, 0x2705e562, 0xff33b3c1, 0x48a1fafe, 0xe622cc82, 0xa3820040, 0xff220482, 0x098280e5, 0x70fd0f26, 0xc0e4ffff, + 0x0e380982, 0xff08b8de, 0x856bb8ff, 0xfd2600ff, 0xffff0570, 0xff41a0c6, 0x9a1937ff, 0xfb220a82, 0x944f0020, 0x08002805, 0xffff9af9, 0x822a5ced, + 0x67e62543, 0x1efbffff, 0x00213482, 0x2f0a8511, 0x1000ffba, 0x00ffe1ba, 0xffc2e009, 0xb9de0400, 0xfd2a0e82, 0x00ff08f4, 0xff48a124, 0x48838000, + 0x823c0021, 0xd7ff230a, 0x538248a1, 0xd823b122, 0x820e437a, 0x111d621b, 0x21068e7d, 0x68839e11, 0x90000027, 0xee5f00ff, 0x373e8214, 0xffe6fdff, + 0xe0ba0a00, 0x99faffff, 0xffff959a, 0xff9919f7, 0x68e60500, 0x65216f82, 0x22998266, 0x82cc4cc5, 0x1ef228ed, 0xffff8bb8, 0x8214eef3, 0x12232120, + 0x9e21af82, 0x210e82ba, 0xe982c600, 0x8240e721, 0x83b520d3, 0x012a084b, 0x0668e63f, 0x199affff, 0xce00ff9a, 0xff05cc4c, 0xb89ef4ff, 0x7d1600ff, + 0xe0ffff70, 0x00ffae47, 0x7ed82301, 0x61eaffff, 0x10820848, 0xff281c26, 0x3ecac9ff, 0xbe2e2582, 0x00ff70bd, 0x05d6a323, 0x7900ff73, 0x11823333, + 0x7a54f72a, 0xb02700ff, 0xe7ffffa5, 0x21394c83, 0xffff9899, 0x9d66e6db, 0x00ff8a08, 0xfffa7f00, 0x00e0feff, 0x200000ff, 0x210f8306, 0x4e820080, + 0x82c0fd21, 0x20012c10, 0xfdffff00, 0xffff7d7f, 0x829af9ff, 0x83802009, 0x66862113, 0xf0251e82, 0x00ffe9c6, 0x2b4b8206, 0x33b3efff, 0xde0300ff, + 0xefffffb8, 0x2805d341, 0x066666b6, 0xc0f6ffff, 0x22e08200, 0x823333f7, 0x62f021db, 0x21833f82, 0x8a21f92e, 0xc8ffff08, 0xffffcd0c, 0x057a14c0, + 0xeb835682, 0x0e00ff22, 0xfe220986, 0x098836e0, 0xf7208483, 0xf2257f83, 0x00ff64e6, 0x239f8205, 0xe33aecff, 0xa1312b82, 0xf8ffff48, 0xff084721, + 0x9a995001, 0xb347ffff, 0x22488232, 0x82ba29f6, 0x48212180, 0xd7230a82, 0x8206acfc, 0xfdff2d7a, 0xffff1530, 0xffcccc32, 0x66e6d300, 0xe8200a82, + 0x0c2cbd83, 0xff05b8de, 0x48211c00, 0x1e2000ff, 0x222d0a83, 0xff064861, 0x70fdd8ff, 0x02d3ffff, 0x2e1b8290, 0x579a995d, 0x2200ff15, 0x00ff66e6, + 0x82ae4729, 0x820d2011, 0xbcff2338, 0x5b82d863, 0x7182cf20, 0x541a0028, 0xff0e057a, 0x0b826001, 0x84400121, 0xe1e3225a, 0x20718248, 0x2d4483e5, + 0x740080fb, 0x9ef7ffff, 0x00ff08ba, 0x6682610c, 0x98197b22, 0x01204382, 0x8e60c982, 0xc0f62505, 0x0800ff00, 0xff271982, 0xff00a0f5, 0x83c0feff, + 0x40b021e8, 0xf5200a82, 0xff289582, 0xffff7fc1, 0x0080bcff, 0xae234f82, 0x82085238, 0x265c8206, 0x800400ff, 0x83ffff01, 0x273a8260, 0xff087447, + 0x1fc585ff, 0x0731e119, 0x9f82f520, 0x60830020, 0xb8227682, 0x6084ffff, 0x50840120, 0x5b82a020, 0x19090025, 0x83ffff9a, 0x44002e60, 0xffff6766, + 0xff9a59c2, 0xcdcc5100, 0x28a0828b, 0x8bb81e1c, 0x021a00ff, 0x82608390, 0x82162096, 0x2060827b, 0x215f8248, 0x4a829ef3, 0xcd598420, 0x83e02005, + 0x210f829c, 0x55830900, 0x0280f72c, 0x600a00ff, 0x0100ff00, 0x4482fe3f, 0x00c04f2b, 0x3d00ff95, 0x00ff66a6, 0x82b78343, 0x82ce205c, 0x820020b7, + 0xffff225c, 0x839b83fb, 0x209b8360, 0x202d82a2, 0x828d837b, 0x8205205c, 0x421b8243, 0x08230578, 0x85ff4861, 0xc0fe215c, 0x5c825782, 0xf52a8182, + 0x00ffe2fa, 0xff32b34f, 0x2882bcff, 0x823e0021, 0xaeff2304, 0xb7823433, 0x809eff25, 0x1834fb00, 0x210e1c41, 0xd9654861, 0xb85e240f, 0x830e00ff, + 0x1c411859, 0x08aa6812, 0xffff8b23, 0x632382ee, 0xf120058e, 0xff21e482, 0x39c482ed, 0x01ff0e08, 0xffcc4cf4, 0xbebfb801, 0x0700ff15, 0xffff6866, + 0xffc8ebf9, 0x14820400, 0xebf6ff23, 0x26368284, 0x085c4ff7, 0x820724fb, 0x99e42509, 0xe3ffff9a, 0xeb271983, 0xffff6666, 0x83ceccdb, 0x99dd22a4, + 0x201b829a, 0x211182e2, 0x0a831400, 0x661b0024, 0xa3820866, 0x2d821920, 0x831d0021, 0x83162004, 0x6622221b, 0x302d8266, 0xec113800, 0xffff2b07, + 0x05ccccec, 0x218bffff, 0x24578848, 0xff3233e4, 0x20578dff, 0x21578499, 0x5794ff67, 0x00ff9922, 0x67235786, 0x82eb088b, 0x0e003f46, 0x00ff2a5c, + 0xff32b30b, 0x48210d00, 0xe60e00ff, 0x0200ff68, 0xf70870fd, 0x2000ff34, 0xe05a0c00, 0x01002d06, 0x00ff7ce1, 0xffcccc09, 0xe690fdff, 0xca82f383, + 0x08ecf928, 0xff068b08, 0x428256fe, 0x26d8fe24, 0x488215a8, 0xff0ad726, 0x66e61000, 0x05213682, 0x200f82ee, 0x254e8308, 0xff52f809, 0xa9820600, + 0x4f0a0021, 0x3d2405f5, 0xff06cdcc, 0x342b0c82, 0xffff958b, 0xffceccf9, 0x82e60500, 0x19f7234f, 0x42820898, 0xffcdcc26, 0x9a19efff, 0x19204282, + 0x1b232784, 0x848b6666, 0xffff24cd, 0x829a99e9, 0x66e625dd, 0x04fb0866, 0x84080341, 0x200484fe, 0x281e82e4, 0x0654fb08, 0x63e6ffff, 0x222882d7, + 0x411382ea, 0xf7200b06, 0x00283383, 0xff9a9919, 0xed7d1500, 0x23060941, 0x8b299c19, 0x1b227582, 0x92825d8f, 0xa4704424, 0x3d821553, 0x6c827183, + 0x718b9920, 0x2306ca41, 0x67661600, 0x0d5c9a18, 0x72419f89, 0x83ff2011, 0x82328297, 0x2b9c84dd, 0x332901ff, 0xff158332, 0x34b33700, 0x06226f82, + 0xda8234b3, 0x8626fc82, 0x800100ff, 0x2261ff00, 0x03002305, 0x0a823233, 0xffcccc27, 0xce4cfeff, 0x050167ff, 0x82e6fa21, 0xb3fb2c43, 0x14fb0834, + 0xff0504fb, 0x8366faff, 0x68e6260f, 0xb3f7ffff, 0x28288234, 0xff85cccc, 0x66660400, 0x20068308, 0x293a824c, 0x9332b3fd, 0x0600ff8e, 0xde8266e6, + 0x68662627, 0x995a00ff, 0x2338829a, 0x06cc4cc8, 0x4c215d82, 0x70d082cc, 0x3320057f, 0xfd223f82, 0x2b829a99, 0x08cc4c25, 0x82fdffff, 0x0600214f, + 0x00271482, 0xff32b301, 0x82190700, 0x84052019, 0x32332504, 0xf714f708, 0x00217d82, 0x202e8305, 0x20148304, 0x2a6b8208, 0xcd4c0000, 0xfbffff91, + 0x83089999, 0x233f8306, 0x83343302, 0x21824a82, 0x19f9ff23, 0x3a55829a, 0xff9899d9, 0x3233a7ff, 0xbcfeff05, 0x28f76866, 0x9fffff15, 0x00ff6626, + 0x8266e663, 0x09e43b94, 0x1c00ffba, 0x00ffa4f0, 0xff7d7f01, 0x34f32f00, 0x761f00ff, 0x1a00ffc9, 0xbe8252f8, 0xff290582, 0x1c7a1700, 0x702900ff, + 0x246882a4, 0x00ff4881, 0x362d8218, 0x2c87e6ff, 0xffff9508, 0x058e82f5, 0x800900ff, 0x0a00ff00, 0x8205727d, 0x78193946, 0x2800ffd4, 0x00ff67e6, + 0xa7b87e04, 0x85e8ffff, 0xffaa08e4, 0xae07e5ff, 0x28066941, 0x6fcc0cd0, 0x0fe3ffff, 0x279b825c, 0xff99999f, 0x9a199cff, 0xf9208882, 0xff204382, + 0xf5310484, 0x858b0080, 0x800600ff, 0x068b0800, 0x1200ff0e, 0x260d82eb, 0x15cccc60, 0x826c00ff, 0x2e002324, 0x73821e85, 0x82c70c21, 0x87053150, + 0x0e00fff0, 0xffff71fd, 0xff1e45fc, 0x14ae0800, 0x38219282, 0x27b88210, 0xff0a172c, 0x142ecaff, 0x45272982, 0xffad0040, 0x82403800, 0x4f3822a3, + 0x220a825c, 0x82a43045, 0x30ca217b, 0x2c22ad82, 0x7b823e0a, 0x1b83f520, 0xf0c70822, 0x57214682, 0x2850820a, 0x00ffb4e8, 0xff9e6f05, 0x25648200, + 0x2e00ff08, 0x7a849082, 0x06314b82, 0x00ff1018, 0xfff6e80d, 0x8a010f00, 0x9c0700ff, 0x212e8228, 0x3882a4b0, 0x820a9721, 0xcc642229, 0x21f182cc, + 0x298200c0, 0x53820e20, 0xc0fcff22, 0x092e7482, 0xffff52f8, 0x8b3473f3, 0x57f1ffff, 0x0682080a, 0x34b30327, 0xcc32ffff, 0x230486ce, 0x8b32b303, + 0xf1229082, 0x1b827b54, 0x707df326, 0xf70900ff, 0xfc221b82, 0x5c82e1ba, 0x82844021, 0x83e8201a, 0xcc642247, 0x22ab82ce, 0x820ca2fc, 0x66a62115, + 0x96217c82, 0x218682c9, 0x90823233, 0x91eae629, 0x8b2f0e08, 0x5d15f4f7, 0x9a5506d8, 0xe3ff2307, 0x58189a59, 0xd4210791, 0x22098506, 0x861c00ff, + 0x05c9551e, 0xd4f70823, 0x20098507, 0x832e85ff, 0xdcff251e, 0x088b66a6, 0x830e0756, 0x063b561e, 0x6900ff33, 0xffff0080, 0x15666630, 0x3d3600ff, + 0x1700ff71, 0x27f68340, 0xff196406, 0x18c40200, 0x22089e82, 0xffff4d82, 0xffe423fe, 0x0b570400, 0x9cfaffff, 0x00ff081c, 0xff1f0516, 0x0a17e5ff, + 0x2200ff05, 0x829c48a1, 0xd723218a, 0xd8200483, 0x22220a82, 0xea82289c, 0x26821c82, 0x82cd0c21, 0xa0fa22ea, 0x823c8200, 0xfeff2350, 0x5082fc29, + 0x82627021, 0x10b8265a, 0x630600ff, 0x224b82d8, 0x821e4517, 0xac47217a, 0x03214b82, 0x220f820c, 0x82f8f306, 0x028b2624, 0xd10300ff, 0x21098228, + 0x7f820a57, 0x82c04a21, 0x61322719, 0xf4ffff48, 0x2982b85e, 0x82200721, 0x60fe22b5, 0x26588200, 0xffff28fc, 0x82e8bbf9, 0xabf823d0, 0x068208c6, + 0x66e68126, 0x6699ffff, 0x4c270483, 0x81ffffcc, 0x828b67e6, 0xa9f82290, 0x221b82fc, 0x826abcf9, 0xe8fb2132, 0x5c215282, 0x215c8229, 0x1a824020, + 0x4761f427, 0x633200ff, 0x22ab82d8, 0x824636fe, 0x82552015, 0xca032257, 0x2809823e, 0x8e929a99, 0xf7ef0e08, 0x051570f4, 0xff22bf82, 0x5318d6f8, + 0xfb270c4d, 0xffff0634, 0x827929f7, 0xd6f8225c, 0x33531887, 0xf78b250b, 0x04fb05c4, 0x200a4063, 0xb26118a3, 0x05fa660b, 0x707de522, 0x4b054163, + 0x1a2205eb, 0x62199082, 0xff201b45, 0xec220082, 0x728205db, 0x055b8b26, 0x15848cfb, 0xfb277482, 0xfffff007, 0x8710f8fb, 0xef072404, 0x826d088b, + 0x82fb2074, 0x24138508, 0xf0070400, 0x24f5828b, 0xa90810f8, 0x82088507, 0x8336820d, 0x25098218, 0x088b11f8, 0x088506a9, 0x4f831885, 0x08245a85, + 0xf38b076d, 0x209a6640, 0x21b08390, 0x05828fae, 0x9c52f821, 0xc4f723c5, 0xc78246fb, 0xf8040023, 0x20fc8d10, 0x21368710, 0xfc938b10, 0x41ffff21, + 0xf0201060, 0x21076041, 0x60418bf0, 0x00ff2d12, 0xf89819b7, 0xfeff152d, 0x060200a0, 0x21090b47, 0xf768ff9a, 0x0794210b, 0x2306a85c, 0x717d1500, + 0xff2b1984, 0x8f821a00, 0x01ff088b, 0x18feff5f, 0x271797e1, 0xff0794f7, 0x68e60000, 0x90202b83, 0x80223582, 0x3f82ff00, 0xffff7025, 0x829899e4, + 0xe0fe2a3a, 0x154b0200, 0xae1100ff, 0x25cb8214, 0xffec510e, 0x6318f1ff, 0xae2111a2, 0x24168414, 0x51eeffff, 0x233482ec, 0x3233efff, 0xf0238b82, + 0x58ffcecc, 0x34200f70, 0x27069744, 0xffcc4c0e, 0xcecc1000, 0x01312d82, 0xfffeff0e, 0x666628ff, 0xfdffff15, 0xffff3433, 0x283782fa, 0x9c99faff, + 0xccfcffff, 0x200e82cc, 0x24888419, 0x069a19df, 0x21558285, 0x986366fb, 0x242c8307, 0xce4c0500, 0x5d378208, 0xff23062e, 0x82800000, 0x830620c0, + 0x99032c04, 0x0400ff9a, 0xd108cccc, 0x828e05eb, 0x835a8209, 0x07ee6b0e, 0x82343321, 0x0500237b, 0xd782281c, 0xd4cd0422, 0x21084382, 0x00ff1c8f, + 0xff180403, 0xf2ddfbff, 0x1600ff08, 0xffff9a59, 0x050a57e1, 0xbd3e00ff, 0x5e00ff70, 0x0a82281c, 0xe2fa0222, 0x74224b82, 0x4782903c, 0xff84ab24, + 0xea820600, 0x05222c82, 0x47831659, 0x82f4fd21, 0xf8532147, 0xf8211b82, 0x21478252, 0x1a82088c, 0x34b36a24, 0x398234fb, 0x3c4a0322, 0x20201282, + 0x00269e82, 0xffffd04c, 0xea82b3f9, 0x3033fd22, 0xb33ce082, 0xef0e0832, 0x15abf4f7, 0xb3d2ffff, 0x00ff0634, 0xffc2f512, 0x9a194000, 0xc9ffff05, + 0x2b227a83, 0x0a826666, 0x3183df20, 0x00809422, 0xd0220a82, 0x2a6666e6, 0x98d0180c, 0x09c06a18, 0x99205784, 0xff21d282, 0x22cc82fd, 0x41cc4c0e, + 0xff20129b, 0x5507d959, 0x082e054f, 0xcc1601ff, 0xcaffffcc, 0xff1566e6, 0x3c82ebfe, 0xb3d80023, 0x27ca8233, 0xff48a12d, 0xff7f9c00, 0x6f260a82, + 0x6b0652f8, 0x30828b07, 0x565c4f21, 0x8b8305e5, 0x1100ff25, 0x828b84ab, 0x850683fc, 0x0e002416, 0x828b5c4f, 0xa4b02117, 0x2205e867, 0x42a4b011, + 0x18830534, 0x54253e82, 0xfb088b7c, 0x29d597f4, 0xe3dbffff, 0xffff07d8, 0x6582cf86, 0x48e15e31, 0xf5ffff05, 0x00ffae87, 0xff103808, 0x82f0f0ff, + 0x26fe274a, 0xf7ffffa8, 0x18827bd4, 0x08e08f22, 0xff240a89, 0x2dd20100, 0xe5252382, 0x0a00ffe2, 0x2c18836c, 0xff089ad9, 0x98194f02, 0xe630feff, + 0x31c28266, 0xfff06704, 0xf087fcff, 0x340500ff, 0xfeffff38, 0x09828c57, 0x83a43021, 0x200722be, 0x31b38200, 0xff840b07, 0xfc290300, 0xba0400ff, + 0x0600ffe4, 0xd982f007, 0xf41d0927, 0x850900ff, 0x26308220, 0x00ff9c19, 0x829a190f, 0x98992179, 0x33379282, 0xfeff0832, 0xffce4cb5, 0x34330301, + 0xadffff15, 0x00ff85eb, 0x827a5440, 0x7a03226a, 0x265b82e1, 0x00ffec11, 0x82008002, 0xcccc2109, 0x31085e82, 0x0834b306, 0x00ff07ab, 0x06cc4c6d, + 0xccdeffff, 0x8effffce, 0x0e059a19, 0x666800ff, 0xe9ffff67, 0xff1566e6, 0xb91e0c00, 0xbdf2ffff, 0x1600ff70, 0x3482a4f0, 0x47210c27, 0x420d00ff, + 0x20898290, 0x237a8257, 0x0a176000, 0x0b225f82, 0x1582a4f0, 0xffcc0c2b, 0xb81effff, 0x421400ff, 0x27348290, 0x00ff94f8, 0x08c2f50b, 0xfa200a82, + 0x0b277e82, 0xffff34f3, 0x8200c0eb, 0x0a172b23, 0x0cf4ffff, 0xf2ffffcd, 0x1e82acfc, 0xbe7fe02e, 0x9cdcffff, 0x01ff05ee, 0x07ec112e, 0x2006bc55, + 0x050862ff, 0x187a5421, 0x82126555, 0x8b84211b, 0x23081782, 0xfb08ce4c, 0xffff07c2, 0xff9999df, 0xd6632300, 0xf9ffff05, 0x00ff21b0, 0xff0ce206, + 0x3b5ff7ff, 0x810300ff, 0xf7239482, 0x828b7b54, 0x47f82267, 0x213482ef, 0x6d823ff8, 0x0a37fd22, 0xdc262a82, 0xfaffff29, 0x1a82fa5e, 0x52f8f222, + 0x2b829283, 0x4821ff22, 0xba21a682, 0x21bb82e2, 0xa18256ee, 0x8334f321, 0x30fd26ea, 0xd59fffff, 0x33ea8280, 0xff9a99d7, 0x9a197601, 0x3200ff15, + 0xff0600c0, 0xb89eb6ff, 0x7b820484, 0x10d8f624, 0x0484ffff, 0x1844fd22, 0x3e253b82, 0x0400fffa, 0x221e82f3, 0x82ae07f4, 0x820a8745, 0x90ad2b5a, + 0x3af8ffff, 0x0c00ffe1, 0x9a8214ee, 0x197f002f, 0x00ff069a, 0xffa69b12, 0x67e60000, 0x05ef5dff, 0x67660d28, 0x1100ff8b, 0x046333b3, 0x20f68207, + 0x231b8586, 0x7a54eeff, 0xff223782, 0x828240cd, 0x61490024, 0x0483ff48, 0x09249e82, 0x00fff027, 0x02260484, 0x00ffe8bb, 0xa182c10d, 0x820cfb21, + 0xf80b251e, 0xffff0852, 0xec820a87, 0xffb64826, 0x1ec50700, 0x3321a682, 0x694a8334, 0xee21059c, 0x0749554c, 0x2213db43, 0x43ffcc4c, 0xa95c0666, + 0xac230805, 0xfeff9a99, 0x1534b3ae, 0x02b0ffff, 0xa000ff90, 0xff059a19, 0xf628f5ff, 0xcf1500ff, 0xdcffff5c, 0x858ba470, 0xeaff230f, 0x7f82a430, + 0xff232583, 0x8266e65f, 0x18f83025, 0xf0ffff10, 0x00ff0a17, 0xfff06706, 0x82abecff, 0x830f20da, 0x0cf83134, 0x00ff08cc, 0xffb8de0f, 0xf813f8ff, + 0x2b1300ff, 0x06221982, 0xae82ec71, 0x82d6e321, 0x82e02118, 0x07271e82, 0x00ff6c27, 0x82d8630e, 0x6e5823f2, 0x1b820614, 0xff231082, 0x82289cf1, + 0x2c062610, 0xf3ffff8c, 0x22308291, 0x82c6cb11, 0x5c8f21e9, 0x2206da44, 0x82527809, 0xcf0f223a, 0x224a86e0, 0x82666606, 0x2304825e, 0x9a19f8ff, + 0xe6215982, 0x32a28268, 0xff323383, 0x66e62900, 0x1000ff15, 0x00ff3433, 0x8232b320, 0x38102753, 0xdfffff52, 0xb882b85e, 0x7a94df23, 0x2fd58206, + 0x1516eeff, 0x9700ff0e, 0x01ff9a99, 0x15cc0c96, 0xe12b7282, 0x0d00ff48, 0xffff9042, 0x825c0fe9, 0x83f32021, 0xbdf222c2, 0x27548270, 0xff66e6a8, + 0xf8e89fff, 0xf3303e82, 0xffffba29, 0xffa2f0f2, 0x00e00000, 0xb3ebffff, 0x0d226382, 0xa7823108, 0x829a1921, 0x050d229d, 0x0589421f, 0x40140023, + 0x26238200, 0x00fff6e8, 0x8233f30b, 0x54032158, 0x202b1e82, 0x00ff6766, 0x05506d23, 0x8207c2fb, 0x83ee2062, 0x180e20ac, 0x240f5e98, 0x8b33b311, + 0x05395bff, 0x21054865, 0x5a829912, 0x332d0127, 0x00ff0734, 0x22ef8320, 0x829a99dc, 0x4f0630d4, 0xf9ffffdf, 0x00fff41d, 0xffc5a008, 0x827efcff, + 0xab08238a, 0x67828b85, 0x10b80722, 0x07314282, 0x00ff42c0, 0xfff6c802, 0xd7230600, 0xa10500ff, 0x221a8206, 0x83ae070d, 0x202b8292, 0x23e08200, + 0x1e451400, 0x1121b082, 0x21a182aa, 0xea83ce0c, 0xffd20226, 0x540e6000, 0xa8205f82, 0xc9226a83, 0x031034f3, 0x2605022b, 0xf7d4f7af, 0x70eb1574, + 0x002a0cdd, 0x8b7b540e, 0xab1100ff, 0x06840885, 0x44ff8421, 0x542206e3, 0xe344ff7c, 0x48a02007, 0x7a210674, 0x375f188b, 0x905b1808, 0x0617680c, + 0x2a052f46, 0x8b34b311, 0x14fb8b08, 0x8f34f715, 0xc45f1868, 0x2068870e, 0x2068887a, 0x20689160, 0x22738286, 0x827a54ee, 0x248d839c, 0x660d00ff, + 0x61848566, 0x8b2405f4, 0xab1594f7, 0x0d226788, 0x6e18146e, 0xd7830c18, 0xef26d08c, 0x088be03a, 0x7085066b, 0x7c20cc95, 0x2206df45, 0x8284abf1, + 0x27cc833e, 0xd4fb74f7, 0x20ffff15, 0x0e219ca1, 0x22cb8254, 0x8286abf1, 0x86ab2838, 0x00ff088b, 0x849a19df, 0x8b84219c, 0x04839784, 0x21100441, + 0x168434b3, 0x21077949, 0xe182a0fe, 0x4c550023, 0x277282cc, 0xff9a99df, 0x9a99dcff, 0x200b9747, 0x5fb68232, 0x7c20059b, 0x12966e18, 0x21159747, + 0x97477a54, 0x3c7f2312, 0x9747ffff, 0x10382112, 0x21079747, 0x9747f45d, 0x82192022, 0xe89f23a1, 0xa84805f6, 0xc4f42b46, 0x0b00ff9c, 0xffff1cef, + 0xd278cceb, 0x7e7f2705, 0xf8af0e08, 0x8141abb4, 0x74fb2368, 0x5342d4f7, 0xfb8b2260, 0xcd884314, 0x57ffff27, 0x01ff9a99, 0x2b874736, 0x473d2a21, + 0x07211187, 0x078747ae, 0x19240631, 0x5efaffff, 0x0700fff8, 0xffffbfbf, 0x820c37fd, 0x52b82909, 0x00ff088b, 0x8b08ac08, 0x28053247, 0x04810300, + 0x4f0600ff, 0x2104825c, 0x9e47d2e2, 0x8c6c2108, 0x21289e47, 0x4a827a54, 0x34b31123, 0x05fb4a08, 0x200a9e47, 0x2d9d8297, 0x00ffffff, 0x8a343314, + 0x0c00ff98, 0x7b470100, 0xff322209, 0x157b4700, 0xfff00736, 0x7a146000, 0x6cf70e05, 0xb37f00ff, 0xffff1534, 0x8bf853f7, 0x7a050c4b, 0xf93205fa, + 0xffffa4b0, 0x08b81ef9, 0x9cdfffff, 0xdcffff29, 0xe0437a94, 0x0cf42744, 0x0d00ffcd, 0xe44b9002, 0x00002305, 0xf84b66e6, 0xf4ff2305, 0xc9431a0f, + 0xabfb3171, 0x0500ff02, 0xffff8aa1, 0xff3333f8, 0xcecc0200, 0x4c2e0982, 0xff088bcd, 0x34b38d00, 0x337700ff, 0x11821532, 0xff685139, 0xfafef7ff, + 0xf5ffff05, 0xffffae47, 0xff0ad7f4, 0x48610000, 0x82eeffff, 0x0b00230e, 0x18820a27, 0x08ec5122, 0x67354a82, 0xfafffff0, 0x00fff0c7, 0xff060107, + 0x3068fdff, 0xf80600ff, 0x234f8352, 0x8b105807, 0x60261682, 0x0200ff42, 0x2a8200e0, 0x82527821, 0x00c02104, 0x45313582, 0x00ff289c, 0xffae8748, + 0x72fd1300, 0xdc0c00ff, 0x2329822a, 0x08f4682a, 0x30250682, 0xffff9a99, 0x280482d8, 0x66662700, 0x66cfffff, 0x844c8266, 0x83168506, 0x848b201b, + 0xff083317, 0x7819ffff, 0xa6dbffff, 0xffffa2aa, 0xff32b3e0, 0x37821f00, 0x99f2ff23, 0x2d63829a, 0xffcc4c22, 0x9a196900, 0x0d00ff15, 0x5882e23a, + 0x1ec50a22, 0x3a21b582, 0x223c82e0, 0x8220c5f2, 0x82ff206a, 0x21118206, 0x16843433, 0xf2ffff24, 0x6a83cccc, 0x16850683, 0x820a0021, 0x213e8211, + 0x2d823433, 0x820d0021, 0x20118328, 0x820485ff, 0x088b260e, 0xbffeffa3, 0x23628399, 0x071e0560, 0x0b276382, 0xffffa430, 0x82f027fa, 0x0a572623, + 0x76f6ffff, 0x21f282c8, 0xa9825ccf, 0x1078f622, 0xc72b0a82, 0xf4fffff0, 0x00fffa1e, 0x82306800, 0xec11211e, 0x22082d82, 0x6b08c0df, 0x68efffff, + 0xffff05f6, 0xff5c4ff0, 0x00e0f7ff, 0xe1f9ffff, 0xecffff48, 0x00ff5caf, 0x84b81e08, 0x22d38218, 0x82c2b505, 0xe4e5263f, 0x190b00ff, 0x05ff589a, + 0x990b0023, 0x28b5839a, 0x070a97d0, 0x4feeffff, 0x21de825c, 0x8582b0f1, 0x06500482, 0x4a3a1905, 0x06cb2617, 0xb01100ff, 0x20b582a4, 0x5075820e, + 0x16500a0f, 0x50ff2005, 0x5120067d, 0xee32a382, 0x088bcc4c, 0xed00ff0e, 0x01ff9a99, 0x1534b308, 0xed4a00ff, 0x1d714306, 0x820a1721, 0x4bf320d3, + 0xf98320fe, 0x3d2af328, 0xeef2ffff, 0xfe4bff14, 0xcecc2106, 0x7f206384, 0x211cfa4b, 0x5b444e02, 0x566e2108, 0x20075b44, 0x082e7c4c, 0x7186ab21, + 0x10220815, 0xd6821fc5, 0xe23a0f22, 0x2808ec47, 0xf70834b3, 0x00ff07c2, 0x472f8221, 0x002005cd, 0x230ff74b, 0x00ffc480, 0x2e07f74b, 0xffffa4b0, + 0xffe0faff, 0xcdcc0700, 0x830200ff, 0x1906279e, 0x0500ff9a, 0x83829a99, 0x0a827820, 0x10eeff21, 0x1a023b03, 0x02ffaf2b, 0xff989936, 0x9a99b600, + 0x066f7615, 0x00800c28, 0xc0ebffff, 0x0f858b00, 0x80f3ff29, 0xffff0800, 0x8268a656, 0x9a992704, 0xb6ffff05, 0xbe50b89e, 0x211b8306, 0x309500ff, + 0x40843682, 0x4c824682, 0x14822586, 0x2beb0822, 0x0c926318, 0xa430082e, 0xe1fcffff, 0x0800ffcc, 0x088b142e, 0x05820685, 0xff343328, 0x361e0300, + 0x631800ff, 0xf72308ad, 0x8254f754, 0x7a0c223a, 0x224d82e0, 0x188be891, 0x2e118cba, 0xff68e6a6, 0x33b33500, 0x00ff3b15, 0x82ffffbf, 0x19fb2bab, + 0x0b00ff9a, 0xffff6ee7, 0x62824cf4, 0x02c80722, 0x19219482, 0x21678299, 0x0682f3ff, 0x572b1682, 0xf8ffff0a, 0xfffffe37, 0x82ae07fb, 0x9218280e, + 0xffff3b08, 0x82010040, 0x33f9233c, 0x0763ffb6, 0xb3072b05, 0xedfffff8, 0x00ff3333, 0xae825010, 0xcd4cf922, 0x102ba882, 0xffff295c, 0xff2030f9, + 0x82b31200, 0xbf072119, 0x06229782, 0x2382aec7, 0x82524821, 0x2105221e, 0x21a78289, 0xb2825c4f, 0x15ae5a25, 0x8300ff06, 0xf3ff2310, 0x1082a4b0, + 0xe71b0522, 0xb8218782, 0x219b8252, 0x7f8238e9, 0x820a9721, 0xae87212a, 0x00239682, 0x82101804, 0x2c0432d9, 0x0000ff09, 0x00fffdc7, 0xffb40804, + 0x13b00100, 0x29578208, 0x00ff2b47, 0xff75b306, 0x70830700, 0xcdcc1225, 0x84f9ffff, 0x268f8394, 0x7bd47fff, 0x823300ff, 0x269082fd, 0x00ff85ab, + 0x82cccc2c, 0x8212206a, 0xd3ff220a, 0x24758230, 0xf6a8daff, 0x2b5b8206, 0x15900200, 0xabc200ff, 0xdb152b85, 0x2c229682, 0x1482281c, 0xd8e32327, + 0xde2300ff, 0x230a82b8, 0x08e23a2b, 0x17260682, 0xffff6626, 0xa382f8f5, 0x34b3142c, 0x3df0ffff, 0x0e00ff70, 0x8782b89e, 0x0a170622, 0x2124ae82, + 0x0300ff48, 0x00231982, 0x8266a60c, 0xa30d222e, 0x203583d6, 0x2316822c, 0x281cdcff, 0xff244c84, 0x3ecad4ff, 0xff27d482, 0xff9a19bf, 0x82feffff, + 0xeeff228f, 0x09184e54, 0x8ba4b02e, 0x35efffff, 0xffff08c4, 0x07ffff3f, 0xed220c82, 0x65822a6a, 0xffcc4c24, 0xe283f1ff, 0x34b3112c, 0xffab088b, + 0x70fdbf00, 0xab82ab15, 0xf8d30822, 0x07216a82, 0x2230822c, 0x82e0cff8, 0x30f7222f, 0x28758220, 0x2230f7ff, 0xd3f8ffff, 0x2b0482f8, 0xffffdecf, + 0x8b082cf7, 0xab066b08, 0xa0205183, 0xbb20ed82, 0x20203a9c, 0xe0203a88, 0x5b203a86, 0x0e2e3a82, 0xef01ffef, 0xf4f79a19, 0xcaffff15, 0x6b82b8de, + 0xda83cf20, 0x00c0e229, 0xd1ffff72, 0x8508b81e, 0x00ff2d06, 0xff00c002, 0x7c14c7ff, 0x801d00ff, 0xd3220982, 0x9d8266e6, 0x9a599022, 0x24347382, + 0x00ff48a1, 0xff48e136, 0xb89efaff, 0xeb4800ff, 0xd3ffff85, 0x00232e82, 0x82010031, 0x83d32024, 0xde302714, 0xb7ffffb8, 0x2143e2fa, 0xccc52106, + 0xe022fb82, 0x1e8248e1, 0xff2c0a87, 0xec51e2ff, 0x3dbdffff, 0x1000ff70, 0xbf208383, 0x9b241e82, 0x3900ff4b, 0xff205e82, 0xff286f82, 0x53f84100, + 0xf4f7088b, 0x4f217282, 0x253f828c, 0xff7a14ff, 0x8d824000, 0x8b260483, 0x804f00ff, 0x06850800, 0xbfffff22, 0xff2e1686, 0x9a99afff, 0xfeff088b, + 0xfbd6e350, 0x1e821524, 0x821e2c21, 0x822320a3, 0x840020ad, 0x1e2c2204, 0x201e82b9, 0x20068300, 0x201182ff, 0xe2491947, 0x82d3200e, 0xdcff2128, + 0xff233282, 0x821e05dd, 0x48e121d6, 0xff202d82, 0x8b201582, 0xae202884, 0x2606f878, 0x1caf01ff, 0x82153b2a, 0xb8de2120, 0xbf821983, 0x48204c82, + 0x2b221d82, 0x94835238, 0x5e830682, 0x00ff4826, 0xffaec724, 0xb8206e82, 0xb6207585, 0x87832282, 0x38826383, 0x2d825882, 0x68215f83, 0x2f7186ff, + 0x088b0200, 0x01ffef0e, 0xff9a19e9, 0x9a19b700, 0xf72b6482, 0x00ff6666, 0x6d666639, 0x82af00ff, 0xc5ff26e7, 0x088bcccc, 0x363e827d, 0xff866bf3, + 0x0020faff, 0x7ff5ffff, 0xf7fffffe, 0xff0800e0, 0x8240ebff, 0x82f0200f, 0xe3ff2291, 0x21918221, 0xcd82ebff, 0xde0f0023, 0x2e1a82b8, 0x93e47af5, + 0x80f3ffff, 0xffff9100, 0x82fffff1, 0xc5ff2392, 0x488200c0, 0xe1fae125, 0x8350ffff, 0x83f6205b, 0x99c62804, 0x00ff089a, 0x821fc526, 0x6666222c, + 0x825e82c2, 0x4b002315, 0x31826766, 0x66200682, 0x3820c482, 0x07b14618, 0xe6250022, 0x0c209d82, 0x8f273184, 0x00ffcecc, 0x82333325, 0xe0f925b3, + 0x0400ff00, 0xf7279a83, 0xffffccec, 0x828f62ff, 0x008024a9, 0x828a0886, 0x2016830c, 0x2840829b, 0xe21aa6ff, 0x3340ffff, 0x23578232, 0x9a1941ff, + 0x9a2d8982, 0x00ff32b3, 0x8a70fd59, 0xde0000ff, 0x20b382b9, 0x207a83fa, 0x234d8204, 0x3dcaf7ff, 0xa2211482, 0x2048820c, 0x20e28200, 0x83ed84fb, + 0x82ff2067, 0xffff290a, 0xffba89fd, 0x293cf8ff, 0x4c055e58, 0x0023055c, 0x8261a500, 0xacfc2919, 0x9e4c00ff, 0x38fffffa, 0xf0224c83, 0x6f82e2ba, + 0x06830020, 0x4d00ff27, 0x00ff5478, 0x241682c7, 0x64e6ffff, 0x25f5828d, 0xffcc4c04, 0xd3820600, 0x82fdff21, 0x07002115, 0xf922a683, 0xcc8268e6, + 0x0833332b, 0x01ffef0e, 0xf7cccc04, 0x25e18250, 0xffce4ce3, 0x28831600, 0x33b3de2c, 0x190c00ff, 0xddffff9a, 0x5a829999, 0x9eb2ff23, 0x26ca82b8, + 0xffe17abe, 0x8240c1ff, 0x83eb20aa, 0xc0a22225, 0x20ce8200, 0x275482fc, 0x4861efff, 0x200300ff, 0xee271982, 0xff9470bd, 0x8280f2ff, 0x0800221a, + 0x211082c0, 0x1a82e1f2, 0x48210d22, 0x2982ca82, 0x000e0030, 0xff088b00, 0x54182202, 0x98ffff06, 0x5682cccc, 0x3433cc25, 0x832500ff, 0xccb12821, + 0x4300ffcc, 0x8208b85e, 0x805426f3, 0x00ff0500, 0x23ad82ea, 0x33331200, 0xe4289e82, 0x00ffb8de, 0x0501809c, 0x2020ff82, 0x2007ac6a, 0x200983f6, + 0x2192830f, 0x6782a1f1, 0x92840920, 0xff220a87, 0x5582eeff, 0x8c030034, 0xffff7acc, 0x080060fc, 0xe340ffff, 0xd7ffffd6, 0x4482e25a, 0xcdcce425, + 0x84faffff, 0x260983cd, 0x885278e9, 0x83e4ffff, 0xf9ff21b8, 0xbe22fa83, 0x8082cccc, 0x82e00621, 0x8300206a, 0xbe062104, 0x01207f82, 0x07226f83, + 0xc3824821, 0xde290027, 0x00ff8bb8, 0x21628228, 0xda83f1ff, 0x66662334, 0x9ee3ffff, 0xffed08b8, 0x48a1abff, 0xffffd205, 0x3d82c0c2, 0x4d832c20, + 0x2183dc20, 0x9a196122, 0x977a3883, 0x18002009, 0x23092f43, 0x0c0000ff, 0x1920fd82, 0xe2394483, 0xffe96866, 0x98198dff, 0xcc0700ff, 0xfb0e08cd, + 0x15eb8b30, 0xa7ffff8b, 0x2082829e, 0x22e88247, 0x8261b8ff, 0x5e582bed, 0xcb088bb9, 0x5800ff06, 0x89824861, 0x1d864720, 0x58330a82, 0xf708b85e, + 0x14fc0714, 0x0714fb06, 0xf4f744f7, 0x82067b15, 0x47a1213e, 0xb8234482, 0x83ffb85e, 0x214f853f, 0x1f826b08, 0x54f70625, 0x828bbb07, 0x54fb2123, + 0xab210d83, 0x82428307, 0xb8ff2161, 0x00208d82, 0xff205783, 0x07f67e18, 0x19bf3008, 0x15d4f79a, 0x661bffff, 0xff058b66, 0x34331401, 0xf85000ff, + 0x00ff0552, 0xff52b80c, 0xe8bb0300, 0x610600ff, 0x0d00ff46, 0xffff7453, 0x84162efd, 0xff082518, 0xf047fcff, 0xb3260a82, 0xf3ffff34, 0x2382769e, + 0xff235982, 0x83ec51f2, 0x14250823, 0x52feff08, 0xffffcc8c, 0x05ec1182, 0xeee2ffff, 0xf7ffff14, 0xffffee7c, 0xff1f85eb, 0x44b6e5ff, 0x28feffff, + 0x211882f6, 0x48822005, 0x82a4ff21, 0xaeff2223, 0x22058214, 0x8266e600, 0xdcff26aa, 0x00ffa4b0, 0x2c04821c, 0xc235e4ff, 0x682200ff, 0xff088bf6, + 0x05fc5901, 0x5c4f2322, 0x1b22cc82, 0x21843eca, 0x1d820a82, 0x00ff082f, 0x079a19ff, 0xcc0100ff, 0x2300ff9e, 0x2279824c, 0x823233e4, 0x689d8320, + 0xfe26053e, 0xfb66e690, 0x2f82150c, 0x82670421, 0x98032cb7, 0x0200ff11, 0x00ffaab1, 0x82898103, 0x6f00265c, 0xff069a19, 0x821b8200, 0x24178321, + 0xf067fcff, 0x21e4828b, 0xa182767e, 0x9685f020, 0x1098fb22, 0x3e821182, 0x4efdff23, 0x821b8456, 0x82ff2039, 0xff062258, 0x821b82ff, 0x2317832e, + 0x10980300, 0x03224482, 0x96828a81, 0x96820f20, 0xfd82f720, 0x66e67022, 0x25837b82, 0xb5b941b3, 0x99cb9b21, 0x95f28476, 0x079b21b8, 0x8f207298, + 0x2a192841, 0x00ff077b, 0x8bcccc01, 0x8200ff15, 0x15432f25, 0xd7d3ffff, 0xffff8b0a, 0xfff628dc, 0x0a832300, 0x422b0024, 0x5a820890, 0x11840682, + 0x2400ff2b, 0x00ff70bd, 0x8bf6282c, 0x24068508, 0xf02200ff, 0x213282a4, 0x38826626, 0x9ad9d322, 0xff202d82, 0x69310682, 0x0cddffff, 0xd2ffffcc, + 0x088b66e6, 0xf794f70e, 0x205d82b4, 0x240c82ca, 0x19d5ffff, 0x8204849a, 0x8310822f, 0x2406822f, 0xeb2a00ff, 0x24168485, 0x143500ff, 0x225d837b, + 0x827c1435, 0xeb2a2279, 0x201b8384, 0x820a8284, 0x822d8210, 0x867c201e, 0x201b8328, 0x573c82ff, 0x98790519, 0xff34251b, 0x7b540e00, 0x4c220482, + 0x6b74ffcc, 0x82862009, 0x065c5654, 0x8d828520, 0x7b54ee22, 0xff215f82, 0x123379ee, 0xbf848b20, 0x9a997222, 0x8d242682, 0xffff6666, 0x0a820482, + 0x31831082, 0xff210682, 0x83048300, 0x00ff2116, 0x08201b83, 0x16850685, 0x6a821b83, 0xf5191782, 0x8b2817b0, 0xff1514fc, 0x0040b9ff, 0xc6215482, + 0xef4218c0, 0x2038820c, 0x23118646, 0x403900ff, 0x0e821b82, 0x5f828b20, 0x091d4318, 0x3282ff20, 0x3e823882, 0x45835f82, 0xc6ffff24, 0x0482cccc, + 0xff303782, 0x8b3433b9, 0x30fb0e08, 0xf4f7f4f7, 0x9b066b15, 0x0a615f18, 0x5f18cc20, 0x22820861, 0x0f675618, 0x08316018, 0x8d077b21, 0x975f1835, + 0x2035850c, 0x257d8233, 0xffcdccf8, 0x358af8ff, 0xff065b26, 0x66e64800, 0x0c266f83, 0xffff2a5c, 0x39824cf5, 0x70bd0a23, 0xb38a18ff, 0xf5ff2311, + 0x42829042, 0xd6a3f328, 0xb7ffff08, 0x71829a19, 0xeeffff24, 0x13826666, 0x9a99f124, 0x0482ffff, 0x10820a82, 0x4d221e82, 0x5282cc4c, 0x84f7ff3f, + 0x0300ff18, 0xffff7d5f, 0xff30ddf7, 0x7dff0500, 0x00ff0885, 0xff06a116, 0xec51e9ff, 0x053c6b05, 0x0080e522, 0x8307bb65, 0x821a2609, 0xf7088b8f, + 0x18bb6374, 0x83070421, 0x84482041, 0x82052004, 0x52f82153, 0x03280486, 0x00ff6666, 0x8b323308, 0x80210582, 0x22678200, 0x8234b3b2, 0x11002184, + 0xff229c86, 0x21820e00, 0x0824b184, 0x156cfb4b, 0xfb20ac82, 0xfc201a83, 0x04841583, 0x8b230e82, 0x1844fb08, 0x210e3185, 0x51829a99, 0x66660424, + 0x4d839b08, 0xd2820882, 0x7f82a120, 0x21056b63, 0xad82b95e, 0x00203282, 0x27821882, 0xff201483, 0x5c854c82, 0x077b0823, 0x052b448b, 0x21ca6840, + 0xb176ef0e, 0x6658261f, 0x00ff8b66, 0x20f38347, 0x280a83b8, 0x9a99a7ff, 0x0734fb08, 0x0ecd76ab, 0x7812407e, 0xfb3f0c20, 0x568b06d4, 0x8b566060, + 0xcaffff08, 0xff8b9a19, 0x66e6d5ff, 0x08c08bb6, 0xffff067b, 0x82ebd1d3, 0x2edc2510, 0x2300ff14, 0x084c6218, 0x0774f72c, 0x84fbd4f7, 0x0614f715, + 0x2c4307eb, 0x0700230d, 0x95823333, 0xcdcc0823, 0x20068508, 0x201182ff, 0x23048334, 0x0800ff33, 0x08234182, 0x61cb06ab, 0xb32009ff, 0x20069d74, + 0xaa4218ff, 0x0b9d6008, 0xfb26b988, 0x74fb0754, 0x437974f7, 0x7dff200c, 0x4b2009f8, 0x41825082, 0x4f18cd20, 0x6b82085b, 0x85ab1124, 0xa082088b, + 0x5f00ff21, 0xcd200c2a, 0x10829582, 0x82062864, 0x7546827e, 0x418306e0, 0xfb088b22, 0xfb21d382, 0x044c18e4, 0x0a18490c, 0x1a223d82, 0xcc660080, + 0x18098307, 0x2110b043, 0xfd18eaff, 0x3f830f56, 0x3c823286, 0x0e088b2f, 0xf81494f8, 0x010015b0, 0x00000080, 0x820382c0, 0x82012007, 0x40012207, + 0x84138400, 0x830f870b, 0x82002013, 0x87078317, 0x8b0b871f, 0x83438707, 0x21178207, 0x33820002, 0x01200b86, 0x0b870783, 0x5f841b82, 0x47870f8b, + 0x8b8b7383, 0x1b830f83, 0x07863f87, 0x138e0220, 0x00820020, 0x03870220, 0x1f831b82, 0x33820f88, 0x03830220, 0x00221783, 0x1b840000, 0x1b870f87, + 0x438b0787, 0x7786378b, 0x07820120, 0x6b8a0220, 0x9f820120, 0x478b5b84, 0x0f861f83, 0x23841f83, 0x57419386, 0x06334110, 0x5f410220, 0x225b9006, + 0x84000000, 0x201f863f, 0x832f8201, 0x200784db, 0x87cb8500, 0x07bb410b, 0x02201f83, 0x27411b87, 0x8701200e, 0x8a9f8b97, 0x82df8c13, 0x82db843b, + 0x411784ef, 0x938b0a57, 0x17870220, 0x8707c341, 0x0f2741a3, 0x02200f8a, 0x8a072341, 0x10474163, 0x8a0fa341, 0x86738467, 0x0ce741b7, 0x01235786, + 0x840000c0, 0x41338317, 0x0b86073b, 0x41080b42, 0x1f820ffb, 0x93873784, 0x93861f93, 0xef410120, 0x866f880e, 0x8493837f, 0x844b8623, 0x203b861f, + 0x86c78f02, 0x82178423, 0x84378323, 0x8600203b, 0x948792c3, 0x41df9f43, 0x57920f4f, 0xc3410120, 0x08634206, 0x200af341, 0x209b8602, 0x065b4202, + 0x860c7741, 0x833f834b, 0x411b9027, 0x0b8f0b53, 0x200e6f41, 0x06534301, 0x41086341, 0x3341132f, 0x422f880a, 0xab8c129f, 0x420eb341, 0xd787106f, + 0x2b416f93, 0x410f930f, 0x374407fb, 0x0fd74312, 0x8b080744, 0x4277872b, 0x27450f27, 0x08f34106, 0x840a6342, 0x938b9357, 0x83df8713, 0x4443861b, + 0x8b430c33, 0x0cd3420e, 0x82078b42, 0x84179323, 0x077f42cf, 0x7f412b8a, 0x861f8f0c, 0x844f8b8f, 0x07ff418f, 0x4406c343, 0x0f82086b, 0xbb870120, + 0x73843b82, 0x13840f82, 0x57419786, 0x822b8308, 0x86022003, 0x8643848b, 0x075b437f, 0x1b864b8c, 0x2f820220, 0xb3460120, 0x830f830a, 0x43978703, + 0x2782081f, 0x07931b87, 0x9f878788, 0x978eaf87, 0x13825b84, 0x7b410220, 0x0e63410b, 0x17414b88, 0x822b8406, 0x2007834f, 0x42879301, 0x1f820b53, + 0x0f820120, 0x4b410120, 0x86022006, 0x860120e7, 0x072f410f, 0x738e0220, 0x0120d38b, 0xf393b392, 0x8b10f343, 0x97ff8e77, 0x08cf428f, 0x220b5748, + 0x87000000, 0x077f41e7, 0xa38c0783, 0x02206b82, 0x03843382, 0x4b88f386, 0x01201b82, 0x1b88c382, 0x430fb347, 0x6b410a4f, 0x830b840b, 0x8303833b, + 0x47578653, 0x47820843, 0x88075b41, 0x0f8f41cf, 0x2012cb43, 0x87a78202, 0x07bb442f, 0x4b820020, 0x200f5341, 0x07c74101, 0x8f063b41, 0x8e0f881f, + 0x4100204f, 0xc78c0eef, 0x4f426782, 0x42022007, 0xf7880a0b, 0x4907fb42, 0x67830a77, 0x97460120, 0x87738b06, 0x0c87413f, 0x4306b741, 0x5b430c37, + 0x8a17880a, 0x420120ef, 0x012006fb, 0xf78b1387, 0x63888f86, 0xf7864b8b, 0xa786df8c, 0x078baf87, 0x13444388, 0x4273870a, 0x012017e3, 0x860b2b45, + 0x44a78897, 0x9b870fbf, 0x8412c745, 0x8b178733, 0x825f8737, 0x084b421b, 0x4f461387, 0x420f820f, 0x2382087b, 0xcb469b8b, 0x87c78807, 0x0f9b496b, + 0x880a0346, 0x133341c7, 0x820f8f42, 0x0c9f4147, 0x2f439b86, 0x4102200f, 0xf7410bff, 0x863f840e, 0x480b8b13, 0x8782082f, 0xe3820220, 0xc3420384, + 0x87138b07, 0x4c13833b, 0x1f86137f, 0xa3413f83, 0x123f430c, 0x920c7f43, 0x8f83841f, 0x200f8abf, 0x06574101, 0x84077b42, 0x0ffb4373, 0x8b8c0f86, + 0x830f8b44, 0x2003820f, 0x424f8202, 0x1b4314b3, 0x0a074107, 0x8f0ce341, 0x43278a73, 0xc0200c83, 0x8405474c, 0x42538363, 0x02200a4b, 0xd3410b87, + 0x41378706, 0x378b108b, 0x01200b82, 0x4a0e7b47, 0x6f450cbf, 0x8717840a, 0x43378b5b, 0xff41064f, 0x838b8f14, 0x4113872b, 0x5b840a0b, 0x4c068b41, + 0x2f8b0c13, 0x83411f82, 0x8347830c, 0x0f774a03, 0x8b0b8744, 0x8f0b879b, 0x8217877f, 0x8f5f8407, 0x0f0744cf, 0x0f41478b, 0x43ff830a, 0x0f8b0f47, + 0xb387e388, 0x460f3f44, 0xbb4c0663, 0x0eff430c, 0x410cef42, 0xa74b0683, 0x8701200f, 0x0f7b4193, 0x42061741, 0x97450c17, 0x8493820f, 0x4e8b86b3, + 0x7b840b37, 0x9f884382, 0x87077f41, 0x07ab4107, 0x820b9741, 0x0b5f420b, 0x0f8a0220, 0x2f430120, 0x0ca7430a, 0x2782a783, 0x0faba78c, 0xd387878f, + 0x0b8b578b, 0x7b8c2f92, 0x0220a786, 0x01209792, 0x01203b8a, 0x420f6b45, 0x178c0627, 0x8f0f8342, 0x0fe34253, 0x860b7b42, 0x076742c7, 0x0f4f0220, + 0x4a078406, 0xbf900e17, 0x438ac387, 0xc3872388, 0x8a1f0741, 0x081f4e8b, 0xef4b5786, 0x088f420b, 0x01201b82, 0x02200382, 0x970fbb41, 0x475f87f3, + 0x538c122f, 0xa342eb82, 0x415f8208, 0x438b0c5f, 0x0b87478b, 0xc7427b87, 0x410b8b0b, 0x87430a9f, 0x20c3860c, 0x836f8601, 0x07274507, 0xe349df83, + 0x887f8608, 0x43838e1f, 0x57420c43, 0x840b820b, 0x0f2f411b, 0x1782cf97, 0xbb44f78f, 0x42b78714, 0x3b8b0b1f, 0x83060f41, 0x864f8c3b, 0x44022037, + 0x1b410b33, 0x82f3840a, 0x13ef4a53, 0x37831b83, 0xdb8a4f90, 0x88071344, 0x87678b23, 0x842f827b, 0x0a574327, 0x5b900f83, 0x17843b82, 0x840a6742, + 0x83db8a0f, 0x42038433, 0x234113ff, 0x4201200e, 0x5f4c075f, 0x86138c0a, 0x8b022057, 0x0e1b4137, 0x27846f8b, 0x830fa346, 0x863f872f, 0x0100213b, + 0x0a2e1082, 0x2c001e00, 0x616c0100, 0x08006e74, 0x11820400, 0xffff0024, 0x07820100, 0x696c0124, 0x13826167, 0x0d850020, 0x07201b82, 0x00231583, + 0x82010008, 0x8300200b, 0xc8430907, 0x001a00a8, 0x1e1c103a, 0x3a663438, 0x4dfa3e08, 0x646c53ae, 0x678e66ae, 0x6e36684c, 0x7bbc7ade, 0x8d167c8a, + 0x94ea8ede, 0xba76aaec, 0xc4dac0d8, 0xc8f6c74a, 0x009cc868, 0x01f6007a, 0x0176013e, 0x02e201ac, 0x024a0216, 0x02b2027e, 0x031603e4, 0x03760348, + 0x03d203a4, 0x042a04fe, 0x04820456, 0x05da04ae, 0x05320506, 0x0584055c, 0x05d405ac, 0x062406fc, 0x0674064c, 0x06c4069c, 0x071207ec, 0x075e0738, + 0x07aa0784, 0x08f207ce, 0x083a0816, 0x0882085e, 0x08ca08a6, 0x091209ee, 0x09580936, 0x099c097a, 0x0ae009be, 0x0a200a00, 0x0a600a40, 0x0a9e0a80, + 0x0ada0abc, 0x0b160bf8, 0x0b500b34, 0x0b880b6c, 0x0bc00ba4, 0x0cf80bdc, 0x0c2e0c14, 0x0c620c48, 0x0c960c7c, 0x0cca0cb0, 0x0dfe0ce4, 0x0d320d18, + 0x0d620d4a, 0x0d920d7a, 0x0dc20daa, 0x0ef20dda, 0x0e1e0e08, 0x0e4a0e34, 0x0e760e60, 0x0ea20e8c, 0x0eca0eb6, 0x0ff20ede, 0x0f160f04, 0x0f3a0f28, + 0x0f5c0f4c, 0x0f7a0f6c, 0x0f960f88, 0x0fae0fa2, 0x0fc40fba, 0x0fd60fce, 0x002303dc, 0x00240023, 0x0029001c, 0x001a0020, 0x00250018, 0x822a0008, + 0x841e200b, 0x84232009, 0x001e2211, 0x2007822c, 0x2025821e, 0x22198208, 0x842b0025, 0x8227202f, 0x821c2033, 0x8220200b, 0x031e2429, 0x821b0022, + 0x20398337, 0x2013842a, 0x202d842d, 0x832f8223, 0x821c200f, 0x84278423, 0x8230205d, 0x20438329, 0x20078224, 0x207582ab, 0x22498229, 0x822e0026, + 0x002c221b, 0x20058227, 0x200f841d, 0x20098224, 0x2009841e, 0x203d822c, 0x200d821b, 0x8485822e, 0xfa01217b, 0xc1833592, 0x1f001e22, 0x08217d82, + 0x22418900, 0x8428002a, 0x002926bd, 0x00c1011c, 0x214f8219, 0x6b830029, 0x6d882a20, 0x0f841b20, 0x0f822520, 0xb3822320, 0x3f841d20, 0xb0204b89, + 0x2393338e, 0x33820820, 0x3f842620, 0x25002022, 0xa5204382, 0x25203382, 0x1f20a182, 0x29205982, 0x1a221782, 0x77822000, 0x83001a21, 0x8208203b, + 0x822f201f, 0x8223201b, 0x822420cb, 0x822b2003, 0x8226201b, 0x8aa82035, 0x00082167, 0x11419389, 0x84182005, 0x002622ef, 0x2001822a, 0x84478208, + 0xf8012167, 0x3b413f82, 0x8bb38909, 0x83f183ff, 0x8222203d, 0x002b2277, 0x20318ab2, 0x2299822a, 0x8427002a, 0x412b204d, 0x1820080d, 0x1b208b82, + 0x200a0b41, 0x41638cac, 0x91410f9f, 0x2a318208, 0x002c0027, 0x03270024, 0x41160056, 0x08200865, 0x23213d82, 0x415d8300, 0xab880d03, 0x8cfb0121, + 0x8217882d, 0x002b224f, 0x8c058226, 0x370221bf, 0x18202d98, 0x2320738a, 0x1d26eb82, 0x54032b00, 0x89a01500, 0x21066941, 0x2b8c8e02, 0x24097f41, + 0x0020002e, 0x234f821b, 0x002a0008, 0x2205cf41, 0x8aaf002b, 0x822a202b, 0x852d89a3, 0x822720b3, 0x0026282f, 0x00230027, 0x8c29041c, 0x15a34157, + 0x63821d20, 0x02212b82, 0x242b8e30, 0x002b0026, 0x20038218, 0x2063821c, 0x24098219, 0x0022001a, 0x2407822e, 0x051b0029, 0x892b8c64, 0x20a58981, + 0x262b8208, 0x001b0020, 0x8c55031c, 0x8218202b, 0x11914197, 0x33412320, 0x5c002105, 0xef412b8c, 0x0c8d410f, 0x009e0123, 0x0a5f4114, 0x8b002921, + 0x821d20af, 0x8729200d, 0x8f0223ad, 0x298a1300, 0x59415585, 0x92ad2013, 0x0b334127, 0x2b24e783, 0xaa002a00, 0x3542278c, 0x001a2811, 0x002b0020, + 0x9e2a0430, 0x06794127, 0x8aae0021, 0x13d14127, 0x4f822320, 0x1c002524, 0x4f8c5703, 0x83154941, 0x8eb720dd, 0x002b224f, 0x20ff822c, 0x08d54225, + 0x0521c786, 0x414f8c65, 0xc1410517, 0xa4002112, 0x51442782, 0x001a2a19, 0x001c001f, 0x0022001a, 0x24279ca6, 0x0024002f, 0x24878218, 0x009e0122, + 0x0cb94112, 0x1e002022, 0x2b204382, 0xc5419f82, 0x8ca9200b, 0x0f934425, 0x26002322, 0x4b907383, 0x410b0542, 0x02210899, 0x444b8c0c, 0x0221160d, + 0x22258247, 0x451e0025, 0x71830629, 0x19002c22, 0x4b890d86, 0x11003022, 0x2743bd8c, 0x0e022112, 0x6f8d238c, 0xb820c987, 0x0f46238a, 0x05c34309, + 0x2106f141, 0x23824602, 0x33439197, 0x0b022106, 0x23876b9a, 0x479a4920, 0x03218f86, 0x2823821f, 0x001b002c, 0x00260020, 0x24078208, 0x002a001c, + 0x24e9821a, 0x00270020, 0x2115842b, 0xfb9b0225, 0x238d6b87, 0x410bb146, 0xb6200929, 0xa142fb8e, 0x08674109, 0x8ef10121, 0x12fb4623, 0x00970223, + 0x0c8b4110, 0x20094942, 0x24c58223, 0x011e0025, 0x92218cda, 0x23032167, 0x2a222182, 0xf3822300, 0x48002021, 0x0021145d, 0x22438e5a, 0x461c0029, + 0x3b4106a7, 0xb3002106, 0x2a20218a, 0x41086743, 0x02230af7, 0x8a0f007b, 0x208789a9, 0x05ff471b, 0x8c0d0221, 0x0d31421f, 0x27002c24, 0x1f8c9402, + 0x86090d43, 0x960221e7, 0x2b411f8c, 0x201f8709, 0x421f8248, 0x5f831749, 0x0e009022, 0x5f899f8a, 0xcd820a20, 0x8c021222, 0x18201d96, 0x31221d82, + 0x1d966205, 0x1d823120, 0xf0011822, 0xf7481d8a, 0x66052110, 0x12203b96, 0x0a223b82, 0x1d8c5b00, 0xa1822b20, 0x2b077941, 0x0127002c, 0x000d00b7, + 0x00200023, 0x23052d4a, 0x002c0021, 0x2405fd49, 0x0130001d, 0x481b829f, 0x7583079d, 0x200b5944, 0x431b8eb4, 0xf3830573, 0x7f042b22, 0x20201b82, + 0xc5486782, 0x821c2005, 0x001f2451, 0x8225001c, 0x02292203, 0x24378afb, 0x00270008, 0x0a8f4a26, 0x5394b520, 0x30001c26, 0x95021c00, 0xb982378c, + 0x9741db82, 0x8c7a2007, 0x0917421b, 0x03232582, 0x4a0c0053, 0x18200c31, 0x22063b47, 0x82b5012d, 0x20f98919, 0x229d821a, 0x822b0025, 0x03292205, + 0x22339652, 0x822b031f, 0x001b2219, 0x8351821b, 0x822a20d5, 0x001a2283, 0x220d8218, 0x8a91021b, 0x00082133, 0x0a209f85, 0x12221f82, 0x19926705, + 0x19821220, 0x47020a22, 0x4f421982, 0x434b8307, 0x032108b7, 0x2267902a, 0x82260019, 0x02222201, 0x204d928d, 0x224d8218, 0x825d0031, 0x002c2219, + 0x20c3822a, 0x20938229, 0x4c138223, 0x05210605, 0x42339263, 0xb6220557, 0xfd410b00, 0x217f880a, 0x17824902, 0xcb42998b, 0x46022106, 0x2343178e, + 0x4b022106, 0x0821178a, 0x21478800, 0x1782d701, 0x2013df4a, 0x83178ab1, 0x002a28f9, 0x00200027, 0x84a70025, 0x001a2247, 0x20eb821f, 0x46c18229, + 0x042106a1, 0x20178280, 0x4b238227, 0x2e20057f, 0x0b821f84, 0x004d0224, 0x9143000a, 0x002e240d, 0x82140225, 0x0bb74215, 0xe3821820, 0xb4012b22, + 0xef411582, 0x21b98609, 0x2b8ad601, 0x27820820, 0x1d001c26, 0xae022b00, 0x2c221582, 0x85822b00, 0x03822420, 0x9b821920, 0x1c002324, 0x6d8c4a02, + 0x02214186, 0x224184d2, 0x8218001c, 0x821a20af, 0x82182099, 0x012b22ff, 0x20578cd9, 0x05a1441b, 0x00880323, 0x83638209, 0x00292239, 0x2455821e, + 0x022a001c, 0x41138248, 0x2c240b6b, 0x40022700, 0x24241382, 0x2c001900, 0x18202d82, 0x1a24e182, 0x80041c00, 0x03411382, 0x20d38509, 0x4d7382d8, + 0x06200d7b, 0xaf4d1182, 0x82292005, 0x002a245f, 0x8af00122, 0x822a2023, 0x022d220b, 0x4105824c, 0x6f820935, 0x8ef10121, 0x041f2423, 0x82070012, + 0x20cf83c7, 0x22d9822e, 0x889c0230, 0x0020280f, 0x021c002d, 0x84060071, 0x821f2097, 0x012922d9, 0x2a0d82be, 0x0021001b, 0x002a002c, 0x82c1012b, + 0x087f410d, 0x00140424, 0xf34a0005, 0x13042106, 0x2b200b82, 0x2a22d384, 0x0b821104, 0x1e002522, 0x30246582, 0x0400a004, 0x22244d82, 0x81041f00, + 0x77410982, 0x00072405, 0x821b0003, 0x00172601, 0x042b0002, 0x0905829f, 0x92001b30, 0x5e012601, 0xca019601, 0x2402f801, 0x78025002, 0xc802a002, + 0x1803f002, 0x62033e03, 0xa8038603, 0xea03ca03, 0x2a040a04, 0x6a044a04, 0xaa048a04, 0xe604c804, 0x22050405, 0x5e054005, 0x96057a05, 0xce05b205, + 0x0606ea05, 0x3e062206, 0x76065a06, 0xae069206, 0xe606ca06, 0x1e070207, 0x52073807, 0x86076c07, 0xba07a007, 0xee07d407, 0x22080808, 0x54083c08, + 0x84086c08, 0xb4089c08, 0xe408cc08, 0x1409fc08, 0x40092a09, 0x6c095609, 0x98098209, 0xc409ae09, 0xf009da09, 0x1c0a060a, 0x440a300a, 0x6c0a580a, + 0x940a800a, 0xbc0aa80a, 0xe40ad00a, 0x0c0bf80a, 0x340b200b, 0x5c0b480b, 0x840b700b, 0xaa0b980b, 0xce0bbc0b, 0xf20be00b, 0x160c040c, 0x3a0c280c, + 0x5a0c4a0c, 0x7a0c6a0c, 0x9a0c8a0c, 0xba0caa0c, 0xd60cc80c, 0xf20ce40c, 0x0a0dfe0c, 0x220d160d, 0x3a0d2e0d, 0x520d460d, 0x680d5e0d, 0x7c0d720d, + 0x900d860d, 0xa40d9a0d, 0xb80dae0d, 0xcc0dc20d, 0xe00dd60d, 0xf40dea0d, 0x040efc0d, 0x140e0c0e, 0x1b00c800, 0x20002c00, 0x07822300, 0x25002024, + 0xc14e1e00, 0xa0c62026, 0x0ba34d37, 0x2408e543, 0x1900c000, 0x200d8300, 0x2069821b, 0x276ba51c, 0x1600f702, 0x2b001800, 0x1c200182, 0x30203b82, + 0x2b223582, 0x09821f00, 0x83001c21, 0x82282041, 0x206b83bf, 0x260d822b, 0x002a0029, 0x9e1500c9, 0x08194bd1, 0xa0c70021, 0x086d4b2b, 0x00d50323, + 0x20858213, 0x22038223, 0x841a0025, 0x822a2079, 0x4a182007, 0x00210faf, 0x20278299, 0x22258229, 0x82200031, 0x8220201b, 0x82252009, 0x822920b1, + 0x202b8331, 0x086f5108, 0x2784c120, 0x41002021, 0xa3881509, 0x82b00421, 0x00262427, 0x82220026, 0x82212045, 0x002c2407, 0x82250029, 0x82232055, + 0x002e220f, 0x2065841f, 0x20558223, 0x894f9cbf, 0x00d422c7, 0x44c79a12, 0x032306a9, 0x82110074, 0x822a2025, 0x841920b5, 0x836d832d, 0x822b2009, + 0x21118675, 0x23828c03, 0x20002922, 0x1d222382, 0x2d861a00, 0x24000822, 0x1b200f82, 0x11831582, 0xa4022324, 0x8d411000, 0x00262212, 0x26158223, + 0x00250024, 0x8283042a, 0x22df8721, 0x82270026, 0x092f413d, 0x0d821b20, 0xf9022924, 0xff410f00, 0x0cf3410e, 0x841c0321, 0x002a221f, 0x832d8222, + 0x002a239f, 0x4983001f, 0x22052746, 0x8c76031e, 0x24cf8d1f, 0x05230023, 0x231f825a, 0x00290026, 0xdf826d84, 0x3d842b20, 0x2108e145, 0x1f82cd00, + 0x830f2343, 0x82202063, 0x0023246f, 0x82a2041b, 0x1107411f, 0xe3821a20, 0x1a002626, 0xd8032200, 0x26201f84, 0x1b20c382, 0x83062741, 0x206583a5, + 0x2441822e, 0x00ba0029, 0x2271820e, 0x4d2b002b, 0x29200809, 0x23208184, 0x2b221d82, 0x1d820b04, 0x9d821820, 0x2005fb46, 0x2245822b, 0x841e001e, + 0x821c2037, 0x821d207b, 0x821c201d, 0x82232037, 0x821a20b7, 0x82252035, 0x20978361, 0x20238429, 0x8f1d82d0, 0x002e24b9, 0x821c001f, 0x002b2245, + 0x51778460, 0x232205b1, 0x31822000, 0x83821f20, 0x09822520, 0x1e002524, 0x59844302, 0x79821c20, 0x24000824, 0x1d822c00, 0x37820820, 0x2700242a, + 0x30002b00, 0x0d00c301, 0x820da350, 0x821d207f, 0x822a2011, 0x82cf201d, 0x22758f1b, 0x822a002c, 0x0429223d, 0x831b82cc, 0x412520d7, 0x2722086d, + 0xb7841f00, 0x8b031c22, 0x26221b82, 0x27822f00, 0x1a22eb89, 0x0f822200, 0x52051b22, 0x29206f84, 0x08204582, 0x29208182, 0x1e223182, 0x29842900, + 0x75032a22, 0xab421b84, 0x00232411, 0x84610023, 0x053d4353, 0x82061749, 0x821820cd, 0x0322223b, 0x43378401, 0x022114d1, 0x201b82d1, 0x20258220, + 0x209d822b, 0x20d7821b, 0x20df8230, 0x8307821a, 0x8cbd208d, 0x412720a7, 0x20260607, 0x1e002500, 0xfb92ca00, 0x87821d20, 0x1b821820, 0x1b92cb20, + 0x2106b548, 0x8b84fa02, 0x200be344, 0x26a7821c, 0x002b0027, 0x84a20430, 0x002a2137, 0x1c226183, 0x01822a00, 0x17820820, 0x1f822020, 0x0d051c22, + 0x19213784, 0x209f8700, 0x20b38229, 0x24918220, 0x011c001e, 0x12a341c2, 0x2405ef47, 0x00c30027, 0x0c87450c, 0x2108db53, 0x1982f602, 0x220d6d45, + 0x822c001d, 0x052322c1, 0x4319825a, 0x4b830b27, 0x19823020, 0x3c051c22, 0x65411984, 0x0cff4305, 0x841b0321, 0x001e224d, 0x43b58208, 0x00210c95, + 0x423384bb, 0x818909f5, 0x8190f820, 0xd1821f20, 0x1d002324, 0x19821604, 0x31001c25, 0x42002000, 0x1a2a0597, 0x29002c00, 0x1c002d00, 0x19827703, + 0x2e002622, 0x20218d82, 0x05c54600, 0x2007e743, 0x2619825f, 0x002b0020, 0x8226001a, 0x0bf15637, 0x1982cc20, 0x830fa742, 0x0026243b, 0x440b00ce, + 0x2c2010b5, 0xc2205782, 0xbd461782, 0x06bd410b, 0x82080421, 0x82182017, 0x8208201f, 0x822420e5, 0x84222067, 0x041e2269, 0x41178486, 0x1a200bd5, + 0x2922c982, 0x17825905, 0x200b4941, 0x24338225, 0x041c0025, 0x41178483, 0x29200547, 0x1822e382, 0x05821b00, 0x51052922, 0x2b20178a, 0x25204182, + 0x22240382, 0x9c021f00, 0x2f221784, 0x0f820800, 0x1a002924, 0x77821f00, 0x1c002d24, 0xa7843d05, 0x15821c20, 0x1b821b20, 0x23002a22, 0x1a201782, + 0x58221782, 0x69820a00, 0x2009e944, 0x22198218, 0x843c0023, 0x20458315, 0x2027822b, 0x20c3822a, 0x208b822c, 0x85158413, 0x0018228b, 0x2429822b, + 0x032a0018, 0x82158276, 0x22002107, 0x2b219782, 0x06634100, 0x8aa10421, 0x8219202b, 0x82192043, 0x031c222d, 0x20158284, 0x226f8229, 0x82240026, + 0x202b8785, 0x20158219, 0x2063822c, 0x20038208, 0x20198220, 0x202b8427, 0x201582da, 0x20af8223, 0x2059821a, 0x21338219, 0xa5820018, 0x8acd0421, + 0x822a2057, 0x822c2019, 0x0223222b, 0x221582c7, 0x82250020, 0x001a2125, 0x2b831183, 0xcc022a22, 0x1c201582, 0x0820cf84, 0x4b835982, 0x1f002a24, + 0x418abf04, 0x2d822820, 0x63822920, 0xf9022524, 0x51460900, 0x040b220e, 0x83138415, 0x002a227f, 0x22898427, 0x828f001c, 0x05554213, 0x8f820820, + 0x1a002026, 0xf7021c00, 0x0d223b90, 0x13829f03, 0x1b001c22, 0x2720e582, 0x2a239184, 0x83001c00, 0x002c2113, 0x8605f942, 0x0e05218d, 0x20202782, + 0x1f20b782, 0x31205f82, 0xe3820382, 0x848b0321, 0x822f2063, 0x822a2031, 0x8218203f, 0x002b22c1, 0x201384b9, 0x22138229, 0x821f0008, 0x8223202f, + 0x845e2009, 0x001f2277, 0x4d25822b, 0x022106ad, 0x228b90f6, 0x8213020e, 0x0f8d4613, 0xc78abc20, 0x4f821d20, 0x1b002624, 0x3b84f201, 0x8305b158, + 0x8229208f, 0x843b2059, 0x491a2013, 0x20260669, 0x24002c00, 0x3b84cd04, 0x20050742, 0x2487821b, 0x021b0018, 0x227790f8, 0x90fa020c, 0x03092213, + 0x223b8ad7, 0x82270026, 0x0225223d, 0x20bf8273, 0x22e5822c, 0x822a0023, 0x0030240f, 0x8475031c, 0x0bbf45f7, 0x11843a20, 0x18228789, 0x1182aa03, + 0x2f002622, 0x47850584, 0x4784a820, 0x49822020, 0x6d431b20, 0xc4012105, 0x22223586, 0x5b412e00, 0x84892006, 0x00252211, 0x2007841b, 0x20b98220, + 0x287d8805, 0x0026001f, 0x01250029, 0x225384ac, 0x46220026, 0xd6220817, 0x55820700, 0x46001c21, 0x022106a3, 0x450f82f6, 0x02210a11, 0x240f82d7, + 0x001a0020, 0x24038230, 0x041c0023, 0x420f8219, 0x182005d1, 0x2b223782, 0x2f863503, 0x2b001f28, 0x19002c00, 0x0f848903, 0x85822520, 0x1e001822, + 0x2120ef82, 0x29200f82, 0x2020a182, 0x23242d82, 0xa8011c00, 0x29201f84, 0x26204d82, 0x1c242382, 0x0600c400, 0x1a203782, 0x21056343, 0x0d844605, + 0x39832920, 0x05290023, 0x200d8257, 0x22198220, 0x82250020, 0x82be2011, 0x088f440d, 0x00840423, 0x21d18205, 0x1b820018, 0x821e0321, 0x8323200b, + 0x1b002309, 0x0b82ae04, 0x1f001822, 0x05217183, 0x260b843b, 0x0026001a, 0x84180425, 0x002c262f, 0x031f002a, 0x240b828b, 0x002f0026, 0x200d821c, + 0x200b82d1, 0x2449822c, 0x042b002a, 0x220b82a1, 0x82190020, 0x031c22a9, 0x202f84d9, 0x243b8226, 0x000f0524, 0x24138204, 0x051e0026, 0x2409820c, + 0x00190018, 0x20f78230, 0x24638204, 0x021f002b, 0x2413841e, 0x022a0029, 0x240984a4, 0x02220025, 0x2009823d, 0x2233821c, 0x828d0323, 0x225f8309, + 0x82320225, 0x82262009, 0x042b2213, 0x24098482, 0x021c0025, 0x240984c4, 0x01190024, 0x240984ab, 0x01220026, 0x240984b0, 0x001b0023, 0x243b84c5, + 0x042a001e, 0x48138417, 0x042005a9, 0x1c26b782, 0xd5012900, 0x81820300, 0x9d022522, 0x2c240782, 0xf3021e00, 0x1c240782, 0xd8021b00, 0x2a220f84, + 0x07828a03, 0xb809e583, 0x01b601da, 0x020e02e2, 0x02620238, 0x02b2028a, 0x030203da, 0x0352032a, 0x03a0037a, 0x04ec03c6, 0x04380412, 0x0484045e, + 0x04cc04a8, 0x051405f0, 0x055c0538, 0x05a40580, 0x06ec05c8, 0x0630060e, 0x06740652, 0x06b60696, 0x07f606d6, 0x07360716, 0x07760756, 0x07b60796, + 0x08f407d6, 0x08300812, 0x086c084e, 0x08a8088a, 0x09e408c6, 0x09200902, 0x095c093e, 0x0998097a, 0x09d009b4, 0x0a080aec, 0x0a400a24, 0x0a780a5c, + 0x0ab00a94, 0x0be80acc, 0x0b1c0b02, 0x0b500b36, 0x0b840b6a, 0x0bb80b9e, 0x0cec0bd2, 0x0c200c06, 0x0c540c3a, 0x0c880c6e, 0x0cbc0ca2, 0x0df00cd6, + 0x0d240d0a, 0x0d580d3e, 0x0d8c0d72, 0x0dc00da6, 0x0ef40dda, 0x0e240e0c, 0x0e540e3c, 0x0e840e6c, 0x0eb40e9c, 0x0ee40ecc, 0x0f140ffc, 0x0f440f2c, + 0x0f740f5c, 0x0fa40f8c, 0x0fd40fbc, 0x100410ec, 0x1032101c, 0x105e1048, 0x108a1074, 0x10b610a0, 0x10e210cc, 0x110e11f8, 0x113a1124, 0x11661150, + 0x1192117c, 0x11be11a8, 0x12ea11d4, 0x12161200, 0x123e122a, 0x12661252, 0x128e127a, 0x12b612a2, 0x12de12ca, 0x130613f2, 0x132c131a, 0x1350133e, + 0x13741362, 0x13981386, 0x13bc13aa, 0x13e013ce, 0x140414f2, 0x14241414, 0x14441434, 0x14641454, 0x14801472, 0x149c148e, 0x14b814aa, 0x14d414c6, + 0x14f014e2, 0x150a15fe, 0x15221516, 0x153a152e, 0x15521546, 0x156a155e, 0x15821576, 0x159a158e, 0x15b015a6, 0x15c415ba, 0x15d815ce, 0x15ec15e2, + 0x16fe15f6, 0x160e1606, 0x161e1616, 0x00ae0326, 0x0c5b5d15, 0x26001b24, 0x01822300, 0x29001826, 0x2b000800, 0x08220d82, 0x0f822a00, 0x2b002624, + 0x2b825704, 0x2b201783, 0x1d201982, 0x2b262384, 0x1c001900, 0x0f821b00, 0x2c002a22, 0x2b244782, 0x18001a00, 0x1c262f82, 0x14006e02, 0x1b821f00, + 0x47822d20, 0x25002622, 0x0f562182, 0x08bd4e0d, 0xdd5d2984, 0x8e1a200b, 0x22298937, 0x8c130070, 0x83298fab, 0x002e23bb, 0x27830225, 0x27867b9b, + 0x82d80021, 0x8223204f, 0x862c20e1, 0x821f20c1, 0x002e220b, 0x20b1821c, 0x49af822a, 0x0521083b, 0x24278215, 0x00240026, 0x0a775427, 0xd5541820, + 0x6d022111, 0x779b2782, 0x5b822320, 0x2b001d22, 0xf19b2784, 0x04212786, 0x839f9cf9, 0x00182969, 0x0230002d, 0x00120083, 0x1c208f83, 0x5f06c746, + 0xc58208af, 0x21083d41, 0x2582de01, 0x2120455f, 0x258e0c02, 0x21147150, 0x258ebe01, 0x7f821f20, 0x1d002322, 0x2a286f82, 0x29002b00, 0x22002600, + 0xd720eb82, 0x23252582, 0x27002000, 0x087d4800, 0x9d832182, 0x83001c21, 0x82202027, 0x02252227, 0x21258438, 0x85410026, 0x079b4105, 0x26002322, + 0x63465382, 0x00232405, 0x82db032b, 0x20658525, 0x204d8c22, 0x2167822b, 0x09420018, 0x02292405, 0x4211000b, 0xd35e0c21, 0x9e022112, 0x2d412382, + 0x06794117, 0x826f0221, 0x1bc94123, 0x27002c22, 0xc5412384, 0x2023831b, 0x834782d9, 0x822a20c9, 0x20cb83a5, 0x5ad3821a, 0xa9820889, 0x1e002524, + 0x23826a00, 0x1b002622, 0x08262182, 0x2c002700, 0x01822300, 0x29000822, 0x29410f82, 0x1a052108, 0x18248f84, 0x27002400, 0x1e224182, 0x2d842500, + 0x29821e20, 0x2a001822, 0x1c240182, 0x0e022a00, 0x5541fb9a, 0xbe022106, 0x1a228f86, 0xa95c2200, 0x08994f0e, 0x41810221, 0x47871a1f, 0x10003922, + 0xb3417b82, 0x84e98207, 0x8218200d, 0x820820c5, 0x0023249f, 0x8223042b, 0x05334321, 0x0820a185, 0x29201b82, 0x1d221b82, 0xf7852b00, 0x82890421, + 0x821f2021, 0x00292211, 0x8211851e, 0x822a2091, 0x8418201d, 0x00262421, 0x82280525, 0x0b614121, 0x1b203f83, 0x21882b82, 0x8c380221, 0x0bed4187, + 0x0324a986, 0x000f008f, 0x2a118342, 0x001f001a, 0x001a001c, 0x82a50422, 0x20a7831f, 0x200f8224, 0x20798225, 0x4585822a, 0x02210a03, 0x831f82dc, + 0x822b2057, 0x215f9217, 0x1f820d02, 0x238ba38b, 0x27002c24, 0x3f868202, 0x24139b43, 0x0527002c, 0x517f8e41, 0x01210eeb, 0x435f8ed2, 0x04210e3d, + 0x41df84f7, 0x24220789, 0x01822600, 0xab822520, 0x18002928, 0x25002000, 0x1f82db03, 0x22133743, 0x822a002c, 0x022922f1, 0x201f8202, 0x20098229, + 0x202d821b, 0x2037822b, 0x2037821a, 0x09c74129, 0x00400523, 0x123f410e, 0x04213d86, 0x211d821d, 0x1f510026, 0x0008240d, 0x821c0019, 0x04232233, + 0x211d84a4, 0x5b410024, 0x82082007, 0x085d4657, 0x82120321, 0x8218201d, 0x001c2127, 0x2005c549, 0x537d8229, 0x1d9408a1, 0xa3822b20, 0x5b822420, + 0x90032a22, 0x23209594, 0x2a241f82, 0x11032b00, 0x24205992, 0x25261b82, 0x2a002c00, 0x1d828101, 0x0d821f20, 0xe5842320, 0x3f442920, 0x82202008, + 0x021e2287, 0x41598439, 0xcd41074f, 0x3f05210e, 0x29831d84, 0x1a002022, 0x974faf82, 0xf604210c, 0x1b833b8c, 0x2b001826, 0x18001900, 0x2322e582, + 0x0d416c05, 0x82272006, 0x822b2085, 0x84292075, 0x2469833f, 0x031c002a, 0x42b39213, 0x022108a5, 0x45598c38, 0x04210e23, 0x201d8cfa, 0x425f822a, + 0x00250a01, 0x000d006c, 0x20138229, 0x20738231, 0x20098220, 0x20778226, 0x24ff822a, 0x0325001e, 0x421b82ac, 0x08200bfd, 0x2109e54d, 0x1b820a05, + 0x48062543, 0x00210f09, 0x201b82da, 0x20d9822c, 0x06734e1c, 0xe3822b20, 0x22001a22, 0x1b226182, 0x1b82ed01, 0x67821820, 0x20133554, 0x201b8410, + 0x41278223, 0x272809f3, 0x2c002300, 0x11052a00, 0x2e201b92, 0x1c202982, 0x62205782, 0x24201b84, 0x29200d82, 0x08206982, 0x2b20c584, 0x2b240982, + 0xe6011c00, 0x1b203792, 0x30201b82, 0x14205382, 0x2a221b84, 0xc1821f00, 0x3d822920, 0x4d671e20, 0x01292208, 0x451b82cd, 0x2b470de3, 0x06015208, + 0x820af751, 0x8219203f, 0x00192653, 0x00bc0230, 0x0c63460c, 0x2600252a, 0x1a002b00, 0x94031f00, 0x1f491982, 0xde032114, 0x26241982, 0x27002400, + 0x1a204382, 0x08222d82, 0x89841b00, 0xf3011a22, 0x18201982, 0x1c211982, 0x20d98700, 0x0541471c, 0x8ed00121, 0x081b4367, 0x82680021, 0x00262119, + 0x21053146, 0x5787001a, 0x1c002924, 0x19823902, 0x4509d148, 0x01210a97, 0x431982e6, 0x0f830f6d, 0x56032b22, 0x0541678e, 0x92102009, 0x821b2033, + 0x033022c1, 0x83338e19, 0x002c22d7, 0x2081822a, 0x20198261, 0x2623821f, 0x00250020, 0x48190008, 0x2522080b, 0x19822b03, 0x15822620, 0x44052b42, + 0x02210a6b, 0x2133847c, 0x9546001c, 0x0b6f6805, 0x678ed120, 0x20081143, 0x42198301, 0x5b4a099d, 0xcc01210a, 0x794a4d86, 0x06d54709, 0x8c1b0421, + 0x0a1b6367, 0x86790321, 0x05075419, 0x20001922, 0x1f25cb82, 0x27002600, 0x24678302, 0x00220018, 0x20cd821c, 0x2ad7821a, 0x001b0025, 0x001c0023, + 0x4172032a, 0x292008d3, 0x31820f83, 0x1f820820, 0x2b002324, 0x19829a00, 0x2005d946, 0x2035822b, 0x224d822a, 0x83270024, 0x2a032135, 0x20100341, + 0x24658219, 0x03220026, 0x451984ab, 0x2b200f2b, 0x7c206782, 0x22229b8c, 0x4f822500, 0x1f001e22, 0x64206782, 0x1a21678c, 0x08015800, 0x41eb0121, + 0x33441003, 0x41d62007, 0x25200e51, 0x1b203582, 0x6620bf84, 0x23201982, 0x2720c182, 0x1c22ab82, 0x65492900, 0xcf012109, 0x2420338e, 0x22084b45, + 0x430b00ce, 0x27200c0b, 0x2105cb43, 0x17820602, 0x2b204383, 0x1d201d82, 0x1a200382, 0x2b245782, 0x80011c00, 0x7b451782, 0x821b2009, 0x001c2665, + 0x042a002a, 0x088b531f, 0x8b822020, 0x7b820820, 0xdf822020, 0x2c031c22, 0x2c205f8e, 0x57822d82, 0x82200421, 0x00292217, 0x52a98226, 0x02210cf1, + 0x832f8e77, 0x0018248f, 0x8cd40030, 0x84292077, 0x00232495, 0x8461021c, 0x54182017, 0xff8308c3, 0x1f002a24, 0x17822a02, 0x4309234a, 0x03210811, + 0x842f847e, 0x08c94ab3, 0x25001c24, 0x17846500, 0x2b203183, 0x1e201782, 0x2524ed82, 0x2b002b00, 0x2006ab54, 0x20138229, 0x0b1b5319, 0x845c0321, + 0x0bc143ef, 0x82002421, 0x1a0321f1, 0x2a20bf8e, 0xe5824582, 0x84320521, 0x0b1d422f, 0x24002a26, 0x54032a00, 0xe5412f8e, 0x55032106, 0x2328178e, + 0x1d001c00, 0xd3012b00, 0x2020178e, 0x1d24bb82, 0x60022600, 0x19228f8a, 0xab822900, 0x1a002526, 0x02021f00, 0x1d481782, 0x18032112, 0x18268f90, + 0x2b002300, 0x1f417a03, 0x08f54b0c, 0x00ae0123, 0x4553820a, 0x2d8409bf, 0x829a0121, 0x06ed5515, 0x82080021, 0x0026269f, 0x0129002c, 0x241582d4, + 0x00260029, 0x2001822a, 0x2035821f, 0x228f8220, 0x86ce042a, 0x00272241, 0x830f821e, 0x00252429, 0x829f021b, 0x0b7d4915, 0x26001b26, 0x27022b00, + 0x29202b84, 0x2b20f382, 0x13415782, 0x07052106, 0x2c226d86, 0x15821b00, 0x29821920, 0x0121b182, 0x461582ea, 0x2c240d05, 0xd3002700, 0x08224186, + 0x93822b00, 0x25002522, 0x23224b82, 0x2b867d03, 0x20052544, 0x249b8227, 0x0325002e, 0x4515825d, 0xe185078d, 0x1c001e24, 0x6d8cf804, 0x2b822920, + 0x2b822020, 0x4184da20, 0xc54cfd83, 0x7f03210a, 0xfb83578c, 0x22002624, 0xc58c2902, 0x2106c141, 0x2b8c7b03, 0x82002221, 0x1e002355, 0x8384ab03, + 0x84091f42, 0xd4022115, 0x95422b84, 0x84232007, 0x041c222b, 0x22998cd1, 0x82260024, 0x02252201, 0x226d84cb, 0x821a0023, 0x822320ef, 0x822b20ad, + 0x02292215, 0x28418cd2, 0x00290018, 0x0518001c, 0x262b8412, 0x001b0025, 0x82080030, 0x00182631, 0x001c0025, 0x2215826b, 0x4a230026, 0x2a20067f, + 0x1e266d82, 0xd2042500, 0x13840900, 0x20057541, 0x225d822a, 0x82690025, 0x07314113, 0x26001d22, 0x22225582, 0x39558704, 0x82192008, 0x00292423, + 0x8a2b002a, 0x821a2013, 0x82182023, 0x011f2213, 0x452782f2, 0x1920095b, 0x2922a982, 0x13825703, 0x240b0542, 0x0227002c, 0x20278cd3, 0x228d8227, + 0x86db021c, 0x822b2063, 0x442720b5, 0x002105a9, 0x20138263, 0x20c9821c, 0x86138220, 0x390521b3, 0x19202784, 0xf5452182, 0x02292207, 0x22b384ce, + 0x63300027, 0x0321095d, 0x4edb8451, 0x94200ddf, 0x25204f84, 0x200b5156, 0x205b8304, 0x20e78229, 0x20638227, 0x21558218, 0x5783042b, 0x1a002624, + 0x27822200, 0x9b821820, 0x6a022322, 0x1c221b86, 0x8d822500, 0x29001824, 0x11842802, 0x8207c542, 0x8e0321d3, 0x27241184, 0x2c002a00, 0x2a229b84, + 0x1182dc01, 0x24002624, 0x49452700, 0x84882008, 0x82292023, 0x822a2005, 0x001b2457, 0x82d5001c, 0x821f200b, 0x8223200b, 0x224d8357, 0x82980325, + 0x0b2f4111, 0xd9001f22, 0x2c224788, 0x33822b00, 0xf6012922, 0x174d1186, 0x1a042108, 0x25205984, 0x18229f82, 0x4f821900, 0x85042a22, 0x29206b88, + 0xb3833382, 0x07008022, 0x24088f48, 0x032a002a, 0x830f823e, 0x82232051, 0x0029241f, 0x55700530, 0x18280695, 0x18002d00, 0xe8012500, 0x65862f86, + 0x842b0221, 0x0023220f, 0x21d3822c, 0x61830025, 0x27820720, 0x182acd83, 0x2b002300, 0x06003e05, 0x4b821f00, 0x2a001c26, 0x13051c00, 0x18200d82, + 0x22068751, 0x86d2002b, 0x8208200d, 0x01252281, 0x830d84ae, 0x00292457, 0x84dc0318, 0x822c2037, 0x001a242b, 0x84d5011f, 0x0025221b, 0x2249821a, + 0x82420523, 0x8229200d, 0x822b2071, 0x001f220f, 0x200d8267, 0x20418223, 0x221b822d, 0x821e0429, 0x8226200d, 0x8222200d, 0x021c21ef, 0x26227d83, + 0x01821d00, 0x1c001c24, 0x1b825402, 0x23084541, 0x0500ac02, 0x19204382, 0x2a223582, 0x0b829a01, 0x2106d744, 0x0b82ad03, 0x19822620, 0x03217782, + 0x200b8278, 0x2321831f, 0xe0032a00, 0x29200b82, 0x2e245982, 0xa6042500, 0x2a240b86, 0xa9022a00, 0x20262384, 0x1b002300, 0x47860003, 0x1c002524, + 0x0b869301, 0x79822a20, 0x23841620, 0x93821820, 0x17022522, 0x2c201786, 0xdd202f82, 0x20266b84, 0x2a002500, 0x23849201, 0x1a001c26, 0xd0042200, + 0x29242f88, 0x04001a02, 0x27247582, 0xf5013000, 0x1e200984, 0xd1207382, 0x18220982, 0x59822200, 0x0982ab20, 0x82002c21, 0x5c0221c5, 0x1b201d84, + 0x5f201382, 0x29200982, 0x04213383, 0x260982a3, 0x002b0020, 0x86df0330, 0x022e2a13, 0x000300ae, 0x02290018, 0x24078219, 0x042b002c, 0x220f84cf, + 0x8298012b, 0x00262407, 0x8287021e, 0x00252407, 0x84af0230, 0x04192217, 0x081784d3, 0x3e002e82, 0xc0007e00, 0x0e01e800, 0x58013401, 0x9a017a01, + 0xd801ba01, 0x1002f401, 0x48022c02, 0x7c026202, 0xae029602, 0xde02c602, 0x0c03f602, 0x38032203, 0x60034c03, 0x88037403, 0xb0039c03, 0xd803c403, + 0xfc03ea03, 0x20040e04, 0x44043204, 0x68045604, 0x8c047a04, 0xac049c04, 0xcc04bc04, 0xec04dc04, 0x0c05fc04, 0x28051a05, 0x44053605, 0x5e055205, + 0x74056a05, 0x88057e05, 0x9a059205, 0x20007203, 0x2a12b372, 0x00250018, 0x0008001b, 0x8227002c, 0x13136f05, 0x21821c20, 0x1c002b28, 0x9c002900, + 0x43821300, 0x1e001822, 0x18220b82, 0x2f822400, 0x20058343, 0x201d821b, 0x05e3411a, 0x29246182, 0x12002104, 0x1e202782, 0x2b240382, 0x23001800, + 0x07832782, 0x1f001a24, 0x3b862600, 0x1f002724, 0x25848a04, 0x26204783, 0x45698386, 0x22878909, 0x8e11009d, 0x822a2073, 0x001a21ab, 0x23226f8b, + 0x91841000, 0x82086751, 0x09234c71, 0x2a002a26, 0x0f002e03, 0x20222182, 0xe9542d00, 0x82232008, 0x26438355, 0x002a0025, 0x82fd031c, 0x8220201f, + 0x22d98dab, 0x82210026, 0x001a262f, 0x00d8042b, 0x223f820e, 0x5324002c, 0x1a2206c3, 0x63822200, 0x43821920, 0x3d822b20, 0x0d009422, 0x2320d982, + 0x3020e982, 0x210f2556, 0x1b821705, 0x27203783, 0x1c203984, 0x08224582, 0x37821d00, 0x1c002924, 0x1b827804, 0x39822920, 0x39822720, 0x3d451c20, + 0x82232006, 0x002a2485, 0x8425041f, 0x2039831b, 0x20398608, 0x2025821c, 0x241d8227, 0x008b0425, 0x20ef840c, 0x206d822e, 0x22798427, 0x821e0030, + 0x04252207, 0x081d4ba7, 0x29822420, 0x1f001a22, 0x22200582, 0x9b202b84, 0xe18d1982, 0xdb822520, 0x2b002f26, 0x0b001504, 0x23200982, 0x2b200382, + 0x13530382, 0x5e032108, 0x2a221784, 0x8f492200, 0x266b8205, 0x00230018, 0x82e9032b, 0x74262017, 0xe95308a3, 0x84042009, 0x09475717, 0x20002a22, + 0x25269582, 0x0a009f02, 0xcd732600, 0xe603210f, 0x20221582, 0x71841a00, 0xa7822b20, 0x09822920, 0x8a041c22, 0x0b831584, 0x31821a20, 0x37822020, + 0x2a002526, 0x09004b03, 0x260ab942, 0x00250026, 0x82e3031e, 0x203f8713, 0x241d821d, 0x0429002c, 0x22138295, 0x822a0018, 0x0885494d, 0x84ea0321, + 0x0026223b, 0x22bf8229, 0x82270026, 0x03252265, 0x263b8ce2, 0x002d0020, 0x8293031c, 0x82262013, 0x002322df, 0x83298230, 0x002f223f, 0x2013846e, + 0x067b5d25, 0x0321cd84, 0x203b8491, 0x20138218, 0x20758225, 0x224f822a, 0x82b1022a, 0x82182031, 0x001824af, 0x82180019, 0x031c227f, 0x20118224, + 0x200b821c, 0x20ab821d, 0x2211821c, 0x82e5032a, 0x26af8711, 0x0020002a, 0x8ad4042f, 0x001b2611, 0x0309000b, 0x22118280, 0x8224002c, 0x82192045, + 0x00232457, 0x8ae40323, 0x83262023, 0x9c01214b, 0x2e20c784, 0x23200b82, 0x18247f82, 0x16051b00, 0x61423586, 0xfb042108, 0x24207d84, 0x1a201f82, + 0x1824f782, 0xe7032b00, 0x2b2b478a, 0x26002e00, 0x07005e03, 0x41001c00, 0x6d2009dd, 0x20200f82, 0x27220f82, 0xb7822300, 0xbf013022, 0x9b420f82, + 0xdd02210a, 0xad431f84, 0x43052108, 0xff830f84, 0x0421f184, 0x200f82d9, 0x2095822c, 0x8255821e, 0x5b0521a9, 0x1e221f84, 0xeb821e00, 0x1e002524, + 0x0f84d504, 0x2605ef41, 0x010f001b, 0x820600b9, 0x821b2029, 0x82252003, 0x82ae209f, 0x8235820d, 0x822b2079, 0x84042011, 0x0649420d, 0x82d70421, + 0x8229200d, 0x821e2019, 0x032522cf, 0x220d82e8, 0x822d0020, 0x001b2655, 0x0022041c, 0x26098205, 0x00310031, 0x82930330, 0x06c1410b, 0x00e10323, + 0x82178204, 0x2404216d, 0x29260982, 0x24002c00, 0x0982af03, 0x39822620, 0x83031c21, 0x821c2013, 0x031d2451, 0x82030092, 0x041822b3, 0x200782d6, + 0x08ab8226, 0x62003062, 0xc0009400, 0x1401ea00, 0x60013a01, 0xa8018401, 0xf001cc01, 0x2e021002, 0x6a024c02, 0xa2028602, 0xda02be02, 0x0e03f402, + 0x40032803, 0x6e035803, 0x9a038403, 0xc603b003, 0xf003dc03, 0x18040404, 0x3c042a04, 0x60044e04, 0x84047204, 0xa0049204, 0xba04ae04, 0xd004c604, + 0xe204da04, 0x5903ea04, 0x2f217782, 0x67e58300, 0x2320097d, 0x2525ab82, 0x08002200, 0x0a075000, 0x18220d82, 0x29822300, 0x1500db22, 0x2d22a382, + 0x0d821c00, 0x27002622, 0x08210782, 0x0d575a00, 0x1f001a22, 0x1a271582, 0xe4012200, 0x78001400, 0x08201327, 0x29204782, 0x18206582, 0x1e204982, + 0x1c224782, 0x29847e02, 0x042387a2, 0x901200a8, 0x2087857f, 0x83a38225, 0x21cf8241, 0x2582de01, 0xab8a7995, 0x00580323, 0x979f8211, 0x21ef8475, + 0x23827502, 0xa3822320, 0xeb822020, 0xb3822a20, 0x65822a20, 0x2920fd83, 0x2020c382, 0x2582f982, 0x84500321, 0x00272147, 0x2f59cf83, 0x107b6d05, + 0x82cf0221, 0x00302223, 0x213d821c, 0xc942001b, 0x82272005, 0x8229200d, 0x0811650f, 0x00a30223, 0x41db900f, 0x04230a83, 0x8e0e00b4, 0x822a201f, + 0x0019223f, 0x229f822c, 0x82380422, 0x8218201d, 0x002b225b, 0x2215821f, 0x84240018, 0x22a3855f, 0x8226032a, 0x8230201d, 0x82082011, 0x05a77a2b, + 0xcd842d20, 0x26002028, 0x29032500, 0x598e0d00, 0x17820820, 0x2520a183, 0x0d205782, 0xef83d982, 0x01215790, 0x423782fa, 0x9e20173f, 0x83088554, + 0x00262237, 0x207d821a, 0x28658218, 0x03180020, 0x000c005a, 0x2011822f, 0x2159821f, 0x957b0025, 0x82182005, 0x052b2299, 0x08c1531c, 0x1c203583, + 0x2d41db82, 0x041c2205, 0x22198c37, 0x7b1d0018, 0x022208ef, 0x67420b00, 0xcf022113, 0x73411782, 0x74022312, 0x6b820a00, 0xff822320, 0x41002721, + 0x1f2207d3, 0x15927502, 0x39042d22, 0x55411582, 0x202f830b, 0x21598218, 0x5983000a, 0x210ccb41, 0x2b827303, 0x42002f21, 0x23240b07, 0x22032b00, + 0x8308c94e, 0x002a2a71, 0x001c002b, 0x00e30125, 0x20418409, 0x09ef5508, 0x82dc0021, 0x822f2013, 0x0023223f, 0x24978426, 0x02250026, 0x20138284, + 0x0d33562c, 0x00180523, 0x20458208, 0x2247821f, 0x82250029, 0x002b2205, 0x2011826f, 0x20098223, 0x08374e2d, 0x11822f20, 0x43002521, 0xf5820aa7, + 0xf58d0820, 0x4c240321, 0x1b20083d, 0x18243b82, 0x37021d00, 0x97411182, 0x0014260d, 0x00280006, 0x2457822c, 0x022a0023, 0x200d8265, 0x200b8229, + 0x222f822a, 0x82db0129, 0x23ef880d, 0x05003804, 0x29201982, 0x01219983, 0x200b82cb, 0x2c238221, 0x012b001a, 0x000400c0, 0x0020001b, 0x21cb822b, + 0xcb840004, 0x00440529, 0x001e0003, 0x82e2011e, 0x00302207, 0x2019821c, 0x09198403, 0x14018925, 0x74014401, 0xd001a201, 0x2602fc01, 0x7a025002, + 0xcc02a402, 0x1803f402, 0x60033c03, 0xa8038403, 0xf003cc03, 0x38041404, 0x7e045c04, 0xc204a004, 0x0605e404, 0x46052605, 0x86056605, 0xc605a605, + 0x0606e605, 0x46062606, 0x82066406, 0xbe06a006, 0xfa06dc06, 0x36071807, 0x6e075207, 0xa6078a07, 0xde07c207, 0x1608fa07, 0x4e083208, 0x82086808, + 0xb6089c08, 0xea08d008, 0x1e090409, 0x52093809, 0x86096c09, 0xb809a009, 0xe809d009, 0x180a000a, 0x480a300a, 0x780a600a, 0xa80a900a, 0xd80ac00a, + 0x080bf00a, 0x380b200b, 0x640b4e0b, 0x900b7a0b, 0xbc0ba60b, 0xe80bd20b, 0x140cfe0b, 0x400c2a0c, 0x6c0c560c, 0x940c800c, 0xbc0ca80c, 0xe40cd00c, + 0x0c0df80c, 0x320d200d, 0x560d440d, 0x7a0d680d, 0x9e0d8c0d, 0xc00db00d, 0xe00dd00d, 0xfc0dee0d, 0x180e0a0e, 0x320e260e, 0x4a0e3e0e, 0x5e0e540e, + 0x720e680e, 0x860e7c0e, 0x9a0e900e, 0xac0ea40e, 0x17004504, 0x1a001800, 0x08001c00, 0x29001e00, 0x44002000, 0x262005e9, 0x1e220782, 0x17842c00, + 0x83052544, 0x002b2219, 0x222f82de, 0x45230020, 0x1c201299, 0x24132543, 0x16002703, 0x204b8300, 0x225f822b, 0x822e0018, 0x822a2037, 0x4424200f, + 0x1e20082b, 0x08220d82, 0x69821d00, 0x23002324, 0x2d824104, 0x7f8b8d91, 0x2b000822, 0x18203b82, 0x2a24a982, 0x15004604, 0x2e20bba0, 0x2224d184, + 0x14005204, 0x22242b88, 0x2a002000, 0x08210182, 0x821d8600, 0x861f209b, 0x042b2255, 0x41298a3e, 0x19200911, 0x24201f84, 0x2a202982, 0x1820c584, + 0xe0208782, 0x0b412982, 0x00282215, 0x20e9842c, 0x8269822b, 0xab0421fd, 0x0d462986, 0x0fd34605, 0x230a8f5c, 0x13002c04, 0x5f413382, 0x00202605, + 0x002d0025, 0x410f8226, 0x278a059f, 0x86700021, 0x58519527, 0x0323084b, 0x41110027, 0x1d28187f, 0x18002300, 0x82011e00, 0xc7952382, 0x21086d47, + 0x23846b02, 0x24055d67, 0x002f001c, 0x2295822b, 0x821e0025, 0x002024e7, 0x821f002a, 0x042922ed, 0x21478a2d, 0x2b830027, 0x9d792a20, 0x8d03210f, + 0x7f85478a, 0x57050b42, 0x04210a45, 0x42238255, 0xa1830705, 0x67822c20, 0x08001f22, 0x26063148, 0x00250020, 0x8a5d042b, 0x82292023, 0x822320e1, + 0x201983cb, 0x2227821e, 0x8230001c, 0x002a228f, 0x56d798df, 0x052108e1, 0x228f963a, 0x822c001a, 0x822d20c1, 0x011b2247, 0x41479883, 0x96220967, + 0xb7411000, 0x0c355c08, 0x20081352, 0x42218244, 0x2b2011db, 0x4741bb82, 0x041c2205, 0x4221943f, 0xff820899, 0x658aa020, 0x200d1749, 0x05ef5227, + 0x94400421, 0x0a414343, 0x00540424, 0x5d41000f, 0x06e14213, 0x8a420421, 0x09ff421f, 0x2b002a22, 0x29243582, 0x26042a00, 0x1c201f82, 0x2b200b82, + 0x8205f541, 0x822720df, 0x002022c3, 0x24218225, 0x041b001c, 0x223f8a35, 0x4c29001d, 0x262808cd, 0x1c002700, 0x28042500, 0x20201f82, 0x1c20ad82, + 0x2115715f, 0x3f8abe03, 0x24002a22, 0x43085541, 0x042106ab, 0x871f966c, 0x944320bf, 0x083544bf, 0x8ab50221, 0x20b9837f, 0x2095822e, 0x209b8229, + 0x82698226, 0x560421c3, 0x87161f41, 0x002e227f, 0x2093880e, 0x2009822a, 0x2af9821e, 0x002b0018, 0x0029002c, 0x825c041c, 0x075d411d, 0x59822420, + 0xe5821f20, 0xed821920, 0x25821820, 0x3c042222, 0x5b411d8a, 0x822e2009, 0x821b2045, 0x943d203b, 0x21d7861d, 0x778a3502, 0xb35f1a20, 0x4704210f, + 0xb3873b94, 0x1d8a5120, 0x2009fd44, 0x249f8219, 0x02240018, 0x241d825a, 0x00180023, 0x43ab821e, 0x002108f1, 0x21cf831c, 0xb5701b00, 0x822a2006, + 0x000821e1, 0x0e634118, 0x00810325, 0x8226000d, 0x08055f01, 0x1820ed84, 0x23229d82, 0x1b822704, 0x46095544, 0x29200503, 0x1a246582, 0x74042b00, + 0x25411b82, 0x002a2207, 0x2069822c, 0x26038227, 0x002a0020, 0x8a96031c, 0x822e2037, 0x822d202f, 0x821d2089, 0x00292463, 0x8a2f0424, 0x0ebb5f1b, + 0x8a280421, 0x0e415f1b, 0x84720021, 0x002322a7, 0x22d5841b, 0x821a0008, 0x832620a1, 0x1b00236d, 0x1b82ab04, 0x25002c22, 0x1c200182, 0xc3601582, + 0x6904210c, 0x1820a78c, 0x7f463f82, 0x27032108, 0x2008eb5b, 0x46a58208, 0x04210ad9, 0x891984a9, 0x086d446d, 0x84c90121, 0xf5411819, 0x08002308, + 0x3b821d00, 0x2b002a22, 0x18201984, 0x2b209182, 0x26211384, 0x21238800, 0x33822b04, 0x46074741, 0x818a0c11, 0x818e0120, 0x33823a20, 0x200d6b44, + 0x24218224, 0x011c001a, 0x828190ca, 0x1c00257d, 0x68042700, 0x2a20338a, 0xcf642d82, 0x00292405, 0x8a340430, 0x001d2419, 0x822c0023, 0x821f20a7, + 0x031b2233, 0x449b8a95, 0x01210cf5, 0x0e0341ee, 0x21080343, 0x338ab702, 0x29001830, 0x1f001a00, 0x2d002000, 0x26041c00, 0x55820b00, 0x7d4a1820, + 0x82082008, 0x00232485, 0x82db042b, 0x41202017, 0x2920061b, 0x0b831382, 0x1b001c24, 0x17842f04, 0x5f052b47, 0x00210a0b, 0x20178ae1, 0x265d842a, + 0x0023001c, 0x84e2001b, 0x05c34617, 0xc5821920, 0x2205df4a, 0x82710029, 0x00232217, 0x08fd4826, 0x2106d543, 0x1782ef01, 0x39842620, 0x53511c20, + 0xc502210b, 0x2c201782, 0x1920a582, 0x23203382, 0x2109f142, 0x5f844202, 0x71821e20, 0x20079547, 0x22cf8221, 0x8e45052b, 0x822b2047, 0x821c204d, + 0x8a2a20ef, 0x002024a7, 0x84270024, 0x042b2283, 0x22178a29, 0x872f001c, 0x34002117, 0x18201782, 0x1a20b782, 0x77825583, 0xb1841b20, 0x32042722, + 0xe94c2f84, 0x82292005, 0x0029282d, 0x00250020, 0x8ab7022b, 0x82312047, 0x82272013, 0x001c241b, 0x821c0229, 0x83ef8317, 0x8430200f, 0x00202647, + 0x0422002a, 0x20a78eaa, 0x05eb4127, 0x00530423, 0x1131460a, 0x8a550221, 0x08a74515, 0x8f4c0420, 0x07af4805, 0x31002022, 0x30220182, 0x2b827300, + 0x43822920, 0x1a002522, 0x5f416f82, 0x35042106, 0x26221584, 0xad822e00, 0xfb820820, 0x1c002722, 0xe4200982, 0x23201582, 0x2a222b82, 0x2b822200, + 0x20002d22, 0x23220b82, 0x15828b02, 0x35462020, 0x84232006, 0x001c24df, 0x8ab6022a, 0x00202215, 0x24298224, 0x041c001e, 0x20998a79, 0x202b822b, + 0x22578229, 0x8ab8021b, 0x0018242b, 0x821b002c, 0x02262219, 0x22158ab4, 0x822f001c, 0x001c249f, 0x8a560223, 0x08c34641, 0x8a110421, 0x82182015, + 0x001e26a9, 0x02300029, 0x83418ab9, 0x821b20ad, 0x0426246d, 0x41090050, 0x71450833, 0x97032106, 0x20201382, 0x4b453382, 0x00182605, 0x021b0020, + 0x421384ba, 0x1a2205c3, 0x95822600, 0x70041c21, 0x934b0751, 0xb302210a, 0x2e20278a, 0x29202782, 0x8b203b82, 0x2b20138a, 0x2f247582, 0x4f032b00, + 0x1c20138a, 0x2b22e384, 0x1384e300, 0x20052563, 0x2475821d, 0x042a0025, 0x68138431, 0x4742058b, 0x81032306, 0xcd450800, 0xda04210d, 0xc3451182, + 0x002a2409, 0x8a8b022d, 0x00182611, 0x022b0023, 0x46118257, 0x04210cf1, 0x201182fc, 0x20fd8223, 0x2407821e, 0x002a002c, 0x20958218, 0x08334708, + 0xa9822720, 0x3a052522, 0x8b434784, 0x20478505, 0x20598ab2, 0x24b98227, 0x0034041d, 0x0c6d4407, 0x0f82eb20, 0x79481c20, 0xc8012109, 0x29450f82, + 0x9802230a, 0x5b820600, 0x21822420, 0x1c002324, 0x0d821202, 0x3f822020, 0x13822b20, 0x33002922, 0x3b430d82, 0xc5022108, 0xc1430d82, 0xee012108, + 0xe7430d82, 0x18022308, 0x35820500, 0xb7821820, 0xdd002222, 0x1c220b82, 0x01822900, 0x56023022, 0xcd480b82, 0x30042306, 0xcf840400, 0x03022322, + 0x1c200982, 0x1b226182, 0x0982a201, 0x0121f584, 0x241d84e1, 0x011c0029, 0x260982af, 0x00250026, 0x848a022b, 0x82232013, 0x868e2013, 0x04242209, + 0x24098433, 0x031f002a, 0x830982ec, 0x021e2a5b, 0x000300a7, 0x052f0018, 0x2f07845c, 0x003b0025, 0x00a00078, 0x01f000c8, 0x013c0116, 0x3205a553, + 0x02ec01ca, 0x022c020c, 0x0268024a, 0x02a00284, 0x53d802bc, 0x3a0806a5, 0x035c0342, 0x03900376, 0x03c003a8, 0x04f003d8, 0x041c0406, 0x04480432, + 0x0474045e, 0x049c0488, 0x04c404b0, 0x04e804d6, 0x050805f8, 0x05280518, 0x05420536, 0x055a054e, 0x59720566, 0x9c2a063b, 0xae05a605, 0x1e05b605, + 0xf5821300, 0x27002022, 0x0ab54b18, 0x9d522a20, 0xe6002111, 0xf5832782, 0x23074f4d, 0x002b0018, 0x20052d45, 0x203f821b, 0x823f8226, 0x201382f3, + 0x224f84e7, 0x842c0026, 0x0d5d6d51, 0x2b20f983, 0x3982f582, 0x00450423, 0x08874512, 0x4b0a1b4b, 0x03210dfd, 0x422584ef, 0x1c20050b, 0x08202f82, + 0x1f206182, 0x25204182, 0x1c242782, 0x2c002800, 0x23240b82, 0x11003604, 0x2208416b, 0x82240008, 0x4c292013, 0x202006b7, 0x2008954b, 0x20238298, + 0x522f8218, 0x854c0525, 0x2821820a, 0x0020001f, 0x041f001e, 0x20238241, 0x08436229, 0x20215d83, 0x05015e00, 0x2308554a, 0x10009704, 0x2c205f82, + 0x1c202f82, 0x820d1364, 0x0024260d, 0x041b001c, 0x4f218246, 0x2e20155f, 0x22245b84, 0x0f003e04, 0x6f4efb88, 0x48042112, 0x27201f86, 0xaf469b84, + 0x00312205, 0x268b8426, 0x04230018, 0x820e0038, 0x002621ef, 0x08203b83, 0xa3538d82, 0xa502210c, 0x29201d82, 0x1b221582, 0x05822c00, 0x73822b20, + 0x08223983, 0x0d821a00, 0x88012724, 0x2b410d00, 0x49042117, 0x29201b82, 0x77832f82, 0x210e9d54, 0x378c1b05, 0x1f002e22, 0x2a222782, 0xf1822200, + 0x9e003022, 0x8f871b84, 0x200da353, 0x06914982, 0x3f471d20, 0x20098209, 0x2637822b, 0x0015001c, 0x8229000c, 0x094b4209, 0x1f002b22, 0x2522a582, + 0x19829704, 0x2114ad41, 0x19821a05, 0x20098742, 0x202f821a, 0x2441821c, 0x002a0029, 0x20198274, 0x833d822c, 0x822520fb, 0x8208209d, 0x00202613, + 0x0525001e, 0x8733841c, 0x0f0d549f, 0x41002321, 0x0d540949, 0x44042308, 0x9f420b00, 0x82e52014, 0x12074317, 0x8a3f0421, 0x821f202f, 0x82182091, + 0x002b243d, 0x8a40042a, 0x0b9d4d17, 0x0a009622, 0x4742ab82, 0x821f2007, 0x001e24af, 0x8242041f, 0x09814215, 0xcd842b20, 0x1d052a22, 0xa3431586, + 0xef02210c, 0x1c241582, 0x1b002500, 0x2320ff84, 0x2a200582, 0x39206f82, 0xd18b1582, 0x59822a20, 0x43041822, 0xcb42578a, 0x00472209, 0x42e38809, + 0x6f5a079b, 0x20978705, 0x22558224, 0x8a3d041b, 0x84192027, 0x032422db, 0x23138282, 0x00230026, 0x230ad741, 0x08003c04, 0x18204f88, 0x2b221b82, + 0x1182ed03, 0x2a001822, 0x272d0582, 0x24002c00, 0xac042700, 0x26000700, 0x200d8300, 0x22dd8229, 0x82ee0324, 0x074f410f, 0xbf821c20, 0x0f823a20, + 0xb3822920, 0x1d822420, 0x1c001a24, 0x0f825802, 0x39821820, 0x33821c20, 0x1b00182c, 0x06001f05, 0x20002c00, 0x1f822b00, 0x31022924, 0x07820500, + 0x93822d20, 0xf5012322, 0x1c200b82, 0x29240d82, 0x0f022a00, 0x23200b82, 0x2105d741, 0x23849504, 0x1e002c26, 0xdc041c00, 0x1f200b82, 0x2a241782, + 0x19052b00, 0x20200b82, 0x2b26bf82, 0x98012a00, 0xd7840400, 0x3b042922, 0x29200982, 0x25225f82, 0x09864804, 0xdf012722, 0x29840982, 0x00850225, + 0x82190003, 0x82752089, 0x002c2407, 0x825f0325, 0x821c2007, 0x9227099d, 0x7a012601, 0x0602c401, 0x72023c02, 0xd602a402, 0x34030603, 0x8e036203, + 0xe403ba03, 0x38040e04, 0x8a046204, 0xda04b204, 0x28050205, 0x74054e05, 0xc0059a05, 0x0c06e605, 0x58063206, 0xa2067e06, 0xea06c606, 0x32070e07, + 0x78075607, 0xbc079a07, 0xfc07dc07, 0x3c081c08, 0x7c085c08, 0xbc089c08, 0xfc08dc08, 0x3a091c09, 0x76095809, 0xb2099409, 0xee09d009, 0x280a0c0a, + 0x600a440a, 0x980a7c0a, 0xd00ab40a, 0x080bec0a, 0x400b240b, 0x780b5c0b, 0xb00b940b, 0xe40bca0b, 0x180cfe0b, 0x4c0c320c, 0x800c660c, 0xb00c980c, + 0xe00cc80c, 0x100df80c, 0x400d280d, 0x700d580d, 0xa00d880d, 0xcc0db60d, 0xf80de20d, 0x240e0e0e, 0x500e3a0e, 0x7c0e660e, 0xa80e920e, 0xd40ebe0e, + 0xfc0ee80e, 0x240f100f, 0x4c0f380f, 0x740f600f, 0x9c0f880f, 0xc20fb00f, 0xe60fd40f, 0x0a10f80f, 0x2c101c10, 0x4c103c10, 0x6c105c10, 0x8c107c10, + 0xa8109a10, 0xc410b610, 0xde10d210, 0xf610ea10, 0x0e110211, 0x26111a11, 0x3a113011, 0x43002303, 0x1b22059b, 0x5b582a00, 0x82252010, 0x6d531811, + 0xfd002732, 0x26002400, 0x51822c00, 0x41821c20, 0x23001d22, 0x26220d82, 0x0b821b00, 0x7408f773, 0x0b7310b3, 0x00002215, 0x4c498a20, 0x41900ce5, + 0x03551c20, 0x01012313, 0x41a81a00, 0xb7822f20, 0x22228783, 0x35aaff00, 0x2605ef44, 0x0022001a, 0x8a1800f8, 0x0d23526b, 0x00219d94, 0x433182ef, + 0xb36b051f, 0x20437405, 0x005d0523, 0x08c94417, 0xaf820820, 0x2a002c24, 0xad822000, 0x03820820, 0xeb6c1820, 0x8219200a, 0x00232689, 0x0023032b, + 0x21638216, 0xdf410025, 0xc94c1807, 0x8a40201d, 0x821f202d, 0x82222037, 0x8408206b, 0x00242361, 0x294b0027, 0x20418305, 0x24138218, 0x0043001f, + 0x218b8415, 0x2385001b, 0x2d841b20, 0x22056f41, 0x841f001e, 0x06d77c15, 0x823f0521, 0x0913422b, 0x2205774e, 0x82250024, 0x82302031, 0x0cd94127, + 0x00b30323, 0x08715b14, 0xc7841f20, 0xe3821b20, 0x48051f5f, 0x3d200dd9, 0x538c299a, 0x88ec0021, 0x822a2029, 0x41558f6f, 0x35200bab, 0xa9992982, + 0x20059345, 0x2495821b, 0x00eb002e, 0x0a5b4113, 0x1f205391, 0x2324b582, 0xe3041b00, 0x51992782, 0x29001a22, 0x1a244582, 0xb2032200, 0x08214f88, + 0x564d8f00, 0x40200b7f, 0x2a202788, 0x18212782, 0x05a54100, 0x23001824, 0x73412b00, 0xf200230b, 0x2b421200, 0x0d8f420a, 0x2009eb42, 0x8b2582f7, + 0x1177759d, 0x61821a20, 0x259af920, 0x05214b88, 0x24258247, 0x00250018, 0x2287821b, 0x82200024, 0x421b2007, 0x1d200635, 0x2406c141, 0x0329001c, + 0x8f258ab3, 0x092144e7, 0x718e4620, 0x41821f20, 0x44093142, 0x2922055d, 0xe39af000, 0x25218183, 0x21298200, 0x719ab103, 0x21081948, 0x718c0201, + 0x220d3f42, 0x821d0008, 0x001824c9, 0x9aee001e, 0x090b4471, 0x1100f122, 0x4f187b41, 0x002106db, 0x43239aed, 0x002106bf, 0x202384f3, 0x24fb8223, + 0x0026001a, 0x08e14b27, 0x30002a25, 0x84002400, 0x4a042125, 0x18222384, 0x1f821b00, 0x25821f20, 0x79822520, 0x094b2a20, 0x82e8200e, 0x07994123, + 0x210f7341, 0x1985001f, 0x2382fc20, 0x231eb745, 0x1000b603, 0x4408f342, 0x03211421, 0x422188b2, 0x2c2611c5, 0x1b002a00, 0x218a0702, 0x2009bf56, + 0x09fd6908, 0x006b0523, 0x4565820f, 0x26220513, 0xe7842e00, 0x65443020, 0x8441200a, 0x05d5441f, 0x6d44858b, 0x45002106, 0x42181f82, 0x2021094d, + 0x05994400, 0x20002d22, 0x83826382, 0x82050321, 0x0026221f, 0x770d822c, 0x082109e7, 0x09af5f00, 0x5f880a20, 0x8b000821, 0x05f743a1, 0xb5032522, + 0xf5607f94, 0x42002108, 0x19457f94, 0x98032108, 0x2a207f84, 0x20225b82, 0xe9822b00, 0xdb842320, 0x2108d141, 0x5f842403, 0xb7822920, 0x26000824, + 0x1d821d00, 0x2607a542, 0x00250020, 0x9402031e, 0x842a20bf, 0x0029244b, 0x9608022b, 0x822320bf, 0x001d26e3, 0x0003032b, 0x8f57820e, 0x841f20ff, + 0x041d2289, 0x201d824a, 0x420b821c, 0x18260f4f, 0x2b002300, 0x3b844d04, 0x08002b22, 0x2c226d82, 0x07821900, 0x55822720, 0x2a002922, 0x25225182, + 0x1d82f600, 0x27822020, 0x2920d183, 0x1a221182, 0x19822200, 0x41002321, 0xf5200583, 0x18221d8a, 0x63822d00, 0x03822320, 0x1a002524, 0x43821f00, + 0x77884420, 0x33820820, 0x08223185, 0x21822400, 0x22002a24, 0x1d820603, 0x5b441820, 0x82192006, 0x24598313, 0x001d0008, 0x222b8220, 0x8876002b, + 0x822a201d, 0x001a2191, 0x27225783, 0x1d822700, 0x1e002526, 0x0d004905, 0x6f418b82, 0x822c200d, 0x001c2437, 0x84040329, 0x0f0b411b, 0x69831c20, + 0x82b60321, 0x4573851b, 0x03211069, 0x201b8ab5, 0x20bf8408, 0x216f8723, 0x1b883e00, 0x65820820, 0xad822720, 0x22002922, 0x1c209382, 0x93200d82, + 0x2a226f86, 0xf9461c00, 0x0301210f, 0x2b201b8c, 0x2c202d82, 0x18268782, 0x20002400, 0x6f8cbe04, 0x29002722, 0x30205582, 0x0321df85, 0x206f8c08, + 0x2015821a, 0x203b822a, 0x22238226, 0x8cb4032a, 0x0dfb4337, 0x6f8c9120, 0x210c9547, 0x37880902, 0x240d0343, 0x0527002c, 0x201b8248, 0x20cf821c, + 0xc14a1824, 0x00182208, 0x220b841d, 0x8c3f0030, 0x0019246f, 0x8219002c, 0x82232001, 0x022a211d, 0x26201b83, 0x27209982, 0x2b20a182, 0x2322bf82, + 0x5a180800, 0x0b220807, 0xf5470c00, 0x09734308, 0x29001c24, 0x19823600, 0x4a099744, 0x18240791, 0x20052300, 0x3f491982, 0x0a117509, 0x8ce30421, + 0x821b2033, 0x82242059, 0x821e2003, 0x8c472085, 0x05274219, 0x26002b26, 0xb0032700, 0x2741818a, 0xe404210c, 0x29261982, 0x2d003000, 0xb9822500, + 0xb5821820, 0xd1828586, 0x59420c20, 0x05ef6210, 0x51572020, 0x00292206, 0x472f822b, 0x042009e5, 0x7b441782, 0x030c2211, 0x42178209, 0x0822056b, + 0x65822300, 0xaf823120, 0x1b002924, 0x1788ea00, 0x83051364, 0x0025243b, 0x8221051b, 0x0b496817, 0x29001c22, 0x30220182, 0x5f940303, 0x83030b22, + 0x1a211784, 0x051f5000, 0x27000825, 0x82002c00, 0x9901210d, 0x24221784, 0xa5821c00, 0x1e002322, 0x20080f66, 0x21178492, 0xa742002c, 0x21bf8805, + 0x17824c04, 0x27822020, 0xa5841f20, 0x21087157, 0xef8ce202, 0x23205d83, 0x03213b83, 0x248f9402, 0x00fa000a, 0x0c254c0a, 0xbd822020, 0xfb001c22, + 0x2326158e, 0x1e001800, 0x1582a301, 0x21109144, 0x1584f003, 0x210e1b47, 0x15820402, 0x4b821820, 0xa5571b20, 0x002d2408, 0x7107031c, 0xf9830857, + 0xfd821820, 0x29001c24, 0x1584df04, 0x29822b20, 0x71412e20, 0x6a052109, 0x1a201588, 0x7d46a182, 0x0c032106, 0x8d83418c, 0x1c001a24, 0xaf8c7700, + 0x22052d41, 0x8a0a0329, 0x822a202b, 0x0026266b, 0x0522001a, 0x212b8422, 0x51410029, 0x05d14505, 0xfe001b22, 0x2320418c, 0x2b827182, 0x883f0021, + 0x842a2041, 0x8218209d, 0x031f2435, 0x43090088, 0x1b200823, 0x2b242982, 0x05032a00, 0x4f421382, 0x2803210e, 0xb7442788, 0xfd042108, 0x2c221382, + 0x5b652900, 0x82252008, 0x82f420bd, 0x0bc74313, 0x25002c24, 0x3b880603, 0x2b820820, 0x0421b984, 0x21138adb, 0x7145001d, 0x88e92005, 0x001a2413, + 0x821d002c, 0x022a2201, 0x204f84e2, 0x22378218, 0x8219002b, 0x0018245f, 0x8477002b, 0x055f429f, 0x21061f41, 0x3b844605, 0x23822420, 0x2b822c20, + 0x29821e20, 0x99012922, 0x2621e782, 0x26278500, 0x00230018, 0x82de042b, 0x00182211, 0x205d8225, 0x24738222, 0x021f0018, 0x68118244, 0x05210cbd, + 0x47238448, 0x1f210529, 0x866f8200, 0x822b2011, 0x820f8317, 0x3f022119, 0xfd455984, 0x4d04250a, 0x26000700, 0x08209b82, 0x2105c346, 0xdd564b04, + 0x001b2206, 0x228b822a, 0x8203002b, 0x8218200f, 0x821f200b, 0x0018241f, 0x82e4041e, 0x0bff430f, 0x3f849120, 0x21083343, 0x3f88bf02, 0xaf822020, + 0xbe021e22, 0x25410f82, 0x82262005, 0x053024df, 0x8406004a, 0x821b206f, 0x821e2005, 0x8206202d, 0x00182265, 0x2205821b, 0x82ae0429, 0x0018241b, + 0x82220030, 0x042322bd, 0x210d84dd, 0x5b830024, 0xe0042922, 0x47180d82, 0x0423083d, 0x820500ad, 0x00242623, 0x0418002a, 0x830b82e2, 0x21af825b, + 0x17842503, 0x4f822520, 0x4e042a22, 0x2b201784, 0x23225982, 0x0b82e104, 0x27002022, 0x26220182, 0x17849901, 0x3b822c20, 0x8b011c22, 0x24089551, + 0x0007032b, 0x82538204, 0x9901213b, 0x26200982, 0x02217783, 0x20ff8204, 0x084d821b, 0x32001835, 0x74005600, 0xa8008e00, 0xd800c000, 0x0401f000, + 0x28011601, 0x4c013a01, 0x6c015c01, 0x88017a01, 0xa2019601, 0xba01ae01, 0xd001c601, 0x7800d801, 0x82001100, 0x2000214b, 0x08205384, 0x2c22fb82, + 0x8b822700, 0x08001c22, 0x20287982, 0x25001e00, 0x0e006a03, 0x18206582, 0x15830b82, 0x26002722, 0x2b202582, 0x18200382, 0x2b243582, 0x0c009903, + 0x08217982, 0x092b7f00, 0x23001a22, 0x27201982, 0x0c205b82, 0x33825b95, 0x338e0b20, 0x33821820, 0xa4022b24, 0x31820b00, 0x2b002a22, 0x2b223f82, + 0x07842c00, 0x25002624, 0x1784d301, 0x79821d20, 0x230c0d64, 0x09004b05, 0x95837782, 0x8f821a20, 0xc3821c20, 0xf1032422, 0x2522b982, 0x41821d00, + 0x45842520, 0xfc023022, 0x37831182, 0x23822c20, 0x43822a20, 0x14032922, 0x1b202384, 0x6b836182, 0x30002924, 0x11822d03, 0x03821b20, 0x43821920, + 0x1e001b28, 0x2e031c00, 0xa38b0700, 0x82230521, 0x821a200f, 0x481a2051, 0x03230515, 0x41060047, 0x2a220815, 0x0d82b101, 0x3b822b20, 0x21832320, + 0x82ba0121, 0x8225200d, 0x821c203d, 0x052b24cd, 0x8205005d, 0x23c782a5, 0x9d012a00, 0x25220b82, 0x85821900, 0x24052f22, 0x1e200b82, 0x26244d82, + 0xbc012600, 0x24200b82, 0x79823f82, 0x00620223, 0x83378204, 0x007822ed, 0x22098203, 0x82da0229, 0x00232207, 0x38ed822a, 0x00320014, 0x006c0050, + 0x00980084, 0x00ae00a4, 0x000601b6, 0x001c000e, 0x83bb822b, 0x08dd45f3, 0x2c240f82, 0xb0042700, 0x1808374a, 0x2512d153, 0x0d000701, 0xed822c00, + 0xab840820, 0x8205875d, 0x24738281, 0x0042022b, 0x2157930b, 0x85820501, 0x29001822, 0x51185f82, 0x042108e7, 0x20bd824f, 0x24f98226, 0x042b0025, + 0x20bd82af, 0x224f821c, 0x82870220, 0x002724b5, 0x82040130, 0x2c318307, 0x001a000c, 0x0052003a, 0x007e006a, 0x2cbd8292, 0x00c400b6, 0x00da00d0, + 0x005204e2, 0x1b65660f, 0x82970321, 0x8420208b, 0x0ce34de3, 0x86080121, 0x001a2217, 0x20ab821f, 0x20938225, 0x2207822a, 0x82f2032b, 0x002022a3, + 0x2253822e, 0x82190008, 0x00292405, 0x8451041b, 0x002a2113, 0x26059347, 0x0018001c, 0x82590224, 0x001c2231, 0x20238230, 0x820f8226, 0x79002125, + 0x20201182, 0x2608497b, 0x0425001e, 0x820600b2, 0x0018225d, 0x22d38225, 0x82b10418, 0x821820e9, 0x0019242b, 0x82500418, 0x822020e9, 0x012a224f, + 0x82e182f4, 0x89022147, 0x29200782, 0x433c7782, 0xb2008800, 0x0201da00, 0x4e012a01, 0x94017201, 0xd401b401, 0x1202f401, 0x4e023002, 0x5a102d6e, + 0x56080787, 0x03c403aa, 0x04f803de, 0x04280410, 0x04580440, 0x0484046e, 0x04b0049a, 0x04dc04c6, 0x050805f2, 0x0530051c, 0x05580544, 0x0580056c, + 0x05a80594, 0x05cc05ba, 0x06f005de, 0x06140602, 0x06340624, 0x06500642, 0x0668065c, 0x06800674, 0x0694068a, 0x004d039e, 0x82260014, 0x052348b9, + 0x099b5918, 0x79501820, 0x084d7306, 0x004b0323, 0x20299c13, 0x241d821b, 0x0325002e, 0x28279e4c, 0x001c0023, 0x042b001d, 0x2027848e, 0x0e3b591a, + 0x2310c97a, 0x11004e03, 0x2c24779c, 0x0d012700, 0x4b8d2384, 0x20002722, 0x0820d782, 0x2628c782, 0x22001a00, 0x10009702, 0xe1894794, 0x0f00f322, + 0xff419b82, 0x002b2205, 0x0fff5a1f, 0x82960221, 0x132b411f, 0x0221d186, 0x411f9694, 0x05230619, 0x820e004c, 0x73272053, 0xa9420813, 0x6003210c, + 0x1c221d82, 0x81822d00, 0x65182320, 0x18200ce1, 0x2b22c182, 0x1d825e02, 0x1820c783, 0x20203d82, 0x0820c784, 0x09276718, 0x4bfe0421, 0x2420089f, + 0x22201584, 0x24244186, 0x0a011c00, 0x1d201b92, 0x18245382, 0x7b001e00, 0x20201b82, 0x1c205182, 0x11995218, 0x840c0121, 0x8225201b, 0x822a208f, + 0x6e23204d, 0x2524080f, 0x95021e00, 0x09411b82, 0x002c2613, 0x00630327, 0x419f820c, 0x1b200d8b, 0x2b201182, 0x0c20a582, 0x25229d82, 0x93551b00, + 0x24c38308, 0x042b0023, 0x22338277, 0x641b0018, 0x2e20084f, 0x2b202782, 0x29227182, 0x19822002, 0x5f002021, 0x252205e1, 0x39822c00, 0x29001c28, + 0x1a002000, 0xbb5a5504, 0x0ecb6808, 0x82610321, 0x09494119, 0x7a002c21, 0x01210847, 0x209b92bd, 0x224d8227, 0x82570425, 0x002c2219, 0x2001821e, + 0x155a1818, 0x00182608, 0x002b0029, 0x41678447, 0x1f2009b5, 0x2c20cb82, 0x1c229182, 0x9b8ab801, 0x230af96f, 0x09012a00, 0x200a754c, 0x825f8324, + 0x820820cb, 0x01252437, 0x420b000b, 0x1d200c03, 0x23241d82, 0x8c041c00, 0x1a20178e, 0x1b202d82, 0x8d201782, 0x30201784, 0x29223f82, 0xcb7d0800, + 0x00272208, 0x22178248, 0x8225002c, 0x822a2011, 0x09055117, 0x0a005222, 0x6a182b82, 0x02210e53, 0x41158211, 0xcf520745, 0x54042108, 0x18221582, + 0x43822c00, 0x43821f20, 0x37821920, 0x24001824, 0x2b846102, 0x22002522, 0x17561382, 0xd4022108, 0x1c201586, 0x41831582, 0x29001826, 0x7b022b00, + 0xb3426d84, 0x2603210e, 0xb5701582, 0x56042110, 0x2e226d8c, 0xbd822000, 0x1f022222, 0x20067345, 0x2057822b, 0x24f3821b, 0x002a002b, 0x20138213, + 0x8307821c, 0x068743d9, 0x84bb0221, 0x001d2127, 0x29207f83, 0x1e223b84, 0x1384a102, 0x4d002921, 0x00210abb, 0x067b467a, 0xbd842020, 0xdb822020, + 0x4c032522, 0x13414f84, 0x82232005, 0x00252463, 0x8436021e, 0x050b473b, 0x2c001928, 0x19002300, 0x13826203, 0x1a002622, 0x2622f984, 0x6b822700, + 0x83022521, 0x82202047, 0x209f838b, 0x2253820a, 0x82a0010b, 0x20118705, 0x22378218, 0x82a6022b, 0x82182011, 0x821e20cd, 0x82182047, 0x041c2271, + 0x4311828e, 0x04210cad, 0x422386b3, 0x022108fb, 0x4211827a, 0x02210ca5, 0x08614a20, 0xa5820820, 0x1f022322, 0xa1820f8a, 0x004e0223, 0x093b4206, + 0x820e0121, 0x2063830d, 0x239d832c, 0x05008f04, 0xd9827d82, 0x022a0023, 0x220b8231, 0x821e001c, 0x0423222b, 0x08955b53, 0xfe011f22, 0x24201784, + 0x25245b82, 0x04001602, 0x21053974, 0x0982e001, 0x2b821c20, 0xb8011d22, 0x2a241384, 0xa1012b00, 0x5b830982, 0x00226008, 0x01dc006d, 0x014a0116, + 0x01a8017a, 0x020402d6, 0x025a0230, 0x02ae0284, 0x030003d8, 0x03500328, 0x03a00378, 0x04ec03c6, 0x04340410, 0x04780456, 0x04bc049a, 0x050005de, + 0x05400520, 0x05800560, 0x05bc059e, 0x06f805da, 0x06340616, 0x06700652, 0x06a8068c, 0x06e006c4, 0x071807fc, 0x18500734, 0x0812bf5e, 0x7008566b, + 0xa0088808, 0xd008b808, 0xfc08e608, 0x28091209, 0x54093e09, 0x80096a09, 0xac099609, 0xd409c009, 0xfc09e809, 0x240a100a, 0x480a360a, 0x6c0a5a0a, + 0x900a7e0a, 0xb00aa00a, 0xd00ac00a, 0xee0ae00a, 0x0a0bfc0a, 0x260b180b, 0x420b340b, 0x5e0b500b, 0x760b6a0b, 0x8e0b820b, 0xa60b9a0b, 0xba0bb00b, + 0xce0bc40b, 0x0f01d60b, 0x28f78300, 0x0025001e, 0x001d0020, 0x58058230, 0x3f54058f, 0x14c35a0b, 0x00c10426, 0x00180019, 0x2320399d, 0x230d0545, + 0x1700c004, 0x115833a0, 0x1001230a, 0x2fa01600, 0x21088943, 0x2da29501, 0x20093b57, 0x242d82f5, 0x001a0020, 0x22a38229, 0x821f0027, 0x00252205, + 0x0e99621c, 0x2308fb43, 0x15009401, 0x272a89a0, 0x2c002300, 0x11012a00, 0x2b821400, 0x5c002921, 0x25220579, 0x55821b00, 0x5b822d20, 0x82002521, + 0x180b821d, 0x2009ad40, 0x2329861c, 0x0020002b, 0x41054760, 0x1a200b77, 0x2b201582, 0x35829f82, 0x82650321, 0x00262229, 0x08f16419, 0xb9842a20, + 0x55841c20, 0x17820820, 0x2b002c22, 0x26240182, 0xf5032500, 0xd7932982, 0x23104759, 0x13008801, 0x560ebf62, 0x03211435, 0x822782f7, 0x206b8259, + 0x20bd8430, 0x20e78220, 0x20098223, 0x833d822e, 0x820820d7, 0x00232407, 0x9615012b, 0x05054d27, 0x2a002524, 0x43821d00, 0x16012922, 0x1c21279a, + 0x052f4100, 0x27002c24, 0x9f848c00, 0xf3821e20, 0x6d861a20, 0x2a201b85, 0x18211b82, 0x08795400, 0x00f90323, 0x06bd4112, 0xdb459f83, 0x42338208, + 0x03210a4b, 0x41258467, 0x18200941, 0x29206984, 0x20213982, 0x05037700, 0x2b002322, 0x1120eb82, 0x2d854b8a, 0x49822320, 0x81860a20, 0x0223ef82, + 0x411100ed, 0x2a2208df, 0x89822b00, 0x22002622, 0x28089545, 0x001f001e, 0x0059042b, 0x20238210, 0x43358227, 0x95860e03, 0x8a012b22, 0x3f432184, + 0x6403211a, 0xc9412182, 0x08ab6813, 0x825d0421, 0x821c2021, 0x8408206f, 0x12af7083, 0x96680221, 0x09d94243, 0x21821720, 0x2215dd41, 0x821c001f, + 0x012b22c3, 0xf75f1813, 0x4a292008, 0x2723081b, 0x83002000, 0x0026246f, 0x49f6032e, 0x1c2106f3, 0x141f4200, 0x84120121, 0x077b693f, 0x25001c24, + 0x3d842b00, 0x2b001828, 0x29002600, 0x3f8cf903, 0x200bbf41, 0x24638218, 0x0066032b, 0x4127820e, 0x032116b9, 0x5d1d8468, 0xb1410771, 0x213b8409, + 0x1d82e602, 0x43001821, 0x0321168b, 0x411d8264, 0x3b841361, 0x84630321, 0x0027253b, 0x00240008, 0x22204383, 0x4218fd82, 0x04210857, 0x421d9259, + 0x02210847, 0x201d845d, 0x20bf8220, 0x227d8208, 0x8227001c, 0x82302009, 0x22598349, 0x18ec0223, 0x210e4b60, 0x41420029, 0x002c2607, 0x005f0427, + 0x063d500d, 0x08207583, 0x1c243b82, 0x2b002a00, 0x1c224182, 0x1b823604, 0x31441583, 0x9b042112, 0x2a221b84, 0x2d822200, 0x2f820820, 0x8306bf41, + 0x500221b5, 0x43415384, 0x00192109, 0x21083144, 0x2d57fb02, 0x0ca3560c, 0x8e670321, 0x0a774437, 0x84ed0221, 0x055b416f, 0x220d0743, 0x841b011f, + 0x002c2237, 0x22878225, 0x18200018, 0x2208cd55, 0x8230002b, 0x430d20fd, 0x2d24163f, 0x0c00a502, 0x1920fb8c, 0xef830d82, 0x68031b22, 0xe7411984, + 0x010a2211, 0x201982da, 0x20638218, 0x0fe76e23, 0x84190121, 0x002a2233, 0x22ed8228, 0x822b0020, 0x8208204b, 0x001c2489, 0x8279022b, 0x82202019, + 0x0591450b, 0x210ab94a, 0x4d845804, 0x2112b943, 0x4d846603, 0x21094341, 0x35460027, 0x1c012106, 0xed8d1984, 0x73822a20, 0x14012522, 0x2922338e, + 0x87821c00, 0x26002924, 0x818ccf01, 0x230ac55e, 0x0b00eb02, 0x21131f41, 0x178ae902, 0xcb821b20, 0x19002c28, 0x1c002300, 0x1782f803, 0x4309c143, + 0x7f20093f, 0xb785178c, 0x2a002327, 0x0a006702, 0x10f54200, 0x8a900421, 0x002a2215, 0x245f821a, 0x011c0027, 0x211582bd, 0x03430018, 0x3e02210e, + 0x2c261582, 0x08001e00, 0xa9822a00, 0x2d822c20, 0x29001c24, 0x15826503, 0x200ba346, 0x229d8218, 0x9258042b, 0x021b2241, 0x412b8426, 0x7c200fcd, + 0x25202b84, 0x5d185382, 0x03210a5d, 0x4315846b, 0x02210e4b, 0x244184e0, 0x0026002b, 0x207f8229, 0x26038230, 0x001c0023, 0x8209007d, 0x056b443d, + 0x09821d20, 0x13821a20, 0x13827e20, 0x23203d83, 0x2020af84, 0x2522b782, 0x13825c04, 0x70053945, 0x04210845, 0x853b84b4, 0x00192267, 0x22bd822c, + 0x84160322, 0x89272013, 0x2a002339, 0x4f843b03, 0x77821a20, 0x75822620, 0x20001f26, 0x18012700, 0x26202182, 0x82084d76, 0x15052195, 0x20221182, + 0x1d822500, 0x03822420, 0x1c003124, 0x23845e04, 0x2c002524, 0x95822400, 0x2b002524, 0x1184e604, 0x25432c20, 0x93012109, 0x79831182, 0x33822b20, + 0x81822720, 0x50033022, 0x18221182, 0x47892f00, 0x00150323, 0x83d98207, 0x82272093, 0x05252215, 0x200f8226, 0x28d5822c, 0x001f0008, 0x022b0026, + 0x200f82e5, 0x229d821c, 0x822c001a, 0x03302205, 0x200f8418, 0x209d822a, 0x22258218, 0x84b5041c, 0x8225200f, 0x8229202b, 0x031f2447, 0x45060066, + 0x0421095f, 0x220d82ff, 0x822b001c, 0x002624a1, 0x82a40229, 0x822c200d, 0x821c2039, 0x0324224b, 0x201b84f4, 0x22398424, 0x825a0430, 0x0817450d, + 0x84410221, 0x001b221b, 0x22938222, 0x84e9012b, 0x431e201b, 0x0521056d, 0x200d8225, 0x83538220, 0x04252255, 0x436f84b6, 0x1c240573, 0x05006c05, + 0x63844f82, 0x82240221, 0x24a3830b, 0x011a0020, 0x200b82dd, 0x05a14320, 0x82890121, 0x8321830b, 0x861a2017, 0x0025242f, 0x825b041b, 0x001c220b, + 0x24c5821b, 0x00990223, 0x23078304, 0x9b021c00, 0x26200982, 0x25225382, 0x1384e402, 0x2a002924, 0x0984e504, 0x22002a26, 0x03001703, 0x27222782, + 0x07825702, 0x1f001c3a, 0x14000900, 0x4c003000, 0x7a006400, 0xa2008e00, 0xc000b200, 0x0d00e704, 0x2b22ff82, 0xe9842e00, 0x08002222, 0x20220982, + 0x13822900, 0x9a031b22, 0x26201b82, 0x1c22cb82, 0xe75c2a00, 0xff02240f, 0x85000b00, 0x8208201b, 0x002b2a1d, 0x001a0020, 0x00300022, 0x06c14280, + 0x210ca74d, 0x7b82fa03, 0x08202d83, 0x28225782, 0xc5842c00, 0x1382c920, 0x6d821c20, 0x2005e348, 0x24198227, 0x001e0229, 0x201b8207, 0x264d842d, + 0x02250026, 0x820600ee, 0x842c2017, 0x00292283, 0x08835781, 0x1d001c22, 0x10202982, 0x48243d82, 0x6a005a00, 0x8628cf82, 0x0e00fe02, 0x21001900, + 0x1a202f82, 0x08202f82, 0x25226582, 0xc9821e00, 0x09822620, 0xfd022724, 0x1d8c0c00, 0x01211988, 0x43db821d, 0x2e280509, 0x23001c00, 0xb9012300, + 0x73835b82, 0x0f821b20, 0x2b002524, 0x0f829104, 0x1a202185, 0x25249d82, 0x0500e804, 0x0806e141, 0xb7042948, 0x24000200, 0x32019800, 0xbe018001, + 0x2c02f601, 0x94026002, 0xfc02c802, 0x60032e03, 0xc4039203, 0x2404f403, 0x80045204, 0xd804ac04, 0x30050405, 0x84055a05, 0xd605ae05, 0x2606fe05, + 0x76064e06, 0xc2069c06, 0xa568e806, 0x7af20806, 0xc2079e07, 0x0608e407, 0x4a082808, 0x8e086c08, 0xce08ae08, 0x0e09ee08, 0x4c092e09, 0x88096a09, + 0xc409a609, 0x000ae209, 0x3c0a1e0a, 0x760a5a0a, 0xae0a920a, 0xe60aca0a, 0x1e0b020b, 0x560b3a0b, 0x8a0b700b, 0xbe0ba40b, 0xf20bd80b, 0x260c0c0c, + 0x5a0c400c, 0x8e0c740c, 0xc20ca80c, 0xf20cda0c, 0x220d0a0d, 0x520d3a0d, 0x820d6a0d, 0xb20d9a0d, 0xe20dca0d, 0x120efa0d, 0x400e2a0e, 0x6c0e560e, + 0x980e820e, 0xc40eae0e, 0xf00eda0e, 0x1c0f060f, 0x480f320f, 0x700f5c0f, 0x980f840f, 0xc00fac0f, 0xe80fd40f, 0x1010fc0f, 0x34102210, 0x58104610, + 0x7c106a10, 0x9c108c10, 0xbc10ac10, 0xdc10cc10, 0xf810ea10, 0x14110611, 0x2c112011, 0x44113811, 0x5c115011, 0x74116811, 0x88117e11, 0x9c119211, + 0xb011a611, 0xc011b811, 0x26003d01, 0x29001c00, 0x07822a00, 0x0800252a, 0x18002e00, 0x22002300, 0x2008954d, 0x220f821b, 0x821f002a, 0x4c1b2023, + 0x05530aa9, 0x2015820a, 0x202d8229, 0x2423821e, 0x003b012b, 0x184d9c1e, 0x200de95a, 0x6d691826, 0x9e03230d, 0x6f7b1b00, 0x20638215, 0x222b8219, + 0x822b002b, 0x11eb5f9b, 0x1a003c22, 0xab8975a8, 0x19003722, 0x2420358c, 0x2320c582, 0x2b200382, 0x2922f182, 0x73823000, 0x6105bd47, 0x01210a93, + 0x8b338e23, 0x1d7a18cf, 0x244b830f, 0x011c0025, 0x18339a24, 0x870f7779, 0x8e2a2033, 0x0d716633, 0x21140169, 0xb7821e03, 0x201bc941, 0x20db842e, + 0x20d7821f, 0x8229821a, 0x49002199, 0x26203184, 0x70088f68, 0x23200dcf, 0x2111d152, 0x67624001, 0x6a1c2008, 0x35202635, 0x6541958e, 0x09fd4911, + 0x2500202b, 0x46011e00, 0x23001700, 0x05eb4700, 0x9e20f7a3, 0xa57d2f82, 0x10354214, 0x57821820, 0x3e012b24, 0xf7411600, 0x0ff1420c, 0x1e207b85, + 0x1e24b782, 0x2d011c00, 0x918d2d8e, 0x230e217f, 0x15008603, 0x83083943, 0x82cf82d7, 0x82272085, 0x001b224b, 0x06bb421b, 0x0d821920, 0x23002324, + 0x2b823601, 0x410baf41, 0x29201119, 0x1d204b82, 0x01213583, 0x222b8e84, 0x451f002b, 0x1d6a0651, 0x842e2005, 0x001b2675, 0x032e0026, 0x832b8e91, + 0x002b2215, 0x2087822a, 0x2033841d, 0x09c74324, 0x00300523, 0x0c0b4114, 0x22002a22, 0x20214982, 0x47b78500, 0x1b2005af, 0x1a221182, 0x298e3201, + 0xc5851d20, 0x6150ed88, 0x25012108, 0x1922298e, 0x63822900, 0x81821820, 0x1d002b22, 0x1c220982, 0x35851b00, 0x002e0123, 0x417d8c13, 0x2f220d5b, + 0x63822400, 0x22002924, 0x279c2b01, 0x21085f51, 0x279c2901, 0x2108a54a, 0x278e3305, 0xef822a20, 0x2e002623, 0x08f94b00, 0x03219f85, 0x4227829d, + 0x01252259, 0x00120041, 0x06534323, 0x47180820, 0xc5890ee9, 0x25822c20, 0x45001c21, 0xed8d0969, 0x41822720, 0x2a002c24, 0x258e2f01, 0x5b071145, + 0x2c20051d, 0x2b223f84, 0x719a3f01, 0x0123e788, 0x43110049, 0x95891649, 0x23984720, 0x20095741, 0x8b238233, 0x476118b9, 0x219d8809, 0x238e2801, + 0x20052353, 0xd3691823, 0x4501210b, 0xb3886b98, 0x00ba0423, 0x2ab38210, 0x001a0018, 0x0008001c, 0x821d0026, 0x822e2005, 0x00292a07, 0x001f002a, + 0x03270020, 0x202182b8, 0x2011821c, 0xbf431827, 0x00182208, 0x20018229, 0x20298230, 0x22178219, 0x8444012f, 0x13414443, 0x23241f83, 0x48012b00, + 0x87412198, 0x84342007, 0x09ad4165, 0x2922f383, 0x85821800, 0x1d422a20, 0x5f052105, 0x1f202182, 0x1808c353, 0x2312074a, 0x0f003001, 0x200cdf42, + 0x24a5821b, 0x002e0026, 0x21418525, 0x1f82fd03, 0x41822920, 0x20092b49, 0x2219821b, 0x821e0018, 0x00182427, 0x8e900024, 0x8227203f, 0x821c2017, + 0x8225201d, 0x00252487, 0x8266042b, 0x0977421f, 0x6b821b20, 0x19822720, 0x2b002924, 0x29832c00, 0x8e760421, 0x002a223f, 0x205f822e, 0x20598224, + 0x24838220, 0x0021011e, 0x4533820e, 0x8b8309ff, 0x19001922, 0x3022b384, 0x1d84bd04, 0x67090141, 0x04210c27, 0x221d82b8, 0x822a0018, 0x0018226b, + 0x2075841d, 0x20058220, 0x245f8225, 0x0524002a, 0x223b8e2e, 0x8222002a, 0x822b201d, 0x0025241d, 0x903a011e, 0x821f201d, 0x00232273, 0x2205822b, + 0x8e0f0429, 0x0c9f451d, 0x8e200121, 0x002723b3, 0x8552002c, 0xea042108, 0x29203b8e, 0x25201d82, 0x21076f41, 0x1d8e5b05, 0x8f821b20, 0x1e001e22, + 0x31209586, 0xe1441d8e, 0x7d02230c, 0x9d820d00, 0x1a002522, 0x23212d82, 0x0c396300, 0x50b70321, 0x18200695, 0x1f221d82, 0xc7842c00, 0x42000821, + 0xc020058b, 0x08203786, 0x26201582, 0x0021378d, 0x471b8449, 0x0521147f, 0x411b842f, 0x2a20097d, 0x21099945, 0x1b82be04, 0x18002924, 0x7d453000, + 0x821f2008, 0x0025260d, 0x052a001b, 0x20378e57, 0x20238219, 0x21278522, 0x1b8ee004, 0x1b8a1f20, 0x1b826520, 0x43094b42, 0x20220551, 0x57822d00, + 0x39012324, 0xc7420c00, 0x0997460c, 0x198e2620, 0x21080546, 0x19846404, 0x24092f41, 0x002c0029, 0x21458323, 0x33900005, 0x26002627, 0x1f002b00, + 0x43198302, 0x03211451, 0x413384b8, 0x1a200929, 0x29269782, 0x30002900, 0x19826602, 0x31002c22, 0x5d830182, 0x27000822, 0x1c26d382, 0x1c001a00, + 0x19826704, 0x2114bd45, 0x818e9802, 0x2108c544, 0x19826004, 0x41821820, 0x8f822520, 0x2409e154, 0x0329001c, 0x89198220, 0x822d209b, 0x002328b1, + 0x0024002c, 0x8419031c, 0x002c2233, 0x45dd822a, 0x01210cfd, 0x4cb58e1e, 0x002108eb, 0x8319824b, 0x4d27203d, 0x00230fcf, 0x820b0083, 0x822a2047, + 0x822b2003, 0x820820e3, 0x00202655, 0x0225001e, 0x20178277, 0x20118223, 0x0d774930, 0x86430121, 0x842b2017, 0x08f9617d, 0x84220121, 0x0ddb4347, + 0x1d002624, 0x2f84ce01, 0x46058352, 0x05210a81, 0x83178260, 0x05f34adf, 0x2108017e, 0x1782d002, 0x22091141, 0x82290019, 0x002a24f5, 0x824f051f, + 0x00202217, 0x20018231, 0x2a918218, 0x0023002a, 0x001a0020, 0x8669031c, 0x84252047, 0x09f3558f, 0x8f842720, 0x2009cf42, 0x83cb821a, 0x844a2023, + 0x0018218f, 0x1f202f8f, 0x5f83bf8e, 0x01212382, 0x43478e38, 0x2a220507, 0xa784bd02, 0x75822720, 0x8f822920, 0x8f822720, 0x02215384, 0x45ef8a45, + 0x02270aa3, 0x000a0085, 0x822c0026, 0x821b2077, 0x822a202f, 0x001e24bd, 0x825e0525, 0x09e54115, 0x45821d20, 0x27002024, 0x15866005, 0x20051b41, + 0x242b821d, 0x02240023, 0x06614fd0, 0x2b002523, 0x08174100, 0x82420121, 0x09474315, 0x26002328, 0x22001a00, 0x15829f03, 0x0b842920, 0x1b001c22, + 0x23059d45, 0x7d022a00, 0x1c201582, 0x4d448182, 0x9500210c, 0x2c224184, 0x97822a00, 0x21088347, 0x2b864803, 0x7d841a20, 0x18000822, 0x2b229b82, + 0x15844e05, 0x87002721, 0x22bb83f7, 0x82b9032b, 0x00202215, 0x2001821e, 0x20438230, 0x242b8219, 0x01220025, 0x20998885, 0x2015822b, 0x2247842e, + 0x8405002b, 0x82292041, 0x821c20a5, 0x822b2089, 0x001e282b, 0x0001051c, 0x82260009, 0x82082001, 0x822b2085, 0x00292407, 0x82640424, 0x841c2013, + 0x08cb43ad, 0x824c0021, 0x002c2213, 0x207f8224, 0x20298208, 0x223d8226, 0x84840027, 0x862a2027, 0x8220203d, 0x05252285, 0x4113825e, 0xbb840957, + 0x82d30221, 0x00202113, 0x210cd95e, 0x63886204, 0x4b821d20, 0x95822520, 0xc0023022, 0x18221382, 0x0f822900, 0x24051747, 0x011f0027, 0x209f8496, + 0x203d822e, 0x06254829, 0x1b021d22, 0x09412784, 0x411a2005, 0x042105b9, 0x221d8261, 0x822a0018, 0x84272001, 0x032b22c5, 0x212f846a, 0x27670029, + 0x20eb8208, 0x20eb8608, 0x24078219, 0x032b0023, 0x8523824a, 0x214786e9, 0x47848200, 0x43842520, 0x24001822, 0x85208b82, 0xe7411182, 0x002c2609, + 0x00630427, 0x208f8207, 0x24178225, 0x00200025, 0x87458219, 0x21ef840f, 0x1f82fc03, 0xc7821820, 0x1d822220, 0x1e002524, 0x0f823603, 0x18002621, + 0x20091778, 0x08435305, 0x2b227b83, 0x2f84fb03, 0x53822320, 0xad822b20, 0x9b031c24, 0x77820600, 0xd9822320, 0x2b001c24, 0x0d82bc04, 0x0b822620, + 0x6f822320, 0x99021f22, 0xa1490d82, 0x48032108, 0x25220d84, 0x69821a00, 0x35022324, 0x37820500, 0x43832a20, 0x84c60121, 0x002c260b, 0x011c002a, + 0x860b82e5, 0xb90421c1, 0x1c200b82, 0x1a242582, 0x9c031c00, 0x20200b82, 0x2a225984, 0x0b82ad01, 0x20002928, 0x2b002500, 0x3b844d05, 0x8f821e20, + 0xff012922, 0x1f200b82, 0x2305fb48, 0x0400c501, 0x18222d82, 0xaf823000, 0x5d820983, 0x82920421, 0x82262013, 0x0427221f, 0x200982bd, 0x22598229, + 0x84c80230, 0x002c2427, 0x84bb041e, 0x23c9821d, 0x0300aa02, 0x2e221b82, 0x07824603, 0x03212f82, 0x20078249, 0x3a6d821c, 0x0016000a, 0x00600040, + 0x009e0080, 0x00cc00b6, 0x01f200e0, 0x00840300, 0x822c0014, 0x001b228d, 0x2005821b, 0x20df822b, 0x22fd821f, 0x18290019, 0x230f6974, 0x0f005202, + 0x26212982, 0x05154500, 0x8208f34f, 0x0018262d, 0x012b0023, 0x221f84d2, 0x822a001c, 0x84202021, 0x0cb945c7, 0x00510223, 0x4f3f8a0e, 0x3d840909, + 0x00520223, 0x825d930b, 0x910a2035, 0x20b58235, 0x20b59009, 0x18898216, 0x230c5b4d, 0x0600a701, 0x1a20c782, 0x1b268b82, 0xbf041c00, 0x33820500, + 0x00299008, 0x00250018, 0x00880043, 0x01de00b8, 0x01260102, 0x016a0148, 0x01aa018a, 0x02e801ca, 0x02240206, 0x025e0242, 0x0296027a, 0x02ca02b0, + 0x03fe02e4, 0x03300318, 0x03600348, 0x03900378, 0x03bc03a6, 0x03e803d2, 0x041404fe, 0x043e042a, 0x04660452, 0x048c047a, 0x04ae049e, 0x04ce04be, + 0x04ee04de, 0x050e05fe, 0x052a051c, 0x05460538, 0x05620554, 0x057c0570, 0x05940588, 0x05ac05a0, 0x05c405b8, 0x05d805ce, 0x05ea05e2, 0x01fa05f2, + 0x1817004e, 0x4c08ed6c, 0x8f500dbb, 0x00432315, 0x86180012, 0x1d200925, 0x2622dd82, 0x8b182400, 0x01230fe9, 0x9611004d, 0x001a2a55, 0x001c001f, + 0x0122001a, 0x4c23984f, 0x042708c7, 0x00100002, 0x8223002c, 0x18292031, 0x21155740, 0x21824403, 0x8c188f89, 0x03231275, 0x820f0071, 0x001a233f, + 0x7f74002b, 0x00082209, 0x20c5822b, 0x20178224, 0x881f962a, 0x3f032183, 0x26203f82, 0x77423d84, 0x674a1805, 0xa001230e, 0x5f920e00, 0x20002328, + 0x2b002a00, 0x1d820304, 0x4018c189, 0x04210ea1, 0x261d8c01, 0x0026001a, 0x82190024, 0x82252039, 0x031b2251, 0x8b1d8245, 0x958b1879, 0x6001230c, + 0x2f820d00, 0x08001b22, 0x2a24d782, 0x23001a00, 0x27203382, 0x2c243b82, 0x28052a00, 0x18221b82, 0x0d821b00, 0x240de366, 0x052b0023, 0x201b8261, + 0x2267821c, 0x822d0026, 0x00082131, 0x24205585, 0x2b244582, 0x0c009f04, 0x1824cb92, 0x6e051b00, 0x26221986, 0x57822900, 0x3b820820, 0x25002028, + 0x23003000, 0x19824a01, 0x0b821820, 0x22095d54, 0x822b002a, 0x0129224d, 0x2019824b, 0x6b098226, 0x292207e9, 0x91822900, 0x29001c22, 0x0c20d982, + 0x0c6f8c18, 0x2308cb43, 0x0b004c01, 0x18083942, 0x210a5980, 0x178a5101, 0x83002a21, 0x822220e7, 0x032a22a9, 0x8317843f, 0x059d416f, 0x9006d543, + 0x07b54117, 0x2f828620, 0x3f842c20, 0x1f001824, 0x756d0800, 0x000e2208, 0x204f820a, 0x05b5411e, 0x29200982, 0x1b220382, 0x15840305, 0x2c002725, + 0x49001900, 0x1824050b, 0x5a032500, 0x73421582, 0x21718609, 0x15828602, 0x2110cd6d, 0x15827602, 0x65822a20, 0x210c0d48, 0x418e4d03, 0x25002626, + 0x88021e00, 0x69834184, 0x99891c20, 0x00500123, 0x08114109, 0x09822320, 0x22001a24, 0x13822705, 0x210edf41, 0x27846001, 0x39841b20, 0x18002528, + 0x1c002200, 0x13825d02, 0x210e335e, 0x21822905, 0x20052345, 0x244d8229, 0x03240026, 0x20118445, 0x200d821b, 0x26378208, 0x032b0023, 0x820700fe, + 0x821a20ff, 0x00202603, 0x022b0027, 0x200f86ad, 0x05674230, 0x840b0421, 0x0026240f, 0x821b0029, 0x01292223, 0x200f849f, 0x830f821d, 0x051f2259, + 0x220f8202, 0x82200018, 0x821920d5, 0x042e2255, 0x200f82ea, 0x4f0d822c, 0x01210623, 0x222f84ec, 0x822e002b, 0x821c203d, 0x006c225f, 0x82d98506, + 0x032b220f, 0x410d8441, 0x012106d3, 0x082b5a93, 0x1c002d24, 0x0d82e701, 0x49821820, 0x2f821b20, 0xba032422, 0x20220d82, 0x01821900, 0x25002624, + 0x29845b03, 0x43822720, 0x53821820, 0x45848820, 0x1b822c20, 0x1c002328, 0x05008602, 0xcb822c00, 0x1c001c24, 0x0b826d05, 0xb9821820, 0x26002024, + 0x0b82bb03, 0x19822620, 0x1c002b24, 0x23840004, 0x00232d82, 0x84880229, 0x0019210b, 0x03210d82, 0x202384ff, 0x22718219, 0x826b032b, 0x821c200b, + 0x00232647, 0x009e0130, 0x246b8204, 0x0426001b, 0x200982e9, 0x22958220, 0x829b011e, 0x00263609, 0x021b0018, 0x00030087, 0x02190024, 0x00030003, + 0x012a002a, 0x22078252, 0x821e002c, 0x82032059, 0x196a086f, 0xac01d500, 0x1202e001, 0x6e024002, 0xc6029a02, 0x1c03f202, 0x70034603, 0xc0039803, + 0x1004e803, 0x5c043604, 0xa8048204, 0xf204ce04, 0x3a051605, 0x82055e05, 0xca05a605, 0x1206ee05, 0x56063406, 0x9a067806, 0xde06bc06, 0x22070007, + 0x64074407, 0xa4078407, 0xe407c407, 0x24080408, 0x64084408, 0xa4088408, 0xe008c208, 0x4118fe08, 0x923c0883, 0xca09ae09, 0x020ae609, 0x3a0a1e0a, + 0x720a560a, 0xaa0a8e0a, 0xe20ac60a, 0x1a0bfe0a, 0x26af7618, 0x0817df58, 0x5a0e42e6, 0x8a0e720e, 0xba0ea20e, 0xea0ed20e, 0x1a0f020f, 0x4a0f320f, + 0x780f620f, 0xa40f8e0f, 0xd00fba0f, 0xfc0fe60f, 0x28101210, 0x54103e10, 0x7e106a10, 0xa6109210, 0xce10ba10, 0xf610e210, 0x1e110a11, 0x46113211, + 0x6e115a11, 0x94118211, 0xb811a611, 0xdc11ca11, 0x0012ee11, 0x24121212, 0x48123612, 0x6c125a12, 0x8e127e12, 0xae129e12, 0xce12be12, 0xee12de12, + 0x0e13fe12, 0x2e131e13, 0x4e133e13, 0x6e135e13, 0x8e137e13, 0xaa139c13, 0xc613b813, 0xe213d413, 0xfe13f013, 0x1a140c14, 0x36142814, 0x52144414, + 0x6e146014, 0x8a147c14, 0xa4149814, 0xbc14b014, 0xd414c814, 0xec14e014, 0x0415f814, 0x18150e15, 0x2c152215, 0x40153615, 0x54154a15, 0x68155e15, + 0x7a157215, 0x55018215, 0x1a001900, 0x26001f00, 0x23210182, 0x0c554800, 0x29470d82, 0xb8042514, 0x27001800, 0x1e200382, 0x1c223782, 0x01822b00, + 0x2b822020, 0x26002426, 0x2a002500, 0x1c220d82, 0x0f822900, 0x23001d26, 0x20003000, 0x1e281382, 0x1600bc04, 0x2c002800, 0x29223382, 0x1b821c00, + 0x6d842720, 0x79836f83, 0x25822920, 0x0a514718, 0x905e0121, 0x0d87542d, 0x1d206783, 0x1c265984, 0x66051b00, 0x4d821500, 0x20056b77, 0x20638225, + 0x83618224, 0x6d1a2051, 0x0321111f, 0x202b82d5, 0x2085821a, 0x22858423, 0x8225002c, 0x001822fd, 0x22118223, 0x821a0025, 0x861b2013, 0x002024b7, + 0x827e0227, 0x18b38b2b, 0x820ef950, 0x08db4529, 0x00c30423, 0x20df8c14, 0x22918229, 0x822b0026, 0x522d2023, 0x1920086b, 0x1c226782, 0x298ebb04, + 0x47090941, 0x05210e41, 0x21298264, 0xd7850026, 0x24001822, 0x2c205182, 0x6918af82, 0x5d820a7b, 0x2b24bb83, 0x13006705, 0x20180141, 0x0ad76c2c, + 0x27825620, 0x4819eb41, 0x05210817, 0x834f8a62, 0x00272261, 0x21c5821f, 0x315a0008, 0x21778409, 0x4f9c5401, 0x23080f49, 0x12007f04, 0x29208582, + 0x20080d50, 0x20c78218, 0x0f1d7b08, 0x82830221, 0x0b6f4125, 0x2f821a20, 0x1c002922, 0x0df79618, 0x82380521, 0x001a2125, 0x2e201783, 0x29238f82, + 0x41002000, 0x08220537, 0x15842e00, 0x1a002526, 0xc3021f00, 0x2a204b8e, 0x7b42c184, 0x9b6d1805, 0x65052108, 0x61412582, 0x0a354115, 0x00900223, + 0x185d4111, 0x21061141, 0x23827f02, 0xdd421f20, 0x093b4a08, 0x200bc14f, 0x9723829e, 0x822320df, 0x001d24e7, 0x8e5f052b, 0x083f6323, 0x21099742, + 0x8f9c6605, 0x2a001c26, 0x60011a00, 0x2b202382, 0x1d228f82, 0x39821d00, 0x5d821820, 0x00231582, 0x8223002c, 0x06494913, 0x86c40421, 0x84292023, + 0x00252221, 0x4107821b, 0x2b830559, 0x25001c26, 0x81022b00, 0x93418f8e, 0x21fb860b, 0x8f8a6305, 0x61821820, 0x41072d42, 0x8e220b43, 0x43411000, + 0x14cb4208, 0x8a900221, 0x0fc54321, 0x82001821, 0x72042191, 0xd3832182, 0xd157af83, 0x0a556509, 0x82730421, 0x2f7b1821, 0x18d1820c, 0x210ca558, + 0x2182ec04, 0x2c002222, 0xeb44a582, 0x201d8305, 0x225d822a, 0x82260019, 0x001c24ef, 0x82d4032a, 0x1c214421, 0x92410221, 0x0ca37165, 0x9a640521, + 0x236382ed, 0xc3021a00, 0x08a57718, 0xa3821c20, 0x4209776a, 0x0523081f, 0x410f0062, 0x23210a31, 0x09834300, 0x8e204185, 0x1d441f8c, 0x0018220b, + 0x2061822a, 0x421f8282, 0x2c24176d, 0x1c032700, 0x1f201f82, 0x27206182, 0x20205982, 0x1e20fb82, 0x19218782, 0x263b8300, 0x001c0022, 0x8e59032b, + 0x05cd413f, 0x2108f144, 0x7f8c8c02, 0x26269f8b, 0x25002e00, 0x1f82c104, 0x4f821c20, 0x1a002924, 0x5b821f00, 0x210ee369, 0x5f8ec304, 0x26093145, + 0x00230018, 0x8a91022b, 0x0f0f425f, 0x27002c24, 0x3f8ea302, 0x60181c20, 0x51200eeb, 0x2b201f82, 0xf343df82, 0x10d96b05, 0x008f0223, 0x1691420e, + 0x03215d82, 0x421d8201, 0x19200905, 0x2608455e, 0x001c001a, 0x8261011b, 0x822c201d, 0x0008226f, 0x20ab8227, 0x06954518, 0x20002e22, 0x8c20b984, + 0x1941598c, 0x00182609, 0x051a002a, 0x221d822b, 0x822b0018, 0x05055847, 0x08220983, 0x3b821b00, 0x1f002a24, 0x1d829701, 0x1e002022, 0x08358b18, + 0x27822720, 0x1d002922, 0x1a240582, 0xfc032b00, 0x45471d82, 0x0018230d, 0x9d4c0029, 0xa2022306, 0x8f820d00, 0x5a001821, 0x4d820589, 0x822c0021, + 0x822b2067, 0x021c2293, 0x201b8221, 0x202b822b, 0x202d8220, 0x5d15821c, 0x04210a8d, 0x831b8472, 0x00082149, 0x20095743, 0x22378218, 0x826c032b, + 0x821f201b, 0x821c209b, 0x001b210d, 0x2d201f87, 0x1b228f82, 0x1b86a003, 0x210b4142, 0xe583001d, 0x25032b22, 0xc7851b82, 0x21410820, 0x08f57006, + 0x82300521, 0x16b55d1b, 0x7d580420, 0x428b8305, 0x1b210535, 0x05335200, 0xdf841182, 0xd3891f20, 0x2a208d82, 0x0221ef87, 0x4553828d, 0x734109c9, + 0x002c2409, 0x84850227, 0x821c20df, 0x6f2320fd, 0x2a2008bb, 0x1e240982, 0x77042500, 0x635a1b82, 0x2255820c, 0x82260027, 0x04232201, 0x0a1741c5, + 0x1d002622, 0x1b201982, 0x2d20dd82, 0x1b223982, 0xfb845901, 0x1c001c24, 0x31842b00, 0xf7852320, 0x1a221b82, 0x1b84ed01, 0x9b822620, 0x6f882720, + 0x1f821a20, 0x2b002924, 0x5384c201, 0x1b821c20, 0x11d55918, 0x0c001b23, 0x13914300, 0x69021e22, 0x20201984, 0x23226d82, 0x6f821b00, 0x21088f67, + 0x19823305, 0xad822520, 0x21100b5e, 0x19829501, 0x200b7f43, 0x248b8424, 0x022a002c, 0x4419827c, 0xb7500d19, 0x00022106, 0x7d46198e, 0x7f022108, + 0x18218184, 0x054d4300, 0x210ad546, 0x19824303, 0x1e002024, 0x97822500, 0x4d056d4c, 0x01210669, 0x201982ca, 0x20b3822b, 0x10736a27, 0xcf8e5c20, + 0x08874718, 0x8e790221, 0x21b58881, 0x198e3a03, 0x2108ad48, 0x818abd03, 0x18001f22, 0x1e208982, 0x1e22eb84, 0x1982c704, 0xf76d1a20, 0x00082408, + 0x8226002b, 0x0018240d, 0x8e4d001f, 0x08197581, 0x82940421, 0x07654619, 0x2005f541, 0x204d8223, 0x20c7821d, 0x24198450, 0x00270026, 0x2065822e, + 0x06d7442b, 0x09000b24, 0x9b8e5f01, 0x03234d88, 0x4a0b0085, 0x1d280c17, 0x23002c00, 0x1a032300, 0x8d831782, 0x714b2720, 0x5801210d, 0xa1491782, + 0x8223200b, 0x001a24b1, 0x84600122, 0x0018222f, 0x2401821d, 0x002a0008, 0x24818225, 0x021c0022, 0x2217843b, 0x822b001c, 0x822620d3, 0x821a2017, + 0x0027242f, 0x8268051c, 0x46078217, 0xe14108e7, 0x82c22007, 0x09a74817, 0x21080949, 0x778e5701, 0x39821d20, 0x1e001824, 0x17820c04, 0x29002b22, + 0xf7875582, 0x1c001d26, 0x06042300, 0x26204784, 0x08200b82, 0x09f95818, 0x52207f82, 0x26202f84, 0x20082742, 0x24a78223, 0x041f002a, 0x495f8405, + 0x022110b5, 0x221782c5, 0x821a0026, 0x821c2001, 0x05134333, 0x23002324, 0x17825005, 0x15821820, 0x08002223, 0x0a034400, 0x846d0421, 0x2055832f, + 0x20198229, 0x205d8227, 0x208f8425, 0x448f846a, 0x1b8208ef, 0x1b832d20, 0x82630221, 0x822c2017, 0x205d83a1, 0x224f822a, 0x82200029, 0x012b220d, + 0x43178294, 0x27200b1d, 0x2c24ef82, 0x08042a00, 0x24201782, 0x5345ed82, 0x20478206, 0x20478419, 0x20d784ff, 0x20918420, 0x20158230, 0x24238225, + 0x021c002b, 0x227784da, 0x8328001c, 0x20178285, 0x245f822a, 0x0325001e, 0x20178244, 0x06154320, 0x25002022, 0x18201982, 0x2b226182, 0x1782e102, + 0x29002b22, 0x1c222d82, 0x15822b00, 0x2f822d20, 0x2e001c22, 0x22204788, 0x0221478d, 0x0e3f4245, 0x0324a786, 0x000a006c, 0x840b9745, 0x5d01215d, + 0x28221582, 0x874a2c00, 0x00252608, 0x0120001d, 0x262b8e5b, 0x0026001b, 0x82be031e, 0x82242015, 0x8223207d, 0x00082271, 0x2409822e, 0x02220025, + 0x20418e7d, 0x221d8227, 0x82750425, 0x09f34215, 0x3f821920, 0x22002624, 0x578e5a01, 0x77821a20, 0x6c042b22, 0x1920578c, 0x18243f82, 0x53012400, + 0x18241582, 0x22001a00, 0xb943f382, 0x76022108, 0x29266d8e, 0x2a002a00, 0x15821603, 0x20053b41, 0x202d822a, 0x246d8227, 0x002b002a, 0x226d8451, + 0x82270026, 0x08a55b13, 0x00640227, 0x002c0009, 0x21378219, 0xdb41001a, 0x70042106, 0x27201382, 0x18220d82, 0x2b823000, 0x25229583, 0x1382c604, + 0x25003022, 0x1e20a182, 0x1e204f82, 0x1c223382, 0x1382c102, 0xf7822320, 0x6f181b20, 0x1f2208b1, 0x1382c202, 0x26091f43, 0x00230018, 0x820a042b, + 0x0e494813, 0x822d0221, 0x076f4613, 0x2a243f83, 0x2a051a00, 0xd9471382, 0x6b04210e, 0xcb851382, 0x2c201983, 0x1c229582, 0x6384a100, 0x2320c985, + 0x1a248d82, 0x3c032200, 0xc7451382, 0x05794305, 0x1c002222, 0x2626638e, 0x25002e00, 0x8b84f701, 0x210cab47, 0x13844203, 0x200d9744, 0x20f98296, + 0x22db8218, 0x82190023, 0x217b8261, 0x11822e02, 0x24092147, 0x021a002a, 0x42118244, 0x1f220b2d, 0x11822d05, 0x24002022, 0xaf460582, 0x041b2205, + 0x830b8274, 0x822720b5, 0x002026b9, 0x031c002a, 0x261182bc, 0x001c001c, 0x8223001b, 0x0025245f, 0x8219021e, 0x77481811, 0x3505210c, 0xcd851182, + 0x25822720, 0x2e002624, 0x4784dd01, 0x2b001922, 0x18264782, 0x2b001a00, 0x1182f801, 0x210c3746, 0x11889701, 0x35821820, 0x0e000824, 0x11824103, + 0x25003022, 0x08222f82, 0x13821800, 0x3c022b22, 0x20204784, 0xa1834782, 0x1c002a24, 0x11826904, 0x8d821820, 0x13820820, 0x25821c20, 0x2e052926, + 0x22000700, 0x2b200982, 0xc1209f86, 0xe7410f82, 0x8601210a, 0x2b200f82, 0x9b831f82, 0x29001c24, 0x0f829700, 0x1a001c22, 0x20263f82, 0x25002600, + 0x0f822503, 0x1e002022, 0x20207782, 0x1e220382, 0x0f88fb01, 0x51830820, 0x5f830220, 0x24074941, 0x0527002c, 0xdf41182c, 0xa203210d, 0x30200f82, + 0x3d845782, 0x6820a182, 0xa1850f82, 0x15821a20, 0xa1033022, 0x63440f82, 0xe701210a, 0x1f240f82, 0x1d002c00, 0x23240182, 0x53021c00, 0x27200f82, + 0x7d826983, 0x29001c24, 0x0f823405, 0x20054d41, 0x22b58224, 0x82760425, 0x822e200f, 0x0024231f, 0x1f820024, 0x84330221, 0x822b209f, 0x221f830b, + 0x846f0427, 0x8223203f, 0x822b20cb, 0x041f24d5, 0x51060004, 0x042109e1, 0x830d82ee, 0x841b205d, 0x8269203b, 0x0847440d, 0x828a0121, 0x0815450d, + 0x84930421, 0x0018221b, 0x22298227, 0x821d022a, 0x082d420d, 0x822f0521, 0x08c3490d, 0x84eb0421, 0x82292061, 0x00232471, 0x84980023, 0x84292037, + 0x032722a1, 0x836f84bc, 0x002c241b, 0x8287002b, 0x822b200d, 0x002026c5, 0x042a0029, 0x200d840b, 0x05234429, 0x82f50221, 0x002c240d, 0x822e0019, + 0x0230221f, 0x228b84f0, 0x842d0029, 0x84da20a7, 0x001c2253, 0x220d8228, 0x82310523, 0x8223200d, 0x00202609, 0x011f001e, 0x4b0d8297, 0x02200833, + 0x22202987, 0x23221f82, 0x37843403, 0x53822620, 0x29001c26, 0x05007104, 0x18268382, 0x27002400, 0x0b82da01, 0x29451f20, 0x55022105, 0x24200b82, + 0x5382af82, 0x840e0421, 0x82202017, 0x032b229f, 0x220b823d, 0x82260027, 0x04252201, 0x203b8409, 0x22178226, 0x82ed041c, 0x8223200b, 0x002a243b, + 0x8207041f, 0x0022220b, 0x22f7822c, 0x82c20423, 0x0026320b, 0x0022001a, 0x009f012a, 0x00300004, 0x021a0025, 0x2009822c, 0x22378226, 0x8204052b, + 0x82242009, 0x001e224d, 0x2609824e, 0x00250020, 0x820a0422, 0x821f2009, 0x01272213, 0x200982c7, 0x2109832b, 0x31844f00, 0x27001824, 0x2784bd03, + 0x25001e24, 0x2784de02, 0xb9822020, 0x27848c20, 0x29001824, 0x09821c02, 0x2d001828, 0x32051c00, 0xd5820300, 0x6e042a22, 0x27240782, 0x9a021800, + 0x2c200782, 0x46095f82, 0x013a019c, 0x01a60170, 0x020802d8, 0x02640236, 0x02be0292, 0x031203e8, 0x0366033c, 0x03b6038e, 0x040404de, 0x0450042a, + 0x049a0476, 0x05e204be, 0x052a0506, 0x0572054e, 0x05b60594, 0x06fa05d8, 0x063e061c, 0x06820660, 0x06c206a2, 0x070207e2, 0x07420722, 0x077e0760, + 0x07ba079c, 0x08f607d8, 0x082e0812, 0x0866084a, 0x089e0882, 0x08d608ba, 0x090e09f2, 0x0946092a, 0x097e0962, 0x09b6099a, 0x0aee09d2, 0x0a260a0a, + 0x0a5c0a42, 0x0a900a76, 0x0ac40aaa, 0x0bf80ade, 0x0b2c0b12, 0x0b5e0b46, 0x0b8e0b76, 0x0bbe0ba6, 0x0cee0bd6, 0x0c1c0c06, 0x0c480c32, 0x0c740c5e, + 0x0ca00c8a, 0x0ccc0cb6, 0x0df80ce2, 0x0d240d0e, 0x0d500d3a, 0x0d7a0d66, 0x0da20d8e, 0x0dca0db6, 0x0ef20dde, 0x0e1a0e06, 0x0e3e0e2c, 0x0e620e50, + 0x0e820e72, 0x0ea20e92, 0x0ec20eb2, 0x0ee20ed2, 0x0ffe0ef0, 0x0f1a0f0c, 0x0f360f28, 0x0f520f44, 0x0f6a0f5e, 0x0f820f76, 0x0f9a0f8e, 0x0fb20fa6, + 0x0fca0fbe, 0x0fe20fd6, 0x10f80fee, 0x100c1002, 0x10201016, 0x1034102a, 0x1046103e, 0x1056104e, 0x0030035c, 0x001f001a, 0x0029001c, 0x82260024, + 0x001c2203, 0x200d842b, 0x18078208, 0x8418d199, 0x821c2035, 0x05df602d, 0x9d09f345, 0x00862235, 0x22018218, 0x82230019, 0x22298361, 0x8225001c, + 0x00202101, 0x2005ff46, 0x4b531818, 0x8219200a, 0x00232627, 0x00650123, 0x202b8217, 0x6e8b8225, 0xd36d0dd9, 0x95042316, 0x39821600, 0xcb8dd183, + 0x73821820, 0x83002b21, 0x822d2043, 0x8229204f, 0x001e2423, 0x8293041c, 0xcb71182d, 0x0da54a0c, 0x200e1566, 0x952d8237, 0x0b3155f3, 0x01239986, + 0x94150066, 0x13bd6db9, 0x14006722, 0x2b262b94, 0x29002c00, 0x87822500, 0x01213586, 0x8f2982e4, 0x14bb56b1, 0x826d0321, 0x00182129, 0x83056b41, + 0x0aad77f9, 0x19204f82, 0x2b285982, 0x26002b00, 0x38002500, 0x24217d84, 0x11cb4100, 0x230e0956, 0x13003203, 0x20162b42, 0x834f8228, 0x822b202d, + 0x042922c7, 0x21278296, 0x85410018, 0x001d2619, 0x002a0018, 0x414f842b, 0x4f8d1551, 0x12009722, 0x4116d541, 0x00210acd, 0x24258253, 0x00200026, + 0x83838223, 0x822720f1, 0x20d38533, 0xa7701808, 0x21042109, 0x1e224b8a, 0x23842900, 0x08001f24, 0x39821b00, 0x03821e20, 0x11822b20, 0x54052322, + 0x29202582, 0x976fa584, 0x0d814209, 0x27002c26, 0x11007101, 0x2c204182, 0x2220e982, 0x0e6d6a18, 0x4d842920, 0xe3821f20, 0x23823320, 0x5318e395, + 0x0021088b, 0x2023828a, 0x2049822c, 0x20358222, 0x0645522a, 0x9b842020, 0x2026b983, 0x25001e00, 0x23828f01, 0xcf411820, 0x00082206, 0x20e3821a, + 0x20e98223, 0x2077822a, 0x20a78223, 0x21238229, 0x6b83031c, 0x8815cb43, 0x6d01216b, 0x27464782, 0x203b8206, 0x20518226, 0x224b822a, 0x822d0029, + 0x822b2045, 0x0026227f, 0x83fd8225, 0x001821d7, 0x29208b85, 0x2a211f82, 0x0e194a00, 0x002f0323, 0x42178210, 0x1d221335, 0x99822c00, 0x05052322, + 0x1f202198, 0x21051d41, 0x219a3103, 0x43821820, 0x21841d20, 0x1f20d195, 0x2322af82, 0x87841d00, 0x87862195, 0x84680121, 0x0f434465, 0xfd822a20, + 0x2106ab43, 0x87983700, 0x01212186, 0x4221826b, 0x3b83095b, 0x26002726, 0x2b002900, 0x19208582, 0x1c24a982, 0x0f006a01, 0x7d421182, 0x211f8c0b, + 0x1f82e702, 0x25053762, 0x001e002a, 0x9b18001c, 0x1820096d, 0x2b223f82, 0x1f829804, 0x43133343, 0x7120072b, 0x20221f82, 0x39822400, 0x29207d83, + 0x210fe35f, 0x1f820605, 0x20156742, 0x22978223, 0x84d8032e, 0x822e209f, 0x82292037, 0x821920f9, 0xfd9c18bb, 0x9604230c, 0x63430e00, 0x00232416, + 0x8274012b, 0x0029221d, 0x06e9422c, 0x20001d22, 0x2408a351, 0x0025002c, 0x951d8238, 0x002c247b, 0x846e0327, 0x09894459, 0x210c6d7f, 0x598cc003, + 0x83822920, 0x27002422, 0x2624a184, 0x53052f00, 0x18211d84, 0x05894200, 0x220f8f44, 0x820d006f, 0x181a2089, 0x220a659e, 0x82240020, 0x0023243d, + 0x8232031c, 0x1517421b, 0x30030a22, 0xaf951b82, 0x1b840c20, 0x0c223795, 0x53869b04, 0x09396218, 0xaf822420, 0x7f822a20, 0x6f842a20, 0x0a225395, + 0x6f983303, 0x1b840920, 0x09226f95, 0x37827001, 0x43002921, 0x232605ad, 0x19000800, 0xef862900, 0x9d042a22, 0x91411b84, 0x0c935c07, 0x982f0321, + 0x840d206f, 0x226f951b, 0x9831030d, 0x840b2037, 0x2237951b, 0x824f020b, 0x0b6b4637, 0x210a5d46, 0x1b8a2b02, 0x1a000822, 0x24089f6b, 0x032a0025, + 0x20c38cc0, 0x221b8223, 0x821b0018, 0x002524e1, 0x8c72011e, 0x135d181b, 0x9c04210c, 0x18221b84, 0x01821d00, 0x53822020, 0x23000822, 0x1e263582, + 0x2b001f00, 0x378c4002, 0x200daf58, 0x441b8453, 0x042314d7, 0x430c00ef, 0x18200ebf, 0x21051147, 0x19823a03, 0x54097943, 0x05210a13, 0x22198207, + 0x432c001f, 0x2a2008cb, 0x22062545, 0x828a0024, 0x14d14519, 0x829e0421, 0x09494319, 0xb7822720, 0x22001a28, 0x27002c00, 0x678cd001, 0x210ac965, + 0x1982f502, 0x18002922, 0x25242b82, 0x2a000800, 0x19227182, 0x0f822e00, 0x86033022, 0x15461982, 0x002b2209, 0x0751491c, 0x84630121, 0x82292019, + 0x000821c3, 0x210c3d41, 0x818cc103, 0x26002424, 0x59842d00, 0x75011e24, 0xcf460b00, 0x0027220a, 0x20638223, 0x20538225, 0x20178c89, 0x2023821d, + 0x22678226, 0x84e7022b, 0x82182017, 0x0cd3440b, 0x8e730121, 0x062d442f, 0x82930221, 0x001f2617, 0x0024002c, 0x5dc58219, 0x01210867, 0x46178290, + 0x032112db, 0x4a2f84a4, 0x0121109b, 0x281782b2, 0x002f001c, 0x0008002b, 0x219f821f, 0xfb410020, 0x00d52205, 0x20cd820a, 0x4a0d821e, 0x26260561, + 0x1d001d00, 0x1582b301, 0x2e202d87, 0x1b20e982, 0x1f223782, 0x15849a04, 0x0b831c20, 0x26224582, 0x47822700, 0x36052522, 0x25201584, 0xbf634182, + 0xc804210a, 0x29205784, 0x20203b82, 0x1e222b82, 0x35821800, 0x78041c22, 0x20201582, 0x5e18fb82, 0x03210c91, 0x4315826d, 0x18260b0b, 0x2b002300, + 0x1582f901, 0x0820f987, 0x18263d82, 0x22001a00, 0x1582a003, 0x45090b42, 0x0f2007e9, 0x23208384, 0x2d248f82, 0x2a002000, 0x26240382, 0x6f032500, + 0xeb446d84, 0x20578509, 0x20418487, 0x20238218, 0x22998225, 0x8229002b, 0x0524229b, 0x52f18a61, 0x04210843, 0x49998498, 0x01210e95, 0x20db846c, + 0x206d822e, 0x22418229, 0x821c001a, 0x012322af, 0x20c58a91, 0x83118208, 0x012b2487, 0x1809006e, 0x2008e3a5, 0x2473821a, 0x0230002b, 0x211382d6, + 0x73410026, 0x0525220b, 0x24138252, 0x002a0018, 0x20038222, 0x24918208, 0x032b0023, 0x23138260, 0x0029002c, 0x5547a783, 0x92022106, 0x0f421382, + 0x002c240b, 0x8af90127, 0x822b2013, 0x21f1823b, 0x77844003, 0x8d495183, 0x20138e08, 0x22a38218, 0x860d032b, 0x821b2027, 0x822420c5, 0x0029263b, + 0x00c60222, 0x200d8208, 0x82038223, 0x270025ad, 0x5b021c00, 0x29241184, 0x20002400, 0x18248d82, 0x8f012300, 0x59831182, 0x21084949, 0x11828800, + 0x21822020, 0xfb841c20, 0x1c002528, 0x07000805, 0xbf842600, 0x1b001826, 0x61032600, 0xcf870f82, 0x57822c20, 0x0f823920, 0x8305a343, 0x0429226b, + 0x240f820e, 0x002a0008, 0x2465821f, 0x042b0029, 0x201f86f0, 0x0523441a, 0x82910121, 0x2073850f, 0x22258220, 0x820d042b, 0x8226200f, 0x00232261, + 0x22058219, 0x82a3032f, 0x0947420f, 0x78022a24, 0x49820600, 0x2106ff41, 0x0d820f03, 0x356b2d20, 0x82fc2008, 0x8229200d, 0x82272035, 0x0530226d, + 0x480d8237, 0x032108ab, 0x880d826e, 0x6f012147, 0x2e212986, 0x82d98200, 0x890620a3, 0x510521a1, 0x252a2984, 0x22001800, 0x7a041f00, 0x51820500, + 0xad822620, 0x79041f22, 0x20200b82, 0x1c24fb82, 0x36051b00, 0x1c280b82, 0x1e002500, 0x11021c00, 0x18200b82, 0x22244182, 0xf4022a00, 0xff850b82, + 0x93012522, 0x24202f84, 0x2a226382, 0x0b82c704, 0x21068d58, 0x3b849904, 0x53831c20, 0x84690121, 0x8225200b, 0x022a220b, 0x263b8425, 0x001a002c, + 0x84380522, 0x0026222f, 0x20538223, 0x205f8423, 0x220b8219, 0x84cd021c, 0x2b6d8323, 0x00bf031f, 0x00180004, 0x011c0027, 0x20210983, 0x21458200, + 0x1384aa01, 0x2a001e24, 0x09826401, 0x13831c20, 0x82390521, 0x22938309, 0x84af0224, 0x002f241d, 0x84620120, 0x00292409, 0x84b00227, 0x001c261d, + 0x00c6021c, 0x22878203, 0x828a0030, 0x00292407, 0x82a90130, 0x00182a07, 0x000f031e, 0x012d0002, 0x08058290, 0x3d001f80, 0xc2007c00, 0x1401ec00, + 0x5c013a01, 0xa0017e01, 0xde01c001, 0x1a02fc01, 0x54023802, 0x8a027002, 0xbc02a402, 0xec02d402, 0x1c030403, 0x48033203, 0x74035e03, 0xa0038a03, + 0xcc03b603, 0xf803e203, 0x24040e04, 0x50043a04, 0x7a046604, 0xa2048e04, 0xca04b604, 0xf004de04, 0x14050205, 0x38052605, 0x5c054a05, 0x80056e05, + 0xa0059005, 0xbe05b005, 0xda05cc05, 0xf005e605, 0x7303fa05, 0xed822200, 0x6d000821, 0x25220d2f, 0xf9631b00, 0x09594e0c, 0x24099761, 0x001c001a, + 0x26db8225, 0x0329001c, 0x90140058, 0x46298945, 0x01250ad7, 0x00130076, 0x2039822a, 0xfb531829, 0x002b2208, 0x200f822e, 0x204b821c, 0x07114308, + 0x022a0025, 0x84120014, 0x06cf4351, 0x7e09a74e, 0x7a220c7b, 0x4d8a1000, 0x20002d22, 0x2e224982, 0x07821d00, 0xc1822520, 0x99821c20, 0x21821d20, + 0x0f822520, 0x2205cd4d, 0x8218002a, 0x82082063, 0x001a2205, 0x242b821a, 0x032a002a, 0x834388c4, 0x0018227f, 0x08a14529, 0x27822320, 0x1f002a26, + 0x0f007901, 0x1f4b658a, 0x20418210, 0x831f860e, 0x18232059, 0x220d4764, 0x8b00c503, 0x822a201d, 0x0029241d, 0x82250026, 0x002c245b, 0x8272022b, + 0x8225201d, 0x82262093, 0x8222208f, 0x822220db, 0x00302295, 0x2421821f, 0x041c0023, 0x221d827b, 0x82190024, 0x821c2093, 0x208f8323, 0x200d8208, + 0x24bf841c, 0x003d031f, 0x204d820d, 0x224b821c, 0x8420002a, 0x002a22d7, 0x82398227, 0xcb03215d, 0x67411b82, 0x82082005, 0x822920cf, 0x001b2231, + 0x2605822c, 0x031c002b, 0x880c00ca, 0x821d20af, 0x8220205b, 0x00252673, 0x042a001b, 0x20198af1, 0x22578220, 0x842c0021, 0x021b247b, 0x880b00df, + 0x20578333, 0x2217841a, 0x8a2c032b, 0x0a574817, 0x88540021, 0x822a2017, 0x082946d5, 0x8ccf0321, 0x001f2147, 0x23247b83, 0x3a021b00, 0x1b20178a, + 0x1a20c382, 0x2305cb44, 0x0a00ce03, 0x25207788, 0x25242d82, 0x18002100, 0x1589c182, 0x89821e20, 0x2c002626, 0xcd032700, 0xf55c2b8a, 0x77012108, + 0x89831588, 0x43842320, 0x78011c22, 0x2928158c, 0x30001800, 0x70032a00, 0x0b421588, 0xa402210a, 0x43421582, 0x0020260b, 0x0330002b, 0x202b8ac7, + 0x07c1411a, 0x84720221, 0x8423202b, 0x05b94fc1, 0x2b002324, 0x2b8ad003, 0x20090b41, 0x22838cd3, 0x821c001e, 0x03292285, 0x20578cc6, 0x2415821f, + 0x0222001a, 0x22158af2, 0x4624002f, 0x158b0681, 0x2108b36e, 0x33415505, 0x002c2a0c, 0x002a0029, 0x00c8031c, 0x08494109, 0xd3206b87, 0x2a241388, + 0x1a000800, 0x1e22b582, 0x1388c903, 0x1c000825, 0x82001b00, 0xf10221ed, 0x2720138a, 0x2c24eb82, 0xcc032a00, 0xef86138a, 0x82220221, 0xbf6d1813, + 0x00202609, 0x021c0025, 0x2059822c, 0x20798225, 0x20878226, 0x2151832b, 0x1182d203, 0x0f829182, 0x2b000822, 0x1c225f82, 0x118a7003, 0x5f821820, + 0x85822b20, 0xad880820, 0x35822720, 0xd1032522, 0x1824358c, 0x3e031e00, 0x51831182, 0x20205d83, 0x2a203582, 0x3589e382, 0x0221cd84, 0x43238234, + 0x03210c41, 0x6c8f843f, 0x4e240bcf, 0x27000700, 0xc5831582, 0x57822520, 0x0f865320, 0x2e242383, 0x3a022500, 0xaf870f82, 0x1b002427, 0x06000102, + 0x08b34300, 0x86610221, 0x8220200d, 0x01222213, 0x200d82fd, 0x228b8227, 0x82180026, 0x00152229, 0x24c58605, 0x008d012a, 0x210b8504, 0x09823002, + 0x1b002524, 0x07822600, 0x13820320, 0x39821b20, 0x004c4c08, 0x009a0076, 0x00de00be, 0x011401fa, 0x0148012e, 0x017c0162, 0x01ae0196, 0x01de01c6, + 0x020e02f6, 0x023e0226, 0x026a0254, 0x02960280, 0x02c002ac, 0x02e602d4, 0x030603f6, 0x03200314, 0x0338032c, 0x03500344, 0x0366035c, 0x4d140020, + 0x1c200809, 0x1a20d582, 0x25200d82, 0x20067544, 0x600f8223, 0x01250891, 0x0011007b, 0x83a78220, 0x0ddd7115, 0x42001a21, 0x00210677, 0x222384a3, + 0x822c0029, 0x000822a7, 0x06d14b1a, 0xd3431b20, 0x0087220c, 0x2017820f, 0x24f58223, 0x0030001c, 0x4e518419, 0x18200553, 0x23261382, 0x0d007c04, + 0x3b821c00, 0x25822b20, 0xf9542920, 0xca04230d, 0xad8c0c00, 0x2108c542, 0x1982e802, 0x4b181c20, 0x1b20083b, 0x2c202582, 0x23205b82, 0x59204982, + 0x2a201984, 0x0822d382, 0x47602700, 0x001c2208, 0x434d902a, 0x04210829, 0x833382f2, 0x821a207b, 0x0029222f, 0x2049821b, 0x21098526, 0x1982bb01, + 0x11822020, 0x61821c20, 0x1820e183, 0x08076c18, 0x0b005625, 0x87002000, 0x08b743fb, 0x82a50121, 0x00262417, 0x842c0023, 0x086b4c29, 0x0b207d82, + 0x2420cb8c, 0x2b242182, 0xc2031c00, 0x1b204784, 0x2620b982, 0x210b3741, 0x478ea601, 0x6d821f20, 0x1f001e24, 0x17826a04, 0x25001822, 0x1f202b84, + 0x2b204384, 0x1c226d82, 0x8f8ca200, 0x23088b41, 0x0a00a401, 0x2624778c, 0x1d001d00, 0x158da582, 0x23822320, 0xea022e22, 0x55412b82, 0x05474409, + 0x7c012a22, 0x20221582, 0x65821800, 0x61000821, 0x87200979, 0x23205786, 0xd741b982, 0x69052308, 0x49820900, 0x1a002022, 0x3f831582, 0x23002024, + 0x1384a601, 0x24091141, 0x0527002c, 0x21bf820a, 0xff820026, 0x30200782, 0x18242b82, 0x07000905, 0x1a20a784, 0x25206982, 0x57200982, 0x5f410f82, + 0x001c2a07, 0x00c9042a, 0x00200006, 0x261d821f, 0x03180029, 0x8205002b, 0x00182663, 0x021b0029, 0x06d149e3, 0x2a002c24, 0x0b825500, 0x95412020, + 0x828b2006, 0x0018220b, 0x22b7822c, 0x84bb012b, 0x821b2017, 0x03262269, 0x830b84a6, 0x002a24cf, 0x82040058, 0x002a2413, 0x82a5032b, 0x08e58509, + 0x4c00254c, 0xae008600, 0xf000d000, 0x30011001, 0x6c014e01, 0xa8018a01, 0xe001c401, 0x1602fc01, 0x4a023002, 0x7a026202, 0xa8029202, 0xd402be02, + 0xfc02e802, 0x22031003, 0x42033203, 0x5e035003, 0x7a036c03, 0x90038603, 0xa4039a03, 0x5d827d01, 0x03821f20, 0x2b001822, 0x1823e982, 0x18002e00, + 0x571153a4, 0x00231447, 0x8213008c, 0x056b49eb, 0x09822420, 0xfd821e20, 0x43821a20, 0x0e795218, 0x007e0423, 0x18198210, 0x180f59a1, 0x230a7169, + 0x0f003703, 0xb1442184, 0x00082205, 0x184d8224, 0x200bcb4b, 0x181f9038, 0x210c334c, 0x1f828e00, 0xc3821f20, 0x23001c26, 0x1f001a00, 0x20223d82, + 0x89822900, 0x2600242a, 0x1c002d00, 0x0e003903, 0xb7555f8c, 0x859f820c, 0x821c201d, 0xd1551831, 0x0023240d, 0x827d042b, 0x001c213b, 0x64091173, + 0x79820c5f, 0x6f820e20, 0x7b821c20, 0x1820798d, 0x2b248982, 0x0d006f05, 0x23228b82, 0x3f822200, 0x2b205d83, 0x05210d89, 0x201b821b, 0x2017821f, + 0x221d822a, 0x8b30001c, 0xf304217b, 0x53183784, 0x712215c7, 0xcb8c0c00, 0x2405bb47, 0x041c002a, 0x53198277, 0x2320097f, 0x1b226b82, 0x99821b00, + 0xa8032922, 0xc38b1982, 0x1a002a22, 0x1c248984, 0x0b00f504, 0x18089b41, 0x210aaf48, 0x17825605, 0x2d001822, 0x08213d82, 0x0aff4a00, 0x84ca0221, + 0x821d202f, 0x2c178333, 0x0029002b, 0x00250026, 0x00c3031e, 0x11e3410a, 0x82240221, 0x82182015, 0x821b201f, 0x082142dd, 0x82a00221, 0x11ad4115, + 0x09008d23, 0x0b874200, 0x2b002324, 0x1382a703, 0x63821820, 0x19821c20, 0x2c002622, 0x1c218982, 0x24278f00, 0x0225002e, 0x205f8289, 0x83678226, + 0x00202893, 0x0125001e, 0x820700e4, 0x822920e1, 0x82202013, 0x041e2203, 0x410f840f, 0x25200589, 0xa822af82, 0x1d510600, 0x10042109, 0x18220d82, + 0x01822300, 0x2b001c23, 0x200d8302, 0x241d8229, 0x001a0025, 0x20f1821f, 0x85d98206, 0x050c24f1, 0x8205000b, 0x822b2057, 0x0429241d, 0x840400f4, + 0x011b22f3, 0x2009827e, 0x20a78226, 0x832d8224, 0x822d8213, 0x00032493, 0x82250026, 0x820c202f, 0x00402a07, 0x0366005a, 0x000c003a, 0x20978424, + 0x0d474622, 0x8cd00121, 0x0acd4619, 0x8a7f0121, 0x0a014a19, 0x012a0023, 0x865b8293, 0xa903214d, 0x08200b82, 0x18248182, 0x03003000, 0x1a245b82, + 0xcb042c00, 0xfd830782, 0x13820820, 0x89821820, 0x87021e22, 0x1c201182, 0x820b2741, 0x00032111, 0x01241183, 0x32020400, 0x18243982, 0x01002700, + 0x1822f782, 0x05821900, 0x1b821b20, 0x1e001d24, 0xe7821f00, 0x22002126, 0x24002300, 0x26203d82, 0x28322382, 0x2a002900, 0x2c002b00, 0x2e002d00, + 0x30002f00, 0xfa053100, 0xcbe5c0c2, +};++}
+ cbits/tracy/profiler/src/icon.hpp view
@@ -0,0 +1,25 @@+// File: 'icon.png' (854 bytes)+// Exported using binary_to_compressed_c.cpp+static const unsigned int Icon_size = 854;+static const unsigned int Icon_data[856/4] =+{+ 0x474e5089, 0x0a1a0a0d, 0x0d000000, 0x52444849, 0x00010000, 0x00010000, 0x00000308, 0x58ac6b00, 0x00000054, 0x59487009, 0x0a000073, 0x0a000000, + 0x82430100, 0x00003ccc, 0x42730300, 0x08085449, 0x4fe1db08, 0x000000e0, 0x544c50b4, 0x00000045, 0x00000000, 0x00000000, 0xffe4d600, 0xb9f1d1bd, + 0xc8b0efcf, 0xe8c5adea, 0x9de7c4ab, 0xb191dfb9, 0xcda27ed8, 0x72c99e77, 0x9a72c79a, 0xbc8b5fc6, 0x56bc8b5e, 0x713cb684, 0xa67039a7, 0x35a66e37, + 0x6b34a46d, 0xa36b33a3, 0x009d642a, 0x6126d66e, 0xcc69009b, 0x00cb6800, 0x6300c364, 0xbc6000c1, 0x19ba6000, 0x5b009458, 0xab5800b1, 0x00a95700, + 0x5300a655, 0x8e4f0ea0, 0x008e4f0d, 0x5100a052, 0x9d51009e, 0x00994e00, 0x4d00974d, 0x944c0096, 0x00914b00, 0x4700914a, 0x8a47008b, 0x00894700, + 0x45008946, 0x14121186, 0x01110f0e, 0x00000101, 0x56a20400, 0x0000006f, 0x4e527404, 0x521b0053, 0xb06c3055, 0x020000a6, 0x41444929, 0xedda7854, + 0x2c95c5db, 0xc1441449, 0x66666a62, 0xf5fd6666, 0xe7ce5a9a, 0xc4dce8c8, 0xd822bb2b, 0x24378fd6, 0x3db35249, 0x027f3561, 0x584d7d68, 0x0000002d, + 0x00000000, 0x005f8000, 0xf7023f3e, 0xdef00099, 0xdffbdc09, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x0587f400, 0xe011afd6, 0x0ec0adf0, 0x700004eb, 0xb7585fbb, 0x6e5c0335, 0x3e65d616, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0xac2d3c78, 0x0c013ac7, 0xd9e75b23, 0xf3b37c5d, 0x01b2b6ec, 0x9beded6a, 0xbf8f3f15, 0xce3db801, 0xc00436ee, 0x277666c9, 0x000001a5, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xa39b8000, 0x078a6eec, 0xe8008c30, 0xb30ee6f5, 0x4af5eb9b, 0xf3371807, 0xa74cdd96, + 0xeae00313, 0x40aba32c, 0x199bdb00, 0x0009976d, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0e000000, 0x883a32f6, 0x01186001, + 0x568d1dd0, 0x195a3236, 0x0021ba8d, 0x5fe61dc6, 0xbc00a35f, 0x25ec543c, 0x66e5c018, 0x05cb2ec5, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xbb153bd7, 0x1860040e, 0xbb3d3001, 0x85b15ab0, 0x0038e9d9, 0x2adea6e3, 0x00e9d536, 0xbbb00608, 0xe16edc99, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x53f3c000, 0x9186cf72, 0xc5830070, 0xe4b5a5c5, 0x07171696, 0xadc600c1, 0xdeb725bf, + 0x1e200719, 0x524efdc0, 0xee0161f7, 0x03ba9336, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11000000, 0x92ef5e00, 0xc48c357a, + 0x4e5f9804, 0x804cbe6e, 0x00000202, 0x00000000, 0x00000000, 0x00000000, 0x0000043f, 0x00000000, 0x00000000, 0xe047e7c0, 0xe200133e, 0x00000007, + 0x00000000, 0xcd43f000, 0x6cd584f6, 0x24927c4c, 0x8a1907fd, 0xabe6918e, 0x00003480, 0x45490000, 0x42ae444e, 0x00008260, +};+
+ cbits/tracy/profiler/src/ini.c view
@@ -0,0 +1,274 @@+/**+ * Copyright (c) 2016 rxi+ *+ * 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 <stdio.h>+#include <stdlib.h>+#include <string.h>+#include <ctype.h>++#include "ini.h"++struct ini_t {+ char *data;+ char *end;+};+++/* Case insensitive string compare */+static int strcmpci(const char *a, const char *b) {+ for (;;) {+ int d = tolower(*a) - tolower(*b);+ if (d != 0 || !*a) {+ return d;+ }+ a++, b++;+ }+}++/* Returns the next string in the split data */+static char* next(ini_t *ini, char *p) {+ p += strlen(p);+ while (p < ini->end && *p == '\0') {+ p++;+ }+ return p;+}++static void trim_back(ini_t *ini, char *p) {+ while (p >= ini->data && (*p == ' ' || *p == '\t' || *p == '\r')) {+ *p-- = '\0';+ }+}++static char* discard_line(ini_t *ini, char *p) {+ while (p < ini->end && *p != '\n') {+ *p++ = '\0';+ }+ return p;+}+++static char *unescape_quoted_value(ini_t *ini, char *p) {+ /* Use `q` as write-head and `p` as read-head, `p` is always ahead of `q`+ * as escape sequences are always larger than their resultant data */+ char *q = p;+ p++;+ while (p < ini->end && *p != '"' && *p != '\r' && *p != '\n') {+ if (*p == '\\') {+ /* Handle escaped char */+ p++;+ switch (*p) {+ default : *q = *p; break;+ case 'r' : *q = '\r'; break;+ case 'n' : *q = '\n'; break;+ case 't' : *q = '\t'; break;+ case '\r' :+ case '\n' :+ case '\0' : goto end;+ }++ } else {+ /* Handle normal char */+ *q = *p;+ }+ q++, p++;+ }+end:+ return q;+}+++/* Splits data in place into strings containing section-headers, keys and+ * values using one or more '\0' as a delimiter. Unescapes quoted values */+static void split_data(ini_t *ini) {+ char *value_start, *line_start;+ char *p = ini->data;++ while (p < ini->end) {+ switch (*p) {+ case '\r':+ case '\n':+ case '\t':+ case ' ':+ *p = '\0';+ /* Fall through */++ case '\0':+ p++;+ break;++ case '[':+ p += strcspn(p, "]\n");+ *p = '\0';+ break;++ case ';':+ p = discard_line(ini, p);+ break;++ default:+ line_start = p;+ p += strcspn(p, "=\n");++ /* Is line missing a '='? */+ if (*p != '=') {+ p = discard_line(ini, line_start);+ break;+ }+ trim_back(ini, p - 1);++ /* Replace '=' and whitespace after it with '\0' */+ do {+ *p++ = '\0';+ } while (*p == ' ' || *p == '\r' || *p == '\t');++ /* Is a value after '=' missing? */+ if (*p == '\n' || *p == '\0') {+ p = discard_line(ini, line_start);+ break;+ }++ if (*p == '"') {+ /* Handle quoted string value */+ value_start = p;+ p = unescape_quoted_value(ini, p);++ /* Was the string empty? */+ if (p == value_start) {+ p = discard_line(ini, line_start);+ break;+ }++ /* Discard the rest of the line after the string value */+ p = discard_line(ini, p);++ } else {+ /* Handle normal value */+ p += strcspn(p, "\n");+ trim_back(ini, p - 1);+ }+ break;+ }+ }+}++++ini_t* ini_load(const char *filename) {+ ini_t *ini = NULL;+ FILE *fp = NULL;+ int n, sz;++ /* Init ini struct */+ ini = malloc(sizeof(*ini));+ if (!ini) {+ goto fail;+ }+ memset(ini, 0, sizeof(*ini));++ /* Open file */+ fp = fopen(filename, "rb");+ if (!fp) {+ goto fail;+ }++ /* Get file size */+ fseek(fp, 0, SEEK_END);+ sz = ftell(fp);+ rewind(fp);++ /* Load file content into memory, null terminate, init end var */+ ini->data = malloc(sz + 1);+ ini->data[sz] = '\0';+ ini->end = ini->data + sz;+ n = fread(ini->data, 1, sz, fp);+ if (n != sz) {+ goto fail;+ }++ /* Prepare data */+ split_data(ini);++ /* Clean up and return */+ fclose(fp);+ return ini;++fail:+ if (fp) fclose(fp);+ if (ini) ini_free(ini);+ return NULL;+}+++void ini_free(ini_t *ini) {+ free(ini->data);+ free(ini);+}+++const char* ini_get(ini_t *ini, const char *section, const char *key) {+ char *current_section = "";+ char *val;+ char *p = ini->data;++ if (*p == '\0') {+ p = next(ini, p);+ }++ while (p < ini->end) {+ if (*p == '[') {+ /* Handle section */+ current_section = p + 1;++ } else {+ /* Handle key */+ val = next(ini, p);+ if (!section || !strcmpci(section, current_section)) {+ if (!strcmpci(p, key)) {+ return val;+ }+ }+ p = val;+ }++ p = next(ini, p);+ }++ return NULL;+}+++int ini_sget(+ ini_t *ini, const char *section, const char *key,+ const char *scanfmt, void *dst+) {+ const char *val = ini_get(ini, section, key);+ if (!val) {+ return 0;+ }+ if (scanfmt) {+ sscanf(val, scanfmt, dst);+ } else {+ *((const char**) dst) = val;+ }+ return 1;+}
+ cbits/tracy/profiler/src/ini.h view
@@ -0,0 +1,28 @@+/**+ * Copyright (c) 2016 rxi+ *+ * This library is free software; you can redistribute it and/or modify it+ * under the terms of the MIT license. See `ini.c` for details.+ */++#ifndef INI_H+#define INI_H++#define INI_VERSION "0.1.1"++#if defined(__cplusplus)+extern "C" {+#endif++typedef struct ini_t ini_t;++ini_t* ini_load(const char *filename);+void ini_free(ini_t *ini);+const char* ini_get(ini_t *ini, const char *section, const char *key);+int ini_sget(ini_t *ini, const char *section, const char *key, const char *scanfmt, void *dst);++#if defined(__cplusplus)+}+#endif++#endif
+ cbits/tracy/profiler/src/main.cpp view
@@ -0,0 +1,1591 @@+#include <algorithm>+#include <assert.h>+#include <atomic>+#include <chrono>+#include <inttypes.h>+#define IMGUI_DEFINE_MATH_OPERATORS 1+#include <imgui.h>+#include <mutex>+#include <stdint.h>+#include <stdio.h>+#include <stdlib.h>+#include <string>+#include <unordered_map>+#include <memory>+#include <sys/stat.h>+#include <locale.h>++#ifdef _WIN32+# include <windows.h>+#endif++#define STB_IMAGE_IMPLEMENTATION+#define STBI_ONLY_PNG+#include "stb_image.h"++#define STB_IMAGE_RESIZE_IMPLEMENTATION+#include "stb_image_resize.h"++#include "ini.h"++#include "../../public/common/TracyProtocol.hpp"+#include "../../public/common/TracyVersion.hpp"+#include "profiler/TracyAchievements.hpp"+#include "profiler/TracyBadVersion.hpp"+#include "profiler/TracyConfig.hpp"+#include "profiler/TracyFileselector.hpp"+#include "profiler/TracyImGui.hpp"+#include "profiler/TracyMouse.hpp"+#include "profiler/TracyProtoHistory.hpp"+#include "profiler/TracyStorage.hpp"+#include "profiler/TracyTexture.hpp"+#include "profiler/TracyView.hpp"+#include "profiler/TracyWeb.hpp"+#include "profiler/IconsFontAwesome6.h"+#include "../../server/tracy_pdqsort.h"+#include "../../server/tracy_robin_hood.h"+#include "../../server/TracyFileHeader.hpp"+#include "../../server/TracyFileRead.hpp"+#include "../../server/TracyPrint.hpp"+#include "../../server/TracySysUtil.hpp"+#include "../../server/TracyWorker.hpp"++#include "icon.hpp"+#include "zigzag01.hpp"+#include "zigzag02.hpp"+#include "zigzag04.hpp"+#include "zigzag08.hpp"+#include "zigzag16.hpp"+#include "zigzag32.hpp"++#include "Backend.hpp"+#include "ConnectionHistory.hpp"+#include "Filters.hpp"+#include "Fonts.hpp"+#include "HttpRequest.hpp"+#include "IsElevated.hpp"+#include "ImGuiContext.hpp"+#include "ResolvService.hpp"+#include "RunQueue.hpp"++#include "GitRef.hpp"+++struct ClientData+{+ int64_t time;+ uint32_t protocolVersion;+ int32_t activeTime;+ uint16_t port;+ uint64_t pid;+ std::string procName;+ std::string address;+};++enum class ViewShutdown { False, True, Join };++static tracy::unordered_flat_map<uint64_t, ClientData> clients;+static std::unique_ptr<tracy::View> view;+static tracy::BadVersionState badVer;+static uint16_t port = 8086;+static const char* connectTo = nullptr;+static char title[128];+static std::thread loadThread, updateThread, updateNotesThread;+static std::unique_ptr<tracy::UdpListen> broadcastListen;+static std::mutex resolvLock;+static tracy::unordered_flat_map<std::string, std::string> resolvMap;+static ResolvService resolv( port );+static char addr[1024] = { "127.0.0.1" };+static ConnectionHistory* connHist;+static std::atomic<ViewShutdown> viewShutdown { ViewShutdown::False };+static double animTime = 0;+static float dpiScale = -1.f;+static bool dpiScaleOverriddenFromEnv = false;+static float prevScale = 1.f;+static int dpiChanged = 0;+static bool dpiFirstSetup = true;+static Filters* filt;+static RunQueue mainThreadTasks;+static uint32_t updateVersion = 0;+static bool showReleaseNotes = false;+static std::string releaseNotes;+static uint8_t* iconPx;+static int iconX, iconY;+static ImTextureID iconTex;+static int iconTexSz;+static uint8_t* zigzagPx[6];+static int zigzagX[6], zigzagY[6];+ImTextureID zigzagTex;+static Backend* bptr;+static bool s_customTitle = false;+static bool s_isElevated = false;+static size_t s_totalMem = tracy::GetPhysicalMemorySize();+tracy::Config s_config;+tracy::AchievementsMgr* s_achievements;+static const tracy::data::AchievementItem* s_achievementItem = nullptr;+static bool s_switchAchievementCategory = false;++static float smoothstep( float x )+{+ return x * x * ( 3.0f - 2.0f * x );+}++static void SetWindowTitleCallback( const char* title )+{+ char tmp[1024];+ sprintf( tmp, "%s - Tracy Profiler %i.%i.%i", title, tracy::Version::Major, tracy::Version::Minor, tracy::Version::Patch );+ bptr->SetTitle( tmp );+ s_customTitle = true;+}++static void AttentionCallback()+{+ bptr->Attention();+}++static void DrawContents();++static void RunOnMainThread( const std::function<void()>& cb, bool forceDelay = false )+{+ mainThreadTasks.Queue( cb, forceDelay );+}++static void ScaleWindow(ImGuiWindow* window, float scale)+{+ ImVec2 origin = window->Viewport->Pos;+ window->Pos = ImFloor((window->Pos - origin) * scale + origin);+ window->Size = ImTrunc(window->Size * scale);+ window->SizeFull = ImTrunc(window->SizeFull * scale);+ window->ContentSize = ImTrunc(window->ContentSize * scale);+}++static void SetupDPIScale()+{+ auto scale = dpiScale * s_config.userScale;++ if( !dpiFirstSetup && prevScale == scale ) return;+ dpiFirstSetup = false;+ dpiChanged = 2;++ LoadFonts( scale );+ if( view ) view->UpdateFont( s_fixedWidth, s_smallFont, s_bigFont );++#ifdef __APPLE__+ // No need to upscale the style on macOS, but we need to downscale the fonts.+ ImGuiIO& io = ImGui::GetIO();+ io.FontGlobalScale = 1.0f / dpiScale;+ scale = 1.0f;+#endif++ auto& style = ImGui::GetStyle();+ style = ImGuiStyle();+ ImGui::StyleColorsDark();+ style.WindowBorderSize = 1.f * scale;+ style.FrameBorderSize = 1.f * scale;+ style.FrameRounding = 5.f;+ style.Colors[ImGuiCol_ScrollbarBg] = ImVec4( 1, 1, 1, 0.03f );+ style.Colors[ImGuiCol_Header] = ImVec4(0.26f, 0.59f, 0.98f, 0.25f);+ style.Colors[ImGuiCol_HeaderHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);+ style.Colors[ImGuiCol_HeaderActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.45f);+ style.Colors[ImGuiCol_TitleBgCollapsed] = style.Colors[ImGuiCol_TitleBg];+ style.ScaleAllSizes( scale );++ const auto ty = int( 80 * scale );+ iconTexSz = ty;+ auto scaleIcon = new uint8_t[4*ty*ty];+ stbir_resize_uint8( iconPx, iconX, iconY, 0, scaleIcon, ty, ty, 0, 4 );+ tracy::UpdateTextureRGBA( iconTex, scaleIcon, ty, ty );+ delete[] scaleIcon;++ const auto ratio = scale / prevScale;+ prevScale = scale;+ auto ctx = ImGui::GetCurrentContext();+ for( auto& w : ctx->Windows ) ScaleWindow( w, ratio );+}++static int IsBusy()+{+ if( loadThread.joinable() ) return 2;+ if( view && !view->IsBackgroundDone() ) return 1;+ return 0;+}++static void LoadConfig()+{+ const auto fn = tracy::GetSavePath( "tracy.ini" );+ auto ini = ini_load( fn );+ if( !ini ) return;++ int v;+ double v1;+ if( ini_sget( ini, "core", "threadedRendering", "%d", &v ) ) s_config.threadedRendering = v;+ if( ini_sget( ini, "core", "focusLostLimit", "%d", &v ) ) s_config.focusLostLimit = v;+ if( ini_sget( ini, "timeline", "targetFps", "%d", &v ) && v >= 1 && v < 10000 ) s_config.targetFps = v;+ if( ini_sget( ini, "timeline", "dynamicColors", "%d", &v ) ) s_config.dynamicColors = v;+ if( ini_sget( ini, "timeline", "forceColors", "%d", &v ) ) s_config.forceColors = v;+ if( ini_sget( ini, "timeline", "shortenName", "%d", &v ) ) s_config.shortenName = v;+ if( ini_sget( ini, "timeline", "horizontalScrollMultiplier", "%lf", &v1 ) && v1 > 0.0 ) s_config.horizontalScrollMultiplier = v1;+ if( ini_sget( ini, "timeline", "verticalScrollMultiplier", "%lf", &v1 ) && v1 > 0.0 ) s_config.verticalScrollMultiplier = v1;+ if( ini_sget( ini, "memory", "limit", "%d", &v ) ) s_config.memoryLimit = v;+ if( ini_sget( ini, "memory", "percent", "%d", &v ) && v >= 1 && v < 1000 ) s_config.memoryLimitPercent = v;+ if( ini_sget( ini, "achievements", "enabled", "%d", &v ) ) s_config.achievements = v;+ if( ini_sget( ini, "achievements", "asked", "%d", &v ) ) s_config.achievementsAsked = v;+ if( ini_sget( ini, "ui", "saveUserScale", "%d", &v ) ) s_config.saveUserScale = v;+ if( ini_sget( ini, "ui", "userScale", "%lf", &v1 ) && v1 > 0.0 && s_config.saveUserScale ) s_config.userScale = v1;+ ++ ini_free( ini );+}++static bool SaveConfig()+{+ const auto fn = tracy::GetSavePath( "tracy.ini" );+ FILE* f = fopen( fn, "wb" );+ if( !f ) return false;++ fprintf( f, "[core]\n" );+ fprintf( f, "threadedRendering = %i\n", (int)s_config.threadedRendering );+ fprintf( f, "focusLostLimit = %i\n", (int)s_config.focusLostLimit );++ fprintf( f, "\n[timeline]\n" );+ fprintf( f, "targetFps = %i\n", s_config.targetFps );+ fprintf( f, "dynamicColors = %i\n", s_config.dynamicColors );+ fprintf( f, "forceColors = %i\n", (int)s_config.forceColors );+ fprintf( f, "shortenName = %i\n", s_config.shortenName );+ fprintf( f, "horizontalScrollMultiplier = %lf\n", s_config.horizontalScrollMultiplier );+ fprintf( f, "verticalScrollMultiplier = %lf\n", s_config.verticalScrollMultiplier );++ fprintf( f, "\n[memory]\n" );+ fprintf( f, "limit = %i\n", (int)s_config.memoryLimit );+ fprintf( f, "percent = %i\n", s_config.memoryLimitPercent );++ fprintf( f, "\n[achievements]\n" );+ fprintf( f, "enabled = %i\n", (int)s_config.achievements );+ fprintf( f, "asked = %i\n", (int)s_config.achievementsAsked );++ fprintf( f, "\n[ui]\n" );+ fprintf( f, "saveUserScale = %i\n", (int)s_config.saveUserScale );+ fprintf( f, "userScale = %lf\n", s_config.userScale );++ fclose( f );+ return true;+}++static void SetupScaleCallback( float scale )+{+ s_config.userScale = scale;+ if ( s_config.saveUserScale ) SaveConfig();+ RunOnMainThread( []{ SetupDPIScale(); }, true );+}++static void ScaleChanged( float scale )+{+ if( dpiScaleOverriddenFromEnv ) return;+ if( dpiScale == scale ) return;++ dpiScale = scale;+ SetupDPIScale();+}++int main( int argc, char** argv )+{+ sprintf( title, "Tracy Profiler %i.%i.%i", tracy::Version::Major, tracy::Version::Minor, tracy::Version::Patch );++ std::unique_ptr<tracy::FileRead> initFileOpen;+#ifdef __EMSCRIPTEN__+ initFileOpen = std::unique_ptr<tracy::FileRead>( tracy::FileRead::Open( "embed.tracy" ) );+#endif+ if( argc == 2 )+ {+ if( strcmp( argv[1], "--help" ) == 0 )+ {+ printf( "%s\n\n", title );+ printf( "Usage:\n\n" );+ printf( " Open trace file stored on disk:\n" );+ printf( " %s file.tracy\n\n", argv[0] );+ printf( " Connect to a running client:\n" );+ printf( " %s -a address [-p port]\n", argv[0] );+ exit( 0 );+ }+ try+ {+ initFileOpen = std::unique_ptr<tracy::FileRead>( tracy::FileRead::Open( argv[1] ) );+ }+ catch( const tracy::UnsupportedVersion& e )+ {+ fprintf( stderr, "The file you are trying to open is from the future version.\n" );+ exit( 1 );+ }+ catch( const tracy::NotTracyDump& e )+ {+ fprintf( stderr, "The file you are trying to open is not a tracy dump.\n" );+ exit( 1 );+ }+ catch( const tracy::LegacyVersion& e )+ {+ fprintf( stderr, "The file you are trying to open is from a legacy version.\n" );+ exit( 1 );+ }+ if( !initFileOpen )+ {+ fprintf( stderr, "Cannot open trace file: %s\n", argv[1] );+ exit( 1 );+ }+ }+ else+ {+ while( argc >= 3 )+ {+ if( strcmp( argv[1], "-a" ) == 0 )+ {+ connectTo = argv[2];+ }+ else if( strcmp( argv[1], "-p" ) == 0 )+ {+ port = (uint16_t)atoi( argv[2] );+ }+ else+ {+ fprintf( stderr, "Bad parameter: %s", argv[1] );+ exit( 1 );+ }+ argc -= 2;+ argv += 2;+ }+ }++ ConnectionHistory connHistory;+ Filters filters;+ tracy::AchievementsMgr achievements;++ connHist = &connHistory;+ filt = &filters;+ s_achievements = &achievements;++#ifndef __EMSCRIPTEN__+ updateThread = std::thread( [] {+ HttpRequest( "nereid.pl", "/tracy/version", 8099, [] ( int size, char* data ) {+ if( size == 4 )+ {+ uint32_t ver;+ memcpy( &ver, data, 4 );+ RunOnMainThread( [ver] { updateVersion = ver; tracy::s_wasActive = true; } );+ }+ delete[] data;+ } );+ } );+#endif++ auto iconThread = std::thread( [] {+ iconPx = stbi_load_from_memory( (const stbi_uc*)Icon_data, Icon_size, &iconX, &iconY, nullptr, 4 );+ zigzagPx[0] = stbi_load_from_memory( (const stbi_uc*)ZigZag32_data, ZigZag32_size, &zigzagX[0], &zigzagY[0], nullptr, 4 );+ zigzagPx[1] = stbi_load_from_memory( (const stbi_uc*)ZigZag16_data, ZigZag16_size, &zigzagX[1], &zigzagY[1], nullptr, 4 );+ zigzagPx[2] = stbi_load_from_memory( (const stbi_uc*)ZigZag08_data, ZigZag08_size, &zigzagX[2], &zigzagY[2], nullptr, 4 );+ zigzagPx[3] = stbi_load_from_memory( (const stbi_uc*)ZigZag04_data, ZigZag04_size, &zigzagX[3], &zigzagY[3], nullptr, 4 );+ zigzagPx[4] = stbi_load_from_memory( (const stbi_uc*)ZigZag02_data, ZigZag02_size, &zigzagX[4], &zigzagY[4], nullptr, 4 );+ zigzagPx[5] = stbi_load_from_memory( (const stbi_uc*)ZigZag01_data, ZigZag01_size, &zigzagX[5], &zigzagY[5], nullptr, 4 );+ } );++ LoadConfig();++ ImGuiTracyContext imguiContext;+ Backend backend( title, DrawContents, ScaleChanged, IsBusy, &mainThreadTasks );+ tracy::InitTexture();+ iconTex = tracy::MakeTexture();+ zigzagTex = tracy::MakeTexture( true );+ iconThread.join();+ backend.SetIcon( iconPx, iconX, iconY );+ bptr = &backend;++ const auto envDpiScale = getenv( "TRACY_DPI_SCALE" );+ if( envDpiScale )+ {+ const auto cnv = atof( envDpiScale );+ if( cnv != 0 )+ {+ dpiScale = cnv;+ dpiScaleOverriddenFromEnv = true;+ SetupDPIScale();+ }+ }++ s_achievements->Achieve( "achievementsIntro" );++ tracy::UpdateTextureRGBAMips( zigzagTex, (void**)zigzagPx, zigzagX, zigzagY, 6 );+ for( auto& v : zigzagPx ) free( v );++ if( initFileOpen )+ {+ view = std::make_unique<tracy::View>( RunOnMainThread, *initFileOpen, s_fixedWidth, s_smallFont, s_bigFont, SetWindowTitleCallback, SetupScaleCallback, AttentionCallback, s_config, s_achievements );+ initFileOpen.reset();+ }+ else if( connectTo )+ {+ view = std::make_unique<tracy::View>( RunOnMainThread, connectTo, port, s_fixedWidth, s_smallFont, s_bigFont, SetWindowTitleCallback, SetupScaleCallback, AttentionCallback, s_config, s_achievements );+ }++ tracy::Fileselector::Init();+ s_isElevated = IsElevated();++ backend.Show();+ backend.Run();++ if( loadThread.joinable() ) loadThread.join();+ if( updateThread.joinable() ) updateThread.join();+ if( updateNotesThread.joinable() ) updateNotesThread.join();+ view.reset();++ tracy::FreeTexture( zigzagTex, RunOnMainThread );+ tracy::FreeTexture( iconTex, RunOnMainThread );+ free( iconPx );++ tracy::Fileselector::Shutdown();++ return 0;+}++static void UpdateBroadcastClients()+{+ if( !view )+ {+ const auto time = std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::system_clock::now().time_since_epoch() ).count();+ if( !broadcastListen )+ {+ broadcastListen = std::make_unique<tracy::UdpListen>();+ if( !broadcastListen->Listen( port ) )+ {+ broadcastListen.reset();+ }+ }+ else+ {+ tracy::IpAddress addr;+ size_t len;+ for(;;)+ {+ auto msg = broadcastListen->Read( len, addr, 0 );+ if( !msg ) break;+ if( len > sizeof( tracy::BroadcastMessage ) ) continue;+ uint16_t broadcastVersion;+ memcpy( &broadcastVersion, msg, sizeof( uint16_t ) );+ if( broadcastVersion <= tracy::BroadcastVersion )+ {+ uint32_t protoVer;+ char procname[tracy::WelcomeMessageProgramNameSize];+ int32_t activeTime;+ uint16_t listenPort;+ uint64_t pid;++ switch( broadcastVersion )+ {+ case 3:+ {+ tracy::BroadcastMessage bm;+ memcpy( &bm, msg, len );+ protoVer = bm.protocolVersion;+ strcpy( procname, bm.programName );+ activeTime = bm.activeTime;+ listenPort = bm.listenPort;+ pid = bm.pid;+ break;+ }+ case 2:+ {+ if( len > sizeof( tracy::BroadcastMessage_v2 ) ) continue;+ tracy::BroadcastMessage_v2 bm;+ memcpy( &bm, msg, len );+ protoVer = bm.protocolVersion;+ strcpy( procname, bm.programName );+ activeTime = bm.activeTime;+ listenPort = bm.listenPort;+ pid = 0;+ break;+ }+ case 1:+ {+ if( len > sizeof( tracy::BroadcastMessage_v1 ) ) continue;+ tracy::BroadcastMessage_v1 bm;+ memcpy( &bm, msg, len );+ protoVer = bm.protocolVersion;+ strcpy( procname, bm.programName );+ activeTime = bm.activeTime;+ listenPort = bm.listenPort;+ pid = 0;+ break;+ }+ case 0:+ {+ if( len > sizeof( tracy::BroadcastMessage_v0 ) ) continue;+ tracy::BroadcastMessage_v0 bm;+ memcpy( &bm, msg, len );+ protoVer = bm.protocolVersion;+ strcpy( procname, bm.programName );+ activeTime = bm.activeTime;+ listenPort = 8086;+ pid = 0;+ break;+ }+ default:+ assert( false );+ break;+ }++ auto address = addr.GetText();+ const auto ipNumerical = addr.GetNumber();+ const auto clientId = uint64_t( ipNumerical ) | ( uint64_t( listenPort ) << 32 );+ auto it = clients.find( clientId );+ if( activeTime >= 0 )+ {+ if( it == clients.end() )+ {+ std::string ip( address );+ resolvLock.lock();+ if( resolvMap.find( ip ) == resolvMap.end() )+ {+ resolvMap.emplace( ip, ip );+ resolv.Query( ipNumerical, [ip] ( std::string&& name ) {+ std::lock_guard<std::mutex> lock( resolvLock );+ auto it = resolvMap.find( ip );+ assert( it != resolvMap.end() );+ std::swap( it->second, name );+ } );+ }+ resolvLock.unlock();+ clients.emplace( clientId, ClientData { time, protoVer, activeTime, listenPort, pid, procname, std::move( ip ) } );+ }+ else+ {+ it->second.time = time;+ it->second.activeTime = activeTime;+ it->second.port = listenPort;+ it->second.pid = pid;+ it->second.protocolVersion = protoVer;+ if( strcmp( it->second.procName.c_str(), procname ) != 0 ) it->second.procName = procname;+ }+ }+ else if( it != clients.end() )+ {+ clients.erase( it );+ }+ }+ }+ auto it = clients.begin();+ while( it != clients.end() )+ {+ const auto diff = time - it->second.time;+ if( diff > 4000 ) // 4s+ {+ it = clients.erase( it );+ }+ else+ {+ ++it;+ }+ }+ }+ }+ else if( !clients.empty() )+ {+ clients.clear();+ }+}++static void TextComment( const char* str )+{+ ImGui::SameLine();+ ImGui::PushFont( s_smallFont );+ ImGui::AlignTextToFramePadding();+ tracy::TextDisabledUnformatted( str );+ ImGui::PopFont();+}++static void DrawAchievements( tracy::data::AchievementItem** items )+{+ while( *items )+ {+ auto& it = *items++;+ if( it->unlockTime > 0 )+ {+ if( it->doneTime > 0 ) ImGui::PushStyleColor( ImGuiCol_Text, GImGui->Style.Colors[ImGuiCol_TextDisabled] );+ bool isSelected = s_achievementItem == it;+ if( isSelected )+ {+ if( !it->hideNew ) it->hideNew = true;+ if( !it->hideCompleted && it->doneTime > 0 ) it->hideCompleted = true;+ }+ if( ImGui::Selectable( it->name, isSelected ) )+ {+ s_achievementItem = it;+ }+ if( it->doneTime > 0 ) ImGui::PopStyleColor();+ if( !it->hideNew )+ {+ ImGui::SameLine();+ tracy::TextColoredUnformatted( 0xFF4488FF, ICON_FA_CIRCLE_EXCLAMATION );+ }+ if( !it->hideCompleted && it->doneTime > 0 )+ {+ ImGui::SameLine();+ tracy::TextColoredUnformatted( 0xFF44FF44, ICON_FA_CIRCLE_CHECK );+ }+ if( it->items )+ {+ ImGui::Indent();+ DrawAchievements( it->items );+ ImGui::Unindent();+ }+ }+ }+}++static void DrawContents()+{+ static bool reconnect = false;+ static std::string reconnectAddr;+ static uint16_t reconnectPort;+ static bool showFilter = false;++#ifndef __EMSCRIPTEN__+ UpdateBroadcastClients();+#endif++ int display_w, display_h;+ bptr->NewFrame( display_w, display_h );++ const bool achievementsAttention = s_config.achievements ? s_achievements->NeedsAttention() : false;++ static int activeFrames = 3;+ if( tracy::WasActive() || !clients.empty() || ( view && view->WasActive() ) || achievementsAttention )+ {+ activeFrames = 3;+ }+ else+ {+ auto ctx = ImGui::GetCurrentContext();+ if( ctx->NavWindowingTarget || ( ctx->DimBgRatio != 0 && ctx->DimBgRatio != 1 ) )+ {+ activeFrames = 3;+ }+ else+ {+ auto& inputQueue = ctx->InputEventsQueue;+ if( !inputQueue.empty() )+ {+ for( auto& v : inputQueue )+ {+ if( v.Type != ImGuiInputEventType_MouseViewport )+ {+ activeFrames = 3;+ break;+ }+ }+ }+ }+ }+ if( activeFrames == 0 )+ {+ std::this_thread::sleep_for( std::chrono::milliseconds( 16 ) );+ return;+ }+ activeFrames--;++ ImGui::NewFrame();+ tracy::MouseFrame();++ setlocale( LC_NUMERIC, "C" );++ if( !view )+ {+ if( s_customTitle )+ {+ s_customTitle = false;+ bptr->SetTitle( title );+ }++ auto& style = ImGui::GetStyle();+ style.Colors[ImGuiCol_WindowBg] = ImVec4( 0.129f, 0.137f, 0.11f, 1.f );+ ImGui::Begin( "Get started", nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings );+ char buf[128];+ sprintf( buf, "Tracy Profiler %i.%i.%i", tracy::Version::Major, tracy::Version::Minor, tracy::Version::Patch );+ ImGui::PushFont( s_bigFont );+ tracy::TextCentered( buf );+ ImGui::PopFont();+ if( dpiChanged == 0 )+ {+ ImGui::SameLine( ImGui::GetWindowContentRegionMax().x - ImGui::CalcTextSize( ICON_FA_WRENCH ).x - ImGui::GetStyle().FramePadding.x * 2 );+ if( ImGui::Button( ICON_FA_WRENCH ) )+ {+ ImGui::OpenPopup( "About Tracy" );+ }+ }+ bool keepOpenAbout = true;+ if( ImGui::BeginPopupModal( "About Tracy", &keepOpenAbout, ImGuiWindowFlags_AlwaysAutoResize ) )+ {+ tracy::ImageCentered( iconTex, ImVec2( iconTexSz, iconTexSz ) );+ ImGui::Spacing();+ ImGui::PushFont( s_bigFont );+ tracy::TextCentered( buf );+ ImGui::PopFont();+ ImGui::PushFont( s_smallFont );+ ImGui::PushStyleColor( ImGuiCol_Text, GImGui->Style.Colors[ImGuiCol_TextDisabled] );+ tracy::TextCentered( tracy::GitRef );+ ImGui::PopStyleColor();+ ImGui::PopFont();+ if( ImGui::IsItemHovered() )+ {+ ImGui::BeginTooltip();+ ImGui::TextUnformatted( "Click to copy git reference to clipboard" );+ ImGui::EndTooltip();+ if( ImGui::IsItemClicked() )+ {+ ImGui::SetClipboardText( tracy::GitRef );+ }+ }+#ifndef NDEBUG+ ImGui::PushFont( s_smallFont );+ ImGui::PushStyleColor( ImGuiCol_Text, ImVec4( 1.f, 0.5f, 0.5f, 1.f ) );+ tracy::TextCentered( "Debug build" );+ ImGui::PopStyleColor();+ ImGui::PopFont();+#endif+ ImGui::Spacing();+ ImGui::TextUnformatted( "A real time, nanosecond resolution, remote telemetry, hybrid\nframe and sampling profiler for games and other applications." );+ ImGui::Spacing();+ ImGui::TextUnformatted( "Created by Bartosz Taudul" );+ ImGui::SameLine();+ tracy::TextDisabledUnformatted( "<wolf@nereid.pl>" );+ tracy::TextDisabledUnformatted( "Additional authors listed in git history." );+ ImGui::Separator();+ if( ImGui::TreeNode( ICON_FA_TOOLBOX " Global settings" ) )+ {+ s_achievements->Achieve( "globalSettings" );++ ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 0, 0 ) );++ ImGui::TextUnformatted( "Threaded rendering" );+ ImGui::Indent();+ if( ImGui::RadioButton( "Enabled", s_config.threadedRendering ) ) { s_config.threadedRendering = true; SaveConfig(); }+ ImGui::SameLine();+ tracy::DrawHelpMarker( "Uses multiple CPU cores for rendering. May affect performance of the profiled application when running on the same machine." );+ if( ImGui::RadioButton( "Disabled", !s_config.threadedRendering ) ) { s_config.threadedRendering = false; SaveConfig(); }+ ImGui::SameLine();+ tracy::DrawHelpMarker( "Restricts rendering to a single CPU core. Can reduce profiler frame rate." );+ ImGui::Unindent();++ ImGui::Spacing();+ if( ImGui::Checkbox( "Reduce render rate when focus is lost", &s_config.focusLostLimit ) ) SaveConfig();++ ImGui::Spacing();+ ImGui::TextUnformatted( "Target FPS" );+ ImGui::SameLine();+ tracy::DrawHelpMarker( "The default target frame rate for your application. Frames displayed in the frame time graph will be colored accordingly if they are within the target frame rate. This can be adjusted later for each individual trace." );+ ImGui::SameLine();+ int tmp = s_config.targetFps;+ ImGui::SetNextItemWidth( 90 * dpiScale );+ if( ImGui::InputInt( "##targetfps", &tmp ) ) { s_config.targetFps = std::clamp( tmp, 1, 9999 ); SaveConfig(); }++ ImGui::Spacing();+ ImGui::TextUnformatted( ICON_FA_PALETTE " Zone colors" );+ ImGui::SameLine();+ tracy::SmallCheckbox( "Ignore custom", &s_config.forceColors );+ ImGui::Indent();+ ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 0, 0 ) );+ ImGui::RadioButton( "Static", &s_config.dynamicColors, 0 );+ ImGui::RadioButton( "Thread dynamic", &s_config.dynamicColors, 1 );+ ImGui::RadioButton( "Source location dynamic", &s_config.dynamicColors, 2 );+ ImGui::PopStyleVar();+ ImGui::Unindent();+ ImGui::TextUnformatted( ICON_FA_RULER_HORIZONTAL " Zone name shortening" );+ ImGui::Indent();+ ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 0, 0 ) );+ ImGui::RadioButton( "Disabled", &s_config.shortenName, (uint8_t)tracy::ShortenName::Never );+ ImGui::RadioButton( "Minimal length", &s_config.shortenName, (uint8_t)tracy::ShortenName::Always );+ ImGui::RadioButton( "Only normalize", &s_config.shortenName, (uint8_t)tracy::ShortenName::OnlyNormalize );+ ImGui::RadioButton( "As needed", &s_config.shortenName, (uint8_t)tracy::ShortenName::NoSpace );+ ImGui::RadioButton( "As needed + normalize", &s_config.shortenName, (uint8_t)tracy::ShortenName::NoSpaceAndNormalize );+ ImGui::PopStyleVar();+ ImGui::Unindent();++ ImGui::Spacing();+ ImGui::TextUnformatted( "Scroll Multipliers" );+ ImGui::SameLine();+ tracy::DrawHelpMarker( "The multipliers to the amount to scroll by horizontally and vertically. This is used in the timeline and setting this value can help compensate for scroll wheel sensitivity." );+ ImGui::SameLine();+ double tmpScroll = s_config.horizontalScrollMultiplier;+ ImGui::SetNextItemWidth( 45 * dpiScale );+ if( ImGui::InputDouble( "##horizontalscrollmultiplier", &tmpScroll ) ) { s_config.horizontalScrollMultiplier = std::max( tmpScroll, 0.01 ); SaveConfig(); }+ tmpScroll = s_config.verticalScrollMultiplier;+ ImGui::SameLine();+ ImGui::SetNextItemWidth( 45 * dpiScale );+ if( ImGui::InputDouble( "##verticalscrollmultiplier", &tmpScroll ) ) { s_config.verticalScrollMultiplier = std::max( tmpScroll, 0.01 ); SaveConfig(); }++ if( s_totalMem == 0 )+ {+ ImGui::BeginDisabled();+ s_config.memoryLimit = false;+ }++ ImGui::Spacing();+ if( ImGui::Checkbox( "Memory limit", &s_config.memoryLimit ) ) SaveConfig();+ ImGui::SameLine();+ tracy::DrawHelpMarker( "When enabled, profiler will stop recording data when memory usage exceeds the specified percentage of available memory. Values greater than 100% will rely on swap. You need to make sure that memory is actually available." );+ ImGui::SameLine();+ ImGui::SetNextItemWidth( 70 * dpiScale );+ if( ImGui::InputInt( "##memorylimit", &s_config.memoryLimitPercent ) ) { s_config.memoryLimitPercent = std::clamp( s_config.memoryLimitPercent, 1, 999 ); SaveConfig(); }+ ImGui::SameLine();+ ImGui::TextUnformatted( "%" );+ if( s_totalMem != 0 )+ {+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", tracy::MemSizeToString( s_totalMem * s_config.memoryLimitPercent / 100 ) );+ }+ else+ {+ ImGui::EndDisabled();+ }++ ImGui::Spacing();+ if( ImGui::Checkbox( "Enable achievements", &s_config.achievements ) ) SaveConfig();+ if( ImGui::Checkbox( "Save UI scale", &s_config.saveUserScale) ) SaveConfig();++ ImGui::PopStyleVar();+ ImGui::TreePop();+ }+ ImGui::Separator();+ ImGui::PushFont( s_smallFont );+ tracy::TextFocused( "Protocol version", tracy::RealToString( tracy::ProtocolVersion ) );+ ImGui::SameLine();+ ImGui::SeparatorEx( ImGuiSeparatorFlags_Vertical );+ ImGui::SameLine();+ tracy::TextFocused( "Broadcast version", tracy::RealToString( tracy::BroadcastVersion ) );+ ImGui::SameLine();+ ImGui::SeparatorEx( ImGuiSeparatorFlags_Vertical );+ ImGui::SameLine();+ tracy::TextFocused( "Build date", __DATE__ ", " __TIME__ );+ ImGui::PopFont();+ ImGui::EndPopup();+ }+ ImGui::Spacing();+ if( ImGui::Button( ICON_FA_BOOK " Manual" ) )+ {+ tracy::OpenWebpage( "https://github.com/wolfpld/tracy/releases" );+ }+ ImGui::SameLine();+ if( ImGui::Button( ICON_FA_EARTH_AMERICAS " Web" ) )+ {+ ImGui::OpenPopup( "web" );+ }+ if( ImGui::BeginPopup( "web" ) )+ {+ if( ImGui::Selectable( ICON_FA_HOUSE_CHIMNEY " Tracy Profiler home page" ) )+ {+ tracy::OpenWebpage( "https://github.com/wolfpld/tracy" );+ }+ ImGui::Separator();+ if( ImGui::Selectable( ICON_FA_VIDEO " An Introduction to Tracy Profiler in C++ - Marcos Slomp - CppCon 2023" ) )+ {+ tracy::OpenWebpage( "https://youtu.be/ghXk3Bk5F2U?t=37" );+ }+ ImGui::Separator();+ if( ImGui::Selectable( ICON_FA_VIDEO " New features in v0.8" ) )+ {+ tracy::OpenWebpage( "https://www.youtube.com/watch?v=30wpRpHTTag" );+ }+ TextComment( "2022-03-28" );+ if( ImGui::Selectable( ICON_FA_VIDEO " New features in v0.7" ) )+ {+ tracy::OpenWebpage( "https://www.youtube.com/watch?v=_hU7vw00MZ4" );+ }+ TextComment( "2020-06-11" );+ if( ImGui::Selectable( ICON_FA_VIDEO " New features in v0.6" ) )+ {+ tracy::OpenWebpage( "https://www.youtube.com/watch?v=uJkrFgriuOo" );+ }+ TextComment( "2019-11-17" );+ if( ImGui::Selectable( ICON_FA_VIDEO " New features in v0.5" ) )+ {+ tracy::OpenWebpage( "https://www.youtube.com/watch?v=P6E7qLMmzTQ" );+ }+ TextComment( "2019-08-10" );+ if( ImGui::Selectable( ICON_FA_VIDEO " New features in v0.4" ) )+ {+ tracy::OpenWebpage( "https://www.youtube.com/watch?v=eAkgkaO8B9o" );+ }+ TextComment( "2018-10-09" );+ if( ImGui::Selectable( ICON_FA_VIDEO " New features in v0.3" ) )+ {+ tracy::OpenWebpage( "https://www.youtube.com/watch?v=3SXpDpDh2Uo" );+ }+ TextComment( "2018-07-03" );+ if( ImGui::Selectable( ICON_FA_VIDEO " Overview of v0.2" ) )+ {+ tracy::OpenWebpage( "https://www.youtube.com/watch?v=fB5B46lbapc" );+ }+ TextComment( "2018-03-25" );+ ImGui::EndPopup();+ }+ ImGui::SameLine();+ if( ImGui::Button( ICON_FA_COMMENT " Chat" ) )+ {+ tracy::OpenWebpage( "https://discord.gg/pk78auc" );+ }+ ImGui::SameLine();+ if( ImGui::Button( ICON_FA_HEART " Sponsor" ) )+ {+ tracy::OpenWebpage( "https://github.com/sponsors/wolfpld/" );+ }+ if( updateVersion > tracy::FileVersion( tracy::Version::Major, tracy::Version::Minor, tracy::Version::Patch ) )+ {+ ImGui::Separator();+ ImGui::TextColored( ImVec4( 1, 1, 0, 1 ), ICON_FA_EXCLAMATION " Update to %i.%i.%i is available!", ( updateVersion >> 16 ) & 0xFF, ( updateVersion >> 8 ) & 0xFF, updateVersion & 0xFF );+ ImGui::SameLine();+ if( ImGui::SmallButton( ICON_FA_GIFT " Get it!" ) )+ {+ showReleaseNotes = true;+ if( !updateNotesThread.joinable() )+ {+ updateNotesThread = std::thread( [] {+ HttpRequest( "nereid.pl", "/tracy/notes", 8099, [] ( int size, char* data ) {+ std::string notes( data, data+size );+ delete[] data;+ RunOnMainThread( [notes = std::move( notes )] () mutable { releaseNotes = std::move( notes ); tracy::s_wasActive = true; } );+ } );+ } );+ }+ }+ }+ if( s_isElevated )+ {+ ImGui::Separator();+ ImGui::PushStyleColor( ImGuiCol_Text, ImVec4( 1.f, 0.25f, 0.25f, 1.f ) );+ tracy::TextCentered( ICON_FA_TRIANGLE_EXCLAMATION " Profiler has elevated privileges! " ICON_FA_TRIANGLE_EXCLAMATION );+ ImGui::PushFont( s_smallFont );+ tracy::TextCentered( "You are running the profiler interface with admin privileges. This is" );+ tracy::TextCentered( "most likely a mistake, as there is no reason to do so. Instead, you" );+ tracy::TextCentered( "probably wanted to run the client (the application you are profiling)" );+ tracy::TextCentered( "with elevated privileges." );+ ImGui::PopFont();+ ImGui::PopStyleColor();+ }+ ImGui::Separator();+ ImGui::TextUnformatted( "Client address" );+ bool connectClicked = false;+ connectClicked |= ImGui::InputTextWithHint( "###connectaddress", "Enter address", addr, 1024, ImGuiInputTextFlags_EnterReturnsTrue );+ if( !connHist->empty() )+ {+ ImGui::SameLine();+ if( ImGui::BeginCombo( "##frameCombo", nullptr, ImGuiComboFlags_NoPreview ) )+ {+ int idxRemove = -1;+ const auto sz = std::min<size_t>( 5, connHist->size() );+ for( size_t i=0; i<sz; i++ )+ {+ const auto& str = connHist->Name( i );+ if( ImGui::Selectable( str.c_str() ) )+ {+ memcpy( addr, str.c_str(), str.size() + 1 );+ }+ if( ImGui::IsItemHovered() && ImGui::IsKeyPressed( ImGuiKey_Delete, false ) )+ {+ idxRemove = (int)i;+ }+ }+ if( idxRemove >= 0 )+ {+ connHist->Erase( idxRemove );+ }+ ImGui::EndCombo();+ }+ }+#ifdef __EMSCRIPTEN__+ ImGui::BeginDisabled();+#endif+ connectClicked |= ImGui::Button( ICON_FA_WIFI " Connect" );+#ifdef __EMSCRIPTEN__+ ImGui::EndDisabled();+ connectClicked = false;+#endif+ if( connectClicked && *addr && !loadThread.joinable() )+ {+ auto aptr = addr;+ while( *aptr == ' ' || *aptr == '\t' ) aptr++;+ auto aend = aptr;+ while( *aend && *aend != ' ' && *aend != '\t' ) aend++;++ if( aptr != aend )+ {+ std::string address( aptr, aend );+ connHist->Count( address );++ auto adata = address.data();+ auto ptr = adata + address.size() - 1;+ while( ptr > adata && *ptr != ':' ) ptr--;+ if( *ptr == ':' )+ {+ std::string addrPart = std::string( adata, ptr );+ uint16_t portPart = (uint16_t)atoi( ptr+1 );+ view = std::make_unique<tracy::View>( RunOnMainThread, addrPart.c_str(), portPart, s_fixedWidth, s_smallFont, s_bigFont, SetWindowTitleCallback, SetupScaleCallback, AttentionCallback, s_config, s_achievements );+ }+ else+ {+ view = std::make_unique<tracy::View>( RunOnMainThread, address.c_str(), port, s_fixedWidth, s_smallFont, s_bigFont, SetWindowTitleCallback, SetupScaleCallback, AttentionCallback, s_config, s_achievements );+ }+ }+ }+ if( s_config.memoryLimit )+ {+ ImGui::SameLine();+ tracy::TextColoredUnformatted( 0xFF00FFFF, ICON_FA_TRIANGLE_EXCLAMATION );+ tracy::TooltipIfHovered( "Memory limit is active" );+ }+ ImGui::SameLine( 0, ImGui::GetTextLineHeight() * 2 );++#ifndef TRACY_NO_FILESELECTOR+ if( ImGui::Button( ICON_FA_FOLDER_OPEN " Open saved trace" ) && !loadThread.joinable() )+ {+ tracy::Fileselector::OpenFile( "tracy", "Tracy Profiler trace file", []( const char* fn ) {+ try+ {+ auto f = std::shared_ptr<tracy::FileRead>( tracy::FileRead::Open( fn ) );+ if( f )+ {+ loadThread = std::thread( [f] {+ try+ {+ view = std::make_unique<tracy::View>( RunOnMainThread, *f, s_fixedWidth, s_smallFont, s_bigFont, SetWindowTitleCallback, SetupScaleCallback, AttentionCallback, s_config, s_achievements );+ }+ catch( const tracy::UnsupportedVersion& e )+ {+ badVer.state = tracy::BadVersionState::UnsupportedVersion;+ badVer.version = e.version;+ }+ catch( const tracy::LegacyVersion& e )+ {+ badVer.state = tracy::BadVersionState::LegacyVersion;+ badVer.version = e.version;+ }+ catch( const tracy::LoadFailure& e )+ {+ badVer.state = tracy::BadVersionState::LoadFailure;+ badVer.msg = e.msg;+ }+ } );+ }+ }+ catch( const tracy::NotTracyDump& )+ {+ badVer.state = tracy::BadVersionState::BadFile;+ }+ catch( const tracy::FileReadError& )+ {+ badVer.state = tracy::BadVersionState::ReadError;+ }+ } );+ }+#endif++ if( badVer.state != tracy::BadVersionState::Ok )+ {+ if( loadThread.joinable() ) { loadThread.join(); }+ tracy::BadVersion( badVer, s_bigFont );+ }++ if( !clients.empty() )+ {+ ImGui::Separator();+ ImGui::TextUnformatted( "Discovered clients:" );+ ImGui::SameLine();+ tracy::SmallToggleButton( ICON_FA_FILTER " Filter", showFilter );+ if( filt->IsActive() )+ {+ ImGui::SameLine();+ tracy::TextColoredUnformatted( 0xFF00FFFF, ICON_FA_TRIANGLE_EXCLAMATION );+ tracy::TooltipIfHovered( "Filters are active" );+ if( showFilter )+ {+ ImGui::SameLine();+ if( ImGui::SmallButton( ICON_FA_DELETE_LEFT " Clear" ) )+ {+ filt->Clear();+ }+ }+ }+ if( showFilter )+ {+ const auto w = ImGui::GetTextLineHeight() * 12;+ ImGui::Separator();+ filt->Draw( w );+ }+ ImGui::Separator();+ static bool widthSet = false;+ ImGui::Columns( 3 );+ if( !widthSet )+ {+ widthSet = true;+ const auto w = ImGui::GetWindowWidth();+ ImGui::SetColumnWidth( 0, w * 0.35f );+ ImGui::SetColumnWidth( 1, w * 0.175f );+ ImGui::SetColumnWidth( 2, w * 0.425f );+ }+ const auto time = std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::system_clock::now().time_since_epoch() ).count();+ int idx = 0;+ int passed = 0;+ std::lock_guard<std::mutex> lock( resolvLock );+ for( auto& v : clients )+ {+ const bool badProto = v.second.protocolVersion != tracy::ProtocolVersion;+ bool sel = false;+ const auto& name = resolvMap.find( v.second.address );+ assert( name != resolvMap.end() );+ if( filt->FailAddr( name->second.c_str() ) && filt->FailAddr( v.second.address.c_str() ) ) continue;+ if( filt->FailPort( v.second.port ) ) continue;+ if( filt->FailProg( v.second.procName.c_str() ) ) continue;+ ImGuiSelectableFlags flags = ImGuiSelectableFlags_SpanAllColumns;+ if( badProto ) flags |= ImGuiSelectableFlags_Disabled;+ ImGui::PushID( idx++ );+ const bool selected = ImGui::Selectable( name->second.c_str(), &sel, flags );+ ImGui::PopID();+ if( ImGui::IsItemHovered( ImGuiHoveredFlags_AllowWhenDisabled ) )+ {+ char portstr[32];+ sprintf( portstr, "%" PRIu16, v.second.port );+ ImGui::BeginTooltip();+ if( badProto )+ {+ tracy::TextColoredUnformatted( 0xFF0000FF, "Incompatible protocol!" );+ ImGui::SameLine();+ auto ph = tracy::ProtocolHistory;+ ImGui::TextDisabled( "(used: %i, required: %i)", v.second.protocolVersion, tracy::ProtocolVersion );+ while( ph->protocol && ph->protocol != v.second.protocolVersion ) ph++;+ if( ph->protocol )+ {+ if( ph->maxVer )+ {+ ImGui::TextDisabled( "Compatible Tracy versions: %i.%i.%i to %i.%i.%i", ph->minVer >> 16, ( ph->minVer >> 8 ) & 0xFF, ph->minVer & 0xFF, ph->maxVer >> 16, ( ph->maxVer >> 8 ) & 0xFF, ph->maxVer & 0xFF );+ }+ else+ {+ ImGui::TextDisabled( "Compatible Tracy version: %i.%i.%i", ph->minVer >> 16, ( ph->minVer >> 8 ) & 0xFF, ph->minVer & 0xFF );+ }+ }+ ImGui::Separator();+ }+ tracy::TextFocused( "IP:", v.second.address.c_str() );+ tracy::TextFocused( "Port:", portstr );+ if( v.second.pid != 0 )+ {+ tracy::TextFocused( "PID:", tracy::RealToString( v.second.pid ) );+ }+ ImGui::EndTooltip();+ }+ if( v.second.port != port )+ {+ ImGui::SameLine();+ ImGui::TextDisabled( ":%" PRIu16, v.second.port );+ }+ if( selected && !loadThread.joinable() )+ {+ view = std::make_unique<tracy::View>( RunOnMainThread, v.second.address.c_str(), v.second.port, s_fixedWidth, s_smallFont, s_bigFont, SetWindowTitleCallback, SetupScaleCallback, AttentionCallback, s_config, s_achievements );+ }+ ImGui::NextColumn();+ const auto acttime = ( v.second.activeTime + ( time - v.second.time ) / 1000 ) * 1000000000ll;+ if( badProto )+ {+ tracy::TextDisabledUnformatted( tracy::TimeToString( acttime ) );+ }+ else+ {+ ImGui::TextUnformatted( tracy::TimeToString( acttime ) );+ }+ ImGui::NextColumn();+ if( badProto )+ {+ tracy::TextDisabledUnformatted( v.second.procName.c_str() );+ }+ else+ {+ ImGui::TextUnformatted( v.second.procName.c_str() );+ }+ ImGui::NextColumn();+ passed++;+ }+ ImGui::EndColumns();+ if( passed == 0 )+ {+ ImGui::TextUnformatted( "All clients are filtered." );+ }+ }+ ImGui::End();++ if( showReleaseNotes )+ {+ assert( updateNotesThread.joinable() );+ ImGui::SetNextWindowSize( ImVec2( 600 * dpiScale, 400 * dpiScale ), ImGuiCond_FirstUseEver );+ ImGui::Begin( "Update available!", &showReleaseNotes );+ if( ImGui::Button( ICON_FA_DOWNLOAD " Download" ) )+ {+ tracy::OpenWebpage( "https://github.com/wolfpld/tracy/releases" );+ }+ ImGui::BeginChild( "###notes", ImVec2( 0, 0 ), true );+ if( releaseNotes.empty() )+ {+ static float rnTime = 0;+ rnTime += ImGui::GetIO().DeltaTime;+ tracy::TextCentered( "Fetching release notes..." );+ tracy::DrawWaitingDots( rnTime );+ }+ else+ {+ ImGui::PushFont( s_fixedWidth );+ ImGui::TextUnformatted( releaseNotes.c_str() );+ ImGui::PopFont();+ }+ ImGui::EndChild();+ ImGui::End();+ }+ }+ else+ {+ if( showReleaseNotes ) showReleaseNotes = false;+ if( broadcastListen )+ {+ broadcastListen.reset();+ clients.clear();+ }+ if( loadThread.joinable() ) loadThread.join();+ view->NotifyRootWindowSize( display_w, display_h );+ if( !view->Draw() )+ {+ viewShutdown.store( ViewShutdown::True, std::memory_order_relaxed );+ reconnect = view->ReconnectRequested();+ if( reconnect )+ {+ reconnectAddr = view->GetAddress();+ reconnectPort = view->GetPort();+ }+ loadThread = std::thread( [view = std::move( view )] () mutable {+ view.reset();+ viewShutdown.store( ViewShutdown::Join, std::memory_order_relaxed );+ } );+ }+ }+ auto& progress = tracy::Worker::GetLoadProgress();+ auto totalProgress = progress.total.load( std::memory_order_relaxed );+ if( totalProgress != 0 )+ {+ ImGui::OpenPopup( "Loading trace..." );+ }+ if( ImGui::BeginPopupModal( "Loading trace...", nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings) )+ {+ ImGui::PushFont( s_bigFont );+ tracy::TextCentered( ICON_FA_HOURGLASS_HALF );+ ImGui::PopFont();++ animTime += ImGui::GetIO().DeltaTime;+ tracy::DrawWaitingDots( animTime );++ auto currProgress = progress.progress.load( std::memory_order_relaxed );+ if( totalProgress == 0 )+ {+ ImGui::CloseCurrentPopup();+ totalProgress = currProgress;+ }+ switch( currProgress )+ {+ case tracy::LoadProgress::Initialization:+ ImGui::TextUnformatted( "Initialization..." );+ break;+ case tracy::LoadProgress::Locks:+ ImGui::TextUnformatted( "Locks..." );+ break;+ case tracy::LoadProgress::Messages:+ ImGui::TextUnformatted( "Messages..." );+ break;+ case tracy::LoadProgress::Zones:+ ImGui::TextUnformatted( "CPU zones..." );+ break;+ case tracy::LoadProgress::GpuZones:+ ImGui::TextUnformatted( "GPU zones..." );+ break;+ case tracy::LoadProgress::Plots:+ ImGui::TextUnformatted( "Plots..." );+ break;+ case tracy::LoadProgress::Memory:+ ImGui::TextUnformatted( "Memory..." );+ break;+ case tracy::LoadProgress::CallStacks:+ ImGui::TextUnformatted( "Call stacks..." );+ break;+ case tracy::LoadProgress::FrameImages:+ ImGui::TextUnformatted( "Frame images..." );+ break;+ case tracy::LoadProgress::ContextSwitches:+ ImGui::TextUnformatted( "Context switches..." );+ break;+ case tracy::LoadProgress::ContextSwitchesPerCpu:+ ImGui::TextUnformatted( "CPU context switches..." );+ break;+ default:+ assert( false );+ break;+ }+ ImGui::ProgressBar( float( currProgress ) / totalProgress, ImVec2( 200 * dpiScale, 0 ) );++ ImGui::TextUnformatted( "Progress..." );+ auto subTotal = progress.subTotal.load( std::memory_order_relaxed );+ auto subProgress = progress.subProgress.load( std::memory_order_relaxed );+ if( subTotal == 0 )+ {+ ImGui::ProgressBar( 1.f, ImVec2( 200 * dpiScale, 0 ) );+ }+ else+ {+ ImGui::ProgressBar( float( subProgress ) / subTotal, ImVec2( 200 * dpiScale, 0 ) );+ }+ ImGui::EndPopup();+ }+ switch( viewShutdown.load( std::memory_order_relaxed ) )+ {+ case ViewShutdown::True:+ ImGui::OpenPopup( "Capture cleanup..." );+ break;+ case ViewShutdown::Join:+ loadThread.join();+ viewShutdown.store( ViewShutdown::False, std::memory_order_relaxed );+ if( reconnect )+ {+ view = std::make_unique<tracy::View>( RunOnMainThread, reconnectAddr.c_str(), reconnectPort, s_fixedWidth, s_smallFont, s_bigFont, SetWindowTitleCallback, SetupScaleCallback, AttentionCallback, s_config, s_achievements );+ }+ break;+ default:+ break;+ }+ if( ImGui::BeginPopupModal( "Capture cleanup...", nullptr, ImGuiWindowFlags_AlwaysAutoResize ) )+ {+ if( viewShutdown.load( std::memory_order_relaxed ) != ViewShutdown::True ) ImGui::CloseCurrentPopup();+ ImGui::PushFont( s_bigFont );+ tracy::TextCentered( ICON_FA_BROOM );+ ImGui::PopFont();+ animTime += ImGui::GetIO().DeltaTime;+ tracy::DrawWaitingDots( animTime );+ ImGui::TextUnformatted( "Please wait, cleanup is in progress" );+ ImGui::EndPopup();+ }++ if( tracy::Fileselector::HasFailed() ) ImGui::OpenPopup( "File selector is not available" );+ if( ImGui::BeginPopupModal( "File selector is not available", nullptr, ImGuiWindowFlags_AlwaysAutoResize ) )+ {+ ImGui::TextUnformatted( "File selector cannot be displayed." );+ ImGui::TextUnformatted( "Check nfd library implementation for details." );+ ImGui::Separator();+ if( ImGui::Button( "Ok" ) ) ImGui::CloseCurrentPopup();+ ImGui::EndPopup();+ }++#ifndef __EMSCRIPTEN__+ if( !s_config.achievementsAsked )+ {+ s_config.achievementsAsked = true;+ ImGui::OpenPopup( ICON_FA_STAR " Achievements" );+ }+#endif++ if( ImGui::BeginPopupModal( ICON_FA_STAR " Achievements", nullptr, ImGuiWindowFlags_AlwaysAutoResize ) )+ {+ ImGui::TextUnformatted( "Tracy Profiler is a complex tool with many features. It" );+ ImGui::TextUnformatted( "can be difficult to discover all of them on your own." );+ ImGui::TextUnformatted( "The Achievements system will guide you through the" );+ ImGui::TextUnformatted( "main features and teach you how to use them in an" );+ ImGui::TextUnformatted( "easy-to-handle manner." );+ ImGui::Separator();+ ImGui::TextUnformatted( "Would you like to enable achievements?" );+ ImGui::PushFont( s_smallFont );+ tracy::TextDisabledUnformatted( "You can change this setting later in the global settings." );+ ImGui::PopFont();+ ImGui::Separator();+ if( ImGui::Button( "Yes" ) )+ {+ s_config.achievements = true;+ SaveConfig();+ ImGui::CloseCurrentPopup();+ }+ ImGui::SameLine();+ if( ImGui::Button( "No" ) )+ {+ s_config.achievements = false;+ SaveConfig();+ ImGui::CloseCurrentPopup();+ }+ ImGui::EndPopup();+ }++ if( s_config.achievements )+ {+ ImGui::PushStyleVar( ImGuiStyleVar_WindowRounding, 16 * dpiScale );++ ImGui::PushFont( s_bigFont );+ const auto starSize = ImGui::CalcTextSize( ICON_FA_STAR );+ ImGui::PopFont();++ static int animStage = 0;+ static float animProgress = 0;+ static bool showAchievements = false;+ static float openTimeLeft = 0;++ float aSize = 0;+ const auto aItem = s_achievements->GetNextQueue();++ if( aItem )+ {+ aSize = ImGui::CalcTextSize( aItem->name ).x + ImGui::GetStyle().ItemSpacing.x + ImGui::GetStyle().WindowPadding.x * 0.5f;+ if( animStage == 0 )+ {+ animStage = 1;+ }+ }++ if( animStage > 0 )+ {+ tracy::s_wasActive = true;++ if( animStage == 1 )+ {+ animProgress = std::min( animProgress + ImGui::GetIO().DeltaTime / 0.3f, 1.f );+ if( animProgress == 1 )+ {+ animStage = 2;+ openTimeLeft = 8;+ }+ tracy::s_wasActive = true;+ }+ else if( animStage == 3 )+ {+ animProgress = std::max( animProgress - ImGui::GetIO().DeltaTime / 0.3f, 0.f );+ if( animProgress == 0 )+ {+ s_achievements->PopQueue();+ animStage = 0;+ }+ }+ }++ ImGui::SetNextWindowPos( ImVec2( display_w - starSize.x - ImGui::GetStyle().WindowPadding.x * 1.5f - aSize * smoothstep( animProgress ), display_h - starSize.y * 2 - ImGui::GetStyle().WindowPadding.y * 2 ) );+ ImGui::SetNextWindowSize( ImVec2( starSize.x + aSize + 100, starSize.y + ImGui::GetStyle().WindowPadding.y * 2 ) );+ ImGui::Begin( "###achievements", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_Tooltip );++ const auto cursor = ImGui::GetCursorPos();+ const auto cursorScreen = ImGui::GetCursorScreenPos();+ uint32_t color = 0xFF888888;+ if( achievementsAttention && !showAchievements )+ {+ const auto t = sin( ImGui::GetTime() * 4 ) * 0.5f + 0.5f;+ const auto c0 = uint32_t( std::lerp( 0x88, 0x00, t ) );+ const auto c1 = uint32_t( std::lerp( 0x88, 0xFF, t ) );+ color = 0xFF000000 | ( c0 << 16 ) | ( c1 << 8 ) | c1;+ }+ if( ( animStage == 0 || animStage == 2 ) && ImGui::IsMouseHoveringRect( cursorScreen - ImVec2( dpiScale * 2, dpiScale * 2 ), cursorScreen + starSize + ImVec2( dpiScale * 4, dpiScale * 4 ) ) )+ {+ color = 0xFFFFFFFF;+ if( ImGui::IsMouseClicked( 0 ) )+ {+ if( animStage == 0 )+ {+ showAchievements = !showAchievements;+ }+ else+ {+ showAchievements = true;+ animStage = 3;+ s_achievementItem = aItem;+ }+ }+ }+ ImGui::PushFont( s_bigFont );+ tracy::TextColoredUnformatted( color, ICON_FA_STAR );+ ImGui::PopFont();++ if( aItem )+ {+ ImGui::SameLine();+ const auto dismiss = ImGui::GetCursorScreenPos();+ const auto th = ImGui::GetTextLineHeight();+ ImGui::SetCursorPosY( cursor.y - th * 0.175f );+ ImGui::TextUnformatted( aItem->name );+ ImGui::PushFont( s_smallFont );+ ImGui::SetCursorPos( cursor + ImVec2( starSize.x + ImGui::GetStyle().ItemSpacing.x, th ) );+ tracy::TextDisabledUnformatted( "Click to open" );+ ImGui::PopFont();+ if( animStage == 2 )+ {+ if( ImGui::IsMouseHoveringRect( dismiss - ImVec2( 0, dpiScale * 6 ), dismiss + ImVec2( aSize, th * 1.5f + dpiScale * 4 ) ) && ImGui::IsMouseClicked( 0 ) )+ {+ s_achievementItem = aItem;+ s_switchAchievementCategory = true;+ showAchievements = true;+ animStage = 3;+ }+ if( !aItem->keepOpen )+ {+ openTimeLeft -= ImGui::GetIO().DeltaTime;+ if( openTimeLeft < 0 ) animStage = 3;+ }+ }+ }++ ImGui::End();+ ImGui::PopStyleVar();++ if( showAchievements )+ {+ const tracy::data::AchievementCategory* targetCategory = nullptr;+ if( s_switchAchievementCategory )+ {+ s_switchAchievementCategory = false;+ assert( s_achievementItem );+ targetCategory = s_achievements->GetCategoryForAchievement( s_achievementItem->id );+ }++ ImGui::SetNextWindowSize( ImVec2( 700 * dpiScale, 450 * dpiScale ), ImGuiCond_FirstUseEver );+ ImGui::Begin( "Achievements List", &showAchievements, ImGuiWindowFlags_NoDocking );+ ImGui::BeginTabBar( "###categories" );+ auto categories = s_achievements->GetCategories();+ while( *categories )+ {+ auto& c = *categories++;+ if( c->unlockTime > 0 )+ {+ char tmp[256];+ if( s_achievements->CategoryNeedsAttention( c->id ) )+ {+ snprintf( tmp, 256, ICON_FA_CIRCLE_EXCLAMATION " %s###%s", c->name, c->id );+ }+ else+ {+ snprintf( tmp, 256, "%s###%s", c->name, c->id );+ }+ ImGuiTabItemFlags flags = 0;+ if( targetCategory == c ) flags |= ImGuiTabItemFlags_SetSelected;+ if( ImGui::BeginTabItem( tmp, nullptr, flags ) )+ {+ ImGui::Columns( 2 );+ ImGui::SetColumnWidth( 0, 300 * dpiScale );+ DrawAchievements( c->items );+ ImGui::NextColumn();+ if( s_achievementItem )+ {+ const tracy::data::ctx ctx = { s_bigFont, s_smallFont, s_fixedWidth };+ s_achievementItem->description( ctx );+ }+ ImGui::EndColumns();+ ImGui::EndTabItem();+ }+ }+ }+ ImGui::EndTabBar();+ ImGui::End();+ }+ }++ bptr->EndFrame();+ if( dpiChanged > 0 ) dpiChanged--;+}
+ cbits/tracy/profiler/src/profiler/IconsFontAwesome6.h view
@@ -0,0 +1,1400 @@+// Generated by https://github.com/juliettef/IconFontCppHeaders script GenerateIconFontCppHeaders.py for languages C and C+++// from https://github.com/FortAwesome/Font-Awesome/raw/6.x/metadata/icons.yml+// for use with https://github.com/FortAwesome/Font-Awesome/blob/6.x/webfonts/fa-regular-400.ttf, https://github.com/FortAwesome/Font-Awesome/blob/6.x/webfonts/fa-solid-900.ttf+#pragma once++#define FONT_ICON_FILE_NAME_FAR "fa-regular-400.ttf"+#define FONT_ICON_FILE_NAME_FAS "fa-solid-900.ttf"++#define ICON_MIN_FA 0xe005+#define ICON_MAX_16_FA 0xf8ff+#define ICON_MAX_FA 0xf8ff+#define ICON_FA_0 "0" // U+0030+#define ICON_FA_1 "1" // U+0031+#define ICON_FA_2 "2" // U+0032+#define ICON_FA_3 "3" // U+0033+#define ICON_FA_4 "4" // U+0034+#define ICON_FA_5 "5" // U+0035+#define ICON_FA_6 "6" // U+0036+#define ICON_FA_7 "7" // U+0037+#define ICON_FA_8 "8" // U+0038+#define ICON_FA_9 "9" // U+0039+#define ICON_FA_A "A" // U+0041+#define ICON_FA_ADDRESS_BOOK "\xef\x8a\xb9" // U+f2b9+#define ICON_FA_ADDRESS_CARD "\xef\x8a\xbb" // U+f2bb+#define ICON_FA_ALIGN_CENTER "\xef\x80\xb7" // U+f037+#define ICON_FA_ALIGN_JUSTIFY "\xef\x80\xb9" // U+f039+#define ICON_FA_ALIGN_LEFT "\xef\x80\xb6" // U+f036+#define ICON_FA_ALIGN_RIGHT "\xef\x80\xb8" // U+f038+#define ICON_FA_ANCHOR "\xef\x84\xbd" // U+f13d+#define ICON_FA_ANCHOR_CIRCLE_CHECK "\xee\x92\xaa" // U+e4aa+#define ICON_FA_ANCHOR_CIRCLE_EXCLAMATION "\xee\x92\xab" // U+e4ab+#define ICON_FA_ANCHOR_CIRCLE_XMARK "\xee\x92\xac" // U+e4ac+#define ICON_FA_ANCHOR_LOCK "\xee\x92\xad" // U+e4ad+#define ICON_FA_ANGLE_DOWN "\xef\x84\x87" // U+f107+#define ICON_FA_ANGLE_LEFT "\xef\x84\x84" // U+f104+#define ICON_FA_ANGLE_RIGHT "\xef\x84\x85" // U+f105+#define ICON_FA_ANGLE_UP "\xef\x84\x86" // U+f106+#define ICON_FA_ANGLES_DOWN "\xef\x84\x83" // U+f103+#define ICON_FA_ANGLES_LEFT "\xef\x84\x80" // U+f100+#define ICON_FA_ANGLES_RIGHT "\xef\x84\x81" // U+f101+#define ICON_FA_ANGLES_UP "\xef\x84\x82" // U+f102+#define ICON_FA_ANKH "\xef\x99\x84" // U+f644+#define ICON_FA_APPLE_WHOLE "\xef\x97\x91" // U+f5d1+#define ICON_FA_ARCHWAY "\xef\x95\x97" // U+f557+#define ICON_FA_ARROW_DOWN "\xef\x81\xa3" // U+f063+#define ICON_FA_ARROW_DOWN_1_9 "\xef\x85\xa2" // U+f162+#define ICON_FA_ARROW_DOWN_9_1 "\xef\xa2\x86" // U+f886+#define ICON_FA_ARROW_DOWN_A_Z "\xef\x85\x9d" // U+f15d+#define ICON_FA_ARROW_DOWN_LONG "\xef\x85\xb5" // U+f175+#define ICON_FA_ARROW_DOWN_SHORT_WIDE "\xef\xa2\x84" // U+f884+#define ICON_FA_ARROW_DOWN_UP_ACROSS_LINE "\xee\x92\xaf" // U+e4af+#define ICON_FA_ARROW_DOWN_UP_LOCK "\xee\x92\xb0" // U+e4b0+#define ICON_FA_ARROW_DOWN_WIDE_SHORT "\xef\x85\xa0" // U+f160+#define ICON_FA_ARROW_DOWN_Z_A "\xef\xa2\x81" // U+f881+#define ICON_FA_ARROW_LEFT "\xef\x81\xa0" // U+f060+#define ICON_FA_ARROW_LEFT_LONG "\xef\x85\xb7" // U+f177+#define ICON_FA_ARROW_POINTER "\xef\x89\x85" // U+f245+#define ICON_FA_ARROW_RIGHT "\xef\x81\xa1" // U+f061+#define ICON_FA_ARROW_RIGHT_ARROW_LEFT "\xef\x83\xac" // U+f0ec+#define ICON_FA_ARROW_RIGHT_FROM_BRACKET "\xef\x82\x8b" // U+f08b+#define ICON_FA_ARROW_RIGHT_LONG "\xef\x85\xb8" // U+f178+#define ICON_FA_ARROW_RIGHT_TO_BRACKET "\xef\x82\x90" // U+f090+#define ICON_FA_ARROW_RIGHT_TO_CITY "\xee\x92\xb3" // U+e4b3+#define ICON_FA_ARROW_ROTATE_LEFT "\xef\x83\xa2" // U+f0e2+#define ICON_FA_ARROW_ROTATE_RIGHT "\xef\x80\x9e" // U+f01e+#define ICON_FA_ARROW_TREND_DOWN "\xee\x82\x97" // U+e097+#define ICON_FA_ARROW_TREND_UP "\xee\x82\x98" // U+e098+#define ICON_FA_ARROW_TURN_DOWN "\xef\x85\x89" // U+f149+#define ICON_FA_ARROW_TURN_UP "\xef\x85\x88" // U+f148+#define ICON_FA_ARROW_UP "\xef\x81\xa2" // U+f062+#define ICON_FA_ARROW_UP_1_9 "\xef\x85\xa3" // U+f163+#define ICON_FA_ARROW_UP_9_1 "\xef\xa2\x87" // U+f887+#define ICON_FA_ARROW_UP_A_Z "\xef\x85\x9e" // U+f15e+#define ICON_FA_ARROW_UP_FROM_BRACKET "\xee\x82\x9a" // U+e09a+#define ICON_FA_ARROW_UP_FROM_GROUND_WATER "\xee\x92\xb5" // U+e4b5+#define ICON_FA_ARROW_UP_FROM_WATER_PUMP "\xee\x92\xb6" // U+e4b6+#define ICON_FA_ARROW_UP_LONG "\xef\x85\xb6" // U+f176+#define ICON_FA_ARROW_UP_RIGHT_DOTS "\xee\x92\xb7" // U+e4b7+#define ICON_FA_ARROW_UP_RIGHT_FROM_SQUARE "\xef\x82\x8e" // U+f08e+#define ICON_FA_ARROW_UP_SHORT_WIDE "\xef\xa2\x85" // U+f885+#define ICON_FA_ARROW_UP_WIDE_SHORT "\xef\x85\xa1" // U+f161+#define ICON_FA_ARROW_UP_Z_A "\xef\xa2\x82" // U+f882+#define ICON_FA_ARROWS_DOWN_TO_LINE "\xee\x92\xb8" // U+e4b8+#define ICON_FA_ARROWS_DOWN_TO_PEOPLE "\xee\x92\xb9" // U+e4b9+#define ICON_FA_ARROWS_LEFT_RIGHT "\xef\x81\xbe" // U+f07e+#define ICON_FA_ARROWS_LEFT_RIGHT_TO_LINE "\xee\x92\xba" // U+e4ba+#define ICON_FA_ARROWS_ROTATE "\xef\x80\xa1" // U+f021+#define ICON_FA_ARROWS_SPIN "\xee\x92\xbb" // U+e4bb+#define ICON_FA_ARROWS_SPLIT_UP_AND_LEFT "\xee\x92\xbc" // U+e4bc+#define ICON_FA_ARROWS_TO_CIRCLE "\xee\x92\xbd" // U+e4bd+#define ICON_FA_ARROWS_TO_DOT "\xee\x92\xbe" // U+e4be+#define ICON_FA_ARROWS_TO_EYE "\xee\x92\xbf" // U+e4bf+#define ICON_FA_ARROWS_TURN_RIGHT "\xee\x93\x80" // U+e4c0+#define ICON_FA_ARROWS_TURN_TO_DOTS "\xee\x93\x81" // U+e4c1+#define ICON_FA_ARROWS_UP_DOWN "\xef\x81\xbd" // U+f07d+#define ICON_FA_ARROWS_UP_DOWN_LEFT_RIGHT "\xef\x81\x87" // U+f047+#define ICON_FA_ARROWS_UP_TO_LINE "\xee\x93\x82" // U+e4c2+#define ICON_FA_ASTERISK "*" // U+002a+#define ICON_FA_AT "@" // U+0040+#define ICON_FA_ATOM "\xef\x97\x92" // U+f5d2+#define ICON_FA_AUDIO_DESCRIPTION "\xef\x8a\x9e" // U+f29e+#define ICON_FA_AUSTRAL_SIGN "\xee\x82\xa9" // U+e0a9+#define ICON_FA_AWARD "\xef\x95\x99" // U+f559+#define ICON_FA_B "B" // U+0042+#define ICON_FA_BABY "\xef\x9d\xbc" // U+f77c+#define ICON_FA_BABY_CARRIAGE "\xef\x9d\xbd" // U+f77d+#define ICON_FA_BACKWARD "\xef\x81\x8a" // U+f04a+#define ICON_FA_BACKWARD_FAST "\xef\x81\x89" // U+f049+#define ICON_FA_BACKWARD_STEP "\xef\x81\x88" // U+f048+#define ICON_FA_BACON "\xef\x9f\xa5" // U+f7e5+#define ICON_FA_BACTERIA "\xee\x81\x99" // U+e059+#define ICON_FA_BACTERIUM "\xee\x81\x9a" // U+e05a+#define ICON_FA_BAG_SHOPPING "\xef\x8a\x90" // U+f290+#define ICON_FA_BAHAI "\xef\x99\xa6" // U+f666+#define ICON_FA_BAHT_SIGN "\xee\x82\xac" // U+e0ac+#define ICON_FA_BAN "\xef\x81\x9e" // U+f05e+#define ICON_FA_BAN_SMOKING "\xef\x95\x8d" // U+f54d+#define ICON_FA_BANDAGE "\xef\x91\xa2" // U+f462+#define ICON_FA_BARCODE "\xef\x80\xaa" // U+f02a+#define ICON_FA_BARS "\xef\x83\x89" // U+f0c9+#define ICON_FA_BARS_PROGRESS "\xef\xa0\xa8" // U+f828+#define ICON_FA_BARS_STAGGERED "\xef\x95\x90" // U+f550+#define ICON_FA_BASEBALL "\xef\x90\xb3" // U+f433+#define ICON_FA_BASEBALL_BAT_BALL "\xef\x90\xb2" // U+f432+#define ICON_FA_BASKET_SHOPPING "\xef\x8a\x91" // U+f291+#define ICON_FA_BASKETBALL "\xef\x90\xb4" // U+f434+#define ICON_FA_BATH "\xef\x8b\x8d" // U+f2cd+#define ICON_FA_BATTERY_EMPTY "\xef\x89\x84" // U+f244+#define ICON_FA_BATTERY_FULL "\xef\x89\x80" // U+f240+#define ICON_FA_BATTERY_HALF "\xef\x89\x82" // U+f242+#define ICON_FA_BATTERY_QUARTER "\xef\x89\x83" // U+f243+#define ICON_FA_BATTERY_THREE_QUARTERS "\xef\x89\x81" // U+f241+#define ICON_FA_BED "\xef\x88\xb6" // U+f236+#define ICON_FA_BED_PULSE "\xef\x92\x87" // U+f487+#define ICON_FA_BEER_MUG_EMPTY "\xef\x83\xbc" // U+f0fc+#define ICON_FA_BELL "\xef\x83\xb3" // U+f0f3+#define ICON_FA_BELL_CONCIERGE "\xef\x95\xa2" // U+f562+#define ICON_FA_BELL_SLASH "\xef\x87\xb6" // U+f1f6+#define ICON_FA_BEZIER_CURVE "\xef\x95\x9b" // U+f55b+#define ICON_FA_BICYCLE "\xef\x88\x86" // U+f206+#define ICON_FA_BINOCULARS "\xef\x87\xa5" // U+f1e5+#define ICON_FA_BIOHAZARD "\xef\x9e\x80" // U+f780+#define ICON_FA_BITCOIN_SIGN "\xee\x82\xb4" // U+e0b4+#define ICON_FA_BLENDER "\xef\x94\x97" // U+f517+#define ICON_FA_BLENDER_PHONE "\xef\x9a\xb6" // U+f6b6+#define ICON_FA_BLOG "\xef\x9e\x81" // U+f781+#define ICON_FA_BOLD "\xef\x80\xb2" // U+f032+#define ICON_FA_BOLT "\xef\x83\xa7" // U+f0e7+#define ICON_FA_BOLT_LIGHTNING "\xee\x82\xb7" // U+e0b7+#define ICON_FA_BOMB "\xef\x87\xa2" // U+f1e2+#define ICON_FA_BONE "\xef\x97\x97" // U+f5d7+#define ICON_FA_BONG "\xef\x95\x9c" // U+f55c+#define ICON_FA_BOOK "\xef\x80\xad" // U+f02d+#define ICON_FA_BOOK_ATLAS "\xef\x95\x98" // U+f558+#define ICON_FA_BOOK_BIBLE "\xef\x99\x87" // U+f647+#define ICON_FA_BOOK_BOOKMARK "\xee\x82\xbb" // U+e0bb+#define ICON_FA_BOOK_JOURNAL_WHILLS "\xef\x99\xaa" // U+f66a+#define ICON_FA_BOOK_MEDICAL "\xef\x9f\xa6" // U+f7e6+#define ICON_FA_BOOK_OPEN "\xef\x94\x98" // U+f518+#define ICON_FA_BOOK_OPEN_READER "\xef\x97\x9a" // U+f5da+#define ICON_FA_BOOK_QURAN "\xef\x9a\x87" // U+f687+#define ICON_FA_BOOK_SKULL "\xef\x9a\xb7" // U+f6b7+#define ICON_FA_BOOK_TANAKH "\xef\xa0\xa7" // U+f827+#define ICON_FA_BOOKMARK "\xef\x80\xae" // U+f02e+#define ICON_FA_BORDER_ALL "\xef\xa1\x8c" // U+f84c+#define ICON_FA_BORDER_NONE "\xef\xa1\x90" // U+f850+#define ICON_FA_BORDER_TOP_LEFT "\xef\xa1\x93" // U+f853+#define ICON_FA_BORE_HOLE "\xee\x93\x83" // U+e4c3+#define ICON_FA_BOTTLE_DROPLET "\xee\x93\x84" // U+e4c4+#define ICON_FA_BOTTLE_WATER "\xee\x93\x85" // U+e4c5+#define ICON_FA_BOWL_FOOD "\xee\x93\x86" // U+e4c6+#define ICON_FA_BOWL_RICE "\xee\x8b\xab" // U+e2eb+#define ICON_FA_BOWLING_BALL "\xef\x90\xb6" // U+f436+#define ICON_FA_BOX "\xef\x91\xa6" // U+f466+#define ICON_FA_BOX_ARCHIVE "\xef\x86\x87" // U+f187+#define ICON_FA_BOX_OPEN "\xef\x92\x9e" // U+f49e+#define ICON_FA_BOX_TISSUE "\xee\x81\x9b" // U+e05b+#define ICON_FA_BOXES_PACKING "\xee\x93\x87" // U+e4c7+#define ICON_FA_BOXES_STACKED "\xef\x91\xa8" // U+f468+#define ICON_FA_BRAILLE "\xef\x8a\xa1" // U+f2a1+#define ICON_FA_BRAIN "\xef\x97\x9c" // U+f5dc+#define ICON_FA_BRAZILIAN_REAL_SIGN "\xee\x91\xac" // U+e46c+#define ICON_FA_BREAD_SLICE "\xef\x9f\xac" // U+f7ec+#define ICON_FA_BRIDGE "\xee\x93\x88" // U+e4c8+#define ICON_FA_BRIDGE_CIRCLE_CHECK "\xee\x93\x89" // U+e4c9+#define ICON_FA_BRIDGE_CIRCLE_EXCLAMATION "\xee\x93\x8a" // U+e4ca+#define ICON_FA_BRIDGE_CIRCLE_XMARK "\xee\x93\x8b" // U+e4cb+#define ICON_FA_BRIDGE_LOCK "\xee\x93\x8c" // U+e4cc+#define ICON_FA_BRIDGE_WATER "\xee\x93\x8e" // U+e4ce+#define ICON_FA_BRIEFCASE "\xef\x82\xb1" // U+f0b1+#define ICON_FA_BRIEFCASE_MEDICAL "\xef\x91\xa9" // U+f469+#define ICON_FA_BROOM "\xef\x94\x9a" // U+f51a+#define ICON_FA_BROOM_BALL "\xef\x91\x98" // U+f458+#define ICON_FA_BRUSH "\xef\x95\x9d" // U+f55d+#define ICON_FA_BUCKET "\xee\x93\x8f" // U+e4cf+#define ICON_FA_BUG "\xef\x86\x88" // U+f188+#define ICON_FA_BUG_SLASH "\xee\x92\x90" // U+e490+#define ICON_FA_BUGS "\xee\x93\x90" // U+e4d0+#define ICON_FA_BUILDING "\xef\x86\xad" // U+f1ad+#define ICON_FA_BUILDING_CIRCLE_ARROW_RIGHT "\xee\x93\x91" // U+e4d1+#define ICON_FA_BUILDING_CIRCLE_CHECK "\xee\x93\x92" // U+e4d2+#define ICON_FA_BUILDING_CIRCLE_EXCLAMATION "\xee\x93\x93" // U+e4d3+#define ICON_FA_BUILDING_CIRCLE_XMARK "\xee\x93\x94" // U+e4d4+#define ICON_FA_BUILDING_COLUMNS "\xef\x86\x9c" // U+f19c+#define ICON_FA_BUILDING_FLAG "\xee\x93\x95" // U+e4d5+#define ICON_FA_BUILDING_LOCK "\xee\x93\x96" // U+e4d6+#define ICON_FA_BUILDING_NGO "\xee\x93\x97" // U+e4d7+#define ICON_FA_BUILDING_SHIELD "\xee\x93\x98" // U+e4d8+#define ICON_FA_BUILDING_UN "\xee\x93\x99" // U+e4d9+#define ICON_FA_BUILDING_USER "\xee\x93\x9a" // U+e4da+#define ICON_FA_BUILDING_WHEAT "\xee\x93\x9b" // U+e4db+#define ICON_FA_BULLHORN "\xef\x82\xa1" // U+f0a1+#define ICON_FA_BULLSEYE "\xef\x85\x80" // U+f140+#define ICON_FA_BURGER "\xef\xa0\x85" // U+f805+#define ICON_FA_BURST "\xee\x93\x9c" // U+e4dc+#define ICON_FA_BUS "\xef\x88\x87" // U+f207+#define ICON_FA_BUS_SIMPLE "\xef\x95\x9e" // U+f55e+#define ICON_FA_BUSINESS_TIME "\xef\x99\x8a" // U+f64a+#define ICON_FA_C "C" // U+0043+#define ICON_FA_CABLE_CAR "\xef\x9f\x9a" // U+f7da+#define ICON_FA_CAKE_CANDLES "\xef\x87\xbd" // U+f1fd+#define ICON_FA_CALCULATOR "\xef\x87\xac" // U+f1ec+#define ICON_FA_CALENDAR "\xef\x84\xb3" // U+f133+#define ICON_FA_CALENDAR_CHECK "\xef\x89\xb4" // U+f274+#define ICON_FA_CALENDAR_DAY "\xef\x9e\x83" // U+f783+#define ICON_FA_CALENDAR_DAYS "\xef\x81\xb3" // U+f073+#define ICON_FA_CALENDAR_MINUS "\xef\x89\xb2" // U+f272+#define ICON_FA_CALENDAR_PLUS "\xef\x89\xb1" // U+f271+#define ICON_FA_CALENDAR_WEEK "\xef\x9e\x84" // U+f784+#define ICON_FA_CALENDAR_XMARK "\xef\x89\xb3" // U+f273+#define ICON_FA_CAMERA "\xef\x80\xb0" // U+f030+#define ICON_FA_CAMERA_RETRO "\xef\x82\x83" // U+f083+#define ICON_FA_CAMERA_ROTATE "\xee\x83\x98" // U+e0d8+#define ICON_FA_CAMPGROUND "\xef\x9a\xbb" // U+f6bb+#define ICON_FA_CANDY_CANE "\xef\x9e\x86" // U+f786+#define ICON_FA_CANNABIS "\xef\x95\x9f" // U+f55f+#define ICON_FA_CAPSULES "\xef\x91\xab" // U+f46b+#define ICON_FA_CAR "\xef\x86\xb9" // U+f1b9+#define ICON_FA_CAR_BATTERY "\xef\x97\x9f" // U+f5df+#define ICON_FA_CAR_BURST "\xef\x97\xa1" // U+f5e1+#define ICON_FA_CAR_ON "\xee\x93\x9d" // U+e4dd+#define ICON_FA_CAR_REAR "\xef\x97\x9e" // U+f5de+#define ICON_FA_CAR_SIDE "\xef\x97\xa4" // U+f5e4+#define ICON_FA_CAR_TUNNEL "\xee\x93\x9e" // U+e4de+#define ICON_FA_CARAVAN "\xef\xa3\xbf" // U+f8ff+#define ICON_FA_CARET_DOWN "\xef\x83\x97" // U+f0d7+#define ICON_FA_CARET_LEFT "\xef\x83\x99" // U+f0d9+#define ICON_FA_CARET_RIGHT "\xef\x83\x9a" // U+f0da+#define ICON_FA_CARET_UP "\xef\x83\x98" // U+f0d8+#define ICON_FA_CARROT "\xef\x9e\x87" // U+f787+#define ICON_FA_CART_ARROW_DOWN "\xef\x88\x98" // U+f218+#define ICON_FA_CART_FLATBED "\xef\x91\xb4" // U+f474+#define ICON_FA_CART_FLATBED_SUITCASE "\xef\x96\x9d" // U+f59d+#define ICON_FA_CART_PLUS "\xef\x88\x97" // U+f217+#define ICON_FA_CART_SHOPPING "\xef\x81\xba" // U+f07a+#define ICON_FA_CASH_REGISTER "\xef\x9e\x88" // U+f788+#define ICON_FA_CAT "\xef\x9a\xbe" // U+f6be+#define ICON_FA_CEDI_SIGN "\xee\x83\x9f" // U+e0df+#define ICON_FA_CENT_SIGN "\xee\x8f\xb5" // U+e3f5+#define ICON_FA_CERTIFICATE "\xef\x82\xa3" // U+f0a3+#define ICON_FA_CHAIR "\xef\x9b\x80" // U+f6c0+#define ICON_FA_CHALKBOARD "\xef\x94\x9b" // U+f51b+#define ICON_FA_CHALKBOARD_USER "\xef\x94\x9c" // U+f51c+#define ICON_FA_CHAMPAGNE_GLASSES "\xef\x9e\x9f" // U+f79f+#define ICON_FA_CHARGING_STATION "\xef\x97\xa7" // U+f5e7+#define ICON_FA_CHART_AREA "\xef\x87\xbe" // U+f1fe+#define ICON_FA_CHART_BAR "\xef\x82\x80" // U+f080+#define ICON_FA_CHART_COLUMN "\xee\x83\xa3" // U+e0e3+#define ICON_FA_CHART_GANTT "\xee\x83\xa4" // U+e0e4+#define ICON_FA_CHART_LINE "\xef\x88\x81" // U+f201+#define ICON_FA_CHART_PIE "\xef\x88\x80" // U+f200+#define ICON_FA_CHART_SIMPLE "\xee\x91\xb3" // U+e473+#define ICON_FA_CHECK "\xef\x80\x8c" // U+f00c+#define ICON_FA_CHECK_DOUBLE "\xef\x95\xa0" // U+f560+#define ICON_FA_CHECK_TO_SLOT "\xef\x9d\xb2" // U+f772+#define ICON_FA_CHEESE "\xef\x9f\xaf" // U+f7ef+#define ICON_FA_CHESS "\xef\x90\xb9" // U+f439+#define ICON_FA_CHESS_BISHOP "\xef\x90\xba" // U+f43a+#define ICON_FA_CHESS_BOARD "\xef\x90\xbc" // U+f43c+#define ICON_FA_CHESS_KING "\xef\x90\xbf" // U+f43f+#define ICON_FA_CHESS_KNIGHT "\xef\x91\x81" // U+f441+#define ICON_FA_CHESS_PAWN "\xef\x91\x83" // U+f443+#define ICON_FA_CHESS_QUEEN "\xef\x91\x85" // U+f445+#define ICON_FA_CHESS_ROOK "\xef\x91\x87" // U+f447+#define ICON_FA_CHEVRON_DOWN "\xef\x81\xb8" // U+f078+#define ICON_FA_CHEVRON_LEFT "\xef\x81\x93" // U+f053+#define ICON_FA_CHEVRON_RIGHT "\xef\x81\x94" // U+f054+#define ICON_FA_CHEVRON_UP "\xef\x81\xb7" // U+f077+#define ICON_FA_CHILD "\xef\x86\xae" // U+f1ae+#define ICON_FA_CHILD_DRESS "\xee\x96\x9c" // U+e59c+#define ICON_FA_CHILD_REACHING "\xee\x96\x9d" // U+e59d+#define ICON_FA_CHILD_RIFLE "\xee\x93\xa0" // U+e4e0+#define ICON_FA_CHILDREN "\xee\x93\xa1" // U+e4e1+#define ICON_FA_CHURCH "\xef\x94\x9d" // U+f51d+#define ICON_FA_CIRCLE "\xef\x84\x91" // U+f111+#define ICON_FA_CIRCLE_ARROW_DOWN "\xef\x82\xab" // U+f0ab+#define ICON_FA_CIRCLE_ARROW_LEFT "\xef\x82\xa8" // U+f0a8+#define ICON_FA_CIRCLE_ARROW_RIGHT "\xef\x82\xa9" // U+f0a9+#define ICON_FA_CIRCLE_ARROW_UP "\xef\x82\xaa" // U+f0aa+#define ICON_FA_CIRCLE_CHECK "\xef\x81\x98" // U+f058+#define ICON_FA_CIRCLE_CHEVRON_DOWN "\xef\x84\xba" // U+f13a+#define ICON_FA_CIRCLE_CHEVRON_LEFT "\xef\x84\xb7" // U+f137+#define ICON_FA_CIRCLE_CHEVRON_RIGHT "\xef\x84\xb8" // U+f138+#define ICON_FA_CIRCLE_CHEVRON_UP "\xef\x84\xb9" // U+f139+#define ICON_FA_CIRCLE_DOLLAR_TO_SLOT "\xef\x92\xb9" // U+f4b9+#define ICON_FA_CIRCLE_DOT "\xef\x86\x92" // U+f192+#define ICON_FA_CIRCLE_DOWN "\xef\x8d\x98" // U+f358+#define ICON_FA_CIRCLE_EXCLAMATION "\xef\x81\xaa" // U+f06a+#define ICON_FA_CIRCLE_H "\xef\x91\xbe" // U+f47e+#define ICON_FA_CIRCLE_HALF_STROKE "\xef\x81\x82" // U+f042+#define ICON_FA_CIRCLE_INFO "\xef\x81\x9a" // U+f05a+#define ICON_FA_CIRCLE_LEFT "\xef\x8d\x99" // U+f359+#define ICON_FA_CIRCLE_MINUS "\xef\x81\x96" // U+f056+#define ICON_FA_CIRCLE_NODES "\xee\x93\xa2" // U+e4e2+#define ICON_FA_CIRCLE_NOTCH "\xef\x87\x8e" // U+f1ce+#define ICON_FA_CIRCLE_PAUSE "\xef\x8a\x8b" // U+f28b+#define ICON_FA_CIRCLE_PLAY "\xef\x85\x84" // U+f144+#define ICON_FA_CIRCLE_PLUS "\xef\x81\x95" // U+f055+#define ICON_FA_CIRCLE_QUESTION "\xef\x81\x99" // U+f059+#define ICON_FA_CIRCLE_RADIATION "\xef\x9e\xba" // U+f7ba+#define ICON_FA_CIRCLE_RIGHT "\xef\x8d\x9a" // U+f35a+#define ICON_FA_CIRCLE_STOP "\xef\x8a\x8d" // U+f28d+#define ICON_FA_CIRCLE_UP "\xef\x8d\x9b" // U+f35b+#define ICON_FA_CIRCLE_USER "\xef\x8a\xbd" // U+f2bd+#define ICON_FA_CIRCLE_XMARK "\xef\x81\x97" // U+f057+#define ICON_FA_CITY "\xef\x99\x8f" // U+f64f+#define ICON_FA_CLAPPERBOARD "\xee\x84\xb1" // U+e131+#define ICON_FA_CLIPBOARD "\xef\x8c\xa8" // U+f328+#define ICON_FA_CLIPBOARD_CHECK "\xef\x91\xac" // U+f46c+#define ICON_FA_CLIPBOARD_LIST "\xef\x91\xad" // U+f46d+#define ICON_FA_CLIPBOARD_QUESTION "\xee\x93\xa3" // U+e4e3+#define ICON_FA_CLIPBOARD_USER "\xef\x9f\xb3" // U+f7f3+#define ICON_FA_CLOCK "\xef\x80\x97" // U+f017+#define ICON_FA_CLOCK_ROTATE_LEFT "\xef\x87\x9a" // U+f1da+#define ICON_FA_CLONE "\xef\x89\x8d" // U+f24d+#define ICON_FA_CLOSED_CAPTIONING "\xef\x88\x8a" // U+f20a+#define ICON_FA_CLOUD "\xef\x83\x82" // U+f0c2+#define ICON_FA_CLOUD_ARROW_DOWN "\xef\x83\xad" // U+f0ed+#define ICON_FA_CLOUD_ARROW_UP "\xef\x83\xae" // U+f0ee+#define ICON_FA_CLOUD_BOLT "\xef\x9d\xac" // U+f76c+#define ICON_FA_CLOUD_MEATBALL "\xef\x9c\xbb" // U+f73b+#define ICON_FA_CLOUD_MOON "\xef\x9b\x83" // U+f6c3+#define ICON_FA_CLOUD_MOON_RAIN "\xef\x9c\xbc" // U+f73c+#define ICON_FA_CLOUD_RAIN "\xef\x9c\xbd" // U+f73d+#define ICON_FA_CLOUD_SHOWERS_HEAVY "\xef\x9d\x80" // U+f740+#define ICON_FA_CLOUD_SHOWERS_WATER "\xee\x93\xa4" // U+e4e4+#define ICON_FA_CLOUD_SUN "\xef\x9b\x84" // U+f6c4+#define ICON_FA_CLOUD_SUN_RAIN "\xef\x9d\x83" // U+f743+#define ICON_FA_CLOVER "\xee\x84\xb9" // U+e139+#define ICON_FA_CODE "\xef\x84\xa1" // U+f121+#define ICON_FA_CODE_BRANCH "\xef\x84\xa6" // U+f126+#define ICON_FA_CODE_COMMIT "\xef\x8e\x86" // U+f386+#define ICON_FA_CODE_COMPARE "\xee\x84\xba" // U+e13a+#define ICON_FA_CODE_FORK "\xee\x84\xbb" // U+e13b+#define ICON_FA_CODE_MERGE "\xef\x8e\x87" // U+f387+#define ICON_FA_CODE_PULL_REQUEST "\xee\x84\xbc" // U+e13c+#define ICON_FA_COINS "\xef\x94\x9e" // U+f51e+#define ICON_FA_COLON_SIGN "\xee\x85\x80" // U+e140+#define ICON_FA_COMMENT "\xef\x81\xb5" // U+f075+#define ICON_FA_COMMENT_DOLLAR "\xef\x99\x91" // U+f651+#define ICON_FA_COMMENT_DOTS "\xef\x92\xad" // U+f4ad+#define ICON_FA_COMMENT_MEDICAL "\xef\x9f\xb5" // U+f7f5+#define ICON_FA_COMMENT_SLASH "\xef\x92\xb3" // U+f4b3+#define ICON_FA_COMMENT_SMS "\xef\x9f\x8d" // U+f7cd+#define ICON_FA_COMMENTS "\xef\x82\x86" // U+f086+#define ICON_FA_COMMENTS_DOLLAR "\xef\x99\x93" // U+f653+#define ICON_FA_COMPACT_DISC "\xef\x94\x9f" // U+f51f+#define ICON_FA_COMPASS "\xef\x85\x8e" // U+f14e+#define ICON_FA_COMPASS_DRAFTING "\xef\x95\xa8" // U+f568+#define ICON_FA_COMPRESS "\xef\x81\xa6" // U+f066+#define ICON_FA_COMPUTER "\xee\x93\xa5" // U+e4e5+#define ICON_FA_COMPUTER_MOUSE "\xef\xa3\x8c" // U+f8cc+#define ICON_FA_COOKIE "\xef\x95\xa3" // U+f563+#define ICON_FA_COOKIE_BITE "\xef\x95\xa4" // U+f564+#define ICON_FA_COPY "\xef\x83\x85" // U+f0c5+#define ICON_FA_COPYRIGHT "\xef\x87\xb9" // U+f1f9+#define ICON_FA_COUCH "\xef\x92\xb8" // U+f4b8+#define ICON_FA_COW "\xef\x9b\x88" // U+f6c8+#define ICON_FA_CREDIT_CARD "\xef\x82\x9d" // U+f09d+#define ICON_FA_CROP "\xef\x84\xa5" // U+f125+#define ICON_FA_CROP_SIMPLE "\xef\x95\xa5" // U+f565+#define ICON_FA_CROSS "\xef\x99\x94" // U+f654+#define ICON_FA_CROSSHAIRS "\xef\x81\x9b" // U+f05b+#define ICON_FA_CROW "\xef\x94\xa0" // U+f520+#define ICON_FA_CROWN "\xef\x94\xa1" // U+f521+#define ICON_FA_CRUTCH "\xef\x9f\xb7" // U+f7f7+#define ICON_FA_CRUZEIRO_SIGN "\xee\x85\x92" // U+e152+#define ICON_FA_CUBE "\xef\x86\xb2" // U+f1b2+#define ICON_FA_CUBES "\xef\x86\xb3" // U+f1b3+#define ICON_FA_CUBES_STACKED "\xee\x93\xa6" // U+e4e6+#define ICON_FA_D "D" // U+0044+#define ICON_FA_DATABASE "\xef\x87\x80" // U+f1c0+#define ICON_FA_DELETE_LEFT "\xef\x95\x9a" // U+f55a+#define ICON_FA_DEMOCRAT "\xef\x9d\x87" // U+f747+#define ICON_FA_DESKTOP "\xef\x8e\x90" // U+f390+#define ICON_FA_DHARMACHAKRA "\xef\x99\x95" // U+f655+#define ICON_FA_DIAGRAM_NEXT "\xee\x91\xb6" // U+e476+#define ICON_FA_DIAGRAM_PREDECESSOR "\xee\x91\xb7" // U+e477+#define ICON_FA_DIAGRAM_PROJECT "\xef\x95\x82" // U+f542+#define ICON_FA_DIAGRAM_SUCCESSOR "\xee\x91\xba" // U+e47a+#define ICON_FA_DIAMOND "\xef\x88\x99" // U+f219+#define ICON_FA_DIAMOND_TURN_RIGHT "\xef\x97\xab" // U+f5eb+#define ICON_FA_DICE "\xef\x94\xa2" // U+f522+#define ICON_FA_DICE_D20 "\xef\x9b\x8f" // U+f6cf+#define ICON_FA_DICE_D6 "\xef\x9b\x91" // U+f6d1+#define ICON_FA_DICE_FIVE "\xef\x94\xa3" // U+f523+#define ICON_FA_DICE_FOUR "\xef\x94\xa4" // U+f524+#define ICON_FA_DICE_ONE "\xef\x94\xa5" // U+f525+#define ICON_FA_DICE_SIX "\xef\x94\xa6" // U+f526+#define ICON_FA_DICE_THREE "\xef\x94\xa7" // U+f527+#define ICON_FA_DICE_TWO "\xef\x94\xa8" // U+f528+#define ICON_FA_DISEASE "\xef\x9f\xba" // U+f7fa+#define ICON_FA_DISPLAY "\xee\x85\xa3" // U+e163+#define ICON_FA_DIVIDE "\xef\x94\xa9" // U+f529+#define ICON_FA_DNA "\xef\x91\xb1" // U+f471+#define ICON_FA_DOG "\xef\x9b\x93" // U+f6d3+#define ICON_FA_DOLLAR_SIGN "$" // U+0024+#define ICON_FA_DOLLY "\xef\x91\xb2" // U+f472+#define ICON_FA_DONG_SIGN "\xee\x85\xa9" // U+e169+#define ICON_FA_DOOR_CLOSED "\xef\x94\xaa" // U+f52a+#define ICON_FA_DOOR_OPEN "\xef\x94\xab" // U+f52b+#define ICON_FA_DOVE "\xef\x92\xba" // U+f4ba+#define ICON_FA_DOWN_LEFT_AND_UP_RIGHT_TO_CENTER "\xef\x90\xa2" // U+f422+#define ICON_FA_DOWN_LONG "\xef\x8c\x89" // U+f309+#define ICON_FA_DOWNLOAD "\xef\x80\x99" // U+f019+#define ICON_FA_DRAGON "\xef\x9b\x95" // U+f6d5+#define ICON_FA_DRAW_POLYGON "\xef\x97\xae" // U+f5ee+#define ICON_FA_DROPLET "\xef\x81\x83" // U+f043+#define ICON_FA_DROPLET_SLASH "\xef\x97\x87" // U+f5c7+#define ICON_FA_DRUM "\xef\x95\xa9" // U+f569+#define ICON_FA_DRUM_STEELPAN "\xef\x95\xaa" // U+f56a+#define ICON_FA_DRUMSTICK_BITE "\xef\x9b\x97" // U+f6d7+#define ICON_FA_DUMBBELL "\xef\x91\x8b" // U+f44b+#define ICON_FA_DUMPSTER "\xef\x9e\x93" // U+f793+#define ICON_FA_DUMPSTER_FIRE "\xef\x9e\x94" // U+f794+#define ICON_FA_DUNGEON "\xef\x9b\x99" // U+f6d9+#define ICON_FA_E "E" // U+0045+#define ICON_FA_EAR_DEAF "\xef\x8a\xa4" // U+f2a4+#define ICON_FA_EAR_LISTEN "\xef\x8a\xa2" // U+f2a2+#define ICON_FA_EARTH_AFRICA "\xef\x95\xbc" // U+f57c+#define ICON_FA_EARTH_AMERICAS "\xef\x95\xbd" // U+f57d+#define ICON_FA_EARTH_ASIA "\xef\x95\xbe" // U+f57e+#define ICON_FA_EARTH_EUROPE "\xef\x9e\xa2" // U+f7a2+#define ICON_FA_EARTH_OCEANIA "\xee\x91\xbb" // U+e47b+#define ICON_FA_EGG "\xef\x9f\xbb" // U+f7fb+#define ICON_FA_EJECT "\xef\x81\x92" // U+f052+#define ICON_FA_ELEVATOR "\xee\x85\xad" // U+e16d+#define ICON_FA_ELLIPSIS "\xef\x85\x81" // U+f141+#define ICON_FA_ELLIPSIS_VERTICAL "\xef\x85\x82" // U+f142+#define ICON_FA_ENVELOPE "\xef\x83\xa0" // U+f0e0+#define ICON_FA_ENVELOPE_CIRCLE_CHECK "\xee\x93\xa8" // U+e4e8+#define ICON_FA_ENVELOPE_OPEN "\xef\x8a\xb6" // U+f2b6+#define ICON_FA_ENVELOPE_OPEN_TEXT "\xef\x99\x98" // U+f658+#define ICON_FA_ENVELOPES_BULK "\xef\x99\xb4" // U+f674+#define ICON_FA_EQUALS "=" // U+003d+#define ICON_FA_ERASER "\xef\x84\xad" // U+f12d+#define ICON_FA_ETHERNET "\xef\x9e\x96" // U+f796+#define ICON_FA_EURO_SIGN "\xef\x85\x93" // U+f153+#define ICON_FA_EXCLAMATION "!" // U+0021+#define ICON_FA_EXPAND "\xef\x81\xa5" // U+f065+#define ICON_FA_EXPLOSION "\xee\x93\xa9" // U+e4e9+#define ICON_FA_EYE "\xef\x81\xae" // U+f06e+#define ICON_FA_EYE_DROPPER "\xef\x87\xbb" // U+f1fb+#define ICON_FA_EYE_LOW_VISION "\xef\x8a\xa8" // U+f2a8+#define ICON_FA_EYE_SLASH "\xef\x81\xb0" // U+f070+#define ICON_FA_F "F" // U+0046+#define ICON_FA_FACE_ANGRY "\xef\x95\x96" // U+f556+#define ICON_FA_FACE_DIZZY "\xef\x95\xa7" // U+f567+#define ICON_FA_FACE_FLUSHED "\xef\x95\xb9" // U+f579+#define ICON_FA_FACE_FROWN "\xef\x84\x99" // U+f119+#define ICON_FA_FACE_FROWN_OPEN "\xef\x95\xba" // U+f57a+#define ICON_FA_FACE_GRIMACE "\xef\x95\xbf" // U+f57f+#define ICON_FA_FACE_GRIN "\xef\x96\x80" // U+f580+#define ICON_FA_FACE_GRIN_BEAM "\xef\x96\x82" // U+f582+#define ICON_FA_FACE_GRIN_BEAM_SWEAT "\xef\x96\x83" // U+f583+#define ICON_FA_FACE_GRIN_HEARTS "\xef\x96\x84" // U+f584+#define ICON_FA_FACE_GRIN_SQUINT "\xef\x96\x85" // U+f585+#define ICON_FA_FACE_GRIN_SQUINT_TEARS "\xef\x96\x86" // U+f586+#define ICON_FA_FACE_GRIN_STARS "\xef\x96\x87" // U+f587+#define ICON_FA_FACE_GRIN_TEARS "\xef\x96\x88" // U+f588+#define ICON_FA_FACE_GRIN_TONGUE "\xef\x96\x89" // U+f589+#define ICON_FA_FACE_GRIN_TONGUE_SQUINT "\xef\x96\x8a" // U+f58a+#define ICON_FA_FACE_GRIN_TONGUE_WINK "\xef\x96\x8b" // U+f58b+#define ICON_FA_FACE_GRIN_WIDE "\xef\x96\x81" // U+f581+#define ICON_FA_FACE_GRIN_WINK "\xef\x96\x8c" // U+f58c+#define ICON_FA_FACE_KISS "\xef\x96\x96" // U+f596+#define ICON_FA_FACE_KISS_BEAM "\xef\x96\x97" // U+f597+#define ICON_FA_FACE_KISS_WINK_HEART "\xef\x96\x98" // U+f598+#define ICON_FA_FACE_LAUGH "\xef\x96\x99" // U+f599+#define ICON_FA_FACE_LAUGH_BEAM "\xef\x96\x9a" // U+f59a+#define ICON_FA_FACE_LAUGH_SQUINT "\xef\x96\x9b" // U+f59b+#define ICON_FA_FACE_LAUGH_WINK "\xef\x96\x9c" // U+f59c+#define ICON_FA_FACE_MEH "\xef\x84\x9a" // U+f11a+#define ICON_FA_FACE_MEH_BLANK "\xef\x96\xa4" // U+f5a4+#define ICON_FA_FACE_ROLLING_EYES "\xef\x96\xa5" // U+f5a5+#define ICON_FA_FACE_SAD_CRY "\xef\x96\xb3" // U+f5b3+#define ICON_FA_FACE_SAD_TEAR "\xef\x96\xb4" // U+f5b4+#define ICON_FA_FACE_SMILE "\xef\x84\x98" // U+f118+#define ICON_FA_FACE_SMILE_BEAM "\xef\x96\xb8" // U+f5b8+#define ICON_FA_FACE_SMILE_WINK "\xef\x93\x9a" // U+f4da+#define ICON_FA_FACE_SURPRISE "\xef\x97\x82" // U+f5c2+#define ICON_FA_FACE_TIRED "\xef\x97\x88" // U+f5c8+#define ICON_FA_FAN "\xef\xa1\xa3" // U+f863+#define ICON_FA_FAUCET "\xee\x80\x85" // U+e005+#define ICON_FA_FAUCET_DRIP "\xee\x80\x86" // U+e006+#define ICON_FA_FAX "\xef\x86\xac" // U+f1ac+#define ICON_FA_FEATHER "\xef\x94\xad" // U+f52d+#define ICON_FA_FEATHER_POINTED "\xef\x95\xab" // U+f56b+#define ICON_FA_FERRY "\xee\x93\xaa" // U+e4ea+#define ICON_FA_FILE "\xef\x85\x9b" // U+f15b+#define ICON_FA_FILE_ARROW_DOWN "\xef\x95\xad" // U+f56d+#define ICON_FA_FILE_ARROW_UP "\xef\x95\xb4" // U+f574+#define ICON_FA_FILE_AUDIO "\xef\x87\x87" // U+f1c7+#define ICON_FA_FILE_CIRCLE_CHECK "\xee\x96\xa0" // U+e5a0+#define ICON_FA_FILE_CIRCLE_EXCLAMATION "\xee\x93\xab" // U+e4eb+#define ICON_FA_FILE_CIRCLE_MINUS "\xee\x93\xad" // U+e4ed+#define ICON_FA_FILE_CIRCLE_PLUS "\xee\x92\x94" // U+e494+#define ICON_FA_FILE_CIRCLE_QUESTION "\xee\x93\xaf" // U+e4ef+#define ICON_FA_FILE_CIRCLE_XMARK "\xee\x96\xa1" // U+e5a1+#define ICON_FA_FILE_CODE "\xef\x87\x89" // U+f1c9+#define ICON_FA_FILE_CONTRACT "\xef\x95\xac" // U+f56c+#define ICON_FA_FILE_CSV "\xef\x9b\x9d" // U+f6dd+#define ICON_FA_FILE_EXCEL "\xef\x87\x83" // U+f1c3+#define ICON_FA_FILE_EXPORT "\xef\x95\xae" // U+f56e+#define ICON_FA_FILE_IMAGE "\xef\x87\x85" // U+f1c5+#define ICON_FA_FILE_IMPORT "\xef\x95\xaf" // U+f56f+#define ICON_FA_FILE_INVOICE "\xef\x95\xb0" // U+f570+#define ICON_FA_FILE_INVOICE_DOLLAR "\xef\x95\xb1" // U+f571+#define ICON_FA_FILE_LINES "\xef\x85\x9c" // U+f15c+#define ICON_FA_FILE_MEDICAL "\xef\x91\xb7" // U+f477+#define ICON_FA_FILE_PDF "\xef\x87\x81" // U+f1c1+#define ICON_FA_FILE_PEN "\xef\x8c\x9c" // U+f31c+#define ICON_FA_FILE_POWERPOINT "\xef\x87\x84" // U+f1c4+#define ICON_FA_FILE_PRESCRIPTION "\xef\x95\xb2" // U+f572+#define ICON_FA_FILE_SHIELD "\xee\x93\xb0" // U+e4f0+#define ICON_FA_FILE_SIGNATURE "\xef\x95\xb3" // U+f573+#define ICON_FA_FILE_VIDEO "\xef\x87\x88" // U+f1c8+#define ICON_FA_FILE_WAVEFORM "\xef\x91\xb8" // U+f478+#define ICON_FA_FILE_WORD "\xef\x87\x82" // U+f1c2+#define ICON_FA_FILE_ZIPPER "\xef\x87\x86" // U+f1c6+#define ICON_FA_FILL "\xef\x95\xb5" // U+f575+#define ICON_FA_FILL_DRIP "\xef\x95\xb6" // U+f576+#define ICON_FA_FILM "\xef\x80\x88" // U+f008+#define ICON_FA_FILTER "\xef\x82\xb0" // U+f0b0+#define ICON_FA_FILTER_CIRCLE_DOLLAR "\xef\x99\xa2" // U+f662+#define ICON_FA_FILTER_CIRCLE_XMARK "\xee\x85\xbb" // U+e17b+#define ICON_FA_FINGERPRINT "\xef\x95\xb7" // U+f577+#define ICON_FA_FIRE "\xef\x81\xad" // U+f06d+#define ICON_FA_FIRE_BURNER "\xee\x93\xb1" // U+e4f1+#define ICON_FA_FIRE_EXTINGUISHER "\xef\x84\xb4" // U+f134+#define ICON_FA_FIRE_FLAME_CURVED "\xef\x9f\xa4" // U+f7e4+#define ICON_FA_FIRE_FLAME_SIMPLE "\xef\x91\xaa" // U+f46a+#define ICON_FA_FISH "\xef\x95\xb8" // U+f578+#define ICON_FA_FISH_FINS "\xee\x93\xb2" // U+e4f2+#define ICON_FA_FLAG "\xef\x80\xa4" // U+f024+#define ICON_FA_FLAG_CHECKERED "\xef\x84\x9e" // U+f11e+#define ICON_FA_FLAG_USA "\xef\x9d\x8d" // U+f74d+#define ICON_FA_FLASK "\xef\x83\x83" // U+f0c3+#define ICON_FA_FLASK_VIAL "\xee\x93\xb3" // U+e4f3+#define ICON_FA_FLOPPY_DISK "\xef\x83\x87" // U+f0c7+#define ICON_FA_FLORIN_SIGN "\xee\x86\x84" // U+e184+#define ICON_FA_FOLDER "\xef\x81\xbb" // U+f07b+#define ICON_FA_FOLDER_CLOSED "\xee\x86\x85" // U+e185+#define ICON_FA_FOLDER_MINUS "\xef\x99\x9d" // U+f65d+#define ICON_FA_FOLDER_OPEN "\xef\x81\xbc" // U+f07c+#define ICON_FA_FOLDER_PLUS "\xef\x99\x9e" // U+f65e+#define ICON_FA_FOLDER_TREE "\xef\xa0\x82" // U+f802+#define ICON_FA_FONT "\xef\x80\xb1" // U+f031+#define ICON_FA_FONT_AWESOME "\xef\x8a\xb4" // U+f2b4+#define ICON_FA_FOOTBALL "\xef\x91\x8e" // U+f44e+#define ICON_FA_FORWARD "\xef\x81\x8e" // U+f04e+#define ICON_FA_FORWARD_FAST "\xef\x81\x90" // U+f050+#define ICON_FA_FORWARD_STEP "\xef\x81\x91" // U+f051+#define ICON_FA_FRANC_SIGN "\xee\x86\x8f" // U+e18f+#define ICON_FA_FROG "\xef\x94\xae" // U+f52e+#define ICON_FA_FUTBOL "\xef\x87\xa3" // U+f1e3+#define ICON_FA_G "G" // U+0047+#define ICON_FA_GAMEPAD "\xef\x84\x9b" // U+f11b+#define ICON_FA_GAS_PUMP "\xef\x94\xaf" // U+f52f+#define ICON_FA_GAUGE "\xef\x98\xa4" // U+f624+#define ICON_FA_GAUGE_HIGH "\xef\x98\xa5" // U+f625+#define ICON_FA_GAUGE_SIMPLE "\xef\x98\xa9" // U+f629+#define ICON_FA_GAUGE_SIMPLE_HIGH "\xef\x98\xaa" // U+f62a+#define ICON_FA_GAVEL "\xef\x83\xa3" // U+f0e3+#define ICON_FA_GEAR "\xef\x80\x93" // U+f013+#define ICON_FA_GEARS "\xef\x82\x85" // U+f085+#define ICON_FA_GEM "\xef\x8e\xa5" // U+f3a5+#define ICON_FA_GENDERLESS "\xef\x88\xad" // U+f22d+#define ICON_FA_GHOST "\xef\x9b\xa2" // U+f6e2+#define ICON_FA_GIFT "\xef\x81\xab" // U+f06b+#define ICON_FA_GIFTS "\xef\x9e\x9c" // U+f79c+#define ICON_FA_GLASS_WATER "\xee\x93\xb4" // U+e4f4+#define ICON_FA_GLASS_WATER_DROPLET "\xee\x93\xb5" // U+e4f5+#define ICON_FA_GLASSES "\xef\x94\xb0" // U+f530+#define ICON_FA_GLOBE "\xef\x82\xac" // U+f0ac+#define ICON_FA_GOLF_BALL_TEE "\xef\x91\x90" // U+f450+#define ICON_FA_GOPURAM "\xef\x99\xa4" // U+f664+#define ICON_FA_GRADUATION_CAP "\xef\x86\x9d" // U+f19d+#define ICON_FA_GREATER_THAN ">" // U+003e+#define ICON_FA_GREATER_THAN_EQUAL "\xef\x94\xb2" // U+f532+#define ICON_FA_GRIP "\xef\x96\x8d" // U+f58d+#define ICON_FA_GRIP_LINES "\xef\x9e\xa4" // U+f7a4+#define ICON_FA_GRIP_LINES_VERTICAL "\xef\x9e\xa5" // U+f7a5+#define ICON_FA_GRIP_VERTICAL "\xef\x96\x8e" // U+f58e+#define ICON_FA_GROUP_ARROWS_ROTATE "\xee\x93\xb6" // U+e4f6+#define ICON_FA_GUARANI_SIGN "\xee\x86\x9a" // U+e19a+#define ICON_FA_GUITAR "\xef\x9e\xa6" // U+f7a6+#define ICON_FA_GUN "\xee\x86\x9b" // U+e19b+#define ICON_FA_H "H" // U+0048+#define ICON_FA_HAMMER "\xef\x9b\xa3" // U+f6e3+#define ICON_FA_HAMSA "\xef\x99\xa5" // U+f665+#define ICON_FA_HAND "\xef\x89\x96" // U+f256+#define ICON_FA_HAND_BACK_FIST "\xef\x89\x95" // U+f255+#define ICON_FA_HAND_DOTS "\xef\x91\xa1" // U+f461+#define ICON_FA_HAND_FIST "\xef\x9b\x9e" // U+f6de+#define ICON_FA_HAND_HOLDING "\xef\x92\xbd" // U+f4bd+#define ICON_FA_HAND_HOLDING_DOLLAR "\xef\x93\x80" // U+f4c0+#define ICON_FA_HAND_HOLDING_DROPLET "\xef\x93\x81" // U+f4c1+#define ICON_FA_HAND_HOLDING_HAND "\xee\x93\xb7" // U+e4f7+#define ICON_FA_HAND_HOLDING_HEART "\xef\x92\xbe" // U+f4be+#define ICON_FA_HAND_HOLDING_MEDICAL "\xee\x81\x9c" // U+e05c+#define ICON_FA_HAND_LIZARD "\xef\x89\x98" // U+f258+#define ICON_FA_HAND_MIDDLE_FINGER "\xef\xa0\x86" // U+f806+#define ICON_FA_HAND_PEACE "\xef\x89\x9b" // U+f25b+#define ICON_FA_HAND_POINT_DOWN "\xef\x82\xa7" // U+f0a7+#define ICON_FA_HAND_POINT_LEFT "\xef\x82\xa5" // U+f0a5+#define ICON_FA_HAND_POINT_RIGHT "\xef\x82\xa4" // U+f0a4+#define ICON_FA_HAND_POINT_UP "\xef\x82\xa6" // U+f0a6+#define ICON_FA_HAND_POINTER "\xef\x89\x9a" // U+f25a+#define ICON_FA_HAND_SCISSORS "\xef\x89\x97" // U+f257+#define ICON_FA_HAND_SPARKLES "\xee\x81\x9d" // U+e05d+#define ICON_FA_HAND_SPOCK "\xef\x89\x99" // U+f259+#define ICON_FA_HANDCUFFS "\xee\x93\xb8" // U+e4f8+#define ICON_FA_HANDS "\xef\x8a\xa7" // U+f2a7+#define ICON_FA_HANDS_ASL_INTERPRETING "\xef\x8a\xa3" // U+f2a3+#define ICON_FA_HANDS_BOUND "\xee\x93\xb9" // U+e4f9+#define ICON_FA_HANDS_BUBBLES "\xee\x81\x9e" // U+e05e+#define ICON_FA_HANDS_CLAPPING "\xee\x86\xa8" // U+e1a8+#define ICON_FA_HANDS_HOLDING "\xef\x93\x82" // U+f4c2+#define ICON_FA_HANDS_HOLDING_CHILD "\xee\x93\xba" // U+e4fa+#define ICON_FA_HANDS_HOLDING_CIRCLE "\xee\x93\xbb" // U+e4fb+#define ICON_FA_HANDS_PRAYING "\xef\x9a\x84" // U+f684+#define ICON_FA_HANDSHAKE "\xef\x8a\xb5" // U+f2b5+#define ICON_FA_HANDSHAKE_ANGLE "\xef\x93\x84" // U+f4c4+#define ICON_FA_HANDSHAKE_SIMPLE "\xef\x93\x86" // U+f4c6+#define ICON_FA_HANDSHAKE_SIMPLE_SLASH "\xee\x81\x9f" // U+e05f+#define ICON_FA_HANDSHAKE_SLASH "\xee\x81\xa0" // U+e060+#define ICON_FA_HANUKIAH "\xef\x9b\xa6" // U+f6e6+#define ICON_FA_HARD_DRIVE "\xef\x82\xa0" // U+f0a0+#define ICON_FA_HASHTAG "#" // U+0023+#define ICON_FA_HAT_COWBOY "\xef\xa3\x80" // U+f8c0+#define ICON_FA_HAT_COWBOY_SIDE "\xef\xa3\x81" // U+f8c1+#define ICON_FA_HAT_WIZARD "\xef\x9b\xa8" // U+f6e8+#define ICON_FA_HEAD_SIDE_COUGH "\xee\x81\xa1" // U+e061+#define ICON_FA_HEAD_SIDE_COUGH_SLASH "\xee\x81\xa2" // U+e062+#define ICON_FA_HEAD_SIDE_MASK "\xee\x81\xa3" // U+e063+#define ICON_FA_HEAD_SIDE_VIRUS "\xee\x81\xa4" // U+e064+#define ICON_FA_HEADING "\xef\x87\x9c" // U+f1dc+#define ICON_FA_HEADPHONES "\xef\x80\xa5" // U+f025+#define ICON_FA_HEADPHONES_SIMPLE "\xef\x96\x8f" // U+f58f+#define ICON_FA_HEADSET "\xef\x96\x90" // U+f590+#define ICON_FA_HEART "\xef\x80\x84" // U+f004+#define ICON_FA_HEART_CIRCLE_BOLT "\xee\x93\xbc" // U+e4fc+#define ICON_FA_HEART_CIRCLE_CHECK "\xee\x93\xbd" // U+e4fd+#define ICON_FA_HEART_CIRCLE_EXCLAMATION "\xee\x93\xbe" // U+e4fe+#define ICON_FA_HEART_CIRCLE_MINUS "\xee\x93\xbf" // U+e4ff+#define ICON_FA_HEART_CIRCLE_PLUS "\xee\x94\x80" // U+e500+#define ICON_FA_HEART_CIRCLE_XMARK "\xee\x94\x81" // U+e501+#define ICON_FA_HEART_CRACK "\xef\x9e\xa9" // U+f7a9+#define ICON_FA_HEART_PULSE "\xef\x88\x9e" // U+f21e+#define ICON_FA_HELICOPTER "\xef\x94\xb3" // U+f533+#define ICON_FA_HELICOPTER_SYMBOL "\xee\x94\x82" // U+e502+#define ICON_FA_HELMET_SAFETY "\xef\xa0\x87" // U+f807+#define ICON_FA_HELMET_UN "\xee\x94\x83" // U+e503+#define ICON_FA_HIGHLIGHTER "\xef\x96\x91" // U+f591+#define ICON_FA_HILL_AVALANCHE "\xee\x94\x87" // U+e507+#define ICON_FA_HILL_ROCKSLIDE "\xee\x94\x88" // U+e508+#define ICON_FA_HIPPO "\xef\x9b\xad" // U+f6ed+#define ICON_FA_HOCKEY_PUCK "\xef\x91\x93" // U+f453+#define ICON_FA_HOLLY_BERRY "\xef\x9e\xaa" // U+f7aa+#define ICON_FA_HORSE "\xef\x9b\xb0" // U+f6f0+#define ICON_FA_HORSE_HEAD "\xef\x9e\xab" // U+f7ab+#define ICON_FA_HOSPITAL "\xef\x83\xb8" // U+f0f8+#define ICON_FA_HOSPITAL_USER "\xef\xa0\x8d" // U+f80d+#define ICON_FA_HOT_TUB_PERSON "\xef\x96\x93" // U+f593+#define ICON_FA_HOTDOG "\xef\xa0\x8f" // U+f80f+#define ICON_FA_HOTEL "\xef\x96\x94" // U+f594+#define ICON_FA_HOURGLASS "\xef\x89\x94" // U+f254+#define ICON_FA_HOURGLASS_END "\xef\x89\x93" // U+f253+#define ICON_FA_HOURGLASS_HALF "\xef\x89\x92" // U+f252+#define ICON_FA_HOURGLASS_START "\xef\x89\x91" // U+f251+#define ICON_FA_HOUSE "\xef\x80\x95" // U+f015+#define ICON_FA_HOUSE_CHIMNEY "\xee\x8e\xaf" // U+e3af+#define ICON_FA_HOUSE_CHIMNEY_CRACK "\xef\x9b\xb1" // U+f6f1+#define ICON_FA_HOUSE_CHIMNEY_MEDICAL "\xef\x9f\xb2" // U+f7f2+#define ICON_FA_HOUSE_CHIMNEY_USER "\xee\x81\xa5" // U+e065+#define ICON_FA_HOUSE_CHIMNEY_WINDOW "\xee\x80\x8d" // U+e00d+#define ICON_FA_HOUSE_CIRCLE_CHECK "\xee\x94\x89" // U+e509+#define ICON_FA_HOUSE_CIRCLE_EXCLAMATION "\xee\x94\x8a" // U+e50a+#define ICON_FA_HOUSE_CIRCLE_XMARK "\xee\x94\x8b" // U+e50b+#define ICON_FA_HOUSE_CRACK "\xee\x8e\xb1" // U+e3b1+#define ICON_FA_HOUSE_FIRE "\xee\x94\x8c" // U+e50c+#define ICON_FA_HOUSE_FLAG "\xee\x94\x8d" // U+e50d+#define ICON_FA_HOUSE_FLOOD_WATER "\xee\x94\x8e" // U+e50e+#define ICON_FA_HOUSE_FLOOD_WATER_CIRCLE_ARROW_RIGHT "\xee\x94\x8f" // U+e50f+#define ICON_FA_HOUSE_LAPTOP "\xee\x81\xa6" // U+e066+#define ICON_FA_HOUSE_LOCK "\xee\x94\x90" // U+e510+#define ICON_FA_HOUSE_MEDICAL "\xee\x8e\xb2" // U+e3b2+#define ICON_FA_HOUSE_MEDICAL_CIRCLE_CHECK "\xee\x94\x91" // U+e511+#define ICON_FA_HOUSE_MEDICAL_CIRCLE_EXCLAMATION "\xee\x94\x92" // U+e512+#define ICON_FA_HOUSE_MEDICAL_CIRCLE_XMARK "\xee\x94\x93" // U+e513+#define ICON_FA_HOUSE_MEDICAL_FLAG "\xee\x94\x94" // U+e514+#define ICON_FA_HOUSE_SIGNAL "\xee\x80\x92" // U+e012+#define ICON_FA_HOUSE_TSUNAMI "\xee\x94\x95" // U+e515+#define ICON_FA_HOUSE_USER "\xee\x86\xb0" // U+e1b0+#define ICON_FA_HRYVNIA_SIGN "\xef\x9b\xb2" // U+f6f2+#define ICON_FA_HURRICANE "\xef\x9d\x91" // U+f751+#define ICON_FA_I "I" // U+0049+#define ICON_FA_I_CURSOR "\xef\x89\x86" // U+f246+#define ICON_FA_ICE_CREAM "\xef\xa0\x90" // U+f810+#define ICON_FA_ICICLES "\xef\x9e\xad" // U+f7ad+#define ICON_FA_ICONS "\xef\xa1\xad" // U+f86d+#define ICON_FA_ID_BADGE "\xef\x8b\x81" // U+f2c1+#define ICON_FA_ID_CARD "\xef\x8b\x82" // U+f2c2+#define ICON_FA_ID_CARD_CLIP "\xef\x91\xbf" // U+f47f+#define ICON_FA_IGLOO "\xef\x9e\xae" // U+f7ae+#define ICON_FA_IMAGE "\xef\x80\xbe" // U+f03e+#define ICON_FA_IMAGE_PORTRAIT "\xef\x8f\xa0" // U+f3e0+#define ICON_FA_IMAGES "\xef\x8c\x82" // U+f302+#define ICON_FA_INBOX "\xef\x80\x9c" // U+f01c+#define ICON_FA_INDENT "\xef\x80\xbc" // U+f03c+#define ICON_FA_INDIAN_RUPEE_SIGN "\xee\x86\xbc" // U+e1bc+#define ICON_FA_INDUSTRY "\xef\x89\xb5" // U+f275+#define ICON_FA_INFINITY "\xef\x94\xb4" // U+f534+#define ICON_FA_INFO "\xef\x84\xa9" // U+f129+#define ICON_FA_ITALIC "\xef\x80\xb3" // U+f033+#define ICON_FA_J "J" // U+004a+#define ICON_FA_JAR "\xee\x94\x96" // U+e516+#define ICON_FA_JAR_WHEAT "\xee\x94\x97" // U+e517+#define ICON_FA_JEDI "\xef\x99\xa9" // U+f669+#define ICON_FA_JET_FIGHTER "\xef\x83\xbb" // U+f0fb+#define ICON_FA_JET_FIGHTER_UP "\xee\x94\x98" // U+e518+#define ICON_FA_JOINT "\xef\x96\x95" // U+f595+#define ICON_FA_JUG_DETERGENT "\xee\x94\x99" // U+e519+#define ICON_FA_K "K" // U+004b+#define ICON_FA_KAABA "\xef\x99\xab" // U+f66b+#define ICON_FA_KEY "\xef\x82\x84" // U+f084+#define ICON_FA_KEYBOARD "\xef\x84\x9c" // U+f11c+#define ICON_FA_KHANDA "\xef\x99\xad" // U+f66d+#define ICON_FA_KIP_SIGN "\xee\x87\x84" // U+e1c4+#define ICON_FA_KIT_MEDICAL "\xef\x91\xb9" // U+f479+#define ICON_FA_KITCHEN_SET "\xee\x94\x9a" // U+e51a+#define ICON_FA_KIWI_BIRD "\xef\x94\xb5" // U+f535+#define ICON_FA_L "L" // U+004c+#define ICON_FA_LAND_MINE_ON "\xee\x94\x9b" // U+e51b+#define ICON_FA_LANDMARK "\xef\x99\xaf" // U+f66f+#define ICON_FA_LANDMARK_DOME "\xef\x9d\x92" // U+f752+#define ICON_FA_LANDMARK_FLAG "\xee\x94\x9c" // U+e51c+#define ICON_FA_LANGUAGE "\xef\x86\xab" // U+f1ab+#define ICON_FA_LAPTOP "\xef\x84\x89" // U+f109+#define ICON_FA_LAPTOP_CODE "\xef\x97\xbc" // U+f5fc+#define ICON_FA_LAPTOP_FILE "\xee\x94\x9d" // U+e51d+#define ICON_FA_LAPTOP_MEDICAL "\xef\xa0\x92" // U+f812+#define ICON_FA_LARI_SIGN "\xee\x87\x88" // U+e1c8+#define ICON_FA_LAYER_GROUP "\xef\x97\xbd" // U+f5fd+#define ICON_FA_LEAF "\xef\x81\xac" // U+f06c+#define ICON_FA_LEFT_LONG "\xef\x8c\x8a" // U+f30a+#define ICON_FA_LEFT_RIGHT "\xef\x8c\xb7" // U+f337+#define ICON_FA_LEMON "\xef\x82\x94" // U+f094+#define ICON_FA_LESS_THAN "<" // U+003c+#define ICON_FA_LESS_THAN_EQUAL "\xef\x94\xb7" // U+f537+#define ICON_FA_LIFE_RING "\xef\x87\x8d" // U+f1cd+#define ICON_FA_LIGHTBULB "\xef\x83\xab" // U+f0eb+#define ICON_FA_LINES_LEANING "\xee\x94\x9e" // U+e51e+#define ICON_FA_LINK "\xef\x83\x81" // U+f0c1+#define ICON_FA_LINK_SLASH "\xef\x84\xa7" // U+f127+#define ICON_FA_LIRA_SIGN "\xef\x86\x95" // U+f195+#define ICON_FA_LIST "\xef\x80\xba" // U+f03a+#define ICON_FA_LIST_CHECK "\xef\x82\xae" // U+f0ae+#define ICON_FA_LIST_OL "\xef\x83\x8b" // U+f0cb+#define ICON_FA_LIST_UL "\xef\x83\x8a" // U+f0ca+#define ICON_FA_LITECOIN_SIGN "\xee\x87\x93" // U+e1d3+#define ICON_FA_LOCATION_ARROW "\xef\x84\xa4" // U+f124+#define ICON_FA_LOCATION_CROSSHAIRS "\xef\x98\x81" // U+f601+#define ICON_FA_LOCATION_DOT "\xef\x8f\x85" // U+f3c5+#define ICON_FA_LOCATION_PIN "\xef\x81\x81" // U+f041+#define ICON_FA_LOCATION_PIN_LOCK "\xee\x94\x9f" // U+e51f+#define ICON_FA_LOCK "\xef\x80\xa3" // U+f023+#define ICON_FA_LOCK_OPEN "\xef\x8f\x81" // U+f3c1+#define ICON_FA_LOCUST "\xee\x94\xa0" // U+e520+#define ICON_FA_LUNGS "\xef\x98\x84" // U+f604+#define ICON_FA_LUNGS_VIRUS "\xee\x81\xa7" // U+e067+#define ICON_FA_M "M" // U+004d+#define ICON_FA_MAGNET "\xef\x81\xb6" // U+f076+#define ICON_FA_MAGNIFYING_GLASS "\xef\x80\x82" // U+f002+#define ICON_FA_MAGNIFYING_GLASS_ARROW_RIGHT "\xee\x94\xa1" // U+e521+#define ICON_FA_MAGNIFYING_GLASS_CHART "\xee\x94\xa2" // U+e522+#define ICON_FA_MAGNIFYING_GLASS_DOLLAR "\xef\x9a\x88" // U+f688+#define ICON_FA_MAGNIFYING_GLASS_LOCATION "\xef\x9a\x89" // U+f689+#define ICON_FA_MAGNIFYING_GLASS_MINUS "\xef\x80\x90" // U+f010+#define ICON_FA_MAGNIFYING_GLASS_PLUS "\xef\x80\x8e" // U+f00e+#define ICON_FA_MANAT_SIGN "\xee\x87\x95" // U+e1d5+#define ICON_FA_MAP "\xef\x89\xb9" // U+f279+#define ICON_FA_MAP_LOCATION "\xef\x96\x9f" // U+f59f+#define ICON_FA_MAP_LOCATION_DOT "\xef\x96\xa0" // U+f5a0+#define ICON_FA_MAP_PIN "\xef\x89\xb6" // U+f276+#define ICON_FA_MARKER "\xef\x96\xa1" // U+f5a1+#define ICON_FA_MARS "\xef\x88\xa2" // U+f222+#define ICON_FA_MARS_AND_VENUS "\xef\x88\xa4" // U+f224+#define ICON_FA_MARS_AND_VENUS_BURST "\xee\x94\xa3" // U+e523+#define ICON_FA_MARS_DOUBLE "\xef\x88\xa7" // U+f227+#define ICON_FA_MARS_STROKE "\xef\x88\xa9" // U+f229+#define ICON_FA_MARS_STROKE_RIGHT "\xef\x88\xab" // U+f22b+#define ICON_FA_MARS_STROKE_UP "\xef\x88\xaa" // U+f22a+#define ICON_FA_MARTINI_GLASS "\xef\x95\xbb" // U+f57b+#define ICON_FA_MARTINI_GLASS_CITRUS "\xef\x95\xa1" // U+f561+#define ICON_FA_MARTINI_GLASS_EMPTY "\xef\x80\x80" // U+f000+#define ICON_FA_MASK "\xef\x9b\xba" // U+f6fa+#define ICON_FA_MASK_FACE "\xee\x87\x97" // U+e1d7+#define ICON_FA_MASK_VENTILATOR "\xee\x94\xa4" // U+e524+#define ICON_FA_MASKS_THEATER "\xef\x98\xb0" // U+f630+#define ICON_FA_MATTRESS_PILLOW "\xee\x94\xa5" // U+e525+#define ICON_FA_MAXIMIZE "\xef\x8c\x9e" // U+f31e+#define ICON_FA_MEDAL "\xef\x96\xa2" // U+f5a2+#define ICON_FA_MEMORY "\xef\x94\xb8" // U+f538+#define ICON_FA_MENORAH "\xef\x99\xb6" // U+f676+#define ICON_FA_MERCURY "\xef\x88\xa3" // U+f223+#define ICON_FA_MESSAGE "\xef\x89\xba" // U+f27a+#define ICON_FA_METEOR "\xef\x9d\x93" // U+f753+#define ICON_FA_MICROCHIP "\xef\x8b\x9b" // U+f2db+#define ICON_FA_MICROPHONE "\xef\x84\xb0" // U+f130+#define ICON_FA_MICROPHONE_LINES "\xef\x8f\x89" // U+f3c9+#define ICON_FA_MICROPHONE_LINES_SLASH "\xef\x94\xb9" // U+f539+#define ICON_FA_MICROPHONE_SLASH "\xef\x84\xb1" // U+f131+#define ICON_FA_MICROSCOPE "\xef\x98\x90" // U+f610+#define ICON_FA_MILL_SIGN "\xee\x87\xad" // U+e1ed+#define ICON_FA_MINIMIZE "\xef\x9e\x8c" // U+f78c+#define ICON_FA_MINUS "\xef\x81\xa8" // U+f068+#define ICON_FA_MITTEN "\xef\x9e\xb5" // U+f7b5+#define ICON_FA_MOBILE "\xef\x8f\x8e" // U+f3ce+#define ICON_FA_MOBILE_BUTTON "\xef\x84\x8b" // U+f10b+#define ICON_FA_MOBILE_RETRO "\xee\x94\xa7" // U+e527+#define ICON_FA_MOBILE_SCREEN "\xef\x8f\x8f" // U+f3cf+#define ICON_FA_MOBILE_SCREEN_BUTTON "\xef\x8f\x8d" // U+f3cd+#define ICON_FA_MONEY_BILL "\xef\x83\x96" // U+f0d6+#define ICON_FA_MONEY_BILL_1 "\xef\x8f\x91" // U+f3d1+#define ICON_FA_MONEY_BILL_1_WAVE "\xef\x94\xbb" // U+f53b+#define ICON_FA_MONEY_BILL_TRANSFER "\xee\x94\xa8" // U+e528+#define ICON_FA_MONEY_BILL_TREND_UP "\xee\x94\xa9" // U+e529+#define ICON_FA_MONEY_BILL_WAVE "\xef\x94\xba" // U+f53a+#define ICON_FA_MONEY_BILL_WHEAT "\xee\x94\xaa" // U+e52a+#define ICON_FA_MONEY_BILLS "\xee\x87\xb3" // U+e1f3+#define ICON_FA_MONEY_CHECK "\xef\x94\xbc" // U+f53c+#define ICON_FA_MONEY_CHECK_DOLLAR "\xef\x94\xbd" // U+f53d+#define ICON_FA_MONUMENT "\xef\x96\xa6" // U+f5a6+#define ICON_FA_MOON "\xef\x86\x86" // U+f186+#define ICON_FA_MORTAR_PESTLE "\xef\x96\xa7" // U+f5a7+#define ICON_FA_MOSQUE "\xef\x99\xb8" // U+f678+#define ICON_FA_MOSQUITO "\xee\x94\xab" // U+e52b+#define ICON_FA_MOSQUITO_NET "\xee\x94\xac" // U+e52c+#define ICON_FA_MOTORCYCLE "\xef\x88\x9c" // U+f21c+#define ICON_FA_MOUND "\xee\x94\xad" // U+e52d+#define ICON_FA_MOUNTAIN "\xef\x9b\xbc" // U+f6fc+#define ICON_FA_MOUNTAIN_CITY "\xee\x94\xae" // U+e52e+#define ICON_FA_MOUNTAIN_SUN "\xee\x94\xaf" // U+e52f+#define ICON_FA_MUG_HOT "\xef\x9e\xb6" // U+f7b6+#define ICON_FA_MUG_SAUCER "\xef\x83\xb4" // U+f0f4+#define ICON_FA_MUSIC "\xef\x80\x81" // U+f001+#define ICON_FA_N "N" // U+004e+#define ICON_FA_NAIRA_SIGN "\xee\x87\xb6" // U+e1f6+#define ICON_FA_NETWORK_WIRED "\xef\x9b\xbf" // U+f6ff+#define ICON_FA_NEUTER "\xef\x88\xac" // U+f22c+#define ICON_FA_NEWSPAPER "\xef\x87\xaa" // U+f1ea+#define ICON_FA_NOT_EQUAL "\xef\x94\xbe" // U+f53e+#define ICON_FA_NOTDEF "\xee\x87\xbe" // U+e1fe+#define ICON_FA_NOTE_STICKY "\xef\x89\x89" // U+f249+#define ICON_FA_NOTES_MEDICAL "\xef\x92\x81" // U+f481+#define ICON_FA_O "O" // U+004f+#define ICON_FA_OBJECT_GROUP "\xef\x89\x87" // U+f247+#define ICON_FA_OBJECT_UNGROUP "\xef\x89\x88" // U+f248+#define ICON_FA_OIL_CAN "\xef\x98\x93" // U+f613+#define ICON_FA_OIL_WELL "\xee\x94\xb2" // U+e532+#define ICON_FA_OM "\xef\x99\xb9" // U+f679+#define ICON_FA_OTTER "\xef\x9c\x80" // U+f700+#define ICON_FA_OUTDENT "\xef\x80\xbb" // U+f03b+#define ICON_FA_P "P" // U+0050+#define ICON_FA_PAGER "\xef\xa0\x95" // U+f815+#define ICON_FA_PAINT_ROLLER "\xef\x96\xaa" // U+f5aa+#define ICON_FA_PAINTBRUSH "\xef\x87\xbc" // U+f1fc+#define ICON_FA_PALETTE "\xef\x94\xbf" // U+f53f+#define ICON_FA_PALLET "\xef\x92\x82" // U+f482+#define ICON_FA_PANORAMA "\xee\x88\x89" // U+e209+#define ICON_FA_PAPER_PLANE "\xef\x87\x98" // U+f1d8+#define ICON_FA_PAPERCLIP "\xef\x83\x86" // U+f0c6+#define ICON_FA_PARACHUTE_BOX "\xef\x93\x8d" // U+f4cd+#define ICON_FA_PARAGRAPH "\xef\x87\x9d" // U+f1dd+#define ICON_FA_PASSPORT "\xef\x96\xab" // U+f5ab+#define ICON_FA_PASTE "\xef\x83\xaa" // U+f0ea+#define ICON_FA_PAUSE "\xef\x81\x8c" // U+f04c+#define ICON_FA_PAW "\xef\x86\xb0" // U+f1b0+#define ICON_FA_PEACE "\xef\x99\xbc" // U+f67c+#define ICON_FA_PEN "\xef\x8c\x84" // U+f304+#define ICON_FA_PEN_CLIP "\xef\x8c\x85" // U+f305+#define ICON_FA_PEN_FANCY "\xef\x96\xac" // U+f5ac+#define ICON_FA_PEN_NIB "\xef\x96\xad" // U+f5ad+#define ICON_FA_PEN_RULER "\xef\x96\xae" // U+f5ae+#define ICON_FA_PEN_TO_SQUARE "\xef\x81\x84" // U+f044+#define ICON_FA_PENCIL "\xef\x8c\x83" // U+f303+#define ICON_FA_PEOPLE_ARROWS "\xee\x81\xa8" // U+e068+#define ICON_FA_PEOPLE_CARRY_BOX "\xef\x93\x8e" // U+f4ce+#define ICON_FA_PEOPLE_GROUP "\xee\x94\xb3" // U+e533+#define ICON_FA_PEOPLE_LINE "\xee\x94\xb4" // U+e534+#define ICON_FA_PEOPLE_PULLING "\xee\x94\xb5" // U+e535+#define ICON_FA_PEOPLE_ROBBERY "\xee\x94\xb6" // U+e536+#define ICON_FA_PEOPLE_ROOF "\xee\x94\xb7" // U+e537+#define ICON_FA_PEPPER_HOT "\xef\xa0\x96" // U+f816+#define ICON_FA_PERCENT "%" // U+0025+#define ICON_FA_PERSON "\xef\x86\x83" // U+f183+#define ICON_FA_PERSON_ARROW_DOWN_TO_LINE "\xee\x94\xb8" // U+e538+#define ICON_FA_PERSON_ARROW_UP_FROM_LINE "\xee\x94\xb9" // U+e539+#define ICON_FA_PERSON_BIKING "\xef\xa1\x8a" // U+f84a+#define ICON_FA_PERSON_BOOTH "\xef\x9d\x96" // U+f756+#define ICON_FA_PERSON_BREASTFEEDING "\xee\x94\xba" // U+e53a+#define ICON_FA_PERSON_BURST "\xee\x94\xbb" // U+e53b+#define ICON_FA_PERSON_CANE "\xee\x94\xbc" // U+e53c+#define ICON_FA_PERSON_CHALKBOARD "\xee\x94\xbd" // U+e53d+#define ICON_FA_PERSON_CIRCLE_CHECK "\xee\x94\xbe" // U+e53e+#define ICON_FA_PERSON_CIRCLE_EXCLAMATION "\xee\x94\xbf" // U+e53f+#define ICON_FA_PERSON_CIRCLE_MINUS "\xee\x95\x80" // U+e540+#define ICON_FA_PERSON_CIRCLE_PLUS "\xee\x95\x81" // U+e541+#define ICON_FA_PERSON_CIRCLE_QUESTION "\xee\x95\x82" // U+e542+#define ICON_FA_PERSON_CIRCLE_XMARK "\xee\x95\x83" // U+e543+#define ICON_FA_PERSON_DIGGING "\xef\xa1\x9e" // U+f85e+#define ICON_FA_PERSON_DOTS_FROM_LINE "\xef\x91\xb0" // U+f470+#define ICON_FA_PERSON_DRESS "\xef\x86\x82" // U+f182+#define ICON_FA_PERSON_DRESS_BURST "\xee\x95\x84" // U+e544+#define ICON_FA_PERSON_DROWNING "\xee\x95\x85" // U+e545+#define ICON_FA_PERSON_FALLING "\xee\x95\x86" // U+e546+#define ICON_FA_PERSON_FALLING_BURST "\xee\x95\x87" // U+e547+#define ICON_FA_PERSON_HALF_DRESS "\xee\x95\x88" // U+e548+#define ICON_FA_PERSON_HARASSING "\xee\x95\x89" // U+e549+#define ICON_FA_PERSON_HIKING "\xef\x9b\xac" // U+f6ec+#define ICON_FA_PERSON_MILITARY_POINTING "\xee\x95\x8a" // U+e54a+#define ICON_FA_PERSON_MILITARY_RIFLE "\xee\x95\x8b" // U+e54b+#define ICON_FA_PERSON_MILITARY_TO_PERSON "\xee\x95\x8c" // U+e54c+#define ICON_FA_PERSON_PRAYING "\xef\x9a\x83" // U+f683+#define ICON_FA_PERSON_PREGNANT "\xee\x8c\x9e" // U+e31e+#define ICON_FA_PERSON_RAYS "\xee\x95\x8d" // U+e54d+#define ICON_FA_PERSON_RIFLE "\xee\x95\x8e" // U+e54e+#define ICON_FA_PERSON_RUNNING "\xef\x9c\x8c" // U+f70c+#define ICON_FA_PERSON_SHELTER "\xee\x95\x8f" // U+e54f+#define ICON_FA_PERSON_SKATING "\xef\x9f\x85" // U+f7c5+#define ICON_FA_PERSON_SKIING "\xef\x9f\x89" // U+f7c9+#define ICON_FA_PERSON_SKIING_NORDIC "\xef\x9f\x8a" // U+f7ca+#define ICON_FA_PERSON_SNOWBOARDING "\xef\x9f\x8e" // U+f7ce+#define ICON_FA_PERSON_SWIMMING "\xef\x97\x84" // U+f5c4+#define ICON_FA_PERSON_THROUGH_WINDOW "\xee\x96\xa9" // U+e5a9+#define ICON_FA_PERSON_WALKING "\xef\x95\x94" // U+f554+#define ICON_FA_PERSON_WALKING_ARROW_LOOP_LEFT "\xee\x95\x91" // U+e551+#define ICON_FA_PERSON_WALKING_ARROW_RIGHT "\xee\x95\x92" // U+e552+#define ICON_FA_PERSON_WALKING_DASHED_LINE_ARROW_RIGHT "\xee\x95\x93" // U+e553+#define ICON_FA_PERSON_WALKING_LUGGAGE "\xee\x95\x94" // U+e554+#define ICON_FA_PERSON_WALKING_WITH_CANE "\xef\x8a\x9d" // U+f29d+#define ICON_FA_PESETA_SIGN "\xee\x88\xa1" // U+e221+#define ICON_FA_PESO_SIGN "\xee\x88\xa2" // U+e222+#define ICON_FA_PHONE "\xef\x82\x95" // U+f095+#define ICON_FA_PHONE_FLIP "\xef\xa1\xb9" // U+f879+#define ICON_FA_PHONE_SLASH "\xef\x8f\x9d" // U+f3dd+#define ICON_FA_PHONE_VOLUME "\xef\x8a\xa0" // U+f2a0+#define ICON_FA_PHOTO_FILM "\xef\xa1\xbc" // U+f87c+#define ICON_FA_PIGGY_BANK "\xef\x93\x93" // U+f4d3+#define ICON_FA_PILLS "\xef\x92\x84" // U+f484+#define ICON_FA_PIZZA_SLICE "\xef\xa0\x98" // U+f818+#define ICON_FA_PLACE_OF_WORSHIP "\xef\x99\xbf" // U+f67f+#define ICON_FA_PLANE "\xef\x81\xb2" // U+f072+#define ICON_FA_PLANE_ARRIVAL "\xef\x96\xaf" // U+f5af+#define ICON_FA_PLANE_CIRCLE_CHECK "\xee\x95\x95" // U+e555+#define ICON_FA_PLANE_CIRCLE_EXCLAMATION "\xee\x95\x96" // U+e556+#define ICON_FA_PLANE_CIRCLE_XMARK "\xee\x95\x97" // U+e557+#define ICON_FA_PLANE_DEPARTURE "\xef\x96\xb0" // U+f5b0+#define ICON_FA_PLANE_LOCK "\xee\x95\x98" // U+e558+#define ICON_FA_PLANE_SLASH "\xee\x81\xa9" // U+e069+#define ICON_FA_PLANE_UP "\xee\x88\xad" // U+e22d+#define ICON_FA_PLANT_WILT "\xee\x96\xaa" // U+e5aa+#define ICON_FA_PLATE_WHEAT "\xee\x95\x9a" // U+e55a+#define ICON_FA_PLAY "\xef\x81\x8b" // U+f04b+#define ICON_FA_PLUG "\xef\x87\xa6" // U+f1e6+#define ICON_FA_PLUG_CIRCLE_BOLT "\xee\x95\x9b" // U+e55b+#define ICON_FA_PLUG_CIRCLE_CHECK "\xee\x95\x9c" // U+e55c+#define ICON_FA_PLUG_CIRCLE_EXCLAMATION "\xee\x95\x9d" // U+e55d+#define ICON_FA_PLUG_CIRCLE_MINUS "\xee\x95\x9e" // U+e55e+#define ICON_FA_PLUG_CIRCLE_PLUS "\xee\x95\x9f" // U+e55f+#define ICON_FA_PLUG_CIRCLE_XMARK "\xee\x95\xa0" // U+e560+#define ICON_FA_PLUS "+" // U+002b+#define ICON_FA_PLUS_MINUS "\xee\x90\xbc" // U+e43c+#define ICON_FA_PODCAST "\xef\x8b\x8e" // U+f2ce+#define ICON_FA_POO "\xef\x8b\xbe" // U+f2fe+#define ICON_FA_POO_STORM "\xef\x9d\x9a" // U+f75a+#define ICON_FA_POOP "\xef\x98\x99" // U+f619+#define ICON_FA_POWER_OFF "\xef\x80\x91" // U+f011+#define ICON_FA_PRESCRIPTION "\xef\x96\xb1" // U+f5b1+#define ICON_FA_PRESCRIPTION_BOTTLE "\xef\x92\x85" // U+f485+#define ICON_FA_PRESCRIPTION_BOTTLE_MEDICAL "\xef\x92\x86" // U+f486+#define ICON_FA_PRINT "\xef\x80\xaf" // U+f02f+#define ICON_FA_PUMP_MEDICAL "\xee\x81\xaa" // U+e06a+#define ICON_FA_PUMP_SOAP "\xee\x81\xab" // U+e06b+#define ICON_FA_PUZZLE_PIECE "\xef\x84\xae" // U+f12e+#define ICON_FA_Q "Q" // U+0051+#define ICON_FA_QRCODE "\xef\x80\xa9" // U+f029+#define ICON_FA_QUESTION "?" // U+003f+#define ICON_FA_QUOTE_LEFT "\xef\x84\x8d" // U+f10d+#define ICON_FA_QUOTE_RIGHT "\xef\x84\x8e" // U+f10e+#define ICON_FA_R "R" // U+0052+#define ICON_FA_RADIATION "\xef\x9e\xb9" // U+f7b9+#define ICON_FA_RADIO "\xef\xa3\x97" // U+f8d7+#define ICON_FA_RAINBOW "\xef\x9d\x9b" // U+f75b+#define ICON_FA_RANKING_STAR "\xee\x95\xa1" // U+e561+#define ICON_FA_RECEIPT "\xef\x95\x83" // U+f543+#define ICON_FA_RECORD_VINYL "\xef\xa3\x99" // U+f8d9+#define ICON_FA_RECTANGLE_AD "\xef\x99\x81" // U+f641+#define ICON_FA_RECTANGLE_LIST "\xef\x80\xa2" // U+f022+#define ICON_FA_RECTANGLE_XMARK "\xef\x90\x90" // U+f410+#define ICON_FA_RECYCLE "\xef\x86\xb8" // U+f1b8+#define ICON_FA_REGISTERED "\xef\x89\x9d" // U+f25d+#define ICON_FA_REPEAT "\xef\x8d\xa3" // U+f363+#define ICON_FA_REPLY "\xef\x8f\xa5" // U+f3e5+#define ICON_FA_REPLY_ALL "\xef\x84\xa2" // U+f122+#define ICON_FA_REPUBLICAN "\xef\x9d\x9e" // U+f75e+#define ICON_FA_RESTROOM "\xef\x9e\xbd" // U+f7bd+#define ICON_FA_RETWEET "\xef\x81\xb9" // U+f079+#define ICON_FA_RIBBON "\xef\x93\x96" // U+f4d6+#define ICON_FA_RIGHT_FROM_BRACKET "\xef\x8b\xb5" // U+f2f5+#define ICON_FA_RIGHT_LEFT "\xef\x8d\xa2" // U+f362+#define ICON_FA_RIGHT_LONG "\xef\x8c\x8b" // U+f30b+#define ICON_FA_RIGHT_TO_BRACKET "\xef\x8b\xb6" // U+f2f6+#define ICON_FA_RING "\xef\x9c\x8b" // U+f70b+#define ICON_FA_ROAD "\xef\x80\x98" // U+f018+#define ICON_FA_ROAD_BARRIER "\xee\x95\xa2" // U+e562+#define ICON_FA_ROAD_BRIDGE "\xee\x95\xa3" // U+e563+#define ICON_FA_ROAD_CIRCLE_CHECK "\xee\x95\xa4" // U+e564+#define ICON_FA_ROAD_CIRCLE_EXCLAMATION "\xee\x95\xa5" // U+e565+#define ICON_FA_ROAD_CIRCLE_XMARK "\xee\x95\xa6" // U+e566+#define ICON_FA_ROAD_LOCK "\xee\x95\xa7" // U+e567+#define ICON_FA_ROAD_SPIKES "\xee\x95\xa8" // U+e568+#define ICON_FA_ROBOT "\xef\x95\x84" // U+f544+#define ICON_FA_ROCKET "\xef\x84\xb5" // U+f135+#define ICON_FA_ROTATE "\xef\x8b\xb1" // U+f2f1+#define ICON_FA_ROTATE_LEFT "\xef\x8b\xaa" // U+f2ea+#define ICON_FA_ROTATE_RIGHT "\xef\x8b\xb9" // U+f2f9+#define ICON_FA_ROUTE "\xef\x93\x97" // U+f4d7+#define ICON_FA_RSS "\xef\x82\x9e" // U+f09e+#define ICON_FA_RUBLE_SIGN "\xef\x85\x98" // U+f158+#define ICON_FA_RUG "\xee\x95\xa9" // U+e569+#define ICON_FA_RULER "\xef\x95\x85" // U+f545+#define ICON_FA_RULER_COMBINED "\xef\x95\x86" // U+f546+#define ICON_FA_RULER_HORIZONTAL "\xef\x95\x87" // U+f547+#define ICON_FA_RULER_VERTICAL "\xef\x95\x88" // U+f548+#define ICON_FA_RUPEE_SIGN "\xef\x85\x96" // U+f156+#define ICON_FA_RUPIAH_SIGN "\xee\x88\xbd" // U+e23d+#define ICON_FA_S "S" // U+0053+#define ICON_FA_SACK_DOLLAR "\xef\xa0\x9d" // U+f81d+#define ICON_FA_SACK_XMARK "\xee\x95\xaa" // U+e56a+#define ICON_FA_SAILBOAT "\xee\x91\x85" // U+e445+#define ICON_FA_SATELLITE "\xef\x9e\xbf" // U+f7bf+#define ICON_FA_SATELLITE_DISH "\xef\x9f\x80" // U+f7c0+#define ICON_FA_SCALE_BALANCED "\xef\x89\x8e" // U+f24e+#define ICON_FA_SCALE_UNBALANCED "\xef\x94\x95" // U+f515+#define ICON_FA_SCALE_UNBALANCED_FLIP "\xef\x94\x96" // U+f516+#define ICON_FA_SCHOOL "\xef\x95\x89" // U+f549+#define ICON_FA_SCHOOL_CIRCLE_CHECK "\xee\x95\xab" // U+e56b+#define ICON_FA_SCHOOL_CIRCLE_EXCLAMATION "\xee\x95\xac" // U+e56c+#define ICON_FA_SCHOOL_CIRCLE_XMARK "\xee\x95\xad" // U+e56d+#define ICON_FA_SCHOOL_FLAG "\xee\x95\xae" // U+e56e+#define ICON_FA_SCHOOL_LOCK "\xee\x95\xaf" // U+e56f+#define ICON_FA_SCISSORS "\xef\x83\x84" // U+f0c4+#define ICON_FA_SCREWDRIVER "\xef\x95\x8a" // U+f54a+#define ICON_FA_SCREWDRIVER_WRENCH "\xef\x9f\x99" // U+f7d9+#define ICON_FA_SCROLL "\xef\x9c\x8e" // U+f70e+#define ICON_FA_SCROLL_TORAH "\xef\x9a\xa0" // U+f6a0+#define ICON_FA_SD_CARD "\xef\x9f\x82" // U+f7c2+#define ICON_FA_SECTION "\xee\x91\x87" // U+e447+#define ICON_FA_SEEDLING "\xef\x93\x98" // U+f4d8+#define ICON_FA_SERVER "\xef\x88\xb3" // U+f233+#define ICON_FA_SHAPES "\xef\x98\x9f" // U+f61f+#define ICON_FA_SHARE "\xef\x81\xa4" // U+f064+#define ICON_FA_SHARE_FROM_SQUARE "\xef\x85\x8d" // U+f14d+#define ICON_FA_SHARE_NODES "\xef\x87\xa0" // U+f1e0+#define ICON_FA_SHEET_PLASTIC "\xee\x95\xb1" // U+e571+#define ICON_FA_SHEKEL_SIGN "\xef\x88\x8b" // U+f20b+#define ICON_FA_SHIELD "\xef\x84\xb2" // U+f132+#define ICON_FA_SHIELD_CAT "\xee\x95\xb2" // U+e572+#define ICON_FA_SHIELD_DOG "\xee\x95\xb3" // U+e573+#define ICON_FA_SHIELD_HALVED "\xef\x8f\xad" // U+f3ed+#define ICON_FA_SHIELD_HEART "\xee\x95\xb4" // U+e574+#define ICON_FA_SHIELD_VIRUS "\xee\x81\xac" // U+e06c+#define ICON_FA_SHIP "\xef\x88\x9a" // U+f21a+#define ICON_FA_SHIRT "\xef\x95\x93" // U+f553+#define ICON_FA_SHOE_PRINTS "\xef\x95\x8b" // U+f54b+#define ICON_FA_SHOP "\xef\x95\x8f" // U+f54f+#define ICON_FA_SHOP_LOCK "\xee\x92\xa5" // U+e4a5+#define ICON_FA_SHOP_SLASH "\xee\x81\xb0" // U+e070+#define ICON_FA_SHOWER "\xef\x8b\x8c" // U+f2cc+#define ICON_FA_SHRIMP "\xee\x91\x88" // U+e448+#define ICON_FA_SHUFFLE "\xef\x81\xb4" // U+f074+#define ICON_FA_SHUTTLE_SPACE "\xef\x86\x97" // U+f197+#define ICON_FA_SIGN_HANGING "\xef\x93\x99" // U+f4d9+#define ICON_FA_SIGNAL "\xef\x80\x92" // U+f012+#define ICON_FA_SIGNATURE "\xef\x96\xb7" // U+f5b7+#define ICON_FA_SIGNS_POST "\xef\x89\xb7" // U+f277+#define ICON_FA_SIM_CARD "\xef\x9f\x84" // U+f7c4+#define ICON_FA_SINK "\xee\x81\xad" // U+e06d+#define ICON_FA_SITEMAP "\xef\x83\xa8" // U+f0e8+#define ICON_FA_SKULL "\xef\x95\x8c" // U+f54c+#define ICON_FA_SKULL_CROSSBONES "\xef\x9c\x94" // U+f714+#define ICON_FA_SLASH "\xef\x9c\x95" // U+f715+#define ICON_FA_SLEIGH "\xef\x9f\x8c" // U+f7cc+#define ICON_FA_SLIDERS "\xef\x87\x9e" // U+f1de+#define ICON_FA_SMOG "\xef\x9d\x9f" // U+f75f+#define ICON_FA_SMOKING "\xef\x92\x8d" // U+f48d+#define ICON_FA_SNOWFLAKE "\xef\x8b\x9c" // U+f2dc+#define ICON_FA_SNOWMAN "\xef\x9f\x90" // U+f7d0+#define ICON_FA_SNOWPLOW "\xef\x9f\x92" // U+f7d2+#define ICON_FA_SOAP "\xee\x81\xae" // U+e06e+#define ICON_FA_SOCKS "\xef\x9a\x96" // U+f696+#define ICON_FA_SOLAR_PANEL "\xef\x96\xba" // U+f5ba+#define ICON_FA_SORT "\xef\x83\x9c" // U+f0dc+#define ICON_FA_SORT_DOWN "\xef\x83\x9d" // U+f0dd+#define ICON_FA_SORT_UP "\xef\x83\x9e" // U+f0de+#define ICON_FA_SPA "\xef\x96\xbb" // U+f5bb+#define ICON_FA_SPAGHETTI_MONSTER_FLYING "\xef\x99\xbb" // U+f67b+#define ICON_FA_SPELL_CHECK "\xef\xa2\x91" // U+f891+#define ICON_FA_SPIDER "\xef\x9c\x97" // U+f717+#define ICON_FA_SPINNER "\xef\x84\x90" // U+f110+#define ICON_FA_SPLOTCH "\xef\x96\xbc" // U+f5bc+#define ICON_FA_SPOON "\xef\x8b\xa5" // U+f2e5+#define ICON_FA_SPRAY_CAN "\xef\x96\xbd" // U+f5bd+#define ICON_FA_SPRAY_CAN_SPARKLES "\xef\x97\x90" // U+f5d0+#define ICON_FA_SQUARE "\xef\x83\x88" // U+f0c8+#define ICON_FA_SQUARE_ARROW_UP_RIGHT "\xef\x85\x8c" // U+f14c+#define ICON_FA_SQUARE_CARET_DOWN "\xef\x85\x90" // U+f150+#define ICON_FA_SQUARE_CARET_LEFT "\xef\x86\x91" // U+f191+#define ICON_FA_SQUARE_CARET_RIGHT "\xef\x85\x92" // U+f152+#define ICON_FA_SQUARE_CARET_UP "\xef\x85\x91" // U+f151+#define ICON_FA_SQUARE_CHECK "\xef\x85\x8a" // U+f14a+#define ICON_FA_SQUARE_ENVELOPE "\xef\x86\x99" // U+f199+#define ICON_FA_SQUARE_FULL "\xef\x91\x9c" // U+f45c+#define ICON_FA_SQUARE_H "\xef\x83\xbd" // U+f0fd+#define ICON_FA_SQUARE_MINUS "\xef\x85\x86" // U+f146+#define ICON_FA_SQUARE_NFI "\xee\x95\xb6" // U+e576+#define ICON_FA_SQUARE_PARKING "\xef\x95\x80" // U+f540+#define ICON_FA_SQUARE_PEN "\xef\x85\x8b" // U+f14b+#define ICON_FA_SQUARE_PERSON_CONFINED "\xee\x95\xb7" // U+e577+#define ICON_FA_SQUARE_PHONE "\xef\x82\x98" // U+f098+#define ICON_FA_SQUARE_PHONE_FLIP "\xef\xa1\xbb" // U+f87b+#define ICON_FA_SQUARE_PLUS "\xef\x83\xbe" // U+f0fe+#define ICON_FA_SQUARE_POLL_HORIZONTAL "\xef\x9a\x82" // U+f682+#define ICON_FA_SQUARE_POLL_VERTICAL "\xef\x9a\x81" // U+f681+#define ICON_FA_SQUARE_ROOT_VARIABLE "\xef\x9a\x98" // U+f698+#define ICON_FA_SQUARE_RSS "\xef\x85\x83" // U+f143+#define ICON_FA_SQUARE_SHARE_NODES "\xef\x87\xa1" // U+f1e1+#define ICON_FA_SQUARE_UP_RIGHT "\xef\x8d\xa0" // U+f360+#define ICON_FA_SQUARE_VIRUS "\xee\x95\xb8" // U+e578+#define ICON_FA_SQUARE_XMARK "\xef\x8b\x93" // U+f2d3+#define ICON_FA_STAFF_SNAKE "\xee\x95\xb9" // U+e579+#define ICON_FA_STAIRS "\xee\x8a\x89" // U+e289+#define ICON_FA_STAMP "\xef\x96\xbf" // U+f5bf+#define ICON_FA_STAPLER "\xee\x96\xaf" // U+e5af+#define ICON_FA_STAR "\xef\x80\x85" // U+f005+#define ICON_FA_STAR_AND_CRESCENT "\xef\x9a\x99" // U+f699+#define ICON_FA_STAR_HALF "\xef\x82\x89" // U+f089+#define ICON_FA_STAR_HALF_STROKE "\xef\x97\x80" // U+f5c0+#define ICON_FA_STAR_OF_DAVID "\xef\x9a\x9a" // U+f69a+#define ICON_FA_STAR_OF_LIFE "\xef\x98\xa1" // U+f621+#define ICON_FA_STERLING_SIGN "\xef\x85\x94" // U+f154+#define ICON_FA_STETHOSCOPE "\xef\x83\xb1" // U+f0f1+#define ICON_FA_STOP "\xef\x81\x8d" // U+f04d+#define ICON_FA_STOPWATCH "\xef\x8b\xb2" // U+f2f2+#define ICON_FA_STOPWATCH_20 "\xee\x81\xaf" // U+e06f+#define ICON_FA_STORE "\xef\x95\x8e" // U+f54e+#define ICON_FA_STORE_SLASH "\xee\x81\xb1" // U+e071+#define ICON_FA_STREET_VIEW "\xef\x88\x9d" // U+f21d+#define ICON_FA_STRIKETHROUGH "\xef\x83\x8c" // U+f0cc+#define ICON_FA_STROOPWAFEL "\xef\x95\x91" // U+f551+#define ICON_FA_SUBSCRIPT "\xef\x84\xac" // U+f12c+#define ICON_FA_SUITCASE "\xef\x83\xb2" // U+f0f2+#define ICON_FA_SUITCASE_MEDICAL "\xef\x83\xba" // U+f0fa+#define ICON_FA_SUITCASE_ROLLING "\xef\x97\x81" // U+f5c1+#define ICON_FA_SUN "\xef\x86\x85" // U+f185+#define ICON_FA_SUN_PLANT_WILT "\xee\x95\xba" // U+e57a+#define ICON_FA_SUPERSCRIPT "\xef\x84\xab" // U+f12b+#define ICON_FA_SWATCHBOOK "\xef\x97\x83" // U+f5c3+#define ICON_FA_SYNAGOGUE "\xef\x9a\x9b" // U+f69b+#define ICON_FA_SYRINGE "\xef\x92\x8e" // U+f48e+#define ICON_FA_T "T" // U+0054+#define ICON_FA_TABLE "\xef\x83\x8e" // U+f0ce+#define ICON_FA_TABLE_CELLS "\xef\x80\x8a" // U+f00a+#define ICON_FA_TABLE_CELLS_LARGE "\xef\x80\x89" // U+f009+#define ICON_FA_TABLE_COLUMNS "\xef\x83\x9b" // U+f0db+#define ICON_FA_TABLE_LIST "\xef\x80\x8b" // U+f00b+#define ICON_FA_TABLE_TENNIS_PADDLE_BALL "\xef\x91\x9d" // U+f45d+#define ICON_FA_TABLET "\xef\x8f\xbb" // U+f3fb+#define ICON_FA_TABLET_BUTTON "\xef\x84\x8a" // U+f10a+#define ICON_FA_TABLET_SCREEN_BUTTON "\xef\x8f\xba" // U+f3fa+#define ICON_FA_TABLETS "\xef\x92\x90" // U+f490+#define ICON_FA_TACHOGRAPH_DIGITAL "\xef\x95\xa6" // U+f566+#define ICON_FA_TAG "\xef\x80\xab" // U+f02b+#define ICON_FA_TAGS "\xef\x80\xac" // U+f02c+#define ICON_FA_TAPE "\xef\x93\x9b" // U+f4db+#define ICON_FA_TARP "\xee\x95\xbb" // U+e57b+#define ICON_FA_TARP_DROPLET "\xee\x95\xbc" // U+e57c+#define ICON_FA_TAXI "\xef\x86\xba" // U+f1ba+#define ICON_FA_TEETH "\xef\x98\xae" // U+f62e+#define ICON_FA_TEETH_OPEN "\xef\x98\xaf" // U+f62f+#define ICON_FA_TEMPERATURE_ARROW_DOWN "\xee\x80\xbf" // U+e03f+#define ICON_FA_TEMPERATURE_ARROW_UP "\xee\x81\x80" // U+e040+#define ICON_FA_TEMPERATURE_EMPTY "\xef\x8b\x8b" // U+f2cb+#define ICON_FA_TEMPERATURE_FULL "\xef\x8b\x87" // U+f2c7+#define ICON_FA_TEMPERATURE_HALF "\xef\x8b\x89" // U+f2c9+#define ICON_FA_TEMPERATURE_HIGH "\xef\x9d\xa9" // U+f769+#define ICON_FA_TEMPERATURE_LOW "\xef\x9d\xab" // U+f76b+#define ICON_FA_TEMPERATURE_QUARTER "\xef\x8b\x8a" // U+f2ca+#define ICON_FA_TEMPERATURE_THREE_QUARTERS "\xef\x8b\x88" // U+f2c8+#define ICON_FA_TENGE_SIGN "\xef\x9f\x97" // U+f7d7+#define ICON_FA_TENT "\xee\x95\xbd" // U+e57d+#define ICON_FA_TENT_ARROW_DOWN_TO_LINE "\xee\x95\xbe" // U+e57e+#define ICON_FA_TENT_ARROW_LEFT_RIGHT "\xee\x95\xbf" // U+e57f+#define ICON_FA_TENT_ARROW_TURN_LEFT "\xee\x96\x80" // U+e580+#define ICON_FA_TENT_ARROWS_DOWN "\xee\x96\x81" // U+e581+#define ICON_FA_TENTS "\xee\x96\x82" // U+e582+#define ICON_FA_TERMINAL "\xef\x84\xa0" // U+f120+#define ICON_FA_TEXT_HEIGHT "\xef\x80\xb4" // U+f034+#define ICON_FA_TEXT_SLASH "\xef\xa1\xbd" // U+f87d+#define ICON_FA_TEXT_WIDTH "\xef\x80\xb5" // U+f035+#define ICON_FA_THERMOMETER "\xef\x92\x91" // U+f491+#define ICON_FA_THUMBS_DOWN "\xef\x85\xa5" // U+f165+#define ICON_FA_THUMBS_UP "\xef\x85\xa4" // U+f164+#define ICON_FA_THUMBTACK "\xef\x82\x8d" // U+f08d+#define ICON_FA_TICKET "\xef\x85\x85" // U+f145+#define ICON_FA_TICKET_SIMPLE "\xef\x8f\xbf" // U+f3ff+#define ICON_FA_TIMELINE "\xee\x8a\x9c" // U+e29c+#define ICON_FA_TOGGLE_OFF "\xef\x88\x84" // U+f204+#define ICON_FA_TOGGLE_ON "\xef\x88\x85" // U+f205+#define ICON_FA_TOILET "\xef\x9f\x98" // U+f7d8+#define ICON_FA_TOILET_PAPER "\xef\x9c\x9e" // U+f71e+#define ICON_FA_TOILET_PAPER_SLASH "\xee\x81\xb2" // U+e072+#define ICON_FA_TOILET_PORTABLE "\xee\x96\x83" // U+e583+#define ICON_FA_TOILETS_PORTABLE "\xee\x96\x84" // U+e584+#define ICON_FA_TOOLBOX "\xef\x95\x92" // U+f552+#define ICON_FA_TOOTH "\xef\x97\x89" // U+f5c9+#define ICON_FA_TORII_GATE "\xef\x9a\xa1" // U+f6a1+#define ICON_FA_TORNADO "\xef\x9d\xaf" // U+f76f+#define ICON_FA_TOWER_BROADCAST "\xef\x94\x99" // U+f519+#define ICON_FA_TOWER_CELL "\xee\x96\x85" // U+e585+#define ICON_FA_TOWER_OBSERVATION "\xee\x96\x86" // U+e586+#define ICON_FA_TRACTOR "\xef\x9c\xa2" // U+f722+#define ICON_FA_TRADEMARK "\xef\x89\x9c" // U+f25c+#define ICON_FA_TRAFFIC_LIGHT "\xef\x98\xb7" // U+f637+#define ICON_FA_TRAILER "\xee\x81\x81" // U+e041+#define ICON_FA_TRAIN "\xef\x88\xb8" // U+f238+#define ICON_FA_TRAIN_SUBWAY "\xef\x88\xb9" // U+f239+#define ICON_FA_TRAIN_TRAM "\xee\x96\xb4" // U+e5b4+#define ICON_FA_TRANSGENDER "\xef\x88\xa5" // U+f225+#define ICON_FA_TRASH "\xef\x87\xb8" // U+f1f8+#define ICON_FA_TRASH_ARROW_UP "\xef\xa0\xa9" // U+f829+#define ICON_FA_TRASH_CAN "\xef\x8b\xad" // U+f2ed+#define ICON_FA_TRASH_CAN_ARROW_UP "\xef\xa0\xaa" // U+f82a+#define ICON_FA_TREE "\xef\x86\xbb" // U+f1bb+#define ICON_FA_TREE_CITY "\xee\x96\x87" // U+e587+#define ICON_FA_TRIANGLE_EXCLAMATION "\xef\x81\xb1" // U+f071+#define ICON_FA_TROPHY "\xef\x82\x91" // U+f091+#define ICON_FA_TROWEL "\xee\x96\x89" // U+e589+#define ICON_FA_TROWEL_BRICKS "\xee\x96\x8a" // U+e58a+#define ICON_FA_TRUCK "\xef\x83\x91" // U+f0d1+#define ICON_FA_TRUCK_ARROW_RIGHT "\xee\x96\x8b" // U+e58b+#define ICON_FA_TRUCK_DROPLET "\xee\x96\x8c" // U+e58c+#define ICON_FA_TRUCK_FAST "\xef\x92\x8b" // U+f48b+#define ICON_FA_TRUCK_FIELD "\xee\x96\x8d" // U+e58d+#define ICON_FA_TRUCK_FIELD_UN "\xee\x96\x8e" // U+e58e+#define ICON_FA_TRUCK_FRONT "\xee\x8a\xb7" // U+e2b7+#define ICON_FA_TRUCK_MEDICAL "\xef\x83\xb9" // U+f0f9+#define ICON_FA_TRUCK_MONSTER "\xef\x98\xbb" // U+f63b+#define ICON_FA_TRUCK_MOVING "\xef\x93\x9f" // U+f4df+#define ICON_FA_TRUCK_PICKUP "\xef\x98\xbc" // U+f63c+#define ICON_FA_TRUCK_PLANE "\xee\x96\x8f" // U+e58f+#define ICON_FA_TRUCK_RAMP_BOX "\xef\x93\x9e" // U+f4de+#define ICON_FA_TTY "\xef\x87\xa4" // U+f1e4+#define ICON_FA_TURKISH_LIRA_SIGN "\xee\x8a\xbb" // U+e2bb+#define ICON_FA_TURN_DOWN "\xef\x8e\xbe" // U+f3be+#define ICON_FA_TURN_UP "\xef\x8e\xbf" // U+f3bf+#define ICON_FA_TV "\xef\x89\xac" // U+f26c+#define ICON_FA_U "U" // U+0055+#define ICON_FA_UMBRELLA "\xef\x83\xa9" // U+f0e9+#define ICON_FA_UMBRELLA_BEACH "\xef\x97\x8a" // U+f5ca+#define ICON_FA_UNDERLINE "\xef\x83\x8d" // U+f0cd+#define ICON_FA_UNIVERSAL_ACCESS "\xef\x8a\x9a" // U+f29a+#define ICON_FA_UNLOCK "\xef\x82\x9c" // U+f09c+#define ICON_FA_UNLOCK_KEYHOLE "\xef\x84\xbe" // U+f13e+#define ICON_FA_UP_DOWN "\xef\x8c\xb8" // U+f338+#define ICON_FA_UP_DOWN_LEFT_RIGHT "\xef\x82\xb2" // U+f0b2+#define ICON_FA_UP_LONG "\xef\x8c\x8c" // U+f30c+#define ICON_FA_UP_RIGHT_AND_DOWN_LEFT_FROM_CENTER "\xef\x90\xa4" // U+f424+#define ICON_FA_UP_RIGHT_FROM_SQUARE "\xef\x8d\x9d" // U+f35d+#define ICON_FA_UPLOAD "\xef\x82\x93" // U+f093+#define ICON_FA_USER "\xef\x80\x87" // U+f007+#define ICON_FA_USER_ASTRONAUT "\xef\x93\xbb" // U+f4fb+#define ICON_FA_USER_CHECK "\xef\x93\xbc" // U+f4fc+#define ICON_FA_USER_CLOCK "\xef\x93\xbd" // U+f4fd+#define ICON_FA_USER_DOCTOR "\xef\x83\xb0" // U+f0f0+#define ICON_FA_USER_GEAR "\xef\x93\xbe" // U+f4fe+#define ICON_FA_USER_GRADUATE "\xef\x94\x81" // U+f501+#define ICON_FA_USER_GROUP "\xef\x94\x80" // U+f500+#define ICON_FA_USER_INJURED "\xef\x9c\xa8" // U+f728+#define ICON_FA_USER_LARGE "\xef\x90\x86" // U+f406+#define ICON_FA_USER_LARGE_SLASH "\xef\x93\xba" // U+f4fa+#define ICON_FA_USER_LOCK "\xef\x94\x82" // U+f502+#define ICON_FA_USER_MINUS "\xef\x94\x83" // U+f503+#define ICON_FA_USER_NINJA "\xef\x94\x84" // U+f504+#define ICON_FA_USER_NURSE "\xef\xa0\xaf" // U+f82f+#define ICON_FA_USER_PEN "\xef\x93\xbf" // U+f4ff+#define ICON_FA_USER_PLUS "\xef\x88\xb4" // U+f234+#define ICON_FA_USER_SECRET "\xef\x88\x9b" // U+f21b+#define ICON_FA_USER_SHIELD "\xef\x94\x85" // U+f505+#define ICON_FA_USER_SLASH "\xef\x94\x86" // U+f506+#define ICON_FA_USER_TAG "\xef\x94\x87" // U+f507+#define ICON_FA_USER_TIE "\xef\x94\x88" // U+f508+#define ICON_FA_USER_XMARK "\xef\x88\xb5" // U+f235+#define ICON_FA_USERS "\xef\x83\x80" // U+f0c0+#define ICON_FA_USERS_BETWEEN_LINES "\xee\x96\x91" // U+e591+#define ICON_FA_USERS_GEAR "\xef\x94\x89" // U+f509+#define ICON_FA_USERS_LINE "\xee\x96\x92" // U+e592+#define ICON_FA_USERS_RAYS "\xee\x96\x93" // U+e593+#define ICON_FA_USERS_RECTANGLE "\xee\x96\x94" // U+e594+#define ICON_FA_USERS_SLASH "\xee\x81\xb3" // U+e073+#define ICON_FA_USERS_VIEWFINDER "\xee\x96\x95" // U+e595+#define ICON_FA_UTENSILS "\xef\x8b\xa7" // U+f2e7+#define ICON_FA_V "V" // U+0056+#define ICON_FA_VAN_SHUTTLE "\xef\x96\xb6" // U+f5b6+#define ICON_FA_VAULT "\xee\x8b\x85" // U+e2c5+#define ICON_FA_VECTOR_SQUARE "\xef\x97\x8b" // U+f5cb+#define ICON_FA_VENUS "\xef\x88\xa1" // U+f221+#define ICON_FA_VENUS_DOUBLE "\xef\x88\xa6" // U+f226+#define ICON_FA_VENUS_MARS "\xef\x88\xa8" // U+f228+#define ICON_FA_VEST "\xee\x82\x85" // U+e085+#define ICON_FA_VEST_PATCHES "\xee\x82\x86" // U+e086+#define ICON_FA_VIAL "\xef\x92\x92" // U+f492+#define ICON_FA_VIAL_CIRCLE_CHECK "\xee\x96\x96" // U+e596+#define ICON_FA_VIAL_VIRUS "\xee\x96\x97" // U+e597+#define ICON_FA_VIALS "\xef\x92\x93" // U+f493+#define ICON_FA_VIDEO "\xef\x80\xbd" // U+f03d+#define ICON_FA_VIDEO_SLASH "\xef\x93\xa2" // U+f4e2+#define ICON_FA_VIHARA "\xef\x9a\xa7" // U+f6a7+#define ICON_FA_VIRUS "\xee\x81\xb4" // U+e074+#define ICON_FA_VIRUS_COVID "\xee\x92\xa8" // U+e4a8+#define ICON_FA_VIRUS_COVID_SLASH "\xee\x92\xa9" // U+e4a9+#define ICON_FA_VIRUS_SLASH "\xee\x81\xb5" // U+e075+#define ICON_FA_VIRUSES "\xee\x81\xb6" // U+e076+#define ICON_FA_VOICEMAIL "\xef\xa2\x97" // U+f897+#define ICON_FA_VOLCANO "\xef\x9d\xb0" // U+f770+#define ICON_FA_VOLLEYBALL "\xef\x91\x9f" // U+f45f+#define ICON_FA_VOLUME_HIGH "\xef\x80\xa8" // U+f028+#define ICON_FA_VOLUME_LOW "\xef\x80\xa7" // U+f027+#define ICON_FA_VOLUME_OFF "\xef\x80\xa6" // U+f026+#define ICON_FA_VOLUME_XMARK "\xef\x9a\xa9" // U+f6a9+#define ICON_FA_VR_CARDBOARD "\xef\x9c\xa9" // U+f729+#define ICON_FA_W "W" // U+0057+#define ICON_FA_WALKIE_TALKIE "\xef\xa3\xaf" // U+f8ef+#define ICON_FA_WALLET "\xef\x95\x95" // U+f555+#define ICON_FA_WAND_MAGIC "\xef\x83\x90" // U+f0d0+#define ICON_FA_WAND_MAGIC_SPARKLES "\xee\x8b\x8a" // U+e2ca+#define ICON_FA_WAND_SPARKLES "\xef\x9c\xab" // U+f72b+#define ICON_FA_WAREHOUSE "\xef\x92\x94" // U+f494+#define ICON_FA_WATER "\xef\x9d\xb3" // U+f773+#define ICON_FA_WATER_LADDER "\xef\x97\x85" // U+f5c5+#define ICON_FA_WAVE_SQUARE "\xef\xa0\xbe" // U+f83e+#define ICON_FA_WEIGHT_HANGING "\xef\x97\x8d" // U+f5cd+#define ICON_FA_WEIGHT_SCALE "\xef\x92\x96" // U+f496+#define ICON_FA_WHEAT_AWN "\xee\x8b\x8d" // U+e2cd+#define ICON_FA_WHEAT_AWN_CIRCLE_EXCLAMATION "\xee\x96\x98" // U+e598+#define ICON_FA_WHEELCHAIR "\xef\x86\x93" // U+f193+#define ICON_FA_WHEELCHAIR_MOVE "\xee\x8b\x8e" // U+e2ce+#define ICON_FA_WHISKEY_GLASS "\xef\x9e\xa0" // U+f7a0+#define ICON_FA_WIFI "\xef\x87\xab" // U+f1eb+#define ICON_FA_WIND "\xef\x9c\xae" // U+f72e+#define ICON_FA_WINDOW_MAXIMIZE "\xef\x8b\x90" // U+f2d0+#define ICON_FA_WINDOW_MINIMIZE "\xef\x8b\x91" // U+f2d1+#define ICON_FA_WINDOW_RESTORE "\xef\x8b\x92" // U+f2d2+#define ICON_FA_WINE_BOTTLE "\xef\x9c\xaf" // U+f72f+#define ICON_FA_WINE_GLASS "\xef\x93\xa3" // U+f4e3+#define ICON_FA_WINE_GLASS_EMPTY "\xef\x97\x8e" // U+f5ce+#define ICON_FA_WON_SIGN "\xef\x85\x99" // U+f159+#define ICON_FA_WORM "\xee\x96\x99" // U+e599+#define ICON_FA_WRENCH "\xef\x82\xad" // U+f0ad+#define ICON_FA_X "X" // U+0058+#define ICON_FA_X_RAY "\xef\x92\x97" // U+f497+#define ICON_FA_XMARK "\xef\x80\x8d" // U+f00d+#define ICON_FA_XMARKS_LINES "\xee\x96\x9a" // U+e59a+#define ICON_FA_Y "Y" // U+0059+#define ICON_FA_YEN_SIGN "\xef\x85\x97" // U+f157+#define ICON_FA_YIN_YANG "\xef\x9a\xad" // U+f6ad+#define ICON_FA_Z "Z" // U+005a
+ cbits/tracy/profiler/src/profiler/TracyAchievementData.cpp view
@@ -0,0 +1,202 @@+#include "IconsFontAwesome6.h"+#include "TracyAchievements.hpp"+#include "TracyImGui.hpp"+#include "TracySourceContents.hpp"+#include "TracyWeb.hpp"++namespace tracy::data+{++AchievementItem ai_samplingIntro = { "samplingIntro", "Sampling program execution", [](const ctx& c){+ ImGui::TextWrapped( "Sampling program execution is a great way to find out where the hot spots are in your program. It can be used to find out which functions take the most time, or which lines of code are executed the most often." );+ ImGui::TextWrapped( "While instrumentation requires changes to your code, sampling does not. However, because of the way it works, the results are coarser and it's not possible to know when functions are called or when they return." );+ ImGui::TextWrapped( "Sampling is automatic on Linux. On Windows, you must run the profiled application as an administrator for it to work." );+ ImGui::PushFont( c.small );+ ImGui::PushStyleColor( ImGuiCol_Text, GImGui->Style.Colors[ImGuiCol_TextDisabled] );+ ImGui::TextWrapped( "Depending on your system configuration, some additional steps may be required. Please refer to the user manual for more information." );+ ImGui::PopStyleColor();+ ImGui::PopFont();+} };++AchievementItem* ac_samplingItems[] = { &ai_samplingIntro, nullptr };+AchievementCategory ac_sampling = { "sampling", "Sampling", ac_samplingItems };+++AchievementItem ai_100million = { "100million", "It's over 100 million!", [](const ctx& c){+ ImGui::TextWrapped( "Tracy can handle a lot of data. How about 100 million zones in a single trace? Add a lot of zones to your program and see how it handles it!" );+ ImGui::TextWrapped( "Capturing a long-running profile trace is easy. Need to profile an hour of your program execution? You can do it." );+ ImGui::TextWrapped( "Note that it doesn't make much sense to instrument every little function you might have. The cost of the instrumentation itself will be higher than the cost of the function in such a case." );+ ImGui::PushFont( c.small );+ ImGui::PushStyleColor( ImGuiCol_Text, GImGui->Style.Colors[ImGuiCol_TextDisabled] );+ ImGui::TextWrapped( "Keep in mind that the more zones you have, the more memory and CPU time the profiler will use. Be careful not to run out of memory." );+ ImGui::TextWrapped( "To capture 100 million zones, you will need approximately 4 GB of RAM." );+ ImGui::PopStyleColor();+ ImGui::PopFont();+} };++AchievementItem ai_instrumentationStatistics = { "instrumentationStatistics", "Show me the stats!", [](const ctx&){+ ImGui::TextWrapped( "Once you have instrumented your application, you can view the statistics for each zone in the timeline. This allows you to see how much time is spent in each zone and how many times it is called." );+ ImGui::TextWrapped( "To view the statistics, click on the \"" ICON_FA_ARROW_UP_WIDE_SHORT " Statistics\" button on the top bar. This will open a new window with a list of all zones in the trace." );+} };++AchievementItem ai_findZone = { "findZone", "Find some zones", [](const ctx&){+ ImGui::TextWrapped( "You can search for zones in the trace by opening the search window with the \"" ICON_FA_MAGNIFYING_GLASS " Find zone\" button on the top bar. It will ask you for the zone name, which in most cases will be the function name in the code." );+ ImGui::TextWrapped( "The search may find more than one zone with the same name. A list of all the zones found is displayed, and you can select any of them." );+ ImGui::TextWrapped( "Alternatively, you can open the Statistics window and click an entry there. This will open the Find zone window as if you had searched for that zone." );+ ImGui::TextWrapped( "When a zone is selected, a number of statistics are displayed to help you understand the performance of your application. In addition, a histogram of the zone execution times is displayed to make it easier for you to determine the performance of the profiled code. Be sure to select a zone with a large number of calls to make the histogram look interesting!" );+ ImGui::TextWrapped( "Note that you can draw a range on the histogram to limit the number of entries displayed in the zone list below. This list allows you to examine each zone individually. There are also a number of zone groupings that you can select. Each group can be selected and the time associated with the selected group will be highlighted on the histogram." );+} };++AchievementItem* ac_instrumentationIntroItems[] = {+ &ai_100million,+ &ai_instrumentationStatistics,+ &ai_findZone,+ nullptr+};++AchievementItem ai_instrumentationIntro = { "instrumentationIntro", "Instrumentating your application", [](const ctx& c){+ constexpr const char* src = R"(#include "Tracy.hpp"++void SomeFunction()+{+ ZoneScoped;+ // Your code here+}+)";++ static SourceContents sc;+ sc.Parse( src );++ ImGui::TextWrapped( "Instrumentation is a powerful feature that allows you to see the exact runtime of each call to the selected set of functions. The downside is that it takes a bit of manual work to get it set up." );+ ImGui::TextWrapped( "To get started, open a source file and include the Tracy.hpp header. This will give you access to a variety of macros provided by Tracy. Next, add the ZoneScoped macro to the beginning of one of your functions, like this:" );+ ImGui::PushFont( c.fixed );+ PrintSource( sc.get() );+ ImGui::PopFont();+ ImGui::TextWrapped( "Now, when you profile your application, you will see a new zone appear on the timeline for each call to the function. This allows you to see how much time is spent in each call and how many times the function is called." );+ ImGui::PushFont( c.small );+ ImGui::PushStyleColor( ImGuiCol_Text, GImGui->Style.Colors[ImGuiCol_TextDisabled] );+ ImGui::TextWrapped( "Note: The ZoneScoped macro is just one of the many macros provided by Tracy. See the documentation for more information." );+ ImGui::TextWrapped( "The above description applies to C++ code, but things are done similarly in other programming languages. Refer to the documentation for your language for more information." );+ ImGui::PopStyleColor();+ ImGui::PopFont();+}, ac_instrumentationIntroItems };++AchievementItem ai_frameImages = { "frameImages", "A picture is worth a thousand words", [](const ctx&){+ ImGui::TextWrapped( "Tracy allows you to add context to each frame, by attaching a screenshot. You can do this with the FrameImage macro." );+ ImGui::TextWrapped( "You will have to do the screen capture and resizing yourself, which can be a bit complicated. The manual provides a sample code that shows how to do this in a performant way." );+ ImGui::TextWrapped( "The frame images are displayed in the context of a frame, for example, when you hover over the frame in the timeline or in the frame graph at the top of the screen." );+ ImGui::TextWrapped( "You can even view a recording of what your application was doing by clicking the " ICON_FA_SCREWDRIVER_WRENCH " icon and then selecting the \"" ICON_FA_PLAY " Playback\" option. Try it out!" );+ ImGui::TextWrapped( "The FrameImage macro is a great way to see what happened in your application at a particular time. Maybe you have a performance problem that only occurs when a certain object is on the screen?" );+} };++AchievementItem* ac_instrumentFramesItems[] = {+ &ai_frameImages,+ nullptr+};++AchievementItem ai_instrumentFrames = { "instrumentFrames", "Instrumenting frames", [](const ctx& c){+ constexpr const char* src = R"(#include "Tracy.hpp"++void Render()+{+ // Render the frame+ SwapBuffers();+ FrameMark;+}+)";++ static SourceContents sc;+ sc.Parse( src );++ ImGui::TextWrapped( "In addition to instrumenting functions, you can also instrument frames. This allows you to see how much time is spent in each frame of your application." );+ ImGui::TextWrapped( "To instrument frames, you need to add the FrameMark macro at the beginning of each frame. This can be done in the main loop of your application, or in a separate function that is called at the beginning of each frame." );+ ImGui::PushFont( c.fixed );+ PrintSource( sc.get() );+ ImGui::PopFont();+ ImGui::TextWrapped( "When you profile your application, you will see a new frame appear on the timeline each time the FrameMark macro is called. This allows you to see how much time is spent in each frame and how many frames are rendered per second." );+ ImGui::TextWrapped( "The FrameMark macro is a great way to see at a glance how your application is performing over time. Maybe there are some performance problems that only appear after a few minutes of running the application? A frame graph is drawn at the top of the profiler window where you can see the timing of all frames." );+ ImGui::TextWrapped( "Note that some applications do not have a frame-based structure, and in such cases, frame instrumentation may not be useful. That's ok." );+}, ac_instrumentFramesItems };++AchievementItem* ac_instrumentationItems[] = { &ai_instrumentationIntro, &ai_instrumentFrames, nullptr };+AchievementCategory ac_instrumentation = { "instrumentation", "Instrumentation", ac_instrumentationItems };+++AchievementItem ai_loadTrace = { "loadTrace", "Load a trace", [](const ctx&){+ ImGui::TextWrapped( "You can open a previously saved trace file (or one received from a friend) with the \"" ICON_FA_FOLDER_OPEN " Open saved trace\" button on the welcome screen." );+} };++AchievementItem ai_saveTrace = { "saveTrace", "Save a trace", [](const ctx&){+ ImGui::TextWrapped( "Now that you have traced your application (or are in the process of doing so), you can save it to disk for future reference. You can do this by clicking on the " ICON_FA_WIFI " icon in the top left corner of the screen and then clicking on the \"" ICON_FA_FLOPPY_DISK " Save trace\" button." );+ ImGui::TextWrapped( "Keeping old traces on hand can be beneficial, as you can compare the performance of your optimizations with what you had before." );+ ImGui::TextWrapped( "You can also share the trace with your friends or co-workers by sending them the trace file." );+ ImGui::Spacing();+ tracy::TextColoredUnformatted( 0xFF44FFFF, ICON_FA_TRIANGLE_EXCLAMATION );+ ImGui::SameLine();+ ImGui::TextUnformatted( "Warning" );+ ImGui::SameLine();+ tracy::TextColoredUnformatted( 0xFF44FFFF, ICON_FA_TRIANGLE_EXCLAMATION );+ ImGui::TextWrapped( "Trace files can contain sensitive information about your application, such as program code, or even the contents of source files. Be careful when sharing them with others." );+} };++AchievementItem* ac_connectToServerItems[] = {+ &ai_saveTrace,+ &ai_loadTrace,+ nullptr+};++AchievementItem* ac_connectToServerUnlock[] = {+ &ai_instrumentationIntro,+ &ai_samplingIntro,+ nullptr+};++AchievementItem ai_connectToServer = { "connectToClient", "First profiling session", [](const ctx&){+ ImGui::TextWrapped( "Let's start our adventure by instrumenting your application and connecting it to the profiler. Here's a quick refresher:" );+ ImGui::TextWrapped( " 1. Integrate Tracy Profiler into your application. This can be done using CMake, Meson, or simply by adding the source files to your project." );+ ImGui::TextWrapped( " 2. Make sure that TracyClient.cpp (or the Tracy library) is included in your build." );+ ImGui::TextWrapped( " 3. Define TRACY_ENABLE in your build configuration, for the whole application. Do not do it in a single source file because it won't work." );+ ImGui::TextWrapped( " 4. Start your application, and \"" ICON_FA_WIFI " Connect\" to it with the profiler." );+ ImGui::TextWrapped( "Please refer to the user manual for more details." );+ if( ImGui::SmallButton( "Download the user manual" ) )+ {+ tracy::OpenWebpage( "https://github.com/wolfpld/tracy/releases" );+ }+}, ac_connectToServerItems, ac_connectToServerUnlock };++AchievementItem ai_globalSettings = { "globalSettings", "Global settings", [](const ctx&){+ ImGui::TextWrapped( "Tracy has a variety of settings that can be adjusted to suit your needs. These settings can be found by clicking on the " ICON_FA_WRENCH " icon on the welcome screen. This will open the about window, where you can expand the \"" ICON_FA_TOOLBOX " Global settings\" menu." );+ ImGui::TextWrapped( "The settings are saved between sessions, so you only need to set them once." );+} };++AchievementItem* ac_achievementsIntroItems[] = {+ &ai_connectToServer,+ &ai_globalSettings,+ nullptr+};++AchievementItem ai_achievementsIntro = { "achievementsIntro", "Click here to discover achievements!", [](const ctx&){+ ImGui::TextWrapped( "Clicking on the " ICON_FA_STAR " button opens the Achievements List. Here you can see the tasks to be completed along with a short description of what needs to be done." );+ ImGui::TextWrapped( "As you complete each Achievement, new Achievements will appear, so be sure to keep checking the list for new ones!" );+ ImGui::TextWrapped( "To make the new things easier to spot, the Achievements List will show a marker next to them. The achievements " ICON_FA_STAR " button will glow yellow when there are new things to see." );+ ImGui::TextUnformatted( "New tasks:" );+ ImGui::SameLine();+ TextColoredUnformatted( 0xFF4488FF, ICON_FA_CIRCLE_EXCLAMATION );+ ImGui::TextUnformatted( "Completed tasks:" );+ ImGui::SameLine();+ TextColoredUnformatted( 0xFF44FF44, ICON_FA_CIRCLE_CHECK );+ ImGui::TextWrapped( "Good luck!" );+}, ac_achievementsIntroItems, nullptr, true, 1 };++AchievementItem* ac_firstStepsItems[] = { &ai_achievementsIntro, nullptr };+AchievementCategory ac_firstSteps = { "firstSteps", "First steps", ac_firstStepsItems, 1 };+++AchievementCategory* AchievementCategories[] = {+ &ac_firstSteps,+ &ac_instrumentation,+ &ac_sampling,+ nullptr+};++}
+ cbits/tracy/profiler/src/profiler/TracyAchievements.cpp view
@@ -0,0 +1,225 @@+#include <assert.h>+#include <inttypes.h>+#include <time.h>++#include "../ini.h"++#include "TracyAchievements.hpp"+#include "TracyStorage.hpp"++namespace tracy+{++namespace data { extern AchievementCategory* AchievementCategories[]; }++AchievementsMgr::AchievementsMgr()+{+ auto cat = data::AchievementCategories;+ while( *cat )+ {+ FillMap( (*cat)->items, *cat );+ cat++;+ }++ const auto fn = tracy::GetSavePath( "achievements.ini" );+ auto ini = ini_load( fn );+ if( !ini ) return;++ for( auto& v : m_map )+ {+ uint64_t unlockTime, doneTime;+ int hideCompleted, hideNew;++ if( ini_sget( ini, v.first, "unlockTime", "%" PRIu64, &unlockTime ) &&+ ini_sget( ini, v.first, "doneTime", "%" PRIu64, &doneTime ) &&+ ini_sget( ini, v.first, "hideCompleted", "%d", &hideCompleted ) &&+ ini_sget( ini, v.first, "hideNew", "%d", &hideNew ) )+ {+ auto& it = v.second.item;+ it->unlockTime = unlockTime;+ it->doneTime = doneTime;+ it->hideCompleted = hideCompleted != 0;+ it->hideNew = hideNew != 0;+ }+ }++ for( auto& v : m_map )+ {+ auto& it = v.second.item;+ if( it->doneTime > 0 )+ {+ auto c = it->items;+ if( c )+ {+ while( *c )+ {+ if( (*c)->unlockTime == 0 ) (*c)->unlockTime = it->doneTime;+ c++;+ }+ }+ c = it->unlocks;+ if( c )+ {+ while( *c )+ {+ if( (*c)->unlockTime == 0 ) (*c)->unlockTime = it->doneTime;+ c++;+ }+ }+ }+ }++ for( auto& v : m_map )+ {+ if( v.second.category->unlockTime == 0 && v.second.item->unlockTime > 0 )+ {+ v.second.category->unlockTime = v.second.item->unlockTime;+ }+ }++ auto c = data::AchievementCategories;+ while( *c )+ {+ if( (*c)->unlockTime > 0 )+ {+ auto items = (*c)->items;+ while( *items )+ {+ if( (*items)->unlockTime == 0 ) (*items)->unlockTime = (*c)->unlockTime;+ items++;+ }+ }+ c++;+ }++ ini_free( ini );+}++AchievementsMgr::~AchievementsMgr()+{+ Save();+}++void AchievementsMgr::Achieve( const char* id )+{+ auto it = m_map.find( id );+ assert( it != m_map.end() );+ auto& a = *it->second.item;++ if( a.unlockTime == 0 ) return;+ if( a.doneTime > 0 ) return;++ const auto t = uint64_t( time( nullptr ) );++ a.doneTime = uint64_t( t );+ m_queue.push_back( &a );++ auto c = a.items;+ if( c )+ {+ while( *c ) (*c++)->unlockTime = t;+ }+ c = a.unlocks;+ if( c )+ {+ while( *c )+ {+ (*c)->unlockTime = t;+ auto cit = m_map.find( (*c)->id );+ if( cit->second.category->unlockTime == 0 ) cit->second.category->unlockTime = t;+ c++;+ }+ }++ Save();+}++data::AchievementCategory** AchievementsMgr::GetCategories() const+{+ return data::AchievementCategories;+}++data::AchievementCategory* AchievementsMgr::GetCategoryForAchievement( const char* id ) const+{+ auto it = m_map.find( id );+ assert( it != m_map.end() );+ return it->second.category;+}++data::AchievementItem* AchievementsMgr::GetNextQueue()+{+ if( m_queue.empty() ) return nullptr;+ return m_queue.front();+}++void AchievementsMgr::PopQueue()+{+ assert( !m_queue.empty() );+ m_queue.erase( m_queue.begin() );+}++bool AchievementsMgr::NeedsAttention() const+{+ for( auto& v : m_map )+ {+ auto& it = v.second.item;+ if( it->unlockTime > 0 && !it->hideNew ) return true;+ if( it->doneTime > 0 && !it->hideCompleted ) return true;+ }+ return false;+}++bool AchievementsMgr::CategoryNeedsAttention( const char* id ) const+{+ auto c = data::AchievementCategories;+ while( *c )+ {+ if( strcmp( (*c)->id, id ) == 0 )+ {+ for( auto& v : m_map )+ {+ if( v.second.category == (*c) )+ {+ auto& it = v.second.item;+ if( it->unlockTime > 0 && !it->hideNew ) return true;+ if( it->doneTime > 0 && !it->hideCompleted ) return true;+ }+ }+ return false;+ }+ c++;+ }+ assert( false );+ return false;+}++void AchievementsMgr::FillMap( data::AchievementItem** items, data::AchievementCategory* category )+{+ while( *items )+ {+ m_map.emplace( (*items)->id, AchievementPair { *items, category } );+ if( (*items)->items) FillMap( (*items)->items, category );+ items++;+ }+}++void AchievementsMgr::Save()+{+ const auto fn = tracy::GetSavePath( "achievements.ini" );+ FILE* f = fopen( fn, "wb" );+ if( !f ) return;++ for( auto& v : m_map )+ {+ auto& it = v.second.item;+ fprintf( f, "[%s]\n", it->id );+ fprintf( f, "unlockTime=%" PRIu64 "\n", it->unlockTime );+ fprintf( f, "doneTime=%" PRIu64 "\n", it->doneTime );+ fprintf( f, "hideCompleted=%d\n", it->hideCompleted ? 1 : 0 );+ fprintf( f, "hideNew=%d\n\n", it->hideNew ? 1 : 0 );+ }++ fclose( f );+}++}
+ cbits/tracy/profiler/src/profiler/TracyAchievements.hpp view
@@ -0,0 +1,82 @@+#ifndef __TRACYACHIEVEMENTS_HPP__+#define __TRACYACHIEVEMENTS_HPP__++#include <stdint.h>+#include <string>+#include <vector>++#include "imgui.h"++#include "TracyCharUtil.hpp"+#include "tracy_robin_hood.h"++namespace tracy+{++namespace data+{++struct ctx+{+ ImFont* big;+ ImFont* small;+ ImFont* fixed;+};++struct AchievementItem+{+ const char* id;+ const char* name;+ void(*description)(const ctx&);+ AchievementItem** items;+ AchievementItem** unlocks;+ bool keepOpen;+ uint64_t unlockTime;+ uint64_t doneTime;+ bool hideCompleted;+ bool hideNew;+};++struct AchievementCategory+{+ const char* id;+ const char* name;+ AchievementItem** items;+ uint64_t unlockTime;+};++}++class AchievementsMgr+{+ struct AchievementPair+ {+ data::AchievementItem* item;+ data::AchievementCategory* category;+ };++public:+ AchievementsMgr();+ ~AchievementsMgr();++ void Achieve( const char* id );+ data::AchievementCategory** GetCategories() const;+ data::AchievementCategory* GetCategoryForAchievement( const char* id ) const;++ data::AchievementItem* GetNextQueue();+ void PopQueue();++ bool NeedsAttention() const;+ bool CategoryNeedsAttention( const char* id ) const;++private:+ void FillMap( data::AchievementItem** items, data::AchievementCategory* category );+ void Save();++ std::vector<data::AchievementItem*> m_queue;+ tracy::unordered_flat_map<const char*, AchievementPair, charutil::Hasher, charutil::Comparator> m_map;+};++}++#endif
+ cbits/tracy/profiler/src/profiler/TracyBadVersion.cpp view
@@ -0,0 +1,124 @@+#include <assert.h>++#include "imgui.h"++#include "IconsFontAwesome6.h"+#include "TracyBadVersion.hpp"+#include "TracyImGui.hpp"+#include "TracyWeb.hpp"++namespace tracy+{++namespace detail+{++void BadVersionImpl( BadVersionState& badVer, ImFont* big )+{+ assert( badVer.state != BadVersionState::Ok );++ switch( badVer.state )+ {+ case BadVersionState::BadFile:+ ImGui::OpenPopup( "Bad file" );+ break;+ case BadVersionState::ReadError:+ ImGui::OpenPopup( "File read error" );+ break;+ case BadVersionState::UnsupportedVersion:+ ImGui::OpenPopup( "Unsupported file version" );+ break;+ case BadVersionState::LegacyVersion:+ ImGui::OpenPopup( "Legacy file version" );+ break;+ case BadVersionState::LoadFailure:+ ImGui::OpenPopup( "Trace load failure" );+ break;+ default:+ assert( false );+ break;+ }+ if( ImGui::BeginPopupModal( "Bad file", nullptr, ImGuiWindowFlags_AlwaysAutoResize ) )+ {+ ImGui::PushFont( big );+ TextCentered( ICON_FA_TRIANGLE_EXCLAMATION );+ ImGui::PopFont();+ ImGui::Text( "The file you are trying to open is not a Tracy dump." );+ ImGui::Separator();+ if( ImGui::Button( "Oops" ) )+ {+ ImGui::CloseCurrentPopup();+ badVer.state = BadVersionState::Ok;+ }+ ImGui::EndPopup();+ }+ if( ImGui::BeginPopupModal( "File read error", nullptr, ImGuiWindowFlags_AlwaysAutoResize ) )+ {+ ImGui::PushFont( big );+ TextCentered( ICON_FA_TRIANGLE_EXCLAMATION );+ ImGui::PopFont();+ ImGui::Text( "The file you are trying to open cannot be mapped to memory." );+ ImGui::Separator();+ if( ImGui::Button( "OK" ) )+ {+ ImGui::CloseCurrentPopup();+ badVer.state = BadVersionState::Ok;+ }+ ImGui::EndPopup();+ }+ if( ImGui::BeginPopupModal( "Unsupported file version", nullptr, ImGuiWindowFlags_AlwaysAutoResize ) )+ {+ ImGui::PushFont( big );+ TextCentered( ICON_FA_CLOUD_ARROW_DOWN );+ ImGui::PopFont();+ ImGui::Text( "The file you are trying to open is unsupported.\nYou should update to Tracy %i.%i.%i or newer and try again.", badVer.version >> 16, ( badVer.version >> 8 ) & 0xFF, badVer.version & 0xFF );+ ImGui::Separator();+ if( ImGui::Button( ICON_FA_DOWNLOAD " Download update" ) )+ {+ tracy::OpenWebpage( "https://github.com/wolfpld/tracy/releases" );+ ImGui::CloseCurrentPopup();+ badVer.state = BadVersionState::Ok;+ }+ ImGui::SameLine();+ if( ImGui::Button( "Maybe later" ) )+ {+ ImGui::CloseCurrentPopup();+ badVer.state = BadVersionState::Ok;+ }+ ImGui::EndPopup();+ }+ if( ImGui::BeginPopupModal( "Legacy file version", nullptr, ImGuiWindowFlags_AlwaysAutoResize ) )+ {+ ImGui::PushFont( big );+ TextCentered( ICON_FA_GHOST );+ ImGui::PopFont();+ ImGui::Text( "You are trying to open a file which was created by legacy version %i.%i.%i.\nUse the update utility from an older version of the profiler to convert the file to a supported version.", badVer.version >> 16, ( badVer.version >> 8 ) & 0xFF, badVer.version & 0xFF );+ ImGui::Separator();+ if( ImGui::Button( "Maybe I don't need it" ) )+ {+ ImGui::CloseCurrentPopup();+ badVer.state = BadVersionState::Ok;+ }+ ImGui::EndPopup();+ }+ if( ImGui::BeginPopupModal( "Trace load failure", nullptr, ImGuiWindowFlags_AlwaysAutoResize ) )+ {+ ImGui::PushFont( big );+ TextCentered( ICON_FA_BOMB );+ ImGui::PopFont();+ ImGui::TextUnformatted( "The file you are trying to open is corrupted." );+ ImGui::Spacing();+ ImGui::TextUnformatted( badVer.msg.c_str() );+ ImGui::Separator();+ if( ImGui::Button( "OK" ) )+ {+ ImGui::CloseCurrentPopup();+ badVer.state = BadVersionState::Ok;+ }+ ImGui::EndPopup();+ }+}++}++}
+ cbits/tracy/profiler/src/profiler/TracyBadVersion.hpp view
@@ -0,0 +1,39 @@+#ifndef __TRACYBADVERSION_HPP__+#define __TRACYBADVERSION_HPP__++#include <string>++#include "../public/common/TracyForceInline.hpp"++struct ImFont;++namespace tracy+{++struct BadVersionState+{+ enum State+ {+ Ok,+ BadFile,+ ReadError,+ UnsupportedVersion,+ LegacyVersion,+ LoadFailure+ };++ State state = Ok;+ int version = 0;+ std::string msg;+};++namespace detail+{+void BadVersionImpl( BadVersionState& badVer, ImFont* big );+}++tracy_force_inline void BadVersion( BadVersionState& badVer, ImFont* big ) { if( badVer.state != BadVersionState::Ok ) detail::BadVersionImpl( badVer, big ); }++}++#endif
+ cbits/tracy/profiler/src/profiler/TracyBuzzAnim.hpp view
@@ -0,0 +1,50 @@+#ifndef __TRACYBUZZANIM_HPP__+#define __TRACYBUZZANIM_HPP__++#include <assert.h>++namespace tracy+{++template<typename T>+class BuzzAnim+{+public:+ bool Match( const T& comp ) const+ {+ return active && comp == id;+ }++ float Time() const+ {+ assert( active );+ return time;+ }++ void Enable( const T& val, float len )+ {+ active = true;+ time = len;+ id = val;+ }++ bool Update( float dt )+ {+ if( active )+ {+ time -= dt;+ if( time <= 0 ) active = false;+ return true;+ }+ return false;+ }++private:+ bool active = false;+ float time;+ T id;+};++}++#endif
+ cbits/tracy/profiler/src/profiler/TracyColor.cpp view
@@ -0,0 +1,36 @@+#include <algorithm>++#include "TracyColor.hpp"++namespace tracy+{++uint32_t GetHsvColor( uint64_t hue, int value )+{+ const uint8_t h = ( hue * 11400714819323198485ull ) & 0xFF;+ const uint8_t s = 108;+ const uint8_t v = std::max( 96, 170 - value * 8 );++ const uint8_t reg = h / 43;+ const uint8_t rem = ( h - ( reg * 43 ) ) * 6;++ const uint8_t p = ( v * ( 255 - s ) ) >> 8;+ const uint8_t q = ( v * ( 255 - ( ( s * rem ) >> 8 ) ) ) >> 8;+ const uint8_t t = ( v * ( 255 - ( ( s * ( 255 - rem ) ) >> 8 ) ) ) >> 8;++ uint8_t r, g, b;++ switch( reg )+ {+ case 0: r = v; g = t; b = p; break;+ case 1: r = q; g = v; b = p; break;+ case 2: r = p; g = v; b = t; break;+ case 3: r = p; g = q; b = v; break;+ case 4: r = t; g = p; b = v; break;+ default: r = v; g = p; b = q; break;+ }++ return 0xFF000000 | ( r << 16 ) | ( g << 8 ) | b;+}++}
+ cbits/tracy/profiler/src/profiler/TracyColor.hpp view
@@ -0,0 +1,57 @@+#ifndef __TRACYCOLOR_HPP__+#define __TRACYCOLOR_HPP__++#include <algorithm>+#include <stdint.h>++#include "../public/common/TracyForceInline.hpp"++namespace tracy+{++uint32_t GetHsvColor( uint64_t hue, int value );++template<int V = 25>+static tracy_force_inline uint32_t HighlightColor( uint32_t color )+{+ return 0xFF000000 |+ ( std::min<int>( 0xFF, ( ( ( color & 0x00FF0000 ) >> 16 ) + V ) ) << 16 ) |+ ( std::min<int>( 0xFF, ( ( ( color & 0x0000FF00 ) >> 8 ) + V ) ) << 8 ) |+ ( std::min<int>( 0xFF, ( ( ( color & 0x000000FF ) ) + V ) ) );+}++static tracy_force_inline uint32_t DarkenColorSlightly( uint32_t color )+{+ return 0xFF000000 |+ ( ( ( ( color & 0x00FF0000 ) >> 16 ) * 4 / 5 ) << 16 ) |+ ( ( ( ( color & 0x0000FF00 ) >> 8 ) * 4 / 5 ) << 8 ) |+ ( ( ( ( color & 0x000000FF ) ) * 4 / 5 ) );+}++static tracy_force_inline uint32_t DarkenColor( uint32_t color )+{+ return 0xFF000000 |+ ( ( ( ( color & 0x00FF0000 ) >> 16 ) * 2 / 3 ) << 16 ) |+ ( ( ( ( color & 0x0000FF00 ) >> 8 ) * 2 / 3 ) << 8 ) |+ ( ( ( ( color & 0x000000FF ) ) * 2 / 3 ) );+}++static tracy_force_inline uint32_t DarkenColorHalf( uint32_t color )+{+ return 0xFF000000 |+ ( ( ( ( color & 0x00FF0000 ) >> 16 ) / 2 ) << 16 ) |+ ( ( ( ( color & 0x0000FF00 ) >> 8 ) / 2 ) << 8 ) |+ ( ( ( ( color & 0x000000FF ) ) / 2 ) );+}++static tracy_force_inline uint32_t DarkenColorMore( uint32_t color )+{+ return 0xFF000000 |+ ( ( ( ( color & 0x00FF0000 ) >> 16 ) * 1 / 4 ) << 16 ) |+ ( ( ( ( color & 0x0000FF00 ) >> 8 ) * 1 / 4 ) << 8 ) |+ ( ( ( ( color & 0x000000FF ) ) * 1 / 4 ) );+}++}++#endif
+ cbits/tracy/profiler/src/profiler/TracyConfig.hpp view
@@ -0,0 +1,29 @@+#ifndef __TRACYCONFIG_HPP__+#define __TRACYCONFIG_HPP__++#include "TracyUtility.hpp"++namespace tracy+{++struct Config+{+ bool threadedRendering = true;+ bool focusLostLimit = true;+ int targetFps = 60;+ double horizontalScrollMultiplier = 1.0;+ double verticalScrollMultiplier = 1.0;+ bool memoryLimit = false;+ int memoryLimitPercent = 80;+ bool achievements = false;+ bool achievementsAsked = false;+ int dynamicColors = 1;+ bool forceColors = false;+ int shortenName = (int)ShortenName::NoSpaceAndNormalize;+ bool saveUserScale = false;+ float userScale = 1.0f;+};++}++#endif
+ cbits/tracy/profiler/src/profiler/TracyDecayValue.hpp view
@@ -0,0 +1,48 @@+#ifndef __TRACYDECAYVALUE_HPP__+#define __TRACYDECAYVALUE_HPP__++#include "../public/common/TracyForceInline.hpp"++namespace tracy+{++template<typename T>+class DecayValue+{+public:+ DecayValue( const T& init, bool active = false )+ : m_value( init )+ , m_active( active )+ {+ }++ tracy_force_inline operator const T& () const { return m_value; }+ tracy_force_inline T operator->() const { return m_value; }++ tracy_force_inline DecayValue& operator=( const T& value )+ {+ m_value = value;+ m_active = true;+ return *this;+ }++ tracy_force_inline void Decay( const T& value )+ {+ if( m_active )+ {+ m_active = false;+ }+ else+ {+ m_value = value;+ }+ }++private:+ T m_value;+ bool m_active;+};++}++#endif
+ cbits/tracy/profiler/src/profiler/TracyEventDebug.cpp view
@@ -0,0 +1,361 @@+#include <assert.h>+#include <stdio.h>+#include <inttypes.h>++#include "TracyEventDebug.hpp"+#include "../public/common/TracyQueue.hpp"++namespace tracy+{++void EventDebug( const QueueItem& ev )+{+ static FILE* f = fopen( "eventdebug.txt", "wb" );+ switch( ev.hdr.type )+ {+ case QueueType::ZoneText:+ fprintf( f, "ev %i (ZoneText)\n", ev.hdr.idx );+ break;+ case QueueType::ZoneName:+ fprintf( f, "ev %i (ZoneName)\n", ev.hdr.idx );+ break;+ case QueueType::Message:+ fprintf( f, "ev %i (Message)\n", ev.hdr.idx );+ break;+ case QueueType::MessageColor:+ fprintf( f, "ev %i (MessageColor)\n", ev.hdr.idx );+ break;+ case QueueType::MessageCallstack:+ fprintf( f, "ev %i (MessageCallstack)\n", ev.hdr.idx );+ break;+ case QueueType::MessageColorCallstack:+ fprintf( f, "ev %i (MessageColorCallstack)\n", ev.hdr.idx );+ break;+ case QueueType::MessageAppInfo:+ fprintf( f, "ev %i (MessageAppInfo)\n", ev.hdr.idx );+ break;+ case QueueType::ZoneBeginAllocSrcLoc:+ fprintf( f, "ev %i (ZoneBeginAllocSrcLoc)\n", ev.hdr.idx );+ break;+ case QueueType::ZoneBeginAllocSrcLocCallstack:+ fprintf( f, "ev %i (ZoneBeginAllocSrcLocCallstack)\n", ev.hdr.idx );+ break;+ case QueueType::CallstackSerial:+ fprintf( f, "ev %i (CallstackSerial)\n", ev.hdr.idx );+ break;+ case QueueType::Callstack:+ fprintf( f, "ev %i (Callstack)\n", ev.hdr.idx );+ break;+ case QueueType::CallstackAlloc:+ fprintf( f, "ev %i (CallstackAlloc)\n", ev.hdr.idx );+ break;+ case QueueType::CallstackSample:+ fprintf( f, "ev %i (CallstackSample)\n", ev.hdr.idx );+ break;+ case QueueType::CallstackSampleContextSwitch:+ fprintf( f, "ev %i (CallstackSampleContextSwitch)\n", ev.hdr.idx );+ break;+ case QueueType::FrameImage:+ fprintf( f, "ev %i (FrameImage)\n", ev.hdr.idx );+ break;+ case QueueType::ZoneBegin:+ fprintf( f, "ev %i (ZoneBegin)\n", ev.hdr.idx );+ fprintf( f, "\ttime = %" PRIi64 "\n", ev.zoneBeginLean.time );+ break;+ case QueueType::ZoneBeginCallstack:+ fprintf( f, "ev %i (ZoneBeginCallstack)\n", ev.hdr.idx );+ break;+ case QueueType::ZoneEnd:+ fprintf( f, "ev %i (ZoneEnd)\n", ev.hdr.idx );+ fprintf( f, "\ttime = %" PRIi64 "\n", ev.zoneEnd.time );+ break;+ case QueueType::LockWait:+ fprintf( f, "ev %i (LockWait)\n", ev.hdr.idx );+ break;+ case QueueType::LockObtain:+ fprintf( f, "ev %i (LockObtain)\n", ev.hdr.idx );+ break;+ case QueueType::LockRelease:+ fprintf( f, "ev %i (LockRelease)\n", ev.hdr.idx );+ break;+ case QueueType::LockSharedWait:+ fprintf( f, "ev %i (LockSharedWait)\n", ev.hdr.idx );+ break;+ case QueueType::LockSharedObtain:+ fprintf( f, "ev %i (LockSharedObtain)\n", ev.hdr.idx );+ break;+ case QueueType::LockSharedRelease:+ fprintf( f, "ev %i (LockSharedRelease)\n", ev.hdr.idx );+ break;+ case QueueType::LockName:+ fprintf( f, "ev %i (LockName)\n", ev.hdr.idx );+ break;+ case QueueType::MemAlloc:+ fprintf( f, "ev %i (MemAlloc)\n", ev.hdr.idx );+ break;+ case QueueType::MemAllocNamed:+ fprintf( f, "ev %i (MemAllocNamed)\n", ev.hdr.idx );+ break;+ case QueueType::MemFree:+ fprintf( f, "ev %i (MemFree)\n", ev.hdr.idx );+ break;+ case QueueType::MemFreeNamed:+ fprintf( f, "ev %i (MemFreeNamed)\n", ev.hdr.idx );+ break;+ case QueueType::MemAllocCallstack:+ fprintf( f, "ev %i (MemAllocCallstack)\n", ev.hdr.idx );+ break;+ case QueueType::MemAllocCallstackNamed:+ fprintf( f, "ev %i (MemAllocCallstackNamed)\n", ev.hdr.idx );+ break;+ case QueueType::MemFreeCallstack:+ fprintf( f, "ev %i (MemFreeCallstack)\n", ev.hdr.idx );+ break;+ case QueueType::MemFreeCallstackNamed:+ fprintf( f, "ev %i (MemFreeCallstackNamed)\n", ev.hdr.idx );+ break;+ case QueueType::GpuZoneBegin:+ fprintf( f, "ev %i (GpuZoneBegin)\n", ev.hdr.idx );+ break;+ case QueueType::GpuZoneBeginCallstack:+ fprintf( f, "ev %i (GpuZoneBeginCallstack)\n", ev.hdr.idx );+ break;+ case QueueType::GpuZoneBeginAllocSrcLoc:+ fprintf( f, "ev %i (GpuZoneBeginAllocSrcLoc)\n", ev.hdr.idx );+ break;+ case QueueType::GpuZoneBeginAllocSrcLocCallstack:+ fprintf( f, "ev %i (GpuZoneBeginAllocSrcLocCallstack)\n", ev.hdr.idx );+ break;+ case QueueType::GpuZoneEnd:+ fprintf( f, "ev %i (GpuZoneEnd)\n", ev.hdr.idx );+ break;+ case QueueType::GpuZoneBeginSerial:+ fprintf( f, "ev %i (GpuZoneBeginSerial)\n", ev.hdr.idx );+ break;+ case QueueType::GpuZoneBeginCallstackSerial:+ fprintf( f, "ev %i (GpuZoneBeginCallstackSerial)\n", ev.hdr.idx );+ break;+ case QueueType::GpuZoneBeginAllocSrcLocSerial:+ fprintf( f, "ev %i (GpuZoneBeginAllocSrcLocSerial)\n", ev.hdr.idx );+ break;+ case QueueType::GpuZoneBeginAllocSrcLocCallstackSerial:+ fprintf( f, "ev %i (GpuZoneBeginAllocSrcLocCallstackSerial)\n", ev.hdr.idx );+ break;+ case QueueType::GpuZoneEndSerial:+ fprintf( f, "ev %i (GpuZoneEndSerial)\n", ev.hdr.idx );+ break;+ case QueueType::PlotDataInt:+ fprintf( f, "ev %i (PlotDataInt)\n", ev.hdr.idx );+ break;+ case QueueType::PlotDataFloat:+ fprintf( f, "ev %i (PlotDataFloat)\n", ev.hdr.idx );+ break;+ case QueueType::PlotDataDouble:+ fprintf( f, "ev %i (PlotDataDouble)\n", ev.hdr.idx );+ break;+ case QueueType::ContextSwitch:+ fprintf( f, "ev %i (ContextSwitch)\n", ev.hdr.idx );+ fprintf( f, "\ttime = %" PRIi64 "\n", ev.contextSwitch.time );+ fprintf( f, "\tthread = %" PRIu32 " -> %" PRIu32 "\n", ev.contextSwitch.oldThread, ev.contextSwitch.newThread );+ fprintf( f, "\tcpu = %" PRIu8 ", oldThreadWaitReason = %" PRIu8 ", oldThreadState = %" PRIu8 "\n", ev.contextSwitch.cpu, ev.contextSwitch.oldThreadWaitReason, ev.contextSwitch.oldThreadState);+ break;+ case QueueType::ThreadWakeup:+ fprintf( f, "ev %i (ThreadWakeup)\n", ev.hdr.idx );+ break;+ case QueueType::GpuTime:+ fprintf( f, "ev %i (GpuTime)\n", ev.hdr.idx );+ break;+ case QueueType::GpuContextName:+ fprintf( f, "ev %i (GpuContextName)\n", ev.hdr.idx );+ break;+ case QueueType::CallstackFrameSize:+ fprintf( f, "ev %i (CallstackFrameSize)\n", ev.hdr.idx );+ break;+ case QueueType::SymbolInformation:+ fprintf( f, "ev %i (SymbolInformation)\n", ev.hdr.idx );+ break;+ case QueueType::FiberEnter:+ fprintf( f, "ev %i (FiberEnter)\n", ev.hdr.idx );+ fprintf( f, "\ttime = %" PRIi64 "\n", ev.fiberEnter.time );+ fprintf( f, "\tfiber = %" PRIu64 "\n", ev.fiberEnter.fiber );+ fprintf( f, "\tthread = %" PRIu32 "\n", ev.fiberEnter.thread );+ break;+ case QueueType::FiberLeave:+ fprintf( f, "ev %i (FiberLeave)\n", ev.hdr.idx );+ fprintf( f, "\ttime = %" PRIi64 "\n", ev.fiberLeave.time );+ fprintf( f, "\tthread = %" PRIu32 "\n", ev.fiberLeave.thread );+ break;+ case QueueType::Terminate:+ fprintf( f, "ev %i (Terminate)\n", ev.hdr.idx );+ break;+ case QueueType::KeepAlive:+ fprintf( f, "ev %i (KeepAlive)\n", ev.hdr.idx );+ break;+ case QueueType::ThreadContext:+ fprintf( f, "ev %i (ThreadContext)\n", ev.hdr.idx );+ fprintf( f, "\tthread = %" PRIu32 "\n", ev.threadCtx.thread );+ break;+ case QueueType::GpuCalibration:+ fprintf( f, "ev %i (GpuCalibration)\n", ev.hdr.idx );+ break;+ case QueueType::GpuTimeSync:+ fprintf( f, "ev %i (GpuTimeSync)\n", ev.hdr.idx );+ break;+ case QueueType::Crash:+ fprintf( f, "ev %i (Crash)\n", ev.hdr.idx );+ break;+ case QueueType::CrashReport:+ fprintf( f, "ev %i (CrashReport)\n", ev.hdr.idx );+ break;+ case QueueType::ZoneValidation:+ fprintf( f, "ev %i (ZoneValidation)\n", ev.hdr.idx );+ fprintf( f, "\tid = %" PRIu32 "\n", ev.zoneValidation.id );+ break;+ case QueueType::ZoneColor:+ fprintf( f, "ev %i (ZoneColor)\n", ev.hdr.idx );+ break;+ case QueueType::ZoneValue:+ fprintf( f, "ev %i (ZoneValue)\n", ev.hdr.idx );+ break;+ case QueueType::FrameMarkMsg:+ fprintf( f, "ev %i (FrameMarkMsg)\n", ev.hdr.idx );+ break;+ case QueueType::FrameMarkMsgStart:+ fprintf( f, "ev %i (FrameMarkMsgStart)\n", ev.hdr.idx );+ break;+ case QueueType::FrameMarkMsgEnd:+ fprintf( f, "ev %i (FrameMarkMsgEnd)\n", ev.hdr.idx );+ break;+ case QueueType::SourceLocation:+ fprintf( f, "ev %i (SourceLocation)\n", ev.hdr.idx );+ break;+ case QueueType::LockAnnounce:+ fprintf( f, "ev %i (LockAnnounce)\n", ev.hdr.idx );+ break;+ case QueueType::LockTerminate:+ fprintf( f, "ev %i (LockTerminate)\n", ev.hdr.idx );+ break;+ case QueueType::LockMark:+ fprintf( f, "ev %i (LockMark)\n", ev.hdr.idx );+ break;+ case QueueType::MessageLiteral:+ fprintf( f, "ev %i (MessageLiteral)\n", ev.hdr.idx );+ break;+ case QueueType::MessageLiteralColor:+ fprintf( f, "ev %i (MessageLiteralColor)\n", ev.hdr.idx );+ break;+ case QueueType::MessageLiteralCallstack:+ fprintf( f, "ev %i (MessageLiteralCallstack)\n", ev.hdr.idx );+ break;+ case QueueType::MessageLiteralColorCallstack:+ fprintf( f, "ev %i (MessageLiteralColorCallstack)\n", ev.hdr.idx );+ break;+ case QueueType::GpuNewContext:+ fprintf( f, "ev %i (GpuNewContext)\n", ev.hdr.idx );+ break;+ case QueueType::CallstackFrame:+ fprintf( f, "ev %i (CallstackFrame)\n", ev.hdr.idx );+ break;+ case QueueType::SysTimeReport:+ fprintf( f, "ev %i (SysTimeReport)\n", ev.hdr.idx );+ fprintf( f, "\ttime = %" PRIi64 "\n", ev.sysTime.time );+ fprintf( f, "\tsysTime = %f\n", ev.sysTime.sysTime );+ break;+ case QueueType::TidToPid:+ fprintf( f, "ev %i (TidToPid)\n", ev.hdr.idx );+ break;+ case QueueType::HwSampleCpuCycle:+ fprintf( f, "ev %i (HwSampleCpuCycle)\n", ev.hdr.idx );+ break;+ case QueueType::HwSampleInstructionRetired:+ fprintf( f, "ev %i (HwSampleInstructionRetired)\n", ev.hdr.idx );+ break;+ case QueueType::HwSampleCacheReference:+ fprintf( f, "ev %i (HwSampleCacheReference)\n", ev.hdr.idx );+ break;+ case QueueType::HwSampleCacheMiss:+ fprintf( f, "ev %i (HwSampleCacheMiss)\n", ev.hdr.idx );+ break;+ case QueueType::HwSampleBranchRetired:+ fprintf( f, "ev %i (HwSampleBranchRetired)\n", ev.hdr.idx );+ break;+ case QueueType::HwSampleBranchMiss:+ fprintf( f, "ev %i (HwSampleBranchMiss)\n", ev.hdr.idx );+ break;+ case QueueType::PlotConfig:+ fprintf( f, "ev %i (PlotConfig)\n", ev.hdr.idx );+ break;+ case QueueType::ParamSetup:+ fprintf( f, "ev %i (ParamSetup)\n", ev.hdr.idx );+ break;+ case QueueType::AckServerQueryNoop:+ fprintf( f, "ev %i (AckServerQueryNoop)\n", ev.hdr.idx );+ break;+ case QueueType::AckSourceCodeNotAvailable:+ fprintf( f, "ev %i (AckSourceCodeNotAvailable)\n", ev.hdr.idx );+ break;+ case QueueType::AckSymbolCodeNotAvailable:+ fprintf( f, "ev %i (AckSymbolCodeNotAvailable)\n", ev.hdr.idx );+ break;+ case QueueType::CpuTopology:+ fprintf( f, "ev %i (CpuTopology)\n", ev.hdr.idx );+ fprintf( f, "\tpackage = %" PRIu32 "\n", ev.cpuTopology.package );+ fprintf( f, "\tcore = %" PRIu32 "\n", ev.cpuTopology.core );+ fprintf( f, "\tthread = %" PRIu32 "\n", ev.cpuTopology.thread );+ break;+ case QueueType::SingleStringData:+ fprintf( f, "ev %i (SingleStringData)\n", ev.hdr.idx );+ break;+ case QueueType::SecondStringData:+ fprintf( f, "ev %i (SecondStringData)\n", ev.hdr.idx );+ break;+ case QueueType::MemNamePayload:+ fprintf( f, "ev %i (MemNamePayload)\n", ev.hdr.idx );+ break;+ case QueueType::StringData:+ fprintf( f, "ev %i (StringData)\n", ev.hdr.idx );+ break;+ case QueueType::ThreadName:+ fprintf( f, "ev %i (ThreadName)\n", ev.hdr.idx );+ break;+ case QueueType::PlotName:+ fprintf( f, "ev %i (PlotName)\n", ev.hdr.idx );+ break;+ case QueueType::SourceLocationPayload:+ fprintf( f, "ev %i (SourceLocationPayload)\n", ev.hdr.idx );+ break;+ case QueueType::CallstackPayload:+ fprintf( f, "ev %i (CallstackPayload)\n", ev.hdr.idx );+ break;+ case QueueType::CallstackAllocPayload:+ fprintf( f, "ev %i (CallstackAllocPayload)\n", ev.hdr.idx );+ break;+ case QueueType::FrameName:+ fprintf( f, "ev %i (FrameName)\n", ev.hdr.idx );+ break;+ case QueueType::FrameImageData:+ fprintf( f, "ev %i (FrameImageData)\n", ev.hdr.idx );+ break;+ case QueueType::ExternalName:+ fprintf( f, "ev %i (ExternalName)\n", ev.hdr.idx );+ break;+ case QueueType::ExternalThreadName:+ fprintf( f, "ev %i (ExternalThreadName)\n", ev.hdr.idx );+ break;+ case QueueType::SymbolCode:+ fprintf( f, "ev %i (SymbolCode)\n", ev.hdr.idx );+ break;+ case QueueType::SourceCode:+ fprintf( f, "ev %i (SourceCode)\n", ev.hdr.idx );+ break;+ case QueueType::FiberName:+ fprintf( f, "ev %i (FiberName)\n", ev.hdr.idx );+ break;+ default:+ assert( false );+ break;+ }+ fflush( f );+}++}
+ cbits/tracy/profiler/src/profiler/TracyEventDebug.hpp view
@@ -0,0 +1,10 @@+#ifndef __TRACYEVENTDEBUG_HPP__+#define __TRACYEVENTDEBUG_HPP__++namespace tracy+{+struct QueueItem;+void EventDebug( const QueueItem& ev );+}++#endif
+ cbits/tracy/profiler/src/profiler/TracyFileselector.cpp view
@@ -0,0 +1,126 @@+#include "TracyFileselector.hpp"++#ifndef TRACY_NO_FILESELECTOR+# ifdef __EMSCRIPTEN__+# include <emscripten.h>+# else+# include <nfd.h>+# endif+#endif++namespace tracy::Fileselector+{++static bool s_hasFailed = false;++void Init()+{+#if !defined TRACY_NO_FILESELECTOR && !defined __EMSCRIPTEN__+ NFD_Init();+#endif+}++void Shutdown()+{+#if !defined TRACY_NO_FILESELECTOR && !defined __EMSCRIPTEN__+ NFD_Quit();+#endif+}++bool HasFailed()+{+ if( s_hasFailed )+ {+ s_hasFailed = false;+ return true;+ }+ else+ {+ return false;+ }+}++#ifdef __EMSCRIPTEN__+static std::function<void(const char*)> s_openFileCallback;++extern "C" int nativeOpenFile()+{+ s_openFileCallback( "upload.tracy" );+ return 0;+}+#endif++static bool OpenFileImpl( const char* ext, const char* desc, const std::function<void(const char*)>& callback )+{+#ifndef TRACY_NO_FILESELECTOR+# ifdef __EMSCRIPTEN__+ s_openFileCallback = callback;+ EM_ASM( {+ var input = document.createElement( 'input' );+ input.type = 'file';+ input.accept = UTF8ToString( $0 );+ input.onchange = (e) => {+ var file = e.target.files[0];+ var reader = new FileReader();+ reader.readAsArrayBuffer( file );+ reader.onload = () => {+ var buf = reader.result;+ var view = new Uint8Array( buf );+ FS.createDataFile( '/', 'upload.tracy', view, true, true );+ Module.ccall( 'nativeOpenFile', 'number', [], [] );+ FS.unlink( '/upload.tracy' );+ };+ };+ input.click();+ }, ext );+ return true;+# else+ nfdu8filteritem_t filter = { desc, ext };+ nfdu8char_t* fn;+ const auto res = NFD_OpenDialogU8( &fn, &filter, 1, nullptr );+ if( res == NFD_OKAY )+ {+ callback( (const char*)fn );+ NFD_FreePathU8( fn );+ return true;+ }+ else+ {+ return res != NFD_ERROR;+ }+# endif+#endif+ return false;+}++static bool SaveFileImpl( const char* ext, const char* desc, const std::function<void(const char*)>& callback )+{+#if !defined TRACY_NO_FILESELECTOR && !defined __EMSCRIPTEN__+ nfdu8filteritem_t filter = { desc, ext };+ nfdu8char_t* fn;+ const auto res = NFD_SaveDialogU8( &fn, &filter, 1, nullptr, nullptr );+ if( res == NFD_OKAY )+ {+ callback( (const char*)fn );+ NFD_FreePathU8( fn );+ return true;+ }+ else+ {+ return res != NFD_ERROR;+ }+#endif+ return false;+}++void OpenFile( const char* ext, const char* desc, const std::function<void(const char*)>& callback )+{+ if( !OpenFileImpl( ext, desc, callback ) ) s_hasFailed = true;+}++void SaveFile( const char* ext, const char* desc, const std::function<void(const char*)>& callback )+{+ if( !SaveFileImpl( ext, desc, callback ) ) s_hasFailed = true;+}++}
+ cbits/tracy/profiler/src/profiler/TracyFileselector.hpp view
@@ -0,0 +1,18 @@+#ifndef __TRACYFILESELECTOR_HPP__+#define __TRACYFILESELECTOR_HPP__++#include <functional>++namespace tracy::Fileselector+{++void Init();+void Shutdown();+bool HasFailed();++void OpenFile( const char* ext, const char* desc, const std::function<void(const char*)>& callback );+void SaveFile( const char* ext, const char* desc, const std::function<void(const char*)>& callback );++}++#endif
+ cbits/tracy/profiler/src/profiler/TracyFilesystem.cpp view
@@ -0,0 +1,19 @@+#include "TracyFilesystem.hpp"+#include "TracyView.hpp"++namespace tracy+{++bool SourceFileValid( const char* fn, uint64_t olderThan, const View& view, const Worker& worker )+{+ if( worker.GetSourceFileFromCache( fn ).data != nullptr ) return true;+ struct stat buf;+ if( stat( view.SourceSubstitution( fn ), &buf ) == 0 && ( buf.st_mode & S_IFREG ) != 0 )+ {+ if(!view.ValidateSourceAge()) return true;+ return (uint64_t)buf.st_mtime < olderThan;+ }+ return false;+}++}
+ cbits/tracy/profiler/src/profiler/TracyFilesystem.hpp view
@@ -0,0 +1,23 @@+#ifndef __TRACYFILESYSTEM_HPP__+#define __TRACYFILESYSTEM_HPP__++#include <stdint.h>+#include <sys/stat.h>++namespace tracy+{++class View;+class Worker;++static inline bool FileExists( const char* fn )+{+ struct stat buf;+ return stat( fn, &buf ) == 0 && ( buf.st_mode & S_IFREG ) != 0;+}++bool SourceFileValid( const char* fn, uint64_t olderThan, const View& view, const Worker& worker );++}++#endif
+ cbits/tracy/profiler/src/profiler/TracyImGui.cpp view
@@ -0,0 +1,130 @@+#include <assert.h>+#include <algorithm>++#include "TracyPrint.hpp"+#include "TracyImGui.hpp"++extern ImTextureID zigzagTex;++namespace tracy+{++bool s_wasActive = false;++bool WasActive()+{+ if( s_wasActive )+ {+ s_wasActive = false;+ return true;+ }+ return false;+}+++void DrawZigZag( ImDrawList* draw, const ImVec2& wpos, double start, double end, double h, uint32_t color )+{+ const auto v = ( end - start ) / ( h * 2 );+ draw->AddImage( zigzagTex, wpos + ImVec2( start, -h ), wpos + ImVec2( end, h ), ImVec2( 0, 0 ), ImVec2( v, 1 ), color );+}++void DrawStripedRect( ImDrawList* draw, const ImVec2& wpos, double x0, double y0, double x1, double y1, double sw, uint32_t color, bool fix_stripes_in_screen_space, bool inverted )+{+ assert( x1 >= x0 );+ assert( y1 >= y0 );+ assert( sw > 0 );++ const auto ww = ImGui::GetItemRectSize().x;+ if( x0 > ww || x1 < 0 ) return;++ if( x1 - x0 > ww )+ {+ x0 = std::max<double>( 0, x0 );+ x1 = std::min<double>( ww, x1 );+ }++ x0 += wpos.x;+ x1 += wpos.x;++ ImGui::PushClipRect( ImVec2( x0, y0 ), ImVec2( x1, y1 ), true );++ const auto rw = x1 - x0;+ const auto rh = y1 - y0;+ const auto cnt = int( ( rh + rw + sw*2 ) / ( sw*2 ) );+ auto v0 = ImVec2( x0, y0 - rw );++ if ( fix_stripes_in_screen_space )+ {+ const auto window_height = double( ImGui::GetWindowHeight() );+ const auto flipped_v0y = window_height - v0.y; //we transform into a y-is-up coordinate space to achieve upper-left to lower-right stripes. If we didn't, we would calculate values for lower-left to upper-right++ const auto manhattan_distance = x0 + flipped_v0y;+ const auto in_multiples_of_2_times_sw = int( manhattan_distance / ( sw*2 ) );++ const auto floored_manhatten_distance = double( in_multiples_of_2_times_sw*sw*2 ); //floor in terms of 2 * stripe width++ const auto corrected_flipped_v0y = ( floored_manhatten_distance - x0 ); //the corrected (floored) y respects the position of the stripes+ v0.y = window_height - corrected_flipped_v0y - double( inverted*sw ); //transform back into y-is-down imgui space+ }++ for( int i=0; i<cnt; i++ )+ {+ draw->PathLineTo( v0 + ImVec2( 0, i*sw*2 ) );+ draw->PathLineTo( v0 + ImVec2( rw, i*sw*2 + rw ) );+ draw->PathLineTo( v0 + ImVec2( rw, i*sw*2 + rw + sw ) );+ draw->PathLineTo( v0 + ImVec2( 0, i*sw*2 + sw ) );+ draw->PathFillConvex( color );+ }++ ImGui::PopClipRect();+}++void DrawHistogramMinMaxLabel( ImDrawList* draw, int64_t tmin, int64_t tmax, ImVec2 wpos, float w, float ty )+{+ const auto dpos = wpos + ImVec2( 0.5f, 0.5f );+ const auto ty15 = round( ty * 1.5f );+ const auto mintxt = TimeToString( tmin );+ const auto maxtxt = TimeToString( tmax );+ const auto maxsz = ImGui::CalcTextSize( maxtxt ).x;+ DrawLine( draw, dpos, dpos + ImVec2( 0, ty15 ), 0x66FFFFFF );+ DrawLine( draw, dpos + ImVec2( w-1, 0 ), dpos + ImVec2( w-1, ty15 ), 0x66FFFFFF );+ draw->AddText( wpos + ImVec2( 0, ty15 ), 0x66FFFFFF, mintxt );+ draw->AddText( wpos + ImVec2( w-1-maxsz, ty15 ), 0x66FFFFFF, maxtxt );++ char range[64];+ sprintf( range, ICON_FA_LEFT_LONG " %s " ICON_FA_RIGHT_LONG, TimeToString( tmax - tmin ) );++ const auto rsz = ImGui::CalcTextSize( range ).x;+ draw->AddText( wpos + ImVec2( round( (w-1-rsz) * 0.5 ), ty15 ), 0x66FFFFFF, range );+}++void PrintSource( const std::vector<Tokenizer::Line>& lines )+{+ for( auto& line: lines )+ {+ auto ptr = line.begin;+ auto it = line.tokens.begin();+ while( ptr < line.end )+ {+ if( it == line.tokens.end() )+ {+ ImGui::TextUnformatted( ptr, line.end );+ ImGui::SameLine( 0, 0 );+ break;+ }+ if( ptr < it->begin )+ {+ ImGui::TextUnformatted( ptr, it->begin );+ ImGui::SameLine( 0, 0 );+ }+ auto color = SyntaxColors[(int)it->color];+ TextColoredUnformatted( color, it->begin, it->end );+ ImGui::SameLine( 0, 0 );+ ptr = it->end;+ ++it;+ }+ ImGui::ItemSize( ImVec2( 0, 0 ), 0 );+ }+}++}
+ cbits/tracy/profiler/src/profiler/TracyImGui.hpp view
@@ -0,0 +1,278 @@+#ifndef __TRACYIMGUI_HPP__+#define __TRACYIMGUI_HPP__++#ifdef _MSC_VER+# pragma warning( disable: 4244 ) // conversion from don't care to whatever, possible loss of data+#endif++#include <math.h>+#include <stdint.h>+#include <vector>++#include "imgui.h"+#include "imgui_internal.h"++#include "../public/common/TracyForceInline.hpp"+#include "IconsFontAwesome6.h"+#include "TracySourceTokenizer.hpp"++#if !IMGUI_DEFINE_MATH_OPERATORS+static inline ImVec2 operator+( const ImVec2& l, const ImVec2& r ) { return ImVec2( l.x + r.x, l.y + r.y ); }+static inline ImVec2 operator-( const ImVec2& l, const ImVec2& r ) { return ImVec2( l.x - r.x, l.y - r.y ); }+#endif++namespace tracy+{++extern bool s_wasActive;+bool WasActive();+++void DrawZigZag( ImDrawList* draw, const ImVec2& wpos, double start, double end, double h, uint32_t color );+void DrawStripedRect( ImDrawList* draw, const ImVec2& wpos, double x0, double y0, double x1, double y1, double sw, uint32_t color, bool fix_stripes_in_screen_space, bool inverted );+void DrawHistogramMinMaxLabel( ImDrawList* draw, int64_t tmin, int64_t tmax, ImVec2 wpos, float w, float ty );+void PrintSource( const std::vector<Tokenizer::Line>& lines );+++static constexpr const uint32_t SyntaxColors[] = {+ 0xFFB2B2B2, // default+ 0xFF51AD72, // comment+ 0xFF1E5EB7, // preprocessor+ 0xFFFFA3A3, // string+ 0xFFFFD1A3, // char literal+ 0xFF87E8FF, // keyword+ 0xFFE899CE, // number+ 0xFFE5E5E5, // punctuation+ 0xFFBF75C6, // type+ 0xFFE2AF35, // special+};++static constexpr const uint32_t AsmOpTypeColors[] = {+ 0xFFE2AF35, // None+ 0xFF358FE2, // Jump+ 0xFF358FE2, // Branch+ 0xFF35E2AF, // Call+ 0xFF35E2AF, // Ret+ 0xFF22FFFF, // Privileged+};++static constexpr const uint32_t AsmSyntaxColors[] = {+ 0xFFFFD1A3, // label+ 0xFFE5E5E5, // default ('[', '+', '*', ',')+ 0xFF51AD72, // dword/xmmword 'ptr'+ 0xFFBF75C6, // register+ 0xFFE899CE, // literal+};+++[[maybe_unused]] static inline float GetScale()+{+ return ImGui::GetTextLineHeight() / 15.f;+}++[[maybe_unused]] static inline void ImageCentered( ImTextureID user_texture_id, const ImVec2& size )+{+ ImGui::SetCursorPosX( ( ImGui::GetWindowWidth() - size.x ) * 0.5f );+ ImGui::Image( user_texture_id, size );+}++[[maybe_unused]] static inline void TextCentered( const char* text )+{+ const auto tw = ImGui::CalcTextSize( text ).x;+ ImGui::SetCursorPosX( ( ImGui::GetWindowWidth() - tw ) * 0.5f );+ ImGui::TextUnformatted( text );+}++[[maybe_unused]] static inline bool ButtonCentered( const char* text )+{+ const auto tw = ImGui::CalcTextSize( text ).x + ImGui::GetStyle().FramePadding.x * 2;+ ImGui::SetCursorPosX( ( ImGui::GetWindowWidth() - tw ) * 0.5f );+ return ImGui::Button( text );+}++[[maybe_unused]] static inline void TextColoredUnformatted( uint32_t col, const char* text, const char* end = nullptr )+{+ ImGui::PushStyleColor( ImGuiCol_Text, col );+ ImGui::TextUnformatted( text, end );+ ImGui::PopStyleColor();+}++[[maybe_unused]] static inline void TextColoredUnformatted( const ImVec4& col, const char* text, const char* end = nullptr )+{+ ImGui::PushStyleColor( ImGuiCol_Text, col );+ ImGui::TextUnformatted( text, end );+ ImGui::PopStyleColor();+}++[[maybe_unused]] static inline void TextDisabledUnformatted( const char* begin, const char* end = nullptr )+{+ ImGui::PushStyleColor( ImGuiCol_Text, GImGui->Style.Colors[ImGuiCol_TextDisabled] );+ ImGui::TextUnformatted( begin, end );+ ImGui::PopStyleColor();+}++[[maybe_unused]] static inline void TextFocused( const char* label, const char* value )+{+ TextDisabledUnformatted( label );+ ImGui::SameLine();+ ImGui::TextUnformatted( value );+}++[[maybe_unused]] static inline void DrawWaitingDots( double time )+{+ s_wasActive = true;+ ImGui::TextUnformatted( "" );+ auto draw = ImGui::GetWindowDrawList();+ const auto wpos = ImGui::GetWindowPos();+ const auto ty = ImGui::GetTextLineHeight();+ const auto h = ImGui::GetCursorPosY() - ty * 0.5f;+ const auto w = ImGui::GetWindowWidth();+ draw->AddCircleFilled( wpos + ImVec2( w * 0.5f - ty, h ), ty * ( 0.15f + 0.2f * ( pow( cos( time * 3.5f + 0.3f ), 16.f ) ) ), 0xFFBBBBBB, 12 );+ draw->AddCircleFilled( wpos + ImVec2( w * 0.5f , h ), ty * ( 0.15f + 0.2f * ( pow( cos( time * 3.5f ), 16.f ) ) ), 0xFFBBBBBB, 12 );+ draw->AddCircleFilled( wpos + ImVec2( w * 0.5f + ty, h ), ty * ( 0.15f + 0.2f * ( pow( cos( time * 3.5f - 0.3f ), 16.f ) ) ), 0xFFBBBBBB, 12 );+}++[[maybe_unused]] static inline bool SmallCheckbox( const char* label, bool* var )+{+ ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 0, 0 ) );+ auto ret = ImGui::Checkbox( label, var );+ ImGui::PopStyleVar();+ return ret;+}++[[maybe_unused]] static inline void SmallColorBox( uint32_t color )+{+ ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 0, 0 ) );+ ImGui::ColorButton( "c1", ImVec4( (color & 0xFF) / 255.f, ((color>>8) & 0xFF ) / 255.f, ((color>>16) & 0xFF ) / 255.f, 1.f ), ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoDragDrop );+ ImGui::PopStyleVar();+}++[[maybe_unused]] static inline bool ButtonDisablable( const char* label, bool disabled )+{+ if( disabled )+ {+ ImGui::BeginDisabled();+ ImGui::Button( label );+ ImGui::EndDisabled();+ return false;+ }+ else+ {+ return ImGui::Button( label );+ }+}++[[maybe_unused]] static inline bool SmallButtonDisablable( const char* label, bool disabled )+{+ if( disabled )+ {+ ImGui::BeginDisabled();+ ImGui::SmallButton( label );+ ImGui::EndDisabled();+ return false;+ }+ else+ {+ return ImGui::SmallButton( label );+ }+}++[[maybe_unused]] static inline void DrawTextContrast( ImDrawList* draw, const ImVec2& pos, uint32_t color, const char* text )+{+ const auto scale = round( GetScale() );+ draw->AddText( pos + ImVec2( scale, scale ), 0xAA000000, text );+ draw->AddText( pos, color, text );+}++[[maybe_unused]] static inline void DrawTextSuperContrast( ImDrawList* draw, const ImVec2& pos, uint32_t color, const char* text )+{+ const auto scale = GetScale();+ const auto s1 = round( scale );+ const auto s2 = round( scale * 1.5f );+ draw->AddText( pos + ImVec2( 0, s2 ), 0xAA000000, text );+ draw->AddText( pos + ImVec2( 0, -s2 ), 0xAA000000, text );+ draw->AddText( pos + ImVec2( s2, 0 ), 0xAA000000, text );+ draw->AddText( pos + ImVec2( -s2, 0 ), 0xAA000000, text );+ draw->AddText( pos + ImVec2( s1, s1 ), 0xAA000000, text );+ draw->AddText( pos + ImVec2( -s1, s1 ), 0xAA000000, text );+ draw->AddText( pos + ImVec2( -s1, -s1 ), 0xAA000000, text );+ draw->AddText( pos + ImVec2( s1, -s1 ), 0xAA000000, text );+ draw->AddText( pos, color, text );+}++[[maybe_unused]] static void SetButtonHighlightColor()+{+ ImGui::PushStyleColor( ImGuiCol_Button, (ImVec4)ImColor::HSV( 0.35f, 0.6f, 0.6f ) );+ ImGui::PushStyleColor( ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV( 0.35f, 0.8f, 0.8f ) );+ ImGui::PushStyleColor( ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV( 0.35f, 0.7f, 0.7f ) );+}++[[maybe_unused]] static void ToggleButton( const char* label, bool& toggle )+{+ const auto active = toggle;+ if( active ) SetButtonHighlightColor();+ if( ImGui::Button( label ) ) toggle = !toggle;+ if( active ) ImGui::PopStyleColor( 3 );+}++[[maybe_unused]] static void SmallToggleButton( const char* label, bool& toggle )+{+ const auto active = toggle;+ if( active ) SetButtonHighlightColor();+ ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 0, 0 ) );+ if( ImGui::Button( label ) ) toggle = !toggle;+ ImGui::PopStyleVar( 1 );+ if( active ) ImGui::PopStyleColor( 3 );+}++[[maybe_unused]] static bool ClipboardButton( int id = 0 )+{+ ImGui::PushStyleColor( ImGuiCol_Border, ImVec4( 0.43f, 0.43f, 0.50f, 0.25f ) );+ ImGui::PushStyleColor( ImGuiCol_Button, ImVec4( 0.26f, 0.59f, 0.98f, 0.20f ) );+ ImGui::PushStyleColor( ImGuiCol_ButtonHovered, ImVec4( 0.26f, 0.59f, 0.98f, 0.5f ) );+ ImGui::PushStyleColor( ImGuiCol_ButtonActive, ImVec4( 0.06f, 0.53f, 0.98f, 0.5f ) );+ ImGui::PushStyleColor( ImGuiCol_Text, GImGui->Style.Colors[ImGuiCol_TextDisabled] );+ ImGui::PushID( id );+ const auto res = ImGui::SmallButton( ICON_FA_CLIPBOARD );+ ImGui::PopID();+ ImGui::PopStyleColor( 5 );+ return res;+}++[[maybe_unused]] static tracy_force_inline void DrawLine( ImDrawList* draw, const ImVec2& v1, const ImVec2& v2, uint32_t col, float thickness = 1.0f )+{+ const ImVec2 data[2] = { v1, v2 };+ draw->AddPolyline( data, 2, col, 0, thickness );+}++[[maybe_unused]] static tracy_force_inline void DrawLine( ImDrawList* draw, const ImVec2& v1, const ImVec2& v2, const ImVec2& v3, uint32_t col, float thickness = 1.0f )+{+ const ImVec2 data[3] = { v1, v2, v3 };+ draw->AddPolyline( data, 3, col, 0, thickness );+}++[[maybe_unused]] static tracy_force_inline void TooltipIfHovered( const char* text )+{+ if( !ImGui::IsItemHovered() ) return;+ ImGui::BeginTooltip();+ ImGui::TextUnformatted( text );+ ImGui::EndTooltip();+}++[[maybe_unused]] void tracy_force_inline DrawHelpMarker( const char* desc )+{+ TextDisabledUnformatted( "(?)" );+ if( ImGui::IsItemHovered() )+ {+ const auto ty = ImGui::GetTextLineHeight();+ ImGui::BeginTooltip();+ ImGui::PushTextWrapPos( 450.0f * ty / 15.f );+ ImGui::TextUnformatted( desc );+ ImGui::PopTextWrapPos();+ ImGui::EndTooltip();+ }+}++}++#endif
+ cbits/tracy/profiler/src/profiler/TracyLockHelpers.hpp view
@@ -0,0 +1,28 @@+#ifndef __TRACYLOCKHELPERS_HPP__+#define __TRACYLOCKHELPERS_HPP__++#include <stdint.h>++#include "../public/common/TracyForceInline.hpp"++namespace tracy+{++static tracy_force_inline uint64_t GetThreadBit( uint8_t thread )+{+ return uint64_t( 1 ) << thread;+}++static tracy_force_inline bool IsThreadWaiting( uint64_t bitlist, uint64_t threadBit )+{+ return ( bitlist & threadBit ) != 0;+}++static tracy_force_inline bool AreOtherWaiting( uint64_t bitlist, uint64_t threadBit )+{+ return ( bitlist & ~threadBit ) != 0;+}++}++#endif
+ cbits/tracy/profiler/src/profiler/TracyMicroArchitecture.cpp view
file too large to diff
+ cbits/tracy/profiler/src/profiler/TracyMicroArchitecture.hpp view
@@ -0,0 +1,46 @@+#include <stdint.h>++namespace tracy+{++struct AsmDesc+{+ uint8_t type;+ uint16_t width;+};++struct AsmVar+{+ int descNum;+ AsmDesc desc[5];+ int isaSet;+ float tp;+ int port, uops, minlat, maxlat;+ bool minbound, maxbound;+};++struct AsmOp+{+ int id;+ int descId;+ int numVariants;+ const AsmVar*const* variant;+};++struct MicroArchitecture+{+ int numOps;+ const AsmOp*const* ops;+};++extern const char* MicroArchitectureList[];+extern const char* PortList[];+extern const char* OpsList[];+extern const char* OpDescList[];+extern const char* IsaList[];+extern const MicroArchitecture* const MicroArchitectureData[];++extern int OpsNum;+extern int MicroArchitectureNum;++};
+ cbits/tracy/profiler/src/profiler/TracyMouse.cpp view
@@ -0,0 +1,90 @@+#include <cmath>++#include "TracyMouse.hpp"++#include "imgui_internal.h"++namespace tracy+{++static constexpr int MouseButtons = IM_ARRAYSIZE( ImGuiContext::IO.MouseDown );+static constexpr float MouseDragThreshold = 2;++struct Mouse+{+ bool mouseDown[MouseButtons];+ bool mouseClicked[MouseButtons];+ bool mouseReleased[MouseButtons];+ bool mouseDragging[MouseButtons];+ ImVec2 mouseDragDelta[MouseButtons];+ bool mousePotentialClickRelease[MouseButtons];+};++static Mouse s_mouse = {};++void MouseFrame()+{+ for( int i=0; i<MouseButtons; i++ )+ {+ s_mouse.mouseDown[i] = ImGui::IsMouseDown( i );+ s_mouse.mouseClicked[i] = ImGui::IsMouseClicked( i );+ s_mouse.mouseReleased[i] = ImGui::IsMouseReleased( i );+ s_mouse.mouseDragging[i] = ImGui::IsMouseDragging( i, 0 );+ s_mouse.mouseDragDelta[i] = ImGui::GetMouseDragDelta( i, 0 );++ if( s_mouse.mouseDragging[i] )+ {+ if( s_mouse.mouseClicked[i] || s_mouse.mousePotentialClickRelease[i] )+ {+ if( std::abs( s_mouse.mouseDragDelta[i].x ) < MouseDragThreshold && std::abs( s_mouse.mouseDragDelta[i].y ) < MouseDragThreshold )+ {+ s_mouse.mouseDragging[i] = false;+ }+ else+ {+ s_mouse.mousePotentialClickRelease[i] = false;+ }+ }+ }+ else if( !s_mouse.mouseDown[i] && !s_mouse.mouseReleased[i] )+ {+ s_mouse.mousePotentialClickRelease[i] = false;+ }+ }+}++bool IsMouseDown( ImGuiMouseButton button )+{+ return s_mouse.mouseDown[button];+}++bool IsMouseClicked( ImGuiMouseButton button )+{+ return s_mouse.mouseClicked[button];+}++bool IsMouseDragging( ImGuiMouseButton button )+{+ return s_mouse.mouseDragging[button];+}++ImVec2 GetMouseDragDelta( ImGuiMouseButton button )+{+ return s_mouse.mouseDragDelta[button];+}++void ConsumeMouseEvents( ImGuiMouseButton button )+{+ s_mouse.mouseDown[button] = false;+ s_mouse.mouseClicked[button] = false;+ s_mouse.mouseDragging[button] = false;+}++bool IsMouseClickReleased( ImGuiMouseButton button )+{+ if( s_mouse.mouseReleased[button] && s_mouse.mousePotentialClickRelease[button] ) return true;+ if( s_mouse.mouseClicked[button] ) s_mouse.mousePotentialClickRelease[button] = true;+ return false;+}++}
+ cbits/tracy/profiler/src/profiler/TracyMouse.hpp view
@@ -0,0 +1,21 @@+#ifndef __TRACYMOUSE_HPP__+#define __TRACYMOUSE_HPP__++#include "imgui.h"++namespace tracy+{++void MouseFrame();++bool IsMouseDown( ImGuiMouseButton button );+bool IsMouseClicked( ImGuiMouseButton button );+bool IsMouseDragging( ImGuiMouseButton button );+ImVec2 GetMouseDragDelta( ImGuiMouseButton button );++void ConsumeMouseEvents( ImGuiMouseButton button );+bool IsMouseClickReleased( ImGuiMouseButton button );++}++#endif
+ cbits/tracy/profiler/src/profiler/TracyProtoHistory.cpp view
@@ -0,0 +1,31 @@+#include "TracyFileHeader.hpp"+#include "TracyProtoHistory.hpp"++namespace tracy+{++constexpr ProtocolHistory_t ProtocolHistoryArr[] = {+ { 74, FileVersion( 0, 12, 0 ), FileVersion( 0, 12, 2 ) },+ { 69, FileVersion( 0, 11, 1 ) },+ { 66, FileVersion( 0, 11, 0 ) },+ { 64, FileVersion( 0, 10, 0 ) },+ { 63, FileVersion( 0, 9, 0 ), FileVersion( 0, 9, 1 ) },+ { 57, FileVersion( 0, 8, 2 ) },+ { 56, FileVersion( 0, 8, 1 ) },+ { 55, FileVersion( 0, 8, 0 ) },+ { 46, FileVersion( 0, 7, 6 ), FileVersion( 0, 7, 8 ) },+ { 44, FileVersion( 0, 7, 5 ) },+ { 42, FileVersion( 0, 7, 3 ), FileVersion( 0, 7, 4 ) },+ { 40, FileVersion( 0, 7, 1 ), FileVersion( 0, 7, 2 ) },+ { 35, FileVersion( 0, 7, 0 ) },+ { 25, FileVersion( 0, 6, 2 ), FileVersion( 0, 6, 3 ) },+ { 24, FileVersion( 0, 6, 1 ) },+ { 23, FileVersion( 0, 6, 0 ) },+ { 14, FileVersion( 0, 5, 0 ) },+ { 1, FileVersion( 0, 4, 1 ) },+ {}+};++const ProtocolHistory_t* ProtocolHistory = ProtocolHistoryArr;++}
+ cbits/tracy/profiler/src/profiler/TracyProtoHistory.hpp view
@@ -0,0 +1,20 @@+#ifndef __TRACYPROTOHISTORY_HPP__+#define __TRACYPROTOHISTORY_HPP__++#include <stdint.h>++namespace tracy+{++struct ProtocolHistory_t+{+ uint32_t protocol;+ uint32_t minVer;+ uint32_t maxVer;+};++extern const ProtocolHistory_t* ProtocolHistory;++}++#endif
+ cbits/tracy/profiler/src/profiler/TracySourceContents.cpp view
@@ -0,0 +1,106 @@+#include "TracySourceContents.hpp"+#include "TracyView.hpp"+#include "TracyWorker.hpp"++namespace tracy+{++SourceContents::SourceContents()+ : m_file( nullptr )+ , m_fileStringIdx( 0 )+ , m_data( nullptr )+ , m_dataSize( 0 )+ , m_dataBuf( nullptr )+ , m_dataBufSize( 0 )+{+}++SourceContents::~SourceContents()+{+ delete[] m_dataBuf;+}++void SourceContents::Parse( const char* fileName, const Worker& worker, const View& view )+{+ if( m_file == fileName ) return;++ m_file = fileName;+ m_fileStringIdx = worker.FindStringIdx( fileName );+ m_lines.clear();+ if( fileName )+ {+ uint32_t sz;+ const auto srcCache = worker.GetSourceFileFromCache( fileName );+ if( srcCache.data != nullptr )+ {+ m_data = srcCache.data;+ m_dataSize = srcCache.len;+ sz = srcCache.len;+ }+ else+ {+ FILE* f = fopen( view.SourceSubstitution( fileName ), "rb" );+ if( f )+ {+ fseek( f, 0, SEEK_END );+ sz = ftell( f );+ fseek( f, 0, SEEK_SET );+ if( sz > m_dataBufSize )+ {+ delete[] m_dataBuf;+ m_dataBuf = new char[sz];+ m_dataBufSize = sz;+ }+ fread( m_dataBuf, 1, sz, f );+ m_data = m_dataBuf;+ m_dataSize = sz;+ fclose( f );+ }+ else+ {+ m_file = nullptr;+ }+ }++ if( m_file ) Tokenize( m_data, sz );+ }+}++void SourceContents::Parse( const char* source )+{+ if( source == m_data ) return;++ const size_t len = strlen( source );++ m_file = nullptr;+ m_fileStringIdx = 0;+ m_data = source;+ m_dataSize = len;+ Tokenize( source, len );+}++void SourceContents::Tokenize( const char* txt, size_t sz )+{+ Tokenizer tokenizer;+ for(;;)+ {+ auto end = txt;+ while( *end != '\n' && *end != '\r' && end - m_data < sz ) end++;+ m_lines.emplace_back( Tokenizer::Line { txt, end, tokenizer.Tokenize( txt, end ) } );+ if( end - m_data == sz ) break;+ if( *end == '\n' )+ {+ end++;+ if( end - m_data < sz && *end == '\r' ) end++;+ }+ else if( *end == '\r' )+ {+ end++;+ if( end - m_data < sz && *end == '\n' ) end++;+ }+ if( end - m_data == sz ) break;+ txt = end;+ }+}++}
+ cbits/tracy/profiler/src/profiler/TracySourceContents.hpp view
@@ -0,0 +1,51 @@+#ifndef __TRACYSOURCECONTENTS_HPP__+#define __TRACYSOURCECONTENTS_HPP__++#include <stdint.h>+#include <stddef.h>+#include <vector>++#include "TracySourceTokenizer.hpp"++namespace tracy+{++class View;+class Worker;++class SourceContents+{+public:+ SourceContents();+ ~SourceContents();++ void Parse( const char* fileName, const Worker& worker, const View& view );+ void Parse( const char* source );++ const std::vector<Tokenizer::Line>& get() const { return m_lines; }+ bool empty() const { return m_lines.empty(); }++ const char* filename() const { return m_file; }+ uint32_t idx() const { return m_fileStringIdx; }+ bool is_cached() const { return m_data != m_dataBuf; }+ const char* data() const { return m_data; }+ size_t data_size() const { return m_dataSize; }++private:+ void Tokenize( const char* txt, size_t sz );++ const char* m_file;+ uint32_t m_fileStringIdx;++ const char* m_data;+ size_t m_dataSize;++ char* m_dataBuf;+ size_t m_dataBufSize;++ std::vector<Tokenizer::Line> m_lines;+};++}++#endif
+ cbits/tracy/profiler/src/profiler/TracySourceTokenizer.cpp view
@@ -0,0 +1,421 @@+#include "tracy_robin_hood.h"+#include "TracyCharUtil.hpp"+#include "TracySourceTokenizer.hpp"++namespace tracy+{++namespace {+static unordered_flat_set<const char*, charutil::Hasher, charutil::Comparator> GetKeywords()+{+ unordered_flat_set<const char*, charutil::Hasher, charutil::Comparator> ret;+ for( auto& v : {+ "alignas", "alignof", "and", "and_eq", "asm", "atomic_cancel", "atomic_commit", "atomic_noexcept",+ "bitand", "bitor", "break", "case", "catch", "class", "compl", "concept", "const", "consteval",+ "constexpr", "constinit", "const_cast", "continue", "co_await", "co_return", "co_yield", "decltype",+ "default", "delete", "do", "dynamic_cast", "else", "enum", "explicit", "export", "extern", "for",+ "friend", "if", "inline", "mutable", "namespace", "new", "noexcept", "not", "not_eq", "operator",+ "or", "or_eq", "private", "protected", "public", "reflexpr", "register", "reinterpret_cast",+ "return", "requires", "sizeof", "static", "static_assert", "static_cast", "struct", "switch",+ "synchronized", "template", "thread_local", "throw", "try", "typedef", "typeid", "typename",+ "union", "using", "virtual", "volatile", "while", "xor", "xor_eq", "override", "final", "import",+ "module", "transaction_safe", "transaction_safe_dynamic" } )+ {+ ret.insert( v );+ }+ return ret;+}+static unordered_flat_set<const char*, charutil::Hasher, charutil::Comparator> GetTypes()+{+ unordered_flat_set<const char*, charutil::Hasher, charutil::Comparator> ret;+ for( auto& v : {+ "bool", "char", "char8_t", "char16_t", "char32_t", "double", "float", "int", "long", "short", "signed",+ "unsigned", "void", "wchar_t", "size_t", "int8_t", "int16_t", "int32_t", "int64_t", "int_fast8_t",+ "int_fast16_t", "int_fast32_t", "int_fast64_t", "int_least8_t", "int_least16_t", "int_least32_t",+ "int_least64_t", "intmax_t", "intptr_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", "uint_fast8_t",+ "uint_fast16_t", "uint_fast32_t", "uint_fast64_t", "uint_least8_t", "uint_least16_t", "uint_least32_t",+ "uint_least64_t", "uintmax_t", "uintptr_t", "type_info", "bad_typeid", "bad_cast", "type_index",+ "clock_t", "time_t", "tm", "timespec", "ptrdiff_t", "nullptr_t", "max_align_t", "auto",++ "__m64", "__m128", "__m128i", "__m128d", "__m256", "__m256i", "__m256d", "__m512", "__m512i",+ "__m512d", "__mmask8", "__mmask16", "__mmask32", "__mmask64",++ "int8x8_t", "int16x4_t", "int32x2_t", "int64x1_t", "uint8x8_t", "uint16x4_t", "uint32x2_t",+ "uint64x1_t", "float32x2_t", "poly8x8_t", "poly16x4_t", "int8x16_t", "int16x8_t", "int32x4_t",+ "int64x2_t", "uint8x16_t", "uint16x8_t", "uint32x4_t", "uint64x2_t", "float32x4_t", "poly8x16_t",+ "poly16x8_t",++ "int8x8x2_t", "int16x4x2_t", "int32x2x2_t", "int64x1x2_t", "uint8x8x2_t", "uint16x4x2_t",+ "uint32x2x2_t", "uint64x1x2_t", "float32x2x2_t", "poly8x8x2_t", "poly16x4x2_t", "int8x16x2_t",+ "int16x8x2_t", "int32x4x2_t", "int64x2x2_t", "uint8x16x2_t", "uint16x8x2_t", "uint32x4x2_t",+ "uint64x2x2_t", "float32x4x2_t", "poly8x16x2_t", "poly16x8x2_t",++ "int8x8x3_t", "int16x4x3_t", "int32x2x3_t", "int64x1x3_t", "uint8x8x3_t", "uint16x4x3_t",+ "uint32x2x3_t", "uint64x1x3_t", "float32x2x3_t", "poly8x8x3_t", "poly16x4x3_t", "int8x16x3_t",+ "int16x8x3_t", "int32x4x3_t", "int64x2x3_t", "uint8x16x3_t", "uint16x8x3_t", "uint32x4x3_t",+ "uint64x2x3_t", "float32x4x3_t", "poly8x16x3_t", "poly16x8x3_t",++ "int8x8x4_t", "int16x4x4_t", "int32x2x4_t", "int64x1x4_t", "uint8x8x4_t", "uint16x4x4_t",+ "uint32x2x4_t", "uint64x1x4_t", "float32x2x4_t", "poly8x8x4_t", "poly16x4x4_t", "int8x16x4_t",+ "int16x8x4_t", "int32x4x4_t", "int64x2x4_t", "uint8x16x4_t", "uint16x8x4_t", "uint32x4x4_t",+ "uint64x2x4_t", "float32x4x4_t", "poly8x16x4_t", "poly16x8x4_t" } )+ {+ ret.insert( v );+ }+ return ret;+}+static unordered_flat_set<const char*, charutil::Hasher, charutil::Comparator> GetSpecial()+{+ unordered_flat_set<const char*, charutil::Hasher, charutil::Comparator> ret;+ for( auto& v : { "this", "nullptr", "true", "false", "goto", "NULL" } )+ {+ ret.insert( v );+ }+ return ret;+}+static unordered_flat_set<const char*, charutil::Hasher, charutil::Comparator> GetAsmRegs()+{+ unordered_flat_set<const char*, charutil::Hasher, charutil::Comparator> ret;+ for( auto& v : {+ // x64+ "ah", "al", "ax", "bh", "bl", "bp", "bpl", "bx", "ch", "cl", "cs", "cx", "dh", "di", "dil", "dl", "ds", "dx",+ "eax", "ebp", "ebx", "ecx", "edi", "edx", "flags", "eip", "eiz", "es", "esi", "esp", "fpsw", "fs", "gs", "ip",+ "rax", "rbp", "rbx", "rcx", "rdi", "rdx", "rip", "riz", "rsi", "rsp", "si", "sil", "sp", "spl", "ss", "cr0",+ "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", "cr8", "cr9", "cr10", "cr11", "cr12", "cr13", "cr14", "cr15",+ "dr0", "dr1", "dr2", "dr3", "dr4", "dr5", "dr6", "dr7", "dr8", "dr9", "dr10", "dr11", "dr12", "dr13", "dr14",+ "dr15", "fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7", "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7",+ "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",+ "st(0)", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4",+ "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "xmm16", "xmm17",+ "xmm18", "xmm19", "xmm20", "xmm21", "xmm22", "xmm23", "xmm24", "xmm25", "xmm26", "xmm27", "xmm28", "xmm29",+ "xmm30", "xmm31", "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", "ymm8", "ymm9", "ymm10",+ "ymm11", "ymm12", "ymm13", "ymm14", "ymm15", "ymm16", "ymm17", "ymm18", "ymm19", "ymm20", "ymm21", "ymm22",+ "ymm23", "ymm24", "ymm25", "ymm26", "ymm27", "ymm28", "ymm29", "ymm30", "ymm31", "zmm0", "zmm1", "zmm2",+ "zmm3", "zmm4", "zmm5", "zmm6", "zmm7", "zmm8", "zmm9", "zmm10", "zmm11", "zmm12", "zmm13", "zmm14", "zmm15",+ "zmm16", "zmm17", "zmm18", "zmm19", "zmm20", "zmm21", "zmm22", "zmm23", "zmm24", "zmm25", "zmm26", "zmm27",+ "zmm28", "zmm29", "zmm30", "zmm31", "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b", "r8d", "r9d",+ "r10d", "r11d", "r12d", "r13d", "r14d", "r15d", "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w",+ // ARM+ "apsr", "apsr_nzcv", "cpsr", "fpexc", "fpinst", "fpscr", "fpscr_nzcv", "fpsid", "itstate", "lr", "pc", "sp",+ "spsr", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15",+ "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",+ "fpinst2", "mvfr0", "mvfr1", "mvfr2", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11",+ "q12", "q13", "q14", "q15", "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12",+ "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15", "s16",+ "s17", "s18", "s19", "s20", "s21", "s22", "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31", "w0",+ "w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10", "w11", "w12", "w13", "w14", "w15", "w16", "w17",+ "w18", "w19", "w20", "w21", "w22", "w23", "w24", "w25", "w26", "w27", "w28", "w29", "w30", "x0", "x1", "x2",+ "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19",+ "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28", "x29", "x30", "v0", "v1", "v2", "v3", "v4",+ "v5", "v6", "v7", "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20",+ "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "xzr", "wzr", "b0", "b1", "b2", "b3",+ "b4", "b5", "b6", "b7", "b8", "b9", "b10", "b11", "b12", "b13", "b14", "b15", "b16", "b17", "b18", "b19",+ "b20", "b21", "b22", "b23", "b24", "b25", "b26", "b27", "b28", "b29", "b30", "h0", "h1", "h2", "h3", "h4",+ "h5", "h6", "h7", "h8", "h9", "h10", "h11", "h12", "h13", "h14", "h15", "h16", "h17", "h18", "h19", "h20",+ "h21", "h22", "h23", "h24", "h25", "h26", "h27", "h28", "h29", "h30" } )+ {+ ret.insert( v );+ }+ return ret;+}+static unordered_flat_set<const char*, charutil::Hasher, charutil::Comparator> GetAsmSizeDirectives()+{+ unordered_flat_set<const char*, charutil::Hasher, charutil::Comparator> ret;+ for( auto& v : { "byte", "word", "dword", "qword", "xmmword", "ymmword", "zmmword" } )+ {+ ret.insert( v );+ }+ return ret;+}+}++Tokenizer::Tokenizer()+ : m_isInComment( false )+ , m_isInPreprocessor( false )+{+}++std::vector<Tokenizer::Token> Tokenizer::Tokenize( const char* begin, const char* end )+{+ std::vector<Token> ret;+ if( m_isInPreprocessor )+ {+ if( begin == end )+ {+ m_isInPreprocessor = false;+ return ret;+ }+ if( *(end-1) != '\\' ) m_isInPreprocessor = false;+ ret.emplace_back( Token { begin, end, TokenColor::Preprocessor } );+ return ret;+ }+ const bool first = !m_isInComment;+ while( begin != end )+ {+ if( m_isInComment )+ {+ const auto pos = begin;+ for(;;)+ {+ while( begin != end && *begin != '*' ) begin++;+ begin++;+ if( begin < end )+ {+ if( *begin == '/' )+ {+ begin++;+ ret.emplace_back( Token { pos, begin, TokenColor::Comment } );+ m_isInComment = false;+ break;+ }+ }+ else+ {+ ret.emplace_back( Token { pos, end, TokenColor::Comment } );+ return ret;+ }+ }+ }+ else+ {+ while( begin != end && isspace( (uint8_t)*begin ) ) begin++;+ if( first && begin < end && *begin == '#' )+ {+ if( *(end-1) == '\\' ) m_isInPreprocessor = true;+ ret.emplace_back( Token { begin, end, TokenColor::Preprocessor } );+ return ret;+ }+ const auto pos = begin;+ const auto col = IdentifyToken( begin, end );+ ret.emplace_back( Token { pos, begin, col } );+ }+ }+ return ret;+}++static bool TokenizeNumber( const char*& begin, const char* end )+{+ const bool startNum = *begin >= '0' && *begin <= '9';+ if( *begin != '+' && *begin != '-' && !startNum ) return false;+ begin++;+ bool hasNum = startNum;+ while( begin < end && ( ( *begin >= '0' && *begin <= '9' ) || *begin == '\'' ) )+ {+ hasNum = true;+ begin++;+ }+ if( !hasNum ) return false;+ bool isFloat = false, isBinary = false;+ if( begin < end )+ {+ if( *begin == '.' )+ {+ isFloat = true;+ begin++;+ while( begin < end && ( ( *begin >= '0' && *begin <= '9' ) || *begin == '\'' ) ) begin++;+ }+ else if( *begin == 'x' || *begin == 'X' )+ {+ // hexadecimal+ begin++;+ while( begin < end && ( ( *begin >= '0' && *begin <= '9' ) || ( *begin >= 'a' && *begin <= 'f' ) || ( *begin >= 'A' && *begin <= 'F' ) || *begin == '\'' ) ) begin++;+ }+ else if( *begin == 'b' || *begin == 'B' )+ {+ isBinary = true;+ begin++;+ while( begin < end && ( ( *begin == '0' || *begin == '1' ) || *begin == '\'' ) ) begin++;+ }+ }+ if( !isBinary )+ {+ if( begin < end && ( *begin == 'e' || *begin == 'E' || *begin == 'p' || *begin == 'P' ) )+ {+ isFloat = true;+ begin++;+ if( begin < end && ( *begin == '+' || *begin == '-' ) ) begin++;+ bool hasDigits = false;+ while( begin < end && ( ( *begin >= '0' && *begin <= '9' ) || ( *begin >= 'a' && *begin <= 'f' ) || ( *begin >= 'A' && *begin <= 'F' ) || *begin == '\'' ) )+ {+ hasDigits = true;+ begin++;+ }+ if( !hasDigits ) return false;+ }+ if( begin < end && ( *begin == 'f' || *begin == 'F' || *begin == 'l' || *begin == 'L' ) ) begin++;+ }+ if( !isFloat )+ {+ while( begin < end && ( *begin == 'u' || *begin == 'U' || *begin == 'l' || *begin == 'L' ) ) begin++;+ }+ return true;+}++Tokenizer::TokenColor Tokenizer::IdentifyToken( const char*& begin, const char* end )+{+ static const auto s_keywords = GetKeywords();+ static const auto s_types = GetTypes();+ static const auto s_special = GetSpecial();++ if( *begin == '"' )+ {+ begin++;+ while( begin < end )+ {+ if( *begin == '"' )+ {+ begin++;+ break;+ }+ begin += 1 + ( *begin == '\\' && end - begin > 1 && *(begin+1) == '"' );+ }+ return TokenColor::String;+ }+ if( *begin == '\'' )+ {+ begin++;+ if( begin < end && *begin == '\\' ) begin++;+ if( begin < end ) begin++;+ if( begin < end && *begin == '\'' ) begin++;+ return TokenColor::CharacterLiteral;+ }+ if( ( *begin >= 'a' && *begin <= 'z' ) || ( *begin >= 'A' && *begin <= 'Z' ) || *begin == '_' )+ {+ const char* tmp = begin;+ begin++;+ while( begin < end && ( ( *begin >= 'a' && *begin <= 'z' ) || ( *begin >= 'A' && *begin <= 'Z' ) || ( *begin >= '0' && *begin <= '9' ) || *begin == '_' ) ) begin++;+ if( begin - tmp <= 24 )+ {+ char buf[25];+ memcpy( buf, tmp, begin-tmp );+ buf[begin-tmp] = '\0';+ if( s_keywords.find( buf ) != s_keywords.end() ) return TokenColor::Keyword;+ if( s_types.find( buf ) != s_types.end() ) return TokenColor::Type;+ if( s_special.find( buf ) != s_special.end() ) return TokenColor::Special;+ }+ return TokenColor::Default;+ }+ const char* tmp = begin;+ if( TokenizeNumber( begin, end ) ) return TokenColor::Number;+ begin = tmp;+ if( *begin == '/' && end - begin > 1 )+ {+ if( *(begin+1) == '/' )+ {+ begin = end;+ return TokenColor::Comment;+ }+ if( *(begin+1) == '*' )+ {+ begin += 2;+ for(;;)+ {+ while( begin < end && *begin != '*' ) begin++;+ if( begin == end )+ {+ m_isInComment = true;+ return TokenColor::Comment;+ }+ begin++;+ if( begin < end && *begin == '/' )+ {+ begin++;+ return TokenColor::Comment;+ }+ }+ }+ }+ while( begin < end )+ {+ switch( *begin )+ {+ case '[':+ case ']':+ case '{':+ case '}':+ case '!':+ case '%':+ case '^':+ case '&':+ case '*':+ case '(':+ case ')':+ case '-':+ case '+':+ case '=':+ case '~':+ case '|':+ case '<':+ case '>':+ case '?':+ case ':':+ case '/':+ case ';':+ case ',':+ case '.':+ begin++;+ break;+ default:+ goto out;+ }+ }+out:+ if( begin != tmp ) return TokenColor::Punctuation;+ begin = end;+ return TokenColor::Default;+}++std::vector<Tokenizer::AsmToken> Tokenizer::TokenizeAsm( const char* begin, const char* end )+{+ std::vector<AsmToken> ret;+ while( begin != end )+ {+ while( begin != end && isspace( (uint8_t)*begin ) ) begin++;+ const auto pos = begin;+ const auto col = IdentifyAsmToken( begin, end );+ ret.emplace_back( AsmToken { pos, begin, col } );+ }+ return ret;+}++Tokenizer::AsmTokenColor Tokenizer::IdentifyAsmToken( const char*& begin, const char* end )+{+ static const auto s_regs = GetAsmRegs();+ static const auto s_sizes = GetAsmSizeDirectives();++ while( begin < end && *begin == ' ' ) begin++;+ if( ( *begin >= 'a' && *begin <= 'z' ) || ( *begin >= 'A' && *begin <= 'Z' ) )+ {+ const char* tmp = begin;+ begin++;+ while( begin < end && ( ( *begin >= 'a' && *begin <= 'z' ) || ( *begin >= 'A' && *begin <= 'Z' ) || ( *begin >= '0' && *begin <= '9' ) || *begin == '_' ) ) begin++;+ if( begin - tmp <= 10 )+ {+ char buf[11];+ memcpy( buf, tmp, begin-tmp );+ buf[begin-tmp] = '\0';+ if( s_regs.find( buf ) != s_regs.end() ) return AsmTokenColor::Register;+ if( s_sizes.find( buf ) != s_sizes.end() )+ {+ if( end - begin >= 4 && memcmp( begin, " ptr", 4 ) == 0 )+ {+ begin += 4;+ return AsmTokenColor::SizeDirective;+ }+ }+ }+ return AsmTokenColor::Default;+ }+ else if( *begin >= '0' && *begin <= '9' )+ {+ while( begin < end && ( ( *begin >= 'a' && *begin <= 'z' ) || ( *begin >= 'A' && *begin <= 'Z' ) || ( *begin >= '0' && *begin <= '9' ) || *begin == '_' ) ) begin++;+ return AsmTokenColor::Literal;+ }+ else+ {+ while( begin < end && !( ( *begin >= 'a' && *begin <= 'z' ) || ( *begin >= 'A' && *begin <= 'Z' ) || ( *begin >= '0' && *begin <= '9' ) || *begin == '_' ) ) begin++;+ return AsmTokenColor::Default;+ }+}++}
+ cbits/tracy/profiler/src/profiler/TracySourceTokenizer.hpp view
@@ -0,0 +1,72 @@+#ifndef __TRACYSOURCETOKENIZER_HPP__+#define __TRACYSOURCETOKENIZER_HPP__++#include <stdint.h>+#include <vector>++namespace tracy+{++class Tokenizer+{+public:+ enum class TokenColor : uint8_t+ {+ Default,+ Comment,+ Preprocessor,+ String,+ CharacterLiteral,+ Keyword,+ Number,+ Punctuation,+ Type,+ Special+ };++ struct Token+ {+ const char* begin;+ const char* end;+ TokenColor color;+ };++ struct Line+ {+ const char* begin;+ const char* end;+ std::vector<Token> tokens;+ };++ enum class AsmTokenColor : uint8_t+ {+ Label, // no-op, padding+ Default, // '+', '[', '*', etc+ SizeDirective, // byte, word, dword, etc+ Register, // rax, rip, etc+ Literal, // 0x04, etc+ };++ struct AsmToken+ {+ const char* begin;+ const char* end;+ AsmTokenColor color;+ };++ Tokenizer();++ std::vector<Token> Tokenize( const char* begin, const char* end );+ std::vector<AsmToken> TokenizeAsm( const char* begin, const char* end );++private:+ TokenColor IdentifyToken( const char*& begin, const char* end );+ AsmTokenColor IdentifyAsmToken( const char*& begin, const char* end );++ bool m_isInComment;+ bool m_isInPreprocessor;+};++}++#endif
+ cbits/tracy/profiler/src/profiler/TracySourceView.cpp view
@@ -0,0 +1,5753 @@+#include <ctype.h>+#include <inttypes.h>+#include <sstream>+#include <stdio.h>++#include <capstone.h>++#include "imgui.h"+#include "TracyCharUtil.hpp"+#include "TracyColor.hpp"+#include "TracyFileselector.hpp"+#include "TracyFilesystem.hpp"+#include "TracyImGui.hpp"+#include "TracyMicroArchitecture.hpp"+#include "TracyPrint.hpp"+#include "TracySourceView.hpp"+#include "TracyUtility.hpp"+#include "TracyView.hpp"+#include "TracyWorker.hpp"+#include "tracy_pdqsort.h"++#include "IconsFontAwesome6.h"++namespace tracy+{++struct MicroArchUx+{+ const char* uArch;+ const char* cpuName;+ const char* moniker;+};++static constexpr MicroArchUx s_uArchUx[] = {+ { "AMD Zen 4", "Ryzen 5 7600X", "ZEN4" },+ { "AMD Zen 3", "Ryzen 5 5600X", "ZEN3" },+ { "AMD Zen 2", "Ryzen 7 3700X", "ZEN2" },+ { "AMD Zen+", "Ryzen 5 2600", "ZEN+" },+ { "Alder Lake P", "Core i5-12600K", "ADL-P" },+ { "Alder Lake E", "Core i5-12600K", "ADL-E" },+ { "Rocket Lake", "Core i9-11900", "RKL" },+ { "Tiger Lake", "Core i7-1165G7", "TGL" },+ { "Ice Lake", "Core i5-1035G1", "ICL" },+ { "Cascade Lake", "Core i9-10980XE", "CLX" },+ { "Cannon Lake", "Core i3-8121U", "CNL" },+ { "Coffee Lake", "Core i7-8700K", "CFL" },+ { "Kaby Lake", "Core i7-7700", "KBL" },+ { "Skylake-X", "Core i9-7900X", "SKX" },+ { "Skylake", "Core i7-6500U", "SKL" },+ { "Broadwell", "Core i5-5200U", "BDW" },+ { "Haswell", "Xeon E3-1225 v3", "HSW" },+ { "Ivy Bridge", "Core i5-3470", "IVB" },+ { "Sandy Bridge", "Core i7-2600", "SNB" },+ { "Westmere", "Core i5-650", "WSM" },+ { "Nehalem", "Core i5-750", "NHM" },+ { "Wolfdale", "Core 2 Duo E8400", "WOL" },+ { "Conroe", "Core 2 Duo E6750", "CON" },+ { "Bonnell", "Atom D525", "BNL" },+ { "Airmont", "Celeron N3000", "AMT" },+ { "Goldmont", "Celeron J3455", "GLM" },+ { "Goldmont Plus", "Celeron J4125", "GLP" },+ { "Tremont", "Pentium Silver N6005", "TRM" },+};++static constexpr const char* s_regNameX86[] = {+ "invalid", "rflags",+ "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "rsp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",+ "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7",+ "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9",+ "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "xmm16", "xmm17", "xmm18", "xmm19",+ "xmm20", "xmm21", "xmm22", "xmm23", "xmm24", "xmm25", "xmm26", "xmm27", "xmm28", "xmm29",+ "xmm30", "xmm31", "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7"+};+static_assert( sizeof( s_regNameX86 ) / sizeof( *s_regNameX86 ) == (size_t)SourceView::RegsX86::NUMBER_OF_ENTRIES, "Invalid x86 register name table" );++static SourceView::RegsX86 s_regMapX86[X86_REG_ENDING];+++static constexpr const char* s_CostName[] = {+ "Sample count",+ "Cycles",+ "Branch impact",+ "Cache impact",+ "Retirements",+ "Branches taken",+ "Branch miss",+ "Cache access",+ "Cache miss"+};++static constexpr SourceView::CostType s_costSeparateAfter = SourceView::CostType::SlowCache;++struct ChildStat+{+ uint64_t addr;+ uint32_t count;+};+++static tracy_force_inline uint64_t PackFileLine( uint32_t fileIdx, uint32_t line )+{+ return ( uint64_t( fileIdx ) << 32 ) | line;+}++static size_t CountHwSamples( const SortedVector<Int48, Int48Sort>& vec, const Range& range )+{+ if( vec.empty() ) return 0;+ auto it = std::lower_bound( vec.begin(), vec.end(), range.min, [] ( const auto& lhs, const auto& rhs ) { return lhs.Val() < rhs; } );+ if( it == vec.end() ) return 0;+ auto end = std::lower_bound( it, vec.end(), range.max, [] ( const auto& lhs, const auto& rhs ) { return lhs.Val() < rhs; } );+ return std::distance( it, end );+}++static void PrintHwSampleTooltip( size_t cycles, size_t retired, size_t cacheRef, size_t cacheMiss, size_t branchRetired, size_t branchMiss, bool hideFirstSeparator )+{+ if( cycles || retired )+ {+ if( hideFirstSeparator )+ {+ hideFirstSeparator = false;+ }+ else+ {+ ImGui::Separator();+ }+ if( cycles && retired )+ {+ char buf[32];+ auto end = PrintFloat( buf, buf+32, float( retired ) / cycles, 2 );+ *end = '\0';+ TextFocused( "IPC:", buf );+ }+ if( cycles ) TextFocused( "Cycles:", RealToString( cycles ) );+ if( retired ) TextFocused( "Retirements:", RealToString( retired ) );+ }+ if( cacheRef || cacheMiss )+ {+ if( hideFirstSeparator )+ {+ hideFirstSeparator = false;+ }+ else+ {+ ImGui::Separator();+ }+ if( cacheRef )+ {+ char buf[32];+ auto end = PrintFloat( buf, buf+32, float( 100 * cacheMiss ) / cacheRef, 2 );+ memcpy( end, "%", 2 );+ TextFocused( "Cache miss rate:", buf );+ TextFocused( "Cache references:", RealToString( cacheRef ) );+ }+ if( cacheMiss ) TextFocused( "Cache misses:", RealToString( cacheMiss ) );+ }+ if( branchRetired || branchMiss )+ {+ if( hideFirstSeparator )+ {+ hideFirstSeparator = false;+ }+ else+ {+ ImGui::Separator();+ }+ if( branchRetired )+ {+ char buf[32];+ auto end = PrintFloat( buf, buf+32, float( 100 * branchMiss ) / branchRetired, 2 );+ memcpy( end, "%", 2 );+ TextFocused( "Branch mispredictions rate:", buf );+ TextFocused( "Retired branches:", RealToString( branchRetired ) );+ }+ if( branchMiss ) TextFocused( "Branch mispredictions:", RealToString( branchMiss ) );+ }+}++static void PrintSourceFragment( const SourceContents& src, uint32_t srcline, int pre = 4, int post = 3 )+{+ auto& lines = src.get();+ const int start = std::max( 0, (int)srcline - pre );+ const int end = std::min<int>( src.get().size(), srcline + post );+ bool first = true;+ int bottomEmpty = 0;+ for( int i=start; i<end; i++ )+ {+ auto& line = lines[i];+ if( line.begin == line.end )+ {+ if( !first ) bottomEmpty++;+ }+ else+ {+ first = false;+ while( bottomEmpty > 0 )+ {+ ImGui::TextUnformatted( "" );+ bottomEmpty--;+ }++ auto ptr = line.begin;+ auto it = line.tokens.begin();+ while( ptr < line.end )+ {+ if( it == line.tokens.end() )+ {+ ImGui::TextUnformatted( ptr, line.end );+ ImGui::SameLine( 0, 0 );+ break;+ }+ if( ptr < it->begin )+ {+ ImGui::TextUnformatted( ptr, it->begin );+ ImGui::SameLine( 0, 0 );+ }+ auto color = SyntaxColors[(int)it->color];+ if( i != srcline-1 ) color = ( color & 0xFFFFFF ) | 0x99000000;+ TextColoredUnformatted( color, it->begin, it->end );+ ImGui::SameLine( 0, 0 );+ ptr = it->end;+ ++it;+ }+ ImGui::ItemSize( ImVec2( 0, 0 ), 0 );+ }+ }+}+++constexpr float JumpSeparationBase = 6;+constexpr float JumpArrowBase = 9;++float SourceView::CalcJumpSeparation( float scale )+{+ float jsb = JumpSeparationBase;+ if( m_maxJumpLevel > 75 ) jsb -= 5;+ else if( m_maxJumpLevel > 60 ) jsb -= 4;+ else if( m_maxJumpLevel > 45 ) jsb -= 3;+ else if( m_maxJumpLevel > 30 ) jsb -= 2;+ else if( m_maxJumpLevel > 15 ) jsb -= 1;+ return round( jsb * scale );+}+++SourceView::SourceView()+ : m_font( nullptr )+ , m_smallFont( nullptr )+ , m_symAddr( 0 )+ , m_targetAddr( 0 )+ , m_targetLine( 0 )+ , m_selectedLine( 0 )+ , m_asmSelected( -1 )+ , m_hoveredLine( 0 )+ , m_hoveredSource( 0 )+ , m_codeLen( 0 )+ , m_highlightAddr( 0 )+ , m_asmCountBase( -1 )+ , m_asmRelative( true )+ , m_asmBytes( false )+ , m_asmShowSourceLocation( true )+ , m_calcInlineStats( true )+ , m_hwSamples( true )+ , m_hwSamplesRelative( true )+ , m_childCalls( false )+ , m_childCallList( false )+ , m_propagateInlines( false )+ , m_cost( CostType::SampleCount )+ , m_showJumps( true )+ , m_locAddrIsProp( false )+ , m_cpuArch( CpuArchUnknown )+{+ m_microArchOpMap.reserve( OpsNum );+ for( int i=0; i<OpsNum; i++ )+ {+ m_microArchOpMap.emplace( OpsList[i], i );+ }++ memset( s_regMapX86, 0, sizeof( s_regMapX86 ) );++ s_regMapX86[X86_REG_EFLAGS] = RegsX86::flags;+ s_regMapX86[X86_REG_AH] = RegsX86::rax;+ s_regMapX86[X86_REG_AL] = RegsX86::rax;+ s_regMapX86[X86_REG_AX] = RegsX86::rax;+ s_regMapX86[X86_REG_EAX] = RegsX86::rax;+ s_regMapX86[X86_REG_RAX] = RegsX86::rax;+ s_regMapX86[X86_REG_BH] = RegsX86::rbx;+ s_regMapX86[X86_REG_BL] = RegsX86::rbx;+ s_regMapX86[X86_REG_BX] = RegsX86::rbx;+ s_regMapX86[X86_REG_EBX] = RegsX86::rbx;+ s_regMapX86[X86_REG_RBX] = RegsX86::rbx;+ s_regMapX86[X86_REG_CH] = RegsX86::rcx;+ s_regMapX86[X86_REG_CL] = RegsX86::rcx;+ s_regMapX86[X86_REG_CX] = RegsX86::rcx;+ s_regMapX86[X86_REG_ECX] = RegsX86::rcx;+ s_regMapX86[X86_REG_RCX] = RegsX86::rcx;+ s_regMapX86[X86_REG_DH] = RegsX86::rdx;+ s_regMapX86[X86_REG_DL] = RegsX86::rdx;+ s_regMapX86[X86_REG_DX] = RegsX86::rdx;+ s_regMapX86[X86_REG_EDX] = RegsX86::rdx;+ s_regMapX86[X86_REG_RDX] = RegsX86::rdx;+ s_regMapX86[X86_REG_SIL] = RegsX86::rsi;+ s_regMapX86[X86_REG_SI] = RegsX86::rsi;+ s_regMapX86[X86_REG_ESI] = RegsX86::rsi;+ s_regMapX86[X86_REG_RSI] = RegsX86::rsi;+ s_regMapX86[X86_REG_DIL] = RegsX86::rdi;+ s_regMapX86[X86_REG_DI] = RegsX86::rdi;+ s_regMapX86[X86_REG_EDI] = RegsX86::rdi;+ s_regMapX86[X86_REG_RDI] = RegsX86::rdi;+ s_regMapX86[X86_REG_BP] = RegsX86::rbp;+ s_regMapX86[X86_REG_BP] = RegsX86::rbp;+ s_regMapX86[X86_REG_EBP] = RegsX86::rbp;+ s_regMapX86[X86_REG_RBP] = RegsX86::rbp;+ s_regMapX86[X86_REG_SPL] = RegsX86::rsp;+ s_regMapX86[X86_REG_SP] = RegsX86::rsp;+ s_regMapX86[X86_REG_ESP] = RegsX86::rsp;+ s_regMapX86[X86_REG_RSP] = RegsX86::rsp;+ s_regMapX86[X86_REG_R8B] = RegsX86::r8;+ s_regMapX86[X86_REG_R8W] = RegsX86::r8;+ s_regMapX86[X86_REG_R8D] = RegsX86::r8;+ s_regMapX86[X86_REG_R8] = RegsX86::r8;+ s_regMapX86[X86_REG_R9B] = RegsX86::r9;+ s_regMapX86[X86_REG_R9W] = RegsX86::r9;+ s_regMapX86[X86_REG_R9D] = RegsX86::r9;+ s_regMapX86[X86_REG_R9] = RegsX86::r9;+ s_regMapX86[X86_REG_R10B] = RegsX86::r10;+ s_regMapX86[X86_REG_R10W] = RegsX86::r10;+ s_regMapX86[X86_REG_R10D] = RegsX86::r10;+ s_regMapX86[X86_REG_R10] = RegsX86::r10;+ s_regMapX86[X86_REG_R11B] = RegsX86::r11;+ s_regMapX86[X86_REG_R11W] = RegsX86::r11;+ s_regMapX86[X86_REG_R11D] = RegsX86::r11;+ s_regMapX86[X86_REG_R11] = RegsX86::r11;+ s_regMapX86[X86_REG_R12B] = RegsX86::r12;+ s_regMapX86[X86_REG_R12W] = RegsX86::r12;+ s_regMapX86[X86_REG_R12D] = RegsX86::r12;+ s_regMapX86[X86_REG_R12] = RegsX86::r12;+ s_regMapX86[X86_REG_R13B] = RegsX86::r13;+ s_regMapX86[X86_REG_R13W] = RegsX86::r13;+ s_regMapX86[X86_REG_R13D] = RegsX86::r13;+ s_regMapX86[X86_REG_R13] = RegsX86::r13;+ s_regMapX86[X86_REG_R14B] = RegsX86::r14;+ s_regMapX86[X86_REG_R14W] = RegsX86::r14;+ s_regMapX86[X86_REG_R14D] = RegsX86::r14;+ s_regMapX86[X86_REG_R14] = RegsX86::r14;+ s_regMapX86[X86_REG_R15B] = RegsX86::r15;+ s_regMapX86[X86_REG_R15W] = RegsX86::r15;+ s_regMapX86[X86_REG_R15D] = RegsX86::r15;+ s_regMapX86[X86_REG_R15] = RegsX86::r15;+ s_regMapX86[X86_REG_MM0] = RegsX86::mm0;+ s_regMapX86[X86_REG_MM1] = RegsX86::mm1;+ s_regMapX86[X86_REG_MM2] = RegsX86::mm2;+ s_regMapX86[X86_REG_MM3] = RegsX86::mm3;+ s_regMapX86[X86_REG_MM4] = RegsX86::mm4;+ s_regMapX86[X86_REG_MM5] = RegsX86::mm5;+ s_regMapX86[X86_REG_MM6] = RegsX86::mm6;+ s_regMapX86[X86_REG_MM7] = RegsX86::mm7;+ s_regMapX86[X86_REG_ST0] = RegsX86::mm0;+ s_regMapX86[X86_REG_ST1] = RegsX86::mm1;+ s_regMapX86[X86_REG_ST2] = RegsX86::mm2;+ s_regMapX86[X86_REG_ST3] = RegsX86::mm3;+ s_regMapX86[X86_REG_ST4] = RegsX86::mm4;+ s_regMapX86[X86_REG_ST5] = RegsX86::mm5;+ s_regMapX86[X86_REG_ST6] = RegsX86::mm6;+ s_regMapX86[X86_REG_ST7] = RegsX86::mm7;+ s_regMapX86[X86_REG_XMM0] = RegsX86::xmm0;+ s_regMapX86[X86_REG_YMM0] = RegsX86::xmm0;+ s_regMapX86[X86_REG_ZMM0] = RegsX86::xmm0;+ s_regMapX86[X86_REG_XMM1] = RegsX86::xmm1;+ s_regMapX86[X86_REG_YMM1] = RegsX86::xmm1;+ s_regMapX86[X86_REG_ZMM1] = RegsX86::xmm1;+ s_regMapX86[X86_REG_XMM2] = RegsX86::xmm2;+ s_regMapX86[X86_REG_YMM2] = RegsX86::xmm2;+ s_regMapX86[X86_REG_ZMM2] = RegsX86::xmm2;+ s_regMapX86[X86_REG_XMM3] = RegsX86::xmm3;+ s_regMapX86[X86_REG_YMM3] = RegsX86::xmm3;+ s_regMapX86[X86_REG_ZMM3] = RegsX86::xmm3;+ s_regMapX86[X86_REG_XMM4] = RegsX86::xmm4;+ s_regMapX86[X86_REG_YMM4] = RegsX86::xmm4;+ s_regMapX86[X86_REG_ZMM4] = RegsX86::xmm4;+ s_regMapX86[X86_REG_XMM5] = RegsX86::xmm5;+ s_regMapX86[X86_REG_YMM5] = RegsX86::xmm5;+ s_regMapX86[X86_REG_ZMM5] = RegsX86::xmm5;+ s_regMapX86[X86_REG_XMM6] = RegsX86::xmm6;+ s_regMapX86[X86_REG_YMM6] = RegsX86::xmm6;+ s_regMapX86[X86_REG_ZMM6] = RegsX86::xmm6;+ s_regMapX86[X86_REG_XMM7] = RegsX86::xmm7;+ s_regMapX86[X86_REG_YMM7] = RegsX86::xmm7;+ s_regMapX86[X86_REG_ZMM7] = RegsX86::xmm7;+ s_regMapX86[X86_REG_XMM8] = RegsX86::xmm8;+ s_regMapX86[X86_REG_YMM8] = RegsX86::xmm8;+ s_regMapX86[X86_REG_ZMM8] = RegsX86::xmm8;+ s_regMapX86[X86_REG_XMM9] = RegsX86::xmm9;+ s_regMapX86[X86_REG_YMM9] = RegsX86::xmm9;+ s_regMapX86[X86_REG_ZMM9] = RegsX86::xmm9;+ s_regMapX86[X86_REG_XMM10] = RegsX86::xmm10;+ s_regMapX86[X86_REG_YMM10] = RegsX86::xmm10;+ s_regMapX86[X86_REG_ZMM10] = RegsX86::xmm10;+ s_regMapX86[X86_REG_XMM11] = RegsX86::xmm11;+ s_regMapX86[X86_REG_YMM11] = RegsX86::xmm11;+ s_regMapX86[X86_REG_ZMM11] = RegsX86::xmm11;+ s_regMapX86[X86_REG_XMM12] = RegsX86::xmm12;+ s_regMapX86[X86_REG_YMM12] = RegsX86::xmm12;+ s_regMapX86[X86_REG_ZMM12] = RegsX86::xmm12;+ s_regMapX86[X86_REG_XMM13] = RegsX86::xmm13;+ s_regMapX86[X86_REG_YMM13] = RegsX86::xmm13;+ s_regMapX86[X86_REG_ZMM13] = RegsX86::xmm13;+ s_regMapX86[X86_REG_XMM14] = RegsX86::xmm14;+ s_regMapX86[X86_REG_YMM14] = RegsX86::xmm14;+ s_regMapX86[X86_REG_ZMM14] = RegsX86::xmm14;+ s_regMapX86[X86_REG_XMM15] = RegsX86::xmm15;+ s_regMapX86[X86_REG_YMM15] = RegsX86::xmm15;+ s_regMapX86[X86_REG_ZMM15] = RegsX86::xmm15;+ s_regMapX86[X86_REG_XMM16] = RegsX86::xmm16;+ s_regMapX86[X86_REG_YMM16] = RegsX86::xmm16;+ s_regMapX86[X86_REG_ZMM16] = RegsX86::xmm16;+ s_regMapX86[X86_REG_XMM17] = RegsX86::xmm17;+ s_regMapX86[X86_REG_YMM17] = RegsX86::xmm17;+ s_regMapX86[X86_REG_ZMM17] = RegsX86::xmm17;+ s_regMapX86[X86_REG_XMM18] = RegsX86::xmm18;+ s_regMapX86[X86_REG_YMM18] = RegsX86::xmm18;+ s_regMapX86[X86_REG_ZMM18] = RegsX86::xmm18;+ s_regMapX86[X86_REG_XMM19] = RegsX86::xmm19;+ s_regMapX86[X86_REG_YMM19] = RegsX86::xmm19;+ s_regMapX86[X86_REG_ZMM19] = RegsX86::xmm19;+ s_regMapX86[X86_REG_XMM20] = RegsX86::xmm20;+ s_regMapX86[X86_REG_YMM20] = RegsX86::xmm20;+ s_regMapX86[X86_REG_ZMM20] = RegsX86::xmm20;+ s_regMapX86[X86_REG_XMM21] = RegsX86::xmm21;+ s_regMapX86[X86_REG_YMM21] = RegsX86::xmm21;+ s_regMapX86[X86_REG_ZMM21] = RegsX86::xmm21;+ s_regMapX86[X86_REG_XMM22] = RegsX86::xmm22;+ s_regMapX86[X86_REG_YMM22] = RegsX86::xmm22;+ s_regMapX86[X86_REG_ZMM22] = RegsX86::xmm22;+ s_regMapX86[X86_REG_XMM23] = RegsX86::xmm23;+ s_regMapX86[X86_REG_YMM23] = RegsX86::xmm23;+ s_regMapX86[X86_REG_ZMM23] = RegsX86::xmm23;+ s_regMapX86[X86_REG_XMM24] = RegsX86::xmm24;+ s_regMapX86[X86_REG_YMM24] = RegsX86::xmm24;+ s_regMapX86[X86_REG_ZMM24] = RegsX86::xmm24;+ s_regMapX86[X86_REG_XMM25] = RegsX86::xmm25;+ s_regMapX86[X86_REG_YMM25] = RegsX86::xmm25;+ s_regMapX86[X86_REG_ZMM25] = RegsX86::xmm25;+ s_regMapX86[X86_REG_XMM26] = RegsX86::xmm26;+ s_regMapX86[X86_REG_YMM26] = RegsX86::xmm26;+ s_regMapX86[X86_REG_ZMM26] = RegsX86::xmm26;+ s_regMapX86[X86_REG_XMM27] = RegsX86::xmm27;+ s_regMapX86[X86_REG_YMM27] = RegsX86::xmm27;+ s_regMapX86[X86_REG_ZMM27] = RegsX86::xmm27;+ s_regMapX86[X86_REG_XMM28] = RegsX86::xmm28;+ s_regMapX86[X86_REG_YMM28] = RegsX86::xmm28;+ s_regMapX86[X86_REG_ZMM28] = RegsX86::xmm28;+ s_regMapX86[X86_REG_XMM29] = RegsX86::xmm29;+ s_regMapX86[X86_REG_YMM29] = RegsX86::xmm29;+ s_regMapX86[X86_REG_ZMM29] = RegsX86::xmm29;+ s_regMapX86[X86_REG_XMM30] = RegsX86::xmm30;+ s_regMapX86[X86_REG_YMM30] = RegsX86::xmm30;+ s_regMapX86[X86_REG_ZMM30] = RegsX86::xmm30;+ s_regMapX86[X86_REG_XMM31] = RegsX86::xmm31;+ s_regMapX86[X86_REG_YMM31] = RegsX86::xmm31;+ s_regMapX86[X86_REG_ZMM31] = RegsX86::xmm31;+ s_regMapX86[X86_REG_K0] = RegsX86::k0;+ s_regMapX86[X86_REG_K1] = RegsX86::k1;+ s_regMapX86[X86_REG_K2] = RegsX86::k2;+ s_regMapX86[X86_REG_K3] = RegsX86::k3;+ s_regMapX86[X86_REG_K4] = RegsX86::k4;+ s_regMapX86[X86_REG_K5] = RegsX86::k5;+ s_regMapX86[X86_REG_K6] = RegsX86::k6;+ s_regMapX86[X86_REG_K7] = RegsX86::k7;+}++static constexpr uint32_t PackCpuInfo( uint32_t cpuid )+{+ return ( cpuid & 0xFFF ) | ( ( cpuid & 0xFFF0000 ) >> 4 );+}++struct CpuIdMap+{+ uint32_t cpuInfo;+ const char* moniker;+};++// http://instlatx64.atw.hu/ seems to be a good resource+//+// .------ extended family id+// |.----- extended model id+// || .--- family id+// || |.-- model+// || ||.- stepping+// || |||+static constexpr CpuIdMap s_cpuIdMap[] = {+ { PackCpuInfo( 0x810F81 ), "ZEN+" },+ { PackCpuInfo( 0x800F82 ), "ZEN+" },+ { PackCpuInfo( 0x830F10 ), "ZEN2" },+ { PackCpuInfo( 0x840F70 ), "ZEN2" },+ { PackCpuInfo( 0x860F01 ), "ZEN2" },+ { PackCpuInfo( 0x860F81 ), "ZEN2" },+ { PackCpuInfo( 0x870F10 ), "ZEN2" },+ { PackCpuInfo( 0x890F00 ), "ZEN2" },+ { PackCpuInfo( 0x890F80 ), "ZEN2" },+ { PackCpuInfo( 0xA00F11 ), "ZEN3" },+ { PackCpuInfo( 0xA00F80 ), "ZEN3" },+ { PackCpuInfo( 0xA20F10 ), "ZEN3" },+ { PackCpuInfo( 0xA20F12 ), "ZEN3" },+ { PackCpuInfo( 0xA30F00 ), "ZEN3" },+ { PackCpuInfo( 0xA40F00 ), "ZEN3" },+ { PackCpuInfo( 0xA40F41 ), "ZEN3" },+ { PackCpuInfo( 0xA50F00 ), "ZEN3" },+ { PackCpuInfo( 0xA60F12 ), "ZEN4" },+ { PackCpuInfo( 0xA10F11 ), "ZEN4" },+ { PackCpuInfo( 0x090672 ), "ADL-P" },+ { PackCpuInfo( 0x090675 ), "ADL-P" },+ { PackCpuInfo( 0x0906A2 ), "ADL-P" },+ { PackCpuInfo( 0x0906A3 ), "ADL-P" },+ { PackCpuInfo( 0x0906A4 ), "ADL-P" },+ { PackCpuInfo( 0x0A0671 ), "RKL" },+ { PackCpuInfo( 0x0806C1 ), "TGL" },+ { PackCpuInfo( 0x0806D1 ), "TGL" },+ { PackCpuInfo( 0x0706E5 ), "ICL" },+ { PackCpuInfo( 0x0606A6 ), "ICL" },+ { PackCpuInfo( 0x050656 ), "CLX" },+ { PackCpuInfo( 0x050657 ), "CLX" },+ { PackCpuInfo( 0x060663 ), "CNL" },+ { PackCpuInfo( 0x0906EA ), "CFL" },+ { PackCpuInfo( 0x0906EB ), "CFL" },+ { PackCpuInfo( 0x0906EC ), "CFL" },+ { PackCpuInfo( 0x0906ED ), "CFL" },+ { PackCpuInfo( 0x0806E9 ), "KBL" },+ { PackCpuInfo( 0x0806EA ), "KBL" },+ { PackCpuInfo( 0x0906E9 ), "KBL" },+ { PackCpuInfo( 0x050654 ), "SKX" },+ { PackCpuInfo( 0x0406E3 ), "SKL" },+ { PackCpuInfo( 0x0506E0 ), "SKL" },+ { PackCpuInfo( 0x0506E3 ), "SKL" },+ { PackCpuInfo( 0x0306D4 ), "BDW" },+ { PackCpuInfo( 0x040671 ), "BDW" },+ { PackCpuInfo( 0x0406F1 ), "BDW" },+ { PackCpuInfo( 0x0306C3 ), "HSW" },+ { PackCpuInfo( 0x0306F2 ), "HSW" },+ { PackCpuInfo( 0x040651 ), "HSW" },+ { PackCpuInfo( 0x0306A9 ), "IVB" },+ { PackCpuInfo( 0x0306E3 ), "IVB" },+ { PackCpuInfo( 0x0306E4 ), "IVB" },+ { PackCpuInfo( 0x0206A2 ), "SNB" },+ { PackCpuInfo( 0x0206A7 ), "SNB" },+ { PackCpuInfo( 0x0206D5 ), "SNB" },+ { PackCpuInfo( 0x0206D6 ), "SNB" },+ { PackCpuInfo( 0x0206D7 ), "SNB" },+ { PackCpuInfo( 0x0206F2 ), "WSM" },+ { PackCpuInfo( 0x0206C0 ), "WSM" },+ { PackCpuInfo( 0x0206C1 ), "WSM" },+ { PackCpuInfo( 0x0206C2 ), "WSM" },+ { PackCpuInfo( 0x020652 ), "WSM" },+ { PackCpuInfo( 0x020655 ), "WSM" },+ { PackCpuInfo( 0x0206E6 ), "NHM" },+ { PackCpuInfo( 0x0106A1 ), "NHM" },+ { PackCpuInfo( 0x0106A2 ), "NHM" },+ { PackCpuInfo( 0x0106A4 ), "NHM" },+ { PackCpuInfo( 0x0106A5 ), "NHM" },+ { PackCpuInfo( 0x0106E4 ), "NHM" },+ { PackCpuInfo( 0x0106E5 ), "NHM" },+ { PackCpuInfo( 0x010676 ), "WOL" },+ { PackCpuInfo( 0x01067A ), "WOL" },+ { PackCpuInfo( 0x0006F2 ), "CON" },+ { PackCpuInfo( 0x0006F4 ), "CON" },+ { PackCpuInfo( 0x0006F6 ), "CON" },+ { PackCpuInfo( 0x0006FB ), "CON" },+ { PackCpuInfo( 0x0006FD ), "CON" },+ { PackCpuInfo( 0x0106C2 ), "BNL" },+ { PackCpuInfo( 0x0106CA ), "BNL" },+ { PackCpuInfo( 0x07065A ), "AMT" },+ { PackCpuInfo( 0x0506C9 ), "GLM" },+ { PackCpuInfo( 0x0506F1 ), "GLM" },+ { PackCpuInfo( 0x0706A1 ), "GLP" },+ { PackCpuInfo( 0x0706A8 ), "GLP" },+ { PackCpuInfo( 0x0806A1 ), "TRM" },+ { PackCpuInfo( 0x090661 ), "TRM" },+ { PackCpuInfo( 0x0906C0 ), "TRM" },+ { 0, 0 }+};++void SourceView::SetCpuId( uint32_t cpuId )+{+ auto ptr = s_cpuIdMap;+ while( ptr->cpuInfo )+ {+ if( cpuId == ptr->cpuInfo )+ {+ SelectMicroArchitecture( ptr->moniker );+ m_profileMicroArch = m_selMicroArch;+ return;+ }+ ptr++;+ }+ SelectMicroArchitecture( "ZEN4" );+ m_profileMicroArch = -1;+}++void SourceView::OpenSource( const char* fileName, int line, const View& view, const Worker& worker )+{+ m_targetLine = line;+ m_selectedLine = line;+ m_targetAddr = 0;+ m_baseAddr = 0;+ m_symAddr = 0;+ m_sourceFiles.clear();+ m_asm.clear();++ ParseSource( fileName, worker, view );+ assert( !m_source.empty() );+}++void SourceView::OpenSymbol( const char* fileName, int line, uint64_t baseAddr, uint64_t symAddr, Worker& worker, const View& view, bool updateHistory )+{+ m_targetLine = line;+ m_targetAddr = symAddr;+ m_baseAddr = baseAddr;+ m_symAddr = symAddr;+ m_sourceFiles.clear();+ m_selectedAddresses.clear();+ m_selectedAddresses.emplace( symAddr );++ ParseSource( fileName, worker, view );+ Disassemble( baseAddr, worker );+ SelectLine( line, &worker, true, symAddr );++ SelectViewMode();++ if( !worker.GetInlineSymbolList( baseAddr, m_codeLen ) ) m_calcInlineStats = false;++ if( updateHistory )+ {+ m_history.erase( m_history.begin() + m_historyCursor, m_history.end() );++ History entry = { fileName, line, baseAddr, symAddr };+ if( m_history.empty() || memcmp( &m_history.back(), &entry, sizeof( History ) ) != 0 )+ {+ m_history.emplace_back( entry );+ if( m_history.size() > 100 ) m_history.erase( m_history.begin() );+ m_historyCursor = m_history.size();+ }+ }+}++void SourceView::SelectViewMode()+{+ if( !m_source.empty() )+ {+ if( !m_asm.empty() )+ {+ m_displayMode = DisplayMixed;+ }+ else+ {+ m_displayMode = DisplaySource;+ }+ }+ else+ {+ assert( !m_asm.empty() );+ m_displayMode = DisplayAsm;+ }+}++void SourceView::ParseSource( const char* fileName, const Worker& worker, const View& view )+{+ if( m_source.filename() != fileName )+ {+ m_srcWidth = 0;+ m_source.Parse( fileName, worker, view );+ }+}++static bool IsJumpConditionalX86( const char* op )+{+ static constexpr const char* branchX86[] = {+ "je", "jne", "jg", "jge", "ja", "jae", "jl", "jle", "jb", "jbe", "jo", "jno", "jz", "jnz", "js", "jns", "jcxz", "jecxz", "jrcxz", "loop", "loope",+ "loopne", "loopnz", "loopz", "jnle", "jnl", "jnge", "jng", "jnbe", "jnb", "jnae", "jna", "jc", "jnc", "jp", "jpe", "jnp", "jpo", nullptr+ };+ auto ptr = branchX86;+ while( *ptr ) if( strcmp( *ptr++, op ) == 0 ) return true;+ return false;+}++bool SourceView::Disassemble( uint64_t symAddr, const Worker& worker )+{+ m_asm.clear();+ m_locMap.clear();+ m_jumpTable.clear();+ m_jumpOut.clear();+ m_locationAddress.clear();+ m_maxJumpLevel = 0;+ m_asmSelected = -1;+ m_asmCountBase = -1;+ m_asmWidth = 0;+ if( symAddr == 0 ) return false;+ m_cpuArch = worker.GetCpuArch();+ if( m_cpuArch == CpuArchUnknown ) return false;+ uint32_t len;+ auto code = worker.GetSymbolCode( symAddr, len );+ if( !code ) return false;+ m_disasmFail = -1;+ csh handle;+ cs_err rval = CS_ERR_ARCH;+ switch( m_cpuArch )+ {+ case CpuArchX86:+ rval = cs_open( CS_ARCH_X86, CS_MODE_32, &handle );+ break;+ case CpuArchX64:+ rval = cs_open( CS_ARCH_X86, CS_MODE_64, &handle );+ break;+ case CpuArchArm32:+ rval = cs_open( CS_ARCH_ARM, CS_MODE_ARM, &handle );+ break;+ case CpuArchArm64:+ rval = cs_open( CS_ARCH_AARCH64, CS_MODE_ARM, &handle );+ break;+ default:+ assert( false );+ break;+ }+ if( rval != CS_ERR_OK ) return false;+ cs_option( handle, CS_OPT_DETAIL, CS_OPT_ON );+ cs_option( handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_INTEL );+ cs_insn* insn;+ size_t cnt = cs_disasm( handle, (const uint8_t*)code, len, symAddr, 0, &insn );+ if( cnt > 0 )+ {+ if( insn[cnt-1].address - symAddr + insn[cnt-1].size < len ) m_disasmFail = insn[cnt-1].address - symAddr;+ int bytesMax = 0;+ int mLenMax = 0;+ int oLenMax = 0;+ m_asm.reserve( cnt );+ for( size_t i=0; i<cnt; i++ )+ {+ const auto& op = insn[i];+ const auto& detail = *op.detail;+ bool hasJump = false;+ bool jumpConditional = false;+ OpType opType = OpType::None;+ for( auto j=0; j<detail.groups_count; j++ )+ {+ if( detail.groups[j] == CS_GRP_JUMP || detail.groups[j] == CS_GRP_CALL || detail.groups[j] == CS_GRP_RET )+ {+ hasJump = true;+ break;+ }+ }+ for( auto j=0; j<detail.groups_count; j++ )+ {+ if( detail.groups[j] == CS_GRP_JUMP && opType < OpType::Jump ) opType = OpType::Jump;+ else if( detail.groups[j] == CS_GRP_BRANCH_RELATIVE && opType < OpType::Branch ) opType = OpType::Branch;+ else if( detail.groups[j] == CS_GRP_CALL && opType < OpType::Call ) opType = OpType::Call;+ else if( detail.groups[j] == CS_GRP_RET && opType < OpType::Ret ) opType = OpType::Ret;+ else if( detail.groups[j] == CS_GRP_PRIVILEGE && opType < OpType::Privileged )+ {+ opType = OpType::Privileged;+ break;+ }+ }+ uint64_t jumpAddr = 0;+ if( hasJump )+ {+ switch( m_cpuArch )+ {+ case CpuArchX86:+ case CpuArchX64:+ if( detail.x86.op_count == 1 && detail.x86.operands[0].type == X86_OP_IMM )+ {+ jumpAddr = (uint64_t)detail.x86.operands[0].imm;+ }+ jumpConditional = IsJumpConditionalX86( op.mnemonic );+ break;+ case CpuArchArm32:+ if( detail.arm.op_count == 1 && detail.arm.operands[0].type == ARM_OP_IMM )+ {+ jumpAddr = (uint64_t)detail.arm.operands[0].imm;+ }+ break;+ case CpuArchArm64:+ if( detail.aarch64.op_count == 1 && detail.aarch64.operands[0].type == AARCH64_OP_IMM )+ {+ jumpAddr = (uint64_t)detail.aarch64.operands[0].imm;+ }+ break;+ default:+ assert( false );+ break;+ }+ if( jumpAddr >= symAddr && jumpAddr < symAddr + len )+ {+ auto fit = std::lower_bound( insn, insn+cnt, jumpAddr, []( const auto& l, const auto& r ) { return l.address < r; } );+ if( fit != insn+cnt && fit->address == jumpAddr )+ {+ const auto min = std::min( jumpAddr, op.address );+ const auto max = std::max( jumpAddr, op.address );+ auto it = m_jumpTable.find( jumpAddr );+ if( it == m_jumpTable.end() )+ {+ m_jumpTable.emplace( jumpAddr, JumpData { min, max, 0, { op.address } } );+ }+ else+ {+ if( it->second.min > min ) it->second.min = min;+ else if( it->second.max < max ) it->second.max = max;+ it->second.source.emplace_back( op.address );+ }+ }+ else+ {+ jumpAddr = 0;+ }+ }+ else+ {+ m_jumpOut.emplace( op.address );+ }+ }+ std::vector<AsmOpParams> params;+ switch( m_cpuArch )+ {+ case CpuArchX86:+ case CpuArchX64:+ for( uint8_t i=0; i<detail.x86.op_count; i++ )+ {+ uint8_t type = 0;+ switch( detail.x86.operands[i].type )+ {+ case X86_OP_IMM:+ type = 0;+ break;+ case X86_OP_REG:+ type = 1;+ break;+ case X86_OP_MEM:+ type = 2;+ break;+ default:+ assert( false );+ break;+ }+ params.emplace_back( AsmOpParams { type, uint16_t( detail.x86.operands[i].size * 8 ) } );+ }+ break;+ case CpuArchArm32:+ for( uint8_t i=0; i<detail.arm.op_count; i++ )+ {+ uint8_t type = 0;+ switch( detail.arm.operands[i].type )+ {+ case ARM_OP_IMM:+ type = 0;+ break;+ case ARM_OP_REG:+ type = 1;+ break;+ case ARM_OP_MEM:+ type = 2;+ break;+ default:+ type = 255;+ break;+ }+ params.emplace_back( AsmOpParams { type, 0 } );+ }+ break;+ case CpuArchArm64:+ for( uint8_t i=0; i<detail.aarch64.op_count; i++ )+ {+ uint8_t type = 0;+ switch( detail.aarch64.operands[i].type )+ {+ case AARCH64_OP_IMM:+ type = 0;+ break;+ case AARCH64_OP_REG:+ type = 1;+ break;+ case AARCH64_OP_MEM:+ type = 2;+ break;+ default:+ type = 255;+ break;+ }+ params.emplace_back( AsmOpParams { type, 0 } );+ }+ break;+ default:+ assert( false );+ break;+ }+ LeaData leaData = LeaData::none;+ if( ( m_cpuArch == CpuArchX64 || m_cpuArch == CpuArchX86 ) && op.id == X86_INS_LEA )+ {+ assert( op.detail->x86.op_count == 2 );+ assert( op.detail->x86.operands[1].type == X86_OP_MEM );+ auto& mem = op.detail->x86.operands[1].mem;+ if( mem.base == X86_REG_INVALID )+ {+ if( mem.index == X86_REG_INVALID )+ {+ leaData = LeaData::d;+ }+ else+ {+ leaData = mem.disp == 0 ? LeaData::i : LeaData::id;+ }+ }+ else if( mem.base == X86_REG_RIP )+ {+ leaData = mem.disp == 0 ? LeaData::r : LeaData::rd;+ }+ else+ {+ if( mem.index == X86_REG_INVALID )+ {+ leaData = mem.disp == 0 ? LeaData::b : LeaData::bd;+ }+ else+ {+ leaData = mem.disp == 0 ? LeaData::bi : LeaData::bid;+ }+ }+ }+ m_asm.emplace_back( AsmLine { op.address, jumpAddr, op.mnemonic, op.op_str, (uint8_t)op.size, leaData, opType, jumpConditional, std::move( params ) } );+ const auto& operands = m_asm.back().operands;+ m_asm.back().opTokens = m_tokenizer.TokenizeAsm( operands.c_str(), operands.c_str() + operands.size() );++#if CS_API_MAJOR >= 4+ auto& entry = m_asm.back();+ cs_regs read, write;+ uint8_t rcnt, wcnt;+ cs_regs_access( handle, &op, read, &rcnt, write, &wcnt );+ int idx;+ switch( m_cpuArch )+ {+ case CpuArchX86:+ case CpuArchX64:+ assert( rcnt < sizeof( entry.readX86 ) );+ assert( wcnt < sizeof( entry.writeX86 ) );+ idx = 0;+ for( int i=0; i<rcnt; i++ )+ {+ if( s_regMapX86[read[i]] != RegsX86::invalid ) entry.readX86[idx++] = s_regMapX86[read[i]];+ entry.readX86[idx] = RegsX86::invalid;+ }+ idx = 0;+ for( int i=0; i<wcnt; i++ )+ {+ if( s_regMapX86[write[i]] != RegsX86::invalid ) entry.writeX86[idx++] = s_regMapX86[write[i]];+ entry.writeX86[idx] = RegsX86::invalid;+ }+ break;+ default:+ break;+ }+#endif++ const auto mLen = (int)strlen( op.mnemonic );+ if( mLen > mLenMax ) mLenMax = mLen;+ const auto oLen = (int)strlen( op.op_str );+ if( oLen > oLenMax ) oLenMax = oLen;+ if( op.size > bytesMax ) bytesMax = op.size;++ uint32_t mLineMax = 0;+ uint32_t srcline;+ const auto srcidx = worker.GetLocationForAddress( op.address, srcline );+ if( srcline != 0 )+ {+ if( srcline > mLineMax ) mLineMax = srcline;+ const auto idx = srcidx.Idx();+ auto sit = m_sourceFiles.find( idx );+ if( sit == m_sourceFiles.end() ) m_sourceFiles.emplace( idx, srcline );+ }+ char tmp[16];+ sprintf( tmp, "%" PRIu32, mLineMax );+ m_maxLine = strlen( tmp ) + 1;+ }+ cs_free( insn, cnt );+ m_maxMnemonicLen = mLenMax + 1;+ m_maxOperandLen = oLenMax + 1;+ m_maxAsmBytes = bytesMax;+ if( !m_jumpTable.empty() )+ {+ struct JumpRange+ {+ uint64_t target;+ uint64_t len;+ };+ std::vector<JumpRange> jumpRange;+ jumpRange.reserve( m_jumpTable.size() );+ for( auto& v : m_jumpTable )+ {+ pdqsort_branchless( v.second.source.begin(), v.second.source.end() );+ jumpRange.emplace_back( JumpRange { v.first, v.second.max - v.second.min } );+ }+ pdqsort_branchless( jumpRange.begin(), jumpRange.end(), []( const auto& l, const auto& r ) { return l.len < r.len; } );+ std::vector<std::vector<std::pair<uint64_t, uint64_t>>> levelRanges;+ for( auto& v : jumpRange )+ {+ auto it = m_jumpTable.find( v.target );+ assert( it != m_jumpTable.end() );+ size_t level = 0;+ for(;;)+ {+ assert( levelRanges.size() >= level );+ if( levelRanges.size() == level )+ {+ it->second.level = level;+ levelRanges.push_back( { { it->second.min, it->second.max } } );+ break;+ }+ else+ {+ bool validFit = true;+ auto& lr = levelRanges[level];+ for( auto& range : lr )+ {+ assert( !( it->second.min >= range.first && it->second.max <= range.second ) );+ if( it->second.min <= range.second && it->second.max >= range.first )+ {+ validFit = false;+ break;+ }+ }+ if( validFit )+ {+ it->second.level = level;+ lr.emplace_back( it->second.min, it->second.max );+ break;+ }+ level++;+ }+ }+ if( level > m_maxJumpLevel ) m_maxJumpLevel = level;+ }++ uint32_t locNum = 0;+ for( auto& v : m_asm )+ {+ if( m_jumpTable.find( v.addr ) != m_jumpTable.end() )+ {+ m_locMap.emplace( v.addr, locNum++ );+ }+ }+ }+ }+ cs_close( &handle );+ m_codeLen = len;+ ResetAsm();+ return true;+}++void SourceView::Render( Worker& worker, View& view )+{+ m_highlightAddr.Decay( 0 );+ m_hoveredLine.Decay( 0 );+ m_hoveredSource.Decay( 0 );++ if( m_symAddr == 0 )+ {+ ImGui::PushFont( m_bigFont );+ if( ClipboardButton() )+ {+ std::ostringstream stream;+ stream.write( m_source.data(), m_source.data_size() );+ ImGui::SetClipboardText( stream.str().c_str() );+ }+ ImGui::PopFont();+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ if( m_source.filename() )+ {+ ImGui::PushFont( m_bigFont );+ TextFocused( ICON_FA_FILE " File:", m_source.filename() );+ ImGui::PopFont();+ }+ if( m_source.is_cached() )+ {+ TextColoredUnformatted( ImVec4( 0.4f, 0.8f, 0.4f, 1.f ), ICON_FA_DATABASE );+ ImGui::SameLine();+ ImGui::TextUnformatted( "Source file cached during profiling run" );+ }+ else+ {+ TextColoredUnformatted( ImVec4( 1.f, 1.f, 0.2f, 1.f ), ICON_FA_TRIANGLE_EXCLAMATION );+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 1.f, 0.3f, 0.3f, 1.f ), "The source file contents might not reflect the actual profiled code!" );+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 1.f, 1.f, 0.2f, 1.f ), ICON_FA_TRIANGLE_EXCLAMATION );+ }++ RenderSimpleSourceView();+ }+ else+ {+ RenderSymbolView( worker, view );+ }+}++void SourceView::RenderSimpleSourceView()+{+ ImGui::SetNextWindowContentSize( ImVec2( m_srcWidth, 0 ) );+ ImGui::BeginChild( "##sourceView", ImVec2( 0, 0 ), true, ImGuiWindowFlags_HorizontalScrollbar );+ SetFont();++ auto& lines = m_source.get();+ auto draw = ImGui::GetWindowDrawList();+ const auto wpos = ImGui::GetWindowPos();+ const auto dpos = wpos + ImVec2( 0.5f, 0.5f );+ const auto wh = ImGui::GetWindowHeight();+ const auto ty = ImGui::GetTextLineHeight();+ const auto ts = ImGui::CalcTextSize( " " ).x;+ const auto lineCount = lines.size();+ const auto tmp = RealToString( lineCount );+ const auto maxLine = strlen( tmp );+ const auto lx = ts * maxLine + ty + round( ts*0.4f );+ DrawLine( draw, dpos + ImVec2( lx, 0 ), dpos + ImVec2( lx, wh ), 0x08FFFFFF );++ const AddrStatData zero;+ if( m_targetLine != 0 )+ {+ int lineNum = 1;+ for( auto& line : lines )+ {+ if( m_targetLine == lineNum )+ {+ m_targetLine = 0;+ ImGui::SetScrollHereY();+ }+ RenderLine( line, lineNum++, zero.ipMaxAsm, zero, nullptr, nullptr );+ }+ const auto win = ImGui::GetCurrentWindowRead();+ m_srcWidth = win->DC.CursorMaxPos.x - win->DC.CursorStartPos.x;+ }+ else+ {+ ImGuiListClipper clipper;+ clipper.Begin( (int)lines.size() );+ while( clipper.Step() )+ {+ for( auto i=clipper.DisplayStart; i<clipper.DisplayEnd; i++ )+ {+ RenderLine( lines[i], i+1, zero.ipMaxAsm, zero, nullptr, nullptr );+ }+ }+ }++ UnsetFont();+ ImGui::EndChild();+}++void SourceView::RenderSymbolView( Worker& worker, View& view )+{+ assert( m_symAddr != 0 );++ const auto shortenName = view.GetShortenName();+ auto sym = worker.GetSymbolData( m_symAddr );+ assert( sym );+ ImGui::PushFont( m_bigFont );+ ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 0, 0 ) );+ if( ButtonDisablable( " " ICON_FA_CARET_LEFT " ", m_historyCursor <= 1 ) )+ {+ m_historyCursor--;+ const auto& entry = m_history[m_historyCursor-1];+ OpenSymbol( entry.fileName, entry.line, entry.baseAddr, entry.symAddr, worker, view, false );+ }+ ImGui::SameLine( 0, 0 );+ if( ButtonDisablable( " " ICON_FA_CARET_RIGHT " ", m_historyCursor == m_history.size() ) )+ {+ m_historyCursor++;+ const auto& entry = m_history[m_historyCursor-1];+ OpenSymbol( entry.fileName, entry.line, entry.baseAddr, entry.symAddr, worker, view, false );+ }+ ImGui::PopStyleVar();+ ImGui::SameLine();+ if( sym->isInline )+ {+ auto parent = worker.GetSymbolData( m_baseAddr );+ if( parent )+ {+ const auto symName = worker.GetString( parent->name );+ if( shortenName == ShortenName::Never )+ {+ TextFocused( ICON_FA_PUZZLE_PIECE " Symbol:", symName );+ }+ else+ {+ const auto normalized = ShortenZoneName( ShortenName::OnlyNormalize, symName );+ TextFocused( ICON_FA_PUZZLE_PIECE " Symbol:", normalized );+ ImGui::PopFont();+ TooltipNormalizedName( symName, normalized );+ ImGui::PushFont( m_bigFont );+ }+ }+ else+ {+ char tmp[32];+ sprintf( tmp, "0x%" PRIx64, m_baseAddr );+ TextFocused( ICON_FA_PUZZLE_PIECE " Symbol:", tmp );+ }+ }+ else+ {+ const auto symName = worker.GetString( sym->name );+ if( shortenName == ShortenName::Never )+ {+ TextFocused( ICON_FA_PUZZLE_PIECE " Symbol:", symName );+ }+ else+ {+ const auto normalized = ShortenZoneName( ShortenName::OnlyNormalize, symName );+ TextFocused( ICON_FA_PUZZLE_PIECE " Symbol:", normalized );+ ImGui::PopFont();+ TooltipNormalizedName( symName, normalized );+ ImGui::PushFont( m_bigFont );+ }+ }+ ImGui::SameLine();+ ImGui::PopFont();++ auto inlineList = worker.GetInlineSymbolList( m_baseAddr, m_codeLen );+ const auto symEnd = m_baseAddr + m_codeLen;+ if( inlineList )+ {+ auto it = inlineList;+ while( *it < symEnd ) ++it;+ const auto inlineCount = it - inlineList;+ if( inlineCount > 0 )+ {+ ImGui::SameLine();+ ImGui::AlignTextToFramePadding();+ ImGui::TextDisabled( "(+%s inlined functions)", RealToString( inlineCount ) );+ }+ }+ ImGui::SameLine();+ ImGui::AlignTextToFramePadding();+ if( ImGui::SmallButton( ICON_FA_ARROW_DOWN_SHORT_WIDE " Entry stacks" ) ) view.ShowSampleParents( m_symAddr, !m_calcInlineStats );+ if( inlineList )+ {+ if( m_calcInlineStats )+ {+ ImGui::SameLine();+ ImGui::AlignTextToFramePadding();+ TextColoredUnformatted( ImVec4( 1.f, 1.f, 0.2f, 1.f ), ICON_FA_TRIANGLE_EXCLAMATION );+ TooltipIfHovered( "Context is limited to an inline function" );+ }+ }++ {+ const auto imageName = worker.GetString( sym->imageName );+ char tmp[1024];+ snprintf( tmp, 1024, "%s 0x%" PRIx64, imageName, m_baseAddr );+ ImGui::SameLine( ImGui::GetWindowContentRegionMax().x - ImGui::CalcTextSize( tmp ).x - ImGui::GetStyle().FramePadding.x * 2 );+ ImGui::AlignTextToFramePadding();+ TextDisabledUnformatted( tmp );+ }++ if( ImGui::IsKeyDown( ImGuiKey_Z ) ) m_childCalls = !m_childCalls;+ if( ImGui::IsKeyDown( ImGuiKey_X ) ) m_propagateInlines = !m_propagateInlines;++ const bool limitView = view.m_statRange.active;+ if( inlineList )+ {+ if( SmallCheckbox( ICON_FA_SITEMAP " Function:", &m_calcInlineStats ) )+ {+ m_asmTarget.line = 0;+ SelectLine( m_selectedLine, &worker, true, 0, false );+ }+ ImGui::SameLine();+ ImGui::SetNextItemWidth( -1 );+ ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 0, 0 ) );+ auto currSymName = m_symAddr == m_baseAddr ? "[ - self - ]" : worker.GetString( sym->name );+ if( shortenName != ShortenName::Never ) currSymName = ShortenZoneName( ShortenName::OnlyNormalize, currSymName );+ if( ImGui::BeginCombo( "##functionList", currSymName, ImGuiComboFlags_HeightLarge ) )+ {+ unordered_flat_map<uint64_t, uint32_t> symStat;+ if( limitView )+ {+ symStat.emplace( m_baseAddr, CountAsmIpStats( m_baseAddr, worker, true, view ) );+ auto ptr = inlineList;+ while( *ptr < symEnd )+ {+ symStat.emplace( *ptr, CountAsmIpStats( *ptr, worker, true, view ) );+ ptr++;+ }+ }+ else+ {+ const auto& ss = worker.GetSymbolStats();+ for( auto& v : ss ) symStat.emplace( v.first, v.second.excl );+ }++ uint32_t totalSamples = 0;+ Vector<std::pair<uint64_t, uint32_t>> symInline;+ auto baseStatIt = symStat.find( m_baseAddr );+ if( baseStatIt == symStat.end() || baseStatIt->second == 0 )+ {+ symInline.push_back( std::make_pair( m_baseAddr, 0 ) );+ }+ else+ {+ symInline.push_back( std::make_pair( m_baseAddr, baseStatIt->second ) );+ totalSamples += baseStatIt->second;+ }+ while( *inlineList < symEnd )+ {+ if( *inlineList != m_baseAddr )+ {+ auto statIt = symStat.find( *inlineList );+ if( statIt == symStat.end() || statIt->second == 0 )+ {+ symInline.push_back_non_empty( std::make_pair( *inlineList, 0 ) );+ }+ else+ {+ symInline.push_back_non_empty( std::make_pair( *inlineList, statIt->second ) );+ totalSamples += statIt->second;+ }+ }+ inlineList++;+ }+ pdqsort_branchless( symInline.begin(), symInline.end(), []( const auto& l, const auto& r ) { return l.second == r.second ? l.first < r.first : l.second > r.second; } );++ if( totalSamples == 0 )+ {+ ImGui::Columns( 2 );+ static bool widthSet = false;+ if( !widthSet )+ {+ widthSet = true;+ const auto w = ImGui::GetWindowWidth();+ const auto c1 = ImGui::CalcTextSize( "0xeeeeeeeeeeeeee" ).x;+ ImGui::SetColumnWidth( 0, w - c1 );+ ImGui::SetColumnWidth( 1, c1 );+ }+ }+ else+ {+ ImGui::Columns( 3 );+ static bool widthSet = false;+ if( !widthSet )+ {+ widthSet = true;+ const auto w = ImGui::GetWindowWidth();+ const auto c0 = ImGui::CalcTextSize( "12345678901234567890" ).x;+ const auto c2 = ImGui::CalcTextSize( "0xeeeeeeeeeeeeee" ).x;+ ImGui::SetColumnWidth( 0, c0 );+ ImGui::SetColumnWidth( 1, w - c0 - c2 );+ ImGui::SetColumnWidth( 2, c2 );+ }+ }+ for( auto& v : symInline )+ {+ if( totalSamples != 0 )+ {+ if( v.second != 0 )+ {+ ImGui::TextUnformatted( TimeToString( v.second * worker.GetSamplingPeriod() ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%.2f%%)", 100.f * v.second / totalSamples );+ if( ImGui::IsItemHovered() )+ {+ ImGui::BeginTooltip();+ TextFocused( "Sample count:", RealToString( v.second ) );+ ImGui::EndTooltip();+ }+ }+ ImGui::NextColumn();+ }+ auto isym = worker.GetSymbolData( v.first );+ assert( isym );+ const char* file;+ uint32_t line;+ if( isym->isInline )+ {+ file = worker.GetString( isym->callFile );+ line = isym->callLine;+ }+ else+ {+ file = worker.GetString( isym->file );+ line = isym->line;+ }+ ImGui::PushID( v.first );+ const auto symName = v.first == m_baseAddr ? "[ - self - ]" : worker.GetString( isym->name );+ const auto normalized = shortenName != ShortenName::Never ? ShortenZoneName( ShortenName::OnlyNormalize, symName ) : symName;+ const auto selected = ImGui::Selectable( "", v.first == m_symAddr, ImGuiSelectableFlags_SpanAllColumns );+ ImGui::SameLine( 0, 0 );+ ImGui::TextUnformatted( normalized );+ TooltipNormalizedName( symName, normalized );+ if( selected )+ {+ m_symAddr = v.first;+ ParseSource( file, worker, view );+ m_targetLine = line;+ SelectLine( line, &worker, true );+ SelectViewMode();+ }+ ImGui::PopID();+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::TextDisabled( "%s:%i", file, line );+ if( ImGui::IsItemHovered() && SourceFileValid( file, worker.GetCaptureTime(), view, worker ) )+ {+ m_sourceTooltip.Parse( file, worker, view );+ if( !m_sourceTooltip.empty() )+ {+ ImGui::BeginTooltip();+ SetFont();+ PrintSourceFragment( m_sourceTooltip, line, 4, 7 );+ UnsetFont();+ ImGui::EndTooltip();+ }+ }+ ImGui::NextColumn();+ ImGui::TextDisabled( "0x%" PRIx64, v.first );+ ImGui::NextColumn();+ }+ ImGui::EndColumns();+ ImGui::EndCombo();+ }+ ImGui::PopStyleVar();+ }++ TextDisabledUnformatted( "Mode:" );+ ImGui::SameLine();+ ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 0, 0 ) );+ if( !m_source.empty() )+ {+ ImGui::RadioButton( "Source", &m_displayMode, DisplaySource );+ if( !m_asm.empty() )+ {+ ImGui::SameLine();+ ImGui::RadioButton( "Assembly", &m_displayMode, DisplayAsm );+ ImGui::SameLine();+ ImGui::RadioButton( "Both", &m_displayMode, DisplayMixed );+ }+ }+ else+ {+ ImGui::RadioButton( "Assembly", &m_displayMode, DisplayAsm );+ }++ AddrStatData as;+ if( m_cost == CostType::SampleCount )+ {+ if( m_calcInlineStats )+ {+ GatherIpStats( m_symAddr, as, worker, limitView, view );+ GatherAdditionalIpStats( m_symAddr, as, worker, limitView, view );+ }+ else+ {+ GatherIpStats( m_baseAddr, as, worker, limitView, view );+ auto iptr = worker.GetInlineSymbolList( m_baseAddr, m_codeLen );+ if( iptr )+ {+ const auto symEnd = m_baseAddr + m_codeLen;+ while( *iptr < symEnd )+ {+ GatherIpStats( *iptr, as, worker, limitView, view );+ iptr++;+ }+ }+ GatherAdditionalIpStats( m_baseAddr, as, worker, limitView, view );+ }+ }+ else+ {+ GatherIpHwStats( as, worker, view, m_cost );+ }+ if( !m_calcInlineStats )+ {+ as.ipTotalSrc = as.ipTotalAsm;+ }+ if( m_hwSamplesRelative )+ {+ CountHwStats( as, worker, view );+ }+ const auto samplesReady = worker.AreSymbolSamplesReady();+ if( ( as.ipTotalAsm.local + as.ipTotalAsm.ext ) > 0 || ( view.m_statRange.active && worker.GetSamplesForSymbol( m_baseAddr ) ) )+ {+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ if( worker.GetHwSampleCountAddress() != 0 )+ {+ SmallCheckbox( ICON_FA_HAMMER " HW", &m_hwSamples );+ ImGui::SameLine();+ SmallCheckbox( ICON_FA_CAR_BURST " Impact", &m_hwSamplesRelative );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::TextUnformatted( ICON_FA_HIGHLIGHTER " Cost" );+ ImGui::SameLine();+ float mw = 0;+ for( auto& v : s_CostName )+ {+ const auto w = ImGui::CalcTextSize( v ).x;+ if( w > mw ) mw = w;+ }+ ImGui::SetNextItemWidth( mw + ImGui::GetTextLineHeight() );+ ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 0, 0 ) );+ if( ImGui::BeginCombo( "##cost", s_CostName[(int)m_cost], ImGuiComboFlags_HeightLarge ) )+ {+ int idx = 0;+ for( auto& v : s_CostName )+ {+ if( ImGui::Selectable( v, idx == (int)m_cost ) )+ {+ m_cost = (CostType)idx;++ if( m_cost == CostType::SlowBranches && !worker.HasHwBranchRetirement() )+ {+ m_cost = CostType::BranchMiss;+ }+ }+ if( (CostType)idx == s_costSeparateAfter ) ImGui::Separator();+ idx++;+ }+ ImGui::EndCombo();+ }+ ImGui::PopStyleVar();+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ }+ if( m_cost == CostType::SampleCount )+ {+ if( !samplesReady )+ {+ ImGui::PushItemFlag( ImGuiItemFlags_Disabled, true );+ ImGui::PushStyleVar( ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f );+ m_childCalls = false;+ m_childCallList = false;+ m_propagateInlines = false;+ }+ SmallCheckbox( ICON_FA_RIGHT_FROM_BRACKET " Child calls", &m_childCalls );+ if( !samplesReady )+ {+ ImGui::PopStyleVar();+ ImGui::PopItemFlag();+ TooltipIfHovered( "Please wait, processing data..." );+ }+ else+ {+ TooltipIfHovered( "Press Z key to temporarily reverse selection." );+ }+ ImGui::SameLine();+ if( ImGui::SmallButton( m_childCallList ? " " ICON_FA_CARET_UP " " : " " ICON_FA_CARET_DOWN " " ) ) m_childCallList = !m_childCallList;+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ if( m_childCalls )+ {+ TextFocused( ICON_FA_STOPWATCH " Time:", TimeToString( ( as.ipTotalAsm.local + as.ipTotalAsm.ext ) * worker.GetSamplingPeriod() ) );+ }+ else+ {+ TextFocused( ICON_FA_STOPWATCH " Time:", TimeToString( as.ipTotalAsm.local * worker.GetSamplingPeriod() ) );+ }+ if( as.ipTotalAsm.ext )+ {+ ImGui::SameLine();+ ImGui::TextDisabled( "(%c%s)", m_childCalls ? '-' : '+', TimeToString( as.ipTotalAsm.ext * worker.GetSamplingPeriod() ) );+ TooltipIfHovered( "Child call samples" );+ }+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ if( m_childCalls )+ {+ TextFocused( ICON_FA_EYE_DROPPER " Samples:", RealToString( as.ipTotalAsm.local + as.ipTotalAsm.ext ) );+ }+ else+ {+ TextFocused( ICON_FA_EYE_DROPPER " Samples:", RealToString( as.ipTotalAsm.local ) );+ }+ if( as.ipTotalAsm.ext )+ {+ ImGui::SameLine();+ ImGui::Text( "(%c%s)", m_childCalls ? '-' : '+', RealToString( as.ipTotalAsm.ext ) );+ TooltipIfHovered( "Child call samples" );+ }+ }+ else+ {+ TextFocused( "Events:", RealToString( as.ipTotalAsm.local ) );+ m_childCallList = false;+ }+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ if( !worker.AreSymbolSamplesReady() )+ {+ view.m_statRange.active = false;+ bool val = false;+ ImGui::PushItemFlag( ImGuiItemFlags_Disabled, true );+ ImGui::PushStyleVar( ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f );+ ImGui::Checkbox( "Limit range", &val );+ ImGui::PopItemFlag();+ ImGui::PopStyleVar();+ TooltipIfHovered( "Please wait, processing data..." );+ }+ else+ {+ if( ImGui::Checkbox( "Limit range", &view.m_statRange.active ) )+ {+ if( view.m_statRange.active && view.m_statRange.min == 0 && view.m_statRange.max == 0 )+ {+ const auto& vd = view.GetViewData();+ view.m_statRange.min = vd.zvStart;+ view.m_statRange.max = vd.zvEnd;+ }+ }+ if( view.m_statRange.active )+ {+ ImGui::SameLine();+ TextColoredUnformatted( 0xFF00FFFF, ICON_FA_TRIANGLE_EXCLAMATION );+ ImGui::SameLine();+ ToggleButton( ICON_FA_RULER " Limits", view.m_showRanges );+ }+ }+ }+ else+ {+ m_cost = CostType::SampleCount;+ }++ ImGui::PopStyleVar();+ ImGui::Separator();++ if( m_childCallList )+ {+ unordered_flat_map<uint64_t, uint32_t> map;+ if( m_calcInlineStats )+ {+ GatherChildStats( m_symAddr, map, worker, limitView, view );+ }+ else+ {+ GatherChildStats( m_baseAddr, map, worker, limitView, view );+ }+ if( !map.empty() )+ {+ TextDisabledUnformatted( "Child call distribution" );+ if( ImGui::BeginChild( "ccd", ImVec2( 0, ImGui::GetTextLineHeight() * std::min<size_t>( 4, map.size() ) + ImGui::GetStyle().WindowPadding.y ) ) )+ {+ std::vector<ChildStat> vec;+ vec.reserve( map.size() );+ for( auto& v : map ) vec.emplace_back( ChildStat { v.first, v.second } );+ pdqsort_branchless( vec.begin(), vec.end(), []( const auto& lhs, const auto& rhs ) { return lhs.count > rhs.count; } );+ int idx = 1;+ for( auto& v : vec )+ {+ ImGui::TextDisabled( "%i.", idx++ );+ ImGui::SameLine();+ auto sd = worker.GetSymbolData( v.addr );+ const auto symName = sd ? worker.GetString( sd->name ) : "[unknown]";+ if( v.addr >> 63 == 0 )+ {+ if( shortenName == ShortenName::Never )+ {+ ImGui::TextUnformatted( symName );+ }+ else+ {+ const auto normalized = ShortenZoneName( ShortenName::OnlyNormalize, symName );+ ImGui::TextUnformatted( normalized );+ TooltipNormalizedName( symName, normalized );+ }+ }+ else+ {+ TextColoredUnformatted( 0xFF8888FF, symName );+ }+ ImGui::SameLine();+ char tmp[16];+ auto end = PrintFloat( tmp, tmp+16, 100.f * v.count / as.ipTotalAsm.ext, 2 );+ *end = '\0';+ ImGui::TextDisabled( "%s (%s%%)", TimeToString( v.count * worker.GetSamplingPeriod() ), tmp );+ if( ImGui::IsItemHovered() )+ {+ ImGui::BeginTooltip();+ ImGui::Text( "%s samples", RealToString( v.count ) );+ ImGui::EndTooltip();+ }+ if( sd && sd->line != 0 )+ {+ const auto fileName = worker.GetString( sd->file );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::TextDisabled( "%s:%i", fileName, sd->line );+ if( ImGui::IsItemHovered() && SourceFileValid( fileName, worker.GetCaptureTime(), view, worker ) )+ {+ m_sourceTooltip.Parse( fileName, worker, view );+ if( !m_sourceTooltip.empty() )+ {+ ImGui::BeginTooltip();+ SetFont();+ PrintSourceFragment( m_sourceTooltip, sd->line, 4, 7 );+ UnsetFont();+ ImGui::EndTooltip();+ }+ if( ImGui::IsMouseClicked( 1 ) )+ {+ OpenSymbol( fileName, sd->line, v.addr, v.addr, worker, view );+ }+ }+ }+ }+ }+ ImGui::EndChild();+ ImGui::Separator();+ }+ }++ uint64_t jumpOut = 0;+ switch( m_displayMode )+ {+ case DisplaySource:+ RenderSymbolSourceView( as, worker, view, inlineList != nullptr );+ break;+ case DisplayAsm:+ jumpOut = RenderSymbolAsmView( as, worker, view );+ break;+ case DisplayMixed:+ ImGui::Columns( 2 );+ RenderSymbolSourceView( as, worker, view, inlineList != nullptr );+ ImGui::NextColumn();+ jumpOut = RenderSymbolAsmView( as, worker, view );+ ImGui::EndColumns();+ break;+ default:+ assert( false );+ break;+ }++ if( ImGui::IsKeyDown( ImGuiKey_Z ) ) m_childCalls = !m_childCalls;+ if( ImGui::IsKeyDown( ImGuiKey_X ) ) m_propagateInlines = !m_propagateInlines;++ if( jumpOut != 0 )+ {+ auto sym = worker.GetSymbolData( jumpOut );+ if( sym )+ {+ auto line = sym->line;+ auto file = line == 0 ? nullptr : worker.GetString( sym->file );+ if( file && !SourceFileValid( file, worker.GetCaptureTime(), view, worker ) )+ {+ file = nullptr;+ line = 0;+ }+ if( line > 0 || sym->size.Val() > 0 )+ {+ OpenSymbol( file, line, jumpOut, jumpOut, worker, view );+ }+ }+ }+}++static uint32_t GetHotnessColor( uint32_t count, uint32_t maxCount )+{+ const auto ratio = float( 2 * count ) / maxCount;+ if( ratio <= 0.5f )+ {+ const auto a = int( ( ratio * 1.5f + 0.25f ) * 255 );+ return 0x000000FF | ( a << 24 );+ }+ else if( ratio <= 1.f )+ {+ const auto g = int( ( ratio - 0.5f ) * 511 );+ return 0xFF0000FF | ( g << 8 );+ }+ else if( ratio <= 2.f )+ {+ const auto b = int( ( ratio - 1.f ) * 255 );+ return 0xFF00FFFF | ( b << 16 );+ }+ else+ {+ return 0xFFFFFFFF;+ }+}++static uint32_t GetHotnessGlow( uint32_t count, uint32_t maxCount )+{+ const auto ratio = float( 2 * count ) / maxCount;+ if( ratio <= 0.5f )+ {+ return 0;+ }+ else if( ratio <= 1.f )+ {+ const auto a = int( ( ratio * 2.f - 1.f ) * 102 );+ return 0x000000FF | ( a << 24 );+ }+ else if( ratio <= 2.f )+ {+ const auto g = int( ( ratio - 1.f ) * 192 );+ return 0x660000FF | ( g << 8 );+ }+ else+ {+ return 0x6600C0FF;+ }+}++static constexpr uint32_t GoodnessColor[256] = {+ 0xFF3232FF, 0xFF3235FE, 0xFF3238FE, 0xFF323AFD, 0xFF323DFD, 0xFF323FFC, 0xFF3242FC, 0xFF3244FB,+ 0xFF3246FB, 0xFF3248FB, 0xFF324AFA, 0xFF324CFA, 0xFF324EF9, 0xFF3250F9, 0xFF3252F8, 0xFF3254F8,+ 0xFF3255F8, 0xFF3257F7, 0xFF3259F7, 0xFF325AF6, 0xFF325CF6, 0xFF325EF5, 0xFF325FF5, 0xFF3260F4,+ 0xFF3262F4, 0xFF3263F3, 0xFF3265F3, 0xFF3266F3, 0xFF3268F2, 0xFF3269F2, 0xFF326AF1, 0xFF326BF1,+ 0xFF326DF0, 0xFF326EF0, 0xFF326FEF, 0xFF3270EF, 0xFF3272EE, 0xFF3273EE, 0xFF3274EE, 0xFF3275ED,+ 0xFF3276ED, 0xFF3277EC, 0xFF3279EC, 0xFF327AEB, 0xFF327BEB, 0xFF327CEA, 0xFF327DEA, 0xFF327EE9,+ 0xFF327FE9, 0xFF3280E8, 0xFF3281E8, 0xFF3282E7, 0xFF3283E7, 0xFF3284E6, 0xFF3285E6, 0xFF3286E5,+ 0xFF3287E5, 0xFF3288E4, 0xFF3289E4, 0xFF328AE3, 0xFF328BE3, 0xFF328CE2, 0xFF328DE2, 0xFF328EE1,+ 0xFF328EE1, 0xFF328FE0, 0xFF3290E0, 0xFF3291DF, 0xFF3292DF, 0xFF3293DE, 0xFF3294DE, 0xFF3295DD,+ 0xFF3295DD, 0xFF3296DC, 0xFF3297DC, 0xFF3298DB, 0xFF3299DB, 0xFF329ADA, 0xFF329ADA, 0xFF329BD9,+ 0xFF329CD9, 0xFF329DD8, 0xFF329ED8, 0xFF329ED7, 0xFF329FD7, 0xFF32A0D6, 0xFF32A1D5, 0xFF32A2D5,+ 0xFF32A2D4, 0xFF32A3D4, 0xFF32A4D3, 0xFF32A5D3, 0xFF32A5D2, 0xFF32A6D2, 0xFF32A7D1, 0xFF32A8D1,+ 0xFF32A8D0, 0xFF32A9CF, 0xFF32AACF, 0xFF32AACE, 0xFF32ABCE, 0xFF32ACCD, 0xFF32ADCD, 0xFF32ADCC,+ 0xFF32AECC, 0xFF32AFCB, 0xFF32AFCA, 0xFF32B0CA, 0xFF32B1C9, 0xFF32B1C9, 0xFF32B2C8, 0xFF32B3C7,+ 0xFF32B3C7, 0xFF32B4C6, 0xFF32B5C6, 0xFF32B5C5, 0xFF32B6C5, 0xFF32B7C4, 0xFF32B7C3, 0xFF32B8C3,+ 0xFF32B9C2, 0xFF32B9C2, 0xFF32BAC1, 0xFF32BBC0, 0xFF32BBC0, 0xFF32BCBF, 0xFF32BDBE, 0xFF32BDBE,+ 0xFF32BEBD, 0xFF32BEBD, 0xFF32BFBC, 0xFF32C0BB, 0xFF32C0BB, 0xFF32C1BA, 0xFF32C2B9, 0xFF32C2B9,+ 0xFF32C3B8, 0xFF32C3B7, 0xFF32C4B7, 0xFF32C5B6, 0xFF32C5B5, 0xFF32C6B5, 0xFF32C6B4, 0xFF32C7B3,+ 0xFF32C7B3, 0xFF32C8B2, 0xFF32C9B1, 0xFF32C9B1, 0xFF32CAB0, 0xFF32CAAF, 0xFF32CBAF, 0xFF32CCAE,+ 0xFF32CCAD, 0xFF32CDAD, 0xFF32CDAC, 0xFF32CEAB, 0xFF32CEAA, 0xFF32CFAA, 0xFF32CFA9, 0xFF32D0A8,+ 0xFF32D1A8, 0xFF32D1A7, 0xFF32D2A6, 0xFF32D2A5, 0xFF32D3A5, 0xFF32D3A4, 0xFF32D4A3, 0xFF32D4A2,+ 0xFF32D5A2, 0xFF32D5A1, 0xFF32D6A0, 0xFF32D79F, 0xFF32D79E, 0xFF32D89E, 0xFF32D89D, 0xFF32D99C,+ 0xFF32D99B, 0xFF32DA9A, 0xFF32DA9A, 0xFF32DB99, 0xFF32DB98, 0xFF32DC97, 0xFF32DC96, 0xFF32DD95,+ 0xFF32DD95, 0xFF32DE94, 0xFF32DE93, 0xFF32DF92, 0xFF32DF91, 0xFF32E090, 0xFF32E08F, 0xFF32E18E,+ 0xFF32E18E, 0xFF32E28D, 0xFF32E28C, 0xFF32E38B, 0xFF32E38A, 0xFF32E489, 0xFF32E488, 0xFF32E587,+ 0xFF32E586, 0xFF32E685, 0xFF32E684, 0xFF32E783, 0xFF32E782, 0xFF32E881, 0xFF32E880, 0xFF32E97F,+ 0xFF32E97E, 0xFF32EA7D, 0xFF32EA7C, 0xFF32EB7B, 0xFF32EB7A, 0xFF32EC79, 0xFF32EC77, 0xFF32ED76,+ 0xFF32ED75, 0xFF32EE74, 0xFF32EE73, 0xFF32EE72, 0xFF32EF70, 0xFF32EF6F, 0xFF32F06E, 0xFF32F06D,+ 0xFF32F16B, 0xFF32F16A, 0xFF32F269, 0xFF32F268, 0xFF32F366, 0xFF32F365, 0xFF32F363, 0xFF32F462,+ 0xFF32F460, 0xFF32F55F, 0xFF32F55E, 0xFF32F65C, 0xFF32F65A, 0xFF32F759, 0xFF32F757, 0xFF32F855,+ 0xFF32F854, 0xFF32F852, 0xFF32F950, 0xFF32F94E, 0xFF32FA4C, 0xFF32FA4A, 0xFF32FB48, 0xFF32FB46,+ 0xFF32FB44, 0xFF32FC42, 0xFF32FC3F, 0xFF32FD3D, 0xFF32FD3A, 0xFF32FE38, 0xFF32FE35, 0xFF32FF32,+};++static uint32_t GetGoodnessColor( float inRatio )+{+ const auto ratio = std::clamp( int( inRatio * 255.f ), 0, 255 );+ return GoodnessColor[ratio];+}++void SourceView::RenderSymbolSourceView( const AddrStatData& as, Worker& worker, const View& view, bool hasInlines )+{+ const auto scale = GetScale();+ if( hasInlines && !m_calcInlineStats && ( ( as.ipTotalAsm.local + as.ipTotalAsm.ext ) > 0 || ( view.m_statRange.active && worker.GetSamplesForSymbol( m_baseAddr ) ) ) )+ {+ const auto samplesReady = worker.AreSymbolSamplesReady();+ if( !samplesReady )+ {+ ImGui::PushItemFlag( ImGuiItemFlags_Disabled, true );+ ImGui::PushStyleVar( ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f );+ }+ SmallCheckbox( ICON_FA_ARROWS_TURN_TO_DOTS " Propagate inlines", &m_propagateInlines );+ if( !samplesReady )+ {+ ImGui::PopStyleVar();+ ImGui::PopItemFlag();+ TooltipIfHovered( "Please wait, processing data..." );+ }+ else+ {+ TooltipIfHovered( "Press X key to temporarily reverse selection." );+ }+ ImGui::SameLine();+ ImGui::SeparatorEx( ImGuiSeparatorFlags_Vertical );+ ImGui::SameLine();+ }+ if( m_sourceFiles.empty() )+ {+ if( m_source.is_cached() )+ {+ TextColoredUnformatted( ImVec4( 0.4f, 0.8f, 0.4f, 1.f ), ICON_FA_DATABASE );+ ImGui::SameLine();+ ImGui::TextUnformatted( "Source file cached during profiling run" );+ }+ else+ {+ TextColoredUnformatted( ImVec4( 1.f, 1.f, 0.2f, 1.f ), ICON_FA_TRIANGLE_EXCLAMATION );+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 1.f, 0.3f, 0.3f, 1.f ), "The source file contents might not reflect the actual profiled code!" );+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 1.f, 1.f, 0.2f, 1.f ), ICON_FA_TRIANGLE_EXCLAMATION );+ }+ }+ else+ {+ if( m_source.is_cached() )+ {+ TextColoredUnformatted( ImVec4( 0.4f, 0.8f, 0.4f, 1.f ), ICON_FA_DATABASE );+ TooltipIfHovered( "Source file cached during profiling run" );+ }+ else+ {+ TextColoredUnformatted( ImVec4( 1.f, 1.f, 0.2f, 1.f ), ICON_FA_TRIANGLE_EXCLAMATION );+ if( ImGui::IsItemHovered() )+ {+ ImGui::BeginTooltip();+ TextColoredUnformatted( ImVec4( 1.f, 1.f, 0.2f, 1.f ), ICON_FA_TRIANGLE_EXCLAMATION );+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 1.f, 0.3f, 0.3f, 1.f ), "The source file contents might not reflect the actual profiled code!" );+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 1.f, 1.f, 0.2f, 1.f ), ICON_FA_TRIANGLE_EXCLAMATION );+ ImGui::EndTooltip();+ }+ }+ ImGui::SameLine();+ TextDisabledUnformatted( ICON_FA_FILE " File:" );+ ImGui::SameLine();+ const auto fileColor = GetHsvColor( m_source.idx(), 0 );+ SmallColorBox( fileColor );+ ImGui::SameLine();+ ImGui::SetNextItemWidth( -1 );+ ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 0, 0 ) );+ if( ImGui::BeginCombo( "##fileList", m_source.filename(), ImGuiComboFlags_HeightLarge ) )+ {+ if( m_asm.empty() )+ {+ for( auto& v : m_sourceFiles )+ {+ const auto color = GetHsvColor( v.first, 0 );+ SmallColorBox( color );+ ImGui::SameLine();+ auto fstr = worker.GetString( StringIdx( v.first ) );+ if( SourceFileValid( fstr, worker.GetCaptureTime(), view, worker ) )+ {+ ImGui::PushID( v.first );+ if( ImGui::Selectable( fstr, fstr == m_source.filename() ) )+ {+ ParseSource( fstr, worker, view );+ m_targetLine = v.second;+ SelectLine( v.second, &worker );+ }+ ImGui::PopID();+ }+ else+ {+ TextDisabledUnformatted( fstr );+ }+ }+ }+ else+ {+ AddrStat totalSamples = {};+ unordered_flat_map<uint32_t, AddrStat> fileCounts;+ for( auto& v : m_asm )+ {+ uint32_t srcline;+ const auto srcidx = worker.GetLocationForAddress( v.addr, srcline );+ if( srcline != 0 )+ {+ AddrStat cnt = {};+ auto ait = as.ipCountAsm.find( v.addr );+ if( ait != as.ipCountAsm.end() ) cnt = ait->second;++ auto fit = fileCounts.find( srcidx.Idx() );+ if( fit == fileCounts.end() )+ {+ fileCounts.emplace( srcidx.Idx(), cnt );+ }+ else+ {+ fit->second += cnt;+ }+ totalSamples += cnt;+ }+ }+ std::vector<std::pair<uint32_t, AddrStat>> fileCountsVec;+ fileCountsVec.reserve( fileCounts.size() );+ for( auto& v : fileCounts ) fileCountsVec.emplace_back( v.first, v.second );+ if( m_childCalls )+ {+ pdqsort_branchless( fileCountsVec.begin(), fileCountsVec.end(), [&worker] (const auto& l, const auto& r ) { return ( l.second.local + l.second.ext == r.second.local + r.second.ext ) ? strcmp( worker.GetString( l.first ), worker.GetString( r.first ) ) < 0 : ( l.second.local + l.second.ext > r.second.local + r.second.ext ); } );+ }+ else+ {+ pdqsort_branchless( fileCountsVec.begin(), fileCountsVec.end(), [&worker] (const auto& l, const auto& r ) { return l.second.local == r.second.local ? strcmp( worker.GetString( l.first ), worker.GetString( r.first ) ) < 0 : l.second.local > r.second.local; } );+ }++ const auto hasSamples = totalSamples.local + totalSamples.ext != 0;+ if( hasSamples )+ {+ ImGui::Columns( 2 );+ static bool widthSet = false;+ if( !widthSet )+ {+ widthSet = true;+ const auto c0 = ImGui::CalcTextSize( "12345678901234567890" ).x;+ ImGui::SetColumnWidth( 0, c0 );+ }+ }+ for( auto& v : fileCountsVec )+ {+ if( hasSamples )+ {+ auto fit = fileCounts.find( v.first );+ assert( fit != fileCounts.end() );+ if( fit->second.local + fit->second.ext != 0 )+ {+ if( m_cost == CostType::SampleCount )+ {+ if( m_childCalls )+ {+ ImGui::TextUnformatted( TimeToString( ( fit->second.local + fit->second.ext ) * worker.GetSamplingPeriod() ) );+ }+ else+ {+ ImGui::TextUnformatted( TimeToString( fit->second.local * worker.GetSamplingPeriod() ) );+ }+ if( ImGui::IsItemHovered() )+ {+ ImGui::BeginTooltip();+ if( fit->second.local )+ {+ TextFocused( "Local time:", TimeToString( fit->second.local * worker.GetSamplingPeriod() ) );+ TextFocused( "Local samples:", RealToString( fit->second.local ) );+ }+ if( fit->second.ext )+ {+ TextFocused( "Child time:", TimeToString( fit->second.ext * worker.GetSamplingPeriod() ) );+ TextFocused( "Child samples:", RealToString( fit->second.ext ) );+ }+ ImGui::EndTooltip();+ }+ }+ else+ {+ ImGui::TextUnformatted( RealToString( fit->second.local ) );+ }+ ImGui::SameLine();+ if( m_childCalls )+ {+ ImGui::TextDisabled( "(%.2f%%)", 100.f * ( fit->second.local + fit->second.ext ) / ( totalSamples.local + totalSamples.ext ) );+ }+ else if( totalSamples.local != 0 )+ {+ ImGui::TextDisabled( "(%.2f%%)", 100.f * fit->second.local / totalSamples.local );+ }+ else+ {+ TextDisabledUnformatted( "(0.00%%)" );+ }+ }+ ImGui::NextColumn();+ }+ const auto color = GetHsvColor( v.first, 0 );+ SmallColorBox( color );+ ImGui::SameLine();+ auto fstr = worker.GetString( StringIdx( v.first ) );+ if( SourceFileValid( fstr, worker.GetCaptureTime(), view, worker ) )+ {+ ImGui::PushID( v.first );+ if( ImGui::Selectable( fstr, fstr == m_source.filename(), ImGuiSelectableFlags_SpanAllColumns ) )+ {+ uint32_t line = 0;+ for( auto& file : m_sourceFiles )+ {+ if( file.first == v.first )+ {+ line = file.second;+ break;+ }+ }+ ParseSource( fstr, worker, view );+ m_targetLine = line;+ SelectLine( line, &worker );+ }+ ImGui::PopID();+ }+ else+ {+ TextDisabledUnformatted( fstr );+ }+ if( hasSamples ) ImGui::NextColumn();+ }+ if( hasSamples ) ImGui::EndColumns();+ }+ ImGui::EndCombo();+ }+ ImGui::PopStyleVar();+ }++ const float bottom = m_srcSampleSelect.empty() ? 0 : ImGui::GetFrameHeight();+ ImGui::SetNextWindowContentSize( ImVec2( m_srcWidth, 0 ) );+ ImGui::BeginChild( "##sourceView", ImVec2( 0, -bottom ), true, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_HorizontalScrollbar );+ SetFont();++ auto& lines = m_source.get();++ {+ auto draw = ImGui::GetWindowDrawList();+ const auto wpos = ImGui::GetWindowPos() - ImVec2( ImGui::GetCurrentWindowRead()->Scroll.x, 0 );+ const auto dpos = wpos + ImVec2( 0.5f, 0.5f );+ const auto wh = ImGui::GetWindowHeight();+ const auto ty = ImGui::GetTextLineHeight();+ const auto ts = ImGui::CalcTextSize( " " ).x;+ const auto lineCount = lines.size();+ char buf[32];+ sprintf( buf, "%zu", lineCount );+ const auto maxLine = strlen( buf );+ auto lx = ts * maxLine + ty + round( ts*0.4f );+ if( as.ipTotalSrc.local + as.ipTotalSrc.ext != 0 ) lx += ts * 7 + ty;+ if( !m_asm.empty() )+ {+ sprintf( buf, "%zu", m_asm.size() );+ const auto maxAsm = strlen( buf ) + 1;+ lx += ts * maxAsm + ty;+ }+ if( m_hwSamples && worker.GetHwSampleCountAddress() != 0 ) lx += 15 * ts + ty;+ DrawLine( draw, dpos + ImVec2( lx, 0 ), dpos + ImVec2( lx, wh ), 0x08FFFFFF );+ }++ const AddrStatData zero;+ m_selectedAddressesHover.clear();+ if( m_targetLine != 0 )+ {+ int lineNum = 1;+ for( auto& line : lines )+ {+ if( m_targetLine == lineNum )+ {+ m_targetLine = 0;+ ImGui::SetScrollHereY();+ }+ RenderLine( line, lineNum++, zero.ipMaxAsm, as, &worker, &view );+ }+ const auto win = ImGui::GetCurrentWindowRead();+ m_srcWidth = win->DC.CursorMaxPos.x - win->DC.CursorStartPos.x;+ }+ else+ {+ ImGuiListClipper clipper;+ clipper.Begin( (int)lines.size() );+ while( clipper.Step() )+ {+ if( as.ipTotalSrc.local + as.ipTotalSrc.ext == 0 )+ {+ for( auto i=clipper.DisplayStart; i<clipper.DisplayEnd; i++ )+ {+ RenderLine( lines[i], i+1, zero.ipMaxAsm, zero, &worker, &view );+ }+ }+ else+ {+ for( auto i=clipper.DisplayStart; i<clipper.DisplayEnd; i++ )+ {+ auto it = as.ipCountSrc.find( i+1 );+ const auto ipcnt = it == as.ipCountSrc.end() ? zero.ipMaxAsm : it->second;+ RenderLine( lines[i], i+1, ipcnt, as, &worker, &view );+ }+ }+ }+ }++ const auto win = ImGui::GetCurrentWindowRead();+ if( win->ScrollbarY )+ {+ auto draw = ImGui::GetWindowDrawList();+ auto rect = ImGui::GetWindowScrollbarRect( win, ImGuiAxis_Y );+ ImGui::PushClipRect( rect.Min, rect.Max, false );+ if( m_selectedLine != 0 )+ {+ const auto ly = round( rect.Min.y + ( m_selectedLine - 0.5f ) / lines.size() * rect.GetHeight() );+ DrawLine( draw, ImVec2( rect.Min.x + 0.5f, ly + 0.5f ), ImVec2( rect.Max.x + 0.5f, ly + 0.5f ), 0x8899994C, 3 );+ }+ if( m_source.idx() == m_hoveredSource && m_hoveredLine != 0 )+ {+ const auto ly = round( rect.Min.y + ( m_hoveredLine - 0.5f ) / lines.size() * rect.GetHeight() );+ DrawLine( draw, ImVec2( rect.Min.x + 0.5f, ly + 0.5f ), ImVec2( rect.Max.x + 0.5f, ly + 0.5f ), 0x88888888, 3 );+ }++ std::vector<std::pair<uint64_t, AddrStat>> ipData;+ ipData.reserve( as.ipCountSrc.size() );+ for( auto& v : as.ipCountSrc ) ipData.emplace_back( v.first, v.second );+ for( uint32_t lineNum = 1; lineNum <= lines.size(); lineNum++ )+ {+ if( as.ipCountSrc.find( lineNum ) == as.ipCountSrc.end() )+ {+ auto addresses = GetAddressesForLocation( m_source.idx(), lineNum, worker );+ if( addresses )+ {+ for( auto& addr : *addresses )+ {+ if( addr >= m_baseAddr && addr < m_baseAddr + m_codeLen )+ {+ ipData.emplace_back( lineNum, AddrStat {} );+ break;+ }+ }+ }+ }+ }+ pdqsort_branchless( ipData.begin(), ipData.end(), []( const auto& l, const auto& r ) { return l.first < r.first; } );++ const auto step = uint32_t( lines.size() * 2 / rect.GetHeight() );+ const auto x14 = round( rect.Min.x + rect.GetWidth() * 0.4f );+ const auto x34 = round( rect.Min.x + rect.GetWidth() * 0.6f );++ auto it = ipData.begin();+ while( it != ipData.end() )+ {+ const auto firstLine = it->first;+ AddrStat ipSum = {};+ while( it != ipData.end() && it->first <= firstLine + step )+ {+ ipSum += it->second;+ ++it;+ }+ const auto ly = round( rect.Min.y + float( firstLine ) / lines.size() * rect.GetHeight() );+ if( m_childCalls )+ {+ const auto color = ( ipSum.local + ipSum.ext == 0 ) ? 0x22FFFFFF : GetHotnessColor( ipSum.local + ipSum.ext, as.ipMaxSrc.local + as.ipMaxSrc.ext );+ draw->AddRectFilled( ImVec2( x14, ly ), ImVec2( x34, ly+3*scale ), color );+ }+ else+ {+ const auto color = ipSum.local == 0 ? 0x22FFFFFF : GetHotnessColor( ipSum.local, as.ipMaxSrc.local );+ draw->AddRectFilled( ImVec2( x14, ly ), ImVec2( x34, ly+3*scale ), color );+ }+ }++ ImGui::PopClipRect();+ }++ UnsetFont();+ ImGui::EndChild();++ if( !m_srcSampleSelect.empty() )+ {+ AddrStat count = {};+ uint32_t numLines = 0;+ for( auto& idx : m_srcSampleSelect )+ {+ auto it = as.ipCountSrc.find( idx );+ if( it != as.ipCountSrc.end() )+ {+ count += it->second;+ numLines++;+ }+ }++ ImGui::BeginChild( "##srcSelect" );+ if( ImGui::SmallButton( ICON_FA_XMARK ) )+ {+ m_srcSampleSelect.clear();+ m_srcGroupSelect = -1;+ }+ ImGui::SameLine();+ char buf[16];+ char* end;+ if( m_childCalls )+ {+ end = PrintFloat( buf, buf+16, 100.f * ( count.local + count.ext ) / ( as.ipTotalSrc.local + as.ipTotalSrc.ext ), 2 );+ }+ else if( as.ipTotalSrc.local != 0 )+ {+ end = PrintFloat( buf, buf+16, 100.f * count.local / as.ipTotalSrc.local, 2 );+ }+ else+ {+ end = PrintFloat( buf, buf+16, 0.f, 2 );+ }+ memcpy( end, "%", 2 );+ TextFocused( "Selected:", buf );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ if( m_cost == CostType::SampleCount )+ {+ int64_t time;+ if( m_childCalls )+ {+ time = ( count.local + count.ext ) * worker.GetSamplingPeriod();+ }+ else+ {+ time = count.local * worker.GetSamplingPeriod();+ }+ TextFocused( "Time:", TimeToString( time ) );+ const auto timePct = 100.f * time / worker.GetLastTime();+ if( timePct >= 0.01f )+ {+ ImGui::SameLine();+ ImGui::TextDisabled( "(%.2f%% run time)", timePct );+ }+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ if( m_childCalls )+ {+ TextFocused( "Sample count:", RealToString( count.local + count.ext ) );+ }+ else+ {+ TextFocused( "Sample count:", RealToString( count.local ) );+ }+ }+ else+ {+ TextFocused( "Events:", RealToString( count.local ) );+ }+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ TextFocused( "Lines:", RealToString( numLines ) );+ ImGui::EndChild();+ }+}++static constexpr char HexPrint[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };++static int FormatHexBytesRaw( char* buf, const uint8_t* bytes, size_t len )+{+ const auto start = buf;+ for( size_t i=0; i<len; i++ )+ {+ const auto byte = bytes[i];+ *buf++ = HexPrint[byte >> 4];+ *buf++ = HexPrint[byte & 0xF];+ *buf++ = ' ';+ }+ *--buf = '\0';+ return buf - start;+}++static int PrintHexBytesRaw( const uint8_t* bytes, size_t len )+{+ char buf[2];+ bool first = true;+ for( size_t i=0; i<len; i++ )+ {+ if( first ) first = false;+ else ImGui::SameLine( 0, 0 );+ const auto byte = bytes[i];+ buf[0] = HexPrint[byte >> 4];+ buf[1] = HexPrint[byte & 0xF];+ TextColoredUnformatted( (i%2 == 0) ? 0xFFFFBBBB : 0xFFBB7777, buf, buf+2 );+ }+ return len * 2;+}++static int PrintHexBytesArm( const uint8_t* bytes )+{+ char buf[2];+ bool first = true;+ for( int i=3; i>=0; i-- )+ {+ if( first ) first = false;+ else ImGui::SameLine( 0, 0 );+ const auto byte = bytes[i];+ buf[0] = HexPrint[byte >> 4];+ buf[1] = HexPrint[byte & 0xF];+ TextColoredUnformatted( (i%2 != 0) ? 0xFFFFBBBB : 0xFFBB7777, buf, buf+2 );+ }+ return 8;+}++static int PrintHexBytes( const uint8_t* bytes, size_t len, CpuArchitecture arch )+{+ switch( arch )+ {+ case CpuArchX86:+ case CpuArchX64:+ return PrintHexBytesRaw( bytes, len );+ case CpuArchArm32:+ case CpuArchArm64:+ assert( len == 4 );+ return PrintHexBytesArm( bytes );+ default:+ assert( false );+ return 0;+ }+}++uint64_t SourceView::RenderSymbolAsmView( const AddrStatData& as, Worker& worker, View& view )+{+ const auto scale = GetScale();+ if( m_disasmFail >= 0 )+ {+ TextColoredUnformatted( ImVec4( 1.f, 1.f, 0.2f, 1.f ), ICON_FA_TRIANGLE_EXCLAMATION );+ if( ImGui::IsItemHovered() )+ {+ const bool clicked = ImGui::IsItemClicked();+ ImGui::BeginTooltip();+ TextColoredUnformatted( ImVec4( 1, 0, 0, 1 ), "Disassembly failure." );+ ImGui::TextUnformatted( "Some instructions weren't properly decoded. Possible reasons:" );+ ImGui::TextUnformatted( " 1. Old version of capstone library doesn't support some instructions." );+ ImGui::TextUnformatted( " 2. Trying to decode data part of the symbol (e.g. jump arrays, etc.)" );+ TextFocused( "Code size:", RealToString( m_codeLen ) );+ TextFocused( "Disassembled bytes:", RealToString( m_disasmFail ) );+ char tmp[64];+ auto bytesLeft = std::min( 16u, m_codeLen - m_disasmFail );+ auto code = worker.GetSymbolCode( m_baseAddr, m_codeLen );+ assert( code );+ FormatHexBytesRaw( tmp, (const uint8_t*)code, bytesLeft );+ TextFocused( "Failure bytes:", tmp );+ TextDisabledUnformatted( "Click to copy to clipboard." );+ ImGui::EndTooltip();+ if( clicked ) ImGui::SetClipboardText( tmp );+ }+ ImGui::SameLine();+ }+ SmallCheckbox( ICON_FA_MAGNIFYING_GLASS_LOCATION " Relative", &m_asmRelative );+ if( !m_sourceFiles.empty() )+ {+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ SmallCheckbox( ICON_FA_FILE_IMPORT " Source", &m_asmShowSourceLocation );+ }+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ SmallCheckbox( ICON_FA_GEARS " Raw code", &m_asmBytes );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ SmallCheckbox( ICON_FA_SHARE " Jumps", &m_showJumps );++ if( m_cpuArch == CpuArchX64 || m_cpuArch == CpuArchX86 )+ {+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ float mw = 0;+ for( auto& v : s_uArchUx )+ {+ const auto w = ImGui::CalcTextSize( v.uArch ).x;+ if( w > mw ) mw = w;+ }+ if( m_selMicroArch == m_profileMicroArch )+ {+ TextColoredUnformatted( ImVec4( 0.4f, 0.8f, 0.4f, 1.f ), ICON_FA_MICROCHIP );+ TooltipIfHovered( "Selected microarchitecture is the same as the profiled application was running on" );+ }+ else+ {+ TextColoredUnformatted( ImVec4( 1.f, 0.3f, 0.3f, 1.f ), ICON_FA_MICROCHIP );+ if( ImGui::IsItemHovered() )+ {+ const bool clicked = ImGui::IsItemClicked();+ ImGui::BeginTooltip();+ ImGui::TextUnformatted( "Selected microarchitecture does not match the one profiled application was running on" );+ if( m_profileMicroArch >= 0 )+ {+ ImGui::Text( "Measurements were performed on the %s microarchitecture", s_uArchUx[m_profileMicroArch].uArch );+ if( clicked ) SelectMicroArchitecture( s_uArchUx[m_profileMicroArch].moniker );+ }+ else+ {+ ImGui::TextUnformatted( "Measurements were performed on an unknown microarchitecture" );+ }+ ImGui::EndTooltip();+ }+ }+ ImGui::SameLine( 0, 0 );+ ImGui::TextUnformatted( " \xce\xbc""arch:" );+ ImGui::SameLine();+ ImGui::SetNextItemWidth( mw + ImGui::GetTextLineHeight() );+ ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 0, 0 ) );+ if( ImGui::BeginCombo( "##uarch", s_uArchUx[m_selMicroArch].uArch, ImGuiComboFlags_HeightLarge ) )+ {+ int idx = 0;+ for( auto& v : s_uArchUx )+ {+ if( ImGui::Selectable( v.uArch, idx == m_selMicroArch ) ) SelectMicroArchitecture( v.moniker );+ ImGui::SameLine();+ TextDisabledUnformatted( v.cpuName );+ idx++;+ }+ ImGui::EndCombo();+ }+ ImGui::PopStyleVar();+ }++ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ TextFocused( ICON_FA_WEIGHT_HANGING, MemSizeToString( m_codeLen ) );+ TooltipIfHovered( "Code size" );++#ifndef TRACY_NO_FILESELECTOR+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ if( ImGui::SmallButton( ICON_FA_FILE_IMPORT " Save" ) )+ {+ Save( worker );+ }+#endif++ const float bottom = m_asmSampleSelect.empty() ? 0 : ImGui::GetFrameHeight();+ ImGui::SetNextWindowContentSize( ImVec2( m_asmWidth, 0 ) );+ ImGui::BeginChild( "##asmView", ImVec2( 0, -bottom ), true, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_HorizontalScrollbar );+ SetFont();++ int maxAddrLen;+ int maxAddrLenRel;+ {+ char tmp[32], tmp2[32];+ sprintf( tmp, "%" PRIx64, m_baseAddr + m_codeLen );+ maxAddrLen = strlen( tmp );+ sprintf( tmp, "%zu", m_asm.size() );+ sprintf( tmp2, "+%" PRIu32, m_codeLen );+ maxAddrLenRel = std::max( strlen( tmp ) + 3, strlen( tmp2 ) ); // +3: [-123]+ }++ uint64_t selJumpStart = 0;+ uint64_t selJumpEnd;+ uint64_t selJumpTarget;+ uint64_t jumpOut = 0;++ const AddrStatData zero;+ if( m_targetAddr != 0 )+ {+ for( auto& line : m_asm )+ {+ if( m_targetAddr == line.addr )+ {+ m_targetAddr = 0;+ ImGui::SetScrollHereY();+ }+ RenderAsmLine( line, zero.ipMaxAsm, as, worker, jumpOut, maxAddrLen, maxAddrLenRel, view );+ }+ const auto win = ImGui::GetCurrentWindowRead();+ m_asmWidth = win->DC.CursorMaxPos.x - win->DC.CursorStartPos.x;+ }+ else+ {+ const auto th = (int)ImGui::GetTextLineHeightWithSpacing();+ ImGuiListClipper clipper;+ clipper.Begin( (int)m_asm.size(), th );+ while( clipper.Step() )+ {+ const auto wpos = ImGui::GetCursorScreenPos();+ const auto dpos = wpos + ImVec2( 0.5f, 0.5f );+ static std::vector<uint64_t> insList;+ insList.clear();+ if( as.ipTotalAsm.local + as.ipTotalAsm.ext == 0 )+ {+ for( auto i=clipper.DisplayStart; i<clipper.DisplayEnd; i++ )+ {+ RenderAsmLine( m_asm[i], zero.ipMaxAsm, zero, worker, jumpOut, maxAddrLen, maxAddrLenRel, view );+ insList.emplace_back( m_asm[i].addr );+ const auto win = ImGui::GetCurrentWindowRead();+ const auto lineWidth = win->DC.CursorMaxPos.x - win->DC.CursorStartPos.x;+ if( lineWidth > m_asmWidth ) m_asmWidth = lineWidth;+ }+ }+ else+ {+ for( auto i=clipper.DisplayStart; i<clipper.DisplayEnd; i++ )+ {+ auto& line = m_asm[i];+ auto it = as.ipCountAsm.find( line.addr );+ const auto ipcnt = it == as.ipCountAsm.end() ? zero.ipMaxAsm : it->second;+ RenderAsmLine( line, ipcnt, as, worker, jumpOut, maxAddrLen, maxAddrLenRel, view );+ insList.emplace_back( line.addr );+ const auto win = ImGui::GetCurrentWindowRead();+ const auto lineWidth = win->DC.CursorMaxPos.x - win->DC.CursorStartPos.x;+ if( lineWidth > m_asmWidth ) m_asmWidth = lineWidth;+ }+ }+ if( m_showJumps && !m_jumpTable.empty() && clipper.DisplayStart != clipper.DisplayEnd )+ {+ auto draw = ImGui::GetWindowDrawList();+ const auto ts = ImGui::CalcTextSize( " " );+ const auto th2 = floor( ts.y / 2 );+ const auto th4 = floor( ts.y / 4 );+ const auto xoff = m_jumpOffset;+ const auto minAddr = m_asm[clipper.DisplayStart].addr;+ const auto maxAddr = m_asm[clipper.DisplayEnd-1].addr;+ const auto mjl = m_maxJumpLevel;+ const auto JumpArrow = JumpArrowBase * ts.y / 15;+ const auto JumpSeparation = CalcJumpSeparation( ts.y / 15 );++ int i = -1;+ for( auto& v : m_jumpTable )+ {+ i++;+ if( v.second.min > maxAddr || v.second.max < minAddr ) continue;+ const auto col = GetHsvColor( i, 0 );++ auto it0 = std::lower_bound( insList.begin(), insList.end(), v.second.min );+ auto it1 = std::lower_bound( insList.begin(), insList.end(), v.second.max );+ const auto y0 = ( it0 == insList.end() || *it0 != v.second.min ) ? -th : ( it0 - insList.begin() ) * th;+ const auto y1 = it1 == insList.end() ? ( insList.size() + 1 ) * th : ( it1 - insList.begin() ) * th;++ float thickness = m_highlightAddr == v.first ? 2 : 1;+ if( ImGui::IsWindowHovered() && ImGui::IsMouseHoveringRect( wpos + ImVec2( xoff + JumpSeparation * ( mjl - v.second.level ) - JumpSeparation / 2, y0 + th2 ), wpos + ImVec2( xoff + JumpSeparation * ( mjl - v.second.level ) + JumpSeparation / 2, y1 + th2 ) ) )+ {+ thickness = 2;+ const auto shortenName = view.GetShortenName();+ UnsetFont();+ ImGui::BeginTooltip();+ char tmp[32];+ sprintf( tmp, "+%" PRIu64, v.first - m_baseAddr );+ TextFocused( "Jump target:", tmp );+ ImGui::SameLine();+ sprintf( tmp, "(0x%" PRIx64 ")", v.first );+ TextDisabledUnformatted( tmp );+ auto lit = m_locMap.find( v.first );+ assert( lit != m_locMap.end() );+ sprintf( tmp, ".L%" PRIu32, lit->second );+ TextFocused( "Jump label:", tmp );+ uint32_t srcline;+ const auto srcidx = worker.GetLocationForAddress( v.first, srcline );+ if( srcline != 0 )+ {+ const auto fileName = worker.GetString( srcidx );+ const auto fileColor = GetHsvColor( srcidx.Idx(), 0 );+ TextDisabledUnformatted( "Target location:" );+ SmallColorBox( fileColor );+ ImGui::SameLine();+ ImGui::Text( "%s:%i", fileName, srcline );+ const auto symAddr = worker.GetInlineSymbolForAddress( v.first );+ if( symAddr != 0 )+ {+ const auto symData = worker.GetSymbolData( symAddr );+ if( symData )+ {+ ImGui::SameLine();+ ImGui::PushFont( m_smallFont );+ ImGui::AlignTextToFramePadding();+ const auto symName = worker.GetString( symData->name );+ const auto normalized = shortenName != ShortenName::Never ? ShortenZoneName( ShortenName::OnlyNormalize, symName ) : symName;+ TextDisabledUnformatted( normalized );+ ImGui::PopFont();+ }+ }+ }+ TextFocused( "Jump range:", MemSizeToString( v.second.max - v.second.min ) );+ ImGui::Separator();+ TextFocused( "Jump sources:", RealToString( v.second.source.size() ) );+ const auto ssz = std::min<size_t>( v.second.source.size(), 10 );+ for( int j=0; j<ssz; j++ )+ {+ const auto sidx = worker.GetLocationForAddress( v.second.source[j], srcline );+ if( srcline == 0 )+ {+ SmallColorBox( 0 );+ ImGui::SameLine();+ ImGui::TextDisabled( "%i. 0x%" PRIx64, j+1, v.second.source[j] );+ }+ else+ {+ const auto fn = worker.GetString( sidx );+ const auto fc = GetHsvColor( sidx.Idx(), 0 );+ SmallColorBox( fc );+ ImGui::SameLine();+ ImGui::Text( "%i. %s:%i", j+1, fn, srcline );++ const auto symAddr = worker.GetInlineSymbolForAddress( v.second.source[j] );+ if( symAddr != 0 )+ {+ const auto symData = worker.GetSymbolData( symAddr );+ if( symData )+ {+ ImGui::SameLine();+ ImGui::PushFont( m_smallFont );+ ImGui::AlignTextToFramePadding();+ const auto symName = worker.GetString( symData->name );+ const auto normalized = shortenName != ShortenName::Never ? ShortenZoneName( ShortenName::OnlyNormalize, symName ) : symName;+ TextDisabledUnformatted( normalized );+ ImGui::PopFont();+ }+ }+ }+ }+ if( ssz != v.second.source.size() )+ {+ ImGui::TextUnformatted( "..." );+ }+ ImGui::EndTooltip();+ SetFont();+ if( ImGui::IsMouseClicked( 0 ) )+ {+ m_targetAddr = v.first;+ m_selectedAddresses.clear();+ m_selectedAddresses.emplace( v.first );+ }+ else if( ImGui::IsMouseClicked( 1 ) )+ {+ ImGui::OpenPopup( "jumpPopup" );+ m_jumpPopupAddr = v.first;+ }+ selJumpStart = v.second.min;+ selJumpEnd = v.second.max;+ selJumpTarget = v.first;+ }++ DrawLine( draw, dpos + ImVec2( xoff + JumpSeparation * ( mjl - v.second.level ), y0 + th2 ), dpos + ImVec2( xoff + JumpSeparation * ( mjl - v.second.level ), y1 + th2 ), col, thickness );++ if( v.first >= minAddr && v.first <= maxAddr )+ {+ auto iit = std::lower_bound( insList.begin(), insList.end(), v.first );+ assert( iit != insList.end() );+ const auto y = ( iit - insList.begin() ) * th;+ DrawLine( draw, dpos + ImVec2( xoff + JumpSeparation * ( mjl - v.second.level ), y + th2 ), dpos + ImVec2( xoff + JumpSeparation * mjl + JumpArrow + 1, y + th2 ), col, thickness );+ DrawLine( draw, dpos + ImVec2( xoff + JumpSeparation * mjl + JumpArrow, y + th2 ), dpos + ImVec2( xoff + JumpSeparation * mjl + JumpArrow - th4, y + th2 - th4 ), col, thickness );+ DrawLine( draw, dpos + ImVec2( xoff + JumpSeparation * mjl + JumpArrow, y + th2 ), dpos + ImVec2( xoff + JumpSeparation * mjl + JumpArrow - th4, y + th2 + th4 ), col, thickness );+ }+ for( auto& s : v.second.source )+ {+ if( s >= minAddr && s <= maxAddr )+ {+ auto iit = std::lower_bound( insList.begin(), insList.end(), s );+ assert( iit != insList.end() );+ const auto y = ( iit - insList.begin() ) * th;+ DrawLine( draw, dpos + ImVec2( xoff + JumpSeparation * ( mjl - v.second.level ), y + th2 ), dpos + ImVec2( xoff + JumpSeparation * mjl + JumpArrow, y + th2 ), col, thickness );+ }+ }+ }+ }+ }++ UnsetFont();+ if( ImGui::BeginPopup( "jumpPopup" ) )+ {+ auto it = m_jumpTable.find( m_jumpPopupAddr );+ assert( it != m_jumpTable.end() );++#ifndef TRACY_NO_FILESELECTOR+ if( ImGui::MenuItem( ICON_FA_FILE_IMPORT " Save jump range" ) )+ {+ size_t minIdx = 0, maxIdx = 0;+ size_t i;+ for( i=0; i<m_asm.size(); i++ )+ {+ if( m_asm[i].addr == it->second.min )+ {+ minIdx = i++;+ break;+ }+ }+ assert( i != m_asm.size() );+ for( ; i<m_asm.size(); i++ )+ {+ if( m_asm[i].addr == it->second.max )+ {+ maxIdx = i+1;+ break;+ }+ }+ assert( i != m_asm.size() );++ Save( worker, minIdx, maxIdx );+ ImGui::CloseCurrentPopup();+ }+ ImGui::Separator();+#endif+ if( ImGui::BeginMenu( "Sources" ) )+ {+ for( auto& src : it->second.source )+ {+ uint32_t srcline;+ const auto srcidx = worker.GetLocationForAddress( src, srcline );+ if( srcline == 0 )+ {+ SmallColorBox( 0 );+ ImGui::SameLine();+ char buf[32];+ sprintf( buf, "0x%" PRIx64, src );+ if( ImGui::MenuItem( buf ) )+ {+ m_targetAddr = src;+ m_selectedAddresses.clear();+ m_selectedAddresses.emplace( src );+ }+ }+ else+ {+ const auto fileName = worker.GetString( srcidx );+ const auto fileColor = GetHsvColor( srcidx.Idx(), 0 );+ SmallColorBox( fileColor );+ ImGui::SameLine();+ char buf[1024];+ snprintf( buf, 1024, "%s:%i", fileName, srcline );+ ImGui::PushID( src );+ if( ImGui::BeginMenu( buf ) )+ {+ if( SourceFileValid( fileName, worker.GetCaptureTime(), view, worker ) )+ {+ m_sourceTooltip.Parse( fileName, worker, view );+ if( !m_sourceTooltip.empty() )+ {+ SetFont();+ PrintSourceFragment( m_sourceTooltip, srcline );+ UnsetFont();+ }+ }+ else+ {+ TextDisabledUnformatted( "Source not available" );+ }+ ImGui::EndMenu();+ if( ImGui::IsItemClicked() )+ {+ m_targetAddr = src;+ m_selectedAddresses.clear();+ m_selectedAddresses.emplace( src );+ }+ }+ ImGui::PopID();+ }+ }+ ImGui::EndMenu();+ }+ if( ImGui::BeginMenu( "Target" ) )+ {+ uint32_t srcline;+ const auto srcidx = worker.GetLocationForAddress( m_jumpPopupAddr, srcline );+ const auto fileName = srcline != 0 ? worker.GetString( srcidx ) : nullptr;+ const auto fileColor = srcline != 0 ? GetHsvColor( srcidx.Idx(), 0 ) : 0;+ SmallColorBox( fileColor );+ ImGui::SameLine();+ char buf[1024];+ if( fileName )+ {+ snprintf( buf, 1024, "%s:%i", fileName, srcline );+ }+ else+ {+ uint32_t jumpOffset = 0;+ uint64_t jumpBase = worker.GetSymbolForAddress( m_jumpPopupAddr, jumpOffset );+ auto jumpSym = jumpBase == 0 ? worker.GetSymbolData( m_jumpPopupAddr ) : worker.GetSymbolData( jumpBase );+ if( jumpSym )+ {+ const auto jumpName = worker.GetString( jumpSym->name );+ const auto normalized = view.GetShortenName() != ShortenName::Never ? ShortenZoneName( ShortenName::OnlyNormalize, jumpName ) : jumpName;+ snprintf( buf, 1024, "%s+%" PRIu32, normalized, jumpOffset );+ }+ else+ {+ ImGui::TextDisabled( "0x%" PRIx64, m_jumpPopupAddr );+ }+ }+ if( ImGui::BeginMenu( buf ) )+ {+ if( fileName && SourceFileValid( fileName, worker.GetCaptureTime(), view, worker ) )+ {+ m_sourceTooltip.Parse( fileName, worker, view );+ if( !m_sourceTooltip.empty() )+ {+ SetFont();+ PrintSourceFragment( m_sourceTooltip, srcline );+ UnsetFont();+ }+ }+ else+ {+ TextDisabledUnformatted( "Source not available" );+ }+ ImGui::EndMenu();+ if( ImGui::IsItemClicked() )+ {+ m_targetAddr = m_jumpPopupAddr;+ m_selectedAddresses.clear();+ m_selectedAddresses.emplace( m_jumpPopupAddr );+ }+ }+ ImGui::EndMenu();+ }+ ImGui::EndPopup();+ }+ if( ImGui::BeginPopup( "localCallstackPopup" ) )+ {+ ImGui::PushFont( m_smallFont );+ TextDisabledUnformatted( "Local call stack:" );+ ImGui::PopFont();+ const auto lcs = m_localCallstackPopup;+ for( uint8_t i=0; i<lcs->size; i++ )+ {+ ImGui::PushID( i );+ ImGui::TextDisabled( "%i.", i+1 );+ ImGui::SameLine();+ const auto symName = worker.GetString( lcs->data[i].name );+ const auto normalized = view.GetShortenName() != ShortenName::Never ? ShortenZoneName( ShortenName::OnlyNormalize, symName ) : symName;+ const auto fn = worker.GetString( lcs->data[i].file );+ const auto srcline = lcs->data[i].line;+ if( ImGui::BeginMenu( normalized ) )+ {+ if( SourceFileValid( fn, worker.GetCaptureTime(), view, worker ) )+ {+ m_sourceTooltip.Parse( fn, worker, view );+ if( !m_sourceTooltip.empty() )+ {+ ImGui::PushFont( m_smallFont );+ ImGui::TextDisabled( "%s:%i", fn, srcline );+ ImGui::PopFont();+ ImGui::Separator();+ SetFont();+ PrintSourceFragment( m_sourceTooltip, srcline );+ UnsetFont();+ }+ }+ else+ {+ TextDisabledUnformatted( "Source not available" );+ }+ ImGui::EndMenu();+ if( ImGui::IsItemClicked() )+ {+ m_targetLine = srcline;+ if( m_source.filename() == fn )+ {+ SelectLine( srcline, &worker, false );+ m_displayMode = DisplayMixed;+ }+ else if( SourceFileValid( fn, worker.GetCaptureTime(), view, worker ) )+ {+ ParseSource( fn, worker, view );+ SelectLine( srcline, &worker, false );+ SelectViewMode();+ }+ }+ }+ ImGui::PopID();+ }+ ImGui::EndPopup();+ }+ SetFont();+ }++ const auto win = ImGui::GetCurrentWindowRead();+ if( win->ScrollbarY )+ {+ auto draw = ImGui::GetWindowDrawList();+ auto rect = ImGui::GetWindowScrollbarRect( win, ImGuiAxis_Y );+ ImGui::PushClipRect( rect.Min, rect.Max, false );+ std::vector<uint32_t> lineOff;+ lineOff.reserve( std::max( m_selectedAddresses.size(), m_selectedAddressesHover.size() ) );+ if( !m_selectedAddresses.empty() )+ {+ for( size_t i=0; i<m_asm.size(); i++ )+ {+ if( m_selectedAddresses.find( m_asm[i].addr ) != m_selectedAddresses.end() )+ {+ lineOff.push_back( uint32_t( i ) );+ }+ }+ float lastLine = 0;+ for( auto& v : lineOff )+ {+ const auto ly = round( rect.Min.y + ( v - 0.5f ) / m_asm.size() * rect.GetHeight() );+ if( ly > lastLine )+ {+ lastLine = ly;+ DrawLine( draw, ImVec2( rect.Min.x + 0.5f, ly + 0.5f ), ImVec2( rect.Max.x + 0.5f, ly + 0.5f ), 0x8899994C, 1 );+ }+ }+ }+ if( !m_selectedAddressesHover.empty() )+ {+ lineOff.clear();+ for( size_t i=0; i<m_asm.size(); i++ )+ {+ if( m_selectedAddressesHover.find( m_asm[i].addr ) != m_selectedAddressesHover.end() )+ {+ lineOff.push_back( uint32_t( i ) );+ }+ }+ float lastLine = 0;+ for( auto& v : lineOff )+ {+ const auto ly = round( rect.Min.y + ( v - 0.5f ) / m_asm.size() * rect.GetHeight() );+ if( ly > lastLine )+ {+ lastLine = ly;+ DrawLine( draw, ImVec2( rect.Min.x + 0.5f, ly + 0.5f ), ImVec2( rect.Max.x + 0.5f, ly + 0.5f ), 0x88888888, 1 );+ }+ }+ }++ uint32_t selJumpLineStart, selJumpLineEnd, selJumpLineTarget;+ std::vector<std::pair<uint64_t, AddrStat>> ipData;+ ipData.reserve( as.ipCountAsm.size() );+ if( selJumpStart == 0 )+ {+ for( size_t i=0; i<m_asm.size(); i++ )+ {+ auto it = as.ipCountAsm.find( m_asm[i].addr );+ if( it == as.ipCountAsm.end() ) continue;+ ipData.emplace_back( i, it->second );+ }+ }+ else+ {+ for( size_t i=0; i<m_asm.size(); i++ )+ {+ if( selJumpStart == m_asm[i].addr ) selJumpLineStart = i;+ if( selJumpEnd == m_asm[i].addr ) selJumpLineEnd = i;+ if( selJumpTarget == m_asm[i].addr ) selJumpLineTarget = i;++ auto it = as.ipCountAsm.find( m_asm[i].addr );+ if( it == as.ipCountAsm.end() ) continue;+ ipData.emplace_back( i, it->second );+ }+ }+ pdqsort_branchless( ipData.begin(), ipData.end(), []( const auto& l, const auto& r ) { return l.first < r.first; } );++ const auto step = uint32_t( m_asm.size() * 2 / rect.GetHeight() );+ const auto x40 = round( rect.Min.x + rect.GetWidth() * 0.4f );+ const auto x60 = round( rect.Min.x + rect.GetWidth() * 0.6f );++ auto it = ipData.begin();+ while( it != ipData.end() )+ {+ const auto firstLine = it->first;+ AddrStat ipSum = {};+ while( it != ipData.end() && it->first <= firstLine + step )+ {+ ipSum += it->second;+ ++it;+ }+ const auto ly = round( rect.Min.y + float( firstLine ) / m_asm.size() * rect.GetHeight() );+ if( m_childCalls )+ {+ const auto color = GetHotnessColor( ipSum.local + ipSum.ext, as.ipMaxAsm.local + as.ipMaxAsm.ext );+ draw->AddRectFilled( ImVec2( x40, ly ), ImVec2( x60, ly+3*scale ), color );+ }+ else if( as.ipMaxAsm.local != 0 )+ {+ const auto color = GetHotnessColor( ipSum.local, as.ipMaxAsm.local );+ draw->AddRectFilled( ImVec2( x40, ly ), ImVec2( x60, ly+3*scale ), color );+ }+ }++ if( selJumpStart != 0 )+ {+ const auto yStart = 0.5f + rect.Min.y + float( selJumpLineStart ) / m_asm.size() * rect.GetHeight();+ const auto yEnd = 0.5f + rect.Min.y + float( selJumpLineEnd ) / m_asm.size() * rect.GetHeight();+ const auto yTarget = 0.5f + rect.Min.y + float( selJumpLineTarget ) / m_asm.size() * rect.GetHeight();+ const auto x50 = 0.5f + round( rect.Min.x + rect.GetWidth() * 0.5f ) - 1;+ const auto x25 = 0.5f + round( rect.Min.x + rect.GetWidth() * 0.25f );+ const auto x75 = 0.5f + round( rect.Min.x + rect.GetWidth() * 0.75f );+ DrawLine( draw, ImVec2( x50, yStart ), ImVec2( x50, yEnd ), 0xFF00FF00 );+ DrawLine( draw, ImVec2( x25, yTarget ), ImVec2( x75, yTarget ), 0xFF00FF00 );+ }++ if( m_asmSelected >= 0 )+ {+ const auto x0 = rect.Min.x;+ const auto x1 = rect.Min.x + rect.GetWidth() * 0.2f;+ float sy;+ for( int i=0; i<(int)m_asm.size(); i++ )+ {+ if( i == m_asmSelected )+ {+ sy = round( rect.Min.y + ( i - 0.5f ) / m_asm.size() * rect.GetHeight() );+ }+ else if( m_asm[i].regData[0] != 0 )+ {+ int flags = 0;+ int idx = 0;+ for(;;)+ {+ const auto& v = m_asm[i].regData[idx++];+ if( v == 0 ) break;+ flags |= v & FlagMask;+ }+ uint32_t col = 0;+ if( ( flags & ( WriteBit | ReadBit ) ) == ( WriteBit | ReadBit ) ) col = 0xFF00FFFF;+ else if( flags & WriteBit ) col = 0xFF0000FF;+ else if( flags & ReadBit ) col = 0xFF00FF00;+ if( col != 0 )+ {+ const auto ly = round( rect.Min.y + ( i - 0.5f ) / m_asm.size() * rect.GetHeight() );+ DrawLine( draw, ImVec2( x0 + 0.5f, ly + 0.5f ), ImVec2( x1 + 0.5f, ly + 0.5f ), col, 3 );+ }+ }+ }+ DrawLine( draw, ImVec2( x0 + 0.5f, sy + 0.5f ), ImVec2( x1 + 0.5f, sy + 0.5f ), 0xFFFF9900, 3 );+ }+ }++ UnsetFont();+ ImGui::EndChild();++ if( !m_asmSampleSelect.empty() )+ {+ AddrStat count = {};+ uint32_t numLines = 0;+ for( auto& idx : m_asmSampleSelect )+ {+ auto it = as.ipCountAsm.find( m_asm[idx].addr );+ if( it != as.ipCountAsm.end() )+ {+ count += it->second;+ numLines++;+ }+ }++ ImGui::BeginChild( "##asmSelect" );+ if( ImGui::SmallButton( ICON_FA_XMARK ) )+ {+ m_asmSampleSelect.clear();+ m_asmGroupSelect = -1;+ }+ ImGui::SameLine();+ char buf[16];+ char* end;+ if( m_childCalls )+ {+ end = PrintFloat( buf, buf+16, 100.f * ( count.local + count.ext ) / ( as.ipTotalAsm.local + as.ipTotalAsm.ext ), 2 );+ }+ else if( as.ipTotalAsm.local != 0 )+ {+ end = PrintFloat( buf, buf+16, 100.f * count.local / as.ipTotalAsm.local, 2 );+ }+ else+ {+ end = PrintFloat( buf, buf+16, 0.f, 2 );+ }+ memcpy( end, "%", 2 );+ TextFocused( "Selected:", buf );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ if( m_cost == CostType::SampleCount )+ {+ int64_t time;+ if( m_childCalls )+ {+ time = ( count.local + count.ext ) * worker.GetSamplingPeriod();+ }+ else+ {+ time = count.local * worker.GetSamplingPeriod();+ }+ TextFocused( "Time:", TimeToString( time ) );+ const auto timePct = 100.f * time / worker.GetLastTime();+ if( timePct >= 0.01f )+ {+ ImGui::SameLine();+ ImGui::TextDisabled( "(%.2f%% run time)", timePct );+ }+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ if( m_childCalls )+ {+ TextFocused( "Sample count:", RealToString( count.local + count.ext ) );+ }+ else+ {+ TextFocused( "Sample count:", RealToString( count.local ) );+ }+ }+ else+ {+ TextFocused( "Events:", RealToString( count.local ) );+ }+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ TextFocused( "Lines:", RealToString( numLines ) );+ ImGui::EndChild();+ }++ return jumpOut;+}++static bool PrintPercentage( float val, uint32_t col = 0xFFFFFFFF )+{+ const auto ty = ImGui::GetTextLineHeight();+ auto draw = ImGui::GetWindowDrawList();+ const auto wpos = ImGui::GetCursorScreenPos();+ const auto stw = ImGui::CalcTextSize( " " ).x;+ const auto htw = stw / 2;+ const auto tw = stw * 8;++ char tmp[16];+ auto end = PrintFloat( tmp, tmp+16, val, 2 );+ memcpy( end, "%", 2 );+ end++;+ const auto sz = end - tmp;+ char buf[16];+ memset( buf, ' ', 7-sz );+ memcpy( buf + 7 - sz, tmp, sz+1 );++ draw->AddRectFilled( wpos + ImVec2( 0, 1 ), wpos + ImVec2( val * tw / 100, ty ), 0xFF444444 );+ DrawTextContrast( draw, wpos + ImVec2( htw, 0 ), col, buf );++ ImGui::ItemSize( ImVec2( stw * 7, ty ), 0 );+ return ImGui::IsWindowHovered() && ImGui::IsMouseHoveringRect( wpos, wpos + ImVec2( stw * 7, ty ) );+}++void SourceView::RenderLine( const Tokenizer::Line& line, int lineNum, const AddrStat& ipcnt, const AddrStatData& as, Worker* worker, const View* view )+{+ const auto scale = GetScale();+ const auto ts = ImGui::CalcTextSize( " " );+ const auto ty = ImGui::GetTextLineHeight();+ auto draw = ImGui::GetWindowDrawList();+ const auto w = std::max( m_srcWidth, ImGui::GetWindowWidth() );+ const auto wpos = ImGui::GetCursorScreenPos();+ const auto dpos = wpos + ImVec2( 0.5f, 0.5f );+ if( m_source.idx() == m_hoveredSource && lineNum == m_hoveredLine )+ {+ draw->AddRectFilled( wpos + ImVec2( 0, 1 ), wpos + ImVec2( w, ty ), 0x22FFFFFF );+ }+ else if( lineNum == m_selectedLine )+ {+ draw->AddRectFilled( wpos + ImVec2( 0, 1 ), wpos + ImVec2( w, ty ), 0xFF333322 );+ }++ bool hasHwData = false;+ size_t cycles = 0, retired = 0, cacheRef = 0, cacheMiss = 0, branchRetired = 0, branchMiss = 0;+ uint32_t match = 0;+ if( !m_asm.empty() )+ {+ assert( worker && view );+ auto addresses = GetAddressesForLocation( m_source.idx(), lineNum, *worker );+ if( addresses )+ {+ for( auto& addr : *addresses )+ {+ if( addr >= m_baseAddr && addr < m_baseAddr + m_codeLen )+ {+ if( !m_calcInlineStats || worker->GetInlineSymbolForAddress( addr ) == m_symAddr )+ {+ match++;+ const auto hw = worker->GetHwSampleData( addr );+ if( hw )+ {+ hasHwData = true;+ auto& statRange = view->m_statRange;+ if( statRange.active )+ {+ hw->sort();+ cycles += CountHwSamples( hw->cycles, statRange );+ retired += CountHwSamples( hw->retired, statRange );+ cacheRef += CountHwSamples( hw->cacheRef, statRange );+ cacheMiss += CountHwSamples( hw->cacheMiss, statRange );+ branchRetired += CountHwSamples( hw->branchRetired, statRange );+ branchMiss += CountHwSamples( hw->branchMiss, statRange );+ }+ else+ {+ cycles += hw->cycles.size();+ retired += hw->retired.size();+ cacheRef += hw->cacheRef.size();+ cacheMiss += hw->cacheMiss.size();+ branchRetired += hw->branchRetired.size();+ branchMiss += hw->branchMiss.size();+ }+ }+ }+ }+ }+ }+ }++ bool mouseHandled = false;+ if( as.ipTotalSrc.local + as.ipTotalSrc.ext != 0 )+ {+ if( ( m_childCalls && ipcnt.local + ipcnt.ext == 0 ) || ( !m_childCalls && ipcnt.local == 0 ) )+ {+ const auto ts = ImGui::CalcTextSize( " " );+ ImGui::ItemSize( ImVec2( 7 * ts.x, ts.y ) );+ if( hasHwData && ImGui::IsWindowHovered() && ImGui::IsMouseHoveringRect( wpos, wpos + ImVec2( ts.x * 7, ty ) ) )+ {+ UnsetFont();+ ImGui::BeginTooltip();+ PrintHwSampleTooltip( cycles, retired, cacheRef, cacheMiss, branchRetired, branchMiss, true );+ ImGui::EndTooltip();+ SetFont();+ }+ }+ else+ {+ auto sit = m_srcSampleSelect.find( lineNum );+ bool hover;+ if( m_childCalls )+ {+ hover = PrintPercentage( 100.f * ( ipcnt.local + ipcnt.ext ) / ( as.ipTotalSrc.local + as.ipTotalSrc.ext ), sit == m_srcSampleSelect.end() ? 0xFFFFFFFF : 0xFF8888FF );+ }+ else+ {+ hover = PrintPercentage( 100.f * ipcnt.local / as.ipTotalSrc.local, sit == m_srcSampleSelect.end() ? 0xFFFFFFFF : 0xFF8888FF );+ }+ if( hover )+ {+ UnsetFont();+ ImGui::BeginTooltip();+ if( ipcnt.local )+ {+ if( m_cost == CostType::SampleCount )+ {+ if( worker )+ {+ const auto time = ipcnt.local * worker->GetSamplingPeriod();+ TextFocused( "Local time:", TimeToString( time ) );+ const auto timePct = 100.f * time / worker->GetLastTime();+ if( timePct >= 0.01f )+ {+ ImGui::SameLine();+ ImGui::TextDisabled( "(%.2f%% run time)", timePct );+ }+ }+ TextFocused( "Local samples:", RealToString( ipcnt.local ) );+ }+ else+ {+ TextFocused( "Events:", RealToString( ipcnt.local ) );+ }+ }+ if( ipcnt.ext )+ {+ if( worker )+ {+ const auto time = ipcnt.ext * worker->GetSamplingPeriod();+ TextFocused( "Child time:", TimeToString( time ) );+ const auto timePct = 100.f * time / worker->GetLastTime();+ if( timePct >= 0.01f )+ {+ ImGui::SameLine();+ ImGui::TextDisabled( "(%.2f%% run time)", timePct );+ }+ }+ TextFocused( "Child samples:", RealToString( ipcnt.ext ) );+ }+ if( hasHwData ) PrintHwSampleTooltip( cycles, retired, cacheRef, cacheMiss, branchRetired, branchMiss, false );+ ImGui::EndTooltip();+ SetFont();++ if( ImGui::IsMouseClicked( 0 ) )+ {+ mouseHandled = true;+ auto& io = ImGui::GetIO();+ if( io.KeyCtrl )+ {+ m_srcGroupSelect = lineNum;+ if( sit == m_srcSampleSelect.end() )+ {+ m_srcSampleSelect.emplace( lineNum );+ }+ else+ {+ m_srcSampleSelect.erase( sit );+ }+ }+ else if( io.KeyShift )+ {+ m_srcSampleSelect.clear();+ if( m_srcGroupSelect == -1 )+ {+ m_srcGroupSelect = lineNum;+ m_srcSampleSelect.insert( lineNum );+ }+ else+ {+ if( lineNum < m_srcGroupSelect )+ {+ for( int i=lineNum; i<=m_srcGroupSelect; i++ )+ {+ m_srcSampleSelect.insert( i );+ }+ }+ else+ {+ for( int i=m_srcGroupSelect; i<=lineNum; i++ )+ {+ m_srcSampleSelect.insert( i );+ }+ }+ }+ }+ else+ {+ m_srcSampleSelect.clear();+ m_srcSampleSelect.insert( lineNum );+ m_srcGroupSelect = lineNum;+ }+ }+ else if( ImGui::IsMouseClicked( 1 ) )+ {+ mouseHandled = true;+ m_srcSampleSelect.clear();+ m_srcGroupSelect = -1;+ }+ }++ uint32_t col, glow;+ if( m_childCalls )+ {+ col = GetHotnessColor( ipcnt.local + ipcnt.ext, as.ipMaxSrc.local + as.ipMaxSrc.ext );+ glow = GetHotnessGlow( ipcnt.local + ipcnt.ext, as.ipMaxSrc.local + as.ipMaxSrc.ext );+ }+ else+ {+ col = GetHotnessColor( ipcnt.local, as.ipMaxSrc.local );+ glow = GetHotnessGlow( ipcnt.local, as.ipMaxSrc.local );+ }+ if( glow )+ {+ DrawLine( draw, dpos + ImVec2( scale, 2 ), dpos + ImVec2( scale, ty-1 ), glow, scale );+ DrawLine( draw, dpos + ImVec2( -scale, 2 ), dpos + ImVec2( -scale, ty-1 ), glow, scale );+ }+ DrawLine( draw, dpos + ImVec2( 0, 2 ), dpos + ImVec2( 0, ty-1 ), col, scale );+ }+ ImGui::SameLine( 0, ty );+ }++ const bool showHwSamples = worker && m_hwSamples && worker->GetHwSampleCountAddress() != 0;+ if( showHwSamples )+ {+ const auto startPos = ImGui::GetCursorScreenPos();+ if( hasHwData )+ {+ if( m_hwSamplesRelative )+ {+ auto it = as.hwCountSrc.find( lineNum );+ if( it == as.hwCountSrc.end() )+ {+ RenderHwLinePart( cycles, retired, branchRetired, branchMiss, cacheRef, cacheMiss, 0, 0, 0, 0, ts );+ }+ else+ {+ RenderHwLinePart( cycles, retired, branchRetired, branchMiss, cacheRef, cacheMiss, it->second.local, as.hwMaxSrc.local, it->second.ext, as.hwMaxSrc.ext, ts );+ }+ }+ else+ {+ RenderHwLinePart( cycles, retired, branchRetired, branchMiss, cacheRef, cacheMiss, 0, 0, 0, 0, ts );+ }+ ImGui::SameLine( 0, 0 );+ }+ const auto endPos = ImGui::GetCursorScreenPos();+ const auto itemsWidth = ( endPos - startPos ).x;+ const auto fixedWidth = 17 * ts.x;+ ImGui::ItemSize( ImVec2( fixedWidth - itemsWidth, 0 ) );+ ImGui::SameLine( 0, 0 );+ }++ {+ char tmp[32], buf[32];+ const auto lineCount = m_source.get().size();+ sprintf( tmp, "%zu", lineCount );+ const auto maxLine = strlen( tmp );+ sprintf( tmp, "%i", lineNum );+ const auto linesz = strlen( tmp );+ memset( buf, ' ', maxLine - linesz );+ memcpy( buf + maxLine - linesz, tmp, linesz+1 );+ TextDisabledUnformatted( buf );+ ImGui::SameLine( 0, ty );+ }++ if( !m_asm.empty() )+ {+ char buf[32];+ sprintf( buf, "%zu", m_asm.size() );+ const auto maxAsm = strlen( buf ) + 1;+ if( match > 0 )+ {+ sprintf( buf, "@%" PRIu32, match );+ const auto asmsz = strlen( buf );+ TextDisabledUnformatted( buf );+ ImGui::SameLine( 0, 0 );+ ImGui::ItemSize( ImVec2( ts.x * ( maxAsm - asmsz ), ty ), 0 );+ }+ else+ {+ ImGui::ItemSize( ImVec2( ts.x * maxAsm, ty ), 0 );+ }+ }++ ImGui::SameLine( 0, ty );+ auto ptr = line.begin;+ auto it = line.tokens.begin();+ while( ptr < line.end )+ {+ if( it == line.tokens.end() )+ {+ ImGui::TextUnformatted( ptr, line.end );+ ImGui::SameLine( 0, 0 );+ break;+ }+ if( ptr < it->begin )+ {+ ImGui::TextUnformatted( ptr, it->begin );+ ImGui::SameLine( 0, 0 );+ }+ TextColoredUnformatted( SyntaxColors[(int)it->color], it->begin, it->end );+ ImGui::SameLine( 0, 0 );+ ptr = it->end;+ ++it;+ }+ ImGui::ItemSize( ImVec2( 0, 0 ), 0 );++ if( match > 0 && ImGui::IsWindowHovered() && ImGui::IsMouseHoveringRect( wpos, wpos + ImVec2( w, ty ) ) )+ {+ draw->AddRectFilled( wpos + ImVec2( 0, 1 ), wpos + ImVec2( w, ty ), 0x11FFFFFF );+ if( !mouseHandled && ( ImGui::IsMouseClicked( 0 ) || ImGui::IsMouseClicked( 1 ) ) )+ {+ m_displayMode = DisplayMixed;+ SelectLine( lineNum, worker, ImGui::IsMouseClicked( 0 ) );+ }+ else+ {+ SelectAsmLinesHover( m_source.idx(), lineNum, *worker );+ }+ }++ DrawLine( draw, dpos + ImVec2( 0, ty ), dpos + ImVec2( w, ty ), 0x08FFFFFF );+}++static tracy_force_inline uint32_t AsmColor( uint32_t base, bool inContext, int isSelected )+{+ if( inContext )+ {+ switch( isSelected )+ {+ case 0: return base;+ case 1: return 0xFFFFFFFF;+ case 2: return 0xFF2F2FFF;+ default: assert( false ); return 0;+ }+ }+ else+ {+ switch( isSelected )+ {+ case 0: return ( base & 0xFFFFFF ) | 0x88000000;+ case 1: return 0x88FFFFFF;+ case 2: return 0x882F2FFF;+ default: assert( false ); return 0;+ }+ }+}++void SourceView::RenderAsmLine( AsmLine& line, const AddrStat& ipcnt, const AddrStatData& as, Worker& worker, uint64_t& jumpOut, int maxAddrLen, int maxAddrLenRel, View& view )+{+ const auto scale = GetScale();+ const auto ty = ImGui::GetTextLineHeight();+ auto draw = ImGui::GetWindowDrawList();+ const auto w = std::max( m_asmWidth, ImGui::GetWindowWidth() );+ const auto wpos = ImGui::GetCursorScreenPos();+ const auto dpos = wpos + ImVec2( 0.5f, 0.5f );+ if( m_selectedAddressesHover.find( line.addr ) != m_selectedAddressesHover.end() )+ {+ draw->AddRectFilled( wpos + ImVec2( 0, 1 ), wpos + ImVec2( w, ty ), 0x22FFFFFF );+ }+ else if( m_selectedAddresses.find( line.addr ) != m_selectedAddresses.end() )+ {+ draw->AddRectFilled( wpos + ImVec2( 0, 1 ), wpos + ImVec2( w, ty ), 0xFF333322 );+ }+ if( line.addr == m_highlightAddr )+ {+ draw->AddRectFilled( wpos + ImVec2( 0, 1 ), wpos + ImVec2( w, ty ), 0xFF222233 );+ }++ const auto asmIdx = &line - m_asm.data();++ const auto hw = worker.GetHwSampleData( line.addr );+ size_t cycles = 0, retired = 0, cacheRef = 0, cacheMiss = 0, branchRetired = 0, branchMiss = 0;+ if( hw && ( !m_calcInlineStats || worker.GetInlineSymbolForAddress( line.addr ) == m_symAddr ) )+ {+ if( view.m_statRange.active )+ {+ hw->sort();+ cycles = CountHwSamples( hw->cycles, view.m_statRange );+ retired = CountHwSamples( hw->retired, view.m_statRange );+ cacheRef = CountHwSamples( hw->cacheRef, view.m_statRange );+ cacheMiss = CountHwSamples( hw->cacheMiss, view.m_statRange );+ branchRetired = CountHwSamples( hw->branchRetired, view.m_statRange );+ branchMiss = CountHwSamples( hw->branchMiss, view.m_statRange );+ }+ else+ {+ cycles = hw->cycles.size();+ retired = hw->retired.size();+ cacheRef = hw->cacheRef.size();+ cacheMiss = hw->cacheMiss.size();+ branchRetired = hw->branchRetired.size();+ branchMiss = hw->branchMiss.size();+ }+ }++ const auto ts = ImGui::CalcTextSize( " " );+ if( as.ipTotalAsm.local + as.ipTotalAsm.ext != 0 )+ {+ if( ( m_childCalls && ipcnt.local + ipcnt.ext == 0 ) || ( !m_childCalls && ipcnt.local == 0 ) )+ {+ ImGui::ItemSize( ImVec2( 7 * ts.x, ts.y ) );+ if( hw && ImGui::IsWindowHovered() && ImGui::IsMouseHoveringRect( wpos, wpos + ImVec2( ts.x * 7, ty ) ) )+ {+ UnsetFont();+ ImGui::BeginTooltip();+ PrintHwSampleTooltip( cycles, retired, cacheRef, cacheMiss, branchRetired, branchMiss, true );+ ImGui::EndTooltip();+ SetFont();+ }+ }+ else+ {+ const auto idx = &line - m_asm.data();+ auto sit = m_asmSampleSelect.find( idx );+ bool hover;+ if( m_childCalls )+ {+ hover = PrintPercentage( 100.f * ( ipcnt.local + ipcnt.ext ) / ( as.ipTotalAsm.local + as.ipTotalAsm.ext ), sit == m_asmSampleSelect.end() ? 0xFFFFFFFF : 0xFF8888FF );+ }+ else+ {+ hover = PrintPercentage( 100.f * ipcnt.local / as.ipTotalAsm.local, sit == m_asmSampleSelect.end() ? 0xFFFFFFFF : 0xFF8888FF );+ }+ if( hover )+ {+ uint64_t symAddrParents = m_baseAddr;+ auto inlineList = worker.GetInlineSymbolList( m_baseAddr, m_codeLen );+ if( inlineList )+ {+ const auto cfi = worker.PackPointer( line.addr );+ const auto symEnd = m_baseAddr + m_codeLen;+ while( *inlineList < symEnd )+ {+ auto ipmap = worker.GetSymbolInstructionPointers( *inlineList );+ if( ipmap )+ {+ if( ipmap->find( cfi ) != ipmap->end() )+ {+ symAddrParents = *inlineList;+ break;+ }+ }+ inlineList++;+ }+ }++ UnsetFont();+ ImGui::BeginTooltip();+ if( ipcnt.local )+ {+ if( m_cost == CostType::SampleCount )+ {+ const auto time = ipcnt.local * worker.GetSamplingPeriod();+ TextFocused( "Local time:", TimeToString( time ) );+ const auto timePct = 100.f * time / worker.GetLastTime();+ if( timePct >= 0.01f )+ {+ ImGui::SameLine();+ ImGui::TextDisabled( "(%.2f%% run time)", timePct );+ }+ TextFocused( "Local samples:", RealToString( ipcnt.local ) );+ }+ else+ {+ TextFocused( "Events:", RealToString( ipcnt.local ) );+ }+ }+ if( ipcnt.ext )+ {+ const auto time = ipcnt.ext * worker.GetSamplingPeriod();+ TextFocused( "Child time:", TimeToString( time ) );+ const auto timePct = 100.f * time / worker.GetLastTime();+ if( timePct >= 0.01f )+ {+ ImGui::SameLine();+ ImGui::TextDisabled( "(%.2f%% run time)", timePct );+ }+ TextFocused( "Child samples:", RealToString( ipcnt.ext ) );+ }++ if( hw ) PrintHwSampleTooltip( cycles, retired, cacheRef, cacheMiss, branchRetired, branchMiss, false );++ const auto stats = worker.GetSymbolStats( symAddrParents );+ if( stats && !stats->parents.empty() )+ {+ ImGui::Separator();+ TextFocused( "Entry call stacks:", RealToString( stats->parents.size() ) );+ ImGui::SameLine();+ TextDisabledUnformatted( "(middle click to view)" );+ }+ ImGui::EndTooltip();+ SetFont();++ if( ImGui::IsMouseClicked( 0 ) )+ {+ auto& io = ImGui::GetIO();+ if( io.KeyCtrl )+ {+ m_asmGroupSelect = idx;+ if( sit == m_asmSampleSelect.end() )+ {+ m_asmSampleSelect.emplace( idx );+ }+ else+ {+ m_asmSampleSelect.erase( sit );+ }+ }+ else if( io.KeyShift )+ {+ m_asmSampleSelect.clear();+ if( m_asmGroupSelect == -1 )+ {+ m_asmGroupSelect = idx;+ m_asmSampleSelect.insert( idx );+ }+ else+ {+ if( idx < m_asmGroupSelect )+ {+ for( int i=idx; i<=m_asmGroupSelect; i++ )+ {+ m_asmSampleSelect.insert( i );+ }+ }+ else+ {+ for( int i=m_asmGroupSelect; i<=idx; i++ )+ {+ m_asmSampleSelect.insert( i );+ }+ }+ }+ }+ else+ {+ m_asmSampleSelect.clear();+ m_asmSampleSelect.insert( idx );+ m_asmGroupSelect = idx;+ }+ }+ else if( ImGui::IsMouseClicked( 1 ) )+ {+ m_asmSampleSelect.clear();+ m_asmGroupSelect = -1;+ }+ else if( stats && !stats->parents.empty() && ImGui::IsMouseClicked( 2 ) )+ {+ view.ShowSampleParents( symAddrParents, false );+ }+ }++ uint32_t col, glow;+ if( m_childCalls )+ {+ col = GetHotnessColor( ipcnt.local + ipcnt.ext, as.ipMaxAsm.local + as.ipMaxAsm.ext );+ glow = GetHotnessGlow( ipcnt.local + ipcnt.ext, as.ipMaxAsm.local + as.ipMaxAsm.ext );+ }+ else+ {+ col = GetHotnessColor( ipcnt.local, as.ipMaxAsm.local );+ glow = GetHotnessGlow( ipcnt.local, as.ipMaxAsm.local );+ }+ if( glow )+ {+ DrawLine( draw, dpos + ImVec2( scale, 2 ), dpos + ImVec2( scale, ty-1 ), glow, scale );+ DrawLine( draw, dpos + ImVec2( -scale, 2 ), dpos + ImVec2( -scale, ty-1 ), glow, scale );+ }+ DrawLine( draw, dpos + ImVec2( 0, 2 ), dpos + ImVec2( 0, ty-1 ), col, scale );+ }+ ImGui::SameLine( 0, ty );+ }++ const bool showHwSamples = m_hwSamples && worker.GetHwSampleCountAddress() != 0;+ if( showHwSamples )+ {+ const auto startPos = ImGui::GetCursorScreenPos();+ if( hw )+ {+ if( m_hwSamplesRelative )+ {+ auto it = as.hwCountAsm.find( line.addr );+ if( it == as.hwCountAsm.end() )+ {+ RenderHwLinePart( cycles, retired, branchRetired, branchMiss, cacheRef, cacheMiss, 0, 0, 0, 0, ts );+ }+ else+ {+ RenderHwLinePart( cycles, retired, branchRetired, branchMiss, cacheRef, cacheMiss, it->second.local, as.hwMaxAsm.local, it->second.ext, as.hwMaxAsm.ext, ts );+ }+ }+ else+ {+ RenderHwLinePart( cycles, retired, branchRetired, branchMiss, cacheRef, cacheMiss, 0, 0, 0, 0, ts );+ }+ ImGui::SameLine( 0, 0 );+ }+ const auto endPos = ImGui::GetCursorScreenPos();+ const auto itemsWidth = ( endPos - startPos ).x;+ const auto fixedWidth = 17 * ts.x;+ ImGui::ItemSize( ImVec2( fixedWidth - itemsWidth, 0 ) );+ ImGui::SameLine( 0, 0 );+ }++ char buf[256];+ if( m_asmCountBase >= 0 )+ {+ sprintf( buf, "[%i]", int( asmIdx - m_asmCountBase ) );+ }+ else if( m_asmRelative )+ {+ sprintf( buf, "+%" PRIu64, line.addr - m_baseAddr );+ }+ else+ {+ sprintf( buf, "%" PRIx64, line.addr );+ }+ const auto asz = strlen( buf );+ if( m_asmRelative )+ {+ memset( buf+asz, ' ', maxAddrLenRel-asz );+ buf[maxAddrLenRel] = '\0';+ }+ else+ {+ memset( buf+asz, ' ', maxAddrLen-asz );+ buf[maxAddrLen] = '\0';+ }+ if( m_asmCountBase >= 0 )+ {+ TextColoredUnformatted( asmIdx - m_asmCountBase < 0 ? 0xFFBB6666 : 0xFF66BBBB, buf );+ }+ else+ {+ TextDisabledUnformatted( buf );+ }+ if( ImGui::IsItemHovered() )+ {+ UnsetFont();+ ImGui::BeginTooltip();+ if( m_asmCountBase >= 0 )+ {+ TextDisabledUnformatted( "Absolute address:" );+ ImGui::SameLine();+ ImGui::Text( "%" PRIx64, line.addr );+ TextDisabledUnformatted( "Relative address:" );+ ImGui::SameLine();+ ImGui::Text( "+%" PRIx64, line.addr - m_baseAddr );+ }+ else if( m_asmRelative )+ {+ TextDisabledUnformatted( "Absolute address:" );+ ImGui::SameLine();+ ImGui::Text( "%" PRIx64, line.addr );+ }+ else+ {+ TextDisabledUnformatted( "Relative address:" );+ ImGui::SameLine();+ ImGui::Text( "+%" PRIx64, line.addr - m_baseAddr );+ }+ ImGui::EndTooltip();+ SetFont();++ if( ImGui::IsItemClicked( 0 ) )+ {+ m_asmCountBase = asmIdx;+ }+ else if( ImGui::IsItemClicked( 1 ) )+ {+ m_asmCountBase = -1;+ }+ }++ const auto stw = ImGui::CalcTextSize( " " ).x;+ bool lineHovered = false;+ if( m_asmShowSourceLocation && !m_sourceFiles.empty() )+ {+ constexpr size_t MaxSourceLength = 26;+ ImGui::SameLine( 0, stw );+ ImVec2 startPos;+ uint32_t srcline;+ const auto srcidx = worker.GetLocationForAddress( line.addr, srcline );+ if( srcline != 0 )+ {+ const auto fileName = worker.GetString( srcidx );+ const auto fileColor = GetHsvColor( srcidx.Idx(), 0 );+ ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 0, 0 ) );+ ImGui::ColorButton( "c1", ImVec4( (fileColor & 0xFF) / 255.f, ((fileColor>>8) & 0xFF ) / 255.f, ((fileColor>>16) & 0xFF ) / 255.f, 1.f ), ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoDragDrop, ImVec2( ty - 3 * scale, ty - 3 * scale) );+ ImGui::PopStyleVar();+ ImGui::SameLine();+ startPos = ImGui::GetCursorScreenPos();+ char buf[64];+ const auto fnsz = strlen( fileName );+ if( fnsz < MaxSourceLength - m_maxLine )+ {+ sprintf( buf, "%s:%i", fileName, srcline );+ }+ else+ {+ sprintf( buf, "\xe2\x80\xa6%s:%i", fileName+fnsz-(MaxSourceLength-1-1-m_maxLine), srcline );+ }+ TextDisabledUnformatted( buf );+ if( ImGui::IsItemHovered() )+ {+ lineHovered = true;+ UnsetFont();+ ImGui::BeginTooltip();+ if( worker.HasInlineSymbolAddresses() )+ {+ const auto symAddr = worker.GetInlineSymbolForAddress( line.addr );+ if( symAddr != 0 )+ {+ const auto symData = worker.GetSymbolData( symAddr );+ if( symData )+ {+ const auto symName = worker.GetString( symData->name );+ const auto normalized = view.GetShortenName() != ShortenName::Never ? ShortenZoneName( ShortenName::OnlyNormalize, symName ) : symName;+ TextFocused( "Function:", normalized );+ ImGui::SameLine();+ ImGui::TextDisabled( "(0x%" PRIx64 ")", symAddr );+ if( normalized != symName && strcmp( normalized, symName ) != 0 )+ {+ ImGui::PushFont( m_smallFont );+ TextDisabledUnformatted( symName );+ ImGui::PopFont();+ }+ }+ }+ }+ TextFocused( "File:", fileName );+ TextFocused( "Line:", RealToString( srcline ) );+ if( SourceFileValid( fileName, worker.GetCaptureTime(), view, worker ) )+ {+ m_sourceTooltip.Parse( fileName, worker, view );+ if( !m_sourceTooltip.empty() )+ {+ ImGui::Separator();+ SetFont();+ PrintSourceFragment( m_sourceTooltip, srcline );+ UnsetFont();+ }+ }+ const auto frame = worker.GetCallstackFrame( worker.PackPointer( line.addr ) );+ if( frame && frame->size > 1 )+ {+ ImGui::Separator();+ TextDisabledUnformatted( "Local call stack:" );+ for( uint8_t i=0; i<frame->size; i++ )+ {+ ImGui::TextDisabled( "%i.", i+1 );+ ImGui::SameLine();+ const auto symName = worker.GetString( frame->data[i].name );+ const auto normalized = view.GetShortenName() != ShortenName::Never ? ShortenZoneName( ShortenName::OnlyNormalize, symName ) : symName;+ ImGui::Text( "%s", normalized );+ ImGui::SameLine();+ ImGui::PushFont( m_smallFont );+ ImGui::AlignTextToFramePadding();+ ImGui::TextDisabled( "%s:%i", worker.GetString( frame->data[i].file ), frame->data[i].line );+ ImGui::PopFont();+ }+ }+ ImGui::EndTooltip();+ SetFont();+ if( ImGui::IsItemClicked( 0 ) )+ {+ if( m_source.filename() == fileName )+ {+ m_targetLine = srcline;+ SelectLine( srcline, &worker, false );+ m_displayMode = DisplayMixed;+ }+ else if( SourceFileValid( fileName, worker.GetCaptureTime(), view, worker ) )+ {+ m_targetLine = srcline;+ ParseSource( fileName, worker, view );+ SelectLine( srcline, &worker, false );+ SelectViewMode();+ }+ m_selectedAddresses.clear();+ m_selectedAddresses.emplace( line.addr );+ }+ else+ {+ m_hoveredLine = srcline;+ m_hoveredSource = srcidx.Idx();+ }+ if( frame && frame->data[0].name.Active() && ImGui::IsItemClicked( 1 ) )+ {+ ImGui::OpenPopup( "localCallstackPopup" );+ m_localCallstackPopup = frame;+ m_selectedAddresses.clear();+ m_selectedAddresses.emplace( line.addr );+ }+ }+ }+ else+ {+ ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 0, 0 ) );+ ImGui::ColorButton( "c1", ImVec4( 0.f, 0.f, 0.f, 1.f ), ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoDragDrop, ImVec2( ty - 3 * scale, ty - 3 * scale) );+ ImGui::PopStyleVar();+ ImGui::SameLine();+ startPos = ImGui::GetCursorScreenPos();+ TextDisabledUnformatted( "[unknown]" );+ if( ImGui::IsItemHovered() ) lineHovered = true;+ }+ ImGui::SameLine( 0, 0 );+ const auto endPos = ImGui::GetCursorScreenPos();+ const auto itemsWidth = ( endPos - startPos ).x;+ const auto fixedWidth = ( MaxSourceLength + 2 ) * ts.x;+ ImGui::ItemSize( ImVec2( fixedWidth - itemsWidth, 0 ) );++ }+ if( m_asmBytes )+ {+ auto code = (const uint8_t*)worker.GetSymbolCode( m_baseAddr, m_codeLen );+ assert( code );+ ImGui::SameLine( 0, stw );+ const auto len = PrintHexBytes( code + line.addr - m_baseAddr, line.len, worker.GetCpuArch() );+ ImGui::SameLine( 0, 0 );+ ImGui::ItemSize( ImVec2( stw * ( m_maxAsmBytes*2 - len ), ty ), 0 );+ }+ if( m_showJumps )+ {+ ImGui::SameLine( 0, 0 );+ const auto xoff = round( ImGui::GetCursorScreenPos().x - wpos.x + ( ty * 0.66f ) );+ m_jumpOffset = xoff;++ const auto JumpArrow = JumpArrowBase * ty / 15;+ const auto JumpSeparation = CalcJumpSeparation( ts.y / 15 );+ ImGui::SameLine( 0, ty + JumpArrow + m_maxJumpLevel * JumpSeparation );+ auto jit = m_jumpOut.find( line.addr );+ if( jit != m_jumpOut.end() )+ {+ const auto th2 = floor( ts.y / 2 );+ const auto th4 = floor( ts.y / 4 );+ const auto& mjl = m_maxJumpLevel;+ const auto col = GetHsvColor( line.jumpAddr, 6 );++ DrawLine( draw, dpos + ImVec2( xoff + JumpSeparation * mjl + th2, th2 ), dpos + ImVec2( xoff + JumpSeparation * mjl + th2 + JumpArrow / 2, th2 ), col );+ DrawLine( draw, dpos + ImVec2( xoff + JumpSeparation * mjl + th2, th2 ), dpos + ImVec2( xoff + JumpSeparation * mjl + th2 + th4, th2 - th4 ), col );+ DrawLine( draw, dpos + ImVec2( xoff + JumpSeparation * mjl + th2, th2 ), dpos + ImVec2( xoff + JumpSeparation * mjl + th2 + th4, th2 + th4 ), col );+ }+ }+ else+ {+ ImGui::SameLine( 0, ty );+ }++ int opdesc = 0;+ const AsmVar* asmVar = nullptr;+ if( m_cpuArch == CpuArchX64 || m_cpuArch == CpuArchX86 )+ {+ auto uarch = MicroArchitectureData[m_idxMicroArch];+ char tmp[32];+ for( size_t i=0; i<line.mnemonic.size(); i++ )+ {+ auto c = line.mnemonic[i];+ if( c >= 'a' && c <= 'z' ) c = c - 'a' + 'A';+ tmp[i] = c;+ }+ tmp[line.mnemonic.size()] = '\0';+ const char* mnemonic = tmp;+ if( strcmp( mnemonic, "LEA" ) == 0 )+ {+ static constexpr const char* LeaTable[] = { "LEA", "LEA_B", "LEA_BD", "LEA_BI", "LEA_BID", "LEA_D", "LEA_I", "LEA_ID", "LEA_R", "LEA_RD" };+ mnemonic = LeaTable[(int)line.leaData];+ }+ auto it = m_microArchOpMap.find( mnemonic );+ if( it != m_microArchOpMap.end() )+ {+ const auto opid = it->second;+ auto oit = std::lower_bound( uarch->ops, uarch->ops + uarch->numOps, opid, []( const auto& l, const auto& r ) { return l->id < r; } );+ if( oit != uarch->ops + uarch->numOps && (*oit)->id == opid )+ {+ const auto& op = *oit;+ opdesc = op->descId;+ std::vector<std::pair<int, int>> res;+ res.reserve( op->numVariants );+ for( int i=0; i<op->numVariants; i++ )+ {+ const auto& var = *op->variant[i];+ if( var.descNum == (int)line.params.size() )+ {+ int penalty = 0;+ bool match = true;+ for( int j=0; j<var.descNum; j++ )+ {+ if( var.desc[j].type != line.params[j].type )+ {+ match = false;+ break;+ }+ if( var.desc[j].width != line.params[j].width ) penalty++;+ }+ if( match )+ {+ res.emplace_back( i, penalty );+ }+ }+ }+ if( !res.empty() )+ {+ pdqsort_branchless( res.begin(), res.end(), []( const auto& l, const auto& r ) { return l.second < r.second; } );+ asmVar = op->variant[res[0].first];+ }+ }+ }+ }++ const bool inContext = IsInContext( worker, line.addr );+ int isSelected = asmIdx == m_asmSelected;+ if( !isSelected && line.regData[0] != 0 )+ {+ int idx = 0;+ while( line.regData[idx] != 0 )+ {+ if( line.regData[idx] & ( WriteBit | ReadBit ) )+ {+ isSelected = 2;+ break;+ }+ idx++;+ }+ }++ uint32_t jumpOffset;+ uint64_t jumpBase;+ const char* jumpName = nullptr;+ const char* normalized = nullptr;+ if( line.jumpAddr != 0 )+ {+ jumpOffset = 0;+ jumpBase = worker.GetSymbolForAddress( line.jumpAddr, jumpOffset );+ auto jumpSym = jumpBase == 0 ? worker.GetSymbolData( line.jumpAddr ) : worker.GetSymbolData( jumpBase );+ if( jumpSym )+ {+ if( worker.HasInlineSymbolAddresses() )+ {+ const auto symAddr = worker.GetInlineSymbolForAddress( line.jumpAddr );+ if( symAddr != 0 )+ {+ const auto symData = worker.GetSymbolData( symAddr );+ if( symData ) jumpName = worker.GetString( symData->name );+ }+ }+ if( !jumpName ) jumpName = worker.GetString( jumpSym->name );+ if( jumpName ) normalized = view.GetShortenName() != ShortenName::Never ? ShortenZoneName( ShortenName::OnlyNormalize, jumpName ) : jumpName;+ }+ }++ ImGui::BeginGroup();+ TextColoredUnformatted( AsmColor( AsmOpTypeColors[(int)line.opType], inContext, isSelected ), line.mnemonic.c_str() );+ ImGui::SameLine( 0, ImGui::CalcTextSize( " " ).x * ( m_maxMnemonicLen - line.mnemonic.size() ) );+ bool hasJump = false;+ if( line.jumpAddr != 0 )+ {+ auto lit = m_locMap.find( line.jumpAddr );+ if( lit != m_locMap.end() )+ {+ ImGui::PushStyleColor( ImGuiCol_Text, AsmColor( AsmSyntaxColors[(int)Tokenizer::AsmTokenColor::Label], inContext, isSelected ) );+ ImGui::Text( ".L%" PRIu32, lit->second );+ ImGui::PopStyleColor();+ hasJump = true;+ }+ }+ if( !hasJump && jumpName && jumpBase != m_baseAddr )+ {+ ImGui::PushStyleColor( ImGuiCol_Text, AsmColor( AsmSyntaxColors[(int)Tokenizer::AsmTokenColor::Label], inContext, isSelected ) );+ if( jumpOffset == 0 )+ {+ ImGui::Text( "%s", normalized );+ }+ else+ {+ ImGui::Text( "%s+%" PRIu32, normalized, jumpOffset );+ }+ ImGui::PopStyleColor();+ hasJump = true;+ }+ if( !hasJump )+ {+ auto ptr = line.operands.c_str();+ auto end = ptr + line.operands.size();+ auto it = line.opTokens.begin();+ while( ptr < end )+ {+ if( it == line.opTokens.end() )+ {+ ImGui::TextUnformatted( ptr, end );+ ImGui::SameLine( 0, 0 );+ break;+ }+ if( ptr < it->begin )+ {+ ImGui::TextUnformatted( ptr, it->begin );+ ImGui::SameLine( 0, 0 );+ }+ TextColoredUnformatted( AsmColor( AsmSyntaxColors[(int)it->color], inContext, isSelected ), it->begin, it->end );+ ImGui::SameLine( 0, 0 );+ ptr = it->end;+ ++it;+ }+ ImGui::ItemSize( ImVec2( 0, 0 ), 0 );+ }+ ImGui::EndGroup();++ if( ImGui::IsItemHovered() )+ {+ if( asmVar )+ {+ const auto& var = *asmVar;+ UnsetFont();+ ImGui::BeginTooltip();+ if( jumpName || opdesc != 0 )+ {+ if( opdesc != 0 )+ {+ ImGui::TextUnformatted( OpDescList[opdesc] );+ if( line.opType == OpType::Privileged )+ {+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ TextColoredUnformatted( AsmOpTypeColors[(int)OpType::Privileged], "privileged" );+ }+ }+ else if( line.opType == OpType::Privileged )+ {+ TextColoredUnformatted( AsmOpTypeColors[(int)OpType::Privileged], "Privileged" );+ }+ if( jumpName )+ {+ if( jumpBase == m_baseAddr )+ {+ TextDisabledUnformatted( "Local target:" );+ }+ else+ {+ TextDisabledUnformatted( "External target:" );+ }+ ImGui::SameLine();+ if( jumpOffset == 0 )+ {+ ImGui::Text( "%s", normalized );+ }+ else+ {+ ImGui::Text( "%s+%" PRIu32, normalized, jumpOffset );+ }+ if( normalized != jumpName )+ {+ ImGui::PushFont( m_smallFont );+ TextDisabledUnformatted( jumpName );+ ImGui::PopFont();+ }+ if( jumpBase == m_baseAddr )+ {+ uint32_t srcline;+ const auto srcidx = worker.GetLocationForAddress( line.jumpAddr, srcline );+ if( srcline != 0 )+ {+ const auto fileName = worker.GetString( srcidx );+ const auto fileColor = GetHsvColor( srcidx.Idx(), 0 );+ TextDisabledUnformatted( "Target location:" );+ ImGui::SameLine();+ SmallColorBox( fileColor );+ ImGui::SameLine();+ ImGui::Text( "%s:%i", fileName, srcline );+ }+ }+ }+ ImGui::Separator();+ }++ TextFocused( "Throughput:", RealToString( var.tp ) );+ ImGui::SameLine();+ TextDisabledUnformatted( "(cycles per instruction, lower is better)" );+ if( var.maxlat >= 0 )+ {+ bool exact = false;+ TextDisabledUnformatted( "Latency:" );+ ImGui::SameLine();+ if( var.minlat == var.maxlat && var.minbound == var.maxbound )+ {+ if( var.minbound )+ {+ ImGui::Text( "\xe2\x89\xa4%s", RealToString( var.minlat ) );+ }+ else+ {+ ImGui::TextUnformatted( RealToString( var.minlat ) );+ exact = true;+ }+ }+ else+ {+ if( var.minbound )+ {+ ImGui::Text( "[\xe2\x89\xa4%s", RealToString( var.minlat ) );+ }+ else+ {+ ImGui::Text( "[%s", RealToString( var.minlat ) );+ }+ ImGui::SameLine( 0, 0 );+ if( var.maxbound )+ {+ ImGui::Text( " \xE2\x80\x93 \xe2\x89\xa4%s]", RealToString( var.maxlat ) );+ }+ else+ {+ ImGui::Text( " \xE2\x80\x93 %s]", RealToString( var.maxlat ) );+ }+ }+ ImGui::SameLine();+ if( exact )+ {+ TextDisabledUnformatted( "(cycles in execution)" );+ }+ else+ {+ TextDisabledUnformatted( "(cycles in execution, may vary by used output)" );+ }+ }+ TextFocused( "\xce\xbcops:", RealToString( var.uops ) );+ if( var.port != -1 ) TextFocused( "Ports:", PortList[var.port] );+ ImGui::Separator();+ TextFocused( "ISA set:", IsaList[var.isaSet] );+ if( var.descNum > 0 )+ {+ TextDisabledUnformatted( "Operands:" );+ ImGui::SameLine();+ bool first = true;+ for( int i=0; i<var.descNum; i++ )+ {+ const char* t = "?";+ switch( var.desc[i].type )+ {+ case 0:+ t = "Imm";+ break;+ case 1:+ t = "Reg";+ break;+ case 2:+ t = var.desc[i].width == 0 ? "AGen" : "Mem";+ break;+ default:+ assert( false );+ break;+ }+ if( first )+ {+ first = false;+ if( var.desc[i].width == 0 )+ {+ ImGui::TextUnformatted( t );+ }+ else+ {+ ImGui::Text( "%s%i", t, var.desc[i].width );+ }+ }+ else+ {+ ImGui::SameLine( 0, 0 );+ if( var.desc[i].width == 0 )+ {+ ImGui::Text( ", %s", t );+ }+ else+ {+ ImGui::Text( ", %s%i", t, var.desc[i].width );+ }+ }+ }+ }+ ImGui::EndTooltip();+ SetFont();+ }+ else if( jumpName )+ {+ UnsetFont();+ ImGui::BeginTooltip();+ if( jumpBase == m_baseAddr )+ {+ TextDisabledUnformatted( "Local target:" );+ }+ else+ {+ TextDisabledUnformatted( "External target:" );+ }+ ImGui::SameLine();+ if( jumpOffset == 0 )+ {+ ImGui::Text( "%s", normalized );+ }+ else+ {+ ImGui::Text( "%s+%" PRIu32, normalized, jumpOffset );+ }+ if( normalized != jumpName && strcmp( normalized, jumpName ) != 0 )+ {+ ImGui::PushFont( m_smallFont );+ TextDisabledUnformatted( jumpName );+ ImGui::PopFont();+ }+ if( jumpBase == m_baseAddr )+ {+ uint32_t srcline;+ const auto srcidx = worker.GetLocationForAddress( line.jumpAddr, srcline );+ if( srcline != 0 )+ {+ const auto fileName = worker.GetString( srcidx );+ const auto fileColor = GetHsvColor( srcidx.Idx(), 0 );+ TextDisabledUnformatted( "Target location:" );+ ImGui::SameLine();+ SmallColorBox( fileColor );+ ImGui::SameLine();+ ImGui::Text( "%s:%i", fileName, srcline );+ }+ }+ ImGui::EndTooltip();+ SetFont();+ }+ if( m_cpuArch == CpuArchX86 || m_cpuArch == CpuArchX64 )+ {+ if( line.readX86[0] != RegsX86::invalid || line.writeX86[0] != RegsX86::invalid )+ {+ UnsetFont();+ ImGui::BeginTooltip();+ if( asmVar ) ImGui::Separator();+ if( line.readX86[0] != RegsX86::invalid )+ {+ TextDisabledUnformatted( "Read:" );+ ImGui::SameLine();+ int idx = 0;+ for(;;)+ {+ if( line.readX86[idx] == RegsX86::invalid ) break;+ if( idx == 0 )+ {+ ImGui::TextUnformatted( s_regNameX86[(int)line.readX86[idx++]] );+ }+ else+ {+ ImGui::SameLine( 0, 0 );+ ImGui::Text( ", %s", s_regNameX86[(int)line.readX86[idx++]] );+ }+ }+ }+ if( line.writeX86[0] != RegsX86::invalid )+ {+ TextDisabledUnformatted( "Write:" );+ ImGui::SameLine();+ int idx = 0;+ for(;;)+ {+ if( line.writeX86[idx] == RegsX86::invalid ) break;+ if( idx == 0 )+ {+ ImGui::TextUnformatted( s_regNameX86[(int)line.writeX86[idx++]] );+ }+ else+ {+ ImGui::SameLine( 0, 0 );+ ImGui::Text( ", %s", s_regNameX86[(int)line.writeX86[idx++]] );+ }+ }+ }+ ImGui::EndTooltip();+ SetFont();+ }+ }+ if( ImGui::IsMouseClicked( 0 ) )+ {+ m_asmSelected = asmIdx;+ ResetAsm();+ int idx = 0;+ for(;;)+ {+ if( line.readX86[idx] == RegsX86::invalid ) break;+ line.regData[idx] = ReadBit | (int)line.readX86[idx];+ FollowWrite( asmIdx, line.readX86[idx++], 64 );+ }+ idx = 0;+ for(;;)+ {+ if( line.writeX86[idx] == RegsX86::invalid ) break;+ int ridx = 0;+ for(;;)+ {+ if( line.regData[ridx] == 0 )+ {+ line.regData[ridx] = WriteBit | (int)line.writeX86[idx];+ break;+ }+ else if( ( line.regData[ridx] & RegMask ) == (int)line.writeX86[idx] )+ {+ line.regData[ridx] |= WriteBit;+ break;+ }+ ridx++;+ }+ FollowRead( asmIdx, line.writeX86[idx++], 64 );+ }+ }+ else if( ImGui::IsMouseClicked( 1 ) )+ {+ m_asmSelected = -1;+ ResetAsm();+ }+ }++ auto lit = m_locMap.find( line.addr );+ if( lit != m_locMap.end() )+ {+ ImGui::SameLine();+ ImGui::TextDisabled( " ; .L%" PRIu32, lit->second );+ }++ if( line.regData[0] != 0 )+ {+ if( !line.params.empty() )+ {+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ }+ else+ {+ ImGui::SameLine( 0, 0 );+ }+ TextColoredUnformatted( ImVec4( 0.5f, 0.5, 1, 1 ), " {" );+ ImGui::SameLine( 0, 0 );+ int idx = 0;+ for(;;)+ {+ ImVec4 col;+ if( line.regData[idx] == 0 ) break;+ if( ( line.regData[idx] & ( WriteBit | ReadBit ) ) == ( WriteBit | ReadBit ) ) col = ImVec4( 1, 1, 0.5f, 1 );+ else if( line.regData[idx] & WriteBit ) col = ImVec4( 1, 0.5f, 0.5f, 1 );+ else if( line.regData[idx] & ReadBit ) col = ImVec4( 0.5f, 1, 0.5f, 1 );+ else col = ImVec4( 0.5f, 0.5f, 0.5f, 1 );+ if( idx > 0 )+ {+ ImGui::SameLine( 0, 0 );+ TextColoredUnformatted( ImVec4( 0.5f, 0.5, 1, 1 ), ", " );+ ImGui::SameLine( 0, 0 );+ }+ TextColoredUnformatted( col, s_regNameX86[line.regData[idx] & RegMask] );+ if( ImGui::IsItemHovered() )+ {+ ImGui::BeginTooltip();+ if( ( line.regData[idx] & ( WriteBit | ReadBit ) ) == ( WriteBit | ReadBit ) ) ImGui::TextUnformatted( "Read and write" );+ else if( line.regData[idx] & WriteBit ) ImGui::TextUnformatted( "Write" );+ else if( line.regData[idx] & ReadBit ) ImGui::TextUnformatted( "Read" );+ else ImGui::TextUnformatted( "Previous read" );+ ImGui::EndTooltip();+ }+ idx++;+ }+ ImGui::SameLine( 0, 0 );+ TextColoredUnformatted( ImVec4( 0.5f, 0.5, 1, 1 ), "}" );+ }++ if( jumpName )+ {+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ if( jumpBase == m_baseAddr )+ {+ ImGui::TextDisabled( " -> [%s]", normalized );+ if( ImGui::IsItemHovered() )+ {+ UnsetFont();+ ImGui::BeginTooltip();+ if( normalized != jumpName && strcmp( normalized, jumpName ) != 0 )+ {+ ImGui::TextUnformatted( jumpName );+ }+ char tmp[32];+ sprintf( tmp, "+%" PRIu32, jumpOffset );+ TextFocused( "Jump target:", tmp );+ uint32_t srcline;+ const auto srcidx = worker.GetLocationForAddress( line.jumpAddr, srcline );+ if( srcline != 0 )+ {+ const auto fileName = worker.GetString( srcidx );+ if( fileName )+ {+ if( SourceFileValid( fileName, worker.GetCaptureTime(), view, worker ) )+ {+ m_sourceTooltip.Parse( fileName, worker, view );+ if( !m_sourceTooltip.empty() )+ {+ ImGui::Separator();+ SetFont();+ PrintSourceFragment( m_sourceTooltip, srcline );+ UnsetFont();+ }+ }+ }+ }+ ImGui::EndTooltip();+ SetFont();+ m_highlightAddr = line.jumpAddr;+ if( ImGui::IsItemClicked() )+ {+ m_targetAddr = line.jumpAddr;+ m_selectedAddresses.clear();+ m_selectedAddresses.emplace( line.jumpAddr );+ }+ }+ }+ else+ {+ ImGui::TextDisabled( " [%s]", line.operands.c_str() );+ if( ImGui::IsItemClicked() )+ {+ jumpOut = line.jumpAddr;+ }+ }+ }++ if( lineHovered )+ {+ draw->AddRectFilled( wpos, wpos + ImVec2( w, ty+1 ), 0x11FFFFFF );+ }++ DrawLine( draw, dpos + ImVec2( 0, ty ), dpos + ImVec2( w, ty ), 0x08FFFFFF );+}++void SourceView::RenderHwLinePart( size_t cycles, size_t retired, size_t branchRetired, size_t branchMiss, size_t cacheRef, size_t cacheMiss, size_t branchRel, size_t branchRelMax, size_t cacheRel, size_t cacheRelMax, const ImVec2& ts )+{+ if( cycles )+ {+ const bool unreliable = cycles < 10 || retired < 10;+ const float ipc = float( retired ) / cycles;+ uint32_t col = unreliable ? 0x44FFFFFF : GetGoodnessColor( ipc * 0.25f );+ if( ipc >= 10 )+ {+ TextColoredUnformatted( col, " 10+ " );+ }+ else+ {+ char buf[16];+ const auto end = PrintFloat( buf, buf+16, ipc, 2 );+ assert( end == buf + 4 );+ memcpy( end, " ", 2 );+ TextColoredUnformatted( col, buf );+ }+ if( ImGui::IsItemHovered() )+ {+ UnsetFont();+ ImGui::BeginTooltip();+ ImGui::TextUnformatted( "Instructions Per Cycle (IPC)" );+ ImGui::SameLine();+ TextDisabledUnformatted( "Higher is better" );+ ImGui::Separator();+ TextFocused( "Cycles:", RealToString( cycles ) );+ TextFocused( "Retirements:", RealToString( retired ) );+ if( unreliable ) TextColoredUnformatted( 0xFF4444FF, "Not enough samples for reliable data!" );+ ImGui::EndTooltip();+ SetFont();+ }+ }+ else+ {+ ImGui::ItemSize( ImVec2( 5 * ts.x, ts.y ) );+ }+ ImGui::SameLine( 0, 0 );+ if( m_hwSamplesRelative )+ {+ if( branchRel && branchRelMax )+ {+ const float rate = float( branchRel ) / branchRelMax;+ uint32_t col = GetGoodnessColor( 1.f - rate * 3.f );+ if( rate >= 1.f )+ {+ TextColoredUnformatted( col, " 100% " );+ }+ else+ {+ char buf[16];+ const auto end = PrintFloat( buf, buf+16, rate * 100, 1 );+ memcpy( end, "% ", 3 );+ if( end - buf == 4 )+ {+ TextColoredUnformatted( col, buf );+ }+ else+ {+ ImGui::SameLine( 0, ts.x );+ TextColoredUnformatted( col, buf );+ }+ }+ if( ImGui::IsItemHovered() )+ {+ UnsetFont();+ ImGui::BeginTooltip();+ ImGui::TextUnformatted( "Branch mispredictions impact" );+ ImGui::SameLine();+ TextDisabledUnformatted( "Lower is better" );+ ImGui::Separator();+ TextFocused( "Impact value:", RealToString( branchRel ) );+ TextFocused( "Relative to:", RealToString( branchRelMax ) );+ ImGui::EndTooltip();+ SetFont();+ }+ }+ else+ {+ ImGui::ItemSize( ImVec2( 6 * ts.x, ts.y ) );+ }+ ImGui::SameLine( 0, 0 );+ if( cacheRel && cacheRelMax )+ {+ const float rate = float( cacheRel ) / cacheRelMax;+ uint32_t col = GetGoodnessColor( 1.f - rate * 3.f );+ if( rate >= 1.f )+ {+ TextColoredUnformatted( col, " 100%" );+ }+ else+ {+ char buf[16];+ const auto end = PrintFloat( buf, buf+16, rate * 100, 1 );+ memcpy( end, "%", 2 );+ if( end - buf == 4 )+ {+ TextColoredUnformatted( col, buf );+ }+ else+ {+ ImGui::SameLine( 0, ts.x );+ TextColoredUnformatted( col, buf );+ }+ }+ if( ImGui::IsItemHovered() )+ {+ UnsetFont();+ ImGui::BeginTooltip();+ ImGui::TextUnformatted( "Cache miss rate impact" );+ ImGui::SameLine();+ TextDisabledUnformatted( "Lower is better" );+ ImGui::Separator();+ TextFocused( "Impact value:", RealToString( cacheRel ) );+ TextFocused( "Relative to:", RealToString( cacheRelMax ) );+ ImGui::EndTooltip();+ SetFont();+ }+ }+ else+ {+ ImGui::ItemSize( ImVec2( 5 * ts.x, ts.y ) );+ }+ }+ else+ {+ if( branchRetired )+ {+ const bool unreliable = branchRetired < 10;+ const float rate = float( branchMiss ) / branchRetired;+ uint32_t col = unreliable ? 0x44FFFFFF : GetGoodnessColor( 1.f - rate * 3.f );+ if( branchMiss == 0 )+ {+ TextColoredUnformatted( col, " 0% " );+ }+ else if( rate >= 1.f )+ {+ TextColoredUnformatted( col, " 100% " );+ }+ else+ {+ char buf[16];+ const auto end = PrintFloat( buf, buf+16, rate * 100, 1 );+ memcpy( end, "% ", 3 );+ if( end - buf == 4 )+ {+ TextColoredUnformatted( col, buf );+ }+ else+ {+ ImGui::SameLine( 0, ts.x );+ TextColoredUnformatted( col, buf );+ }+ }+ if( ImGui::IsItemHovered() )+ {+ UnsetFont();+ ImGui::BeginTooltip();+ ImGui::TextUnformatted( "Branch mispredictions rate" );+ ImGui::SameLine();+ TextDisabledUnformatted( "Lower is better" );+ ImGui::Separator();+ TextFocused( "Retired branches:", RealToString( branchRetired ) );+ TextFocused( "Branch mispredictions:", RealToString( branchMiss ) );+ if( unreliable ) TextColoredUnformatted( 0xFF4444FF, "Not enough samples for reliable data!" );+ ImGui::EndTooltip();+ SetFont();+ }+ }+ else+ {+ ImGui::ItemSize( ImVec2( 6 * ts.x, ts.y ) );+ }+ ImGui::SameLine( 0, 0 );+ if( cacheRef )+ {+ const bool unreliable = cacheRef < 10;+ const float rate = float( cacheMiss ) / cacheRef;+ uint32_t col = unreliable ? 0x44FFFFFF : GetGoodnessColor( 1.f - rate * 3.f );+ if( cacheMiss == 0 )+ {+ TextColoredUnformatted( col, " 0%" );+ }+ else if( rate >= 1.f )+ {+ TextColoredUnformatted( col, " 100%" );+ }+ else+ {+ char buf[16];+ const auto end = PrintFloat( buf, buf+16, rate * 100, 1 );+ memcpy( end, "%", 2 );+ if( end - buf == 4 )+ {+ TextColoredUnformatted( col, buf );+ }+ else+ {+ ImGui::SameLine( 0, ts.x );+ TextColoredUnformatted( col, buf );+ }+ }+ if( ImGui::IsItemHovered() )+ {+ UnsetFont();+ ImGui::BeginTooltip();+ ImGui::TextUnformatted( "Cache miss rate" );+ ImGui::SameLine();+ TextDisabledUnformatted( "Lower is better" );+ ImGui::Separator();+ TextFocused( "Cache references:", RealToString( cacheRef ) );+ TextFocused( "Cache misses:", RealToString( cacheMiss ) );+ if( unreliable ) TextColoredUnformatted( 0xFF4444FF, "Not enough samples for reliable data!" );+ ImGui::EndTooltip();+ SetFont();+ }+ }+ else+ {+ ImGui::ItemSize( ImVec2( 5 * ts.x, ts.y ) );+ }+ }+}++void SourceView::SelectLine( uint32_t line, const Worker* worker, bool updateAsmLine, uint64_t targetAddr, bool changeAsmLine )+{+ m_selectedLine = line;+ if( m_symAddr == 0 ) return;+ assert( worker );+ SelectAsmLines( m_source.idx(), line, *worker, updateAsmLine, targetAddr, changeAsmLine );+}++void SourceView::SelectAsmLines( uint32_t file, uint32_t line, const Worker& worker, bool updateAsmLine, uint64_t targetAddr, bool changeAsmLine )+{+ m_selectedAddresses.clear();+ auto addresses = GetAddressesForLocation( file, line, worker );+ if( addresses )+ {+ const auto& addr = *addresses;+ if( updateAsmLine )+ {+ for( auto& v : addr )+ {+ if( v >= m_baseAddr && v < m_baseAddr + m_codeLen )+ {+ if( IsInContext( worker, v ) ) m_selectedAddresses.emplace( v );+ }+ }+ if( targetAddr != 0 )+ {+ if( changeAsmLine ) m_targetAddr = targetAddr;+ }+ else if( !m_selectedAddresses.empty() )+ {+ if( m_asmTarget.file != file || m_asmTarget.line != line )+ {+ m_asmTarget.file = file;+ m_asmTarget.line = line;+ m_asmTarget.sel = 0;+ m_asmTarget.target.clear();++ std::vector<uint64_t> tmp;+ tmp.reserve( m_selectedAddresses.size() );+ for( auto& v : m_selectedAddresses ) tmp.emplace_back( v );+ pdqsort_branchless( tmp.begin(), tmp.end() );++ bool first = true;+ auto lit = m_asm.begin();+ for( auto& v : tmp )+ {+ const auto prev = lit;+ while( lit->addr != v ) lit++;+ if( first || lit - prev > 1 )+ {+ first = false;+ m_asmTarget.target.emplace_back( v );+ }+ }+ if( changeAsmLine ) m_targetAddr = m_asmTarget.target[0];+ }+ else if( changeAsmLine )+ {+ m_asmTarget.sel = ( m_asmTarget.sel + 1 ) % m_asmTarget.target.size();+ m_targetAddr = m_asmTarget.target[m_asmTarget.sel];+ }+ }+ }+ }+}++void SourceView::SelectAsmLinesHover( uint32_t file, uint32_t line, const Worker& worker )+{+ assert( m_selectedAddressesHover.empty() );+ auto addresses = GetAddressesForLocation( file, line, worker );+ if( addresses )+ {+ for( auto& v : *addresses )+ {+ if( v >= m_baseAddr && v < m_baseAddr + m_codeLen )+ {+ if( IsInContext( worker, v ) ) m_selectedAddressesHover.emplace( v );+ }+ }+ }+}++void SourceView::GatherIpHwStats( AddrStatData& as, Worker& worker, const View& view, CostType cost )+{+ auto filename = m_source.filename();+ for( auto& v : m_asm )+ {+ const auto& addr = v.addr;+ if( m_calcInlineStats && worker.GetInlineSymbolForAddress( addr ) != m_symAddr ) continue;+ const auto hw = worker.GetHwSampleData( addr );+ if( !hw ) continue;+ uint64_t stat;+ if( view.m_statRange.active )+ {+ switch( cost )+ {+ case CostType::Cycles: stat = CountHwSamples( hw->cycles, view.m_statRange ); break;+ case CostType::Retirements: stat = CountHwSamples( hw->retired, view.m_statRange ); break;+ case CostType::BranchesTaken: stat = CountHwSamples( hw->branchRetired, view.m_statRange ); break;+ case CostType::BranchMiss: stat = CountHwSamples( hw->branchMiss, view.m_statRange ); break;+ case CostType::SlowBranches: stat = sqrt( CountHwSamples( hw->branchMiss, view.m_statRange ) * CountHwSamples( hw->branchRetired, view.m_statRange ) ); break;+ case CostType::CacheAccess: stat = CountHwSamples( hw->cacheRef, view.m_statRange ); break;+ case CostType::CacheMiss: stat = CountHwSamples( hw->cacheMiss, view.m_statRange ); break;+ case CostType::SlowCache: stat = sqrt( CountHwSamples( hw->cacheMiss, view.m_statRange ) * CountHwSamples( hw->cacheRef, view.m_statRange ) ); break;+ default: assert( false ); return;+ }+ }+ else+ {+ switch( cost )+ {+ case CostType::Cycles: stat = hw->cycles.size(); break;+ case CostType::Retirements: stat = hw->retired.size(); break;+ case CostType::BranchesTaken: stat = hw->branchRetired.size(); break;+ case CostType::BranchMiss: stat = hw->branchMiss.size(); break;+ case CostType::SlowBranches: stat = sqrt( hw->branchMiss.size() * hw->branchRetired.size() ); break;+ case CostType::CacheAccess: stat = hw->cacheRef.size(); break;+ case CostType::CacheMiss: stat = hw->cacheMiss.size(); break;+ case CostType::SlowCache: stat = sqrt( hw->cacheMiss.size() * hw->cacheRef.size() ); break;+ default: assert( false ); return;+ }+ }+ assert( as.ipCountAsm.find( addr ) == as.ipCountAsm.end() );+ as.ipCountAsm.emplace( addr, AddrStat { stat, 0 } );+ as.ipTotalAsm.local += stat;+ if( as.ipMaxAsm.local < stat ) as.ipMaxAsm.local = stat;++ if( filename )+ {+ auto frame = worker.GetCallstackFrame( worker.PackPointer( addr ) );+ if( frame )+ {+ const auto end = m_propagateInlines ? frame->size : 1;+ for( uint8_t i=0; i<end; i++ )+ {+ const auto line = frame->data[i].line;+ if( line != 0 )+ {+ auto ffn = worker.GetString( frame->data[i].file );+ if( strcmp( ffn, filename ) == 0 )+ {+ auto it = as.ipCountSrc.find( line );+ if( it == as.ipCountSrc.end() )+ {+ as.ipCountSrc.emplace( line, AddrStat{ stat, 0 } );+ if( as.ipMaxSrc.local < stat ) as.ipMaxSrc.local = stat;+ }+ else+ {+ const auto sum = it->second.local + stat;+ it->second.local = sum;+ if( as.ipMaxSrc.local < sum ) as.ipMaxSrc.local = sum;+ }+ as.ipTotalSrc.local += stat;+ }+ }+ }+ }+ }+ }+}++void SourceView::CountHwStats( AddrStatData& as, Worker& worker, const View& view )+{+ const auto hasBranchRetirement = worker.HasHwBranchRetirement();+ auto filename = m_source.filename();+ for( auto& v : m_asm )+ {+ const auto& addr = v.addr;+ if( m_calcInlineStats && worker.GetInlineSymbolForAddress( addr ) != m_symAddr ) continue;+ const auto hw = worker.GetHwSampleData( addr );+ if( !hw ) continue;+ uint64_t branch, cache;+ if( view.m_statRange.active )+ {+ if( hasBranchRetirement )+ {+ branch = sqrt( CountHwSamples( hw->branchMiss, view.m_statRange ) * CountHwSamples( hw->branchRetired, view.m_statRange ) );+ }+ else+ {+ branch = CountHwSamples( hw->branchMiss, view.m_statRange );+ }+ cache = sqrt( CountHwSamples( hw->cacheMiss, view.m_statRange ) * CountHwSamples( hw->cacheRef, view.m_statRange ) );+ }+ else+ {+ if( hasBranchRetirement )+ {+ branch = sqrt( hw->branchMiss.size() * hw->branchRetired.size() );+ }+ else+ {+ branch = hw->branchMiss.size();+ }+ cache = sqrt( hw->cacheMiss.size() * hw->cacheRef.size() );+ }+ assert( as.hwCountAsm.find( addr ) == as.hwCountAsm.end() );+ as.hwCountAsm.emplace( addr, AddrStat { branch, cache } );+ if( as.hwMaxAsm.local < branch ) as.hwMaxAsm.local = branch;+ if( as.hwMaxAsm.ext < cache ) as.hwMaxAsm.ext = cache;++ if( filename )+ {+ auto frame = worker.GetCallstackFrame( worker.PackPointer( addr ) );+ if( frame )+ {+ const auto end = m_propagateInlines ? frame->size : 1;+ for( uint8_t i=0; i<end; i++ )+ {+ const auto line = frame->data[i].line;+ if( line != 0 )+ {+ auto ffn = worker.GetString( frame->data[i].file );+ if( strcmp( ffn, filename ) == 0 )+ {+ auto it = as.hwCountSrc.find( line );+ if( it == as.hwCountSrc.end() )+ {+ as.hwCountSrc.emplace( line, AddrStat{ branch, cache } );+ if( as.hwMaxSrc.local < branch ) as.hwMaxSrc.local = branch;+ if( as.hwMaxSrc.ext < cache ) as.hwMaxSrc.ext = cache;+ }+ else+ {+ const auto branchSum = it->second.local + branch;+ const auto cacheSum = it->second.ext + cache;+ it->second.local = branchSum;+ it->second.ext = cacheSum;+ if( as.hwMaxSrc.local < branchSum ) as.hwMaxSrc.local = branchSum;+ if( as.hwMaxSrc.ext < cacheSum ) as.hwMaxSrc.ext = cacheSum;+ }+ }+ }+ }+ }+ }+ }+}++void SourceView::GatherIpStats( uint64_t baseAddr, AddrStatData& as, const Worker& worker, bool limitView, const View& view )+{+ auto filename = m_source.filename();+ if( limitView )+ {+ auto vec = worker.GetSamplesForSymbol( baseAddr );+ if( !vec ) return;+ auto it = std::lower_bound( vec->begin(), vec->end(), view.m_statRange.min, [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs; } );+ if( it == vec->end() ) return;+ auto end = std::lower_bound( it, vec->end(), view.m_statRange.max, [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs; } );+ as.ipTotalAsm.local += end - it;+ while( it != end )+ {+ if( filename )+ {+ auto frame = worker.GetCallstackFrame( it->ip );+ if( frame )+ {+ const auto end = m_propagateInlines ? frame->size : 1;+ for( uint8_t i=0; i<end; i++ )+ {+ const auto line = frame->data[i].line;+ if( line != 0 )+ {+ auto ffn = worker.GetString( frame->data[i].file );+ if( strcmp( ffn, filename ) == 0 )+ {+ auto sit = as.ipCountSrc.find( line );+ if( sit == as.ipCountSrc.end() )+ {+ as.ipCountSrc.emplace( line, AddrStat { 1, 0 } );+ if( as.ipMaxSrc.local < 1 ) as.ipMaxSrc.local = 1;+ }+ else+ {+ const auto sum = sit->second.local + 1;+ sit->second.local = sum;+ if( as.ipMaxSrc.local < sum ) as.ipMaxSrc.local = sum;+ }+ as.ipTotalSrc.local++;+ }+ }+ }+ }+ }++ auto addr = worker.GetCanonicalPointer( it->ip );+ auto sit = as.ipCountAsm.find( addr );+ if( sit == as.ipCountAsm.end() )+ {+ as.ipCountAsm.emplace( addr, AddrStat{ 1, 0 } );+ if( as.ipMaxAsm.local < 1 ) as.ipMaxAsm.local = 1;+ }+ else+ {+ const auto sum = sit->second.local + 1;+ sit->second.local = sum;+ if( as.ipMaxAsm.local < sum ) as.ipMaxAsm.local = sum;+ }++ ++it;+ }+ }+ else+ {+ auto ipmap = worker.GetSymbolInstructionPointers( baseAddr );+ if( !ipmap ) return;+ for( auto& ip : *ipmap )+ {+ auto addr = worker.GetCanonicalPointer( ip.first );+ assert( as.ipCountAsm.find( addr ) == as.ipCountAsm.end() );+ as.ipCountAsm.emplace( addr, AddrStat { ip.second, 0 } );+ as.ipTotalAsm.local += ip.second;+ if( as.ipMaxAsm.local < ip.second ) as.ipMaxAsm.local = ip.second;++ if( filename )+ {+ auto frame = worker.GetCallstackFrame( ip.first );+ if( frame )+ {+ const auto end = m_propagateInlines ? frame->size : 1;+ for( uint8_t i=0; i<end; i++ )+ {+ const auto line = frame->data[i].line;+ if( line != 0 )+ {+ auto ffn = worker.GetString( frame->data[i].file );+ if( strcmp( ffn, filename ) == 0 )+ {+ auto it = as.ipCountSrc.find( line );+ if( it == as.ipCountSrc.end() )+ {+ as.ipCountSrc.emplace( line, AddrStat{ ip.second, 0 } );+ if( as.ipMaxSrc.local < ip.second ) as.ipMaxSrc.local = ip.second;+ }+ else+ {+ const auto sum = it->second.local + ip.second;+ it->second.local = sum;+ if( as.ipMaxSrc.local < sum ) as.ipMaxSrc.local = sum;+ }+ as.ipTotalSrc.local += ip.second;+ }+ }+ }+ }+ }+ }+ }+}++void SourceView::GatherAdditionalIpStats( uint64_t baseAddr, AddrStatData& as, const Worker& worker, bool limitView, const View& view )+{+ if( !worker.AreSymbolSamplesReady() ) return;+ auto sym = worker.GetSymbolData( baseAddr );+ if( !sym ) return;++ auto filename = m_source.filename();+ if( limitView )+ {+ for( uint64_t ip = baseAddr; ip < baseAddr + sym->size.Val(); ip++ )+ {+ auto cp = worker.GetChildSamples( ip );+ if( !cp ) continue;+ auto it = std::lower_bound( cp->begin(), cp->end(), view.m_statRange.min, [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs; } );+ if( it == cp->end() ) continue;+ auto end = std::lower_bound( it, cp->end(), view.m_statRange.max, [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs; } );+ const auto ccnt = uint64_t( end - it );+ auto eit = as.ipCountAsm.find( ip );+ if( eit == as.ipCountAsm.end() )+ {+ as.ipCountAsm.emplace( ip, AddrStat { 0, ccnt } );+ }+ else+ {+ eit->second.ext += ccnt;+ }+ as.ipTotalAsm.ext += ccnt;+ if( as.ipMaxAsm.ext < ccnt ) as.ipMaxAsm.ext = ccnt;++ if( filename )+ {+ auto frame = worker.GetCallstackFrame( worker.PackPointer( ip ) );+ if( frame )+ {+ const auto end = m_propagateInlines ? frame->size : 1;+ for( uint8_t i=0; i<end; i++ )+ {+ const auto line = frame->data[i].line;+ if( line != 0 )+ {+ auto ffn = worker.GetString( frame->data[i].file );+ if( strcmp( ffn, filename ) == 0 )+ {+ auto sit = as.ipCountSrc.find( line );+ if( sit == as.ipCountSrc.end() )+ {+ as.ipCountSrc.emplace( line, AddrStat{ 0, ccnt } );+ if( as.ipMaxSrc.ext < ccnt ) as.ipMaxSrc.ext = ccnt;+ }+ else+ {+ const auto csum = sit->second.ext + ccnt;+ sit->second.ext = csum;+ if( as.ipMaxSrc.ext < csum ) as.ipMaxSrc.ext = csum;+ }+ as.ipTotalSrc.ext += ccnt;+ }+ }+ }+ }+ }+ }+ }+ else+ {+ for( uint64_t ip = baseAddr; ip < baseAddr + sym->size.Val(); ip++ )+ {+ auto cp = worker.GetChildSamples( ip );+ if( !cp ) continue;+ const auto ccnt = cp->size();+ auto eit = as.ipCountAsm.find( ip );+ if( eit == as.ipCountAsm.end() )+ {+ as.ipCountAsm.emplace( ip, AddrStat { 0, ccnt } );+ }+ else+ {+ eit->second.ext += ccnt;+ }+ as.ipTotalAsm.ext += ccnt;+ if( as.ipMaxAsm.ext < ccnt ) as.ipMaxAsm.ext = ccnt;++ if( filename )+ {+ auto frame = worker.GetCallstackFrame( worker.PackPointer( ip ) );+ if( frame )+ {+ const auto end = m_propagateInlines ? frame->size : 1;+ for( uint8_t i=0; i<end; i++ )+ {+ const auto line = frame->data[i].line;+ if( line != 0 )+ {+ auto ffn = worker.GetString( frame->data[i].file );+ if( strcmp( ffn, filename ) == 0 )+ {+ auto sit = as.ipCountSrc.find( line );+ if( sit == as.ipCountSrc.end() )+ {+ as.ipCountSrc.emplace( line, AddrStat{ 0, ccnt } );+ if( as.ipMaxSrc.ext < ccnt ) as.ipMaxSrc.ext = ccnt;+ }+ else+ {+ const auto csum = sit->second.ext + ccnt;+ sit->second.ext = csum;+ if( as.ipMaxSrc.ext < csum ) as.ipMaxSrc.ext = csum;+ }+ as.ipTotalSrc.ext += ccnt;+ }+ }+ }+ }+ }+ }+ }+}++void SourceView::GatherChildStats( uint64_t baseAddr, unordered_flat_map<uint64_t, uint32_t>& map, Worker& worker, bool limitView, const View& view )+{+ if( !worker.AreSymbolSamplesReady() ) return;+ auto sym = worker.GetSymbolData( baseAddr );+ if( !sym ) return;+ if( limitView )+ {+ for( uint64_t ip = baseAddr; ip < baseAddr + sym->size.Val(); ip++ )+ {+ auto cp = worker.GetChildSamples( ip );+ if( !cp ) continue;+ auto it = std::lower_bound( cp->begin(), cp->end(), view.m_statRange.min, [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs; } );+ if( it == cp->end() ) continue;+ auto end = std::lower_bound( it, cp->end(), view.m_statRange.max, [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs; } );+ while( it != end )+ {+ auto child = worker.GetSymbolForAddress( it->addr );+ auto mit = map.find( child );+ if( mit == map.end() )+ {+ map.emplace( child, 1 );+ }+ else+ {+ mit->second++;+ }+ ++it;+ }+ }+ }+ else+ {+ for( uint64_t ip = baseAddr; ip < baseAddr + sym->size.Val(); ip++ )+ {+ auto cp = worker.GetChildSamples( ip );+ if( !cp ) continue;+ for( auto& s : *cp )+ {+ auto child = worker.GetSymbolForAddress( s.addr );+ auto mit = map.find( child );+ if( mit == map.end() )+ {+ map.emplace( child, 1 );+ }+ else+ {+ mit->second++;+ }+ }+ }+ }+}++uint32_t SourceView::CountAsmIpStats( uint64_t baseAddr, const Worker& worker, bool limitView, const View& view )+{+ if( limitView )+ {+ auto vec = worker.GetSamplesForSymbol( baseAddr );+ if( !vec ) return 0;+ auto it = std::lower_bound( vec->begin(), vec->end(), view.m_statRange.min, [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs; } );+ if( it == vec->end() ) return 0;+ auto end = std::lower_bound( it, vec->end(), view.m_statRange.max, [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs; } );+ return end - it;+ }+ else+ {+ uint32_t cnt = 0;+ auto ipmap = worker.GetSymbolInstructionPointers( baseAddr );+ if( !ipmap ) return 0;+ for( auto& ip : *ipmap ) cnt += ip.second;+ return cnt;+ }+}++void SourceView::SelectMicroArchitecture( const char* moniker )+{+ int idx = 0;+ for( auto& v : s_uArchUx )+ {+ if( strcmp( v.moniker, moniker ) == 0 )+ {+ m_selMicroArch = idx;+ break;+ }+ idx++;+ }+ for( idx=0; idx<MicroArchitectureNum; idx++ )+ {+ if( strcmp( MicroArchitectureList[idx], moniker ) == 0 )+ {+ m_idxMicroArch = idx;+ break;+ }+ }+ assert( idx != MicroArchitectureNum );+}++void SourceView::ResetAsm()+{+ for( auto& line : m_asm ) memset( line.regData, 0, sizeof( line.regData ) );+}++void SourceView::FollowRead( size_t line, RegsX86 reg, size_t limit )+{+ if( limit == 0 ) return;+ const auto& data = m_asm[line];+ if( m_jumpOut.find( data.addr ) != m_jumpOut.end() && !data.jumpConditional ) return;+ if( data.jumpAddr != 0 )+ {+ auto fit = std::lower_bound( m_asm.begin(), m_asm.end(), data.jumpAddr, []( const auto& l, const auto& r ) { return l.addr < r; } );+ if( fit != m_asm.end() && fit->addr == data.jumpAddr )+ {+ CheckRead( fit - m_asm.begin(), reg, limit );+ }+ if( !data.jumpConditional ) return;+ }+ if( line+1 < m_asm.size() )+ {+ CheckRead( line+1, reg, limit );+ }+}++void SourceView::FollowWrite( size_t line, RegsX86 reg, size_t limit )+{+ if( limit == 0 ) return;+ const auto& data = m_asm[line];+ if( m_jumpOut.find( data.addr ) != m_jumpOut.end() && !data.jumpConditional ) return;+ auto it = m_jumpTable.find( data.addr );+ if( it != m_jumpTable.end() )+ {+ for( auto& v : it->second.source )+ {+ auto fit = std::lower_bound( m_asm.begin(), m_asm.end(), v, []( const auto& l, const auto& r ) { return l.addr < r; } );+ assert( fit != m_asm.end() && fit->addr == v );+ CheckWrite( fit - m_asm.begin(), reg, limit );+ }+ }+ if( line > 0 )+ {+ CheckWrite( line-1, reg, limit );+ }+}++void SourceView::CheckRead( size_t line, RegsX86 reg, size_t limit )+{+ assert( limit > 0 );+ auto& data = m_asm[line];+ int idx = 0;+ for(;;)+ {+ if( data.readX86[idx] == RegsX86::invalid )+ {+ idx = 0;+ for(;;)+ {+ if( data.writeX86[idx] == RegsX86::invalid )+ {+ FollowRead( line, reg, limit - 1 );+ return;+ }+ if( data.writeX86[idx] == reg )+ {+ idx = 0;+ for(;;)+ {+ if( data.regData[idx] == 0 )+ {+ data.regData[idx] = ReuseBit | (int)reg;+ return;+ }+ if( ( data.regData[idx] & RegMask ) == (int)reg )+ {+ data.regData[idx] |= ReuseBit;+ return;+ }+ idx++;+ }+ }+ idx++;+ }+ }+ if( data.readX86[idx] == reg )+ {+ idx = 0;+ for(;;)+ {+ if( data.regData[idx] == 0 )+ {+ data.regData[idx] = ReadBit | (int)reg;+ return;+ }+ if( ( data.regData[idx] & RegMask ) == (int)reg )+ {+ data.regData[idx] |= ReadBit;+ return;+ }+ idx++;+ }+ }+ idx++;+ }+}++void SourceView::CheckWrite( size_t line, RegsX86 reg, size_t limit )+{+ assert( limit > 0 );+ auto& data = m_asm[line];+ int idx = 0;+ for(;;)+ {+ if( data.writeX86[idx] == RegsX86::invalid )+ {+ idx = 0;+ for(;;)+ {+ if( data.readX86[idx] == RegsX86::invalid )+ {+ FollowWrite( line, reg, limit - 1 );+ return;+ }+ if( data.readX86[idx] == reg )+ {+ idx = 0;+ for(;;)+ {+ if( data.regData[idx] == 0 )+ {+ data.regData[idx] = ReuseBit | (int)reg;+ return;+ }+ if( ( data.regData[idx] & RegMask ) == (int)reg )+ {+ data.regData[idx] |= ReuseBit;+ return;+ }+ idx++;+ }+ }+ idx++;+ }++ }+ if( data.writeX86[idx] == reg )+ {+ idx = 0;+ for(;;)+ {+ if( data.regData[idx] == 0 )+ {+ data.regData[idx] = WriteBit | (int)reg;+ return;+ }+ else if( ( data.regData[idx] & RegMask ) == (int)reg )+ {+ data.regData[idx] |= WriteBit;+ return;+ }+ idx++;+ }+ }+ idx++;+ }+}++bool SourceView::IsInContext( const Worker& worker, uint64_t addr ) const+{+ return !m_calcInlineStats || !worker.HasInlineSymbolAddresses() || worker.GetInlineSymbolForAddress( addr ) == m_symAddr;+}++const std::vector<uint64_t>* SourceView::GetAddressesForLocation( uint32_t fileStringIdx, uint32_t line, const Worker& worker )+{+ if( m_locationAddress.empty() || m_propagateInlines != m_locAddrIsProp )+ {+ m_locationAddress.clear();+ m_locAddrIsProp = m_propagateInlines;++ for( auto& op : m_asm )+ {+ auto frame = worker.GetCallstackFrame( worker.PackPointer( op.addr ) );+ if( frame )+ {+ uint8_t end = m_propagateInlines ? frame->size : 1;+ for( uint8_t i=0; i<end; i++ )+ {+ const auto idx = frame->data[i].file.Idx();+ const auto line = frame->data[i].line;+ const auto packed = PackFileLine( idx, line );+ auto lit = m_locationAddress.find( packed );+ if( lit == m_locationAddress.end() )+ {+ m_locationAddress.emplace( packed, std::vector<uint64_t>( { op.addr } ) );+ }+ else+ {+ // In some cases debug data can be nonsense, assigning an inline function to the same line as the parent.+ // The specific example is in TracySysTrace.cpp:1150, which has the following local stack trace:+ // 1. RingBuffer::Enable() TracySysTrace.cpp:1150+ // 2. SysTraceWorker() TracySysTrace.cpp:1150+ // RingBuffer::Enable() is in TracyRingBuffer.hpp:74, and this line is assigned to the remaining asm lines+ // generated by this inline function. But for some reason, the parent call site is assigned for the first+ // asm line, that should be assigned to the inline function itself.+ // Workaround this by checking if the asm line address is already in the list.+ if( lit->second.back() == op.addr ) continue;++ assert( lit->second.back() < op.addr );+ lit->second.emplace_back( op.addr );+ }+ }+ }+ }+ }++ auto it = m_locationAddress.find( PackFileLine( fileStringIdx, line ) );+ if( it == m_locationAddress.end() )+ {+ return nullptr;+ }+ else+ {+ return &it->second;+ }+}++#ifndef TRACY_NO_FILESELECTOR+void SourceView::Save( const Worker& worker, size_t start, size_t stop )+{+ assert( start < m_asm.size() );+ assert( start < stop );++ Fileselector::SaveFile( "asm", "Assembly file", [this, &worker, start, stop]( const char* fn ) {+ FILE* f = nullptr;+ const auto sz = strlen( fn );+ if( sz < 5 || memcmp( fn + sz - 4, ".asm", 4 ) != 0 )+ {+ char tmp[1024];+ sprintf( tmp, "%s.asm", fn );+ f = fopen( tmp, "wb" );+ }+ else+ {+ f = fopen( fn, "wb" );+ }+ if( !f ) return;+ char tmp[32];+ auto sym = worker.GetSymbolData( m_symAddr );+ assert( sym );+ const char* symName;+ if( sym->isInline )+ {+ auto parent = worker.GetSymbolData( m_baseAddr );+ if( parent )+ {+ symName = worker.GetString( parent->name );+ }+ else+ {+ sprintf( tmp, "0x%" PRIx64, m_baseAddr );+ symName = tmp;+ }+ }+ else+ {+ symName = worker.GetString( sym->name );+ }+ fprintf( f, "# Tracy Profiler disassembly of symbol %s [%s]\n\n", symName, worker.GetCaptureProgram().c_str() );+ fprintf( f, ".intel_syntax\n\n" );++ const auto end = m_asm.size() < stop ? m_asm.size() : stop;+ for( size_t i=start; i<end; i++ )+ {+ const auto& v = m_asm[i];+ auto it = m_locMap.find( v.addr );+ if( it != m_locMap.end() )+ {+ fprintf( f, ".L%" PRIu32 ":\n", it->second );+ }+ bool hasJump = false;+ int psz = 0;+ if( v.jumpAddr != 0 )+ {+ auto lit = m_locMap.find( v.jumpAddr );+ if( lit != m_locMap.end() )+ {+ psz = fprintf( f, "\t%-*s.L%" PRIu32, m_maxMnemonicLen, v.mnemonic.c_str(), lit->second );+ hasJump = true;+ }+ }+ if( !hasJump )+ {+ if( v.operands.empty() )+ {+ psz = fprintf( f, "\t%s", v.mnemonic.c_str() );+ }+ else+ {+ psz = fprintf( f, "\t%-*s%s", m_maxMnemonicLen, v.mnemonic.c_str(), v.operands.c_str() );+ }+ }+ uint32_t srcline;+ const auto srcidx = worker.GetLocationForAddress( v.addr, srcline );+ if( srcline != 0 && psz > 0 )+ {+ int spaces = std::max( m_maxMnemonicLen + m_maxOperandLen - psz, 0 ) + 1;+ while( spaces-- ) fputc( ' ', f );+ fprintf( f, "# %s:%i\n", worker.GetString( srcidx ), srcline );+ }+ else+ {+ fputc( '\n', f );+ }+ }+ fclose( f );+ } );+}+#endif++void SourceView::SetFont()+{+ ImGui::PushFont( m_font );+ ImGui::PushStyleVar( ImGuiStyleVar_ItemSpacing, ImVec2( 0, 0 ) );+}++void SourceView::UnsetFont()+{+ ImGui::PopStyleVar();+ ImGui::PopFont();+}++}
+ cbits/tracy/profiler/src/profiler/TracySourceView.hpp view
@@ -0,0 +1,305 @@+#ifndef __TRACYSOURCEVIEW_HPP__+#define __TRACYSOURCEVIEW_HPP__++#include <limits>+#include <string>+#include <vector>++#include "tracy_robin_hood.h"+#include "TracyCharUtil.hpp"+#include "TracyDecayValue.hpp"+#include "TracySourceContents.hpp"+#include "TracySourceTokenizer.hpp"+#include "../public/common/TracyForceInline.hpp"+#include "../public/common/TracyProtocol.hpp"++struct ImFont;+struct ImVec2;++namespace tracy+{++class View;+class Worker;+struct CallstackFrameData;++class SourceView+{+public:+ enum class RegsX86 : uint8_t+ {+ invalid, flags,+ rax, rbx, rcx, rdx, rsi, rdi, rbp, rsp, r8, r9, r10, r11, r12, r13, r14, r15,+ mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7,+ xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9,+ xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, xmm16, xmm17, xmm18, xmm19,+ xmm20, xmm21, xmm22, xmm23, xmm24, xmm25, xmm26, xmm27, xmm28, xmm29,+ xmm30, xmm31, k0, k1, k2, k3, k4, k5, k6, k7,+ NUMBER_OF_ENTRIES+ };++ enum class CostType+ {+ SampleCount,+ Cycles,+ SlowBranches,+ SlowCache,+ Retirements,+ BranchesTaken,+ BranchMiss,+ CacheAccess,+ CacheMiss+ };++private:+ struct AsmOpParams+ {+ uint8_t type;+ uint16_t width;+ };++ enum class LeaData : uint8_t+ {+ none,+ b,+ bd,+ bi,+ bid,+ d,+ i,+ id,+ r,+ rd+ };++ static constexpr int ReadBit = 0x100;+ static constexpr int WriteBit = 0x200;+ static constexpr int ReuseBit = 0x400;+ static constexpr int RegMask = 0x0FF;+ static constexpr int FlagMask = 0xF00;++ enum class OpType : uint8_t+ {+ None,+ Jump,+ Branch,+ Call,+ Ret,+ Privileged+ };++ struct AsmLine+ {+ uint64_t addr;+ uint64_t jumpAddr;+ std::string mnemonic;+ std::string operands;+ uint8_t len;+ LeaData leaData;+ OpType opType;+ bool jumpConditional;+ std::vector<AsmOpParams> params;+ std::vector<Tokenizer::AsmToken> opTokens;+ union+ {+ RegsX86 readX86[12];+ };+ union+ {+ RegsX86 writeX86[20];+ };+ uint16_t regData[20];+ };++ enum { AsmLineSize = sizeof( AsmLine ) };++ struct JumpData+ {+ uint64_t min;+ uint64_t max;+ size_t level;+ std::vector<uint64_t> source;+ };++ enum+ {+ DisplaySource,+ DisplayAsm,+ DisplayMixed+ };++ struct AddrStat+ {+ uint64_t local;+ uint64_t ext;++ AddrStat& operator+=( const AddrStat& other )+ {+ local += other.local;+ ext += other.ext;+ return *this;+ }+ };++ struct AddrStatData+ {+ AddrStat ipTotalSrc = {};+ AddrStat ipTotalAsm = {};+ AddrStat ipMaxSrc = {};+ AddrStat ipMaxAsm = {};+ AddrStat hwMaxSrc = {};+ AddrStat hwMaxAsm = {};+ unordered_flat_map<uint64_t, AddrStat> ipCountSrc, ipCountAsm;+ unordered_flat_map<uint64_t, AddrStat> hwCountSrc, hwCountAsm;+ };++ struct History+ {+ const char* fileName;+ int64_t line;+ uint64_t baseAddr;+ uint64_t symAddr;+ };++public:+ SourceView();++ void UpdateFont( ImFont* fixed, ImFont* small, ImFont* big ) { m_font = fixed; m_smallFont = small; m_bigFont = big; }+ void SetCpuId( uint32_t cpuid );++ void OpenSource( const char* fileName, int line, const View& view, const Worker& worker );+ void OpenSymbol( const char* fileName, int line, uint64_t baseAddr, uint64_t symAddr, Worker& worker, const View& view, bool updateHistory = true );+ void Render( Worker& worker, View& view );++ void CalcInlineStats( bool val ) { m_calcInlineStats = val; }+ bool IsSymbolView() const { return !m_asm.empty(); }++private:+ void ParseSource( const char* fileName, const Worker& worker, const View& view );+ bool Disassemble( uint64_t symAddr, const Worker& worker );++ void SelectViewMode();++ void RenderSimpleSourceView();+ void RenderSymbolView( Worker& worker, View& view );++ void RenderSymbolSourceView( const AddrStatData& as, Worker& worker, const View& view, bool hasInlines );+ uint64_t RenderSymbolAsmView( const AddrStatData& as, Worker& worker, View& view );++ void RenderLine( const Tokenizer::Line& line, int lineNum, const AddrStat& ipcnt, const AddrStatData& as, Worker* worker, const View* view );+ void RenderAsmLine( AsmLine& line, const AddrStat& ipcnt, const AddrStatData& as, Worker& worker, uint64_t& jumpOut, int maxAddrLen, int maxAddrLenRel, View& view );+ void RenderHwLinePart( size_t cycles, size_t retired, size_t branchRetired, size_t branchMiss, size_t cacheRef, size_t cacheMiss, size_t branchRel, size_t branchRelMax, size_t cacheRel, size_t cacheRelMax, const ImVec2& ts );++ void SelectLine( uint32_t line, const Worker* worker, bool updateAsmLine = true, uint64_t targetAddr = 0, bool changeAsmLine = true );+ void SelectAsmLines( uint32_t file, uint32_t line, const Worker& worker, bool updateAsmLine = true, uint64_t targetAddr = 0, bool changeAsmLine = true );+ void SelectAsmLinesHover( uint32_t file, uint32_t line, const Worker& worker );++ void GatherIpHwStats( AddrStatData& as, Worker& worker, const View& view, CostType cost );+ void GatherIpStats( uint64_t baseAddr, AddrStatData& as, const Worker& worker, bool limitView, const View& view );+ void GatherAdditionalIpStats( uint64_t baseAddr, AddrStatData& as, const Worker& worker, bool limitView, const View& view );+ void GatherChildStats( uint64_t baseAddr, unordered_flat_map<uint64_t, uint32_t>& vec, Worker& worker, bool limitView, const View& view );++ uint32_t CountAsmIpStats( uint64_t baseAddr, const Worker& worker, bool limitView, const View& view );+ void CountHwStats( AddrStatData& as, Worker& worker, const View& view );++ void SelectMicroArchitecture( const char* moniker );++ void ResetAsm();+ void FollowRead( size_t line, RegsX86 reg, size_t limit );+ void FollowWrite( size_t line, RegsX86 reg, size_t limit );+ void CheckRead( size_t line, RegsX86 reg, size_t limit );+ void CheckWrite( size_t line, RegsX86 reg, size_t limit );++ bool IsInContext( const Worker& worker, uint64_t addr ) const;+ const std::vector<uint64_t>* GetAddressesForLocation( uint32_t fileStringIdx, uint32_t line, const Worker& worker );++ tracy_force_inline float CalcJumpSeparation( float scale );++#ifndef TRACY_NO_FILESELECTOR+ void Save( const Worker& worker, size_t start = 0, size_t stop = std::numeric_limits<size_t>::max() );+#endif++ tracy_force_inline void SetFont();+ tracy_force_inline void UnsetFont();++ ImFont* m_font;+ ImFont* m_smallFont;+ ImFont* m_bigFont;+ uint64_t m_symAddr;+ uint64_t m_baseAddr;+ uint64_t m_targetAddr;+ int m_targetLine;+ int m_selectedLine;+ int m_asmSelected;+ DecayValue<int> m_hoveredLine;+ DecayValue<uint32_t> m_hoveredSource;+ int m_displayMode;+ uint32_t m_codeLen;+ int32_t m_disasmFail;+ DecayValue<uint64_t> m_highlightAddr;+ int m_asmCountBase;+ bool m_asmRelative;+ bool m_asmBytes;+ bool m_asmShowSourceLocation;+ bool m_calcInlineStats;+ uint8_t m_maxAsmBytes;+ uint64_t m_jumpPopupAddr;+ const CallstackFrameData* m_localCallstackPopup;+ bool m_hwSamples, m_hwSamplesRelative;+ bool m_childCalls;+ bool m_childCallList;+ bool m_propagateInlines;+ CostType m_cost;++ SourceContents m_source;+ SourceContents m_sourceTooltip;+ std::vector<AsmLine> m_asm;++ unordered_flat_map<uint64_t, uint32_t> m_locMap;+ unordered_flat_map<uint64_t, JumpData> m_jumpTable;+ unordered_flat_set<uint64_t> m_jumpOut;+ size_t m_maxJumpLevel;+ bool m_showJumps;++ unordered_flat_map<uint64_t, std::vector<uint64_t>> m_locationAddress;+ bool m_locAddrIsProp;++ unordered_flat_map<uint32_t, uint32_t> m_sourceFiles;+ unordered_flat_set<uint64_t> m_selectedAddresses;+ unordered_flat_set<uint64_t> m_selectedAddressesHover;++ uint32_t m_maxLine;+ int m_maxMnemonicLen;+ int m_maxOperandLen;++ unordered_flat_map<const char*, int, charutil::Hasher, charutil::Comparator> m_microArchOpMap;+ CpuArchitecture m_cpuArch;+ int m_selMicroArch;+ int m_idxMicroArch, m_profileMicroArch;++ unordered_flat_set<uint32_t> m_asmSampleSelect;+ unordered_flat_set<uint32_t> m_srcSampleSelect;+ int32_t m_asmGroupSelect = -1;+ int32_t m_srcGroupSelect = -1;++ float m_srcWidth;+ float m_asmWidth;+ float m_jumpOffset;++ Tokenizer m_tokenizer;++ struct+ {+ uint32_t file = 0;+ uint32_t line = 0;+ size_t sel;+ std::vector<uint64_t> target;+ } m_asmTarget;++ std::vector<History> m_history;+ size_t m_historyCursor = 0;+};++}++#endif
+ cbits/tracy/profiler/src/profiler/TracyStorage.cpp view
@@ -0,0 +1,211 @@+#ifdef __MINGW32__+# define __STDC_FORMAT_MACROS+#endif+#include <assert.h>+#include <inttypes.h>+#include <string>+#include <string.h>++#ifdef _WIN32+# include <direct.h>+# include <windows.h>+#else+# include <dirent.h>+# include <sys/types.h>+# include <unistd.h>+# include <errno.h>+#endif+#include <sys/stat.h>++#include "TracyStorage.hpp"++namespace tracy+{++static bool CreateDirStruct( const std::string& path )+{+ struct stat buf;+ if( stat( path.c_str(), &buf ) == 0 ) return true;++ if( errno != ENOENT )+ {+ return false;+ }++ size_t pos = 0;+ do+ {+ pos = path.find( '/', pos+1 );+#ifdef _WIN32+ if( pos == 2 && path[1] == ':' ) continue; // Don't create drive name.+ if( _mkdir( path.substr( 0, pos ).c_str() ) != 0 )+#else+ if( mkdir( path.substr( 0, pos ).c_str(), S_IRWXU ) != 0 )+#endif+ {+ if( errno != EEXIST )+ {+ return false;+ }+ }+ }+ while( pos != std::string::npos );++ return true;+}++static void GetConfigDirectory( char* buf, size_t& sz )+{+#ifdef _WIN32+ auto path = getenv( "APPDATA" );+ sz = strlen( path );+ memcpy( buf, path, sz );++ for( size_t i=0; i<sz; i++ )+ {+ if( buf[i] == '\\' )+ {+ buf[i] = '/';+ }+ }+#else+ auto path = getenv( "XDG_CONFIG_HOME" );+ if( path && *path )+ {+ sz = strlen( path );+ memcpy( buf, path, sz );+ }+ else+ {+ path = getenv( "HOME" );+ assert( path && *path );++ sz = strlen( path );+ memcpy( buf, path, sz );+ memcpy( buf+sz, "/.config", 8 );+ sz += 8;+ }+#endif+}++const char* GetSavePath( const char* file )+{+ assert( file && *file );++ enum { Pool = 8 };+ enum { MaxPath = 512 };+ static char bufpool[Pool][MaxPath];+ static int bufsel = 0;+ char* buf = bufpool[bufsel];+ bufsel = ( bufsel + 1 ) % Pool;++ size_t sz;+ GetConfigDirectory( buf, sz );++ memcpy( buf+sz, "/tracy/", 8 );+ sz += 7;++ auto status = CreateDirStruct( buf );+ assert( status );++ const auto fsz = strlen( file );+ assert( sz + fsz < MaxPath );+ memcpy( buf+sz, file, fsz+1 );++ return buf;+}++const char* GetSavePath( const char* program, uint64_t time, const char* file, bool create )+{+ assert( program && *program );++ enum { Pool = 8 };+ enum { MaxPath = 512 };+ static char bufpool[Pool][MaxPath];+ static int bufsel = 0;+ char* buf = bufpool[bufsel];+ bufsel = ( bufsel + 1 ) % Pool;++ size_t sz;+ GetConfigDirectory( buf, sz );++ const auto psz = strlen( program );+ assert( psz < 512 );+ char tmp[512];+ strcpy( tmp, program );+ for( size_t i=0; i<psz; i++ )+ {+ switch( tmp[i] )+ {+ case 1:+ case 2:+ case 3:+ case 4:+ case 5:+ case 6:+ case 7:+ case 8:+ case 9:+ case 10:+ case 11:+ case 12:+ case 13:+ case 14:+ case 15:+ case 16:+ case 17:+ case 18:+ case 19:+ case 20:+ case 21:+ case 22:+ case 23:+ case 24:+ case 25:+ case 26:+ case 27:+ case 28:+ case 29:+ case 30:+ case 31:+ case 0x7F:+ case '<':+ case '>':+ case ':':+ case '"':+ case '/':+ case '\\':+ case '|':+ case '?':+ case '*':+ tmp[i] = '_';+ break;+ default:+ break;+ }+ }++ // 604800 = 7 days+ sz += sprintf( buf+sz, "/tracy/user/%c/%s/%" PRIu64 "/%" PRIu64 "/", tmp[0], tmp, uint64_t( time / 604800 ), time );++ if( create )+ {+ auto status = CreateDirStruct( buf );+ assert( status );+ }++ if( file )+ {+ const auto fsz = strlen( file );+ assert( sz + fsz < MaxPath );+ memcpy( buf+sz, file, fsz+1 );+ }+ else+ {+ buf[sz] = '\0';+ }++ return buf;+}++}
+ cbits/tracy/profiler/src/profiler/TracyStorage.hpp view
@@ -0,0 +1,14 @@+#ifndef __TRACYSTORAGE_HPP__+#define __TRACYSTORAGE_HPP__++#include <stdint.h>++namespace tracy+{++const char* GetSavePath( const char* file );+const char* GetSavePath( const char* program, uint64_t time, const char* file, bool create );++}++#endif
+ cbits/tracy/profiler/src/profiler/TracyTexture.cpp view
@@ -0,0 +1,187 @@+#include <inttypes.h>+#include <string.h>++#ifdef __EMSCRIPTEN__+# include <emscripten/html5.h>+# include <GLES2/gl2.h>+#else+# include <backends/imgui_impl_opengl3_loader.h>+#endif+#include "TracyTexture.hpp"+#include "../public/common/TracyForceInline.hpp"++#ifndef COMPRESSED_RGB_S3TC_DXT1_EXT+# define COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0+#endif++namespace tracy+{++static bool s_hardwareS3tc;++void InitTexture()+{+#ifdef __EMSCRIPTEN__+ s_hardwareS3tc = emscripten_webgl_enable_extension( emscripten_webgl_get_current_context(), "WEBGL_compressed_texture_s3tc" );+#else+ s_hardwareS3tc = false;+ GLint num;+ glGetIntegerv( GL_NUM_EXTENSIONS, &num );+ for( GLint i=0; i<num; i++ )+ {+ auto ext = (const char*)glGetStringi( GL_EXTENSIONS, GLuint( i ) );+ if( strcmp( ext, "GL_EXT_texture_compression_s3tc" ) == 0 )+ {+ s_hardwareS3tc = true;+ break;+ }+ }+#endif+}++ImTextureID MakeTexture( bool zigzag )+{+ GLuint tex;+ glGenTextures( 1, &tex );+ glBindTexture( GL_TEXTURE_2D, tex );+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, zigzag ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR );+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, zigzag ? GL_REPEAT : GL_CLAMP_TO_EDGE );+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );+ return tex;+}++void FreeTexture( ImTextureID _tex, void(*runOnMainThread)(const std::function<void()>&, bool) )+{+ auto tex = (GLuint)_tex;+ runOnMainThread( [tex] { glDeleteTextures( 1, &tex ); }, false );+}++static tracy_force_inline void DecodeDxt1Part( uint64_t d, uint32_t* dst, uint32_t w )+{+ uint8_t* in = (uint8_t*)&d;+ uint16_t c0, c1;+ uint32_t idx;+ memcpy( &c0, in, 2 );+ memcpy( &c1, in+2, 2 );+ memcpy( &idx, in+4, 4 );++ uint8_t r0 = ( ( c0 & 0xF800 ) >> 8 ) | ( ( c0 & 0xF800 ) >> 13 );+ uint8_t g0 = ( ( c0 & 0x07E0 ) >> 3 ) | ( ( c0 & 0x07E0 ) >> 9 );+ uint8_t b0 = ( ( c0 & 0x001F ) << 3 ) | ( ( c0 & 0x001F ) >> 2 );++ uint8_t r1 = ( ( c1 & 0xF800 ) >> 8 ) | ( ( c1 & 0xF800 ) >> 13 );+ uint8_t g1 = ( ( c1 & 0x07E0 ) >> 3 ) | ( ( c1 & 0x07E0 ) >> 9 );+ uint8_t b1 = ( ( c1 & 0x001F ) << 3 ) | ( ( c1 & 0x001F ) >> 2 );++ uint32_t dict[4];++ dict[0] = 0xFF000000 | ( b0 << 16 ) | ( g0 << 8 ) | r0;+ dict[1] = 0xFF000000 | ( b1 << 16 ) | ( g1 << 8 ) | r1;++ uint32_t r, g, b;+ if( c0 > c1 )+ {+ r = (2*r0+r1)/3;+ g = (2*g0+g1)/3;+ b = (2*b0+b1)/3;+ dict[2] = 0xFF000000 | ( b << 16 ) | ( g << 8 ) | r;+ r = (2*r1+r0)/3;+ g = (2*g1+g0)/3;+ b = (2*b1+b0)/3;+ dict[3] = 0xFF000000 | ( b << 16 ) | ( g << 8 ) | r;+ }+ else+ {+ r = (int(r0)+r1)/2;+ g = (int(g0)+g1)/2;+ b = (int(b0)+b1)/2;+ dict[2] = 0xFF000000 | ( b << 16 ) | ( g << 8 ) | r;+ dict[3] = 0xFF000000;+ }++ memcpy( dst+0, dict + (idx & 0x3), 4 );+ idx >>= 2;+ memcpy( dst+1, dict + (idx & 0x3), 4 );+ idx >>= 2;+ memcpy( dst+2, dict + (idx & 0x3), 4 );+ idx >>= 2;+ memcpy( dst+3, dict + (idx & 0x3), 4 );+ idx >>= 2;+ dst += w;++ memcpy( dst+0, dict + (idx & 0x3), 4 );+ idx >>= 2;+ memcpy( dst+1, dict + (idx & 0x3), 4 );+ idx >>= 2;+ memcpy( dst+2, dict + (idx & 0x3), 4 );+ idx >>= 2;+ memcpy( dst+3, dict + (idx & 0x3), 4 );+ idx >>= 2;+ dst += w;++ memcpy( dst+0, dict + (idx & 0x3), 4 );+ idx >>= 2;+ memcpy( dst+1, dict + (idx & 0x3), 4 );+ idx >>= 2;+ memcpy( dst+2, dict + (idx & 0x3), 4 );+ idx >>= 2;+ memcpy( dst+3, dict + (idx & 0x3), 4 );+ idx >>= 2;+ dst += w;++ memcpy( dst+0, dict + (idx & 0x3), 4 );+ idx >>= 2;+ memcpy( dst+1, dict + (idx & 0x3), 4 );+ idx >>= 2;+ memcpy( dst+2, dict + (idx & 0x3), 4 );+ idx >>= 2;+ memcpy( dst+3, dict + (idx & 0x3), 4 );+}++void UpdateTexture( ImTextureID _tex, const char* data, int w, int h )+{+ auto tex = (GLuint)_tex;+ glBindTexture( GL_TEXTURE_2D, tex );+ if( s_hardwareS3tc )+ {+ glCompressedTexImage2D( GL_TEXTURE_2D, 0, COMPRESSED_RGB_S3TC_DXT1_EXT, w, h, 0, w * h / 2, data );+ }+ else+ {+ auto tmp = new uint32_t[w*h];+ auto src = (const uint64_t*)data;+ auto dst = tmp;+ for( int y=0; y<h/4; y++ )+ {+ for( int x=0; x<w/4; x++ )+ {+ uint64_t d = *src++;+ DecodeDxt1Part( d, dst, w );+ dst += 4;+ }+ dst += w*3;+ }+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, tmp );+ delete[] tmp;+ }+}++void UpdateTextureRGBA( ImTextureID _tex, void* data, int w, int h )+{+ auto tex = (GLuint)_tex;+ glBindTexture( GL_TEXTURE_2D, tex );+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );+}++void UpdateTextureRGBAMips( ImTextureID _tex, void** data, int* w, int* h, size_t mips )+{+ auto tex = (GLuint)_tex;+ glBindTexture( GL_TEXTURE_2D, tex );+ for( size_t i=0; i<mips; i++ )+ {+ glTexImage2D( GL_TEXTURE_2D, i, GL_RGBA, w[i], h[i], 0, GL_RGBA, GL_UNSIGNED_BYTE, data[i] );+ }+}++}
+ cbits/tracy/profiler/src/profiler/TracyTexture.hpp view
@@ -0,0 +1,19 @@+#ifndef __TRACYTEXTURE_HPP__+#define __TRACYTEXTURE_HPP__++#include <functional>+#include <imgui.h>++namespace tracy+{++void InitTexture();+ImTextureID MakeTexture( bool zigzag = false );+void FreeTexture( ImTextureID tex, void(*runOnMainThread)(const std::function<void()>&, bool) );+void UpdateTexture( ImTextureID tex, const char* data, int w, int h );+void UpdateTextureRGBA( ImTextureID tex, void* data, int w, int h );+void UpdateTextureRGBAMips( ImTextureID tex, void** data, int* w, int* h, size_t mips );++}++#endif
+ cbits/tracy/profiler/src/profiler/TracyTimelineContext.hpp view
@@ -0,0 +1,23 @@+#ifndef __TRACYTIMELINECONTEXT_HPP__+#define __TRACYTIMELINECONTEXT_HPP__++#include <stdint.h>++#include "imgui.h"++namespace tracy+{++struct TimelineContext+{+ float w, ty, sty, scale;+ float yMin, yMax;+ double pxns, nspx;+ int64_t vStart, vEnd;+ ImVec2 wpos;+ bool hover;+};++}++#endif
+ cbits/tracy/profiler/src/profiler/TracyTimelineController.cpp view
@@ -0,0 +1,177 @@+#include <algorithm>+#include <thread>++#include "TracyTimelineItem.hpp"+#include "TracyTimelineContext.hpp"+#include "TracyTimelineController.hpp"+#include "TracyView.hpp"++namespace tracy+{++TimelineController::TimelineController( View& view, Worker& worker, bool threading )+ : m_height( 0 )+ , m_scroll( 0 )+ , m_centerItemkey( nullptr )+ , m_centerItemOffsetY( 0 )+ , m_firstFrame( true )+ , m_view( view )+ , m_worker( worker )+#ifdef __EMSCRIPTEN__+ , m_td( threading ? 2 : 0, "Render" )+#else+ , m_td( threading ? (size_t)std::max( 0, ( (int)std::thread::hardware_concurrency() - 2 ) / 2 ) : 0, "Render" )+#endif+{+}++TimelineController::~TimelineController()+{+}++void TimelineController::FirstFrameExpired()+{+ m_firstFrame = false;+}++void TimelineController::Begin()+{+ m_items.clear();+}++void TimelineController::UpdateCenterItem()+{+ ImVec2 mousePos = ImGui::GetMousePos();++ m_centerItemkey = nullptr;+ m_centerItemOffsetY = 0;++ if( m_firstFrame || !ImGui::IsMousePosValid( &mousePos ) ) return;++ const auto timelineMousePosY = mousePos.y - ImGui::GetWindowPos().y;+ int centerY = timelineMousePosY + ImGui::GetScrollY();++ int yBegin = 0;+ int yEnd = 0;+ for( auto& item : m_items )+ {+ m_centerItemkey = item->GetKey();+ yBegin = yEnd;+ yEnd += item->GetHeight();++ const auto inLowerBounds = m_centerItemkey == m_items.front()->GetKey() || yBegin <= centerY;+ const auto inUpperBounds = m_centerItemkey == m_items.back()->GetKey() || centerY < yEnd;++ if( inLowerBounds && inUpperBounds )+ {+ m_centerItemOffsetY = centerY - yBegin;+ break;+ }+ }+}++std::optional<int> TimelineController::CalculateScrollPosition() const+{+ if( !m_centerItemkey ) return std::nullopt;++ ImVec2 mousePos = ImGui::GetMousePos();++ if( !ImGui::IsMousePosValid( &mousePos ) ) return std::nullopt;++ const auto timelineMousePosY = mousePos.y - ImGui::GetWindowPos().y;++ int yBegin = 0;+ int yEnd = 0;+ for( auto& item : m_items )+ {+ yBegin = yEnd;+ yEnd += item->GetHeight();++ if( item->GetKey() != m_centerItemkey ) continue;++ int scrollY = yBegin + m_centerItemOffsetY - timelineMousePosY;++ return scrollY;+ }++ return std::nullopt;+}++void TimelineController::End( double pxns, const ImVec2& wpos, bool hover, bool vcenter, float yMin, float yMax, ImFont* smallFont )+{+ auto shouldUpdateCenterItem = [&] () {+ const auto imguiChangedScroll = m_scroll != ImGui::GetScrollY();+ const auto& mouseDelta = ImGui::GetIO().MouseDelta;+ const auto mouseMoved = mouseDelta.x != 0.0f || mouseDelta.y != 0.0f;+ const auto& mousePos = ImGui::GetIO().MousePos;+ const auto mouseVisible = ImGui::IsMousePosValid( &mousePos );+ return ( ( imguiChangedScroll || mouseMoved || !mouseVisible ) && !ImGui::IsMouseDown( 1 ) ) || !m_centerItemkey;+ };++ if( !vcenter )+ {+ m_centerItemkey = nullptr;+ m_centerItemOffsetY = 0;+ }+ else if( shouldUpdateCenterItem() )+ {+ UpdateCenterItem();+ }++ const auto& viewData = m_view.GetViewData();++ TimelineContext ctx;+ ctx.w = ImGui::GetContentRegionAvail().x - 1;+ ctx.ty = ImGui::GetTextLineHeight();+ ImGui::PushFont( smallFont );+ ctx.sty = ImGui::GetTextLineHeight();+ ImGui::PopFont();+ ctx.scale = GetScale();+ ctx.yMin = yMin;+ ctx.yMax = yMax;+ ctx.pxns = pxns;+ ctx.nspx = 1.0 / pxns;+ ctx.vStart = viewData.zvStart;+ ctx.vEnd = viewData.zvEnd;+ ctx.wpos = wpos;+ ctx.hover = hover;++ int yOffset = 0;+ for( auto& item : m_items )+ {+ if( item->WantPreprocess() && item->IsVisible() )+ {+ const auto yPos = wpos.y + yOffset;+ const bool visible = m_firstFrame || ( yPos < yMax && yPos + item->GetHeight() >= yMin );+ item->Preprocess( ctx, m_td, visible, yPos );+ }+ yOffset += m_firstFrame ? 0 : item->GetHeight();+ }+ m_td.Sync();++ yOffset = 0;+ for( auto& item : m_items )+ {+ auto currentFrameItemHeight = item->GetHeight();+ item->Draw( m_firstFrame, ctx, yOffset );+ if( m_firstFrame ) currentFrameItemHeight = item->GetHeight();+ yOffset += currentFrameItemHeight;+ }++ if( const auto scrollY = CalculateScrollPosition() )+ {+ int clampedScrollY = std::min<int>( *scrollY, std::max<int>( yOffset - ImGui::GetWindowHeight(), 0 ) );+ ImGui::SetScrollY( clampedScrollY );+ int minHeight = ImGui::GetWindowHeight() + clampedScrollY;+ yOffset = std::max( yOffset, minHeight );+ }++ const auto scrollPos = ImGui::GetScrollY();+ if( ( scrollPos == 0 && m_scroll != 0 ) || yOffset > m_height )+ {+ m_height = yOffset;+ }+ m_scroll = scrollPos;+}++}
+ cbits/tracy/profiler/src/profiler/TracyTimelineController.hpp view
@@ -0,0 +1,71 @@+#ifndef __TRACYTIMELINECONTROLLER_HPP__+#define __TRACYTIMELINECONTROLLER_HPP__++#include <assert.h>+#include <optional>+#include <vector>++#include "TracyImGui.hpp"+#include "../server/TracyTaskDispatch.hpp"+#include "../server/tracy_robin_hood.h"+#include "../public/common/TracyForceInline.hpp"++namespace tracy+{++class TimelineItem;+class View;+class Worker;++class TimelineController+{+public:+ TimelineController( View& view, Worker& worker, bool threading );+ ~TimelineController();++ void FirstFrameExpired();+ void Begin();+ void End( double pxns, const ImVec2& wpos, bool hover, bool vcenter, float yMin, float yMax, ImFont* smallFont );++ template<class T, class U>+ void AddItem( U* data )+ {+ auto it = m_itemMap.find( data );+ if( it == m_itemMap.end() ) it = m_itemMap.emplace( data, std::make_unique<T>( m_view, m_worker, data ) ).first;+ m_items.emplace_back( it->second.get() );+ }++ float GetHeight() const { return m_height; }+ const unordered_flat_map<const void*, std::unique_ptr<TimelineItem>>& GetItemMap() const { return m_itemMap; }++ tracy_force_inline TimelineItem& GetItem( const void* data )+ {+ auto it = m_itemMap.find( data );+ assert( it != m_itemMap.end() );+ return *it->second;+ }++private:+ void UpdateCenterItem();+ std::optional<int> CalculateScrollPosition() const;++ std::vector<TimelineItem*> m_items;+ unordered_flat_map<const void*, std::unique_ptr<TimelineItem>> m_itemMap;++ float m_height;+ float m_scroll;++ const void* m_centerItemkey;+ int m_centerItemOffsetY;++ bool m_firstFrame;++ View& m_view;+ Worker& m_worker;++ TaskDispatch m_td;+};++}++#endif
+ cbits/tracy/profiler/src/profiler/TracyTimelineDraw.hpp view
@@ -0,0 +1,105 @@+#ifndef __TRACYTIMELINEDRAW_HPP__+#define __TRACYTIMELINEDRAW_HPP__++#include <stdint.h>++#include "TracyEvent.hpp"+#include "TracyShortPtr.hpp"++namespace tracy+{++enum class TimelineDrawType : uint8_t+{+ Folded,+ Zone,+ GhostFolded,+ Ghost+};++struct TimelineDraw+{+ TimelineDrawType type;+ uint16_t depth;+ short_ptr<void*> ev;+ Int48 rend;+ uint32_t num;+ uint32_t inheritedColor;+};+++enum class ContextSwitchDrawType : uint8_t+{+ Waiting,+ Folded,+ Running+};++struct ContextSwitchDraw+{+ ContextSwitchDrawType type;+ uint32_t idx;+ uint32_t data; // Folded: number of items -OR- Waiting: wait stack+};+++struct SamplesDraw+{+ uint32_t num;+ uint32_t idx;+};+++struct MessagesDraw+{+ short_ptr<MessageData> msg;+ bool highlight;+ uint32_t num;+};+++struct CpuUsageDraw+{+ int own;+ int other;+};+++struct CpuCtxDraw+{+ uint32_t idx;+ uint32_t num;+};++++struct LockState+{+ enum Type : uint8_t+ {+ Nothing = 1 << 0,+ HasLock = 1 << 1, // green+ HasBlockingLock = 1 << 2, // yellow+ WaitLock = 1 << 3 // red+ };+};++struct LockDrawItem+{+ Int48 t1;+ LockState::Type state;+ uint32_t condensed;+ short_ptr<LockEventPtr> ptr, next;+};++struct LockDraw+{+ uint32_t id;+ bool forceDraw;+ uint8_t thread;+ std::vector<LockDrawItem> data;+};++}++#endif
+ cbits/tracy/profiler/src/profiler/TracyTimelineItem.cpp view
@@ -0,0 +1,168 @@+#include <algorithm>++#include "TracyImGui.hpp"+#include "TracyMouse.hpp"+#include "TracyTimelineContext.hpp"+#include "TracyTimelineItem.hpp"+#include "TracyView.hpp"++namespace tracy+{++TimelineItem::TimelineItem( View& view, Worker& worker, const void* key, bool wantPreprocess )+ : m_visible( true )+ , m_showFull( true )+ , m_height( 0 )+ , m_wantPreprocess( wantPreprocess )+ , m_key( key )+ , m_view( view )+ , m_worker( worker )+{+}++void TimelineItem::Draw( bool firstFrame, const TimelineContext& ctx, int yOffset )+{+ const auto yBegin = yOffset;+ auto yEnd = yOffset;++ if( !IsVisible() )+ {+ DrawFinished();+ if( m_height != 0 ) AdjustThreadHeight( firstFrame, yBegin, yEnd );+ return;+ }+ if( IsEmpty() )+ {+ DrawFinished();+ return;+ }++ const auto w = ctx.w;+ const auto ty = ctx.ty;+ const auto ostep = ty + 1;+ const auto& wpos = ctx.wpos;+ const auto yPos = wpos.y + yBegin;+ const auto dpos = wpos + ImVec2( 0.5f, 0.5f );+ auto draw = ImGui::GetWindowDrawList();++ ImGui::PushID( this );+ ImGui::PushClipRect( wpos + ImVec2( 0, yBegin ), wpos + ImVec2( w, yBegin + m_height ), true );++ yEnd += ostep;+ if( m_showFull )+ {+ if( !DrawContents( ctx, yEnd ) && !m_view.GetViewData().drawEmptyLabels )+ {+ DrawFinished();+ yEnd = yBegin;+ AdjustThreadHeight( firstFrame, yBegin, yEnd );+ ImGui::PopClipRect();+ ImGui::PopID();+ return;+ }+ }++ DrawOverlay( wpos + ImVec2( 0, yBegin ), wpos + ImVec2( w, yEnd ) );+ ImGui::PopClipRect();++ float labelWidth;+ const auto hdrOffset = yBegin;+ const bool drawHeader = yPos + ty >= ctx.yMin && yPos <= ctx.yMax;+ if( drawHeader )+ {+ const auto color = HeaderColor();+ const auto colorInactive = HeaderColorInactive();++ if( m_showFull )+ {+ DrawTextContrast( draw, wpos + ImVec2( 0, hdrOffset ), color, ICON_FA_CARET_DOWN );+ }+ else+ {+ DrawTextContrast( draw, wpos + ImVec2( 0, hdrOffset ), colorInactive, ICON_FA_CARET_RIGHT );+ }+ const auto label = HeaderLabel();+ labelWidth = ImGui::CalcTextSize( label ).x;+ DrawTextContrast( draw, wpos + ImVec2( ty, hdrOffset ), m_showFull ? color : colorInactive, label );+ if( m_showFull )+ {+ DrawLine( draw, dpos + ImVec2( 0, hdrOffset + ty - 1 ), dpos + ImVec2( w, hdrOffset + ty - 1 ), HeaderLineColor() );+ HeaderExtraContents( ctx, hdrOffset, labelWidth );+ }++ if( ctx.hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( 0, hdrOffset ), wpos + ImVec2( ty + labelWidth, hdrOffset + ty ) ) )+ {+ HeaderTooltip( label );++ if( IsMouseClicked( 0 ) )+ {+ m_showFull = !m_showFull;+ }+ if( IsMouseClicked( 2 ) )+ {+ const auto t0 = RangeBegin();+ const auto t1 = RangeEnd();+ if( t0 < t1 )+ {+ m_view.ZoomToRange( t0, t1 );+ }+ }+ if( IsMouseClicked( 1 ) )+ {+ ImGui::OpenPopup( "menuPopup" );+ }+ }+ }++ if( ImGui::BeginPopup( "menuPopup" ) )+ {+ if( ImGui::MenuItem( ICON_FA_EYE_SLASH " Hide" ) )+ {+ SetVisible( false );+ ImGui::CloseCurrentPopup();+ }+ DrawExtraPopupItems();+ ImGui::EndPopup();+ }++ yEnd += 0.2f * ostep;+ AdjustThreadHeight( firstFrame, yBegin, yEnd );+ DrawFinished();++ ImGui::PopID();+}++void TimelineItem::AdjustThreadHeight( bool firstFrame, int yBegin, int yEnd )+{+ const auto speed = 4.0;+ const auto baseMove = 1.0;++ const auto newHeight = yEnd - yBegin;+ if( firstFrame )+ {+ m_height = newHeight;+ }+ else if( m_height != newHeight )+ {+ const auto diff = newHeight - m_height;+ const auto preClampMove = diff * speed * ImGui::GetIO().DeltaTime;+ if( diff > 0 )+ {+ const auto move = preClampMove + baseMove;+ m_height = int( std::min<double>( m_height + move, newHeight ) );+ }+ else+ {+ const auto move = preClampMove - baseMove;+ m_height = int( std::max<double>( m_height + move, newHeight ) );+ }+ s_wasActive = true;+ }+}++void TimelineItem::VisibilityCheckbox()+{+ SmallCheckbox( HeaderLabel(), &m_visible );+}++}
+ cbits/tracy/profiler/src/profiler/TracyTimelineItem.hpp view
@@ -0,0 +1,77 @@+#ifndef __TRACYTIMELINEITEM_HPP__+#define __TRACYTIMELINEITEM_HPP__++#include <assert.h>+#include <stdint.h>++#include "imgui.h"++namespace tracy+{++struct TimelineContext;+class TaskDispatch;+class View;+class Worker;++class TimelineItem+{+public:+ TimelineItem( View& view, Worker& worker, const void* key, bool wantPreprocess );+ virtual ~TimelineItem() = default;++ // draws the timeline item and also updates the next frame height value+ void Draw( bool firstFrame, const TimelineContext& ctx, int yOffset );++ bool WantPreprocess() const { return m_wantPreprocess; }+ virtual void Preprocess( const TimelineContext& ctx, TaskDispatch& td, bool visible, int yPos ) { assert( false ); }++ void VisibilityCheckbox();+ virtual void SetVisible( bool visible ) { m_visible = visible; }+ virtual bool IsVisible() const { return m_visible; }++ void SetShowFull( bool showFull ) { m_showFull = showFull; }++ // returns 0 instead of the correct value for the first frame+ int GetHeight() const { return m_height; }++ const void* GetKey() const { return m_key; }++protected:+ virtual uint32_t HeaderColor() const = 0;+ virtual uint32_t HeaderColorInactive() const = 0;+ virtual uint32_t HeaderLineColor() const = 0;+ virtual const char* HeaderLabel() const = 0;++ virtual void HeaderTooltip( const char* label ) const {};+ virtual void HeaderExtraContents( const TimelineContext& ctx, int offset, float labelWidth ) {};++ virtual int64_t RangeBegin() const = 0;+ virtual int64_t RangeEnd() const = 0;++ virtual bool DrawContents( const TimelineContext& ctx, int& offset ) = 0;+ virtual void DrawOverlay( const ImVec2& ul, const ImVec2& dr ) {}+ virtual void DrawExtraPopupItems() {}+ virtual void DrawFinished() {}++ virtual bool IsEmpty() const { return false; }++ bool m_visible;+ bool m_showFull;++private:+ void AdjustThreadHeight( bool firstFrame, int yBegin, int yEnd );++ int m_height;+ bool m_wantPreprocess;++ const void* m_key;++protected:+ View& m_view;+ Worker& m_worker;+};++}++#endif
+ cbits/tracy/profiler/src/profiler/TracyTimelineItemCpuData.cpp view
@@ -0,0 +1,259 @@+#include "TracyImGui.hpp"+#include "TracyPrint.hpp"+#include "TracyTimelineContext.hpp"+#include "TracyTimelineItemCpuData.hpp"+#include "TracyUtility.hpp"+#include "TracyView.hpp"+#include "TracyWorker.hpp"++namespace tracy+{++TimelineItemCpuData::TimelineItemCpuData( View& view, Worker& worker, void* key )+ : TimelineItem( view, worker, key, true )+{+}++void TimelineItemCpuData::SetVisible( bool visible )+{+ m_view.GetViewData().drawCpuData = visible;+}++bool TimelineItemCpuData::IsVisible() const+{+ return m_view.GetViewData().drawCpuData;+}++bool TimelineItemCpuData::IsEmpty() const+{+ return m_worker.GetCpuDataCpuCount() == 0;+}++int64_t TimelineItemCpuData::RangeBegin() const+{+ return -1;+}++int64_t TimelineItemCpuData::RangeEnd() const+{+ return -1;+}++bool TimelineItemCpuData::DrawContents( const TimelineContext& ctx, int& offset )+{+ m_view.DrawCpuData( ctx, m_cpuDraw, m_ctxDraw, offset, m_hasCpuData );+ return true;+}++void TimelineItemCpuData::DrawFinished()+{+ m_cpuDraw.clear();+ for( auto& v : m_ctxDraw ) v.clear();+}++void TimelineItemCpuData::Preprocess( const TimelineContext& ctx, TaskDispatch& td, bool visible, int yPos )+{+ assert( m_cpuDraw.empty() );+ for( auto& v : m_ctxDraw ) assert( v.empty() );++ if( !visible ) return;++ const auto yMin = ctx.yMin;+ const auto yMax = ctx.yMax;+ const auto ty = ctx.ty;+ const auto sty = ctx.sty;+ const auto ostep = ty + 1;+ const auto sstep = sty + 1;++ bool hasCpuData = false;+ auto pos = yPos + ostep;++#ifdef TRACY_NO_STATISTICS+ if( m_view.GetViewData().drawCpuUsageGraph )+#else+ if( m_view.GetViewData().drawCpuUsageGraph && m_worker.IsCpuUsageReady() )+#endif+ {+#ifndef TRACY_NO_STATISTICS+ auto& ctxUsage = m_worker.GetCpuUsage();+ if( !ctxUsage.empty() )+ {+ hasCpuData = true;+ }+ else+#endif+ {+ const auto cpuDataCount = m_worker.GetCpuDataCpuCount();+ const auto cpuData = m_worker.GetCpuData();+ for( int i=0; i<cpuDataCount; i++ )+ {+ if( !cpuData[i].cs.empty() )+ {+ hasCpuData = true;+ break;+ }+ }+ }+ if( hasCpuData )+ {+ const auto cpuUsageHeight = floor( 30.f * GetScale() );+ if( pos <= yMax && pos + cpuUsageHeight + 3 >= yMin )+ {+ td.Queue( [this, &ctx] {+ PreprocessCpuUsage( ctx );+ } );+ }+ pos += cpuUsageHeight + 3;+ }+ }+ m_hasCpuData = hasCpuData;++ auto cpuData = m_worker.GetCpuData();+ const auto cpuCnt = m_worker.GetCpuDataCpuCount();+ if( m_ctxDraw.size() != cpuCnt ) m_ctxDraw.resize( cpuCnt );++ for( int i=0; i<cpuCnt; i++ )+ {+ auto& cs = cpuData[i].cs;+ if( !cs.empty() && pos <= yMax && pos + sty >= yMin )+ {+ td.Queue( [this, &ctx, &cs, i] {+ PreprocessCpuCtxSwitches( ctx, cs, m_ctxDraw[i] );+ } );+ }+ pos += sstep;+ }+}++constexpr float MinVisSize = 3;++void TimelineItemCpuData::PreprocessCpuCtxSwitches( const TimelineContext& ctx, const Vector<ContextSwitchCpu>& cs, std::vector<CpuCtxDraw>& out )+{+ const auto vStart = ctx.vStart;+ const auto vEnd = ctx.vEnd;+ const auto nspx = ctx.nspx;++ auto it = std::lower_bound( cs.begin(), cs.end(), std::max<int64_t>( 0, vStart ), [] ( const auto& l, const auto& r ) { return ( l.IsEndValid() ? l.End() : l.Start() ) < r; } );+ if( it == cs.end() ) return;+ auto eit = std::lower_bound( it, cs.end(), vEnd, [] ( const auto& l, const auto& r ) { return l.Start() < r; } );+ if( it == eit ) return;++ const auto MinVisNs = int64_t( round( GetScale() * MinVisSize * nspx ) );++ while( it < eit )+ {+ const auto end = it->IsEndValid() ? it->End() : it->Start();+ const auto zsz = end - it->Start();+ if( zsz < MinVisNs )+ {+ auto nextTime = end + MinVisNs;+ auto next = it + 1;+ for(;;)+ {+ next = std::lower_bound( next, eit, nextTime, [] ( const auto& l, const auto& r ) { return ( l.IsEndValid() ? l.End() : l.Start() ) < r; } );+ if( next == eit ) break;+ auto prev = next - 1;+ const auto pt = prev->IsEndValid() ? prev->End() : prev->Start();+ const auto nt = next->IsEndValid() ? next->End() : next->Start();+ if( nt - pt >= MinVisNs ) break;+ nextTime = nt + MinVisNs;+ }+ out.emplace_back( CpuCtxDraw { uint32_t( it - cs.begin() ), uint32_t( next - it ) } );+ it = next;+ }+ else+ {+ out.emplace_back( CpuCtxDraw { uint32_t( it - cs.begin() ), 0 } );+ ++it;+ }+ }+}++void TimelineItemCpuData::PreprocessCpuUsage( const TimelineContext& ctx )+{+ const auto vStart = ctx.vStart;+ const auto nspx = ctx.nspx;+ const auto w = ctx.w;+ const auto num = size_t( w );++ if( vStart > m_worker.GetLastTime() || int64_t( vStart + nspx * num ) < 0 ) return;++ const auto lastTime = m_worker.GetLastTime();++#ifndef TRACY_NO_STATISTICS+ auto& ctxUsage = m_worker.GetCpuUsage();+ if( !ctxUsage.empty() )+ {+ auto itBegin = ctxUsage.begin();+ for( size_t i=0; i<num; i++ )+ {+ const auto time = int64_t( vStart + nspx * i );+ if( time > lastTime ) return;+ if( time < 0 )+ {+ m_cpuDraw.emplace_back( CpuUsageDraw { 0, 0 } );+ }+ else+ {+ const auto test = ( time << 16 ) | 0xFFFF;+ auto it = std::upper_bound( itBegin, ctxUsage.end(), test, [] ( const auto& l, const auto& r ) { return l < r._time_other_own; } );+ if( it == ctxUsage.end() ) return;+ if( it == ctxUsage.begin() )+ {+ m_cpuDraw.emplace_back( CpuUsageDraw { 0, 0 } );+ }+ else+ {+ --it;+ m_cpuDraw.emplace_back( CpuUsageDraw { it->Own(), it->Other() } );+ }+ itBegin = it;+ }+ }+ }+ else+#endif+ {+ m_cpuDraw.resize( num );+ memset( m_cpuDraw.data(), 0, sizeof( CpuUsageDraw ) * num );++ const auto pid = m_worker.GetPid();+ const auto cpuDataCount = m_worker.GetCpuDataCpuCount();+ const auto cpuData = m_worker.GetCpuData();++ for( int i=0; i<cpuDataCount; i++ )+ {+ auto& cs = cpuData[i].cs;+ if( !cs.empty() )+ {+ auto itBegin = cs.begin();+ auto ptr = m_cpuDraw.data();+ for( size_t i=0; i<num; i++ )+ {+ const auto time = int64_t( vStart + nspx * i );+ if( time > lastTime ) break;+ if( time >= 0 )+ {+ auto it = std::lower_bound( itBegin, cs.end(), time, [] ( const auto& l, const auto& r ) { return (uint64_t)l.End() < (uint64_t)r; } );+ if( it == cs.end() ) break;+ if( it->IsEndValid() && it->Start() <= time )+ {+ if( m_worker.GetPidFromTid( m_worker.DecompressThreadExternal( it->Thread() ) ) == pid )+ {+ ptr->own++;+ }+ else+ {+ ptr->other++;+ }+ }+ itBegin = it;+ }+ ptr++;+ }+ }+ }+ }+}++}
+ cbits/tracy/profiler/src/profiler/TracyTimelineItemCpuData.hpp view
@@ -0,0 +1,47 @@+#ifndef __TRACYTIMELINEITEMCPUDATA_HPP__+#define __TRACYTIMELINEITEMCPUDATA_HPP__++#include "TracyEvent.hpp"+#include "TracyTimelineItem.hpp"+#include "TracyTimelineDraw.hpp"++namespace tracy+{++class TimelineItemCpuData final : public TimelineItem+{+public:+ TimelineItemCpuData( View& view, Worker& worker, void* key );++ void SetVisible( bool visible ) override;+ bool IsVisible() const override;++protected:+ uint32_t HeaderColor() const override { return 0xFFDD88DD; }+ uint32_t HeaderColorInactive() const override { return 0xFF6E446E; }+ uint32_t HeaderLineColor() const override { return 0x66DD88DD; }+ const char* HeaderLabel() const override { return "CPU data"; }++ int64_t RangeBegin() const override;+ int64_t RangeEnd() const override;++ bool DrawContents( const TimelineContext& ctx, int& offset ) override;+ void DrawFinished() override;++ bool IsEmpty() const override;++ void Preprocess( const TimelineContext& ctx, TaskDispatch& td, bool visible, int yPos ) override;++private:+ void PreprocessCpuUsage( const TimelineContext& ctx );+ void PreprocessCpuCtxSwitches( const TimelineContext& ctx, const Vector<ContextSwitchCpu>& cs, std::vector<CpuCtxDraw>& out );++ std::vector<CpuUsageDraw> m_cpuDraw;+ std::vector<std::vector<CpuCtxDraw>> m_ctxDraw;++ bool m_hasCpuData;+};++}++#endif
+ cbits/tracy/profiler/src/profiler/TracyTimelineItemGpu.cpp view
@@ -0,0 +1,198 @@+#include "TracyImGui.hpp"+#include "TracyPopcnt.hpp"+#include "TracyPrint.hpp"+#include "TracyTimelineContext.hpp"+#include "TracyTimelineItemGpu.hpp"+#include "TracyUtility.hpp"+#include "TracyView.hpp"+#include "TracyWorker.hpp"++namespace tracy+{++TimelineItemGpu::TimelineItemGpu( View& view, Worker& worker, GpuCtxData* gpu )+ : TimelineItem( view, worker, gpu, false )+ , m_gpu( gpu )+ , m_idx( view.GetNextGpuIdx() )+{+}++bool TimelineItemGpu::IsEmpty() const+{+ return m_gpu->threadData.empty();+}++const char* TimelineItemGpu::HeaderLabel() const+{+ static char buf[4096];+ if( m_gpu->name.Active() )+ {+ sprintf( buf, "%s", m_worker.GetString( m_gpu->name ) );+ }+ else+ {+ sprintf( buf, "%s context %i", GpuContextNames[(int)m_gpu->type], m_idx );+ }+ return buf;+}++void TimelineItemGpu::HeaderTooltip( const char* label ) const+{+ const bool dynamicColors = m_view.GetViewData().dynamicColors;+ const bool isMultithreaded =+ ( m_gpu->type == GpuContextType::Vulkan ) ||+ ( m_gpu->type == GpuContextType::OpenCL ) ||+ ( m_gpu->type == GpuContextType::Direct3D12 ) ||+ ( m_gpu->type == GpuContextType::Metal );++ char buf[64];+ sprintf( buf, "%s context %i", GpuContextNames[(int)m_gpu->type], m_idx );++ ImGui::BeginTooltip();+ if( m_gpu->name.Active() ) TextFocused( "Name:", m_worker.GetString( m_gpu->name ) );+ ImGui::TextUnformatted( buf );+ ImGui::Separator();+ if( !isMultithreaded )+ {+ SmallColorBox( GetThreadColor( m_gpu->thread, 0, dynamicColors ) );+ ImGui::SameLine();+ TextFocused( "Thread:", m_worker.GetThreadName( m_gpu->thread ) );+ }+ else+ {+ if( m_gpu->threadData.size() == 1 )+ {+ auto it = m_gpu->threadData.begin();+ auto tid = it->first;+ if( tid == 0 )+ {+ if( !it->second.timeline.empty() )+ {+ if( it->second.timeline.is_magic() )+ {+ auto& tl = *(Vector<GpuEvent>*)&it->second.timeline;+ tid = m_worker.DecompressThread( tl.begin()->Thread() );+ }+ else+ {+ tid = m_worker.DecompressThread( (*it->second.timeline.begin())->Thread() );+ }+ }+ }+ SmallColorBox( GetThreadColor( tid, 0, dynamicColors ) );+ ImGui::SameLine();+ TextFocused( "Thread:", m_worker.GetThreadName( tid ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( tid ) );+ if( m_worker.IsThreadFiber( tid ) )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 0.2f, 0.6f, 0.2f, 1.f ), "Fiber" );+ }+ }+ else+ {+ ImGui::TextDisabled( "Threads:" );+ ImGui::Indent();+ for( auto& td : m_gpu->threadData )+ {+ SmallColorBox( GetThreadColor( td.first, 0, dynamicColors ) );+ ImGui::SameLine();+ ImGui::TextUnformatted( m_worker.GetThreadName( td.first ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( td.first ) );+ }+ ImGui::Unindent();+ }+ }+ const auto t0 = RangeBegin();+ if( t0 != std::numeric_limits<int64_t>::max() )+ {+ TextFocused( "Appeared at", TimeToString( t0 ) );+ }+ TextFocused( "Zone count:", RealToString( m_gpu->count ) );+ if( m_gpu->period != 1.f )+ {+ TextFocused( "Timestamp accuracy:", TimeToString( m_gpu->period ) );+ }+ if( m_gpu->overflow != 0 )+ {+ ImGui::Separator();+ ImGui::TextUnformatted( "GPU timer overflow has been detected." );+ TextFocused( "Timer resolution:", RealToString( 63 - TracyLzcnt( m_gpu->overflow ) ) );+ ImGui::SameLine();+ TextDisabledUnformatted( "bits" );+ }+ ImGui::EndTooltip();+}++void TimelineItemGpu::HeaderExtraContents( const TimelineContext& ctx, int offset, float labelWidth )+{+ if( m_gpu->name.Active() )+ {+ auto draw = ImGui::GetWindowDrawList();+ const auto ty = ImGui::GetTextLineHeight();++ char buf[64];+ sprintf( buf, "%s context %i", GpuContextNames[(int)m_gpu->type], m_idx );+ draw->AddText( ctx.wpos + ImVec2( ty * 1.5f + labelWidth, offset ), HeaderColorInactive(), buf );+ }+}++int64_t TimelineItemGpu::RangeBegin() const+{+ int64_t t = std::numeric_limits<int64_t>::max();+ for( auto& td : m_gpu->threadData )+ {+ int64_t t0;+ if( td.second.timeline.is_magic() )+ {+ t0 = ((Vector<GpuEvent>*)&td.second.timeline)->front().GpuStart();+ }+ else+ {+ t0 = td.second.timeline.front()->GpuStart();+ }+ if( t0 >= 0 )+ {+ t = std::min( t, t0 );+ }+ }+ return t;+}++int64_t TimelineItemGpu::RangeEnd() const+{+ int64_t t = std::numeric_limits<int64_t>::min();+ for( auto& td : m_gpu->threadData )+ {+ int64_t t0;+ if( td.second.timeline.is_magic() )+ {+ t0 = ((Vector<GpuEvent>*)&td.second.timeline)->front().GpuStart();+ }+ else+ {+ t0 = td.second.timeline.front()->GpuStart();+ }+ if( t0 >= 0 )+ {+ if( td.second.timeline.is_magic() )+ {+ t = std::max( t, std::min( m_worker.GetLastTime(), m_worker.GetZoneEnd( ((Vector<GpuEvent>*)&td.second.timeline)->back() ) ) );+ }+ else+ {+ t = std::max( t, std::min( m_worker.GetLastTime(), m_worker.GetZoneEnd( *td.second.timeline.back() ) ) );+ }+ }+ }+ return t;+}++bool TimelineItemGpu::DrawContents( const TimelineContext& ctx, int& offset )+{+ return m_view.DrawGpu( ctx, *m_gpu, offset );+}++}
+ cbits/tracy/profiler/src/profiler/TracyTimelineItemGpu.hpp view
@@ -0,0 +1,40 @@+#ifndef __TRACYTIMELINEITEMGPU_HPP__+#define __TRACYTIMELINEITEMGPU_HPP__++#include "TracyEvent.hpp"+#include "TracyTimelineItem.hpp"++namespace tracy+{++class TimelineItemGpu final : public TimelineItem+{+public:+ TimelineItemGpu( View& view, Worker& worker, GpuCtxData* gpu );++ int GetIdx() const { return m_idx; }++protected:+ uint32_t HeaderColor() const override { return 0xFFFFAAAA; }+ uint32_t HeaderColorInactive() const override { return 0xFF886666; }+ uint32_t HeaderLineColor() const override { return 0x33FFFFFF; }+ const char* HeaderLabel() const override;++ int64_t RangeBegin() const override;+ int64_t RangeEnd() const override;++ void HeaderTooltip( const char* label ) const override;+ void HeaderExtraContents( const TimelineContext& ctx, int offset, float labelWidth ) override;++ bool DrawContents( const TimelineContext& ctx, int& offset ) override;++ bool IsEmpty() const override;++private:+ GpuCtxData* m_gpu;+ int m_idx;+};++}++#endif
+ cbits/tracy/profiler/src/profiler/TracyTimelineItemPlot.cpp view
@@ -0,0 +1,252 @@+#include "TracyImGui.hpp"+#include "TracyPrint.hpp"+#include "TracyTimelineContext.hpp"+#include "TracyTimelineItemPlot.hpp"+#include "TracyUtility.hpp"+#include "TracyView.hpp"+#include "TracyWorker.hpp"+#include "tracy_pdqsort.h"++namespace tracy+{++constexpr int PlotHeightPx = 100;+constexpr int MinVisSize = 3;+++TimelineItemPlot::TimelineItemPlot( View& view, Worker& worker, PlotData* plot )+ : TimelineItem( view, worker, plot, true )+ , m_plot( plot )+{+}++bool TimelineItemPlot::IsEmpty() const+{+ return m_plot->data.empty();+}++const char* TimelineItemPlot::HeaderLabel() const+{+ static char tmp[1024];+ switch( m_plot->type )+ {+ case PlotType::User:+ return m_worker.GetString( m_plot->name );+ case PlotType::Memory:+ if( m_plot->name == 0 )+ {+ return ICON_FA_MEMORY " Memory usage";+ }+ else+ {+ sprintf( tmp, ICON_FA_MEMORY " %s", m_worker.GetString( m_plot->name ) );+ return tmp;+ }+ case PlotType::SysTime:+ return ICON_FA_GAUGE_HIGH " CPU usage";+ case PlotType::Power:+ sprintf( tmp, ICON_FA_BOLT " %s", m_worker.GetString( m_plot->name ) );+ return tmp;+ default:+ assert( false );+ return nullptr;+ }+}++void TimelineItemPlot::HeaderTooltip( const char* label ) const+{+ ImGui::BeginTooltip();+ SmallColorBox( GetPlotColor( *m_plot, m_worker ) );+ ImGui::SameLine();+ TextFocused( "Plot", label );+ ImGui::Separator();++ const auto first = RangeBegin();+ const auto last = RangeEnd();+ const auto activity = last - first;+ const auto traceLen = m_worker.GetLastTime() - m_worker.GetFirstTime();++ TextFocused( "Appeared at", TimeToString( first ) );+ TextFocused( "Last event at", TimeToString( last ) );+ TextFocused( "Activity time:", TimeToString( activity ) );+ ImGui::SameLine();+ char buf[64];+ PrintStringPercent( buf, activity / double( traceLen ) * 100 );+ TextDisabledUnformatted( buf );+ ImGui::Separator();+ TextFocused( "Data points:", RealToString( m_plot->data.size() ) );+ TextFocused( "Data range:", FormatPlotValue( m_plot->max - m_plot->min, m_plot->format ) );+ TextFocused( "Min value:", FormatPlotValue( m_plot->min, m_plot->format ) );+ TextFocused( "Max value:", FormatPlotValue( m_plot->max, m_plot->format ) );+ TextFocused( "Avg value:", FormatPlotValue( m_plot->sum / m_plot->data.size(), m_plot->format ) );+ TextFocused( "Data/second:", RealToString( double( m_plot->data.size() ) / activity * 1000000000ll ) );++ const auto it = std::lower_bound( m_plot->data.begin(), m_plot->data.end(), last - 1000000000ll * 10, [] ( const auto& l, const auto& r ) { return l.time.Val() < r; } );+ const auto tr10 = last - it->time.Val();+ if( tr10 != 0 )+ {+ TextFocused( "D/s (10s):", RealToString( double( std::distance( it, m_plot->data.end() ) ) / tr10 * 1000000000ll ) );+ }+ ImGui::EndTooltip();+}++void TimelineItemPlot::HeaderExtraContents( const TimelineContext& ctx, int offset, float labelWidth )+{+ auto draw = ImGui::GetWindowDrawList();+ const auto ty = ImGui::GetTextLineHeight();++ char tmp[128];+ sprintf( tmp, "(y-range: %s, visible data points: %s)", FormatPlotValue( m_plot->rMax - m_plot->rMin, m_plot->format ), RealToString( m_plot->num ) );+ draw->AddText( ctx.wpos + ImVec2( ty * 1.5f + labelWidth, offset ), 0xFF226E6E, tmp );+}++int64_t TimelineItemPlot::RangeBegin() const+{+ return m_plot->data.front().time.Val();+}++int64_t TimelineItemPlot::RangeEnd() const+{+ return m_plot->data.back().time.Val();+}++bool TimelineItemPlot::DrawContents( const TimelineContext& ctx, int& offset )+{+ return m_view.DrawPlot( ctx, *m_plot, m_draw, offset, m_rightEnd );+}++void TimelineItemPlot::DrawFinished()+{+ m_draw.clear();+}++void TimelineItemPlot::Preprocess( const TimelineContext& ctx, TaskDispatch& td, bool visible, int yPos )+{+ assert( m_draw.empty() );++ if( !visible ) return;+ if( yPos > ctx.yMax ) return;+ if( m_plot->data.empty() ) return;+ const auto PlotHeight = int( round( PlotHeightPx * GetScale() ) );+ if( yPos + PlotHeight < ctx.yMin ) return;++ td.Queue( [this, &ctx] {+ const auto vStart = ctx.vStart;+ const auto vEnd = ctx.vEnd;+ const auto nspx = ctx.nspx;+ const auto MinVisNs = int64_t( round( MinVisSize * nspx ) );++ auto& vec = m_plot->data;+ vec.ensure_sorted();+ if( vec.front().time.Val() > vEnd )+ {+ m_plot->rMin = 0;+ m_plot->rMax = 0;+ m_plot->num = 0;+ m_rightEnd = false;+ return;+ }+ else if( vec.back().time.Val() < vStart )+ {+ const auto lastTime = m_worker.GetLastTime();+ const auto val = vec.back().val;+ m_plot->rMin = val - 1;+ m_plot->rMax = val + 1;+ m_plot->num = lastTime < vStart ? 0 : 1;+ m_rightEnd = vec.back().time.Val() < lastTime;+ return;+ }++ auto it = std::lower_bound( vec.begin(), vec.end(), vStart, [] ( const auto& l, const auto& r ) { return l.time.Val() < r; } );+ auto end = std::lower_bound( it, vec.end(), vEnd, [] ( const auto& l, const auto& r ) { return l.time.Val() < r; } );++ m_rightEnd = end == vec.end() && vec.back().time.Val() < m_worker.GetLastTime();++ if( end != vec.end() ) end++;+ if( it != vec.begin() ) it--;++ double min = it->val;+ double max = it->val;+ const auto num = end - it;+ if( num > 1000000 )+ {+ min = m_plot->min;+ max = m_plot->max;+ }+ else+ {+ auto tmp = it;+ while( ++tmp < end )+ {+ if( tmp->val < min ) min = tmp->val;+ else if( tmp->val > max ) max = tmp->val;+ }+ }+ if( min == max )+ {+ min--;+ max++;+ }++ m_plot->rMin = min;+ m_plot->rMax = max;+ m_plot->num = num;++ m_draw.emplace_back( 0 );+ m_draw.emplace_back( it - vec.begin() );++ ++it;+ while( it < end )+ {+ auto next = std::upper_bound( it, end, int64_t( it->time.Val() + MinVisNs ), [] ( const auto& l, const auto& r ) { return l < r.time.Val(); } );+ assert( next > it );+ const auto rsz = uint32_t( next - it );+ if( rsz < 4 )+ {+ for( int i=0; i<rsz; i++ )+ {+ m_draw.emplace_back( 0 );+ m_draw.emplace_back( it - vec.begin() );+ ++it;+ }+ }+ else+ {+ // Sync with View::DrawPlot()!+ constexpr int NumSamples = 256;+ uint32_t samples[NumSamples];+ uint32_t cnt = 0;+ uint32_t offset = it - vec.begin();+ if( rsz < NumSamples )+ {+ for( cnt=0; cnt<rsz; cnt++ )+ {+ samples[cnt] = offset + cnt;+ }+ }+ else+ {+ const auto skip = ( rsz + NumSamples - 1 ) / NumSamples;+ const auto limit = rsz / skip;+ for( cnt=0; cnt<limit; cnt++ )+ {+ samples[cnt] = offset + cnt * skip;+ }+ if( cnt == limit ) cnt--;+ samples[cnt++] = offset + rsz - 1;+ }+ it = next;++ pdqsort_branchless( samples, samples+cnt, [&vec] ( const auto& l, const auto& r ) { return vec[l].val < vec[r].val; } );++ assert( rsz > 0 );+ m_draw.emplace_back( rsz );+ m_draw.emplace_back( offset );+ m_draw.emplace_back( samples[0] );+ m_draw.emplace_back( samples[cnt-1] );+ }+ }+ } );+}++}
+ cbits/tracy/profiler/src/profiler/TracyTimelineItemPlot.hpp view
@@ -0,0 +1,44 @@+#ifndef __TRACYTIMELINEITEMPLOT_HPP__+#define __TRACYTIMELINEITEMPLOT_HPP__++#include "TracyEvent.hpp"+#include "TracyTimelineDraw.hpp"+#include "TracyTimelineItem.hpp"++namespace tracy+{++class TimelineItemPlot final : public TimelineItem+{+public:+ TimelineItemPlot( View& view, Worker& worker, PlotData* plot );++protected:+ uint32_t HeaderColor() const override { return 0xFF44DDDD; }+ uint32_t HeaderColorInactive() const override { return 0xFF226E6E; }+ uint32_t HeaderLineColor() const override { return 0x8844DDDD; }+ const char* HeaderLabel() const override;++ int64_t RangeBegin() const override;+ int64_t RangeEnd() const override;++ void HeaderTooltip( const char* label ) const override;+ void HeaderExtraContents( const TimelineContext& ctx, int offset, float labelWidth ) override;++ bool DrawContents( const TimelineContext& ctx, int& offset ) override;+ void DrawFinished() override;++ bool IsEmpty() const override;++ void Preprocess( const TimelineContext& ctx, TaskDispatch& td, bool visible, int yPos ) override;++private:+ PlotData* m_plot;++ std::vector<uint32_t> m_draw;+ bool m_rightEnd;+};++}++#endif
+ cbits/tracy/profiler/src/profiler/TracyTimelineItemThread.cpp view
@@ -0,0 +1,1046 @@+#include <algorithm>+#include <limits>++#include "TracyColor.hpp"+#include "TracyImGui.hpp"+#include "TracyLockHelpers.hpp"+#include "TracyMouse.hpp"+#include "TracyPrint.hpp"+#include "TracyTimelineContext.hpp"+#include "TracyTimelineItemThread.hpp"+#include "TracyView.hpp"+#include "TracyWorker.hpp"++namespace tracy+{++constexpr float MinVisSize = 3;+constexpr float MinCtxSize = 4;+++TimelineItemThread::TimelineItemThread( View& view, Worker& worker, const ThreadData* thread )+ : TimelineItem( view, worker, thread, true )+ , m_thread( thread )+ , m_ghost( false )+{+ auto name = worker.GetThreadName( thread->id );+ if( strncmp( name, "Tracy ", 6 ) == 0 )+ {+ m_showFull = false;+ }+}++bool TimelineItemThread::IsEmpty() const+{+ auto& crash = m_worker.GetCrashEvent();+ return crash.thread != m_thread->id &&+ m_thread->timeline.empty() &&+ m_thread->messages.empty() &&+ m_thread->ghostZones.empty();+}++uint32_t TimelineItemThread::HeaderColor() const+{+ auto& crash = m_worker.GetCrashEvent();+ if( crash.thread == m_thread->id ) return 0xFF2222FF;+ if( m_thread->isFiber ) return 0xFF88FF88;+ return 0xFFFFFFFF;+}++uint32_t TimelineItemThread::HeaderColorInactive() const+{+ auto& crash = m_worker.GetCrashEvent();+ if( crash.thread == m_thread->id ) return 0xFF111188;+ if( m_thread->isFiber ) return 0xFF448844;+ return 0xFF888888;+}++uint32_t TimelineItemThread::HeaderLineColor() const+{+ return 0x33FFFFFF;+}++const char* TimelineItemThread::HeaderLabel() const+{+ return m_worker.GetThreadName( m_thread->id );+}++int64_t TimelineItemThread::RangeBegin() const+{+ int64_t first = std::numeric_limits<int64_t>::max();+ const auto ctx = m_worker.GetContextSwitchData( m_thread->id );+ if( ctx && !ctx->v.empty() )+ {+ first = ctx->v.begin()->Start();+ }+ if( !m_thread->timeline.empty() )+ {+ if( m_thread->timeline.is_magic() )+ {+ auto& tl = *((Vector<ZoneEvent>*)&m_thread->timeline);+ first = std::min( first, tl.front().Start() );+ }+ else+ {+ first = std::min( first, m_thread->timeline.front()->Start() );+ }+ }+ if( !m_thread->messages.empty() )+ {+ first = std::min( first, m_thread->messages.front()->time );+ }+ for( const auto& lock : m_worker.GetLockMap() )+ {+ const auto& lockmap = *lock.second;+ if( !lockmap.valid ) continue;+ auto it = lockmap.threadMap.find( m_thread->id );+ if( it == lockmap.threadMap.end() ) continue;+ const auto thread = it->second;+ auto lptr = lockmap.timeline.data();+ while( lptr->ptr->thread != thread ) lptr++;+ if( lptr->ptr->Time() < first ) first = lptr->ptr->Time();+ }+ return first;+}++int64_t TimelineItemThread::RangeEnd() const+{+ int64_t last = -1;+ const auto ctx = m_worker.GetContextSwitchData( m_thread->id );+ if( ctx && !ctx->v.empty() )+ {+ const auto& back = ctx->v.back();+ last = back.IsEndValid() ? back.End() : back.Start();+ }+ if( !m_thread->timeline.empty() )+ {+ if( m_thread->timeline.is_magic() )+ {+ auto& tl = *((Vector<ZoneEvent>*)&m_thread->timeline);+ last = std::max( last, m_worker.GetZoneEnd( tl.back() ) );+ }+ else+ {+ last = std::max( last, m_worker.GetZoneEnd( *m_thread->timeline.back() ) );+ }+ }+ if( !m_thread->messages.empty() )+ {+ last = std::max( last, m_thread->messages.back()->time );+ }+ for( const auto& lock : m_worker.GetLockMap() )+ {+ const auto& lockmap = *lock.second;+ if( !lockmap.valid ) continue;+ auto it = lockmap.threadMap.find( m_thread->id );+ if( it == lockmap.threadMap.end() ) continue;+ const auto thread = it->second;+ auto eptr = lockmap.timeline.data() + lockmap.timeline.size() - 1;+ while( eptr->ptr->thread != thread ) eptr--;+ if( eptr->ptr->Time() > last ) last = eptr->ptr->Time();+ }+ return last;+}++void TimelineItemThread::HeaderTooltip( const char* label ) const+{+ m_view.HighlightThread( m_thread->id );++ ImGui::BeginTooltip();+ SmallColorBox( GetThreadColor( m_thread->id, 0, m_view.GetViewData().dynamicColors ) );+ ImGui::SameLine();+ ImGui::TextUnformatted( m_worker.GetThreadName( m_thread->id ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( m_thread->id ) );+ auto& crash = m_worker.GetCrashEvent();+ if( crash.thread == m_thread->id )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 1.f, 0.2f, 0.2f, 1.f ), ICON_FA_SKULL " Crashed" );+ }+ if( m_thread->isFiber )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 0.2f, 0.6f, 0.2f, 1.f ), "Fiber" );+ }++ const auto ctx = m_worker.GetContextSwitchData( m_thread->id );+ const auto first = RangeBegin();+ const auto last = RangeEnd();++ ImGui::Separator();++ size_t lockCnt = 0;+ for( const auto& lock : m_worker.GetLockMap() )+ {+ const auto& lockmap = *lock.second;+ if( !lockmap.valid ) continue;+ auto it = lockmap.threadMap.find( m_thread->id );+ if( it == lockmap.threadMap.end() ) continue;+ lockCnt++;+ }++ if( last >= 0 )+ {+ const auto lifetime = last - first;+ const auto traceLen = m_worker.GetLastTime() - m_worker.GetFirstTime();++ TextFocused( "Appeared at", TimeToString( first ) );+ TextFocused( "Last event at", TimeToString( last ) );+ TextFocused( "Lifetime:", TimeToString( lifetime ) );+ ImGui::SameLine();+ char buf[64];+ PrintStringPercent( buf, lifetime / double( traceLen ) * 100 );+ TextDisabledUnformatted( buf );++ if( ctx )+ {+ TextFocused( "Time in running state:", TimeToString( ctx->runningTime ) );+ ImGui::SameLine();+ PrintStringPercent( buf, ctx->runningTime / double( lifetime ) * 100 );+ TextDisabledUnformatted( buf );+ }+ }++ ImGui::Separator();+ if( !m_thread->timeline.empty() )+ {+ TextFocused( "Zone count:", RealToString( m_thread->count ) );+ TextFocused( "Top-level zones:", RealToString( m_thread->timeline.size() ) );+ }+ if( !m_thread->messages.empty() )+ {+ TextFocused( "Messages:", RealToString( m_thread->messages.size() ) );+ }+ if( lockCnt != 0 )+ {+ TextFocused( "Locks:", RealToString( lockCnt ) );+ }+ if( ctx )+ {+ TextFocused( "Running state regions:", RealToString( ctx->v.size() ) );+ }+ if( !m_thread->samples.empty() )+ {+ TextFocused( "Call stack samples:", RealToString( m_thread->samples.size() ) );+ if( m_thread->kernelSampleCnt != 0 )+ {+ TextFocused( "Kernel samples:", RealToString( m_thread->kernelSampleCnt ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%.2f%%)", 100.f * m_thread->kernelSampleCnt / m_thread->samples.size() );+ }+ }+ ImGui::EndTooltip();+}++void TimelineItemThread::HeaderExtraContents( const TimelineContext& ctx, int offset, float labelWidth )+{+ m_view.DrawThreadMessagesList( ctx, m_msgDraw, offset, m_thread->id );++#ifndef TRACY_NO_STATISTICS+ const bool hasGhostZones = m_worker.AreGhostZonesReady() && !m_thread->ghostZones.empty();+ if( hasGhostZones && !m_thread->timeline.empty() )+ {+ auto draw = ImGui::GetWindowDrawList();+ const auto ty = ImGui::GetTextLineHeight();++ const auto color = m_ghost ? 0xFFAA9999 : 0x88AA7777;+ draw->AddText( ctx.wpos + ImVec2( 1.5f * ty + labelWidth, offset ), color, ICON_FA_GHOST );+ float ghostSz = ImGui::CalcTextSize( ICON_FA_GHOST ).x;++ if( ctx.hover && ImGui::IsMouseHoveringRect( ctx.wpos + ImVec2( 1.5f * ty + labelWidth, offset ), ctx.wpos + ImVec2( 1.5f * ty + labelWidth + ghostSz, offset + ty ) ) )+ {+ if( IsMouseClicked( 0 ) )+ {+ m_ghost = !m_ghost;+ }+ }+ }+#endif+}++bool TimelineItemThread::DrawContents( const TimelineContext& ctx, int& offset )+{+ m_view.DrawThread( ctx, *m_thread, m_draw, m_ctxDraw, m_samplesDraw, m_lockDraw, offset, m_depth, m_hasCtxSwitch, m_hasSamples );+ if( m_depth == 0 && !m_hasMessages )+ {+ auto& crash = m_worker.GetCrashEvent();+ return crash.thread == m_thread->id;+ }+ return true;+}++void TimelineItemThread::DrawOverlay( const ImVec2& ul, const ImVec2& dr )+{+ m_view.DrawThreadOverlays( *m_thread, ul, dr );+}++void TimelineItemThread::DrawExtraPopupItems()+{+ if( m_view.GetSelectThread() == m_thread->id )+ {+ if( ImGui::MenuItem( ICON_FA_TIMELINE " Unselect in CPU timeline" ) )+ {+ m_view.SelectThread( 0 );+ }+ }+ else if( m_view.GetViewData().drawCpuData && ImGui::MenuItem( ICON_FA_TIMELINE " Select in CPU timeline" ) )+ {+ m_view.SelectThread( m_thread->id );+ }+ }++void TimelineItemThread::DrawFinished()+{+ m_samplesDraw.clear();+ m_ctxDraw.clear();+ m_draw.clear();+ m_msgDraw.clear();+ m_lockDraw.clear();+}++void TimelineItemThread::Preprocess( const TimelineContext& ctx, TaskDispatch& td, bool visible, int yPos )+{+ assert( m_samplesDraw.empty() );+ assert( m_ctxDraw.empty() );+ assert( m_draw.empty() );+ assert( m_msgDraw.empty() );+ assert( m_lockDraw.empty() );++ td.Queue( [this, &ctx, visible] {+#ifndef TRACY_NO_STATISTICS+ if( m_worker.AreGhostZonesReady() && ( m_ghost || ( m_view.GetViewData().ghostZones && m_thread->timeline.empty() ) ) )+ {+ m_depth = PreprocessGhostLevel( ctx, m_thread->ghostZones, 0, visible );+ }+ else+#endif+ {+ m_depth = PreprocessZoneLevel( ctx, m_thread->timeline, 0, visible, 0 );+ }+ } );++ const auto& vd = m_view.GetViewData();++ m_hasCtxSwitch = false;+ if( vd.drawContextSwitches )+ {+ auto ctxSwitch = m_worker.GetContextSwitchData( m_thread->id );+ if( ctxSwitch )+ {+ // There is no yPos passed here to enable more granular visibility check,+ // as context switch shadows will usually be projected down onto zones.+ td.Queue( [this, &ctx, ctxSwitch, visible] {+ PreprocessContextSwitches( ctx, *ctxSwitch, visible );+ } );+ }+ }++ m_hasSamples = false;+ if( vd.drawSamples && !m_thread->samples.empty() )+ {+ td.Queue( [this, &ctx, visible, yPos] {+ PreprocessSamples( ctx, m_thread->samples, visible, yPos );+ } );+ }++ m_hasMessages = false;+ td.Queue( [this, &ctx, visible, yPos] {+ PreprocessMessages( ctx, m_thread->messages, m_thread->id, visible, yPos );+ } );++ if( vd.drawLocks )+ {+ const auto& locks = m_worker.GetLockMap();+ if( !locks.empty() )+ {+ PreprocessLocks( ctx, locks, m_thread->id, td, visible );+ }+ }+}++#ifndef TRACY_NO_STATISTICS+int TimelineItemThread::PreprocessGhostLevel( const TimelineContext& ctx, const Vector<GhostZone>& vec, int depth, bool visible )+{+ const auto nspx = ctx.nspx;+ const auto vStart = ctx.vStart;+ const auto vEnd = ctx.vEnd;++ const auto MinVisNs = int64_t( round( GetScale() * MinVisSize * nspx ) );++ auto it = std::lower_bound( vec.begin(), vec.end(), std::max<int64_t>( 0, vStart - 2 * MinVisNs ), [] ( const auto& l, const auto& r ) { return l.end.Val() < r; } );+ if( it == vec.end() ) return depth;++ const auto zitend = std::lower_bound( it, vec.end(), vEnd, [] ( const auto& l, const auto& r ) { return l.start.Val() < r; } );+ if( it == zitend ) return depth;+ if( (zitend-1)->end.Val() < vStart ) return depth;++ int maxdepth = depth + 1;++ while( it < zitend )+ {+ auto& ev = *it;+ const auto end = ev.end.Val();+ const auto zsz = end - ev.start.Val();+ if( zsz < MinVisNs )+ {+ auto nextTime = end + MinVisNs;+ auto next = it + 1;+ for(;;)+ {+ next = std::lower_bound( next, zitend, nextTime, [] ( const auto& l, const auto& r ) { return l.end.Val() < r; } );+ if( next == zitend ) break;+ auto prev = next - 1;+ const auto pt = prev->end.Val();+ const auto nt = next->end.Val();+ if( nt - pt >= MinVisNs ) break;+ nextTime = nt + MinVisNs;+ }+ if( visible ) m_draw.emplace_back( TimelineDraw { TimelineDrawType::GhostFolded, uint16_t( depth ), (void**)&ev, (next-1)->end } );+ it = next;+ }+ else+ {+ if( ev.child >= 0 )+ {+ const auto d = PreprocessGhostLevel( ctx, m_worker.GetGhostChildren( ev.child ), depth + 1, visible );+ if( d > maxdepth ) maxdepth = d;+ }+ if( visible ) m_draw.emplace_back( TimelineDraw { TimelineDrawType::Ghost, uint16_t( depth ), (void**)&ev } );+ ++it;+ }+ }++ return maxdepth;+}+#endif++int TimelineItemThread::PreprocessZoneLevel( const TimelineContext& ctx, const Vector<short_ptr<ZoneEvent>>& vec, int depth, bool visible, const uint32_t inheritedColor )+{+ if( vec.is_magic() )+ {+ return PreprocessZoneLevel<VectorAdapterDirect<ZoneEvent>>( ctx, *(Vector<ZoneEvent>*)( &vec ), depth, visible, inheritedColor );+ }+ else+ {+ return PreprocessZoneLevel<VectorAdapterPointer<ZoneEvent>>( ctx, vec, depth, visible, inheritedColor );+ }+}++template<typename Adapter, typename V>+int TimelineItemThread::PreprocessZoneLevel( const TimelineContext& ctx, const V& vec, int depth, bool visible, const uint32_t inheritedColor )+{+ const auto vStart = ctx.vStart;+ const auto vEnd = ctx.vEnd;+ const auto nspx = ctx.nspx;++ const auto MinVisNs = int64_t( round( GetScale() * MinVisSize * nspx ) );++ auto it = std::lower_bound( vec.begin(), vec.end(), vStart, [this] ( const auto& l, const auto& r ) { Adapter a; return m_worker.GetZoneEnd( a(l) ) < r; } );+ if( it == vec.end() ) return depth;++ const auto zitend = std::lower_bound( it, vec.end(), vEnd, [] ( const auto& l, const auto& r ) { Adapter a; return a(l).Start() < r; } );+ if( it == zitend ) return depth;+ Adapter a;+ if( !a(*it).IsEndValid() && m_worker.GetZoneEnd( a(*it) ) < vStart ) return depth;+ if( m_worker.GetZoneEnd( a(*(zitend-1)) ) < vStart ) return depth;++ int maxdepth = depth + 1;++ while( it < zitend )+ {+ auto& ev = a(*it);+ const auto end = m_worker.GetZoneEnd( ev );+ const auto zsz = end - ev.Start();+ if( zsz < MinVisNs )+ {+ auto nextTime = end + MinVisNs;+ auto next = it + 1;+ for(;;)+ {+ next = std::lower_bound( next, zitend, nextTime, [this] ( const auto& l, const auto& r ) { Adapter a; return m_worker.GetZoneEnd( a(l) ) < r; } );+ if( next == zitend ) break;+ auto prev = next - 1;+ const auto pt = m_worker.GetZoneEnd( a(*prev) );+ const auto nt = m_worker.GetZoneEnd( a(*next) );+ if( nt - pt >= MinVisNs ) break;+ nextTime = nt + MinVisNs;+ }+ if( visible ) m_draw.emplace_back( TimelineDraw { TimelineDrawType::Folded, uint16_t( depth ), (void**)&ev, m_worker.GetZoneEnd( a(*(next-1)) ), uint32_t( next - it ), inheritedColor } );+ it = next;+ }+ else+ {+ const auto hasChildren = ev.HasChildren();+ auto currentInherited = inheritedColor;+ auto childrenInherited = inheritedColor;+ if( m_view.GetViewData().inheritParentColors )+ {+ uint32_t color = 0;+ if( m_worker.HasZoneExtra( ev ) )+ {+ const auto& extra = m_worker.GetZoneExtra( ev );+ color = extra.color.Val();+ }+ if( color == 0 )+ {+ auto& srcloc = m_worker.GetSourceLocation( ev.SrcLoc() );+ color = srcloc.color;+ }+ if( color != 0 )+ {+ currentInherited = color | 0xFF000000;+ if( hasChildren ) childrenInherited = DarkenColorSlightly( color );+ }+ }+ if( hasChildren )+ {+ const auto d = PreprocessZoneLevel( ctx, m_worker.GetZoneChildren( ev.Child() ), depth + 1, visible, childrenInherited );+ if( d > maxdepth ) maxdepth = d;+ }+ if( visible ) m_draw.emplace_back( TimelineDraw { TimelineDrawType::Zone, uint16_t( depth ), (void**)&ev, 0, 0, currentInherited } );+ ++it;+ }+ }++ return maxdepth;+}++void TimelineItemThread::PreprocessContextSwitches( const TimelineContext& ctx, const ContextSwitch& ctxSwitch, bool visible )+{+ const auto nspx = ctx.nspx;+ const auto vStart = ctx.vStart;+ const auto vEnd = ctx.vEnd;++ auto& vec = ctxSwitch.v;+ auto it = std::lower_bound( vec.begin(), vec.end(), std::max<int64_t>( 0, vStart ), [] ( const auto& l, const auto& r ) { return ( l.IsEndValid() ? l.End() : l.Start() ) < r; } );+ if( it == vec.end() ) return;+ if( it != vec.begin() ) --it;++ auto citend = std::lower_bound( it, vec.end(), vEnd, [] ( const auto& l, const auto& r ) { return l.Start() < r; } );+ if( it == citend ) return;+ if( citend != vec.end() ) ++citend;++ m_hasCtxSwitch = true;+ if( !visible ) return;++ const auto MinCtxNs = int64_t( round( GetScale() * MinCtxSize * nspx ) );+ const auto& sampleData = m_thread->samples;++ bool first = true;+ while( it < citend )+ {+ auto& ev = *it;+ if( first )+ {+ first = false;+ }+ else+ {+ uint32_t waitStack = 0;+ if( !sampleData.empty() )+ {+ auto sdit = std::lower_bound( sampleData.begin(), sampleData.end(), ev.Start(), [] ( const auto& l, const auto& r ) { return l.time.Val() < r; } );+ bool found = sdit != sampleData.end() && sdit->time.Val() == ev.Start();+ if( !found && it != vec.begin() )+ {+ auto eit = it;+ --eit;+ sdit = std::lower_bound( sampleData.begin(), sampleData.end(), eit->End(), [] ( const auto& l, const auto& r ) { return l.time.Val() < r; } );+ found = sdit != sampleData.end() && sdit->time.Val() == eit->End();+ }+ if( found ) waitStack = sdit->callstack.Val();+ }+ m_ctxDraw.emplace_back( ContextSwitchDraw { ContextSwitchDrawType::Waiting, uint32_t( it - vec.begin() ), waitStack } );+ }++ const auto end = ev.IsEndValid() ? ev.End() : ev.Start();+ const auto zsz = end - ev.Start();+ if( zsz < MinCtxNs )+ {+ auto nextTime = end + MinCtxNs;+ auto next = it + 1;+ for(;;)+ {+ next = std::lower_bound( next, citend, nextTime, [] ( const auto& l, const auto& r ) { return ( l.IsEndValid() ? l.End() : l.Start() ) < r; } );+ if( next == citend ) break;+ auto prev = next - 1;+ const auto pt = prev->IsEndValid() ? prev->End() : prev->Start();+ const auto nt = next->IsEndValid() ? next->End() : next->Start();+ if( nt - pt >= MinCtxNs ) break;+ nextTime = nt + MinCtxNs;+ }+ m_ctxDraw.emplace_back( ContextSwitchDraw { ContextSwitchDrawType::Folded, uint32_t( it - vec.begin() ), uint32_t( next - it ) } );+ it = next;+ }+ else+ {+ m_ctxDraw.emplace_back( ContextSwitchDraw { ContextSwitchDrawType::Running, uint32_t( it - vec.begin() ) } );+ ++it;+ }+ }+}++void TimelineItemThread::PreprocessSamples( const TimelineContext& ctx, const Vector<SampleData>& vec, bool visible, int yPos )+{+ const auto vStart = ctx.vStart;+ const auto vEnd = ctx.vEnd;+ const auto nspx = ctx.nspx;+ const auto ty = ctx.ty;+ const auto ostep = ty + 1;+ const auto pos = yPos + ostep;++ const auto MinVis = 5 * GetScale();+ const auto MinVisNs = int64_t( round( MinVis * nspx ) );++ auto it = std::lower_bound( vec.begin(), vec.end(), vStart - MinVisNs, [] ( const auto& l, const auto& r ) { return l.time.Val() < r; } );+ if( it == vec.end() ) return;+ const auto itend = std::lower_bound( it, vec.end(), vEnd, [] ( const auto& l, const auto& r ) { return l.time.Val() < r; } );+ if( it == itend ) return;++ m_hasSamples = true;+ if( !visible ) return;++ const auto ty0375 = pos + round( ty * 0.375f );+ const auto ty02 = round( ty * 0.2f );+ const auto y0 = ty0375 - ty02 - 3;+ const auto y1 = ty0375 + ty02 - 1;+ if( y0 > ctx.yMax || y1 < ctx.yMin ) return;++ while( it < itend )+ {+ auto next = it + 1;+ if( next != itend )+ {+ const auto t0 = it->time.Val();+ auto nextTime = t0 + MinVisNs;+ for(;;)+ {+ next = std::lower_bound( next, itend, nextTime, [] ( const auto& l, const auto& r ) { return l.time.Val() < r; } );+ if( next == itend ) break;+ auto prev = next - 1;+ const auto pt = prev->time.Val();+ const auto nt = next->time.Val();+ if( nt - pt >= MinVisNs ) break;+ nextTime = nt + MinVisNs;+ }+ }+ m_samplesDraw.emplace_back( SamplesDraw { uint32_t( next - it - 1 ), uint32_t( it - vec.begin() ) } );+ it = next;+ }+}++void TimelineItemThread::PreprocessMessages( const TimelineContext& ctx, const Vector<short_ptr<MessageData>>& vec, uint64_t tid, bool visible, int yPos )+{+ const auto vStart = ctx.vStart;+ const auto vEnd = ctx.vEnd;+ const auto nspx = ctx.nspx;++ const auto MinVisNs = int64_t( round( GetScale() * MinVisSize * nspx ) );++ auto it = std::lower_bound( vec.begin(), vec.end(), vStart, [] ( const auto& lhs, const auto& rhs ) { return lhs->time < rhs; } );+ if( it == vec.end() ) return;+ auto end = std::lower_bound( it, vec.end(), vEnd+1, [] ( const auto& lhs, const auto& rhs ) { return lhs->time < rhs; } );+ if( it == end ) return;++ m_hasMessages = true;+ if( !visible ) return;+ if( yPos > ctx.yMax || yPos + ctx.ty < ctx.yMin ) return;++ const auto hMsg = m_view.GetMessageHighlight();+ const auto hThread = hMsg ? m_worker.DecompressThread( hMsg->thread ) : 0;++ while( it < end )+ {+ const auto msgTime = (*it)->time;+ const auto nextTime = msgTime + MinVisNs;+ const auto next = std::upper_bound( it, vec.end(), nextTime, [] ( const auto& lhs, const auto& rhs ) { return lhs < rhs->time; } );+ const auto num = next - it;+ bool hilite;+ if( num == 1 )+ {+ hilite = hMsg == *it;+ }+ else+ {+ if( hMsg && hThread == tid )+ {+ const auto hTime = hMsg->time;+ hilite = (*it)->time <= hTime && ( next == vec.end() || (*next)->time > hTime );+ }+ else+ {+ hilite = false;+ }+ }+ m_msgDraw.emplace_back( MessagesDraw { *it, hilite, uint32_t( num ) } );+ it = next;+ }+}++static Vector<LockEventPtr>::const_iterator GetNextLockEvent( const Vector<LockEventPtr>::const_iterator& it, const Vector<LockEventPtr>::const_iterator& end, LockState::Type& nextState, uint64_t threadBit )+{+ auto next = it;+ next++;++ switch( nextState )+ {+ case LockState::Nothing:+ while( next < end )+ {+ if( next->lockCount != 0 )+ {+ if( GetThreadBit( next->lockingThread ) == threadBit )+ {+ nextState = AreOtherWaiting( next->waitList, threadBit ) ? LockState::HasBlockingLock : LockState::HasLock;+ break;+ }+ else if( IsThreadWaiting( next->waitList, threadBit ) )+ {+ nextState = LockState::WaitLock;+ break;+ }+ }+ next++;+ }+ break;+ case LockState::HasLock:+ while( next < end )+ {+ if( next->lockCount == 0 )+ {+ nextState = LockState::Nothing;+ break;+ }+ if( next->waitList != 0 )+ {+ if( AreOtherWaiting( next->waitList, threadBit ) )+ {+ nextState = LockState::HasBlockingLock;+ }+ break;+ }+ if( next->waitList != it->waitList || next->lockCount != it->lockCount )+ {+ break;+ }+ next++;+ }+ break;+ case LockState::HasBlockingLock:+ while( next < end )+ {+ if( next->lockCount == 0 )+ {+ nextState = LockState::Nothing;+ break;+ }+ if( next->waitList != it->waitList || next->lockCount != it->lockCount )+ {+ break;+ }+ next++;+ }+ break;+ case LockState::WaitLock:+ while( next < end )+ {+ if( GetThreadBit( next->lockingThread ) == threadBit )+ {+ nextState = AreOtherWaiting( next->waitList, threadBit ) ? LockState::HasBlockingLock : LockState::HasLock;+ break;+ }+ if( next->lockingThread != it->lockingThread )+ {+ break;+ }+ if( next->lockCount == 0 )+ {+ break;+ }+ next++;+ }+ break;+ default:+ assert( false );+ break;+ }++ return next;+}++static LockState::Type CombineLockState( LockState::Type state, LockState::Type next )+{+ return std::max( state, next );+}++static Vector<LockEventPtr>::const_iterator GetNextLockEventShared( const Vector<LockEventPtr>::const_iterator& it, const Vector<LockEventPtr>::const_iterator& end, LockState::Type& nextState, uint64_t threadBit )+{+ const auto itptr = (const LockEventShared*)(const LockEvent*)it->ptr;+ auto next = it;+ next++;++ switch( nextState )+ {+ case LockState::Nothing:+ while( next < end )+ {+ const auto ptr = (const LockEventShared*)(const LockEvent*)next->ptr;+ if( next->lockCount != 0 )+ {+ const auto wait = next->waitList | ptr->waitShared;+ if( GetThreadBit( next->lockingThread ) == threadBit )+ {+ nextState = AreOtherWaiting( wait, threadBit ) ? LockState::HasBlockingLock : LockState::HasLock;+ break;+ }+ else if( IsThreadWaiting( wait, threadBit ) )+ {+ nextState = LockState::WaitLock;+ break;+ }+ }+ else if( IsThreadWaiting( ptr->sharedList, threadBit ) )+ {+ nextState = ( next->waitList != 0 ) ? LockState::HasBlockingLock : LockState::HasLock;+ break;+ }+ else if( ptr->sharedList != 0 && IsThreadWaiting( next->waitList, threadBit ) )+ {+ nextState = LockState::WaitLock;+ break;+ }+ next++;+ }+ break;+ case LockState::HasLock:+ while( next < end )+ {+ const auto ptr = (const LockEventShared*)(const LockEvent*)next->ptr;+ if( next->lockCount == 0 && !IsThreadWaiting( ptr->sharedList, threadBit ) )+ {+ nextState = LockState::Nothing;+ break;+ }+ if( next->waitList != 0 )+ {+ if( AreOtherWaiting( next->waitList, threadBit ) )+ {+ nextState = LockState::HasBlockingLock;+ }+ break;+ }+ else if( !IsThreadWaiting( ptr->sharedList, threadBit ) && ptr->waitShared != 0 )+ {+ nextState = LockState::HasBlockingLock;+ break;+ }+ if( next->waitList != it->waitList || ptr->waitShared != itptr->waitShared || next->lockCount != it->lockCount || ptr->sharedList != itptr->sharedList )+ {+ break;+ }+ next++;+ }+ break;+ case LockState::HasBlockingLock:+ while( next < end )+ {+ const auto ptr = (const LockEventShared*)(const LockEvent*)next->ptr;+ if( next->lockCount == 0 && !IsThreadWaiting( ptr->sharedList, threadBit ) )+ {+ nextState = LockState::Nothing;+ break;+ }+ if( next->waitList != it->waitList || ptr->waitShared != itptr->waitShared || next->lockCount != it->lockCount || ptr->sharedList != itptr->sharedList )+ {+ break;+ }+ next++;+ }+ break;+ case LockState::WaitLock:+ while( next < end )+ {+ const auto ptr = (const LockEventShared*)(const LockEvent*)next->ptr;+ if( GetThreadBit( next->lockingThread ) == threadBit )+ {+ const auto wait = next->waitList | ptr->waitShared;+ nextState = AreOtherWaiting( wait, threadBit ) ? LockState::HasBlockingLock : LockState::HasLock;+ break;+ }+ if( IsThreadWaiting( ptr->sharedList, threadBit ) )+ {+ nextState = ( next->waitList != 0 ) ? LockState::HasBlockingLock : LockState::HasLock;+ break;+ }+ if( next->lockingThread != it->lockingThread )+ {+ break;+ }+ if( next->lockCount == 0 && !IsThreadWaiting( ptr->waitShared, threadBit ) )+ {+ break;+ }+ next++;+ }+ break;+ default:+ assert( false );+ break;+ }++ return next;+}++void TimelineItemThread::PreprocessLocks( const TimelineContext& ctx, const unordered_flat_map<uint32_t, LockMap*>& locks, uint32_t tid, TaskDispatch& td, bool visible )+{+ const auto vStart = ctx.vStart;+ const auto vEnd = ctx.vEnd;+ const auto nspx = ctx.nspx;++ const auto& vd = m_view.GetViewData();+ const auto lockInfoWindow = m_view.GetLockInfoWindow();++ const auto MinVisNs = int64_t( round( GetScale() * MinVisSize * nspx ) );++ for( auto& v : locks )+ {+ const auto& lockmap = *v.second;+ if( !lockmap.valid ) continue;+ if( !m_view.Vis( &lockmap ) ) continue;+ if( vd.onlyContendedLocks && lockInfoWindow != v.first && ( lockmap.threadList.size() == 1 || !lockmap.isContended ) ) continue;++ auto it = lockmap.threadMap.find( tid );+ if( it == lockmap.threadMap.end() ) continue;++ assert( !lockmap.timeline.empty() );+ const auto& range = lockmap.range[it->second];+ if( range.start > vEnd || range.end < vStart )+ {+ if( lockInfoWindow == v.first )+ {+ m_lockDraw.emplace_back( std::make_unique<LockDraw>( LockDraw { v.first, true, it->second } ) );+ }+ continue;+ }++ auto drawData = std::make_unique<LockDraw>( LockDraw { v.first, false, it->second } );+ auto drawPtr = drawData.get();+ m_lockDraw.emplace_back( std::move( drawData ) );++ td.Queue( [this, it, &lockmap, &ctx, &range, &vd, visible, drawPtr, MinVisNs] {+ const auto vStart = ctx.vStart;+ const auto vEnd = ctx.vEnd;++ auto GetNextLockFunc = lockmap.type == LockType::Lockable ? GetNextLockEvent : GetNextLockEventShared;+ const auto thread = it->second;+ const auto threadBit = GetThreadBit( thread );+ const auto& tl = lockmap.timeline;++ auto vbegin = std::lower_bound( tl.begin(), tl.end(), std::max( range.start, vStart ), [] ( const auto& l, const auto& r ) { return l.ptr->Time() < r; } );+ const auto vend = std::lower_bound( vbegin, tl.end(), std::min( range.end, vEnd ), [] ( const auto& l, const auto& r ) { return l.ptr->Time() < r; } );++ if( vbegin > tl.begin() ) vbegin--;++ LockState::Type state = LockState::Nothing;+ if( lockmap.type == LockType::Lockable )+ {+ if( vbegin->lockCount != 0 )+ {+ if( vbegin->lockingThread == thread )+ {+ state = AreOtherWaiting( vbegin->waitList, threadBit ) ? LockState::HasBlockingLock : LockState::HasLock;+ }+ else if( IsThreadWaiting( vbegin->waitList, threadBit ) )+ {+ state = LockState::WaitLock;+ }+ }+ }+ else+ {+ auto ptr = (const LockEventShared*)(const LockEvent*)vbegin->ptr;+ if( vbegin->lockCount != 0 )+ {+ if( vbegin->lockingThread == thread )+ {+ state = ( AreOtherWaiting( vbegin->waitList, threadBit ) || AreOtherWaiting( ptr->waitShared, threadBit ) ) ? LockState::HasBlockingLock : LockState::HasLock;+ }+ else if( IsThreadWaiting( vbegin->waitList, threadBit ) || IsThreadWaiting( ptr->waitShared, threadBit ) )+ {+ state = LockState::WaitLock;+ }+ }+ else if( IsThreadWaiting( ptr->sharedList, threadBit ) )+ {+ state = vbegin->waitList != 0 ? LockState::HasBlockingLock : LockState::HasLock;+ }+ else if( ptr->sharedList != 0 && IsThreadWaiting( vbegin->waitList, threadBit ) )+ {+ state = LockState::WaitLock;+ }+ }++ const uint8_t mask = vd.onlyContendedLocks ? ( LockState::Nothing | LockState::HasLock ) : LockState::Nothing;+ if( !visible )+ {+ while( vbegin < vend && ( state & mask ) != 0 )+ {+ vbegin = GetNextLockFunc( vbegin, vend, state, threadBit );+ }+ drawPtr->forceDraw = vbegin < vend;+ return;+ }++ auto& dst = drawPtr->data;+ for(;;)+ {+ while( vbegin < vend && ( state & mask ) != 0 )+ {+ vbegin = GetNextLockFunc( vbegin, vend, state, threadBit );+ }+ if( vbegin >= vend ) break;+ assert( ( state & mask ) == 0 );++ LockState::Type drawState = state;+ auto next = GetNextLockFunc( vbegin, vend, state, threadBit );++ const auto tStart = vbegin->ptr->Time();+ int64_t t0 = tStart;+ int64_t t1 = next == tl.end() ? m_worker.GetLastTime() : next->ptr->Time();+ uint32_t condensed = 0;++ for(;;)+ {+ if( next >= vend || t1 - t0 > MinVisNs ) break;+ auto n = next;+ auto ns = state;+ while( n < vend && ( ns & mask ) != 0 )+ {+ n = GetNextLockFunc( n, vend, ns, threadBit );+ }+ if( n >= vend ) break;+ if( n == next )+ {+ n = GetNextLockFunc( n, vend, ns, threadBit );+ }+ drawState = CombineLockState( drawState, state );+ condensed++;+ const auto t2 = n == tl.end() ? m_worker.GetLastTime() : n->ptr->Time();+ if( t2 - t1 > MinVisNs ) break;+ if( drawState != ns && t2 - tStart > MinVisNs && ( ns & mask ) == 0 ) break;+ t0 = t1;+ t1 = t2;+ next = n;+ state = ns;+ }++ dst.emplace_back( LockDrawItem { t1, drawState, condensed, vbegin, next } );++ vbegin = next;+ }+ } );+ }+}++}
+ cbits/tracy/profiler/src/profiler/TracyTimelineItemThread.hpp view
@@ -0,0 +1,67 @@+#ifndef __TRACYTIMELINEITEMTHREAD_HPP__+#define __TRACYTIMELINEITEMTHREAD_HPP__++#include "TracyEvent.hpp"+#include "TracyTimelineDraw.hpp"+#include "TracyTimelineItem.hpp"++namespace tracy+{++class TimelineItemThread final : public TimelineItem+{+public:+ TimelineItemThread( View& view, Worker& worker, const ThreadData* plot );++protected:+ uint32_t HeaderColor() const override;+ uint32_t HeaderColorInactive() const override;+ uint32_t HeaderLineColor() const override;+ const char* HeaderLabel() const override;++ int64_t RangeBegin() const override;+ int64_t RangeEnd() const override;++ void HeaderTooltip( const char* label ) const override;+ void HeaderExtraContents( const TimelineContext& ctx, int offset, float labelWidth ) override;++ bool DrawContents( const TimelineContext& ctx, int& offset ) override;+ void DrawOverlay( const ImVec2& ul, const ImVec2& dr ) override;+ void DrawExtraPopupItems() override;+ void DrawFinished() override;++ bool IsEmpty() const override;++ void Preprocess( const TimelineContext& ctx, TaskDispatch& td, bool visible, int yPos ) override;++private:+#ifndef TRACY_NO_STATISTICS+ int PreprocessGhostLevel( const TimelineContext& ctx, const Vector<GhostZone>& vec, int depth, bool visible );+#endif+ int PreprocessZoneLevel( const TimelineContext& ctx, const Vector<short_ptr<ZoneEvent>>& vec, int depth, bool visible, const uint32_t inheritedColor );++ template<typename Adapter, typename V>+ int PreprocessZoneLevel( const TimelineContext& ctx, const V& vec, int depth, bool visible, const uint32_t inheritedColor );++ void PreprocessContextSwitches( const TimelineContext& ctx, const ContextSwitch& ctxSwitch, bool visible );+ void PreprocessSamples( const TimelineContext& ctx, const Vector<SampleData>& vec, bool visible, int yPos );+ void PreprocessMessages( const TimelineContext& ctx, const Vector<short_ptr<MessageData>>& vec, uint64_t tid, bool visible, int yPos );+ void PreprocessLocks( const TimelineContext& ctx, const unordered_flat_map<uint32_t, LockMap*>& locks, uint32_t tid, TaskDispatch& td, bool visible );++ const ThreadData* m_thread;+ bool m_ghost;++ std::vector<SamplesDraw> m_samplesDraw;+ std::vector<ContextSwitchDraw> m_ctxDraw;+ std::vector<TimelineDraw> m_draw;+ std::vector<MessagesDraw> m_msgDraw;+ std::vector<std::unique_ptr<LockDraw>> m_lockDraw;+ int m_depth;+ bool m_hasCtxSwitch;+ bool m_hasSamples;+ bool m_hasMessages;+};++}++#endif
+ cbits/tracy/profiler/src/profiler/TracyUserData.cpp view
@@ -0,0 +1,389 @@+#include <assert.h>+#include <memory>++#ifdef _WIN32+# include <stdio.h>+#else+# include <unistd.h>+#endif++#include "../ini.h"++#include "TracyStorage.hpp"+#include "TracyUserData.hpp"+#include "TracyViewData.hpp"++namespace tracy+{++constexpr auto FileDescription = "description";+constexpr auto FileTimeline = "timeline";+constexpr auto FileOptions = "options";+constexpr auto FileAnnotations = "annotations";+constexpr auto FileSourceSubstitutions = "srcsub";++enum : uint32_t { VersionTimeline = 0 };+enum : uint32_t { VersionOptions = 7 };+enum : uint32_t { VersionAnnotations = 0 };+enum : uint32_t { VersionSourceSubstitutions = 0 };++UserData::UserData()+ : m_preserveState( false )+{+}++UserData::UserData( const char* program, uint64_t time )+ : m_program( program )+ , m_time( time )+{+ if( m_program.empty() ) m_program = "_";++ FILE* f = OpenFile( FileDescription, false );+ if( f )+ {+ fseek( f, 0, SEEK_END );+ const auto sz = ftell( f );+ fseek( f, 0, SEEK_SET );+ auto buf = std::unique_ptr<char[]>( new char[sz] );+ fread( buf.get(), 1, sz, f );+ fclose( f );+ m_description.assign( buf.get(), buf.get() + sz );+ }+}++void UserData::Init( const char* program, uint64_t time )+{+ assert( !Valid() );+ m_program = program;+ m_time = time;++ if( m_program.empty() ) m_program = "_";+}++bool UserData::SetDescription( const char* description )+{+ assert( Valid() );++ m_description = description;+ const auto sz = m_description.size();++ FILE* f = OpenFile( FileDescription, true );+ if( !f ) return false;++ fwrite( description, 1, sz, f );+ fclose( f );+ return true;+}++void UserData::LoadState( ViewData& data )+{+ assert( Valid() );+ FILE* f = OpenFile( FileTimeline, false );+ if( f )+ {+ uint32_t ver;+ fread( &ver, 1, sizeof( ver ), f );+ if( ver == VersionTimeline )+ {+ fread( &data.zvStart, 1, sizeof( data.zvStart ), f );+ fread( &data.zvEnd, 1, sizeof( data.zvEnd ), f );+ //fread( &data.zvHeight, 1, sizeof( data.zvHeight ), f );+ fseek( f, sizeof( float ), SEEK_CUR );+ //fread( &data.zvScroll, 1, sizeof( data.zvScroll ), f );+ fseek( f, sizeof( float ), SEEK_CUR );+ fread( &data.frameScale, 1, sizeof( data.frameScale ), f );+ fread( &data.frameStart, 1, sizeof( data.frameStart ), f );+ }+ fclose( f );+ }++ f = OpenFile( FileOptions, false );+ if( f )+ {+ uint32_t ver;+ fread( &ver, 1, sizeof( ver ), f );+ // TODO: remove in future+ if( ver == VersionOptions )+ {+ fread( &data.drawGpuZones, 1, sizeof( data.drawGpuZones ), f );+ fread( &data.drawZones, 1, sizeof( data.drawZones ), f );+ fread( &data.drawLocks, 1, sizeof( data.drawLocks ), f );+ fread( &data.drawPlots, 1, sizeof( data.drawPlots ), f );+ fread( &data.onlyContendedLocks, 1, sizeof( data.onlyContendedLocks ), f );+ fread( &data.drawEmptyLabels, 1, sizeof( data.drawEmptyLabels ), f );+ fread( &data.drawFrameTargets, 1, sizeof( data.drawFrameTargets ), f );+ fread( &data.drawContextSwitches, 1, sizeof( data.drawContextSwitches ), f );+ fread( &data.darkenContextSwitches, 1, sizeof( data.darkenContextSwitches ), f );+ fread( &data.drawCpuData, 1, sizeof( data.drawCpuData ), f );+ fread( &data.drawCpuUsageGraph, 1, sizeof( data.drawCpuUsageGraph ), f );+ fread( &data.drawSamples, 1, sizeof( data.drawSamples ), f );+ fread( &data.dynamicColors, 1, sizeof( data.dynamicColors ), f );+ fread( &data.forceColors, 1, sizeof( data.forceColors ), f );+ fread( &data.ghostZones, 1, sizeof( data.ghostZones ), f );+ fread( &data.frameTarget, 1, sizeof( data.frameTarget ), f );+ fclose( f );+ }+ else+ {+ fclose( f );+ const auto path = GetSavePath( m_program.c_str(), m_time, FileOptions, false );+ assert( path );+ auto ini = ini_load( path );+ if( ini )+ {+ int v;+ if( ini_sget( ini, "options", "drawGpuZones", "%d", &v ) ) data.drawGpuZones = v;+ if( ini_sget( ini, "options", "drawZones", "%d", &v ) ) data.drawZones = v;+ if( ini_sget( ini, "options", "drawLocks", "%d", &v ) ) data.drawLocks = v;+ if( ini_sget( ini, "options", "drawPlots", "%d", &v ) ) data.drawPlots = v;+ if( ini_sget( ini, "options", "onlyContendedLocks", "%d", &v ) ) data.onlyContendedLocks = v;+ if( ini_sget( ini, "options", "drawEmptyLabels", "%d", &v ) ) data.drawEmptyLabels = v;+ if( ini_sget( ini, "options", "drawFrameTargets", "%d", &v ) ) data.drawFrameTargets = v;+ if( ini_sget( ini, "options", "drawContextSwitches", "%d", &v ) ) data.drawContextSwitches = v;+ if( ini_sget( ini, "options", "darkenContextSwitches", "%d", &v ) ) data.darkenContextSwitches = v;+ if( ini_sget( ini, "options", "drawCpuData", "%d", &v ) ) data.drawCpuData = v;+ if( ini_sget( ini, "options", "drawCpuUsageGraph", "%d", &v ) ) data.drawCpuUsageGraph = v;+ if( ini_sget( ini, "options", "drawSamples", "%d", &v ) ) data.drawSamples = v;+ if( ini_sget( ini, "options", "dynamicColors", "%d", &v ) ) data.dynamicColors = v;+ if( ini_sget( ini, "options", "inheritParentColors", "%d", &v ) ) data.inheritParentColors = v;+ if( ini_sget( ini, "options", "forceColors", "%d", &v ) ) data.forceColors = v;+ if( ini_sget( ini, "options", "ghostZones", "%d", &v ) ) data.ghostZones = v;+ if( ini_sget( ini, "options", "frameTarget", "%d", &v ) ) data.frameTarget = v;+ if( ini_sget( ini, "options", "shortenName", "%d", &v ) ) data.shortenName = (ShortenName)v;+ if( ini_sget( ini, "options", "plotHeight", "%d", &v ) ) data.plotHeight = v;+ ini_free( ini );+ }+ }+ }+}++void UserData::SaveState( const ViewData& data )+{+ if( !m_preserveState ) return;+ assert( Valid() );+ FILE* f = OpenFile( FileTimeline, true );+ if( f )+ {+ uint32_t ver = VersionTimeline;+ fwrite( &ver, 1, sizeof( ver ), f );+ fwrite( &data.zvStart, 1, sizeof( data.zvStart ), f );+ fwrite( &data.zvEnd, 1, sizeof( data.zvEnd ), f );+ //fwrite( &data.zvHeight, 1, sizeof( data.zvHeight ), f );+ float zero = 0;+ fwrite( &zero, 1, sizeof( zero ), f );+ //fwrite( &data.zvScroll, 1, sizeof( data.zvScroll ), f );+ fwrite( &zero, 1, sizeof( zero ), f );+ fwrite( &data.frameScale, 1, sizeof( data.frameScale ), f );+ fwrite( &data.frameStart, 1, sizeof( data.frameStart ), f );+ fclose( f );+ }++ f = OpenFile( FileOptions, true );+ if( f )+ {+ fprintf( f, "[options]\n" );+ fprintf( f, "drawGpuZones = %d\n", data.drawGpuZones );+ fprintf( f, "drawZones = %d\n", data.drawZones );+ fprintf( f, "drawLocks = %d\n", data.drawLocks );+ fprintf( f, "drawPlots = %d\n", data.drawPlots );+ fprintf( f, "onlyContendedLocks = %d\n", data.onlyContendedLocks );+ fprintf( f, "drawEmptyLabels = %d\n", data.drawEmptyLabels );+ fprintf( f, "drawFrameTargets = %d\n", data.drawFrameTargets );+ fprintf( f, "drawContextSwitches = %d\n", data.drawContextSwitches );+ fprintf( f, "darkenContextSwitches = %d\n", data.darkenContextSwitches );+ fprintf( f, "drawCpuData = %d\n", data.drawCpuData );+ fprintf( f, "drawCpuUsageGraph = %d\n", data.drawCpuUsageGraph );+ fprintf( f, "drawSamples = %d\n", data.drawSamples );+ fprintf( f, "dynamicColors = %d\n", data.dynamicColors );+ fprintf( f, "inheritParentColors = %d\n", data.inheritParentColors );+ fprintf( f, "forceColors = %d\n", data.forceColors );+ fprintf( f, "ghostZones = %d\n", data.ghostZones );+ fprintf( f, "frameTarget = %d\n", data.frameTarget );+ fprintf( f, "shortenName = %d\n", (int)data.shortenName );+ fprintf( f, "plotHeight = %d\n", data.plotHeight );+ fclose( f );+ }+}++void UserData::StateShouldBePreserved()+{+ m_preserveState = true;+}++void UserData::LoadAnnotations( std::vector<std::unique_ptr<Annotation>>& data )+{+ assert( Valid() );+ FILE* f = OpenFile( FileAnnotations, false );+ if( f )+ {+ uint32_t ver;+ fread( &ver, 1, sizeof( ver ), f );+ if( ver == VersionAnnotations )+ {+ uint32_t sz;+ fread( &sz, 1, sizeof( sz ), f );+ for( uint32_t i=0; i<sz; i++ )+ {+ auto ann = std::make_unique<Annotation>();++ uint32_t tsz;+ fread( &tsz, 1, sizeof( tsz ), f );+ if( tsz != 0 )+ {+ char buf[1024];+ assert( tsz < 1024 );+ fread( buf, 1, tsz, f );+ ann->text.assign( buf, tsz );+ }+ fread( &ann->range.min, 1, sizeof( ann->range.min ), f );+ fread( &ann->range.max, 1, sizeof( ann->range.max ), f );+ fread( &ann->color, 1, sizeof( ann->color ), f );+ ann->range.active = true;++ data.emplace_back( std::move( ann ) );+ }+ }+ fclose( f );+ }+}++void UserData::SaveAnnotations( const std::vector<std::unique_ptr<Annotation>>& data )+{+ if( !m_preserveState ) return;+ if( data.empty() )+ {+ Remove( FileAnnotations );+ return;+ }+ assert( Valid() );+ FILE* f = OpenFile( FileAnnotations, true );+ if( f )+ {+ uint32_t ver = VersionAnnotations;+ fwrite( &ver, 1, sizeof( ver ), f );+ uint32_t sz = uint32_t( data.size() );+ fwrite( &sz, 1, sizeof( sz ), f );+ for( auto& ann : data )+ {+ sz = uint32_t( ann->text.size() );+ fwrite( &sz, 1, sizeof( sz ), f );+ if( sz != 0 )+ {+ fwrite( ann->text.c_str(), 1, sz, f );+ }+ fwrite( &ann->range.min, 1, sizeof( ann->range.min ), f );+ fwrite( &ann->range.max, 1, sizeof( ann->range.max ), f );+ fwrite( &ann->color, 1, sizeof( ann->color ), f );+ }+ fclose( f );+ }+}++bool UserData::LoadSourceSubstitutions( std::vector<SourceRegex>& data )+{+ assert( Valid() );+ bool regexValid = true;+ FILE* f = OpenFile( FileSourceSubstitutions, false );+ if( f )+ {+ uint32_t ver;+ fread( &ver, 1, sizeof( ver ), f );+ if( ver == VersionSourceSubstitutions )+ {+ uint32_t sz;+ fread( &sz, 1, sizeof( sz ), f );+ for( uint32_t i=0; i<sz; i++ )+ {+ std::string pattern, target;+ uint32_t tsz;+ fread( &tsz, 1, sizeof( tsz ), f );+ if( tsz != 0 )+ {+ char buf[1024];+ assert( tsz < 1024 );+ fread( buf, 1, tsz, f );+ pattern.assign( buf, tsz );+ }+ fread( &tsz, 1, sizeof( tsz ), f );+ if( tsz != 0 )+ {+ char buf[1024];+ assert( tsz < 1024 );+ fread( buf, 1, tsz, f );+ target.assign( buf, tsz );+ }+ std::regex regex;+ try+ {+ regex.assign( pattern );+ }+ catch( std::regex_error& )+ {+ regexValid = false;+ }+ data.emplace_back( SourceRegex { std::move( pattern ), std::move( target ), std::move( regex ) } );+ }+ }+ fclose( f );+ }+ return regexValid;+}++void UserData::SaveSourceSubstitutions( const std::vector<SourceRegex>& data )+{+ if( !m_preserveState ) return;+ if( data.empty() )+ {+ Remove( FileSourceSubstitutions );+ return;+ }+ assert( Valid() );+ FILE* f = OpenFile( FileSourceSubstitutions, true );+ if( f )+ {+ uint32_t ver = VersionSourceSubstitutions;+ fwrite( &ver, 1, sizeof( ver ), f );+ uint32_t sz = uint32_t( data.size() );+ fwrite( &sz, 1, sizeof( sz ), f );+ for( auto& v : data )+ {+ sz = uint32_t( v.pattern.size() );+ fwrite( &sz, 1, sizeof( sz ), f );+ if( sz != 0 )+ {+ fwrite( v.pattern.c_str(), 1, sz, f );+ }+ sz = uint32_t( v.target.size() );+ fwrite( &sz, 1, sizeof( sz ), f );+ if( sz != 0 )+ {+ fwrite( v.target.c_str(), 1, sz, f );+ }+ }+ fclose( f );+ }+}+++FILE* UserData::OpenFile( const char* filename, bool write )+{+ const auto path = GetSavePath( m_program.c_str(), m_time, filename, write );+ if( !path ) return nullptr;+ FILE* f = fopen( path, write ? "wb" : "rb" );+ return f;+}++void UserData::Remove( const char* filename )+{+ const auto path = GetSavePath( m_program.c_str(), m_time, filename, false );+ if( !path ) return;+ unlink( path );+}++const char* UserData::GetConfigLocation() const+{+ assert( Valid() );+ return GetSavePath( m_program.c_str(), m_time, nullptr, false );+}++}
+ cbits/tracy/profiler/src/profiler/TracyUserData.hpp view
@@ -0,0 +1,55 @@+#ifndef __TRACYUSERDATA_HPP__+#define __TRACYUSERDATA_HPP__++#include <memory>+#include <stdint.h>+#include <stdio.h>+#include <string>+#include <vector>++namespace tracy+{++struct Annotation;+struct SourceRegex;+struct ViewData;++class UserData+{+public:+ UserData();+ UserData( const char* program, uint64_t time );++ bool Valid() const { return !m_program.empty(); }+ void Init( const char* program, uint64_t time );++ const std::string& GetDescription() const { return m_description; }+ bool SetDescription( const char* description );++ void LoadState( ViewData& data );+ void SaveState( const ViewData& data );+ void StateShouldBePreserved();++ void LoadAnnotations( std::vector<std::unique_ptr<Annotation>>& data );+ void SaveAnnotations( const std::vector<std::unique_ptr<Annotation>>& data );++ bool LoadSourceSubstitutions( std::vector<SourceRegex>& data );+ void SaveSourceSubstitutions( const std::vector<SourceRegex>& data );++ const char* GetConfigLocation() const;++private:+ FILE* OpenFile( const char* filename, bool write );+ void Remove( const char* filename );++ std::string m_program;+ uint64_t m_time;++ std::string m_description;++ bool m_preserveState;+};++}++#endif
+ cbits/tracy/profiler/src/profiler/TracyUtility.cpp view
@@ -0,0 +1,190 @@+#include <assert.h>++#include "TracyColor.hpp"+#include "TracyPrint.hpp"+#include "TracyUtility.hpp"+#include "TracyWorker.hpp"++namespace tracy+{++// Short list based on GetTypes() in TracySourceTokenizer.cpp+constexpr const char* TypesList[] = {+ "bool ", "char ", "double ", "float ", "int ", "long ", "short ",+ "signed ", "unsigned ", "void ", "wchar_t ", "size_t ", "int8_t ",+ "int16_t ", "int32_t ", "int64_t ", "intptr_t ", "uint8_t ", "uint16_t ",+ "uint32_t ", "uint64_t ", "ptrdiff_t ", nullptr+};++const char* ShortenZoneName( ShortenName type, const char* name, ImVec2& tsz, float zsz )+{+ assert( type != ShortenName::Never );+ if( name[0] == '<' || name[0] == '[' ) return name;+ if( type == ShortenName::Always ) zsz = 0;++ static char buf[64*1024];+ char tmp[64*1024];++ auto end = name + strlen( name );+ auto ptr = name;+ auto dst = tmp;+ int cnt = 0;+ for(;;)+ {+ auto start = ptr;+ while( ptr < end && *ptr != '<' ) ptr++;+ memcpy( dst, start, ptr - start + 1 );+ dst += ptr - start + 1;+ if( ptr == end ) break;+ cnt++;+ ptr++;+ while( cnt > 0 )+ {+ if( ptr == end ) break;+ if( *ptr == '<' ) cnt++;+ else if( *ptr == '>' ) cnt--;+ ptr++;+ }+ *dst++ = '>';+ }++ end = dst-1;+ ptr = tmp;+ dst = buf;+ cnt = 0;+ for(;;)+ {+ auto start = ptr;+ while( ptr < end && *ptr != '(' ) ptr++;+ memcpy( dst, start, ptr - start + 1 );+ dst += ptr - start + 1;+ if( ptr == end ) break;+ cnt++;+ ptr++;+ while( cnt > 0 )+ {+ if( ptr == end ) break;+ if( *ptr == '(' ) cnt++;+ else if( *ptr == ')' ) cnt--;+ ptr++;+ }+ *dst++ = ')';+ }++ end = dst-1;+ if( end - buf > 6 && memcmp( end-6, " const", 6 ) == 0 )+ {+ dst[-7] = '\0';+ end -= 6;+ }++ ptr = buf;+ for(;;)+ {+ auto match = TypesList;+ while( *match )+ {+ auto m = *match;+ auto p = ptr;+ while( *m )+ {+ if( *m != *p ) break;+ m++;+ p++;+ }+ if( !*m )+ {+ ptr = p;+ break;+ }+ match++;+ }+ if( !*match ) break;+ }++ tsz = ImGui::CalcTextSize( ptr, end );+ if( type == ShortenName::OnlyNormalize || tsz.x < zsz ) return ptr;++ for(;;)+ {+ auto p = ptr;+ while( p < end && *p != ':' ) p++;+ if( p == end ) return ptr;+ p++;+ while( p < end && *p == ':' ) p++;+ ptr = p;+ tsz = ImGui::CalcTextSize( ptr, end );+ if( tsz.x < zsz ) return ptr;+ }+}++void TooltipNormalizedName( const char* name, const char* normalized )+{+ if( ImGui::IsItemHovered() && normalized != name && strcmp( normalized, name ) != 0 )+ {+ const auto scale = ImGui::GetTextLineHeight() / 15.f;+ if( ImGui::CalcTextSize( name ).x > 1400 * scale )+ {+ ImGui::SetNextWindowSize( ImVec2( 1400 * scale, 0 ) );+ ImGui::BeginTooltip();+ ImGui::TextWrapped( "%s", name );+ }+ else+ {+ ImGui::BeginTooltip();+ ImGui::TextUnformatted( name );+ }+ ImGui::EndTooltip();+ }+}++uint32_t GetThreadColor( uint64_t thread, int depth, bool dynamic )+{+ if( !dynamic ) return 0xFFCC5555;+ return GetHsvColor( thread, depth );+}++uint32_t GetPlotColor( const PlotData& plot, const Worker& worker )+{+ switch( plot.type )+ {+ case PlotType::User:+ if( plot.color != 0 ) return plot.color | 0xFF000000;+ return GetHsvColor( charutil::hash( worker.GetString( plot.name ) ), -10 );+ case PlotType::Memory:+ return 0xFF2266CC;+ case PlotType::SysTime:+ return 0xFFBAB220;+ case PlotType::Power:+ return 0xFF33CC33;+ default:+ assert( false );+ return 0;+ }+}++const char* FormatPlotValue( double val, PlotValueFormatting format )+{+ static char buf[64];+ switch( format )+ {+ case PlotValueFormatting::Number:+ return RealToString( val );+ break;+ case PlotValueFormatting::Memory:+ return MemSizeToString( val );+ break;+ case PlotValueFormatting::Percentage:+ sprintf( buf, "%.2f%%", val );+ break;+ case PlotValueFormatting::Watt:+ sprintf( buf, "%s W", RealToString( val ) );+ break;+ default:+ assert( false );+ break;+ }+ return buf;+}++}
+ cbits/tracy/profiler/src/profiler/TracyUtility.hpp view
@@ -0,0 +1,34 @@+#ifndef __TRACYUTILITY_HPP__+#define __TRACYUTILITY_HPP__++#include <stdint.h>++#include "imgui.h"+#include "../server/TracyEvent.hpp"++namespace tracy+{++class Worker;++enum class ShortenName : uint8_t+{+ Never,+ Always,+ OnlyNormalize,+ NoSpace,+ NoSpaceAndNormalize,+};++const char* ShortenZoneName( ShortenName type, const char* name, ImVec2& tsz, float zsz );+void TooltipNormalizedName( const char* name, const char* normalized );++static inline const char* ShortenZoneName( ShortenName type, const char* name ) { ImVec2 tsz = {}; return ShortenZoneName( type, name, tsz, 0 ); }++uint32_t GetThreadColor( uint64_t thread, int depth, bool dynamic );+uint32_t GetPlotColor( const PlotData& plot, const Worker& worker );+const char* FormatPlotValue( double val, PlotValueFormatting format );++}++#endif
+ cbits/tracy/profiler/src/profiler/TracyView.cpp view
@@ -0,0 +1,1465 @@+#ifdef _MSC_VER+# pragma warning( disable: 4267 ) // conversion from don't care to whatever, possible loss of data+#endif++#ifdef __MINGW32__+# define __STDC_FORMAT_MACROS+#endif+#include <algorithm>+#include <assert.h>+#include <inttypes.h>+#include <math.h>+#include <mutex>++#include "imgui.h"++#include "TracyFileRead.hpp"+#include "TracyFilesystem.hpp"+#include "TracyImGui.hpp"+#include "TracyPrint.hpp"+#include "TracySourceView.hpp"+#include "TracyTexture.hpp"+#include "TracyView.hpp"+#include "../server/TracySysUtil.hpp"+#include "../public/common/TracyStackFrames.hpp"++#include "imgui_internal.h"+#include "IconsFontAwesome6.h"++#ifndef M_PI_2+#define M_PI_2 1.57079632679489661923+#endif++namespace tracy+{++double s_time = 0;++View::View( void(*cbMainThread)(const std::function<void()>&, bool), const char* addr, uint16_t port, ImFont* fixedWidth, ImFont* smallFont, ImFont* bigFont, SetTitleCallback stcb, SetScaleCallback sscb, AttentionCallback acb, const Config& config, AchievementsMgr* amgr )+ : m_worker( addr, port, config.memoryLimit == 0 ? -1 : ( config.memoryLimitPercent * tracy::GetPhysicalMemorySize() / 100 ) )+ , m_staticView( false )+ , m_viewMode( ViewMode::LastFrames )+ , m_viewModeHeuristicTry( true )+ , m_totalMemory( GetPhysicalMemorySize() )+ , m_forceConnectionPopup( true, true )+ , m_tc( *this, m_worker, config.threadedRendering )+ , m_frames( nullptr )+ , m_messagesScrollBottom( true )+ , m_reactToCrash( true )+ , m_reactToLostConnection( true )+ , m_smallFont( smallFont )+ , m_bigFont( bigFont )+ , m_fixedFont( fixedWidth )+ , m_stcb( stcb )+ , m_sscb( sscb )+ , m_acb( acb )+ , m_cbMainThread( cbMainThread )+ , m_achievementsMgr( amgr )+ , m_achievements( config.achievements )+ , m_horizontalScrollMultiplier( config.horizontalScrollMultiplier )+ , m_verticalScrollMultiplier( config.verticalScrollMultiplier )+#ifdef __EMSCRIPTEN__+ , m_td( 2, "ViewMt" )+#else+ , m_td( std::thread::hardware_concurrency(), "ViewMt" )+#endif+{+ InitTextEditor();+ SetupConfig( config );+}++View::View( void(*cbMainThread)(const std::function<void()>&, bool), FileRead& f, ImFont* fixedWidth, ImFont* smallFont, ImFont* bigFont, SetTitleCallback stcb, SetScaleCallback sscb, AttentionCallback acb, const Config& config, AchievementsMgr* amgr )+ : m_worker( f )+ , m_filename( f.GetFilename() )+ , m_staticView( true )+ , m_viewMode( ViewMode::Paused )+ , m_totalMemory( GetPhysicalMemorySize() )+ , m_tc( *this, m_worker, config.threadedRendering )+ , m_frames( m_worker.GetFramesBase() )+ , m_messagesScrollBottom( false )+ , m_smallFont( smallFont )+ , m_bigFont( bigFont )+ , m_fixedFont( fixedWidth )+ , m_stcb( stcb )+ , m_sscb( sscb )+ , m_acb( acb )+ , m_userData( m_worker.GetCaptureProgram().c_str(), m_worker.GetCaptureTime() )+ , m_cbMainThread( cbMainThread )+ , m_achievementsMgr( amgr )+ , m_achievements( config.achievements )+ , m_horizontalScrollMultiplier( config.horizontalScrollMultiplier )+ , m_verticalScrollMultiplier( config.verticalScrollMultiplier )+#ifdef __EMSCRIPTEN__+ , m_td( 2, "ViewMt" )+#else+ , m_td( std::thread::hardware_concurrency(), "ViewMt" )+#endif+{+ m_notificationTime = 4;+ m_notificationText = std::string( "Trace loaded in " ) + TimeToString( m_worker.GetLoadTime() );++ InitTextEditor();+ SetupConfig( config );++ m_vd.zvStart = m_worker.GetFirstTime();+ m_vd.zvEnd = m_worker.GetLastTime();+ m_userData.StateShouldBePreserved();+ m_userData.LoadState( m_vd );+ m_userData.LoadAnnotations( m_annotations );+ m_sourceRegexValid = m_userData.LoadSourceSubstitutions( m_sourceSubstitutions );++ if( m_worker.GetCallstackFrameCount() == 0 ) m_showUnknownFrames = false;+ if( m_worker.GetCallstackSampleCount() == 0 ) m_showAllSymbols = true;++ Achieve( "loadTrace" );+}++View::~View()+{+ m_worker.Shutdown();++ m_userData.SaveState( m_vd );+ m_userData.SaveAnnotations( m_annotations );+ m_userData.SaveSourceSubstitutions( m_sourceSubstitutions );++ if( m_compare.loadThread.joinable() ) m_compare.loadThread.join();+ if( m_saveThread.joinable() ) m_saveThread.join();++ if( m_frameTexture ) FreeTexture( m_frameTexture, m_cbMainThread );+ if( m_playback.texture ) FreeTexture( m_playback.texture, m_cbMainThread );+}++void View::InitTextEditor()+{+ m_sourceView = std::make_unique<SourceView>();+ m_sourceViewFile = nullptr;+}++void View::SetupConfig( const Config& config )+{+ m_vd.frameTarget = config.targetFps;+ m_vd.dynamicColors = config.dynamicColors;+ m_vd.forceColors = config.forceColors;+ m_vd.shortenName = (ShortenName)config.shortenName;+}++void View::Achieve( const char* id )+{+ if( !m_achievements || !m_achievementsMgr ) return;+ m_achievementsMgr->Achieve( id );+}++void View::ViewSource( const char* fileName, int line )+{+ assert( fileName );+ m_sourceViewFile = fileName;+ m_sourceView->OpenSource( fileName, line, *this, m_worker );+}++void View::ViewSource( const char* fileName, int line, const char* functionName )+{+ assert( functionName );++ uint64_t addr = 0;+ uint64_t base = 0;+ const auto fnsz = strlen( functionName );+ auto& symMap = m_worker.GetSymbolMap();+ for( auto& sym : symMap )+ {+ const auto name = m_worker.GetString( sym.second.name );+ const auto ptr = strstr( name, functionName );+ if( ptr &&+ ( ptr[fnsz] == 0 || ptr[fnsz] == '(' || ptr[fnsz] == '<' ) &&+ ( ptr == name || ( ptr[-1] == ' ' || ptr[-1] == ':' ) ) )+ {+ if( addr != 0 )+ {+ // Ambiguous function name. Bail out.+ ViewSource( fileName, line );+ return;+ }+ else+ {+ addr = sym.first;+ if( sym.second.isInline )+ {+ base = m_worker.GetSymbolForAddress( addr );+ if( base == 0 )+ {+ addr = 0;+ }+ }+ else+ {+ base = addr;+ }+ }+ }+ }+ if( addr != 0 && base != 0 )+ {+ ViewSymbol( fileName, line, base, addr );+ }+ else+ {+ ViewSource( fileName, line );+ }+}++void View::ViewSourceCheckKeyMod( const char* fileName, int line, const char* functionName )+{+ if( ImGui::GetIO().KeyCtrl )+ {+ ViewSource( fileName, line );+ }+ else+ {+ ViewSource( fileName, line, functionName );+ }+}++void View::ViewSymbol( const char* fileName, int line, uint64_t baseAddr, uint64_t symAddr )+{+ assert( fileName || symAddr );+ m_sourceViewFile = fileName ? fileName : (const char*)~uint64_t( 0 );+ m_sourceView->OpenSymbol( fileName, line, baseAddr, symAddr, m_worker, *this );+}++bool View::ViewDispatch( const char* fileName, int line, uint64_t symAddr )+{+ if( line == 0 )+ {+ fileName = nullptr;+ }+ else+ {+ if( !SourceFileValid( fileName, m_worker.GetCaptureTime(), *this, m_worker ) )+ {+ fileName = nullptr;+ line = 0;+ }+ }+ if( symAddr == 0 )+ {+ if( line != 0 )+ {+ ViewSource( fileName, line );+ return true;+ }+ return false;+ }+ else+ {+ uint64_t baseAddr = 0;+ if( m_worker.HasSymbolCode( symAddr ) )+ {+ baseAddr = symAddr;+ }+ else+ {+ const auto parentAddr = m_worker.GetSymbolForAddress( symAddr );+ if( parentAddr != 0 && m_worker.HasSymbolCode( parentAddr ) )+ {+ baseAddr = parentAddr;+ }+ }+ if( baseAddr != 0 || line != 0 )+ {+ ViewSymbol( fileName, line, baseAddr, symAddr );+ return true;+ }+ return false;+ }+}++static const char* CompressionName[] = {+ "LZ4",+ "LZ4 HC",+ "LZ4 HC extreme",+ "Zstd",+ nullptr+};++static const char* CompressionDesc[] = {+ "Fastest save, fast load time, big file size",+ "Slow save, fastest load time, reasonable file size",+ "Very slow save, fastest load time, file smaller than LZ4 HC",+ "Configurable save time (fast-slowest), reasonable load time, smallest file size",+ nullptr+};++static_assert( sizeof( CompressionName ) == sizeof( CompressionDesc ), "Unmatched compression names and descriptions" );+++bool View::Draw()+{+ HandshakeStatus status = (HandshakeStatus)m_worker.GetHandshakeStatus();+ switch( status )+ {+ case HandshakeProtocolMismatch:+ Attention( m_attnProtoMismatch );+ ImGui::OpenPopup( "Protocol mismatch" );+ break;+ case HandshakeNotAvailable:+ Attention( m_attnNotAvailable );+ ImGui::OpenPopup( "Client not ready" );+ break;+ case HandshakeDropped:+ Attention( m_attnDropped );+ ImGui::OpenPopup( "Client disconnected" );+ break;+ default:+ break;+ }++ const auto& failure = m_worker.GetFailureType();+ if( failure != Worker::Failure::None )+ {+ Attention( m_attnFailure );+ ImGui::OpenPopup( "Instrumentation failure" );+ }++ if( ImGui::BeginPopupModal( "Protocol mismatch", nullptr, ImGuiWindowFlags_AlwaysAutoResize ) )+ {+ ImGui::PushFont( m_bigFont );+ TextCentered( ICON_FA_TRIANGLE_EXCLAMATION );+ ImGui::PopFont();+ ImGui::TextUnformatted( "The client you are trying to connect to uses incompatible protocol version.\nMake sure you are using the same Tracy version on both client and server." );+ ImGui::Separator();+ if( ImGui::Button( "My bad" ) )+ {+ ImGui::CloseCurrentPopup();+ ImGui::EndPopup();+ m_attnProtoMismatch = false;+ return false;+ }+ ImGui::SameLine();+ if( ImGui::Button( "Reconnect" ) )+ {+ ImGui::CloseCurrentPopup();+ ImGui::EndPopup();+ m_reconnectRequested = true;+ m_attnProtoMismatch = false;+ return false;+ }+ ImGui::EndPopup();+ }++ if( ImGui::BeginPopupModal( "Client not ready", nullptr, ImGuiWindowFlags_AlwaysAutoResize ) )+ {+ ImGui::PushFont( m_bigFont );+ TextCentered( ICON_FA_LIGHTBULB );+ ImGui::PopFont();+ ImGui::TextUnformatted( "The client you are trying to connect to is no longer able to sent profiling data,\nbecause another server was already connected to it.\nYou can do the following:\n\n 1. Restart the client application.\n 2. Rebuild the client application with on-demand mode enabled." );+ ImGui::Separator();+ if( ImGui::Button( "I understand" ) )+ {+ ImGui::CloseCurrentPopup();+ ImGui::EndPopup();+ m_attnNotAvailable = false;+ return false;+ }+ ImGui::SameLine();+ if( ImGui::Button( "Reconnect" ) )+ {+ ImGui::CloseCurrentPopup();+ ImGui::EndPopup();+ m_reconnectRequested = true;+ m_attnNotAvailable = false;+ return false;+ }+ ImGui::EndPopup();+ }++ if( ImGui::BeginPopupModal( "Client disconnected", nullptr, ImGuiWindowFlags_AlwaysAutoResize ) )+ {+ ImGui::PushFont( m_bigFont );+ TextCentered( ICON_FA_HANDSHAKE );+ ImGui::PopFont();+ ImGui::TextUnformatted( "The client you are trying to connect to has disconnected during the initial\nconnection handshake. Please check your network configuration." );+ ImGui::Separator();+ if( ImGui::Button( "Will do" ) )+ {+ ImGui::CloseCurrentPopup();+ ImGui::EndPopup();+ m_attnDropped = false;+ return false;+ }+ ImGui::SameLine();+ if( ImGui::Button( "Reconnect" ) )+ {+ ImGui::CloseCurrentPopup();+ ImGui::EndPopup();+ m_reconnectRequested = true;+ m_attnDropped = false;+ return false;+ }+ ImGui::EndPopup();+ }++ if( ImGui::BeginPopupModal( "Instrumentation failure", nullptr, ImGuiWindowFlags_AlwaysAutoResize ) )+ {+ const auto& data = m_worker.GetFailureData();+ ImGui::PushFont( m_bigFont );+ TextCentered( ICON_FA_SKULL );+ ImGui::PopFont();+ ImGui::TextUnformatted( "Profiling session terminated due to improper instrumentation.\nPlease correct your program and try again." );+ ImGui::TextUnformatted( "Reason:" );+ ImGui::SameLine();+ ImGui::TextUnformatted( Worker::GetFailureString( failure ) );+ ImGui::Separator();+ if( data.srcloc != 0 )+ {+ const auto& srcloc = m_worker.GetSourceLocation( data.srcloc );+ if( srcloc.name.active )+ {+ TextFocused( "Zone name:", m_worker.GetString( srcloc.name ) );+ }+ TextFocused( "Function:", m_worker.GetString( srcloc.function ) );+ TextDisabledUnformatted( "Location:" );+ ImGui::SameLine();+ ImGui::TextUnformatted( LocationToString( m_worker.GetString( srcloc.file ), srcloc.line ) );+ }+ if( data.thread != 0 )+ {+ TextFocused( "Thread:", m_worker.GetThreadName( data.thread ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( data.thread ) );+ if( m_worker.IsThreadFiber( data.thread ) )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 0.2f, 0.6f, 0.2f, 1.f ), "Fiber" );+ }+ }+ if( !data.message.empty() )+ {+ TextFocused( "Context:", data.message.c_str() );+ }+ if( data.callstack != 0 )+ {+ if( ImGui::TreeNode( "Call stack" ) )+ {+ ImGui::BeginChild( "##callstackFailure", ImVec2( 1200, 500 ) );+ if( ImGui::BeginTable( "##callstack", 4, ImGuiTableFlags_Resizable | ImGuiTableFlags_Borders ) )+ {+ ImGui::TableSetupColumn( "Frame", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize );+ ImGui::TableSetupColumn( "Function" );+ ImGui::TableSetupColumn( "Location" );+ ImGui::TableSetupColumn( "Image" );+ ImGui::TableHeadersRow();++ auto& cs = m_worker.GetCallstack( data.callstack );+ int fidx = 0;+ for( auto& entry : cs )+ {+ auto frameData = m_worker.GetCallstackFrame( entry );+ if( !frameData )+ {+ ImGui::TableNextRow();+ ImGui::TableNextColumn();+ ImGui::Text( "%i", fidx++ );+ ImGui::TableNextColumn();+ char buf[32];+ sprintf( buf, "%p", (void*)m_worker.GetCanonicalPointer( entry ) );+ ImGui::TextUnformatted( buf );+ if( ImGui::IsItemHovered() )+ {+ ImGui::BeginTooltip();+ ImGui::TextUnformatted( "Click on entry to copy it to clipboard." );+ ImGui::EndTooltip();+ if( ImGui::IsItemClicked() )+ {+ ImGui::SetClipboardText( buf );+ }+ }+ }+ else+ {+ const auto fsz = frameData->size;+ for( uint8_t f=0; f<fsz; f++ )+ {+ const auto& frame = frameData->data[f];+ auto txt = m_worker.GetString( frame.name );++ if( fidx == 0 && f != fsz-1 )+ {+ auto test = s_tracyStackFrames;+ bool match = false;+ do+ {+ if( strcmp( txt, *test ) == 0 )+ {+ match = true;+ break;+ }+ }+ while( *++test );+ if( match ) continue;+ }++ ImGui::TableNextRow();+ ImGui::TableNextColumn();+ if( f == fsz-1 )+ {+ ImGui::Text( "%i", fidx++ );+ }+ else+ {+ TextDisabledUnformatted( "inline" );+ }+ ImGui::TableNextColumn();+ {+ ImGui::PushTextWrapPos( 0.0f );+ if( txt[0] == '[' )+ {+ TextDisabledUnformatted( txt );+ }+ else+ {+ ImGui::TextUnformatted( txt );+ }+ ImGui::PopTextWrapPos();+ }+ if( ImGui::IsItemHovered() )+ {+ ImGui::BeginTooltip();+ ImGui::TextUnformatted( "Click on entry to copy it to clipboard." );+ ImGui::EndTooltip();+ if( ImGui::IsItemClicked() )+ {+ ImGui::SetClipboardText( txt );+ }+ }+ ImGui::TableNextColumn();+ ImGui::PushTextWrapPos( 0.0f );+ txt = m_worker.GetString( frame.file );+ TextDisabledUnformatted( LocationToString( txt, frame.line ) );+ if( ImGui::IsItemHovered() )+ {+ ImGui::BeginTooltip();+ ImGui::TextUnformatted( "Click on entry to copy it to clipboard." );+ ImGui::EndTooltip();+ if( ImGui::IsItemClicked() )+ {+ ImGui::SetClipboardText( txt );+ }+ }+ ImGui::PopTextWrapPos();+ ImGui::TableNextColumn();+ if( frameData->imageName.Active() )+ {+ TextDisabledUnformatted( m_worker.GetString( frameData->imageName ) );+ }+ }+ }+ }+ ImGui::EndTable();+ }+ ImGui::EndChild();+ ImGui::TreePop();+ }+ }+ ImGui::Separator();+ if( ImGui::Button( "I understand" ) )+ {+ ImGui::CloseCurrentPopup();+ m_worker.ClearFailure();+ m_attnFailure = false;+ }+ ImGui::EndPopup();+ }++ static FileCompression comp = FileCompression::Zstd;+ static int zlvl = 3;+ static bool buildDict = false;+ static int streams = 4;++ bool saveFailed = false;+ if( !m_filenameStaging.empty() )+ {+ ImGui::OpenPopup( "Save trace" );+ }+ if( ImGui::BeginPopupModal( "Save trace", nullptr, ImGuiWindowFlags_AlwaysAutoResize ) )+ {+ assert( !m_filenameStaging.empty() );+ auto fn = m_filenameStaging.c_str();+ ImGui::PushFont( m_bigFont );+ TextFocused( "Path:", fn );+ ImGui::PopFont();+ ImGui::Separator();++ if( ImGui::TreeNode( ICON_FA_FILE_ZIPPER " Trace compression" ) )+ {+ TextDisabledUnformatted( "Can be changed later with the upgrade utility" );+ ImGui::Indent();+ int idx = 0;+ while( CompressionName[idx] )+ {+ if( ImGui::RadioButton( CompressionName[idx], (int)comp == idx ) ) comp = (FileCompression)idx;+ ImGui::SameLine();+ TextDisabledUnformatted( CompressionDesc[idx] );+ idx++;+ }+ ImGui::Unindent();+ ImGui::TextUnformatted( "Zstd level" );+ ImGui::SameLine();+ TextDisabledUnformatted( "Increasing level decreases file size, but increases save and load times" );+ ImGui::Indent();+ if( ImGui::SliderInt( "##zstd", &zlvl, 1, 22, "%d", ImGuiSliderFlags_AlwaysClamp ) )+ {+ comp = FileCompression::Zstd;+ }+ ImGui::Unindent();++ ImGui::TextUnformatted( ICON_FA_SHUFFLE " Compression streams" );+ ImGui::SameLine();+ TextDisabledUnformatted( "Parallelize save and load at the cost of file size" );+ ImGui::Indent();+ ImGui::SliderInt( "##streams", &streams, 1, 64, "%d", ImGuiSliderFlags_AlwaysClamp );+ ImGui::Unindent();++ if( m_worker.GetFrameImageCount() != 0 )+ {+ ImGui::Separator();+ ImGui::Checkbox( "Build frame images dictionary", &buildDict );+ ImGui::SameLine();+ TextDisabledUnformatted( "Decreases run-time memory requirements" );+ }+ ImGui::TreePop();+ }++ ImGui::Separator();+ if( ImGui::Button( ICON_FA_FLOPPY_DISK " Save trace" ) )+ {+ saveFailed = !Save( fn, comp, zlvl, buildDict, streams );+ m_filenameStaging.clear();+ ImGui::CloseCurrentPopup();+ Achieve( "saveTrace" );+ }+ ImGui::SameLine();+ if( ImGui::Button( "Cancel" ) )+ {+ m_filenameStaging.clear();+ ImGui::CloseCurrentPopup();+ }+ ImGui::EndPopup();+ }++ if( saveFailed ) ImGui::OpenPopup( "Save failed" );+ if( ImGui::BeginPopupModal( "Save failed", nullptr, ImGuiWindowFlags_AlwaysAutoResize ) )+ {+ ImGui::PushFont( m_bigFont );+ TextCentered( ICON_FA_TRIANGLE_EXCLAMATION );+ ImGui::PopFont();+ ImGui::TextUnformatted( "Could not save trace at the specified location. Try again somewhere else." );+ ImGui::Separator();+ if( ImGui::Button( "Oh well" ) ) ImGui::CloseCurrentPopup();+ ImGui::EndPopup();+ }++ if( !m_staticView &&+ ( ImGui::IsKeyDown( ImGuiKey_LeftCtrl ) || ImGui::IsKeyDown( ImGuiKey_RightCtrl ) ) &&+ ( ImGui::IsKeyDown( ImGuiKey_LeftShift ) || ImGui::IsKeyDown( ImGuiKey_RightShift ) ) &&+ ( ImGui::IsKeyDown( ImGuiKey_LeftAlt ) || ImGui::IsKeyDown( ImGuiKey_RightAlt ) ) &&+ ImGui::IsKeyPressed( ImGuiKey_R ) )+ {+ m_reconnectRequested = true;+ return false;+ }++ s_time += ImGui::GetIO().DeltaTime;+ return DrawImpl();+}++static const char* MainWindowButtons[] = {+ ICON_FA_PLAY " Resume",+ ICON_FA_PAUSE " Pause",+ ICON_FA_SQUARE " Stopped"+};++enum { MainWindowButtonsCount = sizeof( MainWindowButtons ) / sizeof( *MainWindowButtons ) };++bool View::DrawImpl()+{+ if( !m_worker.HasData() )+ {+ bool keepOpen = true;+ char tmp[2048];+ sprintf( tmp, "%s###Connection", m_worker.GetAddr().c_str() );+ ImGui::Begin( tmp, &keepOpen, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse );+ ImGui::PushFont( m_bigFont );+ TextCentered( ICON_FA_WIFI );+ ImGui::PopFont();+ ImGui::TextUnformatted( "Waiting for connection..." );+ DrawWaitingDots( s_time );+ ImGui::End();+ return keepOpen;+ }++ if( m_achievements )+ {+ if( m_worker.IsConnected() ) Achieve( "connectToClient" );+ if( m_worker.GetZoneCount() > 0 ) Achieve( "instrumentationIntro" );+ if( m_worker.GetZoneCount() > 100 * 1000 * 1000 ) Achieve( "100million" );+ if( m_worker.GetCallstackSampleCount() > 0 ) Achieve( "samplingIntro" );+ if( m_worker.AreFramesUsed() ) Achieve( "instrumentFrames" );+ }++ Attention( m_attnWorking );++ if( !m_uarchSet )+ {+ m_uarchSet = true;+ m_sourceView->SetCpuId( m_worker.GetCpuId() );+ }+ if( !m_userData.Valid() ) m_userData.Init( m_worker.GetCaptureProgram().c_str(), m_worker.GetCaptureTime() );+ if( m_saveThreadState.load( std::memory_order_acquire ) == SaveThreadState::NeedsJoin )+ {+ m_saveThread.join();+ m_saveThreadState.store( SaveThreadState::Inert, std::memory_order_release );+ const auto src = m_srcFileBytes.load( std::memory_order_relaxed );+ const auto dst = m_dstFileBytes.load( std::memory_order_relaxed );+ m_notificationTime = 4;+ char buf[1024];+ sprintf( buf, "Trace size %s (%.2f%% ratio)", MemSizeToString( dst ), 100.f * dst / src );+ m_notificationText = buf;+ m_acb();+ }++ auto& threadHints = m_worker.GetPendingThreadHints();+ if( !threadHints.empty() )+ {+ m_threadReinsert.reserve( threadHints.size() );+ for( auto v : threadHints )+ {+ auto it = std::find_if( m_threadOrder.begin(), m_threadOrder.end(), [v]( const auto& t ) { return t->id == v; } );+ if( it != m_threadOrder.end() )+ {+ // Will be reinserted in the correct place later.+ // A separate list is kept of threads that were already known to avoid having to figure out which one is missing in m_threadOrder.+ m_threadReinsert.push_back( *it );+ m_threadOrder.erase( it );+ }+ }+ m_worker.ClearPendingThreadHints();+ }++ const auto& io = ImGui::GetIO();+ m_wasActive = false;++ assert( m_shortcut == ShortcutAction::None );+ if( io.KeyCtrl )+ {+ if( ImGui::IsKeyPressed( ImGuiKey_F ) )+ {+ m_findZone.show = true;+ m_shortcut = ShortcutAction::OpenFind;+ }+ }++ if( !m_frames ) m_frames = m_worker.GetFramesBase();++ const auto th = ImGui::GetTextLineHeight();+ float bw = 0;+ for( int i=0; i<MainWindowButtonsCount; i++ )+ {+ bw = std::max( bw, ImGui::CalcTextSize( MainWindowButtons[i] ).x );+ }+ bw += th;++ bool keepOpen = true;+ bool* keepOpenPtr = nullptr;+ (void)keepOpenPtr;+ if( m_staticView )+ {+ keepOpenPtr = &keepOpen;+ }++#ifndef TRACY_NO_ROOT_WINDOW+ if( !m_titleSet && m_stcb )+ {+ m_titleSet = true;+ UpdateTitle();+ }++ ImGuiViewport* viewport = ImGui::GetMainViewport();+ {+ auto& style = ImGui::GetStyle();+ const auto wrPrev = style.WindowRounding;+ const auto wbsPrev = style.WindowBorderSize;+ const auto wpPrev = style.WindowPadding;+ style.WindowRounding = 0.f;+ style.WindowBorderSize = 0.f;+ style.WindowPadding = ImVec2( 4.f, 4.f );+ style.Colors[ImGuiCol_WindowBg] = ImVec4( 0.129f, 0.137f, 0.11f, 1.f );++ ImGui::SetNextWindowPos( viewport->Pos );+ ImGui::SetNextWindowSize( ImVec2( m_rootWidth, m_rootHeight ) );+ ImGui::SetNextWindowViewport( viewport->ID );+ ImGui::Begin( "Timeline view###Profiler", nullptr, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoNavFocus );++ style.WindowRounding = wrPrev;+ style.WindowBorderSize = wbsPrev;+ style.WindowPadding = wpPrev;+ style.Colors[ImGuiCol_WindowBg] = ImVec4( 0.11f, 0.11f, 0.08f, 1.f );+ }+#else+ char tmp[2048];+ sprintf( tmp, "%s###Profiler", m_worker.GetCaptureName().c_str() );+ ImGui::SetNextWindowSize( ImVec2( 1550, 800 ), ImGuiCond_FirstUseEver );+ ImGui::Begin( tmp, keepOpenPtr, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoBringToFrontOnFocus );+ ImGuiViewport* viewport = ImGui::GetMainViewport();+#endif++ if( !m_staticView )+ {+ if( ImGui::Button( ICON_FA_WIFI ) || m_forceConnectionPopup )+ {+ if( m_forceConnectionPopup )+ {+ m_forceConnectionPopup.Decay( false );+ ImGui::SetNextWindowPos( viewport->Pos + ImGui::GetCursorPos() );+ }+ ImGui::OpenPopup( "TracyConnectionPopup" );+ }+ ImGui::SameLine();+ if( ImGui::BeginPopup( "TracyConnectionPopup" ) )+ {+ const bool wasDisconnectIssued = m_disconnectIssued;+ const bool discardData = !DrawConnection();+ const bool disconnectIssuedJustNow = m_disconnectIssued != wasDisconnectIssued;+ if( discardData ) keepOpen = false;+ if( disconnectIssuedJustNow || discardData ) ImGui::CloseCurrentPopup();+ ImGui::EndPopup();+ }+ }+ std::lock_guard<std::mutex> lock( m_worker.GetDataLock() );+ m_worker.DoPostponedWork();+ if( !m_worker.IsDataStatic() )+ {+ if( m_worker.IsConnected() )+ {+ if( ImGui::Button( m_viewMode == ViewMode::Paused ? MainWindowButtons[0] : MainWindowButtons[1], ImVec2( bw, 0 ) ) )+ {+ if( m_viewMode != ViewMode::Paused )+ {+ m_viewMode = ViewMode::Paused;+ m_viewModeHeuristicTry = false;+ }+ else+ {+ ImGui::OpenPopup( "viewMode" );+ }+ }+ }+ else+ {+ Attention( m_attnDisconnected );+ ImGui::BeginDisabled();+ ImGui::ButtonEx( MainWindowButtons[2], ImVec2( bw, 0 ) );+ ImGui::EndDisabled();+ }+ if( ImGui::BeginPopup( "viewMode" ) )+ {+ if( ImGui::Selectable( ICON_FA_MAGNIFYING_GLASS_PLUS " Newest three frames" ) )+ {+ m_viewMode = ViewMode::LastFrames;+ }+ if( ImGui::Selectable( ICON_FA_RULER_HORIZONTAL " Use current zoom level" ) )+ {+ m_viewMode = ViewMode::LastRange;+ }+ ImGui::EndPopup();+ }+ else if( m_viewModeHeuristicTry )+ {+ const auto lastTime = m_worker.GetLastTime() - m_worker.GetFirstTime();+ if( lastTime > 5*1000*1000*1000ll )+ {+ if( m_viewMode == ViewMode::LastFrames && m_worker.GetFrameCount( *m_worker.GetFramesBase() ) <= ( m_worker.IsOnDemand() ? 3 : 2 ) )+ {+ m_viewMode = ViewMode::LastRange;+ ZoomToRange( lastTime - 5*1000*1000*1000ll, lastTime, false );+ }+ else+ {+ m_viewModeHeuristicTry = false;+ }+ }+ }+ }+ else+ {+ ImGui::PushStyleColor( ImGuiCol_Button, (ImVec4)ImColor::HSV( 0.f, 0.6f, 0.6f) );+ ImGui::PushStyleColor( ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV( 0.f, 0.7f, 0.7f) );+ ImGui::PushStyleColor( ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV( 0.f, 0.8f, 0.8f) );+ if( ImGui::Button( ICON_FA_POWER_OFF ) ) keepOpen = false;+ ImGui::PopStyleColor( 3 );+ }+ ImGui::SameLine();+ ToggleButton( ICON_FA_GEAR, m_showOptions );+ ImGui::SameLine();+ ToggleButton( ICON_FA_TAGS " Messages", m_showMessages );+ ImGui::SameLine();+ ToggleButton( ICON_FA_MAGNIFYING_GLASS " Find", m_findZone.show );+ ImGui::SameLine();+ ToggleButton( ICON_FA_ARROW_UP_WIDE_SHORT " Statistics", m_showStatistics );+ ImGui::SameLine();+ ToggleButton( ICON_FA_FIRE_FLAME_CURVED " Flame", m_showFlameGraph );+ ImGui::SameLine();+ ToggleButton( ICON_FA_MEMORY " Memory", m_memInfo.show );+ ImGui::SameLine();+ ToggleButton( ICON_FA_SCALE_BALANCED " Compare", m_compare.show );+ ImGui::SameLine();+ ToggleButton( ICON_FA_FINGERPRINT " Info", m_showInfo );+ ImGui::SameLine();+ if( ImGui::Button( ICON_FA_SCREWDRIVER_WRENCH ) ) ImGui::OpenPopup( "ToolsPopup" );+ if( ImGui::BeginPopup( "ToolsPopup" ) )+ {+ const auto ficnt = m_worker.GetFrameImageCount();+ if( ButtonDisablable( ICON_FA_PLAY " Playback", ficnt == 0 ) )+ {+ m_showPlayback = true;+ }+ const auto& ctd = m_worker.GetCpuThreadData();+ if( ButtonDisablable( ICON_FA_SLIDERS " CPU data", ctd.empty() ) )+ {+ m_showCpuDataWindow = true;+ }+ ToggleButton( ICON_FA_NOTE_STICKY " Annotations", m_showAnnotationList );+ ToggleButton( ICON_FA_RULER " Limits", m_showRanges );+ const auto cscnt = m_worker.GetContextSwitchSampleCount();+ if( ButtonDisablable( ICON_FA_HOURGLASS_HALF " Wait stacks", cscnt == 0 ) )+ {+ m_showWaitStacks = true;+ }+ ImGui::EndPopup();+ }+ if( m_sscb )+ {+ ImGui::SameLine();+ if( ImGui::Button( ICON_FA_MAGNIFYING_GLASS_PLUS ) ) ImGui::OpenPopup( "ZoomPopup" );+ if( ImGui::BeginPopup( "ZoomPopup" ) )+ {+ if( ImGui::Button( "50%" ) ) m_sscb( 1.f/2 );+ if( ImGui::Button( "57%" ) ) m_sscb( 1.f/1.75f );+ if( ImGui::Button( "66%" ) ) m_sscb( 1.f/1.5f );+ if( ImGui::Button( "80%" ) ) m_sscb( 1.f/1.25f );+ if( ImGui::Button( "100%" ) ) m_sscb( 1.f );+ if( ImGui::Button( "125%" ) ) m_sscb( 1.25f );+ if( ImGui::Button( "150%" ) ) m_sscb( 1.5f );+ if( ImGui::Button( "175%" ) ) m_sscb( 1.75f );+ if( ImGui::Button( "200%" ) ) m_sscb( 2.f );+ if( ImGui::Button( "225%" ) ) m_sscb( 2.25f );+ if( ImGui::Button( "250%" ) ) m_sscb( 2.5f );+ if( ImGui::Button( "275%" ) ) m_sscb( 2.75f );+ if( ImGui::Button( "300%" ) ) m_sscb( 3.f );+ ImGui::EndPopup();+ }+ }+ if( m_worker.AreFramesUsed() )+ {+ ImGui::SameLine();+ if( ImGui::SmallButton( " " ICON_FA_CARET_LEFT " " ) ) ZoomToPrevFrame();+ ImGui::SameLine();+ {+ const auto vis = Vis( m_frames );+ if( !vis )+ {+ ImGui::PushStyleColor( ImGuiCol_Text, GImGui->Style.Colors[ImGuiCol_TextDisabled] );+ }+ ImGui::Text( "%s: %s", GetFrameSetName( *m_frames ), RealToString( m_worker.GetFrameCount( *m_frames ) ) );+ if( !vis )+ {+ ImGui::PopStyleColor();+ }+ if( ImGui::IsItemClicked() ) ImGui::OpenPopup( "GoToFramePopup" );+ }+ ImGui::SameLine();+ if( ImGui::SmallButton( " " ICON_FA_CARET_RIGHT " " ) ) ZoomToNextFrame();+ ImGui::SameLine();+ if( ImGui::BeginCombo( "##frameCombo", nullptr, ImGuiComboFlags_NoPreview ) )+ {+ auto& frames = m_worker.GetFrames();+ for( auto& fd : frames )+ {+ bool isSelected = m_frames == fd;+ if( ImGui::Selectable( GetFrameSetName( *fd ), isSelected ) )+ {+ m_frames = fd;+ }+ if( isSelected )+ {+ ImGui::SetItemDefaultFocus();+ }+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( fd->frames.size() ) );+ }+ ImGui::EndCombo();+ }+ if( ImGui::BeginPopup( "GoToFramePopup" ) )+ {+ static int frameNum = 1;+ const bool mainFrameSet = m_frames->name == 0;+ const auto numFrames = mainFrameSet ? m_frames->frames.size() - 1 : m_frames->frames.size();+ const auto frameOffset = mainFrameSet ? 0 : 1;+ ImGui::SetNextItemWidth( 120 * GetScale() );+ const bool clicked = ImGui::InputInt( "##goToFrame", &frameNum, 1, 100, ImGuiInputTextFlags_EnterReturnsTrue );+ frameNum = std::min( std::max( frameNum, 1 ), int( numFrames ) );+ if( clicked ) ZoomToRange( m_worker.GetFrameBegin( *m_frames, frameNum - frameOffset ), m_worker.GetFrameEnd( *m_frames, frameNum - frameOffset ) );+ ImGui::EndPopup();+ }+ }++ {+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();++ auto targetLabelSize = ImGui::CalcTextSize( ICON_FA_EYE " 12345.67 ms" ).x;+ auto cx = ImGui::GetCursorPosX();+ ImGui::Text( ICON_FA_EYE " %s", TimeToString( m_vd.zvEnd - m_vd.zvStart ) );+ TooltipIfHovered( "View span" );+ ImGui::SameLine();+ auto dx = ImGui::GetCursorPosX() - cx;+ if( dx < targetLabelSize ) ImGui::SameLine( cx + targetLabelSize );++ const auto firstTime = m_worker.GetFirstTime();+ const auto lastTime = m_worker.GetLastTime();+ cx = ImGui::GetCursorPosX();+ ImGui::Text( ICON_FA_DATABASE " %s", TimeToString( lastTime - firstTime ) );+ if( ImGui::IsItemHovered() )+ {+ ImGui::BeginTooltip();+ if( firstTime == 0 )+ {+ ImGui::Text( "Time span" );+ }+ else+ {+ TextFocused( "Total time span:", TimeToString( lastTime ) );+ }+ ImGui::EndTooltip();+ if( ImGui::IsItemClicked( 2 ) )+ {+ ZoomToRange( firstTime, lastTime );+ }+ }+ ImGui::SameLine();+ dx = ImGui::GetCursorPosX() - cx;+ if( dx < targetLabelSize ) ImGui::SameLine( cx + targetLabelSize );++ targetLabelSize = ImGui::CalcTextSize( ICON_FA_MEMORY " 1234.56 MB (123.45 %%)" ).x;+ cx = ImGui::GetCursorPosX();+ const auto mem = memUsage.load( std::memory_order_relaxed );+ ImGui::Text( ICON_FA_MEMORY " %s", MemSizeToString( mem ) );+ TooltipIfHovered( "Profiler memory usage" );+ if( m_totalMemory != 0 )+ {+ ImGui::SameLine();+ const auto memUse = float( mem ) / m_totalMemory * 100;+ if( memUse < 80 )+ {+ ImGui::TextDisabled( "(%.2f%%)", memUse );+ }+ else+ {+ ImGui::TextColored( ImVec4( 1.f, 0.25f, 0.25f, 1.f ), "(%.2f%%)", memUse );+ }+ }+ ImGui::SameLine();+ dx = ImGui::GetCursorPosX() - cx;+ if( dx < targetLabelSize ) ImGui::SameLine( cx + targetLabelSize );+ ImGui::Spacing();++ const auto memoryLimit = m_worker.GetMemoryLimit();+ if( memoryLimit > 0 )+ {+ ImGui::SameLine();+ if( memUsage.load( std::memory_order_relaxed ) > memoryLimit )+ {+ TextColoredUnformatted( 0xFF2222FF, ICON_FA_TRIANGLE_EXCLAMATION );+ }+ else+ {+ TextColoredUnformatted( 0xFF00FFFF, ICON_FA_TRIANGLE_EXCLAMATION );+ }+ if( ImGui::IsItemHovered() )+ {+ ImGui::BeginTooltip();+ ImGui::Text( "Memory limit: %s", MemSizeToString( memoryLimit ) );+ ImGui::EndTooltip();+ }+ }+ }+ DrawNotificationArea();++ m_frameHover = -1;++ DrawFrames();++ const auto dockspaceId = ImGui::GetID( "tracyDockspace" );+ ImGui::DockSpace( dockspaceId, ImVec2( 0, 0 ), ImGuiDockNodeFlags_NoDockingOverCentralNode );+ if( ImGuiDockNode* node = ImGui::DockBuilderGetCentralNode( dockspaceId ) )+ {+ node->LocalFlags |= ImGuiDockNodeFlags_NoTabBar;+ }+ ImGui::SetNextWindowDockID( dockspaceId );+ {+ auto& style = ImGui::GetStyle();+ const auto wpPrev = style.WindowPadding;+ style.WindowPadding = ImVec2( 1, 0 );+#ifndef TRACY_NO_ROOT_WINDOW+ style.Colors[ImGuiCol_WindowBg] = ImVec4( 0.129f, 0.137f, 0.11f, 1.f );+#endif++ ImGui::Begin( "Work area", nullptr, ImGuiWindowFlags_NoNavFocus );++ style.WindowPadding = wpPrev;+#ifndef TRACY_NO_ROOT_WINDOW+ style.Colors[ImGuiCol_WindowBg] = ImVec4( 0.11f, 0.11f, 0.08f, 1.f );+#endif+ }++ DrawTimeline();++ ImGui::End();+ ImGui::End();++ m_zoneHighlight = nullptr;+ m_gpuHighlight = nullptr;++ DrawInfoWindow();++ if( m_showOptions ) DrawOptions();+ if( m_showMessages ) DrawMessages();+ if( m_showFlameGraph ) DrawFlameGraph();+ if( m_findZone.show ) DrawFindZone();+ if( m_showStatistics ) DrawStatistics();+ if( m_memInfo.show ) DrawMemory();+ if( m_memInfo.showAllocList ) DrawAllocList();+ if( m_compare.show ) DrawCompare();+ if( m_callstackInfoWindow != 0 ) DrawCallstackWindow();+ if( m_memoryAllocInfoWindow >= 0 ) DrawMemoryAllocWindow();+ if( m_showInfo ) DrawInfo();+ if( m_sourceViewFile ) DrawTextEditor();+ if( m_lockInfoWindow != InvalidId ) DrawLockInfoWindow();+ if( m_showPlayback ) DrawPlayback();+ if( m_showCpuDataWindow ) DrawCpuDataWindow();+ if( m_selectedAnnotation ) DrawSelectedAnnotation();+ if( m_showAnnotationList ) DrawAnnotationList();+ if( m_sampleParents.symAddr != 0 ) DrawSampleParents();+ if( m_showRanges ) DrawRanges();+ if( m_showWaitStacks ) DrawWaitStacks();++ if( m_setRangePopup.active )+ {+ m_setRangePopup.active = false;+ ImGui::OpenPopup( "SetZoneRange" );+ }+ if( ImGui::BeginPopup( "SetZoneRange" ) )+ {+ const auto s = std::min( m_setRangePopup.min, m_setRangePopup.max );+ const auto e = std::max( m_setRangePopup.min, m_setRangePopup.max );+ if( ImGui::Selectable( ICON_FA_MAGNIFYING_GLASS " Limit find zone time range" ) )+ {+ m_findZone.range.active = true;+ m_findZone.range.min = s;+ m_findZone.range.max = e;+ }+ if( ImGui::Selectable( ICON_FA_ARROW_UP_WIDE_SHORT " Limit statistics time range" ) )+ {+ m_statRange.active = true;+ m_statRange.min = s;+ m_statRange.max = e;+ }+ if( ImGui::Selectable( ICON_FA_FIRE_FLAME_CURVED " Limit flame time range" ) )+ {+ m_flameRange.active = true;+ m_flameRange.min = s;+ m_flameRange.max = e;+ }+ if( ImGui::Selectable( ICON_FA_HOURGLASS_HALF " Limit wait stacks range" ) )+ {+ m_waitStackRange.active = true;+ m_waitStackRange.min = s;+ m_waitStackRange.max = e;+ }+ if( ImGui::Selectable( ICON_FA_MEMORY " Limit memory range" ) )+ {+ m_memInfo.range.active = true;+ m_memInfo.range.min = s;+ m_memInfo.range.max = e;+ }+ ImGui::Separator();+ if( ImGui::Selectable( ICON_FA_NOTE_STICKY " Add annotation" ) )+ {+ AddAnnotation( s, e );+ }+ ImGui::EndPopup();+ }+ m_setRangePopupOpen = ImGui::IsPopupOpen( "SetZoneRange" );++ if( m_zoomAnim.active )+ {+ if( m_viewMode == ViewMode::LastRange )+ {+ const auto delta = m_worker.GetLastTime() - m_vd.zvEnd;+ if( delta != 0 )+ {+ m_zoomAnim.start0 += delta;+ m_zoomAnim.start1 += delta;+ m_zoomAnim.end0 += delta;+ m_zoomAnim.end1 += delta;+ }+ }+ m_zoomAnim.progress += io.DeltaTime * 3.33f;+ if( m_zoomAnim.progress >= 1.f )+ {+ m_zoomAnim.active = false;+ m_vd.zvStart = m_zoomAnim.start1;+ m_vd.zvEnd = m_zoomAnim.end1;+ }+ else+ {+ const auto v = sqrt( sin( M_PI_2 * m_zoomAnim.progress ) );+ m_vd.zvStart = int64_t( m_zoomAnim.start0 + ( m_zoomAnim.start1 - m_zoomAnim.start0 ) * v );+ m_vd.zvEnd = int64_t( m_zoomAnim.end0 + ( m_zoomAnim.end1 - m_zoomAnim.end0 ) * v );+ }+ }++ m_wasActive |= m_callstackBuzzAnim.Update( io.DeltaTime );+ m_wasActive |= m_sampleParentBuzzAnim.Update( io.DeltaTime );+ m_wasActive |= m_callstackTreeBuzzAnim.Update( io.DeltaTime );+ m_wasActive |= m_zoneinfoBuzzAnim.Update( io.DeltaTime );+ m_wasActive |= m_findZoneBuzzAnim.Update( io.DeltaTime );+ m_wasActive |= m_optionsLockBuzzAnim.Update( io.DeltaTime );+ m_wasActive |= m_lockInfoAnim.Update( io.DeltaTime );+ m_wasActive |= m_statBuzzAnim.Update( io.DeltaTime );++ if( m_firstFrame )+ {+ const auto now = std::chrono::high_resolution_clock::now();+ if( m_firstFrameTime.time_since_epoch().count() == 0 )+ {+ m_firstFrameTime = now;+ }+ else+ {+ if( std::chrono::duration_cast<std::chrono::milliseconds>( now - m_firstFrameTime ).count() > 500 )+ {+ m_firstFrame = false;+ m_tc.FirstFrameExpired();+ }+ }+ }++ if( m_reactToCrash )+ {+ auto& crash = m_worker.GetCrashEvent();+ if( crash.thread != 0 )+ {+ m_reactToCrash = false;+ ImGui::OpenPopup( "Application crashed!" );+ }+ }+ if( ImGui::BeginPopupModal( "Application crashed!", nullptr, ImGuiWindowFlags_AlwaysAutoResize ) )+ {+ auto& crash = m_worker.GetCrashEvent();+ assert( crash.thread != 0 );+ ImGui::TextUnformatted( ICON_FA_SKULL );+ ImGui::SameLine();+ TextColoredUnformatted( 0xFF4444FF, "Application has crashed" );+ ImGui::SameLine();+ ImGui::TextUnformatted( ICON_FA_SKULL );+ ImGui::Separator();+ TextFocused( "Time:", TimeToString( crash.time ) );+ TextFocused( "Thread:", m_worker.GetThreadName( crash.thread ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( crash.thread ) );+ if( m_worker.IsThreadFiber( crash.thread ) )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 0.2f, 0.6f, 0.2f, 1.f ), "Fiber" );+ }+ TextFocused( "Reason:", m_worker.GetString( crash.message ) );+ if( crash.callstack != 0 )+ {+ bool hilite = m_callstackInfoWindow == crash.callstack;+ if( hilite )+ {+ SetButtonHighlightColor();+ }+ if( ImGui::Button( ICON_FA_ALIGN_JUSTIFY " Call stack" ) )+ {+ m_callstackInfoWindow = crash.callstack;+ }+ if( hilite )+ {+ ImGui::PopStyleColor( 3 );+ }+ if( ImGui::IsItemHovered() )+ {+ CallstackTooltip( crash.callstack );+ }+ }+ ImGui::Separator();+ if( ImGui::Button( ICON_FA_MICROSCOPE " Focus" ) ) CenterAtTime( crash.time );+ ImGui::SameLine();+ if( ImGui::Button( "Dismiss" ) ) ImGui::CloseCurrentPopup();+ ImGui::EndPopup();+ }++ if( m_reactToLostConnection && !m_worker.IsConnected() )+ {+ m_reactToLostConnection = false;+ const auto inFlight = m_worker.GetSendInFlight();+ if( inFlight > 1 || ( inFlight == 1 && !m_worker.WasDisconnectIssued() ) )+ {+ ImGui::OpenPopup( "Connection lost!" );+ }+ }+ if( ImGui::BeginPopupModal( "Connection lost!", nullptr, ImGuiWindowFlags_AlwaysAutoResize ) )+ {+ ImGui::PushFont( m_bigFont );+ TextCentered( ICON_FA_PLUG );+ ImGui::PopFont();+ ImGui::TextUnformatted(+ "Connection to the profiled application was lost\n"+ "before all required profiling data could be retrieved.\n"+ "This will result in missing source locations,\n"+ "unresolved stack frames, etc." );+ ImGui::Separator();+ if( ImGui::Button( "Dismiss" ) ) ImGui::CloseCurrentPopup();+ ImGui::EndPopup();+ }++ return keepOpen;+}++void View::DrawTextEditor()+{+ const auto scale = GetScale();+ ImGui::SetNextWindowSize( ImVec2( 1800 * scale, 800 * scale ), ImGuiCond_FirstUseEver );+ bool show = true;+ ImGui::Begin( "Source view", &show, ImGuiWindowFlags_NoScrollbar );+ if( !ImGui::GetCurrentWindowRead()->SkipItems )+ {+ m_sourceView->UpdateFont( m_fixedFont, m_smallFont, m_bigFont );+ m_sourceView->Render( m_worker, *this );+ }+ ImGui::End();+ if( !show ) m_sourceViewFile = nullptr;+}++void View::CrashTooltip()+{+ auto& crash = m_worker.GetCrashEvent();+ ImGui::BeginTooltip();+ TextFocused( "Time:", TimeToString( crash.time ) );+ TextFocused( "Reason:", m_worker.GetString( crash.message ) );+ ImGui::EndTooltip();+}++void View::DrawSourceTooltip( const char* filename, uint32_t srcline, int before, int after, bool separateTooltip )+{+ if( !filename ) return;+ if( !SourceFileValid( filename, m_worker.GetCaptureTime(), *this, m_worker ) ) return;+ m_srcHintCache.Parse( filename, m_worker, *this );+ if( m_srcHintCache.empty() ) return;+ ImGui::PushStyleVar( ImGuiStyleVar_ItemSpacing, ImVec2( 0, 0 ) );+ if( separateTooltip ) ImGui::BeginTooltip();+ ImGui::PushFont( m_fixedFont );+ auto& lines = m_srcHintCache.get();+ const int start = std::max( 0, (int)srcline - ( before+1 ) );+ const int end = std::min<int>( m_srcHintCache.get().size(), srcline + after );+ bool first = true;+ int bottomEmpty = 0;+ for( int i=start; i<end; i++ )+ {+ auto& line = lines[i];+ if( line.begin == line.end )+ {+ if( !first ) bottomEmpty++;+ }+ else+ {+ first = false;+ while( bottomEmpty > 0 )+ {+ ImGui::TextUnformatted( "" );+ bottomEmpty--;+ }++ auto ptr = line.begin;+ auto it = line.tokens.begin();+ while( ptr < line.end )+ {+ if( it == line.tokens.end() )+ {+ ImGui::TextUnformatted( ptr, line.end );+ ImGui::SameLine( 0, 0 );+ break;+ }+ if( ptr < it->begin )+ {+ ImGui::TextUnformatted( ptr, it->begin );+ ImGui::SameLine( 0, 0 );+ }+ auto color = SyntaxColors[(int)it->color];+ if( i != srcline-1 ) color = ( color & 0xFFFFFF ) | 0x99000000;+ TextColoredUnformatted( color, it->begin, it->end );+ ImGui::SameLine( 0, 0 );+ ptr = it->end;+ ++it;+ }+ ImGui::ItemSize( ImVec2( 0, 0 ), 0 );+ }+ }+ ImGui::PopFont();+ if( separateTooltip ) ImGui::EndTooltip();+ ImGui::PopStyleVar();+}++bool View::Save( const char* fn, FileCompression comp, int zlevel, bool buildDict, int streams )+{+ std::unique_ptr<FileWrite> f( FileWrite::Open( fn, comp, zlevel, streams ) );+ if( !f ) return false;++ m_userData.StateShouldBePreserved();+ m_saveThreadState.store( SaveThreadState::Saving, std::memory_order_relaxed );+ m_saveThread = std::thread( [this, f{std::move( f )}, buildDict] {+ std::lock_guard<std::mutex> lock( m_worker.GetDataLock() );+ m_worker.Write( *f, buildDict );+ f->Finish();+ const auto stats = f->GetCompressionStatistics();+ m_srcFileBytes.store( stats.first, std::memory_order_relaxed );+ m_dstFileBytes.store( stats.second, std::memory_order_relaxed );+ m_saveThreadState.store( SaveThreadState::NeedsJoin, std::memory_order_release );+ } );++ return true;+}++void View::HighlightThread( uint64_t thread )+{+ m_drawThreadMigrations = thread;+ m_drawThreadHighlight = thread;+}++void View::SelectThread( uint64_t thread )+{+ m_selectedThread = thread;+}++bool View::WasActive() const+{+ return m_wasActive ||+ m_zoomAnim.active ||+ m_notificationTime > 0 ||+ !m_playback.pause ||+ m_worker.IsConnected() ||+ !m_worker.IsBackgroundDone();+}++}
+ cbits/tracy/profiler/src/profiler/TracyView.hpp view
@@ -0,0 +1,943 @@+#ifndef __TRACYVIEW_HPP__+#define __TRACYVIEW_HPP__++#include <array>+#include <atomic>+#include <chrono>+#include <functional>+#include <memory>+#include <string>+#include <thread>+#include <vector>++#include "imgui.h"++#include "TracyAchievements.hpp"+#include "TracyBadVersion.hpp"+#include "TracyBuzzAnim.hpp"+#include "TracyConfig.hpp"+#include "TracyDecayValue.hpp"+#include "TracySourceContents.hpp"+#include "TracyTimelineController.hpp"+#include "TracyUserData.hpp"+#include "TracyUtility.hpp"+#include "TracyViewData.hpp"+#include "../server/TracyFileWrite.hpp"+#include "../server/TracyTaskDispatch.hpp"+#include "../server/TracyShortPtr.hpp"+#include "../server/TracyWorker.hpp"+#include "../server/tracy_robin_hood.h"+#include "../server/TracyVector.hpp"++namespace tracy+{++constexpr const char* GpuContextNames[] = {+ "Invalid",+ "OpenGL",+ "Vulkan",+ "OpenCL",+ "Direct3D 12",+ "Direct3D 11",+ "Metal",+ "Custom",+ "CUDA"+};++struct MemoryPage;+class FileRead;+class SourceView;+struct TimelineContext;+struct TimelineDraw;+struct ContextSwitchDraw;+struct SamplesDraw;+struct MessagesDraw;+struct CpuUsageDraw;+struct CpuCtxDraw;+struct LockDraw;+struct PlotDraw;+struct FlameGraphContext;+++class View+{+ struct Animation+ {+ bool active = false;+ int64_t start0, start1;+ int64_t end0, end1;+ double progress;+ };++ struct Region+ {+ bool active = false;+ int64_t start;+ int64_t end;+ };++ struct ZoneTimeData+ {+ int64_t time;+ uint64_t count;+ };++ enum class AccumulationMode+ {+ SelfOnly,+ AllChildren,+ NonReentrantChildren+ };++ struct StatisticsCache+ {+ RangeSlim range;+ AccumulationMode accumulationMode;+ size_t sourceCount;+ size_t count;+ int64_t total;+ uint16_t threadNum;+ };++public:+ struct PlotView+ {+ double min;+ double max;+ };++ using SetTitleCallback = void(*)( const char* );+ using SetScaleCallback = void(*)( float );+ using AttentionCallback = void(*)();++ View( void(*cbMainThread)(const std::function<void()>&, bool), const char* addr, uint16_t port, ImFont* fixedWidth, ImFont* smallFont, ImFont* bigFont, SetTitleCallback stcb, SetScaleCallback sscb, AttentionCallback acb, const Config& config, AchievementsMgr* amgr );+ View( void(*cbMainThread)(const std::function<void()>&, bool), FileRead& f, ImFont* fixedWidth, ImFont* smallFont, ImFont* bigFont, SetTitleCallback stcb, SetScaleCallback sscb, AttentionCallback acb, const Config& config, AchievementsMgr* amgr );+ ~View();++ bool Draw();+ bool WasActive() const;++ void UpdateFont( ImFont* fixed, ImFont* small, ImFont* big ) { m_fixedFont = fixed; m_smallFont = small; m_bigFont = big; }++ void NotifyRootWindowSize( float w, float h ) { m_rootWidth = w; m_rootHeight = h; }+ void ViewSource( const char* fileName, int line );+ void ViewSource( const char* fileName, int line, const char* functionName );+ void ViewSourceCheckKeyMod( const char* fileName, int line, const char* functionName );+ void ViewSymbol( const char* fileName, int line, uint64_t baseAddr, uint64_t symAddr );+ bool ViewDispatch( const char* fileName, int line, uint64_t symAddr );++ bool ReconnectRequested() const { return m_reconnectRequested; }+ std::string GetAddress() const { return m_worker.GetAddr(); }+ uint16_t GetPort() const { return m_worker.GetPort(); }++ const char* SourceSubstitution( const char* srcFile ) const;+ bool ValidateSourceAge() const { return m_validateSourceAge; }++ void ShowSampleParents( uint64_t symAddr, bool withInlines ) { m_sampleParents.symAddr = symAddr; m_sampleParents.sel = 0; m_sampleParents.withInlines = withInlines; }++ ViewData& GetViewData() { return m_vd; }+ const ViewData& GetViewData() const { return m_vd; }++ ShortenName GetShortenName() const { return m_vd.shortenName; }+ int GetNextGpuIdx() { return m_gpuIdx++; }++ const MessageData* GetMessageHighlight() const { return m_msgHighlight; }+ uint32_t GetLockInfoWindow() const { return m_lockInfoWindow; }++ tracy_force_inline bool& Vis( const void* ptr )+ {+ auto it = m_visMap.find( ptr );+ if( it == m_visMap.end() ) it = m_visMap.emplace( ptr, true ).first;+ return it->second;+ }++ void HighlightThread( uint64_t thread );+ void SelectThread( uint64_t thread );+ uint64_t GetSelectThread() { return m_selectedThread; }+ void ZoomToRange( int64_t start, int64_t end, bool pause = true );+ bool DrawPlot( const TimelineContext& ctx, PlotData& plot, const std::vector<uint32_t>& plotDraw, int& offset, bool rightEnd );+ void DrawThread( const TimelineContext& ctx, const ThreadData& thread, const std::vector<TimelineDraw>& draw, const std::vector<ContextSwitchDraw>& ctxDraw, const std::vector<SamplesDraw>& samplesDraw, const std::vector<std::unique_ptr<LockDraw>>& lockDraw, int& offset, int depth, bool hasCtxSwitches, bool hasSamples );+ void DrawThreadMessagesList( const TimelineContext& ctx, const std::vector<MessagesDraw>& drawList, int offset, uint64_t tid );+ void DrawThreadOverlays( const ThreadData& thread, const ImVec2& ul, const ImVec2& dr );+ bool DrawGpu( const TimelineContext& ctx, const GpuCtxData& gpu, int& offset );+ bool DrawCpuData( const TimelineContext& ctx, const std::vector<CpuUsageDraw>& cpuDraw, const std::vector<std::vector<CpuCtxDraw>>& ctxDraw, int& offset, bool hasCpuData );+ void DrawThreadMigrations( const TimelineContext& ctx, const int origOffset, uint64_t thread );++ bool IsBackgroundDone() const { return m_worker.IsBackgroundDone(); }++ bool m_showRanges = false;+ Range m_statRange;+ Range m_flameRange;+ Range m_waitStackRange;++private:+ enum class ShortcutAction : uint8_t+ {+ None,+ OpenFind+ };++ enum { InvalidId = 0xFFFFFFFF };++ struct MemPathData+ {+ uint32_t cnt;+ uint64_t mem;+ };++ enum class ViewMode+ {+ Paused,+ LastFrames,+ LastRange+ };++ enum class MemRange+ {+ Full,+ Active,+ Inactive+ };++ struct KeyboardNavigation+ {+ enum Direction+ {+ // Pan left / right+ Left,+ Right,+ // Zoom in / out+ In,+ Out+ };++ constexpr static auto DirectionToKeyMap = std::array<ImGuiKey, 4> { ImGuiKey_A, ImGuiKey_D, ImGuiKey_W, ImGuiKey_S };+ constexpr static auto StartRangeMod = std::array<int, 4> { -1, 1, 1, -1 };+ constexpr static auto EndRangeMod = std::array<int, 4> { -1, 1, -1, 1 };++ std::array<float, 4> m_scrollInertia;+ };++ struct ZoneColorData+ {+ uint32_t color;+ uint32_t accentColor;+ float thickness;+ bool highlight;+ };++ struct SymList+ {+ uint64_t symAddr;+ uint32_t incl, excl;+ uint32_t count;+ };++ void InitTextEditor();+ void SetupConfig( const Config& config );+ void Achieve( const char* id );++ bool DrawImpl();+ void DrawNotificationArea();+ bool DrawConnection();+ void DrawFrames();+ void DrawTimelineFramesHeader();+ void DrawTimelineFrames( const FrameData& frames );+ void DrawTimeline();+ void DrawSampleList( const TimelineContext& ctx, const std::vector<SamplesDraw>& drawList, const Vector<SampleData>& vec, int offset );+ void DrawZoneList( const TimelineContext& ctx, const std::vector<TimelineDraw>& drawList, int offset, uint64_t tid );+ void DrawContextSwitchList( const TimelineContext& ctx, const std::vector<ContextSwitchDraw>& drawList, const Vector<ContextSwitchData>& ctxSwitch, int offset, int endOffset, bool isFiber );+ int DispatchGpuZoneLevel( const Vector<short_ptr<GpuEvent>>& vec, bool hover, double pxns, int64_t nspx, const ImVec2& wpos, int offset, int depth, uint64_t thread, float yMin, float yMax, int64_t begin, int drift );+ template<typename Adapter, typename V>+ int DrawGpuZoneLevel( const V& vec, bool hover, double pxns, int64_t nspx, const ImVec2& wpos, int offset, int depth, uint64_t thread, float yMin, float yMax, int64_t begin, int drift );+ template<typename Adapter, typename V>+ int SkipGpuZoneLevel( const V& vec, bool hover, double pxns, int64_t nspx, const ImVec2& wpos, int offset, int depth, uint64_t thread, float yMin, float yMax, int64_t begin, int drift );+ void DrawLockHeader( uint32_t id, const LockMap& lockmap, const SourceLocation& srcloc, bool hover, ImDrawList* draw, const ImVec2& wpos, float w, float ty, float offset, uint8_t tid );+ int DrawLocks( const TimelineContext& ctx, const std::vector<std::unique_ptr<LockDraw>>& lockDraw, uint64_t tid, int _offset, LockHighlight& highlight );+ void DrawPlotPoint( const ImVec2& wpos, float x, float y, int offset, uint32_t color, bool hover, bool hasPrev, const PlotItem& item, double prev, PlotType type, PlotValueFormatting format, float PlotHeight, uint64_t name );+ void DrawPlotPoint( const ImVec2& wpos, float x, float y, int offset, uint32_t color, bool hover, double val, PlotValueFormatting format, float PlotHeight );+ void DrawOptions();+ void DrawMessages();+ void DrawMessageLine( const MessageData& msg, bool hasCallstack, int& idx );+ void DrawFindZone();+ void AccumulationModeComboBox();+ void DrawStatistics();+ void DrawSamplesStatistics(Vector<SymList>& data, int64_t timeRange, AccumulationMode accumulationMode);+ void DrawMemory();+ void DrawAllocList();+ void DrawCompare();+ void DrawCallstackWindow();+ void DrawCallstackTable( uint32_t callstack, bool globalEntriesButton );+ void DrawMemoryAllocWindow();+ void DrawInfo();+ void DrawTextEditor();+ void DrawLockInfoWindow();+ void DrawPlayback();+ void DrawCpuDataWindow();+ void DrawSelectedAnnotation();+ void DrawAnnotationList();+ void DrawSampleParents();+ void DrawRanges();+ void DrawRangeEntry( Range& range, const char* label, uint32_t color, const char* popupLabel, int id );+ void DrawSourceTooltip( const char* filename, uint32_t line, int before = 3, int after = 3, bool separateTooltip = true );+ void DrawWaitStacks();+ void DrawFlameGraph();+ void DrawFlameGraphHeader( uint64_t timespan );+ void DrawFlameGraphLevel( const std::vector<FlameGraphItem>& data, FlameGraphContext& ctx, int depth, bool samples );+ void DrawFlameGraphItem( const FlameGraphItem& item, FlameGraphContext& ctx, int depth, bool samples );+ void BuildFlameGraph( const Worker& worker, std::vector<FlameGraphItem>& data, const Vector<short_ptr<ZoneEvent>>& zones );+ void BuildFlameGraph( const Worker& worker, std::vector<FlameGraphItem>& data, const Vector<short_ptr<ZoneEvent>>& zones, const ContextSwitch* ctx );+ void BuildFlameGraph( const Worker& worker, std::vector<FlameGraphItem>& data, const Vector<SampleData>& samples );++ void ListMemData( std::vector<const MemEvent*>& vec, const std::function<void(const MemEvent*)>& DrawAddress, int64_t startTime = -1, uint64_t pool = 0 );++ unordered_flat_map<uint32_t, MemPathData> GetCallstackPaths( const MemData& mem, MemRange memRange ) const;+ unordered_flat_map<uint64_t, MemCallstackFrameTree> GetCallstackFrameTreeBottomUp( const MemData& mem ) const;+ unordered_flat_map<uint64_t, MemCallstackFrameTree> GetCallstackFrameTreeTopDown( const MemData& mem ) const;+ void DrawFrameTreeLevel( const unordered_flat_map<uint64_t, MemCallstackFrameTree>& tree, int& idx );+ void DrawZoneList( int id, const Vector<short_ptr<ZoneEvent>>& zones );++ unordered_flat_map<uint64_t, CallstackFrameTree> GetCallstackFrameTreeBottomUp( const unordered_flat_map<uint32_t, uint64_t>& stacks, bool group ) const;+ unordered_flat_map<uint64_t, CallstackFrameTree> GetCallstackFrameTreeTopDown( const unordered_flat_map<uint32_t, uint64_t>& stacks, bool group ) const;+ void DrawFrameTreeLevel( const unordered_flat_map<uint64_t, CallstackFrameTree>& tree, int& idx );++ unordered_flat_map<uint64_t, CallstackFrameTree> GetParentsCallstackFrameTreeBottomUp( const unordered_flat_map<uint32_t, uint32_t>& stacks, bool group ) const;+ unordered_flat_map<uint64_t, CallstackFrameTree> GetParentsCallstackFrameTreeTopDown( const unordered_flat_map<uint32_t, uint32_t>& stacks, bool group ) const;+ void DrawParentsFrameTreeLevel( const unordered_flat_map<uint64_t, CallstackFrameTree>& tree, int& idx );++ void DrawInfoWindow();+ void DrawZoneInfoWindow();+ void DrawGpuInfoWindow();++ template<typename Adapter, typename V>+ void DrawZoneInfoChildren( const V& children, int64_t ztime );+ template<typename Adapter, typename V>+ void DrawGpuInfoChildren( const V& children, int64_t ztime );++ void HandleRange( Range& range, int64_t timespan, const ImVec2& wpos, float w );+ void HandleTimelineMouse( int64_t timespan, const ImVec2& wpos, float w );+ void HandleTimelineKeyboard( int64_t timespan, const ImVec2& wpos, float w );++ void AddAnnotation( int64_t start, int64_t end );++ bool IsFrameExternal( const char* filename, const char* image );+ uint32_t GetThreadColor( uint64_t thread, int depth );+ uint32_t GetSrcLocColor( const SourceLocation& srcloc, int depth );+ uint32_t GetRawSrcLocColor( const SourceLocation& srcloc, int depth );+ uint32_t GetZoneColor( const ZoneEvent& ev, uint64_t thread, int depth );+ uint32_t GetZoneColor( const GpuEvent& ev );+ ZoneColorData GetZoneColorData( const ZoneEvent& ev, uint64_t thread, int depth, uint32_t inheritedColor );+ ZoneColorData GetZoneColorData( const GpuEvent& ev );++ void ZoomToZone( const ZoneEvent& ev );+ void ZoomToZone( const GpuEvent& ev );+ void ZoomToPrevFrame();+ void ZoomToNextFrame();+ void CenterAtTime( int64_t t );++ void ShowZoneInfo( const ZoneEvent& ev );+ void ShowZoneInfo( const GpuEvent& ev, uint64_t thread );++ void ZoneTooltip( const ZoneEvent& ev );+ void ZoneTooltip( const GpuEvent& ev );+ void CallstackTooltip( uint32_t idx );+ void CallstackTooltipContents( uint32_t idx );+ void CrashTooltip();++ const ZoneEvent* GetZoneParent( const ZoneEvent& zone ) const;+ const ZoneEvent* GetZoneParent( const ZoneEvent& zone, uint64_t tid ) const;+ const ZoneEvent* GetZoneChild( const ZoneEvent& zone, int64_t time ) const;+ bool IsZoneReentry( const ZoneEvent& zone ) const;+ bool IsZoneReentry( const ZoneEvent& zone, uint64_t tid ) const;+ const GpuEvent* GetZoneParent( const GpuEvent& zone ) const;+ const ThreadData* GetZoneThreadData( const ZoneEvent& zone ) const;+ uint64_t GetZoneThread( const ZoneEvent& zone ) const;+ uint64_t GetZoneThread( const GpuEvent& zone ) const;+ const GpuCtxData* GetZoneCtx( const GpuEvent& zone ) const;+ bool FindMatchingZone( int prev0, int prev1, int flags );+ const ZoneEvent* FindZoneAtTime( uint64_t thread, int64_t time ) const;+ uint64_t GetFrameNumber( const FrameData& fd, int i ) const;+ const char* GetFrameText( const FrameData& fd, int i, uint64_t ftime ) const;+ const char* GetFrameSetName( const FrameData& fd ) const;+ static const char* GetFrameSetName( const FrameData& fd, const Worker& worker );++#ifndef TRACY_NO_STATISTICS+ void FindZones();+ void FindZonesCompare();+#endif++ std::vector<MemoryPage> GetMemoryPages() const;++ void SmallCallstackButton( const char* name, uint32_t callstack, int& idx, bool tooltip = true );+ void DrawCallstackCalls( uint32_t callstack, uint16_t limit ) const;+ void SetViewToLastFrames();+ int64_t GetZoneChildTime( const ZoneEvent& zone );+ int64_t GetZoneChildTime( const GpuEvent& zone );+ int64_t GetZoneChildTimeFast( const ZoneEvent& zone );+ int64_t GetZoneChildTimeFastClamped( const ZoneEvent& zone, int64_t t0, int64_t t1 );+ int64_t GetZoneSelfTime( const ZoneEvent& zone );+ int64_t GetZoneSelfTime( const GpuEvent& zone );+ bool GetZoneRunningTime( const ContextSwitch* ctx, const ZoneEvent& ev, int64_t& time, uint64_t& cnt );+ bool GetZoneRunningTime( const ContextSwitch* ctx, const ZoneEvent& ev, const RangeSlim& range, int64_t& time, uint64_t& cnt );+ const char* GetThreadContextData( uint64_t thread, bool& local, bool& untracked, const char*& program );++ tracy_force_inline void CalcZoneTimeData( unordered_flat_map<int16_t, ZoneTimeData>& data, int64_t& ztime, const ZoneEvent& zone );+ tracy_force_inline void CalcZoneTimeData( const ContextSwitch* ctx, unordered_flat_map<int16_t, ZoneTimeData>& data, int64_t& ztime, const ZoneEvent& zone );+ template<typename Adapter, typename V>+ void CalcZoneTimeDataImpl( const V& children, unordered_flat_map<int16_t, ZoneTimeData>& data, int64_t& ztime );+ template<typename Adapter, typename V>+ void CalcZoneTimeDataImpl( const V& children, const ContextSwitch* ctx, unordered_flat_map<int16_t, ZoneTimeData>& data, int64_t& ztime );++ void SetPlaybackFrame( uint32_t idx );+ bool Save( const char* fn, FileCompression comp, int zlevel, bool buildDict, int streams );++ void Attention( bool& alreadyDone );+ void UpdateTitle();++ unordered_flat_map<uint64_t, bool> m_visibleMsgThread;+ unordered_flat_map<uint64_t, bool> m_waitStackThread;+ unordered_flat_map<uint64_t, bool> m_flameGraphThread;+ unordered_flat_map<const void*, int> m_gpuDrift;+ unordered_flat_map<const PlotData*, PlotView> m_plotView;+ Vector<const ThreadData*> m_threadOrder;+ Vector<const ThreadData*> m_threadReinsert;+ Vector<float> m_threadDnd;++ tracy_force_inline bool& VisibleMsgThread( uint64_t thread )+ {+ auto it = m_visibleMsgThread.find( thread );+ if( it == m_visibleMsgThread.end() )+ {+ it = m_visibleMsgThread.emplace( thread, true ).first;+ }+ return it->second;+ }++ tracy_force_inline bool& WaitStackThread( uint64_t thread )+ {+ auto it = m_waitStackThread.find( thread );+ if( it == m_waitStackThread.end() )+ {+ it = m_waitStackThread.emplace( thread, true ).first;+ }+ return it->second;+ }++ tracy_force_inline bool& FlameGraphThread( uint64_t thread )+ {+ auto it = m_flameGraphThread.find( thread );+ if( it == m_flameGraphThread.end() )+ {+ it = m_flameGraphThread.emplace( thread, true ).first;+ }+ return it->second;+ }++ tracy_force_inline int& GpuDrift( const void* ptr )+ {+ auto it = m_gpuDrift.find( ptr );+ if( it == m_gpuDrift.end() )+ {+ it = m_gpuDrift.emplace( ptr, 0 ).first;+ }+ return it->second;+ }++ static int64_t AdjustGpuTime( int64_t time, int64_t begin, int drift );++ static const char* DecodeContextSwitchState( uint8_t state );+ static const char* DecodeContextSwitchStateCode( uint8_t state );+ static const char* DecodeContextSwitchReason( uint8_t reason );+ static const char* DecodeContextSwitchReasonCode( uint8_t reason );++ Worker m_worker;+ std::string m_filename, m_filenameStaging;+ bool m_staticView;+ ViewMode m_viewMode;+ bool m_viewModeHeuristicTry = false;+ DecayValue<bool> m_forceConnectionPopup = false;+ uint64_t m_totalMemory;++ ViewData m_vd;+ TimelineController m_tc;+ KeyboardNavigation m_kbNavCtrl;++ const ZoneEvent* m_zoneInfoWindow = nullptr;+ const ZoneEvent* m_zoneHighlight;+ DecayValue<int16_t> m_zoneSrcLocHighlight = 0;+ LockHighlight m_lockHighlight { -1 };+ LockHighlight m_nextLockHighlight;+ DecayValue<const MessageData*> m_msgHighlight = nullptr;+ DecayValue<uint32_t> m_lockHoverHighlight = InvalidId;+ DecayValue<const MessageData*> m_msgToFocus = nullptr;+ const GpuEvent* m_gpuInfoWindow = nullptr;+ const GpuEvent* m_gpuHighlight;+ uint64_t m_gpuInfoWindowThread;+ uint32_t m_callstackInfoWindow = 0;+ int64_t m_memoryAllocInfoWindow = -1;+ uint64_t m_memoryAllocInfoPool = 0;+ int64_t m_memoryAllocHover = -1;+ uint64_t m_memoryAllocHoverPool = 0;+ int m_memoryAllocHoverWait = 0;+ const FrameData* m_frames;+ uint32_t m_lockInfoWindow = InvalidId;+ const ZoneEvent* m_zoneHover = nullptr;+ DecayValue<const ZoneEvent*> m_zoneHover2 = nullptr;+ int m_frameHover = -1;+ bool m_messagesScrollBottom;+ ImGuiTextFilter m_messageFilter;+ bool m_showMessageImages = false;+ int m_visibleMessages = 0;+ size_t m_prevMessages = 0;+ bool m_messagesShowCallstack = false;+ Vector<uint32_t> m_msgList;+ bool m_disconnectIssued = false;+ uint64_t m_selectedThread = 0;+ DecayValue<uint64_t> m_drawThreadMigrations = 0;+ DecayValue<uint64_t> m_drawThreadHighlight = 0;+ Annotation* m_selectedAnnotation = nullptr;+ bool m_reactToCrash = false;+ bool m_reactToLostConnection = false;++ ImGuiTextFilter m_statisticsFilter;+ ImGuiTextFilter m_statisticsImageFilter;+ ImGuiTextFilter m_userTextFilter;+ unordered_flat_set<Worker::ZoneThreadData*> m_filteredZones;++ Region m_highlight;+ Region m_highlightZoom;++ DecayValue<uint64_t> m_cpuDataThread = 0;+ uint64_t m_gpuThread = 0;+ int64_t m_gpuStart = 0;+ int64_t m_gpuEnd = 0;++ bool m_showOptions = false;+ bool m_showMessages = false;+ bool m_showStatistics = false;+ bool m_showInfo = false;+ bool m_showPlayback = false;+ bool m_showCpuDataWindow = false;+ bool m_showAnnotationList = false;+ bool m_showWaitStacks = false;+ bool m_showFlameGraph = false;++ AccumulationMode m_statAccumulationMode = AccumulationMode::SelfOnly;+ bool m_statSampleTime = true;+ int m_statMode = 0;+ bool m_shortImageNames = true;+ int m_flameMode = 0;+ bool m_flameSort = false;+ bool m_flameRunningTime = false;+ bool m_flameExternal = true;+ bool m_flameExternalTail = true;+ int m_statSampleLocation = 2;+ bool m_statHideUnknown = true;+ bool m_showAllSymbols = false;+ int m_showCallstackFrameAddress = 0;+ bool m_showExternalFrames = true;+ bool m_showUnknownFrames = true;+ bool m_statSeparateInlines = false;+ bool m_mergeInlines = false;+ bool m_relativeInlines = false;+ bool m_topInline = false;+ bool m_statShowAddress = false;+ bool m_statShowKernel = true;+ bool m_groupChildrenLocations = false;+ bool m_allocTimeRelativeToZone = true;+ bool m_ctxSwitchTimeRelativeToZone = true;+ bool m_messageTimeRelativeToZone = true;+ bool m_messagesExcludeChildren = true;+ uint64_t m_zoneInfoMemPool = 0;+ int m_waitStack = 0;+ int m_waitStackMode = 0;+ bool m_groupWaitStackBottomUp = true;+ bool m_groupWaitStackTopDown = true;++ ShortcutAction m_shortcut = ShortcutAction::None;+ Animation m_zoomAnim;+ BuzzAnim<int> m_callstackBuzzAnim;+ BuzzAnim<int> m_sampleParentBuzzAnim;+ BuzzAnim<int> m_callstackTreeBuzzAnim;+ BuzzAnim<const void*> m_zoneinfoBuzzAnim;+ BuzzAnim<int> m_findZoneBuzzAnim;+ BuzzAnim<int16_t> m_optionsLockBuzzAnim;+ BuzzAnim<uint32_t> m_lockInfoAnim;+ BuzzAnim<uint32_t> m_statBuzzAnim;++ Vector<const ZoneEvent*> m_zoneInfoStack;+ Vector<const GpuEvent*> m_gpuInfoStack;++ SourceContents m_srcHintCache;+ std::unique_ptr<SourceView> m_sourceView;+ const char* m_sourceViewFile;+ bool m_uarchSet = false;++ ImFont* m_smallFont;+ ImFont* m_bigFont;+ ImFont* m_fixedFont;++ float m_rootWidth, m_rootHeight;+ SetTitleCallback m_stcb;+ bool m_titleSet = false;+ SetScaleCallback m_sscb;+ AttentionCallback m_acb;++ float m_notificationTime = 0;+ std::string m_notificationText;++ bool m_groupCallstackTreeByNameBottomUp = true;+ bool m_groupCallstackTreeByNameTopDown = true;+ MemRange m_memRangeBottomUp = MemRange::Full;+ MemRange m_memRangeTopDown = MemRange::Full;++ enum class SaveThreadState+ {+ Inert,+ Saving,+ NeedsJoin+ };++ enum+ {+ FindMatchingZoneFlagDefault = 0,+ FindMatchingZoneFlagSourceFile = (1 << 0),+ FindMatchingZoneFlagLineNum = (1 << 1),+ };++ std::atomic<SaveThreadState> m_saveThreadState { SaveThreadState::Inert };+ std::thread m_saveThread;+ std::atomic<size_t> m_srcFileBytes { 0 };+ std::atomic<size_t> m_dstFileBytes { 0 };++ ImTextureID m_frameTexture = 0;+ const void* m_frameTexturePtr = nullptr;++ ImTextureID m_frameTextureConn = 0;+ const void* m_frameTextureConnPtr = nullptr;++ std::vector<std::unique_ptr<Annotation>> m_annotations;+ UserData m_userData;++ bool m_wasActive = false;+ bool m_reconnectRequested = false;+ bool m_firstFrame = true;+ std::chrono::time_point<std::chrono::high_resolution_clock> m_firstFrameTime;+ float m_yDelta;++ std::vector<SourceRegex> m_sourceSubstitutions;+ bool m_sourceRegexValid = true;+ bool m_validateSourceAge = true;++ RangeSlim m_setRangePopup;+ bool m_setRangePopupOpen = false;++ unordered_flat_map<int16_t, StatisticsCache> m_statCache;+ unordered_flat_map<int16_t, StatisticsCache> m_gpuStatCache;++ unordered_flat_map<const void*, bool> m_visMap;++ void(*m_cbMainThread)(const std::function<void()>&, bool);++ int m_gpuIdx = 0;++ struct FindZone {+ enum : uint64_t { Unselected = std::numeric_limits<uint64_t>::max() - 1 };+ enum class GroupBy : int { Thread, UserText, ZoneName, Callstack, Parent, NoGrouping };+ enum class SortBy : int { Order, Count, Time, Mtpc };++ struct Group+ {+ uint16_t id;+ Vector<short_ptr<ZoneEvent>> zones;+ Vector<uint16_t> zonesTids;+ int64_t time = 0;+ };++ bool hasResults = false;+ bool show = false;+ bool ignoreCase = false;+ std::vector<int16_t> match;+ unordered_flat_map<uint64_t, Group> groups;+ size_t processed;+ uint16_t groupId;+ int selMatch = 0;+ uint64_t selGroup = Unselected;+ char pattern[1024] = {};+ bool logVal = false;+ bool logTime = true;+ bool cumulateTime = false;+ bool selfTime = false;+ bool runningTime = false;+ GroupBy groupBy = GroupBy::Thread;+ SortBy sortBy = SortBy::Count;+ Region highlight;+ int64_t hlOrig_t0, hlOrig_t1;+ int64_t numBins = -1;+ std::unique_ptr<int64_t[]> bins, binTime, selBin;+ Vector<int64_t> sorted, selSort;+ size_t sortedNum = 0, selSortNum, selSortActive;+ float average, selAverage;+ float median, selMedian;+ float p75, p90;+ int64_t total, selTotal;+ int64_t selTime;+ bool drawAvgMed = true;+ bool drawSelAvgMed = true;+ bool scheduleResetMatch = false;+ int selCs = 0;+ int minBinVal = 1;+ int64_t tmin, tmax;+ bool showZoneInFrames = false;+ Range range;+ RangeSlim rangeSlim;++ struct+ {+ int numBins = -1;+ ptrdiff_t distBegin;+ ptrdiff_t distEnd;+ } binCache;++ struct {+ Vector<SymList> counts;+ bool scheduleUpdate = false;+ bool enabled = false;+ } samples;++ void Reset()+ {+ ResetMatch();+ match.clear();+ selMatch = 0;+ selGroup = Unselected;+ highlight.active = false;+ samples.counts.clear();+ hasResults = false;+ }++ void ResetMatch()+ {+ ResetGroups();+ sorted.clear();+ sortedNum = 0;+ average = 0;+ median = 0;+ p75 = 0;+ p90 = 0;+ total = 0;+ tmin = std::numeric_limits<int64_t>::max();+ tmax = std::numeric_limits<int64_t>::min();+ }++ void ResetGroups()+ {+ ResetSelection();+ groups.clear();+ processed = 0;+ groupId = 0;+ selCs = 0;+ selGroup = Unselected;+ }++ void ResetSelection()+ {+ selSort.clear();+ selSortNum = 0;+ selSortActive = 0;+ selAverage = 0;+ selMedian = 0;+ selTotal = 0;+ selTime = 0;+ binCache.numBins = -1;+ samples.scheduleUpdate = true;+ }++ void ShowZone( int16_t srcloc, const char* name )+ {+ show = true;+ range.active = false;+ Reset();+ match.emplace_back( srcloc );+ strcpy( pattern, name );+ }++ void ShowZone( int16_t srcloc, const char* name, int64_t limitMin, int64_t limitMax )+ {+ assert( limitMin <= limitMax );+ show = true;+ range.active = true;+ range.min = limitMin;+ range.max = limitMax;+ Reset();+ match.emplace_back( srcloc );+ strcpy( pattern, name );+ }+ } m_findZone;++ tracy_force_inline uint64_t GetSelectionTarget( const Worker::ZoneThreadData& ev, FindZone::GroupBy groupBy ) const;++ struct CompVal+ {+ double v0;+ double v1;+ };++ struct {+ bool show = false;+ bool ignoreCase = false;+ bool link = true;+ std::unique_ptr<Worker> second;+ std::unique_ptr<UserData> userData;+ std::thread loadThread;+ BadVersionState badVer;+ char pattern[1024] = {};+ std::vector<int16_t> match[2];+ int selMatch[2] = { 0, 0 };+ bool logVal = false;+ bool logTime = true;+ bool cumulateTime = false;+ bool normalize = true;+ int64_t numBins = -1;+ std::unique_ptr<CompVal[]> bins, binTime;+ std::vector<int64_t> sorted[2];+ size_t sortedNum[2] = { 0, 0 };+ float average[2];+ float median[2];+ int64_t total[2];+ int minBinVal = 1;+ int compareMode = 0;+ bool diffDone = false;+ bool diffDirection;+ std::vector<const char*> thisUnique;+ std::vector<const char*> secondUnique;+ std::vector<std::pair<const char*, std::string>> diffs;++ void ResetSelection()+ {+ for( int i=0; i<2; i++ )+ {+ sorted[i].clear();+ sortedNum[i] = 0;+ average[i] = 0;+ median[i] = 0;+ total[i] = 0;+ }+ }++ void Reset()+ {+ ResetSelection();+ for( int i=0; i<2; i++ )+ {+ match[i].clear();+ selMatch[i] = 0;+ }+ diffDone = false;+ thisUnique.clear();+ secondUnique.clear();+ diffs.clear();+ }+ } m_compare;++ struct {+ bool show = false;+ char pattern[1024] = {};+ uint64_t ptrFind = 0;+ uint64_t pool = 0;+ bool showAllocList = false;+ std::vector<size_t> allocList;+ Range range;+ } m_memInfo;++ struct {+ std::vector<int64_t> data;+ const FrameData* frameSet = nullptr;+ size_t frameNum = 0;+ float average = 0;+ float median = 0;+ int64_t total = 0;+ bool logVal = false;+ bool logTime = true;+ int64_t numBins = -1;+ std::unique_ptr<int64_t[]> bins;+ bool drawAvgMed = true;+ bool limitToView = false;+ std::pair<int, int> limitRange = { -1, 0 };+ int minBinVal = 1;+ } m_frameSortData;++ struct {+ std::pair<const ZoneEvent*, int64_t> zoneSelfTime = { nullptr, 0 };+ std::pair<const ZoneEvent*, int64_t> zoneSelfTime2 = { nullptr, 0 };+ std::pair<const GpuEvent*, int64_t> gpuSelfTime = { nullptr, 0 };+ std::pair<const GpuEvent*, int64_t> gpuSelfTime2 = { nullptr, 0 };+ } m_cache;++ struct {+ ImTextureID texture = 0;+ float timeLeft = 0;+ float speed = 1;+ uint32_t frame = 0;+ uint32_t currFrame = -1;+ bool pause = true;+ bool sync = false;+ bool zoom = false;+ } m_playback;++ struct TimeDistribution {+ bool runningTime = false;+ bool exclusiveTime = true;+ unordered_flat_map<int16_t, ZoneTimeData> data;+ const ZoneEvent* dataValidFor = nullptr;+ float fztime;+ } m_timeDist;++ struct {+ uint64_t symAddr = 0;+ int sel;+ bool withInlines = false;+ int mode = 0;+ bool groupBottomUp = true;+ bool groupTopDown = true;+ } m_sampleParents;++ struct+ {+ bool enabled = false;+ bool monitor = false;+ int64_t time;+ } m_sendQueueWarning;++ bool m_attnProtoMismatch = false;+ bool m_attnNotAvailable = false;+ bool m_attnDropped = false;+ bool m_attnFailure = false;+ bool m_attnWorking = false;+ bool m_attnDisconnected = false;++ AchievementsMgr* m_achievementsMgr;+ bool m_achievements = false;++ double m_horizontalScrollMultiplier = 1.0;+ double m_verticalScrollMultiplier = 1.0;++ TaskDispatch m_td;+ std::vector<FlameGraphItem> m_flameGraphData;+ struct+ {+ uint64_t count = 0;+ uint64_t lastTime = 0;+ RangeSlim range = {false, 0, 0};++ void Reset()+ {+ count = 0;+ lastTime = 0;+ }+ } m_flameGraphInvariant;+};++}++#endif
+ cbits/tracy/profiler/src/profiler/TracyViewData.hpp view
@@ -0,0 +1,82 @@+#ifndef __TRACYVIEWDATA_HPP__+#define __TRACYVIEWDATA_HPP__++#include <stdint.h>+#include <regex>++#include "TracyUtility.hpp"++namespace tracy+{++struct Range+{+ void StartFrame() { hiMin = hiMax = false; }++ int64_t min = 0;+ int64_t max = 0;+ bool active = false;+ bool hiMin = false;+ bool hiMax = false;+ bool modMin = false;+ bool modMax = false;+};++struct RangeSlim+{+ bool operator==( const Range& other ) const { return other.active == active && other.min == min && other.max == max; }+ bool operator!=( const Range& other ) const { return !(*this == other); }+ void operator=( const Range& other ) { active = other.active; min = other.min; max = other.max; }++ int64_t min, max;+ bool active = false;+};+++struct ViewData+{+ int64_t zvStart = 0;+ int64_t zvEnd = 0;+ int32_t frameScale = 0;+ int32_t frameStart = 0;++ uint8_t drawGpuZones = true;+ uint8_t drawZones = true;+ uint8_t drawLocks = true;+ uint8_t drawPlots = true;+ uint8_t onlyContendedLocks = true;+ uint8_t drawEmptyLabels = false;+ uint8_t drawFrameTargets = false;+ uint8_t drawContextSwitches = true;+ uint8_t darkenContextSwitches = true;+ uint8_t drawCpuData = true;+ uint8_t drawCpuUsageGraph = true;+ uint8_t drawSamples = true;+ uint8_t dynamicColors = 1;+ uint8_t inheritParentColors = true;+ uint8_t forceColors = false;+ uint8_t ghostZones = true;+ ShortenName shortenName = ShortenName::NoSpaceAndNormalize;++ uint32_t frameTarget = 60;++ uint32_t plotHeight = 100;+};++struct Annotation+{+ std::string text;+ Range range;+ uint32_t color;+};++struct SourceRegex+{+ std::string pattern;+ std::string target;+ std::regex regex;+};++}++#endif
+ cbits/tracy/profiler/src/profiler/TracyView_Annotations.cpp view
@@ -0,0 +1,158 @@+#include "TracyImGui.hpp"+#include "TracyPrint.hpp"+#include "TracyView.hpp"+#include "tracy_pdqsort.h"++namespace tracy+{++void View::AddAnnotation( int64_t start, int64_t end )+{+ auto ann = std::make_unique<Annotation>();+ ann->range.active = true;+ ann->range.min = start;+ ann->range.max = end;+ ann->color = 0x888888;+ m_selectedAnnotation = ann.get();+ m_annotations.emplace_back( std::move( ann ) );+ pdqsort_branchless( m_annotations.begin(), m_annotations.end(), []( const auto& lhs, const auto& rhs ) { return lhs->range.min < rhs->range.min; } );+}++void View::DrawSelectedAnnotation()+{+ assert( m_selectedAnnotation );+ bool show = true;+ ImGui::Begin( "Annotation", &show, ImGuiWindowFlags_AlwaysAutoResize );+ if( !ImGui::GetCurrentWindowRead()->SkipItems )+ {+ if( ImGui::Button( ICON_FA_MICROSCOPE " Zoom to annotation" ) )+ {+ ZoomToRange( m_selectedAnnotation->range.min, m_selectedAnnotation->range.max );+ }+ ImGui::SameLine();+ if( ImGui::Button( ICON_FA_TRASH_CAN " Remove" ) )+ {+ for( auto it = m_annotations.begin(); it != m_annotations.end(); ++it )+ {+ if( it->get() == m_selectedAnnotation )+ {+ m_annotations.erase( it );+ break;+ }+ }+ ImGui::End();+ m_selectedAnnotation = nullptr;+ return;+ }+ ImGui::Separator();+ {+ const auto desc = m_selectedAnnotation->text.c_str();+ const auto descsz = std::min<size_t>( 1023, m_selectedAnnotation->text.size() );+ char buf[1024];+ buf[descsz] = '\0';+ memcpy( buf, desc, descsz );+ if( ImGui::InputTextWithHint( "##anndesc", "Describe annotation", buf, 256 ) )+ {+ m_selectedAnnotation->text.assign( buf );+ }+ }+ ImVec4 col = ImGui::ColorConvertU32ToFloat4( m_selectedAnnotation->color );+ ImGui::ColorEdit3( "Color", &col.x );+ m_selectedAnnotation->color = ImGui::ColorConvertFloat4ToU32( col );+ ImGui::Separator();+ TextFocused( "Annotation begin:", TimeToStringExact( m_selectedAnnotation->range.min ) );+ TextFocused( "Annotation end:", TimeToStringExact( m_selectedAnnotation->range.max ) );+ TextFocused( "Annotation length:", TimeToString( m_selectedAnnotation->range.max - m_selectedAnnotation->range.min ) );+ }+ ImGui::End();+ if( !show ) m_selectedAnnotation = nullptr;+}++void View::DrawAnnotationList()+{+ const auto scale = GetScale();+ ImGui::SetNextWindowSize( ImVec2( 600 * scale, 300 * scale ), ImGuiCond_FirstUseEver );+ ImGui::Begin( "Annotation list", &m_showAnnotationList );+ if( ImGui::GetCurrentWindowRead()->SkipItems ) { ImGui::End(); return; }++ if( ImGui::Button( ICON_FA_PLUS " Add annotation" ) )+ {+ AddAnnotation( m_vd.zvStart, m_vd.zvEnd );+ }++ if( m_annotations.empty() )+ {+ ImGui::Separator();+ ImGui::PushFont( m_bigFont );+ ImGui::Dummy( ImVec2( 0, ( ImGui::GetContentRegionAvail().y - ImGui::GetTextLineHeight() * 2 ) * 0.5f ) );+ TextCentered( ICON_FA_HORSE );+ TextCentered( "No annotations" );+ ImGui::PopFont();+ ImGui::End();+ return;+ }+ else+ {+ ImGui::SameLine();+ ImGui::SeparatorEx( ImGuiSeparatorFlags_Vertical );+ ImGui::SameLine();+ }++ TextFocused( "Annotations:", RealToString( m_annotations.size() ) );+ ImGui::Separator();+ ImGui::BeginChild( "##annotationList" );+ const bool ctrl = ImGui::GetIO().KeyCtrl;+ int remove = -1;+ int idx = 0;+ for( auto& ann : m_annotations )+ {+ ImGui::PushID( idx );+ if( ImGui::Button( ICON_FA_PEN_TO_SQUARE ) )+ {+ m_selectedAnnotation = ann.get();+ }+ ImGui::SameLine();+ if( ImGui::Button( ICON_FA_MICROSCOPE ) )+ {+ ZoomToRange( ann->range.min, ann->range.max );+ }+ ImGui::SameLine();+ if( ButtonDisablable( ICON_FA_TRASH_CAN, !ctrl ) )+ {+ remove = idx;+ }+ if( !ctrl ) TooltipIfHovered( "Press ctrl key to enable removal" );+ ImGui::SameLine();+ ImGui::ColorButton( "c", ImGui::ColorConvertU32ToFloat4( ann->color ), ImGuiColorEditFlags_NoTooltip );+ ImGui::SameLine();+ if( m_selectedAnnotation == ann.get() )+ {+ bool t = true;+ ImGui::Selectable( "##annSelectable", &t );+ ImGui::SameLine( 0, 0 );+ }+ if( ann->text.empty() )+ {+ TextDisabledUnformatted( "Empty annotation" );+ }+ else+ {+ ImGui::TextUnformatted( ann->text.c_str() );+ }+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::TextDisabled( "%s - %s (%s)", TimeToStringExact( ann->range.min ), TimeToStringExact( ann->range.max ), TimeToString( ann->range.max - ann->range.min ) );+ ImGui::PopID();+ idx++;+ }+ if( remove >= 0 )+ {+ if( m_annotations[remove].get() == m_selectedAnnotation ) m_selectedAnnotation = nullptr;+ m_annotations.erase( m_annotations.begin() + remove );+ }+ ImGui::EndChild();+ ImGui::End();+}++}
+ cbits/tracy/profiler/src/profiler/TracyView_Callstack.cpp view
@@ -0,0 +1,578 @@+#include <inttypes.h>+#include <sstream>++#include "../public/common/TracyStackFrames.hpp"+#include "TracyImGui.hpp"+#include "TracyPrint.hpp"+#include "TracyUtility.hpp"+#include "TracyView.hpp"++namespace tracy+{++void View::DrawCallstackWindow()+{+ bool show = true;+ const auto scale = GetScale();+ ImGui::SetNextWindowSize( ImVec2( 1400 * scale, 500 * scale ), ImGuiCond_FirstUseEver );+ ImGui::Begin( "Call stack", &show, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse );+ if( !ImGui::GetCurrentWindowRead()->SkipItems )+ {+ DrawCallstackTable( m_callstackInfoWindow, true );+ }+ ImGui::End();+ if( !show ) m_callstackInfoWindow = 0;+}++void View::DrawCallstackTable( uint32_t callstack, bool globalEntriesButton )+{+ auto& cs = m_worker.GetCallstack( callstack );+ if( ClipboardButton() )+ {+ std::ostringstream s;+ int fidx = 0;+ for( auto& entry : cs )+ {+ char buf[64*1024];+ auto frameData = m_worker.GetCallstackFrame( entry );+ if( !frameData )+ {+ sprintf( buf, "%3i. %p\n", fidx++, (void*)m_worker.GetCanonicalPointer( entry ) );+ }+ else+ {+ auto ptr = buf;+ const auto fsz = frameData->size;+ for( uint8_t f=0; f<fsz; f++ )+ {+ const auto& frame = frameData->data[f];+ auto txt = m_worker.GetString( frame.name );++ if( fidx == 0 && f != fsz-1 )+ {+ auto test = tracy::s_tracyStackFrames;+ bool match = false;+ do+ {+ if( strcmp( txt, *test ) == 0 )+ {+ match = true;+ break;+ }+ }+ while( *++test );+ if( match ) continue;+ }++ if( f == fsz-1 )+ {+ ptr += sprintf( ptr, "%3i. ", fidx++ );+ }+ else+ {+ ptr += sprintf( ptr, "inl. " );+ }+ ptr += sprintf( ptr, "%s ", txt );+ txt = m_worker.GetString( frame.file );+ if( frame.line == 0 )+ {+ ptr += sprintf( ptr, "(%s)", txt );+ }+ else+ {+ ptr += sprintf( ptr, "(%s:%" PRIu32 ")", txt, frame.line );+ }+ if( frameData->imageName.Active() )+ {+ ptr += sprintf( ptr, " %s\n", m_worker.GetString( frameData->imageName ) );+ }+ else+ {+ ptr += sprintf( ptr, "\n" );+ }+ }+ }+ s << buf;+ }+ ImGui::SetClipboardText( s.str().c_str() );+ }+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ SmallCheckbox( ICON_FA_SHIELD_HALVED " External frames", &m_showExternalFrames );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ SmallCheckbox( ICON_FA_SCISSORS " Short images", &m_shortImageNames );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::TextUnformatted( ICON_FA_AT " Frame location:" );+ ImGui::SameLine();+ ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 0, 0 ) );+ ImGui::RadioButton( "Source code", &m_showCallstackFrameAddress, 0 );+ ImGui::SameLine();+ ImGui::RadioButton( "Entry point", &m_showCallstackFrameAddress, 3 );+ ImGui::SameLine();+ ImGui::RadioButton( "Return address", &m_showCallstackFrameAddress, 1 );+ ImGui::SameLine();+ ImGui::RadioButton( "Symbol address", &m_showCallstackFrameAddress, 2 );++ if( globalEntriesButton && m_worker.AreCallstackSamplesReady() )+ {+ auto frame = m_worker.GetCallstackFrame( *cs.begin() );+ if( frame && frame->data[0].symAddr != 0 )+ {+ auto sym = m_worker.GetSymbolStats( frame->data[0].symAddr );+ if( sym && !sym->parents.empty() )+ {+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ if( ImGui::Button( ICON_FA_DOOR_OPEN " Global entry statistics" ) )+ {+ ShowSampleParents( frame->data[0].symAddr, true );+ }+ }+ }+ }+ ImGui::PopStyleVar();++ ImGui::Separator();+ if( ImGui::BeginTable( "##callstack", 4, ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders | ImGuiTableFlags_ScrollY ) )+ {+ ImGui::TableSetupScrollFreeze( 0, 1 );+ ImGui::TableSetupColumn( "Frame", ImGuiTableColumnFlags_NoHide | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize );+ ImGui::TableSetupColumn( "Function" );+ ImGui::TableSetupColumn( "Location" );+ ImGui::TableSetupColumn( "Image" );+ ImGui::TableHeadersRow();++ int external = 0;+ int fidx = 0;+ int bidx = 0;+ for( auto& entry : cs )+ {+ auto frameData = m_worker.GetCallstackFrame( entry );+ if( !frameData )+ {+ if( !m_showExternalFrames )+ {+ external++;+ continue;+ }+ ImGui::TableNextRow();+ ImGui::TableNextColumn();+ ImGui::Text( "%i", fidx++ );+ ImGui::TableNextColumn();+ char buf[32];+ sprintf( buf, "%p", (void*)m_worker.GetCanonicalPointer( entry ) );+ ImGui::TextUnformatted( buf );+ if( ImGui::IsItemClicked() )+ {+ ImGui::SetClipboardText( buf );+ }+ }+ else+ {+ const auto fsz = frameData->size;+ for( uint8_t f=0; f<fsz; f++ )+ {+ const auto& frame = frameData->data[f];+ auto txt = m_worker.GetString( frame.name );++ if( fidx == 0 && f != fsz-1 )+ {+ auto test = s_tracyStackFrames;+ bool match = false;+ do+ {+ if( strcmp( txt, *test ) == 0 )+ {+ match = true;+ break;+ }+ }+ while( *++test );+ if( match ) continue;+ }++ auto filename = m_worker.GetString( frame.file );+ auto image = frameData->imageName.Active() ? m_worker.GetString( frameData->imageName ) : nullptr;++ if( IsFrameExternal( filename, image ) )+ {+ if( !m_showExternalFrames )+ {+ if( f == fsz-1 ) fidx++;+ external++;+ continue;+ }+ }+ else if( external != 0 )+ {+ ImGui::TableNextRow();+ ImGui::TableNextColumn();+ ImGui::PushFont( m_smallFont );+ TextDisabledUnformatted( "external" );+ ImGui::TableNextColumn();+ if( external == 1 )+ {+ TextDisabledUnformatted( "1 frame" );+ }+ else+ {+ ImGui::TextDisabled( "%i frames", external );+ }+ ImGui::PopFont();+ external = 0;+ }++ ImGui::TableNextRow();+ ImGui::TableNextColumn();+ bidx++;+ if( f == fsz-1 )+ {+ ImGui::Text( "%i", fidx++ );+ }+ else+ {+ ImGui::PushFont( m_smallFont );+ TextDisabledUnformatted( "inline" );+ ImGui::PopFont();+ }+ ImGui::TableNextColumn();+ {+ ImGui::PushTextWrapPos( 0.0f );+ if( txt[0] == '[' )+ {+ TextDisabledUnformatted( txt );+ }+ else if( m_worker.GetCanonicalPointer( entry ) >> 63 != 0 )+ {+ TextColoredUnformatted( 0xFF8888FF, txt );+ }+ else if( m_vd.shortenName == ShortenName::Never )+ {+ ImGui::TextUnformatted( txt );+ }+ else+ {+ const auto normalized = ShortenZoneName( ShortenName::OnlyNormalize, txt );+ ImGui::TextUnformatted( normalized );+ TooltipNormalizedName( txt, normalized );+ }+ ImGui::PopTextWrapPos();+ }+ if( ImGui::IsItemClicked() )+ {+ ImGui::SetClipboardText( txt );+ }+ ImGui::TableNextColumn();+ ImGui::PushTextWrapPos( 0.0f );+ float indentVal = 0.f;+ if( m_callstackBuzzAnim.Match( bidx ) )+ {+ const auto time = m_callstackBuzzAnim.Time();+ indentVal = sin( time * 60.f ) * 10.f * time;+ ImGui::Indent( indentVal );+ }+ switch( m_showCallstackFrameAddress )+ {+ case 0:+ TextDisabledUnformatted( LocationToString( filename, frame.line ) );+ if( ImGui::IsItemClicked() )+ {+ ImGui::SetClipboardText( LocationToString( filename, frame.line ) );+ }+ break;+ case 1:+ if( entry.sel == 0 )+ {+ const auto addr = m_worker.GetCanonicalPointer( entry );+ ImGui::TextDisabled( "0x%" PRIx64, addr );+ if( ImGui::IsItemClicked() )+ {+ char tmp[32];+ sprintf( tmp, "0x%" PRIx64, addr );+ ImGui::SetClipboardText( tmp );+ }+ }+ else+ {+ ImGui::TextDisabled( "Custom #%" PRIu64, entry.idx );+ }+ break;+ case 2:+ if( entry.sel == 0 )+ {+ ImGui::TextDisabled( "0x%" PRIx64, frame.symAddr );+ if( ImGui::IsItemClicked() )+ {+ char tmp[32];+ sprintf( tmp, "0x%" PRIx64, frame.symAddr );+ ImGui::SetClipboardText( tmp );+ }+ }+ else+ {+ ImGui::TextDisabled( "Custom #%" PRIu64, entry.idx );+ }+ break;+ case 3:+ {+ const auto sym = m_worker.GetSymbolData( frame.symAddr );+ if( sym )+ {+ const auto symtxt = m_worker.GetString( sym->file );+ TextDisabledUnformatted( LocationToString( symtxt, sym->line ) );+ if( ImGui::IsItemClicked() )+ {+ ImGui::SetClipboardText( symtxt );+ }+ }+ else+ {+ TextDisabledUnformatted( "[unknown]" );+ }+ break;+ }+ default:+ assert( false );+ break;+ }+ if( ImGui::IsItemHovered() )+ {+ if( m_showCallstackFrameAddress == 3 )+ {+ const auto sym = m_worker.GetSymbolData( frame.symAddr );+ if( sym )+ {+ const auto symtxt = m_worker.GetString( sym->file );+ DrawSourceTooltip( symtxt, sym->line );+ }+ }+ else+ {+ DrawSourceTooltip( filename, frame.line );+ }+ if( ImGui::IsItemClicked( 1 ) )+ {+ if( m_showCallstackFrameAddress == 3 )+ {+ const auto sym = m_worker.GetSymbolData( frame.symAddr );+ if( sym )+ {+ const auto symtxt = m_worker.GetString( sym->file );+ if( !ViewDispatch( symtxt, sym->line, frame.symAddr ) )+ {+ m_callstackBuzzAnim.Enable( bidx, 0.5f );+ }+ }+ else+ {+ m_callstackBuzzAnim.Enable( bidx, 0.5f );+ }+ }+ else+ {+ if( !ViewDispatch( filename, frame.line, frame.symAddr ) )+ {+ m_callstackBuzzAnim.Enable( bidx, 0.5f );+ }+ }+ }+ }+ if( indentVal != 0.f )+ {+ ImGui::Unindent( indentVal );+ }+ ImGui::PopTextWrapPos();+ ImGui::TableNextColumn();+ if( image )+ {+ const char* end = image + strlen( image );++ if( m_shortImageNames )+ {+ const char* ptr = end - 1;+ while( ptr > image && *ptr != '/' && *ptr != '\\' ) ptr--;+ if( *ptr == '/' || *ptr == '\\' ) ptr++;+ const auto cw = ImGui::GetContentRegionAvail().x;+ const auto tw = ImGui::CalcTextSize( image, end ).x;+ TextDisabledUnformatted( ptr );+ if( ptr != image || tw > cw ) TooltipIfHovered( image );+ }+ else+ {+ const auto cw = ImGui::GetContentRegionAvail().x;+ const auto tw = ImGui::CalcTextSize( image, end ).x;+ TextDisabledUnformatted( image );+ if( tw > cw ) TooltipIfHovered( image );+ }+ }+ }+ }+ }+ if( external != 0 )+ {+ ImGui::TableNextRow();+ ImGui::TableNextColumn();+ ImGui::PushFont( m_smallFont );+ TextDisabledUnformatted( "external" );+ ImGui::TableNextColumn();+ if( external == 1 )+ {+ TextDisabledUnformatted( "1 frame" );+ }+ else+ {+ ImGui::TextDisabled( "%i frames", external );+ }+ ImGui::PopFont();+ }+ ImGui::EndTable();+ }+}++void View::SmallCallstackButton( const char* name, uint32_t callstack, int& idx, bool tooltip )+{+ bool hilite = m_callstackInfoWindow == callstack;+ if( hilite )+ {+ SetButtonHighlightColor();+ }+ ImGui::PushID( idx++ );+ if( ImGui::SmallButton( name ) )+ {+ m_callstackInfoWindow = callstack;+ }+ ImGui::PopID();+ if( hilite )+ {+ ImGui::PopStyleColor( 3 );+ }+ if( tooltip && ImGui::IsItemHovered() )+ {+ CallstackTooltip( callstack );+ }+}++void View::DrawCallstackCalls( uint32_t callstack, uint16_t limit ) const+{+ const auto& csdata = m_worker.GetCallstack( callstack );+ const auto cssz = std::min( csdata.size(), limit );+ bool first = true;+ for( uint16_t i=0; i<cssz; i++ )+ {+ const auto frameData = m_worker.GetCallstackFrame( csdata[i] );+ if( !frameData ) break;+ if( first )+ {+ first = false;+ }+ else+ {+ ImGui::SameLine();+ TextDisabledUnformatted( ICON_FA_LEFT_LONG );+ ImGui::SameLine();+ }+ const auto& frame = frameData->data[frameData->size - 1];+ auto txt = m_worker.GetString( frame.name );+ if( txt[0] == '[' )+ {+ TextDisabledUnformatted( txt );+ }+ else if( m_vd.shortenName == ShortenName::Never )+ {+ ImGui::TextUnformatted( txt );+ }+ else+ {+ ImGui::TextUnformatted( ShortenZoneName( ShortenName::Always, txt ) );+ }+ }+}++void View::CallstackTooltip( uint32_t idx )+{+ ImGui::BeginTooltip();+ CallstackTooltipContents( idx );+ ImGui::EndTooltip();+}++void View::CallstackTooltipContents( uint32_t idx )+{+ auto& cs = m_worker.GetCallstack( idx );+ int fidx = 0;+ for( auto& entry : cs )+ {+ auto frameData = m_worker.GetCallstackFrame( entry );+ if( !frameData )+ {+ ImGui::TextDisabled( "%i.", fidx++ );+ ImGui::SameLine();+ ImGui::Text( "%p", (void*)m_worker.GetCanonicalPointer( entry ) );+ }+ else+ {+ const auto fsz = frameData->size;+ for( uint8_t f=0; f<fsz; f++ )+ {+ const auto& frame = frameData->data[f];+ auto txt = m_worker.GetString( frame.name );++ if( fidx == 0 && f != fsz-1 )+ {+ auto test = s_tracyStackFrames;+ bool match = false;+ do+ {+ if( strcmp( txt, *test ) == 0 )+ {+ match = true;+ break;+ }+ }+ while( *++test );+ if( match ) continue;+ }+ if( f == fsz-1 )+ {+ ImGui::TextDisabled( "%i.", fidx++ );+ }+ else+ {+ TextDisabledUnformatted( ICON_FA_CARET_RIGHT );+ }+ ImGui::SameLine();+ if( txt[0] == '[' )+ {+ TextDisabledUnformatted( txt );+ }+ else if( m_worker.GetCanonicalPointer( entry ) >> 63 != 0 )+ {+ TextColoredUnformatted( 0xFF8888FF, txt );+ }+ else if( m_vd.shortenName == ShortenName::Never )+ {+ ImGui::TextUnformatted( txt );+ }+ else+ {+ ImGui::TextUnformatted( ShortenZoneName( ShortenName::OnlyNormalize, txt ) );+ }+ if( frameData->imageName.Active() )+ {+ ImGui::SameLine();+ ImGui::PushFont( m_smallFont );+ ImGui::AlignTextToFramePadding();+ TextDisabledUnformatted( m_worker.GetString( frameData->imageName ) );+ ImGui::PopFont();+ }+ }+ }+ }+}++}
+ cbits/tracy/profiler/src/profiler/TracyView_Compare.cpp view
@@ -0,0 +1,1331 @@+#include <numeric>+#include <sstream>++#include "../dtl/dtl.hpp"++#include "TracyImGui.hpp"+#include "TracyFileRead.hpp"+#include "TracyFileselector.hpp"+#include "TracyPrint.hpp"+#include "TracyView.hpp"+#include "tracy_pdqsort.h"++namespace tracy+{++extern double s_time;++#ifndef TRACY_NO_STATISTICS+ void View::FindZonesCompare()+ {+ m_compare.match[0] = m_worker.GetMatchingSourceLocation( m_compare.pattern, m_compare.ignoreCase );+ if( !m_compare.match[0].empty() )+ {+ auto it = m_compare.match[0].begin();+ while( it != m_compare.match[0].end() )+ {+ if( m_worker.GetZonesForSourceLocation( *it ).zones.empty() )+ {+ it = m_compare.match[0].erase( it );+ }+ else+ {+ ++it;+ }+ }+ }++ m_compare.match[1] = m_compare.second->GetMatchingSourceLocation( m_compare.pattern, m_compare.ignoreCase );+ if( !m_compare.match[1].empty() )+ {+ auto it = m_compare.match[1].begin();+ while( it != m_compare.match[1].end() )+ {+ if( m_compare.second->GetZonesForSourceLocation( *it ).zones.empty() )+ {+ it = m_compare.match[1].erase( it );+ }+ else+ {+ ++it;+ }+ }+ }+ }+#endif++bool View::FindMatchingZone( int prev0, int prev1, int flags )+{+ int idx = 0;+ bool found = false;+ auto& srcloc0 = m_worker.GetSourceLocation( m_compare.match[0][m_compare.selMatch[0]] );+ auto& srcloc1 = m_compare.second->GetSourceLocation( m_compare.match[1][m_compare.selMatch[1]] );+ auto string0 = m_worker.GetString( srcloc0.name.active ? srcloc0.name : srcloc0.function );+ auto string1 = m_compare.second->GetString( srcloc1.name.active ? srcloc1.name : srcloc1.function );+ auto file0 = m_worker.GetString( srcloc0.file );+ auto file1 = m_compare.second->GetString( srcloc1.file );+ bool wrongFile = false;+ bool wrongLine = false;+ if( flags & FindMatchingZoneFlagSourceFile )+ {+ wrongFile = strcmp( file0, file1 ) != 0;+ }+ if( flags & FindMatchingZoneFlagLineNum )+ {+ wrongLine = srcloc0.line != srcloc1.line;+ }++ if( strcmp( string0, string1 ) != 0 || wrongFile || wrongLine )+ {+ if( prev0 != m_compare.selMatch[0] )+ {+ for( auto& v : m_compare.match[1] )+ {+ auto& srcloc = m_compare.second->GetSourceLocation( v );+ auto string = m_compare.second->GetString( srcloc.name.active ? srcloc.name : srcloc.function );+ auto file = m_compare.second->GetString( srcloc.file );+ bool sameFile = true;+ bool sameLine = true;+ if( flags & FindMatchingZoneFlagSourceFile )+ {+ sameFile = strcmp( file0, file ) == 0;+ }+ if( flags & FindMatchingZoneFlagLineNum )+ {+ sameLine = srcloc0.line == srcloc.line;+ }+ if( strcmp( string0, string ) == 0 && sameFile && sameLine )+ {+ m_compare.selMatch[1] = idx;+ found = true;+ break;+ }+ idx++;+ }+ }+ else+ {+ assert( prev1 != m_compare.selMatch[1] );+ for( auto& v : m_compare.match[0] )+ {+ auto& srcloc = m_worker.GetSourceLocation( v );+ auto string = m_worker.GetString( srcloc.name.active ? srcloc.name : srcloc.function );+ auto file = m_worker.GetString( srcloc.file );+ bool sameFile = true;+ bool sameLine = true;+ if( flags & FindMatchingZoneFlagSourceFile )+ {+ sameFile = strcmp( file1, file ) == 0;+ }+ if( flags & FindMatchingZoneFlagLineNum )+ {+ sameLine = srcloc1.line == srcloc.line;+ }+ if( strcmp( string1, string ) == 0 && sameFile && sameLine )+ {+ m_compare.selMatch[0] = idx;+ found = true;+ break;+ }+ idx++;+ }++ }+ }+ return found;+}++static std::vector<std::string> SplitLines( const char* data, size_t sz )+{+ std::vector<std::string> ret;+ auto txt = data;+ for(;;)+ {+ auto end = txt;+ while( *end != '\n' && *end != '\r' && end - data < sz ) end++;+ ret.emplace_back( std::string { txt, end } );+ if( end - data == sz ) break;+ if( *end == '\n' )+ {+ end++;+ if( end - data < sz && *end == '\r' ) end++;+ }+ else if( *end == '\r' )+ {+ end++;+ if( end - data < sz && *end == '\n' ) end++;+ }+ if( end - data == sz ) break;+ txt = end;+ }+ return ret;+}++static void PrintFile( const char* data, size_t sz, uint32_t color )+{+ auto lines = SplitLines( data, sz );+ for( auto& v : lines )+ {+ TextColoredUnformatted( color, v.c_str() );+ }+}++static void PrintDiff( const std::string& diff )+{+ auto lines = SplitLines( diff.data(), diff.size() );+ for( auto& v : lines )+ {+ assert( !v.empty() );+ switch( v[0] )+ {+ case '@': TextColoredUnformatted( 0xFFFFAAAA, v.c_str() ); break;+ case '-': TextColoredUnformatted( 0xFF6666FF, v.c_str() ); break;+ case '+': TextColoredUnformatted( 0xFF66DD66, v.c_str() ); break;+ default: TextDisabledUnformatted( v.c_str() ); break;+ }+ }+}++static void PrintSpeedupOrSlowdown( double time_this, double time_external, const char *metric )+{+ const char* label;+ const char* time_diff = TimeToString( abs( time_external - time_this ) );+ ImVec4 color;+ double factor = time_this / time_external;+ if( time_external >= time_this )+ {+ label = "less";+ color = ImVec4( 0.1f, 0.6f, 0.1f, 1.0f );+ } else {+ label = "more";+ color = ImVec4( 0.8f, 0.1f, 0.1f, 1.0f );+ }+ ImGui::TextDisabled( "%s:", metric );+ ImGui::SameLine();+ ImGui::TextUnformatted( time_diff );+ ImGui::SameLine();+ TextColoredUnformatted( color, label );+ ImGui::SameLine();+ TextDisabledUnformatted( "than external" );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();++ TextDisabledUnformatted("(");+ ImGui::SameLine( 0, 0 );+ TextColoredUnformatted( ImVec4( 0xDD/511.f, 0xDD/511.f, 0x22/511.f, 1.f ), ICON_FA_LEMON );+ ImGui::SameLine();+ ImGui::TextDisabled("= %.2f%%", factor * 100 );+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 0xDD/511.f, 0x22/511.f, 0x22/511.f, 1.f ), ICON_FA_GEM );+ ImGui::SameLine( 0, 0 );+ TextDisabledUnformatted(")");+}++void View::DrawCompare()+{+ const auto scale = GetScale();+ ImGui::SetNextWindowSize( ImVec2( 590 * scale, 800 * scale ), ImGuiCond_FirstUseEver );+ ImGui::Begin( "Compare traces", &m_compare.show, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse );+ if( ImGui::GetCurrentWindowRead()->SkipItems ) { ImGui::End(); return; }+#ifdef TRACY_NO_STATISTICS+ ImGui::TextWrapped( "Collection of statistical data is disabled in this build." );+ ImGui::TextWrapped( "Rebuild without the TRACY_NO_STATISTICS macro to enable trace comparison." );+#elif defined TRACY_NO_FILESELECTOR+ ImGui::TextWrapped( "File selector is disabled in this build." );+ ImGui::TextWrapped( "Rebuild without the TRACY_NO_FILESELECTOR macro to enable trace comparison." );+#else+ if( !m_compare.second )+ {+ const auto ty = ImGui::GetTextLineHeight();+ ImGui::PushFont( m_bigFont );+ ImGui::Dummy( ImVec2( 0, ( ImGui::GetContentRegionAvail().y - ImGui::GetTextLineHeight() * 5 ) * 0.5f ) );+ TextCentered( ICON_FA_SCALE_BALANCED );+ TextCentered( "Please load a second trace to compare results" );+ ImGui::PopFont();+ ImGui::TextUnformatted( "" );+ if( ButtonCentered( ICON_FA_FOLDER_OPEN " Open second trace" ) && !m_compare.loadThread.joinable() )+ {+ Fileselector::OpenFile( "tracy", "Tracy Profiler trace file", [this]( const char* fn ) {+ try+ {+ auto f = std::shared_ptr<tracy::FileRead>( tracy::FileRead::Open( fn ) );+ if( f )+ {+ m_compare.loadThread = std::thread( [this, f] {+ try+ {+ m_compare.second = std::make_unique<Worker>( *f, EventType::SourceCache );+ m_compare.userData = std::make_unique<UserData>( m_compare.second->GetCaptureProgram().c_str(), m_compare.second->GetCaptureTime() );+ m_compare.diffDirection = m_worker.GetCaptureTime() < m_compare.second->GetCaptureTime();+ }+ catch( const tracy::UnsupportedVersion& e )+ {+ m_compare.badVer.state = BadVersionState::UnsupportedVersion;+ m_compare.badVer.version = e.version;+ }+ } );+ }+ }+ catch( const tracy::NotTracyDump& )+ {+ m_compare.badVer.state = BadVersionState::BadFile;+ }+ catch( const tracy::FileReadError& )+ {+ m_compare.badVer.state = BadVersionState::ReadError;+ }+ } );+ }+ tracy::BadVersion( m_compare.badVer, m_bigFont );+ ImGui::End();+ return;+ }++ if( m_compare.loadThread.joinable() ) m_compare.loadThread.join();++ if( !m_worker.AreSourceLocationZonesReady() || !m_compare.second->AreSourceLocationZonesReady() )+ {+ const auto ty = ImGui::GetTextLineHeight();+ ImGui::PushFont( m_bigFont );+ ImGui::Dummy( ImVec2( 0, ( ImGui::GetContentRegionAvail().y - ImGui::GetTextLineHeight() * 2 - ty ) * 0.5f ) );+ TextCentered( ICON_FA_FROG );+ TextCentered( "Please wait, computing data..." );+ ImGui::PopFont();+ DrawWaitingDots( s_time );+ ImGui::End();+ return;+ }++ TextColoredUnformatted( ImVec4( 0xDD/255.f, 0xDD/255.f, 0x22/255.f, 1.f ), ICON_FA_LEMON );+ ImGui::SameLine();+ TextDisabledUnformatted( "This trace:" );+ ImGui::SameLine();+ const auto& desc0 = m_userData.GetDescription();+ if( desc0.empty() )+ {+ ImGui::TextUnformatted( m_worker.GetCaptureName().c_str() );+ }+ else+ {+ ImGui::TextUnformatted( desc0.c_str() );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", m_worker.GetCaptureName().c_str() );+ }++ TextColoredUnformatted( ImVec4( 0xDD/255.f, 0x22/255.f, 0x22/255.f, 1.f ), ICON_FA_GEM );+ ImGui::SameLine();+ TextDisabledUnformatted( "External trace:" );+ ImGui::SameLine();+ const auto& desc1 = m_compare.userData->GetDescription();+ if( desc1.empty() )+ {+ ImGui::TextUnformatted( m_compare.second->GetCaptureName().c_str() );+ }+ else+ {+ ImGui::TextUnformatted( desc1.c_str() );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", m_compare.second->GetCaptureName().c_str() );+ }++ if( ImGui::Button( ICON_FA_TRASH_CAN " Unload" ) )+ {+ m_compare.Reset();+ m_compare.second.reset();+ m_compare.userData.reset();+ ImGui::End();+ return;+ }+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::Text( "Compare mode: " );+ ImGui::SameLine();+ const auto oldMode = m_compare.compareMode;+ ImGui::RadioButton( "Zones", &m_compare.compareMode, 0 );+ ImGui::SameLine();+ ImGui::RadioButton( "Frames", &m_compare.compareMode, 1 );+ ImGui::SameLine();+ ImGui::RadioButton( "Source diff", &m_compare.compareMode, 2 );+ if( oldMode != m_compare.compareMode )+ {+ m_compare.Reset();+ }++ if( m_compare.compareMode == 2 )+ {+ ImGui::Separator();+ ImGui::BeginChild( "##compare" );++ TextDisabledUnformatted( "Diff direction: " );+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 0xDD/255.f, 0xDD/255.f, 0x22/255.f, 1.f ), ICON_FA_LEMON );+ ImGui::SameLine();+ ImGui::Text( " %s ", m_compare.diffDirection ? ICON_FA_ARROW_RIGHT : ICON_FA_ARROW_LEFT );+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 0xDD/255.f, 0x22/255.f, 0x22/255.f, 1.f ), ICON_FA_GEM );+ ImGui::SameLine();+ if( ImGui::SmallButton( "Switch" ) )+ {+ m_compare.diffDirection = !m_compare.diffDirection;+ m_compare.Reset();+ }+ ImGui::Separator();++ ImGui::BeginChild( "##diff" );++ const auto& tfc = m_compare.diffDirection ? m_worker.GetSourceFileCache() : m_compare.second->GetSourceFileCache();+ const auto& ofc = m_compare.diffDirection ? m_compare.second->GetSourceFileCache() : m_worker.GetSourceFileCache();++ if( !m_compare.diffDone )+ {+ m_compare.diffDone = true;++ if( !tfc.empty() && !ofc.empty() )+ {+ for( auto& tv : tfc )+ {+ auto it = ofc.find( tv.first );+ if( it == ofc.end() )+ {+ m_compare.thisUnique.emplace_back( tv.first );+ }+ else if( tv.second.len != it->second.len || memcmp( tv.second.data, it->second.data, tv.second.len ) != 0 )+ {+ auto src0 = SplitLines( tv.second.data, tv.second.len );+ auto src1 = SplitLines( it->second.data, it->second.len );+ dtl::Diff<std::string, std::vector<std::string>> diff { src0, src1 };+ diff.compose();+ diff.composeUnifiedHunks();+ std::ostringstream stream;+ diff.printUnifiedFormat( stream );+ m_compare.diffs.emplace_back( std::make_pair( tv.first, stream.str() ) );+ }+ }+ for( auto& ov : ofc )+ {+ auto it = tfc.find( ov.first );+ if( it == tfc.end() )+ {+ m_compare.secondUnique.emplace_back( ov.first );+ }+ }++ pdqsort_branchless( m_compare.thisUnique.begin(), m_compare.thisUnique.end(), []( const auto& lhs, const auto& rhs ) { return strcmp( lhs, rhs ) < 0; } );+ pdqsort_branchless( m_compare.secondUnique.begin(), m_compare.secondUnique.end(), []( const auto& lhs, const auto& rhs ) { return strcmp( lhs, rhs ) < 0; } );+ pdqsort_branchless( m_compare.diffs.begin(), m_compare.diffs.end(), []( const auto& lhs, const auto& rhs ) { return strcmp( lhs.first, rhs.first ) < 0; } );+ }+ }++ if( m_compare.thisUnique.empty() && m_compare.secondUnique.empty() && m_compare.diffs.empty() )+ {+ ImGui::TextUnformatted( "Source files are identical." );+ }+ else+ {+ if( !m_compare.thisUnique.empty() )+ {+ const auto expand = ImGui::TreeNode( ICON_FA_FILE_CIRCLE_XMARK " Deleted files" );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( m_compare.thisUnique.size() ) );+ if( expand )+ {+ for( auto& v : m_compare.thisUnique )+ {+ if( ImGui::TreeNode( v ) )+ {+ auto it = tfc.find( v );+ assert( it != tfc.end() );+ ImGui::PushFont( m_fixedFont );+ ImGui::PushStyleVar( ImGuiStyleVar_ItemSpacing, ImVec2( 0, 0 ) );+ PrintFile( it->second.data, it->second.len, 0xFF6666FF );+ ImGui::PopStyleVar();+ ImGui::PopFont();+ ImGui::TreePop();+ }+ }+ ImGui::TreePop();+ }+ }+ if( !m_compare.secondUnique.empty() )+ {+ const auto expand = ImGui::TreeNode( ICON_FA_FILE_CIRCLE_PLUS " Added files" );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( m_compare.secondUnique.size() ) );+ if( expand )+ {+ for( auto& v : m_compare.secondUnique )+ {+ if( ImGui::TreeNode( v ) )+ {+ auto it = ofc.find( v );+ assert( it != ofc.end() );+ ImGui::PushFont( m_fixedFont );+ ImGui::PushStyleVar( ImGuiStyleVar_ItemSpacing, ImVec2( 0, 0 ) );+ PrintFile( it->second.data, it->second.len, 0xFF66DD66 );+ ImGui::PopStyleVar();+ ImGui::PopFont();+ ImGui::TreePop();+ }+ }+ ImGui::TreePop();+ }+ }+ if( !m_compare.diffs.empty() )+ {+ const auto expand = ImGui::TreeNodeEx( ICON_FA_FILE_PEN " Changed files", ImGuiTreeNodeFlags_DefaultOpen );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( m_compare.diffs.size() ) );+ if( expand )+ {+ for( auto& v : m_compare.diffs )+ {+ if( ImGui::TreeNode( v.first ) )+ {+ ImGui::PushFont( m_fixedFont );+ ImGui::PushStyleVar( ImGuiStyleVar_ItemSpacing, ImVec2( 0, 0 ) );+ PrintDiff( v.second );+ ImGui::PopStyleVar();+ ImGui::PopFont();+ ImGui::TreePop();+ }+ }++ ImGui::TreePop();+ }+ }+ }+ ImGui::EndChild();+ }+ else+ {+ bool findClicked = false;++ if( m_compare.compareMode == 0 )+ {+ ImGui::PushItemWidth( -0.01f );+ findClicked |= ImGui::InputTextWithHint( "###compare", "Enter zone name to search for", m_compare.pattern, 1024, ImGuiInputTextFlags_EnterReturnsTrue );+ ImGui::PopItemWidth();++ findClicked |= ImGui::Button( ICON_FA_MAGNIFYING_GLASS " Find" );+ ImGui::SameLine();++ if( ImGui::Button( ICON_FA_BAN " Clear" ) )+ {+ m_compare.Reset();+ }+ ImGui::SameLine();+ ImGui::Checkbox( "Ignore case", &m_compare.ignoreCase );++ if( findClicked )+ {+ m_compare.Reset();+ FindZonesCompare();+ }++ if( m_compare.match[0].empty() && m_compare.match[1].empty() )+ {+ ImGui::End();+ return;+ }++ ImGui::Separator();+ ImGui::BeginChild( "##compare" );++ if( ImGui::TreeNodeEx( "Matched source locations", ImGuiTreeNodeFlags_DefaultOpen ) )+ {+ ImGui::SameLine();+ SmallCheckbox( "Link selection", &m_compare.link );++ ImGui::Separator();+ ImGui::Columns( 2 );+ TextColoredUnformatted( ImVec4( 0xDD/255.f, 0xDD/255.f, 0x22/255.f, 1.f ), ICON_FA_LEMON );+ ImGui::SameLine();+ ImGui::TextUnformatted( "This trace" );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%zu)", m_compare.match[0].size() );+ ImGui::NextColumn();+ TextColoredUnformatted( ImVec4( 0xDD/255.f, 0x22/255.f, 0x22/255.f, 1.f ), ICON_FA_GEM );+ ImGui::SameLine();+ ImGui::TextUnformatted( "External trace" );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%zu)", m_compare.match[1].size() );+ ImGui::Separator();+ ImGui::NextColumn();++ const auto prev0 = m_compare.selMatch[0];+ int idx = 0;+ for( auto& v : m_compare.match[0] )+ {+ auto& srcloc = m_worker.GetSourceLocation( v );+ auto& zones = m_worker.GetZonesForSourceLocation( v ).zones;+ SmallColorBox( GetSrcLocColor( srcloc, 0 ) );+ ImGui::SameLine();+ ImGui::PushID( idx );+ ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 0, 0 ) );+ ImGui::RadioButton( m_worker.GetString( srcloc.name.active ? srcloc.name : srcloc.function ), &m_compare.selMatch[0], idx++ );+ ImGui::PopStyleVar();+ ImGui::SameLine();+ ImGui::TextColored( ImVec4( 0.5, 0.5, 0.5, 1 ), "(%s) %s", RealToString( zones.size() ), LocationToString( m_worker.GetString( srcloc.file ), srcloc.line ) );+ ImGui::PopID();+ }+ ImGui::NextColumn();++ const auto prev1 = m_compare.selMatch[1];+ idx = 0;+ for( auto& v : m_compare.match[1] )+ {+ auto& srcloc = m_compare.second->GetSourceLocation( v );+ auto& zones = m_compare.second->GetZonesForSourceLocation( v ).zones;+ ImGui::PushID( -1 - idx );+ ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 0, 0 ) );+ ImGui::RadioButton( m_compare.second->GetString( srcloc.name.active ? srcloc.name : srcloc.function ), &m_compare.selMatch[1], idx++ );+ ImGui::PopStyleVar();+ ImGui::SameLine();+ ImGui::TextColored( ImVec4( 0.5, 0.5, 0.5, 1 ), "(%s) %s", RealToString( zones.size() ), LocationToString( m_compare.second->GetString( srcloc.file ), srcloc.line ) );+ ImGui::PopID();+ }+ ImGui::NextColumn();+ ImGui::EndColumns();+ ImGui::TreePop();++ if( prev0 != m_compare.selMatch[0] || prev1 != m_compare.selMatch[1] )+ {+ m_compare.ResetSelection();++ if( m_compare.link )+ {+ if( !FindMatchingZone( prev0, prev1, FindMatchingZoneFlagSourceFile | FindMatchingZoneFlagLineNum ) )+ {+ if( !FindMatchingZone( prev0, prev1, FindMatchingZoneFlagSourceFile ) )+ {+ FindMatchingZone( prev0, prev1, FindMatchingZoneFlagDefault );+ }+ }+ }+ }+ }++ if( m_compare.match[0].empty() || m_compare.match[1].empty() )+ {+ ImGui::Separator();+ ImGui::TextWrapped( "Both traces must have matches." );+ ImGui::End();+ return;+ }+ }+ else+ {+ assert( m_compare.compareMode == 1 );++ ImGui::Separator();+ ImGui::BeginChild( "##compare" );+ if( ImGui::TreeNodeEx( "Frame sets", ImGuiTreeNodeFlags_DefaultOpen ) )+ {+ const auto& f0 = m_worker.GetFrames();+ const auto& f1 = m_compare.second->GetFrames();++ ImGui::SameLine();+ SmallCheckbox( "Link selection", &m_compare.link );++ ImGui::Separator();+ ImGui::Columns( 2 );+ TextColoredUnformatted( ImVec4( 0xDD/255.f, 0xDD/255.f, 0x22/255.f, 1.f ), ICON_FA_LEMON );+ ImGui::SameLine();+ ImGui::TextUnformatted( "This trace" );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%zu)", f0.size() );+ ImGui::NextColumn();+ TextColoredUnformatted( ImVec4( 0xDD/255.f, 0x22/255.f, 0x22/255.f, 1.f ), ICON_FA_GEM );+ ImGui::SameLine();+ ImGui::TextUnformatted( "External trace" );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%zu)", f1.size() );+ ImGui::Separator();+ ImGui::NextColumn();++ const auto prev0 = m_compare.selMatch[0];+ int idx = 0;+ for( auto& v : f0 )+ {+ const auto name = GetFrameSetName( *v );+ ImGui::PushID( -1 - idx );+ ImGui::RadioButton( name, &m_compare.selMatch[0], idx++ );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( v->frames.size() ) );+ ImGui::PopID();+ }+ ImGui::NextColumn();++ const auto prev1 = m_compare.selMatch[1];+ idx = 0;+ for( auto& v : f1 )+ {+ const auto name = GetFrameSetName( *v, *m_compare.second );+ ImGui::PushID( idx );+ ImGui::RadioButton( name, &m_compare.selMatch[1], idx++ );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( v->frames.size() ) );+ ImGui::PopID();+ }+ ImGui::NextColumn();+ ImGui::EndColumns();+ ImGui::TreePop();++ if( prev0 != m_compare.selMatch[0] || prev1 != m_compare.selMatch[1] )+ {+ m_compare.ResetSelection();++ if( m_compare.link )+ {+ auto string0 = GetFrameSetName( *f0[m_compare.selMatch[0]] );+ auto string1 = GetFrameSetName( *f1[m_compare.selMatch[1]], *m_compare.second );++ if( strcmp( string0, string1 ) != 0 )+ {+ idx = 0;+ if( prev0 != m_compare.selMatch[0] )+ {+ for( auto& v : f1 )+ {+ auto string = GetFrameSetName( *v, *m_compare.second );+ if( strcmp( string0, string ) == 0 )+ {+ m_compare.selMatch[1] = idx;+ break;+ }+ idx++;+ }+ }+ else+ {+ assert( prev1 != m_compare.selMatch[1] );+ for( auto& v : f0 )+ {+ auto string = GetFrameSetName( *v );+ if( strcmp( string1, string ) == 0 )+ {+ m_compare.selMatch[0] = idx;+ break;+ }+ idx++;+ }+ }+ }+ }+ }+ }+ }++ ImGui::Separator();+ if( ImGui::TreeNodeEx( "Histogram", ImGuiTreeNodeFlags_DefaultOpen ) )+ {+ const auto ty = ImGui::GetTextLineHeight();++ int64_t tmin, tmax;+ size_t size0, size1;+ int64_t total0, total1;+ double sumSq0, sumSq1;++ if( m_compare.compareMode == 0 )+ {+ auto& zoneData0 = m_worker.GetZonesForSourceLocation( m_compare.match[0][m_compare.selMatch[0]] );+ auto& zoneData1 = m_compare.second->GetZonesForSourceLocation( m_compare.match[1][m_compare.selMatch[1]] );+ auto& zones0 = zoneData0.zones;+ auto& zones1 = zoneData1.zones;+ zones0.ensure_sorted();+ zones1.ensure_sorted();++ tmin = std::min( zoneData0.min, zoneData1.min );+ tmax = std::max( zoneData0.max, zoneData1.max );++ size0 = zones0.size();+ size1 = zones1.size();+ total0 = zoneData0.total;+ total1 = zoneData1.total;+ sumSq0 = zoneData0.sumSq;+ sumSq1 = zoneData1.sumSq;++ const size_t zsz[2] = { size0, size1 };+ for( int k=0; k<2; k++ )+ {+ if( m_compare.sortedNum[k] != zsz[k] )+ {+ auto& zones = k == 0 ? zones0 : zones1;+ auto& vec = m_compare.sorted[k];+ vec.reserve( zsz[k] );+ int64_t total = m_compare.total[k];+ size_t i;+ for( i=m_compare.sortedNum[k]; i<zsz[k]; i++ )+ {+ auto& zone = *zones[i].Zone();+ const auto t = zone.End() - zone.Start();+ vec.emplace_back( t );+ total += t;+ }+ auto mid = vec.begin() + m_compare.sortedNum[k];+ pdqsort_branchless( mid, vec.end() );+ std::inplace_merge( vec.begin(), mid, vec.end() );++ m_compare.average[k] = float( total ) / i;+ m_compare.median[k] = vec[i/2];+ m_compare.total[k] = total;+ m_compare.sortedNum[k] = i;+ }+ }+ }+ else+ {+ assert( m_compare.compareMode == 1 );++ const auto& f0 = m_worker.GetFrames()[m_compare.selMatch[0]];+ const auto& f1 = m_compare.second->GetFrames()[m_compare.selMatch[1]];++ tmin = std::min( f0->min, f1->min );+ tmax = std::max( f0->max, f1->max );++ size0 = f0->frames.size();+ size1 = f1->frames.size();+ total0 = f0->total;+ total1 = f1->total;+ sumSq0 = f0->sumSq;+ sumSq1 = f1->sumSq;++ const size_t zsz[2] = { size0, size1 };+ for( int k=0; k<2; k++ )+ {+ if( m_compare.sortedNum[k] != zsz[k] )+ {+ auto& frameSet = k == 0 ? f0 : f1;+ auto worker = k == 0 ? &m_worker : m_compare.second.get();+ auto& vec = m_compare.sorted[k];+ vec.reserve( zsz[k] );+ int64_t total = m_compare.total[k];+ size_t i;+ for( i=m_compare.sortedNum[k]; i<zsz[k]; i++ )+ {+ if( worker->GetFrameEnd( *frameSet, i ) == worker->GetLastTime() ) break;+ const auto t = worker->GetFrameTime( *frameSet, i );+ vec.emplace_back( t );+ total += t;+ }+ auto mid = vec.begin() + m_compare.sortedNum[k];+ pdqsort_branchless( mid, vec.end() );+ std::inplace_merge( vec.begin(), mid, vec.end() );++ m_compare.average[k] = float( total ) / i;+ m_compare.median[k] = vec[i/2];+ m_compare.total[k] = total;+ m_compare.sortedNum[k] = i;+ }+ }+ }++ if( tmin != std::numeric_limits<int64_t>::max() )+ {+ TextDisabledUnformatted( "Minimum values in bin:" );+ ImGui::SameLine();+ ImGui::SetNextItemWidth( ImGui::CalcTextSize( "123456890123456" ).x );+ ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 1, 1 ) );+ ImGui::InputInt( "##minBinVal", &m_compare.minBinVal );+ if( m_compare.minBinVal < 1 ) m_compare.minBinVal = 1;+ ImGui::SameLine();+ if( ImGui::Button( "Reset" ) ) m_compare.minBinVal = 1;+ ImGui::PopStyleVar();++ SmallCheckbox( "Log values", &m_compare.logVal );+ ImGui::SameLine();+ SmallCheckbox( "Log time", &m_compare.logTime );+ ImGui::SameLine();+ SmallCheckbox( "Cumulate time", &m_compare.cumulateTime );+ ImGui::SameLine();+ DrawHelpMarker( "Show total time taken by calls in each bin instead of call counts." );+ ImGui::SameLine();+ SmallCheckbox( "Normalize values", &m_compare.normalize );+ ImGui::SameLine();+ DrawHelpMarker( "Normalization will rescale the total time of the external trace to match the count of this trace. This will skew reported total values!" );++ const auto cumulateTime = m_compare.cumulateTime;++ if( tmax - tmin > 0 )+ {+ const auto w = ImGui::GetContentRegionAvail().x;++ const auto numBins = int64_t( w - 4 );+ if( numBins > 1 )+ {+ if( numBins > m_compare.numBins )+ {+ m_compare.numBins = numBins;+ m_compare.bins = std::make_unique<CompVal[]>( numBins );+ m_compare.binTime = std::make_unique<CompVal[]>( numBins );+ }++ const auto& bins = m_compare.bins;+ const auto& binTime = m_compare.binTime;++ memset( bins.get(), 0, sizeof( CompVal ) * numBins );+ memset( binTime.get(), 0, sizeof( CompVal ) * numBins );++ double adj0 = 1;+ double adj1 = 1;+ if( m_compare.normalize )+ {+ if( size0 > size1 )+ {+ adj1 = double( size0 ) / size1;+ }+ else+ {+ adj0 = double( size1 ) / size0;+ }+ }++ const auto& sorted = m_compare.sorted;+ auto sBegin0 = sorted[0].begin();+ auto sBegin1 = sorted[1].begin();+ auto sEnd0 = sorted[0].end();+ auto sEnd1 = sorted[1].end();++ if( m_compare.minBinVal > 1 )+ {+ if( m_compare.logTime )+ {+ const auto tMinLog = log10( tmin );+ const auto zmax = ( log10( tmax ) - tMinLog ) / numBins;+ int64_t i;+ for( i=0; i<numBins; i++ )+ {+ const auto nextBinVal = int64_t( pow( 10.0, tMinLog + ( i+1 ) * zmax ) );+ auto nit0 = std::lower_bound( sBegin0, sEnd0, nextBinVal );+ auto nit1 = std::lower_bound( sBegin1, sEnd1, nextBinVal );+ const auto distance0 = std::distance( sBegin0, nit0 );+ const auto distance1 = std::distance( sBegin1, nit1 );+ if( distance0 >= m_compare.minBinVal || distance1 >= m_compare.minBinVal ) break;+ sBegin0 = nit0;+ sBegin1 = nit1;+ }+ for( int64_t j=numBins-1; j>i; j-- )+ {+ const auto nextBinVal = int64_t( pow( 10.0, tMinLog + ( j-1 ) * zmax ) );+ auto nit0 = std::lower_bound( sBegin0, sEnd0, nextBinVal );+ auto nit1 = std::lower_bound( sBegin1, sEnd1, nextBinVal );+ const auto distance0 = std::distance( nit0, sEnd0 );+ const auto distance1 = std::distance( nit1, sEnd1 );+ if( distance0 >= m_compare.minBinVal || distance1 >= m_compare.minBinVal ) break;+ sEnd0 = nit0;+ sEnd1 = nit1;+ }+ }+ else+ {+ const auto zmax = tmax - tmin;+ int64_t i;+ for( i=0; i<numBins; i++ )+ {+ const auto nextBinVal = tmin + ( i+1 ) * zmax / numBins;+ auto nit0 = std::lower_bound( sBegin0, sEnd0, nextBinVal );+ auto nit1 = std::lower_bound( sBegin1, sEnd1, nextBinVal );+ const auto distance0 = std::distance( sBegin0, nit0 );+ const auto distance1 = std::distance( sBegin1, nit1 );+ if( distance0 >= m_compare.minBinVal || distance1 >= m_compare.minBinVal ) break;+ sBegin0 = nit0;+ sBegin1 = nit1;+ }+ for( int64_t j=numBins-1; j>i; j-- )+ {+ const auto nextBinVal = tmin + ( j-1 ) * zmax / numBins;+ auto nit0 = std::lower_bound( sBegin0, sEnd0, nextBinVal );+ auto nit1 = std::lower_bound( sBegin1, sEnd1, nextBinVal );+ const auto distance0 = std::distance( nit0, sEnd0 );+ const auto distance1 = std::distance( nit1, sEnd1 );+ if( distance0 >= m_compare.minBinVal || distance1 >= m_compare.minBinVal ) break;+ sEnd0 = nit0;+ sEnd1 = nit1;+ }+ }++ tmin = std::min( *sBegin0, *sBegin1 );+ tmax = std::max( *(sEnd0-1), *(sEnd1-1) );+ }++ auto zit0 = sBegin0;+ auto zit1 = sBegin1;+ if( m_compare.logTime )+ {+ const auto tMinLog = log10( tmin );+ const auto zmax = ( log10( tmax ) - tMinLog ) / numBins;+ for( int64_t i=0; i<numBins; i++ )+ {+ const auto nextBinVal = int64_t( pow( 10.0, tMinLog + ( i+1 ) * zmax ) );+ auto nit0 = std::lower_bound( zit0, sEnd0, nextBinVal );+ auto nit1 = std::lower_bound( zit1, sEnd1, nextBinVal );+ bins[i].v0 += adj0 * std::distance( zit0, nit0 );+ bins[i].v1 += adj1 * std::distance( zit1, nit1 );+ binTime[i].v0 += adj0 * std::accumulate( zit0, nit0, int64_t( 0 ) );+ binTime[i].v1 += adj1 * std::accumulate( zit1, nit1, int64_t( 0 ) );+ zit0 = nit0;+ zit1 = nit1;+ }+ }+ else+ {+ const auto zmax = tmax - tmin;+ for( int64_t i=0; i<numBins; i++ )+ {+ const auto nextBinVal = tmin + ( i+1 ) * zmax / numBins;+ auto nit0 = std::lower_bound( zit0, sEnd0, nextBinVal );+ auto nit1 = std::lower_bound( zit1, sEnd1, nextBinVal );+ bins[i].v0 += adj0 * std::distance( zit0, nit0 );+ bins[i].v1 += adj1 * std::distance( zit1, nit1 );+ binTime[i].v0 += adj0 * std::accumulate( zit0, nit0, int64_t( 0 ) );+ binTime[i].v1 += adj1 * std::accumulate( zit1, nit1, int64_t( 0 ) );+ zit0 = nit0;+ zit1 = nit1;+ }+ }++ double maxVal;+ if( cumulateTime )+ {+ maxVal = std::max( binTime[0].v0, binTime[0].v1 );+ for( int i=1; i<numBins; i++ )+ {+ maxVal = std::max( { maxVal, binTime[i].v0, binTime[i].v1 } );+ }+ }+ else+ {+ maxVal = std::max( bins[0].v0, bins[0].v1 );+ for( int i=1; i<numBins; i++ )+ {+ maxVal = std::max( { maxVal, bins[i].v0, bins[i].v1 } );+ }+ }++ TextColoredUnformatted( ImVec4( 0xDD/511.f, 0xDD/511.f, 0x22/511.f, 1.f ), ICON_FA_LEMON );+ ImGui::SameLine();+ TextFocused( "Total time (this):", TimeToString( total0 * adj0 ) );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 0xDD/511.f, 0x22/511.f, 0x22/511.f, 1.f ), ICON_FA_GEM );+ ImGui::SameLine();+ TextFocused( "Total time (ext.):", TimeToString( total1 * adj1 ) );+ ImGui::Indent();+ PrintSpeedupOrSlowdown( total0 * adj0, total1 * adj1, "Total time" );+ ImGui::Unindent();+ TextFocused( "Max counts:", cumulateTime ? TimeToString( maxVal ) : RealToString( floor( maxVal ) ) );++ TextColoredUnformatted( ImVec4( 0xDD/511.f, 0xDD/511.f, 0x22/511.f, 1.f ), ICON_FA_LEMON );+ ImGui::SameLine();+ TextFocused( "Mean time (this):", TimeToString( m_compare.average[0] ) );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 0xDD/511.f, 0xDD/511.f, 0x22/511.f, 1.f ), ICON_FA_LEMON );+ ImGui::SameLine();+ TextFocused( "Median time (this):", TimeToString( m_compare.median[0] ) );+ if( sorted[0].size() > 1 )+ {+ const auto sz = sorted[0].size();+ const auto avg = m_compare.average[0];+ const auto ss = sumSq0 - 2. * total0 * avg + avg * avg * sz;+ const auto sd = sqrt( ss / ( sz - 1 ) );++ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 0xDD/511.f, 0xDD/511.f, 0x22/511.f, 1.f ), ICON_FA_LEMON );+ ImGui::SameLine();+ TextFocused( "\xcf\x83 (this):", TimeToString( sd ) );+ TooltipIfHovered( "Standard deviation" );+ }+++ TextColoredUnformatted( ImVec4( 0xDD/511.f, 0x22/511.f, 0x22/511.f, 1.f ), ICON_FA_GEM );+ ImGui::SameLine();+ TextFocused( "Mean time (ext.):", TimeToString( m_compare.average[1] ) );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 0xDD/511.f, 0x22/511.f, 0x22/511.f, 1.f ), ICON_FA_GEM );+ ImGui::SameLine();+ TextFocused( "Median time (ext.):", TimeToString( m_compare.median[1] ) );+ if( sorted[1].size() > 1 )+ {+ const auto sz = sorted[1].size();+ const auto avg = m_compare.average[1];+ const auto ss = sumSq1 - 2. * total1 * avg + avg * avg * sz;+ const auto sd = sqrt( ss / ( sz - 1 ) );++ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 0xDD/511.f, 0x22/511.f, 0x22/511.f, 1.f ), ICON_FA_GEM );+ ImGui::SameLine();+ TextFocused( "\xcf\x83 (ext.):", TimeToString( sd ) );+ TooltipIfHovered( "Standard deviation" );+ }+ ImGui::Indent();+ PrintSpeedupOrSlowdown( m_compare.average[0], m_compare.average[1], "Mean time" );+ PrintSpeedupOrSlowdown( m_compare.median[0], m_compare.median[1], "Median time" );+ ImGui::Unindent();++ ImGui::PushStyleColor( ImGuiCol_Text, ImVec4( 0xDD/511.f, 0xDD/511.f, 0x22/511.f, 1.f ) );+ ImGui::PushStyleColor( ImGuiCol_Button, ImVec4( 0xDD/255.f, 0xDD/255.f, 0x22/255.f, 1.f ) );+ ImGui::PushStyleColor( ImGuiCol_ButtonHovered, ImVec4( 0xDD/255.f, 0xDD/255.f, 0x22/255.f, 1.f ) );+ ImGui::PushStyleColor( ImGuiCol_ButtonActive, ImVec4( 0xDD/255.f, 0xDD/255.f, 0x22/255.f, 1.f ) );+ ImGui::Button( ICON_FA_LEMON );+ ImGui::PopStyleColor( 4 );+ ImGui::SameLine();+ ImGui::TextUnformatted( "This trace" );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();++ ImGui::PushStyleColor( ImGuiCol_Text, ImVec4( 0xDD/511.f, 0x22/511.f, 0x22/511.f, 1.f ) );+ ImGui::PushStyleColor( ImGuiCol_Button, ImVec4( 0xDD/255.f, 0x22/255.f, 0x22/255.f, 1.f ) );+ ImGui::PushStyleColor( ImGuiCol_ButtonHovered, ImVec4( 0xDD/255.f, 0x22/255.f, 0x22/255.f, 1.f ) );+ ImGui::PushStyleColor( ImGuiCol_ButtonActive, ImVec4( 0xDD/255.f, 0x22/255.f, 0x22/255.f, 1.f ) );+ ImGui::Button( ICON_FA_GEM );+ ImGui::PopStyleColor( 4 );+ ImGui::SameLine();+ ImGui::TextUnformatted( "External trace" );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();++ ImGui::ColorButton( "c3", ImVec4( 0x44/255.f, 0xBB/255.f, 0xBB/255.f, 1.f ), ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoDragDrop );+ ImGui::SameLine();+ ImGui::TextUnformatted( "Overlap" );++ const auto Height = 200 * scale;+ const auto wpos = ImGui::GetCursorScreenPos();+ const auto dpos = wpos + ImVec2( 0.5f, 0.5f );++ ImGui::InvisibleButton( "##histogram", ImVec2( w, Height + round( ty * 2.5 ) ) );+ const bool hover = ImGui::IsItemHovered();++ auto draw = ImGui::GetWindowDrawList();+ draw->AddRectFilled( wpos, wpos + ImVec2( w, Height ), 0x22FFFFFF );+ draw->AddRect( wpos, wpos + ImVec2( w, Height ), 0x88FFFFFF );++ if( m_compare.logVal )+ {+ const auto hAdj = double( Height - 4 ) / log10( maxVal + 1 );+ for( int i=0; i<numBins; i++ )+ {+ const auto val0 = cumulateTime ? binTime[i].v0 : bins[i].v0;+ const auto val1 = cumulateTime ? binTime[i].v1 : bins[i].v1;+ if( val0 > 0 || val1 > 0 )+ {+ const auto val = std::min( val0, val1 );+ if( val > 0 )+ {+ DrawLine( draw, dpos + ImVec2( 2+i, Height-3 ), dpos + ImVec2( 2+i, Height-3 - log10( val + 1 ) * hAdj ), 0xFFBBBB44 );+ }+ if( val1 == val )+ {+ DrawLine( draw, dpos + ImVec2( 2+i, Height-3 - log10( val + 1 ) * hAdj ), dpos + ImVec2( 2+i, Height-3 - log10( val0 + 1 ) * hAdj ), 0xFF22DDDD );+ }+ else+ {+ DrawLine( draw, dpos + ImVec2( 2+i, Height-3 - log10( val + 1 ) * hAdj ), dpos + ImVec2( 2+i, Height-3 - log10( val1 + 1 ) * hAdj ), 0xFF2222DD );+ }+ }+ }+ }+ else+ {+ const auto hAdj = double( Height - 4 ) / maxVal;+ for( int i=0; i<numBins; i++ )+ {+ const auto val0 = cumulateTime ? binTime[i].v0 : bins[i].v0;+ const auto val1 = cumulateTime ? binTime[i].v1 : bins[i].v1;+ if( val0 > 0 || val1 > 0 )+ {+ const auto val = std::min( val0, val1 );+ if( val > 0 )+ {+ DrawLine( draw, dpos + ImVec2( 2+i, Height-3 ), dpos + ImVec2( 2+i, Height-3 - val * hAdj ), 0xFFBBBB44 );+ }+ if( val1 == val )+ {+ DrawLine( draw, dpos + ImVec2( 2+i, Height-3 - val * hAdj ), dpos + ImVec2( 2+i, Height-3 - val0 * hAdj ), 0xFF22DDDD );+ }+ else+ {+ DrawLine( draw, dpos + ImVec2( 2+i, Height-3 - val * hAdj ), dpos + ImVec2( 2+i, Height-3 - val1 * hAdj ), 0xFF2222DD );+ }+ }+ }+ }++ const auto xoff = 2;+ const auto yoff = Height + 1;++ DrawHistogramMinMaxLabel( draw, tmin, tmax, wpos + ImVec2( 0, yoff ), w, ty );++ const auto ty05 = round( ty * 0.5f );+ const auto ty025 = round( ty * 0.25f );+ if( m_compare.logTime )+ {+ const auto ltmin = log10( tmin );+ const auto ltmax = log10( tmax );+ const auto start = int( floor( ltmin ) );+ const auto end = int( ceil( ltmax ) );++ const auto range = ltmax - ltmin;+ const auto step = w / range;+ auto offset = start - ltmin;+ int tw = 0;+ int tx = 0;++ auto tt = int64_t( pow( 10, start ) );++ static const double logticks[] = { log10( 2 ), log10( 3 ), log10( 4 ), log10( 5 ), log10( 6 ), log10( 7 ), log10( 8 ), log10( 9 ) };++ for( int i=start; i<=end; i++ )+ {+ const auto x = ( i - start + offset ) * step;++ if( x >= 0 )+ {+ DrawLine( draw, dpos + ImVec2( x, yoff ), dpos + ImVec2( x, yoff + ty05 ), 0x66FFFFFF );+ if( tw == 0 || x > tx + tw + ty * 1.1 )+ {+ tx = x;+ auto txt = TimeToString( tt );+ draw->AddText( wpos + ImVec2( x, yoff + ty05 ), 0x66FFFFFF, txt );+ tw = ImGui::CalcTextSize( txt ).x;+ }+ }++ for( int j=0; j<8; j++ )+ {+ const auto xoff = x + logticks[j] * step;+ if( xoff >= 0 )+ {+ DrawLine( draw, dpos + ImVec2( xoff, yoff ), dpos + ImVec2( xoff, yoff + ty025 ), 0x66FFFFFF );+ }+ }++ tt *= 10;+ }+ }+ else+ {+ const auto pxns = numBins / double( tmax - tmin );+ const auto nspx = 1.0 / pxns;+ const auto scale = std::max<float>( 0.0f, round( log10( nspx ) + 2 ) );+ const auto step = pow( 10, scale );++ const auto dx = step * pxns;+ double x = 0;+ int tw = 0;+ int tx = 0;++ const auto sstep = step / 10.0;+ const auto sdx = dx / 10.0;++ static const double linelen[] = { 0.5, 0.25, 0.25, 0.25, 0.25, 0.375, 0.25, 0.25, 0.25, 0.25 };++ int64_t tt = int64_t( ceil( tmin / sstep ) * sstep );+ const auto diff = tmin / sstep - int64_t( tmin / sstep );+ const auto xo = ( diff == 0 ? 0 : ( ( 1 - diff ) * sstep * pxns ) ) + xoff;+ int iter = int( ceil( ( tmin - int64_t( tmin / step ) * step ) / sstep ) );++ while( x < numBins )+ {+ DrawLine( draw, dpos + ImVec2( xo + x, yoff ), dpos + ImVec2( xo + x, yoff + round( ty * linelen[iter] ) ), 0x66FFFFFF );+ if( iter == 0 && ( tw == 0 || x > tx + tw + ty * 1.1 ) )+ {+ tx = x;+ auto txt = TimeToString( tt );+ draw->AddText( wpos + ImVec2( xo + x, yoff + ty05 ), 0x66FFFFFF, txt );+ tw = ImGui::CalcTextSize( txt ).x;+ }++ iter = ( iter + 1 ) % 10;+ x += sdx;+ tt += sstep;+ }+ }++ if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( 2, 2 ), wpos + ImVec2( w-2, Height + round( ty * 1.5 ) ) ) )+ {+ const auto ltmin = log10( tmin );+ const auto ltmax = log10( tmax );++ auto& io = ImGui::GetIO();+ DrawLine( draw, ImVec2( io.MousePos.x + 0.5f, dpos.y ), ImVec2( io.MousePos.x + 0.5f, dpos.y+Height-2 ), 0x33FFFFFF );++ const auto bin = int64_t( io.MousePos.x - wpos.x - 2 );+ int64_t t0, t1;+ if( m_compare.logTime )+ {+ t0 = int64_t( pow( 10, ltmin + double( bin ) / numBins * ( ltmax - ltmin ) ) );+ t1 = int64_t( pow( 10, ltmin + double( bin+1 ) / numBins * ( ltmax - ltmin ) ) );+ }+ else+ {+ t0 = int64_t( tmin + double( bin ) / numBins * ( tmax - tmin ) );+ t1 = int64_t( tmin + double( bin+1 ) / numBins * ( tmax - tmin ) );+ }++ int64_t tBefore[2] = { 0, 0 };+ for( int i=0; i<bin; i++ )+ {+ tBefore[0] += binTime[i].v0;+ tBefore[1] += binTime[i].v1;+ }++ int64_t tAfter[2] = { 0, 0 };+ for( int i=bin+1; i<numBins; i++ )+ {+ tAfter[0] += binTime[i].v0;+ tAfter[1] += binTime[i].v1;+ }++ ImGui::BeginTooltip();+ TextDisabledUnformatted( "Time range:" );+ ImGui::SameLine();+ ImGui::Text( "%s - %s", TimeToString( t0 ), TimeToString( t1 ) );+ TextDisabledUnformatted( "Count:" );+ ImGui::SameLine();+ ImGui::Text( "%s / %s", RealToString( floor( bins[bin].v0 ) ), RealToString( floor( bins[bin].v1 ) ) );+ TextDisabledUnformatted( "Time spent in bin:" );+ ImGui::SameLine();+ ImGui::Text( "%s / %s", TimeToString( binTime[bin].v0 ), TimeToString( binTime[bin].v1 ) );+ TextDisabledUnformatted( "Time spent in the left bins:" );+ ImGui::SameLine();+ ImGui::Text( "%s / %s", TimeToString( tBefore[0] ), TimeToString( tBefore[1] ) );+ TextDisabledUnformatted( "Time spent in the right bins:" );+ ImGui::SameLine();+ ImGui::Text( "%s / %s", TimeToString( tAfter[0] ), TimeToString( tAfter[1] ) );+ TextDisabledUnformatted( "(Data is displayed as:" );+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 0xDD/511.f, 0xDD/511.f, 0x22/511.f, 1.f ), ICON_FA_LEMON );+ ImGui::SameLine();+ TextDisabledUnformatted( "[this trace] /" );+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 0xDD/511.f, 0x22/511.f, 0x22/511.f, 1.f ), ICON_FA_GEM );+ ImGui::SameLine();+ TextDisabledUnformatted( "[external trace])" );+ ImGui::EndTooltip();+ }+ }+ }+ }+ ImGui::TreePop();+ }+ }++ ImGui::EndChild();+#endif+ ImGui::End();+}++}
+ cbits/tracy/profiler/src/profiler/TracyView_ConnectionState.cpp view
@@ -0,0 +1,249 @@+#include "TracyFileselector.hpp"+#include "TracyImGui.hpp"+#include "TracyPrint.hpp"+#include "TracyTexture.hpp"+#include "TracyView.hpp"++namespace tracy+{++constexpr size_t SendQueueEnableThreshold = 1000000;+constexpr size_t SendQueueDisableThreshold = 500000;+constexpr int64_t SendQueueTimespanMs = 10000; // 10 s++bool View::DrawConnection()+{+ const auto scale = GetScale();+ const auto ty = ImGui::GetTextLineHeight();+ const auto cs = ty * 0.9f;+ const auto isConnected = m_worker.IsConnected();+ size_t sendQueue;++ {+ std::shared_lock<std::shared_mutex> lock( m_worker.GetMbpsDataLock() );+ TextFocused( isConnected ? "Connected to:" : "Disconnected:", m_worker.GetAddr().c_str() );+ const auto& mbpsVector = m_worker.GetMbpsData();+ const auto mbps = mbpsVector.back();+ char buf[64];+ if( mbps < 0.1f )+ {+ sprintf( buf, "%6.2f Kbps", mbps * 1000.f );+ }+ else+ {+ sprintf( buf, "%6.2f Mbps", mbps );+ }+ ImGui::Dummy( ImVec2( cs, 0 ) );+ ImGui::SameLine();+ ImGui::PlotLines( buf, mbpsVector.data(), mbpsVector.size(), 0, nullptr, 0, std::numeric_limits<float>::max(), ImVec2( 150 * scale, 0 ) );+ TextDisabledUnformatted( "Ratio" );+ ImGui::SameLine();+ ImGui::Text( "%.1f%%", m_worker.GetCompRatio() * 100.f );+ ImGui::SameLine();+ TextDisabledUnformatted( "Real:" );+ ImGui::SameLine();+ ImGui::Text( "%6.2f Mbps", mbps / m_worker.GetCompRatio() );+ TextFocused( "Data transferred:", MemSizeToString( m_worker.GetDataTransferred() ) );+ sendQueue = m_worker.GetSendQueueSize();+ TextFocused( "Query backlog:", RealToString( sendQueue ) );+ }++ if( !m_sendQueueWarning.enabled )+ {+ if( !m_sendQueueWarning.monitor )+ {+ if( sendQueue > SendQueueEnableThreshold )+ {+ m_sendQueueWarning.monitor = true;+ m_sendQueueWarning.time = std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::system_clock::now().time_since_epoch() ).count();+ }+ }+ else+ {+ if( sendQueue < SendQueueDisableThreshold )+ {+ m_sendQueueWarning.monitor = false;+ }+ else+ {+ const auto t = std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::system_clock::now().time_since_epoch() ).count();+ if( t - m_sendQueueWarning.time > SendQueueTimespanMs )+ {+ m_sendQueueWarning.enabled = true;+ m_sendQueueWarning.monitor = false;+ }+ }+ }+ }++ const auto wpos = ImGui::GetWindowPos() + ImGui::GetWindowContentRegionMin();+ ImGui::GetWindowDrawList()->AddCircleFilled( wpos + ImVec2( 1 + cs * 0.5, 3 + ty * 1.75 ), cs * 0.5, isConnected ? 0xFF2222CC : 0xFF444444, 10 );++ {+ std::lock_guard<std::mutex> lock( m_worker.GetDataLock() );+ ImGui::SameLine();+ TextFocused( "+", RealToString( m_worker.GetSendInFlight() ) );+ const auto sz = m_worker.GetFrameCount( *m_frames );+ if( sz > 1 )+ {+ const auto dt = m_worker.GetFrameTime( *m_frames, sz - 2 );+ const auto fps = 1000000000.f / dt;+ TextDisabledUnformatted( "FPS:" );+ ImGui::SameLine();+ ImGui::Text( "%6.1f", fps );+ ImGui::SameLine();+ TextFocused( "Frame time:", TimeToString( dt ) );+ }+ }++ const auto& fis = m_worker.GetFrameImages();+ if( !fis.empty() )+ {+ const auto fiScale = scale * 0.5f;+ const auto& fi = fis.back();+ if( fi != m_frameTextureConnPtr )+ {+ if( !m_frameTextureConn ) m_frameTextureConn = MakeTexture();+ UpdateTexture( m_frameTextureConn, m_worker.UnpackFrameImage( *fi ), fi->w, fi->h );+ m_frameTextureConnPtr = fi;+ }+ ImGui::Separator();+ if( fi->flip )+ {+ ImGui::Image( m_frameTextureConn, ImVec2( fi->w * fiScale, fi->h * fiScale ), ImVec2( 0, 1 ), ImVec2( 1, 0 ) );+ }+ else+ {+ ImGui::Image( m_frameTextureConn, ImVec2( fi->w * fiScale, fi->h * fiScale ) );+ }+ }++ ImGui::Separator();+ if( ImGui::Button( ICON_FA_FLOPPY_DISK " Save trace" ) && m_saveThreadState.load( std::memory_order_relaxed ) == SaveThreadState::Inert )+ {+ auto cb = [this]( const char* fn ) {+ const auto sz = strlen( fn );+ if( sz < 7 || memcmp( fn + sz - 6, ".tracy", 6 ) != 0 )+ {+ char tmp[1024];+ sprintf( tmp, "%s.tracy", fn );+ m_filenameStaging = tmp;+ }+ else+ {+ m_filenameStaging = fn;+ }+ };++#ifndef TRACY_NO_FILESELECTOR+ Fileselector::SaveFile( "tracy", "Tracy Profiler trace file", cb );+#else+ cb( "trace.tracy" );+#endif+ }++ ImGui::SameLine( 0, 2 * ty );+ const char* stopStr = ICON_FA_PLUG " Stop";+ std::lock_guard<std::mutex> lock( m_worker.GetDataLock() );+ if( !m_disconnectIssued && m_worker.IsConnected() )+ {+ if( ImGui::Button( stopStr ) )+ {+ m_worker.Disconnect();+ m_disconnectIssued = true;+ }+ }+ else+ {+ ImGui::BeginDisabled();+ ImGui::Button( stopStr );+ ImGui::EndDisabled();+ }++ ImGui::SameLine();+ if( ImGui::Button( ICON_FA_TRIANGLE_EXCLAMATION " Discard" ) )+ {+ ImGui::OpenPopup( "Confirm trace discard" );+ }++ if( ImGui::BeginPopupModal( "Confirm trace discard", nullptr, ImGuiWindowFlags_AlwaysAutoResize ) )+ {+ ImGui::PushFont( m_bigFont );+ TextCentered( ICON_FA_TRIANGLE_EXCLAMATION );+ ImGui::PopFont();+ ImGui::TextUnformatted( "All unsaved profiling data will be lost!" );+ ImGui::TextUnformatted( "Are you sure you want to proceed?" );+ ImGui::Separator();+ if( ImGui::Button( "Yes" ) )+ {+ ImGui::CloseCurrentPopup();+ ImGui::EndPopup();+ return false;+ }+ ImGui::SameLine();+ if( ImGui::Button( "Reconnect" ) )+ {+ ImGui::CloseCurrentPopup();+ ImGui::EndPopup();+ m_reconnectRequested = true;+ return false;+ }+ ImGui::SameLine( 0, ty * 2 );+ if( ImGui::Button( "No", ImVec2( ty * 6, 0 ) ) )+ {+ ImGui::CloseCurrentPopup();+ }+ ImGui::EndPopup();+ }++ if( m_worker.IsConnected() )+ {+ const auto& params = m_worker.GetParameters();+ if( !params.empty() )+ {+ ImGui::Separator();+ if( ImGui::TreeNode( "Trace parameters" ) )+ {+ if( ImGui::BeginTable( "##traceparams", 2, ImGuiTableFlags_Borders ) )+ {+ ImGui::TableSetupColumn( "Name" );+ ImGui::TableSetupColumn( "Value", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize );+ ImGui::TableHeadersRow();+ size_t idx = 0;+ for( auto& p : params )+ {+ ImGui::TableNextRow();+ ImGui::TableNextColumn();+ ImGui::TextUnformatted( m_worker.GetString( p.name ) );+ ImGui::TableNextColumn();+ ImGui::PushID( idx );+ if( p.isBool )+ {+ bool val = p.val;+ if( ImGui::Checkbox( "", &val ) )+ {+ m_worker.SetParameter( idx, int32_t( val ) );+ }+ }+ else+ {+ auto val = int( p.val );+ if( ImGui::InputInt( "", &val, 1, 100, ImGuiInputTextFlags_EnterReturnsTrue ) )+ {+ m_worker.SetParameter( idx, int32_t( val ) );+ }+ }+ ImGui::PopID();+ idx++;+ }+ ImGui::EndTable();+ }+ ImGui::TreePop();+ }+ }+ }++ return true;+}++}
+ cbits/tracy/profiler/src/profiler/TracyView_ContextSwitch.cpp view
@@ -0,0 +1,632 @@+#include <algorithm>++#include "TracyImGui.hpp"+#include "TracyMouse.hpp"+#include "TracyPrint.hpp"+#include "TracyTimelineContext.hpp"+#include "TracyTimelineDraw.hpp"+#include "TracyView.hpp"+#include "tracy_pdqsort.h"++namespace tracy+{++const char* View::DecodeContextSwitchReasonCode( uint8_t reason )+{+ switch( reason )+ {+ case ContextSwitchData::Win32_Executive: return "Executive";+ case ContextSwitchData::Win32_FreePage: return "FreePage";+ case ContextSwitchData::Win32_PageIn: return "PageIn";+ case ContextSwitchData::Win32_PoolAllocation: return "PoolAllocation";+ case ContextSwitchData::Win32_DelayExecution: return "DelayExecution";+ case ContextSwitchData::Win32_Suspended: return "Suspended";+ case ContextSwitchData::Win32_UserRequest: return "UserRequest";+ case ContextSwitchData::Win32_WrExecutive: return "WrExecutive";+ case ContextSwitchData::Win32_WrFreePage: return "WrFreePage";+ case ContextSwitchData::Win32_WrPageIn: return "WrPageIn";+ case ContextSwitchData::Win32_WrPoolAllocation: return "WrPoolAllocation";+ case ContextSwitchData::Win32_WrDelayExecution: return "WrDelayExecution";+ case ContextSwitchData::Win32_WrSuspended: return "WrSuspended";+ case ContextSwitchData::Win32_WrUserRequest: return "WrUserRequest";+ case ContextSwitchData::Win32_WrEventPair: return "WrEventPair";+ case ContextSwitchData::Win32_WrQueue: return "WrQueue";+ case ContextSwitchData::Win32_WrLpcReceive: return "WrLpcReceive";+ case ContextSwitchData::Win32_WrLpcReply: return "WrLpcReply";+ case ContextSwitchData::Win32_WrVirtualMemory: return "WrVirtualMemory";+ case ContextSwitchData::Win32_WrPageOut: return "WrPageOut";+ case ContextSwitchData::Win32_WrRendezvous: return "WrRendezvous";+ case ContextSwitchData::Win32_WrKeyedEvent: return "WrKeyedEvent";+ case ContextSwitchData::Win32_WrTerminated: return "WrTerminated";+ case ContextSwitchData::Win32_WrProcessInSwap: return "WrProcessInSwap";+ case ContextSwitchData::Win32_WrCpuRateControl: return "WrCpuRateControl";+ case ContextSwitchData::Win32_WrCalloutStack: return "WrCalloutStack";+ case ContextSwitchData::Win32_WrKernel: return "WrKernel";+ case ContextSwitchData::Win32_WrResource: return "WrResource";+ case ContextSwitchData::Win32_WrPushLock: return "WrPushLock";+ case ContextSwitchData::Win32_WrMutex: return "WrMutex";+ case ContextSwitchData::Win32_WrQuantumEnd: return "WrQuantumEnd";+ case ContextSwitchData::Win32_WrDispatchInt: return "WrDispatchInt";+ case ContextSwitchData::Win32_WrPreempted: return "WrPreempted";+ case ContextSwitchData::Win32_WrYieldExecution: return "WrYieldExecution";+ case ContextSwitchData::Win32_WrFastMutex: return "WrFastMutex";+ case ContextSwitchData::Win32_WrGuardedMutex: return "WrGuardedMutex";+ case ContextSwitchData::Win32_WrRundown: return "WrRundown";+ case ContextSwitchData::Win32_WrAlertByThreadId: return "WrAlertByThreadId";+ case ContextSwitchData::Win32_WrDeferredPreempt: return "WrDeferredPreempt";+ case ContextSwitchData::Win32_WrPhysicalFault: return "WrPhysicalFault";+ case ContextSwitchData::Win32_WrIoRing: return "WrIoRing";+ case ContextSwitchData::Win32_WrMdlCache: return "WrMdlCache";+ case ContextSwitchData::Win32_WrRcu: return "WrRcu";+ default: return "unknown";+ }+}++const char* View::DecodeContextSwitchReason( uint8_t reason )+{+ switch( reason )+ {+ case ContextSwitchData::Win32_Executive: return "(Thread is waiting for the scheduler)";+ case ContextSwitchData::Win32_FreePage: return "(Thread is waiting for a free virtual memory page)";+ case ContextSwitchData::Win32_PageIn: return "(Thread is waiting for a virtual memory page to arrive in memory)"; + case ContextSwitchData::Win32_PoolAllocation: return "(Thread is waiting for a system allocation)";+ case ContextSwitchData::Win32_DelayExecution: return "(Thread execution is delayed)";+ case ContextSwitchData::Win32_Suspended: return "(Thread execution is suspended)";+ case ContextSwitchData::Win32_UserRequest: return "(Thread is waiting on object - WaitForSingleObject, etc.)";+ case ContextSwitchData::Win32_WrExecutive: return "(Thread is waiting for the scheduler)";+ case ContextSwitchData::Win32_WrFreePage: return "(Thread is waiting for a free virtual memory page)";+ case ContextSwitchData::Win32_WrPageIn: return "(Thread is waiting for a virtual memory page to arrive in memory)";+ case ContextSwitchData::Win32_WrPoolAllocation: return "(Thread is waiting for a system allocation)";+ case ContextSwitchData::Win32_WrDelayExecution: return "(Thread execution is delayed)";+ case ContextSwitchData::Win32_WrSuspended: return "(Thread execution is suspended)";+ case ContextSwitchData::Win32_WrUserRequest: return "(Thread is waiting for window messages)";+ case ContextSwitchData::Win32_WrEventPair: return "(Thread is waiting for a client/server event pair)";+ case ContextSwitchData::Win32_WrQueue: return "(Thread is waiting on KQUEUE, which was empty. Usuall has to do with I/O completion.)";+ case ContextSwitchData::Win32_WrLpcReceive: return "(Thread is waiting for a local procedure call to arrive)";+ case ContextSwitchData::Win32_WrLpcReply: return "(Thread is waiting for a local procedure call reply to arrive)";+ case ContextSwitchData::Win32_WrVirtualMemory: return "(Thread is waiting for the system to allocate virtual memory)";+ case ContextSwitchData::Win32_WrPageOut: return "(Thread is waiting for a virtual memory page to be written to disk)";+ case ContextSwitchData::Win32_WrRendezvous: return "(Thread is waiting for a rendezvous.)";+ case ContextSwitchData::Win32_WrKeyedEvent: return "(Thread is waiting for a keyed event)";+ case ContextSwitchData::Win32_WrTerminated: return "(Waiting for thread termination.)";+ case ContextSwitchData::Win32_WrProcessInSwap: return "(Waiting for a process to be swapped in.)";+ case ContextSwitchData::Win32_WrCpuRateControl: return "(CPU rate limiting)";+ case ContextSwitchData::Win32_WrCalloutStack: return "(Waiting for the thread callout routine to finish due to stack being resized.)";+ case ContextSwitchData::Win32_WrKernel: return "(Waiting for a kernel operation)";+ case ContextSwitchData::Win32_WrResource: return "(Kernel is waiting for a resource, usually related to drivers loading, hardware changes or network connections.)";+ case ContextSwitchData::Win32_WrPushLock: return "(Waiting for a driver PushLock to be released.)";+ case ContextSwitchData::Win32_WrMutex: return "(Waiting for a Mutex object. This could be related to Inter Process Synchronization.)";+ case ContextSwitchData::Win32_WrQuantumEnd: return "(Thread has used up all of its quantum and another thread was ready to be scheduled.)";+ case ContextSwitchData::Win32_WrDispatchInt: return "(A software interrupt was dispatched and another thread was scheduled while processing DPCs.)";+ case ContextSwitchData::Win32_WrPreempted: return "(Thread was preempted to run another thread with higher priority.)";+ case ContextSwitchData::Win32_WrYieldExecution: return "(Thread yielded its quantum, most likely through SwitchToThread or Sleep(0).)";+ case ContextSwitchData::Win32_WrFastMutex: return "(Waiting for a Fast Mutex held by the driver. Raises the IRQ level.)";+ case ContextSwitchData::Win32_WrGuardedMutex: return "(Waiting for a Guarded Mutex held by the driver.)";+ case ContextSwitchData::Win32_WrRundown: return "(Driver waiting for rundown. Some kernel shared object is most likely being reloaded.)";+ case ContextSwitchData::Win32_WrAlertByThreadId: return "(Waiting for a synchronization primitive that does not use WaitForObject. Most likely from a SRWLock, CRITICAL_SECTION or WaitOnAdress.)";+ case ContextSwitchData::Win32_WrDeferredPreempt: return "(Thread should be preempting another, but can not due to the other being running uninterruptable code.)";+ case ContextSwitchData::Win32_WrPhysicalFault: return "(A physical fault needs to be handled.)";+ case ContextSwitchData::Win32_WrIoRing: return "(Waiting for I/O Ring operations, likely due to a call to SubmitIORing.)";+ case ContextSwitchData::Win32_WrMdlCache: return "(Waiting for the Memory Descriptor List cache, related to Virtual<>Physical I/O buffers.";+ case ContextSwitchData::Win32_WrRcu: return "(Waiting for a Read-Copy-Update synchronization.)";+ default: return "";+ }+}++const char* View::DecodeContextSwitchStateCode( uint8_t state )+{+ switch( state )+ {+ case 0: return "Initialized";+ case 1: return "Ready";+ case 2: return "Running";+ case 3: return "Standby";+ case 4: return "Terminated";+ case 5: return "Waiting";+ case 6: return "Transition";+ case 7: return "DeferredReady";+ case 101: return "D (disk sleep)";+ case 102: return "I (idle)";+ case 103: return "R (running)";+ case 104: return "S (sleeping)";+ case 105: return "T (stopped)";+ case 106: return "t (tracing stop)";+ case 107: return "W";+ case 108: return "X (dead)";+ case 109: return "Z (zombie)";+ case 110: return "P (parked)";+ default: return "unknown";+ }+}++const char* View::DecodeContextSwitchState( uint8_t state )+{+ switch( state )+ {+ case 0: return "(Thread has been initialized, but has not yet started)";+ case 1: return "(Thread is waiting to use a processor because no processor is free. The thread is prepared to run on the next available processor)";+ case 2: return "(Thread is currently using a processor)";+ case 3: return "(Thread is about to use a processor)";+ case 4: return "(Thread has finished executing and has exited)";+ case 5: return "(Thread is not ready to use the processor because it is waiting for a peripheral operation to complete or a resource to become free)";+ case 6: return "(Thread is waiting for a resource, other than the processor, before it can execute)";+ case 7: return "(Thread has been selected to run on a specific processor but have not yet beed scheduled)";+ case 101: return "(Uninterruptible sleep, usually IO)";+ case 102: return "(Idle kernel thread)";+ case 103: return "(Running or on run queue)";+ case 104: return "(Interruptible sleep, waiting for an event to complete)";+ case 105: return "(Stopped by job control signal)";+ case 106: return "(Stopped by debugger during the tracing)";+ case 107: return "(Paging)";+ case 108: return "(Dead task is scheduling one last time)";+ case 109: return "(Zombie process)";+ case 110: return "(Parked)";+ default: return "";+ }+}++void View::DrawContextSwitchList( const TimelineContext& ctx, const std::vector<ContextSwitchDraw>& drawList, const Vector<ContextSwitchData>& ctxSwitch, int offset, int endOffset, bool isFiber )+{+ constexpr float MinCtxSize = 4;++ const auto vStart = ctx.vStart;+ const auto& wpos = ctx.wpos;+ const auto pxns = ctx.pxns;+ const auto hover = ctx.hover;+ const auto w = ctx.w;+ const auto ty = round( ctx.ty * 0.75f );++ const auto lineSize = 2 * GetScale();+ auto draw = ImGui::GetWindowDrawList();+ const auto dpos = wpos + ImVec2( 0.5f, 0.5f );+ const auto ty05 = round( ty * 0.5f );++ double minpx = -10;++ for( auto& v : drawList )+ {+ const auto it = ctxSwitch.begin() + v.idx;+ const auto& ev = *it;+ switch( v.type )+ {+ case ContextSwitchDrawType::Waiting:+ {+ const auto& prev = *(it-1);+ const bool migration = prev.Cpu() != ev.Cpu();+ const auto px0 = std::max( { ( prev.End() - vStart ) * pxns, -10.0, double( minpx ) } );+ const auto pxw = ( ev.WakeupVal() - vStart ) * pxns;+ const auto px1 = std::min( ( ev.Start() - vStart ) * pxns, w + 10.0 );+ const auto color = migration ? 0xFFEE7711 : 0xFF2222AA;+ if( m_vd.darkenContextSwitches )+ {+ draw->AddRectFilled( dpos + ImVec2( px0, offset + ty05 ), dpos + ImVec2( px1, endOffset ), 0x661C2321 );+ }+ DrawLine( draw, dpos + ImVec2( px0, offset + ty05 - 0.5f ), dpos + ImVec2( std::min( pxw, w+10.0 ), offset + ty05 - 0.5f ), color, lineSize );+ if( ev.WakeupVal() != ev.Start() )+ {+ DrawLine( draw, dpos + ImVec2( std::max( pxw, 10.0 ), offset + ty05 - 0.5f ), dpos + ImVec2( px1, offset + ty05 - 0.5f ), 0xFF2280A0, lineSize );+ }++ if( hover )+ {+ bool tooltip = false;+ if( ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( pxw, offset + ty ) ) )+ {+ ImGui::BeginTooltip();+ if( isFiber )+ {+ TextFocused( "Fiber is", "yielding" );+ TextFocused( "Yield time:", TimeToString( ev.Start() - prev.End() ) );+ }+ else+ {+ TextFocused( "Thread is", migration ? "migrating CPUs" : "waiting" );+ TextFocused( "Waiting time:", TimeToString( ev.WakeupVal() - prev.End() ) );+ if( migration )+ {+ TextFocused( "CPU:", RealToString( prev.Cpu() ) );+ ImGui::SameLine();+ TextFocused( ICON_FA_RIGHT_LONG, RealToString( ev.Cpu() ) );+ }+ else+ {+ TextFocused( "CPU:", RealToString( ev.Cpu() ) );+ }+ if( prev.Reason() != 100 )+ {+ TextFocused( "Wait reason:", DecodeContextSwitchReasonCode( prev.Reason() ) );+ ImGui::SameLine();+ ImGui::PushFont( m_smallFont );+ ImGui::AlignTextToFramePadding();+ TextDisabledUnformatted( DecodeContextSwitchReason( prev.Reason() ) );+ ImGui::PopFont();+ }+ TextFocused( "Wait state:", DecodeContextSwitchStateCode( prev.State() ) );+ ImGui::SameLine();+ ImGui::PushFont( m_smallFont );+ ImGui::AlignTextToFramePadding();+ TextDisabledUnformatted( DecodeContextSwitchState( prev.State() ) );+ ImGui::PopFont();+ }+ tooltip = true;++ if( IsMouseClicked( 2 ) )+ {+ ZoomToRange( prev.End(), ev.WakeupVal() );+ }+ }+ else if( ev.WakeupVal() != ev.Start() && ImGui::IsMouseHoveringRect( wpos + ImVec2( pxw, offset ), wpos + ImVec2( px1, offset + ty ) ) )+ {+ assert( !isFiber );+ ImGui::BeginTooltip();+ TextFocused( "Thread is", "waking up" );+ TextFocused( "Scheduling delay:", TimeToString( ev.Start() - ev.WakeupVal() ) );+ TextFocused( "CPU:", RealToString( ev.Cpu() ) );+ if( IsMouseClicked( 2 ) )+ {+ ZoomToRange( prev.End(), ev.WakeupVal() );+ }+ TextFocused( "Readied by CPU:", RealToString( ev.WakeupCpu() ) );+ tooltip = true;+ }+ if( tooltip )+ {+ const auto waitStack = v.data;+ if( waitStack )+ {+ ImGui::Separator();+ TextDisabledUnformatted( ICON_FA_HOURGLASS_HALF " Wait stack:" );+ CallstackTooltipContents( waitStack );+ if( ImGui::IsMouseClicked( 0 ) )+ {+ m_callstackInfoWindow = waitStack;+ }+ }+ ImGui::EndTooltip();+ }+ }+ break;+ }+ case ContextSwitchDrawType::Folded:+ {+ const auto num = v.data;+ const auto px0 = std::max( ( ev.Start() - vStart ) * pxns, -10.0 );+ const auto eit = it + num - 1;+ const auto end = eit->IsEndValid() ? eit->End() : eit->Start();+ const auto px1ns = end - vStart;+ minpx = std::min( std::max( px1ns * pxns, px0+MinCtxSize ), double( w + 10 ) );+ if( num == 1 )+ {+ DrawLine( draw, dpos + ImVec2( px0, offset + ty05 - 0.5f ), dpos + ImVec2( minpx, offset + ty05 - 0.5f ), 0xFF22DD22, lineSize );+ if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( minpx, offset + ty + 1 ) ) )+ {+ ImGui::BeginTooltip();+ if( isFiber )+ {+ const auto tid = m_worker.DecompressThread( ev.Thread() );+ TextFocused( "Fiber is", "running" );+ TextFocused( "Activity time:", TimeToString( end - ev.Start() ) );+ TextFocused( "Thread:", m_worker.GetThreadName( tid ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( tid ) );+ }+ else+ {+ TextFocused( "Thread is", "running" );+ TextFocused( "Activity time:", TimeToString( end - ev.Start() ) );+ TextFocused( "CPU:", RealToString( ev.Cpu() ) );+ }+ ImGui::EndTooltip();++ if( IsMouseClicked( 2 ) )+ {+ ZoomToRange( ev.Start(), end );+ }+ }+ }+ else+ {+ DrawZigZag( draw, wpos + ImVec2( 0, offset + ty05 ), px0, minpx, ty/4, 0xFF888888 );+ if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( minpx, offset + ty + 1 ) ) )+ {+ ImGui::BeginTooltip();+ TextFocused( isFiber ? "Fiber is" : "Thread is", "changing activity multiple times" );+ TextFocused( "Number of running regions:", RealToString( num ) );+ TextFocused( "Time:", TimeToString( end - ev.Start() ) );+ ImGui::EndTooltip();++ if( IsMouseClicked( 2 ) )+ {+ ZoomToRange( ev.Start(), end );+ }+ }+ }+ break;+ }+ case ContextSwitchDrawType::Running:+ {+ const auto end = ev.IsEndValid() ? ev.End() : ev.Start();+ const auto px0 = std::max( { ( ev.Start() - vStart ) * pxns, -10.0, double( minpx ) } );+ const auto px1 = std::min( ( end - vStart ) * pxns, w + 10.0 );+ DrawLine( draw, dpos + ImVec2( px0, offset + ty05 - 0.5f ), dpos + ImVec2( px1, offset + ty05 - 0.5f ), 0xFF22DD22, lineSize );+ if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + ty + 1 ) ) )+ {+ ImGui::BeginTooltip();+ if( isFiber )+ {+ const auto tid = m_worker.DecompressThread( ev.Thread() );+ TextFocused( "Fiber is", "running" );+ TextFocused( "Activity time:", TimeToString( end - ev.Start() ) );+ TextFocused( "Thread:", m_worker.GetThreadName( tid ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( tid ) );+ }+ else+ {+ TextFocused( "Thread is", "running" );+ TextFocused( "Activity time:", TimeToString( end - ev.Start() ) );+ TextFocused( "CPU:", RealToString( ev.Cpu() ) );+ }+ ImGui::EndTooltip();++ if( IsMouseClicked( 2 ) )+ {+ ZoomToRange( ev.Start(), end );+ }+ }+ break;+ }+ default:+ assert( false );+ break;+ };+ }+}++void View::DrawWaitStacks()+{+ const auto scale = GetScale();+ ImGui::SetNextWindowSize( ImVec2( 1400 * scale, 500 * scale ), ImGuiCond_FirstUseEver );+ ImGui::Begin( "Wait stacks", &m_showWaitStacks );+ if( ImGui::GetCurrentWindowRead()->SkipItems ) { ImGui::End(); return; }+#ifdef TRACY_NO_STATISTICS+ ImGui::TextWrapped( "Rebuild without the TRACY_NO_STATISTICS macro to enable wait stacks." );+#else+ uint64_t totalCount = 0;+ unordered_flat_map<uint32_t, uint64_t> stacks;+ for( auto& t : m_threadOrder )+ {+ if( WaitStackThread( t->id ) )+ {+ auto it = t->ctxSwitchSamples.begin();+ auto end = t->ctxSwitchSamples.end();+ if( m_waitStackRange.active )+ {+ it = std::lower_bound( it, end, m_waitStackRange.min, [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs; } );+ end = std::lower_bound( it, end, m_waitStackRange.max, [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs; } );+ }+ totalCount += std::distance( it, end );+ while( it != end )+ {+ auto cs = it->callstack.Val();+ auto cit = stacks.find( cs );+ if( cit == stacks.end() )+ {+ stacks.emplace( cs, 1 );+ }+ else+ {+ cit->second++;+ }+ ++it;+ }+ }+ }++ ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 2, 2 ) );+ if( ImGui::RadioButton( ICON_FA_TABLE " List", m_waitStackMode == 0 ) ) m_waitStackMode = 0;+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ if( ImGui::RadioButton( ICON_FA_TREE " Bottom-up tree", m_waitStackMode == 1 ) ) m_waitStackMode = 1;+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ if( ImGui::RadioButton( ICON_FA_TREE " Top-down tree", m_waitStackMode == 2 ) ) m_waitStackMode = 2;+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::SeparatorEx( ImGuiSeparatorFlags_Vertical );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ TextFocused( "Total wait stacks:", RealToString( m_worker.GetContextSwitchSampleCount() ) );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ TextFocused( "Selected:", RealToString( totalCount ) );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::SeparatorEx( ImGuiSeparatorFlags_Vertical );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ if( ImGui::Checkbox( "Limit range", &m_waitStackRange.active ) )+ {+ if( m_waitStackRange.active && m_waitStackRange.min == 0 && m_waitStackRange.max == 0 )+ {+ m_waitStackRange.min = m_vd.zvStart;+ m_waitStackRange.max = m_vd.zvEnd;+ }+ }+ if( m_waitStackRange.active )+ {+ ImGui::SameLine();+ TextColoredUnformatted( 0xFF00FFFF, ICON_FA_TRIANGLE_EXCLAMATION );+ ImGui::SameLine();+ ToggleButton( ICON_FA_RULER " Limits", m_showRanges );+ }+ ImGui::PopStyleVar();++ bool threadsChanged = false;+ auto expand = ImGui::TreeNode( ICON_FA_SHUFFLE " Visible threads:" );+ ImGui::SameLine();+ size_t visibleThreads = 0;+ for( const auto& t : m_threadOrder ) if( WaitStackThread( t->id ) ) visibleThreads++;+ if( visibleThreads == m_threadOrder.size() )+ {+ ImGui::TextDisabled( "(%zu)", m_threadOrder.size() );+ }+ else+ {+ ImGui::TextDisabled( "(%zi/%zu)", visibleThreads, m_threadOrder.size() );+ }+ if( expand )+ {+ auto& crash = m_worker.GetCrashEvent();++ ImGui::SameLine();+ if( ImGui::SmallButton( "Select all" ) )+ {+ for( const auto& t : m_threadOrder )+ {+ WaitStackThread( t->id ) = true;+ }+ threadsChanged = true;+ }+ ImGui::SameLine();+ if( ImGui::SmallButton( "Unselect all" ) )+ {+ for( const auto& t : m_threadOrder )+ {+ WaitStackThread( t->id ) = false;+ }+ threadsChanged = true;+ }++ int idx = 0;+ for( const auto& t : m_threadOrder )+ {+ if( t->ctxSwitchSamples.empty() ) continue;+ ImGui::PushID( idx++ );+ const auto threadColor = GetThreadColor( t->id, 0 );+ SmallColorBox( threadColor );+ ImGui::SameLine();+ if( SmallCheckbox( m_worker.GetThreadName( t->id ), &WaitStackThread( t->id ) ) )+ {+ threadsChanged = true;+ }+ ImGui::PopID();+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( t->ctxSwitchSamples.size() ) );+ if( crash.thread == t->id )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 1.f, 0.2f, 0.2f, 1.f ), ICON_FA_SKULL " Crashed" );+ }+ if( t->isFiber )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 0.2f, 0.6f, 0.2f, 1.f ), "Fiber" );+ }+ }+ ImGui::TreePop();+ }+ if( threadsChanged ) m_waitStack = 0;++ ImGui::Separator();+ ImGui::BeginChild( "##waitstacks" );+ if( stacks.empty() )+ {+ ImGui::PushFont( m_bigFont );+ ImGui::Dummy( ImVec2( 0, ( ImGui::GetContentRegionAvail().y - ImGui::GetTextLineHeight() * 2 ) * 0.5f ) );+ TextCentered( ICON_FA_KIWI_BIRD );+ TextCentered( "No wait stacks to display" );+ ImGui::PopFont();+ }+ else+ {+ switch( m_waitStackMode )+ {+ case 0:+ {+ TextDisabledUnformatted( "Wait stack:" );+ ImGui::SameLine();+ if( ImGui::SmallButton( " " ICON_FA_CARET_LEFT " " ) )+ {+ m_waitStack = std::max( m_waitStack - 1, 0 );+ }+ ImGui::SameLine();+ ImGui::Text( "%s / %s", RealToString( m_waitStack + 1 ), RealToString( stacks.size() ) );+ if( ImGui::IsItemClicked() ) ImGui::OpenPopup( "WaitStacksPopup" );+ ImGui::SameLine();+ if( ImGui::SmallButton( " " ICON_FA_CARET_RIGHT " " ) )+ {+ m_waitStack = std::min<int>( m_waitStack + 1, stacks.size() - 1 );+ }+ if( ImGui::BeginPopup( "WaitStacksPopup" ) )+ {+ int sel = m_waitStack + 1;+ ImGui::SetNextItemWidth( 120 * scale );+ const bool clicked = ImGui::InputInt( "##waitStack", &sel, 1, 100, ImGuiInputTextFlags_EnterReturnsTrue );+ if( clicked ) m_waitStack = std::min( std::max( sel, 1 ), int( stacks.size() ) ) - 1;+ ImGui::EndPopup();+ }+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ Vector<decltype(stacks.begin())> data;+ data.reserve( stacks.size() );+ for( auto it = stacks.begin(); it != stacks.end(); ++it ) data.push_back( it );+ pdqsort_branchless( data.begin(), data.end(), []( const auto& l, const auto& r ) { return l->second > r->second; } );+ TextFocused( "Counts:", RealToString( data[m_waitStack]->second ) );+ ImGui::SameLine();+ char buf[64];+ PrintStringPercent( buf, 100. * data[m_waitStack]->second / totalCount );+ TextDisabledUnformatted( buf );+ ImGui::Separator();+ DrawCallstackTable( data[m_waitStack]->first, false );+ break;+ }+ case 1:+ {+ SmallCheckbox( ICON_FA_LAYER_GROUP " Group by function name", &m_groupWaitStackBottomUp );+ auto tree = GetCallstackFrameTreeBottomUp( stacks, m_groupCallstackTreeByNameBottomUp );+ if( !tree.empty() )+ {+ int idx = 0;+ DrawFrameTreeLevel( tree, idx );+ }+ else+ {+ TextDisabledUnformatted( "No call stacks to show" );+ }+ break;+ }+ case 2:+ {+ SmallCheckbox( ICON_FA_LAYER_GROUP " Group by function name", &m_groupWaitStackTopDown );+ auto tree = GetCallstackFrameTreeTopDown( stacks, m_groupCallstackTreeByNameTopDown );+ if( !tree.empty() )+ {+ int idx = 0;+ DrawFrameTreeLevel( tree, idx );+ }+ else+ {+ TextDisabledUnformatted( "No call stacks to show" );+ }+ break;+ }+ default:+ assert( false );+ break;+ }+ }+#endif+ ImGui::EndChild();+ ImGui::End();+}++}
+ cbits/tracy/profiler/src/profiler/TracyView_CpuData.cpp view
@@ -0,0 +1,889 @@+#include <math.h>++#include "TracyColor.hpp"+#include "TracyImGui.hpp"+#include "TracyMouse.hpp"+#include "TracyPrint.hpp"+#include "TracyTimelineDraw.hpp"+#include "TracyTimelineItem.hpp"+#include "TracyTimelineContext.hpp"+#include "TracyView.hpp"+#include "tracy_pdqsort.h"++constexpr float MinVisSize = 3;++namespace tracy+{++bool View::DrawCpuData( const TimelineContext& ctx, const std::vector<CpuUsageDraw>& cpuDraw, const std::vector<std::vector<CpuCtxDraw>>& ctxDraw, int& offset, bool hasCpuData )+{+ auto cpuData = m_worker.GetCpuData();+ const auto cpuCnt = m_worker.GetCpuDataCpuCount();+ assert( cpuCnt != 0 );++ const auto& wpos = ctx.wpos;+ const auto w = ctx.w;+ const auto ty = ctx.ty;+ const auto sty = ctx.sty;+ const auto pxns = ctx.pxns;+ const auto nspx = ctx.nspx;+ const auto dpos = wpos + ImVec2( 0.5f, 0.5f );+ const auto yMin = ctx.yMin;+ const auto yMax = ctx.yMax;+ const auto hover = ctx.hover;+ const auto vStart = ctx.vStart;++ auto draw = ImGui::GetWindowDrawList();++ if( hasCpuData && m_vd.drawCpuUsageGraph )+ {+ const auto cpuUsageHeight = floor( 30.f * GetScale() );+ if( wpos.y + offset + cpuUsageHeight + 3 >= yMin && wpos.y + offset <= yMax )+ {+ const float cpuCntRev = 1.f / cpuCnt;+ int pos = 0;+ for( auto& v : cpuDraw )+ {+ float base;+ if( v.own != 0 )+ {+ base = dpos.y + offset + ( 1.f - v.own * cpuCntRev ) * cpuUsageHeight;+ DrawLine( draw, ImVec2( dpos.x + pos, dpos.y + offset + cpuUsageHeight ), ImVec2( dpos.x + pos, base ), 0xFF55BB55 );+ }+ else+ {+ base = dpos.y + offset + cpuUsageHeight;+ }+ if( v.other != 0 )+ {+ int usageTotal = v.own + v.other;+ DrawLine( draw, ImVec2( dpos.x + pos, base ), ImVec2( dpos.x + pos, dpos.y + offset + ( 1.f - usageTotal * cpuCntRev ) * cpuUsageHeight ), 0xFF666666 );+ }+ pos++;+ }+ DrawLine( draw, dpos + ImVec2( 0, offset+cpuUsageHeight+2 ), dpos + ImVec2( w, offset+cpuUsageHeight+2 ), 0x22DD88DD );++ if( hover && ImGui::IsMouseHoveringRect( ImVec2( wpos.x, wpos.y + offset ), ImVec2( wpos.x + w, wpos.y + offset + cpuUsageHeight ), true ) )+ {+ ImGui::BeginTooltip();+ if( cpuDraw.size() > ( ImGui::GetIO().MousePos.x - wpos.x ) )+ {+ const auto& usage = cpuDraw[ImGui::GetIO().MousePos.x - wpos.x];+ TextFocused( "Cores used by profiled program:", RealToString( usage.own ) );+ ImGui::SameLine();+ char buf[64];+ PrintStringPercent( buf, usage.own * cpuCntRev * 100 );+ TextDisabledUnformatted( buf );+ TextFocused( "Cores used by other programs:", RealToString( usage.other ) );+ ImGui::SameLine();+ PrintStringPercent( buf, usage.other * cpuCntRev * 100 );+ TextDisabledUnformatted( buf );+ TextFocused( "Number of cores:", RealToString( cpuCnt ) );+ if( usage.own + usage.other != 0 )+ {+ auto& topo = m_worker.GetCpuTopology();+ const auto mt = m_vd.zvStart + ( ImGui::GetIO().MousePos.x - wpos.x ) * nspx;+ ImGui::Separator();+ for( int i=0; i<cpuCnt; i++ )+ {+ if( !cpuData[i].cs.empty() )+ {+ auto& cs = cpuData[i].cs;+ auto it = std::lower_bound( cs.begin(), cs.end(), mt, [] ( const auto& l, const auto& r ) { return (uint64_t)l.End() < (uint64_t)r; } );+ if( it != cs.end() && it->Start() <= mt && it->End() >= mt )+ {+ auto tt = m_worker.GetThreadTopology( i );+ if( tt )+ {+ if( topo.size() > 1 )+ {+ ImGui::TextDisabled( "[%i:%i:%i] CPU %i:", tt->package, tt->die, tt->core, i );+ }+ else+ {+ ImGui::TextDisabled( "[%i:%i] CPU %i:", tt->die, tt->core, i );+ }+ }+ else+ {+ ImGui::TextDisabled( "CPU %i:", i );+ }+ ImGui::SameLine();+ const auto thread = m_worker.DecompressThreadExternal( it->Thread() );+ bool local, untracked;+ const char* txt;+ auto label = GetThreadContextData( thread, local, untracked, txt );+ if( local || untracked )+ {+ uint32_t color;+ if( m_vd.dynamicColors != 0 )+ {+ color = local ? GetThreadColor( thread, 0 ) : ( untracked ? 0xFF663333 : 0xFF444444 );+ }+ else+ {+ color = local ? 0xFF334488 : ( untracked ? 0xFF663333 : 0xFF444444 );+ }+ TextColoredUnformatted( HighlightColor<75>( color ), label );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( thread ) );+ }+ else+ {+ TextDisabledUnformatted( label );+ }+ }+ }+ }+ }+ }+ else+ {+ TextFocused( "Cores used by profiled program:", "0" );+ TextFocused( "Cores used by other programs:", "0" );+ TextFocused( "Number of cores:", RealToString( cpuCnt ) );+ }+ ImGui::EndTooltip();+ }+ }+ offset += cpuUsageHeight + 3;+ }++ ImGui::PushFont( m_smallFont );+ const auto sstep = sty + 1;++ const auto origOffset = offset;+ for( int i=0; i<cpuCnt; i++ )+ {+ DrawLine( draw, dpos + ImVec2( 0, offset+sty ), dpos + ImVec2( w, offset+sty ), 0x22DD88DD );+ auto tt = m_worker.GetThreadTopology( i );+ if( !ctxDraw[i].empty() && wpos.y + offset + sty >= yMin && wpos.y + offset <= yMax )+ {+ auto& cs = cpuData[i].cs;+ for( auto& v : ctxDraw[i] )+ {+ const auto& ev = cs[v.idx];+ const auto t0 = ev.Start();+ const auto px0 = ( t0 - vStart ) * pxns;+ if( v.num > 0 )+ {+ const auto& eev = cs[v.idx + v.num - 1];+ const auto t1 = eev.IsEndValid() ? eev.End() : eev.Start();+ const auto px1 = ( t1 - vStart ) * pxns;+ DrawZigZag( draw, wpos + ImVec2( 0, offset + sty/2 ), std::max( px0, -10.0 ), std::min( std::max( px1, px0+MinVisSize ), double( w + 10 ) ), sty/4, 0xFF888888 );++ if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, offset-1 ), wpos + ImVec2( std::max( px1, px0+MinVisSize ), offset + sty ) ) )+ {+ ImGui::PopFont();+ ImGui::BeginTooltip();+ TextFocused( "CPU:", RealToString( i ) );+ if( tt )+ {+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ TextFocused( "Package:", RealToString( tt->package ) );+ ImGui::SameLine();+ TextFocused( "Die:", RealToString( tt->die ) );+ ImGui::SameLine();+ TextFocused( "Core:", RealToString( tt->core ) );+ }+ TextFocused( "Context switch regions:", RealToString( v.num ) );+ ImGui::Separator();+ TextFocused( "Start time:", TimeToString( t0 ) );+ TextFocused( "End time:", TimeToString( t1 ) );+ TextFocused( "Activity time:", TimeToString( t1 - t0 ) );+ ImGui::EndTooltip();+ ImGui::PushFont( m_smallFont );++ if( IsMouseClicked( 2 ) )+ {+ ZoomToRange( t0, t1 );+ }+ }+ }+ else+ {+ const auto end = ev.IsEndValid() ? ev.End() : ev.Start();+ const auto px1 = ( end - vStart ) * pxns;++ const auto thread = m_worker.DecompressThreadExternal( ev.Thread() );+ bool local, untracked;+ const char* txt;+ auto label = GetThreadContextData( thread, local, untracked, txt );++ auto getDisplayThreadColor = [this]( uint64_t thread, bool local, bool untracked ) {+ if( m_vd.dynamicColors != 0 )+ {+ return local ? GetThreadColor( thread, 0 ) : ( untracked ? 0xFF663333 : 0xFF444444 );+ }+ else+ {+ return local ? 0xFF334488 : ( untracked ? 0xFF663333 : 0xFF444444 );+ }+ };+ uint32_t color = getDisplayThreadColor( thread, local, untracked );++ draw->AddRectFilled( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + sty ), color );+ if( m_drawThreadHighlight == thread )+ {+ draw->AddRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + sty ), 0xFFFFFFFF );+ }+ else+ {+ const auto accentColor = HighlightColor( color );+ const auto darkColor = DarkenColor( color );+ DrawLine( draw, dpos + ImVec2( px0, offset + sty ), dpos + ImVec2( px0, offset ), dpos + ImVec2( px1-1, offset ), accentColor, 1.f );+ DrawLine( draw, dpos + ImVec2( px0, offset + sty ), dpos + ImVec2( px1-1, offset + sty ), dpos + ImVec2( px1-1, offset ), darkColor, 1.f );+ }++ const auto zsz = px1 - px0;+ auto tsz = ImGui::CalcTextSize( label );+ if( tsz.x < zsz )+ {+ const auto x = ( ev.Start() - m_vd.zvStart ) * pxns + ( ( end - ev.Start() ) * pxns - tsz.x ) / 2;+ if( x < 0 || x > w - tsz.x )+ {+ ImGui::PushClipRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + tsz.y * 2 ), true );+ DrawTextContrast( draw, wpos + ImVec2( std::max( std::max( 0., px0 ), std::min( double( w - tsz.x ), x ) ), offset-1 ), local ? 0xFFFFFFFF : 0xAAFFFFFF, label );+ ImGui::PopClipRect();+ }+ else if( ev.Start() == ev.End() )+ {+ DrawTextContrast( draw, wpos + ImVec2( px0 + ( px1 - px0 - tsz.x ) * 0.5, offset-1 ), local ? 0xFFFFFFFF : 0xAAFFFFFF, label );+ }+ else+ {+ DrawTextContrast( draw, wpos + ImVec2( x, offset-1 ), local ? 0xFFFFFFFF : 0xAAFFFFFF, label );+ }+ }+ else+ {+ ImGui::PushClipRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + tsz.y * 2 ), true );+ DrawTextContrast( draw, wpos + ImVec2( ( ev.Start() - vStart ) * pxns, offset-1 ), local ? 0xFFFFFFFF : 0xAAFFFFFF, label );+ ImGui::PopClipRect();+ }++ if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, offset-1 ), wpos + ImVec2( px1, offset + sty ) ) )+ {+ m_drawThreadHighlight = thread;+ ImGui::PopFont();+ ImGui::BeginTooltip();+ TextFocused( "CPU:", RealToString( i ) );+ if( tt )+ {+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ TextFocused( "Package:", RealToString( tt->package ) );+ ImGui::SameLine();+ TextFocused( "Die:", RealToString( tt->die ) );+ ImGui::SameLine();+ TextFocused( "Core:", RealToString( tt->core ) );+ }+ if( local )+ {+ TextFocused( "Program:", m_worker.GetCaptureProgram().c_str() );+ ImGui::SameLine();+ TextDisabledUnformatted( "(profiled program)" );+ SmallColorBox( GetThreadColor( thread, 0 ) );+ ImGui::SameLine();+ TextFocused( "Thread:", m_worker.GetThreadName( thread ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( thread ) );+ + m_drawThreadMigrations = thread;+ m_cpuDataThread = thread;+ }+ else+ {+ if( untracked )+ {+ TextFocused( "Program:", m_worker.GetCaptureProgram().c_str() );+ }+ else+ {+ TextFocused( "Program:", txt );+ }+ ImGui::SameLine();+ if( untracked )+ {+ TextDisabledUnformatted( "(untracked thread in profiled program)" );+ }+ else+ {+ TextDisabledUnformatted( "(external)" );+ }+ TextFocused( "Thread:", m_worker.GetExternalName( thread ).second );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( thread ) );+ }+ ImGui::Separator();+ TextFocused( "Start time:", TimeToStringExact( ev.Start() ) );+ TextFocused( "End time:", TimeToStringExact( end ) );+ TextFocused( "Activity time:", TimeToString( end - ev.Start() ) );+ + // Display data about the switch in+ auto threadCtxSwitches = m_worker.GetContextSwitchData( thread );+ if( threadCtxSwitches )+ {+ auto& v = threadCtxSwitches->v;+ auto it = std::lower_bound( v.begin(), v.end(), ev.Start(), [](const auto& l, const auto& r) { return l.Start() < r; } );+ // We should have the data, or something went wrong.+ assert( it != v.end() && it->Start() == ev.Start() );++ // Do we have information about the previous CSwitch?+ if( it != v.begin() )+ {+ auto& prev = *( it - 1 );+ + ImGui::Separator();++ TextFocused( "Wait reason:", DecodeContextSwitchReasonCode( prev.Reason() ) );+ ImGui::SameLine();+ ImGui::PushFont( m_smallFont );+ ImGui::AlignTextToFramePadding();+ TextDisabledUnformatted( DecodeContextSwitchReason( prev.Reason() ) );+ ImGui::PopFont();+ TextFocused( "Wait state:", DecodeContextSwitchStateCode( prev.State() ) );+ TextFocused( "Waiting time:", TimeToString( it->WakeupVal() - prev.End() ) );+ }+ + // Do we have information about the readying thread?+ if( it->Start() - it->WakeupVal() )+ {+ ImGui::Separator();+ TextFocused( "WakeUp delay:", TimeToString( it->Start() - it->WakeupVal() ) );+ assert( it->WakeupCpu() < cpuCnt );+ const auto& wakeUpCpuCSwitches = cpuData[it->WakeupCpu()].cs;+ auto wakeupit = std::lower_bound( wakeUpCpuCSwitches.begin(), wakeUpCpuCSwitches.end(), it->WakeupVal(), []( const auto& l, const auto& r ) { return l.End() < r; } );+ if( wakeupit != wakeUpCpuCSwitches.end()+ && wakeupit->Start() < it->WakeupVal()+ && it->WakeupVal() < wakeupit->End() )+ {+ TextDisabledUnformatted( "Woken up by:" );+ ImGui::SameLine();++ const auto wakeupThread = m_worker.DecompressThreadExternal( wakeupit->Thread() );+ bool wakeupThreadLocal, wakeupThreadUntracked;+ const char* wakeUpThreadProgram;+ auto wakeuplabel = GetThreadContextData( wakeupThread, wakeupThreadLocal, wakeupThreadUntracked, wakeUpThreadProgram );+ + uint32_t wakeupThreadColor = getDisplayThreadColor( wakeupThread, wakeupThreadLocal, wakeupThreadUntracked );+ TextColoredUnformatted( HighlightColor<75>( wakeupThreadColor ), wakeuplabel );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( wakeupThread ) );+ }+ else+ {+ TextDisabledUnformatted( "Woken up by Kernel" );+ }+ }++ }+++ ImGui::EndTooltip();+ ImGui::PushFont( m_smallFont );++ if( local && IsMouseClicked( 0 ) )+ {+ auto& item = m_tc.GetItem( m_worker.GetThreadData( thread ) );+ item.SetVisible( true );+ item.SetShowFull( true );+ }+ if( IsMouseClicked( 2 ) )+ {+ ZoomToRange( ev.Start(), end );+ }+ }+ }+ }+ }++ char buf[64];+ if( tt )+ {+ auto& topo = m_worker.GetCpuTopology();+ if( topo.size() > 1 )+ {+ sprintf( buf, "[%i:%i:%i] CPU %i", tt->package, tt->die, tt->core, i );+ }+ else+ {+ sprintf( buf, "[%i:%i] CPU %i", tt->die, tt->core, i );+ }+ }+ else+ {+ sprintf( buf, "CPU %i", i );+ }+ const auto txtx = ImGui::CalcTextSize( buf ).x;+ DrawTextSuperContrast( draw, wpos + ImVec2( ty, offset-1 ), 0xFFDD88DD, buf );+ if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( 0, offset-1 ), wpos + ImVec2( sty + txtx, offset + sty ) ) )+ {+ ImGui::PopFont();+ ImGui::BeginTooltip();+ TextFocused( "CPU:", RealToString( i ) );+ if( tt )+ {+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ TextFocused( "Package:", RealToString( tt->package ) );+ ImGui::SameLine();+ TextFocused( "Die:", RealToString( tt->die ) );+ ImGui::SameLine();+ TextFocused( "Core:", RealToString( tt->core ) );+ }+ TextFocused( "Context switch regions:", RealToString( cpuData[i].cs.size() ) );+ ImGui::EndTooltip();+ ImGui::PushFont( m_smallFont );+ }++ offset += sstep;+ }++ if( ImGui::IsMouseHoveringRect( wpos, wpos + ImVec2( w, offset ) ) && IsMouseClickReleased( ImGuiMouseButton_Left ) )+ {+ if( m_drawThreadHighlight != 0 )+ {+ m_selectedThread = m_drawThreadHighlight;+ }+ else+ {+ // Clicked anywhere in the CPUData timeline that is not a thread => Clear selected thread.+ m_selectedThread = 0;+ }+ }+ if( m_drawThreadMigrations != 0 )+ {+ DrawThreadMigrations( ctx, origOffset, m_drawThreadMigrations );+ }++ if( m_selectedThread != 0 )+ {+ DrawThreadMigrations( ctx, origOffset, m_selectedThread );+ }++ ImGui::PopFont();+ return true;+}++void View::DrawThreadMigrations( const TimelineContext& ctx, const int origOffset, uint64_t thread )+{+ const auto& wpos = ctx.wpos;+ const auto w = ctx.w;+ const auto ty = ctx.ty;+ const auto sty = ctx.sty;+ const auto pxns = ctx.pxns;+ const auto nspx = ctx.nspx;+ const auto dpos = wpos + ImVec2(0.5f, 0.5f);+ const auto yMin = ctx.yMin;+ const auto yMax = ctx.yMax;+ const auto hover = ctx.hover;+ const auto vStart = ctx.vStart;+ const auto sstep = sty + 1;++ auto draw = ImGui::GetWindowDrawList();+ auto ctxSwitch = m_worker.GetContextSwitchData( thread );+ if( ctxSwitch )+ {+ const auto color = HighlightColor( GetThreadColor( thread, -8 ) );++ auto& v = ctxSwitch->v;+ auto it = std::lower_bound( v.begin(), v.end(), m_vd.zvStart, [] ( const auto& l, const auto& r ) { return l.End() < r; } );+ if( it != v.begin() ) --it;+ auto end = std::lower_bound( it, v.end(), m_vd.zvEnd, [] ( const auto& l, const auto& r ) { return l.Start() < r; } );+ if( end == v.end() ) --end;++ const auto bgSize = GetScale() * 4.f;+ const auto lnSize = GetScale() * 2.f;+ const auto wakeupLineSize = GetScale() * 1.5f;+++ auto computeScreenPos = [&]( int64_t t, uint8_t cpu ) {+ const auto px = ( t - m_vd.zvStart ) * pxns;+ return dpos + ImVec2( px, origOffset + sty * 0.5f + cpu * sstep );+ };++ auto drawWakeUp = [&]( int64_t start, ImVec2 startPos, int64_t wakeup, uint8_t wakeupcpu, uint32_t wakecolor, bool forceDraw ) {+ if( start != wakeup )+ {+ const auto pw = computeScreenPos( wakeup, wakeupcpu );+ const auto wakeupWidthPixels = startPos.x - pw.x;+ if( forceDraw || ( wakeupWidthPixels >= 0.5 ) )+ {++ DrawLine( draw, pw, startPos, wakecolor, wakeupLineSize );+ draw->AddCircleFilled( pw, bgSize, wakecolor );+ + // Vertical line at beginning of thread to emphasize wakeup+ if( wakeupWidthPixels >= 3 )+ {+ const float halfPx = GetScale() * 0.5f;+ DrawLine( draw, ImVec2{ startPos.x, startPos.y - sty * 0.5f - halfPx }, ImVec2{ startPos.x , startPos.y + sty * 0.5f + halfPx }, 0xFF000000, lnSize * 2 );+ DrawLine( draw, ImVec2{ startPos.x, startPos.y - sty * 0.5f - halfPx }, ImVec2{ startPos.x , startPos.y + sty * 0.5f + halfPx }, wakecolor, lnSize );+ }+ }+ }+ };++ if( it != v.end() && it->Start() > m_vd.zvStart )+ {+ drawWakeUp( it->Start(), computeScreenPos( it->Start(), it->Cpu() ), it->WakeupVal(), it->WakeupCpu(), 0xFF444444, true);+ }+ while( it < end )+ {+ const auto t0 = it->End();+ const auto cpu0 = it->Cpu();+ const auto waitReason = it->Reason();+ const auto waitState = it->State();++ ++it;++ + const auto t1 = it->Start();+ const auto cpu1 = it->Cpu();++ const auto p0 = computeScreenPos( t0, cpu0 );+ const auto p1 = computeScreenPos( t1, cpu1 );++ const auto migrationWidthPixels = p1.x - p0.x;+ if( migrationWidthPixels < 2 )+ {+ DrawLine( draw, p0, p1, color );+ }+ else+ {+ DrawLine( draw, p0, p1, 0xFF000000, bgSize );+ DrawLine( draw, p0, p1, color, lnSize );+ }++ const auto hue = 0.38f * float(waitReason); // Golden angle, gives new colors for each reason+ const auto wakecolor = ImColor::HSV(hue, 1.f, 1.f);+ drawWakeUp( t1, p1, it->WakeupVal(), it->WakeupCpu(), wakecolor, (migrationWidthPixels >= 30) );+ }+ }+}++void View::DrawCpuDataWindow()+{+ const auto scale = GetScale();+ ImGui::SetNextWindowSize( ImVec2( 700 * scale, 800 * scale ), ImGuiCond_FirstUseEver );+ ImGui::Begin( "CPU data", &m_showCpuDataWindow );+ if( ImGui::GetCurrentWindowRead()->SkipItems ) { ImGui::End(); return; }++ struct PidData+ {+ std::vector<uint64_t> tids;+ CpuThreadData data;+ };++ const auto& ctd = m_worker.GetCpuThreadData();+ unordered_flat_map<uint64_t, PidData> pids;+ for( auto& v : ctd )+ {+ uint64_t pid = m_worker.GetPidFromTid( v.first );+ auto it = pids.find( pid );+ if( it == pids.end() )+ {+ it = pids.emplace( pid, PidData {} ).first;+ }+ it->second.tids.emplace_back( v.first );+ it->second.data.runningTime += v.second.runningTime;+ it->second.data.runningRegions += v.second.runningRegions;+ it->second.data.migrations += v.second.migrations;+ }++ TextFocused( "Tracked threads:", RealToString( ctd.size() ) );+ ImGui::SameLine();+ TextFocused( "Tracked processes:", RealToString( pids.size() ) );+ ImGui::Separator();+ ImGui::BeginChild( "##cpudata" );+ if( ImGui::BeginTable( "##cpudata", 5, ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Sortable | ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_ScrollY ) )+ {+ ImGui::TableSetupScrollFreeze( 0, 1 );+ ImGui::TableSetupColumn( "PID/TID", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize );+ ImGui::TableSetupColumn( "Name" );+ ImGui::TableSetupColumn( "Running time", ImGuiTableColumnFlags_PreferSortDescending );+ ImGui::TableSetupColumn( "Slices", ImGuiTableColumnFlags_PreferSortDescending | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize );+ ImGui::TableSetupColumn( "Core jumps", ImGuiTableColumnFlags_PreferSortDescending | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize );+ ImGui::TableHeadersRow();++ std::vector<unordered_flat_map<uint64_t, PidData>::iterator> psort;+ psort.reserve( pids.size() );+ for( auto it = pids.begin(); it != pids.end(); ++it ) psort.emplace_back( it );+ const auto& sortspec = *ImGui::TableGetSortSpecs()->Specs;+ switch( sortspec.ColumnIndex )+ {+ case 0:+ if( sortspec.SortDirection == ImGuiSortDirection_Descending )+ {+ pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->first > r->first; } );+ }+ else+ {+ pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->first < r->first; } );+ }+ break;+ case 1:+ if( sortspec.SortDirection == ImGuiSortDirection_Descending )+ {+ pdqsort_branchless( psort.begin(), psort.end(), [this] ( const auto& l, const auto& r ) { return strcmp( m_worker.GetExternalName( l->second.tids[0] ).first, m_worker.GetExternalName( r->second.tids[0] ).first ) > 0; } );+ }+ else+ {+ pdqsort_branchless( psort.begin(), psort.end(), [this] ( const auto& l, const auto& r ) { return strcmp( m_worker.GetExternalName( l->second.tids[0] ).first, m_worker.GetExternalName( r->second.tids[0] ).first ) < 0; } );+ }+ break;+ case 2:+ if( sortspec.SortDirection == ImGuiSortDirection_Descending )+ {+ pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->second.data.runningTime > r->second.data.runningTime; } );+ }+ else+ {+ pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->second.data.runningTime < r->second.data.runningTime; } );+ }+ break;+ case 3:+ if( sortspec.SortDirection == ImGuiSortDirection_Descending )+ {+ pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->second.data.runningRegions > r->second.data.runningRegions; } );+ }+ else+ {+ pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->second.data.runningRegions < r->second.data.runningRegions; } );+ }+ break;+ case 4:+ if( sortspec.SortDirection == ImGuiSortDirection_Descending )+ {+ pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->second.data.migrations > r->second.data.migrations; } );+ }+ else+ {+ pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->second.data.migrations < r->second.data.migrations; } );+ }+ break;+ default:+ assert( false );+ break;+ }++ const auto thisPid = m_worker.GetPid();+ const auto rtimespan = 1.0 / ( m_worker.GetLastTime() - m_worker.GetFirstTime() );+ const auto ty = ImGui::GetTextLineHeight();++ auto& style = ImGui::GetStyle();+ const auto framePaddingY = style.FramePadding.y;+ bool drawSeparator = false;+ for( auto& pidit : psort )+ {+ ImGui::TableNextRow();+ ImGui::TableNextColumn();+ if( drawSeparator ) ImGui::Separator();++ char buf[128];+ auto& pid = *pidit;+ const auto pidMatch = thisPid != 0 && thisPid == pid.first;+ auto name = m_worker.GetExternalName( pid.second.tids[0] ).first;+ if( pidMatch )+ {+ name = m_worker.GetCaptureProgram().c_str();+ ImGui::PushStyleColor( ImGuiCol_Text, ImVec4( 0.2f, 1.0f, 0.2f, 1.0f ) );+ }+ const auto pidtxt = pid.first == 0 ? "Unknown" : RealToString( pid.first );+ const auto expand = ImGui::TreeNode( pidtxt );+ if( ImGui::IsItemHovered() )+ {+ if( pidMatch )+ {+ m_drawThreadMigrations = pid.first;+ m_cpuDataThread = pid.first;+ }+ m_drawThreadHighlight = pid.first;+ }+ const auto tsz = pid.second.tids.size();+ if( tsz > 1 )+ {+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( tsz ) );+ }+ ImGui::TableNextColumn();+ if( drawSeparator ) ImGui::Separator();+ ImGui::TextUnformatted( pid.first == 0 ? "???" : name );+ if( ImGui::IsItemHovered() )+ {+ if( pidMatch )+ {+ m_drawThreadMigrations = pid.first;+ m_cpuDataThread = pid.first;+ }+ m_drawThreadHighlight = pid.first;+ }+ ImGui::TableNextColumn();+ if( drawSeparator ) ImGui::Separator();+ PrintStringPercent( buf, TimeToString( pid.second.data.runningTime ), double( pid.second.data.runningTime ) * rtimespan * 100 );+ style.FramePadding.y = 0;+ ImGui::ProgressBar( double( pid.second.data.runningTime ) * rtimespan, ImVec2( -1, ty ), buf );+ style.FramePadding.y = framePaddingY;+ ImGui::TableNextColumn();+ if( drawSeparator ) ImGui::Separator();+ ImGui::TextUnformatted( RealToString( pid.second.data.runningRegions ) );+ ImGui::TableNextColumn();+ if( drawSeparator )+ {+ drawSeparator = false;+ ImGui::Separator();+ }+ ImGui::TextUnformatted( RealToString( pid.second.data.migrations ) );+ ImGui::SameLine();+ PrintStringPercent( buf, double( pid.second.data.migrations ) / pid.second.data.runningRegions * 100 );+ TextDisabledUnformatted( buf );+ if( expand )+ {+ switch( sortspec.ColumnIndex )+ {+ case 0:+ if( sortspec.SortDirection == ImGuiSortDirection_Descending )+ {+ pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), []( const auto& l, const auto& r ) { return l > r; } );+ }+ else+ {+ pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end() );+ }+ break;+ case 1:+ if( sortspec.SortDirection == ImGuiSortDirection_Descending )+ {+ pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [this] ( const auto& l, const auto& r ) { return strcmp( m_worker.GetExternalName( l ).second, m_worker.GetExternalName( r ).second ) > 0; } );+ }+ else+ {+ pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [this] ( const auto& l, const auto& r ) { return strcmp( m_worker.GetExternalName( l ).second, m_worker.GetExternalName( r ).second ) < 0; } );+ }+ break;+ case 2:+ if( sortspec.SortDirection == ImGuiSortDirection_Descending )+ {+ pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [&ctd] ( const auto& l, const auto& r ) { return ctd.find( l )->second.runningTime > ctd.find( r )->second.runningTime; } );+ }+ else+ {+ pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [&ctd] ( const auto& l, const auto& r ) { return ctd.find( l )->second.runningTime < ctd.find( r )->second.runningTime; } );+ }+ break;+ case 3:+ if( sortspec.SortDirection == ImGuiSortDirection_Descending )+ {+ pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [&ctd] ( const auto& l, const auto& r ) { return ctd.find( l )->second.runningRegions > ctd.find( r )->second.runningRegions; } );+ }+ else+ {+ pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [&ctd] ( const auto& l, const auto& r ) { return ctd.find( l )->second.runningRegions < ctd.find( r )->second.runningRegions; } );+ }+ break;+ case 4:+ if( sortspec.SortDirection == ImGuiSortDirection_Descending )+ {+ pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [&ctd] ( const auto& l, const auto& r ) { return ctd.find( l )->second.migrations > ctd.find( r )->second.migrations; } );+ }+ else+ {+ pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [&ctd] ( const auto& l, const auto& r ) { return ctd.find( l )->second.migrations < ctd.find( r )->second.migrations; } );+ }+ break;+ default:+ assert( false );+ break;+ }+ drawSeparator = true;+ for( auto& tid : pid.second.tids )+ {+ ImGui::TableNextRow();+ ImGui::TableNextColumn();+ if( drawSeparator ) ImGui::Separator();++ const auto tidMatch = pidMatch && m_worker.IsThreadLocal( tid );+ const char* tname;+ if( tidMatch )+ {+ tname = m_worker.GetThreadName( tid );+ ImGui::PushStyleColor( ImGuiCol_Text, ImVec4( 1.0f, 1.0f, 0.2f, 1.0f ) );+ }+ else+ {+ tname = m_worker.GetExternalName( tid ).second;+ }+ const auto& tit = ctd.find( tid );+ assert( tit != ctd.end() );+ ImGui::TextUnformatted( RealToString( tid ) );+ if( ImGui::IsItemHovered() )+ {+ if( tidMatch )+ {+ m_drawThreadMigrations = tid;+ m_cpuDataThread = tid;+ }+ m_drawThreadHighlight = tid;+ }+ ImGui::TableNextColumn();+ if( drawSeparator ) ImGui::Separator();+ if( tidMatch )+ {+ SmallColorBox( GetThreadColor( tid, 0 ) );+ ImGui::SameLine();+ }+ ImGui::TextUnformatted( tname );+ if( ImGui::IsItemHovered() )+ {+ if( tidMatch )+ {+ m_drawThreadMigrations = tid;+ m_cpuDataThread = tid;+ }+ m_drawThreadHighlight = tid;+ }+ ImGui::TableNextColumn();+ if( drawSeparator ) ImGui::Separator();+ PrintStringPercent( buf, TimeToString( tit->second.runningTime ), double( tit->second.runningTime ) * rtimespan * 100 );+ style.FramePadding.y = 0;+ ImGui::ProgressBar( double( tit->second.runningTime ) * rtimespan, ImVec2( -1, ty ), buf );+ style.FramePadding.y = framePaddingY;+ ImGui::TableNextColumn();+ if( drawSeparator ) ImGui::Separator();+ ImGui::TextUnformatted( RealToString( tit->second.runningRegions ) );+ ImGui::TableNextColumn();+ if( drawSeparator )+ {+ drawSeparator = false;+ ImGui::Separator();+ }+ ImGui::TextUnformatted( RealToString( tit->second.migrations ) );+ ImGui::SameLine();+ PrintStringPercent( buf, double( tit->second.migrations ) / tit->second.runningRegions * 100 );+ TextDisabledUnformatted( buf );+ if( tidMatch )+ {+ ImGui::PopStyleColor();+ }+ }+ ImGui::TreePop();+ drawSeparator = true;+ }+ if( pidMatch )+ {+ ImGui::PopStyleColor();+ }+ }+ ImGui::EndTable();+ }+ ImGui::EndChild();+ ImGui::End();+}+++}
+ cbits/tracy/profiler/src/profiler/TracyView_FindZone.cpp view
@@ -0,0 +1,2036 @@+#include <numeric>++#include "imgui.h"++#include "../public/common/TracyStackFrames.hpp"+#include "TracyFilesystem.hpp"+#include "TracyImGui.hpp"+#include "TracyMouse.hpp"+#include "TracyPrint.hpp"+#include "TracySort.hpp"+#include "TracyView.hpp"+#include "tracy_pdqsort.h"++namespace tracy+{++extern double s_time;++#ifndef TRACY_NO_STATISTICS+void View::FindZones()+{+ m_findZone.hasResults = true;+ m_findZone.match = m_worker.GetMatchingSourceLocation( m_findZone.pattern, m_findZone.ignoreCase );+ if( m_findZone.match.empty() ) return;++ auto it = m_findZone.match.begin();+ while( it != m_findZone.match.end() )+ {+ if( m_worker.GetZonesForSourceLocation( *it ).zones.empty() )+ {+ it = m_findZone.match.erase( it );+ }+ else+ {+ ++it;+ }+ }+}+#endif++uint64_t View::GetSelectionTarget( const Worker::ZoneThreadData& ev, FindZone::GroupBy groupBy ) const+{+ switch( groupBy )+ {+ case FindZone::GroupBy::Thread:+ return ev.Thread();+ case FindZone::GroupBy::UserText:+ {+ const auto& zone = *ev.Zone();+ if( !m_worker.HasZoneExtra( zone ) ) return std::numeric_limits<uint64_t>::max();+ const auto& extra = m_worker.GetZoneExtra( zone );+ return extra.text.Active() ? extra.text.Idx() : std::numeric_limits<uint64_t>::max();+ }+ case FindZone::GroupBy::ZoneName:+ {+ const auto& zone = *ev.Zone();+ if( !m_worker.HasZoneExtra( zone ) ) return std::numeric_limits<uint64_t>::max();+ const auto& extra = m_worker.GetZoneExtra( zone );+ return extra.name.Active() ? extra.name.Idx() : std::numeric_limits<uint64_t>::max();+ }+ case FindZone::GroupBy::Callstack:+ return m_worker.GetZoneExtra( *ev.Zone() ).callstack.Val();+ case FindZone::GroupBy::Parent:+ {+ const auto parent = GetZoneParent( *ev.Zone(), m_worker.DecompressThread( ev.Thread() ) );+ return parent ? uint64_t( parent->SrcLoc() ) : 0;+ }+ case FindZone::GroupBy::NoGrouping:+ return 0;+ default:+ assert( false );+ return 0;+ }+}++void View::DrawZoneList( int id, const Vector<short_ptr<ZoneEvent>>& zones )+{+ const auto zsz = zones.size();+ char buf[32];+ sprintf( buf, "%i##zonelist", id );+ if( !ImGui::BeginTable( buf, 3, ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_Resizable | ImGuiTableFlags_Hideable | ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_Sortable | ImGuiTableFlags_ScrollY, ImVec2( 0, ImGui::GetTextLineHeightWithSpacing() * std::min<size_t>( zsz + 1, 15 ) ) ) )+ {+ ImGui::TreePop();+ return;+ }+ ImGui::TableSetupScrollFreeze( 0, 1 );+ ImGui::TableSetupColumn( "Time from start" );+ ImGui::TableSetupColumn( "Execution time", ImGuiTableColumnFlags_PreferSortDescending );+ ImGui::TableSetupColumn( "Name", ImGuiTableColumnFlags_NoSort );+ ImGui::TableHeadersRow();++ const Vector<short_ptr<ZoneEvent>>* zonesToIterate = &zones;+ Vector<short_ptr<ZoneEvent>> sortedZones;++ const auto& sortspec = *ImGui::TableGetSortSpecs()->Specs;+ if( sortspec.ColumnIndex != 0 || sortspec.SortDirection != ImGuiSortDirection_Ascending )+ {+ zonesToIterate = &sortedZones;+ sortedZones.reserve_and_use( zones.size() );+ memcpy( sortedZones.data(), zones.data(), zones.size() * sizeof( decltype( *zones.begin() ) ) );++ switch( sortspec.ColumnIndex )+ {+ case 0:+ assert( sortspec.SortDirection != ImGuiSortDirection_Descending );+ std::reverse( sortedZones.begin(), sortedZones.end() );+ break;+ case 1:+ if( m_findZone.selfTime )+ {+ if( sortspec.SortDirection == ImGuiSortDirection_Descending )+ {+ pdqsort_branchless( sortedZones.begin(), sortedZones.end(), [this]( const auto& lhs, const auto& rhs ) {+ return m_worker.GetZoneEndDirect( *lhs ) - lhs->Start() - this->GetZoneChildTimeFast( *lhs ) >+ m_worker.GetZoneEndDirect( *rhs ) - rhs->Start() - this->GetZoneChildTimeFast( *rhs );+ } );+ }+ else+ {+ pdqsort_branchless( sortedZones.begin(), sortedZones.end(), [this]( const auto& lhs, const auto& rhs ) {+ return m_worker.GetZoneEndDirect( *lhs ) - lhs->Start() - this->GetZoneChildTimeFast( *lhs ) <+ m_worker.GetZoneEndDirect( *rhs ) - rhs->Start() - this->GetZoneChildTimeFast( *rhs );+ } );+ }+ }+ else if( m_findZone.runningTime )+ {+ if( sortspec.SortDirection == ImGuiSortDirection_Descending )+ {+ pdqsort_branchless( sortedZones.begin(), sortedZones.end(), [this]( const auto& lhs, const auto& rhs ) {+ const auto ctx0 = m_worker.GetContextSwitchData( GetZoneThread( *lhs ) );+ const auto ctx1 = m_worker.GetContextSwitchData( GetZoneThread( *rhs ) );+ int64_t t0, t1;+ uint64_t c0, c1;+ GetZoneRunningTime( ctx0, *lhs, t0, c0 );+ GetZoneRunningTime( ctx1, *rhs, t1, c1 );+ return t0 > t1;+ } );+ }+ else+ {+ pdqsort_branchless( sortedZones.begin(), sortedZones.end(), [this]( const auto& lhs, const auto& rhs ) {+ const auto ctx0 = m_worker.GetContextSwitchData( GetZoneThread( *lhs ) );+ const auto ctx1 = m_worker.GetContextSwitchData( GetZoneThread( *rhs ) );+ int64_t t0, t1;+ uint64_t c0, c1;+ GetZoneRunningTime( ctx0, *lhs, t0, c0 );+ GetZoneRunningTime( ctx1, *rhs, t1, c1 );+ return t0 < t1;+ } );+ }+ }+ else+ {+ if( sortspec.SortDirection == ImGuiSortDirection_Descending )+ {+ pdqsort_branchless( sortedZones.begin(), sortedZones.end(), [this]( const auto& lhs, const auto& rhs ) {+ return m_worker.GetZoneEndDirect( *lhs ) - lhs->Start() > m_worker.GetZoneEndDirect( *rhs ) - rhs->Start();+ } );+ }+ else+ {+ pdqsort_branchless( sortedZones.begin(), sortedZones.end(), [this]( const auto& lhs, const auto& rhs ) {+ return m_worker.GetZoneEndDirect( *lhs ) - lhs->Start() < m_worker.GetZoneEndDirect( *rhs ) - rhs->Start();+ } );+ }+ }+ break;+ case 2:+ if( sortspec.SortDirection == ImGuiSortDirection_Descending )+ {+ pdqsort_branchless( sortedZones.begin(), sortedZones.end(), [this]( const auto& lhs, const auto& rhs ) {+ const auto hle = m_worker.HasZoneExtra( *lhs );+ const auto hre = m_worker.HasZoneExtra( *rhs );+ if( !( hle & hre ) ) return hle > hre;+ return strcmp( m_worker.GetString( m_worker.GetZoneExtra( *lhs ).name ), m_worker.GetString( m_worker.GetZoneExtra( *rhs ).name ) ) < 0;+ } );+ }+ else+ {+ pdqsort_branchless( sortedZones.begin(), sortedZones.end(), [this]( const auto& lhs, const auto& rhs ) {+ const auto hle = m_worker.HasZoneExtra( *lhs );+ const auto hre = m_worker.HasZoneExtra( *rhs );+ if( !( hle & hre ) ) return hle < hre;+ return strcmp( m_worker.GetString( m_worker.GetZoneExtra( *lhs ).name ), m_worker.GetString( m_worker.GetZoneExtra( *rhs ).name ) ) > 0;+ } );+ }+ break;+ default:+ assert( false );+ break;+ }+ }++ ImGuiListClipper clipper;+ clipper.Begin( zonesToIterate->size() );+ while( clipper.Step() )+ {+ for( auto i=clipper.DisplayStart; i<clipper.DisplayEnd; i++ )+ {+ ImGui::TableNextRow();+ ImGui::TableNextColumn();++ auto ev = (*zonesToIterate)[i].get();+ const auto end = m_worker.GetZoneEndDirect( *ev );+ int64_t timespan;+ if( m_findZone.runningTime )+ {+ const auto ctx = m_worker.GetContextSwitchData( GetZoneThread( *ev ) );+ uint64_t cnt;+ GetZoneRunningTime( ctx, *ev, timespan, cnt );+ }+ else+ {+ timespan = end - ev->Start();+ if( m_findZone.selfTime ) timespan -= GetZoneChildTimeFast( *ev );+ }++ ImGui::PushID( ev );+ if( m_zoneHover == ev ) ImGui::PushStyleColor( ImGuiCol_Text, ImVec4( 0, 1, 0, 1 ) );+ if( ImGui::Selectable( TimeToStringExact( ev->Start() ), m_zoneInfoWindow == ev, ImGuiSelectableFlags_SpanAllColumns ) )+ {+ ShowZoneInfo( *ev );+ }+ if( ImGui::IsItemHovered() )+ {+ m_zoneHighlight = ev;+ if( IsMouseClicked( 2 ) )+ {+ ZoomToZone( *ev );+ }+ ZoneTooltip( *ev );+ m_zoneHover2 = ev;+ }++ ImGui::TableNextColumn();+ ImGui::TextUnformatted( TimeToString( timespan ) );+ ImGui::TableNextColumn();+ if( m_worker.HasZoneExtra( *ev ) )+ {+ const auto& extra = m_worker.GetZoneExtra( *ev );+ if( extra.name.Active() )+ {+ ImGui::TextUnformatted( m_worker.GetString( extra.name ) );+ }+ }+ if( m_zoneHover == ev ) ImGui::PopStyleColor();+ ImGui::PopID();+ }+ }+ ImGui::EndTable();+ ImGui::TreePop();+}++void View::DrawFindZone()+{+ if( m_shortcut == ShortcutAction::OpenFind ) ImGui::SetNextWindowFocus();++ const auto scale = GetScale();+ ImGui::SetNextWindowSize( ImVec2( 520 * scale, 800 * scale ), ImGuiCond_FirstUseEver );+ ImGui::Begin( "Find zone", &m_findZone.show, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse );+ if( ImGui::GetCurrentWindowRead()->SkipItems ) { ImGui::End(); return; }+#ifdef TRACY_NO_STATISTICS+ ImGui::TextWrapped( "Collection of statistical data is disabled in this build." );+ ImGui::TextWrapped( "Rebuild without the TRACY_NO_STATISTICS macro to enable zone search." );+#else+ if( !m_worker.AreSourceLocationZonesReady() )+ {+ const auto ty = ImGui::GetTextLineHeight();+ ImGui::PushFont( m_bigFont );+ ImGui::Dummy( ImVec2( 0, ( ImGui::GetContentRegionAvail().y - ImGui::GetTextLineHeight() * 2 - ty ) * 0.5f ) );+ TextCentered( ICON_FA_CROW );+ TextCentered( "Please wait, computing data..." );+ ImGui::PopFont();+ DrawWaitingDots( s_time );+ ImGui::End();+ return;+ }+ if( m_worker.GetZoneCount() == 0 )+ {+ ImGui::PushFont( m_bigFont );+ ImGui::Dummy( ImVec2( 0, ( ImGui::GetContentRegionAvail().y - ImGui::GetTextLineHeight() * 2 ) * 0.5f ) );+ TextCentered( ICON_FA_CROW );+ TextCentered( "No zones were collected" );+ ImGui::PopFont();+ ImGui::End();+ return;+ }++ bool findClicked = false;++ ImGui::PushItemWidth( -0.01f );+ if( m_shortcut == ShortcutAction::OpenFind )+ {+ ImGui::SetKeyboardFocusHere();+ m_shortcut = ShortcutAction::None;+ }+ else if( ImGui::IsWindowAppearing() )+ {+ ImGui::SetKeyboardFocusHere();+ }+ findClicked |= ImGui::InputTextWithHint( "###findzone", "Enter zone name to search for", m_findZone.pattern, 1024, ImGuiInputTextFlags_EnterReturnsTrue );+ ImGui::PopItemWidth();++ findClicked |= ImGui::Button( ICON_FA_MAGNIFYING_GLASS " Find" );+ ImGui::SameLine();++ if( ImGui::Button( ICON_FA_BAN " Clear" ) )+ {+ m_findZone.pattern[0] = '\0';+ m_findZone.Reset();+ }+ ImGui::SameLine();+ ImGui::Checkbox( "Ignore case", &m_findZone.ignoreCase );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ if( ImGui::Checkbox( "Limit range", &m_findZone.range.active ) )+ {+ if( m_findZone.range.active && m_findZone.range.min == 0 && m_findZone.range.max == 0 )+ {+ m_findZone.range.min = m_vd.zvStart;+ m_findZone.range.max = m_vd.zvEnd;+ }+ }+ if( m_findZone.range.active )+ {+ ImGui::SameLine();+ TextColoredUnformatted( 0xFF00FFFF, ICON_FA_TRIANGLE_EXCLAMATION );+ ImGui::SameLine();+ ToggleButton( ICON_FA_RULER " Limits", m_showRanges );+ }++ if( m_findZone.rangeSlim != m_findZone.range )+ {+ m_findZone.ResetMatch();+ m_findZone.rangeSlim = m_findZone.range;+ }++ if( findClicked )+ {+ m_findZone.Reset();+ FindZones();+ }++ ImGui::Separator();+ ImGui::BeginChild( "##findzone" );++ if( m_findZone.match.empty() )+ {+ ImGui::PushFont( m_bigFont );+ ImGui::Dummy( ImVec2( 0, ( ImGui::GetContentRegionAvail().y - ImGui::GetTextLineHeight() * 2 ) * 0.5f ) );+ TextCentered( ICON_FA_CROW );+ if( m_findZone.hasResults )+ {+ TextCentered( "No matching zones found" );+ }+ else+ {+ TextCentered( "Please enter search pattern" );+ }+ ImGui::PopFont();+ }+ else+ {+ Achieve( "findZone" );++ const auto rangeMin = m_findZone.range.min;+ const auto rangeMax = m_findZone.range.max;++ bool expand = ImGui::TreeNodeEx( "Matched source locations", ImGuiTreeNodeFlags_DefaultOpen );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%zu)", m_findZone.match.size() );+ if( expand )+ {+ auto prev = m_findZone.selMatch;+ int idx = 0;+ for( auto& v : m_findZone.match )+ {+ auto& srcloc = m_worker.GetSourceLocation( v );+ auto& zones = m_worker.GetZonesForSourceLocation( v ).zones;+ SmallColorBox( GetSrcLocColor( srcloc, 0 ) );+ ImGui::SameLine();+ ImGui::PushID( idx );+ ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 0, 0 ) );+ ImGui::RadioButton( m_worker.GetString( srcloc.name.active ? srcloc.name : srcloc.function ), &m_findZone.selMatch, idx++ );+ ImGui::PopStyleVar();+ if( m_findZoneBuzzAnim.Match( idx ) )+ {+ const auto time = m_findZoneBuzzAnim.Time();+ const auto indentVal = sin( time * 60.f ) * 10.f * time;+ ImGui::SameLine( 0, ImGui::GetStyle().ItemSpacing.x + indentVal );+ }+ else+ {+ ImGui::SameLine();+ }+ const auto fileName = m_worker.GetString( srcloc.file );+ ImGui::TextColored( ImVec4( 0.5, 0.5, 0.5, 1 ), "(%s) %s", RealToString( zones.size() ), LocationToString( fileName, srcloc.line ) );+ if( ImGui::IsItemHovered() )+ {+ DrawSourceTooltip( fileName, srcloc.line );+ if( ImGui::IsItemClicked( 1 ) )+ {+ if( SourceFileValid( fileName, m_worker.GetCaptureTime(), *this, m_worker ) )+ {+ ViewSourceCheckKeyMod( fileName, srcloc.line, m_worker.GetString( srcloc.function ) );+ }+ else+ {+ m_findZoneBuzzAnim.Enable( idx, 0.5f );+ }+ }+ }+ ImGui::PopID();+ }+ ImGui::TreePop();++ if( m_findZone.selMatch != prev )+ {+ m_findZone.ResetMatch();+ }+ }+ if( m_findZone.scheduleResetMatch )+ {+ m_findZone.scheduleResetMatch = false;+ m_findZone.ResetMatch();+ }++ ImGui::Separator();++ auto& zoneData = m_worker.GetZonesForSourceLocation( m_findZone.match[m_findZone.selMatch] );+ auto& zones = zoneData.zones;+ zones.ensure_sorted();+ if( ImGui::TreeNodeEx( "Histogram", ImGuiTreeNodeFlags_DefaultOpen ) )+ {+ const auto ty = ImGui::GetTextLineHeight();++ int64_t tmin = m_findZone.tmin;+ int64_t tmax = m_findZone.tmax;+ int64_t total = m_findZone.total;+ const auto zsz = zones.size();+ if( m_findZone.sortedNum != zsz )+ {+ auto& vec = m_findZone.sorted;+ const auto vszorig = vec.size();+ vec.reserve( zsz );+ size_t i;+ if( m_findZone.runningTime )+ {+ if( m_findZone.range.active )+ {+ for( i=m_findZone.sortedNum; i<zsz; i++ )+ {+ auto& zone = *zones[i].Zone();+ const auto end = zone.End();+ if( end > rangeMax || zone.Start() < rangeMin ) continue;+ const auto ctx = m_worker.GetContextSwitchData( m_worker.DecompressThread( zones[i].Thread() ) );+ if( !ctx ) break;+ int64_t t;+ uint64_t cnt;+ if( !GetZoneRunningTime( ctx, zone, t, cnt ) ) break;+ vec.push_back_no_space_check( t );+ total += t;+ if( t < tmin ) tmin = t;+ else if( t > tmax ) tmax = t;+ }+ }+ else+ {+ for( i=m_findZone.sortedNum; i<zsz; i++ )+ {+ auto& zone = *zones[i].Zone();+ const auto ctx = m_worker.GetContextSwitchData( m_worker.DecompressThread( zones[i].Thread() ) );+ if( !ctx ) break;+ int64_t t;+ uint64_t cnt;+ if( !GetZoneRunningTime( ctx, zone, t, cnt ) ) break;+ vec.push_back_no_space_check( t );+ total += t;+ if( t < tmin ) tmin = t;+ else if( t > tmax ) tmax = t;+ }+ }+ }+ else if( m_findZone.selfTime )+ {+ tmin = zoneData.selfMin;+ tmax = zoneData.selfMax;+ if( m_findZone.range.active )+ {+ for( i=m_findZone.sortedNum; i<zsz; i++ )+ {+ auto& zone = *zones[i].Zone();+ const auto end = zone.End();+ const auto start = zone.Start();+ if( end > rangeMax || start < rangeMin ) continue;+ const auto t = end - start - GetZoneChildTimeFast( zone );+ vec.push_back_no_space_check( t );+ total += t;+ }+ }+ else+ {+ for( i=m_findZone.sortedNum; i<zsz; i++ )+ {+ auto& zone = *zones[i].Zone();+ const auto end = zone.End();+ const auto t = end - zone.Start() - GetZoneChildTimeFast( zone );+ vec.push_back_no_space_check( t );+ total += t;+ }+ }+ }+ else+ {+ tmin = zoneData.min;+ tmax = zoneData.max;+ if( m_findZone.range.active )+ {+ for( i=m_findZone.sortedNum; i<zsz; i++ )+ {+ auto& zone = *zones[i].Zone();+ const auto end = zone.End();+ const auto start = zone.Start();+ if( end > rangeMax || start < rangeMin ) continue;+ const auto t = end - start;+ vec.push_back_no_space_check( t );+ total += t;+ }+ }+ else+ {+ for( i=m_findZone.sortedNum; i<zsz; i++ )+ {+ auto& zone = *zones[i].Zone();+ const auto end = zone.End();+ const auto t = end - zone.Start();+ vec.push_back_no_space_check( t );+ total += t;+ }+ }+ }+ auto mid = vec.begin() + vszorig;+#ifdef __EMSCRIPTEN__+ pdqsort_branchless( mid, vec.end() );+#else+ ppqsort::sort( ppqsort::execution::par, mid, vec.end() );+#endif+ std::inplace_merge( vec.begin(), mid, vec.end() );++ const auto vsz = vec.size();+ if( vsz != 0 )+ {+ m_findZone.average = float( total ) / vsz;+ m_findZone.median = vec[vsz/2];+ m_findZone.p75 = vec[3 * (vsz / 4)];+ m_findZone.p90 = vec[vsz / 10 * 9];+ m_findZone.total = total;+ m_findZone.sortedNum = i;+ m_findZone.tmin = tmin;+ m_findZone.tmax = tmax;+ }+ }++ if( m_findZone.selGroup != m_findZone.Unselected )+ {+ if( m_findZone.selSortNum != m_findZone.sortedNum )+ {+ const auto selGroup = m_findZone.selGroup;+ const auto groupBy = m_findZone.groupBy;++ auto& vec = m_findZone.selSort;+ vec.reserve( zsz );+ auto act = m_findZone.selSortActive;+ int64_t total = m_findZone.selTotal;+ if( m_findZone.runningTime )+ {+ if( m_findZone.range.active )+ {+ for( size_t i=m_findZone.selSortNum; i<m_findZone.sortedNum; i++ )+ {+ auto& ev = zones[i];+ if( ev.Zone()->End() > rangeMax || ev.Zone()->Start() < rangeMin ) continue;+ if( m_filteredZones.contains( &ev ) ) continue;+ if( selGroup == GetSelectionTarget( ev, groupBy ) )+ {+ const auto ctx = m_worker.GetContextSwitchData( m_worker.DecompressThread( zones[i].Thread() ) );+ int64_t t;+ uint64_t cnt;+ GetZoneRunningTime( ctx, *ev.Zone(), t, cnt );+ vec.push_back_no_space_check( t );+ act++;+ total += t;+ }+ }+ }+ else+ {+ for( size_t i=m_findZone.selSortNum; i<m_findZone.sortedNum; i++ )+ {+ auto& ev = zones[i];+ if( m_filteredZones.contains( &ev ) ) continue;+ if( selGroup == GetSelectionTarget( ev, groupBy ) )+ {+ const auto ctx = m_worker.GetContextSwitchData( m_worker.DecompressThread( zones[i].Thread() ) );+ int64_t t;+ uint64_t cnt;+ GetZoneRunningTime( ctx, *ev.Zone(), t, cnt );+ vec.push_back_no_space_check( t );+ act++;+ total += t;+ }+ }+ }+ }+ else if( m_findZone.selfTime )+ {+ if( m_findZone.range.active )+ {+ for( size_t i=m_findZone.selSortNum; i<m_findZone.sortedNum; i++ )+ {+ auto& ev = zones[i];+ if( ev.Zone()->End() > rangeMax || ev.Zone()->Start() < rangeMin ) continue;+ if( m_filteredZones.contains( &ev ) ) continue;+ if( selGroup == GetSelectionTarget( ev, groupBy ) )+ {+ const auto t = ev.Zone()->End() - ev.Zone()->Start() - GetZoneChildTimeFast( *ev.Zone() );+ vec.push_back_no_space_check( t );+ act++;+ total += t;+ }+ }+ }+ else+ {+ for( size_t i=m_findZone.selSortNum; i<m_findZone.sortedNum; i++ )+ {+ auto& ev = zones[i];+ if( m_filteredZones.contains( &ev ) ) continue;+ if( selGroup == GetSelectionTarget( ev, groupBy ) )+ {+ const auto t = ev.Zone()->End() - ev.Zone()->Start() - GetZoneChildTimeFast( *ev.Zone() );+ vec.push_back_no_space_check( t );+ act++;+ total += t;+ }+ }+ }+ }+ else+ {+ if( m_findZone.range.active )+ {+ for( size_t i=m_findZone.selSortNum; i<m_findZone.sortedNum; i++ )+ {+ auto& ev = zones[i];+ if( ev.Zone()->End() > rangeMax || ev.Zone()->Start() < rangeMin ) continue;+ if( m_filteredZones.contains( &ev ) ) continue;+ if( selGroup == GetSelectionTarget( ev, groupBy ) )+ {+ const auto t = ev.Zone()->End() - ev.Zone()->Start();+ vec.push_back_no_space_check( t );+ act++;+ total += t;+ }+ }+ }+ else+ {+ for( size_t i=m_findZone.selSortNum; i<m_findZone.sortedNum; i++ )+ {+ auto& ev = zones[i];+ if( m_filteredZones.contains( &ev ) ) continue;+ if( selGroup == GetSelectionTarget( ev, groupBy ) )+ {+ const auto t = ev.Zone()->End() - ev.Zone()->Start();+ vec.push_back_no_space_check( t );+ act++;+ total += t;+ }+ }+ }+ }+ if( !vec.empty() )+ {+ auto mid = vec.begin() + m_findZone.selSortActive;+ pdqsort_branchless( mid, vec.end() );+ std::inplace_merge( vec.begin(), mid, vec.end() );++ m_findZone.selAverage = float( total ) / act;+ m_findZone.selMedian = vec[act/2];+ m_findZone.selTotal = total;+ m_findZone.selSortNum = m_findZone.sortedNum;+ m_findZone.selSortActive = act;+ }+ }+ }++ if( tmin != std::numeric_limits<int64_t>::max() && !m_findZone.sorted.empty() )+ {+ TextDisabledUnformatted( "Minimum values in bin:" );+ ImGui::SameLine();+ ImGui::SetNextItemWidth( ImGui::CalcTextSize( "123456890123456" ).x );+ ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 1, 1 ) );+ ImGui::InputInt( "##minBinVal", &m_findZone.minBinVal );+ if( m_findZone.minBinVal < 1 ) m_findZone.minBinVal = 1;+ ImGui::SameLine();+ if( ImGui::Button( "Reset" ) ) m_findZone.minBinVal = 1;+ ImGui::PopStyleVar();++ SmallCheckbox( "Log values", &m_findZone.logVal );+ ImGui::SameLine();+ if( SmallCheckbox( "Log time", &m_findZone.logTime ) )+ {+ m_findZone.binCache.numBins = -1;+ }+ ImGui::SameLine();+ SmallCheckbox( "Cumulate time", &m_findZone.cumulateTime );+ ImGui::SameLine();+ DrawHelpMarker( "Show total time taken by calls in each bin instead of call counts." );+ ImGui::SameLine();+ if( SmallCheckbox( "Self time", &m_findZone.selfTime ) )+ {+ m_findZone.runningTime = false;+ m_findZone.scheduleResetMatch = true;+ }+ ImGui::SameLine();+ char buf[64];+ PrintStringPercent( buf, 100.f * zoneData.selfTotal / zoneData.total );+ TextDisabledUnformatted( buf );+ if( m_worker.HasContextSwitches() )+ {+ ImGui::SameLine();+ if( SmallCheckbox( "Running time", &m_findZone.runningTime ) )+ {+ m_findZone.selfTime = false;+ m_findZone.scheduleResetMatch = true;+ }+ }++ const auto cumulateTime = m_findZone.cumulateTime;++ if( tmax - tmin > 0 )+ {+ const auto w = ImGui::GetContentRegionAvail().x;++ const auto numBins = int64_t( w - 4 );+ if( numBins > 1 )+ {+ const auto s = std::min( m_findZone.highlight.start, m_findZone.highlight.end );+ const auto e = std::max( m_findZone.highlight.start, m_findZone.highlight.end );++ const auto& sorted = m_findZone.sorted;++ auto sortedBegin = sorted.begin();+ auto sortedEnd = sorted.end();+ while( sortedBegin != sortedEnd && *sortedBegin == 0 ) ++sortedBegin;++ if( m_findZone.minBinVal > 1 || m_findZone.range.active )+ {+ if( m_findZone.logTime )+ {+ const auto tMinLog = log10( tmin );+ const auto zmax = ( log10( tmax ) - tMinLog ) / numBins;+ int64_t i;+ for( i=0; i<numBins; i++ )+ {+ const auto nextBinVal = int64_t( pow( 10.0, tMinLog + ( i+1 ) * zmax ) );+ auto nit = std::lower_bound( sortedBegin, sortedEnd, nextBinVal );+ const auto distance = std::distance( sortedBegin, nit );+ if( distance >= m_findZone.minBinVal ) break;+ sortedBegin = nit;+ }+ for( int64_t j=numBins-1; j>i; j-- )+ {+ const auto nextBinVal = int64_t( pow( 10.0, tMinLog + ( j-1 ) * zmax ) );+ auto nit = std::lower_bound( sortedBegin, sortedEnd, nextBinVal );+ const auto distance = std::distance( nit, sortedEnd );+ if( distance >= m_findZone.minBinVal ) break;+ sortedEnd = nit;+ }+ }+ else+ {+ const auto zmax = tmax - tmin;+ int64_t i;+ for( i=0; i<numBins; i++ )+ {+ const auto nextBinVal = tmin + ( i+1 ) * zmax / numBins;+ auto nit = std::lower_bound( sortedBegin, sortedEnd, nextBinVal );+ const auto distance = std::distance( sortedBegin, nit );+ if( distance >= m_findZone.minBinVal ) break;+ sortedBegin = nit;+ }+ for( int64_t j=numBins-1; j>i; j-- )+ {+ const auto nextBinVal = tmin + ( j-1 ) * zmax / numBins;+ auto nit = std::lower_bound( sortedBegin, sortedEnd, nextBinVal );+ const auto distance = std::distance( nit, sortedEnd );+ if( distance >= m_findZone.minBinVal ) break;+ sortedEnd = nit;+ }+ }++ if( sortedBegin != sorted.end() )+ {+ tmin = *sortedBegin;+ tmax = *(sortedEnd-1);+ total = 0;+ for( auto ptr = sortedBegin; ptr != sortedEnd; ptr++ ) total += *ptr;+ }+ }++ if( numBins > m_findZone.numBins )+ {+ m_findZone.numBins = numBins;+ m_findZone.bins = std::make_unique<int64_t[]>( numBins );+ m_findZone.binTime = std::make_unique<int64_t[]>( numBins );+ m_findZone.selBin = std::make_unique<int64_t[]>( numBins );+ m_findZone.binCache.numBins = -1;+ }++ const auto& bins = m_findZone.bins;+ const auto& binTime = m_findZone.binTime;+ const auto& selBin = m_findZone.selBin;++ const auto distBegin = std::distance( sorted.begin(), sortedBegin );+ const auto distEnd = std::distance( sorted.begin(), sortedEnd );+ if( m_findZone.binCache.numBins != numBins ||+ m_findZone.binCache.distBegin != distBegin ||+ m_findZone.binCache.distEnd != distEnd )+ {+ m_findZone.binCache.numBins = numBins;+ m_findZone.binCache.distBegin = distBegin;+ m_findZone.binCache.distEnd = distEnd;++ memset( bins.get(), 0, sizeof( int64_t ) * numBins );+ memset( binTime.get(), 0, sizeof( int64_t ) * numBins );+ memset( selBin.get(), 0, sizeof( int64_t ) * numBins );++ int64_t selectionTime = 0;++ if( m_findZone.logTime )+ {+ const auto tMinLog = log10( tmin );+ const auto zmax = ( log10( tmax ) - tMinLog ) / numBins;+ {+ auto zit = sortedBegin;+ for( int64_t i=0; i<numBins; i++ )+ {+ const auto nextBinVal = int64_t( pow( 10.0, tMinLog + ( i+1 ) * zmax ) );+ auto nit = std::lower_bound( zit, sortedEnd, nextBinVal );+ const auto distance = std::distance( zit, nit );+ const auto timeSum = std::accumulate( zit, nit, int64_t( 0 ) );+ bins[i] = distance;+ binTime[i] = timeSum;+ if( m_findZone.highlight.active )+ {+ auto end = nit == zit ? zit : nit-1;+ if( *zit >= s && *end <= e ) selectionTime += timeSum;+ }+ zit = nit;+ }+ const auto timeSum = std::accumulate( zit, sortedEnd, int64_t( 0 ) );+ bins[numBins-1] += std::distance( zit, sortedEnd );+ binTime[numBins-1] += timeSum;+ if( m_findZone.highlight.active && *zit >= s && *(sortedEnd-1) <= e ) selectionTime += timeSum;+ }++ if( m_findZone.selGroup != m_findZone.Unselected )+ {+ auto zit = m_findZone.selSort.begin();+ while( zit != m_findZone.selSort.end() && *zit == 0 ) ++zit;+ for( int64_t i=0; i<numBins; i++ )+ {+ const auto nextBinVal = int64_t( pow( 10.0, tMinLog + ( i+1 ) * zmax ) );+ auto nit = std::lower_bound( zit, m_findZone.selSort.end(), nextBinVal );+ if( cumulateTime )+ {+ selBin[i] = std::accumulate( zit, nit, int64_t( 0 ) );+ }+ else+ {+ selBin[i] = std::distance( zit, nit );+ }+ zit = nit;+ }+ }+ }+ else+ {+ const auto zmax = tmax - tmin;+ auto zit = sortedBegin;+ for( int64_t i=0; i<numBins; i++ )+ {+ const auto nextBinVal = tmin + ( i+1 ) * zmax / numBins;+ auto nit = std::lower_bound( zit, sortedEnd, nextBinVal );+ const auto distance = std::distance( zit, nit );+ const auto timeSum = std::accumulate( zit, nit, int64_t( 0 ) );+ bins[i] = distance;+ binTime[i] = timeSum;+ if( m_findZone.highlight.active )+ {+ auto end = nit == zit ? zit : nit-1;+ if( *zit >= s && *end <= e ) selectionTime += timeSum;+ }+ zit = nit;+ }+ const auto timeSum = std::accumulate( zit, sortedEnd, int64_t( 0 ) );+ bins[numBins-1] += std::distance( zit, sortedEnd );+ binTime[numBins-1] += timeSum;+ if( m_findZone.highlight.active && *zit >= s && *(sortedEnd-1) <= e ) selectionTime += timeSum;++ if( m_findZone.selGroup != m_findZone.Unselected )+ {+ auto zit = m_findZone.selSort.begin();+ while( zit != m_findZone.selSort.end() && *zit == 0 ) ++zit;+ for( int64_t i=0; i<numBins; i++ )+ {+ const auto nextBinVal = tmin + ( i+1 ) * zmax / numBins;+ auto nit = std::lower_bound( zit, m_findZone.selSort.end(), nextBinVal );+ if( cumulateTime )+ {+ selBin[i] = std::accumulate( zit, nit, int64_t( 0 ) );+ }+ else+ {+ selBin[i] = std::distance( zit, nit );+ }+ zit = nit;+ }+ }+ }++ m_findZone.selTime = selectionTime;+ }++ int maxBin = 0;+ int64_t maxVal;+ if( cumulateTime )+ {+ maxVal = binTime[0];+ for( int i=1; i<numBins; i++ )+ {+ if( maxVal < binTime[i] )+ {+ maxVal = binTime[i];+ maxBin = i;+ }+ }+ }+ else+ {+ maxVal = bins[0];+ for( int i=1; i<numBins; i++ )+ {+ if( maxVal < bins[i] )+ {+ maxVal = bins[i];+ maxBin = i;+ }+ }+ }++ TextFocused( "Total time:", TimeToString( total ) );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ TextFocused( "Max counts:", cumulateTime ? TimeToString( maxVal ) : RealToString( maxVal ) );+ TextFocused( "Mean:", TimeToString( m_findZone.average ) );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ TextFocused( "Median:", TimeToString( m_findZone.median ) );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ TextFocused( "P75:", TimeToString( m_findZone.p75 ) );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ TextFocused( "P90:", TimeToString( m_findZone.p90 ) );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ {+ int64_t t0, t1;+ if( m_findZone.logTime )+ {+ const auto ltmin = log10( tmin );+ const auto ltmax = log10( tmax );+ t0 = int64_t( pow( 10, ltmin + double( maxBin ) / numBins * ( ltmax - ltmin ) ) );+ t1 = int64_t( pow( 10, ltmin + double( maxBin+1 ) / numBins * ( ltmax - ltmin ) ) );+ }+ else+ {+ t0 = int64_t( tmin + double( maxBin ) / numBins * ( tmax - tmin ) );+ t1 = int64_t( tmin + double( maxBin+1 ) / numBins * ( tmax - tmin ) );+ }+ TextFocused( "Mode:", TimeToString( ( t0 + t1 ) / 2 ) );+ }+ if( !m_findZone.range.active && m_findZone.sorted.size() > 1 )+ {+ const auto sz = m_findZone.sorted.size();+ const auto avg = m_findZone.average;+ const auto ss = zoneData.sumSq - 2. * zoneData.total * avg + avg * avg * sz;+ const auto sd = sqrt( ss / ( sz - 1 ) );++ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ TextFocused( "\xcf\x83:", TimeToString( sd ) );+ TooltipIfHovered( "Standard deviation" );+ }++ TextDisabledUnformatted( "Selection range:" );+ ImGui::SameLine();+ if( m_findZone.highlight.active )+ {+ const auto s = std::min( m_findZone.highlight.start, m_findZone.highlight.end );+ const auto e = std::max( m_findZone.highlight.start, m_findZone.highlight.end );+ ImGui::Text( "%s - %s (%s)", TimeToString( s ), TimeToString( e ), TimeToString( e - s ) );+ }+ else+ {+ ImGui::TextUnformatted( "none" );+ }+ ImGui::SameLine();+ DrawHelpMarker( "Left draw on histogram to select range. Right click to clear selection." );+ if( m_findZone.highlight.active )+ {+ TextFocused( "Selection time:", TimeToString( m_findZone.selTime ) );+ }+ else+ {+ TextFocused( "Selection time:", "none" );+ }+ if( m_findZone.selGroup != m_findZone.Unselected )+ {+ TextFocused( "Zone group time:", TimeToString( m_findZone.groups[m_findZone.selGroup].time ) );+ TextFocused( "Group mean:", TimeToString( m_findZone.selAverage ) );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ TextFocused( "Group median:", TimeToString( m_findZone.selMedian ) );+ }+ else+ {+ TextFocused( "Zone group time:", "none" );+ TextFocused( "Group mean:", "none" );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ TextFocused( "Group median:", "none" );+ }++ ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 0, 0 ) );+ ImGui::Checkbox( "###draw1", &m_findZone.drawAvgMed );+ ImGui::SameLine();+ ImGui::ColorButton( "c1", ImVec4( 0xFF/255.f, 0x44/255.f, 0x44/255.f, 1.f ), ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoDragDrop );+ ImGui::SameLine();+ ImGui::TextUnformatted( "Mean time" );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::ColorButton( "c2", ImVec4( 0x44/255.f, 0xAA/255.f, 0xFF/255.f, 1.f ), ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoDragDrop );+ ImGui::SameLine();+ ImGui::TextUnformatted( "Median time" );+ ImGui::Checkbox( "###draw2", &m_findZone.drawSelAvgMed );+ ImGui::SameLine();+ ImGui::ColorButton( "c3", ImVec4( 0xFF/255.f, 0xAA/255.f, 0x44/255.f, 1.f ), ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoDragDrop );+ ImGui::SameLine();+ if( m_findZone.selGroup != m_findZone.Unselected )+ {+ ImGui::TextUnformatted( "Group mean" );+ }+ else+ {+ TextDisabledUnformatted( "Group mean" );+ }+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::ColorButton( "c4", ImVec4( 0x44/255.f, 0xDD/255.f, 0x44/255.f, 1.f ), ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoDragDrop );+ ImGui::SameLine();+ if( m_findZone.selGroup != m_findZone.Unselected )+ {+ ImGui::TextUnformatted( "Group median" );+ }+ else+ {+ TextDisabledUnformatted( "Group median" );+ }+ ImGui::PopStyleVar();++ const auto Height = 200 * scale;+ const auto wpos = ImGui::GetCursorScreenPos();+ const auto dpos = wpos + ImVec2( 0.5f, 0.5f );++ ImGui::InvisibleButton( "##histogram", ImVec2( w, Height + round( ty * 2.5 ) ) );+ const bool hover = ImGui::IsItemHovered();++ auto draw = ImGui::GetWindowDrawList();+ draw->AddRectFilled( wpos, wpos + ImVec2( w, Height ), 0x22FFFFFF );+ draw->AddRect( wpos, wpos + ImVec2( w, Height ), 0x88FFFFFF );++ if( m_findZone.logVal )+ {+ const auto hAdj = double( Height - 4 ) / log10( maxVal + 1 );+ for( int i=0; i<numBins; i++ )+ {+ const auto val = cumulateTime ? binTime[i] : bins[i];+ if( val > 0 )+ {+ DrawLine( draw, dpos + ImVec2( 2+i, Height-3 ), dpos + ImVec2( 2+i, Height-3 - log10( val + 1 ) * hAdj ), 0xFF22DDDD );+ if( selBin[i] > 0 )+ {+ DrawLine( draw, dpos + ImVec2( 2+i, Height-3 ), dpos + ImVec2( 2+i, Height-3 - log10( selBin[i] + 1 ) * hAdj ), 0xFFDD7777 );+ }+ }+ }+ }+ else+ {+ const auto hAdj = double( Height - 4 ) / maxVal;+ for( int i=0; i<numBins; i++ )+ {+ const auto val = cumulateTime ? binTime[i] : bins[i];+ if( val > 0 )+ {+ DrawLine( draw, dpos + ImVec2( 2+i, Height-3 ), dpos + ImVec2( 2+i, Height-3 - val * hAdj ), 0xFF22DDDD );+ if( selBin[i] > 0 )+ {+ DrawLine( draw, dpos + ImVec2( 2+i, Height-3 ), dpos + ImVec2( 2+i, Height-3 - selBin[i] * hAdj ), 0xFFDD7777 );+ }+ }+ }+ }++ const auto xoff = 2;+ const auto yoff = Height + 1;++ DrawHistogramMinMaxLabel( draw, tmin, tmax, wpos + ImVec2( 0, yoff ), w, ty );++ const auto ty05 = round( ty * 0.5f );+ const auto ty025 = round( ty * 0.25f );+ if( m_findZone.logTime )+ {+ const auto ltmin = log10( tmin );+ const auto ltmax = log10( tmax );+ const auto start = int( floor( ltmin ) );+ const auto end = int( ceil( ltmax ) );++ const auto range = ltmax - ltmin;+ const auto step = w / range;+ auto offset = start - ltmin;+ int tw = 0;+ int tx = 0;++ auto tt = int64_t( pow( 10, start ) );++ static const double logticks[] = { log10( 2 ), log10( 3 ), log10( 4 ), log10( 5 ), log10( 6 ), log10( 7 ), log10( 8 ), log10( 9 ) };++ for( int i=start; i<=end; i++ )+ {+ const auto x = ( i - start + offset ) * step;++ if( x >= 0 )+ {+ DrawLine( draw, dpos + ImVec2( x, yoff ), dpos + ImVec2( x, yoff + ty05 ), 0x66FFFFFF );+ if( tw == 0 || x > tx + tw + ty * 1.1 )+ {+ tx = x;+ auto txt = TimeToString( tt );+ draw->AddText( wpos + ImVec2( x, yoff + ty05 ), 0x66FFFFFF, txt );+ tw = ImGui::CalcTextSize( txt ).x;+ }+ }++ for( int j=0; j<8; j++ )+ {+ const auto xoff = x + logticks[j] * step;+ if( xoff >= 0 )+ {+ DrawLine( draw, dpos + ImVec2( xoff, yoff ), dpos + ImVec2( xoff, yoff + ty025 ), 0x66FFFFFF );+ }+ }++ tt *= 10;+ }+ }+ else+ {+ const auto pxns = numBins / double( tmax - tmin );+ const auto nspx = 1.0 / pxns;+ const auto scale = std::max<float>( 0.0f, round( log10( nspx ) + 2 ) );+ const auto step = pow( 10, scale );++ const auto dx = step * pxns;+ double x = 0;+ int tw = 0;+ int tx = 0;++ const auto sstep = step / 10.0;+ const auto sdx = dx / 10.0;++ static const double linelen[] = { 0.5, 0.25, 0.25, 0.25, 0.25, 0.375, 0.25, 0.25, 0.25, 0.25 };++ int64_t tt = int64_t( ceil( tmin / sstep ) * sstep );+ const auto diff = tmin / sstep - int64_t( tmin / sstep );+ const auto xo = ( diff == 0 ? 0 : ( ( 1 - diff ) * sstep * pxns ) ) + xoff;+ int iter = int( ceil( ( tmin - int64_t( tmin / step ) * step ) / sstep ) );++ while( x < numBins )+ {+ DrawLine( draw, dpos + ImVec2( xo + x, yoff ), dpos + ImVec2( xo + x, yoff + round( ty * linelen[iter] ) ), 0x66FFFFFF );+ if( iter == 0 && ( tw == 0 || x > tx + tw + ty * 1.1 ) )+ {+ tx = x;+ auto txt = TimeToString( tt );+ draw->AddText( wpos + ImVec2( xo + x, yoff + ty05 ), 0x66FFFFFF, txt );+ tw = ImGui::CalcTextSize( txt ).x;+ }++ iter = ( iter + 1 ) % 10;+ x += sdx;+ tt += sstep;+ }+ }++ float ta, tm, tga, tgm;+ if( m_findZone.logTime )+ {+ const auto ltmin = log10( tmin );+ const auto ltmax = log10( tmax );++ ta = ( log10( m_findZone.average ) - ltmin ) / float( ltmax - ltmin ) * numBins;+ tm = ( log10( m_findZone.median ) - ltmin ) / float( ltmax - ltmin ) * numBins;+ tga = ( log10( m_findZone.selAverage ) - ltmin ) / float( ltmax - ltmin ) * numBins;+ tgm = ( log10( m_findZone.selMedian ) - ltmin ) / float( ltmax - ltmin ) * numBins;+ }+ else+ {+ ta = ( m_findZone.average - tmin ) / float( tmax - tmin ) * numBins;+ tm = ( m_findZone.median - tmin ) / float( tmax - tmin ) * numBins;+ tga = ( m_findZone.selAverage - tmin ) / float( tmax - tmin ) * numBins;+ tgm = ( m_findZone.selMedian - tmin ) / float( tmax - tmin ) * numBins;+ }+ ta = round( ta );+ tm = round( tm );+ tga = round( tga );+ tgm = round( tgm );++ if( m_findZone.drawAvgMed )+ {+ if( ta == tm )+ {+ DrawLine( draw, ImVec2( dpos.x + ta, dpos.y ), ImVec2( dpos.x + ta, dpos.y+Height-2 ), 0xFFFF88FF );+ }+ else+ {+ DrawLine( draw, ImVec2( dpos.x + ta, dpos.y ), ImVec2( dpos.x + ta, dpos.y+Height-2 ), 0xFF4444FF );+ DrawLine( draw, ImVec2( dpos.x + tm, dpos.y ), ImVec2( dpos.x + tm, dpos.y+Height-2 ), 0xFFFFAA44 );+ }+ }+ if( m_findZone.drawSelAvgMed && m_findZone.selGroup != m_findZone.Unselected )+ {+ DrawLine( draw, ImVec2( dpos.x + tga, dpos.y ), ImVec2( dpos.x + tga, dpos.y+Height-2 ), 0xFF44AAFF );+ DrawLine( draw, ImVec2( dpos.x + tgm, dpos.y ), ImVec2( dpos.x + tgm, dpos.y+Height-2 ), 0xFF44DD44 );+ }++ if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( 2, 2 ), wpos + ImVec2( w-2, Height + round( ty * 1.5 ) ) ) )+ {+ const auto ltmin = log10( tmin );+ const auto ltmax = log10( tmax );++ auto& io = ImGui::GetIO();+ DrawLine( draw, ImVec2( io.MousePos.x + 0.5f, dpos.y ), ImVec2( io.MousePos.x + 0.5f, dpos.y+Height-2 ), 0x33FFFFFF );++ const auto bin = int64_t( io.MousePos.x - wpos.x - 2 );+ int64_t t0, t1;+ if( m_findZone.logTime )+ {+ t0 = int64_t( pow( 10, ltmin + double( bin ) / numBins * ( ltmax - ltmin ) ) );++ // Hackfix for inability to select data in last bin.+ // A proper solution would be nice.+ if( bin+1 == numBins )+ {+ t1 = tmax;+ }+ else+ {+ t1 = int64_t( pow( 10, ltmin + double( bin+1 ) / numBins * ( ltmax - ltmin ) ) );+ }+ }+ else+ {+ t0 = int64_t( tmin + double( bin ) / numBins * ( tmax - tmin ) );+ t1 = int64_t( tmin + double( bin+1 ) / numBins * ( tmax - tmin ) );+ }++ int64_t tBefore = 0;+ int64_t cntBefore = 0;+ for( int i=0; i<bin; i++ )+ {+ tBefore += binTime[i];+ cntBefore += bins[i];+ }++ int64_t tAfter = 0;+ int64_t cntAfter = 0;+ for( int i=bin+1; i<numBins; i++ )+ {+ tAfter += binTime[i];+ cntAfter += bins[i];+ }++ ImGui::BeginTooltip();+ TextDisabledUnformatted( "Time range:" );+ ImGui::SameLine();+ ImGui::Text( "%s - %s", TimeToString( t0 ), TimeToString( t1 ) );+ TextFocused( "Count:", RealToString( bins[bin] ) );+ TextFocused( "Count in the left bins:", RealToString( cntBefore ) );+ TextFocused( "Count in the right bins:", RealToString( cntAfter ) );+ TextFocused( "Time spent in bin:", TimeToString( binTime[bin] ) );+ TextFocused( "Time spent in the left bins:", TimeToString( tBefore ) );+ TextFocused( "Time spent in the right bins:", TimeToString( tAfter ) );+ ImGui::EndTooltip();++ if( IsMouseClicked( 1 ) )+ {+ m_findZone.highlight.active = false;+ m_findZone.ResetGroups();+ }+ else if( IsMouseClicked( 0 ) )+ {+ m_findZone.highlight.active = true;+ m_findZone.highlight.start = t0;+ m_findZone.highlight.end = t1;+ m_findZone.hlOrig_t0 = t0;+ m_findZone.hlOrig_t1 = t1;+ }+ else if( IsMouseDragging( 0 ) )+ {+ if( t0 < m_findZone.hlOrig_t0 )+ {+ m_findZone.highlight.start = t0;+ m_findZone.highlight.end = m_findZone.hlOrig_t1;+ }+ else+ {+ m_findZone.highlight.start = m_findZone.hlOrig_t0;+ m_findZone.highlight.end = t1;+ }+ m_findZone.ResetGroups();+ }+ }++ if( m_findZone.highlight.active && m_findZone.highlight.start != m_findZone.highlight.end )+ {+ const auto s = std::min( m_findZone.highlight.start, m_findZone.highlight.end );+ const auto e = std::max( m_findZone.highlight.start, m_findZone.highlight.end );++ float t0, t1;+ if( m_findZone.logTime )+ {+ const auto ltmin = log10( tmin );+ const auto ltmax = log10( tmax );++ t0 = ( log10( s ) - ltmin ) / float( ltmax - ltmin ) * numBins;+ t1 = ( log10( e ) - ltmin ) / float( ltmax - ltmin ) * numBins;+ }+ else+ {+ t0 = ( s - tmin ) / float( tmax - tmin ) * numBins;+ t1 = ( e - tmin ) / float( tmax - tmin ) * numBins;+ }++ draw->PushClipRect( wpos, wpos + ImVec2( w, Height ), true );+ draw->AddRectFilled( wpos + ImVec2( 2 + t0, 1 ), wpos + ImVec2( 2 + t1, Height-1 ), 0x22DD8888 );+ draw->AddRect( wpos + ImVec2( 2 + t0, 1 ), wpos + ImVec2( 2 + t1, Height-1 ), 0x44DD8888 );+ draw->PopClipRect();+ }++ if( ( m_zoneHover && m_findZone.match[m_findZone.selMatch] == m_zoneHover->SrcLoc() ) ||+ ( m_zoneHover2 && m_findZone.match[m_findZone.selMatch] == m_zoneHover2->SrcLoc() ) )+ {+ const auto zoneTime = m_zoneHover ? ( m_worker.GetZoneEnd( *m_zoneHover ) - m_zoneHover->Start() ) : ( m_worker.GetZoneEnd( *m_zoneHover2 ) - m_zoneHover2->Start() );+ float zonePos;+ if( m_findZone.logTime )+ {+ const auto ltmin = log10( tmin );+ const auto ltmax = log10( tmax );+ zonePos = round( ( log10( zoneTime ) - ltmin ) / float( ltmax - ltmin ) * numBins );+ }+ else+ {+ zonePos = round( ( zoneTime - tmin ) / float( tmax - tmin ) * numBins );+ }+ const auto c = uint32_t( ( sin( s_time * 10 ) * 0.25 + 0.75 ) * 255 );+ const auto color = 0xFF000000 | ( c << 16 ) | ( c << 8 ) | c;+ DrawLine( draw, ImVec2( dpos.x + zonePos, dpos.y ), ImVec2( dpos.x + zonePos, dpos.y+Height-2 ), color );+ m_wasActive = true;+ }+ }+ }+ }++ ImGui::TreePop();+ }++ ImGui::Separator();+ SmallCheckbox( "Show zone time in frames", &m_findZone.showZoneInFrames );+ ImGui::Separator();++ ImGui::AlignTextToFramePadding();+ TextDisabledUnformatted( "Filter user text:" );+ ImGui::SameLine();+ bool filterChanged = m_userTextFilter.Draw( ICON_FA_FILTER "###resultFilter", 200 );++ ImGui::SameLine();+ if( ImGui::Button( ICON_FA_DELETE_LEFT " Clear###userText" ) )+ {+ m_userTextFilter.Clear();+ filterChanged = true;+ }+ ImGui::Separator();+ if( filterChanged )+ {+ m_filteredZones.clear();+ m_findZone.ResetGroups();+ }++ ImGui::TextUnformatted( "Found zones:" );+ ImGui::SameLine();+ DrawHelpMarker( "Left click to highlight entry." );+ if( m_findZone.selGroup != m_findZone.Unselected )+ {+ ImGui::SameLine();+ if( ImGui::SmallButton( ICON_FA_DELETE_LEFT " Clear" ) )+ {+ m_findZone.selGroup = m_findZone.Unselected;+ m_findZone.ResetSelection();+ }+ }++ bool groupChanged = false;+ ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 0, 0 ) );+ ImGui::TextUnformatted( "Group by:" );+ ImGui::SameLine();+ groupChanged |= ImGui::RadioButton( "Thread", (int*)( &m_findZone.groupBy ), (int)FindZone::GroupBy::Thread );+ ImGui::SameLine();+ groupChanged |= ImGui::RadioButton( "User text", (int*)( &m_findZone.groupBy ), (int)FindZone::GroupBy::UserText );+ ImGui::SameLine();+ groupChanged |= ImGui::RadioButton( "Zone name", (int*)( &m_findZone.groupBy ), (int)FindZone::GroupBy::ZoneName );+ ImGui::SameLine();+ groupChanged |= ImGui::RadioButton( "Call stacks", (int*)( &m_findZone.groupBy ), (int)FindZone::GroupBy::Callstack );+ ImGui::SameLine();+ groupChanged |= ImGui::RadioButton( "Parent", (int*)( &m_findZone.groupBy ), (int)FindZone::GroupBy::Parent );+ ImGui::SameLine();+ groupChanged |= ImGui::RadioButton( "No grouping", (int*)( &m_findZone.groupBy ), (int)FindZone::GroupBy::NoGrouping );+ if( groupChanged )+ {+ m_findZone.selGroup = m_findZone.Unselected;+ m_findZone.ResetGroups();+ }++ ImGui::TextUnformatted( "Sort by:" );+ ImGui::SameLine();+ ImGui::RadioButton( "Order", (int*)( &m_findZone.sortBy ), (int)FindZone::SortBy::Order );+ ImGui::SameLine();+ ImGui::RadioButton( "Count", (int*)( &m_findZone.sortBy ), (int)FindZone::SortBy::Count );+ ImGui::SameLine();+ ImGui::RadioButton( "Time", (int*)( &m_findZone.sortBy ), (int)FindZone::SortBy::Time );+ ImGui::SameLine();+ ImGui::RadioButton( "MTPC", (int*)( &m_findZone.sortBy ), (int)FindZone::SortBy::Mtpc );+ ImGui::PopStyleVar();+ ImGui::SameLine();+ DrawHelpMarker( "Mean time per call" );++ const auto hmin = std::min( m_findZone.highlight.start, m_findZone.highlight.end );+ const auto hmax = std::max( m_findZone.highlight.start, m_findZone.highlight.end );+ const auto groupBy = m_findZone.groupBy;+ const auto highlightActive = m_findZone.highlight.active;+ const auto limitRange = m_findZone.range.active;+ FindZone::Group* group = nullptr;+ constexpr uint64_t invalidGid = std::numeric_limits<uint64_t>::max() - 1;+ uint64_t lastGid = invalidGid;+ auto zptr = zones.data() + m_findZone.processed;+ const auto zend = zones.data() + zones.size();+ while( zptr < zend )+ {+ auto& ev = *zptr;+ const auto end = ev.Zone()->End();+ const auto start = ev.Zone()->Start();+ if( limitRange && ( start < rangeMin || end > rangeMax ) )+ {+ zptr++;+ continue;+ }++ if( m_userTextFilter.IsActive() )+ {+ bool keep = false;+ if ( m_worker.HasZoneExtra( *ev.Zone() ) && m_worker.GetZoneExtra( *ev.Zone() ).text.Active() )+ {+ auto text = m_worker.GetString( m_worker.GetZoneExtra( *ev.Zone() ).text );+ if( m_userTextFilter.PassFilter( text ) )+ {+ keep = true;+ }+ }+ if( !keep )+ {+ m_filteredZones.insert( &ev );+ zptr++;+ continue;+ }+ }++ auto timespan = end - start;+ assert( timespan != 0 );+ if( m_findZone.selfTime )+ {+ timespan -= GetZoneChildTimeFast( *ev.Zone() );+ }+ else if( m_findZone.runningTime )+ {+ const auto ctx = m_worker.GetContextSwitchData( m_worker.DecompressThread( ev.Thread() ) );+ if( !ctx ) break;+ int64_t t;+ uint64_t cnt;+ if( !GetZoneRunningTime( ctx, *ev.Zone(), t, cnt ) ) break;+ timespan = t;+ }++ if( highlightActive )+ {+ if( timespan < hmin || timespan > hmax )+ {+ zptr++;+ continue;+ }+ }++ zptr++;+ uint64_t gid = 0;+ switch( groupBy )+ {+ case FindZone::GroupBy::Thread:+ gid = ev.Thread();+ break;+ case FindZone::GroupBy::UserText:+ {+ const auto& zone = *ev.Zone();+ if( !m_worker.HasZoneExtra( zone ) )+ {+ gid = std::numeric_limits<uint64_t>::max();+ }+ else+ {+ const auto& extra = m_worker.GetZoneExtra( zone );+ gid = extra.text.Active() ? extra.text.Idx() : std::numeric_limits<uint64_t>::max();+ }+ break;+ }+ case FindZone::GroupBy::ZoneName:+ {+ const auto& zone = *ev.Zone();+ if( !m_worker.HasZoneExtra( zone ) )+ {+ gid = std::numeric_limits<uint64_t>::max();+ }+ else+ {+ const auto& extra = m_worker.GetZoneExtra( zone );+ gid = extra.name.Active() ? extra.name.Idx() : std::numeric_limits<uint64_t>::max();+ }+ break;+ }+ case FindZone::GroupBy::Callstack:+ gid = m_worker.GetZoneExtra( *ev.Zone() ).callstack.Val();+ break;+ case FindZone::GroupBy::Parent:+ {+ const auto parent = GetZoneParent( *ev.Zone(), m_worker.DecompressThread( ev.Thread() ) );+ if( parent ) gid = uint64_t( uint16_t( parent->SrcLoc() ) );+ break;+ }+ case FindZone::GroupBy::NoGrouping:+ break;+ default:+ assert( false );+ break;+ }+ if( lastGid != gid )+ {+ lastGid = gid;+ auto it = m_findZone.groups.find( gid );+ if( it == m_findZone.groups.end() )+ {+ it = m_findZone.groups.emplace( gid, FindZone::Group { m_findZone.groupId++ } ).first;+ it->second.zones.reserve( 1024 );+ if( m_findZone.samples.enabled )+ it->second.zonesTids.reserve( 1024 );+ }+ group = &it->second;+ }+ group->time += timespan;+ group->zones.push_back_non_empty( ev.Zone() );+ if( m_findZone.samples.enabled )+ group->zonesTids.push_back_non_empty( ev.Thread() );+ }+ m_findZone.processed = zptr - zones.data();++ const bool groupsUpdated = lastGid != invalidGid;+ if( m_findZone.samples.enabled && groupsUpdated )+ {+ m_findZone.samples.scheduleUpdate = true;+ }+++ Vector<decltype( m_findZone.groups )::iterator> groups;+ groups.reserve_and_use( m_findZone.groups.size() );+ int idx = 0;+ for( auto it = m_findZone.groups.begin(); it != m_findZone.groups.end(); ++it )+ {+ groups[idx++] = it;+ }++ switch( m_findZone.sortBy )+ {+ case FindZone::SortBy::Order:+ pdqsort_branchless( groups.begin(), groups.end(), []( const auto& lhs, const auto& rhs ) { return lhs->second.id < rhs->second.id; } );+ break;+ case FindZone::SortBy::Count:+ pdqsort_branchless( groups.begin(), groups.end(), []( const auto& lhs, const auto& rhs ) { return lhs->second.zones.size() > rhs->second.zones.size(); } );+ break;+ case FindZone::SortBy::Time:+ pdqsort_branchless( groups.begin(), groups.end(), []( const auto& lhs, const auto& rhs ) { return lhs->second.time > rhs->second.time; } );+ break;+ case FindZone::SortBy::Mtpc:+ pdqsort_branchless( groups.begin(), groups.end(), []( const auto& lhs, const auto& rhs ) { return double( lhs->second.time ) / lhs->second.zones.size() > double( rhs->second.time ) / rhs->second.zones.size(); } );+ break;+ default:+ assert( false );+ break;+ }++ int16_t changeZone = 0;++ if( groupBy == FindZone::GroupBy::Callstack )+ {+ const auto gsz = (int)groups.size();+ if( gsz > 0 )+ {+ if( m_findZone.selCs > gsz ) m_findZone.selCs = gsz;+ const auto group = groups[m_findZone.selCs];++ const bool selHilite = m_findZone.selGroup == group->first;+ if( selHilite ) SetButtonHighlightColor();+ if( ImGui::SmallButton( " " ICON_FA_CHECK " " ) )+ {+ m_findZone.selGroup = group->first;+ m_findZone.ResetSelection();+ }+ if( selHilite ) ImGui::PopStyleColor( 3 );+ ImGui::SameLine();+ if( ImGui::SmallButton( " " ICON_FA_CARET_LEFT " " ) )+ {+ m_findZone.selCs = std::max( m_findZone.selCs - 1, 0 );+ }+ ImGui::SameLine();+ ImGui::Text( "%s / %s", RealToString( m_findZone.selCs + 1 ), RealToString( gsz ) );+ if( ImGui::IsItemClicked() ) ImGui::OpenPopup( "FindZoneCallstackPopup" );+ ImGui::SameLine();+ if( ImGui::SmallButton( " " ICON_FA_CARET_RIGHT " " ) )+ {+ m_findZone.selCs = std::min<int>( m_findZone.selCs + 1, gsz - 1 );+ }+ if( ImGui::BeginPopup( "FindZoneCallstackPopup" ) )+ {+ int sel = m_findZone.selCs + 1;+ ImGui::SetNextItemWidth( 120 * scale );+ const bool clicked = ImGui::InputInt( "##findZoneCallstack", &sel, 1, 100, ImGuiInputTextFlags_EnterReturnsTrue );+ if( clicked ) m_findZone.selCs = std::min( std::max( sel, 1 ), int( gsz ) ) - 1;+ ImGui::EndPopup();+ }++ ImGui::SameLine();+ TextFocused( "Count:", RealToString( group->second.zones.size() ) );+ ImGui::SameLine();+ TextFocused( "Time:", TimeToString( group->second.time ) );+ ImGui::SameLine();+ char buf[64];+ PrintStringPercent( buf, group->second.time * 100.f / zoneData.total );+ TextDisabledUnformatted( buf );++ if( group->first != 0 )+ {+ ImGui::SameLine();+ int idx = 0;+ SmallCallstackButton( " " ICON_FA_ALIGN_JUSTIFY " ", group->first, idx, false );++ int fidx = 0;+ ImGui::Spacing();+ ImGui::Indent();+ auto& csdata = m_worker.GetCallstack( group->first );+ for( auto& entry : csdata )+ {+ auto frameData = m_worker.GetCallstackFrame( entry );+ if( !frameData )+ {+ ImGui::TextDisabled( "%i.", fidx++ );+ ImGui::SameLine();+ ImGui::Text( "%p", (void*)m_worker.GetCanonicalPointer( entry ) );+ }+ else+ {+ const auto fsz = frameData->size;+ for( uint8_t f=0; f<fsz; f++ )+ {+ const auto& frame = frameData->data[f];+ auto txt = m_worker.GetString( frame.name );++ if( fidx == 0 && f != fsz-1 )+ {+ auto test = s_tracyStackFrames;+ bool match = false;+ do+ {+ if( strcmp( txt, *test ) == 0 )+ {+ match = true;+ break;+ }+ }+ while( *++test );+ if( match ) continue;+ }+ if( f == fsz-1 )+ {+ ImGui::TextDisabled( "%i.", fidx++ );+ }+ else+ {+ TextDisabledUnformatted( ICON_FA_CARET_RIGHT );+ }+ ImGui::SameLine();+ if( m_vd.shortenName == ShortenName::Never )+ {+ ImGui::TextUnformatted( txt );+ }+ else+ {+ const auto normalized = ShortenZoneName( ShortenName::OnlyNormalize, txt );+ ImGui::TextUnformatted( normalized );+ TooltipNormalizedName( txt, normalized );+ }+ }+ }+ }+ ImGui::Unindent();+ }+ else+ {+ ImGui::Text( "No call stack" );+ }++ ImGui::Spacing();+ if( ImGui::TreeNodeEx( "Zone list" ) )+ {+ DrawZoneList( group->second.id, group->second.zones );+ }+ }+ }+ else+ {+ TextFocused( "Number of groups:", RealToString( groups.size() ) );+ for( auto& v : groups )+ {+ bool isFiber = false;+ const char* hdrString;+ switch( groupBy )+ {+ case FindZone::GroupBy::Thread:+ {+ const auto tid = m_worker.DecompressThread( v->first );+ const auto threadColor = GetThreadColor( tid, 0 );+ SmallColorBox( threadColor );+ ImGui::SameLine();+ hdrString = m_worker.GetThreadName( tid );+ isFiber = m_worker.IsThreadFiber( tid );+ break;+ }+ case FindZone::GroupBy::UserText:+ hdrString = v->first == std::numeric_limits<uint64_t>::max() ? "No user text" : m_worker.GetString( StringIdx( v->first ) );+ break;+ case FindZone::GroupBy::ZoneName:+ if( v->first == std::numeric_limits<uint64_t>::max() )+ {+ auto& srcloc = m_worker.GetSourceLocation( m_findZone.match[m_findZone.selMatch] );+ hdrString = m_worker.GetString( srcloc.name.active ? srcloc.name : srcloc.function );+ }+ else+ {+ hdrString = m_worker.GetString( StringIdx( v->first ) );+ }+ break;+ case FindZone::GroupBy::Callstack:+ if( v->first == 0 )+ {+ hdrString = "No callstack";+ }+ else+ {+ auto& callstack = m_worker.GetCallstack( v->first );+ auto& frameData = *m_worker.GetCallstackFrame( *callstack.begin() );+ hdrString = m_worker.GetString( frameData.data[frameData.size-1].name );+ }+ break;+ case FindZone::GroupBy::Parent:+ if( v->first == 0 )+ {+ hdrString = "<no parent>";+ SmallColorBox( 0 );+ }+ else+ {+ auto& srcloc = m_worker.GetSourceLocation( int16_t( v->first ) );+ hdrString = m_worker.GetString( srcloc.name.active ? srcloc.name : srcloc.function );+ SmallColorBox( GetSrcLocColor( srcloc, 0 ) );+ }+ ImGui::SameLine();+ break;+ case FindZone::GroupBy::NoGrouping:+ hdrString = "Zone list";+ break;+ default:+ hdrString = nullptr;+ assert( false );+ break;+ }+ ImGui::PushID( v->first );+ const bool expand = ImGui::TreeNodeEx( hdrString, ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ( v->first == m_findZone.selGroup ? ImGuiTreeNodeFlags_Selected : 0 ) );+ if( ImGui::IsItemClicked() )+ {+ m_findZone.selGroup = v->first;+ m_findZone.ResetSelection();+ }+ if( m_findZone.groupBy == FindZone::GroupBy::Parent && ImGui::IsItemClicked( 2 ) )+ {+ changeZone = int16_t( v->first );+ }+ ImGui::PopID();+ if( isFiber )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 0.2f, 0.6f, 0.2f, 1.f ), "Fiber" );+ }+ ImGui::SameLine();+ ImGui::TextColored( ImVec4( 0.5f, 0.5f, 0.5f, 1.0f ), "(%s) %s", RealToString( v->second.zones.size() ), TimeToString( v->second.time ) );+ if( expand )+ {+ DrawZoneList( v->second.id, v->second.zones );+ }+ }+ }++ if( m_findZone.samples.enabled && m_findZone.samples.scheduleUpdate && !m_findZone.scheduleResetMatch )+ {+ m_findZone.samples.scheduleUpdate = false;++ const auto& symMap = m_worker.GetSymbolMap();+ m_findZone.samples.counts.clear();+ m_findZone.samples.counts.reserve( symMap.size() );++ struct GroupRange {+ const FindZone::Group* group;+ Vector<short_ptr<ZoneEvent>>::const_iterator begin;+ Vector<short_ptr<ZoneEvent>>::const_iterator end;+ };+ Vector<GroupRange> selectedGroups;+ selectedGroups.reserve( m_findZone.groups.size() );+ for( auto it = m_findZone.groups.begin(); it != m_findZone.groups.end(); ++it )+ {+ assert( it->second.zones.size() == it->second.zonesTids.size() );+ if( ( m_findZone.selGroup == m_findZone.Unselected || it->first == m_findZone.selGroup )+ && !it->second.zones.empty() )+ {+ selectedGroups.push_back_no_space_check( GroupRange{&it->second} );+ }+ }++ for( auto& v : symMap )+ {+ bool pass = ( m_statShowKernel || ( v.first >> 63 ) == 0 );+ if( !pass && v.second.size.Val() == 0 )+ {+ const auto parentAddr = m_worker.GetSymbolForAddress( v.first );+ if( parentAddr != 0 )+ {+ auto pit = symMap.find( parentAddr );+ if( pit != symMap.end() )+ {+ pass = ( m_statShowKernel || ( parentAddr >> 63 ) == 0 );+ }+ }+ }+ if( !pass ) continue;++ auto samples = m_worker.GetSamplesForSymbol( v.first );+ if( !samples ) continue;++ auto samplesBegin = samples->begin();+ auto samplesEnd = samples->end();+ if( m_findZone.range.active )+ {+ const auto rangeMin = m_findZone.range.min;+ const auto rangeMax = m_findZone.range.max;+ samplesBegin = std::lower_bound( samplesBegin, samplesEnd, rangeMin, [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs; } );+ samplesEnd = std::lower_bound( samplesBegin, samplesEnd, rangeMax, [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs; } );+ }+ if( samplesBegin == samplesEnd ) continue;++ bool empty = true;+ const auto firstTime = samplesBegin->time.Val();+ const auto lastTime = samplesEnd == samples->end() ? m_worker.GetLastTime() : samplesEnd->time.Val();+ for( auto& g: selectedGroups )+ {+ const auto& zones = g.group->zones;+ auto begin = std::lower_bound( zones.begin(), zones.end(), firstTime, [] ( const auto& l, const auto& r ) { return l->Start() < r; } );+ auto end = std::upper_bound( begin, zones.end(), lastTime, [] ( const auto& l, const auto& r ) { return l <= r->Start(); } );+ g.begin = begin;+ g.end = end;+ empty = empty && (begin == end);+ }+ if (empty) continue;++ uint32_t count = 0;+ for( auto it = samplesBegin; it != samplesEnd; ++it )+ {+ const auto time = it->time.Val();+ bool pass = false;+ for( auto& g: selectedGroups )+ {+ while( g.begin != g.end && time > (*g.begin)->End() ) ++g.begin;+ if( g.begin == g.end ) continue;+ if( time < (*g.begin)->Start() ) continue;++ const auto& tids = g.group->zonesTids;+ const auto firstZone = g.group->zones.begin();+ for (auto z = g.begin; z != g.end && (*z)->Start() <= time; ++z)+ {+ auto zoneIndex = z - firstZone;+ if( (*z)->End() > time && it->thread == tids[zoneIndex] )+ {+ pass = true;+ break;+ }+ }+ }+ if( pass ) count ++;+ }+ if( count > 0 ) m_findZone.samples.counts.push_back_no_space_check( SymList { v.first, 0, count } );+ }+ }++ ImGui::Separator();+ const bool hasSamples = m_worker.AreCallstackSamplesReady() && m_worker.GetCallstackSampleCount() > 0;+ if( hasSamples && ImGui::TreeNodeEx( ICON_FA_EYE_DROPPER " Samples", ImGuiTreeNodeFlags_None ) )+ {+ {+ ImGui::Checkbox( ICON_FA_STOPWATCH " Show time", &m_statSampleTime );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::Checkbox( ICON_FA_EYE_SLASH " Hide unknown", &m_statHideUnknown );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::Checkbox( ICON_FA_SITEMAP " Inlines", &m_statSeparateInlines );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::Checkbox( ICON_FA_AT " Address", &m_statShowAddress );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ if( ImGui::Checkbox( ICON_FA_HAT_WIZARD " Include kernel", &m_statShowKernel ))+ {+ m_findZone.samples.scheduleUpdate = true;+ }+ }++ if( !m_findZone.samples.enabled )+ {+ m_findZone.samples.enabled = true;+ m_findZone.samples.scheduleUpdate = true;+ m_findZone.scheduleResetMatch = true;+ }++ Vector<SymList> data;+ data.reserve( m_findZone.samples.counts.size() );+ for( auto it: m_findZone.samples.counts ) data.push_back_no_space_check( it );+ int64_t timeRange = ( m_findZone.selGroup != m_findZone.Unselected ) ? m_findZone.selTotal : m_findZone.total;+ DrawSamplesStatistics( data, timeRange, AccumulationMode::SelfOnly );++ ImGui::TreePop();+ }+ else+ {+ if( m_findZone.samples.enabled )+ {+ m_findZone.samples.enabled = false;+ m_findZone.samples.scheduleUpdate = false;+ m_findZone.samples.counts = Vector<SymList>();+ for( auto& it: m_findZone.groups ) it.second.zonesTids.clear();+ }+ }++ if( changeZone != 0 )+ {+ auto& srcloc = m_worker.GetSourceLocation( changeZone );+ m_findZone.ShowZone( changeZone, m_worker.GetString( srcloc.name.active ? srcloc.name : srcloc.function ) );+ }+ }+ ImGui::EndChild();+#endif++ ImGui::End();+}++}
+ cbits/tracy/profiler/src/profiler/TracyView_FlameGraph.cpp view
@@ -0,0 +1,967 @@+#include <assert.h>+#include <inttypes.h>++#include "TracyColor.hpp"+#include "TracyEvent.hpp"+#include "TracyImGui.hpp"+#include "TracyMouse.hpp"+#include "TracyPrint.hpp"+#include "TracyVector.hpp"+#include "TracyView.hpp"+#include "tracy_pdqsort.h"++namespace tracy+{++constexpr float MinVisSize = 3;++void View::BuildFlameGraph( const Worker& worker, std::vector<FlameGraphItem>& data, const Vector<short_ptr<ZoneEvent>>& zones )+{+ FlameGraphItem* cache;+ int16_t last = 0;++ if( zones.is_magic() )+ {+ auto& vec = *(Vector<ZoneEvent>*)&zones;+ for( auto& v : vec )+ {+ if( !v.IsEndValid() ) break;+ const auto srcloc = v.SrcLoc();++ auto start = v.Start();+ auto end = v.End();++ if ( m_flameGraphInvariant.range.active )+ {+ start = std::clamp(start, m_flameGraphInvariant.range.min, m_flameGraphInvariant.range.max);+ end = std::clamp(end, m_flameGraphInvariant.range.min, m_flameGraphInvariant.range.max);+ }++ const auto duration = end - start;+ if( srcloc == last )+ {+ cache->time += duration;+ if( v.HasChildren() )+ {+ auto& children = worker.GetZoneChildren( v.Child() );+ BuildFlameGraph( worker, cache->children, children );+ }+ }+ else+ {+ auto it = std::find_if( data.begin(), data.end(), [srcloc]( const auto& v ) { return v.srcloc == srcloc; } );+ if( it == data.end() )+ {+ data.emplace_back( FlameGraphItem { srcloc, duration } );+ if( v.HasChildren() )+ {+ auto& children = worker.GetZoneChildren( v.Child() );+ BuildFlameGraph( worker, data.back().children, children );+ }+ cache = &data.back();+ }+ else+ {+ it->time += duration;+ if( v.HasChildren() )+ {+ auto& children = worker.GetZoneChildren( v.Child() );+ BuildFlameGraph( worker, it->children, children );+ }+ cache = &*it;+ }+ last = srcloc;+ }+ }+ }+ else+ {+ for( auto& v : zones )+ {+ if( !v->IsEndValid() ) break;+ const auto srcloc = v->SrcLoc();++ auto start = v->Start();+ auto end = v->End();++ if ( m_flameGraphInvariant.range.active )+ {+ start = std::clamp(start, m_flameGraphInvariant.range.min, m_flameGraphInvariant.range.max);+ end = std::clamp(end, m_flameGraphInvariant.range.min, m_flameGraphInvariant.range.max);+ }++ const auto duration = end - start;+ if( srcloc == last )+ {+ cache->time += duration;+ if( v->HasChildren() )+ {+ auto& children = worker.GetZoneChildren( v->Child() );+ BuildFlameGraph( worker, cache->children, children );+ }+ }+ else+ {+ auto it = std::find_if( data.begin(), data.end(), [srcloc]( const auto& v ) { return v.srcloc == srcloc; } );+ if( it == data.end() )+ {+ data.emplace_back( FlameGraphItem { srcloc, duration } );+ if( v->HasChildren() )+ {+ auto& children = worker.GetZoneChildren( v->Child() );+ BuildFlameGraph( worker, data.back().children, children );+ }+ cache = &data.back();+ }+ else+ {+ it->time += duration;+ if( v->HasChildren() )+ {+ auto& children = worker.GetZoneChildren( v->Child() );+ BuildFlameGraph( worker, it->children, children );+ }+ cache = &*it;+ }+ last = srcloc;+ }+ }+ }+}++void View::BuildFlameGraph( const Worker& worker, std::vector<FlameGraphItem>& data, const Vector<short_ptr<ZoneEvent>>& zones, const ContextSwitch* ctx )+{+ assert( ctx );+ FlameGraphItem* cache;+ int16_t last = 0;++ if( zones.is_magic() )+ {+ auto& vec = *(Vector<ZoneEvent>*)&zones;+ for( auto& v : vec )+ {+ if( !v.IsEndValid() ) break;+ const auto srcloc = v.SrcLoc();+ int64_t duration;+ uint64_t cnt;+ if ( m_flameRange.active )+ {+ if( !GetZoneRunningTime( ctx, v, m_flameGraphInvariant.range, duration, cnt ) ) continue;+ }+ else+ {+ if( !GetZoneRunningTime( ctx, v, duration, cnt ) ) break;+ }++ if( srcloc == last )+ {+ cache->time += duration;+ if( v.HasChildren() )+ {+ auto& children = worker.GetZoneChildren( v.Child() );+ BuildFlameGraph( worker, cache->children, children, ctx );+ }+ }+ else+ {+ auto it = std::find_if( data.begin(), data.end(), [srcloc]( const auto& v ) { return v.srcloc == srcloc; } );+ if( it == data.end() )+ {+ data.emplace_back( FlameGraphItem { srcloc, duration } );+ if( v.HasChildren() )+ {+ auto& children = worker.GetZoneChildren( v.Child() );+ BuildFlameGraph( worker, data.back().children, children, ctx );+ }+ cache = &data.back();+ }+ else+ {+ it->time += duration;+ if( v.HasChildren() )+ {+ auto& children = worker.GetZoneChildren( v.Child() );+ BuildFlameGraph( worker, it->children, children, ctx );+ }+ cache = &*it;+ }+ last = srcloc;+ }+ }+ }+ else+ {+ for( auto& v : zones )+ {+ if( !v->IsEndValid() ) break;+ const auto srcloc = v->SrcLoc();+ int64_t duration;+ uint64_t cnt;+ if ( m_flameRange.active )+ {+ if( !GetZoneRunningTime( ctx, *v, m_flameGraphInvariant.range, duration, cnt ) ) continue;+ }+ else+ {+ if( !GetZoneRunningTime( ctx, *v, duration, cnt ) ) break;+ }++ if( srcloc == last )+ {+ cache->time += duration;+ if( v->HasChildren() )+ {+ auto& children = worker.GetZoneChildren( v->Child() );+ BuildFlameGraph( worker, cache->children, children, ctx );+ }+ }+ else+ {+ auto it = std::find_if( data.begin(), data.end(), [srcloc]( const auto& v ) { return v.srcloc == srcloc; } );+ if( it == data.end() )+ {+ data.emplace_back( FlameGraphItem { srcloc, duration } );+ if( v->HasChildren() )+ {+ auto& children = worker.GetZoneChildren( v->Child() );+ BuildFlameGraph( worker, data.back().children, children, ctx );+ }+ cache = &data.back();+ }+ else+ {+ it->time += duration;+ if( v->HasChildren() )+ {+ auto& children = worker.GetZoneChildren( v->Child() );+ BuildFlameGraph( worker, it->children, children, ctx );+ }+ cache = &*it;+ }+ last = srcloc;+ }+ }+ }+}++void View::BuildFlameGraph( const Worker& worker, std::vector<FlameGraphItem>& data, const Vector<SampleData>& samples )+{+ struct FrameCache+ {+ uint64_t symaddr;+ StringIdx name;+ bool external;+ };++ std::vector<FrameCache> cache;++ for( auto& v : samples )+ {+ if ( m_flameGraphInvariant.range.active )+ {+ if ( v.time.Val() < m_flameGraphInvariant.range.min ||+ v.time.Val() > m_flameGraphInvariant.range.max )+ {+ continue;+ }+ }++ cache.clear();++ const auto cs = v.callstack.Val();+ const auto& callstack = worker.GetCallstack( cs );+ const auto csz = callstack.size();+ if( m_flameExternal )+ {+ for( size_t i=csz; i>0; i-- )+ {+ auto frameData = worker.GetCallstackFrame( callstack[i-1] );+ if( frameData )+ {+ for( uint8_t j=frameData->size; j>0; j-- )+ {+ const auto frame = frameData->data[j-1];+ const auto symaddr = frame.symAddr;+ if( symaddr != 0 )+ {+ cache.emplace_back( FrameCache { symaddr, frame.name } );+ }+ }+ }+ }+ }+ else if( !m_flameExternalTail )+ {+ for( size_t i=csz; i>0; i-- )+ {+ auto frameData = worker.GetCallstackFrame( callstack[i-1] );+ if( frameData )+ {+ for( uint8_t j=frameData->size; j>0; j-- )+ {+ const auto frame = frameData->data[j-1];+ const auto symaddr = frame.symAddr;+ if( symaddr != 0 )+ {+ auto filename = m_worker.GetString( frame.file );+ auto image = frameData->imageName.Active() ? m_worker.GetString( frameData->imageName ) : nullptr;+ if( !IsFrameExternal( filename, image ) )+ {+ cache.emplace_back( FrameCache { symaddr, frame.name } );+ }+ }+ }+ }+ }+ }+ else+ {+ for( size_t i=csz; i>0; i-- )+ {+ auto frameData = worker.GetCallstackFrame( callstack[i-1] );+ if( frameData )+ {+ for( uint8_t j=frameData->size; j>0; j-- )+ {+ const auto frame = frameData->data[j-1];+ const auto symaddr = frame.symAddr;+ if( symaddr != 0 )+ {+ auto filename = m_worker.GetString( frame.file );+ auto image = frameData->imageName.Active() ? m_worker.GetString( frameData->imageName ) : nullptr;+ cache.emplace_back( FrameCache { symaddr, frame.name, IsFrameExternal( filename, image ) } );+ }+ }+ }+ }++ bool tail = true;+ for( size_t i=cache.size(); i>0; i-- )+ {+ const auto idx = i-1;+ if( !cache[idx].external )+ {+ tail = false;+ }+ else if( !tail )+ {+ cache.erase( cache.begin() + idx );+ }+ }+ }++ auto vec = &data;+ for( auto& v : cache )+ {+ auto it = std::find_if( vec->begin(), vec->end(), [symaddr = v.symaddr]( const auto& v ) { return v.srcloc == symaddr; } );+ if( it == vec->end() )+ {+ vec->emplace_back( FlameGraphItem { (int64_t)v.symaddr, 1, v.name } );+ vec = &vec->back().children;+ }+ else+ {+ it->time++;+ vec = &it->children;+ }+ }+ }+}++static void SortFlameGraph( std::vector<FlameGraphItem>& data )+{+ pdqsort_branchless( data.begin(), data.end(), []( const FlameGraphItem& lhs, const FlameGraphItem& rhs ) { return lhs.time > rhs.time; } );+ for( auto& v : data ) SortFlameGraph( v.children );+}++struct FlameGraphContext+{+ ImDrawList* draw;+ ImVec2 wpos;+ ImVec2 dpos;+ float ty;+ float ostep;+ double pxns;+ double nspx;+ int64_t vStart;+ int64_t vEnd;+};++void View::DrawFlameGraphLevel( const std::vector<FlameGraphItem>& data, FlameGraphContext& ctx, int depth, bool samples )+{+ const auto vStart = ctx.vStart;+ const auto vEnd = ctx.vEnd;+ const auto nspx = ctx.nspx;+ const auto pxns = ctx.pxns;+ const auto draw = ctx.draw;+ const auto ostep = ctx.ostep;+ const auto& wpos = ctx.wpos;++ const auto MinVisNs = int64_t( round( GetScale() * MinVisSize * nspx ) );++ auto it = std::lower_bound( data.begin(), data.end(), vStart, [] ( const auto& l, const auto& r ) { return l.begin + l.time < r; } );+ if( it == data.end() ) return;++ const auto zitend = std::lower_bound( it, data.end(), vEnd, [] ( const auto& l, const auto& r ) { return l.begin < r; } );+ if( it == zitend ) return;++ while( it < zitend )+ {+ const auto end = it->begin + it->time;+ const auto zsz = it->time;+ if( zsz < MinVisNs )+ {+ auto nextTime = end + MinVisNs;+ auto next = it + 1;+ for(;;)+ {+ next = std::lower_bound( next, zitend, nextTime, [] ( const auto& l, const auto& r ) { return l.begin + l.time < r; } );+ if( next == zitend ) break;+ if( next->time >= MinVisNs ) break;+ nextTime = next->begin + next->time + MinVisNs;+ }+ const auto px0 = ( it->begin - vStart ) * pxns;+ const auto px1 = ( (next-1)->begin + (next-1)->time - vStart ) * pxns;+ draw->AddRectFilled( ImVec2( wpos.x + px0, wpos.y + depth * ostep ), ImVec2( wpos.x + std::max( px1, px0 + MinVisSize ), wpos.y + ( depth + 1 ) * ostep ), 0xFF666666 );+ DrawZigZag( draw, ImVec2( wpos.x, wpos.y + ( depth + 0.5f ) * ostep ), px0, std::max( px1, px0 + MinVisSize ), ctx.ty / 4, 0xFF444444 );+ it = next;+ }+ else+ {+ DrawFlameGraphItem( *it, ctx, depth, samples );+ ++it;+ }+ }+}++void View::DrawFlameGraphItem( const FlameGraphItem& item, FlameGraphContext& ctx, int depth, bool samples )+{+ const auto x0 = ctx.dpos.x + item.begin * ctx.pxns;+ const auto x1 = x0 + item.time * ctx.pxns;+ const auto y0 = ctx.dpos.y + depth * ctx.ostep;+ const auto y1 = y0 + ctx.ty;++ const SourceLocation* srcloc;+ uint32_t color;+ const char* name;+ const char* normalized;+ const char* slName;++ uint32_t textColor = 0xFFFFFFFF;++ if( !samples )+ {+ srcloc = &m_worker.GetSourceLocation( item.srcloc );+ color = GetSrcLocColor( *srcloc, depth );+ name = slName = m_worker.GetString( srcloc->name.active ? srcloc->name : srcloc->function );+ }+ else+ {+ name = m_worker.GetString( item.name );+ const auto symAddr = (uint64_t)item.srcloc;+ auto sym = m_worker.GetSymbolData( symAddr );+ if( sym )+ {+ auto namehash = charutil::hash( name );+ if( namehash == 0 ) namehash++;+ color = GetHsvColor( namehash, depth );+ if( sym->isInline )+ {+ color = DarkenColorHalf( color );+ }+ }+ else+ {+ color = 0xFF888888;+ }+ if( symAddr >> 63 != 0 )+ {+ textColor = 0xFF8888FF;+ }+ }++ const auto hiColor = HighlightColor( color );+ const auto darkColor = DarkenColor( color );++ const auto zsz = x1 - x0;++ auto tsz = ImGui::CalcTextSize( name );+ if( m_vd.shortenName == ShortenName::Never )+ {+ normalized = name;+ }+ else if( samples )+ {+ normalized = ShortenZoneName( ShortenName::OnlyNormalize, name );+ tsz = ImGui::CalcTextSize( normalized );+ if( tsz.x > zsz && ( m_vd.shortenName == ShortenName::NoSpace || m_vd.shortenName == ShortenName::NoSpaceAndNormalize ) )+ {+ normalized = ShortenZoneName( m_vd.shortenName, normalized, tsz, zsz );+ }+ }+ else if( m_vd.shortenName == ShortenName::Always || ( ( m_vd.shortenName == ShortenName::NoSpace || m_vd.shortenName == ShortenName::NoSpaceAndNormalize ) && tsz.x > zsz ) )+ {+ normalized = ShortenZoneName( m_vd.shortenName, name, tsz, zsz );+ }+ else+ {+ normalized = name;+ }++ const bool hover = ImGui::IsWindowHovered() && ImGui::IsMouseHoveringRect( ImVec2( x0, y0 ), ImVec2( x1, y1 ) );++ ctx.draw->AddRectFilled( ImVec2( x0, y0 ), ImVec2( x1, y1 ), color );+ if( hover )+ {+ ctx.draw->AddRect( ImVec2( x0 - 0.5f, y0 - 0.5f ), ImVec2( x1 - 0.5f, y1 - 0.5f ), 0xFFEEEEEE );+ }+ else+ {+ DrawLine( ctx.draw, ImVec2( x0, y1 ), ImVec2( x0, y0 ), ImVec2( x1-1, y0 ), hiColor );+ DrawLine( ctx.draw, ImVec2( x0, y1 ), ImVec2( x1-1, y1), ImVec2( x1-1, y0 ), darkColor );+ }++ if( tsz.x < zsz )+ {+ const auto x = ( x1 + x0 - tsz.x ) * 0.5;+ DrawTextContrast( ctx.draw, ImVec2( x, y0 ), textColor, normalized );+ }+ else+ {+ ImGui::PushClipRect( ImVec2( x0, y0 ), ImVec2( x1, y1 ), true );+ DrawTextContrast( ctx.draw, ImVec2( x0, y0 ), textColor, normalized );+ ImGui::PopClipRect();+ }++ if( hover )+ {+ uint64_t self = item.time;+ for( auto& v : item.children ) self -= v.time;++ ImGui::BeginTooltip();+ if( samples )+ {+ const auto symAddr = (uint64_t)item.srcloc;+ auto sym = m_worker.GetSymbolData( symAddr );+ if( sym )+ {+ TextFocused( "Name:", normalized );+ if( sym->isInline )+ {+ ImGui::SameLine();+ TextDisabledUnformatted( "[inline]" );+ }+ const bool isKernel = symAddr >> 63 != 0;+ if( isKernel )+ {+ ImGui::SameLine();+ TextDisabledUnformatted( ICON_FA_HAT_WIZARD " kernel" );+ }+ ImGui::SameLine();+ ImGui::PushFont( m_smallFont );+ ImGui::AlignTextToFramePadding();+ ImGui::TextDisabled( "0x%" PRIx64, symAddr );+ ImGui::PopFont();+ if( normalized != name && strcmp( normalized, name ) != 0 )+ {+ ImGui::PushFont( m_smallFont );+ TextDisabledUnformatted( name );+ ImGui::PopFont();+ }+ ImGui::Separator();+ const char* file;+ uint32_t line;+ if( sym->isInline )+ {+ file = m_worker.GetString( sym->callFile );+ line = sym->callLine;+ }+ else+ {+ file = m_worker.GetString( sym->file );+ line = sym->line;+ }+ if( file[0] != '[' )+ {+ ImGui::TextDisabled( "Location:" );+ ImGui::SameLine();+ ImGui::TextUnformatted( LocationToString( file, line ) );+ }+ TextFocused( "Image:", m_worker.GetString( sym->imageName ) );+ ImGui::Separator();+ const auto period = m_worker.GetSamplingPeriod();+ TextFocused( "Execution time:", TimeToString( item.time * period ) );+ if( !item.children.empty() )+ {+ TextFocused( "Self time:", TimeToString( self * period ) );+ char buf[64];+ PrintStringPercent( buf, 100.f * self / item.time );+ ImGui::SameLine();+ TextDisabledUnformatted( buf );+ }++ if( IsMouseClicked( 0 ) )+ {+ ViewDispatch( file, line, symAddr );+ }+ }+ ImGui::EndTooltip();+ }+ else+ {+ if( srcloc->name.active )+ {+ ImGui::TextUnformatted( m_worker.GetString( srcloc->name ) );+ }+ ImGui::TextUnformatted( m_worker.GetString( srcloc->function ) );+ ImGui::Separator();+ SmallColorBox( GetSrcLocColor( *srcloc, 0 ) );+ ImGui::SameLine();+ ImGui::TextUnformatted( LocationToString( m_worker.GetString( srcloc->file ), srcloc->line ) );+ ImGui::Separator();+ TextFocused( "Execution time:", TimeToString( item.time ) );+ if( !item.children.empty() )+ {+ TextFocused( "Self time:", TimeToString( self ) );+ char buf[64];+ PrintStringPercent( buf, 100.f * self / item.time );+ ImGui::SameLine();+ TextDisabledUnformatted( buf );+ }+ ImGui::EndTooltip();++ if( IsMouseClicked( 0 ) )+ {+ m_findZone.ShowZone( item.srcloc, slName );+ }+ }+ }++ DrawFlameGraphLevel( item.children, ctx, depth+1, samples );+}++void View::DrawFlameGraphHeader( uint64_t timespan )+{+ const auto wpos = ImGui::GetCursorScreenPos();+ const auto dpos = wpos + ImVec2( 0.5f, 0.5f );+ const auto w = ImGui::GetContentRegionAvail().x;// - ImGui::GetStyle().ScrollbarSize;+ auto draw = ImGui::GetWindowDrawList();+ const auto ty = ImGui::GetTextLineHeight();+ const auto ty025 = round( ty * 0.25f );+ const auto ty0375 = round( ty * 0.375f );+ const auto ty05 = round( ty * 0.5f );++ const auto pxns = w / double( timespan );+ const auto nspx = 1.0 / pxns;+ const auto scale = std::max( 0.0, round( log10( nspx ) + 2 ) );+ const auto step = pow( 10, scale );++ ImGui::InvisibleButton( "##flameHeader", ImVec2( w, ty * 1.5f ) );+ TooltipIfHovered( TimeToStringExact( ( ImGui::GetIO().MousePos.x - wpos.x ) * nspx ) );++ const auto dx = step * pxns;+ double x = 0;+ int tw = 0;+ int tx = 0;+ int64_t tt = 0;+ while( x < w )+ {+ DrawLine( draw, dpos + ImVec2( x, 0 ), dpos + ImVec2( x, ty05 ), 0x66FFFFFF );+ if( tw == 0 )+ {+ auto txt = "0";+ draw->AddText( wpos + ImVec2( x, ty05 ), 0x66FFFFFF, txt );+ tw = ImGui::CalcTextSize( txt ).x;+ }+ else if( x > tx + tw + ty * 2 )+ {+ tx = x;+ auto txt = TimeToString( tt );+ draw->AddText( wpos + ImVec2( x, ty05 ), 0x66FFFFFF, txt );+ tw = ImGui::CalcTextSize( txt ).x;+ }++ if( scale != 0 )+ {+ for( int i=1; i<5; i++ )+ {+ DrawLine( draw, dpos + ImVec2( x + i * dx / 10, 0 ), dpos + ImVec2( x + i * dx / 10, ty025 ), 0x33FFFFFF );+ }+ DrawLine( draw, dpos + ImVec2( x + 5 * dx / 10, 0 ), dpos + ImVec2( x + 5 * dx / 10, ty0375 ), 0x33FFFFFF );+ for( int i=6; i<10; i++ )+ {+ DrawLine( draw, dpos + ImVec2( x + i * dx / 10, 0 ), dpos + ImVec2( x + i * dx / 10, ty025 ), 0x33FFFFFF );+ }+ }++ x += dx;+ tt += step;+ }+}++static void MergeFlameGraph( std::vector<FlameGraphItem>& dst, std::vector<FlameGraphItem>&& src )+{+ for( auto& v : src )+ {+ auto it = std::find_if( dst.begin(), dst.end(), [&v]( const auto& vv ) { return vv.srcloc == v.srcloc; } );+ if( it == dst.end() )+ {+ dst.emplace_back( std::move( v ) );+ }+ else+ {+ it->time += v.time;+ MergeFlameGraph( it->children, std::move( v.children ) );+ }+ }+}++static void FixupTime( std::vector<FlameGraphItem>& data, uint64_t t = 0 )+{+ for( auto& v : data )+ {+ v.begin = t;+ if( !v.children.empty() ) FixupTime( v.children, t );+ t += v.time;+ }+}+++void View::DrawFlameGraph()+{+ const auto scale = GetScale();+ ImGui::SetNextWindowSize( ImVec2( 1400 * scale, 800 * scale ), ImGuiCond_FirstUseEver );+ ImGui::Begin( "Flame graph", &m_showFlameGraph, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse );+ if( ImGui::GetCurrentWindowRead()->SkipItems ) { ImGui::End(); return; }++ ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 2, 2 ) );+ if( ImGui::RadioButton( ICON_FA_SYRINGE " Instrumentation", &m_flameMode, 0 ) ) m_flameGraphInvariant.Reset();++ if( m_worker.AreCallstackSamplesReady() && m_worker.GetCallstackSampleCount() > 0 )+ {+ ImGui::SameLine();+ if( ImGui::RadioButton( ICON_FA_EYE_DROPPER " Sampling", &m_flameMode, 1 ) ) m_flameGraphInvariant.Reset();+ }++ ImGui::SameLine();+ ImGui::SeparatorEx( ImGuiSeparatorFlags_Vertical );+ ImGui::SameLine();++ if( ImGui::Checkbox( ICON_FA_ARROW_UP_WIDE_SHORT " Sort by time", &m_flameSort ) ) m_flameGraphInvariant.Reset();++ if( m_flameMode == 0 )+ {+ if( m_worker.HasContextSwitches() )+ {+ ImGui::SameLine();+ if( ImGui::Checkbox( "Running time", &m_flameRunningTime ) ) m_flameGraphInvariant.Reset();+ }+ else+ {+ assert( !m_flameRunningTime );+ }+ }+ else+ {+ ImGui::SameLine();+ ImGui::SeparatorEx( ImGuiSeparatorFlags_Vertical );+ ImGui::SameLine();+ ImGui::Text( ICON_FA_SHIELD_HALVED "External" );+ ImGui::SameLine();+ if( ImGui::Checkbox( "Frames", &m_flameExternal ) ) m_flameGraphInvariant.Reset();+ ImGui::SameLine();+ if( m_flameExternal ) ImGui::BeginDisabled();+ if( ImGui::Checkbox( "Tails", &m_flameExternalTail ) ) m_flameGraphInvariant.Reset();+ if( m_flameExternal ) ImGui::EndDisabled();+ }++ if( ImGui::Checkbox( "Limit range", &m_flameRange.active ) )+ {+ if( m_flameRange.active && m_flameRange.min == 0 && m_flameRange.max == 0 )+ {+ m_flameRange.min = m_vd.zvStart;+ m_flameRange.max = m_vd.zvEnd;+ }++ m_flameGraphInvariant.Reset();+ }+ if( m_flameRange.active )+ {+ ImGui::SameLine();+ TextColoredUnformatted( 0xFF00FFFF, ICON_FA_TRIANGLE_EXCLAMATION );+ ImGui::SameLine();+ ToggleButton( ICON_FA_RULER " Limits", m_showRanges );+ }++ auto& td = m_worker.GetThreadData();+ auto expand = ImGui::TreeNode( ICON_FA_SHUFFLE " Visible threads:" );+ ImGui::SameLine();+ size_t visibleThreads = 0;+ size_t tsz = 0;+ for( const auto& t : td )+ {+ if( FlameGraphThread( t->id ) ) visibleThreads++;+ tsz++;+ }+ if( visibleThreads == tsz )+ {+ ImGui::TextDisabled( "(%zu)", tsz );+ }+ else+ {+ ImGui::TextDisabled( "(%zu/%zu)", visibleThreads, tsz );+ }+ if( expand )+ {+ ImGui::SameLine();+ if( ImGui::SmallButton( "Select all" ) )+ {+ for( const auto& t : td )+ {+ FlameGraphThread( t->id ) = true;+ }+ m_flameGraphInvariant.Reset();+ }+ ImGui::SameLine();+ if( ImGui::SmallButton( "Unselect all" ) )+ {+ for( const auto& t : td )+ {+ FlameGraphThread( t->id ) = false;+ }+ m_flameGraphInvariant.Reset();+ }++ int idx = 0;+ for( const auto& t : td )+ {+ ImGui::PushID( idx++ );+ const auto threadColor = GetThreadColor( t->id, 0 );+ SmallColorBox( threadColor );+ ImGui::SameLine();+ if( SmallCheckbox( m_worker.GetThreadName( t->id ), &FlameGraphThread( t->id ) ) ) m_flameGraphInvariant.Reset();+ ImGui::PopID();+ if( t->isFiber )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 0.2f, 0.6f, 0.2f, 1.f ), "Fiber" );+ }+ }+ ImGui::TreePop();+ }++ ImGui::Separator();+ ImGui::PopStyleVar();++ if( m_flameMode == 0 && ( m_flameGraphInvariant.count != m_worker.GetZoneCount() || m_flameGraphInvariant.lastTime != m_worker.GetLastTime() ) ||+ m_flameMode == 1 && ( m_flameGraphInvariant.count != m_worker.GetCallstackSampleCount() ) ||+ m_flameGraphInvariant.range != m_flameRange )+ {+ m_flameGraphInvariant.range = m_flameRange;++ size_t sz = 0;+ for( auto& thread : td ) if( FlameGraphThread( thread->id ) ) sz++;++ std::vector<std::vector<FlameGraphItem>> threadData;+ threadData.resize( sz );++ size_t idx = 0;+ if( m_flameMode == 0 )+ {+ for( auto& thread : td )+ {+ if( FlameGraphThread( thread->id ) )+ {+ if( m_flameRunningTime )+ {+ const auto ctx = m_worker.GetContextSwitchData( thread->id );+ if( ctx )+ {+ m_td.Queue( [this, idx, ctx, thread, &threadData] {+ BuildFlameGraph( m_worker, threadData[idx], thread->timeline, ctx );+ } );+ }+ }+ else+ {+ m_td.Queue( [this, idx, thread, &threadData] {+ BuildFlameGraph( m_worker, threadData[idx], thread->timeline );+ } );+ }+ idx++;+ }+ }++ m_flameGraphInvariant.count = m_worker.GetZoneCount();+ m_flameGraphInvariant.lastTime = m_worker.GetLastTime();+ }+ else+ {+ for( auto& thread : td )+ {+ if( FlameGraphThread( thread->id ) )+ {+ m_td.Queue( [this, idx, thread, &threadData] {+ BuildFlameGraph( m_worker, threadData[idx], thread->samples );+ } );+ idx++;+ }+ }++ m_flameGraphInvariant.count = m_worker.GetCallstackSampleCount();+ }+ m_td.Sync();++ m_flameGraphData.clear();+ if( !threadData.empty() )+ {+ std::swap( m_flameGraphData, threadData[0] );+ for( size_t i=1; i<threadData.size(); i++ )+ {+ MergeFlameGraph( m_flameGraphData, std::move( threadData[i] ) );+ }+ }++ if( m_flameSort ) SortFlameGraph( m_flameGraphData );+ FixupTime( m_flameGraphData );+ }++ int64_t zsz = 0;+ for( auto& v : m_flameGraphData ) zsz += v.time;++ ImGui::BeginChild( "##flameGraph" );+ const auto region = ImGui::GetContentRegionAvail();++ if( m_flameGraphData.empty() )+ {+ ImGui::PushFont( m_bigFont );+ ImGui::Dummy( ImVec2( 0, ( region.y - ImGui::GetTextLineHeight() * 2 ) * 0.5f ) );+ TextCentered( ICON_FA_CAT );+ TextCentered( "No data available to display" );+ ImGui::PopFont();+ }+ else+ {+ DrawFlameGraphHeader( m_flameMode == 0 ? zsz : zsz * m_worker.GetSamplingPeriod() );++ FlameGraphContext ctx;+ ctx.draw = ImGui::GetWindowDrawList();+ ctx.wpos = ImGui::GetCursorScreenPos();+ ctx.dpos = ctx.wpos + ImVec2( 0.5f, 0.5f );+ ctx.ty = ImGui::GetTextLineHeight();+ ctx.ostep = ctx.ty + 1;+ ctx.pxns = region.x / zsz;+ ctx.nspx = 1.0 / ctx.pxns;+ ctx.vStart = 0;+ ctx.vEnd = zsz;++ ImGui::ItemSize( region );+ DrawFlameGraphLevel( m_flameGraphData, ctx, 0, m_flameMode == 1 );+ }++ ImGui::EndChild();++ ImGui::End();+}++}
+ cbits/tracy/profiler/src/profiler/TracyView_FrameOverview.cpp view
@@ -0,0 +1,452 @@+#include "TracyImGui.hpp"+#include "TracyMouse.hpp"+#include "TracyPrint.hpp"+#include "TracyTexture.hpp"+#include "TracyView.hpp"++namespace tracy+{++static uint32_t GetFrameColor( uint64_t time, uint64_t target )+{+ return time > target * 2 ? 0xFF2222DD :+ time > target ? 0xFF22DDDD :+ time > target / 2 ? 0xFF22DD22 : 0xFFDD9900;+}++static int GetFrameWidth( int frameScale )+{+ return frameScale == 0 ? 4 : ( frameScale < 0 ? 6 : 1 );+}++static int GetFrameGroup( int frameScale )+{+ return frameScale < 2 ? 1 : ( 1 << ( frameScale - 1 ) );+}++template<class T>+constexpr const T& clamp( const T& v, const T& lo, const T& hi )+{+ return v < lo ? lo : v > hi ? hi : v;+}++void View::DrawFrames()+{+ assert( m_worker.GetFrameCount( *m_frames ) != 0 );++ const auto scale = GetScale();+ const auto Height = 50 * scale;++ constexpr uint64_t MaxFrameTime = 50 * 1000 * 1000; // 50ms++ ImGuiWindow* window = ImGui::GetCurrentWindowRead();+ if( window->SkipItems ) return;++ const uint64_t frameTarget = 1000 * 1000 * 1000 / m_vd.frameTarget;++ auto& io = ImGui::GetIO();++ const auto wpos = ImGui::GetCursorScreenPos();+ const auto dpos = wpos + ImVec2( 0.5f, 0.5f );+ const auto wspace = ImGui::GetWindowContentRegionMax() - ImGui::GetWindowContentRegionMin();+ const auto w = wspace.x;+ auto draw = ImGui::GetWindowDrawList();++ ImGui::InvisibleButton( "##frames", ImVec2( w, Height ) );+ bool hover = ImGui::IsItemHovered();++ draw->AddRectFilled( wpos, wpos + ImVec2( w, Height ), 0x33FFFFFF );+ const auto wheel = io.MouseWheel;+ const auto prevScale = m_vd.frameScale;+ if( hover )+ {+ if( wheel > 0 )+ {+ if( m_vd.frameScale >= 0 ) m_vd.frameScale--;+ }+ else if( wheel < 0 )+ {+ if( m_vd.frameScale < 10 ) m_vd.frameScale++;+ }+ }++ const int fwidth = GetFrameWidth( m_vd.frameScale );+ const int group = GetFrameGroup( m_vd.frameScale );+ const int total = m_worker.GetFrameCount( *m_frames );+ const int onScreen = ( w - 2 ) / fwidth;+ if( m_viewMode != ViewMode::Paused )+ {+ m_vd.frameStart = ( total < onScreen * group ) ? 0 : total - onScreen * group;+ if( m_viewMode == ViewMode::LastFrames )+ {+ SetViewToLastFrames();+ }+ else+ {+ assert( m_viewMode == ViewMode::LastRange );+ const auto delta = m_worker.GetLastTime() - m_vd.zvEnd;+ if( delta != 0 )+ {+ m_vd.zvStart += delta;+ m_vd.zvEnd += delta;+ }+ }+ }++ if( hover )+ {+ const auto hwheel_delta = io.MouseWheelH * 100.f * m_horizontalScrollMultiplier;+ if( IsMouseDragging( 1 ) || hwheel_delta != 0 )+ {+ m_viewMode = ViewMode::Paused;+ m_viewModeHeuristicTry = false;+ auto delta = GetMouseDragDelta( 1 ).x;+ if( delta == 0 ) delta = hwheel_delta;+ if( abs( delta ) >= fwidth )+ {+ const auto d = (int)delta / fwidth;+ m_vd.frameStart = std::max( 0, m_vd.frameStart - d * group );+ io.MouseClickedPos[1].x = io.MousePos.x + d * fwidth - delta;+ }+ }++ const auto mx = io.MousePos.x;+ if( mx > wpos.x && mx < wpos.x + w - 1 )+ {+ const auto mo = mx - ( wpos.x + 1 );+ const auto off = mo * group / fwidth;++ const int sel = m_vd.frameStart + off;+ if( sel < total )+ {+ ImGui::BeginTooltip();+ if( group > 1 )+ {+ auto f = m_worker.GetFrameTime( *m_frames, sel );+ auto g = std::min( group, total - sel );+ for( int j=1; j<g; j++ )+ {+ f = std::max( f, m_worker.GetFrameTime( *m_frames, sel + j ) );+ }++ TextDisabledUnformatted( "Frames:" );+ ImGui::SameLine();+ ImGui::Text( "%s - %s (%s)", RealToString( sel ), RealToString( sel + g - 1 ), RealToString( g ) );+ ImGui::Separator();+ TextFocused( "Max frame time:", TimeToString( f ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%.1f FPS)", 1000000000.0 / f );++ if( IsMouseClickReleased( 1 ) ) m_setRangePopup = RangeSlim { m_worker.GetFrameTime( *m_frames, sel ), m_worker.GetFrameTime( *m_frames, sel + g - 1 ), true };+ }+ else+ {+ const auto fnum = GetFrameNumber( *m_frames, sel );+ m_frameHover = sel;+ if( m_frames->name == 0 )+ {+ if( sel == 0 )+ {+ ImGui::TextUnformatted( "Tracy initialization" );+ ImGui::Separator();+ TextFocused( "Time:", TimeToString( m_worker.GetFrameTime( *m_frames, sel ) ) );+ }+ else if( !m_worker.IsOnDemand() )+ {+ TextDisabledUnformatted( "Frame:" );+ ImGui::SameLine();+ ImGui::TextUnformatted( RealToString( fnum ) );+ ImGui::Separator();+ const auto frameTime = m_worker.GetFrameTime( *m_frames, sel );+ TextFocused( "Frame time:", TimeToString( frameTime ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%.1f FPS)", 1000000000.0 / frameTime );+ }+ else if( sel == 1 )+ {+ ImGui::TextUnformatted( "Missed frames" );+ ImGui::Separator();+ TextFocused( "Time:", TimeToString( m_worker.GetFrameTime( *m_frames, 1 ) ) );+ }+ else+ {+ TextDisabledUnformatted( "Frame:" );+ ImGui::SameLine();+ ImGui::TextUnformatted( RealToString( fnum ) );+ ImGui::Separator();+ const auto frameTime = m_worker.GetFrameTime( *m_frames, sel );+ TextFocused( "Frame time:", TimeToString( frameTime ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%.1f FPS)", 1000000000.0 / frameTime );+ }+ }+ else+ {+ ImGui::TextDisabled( "%s:", GetFrameSetName( *m_frames ) );+ ImGui::SameLine();+ ImGui::TextUnformatted( RealToString( fnum ) );+ ImGui::Separator();+ const auto frameTime = m_worker.GetFrameTime( *m_frames, sel );+ TextFocused( "Frame time:", TimeToString( frameTime ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%.1f FPS)", 1000000000.0 / frameTime );+ }+ }+ TextFocused( "Time from start of program:", TimeToStringExact( m_worker.GetFrameBegin( *m_frames, sel ) ) );+ auto fi = m_worker.GetFrameImage( *m_frames, sel );+ if( fi )+ {+ if( fi != m_frameTexturePtr )+ {+ if( !m_frameTexture ) m_frameTexture = MakeTexture();+ UpdateTexture( m_frameTexture, m_worker.UnpackFrameImage( *fi ), fi->w, fi->h );+ m_frameTexturePtr = fi;+ }+ ImGui::Separator();+ if( fi->flip )+ {+ ImGui::Image( m_frameTexture, ImVec2( fi->w * scale, fi->h * scale ), ImVec2( 0, 1 ), ImVec2( 1, 0 ) );+ }+ else+ {+ ImGui::Image( m_frameTexture, ImVec2( fi->w * scale, fi->h * scale ) );+ }+ }+ ImGui::EndTooltip();++ if( io.KeyCtrl )+ {+ if( fi && IsMouseDown( 0 ) )+ {+ m_showPlayback = true;+ m_playback.pause = true;+ SetPlaybackFrame( m_frames->frames[sel].frameImage );+ }+ }+ else+ {+ if( IsMouseClicked( 0 ) )+ {+ m_viewMode = ViewMode::Paused;+ m_viewModeHeuristicTry = false;+ m_zoomAnim.active = false;+ if( !m_playback.pause && m_playback.sync ) m_playback.pause = true;+ m_vd.zvStart = m_worker.GetFrameBegin( *m_frames, sel );+ m_vd.zvEnd = m_worker.GetFrameEnd( *m_frames, sel + group - 1 );+ if( m_vd.zvStart == m_vd.zvEnd ) m_vd.zvStart--;+ }+ else if( IsMouseDragging( 0 ) )+ {+ const auto t0 = std::min( m_vd.zvStart, m_worker.GetFrameBegin( *m_frames, sel ) );+ const auto t1 = std::max( m_vd.zvEnd, m_worker.GetFrameEnd( *m_frames, sel + group - 1 ) );+ ZoomToRange( t0, t1 );+ }+ }++ if( IsMouseClickReleased( 1 ) ) m_setRangePopup = RangeSlim { m_worker.GetFrameBegin( *m_frames, sel ), m_worker.GetFrameEnd( *m_frames, sel + group - 1 ), true };+ }++ if( ( !m_worker.IsConnected() || m_viewMode == ViewMode::Paused ) && wheel != 0 )+ {+ const int pfwidth = GetFrameWidth( prevScale );+ const int pgroup = GetFrameGroup( prevScale );++ const auto oldoff = mo * pgroup / pfwidth;+ m_vd.frameStart = std::min( total, std::max( 0, m_vd.frameStart - int( off - oldoff ) ) );+ }+ }+ }++ int i = 0, idx = 0;+#ifndef TRACY_NO_STATISTICS+ if( m_worker.AreSourceLocationZonesReady() && m_findZone.show && m_findZone.showZoneInFrames && !m_findZone.match.empty() )+ {+ auto& zoneData = m_worker.GetZonesForSourceLocation( m_findZone.match[m_findZone.selMatch] );+ zoneData.zones.ensure_sorted();+ auto begin = zoneData.zones.begin();+ while( i < onScreen && m_vd.frameStart + idx < total )+ {+ const auto f0 = m_worker.GetFrameBegin( *m_frames, m_vd.frameStart + idx );+ auto f1 = m_worker.GetFrameEnd( *m_frames, m_vd.frameStart + idx );+ auto f = f1 - f0;+ if( group > 1 )+ {+ const int g = std::min( group, total - ( m_vd.frameStart + idx ) );+ for( int j=1; j<g; j++ )+ {+ f = std::max( f, m_worker.GetFrameTime( *m_frames, m_vd.frameStart + idx + j ) );+ }+ f1 = m_worker.GetFrameEnd( *m_frames, m_vd.frameStart + idx + g - 1 );+ }++ int64_t zoneTime = 0;+ // This search is not valid, as zones are sorted according to their start time, not end time.+ auto itStart = std::lower_bound( begin, zoneData.zones.end(), f0, [] ( const auto& l, const auto& r ) { return l.Zone()->End() < r; } );+ if( itStart != zoneData.zones.end() )+ {+ auto itEnd = std::lower_bound( itStart, zoneData.zones.end(), f1, [] ( const auto& l, const auto& r ) { return l.Zone()->Start() < r; } );+ if( m_frames->continuous )+ {+ if( m_findZone.selfTime )+ {+ while( itStart != itEnd )+ {+ const auto t0 = clamp( itStart->Zone()->Start(), f0, f1 );+ const auto t1 = clamp( m_worker.GetZoneEndDirect( *itStart->Zone() ), f0, f1 );+ zoneTime += t1 - t0 - GetZoneChildTimeFastClamped( *itStart->Zone(), t0, t1 );+ itStart++;+ }+ }+ else+ {+ while( itStart != itEnd )+ {+ const auto t0 = clamp( itStart->Zone()->Start(), f0, f1 );+ const auto t1 = clamp( m_worker.GetZoneEndDirect( *itStart->Zone() ), f0, f1 );+ zoneTime += t1 - t0;+ itStart++;+ }+ }+ }+ else+ {+ if( m_findZone.selfTime )+ {+ while( itStart != itEnd )+ {+ const int g = std::min( group, total - ( m_vd.frameStart + idx ) );+ for( int j=0; j<g; j++ )+ {+ const auto ft0 = m_worker.GetFrameBegin( *m_frames, m_vd.frameStart + idx + j );+ const auto ft1 = m_worker.GetFrameEnd( *m_frames, m_vd.frameStart + idx + j );+ const auto t0 = clamp( itStart->Zone()->Start(), ft0, ft1 );+ const auto t1 = clamp( m_worker.GetZoneEndDirect( *itStart->Zone() ), ft0, ft1 );+ zoneTime += t1 - t0 - GetZoneChildTimeFastClamped( *itStart->Zone(), t0, t1 );+ }+ itStart++;+ }+ }+ else+ {+ while( itStart != itEnd )+ {+ const int g = std::min( group, total - ( m_vd.frameStart + idx ) );+ for( int j=0; j<g; j++ )+ {+ const auto ft0 = m_worker.GetFrameBegin( *m_frames, m_vd.frameStart + idx + j );+ const auto ft1 = m_worker.GetFrameEnd( *m_frames, m_vd.frameStart + idx + j );+ const auto t0 = clamp( itStart->Zone()->Start(), ft0, ft1 );+ const auto t1 = clamp( m_worker.GetZoneEndDirect( *itStart->Zone() ), ft0, ft1 );+ zoneTime += t1 - t0;+ }+ itStart++;+ }+ }+ }+ }+ else+ {+ begin = itStart;+ }++ zoneTime /= group;+ const auto h = std::max( 1.f, float( std::min<uint64_t>( MaxFrameTime, f ) ) / MaxFrameTime * ( Height - 2 ) );+ if( zoneTime == 0 )+ {+ if( fwidth != 1 )+ {+ draw->AddRectFilled( wpos + ImVec2( 1 + i*fwidth, Height-1-h ), wpos + ImVec2( fwidth + i*fwidth, Height-1 ), 0xFF888888 );+ }+ else+ {+ DrawLine( draw, dpos + ImVec2( 1+i, Height-2-h ), dpos + ImVec2( 1+i, Height-2 ), 0xFF888888 );+ }+ }+ else if( zoneTime <= f )+ {+ const auto zh = float( std::min<uint64_t>( MaxFrameTime, zoneTime ) ) / MaxFrameTime * ( Height - 2 );+ if( fwidth != 1 )+ {+ draw->AddRectFilled( wpos + ImVec2( 1 + i*fwidth, Height-1-h ), wpos + ImVec2( fwidth + i*fwidth, Height-1-zh ), 0xFF888888 );+ draw->AddRectFilled( wpos + ImVec2( 1 + i*fwidth, Height-1-zh ), wpos + ImVec2( fwidth + i*fwidth, Height-1 ), 0xFFEEEEEE );+ }+ else+ {+ DrawLine( draw, dpos + ImVec2( 1+i, Height-2-h ), dpos + ImVec2( 1+i, Height-2-zh ), 0xFF888888 );+ DrawLine( draw, dpos + ImVec2( 1+i, Height-2-zh ), dpos + ImVec2( 1+i, Height-2 ), 0xFFEEEEEE );+ }+ }+ else+ {+ const auto zh = float( std::min<uint64_t>( MaxFrameTime, zoneTime ) ) / MaxFrameTime * ( Height - 2 );+ if( fwidth != 1 )+ {+ draw->AddRectFilled( wpos + ImVec2( 1 + i*fwidth, Height-1-zh ), wpos + ImVec2( fwidth + i*fwidth, Height-1-h ), 0xFF2222BB );+ draw->AddRectFilled( wpos + ImVec2( 1 + i*fwidth, Height-1-h ), wpos + ImVec2( fwidth + i*fwidth, Height-1 ), 0xFFEEEEEE );+ }+ else+ {+ DrawLine( draw, dpos + ImVec2( 1+i, Height-2-zh ), dpos + ImVec2( 1+i, Height-2-h ), 0xFF2222BB );+ DrawLine( draw, dpos + ImVec2( 1+i, Height-2-h ), dpos + ImVec2( 1+i, Height-2 ), 0xFFEEEEEE );+ }+ }++ i++;+ idx += group;+ }+ }+ else+#endif+ {+ while( i < onScreen && m_vd.frameStart + idx < total )+ {+ auto f = m_worker.GetFrameTime( *m_frames, m_vd.frameStart + idx );+ if( group > 1 )+ {+ const int g = std::min( group, total - ( m_vd.frameStart + idx ) );+ for( int j=1; j<g; j++ )+ {+ f = std::max( f, m_worker.GetFrameTime( *m_frames, m_vd.frameStart + idx + j ) );+ }+ }++ const auto h = std::max( 1.f, float( std::min<uint64_t>( MaxFrameTime, f ) ) / MaxFrameTime * ( Height - 2 ) );+ if( fwidth != 1 )+ {+ draw->AddRectFilled( wpos + ImVec2( 1 + i*fwidth, Height-1-h ), wpos + ImVec2( fwidth + i*fwidth, Height-1 ), GetFrameColor( f, frameTarget ) );+ }+ else+ {+ DrawLine( draw, dpos + ImVec2( 1+i, Height-2-h ), dpos + ImVec2( 1+i, Height-2 ), GetFrameColor( f, frameTarget ) );+ }++ i++;+ idx += group;+ }+ }++ const auto zrange = m_worker.GetFrameRange( *m_frames, m_vd.zvStart, m_vd.zvEnd );+ if( zrange.second > m_vd.frameStart && zrange.first < m_vd.frameStart + onScreen * group )+ {+ auto x1 = std::min( onScreen * fwidth, ( zrange.second - m_vd.frameStart ) * fwidth / group );+ auto x0 = std::max( 0, ( zrange.first - m_vd.frameStart ) * fwidth / group );++ if( x0 == x1 ) x1 = x0 + 1;+ if( x1 - x0 >= 3 )+ {+ draw->AddRectFilled( wpos + ImVec2( 2+x0, 0 ), wpos + ImVec2( x1, Height ), 0x55DD22DD );+ DrawLine( draw, dpos + ImVec2( 1+x0, -1 ), dpos + ImVec2( 1+x0, Height-1 ), 0x55FF55FF );+ DrawLine( draw, dpos + ImVec2( x1, -1 ), dpos + ImVec2( x1, Height-1 ), 0x55FF55FF );+ }+ else+ {+ draw->AddRectFilled( wpos + ImVec2( 1+x0, 0 ), wpos + ImVec2( 1+x1, Height ), 0x55FF55FF );+ }+ }++ if( frameTarget * 2 <= MaxFrameTime ) DrawLine( draw, dpos + ImVec2( 0, round( Height - Height * frameTarget * 2 / MaxFrameTime ) ), dpos + ImVec2( w, round( Height - Height * frameTarget * 2 / MaxFrameTime ) ), 0x442222DD );+ if( frameTarget <= MaxFrameTime ) DrawLine( draw, dpos + ImVec2( 0, round( Height - Height * frameTarget / MaxFrameTime ) ), dpos + ImVec2( w, round( Height - Height * frameTarget / MaxFrameTime ) ), 0x4422DDDD );+ if( frameTarget / 2 <= MaxFrameTime ) DrawLine( draw, dpos + ImVec2( 0, round( Height - Height * frameTarget / 2 / MaxFrameTime ) ), dpos + ImVec2( w, round( Height - Height * frameTarget / 2 / MaxFrameTime ) ), 0x4422DD22 );+}++}
+ cbits/tracy/profiler/src/profiler/TracyView_FrameTimeline.cpp view
@@ -0,0 +1,336 @@+#include <algorithm>+#include <math.h>++#include "TracyImGui.hpp"+#include "TracyMouse.hpp"+#include "TracyPrint.hpp"+#include "TracyTexture.hpp"+#include "TracyView.hpp"++namespace tracy+{++constexpr float MinVisSize = 3;+constexpr float MinFrameSize = 5;++static tracy_force_inline uint32_t GetColorMuted( uint32_t color, bool active )+{+ if( active )+ {+ return 0xFF000000 | color;+ }+ else+ {+ return 0x66000000 | color;+ }+}++void View::DrawTimelineFramesHeader()+{+ const auto wpos = ImGui::GetCursorScreenPos();+ const auto dpos = wpos + ImVec2( 0.5f, 0.5f );+ const auto w = ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ScrollbarSize;+ auto draw = ImGui::GetWindowDrawList();+ const auto ty = ImGui::GetTextLineHeight();+ const auto ty025 = round( ty * 0.25f );+ const auto ty0375 = round( ty * 0.375f );+ const auto ty05 = round( ty * 0.5f );++ const auto timespan = m_vd.zvEnd - m_vd.zvStart;+ const auto pxns = w / double( timespan );+ const auto nspx = 1.0 / pxns;+ const auto scale = std::max( 0.0, round( log10( nspx ) + 2 ) );+ const auto step = pow( 10, scale );++ ImGui::InvisibleButton( "##zoneFrames", ImVec2( w, ty * 1.5f ) );+ TooltipIfHovered( TimeToStringExact( m_vd.zvStart + ( ImGui::GetIO().MousePos.x - wpos.x ) * nspx ) );++ const auto dx = step * pxns;+ double x = 0;+ int tw = 0;+ int tx = 0;+ int64_t tt = 0;+ while( x < w )+ {+ DrawLine( draw, dpos + ImVec2( x, 0 ), dpos + ImVec2( x, ty05 ), 0x66FFFFFF );+ if( tw == 0 )+ {+ char buf[128];+ auto txt = TimeToStringExact( m_vd.zvStart );+ if( m_vd.zvStart >= 0 )+ {+ sprintf( buf, "+%s", txt );+ txt = buf;+ }+ draw->AddText( wpos + ImVec2( x, ty05 ), 0x66FFFFFF, txt );+ tw = ImGui::CalcTextSize( txt ).x;+ }+ else if( x > tx + tw + ty * 2 )+ {+ tx = x;+ auto txt = TimeToString( tt );+ draw->AddText( wpos + ImVec2( x, ty05 ), 0x66FFFFFF, txt );+ tw = ImGui::CalcTextSize( txt ).x;+ }++ if( scale != 0 )+ {+ for( int i=1; i<5; i++ )+ {+ DrawLine( draw, dpos + ImVec2( x + i * dx / 10, 0 ), dpos + ImVec2( x + i * dx / 10, ty025 ), 0x33FFFFFF );+ }+ DrawLine( draw, dpos + ImVec2( x + 5 * dx / 10, 0 ), dpos + ImVec2( x + 5 * dx / 10, ty0375 ), 0x33FFFFFF );+ for( int i=6; i<10; i++ )+ {+ DrawLine( draw, dpos + ImVec2( x + i * dx / 10, 0 ), dpos + ImVec2( x + i * dx / 10, ty025 ), 0x33FFFFFF );+ }+ }++ x += dx;+ tt += step;+ }+}++void View::DrawTimelineFrames( const FrameData& frames )+{+ const std::pair <int, int> zrange = m_worker.GetFrameRange( frames, m_vd.zvStart, m_vd.zvEnd );+ if( zrange.first < 0 ) return;+ if( m_worker.GetFrameBegin( frames, zrange.first ) > m_vd.zvEnd || m_worker.GetFrameEnd( frames, zrange.second ) < m_vd.zvStart ) return;++ const auto wpos = ImGui::GetCursorScreenPos();+ const auto dpos = wpos + ImVec2( 0.5f, 0.5f );+ const auto w = ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ScrollbarSize;+ const auto wh = ImGui::GetContentRegionAvail().y;+ auto draw = ImGui::GetWindowDrawList();+ const auto ty = ImGui::GetTextLineHeight();+ const auto ty025 = ty * 0.25f;+ const auto ty05 = round( ty * 0.5f );++ ImGui::PushID( &frames );+ ImGui::InvisibleButton( "##zoneFrames", ImVec2( w, ty ) );+ ImGui::PopID();+ bool hover = ImGui::IsItemHovered();++ auto timespan = m_vd.zvEnd - m_vd.zvStart;+ auto pxns = w / double( timespan );++ const auto nspx = 1.0 / pxns;++ int64_t prev = -1;+ int64_t prevEnd = -1;+ int64_t endPos = -1;+ bool tooltipDisplayed = false;+ const auto activeFrameSet = m_frames == &frames;+ const int64_t frameTarget = ( activeFrameSet && m_vd.drawFrameTargets ) ? 1000000000ll / m_vd.frameTarget : std::numeric_limits<int64_t>::max();++ const auto inactiveColor = GetColorMuted( 0x888888, activeFrameSet );+ const auto activeColor = GetColorMuted( 0xFFFFFF, activeFrameSet );+ const auto redColor = GetColorMuted( 0x4444FF, activeFrameSet );++ int i = zrange.first;+ auto x1 = ( m_worker.GetFrameBegin( frames, i ) - m_vd.zvStart ) * pxns;+ while( i < zrange.second )+ {+ const auto ftime = m_worker.GetFrameTime( frames, i );+ const auto fbegin = m_worker.GetFrameBegin( frames, i );+ const auto fend = m_worker.GetFrameEnd( frames, i );+ const auto fsz = pxns * ftime;++ if( hover )+ {+ const auto x0 = frames.continuous ? x1 : ( fbegin - m_vd.zvStart ) * pxns;+ x1 = ( fend - m_vd.zvStart ) * pxns;+ if( ImGui::IsMouseHoveringRect( wpos + ImVec2( x0, 0 ), wpos + ImVec2( x1, ty ) ) )+ {+ tooltipDisplayed = true;+ if( IsMouseClickReleased( 1 ) ) m_setRangePopup = RangeSlim { fbegin, fend, true };++ ImGui::BeginTooltip();+ ImGui::TextUnformatted( GetFrameText( frames, i, ftime ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%.1f FPS)", 1000000000.0 / ftime );+ TextFocused( "Time from start of program:", TimeToStringExact( m_worker.GetFrameBegin( frames, i ) ) );+ auto fi = m_worker.GetFrameImage( frames, i );+ if( fi )+ {+ const auto scale = GetScale();+ if( fi != m_frameTexturePtr )+ {+ if( !m_frameTexture ) m_frameTexture = MakeTexture();+ UpdateTexture( m_frameTexture, m_worker.UnpackFrameImage( *fi ), fi->w, fi->h );+ m_frameTexturePtr = fi;+ }+ ImGui::Separator();+ if( fi->flip )+ {+ ImGui::Image( m_frameTexture, ImVec2( fi->w * scale, fi->h * scale ), ImVec2( 0, 1 ), ImVec2( 1, 0 ) );+ }+ else+ {+ ImGui::Image( m_frameTexture, ImVec2( fi->w * scale, fi->h * scale ) );+ }++ if( ImGui::GetIO().KeyCtrl && IsMouseClicked( 0 ) )+ {+ m_showPlayback = true;+ m_playback.pause = true;+ SetPlaybackFrame( frames.frames[i].frameImage );+ }+ }+ ImGui::EndTooltip();++ if( IsMouseClicked( 2 ) )+ {+ ZoomToRange( fbegin, fend );+ }++ if( activeFrameSet ) m_frameHover = i;+ }+ }++ if( fsz < MinFrameSize )+ {+ if( !frames.continuous && prev != -1 )+ {+ if( ( fbegin - prevEnd ) * pxns >= MinFrameSize )+ {+ DrawZigZag( draw, wpos + ImVec2( 0, ty05 ), ( prev - m_vd.zvStart ) * pxns, ( prevEnd - m_vd.zvStart ) * pxns, ty025, inactiveColor );+ prev = -1;+ }+ else+ {+ prevEnd = std::max<int64_t>( fend, fbegin + MinFrameSize * nspx );+ }+ }+ if( prev == -1 )+ {+ prev = fbegin;+ prevEnd = std::max<int64_t>( fend, fbegin + MinFrameSize * nspx );+ }++ const auto begin = frames.frames.begin() + i;+ const auto end = frames.frames.begin() + zrange.second;+ auto it = std::lower_bound( begin, end, int64_t( fbegin + MinVisSize * nspx ), [this, &frames] ( const auto& l, const auto& r ) { return m_worker.GetFrameEnd( frames, std::distance( frames.frames.begin(), &l ) ) < r; } );+ if( it == begin ) ++it;+ i += std::distance( begin, it );+ continue;+ }++ if( prev != -1 )+ {+ if( frames.continuous )+ {+ DrawZigZag( draw, wpos + ImVec2( 0, ty05 ), ( prev - m_vd.zvStart ) * pxns, ( fbegin - m_vd.zvStart ) * pxns, ty025, inactiveColor );+ }+ else+ {+ DrawZigZag( draw, wpos + ImVec2( 0, ty05 ), ( prev - m_vd.zvStart ) * pxns, ( prevEnd - m_vd.zvStart ) * pxns, ty025, inactiveColor );+ }+ prev = -1;+ }++ if( activeFrameSet )+ {+ if( fend - fbegin > frameTarget )+ {+ draw->AddRectFilled( wpos + ImVec2( ( fbegin + frameTarget - m_vd.zvStart ) * pxns, 0 ), wpos + ImVec2( ( fend - m_vd.zvStart ) * pxns, wh ), 0x224444FF );+ }+ if( fbegin >= m_vd.zvStart && endPos != fbegin )+ {+ DrawLine( draw, dpos + ImVec2( ( fbegin - m_vd.zvStart ) * pxns, 0 ), dpos + ImVec2( ( fbegin - m_vd.zvStart ) * pxns, wh ), 0x22FFFFFF );+ }+ if( fend <= m_vd.zvEnd )+ {+ DrawLine( draw, dpos + ImVec2( ( fend - m_vd.zvStart ) * pxns, 0 ), dpos + ImVec2( ( fend - m_vd.zvStart ) * pxns, wh ), 0x22FFFFFF );+ }+ endPos = fend;+ }++ auto buf = GetFrameText( frames, i, ftime );+ auto tx = ImGui::CalcTextSize( buf ).x;+ uint32_t color = ( frames.name == 0 && i == 0 ) ? redColor : activeColor;++ if( fsz - 7 <= tx )+ {+ static char tmp[256];+ sprintf( tmp, "%s (%s)", RealToString( i ), TimeToString( ftime ) );+ buf = tmp;+ tx = ImGui::CalcTextSize( buf ).x;+ }+ if( fsz - 7 <= tx )+ {+ buf = TimeToString( ftime );+ tx = ImGui::CalcTextSize( buf ).x;+ }++ if( fbegin >= m_vd.zvStart )+ {+ DrawLine( draw, dpos + ImVec2( ( fbegin - m_vd.zvStart ) * pxns + 2, 1 ), dpos + ImVec2( ( fbegin - m_vd.zvStart ) * pxns + 2, ty - 1 ), color );+ }+ if( fend <= m_vd.zvEnd )+ {+ DrawLine( draw, dpos + ImVec2( ( fend - m_vd.zvStart ) * pxns - 2, 1 ), dpos + ImVec2( ( fend - m_vd.zvStart ) * pxns - 2, ty - 1 ), color );+ }+ if( fsz - 7 > tx )+ {+ const auto f0 = ( fbegin - m_vd.zvStart ) * pxns + 2;+ const auto f1 = ( fend - m_vd.zvStart ) * pxns - 2;+ const auto x0 = f0 + 1;+ const auto x1 = f1 - 1;+ const auto te = x1 - tx;++ auto tpos = ( x0 + te ) / 2;+ if( tpos < 0 )+ {+ tpos = std::min( std::min( 0., te - tpos ), te );+ }+ else if( tpos > w - tx )+ {+ tpos = std::max( double( w - tx ), x0 );+ }+ tpos = round( tpos );++ DrawLine( draw, dpos + ImVec2( std::max( -10.0, f0 ), ty05 ), dpos + ImVec2( tpos, ty05 ), color );+ DrawLine( draw, dpos + ImVec2( std::max( -10.0, tpos + tx + 1 ), ty05 ), dpos + ImVec2( std::min( w + 20.0, f1 ), ty05 ), color );+ draw->AddText( wpos + ImVec2( tpos, 0 ), color, buf );+ }+ else+ {+ DrawLine( draw, dpos + ImVec2( std::max( -10.0, ( fbegin - m_vd.zvStart ) * pxns + 2 ), ty05 ), dpos + ImVec2( std::min( w + 20.0, ( fend - m_vd.zvStart ) * pxns - 2 ), ty05 ), color );+ }++ i++;+ }++ if( prev != -1 )+ {+ if( frames.continuous )+ {+ DrawZigZag( draw, wpos + ImVec2( 0, ty05 ), ( prev - m_vd.zvStart ) * pxns, ( m_worker.GetFrameBegin( frames, zrange.second-1 ) - m_vd.zvStart ) * pxns, ty025, inactiveColor );+ }+ else+ {+ const auto begin = ( prev - m_vd.zvStart ) * pxns;+ const auto end = ( m_worker.GetFrameBegin( frames, zrange.second-1 ) - m_vd.zvStart ) * pxns;+ DrawZigZag( draw, wpos + ImVec2( 0, ty05 ), begin, std::max( begin + MinFrameSize, end ), ty025, inactiveColor );+ }+ }++ if( hover )+ {+ if( !tooltipDisplayed )+ {+ ImGui::BeginTooltip();+ TextDisabledUnformatted( "Frame set:" );+ ImGui::SameLine();+ ImGui::TextUnformatted( GetFrameSetName( frames ) );+ ImGui::EndTooltip();+ }+ if( IsMouseClicked( 0 ) )+ {+ m_frames = &frames;+ }+ }+}++}
+ cbits/tracy/profiler/src/profiler/TracyView_FrameTree.cpp view
@@ -0,0 +1,875 @@+#include "TracyImGui.hpp"+#include "TracyPrint.hpp"+#include "TracyView.hpp"+#include "tracy_pdqsort.h"++namespace tracy+{++template<class T>+static tracy_force_inline T* GetFrameTreeItemNoGroup( unordered_flat_map<uint64_t, T>& tree, CallstackFrameId idx )+{+ auto it = tree.find( idx.data );+ if( it == tree.end() )+ {+ it = tree.emplace( idx.data, T( idx ) ).first;+ }+ return &it->second;+}++template<class T>+static tracy_force_inline T* GetFrameTreeItemGroup( unordered_flat_map<uint64_t, T>& tree, CallstackFrameId idx, const Worker& worker )+{+ auto frameDataPtr = worker.GetCallstackFrame( idx );+ if( !frameDataPtr ) return nullptr;++ auto& frameData = *frameDataPtr;+ auto& frame = frameData.data[frameData.size-1];+ auto fidx = frame.name.Idx();++ auto it = tree.find( fidx );+ if( it == tree.end() )+ {+ it = tree.emplace( fidx, T( idx ) ).first;+ }+ return &it->second;+}++template<class T>+static tracy_force_inline T* GetParentFrameTreeItemGroup( unordered_flat_map<uint64_t, T>& tree, CallstackFrameId idx, const Worker& worker )+{+ auto frameDataPtr = idx.custom ? worker.GetParentCallstackFrame( idx ) : worker.GetCallstackFrame( idx );+ if( !frameDataPtr ) return nullptr;++ auto& frameData = *frameDataPtr;+ auto& frame = frameData.data[frameData.size-1];+ auto fidx = frame.name.Idx();++ auto it = tree.find( fidx );+ if( it == tree.end() )+ {+ it = tree.emplace( fidx, T( idx ) ).first;+ }+ return &it->second;+}+++unordered_flat_map<uint32_t, View::MemPathData> View::GetCallstackPaths( const MemData& mem, MemRange memRange ) const+{+ unordered_flat_map<uint32_t, MemPathData> pathSum;+ pathSum.reserve( m_worker.GetCallstackPayloadCount() );++ const bool hide_inactive = memRange == MemRange::Active;++ if( m_memInfo.range.active )+ {+ auto it = std::lower_bound( mem.data.begin(), mem.data.end(), m_memInfo.range.min, []( const auto& lhs, const auto& rhs ) { return lhs.TimeAlloc() < rhs; } );+ if( it != mem.data.end() )+ {+ auto end = std::lower_bound( mem.data.begin(), mem.data.end(), m_memInfo.range.max, []( const auto& lhs, const auto& rhs ) { return lhs.TimeAlloc() < rhs; } );+ if( memRange != MemRange::Full )+ {+ while( it != end )+ {+ auto& ev = *it++;+ if( ev.CsAlloc() == 0 ) continue;+ const bool is_inactive = ev.TimeFree() >= 0 && ev.TimeFree() < m_memInfo.range.max;+ if( hide_inactive == is_inactive ) continue;+ auto pit = pathSum.find( ev.CsAlloc() );+ if( pit == pathSum.end() )+ {+ pathSum.emplace( ev.CsAlloc(), MemPathData { 1, ev.Size() } );+ }+ else+ {+ pit->second.cnt++;+ pit->second.mem += ev.Size();+ }+ }+ }+ else+ {+ while( it != end )+ {+ auto& ev = *it++;+ if( ev.CsAlloc() == 0 ) continue;+ auto pit = pathSum.find( ev.CsAlloc() );+ if( pit == pathSum.end() )+ {+ pathSum.emplace( ev.CsAlloc(), MemPathData { 1, ev.Size() } );+ }+ else+ {+ pit->second.cnt++;+ pit->second.mem += ev.Size();+ }+ }+ }+ }+ }+ else+ {+ if( memRange != MemRange::Full )+ {+ for( auto& ev : mem.data )+ {+ if( ev.CsAlloc() == 0 ) continue;+ const bool is_inactive = ev.TimeFree() >= 0;+ if( hide_inactive == is_inactive ) continue;+ auto it = pathSum.find( ev.CsAlloc() );+ if( it == pathSum.end() )+ {+ pathSum.emplace( ev.CsAlloc(), MemPathData { 1, ev.Size() } );+ }+ else+ {+ it->second.cnt++;+ it->second.mem += ev.Size();+ }+ }+ }+ else+ {+ for( auto& ev : mem.data )+ {+ if( ev.CsAlloc() == 0 ) continue;+ auto it = pathSum.find( ev.CsAlloc() );+ if( it == pathSum.end() )+ {+ pathSum.emplace( ev.CsAlloc(), MemPathData { 1, ev.Size() } );+ }+ else+ {+ it->second.cnt++;+ it->second.mem += ev.Size();+ }+ }+ }+ }+ return pathSum;+}++unordered_flat_map<uint64_t, MemCallstackFrameTree> View::GetCallstackFrameTreeBottomUp( const MemData& mem ) const+{+ unordered_flat_map<uint64_t, MemCallstackFrameTree> root;+ auto pathSum = GetCallstackPaths( mem, m_memRangeBottomUp );+ if( m_groupCallstackTreeByNameBottomUp )+ {+ for( auto& path : pathSum )+ {+ auto& cs = m_worker.GetCallstack( path.first );+ auto base = cs.back();+ auto treePtr = GetFrameTreeItemGroup( root, base, m_worker );+ if( treePtr )+ {+ treePtr->count += path.second.cnt;+ treePtr->alloc += path.second.mem;+ treePtr->callstacks.emplace( path.first );+ for( int i = int( cs.size() ) - 2; i >= 0; i-- )+ {+ treePtr = GetFrameTreeItemGroup( treePtr->children, cs[i], m_worker );+ if( !treePtr ) break;+ treePtr->count += path.second.cnt;+ treePtr->alloc += path.second.mem;+ treePtr->callstacks.emplace( path.first );+ }+ }+ }+ }+ else+ {+ for( auto& path : pathSum )+ {+ auto& cs = m_worker.GetCallstack( path.first );+ auto base = cs.back();+ auto treePtr = GetFrameTreeItemNoGroup( root, base );+ treePtr->count += path.second.cnt;+ treePtr->alloc += path.second.mem;+ treePtr->callstacks.emplace( path.first );+ for( int i = int( cs.size() ) - 2; i >= 0; i-- )+ {+ treePtr = GetFrameTreeItemNoGroup( treePtr->children, cs[i] );+ treePtr->count += path.second.cnt;+ treePtr->alloc += path.second.mem;+ treePtr->callstacks.emplace( path.first );+ }+ }+ }+ return root;+}++unordered_flat_map<uint64_t, CallstackFrameTree> View::GetCallstackFrameTreeBottomUp( const unordered_flat_map<uint32_t, uint64_t>& stacks, bool group ) const+{+ unordered_flat_map<uint64_t, CallstackFrameTree> root;+ if( group )+ {+ for( auto& path : stacks )+ {+ auto& cs = m_worker.GetCallstack( path.first );+ auto base = cs.back();+ auto treePtr = GetFrameTreeItemGroup( root, base, m_worker );+ if( treePtr )+ {+ treePtr->count += path.second;+ for( int i = int( cs.size() ) - 2; i >= 0; i-- )+ {+ treePtr = GetFrameTreeItemGroup( treePtr->children, cs[i], m_worker );+ if( !treePtr ) break;+ treePtr->count += path.second;+ }+ }+ }+ }+ else+ {+ for( auto& path : stacks )+ {+ auto& cs = m_worker.GetCallstack( path.first );+ auto base = cs.back();+ auto treePtr = GetFrameTreeItemNoGroup( root, base );+ treePtr->count += path.second;+ for( int i = int( cs.size() ) - 2; i >= 0; i-- )+ {+ treePtr = GetFrameTreeItemNoGroup( treePtr->children, cs[i] );+ treePtr->count += path.second;+ }+ }+ }+ return root;+}++unordered_flat_map<uint64_t, CallstackFrameTree> View::GetParentsCallstackFrameTreeBottomUp( const unordered_flat_map<uint32_t, uint32_t>& stacks, bool group ) const+{+ unordered_flat_map<uint64_t, CallstackFrameTree> root;+ if( group )+ {+ for( auto& path : stacks )+ {+ auto& cs = m_worker.GetParentCallstack( path.first );+ auto base = cs.back();+ auto treePtr = GetParentFrameTreeItemGroup( root, base, m_worker );+ if( treePtr )+ {+ treePtr->count += path.second;+ for( int i = int( cs.size() ) - 2; i >= 0; i-- )+ {+ treePtr = GetParentFrameTreeItemGroup( treePtr->children, cs[i], m_worker );+ if( !treePtr ) break;+ treePtr->count += path.second;+ }+ }+ }+ }+ else+ {+ for( auto& path : stacks )+ {+ auto& cs = m_worker.GetParentCallstack( path.first );+ auto base = cs.back();+ auto treePtr = GetFrameTreeItemNoGroup( root, base );+ treePtr->count += path.second;+ for( int i = int( cs.size() ) - 2; i >= 0; i-- )+ {+ treePtr = GetFrameTreeItemNoGroup( treePtr->children, cs[i] );+ treePtr->count += path.second;+ }+ }+ }+ return root;+}+++unordered_flat_map<uint64_t, MemCallstackFrameTree> View::GetCallstackFrameTreeTopDown( const MemData& mem ) const+{+ unordered_flat_map<uint64_t, MemCallstackFrameTree> root;+ auto pathSum = GetCallstackPaths( mem, m_memRangeTopDown );+ if( m_groupCallstackTreeByNameTopDown )+ {+ for( auto& path : pathSum )+ {+ auto& cs = m_worker.GetCallstack( path.first );+ auto base = cs.front();+ auto treePtr = GetFrameTreeItemGroup( root, base, m_worker );+ if( treePtr )+ {+ treePtr->count += path.second.cnt;+ treePtr->alloc += path.second.mem;+ treePtr->callstacks.emplace( path.first );+ for( uint16_t i = 1; i < cs.size(); i++ )+ {+ treePtr = GetFrameTreeItemGroup( treePtr->children, cs[i], m_worker );+ if( !treePtr ) break;+ treePtr->count += path.second.cnt;+ treePtr->alloc += path.second.mem;+ treePtr->callstacks.emplace( path.first );+ }+ }+ }+ }+ else+ {+ for( auto& path : pathSum )+ {+ auto& cs = m_worker.GetCallstack( path.first );+ auto base = cs.front();+ auto treePtr = GetFrameTreeItemNoGroup( root, base );+ treePtr->count += path.second.cnt;+ treePtr->alloc += path.second.mem;+ treePtr->callstacks.emplace( path.first );+ for( uint16_t i = 1; i < cs.size(); i++ )+ {+ treePtr = GetFrameTreeItemNoGroup( treePtr->children, cs[i] );+ treePtr->count += path.second.cnt;+ treePtr->alloc += path.second.mem;+ treePtr->callstacks.emplace( path.first );+ }+ }+ }+ return root;+}++unordered_flat_map<uint64_t, CallstackFrameTree> View::GetCallstackFrameTreeTopDown( const unordered_flat_map<uint32_t, uint64_t>& stacks, bool group ) const+{+ unordered_flat_map<uint64_t, CallstackFrameTree> root;+ if( group )+ {+ for( auto& path : stacks )+ {+ auto& cs = m_worker.GetCallstack( path.first );+ auto base = cs.front();+ auto treePtr = GetFrameTreeItemGroup( root, base, m_worker );+ if( treePtr )+ {+ treePtr->count += path.second;+ for( uint16_t i = 1; i < cs.size(); i++ )+ {+ treePtr = GetFrameTreeItemGroup( treePtr->children, cs[i], m_worker );+ if( !treePtr ) break;+ treePtr->count += path.second;+ }+ }+ }+ }+ else+ {+ for( auto& path : stacks )+ {+ auto& cs = m_worker.GetCallstack( path.first );+ auto base = cs.front();+ auto treePtr = GetFrameTreeItemNoGroup( root, base );+ treePtr->count += path.second;+ for( uint16_t i = 1; i < cs.size(); i++ )+ {+ treePtr = GetFrameTreeItemNoGroup( treePtr->children, cs[i] );+ treePtr->count += path.second;+ }+ }+ }+ return root;+}++unordered_flat_map<uint64_t, CallstackFrameTree> View::GetParentsCallstackFrameTreeTopDown( const unordered_flat_map<uint32_t, uint32_t>& stacks, bool group ) const+{+ unordered_flat_map<uint64_t, CallstackFrameTree> root;+ if( group )+ {+ for( auto& path : stacks )+ {+ auto& cs = m_worker.GetParentCallstack( path.first );+ auto base = cs.front();+ auto treePtr = GetParentFrameTreeItemGroup( root, base, m_worker );+ if( treePtr )+ {+ treePtr->count += path.second;+ for( uint16_t i = 1; i < cs.size(); i++ )+ {+ treePtr = GetParentFrameTreeItemGroup( treePtr->children, cs[i], m_worker );+ if( !treePtr ) break;+ treePtr->count += path.second;+ }+ }+ }+ }+ else+ {+ for( auto& path : stacks )+ {+ auto& cs = m_worker.GetParentCallstack( path.first );+ auto base = cs.front();+ auto treePtr = GetFrameTreeItemNoGroup( root, base );+ treePtr->count += path.second;+ for( uint16_t i = 1; i < cs.size(); i++ )+ {+ treePtr = GetFrameTreeItemNoGroup( treePtr->children, cs[i] );+ treePtr->count += path.second;+ }+ }+ }+ return root;+}++void View::DrawFrameTreeLevel( const unordered_flat_map<uint64_t, MemCallstackFrameTree>& tree, int& idx )+{+ auto& io = ImGui::GetIO();++ std::vector<unordered_flat_map<uint64_t, MemCallstackFrameTree>::const_iterator> sorted;+ sorted.reserve( tree.size() );+ for( auto it = tree.begin(); it != tree.end(); ++it )+ {+ sorted.emplace_back( it );+ }+ pdqsort_branchless( sorted.begin(), sorted.end(), [] ( const auto& lhs, const auto& rhs ) { return lhs->second.alloc > rhs->second.alloc; } );++ int lidx = 0;+ for( auto& _v : sorted )+ {+ auto& v = _v->second;+ const auto isKernel = ( m_worker.GetCanonicalPointer( v.frame ) >> 63 ) != 0;+ idx++;+ auto frameDataPtr = m_worker.GetCallstackFrame( v.frame );+ if( frameDataPtr )+ {+ auto& frameData = *frameDataPtr;+ auto frame = frameData.data[frameData.size-1];+ bool expand = false;++ const auto frameName = m_worker.GetString( frame.name );+ if( v.children.empty() )+ {+ ImGui::Indent( ImGui::GetTreeNodeToLabelSpacing() );+ if( frameName[0] == '[' )+ {+ TextDisabledUnformatted( frameName );+ }+ else if( isKernel )+ {+ TextColoredUnformatted( 0xFF8888FF, frameName );+ }+ else if( m_vd.shortenName == ShortenName::Never )+ {+ ImGui::TextUnformatted( frameName );+ }+ else+ {+ const auto normalized = ShortenZoneName( ShortenName::OnlyNormalize, frameName );+ ImGui::TextUnformatted( normalized );+ TooltipNormalizedName( frameName, normalized );+ }+ ImGui::Unindent( ImGui::GetTreeNodeToLabelSpacing() );+ }+ else+ {+ ImGui::PushID( lidx++ );+ if( frameName[0] == '[' ) ImGui::PushStyleColor( ImGuiCol_Text, 0x88FFFFFF );+ else if( isKernel ) ImGui::PushStyleColor( ImGuiCol_Text, 0xFF8888FF );+ if( tree.size() == 1 )+ {+ if( m_vd.shortenName == ShortenName::Never )+ {+ expand = ImGui::TreeNodeEx( frameName, ImGuiTreeNodeFlags_DefaultOpen );+ }+ else+ {+ const auto normalized = ShortenZoneName( ShortenName::OnlyNormalize, frameName );+ expand = ImGui::TreeNodeEx( normalized, ImGuiTreeNodeFlags_DefaultOpen );+ TooltipNormalizedName( frameName, normalized );+ }+ }+ else+ {+ if( m_vd.shortenName == ShortenName::Never )+ {+ expand = ImGui::TreeNode( frameName );+ }+ else+ {+ const auto normalized = ShortenZoneName( ShortenName::OnlyNormalize, frameName );+ expand = ImGui::TreeNode( normalized );+ TooltipNormalizedName( frameName, normalized );+ }+ }+ if( isKernel || frameName[0] == '[' ) ImGui::PopStyleColor();+ ImGui::PopID();+ }++ if( ImGui::IsItemClicked( 1 ) )+ {+ auto& mem = m_worker.GetMemoryNamed( m_memInfo.pool ).data;+ const auto sz = mem.size();+ m_memInfo.showAllocList = true;+ m_memInfo.allocList.clear();+ for( size_t i=0; i<sz; i++ )+ {+ if( v.callstacks.find( mem[i].CsAlloc() ) != v.callstacks.end() )+ {+ m_memInfo.allocList.emplace_back( i );+ }+ }+ }++ if( io.KeyCtrl && ImGui::IsItemHovered() )+ {+ ImGui::BeginTooltip();+ TextFocused( "Allocations size:", MemSizeToString( v.alloc ) );+ TextFocused( "Allocations count:", RealToString( v.count ) );+ TextFocused( "Mean allocation size:", MemSizeToString( v.alloc / v.count ) );+ ImGui::SameLine();+ ImGui::EndTooltip();+ }++ if( m_callstackTreeBuzzAnim.Match( idx ) )+ {+ const auto time = m_callstackTreeBuzzAnim.Time();+ const auto indentVal = sin( time * 60.f ) * 10.f * time;+ ImGui::SameLine( 0, ImGui::GetStyle().ItemSpacing.x + indentVal );+ }+ else+ {+ ImGui::SameLine();+ }+ const char* fileName = nullptr;+ if( frame.line == 0 )+ {+ if( frameDataPtr->imageName.Active() ) TextDisabledUnformatted( m_worker.GetString( frameDataPtr->imageName ) );+ }+ else+ {+ fileName = m_worker.GetString( frame.file );+ ImGui::TextDisabled( "%s:%i", fileName, frame.line );+ }+ if( ImGui::IsItemHovered() )+ {+ DrawSourceTooltip( fileName, frame.line );+ if( ImGui::IsItemClicked( 1 ) )+ {+ if( !ViewDispatch( fileName, frame.line, frame.symAddr ) )+ {+ m_callstackTreeBuzzAnim.Enable( idx, 0.5f );+ }+ }+ }++ ImGui::SameLine();+ if( v.children.empty() )+ {+ ImGui::TextColored( ImVec4( 0.2, 0.8, 0.8, 1.0 ), "%s (%s)", MemSizeToString( v.alloc ), RealToString( v.count ) );+ TooltipIfHovered( "Cost in this node" );+ }+ else+ {+ uint32_t childCost = 0;+ uint64_t childAlloc = 0;+ for( auto& c : v.children )+ {+ childCost += c.second.count;+ childAlloc += c.second.alloc;+ }+ const auto rc = v.count - childCost;+ if( rc != 0 )+ {+ ImGui::TextColored( ImVec4( 0.2, 0.8, 0.8, 1.0 ), "%s (%s)", MemSizeToString( v.alloc - childAlloc ), RealToString( rc ) );+ TooltipIfHovered( "Cost only in this node" );+ ImGui::SameLine();+ }+ ImGui::TextColored( ImVec4( 0.8, 0.8, 0.2, 1.0 ), "%s (%s)", MemSizeToString( v.alloc ), RealToString( v.count ) );+ TooltipIfHovered( "Cost in this node and children" );+ }++ if( expand )+ {+ DrawFrameTreeLevel( v.children, idx );+ ImGui::TreePop();+ }+ }+ }+}++void View::DrawFrameTreeLevel( const unordered_flat_map<uint64_t, CallstackFrameTree>& tree, int& idx )+{+ std::vector<unordered_flat_map<uint64_t, CallstackFrameTree>::const_iterator> sorted;+ sorted.reserve( tree.size() );+ for( auto it = tree.begin(); it != tree.end(); ++it )+ {+ sorted.emplace_back( it );+ }+ pdqsort_branchless( sorted.begin(), sorted.end(), [] ( const auto& lhs, const auto& rhs ) { return lhs->second.count > rhs->second.count; } );++ int lidx = 0;+ for( auto& _v : sorted )+ {+ auto& v = _v->second;+ const auto isKernel = ( m_worker.GetCanonicalPointer( v.frame ) >> 63 ) != 0;+ idx++;+ auto frameDataPtr = m_worker.GetCallstackFrame( v.frame );+ if( frameDataPtr )+ {+ auto& frameData = *frameDataPtr;+ auto frame = frameData.data[frameData.size-1];+ bool expand = false;++ const auto frameName = m_worker.GetString( frame.name );+ if( v.children.empty() )+ {+ ImGui::Indent( ImGui::GetTreeNodeToLabelSpacing() );+ if( frameName[0] == '[' )+ {+ TextDisabledUnformatted( frameName );+ }+ else if( isKernel )+ {+ TextColoredUnformatted( 0xFF8888FF, frameName );+ }+ else if( m_vd.shortenName == ShortenName::Never )+ {+ ImGui::TextUnformatted( frameName );+ }+ else+ {+ const auto normalized = ShortenZoneName( ShortenName::OnlyNormalize, frameName );+ expand = ImGui::TreeNodeEx( normalized, ImGuiTreeNodeFlags_DefaultOpen );+ TooltipNormalizedName( frameName, normalized );+ }+ ImGui::Unindent( ImGui::GetTreeNodeToLabelSpacing() );+ }+ else+ {+ ImGui::PushID( lidx++ );+ if( frameName[0] == '[' ) ImGui::PushStyleColor( ImGuiCol_Text, 0x88FFFFFF );+ else if( isKernel ) ImGui::PushStyleColor( ImGuiCol_Text, 0xFF8888FF );+ if( tree.size() == 1 )+ {+ if( m_vd.shortenName == ShortenName::Never )+ {+ expand = ImGui::TreeNodeEx( frameName, ImGuiTreeNodeFlags_DefaultOpen );+ }+ else+ {+ const auto normalized = ShortenZoneName( ShortenName::OnlyNormalize, frameName );+ expand = ImGui::TreeNodeEx( normalized, ImGuiTreeNodeFlags_DefaultOpen );+ TooltipNormalizedName( frameName, normalized );+ }+ }+ else+ {+ if( m_vd.shortenName == ShortenName::Never )+ {+ expand = ImGui::TreeNode( frameName );+ }+ else+ {+ const auto normalized = ShortenZoneName( ShortenName::OnlyNormalize, frameName );+ expand = ImGui::TreeNode( normalized );+ TooltipNormalizedName( frameName, normalized );+ }+ }+ if( isKernel || frameName[0] == '[' ) ImGui::PopStyleColor();+ ImGui::PopID();+ }++ if( m_callstackTreeBuzzAnim.Match( idx ) )+ {+ const auto time = m_callstackTreeBuzzAnim.Time();+ const auto indentVal = sin( time * 60.f ) * 10.f * time;+ ImGui::SameLine( 0, ImGui::GetStyle().ItemSpacing.x + indentVal );+ }+ else+ {+ ImGui::SameLine();+ }+ const char* fileName = nullptr;+ if( frame.line == 0 )+ {+ TextDisabledUnformatted( m_worker.GetString( frameDataPtr->imageName ) );+ }+ else+ {+ fileName = m_worker.GetString( frame.file );+ ImGui::TextDisabled( "%s:%i", fileName, frame.line );+ }+ if( ImGui::IsItemHovered() )+ {+ DrawSourceTooltip( fileName, frame.line );+ if( ImGui::IsItemClicked( 1 ) )+ {+ if( !ViewDispatch( fileName, frame.line, frame.symAddr ) )+ {+ m_callstackTreeBuzzAnim.Enable( idx, 0.5f );+ }+ }+ }++ ImGui::SameLine();+ if( v.children.empty() )+ {+ ImGui::TextColored( ImVec4( 0.2, 0.8, 0.8, 1.0 ), "(%s)", RealToString( v.count ) );+ TooltipIfHovered( "Cost in this node" );+ }+ else+ {+ uint32_t childCost = 0;+ for( auto& c : v.children ) childCost += c.second.count;+ const auto r = v.count - childCost;+ if( r != 0 )+ {+ ImGui::TextColored( ImVec4( 0.2, 0.8, 0.8, 1.0 ), "(%s)", RealToString( r ) );+ TooltipIfHovered( "Cost only in this node" );+ ImGui::SameLine();+ }+ ImGui::TextColored( ImVec4( 0.8, 0.8, 0.2, 1.0 ), "(%s)", RealToString( v.count ) );+ TooltipIfHovered( "Cost in this node and children" );+ }++ if( expand )+ {+ DrawFrameTreeLevel( v.children, idx );+ ImGui::TreePop();+ }+ }+ }+}++void View::DrawParentsFrameTreeLevel( const unordered_flat_map<uint64_t, CallstackFrameTree>& tree, int& idx )+{+ std::vector<unordered_flat_map<uint64_t, CallstackFrameTree>::const_iterator> sorted;+ sorted.reserve( tree.size() );+ for( auto it = tree.begin(); it != tree.end(); ++it )+ {+ sorted.emplace_back( it );+ }+ pdqsort_branchless( sorted.begin(), sorted.end(), [] ( const auto& lhs, const auto& rhs ) { return lhs->second.count > rhs->second.count; } );++ int lidx = 0;+ for( auto& _v : sorted )+ {+ auto& v = _v->second;+ const auto isKernel = ( m_worker.GetCanonicalPointer( v.frame ) >> 63 ) != 0;+ idx++;+ auto frameDataPtr = v.frame.custom ? m_worker.GetParentCallstackFrame( v.frame ) : m_worker.GetCallstackFrame( v.frame );+ if( frameDataPtr )+ {+ auto& frameData = *frameDataPtr;+ auto frame = frameData.data[frameData.size-1];+ bool expand = false;++ const auto frameName = m_worker.GetString( frame.name );+ if( v.children.empty() )+ {+ ImGui::Indent( ImGui::GetTreeNodeToLabelSpacing() );+ if( frameName[0] == '[' )+ {+ TextDisabledUnformatted( frameName );+ }+ else if( isKernel )+ {+ TextColoredUnformatted( 0xFF8888FF, frameName );+ }+ else if( m_vd.shortenName == ShortenName::Never )+ {+ ImGui::TextUnformatted( frameName );+ }+ else+ {+ const auto normalized = ShortenZoneName( ShortenName::OnlyNormalize, frameName );+ ImGui::TextUnformatted( normalized );+ TooltipNormalizedName( frameName, normalized );+ }+ ImGui::Unindent( ImGui::GetTreeNodeToLabelSpacing() );+ }+ else+ {+ ImGui::PushID( lidx++ );+ if( frameName[0] == '[' ) ImGui::PushStyleColor( ImGuiCol_Text, 0x88FFFFFF );+ else if( isKernel ) ImGui::PushStyleColor( ImGuiCol_Text, 0xFF8888FF );+ if( tree.size() == 1 )+ {+ if( m_vd.shortenName == ShortenName::Never )+ {+ expand = ImGui::TreeNodeEx( frameName, ImGuiTreeNodeFlags_DefaultOpen );+ }+ else+ {+ const auto normalized = ShortenZoneName( ShortenName::OnlyNormalize, frameName );+ expand = ImGui::TreeNodeEx( normalized, ImGuiTreeNodeFlags_DefaultOpen );+ TooltipNormalizedName( frameName, normalized );+ }+ }+ else+ {+ if( m_vd.shortenName == ShortenName::Never )+ {+ expand = ImGui::TreeNode( frameName );+ }+ else+ {+ const auto normalized = ShortenZoneName( ShortenName::OnlyNormalize, frameName );+ expand = ImGui::TreeNode( normalized );+ TooltipNormalizedName( frameName, normalized );+ }+ }+ if( isKernel || frameName[0] == '[' ) ImGui::PopStyleColor();+ ImGui::PopID();+ }++ if( m_callstackTreeBuzzAnim.Match( idx ) )+ {+ const auto time = m_callstackTreeBuzzAnim.Time();+ const auto indentVal = sin( time * 60.f ) * 10.f * time;+ ImGui::SameLine( 0, ImGui::GetStyle().ItemSpacing.x + indentVal );+ }+ else+ {+ ImGui::SameLine();+ }+ const char* fileName = nullptr;+ if( frame.line == 0 )+ {+ TextDisabledUnformatted( m_worker.GetString( frameDataPtr->imageName ) );+ }+ else+ {+ fileName = m_worker.GetString( frame.file );+ ImGui::TextDisabled( "%s:%i", fileName, frame.line );+ }+ if( ImGui::IsItemHovered() )+ {+ DrawSourceTooltip( fileName, frame.line );+ if( ImGui::IsItemClicked( 1 ) )+ {+ if( !ViewDispatch( fileName, frame.line, frame.symAddr ) )+ {+ m_callstackTreeBuzzAnim.Enable( idx, 0.5f );+ }+ }+ }++ ImGui::SameLine();+ if( v.children.empty() )+ {+ ImGui::TextColored( ImVec4( 0.2, 0.8, 0.8, 1.0 ), "(%s)", m_statSampleTime ? TimeToString( m_worker.GetSamplingPeriod() * v.count ) : RealToString( v.count ) );+ TooltipIfHovered( "Cost in this node" );+ }+ else+ {+ uint32_t childCost = 0;+ for( auto& c : v.children ) childCost += c.second.count;+ const auto r = v.count - childCost;+ if( r != 0 )+ {+ ImGui::TextColored( ImVec4( 0.2, 0.8, 0.8, 1.0 ), "(%s)", m_statSampleTime ? TimeToString( m_worker.GetSamplingPeriod() * r ) : RealToString( r ) );+ TooltipIfHovered( "Cost only in this node" );+ ImGui::SameLine();+ }+ ImGui::TextColored( ImVec4( 0.8, 0.8, 0.2, 1.0 ), "(%s)", m_statSampleTime ? TimeToString( m_worker.GetSamplingPeriod() * v.count ) : RealToString( v.count ) );+ TooltipIfHovered( "Cost in this node and children" );+ }++ if( expand )+ {+ DrawParentsFrameTreeLevel( v.children, idx );+ ImGui::TreePop();+ }+ }+ }+}++}
+ cbits/tracy/profiler/src/profiler/TracyView_GpuTimeline.cpp view
@@ -0,0 +1,368 @@+#include "TracyColor.hpp"+#include "TracyImGui.hpp"+#include "TracyMouse.hpp"+#include "TracyPrint.hpp"+#include "TracyTimelineContext.hpp"+#include "TracyView.hpp"++namespace tracy+{++constexpr float MinVisSize = 3;++bool View::DrawGpu( const TimelineContext& ctx, const GpuCtxData& gpu, int& offset )+{+ const auto w = ctx.w;+ const auto ty = ctx.ty;+ const auto ostep = ty + 1;+ const auto pxns = ctx.pxns;+ const auto nspx = ctx.nspx;+ const auto& wpos = ctx.wpos;+ const auto dpos = wpos + ImVec2( 0.5f, 0.5f );+ const auto hover = ctx.hover;+ const auto yMin = ctx.yMin;+ const auto yMax = ctx.yMax;++ auto draw = ImGui::GetWindowDrawList();++ ImGui::PushFont( m_smallFont );+ const auto sty = ImGui::GetTextLineHeight();+ const auto sstep = sty + 1;+ ImGui::PopFont();++ const auto singleThread = gpu.threadData.size() == 1;+ int depth = 0;++ for( auto& td : gpu.threadData )+ {+ auto& tl = td.second.timeline;+ assert( !tl.empty() );+ if( tl.is_magic() )+ {+ auto& tlm = *(Vector<GpuEvent>*)&tl;+ if( tlm.front().GpuStart() >= 0 )+ {+ const auto begin = tlm.front().GpuStart();+ const auto drift = GpuDrift( &gpu );+ if( !singleThread ) offset += sstep;+ const auto partDepth = DispatchGpuZoneLevel( tl, hover, pxns, int64_t( nspx ), wpos, offset, 0, gpu.thread, yMin, yMax, begin, drift );+ if( partDepth != 0 )+ {+ if( !singleThread )+ {+ ImGui::PushFont( m_smallFont );+ DrawTextContrast( draw, wpos + ImVec2( ty, offset-1-sstep ), 0xFFFFAAAA, m_worker.GetThreadName( td.first ) );+ DrawLine( draw, dpos + ImVec2( 0, offset+sty-sstep ), dpos + ImVec2( w, offset+sty-sstep ), 0x22FFAAAA );+ ImGui::PopFont();+ }++ offset += ostep * partDepth;+ depth += partDepth;+ }+ else if( !singleThread )+ {+ offset -= sstep;+ }+ }+ }+ else+ {+ if( tl.front()->GpuStart() >= 0 )+ {+ const auto begin = tl.front()->GpuStart();+ const auto drift = GpuDrift( &gpu );+ if( !singleThread ) offset += sstep;+ const auto partDepth = DispatchGpuZoneLevel( tl, hover, pxns, int64_t( nspx ), wpos, offset, 0, gpu.thread, yMin, yMax, begin, drift );+ if( partDepth != 0 )+ {+ if( !singleThread )+ {+ ImGui::PushFont( m_smallFont );+ DrawTextContrast( draw, wpos + ImVec2( ty, offset-1-sstep ), 0xFFFFAAAA, m_worker.GetThreadName( td.first ) );+ DrawLine( draw, dpos + ImVec2( 0, offset+sty-sstep ), dpos + ImVec2( w, offset+sty-sstep ), 0x22FFAAAA );+ ImGui::PopFont();+ }++ offset += ostep * partDepth;+ depth += partDepth;+ }+ else if( !singleThread )+ {+ offset -= sstep;+ }+ }+ }+ }+ return depth != 0;+}++int View::DispatchGpuZoneLevel( const Vector<short_ptr<GpuEvent>>& vec, bool hover, double pxns, int64_t nspx, const ImVec2& wpos, int _offset, int depth, uint64_t thread, float yMin, float yMax, int64_t begin, int drift )+{+ const auto ty = ImGui::GetTextLineHeight();+ const auto ostep = ty + 1;+ const auto offset = _offset + ostep * depth;++ const auto yPos = wpos.y + offset;+ if( yPos + ostep >= yMin && yPos <= yMax )+ {+ if( vec.is_magic() )+ {+ return DrawGpuZoneLevel<VectorAdapterDirect<GpuEvent>>( *(Vector<GpuEvent>*)&vec, hover, pxns, nspx, wpos, _offset, depth, thread, yMin, yMax, begin, drift );+ }+ else+ {+ return DrawGpuZoneLevel<VectorAdapterPointer<GpuEvent>>( vec, hover, pxns, nspx, wpos, _offset, depth, thread, yMin, yMax, begin, drift );+ }+ }+ else+ {+ if( vec.is_magic() )+ {+ return SkipGpuZoneLevel<VectorAdapterDirect<GpuEvent>>( *(Vector<GpuEvent>*)&vec, hover, pxns, nspx, wpos, _offset, depth, thread, yMin, yMax, begin, drift );+ }+ else+ {+ return SkipGpuZoneLevel<VectorAdapterPointer<GpuEvent>>( vec, hover, pxns, nspx, wpos, _offset, depth, thread, yMin, yMax, begin, drift );+ }+ }+}++template<typename Adapter, typename V>+int View::DrawGpuZoneLevel( const V& vec, bool hover, double pxns, int64_t nspx, const ImVec2& wpos, int _offset, int depth, uint64_t thread, float yMin, float yMax, int64_t begin, int drift )+{+ // cast to uint64_t, so that unended zones (end = -1) are still drawn+ auto it = std::lower_bound( vec.begin(), vec.end(), std::max<int64_t>( 0, m_vd.zvStart ), [begin, drift] ( const auto& l, const auto& r ) { Adapter a; return (uint64_t)AdjustGpuTime( a(l).GpuEnd(), begin, drift ) < (uint64_t)r; } );+ if( it == vec.end() ) return depth;++ Adapter a;++ const auto zitend = std::lower_bound( it, vec.end(), std::max<int64_t>( 0, m_vd.zvEnd ), [begin, drift] ( const auto& l, const auto& r ) { Adapter a; return (uint64_t)AdjustGpuTime( a(l).GpuStart(), begin, drift ) < (uint64_t)r; } );+ if( it == zitend ) return depth;+ if( AdjustGpuTime( a(*(zitend-1)).GpuEnd(), begin, drift ) < m_vd.zvStart ) return depth;++ const auto w = ImGui::GetContentRegionAvail().x - 1;+ const auto ty = ImGui::GetTextLineHeight();+ const auto ostep = ty + 1;+ const auto offset = _offset + ostep * depth;+ auto draw = ImGui::GetWindowDrawList();+ const auto dpos = wpos + ImVec2( 0.5f, 0.5f );++ depth++;+ int maxdepth = depth;++ while( it < zitend )+ {+ auto& ev = a(*it);+ auto end = m_worker.GetZoneEnd( ev );+ if( end == std::numeric_limits<int64_t>::max() ) break;+ const auto start = AdjustGpuTime( ev.GpuStart(), begin, drift );+ end = AdjustGpuTime( end, begin, drift );+ const auto zsz = std::max( ( end - start ) * pxns, pxns * 0.5 );+ if( zsz < MinVisSize )+ {+ const auto color = GetZoneColor( ev );+ const auto MinVisNs = MinVisSize * nspx;+ int num = 0;+ const auto px0 = ( start - m_vd.zvStart ) * pxns;+ auto px1ns = end - m_vd.zvStart;+ auto rend = end;+ auto nextTime = end + MinVisNs;+ for(;;)+ {+ const auto prevIt = it;+ it = std::lower_bound( it, zitend, std::max<int64_t>( 0, nextTime ), [begin, drift] ( const auto& l, const auto& r ) { Adapter a; return (uint64_t)AdjustGpuTime( a(l).GpuEnd(), begin, drift ) < (uint64_t)r; } );+ if( it == prevIt ) ++it;+ num += std::distance( prevIt, it );+ if( it == zitend ) break;+ const auto nend = AdjustGpuTime( m_worker.GetZoneEnd( a(*it) ), begin, drift );+ const auto nsnext = nend - m_vd.zvStart;+ if( nsnext < 0 || nsnext - px1ns >= MinVisNs * 2 ) break;+ px1ns = nsnext;+ rend = nend;+ nextTime = nend + nspx;+ }+ const auto px1 = px1ns * pxns;+ draw->AddRectFilled( wpos + ImVec2( std::max( px0, -10.0 ), offset ), wpos + ImVec2( std::min( std::max( px1, px0+MinVisSize ), double( w + 10 ) ), offset + ty ), color );+ DrawZigZag( draw, wpos + ImVec2( 0, offset + ty/2 ), std::max( px0, -10.0 ), std::min( std::max( px1, px0+MinVisSize ), double( w + 10 ) ), ty/4, DarkenColor( color ) );+ if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( std::max( px0, -10.0 ), offset ), wpos + ImVec2( std::min( std::max( px1, px0+MinVisSize ), double( w + 10 ) ), offset + ty + 1 ) ) )+ {+ if( num > 1 )+ {+ ImGui::BeginTooltip();+ TextFocused( "Zones too small to display:", RealToString( num ) );+ ImGui::Separator();+ TextFocused( "Execution time:", TimeToString( rend - start ) );+ ImGui::EndTooltip();++ if( IsMouseClicked( 2 ) && rend - start > 0 )+ {+ ZoomToRange( start, rend );+ }+ }+ else+ {+ const auto zoneThread = thread != 0 ? thread : m_worker.DecompressThread( ev.Thread() );+ ZoneTooltip( ev );++ if( IsMouseClicked( 2 ) && rend - start > 0 )+ {+ ZoomToZone( ev );+ }+ if( IsMouseClicked( 0 ) )+ {+ ShowZoneInfo( ev, zoneThread );+ }++ m_gpuThread = zoneThread;+ m_gpuStart = ev.CpuStart();+ m_gpuEnd = ev.CpuEnd();+ }+ }+ const auto tmp = RealToString( num );+ const auto tsz = ImGui::CalcTextSize( tmp );+ if( tsz.x < px1 - px0 )+ {+ const auto x = px0 + ( px1 - px0 - tsz.x ) / 2;+ DrawTextContrast( draw, wpos + ImVec2( x, offset ), 0xFF4488DD, tmp );+ }+ }+ else+ {+ if( ev.Child() >= 0 )+ {+ const auto d = DispatchGpuZoneLevel( m_worker.GetGpuChildren( ev.Child() ), hover, pxns, nspx, wpos, _offset, depth, thread, yMin, yMax, begin, drift );+ if( d > maxdepth ) maxdepth = d;+ }++ const char* zoneName = m_worker.GetZoneName( ev );+ auto tsz = ImGui::CalcTextSize( zoneName );++ const auto pr0 = ( start - m_vd.zvStart ) * pxns;+ const auto pr1 = ( end - m_vd.zvStart ) * pxns;+ const auto px0 = std::max( pr0, -10.0 );+ const auto px1 = std::max( { std::min( pr1, double( w + 10 ) ), px0 + pxns * 0.5, px0 + MinVisSize } );+ const auto zoneColor = GetZoneColorData( ev );+ draw->AddRectFilled( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + tsz.y ), zoneColor.color );+ if( zoneColor.highlight )+ {+ if( zoneColor.thickness > 1.f )+ {+ draw->AddRect( wpos + ImVec2( px0 + 1, offset + 1 ), wpos + ImVec2( px1 - 1, offset + tsz.y - 1 ), zoneColor.accentColor, 0.f, -1, zoneColor.thickness );+ }+ else+ {+ draw->AddRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + tsz.y ), zoneColor.accentColor, 0.f, -1, zoneColor.thickness );+ }+ }+ else+ {+ const auto darkColor = DarkenColor( zoneColor.color );+ DrawLine( draw, dpos + ImVec2( px0, offset + tsz.y ), dpos + ImVec2( px0, offset ), dpos + ImVec2( px1-1, offset ), zoneColor.accentColor, zoneColor.thickness );+ DrawLine( draw, dpos + ImVec2( px0, offset + tsz.y ), dpos + ImVec2( px1-1, offset + tsz.y ), dpos + ImVec2( px1-1, offset ), darkColor, zoneColor.thickness );+ }+ if( tsz.x < zsz )+ {+ const auto x = ( start - m_vd.zvStart ) * pxns + ( ( end - start ) * pxns - tsz.x ) / 2;+ if( x < 0 || x > w - tsz.x )+ {+ ImGui::PushClipRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + tsz.y * 2 ), true );+ DrawTextContrast( draw, wpos + ImVec2( std::max( std::max( 0., px0 ), std::min( double( w - tsz.x ), x ) ), offset ), 0xFFFFFFFF, zoneName );+ ImGui::PopClipRect();+ }+ else if( ev.GpuStart() == ev.GpuEnd() )+ {+ DrawTextContrast( draw, wpos + ImVec2( px0 + ( px1 - px0 - tsz.x ) * 0.5, offset ), 0xFFFFFFFF, zoneName );+ }+ else+ {+ DrawTextContrast( draw, wpos + ImVec2( x, offset ), 0xFFFFFFFF, zoneName );+ }+ }+ else+ {+ ImGui::PushClipRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + tsz.y * 2 ), true );+ DrawTextContrast( draw, wpos + ImVec2( ( start - m_vd.zvStart ) * pxns, offset ), 0xFFFFFFFF, zoneName );+ ImGui::PopClipRect();+ }++ if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + tsz.y + 1 ) ) )+ {+ const auto zoneThread = thread != 0 ? thread : m_worker.DecompressThread( ev.Thread() );+ ZoneTooltip( ev );++ if( !m_zoomAnim.active && IsMouseClicked( 2 ) )+ {+ ZoomToZone( ev );+ }+ if( IsMouseClicked( 0 ) )+ {+ ShowZoneInfo( ev, zoneThread );+ }++ m_gpuThread = zoneThread;+ m_gpuStart = ev.CpuStart();+ m_gpuEnd = ev.CpuEnd();+ }++ ++it;+ }+ }+ return maxdepth;+}++template<typename Adapter, typename V>+int View::SkipGpuZoneLevel( const V& vec, bool hover, double pxns, int64_t nspx, const ImVec2& wpos, int _offset, int depth, uint64_t thread, float yMin, float yMax, int64_t begin, int drift )+{+ // cast to uint64_t, so that unended zones (end = -1) are still drawn+ auto it = std::lower_bound( vec.begin(), vec.end(), std::max<int64_t>( 0, m_vd.zvStart ), [begin, drift] ( const auto& l, const auto& r ) { Adapter a; return (uint64_t)AdjustGpuTime( a(l).GpuEnd(), begin, drift ) < (uint64_t)r; } );+ if( it == vec.end() ) return depth;++ Adapter a;++ const auto zitend = std::lower_bound( it, vec.end(), std::max<int64_t>( 0, m_vd.zvEnd ), [begin, drift] ( const auto& l, const auto& r ) { Adapter a; return (uint64_t)AdjustGpuTime( a(l).GpuStart(), begin, drift ) < (uint64_t)r; } );+ if( it == zitend ) return depth;+ if( AdjustGpuTime( a(*(zitend-1)).GpuEnd(), begin, drift ) < m_vd.zvStart ) return depth;++ depth++;+ int maxdepth = depth;++ while( it < zitend )+ {+ auto& ev = a(*it);+ auto end = m_worker.GetZoneEnd( ev );+ if( end == std::numeric_limits<int64_t>::max() ) break;+ const auto start = AdjustGpuTime( ev.GpuStart(), begin, drift );+ end = AdjustGpuTime( end, begin, drift );+ const auto zsz = std::max( ( end - start ) * pxns, pxns * 0.5 );+ if( zsz < MinVisSize )+ {+ const auto MinVisNs = MinVisSize * nspx;+ auto px1ns = end - m_vd.zvStart;+ auto nextTime = end + MinVisNs;+ for(;;)+ {+ const auto prevIt = it;+ it = std::lower_bound( it, zitend, nextTime, [begin, drift] ( const auto& l, const auto& r ) { Adapter a; return (uint64_t)AdjustGpuTime( a(l).GpuEnd(), begin, drift ) < (uint64_t)r; } );+ if( it == prevIt ) ++it;+ if( it == zitend ) break;+ const auto nend = AdjustGpuTime( m_worker.GetZoneEnd( a(*it) ), begin, drift );+ const auto nsnext = nend - m_vd.zvStart;+ if( nsnext - px1ns >= MinVisNs * 2 ) break;+ px1ns = nsnext;+ nextTime = nend + nspx;+ }+ }+ else+ {+ if( ev.Child() >= 0 )+ {+ const auto d = DispatchGpuZoneLevel( m_worker.GetGpuChildren( ev.Child() ), hover, pxns, nspx, wpos, _offset, depth, thread, yMin, yMax, begin, drift );+ if( d > maxdepth ) maxdepth = d;+ }+ ++it;+ }+ }+ return maxdepth;+}++}
+ cbits/tracy/profiler/src/profiler/TracyView_Locks.cpp view
@@ -0,0 +1,660 @@+#include <inttypes.h>++#include "TracyColor.hpp"+#include "TracyFilesystem.hpp"+#include "TracyImGui.hpp"+#include "TracyLockHelpers.hpp"+#include "TracyMouse.hpp"+#include "TracyPrint.hpp"+#include "TracyTimelineContext.hpp"+#include "TracyTimelineDraw.hpp"+#include "TracyView.hpp"++namespace tracy+{++constexpr float MinVisSize = 3;++void View::DrawLockHeader( uint32_t id, const LockMap& lockmap, const SourceLocation& srcloc, bool hover, ImDrawList* draw, const ImVec2& wpos, float w, float ty, float offset, uint8_t tid )+{+ char buf[1024];+ if( lockmap.customName.Active() )+ {+ sprintf( buf, "%" PRIu32 ": %s", id, m_worker.GetString( lockmap.customName ) );+ }+ else+ {+ sprintf( buf, "%" PRIu32 ": %s", id, m_worker.GetString( srcloc.function ) );+ }+ ImGui::PushFont( m_smallFont );+ DrawTextContrast( draw, wpos + ImVec2( 0, offset ), 0xFF8888FF, buf );+ ImGui::PopFont();+ if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( 0, offset ), wpos + ImVec2( w, offset + ty + 1 ) ) )+ {+ m_lockHoverHighlight = id;++ if( ImGui::IsMouseHoveringRect( wpos + ImVec2( 0, offset ), wpos + ImVec2( ty + ImGui::CalcTextSize( buf ).x, offset + ty + 1 ) ) )+ {+ const auto& range = lockmap.range[tid];+ const auto activity = range.end - range.start;+ const auto traceLen = m_worker.GetLastTime();++ int64_t timeAnnounce = lockmap.timeAnnounce;+ int64_t timeTerminate = lockmap.timeTerminate;+ if( !lockmap.timeline.empty() )+ {+ if( timeAnnounce <= 0 )+ {+ timeAnnounce = lockmap.timeline.front().ptr->Time();+ }+ if( timeTerminate <= 0 )+ {+ timeTerminate = lockmap.timeline.back().ptr->Time();+ }+ }+ const auto lockLen = timeTerminate - timeAnnounce;++ ImGui::BeginTooltip();+ switch( lockmap.type )+ {+ case LockType::Lockable:+ TextFocused( "Type:", "lockable" );+ break;+ case LockType::SharedLockable:+ TextFocused( "Type:", "shared lockable" );+ break;+ default:+ assert( false );+ break;+ }+ ImGui::TextUnformatted( LocationToString( m_worker.GetString( srcloc.file ), srcloc.line ) );+ ImGui::Separator();+ TextFocused( ICON_FA_SHUFFLE " Appeared at", TimeToString( range.start ) );+ TextFocused( ICON_FA_SHUFFLE " Last event at", TimeToString( range.end ) );+ TextFocused( ICON_FA_SHUFFLE " Activity time:", TimeToString( activity ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%.2f%% of lock lifetime)", activity / double( lockLen ) * 100 );+ ImGui::Separator();+ TextFocused( "Announce time:", TimeToString( timeAnnounce ) );+ TextFocused( "Terminate time:", TimeToString( timeTerminate ) );+ TextFocused( "Lifetime:", TimeToString( lockLen ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%.2f%% of trace time)", lockLen / double( traceLen ) * 100 );+ ImGui::Separator();+ TextDisabledUnformatted( "Thread list:" );+ ImGui::Indent( ty );+ for( const auto& t : lockmap.threadList )+ {+ SmallColorBox( GetThreadColor( t, 0 ) );+ ImGui::SameLine();+ ImGui::TextUnformatted( m_worker.GetThreadName( t ) );+ }+ ImGui::Unindent( ty );+ ImGui::Separator();+ TextFocused( "Lock events:", RealToString( lockmap.timeline.size() ) );+ ImGui::EndTooltip();++ if( IsMouseClicked( 0 ) )+ {+ m_lockInfoWindow = id;+ }+ if( IsMouseClicked( 2 ) )+ {+ ZoomToRange( range.start, range.end );+ }+ }+ }+}++int View::DrawLocks( const TimelineContext& ctx, const std::vector<std::unique_ptr<LockDraw>>& lockDraw, uint64_t tid, int _offset, LockHighlight& highlight )+{+ const auto w = ctx.w;+ const auto ty = ctx.sty;+ const auto ostep = ty + 1;+ const auto& wpos = ctx.wpos;+ const auto hover = ctx.hover;+ const auto vStart = ctx.vStart;+ const auto pxns = ctx.pxns;++ auto draw = ImGui::GetWindowDrawList();++ const auto ty025 = round( ty * 0.25f );+ const auto ty05 = round( ty * 0.5f );++ const auto& lockMapData = m_worker.GetLockMap();+ const auto MinVisPx = GetScale() * MinVisSize;++ int cnt = 0;+ for( auto& _lock : lockDraw )+ {+ const auto& lock = *_lock;+ if( lock.data.empty() && !lock.forceDraw ) continue;++ auto it = lockMapData.find( lock.id );+ assert( it != lockMapData.end() );+ const auto& lockmap = *it->second;++ const auto& srcloc = m_worker.GetSourceLocation( lockmap.srcloc );+ const auto offset = _offset + ostep * cnt;+ if( lock.data.empty() )+ {+ draw->AddRectFilled( wpos + ImVec2( 0, offset ), wpos + ImVec2( w, offset + ty ), 0x2288DD88 );+ draw->AddRect( wpos + ImVec2( 0, offset ), wpos + ImVec2( w, offset + ty ), 0x4488DD88 );+ DrawLockHeader( lock.id, lockmap, srcloc, hover, draw, wpos, w, ty, offset, lock.thread );+ cnt++;+ continue;+ }++ for( auto& v : lock.data )+ {+ const auto& le = *v.ptr;+ const auto t0 = le.ptr->Time();+ const auto t1 = v.t1.Val();+ const auto px0 = ( t0 - vStart ) * pxns;+ // The usual method of collapsing single small zones into zig-zags would be very bad here. Lock wait zones should+ // be easily visible without having to zoom in first. This sets a minimum width for any lock zone.+ const auto px1 = std::max( ( t1 - vStart ) * pxns, px0 + MinVisPx );++ bool itemHovered = hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + ostep ) );+ if( itemHovered )+ {+ if( IsMouseClicked( 0 ) )+ {+ m_lockInfoWindow = lock.id;+ }+ if( IsMouseClicked( 2 ) )+ {+ ZoomToRange( t0, t1 );+ }++ if( v.condensed > 1 )+ {+ ImGui::BeginTooltip();+ TextFocused( "Multiple lock events:", RealToString( v.condensed ) );+ ImGui::EndTooltip();+ }+ else+ {+ highlight.blocked = v.state == LockState::HasBlockingLock;+ if( !highlight.blocked )+ {+ highlight.id = lock.id;+ highlight.begin = t0;+ highlight.end = t1;+ highlight.thread = lock.thread;+ highlight.blocked = false;+ }+ else+ {+ const auto& tl = lockmap.timeline;+ auto b = v.ptr.get();+ while( b != tl.begin() )+ {+ if( b->lockingThread != v.ptr->lockingThread )+ {+ break;+ }+ b--;+ }+ b++;+ highlight.begin = b->ptr->Time();++ auto e = v.next.get();+ while( e != tl.end() )+ {+ if( e->lockingThread != v.next->lockingThread )+ {+ highlight.id = lock.id;+ highlight.end = e->ptr->Time();+ highlight.thread = lock.thread;+ break;+ }+ e++;+ }+ }++ ImGui::BeginTooltip();+ if( lockmap.customName.Active() )+ {+ ImGui::Text( "Lock #%" PRIu32 ": %s", lock.id, m_worker.GetString( lockmap.customName ) );+ }+ else+ {+ ImGui::Text( "Lock #%" PRIu32 ": %s", lock.id, m_worker.GetString( srcloc.function ) );+ }+ ImGui::Separator();+ ImGui::TextUnformatted( LocationToString( m_worker.GetString( srcloc.file ), srcloc.line ) );+ TextFocused( "Time:", TimeToString( t1 - t0 ) );+ ImGui::Separator();++ const auto threadBit = GetThreadBit( lock.thread );+ int16_t markloc = 0;+ auto it = v.ptr.get();+ for(;;)+ {+ if( it->ptr->thread == lock.thread )+ {+ if( ( it->lockingThread == lock.thread || IsThreadWaiting( it->waitList, threadBit ) ) && it->ptr->SrcLoc() != 0 )+ {+ markloc = it->ptr->SrcLoc();+ break;+ }+ }+ if( it == lockmap.timeline.begin() ) break;+ --it;+ }+ if( markloc != 0 )+ {+ const auto& marklocdata = m_worker.GetSourceLocation( markloc );+ ImGui::TextUnformatted( "Lock event location:" );+ ImGui::TextUnformatted( m_worker.GetString( marklocdata.function ) );+ ImGui::TextUnformatted( LocationToString( m_worker.GetString( marklocdata.file ), marklocdata.line ) );+ ImGui::Separator();+ }++ if( lockmap.type == LockType::Lockable )+ {+ switch( v.state )+ {+ case LockState::HasLock:+ if( v.ptr->lockCount == 1 )+ {+ ImGui::Text( "Thread \"%s\" has lock. No other threads are waiting.", m_worker.GetThreadName( tid ) );+ }+ else+ {+ ImGui::Text( "Thread \"%s\" has %i locks. No other threads are waiting.", m_worker.GetThreadName( tid ), v.ptr->lockCount );+ }+ if( v.ptr->waitList != 0 )+ {+ assert( !AreOtherWaiting( v.next->waitList, threadBit ) );+ ImGui::TextUnformatted( "Recursive lock acquire in thread." );+ }+ break;+ case LockState::HasBlockingLock:+ {+ if( v.ptr->lockCount == 1 )+ {+ ImGui::Text( "Thread \"%s\" has lock. Blocked threads (%" PRIu64 "):", m_worker.GetThreadName( tid ), TracyCountBits( v.ptr->waitList ) );+ }+ else+ {+ ImGui::Text( "Thread \"%s\" has %i locks. Blocked threads (%" PRIu64 "):", m_worker.GetThreadName( tid ), v.ptr->lockCount, TracyCountBits( v.ptr->waitList ) );+ }+ auto waitList = v.ptr->waitList;+ int t = 0;+ ImGui::Indent( ty );+ while( waitList != 0 )+ {+ if( waitList & 0x1 )+ {+ ImGui::Text( "\"%s\"", m_worker.GetThreadName( lockmap.threadList[t] ) );+ }+ waitList >>= 1;+ t++;+ }+ ImGui::Unindent( ty );+ break;+ }+ case LockState::WaitLock:+ {+ if( v.ptr->lockCount > 0 )+ {+ ImGui::Text( "Thread \"%s\" is blocked by other thread:", m_worker.GetThreadName( tid ) );+ }+ else+ {+ ImGui::Text( "Thread \"%s\" waits to obtain lock after release by thread:", m_worker.GetThreadName( tid ) );+ }+ ImGui::Indent( ty );+ ImGui::Text( "\"%s\"", m_worker.GetThreadName( lockmap.threadList[v.ptr->lockingThread] ) );+ ImGui::Unindent( ty );+ break;+ }+ default:+ assert( false );+ break;+ }+ }+ else+ {+ const auto ptr = (const LockEventShared*)(const LockEvent*)v.ptr->ptr;+ switch( v.state )+ {+ case LockState::HasLock:+ assert( v.ptr->waitList == 0 );+ if( ptr->sharedList == 0 )+ {+ assert( v.ptr->lockCount == 1 );+ ImGui::Text( "Thread \"%s\" has lock. No other threads are waiting.", m_worker.GetThreadName( tid ) );+ }+ else if( TracyCountBits( ptr->sharedList ) == 1 )+ {+ ImGui::Text( "Thread \"%s\" has a sole shared lock. No other threads are waiting.", m_worker.GetThreadName( tid ) );+ }+ else+ {+ ImGui::Text( "Thread \"%s\" has shared lock. No other threads are waiting.", m_worker.GetThreadName( tid ) );+ ImGui::Text( "Threads sharing the lock (%" PRIu64 "):", TracyCountBits( ptr->sharedList ) - 1 );+ auto sharedList = ptr->sharedList;+ int t = 0;+ ImGui::Indent( ty );+ while( sharedList != 0 )+ {+ if( sharedList & 0x1 && t != lock.thread )+ {+ ImGui::Text( "\"%s\"", m_worker.GetThreadName( lockmap.threadList[t] ) );+ }+ sharedList >>= 1;+ t++;+ }+ ImGui::Unindent( ty );+ }+ break;+ case LockState::HasBlockingLock:+ {+ if( ptr->sharedList == 0 )+ {+ assert( v.ptr->lockCount == 1 );+ ImGui::Text( "Thread \"%s\" has lock. Blocked threads (%" PRIu64 "):", m_worker.GetThreadName( tid ), TracyCountBits( v.ptr->waitList ) + TracyCountBits( ptr->waitShared ) );+ }+ else if( TracyCountBits( ptr->sharedList ) == 1 )+ {+ ImGui::Text( "Thread \"%s\" has a sole shared lock. Blocked threads (%" PRIu64 "):", m_worker.GetThreadName( tid ), TracyCountBits( v.ptr->waitList ) + TracyCountBits( ptr->waitShared ) );+ }+ else+ {+ ImGui::Text( "Thread \"%s\" has shared lock.", m_worker.GetThreadName( tid ) );+ ImGui::Text( "Threads sharing the lock (%" PRIu64 "):", TracyCountBits( ptr->sharedList ) - 1 );+ auto sharedList = ptr->sharedList;+ int t = 0;+ ImGui::Indent( ty );+ while( sharedList != 0 )+ {+ if( sharedList & 0x1 && t != lock.thread )+ {+ ImGui::Text( "\"%s\"", m_worker.GetThreadName( lockmap.threadList[t] ) );+ }+ sharedList >>= 1;+ t++;+ }+ ImGui::Unindent( ty );+ ImGui::Text( "Blocked threads (%" PRIu64 "):", TracyCountBits( v.ptr->waitList ) + TracyCountBits( ptr->waitShared ) );+ }++ auto waitList = v.ptr->waitList;+ int t = 0;+ ImGui::Indent( ty );+ while( waitList != 0 )+ {+ if( waitList & 0x1 )+ {+ ImGui::Text( "\"%s\"", m_worker.GetThreadName( lockmap.threadList[t] ) );+ }+ waitList >>= 1;+ t++;+ }+ auto waitShared = ptr->waitShared;+ t = 0;+ while( waitShared != 0 )+ {+ if( waitShared & 0x1 )+ {+ ImGui::Text( "\"%s\"", m_worker.GetThreadName( lockmap.threadList[t] ) );+ }+ waitShared >>= 1;+ t++;+ }+ ImGui::Unindent( ty );+ break;+ }+ case LockState::WaitLock:+ {+ assert( v.ptr->lockCount == 0 || v.ptr->lockCount == 1 );+ if( v.ptr->lockCount != 0 || ptr->sharedList != 0 )+ {+ ImGui::Text( "Thread \"%s\" is blocked by other threads (%" PRIu64 "):", m_worker.GetThreadName( tid ), v.ptr->lockCount + TracyCountBits( ptr->sharedList ) );+ }+ else+ {+ ImGui::Text( "Thread \"%s\" waits to obtain lock after release by thread:", m_worker.GetThreadName( tid ) );+ }+ ImGui::Indent( ty );+ if( v.ptr->lockCount != 0 )+ {+ ImGui::Text( "\"%s\"", m_worker.GetThreadName( lockmap.threadList[v.ptr->lockingThread] ) );+ }+ auto sharedList = ptr->sharedList;+ int t = 0;+ while( sharedList != 0 )+ {+ if( sharedList & 0x1 )+ {+ ImGui::Text( "\"%s\"", m_worker.GetThreadName( lockmap.threadList[t] ) );+ }+ sharedList >>= 1;+ t++;+ }+ ImGui::Unindent( ty );+ break;+ }+ default:+ assert( false );+ break;+ }+ }+ ImGui::EndTooltip();+ }+ }++ const auto cfilled = v.state == LockState::HasLock ? 0xFF228A22 : ( v.state == LockState::HasBlockingLock ? 0xFF228A8A : 0xFF2222BD );+ draw->AddRectFilled( wpos + ImVec2( std::max( px0, -10.0 ), offset ), wpos + ImVec2( std::min( px1, double( w + 10 ) ), offset + ty ), cfilled );+ if( m_lockHighlight.thread != lock.thread && ( v.state == LockState::HasBlockingLock ) != m_lockHighlight.blocked && v.next != lockmap.timeline.end() && m_lockHighlight.id == int64_t( lock.id ) && m_lockHighlight.begin <= v.ptr->ptr->Time() && m_lockHighlight.end >= v.next->ptr->Time() )+ {+ const auto t = uint8_t( ( sin( std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::system_clock::now().time_since_epoch() ).count() * 0.01 ) * 0.5 + 0.5 ) * 255 );+ draw->AddRect( wpos + ImVec2( std::max( px0, -10.0 ), offset ), wpos + ImVec2( std::min( px1, double( w + 10 ) ), offset + ty ), 0x00FFFFFF | ( t << 24 ), 0.f, -1, 2.f );+ m_wasActive = true;+ }+ else if( v.condensed == 0 )+ {+ const auto coutline = v.state == LockState::HasLock ? 0xFF3BA33B : ( v.state == LockState::HasBlockingLock ? 0xFF3BA3A3 : 0xFF3B3BD6 );+ draw->AddRect( wpos + ImVec2( std::max( px0, -10.0 ), offset ), wpos + ImVec2( std::min( px1, double( w + 10 ) ), offset + ty ), coutline );+ }+ else if( v.condensed > 1 )+ {+ DrawZigZag( draw, wpos + ImVec2( 0, offset + ty05 ), px0, px1, ty025, DarkenColor( cfilled ) );+ }+ }++ if( m_lockInfoWindow == lock.id )+ {+ draw->AddRectFilled( wpos + ImVec2( 0, offset ), wpos + ImVec2( w, offset + ty ), 0x2288DD88 );+ draw->AddRect( wpos + ImVec2( 0, offset ), wpos + ImVec2( w, offset + ty ), 0x4488DD88 );+ }+ else if( m_lockHoverHighlight == lock.id )+ {+ draw->AddRectFilled( wpos + ImVec2( 0, offset ), wpos + ImVec2( w, offset + ty ), 0x228888DD );+ draw->AddRect( wpos + ImVec2( 0, offset ), wpos + ImVec2( w, offset + ty ), 0x448888DD );+ }+ DrawLockHeader( lock.id, lockmap, srcloc, hover, draw, wpos, w, ty, offset, lock.thread );++ cnt++;+ }++ return cnt;+}++void View::DrawLockInfoWindow()+{+ bool visible = true;+ ImGui::Begin( "Lock info", &visible, ImGuiWindowFlags_AlwaysAutoResize );+ if( !ImGui::GetCurrentWindowRead()->SkipItems )+ {+ auto it = m_worker.GetLockMap().find( m_lockInfoWindow );+ assert( it != m_worker.GetLockMap().end() );+ const auto& lock = *it->second;+ const auto& srcloc = m_worker.GetSourceLocation( lock.srcloc );+ auto fileName = m_worker.GetString( srcloc.file );++ int64_t timeAnnounce = lock.timeAnnounce;+ int64_t timeTerminate = lock.timeTerminate;+ if( !lock.timeline.empty() )+ {+ if( timeAnnounce <= 0 )+ {+ timeAnnounce = lock.timeline.front().ptr->Time();+ }+ if( timeTerminate <= 0 )+ {+ timeTerminate = lock.timeline.back().ptr->Time();+ }+ }++ bool waitState = false;+ bool holdState = false;+ int64_t waitStartTime = 0;+ int64_t holdStartTime = 0;+ int64_t waitTotalTime = 0;+ int64_t holdTotalTime = 0;+ uint32_t maxWaitingThreads = 0;+ for( auto& v : lock.timeline )+ {+ if( holdState )+ {+ if( v.lockCount == 0 )+ {+ holdTotalTime += v.ptr->Time() - holdStartTime;+ holdState = false;+ }+ }+ else+ {+ if( v.lockCount != 0 )+ {+ holdStartTime = v.ptr->Time();+ holdState = true;+ }+ }+ if( waitState )+ {+ if( v.waitList == 0 )+ {+ waitTotalTime += v.ptr->Time() - waitStartTime;+ waitState = false;+ }+ else+ {+ maxWaitingThreads = std::max<uint32_t>( maxWaitingThreads, TracyCountBits( v.waitList ) );+ }+ }+ else+ {+ if( v.waitList != 0 )+ {+ waitStartTime = v.ptr->Time();+ waitState = true;+ maxWaitingThreads = std::max<uint32_t>( maxWaitingThreads, TracyCountBits( v.waitList ) );+ }+ }+ }++ ImGui::PushFont( m_bigFont );+ if( lock.customName.Active() )+ {+ ImGui::Text( "Lock #%" PRIu32 ": %s", m_lockInfoWindow, m_worker.GetString( lock.customName ) );+ }+ else+ {+ ImGui::Text( "Lock #%" PRIu32 ": %s", m_lockInfoWindow, m_worker.GetString( srcloc.function ) );+ }+ ImGui::PopFont();+ if( lock.customName.Active() )+ {+ TextFocused( "Name:", m_worker.GetString( srcloc.function ) );+ }+ TextDisabledUnformatted( "Location:" );+ if( m_lockInfoAnim.Match( m_lockInfoWindow ) )+ {+ const auto time = m_lockInfoAnim.Time();+ const auto indentVal = sin( time * 60.f ) * 10.f * time;+ ImGui::SameLine( 0, ImGui::GetStyle().ItemSpacing.x + indentVal );+ }+ else+ {+ ImGui::SameLine();+ }+ ImGui::TextUnformatted( LocationToString( fileName, srcloc.line ) );+ if( ImGui::IsItemHovered() )+ {+ DrawSourceTooltip( fileName, srcloc.line );+ if( ImGui::IsItemClicked( 1 ) )+ {+ if( SourceFileValid( fileName, m_worker.GetCaptureTime(), *this, m_worker ) )+ {+ ViewSource( fileName, srcloc.line );+ }+ else+ {+ m_lockInfoAnim.Enable( m_lockInfoWindow, 0.5f );+ }+ }+ }+ ImGui::Separator();++ switch( lock.type )+ {+ case LockType::Lockable:+ TextFocused( "Type:", "lockable" );+ break;+ case LockType::SharedLockable:+ TextFocused( "Type:", "shared lockable" );+ break;+ default:+ assert( false );+ break;+ }+ TextFocused( "Lock events:", RealToString( lock.timeline.size() ) );+ ImGui::Separator();++ const auto announce = timeAnnounce;+ const auto terminate = timeTerminate;+ const auto lifetime = timeTerminate - timeAnnounce;+ const auto traceLen = m_worker.GetLastTime();++ TextFocused( "Announce time:", TimeToString( announce ) );+ TextFocused( "Terminate time:", TimeToString( terminate ) );+ TextFocused( "Lifetime:", TimeToString( lifetime ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%.2f%% of trace time)", lifetime / double( traceLen ) * 100 );+ ImGui::Separator();++ TextFocused( "Lock hold time:", TimeToString( holdTotalTime ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%.2f%% of lock lifetime)", holdTotalTime / float( lifetime ) * 100.f );+ TextFocused( "Lock wait time:", TimeToString( waitTotalTime ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%.2f%% of lock lifetime)", waitTotalTime / float( lifetime ) * 100.f );+ TextFocused( "Max waiting threads:", RealToString( maxWaitingThreads ) );+ ImGui::Separator();++ const auto threadList = ImGui::TreeNode( "Thread list" );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%zu)", lock.threadList.size() );+ if( threadList )+ {+ for( const auto& t : lock.threadList )+ {+ SmallColorBox( GetThreadColor( t, 0 ) );+ ImGui::SameLine();+ ImGui::TextUnformatted( m_worker.GetThreadName( t ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( t ) );+ }+ ImGui::TreePop();+ }+ }+ ImGui::End();+ if( !visible ) m_lockInfoWindow = InvalidId;+}++}
+ cbits/tracy/profiler/src/profiler/TracyView_Memory.cpp view
@@ -0,0 +1,931 @@+#include <inttypes.h>++#include "TracyImGui.hpp"+#include "TracyMouse.hpp"+#include "TracyPrint.hpp"+#include "TracyView.hpp"+#include "tracy_pdqsort.h"++namespace tracy+{++constexpr size_t ChunkBits = 10;+constexpr size_t PageBits = 10;+constexpr size_t PageSize = 1 << PageBits;+constexpr size_t PageChunkBits = ChunkBits + PageBits;+constexpr size_t PageChunkSize = 1 << PageChunkBits;++uint32_t MemDecayColor[256] = {+ 0x0, 0xFF077F07, 0xFF078007, 0xFF078207, 0xFF078307, 0xFF078507, 0xFF078707, 0xFF078807,+ 0xFF078A07, 0xFF078B07, 0xFF078D07, 0xFF078F07, 0xFF079007, 0xFF089208, 0xFF089308, 0xFF089508,+ 0xFF089708, 0xFF089808, 0xFF089A08, 0xFF089B08, 0xFF089D08, 0xFF089F08, 0xFF08A008, 0xFF08A208,+ 0xFF09A309, 0xFF09A509, 0xFF09A709, 0xFF09A809, 0xFF09AA09, 0xFF09AB09, 0xFF09AD09, 0xFF09AF09,+ 0xFF09B009, 0xFF09B209, 0xFF09B309, 0xFF09B509, 0xFF0AB70A, 0xFF0AB80A, 0xFF0ABA0A, 0xFF0ABB0A,+ 0xFF0ABD0A, 0xFF0ABF0A, 0xFF0AC00A, 0xFF0AC20A, 0xFF0AC30A, 0xFF0AC50A, 0xFF0AC70A, 0xFF0BC80B,+ 0xFF0BCA0B, 0xFF0BCB0B, 0xFF0BCD0B, 0xFF0BCF0B, 0xFF0BD00B, 0xFF0BD20B, 0xFF0BD30B, 0xFF0BD50B,+ 0xFF0BD70B, 0xFF0BD80B, 0xFF0BDA0B, 0xFF0CDB0C, 0xFF0CDD0C, 0xFF0CDF0C, 0xFF0CE00C, 0xFF0CE20C,+ 0xFF0CE30C, 0xFF0CE50C, 0xFF0CE70C, 0xFF0CE80C, 0xFF0CEA0C, 0xFF0CEB0C, 0xFF0DED0D, 0xFF0DEF0D,+ 0xFF0DF00D, 0xFF0DF20D, 0xFF0DF30D, 0xFF0DF50D, 0xFF0DF70D, 0xFF0DF80D, 0xFF0DFA0D, 0xFF0DFB0D,+ 0xFF0DFD0D, 0xFF0EFF0E, 0xFF0EFF0E, 0xFF0EFF0E, 0xFF0EFF0E, 0xFF0EFF0E, 0xFF0EFF0E, 0xFF0EFF0E,+ 0xFF0EFF0E, 0xFF0EFF0E, 0xFF0EFF0E, 0xFF0EFF0E, 0xFF0EFF0E, 0xFF0FFF0F, 0xFF0FFF0F, 0xFF0FFF0F,+ 0xFF0FFF0F, 0xFF0FFF0F, 0xFF0FFF0F, 0xFF0FFF0F, 0xFF0FFF0F, 0xFF0FFF0F, 0xFF0FFF0F, 0xFF0FFF0F,+ 0xFF10FF10, 0xFF10FF10, 0xFF10FF10, 0xFF10FF10, 0xFF10FF10, 0xFF10FF10, 0xFF10FF10, 0xFF10FF10,+ 0xFF10FF10, 0xFF10FF10, 0xFF10FF10, 0xFF10FF10, 0xFF11FF11, 0xFF11FF11, 0xFF11FF11, 0xFF11FF11,+ 0xFF11FF11, 0xFF11FF11, 0xFF11FF11, 0xFF11FF11, 0xFF11FF11, 0xFF11FF11, 0xFF11FF11, 0xFF12FF12,+ 0x0, 0xFF1212FF, 0xFF1111FF, 0xFF1111FF, 0xFF1111FF, 0xFF1111FF, 0xFF1111FF, 0xFF1111FF,+ 0xFF1111FF, 0xFF1111FF, 0xFF1111FF, 0xFF1111FF, 0xFF1111FF, 0xFF1010FF, 0xFF1010FF, 0xFF1010FF,+ 0xFF1010FF, 0xFF1010FF, 0xFF1010FF, 0xFF1010FF, 0xFF1010FF, 0xFF1010FF, 0xFF1010FF, 0xFF1010FF,+ 0xFF1010FF, 0xFF0F0FFF, 0xFF0F0FFF, 0xFF0F0FFF, 0xFF0F0FFF, 0xFF0F0FFF, 0xFF0F0FFF, 0xFF0F0FFF,+ 0xFF0F0FFF, 0xFF0F0FFF, 0xFF0F0FFF, 0xFF0F0FFF, 0xFF0E0EFF, 0xFF0E0EFF, 0xFF0E0EFF, 0xFF0E0EFF,+ 0xFF0E0EFF, 0xFF0E0EFF, 0xFF0E0EFF, 0xFF0E0EFF, 0xFF0E0EFF, 0xFF0E0EFF, 0xFF0E0EFF, 0xFF0E0EFF,+ 0xFF0D0DFD, 0xFF0D0DFB, 0xFF0D0DFA, 0xFF0D0DF8, 0xFF0D0DF7, 0xFF0D0DF5, 0xFF0D0DF3, 0xFF0D0DF2,+ 0xFF0D0DF0, 0xFF0D0DEF, 0xFF0D0DED, 0xFF0C0CEB, 0xFF0C0CEA, 0xFF0C0CE8, 0xFF0C0CE7, 0xFF0C0CE5,+ 0xFF0C0CE3, 0xFF0C0CE2, 0xFF0C0CE0, 0xFF0C0CDF, 0xFF0C0CDD, 0xFF0C0CDB, 0xFF0B0BDA, 0xFF0B0BD8,+ 0xFF0B0BD7, 0xFF0B0BD5, 0xFF0B0BD3, 0xFF0B0BD2, 0xFF0B0BD0, 0xFF0B0BCF, 0xFF0B0BCD, 0xFF0B0BCB,+ 0xFF0B0BCA, 0xFF0B0BC8, 0xFF0A0AC7, 0xFF0A0AC5, 0xFF0A0AC3, 0xFF0A0AC2, 0xFF0A0AC0, 0xFF0A0ABF,+ 0xFF0A0ABD, 0xFF0A0ABB, 0xFF0A0ABA, 0xFF0A0AB8, 0xFF0A0AB7, 0xFF0909B5, 0xFF0909B3, 0xFF0909B2,+ 0xFF0909B0, 0xFF0909AF, 0xFF0909AD, 0xFF0909AB, 0xFF0909AA, 0xFF0909A8, 0xFF0909A7, 0xFF0909A5,+ 0xFF0909A3, 0xFF0808A2, 0xFF0808A0, 0xFF08089F, 0xFF08089D, 0xFF08089B, 0xFF08089A, 0xFF080898,+ 0xFF080897, 0xFF080895, 0xFF080893, 0xFF080892, 0xFF070790, 0xFF07078F, 0xFF07078D, 0xFF07078B,+ 0xFF07078A, 0xFF070788, 0xFF070787, 0xFF070785, 0xFF070783, 0xFF070782, 0xFF070780, 0xFF07077F,+};++struct MemoryPage+{+ uint64_t page;+ int8_t data[PageSize];+};++static tracy_force_inline MemoryPage& GetPage( unordered_flat_map<uint64_t, MemoryPage>& memmap, uint64_t page )+{+ auto it = memmap.find( page );+ if( it == memmap.end() )+ {+ it = memmap.emplace( page, MemoryPage { page, {} } ).first;+ }+ return it->second;+}++static tracy_force_inline void FillPages( unordered_flat_map<uint64_t, MemoryPage>& memmap, uint64_t c0, uint64_t c1, int8_t val )+{+ auto p0 = c0 >> PageBits;+ const auto p1 = c1 >> PageBits;++ if( p0 == p1 )+ {+ const auto a0 = c0 & ( PageSize - 1 );+ const auto a1 = c1 & ( PageSize - 1 );++ auto& page = GetPage( memmap, p0 );+ if( a0 == a1 )+ {+ page.data[a0] = val;+ }+ else+ {+ memset( page.data + a0, val, a1 - a0 + 1 );+ }+ }+ else+ {+ {+ const auto a0 = c0 & ( PageSize - 1 );+ auto& page = GetPage( memmap, p0 );+ memset( page.data + a0, val, PageSize - a0 );+ }+ while( ++p0 < p1 )+ {+ auto& page = GetPage( memmap, p0 );+ memset( page.data, val, PageSize );+ }+ {+ const auto a1 = c1 & ( PageSize - 1 );+ auto& page = GetPage( memmap, p1 );+ memset( page.data, val, a1 + 1 );+ }+ }+}++std::vector<MemoryPage> View::GetMemoryPages() const+{+ std::vector<MemoryPage> ret;++ static unordered_flat_map<uint64_t, MemoryPage> memmap;++ const auto& mem = m_worker.GetMemoryNamed( m_memInfo.pool );+ const auto memlow = mem.low;++ if( m_memInfo.range.active )+ {+ auto it = std::lower_bound( mem.data.begin(), mem.data.end(), m_memInfo.range.min, []( const auto& lhs, const auto& rhs ) { return lhs.TimeAlloc() < rhs; } );+ if( it != mem.data.end() )+ {+ auto end = std::lower_bound( mem.data.begin(), mem.data.end(), m_memInfo.range.max, []( const auto& lhs, const auto& rhs ) { return lhs.TimeAlloc() < rhs; } );+ while( it != end )+ {+ auto& alloc = *it++;++ const auto a0 = alloc.Ptr() - memlow;+ const auto a1 = a0 + alloc.Size();+ int8_t val = alloc.TimeFree() < 0 ?+ int8_t( std::max( int64_t( 1 ), 127 - ( ( m_memInfo.range.max - alloc.TimeAlloc() ) >> 24 ) ) ) :+ ( alloc.TimeFree() > m_memInfo.range.max ?+ int8_t( std::max( int64_t( 1 ), 127 - ( ( m_memInfo.range.max - alloc.TimeAlloc() ) >> 24 ) ) ) :+ int8_t( -std::max( int64_t( 1 ), 127 - ( ( m_memInfo.range.max - alloc.TimeFree() ) >> 24 ) ) ) );++ const auto c0 = a0 >> ChunkBits;+ const auto c1 = a1 >> ChunkBits;++ FillPages( memmap, c0, c1, val );+ }+ }+ }+ else+ {+ const auto lastTime = m_worker.GetLastTime();+ for( auto& alloc : mem.data )+ {+ const auto a0 = alloc.Ptr() - memlow;+ const auto a1 = a0 + alloc.Size();+ const int8_t val = alloc.TimeFree() < 0 ?+ int8_t( std::max( int64_t( 1 ), 127 - ( ( lastTime - std::min( lastTime, alloc.TimeAlloc() ) ) >> 24 ) ) ) :+ int8_t( -std::max( int64_t( 1 ), 127 - ( ( lastTime - std::min( lastTime, alloc.TimeFree() ) ) >> 24 ) ) );++ const auto c0 = a0 >> ChunkBits;+ const auto c1 = a1 >> ChunkBits;++ FillPages( memmap, c0, c1, val );+ }+ }++ std::vector<unordered_flat_map<uint64_t, MemoryPage>::const_iterator> itmap;+ itmap.reserve( memmap.size() );+ ret.reserve( memmap.size() );+ for( auto it = memmap.begin(); it != memmap.end(); ++it ) itmap.emplace_back( it );+ pdqsort_branchless( itmap.begin(), itmap.end(), []( const auto& lhs, const auto& rhs ) { return lhs->second.page < rhs->second.page; } );+ for( auto& v : itmap ) ret.emplace_back( v->second );++ memmap.clear();+ return ret;+}++void View::DrawMemory()+{+ const auto scale = GetScale();+ ImGui::SetNextWindowSize( ImVec2( 1100 * scale, 500 * scale ), ImGuiCond_FirstUseEver );+ ImGui::Begin( "Memory", &m_memInfo.show, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse );+ if( ImGui::GetCurrentWindowRead()->SkipItems ) { ImGui::End(); return; }++ auto& memNameMap = m_worker.GetMemNameMap();+ if( memNameMap.size() > 1 )+ {+ TextDisabledUnformatted( ICON_FA_BOX_ARCHIVE " Memory pool:" );+ ImGui::SameLine();+ if( ImGui::BeginCombo( "##memoryPool", m_memInfo.pool == 0 ? "Default allocator" : m_worker.GetString( m_memInfo.pool ) ) )+ {+ for( auto& v : memNameMap )+ {+ if( ImGui::Selectable( v.first == 0 ? "Default allocator" : m_worker.GetString( v.first ) ) )+ {+ m_memInfo.pool = v.first;+ m_memInfo.showAllocList = false;+ }+ }+ ImGui::EndCombo();+ }+ ImGui::Separator();+ }++ auto& mem = m_worker.GetMemoryNamed( m_memInfo.pool );+ if( mem.data.empty() )+ {+ const auto ty = ImGui::GetTextLineHeight();+ ImGui::PushFont( m_bigFont );+ ImGui::Dummy( ImVec2( 0, ( ImGui::GetContentRegionAvail().y - ImGui::GetTextLineHeight() * 2 ) * 0.5f ) );+ TextCentered( ICON_FA_DOG );+ TextCentered( "No memory data collected" );+ ImGui::PopFont();+ ImGui::End();+ return;+ }++ TextDisabledUnformatted( "Total allocations:" );+ ImGui::SameLine();+ ImGui::Text( "%-15s", RealToString( mem.data.size() ) );+ ImGui::SameLine();+ TextDisabledUnformatted( "Active allocations:" );+ ImGui::SameLine();+ ImGui::Text( "%-15s", RealToString( mem.active.size() ) );+ ImGui::SameLine();+ TextDisabledUnformatted( "Memory usage:" );+ ImGui::SameLine();+ ImGui::Text( "%-15s", MemSizeToString( mem.usage ) );+ ImGui::SameLine();+ TextFocused( "Memory span:", MemSizeToString( mem.high - mem.low ) );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ DrawHelpMarker(+ "Click on address to display memory allocation info window. Middle click to zoom to allocation range.\n"+ "Active allocations are displayed using green color.\n"+ "A single thread is displayed if alloc and free was performed on the same thread. Otherwise two threads are displayed in order: alloc, free.\n"+ "If alloc and free is performed in the same zone, the free zone is displayed in yellow color." );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::SeparatorEx( ImGuiSeparatorFlags_Vertical );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 2, 2 ) );+ if( ImGui::Checkbox( "Limit range", &m_memInfo.range.active ) )+ {+ if( m_memInfo.range.active && m_memInfo.range.min == 0 && m_memInfo.range.max == 0 )+ {+ m_memInfo.range.min = m_vd.zvStart;+ m_memInfo.range.max = m_vd.zvEnd;+ }+ }+ if( m_memInfo.range.active )+ {+ ImGui::SameLine();+ TextColoredUnformatted( 0xFF00FFFF, ICON_FA_TRIANGLE_EXCLAMATION );+ ImGui::SameLine();+ ToggleButton( ICON_FA_RULER " Limits", m_showRanges );+ }+ ImGui::PopStyleVar();++ ImGui::Separator();+ ImGui::BeginChild( "##memory" );+ if( ImGui::TreeNode( ICON_FA_AT " Allocations" ) )+ {+ bool findClicked = ImGui::InputTextWithHint( "###address", "Enter memory address to search for", m_memInfo.pattern, 1024, ImGuiInputTextFlags_EnterReturnsTrue );+ ImGui::SameLine();+ findClicked |= ImGui::Button( ICON_FA_MAGNIFYING_GLASS " Find" );+ if( findClicked )+ {+ m_memInfo.ptrFind = strtoull( m_memInfo.pattern, nullptr, 0 );+ }+ ImGui::SameLine();+ if( ImGui::Button( ICON_FA_DELETE_LEFT " Clear" ) )+ {+ m_memInfo.ptrFind = 0;+ m_memInfo.pattern[0] = '\0';+ }++ if( m_memInfo.ptrFind != 0 )+ {+ std::vector<const MemEvent*> match;+ match.reserve( mem.active.size() ); // heuristic+ if( m_memInfo.range.active )+ {+ auto it = std::lower_bound( mem.data.begin(), mem.data.end(), m_memInfo.range.min, [] ( const auto& lhs, const auto& rhs ) { return lhs.TimeAlloc() < rhs; } );+ if( it != mem.data.end() )+ {+ auto end = std::lower_bound( it, mem.data.end(), m_memInfo.range.max, [] ( const auto& lhs, const auto& rhs ) { return lhs.TimeAlloc() < rhs; } );+ while( it != end )+ {+ if( it->Ptr() <= m_memInfo.ptrFind && it->Ptr() + it->Size() > m_memInfo.ptrFind )+ {+ match.emplace_back( it );+ }+ ++it;+ }+ }+ }+ else+ {+ for( auto& v : mem.data )+ {+ if( v.Ptr() <= m_memInfo.ptrFind && v.Ptr() + v.Size() > m_memInfo.ptrFind )+ {+ match.emplace_back( &v );+ }+ }+ }++ if( match.empty() )+ {+ ImGui::TextUnformatted( "Found no allocations at given address" );+ }+ else+ {+ ListMemData( match, [this]( auto v ) {+ if( v->Ptr() == m_memInfo.ptrFind )+ {+ ImGui::Text( "0x%" PRIx64, m_memInfo.ptrFind );+ }+ else+ {+ ImGui::Text( "0x%" PRIx64 "+%" PRIu64, v->Ptr(), m_memInfo.ptrFind - v->Ptr() );+ }+ }, -1, m_memInfo.pool );+ }+ }+ ImGui::TreePop();+ }++ ImGui::Separator();+ if( ImGui::TreeNode( ICON_FA_HEART_PULSE " Active allocations" ) )+ {+ uint64_t total = 0;+ std::vector<const MemEvent*> items;+ items.reserve( mem.active.size() );+ if( m_memInfo.range.active )+ {+ auto it = std::lower_bound( mem.data.begin(), mem.data.end(), m_memInfo.range.min, [] ( const auto& lhs, const auto& rhs ) { return lhs.TimeAlloc() < rhs; } );+ if( it != mem.data.end() )+ {+ auto end = std::lower_bound( it, mem.data.end(), m_memInfo.range.max, [] ( const auto& lhs, const auto& rhs ) { return lhs.TimeAlloc() < rhs; } );+ while( it != end )+ {+ const auto tf = it->TimeFree();+ if( tf < 0 || tf >= m_memInfo.range.max )+ {+ items.emplace_back( it );+ total += it->Size();+ }+ ++it;+ }+ }+ }+ else+ {+ auto ptr = mem.data.data();+ for( auto& v : mem.active ) items.emplace_back( ptr + v.second );+ pdqsort_branchless( items.begin(), items.end(), []( const auto& lhs, const auto& rhs ) { return lhs->TimeAlloc() < rhs->TimeAlloc(); } );+ total = mem.usage;+ }++ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( items.size() ) );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ TextFocused( "Memory usage:", MemSizeToString( total ) );++ if( !items.empty() )+ {+ ListMemData( items, []( auto v ) {+ ImGui::Text( "0x%" PRIx64, v->Ptr() );+ }, -1, m_memInfo.pool );+ }+ else+ {+ TextDisabledUnformatted( "No active allocations" );+ }+ ImGui::TreePop();+ }++ ImGui::Separator();+ if( ImGui::TreeNode( ICON_FA_MAP " Memory map" ) )+ {+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ TextFocused( "Single pixel:", MemSizeToString( 1 << ChunkBits ) );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ TextFocused( "Single line:", MemSizeToString( PageChunkSize ) );++ auto pages = GetMemoryPages();+ const size_t lines = pages.size();++ ImGui::BeginChild( "##memMap", ImVec2( PageSize + 2, lines + 2 ), false );+ auto draw = ImGui::GetWindowDrawList();+ const auto wpos = ImGui::GetCursorScreenPos() + ImVec2( 1, 1 );+ const auto dpos = wpos + ImVec2( 0.5f, 0.5f );+ draw->AddRect( wpos - ImVec2( 1, 1 ), wpos + ImVec2( PageSize + 1, lines + 1 ), 0xFF666666 );+ draw->AddRectFilled( wpos, wpos + ImVec2( PageSize, lines ), 0xFF444444 );++ size_t line = 0;+ for( auto& page : pages )+ {+ size_t idx = 0;+ while( idx < PageSize )+ {+ if( page.data[idx] == 0 )+ {+ do+ {+ idx++;+ }+ while( idx < PageSize && page.data[idx] == 0 );+ }+ else+ {+ auto val = page.data[idx];+ const auto i0 = idx;+ do+ {+ idx++;+ }+ while( idx < PageSize && page.data[idx] == val );+ DrawLine( draw, dpos + ImVec2( i0, line ), dpos + ImVec2( idx, line ), MemDecayColor[(uint8_t)val] );+ }+ }+ line++;+ }++ ImGui::EndChild();+ ImGui::TreePop();+ }++ ImGui::PushID( m_memInfo.pool );+ ImGui::Separator();+ if( ImGui::TreeNode( ICON_FA_TREE " Bottom-up call stack tree" ) )+ {+ ImGui::SameLine();+ DrawHelpMarker( "Press ctrl key to display allocation info tooltip. Right click on function name to display allocations list." );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ SmallCheckbox( ICON_FA_LAYER_GROUP " Group by function name", &m_groupCallstackTreeByNameBottomUp );+ ImGui::SameLine();+ DrawHelpMarker( "If enabled, only one source location will be displayed (which may be incorrect)." );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ bool activeOnlyBottomUp = m_memRangeBottomUp == MemRange::Active;+ if( SmallCheckbox( "Only active allocations", &activeOnlyBottomUp ) )+ m_memRangeBottomUp = activeOnlyBottomUp ? MemRange::Active : MemRange::Full;+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ bool inactiveOnlyBottomUp = m_memRangeBottomUp == MemRange::Inactive;+ if( SmallCheckbox( "Only inactive allocations", &inactiveOnlyBottomUp ) )+ m_memRangeBottomUp = inactiveOnlyBottomUp ? MemRange::Inactive : MemRange::Full;++ auto tree = GetCallstackFrameTreeBottomUp( mem );+ if( !tree.empty() )+ {+ int idx = 0;+ DrawFrameTreeLevel( tree, idx );+ }+ else+ {+ TextDisabledUnformatted( "No call stack data collected" );+ }++ ImGui::TreePop();+ }++ ImGui::Separator();+ if( ImGui::TreeNode( ICON_FA_TREE " Top-down call stack tree" ) )+ {+ ImGui::SameLine();+ DrawHelpMarker( "Press ctrl key to display allocation info tooltip. Right click on function name to display allocations list." );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ SmallCheckbox( ICON_FA_LAYER_GROUP " Group by function name", &m_groupCallstackTreeByNameTopDown );+ ImGui::SameLine();+ DrawHelpMarker( "If enabled, only one source location will be displayed (which may be incorrect)." );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ bool activeOnlyTopDown = m_memRangeTopDown == MemRange::Active;+ if( SmallCheckbox( "Only active allocations", &activeOnlyTopDown ) )+ m_memRangeTopDown = activeOnlyTopDown ? MemRange::Active : MemRange::Full;+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ bool inactiveOnlyTopDown = m_memRangeTopDown == MemRange::Inactive;+ if( SmallCheckbox( "Only inactive allocations", &inactiveOnlyTopDown ) )+ m_memRangeTopDown = inactiveOnlyTopDown ? MemRange::Inactive : MemRange::Full;++ auto tree = GetCallstackFrameTreeTopDown( mem );+ if( !tree.empty() )+ {+ int idx = 0;+ DrawFrameTreeLevel( tree, idx );+ }+ else+ {+ TextDisabledUnformatted( "No call stack data collected" );+ }++ ImGui::TreePop();+ }+ ImGui::PopID();++ ImGui::EndChild();+ ImGui::End();+}++void View::DrawMemoryAllocWindow()+{+ bool show = true;+ ImGui::Begin( "Memory allocation", &show, ImGuiWindowFlags_AlwaysAutoResize );+ if( !ImGui::GetCurrentWindowRead()->SkipItems )+ {+ const auto& mem = m_worker.GetMemoryNamed( m_memoryAllocInfoPool );+ const auto& ev = mem.data[m_memoryAllocInfoWindow];+ const auto tidAlloc = m_worker.DecompressThread( ev.ThreadAlloc() );+ const auto tidFree = m_worker.DecompressThread( ev.ThreadFree() );+ int idx = 0;++ if( ImGui::Button( ICON_FA_MICROSCOPE " Zoom to allocation" ) )+ {+ ZoomToRange( ev.TimeAlloc(), ev.TimeFree() >= 0 ? ev.TimeFree() : m_worker.GetLastTime() );+ }++ if( m_worker.GetMemNameMap().size() > 1 )+ {+ TextFocused( ICON_FA_BOX_ARCHIVE " Pool:", m_memoryAllocInfoPool == 0 ? "Default allocator" : m_worker.GetString( m_memoryAllocInfoPool ) );+ }+ char buf[64];+ sprintf( buf, "0x%" PRIx64, ev.Ptr() );+ TextFocused( "Address:", buf );+ TextFocused( "Size:", MemSizeToString( ev.Size() ) );+ if( ev.Size() >= 10000ll )+ {+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s bytes)", RealToString( ev.Size() ) );+ }+ ImGui::Separator();+ TextFocused( "Appeared at", TimeToStringExact( ev.TimeAlloc() ) );+ if( ImGui::IsItemClicked() ) CenterAtTime( ev.TimeAlloc() );+ ImGui::SameLine(); ImGui::Spacing(); ImGui::SameLine();+ SmallColorBox( GetThreadColor( tidAlloc, 0 ) );+ ImGui::SameLine();+ TextFocused( "Thread:", m_worker.GetThreadName( tidAlloc ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( tidAlloc ) );+ if( m_worker.IsThreadFiber( tidAlloc ) )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 0.2f, 0.6f, 0.2f, 1.f ), "Fiber" );+ }+ if( ev.CsAlloc() != 0 )+ {+ const auto cs = ev.CsAlloc();+ SmallCallstackButton( ICON_FA_ALIGN_JUSTIFY, cs, idx );+ ImGui::SameLine();+ DrawCallstackCalls( cs, 4 );+ }+ if( ev.TimeFree() < 0 )+ {+ TextDisabledUnformatted( "Allocation still active" );+ }+ else+ {+ TextFocused( "Freed at", TimeToStringExact( ev.TimeFree() ) );+ if( ImGui::IsItemClicked() ) CenterAtTime( ev.TimeFree() );+ ImGui::SameLine(); ImGui::Spacing(); ImGui::SameLine();+ SmallColorBox( GetThreadColor( tidFree, 0 ) );+ ImGui::SameLine();+ TextFocused( "Thread:", m_worker.GetThreadName( tidFree ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( tidFree ) );+ if( m_worker.IsThreadFiber( tidFree ) )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 0.2f, 0.6f, 0.2f, 1.f ), "Fiber" );+ }+ if( ev.csFree.Val() != 0 )+ {+ const auto cs = ev.csFree.Val();+ SmallCallstackButton( ICON_FA_ALIGN_JUSTIFY, cs, idx );+ ImGui::SameLine();+ DrawCallstackCalls( cs, 4 );+ }+ TextFocused( "Duration:", TimeToString( ev.TimeFree() - ev.TimeAlloc() ) );+ }++ bool sep = false;+ auto zoneAlloc = FindZoneAtTime( tidAlloc, ev.TimeAlloc() );+ if( zoneAlloc )+ {+ ImGui::Separator();+ sep = true;+ const auto& srcloc = m_worker.GetSourceLocation( zoneAlloc->SrcLoc() );+ const auto txt = srcloc.name.active ? m_worker.GetString( srcloc.name ) : m_worker.GetString( srcloc.function );+ ImGui::PushID( idx++ );+ TextFocused( "Zone alloc:", txt );+ auto hover = ImGui::IsItemHovered();+ ImGui::PopID();+ if( ImGui::IsItemClicked() )+ {+ ShowZoneInfo( *zoneAlloc );+ }+ if( hover )+ {+ m_zoneHighlight = zoneAlloc;+ if( IsMouseClicked( 2 ) )+ {+ ZoomToZone( *zoneAlloc );+ }+ ZoneTooltip( *zoneAlloc );+ }+ }++ if( ev.TimeFree() >= 0 )+ {+ auto zoneFree = FindZoneAtTime( tidFree, ev.TimeFree() );+ if( zoneFree )+ {+ if( !sep ) ImGui::Separator();+ const auto& srcloc = m_worker.GetSourceLocation( zoneFree->SrcLoc() );+ const auto txt = srcloc.name.active ? m_worker.GetString( srcloc.name ) : m_worker.GetString( srcloc.function );+ TextFocused( "Zone free:", txt );+ auto hover = ImGui::IsItemHovered();+ if( ImGui::IsItemClicked() )+ {+ ShowZoneInfo( *zoneFree );+ }+ if( hover )+ {+ m_zoneHighlight = zoneFree;+ if( IsMouseClicked( 2 ) )+ {+ ZoomToZone( *zoneFree );+ }+ ZoneTooltip( *zoneFree );+ }+ if( zoneAlloc == zoneFree )+ {+ ImGui::SameLine();+ TextDisabledUnformatted( "(same zone)" );+ }+ }+ }+ }+ ImGui::End();+ if( !show ) m_memoryAllocInfoWindow = -1;+}++void View::ListMemData( std::vector<const MemEvent*>& vec, const std::function<void(const MemEvent*)>& DrawAddress, int64_t startTime, uint64_t pool )+{+ if( startTime == -1 ) startTime = 0;+ if( ImGui::BeginTable( "##mem", 8, ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Sortable | ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_ScrollY, ImVec2( 0, ImGui::GetTextLineHeightWithSpacing() * std::min<int64_t>( 1+vec.size(), 15 ) ) ) )+ {+ ImGui::TableSetupScrollFreeze( 0, 1 );+ ImGui::TableSetupColumn( "Address", ImGuiTableColumnFlags_NoHide );+ ImGui::TableSetupColumn( "Size", ImGuiTableColumnFlags_PreferSortDescending );+ ImGui::TableSetupColumn( "Appeared at", ImGuiTableColumnFlags_DefaultSort );+ ImGui::TableSetupColumn( "Duration", ImGuiTableColumnFlags_PreferSortDescending );+ ImGui::TableSetupColumn( "Thread", ImGuiTableColumnFlags_NoSort );+ ImGui::TableSetupColumn( "Zone alloc", ImGuiTableColumnFlags_NoSort );+ ImGui::TableSetupColumn( "Zone free", ImGuiTableColumnFlags_NoSort );+ ImGui::TableSetupColumn( "Call stack", ImGuiTableColumnFlags_NoSort );+ ImGui::TableHeadersRow();++ const auto& mem = m_worker.GetMemoryNamed( pool );+ const auto& sortspec = *ImGui::TableGetSortSpecs()->Specs;+ switch( sortspec.ColumnIndex )+ {+ case 0:+ if( sortspec.SortDirection == ImGuiSortDirection_Ascending )+ {+ pdqsort_branchless( vec.begin(), vec.end(), []( const auto& l, const auto& r ) { return l->Ptr() < r->Ptr(); } );+ }+ else+ {+ pdqsort_branchless( vec.begin(), vec.end(), []( const auto& l, const auto& r ) { return l->Ptr() > r->Ptr(); } );+ }+ break;+ case 1:+ if( sortspec.SortDirection == ImGuiSortDirection_Ascending )+ {+ pdqsort_branchless( vec.begin(), vec.end(), []( const auto& l, const auto& r ) { return l->Size() < r->Size(); } );+ }+ else+ {+ pdqsort_branchless( vec.begin(), vec.end(), []( const auto& l, const auto& r ) { return l->Size() > r->Size(); } );+ }+ break;+ case 2:+ if( sortspec.SortDirection == ImGuiSortDirection_Descending )+ {+ std::reverse( vec.begin(), vec.end() );+ }+ break;+ case 3:+ if( sortspec.SortDirection == ImGuiSortDirection_Ascending )+ {+ pdqsort_branchless( vec.begin(), vec.end(), []( const auto& l, const auto& r ) { return ( l->TimeFree() - l->TimeAlloc() ) < ( r->TimeFree() - r->TimeAlloc() ); } );+ }+ else+ {+ pdqsort_branchless( vec.begin(), vec.end(), []( const auto& l, const auto& r ) { return ( l->TimeFree() - l->TimeAlloc() ) > ( r->TimeFree() - r->TimeAlloc() ); } );+ }+ break;+ default:+ assert( false );+ break;+ }++ int idx = 0;+ ImGuiListClipper clipper;+ clipper.Begin( vec.end() - vec.begin() );+ while( clipper.Step() )+ {+ for( auto i=clipper.DisplayStart; i<clipper.DisplayEnd; i++ )+ {+ ImGui::TableNextRow();+ ImGui::TableNextColumn();++ auto v = vec[i];+ const auto arrIdx = std::distance( mem.data.begin(), v );++ ImGui::PushFont( m_fixedFont );+ if( m_memoryAllocInfoPool == pool && m_memoryAllocInfoWindow == arrIdx )+ {+ ImGui::PushStyleColor( ImGuiCol_Text, ImVec4( 1.f, 0.f, 0.f, 1.f ) );+ DrawAddress( v );+ ImGui::PopStyleColor();+ }+ else+ {+ DrawAddress( v );+ if( ImGui::IsItemClicked() )+ {+ m_memoryAllocInfoWindow = arrIdx;+ m_memoryAllocInfoPool = pool;+ }+ }+ ImGui::PopFont();+ if( ImGui::IsItemClicked( 2 ) )+ {+ ZoomToRange( v->TimeAlloc(), v->TimeFree() >= 0 ? v->TimeFree() : m_worker.GetLastTime() );+ }+ if( ImGui::IsItemHovered() )+ {+ m_memoryAllocHover = arrIdx;+ m_memoryAllocHoverWait = 2;+ m_memoryAllocHoverPool = pool;+ }+ ImGui::TableNextColumn();+ ImGui::TextUnformatted( MemSizeToString( v->Size() ) );+ ImGui::TableNextColumn();+ ImGui::PushID( idx++ );+ if( ImGui::Selectable( TimeToStringExact( v->TimeAlloc() - startTime ) ) )+ {+ CenterAtTime( v->TimeAlloc() );+ }+ ImGui::PopID();+ ImGui::TableNextColumn();+ if( v->TimeFree() < 0 )+ {+ TextColoredUnformatted( ImVec4( 0.6f, 1.f, 0.6f, 1.f ), TimeToString( m_worker.GetLastTime() - v->TimeAlloc() ) );+ ImGui::TableNextColumn();+ const auto tid = m_worker.DecompressThread( v->ThreadAlloc() );+ SmallColorBox( GetThreadColor( tid, 0 ) );+ ImGui::SameLine();+ ImGui::TextUnformatted( m_worker.GetThreadName( tid ) );+ }+ else+ {+ ImGui::PushID( idx++ );+ if( ImGui::Selectable( TimeToString( v->TimeFree() - v->TimeAlloc() ) ) )+ {+ CenterAtTime( v->TimeFree() );+ }+ ImGui::PopID();+ ImGui::TableNextColumn();+ if( v->ThreadAlloc() == v->ThreadFree() )+ {+ const auto tid = m_worker.DecompressThread( v->ThreadAlloc() );+ SmallColorBox( GetThreadColor( tid, 0 ) );+ ImGui::SameLine();+ ImGui::TextUnformatted( m_worker.GetThreadName( tid ) );+ }+ else+ {+ const auto tidAlloc = m_worker.DecompressThread( v->ThreadAlloc() );+ const auto tidFree = m_worker.DecompressThread( v->ThreadFree() );+ SmallColorBox( GetThreadColor( tidAlloc, 0 ) );+ ImGui::SameLine();+ ImGui::TextUnformatted( m_worker.GetThreadName( tidAlloc ) );+ ImGui::SameLine();+ ImGui::TextUnformatted( "/" );+ ImGui::SameLine();+ SmallColorBox( GetThreadColor( tidFree, 0 ) );+ ImGui::SameLine();+ ImGui::TextUnformatted( m_worker.GetThreadName( tidFree ) );+ }+ }+ ImGui::TableNextColumn();+ auto zone = FindZoneAtTime( m_worker.DecompressThread( v->ThreadAlloc() ), v->TimeAlloc() );+ if( !zone )+ {+ ImGui::TextUnformatted( "-" );+ }+ else+ {+ const auto& srcloc = m_worker.GetSourceLocation( zone->SrcLoc() );+ const auto txt = srcloc.name.active ? m_worker.GetString( srcloc.name ) : m_worker.GetString( srcloc.function );+ ImGui::PushID( idx++ );+ auto sel = ImGui::Selectable( txt, m_zoneInfoWindow == zone );+ auto hover = ImGui::IsItemHovered();+ ImGui::PopID();+ if( sel )+ {+ ShowZoneInfo( *zone );+ }+ if( hover )+ {+ m_zoneHighlight = zone;+ if( IsMouseClicked( 2 ) )+ {+ ZoomToZone( *zone );+ }+ ZoneTooltip( *zone );+ }+ }+ ImGui::TableNextColumn();+ if( v->TimeFree() < 0 )+ {+ TextColoredUnformatted( ImVec4( 0.6f, 1.f, 0.6f, 1.f ), "active" );+ }+ else+ {+ auto zoneFree = FindZoneAtTime( m_worker.DecompressThread( v->ThreadFree() ), v->TimeFree() );+ if( !zoneFree )+ {+ ImGui::TextUnformatted( "-" );+ }+ else+ {+ const auto& srcloc = m_worker.GetSourceLocation( zoneFree->SrcLoc() );+ const auto txt = srcloc.name.active ? m_worker.GetString( srcloc.name ) : m_worker.GetString( srcloc.function );+ ImGui::PushID( idx++ );+ bool sel;+ if( zoneFree == zone )+ {+ ImGui::PushStyleColor( ImGuiCol_Text, ImVec4( 1.f, 1.f, 0.6f, 1.f ) );+ sel = ImGui::Selectable( txt, m_zoneInfoWindow == zoneFree );+ ImGui::PopStyleColor( 1 );+ }+ else+ {+ sel = ImGui::Selectable( txt, m_zoneInfoWindow == zoneFree );+ }+ auto hover = ImGui::IsItemHovered();+ ImGui::PopID();+ if( sel )+ {+ ShowZoneInfo( *zoneFree );+ }+ if( hover )+ {+ m_zoneHighlight = zoneFree;+ if( IsMouseClicked( 2 ) )+ {+ ZoomToZone( *zoneFree );+ }+ ZoneTooltip( *zoneFree );+ }+ }+ }+ ImGui::TableNextColumn();+ if( v->CsAlloc() == 0 )+ {+ TextDisabledUnformatted( "[alloc]" );+ }+ else+ {+ SmallCallstackButton( "alloc", v->CsAlloc(), idx );+ }+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ if( v->csFree.Val() == 0 )+ {+ TextDisabledUnformatted( "[free]" );+ }+ else+ {+ SmallCallstackButton( "free", v->csFree.Val(), idx );+ }+ }+ }+ ImGui::EndTable();+ }+}++void View::DrawAllocList()+{+ const auto scale = GetScale();+ ImGui::SetNextWindowSize( ImVec2( 1100 * scale, 500 * scale ), ImGuiCond_FirstUseEver );+ ImGui::Begin( "Allocations list", &m_memInfo.showAllocList );+ if( ImGui::GetCurrentWindowRead()->SkipItems ) { ImGui::End(); return; }++ std::vector<const MemEvent*> data;+ auto basePtr = m_worker.GetMemoryNamed( m_memInfo.pool ).data.data();+ data.reserve( m_memInfo.allocList.size() );+ for( auto& idx : m_memInfo.allocList )+ {+ data.emplace_back( basePtr + idx );+ }++ TextFocused( "Number of allocations:", RealToString( m_memInfo.allocList.size() ) );+ ListMemData( data, []( auto v ) {+ ImGui::Text( "0x%" PRIx64, v->Ptr() );+ }, -1, m_memInfo.pool );+ ImGui::End();+}++}
+ cbits/tracy/profiler/src/profiler/TracyView_Messages.cpp view
@@ -0,0 +1,336 @@+#include "TracyImGui.hpp"+#include "TracyPrint.hpp"+#include "TracyTexture.hpp"+#include "TracyView.hpp"++namespace tracy+{++void View::DrawMessages()+{+ const auto& msgs = m_worker.GetMessages();++ const auto scale = GetScale();+ ImGui::SetNextWindowSize( ImVec2( 1200 * scale, 600 * scale ), ImGuiCond_FirstUseEver );+ ImGui::Begin( "Messages", &m_showMessages );+ if( ImGui::GetCurrentWindowRead()->SkipItems ) { ImGui::End(); return; }++ if( msgs.empty() )+ {+ const auto ty = ImGui::GetTextLineHeight();+ ImGui::PushFont( m_bigFont );+ ImGui::Dummy( ImVec2( 0, ( ImGui::GetContentRegionAvail().y - ImGui::GetTextLineHeight() * 2 ) * 0.5f ) );+ TextCentered( ICON_FA_FISH_FINS );+ TextCentered( "No messages were collected" );+ ImGui::PopFont();+ ImGui::End();+ return;+ }++ bool filterChanged = m_messageFilter.Draw( ICON_FA_FILTER " Filter messages", 200 );+ ImGui::SameLine();+ if( ImGui::Button( ICON_FA_DELETE_LEFT " Clear" ) )+ {+ m_messageFilter.Clear();+ filterChanged = true;+ }+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ TextFocused( "Total message count:", RealToString( msgs.size() ) );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ TextFocused( "Visible messages:", RealToString( m_visibleMessages ) );+ if( m_worker.GetFrameImageCount() != 0 )+ {+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::Checkbox( ICON_FA_IMAGE " Show frame images", &m_showMessageImages );+ }++ bool threadsChanged = false;+ auto expand = ImGui::TreeNode( ICON_FA_SHUFFLE " Visible threads:" );+ ImGui::SameLine();+ size_t visibleThreads = 0;+ size_t tsz = 0;+ for( const auto& t : m_threadOrder )+ {+ if( t->messages.empty() ) continue;+ if( VisibleMsgThread( t->id ) ) visibleThreads++;+ tsz++;+ }+ if( visibleThreads == tsz )+ {+ ImGui::TextDisabled( "(%zu)", tsz );+ }+ else+ {+ ImGui::TextDisabled( "(%zu/%zu)", visibleThreads, tsz );+ }+ if( expand )+ {+ auto& crash = m_worker.GetCrashEvent();++ ImGui::SameLine();+ if( ImGui::SmallButton( "Select all" ) )+ {+ for( const auto& t : m_threadOrder )+ {+ VisibleMsgThread( t->id ) = true;+ }+ threadsChanged = true;+ }+ ImGui::SameLine();+ if( ImGui::SmallButton( "Unselect all" ) )+ {+ for( const auto& t : m_threadOrder )+ {+ VisibleMsgThread( t->id ) = false;+ }+ threadsChanged = true;+ }++ int idx = 0;+ for( const auto& t : m_threadOrder )+ {+ if( t->messages.empty() ) continue;+ ImGui::PushID( idx++ );+ const auto threadColor = GetThreadColor( t->id, 0 );+ SmallColorBox( threadColor );+ ImGui::SameLine();+ if( SmallCheckbox( m_worker.GetThreadName( t->id ), &VisibleMsgThread( t->id ) ) )+ {+ threadsChanged = true;+ }+ ImGui::PopID();+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( t->messages.size() ) );+ if( crash.thread == t->id )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 1.f, 0.2f, 0.2f, 1.f ), ICON_FA_SKULL " Crashed" );+ }+ if( t->isFiber )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 0.2f, 0.6f, 0.2f, 1.f ), "Fiber" );+ }+ }+ ImGui::TreePop();+ }++ const bool msgsChanged = msgs.size() != m_prevMessages;+ if( filterChanged || threadsChanged )+ {+ bool showCallstack = false;+ m_msgList.reserve( msgs.size() );+ m_msgList.clear();+ if( m_messageFilter.IsActive() )+ {+ for( size_t i=0; i<msgs.size(); i++ )+ {+ const auto& v = msgs[i];+ const auto tid = m_worker.DecompressThread( v->thread );+ if( VisibleMsgThread( tid ) )+ {+ const auto text = m_worker.GetString( msgs[i]->ref );+ if( m_messageFilter.PassFilter( text ) )+ {+ if( !showCallstack && msgs[i]->callstack.Val() != 0 ) showCallstack = true;+ m_msgList.push_back_no_space_check( uint32_t( i ) );+ }+ }+ }+ }+ else+ {+ for( size_t i=0; i<msgs.size(); i++ )+ {+ const auto& v = msgs[i];+ const auto tid = m_worker.DecompressThread( v->thread );+ if( VisibleMsgThread( tid ) )+ {+ if( !showCallstack && msgs[i]->callstack.Val() != 0 ) showCallstack = true;+ m_msgList.push_back_no_space_check( uint32_t( i ) );+ }+ }+ }+ m_messagesShowCallstack = showCallstack;+ m_visibleMessages = m_msgList.size();+ if( msgsChanged ) m_prevMessages = msgs.size();+ }+ else if( msgsChanged )+ {+ assert( m_prevMessages < msgs.size() );+ bool showCallstack = m_messagesShowCallstack;+ m_msgList.reserve( msgs.size() );+ if( m_messageFilter.IsActive() )+ {+ for( size_t i=m_prevMessages; i<msgs.size(); i++ )+ {+ const auto& v = msgs[i];+ const auto tid = m_worker.DecompressThread( v->thread );+ if( VisibleMsgThread( tid ) )+ {+ const auto text = m_worker.GetString( msgs[i]->ref );+ if( m_messageFilter.PassFilter( text ) )+ {+ if( !showCallstack && msgs[i]->callstack.Val() != 0 ) showCallstack = true;+ m_msgList.push_back_no_space_check( uint32_t( i ) );+ }+ }+ }+ }+ else+ {+ for( size_t i=m_prevMessages; i<msgs.size(); i++ )+ {+ const auto& v = msgs[i];+ const auto tid = m_worker.DecompressThread( v->thread );+ if( VisibleMsgThread( tid ) )+ {+ if( !showCallstack && msgs[i]->callstack.Val() != 0 ) showCallstack = true;+ m_msgList.push_back_no_space_check( uint32_t( i ) );+ }+ }+ }+ m_messagesShowCallstack = showCallstack;+ m_visibleMessages = m_msgList.size();+ m_prevMessages = msgs.size();+ }++ bool hasCallstack = m_messagesShowCallstack;+ ImGui::Separator();+ ImGui::BeginChild( "##messages" );+ const int colNum = hasCallstack ? 4 : 3;+ if( ImGui::BeginTable( "##messages", colNum, ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_ScrollY | ImGuiTableFlags_Hideable ) )+ {+ ImGui::TableSetupScrollFreeze( 0, 1 );+ ImGui::TableSetupColumn( "Time", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize );+ ImGui::TableSetupColumn( "Thread" );+ ImGui::TableSetupColumn( "Message" );+ if( hasCallstack ) ImGui::TableSetupColumn( "Call stack" );+ ImGui::TableHeadersRow();++ int idx = 0;+ if( m_msgToFocus )+ {+ for( const auto& msgIdx : m_msgList )+ {+ DrawMessageLine( *msgs[msgIdx], hasCallstack, idx );+ }+ }+ else+ {+ ImGuiListClipper clipper;+ clipper.Begin( m_msgList.size() );+ while( clipper.Step() )+ {+ for( auto i=clipper.DisplayStart; i<clipper.DisplayEnd; i++ )+ {+ DrawMessageLine( *msgs[m_msgList[i]], hasCallstack, idx );+ }+ }+ }++ if( m_worker.IsConnected() && ImGui::GetScrollY() >= ImGui::GetScrollMaxY() )+ {+ ImGui::SetScrollHereY( 1.f );+ }+ ImGui::EndTable();+ }+ ImGui::EndChild();+ ImGui::End();+}++void View::DrawMessageLine( const MessageData& msg, bool hasCallstack, int& idx )+{+ ImGui::TableNextRow();+ ImGui::TableNextColumn();+ const auto text = m_worker.GetString( msg.ref );+ const auto tid = m_worker.DecompressThread( msg.thread );+ ImGui::PushID( &msg );+ if( ImGui::Selectable( TimeToStringExact( msg.time ), m_msgHighlight == &msg, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowOverlap ) )+ {+ CenterAtTime( msg.time );+ }+ if( ImGui::IsItemHovered() )+ {+ m_msgHighlight = &msg;++ if( m_showMessageImages )+ {+ const auto frameIdx = m_worker.GetFrameRange( *m_frames, msg.time, msg.time ).first;+ auto fi = m_worker.GetFrameImage( *m_frames, frameIdx );+ if( fi )+ {+ ImGui::BeginTooltip();+ if( fi != m_frameTexturePtr )+ {+ if( !m_frameTexture ) m_frameTexture = MakeTexture();+ UpdateTexture( m_frameTexture, m_worker.UnpackFrameImage( *fi ), fi->w, fi->h );+ m_frameTexturePtr = fi;+ }+ if( fi->flip )+ {+ ImGui::Image( m_frameTexture, ImVec2( fi->w, fi->h ), ImVec2( 0, 1 ), ImVec2( 1, 0 ) );+ }+ else+ {+ ImGui::Image( m_frameTexture, ImVec2( fi->w, fi->h ) );+ }+ ImGui::EndTooltip();+ }+ }+ }+ if( m_msgToFocus == &msg )+ {+ ImGui::SetScrollHereY();+ m_msgToFocus.Decay( nullptr );+ m_messagesScrollBottom = false;+ }+ ImGui::PopID();+ ImGui::TableNextColumn();+ SmallColorBox( GetThreadColor( tid, 0 ) );+ ImGui::SameLine();+ if( m_worker.IsThreadFiber( tid ) )+ {+ TextColoredUnformatted( 0xFF88FF88, m_worker.GetThreadName( tid ) );+ }+ else+ {+ ImGui::TextUnformatted( m_worker.GetThreadName( tid ) );+ }+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( tid ) );+ ImGui::TableNextColumn();+ auto tend = text;+ while( *tend != '\0' && *tend != '\n' ) tend++;+ ImGui::PushStyleColor( ImGuiCol_Text, msg.color );+ const auto cw = ImGui::GetContentRegionAvail().x;+ const auto tw = ImGui::CalcTextSize( text, tend ).x;+ ImGui::TextUnformatted( text, tend );+ if( tw > cw && ImGui::IsItemHovered() )+ {+ ImGui::SetNextWindowSize( ImVec2( 1000 * GetScale(), 0 ) );+ ImGui::BeginTooltip();+ ImGui::TextWrapped( "%s", text );+ ImGui::EndTooltip();+ }+ ImGui::PopStyleColor();+ if( hasCallstack )+ {+ ImGui::TableNextColumn();+ const auto cs = msg.callstack.Val();+ if( cs != 0 )+ {+ SmallCallstackButton( ICON_FA_ALIGN_JUSTIFY, cs, idx );+ ImGui::SameLine();+ DrawCallstackCalls( cs, 6 );+ }+ }+}++}
@@ -0,0 +1,152 @@+#include "TracyView.hpp"++namespace tracy+{++void View::ZoomToZone( const ZoneEvent& ev )+{+ const auto end = m_worker.GetZoneEnd( ev );+ if( end - ev.Start() <= 0 ) return;+ ZoomToRange( ev.Start(), end );+}++void View::ZoomToZone( const GpuEvent& ev )+{+ const auto end = m_worker.GetZoneEnd( ev );+ if( end - ev.GpuStart() <= 0 ) return;+ auto ctx = GetZoneCtx( ev );+ if( !ctx )+ {+ ZoomToRange( ev.GpuStart(), end );+ }+ else+ {+ const auto td = ctx->threadData.size() == 1 ? ctx->threadData.begin() : ctx->threadData.find( m_worker.DecompressThread( ev.Thread() ) );+ assert( td != ctx->threadData.end() );+ int64_t begin;+ if( td->second.timeline.is_magic() )+ {+ begin = ((Vector<GpuEvent>*)&td->second.timeline)->front().GpuStart();+ }+ else+ {+ begin = td->second.timeline.front()->GpuStart();+ }+ const auto drift = GpuDrift( ctx );+ ZoomToRange( AdjustGpuTime( ev.GpuStart(), begin, drift ), AdjustGpuTime( end, begin, drift ) );+ }+}++void View::ZoomToRange( int64_t start, int64_t end, bool pause )+{+ if( start == end )+ {+ end = start + 1;+ }++ if( pause )+ {+ m_viewMode = ViewMode::Paused;+ m_viewModeHeuristicTry = false;+ }+ m_highlightZoom.active = false;+ if( !m_playback.pause && m_playback.sync ) m_playback.pause = true;++ m_zoomAnim.active = true;+ if( m_viewMode == ViewMode::LastRange )+ {+ const auto rangeCurr = m_vd.zvEnd - m_vd.zvStart;+ const auto rangeDest = end - start;+ m_zoomAnim.start0 = m_vd.zvStart;+ m_zoomAnim.start1 = m_vd.zvStart - ( rangeDest - rangeCurr );+ m_zoomAnim.end0 = m_vd.zvEnd;+ m_zoomAnim.end1 = m_vd.zvEnd;+ }+ else+ {+ m_zoomAnim.start0 = m_vd.zvStart;+ m_zoomAnim.start1 = start;+ m_zoomAnim.end0 = m_vd.zvEnd;+ m_zoomAnim.end1 = end;+ }+ m_zoomAnim.progress = 0;+}++void View::ZoomToPrevFrame()+{+ if( m_vd.zvStart >= m_worker.GetFrameBegin( *m_frames, 0 ) )+ {+ size_t frame;+ if( m_frames->continuous )+ {+ frame = (size_t)m_worker.GetFrameRange( *m_frames, m_vd.zvStart, m_vd.zvStart ).first;+ }+ else+ {+ frame = (size_t)m_worker.GetFrameRange( *m_frames, m_vd.zvStart, m_vd.zvStart ).second;+ }++ if( frame > 0 )+ {+ frame--;+ const auto fbegin = m_worker.GetFrameBegin( *m_frames, frame );+ const auto fend = m_worker.GetFrameEnd( *m_frames, frame );+ ZoomToRange( fbegin, fend );+ }+ }+}++void View::ZoomToNextFrame()+{+ int64_t start;+ if( m_zoomAnim.active )+ {+ start = m_zoomAnim.start1;+ }+ else+ {+ start = m_vd.zvStart;+ }++ size_t frame;+ if( start < m_worker.GetFrameBegin( *m_frames, 0 ) )+ {+ frame = 0;+ }+ else+ {+ frame = (size_t)m_worker.GetFrameRange( *m_frames, start, start ).first + 1;+ }+ if( frame >= m_worker.GetFrameCount( *m_frames ) ) return;++ const auto fbegin = m_worker.GetFrameBegin( *m_frames, frame );+ const auto fend = m_worker.GetFrameEnd( *m_frames, frame );+ ZoomToRange( fbegin, fend );+}++void View::CenterAtTime( int64_t t )+{+ const auto hr = std::max<uint64_t>( 1, ( m_vd.zvEnd - m_vd.zvStart ) / 2 );+ ZoomToRange( t - hr, t + hr );+}++void View::SetViewToLastFrames()+{+ const int total = m_worker.GetFrameCount( *m_frames );++ m_vd.zvStart = m_worker.GetFrameBegin( *m_frames, std::max( 0, total - 4 ) );+ if( total == 1 )+ {+ m_vd.zvEnd = m_worker.GetLastTime();+ }+ else+ {+ m_vd.zvEnd = m_worker.GetFrameBegin( *m_frames, total - 1 );+ }+ if( m_vd.zvEnd == m_vd.zvStart )+ {+ m_vd.zvEnd = m_worker.GetLastTime();+ }+}++}
+ cbits/tracy/profiler/src/profiler/TracyView_NotificationArea.cpp view
@@ -0,0 +1,272 @@+#include "TracyImGui.hpp"+#include "TracyMouse.hpp"+#include "TracyPrint.hpp"+#include "TracyTimelineItem.hpp"+#include "TracyView.hpp"++namespace tracy+{++extern double s_time;++void View::DrawNotificationArea()+{+ if( m_sendQueueWarning.enabled )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 0, 0.5, 1, 1 ), ICON_FA_SATELLITE_DISH );+ if( ImGui::IsItemHovered() )+ {+ ImGui::BeginTooltip();+ ImGui::TextUnformatted( "The client is slow to answer queries." );+ ImGui::TextUnformatted( "" );+ ImGui::TextWrapped( "Such behavior is typically caused by the symbol resolution performed client-side. If this is a problem, you may try the following options:" );+ ImGui::BulletText( "Disable inline-symbol resolution with TRACY_NO_CALLSTACK_INLINES" );+ ImGui::BulletText( "Disable call stack sampling with TRACY_NO_SAMPLING" );+ ImGui::BulletText( "Change sampling frequency with TRACY_SAMPLING_HZ" );+ ImGui::BulletText( "Disable symbol resolution altogether with TRACY_NO_CALLSTACK" );+ ImGui::TextWrapped( "For more information, please refer to the manual." );+ ImGui::EndTooltip();+ if( IsMouseClicked( 0 ) ) m_sendQueueWarning.enabled = false;+ }+ }+ auto& io = ImGui::GetIO();+ const auto ty = ImGui::GetTextLineHeight();+ if( m_worker.IsConnected() )+ {+ size_t sqs;+ {+ std::shared_lock<std::shared_mutex> lock( m_worker.GetMbpsDataLock() );+ sqs = m_worker.GetSendQueueSize();+ }+ if( sqs != 0 )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 1, 0, 0, 1 ), ICON_FA_SATELLITE_DISH );+ if( ImGui::IsItemHovered() )+ {+ ImGui::BeginTooltip();+ TextFocused( "Query backlog:", RealToString( sqs ) );+ ImGui::EndTooltip();+ }+ }+ else+ {+ const auto sif = m_worker.GetSendInFlight();+ if( sif != 0 )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 1, 0.75f, 0, 1 ), ICON_FA_SATELLITE_DISH );+ if( ImGui::IsItemHovered() )+ {+ ImGui::BeginTooltip();+ TextFocused( "Queries in flight:", RealToString( sif ) );+ ImGui::EndTooltip();+ }+ }+ }+ }+ auto& crash = m_worker.GetCrashEvent();+ if( crash.thread != 0 )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 1, 0, 0, 1 ), ICON_FA_SKULL );+ if( ImGui::IsItemHovered() )+ {+ CrashTooltip();+ if( IsMouseClicked( 0 ) )+ {+ m_showInfo = true;+ }+ if( IsMouseClicked( 2 ) )+ {+ CenterAtTime( crash.time );+ }+ }+ }+ if( m_worker.AreSamplesInconsistent() )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 1, 0.5, 0, 1 ), ICON_FA_EYE_DROPPER );+ TooltipIfHovered( "Sampling data and ghost zones may be displayed wrongly due to data inconsistency. Save and reload the trace to fix this." );+ }+ if( m_vd.drawEmptyLabels )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 1, 0.5, 0, 1 ), ICON_FA_EXPAND );+ if( ImGui::IsItemHovered() )+ {+ ImGui::BeginTooltip();+ ImGui::TextUnformatted( "Displaying empty labels." );+ ImGui::EndTooltip();+ if( IsMouseClicked( 0 ) ) m_vd.drawEmptyLabels = false;+ }+ }+ if( !m_vd.drawContextSwitches )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 1, 0.5, 0, 1 ), ICON_FA_PERSON_HIKING );+ if( ImGui::IsItemHovered() )+ {+ ImGui::BeginTooltip();+ ImGui::TextUnformatted( "Context switches are hidden." );+ ImGui::EndTooltip();+ if( IsMouseClicked( 0 ) ) m_vd.drawContextSwitches = true;+ }+ }+ if( !m_vd.drawCpuData )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 1, 0.5, 0, 1 ), ICON_FA_SLIDERS );+ if( ImGui::IsItemHovered() )+ {+ ImGui::BeginTooltip();+ ImGui::TextUnformatted( "CPU data is hidden." );+ ImGui::EndTooltip();+ if( IsMouseClicked( 0 ) ) m_vd.drawCpuData = true;+ }+ }+ if( !m_vd.drawGpuZones )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 1, 0.5, 0, 1 ), ICON_FA_EYE );+ if( ImGui::IsItemHovered() )+ {+ ImGui::BeginTooltip();+ ImGui::TextUnformatted( "GPU zones are hidden." );+ ImGui::EndTooltip();+ if( IsMouseClicked( 0 ) ) m_vd.drawGpuZones = true;+ }+ }+ if( !m_vd.drawZones )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 1, 0.5, 0, 1 ), ICON_FA_MICROCHIP );+ if( ImGui::IsItemHovered() )+ {+ ImGui::BeginTooltip();+ ImGui::TextUnformatted( "CPU zones are hidden." );+ ImGui::EndTooltip();+ if( IsMouseClicked( 0 ) ) m_vd.drawZones = true;+ }+ }+#ifndef TRACY_NO_STATISTICS+ if( !m_vd.ghostZones )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 1, 0.5, 0, 1 ), ICON_FA_GHOST );+ if( ImGui::IsItemHovered() )+ {+ ImGui::BeginTooltip();+ ImGui::TextUnformatted( "Ghost zones are hidden." );+ ImGui::EndTooltip();+ if( IsMouseClicked( 0 ) ) m_vd.ghostZones = true;+ }+ }+#endif+ if( !m_vd.drawLocks )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 1, 0.5, 0, 1 ), ICON_FA_LOCK );+ if( ImGui::IsItemHovered() )+ {+ ImGui::BeginTooltip();+ ImGui::TextUnformatted( "Locks are hidden." );+ ImGui::EndTooltip();+ if( IsMouseClicked( 0 ) ) m_vd.drawLocks = true;+ }+ }+ if( !m_vd.drawPlots )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 1, 0.5, 0, 1 ), ICON_FA_SIGNATURE );+ if( ImGui::IsItemHovered() )+ {+ ImGui::BeginTooltip();+ ImGui::TextUnformatted( "Plots are hidden." );+ ImGui::EndTooltip();+ if( IsMouseClicked( 0 ) ) m_vd.drawPlots = true;+ }+ }+ {+ bool hidden = false;+ for( auto& v : m_visMap )+ {+ if( !v.second )+ {+ hidden = true;+ break;+ }+ }+ if( !hidden )+ {+ for( auto& v : m_tc.GetItemMap() )+ {+ if( !v.second->IsVisible() )+ {+ hidden = true;+ break;+ }+ }+ }++ if( hidden )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 1, 0.5, 0, 1 ), ICON_FA_EYE_LOW_VISION );+ if( ImGui::IsItemHovered() )+ {+ ImGui::BeginTooltip();+ ImGui::TextUnformatted( "Some timeline entries are hidden." );+ ImGui::EndTooltip();+ if( IsMouseClicked( 0 ) ) m_showOptions = true;+ }+ }+ }+ if( !m_worker.IsBackgroundDone() )+ {+ ImGui::SameLine();+ TextDisabledUnformatted( ICON_FA_LIST_CHECK );+ ImGui::SameLine();+ const auto pos = ImGui::GetCursorPos();+ ImGui::TextUnformatted( " " );+ ImGui::GetWindowDrawList()->AddCircleFilled( pos + ImVec2( 0, ty * 0.675f ), ty * ( 0.2f + ( sin( s_time * 8 ) + 1 ) * 0.125f ), 0xFF888888, 10 );+ auto rmin = ImGui::GetItemRectMin();+ rmin.x -= ty * 0.5f;+ const auto rmax = ImGui::GetItemRectMax();+ if( ImGui::IsMouseHoveringRect( rmin, rmax ) )+ {+ ImGui::BeginTooltip();+ ImGui::TextUnformatted( "Processing background tasks" );+ ImGui::EndTooltip();+ }+ }+ if( m_saveThreadState.load( std::memory_order_relaxed ) == SaveThreadState::Saving )+ {+ ImGui::SameLine();+ ImGui::TextUnformatted( ICON_FA_FLOPPY_DISK " Saving trace..." );+ m_notificationTime = 0;+ }+ else if( m_notificationTime > 0 )+ {+ m_notificationTime -= std::min( io.DeltaTime, 0.25f );+ ImGui::SameLine();+ TextDisabledUnformatted( m_notificationText.c_str() );+ }++ ImGui::PushFont( m_smallFont );+ const auto wpos = ImGui::GetWindowPos();+ const auto w = ImGui::GetContentRegionAvail().x;+ const auto fps = RealToString( int( io.Framerate + 0.5f ) );+ const auto fpssz = ImGui::CalcTextSize( fps ).x;+ ImGui::GetWindowDrawList()->AddText( wpos + ImVec2( w-fpssz, 0 ), 0x88FFFFFF, fps );++#ifndef NDEBUG+ const auto dsz = ImGui::CalcTextSize( "8888 DEBUG" ).x;+ ImGui::GetWindowDrawList()->AddText( wpos + ImVec2( w-dsz, 0 ), 0x886666FF, "DEBUG" );+#endif++ ImGui::PopFont();+}++}
+ cbits/tracy/profiler/src/profiler/TracyView_Options.cpp view
@@ -0,0 +1,829 @@+#include <inttypes.h>+#include <random>++#include "TracyFilesystem.hpp"+#include "TracyImGui.hpp"+#include "TracyMouse.hpp"+#include "TracyPrint.hpp"+#include "TracyTimelineItemGpu.hpp"+#include "TracyUtility.hpp"+#include "TracyView.hpp"+#include "tracy_pdqsort.h"++namespace tracy+{++void View::DrawOptions()+{+ ImGui::Begin( "Options", &m_showOptions, ImGuiWindowFlags_AlwaysAutoResize );+ if( ImGui::GetCurrentWindowRead()->SkipItems ) { ImGui::End(); return; }++ const auto scale = GetScale();+ bool val = m_vd.drawEmptyLabels;+ ImGui::Checkbox( ICON_FA_EXPAND " Draw empty labels", &val );+ m_vd.drawEmptyLabels = val;+ val = m_vd.drawFrameTargets;+ ImGui::Checkbox( ICON_FA_FLAG_CHECKERED " Draw frame targets", &val );+ m_vd.drawFrameTargets = val;+ ImGui::Indent();+ int tmp = m_vd.frameTarget;+ ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 0, 0 ) );+ ImGui::SetNextItemWidth( 90 * scale );+ if( ImGui::InputInt( "Target FPS", &tmp ) )+ {+ if( tmp < 1 ) tmp = 1;+ m_vd.frameTarget = tmp;+ }+ ImGui::SameLine();+ TextDisabledUnformatted( TimeToString( 1000*1000*1000 / tmp ) );+ ImGui::PopStyleVar();+ ImGui::PushFont( m_smallFont );+ SmallColorBox( 0xFF2222DD );+ ImGui::SameLine( 0, 0 );+ ImGui::Text( " < %i < ", tmp / 2 );+ ImGui::SameLine( 0, 0 );+ SmallColorBox( 0xFF22DDDD );+ ImGui::SameLine( 0, 0 );+ ImGui::Text( " < %i < ", tmp );+ ImGui::SameLine( 0, 0 );+ SmallColorBox( 0xFF22DD22 );+ ImGui::SameLine( 0, 0 );+ ImGui::Text( " < %i < ", tmp * 2 );+ ImGui::SameLine( 0, 0 );+ SmallColorBox( 0xFFDD9900 );+ ImGui::PopFont();+ ImGui::Unindent();+ if( m_worker.HasContextSwitches() )+ {+ ImGui::Separator();+ val = m_vd.drawContextSwitches;+ ImGui::Checkbox( ICON_FA_PERSON_HIKING " Draw context switches", &val );+ m_vd.drawContextSwitches = val;+ ImGui::Indent();+ val = m_vd.darkenContextSwitches;+ SmallCheckbox( ICON_FA_MOON " Darken inactive threads", &val );+ m_vd.darkenContextSwitches = val;+ ImGui::Unindent();+ val = m_vd.drawCpuData;+ ImGui::Checkbox( ICON_FA_SLIDERS " Draw CPU data", &val );+ m_vd.drawCpuData = val;+ ImGui::Indent();+ val = m_vd.drawCpuUsageGraph;+ SmallCheckbox( ICON_FA_SIGNATURE " Draw CPU usage graph", &val );+ m_vd.drawCpuUsageGraph = val;+ ImGui::Unindent();+ }++ if( m_worker.GetCallstackSampleCount() != 0 )+ {+ val = m_vd.drawSamples;+ ImGui::Checkbox( ICON_FA_EYE_DROPPER " Draw stack samples", &val );+ m_vd.drawSamples = val;+ }++ const auto& gpuData = m_worker.GetGpuData();+ if( !gpuData.empty() )+ {+ ImGui::Separator();+ val = m_vd.drawGpuZones;+ ImGui::Checkbox( ICON_FA_EYE " Draw GPU zones", &val );+ m_vd.drawGpuZones = val;+ const auto expand = ImGui::TreeNode( "GPU zones" );+ ImGui::SameLine();+ size_t visibleGpu = 0;+ for( const auto& gd : gpuData ) if( m_tc.GetItem( gd ).IsVisible() ) visibleGpu++;+ if( visibleGpu == gpuData.size() )+ {+ ImGui::TextDisabled( "(%zu)", gpuData.size() );+ }+ else+ {+ ImGui::TextDisabled( "(%zu/%zu)", visibleGpu, gpuData.size() );+ }+ if( expand )+ {+ for( size_t i=0; i<gpuData.size(); i++ )+ {+ const auto& timeline = gpuData[i]->threadData.begin()->second.timeline;+ m_tc.GetItem( gpuData[i] ).VisibilityCheckbox();+ ImGui::SameLine();+ if( gpuData[i]->threadData.size() == 1 )+ {+ ImGui::TextDisabled( "%s top level zones", RealToString( timeline.size() ) );+ }+ else+ {+ ImGui::TextDisabled( "%s threads", RealToString( gpuData[i]->threadData.size() ) );+ }+ if( gpuData[i]->name.Active() )+ {+ char buf[64];+ auto& item = (TimelineItemGpu&)( m_tc.GetItem( gpuData[i] ) );+ sprintf( buf, "%s context %i", GpuContextNames[(int)gpuData[i]->type], item.GetIdx() );+ ImGui::PushFont( m_smallFont );+ ImGui::TextUnformatted( buf );+ ImGui::PopFont();+ }+ if( !gpuData[i]->hasCalibration )+ {+ ImGui::TreePush( (void*)nullptr );+ auto& drift = GpuDrift( gpuData[i] );+ ImGui::SetNextItemWidth( 120 * scale );+ ImGui::PushID( i );+ ImGui::InputInt( "Drift (ns/s)", &drift );+ ImGui::PopID();+ if( timeline.size() > 1 )+ {+ ImGui::SameLine();+ if( ImGui::Button( ICON_FA_ROBOT " Auto" ) )+ {+ size_t lastidx = 0;+ if( timeline.is_magic() )+ {+ auto& tl = *((Vector<GpuEvent>*)&timeline);+ for( size_t j=tl.size()-1; j > 0; j-- )+ {+ if( tl[j].GpuEnd() >= 0 )+ {+ lastidx = j;+ break;+ }+ }+ }+ else+ {+ for( size_t j=timeline.size()-1; j > 0; j-- )+ {+ if( timeline[j]->GpuEnd() >= 0 )+ {+ lastidx = j;+ break;+ }+ }+ }++ enum { NumSlopes = 10000 };+ std::random_device rd;+ std::default_random_engine gen( rd() );+ std::uniform_int_distribution<size_t> dist( 0, lastidx - 1 );+ float slopes[NumSlopes];+ size_t idx = 0;+ if( timeline.is_magic() )+ {+ auto& tl = *((Vector<GpuEvent>*)&timeline);+ do+ {+ const auto p0 = dist( gen );+ const auto p1 = dist( gen );+ if( p0 != p1 )+ {+ slopes[idx++] = float( 1.0 - double( tl[p1].GpuStart() - tl[p0].GpuStart() ) / double( tl[p1].CpuStart() - tl[p0].CpuStart() ) );+ }+ }+ while( idx < NumSlopes );+ }+ else+ {+ do+ {+ const auto p0 = dist( gen );+ const auto p1 = dist( gen );+ if( p0 != p1 )+ {+ slopes[idx++] = float( 1.0 - double( timeline[p1]->GpuStart() - timeline[p0]->GpuStart() ) / double( timeline[p1]->CpuStart() - timeline[p0]->CpuStart() ) );+ }+ }+ while( idx < NumSlopes );+ }+ pdqsort_branchless( slopes, slopes+NumSlopes );+ drift = int( 1000000000 * -slopes[NumSlopes/2] );+ }+ }+ ImGui::TreePop();+ }+ }+ ImGui::TreePop();+ }+ }++ ImGui::Separator();+ val = m_vd.drawZones;+ ImGui::Checkbox( ICON_FA_MICROCHIP " Draw CPU zones", &val );+ ImGui::Indent();+ m_vd.drawZones = val;++#ifndef TRACY_NO_STATISTICS+ if( m_worker.AreGhostZonesReady() && m_worker.GetGhostZonesCount() != 0 )+ {+ val = m_vd.ghostZones;+ SmallCheckbox( ICON_FA_GHOST " Draw ghost zones", &val );+ m_vd.ghostZones = val;+ }+#endif++ int ival = m_vd.dynamicColors;+ ImGui::TextUnformatted( ICON_FA_PALETTE " Zone colors" );+ ImGui::SameLine();+ bool forceColors = m_vd.forceColors;+ if( SmallCheckbox( "Ignore custom", &forceColors ) ) m_vd.forceColors = forceColors;+ ImGui::SameLine();+ bool inheritColors = m_vd.inheritParentColors;+ if( SmallCheckbox( "Inherit parent colors", &inheritColors ) ) m_vd.inheritParentColors = inheritColors;+ ImGui::Indent();+ ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 0, 0 ) );+ ImGui::RadioButton( "Static", &ival, 0 );+ ImGui::RadioButton( "Thread dynamic", &ival, 1 );+ ImGui::RadioButton( "Source location dynamic", &ival, 2 );+ ImGui::PopStyleVar();+ ImGui::Unindent();+ m_vd.dynamicColors = ival;+ ival = (int)m_vd.shortenName;+ ImGui::TextUnformatted( ICON_FA_RULER_HORIZONTAL " Zone name shortening" );+ ImGui::Indent();+ ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 0, 0 ) );+ ImGui::RadioButton( "Disabled", &ival, (uint8_t)ShortenName::Never );+ ImGui::RadioButton( "Minimal length", &ival, (uint8_t)ShortenName::Always );+ ImGui::RadioButton( "Only normalize", &ival, (uint8_t)ShortenName::OnlyNormalize );+ ImGui::RadioButton( "As needed", &ival, (uint8_t)ShortenName::NoSpace );+ ImGui::RadioButton( "As needed + normalize", &ival, (uint8_t)ShortenName::NoSpaceAndNormalize );+ ImGui::PopStyleVar();+ ImGui::Unindent();+ m_vd.shortenName = (ShortenName)ival;+ ImGui::Unindent();++ if( !m_worker.GetLockMap().empty() )+ {+ size_t lockCnt = 0;+ size_t singleCnt = 0;+ size_t multiCntCont = 0;+ size_t multiCntUncont = 0;+ for( const auto& l : m_worker.GetLockMap() )+ {+ if( l.second->valid && !l.second->timeline.empty() )+ {+ lockCnt++;+ if( l.second->threadList.size() == 1 )+ {+ singleCnt++;+ }+ else if( l.second->isContended )+ {+ multiCntCont++;+ }+ else+ {+ multiCntUncont++;+ }+ }+ }++ ImGui::Separator();+ val = m_vd.drawLocks;+ ImGui::Checkbox( ICON_FA_LOCK " Draw locks", &val );+ m_vd.drawLocks = val;+ ImGui::SameLine();+ val = m_vd.onlyContendedLocks;+ ImGui::Checkbox( "Only contended", &val );+ m_vd.onlyContendedLocks = val;+ const auto expand = ImGui::TreeNode( "Locks" );+ ImGui::SameLine();+ size_t visibleLocks = 0;+ for( const auto& l : m_worker.GetLockMap() ) if( Vis( l.second ) ) visibleLocks++;+ if( visibleLocks == lockCnt )+ {+ ImGui::TextDisabled( "(%zu)", lockCnt );+ }+ else+ {+ ImGui::TextDisabled( "(%zu/%zu)", visibleLocks, lockCnt );+ }+ TooltipIfHovered( "Locks with no recorded events are counted, but not listed." );+ if( expand )+ {+ ImGui::SameLine();+ if( ImGui::SmallButton( "Select all" ) )+ {+ for( const auto& l : m_worker.GetLockMap() )+ {+ Vis( l.second ) = true;+ }+ }+ ImGui::SameLine();+ if( ImGui::SmallButton( "Unselect all" ) )+ {+ for( const auto& l : m_worker.GetLockMap() )+ {+ Vis( l.second ) = false;+ }+ }+ ImGui::SameLine();+ DrawHelpMarker( "Right click on lock name to open lock information window." );++ const bool multiExpand = ImGui::TreeNodeEx( "Contended locks present in multiple threads", ImGuiTreeNodeFlags_DefaultOpen );+ ImGui::SameLine();+ size_t visibleMultiCntCont = 0;+ for( const auto& l : m_worker.GetLockMap() ) if( l.second->threadList.size() != 1 && l.second->isContended && Vis( l.second ) ) visibleMultiCntCont++;+ if( visibleMultiCntCont == multiCntCont )+ {+ ImGui::TextDisabled( "(%zu)", multiCntCont );+ }+ else+ {+ ImGui::TextDisabled( "(%zu/%zu)", visibleMultiCntCont, multiCntCont );+ }+ if( multiExpand )+ {+ ImGui::SameLine();+ if( ImGui::SmallButton( "Select all" ) )+ {+ for( const auto& l : m_worker.GetLockMap() )+ {+ if( l.second->threadList.size() != 1 && l.second->isContended ) Vis( l.second ) = true;+ }+ }+ ImGui::SameLine();+ if( ImGui::SmallButton( "Unselect all" ) )+ {+ for( const auto& l : m_worker.GetLockMap() )+ {+ if( l.second->threadList.size() != 1 && l.second->isContended ) Vis( l.second ) = false;+ }+ }++ for( const auto& l : m_worker.GetLockMap() )+ {+ if( l.second->valid && !l.second->timeline.empty() && l.second->threadList.size() != 1 && l.second->isContended )+ {+ auto& sl = m_worker.GetSourceLocation( l.second->srcloc );+ auto fileName = m_worker.GetString( sl.file );++ char buf[1024];+ if( l.second->customName.Active() )+ {+ sprintf( buf, "%" PRIu32 ": %s", l.first, m_worker.GetString( l.second->customName ) );+ }+ else+ {+ sprintf( buf, "%" PRIu32 ": %s", l.first, m_worker.GetString( m_worker.GetSourceLocation( l.second->srcloc ).function ) );+ }+ SmallCheckbox( buf, &Vis( l.second ) );+ if( ImGui::IsItemHovered() )+ {+ m_lockHoverHighlight = l.first;++ if( ImGui::IsItemClicked( 1 ) )+ {+ m_lockInfoWindow = l.first;+ }+ }+ if( m_optionsLockBuzzAnim.Match( l.second->srcloc ) )+ {+ const auto time = m_optionsLockBuzzAnim.Time();+ const auto indentVal = sin( time * 60.f ) * 10.f * time;+ ImGui::SameLine( 0, ImGui::GetStyle().ItemSpacing.x + indentVal );+ }+ else+ {+ ImGui::SameLine();+ }+ ImGui::TextDisabled( "(%s) %s", RealToString( l.second->timeline.size() ), LocationToString( fileName, sl.line ) );+ if( ImGui::IsItemHovered() )+ {+ DrawSourceTooltip( fileName, sl.line, 1, 1 );+ if( ImGui::IsItemClicked( 1 ) )+ {+ if( SourceFileValid( fileName, m_worker.GetCaptureTime(), *this, m_worker ) )+ {+ ViewSource( fileName, sl.line );+ }+ else+ {+ m_optionsLockBuzzAnim.Enable( l.second->srcloc, 0.5f );+ }+ }+ }+ }+ }+ ImGui::TreePop();+ }+ const bool multiUncontExpand = ImGui::TreeNodeEx( "Uncontended locks present in multiple threads", 0 );+ ImGui::SameLine();+ uint64_t visibleMultiCntUncont = 0;+ for( const auto& l : m_worker.GetLockMap() ) if( l.second->threadList.size() != 1 && !l.second->isContended && Vis( l.second ) ) visibleMultiCntUncont++;+ if( visibleMultiCntUncont == multiCntUncont )+ {+ ImGui::TextDisabled( "(%zu)", multiCntUncont );+ }+ else+ {+ ImGui::TextDisabled( "(%zu/%zu)", visibleMultiCntUncont, multiCntUncont );+ }+ if( multiUncontExpand )+ {+ ImGui::SameLine();+ if( ImGui::SmallButton( "Select all" ) )+ {+ for( const auto& l : m_worker.GetLockMap() )+ {+ if( l.second->threadList.size() != 1 && !l.second->isContended ) Vis( l.second ) = true;+ }+ }+ ImGui::SameLine();+ if( ImGui::SmallButton( "Unselect all" ) )+ {+ for( const auto& l : m_worker.GetLockMap() )+ {+ if( l.second->threadList.size() != 1 && !l.second->isContended ) Vis( l.second ) = false;+ }+ }++ for( const auto& l : m_worker.GetLockMap() )+ {+ if( l.second->valid && !l.second->timeline.empty() && l.second->threadList.size() != 1 && !l.second->isContended )+ {+ auto& sl = m_worker.GetSourceLocation( l.second->srcloc );+ auto fileName = m_worker.GetString( sl.file );++ char buf[1024];+ if( l.second->customName.Active() )+ {+ sprintf( buf, "%" PRIu32 ": %s", l.first, m_worker.GetString( l.second->customName ) );+ }+ else+ {+ sprintf( buf, "%" PRIu32 ": %s", l.first, m_worker.GetString( m_worker.GetSourceLocation( l.second->srcloc ).function ) );+ }+ SmallCheckbox( buf, &Vis( l.second ) );+ if( ImGui::IsItemHovered() )+ {+ m_lockHoverHighlight = l.first;++ if( ImGui::IsItemClicked( 1 ) )+ {+ m_lockInfoWindow = l.first;+ }+ }+ if( m_optionsLockBuzzAnim.Match( l.second->srcloc ) )+ {+ const auto time = m_optionsLockBuzzAnim.Time();+ const auto indentVal = sin( time * 60.f ) * 10.f * time;+ ImGui::SameLine( 0, ImGui::GetStyle().ItemSpacing.x + indentVal );+ }+ else+ {+ ImGui::SameLine();+ }+ ImGui::TextDisabled( "(%s) %s", RealToString( l.second->timeline.size() ), LocationToString( fileName, sl.line ) );+ if( ImGui::IsItemHovered() )+ {+ DrawSourceTooltip( fileName, sl.line, 1, 1 );+ if( ImGui::IsItemClicked( 1 ) )+ {+ if( SourceFileValid( fileName, m_worker.GetCaptureTime(), *this, m_worker ) )+ {+ ViewSource( fileName, sl.line );+ }+ else+ {+ m_optionsLockBuzzAnim.Enable( l.second->srcloc, 0.5f );+ }+ }+ }+ }+ }+ ImGui::TreePop();+ }+ const auto singleExpand = ImGui::TreeNodeEx( "Locks present in a single thread", 0 );+ ImGui::SameLine();+ uint64_t visibleSingleCnt = 0;+ for( const auto& l : m_worker.GetLockMap() ) if( l.second->threadList.size() == 1 && Vis( l.second ) ) visibleSingleCnt++;+ if( visibleSingleCnt == singleCnt )+ {+ ImGui::TextDisabled( "(%zu)", singleCnt );+ }+ else+ {+ ImGui::TextDisabled( "(%zu/%zu)", visibleSingleCnt, singleCnt );+ }+ if( singleExpand )+ {+ ImGui::SameLine();+ if( ImGui::SmallButton( "Select all" ) )+ {+ for( const auto& l : m_worker.GetLockMap() )+ {+ if( l.second->threadList.size() == 1 ) Vis( l.second ) = true;+ }+ }+ ImGui::SameLine();+ if( ImGui::SmallButton( "Unselect all" ) )+ {+ for( const auto& l : m_worker.GetLockMap() )+ {+ if( l.second->threadList.size() == 1 ) Vis( l.second ) = false;+ }+ }++ for( const auto& l : m_worker.GetLockMap() )+ {+ if( l.second->valid && !l.second->timeline.empty() && l.second->threadList.size() == 1 )+ {+ auto& sl = m_worker.GetSourceLocation( l.second->srcloc );+ auto fileName = m_worker.GetString( sl.file );++ char buf[1024];+ if( l.second->customName.Active() )+ {+ sprintf( buf, "%" PRIu32 ": %s", l.first, m_worker.GetString( l.second->customName ) );+ }+ else+ {+ sprintf( buf, "%" PRIu32 ": %s", l.first, m_worker.GetString( m_worker.GetSourceLocation( l.second->srcloc ).function ) );+ }+ SmallCheckbox( buf, &Vis( l.second ) );+ if( ImGui::IsItemHovered() )+ {+ m_lockHoverHighlight = l.first;++ if( ImGui::IsItemClicked( 1 ) )+ {+ m_lockInfoWindow = l.first;+ }+ }+ if( m_optionsLockBuzzAnim.Match( l.second->srcloc ) )+ {+ const auto time = m_optionsLockBuzzAnim.Time();+ const auto indentVal = sin( time * 60.f ) * 10.f * time;+ ImGui::SameLine( 0, ImGui::GetStyle().ItemSpacing.x + indentVal );+ }+ else+ {+ ImGui::SameLine();+ }+ ImGui::TextDisabled( "(%s) %s", RealToString( l.second->timeline.size() ), LocationToString( fileName, sl.line ) );+ if( ImGui::IsItemHovered() )+ {+ DrawSourceTooltip( fileName, sl.line, 1, 1 );+ if( ImGui::IsItemClicked( 1 ) )+ {+ if( SourceFileValid( fileName, m_worker.GetCaptureTime(), *this, m_worker ) )+ {+ ViewSource( fileName, sl.line );+ }+ else+ {+ m_optionsLockBuzzAnim.Enable( l.second->srcloc, 0.5f );+ }+ }+ }+ }+ }+ ImGui::TreePop();+ }+ ImGui::TreePop();+ }+ }++ if( !m_worker.GetPlots().empty() )+ {+ ImGui::Separator();+ val = m_vd.drawPlots;+ ImGui::Checkbox( ICON_FA_SIGNATURE " Draw plots", &val );+ m_vd.drawPlots = val;++ ImGui::SameLine();+ int pH = m_vd.plotHeight;+ ImGui::SliderInt("Plot heights", &pH, 30, 200);+ m_vd.plotHeight = pH;++ const auto expand = ImGui::TreeNode( "Plots" );+ ImGui::SameLine();+ size_t visiblePlots = 0;+ for( const auto& p : m_worker.GetPlots() ) if( m_tc.GetItem( p ).IsVisible() ) visiblePlots++;+ if( visiblePlots == m_worker.GetPlots().size() )+ {+ ImGui::TextDisabled( "(%zu)", m_worker.GetPlots().size() );+ }+ else+ {+ ImGui::TextDisabled( "(%zu/%zu)", visiblePlots, m_worker.GetPlots().size() );+ }+ if( expand )+ {+ ImGui::SameLine();+ if( ImGui::SmallButton( "Select all" ) )+ {+ for( const auto& p : m_worker.GetPlots() )+ {+ m_tc.GetItem( p ).SetVisible( true );+ }+ }+ ImGui::SameLine();+ if( ImGui::SmallButton( "Unselect all" ) )+ {+ for( const auto& p : m_worker.GetPlots() )+ {+ m_tc.GetItem( p ).SetVisible( false );+ }+ }++ for( const auto& p : m_worker.GetPlots() )+ {+ SmallColorBox( GetPlotColor( *p, m_worker ) );+ ImGui::SameLine();+ m_tc.GetItem( p ).VisibilityCheckbox();+ ImGui::SameLine();+ ImGui::TextDisabled( "%s data points", RealToString( p->data.size() ) );+ }+ ImGui::TreePop();+ }+ }++ ImGui::Separator();+ auto expand = ImGui::TreeNode( ICON_FA_SHUFFLE " Visible threads:" );+ ImGui::SameLine();+ size_t visibleThreads = 0;+ for( const auto& t : m_threadOrder ) if( m_tc.GetItem( t ).IsVisible() ) visibleThreads++;+ if( visibleThreads == m_threadOrder.size() )+ {+ ImGui::TextDisabled( "(%zu)", m_threadOrder.size() );+ }+ else+ {+ ImGui::TextDisabled( "(%zu/%zu)", visibleThreads, m_threadOrder.size() );+ }+ if( expand )+ {+ auto& crash = m_worker.GetCrashEvent();++ ImGui::SameLine();+ if( ImGui::SmallButton( "Select all" ) )+ {+ for( const auto& t : m_threadOrder )+ {+ m_tc.GetItem( t ).SetVisible( true );+ }+ }+ ImGui::SameLine();+ if( ImGui::SmallButton( "Unselect all" ) )+ {+ for( const auto& t : m_threadOrder )+ {+ m_tc.GetItem( t ).SetVisible( false );+ }+ }+ ImGui::SameLine();+ if( ImGui::SmallButton( "Sort" ) )+ {+ pdqsort_branchless( m_threadOrder.begin(), m_threadOrder.end(), [this] ( const auto& lhs, const auto& rhs ) {+ if( lhs->groupHint != rhs->groupHint ) return lhs->groupHint < rhs->groupHint;+ return strcmp( m_worker.GetThreadName( lhs->id ), m_worker.GetThreadName( rhs->id ) ) < 0;+ } );+ }++ const auto wposx = ImGui::GetCursorScreenPos().x;+ m_threadDnd.clear();+ int idx = 0;+ for( const auto& t : m_threadOrder )+ {+ m_threadDnd.push_back( ImGui::GetCursorScreenPos().y );+ ImGui::PushID( idx );+ const auto threadName = m_worker.GetThreadName( t->id );+ const auto threadColor = GetThreadColor( t->id, 0 );+ SmallColorBox( threadColor );+ ImGui::SameLine();+ m_tc.GetItem( t ).VisibilityCheckbox();+ if( ImGui::BeginDragDropSource( ImGuiDragDropFlags_SourceNoHoldToOpenOthers ) )+ {+ ImGui::SetDragDropPayload( "ThreadOrder", &idx, sizeof(int) );+ ImGui::TextUnformatted( ICON_FA_SHUFFLE );+ ImGui::SameLine();+ SmallColorBox( threadColor );+ ImGui::SameLine();+ ImGui::TextUnformatted( threadName );+ ImGui::EndDragDropSource();+ }+ ImGui::PopID();+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( t->id ) );+ if( crash.thread == t->id )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 1.f, 0.2f, 0.2f, 1.f ), ICON_FA_SKULL );+ if( ImGui::IsItemHovered() )+ {+ ImGui::BeginTooltip();+ ImGui::TextUnformatted( "Crashed" );+ ImGui::EndTooltip();+ if( IsMouseClicked( 0 ) )+ {+ m_showInfo = true;+ }+ if( IsMouseClicked( 2 ) )+ {+ CenterAtTime( crash.time );+ }+ }+ }+ if( t->isFiber )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 0.2f, 0.6f, 0.2f, 1.f ), "Fiber" );+ }+ ImGui::SameLine();+ ImGui::TextDisabled( "%s top level zones", RealToString( t->timeline.size() ) );+ idx++;+ }+ if( m_threadDnd.size() > 1 )+ {+ const auto w = ImGui::GetContentRegionAvail().x;+ const auto dist = m_threadDnd[1] - m_threadDnd[0];+ const auto half = dist * 0.5f;+ m_threadDnd.push_back( m_threadDnd.back() + dist );++ int target = -1;+ int source;+ for( size_t i=0; i<m_threadDnd.size(); i++ )+ {+ if( ImGui::BeginDragDropTargetCustom( ImRect( wposx, m_threadDnd[i] - half, wposx + w, m_threadDnd[i] + half ), i+1 ) )+ {+ auto draw = ImGui::GetWindowDrawList();+ draw->AddLine( ImVec2( wposx, m_threadDnd[i] ), ImVec2( wposx + w, m_threadDnd[i] ), ImGui::GetColorU32(ImGuiCol_DragDropTarget), 2.f );+ if( auto payload = ImGui::AcceptDragDropPayload( "ThreadOrder", ImGuiDragDropFlags_AcceptNoDrawDefaultRect ) )+ {+ target = (int)i;+ source = *(int*)payload->Data;+ }+ ImGui::EndDragDropTarget();+ }+ }+ if( target >= 0 && target != source )+ {+ const auto srcval = m_threadOrder[source];+ if( target < source )+ {+ assert( source < (int)m_threadOrder.size() );+ m_threadOrder.erase( m_threadOrder.begin() + source );+ m_threadOrder.insert( m_threadOrder.begin() + target, srcval );+ }+ else+ {+ assert( target <= (int)m_threadOrder.size() );+ m_threadOrder.insert( m_threadOrder.begin() + target, srcval );+ m_threadOrder.erase( m_threadOrder.begin() + source );+ }+ }+ }+ ImGui::TreePop();+ }++ if( m_worker.AreFramesUsed() )+ {+ ImGui::Separator();+ expand = ImGui::TreeNode( ICON_FA_IMAGES " Visible frame sets:" );+ ImGui::SameLine();+ uint64_t visibleFrames = 0;+ for( const auto& fd : m_worker.GetFrames() ) if( Vis( fd ) ) visibleFrames++;+ if( visibleFrames == m_worker.GetFrames().size() )+ {+ ImGui::TextDisabled( "(%zu)", m_worker.GetFrames().size() );+ }+ else+ {+ ImGui::TextDisabled( "(%zu/%zu)", visibleFrames, m_worker.GetFrames().size() );+ }+ if( expand )+ {+ ImGui::SameLine();+ if( ImGui::SmallButton( "Select all" ) )+ {+ for( const auto& fd : m_worker.GetFrames() )+ {+ Vis( fd ) = true;+ }+ }+ ImGui::SameLine();+ if( ImGui::SmallButton( "Unselect all" ) )+ {+ for( const auto& fd : m_worker.GetFrames() )+ {+ Vis( fd ) = false;+ }+ }++ int idx = 0;+ for( const auto& fd : m_worker.GetFrames() )+ {+ ImGui::PushID( idx++ );+ SmallCheckbox( GetFrameSetName( *fd ), &Vis( fd ) );+ ImGui::PopID();+ ImGui::SameLine();+ ImGui::TextDisabled( "%s %sframes", RealToString( fd->frames.size() ), fd->continuous ? "" : "discontinuous " );+ }+ ImGui::TreePop();+ }+ }+ ImGui::End();+}++}
+ cbits/tracy/profiler/src/profiler/TracyView_Playback.cpp view
@@ -0,0 +1,218 @@+#include "TracyImGui.hpp"+#include "TracyPrint.hpp"+#include "TracyTexture.hpp"+#include "TracyView.hpp"++namespace tracy+{++void View::SetPlaybackFrame( uint32_t idx )+{+ const auto frameSet = m_worker.GetFramesBase();+ const auto& frameImages = m_worker.GetFrameImages();+ assert( idx < frameImages.size() );++ m_playback.frame = idx;++ if( idx == frameImages.size() - 1 )+ {+ m_playback.pause = true;+ }+ else+ {+ const auto t0 = m_worker.GetFrameBegin( *frameSet, frameImages[idx]->frameRef );+ const auto t1 = m_worker.GetFrameBegin( *frameSet, frameImages[idx+1]->frameRef );+ m_playback.timeLeft = ( t1 - t0 ) / 1000000000.f;+ }+}++static const char* PlaybackWindowButtons[] = {+ ICON_FA_PLAY " Play",+ ICON_FA_PAUSE " Pause",+};++enum { PlaybackWindowButtonsCount = sizeof( PlaybackWindowButtons ) / sizeof( *PlaybackWindowButtons ) };++void View::DrawPlayback()+{+ ImGui::Begin( "Playback", &m_showPlayback, ImGuiWindowFlags_AlwaysAutoResize );+ if( !m_showPlayback ) m_playback.pause = true;+ if( ImGui::GetCurrentWindowRead()->SkipItems ) { ImGui::End(); return; }++ const auto scale = GetScale();+ const auto frameSet = m_worker.GetFramesBase();+ const auto& frameImages = m_worker.GetFrameImages();+ const auto& fi = frameImages[m_playback.frame];+ const auto ficnt = m_worker.GetFrameImageCount();++ const auto tstart = m_worker.GetFrameBegin( *frameSet, fi->frameRef );++ if( !m_playback.texture )+ {+ m_playback.texture = MakeTexture();+ }+ if( m_playback.currFrame != m_playback.frame )+ {+ m_playback.currFrame = m_playback.frame;+ UpdateTexture( m_playback.texture, m_worker.UnpackFrameImage( *fi ), fi->w, fi->h );++ if( m_playback.sync )+ {+ const auto end = m_worker.GetFrameEnd( *frameSet, fi->frameRef );+ m_zoomAnim.active = false;+ m_vd.zvStart = tstart;+ m_vd.zvEnd = end;+ m_viewMode = ViewMode::Paused;+ m_viewModeHeuristicTry = false;+ }+ }++ if( !m_playback.pause )+ {+ Achieve( "frameImages" );++ auto time = ImGui::GetIO().DeltaTime * m_playback.speed;+ while( !m_playback.pause && time > 0 )+ {+ const auto dt = std::min( time, m_playback.timeLeft );+ time -= dt;+ m_playback.timeLeft -= dt;+ if( m_playback.timeLeft == 0 )+ {+ SetPlaybackFrame( m_playback.frame + 1 );+ }+ }+ }++ if( m_playback.zoom )+ {+ if( fi->flip )+ {+ ImGui::Image( m_playback.texture, ImVec2( fi->w * 2 * scale, fi->h * 2 * scale ), ImVec2( 0, 1 ), ImVec2( 1, 0 ) );+ }+ else+ {+ ImGui::Image( m_playback.texture, ImVec2( fi->w * 2 * scale, fi->h * 2 * scale ) );+ }+ }+ else+ {+ if( fi->flip )+ {+ ImGui::Image( m_playback.texture, ImVec2( fi->w * scale, fi->h * scale ), ImVec2( 0, 1 ), ImVec2( 1, 0 ) );+ }+ else+ {+ ImGui::Image( m_playback.texture, ImVec2( fi->w * scale, fi->h * scale ) );+ }+ }+ const auto wheel = ImGui::GetIO().MouseWheel;+ bool changed = false;+ int tmp = m_playback.frame + 1;+ if( wheel && ImGui::IsItemHovered() )+ {+ tmp -= (int)wheel;+ changed = true;+ }+ changed |= ImGui::SliderInt( "Frame image", &tmp, 1, ficnt, "%d" );+ ImGui::SetItemKeyOwner( ImGuiKey_MouseWheelY );+ if( wheel && ImGui::IsItemHovered() )+ {+ if( ImGui::IsItemActive() )+ {+ ImGui::ClearActiveID();+ }+ else+ {+ tmp -= (int)wheel;+ changed = true;+ }+ }+ if( changed )+ {+ if( tmp < 1 ) tmp = 1;+ else if( (uint32_t)tmp > ficnt ) tmp = ficnt;+ SetPlaybackFrame( uint32_t( tmp - 1 ) );+ m_playback.pause = true;+ }+ ImGui::SliderFloat( "Playback speed", &m_playback.speed, 0.1f, 4, "%.2f" );++ const auto th = ImGui::GetTextLineHeight();+ float bw = 0;+ for( int i=0; i<PlaybackWindowButtonsCount; i++ )+ {+ bw = std::max( bw, ImGui::CalcTextSize( PlaybackWindowButtons[i] ).x );+ }+ bw += th;++ if( ImGui::Button( " " ICON_FA_CARET_LEFT " " ) )+ {+ if( m_playback.frame > 0 )+ {+ SetPlaybackFrame( m_playback.frame - 1 );+ m_playback.pause = true;+ }+ }+ ImGui::SameLine();+ if( ImGui::Button( " " ICON_FA_CARET_RIGHT " " ) )+ {+ if( m_playback.frame < ficnt - 1 )+ {+ SetPlaybackFrame( m_playback.frame + 1 );+ m_playback.pause = true;+ }+ }+ ImGui::SameLine();+ if( m_playback.pause )+ {+ if( ImGui::Button( PlaybackWindowButtons[0], ImVec2( bw, 0 ) ) && m_playback.frame != frameImages.size() - 1 )+ {+ m_playback.pause = false;+ }+ }+ else+ {+ if( ImGui::Button( PlaybackWindowButtons[1], ImVec2( bw, 0 ) ) )+ {+ m_playback.pause = true;+ }+ }+ ImGui::SameLine();+ if( ImGui::Checkbox( "Sync timeline", &m_playback.sync ) )+ {+ if( m_playback.sync )+ {+ m_vd.zvStart = m_worker.GetFrameBegin( *frameSet, fi->frameRef );+ m_vd.zvEnd = m_worker.GetFrameEnd( *frameSet, fi->frameRef );+ m_zoomAnim.active = false;+ m_viewMode = ViewMode::Paused;+ m_viewModeHeuristicTry = false;+ }+ }+ ImGui::SameLine();+ ImGui::Checkbox( "Zoom 2\xc3\x97", &m_playback.zoom );+ TextFocused( "Timestamp:", TimeToString( tstart ) );+ TooltipIfHovered( TimeToStringExact( tstart ) );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ TextFocused( "Frame:", RealToString( GetFrameNumber( *frameSet, fi->frameRef ) ) );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ char buf[64];+ auto ptr = PrintFloat( buf, buf+62, 4.f * fi->csz / ( size_t( fi->w ) * size_t( fi->h ) / 2 ), 2 );+ memcpy( ptr, " bpp", 5 );+ TextFocused( "Ratio:", buf );+ if( ImGui::IsItemHovered() )+ {+ ImGui::BeginTooltip();+ ptr = PrintFloat( buf, buf+62, 100.f * fi->csz / ( size_t( fi->w ) * size_t( fi->h ) / 2 ), 2 );+ memcpy( ptr, "%", 2 );+ ImGui::TextUnformatted( buf );+ ImGui::EndTooltip();+ }+ ImGui::End();+}++}
+ cbits/tracy/profiler/src/profiler/TracyView_Plots.cpp view
@@ -0,0 +1,386 @@+#include <inttypes.h>++#include "TracyColor.hpp"+#include "TracyImGui.hpp"+#include "TracyMouse.hpp"+#include "TracyPrint.hpp"+#include "TracyTimelineContext.hpp"+#include "TracyUtility.hpp"+#include "TracyView.hpp"++namespace tracy+{++bool View::DrawPlot( const TimelineContext& ctx, PlotData& plot, const std::vector<uint32_t>& plotDraw, int& offset, bool rightEnd )+{+ auto draw = ImGui::GetWindowDrawList();+ const auto& wpos = ctx.wpos;+ const auto dpos = wpos + ImVec2( 0.5f, 0.5f );+ const auto pxns = ctx.pxns;+ const auto w = ctx.w;+ const auto hover = ctx.hover;+ const auto ty = ctx.ty;++ const auto PlotHeight = m_vd.plotHeight * GetScale();++ auto yPos = wpos.y + offset;+ if( yPos + PlotHeight >= ctx.yMin && yPos <= ctx.yMax )+ {+ auto min = plot.rMin;+ auto max = plot.rMax;++ auto pvit = m_plotView.find( &plot );+ if( pvit == m_plotView.end() )+ {+ pvit = m_plotView.emplace( &plot, PlotView { min, max } ).first;+ }+ auto& pv = pvit->second;+ if( pv.min != min || pv.max != max )+ {+ const auto dt = ImGui::GetIO().DeltaTime;+ const auto minDiff = min - pv.min;+ const auto maxDiff = max - pv.max;++ pv.min += minDiff * 15.0 * dt;+ pv.max += maxDiff * 15.0 * dt;++ const auto minDiffNew = min - pv.min;+ const auto maxDiffNew = max - pv.max;++ if( minDiff * minDiffNew < 0 ) pv.min = min;+ if( maxDiff * maxDiffNew < 0 ) pv.max = max;++ min = pv.min;+ max = pv.max;+ }++ const auto color = GetPlotColor( plot, m_worker );+ const auto bg = 0x22000000 | ( DarkenColorMore( color ) & 0xFFFFFF );+ const auto fill = 0x22000000 | ( DarkenColor( color ) & 0xFFFFFF );++ draw->AddRectFilled( ImVec2( 0, yPos ), ImVec2( w, yPos + PlotHeight ), bg );++ const auto revrange = 1.0 / ( max - min );++ auto it = plotDraw.begin();+ auto end = plotDraw.end();+ double px, py;+ bool first = true;+ while( it < end )+ {+ auto& vec = plot.data;+ const auto cnt = *it++;+ const auto i0 = *it++;+ const auto& v0 = vec[i0];+ double x = ( v0.time.Val() - m_vd.zvStart ) * pxns;+ double y = PlotHeight - ( v0.val - min ) * revrange * PlotHeight;++ if( first )+ {+ first = false;+ }+ else+ {+ if( plot.showSteps )+ {+ if( plot.fill )+ {+ draw->AddRectFilled( dpos + ImVec2( px, offset + PlotHeight ), dpos + ImVec2( x, offset + py ), fill );+ }+ const ImVec2 data[3] = { dpos + ImVec2( px, offset + py ), dpos + ImVec2( x, offset + py ), dpos + ImVec2( x, offset + y ) };+ draw->AddPolyline( data, 3, color, 0, 1.0f );+ }+ else+ {+ if( plot.fill )+ {+ draw->AddQuadFilled( dpos + ImVec2( px, offset + PlotHeight ), dpos + ImVec2( px, offset + py ), dpos + ImVec2( x, offset + y ), dpos + ImVec2( x, offset + PlotHeight ), fill );+ }+ DrawLine( draw, dpos + ImVec2( px, offset + py ), dpos + ImVec2( x, offset + y ), color );+ }+ }++ if( cnt == 0 )+ {+ if( i0 == 0 )+ {+ DrawPlotPoint( wpos, x, y, offset, color, hover, false, v0, 0, plot.type, plot.format, PlotHeight, plot.name );+ }+ else+ {+ DrawPlotPoint( wpos, x, y, offset, color, hover, true, v0, vec[i0-1].val, plot.type, plot.format, PlotHeight, plot.name );+ }+ px = x;+ py = y;+ }+ else+ {+ constexpr int MaxShow = 32;+ const auto i1 = i0 + cnt - 1;+ const auto& v1 = vec[i1];+ px = x;+ py = PlotHeight - ( v1.val - min ) * revrange * PlotHeight;+ const auto imin = *it++;+ const auto imax = *it++;+ const auto vmin = vec[imin].val;+ const auto vmax = vec[imax].val;+ const auto ymin = offset + PlotHeight - ( vmin - min ) * revrange * PlotHeight;+ const auto ymax = offset + PlotHeight - ( vmax - min ) * revrange * PlotHeight;+ if( cnt < MaxShow )+ {+ DrawLine( draw, dpos + ImVec2( x, ymin ), dpos + ImVec2( x, ymax ), color );++ for( int i=0; i<cnt; i++ )+ {+ const auto is = i0 + i;+ const auto& vs = vec[is];+ auto ys = PlotHeight - ( vs.val - min ) * revrange * PlotHeight;+ DrawPlotPoint( wpos, x, ys, offset, color, hover, vs.val, plot.format, PlotHeight );+ }+ }+ else+ {+ if( ymin - ymax < 3 )+ {+ const auto mid = ( ymin + ymax ) * 0.5;+ DrawLine( draw, dpos + ImVec2( x, mid - 1.5 ), dpos + ImVec2( x, mid + 1.5 ), color, 3 );+ }+ else+ {+ DrawLine( draw, dpos + ImVec2( x, ymin ), dpos + ImVec2( x, ymax ), color, 3 );+ }++ if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( x - 2, offset ), wpos + ImVec2( x + 2, offset + PlotHeight ) ) )+ {+ constexpr int NumSamples = 256;+ ImGui::BeginTooltip();+ TextFocused( "Number of values:", RealToString( cnt ) );+ if( cnt < NumSamples )+ {+ TextDisabledUnformatted( "Range:" );+ }+ else+ {+ TextDisabledUnformatted( "Estimated range:" );+ }+ ImGui::SameLine();+ ImGui::Text( "%s - %s", FormatPlotValue( vmin, plot.format ), FormatPlotValue( vmax, plot.format ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", FormatPlotValue( vmax - vmin, plot.format ) );+ ImGui::EndTooltip();+ }+ }+ }+ }++ if( rightEnd )+ {+ const auto lastTime = m_worker.GetLastTime();+ if( lastTime > m_vd.zvStart )+ {+ double y;+ double x0 = 0;+ const auto x1 = std::min<double>( ( lastTime - m_vd.zvStart ) * pxns, w );++ if( plotDraw.empty() )+ {+ y = PlotHeight * 0.5;+ DrawLine( draw, dpos + ImVec2( 0, offset + y ), dpos + ImVec2( x1, offset + y ), color );+ }+ else+ {+ x0 = ( plot.data.back().time.Val() - m_vd.zvStart ) * pxns;+ y = PlotHeight - ( plot.data.back().val - min ) * revrange * PlotHeight;+ DrawLine( draw, dpos + ImVec2( x0, offset + y ), dpos + ImVec2( x1, offset + y ), color );+ }++ if( plot.fill )+ {+ draw->AddRectFilled( dpos + ImVec2( x0, offset + PlotHeight ), dpos + ImVec2( x1, offset + y ), fill );+ }+ }+ }++ auto tmp = FormatPlotValue( plot.rMax, plot.format );+ DrawTextSuperContrast( draw, wpos + ImVec2( 0, offset ), color, tmp );+ offset += PlotHeight - ty;+ tmp = FormatPlotValue( plot.rMin, plot.format );+ DrawTextSuperContrast( draw, wpos + ImVec2( 0, offset ), color, tmp );++ DrawLine( draw, dpos + ImVec2( 0, offset + ty - 1 ), dpos + ImVec2( w, offset + ty - 1 ), 0xFF226E6E );+ offset += ty;++ if( plot.type == PlotType::Memory )+ {+ auto& mem = m_worker.GetMemoryNamed( plot.name );++ if( m_memoryAllocInfoPool == plot.name && m_memoryAllocInfoWindow >= 0 )+ {+ const auto& ev = mem.data[m_memoryAllocInfoWindow];++ const auto tStart = ev.TimeAlloc();+ const auto tEnd = ev.TimeFree() < 0 ? m_worker.GetLastTime() : ev.TimeFree();++ const auto px0 = ( tStart - m_vd.zvStart ) * pxns;+ const auto px1 = std::max( px0 + std::max( 1.0, pxns * 0.5 ), ( tEnd - m_vd.zvStart ) * pxns );+ draw->AddRectFilled( ImVec2( wpos.x + px0, yPos ), ImVec2( wpos.x + px1, yPos + PlotHeight ), 0x2288DD88 );+ draw->AddRect( ImVec2( wpos.x + px0, yPos ), ImVec2( wpos.x + px1, yPos + PlotHeight ), 0x4488DD88 );+ }+ if( m_memoryAllocHover >= 0 && m_memoryAllocHoverPool == plot.name && ( m_memoryAllocInfoPool != plot.name || m_memoryAllocHover != m_memoryAllocInfoWindow ) )+ {+ const auto& ev = mem.data[m_memoryAllocHover];++ const auto tStart = ev.TimeAlloc();+ const auto tEnd = ev.TimeFree() < 0 ? m_worker.GetLastTime() : ev.TimeFree();++ const auto px0 = ( tStart - m_vd.zvStart ) * pxns;+ const auto px1 = std::max( px0 + std::max( 1.0, pxns * 0.5 ), ( tEnd - m_vd.zvStart ) * pxns );+ draw->AddRectFilled( ImVec2( wpos.x + px0, yPos ), ImVec2( wpos.x + px1, yPos + PlotHeight ), 0x228888DD );+ draw->AddRect( ImVec2( wpos.x + px0, yPos ), ImVec2( wpos.x + px1, yPos + PlotHeight ), 0x448888DD );++ if( m_memoryAllocHoverWait > 0 )+ {+ m_memoryAllocHoverWait--;+ }+ else+ {+ m_memoryAllocHover = -1;+ }+ }+ }+ }+ else+ {+ offset += PlotHeight;+ }+ return true;+}++void View::DrawPlotPoint( const ImVec2& wpos, float x, float y, int offset, uint32_t color, bool hover, double val, PlotValueFormatting format, float PlotHeight )+{+ auto draw = ImGui::GetWindowDrawList();+ draw->AddRect( wpos + ImVec2( x - 1.5f, offset + y - 1.5f ), wpos + ImVec2( x + 2.5f, offset + y + 2.5f ), color );++ if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( x - 2, offset ), wpos + ImVec2( x + 2, offset + PlotHeight ) ) )+ {+ ImGui::BeginTooltip();+ TextFocused( "Value:", FormatPlotValue( val, format ) );+ ImGui::EndTooltip();+ }+}++void View::DrawPlotPoint( const ImVec2& wpos, float x, float y, int offset, uint32_t color, bool hover, bool hasPrev, const PlotItem& item, double prev, PlotType type, PlotValueFormatting format, float PlotHeight, uint64_t name )+{+ auto draw = ImGui::GetWindowDrawList();+ draw->AddRect( wpos + ImVec2( x - 1.5f, offset + y - 1.5f ), wpos + ImVec2( x + 2.5f, offset + y + 2.5f ), color );++ if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( x - 2, offset ), wpos + ImVec2( x + 2, offset + PlotHeight ) ) )+ {+ ImGui::BeginTooltip();+ TextFocused( "Time:", TimeToStringExact( item.time.Val() ) );+ if( type == PlotType::Memory )+ {+ TextDisabledUnformatted( "Value:" );+ ImGui::SameLine();+ if( item.val < 10000ll )+ {+ ImGui::TextUnformatted( MemSizeToString( item.val ) );+ }+ else+ {+ ImGui::TextUnformatted( MemSizeToString( item.val ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( item.val ) );+ }+ }+ else+ {+ TextFocused( "Value:", FormatPlotValue( item.val, format ) );+ }+ if( hasPrev )+ {+ const auto change = item.val - prev;+ TextFocused( "Change:", FormatPlotValue( change, format ) );++ if( type == PlotType::Memory )+ {+ auto& mem = m_worker.GetMemoryNamed( name );+ const MemEvent* ev = nullptr;+ if( change > 0 )+ {+ auto it = std::lower_bound( mem.data.begin(), mem.data.end(), item.time.Val(), [] ( const auto& lhs, const auto& rhs ) { return lhs.TimeAlloc() < rhs; } );+ if( it != mem.data.end() && it->TimeAlloc() == item.time.Val() )+ {+ ev = it;+ }+ }+ else+ {+ const auto& data = mem.data;+ auto it = std::lower_bound( mem.frees.begin(), mem.frees.end(), item.time.Val(), [&data] ( const auto& lhs, const auto& rhs ) { return data[lhs].TimeFree() < rhs; } );+ if( it != mem.frees.end() && data[*it].TimeFree() == item.time.Val() )+ {+ ev = &data[*it];+ }+ }+ if( ev )+ {+ ImGui::Separator();+ TextDisabledUnformatted( "Address:" );+ ImGui::SameLine();+ ImGui::Text( "0x%" PRIx64, ev->Ptr() );+ TextFocused( "Appeared at", TimeToStringExact( ev->TimeAlloc() ) );+ if( change > 0 )+ {+ ImGui::SameLine();+ ImGui::TextDisabled( "(this event)" );+ }+ if( ev->TimeFree() < 0 )+ {+ ImGui::TextUnformatted( "Allocation still active" );+ }+ else+ {+ TextFocused( "Freed at", TimeToStringExact( ev->TimeFree() ) );+ if( change < 0 )+ {+ ImGui::SameLine();+ TextDisabledUnformatted( "(this event)" );+ }+ TextFocused( "Duration:", TimeToString( ev->TimeFree() - ev->TimeAlloc() ) );+ }+ uint64_t tid;+ if( change > 0 )+ {+ tid = m_worker.DecompressThread( ev->ThreadAlloc() );+ }+ else+ {+ tid = m_worker.DecompressThread( ev->ThreadFree() );+ }+ SmallColorBox( GetThreadColor( tid, 0 ) );+ ImGui::SameLine();+ TextFocused( "Thread:", m_worker.GetThreadName( tid ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( tid ) );+ if( m_worker.IsThreadFiber( tid ) )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 0.2f, 0.6f, 0.2f, 1.f ), "Fiber" );+ }+ m_memoryAllocHover = std::distance( mem.data.begin(), ev );+ m_memoryAllocHoverWait = 2;+ m_memoryAllocHoverPool = name;+ if( IsMouseClicked( 0 ) )+ {+ m_memoryAllocInfoWindow = m_memoryAllocHover;+ m_memoryAllocInfoPool = name;+ }+ }+ }+ }+ ImGui::EndTooltip();+ }+}++}
+ cbits/tracy/profiler/src/profiler/TracyView_Ranges.cpp view
@@ -0,0 +1,178 @@+#include "TracyImGui.hpp"+#include "TracyMouse.hpp"+#include "TracyPrint.hpp"+#include "TracyView.hpp"++namespace tracy+{++void View::DrawRanges()+{+ ImGui::Begin( "Time range limits", &m_showRanges, ImGuiWindowFlags_AlwaysAutoResize );+ if( ImGui::GetCurrentWindowRead()->SkipItems ) { ImGui::End(); return; }+ DrawRangeEntry( m_findZone.range, ICON_FA_MAGNIFYING_GLASS " Find zone", 0x4488DD88, "RangeFindZoneCopyFrom", 0 );+ ImGui::Separator();+ DrawRangeEntry( m_statRange, ICON_FA_ARROW_UP_WIDE_SHORT " Statistics", 0x448888EE, "RangeStatisticsCopyFrom", 1 );+ ImGui::Separator();+ DrawRangeEntry( m_flameRange, ICON_FA_FIRE_FLAME_CURVED " Flame", 0x4488B5EE, "RangeFlameCopyFrom", 2 );+ ImGui::Separator();+ DrawRangeEntry( m_waitStackRange, ICON_FA_HOURGLASS_HALF " Wait stacks", 0x44EEB588, "RangeWaitStackCopyFrom", 3 );+ ImGui::Separator();+ DrawRangeEntry( m_memInfo.range, ICON_FA_MEMORY " Memory", 0x4488EEE3, "RangeMemoryCopyFrom", 4 );+ ImGui::End();+}++void View::DrawRangeEntry( Range& range, const char* label, uint32_t color, const char* popupLabel, int id )+{+ SmallColorBox( color );+ ImGui::SameLine();+ if( SmallCheckbox( label, &range.active ) )+ {+ if( range.active && range.min == 0 && range.max == 0 )+ {+ range.min = m_vd.zvStart;+ range.max = m_vd.zvEnd;+ }+ }+ if( range.active )+ {+ ImGui::SameLine();+ if( ImGui::SmallButton( "Limit to view" ) )+ {+ range.min = m_vd.zvStart;+ range.max = m_vd.zvEnd;+ }+ TextFocused( "Time range:", TimeToStringExact( range.min ) );+ ImGui::SameLine();+ TextFocused( "-", TimeToStringExact( range.max ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", TimeToString( range.max - range.min ) );+ if( ImGui::SmallButton( ICON_FA_MICROSCOPE " Focus" ) ) ZoomToRange( range.min, range.max );+ ImGui::SameLine();+ if( SmallButtonDisablable( ICON_FA_NOTE_STICKY " Set from annotation", m_annotations.empty() ) ) ImGui::OpenPopup( popupLabel );+ if( ImGui::BeginPopup( popupLabel ) )+ {+ for( auto& v : m_annotations )+ {+ SmallColorBox( v->color );+ ImGui::SameLine();+ if( ImGui::Selectable( v->text.c_str() ) )+ {+ range.min = v->range.min;+ range.max = v->range.max;+ }+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::TextDisabled( "%s - %s (%s)", TimeToStringExact( v->range.min ), TimeToStringExact( v->range.max ), TimeToString( v->range.max - v->range.min ) );+ }+ ImGui::EndPopup();+ }+ if( id != 0 )+ {+ ImGui::SameLine();+ if( SmallButtonDisablable( ICON_FA_MAGNIFYING_GLASS " Copy from find zone", m_findZone.range.min == 0 && m_findZone.range.max == 0 ) ) range = m_findZone.range;+ }+ if( id != 1 )+ {+ ImGui::SameLine();+ if( SmallButtonDisablable( ICON_FA_ARROW_UP_WIDE_SHORT " Copy from statistics", m_statRange.min == 0 && m_statRange.max == 0 ) ) range = m_statRange;+ }+ if( id != 2 )+ {+ ImGui::SameLine();+ if( SmallButtonDisablable( ICON_FA_FIRE_FLAME_CURVED " Copy from flame", m_flameRange.min == 0 && m_flameRange.max == 0 ) ) range = m_flameRange;+ }+ if( id != 3 )+ {+ ImGui::SameLine();+ if( SmallButtonDisablable( ICON_FA_HOURGLASS_HALF " Copy from wait stacks", m_waitStackRange.min == 0 && m_waitStackRange.max == 0 ) ) range = m_waitStackRange;+ }+ if( id != 4 )+ {+ ImGui::SameLine();+ if( SmallButtonDisablable( ICON_FA_MEMORY " Copy from memory", m_memInfo.range.min == 0 && m_memInfo.range.max == 0 ) ) range = m_memInfo.range;+ }+ }+}++void View::HandleRange( Range& range, int64_t timespan, const ImVec2& wpos, float w )+{+ if( !IsMouseDown( 0 ) ) range.modMin = range.modMax = false;+ if( !range.active ) return;+ auto& io = ImGui::GetIO();++ if( range.modMin )+ {+ const auto nspx = double( timespan ) / w;+ range.min = m_vd.zvStart + ( io.MousePos.x - wpos.x ) * nspx;+ range.hiMin = true;+ ConsumeMouseEvents( 0 );+ ImGui::SetMouseCursor( ImGuiMouseCursor_ResizeEW );+ if( range.min > range.max )+ {+ std::swap( range.min, range.max );+ std::swap( range.hiMin, range.hiMax );+ std::swap( range.modMin, range.modMax );+ }+ }+ else if( range.modMax )+ {+ const auto nspx = double( timespan ) / w;+ range.max = m_vd.zvStart + ( io.MousePos.x - wpos.x ) * nspx;+ range.hiMax = true;+ ConsumeMouseEvents( 0 );+ ImGui::SetMouseCursor( ImGuiMouseCursor_ResizeEW );+ if( range.min > range.max )+ {+ std::swap( range.min, range.max );+ std::swap( range.hiMin, range.hiMax );+ std::swap( range.modMin, range.modMax );+ }+ }+ else+ {+ const auto pxns = w / double( timespan );+ const auto px0 = ( range.min - m_vd.zvStart ) * pxns;+ if( abs( px0 - ( io.MousePos.x - wpos.x ) ) < 3 )+ {+ range.hiMin = true;+ ImGui::SetMouseCursor( ImGuiMouseCursor_ResizeEW );+ if( IsMouseClicked( 0 ) )+ {+ range.modMin = true;+ range.min = m_vd.zvStart + ( io.MousePos.x - wpos.x ) / pxns;+ ConsumeMouseEvents( 0 );+ if( range.min > range.max )+ {+ std::swap( range.min, range.max );+ std::swap( range.hiMin, range.hiMax );+ std::swap( range.modMin, range.modMax );+ }+ }+ }+ else+ {+ const auto px1 = ( range.max - m_vd.zvStart ) * pxns;+ if( abs( px1 - ( io.MousePos.x - wpos.x ) ) < 3 )+ {+ range.hiMax = true;+ ImGui::SetMouseCursor( ImGuiMouseCursor_ResizeEW );+ if( IsMouseClicked( 0 ) )+ {+ range.modMax = true;+ range.max = m_vd.zvStart + ( io.MousePos.x - wpos.x ) / pxns;+ ConsumeMouseEvents( 0 );+ if( range.min > range.max )+ {+ std::swap( range.min, range.max );+ std::swap( range.hiMin, range.hiMax );+ std::swap( range.modMin, range.modMax );+ }+ }+ }+ }+ }+}++}
+ cbits/tracy/profiler/src/profiler/TracyView_Samples.cpp view
@@ -0,0 +1,1275 @@+#include <inttypes.h>+#include <math.h>++#include "TracyFilesystem.hpp"+#include "TracyImGui.hpp"+#include "TracyMouse.hpp"+#include "TracyPrint.hpp"+#include "TracySourceView.hpp"+#include "TracyTimelineContext.hpp"+#include "TracyTimelineDraw.hpp"+#include "TracyView.hpp"+#include "tracy_pdqsort.h"++namespace tracy+{++void View::DrawSampleList( const TimelineContext& ctx, const std::vector<SamplesDraw>& drawList, const Vector<SampleData>& vec, int offset )+{+ const auto& wpos = ctx.wpos;+ const auto ty = ctx.ty;+ const auto vStart = ctx.vStart;+ const auto pxns = ctx.pxns;+ const auto hover = ctx.hover;++ const auto MinVis = 3 * GetScale();+ const auto ty0375 = offset + round( ty * 0.375f );+ const auto ty02 = round( ty * 0.2f );+ const auto ty01 = round( ty * 0.1f );+ const auto y0 = ty0375 - ty02 - 3;+ const auto y1 = ty0375 + ty02 - 1;+ auto begin = vec.begin();+ auto draw = ImGui::GetWindowDrawList();+ bool tooltipDisplayed = false;++ for( auto& v : drawList )+ {+ auto it = begin + v.idx;+ const auto t0 = it->time.Val();+ const auto px0 = ( t0 - vStart ) * pxns;+ if( v.num > 0 )+ {+ const auto eit = it + v.num;+ const auto t1 = eit->time.Val();+ const auto px1 = ( t1 - vStart ) * pxns;++ DrawZigZag( draw, wpos + ImVec2( 0, ty0375 ), px0, std::max( px1, px0+MinVis ), ty01, 0xFF997777 );+ if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, y0 ), wpos + ImVec2( std::max( px1, px0+MinVis ), y1 ) ) )+ {+ ImGui::BeginTooltip();+ ImGui::TextUnformatted( "Multiple call stack samples" );+ TextFocused( "Number of samples:", RealToString( v.num + 1 ) );+ ImGui::EndTooltip();++ if( IsMouseClicked( 2 ) )+ {+ ZoomToRange( t0, t1 );+ }+ }+ }+ else+ {+ draw->AddCircleFilled( wpos + ImVec2( px0, ty0375 ), ty02, 0xFFDD8888 );+ if( !tooltipDisplayed && hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px0 - ty02 - 2, y0 ), wpos + ImVec2( px0 + ty02 + 1, y1 ) ) )+ {+ tooltipDisplayed = true;+ CallstackTooltip( it->callstack.Val() );+ if( IsMouseClicked( 0 ) )+ {+ m_callstackInfoWindow = it->callstack.Val();+ }+ }+ }+ }+}++void View::DrawSamplesStatistics( Vector<SymList>& data, int64_t timeRange, AccumulationMode accumulationMode )+{+ static unordered_flat_map<uint64_t, SymList> inlineMap;+ assert( inlineMap.empty() );+ if( !m_statSeparateInlines )+ {+ static unordered_flat_map<uint64_t, SymList> baseMap;+ assert( baseMap.empty() );+ for( auto& v : data )+ {+ auto sym = m_worker.GetSymbolData( v.symAddr );+ const auto symAddr = ( sym && sym->isInline ) ? m_worker.GetSymbolForAddress( v.symAddr ) : v.symAddr;+ auto it = baseMap.find( symAddr );+ if( it == baseMap.end() )+ {+ baseMap.emplace( symAddr, SymList { symAddr, v.incl, v.excl, 0 } );+ }+ else+ {+ assert( symAddr == it->second.symAddr );+ it->second.incl += v.incl;+ it->second.excl += v.excl;+ it->second.count++;+ }+ }+ for( auto& v : data ) inlineMap.emplace( v.symAddr, SymList { v.symAddr, v.incl, v.excl, v.count } );+ data.clear();+ for( auto& v : baseMap )+ {+ data.push_back_no_space_check( v.second );+ }+ baseMap.clear();+ }++ if( data.empty() )+ {+ ImGui::PushFont( m_bigFont );+ ImGui::Dummy( ImVec2( 0, ( ImGui::GetContentRegionAvail().y - ImGui::GetTextLineHeight() * 2 ) * 0.5f ) );+ TextCentered( ICON_FA_HIPPO );+ TextCentered( "No entries to be displayed" );+ ImGui::PopFont();+ }+ else+ {+ const auto& symMap = m_worker.GetSymbolMap();++ if( accumulationMode == AccumulationMode::SelfOnly )+ {+ pdqsort_branchless( data.begin(), data.end(), []( const auto& l, const auto& r ) { return l.excl != r.excl ? l.excl > r.excl : l.symAddr < r.symAddr; } );+ }+ else+ {+ pdqsort_branchless( data.begin(), data.end(), []( const auto& l, const auto& r ) { return l.incl != r.incl ? l.incl > r.incl : l.symAddr < r.symAddr; } );+ }++ ImGui::BeginChild( "##statisticsSampling" );+ if( ImGui::BeginTable( "##statisticsSampling", 5, ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_ScrollY ) )+ {+ ImGui::TableSetupScrollFreeze( 0, 1 );+ ImGui::TableSetupColumn( "Name", ImGuiTableColumnFlags_NoHide );+ ImGui::TableSetupColumn( "Location", ImGuiTableColumnFlags_NoSort );+ ImGui::TableSetupColumn( "Image" );+ ImGui::TableSetupColumn( m_statSampleTime ? "Time" : "Count", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize );+ ImGui::TableSetupColumn( "Code size", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize );+ ImGui::TableHeadersRow();++ double revSampleCount100;+ if( m_statRange.active && m_worker.GetSamplingPeriod() != 0 )+ {+ const auto st = m_statRange.max - m_statRange.min;+ const auto cnt = st / m_worker.GetSamplingPeriod();+ revSampleCount100 = 100. / cnt;+ }+ else+ {+ revSampleCount100 = 100. / m_worker.GetCallstackSampleCount();+ }++ const bool showAll = m_showAllSymbols;+ const auto period = m_worker.GetSamplingPeriod();+ int idx = 0;+ for( auto& v : data )+ {+ const auto cnt = accumulationMode == AccumulationMode::SelfOnly ? v.excl : v.incl;+ if( cnt > 0 || showAll )+ {+ const char* name = "[unknown]";+ const char* file = "[unknown]";+ const char* imageName = "[unknown]";+ uint32_t line = 0;+ bool isInline = false;+ uint32_t symlen = 0;+ auto codeAddr = v.symAddr;++ auto sit = symMap.find( v.symAddr );+ if( sit != symMap.end() )+ {+ name = m_worker.GetString( sit->second.name );+ imageName = m_worker.GetString( sit->second.imageName );+ isInline = sit->second.isInline;+ switch( m_statSampleLocation )+ {+ case 0:+ file = m_worker.GetString( sit->second.file );+ line = sit->second.line;+ break;+ case 1:+ file = m_worker.GetString( sit->second.callFile );+ line = sit->second.callLine;+ break;+ case 2:+ if( sit->second.isInline )+ {+ file = m_worker.GetString( sit->second.callFile );+ line = sit->second.callLine;+ }+ else+ {+ file = m_worker.GetString( sit->second.file );+ line = sit->second.line;+ }+ break;+ default:+ assert( false );+ break;+ }+ if( m_statHideUnknown && file[0] == '[' ) continue;+ symlen = sit->second.size.Val();+ }+ else if( m_statHideUnknown )+ {+ continue;+ }++ ImGui::TableNextRow();+ ImGui::TableNextColumn();++ const bool isKernel = v.symAddr >> 63 != 0;+ const char* parentName = nullptr;+ if( symlen == 0 && !isKernel )+ {+ const auto parentAddr = m_worker.GetSymbolForAddress( v.symAddr );+ if( parentAddr != 0 )+ {+ auto pit = symMap.find( parentAddr );+ if( pit != symMap.end() )+ {+ codeAddr = parentAddr;+ symlen = pit->second.size.Val();+ parentName = m_worker.GetString( pit->second.name );+ }+ }+ }++ bool expand = false;+ if( !m_statSeparateInlines )+ {+ if( v.count > 0 && v.symAddr != 0 )+ {+ ImGui::PushID( v.symAddr );+ expand = ImGui::TreeNodeEx( "", v.count == 0 ? ImGuiTreeNodeFlags_Leaf : 0 );+ ImGui::PopID();+ ImGui::SameLine();+ }+ }+ else if( isInline )+ {+ TextDisabledUnformatted( ICON_FA_CARET_RIGHT );+ ImGui::SameLine();+ }+ uint32_t excl;+ if( m_statSeparateInlines )+ {+ excl = v.excl;+ }+ else+ {+ auto it = inlineMap.find( v.symAddr );+ excl = it != inlineMap.end() ? it->second.excl : 0;+ }+ bool hasNoSamples = v.symAddr == 0 || excl == 0;+ if( !m_statSeparateInlines && hasNoSamples && v.symAddr != 0 && v.count > 0 )+ {+ auto inSym = m_worker.GetInlineSymbolList( v.symAddr, symlen );+ if( inSym )+ {+ const auto symEnd = v.symAddr + symlen;+ while( *inSym < symEnd )+ {+ auto sit = inlineMap.find( *inSym );+ if( sit != inlineMap.end() )+ {+ if( sit->second.excl != 0 )+ {+ hasNoSamples = false;+ break;+ }+ }+ inSym++;+ }+ }+ }++ Vector<SymList> inSymList;+ if( !m_statSeparateInlines && !hasNoSamples && v.count > 0 && v.symAddr != 0 && ( expand || m_topInline ) )+ {+ assert( v.count > 0 );+ assert( symlen != 0 );+ auto inSym = m_worker.GetInlineSymbolList( v.symAddr, symlen );+ assert( inSym != nullptr );+ const auto symEnd = v.symAddr + symlen;+ if( !m_mergeInlines )+ {+ while( *inSym < symEnd )+ {+ auto sit = inlineMap.find( *inSym );+ if( sit != inlineMap.end() )+ {+ inSymList.push_back( SymList { *inSym, sit->second.incl, sit->second.excl } );+ }+ else+ {+ inSymList.push_back( SymList { *inSym, 0, 0 } );+ }+ inSym++;+ }+ }+ else+ {+ unordered_flat_map<uint32_t, uint64_t> mergeMap;+ unordered_flat_map<uint64_t, SymList> outMap;+ while( *inSym < symEnd )+ {+ auto symAddr = *inSym;+ auto sit = inlineMap.find( symAddr );+ auto sym = symMap.find( symAddr );+ if( sym != symMap.end() )+ {+ auto mit = mergeMap.find( sym->second.name.Idx() );+ if( mit == mergeMap.end() )+ {+ mergeMap.emplace( sym->second.name.Idx(), symAddr );+ }+ else+ {+ symAddr = mit->second;+ }+ if( sit != inlineMap.end() )+ {+ auto oit = outMap.find( symAddr );+ if( oit == outMap.end() )+ {+ outMap.emplace( symAddr, SymList { symAddr, sit->second.incl, sit->second.excl, 1 } );+ }+ else+ {+ oit->second.incl += sit->second.incl;+ oit->second.excl += sit->second.excl;+ oit->second.count++;+ }+ }+ else+ {+ auto oit = outMap.find( symAddr );+ if( oit == outMap.end() )+ {+ outMap.emplace( symAddr, SymList { symAddr, 0, 0, 1 } );+ }+ else+ {+ oit->second.count++;+ }+ }+ }+ inSym++;+ }+ inSymList.reserve( outMap.size() );+ for( auto& v : outMap )+ {+ inSymList.push_back( v.second );+ }+ }+ auto statIt = inlineMap.find( v.symAddr );+ if( statIt != inlineMap.end() )+ {+ inSymList.push_back( SymList { v.symAddr, statIt->second.incl, statIt->second.excl } );+ }++ if( accumulationMode == AccumulationMode::SelfOnly )+ {+ pdqsort_branchless( inSymList.begin(), inSymList.end(), []( const auto& l, const auto& r ) { return l.excl != r.excl ? l.excl > r.excl : l.symAddr < r.symAddr; } );+ }+ else+ {+ pdqsort_branchless( inSymList.begin(), inSymList.end(), []( const auto& l, const auto& r ) { return l.incl != l.incl ? l.incl > r.incl : l.symAddr < r.symAddr; } );+ }+ }++ const auto origName = name;+ if( hasNoSamples )+ {+ if( isKernel )+ {+ TextColoredUnformatted( 0xFF8888FF, name );+ }+ else if( m_vd.shortenName == ShortenName::Never )+ {+ ImGui::TextUnformatted( name );+ }+ else+ {+ const auto normalized = ShortenZoneName( ShortenName::OnlyNormalize, name );+ ImGui::TextUnformatted( normalized );+ TooltipNormalizedName( name, normalized );+ }+ }+ else+ {+ if( !inSymList.empty() && m_topInline )+ {+ const auto topName = m_worker.GetString( symMap.find( inSymList[0].symAddr )->second.name );+ if( topName != name )+ {+ // Parent name at this point should only be enabled if m_statSeparateInlines+ // is enabled. These two code paths should be mutually exclusive.+ assert( !parentName );++ parentName = name;+ name = topName;+ }+ }+ ImGui::PushID( idx++ );+ bool clicked;+ if( isKernel )+ {+ ImGui::PushStyleColor( ImGuiCol_Text, 0xFF8888FF );+ clicked = ImGui::Selectable( name, m_sampleParents.withInlines && m_sampleParents.symAddr == v.symAddr, ImGuiSelectableFlags_SpanAllColumns );+ ImGui::PopStyleColor();+ }+ else if( m_vd.shortenName == ShortenName::Never )+ {+ clicked = ImGui::Selectable( name, m_sampleParents.withInlines && m_sampleParents.symAddr == v.symAddr, ImGuiSelectableFlags_SpanAllColumns );+ }+ else+ {+ const auto normalized = ShortenZoneName( ShortenName::OnlyNormalize, name );+ clicked = ImGui::Selectable( "", m_sampleParents.withInlines && m_sampleParents.symAddr == v.symAddr, ImGuiSelectableFlags_SpanAllColumns );+ ImGui::SameLine( 0, 0 );+ ImGui::TextUnformatted( normalized );+ TooltipNormalizedName( name, normalized );+ }+ if( clicked ) ImGui::OpenPopup( "menuPopup" );+ if( ImGui::BeginPopup( "menuPopup" ) )+ {+ uint32_t len;+ const bool sfv = SourceFileValid( file, m_worker.GetCaptureTime(), *this, m_worker ) || ( symlen != 0 && m_worker.GetSymbolCode( codeAddr, len ) );+ if( !sfv ) ImGui::BeginDisabled();+ if( ImGui::MenuItem( " " ICON_FA_FILE_LINES " View symbol" ) )+ {+ if( SourceFileValid( file, m_worker.GetCaptureTime(), *this, m_worker ) )+ {+ ViewSymbol( file, line, codeAddr, v.symAddr );+ if( !m_statSeparateInlines ) m_sourceView->CalcInlineStats( false );+ }+ else if( symlen != 0 )+ {+ uint32_t len;+ if( m_worker.GetSymbolCode( codeAddr, len ) )+ {+ ViewSymbol( nullptr, 0, codeAddr, v.symAddr );+ if( !m_statSeparateInlines ) m_sourceView->CalcInlineStats( false );+ }+ }+ }+ if( !sfv ) ImGui::EndDisabled();+ if( ImGui::MenuItem( ICON_FA_ARROW_DOWN_SHORT_WIDE " Sample entry stacks" ) ) ShowSampleParents( v.symAddr, !m_statSeparateInlines );+ ImGui::EndPopup();+ }+ ImGui::PopID();+ }+ if( parentName )+ {+ ImGui::SameLine();+ if( m_vd.shortenName == ShortenName::Never )+ {+ ImGui::TextDisabled( "(%s)", parentName );+ }+ else+ {+ const auto normalized = ShortenZoneName( ShortenName::OnlyNormalize, parentName );+ ImGui::TextDisabled( "(%s)", normalized );+ TooltipNormalizedName( parentName, normalized );+ }+ }+ if( !m_statSeparateInlines && v.count > 0 && v.symAddr != 0 )+ {+ ImGui::SameLine();+ ImGui::TextDisabled( "(+%s)", RealToString( v.count ) );+ }+ ImGui::TableNextColumn();+ float indentVal = 0.f;+ if( m_statBuzzAnim.Match( v.symAddr ) )+ {+ const auto time = m_statBuzzAnim.Time();+ indentVal = sin( time * 60.f ) * 10.f * time;+ ImGui::Indent( indentVal );+ }+ if( m_statShowAddress )+ {+ ImGui::TextDisabled( "0x%" PRIx64, v.symAddr );+ }+ else+ {+ TextDisabledUnformatted( LocationToString( file, line ) );+ }+ if( ImGui::IsItemHovered() )+ {+ DrawSourceTooltip( file, line );+ if( ImGui::IsItemClicked( 1 ) )+ {+ if( SourceFileValid( file, m_worker.GetCaptureTime(), *this, m_worker ) )+ {+ ViewSymbol( file, line, codeAddr, v.symAddr );+ if( !m_statSeparateInlines ) m_sourceView->CalcInlineStats( false );+ }+ else if( symlen != 0 )+ {+ uint32_t len;+ if( m_worker.GetSymbolCode( codeAddr, len ) )+ {+ ViewSymbol( nullptr, 0, codeAddr, v.symAddr );+ if( !m_statSeparateInlines ) m_sourceView->CalcInlineStats( false );+ }+ else+ {+ m_statBuzzAnim.Enable( v.symAddr, 0.5f );+ }+ }+ else+ {+ m_statBuzzAnim.Enable( v.symAddr, 0.5f );+ }+ }+ }+ if( indentVal != 0.f )+ {+ ImGui::Unindent( indentVal );+ }+ ImGui::TableNextColumn();+ if( m_shortImageNames )+ {+ const char* end = imageName + strlen( imageName );+ const char* ptr = end - 1;+ while( ptr > imageName && *ptr != '/' && *ptr != '\\' ) ptr--;+ if( *ptr == '/' || *ptr == '\\' ) ptr++;+ const auto cw = ImGui::GetContentRegionAvail().x;+ const auto tw = ImGui::CalcTextSize( imageName, end ).x;+ TextDisabledUnformatted( ptr );+ if( ptr != imageName || tw > cw ) TooltipIfHovered( imageName );+ }+ else+ {+ const char* end = imageName + strlen( imageName );+ const auto cw = ImGui::GetContentRegionAvail().x;+ const auto tw = ImGui::CalcTextSize( imageName, end ).x;+ TextDisabledUnformatted( imageName );+ if( tw > cw ) TooltipIfHovered( imageName );+ }+ ImGui::TableNextColumn();+ const auto baseCnt = cnt;+ if( cnt > 0 )+ {+ char buf[64];+ if( m_statSampleTime )+ {+ const auto t = cnt * period;+ ImGui::TextUnformatted( TimeToString( t ) );+ PrintStringPercent( buf, 100. * t / timeRange );+ }+ else+ {+ ImGui::TextUnformatted( RealToString( cnt ) );+ PrintStringPercent( buf, cnt * revSampleCount100 );+ }+ ImGui::SameLine();+ TextDisabledUnformatted( buf );+ }+ ImGui::TableNextColumn();+ if( symlen != 0 )+ {+ if( m_worker.HasSymbolCode( codeAddr ) )+ {+ TextDisabledUnformatted( ICON_FA_DATABASE );+ ImGui::SameLine();+ }+ if( isInline )+ {+ TextDisabledUnformatted( "<" );+ ImGui::SameLine();+ }+ TextDisabledUnformatted( MemSizeToString( symlen ) );+ }++ if( !m_statSeparateInlines && expand )+ {+ const auto revBaseCnt = 100.0 / baseCnt;+ ImGui::Indent();+ for( auto& iv : inSymList )+ {+ const auto cnt = accumulationMode == AccumulationMode::SelfOnly ? iv.excl : iv.incl;+ if( cnt > 0 || showAll )+ {+ ImGui::TableNextRow();+ ImGui::TableNextColumn();+ auto sit = symMap.find( iv.symAddr );+ assert( sit != symMap.end() );+ name = m_worker.GetString( sit->second.name );+ switch( m_statSampleLocation )+ {+ case 0:+ file = m_worker.GetString( sit->second.file );+ line = sit->second.line;+ break;+ case 1:+ file = m_worker.GetString( sit->second.callFile );+ line = sit->second.callLine;+ break;+ case 2:+ if( sit->second.isInline )+ {+ file = m_worker.GetString( sit->second.callFile );+ line = sit->second.callLine;+ }+ else+ {+ file = m_worker.GetString( sit->second.file );+ line = sit->second.line;+ }+ break;+ default:+ assert( false );+ break;+ }++ const char* sn;+ if( iv.symAddr == v.symAddr )+ {+ if( parentName )+ {+ sn = parentName;+ }+ else+ {+ sn = "[ - self - ]";+ }+ }+ else+ {+ sn = name;+ }+ if( m_mergeInlines || iv.excl == 0 )+ {+ if( m_vd.shortenName == ShortenName::Never )+ {+ ImGui::TextUnformatted( sn );+ }+ else+ {+ const auto normalized = ShortenZoneName( ShortenName::OnlyNormalize, sn );+ ImGui::TextUnformatted( normalized );+ TooltipNormalizedName( sn, normalized );+ }+ }+ else+ {+ ImGui::PushID( idx++ );+ bool clicked;+ if( m_vd.shortenName == ShortenName::Never )+ {+ clicked = ImGui::Selectable( sn, !m_sampleParents.withInlines && m_sampleParents.symAddr == iv.symAddr, ImGuiSelectableFlags_SpanAllColumns );+ }+ else+ {+ const auto normalized = ShortenZoneName( ShortenName::OnlyNormalize, sn );+ clicked = ImGui::Selectable( "", !m_sampleParents.withInlines && m_sampleParents.symAddr == iv.symAddr, ImGuiSelectableFlags_SpanAllColumns );+ ImGui::SameLine( 0, 0 );+ ImGui::TextUnformatted( normalized );+ TooltipNormalizedName( sn, normalized );+ }+ if( clicked ) ImGui::OpenPopup( "menuPopup" );+ if( ImGui::BeginPopup( "menuPopup" ) )+ {+ uint32_t len;+ const bool sfv = SourceFileValid( file, m_worker.GetCaptureTime(), *this, m_worker ) || ( symlen != 0 && m_worker.GetSymbolCode( codeAddr, len ) );+ if( !sfv ) ImGui::BeginDisabled();+ if( ImGui::MenuItem( " " ICON_FA_FILE_LINES " View symbol" ) )+ {+ if( SourceFileValid( file, m_worker.GetCaptureTime(), *this, m_worker ) )+ {+ ViewSymbol( file, line, codeAddr, iv.symAddr );+ if( !m_statSeparateInlines ) m_sourceView->CalcInlineStats( true );+ }+ else if( symlen != 0 )+ {+ uint32_t len;+ if( m_worker.GetSymbolCode( codeAddr, len ) )+ {+ ViewSymbol( nullptr, 0, codeAddr, iv.symAddr );+ if( !m_statSeparateInlines ) m_sourceView->CalcInlineStats( true );+ }+ }+ }+ if( !sfv ) ImGui::EndDisabled();+ if( ImGui::MenuItem( ICON_FA_ARROW_DOWN_SHORT_WIDE " Sample entry stacks" ) ) ShowSampleParents( iv.symAddr, false );+ ImGui::EndPopup();+ }+ ImGui::PopID();+ }+ if( sn == parentName )+ {+ ImGui::SameLine();+ TextDisabledUnformatted( "(self)" );+ }+ if( iv.count > 1 )+ {+ ImGui::SameLine();+ ImGui::TextDisabled( "(\xc3\x97%s)", RealToString( iv.count ) );+ }+ ImGui::TableNextColumn();+ float indentVal = 0.f;+ if( m_statBuzzAnim.Match( iv.symAddr ) )+ {+ const auto time = m_statBuzzAnim.Time();+ indentVal = sin( time * 60.f ) * 10.f * time;+ ImGui::Indent( indentVal );+ }+ if( m_statShowAddress )+ {+ ImGui::TextDisabled( "0x%" PRIx64, iv.symAddr );+ }+ else+ {+ TextDisabledUnformatted( LocationToString( file, line ) );+ }+ if( ImGui::IsItemHovered() )+ {+ DrawSourceTooltip( file, line );+ if( ImGui::IsItemClicked( 1 ) )+ {+ if( SourceFileValid( file, m_worker.GetCaptureTime(), *this, m_worker ) )+ {+ ViewSymbol( file, line, codeAddr, iv.symAddr );+ if( !m_statSeparateInlines ) m_sourceView->CalcInlineStats( true );+ }+ else if( symlen != 0 )+ {+ uint32_t len;+ if( m_worker.GetSymbolCode( codeAddr, len ) )+ {+ ViewSymbol( nullptr, 0, codeAddr, iv.symAddr );+ if( !m_statSeparateInlines ) m_sourceView->CalcInlineStats( true );+ }+ else+ {+ m_statBuzzAnim.Enable( iv.symAddr, 0.5f );+ }+ }+ else+ {+ m_statBuzzAnim.Enable( iv.symAddr, 0.5f );+ }+ }+ }+ if( indentVal != 0.f )+ {+ ImGui::Unindent( indentVal );+ }+ ImGui::TableNextColumn();+ ImGui::TableNextColumn();+ if( cnt > 0 )+ {+ char buf[64];+ if( m_statSampleTime )+ {+ const auto t = cnt * period;+ ImGui::TextUnformatted( TimeToString( t ) );+ if( m_relativeInlines )+ {+ const auto tBase = baseCnt * period;+ PrintStringPercent( buf, 100. * t / tBase );+ }+ else+ {+ PrintStringPercent( buf, 100. * t / timeRange );+ }+ }+ else+ {+ ImGui::TextUnformatted( RealToString( cnt ) );+ if( m_relativeInlines )+ {+ PrintStringPercent( buf, cnt * revBaseCnt );+ }+ else+ {+ PrintStringPercent( buf, cnt * revSampleCount100 );+ }+ }+ ImGui::SameLine();+ TextDisabledUnformatted( buf );+ }+ }+ }+ ImGui::Unindent();+ ImGui::TreePop();+ }+ }+ }+ ImGui::EndTable();+ }+ ImGui::EndChild();++ inlineMap.clear();+ }+}++void View::DrawSampleParents()+{+ bool show = true;+ const auto scale = GetScale();+ ImGui::SetNextWindowSize( ImVec2( 1400 * scale, 500 * scale ), ImGuiCond_FirstUseEver );+ ImGui::Begin( "Sample entry stacks", &show, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse );+ if( !ImGui::GetCurrentWindowRead()->SkipItems )+ {+ auto ss = m_worker.GetSymbolStats( m_sampleParents.symAddr );+ auto excl = ss->excl;+ auto stats = ss->parents;++ const auto symbol = m_worker.GetSymbolData( m_sampleParents.symAddr );+ if( !symbol->isInline && m_sampleParents.withInlines )+ {+ const auto symlen = symbol->size.Val();+ auto inSym = m_worker.GetInlineSymbolList( m_sampleParents.symAddr, symlen );+ if( inSym )+ {+ const auto symEnd = m_sampleParents.symAddr + symlen;+ while( *inSym < symEnd )+ {+ auto istat = m_worker.GetSymbolStats( *inSym++ );+ if( !istat ) continue;+ excl += istat->excl;+ for( auto& v : istat->baseParents )+ {+ auto it = stats.find( v.first );+ if( it == stats.end() )+ {+ stats.emplace( v.first, v.second );+ }+ else+ {+ it->second += v.second;+ }+ }+ }+ }+ }+ assert( !stats.empty() );++ const auto symName = m_worker.GetString( symbol->name );+ const char* normalized = m_vd.shortenName != ShortenName::Never ? ShortenZoneName( ShortenName::OnlyNormalize, symName ) : nullptr;+ ImGui::PushFont( m_bigFont );+ TextFocused( "Function:", normalized ? normalized : symName );+ if( normalized )+ {+ ImGui::PopFont();+ TooltipNormalizedName( symName, normalized );+ ImGui::PushFont( m_bigFont );+ }+ if( symbol->isInline )+ {+ ImGui::SameLine();+ TextDisabledUnformatted( "(inline)" );+ }+ else if( !m_sampleParents.withInlines )+ {+ ImGui::SameLine();+ TextDisabledUnformatted( "(without inlines)" );+ }+ ImGui::PopFont();+ TextDisabledUnformatted( "Location:" );+ ImGui::SameLine();+ const auto callFile = m_worker.GetString( symbol->callFile );+ ImGui::TextUnformatted( LocationToString( callFile, symbol->callLine ) );+ if( ImGui::IsItemClicked( 1 ) )+ {+ ViewDispatch( callFile, symbol->callLine, m_sampleParents.symAddr );+ }+ TextDisabledUnformatted( "Entry point:" );+ ImGui::SameLine();+ const auto file = m_worker.GetString( symbol->file );+ ImGui::TextUnformatted( LocationToString( file, symbol->line ) );+ if( ImGui::IsItemClicked( 1 ) )+ {+ ViewDispatch( file, symbol->line, m_sampleParents.symAddr );+ }+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ TextDisabledUnformatted( m_worker.GetString( symbol->imageName ) );+ ImGui::Separator();+ ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 2, 2 ) );+ if( ImGui::RadioButton( ICON_FA_TABLE " List", m_sampleParents.mode == 0 ) ) m_sampleParents.mode = 0;+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ if( ImGui::RadioButton( ICON_FA_TREE " Bottom-up tree", m_sampleParents.mode == 1 ) ) m_sampleParents.mode = 1;+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ if( ImGui::RadioButton( ICON_FA_TREE " Top-down tree", m_sampleParents.mode == 2 ) ) m_sampleParents.mode = 2;+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::SeparatorEx( ImGuiSeparatorFlags_Vertical );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::Checkbox( ICON_FA_STOPWATCH " Show time", &m_statSampleTime );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ if( m_sampleParents.mode == 0 )+ {+ ImGui::Checkbox( ICON_FA_SHIELD_HALVED " External frames", &m_showExternalFrames );+ }+ else if( m_sampleParents.mode == 1 )+ {+ ImGui::Checkbox( ICON_FA_LAYER_GROUP " Group by function name", &m_sampleParents.groupBottomUp );+ }+ else if( m_sampleParents.mode == 2 )+ {+ ImGui::Checkbox( ICON_FA_LAYER_GROUP " Group by function name", &m_sampleParents.groupTopDown );+ }+ ImGui::PopStyleVar();+ ImGui::Separator();+ ImGui::BeginChild( "##sampleParents" );+ switch( m_sampleParents.mode )+ {+ case 0:+ {+ TextDisabledUnformatted( "Entry call stack:" );+ ImGui::SameLine();+ if( ImGui::SmallButton( " " ICON_FA_CARET_LEFT " " ) )+ {+ m_sampleParents.sel = std::max( m_sampleParents.sel - 1, 0 );+ }+ ImGui::SameLine();+ ImGui::Text( "%s / %s", RealToString( m_sampleParents.sel + 1 ), RealToString( stats.size() ) );+ if( ImGui::IsItemClicked() ) ImGui::OpenPopup( "EntryCallStackPopup" );+ ImGui::SameLine();+ if( ImGui::SmallButton( " " ICON_FA_CARET_RIGHT " " ) )+ {+ m_sampleParents.sel = std::min<int>( m_sampleParents.sel + 1, stats.size() - 1 );+ }+ if( ImGui::BeginPopup( "EntryCallStackPopup" ) )+ {+ int sel = m_sampleParents.sel + 1;+ ImGui::SetNextItemWidth( 120 * scale );+ const bool clicked = ImGui::InputInt( "##entryCallStack", &sel, 1, 100, ImGuiInputTextFlags_EnterReturnsTrue );+ if( clicked ) m_sampleParents.sel = std::min( std::max( sel, 1 ), int( stats.size() ) ) - 1;+ ImGui::EndPopup();+ }+ Vector<decltype(stats.begin())> data;+ data.reserve( stats.size() );+ for( auto it = stats.begin(); it != stats.end(); ++it ) data.push_back( it );+ pdqsort_branchless( data.begin(), data.end(), []( const auto& l, const auto& r ) { return l->second > r->second; } );+ ImGui::SameLine();+ ImGui::TextUnformatted( m_statSampleTime ? TimeToString( m_worker.GetSamplingPeriod() * data[m_sampleParents.sel]->second ) : RealToString( data[m_sampleParents.sel]->second ) );+ ImGui::SameLine();+ char buf[64];+ PrintStringPercent( buf, 100. * data[m_sampleParents.sel]->second / excl );+ TextDisabledUnformatted( buf );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 0, 0 ) );+ ImGui::Checkbox( ICON_FA_SCISSORS " Short images", &m_shortImageNames );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::TextUnformatted( ICON_FA_AT " Frame location:" );+ ImGui::SameLine();+ ImGui::RadioButton( "Source code", &m_showCallstackFrameAddress, 0 );+ ImGui::SameLine();+ ImGui::RadioButton( "Entry point", &m_showCallstackFrameAddress, 3 );+ ImGui::SameLine();+ ImGui::RadioButton( "Return address", &m_showCallstackFrameAddress, 1 );+ ImGui::SameLine();+ ImGui::RadioButton( "Symbol address", &m_showCallstackFrameAddress, 2 );+ ImGui::PopStyleVar();++ auto& cs = m_worker.GetParentCallstack( data[m_sampleParents.sel]->first );+ ImGui::Separator();+ if( ImGui::BeginTable( "##callstack", 4, ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders | ImGuiTableFlags_ScrollY ) )+ {+ ImGui::TableSetupScrollFreeze( 0, 1 );+ ImGui::TableSetupColumn( "Frame", ImGuiTableColumnFlags_NoHide | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize );+ ImGui::TableSetupColumn( "Function" );+ ImGui::TableSetupColumn( "Location" );+ ImGui::TableSetupColumn( "Image" );+ ImGui::TableHeadersRow();++ int external = 0;+ int fidx = 0;+ int bidx = 0;+ for( auto& entry : cs )+ {+ auto frameData = entry.custom ? m_worker.GetParentCallstackFrame( entry ) : m_worker.GetCallstackFrame( entry );+ assert( frameData );+ const auto fsz = frameData->size;+ for( uint8_t f=0; f<fsz; f++ )+ {+ const auto& frame = frameData->data[f];+ auto filename = m_worker.GetString( frame.file );+ auto image = frameData->imageName.Active() ? m_worker.GetString( frameData->imageName ) : nullptr;++ if( IsFrameExternal( filename, image ) )+ {+ if( !m_showExternalFrames )+ {+ if( f == fsz-1 ) fidx++;+ external++;+ continue;+ }+ }+ else if( external != 0 )+ {+ ImGui::TableNextRow();+ ImGui::TableNextColumn();+ ImGui::PushFont( m_smallFont );+ TextDisabledUnformatted( "external" );+ ImGui::TableNextColumn();+ if( external == 1 )+ {+ TextDisabledUnformatted( "1 frame" );+ }+ else+ {+ ImGui::TextDisabled( "%i frames", external );+ }+ ImGui::PopFont();+ external = 0;+ }++ ImGui::TableNextRow();+ ImGui::TableNextColumn();+ bidx++;+ if( f == fsz-1 )+ {+ ImGui::Text( "%i", fidx++ );+ }+ else+ {+ ImGui::PushFont( m_smallFont );+ TextDisabledUnformatted( "inline" );+ ImGui::PopFont();+ }+ ImGui::TableNextColumn();+ auto txt = m_worker.GetString( frame.name );+ {+ ImGui::PushTextWrapPos( 0.0f );+ if( txt[0] == '[' )+ {+ TextDisabledUnformatted( txt );+ }+ else if( m_worker.GetCanonicalPointer( entry ) >> 63 != 0 )+ {+ TextColoredUnformatted( 0xFF8888FF, txt );+ }+ else if( m_vd.shortenName == ShortenName::Never )+ {+ ImGui::TextUnformatted( txt );+ }+ else+ {+ const auto normalized = ShortenZoneName( ShortenName::OnlyNormalize, txt );+ ImGui::TextUnformatted( normalized );+ TooltipNormalizedName( txt, normalized );+ }+ ImGui::PopTextWrapPos();+ }+ if( ImGui::IsItemClicked() )+ {+ ImGui::SetClipboardText( txt );+ }+ ImGui::TableNextColumn();+ ImGui::PushTextWrapPos( 0.0f );+ float indentVal = 0.f;+ if( m_sampleParentBuzzAnim.Match( bidx ) )+ {+ const auto time = m_sampleParentBuzzAnim.Time();+ indentVal = sin( time * 60.f ) * 10.f * time;+ ImGui::Indent( indentVal );+ }+ txt = m_worker.GetString( frame.file );+ switch( m_showCallstackFrameAddress )+ {+ case 0:+ TextDisabledUnformatted( LocationToString( txt, frame.line ) );+ if( ImGui::IsItemClicked() )+ {+ ImGui::SetClipboardText( txt );+ }+ break;+ case 1:+ if( entry.custom == 0 )+ {+ const auto addr = m_worker.GetCanonicalPointer( entry );+ ImGui::TextDisabled( "0x%" PRIx64, addr );+ if( ImGui::IsItemClicked() )+ {+ char tmp[32];+ sprintf( tmp, "0x%" PRIx64, addr );+ ImGui::SetClipboardText( tmp );+ }+ }+ else+ {+ TextDisabledUnformatted( "unavailable" );+ }+ break;+ case 2:+ ImGui::TextDisabled( "0x%" PRIx64, frame.symAddr );+ if( ImGui::IsItemClicked() )+ {+ char tmp[32];+ sprintf( tmp, "0x%" PRIx64, frame.symAddr );+ ImGui::SetClipboardText( tmp );+ }+ break;+ case 3:+ {+ const auto sym = m_worker.GetSymbolData( frame.symAddr );+ if( sym )+ {+ const auto symtxt = m_worker.GetString( sym->file );+ TextDisabledUnformatted( LocationToString( symtxt, sym->line ) );+ if( ImGui::IsItemClicked() )+ {+ ImGui::SetClipboardText( symtxt );+ }+ }+ else+ {+ TextDisabledUnformatted( "[unknown]" );+ }+ break;+ }+ default:+ assert( false );+ break;+ }+ if( ImGui::IsItemHovered() )+ {+ if( m_showCallstackFrameAddress == 3 )+ {+ const auto sym = m_worker.GetSymbolData( frame.symAddr );+ if( sym )+ {+ const auto symtxt = m_worker.GetString( sym->file );+ DrawSourceTooltip( symtxt, sym->line );+ }+ }+ else+ {+ DrawSourceTooltip( txt, frame.line );+ }+ if( ImGui::IsItemClicked( 1 ) )+ {+ if( m_showCallstackFrameAddress == 3 )+ {+ const auto sym = m_worker.GetSymbolData( frame.symAddr );+ if( sym )+ {+ const auto symtxt = m_worker.GetString( sym->file );+ if( !ViewDispatch( symtxt, sym->line, frame.symAddr ) )+ {+ m_sampleParentBuzzAnim.Enable( bidx, 0.5f );+ }+ }+ else+ {+ m_sampleParentBuzzAnim.Enable( bidx, 0.5f );+ }+ }+ else+ {+ if( !ViewDispatch( txt, frame.line, frame.symAddr ) )+ {+ m_sampleParentBuzzAnim.Enable( bidx, 0.5f );+ }+ }+ }+ }+ if( indentVal != 0.f )+ {+ ImGui::Unindent( indentVal );+ }+ ImGui::PopTextWrapPos();+ ImGui::TableNextColumn();+ if( frameData->imageName.Active() )+ {+ const char* imageName = m_worker.GetString( frameData->imageName );+ const char* end = imageName + strlen( imageName );++ if( m_shortImageNames )+ {+ const char* ptr = end - 1;+ while( ptr > imageName && *ptr != '/' && *ptr != '\\' ) ptr--;+ if( *ptr == '/' || *ptr == '\\' ) ptr++;+ const auto cw = ImGui::GetContentRegionAvail().x;+ const auto tw = ImGui::CalcTextSize( imageName, end ).x;+ TextDisabledUnformatted( ptr );+ if( ptr != imageName || tw > cw ) TooltipIfHovered( imageName );+ }+ else+ {+ const auto cw = ImGui::GetContentRegionAvail().x;+ const auto tw = ImGui::CalcTextSize( imageName, end ).x;+ TextDisabledUnformatted( imageName );+ if( tw > cw ) TooltipIfHovered( imageName );+ }+ }+ }+ }+ if( external != 0 )+ {+ ImGui::TableNextRow();+ ImGui::TableNextColumn();+ ImGui::PushFont( m_smallFont );+ TextDisabledUnformatted( "external" );+ ImGui::TableNextColumn();+ if( external == 1 )+ {+ TextDisabledUnformatted( "1 frame" );+ }+ else+ {+ ImGui::TextDisabled( "%i frames", external );+ }+ ImGui::PopFont();+ }+ ImGui::EndTable();+ }+ break;+ }+ case 1:+ {+ auto tree = GetParentsCallstackFrameTreeBottomUp( stats, m_sampleParents.groupBottomUp );+ if( !tree.empty() )+ {+ int idx = 0;+ DrawParentsFrameTreeLevel( tree, idx );+ }+ else+ {+ TextDisabledUnformatted( "No call stacks to show" );+ }++ break;+ }+ case 2:+ {+ auto tree = GetParentsCallstackFrameTreeTopDown( stats, m_sampleParents.groupTopDown );+ if( !tree.empty() )+ {+ int idx = 0;+ DrawParentsFrameTreeLevel( tree, idx );+ }+ else+ {+ TextDisabledUnformatted( "No call stacks to show" );+ }+ break;+ }+ default:+ assert( false );+ break;+ }+ ImGui::EndChild();+ }+ ImGui::End();++ if( !show )+ {+ m_sampleParents.symAddr = 0;+ }+}++}
+ cbits/tracy/profiler/src/profiler/TracyView_Statistics.cpp view
@@ -0,0 +1,986 @@+#include <sstream>++#include "TracyFilesystem.hpp"+#include "TracyImGui.hpp"+#include "TracyPrint.hpp"+#include "TracyView.hpp"+#include "tracy_pdqsort.h"++namespace tracy+{++extern double s_time;++struct SrcLocZonesSlim+{+ int16_t srcloc;+ uint16_t numThreads;+ size_t numZones;+ int64_t total;+};++void View::AccumulationModeComboBox()+{+ ImGui::TextUnformatted( "Timing" );+ ImGui::SameLine();+ const char* accumulationModeTable = m_statMode == 1 ? "Self only\0With children\0" : "Self only\0With children\0Non-reentrant\0";+ ImGui::SetNextItemWidth( ImGui::CalcTextSize( "Non-reentrant" ).x + ImGui::GetTextLineHeight() * 2 );+ if( m_statMode == 1 && m_statAccumulationMode == AccumulationMode::NonReentrantChildren )+ {+ m_statAccumulationMode = AccumulationMode::SelfOnly;+ }+ int accumulationMode = static_cast<int>( m_statAccumulationMode );+ ImGui::Combo( "##accumulationMode", &accumulationMode, accumulationModeTable );+ m_statAccumulationMode = static_cast<AccumulationMode>( accumulationMode );+}++void View::DrawStatistics()+{+ const auto scale = GetScale();+ ImGui::SetNextWindowSize( ImVec2( 1400 * scale, 600 * scale ), ImGuiCond_FirstUseEver );+ ImGui::Begin( "Statistics", &m_showStatistics, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse );+ if( ImGui::GetCurrentWindowRead()->SkipItems ) { ImGui::End(); return; }+#ifdef TRACY_NO_STATISTICS+ ImGui::TextWrapped( "Collection of statistical data is disabled in this build." );+ ImGui::TextWrapped( "Rebuild without the TRACY_NO_STATISTICS macro to enable statistics view." );+#else+ if( !m_worker.AreSourceLocationZonesReady() && ( !m_worker.AreCallstackSamplesReady() || m_worker.GetCallstackSampleCount() == 0 ) )+ {+ const auto ty = ImGui::GetTextLineHeight();+ ImGui::PushFont( m_bigFont );+ ImGui::Dummy( ImVec2( 0, ( ImGui::GetContentRegionAvail().y - ImGui::GetTextLineHeight() * 2 - ty ) * 0.5f ) );+ TextCentered( ICON_FA_HIPPO );+ TextCentered( "Please wait, computing data..." );+ ImGui::PopFont();+ DrawWaitingDots( s_time );+ ImGui::End();+ return;+ }++ Achieve( "instrumentationStatistics" );++ ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 2, 2 ) );+ ImGui::RadioButton( ICON_FA_SYRINGE " Instrumentation", &m_statMode, 0 );+ if( m_worker.AreCallstackSamplesReady() )+ {+ ImGui::SameLine();+ if( m_worker.GetCallstackSampleCount() > 0 )+ {+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::RadioButton( ICON_FA_EYE_DROPPER " Sampling", &m_statMode, 1 );+ }+ else if( m_worker.GetSymbolsCount() > 0 )+ {+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::RadioButton( ICON_FA_PUZZLE_PIECE " Symbols", &m_statMode, 1 );+ }+ }+ if( m_worker.GetGpuZoneCount() > 0 )+ {+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::RadioButton( ICON_FA_EYE " GPU", &m_statMode, 2 );+ }+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::SeparatorEx( ImGuiSeparatorFlags_Vertical );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+++ Vector<SrcLocZonesSlim> srcloc;++ bool copySrclocsToClipboard = false;+ if( m_statMode == 0 )+ {+ if( !m_worker.AreSourceLocationZonesReady() )+ {+ ImGui::Spacing();+ ImGui::Separator();+ ImGui::PopStyleVar();+ ImGui::TextWrapped( "Please wait, computing data..." );+ DrawWaitingDots( s_time );+ ImGui::End();+ return;+ }++ const auto filterActive = m_statisticsFilter.IsActive();+ auto& slz = m_worker.GetSourceLocationZones();+ srcloc.reserve( slz.size() );+ uint32_t slzcnt = 0;+ if( m_statRange.active )+ {+ const auto min = m_statRange.min;+ const auto max = m_statRange.max;+ const auto st = max - min;+ for( auto it = slz.begin(); it != slz.end(); ++it )+ {+ if( it->second.total != 0 && it->second.min <= st )+ {+ if( !filterActive )+ {+ auto cit = m_statCache.find( it->first );+ if( cit != m_statCache.end() && cit->second.range == m_statRange && cit->second.accumulationMode == m_statAccumulationMode && cit->second.sourceCount == it->second.zones.size() )+ {+ if( cit->second.count != 0 )+ {+ slzcnt++;+ srcloc.push_back_no_space_check( SrcLocZonesSlim { it->first, cit->second.threadNum, cit->second.count, cit->second.total } );+ }+ }+ else+ {+ unordered_flat_set<uint16_t> threads;+ size_t cnt = 0;+ int64_t total = 0;+ for( auto& v : it->second.zones )+ {+ auto& z = *v.Zone();+ const auto start = z.Start();+ const auto end = z.End();+ if( start >= min && end <= max )+ {+ const auto zt = end - start;+ if( m_statAccumulationMode == AccumulationMode::SelfOnly )+ {+ total += zt - GetZoneChildTimeFast( z );+ cnt++;+ threads.emplace( v.Thread() );+ }+ else if( m_statAccumulationMode == AccumulationMode::AllChildren || !IsZoneReentry( z ) )+ {+ total += zt;+ cnt++;+ threads.emplace( v.Thread() );+ }+ }+ }+ const auto threadNum = (uint16_t)threads.size();+ if( cnt != 0 )+ {+ slzcnt++;+ srcloc.push_back_no_space_check( SrcLocZonesSlim { it->first, threadNum, cnt, total } );+ }+ m_statCache[it->first] = StatisticsCache { RangeSlim { m_statRange.min, m_statRange.max, m_statRange.active }, m_statAccumulationMode, it->second.zones.size(), cnt, total, threadNum };+ }+ }+ else+ {+ slzcnt++;+ auto& sl = m_worker.GetSourceLocation( it->first );+ auto name = m_worker.GetString( sl.name.active ? sl.name : sl.function );+ if( m_statisticsFilter.PassFilter( name ) )+ {+ auto cit = m_statCache.find( it->first );+ if( cit != m_statCache.end() && cit->second.range == m_statRange && cit->second.accumulationMode == m_statAccumulationMode && cit->second.sourceCount == it->second.zones.size() )+ {+ if( cit->second.count != 0 )+ {+ srcloc.push_back_no_space_check( SrcLocZonesSlim { it->first, cit->second.threadNum, cit->second.count, cit->second.total } );+ }+ }+ else+ {+ unordered_flat_set<uint16_t> threads;+ size_t cnt = 0;+ int64_t total = 0;+ for( auto& v : it->second.zones )+ {+ auto& z = *v.Zone();+ const auto start = z.Start();+ const auto end = z.End();+ if( start >= min && end <= max )+ {+ const auto zt = end - start;+ if( m_statAccumulationMode == AccumulationMode::SelfOnly )+ {+ total += zt - GetZoneChildTimeFast( z );+ cnt++;+ threads.emplace( v.Thread() );+ }+ else if( m_statAccumulationMode == AccumulationMode::AllChildren || !IsZoneReentry( z ) )+ {+ total += zt;+ cnt++;+ threads.emplace( v.Thread() );+ }+ }+ }+ const auto threadNum = (uint16_t)threads.size();+ if( cnt != 0 )+ {+ srcloc.push_back_no_space_check( SrcLocZonesSlim { it->first, threadNum, cnt, total } );+ }+ m_statCache[it->first] = StatisticsCache { RangeSlim { m_statRange.min, m_statRange.max, m_statRange.active }, m_statAccumulationMode, it->second.zones.size(), cnt, total, threadNum };+ }+ }+ }+ }+ }+ }+ else+ {+ for( auto it = slz.begin(); it != slz.end(); ++it )+ {+ if( it->second.total != 0 )+ {+ slzcnt++;+ size_t count;+ int64_t total;+ switch( m_statAccumulationMode )+ {+ case AccumulationMode::SelfOnly:+ count = it->second.zones.size();+ total = it->second.selfTotal;+ break;+ case AccumulationMode::AllChildren:+ count = it->second.zones.size();+ total = it->second.total;+ break;+ case AccumulationMode::NonReentrantChildren:+ count = it->second.nonReentrantCount;+ total = it->second.nonReentrantTotal;+ break;+ }+ if( !filterActive )+ {+ srcloc.push_back_no_space_check( SrcLocZonesSlim { it->first, (uint16_t)it->second.threadCnt.size(), count, total } );+ }+ else+ {+ auto& sl = m_worker.GetSourceLocation( it->first );+ auto name = m_worker.GetString( sl.name.active ? sl.name : sl.function );+ if( m_statisticsFilter.PassFilter( name ) )+ {+ srcloc.push_back_no_space_check( SrcLocZonesSlim { it->first, (uint16_t)it->second.threadCnt.size(), count, total } );+ }+ }+ }+ }+ }++ TextFocused( "Total zone count:", RealToString( slzcnt ) );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ TextFocused( "Visible zones:", RealToString( srcloc.size() ) );+ ImGui::SameLine();+ copySrclocsToClipboard = ClipboardButton();+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ AccumulationModeComboBox();+ }+ else if( m_statMode == 1 )+ {+ ImGui::Checkbox( ICON_FA_STOPWATCH " Show time", &m_statSampleTime );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ if( m_statRange.active )+ {+ ImGui::BeginDisabled();+ m_statAccumulationMode = AccumulationMode::SelfOnly;+ AccumulationModeComboBox();+ ImGui::EndDisabled();+ }+ else+ {+ AccumulationModeComboBox();+ }+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::Checkbox( ICON_FA_EYE_SLASH " Hide unknown", &m_statHideUnknown );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::Checkbox( ICON_FA_PUZZLE_PIECE " Show all", &m_showAllSymbols );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::Checkbox( ICON_FA_SITEMAP " Inlines", &m_statSeparateInlines );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::Checkbox( ICON_FA_AT " Address", &m_statShowAddress );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::TextUnformatted( "Location:" );+ ImGui::SameLine();+ const char* locationTable = "Entry\0Sample\0Smart\0";+ ImGui::SetNextItemWidth( ImGui::CalcTextSize( "Sample" ).x + ImGui::GetTextLineHeight() * 2 );+ ImGui::Combo( "##location", &m_statSampleLocation, locationTable );+ }+ else+ {+ assert( m_statMode == 2 );+ if( !m_worker.AreGpuSourceLocationZonesReady() )+ {+ ImGui::Spacing();+ ImGui::Separator();+ ImGui::PopStyleVar();+ ImGui::TextWrapped( "Please wait, computing data..." );+ DrawWaitingDots( s_time );+ ImGui::End();+ return;+ }++ const auto filterActive = m_statisticsFilter.IsActive();+ auto& slz = m_worker.GetGpuSourceLocationZones();+ srcloc.reserve( slz.size() );+ uint32_t slzcnt = 0;+ if( m_statRange.active )+ {+ const auto min = m_statRange.min;+ const auto max = m_statRange.max;+ const auto st = max - min;+ for( auto it = slz.begin(); it != slz.end(); ++it )+ {+ if( it->second.total != 0 && it->second.min <= st )+ {+ if( !filterActive )+ {+ auto cit = m_gpuStatCache.find( it->first );+ if( cit != m_gpuStatCache.end() && cit->second.range == m_statRange && cit->second.accumulationMode == m_statAccumulationMode && cit->second.sourceCount == it->second.zones.size() )+ {+ if( cit->second.count != 0 )+ {+ slzcnt++;+ srcloc.push_back_no_space_check( SrcLocZonesSlim { it->first, 0, cit->second.count, cit->second.total } );+ }+ }+ else+ {+ size_t cnt = 0;+ int64_t total = 0;+ for( auto& v : it->second.zones )+ {+ auto& z = *v.Zone();+ const auto start = z.GpuStart();+ const auto end = z.GpuEnd();+ if( start >= min && end <= max )+ {+ const auto zt = end - start;+ total += zt;+ cnt++;+ }+ }+ if( cnt != 0 )+ {+ slzcnt++;+ srcloc.push_back_no_space_check( SrcLocZonesSlim { it->first, 0, cnt, total } );+ }+ m_gpuStatCache[it->first] = StatisticsCache { RangeSlim { m_statRange.min, m_statRange.max, m_statRange.active }, m_statAccumulationMode, it->second.zones.size(), cnt, total };+ }+ }+ else+ {+ slzcnt++;+ auto& sl = m_worker.GetSourceLocation( it->first );+ auto name = m_worker.GetString( sl.name.active ? sl.name : sl.function );+ if( m_statisticsFilter.PassFilter( name ) )+ {+ auto cit = m_gpuStatCache.find( it->first );+ if( cit != m_gpuStatCache.end() && cit->second.range == m_statRange && cit->second.accumulationMode == m_statAccumulationMode && cit->second.sourceCount == it->second.zones.size() )+ {+ if( cit->second.count != 0 )+ {+ srcloc.push_back_no_space_check( SrcLocZonesSlim { it->first, 0, cit->second.count, cit->second.total } );+ }+ }+ else+ {+ size_t cnt = 0;+ int64_t total = 0;+ for( auto& v : it->second.zones )+ {+ auto& z = *v.Zone();+ const auto start = z.GpuStart();+ const auto end = z.GpuEnd();+ if( start >= min && end <= max )+ {+ const auto zt = end - start;+ total += zt;+ cnt++;+ }+ }+ if( cnt != 0 )+ {+ srcloc.push_back_no_space_check( SrcLocZonesSlim { it->first, 0, cnt, total } );+ }+ m_gpuStatCache[it->first] = StatisticsCache { RangeSlim { m_statRange.min, m_statRange.max, m_statRange.active }, m_statAccumulationMode, it->second.zones.size(), cnt, total };+ }+ }+ }+ }+ }+ }+ else+ {+ for( auto it = slz.begin(); it != slz.end(); ++it )+ {+ if( it->second.total != 0 )+ {+ slzcnt++;+ size_t count = it->second.zones.size();+ int64_t total = it->second.total;+ if( !filterActive )+ {+ srcloc.push_back_no_space_check( SrcLocZonesSlim { it->first, 0, count, total } );+ }+ else+ {+ auto& sl = m_worker.GetSourceLocation( it->first );+ auto name = m_worker.GetString( sl.name.active ? sl.name : sl.function );+ if( m_statisticsFilter.PassFilter( name ) )+ {+ srcloc.push_back_no_space_check( SrcLocZonesSlim { it->first, 0, count, total } );+ }+ }+ }+ }+ }++ TextFocused( "Total zone count:", RealToString( slzcnt ) );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ TextFocused( "Visible zones:", RealToString( srcloc.size() ) );+ ImGui::SameLine();+ copySrclocsToClipboard = ClipboardButton();+ }++ ImGui::Separator();+ ImGui::AlignTextToFramePadding();+ TextDisabledUnformatted( "Name" );+ ImGui::SameLine();+ m_statisticsFilter.Draw( ICON_FA_FILTER "###resultFilter", 200 );+ ImGui::SameLine();+ if( ImGui::Button( ICON_FA_DELETE_LEFT " Clear" ) )+ {+ m_statisticsFilter.Clear();+ }+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ if( m_statMode == 1 )+ {+ TextDisabledUnformatted( "Image" );+ ImGui::SameLine();+ ToggleButton( ICON_FA_SCISSORS, m_shortImageNames );+ ImGui::SameLine();+ m_statisticsImageFilter.Draw( ICON_FA_FILTER "###imageFilter", 200 );+ ImGui::SameLine();+ if( ImGui::BeginCombo( "###imageCombo", nullptr, ImGuiComboFlags_NoPreview | ImGuiComboFlags_HeightLarge ) )+ {+ unordered_flat_set<StringIdx, StringIdxHasher, StringIdxComparator> set;+ std::vector<const char*> imgNames;+ for( auto& v : m_worker.GetSymbolMap() )+ {+ auto it = set.find( v.second.imageName );+ if( it == set.end() )+ {+ set.emplace( v.second.imageName );+ }+ }+ imgNames.reserve( set.size() );+ for( auto& img : set )+ {+ imgNames.emplace_back( m_worker.GetString( img ) );+ }+ pdqsort_branchless( imgNames.begin(), imgNames.end(), [] ( const auto& lhs, const auto& rhs ) { return strcmp( lhs, rhs ) < 0; } );+ for( auto& img : imgNames )+ {+ bool sel = false;+ if( ImGui::Selectable( img, &sel ) )+ {+ auto len = std::min<size_t>( 255, strlen( img ) );+ memcpy( m_statisticsImageFilter.InputBuf, img, len );+ m_statisticsImageFilter.InputBuf[len] = 0;+ m_statisticsImageFilter.Build();+ }+ }+ ImGui::EndCombo();+ }+ ImGui::SameLine();+ if( ImGui::Button( ICON_FA_DELETE_LEFT " Clear###image" ) )+ {+ m_statisticsImageFilter.Clear();+ }+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::Checkbox( ICON_FA_HAT_WIZARD " Include kernel", &m_statShowKernel );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ }+ if( m_statMode == 1 && !m_worker.AreSymbolSamplesReady() )+ {+ m_statRange.active = false;+ bool val = false;+ ImGui::PushItemFlag( ImGuiItemFlags_Disabled, true );+ ImGui::PushStyleVar( ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f );+ ImGui::Checkbox( "Limit range", &val );+ ImGui::PopItemFlag();+ ImGui::PopStyleVar();+ TooltipIfHovered( "Waiting for background tasks to finish" );+ }+ else+ {+ if( ImGui::Checkbox( "Limit range", &m_statRange.active ) )+ {+ if( m_statRange.active && m_statRange.min == 0 && m_statRange.max == 0 )+ {+ m_statRange.min = m_vd.zvStart;+ m_statRange.max = m_vd.zvEnd;+ }+ }+ if( m_statRange.active )+ {+ ImGui::SameLine();+ TextColoredUnformatted( 0xFF00FFFF, ICON_FA_TRIANGLE_EXCLAMATION );+ ImGui::SameLine();+ ToggleButton( ICON_FA_RULER " Limits", m_showRanges );+ }+ }++ if( m_statMode == 1 )+ {+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::SeparatorEx( ImGuiSeparatorFlags_Vertical );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ if( m_statSeparateInlines ) ImGui::BeginDisabled();+ ImGui::TextUnformatted( "Inlines" );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::Checkbox( ICON_FA_LAYER_GROUP " Aggregate", &m_mergeInlines );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::Checkbox( ICON_FA_LINK " Base relative", &m_relativeInlines );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::Checkbox( ICON_FA_FIRE " Top inline", &m_topInline );+ if( m_statSeparateInlines ) ImGui::EndDisabled();+ }++ ImGui::Separator();+ ImGui::PopStyleVar();++ int64_t timeRange;+ if( m_statRange.active )+ {+ const auto st = m_statRange.max - m_statRange.min;+ timeRange = st == 0 ? 1 : st;+ }+ else+ {+ timeRange = m_worker.GetLastTime() - m_worker.GetFirstTime();+ }++ if( m_statMode == 0 || m_statMode == 2 )+ {+ if( srcloc.empty() )+ {+ ImGui::PushFont( m_bigFont );+ ImGui::Dummy( ImVec2( 0, ( ImGui::GetContentRegionAvail().y - ImGui::GetTextLineHeight() * 2 ) * 0.5f ) );+ TextCentered( ICON_FA_HIPPO );+ TextCentered( "No entries to be displayed" );+ ImGui::PopFont();+ }+ else+ {+ ImGui::BeginChild( "##statistics" );+ if( ImGui::BeginTable( "##statistics", m_statMode == 0 ? 6 : 5,+ ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Sortable | ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_ScrollY ) )+ {+ ImGui::TableSetupScrollFreeze( 0, 1 );+ ImGui::TableSetupColumn( "Name", ImGuiTableColumnFlags_NoHide );+ ImGui::TableSetupColumn( "Location" );+ ImGui::TableSetupColumn( "Total time", ImGuiTableColumnFlags_DefaultSort | ImGuiTableColumnFlags_PreferSortDescending | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize );+ ImGui::TableSetupColumn( "Counts", ImGuiTableColumnFlags_PreferSortDescending | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize );+ ImGui::TableSetupColumn( "MTPC", ImGuiTableColumnFlags_PreferSortDescending | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize );+ if( m_statMode == 0 ) ImGui::TableSetupColumn( ICON_FA_SHUFFLE, ImGuiTableColumnFlags_DefaultSort | ImGuiTableColumnFlags_PreferSortDescending | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize );+ ImGui::TableHeadersRow();++ const auto& sortspec = *ImGui::TableGetSortSpecs()->Specs;+ switch( sortspec.ColumnIndex )+ {+ case 0:+ if( sortspec.SortDirection == ImGuiSortDirection_Ascending )+ {+ pdqsort_branchless( srcloc.begin(), srcloc.end(), [this]( const auto& lhs, const auto& rhs ) { return strcmp( m_worker.GetZoneName( m_worker.GetSourceLocation( lhs.srcloc ) ), m_worker.GetZoneName( m_worker.GetSourceLocation( rhs.srcloc ) ) ) < 0; } );+ }+ else+ {+ pdqsort_branchless( srcloc.begin(), srcloc.end(), [this]( const auto& lhs, const auto& rhs ) { return strcmp( m_worker.GetZoneName( m_worker.GetSourceLocation( lhs.srcloc ) ), m_worker.GetZoneName( m_worker.GetSourceLocation( rhs.srcloc ) ) ) > 0; } );+ }+ break;+ case 1:+ if( sortspec.SortDirection == ImGuiSortDirection_Ascending )+ {+ pdqsort_branchless( srcloc.begin(), srcloc.end(), [this]( const auto& lhs, const auto& rhs ) {+ const auto& sll = m_worker.GetSourceLocation( lhs.srcloc );+ const auto& slr = m_worker.GetSourceLocation( rhs.srcloc );+ const auto cmp = strcmp( m_worker.GetString( sll.file ), m_worker.GetString( slr.file ) );+ if( cmp == 0 ) return sll.line < slr.line;+ return cmp < 0;+ } );+ }+ else+ {+ pdqsort_branchless( srcloc.begin(), srcloc.end(), [this]( const auto& lhs, const auto& rhs ) {+ const auto& sll = m_worker.GetSourceLocation( lhs.srcloc );+ const auto& slr = m_worker.GetSourceLocation( rhs.srcloc );+ const auto cmp = strcmp( m_worker.GetString( sll.file ), m_worker.GetString( slr.file ) );+ if( cmp == 0 ) return sll.line > slr.line;+ return cmp > 0;+ } );+ }+ break;+ case 2:+ if( sortspec.SortDirection == ImGuiSortDirection_Ascending )+ {+ pdqsort_branchless( srcloc.begin(), srcloc.end(), []( const auto& lhs, const auto& rhs ) { return lhs.total < rhs.total; } );+ }+ else+ {+ pdqsort_branchless( srcloc.begin(), srcloc.end(), []( const auto& lhs, const auto& rhs ) { return lhs.total > rhs.total; } );+ }+ break;+ case 3:+ if( sortspec.SortDirection == ImGuiSortDirection_Ascending )+ {+ pdqsort_branchless( srcloc.begin(), srcloc.end(), []( const auto& lhs, const auto& rhs ) { return lhs.numZones < rhs.numZones; } );+ }+ else+ {+ pdqsort_branchless( srcloc.begin(), srcloc.end(), []( const auto& lhs, const auto& rhs ) { return lhs.numZones > rhs.numZones; } );+ }+ break;+ case 4:+ if( sortspec.SortDirection == ImGuiSortDirection_Ascending )+ {+ pdqsort_branchless( srcloc.begin(), srcloc.end(), []( const auto& lhs, const auto& rhs ) { return lhs.total / lhs.numZones < rhs.total / rhs.numZones; } );+ }+ else+ {+ pdqsort_branchless( srcloc.begin(), srcloc.end(), []( const auto& lhs, const auto& rhs ) { return lhs.total / lhs.numZones > rhs.total / rhs.numZones; } );+ }+ break;+ case 5:+ if( sortspec.SortDirection == ImGuiSortDirection_Ascending )+ {+ pdqsort_branchless( srcloc.begin(), srcloc.end(), []( const auto& lhs, const auto& rhs ) { return lhs.numThreads < rhs.numThreads; } );+ }+ else+ {+ pdqsort_branchless( srcloc.begin(), srcloc.end(), []( const auto& lhs, const auto& rhs ) { return lhs.numThreads > rhs.numThreads; } );+ }+ break;+ default:+ assert( false );+ break;+ }++ std::ostringstream clipboardCSV;+ if( copySrclocsToClipboard )+ {+ clipboardCSV << "name" << ',' << "src_file" << ',' << "src_line" << ',' << "total_ns" << ',' << "counts" << "\n";+ }++ for( auto& v : srcloc )+ {+ ImGui::TableNextRow();+ ImGui::TableNextColumn();++ ImGui::PushID( v.srcloc );+ auto& srcloc = m_worker.GetSourceLocation( v.srcloc );+ auto name = m_worker.GetString( srcloc.name.active ? srcloc.name : srcloc.function );+ SmallColorBox( GetSrcLocColor( srcloc, 0 ) );+ ImGui::SameLine();+ if( m_statMode == 0 )+ {+ if( ImGui::Selectable( name, m_findZone.show && !m_findZone.match.empty() && m_findZone.match[m_findZone.selMatch] == v.srcloc, ImGuiSelectableFlags_SpanAllColumns ) )+ {+ m_findZone.ShowZone( v.srcloc, name );+ }+ }+ else+ {+ ImGui::TextUnformatted( name );+ }+ ImGui::TableNextColumn();+ float indentVal = 0.f;+ if( m_statBuzzAnim.Match( v.srcloc ) )+ {+ const auto time = m_statBuzzAnim.Time();+ indentVal = sin( time * 60.f ) * 10.f * time;+ ImGui::Indent( indentVal );+ }+ const auto file = m_worker.GetString( srcloc.file );++ TextDisabledUnformatted( LocationToString( file, srcloc.line ) );+ if( ImGui::IsItemHovered() )+ {+ DrawSourceTooltip( file, srcloc.line );+ if( ImGui::IsItemClicked( 1 ) )+ {+ if( SourceFileValid( file, m_worker.GetCaptureTime(), *this, m_worker ) )+ {+ ViewSourceCheckKeyMod( file, srcloc.line, m_worker.GetString( srcloc.function ) );+ }+ else+ {+ m_statBuzzAnim.Enable( v.srcloc, 0.5f );+ }+ }+ }+ if( indentVal != 0.f )+ {+ ImGui::Unindent( indentVal );+ }+ ImGui::TableNextColumn();+ const auto time = v.total;+ ImGui::TextUnformatted( TimeToString( time ) );+ ImGui::SameLine();+ char buf[64];+ PrintStringPercent( buf, 100. * time / timeRange );+ TextDisabledUnformatted( buf );+ ImGui::TableNextColumn();+ ImGui::TextUnformatted( RealToString( v.numZones ) );+ ImGui::TableNextColumn();+ ImGui::TextUnformatted( TimeToString( time / v.numZones ) );+ if( m_statMode == 0 )+ {+ ImGui::TableNextColumn();+ ImGui::TextUnformatted( RealToString( v.numThreads ) );+ }+ ImGui::PopID();++ if( copySrclocsToClipboard )+ {+ clipboardCSV << name << ',' << file << ',' << srcloc.line << ',' << v.total << ',' << v.numZones << '\n';+ }+ }+ ImGui::EndTable();++ if( copySrclocsToClipboard )+ {+ std::string clipboardCSVString = clipboardCSV.str();+ ImGui::SetClipboardText( clipboardCSVString.c_str() );+ }+ }+ ImGui::EndChild();+ }+ }+ else+ {+ assert( m_statMode == 1 );+ const auto& symMap = m_worker.GetSymbolMap();+ const auto& symStat = m_worker.GetSymbolStats();++ Vector<SymList> data;+ if( m_showAllSymbols )+ {+ data.reserve( symMap.size() );+ if( m_statisticsFilter.IsActive() || m_statisticsImageFilter.IsActive() || !m_statShowKernel )+ {+ for( auto& v : symMap )+ {+ const auto name = m_worker.GetString( v.second.name );+ const auto image = m_worker.GetString( v.second.imageName );+ bool pass = ( m_statShowKernel || ( v.first >> 63 ) == 0 ) && m_statisticsFilter.PassFilter( name ) && m_statisticsImageFilter.PassFilter( image );+ if( !pass && v.second.size.Val() == 0 )+ {+ const auto parentAddr = m_worker.GetSymbolForAddress( v.first );+ if( parentAddr != 0 )+ {+ auto pit = symMap.find( parentAddr );+ if( pit != symMap.end() )+ {+ const auto parentName = m_worker.GetString( pit->second.name );+ pass = ( m_statShowKernel || ( parentAddr >> 63 ) == 0 ) && m_statisticsFilter.PassFilter( parentName ) && m_statisticsImageFilter.PassFilter( image );+ }+ }+ }+ if( pass )+ {+ auto it = symStat.find( v.first );+ if( it == symStat.end() )+ {+ data.push_back_no_space_check( SymList { v.first, 0, 0 } );+ }+ else+ {+ if( m_statRange.active )+ {+ auto samples = m_worker.GetSamplesForSymbol( v.first );+ if( samples )+ {+ auto it = std::lower_bound( samples->begin(), samples->end(), m_statRange.min, [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs; } );+ if( it != samples->end() )+ {+ auto end = std::lower_bound( it, samples->end(), m_statRange.max, [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs; } );+ const auto count = uint32_t( end - it );+ data.push_back_no_space_check( SymList { v.first, 0, count } );+ }+ else+ {+ data.push_back_no_space_check( SymList { v.first, 0, 0 } );+ }+ }+ else+ {+ data.push_back_no_space_check( SymList { v.first, 0, 0 } );+ }+ }+ else+ {+ data.push_back_no_space_check( SymList { v.first, it->second.incl, it->second.excl } );+ }+ }+ }+ }+ }+ else+ {+ for( auto& v : symMap )+ {+ auto it = symStat.find( v.first );+ if( it == symStat.end() )+ {+ data.push_back_no_space_check( SymList { v.first, 0, 0 } );+ }+ else+ {+ if( m_statRange.active )+ {+ auto samples = m_worker.GetSamplesForSymbol( v.first );+ if( samples )+ {+ auto it = std::lower_bound( samples->begin(), samples->end(), m_statRange.min, [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs; } );+ if( it != samples->end() )+ {+ auto end = std::lower_bound( it, samples->end(), m_statRange.max, [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs; } );+ const auto count = uint32_t( end - it );+ data.push_back_no_space_check( SymList { v.first, 0, count } );+ }+ else+ {+ data.push_back_no_space_check( SymList { v.first, 0, 0 } );+ }+ }+ else+ {+ data.push_back_no_space_check( SymList { v.first, 0, 0 } );+ }+ }+ else+ {+ data.push_back_no_space_check( SymList { v.first, it->second.incl, it->second.excl } );+ }+ }+ }+ }+ }+ else+ {+ data.reserve( symStat.size() );+ if( m_statisticsFilter.IsActive() || m_statisticsImageFilter.IsActive() || !m_statShowKernel )+ {+ for( auto& v : symStat )+ {+ auto sit = symMap.find( v.first );+ if( sit != symMap.end() )+ {+ const auto name = m_worker.GetString( sit->second.name );+ const auto image = m_worker.GetString( sit->second.imageName );+ bool pass = ( m_statShowKernel || ( v.first >> 63 ) == 0 ) && m_statisticsFilter.PassFilter( name ) && m_statisticsImageFilter.PassFilter( image );+ if( !pass && sit->second.size.Val() == 0 )+ {+ const auto parentAddr = m_worker.GetSymbolForAddress( v.first );+ if( parentAddr != 0 )+ {+ auto pit = symMap.find( parentAddr );+ if( pit != symMap.end() )+ {+ const auto parentName = m_worker.GetString( pit->second.name );+ pass = ( m_statShowKernel || ( parentAddr >> 63 ) == 0 ) && m_statisticsFilter.PassFilter( parentName ) && m_statisticsImageFilter.PassFilter( image );+ }+ }+ }+ if( pass )+ {+ if( m_statRange.active )+ {+ auto samples = m_worker.GetSamplesForSymbol( v.first );+ if( samples )+ {+ auto it = std::lower_bound( samples->begin(), samples->end(), m_statRange.min, [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs; } );+ if( it != samples->end() )+ {+ auto end = std::lower_bound( it, samples->end(), m_statRange.max, [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs; } );+ const auto count = uint32_t( end - it );+ data.push_back_no_space_check( SymList { v.first, 0, count } );+ }+ }+ }+ else+ {+ data.push_back_no_space_check( SymList { v.first, v.second.incl, v.second.excl } );+ }+ }+ }+ }+ }+ else+ {+ if( m_statRange.active )+ {+ for( auto& v : symStat )+ {+ auto samples = m_worker.GetSamplesForSymbol( v.first );+ if( samples )+ {+ auto it = std::lower_bound( samples->begin(), samples->end(), m_statRange.min, [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs; } );+ if( it != samples->end() )+ {+ auto end = std::lower_bound( it, samples->end(), m_statRange.max, [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs; } );+ const auto count = uint32_t( end - it );+ data.push_back_no_space_check( SymList { v.first, 0, count } );+ }+ }+ }+ }+ else+ {+ for( auto& v : symStat )+ {+ data.push_back_no_space_check( SymList { v.first, v.second.incl, v.second.excl } );+ }+ }+ }+ }++ DrawSamplesStatistics( data, timeRange, m_statAccumulationMode );+ }+#endif+ ImGui::End();+}++}
+ cbits/tracy/profiler/src/profiler/TracyView_Timeline.cpp view
@@ -0,0 +1,561 @@+#include <algorithm>++#include "TracyImGui.hpp"+#include "TracyMouse.hpp"+#include "TracyPrint.hpp"+#include "TracySourceView.hpp"+#include "TracyTimelineItemCpuData.hpp"+#include "TracyTimelineItemGpu.hpp"+#include "TracyTimelineItemPlot.hpp"+#include "TracyTimelineItemThread.hpp"+#include "TracyView.hpp"++namespace tracy+{++extern double s_time;++void View::HandleTimelineMouse( int64_t timespan, const ImVec2& wpos, float w )+{+ assert( timespan > 0 );+ auto& io = ImGui::GetIO();++ const auto nspx = double( timespan ) / w;++ if( IsMouseClicked( 0 ) )+ {+ m_highlight.active = true;+ m_highlight.start = m_highlight.end = m_vd.zvStart + ( io.MousePos.x - wpos.x ) * nspx;+ }+ else if( IsMouseDragging( 0 ) )+ {+ m_highlight.end = m_vd.zvStart + ( io.MousePos.x - wpos.x ) * nspx;+ }+ else if( m_highlight.active && !IsMouseDown( 0 ) )+ {+ if( ImGui::GetIO().KeyCtrl && m_highlight.start != m_highlight.end )+ {+ m_setRangePopup = RangeSlim { m_highlight.start, m_highlight.end, true };+ }+ m_highlight.active = false;+ }++ if( IsMouseClicked( 2 ) )+ {+ m_highlightZoom.active = true;+ m_highlightZoom.start = m_highlightZoom.end = m_vd.zvStart + ( io.MousePos.x - wpos.x ) * nspx;+ }+ else if( IsMouseDragging( 2 ) )+ {+ m_highlightZoom.end = m_vd.zvStart + ( io.MousePos.x - wpos.x ) * nspx;+ }+ else if( m_highlightZoom.active && !IsMouseDown( 2 ) )+ {+ if( m_highlightZoom.start != m_highlightZoom.end )+ {+ const auto s = std::min( m_highlightZoom.start, m_highlightZoom.end );+ const auto e = std::max( m_highlightZoom.start, m_highlightZoom.end );++ // ZoomToRange disables m_highlightZoom.active+ if( io.KeyCtrl )+ {+ const auto tsOld = m_vd.zvEnd - m_vd.zvStart;+ const auto tsNew = e - s;+ const auto mul = double( tsOld ) / tsNew;+ const auto left = s - m_vd.zvStart;+ const auto right = m_vd.zvEnd - e;++ auto start = m_vd.zvStart - left * mul;+ auto end = m_vd.zvEnd + right * mul;+ if( end - start > 1000ll * 1000 * 1000 * 60 * 60 * 24 * 10 )+ {+ start = -1000ll * 1000 * 1000 * 60 * 60 * 24 * 5;+ end = 1000ll * 1000 * 1000 * 60 * 60 * 24 * 5;+ }++ ZoomToRange( start, end );+ }+ else+ {+ ZoomToRange( s, e );+ }+ }+ else+ {+ m_highlightZoom.active = false;+ }+ }++ const auto hwheel_delta = io.MouseWheelH * 100.f * m_horizontalScrollMultiplier;+ if( IsMouseDragging( 1 ) || hwheel_delta != 0 )+ {+ m_viewMode = ViewMode::Paused;+ m_viewModeHeuristicTry = false;+ m_zoomAnim.active = false;+ if( !m_playback.pause && m_playback.sync ) m_playback.pause = true;+ const auto delta = GetMouseDragDelta( 1 );+ m_yDelta = delta.y;+ const auto dpx = int64_t( (delta.x * nspx) + (hwheel_delta * nspx));+ if( dpx != 0 )+ {+ m_vd.zvStart -= dpx;+ m_vd.zvEnd -= dpx;+ io.MouseClickedPos[1].x = io.MousePos.x;++ if( m_vd.zvStart < -1000ll * 1000 * 1000 * 60 * 60 * 24 * 5 )+ {+ const auto range = m_vd.zvEnd - m_vd.zvStart;+ m_vd.zvStart = -1000ll * 1000 * 1000 * 60 * 60 * 24 * 5;+ m_vd.zvEnd = m_vd.zvStart + range;+ }+ else if( m_vd.zvEnd > 1000ll * 1000 * 1000 * 60 * 60 * 24 * 5 )+ {+ const auto range = m_vd.zvEnd - m_vd.zvStart;+ m_vd.zvEnd = 1000ll * 1000 * 1000 * 60 * 60 * 24 * 5;+ m_vd.zvStart = m_vd.zvEnd - range;+ }+ }+ }++ const auto wheel = io.MouseWheel;+ if( wheel != 0 )+ {+ if( m_viewMode == ViewMode::LastFrames ) m_viewMode = ViewMode::LastRange;+ const double mouse = io.MousePos.x - wpos.x;+ const auto p = mouse / w;++ int64_t t0, t1;+ if( m_zoomAnim.active )+ {+ t0 = m_zoomAnim.start1;+ t1 = m_zoomAnim.end1;+ }+ else+ {+ t0 = m_vd.zvStart;+ t1 = m_vd.zvEnd;+ }+ const auto zoomSpan = t1 - t0;+ const auto p1 = zoomSpan * p;+ const auto p2 = zoomSpan - p1;++ double mod = 0.25;+ if( io.KeyCtrl ) mod = 0.05;+ else if( io.KeyShift ) mod = 0.5;++ mod *= m_verticalScrollMultiplier;++ if( wheel > 0 )+ {+ t0 += int64_t( p1 * mod );+ t1 -= int64_t( p2 * mod );+ }+ else if( zoomSpan < 1000ll * 1000 * 1000 * 60 * 60 )+ {+ t0 -= std::max( int64_t( 1 ), int64_t( p1 * mod ) );+ t1 += std::max( int64_t( 1 ), int64_t( p2 * mod ) );+ }+ ZoomToRange( t0, t1, !m_worker.IsConnected() || m_viewMode == ViewMode::Paused );+ }+}++void View::HandleTimelineKeyboard( int64_t timespan, const ImVec2& wpos, float w )+{+ assert( timespan > 0 );+ auto& io = ImGui::GetIO();++ int64_t nextTimelineRangeStart, nextTimelineRangeEnd;+ bool anyDeltaApplied = false;+ if( m_zoomAnim.active )+ {+ nextTimelineRangeStart = m_zoomAnim.start1;+ nextTimelineRangeEnd = m_zoomAnim.end1;+ }+ else+ {+ nextTimelineRangeStart = m_vd.zvStart;+ nextTimelineRangeEnd = m_vd.zvEnd;+ }++ const auto bias = (io.MousePos.x - wpos.x) / w;+ const auto span = nextTimelineRangeEnd - nextTimelineRangeStart;+ // Move at a rate of 1/10th the length of the timeline per second, with a minimum of 500ns+ const auto moveInTimelineNanos = std::max<int64_t>( span / 10, 500 );+ const auto movement = moveInTimelineNanos * std::max( std::min( io.DeltaTime, 0.25f ), 0.016f );++ for( int direction = 0; direction < 4; direction++ )+ {+ auto& inertia = m_kbNavCtrl.m_scrollInertia[direction];++ if( ImGui::IsKeyDown( KeyboardNavigation::DirectionToKeyMap[direction] ) )+ {+ const auto timeStartDelta = movement * KeyboardNavigation::StartRangeMod[direction];+ const auto timeEndDelta = movement * KeyboardNavigation::EndRangeMod[direction];++ // This part is completely arbitrary, designed to work in the range ~ 0 -> 15+ const auto x = inertia / 10.0f;+ const auto mult = 1 + std::max( 0.0, 0.7 * std::pow( x, 1.6 ) - 0.8 * std::pow( x, 1.4 ) );++ // If we are zooming in/out+ if( direction > KeyboardNavigation::Right )+ {+ // Bias if equal is 0.5. Multiply by 2 to offset back to the expected movement range.+ nextTimelineRangeStart += timeStartDelta * mult * 2 * bias;+ nextTimelineRangeEnd += timeEndDelta * mult * 2 * (1 - bias);+ }+ else+ {+ nextTimelineRangeStart += timeStartDelta * mult;+ nextTimelineRangeEnd += timeEndDelta * mult;+ }++ inertia = std::min( 150.0f, inertia + 1 );+ anyDeltaApplied = true;+ }+ else+ {+ inertia = std::max( 0.0f, inertia - 1 );+ }+ }++ if( anyDeltaApplied )+ {+ if( m_viewMode == ViewMode::LastFrames ) m_viewMode = ViewMode::LastRange;+ if( nextTimelineRangeStart > nextTimelineRangeEnd ) return;++ // We want to cap the zoom at the range of values that the timeline has data for+ const auto firstTime = m_worker.GetFirstTime();+ const auto lastTime = m_worker.GetLastTime();++ nextTimelineRangeStart = std::max<int64_t>( std::min( nextTimelineRangeStart, lastTime - 50 ), firstTime );+ nextTimelineRangeEnd = std::max<int64_t>( std::min( nextTimelineRangeEnd, lastTime ), firstTime+1 );++ if( nextTimelineRangeEnd - nextTimelineRangeStart <= 50 ) return;+ const auto shouldPause = m_viewMode == ViewMode::Paused || !m_worker.IsConnected();+ ZoomToRange( nextTimelineRangeStart, nextTimelineRangeEnd, shouldPause );+ }+}+++void View::DrawTimeline()+{+ m_msgHighlight.Decay( nullptr );+ m_zoneSrcLocHighlight.Decay( 0 );+ m_lockHoverHighlight.Decay( InvalidId );++ if( !m_vd.drawCpuData )+ {+ m_selectedThread = 0;+ }+ m_drawThreadMigrations.Decay( 0 );+ m_drawThreadHighlight.Decay( 0 );+ m_cpuDataThread.Decay( 0 );+ m_zoneHover = nullptr;+ m_zoneHover2.Decay( nullptr );+ m_findZone.range.StartFrame();+ m_statRange.StartFrame();+ m_flameRange.StartFrame();+ m_waitStackRange.StartFrame();+ m_memInfo.range.StartFrame();+ m_yDelta = 0;+ m_nextLockHighlight = { -1 };++ if( m_vd.zvStart == m_vd.zvEnd ) return;+ assert( m_vd.zvStart < m_vd.zvEnd );++ if( ImGui::GetCurrentWindowRead()->SkipItems ) return;++ m_gpuThread = 0;+ m_gpuStart = 0;+ m_gpuEnd = 0;++ const auto linepos = ImGui::GetCursorScreenPos();+ const auto lineh = ImGui::GetContentRegionAvail().y;++ auto draw = ImGui::GetWindowDrawList();+ const auto w = ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ScrollbarSize;+ const auto timespan = m_vd.zvEnd - m_vd.zvStart;+ auto pxns = w / double( timespan );++ const auto winpos = ImGui::GetWindowPos();+ const auto winsize = ImGui::GetWindowSize();+ const bool drawMouseLine = ImGui::IsWindowHovered( ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem ) && ImGui::IsMouseHoveringRect( winpos, winpos + winsize, false );+ if( drawMouseLine )+ {+ HandleRange( m_findZone.range, timespan, ImGui::GetCursorScreenPos(), w );+ HandleRange( m_statRange, timespan, ImGui::GetCursorScreenPos(), w );+ HandleRange( m_flameRange, timespan, ImGui::GetCursorScreenPos(), w );+ HandleRange( m_waitStackRange, timespan, ImGui::GetCursorScreenPos(), w );+ HandleRange( m_memInfo.range, timespan, ImGui::GetCursorScreenPos(), w );+ for( auto& v : m_annotations )+ {+ v->range.StartFrame();+ HandleRange( v->range, timespan, ImGui::GetCursorScreenPos(), w );+ }+ HandleTimelineMouse( timespan, ImGui::GetCursorScreenPos(), w );+ }+ if( ImGui::IsWindowFocused( ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem ) )+ {+ HandleTimelineKeyboard( timespan, ImGui::GetCursorScreenPos(), w );+ }++ {+ const auto tbegin = m_worker.GetFirstTime();+ const auto tend = m_worker.GetLastTime();+ if( tbegin > m_vd.zvStart )+ {+ draw->AddRectFilled( linepos, linepos + ImVec2( ( tbegin - m_vd.zvStart ) * pxns, lineh ), 0x44000000 );+ }+ if( tend < m_vd.zvEnd )+ {+ draw->AddRectFilled( linepos + ImVec2( ( tend - m_vd.zvStart ) * pxns, 0 ), linepos + ImVec2( w, lineh ), 0x44000000 );+ }+ }++ m_tc.Begin();+ DrawTimelineFramesHeader();+ if( m_worker.AreFramesUsed() )+ {+ auto& frames = m_worker.GetFrames();+ for( auto fd : frames )+ {+ if( Vis( fd ) )+ {+ DrawTimelineFrames( *fd );+ }+ }+ }++ const auto yMin = ImGui::GetCursorScreenPos().y;+ const auto yMax = linepos.y + lineh;++ ImGui::SetNextWindowContentSize( ImVec2( 0, m_tc.GetHeight() ) );+ ImGui::BeginChild( "##zoneWin", ImVec2( ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y ), false, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_NoScrollWithMouse );++ const auto verticallyCenterTimeline = true;++ if( m_yDelta != 0 )+ {+ auto& io = ImGui::GetIO();+ if( !verticallyCenterTimeline )+ {+ auto y = ImGui::GetScrollY();+ ImGui::SetScrollY( y - m_yDelta );+ }+ io.MouseClickedPos[1].y = io.MousePos.y;+ }++ const auto wpos = ImGui::GetCursorScreenPos();+ const auto dpos = wpos + ImVec2( 0.5f, 0.5f );+ const auto h = std::max<float>( m_tc.GetHeight(), ImGui::GetContentRegionAvail().y - 4 ); // magic border value++ ImGui::ItemSize( ImVec2( w, h ) );+ bool hover = ImGui::IsWindowHovered() && ImGui::IsMouseHoveringRect( wpos, wpos + ImVec2( w, h ) );+ draw = ImGui::GetWindowDrawList();++ const auto ty = ImGui::GetTextLineHeight();+ const auto to = 9.f;+ const auto th = ( ty - to ) * sqrt( 3 ) * 0.5;++ if( m_vd.drawGpuZones )+ {+ for( auto& v : m_worker.GetGpuData() )+ {+ m_tc.AddItem<TimelineItemGpu>( v );+ }+ }+ if( m_vd.drawCpuData && m_worker.HasContextSwitches() )+ {+ static char uptr;+ m_tc.AddItem<TimelineItemCpuData>( &uptr );+ }+ if( m_vd.drawZones )+ {+ const auto& threadData = m_worker.GetThreadData();+ if( threadData.size() != m_threadOrder.size() )+ {+ m_threadOrder.reserve( threadData.size() );+ // Only new threads are in the end of the worker's ThreadData vector.+ // Threads which get reordered by received thread hints are not new, yet removed from m_threadOrder.+ // Therefore, those are kept in the m_threadReinsert vector. As such, we will gather first threads from the+ // reinsert vector, and afterwards the remaining ones must be new (and thus found at the end of threadData).+ size_t numReinsert = m_threadReinsert.size();+ size_t numNew = threadData.size() - m_threadOrder.size() - numReinsert;+ for( size_t i = 0; i < numReinsert + numNew; i++ )+ {+ const ThreadData *td = i < numReinsert ? m_threadReinsert[i] : threadData[m_threadOrder.size()];+ auto it = std::find_if( m_threadOrder.begin(), m_threadOrder.end(), [td]( const auto t ) { return td->groupHint < t->groupHint; } );+ m_threadOrder.insert( it, td );+ }+ m_threadReinsert.clear();+ }+ for( const auto& v : m_threadOrder )+ {+ m_tc.AddItem<TimelineItemThread>( v );+ }+ }+ if( m_vd.drawPlots )+ {+ for( const auto& v : m_worker.GetPlots() )+ {+ m_tc.AddItem<TimelineItemPlot>( v );+ }+ }++ const auto vcenter = verticallyCenterTimeline && drawMouseLine && m_viewMode == ViewMode::Paused;+ m_tc.End( pxns, wpos, hover, vcenter, yMin, yMax, m_smallFont );+ ImGui::EndChild();++ m_lockHighlight = m_nextLockHighlight;++ for( auto& ann : m_annotations )+ {+ if( ann->range.min < m_vd.zvEnd && ann->range.max > m_vd.zvStart )+ {+ uint32_t c0 = ( ann->color & 0xFFFFFF ) | ( m_selectedAnnotation == ann.get() ? 0x44000000 : 0x22000000 );+ uint32_t c1 = ( ann->color & 0xFFFFFF ) | ( m_selectedAnnotation == ann.get() ? 0x66000000 : 0x44000000 );+ uint32_t c2 = ( ann->color & 0xFFFFFF ) | ( m_selectedAnnotation == ann.get() ? 0xCC000000 : 0xAA000000 );+ draw->AddRectFilled( linepos + ImVec2( ( ann->range.min - m_vd.zvStart ) * pxns, 0 ), linepos + ImVec2( ( ann->range.max - m_vd.zvStart ) * pxns, lineh ), c0 );+ DrawLine( draw, linepos + ImVec2( ( ann->range.min - m_vd.zvStart ) * pxns + 0.5f, 0.5f ), linepos + ImVec2( ( ann->range.min - m_vd.zvStart ) * pxns + 0.5f, lineh + 0.5f ), ann->range.hiMin ? c2 : c1, ann->range.hiMin ? 2 : 1 );+ DrawLine( draw, linepos + ImVec2( ( ann->range.max - m_vd.zvStart ) * pxns + 0.5f, 0.5f ), linepos + ImVec2( ( ann->range.max - m_vd.zvStart ) * pxns + 0.5f, lineh + 0.5f ), ann->range.hiMax ? c2 : c1, ann->range.hiMax ? 2 : 1 );+ if( drawMouseLine && ImGui::IsMouseHoveringRect( linepos + ImVec2( ( ann->range.min - m_vd.zvStart ) * pxns, 0 ), linepos + ImVec2( ( ann->range.max - m_vd.zvStart ) * pxns, lineh ) ) )+ {+ ImGui::BeginTooltip();+ if( ann->text.empty() )+ {+ TextDisabledUnformatted( "Empty annotation" );+ }+ else+ {+ ImGui::TextUnformatted( ann->text.c_str() );+ }+ ImGui::Separator();+ TextFocused( "Annotation begin:", TimeToStringExact( ann->range.min ) );+ TextFocused( "Annotation end:", TimeToStringExact( ann->range.max ) );+ TextFocused( "Annotation length:", TimeToString( ann->range.max - ann->range.min ) );+ ImGui::EndTooltip();+ }+ const auto aw = ( ann->range.max - ann->range.min ) * pxns;+ if( aw > th * 4 )+ {+ draw->AddCircleFilled( linepos + ImVec2( ( ann->range.min - m_vd.zvStart ) * pxns + th * 2, th * 2 ), th, 0x88AABB22 );+ draw->AddCircle( linepos + ImVec2( ( ann->range.min - m_vd.zvStart ) * pxns + th * 2, th * 2 ), th, 0xAAAABB22 );+ if( drawMouseLine && IsMouseClicked( 0 ) && ImGui::IsMouseHoveringRect( linepos + ImVec2( ( ann->range.min - m_vd.zvStart ) * pxns + th, th ), linepos + ImVec2( ( ann->range.min - m_vd.zvStart ) * pxns + th * 3, th * 3 ) ) )+ {+ m_selectedAnnotation = ann.get();+ }++ if( !ann->text.empty() )+ {+ const auto tw = ImGui::CalcTextSize( ann->text.c_str() ).x;+ if( aw - th*4 > tw )+ {+ draw->AddText( linepos + ImVec2( ( ann->range.min - m_vd.zvStart ) * pxns + th * 4, th * 0.5 ), 0xFFFFFFFF, ann->text.c_str() );+ }+ else+ {+ draw->PushClipRect( linepos + ImVec2( ( ann->range.min - m_vd.zvStart ) * pxns, 0 ), linepos + ImVec2( ( ann->range.max - m_vd.zvStart ) * pxns, lineh ), true );+ draw->AddText( linepos + ImVec2( ( ann->range.min - m_vd.zvStart ) * pxns + th * 4, th * 0.5 ), 0xFFFFFFFF, ann->text.c_str() );+ draw->PopClipRect();+ }+ }+ }+ }+ }++ if( m_gpuStart != 0 && m_gpuEnd != 0 )+ {+ const auto px0 = ( m_gpuStart - m_vd.zvStart ) * pxns;+ const auto px1 = std::max( px0 + std::max( 1.0, pxns * 0.5 ), ( m_gpuEnd - m_vd.zvStart ) * pxns );+ draw->AddRectFilled( ImVec2( wpos.x + px0, linepos.y ), ImVec2( wpos.x + px1, linepos.y + lineh ), 0x228888DD );+ draw->AddRect( ImVec2( wpos.x + px0, linepos.y ), ImVec2( wpos.x + px1, linepos.y + lineh ), 0x448888DD );+ }+ if( m_gpuInfoWindow )+ {+ const auto px0 = ( m_gpuInfoWindow->CpuStart() - m_vd.zvStart ) * pxns;+ const auto px1 = std::max( px0 + std::max( 1.0, pxns * 0.5 ), ( m_gpuInfoWindow->CpuEnd() - m_vd.zvStart ) * pxns );+ draw->AddRectFilled( ImVec2( wpos.x + px0, linepos.y ), ImVec2( wpos.x + px1, linepos.y + lineh ), 0x2288DD88 );+ draw->AddRect( ImVec2( wpos.x + px0, linepos.y ), ImVec2( wpos.x + px1, linepos.y + lineh ), 0x4488DD88 );+ }++ const auto scale = GetScale();+ if( m_findZone.range.active && ( m_findZone.show || m_showRanges ) )+ {+ const auto px0 = ( m_findZone.range.min - m_vd.zvStart ) * pxns;+ const auto px1 = std::max( px0 + std::max( 1.0, pxns * 0.5 ), ( m_findZone.range.max - m_vd.zvStart ) * pxns );+ DrawStripedRect( draw, wpos, px0, linepos.y, px1, linepos.y + lineh, 10 * scale, 0x2288DD88, true, true );+ DrawLine( draw, ImVec2( dpos.x + px0, linepos.y + 0.5f ), ImVec2( dpos.x + px0, linepos.y + lineh + 0.5f ), m_findZone.range.hiMin ? 0x9988DD88 : 0x3388DD88, m_findZone.range.hiMin ? 2 : 1 );+ DrawLine( draw, ImVec2( dpos.x + px1, linepos.y + 0.5f ), ImVec2( dpos.x + px1, linepos.y + lineh + 0.5f ), m_findZone.range.hiMax ? 0x9988DD88 : 0x3388DD88, m_findZone.range.hiMax ? 2 : 1 );+ }++ if( m_statRange.active && ( m_showStatistics || m_showRanges || ( m_sourceViewFile && m_sourceView->IsSymbolView() ) ) )+ {+ const auto px0 = ( m_statRange.min - m_vd.zvStart ) * pxns;+ const auto px1 = std::max( px0 + std::max( 1.0, pxns * 0.5 ), ( m_statRange.max - m_vd.zvStart ) * pxns );+ DrawStripedRect( draw, wpos, px0, linepos.y, px1, linepos.y + lineh, 10 * scale, 0x228888EE, true, false );+ DrawLine( draw, ImVec2( dpos.x + px0, linepos.y + 0.5f ), ImVec2( dpos.x + px0, linepos.y + lineh + 0.5f ), m_statRange.hiMin ? 0x998888EE : 0x338888EE, m_statRange.hiMin ? 2 : 1 );+ DrawLine( draw, ImVec2( dpos.x + px1, linepos.y + 0.5f ), ImVec2( dpos.x + px1, linepos.y + lineh + 0.5f ), m_statRange.hiMax ? 0x998888EE : 0x338888EE, m_statRange.hiMax ? 2 : 1 );+ }++ if( m_flameRange.active && ( m_showFlameGraph || m_showRanges ) )+ {+ const auto px0 = ( m_flameRange.min - m_vd.zvStart ) * pxns;+ const auto px1 = std::max( px0 + std::max( 1.0, pxns * 0.5 ), ( m_flameRange.max - m_vd.zvStart ) * pxns );+ DrawStripedRect( draw, wpos, px0, linepos.y, px1, linepos.y + lineh, 10 * scale, 0x2288B5EE, true, false );+ DrawLine( draw, ImVec2( dpos.x + px0, linepos.y + 0.5f ), ImVec2( dpos.x + px0, linepos.y + lineh + 0.5f ), m_flameRange.hiMin ? 0x9988B5EE : 0x3388B5EE, m_flameRange.hiMin ? 2 : 1 );+ DrawLine( draw, ImVec2( dpos.x + px1, linepos.y + 0.5f ), ImVec2( dpos.x + px1, linepos.y + lineh + 0.5f ), m_flameRange.hiMax ? 0x9988B5EE : 0x3388B5EE, m_flameRange.hiMax ? 2 : 1 );+ }++ if( m_waitStackRange.active && ( m_showWaitStacks || m_showRanges ) )+ {+ const auto px0 = ( m_waitStackRange.min - m_vd.zvStart ) * pxns;+ const auto px1 = std::max( px0 + std::max( 1.0, pxns * 0.5 ), ( m_waitStackRange.max - m_vd.zvStart ) * pxns );+ DrawStripedRect( draw, wpos, px0, linepos.y, px1, linepos.y + lineh, 10 * scale, 0x22EEB588, true, true );+ DrawLine( draw, ImVec2( dpos.x + px0, linepos.y + 0.5f ), ImVec2( dpos.x + px0, linepos.y + lineh + 0.5f ), m_waitStackRange.hiMin ? 0x99EEB588 : 0x33EEB588, m_waitStackRange.hiMin ? 2 : 1 );+ DrawLine( draw, ImVec2( dpos.x + px1, linepos.y + 0.5f ), ImVec2( dpos.x + px1, linepos.y + lineh + 0.5f ), m_waitStackRange.hiMax ? 0x99EEB588 : 0x33EEB588, m_waitStackRange.hiMax ? 2 : 1 );+ }++ if( m_memInfo.range.active && ( m_memInfo.show || m_showRanges ) )+ {+ const auto px0 = ( m_memInfo.range.min - m_vd.zvStart ) * pxns;+ const auto px1 = std::max( px0 + std::max( 1.0, pxns * 0.5 ), ( m_memInfo.range.max - m_vd.zvStart ) * pxns );+ DrawStripedRect( draw, wpos, px0, linepos.y, px1, linepos.y + lineh, 10 * scale, 0x2288EEE3, true, false );+ DrawLine( draw, ImVec2( dpos.x + px0, linepos.y + 0.5f ), ImVec2( dpos.x + px0, linepos.y + lineh + 0.5f ), m_memInfo.range.hiMin ? 0x9988EEE3 : 0x3388EEE3, m_memInfo.range.hiMin ? 2 : 1 );+ DrawLine( draw, ImVec2( dpos.x + px1, linepos.y + 0.5f ), ImVec2( dpos.x + px1, linepos.y + lineh + 0.5f ), m_memInfo.range.hiMax ? 0x9988EEE3 : 0x3388EEE3, m_memInfo.range.hiMax ? 2 : 1 );+ }++ if( m_setRangePopup.active || m_setRangePopupOpen )+ {+ const auto s = std::min( m_setRangePopup.min, m_setRangePopup.max );+ const auto e = std::max( m_setRangePopup.min, m_setRangePopup.max );+ DrawStripedRect( draw, wpos, ( s - m_vd.zvStart ) * pxns, linepos.y, ( e - m_vd.zvStart ) * pxns, linepos.y + lineh, 5 * scale, 0x55DD8888, true, false );+ draw->AddRect( ImVec2( wpos.x + ( s - m_vd.zvStart ) * pxns, linepos.y ), ImVec2( wpos.x + ( e - m_vd.zvStart ) * pxns, linepos.y + lineh ), 0x77DD8888 );+ }++ if( m_highlight.active && m_highlight.start != m_highlight.end )+ {+ const auto s = std::min( m_highlight.start, m_highlight.end );+ const auto e = std::max( m_highlight.start, m_highlight.end );+ draw->AddRectFilled( ImVec2( wpos.x + ( s - m_vd.zvStart ) * pxns, linepos.y ), ImVec2( wpos.x + ( e - m_vd.zvStart ) * pxns, linepos.y + lineh ), 0x22DD8888 );+ draw->AddRect( ImVec2( wpos.x + ( s - m_vd.zvStart ) * pxns, linepos.y ), ImVec2( wpos.x + ( e - m_vd.zvStart ) * pxns, linepos.y + lineh ), 0x44DD8888 );++ ImGui::BeginTooltip();+ ImGui::TextUnformatted( TimeToString( e - s ) );+ ImGui::EndTooltip();+ }+ else if( drawMouseLine )+ {+ auto& io = ImGui::GetIO();+ DrawLine( draw, ImVec2( io.MousePos.x + 0.5f, linepos.y + 0.5f ), ImVec2( io.MousePos.x + 0.5f, linepos.y + lineh + 0.5f ), 0x33FFFFFF );+ }++ if( m_highlightZoom.active && m_highlightZoom.start != m_highlightZoom.end )+ {+ const auto s = std::min( m_highlightZoom.start, m_highlightZoom.end );+ const auto e = std::max( m_highlightZoom.start, m_highlightZoom.end );+ draw->AddRectFilled( ImVec2( wpos.x + ( s - m_vd.zvStart ) * pxns, linepos.y ), ImVec2( wpos.x + ( e - m_vd.zvStart ) * pxns, linepos.y + lineh ), 0x1688DD88 );+ draw->AddRect( ImVec2( wpos.x + ( s - m_vd.zvStart ) * pxns, linepos.y ), ImVec2( wpos.x + ( e - m_vd.zvStart ) * pxns, linepos.y + lineh ), 0x2C88DD88 );+ }+}++}
+ cbits/tracy/profiler/src/profiler/TracyView_TraceInfo.cpp view
@@ -0,0 +1,978 @@+#include <inttypes.h>++#include "TracyImGui.hpp"+#include "TracyPrint.hpp"+#include "TracyView.hpp"+#include "tracy_pdqsort.h"++namespace tracy+{++extern double s_time;++void View::DrawInfo()+{+ const auto scale = GetScale();+ ImGui::SetNextWindowSize( ImVec2( 400 * scale, 650 * scale ), ImGuiCond_FirstUseEver );+ ImGui::Begin( "Trace information", &m_showInfo, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse );+ if( ImGui::GetCurrentWindowRead()->SkipItems ) { ImGui::End(); return; }+ ImGui::PushFont( m_bigFont );+ TextFocused( "Program:", m_worker.GetCaptureProgram().c_str() );+ ImGui::PopFont();+ const auto exectime = m_worker.GetExecutableTime();+ if( exectime != 0 )+ {+ char etmp[64];+ time_t et = exectime;+ auto elt = localtime( &et );+ strftime( etmp, 64, "%F %T", elt );+ TextFocused( "Build time:", etmp );+ }+ {+ char dtmp[64];+ time_t date = m_worker.GetCaptureTime();+ auto lt = localtime( &date );+ strftime( dtmp, 64, "%F %T", lt );+ TextFocused( "Capture time:", dtmp );+ }+ if( !m_filename.empty() )+ {+ TextFocused( "File:", m_filename.c_str() );+ if( m_userData.Valid() )+ {+ const auto save = m_userData.GetConfigLocation();+ if( save )+ {+ ImGui::SameLine();+ if( ImGui::SmallButton( ICON_FA_FOLDER ) )+ {+ ImGui::SetClipboardText( save );+ }+ TooltipIfHovered( "Copy user settings location to clipboard." );+ }+ }+ }+ {+ const auto& desc = m_userData.GetDescription();+ const auto descsz = std::min<size_t>( 255, desc.size() );+ char buf[256];+ buf[descsz] = '\0';+ memcpy( buf, desc.c_str(), descsz );+ ImGui::SetNextItemWidth( -1 );+ if( ImGui::InputTextWithHint( "##traceDesc", "Enter description of the trace", buf, 256 ) )+ {+ m_userData.SetDescription( buf );+ if( m_stcb ) UpdateTitle();+ }+ }++ ImGui::Separator();+ ImGui::BeginChild( "##info" );++ const auto ficnt = m_worker.GetFrameImageCount();+ if( ImGui::TreeNode( "Trace statistics" ) )+ {+ ImGui::TextDisabled( "Trace version:" );+ ImGui::SameLine();+ const auto version = m_worker.GetTraceVersion();+ ImGui::Text( "%i.%i.%i", version >> 16, ( version >> 8 ) & 0xFF, version & 0xFF );+ TextFocused( "Queue delay:", TimeToString( m_worker.GetDelay() ) );+ TextFocused( "Timer resolution:", TimeToString( m_worker.GetResolution() ) );+ TextFocused( "CPU zones:", RealToString( m_worker.GetZoneCount() ) );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ TextFocused( "Extra data:", RealToString( m_worker.GetZoneExtraCount() ) );+ TooltipIfHovered( "Count of zones containing any of the following: call stack trace, custom name, user text" );+ TextFocused( "GPU zones:", RealToString( m_worker.GetGpuZoneCount() ) );+ TextFocused( "Lock events:", RealToString( m_worker.GetLockCount() ) );+ TextFocused( "Plot data points:", RealToString( m_worker.GetPlotCount() ) );+ TooltipIfHovered( "User plots" );+ ImGui::SameLine();+ TextFocused( "+", RealToString( m_worker.GetTracyPlotCount() ) );+ TooltipIfHovered( "Automated Tracy plots" );+ auto& memNameMap = m_worker.GetMemNameMap();+ TextFocused( "Memory pools:", RealToString( memNameMap.size() ) );+ uint64_t memTotalCnt = 0;+ for( auto v : memNameMap ) memTotalCnt += v.second->data.size();+ TextFocused( "Memory allocations:", RealToString( memTotalCnt ) );+ TextFocused( "Source locations:", RealToString( m_worker.GetSrcLocCount() ) );+ TextFocused( "Strings:", RealToString( m_worker.GetStringsCount() ) );+ TextFocused( "Symbols:", RealToString( m_worker.GetSymbolsCount() ) );+ TextFocused( "Symbol code fragments:", RealToString( m_worker.GetSymbolCodeCount() ) );+ TooltipIfHovered( MemSizeToString( m_worker.GetSymbolCodeSize() ) );+ TextFocused( "Call stacks:", RealToString( m_worker.GetCallstackPayloadCount() ) );+ if( m_worker.AreCallstackSamplesReady() )+ {+ ImGui::SameLine();+ TextFocused( "+", RealToString( m_worker.GetCallstackParentPayloadCount() ) );+ TooltipIfHovered( "Parent call stacks for stack samples" );+ }+ TextFocused( "Call stack frames:", RealToString( m_worker.GetCallstackFrameCount() ) );+ if( m_worker.AreCallstackSamplesReady() )+ {+ ImGui::SameLine();+ TextFocused( "+", RealToString( m_worker.GetCallstackParentFrameCount() ) );+ TooltipIfHovered( "Parent call stack frames for stack samples" );+ }+ TextFocused( "Call stack samples:", RealToString( m_worker.GetCallstackSampleCount() ) );+ TextFocused( "Ghost zones:", RealToString( m_worker.GetGhostZonesCount() ) );+#ifndef TRACY_NO_STATISTICS+ TextFocused( "Child sample symbols:", RealToString( m_worker.GetChildSamplesCountSyms() ) );+ if( ImGui::IsItemHovered() )+ {+ ImGui::BeginTooltip();+ TextFocused( "Child samples:", RealToString( m_worker.GetChildSamplesCountFull() ) );+ ImGui::EndTooltip();+ }+ TextFocused( "Context switch samples:", RealToString( m_worker.GetContextSwitchSampleCount() ) );+#endif+ TextFocused( "Hardware samples:", RealToString( m_worker.GetHwSampleCount() ) );+ if( ImGui::IsItemHovered() )+ {+ ImGui::BeginTooltip();+ TextFocused( "Unique addresses:", RealToString( m_worker.GetHwSampleCountAddress() ) );+ ImGui::EndTooltip();+ }+ TextFocused( "Frame images:", RealToString( ficnt ) );+ if( ficnt != 0 && ImGui::IsItemHovered() )+ {+ const auto bytes = m_worker.GetTextureCompressionBytes();+ ImGui::BeginTooltip();+ TextFocused( "Input data:", MemSizeToString( bytes.first ) );+ TextFocused( "Compressed:", MemSizeToString( bytes.second ) );+ char buf[64];+ auto ptr = PrintFloat( buf, buf+62, 100. * bytes.second / bytes.first, 2 );+ memcpy( ptr, "%", 2 );+ TextFocused( "Ratio:", buf );+ ImGui::EndTooltip();+ }+ TextFocused( "Context switch regions:", RealToString( m_worker.GetContextSwitchCount() ) );+ TooltipIfHovered( "Detailed context switch data regarding application threads" );+ ImGui::SameLine();+ TextFocused( "+", RealToString( m_worker.GetContextSwitchPerCpuCount() ) );+ TooltipIfHovered( "Coarse CPU core context switch data" );+ if( m_worker.GetSourceFileCacheCount() == 0 )+ {+ TextFocused( "Source file cache:", "0" );+ }+ else+ {+ ImGui::PushStyleColor( ImGuiCol_Text, GImGui->Style.Colors[ImGuiCol_TextDisabled] );+ const bool expand = ImGui::TreeNode( "Source file cache:" );+ ImGui::PopStyleColor();+ ImGui::SameLine();+ ImGui::TextUnformatted( RealToString( m_worker.GetSourceFileCacheCount() ) );+ TooltipIfHovered( MemSizeToString( m_worker.GetSourceFileCacheSize() ) );+ if( expand )+ {+ auto& cache = m_worker.GetSourceFileCache();+ std::vector<decltype(cache.begin())> vec;+ vec.reserve( cache.size() );+ for( auto it = cache.begin(); it != cache.end(); ++it ) vec.emplace_back( it );+ pdqsort_branchless( vec.begin(), vec.end(), []( const auto& lhs, const auto& rhs ) { return strcmp( lhs->first, rhs->first ) < 0; } );+ for( auto& v : vec )+ {+ ImGui::BulletText( "%s", v->first );+ if( ImGui::IsItemClicked() ) ViewSource( v->first, 0 );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", MemSizeToString( v->second.len ) );+ }+ ImGui::TreePop();+ }+ }+ ImGui::TreePop();+ }++ if( m_worker.AreFramesUsed() && ImGui::TreeNode( "Frame statistics" ) )+ {+ auto fsz = m_worker.GetFullFrameCount( *m_frames );+ if( fsz != 0 )+ {+ TextFocused( "Frame set:", GetFrameSetName( *m_frames ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", m_frames->continuous ? "continuous" : "discontinuous" );+ ImGui::SameLine();+ ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 0, 0 ) );+ if( ImGui::BeginCombo( "##frameCombo", nullptr, ImGuiComboFlags_NoPreview ) )+ {+ auto& frames = m_worker.GetFrames();+ for( auto& fd : frames )+ {+ bool isSelected = m_frames == fd;+ if( ImGui::Selectable( GetFrameSetName( *fd ), isSelected ) )+ {+ m_frames = fd;+ fsz = m_worker.GetFullFrameCount( *m_frames );+ }+ if( isSelected )+ {+ ImGui::SetItemDefaultFocus();+ }+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( fd->frames.size() ) );+ }+ ImGui::EndCombo();+ }+ ImGui::PopStyleVar();+ ImGui::SameLine();+ SmallCheckbox( "Limit to view", &m_frameSortData.limitToView );+ if( m_frameSortData.limitToView )+ {+ ImGui::SameLine();+ TextColoredUnformatted( 0xFF00FFFF, ICON_FA_TRIANGLE_EXCLAMATION );+ }++ const auto frameRange = m_worker.GetFrameRange( *m_frames, m_vd.zvStart, m_vd.zvEnd );+ if( m_frameSortData.frameSet != m_frames || ( m_frameSortData.limitToView && m_frameSortData.limitRange != frameRange ) || ( !m_frameSortData.limitToView && m_frameSortData.limitRange.first != -1 ) )+ {+ m_frameSortData.frameSet = m_frames;+ m_frameSortData.frameNum = 0;+ m_frameSortData.data.clear();+ m_frameSortData.total = 0;+ }+ bool recalc = false;+ int64_t total = 0;+ if( !m_frameSortData.limitToView )+ {+ if( m_frameSortData.frameNum != fsz || m_frameSortData.limitRange.first != -1 )+ {+ auto& vec = m_frameSortData.data;+ vec.reserve( fsz );+ const auto midSz = vec.size();+ total = m_frameSortData.total;+ for( size_t i=m_frameSortData.frameNum; i<fsz; i++ )+ {+ const auto t = m_worker.GetFrameTime( *m_frames, i );+ if( t > 0 )+ {+ vec.emplace_back( t );+ total += t;+ }+ }+ auto mid = vec.begin() + midSz;+ pdqsort_branchless( mid, vec.end() );+ std::inplace_merge( vec.begin(), mid, vec.end() );+ recalc = true;+ m_frameSortData.limitRange.first = -1;+ }+ }+ else+ {+ if( m_frameSortData.limitRange != frameRange )+ {+ auto& vec = m_frameSortData.data;+ assert( vec.empty() );+ vec.reserve( frameRange.second - frameRange.first );+ for( int i=frameRange.first; i<frameRange.second; i++ )+ {+ const auto t = m_worker.GetFrameTime( *m_frames, i );+ if( t > 0 )+ {+ vec.emplace_back( t );+ total += t;+ }+ }+ pdqsort_branchless( vec.begin(), vec.end() );+ recalc = true;+ m_frameSortData.limitRange = frameRange;+ }+ }+ if( recalc )+ {+ auto& vec = m_frameSortData.data;+ const auto vsz = vec.size();+ m_frameSortData.average = float( total ) / vsz;+ m_frameSortData.median = vec[vsz/2];+ m_frameSortData.total = total;+ m_frameSortData.frameNum = fsz;+ }++ const auto profileSpan = m_worker.GetLastTime();+ TextFocused( "Count:", RealToString( fsz ) );+ TextFocused( "Total time:", TimeToString( m_frameSortData.total ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%.2f%% of profile time span)", m_frameSortData.total / float( profileSpan ) * 100.f );+ TextFocused( "Mean frame time:", TimeToString( m_frameSortData.average ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s FPS)", RealToString( round( 1000000000.0 / m_frameSortData.average ) ) );+ if( ImGui::IsItemHovered() )+ {+ ImGui::BeginTooltip();+ ImGui::Text( "%s FPS", RealToString( 1000000000.0 / m_frameSortData.average ) );+ ImGui::EndTooltip();+ }+ TextFocused( "Median frame time:", TimeToString( m_frameSortData.median ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s FPS)", RealToString( round( 1000000000.0 / m_frameSortData.median ) ) );+ if( ImGui::IsItemHovered() )+ {+ ImGui::BeginTooltip();+ ImGui::Text( "%s FPS", RealToString( 1000000000.0 / m_frameSortData.median ) );+ ImGui::EndTooltip();+ }++ if( ImGui::TreeNodeEx( "Histogram", ImGuiTreeNodeFlags_DefaultOpen ) )+ {+ const auto ty = ImGui::GetTextLineHeight();++ auto& frames = m_frameSortData.data;+ auto tmin = frames.front();+ auto tmax = frames.back();++ if( tmin != std::numeric_limits<int64_t>::max() )+ {+ TextDisabledUnformatted( "Minimum values in bin:" );+ ImGui::SameLine();+ ImGui::SetNextItemWidth( ImGui::CalcTextSize( "123456890123456" ).x );+ ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 1, 1 ) );+ ImGui::InputInt( "##minBinVal", &m_frameSortData.minBinVal );+ if( m_frameSortData.minBinVal < 1 ) m_frameSortData.minBinVal = 1;+ ImGui::SameLine();+ if( ImGui::Button( "Reset" ) ) m_frameSortData.minBinVal = 1;+ ImGui::PopStyleVar();++ SmallCheckbox( "Log values", &m_frameSortData.logVal );+ ImGui::SameLine();+ SmallCheckbox( "Log time", &m_frameSortData.logTime );++ TextDisabledUnformatted( "FPS range:" );+ ImGui::SameLine();+ ImGui::Text( "%s FPS - %s FPS", RealToString( round( 1000000000.0 / tmin ) ), RealToString( round( 1000000000.0 / tmax ) ) );++ if( tmax - tmin > 0 )+ {+ const auto w = ImGui::GetContentRegionAvail().x;++ const auto numBins = int64_t( w - 4 );+ if( numBins > 1 )+ {+ if( numBins > m_frameSortData.numBins )+ {+ m_frameSortData.numBins = numBins;+ m_frameSortData.bins = std::make_unique<int64_t[]>( numBins );+ }++ const auto& bins = m_frameSortData.bins;++ memset( bins.get(), 0, sizeof( int64_t ) * numBins );++ auto framesBegin = frames.begin();+ auto framesEnd = frames.end();+ while( framesBegin != framesEnd && *framesBegin == 0 ) ++framesBegin;++ if( m_frameSortData.minBinVal > 1 )+ {+ if( m_frameSortData.logTime )+ {+ const auto tMinLog = log10( tmin );+ const auto zmax = ( log10( tmax ) - tMinLog ) / numBins;+ int64_t i;+ for( i=0; i<numBins; i++ )+ {+ const auto nextBinVal = int64_t( pow( 10.0, tMinLog + ( i+1 ) * zmax ) );+ auto nit = std::lower_bound( framesBegin, framesEnd, nextBinVal );+ const auto distance = std::distance( framesBegin, nit );+ if( distance >= m_frameSortData.minBinVal ) break;+ framesBegin = nit;+ }+ for( int64_t j=numBins-1; j>i; j-- )+ {+ const auto nextBinVal = int64_t( pow( 10.0, tMinLog + ( j-1 ) * zmax ) );+ auto nit = std::lower_bound( framesBegin, framesEnd, nextBinVal );+ const auto distance = std::distance( nit, framesEnd );+ if( distance >= m_frameSortData.minBinVal ) break;+ framesEnd = nit;+ }+ }+ else+ {+ const auto zmax = tmax - tmin;+ int64_t i;+ for( i=0; i<numBins; i++ )+ {+ const auto nextBinVal = tmin + ( i+1 ) * zmax / numBins;+ auto nit = std::lower_bound( framesBegin, framesEnd, nextBinVal );+ const auto distance = std::distance( framesBegin, nit );+ if( distance >= m_frameSortData.minBinVal ) break;+ framesBegin = nit;+ }+ for( int64_t j=numBins-1; j>i; j-- )+ {+ const auto nextBinVal = tmin + ( j-1 ) * zmax / numBins;+ auto nit = std::lower_bound( framesBegin, framesEnd, nextBinVal );+ const auto distance = std::distance( nit, framesEnd );+ if( distance >= m_frameSortData.minBinVal ) break;+ framesEnd = nit;+ }+ }++ tmin = *framesBegin;+ tmax = *(framesEnd-1);+ }++ if( m_frameSortData.logTime )+ {+ const auto tMinLog = log10( tmin );+ const auto zmax = ( log10( tmax ) - tMinLog ) / numBins;+ auto fit = framesBegin;+ for( int64_t i=0; i<numBins; i++ )+ {+ const auto nextBinVal = int64_t( pow( 10.0, tMinLog + ( i+1 ) * zmax ) );+ auto nit = std::lower_bound( fit, framesEnd, nextBinVal );+ bins[i] = std::distance( fit, nit );+ fit = nit;+ }+ bins[numBins-1] += std::distance( fit, framesEnd );+ }+ else+ {+ const auto zmax = tmax - tmin;+ auto fit = framesBegin;+ for( int64_t i=0; i<numBins; i++ )+ {+ const auto nextBinVal = tmin + ( i+1 ) * zmax / numBins;+ auto nit = std::lower_bound( fit, framesEnd, nextBinVal );+ bins[i] = std::distance( fit, nit );+ fit = nit;+ }+ bins[numBins-1] += std::distance( fit, framesEnd );+ }++ int64_t maxVal = bins[0];+ for( int i=1; i<numBins; i++ )+ {+ maxVal = std::max( maxVal, bins[i] );+ }++ TextFocused( "Max counts:", RealToString( maxVal ) );++ ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 0, 0 ) );+ ImGui::Checkbox( "###draw1", &m_frameSortData.drawAvgMed );+ ImGui::SameLine();+ ImGui::ColorButton( "c1", ImVec4( 0xFF/255.f, 0x44/255.f, 0x44/255.f, 1.f ), ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoDragDrop );+ ImGui::SameLine();+ ImGui::TextUnformatted( "Mean time" );+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ ImGui::ColorButton( "c2", ImVec4( 0x44/255.f, 0x88/255.f, 0xFF/255.f, 1.f ), ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoDragDrop );+ ImGui::SameLine();+ ImGui::TextUnformatted( "Median time" );+ ImGui::PopStyleVar();++ const auto Height = 200 * scale;+ const auto wpos = ImGui::GetCursorScreenPos();+ const auto dpos = wpos + ImVec2( 0.5f, 0.5f );++ ImGui::InvisibleButton( "##histogram", ImVec2( w, Height + round( ty * 2.5 ) ) );+ const bool hover = ImGui::IsItemHovered();++ auto draw = ImGui::GetWindowDrawList();+ draw->AddRectFilled( wpos, wpos + ImVec2( w, Height ), 0x22FFFFFF );+ draw->AddRect( wpos, wpos + ImVec2( w, Height ), 0x88FFFFFF );++ if( m_frameSortData.logVal )+ {+ const auto hAdj = double( Height - 4 ) / log10( maxVal + 1 );+ for( int i=0; i<numBins; i++ )+ {+ const auto val = bins[i];+ if( val > 0 )+ {+ DrawLine( draw, dpos + ImVec2( 2+i, Height-3 ), dpos + ImVec2( 2+i, Height-3 - log10( val + 1 ) * hAdj ), 0xFF22DDDD );+ }+ }+ }+ else+ {+ const auto hAdj = double( Height - 4 ) / maxVal;+ for( int i=0; i<numBins; i++ )+ {+ const auto val = bins[i];+ if( val > 0 )+ {+ DrawLine( draw, dpos + ImVec2( 2+i, Height-3 ), dpos + ImVec2( 2+i, Height-3 - val * hAdj ), 0xFF22DDDD );+ }+ }+ }++ const auto xoff = 2;+ const auto yoff = Height + 1;++ DrawHistogramMinMaxLabel( draw, tmin, tmax, wpos + ImVec2( 0, yoff ), w, ty );++ const auto ty05 = round( ty * 0.5f );+ const auto ty025 = round( ty * 0.25f );+ if( m_frameSortData.logTime )+ {+ const auto ltmin = log10( tmin );+ const auto ltmax = log10( tmax );+ const auto start = int( floor( ltmin ) );+ const auto end = int( ceil( ltmax ) );++ const auto range = ltmax - ltmin;+ const auto step = w / range;+ auto offset = start - ltmin;+ int tw = 0;+ int tx = 0;++ auto tt = int64_t( pow( 10, start ) );++ static const double logticks[] = { log10( 2 ), log10( 3 ), log10( 4 ), log10( 5 ), log10( 6 ), log10( 7 ), log10( 8 ), log10( 9 ) };++ for( int i=start; i<=end; i++ )+ {+ const auto x = ( i - start + offset ) * step;++ if( x >= 0 )+ {+ DrawLine( draw, dpos + ImVec2( x, yoff ), dpos + ImVec2( x, yoff + ty05 ), 0x66FFFFFF );+ if( tw == 0 || x > tx + tw + ty * 1.1 )+ {+ tx = x;+ auto txt = TimeToString( tt );+ draw->AddText( wpos + ImVec2( x, yoff + ty05 ), 0x66FFFFFF, txt );+ tw = ImGui::CalcTextSize( txt ).x;+ }+ }++ for( int j=0; j<8; j++ )+ {+ const auto xoff = x + logticks[j] * step;+ if( xoff >= 0 )+ {+ DrawLine( draw, dpos + ImVec2( xoff, yoff ), dpos + ImVec2( xoff, yoff + ty025 ), 0x66FFFFFF );+ }+ }++ tt *= 10;+ }+ }+ else+ {+ const auto pxns = numBins / double( tmax - tmin );+ const auto nspx = 1.0 / pxns;+ const auto scale = std::max<float>( 0.0f, round( log10( nspx ) + 2 ) );+ const auto step = pow( 10, scale );++ const auto dx = step * pxns;+ double x = 0;+ int tw = 0;+ int tx = 0;++ const auto sstep = step / 10.0;+ const auto sdx = dx / 10.0;++ static const double linelen[] = { 0.5, 0.25, 0.25, 0.25, 0.25, 0.375, 0.25, 0.25, 0.25, 0.25 };++ int64_t tt = int64_t( ceil( tmin / sstep ) * sstep );+ const auto diff = tmin / sstep - int64_t( tmin / sstep );+ const auto xo = ( diff == 0 ? 0 : ( ( 1 - diff ) * sstep * pxns ) ) + xoff;+ int iter = int( ceil( ( tmin - int64_t( tmin / step ) * step ) / sstep ) );++ while( x < numBins )+ {+ DrawLine( draw, dpos + ImVec2( xo + x, yoff ), dpos + ImVec2( xo + x, yoff + round( ty * linelen[iter] ) ), 0x66FFFFFF );+ if( iter == 0 && ( tw == 0 || x > tx + tw + ty * 1.1 ) )+ {+ tx = x;+ auto txt = TimeToString( tt );+ draw->AddText( wpos + ImVec2( xo + x, yoff + ty05 ), 0x66FFFFFF, txt );+ tw = ImGui::CalcTextSize( txt ).x;+ }++ iter = ( iter + 1 ) % 10;+ x += sdx;+ tt += sstep;+ }+ }++ if( m_frameSortData.drawAvgMed )+ {+ float ta, tm;+ if( m_frameSortData.logTime )+ {+ const auto ltmin = log10( tmin );+ const auto ltmax = log10( tmax );++ ta = ( log10( m_frameSortData.average ) - ltmin ) / float( ltmax - ltmin ) * numBins;+ tm = ( log10( m_frameSortData.median ) - ltmin ) / float( ltmax - ltmin ) * numBins;+ }+ else+ {+ ta = ( m_frameSortData.average - tmin ) / float( tmax - tmin ) * numBins;+ tm = ( m_frameSortData.median - tmin ) / float( tmax - tmin ) * numBins;+ }+ ta = round( ta );+ tm = round( tm );++ if( ta == tm )+ {+ DrawLine( draw, ImVec2( dpos.x + ta, dpos.y ), ImVec2( dpos.x + ta, dpos.y+Height-2 ), 0xFFFF88FF );+ }+ else+ {+ DrawLine( draw, ImVec2( dpos.x + ta, dpos.y ), ImVec2( dpos.x + ta, dpos.y+Height-2 ), 0xFF4444FF );+ DrawLine( draw, ImVec2( dpos.x + tm, dpos.y ), ImVec2( dpos.x + tm, dpos.y+Height-2 ), 0xFFFF8844 );+ }+ }++ if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( 2, 2 ), wpos + ImVec2( w-2, Height + round( ty * 1.5 ) ) ) )+ {+ const auto ltmin = log10( tmin );+ const auto ltmax = log10( tmax );++ auto& io = ImGui::GetIO();+ DrawLine( draw, ImVec2( io.MousePos.x + 0.5f, dpos.y ), ImVec2( io.MousePos.x + 0.5f, dpos.y+Height-2 ), 0x33FFFFFF );++ const auto bin = int64_t( io.MousePos.x - wpos.x - 2 );+ int64_t t0, t1;+ if( m_frameSortData.logTime )+ {+ t0 = int64_t( pow( 10, ltmin + double( bin ) / numBins * ( ltmax - ltmin ) ) );++ // Hackfix for inability to select data in last bin.+ // A proper solution would be nice.+ if( bin+1 == numBins )+ {+ t1 = tmax;+ }+ else+ {+ t1 = int64_t( pow( 10, ltmin + double( bin+1 ) / numBins * ( ltmax - ltmin ) ) );+ }+ }+ else+ {+ t0 = int64_t( tmin + double( bin ) / numBins * ( tmax - tmin ) );+ t1 = int64_t( tmin + double( bin+1 ) / numBins * ( tmax - tmin ) );+ }++ ImGui::BeginTooltip();+ TextDisabledUnformatted( "Time range:" );+ ImGui::SameLine();+ ImGui::Text( "%s - %s", TimeToString( t0 ), TimeToString( t1 ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s FPS - %s FPS)", RealToString( round( 1000000000.0 / t0 ) ), RealToString( round( 1000000000.0 / t1 ) ) );+ TextFocused( "Count:", RealToString( bins[bin] ) );+ ImGui::EndTooltip();+ }++ if( m_frameHover != -1 )+ {+ const auto frameTime = m_worker.GetFrameTime( *m_frames, m_frameHover );+ float framePos;+ if( m_frameSortData.logTime )+ {+ const auto ltmin = log10( tmin );+ const auto ltmax = log10( tmax );+ framePos = round( ( log10( frameTime ) - ltmin ) / float( ltmax - ltmin ) * numBins );+ }+ else+ {+ framePos = round( ( frameTime - tmin ) / float( tmax - tmin ) * numBins );+ }+ const auto c = uint32_t( ( sin( s_time * 10 ) * 0.25 + 0.75 ) * 255 );+ const auto color = 0xFF000000 | ( c << 16 ) | ( c << 8 ) | c;+ DrawLine( draw, ImVec2( dpos.x + framePos, dpos.y ), ImVec2( dpos.x + framePos, dpos.y+Height-2 ), color );+ m_wasActive = true;+ }+ }+ }+ }++ ImGui::TreePop();+ }+ }+ ImGui::TreePop();+ }++ auto& topology = m_worker.GetCpuTopology();+ if( !topology.empty() )+ {+ if( ImGui::TreeNode( "CPU topology" ) )+ {+ char buf[128];++ const auto ty = ImGui::GetFontSize();+ ImGui::PushFont( m_smallFont );+ const auto sty = ImGui::GetFontSize();+ ImGui::PopFont();+ const float margin = round( ty * 0.5 );+ const float small = round( sty * 0.5 );++ std::vector<int> maxthreads( topology.size() );++ float ptsz = 0;+ float dtsz = 0;+ float ctsz = 0;+ float ttsz = 0;+ for( auto& package : topology )+ {+ sprintf( buf, ICON_FA_BOX " Package %" PRIu32, package.first );+ ImGui::PushFont( m_smallFont );+ const auto psz = ImGui::CalcTextSize( buf ).x;+ if( psz > ptsz ) ptsz = psz;+ ImGui::PopFont();++ size_t mt = 0;+ for( auto& die : package.second )+ {+ sprintf( buf, ICON_FA_DICE_D6 " Die %" PRIu32, die.first );+ const auto dsz = ImGui::CalcTextSize( buf ).x;+ if( dsz > dtsz ) dtsz = dsz;++ for( auto& core : die.second )+ {+ sprintf( buf, ICON_FA_MICROCHIP "%" PRIu32, core.first );+ const auto csz = ImGui::CalcTextSize( buf ).x;+ if( csz > ctsz ) ctsz = csz;++ const auto tnum = core.second.size();+ if( tnum > mt ) mt = tnum;++ for( auto& thread : core.second )+ {+ sprintf( buf, ICON_FA_SHUFFLE "%" PRIu32, thread );+ const auto tsz = ImGui::CalcTextSize( buf ).x;+ if( tsz > ttsz ) ttsz = tsz;+ }+ }+ }+ maxthreads[package.first] = (int)mt;+ }++ const auto remainingWidth = ImGui::GetContentRegionAvail().x;+ auto dpos = ImGui::GetCursorScreenPos() + ImVec2( margin, 0 );+ const auto draw = ImGui::GetWindowDrawList();++ float width = 0;+ float origy = dpos.y;++ std::vector<decltype(topology.begin())> tsort;+ tsort.reserve( topology.size() );+ for( auto it = topology.begin(); it != topology.end(); ++it ) tsort.emplace_back( it );+ pdqsort_branchless( tsort.begin(), tsort.end(), [] ( const auto& l, const auto& r ) { return l->first < r->first; } );+ for( auto& package : tsort )+ {+ if( package->first != 0 ) dpos.y += ty;+ sprintf( buf, ICON_FA_BOX " Package %" PRIu32, package->first );+ draw->AddText( dpos, 0xFFFFFFFF, buf );+ dpos.y += ty;++ std::vector<decltype(package->second.begin())> dsort;+ dsort.reserve( package->second.size() );+ for( auto it = package->second.begin(); it != package->second.end(); ++it ) dsort.emplace_back( it );+ pdqsort_branchless( dsort.begin(), dsort.end(), [] ( const auto& l, const auto& r ) { return l->first < r->first; } );+ for( auto& die : dsort )+ {+ dpos.y += small;+ sprintf( buf, ICON_FA_DICE_D6 " Die %" PRIu32, die->first );+ draw->AddText( dpos, 0xFFFFFFFF, buf );+ dpos.y += ty;++ const auto inCoreWidth = ( ttsz + margin ) * maxthreads[package->first];+ const auto coreWidth = inCoreWidth + 2 * margin;+ const auto inCoreHeight = margin + 2 * small + ty;+ const auto coreHeight = inCoreHeight + ty;+ const auto cpl = std::max( 1, (int)floor( ( remainingWidth - 2 * margin ) / coreWidth ) );+ const auto cl = ( die->second.size() + cpl - 1 ) / cpl;+ const auto pw = cpl * coreWidth + 2 * margin;+ const auto ph = margin + cl * coreHeight;+ if( pw > width ) width = pw;++ draw->AddRect( dpos, dpos + ImVec2( margin + coreWidth * std::min<size_t>( cpl, die->second.size() ), ph ), 0xFFFFFFFF );++ std::vector<decltype(die->second.begin())> csort;+ csort.reserve( die->second.size() );+ for( auto it = die->second.begin(); it != die->second.end(); ++it ) csort.emplace_back( it );+ pdqsort_branchless( csort.begin(), csort.end(), [] ( const auto& l, const auto& r ) { return l->first < r->first; } );+ auto cpos = dpos + ImVec2( margin, margin );+ int ll = cpl;+ for( auto& core : csort )+ {+ sprintf( buf, ICON_FA_MICROCHIP "%" PRIu32, core->first );+ draw->AddText( cpos, 0xFFFFFFFF, buf );+ draw->AddRect( cpos + ImVec2( 0, ty ), cpos + ImVec2( inCoreWidth + small, inCoreHeight + small ), 0xFFFFFFFF );++ for( int i=0; i<core->second.size(); i++ )+ {+ sprintf( buf, ICON_FA_SHUFFLE "%" PRIu32, core->second[i] );+ draw->AddText( cpos + ImVec2( margin + i * ( margin + ttsz ), ty + small ), 0xFFFFFFFF, buf );+ }++ if( --ll == 0 )+ {+ ll = cpl;+ cpos.x -= (cpl-1) * coreWidth;+ cpos.y += coreHeight;+ }+ else+ {+ cpos.x += coreWidth;+ }+ }+ dpos.y += ph;+ }+ }+ ImGui::ItemSize( ImVec2( width, dpos.y - origy ) );+ ImGui::TreePop();+ }+ }++ if( ImGui::TreeNode( "Source location substitutions" ) )+ {+ static char test[1024] = {};+ ImGui::SetNextItemWidth( -1 );+ ImGui::InputTextWithHint( "##srcSubstTest", "Enter example source location to test substitutions", test, 1024 );+ if( m_sourceRegexValid )+ {+ TextFocused( "Result:", SourceSubstitution( test ) );+ }+ else+ {+ ImGui::TextColored( ImVec4( 255, 0, 0, 255 ), "Error in regular expression" );+ }+ if( ImGui::SmallButton( "Add new substitution" ) ) m_sourceSubstitutions.emplace_back( SourceRegex {} );+ int idx = 0, remove = -1;+ bool changed = false;+ ImGui::Columns( 2, nullptr, false );+ for( auto& v : m_sourceSubstitutions )+ {+ ImGui::PushID( idx );+ if( ImGui::Button( ICON_FA_TRASH_CAN ) ) remove = idx;+ ImGui::SameLine();+ char tmp[1024];+ strncpy( tmp, v.pattern.c_str(), 1024 );+ ImGui::SetNextItemWidth( -1 );+ if( ImGui::InputTextWithHint( "##pattern", "Regex pattern", tmp, 1024 ) )+ {+ v.pattern.assign( tmp );+ changed = true;+ }+ ImGui::NextColumn();+ strncpy( tmp, v.target.c_str(), 1024 );+ ImGui::SetNextItemWidth( -1 );+ if( ImGui::InputTextWithHint( "##replacement", "Regex replacement", tmp, 1024 ) ) v.target.assign( tmp );+ ImGui::PopID();+ ImGui::NextColumn();+ idx++;+ }+ ImGui::EndColumns();+ if( remove != -1 )+ {+ m_sourceSubstitutions.erase( m_sourceSubstitutions.begin() + remove );+ changed = true;+ }++ if( changed )+ {+ bool regexValid = true;+ for( auto& v : m_sourceSubstitutions )+ {+ try+ {+ v.regex.assign( v.pattern );+ }+ catch( std::regex_error& )+ {+ regexValid = false;+ break;+ }+ }+ m_sourceRegexValid = regexValid;+ }++ ImGui::Checkbox("Enforce source file modification time older than trace capture time", &m_validateSourceAge);++ ImGui::TreePop();+ }++ ImGui::Separator();+ TextFocused( "PID:", RealToString( m_worker.GetPid() ) );+ TextFocused( "Host info:", m_worker.GetHostInfo().c_str() );++ const auto cpuId = m_worker.GetCpuId();+ if( cpuId != 0 )+ {+ const auto stepping = cpuId & 0xF;+ const auto baseModel = ( cpuId >> 4 ) & 0xF;+ const auto baseFamily = ( cpuId >> 8 ) & 0xF;+ const auto extModel = ( cpuId >> 12 ) & 0xF;+ const auto extFamily = ( cpuId >> 16 );++ const uint32_t model = ( baseFamily == 6 || baseFamily == 15 ) ? ( ( extModel << 4 ) | baseModel ) : baseModel;+ const uint32_t family = baseFamily == 15 ? baseFamily + extFamily : baseFamily;++ TextFocused( "CPU:", m_worker.GetCpuManufacturer() );+ ImGui::SameLine();+ TextFocused( "Family", RealToString( family ) );+ ImGui::SameLine();+ TextFocused( "Model", RealToString( model ) );+ ImGui::SameLine();+ TextFocused( "Stepping", RealToString( stepping ) );+ }++ auto& appInfo = m_worker.GetAppInfo();+ if( !appInfo.empty() )+ {+ ImGui::Separator();+ TextDisabledUnformatted( "Application info:" );+ for( auto& v : appInfo )+ {+ ImGui::TextUnformatted( m_worker.GetString( v ) );+ }+ }++ auto& crash = m_worker.GetCrashEvent();+ if( crash.thread != 0 )+ {+ ImGui::Separator();+ TextColoredUnformatted( ImVec4( 1.f, 0.2f, 0.2f, 1.f ), ICON_FA_SKULL " Application has crashed. " ICON_FA_SKULL );+ TextFocused( "Time of crash:", TimeToString( crash.time ) );+ SmallColorBox( GetThreadColor( crash.thread, 0 ) );+ ImGui::SameLine();+ TextFocused( "Thread:", m_worker.GetThreadName( crash.thread ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( crash.thread ) );+ if( m_worker.IsThreadFiber( crash.thread ) )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 0.2f, 0.6f, 0.2f, 1.f ), "Fiber" );+ }+ TextDisabledUnformatted( "Reason:" );+ ImGui::SameLine();+ ImGui::TextWrapped( "%s", m_worker.GetString( crash.message ) );+ if( ImGui::Button( ICON_FA_MICROSCOPE " Focus" ) )+ {+ CenterAtTime( crash.time );+ }+ if( crash.callstack != 0 )+ {+ ImGui::SameLine();+ bool hilite = m_callstackInfoWindow == crash.callstack;+ if( hilite )+ {+ SetButtonHighlightColor();+ }+ if( ImGui::Button( ICON_FA_ALIGN_JUSTIFY " Call stack" ) )+ {+ m_callstackInfoWindow = crash.callstack;+ }+ if( hilite )+ {+ ImGui::PopStyleColor( 3 );+ }+ if( ImGui::IsItemHovered() )+ {+ CallstackTooltip( crash.callstack );+ }+ }+ }++ ImGui::EndChild();+ ImGui::End();+}++}
+ cbits/tracy/profiler/src/profiler/TracyView_Utility.cpp view
@@ -0,0 +1,936 @@+#include <inttypes.h>++#include "TracyColor.hpp"+#include "TracyPrint.hpp"+#include "TracyUtility.hpp"+#include "TracyView.hpp"++namespace tracy+{++bool View::IsFrameExternal( const char* filename, const char* image )+{+ if( strncmp( filename, "/usr/", 5 ) == 0 || strncmp( filename, "/lib/", 5 ) == 0 || strcmp( filename, "[unknown]" ) == 0 || strcmp( filename, "<kernel>" ) == 0 ) return true;+ if( strncmp( filename, "C:\\Program Files\\", 17 ) == 0 || strncmp( filename, "d:\\a01\\_work\\", 13 ) == 0 ) return true;+ if( !image ) return false;+ return strncmp( image, "/usr/", 5 ) == 0 || strncmp( image, "/lib/", 5 ) == 0 || strncmp( image, "/lib64/", 7 ) == 0 || strcmp( image, "<kernel>" ) == 0;+}++uint32_t View::GetThreadColor( uint64_t thread, int depth )+{+ return tracy::GetThreadColor( thread, depth, m_vd.dynamicColors != 0 );+}++uint32_t View::GetRawSrcLocColor( const SourceLocation& srcloc, int depth )+{+ auto namehash = srcloc.namehash;+ if( namehash == 0 && srcloc.function.active )+ {+ const auto f = m_worker.GetString( srcloc.function );+ namehash = charutil::hash( f );+ if( namehash == 0 ) namehash++;+ srcloc.namehash = namehash;+ }+ if( namehash == 0 )+ {+ return GetHsvColor( uint64_t( &srcloc ), depth );+ }+ else+ {+ return GetHsvColor( namehash, depth );+ }+}++uint32_t View::GetSrcLocColor( const SourceLocation& srcloc, int depth )+{+ const auto color = srcloc.color;+ if( color != 0 && !m_vd.forceColors ) return color | 0xFF000000;+ if( m_vd.dynamicColors == 0 ) return 0xFFCC5555;+ return GetRawSrcLocColor( srcloc, depth );+}++uint32_t View::GetZoneColor( const ZoneEvent& ev, uint64_t thread, int depth )+{+ const auto sl = ev.SrcLoc();+ const auto& srcloc = m_worker.GetSourceLocation( sl );+ if( !m_vd.forceColors )+ {+ if( m_worker.HasZoneExtra( ev ) )+ {+ const auto custom_color = m_worker.GetZoneExtra( ev ).color.Val();+ if( custom_color != 0 ) return custom_color | 0xFF000000;+ }+ const auto color = srcloc.color;+ if( color != 0 ) return color | 0xFF000000;+ }+ switch( m_vd.dynamicColors )+ {+ case 0:+ return 0xFFCC5555;+ case 1:+ return GetHsvColor( thread, depth );+ case 2:+ return GetRawSrcLocColor( srcloc, depth );+ default:+ assert( false );+ return 0;+ }+}++uint32_t View::GetZoneColor( const GpuEvent& ev )+{+ const auto& srcloc = m_worker.GetSourceLocation( ev.SrcLoc() );+ const auto color = srcloc.color;+ return color != 0 ? ( color | 0xFF000000 ) : 0xFF222288;+}++View::ZoneColorData View::GetZoneColorData( const ZoneEvent& ev, uint64_t thread, int depth, uint32_t inheritedColor )+{+ ZoneColorData ret;+ const auto& srcloc = ev.SrcLoc();+ if( m_zoneInfoWindow == &ev )+ {+ ret.color = inheritedColor ? inheritedColor : GetZoneColor( ev, thread, depth );+ ret.accentColor = 0xFF44DD44;+ ret.thickness = 3.f;+ ret.highlight = true;+ }+ else if( m_zoneHighlight == &ev )+ {+ ret.color = inheritedColor ? inheritedColor : GetZoneColor( ev, thread, depth );+ ret.accentColor = 0xFF4444FF;+ ret.thickness = 3.f;+ ret.highlight = true;+ }+ else if( m_zoneSrcLocHighlight == srcloc )+ {+ ret.color = inheritedColor ? inheritedColor : GetZoneColor( ev, thread, depth );+ ret.accentColor = 0xFFEEEEEE;+ ret.thickness = 1.f;+ ret.highlight = true;+ }+ else if( m_findZone.show && !m_findZone.match.empty() && m_findZone.match[m_findZone.selMatch] == srcloc )+ {+ uint32_t color = 0xFF229999;+ if( m_findZone.highlight.active )+ {+ const auto zt = m_worker.GetZoneEnd( ev ) - ev.Start();+ if( zt >= m_findZone.highlight.start && zt <= m_findZone.highlight.end )+ {+ color = 0xFFFFCC66;+ }+ }+ ret.color = color;+ ret.accentColor = HighlightColor( color );+ ret.thickness = 3.f;+ ret.highlight = true;+ }+ else+ {+ const auto color = inheritedColor ? inheritedColor : GetZoneColor( ev, thread, depth );+ ret.color = color;+ ret.accentColor = HighlightColor( color );+ ret.thickness = 1.f;+ ret.highlight = false;+ }+ return ret;+}++View::ZoneColorData View::GetZoneColorData( const GpuEvent& ev )+{+ ZoneColorData ret;+ const auto color = GetZoneColor( ev );+ ret.color = color;+ if( m_gpuInfoWindow == &ev )+ {+ ret.accentColor = 0xFF44DD44;+ ret.thickness = 3.f;+ ret.highlight = true;+ }+ else if( m_gpuHighlight == &ev )+ {+ ret.accentColor = 0xFF4444FF;+ ret.thickness = 3.f;+ ret.highlight = true;+ }+ else+ {+ ret.accentColor = HighlightColor( color );+ ret.thickness = 1.f;+ ret.highlight = false;+ }+ return ret;+}+++const ZoneEvent* View::FindZoneAtTime( uint64_t thread, int64_t time ) const+{+ // TODO add thread rev-map+ ThreadData* td = nullptr;+ for( const auto& t : m_worker.GetThreadData() )+ {+ if( t->id == thread )+ {+ td = t;+ break;+ }+ }+ if( !td ) return nullptr;++ const Vector<short_ptr<ZoneEvent>>* timeline = &td->timeline;+ if( timeline->empty() ) return nullptr;+ const ZoneEvent* ret = nullptr;+ for(;;)+ {+ if( timeline->is_magic() )+ {+ auto vec = (Vector<ZoneEvent>*)timeline;+ auto it = std::upper_bound( vec->begin(), vec->end(), time, [] ( const auto& l, const auto& r ) { return l < r.Start(); } );+ if( it != vec->begin() ) --it;+ if( it->Start() > time || ( it->IsEndValid() && it->End() < time ) ) return ret;+ ret = it;+ if( !it->HasChildren() ) return ret;+ timeline = &m_worker.GetZoneChildren( it->Child() );+ }+ else+ {+ auto it = std::upper_bound( timeline->begin(), timeline->end(), time, [] ( const auto& l, const auto& r ) { return l < r->Start(); } );+ if( it != timeline->begin() ) --it;+ if( (*it)->Start() > time || ( (*it)->IsEndValid() && (*it)->End() < time ) ) return ret;+ ret = *it;+ if( !(*it)->HasChildren() ) return ret;+ timeline = &m_worker.GetZoneChildren( (*it)->Child() );+ }+ }+}++const ZoneEvent* View::GetZoneChild( const ZoneEvent& zone, int64_t time ) const+{+ if( !zone.HasChildren() ) return nullptr;+ auto& children = m_worker.GetZoneChildren( zone.Child() );+ if( children.is_magic() )+ {+ auto& vec = *((Vector<ZoneEvent>*)&children);+ auto it = std::upper_bound( vec.begin(), vec.end(), time, [] ( const auto& l, const auto& r ) { return l < r.Start(); } );+ if( it != vec.begin() ) --it;+ if( it->Start() > time || ( it->IsEndValid() && it->End() < time ) ) return nullptr;+ return it;+ }+ else+ {+ auto it = std::upper_bound( children.begin(), children.end(), time, [] ( const auto& l, const auto& r ) { return l < r->Start(); } );+ if( it != children.begin() ) --it;+ if( (*it)->Start() > time || ( (*it)->IsEndValid() && (*it)->End() < time ) ) return nullptr;+ return *it;+ }+}++const ZoneEvent* View::GetZoneParent( const ZoneEvent& zone ) const+{+#ifndef TRACY_NO_STATISTICS+ if( m_worker.AreSourceLocationZonesReady() )+ {+ auto& slz = m_worker.GetZonesForSourceLocation( zone.SrcLoc() );+ if( !slz.zones.empty() && slz.zones.is_sorted() )+ {+ auto it = std::lower_bound( slz.zones.begin(), slz.zones.end(), zone.Start(), [] ( const auto& lhs, const auto& rhs ) { return lhs.Zone()->Start() < rhs; } );+ if( it != slz.zones.end() && it->Zone() == &zone )+ {+ return GetZoneParent( zone, m_worker.DecompressThread( it->Thread() ) );+ }+ }+ }+#endif++ for( const auto& thread : m_worker.GetThreadData() )+ {+ const ZoneEvent* parent = nullptr;+ const Vector<short_ptr<ZoneEvent>>* timeline = &thread->timeline;+ if( timeline->empty() ) continue;+ for(;;)+ {+ if( timeline->is_magic() )+ {+ auto vec = (Vector<ZoneEvent>*)timeline;+ auto it = std::upper_bound( vec->begin(), vec->end(), zone.Start(), [] ( const auto& l, const auto& r ) { return l < r.Start(); } );+ if( it != vec->begin() ) --it;+ if( zone.IsEndValid() && it->Start() > zone.End() ) break;+ if( it == &zone ) return parent;+ if( !it->HasChildren() ) break;+ parent = it;+ timeline = &m_worker.GetZoneChildren( parent->Child() );+ }+ else+ {+ auto it = std::upper_bound( timeline->begin(), timeline->end(), zone.Start(), [] ( const auto& l, const auto& r ) { return l < r->Start(); } );+ if( it != timeline->begin() ) --it;+ if( zone.IsEndValid() && (*it)->Start() > zone.End() ) break;+ if( *it == &zone ) return parent;+ if( !(*it)->HasChildren() ) break;+ parent = *it;+ timeline = &m_worker.GetZoneChildren( parent->Child() );+ }+ }+ }+ return nullptr;+}++const ZoneEvent* View::GetZoneParent( const ZoneEvent& zone, uint64_t tid ) const+{+ const auto thread = m_worker.GetThreadData( tid );+ const ZoneEvent* parent = nullptr;+ const Vector<short_ptr<ZoneEvent>>* timeline = &thread->timeline;+ if( timeline->empty() ) return nullptr;+ for(;;)+ {+ if( timeline->is_magic() )+ {+ auto vec = (Vector<ZoneEvent>*)timeline;+ auto it = std::upper_bound( vec->begin(), vec->end(), zone.Start(), [] ( const auto& l, const auto& r ) { return l < r.Start(); } );+ if( it != vec->begin() ) --it;+ if( zone.IsEndValid() && it->Start() > zone.End() ) break;+ if( it == &zone ) return parent;+ if( !it->HasChildren() ) break;+ parent = it;+ timeline = &m_worker.GetZoneChildren( parent->Child() );+ }+ else+ {+ auto it = std::upper_bound( timeline->begin(), timeline->end(), zone.Start(), [] ( const auto& l, const auto& r ) { return l < r->Start(); } );+ if( it != timeline->begin() ) --it;+ if( zone.IsEndValid() && (*it)->Start() > zone.End() ) break;+ if( *it == &zone ) return parent;+ if( !(*it)->HasChildren() ) break;+ parent = *it;+ timeline = &m_worker.GetZoneChildren( parent->Child() );+ }+ }+ return nullptr;+}++bool View::IsZoneReentry( const ZoneEvent& zone ) const+{+#ifndef TRACY_NO_STATISTICS+ if( m_worker.AreSourceLocationZonesReady() )+ {+ auto& slz = m_worker.GetZonesForSourceLocation( zone.SrcLoc() );+ if( !slz.zones.empty() && slz.zones.is_sorted() )+ {+ auto it = std::lower_bound( slz.zones.begin(), slz.zones.end(), zone.Start(), [] ( const auto& lhs, const auto& rhs ) { return lhs.Zone()->Start() < rhs; } );+ if( it != slz.zones.end() && it->Zone() == &zone )+ {+ return IsZoneReentry( zone, m_worker.DecompressThread( it->Thread() ) );+ }+ }+ }+#endif++ for( const auto& thread : m_worker.GetThreadData() )+ {+ const ZoneEvent* parent = nullptr;+ const Vector<short_ptr<ZoneEvent>>* timeline = &thread->timeline;+ if( timeline->empty() ) continue;+ for(;;)+ {+ if( timeline->is_magic() )+ {+ auto vec = (Vector<ZoneEvent>*)timeline;+ auto it = std::upper_bound( vec->begin(), vec->end(), zone.Start(), [] ( const auto& l, const auto& r ) { return l < r.Start(); } );+ if( it != vec->begin() ) --it;+ if( zone.IsEndValid() && it->Start() > zone.End() ) break;+ if( it == &zone ) return false;+ if( !it->HasChildren() ) break;+ parent = it;+ if (parent->SrcLoc() == zone.SrcLoc() ) return true;+ timeline = &m_worker.GetZoneChildren( parent->Child() );+ }+ else+ {+ auto it = std::upper_bound( timeline->begin(), timeline->end(), zone.Start(), [] ( const auto& l, const auto& r ) { return l < r->Start(); } );+ if( it != timeline->begin() ) --it;+ if( zone.IsEndValid() && (*it)->Start() > zone.End() ) break;+ if( *it == &zone ) return false;+ if( !(*it)->HasChildren() ) break;+ parent = *it;+ if (parent->SrcLoc() == zone.SrcLoc() ) return true;+ timeline = &m_worker.GetZoneChildren( parent->Child() );+ }+ }+ }+ return false;+}++bool View::IsZoneReentry( const ZoneEvent& zone, uint64_t tid ) const+{+ const auto thread = m_worker.GetThreadData( tid );+ const ZoneEvent* parent = nullptr;+ const Vector<short_ptr<ZoneEvent>>* timeline = &thread->timeline;+ if( timeline->empty() ) return false;+ for(;;)+ {+ if( timeline->is_magic() )+ {+ auto vec = (Vector<ZoneEvent>*)timeline;+ auto it = std::upper_bound( vec->begin(), vec->end(), zone.Start(), [] ( const auto& l, const auto& r ) { return l < r.Start(); } );+ if( it != vec->begin() ) --it;+ if( zone.IsEndValid() && it->Start() > zone.End() ) break;+ if( it == &zone ) return false;+ if( !it->HasChildren() ) break;+ parent = it;+ if (parent->SrcLoc() == zone.SrcLoc() ) return true;+ timeline = &m_worker.GetZoneChildren( parent->Child() );+ }+ else+ {+ auto it = std::upper_bound( timeline->begin(), timeline->end(), zone.Start(), [] ( const auto& l, const auto& r ) { return l < r->Start(); } );+ if( it != timeline->begin() ) --it;+ if( zone.IsEndValid() && (*it)->Start() > zone.End() ) break;+ if( *it == &zone ) return false;+ if( !(*it)->HasChildren() ) break;+ parent = *it;+ if (parent->SrcLoc() == zone.SrcLoc() ) return true;+ timeline = &m_worker.GetZoneChildren( parent->Child() );+ }+ }+ return false;+}++const GpuEvent* View::GetZoneParent( const GpuEvent& zone ) const+{+ for( const auto& ctx : m_worker.GetGpuData() )+ {+ for( const auto& td : ctx->threadData )+ {+ const GpuEvent* parent = nullptr;+ const Vector<short_ptr<GpuEvent>>* timeline = &td.second.timeline;+ if( timeline->empty() ) continue;+ for(;;)+ {+ if( timeline->is_magic() )+ {+ auto vec = (Vector<GpuEvent>*)timeline;+ auto it = std::upper_bound( vec->begin(), vec->end(), zone.GpuStart(), [] ( const auto& l, const auto& r ) { return (uint64_t)l < (uint64_t)r.GpuStart(); } );+ if( it != vec->begin() ) --it;+ if( zone.GpuEnd() >= 0 && it->GpuStart() > zone.GpuEnd() ) break;+ if( it == &zone ) return parent;+ if( it->Child() < 0 ) break;+ parent = it;+ timeline = &m_worker.GetGpuChildren( parent->Child() );+ }+ else+ {+ auto it = std::upper_bound( timeline->begin(), timeline->end(), zone.GpuStart(), [] ( const auto& l, const auto& r ) { return (uint64_t)l < (uint64_t)r->GpuStart(); } );+ if( it != timeline->begin() ) --it;+ if( zone.GpuEnd() >= 0 && (*it)->GpuStart() > zone.GpuEnd() ) break;+ if( *it == &zone ) return parent;+ if( (*it)->Child() < 0 ) break;+ parent = *it;+ timeline = &m_worker.GetGpuChildren( parent->Child() );+ }+ }+ }+ }+ return nullptr;+}++const ThreadData* View::GetZoneThreadData( const ZoneEvent& zone ) const+{+#ifndef TRACY_NO_STATISTICS+ if( m_worker.AreSourceLocationZonesReady() )+ {+ auto& slz = m_worker.GetZonesForSourceLocation( zone.SrcLoc() );+ if( !slz.zones.empty() && slz.zones.is_sorted() )+ {+ auto it = std::lower_bound( slz.zones.begin(), slz.zones.end(), zone.Start(), [] ( const auto& lhs, const auto& rhs ) { return lhs.Zone()->Start() < rhs; } );+ if( it != slz.zones.end() && it->Zone() == &zone )+ {+ return m_worker.GetThreadData( m_worker.DecompressThread( it->Thread() ) );+ }+ }+ }+#endif++ for( const auto& thread : m_worker.GetThreadData() )+ {+ const Vector<short_ptr<ZoneEvent>>* timeline = &thread->timeline;+ if( timeline->empty() ) continue;+ for(;;)+ {+ if( timeline->is_magic() )+ {+ auto vec = (Vector<ZoneEvent>*)timeline;+ auto it = std::upper_bound( vec->begin(), vec->end(), zone.Start(), [] ( const auto& l, const auto& r ) { return l < r.Start(); } );+ if( it != vec->begin() ) --it;+ if( zone.IsEndValid() && it->Start() > zone.End() ) break;+ if( it == &zone ) return thread;+ if( !it->HasChildren() ) break;+ timeline = &m_worker.GetZoneChildren( it->Child() );+ }+ else+ {+ auto it = std::upper_bound( timeline->begin(), timeline->end(), zone.Start(), [] ( const auto& l, const auto& r ) { return l < r->Start(); } );+ if( it != timeline->begin() ) --it;+ if( zone.IsEndValid() && (*it)->Start() > zone.End() ) break;+ if( *it == &zone ) return thread;+ if( !(*it)->HasChildren() ) break;+ timeline = &m_worker.GetZoneChildren( (*it)->Child() );+ }+ }+ }+ return nullptr;+}++uint64_t View::GetZoneThread( const ZoneEvent& zone ) const+{+ auto threadData = GetZoneThreadData( zone );+ return threadData ? threadData->id : 0;+}++uint64_t View::GetZoneThread( const GpuEvent& zone ) const+{+ if( zone.Thread() == 0 )+ {+ for( const auto& ctx : m_worker.GetGpuData() )+ {+ if ( ctx->threadData.size() != 1 ) continue;+ const Vector<short_ptr<GpuEvent>>* timeline = &ctx->threadData.begin()->second.timeline;+ if( timeline->empty() ) continue;+ for(;;)+ {+ if( timeline->is_magic() )+ {+ auto vec = (Vector<GpuEvent>*)timeline;+ auto it = std::upper_bound( vec->begin(), vec->end(), zone.GpuStart(), [] ( const auto& l, const auto& r ) { return (uint64_t)l < (uint64_t)r.GpuStart(); } );+ if( it != vec->begin() ) --it;+ if( zone.GpuEnd() >= 0 && it->GpuStart() > zone.GpuEnd() ) break;+ if( it == &zone ) return ctx->thread;+ if( it->Child() < 0 ) break;+ timeline = &m_worker.GetGpuChildren( it->Child() );+ }+ else+ {+ auto it = std::upper_bound( timeline->begin(), timeline->end(), zone.GpuStart(), [] ( const auto& l, const auto& r ) { return (uint64_t)l < (uint64_t)r->GpuStart(); } );+ if( it != timeline->begin() ) --it;+ if( zone.GpuEnd() >= 0 && (*it)->GpuStart() > zone.GpuEnd() ) break;+ if( *it == &zone ) return ctx->thread;+ if( (*it)->Child() < 0 ) break;+ timeline = &m_worker.GetGpuChildren( (*it)->Child() );+ }+ }+ }+ return 0;+ }+ else+ {+ return m_worker.DecompressThread( zone.Thread() );+ }+}++const GpuCtxData* View::GetZoneCtx( const GpuEvent& zone ) const+{+ for( const auto& ctx : m_worker.GetGpuData() )+ {+ for( const auto& td : ctx->threadData )+ {+ const Vector<short_ptr<GpuEvent>>* timeline = &td.second.timeline;+ if( timeline->empty() ) continue;+ for(;;)+ {+ if( timeline->is_magic() )+ {+ auto vec = (Vector<GpuEvent>*)timeline;+ auto it = std::upper_bound( vec->begin(), vec->end(), zone.GpuStart(), [] ( const auto& l, const auto& r ) { return (uint64_t)l < (uint64_t)r.GpuStart(); } );+ if( it != vec->begin() ) --it;+ if( zone.GpuEnd() >= 0 && it->GpuStart() > zone.GpuEnd() ) break;+ if( it == &zone ) return ctx;+ if( it->Child() < 0 ) break;+ timeline = &m_worker.GetGpuChildren( it->Child() );+ }+ else+ {+ auto it = std::upper_bound( timeline->begin(), timeline->end(), zone.GpuStart(), [] ( const auto& l, const auto& r ) { return (uint64_t)l < (uint64_t)r->GpuStart(); } );+ if( it != timeline->begin() ) --it;+ if( zone.GpuEnd() >= 0 && (*it)->GpuStart() > zone.GpuEnd() ) break;+ if( *it == &zone ) return ctx;+ if( (*it)->Child() < 0 ) break;+ timeline = &m_worker.GetGpuChildren( (*it)->Child() );+ }+ }+ }+ }+ return nullptr;+}++int64_t View::GetZoneChildTime( const ZoneEvent& zone )+{+ int64_t time = 0;+ if( zone.HasChildren() )+ {+ auto& children = m_worker.GetZoneChildren( zone.Child() );+ if( children.is_magic() )+ {+ auto& vec = *(Vector<ZoneEvent>*)&children;+ for( auto& v : vec )+ {+ const auto childSpan = std::max( int64_t( 0 ), v.End() - v.Start() );+ time += childSpan;+ }+ }+ else+ {+ for( auto& v : children )+ {+ const auto childSpan = std::max( int64_t( 0 ), v->End() - v->Start() );+ time += childSpan;+ }+ }+ }+ return time;+}++int64_t View::GetZoneChildTime( const GpuEvent& zone )+{+ int64_t time = 0;+ if( zone.Child() >= 0 )+ {+ auto& children = m_worker.GetGpuChildren( zone.Child() );+ if( children.is_magic() )+ {+ auto& vec = *(Vector<GpuEvent>*)&children;+ for( auto& v : vec )+ {+ const auto childSpan = std::max( int64_t( 0 ), v.GpuEnd() - v.GpuStart() );+ time += childSpan;+ }+ }+ else+ {+ for( auto& v : children )+ {+ const auto childSpan = std::max( int64_t( 0 ), v->GpuEnd() - v->GpuStart() );+ time += childSpan;+ }+ }+ }+ return time;+}++int64_t View::GetZoneChildTimeFast( const ZoneEvent& zone )+{+ int64_t time = 0;+ if( zone.HasChildren() )+ {+ auto& children = m_worker.GetZoneChildren( zone.Child() );+ if( children.is_magic() )+ {+ auto& vec = *(Vector<ZoneEvent>*)&children;+ for( auto& v : vec )+ {+ assert( v.IsEndValid() );+ time += v.End() - v.Start();+ }+ }+ else+ {+ for( auto& v : children )+ {+ assert( v->IsEndValid() );+ time += v->End() - v->Start();+ }+ }+ }+ return time;+}++int64_t View::GetZoneChildTimeFastClamped( const ZoneEvent& zone, int64_t t0, int64_t t1 )+{+ int64_t time = 0;+ if( zone.HasChildren() )+ {+ auto& children = m_worker.GetZoneChildren( zone.Child() );+ if( children.is_magic() )+ {+ auto& vec = *(Vector<ZoneEvent>*)&children;+ auto it = std::lower_bound( vec.begin(), vec.end(), t0, [] ( const auto& l, const auto& r ) { return (uint64_t)l.End() < (uint64_t)r; } );+ if( it == vec.end() ) return 0;+ const auto zitend = std::lower_bound( it, vec.end(), t1, [] ( const auto& l, const auto& r ) { return l.Start() < r; } );+ if( it == zitend ) return 0;+ while( it < zitend )+ {+ const auto c0 = std::max<int64_t>( it->Start(), t0 );+ const auto c1 = std::min<int64_t>( it->End(), t1 );+ time += c1 - c0;+ ++it;+ }+ }+ else+ {+ auto it = std::lower_bound( children.begin(), children.end(), t0, [] ( const auto& l, const auto& r ) { return (uint64_t)l->End() < (uint64_t)r; } );+ if( it == children.end() ) return 0;+ const auto zitend = std::lower_bound( it, children.end(), t1, [] ( const auto& l, const auto& r ) { return l->Start() < r; } );+ if( it == zitend ) return 0;+ while( it < zitend )+ {+ const auto c0 = std::max<int64_t>( (*it)->Start(), t0 );+ const auto c1 = std::min<int64_t>( (*it)->End(), t1 );+ time += c1 - c0;+ ++it;+ }+ }+ }+ return time;+}++int64_t View::GetZoneSelfTime( const ZoneEvent& zone )+{+ if( m_cache.zoneSelfTime.first == &zone ) return m_cache.zoneSelfTime.second;+ if( m_cache.zoneSelfTime2.first == &zone ) return m_cache.zoneSelfTime2.second;+ const auto ztime = m_worker.GetZoneEnd( zone ) - zone.Start();+ const auto selftime = ztime - GetZoneChildTime( zone );+ if( zone.IsEndValid() )+ {+ m_cache.zoneSelfTime2 = m_cache.zoneSelfTime;+ m_cache.zoneSelfTime = std::make_pair( &zone, selftime );+ }+ return selftime;+}++int64_t View::GetZoneSelfTime( const GpuEvent& zone )+{+ if( m_cache.gpuSelfTime.first == &zone ) return m_cache.gpuSelfTime.second;+ if( m_cache.gpuSelfTime2.first == &zone ) return m_cache.gpuSelfTime2.second;+ const auto ztime = m_worker.GetZoneEnd( zone ) - zone.GpuStart();+ const auto selftime = ztime - GetZoneChildTime( zone );+ if( zone.GpuEnd() >= 0 )+ {+ m_cache.gpuSelfTime2 = m_cache.gpuSelfTime;+ m_cache.gpuSelfTime = std::make_pair( &zone, selftime );+ }+ return selftime;+}++bool View::GetZoneRunningTime( const ContextSwitch* ctx, const ZoneEvent& ev, int64_t& time, uint64_t& cnt )+{+ auto it = std::lower_bound( ctx->v.begin(), ctx->v.end(), ev.Start(), [] ( const auto& l, const auto& r ) { return (uint64_t)l.End() < (uint64_t)r; } );+ if( it == ctx->v.end() ) return false;+ const auto end = m_worker.GetZoneEnd( ev );+ const auto eit = std::upper_bound( it, ctx->v.end(), end, [] ( const auto& l, const auto& r ) { return l < r.Start(); } );+ if( eit == ctx->v.end() ) return false;+ cnt = std::distance( it, eit );+ if( cnt == 0 ) return false;+ if( cnt == 1 )+ {+ time = end - ev.Start();+ }+ else+ {+ int64_t running = it->End() - ev.Start();+ ++it;+ for( uint64_t i=0; i<cnt-2; i++ )+ {+ running += it->End() - it->Start();+ ++it;+ }+ running += end - it->Start();+ time = running;+ }+ return true;+}++bool View::GetZoneRunningTime( const ContextSwitch* ctx, const ZoneEvent& ev, const RangeSlim& range, int64_t& time, uint64_t& cnt )+{+ const auto start = std::max( ev.Start(), range.min );+ auto it = std::lower_bound( ctx->v.begin(), ctx->v.end(), start, [] ( const auto& l, const auto& r ) { return (uint64_t)l.End() < (uint64_t)r; } );+ if( it == ctx->v.end() ) return false;+ const auto end = std::min( m_worker.GetZoneEnd( ev ), range.max );+ const auto eit = std::upper_bound( it, ctx->v.end(), end, [] ( const auto& l, const auto& r ) { return l < r.Start(); } );+ if( eit == ctx->v.end() ) return false;+ cnt = std::distance( it, eit );+ if( cnt == 0 ) return false;+ if( cnt == 1 )+ {+ time = end - start;+ }+ else+ {+ int64_t running = it->End() - start;+ ++it;+ for( uint64_t i=0; i<cnt-2; i++ )+ {+ running += it->End() - it->Start();+ ++it;+ }+ running += end - it->Start();+ time = running;+ }+ return true;+}++const char* View::SourceSubstitution( const char* srcFile ) const+{+ if( !m_sourceRegexValid || m_sourceSubstitutions.empty() ) return srcFile;+ static std::string res, tmp;+ res.assign( srcFile );+ for( auto& v : m_sourceSubstitutions )+ {+ tmp = std::regex_replace( res, v.regex, v.target );+ std::swap( tmp, res );+ }+ return res.c_str();+}++int64_t View::AdjustGpuTime( int64_t time, int64_t begin, int drift )+{+ if( time < 0 ) return time;+ const auto t = time - begin;+ return time + t / 1000000000 * drift;+}++uint64_t View::GetFrameNumber( const FrameData& fd, int i ) const+{+ if( fd.name == 0 )+ {+ const auto offset = m_worker.GetFrameOffset();+ if( offset == 0 )+ {+ return i;+ }+ else+ {+ return i + offset - 1;+ }+ }+ else+ {+ return i + 1;+ }+}++const char* View::GetFrameText( const FrameData& fd, int i, uint64_t ftime ) const+{+ const auto fnum = GetFrameNumber( fd, i );+ static char buf[1024];+ if( fd.name == 0 )+ {+ if( i == 0 )+ {+ sprintf( buf, "Tracy init (%s)", TimeToString( ftime ) );+ }+ else if( i != 1 || !m_worker.IsOnDemand() )+ {+ sprintf( buf, "Frame %s (%s)", RealToString( fnum ), TimeToString( ftime ) );+ }+ else+ {+ sprintf( buf, "Missed frames (%s)", TimeToString( ftime ) );+ }+ }+ else+ {+ sprintf( buf, "%s %s (%s)", GetFrameSetName( fd ), RealToString( fnum ), TimeToString( ftime ) );+ }+ return buf;+}++const char* View::GetFrameSetName( const FrameData& fd ) const+{+ return GetFrameSetName( fd, m_worker );+}++const char* View::GetFrameSetName( const FrameData& fd, const Worker& worker )+{+ enum { Pool = 4 };+ static char bufpool[Pool][64];+ static int bufsel = 0;++ if( fd.name == 0 )+ {+ return "Frames";+ }+ else if( fd.name >> 63 != 0 )+ {+ char* buf = bufpool[bufsel];+ bufsel = ( bufsel + 1 ) % Pool;+ sprintf( buf, "[%" PRIu32 "] Vsync", uint32_t( fd.name ) );+ return buf;+ }+ else+ {+ return worker.GetString( fd.name );+ }+}++const char* View::GetThreadContextData( uint64_t thread, bool& _local, bool& _untracked, const char*& program )+{+ static char buf[256];+ const auto local = m_worker.IsThreadLocal( thread );+ auto txt = local ? m_worker.GetThreadName( thread ) : m_worker.GetExternalName( thread ).first;+ auto label = txt;+ bool untracked = false;+ if( !local )+ {+ if( m_worker.GetPid() == 0 )+ {+ untracked = strcmp( txt, m_worker.GetCaptureProgram().c_str() ) == 0;+ }+ else+ {+ const auto pid = m_worker.GetPidFromTid( thread );+ untracked = pid == m_worker.GetPid();+ if( untracked )+ {+ label = txt = m_worker.GetExternalName( thread ).second;+ }+ else+ {+ const auto ttxt = m_worker.GetExternalName( thread ).second;+ if( strcmp( ttxt, "???" ) != 0 && strcmp( ttxt, txt ) != 0 )+ {+ snprintf( buf, 256, "%s (%s)", txt, ttxt );+ label = buf;+ }+ }+ }+ }+ _local = local;+ _untracked = untracked;+ program = txt;+ return label;+}++void View::Attention( bool& alreadyDone )+{+ if( !alreadyDone )+ {+ alreadyDone = true;+ m_acb();+ }+}++void View::UpdateTitle()+{+ auto captureName = m_worker.GetCaptureName().c_str();+ const auto& desc = m_userData.GetDescription();+ if( !desc.empty() )+ {+ char buf[1024];+ snprintf( buf, 1024, "%s (%s)", captureName, desc.c_str() );+ m_stcb( buf );+ }+ else if( !m_filename.empty() )+ {+ auto fptr = m_filename.c_str() + m_filename.size() - 1;+ while( fptr > m_filename.c_str() && *fptr != '/' && *fptr != '\\' ) fptr--;+ if( *fptr == '/' || *fptr == '\\' ) fptr++;++ char buf[1024];+ snprintf( buf, 1024, "%s (%s)", captureName, fptr );+ m_stcb( buf );+ }+ else+ {+ m_stcb( captureName );+ }+}++}
+ cbits/tracy/profiler/src/profiler/TracyView_ZoneInfo.cpp view
@@ -0,0 +1,2052 @@+#include <inttypes.h>++#include "TracyFilesystem.hpp"+#include "TracyImGui.hpp"+#include "TracyPrint.hpp"+#include "TracyMouse.hpp"+#include "TracyView.hpp"+#include "tracy_pdqsort.h"++namespace tracy+{++extern double s_time;++template<typename T>+static inline uint32_t GetZoneCallstack( const T& ev, const Worker& worker );++template<>+inline uint32_t GetZoneCallstack<ZoneEvent>( const ZoneEvent& ev, const Worker& worker )+{+ return worker.GetZoneExtra( ev ).callstack.Val();+}++template<>+inline uint32_t GetZoneCallstack<GpuEvent>( const GpuEvent& ev, const Worker& worker )+{+ return ev.callstack.Val();+}++void View::CalcZoneTimeData( unordered_flat_map<int16_t, ZoneTimeData>& data, int64_t& ztime, const ZoneEvent& zone )+{+ assert( zone.HasChildren() );+ const auto& children = m_worker.GetZoneChildren( zone.Child() );+ if( children.is_magic() )+ {+ CalcZoneTimeDataImpl<VectorAdapterDirect<ZoneEvent>>( *(Vector<ZoneEvent>*)( &children ), data, ztime );+ }+ else+ {+ CalcZoneTimeDataImpl<VectorAdapterPointer<ZoneEvent>>( children, data, ztime );+ }+}++template<typename Adapter, typename V>+void View::CalcZoneTimeDataImpl( const V& children, unordered_flat_map<int16_t, ZoneTimeData>& data, int64_t& ztime )+{+ Adapter a;+ if( m_timeDist.exclusiveTime )+ {+ int64_t zt = ztime;+ for( auto& child : children )+ {+ const auto t = m_worker.GetZoneEnd( a(child) ) - a(child).Start();+ zt -= t;+ }+ ztime = zt;+ }+ for( auto& child : children )+ {+ const auto srcloc = a(child).SrcLoc();+ const auto t = m_worker.GetZoneEnd( a(child) ) - a(child).Start();+ auto it = data.find( srcloc );+ if( it == data.end() )+ {+ it = data.emplace( srcloc, ZoneTimeData { t, 1 } ).first;+ }+ else+ {+ it->second.time += t;+ it->second.count++;+ }+ if( a(child).Child() >= 0 ) CalcZoneTimeData( data, it->second.time, a(child) );+ }+}++void View::CalcZoneTimeData( const ContextSwitch* ctx, unordered_flat_map<int16_t, ZoneTimeData>& data, int64_t& ztime, const ZoneEvent& zone )+{+ assert( zone.HasChildren() );+ const auto& children = m_worker.GetZoneChildren( zone.Child() );+ if( children.is_magic() )+ {+ CalcZoneTimeDataImpl<VectorAdapterDirect<ZoneEvent>>( *(Vector<ZoneEvent>*)( &children ), ctx, data, ztime );+ }+ else+ {+ CalcZoneTimeDataImpl<VectorAdapterPointer<ZoneEvent>>( children, ctx, data, ztime );+ }+}++template<typename Adapter, typename V>+void View::CalcZoneTimeDataImpl( const V& children, const ContextSwitch* ctx, unordered_flat_map<int16_t, ZoneTimeData>& data, int64_t& ztime )+{+ Adapter a;+ if( m_timeDist.exclusiveTime )+ {+ int64_t zt = ztime;+ for( auto& child : children )+ {+ int64_t t;+ uint64_t cnt;+ const auto res = GetZoneRunningTime( ctx, a(child), t, cnt );+ assert( res );+ zt -= t;+ }+ ztime = zt;+ }+ for( auto& child : children )+ {+ const auto srcloc = a(child).SrcLoc();+ int64_t t;+ uint64_t cnt;+ const auto res = GetZoneRunningTime( ctx, a(child), t, cnt );+ assert( res );+ auto it = data.find( srcloc );+ if( it == data.end() )+ {+ it = data.emplace( srcloc, ZoneTimeData { t, 1 } ).first;+ }+ else+ {+ it->second.time += t;+ it->second.count++;+ }+ if( a(child).HasChildren() ) CalcZoneTimeData( ctx, data, it->second.time, a(child) );+ }+}++template<typename T>+void DrawZoneTrace( T zone, const std::vector<T>& trace, const Worker& worker, BuzzAnim<const void*>& anim, View& view, bool& showUnknownFrames, std::function<void(T, int&)> showZone )+{+ bool expand = ImGui::TreeNode( "Zone trace" );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( trace.size() ) );+ if( !expand ) return;++ const auto shortenName = view.GetShortenName();++ ImGui::SameLine();+ SmallCheckbox( "Show unknown frames", &showUnknownFrames );++ int fidx = 1;+ TextDisabledUnformatted( "0." );+ ImGui::SameLine();+ TextDisabledUnformatted( "[this zone]" );++ if( !trace.empty() )+ {+ T prev = zone;+ const auto sz = trace.size();+ for( size_t i=0; i<sz; i++ )+ {+ auto curr = trace[i];+ const auto pcv = GetZoneCallstack( *prev, worker );+ const auto ccv = GetZoneCallstack( *curr, worker );+ if( pcv == 0 || ccv == 0 )+ {+ if( showUnknownFrames )+ {+ ImGui::TextDisabled( "%i.", fidx++ );+ ImGui::SameLine();+ TextDisabledUnformatted( "[unknown frames]" );+ }+ }+ else if( pcv != ccv )+ {+ auto& prevCs = worker.GetCallstack( pcv );+ auto& currCs = worker.GetCallstack( ccv );++ const auto psz = int( prevCs.size() );+ int idx;+ for( idx=0; idx<psz; idx++ )+ {+ auto pf = prevCs[idx];+ bool found = false;+ for( auto& cf : currCs )+ {+ if( cf.data == pf.data )+ {+ idx--;+ found = true;+ break;+ }+ }+ if( found ) break;+ }+ for( int j=1; j<idx; j++ )+ {+ auto frameData = worker.GetCallstackFrame( prevCs[j] );+ auto frame = frameData->data + frameData->size - 1;+ ImGui::TextDisabled( "%i.", fidx++ );+ ImGui::SameLine();+ const auto frameName = worker.GetString( frame->name );+ const auto normalized = shortenName != ShortenName::Never ? ShortenZoneName( ShortenName::OnlyNormalize, frameName ) : frameName;+ TextDisabledUnformatted( normalized );+ TooltipNormalizedName( frameName, normalized );+ ImGui::SameLine();+ ImGui::Spacing();+ if( anim.Match( frame ) )+ {+ const auto time = anim.Time();+ const auto indentVal = sin( time * 60.f ) * 10.f * time;+ ImGui::SameLine( 0, ImGui::GetStyle().ItemSpacing.x + indentVal );+ s_wasActive = true;+ }+ else+ {+ ImGui::SameLine();+ }+ const auto fileName = worker.GetString( frame->file );+ TextDisabledUnformatted( LocationToString( fileName, frame->line ) );+ if( ImGui::IsItemClicked( 1 ) )+ {+ if( !view.ViewDispatch( fileName, frame->line, frame->symAddr ) )+ {+ anim.Enable( frame, 0.5f );+ }+ }+ }+ }++ showZone( curr, fidx );+ prev = curr;+ }+ }++ auto last = trace.empty() ? zone : trace.back();+ const auto lcv = GetZoneCallstack( *last, worker );+ if( lcv == 0 )+ {+ if( showUnknownFrames )+ {+ ImGui::TextDisabled( "%i.", fidx++ );+ ImGui::SameLine();+ TextDisabledUnformatted( "[unknown frames]" );+ }+ }+ else+ {+ auto& cs = worker.GetCallstack( lcv );+ const auto csz = cs.size();+ for( uint16_t i=1; i<csz; i++ )+ {+ auto frameData = worker.GetCallstackFrame( cs[i] );+ auto frame = frameData->data + frameData->size - 1;+ ImGui::TextDisabled( "%i.", fidx++ );+ ImGui::SameLine();+ const auto frameName = worker.GetString( frame->name );+ const auto normalized = shortenName != ShortenName::Never ? ShortenZoneName( ShortenName::OnlyNormalize, frameName ) : frameName;+ TextDisabledUnformatted( normalized );+ TooltipNormalizedName( frameName, normalized );+ ImGui::SameLine();+ ImGui::Spacing();+ if( anim.Match( frame ) )+ {+ const auto time = anim.Time();+ const auto indentVal = sin( time * 60.f ) * 10.f * time;+ ImGui::SameLine( 0, ImGui::GetStyle().ItemSpacing.x + indentVal );+ s_wasActive = true;+ }+ else+ {+ ImGui::SameLine();+ }+ const auto fileName = worker.GetString( frame->file );+ TextDisabledUnformatted( LocationToString( fileName, frame->line ) );+ if( ImGui::IsItemClicked( 1 ) )+ {+ if( !view.ViewDispatch( fileName, frame->line, frame->symAddr ) )+ {+ anim.Enable( frame, 0.5f );+ }+ }+ }+ }++ ImGui::TreePop();+}++void View::DrawInfoWindow()+{+ if( m_zoneInfoWindow )+ {+ DrawZoneInfoWindow();+ }+ else if( m_gpuInfoWindow )+ {+ DrawGpuInfoWindow();+ }+}++void View::DrawZoneInfoWindow()+{+ auto& ev = *m_zoneInfoWindow;++ const auto& srcloc = m_worker.GetSourceLocation( ev.SrcLoc() );++ const auto scale = GetScale();+ ImGui::SetNextWindowSize( ImVec2( 500 * scale, 600 * scale ), ImGuiCond_FirstUseEver );+ bool show = true;+ ImGui::Begin( "Zone info", &show, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse );+ if( !ImGui::GetCurrentWindowRead()->SkipItems )+ {+ if( ImGui::Button( ICON_FA_MICROSCOPE " Zoom to zone" ) )+ {+ ZoomToZone( ev );+ }+ auto parent = GetZoneParent( ev );+ if( parent )+ {+ ImGui::SameLine();+ if( ImGui::Button( ICON_FA_ARROW_UP " Go to parent" ) )+ {+ ShowZoneInfo( *parent );+ }+ }+#ifndef TRACY_NO_STATISTICS+ if( m_worker.AreSourceLocationZonesReady() )+ {+ const auto sl = ev.SrcLoc();+ const auto& slz = m_worker.GetZonesForSourceLocation( sl );+ if( !slz.zones.empty() )+ {+ ImGui::SameLine();+ if( ImGui::Button( ICON_FA_CHART_BAR " Statistics" ) )+ {+ m_findZone.ShowZone( sl, m_worker.GetString( srcloc.name.active ? srcloc.name : srcloc.function ) );+ }+ }+ }+#endif+ if( m_worker.HasZoneExtra( ev ) && m_worker.GetZoneExtra( ev ).callstack.Val() != 0 )+ {+ const auto& extra = m_worker.GetZoneExtra( ev );+ ImGui::SameLine();+ bool hilite = m_callstackInfoWindow == extra.callstack.Val();+ if( hilite )+ {+ SetButtonHighlightColor();+ }+ if( ImGui::Button( ICON_FA_ALIGN_JUSTIFY " Call stack" ) )+ {+ m_callstackInfoWindow = extra.callstack.Val();+ }+ if( hilite )+ {+ ImGui::PopStyleColor( 3 );+ }+ }+ const auto fileName = m_worker.GetString( srcloc.file );+ if( SourceFileValid( fileName, m_worker.GetCaptureTime(), *this, m_worker ) )+ {+ ImGui::SameLine();+ bool hilite = m_sourceViewFile == fileName;+ if( hilite )+ {+ SetButtonHighlightColor();+ }+ if( ImGui::Button( ICON_FA_FILE_LINES " Source" ) )+ {+ ViewSourceCheckKeyMod( fileName, srcloc.line, m_worker.GetString( srcloc.function ) );+ }+ if( hilite )+ {+ ImGui::PopStyleColor( 3 );+ }+ }+ if( !m_zoneInfoStack.empty() )+ {+ ImGui::SameLine();+ if( ImGui::Button( ICON_FA_ARROW_LEFT " Go back" ) )+ {+ m_zoneInfoWindow = m_zoneInfoStack.back_and_pop();+ }+ }++ ImGui::Separator();++ auto threadData = GetZoneThreadData( ev );+ assert( threadData );+ const auto tid = threadData->id;+ if( m_worker.HasZoneExtra( ev ) && m_worker.GetZoneExtra( ev ).name.Active() )+ {+ ImGui::PushFont( m_bigFont );+ TextFocused( "Zone name:", m_worker.GetString( m_worker.GetZoneExtra( ev ).name ) );+ ImGui::PopFont();+ if( srcloc.name.active )+ {+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", m_worker.GetString( srcloc.name ) );+ }+ ImGui::SameLine();+ if( ClipboardButton( 1 ) )+ {+ if( srcloc.name.active )+ {+ char tmp[1024];+ sprintf( tmp, "%s (%s)", m_worker.GetString( m_worker.GetZoneExtra( ev ).name ), m_worker.GetString( srcloc.name ) );+ ImGui::SetClipboardText( tmp );+ }+ else+ {+ ImGui::SetClipboardText( m_worker.GetString( m_worker.GetZoneExtra( ev ).name ) );+ }+ }+ TextFocused( "Function:", m_worker.GetString( srcloc.function ) );+ ImGui::SameLine();+ if( ClipboardButton( 2 ) ) ImGui::SetClipboardText( m_worker.GetString( srcloc.function ) );+ }+ else if( srcloc.name.active )+ {+ ImGui::PushFont( m_bigFont );+ TextFocused( "Zone name:", m_worker.GetString( srcloc.name ) );+ ImGui::PopFont();+ ImGui::SameLine();+ if( ClipboardButton( 1 ) ) ImGui::SetClipboardText( m_worker.GetString( srcloc.name ) );+ TextFocused( "Function:", m_worker.GetString( srcloc.function ) );+ ImGui::SameLine();+ if( ClipboardButton( 2 ) ) ImGui::SetClipboardText( m_worker.GetString( srcloc.function ) );+ }+ else+ {+ ImGui::PushFont( m_bigFont );+ TextFocused( "Function:", m_worker.GetString( srcloc.function ) );+ ImGui::PopFont();+ ImGui::SameLine();+ if( ClipboardButton( 1 ) ) ImGui::SetClipboardText( m_worker.GetString( srcloc.function ) );+ }+ SmallColorBox( GetSrcLocColor( m_worker.GetSourceLocation( ev.SrcLoc() ), 0 ) );+ ImGui::SameLine();+ TextDisabledUnformatted( "Location:" );+ ImGui::SameLine();+ ImGui::TextUnformatted( LocationToString( m_worker.GetString( srcloc.file ), srcloc.line ) );+ ImGui::SameLine();+ if( ClipboardButton( 3 ) )+ {+ ImGui::SetClipboardText( LocationToString( m_worker.GetString( srcloc.file ), srcloc.line ) );+ }+ SmallColorBox( GetThreadColor( tid, 0 ) );+ ImGui::SameLine();+ TextFocused( "Thread:", m_worker.GetThreadName( tid ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( tid ) );+ if( m_worker.IsThreadFiber( tid ) )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 0.2f, 0.6f, 0.2f, 1.f ), "Fiber" );+ }+ if( m_worker.HasZoneExtra( ev ) && m_worker.GetZoneExtra( ev ).text.Active() )+ {+ TextDisabledUnformatted( "User text:" );+ ImGui::SameLine();+ if( ClipboardButton( 4 ) )+ {+ ImGui::SetClipboardText( m_worker.GetString( m_worker.GetZoneExtra( ev ).text ) );+ }+ ImGui::SameLine();+ ImGui::TextUnformatted( m_worker.GetString( m_worker.GetZoneExtra( ev ).text ) );+ }++ ImGui::Separator();+ ImGui::BeginChild( "##zoneinfo" );++ const auto end = m_worker.GetZoneEnd( ev );+ const auto ztime = end - ev.Start();+ const auto selftime = GetZoneSelfTime( ev );+ TextFocused( "Time from start of program:", TimeToStringExact( ev.Start() ) );+ const std::time_t ts = m_worker.GetCaptureTime() + ev.Start() / 1000000000;+ TextFocused( "Wall clock time:", std::asctime( std::localtime( &ts) ) );+ TextFocused( "Execution time:", TimeToString( ztime ) );+#ifndef TRACY_NO_STATISTICS+ if( m_worker.AreSourceLocationZonesReady() )+ {+ auto& zoneData = m_worker.GetZonesForSourceLocation( ev.SrcLoc() );+ if( zoneData.total > 0 )+ {+ ImGui::SameLine();+ ImGui::TextDisabled( "(%.2f%% of mean time)", float( ztime ) / zoneData.total * zoneData.zones.size() * 100 );+ }+ }+#endif+ TextFocused( "Self time:", TimeToString( selftime ) );+ if( ztime != 0 )+ {+ char buf[64];+ PrintStringPercent( buf, 100.f * selftime / ztime );+ ImGui::SameLine();+ TextDisabledUnformatted( buf );+ }+ const auto ctx = m_worker.GetContextSwitchData( tid );+ if( ctx )+ {+ auto it = std::lower_bound( ctx->v.begin(), ctx->v.end(), ev.Start(), [] ( const auto& l, const auto& r ) { return (uint64_t)l.End() < (uint64_t)r; } );+ if( it != ctx->v.end() )+ {+ const auto end = m_worker.GetZoneEnd( ev );+ auto eit = std::upper_bound( it, ctx->v.end(), end, [] ( const auto& l, const auto& r ) { return l < r.Start(); } );+ bool incomplete = eit == ctx->v.end() && !m_worker.IsThreadFiber( tid );+ uint64_t cnt = std::distance( it, eit );+ if( cnt == 1 )+ {+ if( !incomplete )+ {+ TextFocused( "Running state time:", TimeToString( ztime ) );+ ImGui::SameLine();+ TextDisabledUnformatted( "(100%)" );+ ImGui::Separator();+ TextFocused( "Running state regions:", "1" );+ if( !threadData->isFiber ) TextFocused( "CPU:", RealToString( it->Cpu() ) );+ }+ }+ else if( cnt > 1 )+ {+ uint8_t cpus[256] = {};+ auto bit = it;+ int64_t running = it->End() - ev.Start();+ cpus[it->Cpu()] = 1;+ ++it;+ for( uint64_t i=0; i<cnt-2; i++ )+ {+ running += it->End() - it->Start();+ cpus[it->Cpu()] = 1;+ ++it;+ }+ running += end - it->Start();+ cpus[it->Cpu()] = 1;+ TextFocused( "Running state time:", TimeToString( running ) );+ if( ztime != 0 )+ {+ char buf[64];+ PrintStringPercent( buf, 100.f * running / ztime );+ ImGui::SameLine();+ TextDisabledUnformatted( buf );+ }+ ImGui::Separator();+ if( incomplete )+ {+ TextColoredUnformatted( ImVec4( 1, 0, 0, 1 ), "Incomplete context switch data!" );+ }+ TextFocused( "Running state regions:", RealToString( cnt ) );++ if( !threadData->isFiber )+ {+ int numCpus = 0;+ for( int i=0; i<256; i++ ) numCpus += cpus[i];+ if( numCpus == 1 )+ {+ TextFocused( "CPU:", RealToString( it->Cpu() ) );+ }+ else+ {+ ImGui::TextDisabled( "CPUs (%i):", numCpus );+ for( int i=0;; i++ )+ {+ if( cpus[i] != 0 )+ {+ ImGui::SameLine();+ numCpus--;+ if( numCpus == 0 )+ {+ ImGui::Text( "%i", i );+ break;+ }+ else+ {+ int consecutive = 1;+ int remaining = numCpus;+ for(;;)+ {+ if( cpus[i+consecutive] == 0 ) break;+ consecutive++;+ if( --remaining == 0 ) break;+ }+ if( consecutive > 2 )+ {+ if( remaining == 0 )+ {+ ImGui::Text( "%i \xE2\x80\x93 %i", i, i+consecutive-1 );+ break;+ }+ else+ {+ ImGui::Text( "%i \xE2\x80\x93 %i,", i, i+consecutive-1 );+ i += consecutive - 1;+ numCpus = remaining;+ }+ }+ else+ {+ ImGui::Text( "%i,", i );+ }+ }+ }+ }+ }+ }++ --eit;+ if( ImGui::TreeNode( "Wait regions" ) )+ {+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ SmallCheckbox( "Time relative to zone start", &m_ctxSwitchTimeRelativeToZone );+ const int64_t adjust = m_ctxSwitchTimeRelativeToZone ? ev.Start() : 0;+ const auto wrsz = eit - bit;++ const auto numColumns = threadData->isFiber ? 4 : 6;+ if( ImGui::BeginTable( "##waitregions", numColumns, ImGuiTableFlags_Resizable | ImGuiTableFlags_ScrollY | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable, ImVec2( 0, ImGui::GetTextLineHeightWithSpacing() * std::min<int64_t>( 1+wrsz, 15 ) ) ) )+ {+ ImGui::TableSetupScrollFreeze( 0, 1 );+ ImGui::TableSetupColumn( "Begin" );+ ImGui::TableSetupColumn( "End" );+ ImGui::TableSetupColumn( "Time" );+ if( threadData->isFiber )+ {+ ImGui::TableSetupColumn( "Thread" );+ }+ else+ {+ ImGui::TableSetupColumn( "Wakeup" );+ ImGui::TableSetupColumn( "CPU" );+ ImGui::TableSetupColumn( "State" );+ }+ ImGui::TableHeadersRow();++ ImGuiListClipper clipper;+ clipper.Begin( wrsz );+ while( clipper.Step() )+ {+ for( auto i=clipper.DisplayStart; i<clipper.DisplayEnd; i++ )+ {+ const auto cend = bit[i].End();+ const auto cstart = bit[i+1].Start();+ const auto cwakeup = bit[i+1].WakeupVal();++ ImGui::PushID( i );+ ImGui::TableNextRow();+ ImGui::TableNextColumn();++ auto tt = adjust == 0 ? TimeToStringExact( cend ) : TimeToString( cend - adjust );+ if( ImGui::Selectable( tt ) )+ {+ CenterAtTime( cend );+ }+ ImGui::TableNextColumn();+ tt = adjust == 0 ? TimeToStringExact( cstart ) : TimeToString( cstart - adjust );+ if( ImGui::Selectable( tt ) )+ {+ CenterAtTime( cstart );+ }+ ImGui::TableNextColumn();+ if( ImGui::Selectable( TimeToString( cwakeup - cend ) ) )+ {+ ZoomToRange( cend, cwakeup );+ }+ ImGui::TableNextColumn();+ if( threadData->isFiber )+ {+ const auto ftid = m_worker.DecompressThread( bit[i].Thread() );+ ImGui::TextUnformatted( m_worker.GetThreadName( ftid ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( ftid ) );+ }+ else+ {+ const auto cpu0 = bit[i].Cpu();+ const auto reason = bit[i].Reason();+ const auto state = bit[i].State();+ const auto cpu1 = bit[i+1].Cpu();++ if( cstart != cwakeup )+ {+ if( ImGui::Selectable( TimeToString( cstart - cwakeup ) ) )+ {+ ZoomToRange( cwakeup, cstart );+ }+ }+ else+ {+ ImGui::TextUnformatted( "-" );+ }+ ImGui::TableNextColumn();+ if( cpu0 == cpu1 )+ {+ ImGui::TextUnformatted( RealToString( cpu0 ) );+ if( ImGui::IsItemHovered() )+ {+ const auto tt = m_worker.GetThreadTopology( cpu0 );+ if( tt )+ {+ ImGui::BeginTooltip();+ TextFocused( "Package", RealToString( tt->package ) );+ TextFocused( "Die", RealToString( tt->die ) );+ TextFocused( "Core", RealToString( tt->core ) );+ ImGui::EndTooltip();+ }+ }+ }+ else+ {+ const auto tt0 = m_worker.GetThreadTopology( cpu0 );+ const auto tt1 = m_worker.GetThreadTopology( cpu1 );+ ImGui::Text( "%i ", cpu0 );+ if( tt0 && ImGui::IsItemHovered() )+ {+ ImGui::BeginTooltip();+ TextFocused( "Package", RealToString( tt0->package ) );+ TextFocused( "Die", RealToString( tt0->die ) );+ TextFocused( "Core", RealToString( tt0->core ) );+ ImGui::EndTooltip();+ }+ ImGui::SameLine( 0, 0 );+ TextDisabledUnformatted( ICON_FA_RIGHT_LONG );+ ImGui::SameLine( 0, 0 );+ ImGui::Text( " %i", cpu1 );+ if( tt1 && ImGui::IsItemHovered() )+ {+ ImGui::BeginTooltip();+ TextFocused( "Package", RealToString( tt1->package ) );+ TextFocused( "Die", RealToString( tt1->die ) );+ TextFocused( "Core", RealToString( tt1->core ) );+ ImGui::EndTooltip();+ }+ if( tt0 && tt1 )+ {+ if( tt0->package != tt1->package )+ {+ ImGui::SameLine();+ TextDisabledUnformatted( "P" );+ TooltipIfHovered( "Jump from one CPU package to another" );+ }+ else if( tt0->die != tt1->die )+ {+ ImGui::SameLine();+ TextDisabledUnformatted( "D" );+ TooltipIfHovered( "Jump from one CPU die to another, within the same package" );+ }+ else if( tt0->core != tt1->core )+ {+ ImGui::SameLine();+ TextDisabledUnformatted( "C" );+ TooltipIfHovered( "Jump from one CPU core to another, within the same die" );+ }+ else+ {+ ImGui::SameLine();+ TextDisabledUnformatted( "H" );+ TooltipIfHovered( "Jump from one CPU hyperthread to another, within the same core" );+ }+ }+ }+ ImGui::TableNextColumn();+ const char* desc;+ if( reason == ContextSwitchData::NoState )+ {+ ImGui::TextUnformatted( DecodeContextSwitchStateCode( state ) );+ desc = DecodeContextSwitchState( state );+ }+ else+ {+ ImGui::TextUnformatted( DecodeContextSwitchReasonCode( reason ) );+ desc = DecodeContextSwitchReason( reason );+ }+ if( *desc ) TooltipIfHovered( desc );+ }+ ImGui::PopID();+ }+ }+ ImGui::EndTable();+ }+ ImGui::TreePop();+ }+ }+ }+ }++ ImGui::Separator();+ auto& memNameMap = m_worker.GetMemNameMap();+ if( memNameMap.size() > 1 )+ {+ ImGui::AlignTextToFramePadding();+ TextDisabledUnformatted( ICON_FA_BOX_ARCHIVE " Memory pool:" );+ ImGui::SameLine();+ if( ImGui::BeginCombo( "##memoryPool", m_zoneInfoMemPool == 0 ? "Default allocator" : m_worker.GetString( m_zoneInfoMemPool ) ) )+ {+ for( auto& v : memNameMap )+ {+ if( ImGui::Selectable( v.first == 0 ? "Default allocator" : m_worker.GetString( v.first ) ) )+ {+ m_zoneInfoMemPool = v.first;+ }+ }+ ImGui::EndCombo();+ }+ }+ auto& mem = m_worker.GetMemoryNamed( m_zoneInfoMemPool );+ if( mem.data.empty() )+ {+ TextDisabledUnformatted( "No memory events." );+ }+ else+ {+ if( !mem.plot )+ {+ ImGui::Text( "Please wait, computing data..." );+ DrawWaitingDots( s_time );+ }+ else+ {+ const auto thread = m_worker.CompressThread( tid );++ auto ait = std::lower_bound( mem.data.begin(), mem.data.end(), ev.Start(), [] ( const auto& l, const auto& r ) { return l.TimeAlloc() < r; } );+ const auto aend = std::upper_bound( ait, mem.data.end(), end, [] ( const auto& l, const auto& r ) { return l < r.TimeAlloc(); } );++ auto fit = std::lower_bound( mem.frees.begin(), mem.frees.end(), ev.Start(), [&mem] ( const auto& l, const auto& r ) { return mem.data[l].TimeFree() < r; } );+ const auto fend = std::upper_bound( fit, mem.frees.end(), end, [&mem] ( const auto& l, const auto& r ) { return l < mem.data[r].TimeFree(); } );++ const auto aDist = std::distance( ait, aend );+ const auto fDist = std::distance( fit, fend );+ if( aDist == 0 && fDist == 0 )+ {+ TextDisabledUnformatted( "No memory events." );+ }+ else+ {+ int64_t cAlloc = 0;+ int64_t cFree = 0;+ int64_t nAlloc = 0;+ int64_t nFree = 0;++ auto ait2 = ait;+ auto fit2 = fit;++ while( ait != aend )+ {+ if( ait->ThreadAlloc() == thread )+ {+ cAlloc += ait->Size();+ nAlloc++;+ }+ ait++;+ }+ while( fit != fend )+ {+ if( mem.data[*fit].ThreadFree() == thread )+ {+ cFree += mem.data[*fit].Size();+ nFree++;+ }+ fit++;+ }++ if( nAlloc == 0 && nFree == 0 )+ {+ TextDisabledUnformatted( "No memory events." );+ }+ else+ {+ ImGui::TextUnformatted( RealToString( nAlloc + nFree ) );+ ImGui::SameLine();+ TextDisabledUnformatted( "memory events." );+ ImGui::TextUnformatted( RealToString( nAlloc ) );+ ImGui::SameLine();+ TextDisabledUnformatted( "allocs," );+ ImGui::SameLine();+ ImGui::TextUnformatted( RealToString( nFree ) );+ ImGui::SameLine();+ TextDisabledUnformatted( "frees." );+ TextFocused( "Memory allocated:", MemSizeToString( cAlloc ) );+ TextFocused( "Memory freed:", MemSizeToString( cFree ) );+ TextFocused( "Overall change:", MemSizeToString( cAlloc - cFree ) );++ if( ImGui::TreeNode( "Allocations list" ) )+ {+ ImGui::SameLine();+ ImGui::Spacing();+ ImGui::SameLine();+ SmallCheckbox( "Time relative to zone start", &m_allocTimeRelativeToZone );++ std::vector<const MemEvent*> v;+ v.reserve( nAlloc + nFree );++ auto it = ait2;+ while( it != aend )+ {+ if( it->ThreadAlloc() == thread )+ {+ v.emplace_back( it );+ }+ it++;+ }+ while( fit2 != fend )+ {+ const auto ptr = &mem.data[*fit2++];+ if( ptr->ThreadFree() == thread )+ {+ if( ptr < ait2 || ptr >= aend )+ {+ v.emplace_back( ptr );+ }+ }+ }+ pdqsort_branchless( v.begin(), v.end(), [] ( const auto& l, const auto& r ) { return l->TimeAlloc() < r->TimeAlloc(); } );++ ListMemData( v, []( auto v ) {+ ImGui::Text( "0x%" PRIx64, v->Ptr() );+ }, m_allocTimeRelativeToZone ? ev.Start() : -1, m_zoneInfoMemPool );+ ImGui::TreePop();+ }+ }+ }+ }+ }++ ImGui::Separator();+ {+ if( threadData->messages.empty() )+ {+ TextDisabledUnformatted( "No messages" );+ }+ else+ {+ auto msgit = std::lower_bound( threadData->messages.begin(), threadData->messages.end(), ev.Start(), [] ( const auto& lhs, const auto& rhs ) { return lhs->time < rhs; } );+ auto msgend = std::lower_bound( msgit, threadData->messages.end(), end+1, [] ( const auto& lhs, const auto& rhs ) { return lhs->time < rhs; } );++ const auto dist = std::distance( msgit, msgend );+ if( dist == 0 )+ {+ TextDisabledUnformatted( "No messages" );+ }+ else+ {+ bool expand = ImGui::TreeNode( "Messages" );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( dist ) );+ if( expand )+ {+ ImGui::SameLine();+ SmallCheckbox( "Time relative to zone start", &m_messageTimeRelativeToZone );+ ImGui::SameLine();+ SmallCheckbox( "Exclude children", &m_messagesExcludeChildren );+ int64_t viewSize;+ if( !m_messagesExcludeChildren )+ {+ viewSize = std::min<int64_t>( msgend - msgit + 1, 15 );+ }+ else+ {+ viewSize = 0;+ for( auto it = msgit; it < msgend; ++it )+ {+ if( !GetZoneChild( ev, (*it)->time ) )+ {+ viewSize++;+ if( viewSize == 15 ) break;+ }+ }+ if( viewSize < 15 ) viewSize++;+ }+ if( ImGui::BeginTable( "##messages", 2, ImGuiTableFlags_ScrollY | ImGuiTableFlags_BordersInnerV, ImVec2( 0, ImGui::GetTextLineHeightWithSpacing() * viewSize ) ) )+ {+ ImGui::TableSetupScrollFreeze( 0, 1 );+ ImGui::TableSetupColumn( "Time", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize );+ ImGui::TableSetupColumn( "Message" );+ ImGui::TableHeadersRow();+ do+ {+ if( m_messagesExcludeChildren && GetZoneChild( ev, (*msgit)->time ) ) continue;+ ImGui::PushID( *msgit );+ ImGui::TableNextRow();+ ImGui::TableNextColumn();+ if( ImGui::Selectable( m_messageTimeRelativeToZone ? TimeToString( (*msgit)->time - ev.Start() ) : TimeToStringExact( (*msgit)->time ), m_msgHighlight == *msgit, ImGuiSelectableFlags_SpanAllColumns ) )+ {+ CenterAtTime( (*msgit)->time );+ }+ if( ImGui::IsItemHovered() )+ {+ m_msgHighlight = *msgit;+ }+ ImGui::PopID();+ ImGui::TableNextColumn();+ ImGui::PushStyleColor( ImGuiCol_Text, (*msgit)->color );+ const auto text = m_worker.GetString( (*msgit)->ref );+ auto tend = text;+ while( *tend != '\0' && *tend != '\n' ) tend++;+ const auto cw = ImGui::GetContentRegionAvail().x;+ const auto tw = ImGui::CalcTextSize( text, tend ).x;+ ImGui::TextUnformatted( text, tend );+ if( tw > cw && ImGui::IsItemHovered() )+ {+ ImGui::SetNextWindowSize( ImVec2( 1000 * GetScale(), 0 ) );+ ImGui::BeginTooltip();+ ImGui::TextWrapped( "%s", text );+ ImGui::EndTooltip();+ }+ ImGui::PopStyleColor();+ }+ while( ++msgit != msgend );+ ImGui::EndTable();+ }+ ImGui::TreePop();+ ImGui::Spacing();+ }+ }+ }+ }++ ImGui::Separator();++ std::vector<const ZoneEvent*> zoneTrace;+ while( parent )+ {+ zoneTrace.emplace_back( parent );+ parent = GetZoneParent( *parent );+ }+ int idx = 0;+ DrawZoneTrace<const ZoneEvent*>( &ev, zoneTrace, m_worker, m_zoneinfoBuzzAnim, *this, m_showUnknownFrames, [&idx, this] ( const ZoneEvent* v, int& fidx ) {+ ImGui::TextDisabled( "%i.", fidx++ );+ ImGui::SameLine();+ const auto& srcloc = m_worker.GetSourceLocation( v->SrcLoc() );+ SmallColorBox( GetSrcLocColor( srcloc, 0 ) );+ ImGui::SameLine();+ const auto txt = m_worker.GetZoneName( *v, srcloc );+ ImGui::PushID( idx++ );+ auto sel = ImGui::Selectable( txt, false );+ auto hover = ImGui::IsItemHovered();+ const auto fileName = m_worker.GetString( srcloc.file );+ if( m_zoneinfoBuzzAnim.Match( v ) )+ {+ const auto time = m_zoneinfoBuzzAnim.Time();+ const auto indentVal = sin( time * 60.f ) * 10.f * time;+ ImGui::SameLine( 0, ImGui::GetStyle().ItemSpacing.x + indentVal );+ }+ else+ {+ ImGui::SameLine();+ }+ ImGui::TextDisabled( "(%s) %s", TimeToString( m_worker.GetZoneEnd( *v ) - v->Start() ), LocationToString( fileName, srcloc.line ) );+ ImGui::PopID();+ if( ImGui::IsItemClicked( 1 ) )+ {+ if( SourceFileValid( fileName, m_worker.GetCaptureTime(), *this, m_worker ) )+ {+ ViewSourceCheckKeyMod( fileName, srcloc.line, m_worker.GetString( srcloc.function ) );+ }+ else+ {+ m_zoneinfoBuzzAnim.Enable( v, 0.5f );+ }+ }+ if( sel )+ {+ ShowZoneInfo( *v );+ }+ if( hover )+ {+ m_zoneHighlight = v;+ if( IsMouseClicked( 2 ) )+ {+ ZoomToZone( *v );+ }+ ZoneTooltip( *v );+ }+ } );++ if( ev.HasChildren() )+ {+ const auto& children = m_worker.GetZoneChildren( ev.Child() );+ bool expand = ImGui::TreeNode( "Child zones" );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( children.size() ) );+ if( expand )+ {+ if( children.is_magic() )+ {+ DrawZoneInfoChildren<VectorAdapterDirect<ZoneEvent>>( *(Vector<ZoneEvent>*)( &children ), ztime );+ }+ else+ {+ DrawZoneInfoChildren<VectorAdapterPointer<ZoneEvent>>( children, ztime );+ }+ ImGui::TreePop();+ }++ expand = ImGui::TreeNode( "Time distribution" );+ if( expand )+ {+ ImGui::SameLine();+ if( SmallCheckbox( "Self time", &m_timeDist.exclusiveTime ) ) m_timeDist.dataValidFor = nullptr;+ if( ctx )+ {+ ImGui::SameLine();+ if( SmallCheckbox( "Running time", &m_timeDist.runningTime ) ) m_timeDist.dataValidFor = nullptr;+ }+ if( m_timeDist.dataValidFor != &ev )+ {+ m_timeDist.data.clear();+ if( ev.IsEndValid() ) m_timeDist.dataValidFor = &ev;++ if( m_timeDist.runningTime )+ {+ assert( ctx );+ int64_t time;+ uint64_t cnt;+ if( !GetZoneRunningTime( ctx, ev, time, cnt ) )+ {+ TextDisabledUnformatted( "Incomplete context switch data." );+ m_timeDist.dataValidFor = nullptr;+ }+ else+ {+ auto it = m_timeDist.data.emplace( ev.SrcLoc(), ZoneTimeData{ time, 1 } ).first;+ CalcZoneTimeData( ctx, m_timeDist.data, it->second.time, ev );+ }+ m_timeDist.fztime = 100.f / time;+ }+ else+ {+ auto it = m_timeDist.data.emplace( ev.SrcLoc(), ZoneTimeData{ ztime, 1 } ).first;+ CalcZoneTimeData( m_timeDist.data, it->second.time, ev );+ m_timeDist.fztime = 100.f / ztime;+ }+ }+ if( !m_timeDist.data.empty() )+ {+ std::vector<unordered_flat_map<int16_t, ZoneTimeData>::const_iterator> vec;+ vec.reserve( m_timeDist.data.size() );+ for( auto it = m_timeDist.data.cbegin(); it != m_timeDist.data.cend(); ++it ) vec.emplace_back( it );+ if( ImGui::BeginTable( "##timedist", 3, ImGuiTableFlags_Sortable | ImGuiTableFlags_BordersInnerV ) )+ {+ ImGui::TableSetupColumn( "Zone", ImGuiTableColumnFlags_PreferSortDescending );+ ImGui::TableSetupColumn( "Time", ImGuiTableColumnFlags_PreferSortDescending | ImGuiTableColumnFlags_DefaultSort | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize );+ ImGui::TableSetupColumn( "MTPC", ImGuiTableColumnFlags_PreferSortDescending | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize );+ ImGui::TableHeadersRow();+ const auto& sortspec = *ImGui::TableGetSortSpecs()->Specs;+ switch( sortspec.ColumnIndex )+ {+ case 0:+ if( sortspec.SortDirection == ImGuiSortDirection_Ascending )+ {+ pdqsort_branchless( vec.begin(), vec.end(), []( const auto& lhs, const auto& rhs ) { return lhs->second.count < rhs->second.count; } );+ }+ else+ {+ pdqsort_branchless( vec.begin(), vec.end(), []( const auto& lhs, const auto& rhs ) { return lhs->second.count > rhs->second.count; } );+ }+ break;+ case 1:+ if( sortspec.SortDirection == ImGuiSortDirection_Ascending )+ {+ pdqsort_branchless( vec.begin(), vec.end(), []( const auto& lhs, const auto& rhs ) { return lhs->second.time < rhs->second.time; } );+ }+ else+ {+ pdqsort_branchless( vec.begin(), vec.end(), []( const auto& lhs, const auto& rhs ) { return lhs->second.time > rhs->second.time; } );+ }+ break;+ case 2:+ if( sortspec.SortDirection == ImGuiSortDirection_Ascending )+ {+ pdqsort_branchless( vec.begin(), vec.end(), []( const auto& lhs, const auto& rhs ) { return float( lhs->second.time ) / lhs->second.count < float( rhs->second.time ) / rhs->second.count; } );+ }+ else+ {+ pdqsort_branchless( vec.begin(), vec.end(), []( const auto& lhs, const auto& rhs ) { return float( lhs->second.time ) / lhs->second.count > float( rhs->second.time ) / rhs->second.count; } );+ }+ break;+ default:+ assert( false );+ break;+ }+ for( auto& v : vec )+ {+ ImGui::TableNextRow();+ ImGui::TableNextColumn();+ const auto& sl = m_worker.GetSourceLocation( v->first );+ SmallColorBox( GetSrcLocColor( sl, 0 ) );+ ImGui::SameLine();+ const auto name = m_worker.GetZoneName( sl );+ if( ImGui::Selectable( name, false, ImGuiSelectableFlags_SpanAllColumns ) )+ {+ m_findZone.ShowZone( v->first, name, ev.Start(), m_worker.GetZoneEnd( ev ) );+ }+ ImGui::SameLine();+ ImGui::TextDisabled( "(\xc3\x97%s)", RealToString( v->second.count ) );+ ImGui::TableNextColumn();+ ImGui::TextUnformatted( TimeToString( v->second.time ) );+ ImGui::SameLine();+ char buf[64];+ PrintStringPercent( buf, v->second.time * m_timeDist.fztime );+ TextDisabledUnformatted( buf );+ ImGui::TableNextColumn();+ ImGui::TextUnformatted( TimeToString( v->second.time / v->second.count ) );+ }+ ImGui::EndTable();+ }+ }+ ImGui::TreePop();+ }+ }++ ImGui::EndChild();+ }+ ImGui::End();++ if( !show )+ {+ m_zoneInfoWindow = nullptr;+ m_zoneInfoStack.clear();+ }+}++template<typename Adapter, typename V>+void View::DrawZoneInfoChildren( const V& children, int64_t ztime )+{+ Adapter a;+ const auto rztime = 1.0 / ztime;+ const auto ty = ImGui::GetTextLineHeight();++ ImGui::SameLine();+ SmallCheckbox( ICON_FA_LAYER_GROUP " Group children locations", &m_groupChildrenLocations );++ if( m_groupChildrenLocations )+ {+ struct ChildGroup+ {+ int16_t srcloc;+ uint64_t t;+ Vector<uint32_t> v;+ };+ uint64_t ctime = 0;+ unordered_flat_map<int16_t, ChildGroup> cmap;+ cmap.reserve( 128 );+ for( size_t i=0; i<children.size(); i++ )+ {+ const auto& child = a(children[i]);+ const auto cend = m_worker.GetZoneEnd( child );+ const auto ct = cend - child.Start();+ const auto srcloc = child.SrcLoc();+ ctime += ct;++ auto it = cmap.find( srcloc );+ if( it == cmap.end() ) it = cmap.emplace( srcloc, ChildGroup { srcloc } ).first;++ it->second.t += ct;+ it->second.v.push_back( i );+ }++ auto msz = cmap.size();+ Vector<ChildGroup*> cgvec;+ cgvec.reserve_and_use( msz );+ size_t idx = 0;+ for( auto& it : cmap )+ {+ cgvec[idx++] = &it.second;+ }++ pdqsort_branchless( cgvec.begin(), cgvec.end(), []( const auto& lhs, const auto& rhs ) { return lhs->t > rhs->t; } );++ ImGui::Columns( 2 );+ ImGui::Indent( ImGui::GetTreeNodeToLabelSpacing() * 2 );+ TextColoredUnformatted( ImVec4( 1.0f, 1.0f, 0.4f, 1.0f ), "Self time" );+ ImGui::Unindent( ImGui::GetTreeNodeToLabelSpacing() * 2 );+ ImGui::NextColumn();+ char buf[128];+ PrintStringPercent( buf, TimeToString( ztime - ctime ), double( ztime - ctime ) / ztime * 100 );+ ImGui::ProgressBar( double( ztime - ctime ) * rztime, ImVec2( -1, ty ), buf );+ ImGui::NextColumn();+ for( size_t i=0; i<msz; i++ )+ {+ bool expandGroup = false;+ const auto& cgr = *cgvec[i];+ const auto& srcloc = m_worker.GetSourceLocation( cgr.srcloc );+ const auto txt = m_worker.GetZoneName( srcloc );+ if( cgr.v.size() == 1 )+ {+ auto& cev = a(children[cgr.v.front()]);+ const auto txt = m_worker.GetZoneName( cev );+ SmallColorBox( GetSrcLocColor( srcloc, 0 ) );+ ImGui::SameLine();+ ImGui::PushID( (int)cgr.v.front() );+ ImGui::TreeNodeEx( txt, ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen );+ if( ImGui::IsItemClicked() )+ {+ ShowZoneInfo( cev );+ }+ if( ImGui::IsItemHovered() )+ {+ m_zoneHighlight = &cev;+ if( IsMouseClicked( 2 ) )+ {+ ZoomToZone( cev );+ }+ ZoneTooltip( cev );+ }+ ImGui::PopID();+ }+ else+ {+ SmallColorBox( GetSrcLocColor( srcloc, 0 ) );+ ImGui::SameLine();+ ImGui::PushID( cgr.srcloc );+ expandGroup = ImGui::TreeNode( txt );+ ImGui::PopID();+ if( ImGui::IsItemHovered() )+ {+ ImGui::BeginTooltip();+ if( srcloc.name.active )+ {+ ImGui::TextUnformatted( m_worker.GetString( srcloc.name ) );+ }+ ImGui::TextUnformatted( m_worker.GetString( srcloc.function ) );+ ImGui::Separator();+ ImGui::TextUnformatted( LocationToString( m_worker.GetString( srcloc.file ), srcloc.line ) );+ ImGui::EndTooltip();+ }+ ImGui::SameLine();+ ImGui::TextDisabled( "(\xc3\x97%s)", RealToString( cgr.v.size() ) );+ }+ ImGui::NextColumn();+ const auto part = double( cgr.t ) * rztime;+ char buf[128];+ PrintStringPercent( buf, TimeToString( cgr.t ), part * 100 );+ ImGui::ProgressBar( part, ImVec2( -1, ty ), buf );+ ImGui::NextColumn();+ if( expandGroup )+ {+ auto ctt = std::unique_ptr<uint64_t[]>( new uint64_t[cgr.v.size()] );+ auto cti = std::unique_ptr<uint32_t[]>( new uint32_t[cgr.v.size()] );+ for( size_t i=0; i<cgr.v.size(); i++ )+ {+ const auto& child = a(children[cgr.v[i]]);+ const auto cend = m_worker.GetZoneEnd( child );+ const auto ct = cend - child.Start();+ ctt[i] = ct;+ cti[i] = uint32_t( i );+ }++ pdqsort_branchless( cti.get(), cti.get() + cgr.v.size(), [&ctt] ( const auto& lhs, const auto& rhs ) { return ctt[lhs] > ctt[rhs]; } );++ ImGuiListClipper clipper;+ clipper.Begin( cgr.v.size() );+ while( clipper.Step() )+ {+ for( auto i=clipper.DisplayStart; i<clipper.DisplayEnd; i++ )+ {+ auto& cev = a(children[cgr.v[cti[i]]]);+ const auto txt = m_worker.GetZoneName( cev );+ bool b = false;+ ImGui::Indent();+ ImGui::PushID( (int)cgr.v[cti[i]] );+ if( ImGui::Selectable( txt, &b, ImGuiSelectableFlags_SpanAllColumns ) )+ {+ ShowZoneInfo( cev );+ }+ if( ImGui::IsItemHovered() )+ {+ m_zoneHighlight = &cev;+ if( IsMouseClicked( 2 ) )+ {+ ZoomToZone( cev );+ }+ ZoneTooltip( cev );+ }+ ImGui::PopID();+ ImGui::Unindent();+ ImGui::NextColumn();+ const auto part = double( ctt[cti[i]] ) * rztime;+ char buf[128];+ PrintStringPercent( buf, TimeToString( ctt[cti[i]] ), part * 100 );+ ImGui::ProgressBar( part, ImVec2( -1, ty ), buf );+ ImGui::NextColumn();+ }+ }+ ImGui::TreePop();+ }+ }+ ImGui::EndColumns();+ }+ else+ {+ auto ctt = std::unique_ptr<uint64_t[]>( new uint64_t[children.size()] );+ auto cti = std::unique_ptr<uint32_t[]>( new uint32_t[children.size()] );+ uint64_t ctime = 0;+ for( size_t i=0; i<children.size(); i++ )+ {+ const auto& child = a(children[i]);+ const auto cend = m_worker.GetZoneEnd( child );+ const auto ct = cend - child.Start();+ ctime += ct;+ ctt[i] = ct;+ cti[i] = uint32_t( i );+ }++ pdqsort_branchless( cti.get(), cti.get() + children.size(), [&ctt] ( const auto& lhs, const auto& rhs ) { return ctt[lhs] > ctt[rhs]; } );++ ImGui::Columns( 2 );+ ImGui::Indent( ImGui::GetTreeNodeToLabelSpacing() );+ TextColoredUnformatted( ImVec4( 1.0f, 1.0f, 0.4f, 1.0f ), "Self time" );+ ImGui::Unindent( ImGui::GetTreeNodeToLabelSpacing() );+ ImGui::NextColumn();+ char buf[128];+ PrintStringPercent( buf, TimeToString( ztime - ctime ), double( ztime - ctime ) / ztime * 100 );+ ImGui::ProgressBar( double( ztime - ctime ) * rztime, ImVec2( -1, ty ), buf );+ ImGui::NextColumn();+ ImGuiListClipper clipper;+ clipper.Begin( children.size() );+ while( clipper.Step() )+ {+ for( auto i=clipper.DisplayStart; i<clipper.DisplayEnd; i++ )+ {+ auto& cev = a(children[cti[i]]);+ const auto txt = m_worker.GetZoneName( cev );+ bool b = false;+ SmallColorBox( GetSrcLocColor( m_worker.GetSourceLocation( cev.SrcLoc() ), 0 ) );+ ImGui::SameLine();+ ImGui::PushID( (int)i );+ if( ImGui::Selectable( txt, &b, ImGuiSelectableFlags_SpanAllColumns ) )+ {+ ShowZoneInfo( cev );+ }+ if( ImGui::IsItemHovered() )+ {+ m_zoneHighlight = &cev;+ if( IsMouseClicked( 2 ) )+ {+ ZoomToZone( cev );+ }+ ZoneTooltip( cev );+ }+ ImGui::PopID();+ ImGui::NextColumn();+ const auto part = double( ctt[cti[i]] ) * rztime;+ char buf[128];+ PrintStringPercent( buf, TimeToString( ctt[cti[i]] ), part * 100 );+ ImGui::ProgressBar( part, ImVec2( -1, ty ), buf );+ ImGui::NextColumn();+ }+ }+ ImGui::EndColumns();+ }+}++void View::DrawGpuInfoWindow()+{+ auto& ev = *m_gpuInfoWindow;+ const auto& srcloc = m_worker.GetSourceLocation( ev.SrcLoc() );++ const auto scale = GetScale();+ ImGui::SetNextWindowSize( ImVec2( 500 * scale, 600 * scale), ImGuiCond_FirstUseEver );+ bool show = true;+ ImGui::Begin( "Zone info", &show, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse );+ if( !ImGui::GetCurrentWindowRead()->SkipItems )+ {+ if( ImGui::Button( ICON_FA_MICROSCOPE " Zoom to zone" ) )+ {+ ZoomToZone( ev );+ }+ auto parent = GetZoneParent( ev );+ if( parent )+ {+ ImGui::SameLine();+ if( ImGui::Button( ICON_FA_ARROW_UP " Go to parent" ) )+ {+ ShowZoneInfo( *parent, m_gpuInfoWindowThread );+ }+ }+ if( ev.callstack.Val() != 0 )+ {+ ImGui::SameLine();+ bool hilite = m_callstackInfoWindow == ev.callstack.Val();+ if( hilite )+ {+ SetButtonHighlightColor();+ }+ if( ImGui::Button( ICON_FA_ALIGN_JUSTIFY " Call stack" ) )+ {+ m_callstackInfoWindow = ev.callstack.Val();+ }+ if( hilite )+ {+ ImGui::PopStyleColor( 3 );+ }+ }+ const auto fileName = m_worker.GetString( srcloc.file );+ if( SourceFileValid( fileName, m_worker.GetCaptureTime(), *this, m_worker ) )+ {+ ImGui::SameLine();+ bool hilite = m_sourceViewFile == fileName;+ if( hilite )+ {+ SetButtonHighlightColor();+ }+ if( ImGui::Button( ICON_FA_FILE_LINES " Source" ) )+ {+ ViewSourceCheckKeyMod( fileName, srcloc.line, m_worker.GetString( srcloc.function ) );+ }+ if( hilite )+ {+ ImGui::PopStyleColor( 3 );+ }+ }+ if( !m_gpuInfoStack.empty() )+ {+ ImGui::SameLine();+ if( ImGui::Button( ICON_FA_ARROW_LEFT " Go back" ) )+ {+ m_gpuInfoWindow = m_gpuInfoStack.back_and_pop();+ }+ }++ ImGui::Separator();++ const auto tid = GetZoneThread( ev );+ ImGui::PushFont( m_bigFont );+ TextFocused( "Zone name:", m_worker.GetString( srcloc.name ) );+ ImGui::PopFont();+ ImGui::SameLine();+ if( ClipboardButton( 1 ) ) ImGui::SetClipboardText( m_worker.GetString( srcloc.name ) );+ TextFocused( "Function:", m_worker.GetString( srcloc.function ) );+ ImGui::SameLine();+ if( ClipboardButton( 2 ) ) ImGui::SetClipboardText( m_worker.GetString( srcloc.function ) );+ SmallColorBox( GetZoneColor( ev ) );+ ImGui::SameLine();+ TextDisabledUnformatted( "Location:" );+ ImGui::SameLine();+ ImGui::TextUnformatted( LocationToString( m_worker.GetString( srcloc.file ), srcloc.line ) );+ ImGui::SameLine();+ if( ClipboardButton( 3 ) )+ {+ ImGui::SetClipboardText( LocationToString( m_worker.GetString( srcloc.file ), srcloc.line ) );+ }+ SmallColorBox( GetThreadColor( tid, 0 ) );+ ImGui::SameLine();+ TextFocused( "Thread:", m_worker.GetThreadName( tid ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( tid ) );+ if( m_worker.IsThreadFiber( tid ) )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 0.2f, 0.6f, 0.2f, 1.f ), "Fiber" );+ }+ ImGui::Separator();+ ImGui::BeginChild( "##gpuinfo" );++ const auto end = m_worker.GetZoneEnd( ev );+ const auto ztime = end - ev.GpuStart();+ const auto selftime = GetZoneSelfTime( ev );+ TextFocused( "Time from start of program:", TimeToStringExact( ev.GpuStart() ) );+ TextFocused( "GPU execution time:", TimeToString( ztime ) );+ TextFocused( "GPU self time:", TimeToString( selftime ) );+ if( ztime != 0 )+ {+ char buf[64];+ PrintStringPercent( buf, 100.f * selftime / ztime );+ ImGui::SameLine();+ TextDisabledUnformatted( buf );+ }+ TextFocused( "CPU command setup time:", TimeToString( ev.CpuEnd() - ev.CpuStart() ) );+ auto ctx = GetZoneCtx( ev );+ if( !ctx )+ {+ TextFocused( "Delay to execution:", TimeToString( ev.GpuStart() - ev.CpuStart() ) );+ }+ else+ {+ const auto td = ctx->threadData.size() == 1 ? ctx->threadData.begin() : ctx->threadData.find( m_worker.DecompressThread( ev.Thread() ) );+ assert( td != ctx->threadData.end() );+ int64_t begin;+ if( td->second.timeline.is_magic() )+ {+ begin = ((Vector<GpuEvent>*)&td->second.timeline)->front().GpuStart();+ }+ else+ {+ begin = td->second.timeline.front()->GpuStart();+ }+ const auto drift = GpuDrift( ctx );+ TextFocused( "Delay to execution:", TimeToString( AdjustGpuTime( ev.GpuStart(), begin, drift ) - ev.CpuStart() ) );+ }++ ImGui::Separator();++ std::vector<const GpuEvent*> zoneTrace;+ while( parent )+ {+ zoneTrace.emplace_back( parent );+ parent = GetZoneParent( *parent );+ }+ int idx = 0;+ DrawZoneTrace<const GpuEvent*>( &ev, zoneTrace, m_worker, m_zoneinfoBuzzAnim, *this, m_showUnknownFrames, [&idx, this] ( const GpuEvent* v, int& fidx ) {+ ImGui::TextDisabled( "%i.", fidx++ );+ ImGui::SameLine();+ const auto& srcloc = m_worker.GetSourceLocation( v->SrcLoc() );+ const auto txt = m_worker.GetZoneName( srcloc );+ ImGui::PushID( idx++ );+ auto sel = ImGui::Selectable( txt, false );+ auto hover = ImGui::IsItemHovered();+ const auto fileName = m_worker.GetString( srcloc.file );+ if( m_zoneinfoBuzzAnim.Match( v ) )+ {+ const auto time = m_zoneinfoBuzzAnim.Time();+ const auto indentVal = sin( time * 60.f ) * 10.f * time;+ ImGui::SameLine( 0, ImGui::GetStyle().ItemSpacing.x + indentVal );+ }+ else+ {+ ImGui::SameLine();+ }+ ImGui::TextDisabled( "(%s) %s", TimeToString( m_worker.GetZoneEnd( *v ) - v->GpuStart() ), LocationToString( fileName, srcloc.line ) );+ ImGui::PopID();+ if( ImGui::IsItemClicked( 1 ) )+ {+ if( SourceFileValid( fileName, m_worker.GetCaptureTime(), *this, m_worker ) )+ {+ ViewSourceCheckKeyMod( fileName, srcloc.line, m_worker.GetString( srcloc.function ) );+ }+ else+ {+ m_zoneinfoBuzzAnim.Enable( v, 0.5f );+ }+ }+ if( sel )+ {+ ShowZoneInfo( *v, m_gpuInfoWindowThread );+ }+ if( hover )+ {+ m_gpuHighlight = v;+ if( IsMouseClicked( 2 ) )+ {+ ZoomToZone( *v );+ }+ ZoneTooltip( *v );+ }+ } );++ if( ev.Child() >= 0 )+ {+ const auto& children = m_worker.GetGpuChildren( ev.Child() );+ bool expand = ImGui::TreeNode( "Child zones" );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( children.size() ) );+ if( expand )+ {+ if( children.is_magic() )+ {+ DrawGpuInfoChildren<VectorAdapterDirect<GpuEvent>>( *(Vector<GpuEvent>*)( &children ), ztime );+ }+ else+ {+ DrawGpuInfoChildren<VectorAdapterPointer<GpuEvent>>( children, ztime );+ }+ ImGui::TreePop();+ }+ }++ ImGui::EndChild();+ }+ ImGui::End();++ if( !show )+ {+ m_gpuInfoWindow = nullptr;+ m_gpuInfoStack.clear();+ }+}++template<typename Adapter, typename V>+void View::DrawGpuInfoChildren( const V& children, int64_t ztime )+{+ Adapter a;+ const auto rztime = 1.0 / ztime;+ const auto ty = ImGui::GetTextLineHeight();++ ImGui::SameLine();+ SmallCheckbox( ICON_FA_LAYER_GROUP " Group children locations", &m_groupChildrenLocations );++ if( m_groupChildrenLocations )+ {+ struct ChildGroup+ {+ int16_t srcloc;+ uint64_t t;+ Vector<uint32_t> v;+ };+ uint64_t ctime = 0;+ unordered_flat_map<int16_t, ChildGroup> cmap;+ cmap.reserve( 128 );+ for( size_t i=0; i<children.size(); i++ )+ {+ const auto& child = a(children[i]);+ const auto cend = m_worker.GetZoneEnd( child );+ const auto ct = cend - child.GpuStart();+ const auto srcloc = child.SrcLoc();+ ctime += ct;++ auto it = cmap.find( srcloc );+ if( it == cmap.end() ) it = cmap.emplace( srcloc, ChildGroup { srcloc } ).first;++ it->second.t += ct;+ it->second.v.push_back( i );+ }++ auto msz = cmap.size();+ Vector<ChildGroup*> cgvec;+ cgvec.reserve_and_use( msz );+ size_t idx = 0;+ for( auto& it : cmap )+ {+ cgvec[idx++] = &it.second;+ }++ pdqsort_branchless( cgvec.begin(), cgvec.end(), []( const auto& lhs, const auto& rhs ) { return lhs->t > rhs->t; } );++ ImGui::Columns( 2 );+ ImGui::Indent( ImGui::GetTreeNodeToLabelSpacing() );+ TextColoredUnformatted( ImVec4( 1.0f, 1.0f, 0.4f, 1.0f ), "Self time" );+ ImGui::Unindent( ImGui::GetTreeNodeToLabelSpacing() );+ ImGui::NextColumn();+ char buf[128];+ PrintStringPercent( buf, TimeToString( ztime - ctime ), double( ztime - ctime ) / ztime * 100 );+ ImGui::ProgressBar( double( ztime - ctime ) * rztime, ImVec2( -1, ty ), buf );+ ImGui::NextColumn();+ for( size_t i=0; i<msz; i++ )+ {+ bool expandGroup = false;+ const auto& cgr = *cgvec[i];+ const auto& srcloc = m_worker.GetSourceLocation( cgr.srcloc );+ const auto txt = m_worker.GetZoneName( srcloc );+ if( cgr.v.size() == 1 )+ {+ auto& cev = a(children[cgr.v.front()]);+ const auto txt = m_worker.GetZoneName( cev );+ ImGui::PushID( (int)cgr.v.front() );+ ImGui::TreeNodeEx( txt, ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen );+ if( ImGui::IsItemClicked() )+ {+ ShowZoneInfo( cev, m_gpuInfoWindowThread );+ }+ if( ImGui::IsItemHovered() )+ {+ m_gpuHighlight = &cev;+ if( IsMouseClicked( 2 ) )+ {+ ZoomToZone( cev );+ }+ ZoneTooltip( cev );+ }+ ImGui::PopID();+ }+ else+ {+ ImGui::PushID( cgr.srcloc );+ expandGroup = ImGui::TreeNode( txt );+ ImGui::PopID();+ if( ImGui::IsItemHovered() )+ {+ ImGui::BeginTooltip();+ if( srcloc.name.active )+ {+ ImGui::TextUnformatted( m_worker.GetString( srcloc.name ) );+ }+ ImGui::TextUnformatted( m_worker.GetString( srcloc.function ) );+ ImGui::Separator();+ ImGui::TextUnformatted( LocationToString( m_worker.GetString( srcloc.file ), srcloc.line ) );+ ImGui::EndTooltip();+ }+ ImGui::SameLine();+ ImGui::TextDisabled( "(\xc3\x97%s)", RealToString( cgr.v.size() ) );+ }+ ImGui::NextColumn();+ const auto part = double( cgr.t ) * rztime;+ char buf[128];+ PrintStringPercent( buf, TimeToString( cgr.t ), part * 100 );+ ImGui::ProgressBar( part, ImVec2( -1, ty ), buf );+ ImGui::NextColumn();+ if( expandGroup )+ {+ auto ctt = std::unique_ptr<uint64_t[]>( new uint64_t[cgr.v.size()] );+ auto cti = std::unique_ptr<uint32_t[]>( new uint32_t[cgr.v.size()] );+ for( size_t i=0; i<cgr.v.size(); i++ )+ {+ const auto& child = a(children[cgr.v[i]]);+ const auto cend = m_worker.GetZoneEnd( child );+ const auto ct = cend - child.GpuStart();+ ctt[i] = ct;+ cti[i] = uint32_t( i );+ }++ pdqsort_branchless( cti.get(), cti.get() + cgr.v.size(), [&ctt] ( const auto& lhs, const auto& rhs ) { return ctt[lhs] > ctt[rhs]; } );++ for( size_t i=0; i<cgr.v.size(); i++ )+ {+ auto& cev = a(children[cgr.v[cti[i]]]);+ const auto txt = m_worker.GetZoneName( cev );+ bool b = false;+ ImGui::Indent();+ ImGui::PushID( (int)cgr.v[cti[i]] );+ if( ImGui::Selectable( txt, &b, ImGuiSelectableFlags_SpanAllColumns ) )+ {+ ShowZoneInfo( cev, m_gpuInfoWindowThread );+ }+ if( ImGui::IsItemHovered() )+ {+ m_gpuHighlight = &cev;+ if( IsMouseClicked( 2 ) )+ {+ ZoomToZone( cev );+ }+ ZoneTooltip( cev );+ }+ ImGui::PopID();+ ImGui::Unindent();+ ImGui::NextColumn();+ const auto part = double( ctt[cti[i]] ) * rztime;+ char buf[128];+ PrintStringPercent( buf, TimeToString( ctt[cti[i]] ), part * 100 );+ ImGui::ProgressBar( part, ImVec2( -1, ty ), buf );+ ImGui::NextColumn();+ }+ ImGui::TreePop();+ }+ }+ ImGui::EndColumns();+ }+ else+ {+ auto ctt = std::unique_ptr<uint64_t[]>( new uint64_t[children.size()] );+ auto cti = std::unique_ptr<uint32_t[]>( new uint32_t[children.size()] );+ uint64_t ctime = 0;+ for( size_t i=0; i<children.size(); i++ )+ {+ const auto& child = a(children[i]);+ const auto cend = m_worker.GetZoneEnd( child );+ const auto ct = cend - child.GpuStart();+ ctime += ct;+ ctt[i] = ct;+ cti[i] = uint32_t( i );+ }++ pdqsort_branchless( cti.get(), cti.get() + children.size(), [&ctt] ( const auto& lhs, const auto& rhs ) { return ctt[lhs] > ctt[rhs]; } );++ ImGui::Columns( 2 );+ TextColoredUnformatted( ImVec4( 1.0f, 1.0f, 0.4f, 1.0f ), "Self time" );+ ImGui::NextColumn();+ char buf[128];+ PrintStringPercent( buf, TimeToString( ztime - ctime ), double( ztime - ctime ) / ztime * 100 );+ ImGui::ProgressBar( double( ztime - ctime ) / ztime, ImVec2( -1, ty ), buf );+ ImGui::NextColumn();+ for( size_t i=0; i<children.size(); i++ )+ {+ auto& cev = a(children[cti[i]]);+ bool b = false;+ ImGui::PushID( (int)i );+ if( ImGui::Selectable( m_worker.GetZoneName( cev ), &b, ImGuiSelectableFlags_SpanAllColumns ) )+ {+ ShowZoneInfo( cev, m_gpuInfoWindowThread );+ }+ if( ImGui::IsItemHovered() )+ {+ m_gpuHighlight = &cev;+ if( IsMouseClicked( 2 ) )+ {+ ZoomToZone( cev );+ }+ ZoneTooltip( cev );+ }+ ImGui::PopID();+ ImGui::NextColumn();+ const auto part = double( ctt[cti[i]] ) / ztime;+ char buf[128];+ PrintStringPercent( buf, TimeToString( ctt[cti[i]] ), part * 100 );+ ImGui::ProgressBar( part, ImVec2( -1, ty ), buf );+ ImGui::NextColumn();+ }+ ImGui::EndColumns();+ }+}++void View::ShowZoneInfo( const ZoneEvent& ev )+{+ if( m_zoneInfoWindow && m_zoneInfoWindow != &ev )+ {+ m_zoneInfoStack.push_back( m_zoneInfoWindow );+ }+ m_zoneInfoWindow = &ev;++ if( m_gpuInfoWindow )+ {+ m_gpuInfoWindow = nullptr;+ m_gpuInfoStack.clear();+ }+}++void View::ShowZoneInfo( const GpuEvent& ev, uint64_t thread )+{+ if( m_gpuInfoWindow && m_gpuInfoWindow != &ev )+ {+ m_gpuInfoStack.push_back( m_gpuInfoWindow );+ }+ m_gpuInfoWindow = &ev;+ m_gpuInfoWindowThread = thread;++ if( m_zoneInfoWindow )+ {+ m_zoneInfoWindow = nullptr;+ m_zoneInfoStack.clear();+ }+}++void View::ZoneTooltip( const ZoneEvent& ev )+{+ const auto tid = GetZoneThread( ev );+ auto& srcloc = m_worker.GetSourceLocation( ev.SrcLoc() );+ const auto end = m_worker.GetZoneEnd( ev );+ const auto ztime = end - ev.Start();+ const auto selftime = GetZoneSelfTime( ev );++ ImGui::BeginTooltip();+ if( m_worker.HasZoneExtra( ev ) && m_worker.GetZoneExtra( ev ).name.Active() )+ {+ ImGui::TextUnformatted( m_worker.GetString( m_worker.GetZoneExtra( ev ).name ) );+ }+ if( srcloc.name.active )+ {+ ImGui::TextUnformatted( m_worker.GetString( srcloc.name ) );+ }+ ImGui::TextUnformatted( m_worker.GetString( srcloc.function ) );+ ImGui::Separator();+ SmallColorBox( GetSrcLocColor( srcloc, 0 ) );+ ImGui::SameLine();+ ImGui::TextUnformatted( LocationToString( m_worker.GetString( srcloc.file ), srcloc.line ) );+ SmallColorBox( GetThreadColor( tid, 0 ) );+ ImGui::SameLine();+ TextFocused( "Thread:", m_worker.GetThreadName( tid ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( tid ) );+ if( m_worker.IsThreadFiber( tid ) )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 0.2f, 0.6f, 0.2f, 1.f ), "Fiber" );+ }+ ImGui::Separator();+ TextFocused( "Execution time:", TimeToString( ztime ) );+#ifndef TRACY_NO_STATISTICS+ if( m_worker.AreSourceLocationZonesReady() )+ {+ auto& zoneData = m_worker.GetZonesForSourceLocation( ev.SrcLoc() );+ if( zoneData.total > 0 )+ {+ ImGui::SameLine();+ ImGui::TextDisabled( "(%.2f%% of mean time)", float( ztime ) / zoneData.total * zoneData.zones.size() * 100 );+ }+ }+#endif+ TextFocused( "Self time:", TimeToString( selftime ) );+ if( ztime != 0 )+ {+ char buf[64];+ PrintStringPercent( buf, 100.f * selftime / ztime );+ ImGui::SameLine();+ TextDisabledUnformatted( buf );+ }+ const auto ctx = m_worker.GetContextSwitchData( tid );+ if( ctx )+ {+ int64_t time;+ uint64_t cnt;+ if( GetZoneRunningTime( ctx, ev, time, cnt ) )+ {+ TextFocused( "Running state time:", TimeToString( time ) );+ if( ztime != 0 )+ {+ char buf[64];+ PrintStringPercent( buf, 100.f * time / ztime );+ ImGui::SameLine();+ TextDisabledUnformatted( buf );+ }+ TextFocused( "Running state regions:", RealToString( cnt ) );+ }+ }+ if( m_worker.HasZoneExtra( ev ) && m_worker.GetZoneExtra( ev ).text.Active() )+ {+ ImGui::NewLine();+ TextColoredUnformatted( ImVec4( 0xCC / 255.f, 0xCC / 255.f, 0x22 / 255.f, 1.f ), m_worker.GetString( m_worker.GetZoneExtra( ev ).text ) );+ }+ ImGui::EndTooltip();+}++void View::ZoneTooltip( const GpuEvent& ev )+{+ const auto tid = GetZoneThread( ev );+ const auto& srcloc = m_worker.GetSourceLocation( ev.SrcLoc() );+ const auto end = m_worker.GetZoneEnd( ev );+ const auto ztime = end - ev.GpuStart();+ const auto selftime = GetZoneSelfTime( ev );++ ImGui::BeginTooltip();+ ImGui::TextUnformatted( m_worker.GetString( srcloc.name ) );+ ImGui::TextUnformatted( m_worker.GetString( srcloc.function ) );+ ImGui::Separator();+ SmallColorBox( GetSrcLocColor( srcloc, 0 ) );+ ImGui::SameLine();+ ImGui::TextUnformatted( LocationToString( m_worker.GetString( srcloc.file ), srcloc.line ) );+ SmallColorBox( GetThreadColor( tid, 0 ) );+ ImGui::SameLine();+ TextFocused( "Thread:", m_worker.GetThreadName( tid ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( tid ) );+ if( m_worker.IsThreadFiber( tid ) )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 0.2f, 0.6f, 0.2f, 1.f ), "Fiber" );+ }+ ImGui::Separator();+ TextFocused( "GPU execution time:", TimeToString( ztime ) );+ TextFocused( "GPU self time:", TimeToString( selftime ) );+ if( ztime != 0 )+ {+ char buf[64];+ PrintStringPercent( buf, 100.f * selftime / ztime );+ ImGui::SameLine();+ TextDisabledUnformatted( buf );+ }+ TextFocused( "CPU command setup time:", TimeToString( ev.CpuEnd() - ev.CpuStart() ) );+ auto ctx = GetZoneCtx( ev );+ if( !ctx )+ {+ TextFocused( "Delay to execution:", TimeToString( ev.GpuStart() - ev.CpuStart() ) );+ }+ else+ {+ const auto td = ctx->threadData.size() == 1 ? ctx->threadData.begin() : ctx->threadData.find( m_worker.DecompressThread( ev.Thread() ) );+ assert( td != ctx->threadData.end() );+ int64_t begin;+ if( td->second.timeline.is_magic() )+ {+ begin = ((Vector<GpuEvent>*)&td->second.timeline)->front().GpuStart();+ }+ else+ {+ begin = td->second.timeline.front()->GpuStart();+ }+ const auto drift = GpuDrift( ctx );+ TextFocused( "Delay to execution:", TimeToString( AdjustGpuTime( ev.GpuStart(), begin, drift ) - ev.CpuStart() ) );+ }++ ImGui::EndTooltip();+}++}
+ cbits/tracy/profiler/src/profiler/TracyView_ZoneTimeline.cpp view
@@ -0,0 +1,617 @@+#include <inttypes.h>++#include "TracyColor.hpp"+#include "TracyImGui.hpp"+#include "TracyMouse.hpp"+#include "TracyPrint.hpp"+#include "TracyTimelineContext.hpp"+#include "TracyTimelineDraw.hpp"+#include "TracyView.hpp"++namespace tracy+{++extern double s_time;++constexpr float MinVisSize = 3;++static tracy_force_inline uint32_t MixGhostColor( uint32_t c0, uint32_t c1 )+{+ return 0xFF000000 |+ ( ( ( ( ( c0 & 0x00FF0000 ) >> 16 ) + 3 * ( ( c1 & 0x00FF0000 ) >> 16 ) ) >> 2 ) << 16 ) |+ ( ( ( ( ( c0 & 0x0000FF00 ) >> 8 ) + 3 * ( ( c1 & 0x0000FF00 ) >> 8 ) ) >> 2 ) << 8 ) |+ ( ( ( ( ( c0 & 0x000000FF ) ) + 3 * ( ( c1 & 0x000000FF ) ) ) >> 2 ) );+}++void View::DrawThread( const TimelineContext& ctx, const ThreadData& thread, const std::vector<TimelineDraw>& draw, const std::vector<ContextSwitchDraw>& ctxDraw, const std::vector<SamplesDraw>& samplesDraw, const std::vector<std::unique_ptr<LockDraw>>& lockDraw, int& offset, int depth, bool _hasCtxSwitches, bool _hasSamples )+{+ const auto& wpos = ctx.wpos;+ const auto ty = ctx.ty;+ const auto ostep = ty + 1;+ const auto yMin = ctx.yMin;+ const auto yMax = ctx.yMax;+ const auto sty = ctx.sty;+ const auto sstep = sty + 1;++ const auto sampleOffset = offset;+ const auto hasSamples = m_vd.drawSamples && _hasSamples;+ const auto hasCtxSwitch = m_vd.drawContextSwitches && _hasCtxSwitches;++ if( hasSamples )+ {+ if( hasCtxSwitch )+ {+ offset += round( ostep * 0.5f );+ }+ else+ {+ offset += round( ostep * 0.75f );+ }+ }++ const auto ctxOffset = offset;+ if( hasCtxSwitch )+ {+ offset += round( ostep * 0.75f );+ }++ const auto yPos = wpos.y + offset;+ if( !draw.empty() && yPos <= yMax && yPos + ostep * depth >= yMin )+ {+ DrawZoneList( ctx, draw, offset, thread.id );+ }+ offset += ostep * depth;++ if( hasCtxSwitch && !ctxDraw.empty() )+ {+ auto ctxSwitch = m_worker.GetContextSwitchData( thread.id );+ assert( ctxSwitch );+ DrawContextSwitchList( ctx, ctxDraw, ctxSwitch->v, ctxOffset, offset, thread.isFiber );+ }+ if( hasSamples && !samplesDraw.empty() )+ {+ DrawSampleList( ctx, samplesDraw, thread.samples, sampleOffset );+ }++ if( m_vd.drawLocks )+ {+ const auto lockDepth = DrawLocks( ctx, lockDraw, thread.id, offset, m_nextLockHighlight );+ offset += sstep * lockDepth;+ }+}++void View::DrawThreadMessagesList( const TimelineContext& ctx, const std::vector<MessagesDraw>& drawList, int offset, uint64_t tid )+{+ const auto vStart = ctx.vStart;+ const auto vEnd = ctx.vEnd;+ const auto pxns = ctx.pxns;+ const auto hover = ctx.hover;+ const auto& wpos = ctx.wpos;+ const auto ty = ctx.ty;+ const auto to = 9.f * GetScale();+ const auto th = ( ty - to ) * sqrt( 3 ) * 0.5;++ auto draw = ImGui::GetWindowDrawList();++ for( auto& v : drawList )+ {+ const auto& msg = *v.msg;+ const auto px = ( msg.time - vStart ) * pxns;+ const bool isMsgHovered = hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px - (ty - to) * 0.5 - 1, offset ), wpos + ImVec2( px + (ty - to) * 0.5 + 1, offset + ty ) );++ unsigned int color = 0xFFDDDDDD;+ float animOff = 0;+ if( v.highlight )+ {+ color = 0xFF4444FF;+ if( !isMsgHovered )+ {+ animOff = -fabs( sin( s_time * 8 ) ) * th;+ m_wasActive = true;+ }+ }++ if( v.num == 1 )+ {+ draw->AddTriangle( wpos + ImVec2( px - (ty - to) * 0.5, animOff + offset + to ), wpos + ImVec2( px + (ty - to) * 0.5, animOff + offset + to ), wpos + ImVec2( px, animOff + offset + to + th ), color, 2.0f );+ }+ else+ {+ draw->AddTriangleFilled( wpos + ImVec2( px - (ty - to) * 0.5, animOff + offset + to ), wpos + ImVec2( px + (ty - to) * 0.5, animOff + offset + to ), wpos + ImVec2( px, animOff + offset + to + th ), color );+ draw->AddTriangle( wpos + ImVec2( px - (ty - to) * 0.5, animOff + offset + to ), wpos + ImVec2( px + (ty - to) * 0.5, animOff + offset + to ), wpos + ImVec2( px, animOff + offset + to + th ), color, 2.0f );+ }++ if( isMsgHovered )+ {+ ImGui::BeginTooltip();+ if( v.num > 1 )+ {+ ImGui::Text( "%" PRIu32 " messages", v.num );+ }+ else+ {+ TextFocused( "Message at", TimeToStringExact( msg.time ) );+ ImGui::PushStyleColor( ImGuiCol_Text, msg.color );+ ImGui::TextUnformatted( m_worker.GetString( msg.ref ) );+ ImGui::PopStyleColor();+ }+ ImGui::EndTooltip();+ m_msgHighlight = &msg;++ if( IsMouseClicked( 0 ) )+ {+ m_showMessages = true;+ m_msgToFocus = &msg;+ }+ if( IsMouseClicked( 2 ) )+ {+ CenterAtTime( msg.time );+ }+ }+ }++ auto& crash = m_worker.GetCrashEvent();+ if( crash.thread == tid && crash.time >= vStart && crash.time <= vEnd )+ {+ const auto px = ( crash.time - vStart ) * pxns;++ draw->AddTriangleFilled( wpos + ImVec2( px - (ty - to) * 0.25f, offset + to + th * 0.5f ), wpos + ImVec2( px + (ty - to) * 0.25f, offset + to + th * 0.5f ), wpos + ImVec2( px, offset + to + th ), 0xFF2222FF );+ draw->AddTriangle( wpos + ImVec2( px - (ty - to) * 0.25f, offset + to + th * 0.5f ), wpos + ImVec2( px + (ty - to) * 0.25f, offset + to + th * 0.5f ), wpos + ImVec2( px, offset + to + th ), 0xFF2222FF, 2.0f );++ const auto crashText = ICON_FA_SKULL " crash " ICON_FA_SKULL;+ auto ctw = ImGui::CalcTextSize( crashText ).x;+ DrawTextContrast( draw, wpos + ImVec2( px - ctw * 0.5f, offset + to + th * 0.5f - ty ), 0xFF2222FF, crashText );++ if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px - (ty - to) * 0.5 - 1, offset ), wpos + ImVec2( px + (ty - to) * 0.5 + 1, offset + ty ) ) )+ {+ CrashTooltip();+ if( IsMouseClicked( 0 ) )+ {+ m_showInfo = true;+ }+ if( IsMouseClicked( 2 ) )+ {+ CenterAtTime( crash.time );+ }+ }+ }+}++void View::DrawThreadOverlays( const ThreadData& thread, const ImVec2& ul, const ImVec2& dr )+{+ auto draw = ImGui::GetWindowDrawList();++ if( m_gpuThread == thread.id )+ {+ draw->AddRectFilled( ul, dr, 0x228888DD );+ draw->AddRect( ul, dr, 0x448888DD );+ }+ if( m_gpuInfoWindow && m_gpuInfoWindowThread == thread.id )+ {+ draw->AddRectFilled( ul, dr, 0x2288DD88 );+ draw->AddRect( ul, dr, 0x4488DD88 );+ }+ if( m_cpuDataThread == thread.id )+ {+ draw->AddRectFilled( ul, dr, 0x2DFF8888 );+ draw->AddRect( ul, dr, 0x4DFF8888 );+ }+ if( m_selectedThread == thread.id )+ {+ draw->AddRectFilled( ul, dr, 0x2D88AA88 );+ draw->AddRect( ul, dr, 0x4D88AA88 );+ }+}++void View::DrawZoneList( const TimelineContext& ctx, const std::vector<TimelineDraw>& drawList, int _offset, uint64_t tid )+{+ auto draw = ImGui::GetWindowDrawList();+ const auto w = ctx.w;+ const auto& wpos = ctx.wpos;+ const auto dpos = wpos + ImVec2( 0.5f, 0.5f );+ const auto ty = ctx.ty;+ const auto ostep = ty + 1;+ const auto yMin = ctx.yMin;+ const auto yMax = ctx.yMax;+ const auto pxns = ctx.pxns;+ const auto hover = ctx.hover;+ const auto vStart = ctx.vStart;++ for( auto& v : drawList )+ {+ const auto offset = _offset + ostep * v.depth;+ const auto yPos = wpos.y + offset;+ if( yPos > yMax || yPos + ostep < yMin ) continue;++ switch( v.type )+ {+ case TimelineDrawType::Folded:+ {+ auto& ev = *(const ZoneEvent*)v.ev.get();+ const auto color = v.inheritedColor ? v.inheritedColor : ( m_vd.dynamicColors == 2 ? 0xFF666666 : GetThreadColor( tid, v.depth ) );+ const auto rend = v.rend.Val();+ const auto px0 = ( ev.Start() - vStart ) * pxns;+ const auto px1 = ( rend - vStart ) * pxns;+ draw->AddRectFilled( wpos + ImVec2( std::max( px0, -10.0 ), offset ), wpos + ImVec2( std::min( std::max( px1, px0+MinVisSize ), double( w + 10 ) ), offset + ty ), color );+ DrawZigZag( draw, wpos + ImVec2( 0, offset + ty/2 ), std::max( px0, -10.0 ), std::min( std::max( px1, px0+MinVisSize ), double( w + 10 ) ), ty/4, DarkenColor( color ) );+ if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( std::max( px0, -10.0 ), offset ), wpos + ImVec2( std::min( std::max( px1, px0+MinVisSize ), double( w + 10 ) ), offset + ty + 1 ) ) )+ {+ if( IsMouseClickReleased( 1 ) ) m_setRangePopup = RangeSlim { ev.Start(), rend, true };+ if( v.num > 1 )+ {+ ImGui::BeginTooltip();+ TextFocused( "Zones too small to display:", RealToString( v.num ) );+ ImGui::Separator();+ TextFocused( "Execution time:", TimeToString( rend - ev.Start() ) );+ ImGui::EndTooltip();++ if( IsMouseClicked( 2 ) && rend - ev.Start() > 0 )+ {+ ZoomToRange( ev.Start(), rend );+ }+ }+ else+ {+ ZoneTooltip( ev );++ if( IsMouseClicked( 2 ) && rend - ev.Start() > 0 )+ {+ ZoomToZone( ev );+ }+ if( IsMouseClicked( 0 ) )+ {+ if( ImGui::GetIO().KeyCtrl )+ {+ auto& srcloc = m_worker.GetSourceLocation( ev.SrcLoc() );+ m_findZone.ShowZone( ev.SrcLoc(), m_worker.GetString( srcloc.name.active ? srcloc.name : srcloc.function ) );+ }+ else+ {+ ShowZoneInfo( ev );+ }+ }++ m_zoneSrcLocHighlight = ev.SrcLoc();+ m_zoneHover = &ev;+ }+ }+ const auto tmp = RealToString( v.num );+ const auto tsz = ImGui::CalcTextSize( tmp );+ if( tsz.x < px1 - px0 )+ {+ const auto x = px0 + ( px1 - px0 - tsz.x ) / 2;+ DrawTextContrast( draw, wpos + ImVec2( x, offset ), 0xFF4488DD, tmp );+ }+ break;+ }+ case TimelineDrawType::Zone:+ {+ auto& ev = *(const ZoneEvent*)v.ev.get();+ const auto end = m_worker.GetZoneEnd( ev );+ const auto zsz = std::max( ( end - ev.Start() ) * pxns, pxns * 0.5 );+ const auto zoneColor = GetZoneColorData( ev, tid, v.depth, v.inheritedColor );+ const char* zoneName = m_worker.GetZoneName( ev );++ auto tsz = ImGui::CalcTextSize( zoneName );+ if( m_vd.shortenName == ShortenName::Always || ( ( m_vd.shortenName == ShortenName::NoSpace || m_vd.shortenName == ShortenName::NoSpaceAndNormalize ) && tsz.x > zsz ) )+ {+ zoneName = ShortenZoneName( m_vd.shortenName, zoneName, tsz, zsz );+ }++ const auto pr0 = ( ev.Start() - m_vd.zvStart ) * pxns;+ const auto pr1 = ( end - m_vd.zvStart ) * pxns;+ const auto px0 = std::max( pr0, -10.0 );+ const auto px1 = std::max( { std::min( pr1, double( w + 10 ) ), px0 + pxns * 0.5, px0 + MinVisSize } );+ draw->AddRectFilled( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + tsz.y ), zoneColor.color );+ if( zoneColor.highlight )+ {+ if( zoneColor.thickness > 1.f )+ {+ draw->AddRect( wpos + ImVec2( px0 + 1, offset + 1 ), wpos + ImVec2( px1 - 1, offset + tsz.y - 1 ), zoneColor.accentColor, 0.f, -1, zoneColor.thickness );+ }+ else+ {+ draw->AddRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + tsz.y ), zoneColor.accentColor, 0.f, -1, zoneColor.thickness );+ }+ }+ else+ {+ const auto darkColor = DarkenColor( zoneColor.color );+ DrawLine( draw, dpos + ImVec2( px0, offset + tsz.y ), dpos + ImVec2( px0, offset ), dpos + ImVec2( px1-1, offset ), zoneColor.accentColor, zoneColor.thickness );+ DrawLine( draw, dpos + ImVec2( px0, offset + tsz.y ), dpos + ImVec2( px1-1, offset + tsz.y ), dpos + ImVec2( px1-1, offset ), darkColor, zoneColor.thickness );+ }+ if( tsz.x < zsz )+ {+ const auto x = ( ev.Start() - m_vd.zvStart ) * pxns + ( ( end - ev.Start() ) * pxns - tsz.x ) / 2;+ if( x < 0 || x > w - tsz.x )+ {+ ImGui::PushClipRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + tsz.y * 2 ), true );+ DrawTextContrast( draw, wpos + ImVec2( std::max( std::max( 0., px0 ), std::min( double( w - tsz.x ), x ) ), offset ), 0xFFFFFFFF, zoneName );+ ImGui::PopClipRect();+ }+ else if( ev.Start() == ev.End() )+ {+ DrawTextContrast( draw, wpos + ImVec2( px0 + ( px1 - px0 - tsz.x ) * 0.5, offset ), 0xFFFFFFFF, zoneName );+ }+ else+ {+ DrawTextContrast( draw, wpos + ImVec2( x, offset ), 0xFFFFFFFF, zoneName );+ }+ }+ else+ {+ ImGui::PushClipRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + tsz.y * 2 ), true );+ DrawTextContrast( draw, wpos + ImVec2( std::max( int64_t( 0 ), ev.Start() - m_vd.zvStart ) * pxns, offset ), 0xFFFFFFFF, zoneName );+ ImGui::PopClipRect();+ }++ if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + tsz.y + 1 ) ) )+ {+ ZoneTooltip( ev );+ if( IsMouseClickReleased( 1 ) ) m_setRangePopup = RangeSlim { ev.Start(), m_worker.GetZoneEnd( ev ), true };++ if( !m_zoomAnim.active && IsMouseClicked( 2 ) )+ {+ ZoomToZone( ev );+ }+ if( IsMouseClicked( 0 ) )+ {+ if( ImGui::GetIO().KeyCtrl )+ {+ auto& srcloc = m_worker.GetSourceLocation( ev.SrcLoc() );+ m_findZone.ShowZone( ev.SrcLoc(), m_worker.GetString( srcloc.name.active ? srcloc.name : srcloc.function ) );+ }+ else+ {+ ShowZoneInfo( ev );+ }+ }++ m_zoneSrcLocHighlight = ev.SrcLoc();+ m_zoneHover = &ev;+ }+ break;+ }+#ifndef TRACY_NO_STATISTICS+ case TimelineDrawType::GhostFolded:+ {+ auto& ev = *(const GhostZone*)v.ev.get();+ const auto color = m_vd.dynamicColors == 2 ? 0xFF666666 : MixGhostColor( GetThreadColor( tid, v.depth ), 0x665555 );+ const auto rend = v.rend.Val();+ const auto px0 = ( ev.start.Val() - m_vd.zvStart ) * pxns;+ const auto px1 = ( rend - m_vd.zvStart ) * pxns;+ draw->AddRectFilled( wpos + ImVec2( std::max( px0, -10.0 ), offset ), wpos + ImVec2( std::min( std::max( px1, px0+MinVisSize ), double( w + 10 ) ), offset + ty ), color );+ DrawZigZag( draw, wpos + ImVec2( 0, offset + ty/2 ), std::max( px0, -10.0 ), std::min( std::max( px1, px0+MinVisSize ), double( w + 10 ) ), ty/4, DarkenColor( color ) );+ if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( std::max( px0, -10.0 ), offset ), wpos + ImVec2( std::min( std::max( px1, px0+MinVisSize ), double( w + 10 ) ), offset + ty + 1 ) ) )+ {+ if( IsMouseClickReleased( 1 ) ) m_setRangePopup = RangeSlim { ev.start.Val(), rend , true };+ ImGui::BeginTooltip();+ ImGui::TextUnformatted( "Multiple ghost zones" );+ ImGui::Separator();+ TextFocused( "Execution time:", TimeToString( rend - ev.start.Val() ) );+ ImGui::EndTooltip();++ if( IsMouseClicked( 2 ) && rend - ev.start.Val() > 0 )+ {+ ZoomToRange( ev.start.Val(), rend );+ }+ }+ break;+ }+ case TimelineDrawType::Ghost:+ {+ auto& ev = *(const GhostZone*)v.ev.get();+ const auto end = ev.end.Val();+ const auto zsz = std::max( ( end - ev.start.Val() ) * pxns, pxns * 0.5 );++ const auto& ghostKey = m_worker.GetGhostFrame( ev.frame );+ const auto frame = m_worker.GetCallstackFrame( ghostKey.frame );++ uint32_t color;+ if( m_vd.dynamicColors == 2 )+ {+ if( frame )+ {+ const auto& sym = frame->data[ghostKey.inlineFrame];+ color = GetHsvColor( sym.name.Idx(), v.depth );+ }+ else+ {+ color = GetHsvColor( ghostKey.frame.data, v.depth );+ }+ }+ else+ {+ color = MixGhostColor( GetThreadColor( tid, v.depth ), 0x665555 );+ }++ const auto pr0 = ( ev.start.Val() - m_vd.zvStart ) * pxns;+ const auto pr1 = ( ev.end.Val() - m_vd.zvStart ) * pxns;+ const auto px0 = std::max( pr0, -10.0 );+ const auto px1 = std::max( { std::min( pr1, double( w + 10 ) ), px0 + pxns * 0.5, px0 + MinVisSize } );+ if( !frame )+ {+ char symName[64];+ sprintf( symName, "0x%" PRIx64, m_worker.GetCanonicalPointer( ghostKey.frame ) );+ const auto tsz = ImGui::CalcTextSize( symName );++ const auto accentColor = HighlightColor( color );+ const auto darkColor = DarkenColor( color );+ const auto txtColor = 0xFF888888;+ draw->AddRectFilled( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + tsz.y ), DarkenColor( color ) );+ DrawLine( draw, dpos + ImVec2( px0, offset + tsz.y ), dpos + ImVec2( px0, offset ), dpos + ImVec2( px1-1, offset ), accentColor, 1.f );+ DrawLine( draw, dpos + ImVec2( px0, offset + tsz.y ), dpos + ImVec2( px1-1, offset + tsz.y ), dpos + ImVec2( px1-1, offset ), darkColor, 1.f );++ if( tsz.x < zsz )+ {+ const auto x = ( ev.start.Val() - m_vd.zvStart ) * pxns + ( ( end - ev.start.Val() ) * pxns - tsz.x ) / 2;+ if( x < 0 || x > w - tsz.x )+ {+ ImGui::PushClipRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + tsz.y * 2 ), true );+ DrawTextContrast( draw, wpos + ImVec2( std::max( std::max( 0., px0 ), std::min( double( w - tsz.x ), x ) ), offset ), txtColor, symName );+ ImGui::PopClipRect();+ }+ else if( ev.start.Val() == ev.end.Val() )+ {+ DrawTextContrast( draw, wpos + ImVec2( px0 + ( px1 - px0 - tsz.x ) * 0.5, offset ), txtColor, symName );+ }+ else+ {+ DrawTextContrast( draw, wpos + ImVec2( x, offset ), txtColor, symName );+ }+ }+ else+ {+ ImGui::PushClipRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + tsz.y * 2 ), true );+ DrawTextContrast( draw, wpos + ImVec2( ( ev.start.Val() - m_vd.zvStart ) * pxns, offset ), txtColor, symName );+ ImGui::PopClipRect();+ }++ if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + tsz.y + 1 ) ) )+ {+ if( IsMouseClickReleased( 1 ) ) m_setRangePopup = RangeSlim { ev.start.Val(), ev.end.Val() , true };+ ImGui::BeginTooltip();+ TextDisabledUnformatted( ICON_FA_GHOST " Ghost zone" );+ ImGui::Separator();+ TextFocused( "Unknown frame:", symName );+ TextFocused( "Thread:", m_worker.GetThreadName( tid ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( tid ) );+ if( m_worker.IsThreadFiber( tid ) )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 0.2f, 0.6f, 0.2f, 1.f ), "Fiber" );+ }+ ImGui::Separator();+ TextFocused( "Execution time:", TimeToString( ev.end.Val() - ev.start.Val() ) );+ ImGui::EndTooltip();+ if( !m_zoomAnim.active && IsMouseClicked( 2 ) )+ {+ ZoomToRange( ev.start.Val(), ev.end.Val() );+ }+ }+ }+ else+ {+ const auto& sym = frame->data[ghostKey.inlineFrame];+ const auto isInline = ghostKey.inlineFrame != frame->size-1;+ const auto col = isInline ? DarkenColor( color ) : color;+ auto symName = m_worker.GetString( sym.name );+ uint32_t txtColor;+ if( symName[0] == '[' )+ {+ txtColor = 0xFF999999;+ }+ else if( !isInline && ( m_worker.GetCanonicalPointer( ghostKey.frame ) >> 63 != 0 ) )+ {+ txtColor = 0xFF8888FF;+ }+ else+ {+ txtColor = 0xFFFFFFFF;+ }+ auto tsz = ImGui::CalcTextSize( symName );++ const auto accentColor = HighlightColor( col );+ const auto darkColor = DarkenColor( col );+ draw->AddRectFilled( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + tsz.y ), col );+ DrawLine( draw, dpos + ImVec2( px0, offset + tsz.y ), dpos + ImVec2( px0, offset ), dpos + ImVec2( px1-1, offset ), accentColor, 1.f );+ DrawLine( draw, dpos + ImVec2( px0, offset + tsz.y ), dpos + ImVec2( px1-1, offset + tsz.y ), dpos + ImVec2( px1-1, offset ), darkColor, 1.f );++ auto origSymName = symName;+ if( m_vd.shortenName != ShortenName::Never && ( m_vd.shortenName != ShortenName::NoSpace || tsz.x > zsz ) )+ {+ symName = ShortenZoneName( m_vd.shortenName, symName, tsz, zsz );+ }++ if( tsz.x < zsz )+ {+ const auto x = ( ev.start.Val() - m_vd.zvStart ) * pxns + ( ( end - ev.start.Val() ) * pxns - tsz.x ) / 2;+ if( x < 0 || x > w - tsz.x )+ {+ ImGui::PushClipRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + tsz.y * 2 ), true );+ DrawTextContrast( draw, wpos + ImVec2( std::max( std::max( 0., px0 ), std::min( double( w - tsz.x ), x ) ), offset ), txtColor, symName );+ ImGui::PopClipRect();+ }+ else if( ev.start.Val() == ev.end.Val() )+ {+ DrawTextContrast( draw, wpos + ImVec2( px0 + ( px1 - px0 - tsz.x ) * 0.5, offset ), txtColor, symName );+ }+ else+ {+ DrawTextContrast( draw, wpos + ImVec2( x, offset ), txtColor, symName );+ }+ }+ else+ {+ ImGui::PushClipRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + tsz.y * 2 ), true );+ DrawTextContrast( draw, wpos + ImVec2( std::max( int64_t( 0 ), ev.start.Val() - m_vd.zvStart ) * pxns, offset ), txtColor, symName );+ ImGui::PopClipRect();+ }++ if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + tsz.y + 1 ) ) )+ {+ if( IsMouseClickReleased( 1 ) ) m_setRangePopup = RangeSlim { ev.start.Val(), ev.end.Val(), true };+ ImGui::BeginTooltip();+ TextDisabledUnformatted( ICON_FA_GHOST " Ghost zone" );+ if( sym.symAddr >> 63 != 0 )+ {+ ImGui::SameLine();+ TextDisabledUnformatted( ICON_FA_HAT_WIZARD " kernel" );+ }+ ImGui::Separator();+ const auto normalized = m_vd.shortenName == ShortenName::Never ? origSymName : ShortenZoneName( ShortenName::OnlyNormalize, origSymName );+ ImGui::TextUnformatted( normalized );+ if( isInline )+ {+ ImGui::SameLine();+ TextDisabledUnformatted( "[inline]" );+ }+ if( normalized != origSymName && strcmp( normalized, origSymName ) != 0 )+ {+ ImGui::PushFont( m_smallFont );+ TextDisabledUnformatted( origSymName );+ ImGui::PopFont();+ }+ const auto symbol = m_worker.GetSymbolData( sym.symAddr );+ if( symbol ) TextFocused( "Image:", m_worker.GetString( symbol->imageName ) );+ TextDisabledUnformatted( "Location:" );+ ImGui::SameLine();+ const char* file = m_worker.GetString( sym.file );+ uint32_t line = sym.line;+ ImGui::TextUnformatted( LocationToString( file, line ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(0x%" PRIx64 ")", sym.symAddr );+ TextFocused( "Thread:", m_worker.GetThreadName( tid ) );+ ImGui::SameLine();+ ImGui::TextDisabled( "(%s)", RealToString( tid ) );+ if( m_worker.IsThreadFiber( tid ) )+ {+ ImGui::SameLine();+ TextColoredUnformatted( ImVec4( 0.2f, 0.6f, 0.2f, 1.f ), "Fiber" );+ }+ ImGui::Separator();+ TextFocused( "Execution time:", TimeToString( ev.end.Val() - ev.start.Val() ) );+ ImGui::EndTooltip();++ if( IsMouseClicked( 0 ) )+ {+ ViewDispatch( file, line, sym.symAddr );+ }+ else if( !m_zoomAnim.active && IsMouseClicked( 2 ) )+ {+ ZoomToRange( ev.start.Val(), ev.end.Val() );+ }+ }+ }+ break;+ }+#endif+ default:+ assert( false );+ break;+ }+ }+}++}
+ cbits/tracy/profiler/src/profiler/TracyWeb.cpp view
@@ -0,0 +1,33 @@+#ifdef _WIN32+# include <windows.h>+# include <shellapi.h>+#elif defined __EMSCRIPTEN__+# include <emscripten.h>+#else+# include <stdio.h>+# include <stdlib.h>+#endif++#include "TracyWeb.hpp"++namespace tracy+{++void OpenWebpage( const char* url )+{+#ifdef _WIN32+ ShellExecuteA( nullptr, nullptr, url, nullptr, nullptr, 0 );+#elif defined __APPLE__+ char buf[1024];+ sprintf( buf, "open %s", url );+ system( buf );+#elif defined __EMSCRIPTEN__+ EM_ASM( { window.open( UTF8ToString( $0 ), '_blank' ) }, url );+#else+ char buf[1024];+ sprintf( buf, "xdg-open %s", url );+ system( buf );+#endif+}++}
+ cbits/tracy/profiler/src/profiler/TracyWeb.hpp view
@@ -0,0 +1,11 @@+#ifndef __TRACYWEB_HPP__+#define __TRACYWEB_HPP__++namespace tracy+{++void OpenWebpage( const char* url );++}++#endif
+ cbits/tracy/profiler/src/stb_image.h view
@@ -0,0 +1,7985 @@+/* stb_image - v2.29 - public domain image loader - http://nothings.org/stb+ no warranty implied; use at your own risk++ Do this:+ #define STB_IMAGE_IMPLEMENTATION+ before you include this file in *one* C or C++ file to create the implementation.++ // i.e. it should look like this:+ #include ...+ #include ...+ #include ...+ #define STB_IMAGE_IMPLEMENTATION+ #include "stb_image.h"++ You can #define STBI_ASSERT(x) before the #include to avoid using assert.h.+ And #define STBI_MALLOC, STBI_REALLOC, and STBI_FREE to avoid using malloc,realloc,free+++ QUICK NOTES:+ Primarily of interest to game developers and other people who can+ avoid problematic images and only need the trivial interface++ JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib)+ PNG 1/2/4/8/16-bit-per-channel++ TGA (not sure what subset, if a subset)+ BMP non-1bpp, non-RLE+ PSD (composited view only, no extra channels, 8/16 bit-per-channel)++ GIF (*comp always reports as 4-channel)+ HDR (radiance rgbE format)+ PIC (Softimage PIC)+ PNM (PPM and PGM binary only)++ Animated GIF still needs a proper API, but here's one way to do it:+ http://gist.github.com/urraka/685d9a6340b26b830d49++ - decode from memory or through FILE (define STBI_NO_STDIO to remove code)+ - decode from arbitrary I/O callbacks+ - SIMD acceleration on x86/x64 (SSE2) and ARM (NEON)++ Full documentation under "DOCUMENTATION" below.+++LICENSE++ See end of file for license information.++RECENT REVISION HISTORY:++ 2.29 (2023-05-xx) optimizations+ 2.28 (2023-01-29) many error fixes, security errors, just tons of stuff+ 2.27 (2021-07-11) document stbi_info better, 16-bit PNM support, bug fixes+ 2.26 (2020-07-13) many minor fixes+ 2.25 (2020-02-02) fix warnings+ 2.24 (2020-02-02) fix warnings; thread-local failure_reason and flip_vertically+ 2.23 (2019-08-11) fix clang static analysis warning+ 2.22 (2019-03-04) gif fixes, fix warnings+ 2.21 (2019-02-25) fix typo in comment+ 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs+ 2.19 (2018-02-11) fix warning+ 2.18 (2018-01-30) fix warnings+ 2.17 (2018-01-29) bugfix, 1-bit BMP, 16-bitness query, fix warnings+ 2.16 (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes+ 2.15 (2017-03-18) fix png-1,2,4; all Imagenet JPGs; no runtime SSE detection on GCC+ 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs+ 2.13 (2016-12-04) experimental 16-bit API, only for PNG so far; fixes+ 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes+ 2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64+ RGB-format JPEG; remove white matting in PSD;+ allocate large structures on the stack;+ correct channel count for PNG & BMP+ 2.10 (2016-01-22) avoid warning introduced in 2.09+ 2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED++ See end of file for full revision history.+++ ============================ Contributors =========================++ Image formats Extensions, features+ Sean Barrett (jpeg, png, bmp) Jetro Lauha (stbi_info)+ Nicolas Schulz (hdr, psd) Martin "SpartanJ" Golini (stbi_info)+ Jonathan Dummer (tga) James "moose2000" Brown (iPhone PNG)+ Jean-Marc Lienher (gif) Ben "Disch" Wenger (io callbacks)+ Tom Seddon (pic) Omar Cornut (1/2/4-bit PNG)+ Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip)+ Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD)+ github:urraka (animated gif) Junggon Kim (PNM comments)+ Christopher Forseth (animated gif) Daniel Gibson (16-bit TGA)+ socks-the-fox (16-bit PNG)+ Jeremy Sawicki (handle all ImageNet JPGs)+ Optimizations & bugfixes Mikhail Morozov (1-bit BMP)+ Fabian "ryg" Giesen Anael Seghezzi (is-16-bit query)+ Arseny Kapoulkine Simon Breuss (16-bit PNM)+ John-Mark Allen+ Carmelo J Fdez-Aguera++ Bug & warning fixes+ Marc LeBlanc David Woo Guillaume George Martins Mozeiko+ Christpher Lloyd Jerry Jansson Joseph Thomson Blazej Dariusz Roszkowski+ Phil Jordan Dave Moore Roy Eltham+ Hayaki Saito Nathan Reed Won Chun+ Luke Graham Johan Duparc Nick Verigakis the Horde3D community+ Thomas Ruf Ronny Chevalier github:rlyeh+ Janez Zemva John Bartholomew Michal Cichon github:romigrou+ Jonathan Blow Ken Hamada Tero Hanninen github:svdijk+ Eugene Golushkov Laurent Gomila Cort Stratton github:snagar+ Aruelien Pocheville Sergio Gonzalez Thibault Reuille github:Zelex+ Cass Everitt Ryamond Barbiero github:grim210+ Paul Du Bois Engin Manap Aldo Culquicondor github:sammyhw+ Philipp Wiesemann Dale Weiler Oriol Ferrer Mesia github:phprus+ Josh Tobin Neil Bickford Matthew Gregan github:poppolopoppo+ Julian Raschke Gregory Mullen Christian Floisand github:darealshinji+ Baldur Karlsson Kevin Schmidt JR Smith github:Michaelangel007+ Brad Weinberger Matvey Cherevko github:mosra+ Luca Sas Alexander Veselov Zack Middleton [reserved]+ Ryan C. Gordon [reserved] [reserved]+ DO NOT ADD YOUR NAME HERE++ Jacko Dirks++ To add your name to the credits, pick a random blank space in the middle and fill it.+ 80% of merge conflicts on stb PRs are due to people adding their name at the end+ of the credits.+*/++#ifndef STBI_INCLUDE_STB_IMAGE_H+#define STBI_INCLUDE_STB_IMAGE_H++// DOCUMENTATION+//+// Limitations:+// - no 12-bit-per-channel JPEG+// - no JPEGs with arithmetic coding+// - GIF always returns *comp=4+//+// Basic usage (see HDR discussion below for HDR usage):+// int x,y,n;+// unsigned char *data = stbi_load(filename, &x, &y, &n, 0);+// // ... process data if not NULL ...+// // ... x = width, y = height, n = # 8-bit components per pixel ...+// // ... replace '0' with '1'..'4' to force that many components per pixel+// // ... but 'n' will always be the number that it would have been if you said 0+// stbi_image_free(data);+//+// Standard parameters:+// int *x -- outputs image width in pixels+// int *y -- outputs image height in pixels+// int *channels_in_file -- outputs # of image components in image file+// int desired_channels -- if non-zero, # of image components requested in result+//+// The return value from an image loader is an 'unsigned char *' which points+// to the pixel data, or NULL on an allocation failure or if the image is+// corrupt or invalid. The pixel data consists of *y scanlines of *x pixels,+// with each pixel consisting of N interleaved 8-bit components; the first+// pixel pointed to is top-left-most in the image. There is no padding between+// image scanlines or between pixels, regardless of format. The number of+// components N is 'desired_channels' if desired_channels is non-zero, or+// *channels_in_file otherwise. If desired_channels is non-zero,+// *channels_in_file has the number of components that _would_ have been+// output otherwise. E.g. if you set desired_channels to 4, you will always+// get RGBA output, but you can check *channels_in_file to see if it's trivially+// opaque because e.g. there were only 3 channels in the source image.+//+// An output image with N components has the following components interleaved+// in this order in each pixel:+//+// N=#comp components+// 1 grey+// 2 grey, alpha+// 3 red, green, blue+// 4 red, green, blue, alpha+//+// If image loading fails for any reason, the return value will be NULL,+// and *x, *y, *channels_in_file will be unchanged. The function+// stbi_failure_reason() can be queried for an extremely brief, end-user+// unfriendly explanation of why the load failed. Define STBI_NO_FAILURE_STRINGS+// to avoid compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly+// more user-friendly ones.+//+// Paletted PNG, BMP, GIF, and PIC images are automatically depalettized.+//+// To query the width, height and component count of an image without having to+// decode the full file, you can use the stbi_info family of functions:+//+// int x,y,n,ok;+// ok = stbi_info(filename, &x, &y, &n);+// // returns ok=1 and sets x, y, n if image is a supported format,+// // 0 otherwise.+//+// Note that stb_image pervasively uses ints in its public API for sizes,+// including sizes of memory buffers. This is now part of the API and thus+// hard to change without causing breakage. As a result, the various image+// loaders all have certain limits on image size; these differ somewhat+// by format but generally boil down to either just under 2GB or just under+// 1GB. When the decoded image would be larger than this, stb_image decoding+// will fail.+//+// Additionally, stb_image will reject image files that have any of their+// dimensions set to a larger value than the configurable STBI_MAX_DIMENSIONS,+// which defaults to 2**24 = 16777216 pixels. Due to the above memory limit,+// the only way to have an image with such dimensions load correctly+// is for it to have a rather extreme aspect ratio. Either way, the+// assumption here is that such larger images are likely to be malformed+// or malicious. If you do need to load an image with individual dimensions+// larger than that, and it still fits in the overall size limit, you can+// #define STBI_MAX_DIMENSIONS on your own to be something larger.+//+// ===========================================================================+//+// UNICODE:+//+// If compiling for Windows and you wish to use Unicode filenames, compile+// with+// #define STBI_WINDOWS_UTF8+// and pass utf8-encoded filenames. Call stbi_convert_wchar_to_utf8 to convert+// Windows wchar_t filenames to utf8.+//+// ===========================================================================+//+// Philosophy+//+// stb libraries are designed with the following priorities:+//+// 1. easy to use+// 2. easy to maintain+// 3. good performance+//+// Sometimes I let "good performance" creep up in priority over "easy to maintain",+// and for best performance I may provide less-easy-to-use APIs that give higher+// performance, in addition to the easy-to-use ones. Nevertheless, it's important+// to keep in mind that from the standpoint of you, a client of this library,+// all you care about is #1 and #3, and stb libraries DO NOT emphasize #3 above all.+//+// Some secondary priorities arise directly from the first two, some of which+// provide more explicit reasons why performance can't be emphasized.+//+// - Portable ("ease of use")+// - Small source code footprint ("easy to maintain")+// - No dependencies ("ease of use")+//+// ===========================================================================+//+// I/O callbacks+//+// I/O callbacks allow you to read from arbitrary sources, like packaged+// files or some other source. Data read from callbacks are processed+// through a small internal buffer (currently 128 bytes) to try to reduce+// overhead.+//+// The three functions you must define are "read" (reads some bytes of data),+// "skip" (skips some bytes of data), "eof" (reports if the stream is at the end).+//+// ===========================================================================+//+// SIMD support+//+// The JPEG decoder will try to automatically use SIMD kernels on x86 when+// supported by the compiler. For ARM Neon support, you must explicitly+// request it.+//+// (The old do-it-yourself SIMD API is no longer supported in the current+// code.)+//+// On x86, SSE2 will automatically be used when available based on a run-time+// test; if not, the generic C versions are used as a fall-back. On ARM targets,+// the typical path is to have separate builds for NEON and non-NEON devices+// (at least this is true for iOS and Android). Therefore, the NEON support is+// toggled by a build flag: define STBI_NEON to get NEON loops.+//+// If for some reason you do not want to use any of SIMD code, or if+// you have issues compiling it, you can disable it entirely by+// defining STBI_NO_SIMD.+//+// ===========================================================================+//+// HDR image support (disable by defining STBI_NO_HDR)+//+// stb_image supports loading HDR images in general, and currently the Radiance+// .HDR file format specifically. You can still load any file through the existing+// interface; if you attempt to load an HDR file, it will be automatically remapped+// to LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1;+// both of these constants can be reconfigured through this interface:+//+// stbi_hdr_to_ldr_gamma(2.2f);+// stbi_hdr_to_ldr_scale(1.0f);+//+// (note, do not use _inverse_ constants; stbi_image will invert them+// appropriately).+//+// Additionally, there is a new, parallel interface for loading files as+// (linear) floats to preserve the full dynamic range:+//+// float *data = stbi_loadf(filename, &x, &y, &n, 0);+//+// If you load LDR images through this interface, those images will+// be promoted to floating point values, run through the inverse of+// constants corresponding to the above:+//+// stbi_ldr_to_hdr_scale(1.0f);+// stbi_ldr_to_hdr_gamma(2.2f);+//+// Finally, given a filename (or an open file or memory block--see header+// file for details) containing image data, you can query for the "most+// appropriate" interface to use (that is, whether the image is HDR or+// not), using:+//+// stbi_is_hdr(char *filename);+//+// ===========================================================================+//+// iPhone PNG support:+//+// We optionally support converting iPhone-formatted PNGs (which store+// premultiplied BGRA) back to RGB, even though they're internally encoded+// differently. To enable this conversion, call+// stbi_convert_iphone_png_to_rgb(1).+//+// Call stbi_set_unpremultiply_on_load(1) as well to force a divide per+// pixel to remove any premultiplied alpha *only* if the image file explicitly+// says there's premultiplied data (currently only happens in iPhone images,+// and only if iPhone convert-to-rgb processing is on).+//+// ===========================================================================+//+// ADDITIONAL CONFIGURATION+//+// - You can suppress implementation of any of the decoders to reduce+// your code footprint by #defining one or more of the following+// symbols before creating the implementation.+//+// STBI_NO_JPEG+// STBI_NO_PNG+// STBI_NO_BMP+// STBI_NO_PSD+// STBI_NO_TGA+// STBI_NO_GIF+// STBI_NO_HDR+// STBI_NO_PIC+// STBI_NO_PNM (.ppm and .pgm)+//+// - You can request *only* certain decoders and suppress all other ones+// (this will be more forward-compatible, as addition of new decoders+// doesn't require you to disable them explicitly):+//+// STBI_ONLY_JPEG+// STBI_ONLY_PNG+// STBI_ONLY_BMP+// STBI_ONLY_PSD+// STBI_ONLY_TGA+// STBI_ONLY_GIF+// STBI_ONLY_HDR+// STBI_ONLY_PIC+// STBI_ONLY_PNM (.ppm and .pgm)+//+// - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still+// want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB+//+// - If you define STBI_MAX_DIMENSIONS, stb_image will reject images greater+// than that size (in either width or height) without further processing.+// This is to let programs in the wild set an upper bound to prevent+// denial-of-service attacks on untrusted data, as one could generate a+// valid image of gigantic dimensions and force stb_image to allocate a+// huge block of memory and spend disproportionate time decoding it. By+// default this is set to (1 << 24), which is 16777216, but that's still+// very big.++#ifndef STBI_NO_STDIO+#include <stdio.h>+#endif // STBI_NO_STDIO++#define STBI_VERSION 1++enum+{+ STBI_default = 0, // only used for desired_channels++ STBI_grey = 1,+ STBI_grey_alpha = 2,+ STBI_rgb = 3,+ STBI_rgb_alpha = 4+};++#include <stdlib.h>+typedef unsigned char stbi_uc;+typedef unsigned short stbi_us;++#ifdef __cplusplus+extern "C" {+#endif++#ifndef STBIDEF+#ifdef STB_IMAGE_STATIC+#define STBIDEF static+#else+#define STBIDEF extern+#endif+#endif++//////////////////////////////////////////////////////////////////////////////+//+// PRIMARY API - works on images of any type+//++//+// load image by filename, open file, or memory buffer+//++typedef struct+{+ int (*read) (void *user,char *data,int size); // fill 'data' with 'size' bytes. return number of bytes actually read+ void (*skip) (void *user,int n); // skip the next 'n' bytes, or 'unget' the last -n bytes if negative+ int (*eof) (void *user); // returns nonzero if we are at end of file/data+} stbi_io_callbacks;++////////////////////////////////////+//+// 8-bits-per-channel interface+//++STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *channels_in_file, int desired_channels);+STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *channels_in_file, int desired_channels);++#ifndef STBI_NO_STDIO+STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);+STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels);+// for stbi_load_from_file, file pointer is left pointing immediately after image+#endif++#ifndef STBI_NO_GIF+STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp);+#endif++#ifdef STBI_WINDOWS_UTF8+STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input);+#endif++////////////////////////////////////+//+// 16-bits-per-channel interface+//++STBIDEF stbi_us *stbi_load_16_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels);+STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels);++#ifndef STBI_NO_STDIO+STBIDEF stbi_us *stbi_load_16 (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);+STBIDEF stbi_us *stbi_load_from_file_16(FILE *f, int *x, int *y, int *channels_in_file, int desired_channels);+#endif++////////////////////////////////////+//+// float-per-channel interface+//+#ifndef STBI_NO_LINEAR+ STBIDEF float *stbi_loadf_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels);+ STBIDEF float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels);++ #ifndef STBI_NO_STDIO+ STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);+ STBIDEF float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels);+ #endif+#endif++#ifndef STBI_NO_HDR+ STBIDEF void stbi_hdr_to_ldr_gamma(float gamma);+ STBIDEF void stbi_hdr_to_ldr_scale(float scale);+#endif // STBI_NO_HDR++#ifndef STBI_NO_LINEAR+ STBIDEF void stbi_ldr_to_hdr_gamma(float gamma);+ STBIDEF void stbi_ldr_to_hdr_scale(float scale);+#endif // STBI_NO_LINEAR++// stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR+STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user);+STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len);+#ifndef STBI_NO_STDIO+STBIDEF int stbi_is_hdr (char const *filename);+STBIDEF int stbi_is_hdr_from_file(FILE *f);+#endif // STBI_NO_STDIO+++// get a VERY brief reason for failure+// on most compilers (and ALL modern mainstream compilers) this is threadsafe+STBIDEF const char *stbi_failure_reason (void);++// free the loaded image -- this is just free()+STBIDEF void stbi_image_free (void *retval_from_stbi_load);++// get image dimensions & components without fully decoding+STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp);+STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp);+STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len);+STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *clbk, void *user);++#ifndef STBI_NO_STDIO+STBIDEF int stbi_info (char const *filename, int *x, int *y, int *comp);+STBIDEF int stbi_info_from_file (FILE *f, int *x, int *y, int *comp);+STBIDEF int stbi_is_16_bit (char const *filename);+STBIDEF int stbi_is_16_bit_from_file(FILE *f);+#endif++++// for image formats that explicitly notate that they have premultiplied alpha,+// we just return the colors as stored in the file. set this flag to force+// unpremultiplication. results are undefined if the unpremultiply overflow.+STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply);++// indicate whether we should process iphone images back to canonical format,+// or just pass them through "as-is"+STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert);++// flip the image vertically, so the first pixel in the output array is the bottom left+STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip);++// as above, but only applies to images loaded on the thread that calls the function+// this function is only available if your compiler supports thread-local variables;+// calling it will fail to link if your compiler doesn't+STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply);+STBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert);+STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip);++// ZLIB client - used by PNG, available for other purposes++STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen);+STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header);+STBIDEF char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen);+STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen);++STBIDEF char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen);+STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen);+++#ifdef __cplusplus+}+#endif++//+//+//// end header file /////////////////////////////////////////////////////+#endif // STBI_INCLUDE_STB_IMAGE_H++#ifdef STB_IMAGE_IMPLEMENTATION++#if defined(STBI_ONLY_JPEG) || defined(STBI_ONLY_PNG) || defined(STBI_ONLY_BMP) \+ || defined(STBI_ONLY_TGA) || defined(STBI_ONLY_GIF) || defined(STBI_ONLY_PSD) \+ || defined(STBI_ONLY_HDR) || defined(STBI_ONLY_PIC) || defined(STBI_ONLY_PNM) \+ || defined(STBI_ONLY_ZLIB)+ #ifndef STBI_ONLY_JPEG+ #define STBI_NO_JPEG+ #endif+ #ifndef STBI_ONLY_PNG+ #define STBI_NO_PNG+ #endif+ #ifndef STBI_ONLY_BMP+ #define STBI_NO_BMP+ #endif+ #ifndef STBI_ONLY_PSD+ #define STBI_NO_PSD+ #endif+ #ifndef STBI_ONLY_TGA+ #define STBI_NO_TGA+ #endif+ #ifndef STBI_ONLY_GIF+ #define STBI_NO_GIF+ #endif+ #ifndef STBI_ONLY_HDR+ #define STBI_NO_HDR+ #endif+ #ifndef STBI_ONLY_PIC+ #define STBI_NO_PIC+ #endif+ #ifndef STBI_ONLY_PNM+ #define STBI_NO_PNM+ #endif+#endif++#if defined(STBI_NO_PNG) && !defined(STBI_SUPPORT_ZLIB) && !defined(STBI_NO_ZLIB)+#define STBI_NO_ZLIB+#endif+++#include <stdarg.h>+#include <stddef.h> // ptrdiff_t on osx+#include <stdlib.h>+#include <string.h>+#include <limits.h>++#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR)+#include <math.h> // ldexp, pow+#endif++#ifndef STBI_NO_STDIO+#include <stdio.h>+#endif++#ifndef STBI_ASSERT+#include <assert.h>+#define STBI_ASSERT(x) assert(x)+#endif++#ifdef __cplusplus+#define STBI_EXTERN extern "C"+#else+#define STBI_EXTERN extern+#endif+++#ifndef _MSC_VER+ #ifdef __cplusplus+ #define stbi_inline inline+ #else+ #define stbi_inline+ #endif+#else+ #define stbi_inline __forceinline+#endif++#ifndef STBI_NO_THREAD_LOCALS+ #if defined(__cplusplus) && __cplusplus >= 201103L+ #define STBI_THREAD_LOCAL thread_local+ #elif defined(__GNUC__) && __GNUC__ < 5+ #define STBI_THREAD_LOCAL __thread+ #elif defined(_MSC_VER)+ #define STBI_THREAD_LOCAL __declspec(thread)+ #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__)+ #define STBI_THREAD_LOCAL _Thread_local+ #endif++ #ifndef STBI_THREAD_LOCAL+ #if defined(__GNUC__)+ #define STBI_THREAD_LOCAL __thread+ #endif+ #endif+#endif++#if defined(_MSC_VER) || defined(__SYMBIAN32__)+typedef unsigned short stbi__uint16;+typedef signed short stbi__int16;+typedef unsigned int stbi__uint32;+typedef signed int stbi__int32;+#else+#include <stdint.h>+typedef uint16_t stbi__uint16;+typedef int16_t stbi__int16;+typedef uint32_t stbi__uint32;+typedef int32_t stbi__int32;+#endif++// should produce compiler error if size is wrong+typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1];++#ifdef _MSC_VER+#define STBI_NOTUSED(v) (void)(v)+#else+#define STBI_NOTUSED(v) (void)sizeof(v)+#endif++#ifdef _MSC_VER+#define STBI_HAS_LROTL+#endif++#ifdef STBI_HAS_LROTL+ #define stbi_lrot(x,y) _lrotl(x,y)+#else+ #define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (-(y) & 31)))+#endif++#if defined(STBI_MALLOC) && defined(STBI_FREE) && (defined(STBI_REALLOC) || defined(STBI_REALLOC_SIZED))+// ok+#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) && !defined(STBI_REALLOC_SIZED)+// ok+#else+#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC (or STBI_REALLOC_SIZED)."+#endif++#ifndef STBI_MALLOC+#define STBI_MALLOC(sz) malloc(sz)+#define STBI_REALLOC(p,newsz) realloc(p,newsz)+#define STBI_FREE(p) free(p)+#endif++#ifndef STBI_REALLOC_SIZED+#define STBI_REALLOC_SIZED(p,oldsz,newsz) STBI_REALLOC(p,newsz)+#endif++// x86/x64 detection+#if defined(__x86_64__) || defined(_M_X64)+#define STBI__X64_TARGET+#elif defined(__i386) || defined(_M_IX86)+#define STBI__X86_TARGET+#endif++#if defined(__GNUC__) && defined(STBI__X86_TARGET) && !defined(__SSE2__) && !defined(STBI_NO_SIMD)+// gcc doesn't support sse2 intrinsics unless you compile with -msse2,+// which in turn means it gets to use SSE2 everywhere. This is unfortunate,+// but previous attempts to provide the SSE2 functions with runtime+// detection caused numerous issues. The way architecture extensions are+// exposed in GCC/Clang is, sadly, not really suited for one-file libs.+// New behavior: if compiled with -msse2, we use SSE2 without any+// detection; if not, we don't use it at all.+#define STBI_NO_SIMD+#endif++#if defined(__MINGW32__) && defined(STBI__X86_TARGET) && !defined(STBI_MINGW_ENABLE_SSE2) && !defined(STBI_NO_SIMD)+// Note that __MINGW32__ doesn't actually mean 32-bit, so we have to avoid STBI__X64_TARGET+//+// 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the+// Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant.+// As a result, enabling SSE2 on 32-bit MinGW is dangerous when not+// simultaneously enabling "-mstackrealign".+//+// See https://github.com/nothings/stb/issues/81 for more information.+//+// So default to no SSE2 on 32-bit MinGW. If you've read this far and added+// -mstackrealign to your build settings, feel free to #define STBI_MINGW_ENABLE_SSE2.+#define STBI_NO_SIMD+#endif++#if !defined(STBI_NO_SIMD) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET))+#define STBI_SSE2+#include <emmintrin.h>++#ifdef _MSC_VER++#if _MSC_VER >= 1400 // not VC6+#include <intrin.h> // __cpuid+static int stbi__cpuid3(void)+{+ int info[4];+ __cpuid(info,1);+ return info[3];+}+#else+static int stbi__cpuid3(void)+{+ int res;+ __asm {+ mov eax,1+ cpuid+ mov res,edx+ }+ return res;+}+#endif++#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name++#if !defined(STBI_NO_JPEG) && defined(STBI_SSE2)+static int stbi__sse2_available(void)+{+ int info3 = stbi__cpuid3();+ return ((info3 >> 26) & 1) != 0;+}+#endif++#else // assume GCC-style if not VC+++#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16)))++#if !defined(STBI_NO_JPEG) && defined(STBI_SSE2)+static int stbi__sse2_available(void)+{+ // If we're even attempting to compile this on GCC/Clang, that means+ // -msse2 is on, which means the compiler is allowed to use SSE2+ // instructions at will, and so are we.+ return 1;+}+#endif++#endif+#endif++// ARM NEON+#if defined(STBI_NO_SIMD) && defined(STBI_NEON)+#undef STBI_NEON+#endif++#ifdef STBI_NEON+#include <arm_neon.h>+#ifdef _MSC_VER+#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name+#else+#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16)))+#endif+#endif++#ifndef STBI_SIMD_ALIGN+#define STBI_SIMD_ALIGN(type, name) type name+#endif++#ifndef STBI_MAX_DIMENSIONS+#define STBI_MAX_DIMENSIONS (1 << 24)+#endif++///////////////////////////////////////////////+//+// stbi__context struct and start_xxx functions++// stbi__context structure is our basic context used by all images, so it+// contains all the IO context, plus some basic image information+typedef struct+{+ stbi__uint32 img_x, img_y;+ int img_n, img_out_n;++ stbi_io_callbacks io;+ void *io_user_data;++ int read_from_callbacks;+ int buflen;+ stbi_uc buffer_start[128];+ int callback_already_read;++ stbi_uc *img_buffer, *img_buffer_end;+ stbi_uc *img_buffer_original, *img_buffer_original_end;+} stbi__context;+++static void stbi__refill_buffer(stbi__context *s);++// initialize a memory-decode context+static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len)+{+ s->io.read = NULL;+ s->read_from_callbacks = 0;+ s->callback_already_read = 0;+ s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer;+ s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len;+}++// initialize a callback-based context+static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *user)+{+ s->io = *c;+ s->io_user_data = user;+ s->buflen = sizeof(s->buffer_start);+ s->read_from_callbacks = 1;+ s->callback_already_read = 0;+ s->img_buffer = s->img_buffer_original = s->buffer_start;+ stbi__refill_buffer(s);+ s->img_buffer_original_end = s->img_buffer_end;+}++#ifndef STBI_NO_STDIO++static int stbi__stdio_read(void *user, char *data, int size)+{+ return (int) fread(data,1,size,(FILE*) user);+}++static void stbi__stdio_skip(void *user, int n)+{+ int ch;+ fseek((FILE*) user, n, SEEK_CUR);+ ch = fgetc((FILE*) user); /* have to read a byte to reset feof()'s flag */+ if (ch != EOF) {+ ungetc(ch, (FILE *) user); /* push byte back onto stream if valid. */+ }+}++static int stbi__stdio_eof(void *user)+{+ return feof((FILE*) user) || ferror((FILE *) user);+}++static stbi_io_callbacks stbi__stdio_callbacks =+{+ stbi__stdio_read,+ stbi__stdio_skip,+ stbi__stdio_eof,+};++static void stbi__start_file(stbi__context *s, FILE *f)+{+ stbi__start_callbacks(s, &stbi__stdio_callbacks, (void *) f);+}++//static void stop_file(stbi__context *s) { }++#endif // !STBI_NO_STDIO++static void stbi__rewind(stbi__context *s)+{+ // conceptually rewind SHOULD rewind to the beginning of the stream,+ // but we just rewind to the beginning of the initial buffer, because+ // we only use it after doing 'test', which only ever looks at at most 92 bytes+ s->img_buffer = s->img_buffer_original;+ s->img_buffer_end = s->img_buffer_original_end;+}++enum+{+ STBI_ORDER_RGB,+ STBI_ORDER_BGR+};++typedef struct+{+ int bits_per_channel;+ int num_channels;+ int channel_order;+} stbi__result_info;++#ifndef STBI_NO_JPEG+static int stbi__jpeg_test(stbi__context *s);+static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);+static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp);+#endif++#ifndef STBI_NO_PNG+static int stbi__png_test(stbi__context *s);+static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);+static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp);+static int stbi__png_is16(stbi__context *s);+#endif++#ifndef STBI_NO_BMP+static int stbi__bmp_test(stbi__context *s);+static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);+static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp);+#endif++#ifndef STBI_NO_TGA+static int stbi__tga_test(stbi__context *s);+static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);+static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp);+#endif++#ifndef STBI_NO_PSD+static int stbi__psd_test(stbi__context *s);+static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc);+static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp);+static int stbi__psd_is16(stbi__context *s);+#endif++#ifndef STBI_NO_HDR+static int stbi__hdr_test(stbi__context *s);+static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);+static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp);+#endif++#ifndef STBI_NO_PIC+static int stbi__pic_test(stbi__context *s);+static void *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);+static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp);+#endif++#ifndef STBI_NO_GIF+static int stbi__gif_test(stbi__context *s);+static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);+static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp);+static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp);+#endif++#ifndef STBI_NO_PNM+static int stbi__pnm_test(stbi__context *s);+static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);+static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp);+static int stbi__pnm_is16(stbi__context *s);+#endif++static+#ifdef STBI_THREAD_LOCAL+STBI_THREAD_LOCAL+#endif+const char *stbi__g_failure_reason;++STBIDEF const char *stbi_failure_reason(void)+{+ return stbi__g_failure_reason;+}++#ifndef STBI_NO_FAILURE_STRINGS+static int stbi__err(const char *str)+{+ stbi__g_failure_reason = str;+ return 0;+}+#endif++static void *stbi__malloc(size_t size)+{+ return STBI_MALLOC(size);+}++// stb_image uses ints pervasively, including for offset calculations.+// therefore the largest decoded image size we can support with the+// current code, even on 64-bit targets, is INT_MAX. this is not a+// significant limitation for the intended use case.+//+// we do, however, need to make sure our size calculations don't+// overflow. hence a few helper functions for size calculations that+// multiply integers together, making sure that they're non-negative+// and no overflow occurs.++// return 1 if the sum is valid, 0 on overflow.+// negative terms are considered invalid.+static int stbi__addsizes_valid(int a, int b)+{+ if (b < 0) return 0;+ // now 0 <= b <= INT_MAX, hence also+ // 0 <= INT_MAX - b <= INTMAX.+ // And "a + b <= INT_MAX" (which might overflow) is the+ // same as a <= INT_MAX - b (no overflow)+ return a <= INT_MAX - b;+}++// returns 1 if the product is valid, 0 on overflow.+// negative factors are considered invalid.+static int stbi__mul2sizes_valid(int a, int b)+{+ if (a < 0 || b < 0) return 0;+ if (b == 0) return 1; // mul-by-0 is always safe+ // portable way to check for no overflows in a*b+ return a <= INT_MAX/b;+}++#if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR)+// returns 1 if "a*b + add" has no negative terms/factors and doesn't overflow+static int stbi__mad2sizes_valid(int a, int b, int add)+{+ return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add);+}+#endif++// returns 1 if "a*b*c + add" has no negative terms/factors and doesn't overflow+static int stbi__mad3sizes_valid(int a, int b, int c, int add)+{+ return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) &&+ stbi__addsizes_valid(a*b*c, add);+}++// returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow+#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) || !defined(STBI_NO_PNM)+static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add)+{+ return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) &&+ stbi__mul2sizes_valid(a*b*c, d) && stbi__addsizes_valid(a*b*c*d, add);+}+#endif++#if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR)+// mallocs with size overflow checking+static void *stbi__malloc_mad2(int a, int b, int add)+{+ if (!stbi__mad2sizes_valid(a, b, add)) return NULL;+ return stbi__malloc(a*b + add);+}+#endif++static void *stbi__malloc_mad3(int a, int b, int c, int add)+{+ if (!stbi__mad3sizes_valid(a, b, c, add)) return NULL;+ return stbi__malloc(a*b*c + add);+}++#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) || !defined(STBI_NO_PNM)+static void *stbi__malloc_mad4(int a, int b, int c, int d, int add)+{+ if (!stbi__mad4sizes_valid(a, b, c, d, add)) return NULL;+ return stbi__malloc(a*b*c*d + add);+}+#endif++// returns 1 if the sum of two signed ints is valid (between -2^31 and 2^31-1 inclusive), 0 on overflow.+static int stbi__addints_valid(int a, int b)+{+ if ((a >= 0) != (b >= 0)) return 1; // a and b have different signs, so no overflow+ if (a < 0 && b < 0) return a >= INT_MIN - b; // same as a + b >= INT_MIN; INT_MIN - b cannot overflow since b < 0.+ return a <= INT_MAX - b;+}++// returns 1 if the product of two ints fits in a signed short, 0 on overflow.+static int stbi__mul2shorts_valid(int a, int b)+{+ if (b == 0 || b == -1) return 1; // multiplication by 0 is always 0; check for -1 so SHRT_MIN/b doesn't overflow+ if ((a >= 0) == (b >= 0)) return a <= SHRT_MAX/b; // product is positive, so similar to mul2sizes_valid+ if (b < 0) return a <= SHRT_MIN / b; // same as a * b >= SHRT_MIN+ return a >= SHRT_MIN / b;+}++// stbi__err - error+// stbi__errpf - error returning pointer to float+// stbi__errpuc - error returning pointer to unsigned char++#ifdef STBI_NO_FAILURE_STRINGS+ #define stbi__err(x,y) 0+#elif defined(STBI_FAILURE_USERMSG)+ #define stbi__err(x,y) stbi__err(y)+#else+ #define stbi__err(x,y) stbi__err(x)+#endif++#define stbi__errpf(x,y) ((float *)(size_t) (stbi__err(x,y)?NULL:NULL))+#define stbi__errpuc(x,y) ((unsigned char *)(size_t) (stbi__err(x,y)?NULL:NULL))++STBIDEF void stbi_image_free(void *retval_from_stbi_load)+{+ STBI_FREE(retval_from_stbi_load);+}++#ifndef STBI_NO_LINEAR+static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp);+#endif++#ifndef STBI_NO_HDR+static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp);+#endif++static int stbi__vertically_flip_on_load_global = 0;++STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip)+{+ stbi__vertically_flip_on_load_global = flag_true_if_should_flip;+}++#ifndef STBI_THREAD_LOCAL+#define stbi__vertically_flip_on_load stbi__vertically_flip_on_load_global+#else+static STBI_THREAD_LOCAL int stbi__vertically_flip_on_load_local, stbi__vertically_flip_on_load_set;++STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip)+{+ stbi__vertically_flip_on_load_local = flag_true_if_should_flip;+ stbi__vertically_flip_on_load_set = 1;+}++#define stbi__vertically_flip_on_load (stbi__vertically_flip_on_load_set \+ ? stbi__vertically_flip_on_load_local \+ : stbi__vertically_flip_on_load_global)+#endif // STBI_THREAD_LOCAL++static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc)+{+ memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields+ ri->bits_per_channel = 8; // default is 8 so most paths don't have to be changed+ ri->channel_order = STBI_ORDER_RGB; // all current input & output are this, but this is here so we can add BGR order+ ri->num_channels = 0;++ // test the formats with a very explicit header first (at least a FOURCC+ // or distinctive magic number first)+ #ifndef STBI_NO_PNG+ if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp, ri);+ #endif+ #ifndef STBI_NO_BMP+ if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp, ri);+ #endif+ #ifndef STBI_NO_GIF+ if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp, ri);+ #endif+ #ifndef STBI_NO_PSD+ if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp, ri, bpc);+ #else+ STBI_NOTUSED(bpc);+ #endif+ #ifndef STBI_NO_PIC+ if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp, ri);+ #endif++ // then the formats that can end up attempting to load with just 1 or 2+ // bytes matching expectations; these are prone to false positives, so+ // try them later+ #ifndef STBI_NO_JPEG+ if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp, ri);+ #endif+ #ifndef STBI_NO_PNM+ if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp, ri);+ #endif++ #ifndef STBI_NO_HDR+ if (stbi__hdr_test(s)) {+ float *hdr = stbi__hdr_load(s, x,y,comp,req_comp, ri);+ return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp);+ }+ #endif++ #ifndef STBI_NO_TGA+ // test tga last because it's a crappy test!+ if (stbi__tga_test(s))+ return stbi__tga_load(s,x,y,comp,req_comp, ri);+ #endif++ return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt");+}++static stbi_uc *stbi__convert_16_to_8(stbi__uint16 *orig, int w, int h, int channels)+{+ int i;+ int img_len = w * h * channels;+ stbi_uc *reduced;++ reduced = (stbi_uc *) stbi__malloc(img_len);+ if (reduced == NULL) return stbi__errpuc("outofmem", "Out of memory");++ for (i = 0; i < img_len; ++i)+ reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is sufficient approx of 16->8 bit scaling++ STBI_FREE(orig);+ return reduced;+}++static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int channels)+{+ int i;+ int img_len = w * h * channels;+ stbi__uint16 *enlarged;++ enlarged = (stbi__uint16 *) stbi__malloc(img_len*2);+ if (enlarged == NULL) return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory");++ for (i = 0; i < img_len; ++i)+ enlarged[i] = (stbi__uint16)((orig[i] << 8) + orig[i]); // replicate to high and low byte, maps 0->0, 255->0xffff++ STBI_FREE(orig);+ return enlarged;+}++static void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel)+{+ int row;+ size_t bytes_per_row = (size_t)w * bytes_per_pixel;+ stbi_uc temp[2048];+ stbi_uc *bytes = (stbi_uc *)image;++ for (row = 0; row < (h>>1); row++) {+ stbi_uc *row0 = bytes + row*bytes_per_row;+ stbi_uc *row1 = bytes + (h - row - 1)*bytes_per_row;+ // swap row0 with row1+ size_t bytes_left = bytes_per_row;+ while (bytes_left) {+ size_t bytes_copy = (bytes_left < sizeof(temp)) ? bytes_left : sizeof(temp);+ memcpy(temp, row0, bytes_copy);+ memcpy(row0, row1, bytes_copy);+ memcpy(row1, temp, bytes_copy);+ row0 += bytes_copy;+ row1 += bytes_copy;+ bytes_left -= bytes_copy;+ }+ }+}++#ifndef STBI_NO_GIF+static void stbi__vertical_flip_slices(void *image, int w, int h, int z, int bytes_per_pixel)+{+ int slice;+ int slice_size = w * h * bytes_per_pixel;++ stbi_uc *bytes = (stbi_uc *)image;+ for (slice = 0; slice < z; ++slice) {+ stbi__vertical_flip(bytes, w, h, bytes_per_pixel);+ bytes += slice_size;+ }+}+#endif++static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp)+{+ stbi__result_info ri;+ void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 8);++ if (result == NULL)+ return NULL;++ // it is the responsibility of the loaders to make sure we get either 8 or 16 bit.+ STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16);++ if (ri.bits_per_channel != 8) {+ result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp);+ ri.bits_per_channel = 8;+ }++ // @TODO: move stbi__convert_format to here++ if (stbi__vertically_flip_on_load) {+ int channels = req_comp ? req_comp : *comp;+ stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi_uc));+ }++ return (unsigned char *) result;+}++static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, int *y, int *comp, int req_comp)+{+ stbi__result_info ri;+ void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 16);++ if (result == NULL)+ return NULL;++ // it is the responsibility of the loaders to make sure we get either 8 or 16 bit.+ STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16);++ if (ri.bits_per_channel != 16) {+ result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp);+ ri.bits_per_channel = 16;+ }++ // @TODO: move stbi__convert_format16 to here+ // @TODO: special case RGB-to-Y (and RGBA-to-YA) for 8-bit-to-16-bit case to keep more precision++ if (stbi__vertically_flip_on_load) {+ int channels = req_comp ? req_comp : *comp;+ stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi__uint16));+ }++ return (stbi__uint16 *) result;+}++#if !defined(STBI_NO_HDR) && !defined(STBI_NO_LINEAR)+static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp)+{+ if (stbi__vertically_flip_on_load && result != NULL) {+ int channels = req_comp ? req_comp : *comp;+ stbi__vertical_flip(result, *x, *y, channels * sizeof(float));+ }+}+#endif++#ifndef STBI_NO_STDIO++#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8)+STBI_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide);+STBI_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default);+#endif++#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8)+STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input)+{+ return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL);+}+#endif++static FILE *stbi__fopen(char const *filename, char const *mode)+{+ FILE *f;+#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8)+ wchar_t wMode[64];+ wchar_t wFilename[1024];+ if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename)))+ return 0;++ if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode)))+ return 0;++#if defined(_MSC_VER) && _MSC_VER >= 1400+ if (0 != _wfopen_s(&f, wFilename, wMode))+ f = 0;+#else+ f = _wfopen(wFilename, wMode);+#endif++#elif defined(_MSC_VER) && _MSC_VER >= 1400+ if (0 != fopen_s(&f, filename, mode))+ f=0;+#else+ f = fopen(filename, mode);+#endif+ return f;+}+++STBIDEF stbi_uc *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp)+{+ FILE *f = stbi__fopen(filename, "rb");+ unsigned char *result;+ if (!f) return stbi__errpuc("can't fopen", "Unable to open file");+ result = stbi_load_from_file(f,x,y,comp,req_comp);+ fclose(f);+ return result;+}++STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp)+{+ unsigned char *result;+ stbi__context s;+ stbi__start_file(&s,f);+ result = stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);+ if (result) {+ // need to 'unget' all the characters in the IO buffer+ fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR);+ }+ return result;+}++STBIDEF stbi__uint16 *stbi_load_from_file_16(FILE *f, int *x, int *y, int *comp, int req_comp)+{+ stbi__uint16 *result;+ stbi__context s;+ stbi__start_file(&s,f);+ result = stbi__load_and_postprocess_16bit(&s,x,y,comp,req_comp);+ if (result) {+ // need to 'unget' all the characters in the IO buffer+ fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR);+ }+ return result;+}++STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *comp, int req_comp)+{+ FILE *f = stbi__fopen(filename, "rb");+ stbi__uint16 *result;+ if (!f) return (stbi_us *) stbi__errpuc("can't fopen", "Unable to open file");+ result = stbi_load_from_file_16(f,x,y,comp,req_comp);+ fclose(f);+ return result;+}+++#endif //!STBI_NO_STDIO++STBIDEF stbi_us *stbi_load_16_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels)+{+ stbi__context s;+ stbi__start_mem(&s,buffer,len);+ return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels);+}++STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels)+{+ stbi__context s;+ stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user);+ return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels);+}++STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)+{+ stbi__context s;+ stbi__start_mem(&s,buffer,len);+ return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);+}++STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp)+{+ stbi__context s;+ stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);+ return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);+}++#ifndef STBI_NO_GIF+STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp)+{+ unsigned char *result;+ stbi__context s;+ stbi__start_mem(&s,buffer,len);++ result = (unsigned char*) stbi__load_gif_main(&s, delays, x, y, z, comp, req_comp);+ if (stbi__vertically_flip_on_load) {+ stbi__vertical_flip_slices( result, *x, *y, *z, *comp );+ }++ return result;+}+#endif++#ifndef STBI_NO_LINEAR+static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp)+{+ unsigned char *data;+ #ifndef STBI_NO_HDR+ if (stbi__hdr_test(s)) {+ stbi__result_info ri;+ float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp, &ri);+ if (hdr_data)+ stbi__float_postprocess(hdr_data,x,y,comp,req_comp);+ return hdr_data;+ }+ #endif+ data = stbi__load_and_postprocess_8bit(s, x, y, comp, req_comp);+ if (data)+ return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp);+ return stbi__errpf("unknown image type", "Image not of any known type, or corrupt");+}++STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)+{+ stbi__context s;+ stbi__start_mem(&s,buffer,len);+ return stbi__loadf_main(&s,x,y,comp,req_comp);+}++STBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp)+{+ stbi__context s;+ stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);+ return stbi__loadf_main(&s,x,y,comp,req_comp);+}++#ifndef STBI_NO_STDIO+STBIDEF float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp)+{+ float *result;+ FILE *f = stbi__fopen(filename, "rb");+ if (!f) return stbi__errpf("can't fopen", "Unable to open file");+ result = stbi_loadf_from_file(f,x,y,comp,req_comp);+ fclose(f);+ return result;+}++STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp)+{+ stbi__context s;+ stbi__start_file(&s,f);+ return stbi__loadf_main(&s,x,y,comp,req_comp);+}+#endif // !STBI_NO_STDIO++#endif // !STBI_NO_LINEAR++// these is-hdr-or-not is defined independent of whether STBI_NO_LINEAR is+// defined, for API simplicity; if STBI_NO_LINEAR is defined, it always+// reports false!++STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len)+{+ #ifndef STBI_NO_HDR+ stbi__context s;+ stbi__start_mem(&s,buffer,len);+ return stbi__hdr_test(&s);+ #else+ STBI_NOTUSED(buffer);+ STBI_NOTUSED(len);+ return 0;+ #endif+}++#ifndef STBI_NO_STDIO+STBIDEF int stbi_is_hdr (char const *filename)+{+ FILE *f = stbi__fopen(filename, "rb");+ int result=0;+ if (f) {+ result = stbi_is_hdr_from_file(f);+ fclose(f);+ }+ return result;+}++STBIDEF int stbi_is_hdr_from_file(FILE *f)+{+ #ifndef STBI_NO_HDR+ long pos = ftell(f);+ int res;+ stbi__context s;+ stbi__start_file(&s,f);+ res = stbi__hdr_test(&s);+ fseek(f, pos, SEEK_SET);+ return res;+ #else+ STBI_NOTUSED(f);+ return 0;+ #endif+}+#endif // !STBI_NO_STDIO++STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user)+{+ #ifndef STBI_NO_HDR+ stbi__context s;+ stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);+ return stbi__hdr_test(&s);+ #else+ STBI_NOTUSED(clbk);+ STBI_NOTUSED(user);+ return 0;+ #endif+}++#ifndef STBI_NO_LINEAR+static float stbi__l2h_gamma=2.2f, stbi__l2h_scale=1.0f;++STBIDEF void stbi_ldr_to_hdr_gamma(float gamma) { stbi__l2h_gamma = gamma; }+STBIDEF void stbi_ldr_to_hdr_scale(float scale) { stbi__l2h_scale = scale; }+#endif++static float stbi__h2l_gamma_i=1.0f/2.2f, stbi__h2l_scale_i=1.0f;++STBIDEF void stbi_hdr_to_ldr_gamma(float gamma) { stbi__h2l_gamma_i = 1/gamma; }+STBIDEF void stbi_hdr_to_ldr_scale(float scale) { stbi__h2l_scale_i = 1/scale; }+++//////////////////////////////////////////////////////////////////////////////+//+// Common code used by all image loaders+//++enum+{+ STBI__SCAN_load=0,+ STBI__SCAN_type,+ STBI__SCAN_header+};++static void stbi__refill_buffer(stbi__context *s)+{+ int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen);+ s->callback_already_read += (int) (s->img_buffer - s->img_buffer_original);+ if (n == 0) {+ // at end of file, treat same as if from memory, but need to handle case+ // where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file+ s->read_from_callbacks = 0;+ s->img_buffer = s->buffer_start;+ s->img_buffer_end = s->buffer_start+1;+ *s->img_buffer = 0;+ } else {+ s->img_buffer = s->buffer_start;+ s->img_buffer_end = s->buffer_start + n;+ }+}++stbi_inline static stbi_uc stbi__get8(stbi__context *s)+{+ if (s->img_buffer < s->img_buffer_end)+ return *s->img_buffer++;+ if (s->read_from_callbacks) {+ stbi__refill_buffer(s);+ return *s->img_buffer++;+ }+ return 0;+}++#if defined(STBI_NO_JPEG) && defined(STBI_NO_HDR) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM)+// nothing+#else+stbi_inline static int stbi__at_eof(stbi__context *s)+{+ if (s->io.read) {+ if (!(s->io.eof)(s->io_user_data)) return 0;+ // if feof() is true, check if buffer = end+ // special case: we've only got the special 0 character at the end+ if (s->read_from_callbacks == 0) return 1;+ }++ return s->img_buffer >= s->img_buffer_end;+}+#endif++#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC)+// nothing+#else+static void stbi__skip(stbi__context *s, int n)+{+ if (n == 0) return; // already there!+ if (n < 0) {+ s->img_buffer = s->img_buffer_end;+ return;+ }+ if (s->io.read) {+ int blen = (int) (s->img_buffer_end - s->img_buffer);+ if (blen < n) {+ s->img_buffer = s->img_buffer_end;+ (s->io.skip)(s->io_user_data, n - blen);+ return;+ }+ }+ s->img_buffer += n;+}+#endif++#if defined(STBI_NO_PNG) && defined(STBI_NO_TGA) && defined(STBI_NO_HDR) && defined(STBI_NO_PNM)+// nothing+#else+static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n)+{+ if (s->io.read) {+ int blen = (int) (s->img_buffer_end - s->img_buffer);+ if (blen < n) {+ int res, count;++ memcpy(buffer, s->img_buffer, blen);++ count = (s->io.read)(s->io_user_data, (char*) buffer + blen, n - blen);+ res = (count == (n-blen));+ s->img_buffer = s->img_buffer_end;+ return res;+ }+ }++ if (s->img_buffer+n <= s->img_buffer_end) {+ memcpy(buffer, s->img_buffer, n);+ s->img_buffer += n;+ return 1;+ } else+ return 0;+}+#endif++#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC)+// nothing+#else+static int stbi__get16be(stbi__context *s)+{+ int z = stbi__get8(s);+ return (z << 8) + stbi__get8(s);+}+#endif++#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC)+// nothing+#else+static stbi__uint32 stbi__get32be(stbi__context *s)+{+ stbi__uint32 z = stbi__get16be(s);+ return (z << 16) + stbi__get16be(s);+}+#endif++#if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF)+// nothing+#else+static int stbi__get16le(stbi__context *s)+{+ int z = stbi__get8(s);+ return z + (stbi__get8(s) << 8);+}+#endif++#ifndef STBI_NO_BMP+static stbi__uint32 stbi__get32le(stbi__context *s)+{+ stbi__uint32 z = stbi__get16le(s);+ z += (stbi__uint32)stbi__get16le(s) << 16;+ return z;+}+#endif++#define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings++#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM)+// nothing+#else+//////////////////////////////////////////////////////////////////////////////+//+// generic converter from built-in img_n to req_comp+// individual types do this automatically as much as possible (e.g. jpeg+// does all cases internally since it needs to colorspace convert anyway,+// and it never has alpha, so very few cases ). png can automatically+// interleave an alpha=255 channel, but falls back to this for other cases+//+// assume data buffer is malloced, so malloc a new one and free that one+// only failure mode is malloc failing++static stbi_uc stbi__compute_y(int r, int g, int b)+{+ return (stbi_uc) (((r*77) + (g*150) + (29*b)) >> 8);+}+#endif++#if defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM)+// nothing+#else+static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y)+{+ int i,j;+ unsigned char *good;++ if (req_comp == img_n) return data;+ STBI_ASSERT(req_comp >= 1 && req_comp <= 4);++ good = (unsigned char *) stbi__malloc_mad3(req_comp, x, y, 0);+ if (good == NULL) {+ STBI_FREE(data);+ return stbi__errpuc("outofmem", "Out of memory");+ }++ for (j=0; j < (int) y; ++j) {+ unsigned char *src = data + j * x * img_n ;+ unsigned char *dest = good + j * x * req_comp;++ #define STBI__COMBO(a,b) ((a)*8+(b))+ #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b)+ // convert source image with img_n components to one with req_comp components;+ // avoid switch per pixel, so use switch per scanline and massive macros+ switch (STBI__COMBO(img_n, req_comp)) {+ STBI__CASE(1,2) { dest[0]=src[0]; dest[1]=255; } break;+ STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break;+ STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=255; } break;+ STBI__CASE(2,1) { dest[0]=src[0]; } break;+ STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break;+ STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=src[1]; } break;+ STBI__CASE(3,4) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];dest[3]=255; } break;+ STBI__CASE(3,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break;+ STBI__CASE(3,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = 255; } break;+ STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break;+ STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = src[3]; } break;+ STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break;+ default: STBI_ASSERT(0); STBI_FREE(data); STBI_FREE(good); return stbi__errpuc("unsupported", "Unsupported format conversion");+ }+ #undef STBI__CASE+ }++ STBI_FREE(data);+ return good;+}+#endif++#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD)+// nothing+#else+static stbi__uint16 stbi__compute_y_16(int r, int g, int b)+{+ return (stbi__uint16) (((r*77) + (g*150) + (29*b)) >> 8);+}+#endif++#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD)+// nothing+#else+static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y)+{+ int i,j;+ stbi__uint16 *good;++ if (req_comp == img_n) return data;+ STBI_ASSERT(req_comp >= 1 && req_comp <= 4);++ good = (stbi__uint16 *) stbi__malloc(req_comp * x * y * 2);+ if (good == NULL) {+ STBI_FREE(data);+ return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory");+ }++ for (j=0; j < (int) y; ++j) {+ stbi__uint16 *src = data + j * x * img_n ;+ stbi__uint16 *dest = good + j * x * req_comp;++ #define STBI__COMBO(a,b) ((a)*8+(b))+ #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b)+ // convert source image with img_n components to one with req_comp components;+ // avoid switch per pixel, so use switch per scanline and massive macros+ switch (STBI__COMBO(img_n, req_comp)) {+ STBI__CASE(1,2) { dest[0]=src[0]; dest[1]=0xffff; } break;+ STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break;+ STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=0xffff; } break;+ STBI__CASE(2,1) { dest[0]=src[0]; } break;+ STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break;+ STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=src[1]; } break;+ STBI__CASE(3,4) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];dest[3]=0xffff; } break;+ STBI__CASE(3,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break;+ STBI__CASE(3,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = 0xffff; } break;+ STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break;+ STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = src[3]; } break;+ STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break;+ default: STBI_ASSERT(0); STBI_FREE(data); STBI_FREE(good); return (stbi__uint16*) stbi__errpuc("unsupported", "Unsupported format conversion");+ }+ #undef STBI__CASE+ }++ STBI_FREE(data);+ return good;+}+#endif++#ifndef STBI_NO_LINEAR+static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp)+{+ int i,k,n;+ float *output;+ if (!data) return NULL;+ output = (float *) stbi__malloc_mad4(x, y, comp, sizeof(float), 0);+ if (output == NULL) { STBI_FREE(data); return stbi__errpf("outofmem", "Out of memory"); }+ // compute number of non-alpha components+ if (comp & 1) n = comp; else n = comp-1;+ for (i=0; i < x*y; ++i) {+ for (k=0; k < n; ++k) {+ output[i*comp + k] = (float) (pow(data[i*comp+k]/255.0f, stbi__l2h_gamma) * stbi__l2h_scale);+ }+ }+ if (n < comp) {+ for (i=0; i < x*y; ++i) {+ output[i*comp + n] = data[i*comp + n]/255.0f;+ }+ }+ STBI_FREE(data);+ return output;+}+#endif++#ifndef STBI_NO_HDR+#define stbi__float2int(x) ((int) (x))+static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp)+{+ int i,k,n;+ stbi_uc *output;+ if (!data) return NULL;+ output = (stbi_uc *) stbi__malloc_mad3(x, y, comp, 0);+ if (output == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); }+ // compute number of non-alpha components+ if (comp & 1) n = comp; else n = comp-1;+ for (i=0; i < x*y; ++i) {+ for (k=0; k < n; ++k) {+ float z = (float) pow(data[i*comp+k]*stbi__h2l_scale_i, stbi__h2l_gamma_i) * 255 + 0.5f;+ if (z < 0) z = 0;+ if (z > 255) z = 255;+ output[i*comp + k] = (stbi_uc) stbi__float2int(z);+ }+ if (k < comp) {+ float z = data[i*comp+k] * 255 + 0.5f;+ if (z < 0) z = 0;+ if (z > 255) z = 255;+ output[i*comp + k] = (stbi_uc) stbi__float2int(z);+ }+ }+ STBI_FREE(data);+ return output;+}+#endif++//////////////////////////////////////////////////////////////////////////////+//+// "baseline" JPEG/JFIF decoder+//+// simple implementation+// - doesn't support delayed output of y-dimension+// - simple interface (only one output format: 8-bit interleaved RGB)+// - doesn't try to recover corrupt jpegs+// - doesn't allow partial loading, loading multiple at once+// - still fast on x86 (copying globals into locals doesn't help x86)+// - allocates lots of intermediate memory (full size of all components)+// - non-interleaved case requires this anyway+// - allows good upsampling (see next)+// high-quality+// - upsampled channels are bilinearly interpolated, even across blocks+// - quality integer IDCT derived from IJG's 'slow'+// performance+// - fast huffman; reasonable integer IDCT+// - some SIMD kernels for common paths on targets with SSE2/NEON+// - uses a lot of intermediate memory, could cache poorly++#ifndef STBI_NO_JPEG++// huffman decoding acceleration+#define FAST_BITS 9 // larger handles more cases; smaller stomps less cache++typedef struct+{+ stbi_uc fast[1 << FAST_BITS];+ // weirdly, repacking this into AoS is a 10% speed loss, instead of a win+ stbi__uint16 code[256];+ stbi_uc values[256];+ stbi_uc size[257];+ unsigned int maxcode[18];+ int delta[17]; // old 'firstsymbol' - old 'firstcode'+} stbi__huffman;++typedef struct+{+ stbi__context *s;+ stbi__huffman huff_dc[4];+ stbi__huffman huff_ac[4];+ stbi__uint16 dequant[4][64];+ stbi__int16 fast_ac[4][1 << FAST_BITS];++// sizes for components, interleaved MCUs+ int img_h_max, img_v_max;+ int img_mcu_x, img_mcu_y;+ int img_mcu_w, img_mcu_h;++// definition of jpeg image component+ struct+ {+ int id;+ int h,v;+ int tq;+ int hd,ha;+ int dc_pred;++ int x,y,w2,h2;+ stbi_uc *data;+ void *raw_data, *raw_coeff;+ stbi_uc *linebuf;+ short *coeff; // progressive only+ int coeff_w, coeff_h; // number of 8x8 coefficient blocks+ } img_comp[4];++ stbi__uint32 code_buffer; // jpeg entropy-coded buffer+ int code_bits; // number of valid bits+ unsigned char marker; // marker seen while filling entropy buffer+ int nomore; // flag if we saw a marker so must stop++ int progressive;+ int spec_start;+ int spec_end;+ int succ_high;+ int succ_low;+ int eob_run;+ int jfif;+ int app14_color_transform; // Adobe APP14 tag+ int rgb;++ int scan_n, order[4];+ int restart_interval, todo;++// kernels+ void (*idct_block_kernel)(stbi_uc *out, int out_stride, short data[64]);+ void (*YCbCr_to_RGB_kernel)(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step);+ stbi_uc *(*resample_row_hv_2_kernel)(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs);+} stbi__jpeg;++static int stbi__build_huffman(stbi__huffman *h, int *count)+{+ int i,j,k=0;+ unsigned int code;+ // build size list for each symbol (from JPEG spec)+ for (i=0; i < 16; ++i) {+ for (j=0; j < count[i]; ++j) {+ h->size[k++] = (stbi_uc) (i+1);+ if(k >= 257) return stbi__err("bad size list","Corrupt JPEG");+ }+ }+ h->size[k] = 0;++ // compute actual symbols (from jpeg spec)+ code = 0;+ k = 0;+ for(j=1; j <= 16; ++j) {+ // compute delta to add to code to compute symbol id+ h->delta[j] = k - code;+ if (h->size[k] == j) {+ while (h->size[k] == j)+ h->code[k++] = (stbi__uint16) (code++);+ if (code-1 >= (1u << j)) return stbi__err("bad code lengths","Corrupt JPEG");+ }+ // compute largest code + 1 for this size, preshifted as needed later+ h->maxcode[j] = code << (16-j);+ code <<= 1;+ }+ h->maxcode[j] = 0xffffffff;++ // build non-spec acceleration table; 255 is flag for not-accelerated+ memset(h->fast, 255, 1 << FAST_BITS);+ for (i=0; i < k; ++i) {+ int s = h->size[i];+ if (s <= FAST_BITS) {+ int c = h->code[i] << (FAST_BITS-s);+ int m = 1 << (FAST_BITS-s);+ for (j=0; j < m; ++j) {+ h->fast[c+j] = (stbi_uc) i;+ }+ }+ }+ return 1;+}++// build a table that decodes both magnitude and value of small ACs in+// one go.+static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h)+{+ int i;+ for (i=0; i < (1 << FAST_BITS); ++i) {+ stbi_uc fast = h->fast[i];+ fast_ac[i] = 0;+ if (fast < 255) {+ int rs = h->values[fast];+ int run = (rs >> 4) & 15;+ int magbits = rs & 15;+ int len = h->size[fast];++ if (magbits && len + magbits <= FAST_BITS) {+ // magnitude code followed by receive_extend code+ int k = ((i << len) & ((1 << FAST_BITS) - 1)) >> (FAST_BITS - magbits);+ int m = 1 << (magbits - 1);+ if (k < m) k += (~0U << magbits) + 1;+ // if the result is small enough, we can fit it in fast_ac table+ if (k >= -128 && k <= 127)+ fast_ac[i] = (stbi__int16) ((k * 256) + (run * 16) + (len + magbits));+ }+ }+ }+}++static void stbi__grow_buffer_unsafe(stbi__jpeg *j)+{+ do {+ unsigned int b = j->nomore ? 0 : stbi__get8(j->s);+ if (b == 0xff) {+ int c = stbi__get8(j->s);+ while (c == 0xff) c = stbi__get8(j->s); // consume fill bytes+ if (c != 0) {+ j->marker = (unsigned char) c;+ j->nomore = 1;+ return;+ }+ }+ j->code_buffer |= b << (24 - j->code_bits);+ j->code_bits += 8;+ } while (j->code_bits <= 24);+}++// (1 << n) - 1+static const stbi__uint32 stbi__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535};++// decode a jpeg huffman value from the bitstream+stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h)+{+ unsigned int temp;+ int c,k;++ if (j->code_bits < 16) stbi__grow_buffer_unsafe(j);++ // look at the top FAST_BITS and determine what symbol ID it is,+ // if the code is <= FAST_BITS+ c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1);+ k = h->fast[c];+ if (k < 255) {+ int s = h->size[k];+ if (s > j->code_bits)+ return -1;+ j->code_buffer <<= s;+ j->code_bits -= s;+ return h->values[k];+ }++ // naive test is to shift the code_buffer down so k bits are+ // valid, then test against maxcode. To speed this up, we've+ // preshifted maxcode left so that it has (16-k) 0s at the+ // end; in other words, regardless of the number of bits, it+ // wants to be compared against something shifted to have 16;+ // that way we don't need to shift inside the loop.+ temp = j->code_buffer >> 16;+ for (k=FAST_BITS+1 ; ; ++k)+ if (temp < h->maxcode[k])+ break;+ if (k == 17) {+ // error! code not found+ j->code_bits -= 16;+ return -1;+ }++ if (k > j->code_bits)+ return -1;++ // convert the huffman code to the symbol id+ c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k];+ if(c < 0 || c >= 256) // symbol id out of bounds!+ return -1;+ STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]);++ // convert the id to a symbol+ j->code_bits -= k;+ j->code_buffer <<= k;+ return h->values[c];+}++// bias[n] = (-1<<n) + 1+static const int stbi__jbias[16] = {0,-1,-3,-7,-15,-31,-63,-127,-255,-511,-1023,-2047,-4095,-8191,-16383,-32767};++// combined JPEG 'receive' and JPEG 'extend', since baseline+// always extends everything it receives.+stbi_inline static int stbi__extend_receive(stbi__jpeg *j, int n)+{+ unsigned int k;+ int sgn;+ if (j->code_bits < n) stbi__grow_buffer_unsafe(j);+ if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing++ sgn = j->code_buffer >> 31; // sign bit always in MSB; 0 if MSB clear (positive), 1 if MSB set (negative)+ k = stbi_lrot(j->code_buffer, n);+ j->code_buffer = k & ~stbi__bmask[n];+ k &= stbi__bmask[n];+ j->code_bits -= n;+ return k + (stbi__jbias[n] & (sgn - 1));+}++// get some unsigned bits+stbi_inline static int stbi__jpeg_get_bits(stbi__jpeg *j, int n)+{+ unsigned int k;+ if (j->code_bits < n) stbi__grow_buffer_unsafe(j);+ if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing+ k = stbi_lrot(j->code_buffer, n);+ j->code_buffer = k & ~stbi__bmask[n];+ k &= stbi__bmask[n];+ j->code_bits -= n;+ return k;+}++stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j)+{+ unsigned int k;+ if (j->code_bits < 1) stbi__grow_buffer_unsafe(j);+ if (j->code_bits < 1) return 0; // ran out of bits from stream, return 0s intead of continuing+ k = j->code_buffer;+ j->code_buffer <<= 1;+ --j->code_bits;+ return k & 0x80000000;+}++// given a value that's at position X in the zigzag stream,+// where does it appear in the 8x8 matrix coded as row-major?+static const stbi_uc stbi__jpeg_dezigzag[64+15] =+{+ 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,+ // let corrupt input sample past end+ 63, 63, 63, 63, 63, 63, 63, 63,+ 63, 63, 63, 63, 63, 63, 63+};++// decode one 64-entry block--+static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, stbi__huffman *hac, stbi__int16 *fac, int b, stbi__uint16 *dequant)+{+ int diff,dc,k;+ int t;++ if (j->code_bits < 16) stbi__grow_buffer_unsafe(j);+ t = stbi__jpeg_huff_decode(j, hdc);+ if (t < 0 || t > 15) return stbi__err("bad huffman code","Corrupt JPEG");++ // 0 all the ac values now so we can do it 32-bits at a time+ memset(data,0,64*sizeof(data[0]));++ diff = t ? stbi__extend_receive(j, t) : 0;+ if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta","Corrupt JPEG");+ dc = j->img_comp[b].dc_pred + diff;+ j->img_comp[b].dc_pred = dc;+ if (!stbi__mul2shorts_valid(dc, dequant[0])) return stbi__err("can't merge dc and ac", "Corrupt JPEG");+ data[0] = (short) (dc * dequant[0]);++ // decode AC components, see JPEG spec+ k = 1;+ do {+ unsigned int zig;+ int c,r,s;+ if (j->code_bits < 16) stbi__grow_buffer_unsafe(j);+ c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1);+ r = fac[c];+ if (r) { // fast-AC path+ k += (r >> 4) & 15; // run+ s = r & 15; // combined length+ if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available");+ j->code_buffer <<= s;+ j->code_bits -= s;+ // decode into unzigzag'd location+ zig = stbi__jpeg_dezigzag[k++];+ data[zig] = (short) ((r >> 8) * dequant[zig]);+ } else {+ int rs = stbi__jpeg_huff_decode(j, hac);+ if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG");+ s = rs & 15;+ r = rs >> 4;+ if (s == 0) {+ if (rs != 0xf0) break; // end block+ k += 16;+ } else {+ k += r;+ // decode into unzigzag'd location+ zig = stbi__jpeg_dezigzag[k++];+ data[zig] = (short) (stbi__extend_receive(j,s) * dequant[zig]);+ }+ }+ } while (k < 64);+ return 1;+}++static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__huffman *hdc, int b)+{+ int diff,dc;+ int t;+ if (j->spec_end != 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG");++ if (j->code_bits < 16) stbi__grow_buffer_unsafe(j);++ if (j->succ_high == 0) {+ // first scan for DC coefficient, must be first+ memset(data,0,64*sizeof(data[0])); // 0 all the ac values now+ t = stbi__jpeg_huff_decode(j, hdc);+ if (t < 0 || t > 15) return stbi__err("can't merge dc and ac", "Corrupt JPEG");+ diff = t ? stbi__extend_receive(j, t) : 0;++ if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta", "Corrupt JPEG");+ dc = j->img_comp[b].dc_pred + diff;+ j->img_comp[b].dc_pred = dc;+ if (!stbi__mul2shorts_valid(dc, 1 << j->succ_low)) return stbi__err("can't merge dc and ac", "Corrupt JPEG");+ data[0] = (short) (dc * (1 << j->succ_low));+ } else {+ // refinement scan for DC coefficient+ if (stbi__jpeg_get_bit(j))+ data[0] += (short) (1 << j->succ_low);+ }+ return 1;+}++// @OPTIMIZE: store non-zigzagged during the decode passes,+// and only de-zigzag when dequantizing+static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__huffman *hac, stbi__int16 *fac)+{+ int k;+ if (j->spec_start == 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG");++ if (j->succ_high == 0) {+ int shift = j->succ_low;++ if (j->eob_run) {+ --j->eob_run;+ return 1;+ }++ k = j->spec_start;+ do {+ unsigned int zig;+ int c,r,s;+ if (j->code_bits < 16) stbi__grow_buffer_unsafe(j);+ c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1);+ r = fac[c];+ if (r) { // fast-AC path+ k += (r >> 4) & 15; // run+ s = r & 15; // combined length+ if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available");+ j->code_buffer <<= s;+ j->code_bits -= s;+ zig = stbi__jpeg_dezigzag[k++];+ data[zig] = (short) ((r >> 8) * (1 << shift));+ } else {+ int rs = stbi__jpeg_huff_decode(j, hac);+ if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG");+ s = rs & 15;+ r = rs >> 4;+ if (s == 0) {+ if (r < 15) {+ j->eob_run = (1 << r);+ if (r)+ j->eob_run += stbi__jpeg_get_bits(j, r);+ --j->eob_run;+ break;+ }+ k += 16;+ } else {+ k += r;+ zig = stbi__jpeg_dezigzag[k++];+ data[zig] = (short) (stbi__extend_receive(j,s) * (1 << shift));+ }+ }+ } while (k <= j->spec_end);+ } else {+ // refinement scan for these AC coefficients++ short bit = (short) (1 << j->succ_low);++ if (j->eob_run) {+ --j->eob_run;+ for (k = j->spec_start; k <= j->spec_end; ++k) {+ short *p = &data[stbi__jpeg_dezigzag[k]];+ if (*p != 0)+ if (stbi__jpeg_get_bit(j))+ if ((*p & bit)==0) {+ if (*p > 0)+ *p += bit;+ else+ *p -= bit;+ }+ }+ } else {+ k = j->spec_start;+ do {+ int r,s;+ int rs = stbi__jpeg_huff_decode(j, hac); // @OPTIMIZE see if we can use the fast path here, advance-by-r is so slow, eh+ if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG");+ s = rs & 15;+ r = rs >> 4;+ if (s == 0) {+ if (r < 15) {+ j->eob_run = (1 << r) - 1;+ if (r)+ j->eob_run += stbi__jpeg_get_bits(j, r);+ r = 64; // force end of block+ } else {+ // r=15 s=0 should write 16 0s, so we just do+ // a run of 15 0s and then write s (which is 0),+ // so we don't have to do anything special here+ }+ } else {+ if (s != 1) return stbi__err("bad huffman code", "Corrupt JPEG");+ // sign bit+ if (stbi__jpeg_get_bit(j))+ s = bit;+ else+ s = -bit;+ }++ // advance by r+ while (k <= j->spec_end) {+ short *p = &data[stbi__jpeg_dezigzag[k++]];+ if (*p != 0) {+ if (stbi__jpeg_get_bit(j))+ if ((*p & bit)==0) {+ if (*p > 0)+ *p += bit;+ else+ *p -= bit;+ }+ } else {+ if (r == 0) {+ *p = (short) s;+ break;+ }+ --r;+ }+ }+ } while (k <= j->spec_end);+ }+ }+ return 1;+}++// take a -128..127 value and stbi__clamp it and convert to 0..255+stbi_inline static stbi_uc stbi__clamp(int x)+{+ // trick to use a single test to catch both cases+ if ((unsigned int) x > 255) {+ if (x < 0) return 0;+ if (x > 255) return 255;+ }+ return (stbi_uc) x;+}++#define stbi__f2f(x) ((int) (((x) * 4096 + 0.5)))+#define stbi__fsh(x) ((x) * 4096)++// derived from jidctint -- DCT_ISLOW+#define STBI__IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \+ int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \+ p2 = s2; \+ p3 = s6; \+ p1 = (p2+p3) * stbi__f2f(0.5411961f); \+ t2 = p1 + p3*stbi__f2f(-1.847759065f); \+ t3 = p1 + p2*stbi__f2f( 0.765366865f); \+ p2 = s0; \+ p3 = s4; \+ t0 = stbi__fsh(p2+p3); \+ t1 = stbi__fsh(p2-p3); \+ x0 = t0+t3; \+ x3 = t0-t3; \+ x1 = t1+t2; \+ x2 = t1-t2; \+ t0 = s7; \+ t1 = s5; \+ t2 = s3; \+ t3 = s1; \+ p3 = t0+t2; \+ p4 = t1+t3; \+ p1 = t0+t3; \+ p2 = t1+t2; \+ p5 = (p3+p4)*stbi__f2f( 1.175875602f); \+ t0 = t0*stbi__f2f( 0.298631336f); \+ t1 = t1*stbi__f2f( 2.053119869f); \+ t2 = t2*stbi__f2f( 3.072711026f); \+ t3 = t3*stbi__f2f( 1.501321110f); \+ p1 = p5 + p1*stbi__f2f(-0.899976223f); \+ p2 = p5 + p2*stbi__f2f(-2.562915447f); \+ p3 = p3*stbi__f2f(-1.961570560f); \+ p4 = p4*stbi__f2f(-0.390180644f); \+ t3 += p1+p4; \+ t2 += p2+p3; \+ t1 += p2+p4; \+ t0 += p1+p3;++static void stbi__idct_block(stbi_uc *out, int out_stride, short data[64])+{+ int i,val[64],*v=val;+ stbi_uc *o;+ short *d = data;++ // columns+ for (i=0; i < 8; ++i,++d, ++v) {+ // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing+ if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0+ && d[40]==0 && d[48]==0 && d[56]==0) {+ // no shortcut 0 seconds+ // (1|2|3|4|5|6|7)==0 0 seconds+ // all separate -0.047 seconds+ // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds+ int dcterm = d[0]*4;+ v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm;+ } else {+ STBI__IDCT_1D(d[ 0],d[ 8],d[16],d[24],d[32],d[40],d[48],d[56])+ // constants scaled things up by 1<<12; let's bring them back+ // down, but keep 2 extra bits of precision+ x0 += 512; x1 += 512; x2 += 512; x3 += 512;+ v[ 0] = (x0+t3) >> 10;+ v[56] = (x0-t3) >> 10;+ v[ 8] = (x1+t2) >> 10;+ v[48] = (x1-t2) >> 10;+ v[16] = (x2+t1) >> 10;+ v[40] = (x2-t1) >> 10;+ v[24] = (x3+t0) >> 10;+ v[32] = (x3-t0) >> 10;+ }+ }++ for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) {+ // no fast case since the first 1D IDCT spread components out+ STBI__IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7])+ // constants scaled things up by 1<<12, plus we had 1<<2 from first+ // loop, plus horizontal and vertical each scale by sqrt(8) so together+ // we've got an extra 1<<3, so 1<<17 total we need to remove.+ // so we want to round that, which means adding 0.5 * 1<<17,+ // aka 65536. Also, we'll end up with -128 to 127 that we want+ // to encode as 0..255 by adding 128, so we'll add that before the shift+ x0 += 65536 + (128<<17);+ x1 += 65536 + (128<<17);+ x2 += 65536 + (128<<17);+ x3 += 65536 + (128<<17);+ // tried computing the shifts into temps, or'ing the temps to see+ // if any were out of range, but that was slower+ o[0] = stbi__clamp((x0+t3) >> 17);+ o[7] = stbi__clamp((x0-t3) >> 17);+ o[1] = stbi__clamp((x1+t2) >> 17);+ o[6] = stbi__clamp((x1-t2) >> 17);+ o[2] = stbi__clamp((x2+t1) >> 17);+ o[5] = stbi__clamp((x2-t1) >> 17);+ o[3] = stbi__clamp((x3+t0) >> 17);+ o[4] = stbi__clamp((x3-t0) >> 17);+ }+}++#ifdef STBI_SSE2+// sse2 integer IDCT. not the fastest possible implementation but it+// produces bit-identical results to the generic C version so it's+// fully "transparent".+static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64])+{+ // This is constructed to match our regular (generic) integer IDCT exactly.+ __m128i row0, row1, row2, row3, row4, row5, row6, row7;+ __m128i tmp;++ // dot product constant: even elems=x, odd elems=y+ #define dct_const(x,y) _mm_setr_epi16((x),(y),(x),(y),(x),(y),(x),(y))++ // out(0) = c0[even]*x + c0[odd]*y (c0, x, y 16-bit, out 32-bit)+ // out(1) = c1[even]*x + c1[odd]*y+ #define dct_rot(out0,out1, x,y,c0,c1) \+ __m128i c0##lo = _mm_unpacklo_epi16((x),(y)); \+ __m128i c0##hi = _mm_unpackhi_epi16((x),(y)); \+ __m128i out0##_l = _mm_madd_epi16(c0##lo, c0); \+ __m128i out0##_h = _mm_madd_epi16(c0##hi, c0); \+ __m128i out1##_l = _mm_madd_epi16(c0##lo, c1); \+ __m128i out1##_h = _mm_madd_epi16(c0##hi, c1)++ // out = in << 12 (in 16-bit, out 32-bit)+ #define dct_widen(out, in) \+ __m128i out##_l = _mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), (in)), 4); \+ __m128i out##_h = _mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), (in)), 4)++ // wide add+ #define dct_wadd(out, a, b) \+ __m128i out##_l = _mm_add_epi32(a##_l, b##_l); \+ __m128i out##_h = _mm_add_epi32(a##_h, b##_h)++ // wide sub+ #define dct_wsub(out, a, b) \+ __m128i out##_l = _mm_sub_epi32(a##_l, b##_l); \+ __m128i out##_h = _mm_sub_epi32(a##_h, b##_h)++ // butterfly a/b, add bias, then shift by "s" and pack+ #define dct_bfly32o(out0, out1, a,b,bias,s) \+ { \+ __m128i abiased_l = _mm_add_epi32(a##_l, bias); \+ __m128i abiased_h = _mm_add_epi32(a##_h, bias); \+ dct_wadd(sum, abiased, b); \+ dct_wsub(dif, abiased, b); \+ out0 = _mm_packs_epi32(_mm_srai_epi32(sum_l, s), _mm_srai_epi32(sum_h, s)); \+ out1 = _mm_packs_epi32(_mm_srai_epi32(dif_l, s), _mm_srai_epi32(dif_h, s)); \+ }++ // 8-bit interleave step (for transposes)+ #define dct_interleave8(a, b) \+ tmp = a; \+ a = _mm_unpacklo_epi8(a, b); \+ b = _mm_unpackhi_epi8(tmp, b)++ // 16-bit interleave step (for transposes)+ #define dct_interleave16(a, b) \+ tmp = a; \+ a = _mm_unpacklo_epi16(a, b); \+ b = _mm_unpackhi_epi16(tmp, b)++ #define dct_pass(bias,shift) \+ { \+ /* even part */ \+ dct_rot(t2e,t3e, row2,row6, rot0_0,rot0_1); \+ __m128i sum04 = _mm_add_epi16(row0, row4); \+ __m128i dif04 = _mm_sub_epi16(row0, row4); \+ dct_widen(t0e, sum04); \+ dct_widen(t1e, dif04); \+ dct_wadd(x0, t0e, t3e); \+ dct_wsub(x3, t0e, t3e); \+ dct_wadd(x1, t1e, t2e); \+ dct_wsub(x2, t1e, t2e); \+ /* odd part */ \+ dct_rot(y0o,y2o, row7,row3, rot2_0,rot2_1); \+ dct_rot(y1o,y3o, row5,row1, rot3_0,rot3_1); \+ __m128i sum17 = _mm_add_epi16(row1, row7); \+ __m128i sum35 = _mm_add_epi16(row3, row5); \+ dct_rot(y4o,y5o, sum17,sum35, rot1_0,rot1_1); \+ dct_wadd(x4, y0o, y4o); \+ dct_wadd(x5, y1o, y5o); \+ dct_wadd(x6, y2o, y5o); \+ dct_wadd(x7, y3o, y4o); \+ dct_bfly32o(row0,row7, x0,x7,bias,shift); \+ dct_bfly32o(row1,row6, x1,x6,bias,shift); \+ dct_bfly32o(row2,row5, x2,x5,bias,shift); \+ dct_bfly32o(row3,row4, x3,x4,bias,shift); \+ }++ __m128i rot0_0 = dct_const(stbi__f2f(0.5411961f), stbi__f2f(0.5411961f) + stbi__f2f(-1.847759065f));+ __m128i rot0_1 = dct_const(stbi__f2f(0.5411961f) + stbi__f2f( 0.765366865f), stbi__f2f(0.5411961f));+ __m128i rot1_0 = dct_const(stbi__f2f(1.175875602f) + stbi__f2f(-0.899976223f), stbi__f2f(1.175875602f));+ __m128i rot1_1 = dct_const(stbi__f2f(1.175875602f), stbi__f2f(1.175875602f) + stbi__f2f(-2.562915447f));+ __m128i rot2_0 = dct_const(stbi__f2f(-1.961570560f) + stbi__f2f( 0.298631336f), stbi__f2f(-1.961570560f));+ __m128i rot2_1 = dct_const(stbi__f2f(-1.961570560f), stbi__f2f(-1.961570560f) + stbi__f2f( 3.072711026f));+ __m128i rot3_0 = dct_const(stbi__f2f(-0.390180644f) + stbi__f2f( 2.053119869f), stbi__f2f(-0.390180644f));+ __m128i rot3_1 = dct_const(stbi__f2f(-0.390180644f), stbi__f2f(-0.390180644f) + stbi__f2f( 1.501321110f));++ // rounding biases in column/row passes, see stbi__idct_block for explanation.+ __m128i bias_0 = _mm_set1_epi32(512);+ __m128i bias_1 = _mm_set1_epi32(65536 + (128<<17));++ // load+ row0 = _mm_load_si128((const __m128i *) (data + 0*8));+ row1 = _mm_load_si128((const __m128i *) (data + 1*8));+ row2 = _mm_load_si128((const __m128i *) (data + 2*8));+ row3 = _mm_load_si128((const __m128i *) (data + 3*8));+ row4 = _mm_load_si128((const __m128i *) (data + 4*8));+ row5 = _mm_load_si128((const __m128i *) (data + 5*8));+ row6 = _mm_load_si128((const __m128i *) (data + 6*8));+ row7 = _mm_load_si128((const __m128i *) (data + 7*8));++ // column pass+ dct_pass(bias_0, 10);++ {+ // 16bit 8x8 transpose pass 1+ dct_interleave16(row0, row4);+ dct_interleave16(row1, row5);+ dct_interleave16(row2, row6);+ dct_interleave16(row3, row7);++ // transpose pass 2+ dct_interleave16(row0, row2);+ dct_interleave16(row1, row3);+ dct_interleave16(row4, row6);+ dct_interleave16(row5, row7);++ // transpose pass 3+ dct_interleave16(row0, row1);+ dct_interleave16(row2, row3);+ dct_interleave16(row4, row5);+ dct_interleave16(row6, row7);+ }++ // row pass+ dct_pass(bias_1, 17);++ {+ // pack+ __m128i p0 = _mm_packus_epi16(row0, row1); // a0a1a2a3...a7b0b1b2b3...b7+ __m128i p1 = _mm_packus_epi16(row2, row3);+ __m128i p2 = _mm_packus_epi16(row4, row5);+ __m128i p3 = _mm_packus_epi16(row6, row7);++ // 8bit 8x8 transpose pass 1+ dct_interleave8(p0, p2); // a0e0a1e1...+ dct_interleave8(p1, p3); // c0g0c1g1...++ // transpose pass 2+ dct_interleave8(p0, p1); // a0c0e0g0...+ dct_interleave8(p2, p3); // b0d0f0h0...++ // transpose pass 3+ dct_interleave8(p0, p2); // a0b0c0d0...+ dct_interleave8(p1, p3); // a4b4c4d4...++ // store+ _mm_storel_epi64((__m128i *) out, p0); out += out_stride;+ _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p0, 0x4e)); out += out_stride;+ _mm_storel_epi64((__m128i *) out, p2); out += out_stride;+ _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p2, 0x4e)); out += out_stride;+ _mm_storel_epi64((__m128i *) out, p1); out += out_stride;+ _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p1, 0x4e)); out += out_stride;+ _mm_storel_epi64((__m128i *) out, p3); out += out_stride;+ _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p3, 0x4e));+ }++#undef dct_const+#undef dct_rot+#undef dct_widen+#undef dct_wadd+#undef dct_wsub+#undef dct_bfly32o+#undef dct_interleave8+#undef dct_interleave16+#undef dct_pass+}++#endif // STBI_SSE2++#ifdef STBI_NEON++// NEON integer IDCT. should produce bit-identical+// results to the generic C version.+static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64])+{+ int16x8_t row0, row1, row2, row3, row4, row5, row6, row7;++ int16x4_t rot0_0 = vdup_n_s16(stbi__f2f(0.5411961f));+ int16x4_t rot0_1 = vdup_n_s16(stbi__f2f(-1.847759065f));+ int16x4_t rot0_2 = vdup_n_s16(stbi__f2f( 0.765366865f));+ int16x4_t rot1_0 = vdup_n_s16(stbi__f2f( 1.175875602f));+ int16x4_t rot1_1 = vdup_n_s16(stbi__f2f(-0.899976223f));+ int16x4_t rot1_2 = vdup_n_s16(stbi__f2f(-2.562915447f));+ int16x4_t rot2_0 = vdup_n_s16(stbi__f2f(-1.961570560f));+ int16x4_t rot2_1 = vdup_n_s16(stbi__f2f(-0.390180644f));+ int16x4_t rot3_0 = vdup_n_s16(stbi__f2f( 0.298631336f));+ int16x4_t rot3_1 = vdup_n_s16(stbi__f2f( 2.053119869f));+ int16x4_t rot3_2 = vdup_n_s16(stbi__f2f( 3.072711026f));+ int16x4_t rot3_3 = vdup_n_s16(stbi__f2f( 1.501321110f));++#define dct_long_mul(out, inq, coeff) \+ int32x4_t out##_l = vmull_s16(vget_low_s16(inq), coeff); \+ int32x4_t out##_h = vmull_s16(vget_high_s16(inq), coeff)++#define dct_long_mac(out, acc, inq, coeff) \+ int32x4_t out##_l = vmlal_s16(acc##_l, vget_low_s16(inq), coeff); \+ int32x4_t out##_h = vmlal_s16(acc##_h, vget_high_s16(inq), coeff)++#define dct_widen(out, inq) \+ int32x4_t out##_l = vshll_n_s16(vget_low_s16(inq), 12); \+ int32x4_t out##_h = vshll_n_s16(vget_high_s16(inq), 12)++// wide add+#define dct_wadd(out, a, b) \+ int32x4_t out##_l = vaddq_s32(a##_l, b##_l); \+ int32x4_t out##_h = vaddq_s32(a##_h, b##_h)++// wide sub+#define dct_wsub(out, a, b) \+ int32x4_t out##_l = vsubq_s32(a##_l, b##_l); \+ int32x4_t out##_h = vsubq_s32(a##_h, b##_h)++// butterfly a/b, then shift using "shiftop" by "s" and pack+#define dct_bfly32o(out0,out1, a,b,shiftop,s) \+ { \+ dct_wadd(sum, a, b); \+ dct_wsub(dif, a, b); \+ out0 = vcombine_s16(shiftop(sum_l, s), shiftop(sum_h, s)); \+ out1 = vcombine_s16(shiftop(dif_l, s), shiftop(dif_h, s)); \+ }++#define dct_pass(shiftop, shift) \+ { \+ /* even part */ \+ int16x8_t sum26 = vaddq_s16(row2, row6); \+ dct_long_mul(p1e, sum26, rot0_0); \+ dct_long_mac(t2e, p1e, row6, rot0_1); \+ dct_long_mac(t3e, p1e, row2, rot0_2); \+ int16x8_t sum04 = vaddq_s16(row0, row4); \+ int16x8_t dif04 = vsubq_s16(row0, row4); \+ dct_widen(t0e, sum04); \+ dct_widen(t1e, dif04); \+ dct_wadd(x0, t0e, t3e); \+ dct_wsub(x3, t0e, t3e); \+ dct_wadd(x1, t1e, t2e); \+ dct_wsub(x2, t1e, t2e); \+ /* odd part */ \+ int16x8_t sum15 = vaddq_s16(row1, row5); \+ int16x8_t sum17 = vaddq_s16(row1, row7); \+ int16x8_t sum35 = vaddq_s16(row3, row5); \+ int16x8_t sum37 = vaddq_s16(row3, row7); \+ int16x8_t sumodd = vaddq_s16(sum17, sum35); \+ dct_long_mul(p5o, sumodd, rot1_0); \+ dct_long_mac(p1o, p5o, sum17, rot1_1); \+ dct_long_mac(p2o, p5o, sum35, rot1_2); \+ dct_long_mul(p3o, sum37, rot2_0); \+ dct_long_mul(p4o, sum15, rot2_1); \+ dct_wadd(sump13o, p1o, p3o); \+ dct_wadd(sump24o, p2o, p4o); \+ dct_wadd(sump23o, p2o, p3o); \+ dct_wadd(sump14o, p1o, p4o); \+ dct_long_mac(x4, sump13o, row7, rot3_0); \+ dct_long_mac(x5, sump24o, row5, rot3_1); \+ dct_long_mac(x6, sump23o, row3, rot3_2); \+ dct_long_mac(x7, sump14o, row1, rot3_3); \+ dct_bfly32o(row0,row7, x0,x7,shiftop,shift); \+ dct_bfly32o(row1,row6, x1,x6,shiftop,shift); \+ dct_bfly32o(row2,row5, x2,x5,shiftop,shift); \+ dct_bfly32o(row3,row4, x3,x4,shiftop,shift); \+ }++ // load+ row0 = vld1q_s16(data + 0*8);+ row1 = vld1q_s16(data + 1*8);+ row2 = vld1q_s16(data + 2*8);+ row3 = vld1q_s16(data + 3*8);+ row4 = vld1q_s16(data + 4*8);+ row5 = vld1q_s16(data + 5*8);+ row6 = vld1q_s16(data + 6*8);+ row7 = vld1q_s16(data + 7*8);++ // add DC bias+ row0 = vaddq_s16(row0, vsetq_lane_s16(1024, vdupq_n_s16(0), 0));++ // column pass+ dct_pass(vrshrn_n_s32, 10);++ // 16bit 8x8 transpose+ {+// these three map to a single VTRN.16, VTRN.32, and VSWP, respectively.+// whether compilers actually get this is another story, sadly.+#define dct_trn16(x, y) { int16x8x2_t t = vtrnq_s16(x, y); x = t.val[0]; y = t.val[1]; }+#define dct_trn32(x, y) { int32x4x2_t t = vtrnq_s32(vreinterpretq_s32_s16(x), vreinterpretq_s32_s16(y)); x = vreinterpretq_s16_s32(t.val[0]); y = vreinterpretq_s16_s32(t.val[1]); }+#define dct_trn64(x, y) { int16x8_t x0 = x; int16x8_t y0 = y; x = vcombine_s16(vget_low_s16(x0), vget_low_s16(y0)); y = vcombine_s16(vget_high_s16(x0), vget_high_s16(y0)); }++ // pass 1+ dct_trn16(row0, row1); // a0b0a2b2a4b4a6b6+ dct_trn16(row2, row3);+ dct_trn16(row4, row5);+ dct_trn16(row6, row7);++ // pass 2+ dct_trn32(row0, row2); // a0b0c0d0a4b4c4d4+ dct_trn32(row1, row3);+ dct_trn32(row4, row6);+ dct_trn32(row5, row7);++ // pass 3+ dct_trn64(row0, row4); // a0b0c0d0e0f0g0h0+ dct_trn64(row1, row5);+ dct_trn64(row2, row6);+ dct_trn64(row3, row7);++#undef dct_trn16+#undef dct_trn32+#undef dct_trn64+ }++ // row pass+ // vrshrn_n_s32 only supports shifts up to 16, we need+ // 17. so do a non-rounding shift of 16 first then follow+ // up with a rounding shift by 1.+ dct_pass(vshrn_n_s32, 16);++ {+ // pack and round+ uint8x8_t p0 = vqrshrun_n_s16(row0, 1);+ uint8x8_t p1 = vqrshrun_n_s16(row1, 1);+ uint8x8_t p2 = vqrshrun_n_s16(row2, 1);+ uint8x8_t p3 = vqrshrun_n_s16(row3, 1);+ uint8x8_t p4 = vqrshrun_n_s16(row4, 1);+ uint8x8_t p5 = vqrshrun_n_s16(row5, 1);+ uint8x8_t p6 = vqrshrun_n_s16(row6, 1);+ uint8x8_t p7 = vqrshrun_n_s16(row7, 1);++ // again, these can translate into one instruction, but often don't.+#define dct_trn8_8(x, y) { uint8x8x2_t t = vtrn_u8(x, y); x = t.val[0]; y = t.val[1]; }+#define dct_trn8_16(x, y) { uint16x4x2_t t = vtrn_u16(vreinterpret_u16_u8(x), vreinterpret_u16_u8(y)); x = vreinterpret_u8_u16(t.val[0]); y = vreinterpret_u8_u16(t.val[1]); }+#define dct_trn8_32(x, y) { uint32x2x2_t t = vtrn_u32(vreinterpret_u32_u8(x), vreinterpret_u32_u8(y)); x = vreinterpret_u8_u32(t.val[0]); y = vreinterpret_u8_u32(t.val[1]); }++ // sadly can't use interleaved stores here since we only write+ // 8 bytes to each scan line!++ // 8x8 8-bit transpose pass 1+ dct_trn8_8(p0, p1);+ dct_trn8_8(p2, p3);+ dct_trn8_8(p4, p5);+ dct_trn8_8(p6, p7);++ // pass 2+ dct_trn8_16(p0, p2);+ dct_trn8_16(p1, p3);+ dct_trn8_16(p4, p6);+ dct_trn8_16(p5, p7);++ // pass 3+ dct_trn8_32(p0, p4);+ dct_trn8_32(p1, p5);+ dct_trn8_32(p2, p6);+ dct_trn8_32(p3, p7);++ // store+ vst1_u8(out, p0); out += out_stride;+ vst1_u8(out, p1); out += out_stride;+ vst1_u8(out, p2); out += out_stride;+ vst1_u8(out, p3); out += out_stride;+ vst1_u8(out, p4); out += out_stride;+ vst1_u8(out, p5); out += out_stride;+ vst1_u8(out, p6); out += out_stride;+ vst1_u8(out, p7);++#undef dct_trn8_8+#undef dct_trn8_16+#undef dct_trn8_32+ }++#undef dct_long_mul+#undef dct_long_mac+#undef dct_widen+#undef dct_wadd+#undef dct_wsub+#undef dct_bfly32o+#undef dct_pass+}++#endif // STBI_NEON++#define STBI__MARKER_none 0xff+// if there's a pending marker from the entropy stream, return that+// otherwise, fetch from the stream and get a marker. if there's no+// marker, return 0xff, which is never a valid marker value+static stbi_uc stbi__get_marker(stbi__jpeg *j)+{+ stbi_uc x;+ if (j->marker != STBI__MARKER_none) { x = j->marker; j->marker = STBI__MARKER_none; return x; }+ x = stbi__get8(j->s);+ if (x != 0xff) return STBI__MARKER_none;+ while (x == 0xff)+ x = stbi__get8(j->s); // consume repeated 0xff fill bytes+ return x;+}++// in each scan, we'll have scan_n components, and the order+// of the components is specified by order[]+#define STBI__RESTART(x) ((x) >= 0xd0 && (x) <= 0xd7)++// after a restart interval, stbi__jpeg_reset the entropy decoder and+// the dc prediction+static void stbi__jpeg_reset(stbi__jpeg *j)+{+ j->code_bits = 0;+ j->code_buffer = 0;+ j->nomore = 0;+ j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = j->img_comp[3].dc_pred = 0;+ j->marker = STBI__MARKER_none;+ j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff;+ j->eob_run = 0;+ // no more than 1<<31 MCUs if no restart_interal? that's plenty safe,+ // since we don't even allow 1<<30 pixels+}++static int stbi__parse_entropy_coded_data(stbi__jpeg *z)+{+ stbi__jpeg_reset(z);+ if (!z->progressive) {+ if (z->scan_n == 1) {+ int i,j;+ STBI_SIMD_ALIGN(short, data[64]);+ int n = z->order[0];+ // non-interleaved data, we just need to process one block at a time,+ // in trivial scanline order+ // number of blocks to do just depends on how many actual "pixels" this+ // component has, independent of interleaved MCU blocking and such+ int w = (z->img_comp[n].x+7) >> 3;+ int h = (z->img_comp[n].y+7) >> 3;+ for (j=0; j < h; ++j) {+ for (i=0; i < w; ++i) {+ int ha = z->img_comp[n].ha;+ if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0;+ z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data);+ // every data block is an MCU, so countdown the restart interval+ if (--z->todo <= 0) {+ if (z->code_bits < 24) stbi__grow_buffer_unsafe(z);+ // if it's NOT a restart, then just bail, so we get corrupt data+ // rather than no data+ if (!STBI__RESTART(z->marker)) return 1;+ stbi__jpeg_reset(z);+ }+ }+ }+ return 1;+ } else { // interleaved+ int i,j,k,x,y;+ STBI_SIMD_ALIGN(short, data[64]);+ for (j=0; j < z->img_mcu_y; ++j) {+ for (i=0; i < z->img_mcu_x; ++i) {+ // scan an interleaved mcu... process scan_n components in order+ for (k=0; k < z->scan_n; ++k) {+ int n = z->order[k];+ // scan out an mcu's worth of this component; that's just determined+ // by the basic H and V specified for the component+ for (y=0; y < z->img_comp[n].v; ++y) {+ for (x=0; x < z->img_comp[n].h; ++x) {+ int x2 = (i*z->img_comp[n].h + x)*8;+ int y2 = (j*z->img_comp[n].v + y)*8;+ int ha = z->img_comp[n].ha;+ if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0;+ z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data);+ }+ }+ }+ // after all interleaved components, that's an interleaved MCU,+ // so now count down the restart interval+ if (--z->todo <= 0) {+ if (z->code_bits < 24) stbi__grow_buffer_unsafe(z);+ if (!STBI__RESTART(z->marker)) return 1;+ stbi__jpeg_reset(z);+ }+ }+ }+ return 1;+ }+ } else {+ if (z->scan_n == 1) {+ int i,j;+ int n = z->order[0];+ // non-interleaved data, we just need to process one block at a time,+ // in trivial scanline order+ // number of blocks to do just depends on how many actual "pixels" this+ // component has, independent of interleaved MCU blocking and such+ int w = (z->img_comp[n].x+7) >> 3;+ int h = (z->img_comp[n].y+7) >> 3;+ for (j=0; j < h; ++j) {+ for (i=0; i < w; ++i) {+ short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w);+ if (z->spec_start == 0) {+ if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n))+ return 0;+ } else {+ int ha = z->img_comp[n].ha;+ if (!stbi__jpeg_decode_block_prog_ac(z, data, &z->huff_ac[ha], z->fast_ac[ha]))+ return 0;+ }+ // every data block is an MCU, so countdown the restart interval+ if (--z->todo <= 0) {+ if (z->code_bits < 24) stbi__grow_buffer_unsafe(z);+ if (!STBI__RESTART(z->marker)) return 1;+ stbi__jpeg_reset(z);+ }+ }+ }+ return 1;+ } else { // interleaved+ int i,j,k,x,y;+ for (j=0; j < z->img_mcu_y; ++j) {+ for (i=0; i < z->img_mcu_x; ++i) {+ // scan an interleaved mcu... process scan_n components in order+ for (k=0; k < z->scan_n; ++k) {+ int n = z->order[k];+ // scan out an mcu's worth of this component; that's just determined+ // by the basic H and V specified for the component+ for (y=0; y < z->img_comp[n].v; ++y) {+ for (x=0; x < z->img_comp[n].h; ++x) {+ int x2 = (i*z->img_comp[n].h + x);+ int y2 = (j*z->img_comp[n].v + y);+ short *data = z->img_comp[n].coeff + 64 * (x2 + y2 * z->img_comp[n].coeff_w);+ if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n))+ return 0;+ }+ }+ }+ // after all interleaved components, that's an interleaved MCU,+ // so now count down the restart interval+ if (--z->todo <= 0) {+ if (z->code_bits < 24) stbi__grow_buffer_unsafe(z);+ if (!STBI__RESTART(z->marker)) return 1;+ stbi__jpeg_reset(z);+ }+ }+ }+ return 1;+ }+ }+}++static void stbi__jpeg_dequantize(short *data, stbi__uint16 *dequant)+{+ int i;+ for (i=0; i < 64; ++i)+ data[i] *= dequant[i];+}++static void stbi__jpeg_finish(stbi__jpeg *z)+{+ if (z->progressive) {+ // dequantize and idct the data+ int i,j,n;+ for (n=0; n < z->s->img_n; ++n) {+ int w = (z->img_comp[n].x+7) >> 3;+ int h = (z->img_comp[n].y+7) >> 3;+ for (j=0; j < h; ++j) {+ for (i=0; i < w; ++i) {+ short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w);+ stbi__jpeg_dequantize(data, z->dequant[z->img_comp[n].tq]);+ z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data);+ }+ }+ }+ }+}++static int stbi__process_marker(stbi__jpeg *z, int m)+{+ int L;+ switch (m) {+ case STBI__MARKER_none: // no marker found+ return stbi__err("expected marker","Corrupt JPEG");++ case 0xDD: // DRI - specify restart interval+ if (stbi__get16be(z->s) != 4) return stbi__err("bad DRI len","Corrupt JPEG");+ z->restart_interval = stbi__get16be(z->s);+ return 1;++ case 0xDB: // DQT - define quantization table+ L = stbi__get16be(z->s)-2;+ while (L > 0) {+ int q = stbi__get8(z->s);+ int p = q >> 4, sixteen = (p != 0);+ int t = q & 15,i;+ if (p != 0 && p != 1) return stbi__err("bad DQT type","Corrupt JPEG");+ if (t > 3) return stbi__err("bad DQT table","Corrupt JPEG");++ for (i=0; i < 64; ++i)+ z->dequant[t][stbi__jpeg_dezigzag[i]] = (stbi__uint16)(sixteen ? stbi__get16be(z->s) : stbi__get8(z->s));+ L -= (sixteen ? 129 : 65);+ }+ return L==0;++ case 0xC4: // DHT - define huffman table+ L = stbi__get16be(z->s)-2;+ while (L > 0) {+ stbi_uc *v;+ int sizes[16],i,n=0;+ int q = stbi__get8(z->s);+ int tc = q >> 4;+ int th = q & 15;+ if (tc > 1 || th > 3) return stbi__err("bad DHT header","Corrupt JPEG");+ for (i=0; i < 16; ++i) {+ sizes[i] = stbi__get8(z->s);+ n += sizes[i];+ }+ if(n > 256) return stbi__err("bad DHT header","Corrupt JPEG"); // Loop over i < n would write past end of values!+ L -= 17;+ if (tc == 0) {+ if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0;+ v = z->huff_dc[th].values;+ } else {+ if (!stbi__build_huffman(z->huff_ac+th, sizes)) return 0;+ v = z->huff_ac[th].values;+ }+ for (i=0; i < n; ++i)+ v[i] = stbi__get8(z->s);+ if (tc != 0)+ stbi__build_fast_ac(z->fast_ac[th], z->huff_ac + th);+ L -= n;+ }+ return L==0;+ }++ // check for comment block or APP blocks+ if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) {+ L = stbi__get16be(z->s);+ if (L < 2) {+ if (m == 0xFE)+ return stbi__err("bad COM len","Corrupt JPEG");+ else+ return stbi__err("bad APP len","Corrupt JPEG");+ }+ L -= 2;++ if (m == 0xE0 && L >= 5) { // JFIF APP0 segment+ static const unsigned char tag[5] = {'J','F','I','F','\0'};+ int ok = 1;+ int i;+ for (i=0; i < 5; ++i)+ if (stbi__get8(z->s) != tag[i])+ ok = 0;+ L -= 5;+ if (ok)+ z->jfif = 1;+ } else if (m == 0xEE && L >= 12) { // Adobe APP14 segment+ static const unsigned char tag[6] = {'A','d','o','b','e','\0'};+ int ok = 1;+ int i;+ for (i=0; i < 6; ++i)+ if (stbi__get8(z->s) != tag[i])+ ok = 0;+ L -= 6;+ if (ok) {+ stbi__get8(z->s); // version+ stbi__get16be(z->s); // flags0+ stbi__get16be(z->s); // flags1+ z->app14_color_transform = stbi__get8(z->s); // color transform+ L -= 6;+ }+ }++ stbi__skip(z->s, L);+ return 1;+ }++ return stbi__err("unknown marker","Corrupt JPEG");+}++// after we see SOS+static int stbi__process_scan_header(stbi__jpeg *z)+{+ int i;+ int Ls = stbi__get16be(z->s);+ z->scan_n = stbi__get8(z->s);+ if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s->img_n) return stbi__err("bad SOS component count","Corrupt JPEG");+ if (Ls != 6+2*z->scan_n) return stbi__err("bad SOS len","Corrupt JPEG");+ for (i=0; i < z->scan_n; ++i) {+ int id = stbi__get8(z->s), which;+ int q = stbi__get8(z->s);+ for (which = 0; which < z->s->img_n; ++which)+ if (z->img_comp[which].id == id)+ break;+ if (which == z->s->img_n) return 0; // no match+ z->img_comp[which].hd = q >> 4; if (z->img_comp[which].hd > 3) return stbi__err("bad DC huff","Corrupt JPEG");+ z->img_comp[which].ha = q & 15; if (z->img_comp[which].ha > 3) return stbi__err("bad AC huff","Corrupt JPEG");+ z->order[i] = which;+ }++ {+ int aa;+ z->spec_start = stbi__get8(z->s);+ z->spec_end = stbi__get8(z->s); // should be 63, but might be 0+ aa = stbi__get8(z->s);+ z->succ_high = (aa >> 4);+ z->succ_low = (aa & 15);+ if (z->progressive) {+ if (z->spec_start > 63 || z->spec_end > 63 || z->spec_start > z->spec_end || z->succ_high > 13 || z->succ_low > 13)+ return stbi__err("bad SOS", "Corrupt JPEG");+ } else {+ if (z->spec_start != 0) return stbi__err("bad SOS","Corrupt JPEG");+ if (z->succ_high != 0 || z->succ_low != 0) return stbi__err("bad SOS","Corrupt JPEG");+ z->spec_end = 63;+ }+ }++ return 1;+}++static int stbi__free_jpeg_components(stbi__jpeg *z, int ncomp, int why)+{+ int i;+ for (i=0; i < ncomp; ++i) {+ if (z->img_comp[i].raw_data) {+ STBI_FREE(z->img_comp[i].raw_data);+ z->img_comp[i].raw_data = NULL;+ z->img_comp[i].data = NULL;+ }+ if (z->img_comp[i].raw_coeff) {+ STBI_FREE(z->img_comp[i].raw_coeff);+ z->img_comp[i].raw_coeff = 0;+ z->img_comp[i].coeff = 0;+ }+ if (z->img_comp[i].linebuf) {+ STBI_FREE(z->img_comp[i].linebuf);+ z->img_comp[i].linebuf = NULL;+ }+ }+ return why;+}++static int stbi__process_frame_header(stbi__jpeg *z, int scan)+{+ stbi__context *s = z->s;+ int Lf,p,i,q, h_max=1,v_max=1,c;+ Lf = stbi__get16be(s); if (Lf < 11) return stbi__err("bad SOF len","Corrupt JPEG"); // JPEG+ p = stbi__get8(s); if (p != 8) return stbi__err("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline+ s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG+ s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires+ if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");+ if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");+ c = stbi__get8(s);+ if (c != 3 && c != 1 && c != 4) return stbi__err("bad component count","Corrupt JPEG");+ s->img_n = c;+ for (i=0; i < c; ++i) {+ z->img_comp[i].data = NULL;+ z->img_comp[i].linebuf = NULL;+ }++ if (Lf != 8+3*s->img_n) return stbi__err("bad SOF len","Corrupt JPEG");++ z->rgb = 0;+ for (i=0; i < s->img_n; ++i) {+ static const unsigned char rgb[3] = { 'R', 'G', 'B' };+ z->img_comp[i].id = stbi__get8(s);+ if (s->img_n == 3 && z->img_comp[i].id == rgb[i])+ ++z->rgb;+ q = stbi__get8(s);+ z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG");+ z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG");+ z->img_comp[i].tq = stbi__get8(s); if (z->img_comp[i].tq > 3) return stbi__err("bad TQ","Corrupt JPEG");+ }++ if (scan != STBI__SCAN_load) return 1;++ if (!stbi__mad3sizes_valid(s->img_x, s->img_y, s->img_n, 0)) return stbi__err("too large", "Image too large to decode");++ for (i=0; i < s->img_n; ++i) {+ if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h;+ if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v;+ }++ // check that plane subsampling factors are integer ratios; our resamplers can't deal with fractional ratios+ // and I've never seen a non-corrupted JPEG file actually use them+ for (i=0; i < s->img_n; ++i) {+ if (h_max % z->img_comp[i].h != 0) return stbi__err("bad H","Corrupt JPEG");+ if (v_max % z->img_comp[i].v != 0) return stbi__err("bad V","Corrupt JPEG");+ }++ // compute interleaved mcu info+ z->img_h_max = h_max;+ z->img_v_max = v_max;+ z->img_mcu_w = h_max * 8;+ z->img_mcu_h = v_max * 8;+ // these sizes can't be more than 17 bits+ z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w;+ z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h;++ for (i=0; i < s->img_n; ++i) {+ // number of effective pixels (e.g. for non-interleaved MCU)+ z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max;+ z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max;+ // to simplify generation, we'll allocate enough memory to decode+ // the bogus oversized data from using interleaved MCUs and their+ // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't+ // discard the extra data until colorspace conversion+ //+ // img_mcu_x, img_mcu_y: <=17 bits; comp[i].h and .v are <=4 (checked earlier)+ // so these muls can't overflow with 32-bit ints (which we require)+ z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8;+ z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8;+ z->img_comp[i].coeff = 0;+ z->img_comp[i].raw_coeff = 0;+ z->img_comp[i].linebuf = NULL;+ z->img_comp[i].raw_data = stbi__malloc_mad2(z->img_comp[i].w2, z->img_comp[i].h2, 15);+ if (z->img_comp[i].raw_data == NULL)+ return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory"));+ // align blocks for idct using mmx/sse+ z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15);+ if (z->progressive) {+ // w2, h2 are multiples of 8 (see above)+ z->img_comp[i].coeff_w = z->img_comp[i].w2 / 8;+ z->img_comp[i].coeff_h = z->img_comp[i].h2 / 8;+ z->img_comp[i].raw_coeff = stbi__malloc_mad3(z->img_comp[i].w2, z->img_comp[i].h2, sizeof(short), 15);+ if (z->img_comp[i].raw_coeff == NULL)+ return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory"));+ z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15);+ }+ }++ return 1;+}++// use comparisons since in some cases we handle more than one case (e.g. SOF)+#define stbi__DNL(x) ((x) == 0xdc)+#define stbi__SOI(x) ((x) == 0xd8)+#define stbi__EOI(x) ((x) == 0xd9)+#define stbi__SOF(x) ((x) == 0xc0 || (x) == 0xc1 || (x) == 0xc2)+#define stbi__SOS(x) ((x) == 0xda)++#define stbi__SOF_progressive(x) ((x) == 0xc2)++static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan)+{+ int m;+ z->jfif = 0;+ z->app14_color_transform = -1; // valid values are 0,1,2+ z->marker = STBI__MARKER_none; // initialize cached marker to empty+ m = stbi__get_marker(z);+ if (!stbi__SOI(m)) return stbi__err("no SOI","Corrupt JPEG");+ if (scan == STBI__SCAN_type) return 1;+ m = stbi__get_marker(z);+ while (!stbi__SOF(m)) {+ if (!stbi__process_marker(z,m)) return 0;+ m = stbi__get_marker(z);+ while (m == STBI__MARKER_none) {+ // some files have extra padding after their blocks, so ok, we'll scan+ if (stbi__at_eof(z->s)) return stbi__err("no SOF", "Corrupt JPEG");+ m = stbi__get_marker(z);+ }+ }+ z->progressive = stbi__SOF_progressive(m);+ if (!stbi__process_frame_header(z, scan)) return 0;+ return 1;+}++static stbi_uc stbi__skip_jpeg_junk_at_end(stbi__jpeg *j)+{+ // some JPEGs have junk at end, skip over it but if we find what looks+ // like a valid marker, resume there+ while (!stbi__at_eof(j->s)) {+ stbi_uc x = stbi__get8(j->s);+ while (x == 0xff) { // might be a marker+ if (stbi__at_eof(j->s)) return STBI__MARKER_none;+ x = stbi__get8(j->s);+ if (x != 0x00 && x != 0xff) {+ // not a stuffed zero or lead-in to another marker, looks+ // like an actual marker, return it+ return x;+ }+ // stuffed zero has x=0 now which ends the loop, meaning we go+ // back to regular scan loop.+ // repeated 0xff keeps trying to read the next byte of the marker.+ }+ }+ return STBI__MARKER_none;+}++// decode image to YCbCr format+static int stbi__decode_jpeg_image(stbi__jpeg *j)+{+ int m;+ for (m = 0; m < 4; m++) {+ j->img_comp[m].raw_data = NULL;+ j->img_comp[m].raw_coeff = NULL;+ }+ j->restart_interval = 0;+ if (!stbi__decode_jpeg_header(j, STBI__SCAN_load)) return 0;+ m = stbi__get_marker(j);+ while (!stbi__EOI(m)) {+ if (stbi__SOS(m)) {+ if (!stbi__process_scan_header(j)) return 0;+ if (!stbi__parse_entropy_coded_data(j)) return 0;+ if (j->marker == STBI__MARKER_none ) {+ j->marker = stbi__skip_jpeg_junk_at_end(j);+ // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0+ }+ m = stbi__get_marker(j);+ if (STBI__RESTART(m))+ m = stbi__get_marker(j);+ } else if (stbi__DNL(m)) {+ int Ld = stbi__get16be(j->s);+ stbi__uint32 NL = stbi__get16be(j->s);+ if (Ld != 4) return stbi__err("bad DNL len", "Corrupt JPEG");+ if (NL != j->s->img_y) return stbi__err("bad DNL height", "Corrupt JPEG");+ m = stbi__get_marker(j);+ } else {+ if (!stbi__process_marker(j, m)) return 1;+ m = stbi__get_marker(j);+ }+ }+ if (j->progressive)+ stbi__jpeg_finish(j);+ return 1;+}++// static jfif-centered resampling (across block boundaries)++typedef stbi_uc *(*resample_row_func)(stbi_uc *out, stbi_uc *in0, stbi_uc *in1,+ int w, int hs);++#define stbi__div4(x) ((stbi_uc) ((x) >> 2))++static stbi_uc *resample_row_1(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)+{+ STBI_NOTUSED(out);+ STBI_NOTUSED(in_far);+ STBI_NOTUSED(w);+ STBI_NOTUSED(hs);+ return in_near;+}++static stbi_uc* stbi__resample_row_v_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)+{+ // need to generate two samples vertically for every one in input+ int i;+ STBI_NOTUSED(hs);+ for (i=0; i < w; ++i)+ out[i] = stbi__div4(3*in_near[i] + in_far[i] + 2);+ return out;+}++static stbi_uc* stbi__resample_row_h_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)+{+ // need to generate two samples horizontally for every one in input+ int i;+ stbi_uc *input = in_near;++ if (w == 1) {+ // if only one sample, can't do any interpolation+ out[0] = out[1] = input[0];+ return out;+ }++ out[0] = input[0];+ out[1] = stbi__div4(input[0]*3 + input[1] + 2);+ for (i=1; i < w-1; ++i) {+ int n = 3*input[i]+2;+ out[i*2+0] = stbi__div4(n+input[i-1]);+ out[i*2+1] = stbi__div4(n+input[i+1]);+ }+ out[i*2+0] = stbi__div4(input[w-2]*3 + input[w-1] + 2);+ out[i*2+1] = input[w-1];++ STBI_NOTUSED(in_far);+ STBI_NOTUSED(hs);++ return out;+}++#define stbi__div16(x) ((stbi_uc) ((x) >> 4))++static stbi_uc *stbi__resample_row_hv_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)+{+ // need to generate 2x2 samples for every one in input+ int i,t0,t1;+ if (w == 1) {+ out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2);+ return out;+ }++ t1 = 3*in_near[0] + in_far[0];+ out[0] = stbi__div4(t1+2);+ for (i=1; i < w; ++i) {+ t0 = t1;+ t1 = 3*in_near[i]+in_far[i];+ out[i*2-1] = stbi__div16(3*t0 + t1 + 8);+ out[i*2 ] = stbi__div16(3*t1 + t0 + 8);+ }+ out[w*2-1] = stbi__div4(t1+2);++ STBI_NOTUSED(hs);++ return out;+}++#if defined(STBI_SSE2) || defined(STBI_NEON)+static stbi_uc *stbi__resample_row_hv_2_simd(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)+{+ // need to generate 2x2 samples for every one in input+ int i=0,t0,t1;++ if (w == 1) {+ out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2);+ return out;+ }++ t1 = 3*in_near[0] + in_far[0];+ // process groups of 8 pixels for as long as we can.+ // note we can't handle the last pixel in a row in this loop+ // because we need to handle the filter boundary conditions.+ for (; i < ((w-1) & ~7); i += 8) {+#if defined(STBI_SSE2)+ // load and perform the vertical filtering pass+ // this uses 3*x + y = 4*x + (y - x)+ __m128i zero = _mm_setzero_si128();+ __m128i farb = _mm_loadl_epi64((__m128i *) (in_far + i));+ __m128i nearb = _mm_loadl_epi64((__m128i *) (in_near + i));+ __m128i farw = _mm_unpacklo_epi8(farb, zero);+ __m128i nearw = _mm_unpacklo_epi8(nearb, zero);+ __m128i diff = _mm_sub_epi16(farw, nearw);+ __m128i nears = _mm_slli_epi16(nearw, 2);+ __m128i curr = _mm_add_epi16(nears, diff); // current row++ // horizontal filter works the same based on shifted vers of current+ // row. "prev" is current row shifted right by 1 pixel; we need to+ // insert the previous pixel value (from t1).+ // "next" is current row shifted left by 1 pixel, with first pixel+ // of next block of 8 pixels added in.+ __m128i prv0 = _mm_slli_si128(curr, 2);+ __m128i nxt0 = _mm_srli_si128(curr, 2);+ __m128i prev = _mm_insert_epi16(prv0, t1, 0);+ __m128i next = _mm_insert_epi16(nxt0, 3*in_near[i+8] + in_far[i+8], 7);++ // horizontal filter, polyphase implementation since it's convenient:+ // even pixels = 3*cur + prev = cur*4 + (prev - cur)+ // odd pixels = 3*cur + next = cur*4 + (next - cur)+ // note the shared term.+ __m128i bias = _mm_set1_epi16(8);+ __m128i curs = _mm_slli_epi16(curr, 2);+ __m128i prvd = _mm_sub_epi16(prev, curr);+ __m128i nxtd = _mm_sub_epi16(next, curr);+ __m128i curb = _mm_add_epi16(curs, bias);+ __m128i even = _mm_add_epi16(prvd, curb);+ __m128i odd = _mm_add_epi16(nxtd, curb);++ // interleave even and odd pixels, then undo scaling.+ __m128i int0 = _mm_unpacklo_epi16(even, odd);+ __m128i int1 = _mm_unpackhi_epi16(even, odd);+ __m128i de0 = _mm_srli_epi16(int0, 4);+ __m128i de1 = _mm_srli_epi16(int1, 4);++ // pack and write output+ __m128i outv = _mm_packus_epi16(de0, de1);+ _mm_storeu_si128((__m128i *) (out + i*2), outv);+#elif defined(STBI_NEON)+ // load and perform the vertical filtering pass+ // this uses 3*x + y = 4*x + (y - x)+ uint8x8_t farb = vld1_u8(in_far + i);+ uint8x8_t nearb = vld1_u8(in_near + i);+ int16x8_t diff = vreinterpretq_s16_u16(vsubl_u8(farb, nearb));+ int16x8_t nears = vreinterpretq_s16_u16(vshll_n_u8(nearb, 2));+ int16x8_t curr = vaddq_s16(nears, diff); // current row++ // horizontal filter works the same based on shifted vers of current+ // row. "prev" is current row shifted right by 1 pixel; we need to+ // insert the previous pixel value (from t1).+ // "next" is current row shifted left by 1 pixel, with first pixel+ // of next block of 8 pixels added in.+ int16x8_t prv0 = vextq_s16(curr, curr, 7);+ int16x8_t nxt0 = vextq_s16(curr, curr, 1);+ int16x8_t prev = vsetq_lane_s16(t1, prv0, 0);+ int16x8_t next = vsetq_lane_s16(3*in_near[i+8] + in_far[i+8], nxt0, 7);++ // horizontal filter, polyphase implementation since it's convenient:+ // even pixels = 3*cur + prev = cur*4 + (prev - cur)+ // odd pixels = 3*cur + next = cur*4 + (next - cur)+ // note the shared term.+ int16x8_t curs = vshlq_n_s16(curr, 2);+ int16x8_t prvd = vsubq_s16(prev, curr);+ int16x8_t nxtd = vsubq_s16(next, curr);+ int16x8_t even = vaddq_s16(curs, prvd);+ int16x8_t odd = vaddq_s16(curs, nxtd);++ // undo scaling and round, then store with even/odd phases interleaved+ uint8x8x2_t o;+ o.val[0] = vqrshrun_n_s16(even, 4);+ o.val[1] = vqrshrun_n_s16(odd, 4);+ vst2_u8(out + i*2, o);+#endif++ // "previous" value for next iter+ t1 = 3*in_near[i+7] + in_far[i+7];+ }++ t0 = t1;+ t1 = 3*in_near[i] + in_far[i];+ out[i*2] = stbi__div16(3*t1 + t0 + 8);++ for (++i; i < w; ++i) {+ t0 = t1;+ t1 = 3*in_near[i]+in_far[i];+ out[i*2-1] = stbi__div16(3*t0 + t1 + 8);+ out[i*2 ] = stbi__div16(3*t1 + t0 + 8);+ }+ out[w*2-1] = stbi__div4(t1+2);++ STBI_NOTUSED(hs);++ return out;+}+#endif++static stbi_uc *stbi__resample_row_generic(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs)+{+ // resample with nearest-neighbor+ int i,j;+ STBI_NOTUSED(in_far);+ for (i=0; i < w; ++i)+ for (j=0; j < hs; ++j)+ out[i*hs+j] = in_near[i];+ return out;+}++// this is a reduced-precision calculation of YCbCr-to-RGB introduced+// to make sure the code produces the same results in both SIMD and scalar+#define stbi__float2fixed(x) (((int) ((x) * 4096.0f + 0.5f)) << 8)+static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step)+{+ int i;+ for (i=0; i < count; ++i) {+ int y_fixed = (y[i] << 20) + (1<<19); // rounding+ int r,g,b;+ int cr = pcr[i] - 128;+ int cb = pcb[i] - 128;+ r = y_fixed + cr* stbi__float2fixed(1.40200f);+ g = y_fixed + (cr*-stbi__float2fixed(0.71414f)) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000);+ b = y_fixed + cb* stbi__float2fixed(1.77200f);+ r >>= 20;+ g >>= 20;+ b >>= 20;+ if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; }+ if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; }+ if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; }+ out[0] = (stbi_uc)r;+ out[1] = (stbi_uc)g;+ out[2] = (stbi_uc)b;+ out[3] = 255;+ out += step;+ }+}++#if defined(STBI_SSE2) || defined(STBI_NEON)+static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc const *pcb, stbi_uc const *pcr, int count, int step)+{+ int i = 0;++#ifdef STBI_SSE2+ // step == 3 is pretty ugly on the final interleave, and i'm not convinced+ // it's useful in practice (you wouldn't use it for textures, for example).+ // so just accelerate step == 4 case.+ if (step == 4) {+ // this is a fairly straightforward implementation and not super-optimized.+ __m128i signflip = _mm_set1_epi8(-0x80);+ __m128i cr_const0 = _mm_set1_epi16( (short) ( 1.40200f*4096.0f+0.5f));+ __m128i cr_const1 = _mm_set1_epi16( - (short) ( 0.71414f*4096.0f+0.5f));+ __m128i cb_const0 = _mm_set1_epi16( - (short) ( 0.34414f*4096.0f+0.5f));+ __m128i cb_const1 = _mm_set1_epi16( (short) ( 1.77200f*4096.0f+0.5f));+ __m128i y_bias = _mm_set1_epi8((char) (unsigned char) 128);+ __m128i xw = _mm_set1_epi16(255); // alpha channel++ for (; i+7 < count; i += 8) {+ // load+ __m128i y_bytes = _mm_loadl_epi64((__m128i *) (y+i));+ __m128i cr_bytes = _mm_loadl_epi64((__m128i *) (pcr+i));+ __m128i cb_bytes = _mm_loadl_epi64((__m128i *) (pcb+i));+ __m128i cr_biased = _mm_xor_si128(cr_bytes, signflip); // -128+ __m128i cb_biased = _mm_xor_si128(cb_bytes, signflip); // -128++ // unpack to short (and left-shift cr, cb by 8)+ __m128i yw = _mm_unpacklo_epi8(y_bias, y_bytes);+ __m128i crw = _mm_unpacklo_epi8(_mm_setzero_si128(), cr_biased);+ __m128i cbw = _mm_unpacklo_epi8(_mm_setzero_si128(), cb_biased);++ // color transform+ __m128i yws = _mm_srli_epi16(yw, 4);+ __m128i cr0 = _mm_mulhi_epi16(cr_const0, crw);+ __m128i cb0 = _mm_mulhi_epi16(cb_const0, cbw);+ __m128i cb1 = _mm_mulhi_epi16(cbw, cb_const1);+ __m128i cr1 = _mm_mulhi_epi16(crw, cr_const1);+ __m128i rws = _mm_add_epi16(cr0, yws);+ __m128i gwt = _mm_add_epi16(cb0, yws);+ __m128i bws = _mm_add_epi16(yws, cb1);+ __m128i gws = _mm_add_epi16(gwt, cr1);++ // descale+ __m128i rw = _mm_srai_epi16(rws, 4);+ __m128i bw = _mm_srai_epi16(bws, 4);+ __m128i gw = _mm_srai_epi16(gws, 4);++ // back to byte, set up for transpose+ __m128i brb = _mm_packus_epi16(rw, bw);+ __m128i gxb = _mm_packus_epi16(gw, xw);++ // transpose to interleave channels+ __m128i t0 = _mm_unpacklo_epi8(brb, gxb);+ __m128i t1 = _mm_unpackhi_epi8(brb, gxb);+ __m128i o0 = _mm_unpacklo_epi16(t0, t1);+ __m128i o1 = _mm_unpackhi_epi16(t0, t1);++ // store+ _mm_storeu_si128((__m128i *) (out + 0), o0);+ _mm_storeu_si128((__m128i *) (out + 16), o1);+ out += 32;+ }+ }+#endif++#ifdef STBI_NEON+ // in this version, step=3 support would be easy to add. but is there demand?+ if (step == 4) {+ // this is a fairly straightforward implementation and not super-optimized.+ uint8x8_t signflip = vdup_n_u8(0x80);+ int16x8_t cr_const0 = vdupq_n_s16( (short) ( 1.40200f*4096.0f+0.5f));+ int16x8_t cr_const1 = vdupq_n_s16( - (short) ( 0.71414f*4096.0f+0.5f));+ int16x8_t cb_const0 = vdupq_n_s16( - (short) ( 0.34414f*4096.0f+0.5f));+ int16x8_t cb_const1 = vdupq_n_s16( (short) ( 1.77200f*4096.0f+0.5f));++ for (; i+7 < count; i += 8) {+ // load+ uint8x8_t y_bytes = vld1_u8(y + i);+ uint8x8_t cr_bytes = vld1_u8(pcr + i);+ uint8x8_t cb_bytes = vld1_u8(pcb + i);+ int8x8_t cr_biased = vreinterpret_s8_u8(vsub_u8(cr_bytes, signflip));+ int8x8_t cb_biased = vreinterpret_s8_u8(vsub_u8(cb_bytes, signflip));++ // expand to s16+ int16x8_t yws = vreinterpretq_s16_u16(vshll_n_u8(y_bytes, 4));+ int16x8_t crw = vshll_n_s8(cr_biased, 7);+ int16x8_t cbw = vshll_n_s8(cb_biased, 7);++ // color transform+ int16x8_t cr0 = vqdmulhq_s16(crw, cr_const0);+ int16x8_t cb0 = vqdmulhq_s16(cbw, cb_const0);+ int16x8_t cr1 = vqdmulhq_s16(crw, cr_const1);+ int16x8_t cb1 = vqdmulhq_s16(cbw, cb_const1);+ int16x8_t rws = vaddq_s16(yws, cr0);+ int16x8_t gws = vaddq_s16(vaddq_s16(yws, cb0), cr1);+ int16x8_t bws = vaddq_s16(yws, cb1);++ // undo scaling, round, convert to byte+ uint8x8x4_t o;+ o.val[0] = vqrshrun_n_s16(rws, 4);+ o.val[1] = vqrshrun_n_s16(gws, 4);+ o.val[2] = vqrshrun_n_s16(bws, 4);+ o.val[3] = vdup_n_u8(255);++ // store, interleaving r/g/b/a+ vst4_u8(out, o);+ out += 8*4;+ }+ }+#endif++ for (; i < count; ++i) {+ int y_fixed = (y[i] << 20) + (1<<19); // rounding+ int r,g,b;+ int cr = pcr[i] - 128;+ int cb = pcb[i] - 128;+ r = y_fixed + cr* stbi__float2fixed(1.40200f);+ g = y_fixed + cr*-stbi__float2fixed(0.71414f) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000);+ b = y_fixed + cb* stbi__float2fixed(1.77200f);+ r >>= 20;+ g >>= 20;+ b >>= 20;+ if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; }+ if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; }+ if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; }+ out[0] = (stbi_uc)r;+ out[1] = (stbi_uc)g;+ out[2] = (stbi_uc)b;+ out[3] = 255;+ out += step;+ }+}+#endif++// set up the kernels+static void stbi__setup_jpeg(stbi__jpeg *j)+{+ j->idct_block_kernel = stbi__idct_block;+ j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_row;+ j->resample_row_hv_2_kernel = stbi__resample_row_hv_2;++#ifdef STBI_SSE2+ if (stbi__sse2_available()) {+ j->idct_block_kernel = stbi__idct_simd;+ j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd;+ j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd;+ }+#endif++#ifdef STBI_NEON+ j->idct_block_kernel = stbi__idct_simd;+ j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd;+ j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd;+#endif+}++// clean up the temporary component buffers+static void stbi__cleanup_jpeg(stbi__jpeg *j)+{+ stbi__free_jpeg_components(j, j->s->img_n, 0);+}++typedef struct+{+ resample_row_func resample;+ stbi_uc *line0,*line1;+ int hs,vs; // expansion factor in each axis+ int w_lores; // horizontal pixels pre-expansion+ int ystep; // how far through vertical expansion we are+ int ypos; // which pre-expansion row we're on+} stbi__resample;++// fast 0..255 * 0..255 => 0..255 rounded multiplication+static stbi_uc stbi__blinn_8x8(stbi_uc x, stbi_uc y)+{+ unsigned int t = x*y + 128;+ return (stbi_uc) ((t + (t >>8)) >> 8);+}++static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp)+{+ int n, decode_n, is_rgb;+ z->s->img_n = 0; // make stbi__cleanup_jpeg safe++ // validate req_comp+ if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error");++ // load a jpeg image from whichever source, but leave in YCbCr format+ if (!stbi__decode_jpeg_image(z)) { stbi__cleanup_jpeg(z); return NULL; }++ // determine actual number of components to generate+ n = req_comp ? req_comp : z->s->img_n >= 3 ? 3 : 1;++ is_rgb = z->s->img_n == 3 && (z->rgb == 3 || (z->app14_color_transform == 0 && !z->jfif));++ if (z->s->img_n == 3 && n < 3 && !is_rgb)+ decode_n = 1;+ else+ decode_n = z->s->img_n;++ // nothing to do if no components requested; check this now to avoid+ // accessing uninitialized coutput[0] later+ if (decode_n <= 0) { stbi__cleanup_jpeg(z); return NULL; }++ // resample and color-convert+ {+ int k;+ unsigned int i,j;+ stbi_uc *output;+ stbi_uc *coutput[4] = { NULL, NULL, NULL, NULL };++ stbi__resample res_comp[4];++ for (k=0; k < decode_n; ++k) {+ stbi__resample *r = &res_comp[k];++ // allocate line buffer big enough for upsampling off the edges+ // with upsample factor of 4+ z->img_comp[k].linebuf = (stbi_uc *) stbi__malloc(z->s->img_x + 3);+ if (!z->img_comp[k].linebuf) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); }++ r->hs = z->img_h_max / z->img_comp[k].h;+ r->vs = z->img_v_max / z->img_comp[k].v;+ r->ystep = r->vs >> 1;+ r->w_lores = (z->s->img_x + r->hs-1) / r->hs;+ r->ypos = 0;+ r->line0 = r->line1 = z->img_comp[k].data;++ if (r->hs == 1 && r->vs == 1) r->resample = resample_row_1;+ else if (r->hs == 1 && r->vs == 2) r->resample = stbi__resample_row_v_2;+ else if (r->hs == 2 && r->vs == 1) r->resample = stbi__resample_row_h_2;+ else if (r->hs == 2 && r->vs == 2) r->resample = z->resample_row_hv_2_kernel;+ else r->resample = stbi__resample_row_generic;+ }++ // can't error after this so, this is safe+ output = (stbi_uc *) stbi__malloc_mad3(n, z->s->img_x, z->s->img_y, 1);+ if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); }++ // now go ahead and resample+ for (j=0; j < z->s->img_y; ++j) {+ stbi_uc *out = output + n * z->s->img_x * j;+ for (k=0; k < decode_n; ++k) {+ stbi__resample *r = &res_comp[k];+ int y_bot = r->ystep >= (r->vs >> 1);+ coutput[k] = r->resample(z->img_comp[k].linebuf,+ y_bot ? r->line1 : r->line0,+ y_bot ? r->line0 : r->line1,+ r->w_lores, r->hs);+ if (++r->ystep >= r->vs) {+ r->ystep = 0;+ r->line0 = r->line1;+ if (++r->ypos < z->img_comp[k].y)+ r->line1 += z->img_comp[k].w2;+ }+ }+ if (n >= 3) {+ stbi_uc *y = coutput[0];+ if (z->s->img_n == 3) {+ if (is_rgb) {+ for (i=0; i < z->s->img_x; ++i) {+ out[0] = y[i];+ out[1] = coutput[1][i];+ out[2] = coutput[2][i];+ out[3] = 255;+ out += n;+ }+ } else {+ z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n);+ }+ } else if (z->s->img_n == 4) {+ if (z->app14_color_transform == 0) { // CMYK+ for (i=0; i < z->s->img_x; ++i) {+ stbi_uc m = coutput[3][i];+ out[0] = stbi__blinn_8x8(coutput[0][i], m);+ out[1] = stbi__blinn_8x8(coutput[1][i], m);+ out[2] = stbi__blinn_8x8(coutput[2][i], m);+ out[3] = 255;+ out += n;+ }+ } else if (z->app14_color_transform == 2) { // YCCK+ z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n);+ for (i=0; i < z->s->img_x; ++i) {+ stbi_uc m = coutput[3][i];+ out[0] = stbi__blinn_8x8(255 - out[0], m);+ out[1] = stbi__blinn_8x8(255 - out[1], m);+ out[2] = stbi__blinn_8x8(255 - out[2], m);+ out += n;+ }+ } else { // YCbCr + alpha? Ignore the fourth channel for now+ z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n);+ }+ } else+ for (i=0; i < z->s->img_x; ++i) {+ out[0] = out[1] = out[2] = y[i];+ out[3] = 255; // not used if n==3+ out += n;+ }+ } else {+ if (is_rgb) {+ if (n == 1)+ for (i=0; i < z->s->img_x; ++i)+ *out++ = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]);+ else {+ for (i=0; i < z->s->img_x; ++i, out += 2) {+ out[0] = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]);+ out[1] = 255;+ }+ }+ } else if (z->s->img_n == 4 && z->app14_color_transform == 0) {+ for (i=0; i < z->s->img_x; ++i) {+ stbi_uc m = coutput[3][i];+ stbi_uc r = stbi__blinn_8x8(coutput[0][i], m);+ stbi_uc g = stbi__blinn_8x8(coutput[1][i], m);+ stbi_uc b = stbi__blinn_8x8(coutput[2][i], m);+ out[0] = stbi__compute_y(r, g, b);+ out[1] = 255;+ out += n;+ }+ } else if (z->s->img_n == 4 && z->app14_color_transform == 2) {+ for (i=0; i < z->s->img_x; ++i) {+ out[0] = stbi__blinn_8x8(255 - coutput[0][i], coutput[3][i]);+ out[1] = 255;+ out += n;+ }+ } else {+ stbi_uc *y = coutput[0];+ if (n == 1)+ for (i=0; i < z->s->img_x; ++i) out[i] = y[i];+ else+ for (i=0; i < z->s->img_x; ++i) { *out++ = y[i]; *out++ = 255; }+ }+ }+ }+ stbi__cleanup_jpeg(z);+ *out_x = z->s->img_x;+ *out_y = z->s->img_y;+ if (comp) *comp = z->s->img_n >= 3 ? 3 : 1; // report original components, not output+ return output;+ }+}++static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)+{+ unsigned char* result;+ stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg));+ if (!j) return stbi__errpuc("outofmem", "Out of memory");+ memset(j, 0, sizeof(stbi__jpeg));+ STBI_NOTUSED(ri);+ j->s = s;+ stbi__setup_jpeg(j);+ result = load_jpeg_image(j, x,y,comp,req_comp);+ STBI_FREE(j);+ return result;+}++static int stbi__jpeg_test(stbi__context *s)+{+ int r;+ stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg));+ if (!j) return stbi__err("outofmem", "Out of memory");+ memset(j, 0, sizeof(stbi__jpeg));+ j->s = s;+ stbi__setup_jpeg(j);+ r = stbi__decode_jpeg_header(j, STBI__SCAN_type);+ stbi__rewind(s);+ STBI_FREE(j);+ return r;+}++static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp)+{+ if (!stbi__decode_jpeg_header(j, STBI__SCAN_header)) {+ stbi__rewind( j->s );+ return 0;+ }+ if (x) *x = j->s->img_x;+ if (y) *y = j->s->img_y;+ if (comp) *comp = j->s->img_n >= 3 ? 3 : 1;+ return 1;+}++static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp)+{+ int result;+ stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg)));+ if (!j) return stbi__err("outofmem", "Out of memory");+ memset(j, 0, sizeof(stbi__jpeg));+ j->s = s;+ result = stbi__jpeg_info_raw(j, x, y, comp);+ STBI_FREE(j);+ return result;+}+#endif++// public domain zlib decode v0.2 Sean Barrett 2006-11-18+// simple implementation+// - all input must be provided in an upfront buffer+// - all output is written to a single output buffer (can malloc/realloc)+// performance+// - fast huffman++#ifndef STBI_NO_ZLIB++// fast-way is faster to check than jpeg huffman, but slow way is slower+#define STBI__ZFAST_BITS 9 // accelerate all cases in default tables+#define STBI__ZFAST_MASK ((1 << STBI__ZFAST_BITS) - 1)+#define STBI__ZNSYMS 288 // number of symbols in literal/length alphabet++// zlib-style huffman encoding+// (jpegs packs from left, zlib from right, so can't share code)+typedef struct+{+ stbi__uint16 fast[1 << STBI__ZFAST_BITS];+ stbi__uint16 firstcode[16];+ int maxcode[17];+ stbi__uint16 firstsymbol[16];+ stbi_uc size[STBI__ZNSYMS];+ stbi__uint16 value[STBI__ZNSYMS];+} stbi__zhuffman;++stbi_inline static int stbi__bitreverse16(int n)+{+ n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1);+ n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2);+ n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4);+ n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8);+ return n;+}++stbi_inline static int stbi__bit_reverse(int v, int bits)+{+ STBI_ASSERT(bits <= 16);+ // to bit reverse n bits, reverse 16 and shift+ // e.g. 11 bits, bit reverse and shift away 5+ return stbi__bitreverse16(v) >> (16-bits);+}++static int stbi__zbuild_huffman(stbi__zhuffman *z, const stbi_uc *sizelist, int num)+{+ int i,k=0;+ int code, next_code[16], sizes[17];++ // DEFLATE spec for generating codes+ memset(sizes, 0, sizeof(sizes));+ memset(z->fast, 0, sizeof(z->fast));+ for (i=0; i < num; ++i)+ ++sizes[sizelist[i]];+ sizes[0] = 0;+ for (i=1; i < 16; ++i)+ if (sizes[i] > (1 << i))+ return stbi__err("bad sizes", "Corrupt PNG");+ code = 0;+ for (i=1; i < 16; ++i) {+ next_code[i] = code;+ z->firstcode[i] = (stbi__uint16) code;+ z->firstsymbol[i] = (stbi__uint16) k;+ code = (code + sizes[i]);+ if (sizes[i])+ if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt PNG");+ z->maxcode[i] = code << (16-i); // preshift for inner loop+ code <<= 1;+ k += sizes[i];+ }+ z->maxcode[16] = 0x10000; // sentinel+ for (i=0; i < num; ++i) {+ int s = sizelist[i];+ if (s) {+ int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s];+ stbi__uint16 fastv = (stbi__uint16) ((s << 9) | i);+ z->size [c] = (stbi_uc ) s;+ z->value[c] = (stbi__uint16) i;+ if (s <= STBI__ZFAST_BITS) {+ int j = stbi__bit_reverse(next_code[s],s);+ while (j < (1 << STBI__ZFAST_BITS)) {+ z->fast[j] = fastv;+ j += (1 << s);+ }+ }+ ++next_code[s];+ }+ }+ return 1;+}++// zlib-from-memory implementation for PNG reading+// because PNG allows splitting the zlib stream arbitrarily,+// and it's annoying structurally to have PNG call ZLIB call PNG,+// we require PNG read all the IDATs and combine them into a single+// memory buffer++typedef struct+{+ stbi_uc *zbuffer, *zbuffer_end;+ int num_bits;+ int hit_zeof_once;+ stbi__uint32 code_buffer;++ char *zout;+ char *zout_start;+ char *zout_end;+ int z_expandable;++ stbi__zhuffman z_length, z_distance;+} stbi__zbuf;++stbi_inline static int stbi__zeof(stbi__zbuf *z)+{+ return (z->zbuffer >= z->zbuffer_end);+}++stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z)+{+ return stbi__zeof(z) ? 0 : *z->zbuffer++;+}++static void stbi__fill_bits(stbi__zbuf *z)+{+ do {+ if (z->code_buffer >= (1U << z->num_bits)) {+ z->zbuffer = z->zbuffer_end; /* treat this as EOF so we fail. */+ return;+ }+ z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits;+ z->num_bits += 8;+ } while (z->num_bits <= 24);+}++stbi_inline static unsigned int stbi__zreceive(stbi__zbuf *z, int n)+{+ unsigned int k;+ if (z->num_bits < n) stbi__fill_bits(z);+ k = z->code_buffer & ((1 << n) - 1);+ z->code_buffer >>= n;+ z->num_bits -= n;+ return k;+}++static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z)+{+ int b,s,k;+ // not resolved by fast table, so compute it the slow way+ // use jpeg approach, which requires MSbits at top+ k = stbi__bit_reverse(a->code_buffer, 16);+ for (s=STBI__ZFAST_BITS+1; ; ++s)+ if (k < z->maxcode[s])+ break;+ if (s >= 16) return -1; // invalid code!+ // code size is s, so:+ b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s];+ if (b >= STBI__ZNSYMS) return -1; // some data was corrupt somewhere!+ if (z->size[b] != s) return -1; // was originally an assert, but report failure instead.+ a->code_buffer >>= s;+ a->num_bits -= s;+ return z->value[b];+}++stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z)+{+ int b,s;+ if (a->num_bits < 16) {+ if (stbi__zeof(a)) {+ if (!a->hit_zeof_once) {+ // This is the first time we hit eof, insert 16 extra padding btis+ // to allow us to keep going; if we actually consume any of them+ // though, that is invalid data. This is caught later.+ a->hit_zeof_once = 1;+ a->num_bits += 16; // add 16 implicit zero bits+ } else {+ // We already inserted our extra 16 padding bits and are again+ // out, this stream is actually prematurely terminated.+ return -1;+ }+ } else {+ stbi__fill_bits(a);+ }+ }+ b = z->fast[a->code_buffer & STBI__ZFAST_MASK];+ if (b) {+ s = b >> 9;+ a->code_buffer >>= s;+ a->num_bits -= s;+ return b & 511;+ }+ return stbi__zhuffman_decode_slowpath(a, z);+}++static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes+{+ char *q;+ unsigned int cur, limit, old_limit;+ z->zout = zout;+ if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG");+ cur = (unsigned int) (z->zout - z->zout_start);+ limit = old_limit = (unsigned) (z->zout_end - z->zout_start);+ if (UINT_MAX - cur < (unsigned) n) return stbi__err("outofmem", "Out of memory");+ while (cur + n > limit) {+ if(limit > UINT_MAX / 2) return stbi__err("outofmem", "Out of memory");+ limit *= 2;+ }+ q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit);+ STBI_NOTUSED(old_limit);+ if (q == NULL) return stbi__err("outofmem", "Out of memory");+ z->zout_start = q;+ z->zout = q + cur;+ z->zout_end = q + limit;+ return 1;+}++static const int stbi__zlength_base[31] = {+ 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 };++static const int stbi__zlength_extra[31]=+{ 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,0,0 };++static const int stbi__zdist_base[32] = { 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,0,0};++static const int stbi__zdist_extra[32] =+{ 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};++static int stbi__parse_huffman_block(stbi__zbuf *a)+{+ char *zout = a->zout;+ for(;;) {+ int z = stbi__zhuffman_decode(a, &a->z_length);+ if (z < 256) {+ if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); // error in huffman codes+ if (zout >= a->zout_end) {+ if (!stbi__zexpand(a, zout, 1)) return 0;+ zout = a->zout;+ }+ *zout++ = (char) z;+ } else {+ stbi_uc *p;+ int len,dist;+ if (z == 256) {+ a->zout = zout;+ if (a->hit_zeof_once && a->num_bits < 16) {+ // The first time we hit zeof, we inserted 16 extra zero bits into our bit+ // buffer so the decoder can just do its speculative decoding. But if we+ // actually consumed any of those bits (which is the case when num_bits < 16),+ // the stream actually read past the end so it is malformed.+ return stbi__err("unexpected end","Corrupt PNG");+ }+ return 1;+ }+ if (z >= 286) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, length codes 286 and 287 must not appear in compressed data+ z -= 257;+ len = stbi__zlength_base[z];+ if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]);+ z = stbi__zhuffman_decode(a, &a->z_distance);+ if (z < 0 || z >= 30) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, distance codes 30 and 31 must not appear in compressed data+ dist = stbi__zdist_base[z];+ if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]);+ if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG");+ if (len > a->zout_end - zout) {+ if (!stbi__zexpand(a, zout, len)) return 0;+ zout = a->zout;+ }+ p = (stbi_uc *) (zout - dist);+ if (dist == 1) { // run of one byte; common in images.+ stbi_uc v = *p;+ if (len) { do *zout++ = v; while (--len); }+ } else {+ if (len) { do *zout++ = *p++; while (--len); }+ }+ }+ }+}++static int stbi__compute_huffman_codes(stbi__zbuf *a)+{+ static const stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 };+ stbi__zhuffman z_codelength;+ stbi_uc lencodes[286+32+137];//padding for maximum single op+ stbi_uc codelength_sizes[19];+ int i,n;++ int hlit = stbi__zreceive(a,5) + 257;+ int hdist = stbi__zreceive(a,5) + 1;+ int hclen = stbi__zreceive(a,4) + 4;+ int ntot = hlit + hdist;++ memset(codelength_sizes, 0, sizeof(codelength_sizes));+ for (i=0; i < hclen; ++i) {+ int s = stbi__zreceive(a,3);+ codelength_sizes[length_dezigzag[i]] = (stbi_uc) s;+ }+ if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0;++ n = 0;+ while (n < ntot) {+ int c = stbi__zhuffman_decode(a, &z_codelength);+ if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG");+ if (c < 16)+ lencodes[n++] = (stbi_uc) c;+ else {+ stbi_uc fill = 0;+ if (c == 16) {+ c = stbi__zreceive(a,2)+3;+ if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG");+ fill = lencodes[n-1];+ } else if (c == 17) {+ c = stbi__zreceive(a,3)+3;+ } else if (c == 18) {+ c = stbi__zreceive(a,7)+11;+ } else {+ return stbi__err("bad codelengths", "Corrupt PNG");+ }+ if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG");+ memset(lencodes+n, fill, c);+ n += c;+ }+ }+ if (n != ntot) return stbi__err("bad codelengths","Corrupt PNG");+ if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0;+ if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0;+ return 1;+}++static int stbi__parse_uncompressed_block(stbi__zbuf *a)+{+ stbi_uc header[4];+ int len,nlen,k;+ if (a->num_bits & 7)+ stbi__zreceive(a, a->num_bits & 7); // discard+ // drain the bit-packed data into header+ k = 0;+ while (a->num_bits > 0) {+ header[k++] = (stbi_uc) (a->code_buffer & 255); // suppress MSVC run-time check+ a->code_buffer >>= 8;+ a->num_bits -= 8;+ }+ if (a->num_bits < 0) return stbi__err("zlib corrupt","Corrupt PNG");+ // now fill header the normal way+ while (k < 4)+ header[k++] = stbi__zget8(a);+ len = header[1] * 256 + header[0];+ nlen = header[3] * 256 + header[2];+ if (nlen != (len ^ 0xffff)) return stbi__err("zlib corrupt","Corrupt PNG");+ if (a->zbuffer + len > a->zbuffer_end) return stbi__err("read past buffer","Corrupt PNG");+ if (a->zout + len > a->zout_end)+ if (!stbi__zexpand(a, a->zout, len)) return 0;+ memcpy(a->zout, a->zbuffer, len);+ a->zbuffer += len;+ a->zout += len;+ return 1;+}++static int stbi__parse_zlib_header(stbi__zbuf *a)+{+ int cmf = stbi__zget8(a);+ int cm = cmf & 15;+ /* int cinfo = cmf >> 4; */+ int flg = stbi__zget8(a);+ if (stbi__zeof(a)) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec+ if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec+ if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png+ if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); // DEFLATE required for png+ // window = 1 << (8 + cinfo)... but who cares, we fully buffer output+ return 1;+}++static const stbi_uc stbi__zdefault_length[STBI__ZNSYMS] =+{+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,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,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,+ 9,9,9,9,9,9,9,9,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,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8+};+static const stbi_uc stbi__zdefault_distance[32] =+{+ 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+};+/*+Init algorithm:+{+ int i; // use <= to match clearly with spec+ for (i=0; i <= 143; ++i) stbi__zdefault_length[i] = 8;+ for ( ; i <= 255; ++i) stbi__zdefault_length[i] = 9;+ for ( ; i <= 279; ++i) stbi__zdefault_length[i] = 7;+ for ( ; i <= 287; ++i) stbi__zdefault_length[i] = 8;++ for (i=0; i <= 31; ++i) stbi__zdefault_distance[i] = 5;+}+*/++static int stbi__parse_zlib(stbi__zbuf *a, int parse_header)+{+ int final, type;+ if (parse_header)+ if (!stbi__parse_zlib_header(a)) return 0;+ a->num_bits = 0;+ a->code_buffer = 0;+ a->hit_zeof_once = 0;+ do {+ final = stbi__zreceive(a,1);+ type = stbi__zreceive(a,2);+ if (type == 0) {+ if (!stbi__parse_uncompressed_block(a)) return 0;+ } else if (type == 3) {+ return 0;+ } else {+ if (type == 1) {+ // use fixed code lengths+ if (!stbi__zbuild_huffman(&a->z_length , stbi__zdefault_length , STBI__ZNSYMS)) return 0;+ if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance, 32)) return 0;+ } else {+ if (!stbi__compute_huffman_codes(a)) return 0;+ }+ if (!stbi__parse_huffman_block(a)) return 0;+ }+ } while (!final);+ return 1;+}++static int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse_header)+{+ a->zout_start = obuf;+ a->zout = obuf;+ a->zout_end = obuf + olen;+ a->z_expandable = exp;++ return stbi__parse_zlib(a, parse_header);+}++STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen)+{+ stbi__zbuf a;+ char *p = (char *) stbi__malloc(initial_size);+ if (p == NULL) return NULL;+ a.zbuffer = (stbi_uc *) buffer;+ a.zbuffer_end = (stbi_uc *) buffer + len;+ if (stbi__do_zlib(&a, p, initial_size, 1, 1)) {+ if (outlen) *outlen = (int) (a.zout - a.zout_start);+ return a.zout_start;+ } else {+ STBI_FREE(a.zout_start);+ return NULL;+ }+}++STBIDEF char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen)+{+ return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen);+}++STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header)+{+ stbi__zbuf a;+ char *p = (char *) stbi__malloc(initial_size);+ if (p == NULL) return NULL;+ a.zbuffer = (stbi_uc *) buffer;+ a.zbuffer_end = (stbi_uc *) buffer + len;+ if (stbi__do_zlib(&a, p, initial_size, 1, parse_header)) {+ if (outlen) *outlen = (int) (a.zout - a.zout_start);+ return a.zout_start;+ } else {+ STBI_FREE(a.zout_start);+ return NULL;+ }+}++STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen)+{+ stbi__zbuf a;+ a.zbuffer = (stbi_uc *) ibuffer;+ a.zbuffer_end = (stbi_uc *) ibuffer + ilen;+ if (stbi__do_zlib(&a, obuffer, olen, 0, 1))+ return (int) (a.zout - a.zout_start);+ else+ return -1;+}++STBIDEF char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen)+{+ stbi__zbuf a;+ char *p = (char *) stbi__malloc(16384);+ if (p == NULL) return NULL;+ a.zbuffer = (stbi_uc *) buffer;+ a.zbuffer_end = (stbi_uc *) buffer+len;+ if (stbi__do_zlib(&a, p, 16384, 1, 0)) {+ if (outlen) *outlen = (int) (a.zout - a.zout_start);+ return a.zout_start;+ } else {+ STBI_FREE(a.zout_start);+ return NULL;+ }+}++STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen)+{+ stbi__zbuf a;+ a.zbuffer = (stbi_uc *) ibuffer;+ a.zbuffer_end = (stbi_uc *) ibuffer + ilen;+ if (stbi__do_zlib(&a, obuffer, olen, 0, 0))+ return (int) (a.zout - a.zout_start);+ else+ return -1;+}+#endif++// public domain "baseline" PNG decoder v0.10 Sean Barrett 2006-11-18+// simple implementation+// - only 8-bit samples+// - no CRC checking+// - allocates lots of intermediate memory+// - avoids problem of streaming data between subsystems+// - avoids explicit window management+// performance+// - uses stb_zlib, a PD zlib implementation with fast huffman decoding++#ifndef STBI_NO_PNG+typedef struct+{+ stbi__uint32 length;+ stbi__uint32 type;+} stbi__pngchunk;++static stbi__pngchunk stbi__get_chunk_header(stbi__context *s)+{+ stbi__pngchunk c;+ c.length = stbi__get32be(s);+ c.type = stbi__get32be(s);+ return c;+}++static int stbi__check_png_header(stbi__context *s)+{+ static const stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 };+ int i;+ for (i=0; i < 8; ++i)+ if (stbi__get8(s) != png_sig[i]) return stbi__err("bad png sig","Not a PNG");+ return 1;+}++typedef struct+{+ stbi__context *s;+ stbi_uc *idata, *expanded, *out;+ int depth;+} stbi__png;+++enum {+ STBI__F_none=0,+ STBI__F_sub=1,+ STBI__F_up=2,+ STBI__F_avg=3,+ STBI__F_paeth=4,+ // synthetic filter used for first scanline to avoid needing a dummy row of 0s+ STBI__F_avg_first+};++static stbi_uc first_row_filter[5] =+{+ STBI__F_none,+ STBI__F_sub,+ STBI__F_none,+ STBI__F_avg_first,+ STBI__F_sub // Paeth with b=c=0 turns out to be equivalent to sub+};++static int stbi__paeth(int a, int b, int c)+{+ // This formulation looks very different from the reference in the PNG spec, but is+ // actually equivalent and has favorable data dependencies and admits straightforward+ // generation of branch-free code, which helps performance significantly.+ int thresh = c*3 - (a + b);+ int lo = a < b ? a : b;+ int hi = a < b ? b : a;+ int t0 = (hi <= thresh) ? lo : c;+ int t1 = (thresh <= lo) ? hi : t0;+ return t1;+}++static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 };++// adds an extra all-255 alpha channel+// dest == src is legal+// img_n must be 1 or 3+static void stbi__create_png_alpha_expand8(stbi_uc *dest, stbi_uc *src, stbi__uint32 x, int img_n)+{+ int i;+ // must process data backwards since we allow dest==src+ if (img_n == 1) {+ for (i=x-1; i >= 0; --i) {+ dest[i*2+1] = 255;+ dest[i*2+0] = src[i];+ }+ } else {+ STBI_ASSERT(img_n == 3);+ for (i=x-1; i >= 0; --i) {+ dest[i*4+3] = 255;+ dest[i*4+2] = src[i*3+2];+ dest[i*4+1] = src[i*3+1];+ dest[i*4+0] = src[i*3+0];+ }+ }+}++// create the png data from post-deflated data+static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color)+{+ int bytes = (depth == 16 ? 2 : 1);+ stbi__context *s = a->s;+ stbi__uint32 i,j,stride = x*out_n*bytes;+ stbi__uint32 img_len, img_width_bytes;+ stbi_uc *filter_buf;+ int all_ok = 1;+ int k;+ int img_n = s->img_n; // copy it into a local for later++ int output_bytes = out_n*bytes;+ int filter_bytes = img_n*bytes;+ int width = x;++ STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1);+ a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into+ if (!a->out) return stbi__err("outofmem", "Out of memory");++ // note: error exits here don't need to clean up a->out individually,+ // stbi__do_png always does on error.+ if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG");+ img_width_bytes = (((img_n * x * depth) + 7) >> 3);+ if (!stbi__mad2sizes_valid(img_width_bytes, y, img_width_bytes)) return stbi__err("too large", "Corrupt PNG");+ img_len = (img_width_bytes + 1) * y;++ // we used to check for exact match between raw_len and img_len on non-interlaced PNGs,+ // but issue #276 reported a PNG in the wild that had extra data at the end (all zeros),+ // so just check for raw_len < img_len always.+ if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG");++ // Allocate two scan lines worth of filter workspace buffer.+ filter_buf = (stbi_uc *) stbi__malloc_mad2(img_width_bytes, 2, 0);+ if (!filter_buf) return stbi__err("outofmem", "Out of memory");++ // Filtering for low-bit-depth images+ if (depth < 8) {+ filter_bytes = 1;+ width = img_width_bytes;+ }++ for (j=0; j < y; ++j) {+ // cur/prior filter buffers alternate+ stbi_uc *cur = filter_buf + (j & 1)*img_width_bytes;+ stbi_uc *prior = filter_buf + (~j & 1)*img_width_bytes;+ stbi_uc *dest = a->out + stride*j;+ int nk = width * filter_bytes;+ int filter = *raw++;++ // check filter type+ if (filter > 4) {+ all_ok = stbi__err("invalid filter","Corrupt PNG");+ break;+ }++ // if first row, use special filter that doesn't sample previous row+ if (j == 0) filter = first_row_filter[filter];++ // perform actual filtering+ switch (filter) {+ case STBI__F_none:+ memcpy(cur, raw, nk);+ break;+ case STBI__F_sub:+ memcpy(cur, raw, filter_bytes);+ for (k = filter_bytes; k < nk; ++k)+ cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]);+ break;+ case STBI__F_up:+ for (k = 0; k < nk; ++k)+ cur[k] = STBI__BYTECAST(raw[k] + prior[k]);+ break;+ case STBI__F_avg:+ for (k = 0; k < filter_bytes; ++k)+ cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1));+ for (k = filter_bytes; k < nk; ++k)+ cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1));+ break;+ case STBI__F_paeth:+ for (k = 0; k < filter_bytes; ++k)+ cur[k] = STBI__BYTECAST(raw[k] + prior[k]); // prior[k] == stbi__paeth(0,prior[k],0)+ for (k = filter_bytes; k < nk; ++k)+ cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes], prior[k], prior[k-filter_bytes]));+ break;+ case STBI__F_avg_first:+ memcpy(cur, raw, filter_bytes);+ for (k = filter_bytes; k < nk; ++k)+ cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1));+ break;+ }++ raw += nk;++ // expand decoded bits in cur to dest, also adding an extra alpha channel if desired+ if (depth < 8) {+ stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range+ stbi_uc *in = cur;+ stbi_uc *out = dest;+ stbi_uc inb = 0;+ stbi__uint32 nsmp = x*img_n;++ // expand bits to bytes first+ if (depth == 4) {+ for (i=0; i < nsmp; ++i) {+ if ((i & 1) == 0) inb = *in++;+ *out++ = scale * (inb >> 4);+ inb <<= 4;+ }+ } else if (depth == 2) {+ for (i=0; i < nsmp; ++i) {+ if ((i & 3) == 0) inb = *in++;+ *out++ = scale * (inb >> 6);+ inb <<= 2;+ }+ } else {+ STBI_ASSERT(depth == 1);+ for (i=0; i < nsmp; ++i) {+ if ((i & 7) == 0) inb = *in++;+ *out++ = scale * (inb >> 7);+ inb <<= 1;+ }+ }++ // insert alpha=255 values if desired+ if (img_n != out_n)+ stbi__create_png_alpha_expand8(dest, dest, x, img_n);+ } else if (depth == 8) {+ if (img_n == out_n)+ memcpy(dest, cur, x*img_n);+ else+ stbi__create_png_alpha_expand8(dest, cur, x, img_n);+ } else if (depth == 16) {+ // convert the image data from big-endian to platform-native+ stbi__uint16 *dest16 = (stbi__uint16*)dest;+ stbi__uint32 nsmp = x*img_n;++ if (img_n == out_n) {+ for (i = 0; i < nsmp; ++i, ++dest16, cur += 2)+ *dest16 = (cur[0] << 8) | cur[1];+ } else {+ STBI_ASSERT(img_n+1 == out_n);+ if (img_n == 1) {+ for (i = 0; i < x; ++i, dest16 += 2, cur += 2) {+ dest16[0] = (cur[0] << 8) | cur[1];+ dest16[1] = 0xffff;+ }+ } else {+ STBI_ASSERT(img_n == 3);+ for (i = 0; i < x; ++i, dest16 += 4, cur += 6) {+ dest16[0] = (cur[0] << 8) | cur[1];+ dest16[1] = (cur[2] << 8) | cur[3];+ dest16[2] = (cur[4] << 8) | cur[5];+ dest16[3] = 0xffff;+ }+ }+ }+ }+ }++ STBI_FREE(filter_buf);+ if (!all_ok) return 0;++ return 1;+}++static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced)+{+ int bytes = (depth == 16 ? 2 : 1);+ int out_bytes = out_n * bytes;+ stbi_uc *final;+ int p;+ if (!interlaced)+ return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color);++ // de-interlacing+ final = (stbi_uc *) stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0);+ if (!final) return stbi__err("outofmem", "Out of memory");+ for (p=0; p < 7; ++p) {+ int xorig[] = { 0,4,0,2,0,1,0 };+ int yorig[] = { 0,0,4,0,2,0,1 };+ int xspc[] = { 8,8,4,4,2,2,1 };+ int yspc[] = { 8,8,8,4,4,2,2 };+ int i,j,x,y;+ // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1+ x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p];+ y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p];+ if (x && y) {+ stbi__uint32 img_len = ((((a->s->img_n * x * depth) + 7) >> 3) + 1) * y;+ if (!stbi__create_png_image_raw(a, image_data, image_data_len, out_n, x, y, depth, color)) {+ STBI_FREE(final);+ return 0;+ }+ for (j=0; j < y; ++j) {+ for (i=0; i < x; ++i) {+ int out_y = j*yspc[p]+yorig[p];+ int out_x = i*xspc[p]+xorig[p];+ memcpy(final + out_y*a->s->img_x*out_bytes + out_x*out_bytes,+ a->out + (j*x+i)*out_bytes, out_bytes);+ }+ }+ STBI_FREE(a->out);+ image_data += img_len;+ image_data_len -= img_len;+ }+ }+ a->out = final;++ return 1;+}++static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n)+{+ stbi__context *s = z->s;+ stbi__uint32 i, pixel_count = s->img_x * s->img_y;+ stbi_uc *p = z->out;++ // compute color-based transparency, assuming we've+ // already got 255 as the alpha value in the output+ STBI_ASSERT(out_n == 2 || out_n == 4);++ if (out_n == 2) {+ for (i=0; i < pixel_count; ++i) {+ p[1] = (p[0] == tc[0] ? 0 : 255);+ p += 2;+ }+ } else {+ for (i=0; i < pixel_count; ++i) {+ if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2])+ p[3] = 0;+ p += 4;+ }+ }+ return 1;+}++static int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int out_n)+{+ stbi__context *s = z->s;+ stbi__uint32 i, pixel_count = s->img_x * s->img_y;+ stbi__uint16 *p = (stbi__uint16*) z->out;++ // compute color-based transparency, assuming we've+ // already got 65535 as the alpha value in the output+ STBI_ASSERT(out_n == 2 || out_n == 4);++ if (out_n == 2) {+ for (i = 0; i < pixel_count; ++i) {+ p[1] = (p[0] == tc[0] ? 0 : 65535);+ p += 2;+ }+ } else {+ for (i = 0; i < pixel_count; ++i) {+ if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2])+ p[3] = 0;+ p += 4;+ }+ }+ return 1;+}++static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n)+{+ stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y;+ stbi_uc *p, *temp_out, *orig = a->out;++ p = (stbi_uc *) stbi__malloc_mad2(pixel_count, pal_img_n, 0);+ if (p == NULL) return stbi__err("outofmem", "Out of memory");++ // between here and free(out) below, exitting would leak+ temp_out = p;++ if (pal_img_n == 3) {+ for (i=0; i < pixel_count; ++i) {+ int n = orig[i]*4;+ p[0] = palette[n ];+ p[1] = palette[n+1];+ p[2] = palette[n+2];+ p += 3;+ }+ } else {+ for (i=0; i < pixel_count; ++i) {+ int n = orig[i]*4;+ p[0] = palette[n ];+ p[1] = palette[n+1];+ p[2] = palette[n+2];+ p[3] = palette[n+3];+ p += 4;+ }+ }+ STBI_FREE(a->out);+ a->out = temp_out;++ STBI_NOTUSED(len);++ return 1;+}++static int stbi__unpremultiply_on_load_global = 0;+static int stbi__de_iphone_flag_global = 0;++STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply)+{+ stbi__unpremultiply_on_load_global = flag_true_if_should_unpremultiply;+}++STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert)+{+ stbi__de_iphone_flag_global = flag_true_if_should_convert;+}++#ifndef STBI_THREAD_LOCAL+#define stbi__unpremultiply_on_load stbi__unpremultiply_on_load_global+#define stbi__de_iphone_flag stbi__de_iphone_flag_global+#else+static STBI_THREAD_LOCAL int stbi__unpremultiply_on_load_local, stbi__unpremultiply_on_load_set;+static STBI_THREAD_LOCAL int stbi__de_iphone_flag_local, stbi__de_iphone_flag_set;++STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply)+{+ stbi__unpremultiply_on_load_local = flag_true_if_should_unpremultiply;+ stbi__unpremultiply_on_load_set = 1;+}++STBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert)+{+ stbi__de_iphone_flag_local = flag_true_if_should_convert;+ stbi__de_iphone_flag_set = 1;+}++#define stbi__unpremultiply_on_load (stbi__unpremultiply_on_load_set \+ ? stbi__unpremultiply_on_load_local \+ : stbi__unpremultiply_on_load_global)+#define stbi__de_iphone_flag (stbi__de_iphone_flag_set \+ ? stbi__de_iphone_flag_local \+ : stbi__de_iphone_flag_global)+#endif // STBI_THREAD_LOCAL++static void stbi__de_iphone(stbi__png *z)+{+ stbi__context *s = z->s;+ stbi__uint32 i, pixel_count = s->img_x * s->img_y;+ stbi_uc *p = z->out;++ if (s->img_out_n == 3) { // convert bgr to rgb+ for (i=0; i < pixel_count; ++i) {+ stbi_uc t = p[0];+ p[0] = p[2];+ p[2] = t;+ p += 3;+ }+ } else {+ STBI_ASSERT(s->img_out_n == 4);+ if (stbi__unpremultiply_on_load) {+ // convert bgr to rgb and unpremultiply+ for (i=0; i < pixel_count; ++i) {+ stbi_uc a = p[3];+ stbi_uc t = p[0];+ if (a) {+ stbi_uc half = a / 2;+ p[0] = (p[2] * 255 + half) / a;+ p[1] = (p[1] * 255 + half) / a;+ p[2] = ( t * 255 + half) / a;+ } else {+ p[0] = p[2];+ p[2] = t;+ }+ p += 4;+ }+ } else {+ // convert bgr to rgb+ for (i=0; i < pixel_count; ++i) {+ stbi_uc t = p[0];+ p[0] = p[2];+ p[2] = t;+ p += 4;+ }+ }+ }+}++#define STBI__PNG_TYPE(a,b,c,d) (((unsigned) (a) << 24) + ((unsigned) (b) << 16) + ((unsigned) (c) << 8) + (unsigned) (d))++static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)+{+ stbi_uc palette[1024], pal_img_n=0;+ stbi_uc has_trans=0, tc[3]={0};+ stbi__uint16 tc16[3];+ stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0;+ int first=1,k,interlace=0, color=0, is_iphone=0;+ stbi__context *s = z->s;++ z->expanded = NULL;+ z->idata = NULL;+ z->out = NULL;++ if (!stbi__check_png_header(s)) return 0;++ if (scan == STBI__SCAN_type) return 1;++ for (;;) {+ stbi__pngchunk c = stbi__get_chunk_header(s);+ switch (c.type) {+ case STBI__PNG_TYPE('C','g','B','I'):+ is_iphone = 1;+ stbi__skip(s, c.length);+ break;+ case STBI__PNG_TYPE('I','H','D','R'): {+ int comp,filter;+ if (!first) return stbi__err("multiple IHDR","Corrupt PNG");+ first = 0;+ if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG");+ s->img_x = stbi__get32be(s);+ s->img_y = stbi__get32be(s);+ if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");+ if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");+ z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only");+ color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG");+ if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG");+ if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG");+ comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG");+ filter= stbi__get8(s); if (filter) return stbi__err("bad filter method","Corrupt PNG");+ interlace = stbi__get8(s); if (interlace>1) return stbi__err("bad interlace method","Corrupt PNG");+ if (!s->img_x || !s->img_y) return stbi__err("0-pixel image","Corrupt PNG");+ if (!pal_img_n) {+ s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0);+ if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode");+ } else {+ // if paletted, then pal_n is our final components, and+ // img_n is # components to decompress/filter.+ s->img_n = 1;+ if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG");+ }+ // even with SCAN_header, have to scan to see if we have a tRNS+ break;+ }++ case STBI__PNG_TYPE('P','L','T','E'): {+ if (first) return stbi__err("first not IHDR", "Corrupt PNG");+ if (c.length > 256*3) return stbi__err("invalid PLTE","Corrupt PNG");+ pal_len = c.length / 3;+ if (pal_len * 3 != c.length) return stbi__err("invalid PLTE","Corrupt PNG");+ for (i=0; i < pal_len; ++i) {+ palette[i*4+0] = stbi__get8(s);+ palette[i*4+1] = stbi__get8(s);+ palette[i*4+2] = stbi__get8(s);+ palette[i*4+3] = 255;+ }+ break;+ }++ case STBI__PNG_TYPE('t','R','N','S'): {+ if (first) return stbi__err("first not IHDR", "Corrupt PNG");+ if (z->idata) return stbi__err("tRNS after IDAT","Corrupt PNG");+ if (pal_img_n) {+ if (scan == STBI__SCAN_header) { s->img_n = 4; return 1; }+ if (pal_len == 0) return stbi__err("tRNS before PLTE","Corrupt PNG");+ if (c.length > pal_len) return stbi__err("bad tRNS len","Corrupt PNG");+ pal_img_n = 4;+ for (i=0; i < c.length; ++i)+ palette[i*4+3] = stbi__get8(s);+ } else {+ if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG");+ if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG");+ has_trans = 1;+ // non-paletted with tRNS = constant alpha. if header-scanning, we can stop now.+ if (scan == STBI__SCAN_header) { ++s->img_n; return 1; }+ if (z->depth == 16) {+ for (k = 0; k < s->img_n; ++k) tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is+ } else {+ for (k = 0; k < s->img_n; ++k) tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger+ }+ }+ break;+ }++ case STBI__PNG_TYPE('I','D','A','T'): {+ if (first) return stbi__err("first not IHDR", "Corrupt PNG");+ if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG");+ if (scan == STBI__SCAN_header) {+ // header scan definitely stops at first IDAT+ if (pal_img_n)+ s->img_n = pal_img_n;+ return 1;+ }+ if (c.length > (1u << 30)) return stbi__err("IDAT size limit", "IDAT section larger than 2^30 bytes");+ if ((int)(ioff + c.length) < (int)ioff) return 0;+ if (ioff + c.length > idata_limit) {+ stbi__uint32 idata_limit_old = idata_limit;+ stbi_uc *p;+ if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096;+ while (ioff + c.length > idata_limit)+ idata_limit *= 2;+ STBI_NOTUSED(idata_limit_old);+ p = (stbi_uc *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory");+ z->idata = p;+ }+ if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG");+ ioff += c.length;+ break;+ }++ case STBI__PNG_TYPE('I','E','N','D'): {+ stbi__uint32 raw_len, bpl;+ if (first) return stbi__err("first not IHDR", "Corrupt PNG");+ if (scan != STBI__SCAN_load) return 1;+ if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG");+ // initial guess for decoded data size to avoid unnecessary reallocs+ bpl = (s->img_x * z->depth + 7) / 8; // bytes per line, per component+ raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */;+ z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone);+ if (z->expanded == NULL) return 0; // zlib should set error+ STBI_FREE(z->idata); z->idata = NULL;+ if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans)+ s->img_out_n = s->img_n+1;+ else+ s->img_out_n = s->img_n;+ if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace)) return 0;+ if (has_trans) {+ if (z->depth == 16) {+ if (!stbi__compute_transparency16(z, tc16, s->img_out_n)) return 0;+ } else {+ if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0;+ }+ }+ if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2)+ stbi__de_iphone(z);+ if (pal_img_n) {+ // pal_img_n == 3 or 4+ s->img_n = pal_img_n; // record the actual colors we had+ s->img_out_n = pal_img_n;+ if (req_comp >= 3) s->img_out_n = req_comp;+ if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n))+ return 0;+ } else if (has_trans) {+ // non-paletted image with tRNS -> source image has (constant) alpha+ ++s->img_n;+ }+ STBI_FREE(z->expanded); z->expanded = NULL;+ // end of PNG chunk, read and skip CRC+ stbi__get32be(s);+ return 1;+ }++ default:+ // if critical, fail+ if (first) return stbi__err("first not IHDR", "Corrupt PNG");+ if ((c.type & (1 << 29)) == 0) {+ #ifndef STBI_NO_FAILURE_STRINGS+ // not threadsafe+ static char invalid_chunk[] = "XXXX PNG chunk not known";+ invalid_chunk[0] = STBI__BYTECAST(c.type >> 24);+ invalid_chunk[1] = STBI__BYTECAST(c.type >> 16);+ invalid_chunk[2] = STBI__BYTECAST(c.type >> 8);+ invalid_chunk[3] = STBI__BYTECAST(c.type >> 0);+ #endif+ return stbi__err(invalid_chunk, "PNG not supported: unknown PNG chunk type");+ }+ stbi__skip(s, c.length);+ break;+ }+ // end of PNG chunk, read and skip CRC+ stbi__get32be(s);+ }+}++static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, stbi__result_info *ri)+{+ void *result=NULL;+ if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error");+ if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) {+ if (p->depth <= 8)+ ri->bits_per_channel = 8;+ else if (p->depth == 16)+ ri->bits_per_channel = 16;+ else+ return stbi__errpuc("bad bits_per_channel", "PNG not supported: unsupported color depth");+ result = p->out;+ p->out = NULL;+ if (req_comp && req_comp != p->s->img_out_n) {+ if (ri->bits_per_channel == 8)+ result = stbi__convert_format((unsigned char *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y);+ else+ result = stbi__convert_format16((stbi__uint16 *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y);+ p->s->img_out_n = req_comp;+ if (result == NULL) return result;+ }+ *x = p->s->img_x;+ *y = p->s->img_y;+ if (n) *n = p->s->img_n;+ }+ STBI_FREE(p->out); p->out = NULL;+ STBI_FREE(p->expanded); p->expanded = NULL;+ STBI_FREE(p->idata); p->idata = NULL;++ return result;+}++static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)+{+ stbi__png p;+ p.s = s;+ return stbi__do_png(&p, x,y,comp,req_comp, ri);+}++static int stbi__png_test(stbi__context *s)+{+ int r;+ r = stbi__check_png_header(s);+ stbi__rewind(s);+ return r;+}++static int stbi__png_info_raw(stbi__png *p, int *x, int *y, int *comp)+{+ if (!stbi__parse_png_file(p, STBI__SCAN_header, 0)) {+ stbi__rewind( p->s );+ return 0;+ }+ if (x) *x = p->s->img_x;+ if (y) *y = p->s->img_y;+ if (comp) *comp = p->s->img_n;+ return 1;+}++static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp)+{+ stbi__png p;+ p.s = s;+ return stbi__png_info_raw(&p, x, y, comp);+}++static int stbi__png_is16(stbi__context *s)+{+ stbi__png p;+ p.s = s;+ if (!stbi__png_info_raw(&p, NULL, NULL, NULL))+ return 0;+ if (p.depth != 16) {+ stbi__rewind(p.s);+ return 0;+ }+ return 1;+}+#endif++// Microsoft/Windows BMP image++#ifndef STBI_NO_BMP+static int stbi__bmp_test_raw(stbi__context *s)+{+ int r;+ int sz;+ if (stbi__get8(s) != 'B') return 0;+ if (stbi__get8(s) != 'M') return 0;+ stbi__get32le(s); // discard filesize+ stbi__get16le(s); // discard reserved+ stbi__get16le(s); // discard reserved+ stbi__get32le(s); // discard data offset+ sz = stbi__get32le(s);+ r = (sz == 12 || sz == 40 || sz == 56 || sz == 108 || sz == 124);+ return r;+}++static int stbi__bmp_test(stbi__context *s)+{+ int r = stbi__bmp_test_raw(s);+ stbi__rewind(s);+ return r;+}+++// returns 0..31 for the highest set bit+static int stbi__high_bit(unsigned int z)+{+ int n=0;+ if (z == 0) return -1;+ if (z >= 0x10000) { n += 16; z >>= 16; }+ if (z >= 0x00100) { n += 8; z >>= 8; }+ if (z >= 0x00010) { n += 4; z >>= 4; }+ if (z >= 0x00004) { n += 2; z >>= 2; }+ if (z >= 0x00002) { n += 1;/* >>= 1;*/ }+ return n;+}++static int stbi__bitcount(unsigned int a)+{+ a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2+ a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4+ a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits+ a = (a + (a >> 8)); // max 16 per 8 bits+ a = (a + (a >> 16)); // max 32 per 8 bits+ return a & 0xff;+}++// extract an arbitrarily-aligned N-bit value (N=bits)+// from v, and then make it 8-bits long and fractionally+// extend it to full full range.+static int stbi__shiftsigned(unsigned int v, int shift, int bits)+{+ static unsigned int mul_table[9] = {+ 0,+ 0xff/*0b11111111*/, 0x55/*0b01010101*/, 0x49/*0b01001001*/, 0x11/*0b00010001*/,+ 0x21/*0b00100001*/, 0x41/*0b01000001*/, 0x81/*0b10000001*/, 0x01/*0b00000001*/,+ };+ static unsigned int shift_table[9] = {+ 0, 0,0,1,0,2,4,6,0,+ };+ if (shift < 0)+ v <<= -shift;+ else+ v >>= shift;+ STBI_ASSERT(v < 256);+ v >>= (8-bits);+ STBI_ASSERT(bits >= 0 && bits <= 8);+ return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits];+}++typedef struct+{+ int bpp, offset, hsz;+ unsigned int mr,mg,mb,ma, all_a;+ int extra_read;+} stbi__bmp_data;++static int stbi__bmp_set_mask_defaults(stbi__bmp_data *info, int compress)+{+ // BI_BITFIELDS specifies masks explicitly, don't override+ if (compress == 3)+ return 1;++ if (compress == 0) {+ if (info->bpp == 16) {+ info->mr = 31u << 10;+ info->mg = 31u << 5;+ info->mb = 31u << 0;+ } else if (info->bpp == 32) {+ info->mr = 0xffu << 16;+ info->mg = 0xffu << 8;+ info->mb = 0xffu << 0;+ info->ma = 0xffu << 24;+ info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0+ } else {+ // otherwise, use defaults, which is all-0+ info->mr = info->mg = info->mb = info->ma = 0;+ }+ return 1;+ }+ return 0; // error+}++static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)+{+ int hsz;+ if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') return stbi__errpuc("not BMP", "Corrupt BMP");+ stbi__get32le(s); // discard filesize+ stbi__get16le(s); // discard reserved+ stbi__get16le(s); // discard reserved+ info->offset = stbi__get32le(s);+ info->hsz = hsz = stbi__get32le(s);+ info->mr = info->mg = info->mb = info->ma = 0;+ info->extra_read = 14;++ if (info->offset < 0) return stbi__errpuc("bad BMP", "bad BMP");++ if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown");+ if (hsz == 12) {+ s->img_x = stbi__get16le(s);+ s->img_y = stbi__get16le(s);+ } else {+ s->img_x = stbi__get32le(s);+ s->img_y = stbi__get32le(s);+ }+ if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP");+ info->bpp = stbi__get16le(s);+ if (hsz != 12) {+ int compress = stbi__get32le(s);+ if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE");+ if (compress >= 4) return stbi__errpuc("BMP JPEG/PNG", "BMP type not supported: unsupported compression"); // this includes PNG/JPEG modes+ if (compress == 3 && info->bpp != 16 && info->bpp != 32) return stbi__errpuc("bad BMP", "bad BMP"); // bitfields requires 16 or 32 bits/pixel+ stbi__get32le(s); // discard sizeof+ stbi__get32le(s); // discard hres+ stbi__get32le(s); // discard vres+ stbi__get32le(s); // discard colorsused+ stbi__get32le(s); // discard max important+ if (hsz == 40 || hsz == 56) {+ if (hsz == 56) {+ stbi__get32le(s);+ stbi__get32le(s);+ stbi__get32le(s);+ stbi__get32le(s);+ }+ if (info->bpp == 16 || info->bpp == 32) {+ if (compress == 0) {+ stbi__bmp_set_mask_defaults(info, compress);+ } else if (compress == 3) {+ info->mr = stbi__get32le(s);+ info->mg = stbi__get32le(s);+ info->mb = stbi__get32le(s);+ info->extra_read += 12;+ // not documented, but generated by photoshop and handled by mspaint+ if (info->mr == info->mg && info->mg == info->mb) {+ // ?!?!?+ return stbi__errpuc("bad BMP", "bad BMP");+ }+ } else+ return stbi__errpuc("bad BMP", "bad BMP");+ }+ } else {+ // V4/V5 header+ int i;+ if (hsz != 108 && hsz != 124)+ return stbi__errpuc("bad BMP", "bad BMP");+ info->mr = stbi__get32le(s);+ info->mg = stbi__get32le(s);+ info->mb = stbi__get32le(s);+ info->ma = stbi__get32le(s);+ if (compress != 3) // override mr/mg/mb unless in BI_BITFIELDS mode, as per docs+ stbi__bmp_set_mask_defaults(info, compress);+ stbi__get32le(s); // discard color space+ for (i=0; i < 12; ++i)+ stbi__get32le(s); // discard color space parameters+ if (hsz == 124) {+ stbi__get32le(s); // discard rendering intent+ stbi__get32le(s); // discard offset of profile data+ stbi__get32le(s); // discard size of profile data+ stbi__get32le(s); // discard reserved+ }+ }+ }+ return (void *) 1;+}+++static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)+{+ stbi_uc *out;+ unsigned int mr=0,mg=0,mb=0,ma=0, all_a;+ stbi_uc pal[256][4];+ int psize=0,i,j,width;+ int flip_vertically, pad, target;+ stbi__bmp_data info;+ STBI_NOTUSED(ri);++ info.all_a = 255;+ if (stbi__bmp_parse_header(s, &info) == NULL)+ return NULL; // error code already set++ flip_vertically = ((int) s->img_y) > 0;+ s->img_y = abs((int) s->img_y);++ if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");+ if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");++ mr = info.mr;+ mg = info.mg;+ mb = info.mb;+ ma = info.ma;+ all_a = info.all_a;++ if (info.hsz == 12) {+ if (info.bpp < 24)+ psize = (info.offset - info.extra_read - 24) / 3;+ } else {+ if (info.bpp < 16)+ psize = (info.offset - info.extra_read - info.hsz) >> 2;+ }+ if (psize == 0) {+ // accept some number of extra bytes after the header, but if the offset points either to before+ // the header ends or implies a large amount of extra data, reject the file as malformed+ int bytes_read_so_far = s->callback_already_read + (int)(s->img_buffer - s->img_buffer_original);+ int header_limit = 1024; // max we actually read is below 256 bytes currently.+ int extra_data_limit = 256*4; // what ordinarily goes here is a palette; 256 entries*4 bytes is its max size.+ if (bytes_read_so_far <= 0 || bytes_read_so_far > header_limit) {+ return stbi__errpuc("bad header", "Corrupt BMP");+ }+ // we established that bytes_read_so_far is positive and sensible.+ // the first half of this test rejects offsets that are either too small positives, or+ // negative, and guarantees that info.offset >= bytes_read_so_far > 0. this in turn+ // ensures the number computed in the second half of the test can't overflow.+ if (info.offset < bytes_read_so_far || info.offset - bytes_read_so_far > extra_data_limit) {+ return stbi__errpuc("bad offset", "Corrupt BMP");+ } else {+ stbi__skip(s, info.offset - bytes_read_so_far);+ }+ }++ if (info.bpp == 24 && ma == 0xff000000)+ s->img_n = 3;+ else+ s->img_n = ma ? 4 : 3;+ if (req_comp && req_comp >= 3) // we can directly decode 3 or 4+ target = req_comp;+ else+ target = s->img_n; // if they want monochrome, we'll post-convert++ // sanity-check size+ if (!stbi__mad3sizes_valid(target, s->img_x, s->img_y, 0))+ return stbi__errpuc("too large", "Corrupt BMP");++ out = (stbi_uc *) stbi__malloc_mad3(target, s->img_x, s->img_y, 0);+ if (!out) return stbi__errpuc("outofmem", "Out of memory");+ if (info.bpp < 16) {+ int z=0;+ if (psize == 0 || psize > 256) { STBI_FREE(out); return stbi__errpuc("invalid", "Corrupt BMP"); }+ for (i=0; i < psize; ++i) {+ pal[i][2] = stbi__get8(s);+ pal[i][1] = stbi__get8(s);+ pal[i][0] = stbi__get8(s);+ if (info.hsz != 12) stbi__get8(s);+ pal[i][3] = 255;+ }+ stbi__skip(s, info.offset - info.extra_read - info.hsz - psize * (info.hsz == 12 ? 3 : 4));+ if (info.bpp == 1) width = (s->img_x + 7) >> 3;+ else if (info.bpp == 4) width = (s->img_x + 1) >> 1;+ else if (info.bpp == 8) width = s->img_x;+ else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); }+ pad = (-width)&3;+ if (info.bpp == 1) {+ for (j=0; j < (int) s->img_y; ++j) {+ int bit_offset = 7, v = stbi__get8(s);+ for (i=0; i < (int) s->img_x; ++i) {+ int color = (v>>bit_offset)&0x1;+ out[z++] = pal[color][0];+ out[z++] = pal[color][1];+ out[z++] = pal[color][2];+ if (target == 4) out[z++] = 255;+ if (i+1 == (int) s->img_x) break;+ if((--bit_offset) < 0) {+ bit_offset = 7;+ v = stbi__get8(s);+ }+ }+ stbi__skip(s, pad);+ }+ } else {+ for (j=0; j < (int) s->img_y; ++j) {+ for (i=0; i < (int) s->img_x; i += 2) {+ int v=stbi__get8(s),v2=0;+ if (info.bpp == 4) {+ v2 = v & 15;+ v >>= 4;+ }+ out[z++] = pal[v][0];+ out[z++] = pal[v][1];+ out[z++] = pal[v][2];+ if (target == 4) out[z++] = 255;+ if (i+1 == (int) s->img_x) break;+ v = (info.bpp == 8) ? stbi__get8(s) : v2;+ out[z++] = pal[v][0];+ out[z++] = pal[v][1];+ out[z++] = pal[v][2];+ if (target == 4) out[z++] = 255;+ }+ stbi__skip(s, pad);+ }+ }+ } else {+ int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0;+ int z = 0;+ int easy=0;+ stbi__skip(s, info.offset - info.extra_read - info.hsz);+ if (info.bpp == 24) width = 3 * s->img_x;+ else if (info.bpp == 16) width = 2*s->img_x;+ else /* bpp = 32 and pad = 0 */ width=0;+ pad = (-width) & 3;+ if (info.bpp == 24) {+ easy = 1;+ } else if (info.bpp == 32) {+ if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000)+ easy = 2;+ }+ if (!easy) {+ if (!mr || !mg || !mb) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); }+ // right shift amt to put high bit in position #7+ rshift = stbi__high_bit(mr)-7; rcount = stbi__bitcount(mr);+ gshift = stbi__high_bit(mg)-7; gcount = stbi__bitcount(mg);+ bshift = stbi__high_bit(mb)-7; bcount = stbi__bitcount(mb);+ ashift = stbi__high_bit(ma)-7; acount = stbi__bitcount(ma);+ if (rcount > 8 || gcount > 8 || bcount > 8 || acount > 8) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); }+ }+ for (j=0; j < (int) s->img_y; ++j) {+ if (easy) {+ for (i=0; i < (int) s->img_x; ++i) {+ unsigned char a;+ out[z+2] = stbi__get8(s);+ out[z+1] = stbi__get8(s);+ out[z+0] = stbi__get8(s);+ z += 3;+ a = (easy == 2 ? stbi__get8(s) : 255);+ all_a |= a;+ if (target == 4) out[z++] = a;+ }+ } else {+ int bpp = info.bpp;+ for (i=0; i < (int) s->img_x; ++i) {+ stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s));+ unsigned int a;+ out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount));+ out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount));+ out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount));+ a = (ma ? stbi__shiftsigned(v & ma, ashift, acount) : 255);+ all_a |= a;+ if (target == 4) out[z++] = STBI__BYTECAST(a);+ }+ }+ stbi__skip(s, pad);+ }+ }++ // if alpha channel is all 0s, replace with all 255s+ if (target == 4 && all_a == 0)+ for (i=4*s->img_x*s->img_y-1; i >= 0; i -= 4)+ out[i] = 255;++ if (flip_vertically) {+ stbi_uc t;+ for (j=0; j < (int) s->img_y>>1; ++j) {+ stbi_uc *p1 = out + j *s->img_x*target;+ stbi_uc *p2 = out + (s->img_y-1-j)*s->img_x*target;+ for (i=0; i < (int) s->img_x*target; ++i) {+ t = p1[i]; p1[i] = p2[i]; p2[i] = t;+ }+ }+ }++ if (req_comp && req_comp != target) {+ out = stbi__convert_format(out, target, req_comp, s->img_x, s->img_y);+ if (out == NULL) return out; // stbi__convert_format frees input on failure+ }++ *x = s->img_x;+ *y = s->img_y;+ if (comp) *comp = s->img_n;+ return out;+}+#endif++// Targa Truevision - TGA+// by Jonathan Dummer+#ifndef STBI_NO_TGA+// returns STBI_rgb or whatever, 0 on error+static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int* is_rgb16)+{+ // only RGB or RGBA (incl. 16bit) or grey allowed+ if (is_rgb16) *is_rgb16 = 0;+ switch(bits_per_pixel) {+ case 8: return STBI_grey;+ case 16: if(is_grey) return STBI_grey_alpha;+ // fallthrough+ case 15: if(is_rgb16) *is_rgb16 = 1;+ return STBI_rgb;+ case 24: // fallthrough+ case 32: return bits_per_pixel/8;+ default: return 0;+ }+}++static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp)+{+ int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp;+ int sz, tga_colormap_type;+ stbi__get8(s); // discard Offset+ tga_colormap_type = stbi__get8(s); // colormap type+ if( tga_colormap_type > 1 ) {+ stbi__rewind(s);+ return 0; // only RGB or indexed allowed+ }+ tga_image_type = stbi__get8(s); // image type+ if ( tga_colormap_type == 1 ) { // colormapped (paletted) image+ if (tga_image_type != 1 && tga_image_type != 9) {+ stbi__rewind(s);+ return 0;+ }+ stbi__skip(s,4); // skip index of first colormap entry and number of entries+ sz = stbi__get8(s); // check bits per palette color entry+ if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) {+ stbi__rewind(s);+ return 0;+ }+ stbi__skip(s,4); // skip image x and y origin+ tga_colormap_bpp = sz;+ } else { // "normal" image w/o colormap - only RGB or grey allowed, +/- RLE+ if ( (tga_image_type != 2) && (tga_image_type != 3) && (tga_image_type != 10) && (tga_image_type != 11) ) {+ stbi__rewind(s);+ return 0; // only RGB or grey allowed, +/- RLE+ }+ stbi__skip(s,9); // skip colormap specification and image x/y origin+ tga_colormap_bpp = 0;+ }+ tga_w = stbi__get16le(s);+ if( tga_w < 1 ) {+ stbi__rewind(s);+ return 0; // test width+ }+ tga_h = stbi__get16le(s);+ if( tga_h < 1 ) {+ stbi__rewind(s);+ return 0; // test height+ }+ tga_bits_per_pixel = stbi__get8(s); // bits per pixel+ stbi__get8(s); // ignore alpha bits+ if (tga_colormap_bpp != 0) {+ if((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) {+ // when using a colormap, tga_bits_per_pixel is the size of the indexes+ // I don't think anything but 8 or 16bit indexes makes sense+ stbi__rewind(s);+ return 0;+ }+ tga_comp = stbi__tga_get_comp(tga_colormap_bpp, 0, NULL);+ } else {+ tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3) || (tga_image_type == 11), NULL);+ }+ if(!tga_comp) {+ stbi__rewind(s);+ return 0;+ }+ if (x) *x = tga_w;+ if (y) *y = tga_h;+ if (comp) *comp = tga_comp;+ return 1; // seems to have passed everything+}++static int stbi__tga_test(stbi__context *s)+{+ int res = 0;+ int sz, tga_color_type;+ stbi__get8(s); // discard Offset+ tga_color_type = stbi__get8(s); // color type+ if ( tga_color_type > 1 ) goto errorEnd; // only RGB or indexed allowed+ sz = stbi__get8(s); // image type+ if ( tga_color_type == 1 ) { // colormapped (paletted) image+ if (sz != 1 && sz != 9) goto errorEnd; // colortype 1 demands image type 1 or 9+ stbi__skip(s,4); // skip index of first colormap entry and number of entries+ sz = stbi__get8(s); // check bits per palette color entry+ if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd;+ stbi__skip(s,4); // skip image x and y origin+ } else { // "normal" image w/o colormap+ if ( (sz != 2) && (sz != 3) && (sz != 10) && (sz != 11) ) goto errorEnd; // only RGB or grey allowed, +/- RLE+ stbi__skip(s,9); // skip colormap specification and image x/y origin+ }+ if ( stbi__get16le(s) < 1 ) goto errorEnd; // test width+ if ( stbi__get16le(s) < 1 ) goto errorEnd; // test height+ sz = stbi__get8(s); // bits per pixel+ if ( (tga_color_type == 1) && (sz != 8) && (sz != 16) ) goto errorEnd; // for colormapped images, bpp is size of an index+ if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd;++ res = 1; // if we got this far, everything's good and we can return 1 instead of 0++errorEnd:+ stbi__rewind(s);+ return res;+}++// read 16bit value and convert to 24bit RGB+static void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out)+{+ stbi__uint16 px = (stbi__uint16)stbi__get16le(s);+ stbi__uint16 fiveBitMask = 31;+ // we have 3 channels with 5bits each+ int r = (px >> 10) & fiveBitMask;+ int g = (px >> 5) & fiveBitMask;+ int b = px & fiveBitMask;+ // Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later+ out[0] = (stbi_uc)((r * 255)/31);+ out[1] = (stbi_uc)((g * 255)/31);+ out[2] = (stbi_uc)((b * 255)/31);++ // some people claim that the most significant bit might be used for alpha+ // (possibly if an alpha-bit is set in the "image descriptor byte")+ // but that only made 16bit test images completely translucent..+ // so let's treat all 15 and 16bit TGAs as RGB with no alpha.+}++static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)+{+ // read in the TGA header stuff+ int tga_offset = stbi__get8(s);+ int tga_indexed = stbi__get8(s);+ int tga_image_type = stbi__get8(s);+ int tga_is_RLE = 0;+ int tga_palette_start = stbi__get16le(s);+ int tga_palette_len = stbi__get16le(s);+ int tga_palette_bits = stbi__get8(s);+ int tga_x_origin = stbi__get16le(s);+ int tga_y_origin = stbi__get16le(s);+ int tga_width = stbi__get16le(s);+ int tga_height = stbi__get16le(s);+ int tga_bits_per_pixel = stbi__get8(s);+ int tga_comp, tga_rgb16=0;+ int tga_inverted = stbi__get8(s);+ // int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits - unused (useless?)+ // image data+ unsigned char *tga_data;+ unsigned char *tga_palette = NULL;+ int i, j;+ unsigned char raw_data[4] = {0};+ int RLE_count = 0;+ int RLE_repeating = 0;+ int read_next_pixel = 1;+ STBI_NOTUSED(ri);+ STBI_NOTUSED(tga_x_origin); // @TODO+ STBI_NOTUSED(tga_y_origin); // @TODO++ if (tga_height > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");+ if (tga_width > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");++ // do a tiny bit of precessing+ if ( tga_image_type >= 8 )+ {+ tga_image_type -= 8;+ tga_is_RLE = 1;+ }+ tga_inverted = 1 - ((tga_inverted >> 5) & 1);++ // If I'm paletted, then I'll use the number of bits from the palette+ if ( tga_indexed ) tga_comp = stbi__tga_get_comp(tga_palette_bits, 0, &tga_rgb16);+ else tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3), &tga_rgb16);++ if(!tga_comp) // shouldn't really happen, stbi__tga_test() should have ensured basic consistency+ return stbi__errpuc("bad format", "Can't find out TGA pixelformat");++ // tga info+ *x = tga_width;+ *y = tga_height;+ if (comp) *comp = tga_comp;++ if (!stbi__mad3sizes_valid(tga_width, tga_height, tga_comp, 0))+ return stbi__errpuc("too large", "Corrupt TGA");++ tga_data = (unsigned char*)stbi__malloc_mad3(tga_width, tga_height, tga_comp, 0);+ if (!tga_data) return stbi__errpuc("outofmem", "Out of memory");++ // skip to the data's starting position (offset usually = 0)+ stbi__skip(s, tga_offset );++ if ( !tga_indexed && !tga_is_RLE && !tga_rgb16 ) {+ for (i=0; i < tga_height; ++i) {+ int row = tga_inverted ? tga_height -i - 1 : i;+ stbi_uc *tga_row = tga_data + row*tga_width*tga_comp;+ stbi__getn(s, tga_row, tga_width * tga_comp);+ }+ } else {+ // do I need to load a palette?+ if ( tga_indexed)+ {+ if (tga_palette_len == 0) { /* you have to have at least one entry! */+ STBI_FREE(tga_data);+ return stbi__errpuc("bad palette", "Corrupt TGA");+ }++ // any data to skip? (offset usually = 0)+ stbi__skip(s, tga_palette_start );+ // load the palette+ tga_palette = (unsigned char*)stbi__malloc_mad2(tga_palette_len, tga_comp, 0);+ if (!tga_palette) {+ STBI_FREE(tga_data);+ return stbi__errpuc("outofmem", "Out of memory");+ }+ if (tga_rgb16) {+ stbi_uc *pal_entry = tga_palette;+ STBI_ASSERT(tga_comp == STBI_rgb);+ for (i=0; i < tga_palette_len; ++i) {+ stbi__tga_read_rgb16(s, pal_entry);+ pal_entry += tga_comp;+ }+ } else if (!stbi__getn(s, tga_palette, tga_palette_len * tga_comp)) {+ STBI_FREE(tga_data);+ STBI_FREE(tga_palette);+ return stbi__errpuc("bad palette", "Corrupt TGA");+ }+ }+ // load the data+ for (i=0; i < tga_width * tga_height; ++i)+ {+ // if I'm in RLE mode, do I need to get a RLE stbi__pngchunk?+ if ( tga_is_RLE )+ {+ if ( RLE_count == 0 )+ {+ // yep, get the next byte as a RLE command+ int RLE_cmd = stbi__get8(s);+ RLE_count = 1 + (RLE_cmd & 127);+ RLE_repeating = RLE_cmd >> 7;+ read_next_pixel = 1;+ } else if ( !RLE_repeating )+ {+ read_next_pixel = 1;+ }+ } else+ {+ read_next_pixel = 1;+ }+ // OK, if I need to read a pixel, do it now+ if ( read_next_pixel )+ {+ // load however much data we did have+ if ( tga_indexed )+ {+ // read in index, then perform the lookup+ int pal_idx = (tga_bits_per_pixel == 8) ? stbi__get8(s) : stbi__get16le(s);+ if ( pal_idx >= tga_palette_len ) {+ // invalid index+ pal_idx = 0;+ }+ pal_idx *= tga_comp;+ for (j = 0; j < tga_comp; ++j) {+ raw_data[j] = tga_palette[pal_idx+j];+ }+ } else if(tga_rgb16) {+ STBI_ASSERT(tga_comp == STBI_rgb);+ stbi__tga_read_rgb16(s, raw_data);+ } else {+ // read in the data raw+ for (j = 0; j < tga_comp; ++j) {+ raw_data[j] = stbi__get8(s);+ }+ }+ // clear the reading flag for the next pixel+ read_next_pixel = 0;+ } // end of reading a pixel++ // copy data+ for (j = 0; j < tga_comp; ++j)+ tga_data[i*tga_comp+j] = raw_data[j];++ // in case we're in RLE mode, keep counting down+ --RLE_count;+ }+ // do I need to invert the image?+ if ( tga_inverted )+ {+ for (j = 0; j*2 < tga_height; ++j)+ {+ int index1 = j * tga_width * tga_comp;+ int index2 = (tga_height - 1 - j) * tga_width * tga_comp;+ for (i = tga_width * tga_comp; i > 0; --i)+ {+ unsigned char temp = tga_data[index1];+ tga_data[index1] = tga_data[index2];+ tga_data[index2] = temp;+ ++index1;+ ++index2;+ }+ }+ }+ // clear my palette, if I had one+ if ( tga_palette != NULL )+ {+ STBI_FREE( tga_palette );+ }+ }++ // swap RGB - if the source data was RGB16, it already is in the right order+ if (tga_comp >= 3 && !tga_rgb16)+ {+ unsigned char* tga_pixel = tga_data;+ for (i=0; i < tga_width * tga_height; ++i)+ {+ unsigned char temp = tga_pixel[0];+ tga_pixel[0] = tga_pixel[2];+ tga_pixel[2] = temp;+ tga_pixel += tga_comp;+ }+ }++ // convert to target component count+ if (req_comp && req_comp != tga_comp)+ tga_data = stbi__convert_format(tga_data, tga_comp, req_comp, tga_width, tga_height);++ // the things I do to get rid of an error message, and yet keep+ // Microsoft's C compilers happy... [8^(+ tga_palette_start = tga_palette_len = tga_palette_bits =+ tga_x_origin = tga_y_origin = 0;+ STBI_NOTUSED(tga_palette_start);+ // OK, done+ return tga_data;+}+#endif++// *************************************************************************************************+// Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicolas Schulz, tweaked by STB++#ifndef STBI_NO_PSD+static int stbi__psd_test(stbi__context *s)+{+ int r = (stbi__get32be(s) == 0x38425053);+ stbi__rewind(s);+ return r;+}++static int stbi__psd_decode_rle(stbi__context *s, stbi_uc *p, int pixelCount)+{+ int count, nleft, len;++ count = 0;+ while ((nleft = pixelCount - count) > 0) {+ len = stbi__get8(s);+ if (len == 128) {+ // No-op.+ } else if (len < 128) {+ // Copy next len+1 bytes literally.+ len++;+ if (len > nleft) return 0; // corrupt data+ count += len;+ while (len) {+ *p = stbi__get8(s);+ p += 4;+ len--;+ }+ } else if (len > 128) {+ stbi_uc val;+ // Next -len+1 bytes in the dest are replicated from next source byte.+ // (Interpret len as a negative 8-bit int.)+ len = 257 - len;+ if (len > nleft) return 0; // corrupt data+ val = stbi__get8(s);+ count += len;+ while (len) {+ *p = val;+ p += 4;+ len--;+ }+ }+ }++ return 1;+}++static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc)+{+ int pixelCount;+ int channelCount, compression;+ int channel, i;+ int bitdepth;+ int w,h;+ stbi_uc *out;+ STBI_NOTUSED(ri);++ // Check identifier+ if (stbi__get32be(s) != 0x38425053) // "8BPS"+ return stbi__errpuc("not PSD", "Corrupt PSD image");++ // Check file type version.+ if (stbi__get16be(s) != 1)+ return stbi__errpuc("wrong version", "Unsupported version of PSD image");++ // Skip 6 reserved bytes.+ stbi__skip(s, 6 );++ // Read the number of channels (R, G, B, A, etc).+ channelCount = stbi__get16be(s);+ if (channelCount < 0 || channelCount > 16)+ return stbi__errpuc("wrong channel count", "Unsupported number of channels in PSD image");++ // Read the rows and columns of the image.+ h = stbi__get32be(s);+ w = stbi__get32be(s);++ if (h > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");+ if (w > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");++ // Make sure the depth is 8 bits.+ bitdepth = stbi__get16be(s);+ if (bitdepth != 8 && bitdepth != 16)+ return stbi__errpuc("unsupported bit depth", "PSD bit depth is not 8 or 16 bit");++ // Make sure the color mode is RGB.+ // Valid options are:+ // 0: Bitmap+ // 1: Grayscale+ // 2: Indexed color+ // 3: RGB color+ // 4: CMYK color+ // 7: Multichannel+ // 8: Duotone+ // 9: Lab color+ if (stbi__get16be(s) != 3)+ return stbi__errpuc("wrong color format", "PSD is not in RGB color format");++ // Skip the Mode Data. (It's the palette for indexed color; other info for other modes.)+ stbi__skip(s,stbi__get32be(s) );++ // Skip the image resources. (resolution, pen tool paths, etc)+ stbi__skip(s, stbi__get32be(s) );++ // Skip the reserved data.+ stbi__skip(s, stbi__get32be(s) );++ // Find out if the data is compressed.+ // Known values:+ // 0: no compression+ // 1: RLE compressed+ compression = stbi__get16be(s);+ if (compression > 1)+ return stbi__errpuc("bad compression", "PSD has an unknown compression format");++ // Check size+ if (!stbi__mad3sizes_valid(4, w, h, 0))+ return stbi__errpuc("too large", "Corrupt PSD");++ // Create the destination image.++ if (!compression && bitdepth == 16 && bpc == 16) {+ out = (stbi_uc *) stbi__malloc_mad3(8, w, h, 0);+ ri->bits_per_channel = 16;+ } else+ out = (stbi_uc *) stbi__malloc(4 * w*h);++ if (!out) return stbi__errpuc("outofmem", "Out of memory");+ pixelCount = w*h;++ // Initialize the data to zero.+ //memset( out, 0, pixelCount * 4 );++ // Finally, the image data.+ if (compression) {+ // RLE as used by .PSD and .TIFF+ // Loop until you get the number of unpacked bytes you are expecting:+ // Read the next source byte into n.+ // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally.+ // Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times.+ // Else if n is 128, noop.+ // Endloop++ // The RLE-compressed data is preceded by a 2-byte data count for each row in the data,+ // which we're going to just skip.+ stbi__skip(s, h * channelCount * 2 );++ // Read the RLE data by channel.+ for (channel = 0; channel < 4; channel++) {+ stbi_uc *p;++ p = out+channel;+ if (channel >= channelCount) {+ // Fill this channel with default data.+ for (i = 0; i < pixelCount; i++, p += 4)+ *p = (channel == 3 ? 255 : 0);+ } else {+ // Read the RLE data.+ if (!stbi__psd_decode_rle(s, p, pixelCount)) {+ STBI_FREE(out);+ return stbi__errpuc("corrupt", "bad RLE data");+ }+ }+ }++ } else {+ // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...)+ // where each channel consists of an 8-bit (or 16-bit) value for each pixel in the image.++ // Read the data by channel.+ for (channel = 0; channel < 4; channel++) {+ if (channel >= channelCount) {+ // Fill this channel with default data.+ if (bitdepth == 16 && bpc == 16) {+ stbi__uint16 *q = ((stbi__uint16 *) out) + channel;+ stbi__uint16 val = channel == 3 ? 65535 : 0;+ for (i = 0; i < pixelCount; i++, q += 4)+ *q = val;+ } else {+ stbi_uc *p = out+channel;+ stbi_uc val = channel == 3 ? 255 : 0;+ for (i = 0; i < pixelCount; i++, p += 4)+ *p = val;+ }+ } else {+ if (ri->bits_per_channel == 16) { // output bpc+ stbi__uint16 *q = ((stbi__uint16 *) out) + channel;+ for (i = 0; i < pixelCount; i++, q += 4)+ *q = (stbi__uint16) stbi__get16be(s);+ } else {+ stbi_uc *p = out+channel;+ if (bitdepth == 16) { // input bpc+ for (i = 0; i < pixelCount; i++, p += 4)+ *p = (stbi_uc) (stbi__get16be(s) >> 8);+ } else {+ for (i = 0; i < pixelCount; i++, p += 4)+ *p = stbi__get8(s);+ }+ }+ }+ }+ }++ // remove weird white matte from PSD+ if (channelCount >= 4) {+ if (ri->bits_per_channel == 16) {+ for (i=0; i < w*h; ++i) {+ stbi__uint16 *pixel = (stbi__uint16 *) out + 4*i;+ if (pixel[3] != 0 && pixel[3] != 65535) {+ float a = pixel[3] / 65535.0f;+ float ra = 1.0f / a;+ float inv_a = 65535.0f * (1 - ra);+ pixel[0] = (stbi__uint16) (pixel[0]*ra + inv_a);+ pixel[1] = (stbi__uint16) (pixel[1]*ra + inv_a);+ pixel[2] = (stbi__uint16) (pixel[2]*ra + inv_a);+ }+ }+ } else {+ for (i=0; i < w*h; ++i) {+ unsigned char *pixel = out + 4*i;+ if (pixel[3] != 0 && pixel[3] != 255) {+ float a = pixel[3] / 255.0f;+ float ra = 1.0f / a;+ float inv_a = 255.0f * (1 - ra);+ pixel[0] = (unsigned char) (pixel[0]*ra + inv_a);+ pixel[1] = (unsigned char) (pixel[1]*ra + inv_a);+ pixel[2] = (unsigned char) (pixel[2]*ra + inv_a);+ }+ }+ }+ }++ // convert to desired output format+ if (req_comp && req_comp != 4) {+ if (ri->bits_per_channel == 16)+ out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, 4, req_comp, w, h);+ else+ out = stbi__convert_format(out, 4, req_comp, w, h);+ if (out == NULL) return out; // stbi__convert_format frees input on failure+ }++ if (comp) *comp = 4;+ *y = h;+ *x = w;++ return out;+}+#endif++// *************************************************************************************************+// Softimage PIC loader+// by Tom Seddon+//+// See http://softimage.wiki.softimage.com/index.php/INFO:_PIC_file_format+// See http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/softimagepic/++#ifndef STBI_NO_PIC+static int stbi__pic_is4(stbi__context *s,const char *str)+{+ int i;+ for (i=0; i<4; ++i)+ if (stbi__get8(s) != (stbi_uc)str[i])+ return 0;++ return 1;+}++static int stbi__pic_test_core(stbi__context *s)+{+ int i;++ if (!stbi__pic_is4(s,"\x53\x80\xF6\x34"))+ return 0;++ for(i=0;i<84;++i)+ stbi__get8(s);++ if (!stbi__pic_is4(s,"PICT"))+ return 0;++ return 1;+}++typedef struct+{+ stbi_uc size,type,channel;+} stbi__pic_packet;++static stbi_uc *stbi__readval(stbi__context *s, int channel, stbi_uc *dest)+{+ int mask=0x80, i;++ for (i=0; i<4; ++i, mask>>=1) {+ if (channel & mask) {+ if (stbi__at_eof(s)) return stbi__errpuc("bad file","PIC file too short");+ dest[i]=stbi__get8(s);+ }+ }++ return dest;+}++static void stbi__copyval(int channel,stbi_uc *dest,const stbi_uc *src)+{+ int mask=0x80,i;++ for (i=0;i<4; ++i, mask>>=1)+ if (channel&mask)+ dest[i]=src[i];+}++static stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *comp, stbi_uc *result)+{+ int act_comp=0,num_packets=0,y,chained;+ stbi__pic_packet packets[10];++ // this will (should...) cater for even some bizarre stuff like having data+ // for the same channel in multiple packets.+ do {+ stbi__pic_packet *packet;++ if (num_packets==sizeof(packets)/sizeof(packets[0]))+ return stbi__errpuc("bad format","too many packets");++ packet = &packets[num_packets++];++ chained = stbi__get8(s);+ packet->size = stbi__get8(s);+ packet->type = stbi__get8(s);+ packet->channel = stbi__get8(s);++ act_comp |= packet->channel;++ if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (reading packets)");+ if (packet->size != 8) return stbi__errpuc("bad format","packet isn't 8bpp");+ } while (chained);++ *comp = (act_comp & 0x10 ? 4 : 3); // has alpha channel?++ for(y=0; y<height; ++y) {+ int packet_idx;++ for(packet_idx=0; packet_idx < num_packets; ++packet_idx) {+ stbi__pic_packet *packet = &packets[packet_idx];+ stbi_uc *dest = result+y*width*4;++ switch (packet->type) {+ default:+ return stbi__errpuc("bad format","packet has bad compression type");++ case 0: {//uncompressed+ int x;++ for(x=0;x<width;++x, dest+=4)+ if (!stbi__readval(s,packet->channel,dest))+ return 0;+ break;+ }++ case 1://Pure RLE+ {+ int left=width, i;++ while (left>0) {+ stbi_uc count,value[4];++ count=stbi__get8(s);+ if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pure read count)");++ if (count > left)+ count = (stbi_uc) left;++ if (!stbi__readval(s,packet->channel,value)) return 0;++ for(i=0; i<count; ++i,dest+=4)+ stbi__copyval(packet->channel,dest,value);+ left -= count;+ }+ }+ break;++ case 2: {//Mixed RLE+ int left=width;+ while (left>0) {+ int count = stbi__get8(s), i;+ if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (mixed read count)");++ if (count >= 128) { // Repeated+ stbi_uc value[4];++ if (count==128)+ count = stbi__get16be(s);+ else+ count -= 127;+ if (count > left)+ return stbi__errpuc("bad file","scanline overrun");++ if (!stbi__readval(s,packet->channel,value))+ return 0;++ for(i=0;i<count;++i, dest += 4)+ stbi__copyval(packet->channel,dest,value);+ } else { // Raw+ ++count;+ if (count>left) return stbi__errpuc("bad file","scanline overrun");++ for(i=0;i<count;++i, dest+=4)+ if (!stbi__readval(s,packet->channel,dest))+ return 0;+ }+ left-=count;+ }+ break;+ }+ }+ }+ }++ return result;+}++static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp, stbi__result_info *ri)+{+ stbi_uc *result;+ int i, x,y, internal_comp;+ STBI_NOTUSED(ri);++ if (!comp) comp = &internal_comp;++ for (i=0; i<92; ++i)+ stbi__get8(s);++ x = stbi__get16be(s);+ y = stbi__get16be(s);++ if (y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");+ if (x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");++ if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pic header)");+ if (!stbi__mad3sizes_valid(x, y, 4, 0)) return stbi__errpuc("too large", "PIC image too large to decode");++ stbi__get32be(s); //skip `ratio'+ stbi__get16be(s); //skip `fields'+ stbi__get16be(s); //skip `pad'++ // intermediate buffer is RGBA+ result = (stbi_uc *) stbi__malloc_mad3(x, y, 4, 0);+ if (!result) return stbi__errpuc("outofmem", "Out of memory");+ memset(result, 0xff, x*y*4);++ if (!stbi__pic_load_core(s,x,y,comp, result)) {+ STBI_FREE(result);+ result=0;+ }+ *px = x;+ *py = y;+ if (req_comp == 0) req_comp = *comp;+ result=stbi__convert_format(result,4,req_comp,x,y);++ return result;+}++static int stbi__pic_test(stbi__context *s)+{+ int r = stbi__pic_test_core(s);+ stbi__rewind(s);+ return r;+}+#endif++// *************************************************************************************************+// GIF loader -- public domain by Jean-Marc Lienher -- simplified/shrunk by stb++#ifndef STBI_NO_GIF+typedef struct+{+ stbi__int16 prefix;+ stbi_uc first;+ stbi_uc suffix;+} stbi__gif_lzw;++typedef struct+{+ int w,h;+ stbi_uc *out; // output buffer (always 4 components)+ stbi_uc *background; // The current "background" as far as a gif is concerned+ stbi_uc *history;+ int flags, bgindex, ratio, transparent, eflags;+ stbi_uc pal[256][4];+ stbi_uc lpal[256][4];+ stbi__gif_lzw codes[8192];+ stbi_uc *color_table;+ int parse, step;+ int lflags;+ int start_x, start_y;+ int max_x, max_y;+ int cur_x, cur_y;+ int line_size;+ int delay;+} stbi__gif;++static int stbi__gif_test_raw(stbi__context *s)+{+ int sz;+ if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') return 0;+ sz = stbi__get8(s);+ if (sz != '9' && sz != '7') return 0;+ if (stbi__get8(s) != 'a') return 0;+ return 1;+}++static int stbi__gif_test(stbi__context *s)+{+ int r = stbi__gif_test_raw(s);+ stbi__rewind(s);+ return r;+}++static void stbi__gif_parse_colortable(stbi__context *s, stbi_uc pal[256][4], int num_entries, int transp)+{+ int i;+ for (i=0; i < num_entries; ++i) {+ pal[i][2] = stbi__get8(s);+ pal[i][1] = stbi__get8(s);+ pal[i][0] = stbi__get8(s);+ pal[i][3] = transp == i ? 0 : 255;+ }+}++static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_info)+{+ stbi_uc version;+ if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8')+ return stbi__err("not GIF", "Corrupt GIF");++ version = stbi__get8(s);+ if (version != '7' && version != '9') return stbi__err("not GIF", "Corrupt GIF");+ if (stbi__get8(s) != 'a') return stbi__err("not GIF", "Corrupt GIF");++ stbi__g_failure_reason = "";+ g->w = stbi__get16le(s);+ g->h = stbi__get16le(s);+ g->flags = stbi__get8(s);+ g->bgindex = stbi__get8(s);+ g->ratio = stbi__get8(s);+ g->transparent = -1;++ if (g->w > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");+ if (g->h > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)");++ if (comp != 0) *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments++ if (is_info) return 1;++ if (g->flags & 0x80)+ stbi__gif_parse_colortable(s,g->pal, 2 << (g->flags & 7), -1);++ return 1;+}++static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp)+{+ stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif));+ if (!g) return stbi__err("outofmem", "Out of memory");+ if (!stbi__gif_header(s, g, comp, 1)) {+ STBI_FREE(g);+ stbi__rewind( s );+ return 0;+ }+ if (x) *x = g->w;+ if (y) *y = g->h;+ STBI_FREE(g);+ return 1;+}++static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code)+{+ stbi_uc *p, *c;+ int idx;++ // recurse to decode the prefixes, since the linked-list is backwards,+ // and working backwards through an interleaved image would be nasty+ if (g->codes[code].prefix >= 0)+ stbi__out_gif_code(g, g->codes[code].prefix);++ if (g->cur_y >= g->max_y) return;++ idx = g->cur_x + g->cur_y;+ p = &g->out[idx];+ g->history[idx / 4] = 1;++ c = &g->color_table[g->codes[code].suffix * 4];+ if (c[3] > 128) { // don't render transparent pixels;+ p[0] = c[2];+ p[1] = c[1];+ p[2] = c[0];+ p[3] = c[3];+ }+ g->cur_x += 4;++ if (g->cur_x >= g->max_x) {+ g->cur_x = g->start_x;+ g->cur_y += g->step;++ while (g->cur_y >= g->max_y && g->parse > 0) {+ g->step = (1 << g->parse) * g->line_size;+ g->cur_y = g->start_y + (g->step >> 1);+ --g->parse;+ }+ }+}++static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g)+{+ stbi_uc lzw_cs;+ stbi__int32 len, init_code;+ stbi__uint32 first;+ stbi__int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear;+ stbi__gif_lzw *p;++ lzw_cs = stbi__get8(s);+ if (lzw_cs > 12) return NULL;+ clear = 1 << lzw_cs;+ first = 1;+ codesize = lzw_cs + 1;+ codemask = (1 << codesize) - 1;+ bits = 0;+ valid_bits = 0;+ for (init_code = 0; init_code < clear; init_code++) {+ g->codes[init_code].prefix = -1;+ g->codes[init_code].first = (stbi_uc) init_code;+ g->codes[init_code].suffix = (stbi_uc) init_code;+ }++ // support no starting clear code+ avail = clear+2;+ oldcode = -1;++ len = 0;+ for(;;) {+ if (valid_bits < codesize) {+ if (len == 0) {+ len = stbi__get8(s); // start new block+ if (len == 0)+ return g->out;+ }+ --len;+ bits |= (stbi__int32) stbi__get8(s) << valid_bits;+ valid_bits += 8;+ } else {+ stbi__int32 code = bits & codemask;+ bits >>= codesize;+ valid_bits -= codesize;+ // @OPTIMIZE: is there some way we can accelerate the non-clear path?+ if (code == clear) { // clear code+ codesize = lzw_cs + 1;+ codemask = (1 << codesize) - 1;+ avail = clear + 2;+ oldcode = -1;+ first = 0;+ } else if (code == clear + 1) { // end of stream code+ stbi__skip(s, len);+ while ((len = stbi__get8(s)) > 0)+ stbi__skip(s,len);+ return g->out;+ } else if (code <= avail) {+ if (first) {+ return stbi__errpuc("no clear code", "Corrupt GIF");+ }++ if (oldcode >= 0) {+ p = &g->codes[avail++];+ if (avail > 8192) {+ return stbi__errpuc("too many codes", "Corrupt GIF");+ }++ p->prefix = (stbi__int16) oldcode;+ p->first = g->codes[oldcode].first;+ p->suffix = (code == avail) ? p->first : g->codes[code].first;+ } else if (code == avail)+ return stbi__errpuc("illegal code in raster", "Corrupt GIF");++ stbi__out_gif_code(g, (stbi__uint16) code);++ if ((avail & codemask) == 0 && avail <= 0x0FFF) {+ codesize++;+ codemask = (1 << codesize) - 1;+ }++ oldcode = code;+ } else {+ return stbi__errpuc("illegal code in raster", "Corrupt GIF");+ }+ }+ }+}++// this function is designed to support animated gifs, although stb_image doesn't support it+// two back is the image from two frames ago, used for a very specific disposal format+static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp, stbi_uc *two_back)+{+ int dispose;+ int first_frame;+ int pi;+ int pcount;+ STBI_NOTUSED(req_comp);++ // on first frame, any non-written pixels get the background colour (non-transparent)+ first_frame = 0;+ if (g->out == 0) {+ if (!stbi__gif_header(s, g, comp,0)) return 0; // stbi__g_failure_reason set by stbi__gif_header+ if (!stbi__mad3sizes_valid(4, g->w, g->h, 0))+ return stbi__errpuc("too large", "GIF image is too large");+ pcount = g->w * g->h;+ g->out = (stbi_uc *) stbi__malloc(4 * pcount);+ g->background = (stbi_uc *) stbi__malloc(4 * pcount);+ g->history = (stbi_uc *) stbi__malloc(pcount);+ if (!g->out || !g->background || !g->history)+ return stbi__errpuc("outofmem", "Out of memory");++ // image is treated as "transparent" at the start - ie, nothing overwrites the current background;+ // background colour is only used for pixels that are not rendered first frame, after that "background"+ // color refers to the color that was there the previous frame.+ memset(g->out, 0x00, 4 * pcount);+ memset(g->background, 0x00, 4 * pcount); // state of the background (starts transparent)+ memset(g->history, 0x00, pcount); // pixels that were affected previous frame+ first_frame = 1;+ } else {+ // second frame - how do we dispose of the previous one?+ dispose = (g->eflags & 0x1C) >> 2;+ pcount = g->w * g->h;++ if ((dispose == 3) && (two_back == 0)) {+ dispose = 2; // if I don't have an image to revert back to, default to the old background+ }++ if (dispose == 3) { // use previous graphic+ for (pi = 0; pi < pcount; ++pi) {+ if (g->history[pi]) {+ memcpy( &g->out[pi * 4], &two_back[pi * 4], 4 );+ }+ }+ } else if (dispose == 2) {+ // restore what was changed last frame to background before that frame;+ for (pi = 0; pi < pcount; ++pi) {+ if (g->history[pi]) {+ memcpy( &g->out[pi * 4], &g->background[pi * 4], 4 );+ }+ }+ } else {+ // This is a non-disposal case eithe way, so just+ // leave the pixels as is, and they will become the new background+ // 1: do not dispose+ // 0: not specified.+ }++ // background is what out is after the undoing of the previou frame;+ memcpy( g->background, g->out, 4 * g->w * g->h );+ }++ // clear my history;+ memset( g->history, 0x00, g->w * g->h ); // pixels that were affected previous frame++ for (;;) {+ int tag = stbi__get8(s);+ switch (tag) {+ case 0x2C: /* Image Descriptor */+ {+ stbi__int32 x, y, w, h;+ stbi_uc *o;++ x = stbi__get16le(s);+ y = stbi__get16le(s);+ w = stbi__get16le(s);+ h = stbi__get16le(s);+ if (((x + w) > (g->w)) || ((y + h) > (g->h)))+ return stbi__errpuc("bad Image Descriptor", "Corrupt GIF");++ g->line_size = g->w * 4;+ g->start_x = x * 4;+ g->start_y = y * g->line_size;+ g->max_x = g->start_x + w * 4;+ g->max_y = g->start_y + h * g->line_size;+ g->cur_x = g->start_x;+ g->cur_y = g->start_y;++ // if the width of the specified rectangle is 0, that means+ // we may not see *any* pixels or the image is malformed;+ // to make sure this is caught, move the current y down to+ // max_y (which is what out_gif_code checks).+ if (w == 0)+ g->cur_y = g->max_y;++ g->lflags = stbi__get8(s);++ if (g->lflags & 0x40) {+ g->step = 8 * g->line_size; // first interlaced spacing+ g->parse = 3;+ } else {+ g->step = g->line_size;+ g->parse = 0;+ }++ if (g->lflags & 0x80) {+ stbi__gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1);+ g->color_table = (stbi_uc *) g->lpal;+ } else if (g->flags & 0x80) {+ g->color_table = (stbi_uc *) g->pal;+ } else+ return stbi__errpuc("missing color table", "Corrupt GIF");++ o = stbi__process_gif_raster(s, g);+ if (!o) return NULL;++ // if this was the first frame,+ pcount = g->w * g->h;+ if (first_frame && (g->bgindex > 0)) {+ // if first frame, any pixel not drawn to gets the background color+ for (pi = 0; pi < pcount; ++pi) {+ if (g->history[pi] == 0) {+ g->pal[g->bgindex][3] = 255; // just in case it was made transparent, undo that; It will be reset next frame if need be;+ memcpy( &g->out[pi * 4], &g->pal[g->bgindex], 4 );+ }+ }+ }++ return o;+ }++ case 0x21: // Comment Extension.+ {+ int len;+ int ext = stbi__get8(s);+ if (ext == 0xF9) { // Graphic Control Extension.+ len = stbi__get8(s);+ if (len == 4) {+ g->eflags = stbi__get8(s);+ g->delay = 10 * stbi__get16le(s); // delay - 1/100th of a second, saving as 1/1000ths.++ // unset old transparent+ if (g->transparent >= 0) {+ g->pal[g->transparent][3] = 255;+ }+ if (g->eflags & 0x01) {+ g->transparent = stbi__get8(s);+ if (g->transparent >= 0) {+ g->pal[g->transparent][3] = 0;+ }+ } else {+ // don't need transparent+ stbi__skip(s, 1);+ g->transparent = -1;+ }+ } else {+ stbi__skip(s, len);+ break;+ }+ }+ while ((len = stbi__get8(s)) != 0) {+ stbi__skip(s, len);+ }+ break;+ }++ case 0x3B: // gif stream termination code+ return (stbi_uc *) s; // using '1' causes warning on some compilers++ default:+ return stbi__errpuc("unknown code", "Corrupt GIF");+ }+ }+}++static void *stbi__load_gif_main_outofmem(stbi__gif *g, stbi_uc *out, int **delays)+{+ STBI_FREE(g->out);+ STBI_FREE(g->history);+ STBI_FREE(g->background);++ if (out) STBI_FREE(out);+ if (delays && *delays) STBI_FREE(*delays);+ return stbi__errpuc("outofmem", "Out of memory");+}++static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp)+{+ if (stbi__gif_test(s)) {+ int layers = 0;+ stbi_uc *u = 0;+ stbi_uc *out = 0;+ stbi_uc *two_back = 0;+ stbi__gif g;+ int stride;+ int out_size = 0;+ int delays_size = 0;++ STBI_NOTUSED(out_size);+ STBI_NOTUSED(delays_size);++ memset(&g, 0, sizeof(g));+ if (delays) {+ *delays = 0;+ }++ do {+ u = stbi__gif_load_next(s, &g, comp, req_comp, two_back);+ if (u == (stbi_uc *) s) u = 0; // end of animated gif marker++ if (u) {+ *x = g.w;+ *y = g.h;+ ++layers;+ stride = g.w * g.h * 4;++ if (out) {+ void *tmp = (stbi_uc*) STBI_REALLOC_SIZED( out, out_size, layers * stride );+ if (!tmp)+ return stbi__load_gif_main_outofmem(&g, out, delays);+ else {+ out = (stbi_uc*) tmp;+ out_size = layers * stride;+ }++ if (delays) {+ int *new_delays = (int*) STBI_REALLOC_SIZED( *delays, delays_size, sizeof(int) * layers );+ if (!new_delays)+ return stbi__load_gif_main_outofmem(&g, out, delays);+ *delays = new_delays;+ delays_size = layers * sizeof(int);+ }+ } else {+ out = (stbi_uc*)stbi__malloc( layers * stride );+ if (!out)+ return stbi__load_gif_main_outofmem(&g, out, delays);+ out_size = layers * stride;+ if (delays) {+ *delays = (int*) stbi__malloc( layers * sizeof(int) );+ if (!*delays)+ return stbi__load_gif_main_outofmem(&g, out, delays);+ delays_size = layers * sizeof(int);+ }+ }+ memcpy( out + ((layers - 1) * stride), u, stride );+ if (layers >= 2) {+ two_back = out - 2 * stride;+ }++ if (delays) {+ (*delays)[layers - 1U] = g.delay;+ }+ }+ } while (u != 0);++ // free temp buffer;+ STBI_FREE(g.out);+ STBI_FREE(g.history);+ STBI_FREE(g.background);++ // do the final conversion after loading everything;+ if (req_comp && req_comp != 4)+ out = stbi__convert_format(out, 4, req_comp, layers * g.w, g.h);++ *z = layers;+ return out;+ } else {+ return stbi__errpuc("not GIF", "Image was not as a gif type.");+ }+}++static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)+{+ stbi_uc *u = 0;+ stbi__gif g;+ memset(&g, 0, sizeof(g));+ STBI_NOTUSED(ri);++ u = stbi__gif_load_next(s, &g, comp, req_comp, 0);+ if (u == (stbi_uc *) s) u = 0; // end of animated gif marker+ if (u) {+ *x = g.w;+ *y = g.h;++ // moved conversion to after successful load so that the same+ // can be done for multiple frames.+ if (req_comp && req_comp != 4)+ u = stbi__convert_format(u, 4, req_comp, g.w, g.h);+ } else if (g.out) {+ // if there was an error and we allocated an image buffer, free it!+ STBI_FREE(g.out);+ }++ // free buffers needed for multiple frame loading;+ STBI_FREE(g.history);+ STBI_FREE(g.background);++ return u;+}++static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp)+{+ return stbi__gif_info_raw(s,x,y,comp);+}+#endif++// *************************************************************************************************+// Radiance RGBE HDR loader+// originally by Nicolas Schulz+#ifndef STBI_NO_HDR+static int stbi__hdr_test_core(stbi__context *s, const char *signature)+{+ int i;+ for (i=0; signature[i]; ++i)+ if (stbi__get8(s) != signature[i])+ return 0;+ stbi__rewind(s);+ return 1;+}++static int stbi__hdr_test(stbi__context* s)+{+ int r = stbi__hdr_test_core(s, "#?RADIANCE\n");+ stbi__rewind(s);+ if(!r) {+ r = stbi__hdr_test_core(s, "#?RGBE\n");+ stbi__rewind(s);+ }+ return r;+}++#define STBI__HDR_BUFLEN 1024+static char *stbi__hdr_gettoken(stbi__context *z, char *buffer)+{+ int len=0;+ char c = '\0';++ c = (char) stbi__get8(z);++ while (!stbi__at_eof(z) && c != '\n') {+ buffer[len++] = c;+ if (len == STBI__HDR_BUFLEN-1) {+ // flush to end of line+ while (!stbi__at_eof(z) && stbi__get8(z) != '\n')+ ;+ break;+ }+ c = (char) stbi__get8(z);+ }++ buffer[len] = 0;+ return buffer;+}++static void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp)+{+ if ( input[3] != 0 ) {+ float f1;+ // Exponent+ f1 = (float) ldexp(1.0f, input[3] - (int)(128 + 8));+ if (req_comp <= 2)+ output[0] = (input[0] + input[1] + input[2]) * f1 / 3;+ else {+ output[0] = input[0] * f1;+ output[1] = input[1] * f1;+ output[2] = input[2] * f1;+ }+ if (req_comp == 2) output[1] = 1;+ if (req_comp == 4) output[3] = 1;+ } else {+ switch (req_comp) {+ case 4: output[3] = 1; /* fallthrough */+ case 3: output[0] = output[1] = output[2] = 0;+ break;+ case 2: output[1] = 1; /* fallthrough */+ case 1: output[0] = 0;+ break;+ }+ }+}++static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)+{+ char buffer[STBI__HDR_BUFLEN];+ char *token;+ int valid = 0;+ int width, height;+ stbi_uc *scanline;+ float *hdr_data;+ int len;+ unsigned char count, value;+ int i, j, k, c1,c2, z;+ const char *headerToken;+ STBI_NOTUSED(ri);++ // Check identifier+ headerToken = stbi__hdr_gettoken(s,buffer);+ if (strcmp(headerToken, "#?RADIANCE") != 0 && strcmp(headerToken, "#?RGBE") != 0)+ return stbi__errpf("not HDR", "Corrupt HDR image");++ // Parse header+ for(;;) {+ token = stbi__hdr_gettoken(s,buffer);+ if (token[0] == 0) break;+ if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1;+ }++ if (!valid) return stbi__errpf("unsupported format", "Unsupported HDR format");++ // Parse width and height+ // can't use sscanf() if we're not using stdio!+ token = stbi__hdr_gettoken(s,buffer);+ if (strncmp(token, "-Y ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format");+ token += 3;+ height = (int) strtol(token, &token, 10);+ while (*token == ' ') ++token;+ if (strncmp(token, "+X ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format");+ token += 3;+ width = (int) strtol(token, NULL, 10);++ if (height > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)");+ if (width > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)");++ *x = width;+ *y = height;++ if (comp) *comp = 3;+ if (req_comp == 0) req_comp = 3;++ if (!stbi__mad4sizes_valid(width, height, req_comp, sizeof(float), 0))+ return stbi__errpf("too large", "HDR image is too large");++ // Read data+ hdr_data = (float *) stbi__malloc_mad4(width, height, req_comp, sizeof(float), 0);+ if (!hdr_data)+ return stbi__errpf("outofmem", "Out of memory");++ // Load image data+ // image data is stored as some number of sca+ if ( width < 8 || width >= 32768) {+ // Read flat data+ for (j=0; j < height; ++j) {+ for (i=0; i < width; ++i) {+ stbi_uc rgbe[4];+ main_decode_loop:+ stbi__getn(s, rgbe, 4);+ stbi__hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp);+ }+ }+ } else {+ // Read RLE-encoded data+ scanline = NULL;++ for (j = 0; j < height; ++j) {+ c1 = stbi__get8(s);+ c2 = stbi__get8(s);+ len = stbi__get8(s);+ if (c1 != 2 || c2 != 2 || (len & 0x80)) {+ // not run-length encoded, so we have to actually use THIS data as a decoded+ // pixel (note this can't be a valid pixel--one of RGB must be >= 128)+ stbi_uc rgbe[4];+ rgbe[0] = (stbi_uc) c1;+ rgbe[1] = (stbi_uc) c2;+ rgbe[2] = (stbi_uc) len;+ rgbe[3] = (stbi_uc) stbi__get8(s);+ stbi__hdr_convert(hdr_data, rgbe, req_comp);+ i = 1;+ j = 0;+ STBI_FREE(scanline);+ goto main_decode_loop; // yes, this makes no sense+ }+ len <<= 8;+ len |= stbi__get8(s);+ if (len != width) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); }+ if (scanline == NULL) {+ scanline = (stbi_uc *) stbi__malloc_mad2(width, 4, 0);+ if (!scanline) {+ STBI_FREE(hdr_data);+ return stbi__errpf("outofmem", "Out of memory");+ }+ }++ for (k = 0; k < 4; ++k) {+ int nleft;+ i = 0;+ while ((nleft = width - i) > 0) {+ count = stbi__get8(s);+ if (count > 128) {+ // Run+ value = stbi__get8(s);+ count -= 128;+ if ((count == 0) || (count > nleft)) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); }+ for (z = 0; z < count; ++z)+ scanline[i++ * 4 + k] = value;+ } else {+ // Dump+ if ((count == 0) || (count > nleft)) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); }+ for (z = 0; z < count; ++z)+ scanline[i++ * 4 + k] = stbi__get8(s);+ }+ }+ }+ for (i=0; i < width; ++i)+ stbi__hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp);+ }+ if (scanline)+ STBI_FREE(scanline);+ }++ return hdr_data;+}++static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp)+{+ char buffer[STBI__HDR_BUFLEN];+ char *token;+ int valid = 0;+ int dummy;++ if (!x) x = &dummy;+ if (!y) y = &dummy;+ if (!comp) comp = &dummy;++ if (stbi__hdr_test(s) == 0) {+ stbi__rewind( s );+ return 0;+ }++ for(;;) {+ token = stbi__hdr_gettoken(s,buffer);+ if (token[0] == 0) break;+ if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1;+ }++ if (!valid) {+ stbi__rewind( s );+ return 0;+ }+ token = stbi__hdr_gettoken(s,buffer);+ if (strncmp(token, "-Y ", 3)) {+ stbi__rewind( s );+ return 0;+ }+ token += 3;+ *y = (int) strtol(token, &token, 10);+ while (*token == ' ') ++token;+ if (strncmp(token, "+X ", 3)) {+ stbi__rewind( s );+ return 0;+ }+ token += 3;+ *x = (int) strtol(token, NULL, 10);+ *comp = 3;+ return 1;+}+#endif // STBI_NO_HDR++#ifndef STBI_NO_BMP+static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp)+{+ void *p;+ stbi__bmp_data info;++ info.all_a = 255;+ p = stbi__bmp_parse_header(s, &info);+ if (p == NULL) {+ stbi__rewind( s );+ return 0;+ }+ if (x) *x = s->img_x;+ if (y) *y = s->img_y;+ if (comp) {+ if (info.bpp == 24 && info.ma == 0xff000000)+ *comp = 3;+ else+ *comp = info.ma ? 4 : 3;+ }+ return 1;+}+#endif++#ifndef STBI_NO_PSD+static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp)+{+ int channelCount, dummy, depth;+ if (!x) x = &dummy;+ if (!y) y = &dummy;+ if (!comp) comp = &dummy;+ if (stbi__get32be(s) != 0x38425053) {+ stbi__rewind( s );+ return 0;+ }+ if (stbi__get16be(s) != 1) {+ stbi__rewind( s );+ return 0;+ }+ stbi__skip(s, 6);+ channelCount = stbi__get16be(s);+ if (channelCount < 0 || channelCount > 16) {+ stbi__rewind( s );+ return 0;+ }+ *y = stbi__get32be(s);+ *x = stbi__get32be(s);+ depth = stbi__get16be(s);+ if (depth != 8 && depth != 16) {+ stbi__rewind( s );+ return 0;+ }+ if (stbi__get16be(s) != 3) {+ stbi__rewind( s );+ return 0;+ }+ *comp = 4;+ return 1;+}++static int stbi__psd_is16(stbi__context *s)+{+ int channelCount, depth;+ if (stbi__get32be(s) != 0x38425053) {+ stbi__rewind( s );+ return 0;+ }+ if (stbi__get16be(s) != 1) {+ stbi__rewind( s );+ return 0;+ }+ stbi__skip(s, 6);+ channelCount = stbi__get16be(s);+ if (channelCount < 0 || channelCount > 16) {+ stbi__rewind( s );+ return 0;+ }+ STBI_NOTUSED(stbi__get32be(s));+ STBI_NOTUSED(stbi__get32be(s));+ depth = stbi__get16be(s);+ if (depth != 16) {+ stbi__rewind( s );+ return 0;+ }+ return 1;+}+#endif++#ifndef STBI_NO_PIC+static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp)+{+ int act_comp=0,num_packets=0,chained,dummy;+ stbi__pic_packet packets[10];++ if (!x) x = &dummy;+ if (!y) y = &dummy;+ if (!comp) comp = &dummy;++ if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) {+ stbi__rewind(s);+ return 0;+ }++ stbi__skip(s, 88);++ *x = stbi__get16be(s);+ *y = stbi__get16be(s);+ if (stbi__at_eof(s)) {+ stbi__rewind( s);+ return 0;+ }+ if ( (*x) != 0 && (1 << 28) / (*x) < (*y)) {+ stbi__rewind( s );+ return 0;+ }++ stbi__skip(s, 8);++ do {+ stbi__pic_packet *packet;++ if (num_packets==sizeof(packets)/sizeof(packets[0]))+ return 0;++ packet = &packets[num_packets++];+ chained = stbi__get8(s);+ packet->size = stbi__get8(s);+ packet->type = stbi__get8(s);+ packet->channel = stbi__get8(s);+ act_comp |= packet->channel;++ if (stbi__at_eof(s)) {+ stbi__rewind( s );+ return 0;+ }+ if (packet->size != 8) {+ stbi__rewind( s );+ return 0;+ }+ } while (chained);++ *comp = (act_comp & 0x10 ? 4 : 3);++ return 1;+}+#endif++// *************************************************************************************************+// Portable Gray Map and Portable Pixel Map loader+// by Ken Miller+//+// PGM: http://netpbm.sourceforge.net/doc/pgm.html+// PPM: http://netpbm.sourceforge.net/doc/ppm.html+//+// Known limitations:+// Does not support comments in the header section+// Does not support ASCII image data (formats P2 and P3)++#ifndef STBI_NO_PNM++static int stbi__pnm_test(stbi__context *s)+{+ char p, t;+ p = (char) stbi__get8(s);+ t = (char) stbi__get8(s);+ if (p != 'P' || (t != '5' && t != '6')) {+ stbi__rewind( s );+ return 0;+ }+ return 1;+}++static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)+{+ stbi_uc *out;+ STBI_NOTUSED(ri);++ ri->bits_per_channel = stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n);+ if (ri->bits_per_channel == 0)+ return 0;++ if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");+ if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)");++ *x = s->img_x;+ *y = s->img_y;+ if (comp) *comp = s->img_n;++ if (!stbi__mad4sizes_valid(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0))+ return stbi__errpuc("too large", "PNM too large");++ out = (stbi_uc *) stbi__malloc_mad4(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0);+ if (!out) return stbi__errpuc("outofmem", "Out of memory");+ if (!stbi__getn(s, out, s->img_n * s->img_x * s->img_y * (ri->bits_per_channel / 8))) {+ STBI_FREE(out);+ return stbi__errpuc("bad PNM", "PNM file truncated");+ }++ if (req_comp && req_comp != s->img_n) {+ if (ri->bits_per_channel == 16) {+ out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, s->img_n, req_comp, s->img_x, s->img_y);+ } else {+ out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y);+ }+ if (out == NULL) return out; // stbi__convert_format frees input on failure+ }+ return out;+}++static int stbi__pnm_isspace(char c)+{+ return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r';+}++static void stbi__pnm_skip_whitespace(stbi__context *s, char *c)+{+ for (;;) {+ while (!stbi__at_eof(s) && stbi__pnm_isspace(*c))+ *c = (char) stbi__get8(s);++ if (stbi__at_eof(s) || *c != '#')+ break;++ while (!stbi__at_eof(s) && *c != '\n' && *c != '\r' )+ *c = (char) stbi__get8(s);+ }+}++static int stbi__pnm_isdigit(char c)+{+ return c >= '0' && c <= '9';+}++static int stbi__pnm_getinteger(stbi__context *s, char *c)+{+ int value = 0;++ while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) {+ value = value*10 + (*c - '0');+ *c = (char) stbi__get8(s);+ if((value > 214748364) || (value == 214748364 && *c > '7'))+ return stbi__err("integer parse overflow", "Parsing an integer in the PPM header overflowed a 32-bit int");+ }++ return value;+}++static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp)+{+ int maxv, dummy;+ char c, p, t;++ if (!x) x = &dummy;+ if (!y) y = &dummy;+ if (!comp) comp = &dummy;++ stbi__rewind(s);++ // Get identifier+ p = (char) stbi__get8(s);+ t = (char) stbi__get8(s);+ if (p != 'P' || (t != '5' && t != '6')) {+ stbi__rewind(s);+ return 0;+ }++ *comp = (t == '6') ? 3 : 1; // '5' is 1-component .pgm; '6' is 3-component .ppm++ c = (char) stbi__get8(s);+ stbi__pnm_skip_whitespace(s, &c);++ *x = stbi__pnm_getinteger(s, &c); // read width+ if(*x == 0)+ return stbi__err("invalid width", "PPM image header had zero or overflowing width");+ stbi__pnm_skip_whitespace(s, &c);++ *y = stbi__pnm_getinteger(s, &c); // read height+ if (*y == 0)+ return stbi__err("invalid width", "PPM image header had zero or overflowing width");+ stbi__pnm_skip_whitespace(s, &c);++ maxv = stbi__pnm_getinteger(s, &c); // read max value+ if (maxv > 65535)+ return stbi__err("max value > 65535", "PPM image supports only 8-bit and 16-bit images");+ else if (maxv > 255)+ return 16;+ else+ return 8;+}++static int stbi__pnm_is16(stbi__context *s)+{+ if (stbi__pnm_info(s, NULL, NULL, NULL) == 16)+ return 1;+ return 0;+}+#endif++static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp)+{+ #ifndef STBI_NO_JPEG+ if (stbi__jpeg_info(s, x, y, comp)) return 1;+ #endif++ #ifndef STBI_NO_PNG+ if (stbi__png_info(s, x, y, comp)) return 1;+ #endif++ #ifndef STBI_NO_GIF+ if (stbi__gif_info(s, x, y, comp)) return 1;+ #endif++ #ifndef STBI_NO_BMP+ if (stbi__bmp_info(s, x, y, comp)) return 1;+ #endif++ #ifndef STBI_NO_PSD+ if (stbi__psd_info(s, x, y, comp)) return 1;+ #endif++ #ifndef STBI_NO_PIC+ if (stbi__pic_info(s, x, y, comp)) return 1;+ #endif++ #ifndef STBI_NO_PNM+ if (stbi__pnm_info(s, x, y, comp)) return 1;+ #endif++ #ifndef STBI_NO_HDR+ if (stbi__hdr_info(s, x, y, comp)) return 1;+ #endif++ // test tga last because it's a crappy test!+ #ifndef STBI_NO_TGA+ if (stbi__tga_info(s, x, y, comp))+ return 1;+ #endif+ return stbi__err("unknown image type", "Image not of any known type, or corrupt");+}++static int stbi__is_16_main(stbi__context *s)+{+ #ifndef STBI_NO_PNG+ if (stbi__png_is16(s)) return 1;+ #endif++ #ifndef STBI_NO_PSD+ if (stbi__psd_is16(s)) return 1;+ #endif++ #ifndef STBI_NO_PNM+ if (stbi__pnm_is16(s)) return 1;+ #endif+ return 0;+}++#ifndef STBI_NO_STDIO+STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp)+{+ FILE *f = stbi__fopen(filename, "rb");+ int result;+ if (!f) return stbi__err("can't fopen", "Unable to open file");+ result = stbi_info_from_file(f, x, y, comp);+ fclose(f);+ return result;+}++STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp)+{+ int r;+ stbi__context s;+ long pos = ftell(f);+ stbi__start_file(&s, f);+ r = stbi__info_main(&s,x,y,comp);+ fseek(f,pos,SEEK_SET);+ return r;+}++STBIDEF int stbi_is_16_bit(char const *filename)+{+ FILE *f = stbi__fopen(filename, "rb");+ int result;+ if (!f) return stbi__err("can't fopen", "Unable to open file");+ result = stbi_is_16_bit_from_file(f);+ fclose(f);+ return result;+}++STBIDEF int stbi_is_16_bit_from_file(FILE *f)+{+ int r;+ stbi__context s;+ long pos = ftell(f);+ stbi__start_file(&s, f);+ r = stbi__is_16_main(&s);+ fseek(f,pos,SEEK_SET);+ return r;+}+#endif // !STBI_NO_STDIO++STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp)+{+ stbi__context s;+ stbi__start_mem(&s,buffer,len);+ return stbi__info_main(&s,x,y,comp);+}++STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int *y, int *comp)+{+ stbi__context s;+ stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user);+ return stbi__info_main(&s,x,y,comp);+}++STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len)+{+ stbi__context s;+ stbi__start_mem(&s,buffer,len);+ return stbi__is_16_main(&s);+}++STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *c, void *user)+{+ stbi__context s;+ stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user);+ return stbi__is_16_main(&s);+}++#endif // STB_IMAGE_IMPLEMENTATION++/*+ revision history:+ 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs+ 2.19 (2018-02-11) fix warning+ 2.18 (2018-01-30) fix warnings+ 2.17 (2018-01-29) change sbti__shiftsigned to avoid clang -O2 bug+ 1-bit BMP+ *_is_16_bit api+ avoid warnings+ 2.16 (2017-07-23) all functions have 16-bit variants;+ STBI_NO_STDIO works again;+ compilation fixes;+ fix rounding in unpremultiply;+ optimize vertical flip;+ disable raw_len validation;+ documentation fixes+ 2.15 (2017-03-18) fix png-1,2,4 bug; now all Imagenet JPGs decode;+ warning fixes; disable run-time SSE detection on gcc;+ uniform handling of optional "return" values;+ thread-safe initialization of zlib tables+ 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs+ 2.13 (2016-11-29) add 16-bit API, only supported for PNG right now+ 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes+ 2.11 (2016-04-02) allocate large structures on the stack+ remove white matting for transparent PSD+ fix reported channel count for PNG & BMP+ re-enable SSE2 in non-gcc 64-bit+ support RGB-formatted JPEG+ read 16-bit PNGs (only as 8-bit)+ 2.10 (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED+ 2.09 (2016-01-16) allow comments in PNM files+ 16-bit-per-pixel TGA (not bit-per-component)+ info() for TGA could break due to .hdr handling+ info() for BMP to shares code instead of sloppy parse+ can use STBI_REALLOC_SIZED if allocator doesn't support realloc+ code cleanup+ 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA+ 2.07 (2015-09-13) fix compiler warnings+ partial animated GIF support+ limited 16-bpc PSD support+ #ifdef unused functions+ bug with < 92 byte PIC,PNM,HDR,TGA+ 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value+ 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning+ 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit+ 2.03 (2015-04-12) extra corruption checking (mmozeiko)+ stbi_set_flip_vertically_on_load (nguillemot)+ fix NEON support; fix mingw support+ 2.02 (2015-01-19) fix incorrect assert, fix warning+ 2.01 (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2+ 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG+ 2.00 (2014-12-25) optimize JPG, including x86 SSE2 & NEON SIMD (ryg)+ progressive JPEG (stb)+ PGM/PPM support (Ken Miller)+ STBI_MALLOC,STBI_REALLOC,STBI_FREE+ GIF bugfix -- seemingly never worked+ STBI_NO_*, STBI_ONLY_*+ 1.48 (2014-12-14) fix incorrectly-named assert()+ 1.47 (2014-12-14) 1/2/4-bit PNG support, both direct and paletted (Omar Cornut & stb)+ optimize PNG (ryg)+ fix bug in interlaced PNG with user-specified channel count (stb)+ 1.46 (2014-08-26)+ fix broken tRNS chunk (colorkey-style transparency) in non-paletted PNG+ 1.45 (2014-08-16)+ fix MSVC-ARM internal compiler error by wrapping malloc+ 1.44 (2014-08-07)+ various warning fixes from Ronny Chevalier+ 1.43 (2014-07-15)+ fix MSVC-only compiler problem in code changed in 1.42+ 1.42 (2014-07-09)+ don't define _CRT_SECURE_NO_WARNINGS (affects user code)+ fixes to stbi__cleanup_jpeg path+ added STBI_ASSERT to avoid requiring assert.h+ 1.41 (2014-06-25)+ fix search&replace from 1.36 that messed up comments/error messages+ 1.40 (2014-06-22)+ fix gcc struct-initialization warning+ 1.39 (2014-06-15)+ fix to TGA optimization when req_comp != number of components in TGA;+ fix to GIF loading because BMP wasn't rewinding (whoops, no GIFs in my test suite)+ add support for BMP version 5 (more ignored fields)+ 1.38 (2014-06-06)+ suppress MSVC warnings on integer casts truncating values+ fix accidental rename of 'skip' field of I/O+ 1.37 (2014-06-04)+ remove duplicate typedef+ 1.36 (2014-06-03)+ convert to header file single-file library+ if de-iphone isn't set, load iphone images color-swapped instead of returning NULL+ 1.35 (2014-05-27)+ various warnings+ fix broken STBI_SIMD path+ fix bug where stbi_load_from_file no longer left file pointer in correct place+ fix broken non-easy path for 32-bit BMP (possibly never used)+ TGA optimization by Arseny Kapoulkine+ 1.34 (unknown)+ use STBI_NOTUSED in stbi__resample_row_generic(), fix one more leak in tga failure case+ 1.33 (2011-07-14)+ make stbi_is_hdr work in STBI_NO_HDR (as specified), minor compiler-friendly improvements+ 1.32 (2011-07-13)+ support for "info" function for all supported filetypes (SpartanJ)+ 1.31 (2011-06-20)+ a few more leak fixes, bug in PNG handling (SpartanJ)+ 1.30 (2011-06-11)+ added ability to load files via callbacks to accomidate custom input streams (Ben Wenger)+ removed deprecated format-specific test/load functions+ removed support for installable file formats (stbi_loader) -- would have been broken for IO callbacks anyway+ error cases in bmp and tga give messages and don't leak (Raymond Barbiero, grisha)+ fix inefficiency in decoding 32-bit BMP (David Woo)+ 1.29 (2010-08-16)+ various warning fixes from Aurelien Pocheville+ 1.28 (2010-08-01)+ fix bug in GIF palette transparency (SpartanJ)+ 1.27 (2010-08-01)+ cast-to-stbi_uc to fix warnings+ 1.26 (2010-07-24)+ fix bug in file buffering for PNG reported by SpartanJ+ 1.25 (2010-07-17)+ refix trans_data warning (Won Chun)+ 1.24 (2010-07-12)+ perf improvements reading from files on platforms with lock-heavy fgetc()+ minor perf improvements for jpeg+ deprecated type-specific functions so we'll get feedback if they're needed+ attempt to fix trans_data warning (Won Chun)+ 1.23 fixed bug in iPhone support+ 1.22 (2010-07-10)+ removed image *writing* support+ stbi_info support from Jetro Lauha+ GIF support from Jean-Marc Lienher+ iPhone PNG-extensions from James Brown+ warning-fixes from Nicolas Schulz and Janez Zemva (i.stbi__err. Janez (U+017D)emva)+ 1.21 fix use of 'stbi_uc' in header (reported by jon blow)+ 1.20 added support for Softimage PIC, by Tom Seddon+ 1.19 bug in interlaced PNG corruption check (found by ryg)+ 1.18 (2008-08-02)+ fix a threading bug (local mutable static)+ 1.17 support interlaced PNG+ 1.16 major bugfix - stbi__convert_format converted one too many pixels+ 1.15 initialize some fields for thread safety+ 1.14 fix threadsafe conversion bug+ header-file-only version (#define STBI_HEADER_FILE_ONLY before including)+ 1.13 threadsafe+ 1.12 const qualifiers in the API+ 1.11 Support installable IDCT, colorspace conversion routines+ 1.10 Fixes for 64-bit (don't use "unsigned long")+ optimized upsampling by Fabian "ryg" Giesen+ 1.09 Fix format-conversion for PSD code (bad global variables!)+ 1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz+ 1.07 attempt to fix C++ warning/errors again+ 1.06 attempt to fix C++ warning/errors again+ 1.05 fix TGA loading to return correct *comp and use good luminance calc+ 1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free+ 1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR+ 1.02 support for (subset of) HDR files, float interface for preferred access to them+ 1.01 fix bug: possible bug in handling right-side up bmps... not sure+ fix bug: the stbi__bmp_load() and stbi__tga_load() functions didn't work at all+ 1.00 interface to zlib that skips zlib header+ 0.99 correct handling of alpha in palette+ 0.98 TGA loader by lonesock; dynamically add loaders (untested)+ 0.97 jpeg errors on too large a file; also catch another malloc failure+ 0.96 fix detection of invalid v value - particleman@mollyrocket forum+ 0.95 during header scan, seek to markers in case of padding+ 0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same+ 0.93 handle jpegtran output; verbose errors+ 0.92 read 4,8,16,24,32-bit BMP files of several formats+ 0.91 output 24-bit Windows 3.0 BMP files+ 0.90 fix a few more warnings; bump version number to approach 1.0+ 0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd+ 0.60 fix compiling as c+++ 0.59 fix warnings: merge Dave Moore's -Wall fixes+ 0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian+ 0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less than 16 available+ 0.56 fix bug: zlib uncompressed mode len vs. nlen+ 0.55 fix bug: restart_interval not initialized to 0+ 0.54 allow NULL for 'int *comp'+ 0.53 fix bug in png 3->4; speedup png decoding+ 0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments+ 0.51 obey req_comp requests, 1-component jpegs return as 1-component,+ on 'test' only check type, not whether we support this variant+ 0.50 (2006-11-19)+ first released version+*/+++/*+------------------------------------------------------------------------------+This software is available under 2 licenses -- choose whichever you prefer.+------------------------------------------------------------------------------+ALTERNATIVE A - MIT License+Copyright (c) 2017 Sean Barrett+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.+------------------------------------------------------------------------------+ALTERNATIVE B - Public Domain (www.unlicense.org)+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.+------------------------------------------------------------------------------+*/
+ cbits/tracy/profiler/src/stb_image_resize.h view
@@ -0,0 +1,2634 @@+/* stb_image_resize - v0.97 - public domain image resizing+ by Jorge L Rodriguez (@VinoBS) - 2014+ http://github.com/nothings/stb++ Written with emphasis on usability, portability, and efficiency. (No+ SIMD or threads, so it be easily outperformed by libs that use those.)+ Only scaling and translation is supported, no rotations or shears.+ Easy API downsamples w/Mitchell filter, upsamples w/cubic interpolation.++ COMPILING & LINKING+ In one C/C++ file that #includes this file, do this:+ #define STB_IMAGE_RESIZE_IMPLEMENTATION+ before the #include. That will create the implementation in that file.++ QUICKSTART+ stbir_resize_uint8( input_pixels , in_w , in_h , 0,+ output_pixels, out_w, out_h, 0, num_channels)+ stbir_resize_float(...)+ stbir_resize_uint8_srgb( input_pixels , in_w , in_h , 0,+ output_pixels, out_w, out_h, 0,+ num_channels , alpha_chan , 0)+ stbir_resize_uint8_srgb_edgemode(+ input_pixels , in_w , in_h , 0,+ output_pixels, out_w, out_h, 0,+ num_channels , alpha_chan , 0, STBIR_EDGE_CLAMP)+ // WRAP/REFLECT/ZERO++ FULL API+ See the "header file" section of the source for API documentation.++ ADDITIONAL DOCUMENTATION++ SRGB & FLOATING POINT REPRESENTATION+ The sRGB functions presume IEEE floating point. If you do not have+ IEEE floating point, define STBIR_NON_IEEE_FLOAT. This will use+ a slower implementation.++ MEMORY ALLOCATION+ The resize functions here perform a single memory allocation using+ malloc. To control the memory allocation, before the #include that+ triggers the implementation, do:++ #define STBIR_MALLOC(size,context) ...+ #define STBIR_FREE(ptr,context) ...++ Each resize function makes exactly one call to malloc/free, so to use+ temp memory, store the temp memory in the context and return that.++ ASSERT+ Define STBIR_ASSERT(boolval) to override assert() and not use assert.h++ OPTIMIZATION+ Define STBIR_SATURATE_INT to compute clamp values in-range using+ integer operations instead of float operations. This may be faster+ on some platforms.++ DEFAULT FILTERS+ For functions which don't provide explicit control over what filters+ to use, you can change the compile-time defaults with++ #define STBIR_DEFAULT_FILTER_UPSAMPLE STBIR_FILTER_something+ #define STBIR_DEFAULT_FILTER_DOWNSAMPLE STBIR_FILTER_something++ See stbir_filter in the header-file section for the list of filters.++ NEW FILTERS+ A number of 1D filter kernels are used. For a list of+ supported filters see the stbir_filter enum. To add a new filter,+ write a filter function and add it to stbir__filter_info_table.++ PROGRESS+ For interactive use with slow resize operations, you can install+ a progress-report callback:++ #define STBIR_PROGRESS_REPORT(val) some_func(val)++ The parameter val is a float which goes from 0 to 1 as progress is made.++ For example:++ static void my_progress_report(float progress);+ #define STBIR_PROGRESS_REPORT(val) my_progress_report(val)++ #define STB_IMAGE_RESIZE_IMPLEMENTATION+ #include "stb_image_resize.h"++ static void my_progress_report(float progress)+ {+ printf("Progress: %f%%\n", progress*100);+ }++ MAX CHANNELS+ If your image has more than 64 channels, define STBIR_MAX_CHANNELS+ to the max you'll have.++ ALPHA CHANNEL+ Most of the resizing functions provide the ability to control how+ the alpha channel of an image is processed. The important things+ to know about this:++ 1. The best mathematically-behaved version of alpha to use is+ called "premultiplied alpha", in which the other color channels+ have had the alpha value multiplied in. If you use premultiplied+ alpha, linear filtering (such as image resampling done by this+ library, or performed in texture units on GPUs) does the "right+ thing". While premultiplied alpha is standard in the movie CGI+ industry, it is still uncommon in the videogame/real-time world.++ If you linearly filter non-premultiplied alpha, strange effects+ occur. (For example, the 50/50 average of 99% transparent bright green+ and 1% transparent black produces 50% transparent dark green when+ non-premultiplied, whereas premultiplied it produces 50%+ transparent near-black. The former introduces green energy+ that doesn't exist in the source image.)++ 2. Artists should not edit premultiplied-alpha images; artists+ want non-premultiplied alpha images. Thus, art tools generally output+ non-premultiplied alpha images.++ 3. You will get best results in most cases by converting images+ to premultiplied alpha before processing them mathematically.++ 4. If you pass the flag STBIR_FLAG_ALPHA_PREMULTIPLIED, the+ resizer does not do anything special for the alpha channel;+ it is resampled identically to other channels. This produces+ the correct results for premultiplied-alpha images, but produces+ less-than-ideal results for non-premultiplied-alpha images.++ 5. If you do not pass the flag STBIR_FLAG_ALPHA_PREMULTIPLIED,+ then the resizer weights the contribution of input pixels+ based on their alpha values, or, equivalently, it multiplies+ the alpha value into the color channels, resamples, then divides+ by the resultant alpha value. Input pixels which have alpha=0 do+ not contribute at all to output pixels unless _all_ of the input+ pixels affecting that output pixel have alpha=0, in which case+ the result for that pixel is the same as it would be without+ STBIR_FLAG_ALPHA_PREMULTIPLIED. However, this is only true for+ input images in integer formats. For input images in float format,+ input pixels with alpha=0 have no effect, and output pixels+ which have alpha=0 will be 0 in all channels. (For float images,+ you can manually achieve the same result by adding a tiny epsilon+ value to the alpha channel of every image, and then subtracting+ or clamping it at the end.)++ 6. You can suppress the behavior described in #5 and make+ all-0-alpha pixels have 0 in all channels by #defining+ STBIR_NO_ALPHA_EPSILON.++ 7. You can separately control whether the alpha channel is+ interpreted as linear or affected by the colorspace. By default+ it is linear; you almost never want to apply the colorspace.+ (For example, graphics hardware does not apply sRGB conversion+ to the alpha channel.)++ CONTRIBUTORS+ Jorge L Rodriguez: Implementation+ Sean Barrett: API design, optimizations+ Aras Pranckevicius: bugfix+ Nathan Reed: warning fixes++ REVISIONS+ 0.97 (2020-02-02) fixed warning+ 0.96 (2019-03-04) fixed warnings+ 0.95 (2017-07-23) fixed warnings+ 0.94 (2017-03-18) fixed warnings+ 0.93 (2017-03-03) fixed bug with certain combinations of heights+ 0.92 (2017-01-02) fix integer overflow on large (>2GB) images+ 0.91 (2016-04-02) fix warnings; fix handling of subpixel regions+ 0.90 (2014-09-17) first released version++ LICENSE+ See end of file for license information.++ TODO+ Don't decode all of the image data when only processing a partial tile+ Don't use full-width decode buffers when only processing a partial tile+ When processing wide images, break processing into tiles so data fits in L1 cache+ Installable filters?+ Resize that respects alpha test coverage+ (Reference code: FloatImage::alphaTestCoverage and FloatImage::scaleAlphaToCoverage:+ https://code.google.com/p/nvidia-texture-tools/source/browse/trunk/src/nvimage/FloatImage.cpp )+*/++#ifndef STBIR_INCLUDE_STB_IMAGE_RESIZE_H+#define STBIR_INCLUDE_STB_IMAGE_RESIZE_H++#ifdef _MSC_VER+typedef unsigned char stbir_uint8;+typedef unsigned short stbir_uint16;+typedef unsigned int stbir_uint32;+#else+#include <stdint.h>+typedef uint8_t stbir_uint8;+typedef uint16_t stbir_uint16;+typedef uint32_t stbir_uint32;+#endif++#ifndef STBIRDEF+#ifdef STB_IMAGE_RESIZE_STATIC+#define STBIRDEF static+#else+#ifdef __cplusplus+#define STBIRDEF extern "C"+#else+#define STBIRDEF extern+#endif+#endif+#endif++//////////////////////////////////////////////////////////////////////////////+//+// Easy-to-use API:+//+// * "input pixels" points to an array of image data with 'num_channels' channels (e.g. RGB=3, RGBA=4)+// * input_w is input image width (x-axis), input_h is input image height (y-axis)+// * stride is the offset between successive rows of image data in memory, in bytes. you can+// specify 0 to mean packed continuously in memory+// * alpha channel is treated identically to other channels.+// * colorspace is linear or sRGB as specified by function name+// * returned result is 1 for success or 0 in case of an error.+// #define STBIR_ASSERT() to trigger an assert on parameter validation errors.+// * Memory required grows approximately linearly with input and output size, but with+// discontinuities at input_w == output_w and input_h == output_h.+// * These functions use a "default" resampling filter defined at compile time. To change the filter,+// you can change the compile-time defaults by #defining STBIR_DEFAULT_FILTER_UPSAMPLE+// and STBIR_DEFAULT_FILTER_DOWNSAMPLE, or you can use the medium-complexity API.++STBIRDEF int stbir_resize_uint8( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes,+ unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,+ int num_channels);++STBIRDEF int stbir_resize_float( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes,+ float *output_pixels, int output_w, int output_h, int output_stride_in_bytes,+ int num_channels);+++// The following functions interpret image data as gamma-corrected sRGB.+// Specify STBIR_ALPHA_CHANNEL_NONE if you have no alpha channel,+// or otherwise provide the index of the alpha channel. Flags value+// of 0 will probably do the right thing if you're not sure what+// the flags mean.++#define STBIR_ALPHA_CHANNEL_NONE -1++// Set this flag if your texture has premultiplied alpha. Otherwise, stbir will+// use alpha-weighted resampling (effectively premultiplying, resampling,+// then unpremultiplying).+#define STBIR_FLAG_ALPHA_PREMULTIPLIED (1 << 0)+// The specified alpha channel should be handled as gamma-corrected value even+// when doing sRGB operations.+#define STBIR_FLAG_ALPHA_USES_COLORSPACE (1 << 1)++STBIRDEF int stbir_resize_uint8_srgb(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes,+ unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,+ int num_channels, int alpha_channel, int flags);+++typedef enum+{+ STBIR_EDGE_CLAMP = 1,+ STBIR_EDGE_REFLECT = 2,+ STBIR_EDGE_WRAP = 3,+ STBIR_EDGE_ZERO = 4,+} stbir_edge;++// This function adds the ability to specify how requests to sample off the edge of the image are handled.+STBIRDEF int stbir_resize_uint8_srgb_edgemode(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes,+ unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,+ int num_channels, int alpha_channel, int flags,+ stbir_edge edge_wrap_mode);++//////////////////////////////////////////////////////////////////////////////+//+// Medium-complexity API+//+// This extends the easy-to-use API as follows:+//+// * Alpha-channel can be processed separately+// * If alpha_channel is not STBIR_ALPHA_CHANNEL_NONE+// * Alpha channel will not be gamma corrected (unless flags&STBIR_FLAG_GAMMA_CORRECT)+// * Filters will be weighted by alpha channel (unless flags&STBIR_FLAG_ALPHA_PREMULTIPLIED)+// * Filter can be selected explicitly+// * uint16 image type+// * sRGB colorspace available for all types+// * context parameter for passing to STBIR_MALLOC++typedef enum+{+ STBIR_FILTER_DEFAULT = 0, // use same filter type that easy-to-use API chooses+ STBIR_FILTER_BOX = 1, // A trapezoid w/1-pixel wide ramps, same result as box for integer scale ratios+ STBIR_FILTER_TRIANGLE = 2, // On upsampling, produces same results as bilinear texture filtering+ STBIR_FILTER_CUBICBSPLINE = 3, // The cubic b-spline (aka Mitchell-Netrevalli with B=1,C=0), gaussian-esque+ STBIR_FILTER_CATMULLROM = 4, // An interpolating cubic spline+ STBIR_FILTER_MITCHELL = 5, // Mitchell-Netrevalli filter with B=1/3, C=1/3+} stbir_filter;++typedef enum+{+ STBIR_COLORSPACE_LINEAR,+ STBIR_COLORSPACE_SRGB,++ STBIR_MAX_COLORSPACES,+} stbir_colorspace;++// The following functions are all identical except for the type of the image data++STBIRDEF int stbir_resize_uint8_generic( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes,+ unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,+ int num_channels, int alpha_channel, int flags,+ stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space,+ void *alloc_context);++STBIRDEF int stbir_resize_uint16_generic(const stbir_uint16 *input_pixels , int input_w , int input_h , int input_stride_in_bytes,+ stbir_uint16 *output_pixels , int output_w, int output_h, int output_stride_in_bytes,+ int num_channels, int alpha_channel, int flags,+ stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space,+ void *alloc_context);++STBIRDEF int stbir_resize_float_generic( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes,+ float *output_pixels , int output_w, int output_h, int output_stride_in_bytes,+ int num_channels, int alpha_channel, int flags,+ stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space,+ void *alloc_context);++++//////////////////////////////////////////////////////////////////////////////+//+// Full-complexity API+//+// This extends the medium API as follows:+//+// * uint32 image type+// * not typesafe+// * separate filter types for each axis+// * separate edge modes for each axis+// * can specify scale explicitly for subpixel correctness+// * can specify image source tile using texture coordinates++typedef enum+{+ STBIR_TYPE_UINT8 ,+ STBIR_TYPE_UINT16,+ STBIR_TYPE_UINT32,+ STBIR_TYPE_FLOAT ,++ STBIR_MAX_TYPES+} stbir_datatype;++STBIRDEF int stbir_resize( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes,+ void *output_pixels, int output_w, int output_h, int output_stride_in_bytes,+ stbir_datatype datatype,+ int num_channels, int alpha_channel, int flags,+ stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical,+ stbir_filter filter_horizontal, stbir_filter filter_vertical,+ stbir_colorspace space, void *alloc_context);++STBIRDEF int stbir_resize_subpixel(const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes,+ void *output_pixels, int output_w, int output_h, int output_stride_in_bytes,+ stbir_datatype datatype,+ int num_channels, int alpha_channel, int flags,+ stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical,+ stbir_filter filter_horizontal, stbir_filter filter_vertical,+ stbir_colorspace space, void *alloc_context,+ float x_scale, float y_scale,+ float x_offset, float y_offset);++STBIRDEF int stbir_resize_region( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes,+ void *output_pixels, int output_w, int output_h, int output_stride_in_bytes,+ stbir_datatype datatype,+ int num_channels, int alpha_channel, int flags,+ stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical,+ stbir_filter filter_horizontal, stbir_filter filter_vertical,+ stbir_colorspace space, void *alloc_context,+ float s0, float t0, float s1, float t1);+// (s0, t0) & (s1, t1) are the top-left and bottom right corner (uv addressing style: [0, 1]x[0, 1]) of a region of the input image to use.++//+//+//// end header file /////////////////////////////////////////////////////+#endif // STBIR_INCLUDE_STB_IMAGE_RESIZE_H++++++#ifdef STB_IMAGE_RESIZE_IMPLEMENTATION++#ifndef STBIR_ASSERT+#include <assert.h>+#define STBIR_ASSERT(x) assert(x)+#endif++// For memset+#include <string.h>++#include <math.h>++#ifndef STBIR_MALLOC+#include <stdlib.h>+// use comma operator to evaluate c, to avoid "unused parameter" warnings+#define STBIR_MALLOC(size,c) ((void)(c), malloc(size))+#define STBIR_FREE(ptr,c) ((void)(c), free(ptr))+#endif++#ifndef _MSC_VER+#ifdef __cplusplus+#define stbir__inline inline+#else+#define stbir__inline+#endif+#else+#define stbir__inline __forceinline+#endif+++// should produce compiler error if size is wrong+typedef unsigned char stbir__validate_uint32[sizeof(stbir_uint32) == 4 ? 1 : -1];++#ifdef _MSC_VER+#define STBIR__NOTUSED(v) (void)(v)+#else+#define STBIR__NOTUSED(v) (void)sizeof(v)+#endif++#define STBIR__ARRAY_SIZE(a) (sizeof((a))/sizeof((a)[0]))++#ifndef STBIR_DEFAULT_FILTER_UPSAMPLE+#define STBIR_DEFAULT_FILTER_UPSAMPLE STBIR_FILTER_CATMULLROM+#endif++#ifndef STBIR_DEFAULT_FILTER_DOWNSAMPLE+#define STBIR_DEFAULT_FILTER_DOWNSAMPLE STBIR_FILTER_MITCHELL+#endif++#ifndef STBIR_PROGRESS_REPORT+#define STBIR_PROGRESS_REPORT(float_0_to_1)+#endif++#ifndef STBIR_MAX_CHANNELS+#define STBIR_MAX_CHANNELS 64+#endif++#if STBIR_MAX_CHANNELS > 65536+#error "Too many channels; STBIR_MAX_CHANNELS must be no more than 65536."+// because we store the indices in 16-bit variables+#endif++// This value is added to alpha just before premultiplication to avoid+// zeroing out color values. It is equivalent to 2^-80. If you don't want+// that behavior (it may interfere if you have floating point images with+// very small alpha values) then you can define STBIR_NO_ALPHA_EPSILON to+// disable it.+#ifndef STBIR_ALPHA_EPSILON+#define STBIR_ALPHA_EPSILON ((float)1 / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20))+#endif++++#ifdef _MSC_VER+#define STBIR__UNUSED_PARAM(v) (void)(v)+#else+#define STBIR__UNUSED_PARAM(v) (void)sizeof(v)+#endif++// must match stbir_datatype+static unsigned char stbir__type_size[] = {+ 1, // STBIR_TYPE_UINT8+ 2, // STBIR_TYPE_UINT16+ 4, // STBIR_TYPE_UINT32+ 4, // STBIR_TYPE_FLOAT+};++// Kernel function centered at 0+typedef float (stbir__kernel_fn)(float x, float scale);+typedef float (stbir__support_fn)(float scale);++typedef struct+{+ stbir__kernel_fn* kernel;+ stbir__support_fn* support;+} stbir__filter_info;++// When upsampling, the contributors are which source pixels contribute.+// When downsampling, the contributors are which destination pixels are contributed to.+typedef struct+{+ int n0; // First contributing pixel+ int n1; // Last contributing pixel+} stbir__contributors;++typedef struct+{+ const void* input_data;+ int input_w;+ int input_h;+ int input_stride_bytes;++ void* output_data;+ int output_w;+ int output_h;+ int output_stride_bytes;++ float s0, t0, s1, t1;++ float horizontal_shift; // Units: output pixels+ float vertical_shift; // Units: output pixels+ float horizontal_scale;+ float vertical_scale;++ int channels;+ int alpha_channel;+ stbir_uint32 flags;+ stbir_datatype type;+ stbir_filter horizontal_filter;+ stbir_filter vertical_filter;+ stbir_edge edge_horizontal;+ stbir_edge edge_vertical;+ stbir_colorspace colorspace;++ stbir__contributors* horizontal_contributors;+ float* horizontal_coefficients;++ stbir__contributors* vertical_contributors;+ float* vertical_coefficients;++ int decode_buffer_pixels;+ float* decode_buffer;++ float* horizontal_buffer;++ // cache these because ceil/floor are inexplicably showing up in profile+ int horizontal_coefficient_width;+ int vertical_coefficient_width;+ int horizontal_filter_pixel_width;+ int vertical_filter_pixel_width;+ int horizontal_filter_pixel_margin;+ int vertical_filter_pixel_margin;+ int horizontal_num_contributors;+ int vertical_num_contributors;++ int ring_buffer_length_bytes; // The length of an individual entry in the ring buffer. The total number of ring buffers is stbir__get_filter_pixel_width(filter)+ int ring_buffer_num_entries; // Total number of entries in the ring buffer.+ int ring_buffer_first_scanline;+ int ring_buffer_last_scanline;+ int ring_buffer_begin_index; // first_scanline is at this index in the ring buffer+ float* ring_buffer;++ float* encode_buffer; // A temporary buffer to store floats so we don't lose precision while we do multiply-adds.++ int horizontal_contributors_size;+ int horizontal_coefficients_size;+ int vertical_contributors_size;+ int vertical_coefficients_size;+ int decode_buffer_size;+ int horizontal_buffer_size;+ int ring_buffer_size;+ int encode_buffer_size;+} stbir__info;+++static const float stbir__max_uint8_as_float = 255.0f;+static const float stbir__max_uint16_as_float = 65535.0f;+static const double stbir__max_uint32_as_float = 4294967295.0;+++static stbir__inline int stbir__min(int a, int b)+{+ return a < b ? a : b;+}++static stbir__inline float stbir__saturate(float x)+{+ if (x < 0)+ return 0;++ if (x > 1)+ return 1;++ return x;+}++#ifdef STBIR_SATURATE_INT+static stbir__inline stbir_uint8 stbir__saturate8(int x)+{+ if ((unsigned int) x <= 255)+ return x;++ if (x < 0)+ return 0;++ return 255;+}++static stbir__inline stbir_uint16 stbir__saturate16(int x)+{+ if ((unsigned int) x <= 65535)+ return x;++ if (x < 0)+ return 0;++ return 65535;+}+#endif++static float stbir__srgb_uchar_to_linear_float[256] = {+ 0.000000f, 0.000304f, 0.000607f, 0.000911f, 0.001214f, 0.001518f, 0.001821f, 0.002125f, 0.002428f, 0.002732f, 0.003035f,+ 0.003347f, 0.003677f, 0.004025f, 0.004391f, 0.004777f, 0.005182f, 0.005605f, 0.006049f, 0.006512f, 0.006995f, 0.007499f,+ 0.008023f, 0.008568f, 0.009134f, 0.009721f, 0.010330f, 0.010960f, 0.011612f, 0.012286f, 0.012983f, 0.013702f, 0.014444f,+ 0.015209f, 0.015996f, 0.016807f, 0.017642f, 0.018500f, 0.019382f, 0.020289f, 0.021219f, 0.022174f, 0.023153f, 0.024158f,+ 0.025187f, 0.026241f, 0.027321f, 0.028426f, 0.029557f, 0.030713f, 0.031896f, 0.033105f, 0.034340f, 0.035601f, 0.036889f,+ 0.038204f, 0.039546f, 0.040915f, 0.042311f, 0.043735f, 0.045186f, 0.046665f, 0.048172f, 0.049707f, 0.051269f, 0.052861f,+ 0.054480f, 0.056128f, 0.057805f, 0.059511f, 0.061246f, 0.063010f, 0.064803f, 0.066626f, 0.068478f, 0.070360f, 0.072272f,+ 0.074214f, 0.076185f, 0.078187f, 0.080220f, 0.082283f, 0.084376f, 0.086500f, 0.088656f, 0.090842f, 0.093059f, 0.095307f,+ 0.097587f, 0.099899f, 0.102242f, 0.104616f, 0.107023f, 0.109462f, 0.111932f, 0.114435f, 0.116971f, 0.119538f, 0.122139f,+ 0.124772f, 0.127438f, 0.130136f, 0.132868f, 0.135633f, 0.138432f, 0.141263f, 0.144128f, 0.147027f, 0.149960f, 0.152926f,+ 0.155926f, 0.158961f, 0.162029f, 0.165132f, 0.168269f, 0.171441f, 0.174647f, 0.177888f, 0.181164f, 0.184475f, 0.187821f,+ 0.191202f, 0.194618f, 0.198069f, 0.201556f, 0.205079f, 0.208637f, 0.212231f, 0.215861f, 0.219526f, 0.223228f, 0.226966f,+ 0.230740f, 0.234551f, 0.238398f, 0.242281f, 0.246201f, 0.250158f, 0.254152f, 0.258183f, 0.262251f, 0.266356f, 0.270498f,+ 0.274677f, 0.278894f, 0.283149f, 0.287441f, 0.291771f, 0.296138f, 0.300544f, 0.304987f, 0.309469f, 0.313989f, 0.318547f,+ 0.323143f, 0.327778f, 0.332452f, 0.337164f, 0.341914f, 0.346704f, 0.351533f, 0.356400f, 0.361307f, 0.366253f, 0.371238f,+ 0.376262f, 0.381326f, 0.386430f, 0.391573f, 0.396755f, 0.401978f, 0.407240f, 0.412543f, 0.417885f, 0.423268f, 0.428691f,+ 0.434154f, 0.439657f, 0.445201f, 0.450786f, 0.456411f, 0.462077f, 0.467784f, 0.473532f, 0.479320f, 0.485150f, 0.491021f,+ 0.496933f, 0.502887f, 0.508881f, 0.514918f, 0.520996f, 0.527115f, 0.533276f, 0.539480f, 0.545725f, 0.552011f, 0.558340f,+ 0.564712f, 0.571125f, 0.577581f, 0.584078f, 0.590619f, 0.597202f, 0.603827f, 0.610496f, 0.617207f, 0.623960f, 0.630757f,+ 0.637597f, 0.644480f, 0.651406f, 0.658375f, 0.665387f, 0.672443f, 0.679543f, 0.686685f, 0.693872f, 0.701102f, 0.708376f,+ 0.715694f, 0.723055f, 0.730461f, 0.737911f, 0.745404f, 0.752942f, 0.760525f, 0.768151f, 0.775822f, 0.783538f, 0.791298f,+ 0.799103f, 0.806952f, 0.814847f, 0.822786f, 0.830770f, 0.838799f, 0.846873f, 0.854993f, 0.863157f, 0.871367f, 0.879622f,+ 0.887923f, 0.896269f, 0.904661f, 0.913099f, 0.921582f, 0.930111f, 0.938686f, 0.947307f, 0.955974f, 0.964686f, 0.973445f,+ 0.982251f, 0.991102f, 1.0f+};++static float stbir__srgb_to_linear(float f)+{+ if (f <= 0.04045f)+ return f / 12.92f;+ else+ return (float)pow((f + 0.055f) / 1.055f, 2.4f);+}++static float stbir__linear_to_srgb(float f)+{+ if (f <= 0.0031308f)+ return f * 12.92f;+ else+ return 1.055f * (float)pow(f, 1 / 2.4f) - 0.055f;+}++#ifndef STBIR_NON_IEEE_FLOAT+// From https://gist.github.com/rygorous/2203834++typedef union+{+ stbir_uint32 u;+ float f;+} stbir__FP32;++static const stbir_uint32 fp32_to_srgb8_tab4[104] = {+ 0x0073000d, 0x007a000d, 0x0080000d, 0x0087000d, 0x008d000d, 0x0094000d, 0x009a000d, 0x00a1000d,+ 0x00a7001a, 0x00b4001a, 0x00c1001a, 0x00ce001a, 0x00da001a, 0x00e7001a, 0x00f4001a, 0x0101001a,+ 0x010e0033, 0x01280033, 0x01410033, 0x015b0033, 0x01750033, 0x018f0033, 0x01a80033, 0x01c20033,+ 0x01dc0067, 0x020f0067, 0x02430067, 0x02760067, 0x02aa0067, 0x02dd0067, 0x03110067, 0x03440067,+ 0x037800ce, 0x03df00ce, 0x044600ce, 0x04ad00ce, 0x051400ce, 0x057b00c5, 0x05dd00bc, 0x063b00b5,+ 0x06970158, 0x07420142, 0x07e30130, 0x087b0120, 0x090b0112, 0x09940106, 0x0a1700fc, 0x0a9500f2,+ 0x0b0f01cb, 0x0bf401ae, 0x0ccb0195, 0x0d950180, 0x0e56016e, 0x0f0d015e, 0x0fbc0150, 0x10630143,+ 0x11070264, 0x1238023e, 0x1357021d, 0x14660201, 0x156601e9, 0x165a01d3, 0x174401c0, 0x182401af,+ 0x18fe0331, 0x1a9602fe, 0x1c1502d2, 0x1d7e02ad, 0x1ed4028d, 0x201a0270, 0x21520256, 0x227d0240,+ 0x239f0443, 0x25c003fe, 0x27bf03c4, 0x29a10392, 0x2b6a0367, 0x2d1d0341, 0x2ebe031f, 0x304d0300,+ 0x31d105b0, 0x34a80555, 0x37520507, 0x39d504c5, 0x3c37048b, 0x3e7c0458, 0x40a8042a, 0x42bd0401,+ 0x44c20798, 0x488e071e, 0x4c1c06b6, 0x4f76065d, 0x52a50610, 0x55ac05cc, 0x5892058f, 0x5b590559,+ 0x5e0c0a23, 0x631c0980, 0x67db08f6, 0x6c55087f, 0x70940818, 0x74a007bd, 0x787d076c, 0x7c330723,+};++static stbir_uint8 stbir__linear_to_srgb_uchar(float in)+{+ static const stbir__FP32 almostone = { 0x3f7fffff }; // 1-eps+ static const stbir__FP32 minval = { (127-13) << 23 };+ stbir_uint32 tab,bias,scale,t;+ stbir__FP32 f;++ // Clamp to [2^(-13), 1-eps]; these two values map to 0 and 1, respectively.+ // The tests are carefully written so that NaNs map to 0, same as in the reference+ // implementation.+ if (!(in > minval.f)) // written this way to catch NaNs+ in = minval.f;+ if (in > almostone.f)+ in = almostone.f;++ // Do the table lookup and unpack bias, scale+ f.f = in;+ tab = fp32_to_srgb8_tab4[(f.u - minval.u) >> 20];+ bias = (tab >> 16) << 9;+ scale = tab & 0xffff;++ // Grab next-highest mantissa bits and perform linear interpolation+ t = (f.u >> 12) & 0xff;+ return (unsigned char) ((bias + scale*t) >> 16);+}++#else+// sRGB transition values, scaled by 1<<28+static int stbir__srgb_offset_to_linear_scaled[256] =+{+ 0, 40738, 122216, 203693, 285170, 366648, 448125, 529603,+ 611080, 692557, 774035, 855852, 942009, 1033024, 1128971, 1229926,+ 1335959, 1447142, 1563542, 1685229, 1812268, 1944725, 2082664, 2226148,+ 2375238, 2529996, 2690481, 2856753, 3028870, 3206888, 3390865, 3580856,+ 3776916, 3979100, 4187460, 4402049, 4622919, 4850123, 5083710, 5323731,+ 5570236, 5823273, 6082892, 6349140, 6622065, 6901714, 7188133, 7481369,+ 7781466, 8088471, 8402427, 8723380, 9051372, 9386448, 9728650, 10078021,+ 10434603, 10798439, 11169569, 11548036, 11933879, 12327139, 12727857, 13136073,+ 13551826, 13975156, 14406100, 14844697, 15290987, 15745007, 16206795, 16676389,+ 17153826, 17639142, 18132374, 18633560, 19142734, 19659934, 20185196, 20718552,+ 21260042, 21809696, 22367554, 22933648, 23508010, 24090680, 24681686, 25281066,+ 25888850, 26505076, 27129772, 27762974, 28404716, 29055026, 29713942, 30381490,+ 31057708, 31742624, 32436272, 33138682, 33849884, 34569912, 35298800, 36036568,+ 36783260, 37538896, 38303512, 39077136, 39859796, 40651528, 41452360, 42262316,+ 43081432, 43909732, 44747252, 45594016, 46450052, 47315392, 48190064, 49074096,+ 49967516, 50870356, 51782636, 52704392, 53635648, 54576432, 55526772, 56486700,+ 57456236, 58435408, 59424248, 60422780, 61431036, 62449032, 63476804, 64514376,+ 65561776, 66619028, 67686160, 68763192, 69850160, 70947088, 72053992, 73170912,+ 74297864, 75434880, 76581976, 77739184, 78906536, 80084040, 81271736, 82469648,+ 83677792, 84896192, 86124888, 87363888, 88613232, 89872928, 91143016, 92423512,+ 93714432, 95015816, 96327688, 97650056, 98982952, 100326408, 101680440, 103045072,+ 104420320, 105806224, 107202800, 108610064, 110028048, 111456776, 112896264, 114346544,+ 115807632, 117279552, 118762328, 120255976, 121760536, 123276016, 124802440, 126339832,+ 127888216, 129447616, 131018048, 132599544, 134192112, 135795792, 137410592, 139036528,+ 140673648, 142321952, 143981456, 145652208, 147334208, 149027488, 150732064, 152447968,+ 154175200, 155913792, 157663776, 159425168, 161197984, 162982240, 164777968, 166585184,+ 168403904, 170234160, 172075968, 173929344, 175794320, 177670896, 179559120, 181458992,+ 183370528, 185293776, 187228736, 189175424, 191133888, 193104112, 195086128, 197079968,+ 199085648, 201103184, 203132592, 205173888, 207227120, 209292272, 211369392, 213458480,+ 215559568, 217672656, 219797792, 221934976, 224084240, 226245600, 228419056, 230604656,+ 232802400, 235012320, 237234432, 239468736, 241715280, 243974080, 246245120, 248528464,+ 250824112, 253132064, 255452368, 257785040, 260130080, 262487520, 264857376, 267239664,+};++static stbir_uint8 stbir__linear_to_srgb_uchar(float f)+{+ int x = (int) (f * (1 << 28)); // has headroom so you don't need to clamp+ int v = 0;+ int i;++ // Refine the guess with a short binary search.+ i = v + 128; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;+ i = v + 64; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;+ i = v + 32; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;+ i = v + 16; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;+ i = v + 8; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;+ i = v + 4; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;+ i = v + 2; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;+ i = v + 1; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;++ return (stbir_uint8) v;+}+#endif++static float stbir__filter_trapezoid(float x, float scale)+{+ float halfscale = scale / 2;+ float t = 0.5f + halfscale;+ STBIR_ASSERT(scale <= 1);++ x = (float)fabs(x);++ if (x >= t)+ return 0;+ else+ {+ float r = 0.5f - halfscale;+ if (x <= r)+ return 1;+ else+ return (t - x) / scale;+ }+}++static float stbir__support_trapezoid(float scale)+{+ STBIR_ASSERT(scale <= 1);+ return 0.5f + scale / 2;+}++static float stbir__filter_triangle(float x, float s)+{+ STBIR__UNUSED_PARAM(s);++ x = (float)fabs(x);++ if (x <= 1.0f)+ return 1 - x;+ else+ return 0;+}++static float stbir__filter_cubic(float x, float s)+{+ STBIR__UNUSED_PARAM(s);++ x = (float)fabs(x);++ if (x < 1.0f)+ return (4 + x*x*(3*x - 6))/6;+ else if (x < 2.0f)+ return (8 + x*(-12 + x*(6 - x)))/6;++ return (0.0f);+}++static float stbir__filter_catmullrom(float x, float s)+{+ STBIR__UNUSED_PARAM(s);++ x = (float)fabs(x);++ if (x < 1.0f)+ return 1 - x*x*(2.5f - 1.5f*x);+ else if (x < 2.0f)+ return 2 - x*(4 + x*(0.5f*x - 2.5f));++ return (0.0f);+}++static float stbir__filter_mitchell(float x, float s)+{+ STBIR__UNUSED_PARAM(s);++ x = (float)fabs(x);++ if (x < 1.0f)+ return (16 + x*x*(21 * x - 36))/18;+ else if (x < 2.0f)+ return (32 + x*(-60 + x*(36 - 7*x)))/18;++ return (0.0f);+}++static float stbir__support_zero(float s)+{+ STBIR__UNUSED_PARAM(s);+ return 0;+}++static float stbir__support_one(float s)+{+ STBIR__UNUSED_PARAM(s);+ return 1;+}++static float stbir__support_two(float s)+{+ STBIR__UNUSED_PARAM(s);+ return 2;+}++static stbir__filter_info stbir__filter_info_table[] = {+ { NULL, stbir__support_zero },+ { stbir__filter_trapezoid, stbir__support_trapezoid },+ { stbir__filter_triangle, stbir__support_one },+ { stbir__filter_cubic, stbir__support_two },+ { stbir__filter_catmullrom, stbir__support_two },+ { stbir__filter_mitchell, stbir__support_two },+};++stbir__inline static int stbir__use_upsampling(float ratio)+{+ return ratio > 1;+}++stbir__inline static int stbir__use_width_upsampling(stbir__info* stbir_info)+{+ return stbir__use_upsampling(stbir_info->horizontal_scale);+}++stbir__inline static int stbir__use_height_upsampling(stbir__info* stbir_info)+{+ return stbir__use_upsampling(stbir_info->vertical_scale);+}++// This is the maximum number of input samples that can affect an output sample+// with the given filter+static int stbir__get_filter_pixel_width(stbir_filter filter, float scale)+{+ STBIR_ASSERT(filter != 0);+ STBIR_ASSERT(filter < STBIR__ARRAY_SIZE(stbir__filter_info_table));++ if (stbir__use_upsampling(scale))+ return (int)ceil(stbir__filter_info_table[filter].support(1/scale) * 2);+ else+ return (int)ceil(stbir__filter_info_table[filter].support(scale) * 2 / scale);+}++// This is how much to expand buffers to account for filters seeking outside+// the image boundaries.+static int stbir__get_filter_pixel_margin(stbir_filter filter, float scale)+{+ return stbir__get_filter_pixel_width(filter, scale) / 2;+}++static int stbir__get_coefficient_width(stbir_filter filter, float scale)+{+ if (stbir__use_upsampling(scale))+ return (int)ceil(stbir__filter_info_table[filter].support(1 / scale) * 2);+ else+ return (int)ceil(stbir__filter_info_table[filter].support(scale) * 2);+}++static int stbir__get_contributors(float scale, stbir_filter filter, int input_size, int output_size)+{+ if (stbir__use_upsampling(scale))+ return output_size;+ else+ return (input_size + stbir__get_filter_pixel_margin(filter, scale) * 2);+}++static int stbir__get_total_horizontal_coefficients(stbir__info* info)+{+ return info->horizontal_num_contributors+ * stbir__get_coefficient_width (info->horizontal_filter, info->horizontal_scale);+}++static int stbir__get_total_vertical_coefficients(stbir__info* info)+{+ return info->vertical_num_contributors+ * stbir__get_coefficient_width (info->vertical_filter, info->vertical_scale);+}++static stbir__contributors* stbir__get_contributor(stbir__contributors* contributors, int n)+{+ return &contributors[n];+}++// For perf reasons this code is duplicated in stbir__resample_horizontal_upsample/downsample,+// if you change it here change it there too.+static float* stbir__get_coefficient(float* coefficients, stbir_filter filter, float scale, int n, int c)+{+ int width = stbir__get_coefficient_width(filter, scale);+ return &coefficients[width*n + c];+}++static int stbir__edge_wrap_slow(stbir_edge edge, int n, int max)+{+ switch (edge)+ {+ case STBIR_EDGE_ZERO:+ return 0; // we'll decode the wrong pixel here, and then overwrite with 0s later++ case STBIR_EDGE_CLAMP:+ if (n < 0)+ return 0;++ if (n >= max)+ return max - 1;++ return n; // NOTREACHED++ case STBIR_EDGE_REFLECT:+ {+ if (n < 0)+ {+ if (n < max)+ return -n;+ else+ return max - 1;+ }++ if (n >= max)+ {+ int max2 = max * 2;+ if (n >= max2)+ return 0;+ else+ return max2 - n - 1;+ }++ return n; // NOTREACHED+ }++ case STBIR_EDGE_WRAP:+ if (n >= 0)+ return (n % max);+ else+ {+ int m = (-n) % max;++ if (m != 0)+ m = max - m;++ return (m);+ }+ // NOTREACHED++ default:+ STBIR_ASSERT(!"Unimplemented edge type");+ return 0;+ }+}++stbir__inline static int stbir__edge_wrap(stbir_edge edge, int n, int max)+{+ // avoid per-pixel switch+ if (n >= 0 && n < max)+ return n;+ return stbir__edge_wrap_slow(edge, n, max);+}++// What input pixels contribute to this output pixel?+static void stbir__calculate_sample_range_upsample(int n, float out_filter_radius, float scale_ratio, float out_shift, int* in_first_pixel, int* in_last_pixel, float* in_center_of_out)+{+ float out_pixel_center = (float)n + 0.5f;+ float out_pixel_influence_lowerbound = out_pixel_center - out_filter_radius;+ float out_pixel_influence_upperbound = out_pixel_center + out_filter_radius;++ float in_pixel_influence_lowerbound = (out_pixel_influence_lowerbound + out_shift) / scale_ratio;+ float in_pixel_influence_upperbound = (out_pixel_influence_upperbound + out_shift) / scale_ratio;++ *in_center_of_out = (out_pixel_center + out_shift) / scale_ratio;+ *in_first_pixel = (int)(floor(in_pixel_influence_lowerbound + 0.5));+ *in_last_pixel = (int)(floor(in_pixel_influence_upperbound - 0.5));+}++// What output pixels does this input pixel contribute to?+static void stbir__calculate_sample_range_downsample(int n, float in_pixels_radius, float scale_ratio, float out_shift, int* out_first_pixel, int* out_last_pixel, float* out_center_of_in)+{+ float in_pixel_center = (float)n + 0.5f;+ float in_pixel_influence_lowerbound = in_pixel_center - in_pixels_radius;+ float in_pixel_influence_upperbound = in_pixel_center + in_pixels_radius;++ float out_pixel_influence_lowerbound = in_pixel_influence_lowerbound * scale_ratio - out_shift;+ float out_pixel_influence_upperbound = in_pixel_influence_upperbound * scale_ratio - out_shift;++ *out_center_of_in = in_pixel_center * scale_ratio - out_shift;+ *out_first_pixel = (int)(floor(out_pixel_influence_lowerbound + 0.5));+ *out_last_pixel = (int)(floor(out_pixel_influence_upperbound - 0.5));+}++static void stbir__calculate_coefficients_upsample(stbir_filter filter, float scale, int in_first_pixel, int in_last_pixel, float in_center_of_out, stbir__contributors* contributor, float* coefficient_group)+{+ int i;+ float total_filter = 0;+ float filter_scale;++ STBIR_ASSERT(in_last_pixel - in_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(1/scale) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical.++ contributor->n0 = in_first_pixel;+ contributor->n1 = in_last_pixel;++ STBIR_ASSERT(contributor->n1 >= contributor->n0);++ for (i = 0; i <= in_last_pixel - in_first_pixel; i++)+ {+ float in_pixel_center = (float)(i + in_first_pixel) + 0.5f;+ coefficient_group[i] = stbir__filter_info_table[filter].kernel(in_center_of_out - in_pixel_center, 1 / scale);++ // If the coefficient is zero, skip it. (Don't do the <0 check here, we want the influence of those outside pixels.)+ if (i == 0 && !coefficient_group[i])+ {+ contributor->n0 = ++in_first_pixel;+ i--;+ continue;+ }++ total_filter += coefficient_group[i];+ }++ // NOTE(fg): Not actually true in general, nor is there any reason to expect it should be.+ // It would be true in exact math but is at best approximately true in floating-point math,+ // and it would not make sense to try and put actual bounds on this here because it depends+ // on the image aspect ratio which can get pretty extreme.+ //STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(in_last_pixel + 1) + 0.5f - in_center_of_out, 1/scale) == 0);++ STBIR_ASSERT(total_filter > 0.9);+ STBIR_ASSERT(total_filter < 1.1f); // Make sure it's not way off.++ // Make sure the sum of all coefficients is 1.+ filter_scale = 1 / total_filter;++ for (i = 0; i <= in_last_pixel - in_first_pixel; i++)+ coefficient_group[i] *= filter_scale;++ for (i = in_last_pixel - in_first_pixel; i >= 0; i--)+ {+ if (coefficient_group[i])+ break;++ // This line has no weight. We can skip it.+ contributor->n1 = contributor->n0 + i - 1;+ }+}++static void stbir__calculate_coefficients_downsample(stbir_filter filter, float scale_ratio, int out_first_pixel, int out_last_pixel, float out_center_of_in, stbir__contributors* contributor, float* coefficient_group)+{+ int i;++ STBIR_ASSERT(out_last_pixel - out_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(scale_ratio) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical.++ contributor->n0 = out_first_pixel;+ contributor->n1 = out_last_pixel;++ STBIR_ASSERT(contributor->n1 >= contributor->n0);++ for (i = 0; i <= out_last_pixel - out_first_pixel; i++)+ {+ float out_pixel_center = (float)(i + out_first_pixel) + 0.5f;+ float x = out_pixel_center - out_center_of_in;+ coefficient_group[i] = stbir__filter_info_table[filter].kernel(x, scale_ratio) * scale_ratio;+ }++ // NOTE(fg): Not actually true in general, nor is there any reason to expect it should be.+ // It would be true in exact math but is at best approximately true in floating-point math,+ // and it would not make sense to try and put actual bounds on this here because it depends+ // on the image aspect ratio which can get pretty extreme.+ //STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(out_last_pixel + 1) + 0.5f - out_center_of_in, scale_ratio) == 0);++ for (i = out_last_pixel - out_first_pixel; i >= 0; i--)+ {+ if (coefficient_group[i])+ break;++ // This line has no weight. We can skip it.+ contributor->n1 = contributor->n0 + i - 1;+ }+}++static void stbir__normalize_downsample_coefficients(stbir__contributors* contributors, float* coefficients, stbir_filter filter, float scale_ratio, int input_size, int output_size)+{+ int num_contributors = stbir__get_contributors(scale_ratio, filter, input_size, output_size);+ int num_coefficients = stbir__get_coefficient_width(filter, scale_ratio);+ int i, j;+ int skip;++ for (i = 0; i < output_size; i++)+ {+ float scale;+ float total = 0;++ for (j = 0; j < num_contributors; j++)+ {+ if (i >= contributors[j].n0 && i <= contributors[j].n1)+ {+ float coefficient = *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i - contributors[j].n0);+ total += coefficient;+ }+ else if (i < contributors[j].n0)+ break;+ }++ STBIR_ASSERT(total > 0.9f);+ STBIR_ASSERT(total < 1.1f);++ scale = 1 / total;++ for (j = 0; j < num_contributors; j++)+ {+ if (i >= contributors[j].n0 && i <= contributors[j].n1)+ *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i - contributors[j].n0) *= scale;+ else if (i < contributors[j].n0)+ break;+ }+ }++ // Optimize: Skip zero coefficients and contributions outside of image bounds.+ // Do this after normalizing because normalization depends on the n0/n1 values.+ for (j = 0; j < num_contributors; j++)+ {+ int range, max, width;++ skip = 0;+ while (*stbir__get_coefficient(coefficients, filter, scale_ratio, j, skip) == 0)+ skip++;++ contributors[j].n0 += skip;++ while (contributors[j].n0 < 0)+ {+ contributors[j].n0++;+ skip++;+ }++ range = contributors[j].n1 - contributors[j].n0 + 1;+ max = stbir__min(num_coefficients, range);++ width = stbir__get_coefficient_width(filter, scale_ratio);+ for (i = 0; i < max; i++)+ {+ if (i + skip >= width)+ break;++ *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i) = *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i + skip);+ }++ continue;+ }++ // Using min to avoid writing into invalid pixels.+ for (i = 0; i < num_contributors; i++)+ contributors[i].n1 = stbir__min(contributors[i].n1, output_size - 1);+}++// Each scan line uses the same kernel values so we should calculate the kernel+// values once and then we can use them for every scan line.+static void stbir__calculate_filters(stbir__contributors* contributors, float* coefficients, stbir_filter filter, float scale_ratio, float shift, int input_size, int output_size)+{+ int n;+ int total_contributors = stbir__get_contributors(scale_ratio, filter, input_size, output_size);++ if (stbir__use_upsampling(scale_ratio))+ {+ float out_pixels_radius = stbir__filter_info_table[filter].support(1 / scale_ratio) * scale_ratio;++ // Looping through out pixels+ for (n = 0; n < total_contributors; n++)+ {+ float in_center_of_out; // Center of the current out pixel in the in pixel space+ int in_first_pixel, in_last_pixel;++ stbir__calculate_sample_range_upsample(n, out_pixels_radius, scale_ratio, shift, &in_first_pixel, &in_last_pixel, &in_center_of_out);++ stbir__calculate_coefficients_upsample(filter, scale_ratio, in_first_pixel, in_last_pixel, in_center_of_out, stbir__get_contributor(contributors, n), stbir__get_coefficient(coefficients, filter, scale_ratio, n, 0));+ }+ }+ else+ {+ float in_pixels_radius = stbir__filter_info_table[filter].support(scale_ratio) / scale_ratio;++ // Looping through in pixels+ for (n = 0; n < total_contributors; n++)+ {+ float out_center_of_in; // Center of the current out pixel in the in pixel space+ int out_first_pixel, out_last_pixel;+ int n_adjusted = n - stbir__get_filter_pixel_margin(filter, scale_ratio);++ stbir__calculate_sample_range_downsample(n_adjusted, in_pixels_radius, scale_ratio, shift, &out_first_pixel, &out_last_pixel, &out_center_of_in);++ stbir__calculate_coefficients_downsample(filter, scale_ratio, out_first_pixel, out_last_pixel, out_center_of_in, stbir__get_contributor(contributors, n), stbir__get_coefficient(coefficients, filter, scale_ratio, n, 0));+ }++ stbir__normalize_downsample_coefficients(contributors, coefficients, filter, scale_ratio, input_size, output_size);+ }+}++static float* stbir__get_decode_buffer(stbir__info* stbir_info)+{+ // The 0 index of the decode buffer starts after the margin. This makes+ // it okay to use negative indexes on the decode buffer.+ return &stbir_info->decode_buffer[stbir_info->horizontal_filter_pixel_margin * stbir_info->channels];+}++#define STBIR__DECODE(type, colorspace) ((int)(type) * (STBIR_MAX_COLORSPACES) + (int)(colorspace))++static void stbir__decode_scanline(stbir__info* stbir_info, int n)+{+ int c;+ int channels = stbir_info->channels;+ int alpha_channel = stbir_info->alpha_channel;+ int type = stbir_info->type;+ int colorspace = stbir_info->colorspace;+ int input_w = stbir_info->input_w;+ size_t input_stride_bytes = stbir_info->input_stride_bytes;+ float* decode_buffer = stbir__get_decode_buffer(stbir_info);+ stbir_edge edge_horizontal = stbir_info->edge_horizontal;+ stbir_edge edge_vertical = stbir_info->edge_vertical;+ size_t in_buffer_row_offset = stbir__edge_wrap(edge_vertical, n, stbir_info->input_h) * input_stride_bytes;+ const void* input_data = (char *) stbir_info->input_data + in_buffer_row_offset;+ int max_x = input_w + stbir_info->horizontal_filter_pixel_margin;+ int decode = STBIR__DECODE(type, colorspace);++ int x = -stbir_info->horizontal_filter_pixel_margin;++ // special handling for STBIR_EDGE_ZERO because it needs to return an item that doesn't appear in the input,+ // and we want to avoid paying overhead on every pixel if not STBIR_EDGE_ZERO+ if (edge_vertical == STBIR_EDGE_ZERO && (n < 0 || n >= stbir_info->input_h))+ {+ for (; x < max_x; x++)+ for (c = 0; c < channels; c++)+ decode_buffer[x*channels + c] = 0;+ return;+ }++ switch (decode)+ {+ case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_LINEAR):+ for (; x < max_x; x++)+ {+ int decode_pixel_index = x * channels;+ int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;+ for (c = 0; c < channels; c++)+ decode_buffer[decode_pixel_index + c] = ((float)((const unsigned char*)input_data)[input_pixel_index + c]) / stbir__max_uint8_as_float;+ }+ break;++ case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_SRGB):+ for (; x < max_x; x++)+ {+ int decode_pixel_index = x * channels;+ int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;+ for (c = 0; c < channels; c++)+ decode_buffer[decode_pixel_index + c] = stbir__srgb_uchar_to_linear_float[((const unsigned char*)input_data)[input_pixel_index + c]];++ if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE))+ decode_buffer[decode_pixel_index + alpha_channel] = ((float)((const unsigned char*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint8_as_float;+ }+ break;++ case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_LINEAR):+ for (; x < max_x; x++)+ {+ int decode_pixel_index = x * channels;+ int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;+ for (c = 0; c < channels; c++)+ decode_buffer[decode_pixel_index + c] = ((float)((const unsigned short*)input_data)[input_pixel_index + c]) / stbir__max_uint16_as_float;+ }+ break;++ case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_SRGB):+ for (; x < max_x; x++)+ {+ int decode_pixel_index = x * channels;+ int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;+ for (c = 0; c < channels; c++)+ decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear(((float)((const unsigned short*)input_data)[input_pixel_index + c]) / stbir__max_uint16_as_float);++ if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE))+ decode_buffer[decode_pixel_index + alpha_channel] = ((float)((const unsigned short*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint16_as_float;+ }+ break;++ case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_LINEAR):+ for (; x < max_x; x++)+ {+ int decode_pixel_index = x * channels;+ int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;+ for (c = 0; c < channels; c++)+ decode_buffer[decode_pixel_index + c] = (float)(((double)((const unsigned int*)input_data)[input_pixel_index + c]) / stbir__max_uint32_as_float);+ }+ break;++ case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_SRGB):+ for (; x < max_x; x++)+ {+ int decode_pixel_index = x * channels;+ int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;+ for (c = 0; c < channels; c++)+ decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear((float)(((double)((const unsigned int*)input_data)[input_pixel_index + c]) / stbir__max_uint32_as_float));++ if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE))+ decode_buffer[decode_pixel_index + alpha_channel] = (float)(((double)((const unsigned int*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint32_as_float);+ }+ break;++ case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_LINEAR):+ for (; x < max_x; x++)+ {+ int decode_pixel_index = x * channels;+ int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;+ for (c = 0; c < channels; c++)+ decode_buffer[decode_pixel_index + c] = ((const float*)input_data)[input_pixel_index + c];+ }+ break;++ case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_SRGB):+ for (; x < max_x; x++)+ {+ int decode_pixel_index = x * channels;+ int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;+ for (c = 0; c < channels; c++)+ decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear(((const float*)input_data)[input_pixel_index + c]);++ if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE))+ decode_buffer[decode_pixel_index + alpha_channel] = ((const float*)input_data)[input_pixel_index + alpha_channel];+ }++ break;++ default:+ STBIR_ASSERT(!"Unknown type/colorspace/channels combination.");+ break;+ }++ if (!(stbir_info->flags & STBIR_FLAG_ALPHA_PREMULTIPLIED))+ {+ for (x = -stbir_info->horizontal_filter_pixel_margin; x < max_x; x++)+ {+ int decode_pixel_index = x * channels;++ // If the alpha value is 0 it will clobber the color values. Make sure it's not.+ float alpha = decode_buffer[decode_pixel_index + alpha_channel];+#ifndef STBIR_NO_ALPHA_EPSILON+ if (stbir_info->type != STBIR_TYPE_FLOAT) {+ alpha += STBIR_ALPHA_EPSILON;+ decode_buffer[decode_pixel_index + alpha_channel] = alpha;+ }+#endif+ for (c = 0; c < channels; c++)+ {+ if (c == alpha_channel)+ continue;++ decode_buffer[decode_pixel_index + c] *= alpha;+ }+ }+ }++ if (edge_horizontal == STBIR_EDGE_ZERO)+ {+ for (x = -stbir_info->horizontal_filter_pixel_margin; x < 0; x++)+ {+ for (c = 0; c < channels; c++)+ decode_buffer[x*channels + c] = 0;+ }+ for (x = input_w; x < max_x; x++)+ {+ for (c = 0; c < channels; c++)+ decode_buffer[x*channels + c] = 0;+ }+ }+}++static float* stbir__get_ring_buffer_entry(float* ring_buffer, int index, int ring_buffer_length)+{+ return &ring_buffer[index * ring_buffer_length];+}++static float* stbir__add_empty_ring_buffer_entry(stbir__info* stbir_info, int n)+{+ int ring_buffer_index;+ float* ring_buffer;++ stbir_info->ring_buffer_last_scanline = n;++ if (stbir_info->ring_buffer_begin_index < 0)+ {+ ring_buffer_index = stbir_info->ring_buffer_begin_index = 0;+ stbir_info->ring_buffer_first_scanline = n;+ }+ else+ {+ ring_buffer_index = (stbir_info->ring_buffer_begin_index + (stbir_info->ring_buffer_last_scanline - stbir_info->ring_buffer_first_scanline)) % stbir_info->ring_buffer_num_entries;+ STBIR_ASSERT(ring_buffer_index != stbir_info->ring_buffer_begin_index);+ }++ ring_buffer = stbir__get_ring_buffer_entry(stbir_info->ring_buffer, ring_buffer_index, stbir_info->ring_buffer_length_bytes / sizeof(float));+ memset(ring_buffer, 0, stbir_info->ring_buffer_length_bytes);++ return ring_buffer;+}+++static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, float* output_buffer)+{+ int x, k;+ int output_w = stbir_info->output_w;+ int channels = stbir_info->channels;+ float* decode_buffer = stbir__get_decode_buffer(stbir_info);+ stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors;+ float* horizontal_coefficients = stbir_info->horizontal_coefficients;+ int coefficient_width = stbir_info->horizontal_coefficient_width;++ for (x = 0; x < output_w; x++)+ {+ int n0 = horizontal_contributors[x].n0;+ int n1 = horizontal_contributors[x].n1;++ int out_pixel_index = x * channels;+ int coefficient_group = coefficient_width * x;+ int coefficient_counter = 0;++ STBIR_ASSERT(n1 >= n0);+ STBIR_ASSERT(n0 >= -stbir_info->horizontal_filter_pixel_margin);+ STBIR_ASSERT(n1 >= -stbir_info->horizontal_filter_pixel_margin);+ STBIR_ASSERT(n0 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin);+ STBIR_ASSERT(n1 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin);++ switch (channels) {+ case 1:+ for (k = n0; k <= n1; k++)+ {+ int in_pixel_index = k * 1;+ float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];+ STBIR_ASSERT(coefficient != 0);+ output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;+ }+ break;+ case 2:+ for (k = n0; k <= n1; k++)+ {+ int in_pixel_index = k * 2;+ float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];+ STBIR_ASSERT(coefficient != 0);+ output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;+ output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;+ }+ break;+ case 3:+ for (k = n0; k <= n1; k++)+ {+ int in_pixel_index = k * 3;+ float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];+ STBIR_ASSERT(coefficient != 0);+ output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;+ output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;+ output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient;+ }+ break;+ case 4:+ for (k = n0; k <= n1; k++)+ {+ int in_pixel_index = k * 4;+ float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];+ STBIR_ASSERT(coefficient != 0);+ output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;+ output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;+ output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient;+ output_buffer[out_pixel_index + 3] += decode_buffer[in_pixel_index + 3] * coefficient;+ }+ break;+ default:+ for (k = n0; k <= n1; k++)+ {+ int in_pixel_index = k * channels;+ float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];+ int c;+ STBIR_ASSERT(coefficient != 0);+ for (c = 0; c < channels; c++)+ output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient;+ }+ break;+ }+ }+}++static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, float* output_buffer)+{+ int x, k;+ int input_w = stbir_info->input_w;+ int channels = stbir_info->channels;+ float* decode_buffer = stbir__get_decode_buffer(stbir_info);+ stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors;+ float* horizontal_coefficients = stbir_info->horizontal_coefficients;+ int coefficient_width = stbir_info->horizontal_coefficient_width;+ int filter_pixel_margin = stbir_info->horizontal_filter_pixel_margin;+ int max_x = input_w + filter_pixel_margin * 2;++ STBIR_ASSERT(!stbir__use_width_upsampling(stbir_info));++ switch (channels) {+ case 1:+ for (x = 0; x < max_x; x++)+ {+ int n0 = horizontal_contributors[x].n0;+ int n1 = horizontal_contributors[x].n1;++ int in_x = x - filter_pixel_margin;+ int in_pixel_index = in_x * 1;+ int max_n = n1;+ int coefficient_group = coefficient_width * x;++ for (k = n0; k <= max_n; k++)+ {+ int out_pixel_index = k * 1;+ float coefficient = horizontal_coefficients[coefficient_group + k - n0];+ output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;+ }+ }+ break;++ case 2:+ for (x = 0; x < max_x; x++)+ {+ int n0 = horizontal_contributors[x].n0;+ int n1 = horizontal_contributors[x].n1;++ int in_x = x - filter_pixel_margin;+ int in_pixel_index = in_x * 2;+ int max_n = n1;+ int coefficient_group = coefficient_width * x;++ for (k = n0; k <= max_n; k++)+ {+ int out_pixel_index = k * 2;+ float coefficient = horizontal_coefficients[coefficient_group + k - n0];+ output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;+ output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;+ }+ }+ break;++ case 3:+ for (x = 0; x < max_x; x++)+ {+ int n0 = horizontal_contributors[x].n0;+ int n1 = horizontal_contributors[x].n1;++ int in_x = x - filter_pixel_margin;+ int in_pixel_index = in_x * 3;+ int max_n = n1;+ int coefficient_group = coefficient_width * x;++ for (k = n0; k <= max_n; k++)+ {+ int out_pixel_index = k * 3;+ float coefficient = horizontal_coefficients[coefficient_group + k - n0];+ output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;+ output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;+ output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient;+ }+ }+ break;++ case 4:+ for (x = 0; x < max_x; x++)+ {+ int n0 = horizontal_contributors[x].n0;+ int n1 = horizontal_contributors[x].n1;++ int in_x = x - filter_pixel_margin;+ int in_pixel_index = in_x * 4;+ int max_n = n1;+ int coefficient_group = coefficient_width * x;++ for (k = n0; k <= max_n; k++)+ {+ int out_pixel_index = k * 4;+ float coefficient = horizontal_coefficients[coefficient_group + k - n0];+ output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;+ output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;+ output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient;+ output_buffer[out_pixel_index + 3] += decode_buffer[in_pixel_index + 3] * coefficient;+ }+ }+ break;++ default:+ for (x = 0; x < max_x; x++)+ {+ int n0 = horizontal_contributors[x].n0;+ int n1 = horizontal_contributors[x].n1;++ int in_x = x - filter_pixel_margin;+ int in_pixel_index = in_x * channels;+ int max_n = n1;+ int coefficient_group = coefficient_width * x;++ for (k = n0; k <= max_n; k++)+ {+ int c;+ int out_pixel_index = k * channels;+ float coefficient = horizontal_coefficients[coefficient_group + k - n0];+ for (c = 0; c < channels; c++)+ output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient;+ }+ }+ break;+ }+}++static void stbir__decode_and_resample_upsample(stbir__info* stbir_info, int n)+{+ // Decode the nth scanline from the source image into the decode buffer.+ stbir__decode_scanline(stbir_info, n);++ // Now resample it into the ring buffer.+ if (stbir__use_width_upsampling(stbir_info))+ stbir__resample_horizontal_upsample(stbir_info, stbir__add_empty_ring_buffer_entry(stbir_info, n));+ else+ stbir__resample_horizontal_downsample(stbir_info, stbir__add_empty_ring_buffer_entry(stbir_info, n));++ // Now it's sitting in the ring buffer ready to be used as source for the vertical sampling.+}++static void stbir__decode_and_resample_downsample(stbir__info* stbir_info, int n)+{+ // Decode the nth scanline from the source image into the decode buffer.+ stbir__decode_scanline(stbir_info, n);++ memset(stbir_info->horizontal_buffer, 0, stbir_info->output_w * stbir_info->channels * sizeof(float));++ // Now resample it into the horizontal buffer.+ if (stbir__use_width_upsampling(stbir_info))+ stbir__resample_horizontal_upsample(stbir_info, stbir_info->horizontal_buffer);+ else+ stbir__resample_horizontal_downsample(stbir_info, stbir_info->horizontal_buffer);++ // Now it's sitting in the horizontal buffer ready to be distributed into the ring buffers.+}++// Get the specified scan line from the ring buffer.+static float* stbir__get_ring_buffer_scanline(int get_scanline, float* ring_buffer, int begin_index, int first_scanline, int ring_buffer_num_entries, int ring_buffer_length)+{+ int ring_buffer_index = (begin_index + (get_scanline - first_scanline)) % ring_buffer_num_entries;+ return stbir__get_ring_buffer_entry(ring_buffer, ring_buffer_index, ring_buffer_length);+}+++static void stbir__encode_scanline(stbir__info* stbir_info, int num_pixels, void *output_buffer, float *encode_buffer, int channels, int alpha_channel, int decode)+{+ int x;+ int n;+ int num_nonalpha;+ stbir_uint16 nonalpha[STBIR_MAX_CHANNELS];++ if (!(stbir_info->flags&STBIR_FLAG_ALPHA_PREMULTIPLIED))+ {+ for (x=0; x < num_pixels; ++x)+ {+ int pixel_index = x*channels;++ float alpha = encode_buffer[pixel_index + alpha_channel];+ float reciprocal_alpha = alpha ? 1.0f / alpha : 0;++ // unrolling this produced a 1% slowdown upscaling a large RGBA linear-space image on my machine - stb+ for (n = 0; n < channels; n++)+ if (n != alpha_channel)+ encode_buffer[pixel_index + n] *= reciprocal_alpha;++ // We added in a small epsilon to prevent the color channel from being deleted with zero alpha.+ // Because we only add it for integer types, it will automatically be discarded on integer+ // conversion, so we don't need to subtract it back out (which would be problematic for+ // numeric precision reasons).+ }+ }++ // build a table of all channels that need colorspace correction, so+ // we don't perform colorspace correction on channels that don't need it.+ for (x = 0, num_nonalpha = 0; x < channels; ++x)+ {+ if (x != alpha_channel || (stbir_info->flags & STBIR_FLAG_ALPHA_USES_COLORSPACE))+ {+ nonalpha[num_nonalpha++] = (stbir_uint16)x;+ }+ }++ #define STBIR__ROUND_INT(f) ((int) ((f)+0.5))+ #define STBIR__ROUND_UINT(f) ((stbir_uint32) ((f)+0.5))++ #ifdef STBIR__SATURATE_INT+ #define STBIR__ENCODE_LINEAR8(f) stbir__saturate8 (STBIR__ROUND_INT((f) * stbir__max_uint8_as_float ))+ #define STBIR__ENCODE_LINEAR16(f) stbir__saturate16(STBIR__ROUND_INT((f) * stbir__max_uint16_as_float))+ #else+ #define STBIR__ENCODE_LINEAR8(f) (unsigned char ) STBIR__ROUND_INT(stbir__saturate(f) * stbir__max_uint8_as_float )+ #define STBIR__ENCODE_LINEAR16(f) (unsigned short) STBIR__ROUND_INT(stbir__saturate(f) * stbir__max_uint16_as_float)+ #endif++ switch (decode)+ {+ case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_LINEAR):+ for (x=0; x < num_pixels; ++x)+ {+ int pixel_index = x*channels;++ for (n = 0; n < channels; n++)+ {+ int index = pixel_index + n;+ ((unsigned char*)output_buffer)[index] = STBIR__ENCODE_LINEAR8(encode_buffer[index]);+ }+ }+ break;++ case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_SRGB):+ for (x=0; x < num_pixels; ++x)+ {+ int pixel_index = x*channels;++ for (n = 0; n < num_nonalpha; n++)+ {+ int index = pixel_index + nonalpha[n];+ ((unsigned char*)output_buffer)[index] = stbir__linear_to_srgb_uchar(encode_buffer[index]);+ }++ if (!(stbir_info->flags & STBIR_FLAG_ALPHA_USES_COLORSPACE))+ ((unsigned char *)output_buffer)[pixel_index + alpha_channel] = STBIR__ENCODE_LINEAR8(encode_buffer[pixel_index+alpha_channel]);+ }+ break;++ case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_LINEAR):+ for (x=0; x < num_pixels; ++x)+ {+ int pixel_index = x*channels;++ for (n = 0; n < channels; n++)+ {+ int index = pixel_index + n;+ ((unsigned short*)output_buffer)[index] = STBIR__ENCODE_LINEAR16(encode_buffer[index]);+ }+ }+ break;++ case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_SRGB):+ for (x=0; x < num_pixels; ++x)+ {+ int pixel_index = x*channels;++ for (n = 0; n < num_nonalpha; n++)+ {+ int index = pixel_index + nonalpha[n];+ ((unsigned short*)output_buffer)[index] = (unsigned short)STBIR__ROUND_INT(stbir__linear_to_srgb(stbir__saturate(encode_buffer[index])) * stbir__max_uint16_as_float);+ }++ if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE))+ ((unsigned short*)output_buffer)[pixel_index + alpha_channel] = STBIR__ENCODE_LINEAR16(encode_buffer[pixel_index + alpha_channel]);+ }++ break;++ case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_LINEAR):+ for (x=0; x < num_pixels; ++x)+ {+ int pixel_index = x*channels;++ for (n = 0; n < channels; n++)+ {+ int index = pixel_index + n;+ ((unsigned int*)output_buffer)[index] = (unsigned int)STBIR__ROUND_UINT(((double)stbir__saturate(encode_buffer[index])) * stbir__max_uint32_as_float);+ }+ }+ break;++ case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_SRGB):+ for (x=0; x < num_pixels; ++x)+ {+ int pixel_index = x*channels;++ for (n = 0; n < num_nonalpha; n++)+ {+ int index = pixel_index + nonalpha[n];+ ((unsigned int*)output_buffer)[index] = (unsigned int)STBIR__ROUND_UINT(((double)stbir__linear_to_srgb(stbir__saturate(encode_buffer[index]))) * stbir__max_uint32_as_float);+ }++ if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE))+ ((unsigned int*)output_buffer)[pixel_index + alpha_channel] = (unsigned int)STBIR__ROUND_INT(((double)stbir__saturate(encode_buffer[pixel_index + alpha_channel])) * stbir__max_uint32_as_float);+ }+ break;++ case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_LINEAR):+ for (x=0; x < num_pixels; ++x)+ {+ int pixel_index = x*channels;++ for (n = 0; n < channels; n++)+ {+ int index = pixel_index + n;+ ((float*)output_buffer)[index] = encode_buffer[index];+ }+ }+ break;++ case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_SRGB):+ for (x=0; x < num_pixels; ++x)+ {+ int pixel_index = x*channels;++ for (n = 0; n < num_nonalpha; n++)+ {+ int index = pixel_index + nonalpha[n];+ ((float*)output_buffer)[index] = stbir__linear_to_srgb(encode_buffer[index]);+ }++ if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE))+ ((float*)output_buffer)[pixel_index + alpha_channel] = encode_buffer[pixel_index + alpha_channel];+ }+ break;++ default:+ STBIR_ASSERT(!"Unknown type/colorspace/channels combination.");+ break;+ }+}++static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n)+{+ int x, k;+ int output_w = stbir_info->output_w;+ stbir__contributors* vertical_contributors = stbir_info->vertical_contributors;+ float* vertical_coefficients = stbir_info->vertical_coefficients;+ int channels = stbir_info->channels;+ int alpha_channel = stbir_info->alpha_channel;+ int type = stbir_info->type;+ int colorspace = stbir_info->colorspace;+ int ring_buffer_entries = stbir_info->ring_buffer_num_entries;+ void* output_data = stbir_info->output_data;+ float* encode_buffer = stbir_info->encode_buffer;+ int decode = STBIR__DECODE(type, colorspace);+ int coefficient_width = stbir_info->vertical_coefficient_width;+ int coefficient_counter;+ int contributor = n;++ float* ring_buffer = stbir_info->ring_buffer;+ int ring_buffer_begin_index = stbir_info->ring_buffer_begin_index;+ int ring_buffer_first_scanline = stbir_info->ring_buffer_first_scanline;+ int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float);++ int n0,n1, output_row_start;+ int coefficient_group = coefficient_width * contributor;++ n0 = vertical_contributors[contributor].n0;+ n1 = vertical_contributors[contributor].n1;++ output_row_start = n * stbir_info->output_stride_bytes;++ STBIR_ASSERT(stbir__use_height_upsampling(stbir_info));++ memset(encode_buffer, 0, output_w * sizeof(float) * channels);++ // I tried reblocking this for better cache usage of encode_buffer+ // (using x_outer, k, x_inner), but it lost speed. -- stb++ coefficient_counter = 0;+ switch (channels) {+ case 1:+ for (k = n0; k <= n1; k++)+ {+ int coefficient_index = coefficient_counter++;+ float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length);+ float coefficient = vertical_coefficients[coefficient_group + coefficient_index];+ for (x = 0; x < output_w; ++x)+ {+ int in_pixel_index = x * 1;+ encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient;+ }+ }+ break;+ case 2:+ for (k = n0; k <= n1; k++)+ {+ int coefficient_index = coefficient_counter++;+ float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length);+ float coefficient = vertical_coefficients[coefficient_group + coefficient_index];+ for (x = 0; x < output_w; ++x)+ {+ int in_pixel_index = x * 2;+ encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient;+ encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient;+ }+ }+ break;+ case 3:+ for (k = n0; k <= n1; k++)+ {+ int coefficient_index = coefficient_counter++;+ float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length);+ float coefficient = vertical_coefficients[coefficient_group + coefficient_index];+ for (x = 0; x < output_w; ++x)+ {+ int in_pixel_index = x * 3;+ encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient;+ encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient;+ encode_buffer[in_pixel_index + 2] += ring_buffer_entry[in_pixel_index + 2] * coefficient;+ }+ }+ break;+ case 4:+ for (k = n0; k <= n1; k++)+ {+ int coefficient_index = coefficient_counter++;+ float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length);+ float coefficient = vertical_coefficients[coefficient_group + coefficient_index];+ for (x = 0; x < output_w; ++x)+ {+ int in_pixel_index = x * 4;+ encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient;+ encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient;+ encode_buffer[in_pixel_index + 2] += ring_buffer_entry[in_pixel_index + 2] * coefficient;+ encode_buffer[in_pixel_index + 3] += ring_buffer_entry[in_pixel_index + 3] * coefficient;+ }+ }+ break;+ default:+ for (k = n0; k <= n1; k++)+ {+ int coefficient_index = coefficient_counter++;+ float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length);+ float coefficient = vertical_coefficients[coefficient_group + coefficient_index];+ for (x = 0; x < output_w; ++x)+ {+ int in_pixel_index = x * channels;+ int c;+ for (c = 0; c < channels; c++)+ encode_buffer[in_pixel_index + c] += ring_buffer_entry[in_pixel_index + c] * coefficient;+ }+ }+ break;+ }+ stbir__encode_scanline(stbir_info, output_w, (char *) output_data + output_row_start, encode_buffer, channels, alpha_channel, decode);+}++static void stbir__resample_vertical_downsample(stbir__info* stbir_info, int n)+{+ int x, k;+ int output_w = stbir_info->output_w;+ stbir__contributors* vertical_contributors = stbir_info->vertical_contributors;+ float* vertical_coefficients = stbir_info->vertical_coefficients;+ int channels = stbir_info->channels;+ int ring_buffer_entries = stbir_info->ring_buffer_num_entries;+ float* horizontal_buffer = stbir_info->horizontal_buffer;+ int coefficient_width = stbir_info->vertical_coefficient_width;+ int contributor = n + stbir_info->vertical_filter_pixel_margin;++ float* ring_buffer = stbir_info->ring_buffer;+ int ring_buffer_begin_index = stbir_info->ring_buffer_begin_index;+ int ring_buffer_first_scanline = stbir_info->ring_buffer_first_scanline;+ int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float);+ int n0,n1;++ n0 = vertical_contributors[contributor].n0;+ n1 = vertical_contributors[contributor].n1;++ STBIR_ASSERT(!stbir__use_height_upsampling(stbir_info));++ for (k = n0; k <= n1; k++)+ {+ int coefficient_index = k - n0;+ int coefficient_group = coefficient_width * contributor;+ float coefficient = vertical_coefficients[coefficient_group + coefficient_index];++ float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length);++ switch (channels) {+ case 1:+ for (x = 0; x < output_w; x++)+ {+ int in_pixel_index = x * 1;+ ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient;+ }+ break;+ case 2:+ for (x = 0; x < output_w; x++)+ {+ int in_pixel_index = x * 2;+ ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient;+ ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient;+ }+ break;+ case 3:+ for (x = 0; x < output_w; x++)+ {+ int in_pixel_index = x * 3;+ ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient;+ ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient;+ ring_buffer_entry[in_pixel_index + 2] += horizontal_buffer[in_pixel_index + 2] * coefficient;+ }+ break;+ case 4:+ for (x = 0; x < output_w; x++)+ {+ int in_pixel_index = x * 4;+ ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient;+ ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient;+ ring_buffer_entry[in_pixel_index + 2] += horizontal_buffer[in_pixel_index + 2] * coefficient;+ ring_buffer_entry[in_pixel_index + 3] += horizontal_buffer[in_pixel_index + 3] * coefficient;+ }+ break;+ default:+ for (x = 0; x < output_w; x++)+ {+ int in_pixel_index = x * channels;++ int c;+ for (c = 0; c < channels; c++)+ ring_buffer_entry[in_pixel_index + c] += horizontal_buffer[in_pixel_index + c] * coefficient;+ }+ break;+ }+ }+}++static void stbir__buffer_loop_upsample(stbir__info* stbir_info)+{+ int y;+ float scale_ratio = stbir_info->vertical_scale;+ float out_scanlines_radius = stbir__filter_info_table[stbir_info->vertical_filter].support(1/scale_ratio) * scale_ratio;++ STBIR_ASSERT(stbir__use_height_upsampling(stbir_info));++ for (y = 0; y < stbir_info->output_h; y++)+ {+ float in_center_of_out = 0; // Center of the current out scanline in the in scanline space+ int in_first_scanline = 0, in_last_scanline = 0;++ stbir__calculate_sample_range_upsample(y, out_scanlines_radius, scale_ratio, stbir_info->vertical_shift, &in_first_scanline, &in_last_scanline, &in_center_of_out);++ STBIR_ASSERT(in_last_scanline - in_first_scanline + 1 <= stbir_info->ring_buffer_num_entries);++ if (stbir_info->ring_buffer_begin_index >= 0)+ {+ // Get rid of whatever we don't need anymore.+ while (in_first_scanline > stbir_info->ring_buffer_first_scanline)+ {+ if (stbir_info->ring_buffer_first_scanline == stbir_info->ring_buffer_last_scanline)+ {+ // We just popped the last scanline off the ring buffer.+ // Reset it to the empty state.+ stbir_info->ring_buffer_begin_index = -1;+ stbir_info->ring_buffer_first_scanline = 0;+ stbir_info->ring_buffer_last_scanline = 0;+ break;+ }+ else+ {+ stbir_info->ring_buffer_first_scanline++;+ stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->ring_buffer_num_entries;+ }+ }+ }++ // Load in new ones.+ if (stbir_info->ring_buffer_begin_index < 0)+ stbir__decode_and_resample_upsample(stbir_info, in_first_scanline);++ while (in_last_scanline > stbir_info->ring_buffer_last_scanline)+ stbir__decode_and_resample_upsample(stbir_info, stbir_info->ring_buffer_last_scanline + 1);++ // Now all buffers should be ready to write a row of vertical sampling.+ stbir__resample_vertical_upsample(stbir_info, y);++ STBIR_PROGRESS_REPORT((float)y / stbir_info->output_h);+ }+}++static void stbir__empty_ring_buffer(stbir__info* stbir_info, int first_necessary_scanline)+{+ int output_stride_bytes = stbir_info->output_stride_bytes;+ int channels = stbir_info->channels;+ int alpha_channel = stbir_info->alpha_channel;+ int type = stbir_info->type;+ int colorspace = stbir_info->colorspace;+ int output_w = stbir_info->output_w;+ void* output_data = stbir_info->output_data;+ int decode = STBIR__DECODE(type, colorspace);++ float* ring_buffer = stbir_info->ring_buffer;+ int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float);++ if (stbir_info->ring_buffer_begin_index >= 0)+ {+ // Get rid of whatever we don't need anymore.+ while (first_necessary_scanline > stbir_info->ring_buffer_first_scanline)+ {+ if (stbir_info->ring_buffer_first_scanline >= 0 && stbir_info->ring_buffer_first_scanline < stbir_info->output_h)+ {+ int output_row_start = stbir_info->ring_buffer_first_scanline * output_stride_bytes;+ float* ring_buffer_entry = stbir__get_ring_buffer_entry(ring_buffer, stbir_info->ring_buffer_begin_index, ring_buffer_length);+ stbir__encode_scanline(stbir_info, output_w, (char *) output_data + output_row_start, ring_buffer_entry, channels, alpha_channel, decode);+ STBIR_PROGRESS_REPORT((float)stbir_info->ring_buffer_first_scanline / stbir_info->output_h);+ }++ if (stbir_info->ring_buffer_first_scanline == stbir_info->ring_buffer_last_scanline)+ {+ // We just popped the last scanline off the ring buffer.+ // Reset it to the empty state.+ stbir_info->ring_buffer_begin_index = -1;+ stbir_info->ring_buffer_first_scanline = 0;+ stbir_info->ring_buffer_last_scanline = 0;+ break;+ }+ else+ {+ stbir_info->ring_buffer_first_scanline++;+ stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->ring_buffer_num_entries;+ }+ }+ }+}++static void stbir__buffer_loop_downsample(stbir__info* stbir_info)+{+ int y;+ float scale_ratio = stbir_info->vertical_scale;+ int output_h = stbir_info->output_h;+ float in_pixels_radius = stbir__filter_info_table[stbir_info->vertical_filter].support(scale_ratio) / scale_ratio;+ int pixel_margin = stbir_info->vertical_filter_pixel_margin;+ int max_y = stbir_info->input_h + pixel_margin;++ STBIR_ASSERT(!stbir__use_height_upsampling(stbir_info));++ for (y = -pixel_margin; y < max_y; y++)+ {+ float out_center_of_in; // Center of the current out scanline in the in scanline space+ int out_first_scanline, out_last_scanline;++ stbir__calculate_sample_range_downsample(y, in_pixels_radius, scale_ratio, stbir_info->vertical_shift, &out_first_scanline, &out_last_scanline, &out_center_of_in);++ STBIR_ASSERT(out_last_scanline - out_first_scanline + 1 <= stbir_info->ring_buffer_num_entries);++ if (out_last_scanline < 0 || out_first_scanline >= output_h)+ continue;++ stbir__empty_ring_buffer(stbir_info, out_first_scanline);++ stbir__decode_and_resample_downsample(stbir_info, y);++ // Load in new ones.+ if (stbir_info->ring_buffer_begin_index < 0)+ stbir__add_empty_ring_buffer_entry(stbir_info, out_first_scanline);++ while (out_last_scanline > stbir_info->ring_buffer_last_scanline)+ stbir__add_empty_ring_buffer_entry(stbir_info, stbir_info->ring_buffer_last_scanline + 1);++ // Now the horizontal buffer is ready to write to all ring buffer rows.+ stbir__resample_vertical_downsample(stbir_info, y);+ }++ stbir__empty_ring_buffer(stbir_info, stbir_info->output_h);+}++static void stbir__setup(stbir__info *info, int input_w, int input_h, int output_w, int output_h, int channels)+{+ info->input_w = input_w;+ info->input_h = input_h;+ info->output_w = output_w;+ info->output_h = output_h;+ info->channels = channels;+}++static void stbir__calculate_transform(stbir__info *info, float s0, float t0, float s1, float t1, float *transform)+{+ info->s0 = s0;+ info->t0 = t0;+ info->s1 = s1;+ info->t1 = t1;++ if (transform)+ {+ info->horizontal_scale = transform[0];+ info->vertical_scale = transform[1];+ info->horizontal_shift = transform[2];+ info->vertical_shift = transform[3];+ }+ else+ {+ info->horizontal_scale = ((float)info->output_w / info->input_w) / (s1 - s0);+ info->vertical_scale = ((float)info->output_h / info->input_h) / (t1 - t0);++ info->horizontal_shift = s0 * info->output_w / (s1 - s0);+ info->vertical_shift = t0 * info->output_h / (t1 - t0);+ }+}++static void stbir__choose_filter(stbir__info *info, stbir_filter h_filter, stbir_filter v_filter)+{+ if (h_filter == 0)+ h_filter = stbir__use_upsampling(info->horizontal_scale) ? STBIR_DEFAULT_FILTER_UPSAMPLE : STBIR_DEFAULT_FILTER_DOWNSAMPLE;+ if (v_filter == 0)+ v_filter = stbir__use_upsampling(info->vertical_scale) ? STBIR_DEFAULT_FILTER_UPSAMPLE : STBIR_DEFAULT_FILTER_DOWNSAMPLE;+ info->horizontal_filter = h_filter;+ info->vertical_filter = v_filter;+}++static stbir_uint32 stbir__calculate_memory(stbir__info *info)+{+ int pixel_margin = stbir__get_filter_pixel_margin(info->horizontal_filter, info->horizontal_scale);+ int filter_height = stbir__get_filter_pixel_width(info->vertical_filter, info->vertical_scale);++ info->horizontal_num_contributors = stbir__get_contributors(info->horizontal_scale, info->horizontal_filter, info->input_w, info->output_w);+ info->vertical_num_contributors = stbir__get_contributors(info->vertical_scale , info->vertical_filter , info->input_h, info->output_h);++ // One extra entry because floating point precision problems sometimes cause an extra to be necessary.+ info->ring_buffer_num_entries = filter_height + 1;++ info->horizontal_contributors_size = info->horizontal_num_contributors * sizeof(stbir__contributors);+ info->horizontal_coefficients_size = stbir__get_total_horizontal_coefficients(info) * sizeof(float);+ info->vertical_contributors_size = info->vertical_num_contributors * sizeof(stbir__contributors);+ info->vertical_coefficients_size = stbir__get_total_vertical_coefficients(info) * sizeof(float);+ info->decode_buffer_size = (info->input_w + pixel_margin * 2) * info->channels * sizeof(float);+ info->horizontal_buffer_size = info->output_w * info->channels * sizeof(float);+ info->ring_buffer_size = info->output_w * info->channels * info->ring_buffer_num_entries * sizeof(float);+ info->encode_buffer_size = info->output_w * info->channels * sizeof(float);++ STBIR_ASSERT(info->horizontal_filter != 0);+ STBIR_ASSERT(info->horizontal_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); // this now happens too late+ STBIR_ASSERT(info->vertical_filter != 0);+ STBIR_ASSERT(info->vertical_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); // this now happens too late++ if (stbir__use_height_upsampling(info))+ // The horizontal buffer is for when we're downsampling the height and we+ // can't output the result of sampling the decode buffer directly into the+ // ring buffers.+ info->horizontal_buffer_size = 0;+ else+ // The encode buffer is to retain precision in the height upsampling method+ // and isn't used when height downsampling.+ info->encode_buffer_size = 0;++ return info->horizontal_contributors_size + info->horizontal_coefficients_size+ + info->vertical_contributors_size + info->vertical_coefficients_size+ + info->decode_buffer_size + info->horizontal_buffer_size+ + info->ring_buffer_size + info->encode_buffer_size;+}++static int stbir__resize_allocated(stbir__info *info,+ const void* input_data, int input_stride_in_bytes,+ void* output_data, int output_stride_in_bytes,+ int alpha_channel, stbir_uint32 flags, stbir_datatype type,+ stbir_edge edge_horizontal, stbir_edge edge_vertical, stbir_colorspace colorspace,+ void* tempmem, size_t tempmem_size_in_bytes)+{+ size_t memory_required = stbir__calculate_memory(info);++ int width_stride_input = input_stride_in_bytes ? input_stride_in_bytes : info->channels * info->input_w * stbir__type_size[type];+ int width_stride_output = output_stride_in_bytes ? output_stride_in_bytes : info->channels * info->output_w * stbir__type_size[type];++#ifdef STBIR_DEBUG_OVERWRITE_TEST+#define OVERWRITE_ARRAY_SIZE 8+ unsigned char overwrite_output_before_pre[OVERWRITE_ARRAY_SIZE];+ unsigned char overwrite_tempmem_before_pre[OVERWRITE_ARRAY_SIZE];+ unsigned char overwrite_output_after_pre[OVERWRITE_ARRAY_SIZE];+ unsigned char overwrite_tempmem_after_pre[OVERWRITE_ARRAY_SIZE];++ size_t begin_forbidden = width_stride_output * (info->output_h - 1) + info->output_w * info->channels * stbir__type_size[type];+ memcpy(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE);+ memcpy(overwrite_output_after_pre, &((unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE);+ memcpy(overwrite_tempmem_before_pre, &((unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE);+ memcpy(overwrite_tempmem_after_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE);+#endif++ STBIR_ASSERT(info->channels >= 0);+ STBIR_ASSERT(info->channels <= STBIR_MAX_CHANNELS);++ if (info->channels < 0 || info->channels > STBIR_MAX_CHANNELS)+ return 0;++ STBIR_ASSERT(info->horizontal_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table));+ STBIR_ASSERT(info->vertical_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table));++ if (info->horizontal_filter >= STBIR__ARRAY_SIZE(stbir__filter_info_table))+ return 0;+ if (info->vertical_filter >= STBIR__ARRAY_SIZE(stbir__filter_info_table))+ return 0;++ if (alpha_channel < 0)+ flags |= STBIR_FLAG_ALPHA_USES_COLORSPACE | STBIR_FLAG_ALPHA_PREMULTIPLIED;++ if (!(flags&STBIR_FLAG_ALPHA_USES_COLORSPACE) || !(flags&STBIR_FLAG_ALPHA_PREMULTIPLIED)) {+ STBIR_ASSERT(alpha_channel >= 0 && alpha_channel < info->channels);+ }++ if (alpha_channel >= info->channels)+ return 0;++ STBIR_ASSERT(tempmem);++ if (!tempmem)+ return 0;++ STBIR_ASSERT(tempmem_size_in_bytes >= memory_required);++ if (tempmem_size_in_bytes < memory_required)+ return 0;++ memset(tempmem, 0, tempmem_size_in_bytes);++ info->input_data = input_data;+ info->input_stride_bytes = width_stride_input;++ info->output_data = output_data;+ info->output_stride_bytes = width_stride_output;++ info->alpha_channel = alpha_channel;+ info->flags = flags;+ info->type = type;+ info->edge_horizontal = edge_horizontal;+ info->edge_vertical = edge_vertical;+ info->colorspace = colorspace;++ info->horizontal_coefficient_width = stbir__get_coefficient_width (info->horizontal_filter, info->horizontal_scale);+ info->vertical_coefficient_width = stbir__get_coefficient_width (info->vertical_filter , info->vertical_scale );+ info->horizontal_filter_pixel_width = stbir__get_filter_pixel_width (info->horizontal_filter, info->horizontal_scale);+ info->vertical_filter_pixel_width = stbir__get_filter_pixel_width (info->vertical_filter , info->vertical_scale );+ info->horizontal_filter_pixel_margin = stbir__get_filter_pixel_margin(info->horizontal_filter, info->horizontal_scale);+ info->vertical_filter_pixel_margin = stbir__get_filter_pixel_margin(info->vertical_filter , info->vertical_scale );++ info->ring_buffer_length_bytes = info->output_w * info->channels * sizeof(float);+ info->decode_buffer_pixels = info->input_w + info->horizontal_filter_pixel_margin * 2;++#define STBIR__NEXT_MEMPTR(current, newtype) (newtype*)(((unsigned char*)current) + current##_size)++ info->horizontal_contributors = (stbir__contributors *) tempmem;+ info->horizontal_coefficients = STBIR__NEXT_MEMPTR(info->horizontal_contributors, float);+ info->vertical_contributors = STBIR__NEXT_MEMPTR(info->horizontal_coefficients, stbir__contributors);+ info->vertical_coefficients = STBIR__NEXT_MEMPTR(info->vertical_contributors, float);+ info->decode_buffer = STBIR__NEXT_MEMPTR(info->vertical_coefficients, float);++ if (stbir__use_height_upsampling(info))+ {+ info->horizontal_buffer = NULL;+ info->ring_buffer = STBIR__NEXT_MEMPTR(info->decode_buffer, float);+ info->encode_buffer = STBIR__NEXT_MEMPTR(info->ring_buffer, float);++ STBIR_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->encode_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes);+ }+ else+ {+ info->horizontal_buffer = STBIR__NEXT_MEMPTR(info->decode_buffer, float);+ info->ring_buffer = STBIR__NEXT_MEMPTR(info->horizontal_buffer, float);+ info->encode_buffer = NULL;++ STBIR_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->ring_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes);+ }++#undef STBIR__NEXT_MEMPTR++ // This signals that the ring buffer is empty+ info->ring_buffer_begin_index = -1;++ stbir__calculate_filters(info->horizontal_contributors, info->horizontal_coefficients, info->horizontal_filter, info->horizontal_scale, info->horizontal_shift, info->input_w, info->output_w);+ stbir__calculate_filters(info->vertical_contributors, info->vertical_coefficients, info->vertical_filter, info->vertical_scale, info->vertical_shift, info->input_h, info->output_h);++ STBIR_PROGRESS_REPORT(0);++ if (stbir__use_height_upsampling(info))+ stbir__buffer_loop_upsample(info);+ else+ stbir__buffer_loop_downsample(info);++ STBIR_PROGRESS_REPORT(1);++#ifdef STBIR_DEBUG_OVERWRITE_TEST+ STBIR_ASSERT(memcmp(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0);+ STBIR_ASSERT(memcmp(overwrite_output_after_pre, &((unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE) == 0);+ STBIR_ASSERT(memcmp(overwrite_tempmem_before_pre, &((unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0);+ STBIR_ASSERT(memcmp(overwrite_tempmem_after_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE) == 0);+#endif++ return 1;+}+++static int stbir__resize_arbitrary(+ void *alloc_context,+ const void* input_data, int input_w, int input_h, int input_stride_in_bytes,+ void* output_data, int output_w, int output_h, int output_stride_in_bytes,+ float s0, float t0, float s1, float t1, float *transform,+ int channels, int alpha_channel, stbir_uint32 flags, stbir_datatype type,+ stbir_filter h_filter, stbir_filter v_filter,+ stbir_edge edge_horizontal, stbir_edge edge_vertical, stbir_colorspace colorspace)+{+ stbir__info info;+ int result;+ size_t memory_required;+ void* extra_memory;++ stbir__setup(&info, input_w, input_h, output_w, output_h, channels);+ stbir__calculate_transform(&info, s0,t0,s1,t1,transform);+ stbir__choose_filter(&info, h_filter, v_filter);+ memory_required = stbir__calculate_memory(&info);+ extra_memory = STBIR_MALLOC(memory_required, alloc_context);++ if (!extra_memory)+ return 0;++ result = stbir__resize_allocated(&info, input_data, input_stride_in_bytes,+ output_data, output_stride_in_bytes,+ alpha_channel, flags, type,+ edge_horizontal, edge_vertical,+ colorspace, extra_memory, memory_required);++ STBIR_FREE(extra_memory, alloc_context);++ return result;+}++STBIRDEF int stbir_resize_uint8( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes,+ unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,+ int num_channels)+{+ return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes,+ output_pixels, output_w, output_h, output_stride_in_bytes,+ 0,0,1,1,NULL,num_channels,-1,0, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT,+ STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_LINEAR);+}++STBIRDEF int stbir_resize_float( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes,+ float *output_pixels, int output_w, int output_h, int output_stride_in_bytes,+ int num_channels)+{+ return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes,+ output_pixels, output_w, output_h, output_stride_in_bytes,+ 0,0,1,1,NULL,num_channels,-1,0, STBIR_TYPE_FLOAT, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT,+ STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_LINEAR);+}++STBIRDEF int stbir_resize_uint8_srgb(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes,+ unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,+ int num_channels, int alpha_channel, int flags)+{+ return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes,+ output_pixels, output_w, output_h, output_stride_in_bytes,+ 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT,+ STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB);+}++STBIRDEF int stbir_resize_uint8_srgb_edgemode(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes,+ unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,+ int num_channels, int alpha_channel, int flags,+ stbir_edge edge_wrap_mode)+{+ return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes,+ output_pixels, output_w, output_h, output_stride_in_bytes,+ 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT,+ edge_wrap_mode, edge_wrap_mode, STBIR_COLORSPACE_SRGB);+}++STBIRDEF int stbir_resize_uint8_generic( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes,+ unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,+ int num_channels, int alpha_channel, int flags,+ stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space,+ void *alloc_context)+{+ return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,+ output_pixels, output_w, output_h, output_stride_in_bytes,+ 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, filter, filter,+ edge_wrap_mode, edge_wrap_mode, space);+}++STBIRDEF int stbir_resize_uint16_generic(const stbir_uint16 *input_pixels , int input_w , int input_h , int input_stride_in_bytes,+ stbir_uint16 *output_pixels , int output_w, int output_h, int output_stride_in_bytes,+ int num_channels, int alpha_channel, int flags,+ stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space,+ void *alloc_context)+{+ return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,+ output_pixels, output_w, output_h, output_stride_in_bytes,+ 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT16, filter, filter,+ edge_wrap_mode, edge_wrap_mode, space);+}+++STBIRDEF int stbir_resize_float_generic( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes,+ float *output_pixels , int output_w, int output_h, int output_stride_in_bytes,+ int num_channels, int alpha_channel, int flags,+ stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space,+ void *alloc_context)+{+ return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,+ output_pixels, output_w, output_h, output_stride_in_bytes,+ 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_FLOAT, filter, filter,+ edge_wrap_mode, edge_wrap_mode, space);+}+++STBIRDEF int stbir_resize( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes,+ void *output_pixels, int output_w, int output_h, int output_stride_in_bytes,+ stbir_datatype datatype,+ int num_channels, int alpha_channel, int flags,+ stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical,+ stbir_filter filter_horizontal, stbir_filter filter_vertical,+ stbir_colorspace space, void *alloc_context)+{+ return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,+ output_pixels, output_w, output_h, output_stride_in_bytes,+ 0,0,1,1,NULL,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical,+ edge_mode_horizontal, edge_mode_vertical, space);+}+++STBIRDEF int stbir_resize_subpixel(const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes,+ void *output_pixels, int output_w, int output_h, int output_stride_in_bytes,+ stbir_datatype datatype,+ int num_channels, int alpha_channel, int flags,+ stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical,+ stbir_filter filter_horizontal, stbir_filter filter_vertical,+ stbir_colorspace space, void *alloc_context,+ float x_scale, float y_scale,+ float x_offset, float y_offset)+{+ float transform[4];+ transform[0] = x_scale;+ transform[1] = y_scale;+ transform[2] = x_offset;+ transform[3] = y_offset;+ return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,+ output_pixels, output_w, output_h, output_stride_in_bytes,+ 0,0,1,1,transform,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical,+ edge_mode_horizontal, edge_mode_vertical, space);+}++STBIRDEF int stbir_resize_region( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes,+ void *output_pixels, int output_w, int output_h, int output_stride_in_bytes,+ stbir_datatype datatype,+ int num_channels, int alpha_channel, int flags,+ stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical,+ stbir_filter filter_horizontal, stbir_filter filter_vertical,+ stbir_colorspace space, void *alloc_context,+ float s0, float t0, float s1, float t1)+{+ return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,+ output_pixels, output_w, output_h, output_stride_in_bytes,+ s0,t0,s1,t1,NULL,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical,+ edge_mode_horizontal, edge_mode_vertical, space);+}++#endif // STB_IMAGE_RESIZE_IMPLEMENTATION++/*+------------------------------------------------------------------------------+This software is available under 2 licenses -- choose whichever you prefer.+------------------------------------------------------------------------------+ALTERNATIVE A - MIT License+Copyright (c) 2017 Sean Barrett+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.+------------------------------------------------------------------------------+ALTERNATIVE B - Public Domain (www.unlicense.org)+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.+------------------------------------------------------------------------------+*/
+ cbits/tracy/profiler/src/winmain.cpp view
@@ -0,0 +1,48 @@+#ifdef _WIN32+# include <windows.h>+# include <stdlib.h>+# include <intrin.h>+# include <stdint.h>++namespace tracy+{+bool DiscoveryAVX();+bool DiscoveryAVX2();+}++int main( int argc, char** argv );++int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmd, int nCmd )+{+ {+ uint32_t regs[4];+ __cpuidex( (int*)regs, 0, 0 );+ const uint32_t maxLeaf = regs[0];+ bool cpuHasAVX = false;+ bool cpuHasAVX2 = false;+ if( maxLeaf >= 1 )+ {+ __cpuidex( (int*)regs, 1, 0 );+ cpuHasAVX = ( regs[2] & 0x10000000 ) != 0;+ }+ if( maxLeaf >= 7 )+ {+ __cpuidex( (int*)regs, 7, 0 );+ cpuHasAVX2 = ( regs[1] & 0x00000020 ) != 0;+ }++ if( tracy::DiscoveryAVX2() && !cpuHasAVX2 )+ {+ MessageBoxA( nullptr, "This program is compiled with AVX2 instruction set, but your CPU doesn't support it. You must recompile with lower instruction set.\n\nIn Visual Studio go to Project properties -> C/C++ -> Code Generation -> Enable Enhanced Instruction Set and select appropriate value for your CPU.", "Wrong CPU architecture", MB_ICONERROR );+ return 0;+ }+ if( tracy::DiscoveryAVX() && !cpuHasAVX )+ {+ MessageBoxA( nullptr, "This program is compiled with AVX instruction set, but your CPU doesn't support it. You must recompile with lower instruction set.\n\nIn Visual Studio go to Project properties -> C/C++ -> Code Generation -> Enable Enhanced Instruction Set and select appropriate value for your CPU.", "Wrong CPU architecture", MB_ICONERROR );+ return 0;+ }+ }++ return main( __argc, __argv );+}+#endif
+ cbits/tracy/profiler/src/winmainArchDiscovery.cpp view
@@ -0,0 +1,22 @@+#ifdef _WIN32+namespace tracy+{+ bool DiscoveryAVX()+ {+#ifdef __AVX__+ return true;+#else+ return false;+#endif+ }++ bool DiscoveryAVX2()+ {+#ifdef __AVX2__+ return true;+#else+ return false;+#endif+ }+}+#endif
+ cbits/tracy/profiler/src/zigzag01.hpp view
@@ -0,0 +1,10 @@+// File: 'zigzag01.png' (126 bytes)+// Exported using binary_to_compressed_c.cpp+static const unsigned int ZigZag01_size = 126;+static const unsigned int ZigZag01_data[128/4] =+{+ 0x474e5089, 0x0a1a0a0d, 0x0d000000, 0x52444849, 0x01000000, 0x01000000, 0x00000408, 0x0c1cb500, 0x00000002, 0x58457419, 0x666f5374, 0x72617774, + 0x77770065, 0x6e692e77, 0x6163736b, 0x6f2e6570, 0xee9b6772, 0x00001a3c, 0x48700900, 0x00007359, 0x00007600, 0x4e017600, 0x0008267b, 0x490b0000, + 0x78544144, 0xbff963da, 0xb802001a, 0x77afaf01, 0x0000dbd6, 0x45490000, 0x42ae444e, 0x00008260, +};+
+ cbits/tracy/profiler/src/zigzag02.hpp view
@@ -0,0 +1,10 @@+// File: 'zigzag02.png' (133 bytes)+// Exported using binary_to_compressed_c.cpp+static const unsigned int ZigZag02_size = 133;+static const unsigned int ZigZag02_data[136/4] =+{+ 0x474e5089, 0x0a1a0a0d, 0x0d000000, 0x52444849, 0x02000000, 0x02000000, 0x00000408, 0xc5bfd800, 0x000000af, 0x58457419, 0x666f5374, 0x72617774, + 0x77770065, 0x6e692e77, 0x6163736b, 0x6f2e6570, 0xee9b6772, 0x00001a3c, 0x48700900, 0x00007359, 0x0000ec00, 0x7901ec00, 0x00bd7128, 0x49120000, + 0x78544144, 0xfffc63da, 0xf19fa18c, 0x0143297f, 0x04651900, 0x4bae135b, 0x000000a6, 0x4e454900, 0x6042ae44, 0x00000082, +};+
+ cbits/tracy/profiler/src/zigzag04.hpp view
@@ -0,0 +1,11 @@+// File: 'zigzag04.png' (151 bytes)+// Exported using binary_to_compressed_c.cpp+static const unsigned int ZigZag04_size = 151;+static const unsigned int ZigZag04_data[152/4] =+{+ 0x474e5089, 0x0a1a0a0d, 0x0d000000, 0x52444849, 0x04000000, 0x04000000, 0x00000408, 0x56f80300, 0x000000f5, 0x58457419, 0x666f5374, 0x72617774, + 0x77770065, 0x6e692e77, 0x6163736b, 0x6f2e6570, 0xee9b6772, 0x00001a3c, 0x48700900, 0x00007359, 0x0000d801, 0xfa01d801, 0x0072a65c, 0x49240000, + 0x78544144, 0x6ff863da, 0x8022dff1, 0xe1818021, 0x74202bff, 0x00c0eff8, 0x061c4022, 0xf37ff090, 0x5500e6ff, 0x70bb123d, 0x0058f936, 0x49000000, + 0xae444e45, 0x00826042, +};+
+ cbits/tracy/profiler/src/zigzag08.hpp view
@@ -0,0 +1,11 @@+// File: 'zigzag08.png' (191 bytes)+// Exported using binary_to_compressed_c.cpp+static const unsigned int ZigZag08_size = 191;+static const unsigned int ZigZag08_data[192/4] =+{+ 0x474e5089, 0x0a1a0a0d, 0x0d000000, 0x52444849, 0x08000000, 0x08000000, 0x00000304, 0xa3213600, 0x000000b8, 0x58457419, 0x666f5374, 0x72617774, + 0x77770065, 0x6e692e77, 0x6163736b, 0x6f2e6570, 0xee9b6772, 0x00001a3c, 0x48700900, 0x00007359, 0x0000b003, 0x2701b003, 0x00ad0fc4, 0x500f0000, + 0x5045544c, 0xffff5050, 0xffffffff, 0xffffffff, 0x5a2fffff, 0x0000b6c6, 0x52740500, 0x3700534e, 0x35ea4038, 0x00e23649, 0x49200000, 0x78544144, + 0x030063da, 0x61200526, 0x9c240ce2, 0x19980c4d, 0x4d9d980c, 0x028c0260, 0x32001560, 0x4e760248, 0x00382c13, 0x49000000, 0xae444e45, 0x00826042, +};+
+ cbits/tracy/profiler/src/zigzag16.hpp view
@@ -0,0 +1,12 @@+// File: 'zigzag16.png' (234 bytes)+// Exported using binary_to_compressed_c.cpp+static const unsigned int ZigZag16_size = 234;+static const unsigned int ZigZag16_data[236/4] =+{+ 0x474e5089, 0x0a1a0a0d, 0x0d000000, 0x52444849, 0x10000000, 0x10000000, 0x00000304, 0xe2dded00, 0x00000052, 0x58457419, 0x666f5374, 0x72617774, + 0x77770065, 0x6e692e77, 0x6163736b, 0x6f2e6570, 0xee9b6772, 0x00001a3c, 0x48700900, 0x00007359, 0x00006107, 0x95016107, 0x00b6b8c3, 0x501b0000, + 0x5045544c, 0xffff5050, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x289affff, 0x00004ebe, 0x52740900, 0x3700534e, 0x403d3c38, + 0x6aeae942, 0x0041d380, 0x493b0000, 0x78544144, 0x07c063da, 0x8ca01498, 0xcd085688, 0x009e6652, 0x3027b866, 0xad198197, 0x0600c940, 0x10065606, + 0x4580e201, 0x205813cd, 0xee65ccd2, 0x3046a809, 0xb3e00a30, 0x4f750012, 0x7fcbb408, 0x000025f6, 0x45490000, 0x42ae444e, 0x00008260, +};+
+ cbits/tracy/profiler/src/zigzag32.hpp view
@@ -0,0 +1,13 @@+// File: 'zigzag32.png' (263 bytes)+// Exported using binary_to_compressed_c.cpp+static const unsigned int ZigZag32_size = 263;+static const unsigned int ZigZag32_data[264/4] =+{+ 0x474e5089, 0x0a1a0a0d, 0x0d000000, 0x52444849, 0x20000000, 0x20000000, 0x00000304, 0x67548100, 0x000000c7, 0x58457419, 0x666f5374, 0x72617774, + 0x77770065, 0x6e692e77, 0x6163736b, 0x6f2e6570, 0xee9b6772, 0x00001a3c, 0x48700900, 0x00007359, 0x0000c30e, 0xc701c30e, 0x0064a86f, 0x50180000, + 0x5045544c, 0xffff5050, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x1dffffff, 0x002deec8, 0x74070000, 0x00534e52, 0x877e7d01, 0xbd7e8f88, + 0x0000db4b, 0x44495d00, 0xda785441, 0xc0381863, 0x902680a4, 0x67ca865e, 0x404f4b2b, 0x604f0811, 0xe2401329, 0xb83502b3, 0x002b2227, 0x412887aa, + 0x02514028, 0x610d9031, 0x50859811, 0x5600cac2, 0x1c253080, 0x928456bb, 0xcc30b070, 0x08959814, 0x08055025, 0x08057025, 0x060fe24f, 0x81836606, + 0x3c00248b, 0x79101397, 0x00b45f6d, 0x49000000, 0xae444e45, 0x00826042, +};+
+ cbits/tracy/public/TracyClient.cpp view
@@ -0,0 +1,61 @@+//+// Tracy profiler+// ----------------+//+// For fast integration, compile and+// link with this source file (and none+// other) in your executable (or in the+// main DLL / shared object on multi-DLL+// projects).+//++// Define TRACY_ENABLE to enable profiler.++#include "common/TracySystem.cpp"++#ifdef TRACY_ENABLE++#ifdef _MSC_VER+# pragma warning(push, 0)+#endif++#include "common/tracy_lz4.cpp"+#include "client/TracyProfiler.cpp"+#include "client/TracyCallstack.cpp"+#include "client/TracySysPower.cpp"+#include "client/TracySysTime.cpp"+#include "client/TracySysTrace.cpp"+#include "common/TracySocket.cpp"+#include "client/tracy_rpmalloc.cpp"+#include "client/TracyDxt1.cpp"+#include "client/TracyAlloc.cpp"+#include "client/TracyOverride.cpp"+#include "client/TracyKCore.cpp"++#if defined(TRACY_HAS_CALLSTACK)+# if TRACY_HAS_CALLSTACK == 2 || TRACY_HAS_CALLSTACK == 3 || TRACY_HAS_CALLSTACK == 4 || TRACY_HAS_CALLSTACK == 6+# include "libbacktrace/alloc.cpp"+# include "libbacktrace/dwarf.cpp"+# include "libbacktrace/fileline.cpp"+# include "libbacktrace/mmapio.cpp"+# include "libbacktrace/posix.cpp"+# include "libbacktrace/sort.cpp"+# include "libbacktrace/state.cpp"+# if TRACY_HAS_CALLSTACK == 4+# include "libbacktrace/macho.cpp"+# else+# include "libbacktrace/elf.cpp"+# endif+# include "common/TracyStackFrames.cpp"+# endif+#endif++#ifdef _MSC_VER+# pragma comment(lib, "ws2_32.lib")+# pragma comment(lib, "dbghelp.lib")+# pragma comment(lib, "advapi32.lib")+# pragma comment(lib, "user32.lib")+# pragma warning(pop)+#endif++#endif
+ cbits/tracy/public/client/TracyAlloc.cpp view
@@ -0,0 +1,43 @@+#include "../common/TracyAlloc.hpp"++#ifdef TRACY_USE_RPMALLOC++#include <atomic>++#include "../common/TracyForceInline.hpp"+#include "../common/TracyYield.hpp"++namespace tracy+{++extern thread_local bool RpThreadInitDone;+extern std::atomic<int> RpInitDone;+extern std::atomic<int> RpInitLock;++tracy_no_inline static void InitRpmallocPlumbing()+{+ const auto done = RpInitDone.load( std::memory_order_acquire );+ if( !done )+ {+ int expected = 0;+ while( !RpInitLock.compare_exchange_weak( expected, 1, std::memory_order_release, std::memory_order_relaxed ) ) { expected = 0; YieldThread(); }+ const auto done = RpInitDone.load( std::memory_order_acquire );+ if( !done )+ {+ rpmalloc_initialize();+ RpInitDone.store( 1, std::memory_order_release );+ }+ RpInitLock.store( 0, std::memory_order_release );+ }+ rpmalloc_thread_initialize();+ RpThreadInitDone = true;+}++TRACY_API void InitRpmalloc()+{+ if( !RpThreadInitDone ) InitRpmallocPlumbing();+}++}++#endif
+ cbits/tracy/public/client/TracyArmCpuTable.hpp view
@@ -0,0 +1,419 @@+namespace tracy+{++#if defined __linux__ && defined __ARM_ARCH++static const char* DecodeArmImplementer( uint32_t v )+{+ static char buf[16];+ switch( v )+ {+ case 0x41: return "ARM";+ case 0x42: return "Broadcom";+ case 0x43: return "Cavium";+ case 0x44: return "DEC";+ case 0x46: return "Fujitsu";+ case 0x48: return "HiSilicon";+ case 0x49: return "Infineon";+ case 0x4d: return "Motorola";+ case 0x4e: return "Nvidia";+ case 0x50: return "Applied Micro";+ case 0x51: return "Qualcomm";+ case 0x53: return "Samsung";+ case 0x54: return "Texas Instruments";+ case 0x56: return "Marvell";+ case 0x61: return "Apple";+ case 0x66: return "Faraday";+ case 0x68: return "HXT";+ case 0x69: return "Intel";+ case 0xc0: return "Ampere Computing";+ default: break;+ }+ sprintf( buf, "0x%x", v );+ return buf;+}++static const char* DecodeArmPart( uint32_t impl, uint32_t part )+{+ static char buf[16];+ switch( impl )+ {+ case 0x41: // ARM+ switch( part )+ {+ case 0x810: return "810";+ case 0x920: return "920";+ case 0x922: return "922";+ case 0x926: return "926";+ case 0x940: return "940";+ case 0x946: return "946";+ case 0x966: return "966";+ case 0xa20: return "1020";+ case 0xa22: return "1022";+ case 0xa26: return "1026";+ case 0xb02: return "11 MPCore";+ case 0xb36: return "1136";+ case 0xb56: return "1156";+ case 0xb76: return "1176";+ case 0xc05: return " Cortex-A5";+ case 0xc07: return " Cortex-A7";+ case 0xc08: return " Cortex-A8";+ case 0xc09: return " Cortex-A9";+ case 0xc0c: return " Cortex-A12";+ case 0xc0d: return " Rockchip RK3288";+ case 0xc0e: return " Cortex-A17";+ case 0xc0f: return " Cortex-A15";+ case 0xc14: return " Cortex-R4";+ case 0xc15: return " Cortex-R5";+ case 0xc17: return " Cortex-R7";+ case 0xc18: return " Cortex-R8";+ case 0xc20: return " Cortex-M0";+ case 0xc21: return " Cortex-M1";+ case 0xc23: return " Cortex-M3";+ case 0xc24: return " Cortex-M4";+ case 0xc27: return " Cortex-M7";+ case 0xc60: return " Cortex-M0+";+ case 0xd00: return " AArch64 simulator";+ case 0xd01: return " Cortex-A32";+ case 0xd02: return " Cortex-A34";+ case 0xd03: return " Cortex-A53";+ case 0xd04: return " Cortex-A35";+ case 0xd05: return " Cortex-A55";+ case 0xd06: return " Cortex-A65";+ case 0xd07: return " Cortex-A57";+ case 0xd08: return " Cortex-A72";+ case 0xd09: return " Cortex-A73";+ case 0xd0a: return " Cortex-A75";+ case 0xd0b: return " Cortex-A76";+ case 0xd0c: return " Neoverse N1";+ case 0xd0d: return " Cortex-A77";+ case 0xd0e: return " Cortex-A76AE";+ case 0xd0f: return " AEMv8";+ case 0xd13: return " Cortex-R52";+ case 0xd20: return " Cortex-M23";+ case 0xd21: return " Cortex-M33";+ case 0xd22: return " Cortex-M55";+ case 0xd40: return " Neoverse V1";+ case 0xd41: return " Cortex-A78";+ case 0xd42: return " Cortex-A78AE";+ case 0xd43: return " Cortex-A65AE";+ case 0xd44: return " Cortex-X1";+ case 0xd47: return " Cortex-A710";+ case 0xd48: return " Cortex-X2";+ case 0xd49: return " Neoverse N2";+ case 0xd4a: return " Neoverse E1";+ case 0xd4b: return " Cortex-A78C";+ case 0xd4c: return " Cortex-X1C";+ default: break;+ }+ case 0x42: // Broadcom+ switch( part )+ {+ case 0xf: return " Brahma B15";+ case 0x100: return " Brahma B53";+ case 0x516: return " ThunderX2";+ default: break;+ }+ case 0x43: // Cavium+ switch( part )+ {+ case 0xa0: return " ThunderX";+ case 0xa1: return " ThunderX 88XX";+ case 0xa2: return " ThunderX 81XX";+ case 0xa3: return " ThunderX 83XX";+ case 0xaf: return " ThunderX2 99xx";+ case 0xb0: return " OcteonTX2";+ case 0xb1: return " OcteonTX2 T98";+ case 0xb2: return " OcteonTX2 T96";+ case 0xb3: return " OcteonTX2 F95";+ case 0xb4: return " OcteonTX2 F95N";+ case 0xb5: return " OcteonTX2 F95MM";+ case 0xb6: return " OcteonTX2 F95O";+ case 0xb8: return " ThunderX3 T110";+ default: break;+ }+ case 0x44: // DEC+ switch( part )+ {+ case 0xa10: return " SA110";+ case 0xa11: return " SA1100";+ default: break;+ }+ case 0x46: // Fujitsu+ switch( part )+ {+ case 0x1: return " A64FX";+ default: break;+ }+ case 0x48: // HiSilicon+ switch( part )+ {+ case 0xd01: return " TSV100";+ case 0xd40: return " Kirin 980";+ default: break;+ }+ case 0x4e: // Nvidia+ switch( part )+ {+ case 0x0: return " Denver";+ case 0x3: return " Denver 2";+ case 0x4: return " Carmel";+ default: break;+ }+ case 0x50: // Applied Micro+ switch( part )+ {+ case 0x0: return " X-Gene";+ default: break;+ }+ case 0x51: // Qualcomm+ switch( part )+ {+ case 0xf: return " Scorpion";+ case 0x2d: return " Scorpion";+ case 0x4d: return " Krait";+ case 0x6f: return " Krait";+ case 0x200: return " Kryo";+ case 0x201: return " Kryo Silver (Snapdragon 821)";+ case 0x205: return " Kryo Gold";+ case 0x211: return " Kryo Silver (Snapdragon 820)";+ case 0x800: return " Kryo 260 / 280 Gold";+ case 0x801: return " Kryo 260 / 280 Silver";+ case 0x802: return " Kryo 385 Gold";+ case 0x803: return " Kryo 385 Silver";+ case 0x804: return " Kryo 485 Gold";+ case 0x805: return " Kryo 4xx/5xx Silver";+ case 0xc00: return " Falkor";+ case 0xc01: return " Saphira";+ default: break;+ }+ case 0x53: // Samsung+ switch( part )+ {+ case 0x1: return " Exynos M1/M2";+ case 0x2: return " Exynos M3";+ case 0x3: return " Exynos M4";+ case 0x4: return " Exynos M5";+ default: break;+ }+ case 0x54: // Texas Instruments+ switch( part )+ {+ case 0x925: return " TI925";+ default: break;+ }+ case 0x56: // Marvell+ switch( part )+ {+ case 0x131: return " Feroceon 88FR131";+ case 0x581: return " PJ4 / PJ4B";+ case 0x584: return " PJ4B-MP / PJ4C";+ default: break;+ }+ case 0x61: // Apple+ switch( part )+ {+ case 0x1: return " Cyclone";+ case 0x2: return " Typhoon";+ case 0x3: return " Typhoon/Capri";+ case 0x4: return " Twister";+ case 0x5: return " Twister/Elba/Malta";+ case 0x6: return " Hurricane";+ case 0x7: return " Hurricane/Myst";+ case 0x22: return " M1 Icestorm";+ case 0x23: return " M1 Firestorm";+ case 0x24: return " M1 Icestorm Pro";+ case 0x25: return " M1 Firestorm Pro";+ case 0x28: return " M1 Icestorm Max";+ case 0x29: return " M1 Firestorm Max";+ default: break;+ }+ case 0x66: // Faraday+ switch( part )+ {+ case 0x526: return " FA526";+ case 0x626: return " FA626";+ default: break;+ }+ case 0x68: // HXT+ switch( part )+ {+ case 0x0: return " Phecda";+ default: break;+ }+ case 0xc0: // Ampere Computing+ switch( part )+ {+ case 0xac3: return " Ampere1";+ default: break;+ }+ default: break;+ }+ sprintf( buf, " 0x%x", part );+ return buf;+}++#elif defined __APPLE__ && TARGET_OS_IPHONE == 1++static const char* DecodeIosDevice( const char* id )+{+ static const char* DeviceTable[] = {+ "i386", "32-bit simulator",+ "x86_64", "64-bit simulator",+ "iPhone1,1", "iPhone",+ "iPhone1,2", "iPhone 3G",+ "iPhone2,1", "iPhone 3GS",+ "iPhone3,1", "iPhone 4 (GSM)",+ "iPhone3,2", "iPhone 4 (GSM)",+ "iPhone3,3", "iPhone 4 (CDMA)",+ "iPhone4,1", "iPhone 4S",+ "iPhone5,1", "iPhone 5 (A1428)",+ "iPhone5,2", "iPhone 5 (A1429)",+ "iPhone5,3", "iPhone 5c (A1456/A1532)",+ "iPhone5,4", "iPhone 5c (A1507/A1516/1526/A1529)",+ "iPhone6,1", "iPhone 5s (A1433/A1533)",+ "iPhone6,2", "iPhone 5s (A1457/A1518/A1528/A1530)",+ "iPhone7,1", "iPhone 6 Plus",+ "iPhone7,2", "iPhone 6",+ "iPhone8,1", "iPhone 6S",+ "iPhone8,2", "iPhone 6S Plus",+ "iPhone8,4", "iPhone SE",+ "iPhone9,1", "iPhone 7 (CDMA)",+ "iPhone9,2", "iPhone 7 Plus (CDMA)",+ "iPhone9,3", "iPhone 7 (GSM)",+ "iPhone9,4", "iPhone 7 Plus (GSM)",+ "iPhone10,1", "iPhone 8 (CDMA)",+ "iPhone10,2", "iPhone 8 Plus (CDMA)",+ "iPhone10,3", "iPhone X (CDMA)",+ "iPhone10,4", "iPhone 8 (GSM)",+ "iPhone10,5", "iPhone 8 Plus (GSM)",+ "iPhone10,6", "iPhone X (GSM)",+ "iPhone11,2", "iPhone XS",+ "iPhone11,4", "iPhone XS Max",+ "iPhone11,6", "iPhone XS Max China",+ "iPhone11,8", "iPhone XR",+ "iPhone12,1", "iPhone 11",+ "iPhone12,3", "iPhone 11 Pro",+ "iPhone12,5", "iPhone 11 Pro Max",+ "iPhone12,8", "iPhone SE 2nd Gen",+ "iPhone13,1", "iPhone 12 Mini",+ "iPhone13,2", "iPhone 12",+ "iPhone13,3", "iPhone 12 Pro",+ "iPhone13,4", "iPhone 12 Pro Max",+ "iPhone14,2", "iPhone 13 Pro",+ "iPhone14,3", "iPhone 13 Pro Max",+ "iPhone14,4", "iPhone 13 Mini",+ "iPhone14,5", "iPhone 13",+ "iPhone14,6", "iPhone SE 3rd Gen",+ "iPhone14,7", "iPhone 14",+ "iPhone14,8", "iPhone 14 Plus",+ "iPhone15,2", "iPhone 14 Pro",+ "iPhone15,3", "iPhone 14 Pro Max",+ "iPhone15,4", "iPhone 15",+ "iPhone15,5", "iPhone 15 Plus",+ "iPhone16,1", "iPhone 15 Pro",+ "iPhone16,2", "iPhone 15 Pro Max",+ "iPad1,1", "iPad (A1219/A1337)",+ "iPad2,1", "iPad 2 (A1395)",+ "iPad2,2", "iPad 2 (A1396)",+ "iPad2,3", "iPad 2 (A1397)",+ "iPad2,4", "iPad 2 (A1395)",+ "iPad2,5", "iPad Mini (A1432)",+ "iPad2,6", "iPad Mini (A1454)",+ "iPad2,7", "iPad Mini (A1455)",+ "iPad3,1", "iPad 3 (A1416)",+ "iPad3,2", "iPad 3 (A1403)",+ "iPad3,3", "iPad 3 (A1430)",+ "iPad3,4", "iPad 4 (A1458)",+ "iPad3,5", "iPad 4 (A1459)",+ "iPad3,6", "iPad 4 (A1460)",+ "iPad4,1", "iPad Air (A1474)",+ "iPad4,2", "iPad Air (A1475)",+ "iPad4,3", "iPad Air (A1476)",+ "iPad4,4", "iPad Mini 2 (A1489)",+ "iPad4,5", "iPad Mini 2 (A1490)",+ "iPad4,6", "iPad Mini 2 (A1491)",+ "iPad4,7", "iPad Mini 3 (A1599)",+ "iPad4,8", "iPad Mini 3 (A1600)",+ "iPad4,9", "iPad Mini 3 (A1601)",+ "iPad5,1", "iPad Mini 4 (A1538)",+ "iPad5,2", "iPad Mini 4 (A1550)",+ "iPad5,3", "iPad Air 2 (A1566)",+ "iPad5,4", "iPad Air 2 (A1567)",+ "iPad6,3", "iPad Pro 9.7\" (A1673)",+ "iPad6,4", "iPad Pro 9.7\" (A1674)",+ "iPad6,5", "iPad Pro 9.7\" (A1675)",+ "iPad6,7", "iPad Pro 12.9\" (A1584)",+ "iPad6,8", "iPad Pro 12.9\" (A1652)",+ "iPad6,11", "iPad 5th gen (A1822)",+ "iPad6,12", "iPad 5th gen (A1823)",+ "iPad7,1", "iPad Pro 12.9\" 2nd gen (A1670)",+ "iPad7,2", "iPad Pro 12.9\" 2nd gen (A1671/A1821)",+ "iPad7,3", "iPad Pro 10.5\" (A1701)",+ "iPad7,4", "iPad Pro 10.5\" (A1709)",+ "iPad7,5", "iPad 6th gen (A1893)",+ "iPad7,6", "iPad 6th gen (A1954)",+ "iPad7,11", "iPad 7th gen 10.2\" (Wifi)",+ "iPad7,12", "iPad 7th gen 10.2\" (Wifi+Cellular)",+ "iPad8,1", "iPad Pro 11\" (A1980)",+ "iPad8,2", "iPad Pro 11\" (A1980)",+ "iPad8,3", "iPad Pro 11\" (A1934/A1979/A2013)",+ "iPad8,4", "iPad Pro 11\" (A1934/A1979/A2013)",+ "iPad8,5", "iPad Pro 12.9\" 3rd gen (A1876)",+ "iPad8,6", "iPad Pro 12.9\" 3rd gen (A1876)",+ "iPad8,7", "iPad Pro 12.9\" 3rd gen (A1895/A1983/A2014)",+ "iPad8,8", "iPad Pro 12.9\" 3rd gen (A1895/A1983/A2014)",+ "iPad8,9", "iPad Pro 11\" 2nd gen (Wifi)",+ "iPad8,10", "iPad Pro 11\" 2nd gen (Wifi+Cellular)",+ "iPad8,11", "iPad Pro 12.9\" 4th gen (Wifi)",+ "iPad8,12", "iPad Pro 12.9\" 4th gen (Wifi+Cellular)",+ "iPad11,1", "iPad Mini 5th gen (A2133)",+ "iPad11,2", "iPad Mini 5th gen (A2124/A2125/A2126)",+ "iPad11,3", "iPad Air 3rd gen (A2152)",+ "iPad11,4", "iPad Air 3rd gen (A2123/A2153/A2154)",+ "iPad11,6", "iPad 8th gen (WiFi)",+ "iPad11,7", "iPad 8th gen (WiFi+Cellular)",+ "iPad12,1", "iPad 9th Gen (WiFi)",+ "iPad12,2", "iPad 9th Gen (WiFi+Cellular)",+ "iPad13,1", "iPad Air 4th gen (WiFi)",+ "iPad13,2", "iPad Air 4th gen (WiFi+Cellular)",+ "iPad13,4", "iPad Pro 11\" 3rd gen",+ "iPad13,5", "iPad Pro 11\" 3rd gen",+ "iPad13,6", "iPad Pro 11\" 3rd gen",+ "iPad13,7", "iPad Pro 11\" 3rd gen",+ "iPad13,8", "iPad Pro 12.9\" 5th gen",+ "iPad13,9", "iPad Pro 12.9\" 5th gen",+ "iPad13,10", "iPad Pro 12.9\" 5th gen",+ "iPad13,11", "iPad Pro 12.9\" 5th gen",+ "iPad13,16", "iPad Air 5th Gen (WiFi)",+ "iPad13,17", "iPad Air 5th Gen (WiFi+Cellular)",+ "iPad13,18", "iPad 10th Gen",+ "iPad13,19", "iPad 10th Gen",+ "iPad14,1", "iPad mini 6th Gen (WiFi)",+ "iPad14,2", "iPad mini 6th Gen (WiFi+Cellular)",+ "iPad14,3", "iPad Pro 11\" 4th Gen",+ "iPad14,4", "iPad Pro 11\" 4th Gen",+ "iPad14,5", "iPad Pro 12.9\" 6th Gen",+ "iPad14,6", "iPad Pro 12.9\" 6th Gen",+ "iPod1,1", "iPod Touch",+ "iPod2,1", "iPod Touch 2nd gen",+ "iPod3,1", "iPod Touch 3rd gen",+ "iPod4,1", "iPod Touch 4th gen",+ "iPod5,1", "iPod Touch 5th gen",+ "iPod7,1", "iPod Touch 6th gen",+ "iPod9,1", "iPod Touch 7th gen",+ nullptr+ };++ auto ptr = DeviceTable;+ while( *ptr )+ {+ if( strcmp( ptr[0], id ) == 0 ) return ptr[1];+ ptr += 2;+ }+ return id;+}++#endif++}
+ cbits/tracy/public/client/TracyCallstack.cpp view
@@ -0,0 +1,1420 @@+#include <limits>+#include <new>+#include <stdio.h>+#include <string.h>+#include "TracyCallstack.hpp"+#include "TracyDebug.hpp"+#include "TracyFastVector.hpp"+#include "TracyStringHelpers.hpp"+#include "../common/TracyAlloc.hpp"+#include "../common/TracySystem.hpp"+++#ifdef TRACY_HAS_CALLSTACK++#if TRACY_HAS_CALLSTACK == 1+# ifndef NOMINMAX+# define NOMINMAX+# endif+# include <windows.h>+# include <psapi.h>+# include <algorithm>+# ifdef _MSC_VER+# pragma warning( push )+# pragma warning( disable : 4091 )+# endif+# include <dbghelp.h>+# ifdef _MSC_VER+# pragma warning( pop )+# endif+#elif TRACY_HAS_CALLSTACK == 2 || TRACY_HAS_CALLSTACK == 3 || TRACY_HAS_CALLSTACK == 4 || TRACY_HAS_CALLSTACK == 6+# include "../libbacktrace/backtrace.hpp"+# include <algorithm>+# include <dlfcn.h>+# include <cxxabi.h>+# include <stdlib.h>+#elif TRACY_HAS_CALLSTACK == 5+# include <dlfcn.h>+# include <cxxabi.h>+#endif++#ifdef TRACY_DBGHELP_LOCK+# include "TracyProfiler.hpp"++# define DBGHELP_INIT TracyConcat( TRACY_DBGHELP_LOCK, Init() )+# define DBGHELP_LOCK TracyConcat( TRACY_DBGHELP_LOCK, Lock() );+# define DBGHELP_UNLOCK TracyConcat( TRACY_DBGHELP_LOCK, Unlock() );++extern "C"+{+ void DBGHELP_INIT;+ void DBGHELP_LOCK;+ void DBGHELP_UNLOCK;+};+#endif++#if TRACY_HAS_CALLSTACK == 2 || TRACY_HAS_CALLSTACK == 3 || TRACY_HAS_CALLSTACK == 4 || TRACY_HAS_CALLSTACK == 5 || TRACY_HAS_CALLSTACK == 6+// If you want to use your own demangling functionality (e.g. for another language),+// define TRACY_DEMANGLE and provide your own implementation of the __tracy_demangle+// function. The input parameter is a function name. The demangle function must+// identify whether this name is mangled, and fail if it is not. Failure is indicated+// by returning nullptr. If demangling succeeds, a pointer to the C string containing+// demangled function must be returned. The demangling function is responsible for+// managing memory for this string. It is expected that it will be internally reused.+// When a call to ___tracy_demangle is made, previous contents of the string memory+// do not need to be preserved. Function may return string of any length, but the+// profiler can choose to truncate it.+extern "C" const char* ___tracy_demangle( const char* mangled );++#ifndef TRACY_DEMANGLE+constexpr size_t ___tracy_demangle_buffer_len = 1024*1024;+char* ___tracy_demangle_buffer;++void ___tracy_init_demangle_buffer()+{+ ___tracy_demangle_buffer = (char*)tracy::tracy_malloc( ___tracy_demangle_buffer_len );+}++void ___tracy_free_demangle_buffer()+{+ tracy::tracy_free( ___tracy_demangle_buffer );+}++extern "C" const char* ___tracy_demangle( const char* mangled )+{+ if( !mangled || mangled[0] != '_' ) return nullptr;+ if( strlen( mangled ) > ___tracy_demangle_buffer_len ) return nullptr;+ int status;+ size_t len = ___tracy_demangle_buffer_len;+ return abi::__cxa_demangle( mangled, ___tracy_demangle_buffer, &len, &status );+}+#endif+#endif++#if TRACY_HAS_CALLSTACK == 3+# define TRACY_USE_IMAGE_CACHE+# include <link.h>+#endif++namespace tracy+{++#ifdef TRACY_USE_IMAGE_CACHE+// when we have access to dl_iterate_phdr(), we can build a cache of address ranges to image paths+// so we can quickly determine which image an address falls into.+// We refresh this cache only when we hit an address that doesn't fall into any known range.+class ImageCache+{+public:+ struct ImageEntry+ {+ void* m_startAddress = nullptr;+ void* m_endAddress = nullptr;+ char* m_name = nullptr;+ };++ ImageCache()+ : m_images( 512 )+ {+ Refresh();+ }++ ~ImageCache()+ {+ Clear();+ }++ const ImageEntry* GetImageForAddress( void* address )+ {+ const ImageEntry* entry = GetImageForAddressImpl( address );+ if( !entry )+ {+ Refresh();+ return GetImageForAddressImpl( address );+ }+ return entry;+ }++private:+ tracy::FastVector<ImageEntry> m_images;+ bool m_updated = false;+ bool m_haveMainImageName = false;++ static int Callback( struct dl_phdr_info* info, size_t size, void* data )+ {+ ImageCache* cache = reinterpret_cast<ImageCache*>( data );++ const auto startAddress = reinterpret_cast<void*>( info->dlpi_addr );+ if( cache->Contains( startAddress ) ) return 0;++ const uint32_t headerCount = info->dlpi_phnum;+ assert( headerCount > 0);+ const auto endAddress = reinterpret_cast<void*>( info->dlpi_addr ++ info->dlpi_phdr[info->dlpi_phnum - 1].p_vaddr + info->dlpi_phdr[info->dlpi_phnum - 1].p_memsz);++ ImageEntry* image = cache->m_images.push_next();+ image->m_startAddress = startAddress;+ image->m_endAddress = endAddress;++ // the base executable name isn't provided when iterating with dl_iterate_phdr,+ // we will have to patch the executable image name outside this callback+ if( info->dlpi_name && info->dlpi_name[0] != '\0' )+ {+ size_t sz = strlen( info->dlpi_name ) + 1;+ image->m_name = (char*)tracy_malloc( sz );+ memcpy( image->m_name, info->dlpi_name, sz );+ }+ else+ {+ image->m_name = nullptr;+ }++ cache->m_updated = true;++ return 0;+ }++ bool Contains( void* startAddress ) const+ {+ return std::any_of( m_images.begin(), m_images.end(), [startAddress]( const ImageEntry& entry ) { return startAddress == entry.m_startAddress; } );+ }++ void Refresh()+ {+ m_updated = false;+ dl_iterate_phdr( Callback, this );++ if( m_updated )+ {+ std::sort( m_images.begin(), m_images.end(),+ []( const ImageEntry& lhs, const ImageEntry& rhs ) { return lhs.m_startAddress > rhs.m_startAddress; } );++ // patch the main executable image name here, as calling dl_* functions inside the dl_iterate_phdr callback might cause deadlocks+ UpdateMainImageName();+ }+ }++ void UpdateMainImageName()+ {+ if( m_haveMainImageName )+ {+ return;+ }++ for( ImageEntry& entry : m_images )+ {+ if( entry.m_name == nullptr )+ {+ Dl_info dlInfo;+ if( dladdr( (void *)entry.m_startAddress, &dlInfo ) )+ {+ if( dlInfo.dli_fname )+ {+ size_t sz = strlen( dlInfo.dli_fname ) + 1;+ entry.m_name = (char*)tracy_malloc( sz );+ memcpy( entry.m_name, dlInfo.dli_fname, sz );+ }+ }++ // we only expect one entry to be null for the main executable entry+ break;+ }+ }++ m_haveMainImageName = true;+ }++ const ImageEntry* GetImageForAddressImpl( void* address ) const+ {+ auto it = std::lower_bound( m_images.begin(), m_images.end(), address,+ []( const ImageEntry& lhs, const void* rhs ) { return lhs.m_startAddress > rhs; } );++ if( it != m_images.end() && address < it->m_endAddress )+ {+ return it;+ }+ return nullptr;+ }++ void Clear()+ {+ for( ImageEntry& entry : m_images )+ {+ tracy_free( entry.m_name );+ }++ m_images.clear();+ m_haveMainImageName = false;+ }+};+#endif //#ifdef TRACY_USE_IMAGE_CACHE++// when "TRACY_SYMBOL_OFFLINE_RESOLVE" is set, instead of fully resolving symbols at runtime,+// simply resolve the offset and image name (which will be enough the resolving to be done offline)+#ifdef TRACY_SYMBOL_OFFLINE_RESOLVE+constexpr bool s_shouldResolveSymbolsOffline = true;+#else+static bool s_shouldResolveSymbolsOffline = false;+bool ShouldResolveSymbolsOffline()+{+ const char* symbolOfflineResolve = GetEnvVar( "TRACY_SYMBOL_OFFLINE_RESOLVE" );+ return (symbolOfflineResolve && symbolOfflineResolve[0] == '1');+}+#endif // #ifdef TRACY_SYMBOL_OFFLINE_RESOLVE++#if TRACY_HAS_CALLSTACK == 1++enum { MaxCbTrace = 64 };+enum { MaxNameSize = 8*1024 };++int cb_num;+CallstackEntry cb_data[MaxCbTrace];++extern "C"+{+ typedef DWORD (__stdcall *t_SymAddrIncludeInlineTrace)( HANDLE hProcess, DWORD64 Address );+ typedef BOOL (__stdcall *t_SymQueryInlineTrace)( HANDLE hProcess, DWORD64 StartAddress, DWORD StartContext, DWORD64 StartRetAddress, DWORD64 CurAddress, LPDWORD CurContext, LPDWORD CurFrameIndex );+ typedef BOOL (__stdcall *t_SymFromInlineContext)( HANDLE hProcess, DWORD64 Address, ULONG InlineContext, PDWORD64 Displacement, PSYMBOL_INFO Symbol );+ typedef BOOL (__stdcall *t_SymGetLineFromInlineContext)( HANDLE hProcess, DWORD64 qwAddr, ULONG InlineContext, DWORD64 qwModuleBaseAddress, PDWORD pdwDisplacement, PIMAGEHLP_LINE64 Line64 );++ t_SymAddrIncludeInlineTrace _SymAddrIncludeInlineTrace = 0;+ t_SymQueryInlineTrace _SymQueryInlineTrace = 0;+ t_SymFromInlineContext _SymFromInlineContext = 0;+ t_SymGetLineFromInlineContext _SymGetLineFromInlineContext = 0;++ typedef unsigned long (__stdcall *___tracy_t_RtlWalkFrameChain)( void**, unsigned long, unsigned long );+ ___tracy_t_RtlWalkFrameChain ___tracy_RtlWalkFrameChainPtr = nullptr;+ TRACY_API unsigned long ___tracy_RtlWalkFrameChain( void** callers, unsigned long count, unsigned long flags)+ {+ return ___tracy_RtlWalkFrameChainPtr(callers, count, flags);+ }+}++struct ModuleCache+{+ uint64_t start;+ uint64_t end;+ char* name;+};++static FastVector<ModuleCache>* s_modCache;+++struct KernelDriver+{+ uint64_t addr;+ const char* mod;+ const char* path;+};++KernelDriver* s_krnlCache = nullptr;+size_t s_krnlCacheCnt;++void InitCallstackCritical()+{+ ___tracy_RtlWalkFrameChainPtr = (___tracy_t_RtlWalkFrameChain)GetProcAddress( GetModuleHandleA( "ntdll.dll" ), "RtlWalkFrameChain" );+}++void DbgHelpInit()+{+ if( s_shouldResolveSymbolsOffline ) return;++ _SymAddrIncludeInlineTrace = (t_SymAddrIncludeInlineTrace)GetProcAddress(GetModuleHandleA("dbghelp.dll"), "SymAddrIncludeInlineTrace");+ _SymQueryInlineTrace = (t_SymQueryInlineTrace)GetProcAddress(GetModuleHandleA("dbghelp.dll"), "SymQueryInlineTrace");+ _SymFromInlineContext = (t_SymFromInlineContext)GetProcAddress(GetModuleHandleA("dbghelp.dll"), "SymFromInlineContext");+ _SymGetLineFromInlineContext = (t_SymGetLineFromInlineContext)GetProcAddress(GetModuleHandleA("dbghelp.dll"), "SymGetLineFromInlineContext");++#ifdef TRACY_DBGHELP_LOCK+ DBGHELP_INIT;+ DBGHELP_LOCK;+#endif++ SymInitialize( GetCurrentProcess(), nullptr, true );+ SymSetOptions( SYMOPT_LOAD_LINES );++#ifdef TRACY_DBGHELP_LOCK+ DBGHELP_UNLOCK;+#endif+}++DWORD64 DbgHelpLoadSymbolsForModule( const char* imageName, uint64_t baseOfDll, uint32_t bllSize )+{+ if( s_shouldResolveSymbolsOffline ) return 0;+ return SymLoadModuleEx( GetCurrentProcess(), nullptr, imageName, nullptr, baseOfDll, bllSize, nullptr, 0 );+}++ModuleCache* LoadSymbolsForModuleAndCache( const char* imageName, uint32_t imageNameLength, uint64_t baseOfDll, uint32_t dllSize )+{+ DbgHelpLoadSymbolsForModule( imageName, baseOfDll, dllSize );++ ModuleCache* cachedModule = s_modCache->push_next();+ cachedModule->start = baseOfDll;+ cachedModule->end = baseOfDll + dllSize;++ // when doing offline symbol resolution, we must store the full path of the dll for the resolving to work+ if( s_shouldResolveSymbolsOffline )+ {+ cachedModule->name = (char*)tracy_malloc_fast(imageNameLength + 1);+ memcpy(cachedModule->name, imageName, imageNameLength);+ cachedModule->name[imageNameLength] = '\0';+ }+ else+ {+ auto ptr = imageName + imageNameLength;+ while (ptr > imageName && *ptr != '\\' && *ptr != '/') ptr--;+ if (ptr > imageName) ptr++;+ const auto namelen = imageName + imageNameLength - ptr;+ cachedModule->name = (char*)tracy_malloc_fast(namelen + 3);+ cachedModule->name[0] = '[';+ memcpy(cachedModule->name + 1, ptr, namelen);+ cachedModule->name[namelen + 1] = ']';+ cachedModule->name[namelen + 2] = '\0';+ }++ return cachedModule;+}++void InitCallstack()+{+#ifndef TRACY_SYMBOL_OFFLINE_RESOLVE+ s_shouldResolveSymbolsOffline = ShouldResolveSymbolsOffline();+#endif //#ifndef TRACY_SYMBOL_OFFLINE_RESOLVE+ if( s_shouldResolveSymbolsOffline )+ {+ TracyDebug("TRACY: enabling offline symbol resolving!\n");+ }++ DbgHelpInit();++#ifdef TRACY_DBGHELP_LOCK+ DBGHELP_LOCK;+#endif++ // use TRACY_NO_DBGHELP_INIT_LOAD=1 to disable preloading of driver+ // and process module symbol loading at startup time - they will be loaded on demand later+ // Sometimes this process can take a very long time and prevent resolving callstack frames+ // symbols during that time.+ const char* noInitLoadEnv = GetEnvVar( "TRACY_NO_DBGHELP_INIT_LOAD" );+ const bool initTimeModuleLoad = !( noInitLoadEnv && noInitLoadEnv[0] == '1' );+ if ( !initTimeModuleLoad )+ {+ TracyDebug("TRACY: skipping init time dbghelper module load\n");+ }++ DWORD needed;+ LPVOID dev[4096];+ if( initTimeModuleLoad && EnumDeviceDrivers( dev, sizeof(dev), &needed ) != 0 )+ {+ char windir[MAX_PATH];+ if( !GetWindowsDirectoryA( windir, sizeof( windir ) ) ) memcpy( windir, "c:\\windows", 11 );+ const auto windirlen = strlen( windir );++ const auto sz = needed / sizeof( LPVOID );+ s_krnlCache = (KernelDriver*)tracy_malloc( sizeof(KernelDriver) * sz );+ int cnt = 0;+ for( size_t i=0; i<sz; i++ )+ {+ char fn[MAX_PATH];+ const auto len = GetDeviceDriverBaseNameA( dev[i], fn, sizeof( fn ) );+ if( len != 0 )+ {+ auto buf = (char*)tracy_malloc_fast( len+3 );+ buf[0] = '<';+ memcpy( buf+1, fn, len );+ memcpy( buf+len+1, ">", 2 );+ s_krnlCache[cnt] = KernelDriver { (uint64_t)dev[i], buf };++ const auto len = GetDeviceDriverFileNameA( dev[i], fn, sizeof( fn ) );+ if( len != 0 )+ {+ char full[MAX_PATH];+ char* path = fn;++ if( memcmp( fn, "\\SystemRoot\\", 12 ) == 0 )+ {+ memcpy( full, windir, windirlen );+ strcpy( full + windirlen, fn + 11 );+ path = full;+ }++ DbgHelpLoadSymbolsForModule( path, (DWORD64)dev[i], 0 );++ const auto psz = strlen( path );+ auto pptr = (char*)tracy_malloc_fast( psz+1 );+ memcpy( pptr, path, psz );+ pptr[psz] = '\0';+ s_krnlCache[cnt].path = pptr;+ }++ cnt++;+ }+ }+ s_krnlCacheCnt = cnt;+ std::sort( s_krnlCache, s_krnlCache + s_krnlCacheCnt, []( const KernelDriver& lhs, const KernelDriver& rhs ) { return lhs.addr > rhs.addr; } );+ }++ s_modCache = (FastVector<ModuleCache>*)tracy_malloc( sizeof( FastVector<ModuleCache> ) );+ new(s_modCache) FastVector<ModuleCache>( 512 );++ HANDLE proc = GetCurrentProcess();+ HMODULE mod[1024];+ if( initTimeModuleLoad && EnumProcessModules( proc, mod, sizeof( mod ), &needed ) != 0 )+ {+ const auto sz = needed / sizeof( HMODULE );+ for( size_t i=0; i<sz; i++ )+ {+ MODULEINFO info;+ if( GetModuleInformation( proc, mod[i], &info, sizeof( info ) ) != 0 )+ {+ char name[1024];+ const auto nameLength = GetModuleFileNameA( mod[i], name, 1021 );+ if( nameLength > 0 )+ {+ // This may be a new module loaded since our call to SymInitialize.+ // Just in case, force DbgHelp to load its pdb !+ LoadSymbolsForModuleAndCache( name, nameLength, (DWORD64)info.lpBaseOfDll, info.SizeOfImage );+ }+ }+ }+ }++#ifdef TRACY_DBGHELP_LOCK+ DBGHELP_UNLOCK;+#endif+}++void EndCallstack()+{+}++const char* DecodeCallstackPtrFast( uint64_t ptr )+{+ if( s_shouldResolveSymbolsOffline ) return "[unresolved]";++ static char ret[MaxNameSize];+ const auto proc = GetCurrentProcess();++ char buf[sizeof( SYMBOL_INFO ) + MaxNameSize];+ auto si = (SYMBOL_INFO*)buf;+ si->SizeOfStruct = sizeof( SYMBOL_INFO );+ si->MaxNameLen = MaxNameSize;++#ifdef TRACY_DBGHELP_LOCK+ DBGHELP_LOCK;+#endif+ if( SymFromAddr( proc, ptr, nullptr, si ) == 0 )+ {+ *ret = '\0';+ }+ else+ {+ memcpy( ret, si->Name, si->NameLen );+ ret[si->NameLen] = '\0';+ }+#ifdef TRACY_DBGHELP_LOCK+ DBGHELP_UNLOCK;+#endif+ return ret;+}++const char* GetKernelModulePath( uint64_t addr )+{+ assert( addr >> 63 != 0 );+ if( !s_krnlCache ) return nullptr;+ auto it = std::lower_bound( s_krnlCache, s_krnlCache + s_krnlCacheCnt, addr, []( const KernelDriver& lhs, const uint64_t& rhs ) { return lhs.addr > rhs; } );+ if( it == s_krnlCache + s_krnlCacheCnt ) return nullptr;+ return it->path;+}++struct ModuleNameAndBaseAddress+{+ const char* name;+ uint64_t baseAddr;+};++ModuleNameAndBaseAddress GetModuleNameAndPrepareSymbols( uint64_t addr )+{+ if( ( addr >> 63 ) != 0 )+ {+ if( s_krnlCache )+ {+ auto it = std::lower_bound( s_krnlCache, s_krnlCache + s_krnlCacheCnt, addr, []( const KernelDriver& lhs, const uint64_t& rhs ) { return lhs.addr > rhs; } );+ if( it != s_krnlCache + s_krnlCacheCnt )+ {+ return ModuleNameAndBaseAddress{ it->mod, it->addr };+ }+ }+ return ModuleNameAndBaseAddress{ "<kernel>", addr };+ }++ for( auto& v : *s_modCache )+ {+ if( addr >= v.start && addr < v.end )+ {+ return ModuleNameAndBaseAddress{ v.name, v.start };+ }+ }++ HMODULE mod[1024];+ DWORD needed;+ HANDLE proc = GetCurrentProcess();++ InitRpmalloc();+ if( EnumProcessModules( proc, mod, sizeof( mod ), &needed ) != 0 )+ {+ const auto sz = needed / sizeof( HMODULE );+ for( size_t i=0; i<sz; i++ )+ {+ MODULEINFO info;+ if( GetModuleInformation( proc, mod[i], &info, sizeof( info ) ) != 0 )+ {+ const auto base = uint64_t( info.lpBaseOfDll );+ if( addr >= base && addr < base + info.SizeOfImage )+ {+ char name[1024];+ const auto nameLength = GetModuleFileNameA( mod[i], name, 1021 );+ if( nameLength > 0 )+ {+ // since this is the first time we encounter this module, load its symbols (needed for modules loaded after SymInitialize)+ ModuleCache* cachedModule = LoadSymbolsForModuleAndCache( name, nameLength, (DWORD64)info.lpBaseOfDll, info.SizeOfImage );+ return ModuleNameAndBaseAddress{ cachedModule->name, cachedModule->start };+ }+ }+ }+ }+ }++ return ModuleNameAndBaseAddress{ "[unknown]", 0x0 };+}++CallstackSymbolData DecodeSymbolAddress( uint64_t ptr )+{+ CallstackSymbolData sym;++ if( s_shouldResolveSymbolsOffline )+ {+ sym.file = "[unknown]";+ sym.line = 0;+ sym.needFree = false;+ return sym;+ }++ IMAGEHLP_LINE64 line;+ DWORD displacement = 0;+ line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);+#ifdef TRACY_DBGHELP_LOCK+ DBGHELP_LOCK;+#endif+ const auto res = SymGetLineFromAddr64( GetCurrentProcess(), ptr, &displacement, &line );+ if( res == 0 || line.LineNumber >= 0xF00000 )+ {+ sym.file = "[unknown]";+ sym.line = 0;+ sym.needFree = false;+ }+ else+ {+ sym.file = CopyString( line.FileName );+ sym.line = line.LineNumber;+ sym.needFree = true;+ }+#ifdef TRACY_DBGHELP_LOCK+ DBGHELP_UNLOCK;+#endif+ return sym;+}++CallstackEntryData DecodeCallstackPtr( uint64_t ptr )+{+#ifdef TRACY_DBGHELP_LOCK+ DBGHELP_LOCK;+#endif++ InitRpmalloc();++ const ModuleNameAndBaseAddress moduleNameAndAddress = GetModuleNameAndPrepareSymbols( ptr );++ if( s_shouldResolveSymbolsOffline )+ {+#ifdef TRACY_DBGHELP_LOCK+ DBGHELP_UNLOCK;+#endif++ cb_data[0].symAddr = ptr - moduleNameAndAddress.baseAddr;+ cb_data[0].symLen = 0;++ cb_data[0].name = CopyStringFast("[unresolved]");+ cb_data[0].file = CopyStringFast("[unknown]");+ cb_data[0].line = 0;++ return { cb_data, 1, moduleNameAndAddress.name };+ }++ int write;+ const auto proc = GetCurrentProcess();++#if !defined TRACY_NO_CALLSTACK_INLINES+ BOOL doInline = FALSE;+ DWORD ctx = 0;+ DWORD inlineNum = 0;+ if( _SymAddrIncludeInlineTrace )+ {+ inlineNum = _SymAddrIncludeInlineTrace( proc, ptr );+ if( inlineNum > MaxCbTrace - 1 ) inlineNum = MaxCbTrace - 1;+ DWORD idx;+ if( inlineNum != 0 ) doInline = _SymQueryInlineTrace( proc, ptr, 0, ptr, ptr, &ctx, &idx );+ }+ if( doInline )+ {+ write = inlineNum;+ cb_num = 1 + inlineNum;+ }+ else+#endif+ {+ write = 0;+ cb_num = 1;+ }++ char buf[sizeof( SYMBOL_INFO ) + MaxNameSize];+ auto si = (SYMBOL_INFO*)buf;+ si->SizeOfStruct = sizeof( SYMBOL_INFO );+ si->MaxNameLen = MaxNameSize;++ const auto symValid = SymFromAddr( proc, ptr, nullptr, si ) != 0;++ IMAGEHLP_LINE64 line;+ DWORD displacement = 0;+ line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);++ {+ const char* filename;+ const auto res = SymGetLineFromAddr64( proc, ptr, &displacement, &line );+ if( res == 0 || line.LineNumber >= 0xF00000 )+ {+ filename = "[unknown]";+ cb_data[write].line = 0;+ }+ else+ {+ filename = line.FileName;+ cb_data[write].line = line.LineNumber;+ }++ cb_data[write].name = symValid ? CopyStringFast( si->Name, si->NameLen ) : CopyStringFast( moduleNameAndAddress.name );+ cb_data[write].file = CopyStringFast( filename );+ if( symValid )+ {+ cb_data[write].symLen = si->Size;+ cb_data[write].symAddr = si->Address;+ }+ else+ {+ cb_data[write].symLen = 0;+ cb_data[write].symAddr = 0;+ }+ }++#if !defined TRACY_NO_CALLSTACK_INLINES+ if( doInline )+ {+ for( DWORD i=0; i<inlineNum; i++ )+ {+ auto& cb = cb_data[i];+ const auto symInlineValid = _SymFromInlineContext( proc, ptr, ctx, nullptr, si ) != 0;+ const char* filename;+ if( _SymGetLineFromInlineContext( proc, ptr, ctx, 0, &displacement, &line ) == 0 )+ {+ filename = "[unknown]";+ cb.line = 0;+ }+ else+ {+ filename = line.FileName;+ cb.line = line.LineNumber;+ }++ cb.name = symInlineValid ? CopyStringFast( si->Name, si->NameLen ) : CopyStringFast( moduleNameAndAddress.name );+ cb.file = CopyStringFast( filename );+ if( symInlineValid )+ {+ cb.symLen = si->Size;+ cb.symAddr = si->Address;+ }+ else+ {+ cb.symLen = 0;+ cb.symAddr = 0;+ }++ ctx++;+ }+ }+#endif+#ifdef TRACY_DBGHELP_LOCK+ DBGHELP_UNLOCK;+#endif++ return { cb_data, uint8_t( cb_num ), moduleNameAndAddress.name };+}++#elif TRACY_HAS_CALLSTACK == 2 || TRACY_HAS_CALLSTACK == 3 || TRACY_HAS_CALLSTACK == 4 || TRACY_HAS_CALLSTACK == 6++enum { MaxCbTrace = 64 };++struct backtrace_state* cb_bts = nullptr;++int cb_num;+CallstackEntry cb_data[MaxCbTrace];+int cb_fixup;+#ifdef TRACY_USE_IMAGE_CACHE+static ImageCache* s_imageCache = nullptr;+#endif //#ifdef TRACY_USE_IMAGE_CACHE++#ifdef TRACY_DEBUGINFOD+debuginfod_client* s_debuginfod;++struct DebugInfo+{+ uint8_t* buildid;+ size_t buildid_size;+ char* filename;+ int fd;+};++static FastVector<DebugInfo>* s_di_known;+#endif++#ifdef __linux+struct KernelSymbol+{+ uint64_t addr;+ uint32_t size;+ const char* name;+ const char* mod;+};++KernelSymbol* s_kernelSym = nullptr;+size_t s_kernelSymCnt;++static void InitKernelSymbols()+{+ FILE* f = fopen( "/proc/kallsyms", "rb" );+ if( !f ) return;+ tracy::FastVector<KernelSymbol> tmpSym( 512 * 1024 );+ size_t linelen = 16 * 1024; // linelen must be big enough to prevent reallocs in getline()+ auto linebuf = (char*)tracy_malloc( linelen );+ ssize_t sz;+ size_t validCnt = 0;+ while( ( sz = getline( &linebuf, &linelen, f ) ) != -1 )+ {+ auto ptr = linebuf;+ uint64_t addr = 0;+ while( *ptr != ' ' )+ {+ auto v = *ptr;+ if( v >= '0' && v <= '9' )+ {+ v -= '0';+ }+ else if( v >= 'a' && v <= 'f' )+ {+ v -= 'a';+ v += 10;+ }+ else if( v >= 'A' && v <= 'F' )+ {+ v -= 'A';+ v += 10;+ }+ else+ {+ assert( false );+ }+ assert( ( v & ~0xF ) == 0 );+ addr <<= 4;+ addr |= v;+ ptr++;+ }+ if( addr == 0 ) continue;+ ptr++;+ const bool valid = *ptr == 'T' || *ptr == 't';+ ptr += 2;+ const auto namestart = ptr;+ while( *ptr != '\t' && *ptr != '\n' ) ptr++;+ const auto nameend = ptr;+ const char* modstart = nullptr;+ const char* modend;+ if( *ptr == '\t' )+ {+ ptr += 2;+ modstart = ptr;+ while( *ptr != ']' ) ptr++;+ modend = ptr;+ }++ char* strname = nullptr;+ char* strmod = nullptr;++ if( valid )+ {+ validCnt++;++ strname = (char*)tracy_malloc_fast( nameend - namestart + 1 );+ memcpy( strname, namestart, nameend - namestart );+ strname[nameend-namestart] = '\0';++ if( modstart )+ {+ strmod = (char*)tracy_malloc_fast( modend - modstart + 1 );+ memcpy( strmod, modstart, modend - modstart );+ strmod[modend-modstart] = '\0';+ }+ }++ auto sym = tmpSym.push_next();+ sym->addr = addr;+ sym->size = 0;+ sym->name = strname;+ sym->mod = strmod;+ }+ tracy_free_fast( linebuf );+ fclose( f );+ if( tmpSym.empty() ) return;++ std::sort( tmpSym.begin(), tmpSym.end(), []( const KernelSymbol& lhs, const KernelSymbol& rhs ) { return lhs.addr < rhs.addr; } );+ for( size_t i=0; i<tmpSym.size()-1; i++ )+ {+ if( tmpSym[i].name ) tmpSym[i].size = tmpSym[i+1].addr - tmpSym[i].addr;+ }++ s_kernelSymCnt = validCnt;+ s_kernelSym = (KernelSymbol*)tracy_malloc_fast( sizeof( KernelSymbol ) * validCnt );+ auto dst = s_kernelSym;+ for( auto& v : tmpSym )+ {+ if( v.name ) *dst++ = v;+ }+ assert( dst == s_kernelSym + validCnt );++ TracyDebug( "Loaded %zu kernel symbols (%zu code sections)\n", tmpSym.size(), validCnt );+}+#endif++char* NormalizePath( const char* path )+{+ if( path[0] != '/' ) return nullptr;++ const char* ptr = path;+ const char* end = path + strlen( path );++ char* res = (char*)tracy_malloc( end - ptr + 1 );+ size_t rsz = 0;++ while( ptr < end )+ {+ const char* next = ptr;+ while( next < end && *next != '/' ) next++;+ size_t lsz = next - ptr;+ switch( lsz )+ {+ case 2:+ if( memcmp( ptr, "..", 2 ) == 0 )+ {+ const char* back = res + rsz - 1;+ while( back > res && *back != '/' ) back--;+ rsz = back - res;+ ptr = next + 1;+ continue;+ }+ break;+ case 1:+ if( *ptr == '.' )+ {+ ptr = next + 1;+ continue;+ }+ break;+ case 0:+ ptr = next + 1;+ continue;+ }+ if( rsz != 1 ) res[rsz++] = '/';+ memcpy( res+rsz, ptr, lsz );+ rsz += lsz;+ ptr = next + 1;+ }++ if( rsz == 0 )+ {+ memcpy( res, "/", 2 );+ }+ else+ {+ res[rsz] = '\0';+ }+ return res;+}++void InitCallstackCritical()+{+}++void InitCallstack()+{+ InitRpmalloc();++#ifdef TRACY_USE_IMAGE_CACHE+ s_imageCache = (ImageCache*)tracy_malloc( sizeof( ImageCache ) );+ new(s_imageCache) ImageCache();+#endif //#ifdef TRACY_USE_IMAGE_CACHE++#ifndef TRACY_SYMBOL_OFFLINE_RESOLVE+ s_shouldResolveSymbolsOffline = ShouldResolveSymbolsOffline();+#endif //#ifndef TRACY_SYMBOL_OFFLINE_RESOLVE+ if( s_shouldResolveSymbolsOffline )+ {+ cb_bts = nullptr; // disable use of libbacktrace calls+ TracyDebug("TRACY: enabling offline symbol resolving!\n");+ }+ else+ {+ cb_bts = backtrace_create_state( nullptr, 0, nullptr, nullptr );+ }++#ifndef TRACY_DEMANGLE+ ___tracy_init_demangle_buffer();+#endif++#ifdef __linux+ InitKernelSymbols();+#endif+#ifdef TRACY_DEBUGINFOD+ s_debuginfod = debuginfod_begin();+ s_di_known = (FastVector<DebugInfo>*)tracy_malloc( sizeof( FastVector<DebugInfo> ) );+ new (s_di_known) FastVector<DebugInfo>( 16 );+#endif+}++#ifdef TRACY_DEBUGINFOD+void ClearDebugInfoVector( FastVector<DebugInfo>& vec )+{+ for( auto& v : vec )+ {+ tracy_free( v.buildid );+ tracy_free( v.filename );+ if( v.fd >= 0 ) close( v.fd );+ }+ vec.clear();+}++DebugInfo* FindDebugInfo( FastVector<DebugInfo>& vec, const uint8_t* buildid_data, size_t buildid_size )+{+ for( auto& v : vec )+ {+ if( v.buildid_size == buildid_size && memcmp( v.buildid, buildid_data, buildid_size ) == 0 )+ {+ return &v;+ }+ }+ return nullptr;+}++int GetDebugInfoDescriptor( const char* buildid_data, size_t buildid_size, const char* filename )+{+ auto buildid = (uint8_t*)buildid_data;+ auto it = FindDebugInfo( *s_di_known, buildid, buildid_size );+ if( it ) return it->fd >= 0 ? dup( it->fd ) : -1;++ int fd = debuginfod_find_debuginfo( s_debuginfod, buildid, buildid_size, nullptr );+ it = s_di_known->push_next();+ it->buildid_size = buildid_size;+ it->buildid = (uint8_t*)tracy_malloc( buildid_size );+ memcpy( it->buildid, buildid, buildid_size );+ const auto fnsz = strlen( filename ) + 1;+ it->filename = (char*)tracy_malloc( fnsz );+ memcpy( it->filename, filename, fnsz );+ it->fd = fd >= 0 ? fd : -1;+ TracyDebug( "DebugInfo descriptor query: %i, fn: %s\n", fd, filename );+ return it->fd;+}++const uint8_t* GetBuildIdForImage( const char* image, size_t& size )+{+ assert( image );+ for( auto& v : *s_di_known )+ {+ if( strcmp( image, v.filename ) == 0 )+ {+ size = v.buildid_size;+ return v.buildid;+ }+ }+ return nullptr;+}++debuginfod_client* GetDebuginfodClient()+{+ return s_debuginfod;+}+#endif++void EndCallstack()+{+#ifdef TRACY_USE_IMAGE_CACHE+ if( s_imageCache )+ {+ s_imageCache->~ImageCache();+ tracy_free( s_imageCache );+ }+#endif //#ifdef TRACY_USE_IMAGE_CACHE+#ifndef TRACY_DEMANGLE+ ___tracy_free_demangle_buffer();+#endif+#ifdef TRACY_DEBUGINFOD+ ClearDebugInfoVector( *s_di_known );+ s_di_known->~FastVector<DebugInfo>();+ tracy_free( s_di_known );++ debuginfod_end( s_debuginfod );+#endif+}++const char* DecodeCallstackPtrFast( uint64_t ptr )+{+ static char ret[1024];+ auto vptr = (void*)ptr;+ const char* symname = nullptr;+ Dl_info dlinfo;+ if( dladdr( vptr, &dlinfo ) && dlinfo.dli_sname )+ {+ symname = dlinfo.dli_sname;+ }+ if( symname )+ {+ strcpy( ret, symname );+ }+ else+ {+ *ret = '\0';+ }+ return ret;+}++static int SymbolAddressDataCb( void* data, uintptr_t pc, uintptr_t lowaddr, const char* fn, int lineno, const char* function )+{+ auto& sym = *(CallstackSymbolData*)data;+ if( !fn )+ {+ sym.file = "[unknown]";+ sym.line = 0;+ sym.needFree = false;+ }+ else+ {+ sym.file = NormalizePath( fn );+ if( !sym.file ) sym.file = CopyString( fn );+ sym.line = lineno;+ sym.needFree = true;+ }++ return 1;+}++static void SymbolAddressErrorCb( void* data, const char* /*msg*/, int /*errnum*/ )+{+ auto& sym = *(CallstackSymbolData*)data;+ sym.file = "[unknown]";+ sym.line = 0;+ sym.needFree = false;+}++CallstackSymbolData DecodeSymbolAddress( uint64_t ptr )+{+ CallstackSymbolData sym;+ if( cb_bts )+ {+ backtrace_pcinfo( cb_bts, ptr, SymbolAddressDataCb, SymbolAddressErrorCb, &sym );+ }+ else+ {+ SymbolAddressErrorCb(&sym, nullptr, 0);+ }++ return sym;+}++static int CallstackDataCb( void* /*data*/, uintptr_t pc, uintptr_t lowaddr, const char* fn, int lineno, const char* function )+{+ cb_data[cb_num].symLen = 0;+ cb_data[cb_num].symAddr = (uint64_t)lowaddr;++ if( !fn && !function )+ {+ const char* symname = nullptr;+ auto vptr = (void*)pc;+ ptrdiff_t symoff = 0;++ Dl_info dlinfo;+ if( dladdr( vptr, &dlinfo ) )+ {+ symname = dlinfo.dli_sname;+ symoff = (char*)pc - (char*)dlinfo.dli_saddr;+ const char* demangled = ___tracy_demangle( symname );+ if( demangled ) symname = demangled;+ }++ if( !symname ) symname = "[unknown]";++ if( symoff == 0 )+ {+ const auto len = std::min<size_t>( strlen( symname ), std::numeric_limits<uint16_t>::max() );+ cb_data[cb_num].name = CopyStringFast( symname, len );+ }+ else+ {+ char buf[32];+ const auto offlen = sprintf( buf, " + %td", symoff );+ const auto namelen = std::min<size_t>( strlen( symname ), std::numeric_limits<uint16_t>::max() - offlen );+ auto name = (char*)tracy_malloc_fast( namelen + offlen + 1 );+ memcpy( name, symname, namelen );+ memcpy( name + namelen, buf, offlen );+ name[namelen + offlen] = '\0';+ cb_data[cb_num].name = name;+ }++ cb_data[cb_num].file = CopyStringFast( "[unknown]" );+ cb_data[cb_num].line = 0;+ }+ else+ {+ if( !fn ) fn = "[unknown]";+ if( !function )+ {+ function = "[unknown]";+ }+ else+ {+ const char* demangled = ___tracy_demangle( function );+ if( demangled ) function = demangled;+ }++ const auto len = std::min<size_t>( strlen( function ), std::numeric_limits<uint16_t>::max() );+ cb_data[cb_num].name = CopyStringFast( function, len );+ cb_data[cb_num].file = NormalizePath( fn );+ if( !cb_data[cb_num].file ) cb_data[cb_num].file = CopyStringFast( fn );+ cb_data[cb_num].line = lineno;+ }++ if( ++cb_num >= MaxCbTrace )+ {+ return 1;+ }+ else+ {+ return 0;+ }+}++static void CallstackErrorCb( void* /*data*/, const char* /*msg*/, int /*errnum*/ )+{+ for( int i=0; i<cb_num; i++ )+ {+ tracy_free_fast( (void*)cb_data[i].name );+ tracy_free_fast( (void*)cb_data[i].file );+ }++ cb_data[0].name = CopyStringFast( "[error]" );+ cb_data[0].file = CopyStringFast( "[error]" );+ cb_data[0].line = 0;++ cb_num = 1;+}++void SymInfoCallback( void* /*data*/, uintptr_t pc, const char* symname, uintptr_t symval, uintptr_t symsize )+{+ cb_data[cb_num-1].symLen = (uint32_t)symsize;+ cb_data[cb_num-1].symAddr = (uint64_t)symval;+}++void SymInfoError( void* /*data*/, const char* /*msg*/, int /*errnum*/ )+{+ cb_data[cb_num-1].symLen = 0;+ cb_data[cb_num-1].symAddr = 0;+}++void GetSymbolForOfflineResolve(void* address, uint64_t imageBaseAddress, CallstackEntry& cbEntry)+{+ // tagged with a string that we can identify as an unresolved symbol+ cbEntry.name = CopyStringFast( "[unresolved]" );+ // set .so relative offset so it can be resolved offline+ cbEntry.symAddr = (uint64_t)address - imageBaseAddress;+ cbEntry.symLen = 0x0;+ cbEntry.file = CopyStringFast( "[unknown]" );+ cbEntry.line = 0;+}++CallstackEntryData DecodeCallstackPtr( uint64_t ptr )+{+ InitRpmalloc();+ if( ptr >> 63 == 0 )+ {+ const char* imageName = nullptr;+ uint64_t imageBaseAddress = 0x0;++#ifdef TRACY_USE_IMAGE_CACHE+ const auto* image = s_imageCache->GetImageForAddress((void*)ptr);+ if( image )+ {+ imageName = image->m_name;+ imageBaseAddress = uint64_t(image->m_startAddress);+ }+#else+ Dl_info dlinfo;+ if( dladdr( (void*)ptr, &dlinfo ) )+ {+ imageName = dlinfo.dli_fname;+ imageBaseAddress = uint64_t( dlinfo.dli_fbase );+ }+#endif++ if( s_shouldResolveSymbolsOffline )+ {+ cb_num = 1;+ GetSymbolForOfflineResolve( (void*)ptr, imageBaseAddress, cb_data[0] );+ }+ else+ {+ cb_num = 0;+ backtrace_pcinfo( cb_bts, ptr, CallstackDataCb, CallstackErrorCb, nullptr );+ assert( cb_num > 0 );++ backtrace_syminfo( cb_bts, ptr, SymInfoCallback, SymInfoError, nullptr );+ }++ return { cb_data, uint8_t( cb_num ), imageName ? imageName : "[unknown]" };+ }+#ifdef __linux+ else if( s_kernelSym )+ {+ auto it = std::lower_bound( s_kernelSym, s_kernelSym + s_kernelSymCnt, ptr, []( const KernelSymbol& lhs, const uint64_t& rhs ) { return lhs.addr + lhs.size < rhs; } );+ if( it != s_kernelSym + s_kernelSymCnt )+ {+ cb_data[0].name = CopyStringFast( it->name );+ cb_data[0].file = CopyStringFast( "<kernel>" );+ cb_data[0].line = 0;+ cb_data[0].symLen = it->size;+ cb_data[0].symAddr = it->addr;+ return { cb_data, 1, it->mod ? it->mod : "<kernel>" };+ }+ }+#endif++ cb_data[0].name = CopyStringFast( "[unknown]" );+ cb_data[0].file = CopyStringFast( "<kernel>" );+ cb_data[0].line = 0;+ cb_data[0].symLen = 0;+ cb_data[0].symAddr = 0;+ return { cb_data, 1, "<kernel>" };+}++#elif TRACY_HAS_CALLSTACK == 5++void InitCallstackCritical()+{+}++void InitCallstack()+{+ ___tracy_init_demangle_buffer();+}++void EndCallstack()+{+ ___tracy_free_demangle_buffer();+}++const char* DecodeCallstackPtrFast( uint64_t ptr )+{+ static char ret[1024];+ auto vptr = (void*)ptr;+ const char* symname = nullptr;+ Dl_info dlinfo;+ if( dladdr( vptr, &dlinfo ) && dlinfo.dli_sname )+ {+ symname = dlinfo.dli_sname;+ }+ if( symname )+ {+ strcpy( ret, symname );+ }+ else+ {+ *ret = '\0';+ }+ return ret;+}++CallstackSymbolData DecodeSymbolAddress( uint64_t ptr )+{+ const char* symloc = nullptr;+ Dl_info dlinfo;+ if( dladdr( (void*)ptr, &dlinfo ) ) symloc = dlinfo.dli_fname;+ if( !symloc ) symloc = "[unknown]";+ return CallstackSymbolData { symloc, 0, false, 0 };+}++CallstackEntryData DecodeCallstackPtr( uint64_t ptr )+{+ static CallstackEntry cb;+ cb.line = 0;++ const char* symname = nullptr;+ const char* symloc = nullptr;+ auto vptr = (void*)ptr;+ ptrdiff_t symoff = 0;+ void* symaddr = nullptr;++ Dl_info dlinfo;+ if( dladdr( vptr, &dlinfo ) )+ {+ symloc = dlinfo.dli_fname;+ symname = dlinfo.dli_sname;+ symoff = (char*)ptr - (char*)dlinfo.dli_saddr;+ symaddr = dlinfo.dli_saddr;+ const char* demangled = ___tracy_demangle( symname );+ if( demangled ) symname = demangled;+ }++ if( !symname ) symname = "[unknown]";+ if( !symloc ) symloc = "[unknown]";++ if( symoff == 0 )+ {+ const auto len = std::min<size_t>( strlen( symname ), std::numeric_limits<uint16_t>::max() );+ cb.name = CopyString( symname, len );+ }+ else+ {+ char buf[32];+ const auto offlen = sprintf( buf, " + %td", symoff );+ const auto namelen = std::min<size_t>( strlen( symname ), std::numeric_limits<uint16_t>::max() - offlen );+ auto name = (char*)tracy_malloc( namelen + offlen + 1 );+ memcpy( name, symname, namelen );+ memcpy( name + namelen, buf, offlen );+ name[namelen + offlen] = '\0';+ cb.name = name;+ }++ cb.file = CopyString( "[unknown]" );+ cb.symLen = 0;+ cb.symAddr = (uint64_t)symaddr;++ return { &cb, 1, symloc };+}++#endif++}++#endif
+ cbits/tracy/public/client/TracyCallstack.h view
@@ -0,0 +1,35 @@+#ifndef __TRACYCALLSTACK_H__+#define __TRACYCALLSTACK_H__++#ifndef TRACY_NO_CALLSTACK++# if !defined _WIN32+# include <sys/param.h>+# endif++# if defined _WIN32+# include "../common/TracyUwp.hpp"+# ifndef TRACY_UWP+# define TRACY_HAS_CALLSTACK 1+# endif+# elif defined __ANDROID__+# if !defined __arm__ || __ANDROID_API__ >= 21+# define TRACY_HAS_CALLSTACK 2+# else+# define TRACY_HAS_CALLSTACK 5+# endif+# elif defined __linux+# if defined _GNU_SOURCE && defined __GLIBC__+# define TRACY_HAS_CALLSTACK 3+# else+# define TRACY_HAS_CALLSTACK 2+# endif+# elif defined __APPLE__+# define TRACY_HAS_CALLSTACK 4+# elif defined BSD+# define TRACY_HAS_CALLSTACK 6+# endif++#endif++#endif
+ cbits/tracy/public/client/TracyCallstack.hpp view
@@ -0,0 +1,155 @@+#ifndef __TRACYCALLSTACK_HPP__+#define __TRACYCALLSTACK_HPP__++#include "../common/TracyApi.h"+#include "../common/TracyForceInline.hpp"+#include "TracyCallstack.h"++#ifndef TRACY_HAS_CALLSTACK++namespace tracy+{+static constexpr bool has_callstack() { return false; }+static tracy_force_inline void* Callstack( int32_t /*depth*/ ) { return nullptr; }+}++#else++#if TRACY_HAS_CALLSTACK == 2 || TRACY_HAS_CALLSTACK == 5+# include <unwind.h>+#elif TRACY_HAS_CALLSTACK >= 3+# ifdef TRACY_LIBUNWIND_BACKTRACE+ // libunwind is, in general, significantly faster than execinfo based backtraces+# define UNW_LOCAL_ONLY+# include <libunwind.h>+# else+# include <execinfo.h>+# endif+#endif++#ifdef TRACY_DEBUGINFOD+# include <elfutils/debuginfod.h>+#endif++#include <assert.h>+#include <stdint.h>++#include "../common/TracyAlloc.hpp"++namespace tracy+{++static constexpr bool has_callstack() { return true; }++struct CallstackSymbolData+{+ const char* file;+ uint32_t line;+ bool needFree;+ uint64_t symAddr;+};++struct CallstackEntry+{+ const char* name;+ const char* file;+ uint32_t line;+ uint32_t symLen;+ uint64_t symAddr;+};++struct CallstackEntryData+{+ const CallstackEntry* data;+ uint8_t size;+ const char* imageName;+};++CallstackSymbolData DecodeSymbolAddress( uint64_t ptr );+const char* DecodeCallstackPtrFast( uint64_t ptr );+CallstackEntryData DecodeCallstackPtr( uint64_t ptr );+void InitCallstack();+void InitCallstackCritical();+void EndCallstack();+const char* GetKernelModulePath( uint64_t addr );++#ifdef TRACY_DEBUGINFOD+const uint8_t* GetBuildIdForImage( const char* image, size_t& size );+debuginfod_client* GetDebuginfodClient();+#endif++#if TRACY_HAS_CALLSTACK == 1++extern "C"+{+ TRACY_API unsigned long ___tracy_RtlWalkFrameChain( void**, unsigned long, unsigned long );+}++static tracy_force_inline void* Callstack( int32_t depth )+{+ assert( depth >= 1 && depth < 63 );+ auto trace = (uintptr_t*)tracy_malloc( ( 1 + depth ) * sizeof( uintptr_t ) );+ const auto num = ___tracy_RtlWalkFrameChain( (void**)( trace + 1 ), depth, 0 );+ *trace = num;+ return trace;+}++#elif TRACY_HAS_CALLSTACK == 2 || TRACY_HAS_CALLSTACK == 5++struct BacktraceState+{+ void** current;+ void** end;+};++static _Unwind_Reason_Code tracy_unwind_callback( struct _Unwind_Context* ctx, void* arg )+{+ auto state = (BacktraceState*)arg;+ uintptr_t pc = _Unwind_GetIP( ctx );+ if( pc )+ {+ if( state->current == state->end ) return _URC_END_OF_STACK;+ *state->current++ = (void*)pc;+ }+ return _URC_NO_REASON;+}++static tracy_force_inline void* Callstack( int32_t depth )+{+ assert( depth >= 1 && depth < 63 );++ auto trace = (uintptr_t*)tracy_malloc( ( 1 + depth ) * sizeof( uintptr_t ) );+ BacktraceState state = { (void**)(trace+1), (void**)(trace+1+depth) };+ _Unwind_Backtrace( tracy_unwind_callback, &state );++ *trace = (uintptr_t*)state.current - trace + 1;++ return trace;+}++#elif TRACY_HAS_CALLSTACK == 3 || TRACY_HAS_CALLSTACK == 4 || TRACY_HAS_CALLSTACK == 6++static tracy_force_inline void* Callstack( int32_t depth )+{+ assert( depth >= 1 );++ auto trace = (uintptr_t*)tracy_malloc( ( 1 + (size_t)depth ) * sizeof( uintptr_t ) );++#ifdef TRACY_LIBUNWIND_BACKTRACE+ size_t num = unw_backtrace( (void**)(trace+1), depth );+#else+ const auto num = (size_t)backtrace( (void**)(trace+1), depth );+#endif++ *trace = num;++ return trace;+}++#endif++}++#endif++#endif
+ cbits/tracy/public/client/TracyCpuid.hpp view
@@ -0,0 +1,12 @@+#ifndef __TRACYCPUID_HPP__+#define __TRACYCPUID_HPP__++// Prior to GCC 11 the cpuid.h header did not have any include guards and thus+// including it more than once would cause a compiler error due to symbol+// redefinitions. In order to support older GCC versions, we have to wrap this+// include between custom include guards to prevent this issue.+// See also https://github.com/wolfpld/tracy/issues/452++#include <cpuid.h>++#endif
+ cbits/tracy/public/client/TracyDebug.hpp view
@@ -0,0 +1,11 @@+#ifndef __TRACYPRINT_HPP__+#define __TRACYPRINT_HPP__++#ifdef TRACY_VERBOSE+# include <stdio.h>+# define TracyDebug(...) fprintf( stderr, __VA_ARGS__ );+#else+# define TracyDebug(...)+#endif++#endif
+ cbits/tracy/public/client/TracyDxt1.cpp view
@@ -0,0 +1,644 @@+#include "TracyDxt1.hpp"+#include "../common/TracyForceInline.hpp"++#include <assert.h>+#include <stdint.h>+#include <string.h>++#ifdef __ARM_NEON+# include <arm_neon.h>+#endif++#if defined __AVX__ && !defined __SSE4_1__+# define __SSE4_1__+#endif++#if defined __SSE4_1__ || defined __AVX2__+# ifdef _MSC_VER+# include <intrin.h>+# else+# include <x86intrin.h>+# ifndef _mm256_cvtsi256_si32+# define _mm256_cvtsi256_si32( v ) ( _mm_cvtsi128_si32( _mm256_castsi256_si128( v ) ) )+# endif+# endif+#endif++namespace tracy+{++static inline uint16_t to565( uint8_t r, uint8_t g, uint8_t b )+{+ return ( ( r & 0xF8 ) << 8 ) | ( ( g & 0xFC ) << 3 ) | ( b >> 3 );+}++static inline uint16_t to565( uint32_t c )+{+ return+ ( ( c & 0xF80000 ) >> 19 ) |+ ( ( c & 0x00FC00 ) >> 5 ) |+ ( ( c & 0x0000F8 ) << 8 );+}++static const uint16_t DivTable[255*3+1] = {+ 0xffff, 0xffff, 0xffff, 0xffff, 0xcccc, 0xaaaa, 0x9249, 0x8000, 0x71c7, 0x6666, 0x5d17, 0x5555, 0x4ec4, 0x4924, 0x4444, 0x4000,+ 0x3c3c, 0x38e3, 0x35e5, 0x3333, 0x30c3, 0x2e8b, 0x2c85, 0x2aaa, 0x28f5, 0x2762, 0x25ed, 0x2492, 0x234f, 0x2222, 0x2108, 0x2000,+ 0x1f07, 0x1e1e, 0x1d41, 0x1c71, 0x1bac, 0x1af2, 0x1a41, 0x1999, 0x18f9, 0x1861, 0x17d0, 0x1745, 0x16c1, 0x1642, 0x15c9, 0x1555,+ 0x14e5, 0x147a, 0x1414, 0x13b1, 0x1352, 0x12f6, 0x129e, 0x1249, 0x11f7, 0x11a7, 0x115b, 0x1111, 0x10c9, 0x1084, 0x1041, 0x1000,+ 0x0fc0, 0x0f83, 0x0f48, 0x0f0f, 0x0ed7, 0x0ea0, 0x0e6c, 0x0e38, 0x0e07, 0x0dd6, 0x0da7, 0x0d79, 0x0d4c, 0x0d20, 0x0cf6, 0x0ccc,+ 0x0ca4, 0x0c7c, 0x0c56, 0x0c30, 0x0c0c, 0x0be8, 0x0bc5, 0x0ba2, 0x0b81, 0x0b60, 0x0b40, 0x0b21, 0x0b02, 0x0ae4, 0x0ac7, 0x0aaa,+ 0x0a8e, 0x0a72, 0x0a57, 0x0a3d, 0x0a23, 0x0a0a, 0x09f1, 0x09d8, 0x09c0, 0x09a9, 0x0991, 0x097b, 0x0964, 0x094f, 0x0939, 0x0924,+ 0x090f, 0x08fb, 0x08e7, 0x08d3, 0x08c0, 0x08ad, 0x089a, 0x0888, 0x0876, 0x0864, 0x0853, 0x0842, 0x0831, 0x0820, 0x0810, 0x0800,+ 0x07f0, 0x07e0, 0x07d1, 0x07c1, 0x07b3, 0x07a4, 0x0795, 0x0787, 0x0779, 0x076b, 0x075d, 0x0750, 0x0743, 0x0736, 0x0729, 0x071c,+ 0x070f, 0x0703, 0x06f7, 0x06eb, 0x06df, 0x06d3, 0x06c8, 0x06bc, 0x06b1, 0x06a6, 0x069b, 0x0690, 0x0685, 0x067b, 0x0670, 0x0666,+ 0x065c, 0x0652, 0x0648, 0x063e, 0x0634, 0x062b, 0x0621, 0x0618, 0x060f, 0x0606, 0x05fd, 0x05f4, 0x05eb, 0x05e2, 0x05d9, 0x05d1,+ 0x05c9, 0x05c0, 0x05b8, 0x05b0, 0x05a8, 0x05a0, 0x0598, 0x0590, 0x0588, 0x0581, 0x0579, 0x0572, 0x056b, 0x0563, 0x055c, 0x0555,+ 0x054e, 0x0547, 0x0540, 0x0539, 0x0532, 0x052b, 0x0525, 0x051e, 0x0518, 0x0511, 0x050b, 0x0505, 0x04fe, 0x04f8, 0x04f2, 0x04ec,+ 0x04e6, 0x04e0, 0x04da, 0x04d4, 0x04ce, 0x04c8, 0x04c3, 0x04bd, 0x04b8, 0x04b2, 0x04ad, 0x04a7, 0x04a2, 0x049c, 0x0497, 0x0492,+ 0x048d, 0x0487, 0x0482, 0x047d, 0x0478, 0x0473, 0x046e, 0x0469, 0x0465, 0x0460, 0x045b, 0x0456, 0x0452, 0x044d, 0x0448, 0x0444,+ 0x043f, 0x043b, 0x0436, 0x0432, 0x042d, 0x0429, 0x0425, 0x0421, 0x041c, 0x0418, 0x0414, 0x0410, 0x040c, 0x0408, 0x0404, 0x0400,+ 0x03fc, 0x03f8, 0x03f4, 0x03f0, 0x03ec, 0x03e8, 0x03e4, 0x03e0, 0x03dd, 0x03d9, 0x03d5, 0x03d2, 0x03ce, 0x03ca, 0x03c7, 0x03c3,+ 0x03c0, 0x03bc, 0x03b9, 0x03b5, 0x03b2, 0x03ae, 0x03ab, 0x03a8, 0x03a4, 0x03a1, 0x039e, 0x039b, 0x0397, 0x0394, 0x0391, 0x038e,+ 0x038b, 0x0387, 0x0384, 0x0381, 0x037e, 0x037b, 0x0378, 0x0375, 0x0372, 0x036f, 0x036c, 0x0369, 0x0366, 0x0364, 0x0361, 0x035e,+ 0x035b, 0x0358, 0x0355, 0x0353, 0x0350, 0x034d, 0x034a, 0x0348, 0x0345, 0x0342, 0x0340, 0x033d, 0x033a, 0x0338, 0x0335, 0x0333,+ 0x0330, 0x032e, 0x032b, 0x0329, 0x0326, 0x0324, 0x0321, 0x031f, 0x031c, 0x031a, 0x0317, 0x0315, 0x0313, 0x0310, 0x030e, 0x030c,+ 0x0309, 0x0307, 0x0305, 0x0303, 0x0300, 0x02fe, 0x02fc, 0x02fa, 0x02f7, 0x02f5, 0x02f3, 0x02f1, 0x02ef, 0x02ec, 0x02ea, 0x02e8,+ 0x02e6, 0x02e4, 0x02e2, 0x02e0, 0x02de, 0x02dc, 0x02da, 0x02d8, 0x02d6, 0x02d4, 0x02d2, 0x02d0, 0x02ce, 0x02cc, 0x02ca, 0x02c8,+ 0x02c6, 0x02c4, 0x02c2, 0x02c0, 0x02be, 0x02bc, 0x02bb, 0x02b9, 0x02b7, 0x02b5, 0x02b3, 0x02b1, 0x02b0, 0x02ae, 0x02ac, 0x02aa,+ 0x02a8, 0x02a7, 0x02a5, 0x02a3, 0x02a1, 0x02a0, 0x029e, 0x029c, 0x029b, 0x0299, 0x0297, 0x0295, 0x0294, 0x0292, 0x0291, 0x028f,+ 0x028d, 0x028c, 0x028a, 0x0288, 0x0287, 0x0285, 0x0284, 0x0282, 0x0280, 0x027f, 0x027d, 0x027c, 0x027a, 0x0279, 0x0277, 0x0276,+ 0x0274, 0x0273, 0x0271, 0x0270, 0x026e, 0x026d, 0x026b, 0x026a, 0x0268, 0x0267, 0x0265, 0x0264, 0x0263, 0x0261, 0x0260, 0x025e,+ 0x025d, 0x025c, 0x025a, 0x0259, 0x0257, 0x0256, 0x0255, 0x0253, 0x0252, 0x0251, 0x024f, 0x024e, 0x024d, 0x024b, 0x024a, 0x0249,+ 0x0247, 0x0246, 0x0245, 0x0243, 0x0242, 0x0241, 0x0240, 0x023e, 0x023d, 0x023c, 0x023b, 0x0239, 0x0238, 0x0237, 0x0236, 0x0234,+ 0x0233, 0x0232, 0x0231, 0x0230, 0x022e, 0x022d, 0x022c, 0x022b, 0x022a, 0x0229, 0x0227, 0x0226, 0x0225, 0x0224, 0x0223, 0x0222,+ 0x0220, 0x021f, 0x021e, 0x021d, 0x021c, 0x021b, 0x021a, 0x0219, 0x0218, 0x0216, 0x0215, 0x0214, 0x0213, 0x0212, 0x0211, 0x0210,+ 0x020f, 0x020e, 0x020d, 0x020c, 0x020b, 0x020a, 0x0209, 0x0208, 0x0207, 0x0206, 0x0205, 0x0204, 0x0203, 0x0202, 0x0201, 0x0200,+ 0x01ff, 0x01fe, 0x01fd, 0x01fc, 0x01fb, 0x01fa, 0x01f9, 0x01f8, 0x01f7, 0x01f6, 0x01f5, 0x01f4, 0x01f3, 0x01f2, 0x01f1, 0x01f0,+ 0x01ef, 0x01ee, 0x01ed, 0x01ec, 0x01eb, 0x01ea, 0x01e9, 0x01e9, 0x01e8, 0x01e7, 0x01e6, 0x01e5, 0x01e4, 0x01e3, 0x01e2, 0x01e1,+ 0x01e0, 0x01e0, 0x01df, 0x01de, 0x01dd, 0x01dc, 0x01db, 0x01da, 0x01da, 0x01d9, 0x01d8, 0x01d7, 0x01d6, 0x01d5, 0x01d4, 0x01d4,+ 0x01d3, 0x01d2, 0x01d1, 0x01d0, 0x01cf, 0x01cf, 0x01ce, 0x01cd, 0x01cc, 0x01cb, 0x01cb, 0x01ca, 0x01c9, 0x01c8, 0x01c7, 0x01c7,+ 0x01c6, 0x01c5, 0x01c4, 0x01c3, 0x01c3, 0x01c2, 0x01c1, 0x01c0, 0x01c0, 0x01bf, 0x01be, 0x01bd, 0x01bd, 0x01bc, 0x01bb, 0x01ba,+ 0x01ba, 0x01b9, 0x01b8, 0x01b7, 0x01b7, 0x01b6, 0x01b5, 0x01b4, 0x01b4, 0x01b3, 0x01b2, 0x01b2, 0x01b1, 0x01b0, 0x01af, 0x01af,+ 0x01ae, 0x01ad, 0x01ad, 0x01ac, 0x01ab, 0x01aa, 0x01aa, 0x01a9, 0x01a8, 0x01a8, 0x01a7, 0x01a6, 0x01a6, 0x01a5, 0x01a4, 0x01a4,+ 0x01a3, 0x01a2, 0x01a2, 0x01a1, 0x01a0, 0x01a0, 0x019f, 0x019e, 0x019e, 0x019d, 0x019c, 0x019c, 0x019b, 0x019a, 0x019a, 0x0199,+ 0x0198, 0x0198, 0x0197, 0x0197, 0x0196, 0x0195, 0x0195, 0x0194, 0x0193, 0x0193, 0x0192, 0x0192, 0x0191, 0x0190, 0x0190, 0x018f,+ 0x018f, 0x018e, 0x018d, 0x018d, 0x018c, 0x018b, 0x018b, 0x018a, 0x018a, 0x0189, 0x0189, 0x0188, 0x0187, 0x0187, 0x0186, 0x0186,+ 0x0185, 0x0184, 0x0184, 0x0183, 0x0183, 0x0182, 0x0182, 0x0181, 0x0180, 0x0180, 0x017f, 0x017f, 0x017e, 0x017e, 0x017d, 0x017d,+ 0x017c, 0x017b, 0x017b, 0x017a, 0x017a, 0x0179, 0x0179, 0x0178, 0x0178, 0x0177, 0x0177, 0x0176, 0x0175, 0x0175, 0x0174, 0x0174,+ 0x0173, 0x0173, 0x0172, 0x0172, 0x0171, 0x0171, 0x0170, 0x0170, 0x016f, 0x016f, 0x016e, 0x016e, 0x016d, 0x016d, 0x016c, 0x016c,+ 0x016b, 0x016b, 0x016a, 0x016a, 0x0169, 0x0169, 0x0168, 0x0168, 0x0167, 0x0167, 0x0166, 0x0166, 0x0165, 0x0165, 0x0164, 0x0164,+ 0x0163, 0x0163, 0x0162, 0x0162, 0x0161, 0x0161, 0x0160, 0x0160, 0x015f, 0x015f, 0x015e, 0x015e, 0x015d, 0x015d, 0x015d, 0x015c,+ 0x015c, 0x015b, 0x015b, 0x015a, 0x015a, 0x0159, 0x0159, 0x0158, 0x0158, 0x0158, 0x0157, 0x0157, 0x0156, 0x0156+};++#if defined __ARM_NEON && defined __aarch64__+static const uint16_t DivTableNEON[255*3+1] = {+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,+ 0x0000, 0x1c71, 0x1af2, 0x1999, 0x1861, 0x1745, 0x1642, 0x1555, 0x147a, 0x13b1, 0x12f6, 0x1249, 0x11a7, 0x1111, 0x1084, 0x1000,+ 0x0f83, 0x0f0f, 0x0ea0, 0x0e38, 0x0dd6, 0x0d79, 0x0d20, 0x0ccc, 0x0c7c, 0x0c30, 0x0be8, 0x0ba2, 0x0b60, 0x0b21, 0x0ae4, 0x0aaa,+ 0x0a72, 0x0a3d, 0x0a0a, 0x09d8, 0x09a9, 0x097b, 0x094f, 0x0924, 0x08fb, 0x08d3, 0x08ad, 0x0888, 0x0864, 0x0842, 0x0820, 0x0800,+ 0x07e0, 0x07c1, 0x07a4, 0x0787, 0x076b, 0x0750, 0x0736, 0x071c, 0x0703, 0x06eb, 0x06d3, 0x06bc, 0x06a6, 0x0690, 0x067b, 0x0666,+ 0x0652, 0x063e, 0x062b, 0x0618, 0x0606, 0x05f4, 0x05e2, 0x05d1, 0x05c0, 0x05b0, 0x05a0, 0x0590, 0x0581, 0x0572, 0x0563, 0x0555,+ 0x0547, 0x0539, 0x052b, 0x051e, 0x0511, 0x0505, 0x04f8, 0x04ec, 0x04e0, 0x04d4, 0x04c8, 0x04bd, 0x04b2, 0x04a7, 0x049c, 0x0492,+ 0x0487, 0x047d, 0x0473, 0x0469, 0x0460, 0x0456, 0x044d, 0x0444, 0x043b, 0x0432, 0x0429, 0x0421, 0x0418, 0x0410, 0x0408, 0x0400,+ 0x03f8, 0x03f0, 0x03e8, 0x03e0, 0x03d9, 0x03d2, 0x03ca, 0x03c3, 0x03bc, 0x03b5, 0x03ae, 0x03a8, 0x03a1, 0x039b, 0x0394, 0x038e,+ 0x0387, 0x0381, 0x037b, 0x0375, 0x036f, 0x0369, 0x0364, 0x035e, 0x0358, 0x0353, 0x034d, 0x0348, 0x0342, 0x033d, 0x0338, 0x0333,+ 0x032e, 0x0329, 0x0324, 0x031f, 0x031a, 0x0315, 0x0310, 0x030c, 0x0307, 0x0303, 0x02fe, 0x02fa, 0x02f5, 0x02f1, 0x02ec, 0x02e8,+ 0x02e4, 0x02e0, 0x02dc, 0x02d8, 0x02d4, 0x02d0, 0x02cc, 0x02c8, 0x02c4, 0x02c0, 0x02bc, 0x02b9, 0x02b5, 0x02b1, 0x02ae, 0x02aa,+ 0x02a7, 0x02a3, 0x02a0, 0x029c, 0x0299, 0x0295, 0x0292, 0x028f, 0x028c, 0x0288, 0x0285, 0x0282, 0x027f, 0x027c, 0x0279, 0x0276,+ 0x0273, 0x0270, 0x026d, 0x026a, 0x0267, 0x0264, 0x0261, 0x025e, 0x025c, 0x0259, 0x0256, 0x0253, 0x0251, 0x024e, 0x024b, 0x0249,+ 0x0246, 0x0243, 0x0241, 0x023e, 0x023c, 0x0239, 0x0237, 0x0234, 0x0232, 0x0230, 0x022d, 0x022b, 0x0229, 0x0226, 0x0224, 0x0222,+ 0x021f, 0x021d, 0x021b, 0x0219, 0x0216, 0x0214, 0x0212, 0x0210, 0x020e, 0x020c, 0x020a, 0x0208, 0x0206, 0x0204, 0x0202, 0x0200,+ 0x01fe, 0x01fc, 0x01fa, 0x01f8, 0x01f6, 0x01f4, 0x01f2, 0x01f0, 0x01ee, 0x01ec, 0x01ea, 0x01e9, 0x01e7, 0x01e5, 0x01e3, 0x01e1,+ 0x01e0, 0x01de, 0x01dc, 0x01da, 0x01d9, 0x01d7, 0x01d5, 0x01d4, 0x01d2, 0x01d0, 0x01cf, 0x01cd, 0x01cb, 0x01ca, 0x01c8, 0x01c7,+ 0x01c5, 0x01c3, 0x01c2, 0x01c0, 0x01bf, 0x01bd, 0x01bc, 0x01ba, 0x01b9, 0x01b7, 0x01b6, 0x01b4, 0x01b3, 0x01b2, 0x01b0, 0x01af,+ 0x01ad, 0x01ac, 0x01aa, 0x01a9, 0x01a8, 0x01a6, 0x01a5, 0x01a4, 0x01a2, 0x01a1, 0x01a0, 0x019e, 0x019d, 0x019c, 0x019a, 0x0199,+ 0x0198, 0x0197, 0x0195, 0x0194, 0x0193, 0x0192, 0x0190, 0x018f, 0x018e, 0x018d, 0x018b, 0x018a, 0x0189, 0x0188, 0x0187, 0x0186,+ 0x0184, 0x0183, 0x0182, 0x0181, 0x0180, 0x017f, 0x017e, 0x017d, 0x017b, 0x017a, 0x0179, 0x0178, 0x0177, 0x0176, 0x0175, 0x0174,+ 0x0173, 0x0172, 0x0171, 0x0170, 0x016f, 0x016e, 0x016d, 0x016c, 0x016b, 0x016a, 0x0169, 0x0168, 0x0167, 0x0166, 0x0165, 0x0164,+ 0x0163, 0x0162, 0x0161, 0x0160, 0x015f, 0x015e, 0x015d, 0x015c, 0x015b, 0x015a, 0x0159, 0x0158, 0x0158, 0x0157, 0x0156, 0x0155,+ 0x0154, 0x0153, 0x0152, 0x0151, 0x0150, 0x0150, 0x014f, 0x014e, 0x014d, 0x014c, 0x014b, 0x014a, 0x014a, 0x0149, 0x0148, 0x0147,+ 0x0146, 0x0146, 0x0145, 0x0144, 0x0143, 0x0142, 0x0142, 0x0141, 0x0140, 0x013f, 0x013e, 0x013e, 0x013d, 0x013c, 0x013b, 0x013b,+ 0x013a, 0x0139, 0x0138, 0x0138, 0x0137, 0x0136, 0x0135, 0x0135, 0x0134, 0x0133, 0x0132, 0x0132, 0x0131, 0x0130, 0x0130, 0x012f,+ 0x012e, 0x012e, 0x012d, 0x012c, 0x012b, 0x012b, 0x012a, 0x0129, 0x0129, 0x0128, 0x0127, 0x0127, 0x0126, 0x0125, 0x0125, 0x0124,+ 0x0123, 0x0123, 0x0122, 0x0121, 0x0121, 0x0120, 0x0120, 0x011f, 0x011e, 0x011e, 0x011d, 0x011c, 0x011c, 0x011b, 0x011b, 0x011a,+ 0x0119, 0x0119, 0x0118, 0x0118, 0x0117, 0x0116, 0x0116, 0x0115, 0x0115, 0x0114, 0x0113, 0x0113, 0x0112, 0x0112, 0x0111, 0x0111,+ 0x0110, 0x010f, 0x010f, 0x010e, 0x010e, 0x010d, 0x010d, 0x010c, 0x010c, 0x010b, 0x010a, 0x010a, 0x0109, 0x0109, 0x0108, 0x0108,+ 0x0107, 0x0107, 0x0106, 0x0106, 0x0105, 0x0105, 0x0104, 0x0104, 0x0103, 0x0103, 0x0102, 0x0102, 0x0101, 0x0101, 0x0100, 0x0100,+ 0x00ff, 0x00ff, 0x00fe, 0x00fe, 0x00fd, 0x00fd, 0x00fc, 0x00fc, 0x00fb, 0x00fb, 0x00fa, 0x00fa, 0x00f9, 0x00f9, 0x00f8, 0x00f8,+ 0x00f7, 0x00f7, 0x00f6, 0x00f6, 0x00f5, 0x00f5, 0x00f4, 0x00f4, 0x00f4, 0x00f3, 0x00f3, 0x00f2, 0x00f2, 0x00f1, 0x00f1, 0x00f0,+ 0x00f0, 0x00f0, 0x00ef, 0x00ef, 0x00ee, 0x00ee, 0x00ed, 0x00ed, 0x00ed, 0x00ec, 0x00ec, 0x00eb, 0x00eb, 0x00ea, 0x00ea, 0x00ea,+ 0x00e9, 0x00e9, 0x00e8, 0x00e8, 0x00e7, 0x00e7, 0x00e7, 0x00e6, 0x00e6, 0x00e5, 0x00e5, 0x00e5, 0x00e4, 0x00e4, 0x00e3, 0x00e3,+ 0x00e3, 0x00e2, 0x00e2, 0x00e1, 0x00e1, 0x00e1, 0x00e0, 0x00e0, 0x00e0, 0x00df, 0x00df, 0x00de, 0x00de, 0x00de, 0x00dd, 0x00dd,+ 0x00dd, 0x00dc, 0x00dc, 0x00db, 0x00db, 0x00db, 0x00da, 0x00da, 0x00da, 0x00d9, 0x00d9, 0x00d9, 0x00d8, 0x00d8, 0x00d7, 0x00d7,+ 0x00d7, 0x00d6, 0x00d6, 0x00d6, 0x00d5, 0x00d5, 0x00d5, 0x00d4, 0x00d4, 0x00d4, 0x00d3, 0x00d3, 0x00d3, 0x00d2, 0x00d2, 0x00d2,+ 0x00d1, 0x00d1, 0x00d1, 0x00d0, 0x00d0, 0x00d0, 0x00cf, 0x00cf, 0x00cf, 0x00ce, 0x00ce, 0x00ce, 0x00cd, 0x00cd, 0x00cd, 0x00cc,+ 0x00cc, 0x00cc, 0x00cb, 0x00cb, 0x00cb, 0x00ca, 0x00ca, 0x00ca, 0x00c9, 0x00c9, 0x00c9, 0x00c9, 0x00c8, 0x00c8, 0x00c8, 0x00c7,+ 0x00c7, 0x00c7, 0x00c6, 0x00c6, 0x00c6, 0x00c5, 0x00c5, 0x00c5, 0x00c5, 0x00c4, 0x00c4, 0x00c4, 0x00c3, 0x00c3, 0x00c3, 0x00c3,+ 0x00c2, 0x00c2, 0x00c2, 0x00c1, 0x00c1, 0x00c1, 0x00c1, 0x00c0, 0x00c0, 0x00c0, 0x00bf, 0x00bf, 0x00bf, 0x00bf, 0x00be, 0x00be,+ 0x00be, 0x00bd, 0x00bd, 0x00bd, 0x00bd, 0x00bc, 0x00bc, 0x00bc, 0x00bc, 0x00bb, 0x00bb, 0x00bb, 0x00ba, 0x00ba, 0x00ba, 0x00ba,+ 0x00b9, 0x00b9, 0x00b9, 0x00b9, 0x00b8, 0x00b8, 0x00b8, 0x00b8, 0x00b7, 0x00b7, 0x00b7, 0x00b7, 0x00b6, 0x00b6, 0x00b6, 0x00b6,+ 0x00b5, 0x00b5, 0x00b5, 0x00b5, 0x00b4, 0x00b4, 0x00b4, 0x00b4, 0x00b3, 0x00b3, 0x00b3, 0x00b3, 0x00b2, 0x00b2, 0x00b2, 0x00b2,+ 0x00b1, 0x00b1, 0x00b1, 0x00b1, 0x00b0, 0x00b0, 0x00b0, 0x00b0, 0x00af, 0x00af, 0x00af, 0x00af, 0x00ae, 0x00ae, 0x00ae, 0x00ae,+ 0x00ae, 0x00ad, 0x00ad, 0x00ad, 0x00ad, 0x00ac, 0x00ac, 0x00ac, 0x00ac, 0x00ac, 0x00ab, 0x00ab, 0x00ab, 0x00ab,+};+#endif+++static tracy_force_inline uint64_t ProcessRGB( const uint8_t* src )+{+#ifdef __SSE4_1__+ __m128i px0 = _mm_loadu_si128(((__m128i*)src) + 0);+ __m128i px1 = _mm_loadu_si128(((__m128i*)src) + 1);+ __m128i px2 = _mm_loadu_si128(((__m128i*)src) + 2);+ __m128i px3 = _mm_loadu_si128(((__m128i*)src) + 3);++ __m128i smask = _mm_set1_epi32( 0xF8FCF8 );+ __m128i sd0 = _mm_and_si128( px0, smask );+ __m128i sd1 = _mm_and_si128( px1, smask );+ __m128i sd2 = _mm_and_si128( px2, smask );+ __m128i sd3 = _mm_and_si128( px3, smask );++ __m128i sc = _mm_shuffle_epi32(sd0, _MM_SHUFFLE(0, 0, 0, 0));++ __m128i sc0 = _mm_cmpeq_epi8(sd0, sc);+ __m128i sc1 = _mm_cmpeq_epi8(sd1, sc);+ __m128i sc2 = _mm_cmpeq_epi8(sd2, sc);+ __m128i sc3 = _mm_cmpeq_epi8(sd3, sc);++ __m128i sm0 = _mm_and_si128(sc0, sc1);+ __m128i sm1 = _mm_and_si128(sc2, sc3);+ __m128i sm = _mm_and_si128(sm0, sm1);++ if( _mm_testc_si128(sm, _mm_set1_epi32(-1)) )+ {+ return uint64_t( to565( src[0], src[1], src[2] ) ) << 16;+ }++ __m128i amask = _mm_set1_epi32( 0xFFFFFF );+ px0 = _mm_and_si128( px0, amask );+ px1 = _mm_and_si128( px1, amask );+ px2 = _mm_and_si128( px2, amask );+ px3 = _mm_and_si128( px3, amask );++ __m128i min0 = _mm_min_epu8( px0, px1 );+ __m128i min1 = _mm_min_epu8( px2, px3 );+ __m128i min2 = _mm_min_epu8( min0, min1 );++ __m128i max0 = _mm_max_epu8( px0, px1 );+ __m128i max1 = _mm_max_epu8( px2, px3 );+ __m128i max2 = _mm_max_epu8( max0, max1 );++ __m128i min3 = _mm_shuffle_epi32( min2, _MM_SHUFFLE( 2, 3, 0, 1 ) );+ __m128i max3 = _mm_shuffle_epi32( max2, _MM_SHUFFLE( 2, 3, 0, 1 ) );+ __m128i min4 = _mm_min_epu8( min2, min3 );+ __m128i max4 = _mm_max_epu8( max2, max3 );++ __m128i min5 = _mm_shuffle_epi32( min4, _MM_SHUFFLE( 0, 0, 2, 2 ) );+ __m128i max5 = _mm_shuffle_epi32( max4, _MM_SHUFFLE( 0, 0, 2, 2 ) );+ __m128i rmin = _mm_min_epu8( min4, min5 );+ __m128i rmax = _mm_max_epu8( max4, max5 );++ __m128i range1 = _mm_subs_epu8( rmax, rmin );+ __m128i range2 = _mm_sad_epu8( rmax, rmin );++ uint32_t vrange = _mm_cvtsi128_si32( range2 ) >> 1;+ __m128i range = _mm_set1_epi16( DivTable[vrange] );++ __m128i inset1 = _mm_srli_epi16( range1, 4 );+ __m128i inset = _mm_and_si128( inset1, _mm_set1_epi8( 0xF ) );+ __m128i min = _mm_adds_epu8( rmin, inset );+ __m128i max = _mm_subs_epu8( rmax, inset );++ __m128i c0 = _mm_subs_epu8( px0, rmin );+ __m128i c1 = _mm_subs_epu8( px1, rmin );+ __m128i c2 = _mm_subs_epu8( px2, rmin );+ __m128i c3 = _mm_subs_epu8( px3, rmin );++ __m128i is0 = _mm_maddubs_epi16( c0, _mm_set1_epi8( 1 ) );+ __m128i is1 = _mm_maddubs_epi16( c1, _mm_set1_epi8( 1 ) );+ __m128i is2 = _mm_maddubs_epi16( c2, _mm_set1_epi8( 1 ) );+ __m128i is3 = _mm_maddubs_epi16( c3, _mm_set1_epi8( 1 ) );++ __m128i s0 = _mm_hadd_epi16( is0, is1 );+ __m128i s1 = _mm_hadd_epi16( is2, is3 );++ __m128i m0 = _mm_mulhi_epu16( s0, range );+ __m128i m1 = _mm_mulhi_epu16( s1, range );++ __m128i p0 = _mm_packus_epi16( m0, m1 );++ __m128i p1 = _mm_or_si128( _mm_srai_epi32( p0, 6 ), _mm_srai_epi32( p0, 12 ) );+ __m128i p2 = _mm_or_si128( _mm_srai_epi32( p0, 18 ), p0 );+ __m128i p3 = _mm_or_si128( p1, p2 );+ __m128i p =_mm_shuffle_epi8( p3, _mm_set1_epi32( 0x0C080400 ) );++ uint32_t vmin = _mm_cvtsi128_si32( min );+ uint32_t vmax = _mm_cvtsi128_si32( max );+ uint32_t vp = _mm_cvtsi128_si32( p );++ return uint64_t( ( uint64_t( to565( vmin ) ) << 16 ) | to565( vmax ) | ( uint64_t( vp ) << 32 ) );+#elif defined __ARM_NEON+# ifdef __aarch64__+ uint8x16x4_t px = vld4q_u8( src );++ uint8x16_t lr = px.val[0];+ uint8x16_t lg = px.val[1];+ uint8x16_t lb = px.val[2];++ uint8_t rmaxr = vmaxvq_u8( lr );+ uint8_t rmaxg = vmaxvq_u8( lg );+ uint8_t rmaxb = vmaxvq_u8( lb );++ uint8_t rminr = vminvq_u8( lr );+ uint8_t rming = vminvq_u8( lg );+ uint8_t rminb = vminvq_u8( lb );++ int rr = rmaxr - rminr;+ int rg = rmaxg - rming;+ int rb = rmaxb - rminb;++ int vrange1 = rr + rg + rb;+ uint16_t vrange2 = DivTableNEON[vrange1];++ uint8_t insetr = rr >> 4;+ uint8_t insetg = rg >> 4;+ uint8_t insetb = rb >> 4;++ uint8_t minr = rminr + insetr;+ uint8_t ming = rming + insetg;+ uint8_t minb = rminb + insetb;++ uint8_t maxr = rmaxr - insetr;+ uint8_t maxg = rmaxg - insetg;+ uint8_t maxb = rmaxb - insetb;++ uint8x16_t cr = vsubq_u8( lr, vdupq_n_u8( rminr ) );+ uint8x16_t cg = vsubq_u8( lg, vdupq_n_u8( rming ) );+ uint8x16_t cb = vsubq_u8( lb, vdupq_n_u8( rminb ) );++ uint16x8_t is0l = vaddl_u8( vget_low_u8( cr ), vget_low_u8( cg ) );+ uint16x8_t is0h = vaddl_u8( vget_high_u8( cr ), vget_high_u8( cg ) );+ uint16x8_t is1l = vaddw_u8( is0l, vget_low_u8( cb ) );+ uint16x8_t is1h = vaddw_u8( is0h, vget_high_u8( cb ) );++ int16x8_t range = vdupq_n_s16( vrange2 );+ uint16x8_t m0 = vreinterpretq_u16_s16( vqdmulhq_s16( vreinterpretq_s16_u16( is1l ), range ) );+ uint16x8_t m1 = vreinterpretq_u16_s16( vqdmulhq_s16( vreinterpretq_s16_u16( is1h ), range ) );++ uint8x8_t p00 = vmovn_u16( m0 );+ uint8x8_t p01 = vmovn_u16( m1 );+ uint8x16_t p0 = vcombine_u8( p00, p01 );++ uint32x4_t p1 = vaddq_u32( vshrq_n_u32( vreinterpretq_u32_u8( p0 ), 6 ), vshrq_n_u32( vreinterpretq_u32_u8( p0 ), 12 ) );+ uint32x4_t p2 = vaddq_u32( vshrq_n_u32( vreinterpretq_u32_u8( p0 ), 18 ), vreinterpretq_u32_u8( p0 ) );+ uint32x4_t p3 = vaddq_u32( p1, p2 );++ uint16x4x2_t p4 = vuzp_u16( vget_low_u16( vreinterpretq_u16_u32( p3 ) ), vget_high_u16( vreinterpretq_u16_u32( p3 ) ) );+ uint8x8x2_t p = vuzp_u8( vreinterpret_u8_u16( p4.val[0] ), vreinterpret_u8_u16( p4.val[0] ) );++ uint32_t vp;+ vst1_lane_u32( &vp, vreinterpret_u32_u8( p.val[0] ), 0 );++ return uint64_t( ( uint64_t( to565( minr, ming, minb ) ) << 16 ) | to565( maxr, maxg, maxb ) | ( uint64_t( vp ) << 32 ) );+# else+ uint32x4_t px0 = vld1q_u32( (uint32_t*)src );+ uint32x4_t px1 = vld1q_u32( (uint32_t*)src + 4 );+ uint32x4_t px2 = vld1q_u32( (uint32_t*)src + 8 );+ uint32x4_t px3 = vld1q_u32( (uint32_t*)src + 12 );++ uint32x4_t smask = vdupq_n_u32( 0xF8FCF8 );+ uint32x4_t sd0 = vandq_u32( smask, px0 );+ uint32x4_t sd1 = vandq_u32( smask, px1 );+ uint32x4_t sd2 = vandq_u32( smask, px2 );+ uint32x4_t sd3 = vandq_u32( smask, px3 );++ uint32x4_t sc = vdupq_n_u32( sd0[0] );++ uint32x4_t sc0 = vceqq_u32( sd0, sc );+ uint32x4_t sc1 = vceqq_u32( sd1, sc );+ uint32x4_t sc2 = vceqq_u32( sd2, sc );+ uint32x4_t sc3 = vceqq_u32( sd3, sc );++ uint32x4_t sm0 = vandq_u32( sc0, sc1 );+ uint32x4_t sm1 = vandq_u32( sc2, sc3 );+ int64x2_t sm = vreinterpretq_s64_u32( vandq_u32( sm0, sm1 ) );++ if( sm[0] == -1 && sm[1] == -1 )+ {+ return uint64_t( to565( src[0], src[1], src[2] ) ) << 16;+ }++ uint32x4_t mask = vdupq_n_u32( 0xFFFFFF );+ uint8x16_t l0 = vreinterpretq_u8_u32( vandq_u32( mask, px0 ) );+ uint8x16_t l1 = vreinterpretq_u8_u32( vandq_u32( mask, px1 ) );+ uint8x16_t l2 = vreinterpretq_u8_u32( vandq_u32( mask, px2 ) );+ uint8x16_t l3 = vreinterpretq_u8_u32( vandq_u32( mask, px3 ) );++ uint8x16_t min0 = vminq_u8( l0, l1 );+ uint8x16_t min1 = vminq_u8( l2, l3 );+ uint8x16_t min2 = vminq_u8( min0, min1 );++ uint8x16_t max0 = vmaxq_u8( l0, l1 );+ uint8x16_t max1 = vmaxq_u8( l2, l3 );+ uint8x16_t max2 = vmaxq_u8( max0, max1 );++ uint8x16_t min3 = vreinterpretq_u8_u32( vrev64q_u32( vreinterpretq_u32_u8( min2 ) ) );+ uint8x16_t max3 = vreinterpretq_u8_u32( vrev64q_u32( vreinterpretq_u32_u8( max2 ) ) );++ uint8x16_t min4 = vminq_u8( min2, min3 );+ uint8x16_t max4 = vmaxq_u8( max2, max3 );++ uint8x16_t min5 = vcombine_u8( vget_high_u8( min4 ), vget_low_u8( min4 ) );+ uint8x16_t max5 = vcombine_u8( vget_high_u8( max4 ), vget_low_u8( max4 ) );++ uint8x16_t rmin = vminq_u8( min4, min5 );+ uint8x16_t rmax = vmaxq_u8( max4, max5 );++ uint8x16_t range1 = vsubq_u8( rmax, rmin );+ uint8x8_t range2 = vget_low_u8( range1 );+ uint8x8x2_t range3 = vzip_u8( range2, vdup_n_u8( 0 ) );+ uint16x4_t range4 = vreinterpret_u16_u8( range3.val[0] );++ uint16_t vrange1;+ uint16x4_t range5 = vpadd_u16( range4, range4 );+ uint16x4_t range6 = vpadd_u16( range5, range5 );+ vst1_lane_u16( &vrange1, range6, 0 );++ uint32_t vrange2 = ( 2 << 16 ) / uint32_t( vrange1 + 1 );+ uint16x8_t range = vdupq_n_u16( vrange2 );++ uint8x16_t inset = vshrq_n_u8( range1, 4 );+ uint8x16_t min = vaddq_u8( rmin, inset );+ uint8x16_t max = vsubq_u8( rmax, inset );++ uint8x16_t c0 = vsubq_u8( l0, rmin );+ uint8x16_t c1 = vsubq_u8( l1, rmin );+ uint8x16_t c2 = vsubq_u8( l2, rmin );+ uint8x16_t c3 = vsubq_u8( l3, rmin );++ uint16x8_t is0 = vpaddlq_u8( c0 );+ uint16x8_t is1 = vpaddlq_u8( c1 );+ uint16x8_t is2 = vpaddlq_u8( c2 );+ uint16x8_t is3 = vpaddlq_u8( c3 );++ uint16x4_t is4 = vpadd_u16( vget_low_u16( is0 ), vget_high_u16( is0 ) );+ uint16x4_t is5 = vpadd_u16( vget_low_u16( is1 ), vget_high_u16( is1 ) );+ uint16x4_t is6 = vpadd_u16( vget_low_u16( is2 ), vget_high_u16( is2 ) );+ uint16x4_t is7 = vpadd_u16( vget_low_u16( is3 ), vget_high_u16( is3 ) );++ uint16x8_t s0 = vcombine_u16( is4, is5 );+ uint16x8_t s1 = vcombine_u16( is6, is7 );++ uint16x8_t m0 = vreinterpretq_u16_s16( vqdmulhq_s16( vreinterpretq_s16_u16( s0 ), vreinterpretq_s16_u16( range ) ) );+ uint16x8_t m1 = vreinterpretq_u16_s16( vqdmulhq_s16( vreinterpretq_s16_u16( s1 ), vreinterpretq_s16_u16( range ) ) );++ uint8x8_t p00 = vmovn_u16( m0 );+ uint8x8_t p01 = vmovn_u16( m1 );+ uint8x16_t p0 = vcombine_u8( p00, p01 );++ uint32x4_t p1 = vaddq_u32( vshrq_n_u32( vreinterpretq_u32_u8( p0 ), 6 ), vshrq_n_u32( vreinterpretq_u32_u8( p0 ), 12 ) );+ uint32x4_t p2 = vaddq_u32( vshrq_n_u32( vreinterpretq_u32_u8( p0 ), 18 ), vreinterpretq_u32_u8( p0 ) );+ uint32x4_t p3 = vaddq_u32( p1, p2 );++ uint16x4x2_t p4 = vuzp_u16( vget_low_u16( vreinterpretq_u16_u32( p3 ) ), vget_high_u16( vreinterpretq_u16_u32( p3 ) ) );+ uint8x8x2_t p = vuzp_u8( vreinterpret_u8_u16( p4.val[0] ), vreinterpret_u8_u16( p4.val[0] ) );++ uint32_t vmin, vmax, vp;+ vst1q_lane_u32( &vmin, vreinterpretq_u32_u8( min ), 0 );+ vst1q_lane_u32( &vmax, vreinterpretq_u32_u8( max ), 0 );+ vst1_lane_u32( &vp, vreinterpret_u32_u8( p.val[0] ), 0 );++ return uint64_t( ( uint64_t( to565( vmin ) ) << 16 ) | to565( vmax ) | ( uint64_t( vp ) << 32 ) );+# endif+#else+ uint32_t ref;+ memcpy( &ref, src, 4 );+ uint32_t refMask = ref & 0xF8FCF8;+ auto stmp = src + 4;+ for( int i=1; i<16; i++ )+ {+ uint32_t px;+ memcpy( &px, stmp, 4 );+ if( ( px & 0xF8FCF8 ) != refMask ) break;+ stmp += 4;+ }+ if( stmp == src + 64 )+ {+ return uint64_t( to565( ref ) ) << 16;+ }++ uint8_t min[3] = { src[0], src[1], src[2] };+ uint8_t max[3] = { src[0], src[1], src[2] };+ auto tmp = src + 4;+ for( int i=1; i<16; i++ )+ {+ for( int j=0; j<3; j++ )+ {+ if( tmp[j] < min[j] ) min[j] = tmp[j];+ else if( tmp[j] > max[j] ) max[j] = tmp[j];+ }+ tmp += 4;+ }++ const uint32_t range = DivTable[max[0] - min[0] + max[1] - min[1] + max[2] - min[2]];+ const uint32_t rmin = min[0] + min[1] + min[2];+ for( int i=0; i<3; i++ )+ {+ const uint8_t inset = ( max[i] - min[i] ) >> 4;+ min[i] += inset;+ max[i] -= inset;+ }++ uint32_t data = 0;+ for( int i=0; i<16; i++ )+ {+ const uint32_t c = src[0] + src[1] + src[2] - rmin;+ const uint8_t idx = ( c * range ) >> 16;+ data |= idx << (i*2);+ src += 4;+ }++ return uint64_t( ( uint64_t( to565( min[0], min[1], min[2] ) ) << 16 ) | to565( max[0], max[1], max[2] ) | ( uint64_t( data ) << 32 ) );+#endif+}++#ifdef __AVX2__+static tracy_force_inline void ProcessRGB_AVX( const uint8_t* src, char*& dst )+{+ __m256i px0 = _mm256_loadu_si256(((__m256i*)src) + 0);+ __m256i px1 = _mm256_loadu_si256(((__m256i*)src) + 1);+ __m256i px2 = _mm256_loadu_si256(((__m256i*)src) + 2);+ __m256i px3 = _mm256_loadu_si256(((__m256i*)src) + 3);++ __m256i smask = _mm256_set1_epi32( 0xF8FCF8 );+ __m256i sd0 = _mm256_and_si256( px0, smask );+ __m256i sd1 = _mm256_and_si256( px1, smask );+ __m256i sd2 = _mm256_and_si256( px2, smask );+ __m256i sd3 = _mm256_and_si256( px3, smask );++ __m256i sc = _mm256_shuffle_epi32(sd0, _MM_SHUFFLE(0, 0, 0, 0));++ __m256i sc0 = _mm256_cmpeq_epi8( sd0, sc );+ __m256i sc1 = _mm256_cmpeq_epi8( sd1, sc );+ __m256i sc2 = _mm256_cmpeq_epi8( sd2, sc );+ __m256i sc3 = _mm256_cmpeq_epi8( sd3, sc );++ __m256i sm0 = _mm256_and_si256( sc0, sc1 );+ __m256i sm1 = _mm256_and_si256( sc2, sc3 );+ __m256i sm = _mm256_and_si256( sm0, sm1 );++ const int64_t solid0 = 1 - _mm_testc_si128( _mm256_castsi256_si128( sm ), _mm_set1_epi32( -1 ) );+ const int64_t solid1 = 1 - _mm_testc_si128( _mm256_extracti128_si256( sm, 1 ), _mm_set1_epi32( -1 ) );++ if( solid0 + solid1 == 0 )+ {+ const auto c0 = uint64_t( to565( src[0], src[1], src[2] ) ) << 16;+ const auto c1 = uint64_t( to565( src[16], src[17], src[18] ) ) << 16;+ memcpy( dst, &c0, 8 );+ memcpy( dst+8, &c1, 8 );+ dst += 16;+ return;+ }++ __m256i amask = _mm256_set1_epi32( 0xFFFFFF );+ px0 = _mm256_and_si256( px0, amask );+ px1 = _mm256_and_si256( px1, amask );+ px2 = _mm256_and_si256( px2, amask );+ px3 = _mm256_and_si256( px3, amask );++ __m256i min0 = _mm256_min_epu8( px0, px1 );+ __m256i min1 = _mm256_min_epu8( px2, px3 );+ __m256i min2 = _mm256_min_epu8( min0, min1 );++ __m256i max0 = _mm256_max_epu8( px0, px1 );+ __m256i max1 = _mm256_max_epu8( px2, px3 );+ __m256i max2 = _mm256_max_epu8( max0, max1 );++ __m256i min3 = _mm256_shuffle_epi32( min2, _MM_SHUFFLE( 2, 3, 0, 1 ) );+ __m256i max3 = _mm256_shuffle_epi32( max2, _MM_SHUFFLE( 2, 3, 0, 1 ) );+ __m256i min4 = _mm256_min_epu8( min2, min3 );+ __m256i max4 = _mm256_max_epu8( max2, max3 );++ __m256i min5 = _mm256_shuffle_epi32( min4, _MM_SHUFFLE( 0, 0, 2, 2 ) );+ __m256i max5 = _mm256_shuffle_epi32( max4, _MM_SHUFFLE( 0, 0, 2, 2 ) );+ __m256i rmin = _mm256_min_epu8( min4, min5 );+ __m256i rmax = _mm256_max_epu8( max4, max5 );++ __m256i range1 = _mm256_subs_epu8( rmax, rmin );+ __m256i range2 = _mm256_sad_epu8( rmax, rmin );++ uint16_t vrange0 = DivTable[_mm256_cvtsi256_si32( range2 ) >> 1];+ uint16_t vrange1 = DivTable[_mm256_extract_epi16( range2, 8 ) >> 1];+ __m256i range00 = _mm256_set1_epi16( vrange0 );+ __m256i range = _mm256_inserti128_si256( range00, _mm_set1_epi16( vrange1 ), 1 );++ __m256i inset1 = _mm256_srli_epi16( range1, 4 );+ __m256i inset = _mm256_and_si256( inset1, _mm256_set1_epi8( 0xF ) );+ __m256i min = _mm256_adds_epu8( rmin, inset );+ __m256i max = _mm256_subs_epu8( rmax, inset );++ __m256i c0 = _mm256_subs_epu8( px0, rmin );+ __m256i c1 = _mm256_subs_epu8( px1, rmin );+ __m256i c2 = _mm256_subs_epu8( px2, rmin );+ __m256i c3 = _mm256_subs_epu8( px3, rmin );++ __m256i is0 = _mm256_maddubs_epi16( c0, _mm256_set1_epi8( 1 ) );+ __m256i is1 = _mm256_maddubs_epi16( c1, _mm256_set1_epi8( 1 ) );+ __m256i is2 = _mm256_maddubs_epi16( c2, _mm256_set1_epi8( 1 ) );+ __m256i is3 = _mm256_maddubs_epi16( c3, _mm256_set1_epi8( 1 ) );++ __m256i s0 = _mm256_hadd_epi16( is0, is1 );+ __m256i s1 = _mm256_hadd_epi16( is2, is3 );++ __m256i m0 = _mm256_mulhi_epu16( s0, range );+ __m256i m1 = _mm256_mulhi_epu16( s1, range );++ __m256i p0 = _mm256_packus_epi16( m0, m1 );++ __m256i p1 = _mm256_or_si256( _mm256_srai_epi32( p0, 6 ), _mm256_srai_epi32( p0, 12 ) );+ __m256i p2 = _mm256_or_si256( _mm256_srai_epi32( p0, 18 ), p0 );+ __m256i p3 = _mm256_or_si256( p1, p2 );+ __m256i p =_mm256_shuffle_epi8( p3, _mm256_set1_epi32( 0x0C080400 ) );++ __m256i mm0 = _mm256_unpacklo_epi8( _mm256_setzero_si256(), min );+ __m256i mm1 = _mm256_unpacklo_epi8( _mm256_setzero_si256(), max );+ __m256i mm2 = _mm256_unpacklo_epi64( mm1, mm0 );+ __m256i mmr = _mm256_slli_epi64( _mm256_srli_epi64( mm2, 11 ), 11 );+ __m256i mmg = _mm256_slli_epi64( _mm256_srli_epi64( mm2, 26 ), 5 );+ __m256i mmb = _mm256_srli_epi64( _mm256_slli_epi64( mm2, 16 ), 59 );+ __m256i mm3 = _mm256_or_si256( mmr, mmg );+ __m256i mm4 = _mm256_or_si256( mm3, mmb );+ __m256i mm5 = _mm256_shuffle_epi8( mm4, _mm256_set1_epi32( 0x09080100 ) );++ __m256i d0 = _mm256_unpacklo_epi32( mm5, p );+ __m256i d1 = _mm256_permute4x64_epi64( d0, _MM_SHUFFLE( 3, 2, 2, 0 ) );+ __m128i d2 = _mm256_castsi256_si128( d1 );++ __m128i mask = _mm_set_epi64x( 0xFFFF0000 | -solid1, 0xFFFF0000 | -solid0 );+ __m128i d3 = _mm_and_si128( d2, mask );+ _mm_storeu_si128( (__m128i*)dst, d3 );+ dst += 16;+}+#endif++void CompressImageDxt1( const char* src, char* dst, int w, int h )+{+ assert( (w % 4) == 0 && (h % 4) == 0 );++#ifdef __AVX2__+ if( w%8 == 0 )+ {+ uint32_t buf[8*4];+ int i = 0;++ auto blocks = w * h / 32;+ do+ {+ auto tmp = (char*)buf;+ memcpy( tmp, src, 8*4 );+ memcpy( tmp + 8*4, src + w * 4, 8*4 );+ memcpy( tmp + 16*4, src + w * 8, 8*4 );+ memcpy( tmp + 24*4, src + w * 12, 8*4 );+ src += 8*4;+ if( ++i == w/8 )+ {+ src += w * 3 * 4;+ i = 0;+ }++ ProcessRGB_AVX( (uint8_t*)buf, dst );+ }+ while( --blocks );+ }+ else+#endif+ {+ uint32_t buf[4*4];+ int i = 0;++ auto ptr = dst;+ auto blocks = w * h / 16;+ do+ {+ auto tmp = (char*)buf;+ memcpy( tmp, src, 4*4 );+ memcpy( tmp + 4*4, src + w * 4, 4*4 );+ memcpy( tmp + 8*4, src + w * 8, 4*4 );+ memcpy( tmp + 12*4, src + w * 12, 4*4 );+ src += 4*4;+ if( ++i == w/4 )+ {+ src += w * 3 * 4;+ i = 0;+ }++ const auto c = ProcessRGB( (uint8_t*)buf );+ memcpy( ptr, &c, sizeof( uint64_t ) );+ ptr += sizeof( uint64_t );+ }+ while( --blocks );+ }+}++}
+ cbits/tracy/public/client/TracyDxt1.hpp view
@@ -0,0 +1,11 @@+#ifndef __TRACYDXT1_HPP__+#define __TRACYDXT1_HPP__++namespace tracy+{++void CompressImageDxt1( const char* src, char* dst, int w, int h );++}++#endif
+ cbits/tracy/public/client/TracyFastVector.hpp view
@@ -0,0 +1,118 @@+#ifndef __TRACYFASTVECTOR_HPP__+#define __TRACYFASTVECTOR_HPP__++#include <assert.h>+#include <stddef.h>++#include "../common/TracyAlloc.hpp"+#include "../common/TracyForceInline.hpp"++namespace tracy+{++template<typename T>+class FastVector+{+public:+ using iterator = T*;+ using const_iterator = const T*;++ FastVector( size_t capacity )+ : m_ptr( (T*)tracy_malloc( sizeof( T ) * capacity ) )+ , m_write( m_ptr )+ , m_end( m_ptr + capacity )+ {+ assert( capacity != 0 );+ }++ FastVector( const FastVector& ) = delete;+ FastVector( FastVector&& ) = delete;++ ~FastVector()+ {+ tracy_free( m_ptr );+ }++ FastVector& operator=( const FastVector& ) = delete;+ FastVector& operator=( FastVector&& ) = delete;++ bool empty() const { return m_ptr == m_write; }+ size_t size() const { return m_write - m_ptr; }++ T* data() { return m_ptr; }+ const T* data() const { return m_ptr; };++ T* begin() { return m_ptr; }+ const T* begin() const { return m_ptr; }+ T* end() { return m_write; }+ const T* end() const { return m_write; }++ T& front() { assert( !empty() ); return m_ptr[0]; }+ const T& front() const { assert( !empty() ); return m_ptr[0]; }++ T& back() { assert( !empty() ); return m_write[-1]; }+ const T& back() const { assert( !empty() ); return m_write[-1]; }++ T& operator[]( size_t idx ) { return m_ptr[idx]; }+ const T& operator[]( size_t idx ) const { return m_ptr[idx]; }++ T* push_next()+ {+ if( m_write == m_end ) AllocMore();+ return m_write++;+ }++ T* prepare_next()+ {+ if( m_write == m_end ) AllocMore();+ return m_write;+ }++ void commit_next()+ {+ m_write++;+ }++ void clear()+ {+ m_write = m_ptr;+ }++ void swap( FastVector& vec )+ {+ const auto ptr1 = m_ptr;+ const auto ptr2 = vec.m_ptr;+ const auto write1 = m_write;+ const auto write2 = vec.m_write;+ const auto end1 = m_end;+ const auto end2 = vec.m_end;++ m_ptr = ptr2;+ vec.m_ptr = ptr1;+ m_write = write2;+ vec.m_write = write1;+ m_end = end2;+ vec.m_end = end1;+ }++private:+ tracy_no_inline void AllocMore()+ {+ const auto cap = size_t( m_end - m_ptr ) * 2;+ const auto size = size_t( m_write - m_ptr );+ T* ptr = (T*)tracy_malloc( sizeof( T ) * cap );+ memcpy( ptr, m_ptr, size * sizeof( T ) );+ tracy_free_fast( m_ptr );+ m_ptr = ptr;+ m_write = m_ptr + size;+ m_end = m_ptr + cap;+ }++ T* m_ptr;+ T* m_write;+ T* m_end;+};++}++#endif
+ cbits/tracy/public/client/TracyKCore.cpp view
@@ -0,0 +1,121 @@+#ifdef __linux__++#include <algorithm>+#include <assert.h>+#include <fcntl.h>+#include <limits.h>+#include <unistd.h>++#include "TracyDebug.hpp"+#include "TracyKCore.hpp"+#include "../common/TracyAlloc.hpp"++#if !defined(__GLIBC__) && !defined(__WORDSIZE)+// include __WORDSIZE headers for musl+# include <bits/reg.h>+#endif++namespace tracy+{++using elf_half = uint16_t;+using elf_word = uint32_t;+using elf_sword = int32_t;++#if __WORDSIZE == 32+ using elf_addr = uint32_t;+ using elf_off = uint32_t;+ using elf_xword = uint32_t;+#else+ using elf_addr = uint64_t;+ using elf_off = uint64_t;+ using elf_xword = uint64_t;+#endif++struct elf_ehdr+{+ unsigned char e_ident[16];+ elf_half e_type;+ elf_half e_machine;+ elf_word e_version;+ elf_addr e_entry;+ elf_off e_phoff;+ elf_off e_shoff;+ elf_word e_flags;+ elf_half e_ehsize;+ elf_half e_phentsize;+ elf_half e_phnum;+ elf_half e_shentsize;+ elf_half e_shnum;+ elf_half e_shstrndx;+};++struct elf_phdr+{+ elf_word p_type;+ elf_word p_flags;+ elf_off p_offset;+ elf_addr p_vaddr;+ elf_addr p_paddr;+ elf_xword p_filesz;+ elf_xword p_memsz;+ uint64_t p_align; // include 32-bit-only flags field for 32-bit compatibility+};++KCore::KCore()+ : m_offsets( 16 )+{+ m_fd = open( "/proc/kcore", O_RDONLY );+ if( m_fd == -1 ) return;++ elf_ehdr ehdr;+ if( read( m_fd, &ehdr, sizeof( ehdr ) ) != sizeof( ehdr ) ) goto err;++ assert( ehdr.e_phentsize == sizeof( elf_phdr ) );++ for( elf_half i=0; i<ehdr.e_phnum; i++ )+ {+ elf_phdr phdr;+ if( lseek( m_fd, ehdr.e_phoff + i * ehdr.e_phentsize, SEEK_SET ) == -1 ) goto err;+ if( read( m_fd, &phdr, sizeof( phdr ) ) != sizeof( phdr ) ) goto err;+ if( phdr.p_type != 1 ) continue;++ auto ptr = m_offsets.push_next();+ ptr->start = phdr.p_vaddr;+ ptr->size = phdr.p_memsz;+ ptr->offset = phdr.p_offset;+ }++ std::sort( m_offsets.begin(), m_offsets.end(), []( const Offset& lhs, const Offset& rhs ) { return lhs.start < rhs.start; } );+ TracyDebug( "KCore: %zu segments found\n", m_offsets.size() );+ return;++err:+ close( m_fd );+ m_fd = -1;+}++KCore::~KCore()+{+ if( m_fd != -1 ) close( m_fd );+}++void* KCore::Retrieve( uint64_t addr, uint64_t size ) const+{+ if( m_fd == -1 ) return nullptr;+ auto it = std::lower_bound( m_offsets.begin(), m_offsets.end(), addr, []( const Offset& lhs, uint64_t rhs ) { return lhs.start + lhs.size < rhs; } );+ if( it == m_offsets.end() ) return nullptr;+ if( addr + size > it->start + it->size ) return nullptr;+ if( lseek( m_fd, it->offset + addr - it->start, SEEK_SET ) == -1 ) return nullptr;+ auto ptr = tracy_malloc( size );+ if( read( m_fd, ptr, size ) != ssize_t( size ) )+ {+ tracy_free( ptr );+ return nullptr;+ }+ return ptr;+}++}++#endif
+ cbits/tracy/public/client/TracyKCore.hpp view
@@ -0,0 +1,37 @@+#ifndef __TRACYKCORE_HPP__+#define __TRACYKCORE_HPP__++#ifdef __linux__++#include <stdint.h>++#include "TracyFastVector.hpp"++namespace tracy+{++class KCore+{+ struct Offset+ {+ uint64_t start;+ uint64_t size;+ uint64_t offset;+ };++public:+ KCore();+ ~KCore();++ void* Retrieve( uint64_t addr, uint64_t size ) const;++private:+ int m_fd;+ FastVector<Offset> m_offsets;+};++}++#endif++#endif
+ cbits/tracy/public/client/TracyLock.hpp view
@@ -0,0 +1,546 @@+#ifndef __TRACYLOCK_HPP__+#define __TRACYLOCK_HPP__++#include <atomic>+#include <limits>++#include "../common/TracySystem.hpp"+#include "../common/TracyAlign.hpp"+#include "TracyProfiler.hpp"++namespace tracy+{++class LockableCtx+{+public:+ tracy_force_inline LockableCtx( const SourceLocationData* srcloc )+ : m_id( GetLockCounter().fetch_add( 1, std::memory_order_relaxed ) )+#ifdef TRACY_ON_DEMAND+ , m_lockCount( 0 )+ , m_active( false )+#endif+ {+ assert( m_id != (std::numeric_limits<uint32_t>::max)() );++ auto item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::LockAnnounce );+ MemWrite( &item->lockAnnounce.id, m_id );+ MemWrite( &item->lockAnnounce.time, Profiler::GetTime() );+ MemWrite( &item->lockAnnounce.lckloc, (uint64_t)srcloc );+ MemWrite( &item->lockAnnounce.type, LockType::Lockable );+#ifdef TRACY_ON_DEMAND+ GetProfiler().DeferItem( *item );+#endif+ Profiler::QueueSerialFinish();+ }++ LockableCtx( const LockableCtx& ) = delete;+ LockableCtx& operator=( const LockableCtx& ) = delete;++ tracy_force_inline ~LockableCtx()+ {+ auto item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::LockTerminate );+ MemWrite( &item->lockTerminate.id, m_id );+ MemWrite( &item->lockTerminate.time, Profiler::GetTime() );+#ifdef TRACY_ON_DEMAND+ GetProfiler().DeferItem( *item );+#endif+ Profiler::QueueSerialFinish();+ }++ tracy_force_inline bool BeforeLock()+ {+#ifdef TRACY_ON_DEMAND+ bool queue = false;+ const auto locks = m_lockCount.fetch_add( 1, std::memory_order_relaxed );+ const auto active = m_active.load( std::memory_order_relaxed );+ if( locks == 0 || active )+ {+ const bool connected = GetProfiler().IsConnected();+ if( active != connected ) m_active.store( connected, std::memory_order_relaxed );+ if( connected ) queue = true;+ }+ if( !queue ) return false;+#endif++ auto item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::LockWait );+ MemWrite( &item->lockWait.thread, GetThreadHandle() );+ MemWrite( &item->lockWait.id, m_id );+ MemWrite( &item->lockWait.time, Profiler::GetTime() );+ Profiler::QueueSerialFinish();+ return true;+ }++ tracy_force_inline void AfterLock()+ {+ auto item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::LockObtain );+ MemWrite( &item->lockObtain.thread, GetThreadHandle() );+ MemWrite( &item->lockObtain.id, m_id );+ MemWrite( &item->lockObtain.time, Profiler::GetTime() );+ Profiler::QueueSerialFinish();+ }++ tracy_force_inline void AfterUnlock()+ {+#ifdef TRACY_ON_DEMAND+ m_lockCount.fetch_sub( 1, std::memory_order_relaxed );+ if( !m_active.load( std::memory_order_relaxed ) ) return;+ if( !GetProfiler().IsConnected() )+ {+ m_active.store( false, std::memory_order_relaxed );+ return;+ }+#endif++ auto item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::LockRelease );+ MemWrite( &item->lockRelease.id, m_id );+ MemWrite( &item->lockRelease.time, Profiler::GetTime() );+ Profiler::QueueSerialFinish();+ }++ tracy_force_inline void AfterTryLock( bool acquired )+ {+#ifdef TRACY_ON_DEMAND+ if( !acquired ) return;++ bool queue = false;+ const auto locks = m_lockCount.fetch_add( 1, std::memory_order_relaxed );+ const auto active = m_active.load( std::memory_order_relaxed );+ if( locks == 0 || active )+ {+ const bool connected = GetProfiler().IsConnected();+ if( active != connected ) m_active.store( connected, std::memory_order_relaxed );+ if( connected ) queue = true;+ }+ if( !queue ) return;+#endif++ if( acquired )+ {+ auto item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::LockObtain );+ MemWrite( &item->lockObtain.thread, GetThreadHandle() );+ MemWrite( &item->lockObtain.id, m_id );+ MemWrite( &item->lockObtain.time, Profiler::GetTime() );+ Profiler::QueueSerialFinish();+ }+ }++ tracy_force_inline void Mark( const SourceLocationData* srcloc )+ {+#ifdef TRACY_ON_DEMAND+ const auto active = m_active.load( std::memory_order_relaxed );+ if( !active ) return;+ const auto connected = GetProfiler().IsConnected();+ if( !connected )+ {+ if( active ) m_active.store( false, std::memory_order_relaxed );+ return;+ }+#endif++ auto item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::LockMark );+ MemWrite( &item->lockMark.thread, GetThreadHandle() );+ MemWrite( &item->lockMark.id, m_id );+ MemWrite( &item->lockMark.srcloc, (uint64_t)srcloc );+ Profiler::QueueSerialFinish();+ }++ tracy_force_inline void CustomName( const char* name, size_t size )+ {+ assert( size < (std::numeric_limits<uint16_t>::max)() );+ auto ptr = (char*)tracy_malloc( size );+ memcpy( ptr, name, size );+ auto item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::LockName );+ MemWrite( &item->lockNameFat.id, m_id );+ MemWrite( &item->lockNameFat.name, (uint64_t)ptr );+ MemWrite( &item->lockNameFat.size, (uint16_t)size );+#ifdef TRACY_ON_DEMAND+ GetProfiler().DeferItem( *item );+#endif+ Profiler::QueueSerialFinish();+ }++private:+ uint32_t m_id;++#ifdef TRACY_ON_DEMAND+ std::atomic<uint32_t> m_lockCount;+ std::atomic<bool> m_active;+#endif+};++template<class T>+class Lockable+{+public:+ tracy_force_inline Lockable( const SourceLocationData* srcloc )+ : m_ctx( srcloc )+ {+ }++ Lockable( const Lockable& ) = delete;+ Lockable& operator=( const Lockable& ) = delete;++ tracy_force_inline void lock()+ {+ const auto runAfter = m_ctx.BeforeLock();+ m_lockable.lock();+ if( runAfter ) m_ctx.AfterLock();+ }++ tracy_force_inline void unlock()+ {+ m_lockable.unlock();+ m_ctx.AfterUnlock();+ }++ tracy_force_inline bool try_lock()+ {+ const auto acquired = m_lockable.try_lock();+ m_ctx.AfterTryLock( acquired );+ return acquired;+ }++ tracy_force_inline void Mark( const SourceLocationData* srcloc )+ {+ m_ctx.Mark( srcloc );+ }++ tracy_force_inline void CustomName( const char* name, size_t size )+ {+ m_ctx.CustomName( name, size );+ }++private:+ T m_lockable;+ LockableCtx m_ctx;+};+++class SharedLockableCtx+{+public:+ tracy_force_inline SharedLockableCtx( const SourceLocationData* srcloc )+ : m_id( GetLockCounter().fetch_add( 1, std::memory_order_relaxed ) )+#ifdef TRACY_ON_DEMAND+ , m_lockCount( 0 )+ , m_active( false )+#endif+ {+ assert( m_id != (std::numeric_limits<uint32_t>::max)() );++ auto item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::LockAnnounce );+ MemWrite( &item->lockAnnounce.id, m_id );+ MemWrite( &item->lockAnnounce.time, Profiler::GetTime() );+ MemWrite( &item->lockAnnounce.lckloc, (uint64_t)srcloc );+ MemWrite( &item->lockAnnounce.type, LockType::SharedLockable );+#ifdef TRACY_ON_DEMAND+ GetProfiler().DeferItem( *item );+#endif+ Profiler::QueueSerialFinish();+ }++ SharedLockableCtx( const SharedLockableCtx& ) = delete;+ SharedLockableCtx& operator=( const SharedLockableCtx& ) = delete;++ tracy_force_inline ~SharedLockableCtx()+ {+ auto item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::LockTerminate );+ MemWrite( &item->lockTerminate.id, m_id );+ MemWrite( &item->lockTerminate.time, Profiler::GetTime() );+#ifdef TRACY_ON_DEMAND+ GetProfiler().DeferItem( *item );+#endif+ Profiler::QueueSerialFinish();+ }++ tracy_force_inline bool BeforeLock()+ {+#ifdef TRACY_ON_DEMAND+ bool queue = false;+ const auto locks = m_lockCount.fetch_add( 1, std::memory_order_relaxed );+ const auto active = m_active.load( std::memory_order_relaxed );+ if( locks == 0 || active )+ {+ const bool connected = GetProfiler().IsConnected();+ if( active != connected ) m_active.store( connected, std::memory_order_relaxed );+ if( connected ) queue = true;+ }+ if( !queue ) return false;+#endif++ auto item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::LockWait );+ MemWrite( &item->lockWait.thread, GetThreadHandle() );+ MemWrite( &item->lockWait.id, m_id );+ MemWrite( &item->lockWait.time, Profiler::GetTime() );+ Profiler::QueueSerialFinish();+ return true;+ }++ tracy_force_inline void AfterLock()+ {+ auto item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::LockObtain );+ MemWrite( &item->lockObtain.thread, GetThreadHandle() );+ MemWrite( &item->lockObtain.id, m_id );+ MemWrite( &item->lockObtain.time, Profiler::GetTime() );+ Profiler::QueueSerialFinish();+ }++ tracy_force_inline void AfterUnlock()+ {+#ifdef TRACY_ON_DEMAND+ m_lockCount.fetch_sub( 1, std::memory_order_relaxed );+ if( !m_active.load( std::memory_order_relaxed ) ) return;+ if( !GetProfiler().IsConnected() )+ {+ m_active.store( false, std::memory_order_relaxed );+ return;+ }+#endif++ auto item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::LockRelease );+ MemWrite( &item->lockRelease.id, m_id );+ MemWrite( &item->lockRelease.time, Profiler::GetTime() );+ Profiler::QueueSerialFinish();+ }++ tracy_force_inline void AfterTryLock( bool acquired )+ {+#ifdef TRACY_ON_DEMAND+ if( !acquired ) return;++ bool queue = false;+ const auto locks = m_lockCount.fetch_add( 1, std::memory_order_relaxed );+ const auto active = m_active.load( std::memory_order_relaxed );+ if( locks == 0 || active )+ {+ const bool connected = GetProfiler().IsConnected();+ if( active != connected ) m_active.store( connected, std::memory_order_relaxed );+ if( connected ) queue = true;+ }+ if( !queue ) return;+#endif++ if( acquired )+ {+ auto item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::LockObtain );+ MemWrite( &item->lockObtain.thread, GetThreadHandle() );+ MemWrite( &item->lockObtain.id, m_id );+ MemWrite( &item->lockObtain.time, Profiler::GetTime() );+ Profiler::QueueSerialFinish();+ }+ }++ tracy_force_inline bool BeforeLockShared()+ {+#ifdef TRACY_ON_DEMAND+ bool queue = false;+ const auto locks = m_lockCount.fetch_add( 1, std::memory_order_relaxed );+ const auto active = m_active.load( std::memory_order_relaxed );+ if( locks == 0 || active )+ {+ const bool connected = GetProfiler().IsConnected();+ if( active != connected ) m_active.store( connected, std::memory_order_relaxed );+ if( connected ) queue = true;+ }+ if( !queue ) return false;+#endif++ auto item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::LockSharedWait );+ MemWrite( &item->lockWait.thread, GetThreadHandle() );+ MemWrite( &item->lockWait.id, m_id );+ MemWrite( &item->lockWait.time, Profiler::GetTime() );+ Profiler::QueueSerialFinish();+ return true;+ }++ tracy_force_inline void AfterLockShared()+ {+ auto item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::LockSharedObtain );+ MemWrite( &item->lockObtain.thread, GetThreadHandle() );+ MemWrite( &item->lockObtain.id, m_id );+ MemWrite( &item->lockObtain.time, Profiler::GetTime() );+ Profiler::QueueSerialFinish();+ }++ tracy_force_inline void AfterUnlockShared()+ {+#ifdef TRACY_ON_DEMAND+ m_lockCount.fetch_sub( 1, std::memory_order_relaxed );+ if( !m_active.load( std::memory_order_relaxed ) ) return;+ if( !GetProfiler().IsConnected() )+ {+ m_active.store( false, std::memory_order_relaxed );+ return;+ }+#endif++ auto item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::LockSharedRelease );+ MemWrite( &item->lockReleaseShared.thread, GetThreadHandle() );+ MemWrite( &item->lockReleaseShared.id, m_id );+ MemWrite( &item->lockReleaseShared.time, Profiler::GetTime() );+ Profiler::QueueSerialFinish();+ }++ tracy_force_inline void AfterTryLockShared( bool acquired )+ {+#ifdef TRACY_ON_DEMAND+ if( !acquired ) return;++ bool queue = false;+ const auto locks = m_lockCount.fetch_add( 1, std::memory_order_relaxed );+ const auto active = m_active.load( std::memory_order_relaxed );+ if( locks == 0 || active )+ {+ const bool connected = GetProfiler().IsConnected();+ if( active != connected ) m_active.store( connected, std::memory_order_relaxed );+ if( connected ) queue = true;+ }+ if( !queue ) return;+#endif++ if( acquired )+ {+ auto item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::LockSharedObtain );+ MemWrite( &item->lockObtain.thread, GetThreadHandle() );+ MemWrite( &item->lockObtain.id, m_id );+ MemWrite( &item->lockObtain.time, Profiler::GetTime() );+ Profiler::QueueSerialFinish();+ }+ }++ tracy_force_inline void Mark( const SourceLocationData* srcloc )+ {+#ifdef TRACY_ON_DEMAND+ const auto active = m_active.load( std::memory_order_relaxed );+ if( !active ) return;+ const auto connected = GetProfiler().IsConnected();+ if( !connected )+ {+ if( active ) m_active.store( false, std::memory_order_relaxed );+ return;+ }+#endif++ auto item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::LockMark );+ MemWrite( &item->lockMark.thread, GetThreadHandle() );+ MemWrite( &item->lockMark.id, m_id );+ MemWrite( &item->lockMark.srcloc, (uint64_t)srcloc );+ Profiler::QueueSerialFinish();+ }++ tracy_force_inline void CustomName( const char* name, size_t size )+ {+ assert( size < (std::numeric_limits<uint16_t>::max)() );+ auto ptr = (char*)tracy_malloc( size );+ memcpy( ptr, name, size );+ auto item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::LockName );+ MemWrite( &item->lockNameFat.id, m_id );+ MemWrite( &item->lockNameFat.name, (uint64_t)ptr );+ MemWrite( &item->lockNameFat.size, (uint16_t)size );+#ifdef TRACY_ON_DEMAND+ GetProfiler().DeferItem( *item );+#endif+ Profiler::QueueSerialFinish();+ }++private:+ uint32_t m_id;++#ifdef TRACY_ON_DEMAND+ std::atomic<uint32_t> m_lockCount;+ std::atomic<bool> m_active;+#endif+};++template<class T>+class SharedLockable+{+public:+ tracy_force_inline SharedLockable( const SourceLocationData* srcloc )+ : m_ctx( srcloc )+ {+ }++ SharedLockable( const SharedLockable& ) = delete;+ SharedLockable& operator=( const SharedLockable& ) = delete;++ tracy_force_inline void lock()+ {+ const auto runAfter = m_ctx.BeforeLock();+ m_lockable.lock();+ if( runAfter ) m_ctx.AfterLock();+ }++ tracy_force_inline void unlock()+ {+ m_lockable.unlock();+ m_ctx.AfterUnlock();+ }++ tracy_force_inline bool try_lock()+ {+ const auto acquired = m_lockable.try_lock();+ m_ctx.AfterTryLock( acquired );+ return acquired;+ }++ tracy_force_inline void lock_shared()+ {+ const auto runAfter = m_ctx.BeforeLockShared();+ m_lockable.lock_shared();+ if( runAfter ) m_ctx.AfterLockShared();+ }++ tracy_force_inline void unlock_shared()+ {+ m_lockable.unlock_shared();+ m_ctx.AfterUnlockShared();+ }++ tracy_force_inline bool try_lock_shared()+ {+ const auto acquired = m_lockable.try_lock_shared();+ m_ctx.AfterTryLockShared( acquired );+ return acquired;+ }++ tracy_force_inline void Mark( const SourceLocationData* srcloc )+ {+ m_ctx.Mark( srcloc );+ }++ tracy_force_inline void CustomName( const char* name, size_t size )+ {+ m_ctx.CustomName( name, size );+ }++private:+ T m_lockable;+ SharedLockableCtx m_ctx;+};+++}++#endif
+ cbits/tracy/public/client/TracyOverride.cpp view
@@ -0,0 +1,26 @@+#ifdef TRACY_ENABLE+# ifdef __linux__+# include "TracyDebug.hpp"+# ifdef TRACY_VERBOSE+# include <dlfcn.h>+# include <link.h>+# endif++extern "C" int dlclose( void* hnd )+{+#ifdef TRACY_VERBOSE+ struct link_map* lm;+ if( dlinfo( hnd, RTLD_DI_LINKMAP, &lm ) == 0 )+ {+ TracyDebug( "Overriding dlclose for %s\n", lm->l_name );+ }+ else+ {+ TracyDebug( "Overriding dlclose for unknown object (%s)\n", dlerror() );+ }+#endif+ return 0;+}++# endif+#endif
+ cbits/tracy/public/client/TracyProfiler.cpp view
@@ -0,0 +1,5007 @@+#ifdef TRACY_ENABLE++#ifdef _WIN32+# ifndef NOMINMAX+# define NOMINMAX+# endif+# include <winsock2.h>+# include <windows.h>+# include <tlhelp32.h>+# include <inttypes.h>+# include <intrin.h>+# include "../common/TracyUwp.hpp"+# ifndef _MSC_VER+# include <excpt.h>+# endif+#else+# include <sys/time.h>+# include <sys/param.h>+#endif++#ifdef _GNU_SOURCE+# include <errno.h>+#endif++#ifdef __linux__+# include <dirent.h>+# include <pthread.h>+# include <sys/types.h>+# include <sys/syscall.h>+#endif++#if defined __APPLE__ || defined BSD+# include <sys/types.h>+# include <sys/sysctl.h>+#endif++#if defined __APPLE__+# include "TargetConditionals.h"+# include <mach-o/dyld.h>+#endif++#ifdef __ANDROID__+# include <sys/mman.h>+# include <sys/system_properties.h>+# include <stdio.h>+# include <stdint.h>+# include <algorithm>+# include <vector>+#endif++#ifdef __QNX__+# include <stdint.h>+# include <stdio.h>+# include <string.h>+# include <sys/syspage.h>+# include <sys/stat.h>+#endif++#include <algorithm>+#include <assert.h>+#include <atomic>+#include <chrono>+#include <limits>+#include <new>+#include <stdlib.h>+#include <string.h>+#include <sys/stat.h>+#include <thread>++#include "../common/TracyAlign.hpp"+#include "../common/TracyAlloc.hpp"+#include "../common/TracySocket.hpp"+#include "../common/TracySystem.hpp"+#include "../common/TracyYield.hpp"+#include "../common/tracy_lz4.hpp"+#include "tracy_rpmalloc.hpp"+#include "TracyCallstack.hpp"+#include "TracyDebug.hpp"+#include "TracyDxt1.hpp"+#include "TracyScoped.hpp"+#include "TracyProfiler.hpp"+#include "TracyThread.hpp"+#include "TracyArmCpuTable.hpp"+#include "TracySysTrace.hpp"+#include "../tracy/TracyC.h"++#if defined TRACY_MANUAL_LIFETIME && !defined(TRACY_DELAYED_INIT)+# error "TRACY_MANUAL_LIFETIME requires enabled TRACY_DELAYED_INIT"+#endif++#ifdef TRACY_PORT+# ifndef TRACY_DATA_PORT+# define TRACY_DATA_PORT TRACY_PORT+# endif+# ifndef TRACY_BROADCAST_PORT+# define TRACY_BROADCAST_PORT TRACY_PORT+# endif+#endif++#ifdef __APPLE__+# ifndef TRACY_DELAYED_INIT+# define TRACY_DELAYED_INIT+# endif+#else+# ifdef __GNUC__+# define init_order( val ) __attribute__ ((init_priority(val)))+# else+# define init_order(x)+# endif+#endif++#if defined _WIN32+# include <lmcons.h>+extern "C" typedef LONG (WINAPI *t_RtlGetVersion)( PRTL_OSVERSIONINFOW );+extern "C" typedef BOOL (WINAPI *t_GetLogicalProcessorInformationEx)( LOGICAL_PROCESSOR_RELATIONSHIP, PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, PDWORD );+extern "C" typedef char* (WINAPI *t_WineGetVersion)();+extern "C" typedef char* (WINAPI *t_WineGetBuildId)();+#else+# include <unistd.h>+# include <limits.h>+# include <fcntl.h>+#endif+#if defined __linux__+# include <sys/sysinfo.h>+# include <sys/utsname.h>+#endif++#if !defined _WIN32 && ( defined __i386 || defined _M_IX86 || defined __x86_64__ || defined _M_X64 )+# include "TracyCpuid.hpp"+#endif++#if !( ( defined _WIN32 && _WIN32_WINNT >= _WIN32_WINNT_VISTA ) || defined __linux__ )+# include <mutex>+#endif++#ifdef __QNX__+extern char* __progname;+#endif++namespace tracy+{++#ifdef __ANDROID__+// Implementation helpers of EnsureReadable(address).+// This is so far only needed on Android, where it is common for libraries to be mapped+// with only executable, not readable, permissions. Typical example (line from /proc/self/maps):+/*+746b63b000-746b6dc000 --xp 00042000 07:48 35 /apex/com.android.runtime/lib64/bionic/libc.so+*/+// See https://github.com/wolfpld/tracy/issues/125 .+// To work around this, we parse /proc/self/maps and we use mprotect to set read permissions+// on any mappings that contain symbols addresses hit by HandleSymbolCodeQuery.++namespace {+// Holds some information about a single memory mapping.+struct MappingInfo {+ // Start of address range. Inclusive.+ uintptr_t start_address;+ // End of address range. Exclusive, so the mapping is the half-open interval+ // [start, end) and its length in bytes is `end - start`. As in /proc/self/maps.+ uintptr_t end_address;+ // Read/Write/Executable permissions.+ bool perm_r, perm_w, perm_x;+};+} // anonymous namespace++ // Internal implementation helper for LookUpMapping(address).+ //+ // Parses /proc/self/maps returning a vector<MappingInfo>.+ // /proc/self/maps is assumed to be sorted by ascending address, so the resulting+ // vector is sorted by ascending address too.+static std::vector<MappingInfo> ParseMappings()+{+ std::vector<MappingInfo> result;+ FILE* file = fopen( "/proc/self/maps", "r" );+ if( !file ) return result;+ char line[1024];+ while( fgets( line, sizeof( line ), file ) )+ {+ uintptr_t start_addr;+ uintptr_t end_addr;+#if defined(__LP64__)+ if( sscanf( line, "%lx-%lx", &start_addr, &end_addr ) != 2 ) continue;+#else+ if (sscanf( line, "%dx-%dx", &start_addr, &end_addr ) != 2 ) continue;+#endif+ char* first_space = strchr( line, ' ' );+ if( !first_space ) continue;+ char* perm = first_space + 1;+ char* second_space = strchr( perm, ' ' );+ if( !second_space || second_space - perm != 4 ) continue;+ result.emplace_back();+ auto& mapping = result.back();+ mapping.start_address = start_addr;+ mapping.end_address = end_addr;+ mapping.perm_r = perm[0] == 'r';+ mapping.perm_w = perm[1] == 'w';+ mapping.perm_x = perm[2] == 'x';+ }+ fclose( file );+ return result;+}++// Internal implementation helper for LookUpMapping(address).+//+// Takes as input an `address` and a known vector `mappings`, assumed to be+// sorted by increasing addresses, as /proc/self/maps seems to be.+// Returns a pointer to the MappingInfo describing the mapping that this+// address belongs to, or nullptr if the address isn't in `mappings`.+static MappingInfo* LookUpMapping(std::vector<MappingInfo>& mappings, uintptr_t address)+{+ // Comparison function for std::lower_bound. Returns true if all addresses in `m1`+ // are lower than `addr`.+ auto Compare = []( const MappingInfo& m1, uintptr_t addr ) {+ // '<=' because the address ranges are half-open intervals, [start, end).+ return m1.end_address <= addr;+ };+ auto iter = std::lower_bound( mappings.begin(), mappings.end(), address, Compare );+ if( iter == mappings.end() || iter->start_address > address) {+ return nullptr;+ }+ return &*iter;+}++// Internal implementation helper for EnsureReadable(address).+//+// Takes as input an `address` and returns a pointer to a MappingInfo+// describing the mapping that this address belongs to, or nullptr if+// the address isn't in any known mapping.+//+// This function is stateful and not reentrant (assumes to be called from+// only one thread). It holds a vector of mappings parsed from /proc/self/maps.+//+// Attempts to react to mappings changes by re-parsing /proc/self/maps.+static MappingInfo* LookUpMapping(uintptr_t address)+{+ // Static state managed by this function. Not constant, we mutate that state as+ // we turn some mappings readable. Initially parsed once here, updated as needed below.+ static std::vector<MappingInfo> s_mappings = ParseMappings();+ MappingInfo* mapping = LookUpMapping( s_mappings, address );+ if( mapping ) return mapping;++ // This address isn't in any known mapping. Try parsing again, maybe+ // mappings changed.+ s_mappings = ParseMappings();+ return LookUpMapping( s_mappings, address );+}++// Internal implementation helper for EnsureReadable(address).+//+// Attempts to make the specified `mapping` readable if it isn't already.+// Returns true if and only if the mapping is readable.+static bool EnsureReadable( MappingInfo& mapping )+{+ if( mapping.perm_r )+ {+ // The mapping is already readable.+ return true;+ }+ int prot = PROT_READ;+ if( mapping.perm_w ) prot |= PROT_WRITE;+ if( mapping.perm_x ) prot |= PROT_EXEC;+ if( mprotect( reinterpret_cast<void*>( mapping.start_address ),+ mapping.end_address - mapping.start_address, prot ) == -1 )+ {+ // Failed to make the mapping readable. Shouldn't happen, hasn't+ // been observed yet. If it happened in practice, we should consider+ // adding a bool to MappingInfo to track this to avoid retrying mprotect+ // everytime on such mappings.+ return false;+ }+ // The mapping is now readable. Update `mapping` so the next call will be fast.+ mapping.perm_r = true;+ return true;+}++// Attempts to set the read permission on the entire mapping containing the+// specified address. Returns true if and only if the mapping is now readable.+static bool EnsureReadable( uintptr_t address )+{+ MappingInfo* mapping = LookUpMapping(address);+ return mapping && EnsureReadable( *mapping );+}+#elif defined WIN32+static bool EnsureReadable( uintptr_t address )+{+ MEMORY_BASIC_INFORMATION memInfo;+ VirtualQuery( reinterpret_cast<void*>( address ), &memInfo, sizeof( memInfo ) );+ return memInfo.Protect != PAGE_NOACCESS;+}+#else+static bool EnsureReadable( uintptr_t address )+{+ return true;+}+#endif++#ifndef TRACY_DELAYED_INIT++struct InitTimeWrapper+{+ int64_t val;+};++struct ProducerWrapper+{+ tracy::moodycamel::ConcurrentQueue<QueueItem>::ExplicitProducer* ptr;+};++struct ThreadHandleWrapper+{+ uint32_t val;+};+#endif+++#if defined __i386 || defined _M_IX86 || defined __x86_64__ || defined _M_X64+static inline void CpuId( uint32_t* regs, uint32_t leaf )+{+ memset(regs, 0, sizeof(uint32_t) * 4);+#if defined _MSC_VER+ __cpuidex( (int*)regs, leaf, 0 );+#else+ __get_cpuid( leaf, regs, regs+1, regs+2, regs+3 );+#endif+}++static void InitFailure( const char* msg )+{+#if defined _WIN32+ bool hasConsole = false;+ bool reopen = false;+ const auto attached = AttachConsole( ATTACH_PARENT_PROCESS );+ if( attached )+ {+ hasConsole = true;+ reopen = true;+ }+ else+ {+ const auto err = GetLastError();+ if( err == ERROR_ACCESS_DENIED )+ {+ hasConsole = true;+ }+ }+ if( hasConsole )+ {+ fprintf( stderr, "Tracy Profiler initialization failure: %s\n", msg );+ if( reopen )+ {+ freopen( "CONOUT$", "w", stderr );+ fprintf( stderr, "Tracy Profiler initialization failure: %s\n", msg );+ }+ }+ else+ {+# ifndef TRACY_UWP+ MessageBoxA( nullptr, msg, "Tracy Profiler initialization failure", MB_ICONSTOP );+# endif+ }+#else+ fprintf( stderr, "Tracy Profiler initialization failure: %s\n", msg );+#endif+ exit( 1 );+}++static bool CheckHardwareSupportsInvariantTSC()+{+ const char* noCheck = GetEnvVar( "TRACY_NO_INVARIANT_CHECK" );+ if( noCheck && noCheck[0] == '1' ) return true;++ uint32_t regs[4];+ CpuId( regs, 1 );+ if( !( regs[3] & ( 1 << 4 ) ) )+ {+#if !defined TRACY_TIMER_QPC && !defined TRACY_TIMER_FALLBACK+ InitFailure( "CPU doesn't support RDTSC instruction." );+#else+ return false;+#endif+ }+ CpuId( regs, 0x80000007 );+ if( regs[3] & ( 1 << 8 ) ) return true;++ return false;+}++#if defined TRACY_TIMER_FALLBACK && defined TRACY_HW_TIMER+bool HardwareSupportsInvariantTSC()+{+ static bool cachedResult = CheckHardwareSupportsInvariantTSC();+ return cachedResult;+}+#endif++static int64_t SetupHwTimer()+{+#if !defined TRACY_TIMER_QPC && !defined TRACY_TIMER_FALLBACK+ if( !CheckHardwareSupportsInvariantTSC() )+ {+#if defined _WIN32+ InitFailure( "CPU doesn't support invariant TSC.\nDefine TRACY_NO_INVARIANT_CHECK=1 to ignore this error, *if you know what you are doing*.\nAlternatively you may rebuild the application with the TRACY_TIMER_QPC or TRACY_TIMER_FALLBACK define to use lower resolution timer." );+#else+ InitFailure( "CPU doesn't support invariant TSC.\nDefine TRACY_NO_INVARIANT_CHECK=1 to ignore this error, *if you know what you are doing*.\nAlternatively you may rebuild the application with the TRACY_TIMER_FALLBACK define to use lower resolution timer." );+#endif+ }+#endif++ return Profiler::GetTime();+}+#else+static int64_t SetupHwTimer()+{+ return Profiler::GetTime();+}+#endif++static const char* GetProcessName()+{+ const char* processName = "unknown";+#ifdef _WIN32+ static char buf[_MAX_PATH];+ GetModuleFileNameA( nullptr, buf, _MAX_PATH );+ const char* ptr = buf;+ while( *ptr != '\0' ) ptr++;+ while( ptr > buf && *ptr != '\\' && *ptr != '/' ) ptr--;+ if( ptr > buf ) ptr++;+ processName = ptr;+#elif defined __ANDROID__+# if __ANDROID_API__ >= 21+ auto buf = getprogname();+ if( buf ) processName = buf;+# endif+#elif defined __linux__ && defined _GNU_SOURCE+ if( program_invocation_short_name ) processName = program_invocation_short_name;+#elif defined __APPLE__ || defined BSD+ auto buf = getprogname();+ if( buf ) processName = buf;+#elif defined __QNX__+ processName = __progname;+#endif+ return processName;+}++static const char* GetProcessExecutablePath()+{+#ifdef _WIN32+ static char buf[_MAX_PATH];+ GetModuleFileNameA( nullptr, buf, _MAX_PATH );+ return buf;+#elif defined __ANDROID__+ return nullptr;+#elif defined __linux__ && defined _GNU_SOURCE+ return program_invocation_name;+#elif defined __APPLE__+ static char buf[1024];+ uint32_t size = 1024;+ _NSGetExecutablePath( buf, &size );+ return buf;+#elif defined __DragonFly__+ static char buf[1024];+ readlink( "/proc/curproc/file", buf, 1024 );+ return buf;+#elif defined __FreeBSD__+ static char buf[1024];+ int mib[4];+ mib[0] = CTL_KERN;+ mib[1] = KERN_PROC;+ mib[2] = KERN_PROC_PATHNAME;+ mib[3] = -1;+ size_t cb = 1024;+ sysctl( mib, 4, buf, &cb, nullptr, 0 );+ return buf;+#elif defined __NetBSD__+ static char buf[1024];+ readlink( "/proc/curproc/exe", buf, 1024 );+ return buf;+#elif defined __QNX__+ static char buf[_PC_PATH_MAX + 1];+ _cmdname(buf);+ return buf;+#else+ return nullptr;+#endif+}++#if defined __linux__ && defined __ARM_ARCH+static uint32_t GetHex( char*& ptr, int skip )+{+ uint32_t ret;+ ptr += skip;+ char* end;+ if( ptr[0] == '0' && ptr[1] == 'x' )+ {+ ptr += 2;+ ret = strtol( ptr, &end, 16 );+ }+ else+ {+ ret = strtol( ptr, &end, 10 );+ }+ ptr = end;+ return ret;+}+#endif++static const char* GetHostInfo()+{+ static char buf[1024];+ auto ptr = buf;+#if defined _WIN32+# ifdef TRACY_UWP+ auto GetVersion = &::GetVersionEx;+# else+ auto GetVersion = (t_RtlGetVersion)GetProcAddress( GetModuleHandleA( "ntdll.dll" ), "RtlGetVersion" );+# endif+ if( !GetVersion )+ {+# ifdef __MINGW32__+ ptr += sprintf( ptr, "OS: Windows (MingW)\n" );+# else+ ptr += sprintf( ptr, "OS: Windows\n" );+# endif+ }+ else+ {+ RTL_OSVERSIONINFOW ver = { sizeof( RTL_OSVERSIONINFOW ) };+ GetVersion( &ver );++# ifdef __MINGW32__+ ptr += sprintf( ptr, "OS: Windows %i.%i.%i (MingW)\n", (int)ver.dwMajorVersion, (int)ver.dwMinorVersion, (int)ver.dwBuildNumber );+# else+ auto WineGetVersion = (t_WineGetVersion)GetProcAddress( GetModuleHandleA( "ntdll.dll" ), "wine_get_version" );+ auto WineGetBuildId = (t_WineGetBuildId)GetProcAddress( GetModuleHandleA( "ntdll.dll" ), "wine_get_build_id" );+ if( WineGetVersion && WineGetBuildId )+ {+ ptr += sprintf( ptr, "OS: Windows %lu.%lu.%lu (Wine %s [%s])\n", ver.dwMajorVersion, ver.dwMinorVersion, ver.dwBuildNumber, WineGetVersion(), WineGetBuildId() );+ }+ else+ {+ ptr += sprintf( ptr, "OS: Windows %lu.%lu.%lu\n", ver.dwMajorVersion, ver.dwMinorVersion, ver.dwBuildNumber );+ }+# endif+ }+#elif defined __linux__+ struct utsname utsName;+ uname( &utsName );+# if defined __ANDROID__+ ptr += sprintf( ptr, "OS: Linux %s (Android)\n", utsName.release );+# else+ ptr += sprintf( ptr, "OS: Linux %s\n", utsName.release );+# endif+#elif defined __APPLE__+# if TARGET_OS_IPHONE == 1+ ptr += sprintf( ptr, "OS: Darwin (iOS)\n" );+# elif TARGET_OS_MAC == 1+ ptr += sprintf( ptr, "OS: Darwin (OSX)\n" );+# else+ ptr += sprintf( ptr, "OS: Darwin (unknown)\n" );+# endif+#elif defined __DragonFly__+ ptr += sprintf( ptr, "OS: BSD (DragonFly)\n" );+#elif defined __FreeBSD__+ ptr += sprintf( ptr, "OS: BSD (FreeBSD)\n" );+#elif defined __NetBSD__+ ptr += sprintf( ptr, "OS: BSD (NetBSD)\n" );+#elif defined __OpenBSD__+ ptr += sprintf( ptr, "OS: BSD (OpenBSD)\n" );+#elif defined __QNX__+ ptr += sprintf( ptr, "OS: QNX\n" );+#else+ ptr += sprintf( ptr, "OS: unknown\n" );+#endif++#if defined _MSC_VER+# if defined __clang__+ ptr += sprintf( ptr, "Compiler: MSVC clang-cl %i.%i.%i\n", __clang_major__, __clang_minor__, __clang_patchlevel__ );+# else+ ptr += sprintf( ptr, "Compiler: MSVC %i\n", _MSC_VER );+# endif+#elif defined __clang__+ ptr += sprintf( ptr, "Compiler: clang %i.%i.%i\n", __clang_major__, __clang_minor__, __clang_patchlevel__ );+#elif defined __GNUC__+ ptr += sprintf( ptr, "Compiler: gcc %i.%i.%i\n", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__ );+#else+ ptr += sprintf( ptr, "Compiler: unknown\n" );+#endif++#if defined _WIN32+ InitWinSock();++ char hostname[512];+ gethostname( hostname, 512 );++# ifdef TRACY_UWP+ const char* user = "";+# else+ DWORD userSz = UNLEN+1;+ char user[UNLEN+1];+ GetUserNameA( user, &userSz );+# endif++ ptr += sprintf( ptr, "User: %s@%s\n", user, hostname );+#else+ char hostname[_POSIX_HOST_NAME_MAX]{};+ char user[_POSIX_LOGIN_NAME_MAX]{};++ gethostname( hostname, _POSIX_HOST_NAME_MAX );+# if defined __ANDROID__+ const auto login = getlogin();+ if( login )+ {+ strcpy( user, login );+ }+ else+ {+ memcpy( user, "(?)", 4 );+ }+# else+ getlogin_r( user, _POSIX_LOGIN_NAME_MAX );+# endif++ ptr += sprintf( ptr, "User: %s@%s\n", user, hostname );+#endif++#if defined __i386 || defined _M_IX86+ ptr += sprintf( ptr, "Arch: x86\n" );+#elif defined __x86_64__ || defined _M_X64+ ptr += sprintf( ptr, "Arch: x64\n" );+#elif defined __aarch64__+ ptr += sprintf( ptr, "Arch: ARM64\n" );+#elif defined __ARM_ARCH+ ptr += sprintf( ptr, "Arch: ARM\n" );+#else+ ptr += sprintf( ptr, "Arch: unknown\n" );+#endif++#if defined __i386 || defined _M_IX86 || defined __x86_64__ || defined _M_X64+ uint32_t regs[4];+ char cpuModel[4*4*3+1] = {};+ auto modelPtr = cpuModel;+ for( uint32_t i=0x80000002; i<0x80000005; ++i )+ {+ CpuId( regs, i );+ memcpy( modelPtr, regs, sizeof( regs ) ); modelPtr += sizeof( regs );+ }++ ptr += sprintf( ptr, "CPU: %s\n", cpuModel );+#elif defined __linux__ && defined __ARM_ARCH+ bool cpuFound = false;+ FILE* fcpuinfo = fopen( "/proc/cpuinfo", "rb" );+ if( fcpuinfo )+ {+ enum { BufSize = 4*1024 };+ char buf[BufSize];+ const auto sz = fread( buf, 1, BufSize, fcpuinfo );+ fclose( fcpuinfo );+ const auto end = buf + sz;+ auto cptr = buf;++ uint32_t impl = 0;+ uint32_t var = 0;+ uint32_t part = 0;+ uint32_t rev = 0;++ while( end - cptr > 20 )+ {+ while( end - cptr > 20 && memcmp( cptr, "CPU ", 4 ) != 0 )+ {+ cptr += 4;+ while( end - cptr > 20 && *cptr != '\n' ) cptr++;+ cptr++;+ }+ if( end - cptr <= 20 ) break;+ cptr += 4;+ if( memcmp( cptr, "implementer\t: ", 14 ) == 0 )+ {+ if( impl != 0 ) break;+ impl = GetHex( cptr, 14 );+ }+ else if( memcmp( cptr, "variant\t: ", 10 ) == 0 ) var = GetHex( cptr, 10 );+ else if( memcmp( cptr, "part\t: ", 7 ) == 0 ) part = GetHex( cptr, 7 );+ else if( memcmp( cptr, "revision\t: ", 11 ) == 0 ) rev = GetHex( cptr, 11 );+ while( *cptr != '\n' && *cptr != '\0' ) cptr++;+ cptr++;+ }++ if( impl != 0 || var != 0 || part != 0 || rev != 0 )+ {+ cpuFound = true;+ ptr += sprintf( ptr, "CPU: %s%s r%ip%i\n", DecodeArmImplementer( impl ), DecodeArmPart( impl, part ), var, rev );+ }+ }+ if( !cpuFound )+ {+ ptr += sprintf( ptr, "CPU: unknown\n" );+ }+#elif defined __APPLE__ && TARGET_OS_IPHONE == 1+ {+ size_t sz;+ sysctlbyname( "hw.machine", nullptr, &sz, nullptr, 0 );+ auto str = (char*)tracy_malloc( sz );+ sysctlbyname( "hw.machine", str, &sz, nullptr, 0 );+ ptr += sprintf( ptr, "Device: %s\n", DecodeIosDevice( str ) );+ tracy_free( str );+ }+#else+ ptr += sprintf( ptr, "CPU: unknown\n" );+#endif+#ifdef __ANDROID__+ char deviceModel[PROP_VALUE_MAX+1];+ char deviceManufacturer[PROP_VALUE_MAX+1];+ __system_property_get( "ro.product.model", deviceModel );+ __system_property_get( "ro.product.manufacturer", deviceManufacturer );+ ptr += sprintf( ptr, "Device: %s %s\n", deviceManufacturer, deviceModel );+#endif++ ptr += sprintf( ptr, "CPU cores: %i\n", std::thread::hardware_concurrency() );++#if defined _WIN32+ MEMORYSTATUSEX statex;+ statex.dwLength = sizeof( statex );+ GlobalMemoryStatusEx( &statex );+# ifdef _MSC_VER+ ptr += sprintf( ptr, "RAM: %I64u MB\n", statex.ullTotalPhys / 1024 / 1024 );+# else+ ptr += sprintf( ptr, "RAM: %llu MB\n", statex.ullTotalPhys / 1024 / 1024 );+# endif+#elif defined __linux__+ struct sysinfo sysInfo;+ sysinfo( &sysInfo );+ ptr += sprintf( ptr, "RAM: %lu MB\n", sysInfo.totalram / 1024 / 1024 );+#elif defined __APPLE__+ size_t memSize;+ size_t sz = sizeof( memSize );+ sysctlbyname( "hw.memsize", &memSize, &sz, nullptr, 0 );+ ptr += sprintf( ptr, "RAM: %zu MB\n", memSize / 1024 / 1024 );+#elif defined BSD+ size_t memSize;+ size_t sz = sizeof( memSize );+ sysctlbyname( "hw.physmem", &memSize, &sz, nullptr, 0 );+ ptr += sprintf( ptr, "RAM: %zu MB\n", memSize / 1024 / 1024 );+#elif defined __QNX__+ struct asinfo_entry *entries = SYSPAGE_ENTRY(asinfo);+ size_t count = SYSPAGE_ENTRY_SIZE(asinfo) / sizeof(struct asinfo_entry);+ char *strings = SYSPAGE_ENTRY(strings)->data;++ uint64_t memSize = 0;+ size_t i;+ for (i = 0; i < count; i++) {+ struct asinfo_entry *entry = &entries[i];+ if (strcmp(strings + entry->name, "ram") == 0) {+ memSize += entry->end - entry->start + 1;+ }+ }+ memSize = memSize / 1024 / 1024;+ ptr += sprintf( ptr, "RAM: %llu MB\n", memSize);+#else+ ptr += sprintf( ptr, "RAM: unknown\n" );+#endif++ return buf;+}++static uint64_t GetPid()+{+#if defined _WIN32+ return uint64_t( GetCurrentProcessId() );+#else+ return uint64_t( getpid() );+#endif+}++void Profiler::AckServerQuery()+{+ QueueItem item;+ MemWrite( &item.hdr.type, QueueType::AckServerQueryNoop );+ NeedDataSize( QueueDataSize[(int)QueueType::AckServerQueryNoop] );+ AppendDataUnsafe( &item, QueueDataSize[(int)QueueType::AckServerQueryNoop] );+}++void Profiler::AckSymbolCodeNotAvailable()+{+ QueueItem item;+ MemWrite( &item.hdr.type, QueueType::AckSymbolCodeNotAvailable );+ NeedDataSize( QueueDataSize[(int)QueueType::AckSymbolCodeNotAvailable] );+ AppendDataUnsafe( &item, QueueDataSize[(int)QueueType::AckSymbolCodeNotAvailable] );+}++static BroadcastMessage& GetBroadcastMessage( const char* procname, size_t pnsz, int& len, int port )+{+ static BroadcastMessage msg;++ msg.broadcastVersion = BroadcastVersion;+ msg.protocolVersion = ProtocolVersion;+ msg.listenPort = port;+ msg.pid = GetPid();++ memcpy( msg.programName, procname, pnsz );+ memset( msg.programName + pnsz, 0, WelcomeMessageProgramNameSize - pnsz );++ len = int( offsetof( BroadcastMessage, programName ) + pnsz + 1 );+ return msg;+}++#if defined _WIN32 && !defined TRACY_UWP && !defined TRACY_NO_CRASH_HANDLER+static DWORD s_profilerThreadId = 0;+static DWORD s_symbolThreadId = 0;+static char s_crashText[1024];++LONG WINAPI CrashFilter( PEXCEPTION_POINTERS pExp )+{+ if( !GetProfiler().IsConnected() ) return EXCEPTION_CONTINUE_SEARCH;++ const unsigned ec = pExp->ExceptionRecord->ExceptionCode;+ auto msgPtr = s_crashText;+ switch( ec )+ {+ case EXCEPTION_ACCESS_VIOLATION:+ msgPtr += sprintf( msgPtr, "Exception EXCEPTION_ACCESS_VIOLATION (0x%x). ", ec );+ switch( pExp->ExceptionRecord->ExceptionInformation[0] )+ {+ case 0:+ msgPtr += sprintf( msgPtr, "Read violation at address 0x%" PRIxPTR ".", pExp->ExceptionRecord->ExceptionInformation[1] );+ break;+ case 1:+ msgPtr += sprintf( msgPtr, "Write violation at address 0x%" PRIxPTR ".", pExp->ExceptionRecord->ExceptionInformation[1] );+ break;+ case 8:+ msgPtr += sprintf( msgPtr, "DEP violation at address 0x%" PRIxPTR ".", pExp->ExceptionRecord->ExceptionInformation[1] );+ break;+ default:+ break;+ }+ break;+ case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:+ msgPtr += sprintf( msgPtr, "Exception EXCEPTION_ARRAY_BOUNDS_EXCEEDED (0x%x). ", ec );+ break;+ case EXCEPTION_DATATYPE_MISALIGNMENT:+ msgPtr += sprintf( msgPtr, "Exception EXCEPTION_DATATYPE_MISALIGNMENT (0x%x). ", ec );+ break;+ case EXCEPTION_FLT_DIVIDE_BY_ZERO:+ msgPtr += sprintf( msgPtr, "Exception EXCEPTION_FLT_DIVIDE_BY_ZERO (0x%x). ", ec );+ break;+ case EXCEPTION_ILLEGAL_INSTRUCTION:+ msgPtr += sprintf( msgPtr, "Exception EXCEPTION_ILLEGAL_INSTRUCTION (0x%x). ", ec );+ break;+ case EXCEPTION_IN_PAGE_ERROR:+ msgPtr += sprintf( msgPtr, "Exception EXCEPTION_IN_PAGE_ERROR (0x%x). ", ec );+ break;+ case EXCEPTION_INT_DIVIDE_BY_ZERO:+ msgPtr += sprintf( msgPtr, "Exception EXCEPTION_INT_DIVIDE_BY_ZERO (0x%x). ", ec );+ break;+ case EXCEPTION_PRIV_INSTRUCTION:+ msgPtr += sprintf( msgPtr, "Exception EXCEPTION_PRIV_INSTRUCTION (0x%x). ", ec );+ break;+ case EXCEPTION_STACK_OVERFLOW:+ msgPtr += sprintf( msgPtr, "Exception EXCEPTION_STACK_OVERFLOW (0x%x). ", ec );+ break;+ default:+ return EXCEPTION_CONTINUE_SEARCH;+ }++ {+ GetProfiler().SendCallstack( 60, "KiUserExceptionDispatcher" );++ TracyQueuePrepare( QueueType::CrashReport );+ item->crashReport.time = Profiler::GetTime();+ item->crashReport.text = (uint64_t)s_crashText;+ TracyQueueCommit( crashReportThread );+ }++ HANDLE h = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );+ if( h == INVALID_HANDLE_VALUE ) return EXCEPTION_CONTINUE_SEARCH;++ THREADENTRY32 te = { sizeof( te ) };+ if( !Thread32First( h, &te ) )+ {+ CloseHandle( h );+ return EXCEPTION_CONTINUE_SEARCH;+ }++ const auto pid = GetCurrentProcessId();+ const auto tid = GetCurrentThreadId();++ do+ {+ if( te.th32OwnerProcessID == pid && te.th32ThreadID != tid && te.th32ThreadID != s_profilerThreadId && te.th32ThreadID != s_symbolThreadId )+ {+ HANDLE th = OpenThread( THREAD_SUSPEND_RESUME, FALSE, te.th32ThreadID );+ if( th != INVALID_HANDLE_VALUE )+ {+ SuspendThread( th );+ CloseHandle( th );+ }+ }+ }+ while( Thread32Next( h, &te ) );+ CloseHandle( h );++ {+ TracyLfqPrepare( QueueType::Crash );+ TracyLfqCommit;+ }++ std::this_thread::sleep_for( std::chrono::milliseconds( 500 ) );+ GetProfiler().RequestShutdown();+ while( !GetProfiler().HasShutdownFinished() ) { std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) ); };++ return EXCEPTION_CONTINUE_SEARCH;+}+#endif++#if defined _WIN32 && !defined _MSC_VER+LONG WINAPI CrashFilterExecute( PEXCEPTION_POINTERS pExp )+{+ return EXCEPTION_EXECUTE_HANDLER;+}+#endif++static Profiler* s_instance = nullptr;+static Thread* s_thread;+#ifndef TRACY_NO_FRAME_IMAGE+static Thread* s_compressThread;+#endif+#ifdef TRACY_HAS_CALLSTACK+static Thread* s_symbolThread;+std::atomic<bool> s_symbolThreadGone { false };+#endif+#ifdef TRACY_HAS_SYSTEM_TRACING+static Thread* s_sysTraceThread = nullptr;+#endif++#if defined __linux__ && !defined TRACY_NO_CRASH_HANDLER+# ifndef TRACY_CRASH_SIGNAL+# define TRACY_CRASH_SIGNAL SIGPWR+# endif++static long s_profilerTid = 0;+static long s_symbolTid = 0;+static char s_crashText[1024];+static std::atomic<bool> s_alreadyCrashed( false );++static void ThreadFreezer( int /*signal*/ )+{+ for(;;) sleep( 1000 );+}++static inline void HexPrint( char*& ptr, uint64_t val )+{+ if( val == 0 )+ {+ *ptr++ = '0';+ return;+ }++ static const char HexTable[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };+ char buf[16];+ auto bptr = buf;++ do+ {+ *bptr++ = HexTable[val%16];+ val /= 16;+ }+ while( val > 0 );++ do+ {+ *ptr++ = *--bptr;+ }+ while( bptr != buf );+}++static void CrashHandler( int signal, siginfo_t* info, void* /*ucontext*/ )+{+ bool expected = false;+ if( !s_alreadyCrashed.compare_exchange_strong( expected, true ) ) ThreadFreezer( signal );++ struct sigaction act = {};+ act.sa_handler = SIG_DFL;+ sigaction( SIGABRT, &act, nullptr );++ auto msgPtr = s_crashText;+ switch( signal )+ {+ case SIGILL:+ strcpy( msgPtr, "Illegal Instruction.\n" );+ while( *msgPtr ) msgPtr++;+ switch( info->si_code )+ {+ case ILL_ILLOPC:+ strcpy( msgPtr, "Illegal opcode.\n" );+ break;+ case ILL_ILLOPN:+ strcpy( msgPtr, "Illegal operand.\n" );+ break;+ case ILL_ILLADR:+ strcpy( msgPtr, "Illegal addressing mode.\n" );+ break;+ case ILL_ILLTRP:+ strcpy( msgPtr, "Illegal trap.\n" );+ break;+ case ILL_PRVOPC:+ strcpy( msgPtr, "Privileged opcode.\n" );+ break;+ case ILL_PRVREG:+ strcpy( msgPtr, "Privileged register.\n" );+ break;+ case ILL_COPROC:+ strcpy( msgPtr, "Coprocessor error.\n" );+ break;+ case ILL_BADSTK:+ strcpy( msgPtr, "Internal stack error.\n" );+ break;+ default:+ break;+ }+ break;+ case SIGFPE:+ strcpy( msgPtr, "Floating-point exception.\n" );+ while( *msgPtr ) msgPtr++;+ switch( info->si_code )+ {+ case FPE_INTDIV:+ strcpy( msgPtr, "Integer divide by zero.\n" );+ break;+ case FPE_INTOVF:+ strcpy( msgPtr, "Integer overflow.\n" );+ break;+ case FPE_FLTDIV:+ strcpy( msgPtr, "Floating-point divide by zero.\n" );+ break;+ case FPE_FLTOVF:+ strcpy( msgPtr, "Floating-point overflow.\n" );+ break;+ case FPE_FLTUND:+ strcpy( msgPtr, "Floating-point underflow.\n" );+ break;+ case FPE_FLTRES:+ strcpy( msgPtr, "Floating-point inexact result.\n" );+ break;+ case FPE_FLTINV:+ strcpy( msgPtr, "Floating-point invalid operation.\n" );+ break;+ case FPE_FLTSUB:+ strcpy( msgPtr, "Subscript out of range.\n" );+ break;+ default:+ break;+ }+ break;+ case SIGSEGV:+ strcpy( msgPtr, "Invalid memory reference.\n" );+ while( *msgPtr ) msgPtr++;+ switch( info->si_code )+ {+ case SEGV_MAPERR:+ strcpy( msgPtr, "Address not mapped to object.\n" );+ break;+ case SEGV_ACCERR:+ strcpy( msgPtr, "Invalid permissions for mapped object.\n" );+ break;+# ifdef SEGV_BNDERR+ case SEGV_BNDERR:+ strcpy( msgPtr, "Failed address bound checks.\n" );+ break;+# endif+# ifdef SEGV_PKUERR+ case SEGV_PKUERR:+ strcpy( msgPtr, "Access was denied by memory protection keys.\n" );+ break;+# endif+ default:+ break;+ }+ break;+ case SIGPIPE:+ strcpy( msgPtr, "Broken pipe.\n" );+ while( *msgPtr ) msgPtr++;+ break;+ case SIGBUS:+ strcpy( msgPtr, "Bus error.\n" );+ while( *msgPtr ) msgPtr++;+ switch( info->si_code )+ {+ case BUS_ADRALN:+ strcpy( msgPtr, "Invalid address alignment.\n" );+ break;+ case BUS_ADRERR:+ strcpy( msgPtr, "Nonexistent physical address.\n" );+ break;+ case BUS_OBJERR:+ strcpy( msgPtr, "Object-specific hardware error.\n" );+ break;+# ifdef BUS_MCEERR_AR+ case BUS_MCEERR_AR:+ strcpy( msgPtr, "Hardware memory error consumed on a machine check; action required.\n" );+ break;+# endif+# ifdef BUS_MCEERR_AO+ case BUS_MCEERR_AO:+ strcpy( msgPtr, "Hardware memory error detected in process but not consumed; action optional.\n" );+ break;+# endif+ default:+ break;+ }+ break;+ case SIGABRT:+ strcpy( msgPtr, "Abort signal from abort().\n" );+ break;+ default:+ abort();+ }+ while( *msgPtr ) msgPtr++;++ if( signal != SIGPIPE )+ {+ strcpy( msgPtr, "Fault address: 0x" );+ while( *msgPtr ) msgPtr++;+ HexPrint( msgPtr, uint64_t( info->si_addr ) );+ *msgPtr++ = '\n';+ }++ {+ GetProfiler().SendCallstack( 60, "__kernel_rt_sigreturn" );++ TracyQueuePrepare( QueueType::CrashReport );+ item->crashReport.time = Profiler::GetTime();+ item->crashReport.text = (uint64_t)s_crashText;+ TracyQueueCommit( crashReportThread );+ }++ DIR* dp = opendir( "/proc/self/task" );+ if( !dp ) abort();++ const auto selfTid = syscall( SYS_gettid );++ struct dirent* ep;+ while( ( ep = readdir( dp ) ) != nullptr )+ {+ if( ep->d_name[0] == '.' ) continue;+ int tid = atoi( ep->d_name );+ if( tid != selfTid && tid != s_profilerTid && tid != s_symbolTid )+ {+ syscall( SYS_tkill, tid, TRACY_CRASH_SIGNAL );+ }+ }+ closedir( dp );++#ifdef TRACY_HAS_CALLSTACK+ if( selfTid == s_symbolTid ) s_symbolThreadGone.store( true, std::memory_order_release );+#endif++ TracyLfqPrepare( QueueType::Crash );+ TracyLfqCommit;++ std::this_thread::sleep_for( std::chrono::milliseconds( 500 ) );+ GetProfiler().RequestShutdown();+ while( !GetProfiler().HasShutdownFinished() ) { std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) ); };++ abort();+}+#endif+++enum { QueuePrealloc = 256 * 1024 };++TRACY_API int64_t GetFrequencyQpc()+{+#if defined _WIN32+ LARGE_INTEGER t;+ QueryPerformanceFrequency( &t );+ return t.QuadPart;+#else+ return 0;+#endif+}++#ifdef TRACY_DELAYED_INIT+struct ThreadNameData;+TRACY_API moodycamel::ConcurrentQueue<QueueItem>& GetQueue();++struct ProfilerData+{+ int64_t initTime = SetupHwTimer();+ moodycamel::ConcurrentQueue<QueueItem> queue;+ Profiler profiler;+ std::atomic<uint32_t> lockCounter { 0 };+ std::atomic<uint8_t> gpuCtxCounter { 0 };+ std::atomic<ThreadNameData*> threadNameData { nullptr };+};++struct ProducerWrapper+{+ ProducerWrapper( ProfilerData& data ) : detail( data.queue ), ptr( data.queue.get_explicit_producer( detail ) ) {}+ moodycamel::ProducerToken detail;+ tracy::moodycamel::ConcurrentQueue<QueueItem>::ExplicitProducer* ptr;+};++struct ProfilerThreadData+{+ ProfilerThreadData( ProfilerData& data ) : token( data ), gpuCtx( { nullptr } ) {}+ ProducerWrapper token;+ GpuCtxWrapper gpuCtx;+# ifdef TRACY_ON_DEMAND+ LuaZoneState luaZoneState;+# endif+};++std::atomic<int> RpInitDone { 0 };+std::atomic<int> RpInitLock { 0 };+thread_local bool RpThreadInitDone = false;+thread_local bool RpThreadShutdown = false;++# ifdef TRACY_MANUAL_LIFETIME+ProfilerData* s_profilerData = nullptr;+static ProfilerThreadData& GetProfilerThreadData();+static std::atomic<bool> s_isProfilerStarted { false };+TRACY_API void StartupProfiler()+{+ s_profilerData = (ProfilerData*)tracy_malloc( sizeof( ProfilerData ) );+ new (s_profilerData) ProfilerData();+ s_profilerData->profiler.SpawnWorkerThreads();+ GetProfilerThreadData().token = ProducerWrapper( *s_profilerData );+ s_isProfilerStarted.store( true, std::memory_order_seq_cst );+}+static ProfilerData& GetProfilerData()+{+ assert( s_profilerData );+ return *s_profilerData;+}+TRACY_API void ShutdownProfiler()+{+ s_isProfilerStarted.store( false, std::memory_order_seq_cst );+ s_profilerData->~ProfilerData();+ tracy_free( s_profilerData );+ s_profilerData = nullptr;+ rpmalloc_finalize();+ RpThreadInitDone = false;+ RpInitDone.store( 0, std::memory_order_release );+}+TRACY_API bool IsProfilerStarted()+{+ return s_isProfilerStarted.load( std::memory_order_seq_cst );+}+# else+static std::atomic<int> profilerDataLock { 0 };+static std::atomic<ProfilerData*> profilerData { nullptr };++static ProfilerData& GetProfilerData()+{+ auto ptr = profilerData.load( std::memory_order_acquire );+ if( !ptr )+ {+ int expected = 0;+ while( !profilerDataLock.compare_exchange_weak( expected, 1, std::memory_order_release, std::memory_order_relaxed ) ) { expected = 0; YieldThread(); }+ ptr = profilerData.load( std::memory_order_acquire );+ if( !ptr )+ {+ ptr = (ProfilerData*)tracy_malloc( sizeof( ProfilerData ) );+ new (ptr) ProfilerData();+ profilerData.store( ptr, std::memory_order_release );+ }+ profilerDataLock.store( 0, std::memory_order_release );+ }+ return *ptr;+}+# endif++// GCC prior to 8.4 had a bug with function-inline thread_local variables. Versions of glibc beginning with+// 2.18 may attempt to work around this issue, which manifests as a crash while running static destructors+// if this function is compiled into a shared object. Unfortunately, centos7 ships with glibc 2.17. If running+// on old GCC, use the old-fashioned way as a workaround+// See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85400+#if !defined(__clang__) && defined(__GNUC__) && ((__GNUC__ < 8) || ((__GNUC__ == 8) && (__GNUC_MINOR__ < 4)))+struct ProfilerThreadDataKey+{+public:+ ProfilerThreadDataKey()+ {+ int val = pthread_key_create(&m_key, sDestructor);+ static_cast<void>(val); // unused+ assert(val == 0);+ }+ ~ProfilerThreadDataKey()+ {+ int val = pthread_key_delete(m_key);+ static_cast<void>(val); // unused+ assert(val == 0);+ }+ ProfilerThreadData& get()+ {+ void* p = pthread_getspecific(m_key);+ if (!p)+ {+ p = (ProfilerThreadData*)tracy_malloc( sizeof( ProfilerThreadData ) );+ new (p) ProfilerThreadData(GetProfilerData());+ pthread_setspecific(m_key, p);+ }+ return *static_cast<ProfilerThreadData*>(p);+ }+private:+ pthread_key_t m_key;++ static void sDestructor(void* p)+ {+ ((ProfilerThreadData*)p)->~ProfilerThreadData();+ tracy_free(p);+ }+};++static ProfilerThreadData& GetProfilerThreadData()+{+ static ProfilerThreadDataKey key;+ return key.get();+}+#else+static ProfilerThreadData& GetProfilerThreadData()+{+ thread_local ProfilerThreadData data( GetProfilerData() );+ return data;+}+#endif++TRACY_API moodycamel::ConcurrentQueue<QueueItem>::ExplicitProducer* GetToken() { return GetProfilerThreadData().token.ptr; }+TRACY_API Profiler& GetProfiler() { return GetProfilerData().profiler; }+TRACY_API moodycamel::ConcurrentQueue<QueueItem>& GetQueue() { return GetProfilerData().queue; }+TRACY_API int64_t GetInitTime() { return GetProfilerData().initTime; }+TRACY_API std::atomic<uint32_t>& GetLockCounter() { return GetProfilerData().lockCounter; }+TRACY_API std::atomic<uint8_t>& GetGpuCtxCounter() { return GetProfilerData().gpuCtxCounter; }+TRACY_API GpuCtxWrapper& GetGpuCtx() { return GetProfilerThreadData().gpuCtx; }+TRACY_API uint32_t GetThreadHandle() { return detail::GetThreadHandleImpl(); }+std::atomic<ThreadNameData*>& GetThreadNameData() { return GetProfilerData().threadNameData; }++# ifdef TRACY_ON_DEMAND+TRACY_API LuaZoneState& GetLuaZoneState() { return GetProfilerThreadData().luaZoneState; }+# endif++# ifndef TRACY_MANUAL_LIFETIME+namespace+{+ const auto& __profiler_init = GetProfiler();+}+# endif++#else++// MSVC static initialization order solution. gcc/clang uses init_order() to avoid all this.++// 1a. But s_queue is needed for initialization of variables in point 2.+extern moodycamel::ConcurrentQueue<QueueItem> s_queue;++// 2. If these variables would be in the .CRT$XCB section, they would be initialized only in main thread.+thread_local moodycamel::ProducerToken init_order(107) s_token_detail( s_queue );+thread_local ProducerWrapper init_order(108) s_token { s_queue.get_explicit_producer( s_token_detail ) };+thread_local ThreadHandleWrapper init_order(104) s_threadHandle { detail::GetThreadHandleImpl() };++# ifdef _MSC_VER+// 1. Initialize these static variables before all other variables.+# pragma warning( disable : 4075 )+# pragma init_seg( ".CRT$XCB" )+# endif++static InitTimeWrapper init_order(101) s_initTime { SetupHwTimer() };+std::atomic<int> init_order(102) RpInitDone( 0 );+std::atomic<int> init_order(102) RpInitLock( 0 );+thread_local bool RpThreadInitDone = false;+thread_local bool RpThreadShutdown = false;+moodycamel::ConcurrentQueue<QueueItem> init_order(103) s_queue( QueuePrealloc );+std::atomic<uint32_t> init_order(104) s_lockCounter( 0 );+std::atomic<uint8_t> init_order(104) s_gpuCtxCounter( 0 );++thread_local GpuCtxWrapper init_order(104) s_gpuCtx { nullptr };++struct ThreadNameData;+static std::atomic<ThreadNameData*> init_order(104) s_threadNameDataInstance( nullptr );+std::atomic<ThreadNameData*>& s_threadNameData = s_threadNameDataInstance;++# ifdef TRACY_ON_DEMAND+thread_local LuaZoneState init_order(104) s_luaZoneState { 0, false };+# endif++static Profiler init_order(105) s_profiler;++TRACY_API moodycamel::ConcurrentQueue<QueueItem>::ExplicitProducer* GetToken() { return s_token.ptr; }+TRACY_API Profiler& GetProfiler() { return s_profiler; }+TRACY_API moodycamel::ConcurrentQueue<QueueItem>& GetQueue() { return s_queue; }+TRACY_API int64_t GetInitTime() { return s_initTime.val; }+TRACY_API std::atomic<uint32_t>& GetLockCounter() { return s_lockCounter; }+TRACY_API std::atomic<uint8_t>& GetGpuCtxCounter() { return s_gpuCtxCounter; }+TRACY_API GpuCtxWrapper& GetGpuCtx() { return s_gpuCtx; }+TRACY_API uint32_t GetThreadHandle() { return s_threadHandle.val; }++std::atomic<ThreadNameData*>& GetThreadNameData() { return s_threadNameData; }++# ifdef TRACY_ON_DEMAND+TRACY_API LuaZoneState& GetLuaZoneState() { return s_luaZoneState; }+# endif+#endif++TRACY_API bool ProfilerAvailable() { return s_instance != nullptr; }+TRACY_API bool ProfilerAllocatorAvailable() { return !RpThreadShutdown; }++constexpr static size_t SafeSendBufferSize = 65536;++Profiler::Profiler()+ : m_timeBegin( 0 )+ , m_mainThread( detail::GetThreadHandleImpl() )+ , m_epoch( std::chrono::duration_cast<std::chrono::seconds>( std::chrono::system_clock::now().time_since_epoch() ).count() )+ , m_shutdown( false )+ , m_shutdownManual( false )+ , m_shutdownFinished( false )+ , m_sock( nullptr )+ , m_broadcast( nullptr )+ , m_noExit( false )+ , m_userPort( 0 )+ , m_zoneId( 1 )+ , m_samplingPeriod( 0 )+ , m_stream( LZ4_createStream() )+ , m_buffer( (char*)tracy_malloc( TargetFrameSize*3 ) )+ , m_bufferOffset( 0 )+ , m_bufferStart( 0 )+ , m_lz4Buf( (char*)tracy_malloc( LZ4Size + sizeof( lz4sz_t ) ) )+ , m_serialQueue( 1024*1024 )+ , m_serialDequeue( 1024*1024 )+#ifndef TRACY_NO_FRAME_IMAGE+ , m_fiQueue( 16 )+ , m_fiDequeue( 16 )+#endif+ , m_symbolQueue( 8*1024 )+ , m_frameCount( 0 )+ , m_isConnected( false )+#ifdef TRACY_ON_DEMAND+ , m_connectionId( 0 )+ , m_deferredQueue( 64*1024 )+#endif+ , m_paramCallback( nullptr )+ , m_sourceCallback( nullptr )+ , m_queryImage( nullptr )+ , m_queryData( nullptr )+ , m_crashHandlerInstalled( false )+ , m_programName( nullptr )+{+ assert( !s_instance );+ s_instance = this;++#ifndef TRACY_DELAYED_INIT+# ifdef _MSC_VER+ // 3. But these variables need to be initialized in main thread within the .CRT$XCB section. Do it here.+ s_token_detail = moodycamel::ProducerToken( s_queue );+ s_token = ProducerWrapper { s_queue.get_explicit_producer( s_token_detail ) };+ s_threadHandle = ThreadHandleWrapper { m_mainThread };+# endif+#endif++ CalibrateTimer();+ CalibrateDelay();+ ReportTopology();++#ifdef __linux__+ m_kcore = (KCore*)tracy_malloc( sizeof( KCore ) );+ new(m_kcore) KCore();+#endif++#ifndef TRACY_NO_EXIT+ const char* noExitEnv = GetEnvVar( "TRACY_NO_EXIT" );+ if( noExitEnv && noExitEnv[0] == '1' )+ {+ m_noExit = true;+ }+#endif++ const char* userPort = GetEnvVar( "TRACY_PORT" );+ if( userPort )+ {+ m_userPort = atoi( userPort );+ }++ m_safeSendBuffer = (char*)tracy_malloc( SafeSendBufferSize );++#ifndef _WIN32+ pipe(m_pipe);+# if defined __APPLE__ || defined BSD+ // FreeBSD/XNU don't have F_SETPIPE_SZ, so use the default+ m_pipeBufSize = 16384;+# else+ m_pipeBufSize = (int)(ptrdiff_t)SafeSendBufferSize;+ while( fcntl( m_pipe[0], F_SETPIPE_SZ, m_pipeBufSize ) < 0 && errno == EPERM ) m_pipeBufSize /= 2; // too big; reduce+ m_pipeBufSize = fcntl( m_pipe[0], F_GETPIPE_SZ );+# endif+ fcntl( m_pipe[1], F_SETFL, O_NONBLOCK );+#endif++#if !defined(TRACY_DELAYED_INIT) || !defined(TRACY_MANUAL_LIFETIME)+ SpawnWorkerThreads();+#endif+}++void Profiler::InstallCrashHandler()+{++#if defined __linux__ && !defined TRACY_NO_CRASH_HANDLER+ struct sigaction threadFreezer = {};+ threadFreezer.sa_handler = ThreadFreezer;+ sigaction( TRACY_CRASH_SIGNAL, &threadFreezer, &m_prevSignal.pwr );++ struct sigaction crashHandler = {};+ crashHandler.sa_sigaction = CrashHandler;+ crashHandler.sa_flags = SA_SIGINFO;+ sigaction( SIGILL, &crashHandler, &m_prevSignal.ill );+ sigaction( SIGFPE, &crashHandler, &m_prevSignal.fpe );+ sigaction( SIGSEGV, &crashHandler, &m_prevSignal.segv );+ sigaction( SIGPIPE, &crashHandler, &m_prevSignal.pipe );+ sigaction( SIGBUS, &crashHandler, &m_prevSignal.bus );+ sigaction( SIGABRT, &crashHandler, &m_prevSignal.abrt );+#endif++#if defined _WIN32 && !defined TRACY_UWP && !defined TRACY_NO_CRASH_HANDLER+ // We cannot use Vectored Exception handling because it catches application-wide frame-based SEH blocks. We only+ // want to catch unhandled exceptions.+ m_prevHandler = reinterpret_cast<void*>( SetUnhandledExceptionFilter( CrashFilter ) );+#endif++#ifndef TRACY_NO_CRASH_HANDLER+ m_crashHandlerInstalled = true;+#endif++}++void Profiler::RemoveCrashHandler()+{+#if defined _WIN32 && !defined TRACY_UWP && !defined TRACY_NO_CRASH_HANDLER+ if( m_crashHandlerInstalled )+ {+ auto prev = SetUnhandledExceptionFilter( (LPTOP_LEVEL_EXCEPTION_FILTER)m_prevHandler );+ if( prev != CrashFilter ) SetUnhandledExceptionFilter( prev ); // A different exception filter was installed over ours => put it back+ }+#endif++#if defined __linux__ && !defined TRACY_NO_CRASH_HANDLER+ if( m_crashHandlerInstalled )+ {+ auto restore = []( int signum, struct sigaction* prev ) {+ struct sigaction old;+ sigaction( signum, prev, &old );+ if( old.sa_sigaction != CrashHandler ) sigaction( signum, &old, nullptr ); // A different signal handler was installed over ours => put it back+ };+ restore( TRACY_CRASH_SIGNAL, &m_prevSignal.pwr );+ restore( SIGILL, &m_prevSignal.ill );+ restore( SIGFPE, &m_prevSignal.fpe );+ restore( SIGSEGV, &m_prevSignal.segv );+ restore( SIGPIPE, &m_prevSignal.pipe );+ restore( SIGBUS, &m_prevSignal.bus );+ restore( SIGABRT, &m_prevSignal.abrt );+ }+#endif+ m_crashHandlerInstalled = false;+}++void Profiler::SpawnWorkerThreads()+{+#ifdef TRACY_HAS_SYSTEM_TRACING+ // use TRACY_NO_SYS_TRACE=1 to force disabling sys tracing (even if available in the underlying system)+ // as it can have significant impact on the size of the traces+ const char* noSysTrace = GetEnvVar( "TRACY_NO_SYS_TRACE" );+ const bool disableSystrace = (noSysTrace && noSysTrace[0] == '1');+ if( disableSystrace )+ {+ TracyDebug("TRACY: Sys Trace was disabled by 'TRACY_NO_SYS_TRACE=1'\n");+ }+ else if( SysTraceStart( m_samplingPeriod ) )+ {+ s_sysTraceThread = (Thread*)tracy_malloc( sizeof( Thread ) );+ new(s_sysTraceThread) Thread( SysTraceWorker, nullptr );+ std::this_thread::sleep_for( std::chrono::milliseconds( 1 ) );+ }+#endif++ s_thread = (Thread*)tracy_malloc( sizeof( Thread ) );+ new(s_thread) Thread( LaunchWorker, this );++#ifndef TRACY_NO_FRAME_IMAGE+ s_compressThread = (Thread*)tracy_malloc( sizeof( Thread ) );+ new(s_compressThread) Thread( LaunchCompressWorker, this );+#endif++#ifdef TRACY_HAS_CALLSTACK+ s_symbolThread = (Thread*)tracy_malloc( sizeof( Thread ) );+ new(s_symbolThread) Thread( LaunchSymbolWorker, this );+#endif++#if defined _WIN32 && !defined TRACY_UWP && !defined TRACY_NO_CRASH_HANDLER+ s_profilerThreadId = GetThreadId( s_thread->Handle() );+# ifdef TRACY_HAS_CALLSTACK+ s_symbolThreadId = GetThreadId( s_symbolThread->Handle() );+# endif+#endif++#ifdef TRACY_HAS_CALLSTACK+ InitCallstackCritical();+#endif++ m_timeBegin.store( GetTime(), std::memory_order_relaxed );+}++Profiler::~Profiler()+{+ m_shutdown.store( true, std::memory_order_relaxed );++ RemoveCrashHandler();++#ifdef TRACY_HAS_SYSTEM_TRACING+ if( s_sysTraceThread )+ {+ SysTraceStop();+ s_sysTraceThread->~Thread();+ tracy_free( s_sysTraceThread );+ }+#endif++#ifdef TRACY_HAS_CALLSTACK+ s_symbolThread->~Thread();+ tracy_free( s_symbolThread );+#endif++#ifndef TRACY_NO_FRAME_IMAGE+ s_compressThread->~Thread();+ tracy_free( s_compressThread );+#endif++ s_thread->~Thread();+ tracy_free( s_thread );++#ifdef TRACY_HAS_CALLSTACK+ EndCallstack();+#endif++#ifdef __linux__+ m_kcore->~KCore();+ tracy_free( m_kcore );+#endif++#ifndef _WIN32+ close( m_pipe[0] );+ close( m_pipe[1] );+#endif+ tracy_free( m_safeSendBuffer );++ tracy_free( m_lz4Buf );+ tracy_free( m_buffer );+ LZ4_freeStream( (LZ4_stream_t*)m_stream );++ if( m_sock )+ {+ m_sock->~Socket();+ tracy_free( m_sock );+ }++ if( m_broadcast )+ {+ m_broadcast->~UdpBroadcast();+ tracy_free( m_broadcast );+ }++ assert( s_instance );+ s_instance = nullptr;+}++bool Profiler::ShouldExit()+{+ return s_instance->m_shutdown.load( std::memory_order_relaxed );+}++void Profiler::Worker()+{+#if defined __linux__ && !defined TRACY_NO_CRASH_HANDLER+ s_profilerTid = syscall( SYS_gettid );+#endif++ ThreadExitHandler threadExitHandler;++ SetThreadName( "Tracy Profiler" );++#ifdef TRACY_DATA_PORT+ const bool dataPortSearch = false;+ auto dataPort = m_userPort != 0 ? m_userPort : TRACY_DATA_PORT;+#else+ const bool dataPortSearch = m_userPort == 0;+ auto dataPort = m_userPort != 0 ? m_userPort : 8086;+#endif+#ifdef TRACY_BROADCAST_PORT+ const auto broadcastPort = TRACY_BROADCAST_PORT;+#else+ const auto broadcastPort = 8086;+#endif++ while( m_timeBegin.load( std::memory_order_relaxed ) == 0 ) std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );++#ifdef TRACY_USE_RPMALLOC+ rpmalloc_thread_initialize();+#endif++ m_exectime = 0;+ const auto execname = GetProcessExecutablePath();+ if( execname )+ {+ struct stat st;+ if( stat( execname, &st ) == 0 )+ {+ m_exectime = (uint64_t)st.st_mtime;+ }+ }++ const auto procname = GetProcessName();+ const auto pnsz = std::min<size_t>( strlen( procname ), WelcomeMessageProgramNameSize - 1 );++ const auto hostinfo = GetHostInfo();+ const auto hisz = std::min<size_t>( strlen( hostinfo ), WelcomeMessageHostInfoSize - 1 );++ const uint64_t pid = GetPid();++ uint8_t flags = 0;++#ifdef TRACY_ON_DEMAND+ flags |= WelcomeFlag::OnDemand;+#endif+#ifdef __APPLE__+ flags |= WelcomeFlag::IsApple;+#endif+#ifndef TRACY_NO_CODE_TRANSFER+ flags |= WelcomeFlag::CodeTransfer;+#endif+#ifdef _WIN32+ flags |= WelcomeFlag::CombineSamples;+# ifndef TRACY_NO_CONTEXT_SWITCH+ flags |= WelcomeFlag::IdentifySamples;+# endif+#endif++#if defined __i386 || defined _M_IX86+ uint8_t cpuArch = CpuArchX86;+#elif defined __x86_64__ || defined _M_X64+ uint8_t cpuArch = CpuArchX64;+#elif defined __aarch64__+ uint8_t cpuArch = CpuArchArm64;+#elif defined __ARM_ARCH+ uint8_t cpuArch = CpuArchArm32;+#else+ uint8_t cpuArch = CpuArchUnknown;+#endif++#if defined __i386 || defined _M_IX86 || defined __x86_64__ || defined _M_X64+ uint32_t regs[4];+ char manufacturer[12];+ CpuId( regs, 0 );+ memcpy( manufacturer, regs+1, 4 );+ memcpy( manufacturer+4, regs+3, 4 );+ memcpy( manufacturer+8, regs+2, 4 );++ CpuId( regs, 1 );+ uint32_t cpuId = ( regs[0] & 0xFFF ) | ( ( regs[0] & 0xFFF0000 ) >> 4 );+#else+ const char manufacturer[12] = {};+ uint32_t cpuId = 0;+#endif++ WelcomeMessage welcome;+ MemWrite( &welcome.timerMul, m_timerMul );+ MemWrite( &welcome.initBegin, GetInitTime() );+ MemWrite( &welcome.initEnd, m_timeBegin.load( std::memory_order_relaxed ) );+ MemWrite( &welcome.delay, m_delay );+ MemWrite( &welcome.resolution, m_resolution );+ MemWrite( &welcome.epoch, m_epoch );+ MemWrite( &welcome.exectime, m_exectime );+ MemWrite( &welcome.pid, pid );+ MemWrite( &welcome.samplingPeriod, m_samplingPeriod );+ MemWrite( &welcome.flags, flags );+ MemWrite( &welcome.cpuArch, cpuArch );+ memcpy( welcome.cpuManufacturer, manufacturer, 12 );+ MemWrite( &welcome.cpuId, cpuId );+ memcpy( welcome.programName, procname, pnsz );+ memset( welcome.programName + pnsz, 0, WelcomeMessageProgramNameSize - pnsz );+ memcpy( welcome.hostInfo, hostinfo, hisz );+ memset( welcome.hostInfo + hisz, 0, WelcomeMessageHostInfoSize - hisz );++ moodycamel::ConsumerToken token( GetQueue() );++ ListenSocket listen;+ bool isListening = false;+ if( !dataPortSearch )+ {+ isListening = listen.Listen( dataPort, 4 );+ }+ else+ {+ for( uint32_t i=0; i<20; i++ )+ {+ if( listen.Listen( dataPort+i, 4 ) )+ {+ dataPort += i;+ isListening = true;+ break;+ }+ }+ }+ if( !isListening )+ {+ for(;;)+ {+ if( ShouldExit() )+ {+ m_shutdownFinished.store( true, std::memory_order_relaxed );+ return;+ }++ ClearQueues( token );+ std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );+ }+ }++#ifndef TRACY_NO_BROADCAST+ m_broadcast = (UdpBroadcast*)tracy_malloc( sizeof( UdpBroadcast ) );+ new(m_broadcast) UdpBroadcast();+# ifdef TRACY_ONLY_LOCALHOST+ const char* addr = "127.255.255.255";+# elif defined TRACY_CLIENT_ADDRESS+ const char* addr = TRACY_CLIENT_ADDRESS;+# elif defined __QNX__+ // global broadcast address of 255.255.255.255 is not well-supported by QNX,+ // use the interface broadcast address instead, e.g. "const char* addr = 192.168.1.255;"+# error Need to specify TRACY_CLIENT_ADDRESS for a QNX target.+# else+ const char* addr = "255.255.255.255";+# endif+ if( !m_broadcast->Open( addr, broadcastPort ) )+ {+ m_broadcast->~UdpBroadcast();+ tracy_free( m_broadcast );+ m_broadcast = nullptr;+ }+#endif++ int broadcastLen = 0;+ auto& broadcastMsg = GetBroadcastMessage( procname, pnsz, broadcastLen, dataPort );+ uint64_t lastBroadcast = 0;++ // Connections loop.+ // Each iteration of the loop handles whole connection. Multiple iterations will only+ // happen in the on-demand mode or when handshake fails.+ for(;;)+ {+ // Wait for incoming connection+ for(;;)+ {+#ifndef TRACY_NO_EXIT+ if( !m_noExit && ShouldExit() )+ {+ if( m_broadcast )+ {+ broadcastMsg.activeTime = -1;+ m_broadcast->Send( broadcastPort, &broadcastMsg, broadcastLen );+ }+ m_shutdownFinished.store( true, std::memory_order_relaxed );+ return;+ }+#endif+ m_sock = listen.Accept();+ if( m_sock ) break;+#ifndef TRACY_ON_DEMAND+ ProcessSysTime();+# ifdef TRACY_HAS_SYSPOWER+ m_sysPower.Tick();+# endif+#endif++ if( m_broadcast )+ {+ const auto t = std::chrono::high_resolution_clock::now().time_since_epoch().count();+ if( t - lastBroadcast > 3000000000 ) // 3s+ {+ m_programNameLock.lock();+ if( m_programName )+ {+ broadcastMsg = GetBroadcastMessage( m_programName, strlen( m_programName ), broadcastLen, dataPort );+ m_programName = nullptr;+ }+ m_programNameLock.unlock();++ lastBroadcast = t;+ const auto ts = std::chrono::duration_cast<std::chrono::seconds>( std::chrono::system_clock::now().time_since_epoch() ).count();+ broadcastMsg.activeTime = int32_t( ts - m_epoch );+ assert( broadcastMsg.activeTime >= 0 );+ m_broadcast->Send( broadcastPort, &broadcastMsg, broadcastLen );+ }+ }+ }++ if( m_broadcast )+ {+ lastBroadcast = 0;+ broadcastMsg.activeTime = -1;+ m_broadcast->Send( broadcastPort, &broadcastMsg, broadcastLen );+ }++ // Handshake+ {+ char shibboleth[HandshakeShibbolethSize];+ auto res = m_sock->ReadRaw( shibboleth, HandshakeShibbolethSize, 2000 );+ if( !res || memcmp( shibboleth, HandshakeShibboleth, HandshakeShibbolethSize ) != 0 )+ {+ m_sock->~Socket();+ tracy_free( m_sock );+ m_sock = nullptr;+ continue;+ }++ uint32_t protocolVersion;+ res = m_sock->ReadRaw( &protocolVersion, sizeof( protocolVersion ), 2000 );+ if( !res )+ {+ m_sock->~Socket();+ tracy_free( m_sock );+ m_sock = nullptr;+ continue;+ }++ if( protocolVersion != ProtocolVersion )+ {+ HandshakeStatus status = HandshakeProtocolMismatch;+ m_sock->Send( &status, sizeof( status ) );+ m_sock->~Socket();+ tracy_free( m_sock );+ m_sock = nullptr;+ continue;+ }+ }++#ifdef TRACY_ON_DEMAND+ const auto currentTime = GetTime();+ ClearQueues( token );+ m_connectionId.fetch_add( 1, std::memory_order_release );+#endif+ m_isConnected.store( true, std::memory_order_release );+ InstallCrashHandler();++ HandshakeStatus handshake = HandshakeWelcome;+ m_sock->Send( &handshake, sizeof( handshake ) );++ LZ4_resetStream( (LZ4_stream_t*)m_stream );+ m_sock->Send( &welcome, sizeof( welcome ) );++ m_threadCtx = 0;+ m_refTimeSerial = 0;+ m_refTimeCtx = 0;+ m_refTimeGpu = 0;++#ifdef TRACY_ON_DEMAND+ OnDemandPayloadMessage onDemand;+ onDemand.frames = m_frameCount.load( std::memory_order_relaxed );+ onDemand.currentTime = currentTime;++ m_sock->Send( &onDemand, sizeof( onDemand ) );++ m_deferredLock.lock();+ for( auto& item : m_deferredQueue )+ {+ uint64_t ptr;+ uint16_t size;+ const auto idx = MemRead<uint8_t>( &item.hdr.idx );+ switch( (QueueType)idx )+ {+ case QueueType::MessageAppInfo:+ ptr = MemRead<uint64_t>( &item.messageFat.text );+ size = MemRead<uint16_t>( &item.messageFat.size );+ SendSingleString( (const char*)ptr, size );+ break;+ case QueueType::LockName:+ ptr = MemRead<uint64_t>( &item.lockNameFat.name );+ size = MemRead<uint16_t>( &item.lockNameFat.size );+ SendSingleString( (const char*)ptr, size );+ break;+ case QueueType::GpuContextName:+ ptr = MemRead<uint64_t>( &item.gpuContextNameFat.ptr );+ size = MemRead<uint16_t>( &item.gpuContextNameFat.size );+ SendSingleString( (const char*)ptr, size );+ break;+ default:+ break;+ }+ AppendData( &item, QueueDataSize[idx] );+ }+ m_deferredLock.unlock();+#endif++ // Main communications loop+ int keepAlive = 0;+ for(;;)+ {+ ProcessSysTime();+#ifdef TRACY_HAS_SYSPOWER+ m_sysPower.Tick();+#endif+ const auto status = Dequeue( token );+ const auto serialStatus = DequeueSerial();+ if( status == DequeueStatus::ConnectionLost || serialStatus == DequeueStatus::ConnectionLost )+ {+ break;+ }+ else if( status == DequeueStatus::QueueEmpty && serialStatus == DequeueStatus::QueueEmpty )+ {+ if( ShouldExit() ) break;+ if( m_bufferOffset != m_bufferStart )+ {+ if( !CommitData() ) break;+ }+ if( keepAlive == 500 )+ {+ QueueItem ka;+ ka.hdr.type = QueueType::KeepAlive;+ AppendData( &ka, QueueDataSize[ka.hdr.idx] );+ if( !CommitData() ) break;++ keepAlive = 0;+ }+ else if( !m_sock->HasData() )+ {+ keepAlive++;+ std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );+ }+ }+ else+ {+ keepAlive = 0;+ }++ bool connActive = true;+ while( m_sock->HasData() )+ {+ connActive = HandleServerQuery();+ if( !connActive ) break;+ }+ if( !connActive ) break;+ }+ if( ShouldExit() ) break;++ m_isConnected.store( false, std::memory_order_release );+ RemoveCrashHandler();++#ifdef TRACY_ON_DEMAND+ m_bufferOffset = 0;+ m_bufferStart = 0;+#endif++ m_sock->~Socket();+ tracy_free( m_sock );+ m_sock = nullptr;++#ifndef TRACY_ON_DEMAND+ // Client is no longer available here. Accept incoming connections, but reject handshake.+ for(;;)+ {+ if( ShouldExit() )+ {+ m_shutdownFinished.store( true, std::memory_order_relaxed );+ return;+ }++ ClearQueues( token );++ m_sock = listen.Accept();+ if( m_sock )+ {+ char shibboleth[HandshakeShibbolethSize];+ auto res = m_sock->ReadRaw( shibboleth, HandshakeShibbolethSize, 1000 );+ if( !res || memcmp( shibboleth, HandshakeShibboleth, HandshakeShibbolethSize ) != 0 )+ {+ m_sock->~Socket();+ tracy_free( m_sock );+ m_sock = nullptr;+ continue;+ }++ uint32_t protocolVersion;+ res = m_sock->ReadRaw( &protocolVersion, sizeof( protocolVersion ), 1000 );+ if( !res )+ {+ m_sock->~Socket();+ tracy_free( m_sock );+ m_sock = nullptr;+ continue;+ }++ HandshakeStatus status = HandshakeNotAvailable;+ m_sock->Send( &status, sizeof( status ) );+ m_sock->~Socket();+ tracy_free( m_sock );+ }+ }+#endif+ }+ // End of connections loop++ // Wait for symbols thread to terminate. Symbol resolution will continue in this thread.+#ifdef TRACY_HAS_CALLSTACK+ while( s_symbolThreadGone.load() == false ) { YieldThread(); }+#endif++ // Client is exiting. Send items remaining in queues.+ for(;;)+ {+ const auto status = Dequeue( token );+ const auto serialStatus = DequeueSerial();+ if( status == DequeueStatus::ConnectionLost || serialStatus == DequeueStatus::ConnectionLost )+ {+ m_shutdownFinished.store( true, std::memory_order_relaxed );+ return;+ }+ else if( status == DequeueStatus::QueueEmpty && serialStatus == DequeueStatus::QueueEmpty )+ {+ if( m_bufferOffset != m_bufferStart ) CommitData();+ break;+ }++ while( m_sock->HasData() )+ {+ if( !HandleServerQuery() )+ {+ m_shutdownFinished.store( true, std::memory_order_relaxed );+ return;+ }+ }++#ifdef TRACY_HAS_CALLSTACK+ for(;;)+ {+ auto si = m_symbolQueue.front();+ if( !si ) break;+ HandleSymbolQueueItem( *si );+ m_symbolQueue.pop();+ }+#endif+ }++ // Send client termination notice to the server+ QueueItem terminate;+ MemWrite( &terminate.hdr.type, QueueType::Terminate );+ if( !SendData( (const char*)&terminate, 1 ) )+ {+ m_shutdownFinished.store( true, std::memory_order_relaxed );+ return;+ }+ // Handle remaining server queries+ for(;;)+ {+ while( m_sock->HasData() )+ {+ if( !HandleServerQuery() )+ {+ m_shutdownFinished.store( true, std::memory_order_relaxed );+ return;+ }+ }+#ifdef TRACY_HAS_CALLSTACK+ for(;;)+ {+ auto si = m_symbolQueue.front();+ if( !si ) break;+ HandleSymbolQueueItem( *si );+ m_symbolQueue.pop();+ }+#endif+ const auto status = Dequeue( token );+ const auto serialStatus = DequeueSerial();+ if( status == DequeueStatus::ConnectionLost || serialStatus == DequeueStatus::ConnectionLost )+ {+ m_shutdownFinished.store( true, std::memory_order_relaxed );+ return;+ }+ if( m_bufferOffset != m_bufferStart )+ {+ if( !CommitData() )+ {+ m_shutdownFinished.store( true, std::memory_order_relaxed );+ return;+ }+ }+ }+}++#ifndef TRACY_NO_FRAME_IMAGE+void Profiler::CompressWorker()+{+ ThreadExitHandler threadExitHandler;+ SetThreadName( "Tracy DXT1" );+ while( m_timeBegin.load( std::memory_order_relaxed ) == 0 ) std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );++#ifdef TRACY_USE_RPMALLOC+ rpmalloc_thread_initialize();+#endif++ for(;;)+ {+ const auto shouldExit = ShouldExit();++ {+ bool lockHeld = true;+ while( !m_fiLock.try_lock() )+ {+ if( m_shutdownManual.load( std::memory_order_relaxed ) )+ {+ lockHeld = false;+ break;+ }+ }+ if( !m_fiQueue.empty() ) m_fiQueue.swap( m_fiDequeue );+ if( lockHeld )+ {+ m_fiLock.unlock();+ }+ }++ const auto sz = m_fiDequeue.size();+ if( sz > 0 )+ {+ auto fi = m_fiDequeue.data();+ auto end = fi + sz;+ while( fi != end )+ {+ const auto w = fi->w;+ const auto h = fi->h;+ const auto csz = size_t( w * h / 2 );+ auto etc1buf = (char*)tracy_malloc( csz );+ CompressImageDxt1( (const char*)fi->image, etc1buf, w, h );+ tracy_free( fi->image );++ TracyLfqPrepare( QueueType::FrameImage );+ MemWrite( &item->frameImageFat.image, (uint64_t)etc1buf );+ MemWrite( &item->frameImageFat.frame, fi->frame );+ MemWrite( &item->frameImageFat.w, w );+ MemWrite( &item->frameImageFat.h, h );+ uint8_t flip = fi->flip;+ MemWrite( &item->frameImageFat.flip, flip );+ TracyLfqCommit;++ fi++;+ }+ m_fiDequeue.clear();+ }+ else+ {+ std::this_thread::sleep_for( std::chrono::milliseconds( 20 ) );+ }++ if( shouldExit )+ {+ return;+ }+ }+}+#endif++static void FreeAssociatedMemory( const QueueItem& item )+{+ if( item.hdr.idx >= (int)QueueType::Terminate ) return;++ uint64_t ptr;+ switch( item.hdr.type )+ {+ case QueueType::ZoneText:+ case QueueType::ZoneName:+ ptr = MemRead<uint64_t>( &item.zoneTextFat.text );+ tracy_free( (void*)ptr );+ break;+ case QueueType::MessageColor:+ case QueueType::MessageColorCallstack:+ ptr = MemRead<uint64_t>( &item.messageColorFat.text );+ tracy_free( (void*)ptr );+ break;+ case QueueType::Message:+ case QueueType::MessageCallstack:+#ifndef TRACY_ON_DEMAND+ case QueueType::MessageAppInfo:+#endif+ ptr = MemRead<uint64_t>( &item.messageFat.text );+ tracy_free( (void*)ptr );+ break;+ case QueueType::ZoneBeginAllocSrcLoc:+ case QueueType::ZoneBeginAllocSrcLocCallstack:+ ptr = MemRead<uint64_t>( &item.zoneBegin.srcloc );+ tracy_free( (void*)ptr );+ break;+ case QueueType::GpuZoneBeginAllocSrcLoc:+ case QueueType::GpuZoneBeginAllocSrcLocCallstack:+ case QueueType::GpuZoneBeginAllocSrcLocSerial:+ case QueueType::GpuZoneBeginAllocSrcLocCallstackSerial:+ ptr = MemRead<uint64_t>( &item.gpuZoneBegin.srcloc );+ tracy_free( (void*)ptr );+ break;+ case QueueType::CallstackSerial:+ case QueueType::Callstack:+ ptr = MemRead<uint64_t>( &item.callstackFat.ptr );+ tracy_free( (void*)ptr );+ break;+ case QueueType::CallstackAlloc:+ ptr = MemRead<uint64_t>( &item.callstackAllocFat.nativePtr );+ tracy_free( (void*)ptr );+ ptr = MemRead<uint64_t>( &item.callstackAllocFat.ptr );+ tracy_free( (void*)ptr );+ break;+ case QueueType::CallstackSample:+ case QueueType::CallstackSampleContextSwitch:+ ptr = MemRead<uint64_t>( &item.callstackSampleFat.ptr );+ tracy_free( (void*)ptr );+ break;+ case QueueType::FrameImage:+ ptr = MemRead<uint64_t>( &item.frameImageFat.image );+ tracy_free( (void*)ptr );+ break;+#ifdef TRACY_HAS_CALLSTACK+ case QueueType::CallstackFrameSize:+ {+ InitRpmalloc();+ auto size = MemRead<uint8_t>( &item.callstackFrameSizeFat.size );+ auto data = (const CallstackEntry*)MemRead<uint64_t>( &item.callstackFrameSizeFat.data );+ for( uint8_t i=0; i<size; i++ )+ {+ const auto& frame = data[i];+ tracy_free_fast( (void*)frame.name );+ tracy_free_fast( (void*)frame.file );+ }+ tracy_free_fast( (void*)data );+ break;+ }+ case QueueType::SymbolInformation:+ {+ uint8_t needFree = MemRead<uint8_t>( &item.symbolInformationFat.needFree );+ if( needFree )+ {+ ptr = MemRead<uint64_t>( &item.symbolInformationFat.fileString );+ tracy_free( (void*)ptr );+ }+ break;+ }+ case QueueType::SymbolCodeMetadata:+ ptr = MemRead<uint64_t>( &item.symbolCodeMetadata.ptr );+ tracy_free( (void*)ptr );+ break;+#endif+#ifndef TRACY_ON_DEMAND+ case QueueType::LockName:+ ptr = MemRead<uint64_t>( &item.lockNameFat.name );+ tracy_free( (void*)ptr );+ break;+ case QueueType::GpuContextName:+ ptr = MemRead<uint64_t>( &item.gpuContextNameFat.ptr );+ tracy_free( (void*)ptr );+ break;+#endif+#ifdef TRACY_ON_DEMAND+ case QueueType::MessageAppInfo:+ case QueueType::GpuContextName:+ // Don't free memory associated with deferred messages.+ break;+#endif+#ifdef TRACY_HAS_SYSTEM_TRACING+ case QueueType::ExternalNameMetadata:+ ptr = MemRead<uint64_t>( &item.externalNameMetadata.name );+ tracy_free( (void*)ptr );+ ptr = MemRead<uint64_t>( &item.externalNameMetadata.threadName );+ tracy_free_fast( (void*)ptr );+ break;+#endif+ case QueueType::SourceCodeMetadata:+ ptr = MemRead<uint64_t>( &item.sourceCodeMetadata.ptr );+ tracy_free( (void*)ptr );+ break;+ default:+ break;+ }+}++void Profiler::ClearQueues( moodycamel::ConsumerToken& token )+{+ for(;;)+ {+ const auto sz = GetQueue().try_dequeue_bulk_single( token, [](const uint64_t&){}, []( QueueItem* item, size_t sz ) { assert( sz > 0 ); while( sz-- > 0 ) FreeAssociatedMemory( *item++ ); } );+ if( sz == 0 ) break;+ }++ ClearSerial();+}++void Profiler::ClearSerial()+{+ bool lockHeld = true;+ while( !m_serialLock.try_lock() )+ {+ if( m_shutdownManual.load( std::memory_order_relaxed ) )+ {+ lockHeld = false;+ break;+ }+ }+ for( auto& v : m_serialQueue ) FreeAssociatedMemory( v );+ m_serialQueue.clear();+ if( lockHeld )+ {+ m_serialLock.unlock();+ }++ for( auto& v : m_serialDequeue ) FreeAssociatedMemory( v );+ m_serialDequeue.clear();+}++Profiler::DequeueStatus Profiler::Dequeue( moodycamel::ConsumerToken& token )+{+ bool connectionLost = false;+ const auto sz = GetQueue().try_dequeue_bulk_single( token,+ [this, &connectionLost] ( const uint32_t& threadId )+ {+ if( ThreadCtxCheck( threadId ) == ThreadCtxStatus::ConnectionLost ) connectionLost = true;+ },+ [this, &connectionLost] ( QueueItem* item, size_t sz )+ {+ if( connectionLost ) return;+ InitRpmalloc();+ assert( sz > 0 );+ int64_t refThread = m_refTimeThread;+ int64_t refCtx = m_refTimeCtx;+ int64_t refGpu = m_refTimeGpu;+ while( sz-- > 0 )+ {+ uint64_t ptr;+ uint16_t size;+ auto idx = MemRead<uint8_t>( &item->hdr.idx );+ if( idx < (int)QueueType::Terminate )+ {+ switch( (QueueType)idx )+ {+ case QueueType::ZoneText:+ case QueueType::ZoneName:+ ptr = MemRead<uint64_t>( &item->zoneTextFat.text );+ size = MemRead<uint16_t>( &item->zoneTextFat.size );+ SendSingleString( (const char*)ptr, size );+ tracy_free_fast( (void*)ptr );+ break;+ case QueueType::Message:+ case QueueType::MessageCallstack:+ ptr = MemRead<uint64_t>( &item->messageFat.text );+ size = MemRead<uint16_t>( &item->messageFat.size );+ SendSingleString( (const char*)ptr, size );+ tracy_free_fast( (void*)ptr );+ break;+ case QueueType::MessageColor:+ case QueueType::MessageColorCallstack:+ ptr = MemRead<uint64_t>( &item->messageColorFat.text );+ size = MemRead<uint16_t>( &item->messageColorFat.size );+ SendSingleString( (const char*)ptr, size );+ tracy_free_fast( (void*)ptr );+ break;+ case QueueType::MessageAppInfo:+ ptr = MemRead<uint64_t>( &item->messageFat.text );+ size = MemRead<uint16_t>( &item->messageFat.size );+ SendSingleString( (const char*)ptr, size );+#ifndef TRACY_ON_DEMAND+ tracy_free_fast( (void*)ptr );+#endif+ break;+ case QueueType::ZoneBeginAllocSrcLoc:+ case QueueType::ZoneBeginAllocSrcLocCallstack:+ {+ int64_t t = MemRead<int64_t>( &item->zoneBegin.time );+ int64_t dt = t - refThread;+ refThread = t;+ MemWrite( &item->zoneBegin.time, dt );+ ptr = MemRead<uint64_t>( &item->zoneBegin.srcloc );+ SendSourceLocationPayload( ptr );+ tracy_free_fast( (void*)ptr );+ break;+ }+ case QueueType::Callstack:+ ptr = MemRead<uint64_t>( &item->callstackFat.ptr );+ SendCallstackPayload( ptr );+ tracy_free_fast( (void*)ptr );+ break;+ case QueueType::CallstackAlloc:+ ptr = MemRead<uint64_t>( &item->callstackAllocFat.nativePtr );+ if( ptr != 0 )+ {+ CutCallstack( (void*)ptr, "lua_pcall" );+ SendCallstackPayload( ptr );+ tracy_free_fast( (void*)ptr );+ }+ ptr = MemRead<uint64_t>( &item->callstackAllocFat.ptr );+ SendCallstackAlloc( ptr );+ tracy_free_fast( (void*)ptr );+ break;+ case QueueType::CallstackSample:+ case QueueType::CallstackSampleContextSwitch:+ {+ ptr = MemRead<uint64_t>( &item->callstackSampleFat.ptr );+ SendCallstackPayload64( ptr );+ tracy_free_fast( (void*)ptr );+ int64_t t = MemRead<int64_t>( &item->callstackSampleFat.time );+ int64_t dt = t - refCtx;+ refCtx = t;+ MemWrite( &item->callstackSampleFat.time, dt );+ break;+ }+ case QueueType::FrameImage:+ {+ ptr = MemRead<uint64_t>( &item->frameImageFat.image );+ const auto w = MemRead<uint16_t>( &item->frameImageFat.w );+ const auto h = MemRead<uint16_t>( &item->frameImageFat.h );+ const auto csz = size_t( w * h / 2 );+ SendLongString( ptr, (const char*)ptr, csz, QueueType::FrameImageData );+ tracy_free_fast( (void*)ptr );+ break;+ }+ case QueueType::ZoneBegin:+ case QueueType::ZoneBeginCallstack:+ {+ int64_t t = MemRead<int64_t>( &item->zoneBegin.time );+ int64_t dt = t - refThread;+ refThread = t;+ MemWrite( &item->zoneBegin.time, dt );+ break;+ }+ case QueueType::ZoneEnd:+ {+ int64_t t = MemRead<int64_t>( &item->zoneEnd.time );+ int64_t dt = t - refThread;+ refThread = t;+ MemWrite( &item->zoneEnd.time, dt );+ break;+ }+ case QueueType::GpuZoneBegin:+ case QueueType::GpuZoneBeginCallstack:+ {+ int64_t t = MemRead<int64_t>( &item->gpuZoneBegin.cpuTime );+ int64_t dt = t - refThread;+ refThread = t;+ MemWrite( &item->gpuZoneBegin.cpuTime, dt );+ break;+ }+ case QueueType::GpuZoneBeginAllocSrcLoc:+ case QueueType::GpuZoneBeginAllocSrcLocCallstack:+ {+ int64_t t = MemRead<int64_t>( &item->gpuZoneBegin.cpuTime );+ int64_t dt = t - refThread;+ refThread = t;+ MemWrite( &item->gpuZoneBegin.cpuTime, dt );+ ptr = MemRead<uint64_t>( &item->gpuZoneBegin.srcloc );+ SendSourceLocationPayload( ptr );+ tracy_free_fast( (void*)ptr );+ break;+ }+ case QueueType::GpuZoneEnd:+ {+ int64_t t = MemRead<int64_t>( &item->gpuZoneEnd.cpuTime );+ int64_t dt = t - refThread;+ refThread = t;+ MemWrite( &item->gpuZoneEnd.cpuTime, dt );+ break;+ }+ case QueueType::GpuContextName:+ ptr = MemRead<uint64_t>( &item->gpuContextNameFat.ptr );+ size = MemRead<uint16_t>( &item->gpuContextNameFat.size );+ SendSingleString( (const char*)ptr, size );+#ifndef TRACY_ON_DEMAND+ tracy_free_fast( (void*)ptr );+#endif+ break;+ case QueueType::PlotDataInt:+ case QueueType::PlotDataFloat:+ case QueueType::PlotDataDouble:+ {+ int64_t t = MemRead<int64_t>( &item->plotDataInt.time );+ int64_t dt = t - refThread;+ refThread = t;+ MemWrite( &item->plotDataInt.time, dt );+ break;+ }+ case QueueType::ContextSwitch:+ {+ int64_t t = MemRead<int64_t>( &item->contextSwitch.time );+ int64_t dt = t - refCtx;+ refCtx = t;+ MemWrite( &item->contextSwitch.time, dt );+ break;+ }+ case QueueType::ThreadWakeup:+ {+ int64_t t = MemRead<int64_t>( &item->threadWakeup.time );+ int64_t dt = t - refCtx;+ refCtx = t;+ MemWrite( &item->threadWakeup.time, dt );+ break;+ }+ case QueueType::GpuTime:+ {+ int64_t t = MemRead<int64_t>( &item->gpuTime.gpuTime );+ int64_t dt = t - refGpu;+ refGpu = t;+ MemWrite( &item->gpuTime.gpuTime, dt );+ break;+ }+#ifdef TRACY_HAS_CALLSTACK+ case QueueType::CallstackFrameSize:+ {+ auto data = (const CallstackEntry*)MemRead<uint64_t>( &item->callstackFrameSizeFat.data );+ auto datasz = MemRead<uint8_t>( &item->callstackFrameSizeFat.size );+ auto imageName = (const char*)MemRead<uint64_t>( &item->callstackFrameSizeFat.imageName );+ SendSingleString( imageName );+ AppendData( item++, QueueDataSize[idx] );++ for( uint8_t i=0; i<datasz; i++ )+ {+ const auto& frame = data[i];++ SendSingleString( frame.name );+ SendSecondString( frame.file );++ QueueItem item;+ MemWrite( &item.hdr.type, QueueType::CallstackFrame );+ MemWrite( &item.callstackFrame.line, frame.line );+ MemWrite( &item.callstackFrame.symAddr, frame.symAddr );+ MemWrite( &item.callstackFrame.symLen, frame.symLen );++ AppendData( &item, QueueDataSize[(int)QueueType::CallstackFrame] );++ tracy_free_fast( (void*)frame.name );+ tracy_free_fast( (void*)frame.file );+ }+ tracy_free_fast( (void*)data );+ continue;+ }+ case QueueType::SymbolInformation:+ {+ auto fileString = (const char*)MemRead<uint64_t>( &item->symbolInformationFat.fileString );+ auto needFree = MemRead<uint8_t>( &item->symbolInformationFat.needFree );+ SendSingleString( fileString );+ if( needFree ) tracy_free_fast( (void*)fileString );+ break;+ }+ case QueueType::SymbolCodeMetadata:+ {+ auto symbol = MemRead<uint64_t>( &item->symbolCodeMetadata.symbol );+ auto ptr = (const char*)MemRead<uint64_t>( &item->symbolCodeMetadata.ptr );+ auto size = MemRead<uint32_t>( &item->symbolCodeMetadata.size );+ SendLongString( symbol, ptr, size, QueueType::SymbolCode );+ tracy_free_fast( (void*)ptr );+ ++item;+ continue;+ }+#endif+#ifdef TRACY_HAS_SYSTEM_TRACING+ case QueueType::ExternalNameMetadata:+ {+ auto thread = MemRead<uint64_t>( &item->externalNameMetadata.thread );+ auto name = (const char*)MemRead<uint64_t>( &item->externalNameMetadata.name );+ auto threadName = (const char*)MemRead<uint64_t>( &item->externalNameMetadata.threadName );+ SendString( thread, threadName, QueueType::ExternalThreadName );+ SendString( thread, name, QueueType::ExternalName );+ tracy_free_fast( (void*)threadName );+ tracy_free_fast( (void*)name );+ ++item;+ continue;+ }+#endif+ case QueueType::SourceCodeMetadata:+ {+ auto ptr = (const char*)MemRead<uint64_t>( &item->sourceCodeMetadata.ptr );+ auto size = MemRead<uint32_t>( &item->sourceCodeMetadata.size );+ auto id = MemRead<uint32_t>( &item->sourceCodeMetadata.id );+ SendLongString( (uint64_t)id, ptr, size, QueueType::SourceCode );+ tracy_free_fast( (void*)ptr );+ ++item;+ continue;+ }+ default:+ assert( false );+ break;+ }+ }+ if( !AppendData( item++, QueueDataSize[idx] ) )+ {+ connectionLost = true;+ m_refTimeThread = refThread;+ m_refTimeCtx = refCtx;+ m_refTimeGpu = refGpu;+ return;+ }+ }+ m_refTimeThread = refThread;+ m_refTimeCtx = refCtx;+ m_refTimeGpu = refGpu;+ }+ );+ if( connectionLost ) return DequeueStatus::ConnectionLost;+ return sz > 0 ? DequeueStatus::DataDequeued : DequeueStatus::QueueEmpty;+}++Profiler::DequeueStatus Profiler::DequeueContextSwitches( tracy::moodycamel::ConsumerToken& token, int64_t& timeStop )+{+ const auto sz = GetQueue().try_dequeue_bulk_single( token, [] ( const uint64_t& ) {},+ [this, &timeStop] ( QueueItem* item, size_t sz )+ {+ assert( sz > 0 );+ int64_t refCtx = m_refTimeCtx;+ while( sz-- > 0 )+ {+ FreeAssociatedMemory( *item );+ if( timeStop < 0 ) return;+ const auto idx = MemRead<uint8_t>( &item->hdr.idx );+ if( idx == (uint8_t)QueueType::ContextSwitch )+ {+ const auto csTime = MemRead<int64_t>( &item->contextSwitch.time );+ if( csTime > timeStop )+ {+ timeStop = -1;+ m_refTimeCtx = refCtx;+ return;+ }+ int64_t dt = csTime - refCtx;+ refCtx = csTime;+ MemWrite( &item->contextSwitch.time, dt );+ if( !AppendData( item, QueueDataSize[(int)QueueType::ContextSwitch] ) )+ {+ timeStop = -2;+ m_refTimeCtx = refCtx;+ return;+ }+ }+ else if( idx == (uint8_t)QueueType::ThreadWakeup )+ {+ const auto csTime = MemRead<int64_t>( &item->threadWakeup.time );+ if( csTime > timeStop )+ {+ timeStop = -1;+ m_refTimeCtx = refCtx;+ return;+ }+ int64_t dt = csTime - refCtx;+ refCtx = csTime;+ MemWrite( &item->threadWakeup.time, dt );+ if( !AppendData( item, QueueDataSize[(int)QueueType::ThreadWakeup] ) )+ {+ timeStop = -2;+ m_refTimeCtx = refCtx;+ return;+ }+ }+ item++;+ }+ m_refTimeCtx = refCtx;+ }+ );++ if( timeStop == -2 ) return DequeueStatus::ConnectionLost;+ return ( timeStop == -1 || sz > 0 ) ? DequeueStatus::DataDequeued : DequeueStatus::QueueEmpty;+}++#define ThreadCtxCheckSerial( _name ) \+ uint32_t thread = MemRead<uint32_t>( &item->_name.thread ); \+ switch( ThreadCtxCheck( thread ) ) \+ { \+ case ThreadCtxStatus::Same: break; \+ case ThreadCtxStatus::Changed: assert( m_refTimeThread == 0 ); refThread = 0; break; \+ case ThreadCtxStatus::ConnectionLost: return DequeueStatus::ConnectionLost; \+ default: assert( false ); break; \+ }++Profiler::DequeueStatus Profiler::DequeueSerial()+{+ {+ bool lockHeld = true;+ while( !m_serialLock.try_lock() )+ {+ if( m_shutdownManual.load( std::memory_order_relaxed ) )+ {+ lockHeld = false;+ break;+ }+ }+ if( !m_serialQueue.empty() ) m_serialQueue.swap( m_serialDequeue );+ if( lockHeld )+ {+ m_serialLock.unlock();+ }+ }++ const auto sz = m_serialDequeue.size();+ if( sz > 0 )+ {+ InitRpmalloc();+ int64_t refSerial = m_refTimeSerial;+ int64_t refGpu = m_refTimeGpu;+#ifdef TRACY_FIBERS+ int64_t refThread = m_refTimeThread;+#endif+ auto item = m_serialDequeue.data();+ auto end = item + sz;+ while( item != end )+ {+ uint64_t ptr;+ auto idx = MemRead<uint8_t>( &item->hdr.idx );+ if( idx < (int)QueueType::Terminate )+ {+ switch( (QueueType)idx )+ {+ case QueueType::CallstackSerial:+ ptr = MemRead<uint64_t>( &item->callstackFat.ptr );+ SendCallstackPayload( ptr );+ tracy_free_fast( (void*)ptr );+ break;+ case QueueType::LockWait:+ case QueueType::LockSharedWait:+ {+ int64_t t = MemRead<int64_t>( &item->lockWait.time );+ int64_t dt = t - refSerial;+ refSerial = t;+ MemWrite( &item->lockWait.time, dt );+ break;+ }+ case QueueType::LockObtain:+ case QueueType::LockSharedObtain:+ {+ int64_t t = MemRead<int64_t>( &item->lockObtain.time );+ int64_t dt = t - refSerial;+ refSerial = t;+ MemWrite( &item->lockObtain.time, dt );+ break;+ }+ case QueueType::LockRelease:+ case QueueType::LockSharedRelease:+ {+ int64_t t = MemRead<int64_t>( &item->lockRelease.time );+ int64_t dt = t - refSerial;+ refSerial = t;+ MemWrite( &item->lockRelease.time, dt );+ break;+ }+ case QueueType::LockName:+ {+ ptr = MemRead<uint64_t>( &item->lockNameFat.name );+ uint16_t size = MemRead<uint16_t>( &item->lockNameFat.size );+ SendSingleString( (const char*)ptr, size );+#ifndef TRACY_ON_DEMAND+ tracy_free_fast( (void*)ptr );+#endif+ break;+ }+ case QueueType::MemAlloc:+ case QueueType::MemAllocNamed:+ case QueueType::MemAllocCallstack:+ case QueueType::MemAllocCallstackNamed:+ {+ int64_t t = MemRead<int64_t>( &item->memAlloc.time );+ int64_t dt = t - refSerial;+ refSerial = t;+ MemWrite( &item->memAlloc.time, dt );+ break;+ }+ case QueueType::MemFree:+ case QueueType::MemFreeNamed:+ case QueueType::MemFreeCallstack:+ case QueueType::MemFreeCallstackNamed:+ {+ int64_t t = MemRead<int64_t>( &item->memFree.time );+ int64_t dt = t - refSerial;+ refSerial = t;+ MemWrite( &item->memFree.time, dt );+ break;+ }+ case QueueType::MemDiscard:+ case QueueType::MemDiscardCallstack:+ {+ int64_t t = MemRead<int64_t>( &item->memDiscard.time );+ int64_t dt = t - refSerial;+ refSerial = t;+ MemWrite( &item->memDiscard.time, dt );+ break;+ }+ case QueueType::GpuZoneBeginSerial:+ case QueueType::GpuZoneBeginCallstackSerial:+ {+ int64_t t = MemRead<int64_t>( &item->gpuZoneBegin.cpuTime );+ int64_t dt = t - refSerial;+ refSerial = t;+ MemWrite( &item->gpuZoneBegin.cpuTime, dt );+ break;+ }+ case QueueType::GpuZoneBeginAllocSrcLocSerial:+ case QueueType::GpuZoneBeginAllocSrcLocCallstackSerial:+ {+ int64_t t = MemRead<int64_t>( &item->gpuZoneBegin.cpuTime );+ int64_t dt = t - refSerial;+ refSerial = t;+ MemWrite( &item->gpuZoneBegin.cpuTime, dt );+ ptr = MemRead<uint64_t>( &item->gpuZoneBegin.srcloc );+ SendSourceLocationPayload( ptr );+ tracy_free_fast( (void*)ptr );+ break;+ }+ case QueueType::GpuZoneEndSerial:+ {+ int64_t t = MemRead<int64_t>( &item->gpuZoneEnd.cpuTime );+ int64_t dt = t - refSerial;+ refSerial = t;+ MemWrite( &item->gpuZoneEnd.cpuTime, dt );+ break;+ }+ case QueueType::GpuTime:+ {+ int64_t t = MemRead<int64_t>( &item->gpuTime.gpuTime );+ int64_t dt = t - refGpu;+ refGpu = t;+ MemWrite( &item->gpuTime.gpuTime, dt );+ break;+ }+ case QueueType::GpuContextName:+ {+ ptr = MemRead<uint64_t>( &item->gpuContextNameFat.ptr );+ uint16_t size = MemRead<uint16_t>( &item->gpuContextNameFat.size );+ SendSingleString( (const char*)ptr, size );+#ifndef TRACY_ON_DEMAND+ tracy_free_fast( (void*)ptr );+#endif+ break;+ }+#ifdef TRACY_FIBERS+ case QueueType::ZoneBegin:+ case QueueType::ZoneBeginCallstack:+ {+ ThreadCtxCheckSerial( zoneBeginThread );+ int64_t t = MemRead<int64_t>( &item->zoneBegin.time );+ int64_t dt = t - refThread;+ refThread = t;+ MemWrite( &item->zoneBegin.time, dt );+ break;+ }+ case QueueType::ZoneBeginAllocSrcLoc:+ case QueueType::ZoneBeginAllocSrcLocCallstack:+ {+ ThreadCtxCheckSerial( zoneBeginThread );+ int64_t t = MemRead<int64_t>( &item->zoneBegin.time );+ int64_t dt = t - refThread;+ refThread = t;+ MemWrite( &item->zoneBegin.time, dt );+ ptr = MemRead<uint64_t>( &item->zoneBegin.srcloc );+ SendSourceLocationPayload( ptr );+ tracy_free_fast( (void*)ptr );+ break;+ }+ case QueueType::ZoneEnd:+ {+ ThreadCtxCheckSerial( zoneEndThread );+ int64_t t = MemRead<int64_t>( &item->zoneEnd.time );+ int64_t dt = t - refThread;+ refThread = t;+ MemWrite( &item->zoneEnd.time, dt );+ break;+ }+ case QueueType::ZoneText:+ case QueueType::ZoneName:+ {+ ThreadCtxCheckSerial( zoneTextFatThread );+ ptr = MemRead<uint64_t>( &item->zoneTextFat.text );+ uint16_t size = MemRead<uint16_t>( &item->zoneTextFat.size );+ SendSingleString( (const char*)ptr, size );+ tracy_free_fast( (void*)ptr );+ break;+ }+ case QueueType::Message:+ case QueueType::MessageCallstack:+ {+ ThreadCtxCheckSerial( messageFatThread );+ ptr = MemRead<uint64_t>( &item->messageFat.text );+ uint16_t size = MemRead<uint16_t>( &item->messageFat.size );+ SendSingleString( (const char*)ptr, size );+ tracy_free_fast( (void*)ptr );+ break;+ }+ case QueueType::MessageColor:+ case QueueType::MessageColorCallstack:+ {+ ThreadCtxCheckSerial( messageColorFatThread );+ ptr = MemRead<uint64_t>( &item->messageColorFat.text );+ uint16_t size = MemRead<uint16_t>( &item->messageColorFat.size );+ SendSingleString( (const char*)ptr, size );+ tracy_free_fast( (void*)ptr );+ break;+ }+ case QueueType::Callstack:+ {+ ThreadCtxCheckSerial( callstackFatThread );+ ptr = MemRead<uint64_t>( &item->callstackFat.ptr );+ SendCallstackPayload( ptr );+ tracy_free_fast( (void*)ptr );+ break;+ }+ case QueueType::CallstackAlloc:+ {+ ThreadCtxCheckSerial( callstackAllocFatThread );+ ptr = MemRead<uint64_t>( &item->callstackAllocFat.nativePtr );+ if( ptr != 0 )+ {+ CutCallstack( (void*)ptr, "lua_pcall" );+ SendCallstackPayload( ptr );+ tracy_free_fast( (void*)ptr );+ }+ ptr = MemRead<uint64_t>( &item->callstackAllocFat.ptr );+ SendCallstackAlloc( ptr );+ tracy_free_fast( (void*)ptr );+ break;+ }+ case QueueType::FiberEnter:+ {+ ThreadCtxCheckSerial( fiberEnter );+ int64_t t = MemRead<int64_t>( &item->fiberEnter.time );+ int64_t dt = t - refThread;+ refThread = t;+ MemWrite( &item->fiberEnter.time, dt );+ break;+ }+ case QueueType::FiberLeave:+ {+ ThreadCtxCheckSerial( fiberLeave );+ int64_t t = MemRead<int64_t>( &item->fiberLeave.time );+ int64_t dt = t - refThread;+ refThread = t;+ MemWrite( &item->fiberLeave.time, dt );+ break;+ }+#endif+ default:+ assert( false );+ break;+ }+ }+#ifdef TRACY_FIBERS+ else+ {+ switch( (QueueType)idx )+ {+ case QueueType::ZoneColor:+ {+ ThreadCtxCheckSerial( zoneColorThread );+ break;+ }+ case QueueType::ZoneValue:+ {+ ThreadCtxCheckSerial( zoneValueThread );+ break;+ }+ case QueueType::ZoneValidation:+ {+ ThreadCtxCheckSerial( zoneValidationThread );+ break;+ }+ case QueueType::MessageLiteral:+ case QueueType::MessageLiteralCallstack:+ {+ ThreadCtxCheckSerial( messageLiteralThread );+ break;+ }+ case QueueType::MessageLiteralColor:+ case QueueType::MessageLiteralColorCallstack:+ {+ ThreadCtxCheckSerial( messageColorLiteralThread );+ break;+ }+ case QueueType::CrashReport:+ {+ ThreadCtxCheckSerial( crashReportThread );+ break;+ }+ default:+ break;+ }+ }+#endif+ if( !AppendData( item, QueueDataSize[idx] ) ) return DequeueStatus::ConnectionLost;+ item++;+ }+ m_refTimeSerial = refSerial;+ m_refTimeGpu = refGpu;+#ifdef TRACY_FIBERS+ m_refTimeThread = refThread;+#endif+ m_serialDequeue.clear();+ }+ else+ {+ return DequeueStatus::QueueEmpty;+ }+ return DequeueStatus::DataDequeued;+}++Profiler::ThreadCtxStatus Profiler::ThreadCtxCheck( uint32_t threadId )+{+ if( m_threadCtx == threadId ) return ThreadCtxStatus::Same;+ QueueItem item;+ MemWrite( &item.hdr.type, QueueType::ThreadContext );+ MemWrite( &item.threadCtx.thread, threadId );+ if( !AppendData( &item, QueueDataSize[(int)QueueType::ThreadContext] ) ) return ThreadCtxStatus::ConnectionLost;+ m_threadCtx = threadId;+ m_refTimeThread = 0;+ return ThreadCtxStatus::Changed;+}++bool Profiler::CommitData()+{+ bool ret = SendData( m_buffer + m_bufferStart, m_bufferOffset - m_bufferStart );+ if( m_bufferOffset > TargetFrameSize * 2 ) m_bufferOffset = 0;+ m_bufferStart = m_bufferOffset;+ return ret;+}++char* Profiler::SafeCopyProlog( const char* data, size_t size )+{+ bool success = true;+ char* buf = m_safeSendBuffer;+#ifndef NDEBUG+ assert( !m_inUse.exchange(true) );+#endif++ if( size > SafeSendBufferSize ) buf = (char*)tracy_malloc( size );++#ifdef _WIN32+# ifdef _MSC_VER+ __try+ {+ memcpy( buf, data, size );+ }+ __except( 1 /*EXCEPTION_EXECUTE_HANDLER*/ )+ {+ success = false;+ }+# else+ memcpy( buf, data, size );+# endif+#else+ // Send through the pipe to ensure safe reads+ for( size_t offset = 0; offset != size; /*in loop*/ )+ {+ size_t sendsize = size - offset;+ ssize_t result1, result2;+ while( ( result1 = write( m_pipe[1], data + offset, sendsize ) ) < 0 && errno == EINTR ) { /* retry */ }+ if( result1 < 0 )+ {+ success = false;+ break;+ }+ while( ( result2 = read( m_pipe[0], buf + offset, result1 ) ) < 0 && errno == EINTR ) { /* retry */ }+ if( result2 != result1 )+ {+ success = false;+ break;+ }+ offset += result1;+ }+#endif++ if( success ) return buf;++ SafeCopyEpilog( buf );+ return nullptr;+}++void Profiler::SafeCopyEpilog( char* buf )+{+ if( buf != m_safeSendBuffer ) tracy_free( buf );++#ifndef NDEBUG+ m_inUse.store( false );+#endif+}++bool Profiler::SendData( const char* data, size_t len )+{+ const lz4sz_t lz4sz = LZ4_compress_fast_continue( (LZ4_stream_t*)m_stream, data, m_lz4Buf + sizeof( lz4sz_t ), (int)len, LZ4Size, 1 );+ memcpy( m_lz4Buf, &lz4sz, sizeof( lz4sz ) );+ return m_sock->Send( m_lz4Buf, lz4sz + sizeof( lz4sz_t ) ) != -1;+}++void Profiler::SendString( uint64_t str, const char* ptr, size_t len, QueueType type )+{+ assert( type == QueueType::StringData ||+ type == QueueType::ThreadName ||+ type == QueueType::PlotName ||+ type == QueueType::FrameName ||+ type == QueueType::ExternalName ||+ type == QueueType::ExternalThreadName ||+ type == QueueType::FiberName );++ QueueItem item;+ MemWrite( &item.hdr.type, type );+ MemWrite( &item.stringTransfer.ptr, str );++ assert( len <= std::numeric_limits<uint16_t>::max() );+ auto l16 = uint16_t( len );++ NeedDataSize( QueueDataSize[(int)type] + sizeof( l16 ) + l16 );++ AppendDataUnsafe( &item, QueueDataSize[(int)type] );+ AppendDataUnsafe( &l16, sizeof( l16 ) );+ AppendDataUnsafe( ptr, l16 );+}++void Profiler::SendSingleString( const char* ptr, size_t len )+{+ QueueItem item;+ MemWrite( &item.hdr.type, QueueType::SingleStringData );++ assert( len <= std::numeric_limits<uint16_t>::max() );+ auto l16 = uint16_t( len );++ NeedDataSize( QueueDataSize[(int)QueueType::SingleStringData] + sizeof( l16 ) + l16 );++ AppendDataUnsafe( &item, QueueDataSize[(int)QueueType::SingleStringData] );+ AppendDataUnsafe( &l16, sizeof( l16 ) );+ AppendDataUnsafe( ptr, l16 );+}++void Profiler::SendSecondString( const char* ptr, size_t len )+{+ QueueItem item;+ MemWrite( &item.hdr.type, QueueType::SecondStringData );++ assert( len <= std::numeric_limits<uint16_t>::max() );+ auto l16 = uint16_t( len );++ NeedDataSize( QueueDataSize[(int)QueueType::SecondStringData] + sizeof( l16 ) + l16 );++ AppendDataUnsafe( &item, QueueDataSize[(int)QueueType::SecondStringData] );+ AppendDataUnsafe( &l16, sizeof( l16 ) );+ AppendDataUnsafe( ptr, l16 );+}++void Profiler::SendLongString( uint64_t str, const char* ptr, size_t len, QueueType type )+{+ assert( type == QueueType::FrameImageData ||+ type == QueueType::SymbolCode ||+ type == QueueType::SourceCode );++ QueueItem item;+ MemWrite( &item.hdr.type, type );+ MemWrite( &item.stringTransfer.ptr, str );++ assert( len <= std::numeric_limits<uint32_t>::max() );+ assert( QueueDataSize[(int)type] + sizeof( uint32_t ) + len <= TargetFrameSize );+ auto l32 = uint32_t( len );++ NeedDataSize( QueueDataSize[(int)type] + sizeof( l32 ) + l32 );++ AppendDataUnsafe( &item, QueueDataSize[(int)type] );+ AppendDataUnsafe( &l32, sizeof( l32 ) );+ AppendDataUnsafe( ptr, l32 );+}++void Profiler::SendSourceLocation( uint64_t ptr )+{+ auto srcloc = (const SourceLocationData*)ptr;+ QueueItem item;+ MemWrite( &item.hdr.type, QueueType::SourceLocation );+ MemWrite( &item.srcloc.name, (uint64_t)srcloc->name );+ MemWrite( &item.srcloc.file, (uint64_t)srcloc->file );+ MemWrite( &item.srcloc.function, (uint64_t)srcloc->function );+ MemWrite( &item.srcloc.line, srcloc->line );+ MemWrite( &item.srcloc.b, uint8_t( ( srcloc->color ) & 0xFF ) );+ MemWrite( &item.srcloc.g, uint8_t( ( srcloc->color >> 8 ) & 0xFF ) );+ MemWrite( &item.srcloc.r, uint8_t( ( srcloc->color >> 16 ) & 0xFF ) );+ AppendData( &item, QueueDataSize[(int)QueueType::SourceLocation] );+}++void Profiler::SendSourceLocationPayload( uint64_t _ptr )+{+ auto ptr = (const char*)_ptr;++ QueueItem item;+ MemWrite( &item.hdr.type, QueueType::SourceLocationPayload );+ MemWrite( &item.stringTransfer.ptr, _ptr );++ uint16_t len;+ memcpy( &len, ptr, sizeof( len ) );+ assert( len > 2 );+ len -= 2;+ ptr += 2;++ NeedDataSize( QueueDataSize[(int)QueueType::SourceLocationPayload] + sizeof( len ) + len );++ AppendDataUnsafe( &item, QueueDataSize[(int)QueueType::SourceLocationPayload] );+ AppendDataUnsafe( &len, sizeof( len ) );+ AppendDataUnsafe( ptr, len );+}++void Profiler::SendCallstackPayload( uint64_t _ptr )+{+ auto ptr = (uintptr_t*)_ptr;++ QueueItem item;+ MemWrite( &item.hdr.type, QueueType::CallstackPayload );+ MemWrite( &item.stringTransfer.ptr, _ptr );++ const auto sz = *ptr++;+ const auto len = sz * sizeof( uint64_t );+ const auto l16 = uint16_t( len );++ NeedDataSize( QueueDataSize[(int)QueueType::CallstackPayload] + sizeof( l16 ) + l16 );++ AppendDataUnsafe( &item, QueueDataSize[(int)QueueType::CallstackPayload] );+ AppendDataUnsafe( &l16, sizeof( l16 ) );++ if( compile_time_condition<sizeof( uintptr_t ) == sizeof( uint64_t )>::value )+ {+ AppendDataUnsafe( ptr, sizeof( uint64_t ) * sz );+ }+ else+ {+ for( uintptr_t i=0; i<sz; i++ )+ {+ const auto val = uint64_t( *ptr++ );+ AppendDataUnsafe( &val, sizeof( uint64_t ) );+ }+ }+}++void Profiler::SendCallstackPayload64( uint64_t _ptr )+{+ auto ptr = (uint64_t*)_ptr;++ QueueItem item;+ MemWrite( &item.hdr.type, QueueType::CallstackPayload );+ MemWrite( &item.stringTransfer.ptr, _ptr );++ const auto sz = *ptr++;+ const auto len = sz * sizeof( uint64_t );+ const auto l16 = uint16_t( len );++ NeedDataSize( QueueDataSize[(int)QueueType::CallstackPayload] + sizeof( l16 ) + l16 );++ AppendDataUnsafe( &item, QueueDataSize[(int)QueueType::CallstackPayload] );+ AppendDataUnsafe( &l16, sizeof( l16 ) );+ AppendDataUnsafe( ptr, sizeof( uint64_t ) * sz );+}++void Profiler::SendCallstackAlloc( uint64_t _ptr )+{+ auto ptr = (const char*)_ptr;++ QueueItem item;+ MemWrite( &item.hdr.type, QueueType::CallstackAllocPayload );+ MemWrite( &item.stringTransfer.ptr, _ptr );++ uint16_t len;+ memcpy( &len, ptr, 2 );+ ptr += 2;++ NeedDataSize( QueueDataSize[(int)QueueType::CallstackAllocPayload] + sizeof( len ) + len );++ AppendDataUnsafe( &item, QueueDataSize[(int)QueueType::CallstackAllocPayload] );+ AppendDataUnsafe( &len, sizeof( len ) );+ AppendDataUnsafe( ptr, len );+}++void Profiler::QueueCallstackFrame( uint64_t ptr )+{+#ifdef TRACY_HAS_CALLSTACK+ m_symbolQueue.emplace( SymbolQueueItem { SymbolQueueItemType::CallstackFrame, ptr } );+#else+ AckServerQuery();+#endif+}++void Profiler::QueueSymbolQuery( uint64_t symbol )+{+#ifdef TRACY_HAS_CALLSTACK+ // Special handling for kernel frames+ if( symbol >> 63 != 0 )+ {+ SendSingleString( "<kernel>" );+ QueueItem item;+ MemWrite( &item.hdr.type, QueueType::SymbolInformation );+ MemWrite( &item.symbolInformation.line, 0 );+ MemWrite( &item.symbolInformation.symAddr, symbol );+ AppendData( &item, QueueDataSize[(int)QueueType::SymbolInformation] );+ }+ else+ {+ m_symbolQueue.emplace( SymbolQueueItem { SymbolQueueItemType::SymbolQuery, symbol } );+ }+#else+ AckServerQuery();+#endif+}++void Profiler::QueueExternalName( uint64_t ptr )+{+#ifdef TRACY_HAS_SYSTEM_TRACING+ m_symbolQueue.emplace( SymbolQueueItem { SymbolQueueItemType::ExternalName, ptr } );+#endif+}++void Profiler::QueueKernelCode( uint64_t symbol, uint32_t size )+{+ assert( symbol >> 63 != 0 );+#ifdef TRACY_HAS_CALLSTACK+ m_symbolQueue.emplace( SymbolQueueItem { SymbolQueueItemType::KernelCode, symbol, size } );+#else+ AckSymbolCodeNotAvailable();+#endif+}++void Profiler::QueueSourceCodeQuery( uint32_t id )+{+ assert( m_exectime != 0 );+ assert( m_queryData );+ m_symbolQueue.emplace( SymbolQueueItem { SymbolQueueItemType::SourceCode, uint64_t( m_queryData ), uint64_t( m_queryImage ), id } );+ m_queryData = nullptr;+ m_queryImage = nullptr;+}++#ifdef TRACY_HAS_CALLSTACK+void Profiler::HandleSymbolQueueItem( const SymbolQueueItem& si )+{+ switch( si.type )+ {+ case SymbolQueueItemType::CallstackFrame:+ {+ const auto frameData = DecodeCallstackPtr( si.ptr );+ auto data = tracy_malloc_fast( sizeof( CallstackEntry ) * frameData.size );+ memcpy( data, frameData.data, sizeof( CallstackEntry ) * frameData.size );+ TracyLfqPrepare( QueueType::CallstackFrameSize );+ MemWrite( &item->callstackFrameSizeFat.ptr, si.ptr );+ MemWrite( &item->callstackFrameSizeFat.size, frameData.size );+ MemWrite( &item->callstackFrameSizeFat.data, (uint64_t)data );+ MemWrite( &item->callstackFrameSizeFat.imageName, (uint64_t)frameData.imageName );+ TracyLfqCommit;+ break;+ }+ case SymbolQueueItemType::SymbolQuery:+ {+#ifdef __ANDROID__+ // On Android it's common for code to be in mappings that are only executable+ // but not readable.+ if( !EnsureReadable( si.ptr ) )+ {+ TracyLfqPrepare( QueueType::AckServerQueryNoop );+ TracyLfqCommit;+ break;+ }+#endif+ const auto sym = DecodeSymbolAddress( si.ptr );+ TracyLfqPrepare( QueueType::SymbolInformation );+ MemWrite( &item->symbolInformationFat.line, sym.line );+ MemWrite( &item->symbolInformationFat.symAddr, si.ptr );+ MemWrite( &item->symbolInformationFat.fileString, (uint64_t)sym.file );+ MemWrite( &item->symbolInformationFat.needFree, (uint8_t)sym.needFree );+ TracyLfqCommit;+ break;+ }+#ifdef TRACY_HAS_SYSTEM_TRACING+ case SymbolQueueItemType::ExternalName:+ {+ const char* threadName;+ const char* name;+ SysTraceGetExternalName( si.ptr, threadName, name );+ TracyLfqPrepare( QueueType::ExternalNameMetadata );+ MemWrite( &item->externalNameMetadata.thread, si.ptr );+ MemWrite( &item->externalNameMetadata.name, (uint64_t)name );+ MemWrite( &item->externalNameMetadata.threadName, (uint64_t)threadName );+ TracyLfqCommit;+ break;+ }+#endif+ case SymbolQueueItemType::KernelCode:+ {+#ifdef _WIN32+ auto mod = GetKernelModulePath( si.ptr );+ if( mod )+ {+ auto fn = DecodeCallstackPtrFast( si.ptr );+ if( *fn )+ {+ auto hnd = LoadLibraryExA( mod, nullptr, DONT_RESOLVE_DLL_REFERENCES );+ if( hnd )+ {+ auto ptr = (const void*)GetProcAddress( hnd, fn );+ if( ptr )+ {+ auto buf = (char*)tracy_malloc( si.extra );+ memcpy( buf, ptr, si.extra );+ FreeLibrary( hnd );+ TracyLfqPrepare( QueueType::SymbolCodeMetadata );+ MemWrite( &item->symbolCodeMetadata.symbol, si.ptr );+ MemWrite( &item->symbolCodeMetadata.ptr, (uint64_t)buf );+ MemWrite( &item->symbolCodeMetadata.size, (uint32_t)si.extra );+ TracyLfqCommit;+ break;+ }+ FreeLibrary( hnd );+ }+ }+ }+#elif defined __linux__+ void* data = m_kcore->Retrieve( si.ptr, si.extra );+ if( data )+ {+ TracyLfqPrepare( QueueType::SymbolCodeMetadata );+ MemWrite( &item->symbolCodeMetadata.symbol, si.ptr );+ MemWrite( &item->symbolCodeMetadata.ptr, (uint64_t)data );+ MemWrite( &item->symbolCodeMetadata.size, (uint32_t)si.extra );+ TracyLfqCommit;+ break;+ }+#endif+ TracyLfqPrepare( QueueType::AckSymbolCodeNotAvailable );+ TracyLfqCommit;+ break;+ }+ case SymbolQueueItemType::SourceCode:+ HandleSourceCodeQuery( (char*)si.ptr, (char*)si.extra, si.id );+ break;+ default:+ assert( false );+ break;+ }+}++void Profiler::SymbolWorker()+{+#if defined __linux__ && !defined TRACY_NO_CRASH_HANDLER+ s_symbolTid = syscall( SYS_gettid );+#endif++ ThreadExitHandler threadExitHandler;+ SetThreadName( "Tracy Symbol Worker" );+#ifdef TRACY_USE_RPMALLOC+ InitRpmalloc();+#endif+ InitCallstack();+ while( m_timeBegin.load( std::memory_order_relaxed ) == 0 ) std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );++ for(;;)+ {+ const auto shouldExit = ShouldExit();+#ifdef TRACY_ON_DEMAND+ if( !IsConnected() )+ {+ if( shouldExit )+ {+ s_symbolThreadGone.store( true, std::memory_order_release );+ return;+ }+ while( m_symbolQueue.front() ) m_symbolQueue.pop();+ std::this_thread::sleep_for( std::chrono::milliseconds( 20 ) );+ continue;+ }+#endif+ auto si = m_symbolQueue.front();+ if( si )+ {+ HandleSymbolQueueItem( *si );+ m_symbolQueue.pop();+ }+ else+ {+ if( shouldExit )+ {+ s_symbolThreadGone.store( true, std::memory_order_release );+ return;+ }+ std::this_thread::sleep_for( std::chrono::milliseconds( 20 ) );+ }+ }+}+#endif++bool Profiler::HandleServerQuery()+{+ ServerQueryPacket payload;+ if( !m_sock->Read( &payload, sizeof( payload ), 10 ) ) return false;++ uint8_t type;+ uint64_t ptr;+ memcpy( &type, &payload.type, sizeof( payload.type ) );+ memcpy( &ptr, &payload.ptr, sizeof( payload.ptr ) );++ switch( type )+ {+ case ServerQueryString:+ SendString( ptr, (const char*)ptr, QueueType::StringData );+ break;+ case ServerQueryThreadString:+ if( ptr == m_mainThread )+ {+ SendString( ptr, "Main thread", 11, QueueType::ThreadName );+ }+ else+ {+ auto t = GetThreadNameData( (uint32_t)ptr );+ if( t )+ {+ SendString( ptr, t->name, QueueType::ThreadName );+ if( t->groupHint != 0 )+ {+ TracyLfqPrepare( QueueType::ThreadGroupHint );+ MemWrite( &item->threadGroupHint.thread, (uint32_t)ptr );+ MemWrite( &item->threadGroupHint.groupHint, t->groupHint );+ TracyLfqCommit;+ }+ }+ else+ {+ SendString( ptr, GetThreadName( (uint32_t)ptr ), QueueType::ThreadName );+ }+ }+ break;+ case ServerQuerySourceLocation:+ SendSourceLocation( ptr );+ break;+ case ServerQueryPlotName:+ SendString( ptr, (const char*)ptr, QueueType::PlotName );+ break;+ case ServerQueryTerminate:+ return false;+ case ServerQueryCallstackFrame:+ QueueCallstackFrame( ptr );+ break;+ case ServerQueryFrameName:+ SendString( ptr, (const char*)ptr, QueueType::FrameName );+ break;+ case ServerQueryDisconnect:+ HandleDisconnect();+ return false;+#ifdef TRACY_HAS_SYSTEM_TRACING+ case ServerQueryExternalName:+ QueueExternalName( ptr );+ break;+#endif+ case ServerQueryParameter:+ HandleParameter( ptr );+ break;+ case ServerQuerySymbol:+ QueueSymbolQuery( ptr );+ break;+#ifndef TRACY_NO_CODE_TRANSFER+ case ServerQuerySymbolCode:+ HandleSymbolCodeQuery( ptr, payload.extra );+ break;+#endif+ case ServerQuerySourceCode:+ QueueSourceCodeQuery( uint32_t( ptr ) );+ break;+ case ServerQueryDataTransfer:+ if( m_queryData )+ {+ assert( !m_queryImage );+ m_queryImage = m_queryData;+ }+ m_queryDataPtr = m_queryData = (char*)tracy_malloc( ptr + 11 );+ AckServerQuery();+ break;+ case ServerQueryDataTransferPart:+ memcpy( m_queryDataPtr, &ptr, 8 );+ memcpy( m_queryDataPtr+8, &payload.extra, 4 );+ m_queryDataPtr += 12;+ AckServerQuery();+ break;+#ifdef TRACY_FIBERS+ case ServerQueryFiberName:+ SendString( ptr, (const char*)ptr, QueueType::FiberName );+ break;+#endif+ default:+ assert( false );+ break;+ }++ return true;+}++void Profiler::HandleDisconnect()+{+ moodycamel::ConsumerToken token( GetQueue() );++#ifdef TRACY_HAS_SYSTEM_TRACING+ if( s_sysTraceThread )+ {+ auto timestamp = GetTime();+ for(;;)+ {+ const auto status = DequeueContextSwitches( token, timestamp );+ if( status == DequeueStatus::ConnectionLost )+ {+ return;+ }+ else if( status == DequeueStatus::QueueEmpty )+ {+ if( m_bufferOffset != m_bufferStart )+ {+ if( !CommitData() ) return;+ }+ }+ if( timestamp < 0 )+ {+ if( m_bufferOffset != m_bufferStart )+ {+ if( !CommitData() ) return;+ }+ break;+ }+ ClearSerial();+ if( m_sock->HasData() )+ {+ while( m_sock->HasData() )+ {+ if( !HandleServerQuery() ) return;+ }+ if( m_bufferOffset != m_bufferStart )+ {+ if( !CommitData() ) return;+ }+ }+ else+ {+ if( m_bufferOffset != m_bufferStart )+ {+ if( !CommitData() ) return;+ }+ std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );+ }+ }+ }+#endif++ QueueItem terminate;+ MemWrite( &terminate.hdr.type, QueueType::Terminate );+ if( !SendData( (const char*)&terminate, 1 ) ) return;+ for(;;)+ {+ ClearQueues( token );+ if( m_sock->HasData() )+ {+ while( m_sock->HasData() )+ {+ if( !HandleServerQuery() ) return;+ }+ if( m_bufferOffset != m_bufferStart )+ {+ if( !CommitData() ) return;+ }+ }+ else+ {+ if( m_bufferOffset != m_bufferStart )+ {+ if( !CommitData() ) return;+ }+ std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );+ }+ }+}++void Profiler::CalibrateTimer()+{+ m_timerMul = 1.;++#ifdef TRACY_HW_TIMER++# if !defined TRACY_TIMER_QPC && defined TRACY_TIMER_FALLBACK+ const bool needCalibration = HardwareSupportsInvariantTSC();+# else+ const bool needCalibration = true;+# endif+ if( needCalibration )+ {+ std::atomic_signal_fence( std::memory_order_acq_rel );+ const auto t0 = std::chrono::high_resolution_clock::now();+ const auto r0 = GetTime();+ std::atomic_signal_fence( std::memory_order_acq_rel );+ std::this_thread::sleep_for( std::chrono::milliseconds( 200 ) );+ std::atomic_signal_fence( std::memory_order_acq_rel );+ const auto t1 = std::chrono::high_resolution_clock::now();+ const auto r1 = GetTime();+ std::atomic_signal_fence( std::memory_order_acq_rel );++ const auto dt = std::chrono::duration_cast<std::chrono::nanoseconds>( t1 - t0 ).count();+ const auto dr = r1 - r0;++ m_timerMul = double( dt ) / double( dr );+ }+#endif+}++void Profiler::CalibrateDelay()+{+ constexpr int Iterations = 50000;++ auto mindiff = std::numeric_limits<int64_t>::max();+ for( int i=0; i<Iterations * 10; i++ )+ {+ const auto t0i = GetTime();+ const auto t1i = GetTime();+ const auto dti = t1i - t0i;+ if( dti > 0 && dti < mindiff ) mindiff = dti;+ }+ m_resolution = mindiff;++#ifdef TRACY_DELAYED_INIT+ m_delay = m_resolution;+#else+ constexpr int Events = Iterations * 2; // start + end+ static_assert( Events < QueuePrealloc, "Delay calibration loop will allocate memory in queue" );++ static const tracy::SourceLocationData __tracy_source_location { nullptr, TracyFunction, TracyFile, (uint32_t)TracyLine, 0 };+ const auto t0 = GetTime();+ for( int i=0; i<Iterations; i++ )+ {+ {+ TracyLfqPrepare( QueueType::ZoneBegin );+ MemWrite( &item->zoneBegin.time, Profiler::GetTime() );+ MemWrite( &item->zoneBegin.srcloc, (uint64_t)&__tracy_source_location );+ TracyLfqCommit;+ }+ {+ TracyLfqPrepare( QueueType::ZoneEnd );+ MemWrite( &item->zoneEnd.time, GetTime() );+ TracyLfqCommit;+ }+ }+ const auto t1 = GetTime();+ const auto dt = t1 - t0;+ m_delay = dt / Events;++ moodycamel::ConsumerToken token( GetQueue() );+ int left = Events;+ while( left != 0 )+ {+ const auto sz = GetQueue().try_dequeue_bulk_single( token, [](const uint64_t&){}, [](QueueItem* item, size_t sz){} );+ assert( sz > 0 );+ left -= (int)sz;+ }+ assert( GetQueue().size_approx() == 0 );+#endif+}++void Profiler::ReportTopology()+{+#ifndef TRACY_DELAYED_INIT+ struct CpuData+ {+ uint32_t package;+ uint32_t die;+ uint32_t core;+ uint32_t thread;+ };++#if defined _WIN32+# ifdef TRACY_UWP+ t_GetLogicalProcessorInformationEx _GetLogicalProcessorInformationEx = &::GetLogicalProcessorInformationEx;+# else+ t_GetLogicalProcessorInformationEx _GetLogicalProcessorInformationEx = (t_GetLogicalProcessorInformationEx)GetProcAddress( GetModuleHandleA( "kernel32.dll" ), "GetLogicalProcessorInformationEx" );+# endif+ if( !_GetLogicalProcessorInformationEx ) return;++ SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* packageInfo = nullptr;+ SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* dieInfo = nullptr;+ SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* coreInfo = nullptr;++ DWORD psz = 0;+ _GetLogicalProcessorInformationEx( RelationProcessorPackage, nullptr, &psz );+ if( GetLastError() == ERROR_INSUFFICIENT_BUFFER )+ {+ packageInfo = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)tracy_malloc( psz );+ auto res = _GetLogicalProcessorInformationEx( RelationProcessorPackage, packageInfo, &psz );+ assert( res );+ }+ else+ {+ psz = 0;+ }++ DWORD dsz = 0;+ _GetLogicalProcessorInformationEx( RelationProcessorDie, nullptr, &dsz );+ if( GetLastError() == ERROR_INSUFFICIENT_BUFFER )+ {+ dieInfo = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)tracy_malloc( dsz );+ auto res = _GetLogicalProcessorInformationEx( RelationProcessorDie, dieInfo, &dsz );+ assert( res );+ }+ else+ {+ dsz = 0;+ }++ DWORD csz = 0;+ _GetLogicalProcessorInformationEx( RelationProcessorCore, nullptr, &csz );+ if( GetLastError() == ERROR_INSUFFICIENT_BUFFER )+ {+ coreInfo = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)tracy_malloc( csz );+ auto res = _GetLogicalProcessorInformationEx( RelationProcessorCore, coreInfo, &csz );+ assert( res );+ }+ else+ {+ csz = 0;+ }++ SYSTEM_INFO sysinfo;+ GetSystemInfo( &sysinfo );+ const uint32_t numcpus = sysinfo.dwNumberOfProcessors;++ auto cpuData = (CpuData*)tracy_malloc( sizeof( CpuData ) * numcpus );+ memset( cpuData, 0, sizeof( CpuData ) * numcpus );+ for( uint32_t i=0; i<numcpus; i++ ) cpuData[i].thread = i;++ int idx = 0;+ auto ptr = packageInfo;+ while( (char*)ptr < ((char*)packageInfo) + psz )+ {+ assert( ptr->Relationship == RelationProcessorPackage );+ // FIXME account for GroupCount+ auto mask = ptr->Processor.GroupMask[0].Mask;+ int core = 0;+ while( mask != 0 )+ {+ if( mask & 1 ) cpuData[core].package = idx;+ core++;+ mask >>= 1;+ }+ ptr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)(((char*)ptr) + ptr->Size);+ idx++;+ }++ idx = 0;+ ptr = dieInfo;+ while( (char*)ptr < ((char*)dieInfo) + dsz )+ {+ assert( ptr->Relationship == RelationProcessorDie );+ // FIXME account for GroupCount+ auto mask = ptr->Processor.GroupMask[0].Mask;+ int core = 0;+ while( mask != 0 )+ {+ if( mask & 1 ) cpuData[core].die = idx;+ core++;+ mask >>= 1;+ }+ ptr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)(((char*)ptr) + ptr->Size);+ idx++;+ }++ idx = 0;+ ptr = coreInfo;+ while( (char*)ptr < ((char*)coreInfo) + csz )+ {+ assert( ptr->Relationship == RelationProcessorCore );+ // FIXME account for GroupCount+ auto mask = ptr->Processor.GroupMask[0].Mask;+ int core = 0;+ while( mask != 0 )+ {+ if( mask & 1 ) cpuData[core].core = idx;+ core++;+ mask >>= 1;+ }+ ptr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)(((char*)ptr) + ptr->Size);+ idx++;+ }++ for( uint32_t i=0; i<numcpus; i++ )+ {+ auto& data = cpuData[i];++ TracyLfqPrepare( QueueType::CpuTopology );+ MemWrite( &item->cpuTopology.package, data.package );+ MemWrite( &item->cpuTopology.die, data.die );+ MemWrite( &item->cpuTopology.core, data.core );+ MemWrite( &item->cpuTopology.thread, data.thread );++#ifdef TRACY_ON_DEMAND+ DeferItem( *item );+#endif++ TracyLfqCommit;+ }++ tracy_free( cpuData );+ tracy_free( coreInfo );+ tracy_free( packageInfo );+#elif defined __linux__+ const int numcpus = std::thread::hardware_concurrency();+ auto cpuData = (CpuData*)tracy_malloc( sizeof( CpuData ) * numcpus );+ memset( cpuData, 0, sizeof( CpuData ) * numcpus );++ const char* basePath = "/sys/devices/system/cpu/cpu";+ for( int i=0; i<numcpus; i++ )+ {+ char path[1024];+ sprintf( path, "%s%i/topology/physical_package_id", basePath, i );+ char buf[1024];+ FILE* f = fopen( path, "rb" );+ if( !f )+ {+ tracy_free( cpuData );+ return;+ }+ auto read = fread( buf, 1, 1024, f );+ buf[read] = '\0';+ fclose( f );+ cpuData[i].package = uint32_t( atoi( buf ) );+ cpuData[i].thread = i;++ sprintf( path, "%s%i/topology/core_id", basePath, i );+ f = fopen( path, "rb" );+ if( f )+ {+ read = fread( buf, 1, 1024, f );+ buf[read] = '\0';+ fclose( f );+ cpuData[i].core = uint32_t( atoi( buf ) );+ }++ sprintf( path, "%s%i/topology/die_id", basePath, i );+ f = fopen( path, "rb" );+ if( f )+ {+ read = fread( buf, 1, 1024, f );+ buf[read] = '\0';+ fclose( f );+ cpuData[i].die = uint32_t( atoi( buf ) );+ }+ }++ for( int i=0; i<numcpus; i++ )+ {+ auto& data = cpuData[i];++ TracyLfqPrepare( QueueType::CpuTopology );+ MemWrite( &item->cpuTopology.package, data.package );+ MemWrite( &item->cpuTopology.die, data.die );+ MemWrite( &item->cpuTopology.core, data.core );+ MemWrite( &item->cpuTopology.thread, data.thread );++#ifdef TRACY_ON_DEMAND+ DeferItem( *item );+#endif++ TracyLfqCommit;+ }++ tracy_free( cpuData );+#endif+#endif+}++void Profiler::SendCallstack( int32_t depth, const char* skipBefore )+{+#ifdef TRACY_HAS_CALLSTACK+ auto ptr = Callstack( depth );+ CutCallstack( ptr, skipBefore );++ TracyQueuePrepare( QueueType::Callstack );+ MemWrite( &item->callstackFat.ptr, (uint64_t)ptr );+ TracyQueueCommit( callstackFatThread );+#endif+}++void Profiler::CutCallstack( void* callstack, const char* skipBefore )+{+#ifdef TRACY_HAS_CALLSTACK+ auto data = (uintptr_t*)callstack;+ const auto sz = *data++;+ uintptr_t i;+ for( i=0; i<sz; i++ )+ {+ auto name = DecodeCallstackPtrFast( uint64_t( data[i] ) );+ const bool found = strcmp( name, skipBefore ) == 0;+ if( found )+ {+ i++;+ break;+ }+ }++ if( i != sz )+ {+ memmove( data, data + i, ( sz - i ) * sizeof( uintptr_t* ) );+ *--data = sz - i;+ }+#endif+}++#ifdef TRACY_HAS_SYSTIME+void Profiler::ProcessSysTime()+{+ if( m_shutdown.load( std::memory_order_relaxed ) ) return;+ auto t = std::chrono::high_resolution_clock::now().time_since_epoch().count();+ if( t - m_sysTimeLast > 100000000 ) // 100 ms+ {+ auto sysTime = m_sysTime.Get();+ if( sysTime >= 0 )+ {+ m_sysTimeLast = t;++ TracyLfqPrepare( QueueType::SysTimeReport );+ MemWrite( &item->sysTime.time, GetTime() );+ MemWrite( &item->sysTime.sysTime, sysTime );+ TracyLfqCommit;+ }+ }+}+#endif++void Profiler::HandleParameter( uint64_t payload )+{+ assert( m_paramCallback );+ const auto idx = uint32_t( payload >> 32 );+ const auto val = int32_t( payload & 0xFFFFFFFF );+ m_paramCallback( m_paramCallbackData, idx, val );+ AckServerQuery();+}++void Profiler::HandleSymbolCodeQuery( uint64_t symbol, uint32_t size )+{+ if( symbol >> 63 != 0 )+ {+ QueueKernelCode( symbol, size );+ }+ else+ {+ auto&& lambda = [ this, symbol ]( const char* buf, size_t size ) {+ SendLongString( symbol, buf, size, QueueType::SymbolCode );+ };++ // 'symbol' may have come from a module that has since unloaded, perform a safe copy before sending+ if( !WithSafeCopy( (const char*)symbol, size, lambda ) ) AckSymbolCodeNotAvailable();+ }+}++void Profiler::HandleSourceCodeQuery( char* data, char* image, uint32_t id )+{+ bool ok = false;+ FILE* f = fopen( data, "rb" );+ if( f )+ {+ struct stat st;+ if( fstat( fileno( f ), &st ) == 0 && (uint64_t)st.st_mtime < m_exectime && st.st_size < ( TargetFrameSize - 16 ) )+ {+ auto ptr = (char*)tracy_malloc_fast( st.st_size );+ auto rd = fread( ptr, 1, st.st_size, f );+ if( rd == (size_t)st.st_size )+ {+ TracyLfqPrepare( QueueType::SourceCodeMetadata );+ MemWrite( &item->sourceCodeMetadata.ptr, (uint64_t)ptr );+ MemWrite( &item->sourceCodeMetadata.size, (uint32_t)rd );+ MemWrite( &item->sourceCodeMetadata.id, id );+ TracyLfqCommit;+ ok = true;+ }+ else+ {+ tracy_free_fast( ptr );+ }+ }+ fclose( f );+ }++#ifdef TRACY_DEBUGINFOD+ else if( image && data[0] == '/' )+ {+ size_t size;+ auto buildid = GetBuildIdForImage( image, size );+ if( buildid )+ {+ auto d = debuginfod_find_source( GetDebuginfodClient(), buildid, size, data, nullptr );+ TracyDebug( "DebugInfo source query: %s, fn: %s, image: %s\n", d >= 0 ? " ok " : "fail", data, image );+ if( d >= 0 )+ {+ struct stat st;+ fstat( d, &st );+ if( st.st_size < ( TargetFrameSize - 16 ) )+ {+ lseek( d, 0, SEEK_SET );+ auto ptr = (char*)tracy_malloc_fast( st.st_size );+ auto rd = read( d, ptr, st.st_size );+ if( rd == (size_t)st.st_size )+ {+ TracyLfqPrepare( QueueType::SourceCodeMetadata );+ MemWrite( &item->sourceCodeMetadata.ptr, (uint64_t)ptr );+ MemWrite( &item->sourceCodeMetadata.size, (uint32_t)rd );+ MemWrite( &item->sourceCodeMetadata.id, id );+ TracyLfqCommit;+ ok = true;+ }+ else+ {+ tracy_free_fast( ptr );+ }+ }+ close( d );+ }+ }+ }+ else+ {+ TracyDebug( "DebugInfo invalid query fn: %s, image: %s\n", data, image );+ }+#endif++ if( !ok && m_sourceCallback )+ {+ size_t sz;+ char* ptr = m_sourceCallback( m_sourceCallbackData, data, sz );+ if( ptr )+ {+ if( sz < ( TargetFrameSize - 16 ) )+ {+ TracyLfqPrepare( QueueType::SourceCodeMetadata );+ MemWrite( &item->sourceCodeMetadata.ptr, (uint64_t)ptr );+ MemWrite( &item->sourceCodeMetadata.size, (uint32_t)sz );+ MemWrite( &item->sourceCodeMetadata.id, id );+ TracyLfqCommit;+ ok = true;+ }+ else+ {+ tracy_free_fast( ptr );+ }+ }+ }++ if( !ok )+ {+ TracyLfqPrepare( QueueType::AckSourceCodeNotAvailable );+ MemWrite( &item->sourceCodeNotAvailable, id );+ TracyLfqCommit;+ }++ tracy_free_fast( data );+ tracy_free_fast( image );+}++#if defined _WIN32 && defined TRACY_TIMER_QPC+int64_t Profiler::GetTimeQpc()+{+ LARGE_INTEGER t;+ QueryPerformanceCounter( &t );+ return t.QuadPart;+}+#endif++}++#ifdef __cplusplus+extern "C" {+#endif++TRACY_API TracyCZoneCtx ___tracy_emit_zone_begin( const struct ___tracy_source_location_data* srcloc, int32_t active )+{+ ___tracy_c_zone_context ctx;+#ifdef TRACY_ON_DEMAND+ ctx.active = active && tracy::GetProfiler().IsConnected();+#else+ ctx.active = active;+#endif+ if( !ctx.active ) return ctx;+ const auto id = tracy::GetProfiler().GetNextZoneId();+ ctx.id = id;++#ifndef TRACY_NO_VERIFY+ {+ TracyQueuePrepareC( tracy::QueueType::ZoneValidation );+ tracy::MemWrite( &item->zoneValidation.id, id );+ TracyQueueCommitC( zoneValidationThread );+ }+#endif+ {+ TracyQueuePrepareC( tracy::QueueType::ZoneBegin );+ tracy::MemWrite( &item->zoneBegin.time, tracy::Profiler::GetTime() );+ tracy::MemWrite( &item->zoneBegin.srcloc, (uint64_t)srcloc );+ TracyQueueCommitC( zoneBeginThread );+ }+ return ctx;+}++TRACY_API TracyCZoneCtx ___tracy_emit_zone_begin_callstack( const struct ___tracy_source_location_data* srcloc, int32_t depth, int32_t active )+{+ ___tracy_c_zone_context ctx;+#ifdef TRACY_ON_DEMAND+ ctx.active = active && tracy::GetProfiler().IsConnected();+#else+ ctx.active = active;+#endif+ if( !ctx.active ) return ctx;+ const auto id = tracy::GetProfiler().GetNextZoneId();+ ctx.id = id;++#ifndef TRACY_NO_VERIFY+ {+ TracyQueuePrepareC( tracy::QueueType::ZoneValidation );+ tracy::MemWrite( &item->zoneValidation.id, id );+ TracyQueueCommitC( zoneValidationThread );+ }+#endif+ auto zoneQueue = tracy::QueueType::ZoneBegin;+ if( depth > 0 && tracy::has_callstack() )+ {+ tracy::GetProfiler().SendCallstack( depth );+ zoneQueue = tracy::QueueType::ZoneBeginCallstack;+ }+ TracyQueuePrepareC( zoneQueue );+ tracy::MemWrite( &item->zoneBegin.time, tracy::Profiler::GetTime() );+ tracy::MemWrite( &item->zoneBegin.srcloc, (uint64_t)srcloc );+ TracyQueueCommitC( zoneBeginThread );++ return ctx;+}++TRACY_API TracyCZoneCtx ___tracy_emit_zone_begin_alloc( uint64_t srcloc, int32_t active )+{+ ___tracy_c_zone_context ctx;+#ifdef TRACY_ON_DEMAND+ ctx.active = active && tracy::GetProfiler().IsConnected();+#else+ ctx.active = active;+#endif+ if( !ctx.active )+ {+ tracy::tracy_free( (void*)srcloc );+ return ctx;+ }+ const auto id = tracy::GetProfiler().GetNextZoneId();+ ctx.id = id;++#ifndef TRACY_NO_VERIFY+ {+ TracyQueuePrepareC( tracy::QueueType::ZoneValidation );+ tracy::MemWrite( &item->zoneValidation.id, id );+ TracyQueueCommitC( zoneValidationThread );+ }+#endif+ {+ TracyQueuePrepareC( tracy::QueueType::ZoneBeginAllocSrcLoc );+ tracy::MemWrite( &item->zoneBegin.time, tracy::Profiler::GetTime() );+ tracy::MemWrite( &item->zoneBegin.srcloc, srcloc );+ TracyQueueCommitC( zoneBeginThread );+ }+ return ctx;+}++TRACY_API TracyCZoneCtx ___tracy_emit_zone_begin_alloc_callstack( uint64_t srcloc, int32_t depth, int32_t active )+{+ ___tracy_c_zone_context ctx;+#ifdef TRACY_ON_DEMAND+ ctx.active = active && tracy::GetProfiler().IsConnected();+#else+ ctx.active = active;+#endif+ if( !ctx.active )+ {+ tracy::tracy_free( (void*)srcloc );+ return ctx;+ }+ const auto id = tracy::GetProfiler().GetNextZoneId();+ ctx.id = id;++#ifndef TRACY_NO_VERIFY+ {+ TracyQueuePrepareC( tracy::QueueType::ZoneValidation );+ tracy::MemWrite( &item->zoneValidation.id, id );+ TracyQueueCommitC( zoneValidationThread );+ }+#endif+ auto zoneQueue = tracy::QueueType::ZoneBeginAllocSrcLoc;+ if( depth > 0 && tracy::has_callstack() )+ {+ tracy::GetProfiler().SendCallstack( depth );+ zoneQueue = tracy::QueueType::ZoneBeginAllocSrcLocCallstack;+ }+ TracyQueuePrepareC( zoneQueue );+ tracy::MemWrite( &item->zoneBegin.time, tracy::Profiler::GetTime() );+ tracy::MemWrite( &item->zoneBegin.srcloc, srcloc );+ TracyQueueCommitC( zoneBeginThread );++ return ctx;+}++TRACY_API void ___tracy_emit_zone_end( TracyCZoneCtx ctx )+{+ if( !ctx.active ) return;+#ifndef TRACY_NO_VERIFY+ {+ TracyQueuePrepareC( tracy::QueueType::ZoneValidation );+ tracy::MemWrite( &item->zoneValidation.id, ctx.id );+ TracyQueueCommitC( zoneValidationThread );+ }+#endif+ {+ TracyQueuePrepareC( tracy::QueueType::ZoneEnd );+ tracy::MemWrite( &item->zoneEnd.time, tracy::Profiler::GetTime() );+ TracyQueueCommitC( zoneEndThread );+ }+}++TRACY_API void ___tracy_emit_zone_text( TracyCZoneCtx ctx, const char* txt, size_t size )+{+ assert( size < std::numeric_limits<uint16_t>::max() );+ if( !ctx.active ) return;+ auto ptr = (char*)tracy::tracy_malloc( size );+ memcpy( ptr, txt, size );+#ifndef TRACY_NO_VERIFY+ {+ TracyQueuePrepareC( tracy::QueueType::ZoneValidation );+ tracy::MemWrite( &item->zoneValidation.id, ctx.id );+ TracyQueueCommitC( zoneValidationThread );+ }+#endif+ {+ TracyQueuePrepareC( tracy::QueueType::ZoneText );+ tracy::MemWrite( &item->zoneTextFat.text, (uint64_t)ptr );+ tracy::MemWrite( &item->zoneTextFat.size, (uint16_t)size );+ TracyQueueCommitC( zoneTextFatThread );+ }+}++TRACY_API void ___tracy_emit_zone_name( TracyCZoneCtx ctx, const char* txt, size_t size )+{+ assert( size < std::numeric_limits<uint16_t>::max() );+ if( !ctx.active ) return;+ auto ptr = (char*)tracy::tracy_malloc( size );+ memcpy( ptr, txt, size );+#ifndef TRACY_NO_VERIFY+ {+ TracyQueuePrepareC( tracy::QueueType::ZoneValidation );+ tracy::MemWrite( &item->zoneValidation.id, ctx.id );+ TracyQueueCommitC( zoneValidationThread );+ }+#endif+ {+ TracyQueuePrepareC( tracy::QueueType::ZoneName );+ tracy::MemWrite( &item->zoneTextFat.text, (uint64_t)ptr );+ tracy::MemWrite( &item->zoneTextFat.size, (uint16_t)size );+ TracyQueueCommitC( zoneTextFatThread );+ }+}++TRACY_API void ___tracy_emit_zone_color( TracyCZoneCtx ctx, uint32_t color ) {+ if( !ctx.active ) return;+#ifndef TRACY_NO_VERIFY+ {+ TracyQueuePrepareC( tracy::QueueType::ZoneValidation );+ tracy::MemWrite( &item->zoneValidation.id, ctx.id );+ TracyQueueCommitC( zoneValidationThread );+ }+#endif+ {+ TracyQueuePrepareC( tracy::QueueType::ZoneColor );+ tracy::MemWrite( &item->zoneColor.b, uint8_t( ( color ) & 0xFF ) );+ tracy::MemWrite( &item->zoneColor.g, uint8_t( ( color >> 8 ) & 0xFF ) );+ tracy::MemWrite( &item->zoneColor.r, uint8_t( ( color >> 16 ) & 0xFF ) );+ TracyQueueCommitC( zoneColorThread );+ }+}++TRACY_API void ___tracy_emit_zone_value( TracyCZoneCtx ctx, uint64_t value )+{+ if( !ctx.active ) return;+#ifndef TRACY_NO_VERIFY+ {+ TracyQueuePrepareC( tracy::QueueType::ZoneValidation );+ tracy::MemWrite( &item->zoneValidation.id, ctx.id );+ TracyQueueCommitC( zoneValidationThread );+ }+#endif+ {+ TracyQueuePrepareC( tracy::QueueType::ZoneValue );+ tracy::MemWrite( &item->zoneValue.value, value );+ TracyQueueCommitC( zoneValueThread );+ }+}++TRACY_API void ___tracy_emit_memory_alloc( const void* ptr, size_t size, int32_t secure ) { tracy::Profiler::MemAlloc( ptr, size, secure != 0 ); }+TRACY_API void ___tracy_emit_memory_alloc_callstack( const void* ptr, size_t size, int32_t depth, int32_t secure )+{+ if( depth > 0 && tracy::has_callstack() )+ {+ tracy::Profiler::MemAllocCallstack( ptr, size, depth, secure != 0 );+ }+ else+ {+ tracy::Profiler::MemAlloc( ptr, size, secure != 0 );+ }+}+TRACY_API void ___tracy_emit_memory_free( const void* ptr, int32_t secure ) { tracy::Profiler::MemFree( ptr, secure != 0 ); }+TRACY_API void ___tracy_emit_memory_free_callstack( const void* ptr, int32_t depth, int32_t secure )+{+ if( depth > 0 && tracy::has_callstack() )+ {+ tracy::Profiler::MemFreeCallstack( ptr, depth, secure != 0 );+ }+ else+ {+ tracy::Profiler::MemFree( ptr, secure != 0 );+ }+}+TRACY_API void ___tracy_emit_memory_discard( const char* name, int32_t secure ) { tracy::Profiler::MemDiscard( name, secure != 0 ); }+TRACY_API void ___tracy_emit_memory_discard_callstack( const char* name, int32_t secure, int32_t depth )+{+ if( depth > 0 && tracy::has_callstack() )+ {+ tracy::Profiler::MemDiscardCallstack( name, secure != 0, depth );+ }+ else+ {+ tracy::Profiler::MemDiscard( name, secure != 0 );+ }+}+TRACY_API void ___tracy_emit_memory_alloc_named( const void* ptr, size_t size, int32_t secure, const char* name ) { tracy::Profiler::MemAllocNamed( ptr, size, secure != 0, name ); }+TRACY_API void ___tracy_emit_memory_alloc_callstack_named( const void* ptr, size_t size, int32_t depth, int32_t secure, const char* name )+{+ if( depth > 0 && tracy::has_callstack() )+ {+ tracy::Profiler::MemAllocCallstackNamed( ptr, size, depth, secure != 0, name );+ }+ else+ {+ tracy::Profiler::MemAllocNamed( ptr, size, secure != 0, name );+ }+}+TRACY_API void ___tracy_emit_memory_free_named( const void* ptr, int32_t secure, const char* name ) { tracy::Profiler::MemFreeNamed( ptr, secure != 0, name ); }+TRACY_API void ___tracy_emit_memory_free_callstack_named( const void* ptr, int32_t depth, int32_t secure, const char* name )+{+ if( depth > 0 && tracy::has_callstack() )+ {+ tracy::Profiler::MemFreeCallstackNamed( ptr, depth, secure != 0, name );+ }+ else+ {+ tracy::Profiler::MemFreeNamed( ptr, secure != 0, name );+ }+}+TRACY_API void ___tracy_emit_frame_mark( const char* name ) { tracy::Profiler::SendFrameMark( name ); }+TRACY_API void ___tracy_emit_frame_mark_start( const char* name ) { tracy::Profiler::SendFrameMark( name, tracy::QueueType::FrameMarkMsgStart ); }+TRACY_API void ___tracy_emit_frame_mark_end( const char* name ) { tracy::Profiler::SendFrameMark( name, tracy::QueueType::FrameMarkMsgEnd ); }+TRACY_API void ___tracy_emit_frame_image( const void* image, uint16_t w, uint16_t h, uint8_t offset, int32_t flip ) { tracy::Profiler::SendFrameImage( image, w, h, offset, flip != 0 ); }+TRACY_API void ___tracy_emit_plot( const char* name, double val ) { tracy::Profiler::PlotData( name, val ); }+TRACY_API void ___tracy_emit_plot_float( const char* name, float val ) { tracy::Profiler::PlotData( name, val ); }+TRACY_API void ___tracy_emit_plot_int( const char* name, int64_t val ) { tracy::Profiler::PlotData( name, val ); }+TRACY_API void ___tracy_emit_plot_config( const char* name, int32_t type, int32_t step, int32_t fill, uint32_t color ) { tracy::Profiler::ConfigurePlot( name, tracy::PlotFormatType(type), step != 0, fill != 0, color ); }+TRACY_API void ___tracy_emit_message( const char* txt, size_t size, int32_t callstack_depth ) { tracy::Profiler::Message( txt, size, callstack_depth ); }+TRACY_API void ___tracy_emit_messageL( const char* txt, int32_t callstack_depth ) { tracy::Profiler::Message( txt, callstack_depth ); }+TRACY_API void ___tracy_emit_messageC( const char* txt, size_t size, uint32_t color, int32_t callstack_depth ) { tracy::Profiler::MessageColor( txt, size, color, callstack_depth ); }+TRACY_API void ___tracy_emit_messageLC( const char* txt, uint32_t color, int32_t callstack_depth ) { tracy::Profiler::MessageColor( txt, color, callstack_depth ); }+TRACY_API void ___tracy_emit_message_appinfo( const char* txt, size_t size ) { tracy::Profiler::MessageAppInfo( txt, size ); }++TRACY_API uint64_t ___tracy_alloc_srcloc( uint32_t line, const char* source, size_t sourceSz, const char* function, size_t functionSz, uint32_t color ) {+ return tracy::Profiler::AllocSourceLocation( line, source, sourceSz, function, functionSz, color );+}++TRACY_API uint64_t ___tracy_alloc_srcloc_name( uint32_t line, const char* source, size_t sourceSz, const char* function, size_t functionSz, const char* name, size_t nameSz, uint32_t color ) {+ return tracy::Profiler::AllocSourceLocation( line, source, sourceSz, function, functionSz, name, nameSz, color );+}++TRACY_API void ___tracy_emit_gpu_zone_begin( const struct ___tracy_gpu_zone_begin_data data )+{+ TracyLfqPrepareC( tracy::QueueType::GpuZoneBegin );+ tracy::MemWrite( &item->gpuZoneBegin.cpuTime, tracy::Profiler::GetTime() );+ tracy::MemWrite( &item->gpuZoneBegin.thread, tracy::GetThreadHandle() );+ tracy::MemWrite( &item->gpuZoneBegin.srcloc, data.srcloc );+ tracy::MemWrite( &item->gpuZoneBegin.queryId, data.queryId );+ tracy::MemWrite( &item->gpuZoneBegin.context, data.context );+ TracyLfqCommitC;+}++TRACY_API void ___tracy_emit_gpu_zone_begin_callstack( const struct ___tracy_gpu_zone_begin_callstack_data data )+{+ tracy::GetProfiler().SendCallstack( data.depth );+ TracyLfqPrepareC( tracy::QueueType::GpuZoneBeginCallstack );+ tracy::MemWrite( &item->gpuZoneBegin.thread, tracy::GetThreadHandle() );+ tracy::MemWrite( &item->gpuZoneBegin.cpuTime, tracy::Profiler::GetTime() );+ tracy::MemWrite( &item->gpuZoneBegin.queryId, data.queryId );+ tracy::MemWrite( &item->gpuZoneBegin.context, data.context );+ tracy::MemWrite( &item->gpuZoneBegin.srcloc, data.srcloc );+ TracyLfqCommitC;+}++TRACY_API void ___tracy_emit_gpu_zone_begin_alloc( const struct ___tracy_gpu_zone_begin_data data )+{+ TracyLfqPrepareC( tracy::QueueType::GpuZoneBeginAllocSrcLoc );+ tracy::MemWrite( &item->gpuZoneBegin.cpuTime, tracy::Profiler::GetTime() );+ tracy::MemWrite( &item->gpuZoneBegin.thread, tracy::GetThreadHandle() );+ tracy::MemWrite( &item->gpuZoneBegin.srcloc, data.srcloc );+ tracy::MemWrite( &item->gpuZoneBegin.queryId, data.queryId );+ tracy::MemWrite( &item->gpuZoneBegin.context, data.context );+ TracyLfqCommitC;+}++TRACY_API void ___tracy_emit_gpu_zone_begin_alloc_callstack( const struct ___tracy_gpu_zone_begin_callstack_data data )+{+ tracy::GetProfiler().SendCallstack( data.depth );+ TracyLfqPrepareC( tracy::QueueType::GpuZoneBeginAllocSrcLocCallstack );+ tracy::MemWrite( &item->gpuZoneBegin.cpuTime, tracy::Profiler::GetTime() );+ tracy::MemWrite( &item->gpuZoneBegin.thread, tracy::GetThreadHandle() );+ tracy::MemWrite( &item->gpuZoneBegin.srcloc, data.srcloc );+ tracy::MemWrite( &item->gpuZoneBegin.queryId, data.queryId );+ tracy::MemWrite( &item->gpuZoneBegin.context, data.context );+ TracyLfqCommitC;+}++TRACY_API void ___tracy_emit_gpu_time( const struct ___tracy_gpu_time_data data )+{+ TracyLfqPrepareC( tracy::QueueType::GpuTime );+ tracy::MemWrite( &item->gpuTime.gpuTime, data.gpuTime );+ tracy::MemWrite( &item->gpuTime.queryId, data.queryId );+ tracy::MemWrite( &item->gpuTime.context, data.context );+ TracyLfqCommitC;+}++TRACY_API void ___tracy_emit_gpu_zone_end( const struct ___tracy_gpu_zone_end_data data )+{+ TracyLfqPrepareC( tracy::QueueType::GpuZoneEnd );+ tracy::MemWrite( &item->gpuZoneEnd.cpuTime, tracy::Profiler::GetTime() );+ memset( &item->gpuZoneEnd.thread, 0, sizeof( item->gpuZoneEnd.thread ) );+ tracy::MemWrite( &item->gpuZoneEnd.queryId, data.queryId );+ tracy::MemWrite( &item->gpuZoneEnd.context, data.context );+ TracyLfqCommitC;+}++TRACY_API void ___tracy_emit_gpu_new_context( ___tracy_gpu_new_context_data data )+{+ TracyLfqPrepareC( tracy::QueueType::GpuNewContext );+ tracy::MemWrite( &item->gpuNewContext.cpuTime, tracy::Profiler::GetTime() );+ tracy::MemWrite( &item->gpuNewContext.thread, tracy::GetThreadHandle() );+ tracy::MemWrite( &item->gpuNewContext.gpuTime, data.gpuTime );+ tracy::MemWrite( &item->gpuNewContext.period, data.period );+ tracy::MemWrite( &item->gpuNewContext.context, data.context );+ tracy::MemWrite( &item->gpuNewContext.flags, data.flags );+ tracy::MemWrite( &item->gpuNewContext.type, data.type );++#ifdef TRACY_ON_DEMAND+ tracy::GetProfiler().DeferItem( *item );+#endif++ TracyLfqCommitC;+}++TRACY_API void ___tracy_emit_gpu_context_name( const struct ___tracy_gpu_context_name_data data )+{+ auto ptr = (char*)tracy::tracy_malloc( data.len );+ memcpy( ptr, data.name, data.len );++ TracyLfqPrepareC( tracy::QueueType::GpuContextName );+ tracy::MemWrite( &item->gpuContextNameFat.context, data.context );+ tracy::MemWrite( &item->gpuContextNameFat.ptr, (uint64_t)ptr );+ tracy::MemWrite( &item->gpuContextNameFat.size, data.len );++#ifdef TRACY_ON_DEMAND+ tracy::GetProfiler().DeferItem( *item );+#endif++ TracyLfqCommitC;+}++TRACY_API void ___tracy_emit_gpu_calibration( const struct ___tracy_gpu_calibration_data data )+{+ TracyLfqPrepareC( tracy::QueueType::GpuCalibration );+ tracy::MemWrite( &item->gpuCalibration.cpuTime, tracy::Profiler::GetTime() );+ tracy::MemWrite( &item->gpuCalibration.gpuTime, data.gpuTime );+ tracy::MemWrite( &item->gpuCalibration.cpuDelta, data.cpuDelta );+ tracy::MemWrite( &item->gpuCalibration.context, data.context );+ TracyLfqCommitC;+}++TRACY_API void ___tracy_emit_gpu_time_sync( const struct ___tracy_gpu_time_sync_data data )+{+ TracyLfqPrepareC( tracy::QueueType::GpuTimeSync );+ tracy::MemWrite( &item->gpuTimeSync.cpuTime, tracy::Profiler::GetTime() );+ tracy::MemWrite( &item->gpuTimeSync.gpuTime, data.gpuTime );+ tracy::MemWrite( &item->gpuTimeSync.context, data.context );+ TracyLfqCommitC;+}++TRACY_API void ___tracy_emit_gpu_zone_begin_serial( const struct ___tracy_gpu_zone_begin_data data )+{+ auto item = tracy::Profiler::QueueSerial();+ tracy::MemWrite( &item->hdr.type, tracy::QueueType::GpuZoneBeginSerial );+ tracy::MemWrite( &item->gpuZoneBegin.cpuTime, tracy::Profiler::GetTime() );+ tracy::MemWrite( &item->gpuZoneBegin.srcloc, data.srcloc );+ tracy::MemWrite( &item->gpuZoneBegin.thread, tracy::GetThreadHandle() );+ tracy::MemWrite( &item->gpuZoneBegin.queryId, data.queryId );+ tracy::MemWrite( &item->gpuZoneBegin.context, data.context );+ tracy::Profiler::QueueSerialFinish();+}++TRACY_API void ___tracy_emit_gpu_zone_begin_callstack_serial( const struct ___tracy_gpu_zone_begin_callstack_data data )+{+ auto item = tracy::Profiler::QueueSerialCallstack( tracy::Callstack( data.depth ) );+ tracy::MemWrite( &item->hdr.type, tracy::QueueType::GpuZoneBeginCallstackSerial );+ tracy::MemWrite( &item->gpuZoneBegin.cpuTime, tracy::Profiler::GetTime() );+ tracy::MemWrite( &item->gpuZoneBegin.srcloc, data.srcloc );+ tracy::MemWrite( &item->gpuZoneBegin.thread, tracy::GetThreadHandle() );+ tracy::MemWrite( &item->gpuZoneBegin.queryId, data.queryId );+ tracy::MemWrite( &item->gpuZoneBegin.context, data.context );+ tracy::Profiler::QueueSerialFinish();+}++TRACY_API void ___tracy_emit_gpu_zone_begin_alloc_serial( const struct ___tracy_gpu_zone_begin_data data )+{+ auto item = tracy::Profiler::QueueSerial();+ tracy::MemWrite( &item->hdr.type, tracy::QueueType::GpuZoneBeginAllocSrcLocSerial );+ tracy::MemWrite( &item->gpuZoneBegin.cpuTime, tracy::Profiler::GetTime() );+ tracy::MemWrite( &item->gpuZoneBegin.thread, tracy::GetThreadHandle() );+ tracy::MemWrite( &item->gpuZoneBegin.srcloc, data.srcloc );+ tracy::MemWrite( &item->gpuZoneBegin.queryId, data.queryId );+ tracy::MemWrite( &item->gpuZoneBegin.context, data.context );+ tracy::Profiler::QueueSerialFinish();+}++TRACY_API void ___tracy_emit_gpu_zone_begin_alloc_callstack_serial( const struct ___tracy_gpu_zone_begin_callstack_data data )+{+ auto item = tracy::Profiler::QueueSerialCallstack( tracy::Callstack( data.depth ) );+ tracy::MemWrite( &item->hdr.type, tracy::QueueType::GpuZoneBeginAllocSrcLocCallstackSerial );+ tracy::MemWrite( &item->gpuZoneBegin.cpuTime, tracy::Profiler::GetTime() );+ tracy::MemWrite( &item->gpuZoneBegin.thread, tracy::GetThreadHandle() );+ tracy::MemWrite( &item->gpuZoneBegin.srcloc, data.srcloc );+ tracy::MemWrite( &item->gpuZoneBegin.queryId, data.queryId );+ tracy::MemWrite( &item->gpuZoneBegin.context, data.context );+ tracy::Profiler::QueueSerialFinish();+}++TRACY_API void ___tracy_emit_gpu_time_serial( const struct ___tracy_gpu_time_data data )+{+ auto item = tracy::Profiler::QueueSerial();+ tracy::MemWrite( &item->hdr.type, tracy::QueueType::GpuTime );+ tracy::MemWrite( &item->gpuTime.gpuTime, data.gpuTime );+ tracy::MemWrite( &item->gpuTime.queryId, data.queryId );+ tracy::MemWrite( &item->gpuTime.context, data.context );+ tracy::Profiler::QueueSerialFinish();+}++TRACY_API void ___tracy_emit_gpu_zone_end_serial( const struct ___tracy_gpu_zone_end_data data )+{+ auto item = tracy::Profiler::QueueSerial();+ tracy::MemWrite( &item->hdr.type, tracy::QueueType::GpuZoneEndSerial );+ tracy::MemWrite( &item->gpuZoneEnd.cpuTime, tracy::Profiler::GetTime() );+ memset( &item->gpuZoneEnd.thread, 0, sizeof( item->gpuZoneEnd.thread ) );+ tracy::MemWrite( &item->gpuZoneEnd.queryId, data.queryId );+ tracy::MemWrite( &item->gpuZoneEnd.context, data.context );+ tracy::Profiler::QueueSerialFinish();+}++TRACY_API void ___tracy_emit_gpu_new_context_serial( ___tracy_gpu_new_context_data data )+{+ auto item = tracy::Profiler::QueueSerial();+ tracy::MemWrite( &item->hdr.type, tracy::QueueType::GpuNewContext );+ tracy::MemWrite( &item->gpuNewContext.cpuTime, tracy::Profiler::GetTime() );+ tracy::MemWrite( &item->gpuNewContext.thread, tracy::GetThreadHandle() );+ tracy::MemWrite( &item->gpuNewContext.gpuTime, data.gpuTime );+ tracy::MemWrite( &item->gpuNewContext.period, data.period );+ tracy::MemWrite( &item->gpuNewContext.context, data.context );+ tracy::MemWrite( &item->gpuNewContext.flags, data.flags );+ tracy::MemWrite( &item->gpuNewContext.type, data.type );+ tracy::Profiler::QueueSerialFinish();+}++TRACY_API void ___tracy_emit_gpu_context_name_serial( const struct ___tracy_gpu_context_name_data data )+{+ auto ptr = (char*)tracy::tracy_malloc( data.len );+ memcpy( ptr, data.name, data.len );++ auto item = tracy::Profiler::QueueSerial();+ tracy::MemWrite( &item->hdr.type, tracy::QueueType::GpuContextName );+ tracy::MemWrite( &item->gpuContextNameFat.context, data.context );+ tracy::MemWrite( &item->gpuContextNameFat.ptr, (uint64_t)ptr );+ tracy::MemWrite( &item->gpuContextNameFat.size, data.len );+ tracy::Profiler::QueueSerialFinish();+}++TRACY_API void ___tracy_emit_gpu_calibration_serial( const struct ___tracy_gpu_calibration_data data )+{+ auto item = tracy::Profiler::QueueSerial();+ tracy::MemWrite( &item->hdr.type, tracy::QueueType::GpuCalibration );+ tracy::MemWrite( &item->gpuCalibration.cpuTime, tracy::Profiler::GetTime() );+ tracy::MemWrite( &item->gpuCalibration.gpuTime, data.gpuTime );+ tracy::MemWrite( &item->gpuCalibration.cpuDelta, data.cpuDelta );+ tracy::MemWrite( &item->gpuCalibration.context, data.context );+ tracy::Profiler::QueueSerialFinish();+}++TRACY_API void ___tracy_emit_gpu_time_sync_serial( const struct ___tracy_gpu_time_sync_data data )+{+ auto item = tracy::Profiler::QueueSerial();+ tracy::MemWrite( &item->hdr.type, tracy::QueueType::GpuTimeSync );+ tracy::MemWrite( &item->gpuTimeSync.cpuTime, tracy::Profiler::GetTime() );+ tracy::MemWrite( &item->gpuTimeSync.gpuTime, data.gpuTime );+ tracy::MemWrite( &item->gpuTimeSync.context, data.context );+ tracy::Profiler::QueueSerialFinish();+}++struct __tracy_lockable_context_data+{+ uint32_t m_id;+#ifdef TRACY_ON_DEMAND+ std::atomic<uint32_t> m_lockCount;+ std::atomic<bool> m_active;+#endif+};++TRACY_API struct __tracy_lockable_context_data* ___tracy_announce_lockable_ctx( const struct ___tracy_source_location_data* srcloc )+{+ struct __tracy_lockable_context_data *lockdata = (__tracy_lockable_context_data*)tracy::tracy_malloc( sizeof( __tracy_lockable_context_data ) );+ lockdata->m_id =tracy:: GetLockCounter().fetch_add( 1, std::memory_order_relaxed );+#ifdef TRACY_ON_DEMAND+ new(&lockdata->m_lockCount) std::atomic<uint32_t>( 0 );+ new(&lockdata->m_active) std::atomic<bool>( false );+#endif+ assert( lockdata->m_id != (std::numeric_limits<uint32_t>::max)() );++ auto item = tracy::Profiler::QueueSerial();+ tracy::MemWrite( &item->hdr.type, tracy::QueueType::LockAnnounce );+ tracy::MemWrite( &item->lockAnnounce.id, lockdata->m_id );+ tracy::MemWrite( &item->lockAnnounce.time, tracy::Profiler::GetTime() );+ tracy::MemWrite( &item->lockAnnounce.lckloc, (uint64_t)srcloc );+ tracy::MemWrite( &item->lockAnnounce.type, tracy::LockType::Lockable );+#ifdef TRACY_ON_DEMAND+ tracy::GetProfiler().DeferItem( *item );+#endif+ tracy::Profiler::QueueSerialFinish();++ return lockdata;+}++TRACY_API void ___tracy_terminate_lockable_ctx( struct __tracy_lockable_context_data* lockdata )+{+ auto item = tracy::Profiler::QueueSerial();+ tracy::MemWrite( &item->hdr.type, tracy::QueueType::LockTerminate );+ tracy::MemWrite( &item->lockTerminate.id, lockdata->m_id );+ tracy::MemWrite( &item->lockTerminate.time, tracy::Profiler::GetTime() );+#ifdef TRACY_ON_DEMAND+ tracy::GetProfiler().DeferItem( *item );+#endif+ tracy::Profiler::QueueSerialFinish();++#ifdef TRACY_ON_DEMAND+ lockdata->m_lockCount.~atomic();+ lockdata->m_active.~atomic();+#endif+ tracy::tracy_free((void*)lockdata);+}++TRACY_API int32_t ___tracy_before_lock_lockable_ctx( struct __tracy_lockable_context_data* lockdata )+{+#ifdef TRACY_ON_DEMAND+ bool queue = false;+ const auto locks = lockdata->m_lockCount.fetch_add( 1, std::memory_order_relaxed );+ const auto active = lockdata->m_active.load( std::memory_order_relaxed );+ if( locks == 0 || active )+ {+ const bool connected = tracy::GetProfiler().IsConnected();+ if( active != connected ) lockdata->m_active.store( connected, std::memory_order_relaxed );+ if( connected ) queue = true;+ }+ if( !queue ) return static_cast<int32_t>(false);+#endif++ auto item = tracy::Profiler::QueueSerial();+ tracy::MemWrite( &item->hdr.type, tracy::QueueType::LockWait );+ tracy::MemWrite( &item->lockWait.thread, tracy::GetThreadHandle() );+ tracy::MemWrite( &item->lockWait.id, lockdata->m_id );+ tracy::MemWrite( &item->lockWait.time, tracy::Profiler::GetTime() );+ tracy::Profiler::QueueSerialFinish();+ return static_cast<int32_t>(true);+}++TRACY_API void ___tracy_after_lock_lockable_ctx( struct __tracy_lockable_context_data* lockdata )+{+ auto item = tracy::Profiler::QueueSerial();+ tracy::MemWrite( &item->hdr.type, tracy::QueueType::LockObtain );+ tracy::MemWrite( &item->lockObtain.thread, tracy::GetThreadHandle() );+ tracy::MemWrite( &item->lockObtain.id, lockdata->m_id );+ tracy::MemWrite( &item->lockObtain.time, tracy::Profiler::GetTime() );+ tracy::Profiler::QueueSerialFinish();+}++TRACY_API void ___tracy_after_unlock_lockable_ctx( struct __tracy_lockable_context_data* lockdata )+{+#ifdef TRACY_ON_DEMAND+ lockdata->m_lockCount.fetch_sub( 1, std::memory_order_relaxed );+ if( !lockdata->m_active.load( std::memory_order_relaxed ) ) return;+ if( !tracy::GetProfiler().IsConnected() )+ {+ lockdata->m_active.store( false, std::memory_order_relaxed );+ return;+ }+#endif++ auto item = tracy::Profiler::QueueSerial();+ tracy::MemWrite( &item->hdr.type, tracy::QueueType::LockRelease );+ tracy::MemWrite( &item->lockRelease.id, lockdata->m_id );+ tracy::MemWrite( &item->lockRelease.time, tracy::Profiler::GetTime() );+ tracy::Profiler::QueueSerialFinish();+}++TRACY_API void ___tracy_after_try_lock_lockable_ctx( struct __tracy_lockable_context_data* lockdata, int32_t acquired )+{+#ifdef TRACY_ON_DEMAND+ if( !acquired ) return;++ bool queue = false;+ const auto locks = lockdata->m_lockCount.fetch_add( 1, std::memory_order_relaxed );+ const auto active = lockdata->m_active.load( std::memory_order_relaxed );+ if( locks == 0 || active )+ {+ const bool connected = tracy::GetProfiler().IsConnected();+ if( active != connected ) lockdata->m_active.store( connected, std::memory_order_relaxed );+ if( connected ) queue = true;+ }+ if( !queue ) return;+#endif++ if( acquired )+ {+ auto item = tracy::Profiler::QueueSerial();+ tracy::MemWrite( &item->hdr.type, tracy::QueueType::LockObtain );+ tracy::MemWrite( &item->lockObtain.thread, tracy::GetThreadHandle() );+ tracy::MemWrite( &item->lockObtain.id, lockdata->m_id );+ tracy::MemWrite( &item->lockObtain.time, tracy::Profiler::GetTime() );+ tracy::Profiler::QueueSerialFinish();+ }+}++TRACY_API void ___tracy_mark_lockable_ctx( struct __tracy_lockable_context_data* lockdata, const struct ___tracy_source_location_data* srcloc )+{+#ifdef TRACY_ON_DEMAND+ const auto active = lockdata->m_active.load( std::memory_order_relaxed );+ if( !active ) return;+ const auto connected = tracy::GetProfiler().IsConnected();+ if( !connected )+ {+ if( active ) lockdata->m_active.store( false, std::memory_order_relaxed );+ return;+ }+#endif++ auto item = tracy::Profiler::QueueSerial();+ tracy::MemWrite( &item->hdr.type, tracy::QueueType::LockMark );+ tracy::MemWrite( &item->lockMark.thread, tracy::GetThreadHandle() );+ tracy::MemWrite( &item->lockMark.id, lockdata->m_id );+ tracy::MemWrite( &item->lockMark.srcloc, (uint64_t)srcloc );+ tracy::Profiler::QueueSerialFinish();+}++TRACY_API void ___tracy_custom_name_lockable_ctx( struct __tracy_lockable_context_data* lockdata, const char* name, size_t nameSz )+{+ assert( nameSz < (std::numeric_limits<uint16_t>::max)() );+ auto ptr = (char*)tracy::tracy_malloc( nameSz );+ memcpy( ptr, name, nameSz );+ auto item = tracy::Profiler::QueueSerial();+ tracy::MemWrite( &item->hdr.type, tracy::QueueType::LockName );+ tracy::MemWrite( &item->lockNameFat.id, lockdata->m_id );+ tracy::MemWrite( &item->lockNameFat.name, (uint64_t)ptr );+ tracy::MemWrite( &item->lockNameFat.size, (uint16_t)nameSz );+#ifdef TRACY_ON_DEMAND+ tracy::GetProfiler().DeferItem( *item );+#endif+ tracy::Profiler::QueueSerialFinish();+}++TRACY_API int32_t ___tracy_connected( void )+{+ return static_cast<int32_t>( tracy::GetProfiler().IsConnected() );+}++#ifdef TRACY_FIBERS+TRACY_API void ___tracy_fiber_enter( const char* fiber ){ tracy::Profiler::EnterFiber( fiber, 0 ); }+TRACY_API void ___tracy_fiber_leave( void ){ tracy::Profiler::LeaveFiber(); }+#endif++# if defined TRACY_MANUAL_LIFETIME && defined TRACY_DELAYED_INIT+TRACY_API void ___tracy_startup_profiler( void )+{+ tracy::StartupProfiler();+}++TRACY_API void ___tracy_shutdown_profiler( void )+{+ tracy::ShutdownProfiler();+}++TRACY_API int32_t ___tracy_profiler_started( void )+{+ return static_cast<int32_t>( tracy::s_isProfilerStarted.load( std::memory_order_seq_cst ) );+}+# endif++#ifdef __cplusplus+}+#endif++#endif
+ cbits/tracy/public/client/TracyProfiler.hpp view
@@ -0,0 +1,1089 @@+#ifndef __TRACYPROFILER_HPP__+#define __TRACYPROFILER_HPP__++#include <assert.h>+#include <atomic>+#include <stdint.h>+#include <string.h>+#include <time.h>++#include "tracy_concurrentqueue.h"+#include "tracy_SPSCQueue.h"+#include "TracyCallstack.hpp"+#include "TracyKCore.hpp"+#include "TracySysPower.hpp"+#include "TracySysTime.hpp"+#include "TracyFastVector.hpp"+#include "../common/TracyQueue.hpp"+#include "../common/TracyAlign.hpp"+#include "../common/TracyAlloc.hpp"+#include "../common/TracyMutex.hpp"+#include "../common/TracyProtocol.hpp"++#if defined _WIN32+# include <intrin.h>+#endif+#ifdef __APPLE__+# include <TargetConditionals.h>+# include <mach/mach_time.h>+#endif++#if ( (defined _WIN32 && !(defined _M_ARM64 || defined _M_ARM)) || ( defined __i386 || defined _M_IX86 || defined __x86_64__ || defined _M_X64 ) || ( defined TARGET_OS_IOS && TARGET_OS_IOS == 1 ) )+# define TRACY_HW_TIMER+#endif++#ifdef __linux__+# include <signal.h>+#endif++#if defined TRACY_TIMER_FALLBACK || !defined TRACY_HW_TIMER+# include <chrono>+#endif++#ifndef TracyConcat+# define TracyConcat(x,y) TracyConcatIndirect(x,y)+#endif+#ifndef TracyConcatIndirect+# define TracyConcatIndirect(x,y) x##y+#endif++namespace tracy+{+#if defined(TRACY_DELAYED_INIT) && defined(TRACY_MANUAL_LIFETIME)+TRACY_API void StartupProfiler();+TRACY_API void ShutdownProfiler();+TRACY_API bool IsProfilerStarted();+# define TracyIsStarted tracy::IsProfilerStarted()+#else+# define TracyIsStarted true+#endif++class GpuCtx;+class Profiler;+class Socket;+class UdpBroadcast;++struct GpuCtxWrapper+{+ GpuCtx* ptr;+};++TRACY_API moodycamel::ConcurrentQueue<QueueItem>::ExplicitProducer* GetToken();+TRACY_API Profiler& GetProfiler();+TRACY_API std::atomic<uint32_t>& GetLockCounter();+TRACY_API std::atomic<uint8_t>& GetGpuCtxCounter();+TRACY_API GpuCtxWrapper& GetGpuCtx();+TRACY_API uint32_t GetThreadHandle();+TRACY_API bool ProfilerAvailable();+TRACY_API bool ProfilerAllocatorAvailable();+TRACY_API int64_t GetFrequencyQpc();++#if defined TRACY_TIMER_FALLBACK && defined TRACY_HW_TIMER && ( defined __i386 || defined _M_IX86 || defined __x86_64__ || defined _M_X64 )+TRACY_API bool HardwareSupportsInvariantTSC(); // check, if we need fallback scenario+#else+# if defined TRACY_HW_TIMER+tracy_force_inline bool HardwareSupportsInvariantTSC()+{+ return true; // this is checked at startup+}+# else+tracy_force_inline bool HardwareSupportsInvariantTSC()+{+ return false;+}+# endif+#endif+++struct SourceLocationData+{+ const char* name;+ const char* function;+ const char* file;+ uint32_t line;+ uint32_t color;+};++#ifdef TRACY_ON_DEMAND+struct LuaZoneState+{+ uint32_t counter;+ bool active;+};+#endif+++#define TracyLfqPrepare( _type ) \+ tracy::moodycamel::ConcurrentQueueDefaultTraits::index_t __magic; \+ auto __token = tracy::GetToken(); \+ auto& __tail = __token->get_tail_index(); \+ auto item = __token->enqueue_begin( __magic ); \+ tracy::MemWrite( &item->hdr.type, _type );++#define TracyLfqCommit \+ __tail.store( __magic + 1, std::memory_order_release );++#define TracyLfqPrepareC( _type ) \+ tracy::moodycamel::ConcurrentQueueDefaultTraits::index_t __magic; \+ auto __token = tracy::GetToken(); \+ auto& __tail = __token->get_tail_index(); \+ auto item = __token->enqueue_begin( __magic ); \+ tracy::MemWrite( &item->hdr.type, _type );++#define TracyLfqCommitC \+ __tail.store( __magic + 1, std::memory_order_release );+++#ifdef TRACY_FIBERS+# define TracyQueuePrepare( _type ) \+ auto item = tracy::Profiler::QueueSerial(); \+ tracy::MemWrite( &item->hdr.type, _type );+# define TracyQueueCommit( _name ) \+ tracy::MemWrite( &item->_name.thread, tracy::GetThreadHandle() ); \+ tracy::Profiler::QueueSerialFinish();+# define TracyQueuePrepareC( _type ) \+ auto item = tracy::Profiler::QueueSerial(); \+ tracy::MemWrite( &item->hdr.type, _type );+# define TracyQueueCommitC( _name ) \+ tracy::MemWrite( &item->_name.thread, tracy::GetThreadHandle() ); \+ tracy::Profiler::QueueSerialFinish();+#else+# define TracyQueuePrepare( _type ) TracyLfqPrepare( _type )+# define TracyQueueCommit( _name ) TracyLfqCommit+# define TracyQueuePrepareC( _type ) TracyLfqPrepareC( _type )+# define TracyQueueCommitC( _name ) TracyLfqCommitC+#endif+++typedef void(*ParameterCallback)( void* data, uint32_t idx, int32_t val );+typedef char*(*SourceContentsCallback)( void* data, const char* filename, size_t& size );++class Profiler+{+ struct FrameImageQueueItem+ {+ void* image;+ uint32_t frame;+ uint16_t w;+ uint16_t h;+ bool flip;+ };++ enum class SymbolQueueItemType+ {+ CallstackFrame,+ SymbolQuery,+ ExternalName,+ KernelCode,+ SourceCode+ };++ struct SymbolQueueItem+ {+ SymbolQueueItemType type;+ uint64_t ptr;+ uint64_t extra;+ uint32_t id;+ };++public:+ Profiler();+ ~Profiler();++ void SpawnWorkerThreads();++ static tracy_force_inline int64_t GetTime()+ {+#ifdef TRACY_HW_TIMER+# if defined TARGET_OS_IOS && TARGET_OS_IOS == 1+ if( HardwareSupportsInvariantTSC() ) return mach_absolute_time();+# elif defined _WIN32+# ifdef TRACY_TIMER_QPC+ return GetTimeQpc();+# else+ if( HardwareSupportsInvariantTSC() ) return int64_t( __rdtsc() );+# endif+# elif defined __i386 || defined _M_IX86+ if( HardwareSupportsInvariantTSC() )+ {+ uint32_t eax, edx;+ asm volatile ( "rdtsc" : "=a" (eax), "=d" (edx) );+ return ( uint64_t( edx ) << 32 ) + uint64_t( eax );+ }+# elif defined __x86_64__ || defined _M_X64+ if( HardwareSupportsInvariantTSC() )+ {+ uint64_t rax, rdx;+#ifdef TRACY_PATCHABLE_NOPSLEDS+ // Some external tooling (such as rr) wants to patch our rdtsc and replace it by a+ // branch to control the external input seen by a program. This kind of patching is+ // not generally possible depending on the surrounding code and can lead to significant+ // slowdowns if the compiler generated unlucky code and rr and tracy are used together.+ // To avoid this, use the rr-safe `nopl 0(%rax, %rax, 1); rdtsc` instruction sequence,+ // which rr promises will be patchable independent of the surrounding code.+ asm volatile (+ // This is nopl 0(%rax, %rax, 1), but assemblers are inconsistent about whether+ // they emit that as a 4 or 5 byte sequence and we need to be guaranteed to use+ // the 5 byte one.+ ".byte 0x0f, 0x1f, 0x44, 0x00, 0x00\n\t"+ "rdtsc" : "=a" (rax), "=d" (rdx) );+#else+ asm volatile ( "rdtsc" : "=a" (rax), "=d" (rdx) );+#endif+ return (int64_t)(( rdx << 32 ) + rax);+ }+# else+# error "TRACY_HW_TIMER detection logic needs fixing"+# endif+#endif++#if !defined TRACY_HW_TIMER || defined TRACY_TIMER_FALLBACK+# if defined __linux__ && defined CLOCK_MONOTONIC_RAW+ struct timespec ts;+ clock_gettime( CLOCK_MONOTONIC_RAW, &ts );+ return int64_t( ts.tv_sec ) * 1000000000ll + int64_t( ts.tv_nsec );+# else+ return std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::high_resolution_clock::now().time_since_epoch() ).count();+# endif+#endif++#if !defined TRACY_TIMER_FALLBACK+ return 0; // unreachable branch+#endif+ }++ tracy_force_inline uint32_t GetNextZoneId()+ {+ return m_zoneId.fetch_add( 1, std::memory_order_relaxed );+ }++ static tracy_force_inline QueueItem* QueueSerial()+ {+ auto& p = GetProfiler();+ p.m_serialLock.lock();+ return p.m_serialQueue.prepare_next();+ }++ static tracy_force_inline QueueItem* QueueSerialCallstack( void* ptr )+ {+ auto& p = GetProfiler();+ p.m_serialLock.lock();+ p.SendCallstackSerial( ptr );+ return p.m_serialQueue.prepare_next();+ }++ static tracy_force_inline void QueueSerialFinish()+ {+ auto& p = GetProfiler();+ p.m_serialQueue.commit_next();+ p.m_serialLock.unlock();+ }++ static tracy_force_inline void SendFrameMark( const char* name )+ {+ if( !name ) GetProfiler().m_frameCount.fetch_add( 1, std::memory_order_relaxed );+#ifdef TRACY_ON_DEMAND+ if( !GetProfiler().IsConnected() ) return;+#endif+ auto item = QueueSerial();+ MemWrite( &item->hdr.type, QueueType::FrameMarkMsg );+ MemWrite( &item->frameMark.time, GetTime() );+ MemWrite( &item->frameMark.name, uint64_t( name ) );+ QueueSerialFinish();+ }++ static tracy_force_inline void SendFrameMark( const char* name, QueueType type )+ {+ assert( type == QueueType::FrameMarkMsgStart || type == QueueType::FrameMarkMsgEnd );+#ifdef TRACY_ON_DEMAND+ if( !GetProfiler().IsConnected() ) return;+#endif+ auto item = QueueSerial();+ MemWrite( &item->hdr.type, type );+ MemWrite( &item->frameMark.time, GetTime() );+ MemWrite( &item->frameMark.name, uint64_t( name ) );+ QueueSerialFinish();+ }++ static tracy_force_inline void SendFrameImage( const void* image, uint16_t w, uint16_t h, uint8_t offset, bool flip )+ {+#ifndef TRACY_NO_FRAME_IMAGE+ auto& profiler = GetProfiler();+ assert( profiler.m_frameCount.load( std::memory_order_relaxed ) < (std::numeric_limits<uint32_t>::max)() );+# ifdef TRACY_ON_DEMAND+ if( !profiler.IsConnected() ) return;+# endif+ const auto sz = size_t( w ) * size_t( h ) * 4;+ auto ptr = (char*)tracy_malloc( sz );+ memcpy( ptr, image, sz );++ profiler.m_fiLock.lock();+ auto fi = profiler.m_fiQueue.prepare_next();+ fi->image = ptr;+ fi->frame = uint32_t( profiler.m_frameCount.load( std::memory_order_relaxed ) - offset );+ fi->w = w;+ fi->h = h;+ fi->flip = flip;+ profiler.m_fiQueue.commit_next();+ profiler.m_fiLock.unlock();+#else+ static_cast<void>(image); // unused+ static_cast<void>(w); // unused+ static_cast<void>(h); // unused+ static_cast<void>(offset); // unused+ static_cast<void>(flip); // unused+#endif+ }++ static tracy_force_inline void PlotData( const char* name, int64_t val )+ {+#ifdef TRACY_ON_DEMAND+ if( !GetProfiler().IsConnected() ) return;+#endif+ TracyLfqPrepare( QueueType::PlotDataInt );+ MemWrite( &item->plotDataInt.name, (uint64_t)name );+ MemWrite( &item->plotDataInt.time, GetTime() );+ MemWrite( &item->plotDataInt.val, val );+ TracyLfqCommit;+ }++ static tracy_force_inline void PlotData( const char* name, float val )+ {+#ifdef TRACY_ON_DEMAND+ if( !GetProfiler().IsConnected() ) return;+#endif+ TracyLfqPrepare( QueueType::PlotDataFloat );+ MemWrite( &item->plotDataFloat.name, (uint64_t)name );+ MemWrite( &item->plotDataFloat.time, GetTime() );+ MemWrite( &item->plotDataFloat.val, val );+ TracyLfqCommit;+ }++ static tracy_force_inline void PlotData( const char* name, double val )+ {+#ifdef TRACY_ON_DEMAND+ if( !GetProfiler().IsConnected() ) return;+#endif+ TracyLfqPrepare( QueueType::PlotDataDouble );+ MemWrite( &item->plotDataDouble.name, (uint64_t)name );+ MemWrite( &item->plotDataDouble.time, GetTime() );+ MemWrite( &item->plotDataDouble.val, val );+ TracyLfqCommit;+ }++ static tracy_force_inline void ConfigurePlot( const char* name, PlotFormatType type, bool step, bool fill, uint32_t color )+ {+ TracyLfqPrepare( QueueType::PlotConfig );+ MemWrite( &item->plotConfig.name, (uint64_t)name );+ MemWrite( &item->plotConfig.type, (uint8_t)type );+ MemWrite( &item->plotConfig.step, (uint8_t)step );+ MemWrite( &item->plotConfig.fill, (uint8_t)fill );+ MemWrite( &item->plotConfig.color, color );++#ifdef TRACY_ON_DEMAND+ GetProfiler().DeferItem( *item );+#endif++ TracyLfqCommit;+ }++ static tracy_force_inline void Message( const char* txt, size_t size, int32_t callstack_depth )+ {+ assert( size < (std::numeric_limits<uint16_t>::max)() );+#ifdef TRACY_ON_DEMAND+ if( !GetProfiler().IsConnected() ) return;+#endif+ if( callstack_depth != 0 && has_callstack() )+ {+ tracy::GetProfiler().SendCallstack( callstack_depth );+ }++ auto ptr = (char*)tracy_malloc( size );+ memcpy( ptr, txt, size );++ TracyQueuePrepare( callstack_depth == 0 ? QueueType::Message : QueueType::MessageCallstack );+ MemWrite( &item->messageFat.time, GetTime() );+ MemWrite( &item->messageFat.text, (uint64_t)ptr );+ MemWrite( &item->messageFat.size, (uint16_t)size );+ TracyQueueCommit( messageFatThread );+ }++ static tracy_force_inline void Message( const char* txt, int32_t callstack_depth )+ {+#ifdef TRACY_ON_DEMAND+ if( !GetProfiler().IsConnected() ) return;+#endif+ if( callstack_depth != 0 && has_callstack() )+ {+ tracy::GetProfiler().SendCallstack( callstack_depth );+ }++ TracyQueuePrepare( callstack_depth == 0 ? QueueType::MessageLiteral : QueueType::MessageLiteralCallstack );+ MemWrite( &item->messageLiteral.time, GetTime() );+ MemWrite( &item->messageLiteral.text, (uint64_t)txt );+ TracyQueueCommit( messageLiteralThread );+ }++ static tracy_force_inline void MessageColor( const char* txt, size_t size, uint32_t color, int32_t callstack_depth )+ {+ assert( size < (std::numeric_limits<uint16_t>::max)() );+#ifdef TRACY_ON_DEMAND+ if( !GetProfiler().IsConnected() ) return;+#endif+ if( callstack_depth != 0 && has_callstack() )+ {+ tracy::GetProfiler().SendCallstack( callstack_depth );+ }++ auto ptr = (char*)tracy_malloc( size );+ memcpy( ptr, txt, size );++ TracyQueuePrepare( callstack_depth == 0 ? QueueType::MessageColor : QueueType::MessageColorCallstack );+ MemWrite( &item->messageColorFat.time, GetTime() );+ MemWrite( &item->messageColorFat.text, (uint64_t)ptr );+ MemWrite( &item->messageColorFat.b, uint8_t( ( color ) & 0xFF ) );+ MemWrite( &item->messageColorFat.g, uint8_t( ( color >> 8 ) & 0xFF ) );+ MemWrite( &item->messageColorFat.r, uint8_t( ( color >> 16 ) & 0xFF ) );+ MemWrite( &item->messageColorFat.size, (uint16_t)size );+ TracyQueueCommit( messageColorFatThread );+ }++ static tracy_force_inline void MessageColor( const char* txt, uint32_t color, int32_t callstack_depth )+ {+#ifdef TRACY_ON_DEMAND+ if( !GetProfiler().IsConnected() ) return;+#endif+ if( callstack_depth != 0 && has_callstack() )+ {+ tracy::GetProfiler().SendCallstack( callstack_depth );+ }++ TracyQueuePrepare( callstack_depth == 0 ? QueueType::MessageLiteralColor : QueueType::MessageLiteralColorCallstack );+ MemWrite( &item->messageColorLiteral.time, GetTime() );+ MemWrite( &item->messageColorLiteral.text, (uint64_t)txt );+ MemWrite( &item->messageColorLiteral.b, uint8_t( ( color ) & 0xFF ) );+ MemWrite( &item->messageColorLiteral.g, uint8_t( ( color >> 8 ) & 0xFF ) );+ MemWrite( &item->messageColorLiteral.r, uint8_t( ( color >> 16 ) & 0xFF ) );+ TracyQueueCommit( messageColorLiteralThread );+ }++ static tracy_force_inline void MessageAppInfo( const char* txt, size_t size )+ {+ assert( size < (std::numeric_limits<uint16_t>::max)() );+ auto ptr = (char*)tracy_malloc( size );+ memcpy( ptr, txt, size );+ TracyLfqPrepare( QueueType::MessageAppInfo );+ MemWrite( &item->messageFat.time, GetTime() );+ MemWrite( &item->messageFat.text, (uint64_t)ptr );+ MemWrite( &item->messageFat.size, (uint16_t)size );++#ifdef TRACY_ON_DEMAND+ GetProfiler().DeferItem( *item );+#endif++ TracyLfqCommit;+ }++ static tracy_force_inline void MemAlloc( const void* ptr, size_t size, bool secure )+ {+ if( secure && !ProfilerAvailable() ) return;+#ifdef TRACY_ON_DEMAND+ if( !GetProfiler().IsConnected() ) return;+#endif+ const auto thread = GetThreadHandle();++ GetProfiler().m_serialLock.lock();+ SendMemAlloc( QueueType::MemAlloc, thread, ptr, size );+ GetProfiler().m_serialLock.unlock();+ }++ static tracy_force_inline void MemFree( const void* ptr, bool secure )+ {+ if( secure && !ProfilerAvailable() ) return;+#ifdef TRACY_ON_DEMAND+ if( !GetProfiler().IsConnected() ) return;+#endif+ const auto thread = GetThreadHandle();++ GetProfiler().m_serialLock.lock();+ SendMemFree( QueueType::MemFree, thread, ptr );+ GetProfiler().m_serialLock.unlock();+ }++ static tracy_force_inline void MemAllocCallstack( const void* ptr, size_t size, int32_t depth, bool secure )+ {+ if( secure && !ProfilerAvailable() ) return;+ if( depth > 0 && has_callstack() )+ {+ auto& profiler = GetProfiler();+# ifdef TRACY_ON_DEMAND+ if( !profiler.IsConnected() ) return;+# endif+ const auto thread = GetThreadHandle();++ auto callstack = Callstack( depth );++ profiler.m_serialLock.lock();+ SendCallstackSerial( callstack );+ SendMemAlloc( QueueType::MemAllocCallstack, thread, ptr, size );+ profiler.m_serialLock.unlock();+ }+ else+ {+ MemAlloc( ptr, size, secure );+ }+ }++ static tracy_force_inline void MemFreeCallstack( const void* ptr, int32_t depth, bool secure )+ {+ if( secure && !ProfilerAvailable() ) return;+ if( !ProfilerAllocatorAvailable() )+ {+ MemFree( ptr, secure );+ return;+ }+ if( depth > 0 && has_callstack() )+ {+ auto& profiler = GetProfiler();+# ifdef TRACY_ON_DEMAND+ if( !profiler.IsConnected() ) return;+# endif+ const auto thread = GetThreadHandle();++ auto callstack = Callstack( depth );++ profiler.m_serialLock.lock();+ SendCallstackSerial( callstack );+ SendMemFree( QueueType::MemFreeCallstack, thread, ptr );+ profiler.m_serialLock.unlock();+ }+ else+ {+ MemFree( ptr, secure );+ }+ }++ static tracy_force_inline void MemAllocNamed( const void* ptr, size_t size, bool secure, const char* name )+ {+ if( secure && !ProfilerAvailable() ) return;+#ifdef TRACY_ON_DEMAND+ if( !GetProfiler().IsConnected() ) return;+#endif+ const auto thread = GetThreadHandle();++ GetProfiler().m_serialLock.lock();+ SendMemName( name );+ SendMemAlloc( QueueType::MemAllocNamed, thread, ptr, size );+ GetProfiler().m_serialLock.unlock();+ }++ static tracy_force_inline void MemFreeNamed( const void* ptr, bool secure, const char* name )+ {+ if( secure && !ProfilerAvailable() ) return;+#ifdef TRACY_ON_DEMAND+ if( !GetProfiler().IsConnected() ) return;+#endif+ const auto thread = GetThreadHandle();++ GetProfiler().m_serialLock.lock();+ SendMemName( name );+ SendMemFree( QueueType::MemFreeNamed, thread, ptr );+ GetProfiler().m_serialLock.unlock();+ }++ static tracy_force_inline void MemAllocCallstackNamed( const void* ptr, size_t size, int32_t depth, bool secure, const char* name )+ {+ if( secure && !ProfilerAvailable() ) return;+ if( depth > 0 && has_callstack() )+ {+ auto& profiler = GetProfiler();+# ifdef TRACY_ON_DEMAND+ if( !profiler.IsConnected() ) return;+# endif+ const auto thread = GetThreadHandle();++ auto callstack = Callstack( depth );++ profiler.m_serialLock.lock();+ SendCallstackSerial( callstack );+ SendMemName( name );+ SendMemAlloc( QueueType::MemAllocCallstackNamed, thread, ptr, size );+ profiler.m_serialLock.unlock();+ }+ else+ {+ MemAllocNamed( ptr, size, secure, name );+ }+ }++ static tracy_force_inline void MemFreeCallstackNamed( const void* ptr, int32_t depth, bool secure, const char* name )+ {+ if( secure && !ProfilerAvailable() ) return;+ if( depth > 0 && has_callstack() )+ {+ auto& profiler = GetProfiler();+# ifdef TRACY_ON_DEMAND+ if( !profiler.IsConnected() ) return;+# endif+ const auto thread = GetThreadHandle();++ auto callstack = Callstack( depth );++ profiler.m_serialLock.lock();+ SendCallstackSerial( callstack );+ SendMemName( name );+ SendMemFree( QueueType::MemFreeCallstackNamed, thread, ptr );+ profiler.m_serialLock.unlock();+ }+ else+ {+ MemFreeNamed( ptr, secure, name );+ }+ }++ static tracy_force_inline void MemDiscard( const char* name, bool secure )+ {+ if( secure && !ProfilerAvailable() ) return;+#ifdef TRACY_ON_DEMAND+ if( !GetProfiler().IsConnected() ) return;+#endif+ const auto thread = GetThreadHandle();++ GetProfiler().m_serialLock.lock();+ SendMemDiscard( QueueType::MemDiscard, thread, name );+ GetProfiler().m_serialLock.unlock();+ }++ static tracy_force_inline void MemDiscardCallstack( const char* name, bool secure, int32_t depth )+ {+ if( secure && !ProfilerAvailable() ) return;+ if( depth > 0 && has_callstack() )+ {+# ifdef TRACY_ON_DEMAND+ if( !GetProfiler().IsConnected() ) return;+# endif+ const auto thread = GetThreadHandle();++ auto callstack = Callstack( depth );++ GetProfiler().m_serialLock.lock();+ SendCallstackSerial( callstack );+ SendMemDiscard( QueueType::MemDiscard, thread, name );+ GetProfiler().m_serialLock.unlock();+ }+ else+ {+ MemDiscard( name, secure );+ }+ }++ static tracy_force_inline void SendCallstack( int32_t depth )+ {+ if( depth > 0 && has_callstack() )+ {+ auto ptr = Callstack( depth );+ TracyQueuePrepare( QueueType::Callstack );+ MemWrite( &item->callstackFat.ptr, (uint64_t)ptr );+ TracyQueueCommit( callstackFatThread );+ }+ }++ static tracy_force_inline void ParameterRegister( ParameterCallback cb, void* data )+ {+ auto& profiler = GetProfiler();+ profiler.m_paramCallback = cb;+ profiler.m_paramCallbackData = data;+ }++ static tracy_force_inline void ParameterSetup( uint32_t idx, const char* name, bool isBool, int32_t val )+ {+ TracyLfqPrepare( QueueType::ParamSetup );+ tracy::MemWrite( &item->paramSetup.idx, idx );+ tracy::MemWrite( &item->paramSetup.name, (uint64_t)name );+ tracy::MemWrite( &item->paramSetup.isBool, (uint8_t)isBool );+ tracy::MemWrite( &item->paramSetup.val, val );++#ifdef TRACY_ON_DEMAND+ GetProfiler().DeferItem( *item );+#endif++ TracyLfqCommit;+ }++ static tracy_force_inline void SourceCallbackRegister( SourceContentsCallback cb, void* data )+ {+ auto& profiler = GetProfiler();+ profiler.m_sourceCallback = cb;+ profiler.m_sourceCallbackData = data;+ }++#ifdef TRACY_FIBERS+ static tracy_force_inline void EnterFiber( const char* fiber, int32_t groupHint )+ {+ TracyQueuePrepare( QueueType::FiberEnter );+ MemWrite( &item->fiberEnter.time, GetTime() );+ MemWrite( &item->fiberEnter.fiber, (uint64_t)fiber );+ MemWrite( &item->fiberEnter.groupHint, groupHint );+ TracyQueueCommit( fiberEnter );+ }++ static tracy_force_inline void LeaveFiber()+ {+ TracyQueuePrepare( QueueType::FiberLeave );+ MemWrite( &item->fiberLeave.time, GetTime() );+ TracyQueueCommit( fiberLeave );+ }+#endif++ void SendCallstack( int32_t depth, const char* skipBefore );+ static void CutCallstack( void* callstack, const char* skipBefore );++ static bool ShouldExit();++ tracy_force_inline bool IsConnected() const+ {+ return m_isConnected.load( std::memory_order_acquire );+ }++ tracy_force_inline void SetProgramName( const char* name )+ {+ m_programNameLock.lock();+ m_programName = name;+ m_programNameLock.unlock();+ }++#ifdef TRACY_ON_DEMAND+ tracy_force_inline uint64_t ConnectionId() const+ {+ return m_connectionId.load( std::memory_order_acquire );+ }++ tracy_force_inline void DeferItem( const QueueItem& item )+ {+ m_deferredLock.lock();+ auto dst = m_deferredQueue.push_next();+ memcpy( dst, &item, sizeof( item ) );+ m_deferredLock.unlock();+ }+#endif++ void RequestShutdown() { m_shutdown.store( true, std::memory_order_relaxed ); m_shutdownManual.store( true, std::memory_order_relaxed ); }+ bool HasShutdownFinished() const { return m_shutdownFinished.load( std::memory_order_relaxed ); }++ void SendString( uint64_t str, const char* ptr, QueueType type ) { SendString( str, ptr, strlen( ptr ), type ); }+ void SendString( uint64_t str, const char* ptr, size_t len, QueueType type );+ void SendSingleString( const char* ptr ) { SendSingleString( ptr, strlen( ptr ) ); }+ void SendSingleString( const char* ptr, size_t len );+ void SendSecondString( const char* ptr ) { SendSecondString( ptr, strlen( ptr ) ); }+ void SendSecondString( const char* ptr, size_t len );+++ // Allocated source location data layout:+ // 2b payload size+ // 4b color+ // 4b source line+ // fsz function name+ // 1b null terminator+ // ssz source file name+ // 1b null terminator+ // nsz zone name (optional)++ static tracy_force_inline uint64_t AllocSourceLocation( uint32_t line, const char* source, const char* function, uint32_t color = 0 )+ {+ return AllocSourceLocation( line, source, function, nullptr, 0, color );+ }++ static tracy_force_inline uint64_t AllocSourceLocation( uint32_t line, const char* source, const char* function, const char* name, size_t nameSz, uint32_t color = 0 )+ {+ return AllocSourceLocation( line, source, strlen(source), function, strlen(function), name, nameSz, color );+ }++ static tracy_force_inline uint64_t AllocSourceLocation( uint32_t line, const char* source, size_t sourceSz, const char* function, size_t functionSz, uint32_t color = 0 )+ {+ return AllocSourceLocation( line, source, sourceSz, function, functionSz, nullptr, 0, color );+ }++ static tracy_force_inline uint64_t AllocSourceLocation( uint32_t line, const char* source, size_t sourceSz, const char* function, size_t functionSz, const char* name, size_t nameSz, uint32_t color = 0 )+ {+ const auto sz32 = uint32_t( 2 + 4 + 4 + functionSz + 1 + sourceSz + 1 + nameSz );+ assert( sz32 <= (std::numeric_limits<uint16_t>::max)() );+ const auto sz = uint16_t( sz32 );+ auto ptr = (char*)tracy_malloc( sz );+ memcpy( ptr, &sz, 2 );+ memcpy( ptr + 2, &color, 4 );+ memcpy( ptr + 6, &line, 4 );+ memcpy( ptr + 10, function, functionSz );+ ptr[10 + functionSz] = '\0';+ memcpy( ptr + 10 + functionSz + 1, source, sourceSz );+ ptr[10 + functionSz + 1 + sourceSz] = '\0';+ if( nameSz != 0 )+ {+ memcpy( ptr + 10 + functionSz + 1 + sourceSz + 1, name, nameSz );+ }+ return uint64_t( ptr );+ }++private:+ enum class DequeueStatus { DataDequeued, ConnectionLost, QueueEmpty };+ enum class ThreadCtxStatus { Same, Changed, ConnectionLost };++ static void LaunchWorker( void* ptr ) { ((Profiler*)ptr)->Worker(); }+ void Worker();++#ifndef TRACY_NO_FRAME_IMAGE+ static void LaunchCompressWorker( void* ptr ) { ((Profiler*)ptr)->CompressWorker(); }+ void CompressWorker();+#endif++#ifdef TRACY_HAS_CALLSTACK+ static void LaunchSymbolWorker( void* ptr ) { ((Profiler*)ptr)->SymbolWorker(); }+ void SymbolWorker();+ void HandleSymbolQueueItem( const SymbolQueueItem& si );+#endif++ void InstallCrashHandler();+ void RemoveCrashHandler();++ void ClearQueues( tracy::moodycamel::ConsumerToken& token );+ void ClearSerial();+ DequeueStatus Dequeue( tracy::moodycamel::ConsumerToken& token );+ DequeueStatus DequeueContextSwitches( tracy::moodycamel::ConsumerToken& token, int64_t& timeStop );+ DequeueStatus DequeueSerial();+ ThreadCtxStatus ThreadCtxCheck( uint32_t threadId );+ bool CommitData();++ tracy_force_inline bool AppendData( const void* data, size_t len )+ {+ const auto ret = NeedDataSize( len );+ AppendDataUnsafe( data, len );+ return ret;+ }++ tracy_force_inline bool NeedDataSize( size_t len )+ {+ assert( len <= TargetFrameSize );+ bool ret = true;+ if( m_bufferOffset - m_bufferStart + (int)len > TargetFrameSize )+ {+ ret = CommitData();+ }+ return ret;+ }++ tracy_force_inline void AppendDataUnsafe( const void* data, size_t len )+ {+ memcpy( m_buffer + m_bufferOffset, data, len );+ m_bufferOffset += int( len );+ }++ char* SafeCopyProlog( const char* p, size_t size );+ void SafeCopyEpilog( char* buf );++ template<class Callable> // must be void( const char* buf, size_t size )+ bool WithSafeCopy( const char* p, size_t size, Callable&& callable )+ {+ if( char* buf = SafeCopyProlog( p, size ) )+ {+ callable( buf, size );+ SafeCopyEpilog( buf );+ return true;+ }+ return false;+ }++ bool SendData( const char* data, size_t len );+ void SendLongString( uint64_t ptr, const char* str, size_t len, QueueType type );+ void SendSourceLocation( uint64_t ptr );+ void SendSourceLocationPayload( uint64_t ptr );+ void SendCallstackPayload( uint64_t ptr );+ void SendCallstackPayload64( uint64_t ptr );+ void SendCallstackAlloc( uint64_t ptr );++ void QueueCallstackFrame( uint64_t ptr );+ void QueueSymbolQuery( uint64_t symbol );+ void QueueExternalName( uint64_t ptr );+ void QueueKernelCode( uint64_t symbol, uint32_t size );+ void QueueSourceCodeQuery( uint32_t id );++ bool HandleServerQuery();+ void HandleDisconnect();+ void HandleParameter( uint64_t payload );+ void HandleSymbolCodeQuery( uint64_t symbol, uint32_t size );+ void HandleSourceCodeQuery( char* data, char* image, uint32_t id );++ void AckServerQuery();+ void AckSymbolCodeNotAvailable();++ void CalibrateTimer();+ void CalibrateDelay();+ void ReportTopology();++ static tracy_force_inline void SendCallstackSerial( void* ptr )+ {+ if( has_callstack() )+ {+ auto item = GetProfiler().m_serialQueue.prepare_next();+ MemWrite( &item->hdr.type, QueueType::CallstackSerial );+ MemWrite( &item->callstackFat.ptr, (uint64_t)ptr );+ GetProfiler().m_serialQueue.commit_next();+ }+ }++ static tracy_force_inline void SendMemAlloc( QueueType type, const uint32_t thread, const void* ptr, size_t size )+ {+ assert( type == QueueType::MemAlloc || type == QueueType::MemAllocCallstack || type == QueueType::MemAllocNamed || type == QueueType::MemAllocCallstackNamed );++ auto item = GetProfiler().m_serialQueue.prepare_next();+ MemWrite( &item->hdr.type, type );+ MemWrite( &item->memAlloc.time, GetTime() );+ MemWrite( &item->memAlloc.thread, thread );+ MemWrite( &item->memAlloc.ptr, (uint64_t)ptr );+ if( compile_time_condition<sizeof( size ) == 4>::value )+ {+ memcpy( &item->memAlloc.size, &size, 4 );+ memset( &item->memAlloc.size + 4, 0, 2 );+ }+ else+ {+ assert( sizeof( size ) == 8 );+ memcpy( &item->memAlloc.size, &size, 4 );+ memcpy( ((char*)&item->memAlloc.size)+4, ((char*)&size)+4, 2 );+ }+ GetProfiler().m_serialQueue.commit_next();+ }++ static tracy_force_inline void SendMemFree( QueueType type, const uint32_t thread, const void* ptr )+ {+ assert( type == QueueType::MemFree || type == QueueType::MemFreeCallstack || type == QueueType::MemFreeNamed || type == QueueType::MemFreeCallstackNamed );++ auto item = GetProfiler().m_serialQueue.prepare_next();+ MemWrite( &item->hdr.type, type );+ MemWrite( &item->memFree.time, GetTime() );+ MemWrite( &item->memFree.thread, thread );+ MemWrite( &item->memFree.ptr, (uint64_t)ptr );+ GetProfiler().m_serialQueue.commit_next();+ }++ static tracy_force_inline void SendMemDiscard( QueueType type, const uint32_t thread, const char* name )+ {+ assert( type == QueueType::MemDiscard || type == QueueType::MemDiscardCallstack );++ auto item = GetProfiler().m_serialQueue.prepare_next();+ MemWrite( &item->hdr.type, type );+ MemWrite( &item->memDiscard.time, GetTime() );+ MemWrite( &item->memDiscard.thread, thread );+ MemWrite( &item->memDiscard.name, (uint64_t)name );+ GetProfiler().m_serialQueue.commit_next();+ }++ static tracy_force_inline void SendMemName( const char* name )+ {+ assert( name );+ auto item = GetProfiler().m_serialQueue.prepare_next();+ MemWrite( &item->hdr.type, QueueType::MemNamePayload );+ MemWrite( &item->memName.name, (uint64_t)name );+ GetProfiler().m_serialQueue.commit_next();+ }++#if defined _WIN32 && defined TRACY_TIMER_QPC+ static int64_t GetTimeQpc();+#endif++ double m_timerMul;+ uint64_t m_resolution;+ uint64_t m_delay;+ std::atomic<int64_t> m_timeBegin;+ uint32_t m_mainThread;+ uint64_t m_epoch, m_exectime;+ std::atomic<bool> m_shutdown;+ std::atomic<bool> m_shutdownManual;+ std::atomic<bool> m_shutdownFinished;+ Socket* m_sock;+ UdpBroadcast* m_broadcast;+ bool m_noExit;+ uint32_t m_userPort;+ std::atomic<uint32_t> m_zoneId;+ int64_t m_samplingPeriod;++ uint32_t m_threadCtx;+ int64_t m_refTimeThread;+ int64_t m_refTimeSerial;+ int64_t m_refTimeCtx;+ int64_t m_refTimeGpu;++ void* m_stream; // LZ4_stream_t*+ char* m_buffer;+ int m_bufferOffset;+ int m_bufferStart;++ char* m_lz4Buf;++ FastVector<QueueItem> m_serialQueue, m_serialDequeue;+ TracyMutex m_serialLock;++#ifndef TRACY_NO_FRAME_IMAGE+ FastVector<FrameImageQueueItem> m_fiQueue, m_fiDequeue;+ TracyMutex m_fiLock;+#endif++ SPSCQueue<SymbolQueueItem> m_symbolQueue;++ std::atomic<uint64_t> m_frameCount;+ std::atomic<bool> m_isConnected;+#ifdef TRACY_ON_DEMAND+ std::atomic<uint64_t> m_connectionId;++ TracyMutex m_deferredLock;+ FastVector<QueueItem> m_deferredQueue;+#endif++#ifdef TRACY_HAS_SYSTIME+ void ProcessSysTime();++ SysTime m_sysTime;+ uint64_t m_sysTimeLast = 0;+#else+ void ProcessSysTime() {}+#endif++#ifdef TRACY_HAS_SYSPOWER+ SysPower m_sysPower;+#endif++ ParameterCallback m_paramCallback;+ void* m_paramCallbackData;+ SourceContentsCallback m_sourceCallback;+ void* m_sourceCallbackData;++ char* m_queryImage;+ char* m_queryData;+ char* m_queryDataPtr;++#ifndef NDEBUG+ // m_safeSendBuffer and m_pipe should only be used by the Tracy Profiler thread; this ensures that in debug builds.+ std::atomic_bool m_inUse{ false };+#endif+ char* m_safeSendBuffer;++#if defined _WIN32+ void* m_prevHandler;+#else+ int m_pipe[2];+ int m_pipeBufSize;+#endif++#ifdef __linux__+ struct {+ struct sigaction pwr, ill, fpe, segv, pipe, bus, abrt;+ } m_prevSignal;+ KCore* m_kcore;+#endif+ bool m_crashHandlerInstalled;++ const char* m_programName;+ TracyMutex m_programNameLock;+};++}++#endif
+ cbits/tracy/public/client/TracyRingBuffer.hpp view
@@ -0,0 +1,141 @@+#include <atomic>+#include <assert.h>+#include <errno.h>+#include <linux/perf_event.h>+#include <stdint.h>+#include <string.h>+#include <sys/ioctl.h>+#include <sys/mman.h>+#include <unistd.h>++#include "TracyDebug.hpp"++namespace tracy+{++class RingBuffer+{+public:+ RingBuffer( unsigned int size, int fd, int id, int cpu = -1 )+ : m_size( size )+ , m_id( id )+ , m_cpu( cpu )+ , m_fd( fd )+ {+ const auto pageSize = uint32_t( getpagesize() );+ assert( size >= pageSize );+ assert( __builtin_popcount( size ) == 1 );+ m_mapSize = size + pageSize;+ auto mapAddr = mmap( nullptr, m_mapSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );+ if( mapAddr == MAP_FAILED )+ {+ TracyDebug( "mmap failed: errno %i (%s)\n", errno, strerror( errno ) );+ m_fd = 0;+ m_metadata = nullptr;+ close( fd );+ return;+ }+ m_metadata = (perf_event_mmap_page*)mapAddr;+ assert( m_metadata->data_offset == pageSize );+ m_buffer = ((char*)mapAddr) + pageSize;+ m_tail = m_metadata->data_tail;+ }++ ~RingBuffer()+ {+ if( m_metadata ) munmap( m_metadata, m_mapSize );+ if( m_fd ) close( m_fd );+ }++ RingBuffer( const RingBuffer& ) = delete;+ RingBuffer& operator=( const RingBuffer& ) = delete;++ RingBuffer( RingBuffer&& other )+ {+ memcpy( (char*)&other, (char*)this, sizeof( RingBuffer ) );+ m_metadata = nullptr;+ m_fd = 0;+ }++ RingBuffer& operator=( RingBuffer&& other )+ {+ memcpy( (char*)&other, (char*)this, sizeof( RingBuffer ) );+ m_metadata = nullptr;+ m_fd = 0;+ return *this;+ }++ bool IsValid() const { return m_metadata != nullptr; }+ int GetId() const { return m_id; }+ int GetCpu() const { return m_cpu; }++ void Enable()+ {+ ioctl( m_fd, PERF_EVENT_IOC_ENABLE, 0 );+ }++ void Read( void* dst, uint64_t offset, uint64_t cnt )+ {+ const auto size = m_size;+ auto src = ( m_tail + offset ) % size;+ if( src + cnt <= size )+ {+ memcpy( dst, m_buffer + src, cnt );+ }+ else+ {+ const auto s0 = size - src;+ const auto buf = m_buffer;+ memcpy( dst, buf + src, s0 );+ memcpy( (char*)dst + s0, buf, cnt - s0 );+ }+ }++ void Advance( uint64_t cnt )+ {+ m_tail += cnt;+ StoreTail();+ }++ bool CheckTscCaps() const+ {+ return m_metadata->cap_user_time_zero;+ }++ int64_t ConvertTimeToTsc( int64_t timestamp ) const+ {+ if( !m_metadata->cap_user_time_zero ) return 0;+ const auto time = timestamp - m_metadata->time_zero;+ const auto quot = time / m_metadata->time_mult;+ const auto rem = time % m_metadata->time_mult;+ return ( quot << m_metadata->time_shift ) + ( rem << m_metadata->time_shift ) / m_metadata->time_mult;+ }++ uint64_t LoadHead() const+ {+ return std::atomic_load_explicit( (const volatile std::atomic<uint64_t>*)&m_metadata->data_head, std::memory_order_acquire );+ }++ uint64_t GetTail() const+ {+ return m_tail;+ }++private:+ void StoreTail()+ {+ std::atomic_store_explicit( (volatile std::atomic<uint64_t>*)&m_metadata->data_tail, m_tail, std::memory_order_release );+ }++ unsigned int m_size;+ uint64_t m_tail;+ char* m_buffer;+ int m_id;+ int m_cpu;+ perf_event_mmap_page* m_metadata;++ size_t m_mapSize;+ int m_fd;+};++}
+ cbits/tracy/public/client/TracyScoped.hpp view
@@ -0,0 +1,201 @@+#ifndef __TRACYSCOPED_HPP__+#define __TRACYSCOPED_HPP__++#include <limits>+#include <stdarg.h>+#include <stdint.h>+#include <string.h>++#include "../common/TracySystem.hpp"+#include "../common/TracyAlign.hpp"+#include "../common/TracyAlloc.hpp"+#include "TracyProfiler.hpp"+#include "TracyCallstack.hpp"++namespace tracy+{++class ScopedZone+{+public:+ ScopedZone( const ScopedZone& ) = delete;+ ScopedZone( ScopedZone&& ) = delete;+ ScopedZone& operator=( const ScopedZone& ) = delete;+ ScopedZone& operator=( ScopedZone&& ) = delete;++ tracy_force_inline ScopedZone( const SourceLocationData* srcloc, int32_t depth = -1, bool is_active = true )+#ifdef TRACY_ON_DEMAND+ : m_active( is_active && GetProfiler().IsConnected() )+#else+ : m_active( is_active )+#endif+ {+ if( !m_active ) return;+#ifdef TRACY_ON_DEMAND+ m_connectionId = GetProfiler().ConnectionId();+#endif+ auto zoneQueue = QueueType::ZoneBegin;+ if( depth > 0 && has_callstack() )+ {+ GetProfiler().SendCallstack( depth );+ zoneQueue = QueueType::ZoneBeginCallstack;+ }+ TracyQueuePrepare( zoneQueue );+ MemWrite( &item->zoneBegin.time, Profiler::GetTime() );+ MemWrite( &item->zoneBegin.srcloc, (uint64_t)srcloc );+ TracyQueueCommit( zoneBeginThread );+ }++ tracy_force_inline ScopedZone( uint32_t line, const char* source, size_t sourceSz, const char* function, size_t functionSz, const char* name, size_t nameSz, uint32_t color, int32_t depth = -1, bool is_active = true )+#ifdef TRACY_ON_DEMAND+ : m_active( is_active && GetProfiler().IsConnected() )+#else+ : m_active( is_active )+#endif+ {+ if( !m_active ) return;+#ifdef TRACY_ON_DEMAND+ m_connectionId = GetProfiler().ConnectionId();+#endif+ auto zoneQueue = QueueType::ZoneBeginAllocSrcLoc;+ if( depth > 0 && has_callstack() )+ {+ GetProfiler().SendCallstack( depth );+ zoneQueue = QueueType::ZoneBeginAllocSrcLocCallstack;+ }+ TracyQueuePrepare( zoneQueue );+ const auto srcloc =+ Profiler::AllocSourceLocation( line, source, sourceSz, function, functionSz, name, nameSz, color );+ MemWrite( &item->zoneBegin.time, Profiler::GetTime() );+ MemWrite( &item->zoneBegin.srcloc, srcloc );+ TracyQueueCommit( zoneBeginThread );+ }++ tracy_force_inline ScopedZone( uint32_t line, const char* source, size_t sourceSz, const char* function, size_t functionSz, const char* name, size_t nameSz, int32_t depth, bool is_active = true ) : ScopedZone( line, source, sourceSz, function, functionSz, name, nameSz, 0, depth, is_active ) {}++ tracy_force_inline ~ScopedZone()+ {+ if( !m_active ) return;+#ifdef TRACY_ON_DEMAND+ if( GetProfiler().ConnectionId() != m_connectionId ) return;+#endif+ TracyQueuePrepare( QueueType::ZoneEnd );+ MemWrite( &item->zoneEnd.time, Profiler::GetTime() );+ TracyQueueCommit( zoneEndThread );+ }++ tracy_force_inline void Text( const char* txt, size_t size )+ {+ assert( size < (std::numeric_limits<uint16_t>::max)() );+ if( !m_active ) return;+#ifdef TRACY_ON_DEMAND+ if( GetProfiler().ConnectionId() != m_connectionId ) return;+#endif+ auto ptr = (char*)tracy_malloc( size );+ memcpy( ptr, txt, size );+ TracyQueuePrepare( QueueType::ZoneText );+ MemWrite( &item->zoneTextFat.text, (uint64_t)ptr );+ MemWrite( &item->zoneTextFat.size, (uint16_t)size );+ TracyQueueCommit( zoneTextFatThread );+ }++ void TextFmt( const char* fmt, ... )+ {+ if( !m_active ) return;+#ifdef TRACY_ON_DEMAND+ if( GetProfiler().ConnectionId() != m_connectionId ) return;+#endif+ va_list args;+ va_start( args, fmt );+ auto size = vsnprintf( nullptr, 0, fmt, args );+ va_end( args );+ if( size < 0 ) return;+ assert( size < (std::numeric_limits<uint16_t>::max)() );++ char* ptr = (char*)tracy_malloc( size_t( size ) + 1 );+ va_start( args, fmt );+ vsnprintf( ptr, size_t( size ) + 1, fmt, args );+ va_end( args );++ TracyQueuePrepare( QueueType::ZoneText );+ MemWrite( &item->zoneTextFat.text, (uint64_t)ptr );+ MemWrite( &item->zoneTextFat.size, (uint16_t)size );+ TracyQueueCommit( zoneTextFatThread );+ }++ tracy_force_inline void Name( const char* txt, size_t size )+ {+ assert( size < (std::numeric_limits<uint16_t>::max)() );+ if( !m_active ) return;+#ifdef TRACY_ON_DEMAND+ if( GetProfiler().ConnectionId() != m_connectionId ) return;+#endif+ auto ptr = (char*)tracy_malloc( size );+ memcpy( ptr, txt, size );+ TracyQueuePrepare( QueueType::ZoneName );+ MemWrite( &item->zoneTextFat.text, (uint64_t)ptr );+ MemWrite( &item->zoneTextFat.size, (uint16_t)size );+ TracyQueueCommit( zoneTextFatThread );+ }++ void NameFmt( const char* fmt, ... )+ {+ if( !m_active ) return;+#ifdef TRACY_ON_DEMAND+ if( GetProfiler().ConnectionId() != m_connectionId ) return;+#endif+ va_list args;+ va_start( args, fmt );+ auto size = vsnprintf( nullptr, 0, fmt, args );+ va_end( args );+ if( size < 0 ) return;+ assert( size < (std::numeric_limits<uint16_t>::max)() );++ char* ptr = (char*)tracy_malloc( size_t( size ) + 1 );+ va_start( args, fmt );+ vsnprintf( ptr, size_t( size ) + 1, fmt, args );+ va_end( args );++ TracyQueuePrepare( QueueType::ZoneName );+ MemWrite( &item->zoneTextFat.text, (uint64_t)ptr );+ MemWrite( &item->zoneTextFat.size, (uint16_t)size );+ TracyQueueCommit( zoneTextFatThread );+ }++ tracy_force_inline void Color( uint32_t color )+ {+ if( !m_active ) return;+#ifdef TRACY_ON_DEMAND+ if( GetProfiler().ConnectionId() != m_connectionId ) return;+#endif+ TracyQueuePrepare( QueueType::ZoneColor );+ MemWrite( &item->zoneColor.b, uint8_t( ( color ) & 0xFF ) );+ MemWrite( &item->zoneColor.g, uint8_t( ( color >> 8 ) & 0xFF ) );+ MemWrite( &item->zoneColor.r, uint8_t( ( color >> 16 ) & 0xFF ) );+ TracyQueueCommit( zoneColorThread );+ }++ tracy_force_inline void Value( uint64_t value )+ {+ if( !m_active ) return;+#ifdef TRACY_ON_DEMAND+ if( GetProfiler().ConnectionId() != m_connectionId ) return;+#endif+ TracyQueuePrepare( QueueType::ZoneValue );+ MemWrite( &item->zoneValue.value, value );+ TracyQueueCommit( zoneValueThread );+ }++ tracy_force_inline bool IsActive() const { return m_active; }++private:+ const bool m_active;++#ifdef TRACY_ON_DEMAND+ uint64_t m_connectionId = 0;+#endif+};++}++#endif
+ cbits/tracy/public/client/TracyStringHelpers.hpp view
@@ -0,0 +1,41 @@+#ifndef __TRACYSTRINGHELPERS_HPP__+#define __TRACYSTRINGHELPERS_HPP__++#include <assert.h>+#include <string.h>++#include "../common/TracyAlloc.hpp"+#include "../common/TracyForceInline.hpp"++namespace tracy+{++static tracy_force_inline char* CopyString( const char* src, size_t sz )+{+ auto dst = (char*)tracy_malloc( sz + 1 );+ memcpy( dst, src, sz );+ dst[sz] = '\0';+ return dst;+}++static tracy_force_inline char* CopyString( const char* src )+{+ return CopyString( src, strlen( src ) );+}++static tracy_force_inline char* CopyStringFast( const char* src, size_t sz )+{+ auto dst = (char*)tracy_malloc_fast( sz + 1 );+ memcpy( dst, src, sz );+ dst[sz] = '\0';+ return dst;+}++static tracy_force_inline char* CopyStringFast( const char* src )+{+ return CopyStringFast( src, strlen( src ) );+}++}++#endif
+ cbits/tracy/public/client/TracySysPower.cpp view
@@ -0,0 +1,164 @@+#include "TracySysPower.hpp"++#ifdef TRACY_HAS_SYSPOWER++#include <sys/types.h>+#include <dirent.h>+#include <chrono>+#include <inttypes.h>+#include <stdio.h>+#include <string.h>++#include "TracyDebug.hpp"+#include "TracyProfiler.hpp"+#include "../common/TracyAlloc.hpp"++namespace tracy+{++SysPower::SysPower()+ : m_domains( 4 )+ , m_lastTime( 0 )+{+ ScanDirectory( "/sys/devices/virtual/powercap/intel-rapl", -1 );+}++SysPower::~SysPower()+{+ for( auto& v : m_domains )+ {+ fclose( v.handle );+ // Do not release v.name, as it may be still needed+ }+}++void SysPower::Tick()+{+ auto t = std::chrono::high_resolution_clock::now().time_since_epoch().count();+ if( t - m_lastTime > 10000000 ) // 10 ms+ {+ m_lastTime = t;+ for( auto& v : m_domains )+ {+ char tmp[32];+ if( fread( tmp, 1, 32, v.handle ) > 0 )+ {+ rewind( v.handle );+ auto p = (uint64_t)atoll( tmp );+ uint64_t delta;+ if( p >= v.value )+ {+ delta = p - v.value;+ }+ else+ {+ delta = v.overflow - v.value + p;+ }+ v.value = p;++ TracyLfqPrepare( QueueType::SysPowerReport );+ MemWrite( &item->sysPower.time, Profiler::GetTime() );+ MemWrite( &item->sysPower.delta, delta );+ MemWrite( &item->sysPower.name, (uint64_t)v.name );+ TracyLfqCommit;+ }+ }+ }+}++void SysPower::ScanDirectory( const char* path, int parent )+{+ DIR* dir = opendir( path );+ if( !dir ) return;+ struct dirent* ent;+ uint64_t maxRange = 0;+ char* name = nullptr;+ FILE* handle = nullptr;+ while( ( ent = readdir( dir ) ) )+ {+ if( ent->d_type == DT_REG )+ {+ if( strcmp( ent->d_name, "max_energy_range_uj" ) == 0 )+ {+ char tmp[PATH_MAX];+ snprintf( tmp, PATH_MAX, "%s/max_energy_range_uj", path );+ FILE* f = fopen( tmp, "r" );+ if( f )+ {+ (void)fscanf( f, "%" PRIu64, &maxRange );+ fclose( f );+ }+ }+ else if( strcmp( ent->d_name, "name" ) == 0 )+ {+ char tmp[PATH_MAX];+ snprintf( tmp, PATH_MAX, "%s/name", path );+ FILE* f = fopen( tmp, "r" );+ if( f )+ {+ char ntmp[128];+ if( fgets( ntmp, 128, f ) )+ {+ // Last character is newline, skip it+ const auto sz = strlen( ntmp ) - 1;+ if( parent < 0 )+ {+ name = (char*)tracy_malloc( sz + 1 );+ memcpy( name, ntmp, sz );+ name[sz] = '\0';+ }+ else+ {+ const auto p = m_domains[parent];+ const auto psz = strlen( p.name );+ name = (char*)tracy_malloc( psz + sz + 2 );+ memcpy( name, p.name, psz );+ name[psz] = ':';+ memcpy( name+psz+1, ntmp, sz );+ name[psz+sz+1] = '\0';+ }+ }+ fclose( f );+ }+ }+ else if( strcmp( ent->d_name, "energy_uj" ) == 0 )+ {+ char tmp[PATH_MAX];+ snprintf( tmp, PATH_MAX, "%s/energy_uj", path );+ handle = fopen( tmp, "r" );+ }+ }+ if( name && handle && maxRange > 0 ) break;+ }+ if( name && handle && maxRange > 0 )+ {+ parent = (int)m_domains.size();+ Domain* domain = m_domains.push_next();+ domain->value = 0;+ domain->overflow = maxRange;+ domain->handle = handle;+ domain->name = name;+ TracyDebug( "Power domain id %i, %s found at %s\n", parent, name, path );+ }+ else+ {+ if( name ) tracy_free( name );+ if( handle ) fclose( handle );+ }++ rewinddir( dir );+ while( ( ent = readdir( dir ) ) )+ {+ if( ent->d_type == DT_DIR && strncmp( ent->d_name, "intel-rapl:", 11 ) == 0 )+ {+ char tmp[PATH_MAX];+ snprintf( tmp, PATH_MAX, "%s/%s", path, ent->d_name );+ ScanDirectory( tmp, parent );+ }+ }+ closedir( dir );+}++}++#endif
+ cbits/tracy/public/client/TracySysPower.hpp view
@@ -0,0 +1,44 @@+#ifndef __TRACYSYSPOWER_HPP__+#define __TRACYSYSPOWER_HPP__++#if defined __linux__+# define TRACY_HAS_SYSPOWER+#endif++#ifdef TRACY_HAS_SYSPOWER++#include <stdint.h>+#include <stdio.h>++#include "TracyFastVector.hpp"++namespace tracy+{++class SysPower+{+ struct Domain+ {+ uint64_t value;+ uint64_t overflow;+ FILE* handle;+ const char* name;+ };++public:+ SysPower();+ ~SysPower();++ void Tick();++private:+ void ScanDirectory( const char* path, int parent );++ FastVector<Domain> m_domains;+ uint64_t m_lastTime;+};++}+#endif++#endif
+ cbits/tracy/public/client/TracySysTime.cpp view
@@ -0,0 +1,108 @@+#include "TracySysTime.hpp"++#ifdef TRACY_HAS_SYSTIME++# if defined _WIN32+# include <windows.h>+# elif defined __linux__+# include <stdio.h>+# include <inttypes.h>+# elif defined __APPLE__+# include <mach/mach_host.h>+# include <mach/host_info.h>+# elif defined BSD+# include <sys/types.h>+# include <sys/sysctl.h>+# endif++namespace tracy+{++# if defined _WIN32++static inline uint64_t ConvertTime( const FILETIME& t )+{+ return ( uint64_t( t.dwHighDateTime ) << 32 ) | uint64_t( t.dwLowDateTime );+}++void SysTime::ReadTimes()+{+ FILETIME idleTime;+ FILETIME kernelTime;+ FILETIME userTime;++ GetSystemTimes( &idleTime, &kernelTime, &userTime );++ idle = ConvertTime( idleTime );+ const auto kernel = ConvertTime( kernelTime );+ const auto user = ConvertTime( userTime );+ used = kernel + user;+}++# elif defined __linux__++void SysTime::ReadTimes()+{+ uint64_t user, nice, system;+ FILE* f = fopen( "/proc/stat", "r" );+ if( f )+ {+ int read = fscanf( f, "cpu %" PRIu64 " %" PRIu64 " %" PRIu64" %" PRIu64, &user, &nice, &system, &idle );+ fclose( f );+ if (read == 4)+ {+ used = user + nice + system;+ }+ }+}++# elif defined __APPLE__++void SysTime::ReadTimes()+{+ host_cpu_load_info_data_t info;+ mach_msg_type_number_t cnt = HOST_CPU_LOAD_INFO_COUNT;+ host_statistics( mach_host_self(), HOST_CPU_LOAD_INFO, reinterpret_cast<host_info_t>( &info ), &cnt );+ used = info.cpu_ticks[CPU_STATE_USER] + info.cpu_ticks[CPU_STATE_NICE] + info.cpu_ticks[CPU_STATE_SYSTEM];+ idle = info.cpu_ticks[CPU_STATE_IDLE];+}++# elif defined BSD++void SysTime::ReadTimes()+{+ u_long data[5];+ size_t sz = sizeof( data );+ sysctlbyname( "kern.cp_time", &data, &sz, nullptr, 0 );+ used = data[0] + data[1] + data[2] + data[3];+ idle = data[4];+}++#endif++SysTime::SysTime()+{+ ReadTimes();+}++float SysTime::Get()+{+ const auto oldUsed = used;+ const auto oldIdle = idle;++ ReadTimes();++ const auto diffIdle = idle - oldIdle;+ const auto diffUsed = used - oldUsed;++#if defined _WIN32+ return diffUsed == 0 ? -1 : ( diffUsed - diffIdle ) * 100.f / diffUsed;+#elif defined __linux__ || defined __APPLE__ || defined BSD+ const auto total = diffUsed + diffIdle;+ return total == 0 ? -1 : diffUsed * 100.f / total;+#endif+}++}++#endif
+ cbits/tracy/public/client/TracySysTime.hpp view
@@ -0,0 +1,36 @@+#ifndef __TRACYSYSTIME_HPP__+#define __TRACYSYSTIME_HPP__++#if defined _WIN32 || defined __linux__ || defined __APPLE__+# define TRACY_HAS_SYSTIME+#else+# include <sys/param.h>+#endif++#ifdef BSD+# define TRACY_HAS_SYSTIME+#endif++#ifdef TRACY_HAS_SYSTIME++#include <stdint.h>++namespace tracy+{++class SysTime+{+public:+ SysTime();+ float Get();++ void ReadTimes();++private:+ uint64_t idle, used;+};++}+#endif++#endif
+ cbits/tracy/public/client/TracySysTrace.cpp view
@@ -0,0 +1,1646 @@+#include "TracyDebug.hpp"+#include "TracyStringHelpers.hpp"+#include "TracySysTrace.hpp"+#include "../common/TracySystem.hpp"++#ifdef TRACY_HAS_SYSTEM_TRACING++#ifndef TRACY_SAMPLING_HZ+# if defined _WIN32+# define TRACY_SAMPLING_HZ 8000+# elif defined __linux__+# define TRACY_SAMPLING_HZ 10000+# endif+#endif++namespace tracy+{++static int GetSamplingFrequency()+{+ int samplingHz = TRACY_SAMPLING_HZ;++ auto env = GetEnvVar( "TRACY_SAMPLING_HZ" );+ if( env )+ {+ int val = atoi( env );+ if( val > 0 ) samplingHz = val;+ }++#if defined _WIN32+ return samplingHz > 8000 ? 8000 : ( samplingHz < 1 ? 1 : samplingHz );+#else+ return samplingHz > 1000000 ? 1000000 : ( samplingHz < 1 ? 1 : samplingHz );+#endif+}++static int GetSamplingPeriod()+{+ return 1000000000 / GetSamplingFrequency();+}++}++# if defined _WIN32++# ifndef NOMINMAX+# define NOMINMAX+# endif++# define INITGUID+# include <assert.h>+# include <string.h>+# include <windows.h>+# include <dbghelp.h>+# include <evntrace.h>+# include <evntcons.h>+# include <psapi.h>+# include <winternl.h>++# include "../common/TracyAlloc.hpp"+# include "../common/TracySystem.hpp"+# include "TracyProfiler.hpp"+# include "TracyThread.hpp"++namespace tracy+{++static const GUID PerfInfoGuid = { 0xce1dbfb4, 0x137e, 0x4da6, { 0x87, 0xb0, 0x3f, 0x59, 0xaa, 0x10, 0x2c, 0xbc } };+static const GUID DxgKrnlGuid = { 0x802ec45a, 0x1e99, 0x4b83, { 0x99, 0x20, 0x87, 0xc9, 0x82, 0x77, 0xba, 0x9d } };+static const GUID ThreadV2Guid = { 0x3d6fa8d1, 0xfe05, 0x11d0, { 0x9d, 0xda, 0x00, 0xc0, 0x4f, 0xd7, 0xba, 0x7c } };+++static TRACEHANDLE s_traceHandle;+static TRACEHANDLE s_traceHandle2;+static EVENT_TRACE_PROPERTIES* s_prop;+static DWORD s_pid;++static EVENT_TRACE_PROPERTIES* s_propVsync;+static TRACEHANDLE s_traceHandleVsync;+static TRACEHANDLE s_traceHandleVsync2;+Thread* s_threadVsync = nullptr;++struct CSwitch+{+ uint32_t newThreadId;+ uint32_t oldThreadId;+ int8_t newThreadPriority;+ int8_t oldThreadPriority;+ uint8_t previousCState;+ int8_t spareByte;+ int8_t oldThreadWaitReason;+ int8_t oldThreadWaitMode;+ int8_t oldThreadState;+ int8_t oldThreadWaitIdealProcessor;+ uint32_t newThreadWaitTime;+ uint32_t reserved;+};++struct ReadyThread+{+ uint32_t threadId;+ int8_t adjustReason;+ int8_t adjustIncrement;+ int8_t flag;+ int8_t reserverd;+};++struct ThreadTrace+{+ uint32_t processId;+ uint32_t threadId;+ uint32_t stackBase;+ uint32_t stackLimit;+ uint32_t userStackBase;+ uint32_t userStackLimit;+ uint32_t startAddr;+ uint32_t win32StartAddr;+ uint32_t tebBase;+ uint32_t subProcessTag;+};++struct StackWalkEvent+{+ uint64_t eventTimeStamp;+ uint32_t stackProcess;+ uint32_t stackThread;+ uint64_t stack[192];+};++struct VSyncInfo+{+ void* dxgAdapter;+ uint32_t vidPnTargetId;+ uint64_t scannedPhysicalAddress;+ uint32_t vidPnSourceId;+ uint32_t frameNumber;+ int64_t frameQpcTime;+ void* hFlipDevice;+ uint32_t flipType;+ uint64_t flipFenceId;+};++extern "C" typedef NTSTATUS (WINAPI *t_NtQueryInformationThread)( HANDLE, THREADINFOCLASS, PVOID, ULONG, PULONG );+extern "C" typedef BOOL (WINAPI *t_EnumProcessModules)( HANDLE, HMODULE*, DWORD, LPDWORD );+extern "C" typedef BOOL (WINAPI *t_GetModuleInformation)( HANDLE, HMODULE, LPMODULEINFO, DWORD );+extern "C" typedef DWORD (WINAPI *t_GetModuleBaseNameA)( HANDLE, HMODULE, LPSTR, DWORD );+extern "C" typedef HRESULT (WINAPI *t_GetThreadDescription)( HANDLE, PWSTR* );++t_NtQueryInformationThread NtQueryInformationThread = (t_NtQueryInformationThread)GetProcAddress( GetModuleHandleA( "ntdll.dll" ), "NtQueryInformationThread" );+t_EnumProcessModules _EnumProcessModules = (t_EnumProcessModules)GetProcAddress( GetModuleHandleA( "kernel32.dll" ), "K32EnumProcessModules" );+t_GetModuleInformation _GetModuleInformation = (t_GetModuleInformation)GetProcAddress( GetModuleHandleA( "kernel32.dll" ), "K32GetModuleInformation" );+t_GetModuleBaseNameA _GetModuleBaseNameA = (t_GetModuleBaseNameA)GetProcAddress( GetModuleHandleA( "kernel32.dll" ), "K32GetModuleBaseNameA" );++static t_GetThreadDescription _GetThreadDescription = 0;+++void WINAPI EventRecordCallback( PEVENT_RECORD record )+{+#ifdef TRACY_ON_DEMAND+ if( !GetProfiler().IsConnected() ) return;+#endif++ const auto& hdr = record->EventHeader;+ switch( hdr.ProviderId.Data1 )+ {+ case 0x3d6fa8d1: // Thread Guid+ if( hdr.EventDescriptor.Opcode == 36 )+ {+ const auto cswitch = (const CSwitch*)record->UserData;++ TracyLfqPrepare( QueueType::ContextSwitch );+ MemWrite( &item->contextSwitch.time, hdr.TimeStamp.QuadPart );+ MemWrite( &item->contextSwitch.oldThread, cswitch->oldThreadId );+ MemWrite( &item->contextSwitch.newThread, cswitch->newThreadId );+ MemWrite( &item->contextSwitch.cpu, record->BufferContext.ProcessorNumber );+ MemWrite( &item->contextSwitch.oldThreadWaitReason, cswitch->oldThreadWaitReason );+ MemWrite( &item->contextSwitch.oldThreadState, cswitch->oldThreadState );+ MemWrite( &item->contextSwitch.newThreadPriority, cswitch->newThreadPriority );+ MemWrite( &item->contextSwitch.oldThreadPriority, cswitch->oldThreadPriority );+ MemWrite( &item->contextSwitch.previousCState, cswitch->previousCState );+ TracyLfqCommit;+ }+ else if( hdr.EventDescriptor.Opcode == 50 )+ {+ const auto rt = (const ReadyThread*)record->UserData;++ TracyLfqPrepare( QueueType::ThreadWakeup );+ MemWrite( &item->threadWakeup.time, hdr.TimeStamp.QuadPart );+ MemWrite( &item->threadWakeup.cpu, record->BufferContext.ProcessorNumber );+ MemWrite( &item->threadWakeup.thread, rt->threadId );+ MemWrite( &item->threadWakeup.adjustReason, rt->adjustReason );+ MemWrite( &item->threadWakeup.adjustIncrement, rt->adjustIncrement );+ TracyLfqCommit;+ }+ else if( hdr.EventDescriptor.Opcode == 1 || hdr.EventDescriptor.Opcode == 3 )+ {+ const auto tt = (const ThreadTrace*)record->UserData;++ uint64_t tid = tt->threadId;+ if( tid == 0 ) return;+ uint64_t pid = tt->processId;+ TracyLfqPrepare( QueueType::TidToPid );+ MemWrite( &item->tidToPid.tid, tid );+ MemWrite( &item->tidToPid.pid, pid );+ TracyLfqCommit;+ }+ break;+ case 0xdef2fe46: // StackWalk Guid+ if( hdr.EventDescriptor.Opcode == 32 )+ {+ const auto sw = (const StackWalkEvent*)record->UserData;+ if( sw->stackProcess == s_pid )+ {+ const uint64_t sz = ( record->UserDataLength - 16 ) / 8;+ if( sz > 0 )+ {+ auto trace = (uint64_t*)tracy_malloc( ( 1 + sz ) * sizeof( uint64_t ) );+ memcpy( trace, &sz, sizeof( uint64_t ) );+ memcpy( trace+1, sw->stack, sizeof( uint64_t ) * sz );+ TracyLfqPrepare( QueueType::CallstackSample );+ MemWrite( &item->callstackSampleFat.time, sw->eventTimeStamp );+ MemWrite( &item->callstackSampleFat.thread, sw->stackThread );+ MemWrite( &item->callstackSampleFat.ptr, (uint64_t)trace );+ TracyLfqCommit;+ }+ }+ }+ break;+ default:+ break;+ }+}++void WINAPI EventRecordCallbackVsync( PEVENT_RECORD record )+{+#ifdef TRACY_ON_DEMAND+ if( !GetProfiler().IsConnected() ) return;+#endif++ const auto& hdr = record->EventHeader;+ assert( hdr.ProviderId.Data1 == 0x802EC45A );+ assert( hdr.EventDescriptor.Id == 0x0011 );++ const auto vs = (const VSyncInfo*)record->UserData;++ TracyLfqPrepare( QueueType::FrameVsync );+ MemWrite( &item->frameVsync.time, hdr.TimeStamp.QuadPart );+ MemWrite( &item->frameVsync.id, vs->vidPnTargetId );+ TracyLfqCommit;+}++static void SetupVsync()+{+#if _WIN32_WINNT >= _WIN32_WINNT_WINBLUE && !defined(__MINGW32__)+ const auto psz = sizeof( EVENT_TRACE_PROPERTIES ) + MAX_PATH;+ s_propVsync = (EVENT_TRACE_PROPERTIES*)tracy_malloc( psz );+ memset( s_propVsync, 0, sizeof( EVENT_TRACE_PROPERTIES ) );+ s_propVsync->LogFileMode = EVENT_TRACE_REAL_TIME_MODE;+ s_propVsync->Wnode.BufferSize = psz;+#ifdef TRACY_TIMER_QPC+ s_propVsync->Wnode.ClientContext = 1;+#else+ s_propVsync->Wnode.ClientContext = 3;+#endif+ s_propVsync->LoggerNameOffset = sizeof( EVENT_TRACE_PROPERTIES );+ strcpy( ((char*)s_propVsync) + sizeof( EVENT_TRACE_PROPERTIES ), "TracyVsync" );++ auto backup = tracy_malloc( psz );+ memcpy( backup, s_propVsync, psz );++ const auto controlStatus = ControlTraceA( 0, "TracyVsync", s_propVsync, EVENT_TRACE_CONTROL_STOP );+ if( controlStatus != ERROR_SUCCESS && controlStatus != ERROR_WMI_INSTANCE_NOT_FOUND )+ {+ tracy_free( backup );+ tracy_free( s_propVsync );+ return;+ }++ memcpy( s_propVsync, backup, psz );+ tracy_free( backup );++ const auto startStatus = StartTraceA( &s_traceHandleVsync, "TracyVsync", s_propVsync );+ if( startStatus != ERROR_SUCCESS )+ {+ tracy_free( s_propVsync );+ return;+ }++ EVENT_FILTER_EVENT_ID fe = {};+ fe.FilterIn = TRUE;+ fe.Count = 1;+ fe.Events[0] = 0x0011; // VSyncDPC_Info++ EVENT_FILTER_DESCRIPTOR desc = {};+ desc.Ptr = (ULONGLONG)&fe;+ desc.Size = sizeof( fe );+ desc.Type = EVENT_FILTER_TYPE_EVENT_ID;++ ENABLE_TRACE_PARAMETERS params = {};+ params.Version = ENABLE_TRACE_PARAMETERS_VERSION_2;+ params.EnableProperty = EVENT_ENABLE_PROPERTY_IGNORE_KEYWORD_0;+ params.SourceId = s_propVsync->Wnode.Guid;+ params.EnableFilterDesc = &desc;+ params.FilterDescCount = 1;++ uint64_t mask = 0x4000000000000001; // Microsoft_Windows_DxgKrnl_Performance | Base+ if( EnableTraceEx2( s_traceHandleVsync, &DxgKrnlGuid, EVENT_CONTROL_CODE_ENABLE_PROVIDER, TRACE_LEVEL_INFORMATION, mask, mask, 0, ¶ms ) != ERROR_SUCCESS )+ {+ tracy_free( s_propVsync );+ return;+ }++ char loggerName[MAX_PATH];+ strcpy( loggerName, "TracyVsync" );++ EVENT_TRACE_LOGFILEA log = {};+ log.LoggerName = loggerName;+ log.ProcessTraceMode = PROCESS_TRACE_MODE_REAL_TIME | PROCESS_TRACE_MODE_EVENT_RECORD | PROCESS_TRACE_MODE_RAW_TIMESTAMP;+ log.EventRecordCallback = EventRecordCallbackVsync;++ s_traceHandleVsync2 = OpenTraceA( &log );+ if( s_traceHandleVsync2 == (TRACEHANDLE)INVALID_HANDLE_VALUE )+ {+ CloseTrace( s_traceHandleVsync );+ tracy_free( s_propVsync );+ return;+ }++ s_threadVsync = (Thread*)tracy_malloc( sizeof( Thread ) );+ new(s_threadVsync) Thread( [] (void*) {+ ThreadExitHandler threadExitHandler;+ SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL );+ SetThreadName( "Tracy Vsync" );+ ProcessTrace( &s_traceHandleVsync2, 1, nullptr, nullptr );+ }, nullptr );+#endif+}++static int GetSamplingInterval()+{+ return GetSamplingPeriod() / 100;+}++bool SysTraceStart( int64_t& samplingPeriod )+{+ if( !_GetThreadDescription ) _GetThreadDescription = (t_GetThreadDescription)GetProcAddress( GetModuleHandleA( "kernel32.dll" ), "GetThreadDescription" );++ s_pid = GetCurrentProcessId();++#if defined _WIN64+ constexpr bool isOs64Bit = true;+#else+ BOOL _iswow64;+ IsWow64Process( GetCurrentProcess(), &_iswow64 );+ const bool isOs64Bit = _iswow64;+#endif++ TOKEN_PRIVILEGES priv = {};+ priv.PrivilegeCount = 1;+ priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;+ if( LookupPrivilegeValue( nullptr, SE_SYSTEM_PROFILE_NAME, &priv.Privileges[0].Luid ) == 0 ) return false;++ HANDLE pt;+ if( OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &pt ) == 0 ) return false;+ const auto adjust = AdjustTokenPrivileges( pt, FALSE, &priv, 0, nullptr, nullptr );+ CloseHandle( pt );+ if( adjust == 0 ) return false;+ const auto status = GetLastError();+ if( status != ERROR_SUCCESS ) return false;++ if( isOs64Bit )+ {+ TRACE_PROFILE_INTERVAL interval = {};+ interval.Interval = GetSamplingInterval();+ const auto intervalStatus = TraceSetInformation( 0, TraceSampledProfileIntervalInfo, &interval, sizeof( interval ) );+ if( intervalStatus != ERROR_SUCCESS ) return false;+ samplingPeriod = GetSamplingPeriod();+ }++ const auto psz = sizeof( EVENT_TRACE_PROPERTIES ) + sizeof( KERNEL_LOGGER_NAME );+ s_prop = (EVENT_TRACE_PROPERTIES*)tracy_malloc( psz );+ memset( s_prop, 0, sizeof( EVENT_TRACE_PROPERTIES ) );+ ULONG flags = 0;+#ifndef TRACY_NO_CONTEXT_SWITCH+ flags = EVENT_TRACE_FLAG_CSWITCH | EVENT_TRACE_FLAG_DISPATCHER | EVENT_TRACE_FLAG_THREAD;+#endif+#ifndef TRACY_NO_SAMPLING+ if( isOs64Bit ) flags |= EVENT_TRACE_FLAG_PROFILE;+#endif+ s_prop->EnableFlags = flags;+ s_prop->LogFileMode = EVENT_TRACE_REAL_TIME_MODE;+ s_prop->Wnode.BufferSize = psz;+ s_prop->Wnode.Flags = WNODE_FLAG_TRACED_GUID;+#ifdef TRACY_TIMER_QPC+ s_prop->Wnode.ClientContext = 1;+#else+ s_prop->Wnode.ClientContext = 3;+#endif+ s_prop->Wnode.Guid = SystemTraceControlGuid;+ s_prop->BufferSize = 1024;+ s_prop->MinimumBuffers = std::thread::hardware_concurrency() * 4;+ s_prop->MaximumBuffers = std::thread::hardware_concurrency() * 6;+ s_prop->LoggerNameOffset = sizeof( EVENT_TRACE_PROPERTIES );+ memcpy( ((char*)s_prop) + sizeof( EVENT_TRACE_PROPERTIES ), KERNEL_LOGGER_NAME, sizeof( KERNEL_LOGGER_NAME ) );++ auto backup = tracy_malloc( psz );+ memcpy( backup, s_prop, psz );++ const auto controlStatus = ControlTrace( 0, KERNEL_LOGGER_NAME, s_prop, EVENT_TRACE_CONTROL_STOP );+ if( controlStatus != ERROR_SUCCESS && controlStatus != ERROR_WMI_INSTANCE_NOT_FOUND )+ {+ tracy_free( backup );+ tracy_free( s_prop );+ return false;+ }++ memcpy( s_prop, backup, psz );+ tracy_free( backup );++ const auto startStatus = StartTrace( &s_traceHandle, KERNEL_LOGGER_NAME, s_prop );+ if( startStatus != ERROR_SUCCESS )+ {+ tracy_free( s_prop );+ return false;+ }++#ifndef TRACY_NO_SAMPLING+ if( isOs64Bit )+ {+ CLASSIC_EVENT_ID stackId[2] = {};+ stackId[0].EventGuid = PerfInfoGuid;+ stackId[0].Type = 46;+ stackId[1].EventGuid = ThreadV2Guid;+ stackId[1].Type = 36;+ const auto stackStatus = TraceSetInformation( s_traceHandle, TraceStackTracingInfo, &stackId, sizeof( stackId ) );+ if( stackStatus != ERROR_SUCCESS )+ {+ tracy_free( s_prop );+ return false;+ }+ }+#endif++#ifdef UNICODE+ WCHAR KernelLoggerName[sizeof( KERNEL_LOGGER_NAME )];+#else+ char KernelLoggerName[sizeof( KERNEL_LOGGER_NAME )];+#endif+ memcpy( KernelLoggerName, KERNEL_LOGGER_NAME, sizeof( KERNEL_LOGGER_NAME ) );+ EVENT_TRACE_LOGFILE log = {};+ log.LoggerName = KernelLoggerName;+ log.ProcessTraceMode = PROCESS_TRACE_MODE_REAL_TIME | PROCESS_TRACE_MODE_EVENT_RECORD | PROCESS_TRACE_MODE_RAW_TIMESTAMP;+ log.EventRecordCallback = EventRecordCallback;++ s_traceHandle2 = OpenTrace( &log );+ if( s_traceHandle2 == (TRACEHANDLE)INVALID_HANDLE_VALUE )+ {+ CloseTrace( s_traceHandle );+ tracy_free( s_prop );+ return false;+ }++#ifndef TRACY_NO_VSYNC_CAPTURE+ SetupVsync();+#endif++ return true;+}++void SysTraceStop()+{+ if( s_threadVsync )+ {+ CloseTrace( s_traceHandleVsync2 );+ CloseTrace( s_traceHandleVsync );+ s_threadVsync->~Thread();+ tracy_free( s_threadVsync );+ }++ CloseTrace( s_traceHandle2 );+ CloseTrace( s_traceHandle );+}++void SysTraceWorker( void* ptr )+{+ ThreadExitHandler threadExitHandler;+ SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL );+ SetThreadName( "Tracy SysTrace" );+ ProcessTrace( &s_traceHandle2, 1, 0, 0 );+ ControlTrace( 0, KERNEL_LOGGER_NAME, s_prop, EVENT_TRACE_CONTROL_STOP );+ tracy_free( s_prop );+}++void SysTraceGetExternalName( uint64_t thread, const char*& threadName, const char*& name )+{+ bool threadSent = false;+ auto hnd = OpenThread( THREAD_QUERY_INFORMATION, FALSE, DWORD( thread ) );+ if( hnd == 0 )+ {+ hnd = OpenThread( THREAD_QUERY_LIMITED_INFORMATION, FALSE, DWORD( thread ) );+ }+ if( hnd != 0 )+ {+ if( _GetThreadDescription )+ {+ PWSTR tmp;+ if ( SUCCEEDED( _GetThreadDescription( hnd, &tmp ) ) )+ {+ char buf[256];+ auto ret = wcstombs( buf, tmp, 256 );+ LocalFree(tmp);+ if( ret != 0 )+ {+ threadName = CopyString( buf, ret );+ threadSent = true;+ }+ }+ }+ const auto pid = GetProcessIdOfThread( hnd );+ if( !threadSent && NtQueryInformationThread && _EnumProcessModules && _GetModuleInformation && _GetModuleBaseNameA )+ {+ void* ptr;+ ULONG retlen;+ auto status = NtQueryInformationThread( hnd, (THREADINFOCLASS)9 /*ThreadQuerySetWin32StartAddress*/, &ptr, sizeof( &ptr ), &retlen );+ if( status == 0 )+ {+ const auto phnd = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid );+ if( phnd != INVALID_HANDLE_VALUE )+ {+ HMODULE modules[1024];+ DWORD needed;+ if( _EnumProcessModules( phnd, modules, 1024 * sizeof( HMODULE ), &needed ) != 0 )+ {+ const auto sz = std::min( DWORD( needed / sizeof( HMODULE ) ), DWORD( 1024 ) );+ for( DWORD i=0; i<sz; i++ )+ {+ MODULEINFO info;+ if( _GetModuleInformation( phnd, modules[i], &info, sizeof( info ) ) != 0 )+ {+ if( (uint64_t)ptr >= (uint64_t)info.lpBaseOfDll && (uint64_t)ptr <= (uint64_t)info.lpBaseOfDll + (uint64_t)info.SizeOfImage )+ {+ char buf2[1024];+ const auto modlen = _GetModuleBaseNameA( phnd, modules[i], buf2, 1024 );+ if( modlen != 0 )+ {+ threadName = CopyString( buf2, modlen );+ threadSent = true;+ }+ }+ }+ }+ }+ CloseHandle( phnd );+ }+ }+ }+ CloseHandle( hnd );+ if( !threadSent )+ {+ threadName = CopyString( "???", 3 );+ threadSent = true;+ }+ if( pid != 0 )+ {+ {+ uint64_t _pid = pid;+ TracyLfqPrepare( QueueType::TidToPid );+ MemWrite( &item->tidToPid.tid, thread );+ MemWrite( &item->tidToPid.pid, _pid );+ TracyLfqCommit;+ }+ if( pid == 4 )+ {+ name = CopyStringFast( "System", 6 );+ return;+ }+ else+ {+ const auto phnd = OpenProcess( PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid );+ if( phnd != INVALID_HANDLE_VALUE )+ {+ char buf2[1024];+ const auto sz = GetProcessImageFileNameA( phnd, buf2, 1024 );+ CloseHandle( phnd );+ if( sz != 0 )+ {+ auto ptr = buf2 + sz - 1;+ while( ptr > buf2 && *ptr != '\\' ) ptr--;+ if( *ptr == '\\' ) ptr++;+ name = CopyStringFast( ptr );+ return;+ }+ }+ }+ }+ }++ if( !threadSent )+ {+ threadName = CopyString( "???", 3 );+ }+ name = CopyStringFast( "???", 3 );+}++}++# elif defined __linux__++# include <sys/types.h>+# include <sys/stat.h>+# include <sys/wait.h>+# include <fcntl.h>+# include <inttypes.h>+# include <limits>+# include <poll.h>+# include <stdio.h>+# include <stdlib.h>+# include <string.h>+# include <unistd.h>+# include <atomic>+# include <thread>+# include <linux/perf_event.h>+# include <linux/version.h>+# include <sys/mman.h>+# include <sys/ioctl.h>+# include <sys/syscall.h>++# if defined __i386 || defined __x86_64__+# include "TracyCpuid.hpp"+# endif++# include "TracyProfiler.hpp"+# include "TracyRingBuffer.hpp"+# include "TracyThread.hpp"++namespace tracy+{++static std::atomic<bool> traceActive { false };+static int s_numCpus = 0;+static int s_numBuffers = 0;+static int s_ctxBufferIdx = 0;++static RingBuffer* s_ring = nullptr;++static const int ThreadHashSize = 4 * 1024;+static uint32_t s_threadHash[ThreadHashSize] = {};++static bool CurrentProcOwnsThread( uint32_t tid )+{+ const auto hash = tid & ( ThreadHashSize-1 );+ const auto hv = s_threadHash[hash];+ if( hv == tid ) return true;+ if( hv == -tid ) return false;++ char path[256];+ sprintf( path, "/proc/self/task/%d", tid );+ struct stat st;+ if( stat( path, &st ) == 0 )+ {+ s_threadHash[hash] = tid;+ return true;+ }+ else+ {+ s_threadHash[hash] = -tid;+ return false;+ }+}++static int perf_event_open( struct perf_event_attr* hw_event, pid_t pid, int cpu, int group_fd, unsigned long flags )+{+ return syscall( __NR_perf_event_open, hw_event, pid, cpu, group_fd, flags );+}++enum TraceEventId+{+ EventCallstack,+ EventCpuCycles,+ EventInstructionsRetired,+ EventCacheReference,+ EventCacheMiss,+ EventBranchRetired,+ EventBranchMiss,+ EventVsync,+ EventContextSwitch,+ EventWaking,+};++static void ProbePreciseIp( perf_event_attr& pe, unsigned long long config0, unsigned long long config1, pid_t pid )+{+ pe.config = config1;+ pe.precise_ip = 3;+ while( pe.precise_ip != 0 )+ {+ const int fd = perf_event_open( &pe, pid, 0, -1, PERF_FLAG_FD_CLOEXEC );+ if( fd != -1 )+ {+ close( fd );+ break;+ }+ pe.precise_ip--;+ }+ pe.config = config0;+ while( pe.precise_ip != 0 )+ {+ const int fd = perf_event_open( &pe, pid, 0, -1, PERF_FLAG_FD_CLOEXEC );+ if( fd != -1 )+ {+ close( fd );+ break;+ }+ pe.precise_ip--;+ }+ TracyDebug( " Probed precise_ip: %i\n", pe.precise_ip );+}++static void ProbePreciseIp( perf_event_attr& pe, pid_t pid )+{+ pe.precise_ip = 3;+ while( pe.precise_ip != 0 )+ {+ const int fd = perf_event_open( &pe, pid, 0, -1, PERF_FLAG_FD_CLOEXEC );+ if( fd != -1 )+ {+ close( fd );+ break;+ }+ pe.precise_ip--;+ }+ TracyDebug( " Probed precise_ip: %i\n", pe.precise_ip );+}++static bool IsGenuineIntel()+{+#if defined __i386 || defined __x86_64__+ uint32_t regs[4] = {};+ __get_cpuid( 0, regs, regs+1, regs+2, regs+3 );+ char manufacturer[12];+ memcpy( manufacturer, regs+1, 4 );+ memcpy( manufacturer+4, regs+3, 4 );+ memcpy( manufacturer+8, regs+2, 4 );+ return memcmp( manufacturer, "GenuineIntel", 12 ) == 0;+#else+ return false;+#endif+}++static const char* ReadFile( const char* path )+{+ int fd = open( path, O_RDONLY );+ if( fd < 0 ) return nullptr;++ static char tmp[64];+ const auto cnt = read( fd, tmp, 63 );+ close( fd );+ if( cnt < 0 ) return nullptr;+ tmp[cnt] = '\0';+ return tmp;+}++bool SysTraceStart( int64_t& samplingPeriod )+{+#ifndef CLOCK_MONOTONIC_RAW+ return false;+#endif++ const auto paranoidLevelStr = ReadFile( "/proc/sys/kernel/perf_event_paranoid" );+ if( !paranoidLevelStr ) return false;+#ifdef TRACY_VERBOSE+ int paranoidLevel = 2;+ paranoidLevel = atoi( paranoidLevelStr );+ TracyDebug( "perf_event_paranoid: %i\n", paranoidLevel );+#endif++ int switchId = -1, wakingId = -1, vsyncId = -1;+ const auto switchIdStr = ReadFile( "/sys/kernel/debug/tracing/events/sched/sched_switch/id" );+ if( switchIdStr ) switchId = atoi( switchIdStr );+ const auto wakingIdStr = ReadFile( "/sys/kernel/debug/tracing/events/sched/sched_waking/id" );+ if( wakingIdStr ) wakingId = atoi( wakingIdStr );+ const auto vsyncIdStr = ReadFile( "/sys/kernel/debug/tracing/events/drm/drm_vblank_event/id" );+ if( vsyncIdStr ) vsyncId = atoi( vsyncIdStr );++ TracyDebug( "sched_switch id: %i\n", switchId );+ TracyDebug( "sched_waking id: %i\n", wakingId );+ TracyDebug( "drm_vblank_event id: %i\n", vsyncId );++#ifdef TRACY_NO_SAMPLING+ const bool noSoftwareSampling = true;+#else+ const char* noSoftwareSamplingEnv = GetEnvVar( "TRACY_NO_SAMPLING" );+ const bool noSoftwareSampling = noSoftwareSamplingEnv && noSoftwareSamplingEnv[0] == '1';+#endif++#ifdef TRACY_NO_SAMPLE_RETIREMENT+ const bool noRetirement = true;+#else+ const char* noRetirementEnv = GetEnvVar( "TRACY_NO_SAMPLE_RETIREMENT" );+ const bool noRetirement = noRetirementEnv && noRetirementEnv[0] == '1';+#endif++#ifdef TRACY_NO_SAMPLE_CACHE+ const bool noCache = true;+#else+ const char* noCacheEnv = GetEnvVar( "TRACY_NO_SAMPLE_CACHE" );+ const bool noCache = noCacheEnv && noCacheEnv[0] == '1';+#endif++#ifdef TRACY_NO_SAMPLE_BRANCH+ const bool noBranch = true;+#else+ const char* noBranchEnv = GetEnvVar( "TRACY_NO_SAMPLE_BRANCH" );+ const bool noBranch = noBranchEnv && noBranchEnv[0] == '1';+#endif++#ifdef TRACY_NO_CONTEXT_SWITCH+ const bool noCtxSwitch = true;+#else+ const char* noCtxSwitchEnv = GetEnvVar( "TRACY_NO_CONTEXT_SWITCH" );+ const bool noCtxSwitch = noCtxSwitchEnv && noCtxSwitchEnv[0] == '1';+#endif++#ifdef TRACY_NO_VSYNC_CAPTURE+ const bool noVsync = true;+#else+ const char* noVsyncEnv = GetEnvVar( "TRACY_NO_VSYNC_CAPTURE" );+ const bool noVsync = noVsyncEnv && noVsyncEnv[0] == '1';+#endif++ samplingPeriod = GetSamplingPeriod();+ uint32_t currentPid = (uint32_t)getpid();++ s_numCpus = (int)std::thread::hardware_concurrency();++ const auto maxNumBuffers = s_numCpus * (+ 1 + // software sampling+ 2 + // CPU cycles + instructions retired+ 2 + // cache reference + miss+ 2 + // branch retired + miss+ 2 + // context switches + waking ups+ 1 // vsync+ );+ s_ring = (RingBuffer*)tracy_malloc( sizeof( RingBuffer ) * maxNumBuffers );+ s_numBuffers = 0;++ // software sampling+ perf_event_attr pe = {};+ pe.type = PERF_TYPE_SOFTWARE;+ pe.size = sizeof( perf_event_attr );+ pe.config = PERF_COUNT_SW_CPU_CLOCK;+ pe.sample_freq = GetSamplingFrequency();+ pe.sample_type = PERF_SAMPLE_TID | PERF_SAMPLE_TIME | PERF_SAMPLE_CALLCHAIN;+#if LINUX_VERSION_CODE >= KERNEL_VERSION( 4, 8, 0 )+ pe.sample_max_stack = 127;+#endif+ pe.disabled = 1;+ pe.freq = 1;+ pe.inherit = 1;+#if !defined TRACY_HW_TIMER || !( defined __i386 || defined _M_IX86 || defined __x86_64__ || defined _M_X64 )+ pe.use_clockid = 1;+ pe.clockid = CLOCK_MONOTONIC_RAW;+#endif++ if( !noSoftwareSampling )+ {+ TracyDebug( "Setup software sampling\n" );+ ProbePreciseIp( pe, currentPid );+ for( int i=0; i<s_numCpus; i++ )+ {+ int fd = perf_event_open( &pe, currentPid, i, -1, PERF_FLAG_FD_CLOEXEC );+ if( fd == -1 )+ {+ pe.exclude_kernel = 1;+ ProbePreciseIp( pe, currentPid );+ fd = perf_event_open( &pe, currentPid, i, -1, PERF_FLAG_FD_CLOEXEC );+ if( fd == -1 )+ {+ TracyDebug( " Failed to setup!\n");+ break;+ }+ TracyDebug( " No access to kernel samples\n" );+ }+ new( s_ring+s_numBuffers ) RingBuffer( 64*1024, fd, EventCallstack );+ if( s_ring[s_numBuffers].IsValid() )+ {+ s_numBuffers++;+ TracyDebug( " Core %i ok\n", i );+ }+ }+ }++ // CPU cycles + instructions retired+ pe = {};+ pe.type = PERF_TYPE_HARDWARE;+ pe.size = sizeof( perf_event_attr );+ pe.sample_freq = 5000;+ pe.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TIME;+ pe.disabled = 1;+ pe.exclude_kernel = 1;+ pe.exclude_guest = 1;+ pe.exclude_hv = 1;+ pe.freq = 1;+ pe.inherit = 1;+#if !defined TRACY_HW_TIMER || !( defined __i386 || defined _M_IX86 || defined __x86_64__ || defined _M_X64 )+ pe.use_clockid = 1;+ pe.clockid = CLOCK_MONOTONIC_RAW;+#endif++ if( !noRetirement )+ {+ TracyDebug( "Setup sampling cycles + retirement\n" );+ ProbePreciseIp( pe, PERF_COUNT_HW_CPU_CYCLES, PERF_COUNT_HW_INSTRUCTIONS, currentPid );+ for( int i=0; i<s_numCpus; i++ )+ {+ const int fd = perf_event_open( &pe, currentPid, i, -1, PERF_FLAG_FD_CLOEXEC );+ if( fd != -1 )+ {+ new( s_ring+s_numBuffers ) RingBuffer( 64*1024, fd, EventCpuCycles );+ if( s_ring[s_numBuffers].IsValid() )+ {+ s_numBuffers++;+ TracyDebug( " Core %i ok\n", i );+ }+ }+ }++ pe.config = PERF_COUNT_HW_INSTRUCTIONS;+ for( int i=0; i<s_numCpus; i++ )+ {+ const int fd = perf_event_open( &pe, currentPid, i, -1, PERF_FLAG_FD_CLOEXEC );+ if( fd != -1 )+ {+ new( s_ring+s_numBuffers ) RingBuffer( 64*1024, fd, EventInstructionsRetired );+ if( s_ring[s_numBuffers].IsValid() )+ {+ s_numBuffers++;+ TracyDebug( " Core %i ok\n", i );+ }+ }+ }+ }++ // cache reference + miss+ if( !noCache )+ {+ TracyDebug( "Setup sampling CPU cache references + misses\n" );+ ProbePreciseIp( pe, PERF_COUNT_HW_CACHE_REFERENCES, PERF_COUNT_HW_CACHE_MISSES, currentPid );+ if( IsGenuineIntel() )+ {+ pe.precise_ip = 0;+ TracyDebug( " CPU is GenuineIntel, forcing precise_ip down to 0\n" );+ }+ for( int i=0; i<s_numCpus; i++ )+ {+ const int fd = perf_event_open( &pe, currentPid, i, -1, PERF_FLAG_FD_CLOEXEC );+ if( fd != -1 )+ {+ new( s_ring+s_numBuffers ) RingBuffer( 64*1024, fd, EventCacheReference );+ if( s_ring[s_numBuffers].IsValid() )+ {+ s_numBuffers++;+ TracyDebug( " Core %i ok\n", i );+ }+ }+ }++ pe.config = PERF_COUNT_HW_CACHE_MISSES;+ for( int i=0; i<s_numCpus; i++ )+ {+ const int fd = perf_event_open( &pe, currentPid, i, -1, PERF_FLAG_FD_CLOEXEC );+ if( fd != -1 )+ {+ new( s_ring+s_numBuffers ) RingBuffer( 64*1024, fd, EventCacheMiss );+ if( s_ring[s_numBuffers].IsValid() )+ {+ s_numBuffers++;+ TracyDebug( " Core %i ok\n", i );+ }+ }+ }+ }++ // branch retired + miss+ if( !noBranch )+ {+ TracyDebug( "Setup sampling CPU branch retirements + misses\n" );+ ProbePreciseIp( pe, PERF_COUNT_HW_BRANCH_INSTRUCTIONS, PERF_COUNT_HW_BRANCH_MISSES, currentPid );+ for( int i=0; i<s_numCpus; i++ )+ {+ const int fd = perf_event_open( &pe, currentPid, i, -1, PERF_FLAG_FD_CLOEXEC );+ if( fd != -1 )+ {+ new( s_ring+s_numBuffers ) RingBuffer( 64*1024, fd, EventBranchRetired );+ if( s_ring[s_numBuffers].IsValid() )+ {+ s_numBuffers++;+ TracyDebug( " Core %i ok\n", i );+ }+ }+ }++ pe.config = PERF_COUNT_HW_BRANCH_MISSES;+ for( int i=0; i<s_numCpus; i++ )+ {+ const int fd = perf_event_open( &pe, currentPid, i, -1, PERF_FLAG_FD_CLOEXEC );+ if( fd != -1 )+ {+ new( s_ring+s_numBuffers ) RingBuffer( 64*1024, fd, EventBranchMiss );+ if( s_ring[s_numBuffers].IsValid() )+ {+ s_numBuffers++;+ TracyDebug( " Core %i ok\n", i );+ }+ }+ }+ }++ s_ctxBufferIdx = s_numBuffers;++ // vsync+ if( !noVsync && vsyncId != -1 )+ {+ pe = {};+ pe.type = PERF_TYPE_TRACEPOINT;+ pe.size = sizeof( perf_event_attr );+ pe.sample_period = 1;+ pe.sample_type = PERF_SAMPLE_TIME | PERF_SAMPLE_RAW;+ pe.disabled = 1;+ pe.config = vsyncId;+#if !defined TRACY_HW_TIMER || !( defined __i386 || defined _M_IX86 || defined __x86_64__ || defined _M_X64 )+ pe.use_clockid = 1;+ pe.clockid = CLOCK_MONOTONIC_RAW;+#endif++ TracyDebug( "Setup vsync capture\n" );+ for( int i=0; i<s_numCpus; i++ )+ {+ const int fd = perf_event_open( &pe, -1, i, -1, PERF_FLAG_FD_CLOEXEC );+ if( fd != -1 )+ {+ new( s_ring+s_numBuffers ) RingBuffer( 64*1024, fd, EventVsync, i );+ if( s_ring[s_numBuffers].IsValid() )+ {+ s_numBuffers++;+ TracyDebug( " Core %i ok\n", i );+ }+ }+ }+ }++ // context switches+ if( !noCtxSwitch && switchId != -1 )+ {+ pe = {};+ pe.type = PERF_TYPE_TRACEPOINT;+ pe.size = sizeof( perf_event_attr );+ pe.sample_period = 1;+ pe.sample_type = PERF_SAMPLE_TIME | PERF_SAMPLE_RAW | PERF_SAMPLE_CALLCHAIN;+#if LINUX_VERSION_CODE >= KERNEL_VERSION( 4, 8, 0 )+ pe.sample_max_stack = 127;+#endif+ pe.disabled = 1;+ pe.inherit = 1;+ pe.config = switchId;+#if !defined TRACY_HW_TIMER || !( defined __i386 || defined _M_IX86 || defined __x86_64__ || defined _M_X64 )+ pe.use_clockid = 1;+ pe.clockid = CLOCK_MONOTONIC_RAW;+#endif++ TracyDebug( "Setup context switch capture\n" );+ for( int i=0; i<s_numCpus; i++ )+ {+ const int fd = perf_event_open( &pe, -1, i, -1, PERF_FLAG_FD_CLOEXEC );+ if( fd != -1 )+ {+ new( s_ring+s_numBuffers ) RingBuffer( 256*1024, fd, EventContextSwitch, i );+ if( s_ring[s_numBuffers].IsValid() )+ {+ s_numBuffers++;+ TracyDebug( " Core %i ok\n", i );+ }+ }+ }++ if( wakingId != -1 )+ {+ pe = {};+ pe.type = PERF_TYPE_TRACEPOINT;+ pe.size = sizeof( perf_event_attr );+ pe.sample_period = 1;+ pe.sample_type = PERF_SAMPLE_TIME | PERF_SAMPLE_RAW;+ // Coult ask for callstack here+ //pe.sample_type |= PERF_SAMPLE_CALLCHAIN;+ pe.disabled = 1;+ pe.inherit = 1;+ pe.config = wakingId;+ pe.read_format = 0;+#if !defined TRACY_HW_TIMER || !( defined __i386 || defined _M_IX86 || defined __x86_64__ || defined _M_X64 )+ pe.use_clockid = 1;+ pe.clockid = CLOCK_MONOTONIC_RAW;+#endif++ TracyDebug( "Setup waking up capture\n" );+ for( int i=0; i<s_numCpus; i++ )+ {+ const int fd = perf_event_open( &pe, -1, i, -1, PERF_FLAG_FD_CLOEXEC );+ if( fd != -1 )+ {+ new( s_ring+s_numBuffers ) RingBuffer( 64*1024, fd, EventWaking, i );+ if( s_ring[s_numBuffers].IsValid() )+ {+ s_numBuffers++;+ TracyDebug( " Core %i ok\n", i );+ }+ }+ }+ }+ }++ TracyDebug( "Ringbuffers in use: %i\n", s_numBuffers );++ traceActive.store( true, std::memory_order_relaxed );+ return true;+}++void SysTraceStop()+{+ traceActive.store( false, std::memory_order_relaxed );+}++static uint64_t* GetCallstackBlock( uint64_t cnt, RingBuffer& ring, uint64_t offset )+{+ auto trace = (uint64_t*)tracy_malloc_fast( ( 1 + cnt ) * sizeof( uint64_t ) );+ ring.Read( trace+1, offset, sizeof( uint64_t ) * cnt );++#if defined __x86_64__ || defined _M_X64+ // remove non-canonical pointers+ do+ {+ const auto test = (int64_t)trace[cnt];+ const auto m1 = test >> 63;+ const auto m2 = test >> 47;+ if( m1 == m2 ) break;+ }+ while( --cnt > 0 );+ for( uint64_t j=1; j<cnt; j++ )+ {+ const auto test = (int64_t)trace[j];+ const auto m1 = test >> 63;+ const auto m2 = test >> 47;+ if( m1 != m2 ) trace[j] = 0;+ }+#endif++ for( uint64_t j=1; j<=cnt; j++ )+ {+ if( trace[j] >= (uint64_t)-4095 ) // PERF_CONTEXT_MAX+ {+ memmove( trace+j, trace+j+1, sizeof( uint64_t ) * ( cnt - j ) );+ cnt--;+ }+ }++ memcpy( trace, &cnt, sizeof( uint64_t ) );+ return trace;+}++void SysTraceWorker( void* ptr )+{+ ThreadExitHandler threadExitHandler;+ SetThreadName( "Tracy Sampling" );+ InitRpmalloc();+ sched_param sp = { 99 };+ if( pthread_setschedparam( pthread_self(), SCHED_FIFO, &sp ) != 0 ) TracyDebug( "Failed to increase SysTraceWorker thread priority!\n" );+ auto ctxBufferIdx = s_ctxBufferIdx;+ auto ringArray = s_ring;+ auto numBuffers = s_numBuffers;+ for( int i=0; i<numBuffers; i++ ) ringArray[i].Enable();+ for(;;)+ {+#ifdef TRACY_ON_DEMAND+ if( !GetProfiler().IsConnected() )+ {+ if( !traceActive.load( std::memory_order_relaxed ) ) break;+ for( int i=0; i<numBuffers; i++ )+ {+ auto& ring = ringArray[i];+ const auto head = ring.LoadHead();+ const auto tail = ring.GetTail();+ if( head != tail )+ {+ const auto end = head - tail;+ ring.Advance( end );+ }+ }+ if( !traceActive.load( std::memory_order_relaxed ) ) break;+ std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );+ continue;+ }+#endif++ bool hadData = false;+ for( int i=0; i<ctxBufferIdx; i++ )+ {+ if( !traceActive.load( std::memory_order_relaxed ) ) break;+ auto& ring = ringArray[i];+ const auto head = ring.LoadHead();+ const auto tail = ring.GetTail();+ if( head == tail ) continue;+ assert( head > tail );+ hadData = true;++ const auto id = ring.GetId();+ assert( id != EventContextSwitch );+ const auto end = head - tail;+ uint64_t pos = 0;+ if( id == EventCallstack )+ {+ while( pos < end )+ {+ perf_event_header hdr;+ ring.Read( &hdr, pos, sizeof( perf_event_header ) );+ if( hdr.type == PERF_RECORD_SAMPLE )+ {+ auto offset = pos + sizeof( perf_event_header );++ // Layout:+ // u32 pid, tid+ // u64 time+ // u64 cnt+ // u64 ip[cnt]++ uint32_t tid;+ uint64_t t0;+ uint64_t cnt;++ offset += sizeof( uint32_t );+ ring.Read( &tid, offset, sizeof( uint32_t ) );+ offset += sizeof( uint32_t );+ ring.Read( &t0, offset, sizeof( uint64_t ) );+ offset += sizeof( uint64_t );+ ring.Read( &cnt, offset, sizeof( uint64_t ) );+ offset += sizeof( uint64_t );++ if( cnt > 0 )+ {+#if defined TRACY_HW_TIMER && ( defined __i386 || defined _M_IX86 || defined __x86_64__ || defined _M_X64 )+ t0 = ring.ConvertTimeToTsc( t0 );+#endif+ auto trace = GetCallstackBlock( cnt, ring, offset );++ TracyLfqPrepare( QueueType::CallstackSample );+ MemWrite( &item->callstackSampleFat.time, t0 );+ MemWrite( &item->callstackSampleFat.thread, tid );+ MemWrite( &item->callstackSampleFat.ptr, (uint64_t)trace );+ TracyLfqCommit;+ }+ }+ pos += hdr.size;+ }+ }+ else+ {+ while( pos < end )+ {+ perf_event_header hdr;+ ring.Read( &hdr, pos, sizeof( perf_event_header ) );+ if( hdr.type == PERF_RECORD_SAMPLE )+ {+ auto offset = pos + sizeof( perf_event_header );++ // Layout:+ // u64 ip+ // u64 time++ uint64_t ip, t0;+ ring.Read( &ip, offset, sizeof( uint64_t ) );+ offset += sizeof( uint64_t );+ ring.Read( &t0, offset, sizeof( uint64_t ) );++#if defined TRACY_HW_TIMER && ( defined __i386 || defined _M_IX86 || defined __x86_64__ || defined _M_X64 )+ t0 = ring.ConvertTimeToTsc( t0 );+#endif+ QueueType type;+ switch( id )+ {+ case EventCpuCycles:+ type = QueueType::HwSampleCpuCycle;+ break;+ case EventInstructionsRetired:+ type = QueueType::HwSampleInstructionRetired;+ break;+ case EventCacheReference:+ type = QueueType::HwSampleCacheReference;+ break;+ case EventCacheMiss:+ type = QueueType::HwSampleCacheMiss;+ break;+ case EventBranchRetired:+ type = QueueType::HwSampleBranchRetired;+ break;+ case EventBranchMiss:+ type = QueueType::HwSampleBranchMiss;+ break;+ default:+ abort();+ }++ TracyLfqPrepare( type );+ MemWrite( &item->hwSample.ip, ip );+ MemWrite( &item->hwSample.time, t0 );+ TracyLfqCommit;+ }+ pos += hdr.size;+ }+ }+ assert( pos == end );+ ring.Advance( end );+ }+ if( !traceActive.load( std::memory_order_relaxed ) ) break;++ if( ctxBufferIdx != numBuffers )+ {+ const auto ctxBufNum = numBuffers - ctxBufferIdx;++ int activeNum = 0;+ uint16_t active[512];+ uint32_t end[512];+ uint32_t pos[512];+ for( int i=0; i<ctxBufNum; i++ )+ {+ const auto rbIdx = ctxBufferIdx + i;+ const auto rbHead = ringArray[rbIdx].LoadHead();+ const auto rbTail = ringArray[rbIdx].GetTail();+ const auto rbActive = rbHead != rbTail;++ if( rbActive )+ {+ active[activeNum] = (uint16_t)i;+ activeNum++;+ end[i] = rbHead - rbTail;+ pos[i] = 0;+ }+ else+ {+ end[i] = 0;+ }+ }+ if( activeNum > 0 )+ {+ hadData = true;+ while( activeNum > 0 )+ {+ // Find the earliest event from the active buffers+ int sel = -1;+ int selPos;+ int64_t t0 = std::numeric_limits<int64_t>::max();+ for( int i=0; i<activeNum; i++ )+ {+ auto idx = active[i];+ auto rbPos = pos[idx];+ assert( rbPos < end[idx] );+ const auto rbIdx = ctxBufferIdx + idx;+ perf_event_header hdr;+ ringArray[rbIdx].Read( &hdr, rbPos, sizeof( perf_event_header ) );+ if( hdr.type == PERF_RECORD_SAMPLE )+ {+ int64_t rbTime;+ ringArray[rbIdx].Read( &rbTime, rbPos + sizeof( perf_event_header ), sizeof( int64_t ) );+ if( rbTime < t0 )+ {+ t0 = rbTime;+ sel = idx;+ selPos = i;+ }+ }+ else+ {+ rbPos += hdr.size;+ if( rbPos == end[idx] )+ {+ memmove( active+i, active+i+1, sizeof(*active) * ( activeNum - i - 1 ) );+ activeNum--;+ i--;+ }+ else+ {+ pos[idx] = rbPos;+ }+ }+ }+ // Found any event+ if( sel >= 0 )+ {+ auto& ring = ringArray[ctxBufferIdx + sel];+ auto rbPos = pos[sel];+ auto offset = rbPos;+ perf_event_header hdr;+ ring.Read( &hdr, offset, sizeof( perf_event_header ) );++#if defined TRACY_HW_TIMER && ( defined __i386 || defined _M_IX86 || defined __x86_64__ || defined _M_X64 )+ t0 = ring.ConvertTimeToTsc( t0 );+#endif++ const auto rid = ring.GetId();+ if( rid == EventContextSwitch )+ {+ // Layout: See /sys/kernel/debug/tracing/events/sched/sched_switch/format+ // u64 time // PERF_SAMPLE_TIME+ // u64 cnt // PERF_SAMPLE_CALLCHAIN+ // u64 ip[cnt] // PERF_SAMPLE_CALLCHAIN+ // u32 size+ // u8 data[size]+ // Data (not ABI stable, but has not changed since it was added, in 2009):+ // u8 hdr[8]+ // u8 prev_comm[16]+ // u32 prev_pid+ // u32 prev_prio+ // lng prev_state+ // u8 next_comm[16]+ // u32 next_pid+ // u32 next_prio++ offset += sizeof( perf_event_header ) + sizeof( uint64_t );++ uint64_t cnt;+ ring.Read( &cnt, offset, sizeof( uint64_t ) );+ offset += sizeof( uint64_t );+ const auto traceOffset = offset;+ offset += sizeof( uint64_t ) * cnt + sizeof( uint32_t ) + 8 + 16;++ uint32_t prev_pid, prev_prio;+ uint32_t next_pid, next_prio;+ long prev_state;++ ring.Read( &prev_pid, offset, sizeof( uint32_t ) );+ offset += sizeof( uint32_t );+ ring.Read( &prev_prio, offset, sizeof( uint32_t ) );+ offset += sizeof( uint32_t );+ ring.Read( &prev_state, offset, sizeof( long ) );+ offset += sizeof( long ) + 16;+ ring.Read( &next_pid, offset, sizeof( uint32_t ) );+ offset += sizeof( uint32_t );+ ring.Read( &next_prio, offset, sizeof( uint32_t ) );++ uint8_t oldThreadWaitReason = 100;+ uint8_t oldThreadState;++ if( prev_state & 0x0001 ) oldThreadState = 104;+ else if( prev_state & 0x0002 ) oldThreadState = 101;+ else if( prev_state & 0x0004 ) oldThreadState = 105;+ else if( prev_state & 0x0008 ) oldThreadState = 106;+ else if( prev_state & 0x0010 ) oldThreadState = 108;+ else if( prev_state & 0x0020 ) oldThreadState = 109;+ else if( prev_state & 0x0040 ) oldThreadState = 110;+ else if( prev_state & 0x0080 ) oldThreadState = 102;+ else oldThreadState = 103;++ TracyLfqPrepare( QueueType::ContextSwitch );+ MemWrite( &item->contextSwitch.time, t0 );+ MemWrite( &item->contextSwitch.oldThread, prev_pid );+ MemWrite( &item->contextSwitch.newThread, next_pid );+ MemWrite( &item->contextSwitch.cpu, uint8_t( ring.GetCpu() ) );+ MemWrite( &item->contextSwitch.oldThreadWaitReason, oldThreadWaitReason );+ MemWrite( &item->contextSwitch.oldThreadState, oldThreadState );+ MemWrite( &item->contextSwitch.previousCState, uint8_t( 0 ) );+ MemWrite( &item->contextSwitch.newThreadPriority, int8_t( next_prio ) );+ MemWrite( &item->contextSwitch.oldThreadPriority, int8_t( prev_prio ) );+ TracyLfqCommit;++ if( cnt > 0 && prev_pid != 0 && CurrentProcOwnsThread( prev_pid ) )+ {+ auto trace = GetCallstackBlock( cnt, ring, traceOffset );++ TracyLfqPrepare( QueueType::CallstackSampleContextSwitch );+ MemWrite( &item->callstackSampleFat.time, t0 );+ MemWrite( &item->callstackSampleFat.thread, prev_pid );+ MemWrite( &item->callstackSampleFat.ptr, (uint64_t)trace );+ TracyLfqCommit;+ }+ }+ else if( rid == EventWaking)+ {+ // See /sys/kernel/debug/tracing/events/sched/sched_waking/format+ // Layout:+ // u64 time // PERF_SAMPLE_TIME+ // u32 size+ // u8 data[size]+ // Data:+ // u8 hdr[8]+ // u8 comm[16]+ // u32 pid+ // i32 prio+ // i32 target_cpu+ const uint32_t dataOffset = sizeof( perf_event_header ) + sizeof( uint64_t ) + sizeof( uint32_t ); + offset += dataOffset + 8 + 16;+ uint32_t pid;+ ring.Read( &pid, offset, sizeof( uint32_t ) );+ + TracyLfqPrepare( QueueType::ThreadWakeup );+ MemWrite( &item->threadWakeup.time, t0 );+ MemWrite( &item->threadWakeup.thread, pid );+ MemWrite( &item->threadWakeup.cpu, (uint8_t)ring.GetCpu() );++ int8_t adjustReason = -1; // Does not exist on Linux+ int8_t adjustIncrement = 0; // Should perhaps store the new prio?+ MemWrite( &item->threadWakeup.adjustReason, adjustReason );+ MemWrite( &item->threadWakeup.adjustIncrement, adjustIncrement );+ TracyLfqCommit;+ }+ else+ {+ assert( rid == EventVsync );+ // Layout:+ // u64 time+ // u32 size+ // u8 data[size]+ // Data (not ABI stable):+ // u8 hdr[8]+ // i32 crtc+ // u32 seq+ // i64 ktime+ // u8 high precision++ offset += sizeof( perf_event_header ) + sizeof( uint64_t ) + sizeof( uint32_t ) + 8;++ int32_t crtc;+ ring.Read( &crtc, offset, sizeof( int32_t ) );++ // Note: The timestamp value t0 might be off by a number of microseconds from the+ // true hardware vblank event. The ktime value should be used instead, but it is+ // measured in CLOCK_MONOTONIC time. Tracy only supports the timestamp counter+ // register (TSC) or CLOCK_MONOTONIC_RAW clock.+#if 0+ offset += sizeof( uint32_t ) * 2;+ int64_t ktime;+ ring.Read( &ktime, offset, sizeof( int64_t ) );+#endif++ TracyLfqPrepare( QueueType::FrameVsync );+ MemWrite( &item->frameVsync.id, crtc );+ MemWrite( &item->frameVsync.time, t0 );+ TracyLfqCommit;+ }++ rbPos += hdr.size;+ if( rbPos == end[sel] )+ {+ memmove( active+selPos, active+selPos+1, sizeof(*active) * ( activeNum - selPos - 1 ) );+ activeNum--;+ }+ else+ {+ pos[sel] = rbPos;+ }+ }+ }+ for( int i=0; i<ctxBufNum; i++ )+ {+ if( end[i] != 0 ) ringArray[ctxBufferIdx + i].Advance( end[i] );+ }+ }+ }+ if( !traceActive.load( std::memory_order_relaxed ) ) break;+ if( !hadData )+ {+ std::this_thread::sleep_for( std::chrono::milliseconds( 1 ) );+ }+ }++ for( int i=0; i<numBuffers; i++ ) ringArray[i].~RingBuffer();+ tracy_free_fast( ringArray );+}++void SysTraceGetExternalName( uint64_t thread, const char*& threadName, const char*& name )+{+ FILE* f;+ char fn[256];+ sprintf( fn, "/proc/%" PRIu64 "/comm", thread );+ f = fopen( fn, "rb" );+ if( f )+ {+ char buf[256];+ const auto sz = fread( buf, 1, 256, f );+ if( sz > 0 && buf[sz-1] == '\n' ) buf[sz-1] = '\0';+ threadName = CopyString( buf );+ fclose( f );+ }+ else+ {+ threadName = CopyString( "???", 3 );+ }++ sprintf( fn, "/proc/%" PRIu64 "/status", thread );+ f = fopen( fn, "rb" );+ if( f )+ {+ char* tmp = (char*)tracy_malloc_fast( 8*1024 );+ const auto fsz = (ptrdiff_t)fread( tmp, 1, 8*1024, f );+ fclose( f );++ int pid = -1;+ auto line = tmp;+ for(;;)+ {+ if( memcmp( "Tgid:\t", line, 6 ) == 0 )+ {+ pid = atoi( line + 6 );+ break;+ }+ while( line - tmp < fsz && *line != '\n' ) line++;+ if( *line != '\n' ) break;+ line++;+ }+ tracy_free_fast( tmp );++ if( pid >= 0 )+ {+ {+ uint64_t _pid = pid;+ TracyLfqPrepare( QueueType::TidToPid );+ MemWrite( &item->tidToPid.tid, thread );+ MemWrite( &item->tidToPid.pid, _pid );+ TracyLfqCommit;+ }+ sprintf( fn, "/proc/%i/comm", pid );+ f = fopen( fn, "rb" );+ if( f )+ {+ char buf[256];+ const auto sz = fread( buf, 1, 256, f );+ if( sz > 0 && buf[sz-1] == '\n' ) buf[sz-1] = '\0';+ name = CopyStringFast( buf );+ fclose( f );+ return;+ }+ }+ }+ name = CopyStringFast( "???", 3 );+}++}++# endif++#endif
+ cbits/tracy/public/client/TracySysTrace.hpp view
@@ -0,0 +1,28 @@+#ifndef __TRACYSYSTRACE_HPP__+#define __TRACYSYSTRACE_HPP__++#if !defined TRACY_NO_SYSTEM_TRACING && ( defined _WIN32 || defined __linux__ )+# include "../common/TracyUwp.hpp"+# ifndef TRACY_UWP+# define TRACY_HAS_SYSTEM_TRACING+# endif+#endif++#ifdef TRACY_HAS_SYSTEM_TRACING++#include <stdint.h>++namespace tracy+{++bool SysTraceStart( int64_t& samplingPeriod );+void SysTraceStop();+void SysTraceWorker( void* ptr );++void SysTraceGetExternalName( uint64_t thread, const char*& threadName, const char*& name );++}++#endif++#endif
+ cbits/tracy/public/client/TracyThread.hpp view
@@ -0,0 +1,90 @@+#ifndef __TRACYTHREAD_HPP__+#define __TRACYTHREAD_HPP__++#if defined _WIN32+# include <windows.h>+#else+# include <pthread.h>+#endif++#ifdef TRACY_MANUAL_LIFETIME+# include "tracy_rpmalloc.hpp"+#endif++namespace tracy+{++#ifdef TRACY_MANUAL_LIFETIME+extern thread_local bool RpThreadInitDone;+#endif++class ThreadExitHandler+{+public:+ ~ThreadExitHandler()+ {+#ifdef TRACY_MANUAL_LIFETIME+ rpmalloc_thread_finalize( 1 );+ RpThreadInitDone = false;+#endif+ }+};++#if defined _WIN32++class Thread+{+public:+ Thread( void(*func)( void* ptr ), void* ptr )+ : m_func( func )+ , m_ptr( ptr )+ , m_hnd( CreateThread( nullptr, 0, Launch, this, 0, nullptr ) )+ {}++ ~Thread()+ {+ WaitForSingleObject( m_hnd, INFINITE );+ CloseHandle( m_hnd );+ }++ HANDLE Handle() const { return m_hnd; }++private:+ static DWORD WINAPI Launch( void* ptr ) { ((Thread*)ptr)->m_func( ((Thread*)ptr)->m_ptr ); return 0; }++ void(*m_func)( void* ptr );+ void* m_ptr;+ HANDLE m_hnd;+};++#else++class Thread+{+public:+ Thread( void(*func)( void* ptr ), void* ptr )+ : m_func( func )+ , m_ptr( ptr )+ {+ pthread_create( &m_thread, nullptr, Launch, this );+ }++ ~Thread()+ {+ pthread_join( m_thread, nullptr );+ }++ pthread_t Handle() const { return m_thread; }++private:+ static void* Launch( void* ptr ) { ((Thread*)ptr)->m_func( ((Thread*)ptr)->m_ptr ); return nullptr; }+ void(*m_func)( void* ptr );+ void* m_ptr;+ pthread_t m_thread;+};++#endif++}++#endif
+ cbits/tracy/public/client/tracy_SPSCQueue.h view
@@ -0,0 +1,148 @@+/*+Copyright (c) 2020 Erik Rigtorp <erik@rigtorp.se>++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.+ */++#pragma once++#include <atomic>+#include <cassert>+#include <cstddef>+#include <stdexcept>+#include <type_traits> // std::enable_if, std::is_*_constructible++#include "../common/TracyAlloc.hpp"++#if defined (_MSC_VER)+#pragma warning(push)+#pragma warning(disable:4324)+#endif++namespace tracy {++template <typename T> class SPSCQueue {+public:+ explicit SPSCQueue(const size_t capacity)+ : capacity_(capacity) {+ capacity_++; // Needs one slack element+ slots_ = (T*)tracy_malloc(sizeof(T) * (capacity_ + 2 * kPadding));++ static_assert(alignof(SPSCQueue<T>) == kCacheLineSize, "");+ static_assert(sizeof(SPSCQueue<T>) >= 3 * kCacheLineSize, "");+ assert(reinterpret_cast<char *>(&readIdx_) -+ reinterpret_cast<char *>(&writeIdx_) >=+ static_cast<std::ptrdiff_t>(kCacheLineSize));+ }++ ~SPSCQueue() {+ while (front()) {+ pop();+ }+ tracy_free(slots_);+ }++ // non-copyable and non-movable+ SPSCQueue(const SPSCQueue &) = delete;+ SPSCQueue &operator=(const SPSCQueue &) = delete;++ template <typename... Args>+ void emplace(Args &&...args) noexcept(+ std::is_nothrow_constructible<T, Args &&...>::value) {+ static_assert(std::is_constructible<T, Args &&...>::value,+ "T must be constructible with Args&&...");+ auto const writeIdx = writeIdx_.load(std::memory_order_relaxed);+ auto nextWriteIdx = writeIdx + 1;+ if (nextWriteIdx == capacity_) {+ nextWriteIdx = 0;+ }+ while (nextWriteIdx == readIdxCache_) {+ readIdxCache_ = readIdx_.load(std::memory_order_acquire);+ }+ new (&slots_[writeIdx + kPadding]) T(std::forward<Args>(args)...);+ writeIdx_.store(nextWriteIdx, std::memory_order_release);+ }++ T *front() noexcept {+ auto const readIdx = readIdx_.load(std::memory_order_relaxed);+ if (readIdx == writeIdxCache_) {+ writeIdxCache_ = writeIdx_.load(std::memory_order_acquire);+ if (writeIdxCache_ == readIdx) {+ return nullptr;+ }+ }+ return &slots_[readIdx + kPadding];+ }++ void pop() noexcept {+ static_assert(std::is_nothrow_destructible<T>::value,+ "T must be nothrow destructible");+ auto const readIdx = readIdx_.load(std::memory_order_relaxed);+ assert(writeIdx_.load(std::memory_order_acquire) != readIdx);+ slots_[readIdx + kPadding].~T();+ auto nextReadIdx = readIdx + 1;+ if (nextReadIdx == capacity_) {+ nextReadIdx = 0;+ }+ readIdx_.store(nextReadIdx, std::memory_order_release);+ }++ size_t size() const noexcept {+ std::ptrdiff_t diff = writeIdx_.load(std::memory_order_acquire) -+ readIdx_.load(std::memory_order_acquire);+ if (diff < 0) {+ diff += capacity_;+ }+ return static_cast<size_t>(diff);+ }++ bool empty() const noexcept {+ return writeIdx_.load(std::memory_order_acquire) ==+ readIdx_.load(std::memory_order_acquire);+ }++ size_t capacity() const noexcept { return capacity_ - 1; }++private:+ static constexpr size_t kCacheLineSize = 64;++ // Padding to avoid false sharing between slots_ and adjacent allocations+ static constexpr size_t kPadding = (kCacheLineSize - 1) / sizeof(T) + 1;++private:+ size_t capacity_;+ T *slots_;++ // Align to cache line size in order to avoid false sharing+ // readIdxCache_ and writeIdxCache_ is used to reduce the amount of cache+ // coherency traffic+ alignas(kCacheLineSize) std::atomic<size_t> writeIdx_ = {0};+ alignas(kCacheLineSize) size_t readIdxCache_ = 0;+ alignas(kCacheLineSize) std::atomic<size_t> readIdx_ = {0};+ alignas(kCacheLineSize) size_t writeIdxCache_ = 0;++ // Padding to avoid adjacent allocations to share cache line with+ // writeIdxCache_+ char padding_[kCacheLineSize - sizeof(SPSCQueue<T>::writeIdxCache_)];+};+} // namespace rigtorp++#if defined (_MSC_VER)+#pragma warning(pop)+#endif
+ cbits/tracy/public/client/tracy_concurrentqueue.h view
@@ -0,0 +1,1441 @@+// Provides a C++11 implementation of a multi-producer, multi-consumer lock-free queue.+// An overview, including benchmark results, is provided here:+// http://moodycamel.com/blog/2014/a-fast-general-purpose-lock-free-queue-for-c+++// The full design is also described in excruciating detail at:+// http://moodycamel.com/blog/2014/detailed-design-of-a-lock-free-queue++// Simplified BSD license:+// Copyright (c) 2013-2016, Cameron Desrochers.+// All rights reserved.+//+// 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.+//+// 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 HOLDER 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.+++#pragma once++#include "../common/TracyAlloc.hpp"+#include "../common/TracyForceInline.hpp"+#include "../common/TracySystem.hpp"++#if defined(__GNUC__)+// Disable -Wconversion warnings (spuriously triggered when Traits::size_t and+// Traits::index_t are set to < 32 bits, causing integer promotion, causing warnings+// upon assigning any computed values)+#pragma GCC diagnostic push+#pragma GCC diagnostic ignored "-Wconversion"+#endif++#if defined(__APPLE__)+#include "TargetConditionals.h"+#endif++#include <atomic> // Requires C++11. Sorry VS2010.+#include <cassert>+#include <cstddef> // for max_align_t+#include <cstdint>+#include <cstdlib>+#include <type_traits>+#include <algorithm>+#include <utility>+#include <limits>+#include <climits> // for CHAR_BIT+#include <array>+#include <thread> // partly for __WINPTHREADS_VERSION if on MinGW-w64 w/ POSIX threading++namespace tracy+{++// Compiler-specific likely/unlikely hints+namespace moodycamel { namespace details {+#if defined(__GNUC__)+ inline bool cqLikely(bool x) { return __builtin_expect((x), true); }+ inline bool cqUnlikely(bool x) { return __builtin_expect((x), false); }+#else+ inline bool cqLikely(bool x) { return x; }+ inline bool cqUnlikely(bool x) { return x; }+#endif+} }++namespace+{+ // to avoid MSVC warning 4127: conditional expression is constant+ template <bool>+ struct compile_time_condition+ {+ static const bool value = false;+ };+ template <>+ struct compile_time_condition<true>+ {+ static const bool value = true;+ };+}++namespace moodycamel {+namespace details {+ template<typename T>+ struct const_numeric_max {+ static_assert(std::is_integral<T>::value, "const_numeric_max can only be used with integers");+ static const T value = std::numeric_limits<T>::is_signed+ ? (static_cast<T>(1) << (sizeof(T) * CHAR_BIT - 1)) - static_cast<T>(1)+ : static_cast<T>(-1);+ };++#if defined(__GLIBCXX__)+ typedef ::max_align_t std_max_align_t; // libstdc++ forgot to add it to std:: for a while+#else+ typedef std::max_align_t std_max_align_t; // Others (e.g. MSVC) insist it can *only* be accessed via std::+#endif++ // Some platforms have incorrectly set max_align_t to a type with <8 bytes alignment even while supporting+ // 8-byte aligned scalar values (*cough* 32-bit iOS). Work around this with our own union. See issue #64.+ typedef union {+ std_max_align_t x;+ long long y;+ void* z;+ } max_align_t;+}++// Default traits for the ConcurrentQueue. To change some of the+// traits without re-implementing all of them, inherit from this+// struct and shadow the declarations you wish to be different;+// since the traits are used as a template type parameter, the+// shadowed declarations will be used where defined, and the defaults+// otherwise.+struct ConcurrentQueueDefaultTraits+{+ // General-purpose size type. std::size_t is strongly recommended.+ typedef std::size_t size_t;++ // The type used for the enqueue and dequeue indices. Must be at least as+ // large as size_t. Should be significantly larger than the number of elements+ // you expect to hold at once, especially if you have a high turnover rate;+ // for example, on 32-bit x86, if you expect to have over a hundred million+ // elements or pump several million elements through your queue in a very+ // short space of time, using a 32-bit type *may* trigger a race condition.+ // A 64-bit int type is recommended in that case, and in practice will+ // prevent a race condition no matter the usage of the queue. Note that+ // whether the queue is lock-free with a 64-int type depends on the whether+ // std::atomic<std::uint64_t> is lock-free, which is platform-specific.+ typedef std::size_t index_t;++ // Internally, all elements are enqueued and dequeued from multi-element+ // blocks; this is the smallest controllable unit. If you expect few elements+ // but many producers, a smaller block size should be favoured. For few producers+ // and/or many elements, a larger block size is preferred. A sane default+ // is provided. Must be a power of 2.+ static const size_t BLOCK_SIZE = 64*1024;++ // For explicit producers (i.e. when using a producer token), the block is+ // checked for being empty by iterating through a list of flags, one per element.+ // For large block sizes, this is too inefficient, and switching to an atomic+ // counter-based approach is faster. The switch is made for block sizes strictly+ // larger than this threshold.+ static const size_t EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD = 32;++ // How many full blocks can be expected for a single explicit producer? This should+ // reflect that number's maximum for optimal performance. Must be a power of 2.+ static const size_t EXPLICIT_INITIAL_INDEX_SIZE = 32;++ // Controls the number of items that an explicit consumer (i.e. one with a token)+ // must consume before it causes all consumers to rotate and move on to the next+ // internal queue.+ static const std::uint32_t EXPLICIT_CONSUMER_CONSUMPTION_QUOTA_BEFORE_ROTATE = 256;++ // The maximum number of elements (inclusive) that can be enqueued to a sub-queue.+ // Enqueue operations that would cause this limit to be surpassed will fail. Note+ // that this limit is enforced at the block level (for performance reasons), i.e.+ // it's rounded up to the nearest block size.+ static const size_t MAX_SUBQUEUE_SIZE = details::const_numeric_max<size_t>::value;+++ // Memory allocation can be customized if needed.+ // malloc should return nullptr on failure, and handle alignment like std::malloc.+#if defined(malloc) || defined(free)+ // Gah, this is 2015, stop defining macros that break standard code already!+ // Work around malloc/free being special macros:+ static inline void* WORKAROUND_malloc(size_t size) { return malloc(size); }+ static inline void WORKAROUND_free(void* ptr) { return free(ptr); }+ static inline void* (malloc)(size_t size) { return WORKAROUND_malloc(size); }+ static inline void (free)(void* ptr) { return WORKAROUND_free(ptr); }+#else+ static inline void* malloc(size_t size) { return tracy::tracy_malloc(size); }+ static inline void free(void* ptr) { return tracy::tracy_free(ptr); }+#endif+};+++// When producing or consuming many elements, the most efficient way is to:+// 1) Use one of the bulk-operation methods of the queue with a token+// 2) Failing that, use the bulk-operation methods without a token+// 3) Failing that, create a token and use that with the single-item methods+// 4) Failing that, use the single-parameter methods of the queue+// Having said that, don't create tokens willy-nilly -- ideally there should be+// a maximum of one token per thread (of each kind).+struct ProducerToken;+struct ConsumerToken;++template<typename T, typename Traits> class ConcurrentQueue;+++namespace details+{+ struct ConcurrentQueueProducerTypelessBase+ {+ ConcurrentQueueProducerTypelessBase* next;+ std::atomic<bool> inactive;+ ProducerToken* token;+ uint32_t threadId;++ ConcurrentQueueProducerTypelessBase()+ : next(nullptr), inactive(false), token(nullptr), threadId(0)+ {+ }+ };++ template<typename T>+ static inline bool circular_less_than(T a, T b)+ {+ static_assert(std::is_integral<T>::value && !std::numeric_limits<T>::is_signed, "circular_less_than is intended to be used only with unsigned integer types");+ return static_cast<T>(a - b) > static_cast<T>(static_cast<T>(1) << (static_cast<T>(sizeof(T) * CHAR_BIT - 1)));+ // Note: extra parens around rhs of operator<< is MSVC bug: https://developercommunity2.visualstudio.com/t/C4554-triggers-when-both-lhs-and-rhs-is/10034931+ // silencing the bug requires #pragma warning(disable: 4554) around the calling code and has no effect when done here.+ }++ template<typename U>+ static inline char* align_for(char* ptr)+ {+ const std::size_t alignment = std::alignment_of<U>::value;+ return ptr + (alignment - (reinterpret_cast<std::uintptr_t>(ptr) % alignment)) % alignment;+ }++ template<typename T>+ static inline T ceil_to_pow_2(T x)+ {+ static_assert(std::is_integral<T>::value && !std::numeric_limits<T>::is_signed, "ceil_to_pow_2 is intended to be used only with unsigned integer types");++ // Adapted from http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2+ --x;+ x |= x >> 1;+ x |= x >> 2;+ x |= x >> 4;+ for (std::size_t i = 1; i < sizeof(T); i <<= 1) {+ x |= x >> (i << 3);+ }+ ++x;+ return x;+ }++ template<typename T>+ static inline void swap_relaxed(std::atomic<T>& left, std::atomic<T>& right)+ {+ T temp = std::move(left.load(std::memory_order_relaxed));+ left.store(std::move(right.load(std::memory_order_relaxed)), std::memory_order_relaxed);+ right.store(std::move(temp), std::memory_order_relaxed);+ }++ template<typename T>+ static inline T const& nomove(T const& x)+ {+ return x;+ }++ template<bool Enable>+ struct nomove_if+ {+ template<typename T>+ static inline T const& eval(T const& x)+ {+ return x;+ }+ };++ template<>+ struct nomove_if<false>+ {+ template<typename U>+ static inline auto eval(U&& x)+ -> decltype(std::forward<U>(x))+ {+ return std::forward<U>(x);+ }+ };++ template<typename It>+ static inline auto deref_noexcept(It& it) noexcept -> decltype(*it)+ {+ return *it;+ }++#if defined(__clang__) || !defined(__GNUC__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)+ template<typename T> struct is_trivially_destructible : std::is_trivially_destructible<T> { };+#else+ template<typename T> struct is_trivially_destructible : std::has_trivial_destructor<T> { };+#endif++ template<typename T> struct static_is_lock_free_num { enum { value = 0 }; };+ template<> struct static_is_lock_free_num<signed char> { enum { value = ATOMIC_CHAR_LOCK_FREE }; };+ template<> struct static_is_lock_free_num<short> { enum { value = ATOMIC_SHORT_LOCK_FREE }; };+ template<> struct static_is_lock_free_num<int> { enum { value = ATOMIC_INT_LOCK_FREE }; };+ template<> struct static_is_lock_free_num<long> { enum { value = ATOMIC_LONG_LOCK_FREE }; };+ template<> struct static_is_lock_free_num<long long> { enum { value = ATOMIC_LLONG_LOCK_FREE }; };+ template<typename T> struct static_is_lock_free : static_is_lock_free_num<typename std::make_signed<T>::type> { };+ template<> struct static_is_lock_free<bool> { enum { value = ATOMIC_BOOL_LOCK_FREE }; };+ template<typename U> struct static_is_lock_free<U*> { enum { value = ATOMIC_POINTER_LOCK_FREE }; };+}+++struct ProducerToken+{+ template<typename T, typename Traits>+ explicit ProducerToken(ConcurrentQueue<T, Traits>& queue);++ ProducerToken(ProducerToken&& other) noexcept+ : producer(other.producer)+ {+ other.producer = nullptr;+ if (producer != nullptr) {+ producer->token = this;+ }+ }++ inline ProducerToken& operator=(ProducerToken&& other) noexcept+ {+ swap(other);+ return *this;+ }++ void swap(ProducerToken& other) noexcept+ {+ std::swap(producer, other.producer);+ if (producer != nullptr) {+ producer->token = this;+ }+ if (other.producer != nullptr) {+ other.producer->token = &other;+ }+ }++ // A token is always valid unless:+ // 1) Memory allocation failed during construction+ // 2) It was moved via the move constructor+ // (Note: assignment does a swap, leaving both potentially valid)+ // 3) The associated queue was destroyed+ // Note that if valid() returns true, that only indicates+ // that the token is valid for use with a specific queue,+ // but not which one; that's up to the user to track.+ inline bool valid() const { return producer != nullptr; }++ ~ProducerToken()+ {+ if (producer != nullptr) {+ producer->token = nullptr;+ producer->inactive.store(true, std::memory_order_release);+ }+ }++ // Disable copying and assignment+ ProducerToken(ProducerToken const&) = delete;+ ProducerToken& operator=(ProducerToken const&) = delete;++private:+ template<typename T, typename Traits> friend class ConcurrentQueue;++protected:+ details::ConcurrentQueueProducerTypelessBase* producer;+};+++struct ConsumerToken+{+ template<typename T, typename Traits>+ explicit ConsumerToken(ConcurrentQueue<T, Traits>& q);++ ConsumerToken(ConsumerToken&& other) noexcept+ : initialOffset(other.initialOffset), lastKnownGlobalOffset(other.lastKnownGlobalOffset), itemsConsumedFromCurrent(other.itemsConsumedFromCurrent), currentProducer(other.currentProducer), desiredProducer(other.desiredProducer)+ {+ }++ inline ConsumerToken& operator=(ConsumerToken&& other) noexcept+ {+ swap(other);+ return *this;+ }++ void swap(ConsumerToken& other) noexcept+ {+ std::swap(initialOffset, other.initialOffset);+ std::swap(lastKnownGlobalOffset, other.lastKnownGlobalOffset);+ std::swap(itemsConsumedFromCurrent, other.itemsConsumedFromCurrent);+ std::swap(currentProducer, other.currentProducer);+ std::swap(desiredProducer, other.desiredProducer);+ }++ // Disable copying and assignment+ ConsumerToken(ConsumerToken const&) = delete;+ ConsumerToken& operator=(ConsumerToken const&) = delete;++private:+ template<typename T, typename Traits> friend class ConcurrentQueue;++private: // but shared with ConcurrentQueue+ std::uint32_t initialOffset;+ std::uint32_t lastKnownGlobalOffset;+ std::uint32_t itemsConsumedFromCurrent;+ details::ConcurrentQueueProducerTypelessBase* currentProducer;+ details::ConcurrentQueueProducerTypelessBase* desiredProducer;+};+++template<typename T, typename Traits = ConcurrentQueueDefaultTraits>+class ConcurrentQueue+{+public:+ struct ExplicitProducer;++ typedef moodycamel::ProducerToken producer_token_t;+ typedef moodycamel::ConsumerToken consumer_token_t;++ typedef typename Traits::index_t index_t;+ typedef typename Traits::size_t size_t;++ static const size_t BLOCK_SIZE = static_cast<size_t>(Traits::BLOCK_SIZE);+ static const size_t EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD = static_cast<size_t>(Traits::EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD);+ static const size_t EXPLICIT_INITIAL_INDEX_SIZE = static_cast<size_t>(Traits::EXPLICIT_INITIAL_INDEX_SIZE);+ static const std::uint32_t EXPLICIT_CONSUMER_CONSUMPTION_QUOTA_BEFORE_ROTATE = static_cast<std::uint32_t>(Traits::EXPLICIT_CONSUMER_CONSUMPTION_QUOTA_BEFORE_ROTATE);+#ifdef _MSC_VER+#pragma warning(push)+#pragma warning(disable: 4307) // + integral constant overflow (that's what the ternary expression is for!)+#pragma warning(disable: 4309) // static_cast: Truncation of constant value+#endif+ static const size_t MAX_SUBQUEUE_SIZE = (details::const_numeric_max<size_t>::value - static_cast<size_t>(Traits::MAX_SUBQUEUE_SIZE) < BLOCK_SIZE) ? details::const_numeric_max<size_t>::value : ((static_cast<size_t>(Traits::MAX_SUBQUEUE_SIZE) + (BLOCK_SIZE - 1)) / BLOCK_SIZE * BLOCK_SIZE);+#ifdef _MSC_VER+#pragma warning(pop)+#endif++ static_assert(!std::numeric_limits<size_t>::is_signed && std::is_integral<size_t>::value, "Traits::size_t must be an unsigned integral type");+ static_assert(!std::numeric_limits<index_t>::is_signed && std::is_integral<index_t>::value, "Traits::index_t must be an unsigned integral type");+ static_assert(sizeof(index_t) >= sizeof(size_t), "Traits::index_t must be at least as wide as Traits::size_t");+ static_assert((BLOCK_SIZE > 1) && !(BLOCK_SIZE & (BLOCK_SIZE - 1)), "Traits::BLOCK_SIZE must be a power of 2 (and at least 2)");+ static_assert((EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD > 1) && !(EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD & (EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD - 1)), "Traits::EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD must be a power of 2 (and greater than 1)");+ static_assert((EXPLICIT_INITIAL_INDEX_SIZE > 1) && !(EXPLICIT_INITIAL_INDEX_SIZE & (EXPLICIT_INITIAL_INDEX_SIZE - 1)), "Traits::EXPLICIT_INITIAL_INDEX_SIZE must be a power of 2 (and greater than 1)");++public:+ // Creates a queue with at least `capacity` element slots; note that the+ // actual number of elements that can be inserted without additional memory+ // allocation depends on the number of producers and the block size (e.g. if+ // the block size is equal to `capacity`, only a single block will be allocated+ // up-front, which means only a single producer will be able to enqueue elements+ // without an extra allocation -- blocks aren't shared between producers).+ // This method is not thread safe -- it is up to the user to ensure that the+ // queue is fully constructed before it starts being used by other threads (this+ // includes making the memory effects of construction visible, possibly with a+ // memory barrier).+ explicit ConcurrentQueue(size_t capacity = 6 * BLOCK_SIZE)+ : producerListTail(nullptr),+ producerCount(0),+ initialBlockPoolIndex(0),+ nextExplicitConsumerId(0),+ globalExplicitConsumerOffset(0)+ {+ populate_initial_block_list(capacity / BLOCK_SIZE + ((capacity & (BLOCK_SIZE - 1)) == 0 ? 0 : 1));+ }++ // Computes the correct amount of pre-allocated blocks for you based+ // on the minimum number of elements you want available at any given+ // time, and the maximum concurrent number of each type of producer.+ ConcurrentQueue(size_t minCapacity, size_t maxExplicitProducers)+ : producerListTail(nullptr),+ producerCount(0),+ initialBlockPoolIndex(0),+ nextExplicitConsumerId(0),+ globalExplicitConsumerOffset(0)+ {+ size_t blocks = (((minCapacity + BLOCK_SIZE - 1) / BLOCK_SIZE) - 1) * (maxExplicitProducers + 1) + 2 * (maxExplicitProducers);+ populate_initial_block_list(blocks);+ }++ // Note: The queue should not be accessed concurrently while it's+ // being deleted. It's up to the user to synchronize this.+ // This method is not thread safe.+ ~ConcurrentQueue()+ {+ // Destroy producers+ auto ptr = producerListTail.load(std::memory_order_relaxed);+ while (ptr != nullptr) {+ auto next = ptr->next_prod();+ if (ptr->token != nullptr) {+ ptr->token->producer = nullptr;+ }+ destroy(ptr);+ ptr = next;+ }++ // Destroy global free list+ auto block = freeList.head_unsafe();+ while (block != nullptr) {+ auto next = block->freeListNext.load(std::memory_order_relaxed);+ if (block->dynamicallyAllocated) {+ destroy(block);+ }+ block = next;+ }++ // Destroy initial free list+ destroy_array(initialBlockPool, initialBlockPoolSize);+ }++ // Disable copying and copy assignment+ ConcurrentQueue(ConcurrentQueue const&) = delete;+ ConcurrentQueue(ConcurrentQueue&& other) = delete;+ ConcurrentQueue& operator=(ConcurrentQueue const&) = delete;+ ConcurrentQueue& operator=(ConcurrentQueue&& other) = delete;++public:+ tracy_force_inline T* enqueue_begin(producer_token_t const& token, index_t& currentTailIndex)+ {+ return static_cast<ExplicitProducer*>(token.producer)->ConcurrentQueue::ExplicitProducer::enqueue_begin(currentTailIndex);+ }++ template<class NotifyThread, class ProcessData>+ size_t try_dequeue_bulk_single(consumer_token_t& token, NotifyThread notifyThread, ProcessData processData )+ {+ if (token.desiredProducer == nullptr || token.lastKnownGlobalOffset != globalExplicitConsumerOffset.load(std::memory_order_relaxed)) {+ if (!update_current_producer_after_rotation(token)) {+ return 0;+ }+ }++ size_t count = static_cast<ProducerBase*>(token.currentProducer)->dequeue_bulk(notifyThread, processData);+ token.itemsConsumedFromCurrent += static_cast<std::uint32_t>(count);++ auto tail = producerListTail.load(std::memory_order_acquire);+ auto ptr = static_cast<ProducerBase*>(token.currentProducer)->next_prod();+ if (ptr == nullptr) {+ ptr = tail;+ }+ if( count == 0 )+ {+ while (ptr != static_cast<ProducerBase*>(token.currentProducer)) {+ auto dequeued = ptr->dequeue_bulk(notifyThread, processData);+ if (dequeued != 0) {+ token.currentProducer = ptr;+ token.itemsConsumedFromCurrent = static_cast<std::uint32_t>(dequeued);+ return dequeued;+ }+ ptr = ptr->next_prod();+ if (ptr == nullptr) {+ ptr = tail;+ }+ }+ return 0;+ }+ else+ {+ token.currentProducer = ptr;+ token.itemsConsumedFromCurrent = 0;+ return count;+ }+ }+++ // Returns an estimate of the total number of elements currently in the queue. This+ // estimate is only accurate if the queue has completely stabilized before it is called+ // (i.e. all enqueue and dequeue operations have completed and their memory effects are+ // visible on the calling thread, and no further operations start while this method is+ // being called).+ // Thread-safe.+ size_t size_approx() const+ {+ size_t size = 0;+ for (auto ptr = producerListTail.load(std::memory_order_acquire); ptr != nullptr; ptr = ptr->next_prod()) {+ size += ptr->size_approx();+ }+ return size;+ }+++ // Returns true if the underlying atomic variables used by+ // the queue are lock-free (they should be on most platforms).+ // Thread-safe.+ static bool is_lock_free()+ {+ return+ details::static_is_lock_free<bool>::value == 2 &&+ details::static_is_lock_free<size_t>::value == 2 &&+ details::static_is_lock_free<std::uint32_t>::value == 2 &&+ details::static_is_lock_free<index_t>::value == 2 &&+ details::static_is_lock_free<void*>::value == 2;+ }+++private:+ friend struct ProducerToken;+ friend struct ConsumerToken;+ friend struct ExplicitProducer;+++ ///////////////////////////////+ // Queue methods+ ///////////////////////////////++ inline bool update_current_producer_after_rotation(consumer_token_t& token)+ {+ // Ah, there's been a rotation, figure out where we should be!+ auto tail = producerListTail.load(std::memory_order_acquire);+ if (token.desiredProducer == nullptr && tail == nullptr) {+ return false;+ }+ auto prodCount = producerCount.load(std::memory_order_relaxed);+ auto globalOffset = globalExplicitConsumerOffset.load(std::memory_order_relaxed);+ if (details::cqUnlikely(token.desiredProducer == nullptr)) {+ // Aha, first time we're dequeueing anything.+ // Figure out our local position+ // Note: offset is from start, not end, but we're traversing from end -- subtract from count first+ std::uint32_t offset = prodCount - 1 - (token.initialOffset % prodCount);+ token.desiredProducer = tail;+ for (std::uint32_t i = 0; i != offset; ++i) {+ token.desiredProducer = static_cast<ProducerBase*>(token.desiredProducer)->next_prod();+ if (token.desiredProducer == nullptr) {+ token.desiredProducer = tail;+ }+ }+ }++ std::uint32_t delta = globalOffset - token.lastKnownGlobalOffset;+ if (delta >= prodCount) {+ delta = delta % prodCount;+ }+ for (std::uint32_t i = 0; i != delta; ++i) {+ token.desiredProducer = static_cast<ProducerBase*>(token.desiredProducer)->next_prod();+ if (token.desiredProducer == nullptr) {+ token.desiredProducer = tail;+ }+ }++ token.lastKnownGlobalOffset = globalOffset;+ token.currentProducer = token.desiredProducer;+ token.itemsConsumedFromCurrent = 0;+ return true;+ }+++ ///////////////////////////+ // Free list+ ///////////////////////////++ template <typename N>+ struct FreeListNode+ {+ FreeListNode() : freeListRefs(0), freeListNext(nullptr) { }++ std::atomic<std::uint32_t> freeListRefs;+ std::atomic<N*> freeListNext;+ };++ // A simple CAS-based lock-free free list. Not the fastest thing in the world under heavy contention, but+ // simple and correct (assuming nodes are never freed until after the free list is destroyed), and fairly+ // speedy under low contention.+ template<typename N> // N must inherit FreeListNode or have the same fields (and initialization of them)+ struct FreeList+ {+ FreeList() : freeListHead(nullptr) { }+ FreeList(FreeList&& other) : freeListHead(other.freeListHead.load(std::memory_order_relaxed)) { other.freeListHead.store(nullptr, std::memory_order_relaxed); }+ void swap(FreeList& other) { details::swap_relaxed(freeListHead, other.freeListHead); }++ FreeList(FreeList const&) = delete;+ FreeList& operator=(FreeList const&) = delete;++ inline void add(N* node)+ {+ // We know that the should-be-on-freelist bit is 0 at this point, so it's safe to+ // set it using a fetch_add+ if (node->freeListRefs.fetch_add(SHOULD_BE_ON_FREELIST, std::memory_order_acq_rel) == 0) {+ // Oh look! We were the last ones referencing this node, and we know+ // we want to add it to the free list, so let's do it!+ add_knowing_refcount_is_zero(node);+ }+ }++ inline N* try_get()+ {+ auto head = freeListHead.load(std::memory_order_acquire);+ while (head != nullptr) {+ auto prevHead = head;+ auto refs = head->freeListRefs.load(std::memory_order_relaxed);+ if ((refs & REFS_MASK) == 0 || !head->freeListRefs.compare_exchange_strong(refs, refs + 1, std::memory_order_acquire, std::memory_order_relaxed)) {+ head = freeListHead.load(std::memory_order_acquire);+ continue;+ }++ // Good, reference count has been incremented (it wasn't at zero), which means we can read the+ // next and not worry about it changing between now and the time we do the CAS+ auto next = head->freeListNext.load(std::memory_order_relaxed);+ if (freeListHead.compare_exchange_strong(head, next, std::memory_order_acquire, std::memory_order_relaxed)) {+ // Yay, got the node. This means it was on the list, which means shouldBeOnFreeList must be false no+ // matter the refcount (because nobody else knows it's been taken off yet, it can't have been put back on).+ assert((head->freeListRefs.load(std::memory_order_relaxed) & SHOULD_BE_ON_FREELIST) == 0);++ // Decrease refcount twice, once for our ref, and once for the list's ref+ head->freeListRefs.fetch_sub(2, std::memory_order_release);+ return head;+ }++ // OK, the head must have changed on us, but we still need to decrease the refcount we increased.+ // Note that we don't need to release any memory effects, but we do need to ensure that the reference+ // count decrement happens-after the CAS on the head.+ refs = prevHead->freeListRefs.fetch_sub(1, std::memory_order_acq_rel);+ if (refs == SHOULD_BE_ON_FREELIST + 1) {+ add_knowing_refcount_is_zero(prevHead);+ }+ }++ return nullptr;+ }++ // Useful for traversing the list when there's no contention (e.g. to destroy remaining nodes)+ N* head_unsafe() const { return freeListHead.load(std::memory_order_relaxed); }++ private:+ inline void add_knowing_refcount_is_zero(N* node)+ {+ // Since the refcount is zero, and nobody can increase it once it's zero (except us, and we run+ // only one copy of this method per node at a time, i.e. the single thread case), then we know+ // we can safely change the next pointer of the node; however, once the refcount is back above+ // zero, then other threads could increase it (happens under heavy contention, when the refcount+ // goes to zero in between a load and a refcount increment of a node in try_get, then back up to+ // something non-zero, then the refcount increment is done by the other thread) -- so, if the CAS+ // to add the node to the actual list fails, decrease the refcount and leave the add operation to+ // the next thread who puts the refcount back at zero (which could be us, hence the loop).+ auto head = freeListHead.load(std::memory_order_relaxed);+ while (true) {+ node->freeListNext.store(head, std::memory_order_relaxed);+ node->freeListRefs.store(1, std::memory_order_release);+ if (!freeListHead.compare_exchange_strong(head, node, std::memory_order_release, std::memory_order_relaxed)) {+ // Hmm, the add failed, but we can only try again when the refcount goes back to zero+ if (node->freeListRefs.fetch_add(SHOULD_BE_ON_FREELIST - 1, std::memory_order_release) == 1) {+ continue;+ }+ }+ return;+ }+ }++ private:+ // Implemented like a stack, but where node order doesn't matter (nodes are inserted out of order under contention)+ std::atomic<N*> freeListHead;++ static const std::uint32_t REFS_MASK = 0x7FFFFFFF;+ static const std::uint32_t SHOULD_BE_ON_FREELIST = 0x80000000;+ };+++ ///////////////////////////+ // Block+ ///////////////////////////++ struct Block+ {+ Block()+ : next(nullptr), elementsCompletelyDequeued(0), freeListRefs(0), freeListNext(nullptr), shouldBeOnFreeList(false), dynamicallyAllocated(true)+ {+ }++ inline bool is_empty() const+ {+ if (compile_time_condition<BLOCK_SIZE <= EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD>::value) {+ // Check flags+ for (size_t i = 0; i < BLOCK_SIZE; ++i) {+ if (!emptyFlags[i].load(std::memory_order_relaxed)) {+ return false;+ }+ }++ // Aha, empty; make sure we have all other memory effects that happened before the empty flags were set+ std::atomic_thread_fence(std::memory_order_acquire);+ return true;+ }+ else {+ // Check counter+ if (elementsCompletelyDequeued.load(std::memory_order_relaxed) == BLOCK_SIZE) {+ std::atomic_thread_fence(std::memory_order_acquire);+ return true;+ }+ assert(elementsCompletelyDequeued.load(std::memory_order_relaxed) <= BLOCK_SIZE);+ return false;+ }+ }++ // Returns true if the block is now empty (does not apply in explicit context)+ inline bool set_empty(index_t i)+ {+ if (BLOCK_SIZE <= EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD) {+ // Set flag+ assert(!emptyFlags[BLOCK_SIZE - 1 - static_cast<size_t>(i & static_cast<index_t>(BLOCK_SIZE - 1))].load(std::memory_order_relaxed));+ emptyFlags[BLOCK_SIZE - 1 - static_cast<size_t>(i & static_cast<index_t>(BLOCK_SIZE - 1))].store(true, std::memory_order_release);+ return false;+ }+ else {+ // Increment counter+ auto prevVal = elementsCompletelyDequeued.fetch_add(1, std::memory_order_release);+ assert(prevVal < BLOCK_SIZE);+ return prevVal == BLOCK_SIZE - 1;+ }+ }++ // Sets multiple contiguous item statuses to 'empty' (assumes no wrapping and count > 0).+ // Returns true if the block is now empty (does not apply in explicit context).+ inline bool set_many_empty(index_t i, size_t count)+ {+ if (compile_time_condition<BLOCK_SIZE <= EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD>::value) {+ // Set flags+ std::atomic_thread_fence(std::memory_order_release);+ i = BLOCK_SIZE - 1 - static_cast<size_t>(i & static_cast<index_t>(BLOCK_SIZE - 1)) - count + 1;+ for (size_t j = 0; j != count; ++j) {+ assert(!emptyFlags[i + j].load(std::memory_order_relaxed));+ emptyFlags[i + j].store(true, std::memory_order_relaxed);+ }+ return false;+ }+ else {+ // Increment counter+ auto prevVal = elementsCompletelyDequeued.fetch_add(count, std::memory_order_release);+ assert(prevVal + count <= BLOCK_SIZE);+ return prevVal + count == BLOCK_SIZE;+ }+ }++ inline void set_all_empty()+ {+ if (BLOCK_SIZE <= EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD) {+ // Set all flags+ for (size_t i = 0; i != BLOCK_SIZE; ++i) {+ emptyFlags[i].store(true, std::memory_order_relaxed);+ }+ }+ else {+ // Reset counter+ elementsCompletelyDequeued.store(BLOCK_SIZE, std::memory_order_relaxed);+ }+ }++ inline void reset_empty()+ {+ if (compile_time_condition<BLOCK_SIZE <= EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD>::value) {+ // Reset flags+ for (size_t i = 0; i != BLOCK_SIZE; ++i) {+ emptyFlags[i].store(false, std::memory_order_relaxed);+ }+ }+ else {+ // Reset counter+ elementsCompletelyDequeued.store(0, std::memory_order_relaxed);+ }+ }++ inline T* operator[](index_t idx) noexcept { return static_cast<T*>(static_cast<void*>(elements)) + static_cast<size_t>(idx & static_cast<index_t>(BLOCK_SIZE - 1)); }+ inline T const* operator[](index_t idx) const noexcept { return static_cast<T const*>(static_cast<void const*>(elements)) + static_cast<size_t>(idx & static_cast<index_t>(BLOCK_SIZE - 1)); }++ private:+ // IMPORTANT: This must be the first member in Block, so that if T depends on the alignment of+ // addresses returned by malloc, that alignment will be preserved. Apparently clang actually+ // generates code that uses this assumption for AVX instructions in some cases. Ideally, we+ // should also align Block to the alignment of T in case it's higher than malloc's 16-byte+ // alignment, but this is hard to do in a cross-platform way. Assert for this case:+ static_assert(std::alignment_of<T>::value <= std::alignment_of<details::max_align_t>::value, "The queue does not support super-aligned types at this time");+ // Additionally, we need the alignment of Block itself to be a multiple of max_align_t since+ // otherwise the appropriate padding will not be added at the end of Block in order to make+ // arrays of Blocks all be properly aligned (not just the first one). We use a union to force+ // this.+ union {+ char elements[sizeof(T) * BLOCK_SIZE];+ details::max_align_t dummy;+ };+ public:+ Block* next;+ std::atomic<size_t> elementsCompletelyDequeued;+ std::atomic<bool> emptyFlags[BLOCK_SIZE <= EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD ? BLOCK_SIZE : 1];+ public:+ std::atomic<std::uint32_t> freeListRefs;+ std::atomic<Block*> freeListNext;+ std::atomic<bool> shouldBeOnFreeList;+ bool dynamicallyAllocated; // Perhaps a better name for this would be 'isNotPartOfInitialBlockPool'+ };+ static_assert(std::alignment_of<Block>::value >= std::alignment_of<details::max_align_t>::value, "Internal error: Blocks must be at least as aligned as the type they are wrapping");+++ ///////////////////////////+ // Producer base+ ///////////////////////////++ struct ProducerBase : public details::ConcurrentQueueProducerTypelessBase+ {+ ProducerBase(ConcurrentQueue* parent_) :+ tailIndex(0),+ headIndex(0),+ dequeueOptimisticCount(0),+ dequeueOvercommit(0),+ tailBlock(nullptr),+ parent(parent_)+ {+ }++ virtual ~ProducerBase() { };++ template<class NotifyThread, class ProcessData>+ inline size_t dequeue_bulk(NotifyThread notifyThread, ProcessData processData)+ {+ return static_cast<ExplicitProducer*>(this)->dequeue_bulk(notifyThread, processData);+ }++ inline ProducerBase* next_prod() const { return static_cast<ProducerBase*>(next); }++ inline size_t size_approx() const+ {+ auto tail = tailIndex.load(std::memory_order_relaxed);+ auto head = headIndex.load(std::memory_order_relaxed);+ return details::circular_less_than(head, tail) ? static_cast<size_t>(tail - head) : 0;+ }++ inline index_t getTail() const { return tailIndex.load(std::memory_order_relaxed); }+ protected:+ std::atomic<index_t> tailIndex; // Where to enqueue to next+ std::atomic<index_t> headIndex; // Where to dequeue from next++ std::atomic<index_t> dequeueOptimisticCount;+ std::atomic<index_t> dequeueOvercommit;++ Block* tailBlock;++ public:+ ConcurrentQueue* parent;+ };+++ public:+ ///////////////////////////+ // Explicit queue+ ///////////////////////////+ struct ExplicitProducer : public ProducerBase+ {+ explicit ExplicitProducer(ConcurrentQueue* _parent) :+ ProducerBase(_parent),+ blockIndex(nullptr),+ pr_blockIndexSlotsUsed(0),+ pr_blockIndexSize(EXPLICIT_INITIAL_INDEX_SIZE >> 1),+ pr_blockIndexFront(0),+ pr_blockIndexEntries(nullptr),+ pr_blockIndexRaw(nullptr)+ {+ size_t poolBasedIndexSize = details::ceil_to_pow_2(_parent->initialBlockPoolSize) >> 1;+ if (poolBasedIndexSize > pr_blockIndexSize) {+ pr_blockIndexSize = poolBasedIndexSize;+ }++ new_block_index(0); // This creates an index with double the number of current entries, i.e. EXPLICIT_INITIAL_INDEX_SIZE+ }++ ~ExplicitProducer()+ {+ // Destruct any elements not yet dequeued.+ // Since we're in the destructor, we can assume all elements+ // are either completely dequeued or completely not (no halfways).+ if (this->tailBlock != nullptr) { // Note this means there must be a block index too+ // First find the block that's partially dequeued, if any+ Block* halfDequeuedBlock = nullptr;+ if ((this->headIndex.load(std::memory_order_relaxed) & static_cast<index_t>(BLOCK_SIZE - 1)) != 0) {+ // The head's not on a block boundary, meaning a block somewhere is partially dequeued+ // (or the head block is the tail block and was fully dequeued, but the head/tail are still not on a boundary)+ size_t i = (pr_blockIndexFront - pr_blockIndexSlotsUsed) & (pr_blockIndexSize - 1);+ while (details::circular_less_than<index_t>(pr_blockIndexEntries[i].base + BLOCK_SIZE, this->headIndex.load(std::memory_order_relaxed))) {+ i = (i + 1) & (pr_blockIndexSize - 1);+ }+ assert(details::circular_less_than<index_t>(pr_blockIndexEntries[i].base, this->headIndex.load(std::memory_order_relaxed)));+ halfDequeuedBlock = pr_blockIndexEntries[i].block;+ }++ // Start at the head block (note the first line in the loop gives us the head from the tail on the first iteration)+ auto block = this->tailBlock;+ do {+ block = block->next;+ if (block->ConcurrentQueue::Block::is_empty()) {+ continue;+ }++ size_t i = 0; // Offset into block+ if (block == halfDequeuedBlock) {+ i = static_cast<size_t>(this->headIndex.load(std::memory_order_relaxed) & static_cast<index_t>(BLOCK_SIZE - 1));+ }++ // Walk through all the items in the block; if this is the tail block, we need to stop when we reach the tail index+ auto lastValidIndex = (this->tailIndex.load(std::memory_order_relaxed) & static_cast<index_t>(BLOCK_SIZE - 1)) == 0 ? BLOCK_SIZE : static_cast<size_t>(this->tailIndex.load(std::memory_order_relaxed) & static_cast<index_t>(BLOCK_SIZE - 1));+ while (i != BLOCK_SIZE && (block != this->tailBlock || i != lastValidIndex)) {+ (*block)[i++]->~T();+ }+ } while (block != this->tailBlock);+ }++ // Destroy all blocks that we own+ if (this->tailBlock != nullptr) {+ auto block = this->tailBlock;+ do {+ auto nextBlock = block->next;+ if (block->dynamicallyAllocated) {+ destroy(block);+ }+ else {+ this->parent->add_block_to_free_list(block);+ }+ block = nextBlock;+ } while (block != this->tailBlock);+ }++ // Destroy the block indices+ auto header = static_cast<BlockIndexHeader*>(pr_blockIndexRaw);+ while (header != nullptr) {+ auto prev = static_cast<BlockIndexHeader*>(header->prev);+ header->~BlockIndexHeader();+ (Traits::free)(header);+ header = prev;+ }+ }++ inline void enqueue_begin_alloc(index_t currentTailIndex)+ {+ // We reached the end of a block, start a new one+ if (this->tailBlock != nullptr && this->tailBlock->next->ConcurrentQueue::Block::is_empty()) {+ // We can re-use the block ahead of us, it's empty!+ this->tailBlock = this->tailBlock->next;+ this->tailBlock->ConcurrentQueue::Block::reset_empty();++ // We'll put the block on the block index (guaranteed to be room since we're conceptually removing the+ // last block from it first -- except instead of removing then adding, we can just overwrite).+ // Note that there must be a valid block index here, since even if allocation failed in the ctor,+ // it would have been re-attempted when adding the first block to the queue; since there is such+ // a block, a block index must have been successfully allocated.+ }+ else {+ // We're going to need a new block; check that the block index has room+ if (pr_blockIndexRaw == nullptr || pr_blockIndexSlotsUsed == pr_blockIndexSize) {+ // Hmm, the circular block index is already full -- we'll need+ // to allocate a new index. Note pr_blockIndexRaw can only be nullptr if+ // the initial allocation failed in the constructor.+ new_block_index(pr_blockIndexSlotsUsed);+ }++ // Insert a new block in the circular linked list+ auto newBlock = this->parent->ConcurrentQueue::requisition_block();+ newBlock->ConcurrentQueue::Block::reset_empty();+ if (this->tailBlock == nullptr) {+ newBlock->next = newBlock;+ }+ else {+ newBlock->next = this->tailBlock->next;+ this->tailBlock->next = newBlock;+ }+ this->tailBlock = newBlock;+ ++pr_blockIndexSlotsUsed;+ }++ // Add block to block index+ auto& entry = blockIndex.load(std::memory_order_relaxed)->entries[pr_blockIndexFront];+ entry.base = currentTailIndex;+ entry.block = this->tailBlock;+ blockIndex.load(std::memory_order_relaxed)->front.store(pr_blockIndexFront, std::memory_order_release);+ pr_blockIndexFront = (pr_blockIndexFront + 1) & (pr_blockIndexSize - 1);+ }++ tracy_force_inline T* enqueue_begin(index_t& currentTailIndex)+ {+ currentTailIndex = this->tailIndex.load(std::memory_order_relaxed);+ if (details::cqUnlikely((currentTailIndex & static_cast<index_t>(BLOCK_SIZE - 1)) == 0)) {+ this->enqueue_begin_alloc(currentTailIndex);+ }+ return (*this->tailBlock)[currentTailIndex];+ }++ tracy_force_inline std::atomic<index_t>& get_tail_index()+ {+ return this->tailIndex;+ }++ template<class NotifyThread, class ProcessData>+ size_t dequeue_bulk(NotifyThread notifyThread, ProcessData processData)+ {+ auto tail = this->tailIndex.load(std::memory_order_relaxed);+ auto overcommit = this->dequeueOvercommit.load(std::memory_order_relaxed);+ auto desiredCount = static_cast<size_t>(tail - (this->dequeueOptimisticCount.load(std::memory_order_relaxed) - overcommit));+ if (details::circular_less_than<size_t>(0, desiredCount)) {+ desiredCount = desiredCount < 8192 ? desiredCount : 8192;+ std::atomic_thread_fence(std::memory_order_acquire);++ auto myDequeueCount = this->dequeueOptimisticCount.fetch_add(desiredCount, std::memory_order_relaxed);+ assert(overcommit <= myDequeueCount);++ tail = this->tailIndex.load(std::memory_order_acquire);+ auto actualCount = static_cast<size_t>(tail - (myDequeueCount - overcommit));+ if (details::circular_less_than<size_t>(0, actualCount)) {+ actualCount = desiredCount < actualCount ? desiredCount : actualCount;+ if (actualCount < desiredCount) {+ this->dequeueOvercommit.fetch_add(desiredCount - actualCount, std::memory_order_release);+ }++ // Get the first index. Note that since there's guaranteed to be at least actualCount elements, this+ // will never exceed tail.+ auto firstIndex = this->headIndex.fetch_add(actualCount, std::memory_order_acq_rel);++ // Determine which block the first element is in+ auto localBlockIndex = blockIndex.load(std::memory_order_acquire);+ auto localBlockIndexHead = localBlockIndex->front.load(std::memory_order_acquire);++ auto headBase = localBlockIndex->entries[localBlockIndexHead].base;+ auto firstBlockBaseIndex = firstIndex & ~static_cast<index_t>(BLOCK_SIZE - 1);+ auto offset = static_cast<size_t>(static_cast<typename std::make_signed<index_t>::type>(firstBlockBaseIndex - headBase) / BLOCK_SIZE);+ auto indexIndex = (localBlockIndexHead + offset) & (localBlockIndex->size - 1);++ notifyThread( this->threadId );++ // Iterate the blocks and dequeue+ auto index = firstIndex;+ do {+ auto firstIndexInBlock = index;+ auto endIndex = (index & ~static_cast<index_t>(BLOCK_SIZE - 1)) + static_cast<index_t>(BLOCK_SIZE);+ endIndex = details::circular_less_than<index_t>(firstIndex + static_cast<index_t>(actualCount), endIndex) ? firstIndex + static_cast<index_t>(actualCount) : endIndex;+ auto block = localBlockIndex->entries[indexIndex].block;++ const auto sz = endIndex - index;+ processData( (*block)[index], sz );+ index += sz;++ block->ConcurrentQueue::Block::set_many_empty(firstIndexInBlock, static_cast<size_t>(endIndex - firstIndexInBlock));+ indexIndex = (indexIndex + 1) & (localBlockIndex->size - 1);+ } while (index != firstIndex + actualCount);++ return actualCount;+ }+ else {+ // Wasn't anything to dequeue after all; make the effective dequeue count eventually consistent+ this->dequeueOvercommit.fetch_add(desiredCount, std::memory_order_release);+ }+ }++ return 0;+ }++ private:+ struct BlockIndexEntry+ {+ index_t base;+ Block* block;+ };++ struct BlockIndexHeader+ {+ size_t size;+ std::atomic<size_t> front; // Current slot (not next, like pr_blockIndexFront)+ BlockIndexEntry* entries;+ void* prev;+ };+++ bool new_block_index(size_t numberOfFilledSlotsToExpose)+ {+ auto prevBlockSizeMask = pr_blockIndexSize - 1;++ // Create the new block+ pr_blockIndexSize <<= 1;+ auto newRawPtr = static_cast<char*>((Traits::malloc)(sizeof(BlockIndexHeader) + std::alignment_of<BlockIndexEntry>::value - 1 + sizeof(BlockIndexEntry) * pr_blockIndexSize));+ if (newRawPtr == nullptr) {+ pr_blockIndexSize >>= 1; // Reset to allow graceful retry+ return false;+ }++ auto newBlockIndexEntries = reinterpret_cast<BlockIndexEntry*>(details::align_for<BlockIndexEntry>(newRawPtr + sizeof(BlockIndexHeader)));++ // Copy in all the old indices, if any+ size_t j = 0;+ if (pr_blockIndexSlotsUsed != 0) {+ auto i = (pr_blockIndexFront - pr_blockIndexSlotsUsed) & prevBlockSizeMask;+ do {+ newBlockIndexEntries[j++] = pr_blockIndexEntries[i];+ i = (i + 1) & prevBlockSizeMask;+ } while (i != pr_blockIndexFront);+ }++ // Update everything+ auto header = new (newRawPtr) BlockIndexHeader;+ header->size = pr_blockIndexSize;+ header->front.store(numberOfFilledSlotsToExpose - 1, std::memory_order_relaxed);+ header->entries = newBlockIndexEntries;+ header->prev = pr_blockIndexRaw; // we link the new block to the old one so we can free it later++ pr_blockIndexFront = j;+ pr_blockIndexEntries = newBlockIndexEntries;+ pr_blockIndexRaw = newRawPtr;+ blockIndex.store(header, std::memory_order_release);++ return true;+ }++ private:+ std::atomic<BlockIndexHeader*> blockIndex;++ // To be used by producer only -- consumer must use the ones in referenced by blockIndex+ size_t pr_blockIndexSlotsUsed;+ size_t pr_blockIndexSize;+ size_t pr_blockIndexFront; // Next slot (not current)+ BlockIndexEntry* pr_blockIndexEntries;+ void* pr_blockIndexRaw;+ };++ ExplicitProducer* get_explicit_producer(producer_token_t const& token)+ {+ return static_cast<ExplicitProducer*>(token.producer);+ }++ private:++ //////////////////////////////////+ // Block pool manipulation+ //////////////////////////////////++ void populate_initial_block_list(size_t blockCount)+ {+ initialBlockPoolSize = blockCount;+ if (initialBlockPoolSize == 0) {+ initialBlockPool = nullptr;+ return;+ }++ initialBlockPool = create_array<Block>(blockCount);+ if (initialBlockPool == nullptr) {+ initialBlockPoolSize = 0;+ }+ for (size_t i = 0; i < initialBlockPoolSize; ++i) {+ initialBlockPool[i].dynamicallyAllocated = false;+ }+ }++ inline Block* try_get_block_from_initial_pool()+ {+ if (initialBlockPoolIndex.load(std::memory_order_relaxed) >= initialBlockPoolSize) {+ return nullptr;+ }++ auto index = initialBlockPoolIndex.fetch_add(1, std::memory_order_relaxed);++ return index < initialBlockPoolSize ? (initialBlockPool + index) : nullptr;+ }++ inline void add_block_to_free_list(Block* block)+ {+ freeList.add(block);+ }++ inline void add_blocks_to_free_list(Block* block)+ {+ while (block != nullptr) {+ auto next = block->next;+ add_block_to_free_list(block);+ block = next;+ }+ }++ inline Block* try_get_block_from_free_list()+ {+ return freeList.try_get();+ }++ // Gets a free block from one of the memory pools, or allocates a new one (if applicable)+ Block* requisition_block()+ {+ auto block = try_get_block_from_initial_pool();+ if (block != nullptr) {+ return block;+ }++ block = try_get_block_from_free_list();+ if (block != nullptr) {+ return block;+ }++ return create<Block>();+ }+++ //////////////////////////////////+ // Producer list manipulation+ //////////////////////////////////++ ProducerBase* recycle_or_create_producer()+ {+ bool recycled;+ return recycle_or_create_producer(recycled);+ }++ ProducerBase* recycle_or_create_producer(bool& recycled)+ {+ // Try to re-use one first+ for (auto ptr = producerListTail.load(std::memory_order_acquire); ptr != nullptr; ptr = ptr->next_prod()) {+ if (ptr->inactive.load(std::memory_order_relaxed)) {+ if( ptr->size_approx() == 0 )+ {+ bool expected = true;+ if (ptr->inactive.compare_exchange_strong(expected, /* desired */ false, std::memory_order_acquire, std::memory_order_relaxed)) {+ // We caught one! It's been marked as activated, the caller can have it+ recycled = true;+ return ptr;+ }+ }+ }+ }++ recycled = false;+ return add_producer(static_cast<ProducerBase*>(create<ExplicitProducer>(this)));+ }++ ProducerBase* add_producer(ProducerBase* producer)+ {+ // Handle failed memory allocation+ if (producer == nullptr) {+ return nullptr;+ }++ producerCount.fetch_add(1, std::memory_order_relaxed);++ // Add it to the lock-free list+ auto prevTail = producerListTail.load(std::memory_order_relaxed);+ do {+ producer->next = prevTail;+ } while (!producerListTail.compare_exchange_weak(prevTail, producer, std::memory_order_release, std::memory_order_relaxed));++ return producer;+ }++ void reown_producers()+ {+ // After another instance is moved-into/swapped-with this one, all the+ // producers we stole still think their parents are the other queue.+ // So fix them up!+ for (auto ptr = producerListTail.load(std::memory_order_relaxed); ptr != nullptr; ptr = ptr->next_prod()) {+ ptr->parent = this;+ }+ }++ //////////////////////////////////+ // Utility functions+ //////////////////////////////////++ template<typename U>+ static inline U* create_array(size_t count)+ {+ assert(count > 0);+ return static_cast<U*>((Traits::malloc)(sizeof(U) * count));+ }++ template<typename U>+ static inline void destroy_array(U* p, size_t count)+ {+ ((void)count);+ if (p != nullptr) {+ assert(count > 0);+ (Traits::free)(p);+ }+ }++ template<typename U>+ static inline U* create()+ {+ auto p = (Traits::malloc)(sizeof(U));+ return new (p) U;+ }++ template<typename U, typename A1>+ static inline U* create(A1&& a1)+ {+ auto p = (Traits::malloc)(sizeof(U));+ return new (p) U(std::forward<A1>(a1));+ }++ template<typename U>+ static inline void destroy(U* p)+ {+ if (p != nullptr) {+ p->~U();+ }+ (Traits::free)(p);+ }++private:+ std::atomic<ProducerBase*> producerListTail;+ std::atomic<std::uint32_t> producerCount;++ std::atomic<size_t> initialBlockPoolIndex;+ Block* initialBlockPool;+ size_t initialBlockPoolSize;++ FreeList<Block> freeList;++ std::atomic<std::uint32_t> nextExplicitConsumerId;+ std::atomic<std::uint32_t> globalExplicitConsumerOffset;+};+++template<typename T, typename Traits>+ProducerToken::ProducerToken(ConcurrentQueue<T, Traits>& queue)+ : producer(queue.recycle_or_create_producer())+{+ if (producer != nullptr) {+ producer->token = this;+ producer->threadId = detail::GetThreadHandleImpl();+ }+}++template<typename T, typename Traits>+ConsumerToken::ConsumerToken(ConcurrentQueue<T, Traits>& queue)+ : itemsConsumedFromCurrent(0), currentProducer(nullptr), desiredProducer(nullptr)+{+ initialOffset = queue.nextExplicitConsumerId.fetch_add(1, std::memory_order_release);+ lastKnownGlobalOffset = static_cast<std::uint32_t>(-1);+}++template<typename T, typename Traits>+inline void swap(ConcurrentQueue<T, Traits>& a, ConcurrentQueue<T, Traits>& b) noexcept+{+ a.swap(b);+}++inline void swap(ProducerToken& a, ProducerToken& b) noexcept+{+ a.swap(b);+}++inline void swap(ConsumerToken& a, ConsumerToken& b) noexcept+{+ a.swap(b);+}++}++} /* namespace tracy */++#if defined(__GNUC__)+#pragma GCC diagnostic pop+#endif
+ cbits/tracy/public/client/tracy_rpmalloc.cpp view
@@ -0,0 +1,3519 @@+#ifdef TRACY_ENABLE++/* rpmalloc.c - Memory allocator - Public Domain - 2016-2020 Mattias Jansson+ *+ * This library provides a cross-platform lock free thread caching malloc implementation in C11.+ * The latest source code is always available at+ *+ * https://github.com/mjansson/rpmalloc+ *+ * This library is put in the public domain; you can redistribute it and/or modify it without any restrictions.+ *+ */++#include "tracy_rpmalloc.hpp"++#define BUILD_DYNAMIC_LINK 1++////////////+///+/// Build time configurable limits+///+//////++#if defined(__clang__)+#pragma clang diagnostic ignored "-Wunused-macros"+#pragma clang diagnostic ignored "-Wunused-function"+#if __has_warning("-Wreserved-identifier")+#pragma clang diagnostic ignored "-Wreserved-identifier"+#endif+#elif defined(__GNUC__)+#pragma GCC diagnostic ignored "-Wunused-macros"+#pragma GCC diagnostic ignored "-Wunused-function"+#pragma GCC diagnostic ignored "-Warray-bounds"+#endif++#ifndef HEAP_ARRAY_SIZE+//! Size of heap hashmap+#define HEAP_ARRAY_SIZE 47+#endif+#ifndef ENABLE_THREAD_CACHE+//! Enable per-thread cache+#define ENABLE_THREAD_CACHE 1+#endif+#ifndef ENABLE_GLOBAL_CACHE+//! Enable global cache shared between all threads, requires thread cache+#define ENABLE_GLOBAL_CACHE 1+#endif+#ifndef ENABLE_VALIDATE_ARGS+//! Enable validation of args to public entry points+#define ENABLE_VALIDATE_ARGS 0+#endif+#ifndef ENABLE_STATISTICS+//! Enable statistics collection+#define ENABLE_STATISTICS 0+#endif+#ifndef ENABLE_ASSERTS+//! Enable asserts+#define ENABLE_ASSERTS 0+#endif+#ifndef ENABLE_OVERRIDE+//! Override standard library malloc/free and new/delete entry points+#define ENABLE_OVERRIDE 0+#endif+#ifndef ENABLE_PRELOAD+//! Support preloading+#define ENABLE_PRELOAD 0+#endif+#ifndef DISABLE_UNMAP+//! Disable unmapping memory pages (also enables unlimited cache)+#define DISABLE_UNMAP 0+#endif+#ifndef ENABLE_UNLIMITED_CACHE+//! Enable unlimited global cache (no unmapping until finalization)+#define ENABLE_UNLIMITED_CACHE 0+#endif+#ifndef ENABLE_ADAPTIVE_THREAD_CACHE+//! Enable adaptive thread cache size based on use heuristics+#define ENABLE_ADAPTIVE_THREAD_CACHE 0+#endif+#ifndef DEFAULT_SPAN_MAP_COUNT+//! Default number of spans to map in call to map more virtual memory (default values yield 4MiB here)+#define DEFAULT_SPAN_MAP_COUNT 64+#endif+#ifndef GLOBAL_CACHE_MULTIPLIER+//! Multiplier for global cache+#define GLOBAL_CACHE_MULTIPLIER 8+#endif++#if DISABLE_UNMAP && !ENABLE_GLOBAL_CACHE+#error Must use global cache if unmap is disabled+#endif++#if DISABLE_UNMAP+#undef ENABLE_UNLIMITED_CACHE+#define ENABLE_UNLIMITED_CACHE 1+#endif++#if !ENABLE_GLOBAL_CACHE+#undef ENABLE_UNLIMITED_CACHE+#define ENABLE_UNLIMITED_CACHE 0+#endif++#if !ENABLE_THREAD_CACHE+#undef ENABLE_ADAPTIVE_THREAD_CACHE+#define ENABLE_ADAPTIVE_THREAD_CACHE 0+#endif++#if defined(_WIN32) || defined(__WIN32__) || defined(_WIN64)+# define PLATFORM_WINDOWS 1+# define PLATFORM_POSIX 0+#else+# define PLATFORM_WINDOWS 0+# define PLATFORM_POSIX 1+#endif++/// Platform and arch specifics+#if defined(_MSC_VER) && !defined(__clang__)+# pragma warning (disable: 5105)+# ifndef FORCEINLINE+# define FORCEINLINE inline __forceinline+# endif+#else+# ifndef FORCEINLINE+# define FORCEINLINE inline __attribute__((__always_inline__))+# endif+#endif+#if PLATFORM_WINDOWS+# ifndef WIN32_LEAN_AND_MEAN+# define WIN32_LEAN_AND_MEAN+# endif+# include <windows.h>+# if ENABLE_VALIDATE_ARGS+# include <intsafe.h>+# endif+#else+# include <unistd.h>+# include <stdio.h>+# include <stdlib.h>+# include <time.h>+# if defined(__linux__) || defined(__ANDROID__)+# include <sys/prctl.h>+# if !defined(PR_SET_VMA)+# define PR_SET_VMA 0x53564d41+# define PR_SET_VMA_ANON_NAME 0+# endif+# endif+# if defined(__APPLE__)+# include <TargetConditionals.h>+# if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR+# include <mach/mach.h>+# include <mach/vm_statistics.h>+# endif+# include <pthread.h>+# endif+# if defined(__HAIKU__) || defined(__TINYC__)+# include <pthread.h>+# endif+#endif++#include <stdint.h>+#include <string.h>+#include <errno.h>++#if defined(_WIN32) && (!defined(BUILD_DYNAMIC_LINK) || !BUILD_DYNAMIC_LINK)+#include <fibersapi.h>+static DWORD fls_key;+#endif++#if PLATFORM_POSIX+# include <sys/mman.h>+# include <sched.h>+# ifdef __FreeBSD__+# include <sys/sysctl.h>+# define MAP_HUGETLB MAP_ALIGNED_SUPER+# ifndef PROT_MAX+# define PROT_MAX(f) 0+# endif+# else+# define PROT_MAX(f) 0+# endif+# ifdef __sun+extern int madvise(caddr_t, size_t, int);+# endif+# ifndef MAP_UNINITIALIZED+# define MAP_UNINITIALIZED 0+# endif+#endif+#include <errno.h>++#if ENABLE_ASSERTS+# undef NDEBUG+# if defined(_MSC_VER) && !defined(_DEBUG)+# define _DEBUG+# endif+# include <assert.h>+#define RPMALLOC_TOSTRING_M(x) #x+#define RPMALLOC_TOSTRING(x) RPMALLOC_TOSTRING_M(x)+#define rpmalloc_assert(truth, message) \+ do { \+ if (!(truth)) { \+ if (_memory_config.error_callback) { \+ _memory_config.error_callback( \+ message " (" RPMALLOC_TOSTRING(truth) ") at " __FILE__ ":" RPMALLOC_TOSTRING(__LINE__)); \+ } else { \+ assert((truth) && message); \+ } \+ } \+ } while (0)+#else+# define rpmalloc_assert(truth, message) do {} while(0)+#endif+#if ENABLE_STATISTICS+# include <stdio.h>+#endif++//////+///+/// Atomic access abstraction (since MSVC does not do C11 yet)+///+//////++#include <atomic>++typedef std::atomic<int32_t> atomic32_t;+typedef std::atomic<int64_t> atomic64_t;+typedef std::atomic<void*> atomicptr_t;++static FORCEINLINE int32_t atomic_load32(atomic32_t* src) { return std::atomic_load_explicit(src, std::memory_order_relaxed); }+static FORCEINLINE void atomic_store32(atomic32_t* dst, int32_t val) { std::atomic_store_explicit(dst, val, std::memory_order_relaxed); }+static FORCEINLINE int32_t atomic_incr32(atomic32_t* val) { return std::atomic_fetch_add_explicit(val, 1, std::memory_order_relaxed) + 1; }+static FORCEINLINE int32_t atomic_decr32(atomic32_t* val) { return std::atomic_fetch_add_explicit(val, -1, std::memory_order_relaxed) - 1; }+static FORCEINLINE int32_t atomic_add32(atomic32_t* val, int32_t add) { return std::atomic_fetch_add_explicit(val, add, std::memory_order_relaxed) + add; }+static FORCEINLINE int atomic_cas32_acquire(atomic32_t* dst, int32_t val, int32_t ref) { return std::atomic_compare_exchange_weak_explicit(dst, &ref, val, std::memory_order_acquire, std::memory_order_relaxed); }+static FORCEINLINE void atomic_store32_release(atomic32_t* dst, int32_t val) { std::atomic_store_explicit(dst, val, std::memory_order_release); }+static FORCEINLINE int64_t atomic_load64(atomic64_t* val) { return std::atomic_load_explicit(val, std::memory_order_relaxed); }+static FORCEINLINE int64_t atomic_add64(atomic64_t* val, int64_t add) { return std::atomic_fetch_add_explicit(val, add, std::memory_order_relaxed) + add; }+static FORCEINLINE void* atomic_load_ptr(atomicptr_t* src) { return std::atomic_load_explicit(src, std::memory_order_relaxed); }+static FORCEINLINE void atomic_store_ptr(atomicptr_t* dst, void* val) { std::atomic_store_explicit(dst, val, std::memory_order_relaxed); }+static FORCEINLINE void atomic_store_ptr_release(atomicptr_t* dst, void* val) { std::atomic_store_explicit(dst, val, std::memory_order_release); }+static FORCEINLINE void* atomic_exchange_ptr_acquire(atomicptr_t* dst, void* val) { return std::atomic_exchange_explicit(dst, val, std::memory_order_acquire); }+static FORCEINLINE int atomic_cas_ptr(atomicptr_t* dst, void* val, void* ref) { return std::atomic_compare_exchange_weak_explicit(dst, &ref, val, std::memory_order_relaxed, std::memory_order_relaxed); }++#if defined(_MSC_VER) && !defined(__clang__)++#define EXPECTED(x) (x)+#define UNEXPECTED(x) (x)++#else++#define EXPECTED(x) __builtin_expect((x), 1)+#define UNEXPECTED(x) __builtin_expect((x), 0)++#endif++////////////+///+/// Statistics related functions (evaluate to nothing when statistics not enabled)+///+//////++#if ENABLE_STATISTICS+# define _rpmalloc_stat_inc(counter) atomic_incr32(counter)+# define _rpmalloc_stat_dec(counter) atomic_decr32(counter)+# define _rpmalloc_stat_add(counter, value) atomic_add32(counter, (int32_t)(value))+# define _rpmalloc_stat_add64(counter, value) atomic_add64(counter, (int64_t)(value))+# define _rpmalloc_stat_add_peak(counter, value, peak) do { int32_t _cur_count = atomic_add32(counter, (int32_t)(value)); if (_cur_count > (peak)) peak = _cur_count; } while (0)+# define _rpmalloc_stat_sub(counter, value) atomic_add32(counter, -(int32_t)(value))+# define _rpmalloc_stat_inc_alloc(heap, class_idx) do { \+ int32_t alloc_current = atomic_incr32(&heap->size_class_use[class_idx].alloc_current); \+ if (alloc_current > heap->size_class_use[class_idx].alloc_peak) \+ heap->size_class_use[class_idx].alloc_peak = alloc_current; \+ atomic_incr32(&heap->size_class_use[class_idx].alloc_total); \+} while(0)+# define _rpmalloc_stat_inc_free(heap, class_idx) do { \+ atomic_decr32(&heap->size_class_use[class_idx].alloc_current); \+ atomic_incr32(&heap->size_class_use[class_idx].free_total); \+} while(0)+#else+# define _rpmalloc_stat_inc(counter) do {} while(0)+# define _rpmalloc_stat_dec(counter) do {} while(0)+# define _rpmalloc_stat_add(counter, value) do {} while(0)+# define _rpmalloc_stat_add64(counter, value) do {} while(0)+# define _rpmalloc_stat_add_peak(counter, value, peak) do {} while (0)+# define _rpmalloc_stat_sub(counter, value) do {} while(0)+# define _rpmalloc_stat_inc_alloc(heap, class_idx) do {} while(0)+# define _rpmalloc_stat_inc_free(heap, class_idx) do {} while(0)+#endif+++///+/// Preconfigured limits and sizes+///++//! Granularity of a small allocation block (must be power of two)+#define SMALL_GRANULARITY 16+//! Small granularity shift count+#define SMALL_GRANULARITY_SHIFT 4+//! Number of small block size classes+#define SMALL_CLASS_COUNT 65+//! Maximum size of a small block+#define SMALL_SIZE_LIMIT (SMALL_GRANULARITY * (SMALL_CLASS_COUNT - 1))+//! Granularity of a medium allocation block+#define MEDIUM_GRANULARITY 512+//! Medium granularity shift count+#define MEDIUM_GRANULARITY_SHIFT 9+//! Number of medium block size classes+#define MEDIUM_CLASS_COUNT 61+//! Total number of small + medium size classes+#define SIZE_CLASS_COUNT (SMALL_CLASS_COUNT + MEDIUM_CLASS_COUNT)+//! Number of large block size classes+#define LARGE_CLASS_COUNT 63+//! Maximum size of a medium block+#define MEDIUM_SIZE_LIMIT (SMALL_SIZE_LIMIT + (MEDIUM_GRANULARITY * MEDIUM_CLASS_COUNT))+//! Maximum size of a large block+#define LARGE_SIZE_LIMIT ((LARGE_CLASS_COUNT * _memory_span_size) - SPAN_HEADER_SIZE)+//! Size of a span header (must be a multiple of SMALL_GRANULARITY and a power of two)+#define SPAN_HEADER_SIZE 128+//! Number of spans in thread cache+#define MAX_THREAD_SPAN_CACHE 400+//! Number of spans to transfer between thread and global cache+#define THREAD_SPAN_CACHE_TRANSFER 64+//! Number of spans in thread cache for large spans (must be greater than LARGE_CLASS_COUNT / 2)+#define MAX_THREAD_SPAN_LARGE_CACHE 100+//! Number of spans to transfer between thread and global cache for large spans+#define THREAD_SPAN_LARGE_CACHE_TRANSFER 6++static_assert((SMALL_GRANULARITY & (SMALL_GRANULARITY - 1)) == 0, "Small granularity must be power of two");+static_assert((SPAN_HEADER_SIZE & (SPAN_HEADER_SIZE - 1)) == 0, "Span header size must be power of two");++#if ENABLE_VALIDATE_ARGS+//! Maximum allocation size to avoid integer overflow+#undef MAX_ALLOC_SIZE+#define MAX_ALLOC_SIZE (((size_t)-1) - _memory_span_size)+#endif++#define pointer_offset(ptr, ofs) (void*)((char*)(ptr) + (ptrdiff_t)(ofs))+#define pointer_diff(first, second) (ptrdiff_t)((const char*)(first) - (const char*)(second))++#define INVALID_POINTER ((void*)((uintptr_t)-1))++#define SIZE_CLASS_LARGE SIZE_CLASS_COUNT+#define SIZE_CLASS_HUGE ((uint32_t)-1)++////////////+///+/// Data types+///+//////++namespace tracy+{++//! A memory heap, per thread+typedef struct heap_t heap_t;+//! Span of memory pages+typedef struct span_t span_t;+//! Span list+typedef struct span_list_t span_list_t;+//! Span active data+typedef struct span_active_t span_active_t;+//! Size class definition+typedef struct size_class_t size_class_t;+//! Global cache+typedef struct global_cache_t global_cache_t;++//! Flag indicating span is the first (master) span of a split superspan+#define SPAN_FLAG_MASTER 1U+//! Flag indicating span is a secondary (sub) span of a split superspan+#define SPAN_FLAG_SUBSPAN 2U+//! Flag indicating span has blocks with increased alignment+#define SPAN_FLAG_ALIGNED_BLOCKS 4U+//! Flag indicating an unmapped master span+#define SPAN_FLAG_UNMAPPED_MASTER 8U++#if ENABLE_ADAPTIVE_THREAD_CACHE || ENABLE_STATISTICS+struct span_use_t {+ //! Current number of spans used (actually used, not in cache)+ atomic32_t current;+ //! High water mark of spans used+ atomic32_t high;+#if ENABLE_STATISTICS+ //! Number of spans in deferred list+ atomic32_t spans_deferred;+ //! Number of spans transitioned to global cache+ atomic32_t spans_to_global;+ //! Number of spans transitioned from global cache+ atomic32_t spans_from_global;+ //! Number of spans transitioned to thread cache+ atomic32_t spans_to_cache;+ //! Number of spans transitioned from thread cache+ atomic32_t spans_from_cache;+ //! Number of spans transitioned to reserved state+ atomic32_t spans_to_reserved;+ //! Number of spans transitioned from reserved state+ atomic32_t spans_from_reserved;+ //! Number of raw memory map calls+ atomic32_t spans_map_calls;+#endif+};+typedef struct span_use_t span_use_t;+#endif++#if ENABLE_STATISTICS+struct size_class_use_t {+ //! Current number of allocations+ atomic32_t alloc_current;+ //! Peak number of allocations+ int32_t alloc_peak;+ //! Total number of allocations+ atomic32_t alloc_total;+ //! Total number of frees+ atomic32_t free_total;+ //! Number of spans in use+ atomic32_t spans_current;+ //! Number of spans transitioned to cache+ int32_t spans_peak;+ //! Number of spans transitioned to cache+ atomic32_t spans_to_cache;+ //! Number of spans transitioned from cache+ atomic32_t spans_from_cache;+ //! Number of spans transitioned from reserved state+ atomic32_t spans_from_reserved;+ //! Number of spans mapped+ atomic32_t spans_map_calls;+ int32_t unused;+};+typedef struct size_class_use_t size_class_use_t;+#endif++// A span can either represent a single span of memory pages with size declared by span_map_count configuration variable,+// or a set of spans in a continuous region, a super span. Any reference to the term "span" usually refers to both a single+// span or a super span. A super span can further be divided into multiple spans (or this, super spans), where the first+// (super)span is the master and subsequent (super)spans are subspans. The master span keeps track of how many subspans+// that are still alive and mapped in virtual memory, and once all subspans and master have been unmapped the entire+// superspan region is released and unmapped (on Windows for example, the entire superspan range has to be released+// in the same call to release the virtual memory range, but individual subranges can be decommitted individually+// to reduce physical memory use).+struct span_t {+ //! Free list+ void* free_list;+ //! Total block count of size class+ uint32_t block_count;+ //! Size class+ uint32_t size_class;+ //! Index of last block initialized in free list+ uint32_t free_list_limit;+ //! Number of used blocks remaining when in partial state+ uint32_t used_count;+ //! Deferred free list+ atomicptr_t free_list_deferred;+ //! Size of deferred free list, or list of spans when part of a cache list+ uint32_t list_size;+ //! Size of a block+ uint32_t block_size;+ //! Flags and counters+ uint32_t flags;+ //! Number of spans+ uint32_t span_count;+ //! Total span counter for master spans+ uint32_t total_spans;+ //! Offset from master span for subspans+ uint32_t offset_from_master;+ //! Remaining span counter, for master spans+ atomic32_t remaining_spans;+ //! Alignment offset+ uint32_t align_offset;+ //! Owning heap+ heap_t* heap;+ //! Next span+ span_t* next;+ //! Previous span+ span_t* prev;+};+static_assert(sizeof(span_t) <= SPAN_HEADER_SIZE, "span size mismatch");++struct span_cache_t {+ size_t count;+ span_t* span[MAX_THREAD_SPAN_CACHE];+};+typedef struct span_cache_t span_cache_t;++struct span_large_cache_t {+ size_t count;+ span_t* span[MAX_THREAD_SPAN_LARGE_CACHE];+};+typedef struct span_large_cache_t span_large_cache_t;++struct heap_size_class_t {+ //! Free list of active span+ void* free_list;+ //! Double linked list of partially used spans with free blocks.+ // Previous span pointer in head points to tail span of list.+ span_t* partial_span;+ //! Early level cache of fully free spans+ span_t* cache;+};+typedef struct heap_size_class_t heap_size_class_t;++// Control structure for a heap, either a thread heap or a first class heap if enabled+struct heap_t {+ //! Owning thread ID+ uintptr_t owner_thread;+ //! Free lists for each size class+ heap_size_class_t size_class[SIZE_CLASS_COUNT];+#if ENABLE_THREAD_CACHE+ //! Arrays of fully freed spans, single span+ span_cache_t span_cache;+#endif+ //! List of deferred free spans (single linked list)+ atomicptr_t span_free_deferred;+ //! Number of full spans+ size_t full_span_count;+ //! Mapped but unused spans+ span_t* span_reserve;+ //! Master span for mapped but unused spans+ span_t* span_reserve_master;+ //! Number of mapped but unused spans+ uint32_t spans_reserved;+ //! Child count+ atomic32_t child_count;+ //! Next heap in id list+ heap_t* next_heap;+ //! Next heap in orphan list+ heap_t* next_orphan;+ //! Heap ID+ int32_t id;+ //! Finalization state flag+ int finalize;+ //! Master heap owning the memory pages+ heap_t* master_heap;+#if ENABLE_THREAD_CACHE+ //! Arrays of fully freed spans, large spans with > 1 span count+ span_large_cache_t span_large_cache[LARGE_CLASS_COUNT - 1];+#endif+#if RPMALLOC_FIRST_CLASS_HEAPS+ //! Double linked list of fully utilized spans with free blocks for each size class.+ // Previous span pointer in head points to tail span of list.+ span_t* full_span[SIZE_CLASS_COUNT];+ //! Double linked list of large and huge spans allocated by this heap+ span_t* large_huge_span;+#endif+#if ENABLE_ADAPTIVE_THREAD_CACHE || ENABLE_STATISTICS+ //! Current and high water mark of spans used per span count+ span_use_t span_use[LARGE_CLASS_COUNT];+#endif+#if ENABLE_STATISTICS+ //! Allocation stats per size class+ size_class_use_t size_class_use[SIZE_CLASS_COUNT + 1];+ //! Number of bytes transitioned thread -> global+ atomic64_t thread_to_global;+ //! Number of bytes transitioned global -> thread+ atomic64_t global_to_thread;+#endif+};++// Size class for defining a block size bucket+struct size_class_t {+ //! Size of blocks in this class+ uint32_t block_size;+ //! Number of blocks in each chunk+ uint16_t block_count;+ //! Class index this class is merged with+ uint16_t class_idx;+};+static_assert(sizeof(size_class_t) == 8, "Size class size mismatch");++struct global_cache_t {+ //! Cache lock+ atomic32_t lock;+ //! Cache count+ uint32_t count;+#if ENABLE_STATISTICS+ //! Insert count+ size_t insert_count;+ //! Extract count+ size_t extract_count;+#endif+ //! Cached spans+ span_t* span[GLOBAL_CACHE_MULTIPLIER * MAX_THREAD_SPAN_CACHE];+ //! Unlimited cache overflow+ span_t* overflow;+};++////////////+///+/// Global data+///+//////++//! Default span size (64KiB)+#define _memory_default_span_size (64 * 1024)+#define _memory_default_span_size_shift 16+#define _memory_default_span_mask (~((uintptr_t)(_memory_span_size - 1)))++//! Initialized flag+static int _rpmalloc_initialized;+//! Main thread ID+static uintptr_t _rpmalloc_main_thread_id;+//! Configuration+static rpmalloc_config_t _memory_config;+//! Memory page size+static size_t _memory_page_size;+//! Shift to divide by page size+static size_t _memory_page_size_shift;+//! Granularity at which memory pages are mapped by OS+static size_t _memory_map_granularity;+#if RPMALLOC_CONFIGURABLE+//! Size of a span of memory pages+static size_t _memory_span_size;+//! Shift to divide by span size+static size_t _memory_span_size_shift;+//! Mask to get to start of a memory span+static uintptr_t _memory_span_mask;+#else+//! Hardwired span size+#define _memory_span_size _memory_default_span_size+#define _memory_span_size_shift _memory_default_span_size_shift+#define _memory_span_mask _memory_default_span_mask+#endif+//! Number of spans to map in each map call+static size_t _memory_span_map_count;+//! Number of spans to keep reserved in each heap+static size_t _memory_heap_reserve_count;+//! Global size classes+static size_class_t _memory_size_class[SIZE_CLASS_COUNT];+//! Run-time size limit of medium blocks+static size_t _memory_medium_size_limit;+//! Heap ID counter+static atomic32_t _memory_heap_id;+//! Huge page support+static int _memory_huge_pages;+#if ENABLE_GLOBAL_CACHE+//! Global span cache+static global_cache_t _memory_span_cache[LARGE_CLASS_COUNT];+#endif+//! Global reserved spans+static span_t* _memory_global_reserve;+//! Global reserved count+static size_t _memory_global_reserve_count;+//! Global reserved master+static span_t* _memory_global_reserve_master;+//! All heaps+static heap_t* _memory_heaps[HEAP_ARRAY_SIZE];+//! Used to restrict access to mapping memory for huge pages+static atomic32_t _memory_global_lock;+//! Orphaned heaps+static heap_t* _memory_orphan_heaps;+#if RPMALLOC_FIRST_CLASS_HEAPS+//! Orphaned heaps (first class heaps)+static heap_t* _memory_first_class_orphan_heaps;+#endif+#if ENABLE_STATISTICS+//! Allocations counter+static atomic64_t _allocation_counter;+//! Deallocations counter+static atomic64_t _deallocation_counter;+//! Active heap count+static atomic32_t _memory_active_heaps;+//! Number of currently mapped memory pages+static atomic32_t _mapped_pages;+//! Peak number of concurrently mapped memory pages+static int32_t _mapped_pages_peak;+//! Number of mapped master spans+static atomic32_t _master_spans;+//! Number of unmapped dangling master spans+static atomic32_t _unmapped_master_spans;+//! Running counter of total number of mapped memory pages since start+static atomic32_t _mapped_total;+//! Running counter of total number of unmapped memory pages since start+static atomic32_t _unmapped_total;+//! Number of currently mapped memory pages in OS calls+static atomic32_t _mapped_pages_os;+//! Number of currently allocated pages in huge allocations+static atomic32_t _huge_pages_current;+//! Peak number of currently allocated pages in huge allocations+static int32_t _huge_pages_peak;+#endif++////////////+///+/// Thread local heap and ID+///+//////++//! Current thread heap+#if ((defined(__APPLE__) || defined(__HAIKU__)) && ENABLE_PRELOAD) || defined(__TINYC__)+static pthread_key_t _memory_thread_heap;+#else+# ifdef _MSC_VER+# define _Thread_local __declspec(thread)+# define TLS_MODEL+# else+# if defined(__ANDROID__) && __ANDROID_API__ >= 29 && defined(__NDK_MAJOR__) && __NDK_MAJOR__ >= 26+# define TLS_MODEL __attribute__((tls_model("local-dynamic")))+# elif !defined(__HAIKU__)+# define TLS_MODEL __attribute__((tls_model("initial-exec")))+# else+# define TLS_MODEL+# endif+# if !defined(__clang__) && defined(__GNUC__)+# define _Thread_local __thread+# endif+# endif+static _Thread_local heap_t* _memory_thread_heap TLS_MODEL;+#endif++static inline heap_t*+get_thread_heap_raw(void) {+#if (defined(__APPLE__) || defined(__HAIKU__)) && ENABLE_PRELOAD+ return pthread_getspecific(_memory_thread_heap);+#else+ return _memory_thread_heap;+#endif+}++//! Get the current thread heap+static inline heap_t*+get_thread_heap(void) {+ heap_t* heap = get_thread_heap_raw();+#if ENABLE_PRELOAD+ if (EXPECTED(heap != 0))+ return heap;+ rpmalloc_initialize();+ return get_thread_heap_raw();+#else+ return heap;+#endif+}++//! Fast thread ID+static inline uintptr_t+get_thread_id(void) {+#if defined(_WIN32)+ return (uintptr_t)((void*)NtCurrentTeb());+#elif (defined(__GNUC__) || defined(__clang__)) && !defined(__CYGWIN__)+ uintptr_t tid;+# if defined(__i386__)+ __asm__("movl %%gs:0, %0" : "=r" (tid) : : );+# elif defined(__x86_64__)+# if defined(__MACH__)+ __asm__("movq %%gs:0, %0" : "=r" (tid) : : );+# else+ __asm__("movq %%fs:0, %0" : "=r" (tid) : : );+# endif+# elif defined(__arm__)+ __asm__ volatile ("mrc p15, 0, %0, c13, c0, 3" : "=r" (tid));+# elif defined(__aarch64__)+# if defined(__MACH__)+ // tpidr_el0 likely unused, always return 0 on iOS+ __asm__ volatile ("mrs %0, tpidrro_el0" : "=r" (tid));+# else+ __asm__ volatile ("mrs %0, tpidr_el0" : "=r" (tid));+# endif+# else+ tid = (uintptr_t)((void*)get_thread_heap_raw());+# endif+ return tid;+#else+ return (uintptr_t)((void*)get_thread_heap_raw());+#endif+}++//! Set the current thread heap+static void+set_thread_heap(heap_t* heap) {+#if ((defined(__APPLE__) || defined(__HAIKU__)) && ENABLE_PRELOAD) || defined(__TINYC__)+ pthread_setspecific(_memory_thread_heap, heap);+#else+ _memory_thread_heap = heap;+#endif+ if (heap)+ heap->owner_thread = get_thread_id();+}++//! Set main thread ID+extern void+rpmalloc_set_main_thread(void);++void+rpmalloc_set_main_thread(void) {+ _rpmalloc_main_thread_id = get_thread_id();+}++static void+_rpmalloc_spin(void) {+#if defined(_MSC_VER) && !(defined(_M_ARM) || defined(_M_ARM64))+ _mm_pause();+#elif defined(__x86_64__) || defined(__i386__)+ __asm__ volatile("pause" ::: "memory");+#elif defined(__aarch64__) || (defined(__arm__) && __ARM_ARCH >= 7)+ __asm__ volatile("yield" ::: "memory");+#elif defined(__powerpc__) || defined(__powerpc64__)+ // No idea if ever been compiled in such archs but ... as precaution+ __asm__ volatile("or 27,27,27");+#elif defined(__sparc__)+ __asm__ volatile("rd %ccr, %g0 \n\trd %ccr, %g0 \n\trd %ccr, %g0");+#else+ std::this_thread::yield();+#endif+}++#if defined(_WIN32) && (!defined(BUILD_DYNAMIC_LINK) || !BUILD_DYNAMIC_LINK)+static void NTAPI+_rpmalloc_thread_destructor(void* value) {+#if ENABLE_OVERRIDE+ // If this is called on main thread it means rpmalloc_finalize+ // has not been called and shutdown is forced (through _exit) or unclean+ if (get_thread_id() == _rpmalloc_main_thread_id)+ return;+#endif+ if (value)+ rpmalloc_thread_finalize(1);+}+#endif+++////////////+///+/// Low level memory map/unmap+///+//////++static void+_rpmalloc_set_name(void* address, size_t size) {+#if defined(__linux__) || defined(__ANDROID__)+ const char *name = _memory_huge_pages ? _memory_config.huge_page_name : _memory_config.page_name;+ if (address == MAP_FAILED || !name)+ return;+ // If the kernel does not support CONFIG_ANON_VMA_NAME or if the call fails+ // (e.g. invalid name) it is a no-op basically.+ (void)prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, (uintptr_t)address, size, (uintptr_t)name);+#else+ (void)sizeof(size);+ (void)sizeof(address);+#endif+}+++//! Map more virtual memory+// size is number of bytes to map+// offset receives the offset in bytes from start of mapped region+// returns address to start of mapped region to use+static void*+_rpmalloc_mmap(size_t size, size_t* offset) {+ rpmalloc_assert(!(size % _memory_page_size), "Invalid mmap size");+ rpmalloc_assert(size >= _memory_page_size, "Invalid mmap size");+ void* address = _memory_config.memory_map(size, offset);+ if (EXPECTED(address != 0)) {+ _rpmalloc_stat_add_peak(&_mapped_pages, (size >> _memory_page_size_shift), _mapped_pages_peak);+ _rpmalloc_stat_add(&_mapped_total, (size >> _memory_page_size_shift));+ }+ return address;+}++//! Unmap virtual memory+// address is the memory address to unmap, as returned from _memory_map+// size is the number of bytes to unmap, which might be less than full region for a partial unmap+// offset is the offset in bytes to the actual mapped region, as set by _memory_map+// release is set to 0 for partial unmap, or size of entire range for a full unmap+static void+_rpmalloc_unmap(void* address, size_t size, size_t offset, size_t release) {+ rpmalloc_assert(!release || (release >= size), "Invalid unmap size");+ rpmalloc_assert(!release || (release >= _memory_page_size), "Invalid unmap size");+ if (release) {+ rpmalloc_assert(!(release % _memory_page_size), "Invalid unmap size");+ _rpmalloc_stat_sub(&_mapped_pages, (release >> _memory_page_size_shift));+ _rpmalloc_stat_add(&_unmapped_total, (release >> _memory_page_size_shift));+ }+ _memory_config.memory_unmap(address, size, offset, release);+}++//! Default implementation to map new pages to virtual memory+static void*+_rpmalloc_mmap_os(size_t size, size_t* offset) {+ //Either size is a heap (a single page) or a (multiple) span - we only need to align spans, and only if larger than map granularity+ size_t padding = ((size >= _memory_span_size) && (_memory_span_size > _memory_map_granularity)) ? _memory_span_size : 0;+ rpmalloc_assert(size >= _memory_page_size, "Invalid mmap size");+#if PLATFORM_WINDOWS+ //Ok to MEM_COMMIT - according to MSDN, "actual physical pages are not allocated unless/until the virtual addresses are actually accessed"+ void* ptr = VirtualAlloc(0, size + padding, (_memory_huge_pages ? MEM_LARGE_PAGES : 0) | MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);+ if (!ptr) {+ if (_memory_config.map_fail_callback) {+ if (_memory_config.map_fail_callback(size + padding))+ return _rpmalloc_mmap_os(size, offset);+ } else {+ rpmalloc_assert(ptr, "Failed to map virtual memory block");+ }+ return 0;+ }+#else+ int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_UNINITIALIZED;+# if defined(__APPLE__) && !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR+ int fd = (int)VM_MAKE_TAG(240U);+ if (_memory_huge_pages)+ fd |= VM_FLAGS_SUPERPAGE_SIZE_2MB;+ void* ptr = mmap(0, size + padding, PROT_READ | PROT_WRITE, flags, fd, 0);+# elif defined(MAP_HUGETLB)+ void* ptr = mmap(0, size + padding, PROT_READ | PROT_WRITE | PROT_MAX(PROT_READ | PROT_WRITE), (_memory_huge_pages ? MAP_HUGETLB : 0) | flags, -1, 0);+# if defined(MADV_HUGEPAGE)+ // In some configurations, huge pages allocations might fail thus+ // we fallback to normal allocations and promote the region as transparent huge page+ if ((ptr == MAP_FAILED || !ptr) && _memory_huge_pages) {+ ptr = mmap(0, size + padding, PROT_READ | PROT_WRITE, flags, -1, 0);+ if (ptr && ptr != MAP_FAILED) {+ int prm = madvise(ptr, size + padding, MADV_HUGEPAGE);+ (void)prm;+ rpmalloc_assert((prm == 0), "Failed to promote the page to THP");+ }+ }+# endif+ _rpmalloc_set_name(ptr, size + padding);+# elif defined(MAP_ALIGNED)+ const size_t align = (sizeof(size_t) * 8) - (size_t)(__builtin_clzl(size - 1));+ void* ptr = mmap(0, size + padding, PROT_READ | PROT_WRITE, (_memory_huge_pages ? MAP_ALIGNED(align) : 0) | flags, -1, 0);+# elif defined(MAP_ALIGN)+ caddr_t base = (_memory_huge_pages ? (caddr_t)(4 << 20) : 0);+ void* ptr = mmap(base, size + padding, PROT_READ | PROT_WRITE, (_memory_huge_pages ? MAP_ALIGN : 0) | flags, -1, 0);+# else+ void* ptr = mmap(0, size + padding, PROT_READ | PROT_WRITE, flags, -1, 0);+# endif+ if ((ptr == MAP_FAILED) || !ptr) {+ if (_memory_config.map_fail_callback) {+ if (_memory_config.map_fail_callback(size + padding))+ return _rpmalloc_mmap_os(size, offset);+ } else if (errno != ENOMEM) {+ rpmalloc_assert((ptr != MAP_FAILED) && ptr, "Failed to map virtual memory block");+ }+ return 0;+ }+#endif+ _rpmalloc_stat_add(&_mapped_pages_os, (int32_t)((size + padding) >> _memory_page_size_shift));+ if (padding) {+ size_t final_padding = padding - ((uintptr_t)ptr & ~_memory_span_mask);+ rpmalloc_assert(final_padding <= _memory_span_size, "Internal failure in padding");+ rpmalloc_assert(final_padding <= padding, "Internal failure in padding");+ rpmalloc_assert(!(final_padding % 8), "Internal failure in padding");+ ptr = pointer_offset(ptr, final_padding);+ *offset = final_padding >> 3;+ }+ rpmalloc_assert((size < _memory_span_size) || !((uintptr_t)ptr & ~_memory_span_mask), "Internal failure in padding");+ return ptr;+}++//! Default implementation to unmap pages from virtual memory+static void+_rpmalloc_unmap_os(void* address, size_t size, size_t offset, size_t release) {+ rpmalloc_assert(release || (offset == 0), "Invalid unmap size");+ rpmalloc_assert(!release || (release >= _memory_page_size), "Invalid unmap size");+ rpmalloc_assert(size >= _memory_page_size, "Invalid unmap size");+ if (release && offset) {+ offset <<= 3;+ address = pointer_offset(address, -(int32_t)offset);+ if ((release >= _memory_span_size) && (_memory_span_size > _memory_map_granularity)) {+ //Padding is always one span size+ release += _memory_span_size;+ }+ }+#if !DISABLE_UNMAP+#if PLATFORM_WINDOWS+ if (!VirtualFree(address, release ? 0 : size, release ? MEM_RELEASE : MEM_DECOMMIT)) {+ rpmalloc_assert(0, "Failed to unmap virtual memory block");+ }+#else+ if (release) {+ if (munmap(address, release)) {+ rpmalloc_assert(0, "Failed to unmap virtual memory block");+ }+ } else {+#if defined(MADV_FREE_REUSABLE)+ int ret;+ while ((ret = madvise(address, size, MADV_FREE_REUSABLE)) == -1 && (errno == EAGAIN))+ errno = 0;+ if ((ret == -1) && (errno != 0)) {+#elif defined(MADV_DONTNEED)+ if (madvise(address, size, MADV_DONTNEED)) {+#elif defined(MADV_PAGEOUT)+ if (madvise(address, size, MADV_PAGEOUT)) {+#elif defined(MADV_FREE)+ if (madvise(address, size, MADV_FREE)) {+#else+ if (posix_madvise(address, size, POSIX_MADV_DONTNEED)) {+#endif+ rpmalloc_assert(0, "Failed to madvise virtual memory block as free");+ }+ }+#endif+#endif+ if (release)+ _rpmalloc_stat_sub(&_mapped_pages_os, release >> _memory_page_size_shift);+}++static void+_rpmalloc_span_mark_as_subspan_unless_master(span_t* master, span_t* subspan, size_t span_count);++//! Use global reserved spans to fulfill a memory map request (reserve size must be checked by caller)+static span_t*+_rpmalloc_global_get_reserved_spans(size_t span_count) {+ span_t* span = _memory_global_reserve;+ _rpmalloc_span_mark_as_subspan_unless_master(_memory_global_reserve_master, span, span_count);+ _memory_global_reserve_count -= span_count;+ if (_memory_global_reserve_count)+ _memory_global_reserve = (span_t*)pointer_offset(span, span_count << _memory_span_size_shift);+ else+ _memory_global_reserve = 0;+ return span;+}++//! Store the given spans as global reserve (must only be called from within new heap allocation, not thread safe)+static void+_rpmalloc_global_set_reserved_spans(span_t* master, span_t* reserve, size_t reserve_span_count) {+ _memory_global_reserve_master = master;+ _memory_global_reserve_count = reserve_span_count;+ _memory_global_reserve = reserve;+}+++////////////+///+/// Span linked list management+///+//////++//! Add a span to double linked list at the head+static void+_rpmalloc_span_double_link_list_add(span_t** head, span_t* span) {+ if (*head)+ (*head)->prev = span;+ span->next = *head;+ *head = span;+}++//! Pop head span from double linked list+static void+_rpmalloc_span_double_link_list_pop_head(span_t** head, span_t* span) {+ rpmalloc_assert(*head == span, "Linked list corrupted");+ span = *head;+ *head = span->next;+}++//! Remove a span from double linked list+static void+_rpmalloc_span_double_link_list_remove(span_t** head, span_t* span) {+ rpmalloc_assert(*head, "Linked list corrupted");+ if (*head == span) {+ *head = span->next;+ } else {+ span_t* next_span = span->next;+ span_t* prev_span = span->prev;+ prev_span->next = next_span;+ if (EXPECTED(next_span != 0))+ next_span->prev = prev_span;+ }+}+++////////////+///+/// Span control+///+//////++static void+_rpmalloc_heap_cache_insert(heap_t* heap, span_t* span);++static void+_rpmalloc_heap_finalize(heap_t* heap);++static void+_rpmalloc_heap_set_reserved_spans(heap_t* heap, span_t* master, span_t* reserve, size_t reserve_span_count);++//! Declare the span to be a subspan and store distance from master span and span count+static void+_rpmalloc_span_mark_as_subspan_unless_master(span_t* master, span_t* subspan, size_t span_count) {+ rpmalloc_assert((subspan != master) || (subspan->flags & SPAN_FLAG_MASTER), "Span master pointer and/or flag mismatch");+ if (subspan != master) {+ subspan->flags = SPAN_FLAG_SUBSPAN;+ subspan->offset_from_master = (uint32_t)((uintptr_t)pointer_diff(subspan, master) >> _memory_span_size_shift);+ subspan->align_offset = 0;+ }+ subspan->span_count = (uint32_t)span_count;+}++//! Use reserved spans to fulfill a memory map request (reserve size must be checked by caller)+static span_t*+_rpmalloc_span_map_from_reserve(heap_t* heap, size_t span_count) {+ //Update the heap span reserve+ span_t* span = heap->span_reserve;+ heap->span_reserve = (span_t*)pointer_offset(span, span_count * _memory_span_size);+ heap->spans_reserved -= (uint32_t)span_count;++ _rpmalloc_span_mark_as_subspan_unless_master(heap->span_reserve_master, span, span_count);+ if (span_count <= LARGE_CLASS_COUNT)+ _rpmalloc_stat_inc(&heap->span_use[span_count - 1].spans_from_reserved);++ return span;+}++//! Get the aligned number of spans to map in based on wanted count, configured mapping granularity and the page size+static size_t+_rpmalloc_span_align_count(size_t span_count) {+ size_t request_count = (span_count > _memory_span_map_count) ? span_count : _memory_span_map_count;+ if ((_memory_page_size > _memory_span_size) && ((request_count * _memory_span_size) % _memory_page_size))+ request_count += _memory_span_map_count - (request_count % _memory_span_map_count);+ return request_count;+}++//! Setup a newly mapped span+static void+_rpmalloc_span_initialize(span_t* span, size_t total_span_count, size_t span_count, size_t align_offset) {+ span->total_spans = (uint32_t)total_span_count;+ span->span_count = (uint32_t)span_count;+ span->align_offset = (uint32_t)align_offset;+ span->flags = SPAN_FLAG_MASTER;+ atomic_store32(&span->remaining_spans, (int32_t)total_span_count);+}++static void+_rpmalloc_span_unmap(span_t* span);++//! Map an aligned set of spans, taking configured mapping granularity and the page size into account+static span_t*+_rpmalloc_span_map_aligned_count(heap_t* heap, size_t span_count) {+ //If we already have some, but not enough, reserved spans, release those to heap cache and map a new+ //full set of spans. Otherwise we would waste memory if page size > span size (huge pages)+ size_t aligned_span_count = _rpmalloc_span_align_count(span_count);+ size_t align_offset = 0;+ span_t* span = (span_t*)_rpmalloc_mmap(aligned_span_count * _memory_span_size, &align_offset);+ if (!span)+ return 0;+ _rpmalloc_span_initialize(span, aligned_span_count, span_count, align_offset);+ _rpmalloc_stat_inc(&_master_spans);+ if (span_count <= LARGE_CLASS_COUNT)+ _rpmalloc_stat_inc(&heap->span_use[span_count - 1].spans_map_calls);+ if (aligned_span_count > span_count) {+ span_t* reserved_spans = (span_t*)pointer_offset(span, span_count * _memory_span_size);+ size_t reserved_count = aligned_span_count - span_count;+ if (heap->spans_reserved) {+ _rpmalloc_span_mark_as_subspan_unless_master(heap->span_reserve_master, heap->span_reserve, heap->spans_reserved);+ _rpmalloc_heap_cache_insert(heap, heap->span_reserve);+ }+ if (reserved_count > _memory_heap_reserve_count) {+ // If huge pages or eager spam map count, the global reserve spin lock is held by caller, _rpmalloc_span_map+ rpmalloc_assert(atomic_load32(&_memory_global_lock) == 1, "Global spin lock not held as expected");+ size_t remain_count = reserved_count - _memory_heap_reserve_count;+ reserved_count = _memory_heap_reserve_count;+ span_t* remain_span = (span_t*)pointer_offset(reserved_spans, reserved_count * _memory_span_size);+ if (_memory_global_reserve) {+ _rpmalloc_span_mark_as_subspan_unless_master(_memory_global_reserve_master, _memory_global_reserve, _memory_global_reserve_count);+ _rpmalloc_span_unmap(_memory_global_reserve);+ }+ _rpmalloc_global_set_reserved_spans(span, remain_span, remain_count);+ }+ _rpmalloc_heap_set_reserved_spans(heap, span, reserved_spans, reserved_count);+ }+ return span;+}++//! Map in memory pages for the given number of spans (or use previously reserved pages)+static span_t*+_rpmalloc_span_map(heap_t* heap, size_t span_count) {+ if (span_count <= heap->spans_reserved)+ return _rpmalloc_span_map_from_reserve(heap, span_count);+ span_t* span = 0;+ int use_global_reserve = (_memory_page_size > _memory_span_size) || (_memory_span_map_count > _memory_heap_reserve_count);+ if (use_global_reserve) {+ // If huge pages, make sure only one thread maps more memory to avoid bloat+ while (!atomic_cas32_acquire(&_memory_global_lock, 1, 0))+ _rpmalloc_spin();+ if (_memory_global_reserve_count >= span_count) {+ size_t reserve_count = (!heap->spans_reserved ? _memory_heap_reserve_count : span_count);+ if (_memory_global_reserve_count < reserve_count)+ reserve_count = _memory_global_reserve_count;+ span = _rpmalloc_global_get_reserved_spans(reserve_count);+ if (span) {+ if (reserve_count > span_count) {+ span_t* reserved_span = (span_t*)pointer_offset(span, span_count << _memory_span_size_shift);+ _rpmalloc_heap_set_reserved_spans(heap, _memory_global_reserve_master, reserved_span, reserve_count - span_count);+ }+ // Already marked as subspan in _rpmalloc_global_get_reserved_spans+ span->span_count = (uint32_t)span_count;+ }+ }+ }+ if (!span)+ span = _rpmalloc_span_map_aligned_count(heap, span_count);+ if (use_global_reserve)+ atomic_store32_release(&_memory_global_lock, 0);+ return span;+}++//! Unmap memory pages for the given number of spans (or mark as unused if no partial unmappings)+static void+_rpmalloc_span_unmap(span_t* span) {+ rpmalloc_assert((span->flags & SPAN_FLAG_MASTER) || (span->flags & SPAN_FLAG_SUBSPAN), "Span flag corrupted");+ rpmalloc_assert(!(span->flags & SPAN_FLAG_MASTER) || !(span->flags & SPAN_FLAG_SUBSPAN), "Span flag corrupted");++ int is_master = !!(span->flags & SPAN_FLAG_MASTER);+ span_t* master = is_master ? span : ((span_t*)pointer_offset(span, -(intptr_t)((uintptr_t)span->offset_from_master * _memory_span_size)));+ rpmalloc_assert(is_master || (span->flags & SPAN_FLAG_SUBSPAN), "Span flag corrupted");+ rpmalloc_assert(master->flags & SPAN_FLAG_MASTER, "Span flag corrupted");++ size_t span_count = span->span_count;+ if (!is_master) {+ //Directly unmap subspans (unless huge pages, in which case we defer and unmap entire page range with master)+ rpmalloc_assert(span->align_offset == 0, "Span align offset corrupted");+ if (_memory_span_size >= _memory_page_size)+ _rpmalloc_unmap(span, span_count * _memory_span_size, 0, 0);+ } else {+ //Special double flag to denote an unmapped master+ //It must be kept in memory since span header must be used+ span->flags |= SPAN_FLAG_MASTER | SPAN_FLAG_SUBSPAN | SPAN_FLAG_UNMAPPED_MASTER;+ _rpmalloc_stat_add(&_unmapped_master_spans, 1);+ }++ if (atomic_add32(&master->remaining_spans, -(int32_t)span_count) <= 0) {+ //Everything unmapped, unmap the master span with release flag to unmap the entire range of the super span+ rpmalloc_assert(!!(master->flags & SPAN_FLAG_MASTER) && !!(master->flags & SPAN_FLAG_SUBSPAN), "Span flag corrupted");+ size_t unmap_count = master->span_count;+ if (_memory_span_size < _memory_page_size)+ unmap_count = master->total_spans;+ _rpmalloc_stat_sub(&_master_spans, 1);+ _rpmalloc_stat_sub(&_unmapped_master_spans, 1);+ _rpmalloc_unmap(master, unmap_count * _memory_span_size, master->align_offset, (size_t)master->total_spans * _memory_span_size);+ }+}++//! Move the span (used for small or medium allocations) to the heap thread cache+static void+_rpmalloc_span_release_to_cache(heap_t* heap, span_t* span) {+ rpmalloc_assert(heap == span->heap, "Span heap pointer corrupted");+ rpmalloc_assert(span->size_class < SIZE_CLASS_COUNT, "Invalid span size class");+ rpmalloc_assert(span->span_count == 1, "Invalid span count");+#if ENABLE_ADAPTIVE_THREAD_CACHE || ENABLE_STATISTICS+ atomic_decr32(&heap->span_use[0].current);+#endif+ _rpmalloc_stat_dec(&heap->size_class_use[span->size_class].spans_current);+ if (!heap->finalize) {+ _rpmalloc_stat_inc(&heap->span_use[0].spans_to_cache);+ _rpmalloc_stat_inc(&heap->size_class_use[span->size_class].spans_to_cache);+ if (heap->size_class[span->size_class].cache)+ _rpmalloc_heap_cache_insert(heap, heap->size_class[span->size_class].cache);+ heap->size_class[span->size_class].cache = span;+ } else {+ _rpmalloc_span_unmap(span);+ }+}++//! Initialize a (partial) free list up to next system memory page, while reserving the first block+//! as allocated, returning number of blocks in list+static uint32_t+free_list_partial_init(void** list, void** first_block, void* page_start, void* block_start, uint32_t block_count, uint32_t block_size) {+ rpmalloc_assert(block_count, "Internal failure");+ *first_block = block_start;+ if (block_count > 1) {+ void* free_block = pointer_offset(block_start, block_size);+ void* block_end = pointer_offset(block_start, (size_t)block_size * block_count);+ //If block size is less than half a memory page, bound init to next memory page boundary+ if (block_size < (_memory_page_size >> 1)) {+ void* page_end = pointer_offset(page_start, _memory_page_size);+ if (page_end < block_end)+ block_end = page_end;+ }+ *list = free_block;+ block_count = 2;+ void* next_block = pointer_offset(free_block, block_size);+ while (next_block < block_end) {+ *((void**)free_block) = next_block;+ free_block = next_block;+ ++block_count;+ next_block = pointer_offset(next_block, block_size);+ }+ *((void**)free_block) = 0;+ } else {+ *list = 0;+ }+ return block_count;+}++//! Initialize an unused span (from cache or mapped) to be new active span, putting the initial free list in heap class free list+static void*+_rpmalloc_span_initialize_new(heap_t* heap, heap_size_class_t* heap_size_class, span_t* span, uint32_t class_idx) {+ rpmalloc_assert(span->span_count == 1, "Internal failure");+ size_class_t* size_class = _memory_size_class + class_idx;+ span->size_class = class_idx;+ span->heap = heap;+ span->flags &= ~SPAN_FLAG_ALIGNED_BLOCKS;+ span->block_size = size_class->block_size;+ span->block_count = size_class->block_count;+ span->free_list = 0;+ span->list_size = 0;+ atomic_store_ptr_release(&span->free_list_deferred, 0);++ //Setup free list. Only initialize one system page worth of free blocks in list+ void* block;+ span->free_list_limit = free_list_partial_init(&heap_size_class->free_list, &block, + span, pointer_offset(span, SPAN_HEADER_SIZE), size_class->block_count, size_class->block_size);+ //Link span as partial if there remains blocks to be initialized as free list, or full if fully initialized+ if (span->free_list_limit < span->block_count) {+ _rpmalloc_span_double_link_list_add(&heap_size_class->partial_span, span);+ span->used_count = span->free_list_limit;+ } else {+#if RPMALLOC_FIRST_CLASS_HEAPS+ _rpmalloc_span_double_link_list_add(&heap->full_span[class_idx], span);+#endif+ ++heap->full_span_count;+ span->used_count = span->block_count;+ }+ return block;+}++static void+_rpmalloc_span_extract_free_list_deferred(span_t* span) {+ // We need acquire semantics on the CAS operation since we are interested in the list size+ // Refer to _rpmalloc_deallocate_defer_small_or_medium for further comments on this dependency+ do {+ span->free_list = atomic_exchange_ptr_acquire(&span->free_list_deferred, INVALID_POINTER);+ } while (span->free_list == INVALID_POINTER);+ span->used_count -= span->list_size;+ span->list_size = 0;+ atomic_store_ptr_release(&span->free_list_deferred, 0);+}++static int+_rpmalloc_span_is_fully_utilized(span_t* span) {+ rpmalloc_assert(span->free_list_limit <= span->block_count, "Span free list corrupted");+ return !span->free_list && (span->free_list_limit >= span->block_count);+}++static int+_rpmalloc_span_finalize(heap_t* heap, size_t iclass, span_t* span, span_t** list_head) {+ void* free_list = heap->size_class[iclass].free_list;+ span_t* class_span = (span_t*)((uintptr_t)free_list & _memory_span_mask);+ if (span == class_span) {+ // Adopt the heap class free list back into the span free list+ void* block = span->free_list;+ void* last_block = 0;+ while (block) {+ last_block = block;+ block = *((void**)block);+ }+ uint32_t free_count = 0;+ block = free_list;+ while (block) {+ ++free_count;+ block = *((void**)block);+ }+ if (last_block) {+ *((void**)last_block) = free_list;+ } else {+ span->free_list = free_list;+ }+ heap->size_class[iclass].free_list = 0;+ span->used_count -= free_count;+ }+ //If this assert triggers you have memory leaks+ rpmalloc_assert(span->list_size == span->used_count, "Memory leak detected");+ if (span->list_size == span->used_count) {+ _rpmalloc_stat_dec(&heap->span_use[0].current);+ _rpmalloc_stat_dec(&heap->size_class_use[iclass].spans_current);+ // This function only used for spans in double linked lists+ if (list_head)+ _rpmalloc_span_double_link_list_remove(list_head, span);+ _rpmalloc_span_unmap(span);+ return 1;+ }+ return 0;+}+++////////////+///+/// Global cache+///+//////++#if ENABLE_GLOBAL_CACHE++//! Finalize a global cache+static void+_rpmalloc_global_cache_finalize(global_cache_t* cache) {+ while (!atomic_cas32_acquire(&cache->lock, 1, 0))+ _rpmalloc_spin();++ for (size_t ispan = 0; ispan < cache->count; ++ispan)+ _rpmalloc_span_unmap(cache->span[ispan]);+ cache->count = 0;++ while (cache->overflow) {+ span_t* span = cache->overflow;+ cache->overflow = span->next;+ _rpmalloc_span_unmap(span);+ }++ atomic_store32_release(&cache->lock, 0);+}++static void+_rpmalloc_global_cache_insert_spans(span_t** span, size_t span_count, size_t count) {+ const size_t cache_limit = (span_count == 1) ? + GLOBAL_CACHE_MULTIPLIER * MAX_THREAD_SPAN_CACHE :+ GLOBAL_CACHE_MULTIPLIER * (MAX_THREAD_SPAN_LARGE_CACHE - (span_count >> 1));++ global_cache_t* cache = &_memory_span_cache[span_count - 1];++ size_t insert_count = count;+ while (!atomic_cas32_acquire(&cache->lock, 1, 0))+ _rpmalloc_spin();++#if ENABLE_STATISTICS+ cache->insert_count += count;+#endif+ if ((cache->count + insert_count) > cache_limit)+ insert_count = cache_limit - cache->count;++ memcpy(cache->span + cache->count, span, sizeof(span_t*) * insert_count);+ cache->count += (uint32_t)insert_count;++#if ENABLE_UNLIMITED_CACHE+ while (insert_count < count) {+#else+ // Enable unlimited cache if huge pages, or we will leak since it is unlikely that an entire huge page+ // will be unmapped, and we're unable to partially decommit a huge page+ while ((_memory_page_size > _memory_span_size) && (insert_count < count)) {+#endif + span_t* current_span = span[insert_count++];+ current_span->next = cache->overflow;+ cache->overflow = current_span;+ }+ atomic_store32_release(&cache->lock, 0);++ span_t* keep = 0;+ for (size_t ispan = insert_count; ispan < count; ++ispan) {+ span_t* current_span = span[ispan];+ // Keep master spans that has remaining subspans to avoid dangling them+ if ((current_span->flags & SPAN_FLAG_MASTER) &&+ (atomic_load32(¤t_span->remaining_spans) > (int32_t)current_span->span_count)) {+ current_span->next = keep;+ keep = current_span;+ } else {+ _rpmalloc_span_unmap(current_span);+ }+ }++ if (keep) {+ while (!atomic_cas32_acquire(&cache->lock, 1, 0))+ _rpmalloc_spin();++ size_t islot = 0;+ while (keep) {+ for (; islot < cache->count; ++islot) {+ span_t* current_span = cache->span[islot];+ if (!(current_span->flags & SPAN_FLAG_MASTER) || ((current_span->flags & SPAN_FLAG_MASTER) &&+ (atomic_load32(¤t_span->remaining_spans) <= (int32_t)current_span->span_count))) {+ _rpmalloc_span_unmap(current_span);+ cache->span[islot] = keep;+ break;+ }+ }+ if (islot == cache->count)+ break;+ keep = keep->next;+ }++ if (keep) {+ span_t* tail = keep;+ while (tail->next)+ tail = tail->next;+ tail->next = cache->overflow;+ cache->overflow = keep;+ }++ atomic_store32_release(&cache->lock, 0);+ }+}++static size_t+_rpmalloc_global_cache_extract_spans(span_t** span, size_t span_count, size_t count) {+ global_cache_t* cache = &_memory_span_cache[span_count - 1];++ size_t extract_count = 0;+ while (!atomic_cas32_acquire(&cache->lock, 1, 0))+ _rpmalloc_spin();++#if ENABLE_STATISTICS+ cache->extract_count += count;+#endif+ size_t want = count - extract_count;+ if (want > cache->count)+ want = cache->count;++ memcpy(span + extract_count, cache->span + (cache->count - want), sizeof(span_t*) * want);+ cache->count -= (uint32_t)want;+ extract_count += want;++ while ((extract_count < count) && cache->overflow) {+ span_t* current_span = cache->overflow;+ span[extract_count++] = current_span;+ cache->overflow = current_span->next;+ }++#if ENABLE_ASSERTS+ for (size_t ispan = 0; ispan < extract_count; ++ispan) {+ assert(span[ispan]->span_count == span_count);+ }+#endif++ atomic_store32_release(&cache->lock, 0);++ return extract_count;+}++#endif++////////////+///+/// Heap control+///+//////++static void _rpmalloc_deallocate_huge(span_t*);++//! Store the given spans as reserve in the given heap+static void+_rpmalloc_heap_set_reserved_spans(heap_t* heap, span_t* master, span_t* reserve, size_t reserve_span_count) {+ heap->span_reserve_master = master;+ heap->span_reserve = reserve;+ heap->spans_reserved = (uint32_t)reserve_span_count;+}++//! Adopt the deferred span cache list, optionally extracting the first single span for immediate re-use+static void+_rpmalloc_heap_cache_adopt_deferred(heap_t* heap, span_t** single_span) {+ span_t* span = (span_t*)((void*)atomic_exchange_ptr_acquire(&heap->span_free_deferred, 0));+ while (span) {+ span_t* next_span = (span_t*)span->free_list;+ rpmalloc_assert(span->heap == heap, "Span heap pointer corrupted");+ if (EXPECTED(span->size_class < SIZE_CLASS_COUNT)) {+ rpmalloc_assert(heap->full_span_count, "Heap span counter corrupted");+ --heap->full_span_count;+ _rpmalloc_stat_dec(&heap->span_use[0].spans_deferred);+#if RPMALLOC_FIRST_CLASS_HEAPS+ _rpmalloc_span_double_link_list_remove(&heap->full_span[span->size_class], span);+#endif+ _rpmalloc_stat_dec(&heap->span_use[0].current);+ _rpmalloc_stat_dec(&heap->size_class_use[span->size_class].spans_current);+ if (single_span && !*single_span)+ *single_span = span;+ else+ _rpmalloc_heap_cache_insert(heap, span);+ } else {+ if (span->size_class == SIZE_CLASS_HUGE) {+ _rpmalloc_deallocate_huge(span);+ } else {+ rpmalloc_assert(span->size_class == SIZE_CLASS_LARGE, "Span size class invalid");+ rpmalloc_assert(heap->full_span_count, "Heap span counter corrupted");+ --heap->full_span_count;+#if RPMALLOC_FIRST_CLASS_HEAPS+ _rpmalloc_span_double_link_list_remove(&heap->large_huge_span, span);+#endif+ uint32_t idx = span->span_count - 1;+ _rpmalloc_stat_dec(&heap->span_use[idx].spans_deferred);+ _rpmalloc_stat_dec(&heap->span_use[idx].current);+ if (!idx && single_span && !*single_span)+ *single_span = span;+ else+ _rpmalloc_heap_cache_insert(heap, span);+ }+ }+ span = next_span;+ }+}++static void+_rpmalloc_heap_unmap(heap_t* heap) {+ if (!heap->master_heap) {+ if ((heap->finalize > 1) && !atomic_load32(&heap->child_count)) {+ span_t* span = (span_t*)((uintptr_t)heap & _memory_span_mask);+ _rpmalloc_span_unmap(span);+ }+ } else {+ if (atomic_decr32(&heap->master_heap->child_count) == 0) {+ _rpmalloc_heap_unmap(heap->master_heap);+ }+ }+}++static void+_rpmalloc_heap_global_finalize(heap_t* heap) {+ if (heap->finalize++ > 1) {+ --heap->finalize;+ return;+ }++ _rpmalloc_heap_finalize(heap);++#if ENABLE_THREAD_CACHE+ for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) {+ span_cache_t* span_cache;+ if (!iclass)+ span_cache = &heap->span_cache;+ else+ span_cache = (span_cache_t*)(heap->span_large_cache + (iclass - 1));+ for (size_t ispan = 0; ispan < span_cache->count; ++ispan)+ _rpmalloc_span_unmap(span_cache->span[ispan]);+ span_cache->count = 0;+ }+#endif++ if (heap->full_span_count) {+ --heap->finalize;+ return;+ }++ for (size_t iclass = 0; iclass < SIZE_CLASS_COUNT; ++iclass) {+ if (heap->size_class[iclass].free_list || heap->size_class[iclass].partial_span) {+ --heap->finalize;+ return;+ }+ }+ //Heap is now completely free, unmap and remove from heap list+ size_t list_idx = (size_t)heap->id % HEAP_ARRAY_SIZE;+ heap_t* list_heap = _memory_heaps[list_idx];+ if (list_heap == heap) {+ _memory_heaps[list_idx] = heap->next_heap;+ } else {+ while (list_heap->next_heap != heap)+ list_heap = list_heap->next_heap;+ list_heap->next_heap = heap->next_heap;+ }++ _rpmalloc_heap_unmap(heap);+}++//! Insert a single span into thread heap cache, releasing to global cache if overflow+static void+_rpmalloc_heap_cache_insert(heap_t* heap, span_t* span) {+ if (UNEXPECTED(heap->finalize != 0)) {+ _rpmalloc_span_unmap(span);+ _rpmalloc_heap_global_finalize(heap);+ return;+ }+#if ENABLE_THREAD_CACHE+ size_t span_count = span->span_count;+ _rpmalloc_stat_inc(&heap->span_use[span_count - 1].spans_to_cache);+ if (span_count == 1) {+ span_cache_t* span_cache = &heap->span_cache;+ span_cache->span[span_cache->count++] = span;+ if (span_cache->count == MAX_THREAD_SPAN_CACHE) {+ const size_t remain_count = MAX_THREAD_SPAN_CACHE - THREAD_SPAN_CACHE_TRANSFER;+#if ENABLE_GLOBAL_CACHE+ _rpmalloc_stat_add64(&heap->thread_to_global, THREAD_SPAN_CACHE_TRANSFER * _memory_span_size);+ _rpmalloc_stat_add(&heap->span_use[span_count - 1].spans_to_global, THREAD_SPAN_CACHE_TRANSFER);+ _rpmalloc_global_cache_insert_spans(span_cache->span + remain_count, span_count, THREAD_SPAN_CACHE_TRANSFER);+#else+ for (size_t ispan = 0; ispan < THREAD_SPAN_CACHE_TRANSFER; ++ispan)+ _rpmalloc_span_unmap(span_cache->span[remain_count + ispan]);+#endif+ span_cache->count = remain_count;+ }+ } else {+ size_t cache_idx = span_count - 2;+ span_large_cache_t* span_cache = heap->span_large_cache + cache_idx;+ span_cache->span[span_cache->count++] = span;+ const size_t cache_limit = (MAX_THREAD_SPAN_LARGE_CACHE - (span_count >> 1));+ if (span_cache->count == cache_limit) {+ const size_t transfer_limit = 2 + (cache_limit >> 2);+ const size_t transfer_count = (THREAD_SPAN_LARGE_CACHE_TRANSFER <= transfer_limit ? THREAD_SPAN_LARGE_CACHE_TRANSFER : transfer_limit);+ const size_t remain_count = cache_limit - transfer_count;+#if ENABLE_GLOBAL_CACHE+ _rpmalloc_stat_add64(&heap->thread_to_global, transfer_count * span_count * _memory_span_size);+ _rpmalloc_stat_add(&heap->span_use[span_count - 1].spans_to_global, transfer_count);+ _rpmalloc_global_cache_insert_spans(span_cache->span + remain_count, span_count, transfer_count);+#else+ for (size_t ispan = 0; ispan < transfer_count; ++ispan)+ _rpmalloc_span_unmap(span_cache->span[remain_count + ispan]);+#endif+ span_cache->count = remain_count;+ }+ }+#else+ (void)sizeof(heap);+ _rpmalloc_span_unmap(span);+#endif+}++//! Extract the given number of spans from the different cache levels+static span_t*+_rpmalloc_heap_thread_cache_extract(heap_t* heap, size_t span_count) {+ span_t* span = 0;+#if ENABLE_THREAD_CACHE+ span_cache_t* span_cache;+ if (span_count == 1)+ span_cache = &heap->span_cache;+ else+ span_cache = (span_cache_t*)(heap->span_large_cache + (span_count - 2));+ if (span_cache->count) {+ _rpmalloc_stat_inc(&heap->span_use[span_count - 1].spans_from_cache);+ return span_cache->span[--span_cache->count];+ }+#endif+ return span;+}++static span_t*+_rpmalloc_heap_thread_cache_deferred_extract(heap_t* heap, size_t span_count) {+ span_t* span = 0;+ if (span_count == 1) {+ _rpmalloc_heap_cache_adopt_deferred(heap, &span);+ } else {+ _rpmalloc_heap_cache_adopt_deferred(heap, 0);+ span = _rpmalloc_heap_thread_cache_extract(heap, span_count);+ }+ return span;+}++static span_t*+_rpmalloc_heap_reserved_extract(heap_t* heap, size_t span_count) {+ if (heap->spans_reserved >= span_count)+ return _rpmalloc_span_map(heap, span_count);+ return 0;+}++//! Extract a span from the global cache+static span_t*+_rpmalloc_heap_global_cache_extract(heap_t* heap, size_t span_count) {+#if ENABLE_GLOBAL_CACHE+#if ENABLE_THREAD_CACHE+ span_cache_t* span_cache;+ size_t wanted_count;+ if (span_count == 1) {+ span_cache = &heap->span_cache;+ wanted_count = THREAD_SPAN_CACHE_TRANSFER;+ } else {+ span_cache = (span_cache_t*)(heap->span_large_cache + (span_count - 2));+ wanted_count = THREAD_SPAN_LARGE_CACHE_TRANSFER;+ }+ span_cache->count = _rpmalloc_global_cache_extract_spans(span_cache->span, span_count, wanted_count);+ if (span_cache->count) {+ _rpmalloc_stat_add64(&heap->global_to_thread, span_count * span_cache->count * _memory_span_size);+ _rpmalloc_stat_add(&heap->span_use[span_count - 1].spans_from_global, span_cache->count);+ return span_cache->span[--span_cache->count];+ }+#else+ span_t* span = 0;+ size_t count = _rpmalloc_global_cache_extract_spans(&span, span_count, 1);+ if (count) {+ _rpmalloc_stat_add64(&heap->global_to_thread, span_count * count * _memory_span_size);+ _rpmalloc_stat_add(&heap->span_use[span_count - 1].spans_from_global, count);+ return span;+ }+#endif+#endif+ (void)sizeof(heap);+ (void)sizeof(span_count);+ return 0;+}++static void+_rpmalloc_inc_span_statistics(heap_t* heap, size_t span_count, uint32_t class_idx) {+ (void)sizeof(heap);+ (void)sizeof(span_count);+ (void)sizeof(class_idx);+#if ENABLE_ADAPTIVE_THREAD_CACHE || ENABLE_STATISTICS+ uint32_t idx = (uint32_t)span_count - 1;+ uint32_t current_count = (uint32_t)atomic_incr32(&heap->span_use[idx].current);+ if (current_count > (uint32_t)atomic_load32(&heap->span_use[idx].high))+ atomic_store32(&heap->span_use[idx].high, (int32_t)current_count);+ _rpmalloc_stat_add_peak(&heap->size_class_use[class_idx].spans_current, 1, heap->size_class_use[class_idx].spans_peak);+#endif+}++//! Get a span from one of the cache levels (thread cache, reserved, global cache) or fallback to mapping more memory+static span_t*+_rpmalloc_heap_extract_new_span(heap_t* heap, heap_size_class_t* heap_size_class, size_t span_count, uint32_t class_idx) {+ span_t* span;+#if ENABLE_THREAD_CACHE+ if (heap_size_class && heap_size_class->cache) {+ span = heap_size_class->cache;+ heap_size_class->cache = (heap->span_cache.count ? heap->span_cache.span[--heap->span_cache.count] : 0);+ _rpmalloc_inc_span_statistics(heap, span_count, class_idx);+ return span;+ }+#endif+ (void)sizeof(class_idx);+ // Allow 50% overhead to increase cache hits+ size_t base_span_count = span_count;+ size_t limit_span_count = (span_count > 2) ? (span_count + (span_count >> 1)) : span_count;+ if (limit_span_count > LARGE_CLASS_COUNT)+ limit_span_count = LARGE_CLASS_COUNT;+ do {+ span = _rpmalloc_heap_thread_cache_extract(heap, span_count);+ if (EXPECTED(span != 0)) {+ _rpmalloc_stat_inc(&heap->size_class_use[class_idx].spans_from_cache);+ _rpmalloc_inc_span_statistics(heap, span_count, class_idx);+ return span;+ }+ span = _rpmalloc_heap_thread_cache_deferred_extract(heap, span_count);+ if (EXPECTED(span != 0)) {+ _rpmalloc_stat_inc(&heap->size_class_use[class_idx].spans_from_cache);+ _rpmalloc_inc_span_statistics(heap, span_count, class_idx);+ return span;+ }+ span = _rpmalloc_heap_reserved_extract(heap, span_count);+ if (EXPECTED(span != 0)) {+ _rpmalloc_stat_inc(&heap->size_class_use[class_idx].spans_from_reserved);+ _rpmalloc_inc_span_statistics(heap, span_count, class_idx);+ return span;+ }+ span = _rpmalloc_heap_global_cache_extract(heap, span_count);+ if (EXPECTED(span != 0)) {+ _rpmalloc_stat_inc(&heap->size_class_use[class_idx].spans_from_cache);+ _rpmalloc_inc_span_statistics(heap, span_count, class_idx);+ return span;+ }+ ++span_count;+ } while (span_count <= limit_span_count);+ //Final fallback, map in more virtual memory+ span = _rpmalloc_span_map(heap, base_span_count);+ _rpmalloc_inc_span_statistics(heap, base_span_count, class_idx);+ _rpmalloc_stat_inc(&heap->size_class_use[class_idx].spans_map_calls);+ return span;+}++static void+_rpmalloc_heap_initialize(heap_t* heap) {+ memset((void*)heap, 0, sizeof(heap_t));+ //Get a new heap ID+ heap->id = 1 + atomic_incr32(&_memory_heap_id);++ //Link in heap in heap ID map+ size_t list_idx = (size_t)heap->id % HEAP_ARRAY_SIZE;+ heap->next_heap = _memory_heaps[list_idx];+ _memory_heaps[list_idx] = heap;+}++static void+_rpmalloc_heap_orphan(heap_t* heap, int first_class) {+ heap->owner_thread = (uintptr_t)-1;+#if RPMALLOC_FIRST_CLASS_HEAPS+ heap_t** heap_list = (first_class ? &_memory_first_class_orphan_heaps : &_memory_orphan_heaps);+#else+ (void)sizeof(first_class);+ heap_t** heap_list = &_memory_orphan_heaps;+#endif+ heap->next_orphan = *heap_list;+ *heap_list = heap;+}++//! Allocate a new heap from newly mapped memory pages+static heap_t*+_rpmalloc_heap_allocate_new(void) {+ // Map in pages for a 16 heaps. If page size is greater than required size for this, map a page and+ // use first part for heaps and remaining part for spans for allocations. Adds a lot of complexity,+ // but saves a lot of memory on systems where page size > 64 spans (4MiB)+ size_t heap_size = sizeof(heap_t);+ size_t aligned_heap_size = 16 * ((heap_size + 15) / 16);+ size_t request_heap_count = 16;+ size_t heap_span_count = ((aligned_heap_size * request_heap_count) + sizeof(span_t) + _memory_span_size - 1) / _memory_span_size;+ size_t block_size = _memory_span_size * heap_span_count;+ size_t span_count = heap_span_count;+ span_t* span = 0;+ // If there are global reserved spans, use these first+ if (_memory_global_reserve_count >= heap_span_count) {+ span = _rpmalloc_global_get_reserved_spans(heap_span_count);+ }+ if (!span) {+ if (_memory_page_size > block_size) {+ span_count = _memory_page_size / _memory_span_size;+ block_size = _memory_page_size;+ // If using huge pages, make sure to grab enough heaps to avoid reallocating a huge page just to serve new heaps+ size_t possible_heap_count = (block_size - sizeof(span_t)) / aligned_heap_size;+ if (possible_heap_count >= (request_heap_count * 16))+ request_heap_count *= 16;+ else if (possible_heap_count < request_heap_count)+ request_heap_count = possible_heap_count;+ heap_span_count = ((aligned_heap_size * request_heap_count) + sizeof(span_t) + _memory_span_size - 1) / _memory_span_size;+ }++ size_t align_offset = 0;+ span = (span_t*)_rpmalloc_mmap(block_size, &align_offset);+ if (!span)+ return 0;++ // Master span will contain the heaps+ _rpmalloc_stat_inc(&_master_spans);+ _rpmalloc_span_initialize(span, span_count, heap_span_count, align_offset);+ }++ size_t remain_size = _memory_span_size - sizeof(span_t);+ heap_t* heap = (heap_t*)pointer_offset(span, sizeof(span_t));+ _rpmalloc_heap_initialize(heap);++ // Put extra heaps as orphans+ size_t num_heaps = remain_size / aligned_heap_size;+ if (num_heaps < request_heap_count)+ num_heaps = request_heap_count;+ atomic_store32(&heap->child_count, (int32_t)num_heaps - 1);+ heap_t* extra_heap = (heap_t*)pointer_offset(heap, aligned_heap_size);+ while (num_heaps > 1) {+ _rpmalloc_heap_initialize(extra_heap);+ extra_heap->master_heap = heap;+ _rpmalloc_heap_orphan(extra_heap, 1);+ extra_heap = (heap_t*)pointer_offset(extra_heap, aligned_heap_size);+ --num_heaps;+ }++ if (span_count > heap_span_count) {+ // Cap reserved spans+ size_t remain_count = span_count - heap_span_count;+ size_t reserve_count = (remain_count > _memory_heap_reserve_count ? _memory_heap_reserve_count : remain_count);+ span_t* remain_span = (span_t*)pointer_offset(span, heap_span_count * _memory_span_size);+ _rpmalloc_heap_set_reserved_spans(heap, span, remain_span, reserve_count);++ if (remain_count > reserve_count) {+ // Set to global reserved spans+ remain_span = (span_t*)pointer_offset(remain_span, reserve_count * _memory_span_size);+ reserve_count = remain_count - reserve_count;+ _rpmalloc_global_set_reserved_spans(span, remain_span, reserve_count);+ }+ }++ return heap;+}++static heap_t*+_rpmalloc_heap_extract_orphan(heap_t** heap_list) {+ heap_t* heap = *heap_list;+ *heap_list = (heap ? heap->next_orphan : 0);+ return heap;+}++//! Allocate a new heap, potentially reusing a previously orphaned heap+static heap_t*+_rpmalloc_heap_allocate(int first_class) {+ heap_t* heap = 0;+ while (!atomic_cas32_acquire(&_memory_global_lock, 1, 0))+ _rpmalloc_spin();+ if (first_class == 0)+ heap = _rpmalloc_heap_extract_orphan(&_memory_orphan_heaps);+#if RPMALLOC_FIRST_CLASS_HEAPS+ if (!heap)+ heap = _rpmalloc_heap_extract_orphan(&_memory_first_class_orphan_heaps);+#endif+ if (!heap)+ heap = _rpmalloc_heap_allocate_new();+ atomic_store32_release(&_memory_global_lock, 0);+ _rpmalloc_heap_cache_adopt_deferred(heap, 0);+ return heap;+}++extern thread_local bool RpThreadShutdown;++static void+_rpmalloc_heap_release(void* heapptr, int first_class, int release_cache) {+ heap_t* heap = (heap_t*)heapptr;+ if (!heap)+ return;+ RpThreadShutdown = true;+ //Release thread cache spans back to global cache+ _rpmalloc_heap_cache_adopt_deferred(heap, 0);+ if (release_cache || heap->finalize) {+#if ENABLE_THREAD_CACHE+ for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) {+ span_cache_t* span_cache;+ if (!iclass)+ span_cache = &heap->span_cache;+ else+ span_cache = (span_cache_t*)(heap->span_large_cache + (iclass - 1));+ if (!span_cache->count)+ continue;+#if ENABLE_GLOBAL_CACHE+ if (heap->finalize) {+ for (size_t ispan = 0; ispan < span_cache->count; ++ispan)+ _rpmalloc_span_unmap(span_cache->span[ispan]);+ } else {+ _rpmalloc_stat_add64(&heap->thread_to_global, span_cache->count * (iclass + 1) * _memory_span_size);+ _rpmalloc_stat_add(&heap->span_use[iclass].spans_to_global, span_cache->count);+ _rpmalloc_global_cache_insert_spans(span_cache->span, iclass + 1, span_cache->count);+ }+#else+ for (size_t ispan = 0; ispan < span_cache->count; ++ispan)+ _rpmalloc_span_unmap(span_cache->span[ispan]);+#endif+ span_cache->count = 0;+ }+#endif+ }++ if (get_thread_heap_raw() == heap)+ set_thread_heap(0);++#if ENABLE_STATISTICS+ atomic_decr32(&_memory_active_heaps);+ rpmalloc_assert(atomic_load32(&_memory_active_heaps) >= 0, "Still active heaps during finalization");+#endif++ // If we are forcibly terminating with _exit the state of the+ // lock atomic is unknown and it's best to just go ahead and exit+ if (get_thread_id() != _rpmalloc_main_thread_id) {+ while (!atomic_cas32_acquire(&_memory_global_lock, 1, 0))+ _rpmalloc_spin();+ }+ _rpmalloc_heap_orphan(heap, first_class);+ atomic_store32_release(&_memory_global_lock, 0);+}++static void+_rpmalloc_heap_release_raw(void* heapptr, int release_cache) {+ _rpmalloc_heap_release(heapptr, 0, release_cache);+}++static void+_rpmalloc_heap_release_raw_fc(void* heapptr) {+ _rpmalloc_heap_release_raw(heapptr, 1);+}++static void+_rpmalloc_heap_finalize(heap_t* heap) {+ if (heap->spans_reserved) {+ span_t* span = _rpmalloc_span_map(heap, heap->spans_reserved);+ _rpmalloc_span_unmap(span);+ heap->spans_reserved = 0;+ }++ _rpmalloc_heap_cache_adopt_deferred(heap, 0);++ for (size_t iclass = 0; iclass < SIZE_CLASS_COUNT; ++iclass) {+ if (heap->size_class[iclass].cache)+ _rpmalloc_span_unmap(heap->size_class[iclass].cache);+ heap->size_class[iclass].cache = 0;+ span_t* span = heap->size_class[iclass].partial_span;+ while (span) {+ span_t* next = span->next;+ _rpmalloc_span_finalize(heap, iclass, span, &heap->size_class[iclass].partial_span);+ span = next;+ }+ // If class still has a free list it must be a full span+ if (heap->size_class[iclass].free_list) {+ span_t* class_span = (span_t*)((uintptr_t)heap->size_class[iclass].free_list & _memory_span_mask);+ span_t** list = 0;+#if RPMALLOC_FIRST_CLASS_HEAPS+ list = &heap->full_span[iclass];+#endif+ --heap->full_span_count;+ if (!_rpmalloc_span_finalize(heap, iclass, class_span, list)) {+ if (list)+ _rpmalloc_span_double_link_list_remove(list, class_span);+ _rpmalloc_span_double_link_list_add(&heap->size_class[iclass].partial_span, class_span);+ }+ }+ }++#if ENABLE_THREAD_CACHE+ for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) {+ span_cache_t* span_cache;+ if (!iclass)+ span_cache = &heap->span_cache;+ else+ span_cache = (span_cache_t*)(heap->span_large_cache + (iclass - 1));+ for (size_t ispan = 0; ispan < span_cache->count; ++ispan)+ _rpmalloc_span_unmap(span_cache->span[ispan]);+ span_cache->count = 0;+ }+#endif+ rpmalloc_assert(!atomic_load_ptr(&heap->span_free_deferred), "Heaps still active during finalization");+}+++////////////+///+/// Allocation entry points+///+//////++//! Pop first block from a free list+static void*+free_list_pop(void** list) {+ void* block = *list;+ *list = *((void**)block);+ return block;+}++//! Allocate a small/medium sized memory block from the given heap+static void*+_rpmalloc_allocate_from_heap_fallback(heap_t* heap, heap_size_class_t* heap_size_class, uint32_t class_idx) {+ span_t* span = heap_size_class->partial_span;+ if (EXPECTED(span != 0)) {+ rpmalloc_assert(span->block_count == _memory_size_class[span->size_class].block_count, "Span block count corrupted");+ rpmalloc_assert(!_rpmalloc_span_is_fully_utilized(span), "Internal failure");+ void* block;+ if (span->free_list) {+ //Span local free list is not empty, swap to size class free list+ block = free_list_pop(&span->free_list);+ heap_size_class->free_list = span->free_list;+ span->free_list = 0;+ } else {+ //If the span did not fully initialize free list, link up another page worth of blocks + void* block_start = pointer_offset(span, SPAN_HEADER_SIZE + ((size_t)span->free_list_limit * span->block_size));+ span->free_list_limit += free_list_partial_init(&heap_size_class->free_list, &block,+ (void*)((uintptr_t)block_start & ~(_memory_page_size - 1)), block_start,+ span->block_count - span->free_list_limit, span->block_size);+ }+ rpmalloc_assert(span->free_list_limit <= span->block_count, "Span block count corrupted");+ span->used_count = span->free_list_limit;++ //Swap in deferred free list if present+ if (atomic_load_ptr(&span->free_list_deferred))+ _rpmalloc_span_extract_free_list_deferred(span);++ //If span is still not fully utilized keep it in partial list and early return block+ if (!_rpmalloc_span_is_fully_utilized(span))+ return block;++ //The span is fully utilized, unlink from partial list and add to fully utilized list+ _rpmalloc_span_double_link_list_pop_head(&heap_size_class->partial_span, span);+#if RPMALLOC_FIRST_CLASS_HEAPS+ _rpmalloc_span_double_link_list_add(&heap->full_span[class_idx], span);+#endif+ ++heap->full_span_count;+ return block;+ }++ //Find a span in one of the cache levels+ span = _rpmalloc_heap_extract_new_span(heap, heap_size_class, 1, class_idx);+ if (EXPECTED(span != 0)) {+ //Mark span as owned by this heap and set base data, return first block+ return _rpmalloc_span_initialize_new(heap, heap_size_class, span, class_idx);+ }++ return 0;+}++//! Allocate a small sized memory block from the given heap+static void*+_rpmalloc_allocate_small(heap_t* heap, size_t size) {+ rpmalloc_assert(heap, "No thread heap");+ //Small sizes have unique size classes+ const uint32_t class_idx = (uint32_t)((size + (SMALL_GRANULARITY - 1)) >> SMALL_GRANULARITY_SHIFT);+ heap_size_class_t* heap_size_class = heap->size_class + class_idx;+ _rpmalloc_stat_inc_alloc(heap, class_idx);+ if (EXPECTED(heap_size_class->free_list != 0))+ return free_list_pop(&heap_size_class->free_list);+ return _rpmalloc_allocate_from_heap_fallback(heap, heap_size_class, class_idx);+}++//! Allocate a medium sized memory block from the given heap+static void*+_rpmalloc_allocate_medium(heap_t* heap, size_t size) {+ rpmalloc_assert(heap, "No thread heap");+ //Calculate the size class index and do a dependent lookup of the final class index (in case of merged classes)+ const uint32_t base_idx = (uint32_t)(SMALL_CLASS_COUNT + ((size - (SMALL_SIZE_LIMIT + 1)) >> MEDIUM_GRANULARITY_SHIFT));+ const uint32_t class_idx = _memory_size_class[base_idx].class_idx;+ heap_size_class_t* heap_size_class = heap->size_class + class_idx;+ _rpmalloc_stat_inc_alloc(heap, class_idx);+ if (EXPECTED(heap_size_class->free_list != 0))+ return free_list_pop(&heap_size_class->free_list);+ return _rpmalloc_allocate_from_heap_fallback(heap, heap_size_class, class_idx);+}++//! Allocate a large sized memory block from the given heap+static void*+_rpmalloc_allocate_large(heap_t* heap, size_t size) {+ rpmalloc_assert(heap, "No thread heap");+ //Calculate number of needed max sized spans (including header)+ //Since this function is never called if size > LARGE_SIZE_LIMIT+ //the span_count is guaranteed to be <= LARGE_CLASS_COUNT+ size += SPAN_HEADER_SIZE;+ size_t span_count = size >> _memory_span_size_shift;+ if (size & (_memory_span_size - 1))+ ++span_count;++ //Find a span in one of the cache levels+ span_t* span = _rpmalloc_heap_extract_new_span(heap, 0, span_count, SIZE_CLASS_LARGE);+ if (!span)+ return span;++ //Mark span as owned by this heap and set base data+ rpmalloc_assert(span->span_count >= span_count, "Internal failure");+ span->size_class = SIZE_CLASS_LARGE;+ span->heap = heap;++#if RPMALLOC_FIRST_CLASS_HEAPS+ _rpmalloc_span_double_link_list_add(&heap->large_huge_span, span);+#endif+ ++heap->full_span_count;++ return pointer_offset(span, SPAN_HEADER_SIZE);+}++//! Allocate a huge block by mapping memory pages directly+static void*+_rpmalloc_allocate_huge(heap_t* heap, size_t size) {+ rpmalloc_assert(heap, "No thread heap");+ _rpmalloc_heap_cache_adopt_deferred(heap, 0);+ size += SPAN_HEADER_SIZE;+ size_t num_pages = size >> _memory_page_size_shift;+ if (size & (_memory_page_size - 1))+ ++num_pages;+ size_t align_offset = 0;+ span_t* span = (span_t*)_rpmalloc_mmap(num_pages * _memory_page_size, &align_offset);+ if (!span)+ return span;++ //Store page count in span_count+ span->size_class = SIZE_CLASS_HUGE;+ span->span_count = (uint32_t)num_pages;+ span->align_offset = (uint32_t)align_offset;+ span->heap = heap;+ _rpmalloc_stat_add_peak(&_huge_pages_current, num_pages, _huge_pages_peak);++#if RPMALLOC_FIRST_CLASS_HEAPS+ _rpmalloc_span_double_link_list_add(&heap->large_huge_span, span);+#endif+ ++heap->full_span_count;++ return pointer_offset(span, SPAN_HEADER_SIZE);+}++//! Allocate a block of the given size+static void*+_rpmalloc_allocate(heap_t* heap, size_t size) {+ _rpmalloc_stat_add64(&_allocation_counter, 1);+ if (EXPECTED(size <= SMALL_SIZE_LIMIT))+ return _rpmalloc_allocate_small(heap, size);+ else if (size <= _memory_medium_size_limit)+ return _rpmalloc_allocate_medium(heap, size);+ else if (size <= LARGE_SIZE_LIMIT)+ return _rpmalloc_allocate_large(heap, size);+ return _rpmalloc_allocate_huge(heap, size);+}++static void*+_rpmalloc_aligned_allocate(heap_t* heap, size_t alignment, size_t size) {+ if (alignment <= SMALL_GRANULARITY)+ return _rpmalloc_allocate(heap, size);++#if ENABLE_VALIDATE_ARGS+ if ((size + alignment) < size) {+ errno = EINVAL;+ return 0;+ }+ if (alignment & (alignment - 1)) {+ errno = EINVAL;+ return 0;+ }+#endif++ if ((alignment <= SPAN_HEADER_SIZE) && (size < _memory_medium_size_limit)) {+ // If alignment is less or equal to span header size (which is power of two),+ // and size aligned to span header size multiples is less than size + alignment,+ // then use natural alignment of blocks to provide alignment+ size_t multiple_size = size ? (size + (SPAN_HEADER_SIZE - 1)) & ~(uintptr_t)(SPAN_HEADER_SIZE - 1) : SPAN_HEADER_SIZE;+ rpmalloc_assert(!(multiple_size % SPAN_HEADER_SIZE), "Failed alignment calculation");+ if (multiple_size <= (size + alignment))+ return _rpmalloc_allocate(heap, multiple_size);+ }++ void* ptr = 0;+ size_t align_mask = alignment - 1;+ if (alignment <= _memory_page_size) {+ ptr = _rpmalloc_allocate(heap, size + alignment);+ if ((uintptr_t)ptr & align_mask) {+ ptr = (void*)(((uintptr_t)ptr & ~(uintptr_t)align_mask) + alignment);+ //Mark as having aligned blocks+ span_t* span = (span_t*)((uintptr_t)ptr & _memory_span_mask);+ span->flags |= SPAN_FLAG_ALIGNED_BLOCKS;+ }+ return ptr;+ }++ // Fallback to mapping new pages for this request. Since pointers passed+ // to rpfree must be able to reach the start of the span by bitmasking of+ // the address with the span size, the returned aligned pointer from this+ // function must be with a span size of the start of the mapped area.+ // In worst case this requires us to loop and map pages until we get a+ // suitable memory address. It also means we can never align to span size+ // or greater, since the span header will push alignment more than one+ // span size away from span start (thus causing pointer mask to give us+ // an invalid span start on free)+ if (alignment & align_mask) {+ errno = EINVAL;+ return 0;+ }+ if (alignment >= _memory_span_size) {+ errno = EINVAL;+ return 0;+ }++ size_t extra_pages = alignment / _memory_page_size;++ // Since each span has a header, we will at least need one extra memory page+ size_t num_pages = 1 + (size / _memory_page_size);+ if (size & (_memory_page_size - 1))+ ++num_pages;++ if (extra_pages > num_pages)+ num_pages = 1 + extra_pages;++ size_t original_pages = num_pages;+ size_t limit_pages = (_memory_span_size / _memory_page_size) * 2;+ if (limit_pages < (original_pages * 2))+ limit_pages = original_pages * 2;++ size_t mapped_size, align_offset;+ span_t* span;++retry:+ align_offset = 0;+ mapped_size = num_pages * _memory_page_size;++ span = (span_t*)_rpmalloc_mmap(mapped_size, &align_offset);+ if (!span) {+ errno = ENOMEM;+ return 0;+ }+ ptr = pointer_offset(span, SPAN_HEADER_SIZE);++ if ((uintptr_t)ptr & align_mask)+ ptr = (void*)(((uintptr_t)ptr & ~(uintptr_t)align_mask) + alignment);++ if (((size_t)pointer_diff(ptr, span) >= _memory_span_size) ||+ (pointer_offset(ptr, size) > pointer_offset(span, mapped_size)) ||+ (((uintptr_t)ptr & _memory_span_mask) != (uintptr_t)span)) {+ _rpmalloc_unmap(span, mapped_size, align_offset, mapped_size);+ ++num_pages;+ if (num_pages > limit_pages) {+ errno = EINVAL;+ return 0;+ }+ goto retry;+ }++ //Store page count in span_count+ span->size_class = SIZE_CLASS_HUGE;+ span->span_count = (uint32_t)num_pages;+ span->align_offset = (uint32_t)align_offset;+ span->heap = heap;+ _rpmalloc_stat_add_peak(&_huge_pages_current, num_pages, _huge_pages_peak);++#if RPMALLOC_FIRST_CLASS_HEAPS+ _rpmalloc_span_double_link_list_add(&heap->large_huge_span, span);+#endif+ ++heap->full_span_count;++ _rpmalloc_stat_add64(&_allocation_counter, 1);++ return ptr;+}+++////////////+///+/// Deallocation entry points+///+//////++//! Deallocate the given small/medium memory block in the current thread local heap+static void+_rpmalloc_deallocate_direct_small_or_medium(span_t* span, void* block) {+ heap_t* heap = span->heap;+ rpmalloc_assert(heap->owner_thread == get_thread_id() || !heap->owner_thread || heap->finalize, "Internal failure");+ //Add block to free list+ if (UNEXPECTED(_rpmalloc_span_is_fully_utilized(span))) {+ span->used_count = span->block_count;+#if RPMALLOC_FIRST_CLASS_HEAPS+ _rpmalloc_span_double_link_list_remove(&heap->full_span[span->size_class], span);+#endif+ _rpmalloc_span_double_link_list_add(&heap->size_class[span->size_class].partial_span, span);+ --heap->full_span_count;+ }+ *((void**)block) = span->free_list;+ --span->used_count;+ span->free_list = block;+ if (UNEXPECTED(span->used_count == span->list_size)) {+ // If there are no used blocks it is guaranteed that no other external thread is accessing the span+ if (span->used_count) {+ // Make sure we have synchronized the deferred list and list size by using acquire semantics+ // and guarantee that no external thread is accessing span concurrently+ void* free_list;+ do {+ free_list = atomic_exchange_ptr_acquire(&span->free_list_deferred, INVALID_POINTER);+ } while (free_list == INVALID_POINTER);+ atomic_store_ptr_release(&span->free_list_deferred, free_list);+ }+ _rpmalloc_span_double_link_list_remove(&heap->size_class[span->size_class].partial_span, span);+ _rpmalloc_span_release_to_cache(heap, span);+ }+}++static void+_rpmalloc_deallocate_defer_free_span(heap_t* heap, span_t* span) {+ if (span->size_class != SIZE_CLASS_HUGE)+ _rpmalloc_stat_inc(&heap->span_use[span->span_count - 1].spans_deferred);+ //This list does not need ABA protection, no mutable side state+ do {+ span->free_list = (void*)atomic_load_ptr(&heap->span_free_deferred);+ } while (!atomic_cas_ptr(&heap->span_free_deferred, span, span->free_list));+}++//! Put the block in the deferred free list of the owning span+static void+_rpmalloc_deallocate_defer_small_or_medium(span_t* span, void* block) {+ // The memory ordering here is a bit tricky, to avoid having to ABA protect+ // the deferred free list to avoid desynchronization of list and list size+ // we need to have acquire semantics on successful CAS of the pointer to+ // guarantee the list_size variable validity + release semantics on pointer store+ void* free_list;+ do {+ free_list = atomic_exchange_ptr_acquire(&span->free_list_deferred, INVALID_POINTER);+ } while (free_list == INVALID_POINTER);+ *((void**)block) = free_list;+ uint32_t free_count = ++span->list_size;+ int all_deferred_free = (free_count == span->block_count);+ atomic_store_ptr_release(&span->free_list_deferred, block);+ if (all_deferred_free) {+ // Span was completely freed by this block. Due to the INVALID_POINTER spin lock+ // no other thread can reach this state simultaneously on this span.+ // Safe to move to owner heap deferred cache+ _rpmalloc_deallocate_defer_free_span(span->heap, span);+ }+}++static void+_rpmalloc_deallocate_small_or_medium(span_t* span, void* p) {+ _rpmalloc_stat_inc_free(span->heap, span->size_class);+ if (span->flags & SPAN_FLAG_ALIGNED_BLOCKS) {+ //Realign pointer to block start+ void* blocks_start = pointer_offset(span, SPAN_HEADER_SIZE);+ uint32_t block_offset = (uint32_t)pointer_diff(p, blocks_start);+ p = pointer_offset(p, -(int32_t)(block_offset % span->block_size));+ }+ //Check if block belongs to this heap or if deallocation should be deferred+#if RPMALLOC_FIRST_CLASS_HEAPS+ int defer = (span->heap->owner_thread && (span->heap->owner_thread != get_thread_id()) && !span->heap->finalize);+#else+ int defer = ((span->heap->owner_thread != get_thread_id()) && !span->heap->finalize);+#endif+ if (!defer)+ _rpmalloc_deallocate_direct_small_or_medium(span, p);+ else+ _rpmalloc_deallocate_defer_small_or_medium(span, p);+}++//! Deallocate the given large memory block to the current heap+static void+_rpmalloc_deallocate_large(span_t* span) {+ rpmalloc_assert(span->size_class == SIZE_CLASS_LARGE, "Bad span size class");+ rpmalloc_assert(!(span->flags & SPAN_FLAG_MASTER) || !(span->flags & SPAN_FLAG_SUBSPAN), "Span flag corrupted");+ rpmalloc_assert((span->flags & SPAN_FLAG_MASTER) || (span->flags & SPAN_FLAG_SUBSPAN), "Span flag corrupted");+ //We must always defer (unless finalizing) if from another heap since we cannot touch the list or counters of another heap+#if RPMALLOC_FIRST_CLASS_HEAPS+ int defer = (span->heap->owner_thread && (span->heap->owner_thread != get_thread_id()) && !span->heap->finalize);+#else+ int defer = ((span->heap->owner_thread != get_thread_id()) && !span->heap->finalize);+#endif+ if (defer) {+ _rpmalloc_deallocate_defer_free_span(span->heap, span);+ return;+ }+ rpmalloc_assert(span->heap->full_span_count, "Heap span counter corrupted");+ --span->heap->full_span_count;+#if RPMALLOC_FIRST_CLASS_HEAPS+ _rpmalloc_span_double_link_list_remove(&span->heap->large_huge_span, span);+#endif+#if ENABLE_ADAPTIVE_THREAD_CACHE || ENABLE_STATISTICS+ //Decrease counter+ size_t idx = span->span_count - 1;+ atomic_decr32(&span->heap->span_use[idx].current);+#endif+ heap_t* heap = span->heap;+ rpmalloc_assert(heap, "No thread heap");+#if ENABLE_THREAD_CACHE+ const int set_as_reserved = ((span->span_count > 1) && (heap->span_cache.count == 0) && !heap->finalize && !heap->spans_reserved);+#else+ const int set_as_reserved = ((span->span_count > 1) && !heap->finalize && !heap->spans_reserved);+#endif+ if (set_as_reserved) {+ heap->span_reserve = span;+ heap->spans_reserved = span->span_count;+ if (span->flags & SPAN_FLAG_MASTER) {+ heap->span_reserve_master = span;+ } else { //SPAN_FLAG_SUBSPAN+ span_t* master = (span_t*)pointer_offset(span, -(intptr_t)((size_t)span->offset_from_master * _memory_span_size));+ heap->span_reserve_master = master;+ rpmalloc_assert(master->flags & SPAN_FLAG_MASTER, "Span flag corrupted");+ rpmalloc_assert(atomic_load32(&master->remaining_spans) >= (int32_t)span->span_count, "Master span count corrupted");+ }+ _rpmalloc_stat_inc(&heap->span_use[idx].spans_to_reserved);+ } else {+ //Insert into cache list+ _rpmalloc_heap_cache_insert(heap, span);+ }+}++//! Deallocate the given huge span+static void+_rpmalloc_deallocate_huge(span_t* span) {+ rpmalloc_assert(span->heap, "No span heap");+#if RPMALLOC_FIRST_CLASS_HEAPS+ int defer = (span->heap->owner_thread && (span->heap->owner_thread != get_thread_id()) && !span->heap->finalize);+#else+ int defer = ((span->heap->owner_thread != get_thread_id()) && !span->heap->finalize);+#endif+ if (defer) {+ _rpmalloc_deallocate_defer_free_span(span->heap, span);+ return;+ }+ rpmalloc_assert(span->heap->full_span_count, "Heap span counter corrupted");+ --span->heap->full_span_count;+#if RPMALLOC_FIRST_CLASS_HEAPS+ _rpmalloc_span_double_link_list_remove(&span->heap->large_huge_span, span);+#endif++ //Oversized allocation, page count is stored in span_count+ size_t num_pages = span->span_count;+ _rpmalloc_unmap(span, num_pages * _memory_page_size, span->align_offset, num_pages * _memory_page_size);+ _rpmalloc_stat_sub(&_huge_pages_current, num_pages);+}++//! Deallocate the given block+static void+_rpmalloc_deallocate(void* p) {+ _rpmalloc_stat_add64(&_deallocation_counter, 1);+ //Grab the span (always at start of span, using span alignment)+ span_t* span = (span_t*)((uintptr_t)p & _memory_span_mask);+ if (UNEXPECTED(!span))+ return;+ if (EXPECTED(span->size_class < SIZE_CLASS_COUNT))+ _rpmalloc_deallocate_small_or_medium(span, p);+ else if (span->size_class == SIZE_CLASS_LARGE)+ _rpmalloc_deallocate_large(span);+ else+ _rpmalloc_deallocate_huge(span);+}++////////////+///+/// Reallocation entry points+///+//////++static size_t+_rpmalloc_usable_size(void* p);++//! Reallocate the given block to the given size+static void*+_rpmalloc_reallocate(heap_t* heap, void* p, size_t size, size_t oldsize, unsigned int flags) {+ if (p) {+ //Grab the span using guaranteed span alignment+ span_t* span = (span_t*)((uintptr_t)p & _memory_span_mask);+ if (EXPECTED(span->size_class < SIZE_CLASS_COUNT)) {+ //Small/medium sized block+ rpmalloc_assert(span->span_count == 1, "Span counter corrupted");+ void* blocks_start = pointer_offset(span, SPAN_HEADER_SIZE);+ uint32_t block_offset = (uint32_t)pointer_diff(p, blocks_start);+ uint32_t block_idx = block_offset / span->block_size;+ void* block = pointer_offset(blocks_start, (size_t)block_idx * span->block_size);+ if (!oldsize)+ oldsize = (size_t)((ptrdiff_t)span->block_size - pointer_diff(p, block));+ if ((size_t)span->block_size >= size) {+ //Still fits in block, never mind trying to save memory, but preserve data if alignment changed+ if ((p != block) && !(flags & RPMALLOC_NO_PRESERVE))+ memmove(block, p, oldsize);+ return block;+ }+ } else if (span->size_class == SIZE_CLASS_LARGE) {+ //Large block+ size_t total_size = size + SPAN_HEADER_SIZE;+ size_t num_spans = total_size >> _memory_span_size_shift;+ if (total_size & (_memory_span_mask - 1))+ ++num_spans;+ size_t current_spans = span->span_count;+ void* block = pointer_offset(span, SPAN_HEADER_SIZE);+ if (!oldsize)+ oldsize = (current_spans * _memory_span_size) - (size_t)pointer_diff(p, block) - SPAN_HEADER_SIZE;+ if ((current_spans >= num_spans) && (total_size >= (oldsize / 2))) {+ //Still fits in block, never mind trying to save memory, but preserve data if alignment changed+ if ((p != block) && !(flags & RPMALLOC_NO_PRESERVE))+ memmove(block, p, oldsize);+ return block;+ }+ } else {+ //Oversized block+ size_t total_size = size + SPAN_HEADER_SIZE;+ size_t num_pages = total_size >> _memory_page_size_shift;+ if (total_size & (_memory_page_size - 1))+ ++num_pages;+ //Page count is stored in span_count+ size_t current_pages = span->span_count;+ void* block = pointer_offset(span, SPAN_HEADER_SIZE);+ if (!oldsize)+ oldsize = (current_pages * _memory_page_size) - (size_t)pointer_diff(p, block) - SPAN_HEADER_SIZE;+ if ((current_pages >= num_pages) && (num_pages >= (current_pages / 2))) {+ //Still fits in block, never mind trying to save memory, but preserve data if alignment changed+ if ((p != block) && !(flags & RPMALLOC_NO_PRESERVE))+ memmove(block, p, oldsize);+ return block;+ }+ }+ } else {+ oldsize = 0;+ }++ if (!!(flags & RPMALLOC_GROW_OR_FAIL))+ return 0;++ //Size is greater than block size, need to allocate a new block and deallocate the old+ //Avoid hysteresis by overallocating if increase is small (below 37%)+ size_t lower_bound = oldsize + (oldsize >> 2) + (oldsize >> 3);+ size_t new_size = (size > lower_bound) ? size : ((size > oldsize) ? lower_bound : size);+ void* block = _rpmalloc_allocate(heap, new_size);+ if (p && block) {+ if (!(flags & RPMALLOC_NO_PRESERVE))+ memcpy(block, p, oldsize < new_size ? oldsize : new_size);+ _rpmalloc_deallocate(p);+ }++ return block;+}++static void*+_rpmalloc_aligned_reallocate(heap_t* heap, void* ptr, size_t alignment, size_t size, size_t oldsize,+ unsigned int flags) {+ if (alignment <= SMALL_GRANULARITY)+ return _rpmalloc_reallocate(heap, ptr, size, oldsize, flags);++ int no_alloc = !!(flags & RPMALLOC_GROW_OR_FAIL);+ size_t usablesize = (ptr ? _rpmalloc_usable_size(ptr) : 0);+ if ((usablesize >= size) && !((uintptr_t)ptr & (alignment - 1))) {+ if (no_alloc || (size >= (usablesize / 2)))+ return ptr;+ }+ // Aligned alloc marks span as having aligned blocks+ void* block = (!no_alloc ? _rpmalloc_aligned_allocate(heap, alignment, size) : 0);+ if (EXPECTED(block != 0)) {+ if (!(flags & RPMALLOC_NO_PRESERVE) && ptr) {+ if (!oldsize)+ oldsize = usablesize;+ memcpy(block, ptr, oldsize < size ? oldsize : size);+ }+ _rpmalloc_deallocate(ptr);+ }+ return block;+}+++////////////+///+/// Initialization, finalization and utility+///+//////++//! Get the usable size of the given block+static size_t+_rpmalloc_usable_size(void* p) {+ //Grab the span using guaranteed span alignment+ span_t* span = (span_t*)((uintptr_t)p & _memory_span_mask);+ if (span->size_class < SIZE_CLASS_COUNT) {+ //Small/medium block+ void* blocks_start = pointer_offset(span, SPAN_HEADER_SIZE);+ return span->block_size - ((size_t)pointer_diff(p, blocks_start) % span->block_size);+ }+ if (span->size_class == SIZE_CLASS_LARGE) {+ //Large block+ size_t current_spans = span->span_count;+ return (current_spans * _memory_span_size) - (size_t)pointer_diff(p, span);+ }+ //Oversized block, page count is stored in span_count+ size_t current_pages = span->span_count;+ return (current_pages * _memory_page_size) - (size_t)pointer_diff(p, span);+}++//! Adjust and optimize the size class properties for the given class+static void+_rpmalloc_adjust_size_class(size_t iclass) {+ size_t block_size = _memory_size_class[iclass].block_size;+ size_t block_count = (_memory_span_size - SPAN_HEADER_SIZE) / block_size;++ _memory_size_class[iclass].block_count = (uint16_t)block_count;+ _memory_size_class[iclass].class_idx = (uint16_t)iclass;++ //Check if previous size classes can be merged+ if (iclass >= SMALL_CLASS_COUNT) {+ size_t prevclass = iclass;+ while (prevclass > 0) {+ --prevclass;+ //A class can be merged if number of pages and number of blocks are equal+ if (_memory_size_class[prevclass].block_count == _memory_size_class[iclass].block_count)+ memcpy(_memory_size_class + prevclass, _memory_size_class + iclass, sizeof(_memory_size_class[iclass]));+ else+ break;+ }+ }+}++//! Initialize the allocator and setup global data+TRACY_API int+rpmalloc_initialize(void) {+ if (_rpmalloc_initialized) {+ rpmalloc_thread_initialize();+ return 0;+ }+ return rpmalloc_initialize_config(0);+}++int+rpmalloc_initialize_config(const rpmalloc_config_t* config) {+ if (_rpmalloc_initialized) {+ rpmalloc_thread_initialize();+ return 0;+ }+ _rpmalloc_initialized = 1;++ if (config)+ memcpy(&_memory_config, config, sizeof(rpmalloc_config_t));+ else+ memset(&_memory_config, 0, sizeof(rpmalloc_config_t));++ if (!_memory_config.memory_map || !_memory_config.memory_unmap) {+ _memory_config.memory_map = _rpmalloc_mmap_os;+ _memory_config.memory_unmap = _rpmalloc_unmap_os;+ }++#if PLATFORM_WINDOWS+ SYSTEM_INFO system_info;+ memset(&system_info, 0, sizeof(system_info));+ GetSystemInfo(&system_info);+ _memory_map_granularity = system_info.dwAllocationGranularity;+#else+ _memory_map_granularity = (size_t)sysconf(_SC_PAGESIZE);+#endif++#if RPMALLOC_CONFIGURABLE+ _memory_page_size = _memory_config.page_size;+#else+ _memory_page_size = 0;+#endif+ _memory_huge_pages = 0;+ if (!_memory_page_size) {+#if PLATFORM_WINDOWS+ _memory_page_size = system_info.dwPageSize;+#else+ _memory_page_size = _memory_map_granularity;+ if (_memory_config.enable_huge_pages) {+#if defined(__linux__)+ size_t huge_page_size = 0;+ FILE* meminfo = fopen("/proc/meminfo", "r");+ if (meminfo) {+ char line[128];+ while (!huge_page_size && fgets(line, sizeof(line) - 1, meminfo)) {+ line[sizeof(line) - 1] = 0;+ if (strstr(line, "Hugepagesize:"))+ huge_page_size = (size_t)strtol(line + 13, 0, 10) * 1024;+ }+ fclose(meminfo);+ }+ if (huge_page_size) {+ _memory_huge_pages = 1;+ _memory_page_size = huge_page_size;+ _memory_map_granularity = huge_page_size;+ }+#elif defined(__FreeBSD__)+ int rc;+ size_t sz = sizeof(rc);++ if (sysctlbyname("vm.pmap.pg_ps_enabled", &rc, &sz, NULL, 0) == 0 && rc == 1) {+ _memory_huge_pages = 1;+ _memory_page_size = 2 * 1024 * 1024;+ _memory_map_granularity = _memory_page_size;+ }+#elif defined(__APPLE__) || defined(__NetBSD__)+ _memory_huge_pages = 1;+ _memory_page_size = 2 * 1024 * 1024;+ _memory_map_granularity = _memory_page_size;+#endif+ }+#endif+ } else {+ if (_memory_config.enable_huge_pages)+ _memory_huge_pages = 1;+ }++#if PLATFORM_WINDOWS+ if (_memory_config.enable_huge_pages) {+ HANDLE token = 0;+ size_t large_page_minimum = GetLargePageMinimum();+ if (large_page_minimum)+ OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token);+ if (token) {+ LUID luid;+ if (LookupPrivilegeValue(0, SE_LOCK_MEMORY_NAME, &luid)) {+ TOKEN_PRIVILEGES token_privileges;+ memset(&token_privileges, 0, sizeof(token_privileges));+ token_privileges.PrivilegeCount = 1;+ token_privileges.Privileges[0].Luid = luid;+ token_privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;+ if (AdjustTokenPrivileges(token, FALSE, &token_privileges, 0, 0, 0)) {+ if (GetLastError() == ERROR_SUCCESS)+ _memory_huge_pages = 1;+ }+ }+ CloseHandle(token);+ }+ if (_memory_huge_pages) {+ if (large_page_minimum > _memory_page_size)+ _memory_page_size = large_page_minimum;+ if (large_page_minimum > _memory_map_granularity)+ _memory_map_granularity = large_page_minimum;+ }+ }+#endif++ size_t min_span_size = 256;+ size_t max_page_size;+#if UINTPTR_MAX > 0xFFFFFFFF+ max_page_size = 4096ULL * 1024ULL * 1024ULL;+#else+ max_page_size = 4 * 1024 * 1024;+#endif+ if (_memory_page_size < min_span_size)+ _memory_page_size = min_span_size;+ if (_memory_page_size > max_page_size)+ _memory_page_size = max_page_size;+ _memory_page_size_shift = 0;+ size_t page_size_bit = _memory_page_size;+ while (page_size_bit != 1) {+ ++_memory_page_size_shift;+ page_size_bit >>= 1;+ }+ _memory_page_size = ((size_t)1 << _memory_page_size_shift);++#if RPMALLOC_CONFIGURABLE+ if (!_memory_config.span_size) {+ _memory_span_size = _memory_default_span_size;+ _memory_span_size_shift = _memory_default_span_size_shift;+ _memory_span_mask = _memory_default_span_mask;+ } else {+ size_t span_size = _memory_config.span_size;+ if (span_size > (256 * 1024))+ span_size = (256 * 1024);+ _memory_span_size = 4096;+ _memory_span_size_shift = 12;+ while (_memory_span_size < span_size) {+ _memory_span_size <<= 1;+ ++_memory_span_size_shift;+ }+ _memory_span_mask = ~(uintptr_t)(_memory_span_size - 1);+ }+#endif++ _memory_span_map_count = ( _memory_config.span_map_count ? _memory_config.span_map_count : DEFAULT_SPAN_MAP_COUNT);+ if ((_memory_span_size * _memory_span_map_count) < _memory_page_size)+ _memory_span_map_count = (_memory_page_size / _memory_span_size);+ if ((_memory_page_size >= _memory_span_size) && ((_memory_span_map_count * _memory_span_size) % _memory_page_size))+ _memory_span_map_count = (_memory_page_size / _memory_span_size);+ _memory_heap_reserve_count = (_memory_span_map_count > DEFAULT_SPAN_MAP_COUNT) ? DEFAULT_SPAN_MAP_COUNT : _memory_span_map_count;++ _memory_config.page_size = _memory_page_size;+ _memory_config.span_size = _memory_span_size;+ _memory_config.span_map_count = _memory_span_map_count;+ _memory_config.enable_huge_pages = _memory_huge_pages;++#if ((defined(__APPLE__) || defined(__HAIKU__)) && ENABLE_PRELOAD) || defined(__TINYC__)+ if (pthread_key_create(&_memory_thread_heap, _rpmalloc_heap_release_raw_fc))+ return -1;+#endif+#if defined(_WIN32) && (!defined(BUILD_DYNAMIC_LINK) || !BUILD_DYNAMIC_LINK)+ fls_key = FlsAlloc(&_rpmalloc_thread_destructor);+#endif++ //Setup all small and medium size classes+ size_t iclass = 0;+ _memory_size_class[iclass].block_size = SMALL_GRANULARITY;+ _rpmalloc_adjust_size_class(iclass);+ for (iclass = 1; iclass < SMALL_CLASS_COUNT; ++iclass) {+ size_t size = iclass * SMALL_GRANULARITY;+ _memory_size_class[iclass].block_size = (uint32_t)size;+ _rpmalloc_adjust_size_class(iclass);+ }+ //At least two blocks per span, then fall back to large allocations+ _memory_medium_size_limit = (_memory_span_size - SPAN_HEADER_SIZE) >> 1;+ if (_memory_medium_size_limit > MEDIUM_SIZE_LIMIT)+ _memory_medium_size_limit = MEDIUM_SIZE_LIMIT;+ for (iclass = 0; iclass < MEDIUM_CLASS_COUNT; ++iclass) {+ size_t size = SMALL_SIZE_LIMIT + ((iclass + 1) * MEDIUM_GRANULARITY);+ if (size > _memory_medium_size_limit)+ break;+ _memory_size_class[SMALL_CLASS_COUNT + iclass].block_size = (uint32_t)size;+ _rpmalloc_adjust_size_class(SMALL_CLASS_COUNT + iclass);+ }++ _memory_orphan_heaps = 0;+#if RPMALLOC_FIRST_CLASS_HEAPS+ _memory_first_class_orphan_heaps = 0;+#endif+#if ENABLE_STATISTICS+ atomic_store32(&_memory_active_heaps, 0);+ atomic_store32(&_mapped_pages, 0);+ _mapped_pages_peak = 0;+ atomic_store32(&_master_spans, 0);+ atomic_store32(&_mapped_total, 0);+ atomic_store32(&_unmapped_total, 0);+ atomic_store32(&_mapped_pages_os, 0);+ atomic_store32(&_huge_pages_current, 0);+ _huge_pages_peak = 0;+#endif+ memset(_memory_heaps, 0, sizeof(_memory_heaps));+ atomic_store32_release(&_memory_global_lock, 0);++ //Initialize this thread+ rpmalloc_thread_initialize();+ return 0;+}++//! Finalize the allocator+TRACY_API void+rpmalloc_finalize(void) {+ rpmalloc_thread_finalize(1);+ //rpmalloc_dump_statistics(stdout);++ if (_memory_global_reserve) {+ atomic_add32(&_memory_global_reserve_master->remaining_spans, -(int32_t)_memory_global_reserve_count);+ _memory_global_reserve_master = 0;+ _memory_global_reserve_count = 0;+ _memory_global_reserve = 0;+ }+ atomic_store32_release(&_memory_global_lock, 0); ++ //Free all thread caches and fully free spans+ for (size_t list_idx = 0; list_idx < HEAP_ARRAY_SIZE; ++list_idx) {+ heap_t* heap = _memory_heaps[list_idx];+ while (heap) {+ heap_t* next_heap = heap->next_heap;+ heap->finalize = 1;+ _rpmalloc_heap_global_finalize(heap);+ heap = next_heap;+ }+ }++#if ENABLE_GLOBAL_CACHE+ //Free global caches+ for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass)+ _rpmalloc_global_cache_finalize(&_memory_span_cache[iclass]);+#endif++#if (defined(__APPLE__) || defined(__HAIKU__)) && ENABLE_PRELOAD+ pthread_key_delete(_memory_thread_heap);+#endif+#if defined(_WIN32) && (!defined(BUILD_DYNAMIC_LINK) || !BUILD_DYNAMIC_LINK)+ FlsFree(fls_key);+ fls_key = 0;+#endif+#if ENABLE_STATISTICS+ //If you hit these asserts you probably have memory leaks (perhaps global scope data doing dynamic allocations) or double frees in your code+ rpmalloc_assert(atomic_load32(&_mapped_pages) == 0, "Memory leak detected");+ rpmalloc_assert(atomic_load32(&_mapped_pages_os) == 0, "Memory leak detected");+#endif++ _rpmalloc_initialized = 0;+}++//! Initialize thread, assign heap+TRACY_API void+rpmalloc_thread_initialize(void) {+ if (!get_thread_heap_raw()) {+ heap_t* heap = _rpmalloc_heap_allocate(0);+ if (heap) {+ _rpmalloc_stat_inc(&_memory_active_heaps);+ set_thread_heap(heap);+#if defined(_WIN32) && (!defined(BUILD_DYNAMIC_LINK) || !BUILD_DYNAMIC_LINK)+ FlsSetValue(fls_key, heap);+#endif+ }+ }+}++//! Finalize thread, orphan heap+TRACY_API void+rpmalloc_thread_finalize(int release_caches) {+ heap_t* heap = get_thread_heap_raw();+ if (heap)+ _rpmalloc_heap_release_raw(heap, release_caches);+ set_thread_heap(0);+#if defined(_WIN32) && (!defined(BUILD_DYNAMIC_LINK) || !BUILD_DYNAMIC_LINK)+ FlsSetValue(fls_key, 0);+#endif+}++int+rpmalloc_is_thread_initialized(void) {+ return (get_thread_heap_raw() != 0) ? 1 : 0;+}++const rpmalloc_config_t*+rpmalloc_config(void) {+ return &_memory_config;+}++// Extern interface++TRACY_API RPMALLOC_ALLOCATOR void*+rpmalloc(size_t size) {+#if ENABLE_VALIDATE_ARGS+ if (size >= MAX_ALLOC_SIZE) {+ errno = EINVAL;+ return 0;+ }+#endif+ heap_t* heap = get_thread_heap();+ return _rpmalloc_allocate(heap, size);+}++TRACY_API void+rpfree(void* ptr) {+ _rpmalloc_deallocate(ptr);+}++extern inline RPMALLOC_ALLOCATOR void*+rpcalloc(size_t num, size_t size) {+ size_t total;+#if ENABLE_VALIDATE_ARGS+#if PLATFORM_WINDOWS+ int err = SizeTMult(num, size, &total);+ if ((err != S_OK) || (total >= MAX_ALLOC_SIZE)) {+ errno = EINVAL;+ return 0;+ }+#else+ int err = __builtin_umull_overflow(num, size, &total);+ if (err || (total >= MAX_ALLOC_SIZE)) {+ errno = EINVAL;+ return 0;+ }+#endif+#else+ total = num * size;+#endif+ heap_t* heap = get_thread_heap();+ void* block = _rpmalloc_allocate(heap, total);+ if (block)+ memset(block, 0, total);+ return block;+}++TRACY_API RPMALLOC_ALLOCATOR void*+rprealloc(void* ptr, size_t size) {+#if ENABLE_VALIDATE_ARGS+ if (size >= MAX_ALLOC_SIZE) {+ errno = EINVAL;+ return ptr;+ }+#endif+ heap_t* heap = get_thread_heap();+ return _rpmalloc_reallocate(heap, ptr, size, 0, 0);+}++extern RPMALLOC_ALLOCATOR void*+rpaligned_realloc(void* ptr, size_t alignment, size_t size, size_t oldsize,+ unsigned int flags) {+#if ENABLE_VALIDATE_ARGS+ if ((size + alignment < size) || (alignment > _memory_page_size)) {+ errno = EINVAL;+ return 0;+ }+#endif+ heap_t* heap = get_thread_heap();+ return _rpmalloc_aligned_reallocate(heap, ptr, alignment, size, oldsize, flags);+}++extern RPMALLOC_ALLOCATOR void*+rpaligned_alloc(size_t alignment, size_t size) {+ heap_t* heap = get_thread_heap();+ return _rpmalloc_aligned_allocate(heap, alignment, size);+}++extern inline RPMALLOC_ALLOCATOR void*+rpaligned_calloc(size_t alignment, size_t num, size_t size) {+ size_t total;+#if ENABLE_VALIDATE_ARGS+#if PLATFORM_WINDOWS+ int err = SizeTMult(num, size, &total);+ if ((err != S_OK) || (total >= MAX_ALLOC_SIZE)) {+ errno = EINVAL;+ return 0;+ }+#else+ int err = __builtin_umull_overflow(num, size, &total);+ if (err || (total >= MAX_ALLOC_SIZE)) {+ errno = EINVAL;+ return 0;+ }+#endif+#else+ total = num * size;+#endif+ void* block = rpaligned_alloc(alignment, total);+ if (block)+ memset(block, 0, total);+ return block;+}++extern inline RPMALLOC_ALLOCATOR void*+rpmemalign(size_t alignment, size_t size) {+ return rpaligned_alloc(alignment, size);+}++extern inline int+rpposix_memalign(void **memptr, size_t alignment, size_t size) {+ if (memptr)+ *memptr = rpaligned_alloc(alignment, size);+ else+ return EINVAL;+ return *memptr ? 0 : ENOMEM;+}++extern inline size_t+rpmalloc_usable_size(void* ptr) {+ return (ptr ? _rpmalloc_usable_size(ptr) : 0);+}++extern inline void+rpmalloc_thread_collect(void) {+}++void+rpmalloc_thread_statistics(rpmalloc_thread_statistics_t* stats) {+ memset(stats, 0, sizeof(rpmalloc_thread_statistics_t));+ heap_t* heap = get_thread_heap_raw();+ if (!heap)+ return;++ for (size_t iclass = 0; iclass < SIZE_CLASS_COUNT; ++iclass) {+ size_class_t* size_class = _memory_size_class + iclass;+ span_t* span = heap->size_class[iclass].partial_span;+ while (span) {+ size_t free_count = span->list_size;+ size_t block_count = size_class->block_count;+ if (span->free_list_limit < block_count)+ block_count = span->free_list_limit;+ free_count += (block_count - span->used_count);+ stats->sizecache = free_count * size_class->block_size;+ span = span->next;+ }+ }++#if ENABLE_THREAD_CACHE+ for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) {+ span_cache_t* span_cache;+ if (!iclass)+ span_cache = &heap->span_cache;+ else+ span_cache = (span_cache_t*)(heap->span_large_cache + (iclass - 1));+ stats->spancache = span_cache->count * (iclass + 1) * _memory_span_size;+ }+#endif++ span_t* deferred = (span_t*)atomic_load_ptr(&heap->span_free_deferred);+ while (deferred) {+ if (deferred->size_class != SIZE_CLASS_HUGE)+ stats->spancache = (size_t)deferred->span_count * _memory_span_size;+ deferred = (span_t*)deferred->free_list;+ }++#if ENABLE_STATISTICS+ stats->thread_to_global = (size_t)atomic_load64(&heap->thread_to_global);+ stats->global_to_thread = (size_t)atomic_load64(&heap->global_to_thread);++ for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) {+ stats->span_use[iclass].current = (size_t)atomic_load32(&heap->span_use[iclass].current);+ stats->span_use[iclass].peak = (size_t)atomic_load32(&heap->span_use[iclass].high);+ stats->span_use[iclass].to_global = (size_t)atomic_load32(&heap->span_use[iclass].spans_to_global);+ stats->span_use[iclass].from_global = (size_t)atomic_load32(&heap->span_use[iclass].spans_from_global);+ stats->span_use[iclass].to_cache = (size_t)atomic_load32(&heap->span_use[iclass].spans_to_cache);+ stats->span_use[iclass].from_cache = (size_t)atomic_load32(&heap->span_use[iclass].spans_from_cache);+ stats->span_use[iclass].to_reserved = (size_t)atomic_load32(&heap->span_use[iclass].spans_to_reserved);+ stats->span_use[iclass].from_reserved = (size_t)atomic_load32(&heap->span_use[iclass].spans_from_reserved);+ stats->span_use[iclass].map_calls = (size_t)atomic_load32(&heap->span_use[iclass].spans_map_calls);+ }+ for (size_t iclass = 0; iclass < SIZE_CLASS_COUNT; ++iclass) {+ stats->size_use[iclass].alloc_current = (size_t)atomic_load32(&heap->size_class_use[iclass].alloc_current);+ stats->size_use[iclass].alloc_peak = (size_t)heap->size_class_use[iclass].alloc_peak;+ stats->size_use[iclass].alloc_total = (size_t)atomic_load32(&heap->size_class_use[iclass].alloc_total);+ stats->size_use[iclass].free_total = (size_t)atomic_load32(&heap->size_class_use[iclass].free_total);+ stats->size_use[iclass].spans_to_cache = (size_t)atomic_load32(&heap->size_class_use[iclass].spans_to_cache);+ stats->size_use[iclass].spans_from_cache = (size_t)atomic_load32(&heap->size_class_use[iclass].spans_from_cache);+ stats->size_use[iclass].spans_from_reserved = (size_t)atomic_load32(&heap->size_class_use[iclass].spans_from_reserved);+ stats->size_use[iclass].map_calls = (size_t)atomic_load32(&heap->size_class_use[iclass].spans_map_calls);+ }+#endif+}++void+rpmalloc_global_statistics(rpmalloc_global_statistics_t* stats) {+ memset(stats, 0, sizeof(rpmalloc_global_statistics_t));+#if ENABLE_STATISTICS+ stats->mapped = (size_t)atomic_load32(&_mapped_pages) * _memory_page_size;+ stats->mapped_peak = (size_t)_mapped_pages_peak * _memory_page_size;+ stats->mapped_total = (size_t)atomic_load32(&_mapped_total) * _memory_page_size;+ stats->unmapped_total = (size_t)atomic_load32(&_unmapped_total) * _memory_page_size;+ stats->huge_alloc = (size_t)atomic_load32(&_huge_pages_current) * _memory_page_size;+ stats->huge_alloc_peak = (size_t)_huge_pages_peak * _memory_page_size;+#endif+#if ENABLE_GLOBAL_CACHE+ for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass)+ stats->cached += _memory_span_cache[iclass].count * (iclass + 1) * _memory_span_size;+#endif+}++#if ENABLE_STATISTICS++static void+_memory_heap_dump_statistics(heap_t* heap, void* file) {+ fprintf(file, "Heap %d stats:\n", heap->id);+ fprintf(file, "Class CurAlloc PeakAlloc TotAlloc TotFree BlkSize BlkCount SpansCur SpansPeak PeakAllocMiB ToCacheMiB FromCacheMiB FromReserveMiB MmapCalls\n");+ for (size_t iclass = 0; iclass < SIZE_CLASS_COUNT; ++iclass) {+ if (!atomic_load32(&heap->size_class_use[iclass].alloc_total))+ continue;+ fprintf(file, "%3u: %10u %10u %10u %10u %8u %8u %8d %9d %13zu %11zu %12zu %14zu %9u\n", (uint32_t)iclass,+ atomic_load32(&heap->size_class_use[iclass].alloc_current),+ heap->size_class_use[iclass].alloc_peak,+ atomic_load32(&heap->size_class_use[iclass].alloc_total),+ atomic_load32(&heap->size_class_use[iclass].free_total),+ _memory_size_class[iclass].block_size,+ _memory_size_class[iclass].block_count,+ atomic_load32(&heap->size_class_use[iclass].spans_current),+ heap->size_class_use[iclass].spans_peak,+ ((size_t)heap->size_class_use[iclass].alloc_peak * (size_t)_memory_size_class[iclass].block_size) / (size_t)(1024 * 1024),+ ((size_t)atomic_load32(&heap->size_class_use[iclass].spans_to_cache) * _memory_span_size) / (size_t)(1024 * 1024),+ ((size_t)atomic_load32(&heap->size_class_use[iclass].spans_from_cache) * _memory_span_size) / (size_t)(1024 * 1024),+ ((size_t)atomic_load32(&heap->size_class_use[iclass].spans_from_reserved) * _memory_span_size) / (size_t)(1024 * 1024),+ atomic_load32(&heap->size_class_use[iclass].spans_map_calls));+ }+ fprintf(file, "Spans Current Peak Deferred PeakMiB Cached ToCacheMiB FromCacheMiB ToReserveMiB FromReserveMiB ToGlobalMiB FromGlobalMiB MmapCalls\n");+ for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) {+ if (!atomic_load32(&heap->span_use[iclass].high) && !atomic_load32(&heap->span_use[iclass].spans_map_calls))+ continue;+ fprintf(file, "%4u: %8d %8u %8u %8zu %7u %11zu %12zu %12zu %14zu %11zu %13zu %10u\n", (uint32_t)(iclass + 1),+ atomic_load32(&heap->span_use[iclass].current),+ atomic_load32(&heap->span_use[iclass].high),+ atomic_load32(&heap->span_use[iclass].spans_deferred),+ ((size_t)atomic_load32(&heap->span_use[iclass].high) * (size_t)_memory_span_size * (iclass + 1)) / (size_t)(1024 * 1024),+#if ENABLE_THREAD_CACHE+ (unsigned int)(!iclass ? heap->span_cache.count : heap->span_large_cache[iclass - 1].count),+ ((size_t)atomic_load32(&heap->span_use[iclass].spans_to_cache) * (iclass + 1) * _memory_span_size) / (size_t)(1024 * 1024),+ ((size_t)atomic_load32(&heap->span_use[iclass].spans_from_cache) * (iclass + 1) * _memory_span_size) / (size_t)(1024 * 1024),+#else+ 0, (size_t)0, (size_t)0,+#endif+ ((size_t)atomic_load32(&heap->span_use[iclass].spans_to_reserved) * (iclass + 1) * _memory_span_size) / (size_t)(1024 * 1024),+ ((size_t)atomic_load32(&heap->span_use[iclass].spans_from_reserved) * (iclass + 1) * _memory_span_size) / (size_t)(1024 * 1024),+ ((size_t)atomic_load32(&heap->span_use[iclass].spans_to_global) * (size_t)_memory_span_size * (iclass + 1)) / (size_t)(1024 * 1024),+ ((size_t)atomic_load32(&heap->span_use[iclass].spans_from_global) * (size_t)_memory_span_size * (iclass + 1)) / (size_t)(1024 * 1024),+ atomic_load32(&heap->span_use[iclass].spans_map_calls));+ }+ fprintf(file, "Full spans: %zu\n", heap->full_span_count);+ fprintf(file, "ThreadToGlobalMiB GlobalToThreadMiB\n");+ fprintf(file, "%17zu %17zu\n", (size_t)atomic_load64(&heap->thread_to_global) / (size_t)(1024 * 1024), (size_t)atomic_load64(&heap->global_to_thread) / (size_t)(1024 * 1024));+}++#endif++void+rpmalloc_dump_statistics(void* file) {+#if ENABLE_STATISTICS+ for (size_t list_idx = 0; list_idx < HEAP_ARRAY_SIZE; ++list_idx) {+ heap_t* heap = _memory_heaps[list_idx];+ while (heap) {+ int need_dump = 0;+ for (size_t iclass = 0; !need_dump && (iclass < SIZE_CLASS_COUNT); ++iclass) {+ if (!atomic_load32(&heap->size_class_use[iclass].alloc_total)) {+ rpmalloc_assert(!atomic_load32(&heap->size_class_use[iclass].free_total), "Heap statistics counter mismatch");+ rpmalloc_assert(!atomic_load32(&heap->size_class_use[iclass].spans_map_calls), "Heap statistics counter mismatch");+ continue;+ }+ need_dump = 1;+ }+ for (size_t iclass = 0; !need_dump && (iclass < LARGE_CLASS_COUNT); ++iclass) {+ if (!atomic_load32(&heap->span_use[iclass].high) && !atomic_load32(&heap->span_use[iclass].spans_map_calls))+ continue;+ need_dump = 1;+ }+ if (need_dump)+ _memory_heap_dump_statistics(heap, file);+ heap = heap->next_heap;+ }+ }+ fprintf(file, "Global stats:\n");+ size_t huge_current = (size_t)atomic_load32(&_huge_pages_current) * _memory_page_size;+ size_t huge_peak = (size_t)_huge_pages_peak * _memory_page_size;+ fprintf(file, "HugeCurrentMiB HugePeakMiB\n");+ fprintf(file, "%14zu %11zu\n", huge_current / (size_t)(1024 * 1024), huge_peak / (size_t)(1024 * 1024));++ fprintf(file, "GlobalCacheMiB\n");+ for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) {+ global_cache_t* cache = _memory_span_cache + iclass;+ size_t global_cache = (size_t)cache->count * iclass * _memory_span_size;++ size_t global_overflow_cache = 0;+ span_t* span = cache->overflow;+ while (span) {+ global_overflow_cache += iclass * _memory_span_size;+ span = span->next;+ }+ if (global_cache || global_overflow_cache || cache->insert_count || cache->extract_count)+ fprintf(file, "%4zu: %8zuMiB (%8zuMiB overflow) %14zu insert %14zu extract\n", iclass + 1, global_cache / (size_t)(1024 * 1024), global_overflow_cache / (size_t)(1024 * 1024), cache->insert_count, cache->extract_count);+ }++ size_t mapped = (size_t)atomic_load32(&_mapped_pages) * _memory_page_size;+ size_t mapped_os = (size_t)atomic_load32(&_mapped_pages_os) * _memory_page_size;+ size_t mapped_peak = (size_t)_mapped_pages_peak * _memory_page_size;+ size_t mapped_total = (size_t)atomic_load32(&_mapped_total) * _memory_page_size;+ size_t unmapped_total = (size_t)atomic_load32(&_unmapped_total) * _memory_page_size;+ fprintf(file, "MappedMiB MappedOSMiB MappedPeakMiB MappedTotalMiB UnmappedTotalMiB\n");+ fprintf(file, "%9zu %11zu %13zu %14zu %16zu\n",+ mapped / (size_t)(1024 * 1024),+ mapped_os / (size_t)(1024 * 1024),+ mapped_peak / (size_t)(1024 * 1024),+ mapped_total / (size_t)(1024 * 1024),+ unmapped_total / (size_t)(1024 * 1024));++ fprintf(file, "\n");+#if 0+ int64_t allocated = atomic_load64(&_allocation_counter);+ int64_t deallocated = atomic_load64(&_deallocation_counter);+ fprintf(file, "Allocation count: %lli\n", allocated);+ fprintf(file, "Deallocation count: %lli\n", deallocated);+ fprintf(file, "Current allocations: %lli\n", (allocated - deallocated));+ fprintf(file, "Master spans: %d\n", atomic_load32(&_master_spans));+ fprintf(file, "Dangling master spans: %d\n", atomic_load32(&_unmapped_master_spans));+#endif+#endif+ (void)sizeof(file);+}++#if RPMALLOC_FIRST_CLASS_HEAPS++extern inline rpmalloc_heap_t*+rpmalloc_heap_acquire(void) {+ // Must be a pristine heap from newly mapped memory pages, or else memory blocks+ // could already be allocated from the heap which would (wrongly) be released when+ // heap is cleared with rpmalloc_heap_free_all(). Also heaps guaranteed to be+ // pristine from the dedicated orphan list can be used.+ heap_t* heap = _rpmalloc_heap_allocate(1);+ heap->owner_thread = 0;+ _rpmalloc_stat_inc(&_memory_active_heaps);+ return heap;+}++extern inline void+rpmalloc_heap_release(rpmalloc_heap_t* heap) {+ if (heap)+ _rpmalloc_heap_release(heap, 1, 1);+}++extern inline RPMALLOC_ALLOCATOR void*+rpmalloc_heap_alloc(rpmalloc_heap_t* heap, size_t size) {+#if ENABLE_VALIDATE_ARGS+ if (size >= MAX_ALLOC_SIZE) {+ errno = EINVAL;+ return 0;+ }+#endif+ return _rpmalloc_allocate(heap, size);+}++extern inline RPMALLOC_ALLOCATOR void*+rpmalloc_heap_aligned_alloc(rpmalloc_heap_t* heap, size_t alignment, size_t size) {+#if ENABLE_VALIDATE_ARGS+ if (size >= MAX_ALLOC_SIZE) {+ errno = EINVAL;+ return 0;+ }+#endif+ return _rpmalloc_aligned_allocate(heap, alignment, size);+}++extern inline RPMALLOC_ALLOCATOR void*+rpmalloc_heap_calloc(rpmalloc_heap_t* heap, size_t num, size_t size) {+ return rpmalloc_heap_aligned_calloc(heap, 0, num, size);+}++extern inline RPMALLOC_ALLOCATOR void*+rpmalloc_heap_aligned_calloc(rpmalloc_heap_t* heap, size_t alignment, size_t num, size_t size) {+ size_t total;+#if ENABLE_VALIDATE_ARGS+#if PLATFORM_WINDOWS+ int err = SizeTMult(num, size, &total);+ if ((err != S_OK) || (total >= MAX_ALLOC_SIZE)) {+ errno = EINVAL;+ return 0;+ }+#else+ int err = __builtin_umull_overflow(num, size, &total);+ if (err || (total >= MAX_ALLOC_SIZE)) {+ errno = EINVAL;+ return 0;+ }+#endif+#else+ total = num * size;+#endif+ void* block = _rpmalloc_aligned_allocate(heap, alignment, total);+ if (block)+ memset(block, 0, total);+ return block;+}++extern inline RPMALLOC_ALLOCATOR void*+rpmalloc_heap_realloc(rpmalloc_heap_t* heap, void* ptr, size_t size, unsigned int flags) {+#if ENABLE_VALIDATE_ARGS+ if (size >= MAX_ALLOC_SIZE) {+ errno = EINVAL;+ return ptr;+ }+#endif+ return _rpmalloc_reallocate(heap, ptr, size, 0, flags);+}++extern inline RPMALLOC_ALLOCATOR void*+rpmalloc_heap_aligned_realloc(rpmalloc_heap_t* heap, void* ptr, size_t alignment, size_t size, unsigned int flags) {+#if ENABLE_VALIDATE_ARGS+ if ((size + alignment < size) || (alignment > _memory_page_size)) {+ errno = EINVAL;+ return 0;+ }+#endif+ return _rpmalloc_aligned_reallocate(heap, ptr, alignment, size, 0, flags); +}++extern inline void+rpmalloc_heap_free(rpmalloc_heap_t* heap, void* ptr) {+ (void)sizeof(heap);+ _rpmalloc_deallocate(ptr);+}++extern inline void+rpmalloc_heap_free_all(rpmalloc_heap_t* heap) {+ span_t* span;+ span_t* next_span;++ _rpmalloc_heap_cache_adopt_deferred(heap, 0);++ for (size_t iclass = 0; iclass < SIZE_CLASS_COUNT; ++iclass) {+ span = heap->size_class[iclass].partial_span;+ while (span) {+ next_span = span->next;+ _rpmalloc_heap_cache_insert(heap, span);+ span = next_span;+ }+ heap->size_class[iclass].partial_span = 0;+ span = heap->full_span[iclass];+ while (span) {+ next_span = span->next;+ _rpmalloc_heap_cache_insert(heap, span);+ span = next_span;+ }+ }+ memset(heap->size_class, 0, sizeof(heap->size_class));+ memset(heap->full_span, 0, sizeof(heap->full_span));++ span = heap->large_huge_span;+ while (span) {+ next_span = span->next;+ if (UNEXPECTED(span->size_class == SIZE_CLASS_HUGE))+ _rpmalloc_deallocate_huge(span);+ else+ _rpmalloc_heap_cache_insert(heap, span);+ span = next_span;+ }+ heap->large_huge_span = 0;+ heap->full_span_count = 0;++#if ENABLE_THREAD_CACHE+ for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) {+ span_cache_t* span_cache;+ if (!iclass)+ span_cache = &heap->span_cache;+ else+ span_cache = (span_cache_t*)(heap->span_large_cache + (iclass - 1));+ if (!span_cache->count)+ continue;+#if ENABLE_GLOBAL_CACHE+ _rpmalloc_stat_add64(&heap->thread_to_global, span_cache->count * (iclass + 1) * _memory_span_size);+ _rpmalloc_stat_add(&heap->span_use[iclass].spans_to_global, span_cache->count);+ _rpmalloc_global_cache_insert_spans(span_cache->span, iclass + 1, span_cache->count);+#else+ for (size_t ispan = 0; ispan < span_cache->count; ++ispan)+ _rpmalloc_span_unmap(span_cache->span[ispan]);+#endif+ span_cache->count = 0;+ }+#endif++#if ENABLE_STATISTICS+ for (size_t iclass = 0; iclass < SIZE_CLASS_COUNT; ++iclass) {+ atomic_store32(&heap->size_class_use[iclass].alloc_current, 0);+ atomic_store32(&heap->size_class_use[iclass].spans_current, 0);+ }+ for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) {+ atomic_store32(&heap->span_use[iclass].current, 0);+ }+#endif+}++extern inline void+rpmalloc_heap_thread_set_current(rpmalloc_heap_t* heap) {+ heap_t* prev_heap = get_thread_heap_raw();+ if (prev_heap != heap) {+ set_thread_heap(heap);+ if (prev_heap)+ rpmalloc_heap_release(prev_heap);+ }+}++#endif++}++#endif
+ cbits/tracy/public/client/tracy_rpmalloc.hpp view
@@ -0,0 +1,363 @@+/* rpmalloc.h - Memory allocator - Public Domain - 2016 Mattias Jansson+ *+ * This library provides a cross-platform lock free thread caching malloc implementation in C11.+ * The latest source code is always available at+ *+ * https://github.com/mjansson/rpmalloc+ *+ * This library is put in the public domain; you can redistribute it and/or modify it without any restrictions.+ *+ */++#pragma once++#include <stddef.h>+#include "../common/TracyApi.h"++namespace tracy+{++#if defined(__clang__) || defined(__GNUC__)+# define RPMALLOC_EXPORT __attribute__((visibility("default")))+# define RPMALLOC_ALLOCATOR +# if (defined(__clang_major__) && (__clang_major__ < 4)) || (defined(__GNUC__) && defined(ENABLE_PRELOAD) && ENABLE_PRELOAD)+# define RPMALLOC_ATTRIB_MALLOC+# define RPMALLOC_ATTRIB_ALLOC_SIZE(size)+# define RPMALLOC_ATTRIB_ALLOC_SIZE2(count, size)+# else+# define RPMALLOC_ATTRIB_MALLOC __attribute__((__malloc__))+# define RPMALLOC_ATTRIB_ALLOC_SIZE(size) __attribute__((alloc_size(size)))+# define RPMALLOC_ATTRIB_ALLOC_SIZE2(count, size) __attribute__((alloc_size(count, size)))+# endif+# define RPMALLOC_CDECL+#elif defined(_MSC_VER)+# define RPMALLOC_EXPORT+# define RPMALLOC_ALLOCATOR __declspec(allocator) __declspec(restrict)+# define RPMALLOC_ATTRIB_MALLOC+# define RPMALLOC_ATTRIB_ALLOC_SIZE(size)+# define RPMALLOC_ATTRIB_ALLOC_SIZE2(count,size)+# define RPMALLOC_CDECL __cdecl+#else+# define RPMALLOC_EXPORT+# define RPMALLOC_ALLOCATOR+# define RPMALLOC_ATTRIB_MALLOC+# define RPMALLOC_ATTRIB_ALLOC_SIZE(size)+# define RPMALLOC_ATTRIB_ALLOC_SIZE2(count,size)+# define RPMALLOC_CDECL+#endif++//! Define RPMALLOC_CONFIGURABLE to enable configuring sizes. Will introduce+// a very small overhead due to some size calculations not being compile time constants+#ifndef RPMALLOC_CONFIGURABLE+#define RPMALLOC_CONFIGURABLE 0+#endif++//! Define RPMALLOC_FIRST_CLASS_HEAPS to enable heap based API (rpmalloc_heap_* functions).+// Will introduce a very small overhead to track fully allocated spans in heaps+#ifndef RPMALLOC_FIRST_CLASS_HEAPS+#define RPMALLOC_FIRST_CLASS_HEAPS 0+#endif++//! Flag to rpaligned_realloc to not preserve content in reallocation+#define RPMALLOC_NO_PRESERVE 1+//! Flag to rpaligned_realloc to fail and return null pointer if grow cannot be done in-place,+// in which case the original pointer is still valid (just like a call to realloc which failes to allocate+// a new block).+#define RPMALLOC_GROW_OR_FAIL 2++typedef struct rpmalloc_global_statistics_t {+ //! Current amount of virtual memory mapped, all of which might not have been committed (only if ENABLE_STATISTICS=1)+ size_t mapped;+ //! Peak amount of virtual memory mapped, all of which might not have been committed (only if ENABLE_STATISTICS=1)+ size_t mapped_peak;+ //! Current amount of memory in global caches for small and medium sizes (<32KiB)+ size_t cached;+ //! Current amount of memory allocated in huge allocations, i.e larger than LARGE_SIZE_LIMIT which is 2MiB by default (only if ENABLE_STATISTICS=1)+ size_t huge_alloc;+ //! Peak amount of memory allocated in huge allocations, i.e larger than LARGE_SIZE_LIMIT which is 2MiB by default (only if ENABLE_STATISTICS=1)+ size_t huge_alloc_peak;+ //! Total amount of memory mapped since initialization (only if ENABLE_STATISTICS=1)+ size_t mapped_total;+ //! Total amount of memory unmapped since initialization (only if ENABLE_STATISTICS=1)+ size_t unmapped_total;+} rpmalloc_global_statistics_t;++typedef struct rpmalloc_thread_statistics_t {+ //! Current number of bytes available in thread size class caches for small and medium sizes (<32KiB)+ size_t sizecache;+ //! Current number of bytes available in thread span caches for small and medium sizes (<32KiB)+ size_t spancache;+ //! Total number of bytes transitioned from thread cache to global cache (only if ENABLE_STATISTICS=1)+ size_t thread_to_global;+ //! Total number of bytes transitioned from global cache to thread cache (only if ENABLE_STATISTICS=1)+ size_t global_to_thread;+ //! Per span count statistics (only if ENABLE_STATISTICS=1)+ struct {+ //! Currently used number of spans+ size_t current;+ //! High water mark of spans used+ size_t peak;+ //! Number of spans transitioned to global cache+ size_t to_global;+ //! Number of spans transitioned from global cache+ size_t from_global;+ //! Number of spans transitioned to thread cache+ size_t to_cache;+ //! Number of spans transitioned from thread cache+ size_t from_cache;+ //! Number of spans transitioned to reserved state+ size_t to_reserved;+ //! Number of spans transitioned from reserved state+ size_t from_reserved;+ //! Number of raw memory map calls (not hitting the reserve spans but resulting in actual OS mmap calls)+ size_t map_calls;+ } span_use[64];+ //! Per size class statistics (only if ENABLE_STATISTICS=1)+ struct {+ //! Current number of allocations+ size_t alloc_current;+ //! Peak number of allocations+ size_t alloc_peak;+ //! Total number of allocations+ size_t alloc_total;+ //! Total number of frees+ size_t free_total;+ //! Number of spans transitioned to cache+ size_t spans_to_cache;+ //! Number of spans transitioned from cache+ size_t spans_from_cache;+ //! Number of spans transitioned from reserved state+ size_t spans_from_reserved;+ //! Number of raw memory map calls (not hitting the reserve spans but resulting in actual OS mmap calls)+ size_t map_calls;+ } size_use[128];+} rpmalloc_thread_statistics_t;++typedef struct rpmalloc_config_t {+ //! Map memory pages for the given number of bytes. The returned address MUST be+ // aligned to the rpmalloc span size, which will always be a power of two.+ // Optionally the function can store an alignment offset in the offset variable+ // in case it performs alignment and the returned pointer is offset from the+ // actual start of the memory region due to this alignment. The alignment offset+ // will be passed to the memory unmap function. The alignment offset MUST NOT be+ // larger than 65535 (storable in an uint16_t), if it is you must use natural+ // alignment to shift it into 16 bits. If you set a memory_map function, you+ // must also set a memory_unmap function or else the default implementation will+ // be used for both. This function must be thread safe, it can be called by+ // multiple threads simultaneously.+ void* (*memory_map)(size_t size, size_t* offset);+ //! Unmap the memory pages starting at address and spanning the given number of bytes.+ // If release is set to non-zero, the unmap is for an entire span range as returned by+ // a previous call to memory_map and that the entire range should be released. The+ // release argument holds the size of the entire span range. If release is set to 0,+ // the unmap is a partial decommit of a subset of the mapped memory range.+ // If you set a memory_unmap function, you must also set a memory_map function or+ // else the default implementation will be used for both. This function must be thread+ // safe, it can be called by multiple threads simultaneously.+ void (*memory_unmap)(void* address, size_t size, size_t offset, size_t release);+ //! Called when an assert fails, if asserts are enabled. Will use the standard assert()+ // if this is not set.+ void (*error_callback)(const char* message);+ //! Called when a call to map memory pages fails (out of memory). If this callback is+ // not set or returns zero the library will return a null pointer in the allocation+ // call. If this callback returns non-zero the map call will be retried. The argument+ // passed is the number of bytes that was requested in the map call. Only used if+ // the default system memory map function is used (memory_map callback is not set).+ int (*map_fail_callback)(size_t size);+ //! Size of memory pages. The page size MUST be a power of two. All memory mapping+ // requests to memory_map will be made with size set to a multiple of the page size.+ // Used if RPMALLOC_CONFIGURABLE is defined to 1, otherwise system page size is used.+ size_t page_size;+ //! Size of a span of memory blocks. MUST be a power of two, and in [4096,262144]+ // range (unless 0 - set to 0 to use the default span size). Used if RPMALLOC_CONFIGURABLE+ // is defined to 1.+ size_t span_size;+ //! Number of spans to map at each request to map new virtual memory blocks. This can+ // be used to minimize the system call overhead at the cost of virtual memory address+ // space. The extra mapped pages will not be written until actually used, so physical+ // committed memory should not be affected in the default implementation. Will be+ // aligned to a multiple of spans that match memory page size in case of huge pages.+ size_t span_map_count;+ //! Enable use of large/huge pages. If this flag is set to non-zero and page size is+ // zero, the allocator will try to enable huge pages and auto detect the configuration.+ // If this is set to non-zero and page_size is also non-zero, the allocator will+ // assume huge pages have been configured and enabled prior to initializing the+ // allocator.+ // For Windows, see https://docs.microsoft.com/en-us/windows/desktop/memory/large-page-support+ // For Linux, see https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt+ int enable_huge_pages;+ //! Respectively allocated pages and huge allocated pages names for systems+ // supporting it to be able to distinguish among anonymous regions.+ const char *page_name;+ const char *huge_page_name;+} rpmalloc_config_t;++//! Initialize allocator with default configuration+TRACY_API int+rpmalloc_initialize(void);++//! Initialize allocator with given configuration+RPMALLOC_EXPORT int+rpmalloc_initialize_config(const rpmalloc_config_t* config);++//! Get allocator configuration+RPMALLOC_EXPORT const rpmalloc_config_t*+rpmalloc_config(void);++//! Finalize allocator+TRACY_API void+rpmalloc_finalize(void);++//! Initialize allocator for calling thread+TRACY_API void+rpmalloc_thread_initialize(void);++//! Finalize allocator for calling thread+TRACY_API void+rpmalloc_thread_finalize(int release_caches);++//! Perform deferred deallocations pending for the calling thread heap+RPMALLOC_EXPORT void+rpmalloc_thread_collect(void);++//! Query if allocator is initialized for calling thread+RPMALLOC_EXPORT int+rpmalloc_is_thread_initialized(void);++//! Get per-thread statistics+RPMALLOC_EXPORT void+rpmalloc_thread_statistics(rpmalloc_thread_statistics_t* stats);++//! Get global statistics+RPMALLOC_EXPORT void+rpmalloc_global_statistics(rpmalloc_global_statistics_t* stats);++//! Dump all statistics in human readable format to file (should be a FILE*)+RPMALLOC_EXPORT void+rpmalloc_dump_statistics(void* file);++//! Allocate a memory block of at least the given size+TRACY_API RPMALLOC_ALLOCATOR void*+rpmalloc(size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(1);++//! Free the given memory block+TRACY_API void+rpfree(void* ptr);++//! Allocate a memory block of at least the given size and zero initialize it+RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*+rpcalloc(size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(1, 2);++//! Reallocate the given block to at least the given size+TRACY_API RPMALLOC_ALLOCATOR void*+rprealloc(void* ptr, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2);++//! Reallocate the given block to at least the given size and alignment,+// with optional control flags (see RPMALLOC_NO_PRESERVE).+// Alignment must be a power of two and a multiple of sizeof(void*),+// and should ideally be less than memory page size. A caveat of rpmalloc+// internals is that this must also be strictly less than the span size (default 64KiB)+RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*+rpaligned_realloc(void* ptr, size_t alignment, size_t size, size_t oldsize, unsigned int flags) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(3);++//! Allocate a memory block of at least the given size and alignment.+// Alignment must be a power of two and a multiple of sizeof(void*),+// and should ideally be less than memory page size. A caveat of rpmalloc+// internals is that this must also be strictly less than the span size (default 64KiB)+RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*+rpaligned_alloc(size_t alignment, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2);++//! Allocate a memory block of at least the given size and alignment, and zero initialize it.+// Alignment must be a power of two and a multiple of sizeof(void*),+// and should ideally be less than memory page size. A caveat of rpmalloc+// internals is that this must also be strictly less than the span size (default 64KiB)+RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*+rpaligned_calloc(size_t alignment, size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(2, 3);++//! Allocate a memory block of at least the given size and alignment.+// Alignment must be a power of two and a multiple of sizeof(void*),+// and should ideally be less than memory page size. A caveat of rpmalloc+// internals is that this must also be strictly less than the span size (default 64KiB)+RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*+rpmemalign(size_t alignment, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2);++//! Allocate a memory block of at least the given size and alignment.+// Alignment must be a power of two and a multiple of sizeof(void*),+// and should ideally be less than memory page size. A caveat of rpmalloc+// internals is that this must also be strictly less than the span size (default 64KiB)+RPMALLOC_EXPORT int+rpposix_memalign(void** memptr, size_t alignment, size_t size);++//! Query the usable size of the given memory block (from given pointer to the end of block)+RPMALLOC_EXPORT size_t+rpmalloc_usable_size(void* ptr);++#if RPMALLOC_FIRST_CLASS_HEAPS++//! Heap type+typedef struct heap_t rpmalloc_heap_t;++//! Acquire a new heap. Will reuse existing released heaps or allocate memory for a new heap+// if none available. Heap API is implemented with the strict assumption that only one single+// thread will call heap functions for a given heap at any given time, no functions are thread safe.+RPMALLOC_EXPORT rpmalloc_heap_t*+rpmalloc_heap_acquire(void);++//! Release a heap (does NOT free the memory allocated by the heap, use rpmalloc_heap_free_all before destroying the heap).+// Releasing a heap will enable it to be reused by other threads. Safe to pass a null pointer.+RPMALLOC_EXPORT void+rpmalloc_heap_release(rpmalloc_heap_t* heap);++//! Allocate a memory block of at least the given size using the given heap.+RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*+rpmalloc_heap_alloc(rpmalloc_heap_t* heap, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2);++//! Allocate a memory block of at least the given size using the given heap. The returned+// block will have the requested alignment. Alignment must be a power of two and a multiple of sizeof(void*),+// and should ideally be less than memory page size. A caveat of rpmalloc+// internals is that this must also be strictly less than the span size (default 64KiB).+RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*+rpmalloc_heap_aligned_alloc(rpmalloc_heap_t* heap, size_t alignment, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(3);++//! Allocate a memory block of at least the given size using the given heap and zero initialize it.+RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*+rpmalloc_heap_calloc(rpmalloc_heap_t* heap, size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(2, 3);++//! Allocate a memory block of at least the given size using the given heap and zero initialize it. The returned+// block will have the requested alignment. Alignment must either be zero, or a power of two and a multiple of sizeof(void*),+// and should ideally be less than memory page size. A caveat of rpmalloc+// internals is that this must also be strictly less than the span size (default 64KiB).+RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*+rpmalloc_heap_aligned_calloc(rpmalloc_heap_t* heap, size_t alignment, size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(2, 3);++//! Reallocate the given block to at least the given size. The memory block MUST be allocated+// by the same heap given to this function.+RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*+rpmalloc_heap_realloc(rpmalloc_heap_t* heap, void* ptr, size_t size, unsigned int flags) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(3);++//! Reallocate the given block to at least the given size. The memory block MUST be allocated+// by the same heap given to this function. The returned block will have the requested alignment.+// Alignment must be either zero, or a power of two and a multiple of sizeof(void*), and should ideally be+// less than memory page size. A caveat of rpmalloc internals is that this must also be strictly less than+// the span size (default 64KiB).+RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*+rpmalloc_heap_aligned_realloc(rpmalloc_heap_t* heap, void* ptr, size_t alignment, size_t size, unsigned int flags) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(4);++//! Free the given memory block from the given heap. The memory block MUST be allocated+// by the same heap given to this function.+RPMALLOC_EXPORT void+rpmalloc_heap_free(rpmalloc_heap_t* heap, void* ptr);++//! Free all memory allocated by the heap+RPMALLOC_EXPORT void+rpmalloc_heap_free_all(rpmalloc_heap_t* heap);++//! Set the given heap as the current heap for the calling thread. A heap MUST only be current heap+// for a single thread, a heap can never be shared between multiple threads. The previous+// current heap for the calling thread is released to be reused by other threads.+RPMALLOC_EXPORT void+rpmalloc_heap_thread_set_current(rpmalloc_heap_t* heap);++#endif++}
+ cbits/tracy/public/common/TracyAlign.hpp view
@@ -0,0 +1,27 @@+#ifndef __TRACYALIGN_HPP__+#define __TRACYALIGN_HPP__++#include <string.h>++#include "TracyForceInline.hpp"++namespace tracy+{++template<typename T>+tracy_force_inline T MemRead( const void* ptr )+{+ T val;+ memcpy( &val, ptr, sizeof( T ) );+ return val;+}++template<typename T>+tracy_force_inline void MemWrite( void* ptr, T val )+{+ memcpy( ptr, &val, sizeof( T ) );+}++}++#endif
+ cbits/tracy/public/common/TracyAlloc.hpp view
@@ -0,0 +1,72 @@+#ifndef __TRACYALLOC_HPP__+#define __TRACYALLOC_HPP__++#include <stdlib.h>++#if defined TRACY_ENABLE && !defined __EMSCRIPTEN__+# include "TracyApi.h"+# include "TracyForceInline.hpp"+# include "../client/tracy_rpmalloc.hpp"+# define TRACY_USE_RPMALLOC+#endif++namespace tracy+{++#ifdef TRACY_USE_RPMALLOC+TRACY_API void InitRpmalloc();+#else+static inline void InitRpmalloc() {}+#endif++static inline void* tracy_malloc( size_t size )+{+#ifdef TRACY_USE_RPMALLOC+ InitRpmalloc();+ return rpmalloc( size );+#else+ return malloc( size );+#endif+}++static inline void* tracy_malloc_fast( size_t size )+{+#ifdef TRACY_USE_RPMALLOC+ return rpmalloc( size );+#else+ return malloc( size );+#endif+}++static inline void tracy_free( void* ptr )+{+#ifdef TRACY_USE_RPMALLOC+ InitRpmalloc();+ rpfree( ptr );+#else+ free( ptr );+#endif+}++static inline void tracy_free_fast( void* ptr )+{+#ifdef TRACY_USE_RPMALLOC+ rpfree( ptr );+#else+ free( ptr );+#endif+}++static inline void* tracy_realloc( void* ptr, size_t size )+{+#ifdef TRACY_USE_RPMALLOC+ InitRpmalloc();+ return rprealloc( ptr, size );+#else+ return realloc( ptr, size );+#endif+}++}++#endif
+ cbits/tracy/public/common/TracyApi.h view
@@ -0,0 +1,16 @@+#ifndef __TRACYAPI_H__+#define __TRACYAPI_H__++#if defined _WIN32+# if defined TRACY_EXPORTS+# define TRACY_API __declspec(dllexport)+# elif defined TRACY_IMPORTS+# define TRACY_API __declspec(dllimport)+# else+# define TRACY_API+# endif+#else+# define TRACY_API __attribute__((visibility("default")))+#endif++#endif // __TRACYAPI_H__
+ cbits/tracy/public/common/TracyColor.hpp view
@@ -0,0 +1,690 @@+#ifndef __TRACYCOLOR_HPP__+#define __TRACYCOLOR_HPP__++namespace tracy+{+struct Color+{+enum ColorType+{+ Snow = 0xfffafa,+ GhostWhite = 0xf8f8ff,+ WhiteSmoke = 0xf5f5f5,+ Gainsboro = 0xdcdcdc,+ FloralWhite = 0xfffaf0,+ OldLace = 0xfdf5e6,+ Linen = 0xfaf0e6,+ AntiqueWhite = 0xfaebd7,+ PapayaWhip = 0xffefd5,+ BlanchedAlmond = 0xffebcd,+ Bisque = 0xffe4c4,+ PeachPuff = 0xffdab9,+ NavajoWhite = 0xffdead,+ Moccasin = 0xffe4b5,+ Cornsilk = 0xfff8dc,+ Ivory = 0xfffff0,+ LemonChiffon = 0xfffacd,+ Seashell = 0xfff5ee,+ Honeydew = 0xf0fff0,+ MintCream = 0xf5fffa,+ Azure = 0xf0ffff,+ AliceBlue = 0xf0f8ff,+ Lavender = 0xe6e6fa,+ LavenderBlush = 0xfff0f5,+ MistyRose = 0xffe4e1,+ White = 0xffffff,+ Black = 0x000000,+ DarkSlateGray = 0x2f4f4f,+ DarkSlateGrey = 0x2f4f4f,+ DimGray = 0x696969,+ DimGrey = 0x696969,+ SlateGray = 0x708090,+ SlateGrey = 0x708090,+ LightSlateGray = 0x778899,+ LightSlateGrey = 0x778899,+ Gray = 0xbebebe,+ Grey = 0xbebebe,+ X11Gray = 0xbebebe,+ X11Grey = 0xbebebe,+ WebGray = 0x808080,+ WebGrey = 0x808080,+ LightGrey = 0xd3d3d3,+ LightGray = 0xd3d3d3,+ MidnightBlue = 0x191970,+ Navy = 0x000080,+ NavyBlue = 0x000080,+ CornflowerBlue = 0x6495ed,+ DarkSlateBlue = 0x483d8b,+ SlateBlue = 0x6a5acd,+ MediumSlateBlue = 0x7b68ee,+ LightSlateBlue = 0x8470ff,+ MediumBlue = 0x0000cd,+ RoyalBlue = 0x4169e1,+ Blue = 0x0000ff,+ DodgerBlue = 0x1e90ff,+ DeepSkyBlue = 0x00bfff,+ SkyBlue = 0x87ceeb,+ LightSkyBlue = 0x87cefa,+ SteelBlue = 0x4682b4,+ LightSteelBlue = 0xb0c4de,+ LightBlue = 0xadd8e6,+ PowderBlue = 0xb0e0e6,+ PaleTurquoise = 0xafeeee,+ DarkTurquoise = 0x00ced1,+ MediumTurquoise = 0x48d1cc,+ Turquoise = 0x40e0d0,+ Cyan = 0x00ffff,+ Aqua = 0x00ffff,+ LightCyan = 0xe0ffff,+ CadetBlue = 0x5f9ea0,+ MediumAquamarine = 0x66cdaa,+ Aquamarine = 0x7fffd4,+ DarkGreen = 0x006400,+ DarkOliveGreen = 0x556b2f,+ DarkSeaGreen = 0x8fbc8f,+ SeaGreen = 0x2e8b57,+ MediumSeaGreen = 0x3cb371,+ LightSeaGreen = 0x20b2aa,+ PaleGreen = 0x98fb98,+ SpringGreen = 0x00ff7f,+ LawnGreen = 0x7cfc00,+ Green = 0x00ff00,+ Lime = 0x00ff00,+ X11Green = 0x00ff00,+ WebGreen = 0x008000,+ Chartreuse = 0x7fff00,+ MediumSpringGreen = 0x00fa9a,+ GreenYellow = 0xadff2f,+ LimeGreen = 0x32cd32,+ YellowGreen = 0x9acd32,+ ForestGreen = 0x228b22,+ OliveDrab = 0x6b8e23,+ DarkKhaki = 0xbdb76b,+ Khaki = 0xf0e68c,+ PaleGoldenrod = 0xeee8aa,+ LightGoldenrodYellow = 0xfafad2,+ LightYellow = 0xffffe0,+ Yellow = 0xffff00,+ Gold = 0xffd700,+ LightGoldenrod = 0xeedd82,+ Goldenrod = 0xdaa520,+ DarkGoldenrod = 0xb8860b,+ RosyBrown = 0xbc8f8f,+ IndianRed = 0xcd5c5c,+ SaddleBrown = 0x8b4513,+ Sienna = 0xa0522d,+ Peru = 0xcd853f,+ Burlywood = 0xdeb887,+ Beige = 0xf5f5dc,+ Wheat = 0xf5deb3,+ SandyBrown = 0xf4a460,+ Tan = 0xd2b48c,+ Chocolate = 0xd2691e,+ Firebrick = 0xb22222,+ Brown = 0xa52a2a,+ DarkSalmon = 0xe9967a,+ Salmon = 0xfa8072,+ LightSalmon = 0xffa07a,+ Orange = 0xffa500,+ DarkOrange = 0xff8c00,+ Coral = 0xff7f50,+ LightCoral = 0xf08080,+ Tomato = 0xff6347,+ OrangeRed = 0xff4500,+ Red = 0xff0000,+ HotPink = 0xff69b4,+ DeepPink = 0xff1493,+ Pink = 0xffc0cb,+ LightPink = 0xffb6c1,+ PaleVioletRed = 0xdb7093,+ Maroon = 0xb03060,+ X11Maroon = 0xb03060,+ WebMaroon = 0x800000,+ MediumVioletRed = 0xc71585,+ VioletRed = 0xd02090,+ Magenta = 0xff00ff,+ Fuchsia = 0xff00ff,+ Violet = 0xee82ee,+ Plum = 0xdda0dd,+ Orchid = 0xda70d6,+ MediumOrchid = 0xba55d3,+ DarkOrchid = 0x9932cc,+ DarkViolet = 0x9400d3,+ BlueViolet = 0x8a2be2,+ Purple = 0xa020f0,+ X11Purple = 0xa020f0,+ WebPurple = 0x800080,+ MediumPurple = 0x9370db,+ Thistle = 0xd8bfd8,+ Snow1 = 0xfffafa,+ Snow2 = 0xeee9e9,+ Snow3 = 0xcdc9c9,+ Snow4 = 0x8b8989,+ Seashell1 = 0xfff5ee,+ Seashell2 = 0xeee5de,+ Seashell3 = 0xcdc5bf,+ Seashell4 = 0x8b8682,+ AntiqueWhite1 = 0xffefdb,+ AntiqueWhite2 = 0xeedfcc,+ AntiqueWhite3 = 0xcdc0b0,+ AntiqueWhite4 = 0x8b8378,+ Bisque1 = 0xffe4c4,+ Bisque2 = 0xeed5b7,+ Bisque3 = 0xcdb79e,+ Bisque4 = 0x8b7d6b,+ PeachPuff1 = 0xffdab9,+ PeachPuff2 = 0xeecbad,+ PeachPuff3 = 0xcdaf95,+ PeachPuff4 = 0x8b7765,+ NavajoWhite1 = 0xffdead,+ NavajoWhite2 = 0xeecfa1,+ NavajoWhite3 = 0xcdb38b,+ NavajoWhite4 = 0x8b795e,+ LemonChiffon1 = 0xfffacd,+ LemonChiffon2 = 0xeee9bf,+ LemonChiffon3 = 0xcdc9a5,+ LemonChiffon4 = 0x8b8970,+ Cornsilk1 = 0xfff8dc,+ Cornsilk2 = 0xeee8cd,+ Cornsilk3 = 0xcdc8b1,+ Cornsilk4 = 0x8b8878,+ Ivory1 = 0xfffff0,+ Ivory2 = 0xeeeee0,+ Ivory3 = 0xcdcdc1,+ Ivory4 = 0x8b8b83,+ Honeydew1 = 0xf0fff0,+ Honeydew2 = 0xe0eee0,+ Honeydew3 = 0xc1cdc1,+ Honeydew4 = 0x838b83,+ LavenderBlush1 = 0xfff0f5,+ LavenderBlush2 = 0xeee0e5,+ LavenderBlush3 = 0xcdc1c5,+ LavenderBlush4 = 0x8b8386,+ MistyRose1 = 0xffe4e1,+ MistyRose2 = 0xeed5d2,+ MistyRose3 = 0xcdb7b5,+ MistyRose4 = 0x8b7d7b,+ Azure1 = 0xf0ffff,+ Azure2 = 0xe0eeee,+ Azure3 = 0xc1cdcd,+ Azure4 = 0x838b8b,+ SlateBlue1 = 0x836fff,+ SlateBlue2 = 0x7a67ee,+ SlateBlue3 = 0x6959cd,+ SlateBlue4 = 0x473c8b,+ RoyalBlue1 = 0x4876ff,+ RoyalBlue2 = 0x436eee,+ RoyalBlue3 = 0x3a5fcd,+ RoyalBlue4 = 0x27408b,+ Blue1 = 0x0000ff,+ Blue2 = 0x0000ee,+ Blue3 = 0x0000cd,+ Blue4 = 0x00008b,+ DodgerBlue1 = 0x1e90ff,+ DodgerBlue2 = 0x1c86ee,+ DodgerBlue3 = 0x1874cd,+ DodgerBlue4 = 0x104e8b,+ SteelBlue1 = 0x63b8ff,+ SteelBlue2 = 0x5cacee,+ SteelBlue3 = 0x4f94cd,+ SteelBlue4 = 0x36648b,+ DeepSkyBlue1 = 0x00bfff,+ DeepSkyBlue2 = 0x00b2ee,+ DeepSkyBlue3 = 0x009acd,+ DeepSkyBlue4 = 0x00688b,+ SkyBlue1 = 0x87ceff,+ SkyBlue2 = 0x7ec0ee,+ SkyBlue3 = 0x6ca6cd,+ SkyBlue4 = 0x4a708b,+ LightSkyBlue1 = 0xb0e2ff,+ LightSkyBlue2 = 0xa4d3ee,+ LightSkyBlue3 = 0x8db6cd,+ LightSkyBlue4 = 0x607b8b,+ SlateGray1 = 0xc6e2ff,+ SlateGray2 = 0xb9d3ee,+ SlateGray3 = 0x9fb6cd,+ SlateGray4 = 0x6c7b8b,+ LightSteelBlue1 = 0xcae1ff,+ LightSteelBlue2 = 0xbcd2ee,+ LightSteelBlue3 = 0xa2b5cd,+ LightSteelBlue4 = 0x6e7b8b,+ LightBlue1 = 0xbfefff,+ LightBlue2 = 0xb2dfee,+ LightBlue3 = 0x9ac0cd,+ LightBlue4 = 0x68838b,+ LightCyan1 = 0xe0ffff,+ LightCyan2 = 0xd1eeee,+ LightCyan3 = 0xb4cdcd,+ LightCyan4 = 0x7a8b8b,+ PaleTurquoise1 = 0xbbffff,+ PaleTurquoise2 = 0xaeeeee,+ PaleTurquoise3 = 0x96cdcd,+ PaleTurquoise4 = 0x668b8b,+ CadetBlue1 = 0x98f5ff,+ CadetBlue2 = 0x8ee5ee,+ CadetBlue3 = 0x7ac5cd,+ CadetBlue4 = 0x53868b,+ Turquoise1 = 0x00f5ff,+ Turquoise2 = 0x00e5ee,+ Turquoise3 = 0x00c5cd,+ Turquoise4 = 0x00868b,+ Cyan1 = 0x00ffff,+ Cyan2 = 0x00eeee,+ Cyan3 = 0x00cdcd,+ Cyan4 = 0x008b8b,+ DarkSlateGray1 = 0x97ffff,+ DarkSlateGray2 = 0x8deeee,+ DarkSlateGray3 = 0x79cdcd,+ DarkSlateGray4 = 0x528b8b,+ Aquamarine1 = 0x7fffd4,+ Aquamarine2 = 0x76eec6,+ Aquamarine3 = 0x66cdaa,+ Aquamarine4 = 0x458b74,+ DarkSeaGreen1 = 0xc1ffc1,+ DarkSeaGreen2 = 0xb4eeb4,+ DarkSeaGreen3 = 0x9bcd9b,+ DarkSeaGreen4 = 0x698b69,+ SeaGreen1 = 0x54ff9f,+ SeaGreen2 = 0x4eee94,+ SeaGreen3 = 0x43cd80,+ SeaGreen4 = 0x2e8b57,+ PaleGreen1 = 0x9aff9a,+ PaleGreen2 = 0x90ee90,+ PaleGreen3 = 0x7ccd7c,+ PaleGreen4 = 0x548b54,+ SpringGreen1 = 0x00ff7f,+ SpringGreen2 = 0x00ee76,+ SpringGreen3 = 0x00cd66,+ SpringGreen4 = 0x008b45,+ Green1 = 0x00ff00,+ Green2 = 0x00ee00,+ Green3 = 0x00cd00,+ Green4 = 0x008b00,+ Chartreuse1 = 0x7fff00,+ Chartreuse2 = 0x76ee00,+ Chartreuse3 = 0x66cd00,+ Chartreuse4 = 0x458b00,+ OliveDrab1 = 0xc0ff3e,+ OliveDrab2 = 0xb3ee3a,+ OliveDrab3 = 0x9acd32,+ OliveDrab4 = 0x698b22,+ DarkOliveGreen1 = 0xcaff70,+ DarkOliveGreen2 = 0xbcee68,+ DarkOliveGreen3 = 0xa2cd5a,+ DarkOliveGreen4 = 0x6e8b3d,+ Khaki1 = 0xfff68f,+ Khaki2 = 0xeee685,+ Khaki3 = 0xcdc673,+ Khaki4 = 0x8b864e,+ LightGoldenrod1 = 0xffec8b,+ LightGoldenrod2 = 0xeedc82,+ LightGoldenrod3 = 0xcdbe70,+ LightGoldenrod4 = 0x8b814c,+ LightYellow1 = 0xffffe0,+ LightYellow2 = 0xeeeed1,+ LightYellow3 = 0xcdcdb4,+ LightYellow4 = 0x8b8b7a,+ Yellow1 = 0xffff00,+ Yellow2 = 0xeeee00,+ Yellow3 = 0xcdcd00,+ Yellow4 = 0x8b8b00,+ Gold1 = 0xffd700,+ Gold2 = 0xeec900,+ Gold3 = 0xcdad00,+ Gold4 = 0x8b7500,+ Goldenrod1 = 0xffc125,+ Goldenrod2 = 0xeeb422,+ Goldenrod3 = 0xcd9b1d,+ Goldenrod4 = 0x8b6914,+ DarkGoldenrod1 = 0xffb90f,+ DarkGoldenrod2 = 0xeead0e,+ DarkGoldenrod3 = 0xcd950c,+ DarkGoldenrod4 = 0x8b6508,+ RosyBrown1 = 0xffc1c1,+ RosyBrown2 = 0xeeb4b4,+ RosyBrown3 = 0xcd9b9b,+ RosyBrown4 = 0x8b6969,+ IndianRed1 = 0xff6a6a,+ IndianRed2 = 0xee6363,+ IndianRed3 = 0xcd5555,+ IndianRed4 = 0x8b3a3a,+ Sienna1 = 0xff8247,+ Sienna2 = 0xee7942,+ Sienna3 = 0xcd6839,+ Sienna4 = 0x8b4726,+ Burlywood1 = 0xffd39b,+ Burlywood2 = 0xeec591,+ Burlywood3 = 0xcdaa7d,+ Burlywood4 = 0x8b7355,+ Wheat1 = 0xffe7ba,+ Wheat2 = 0xeed8ae,+ Wheat3 = 0xcdba96,+ Wheat4 = 0x8b7e66,+ Tan1 = 0xffa54f,+ Tan2 = 0xee9a49,+ Tan3 = 0xcd853f,+ Tan4 = 0x8b5a2b,+ Chocolate1 = 0xff7f24,+ Chocolate2 = 0xee7621,+ Chocolate3 = 0xcd661d,+ Chocolate4 = 0x8b4513,+ Firebrick1 = 0xff3030,+ Firebrick2 = 0xee2c2c,+ Firebrick3 = 0xcd2626,+ Firebrick4 = 0x8b1a1a,+ Brown1 = 0xff4040,+ Brown2 = 0xee3b3b,+ Brown3 = 0xcd3333,+ Brown4 = 0x8b2323,+ Salmon1 = 0xff8c69,+ Salmon2 = 0xee8262,+ Salmon3 = 0xcd7054,+ Salmon4 = 0x8b4c39,+ LightSalmon1 = 0xffa07a,+ LightSalmon2 = 0xee9572,+ LightSalmon3 = 0xcd8162,+ LightSalmon4 = 0x8b5742,+ Orange1 = 0xffa500,+ Orange2 = 0xee9a00,+ Orange3 = 0xcd8500,+ Orange4 = 0x8b5a00,+ DarkOrange1 = 0xff7f00,+ DarkOrange2 = 0xee7600,+ DarkOrange3 = 0xcd6600,+ DarkOrange4 = 0x8b4500,+ Coral1 = 0xff7256,+ Coral2 = 0xee6a50,+ Coral3 = 0xcd5b45,+ Coral4 = 0x8b3e2f,+ Tomato1 = 0xff6347,+ Tomato2 = 0xee5c42,+ Tomato3 = 0xcd4f39,+ Tomato4 = 0x8b3626,+ OrangeRed1 = 0xff4500,+ OrangeRed2 = 0xee4000,+ OrangeRed3 = 0xcd3700,+ OrangeRed4 = 0x8b2500,+ Red1 = 0xff0000,+ Red2 = 0xee0000,+ Red3 = 0xcd0000,+ Red4 = 0x8b0000,+ DeepPink1 = 0xff1493,+ DeepPink2 = 0xee1289,+ DeepPink3 = 0xcd1076,+ DeepPink4 = 0x8b0a50,+ HotPink1 = 0xff6eb4,+ HotPink2 = 0xee6aa7,+ HotPink3 = 0xcd6090,+ HotPink4 = 0x8b3a62,+ Pink1 = 0xffb5c5,+ Pink2 = 0xeea9b8,+ Pink3 = 0xcd919e,+ Pink4 = 0x8b636c,+ LightPink1 = 0xffaeb9,+ LightPink2 = 0xeea2ad,+ LightPink3 = 0xcd8c95,+ LightPink4 = 0x8b5f65,+ PaleVioletRed1 = 0xff82ab,+ PaleVioletRed2 = 0xee799f,+ PaleVioletRed3 = 0xcd6889,+ PaleVioletRed4 = 0x8b475d,+ Maroon1 = 0xff34b3,+ Maroon2 = 0xee30a7,+ Maroon3 = 0xcd2990,+ Maroon4 = 0x8b1c62,+ VioletRed1 = 0xff3e96,+ VioletRed2 = 0xee3a8c,+ VioletRed3 = 0xcd3278,+ VioletRed4 = 0x8b2252,+ Magenta1 = 0xff00ff,+ Magenta2 = 0xee00ee,+ Magenta3 = 0xcd00cd,+ Magenta4 = 0x8b008b,+ Orchid1 = 0xff83fa,+ Orchid2 = 0xee7ae9,+ Orchid3 = 0xcd69c9,+ Orchid4 = 0x8b4789,+ Plum1 = 0xffbbff,+ Plum2 = 0xeeaeee,+ Plum3 = 0xcd96cd,+ Plum4 = 0x8b668b,+ MediumOrchid1 = 0xe066ff,+ MediumOrchid2 = 0xd15fee,+ MediumOrchid3 = 0xb452cd,+ MediumOrchid4 = 0x7a378b,+ DarkOrchid1 = 0xbf3eff,+ DarkOrchid2 = 0xb23aee,+ DarkOrchid3 = 0x9a32cd,+ DarkOrchid4 = 0x68228b,+ Purple1 = 0x9b30ff,+ Purple2 = 0x912cee,+ Purple3 = 0x7d26cd,+ Purple4 = 0x551a8b,+ MediumPurple1 = 0xab82ff,+ MediumPurple2 = 0x9f79ee,+ MediumPurple3 = 0x8968cd,+ MediumPurple4 = 0x5d478b,+ Thistle1 = 0xffe1ff,+ Thistle2 = 0xeed2ee,+ Thistle3 = 0xcdb5cd,+ Thistle4 = 0x8b7b8b,+ Gray0 = 0x000000,+ Grey0 = 0x000000,+ Gray1 = 0x030303,+ Grey1 = 0x030303,+ Gray2 = 0x050505,+ Grey2 = 0x050505,+ Gray3 = 0x080808,+ Grey3 = 0x080808,+ Gray4 = 0x0a0a0a,+ Grey4 = 0x0a0a0a,+ Gray5 = 0x0d0d0d,+ Grey5 = 0x0d0d0d,+ Gray6 = 0x0f0f0f,+ Grey6 = 0x0f0f0f,+ Gray7 = 0x121212,+ Grey7 = 0x121212,+ Gray8 = 0x141414,+ Grey8 = 0x141414,+ Gray9 = 0x171717,+ Grey9 = 0x171717,+ Gray10 = 0x1a1a1a,+ Grey10 = 0x1a1a1a,+ Gray11 = 0x1c1c1c,+ Grey11 = 0x1c1c1c,+ Gray12 = 0x1f1f1f,+ Grey12 = 0x1f1f1f,+ Gray13 = 0x212121,+ Grey13 = 0x212121,+ Gray14 = 0x242424,+ Grey14 = 0x242424,+ Gray15 = 0x262626,+ Grey15 = 0x262626,+ Gray16 = 0x292929,+ Grey16 = 0x292929,+ Gray17 = 0x2b2b2b,+ Grey17 = 0x2b2b2b,+ Gray18 = 0x2e2e2e,+ Grey18 = 0x2e2e2e,+ Gray19 = 0x303030,+ Grey19 = 0x303030,+ Gray20 = 0x333333,+ Grey20 = 0x333333,+ Gray21 = 0x363636,+ Grey21 = 0x363636,+ Gray22 = 0x383838,+ Grey22 = 0x383838,+ Gray23 = 0x3b3b3b,+ Grey23 = 0x3b3b3b,+ Gray24 = 0x3d3d3d,+ Grey24 = 0x3d3d3d,+ Gray25 = 0x404040,+ Grey25 = 0x404040,+ Gray26 = 0x424242,+ Grey26 = 0x424242,+ Gray27 = 0x454545,+ Grey27 = 0x454545,+ Gray28 = 0x474747,+ Grey28 = 0x474747,+ Gray29 = 0x4a4a4a,+ Grey29 = 0x4a4a4a,+ Gray30 = 0x4d4d4d,+ Grey30 = 0x4d4d4d,+ Gray31 = 0x4f4f4f,+ Grey31 = 0x4f4f4f,+ Gray32 = 0x525252,+ Grey32 = 0x525252,+ Gray33 = 0x545454,+ Grey33 = 0x545454,+ Gray34 = 0x575757,+ Grey34 = 0x575757,+ Gray35 = 0x595959,+ Grey35 = 0x595959,+ Gray36 = 0x5c5c5c,+ Grey36 = 0x5c5c5c,+ Gray37 = 0x5e5e5e,+ Grey37 = 0x5e5e5e,+ Gray38 = 0x616161,+ Grey38 = 0x616161,+ Gray39 = 0x636363,+ Grey39 = 0x636363,+ Gray40 = 0x666666,+ Grey40 = 0x666666,+ Gray41 = 0x696969,+ Grey41 = 0x696969,+ Gray42 = 0x6b6b6b,+ Grey42 = 0x6b6b6b,+ Gray43 = 0x6e6e6e,+ Grey43 = 0x6e6e6e,+ Gray44 = 0x707070,+ Grey44 = 0x707070,+ Gray45 = 0x737373,+ Grey45 = 0x737373,+ Gray46 = 0x757575,+ Grey46 = 0x757575,+ Gray47 = 0x787878,+ Grey47 = 0x787878,+ Gray48 = 0x7a7a7a,+ Grey48 = 0x7a7a7a,+ Gray49 = 0x7d7d7d,+ Grey49 = 0x7d7d7d,+ Gray50 = 0x7f7f7f,+ Grey50 = 0x7f7f7f,+ Gray51 = 0x828282,+ Grey51 = 0x828282,+ Gray52 = 0x858585,+ Grey52 = 0x858585,+ Gray53 = 0x878787,+ Grey53 = 0x878787,+ Gray54 = 0x8a8a8a,+ Grey54 = 0x8a8a8a,+ Gray55 = 0x8c8c8c,+ Grey55 = 0x8c8c8c,+ Gray56 = 0x8f8f8f,+ Grey56 = 0x8f8f8f,+ Gray57 = 0x919191,+ Grey57 = 0x919191,+ Gray58 = 0x949494,+ Grey58 = 0x949494,+ Gray59 = 0x969696,+ Grey59 = 0x969696,+ Gray60 = 0x999999,+ Grey60 = 0x999999,+ Gray61 = 0x9c9c9c,+ Grey61 = 0x9c9c9c,+ Gray62 = 0x9e9e9e,+ Grey62 = 0x9e9e9e,+ Gray63 = 0xa1a1a1,+ Grey63 = 0xa1a1a1,+ Gray64 = 0xa3a3a3,+ Grey64 = 0xa3a3a3,+ Gray65 = 0xa6a6a6,+ Grey65 = 0xa6a6a6,+ Gray66 = 0xa8a8a8,+ Grey66 = 0xa8a8a8,+ Gray67 = 0xababab,+ Grey67 = 0xababab,+ Gray68 = 0xadadad,+ Grey68 = 0xadadad,+ Gray69 = 0xb0b0b0,+ Grey69 = 0xb0b0b0,+ Gray70 = 0xb3b3b3,+ Grey70 = 0xb3b3b3,+ Gray71 = 0xb5b5b5,+ Grey71 = 0xb5b5b5,+ Gray72 = 0xb8b8b8,+ Grey72 = 0xb8b8b8,+ Gray73 = 0xbababa,+ Grey73 = 0xbababa,+ Gray74 = 0xbdbdbd,+ Grey74 = 0xbdbdbd,+ Gray75 = 0xbfbfbf,+ Grey75 = 0xbfbfbf,+ Gray76 = 0xc2c2c2,+ Grey76 = 0xc2c2c2,+ Gray77 = 0xc4c4c4,+ Grey77 = 0xc4c4c4,+ Gray78 = 0xc7c7c7,+ Grey78 = 0xc7c7c7,+ Gray79 = 0xc9c9c9,+ Grey79 = 0xc9c9c9,+ Gray80 = 0xcccccc,+ Grey80 = 0xcccccc,+ Gray81 = 0xcfcfcf,+ Grey81 = 0xcfcfcf,+ Gray82 = 0xd1d1d1,+ Grey82 = 0xd1d1d1,+ Gray83 = 0xd4d4d4,+ Grey83 = 0xd4d4d4,+ Gray84 = 0xd6d6d6,+ Grey84 = 0xd6d6d6,+ Gray85 = 0xd9d9d9,+ Grey85 = 0xd9d9d9,+ Gray86 = 0xdbdbdb,+ Grey86 = 0xdbdbdb,+ Gray87 = 0xdedede,+ Grey87 = 0xdedede,+ Gray88 = 0xe0e0e0,+ Grey88 = 0xe0e0e0,+ Gray89 = 0xe3e3e3,+ Grey89 = 0xe3e3e3,+ Gray90 = 0xe5e5e5,+ Grey90 = 0xe5e5e5,+ Gray91 = 0xe8e8e8,+ Grey91 = 0xe8e8e8,+ Gray92 = 0xebebeb,+ Grey92 = 0xebebeb,+ Gray93 = 0xededed,+ Grey93 = 0xededed,+ Gray94 = 0xf0f0f0,+ Grey94 = 0xf0f0f0,+ Gray95 = 0xf2f2f2,+ Grey95 = 0xf2f2f2,+ Gray96 = 0xf5f5f5,+ Grey96 = 0xf5f5f5,+ Gray97 = 0xf7f7f7,+ Grey97 = 0xf7f7f7,+ Gray98 = 0xfafafa,+ Grey98 = 0xfafafa,+ Gray99 = 0xfcfcfc,+ Grey99 = 0xfcfcfc,+ Gray100 = 0xffffff,+ Grey100 = 0xffffff,+ DarkGrey = 0xa9a9a9,+ DarkGray = 0xa9a9a9,+ DarkBlue = 0x00008b,+ DarkCyan = 0x008b8b,+ DarkMagenta = 0x8b008b,+ DarkRed = 0x8b0000,+ LightGreen = 0x90ee90,+ Crimson = 0xdc143c,+ Indigo = 0x4b0082,+ Olive = 0x808000,+ RebeccaPurple = 0x663399,+ Silver = 0xc0c0c0,+ Teal = 0x008080,+};+};+}++#endif
+ cbits/tracy/public/common/TracyForceInline.hpp view
@@ -0,0 +1,20 @@+#ifndef __TRACYFORCEINLINE_HPP__+#define __TRACYFORCEINLINE_HPP__++#if defined(__GNUC__)+# define tracy_force_inline __attribute__((always_inline)) inline+#elif defined(_MSC_VER)+# define tracy_force_inline __forceinline+#else+# define tracy_force_inline inline+#endif++#if defined(__GNUC__)+# define tracy_no_inline __attribute__((noinline))+#elif defined(_MSC_VER)+# define tracy_no_inline __declspec(noinline)+#else+# define tracy_no_inline+#endif++#endif
+ cbits/tracy/public/common/TracyMutex.hpp view
@@ -0,0 +1,24 @@+#ifndef __TRACYMUTEX_HPP__+#define __TRACYMUTEX_HPP__++#if defined _MSC_VER++# include <shared_mutex>++namespace tracy+{+using TracyMutex = std::shared_mutex;+}++#else++#include <mutex>++namespace tracy+{+using TracyMutex = std::mutex;+}++#endif++#endif
+ cbits/tracy/public/common/TracyProtocol.hpp view
@@ -0,0 +1,169 @@+#ifndef __TRACYPROTOCOL_HPP__+#define __TRACYPROTOCOL_HPP__++#include <limits>+#include <stdint.h>++namespace tracy+{++constexpr unsigned Lz4CompressBound( unsigned isize ) { return isize + ( isize / 255 ) + 16; }++enum : uint32_t { ProtocolVersion = 74 };+enum : uint16_t { BroadcastVersion = 3 };++using lz4sz_t = uint32_t;++enum { TargetFrameSize = 256 * 1024 };+enum { LZ4Size = Lz4CompressBound( TargetFrameSize ) };+static_assert( LZ4Size <= (std::numeric_limits<lz4sz_t>::max)(), "LZ4Size greater than lz4sz_t" );+static_assert( TargetFrameSize * 2 >= 64 * 1024, "Not enough space for LZ4 stream buffer" );++enum { HandshakeShibbolethSize = 8 };+static const char HandshakeShibboleth[HandshakeShibbolethSize] = { 'T', 'r', 'a', 'c', 'y', 'P', 'r', 'f' };++enum HandshakeStatus : uint8_t+{+ HandshakePending,+ HandshakeWelcome,+ HandshakeProtocolMismatch,+ HandshakeNotAvailable,+ HandshakeDropped+};++enum { WelcomeMessageProgramNameSize = 64 };+enum { WelcomeMessageHostInfoSize = 1024 };++#pragma pack( push, 1 )++// Must increase left query space after handling!+enum ServerQuery : uint8_t+{+ ServerQueryTerminate,+ ServerQueryString,+ ServerQueryThreadString,+ ServerQuerySourceLocation,+ ServerQueryPlotName,+ ServerQueryFrameName,+ ServerQueryParameter,+ ServerQueryFiberName,+ ServerQueryExternalName,+ // Items above are high priority. Split order must be preserved. See IsQueryPrio().+ ServerQueryDisconnect,+ ServerQueryCallstackFrame,+ ServerQuerySymbol,+ ServerQuerySymbolCode,+ ServerQuerySourceCode,+ ServerQueryDataTransfer,+ ServerQueryDataTransferPart+};++struct ServerQueryPacket+{+ ServerQuery type;+ uint64_t ptr;+ uint32_t extra;+};++enum { ServerQueryPacketSize = sizeof( ServerQueryPacket ) };+++enum CpuArchitecture : uint8_t+{+ CpuArchUnknown,+ CpuArchX86,+ CpuArchX64,+ CpuArchArm32,+ CpuArchArm64+};+++struct WelcomeFlag+{+ enum _t : uint8_t+ {+ OnDemand = 1 << 0,+ IsApple = 1 << 1,+ CodeTransfer = 1 << 2,+ CombineSamples = 1 << 3,+ IdentifySamples = 1 << 4,+ };+};++struct WelcomeMessage+{+ double timerMul;+ int64_t initBegin;+ int64_t initEnd;+ uint64_t delay;+ uint64_t resolution;+ uint64_t epoch;+ uint64_t exectime;+ uint64_t pid;+ int64_t samplingPeriod;+ uint8_t flags;+ uint8_t cpuArch;+ char cpuManufacturer[12];+ uint32_t cpuId;+ char programName[WelcomeMessageProgramNameSize];+ char hostInfo[WelcomeMessageHostInfoSize];+};++enum { WelcomeMessageSize = sizeof( WelcomeMessage ) };+++struct OnDemandPayloadMessage+{+ uint64_t frames;+ uint64_t currentTime;+};++enum { OnDemandPayloadMessageSize = sizeof( OnDemandPayloadMessage ) };+++struct BroadcastMessage+{+ uint16_t broadcastVersion;+ uint16_t listenPort;+ uint32_t protocolVersion;+ uint64_t pid;+ int32_t activeTime; // in seconds+ char programName[WelcomeMessageProgramNameSize];+};++struct BroadcastMessage_v2+{+ uint16_t broadcastVersion;+ uint16_t listenPort;+ uint32_t protocolVersion;+ int32_t activeTime;+ char programName[WelcomeMessageProgramNameSize];+};++struct BroadcastMessage_v1+{+ uint32_t broadcastVersion;+ uint32_t protocolVersion;+ uint32_t listenPort;+ uint32_t activeTime;+ char programName[WelcomeMessageProgramNameSize];+};++struct BroadcastMessage_v0+{+ uint32_t broadcastVersion;+ uint32_t protocolVersion;+ uint32_t activeTime;+ char programName[WelcomeMessageProgramNameSize];+};++enum { BroadcastMessageSize = sizeof( BroadcastMessage ) };+enum { BroadcastMessageSize_v2 = sizeof( BroadcastMessage_v2 ) };+enum { BroadcastMessageSize_v1 = sizeof( BroadcastMessage_v1 ) };+enum { BroadcastMessageSize_v0 = sizeof( BroadcastMessage_v0 ) };++#pragma pack( pop )++}++#endif
+ cbits/tracy/public/common/TracyQueue.hpp view
@@ -0,0 +1,926 @@+#ifndef __TRACYQUEUE_HPP__+#define __TRACYQUEUE_HPP__++#include <stddef.h>+#include <stdint.h>++namespace tracy+{++enum class QueueType : uint8_t+{+ ZoneText,+ ZoneName,+ Message,+ MessageColor,+ MessageCallstack,+ MessageColorCallstack,+ MessageAppInfo,+ ZoneBeginAllocSrcLoc,+ ZoneBeginAllocSrcLocCallstack,+ CallstackSerial,+ Callstack,+ CallstackAlloc,+ CallstackSample,+ CallstackSampleContextSwitch,+ FrameImage,+ ZoneBegin,+ ZoneBeginCallstack,+ ZoneEnd,+ LockWait,+ LockObtain,+ LockRelease,+ LockSharedWait,+ LockSharedObtain,+ LockSharedRelease,+ LockName,+ MemAlloc,+ MemAllocNamed,+ MemFree,+ MemFreeNamed,+ MemAllocCallstack,+ MemAllocCallstackNamed,+ MemFreeCallstack,+ MemFreeCallstackNamed,+ MemDiscard,+ MemDiscardCallstack,+ GpuZoneBegin,+ GpuZoneBeginCallstack,+ GpuZoneBeginAllocSrcLoc,+ GpuZoneBeginAllocSrcLocCallstack,+ GpuZoneEnd,+ GpuZoneBeginSerial,+ GpuZoneBeginCallstackSerial,+ GpuZoneBeginAllocSrcLocSerial,+ GpuZoneBeginAllocSrcLocCallstackSerial,+ GpuZoneEndSerial,+ PlotDataInt,+ PlotDataFloat,+ PlotDataDouble,+ ContextSwitch,+ ThreadWakeup,+ GpuTime,+ GpuContextName,+ CallstackFrameSize,+ SymbolInformation,+ ExternalNameMetadata,+ SymbolCodeMetadata,+ SourceCodeMetadata,+ FiberEnter,+ FiberLeave,+ Terminate,+ KeepAlive,+ ThreadContext,+ GpuCalibration,+ GpuTimeSync,+ Crash,+ CrashReport,+ ZoneValidation,+ ZoneColor,+ ZoneValue,+ FrameMarkMsg,+ FrameMarkMsgStart,+ FrameMarkMsgEnd,+ FrameVsync,+ SourceLocation,+ LockAnnounce,+ LockTerminate,+ LockMark,+ MessageLiteral,+ MessageLiteralColor,+ MessageLiteralCallstack,+ MessageLiteralColorCallstack,+ GpuNewContext,+ CallstackFrame,+ SysTimeReport,+ SysPowerReport,+ TidToPid,+ HwSampleCpuCycle,+ HwSampleInstructionRetired,+ HwSampleCacheReference,+ HwSampleCacheMiss,+ HwSampleBranchRetired,+ HwSampleBranchMiss,+ PlotConfig,+ ParamSetup,+ AckServerQueryNoop,+ AckSourceCodeNotAvailable,+ AckSymbolCodeNotAvailable,+ CpuTopology,+ SingleStringData,+ SecondStringData,+ MemNamePayload,+ ThreadGroupHint,+ StringData,+ ThreadName,+ PlotName,+ SourceLocationPayload,+ CallstackPayload,+ CallstackAllocPayload,+ FrameName,+ FrameImageData,+ ExternalName,+ ExternalThreadName,+ SymbolCode,+ SourceCode,+ FiberName,+ NUM_TYPES+};++#pragma pack( push, 1 )++struct QueueThreadContext+{+ uint32_t thread;+};++struct QueueZoneBeginLean+{+ int64_t time;+};++struct QueueZoneBegin : public QueueZoneBeginLean+{+ uint64_t srcloc; // ptr+};++struct QueueZoneBeginThread : public QueueZoneBegin+{+ uint32_t thread;+};++struct QueueZoneEnd+{+ int64_t time;+};++struct QueueZoneEndThread : public QueueZoneEnd+{+ uint32_t thread;+};++struct QueueZoneValidation+{+ uint32_t id;+};++struct QueueZoneValidationThread : public QueueZoneValidation+{+ uint32_t thread;+};++struct QueueZoneColor+{+ uint8_t b;+ uint8_t g;+ uint8_t r;+};++struct QueueZoneColorThread : public QueueZoneColor+{+ uint32_t thread;+};++struct QueueZoneValue+{+ uint64_t value;+};++struct QueueZoneValueThread : public QueueZoneValue+{+ uint32_t thread;+};++struct QueueStringTransfer+{+ uint64_t ptr;+};++struct QueueFrameMark+{+ int64_t time;+ uint64_t name; // ptr+};++struct QueueFrameVsync+{+ int64_t time;+ uint32_t id;+};++struct QueueFrameImage+{+ uint32_t frame;+ uint16_t w;+ uint16_t h;+ uint8_t flip;+};++struct QueueFrameImageFat : public QueueFrameImage+{+ uint64_t image; // ptr+};++struct QueueSourceLocation+{+ uint64_t name;+ uint64_t function; // ptr+ uint64_t file; // ptr+ uint32_t line;+ uint8_t b;+ uint8_t g;+ uint8_t r;+};++struct QueueZoneTextFat+{+ uint64_t text; // ptr+ uint16_t size;+};++struct QueueZoneTextFatThread : public QueueZoneTextFat+{+ uint32_t thread;+};++enum class LockType : uint8_t+{+ Lockable,+ SharedLockable+};++struct QueueLockAnnounce+{+ uint32_t id;+ int64_t time;+ uint64_t lckloc; // ptr+ LockType type;+};++struct QueueFiberEnter+{+ int64_t time;+ uint64_t fiber; // ptr+ uint32_t thread;+ int32_t groupHint;+};++struct QueueFiberLeave+{+ int64_t time;+ uint32_t thread;+};++struct QueueLockTerminate+{+ uint32_t id;+ int64_t time;+};++struct QueueLockWait+{+ uint32_t thread;+ uint32_t id;+ int64_t time;+};++struct QueueLockObtain+{+ uint32_t thread;+ uint32_t id;+ int64_t time;+};++struct QueueLockRelease+{+ uint32_t id;+ int64_t time;+};++struct QueueLockReleaseShared : public QueueLockRelease+{+ uint32_t thread;+};++struct QueueLockMark+{+ uint32_t thread;+ uint32_t id;+ uint64_t srcloc; // ptr+};++struct QueueLockName+{+ uint32_t id;+};++struct QueueLockNameFat : public QueueLockName+{+ uint64_t name; // ptr+ uint16_t size;+};++struct QueuePlotDataBase+{+ uint64_t name; // ptr+ int64_t time;+};++struct QueuePlotDataInt : public QueuePlotDataBase+{+ int64_t val;+};++struct QueuePlotDataFloat : public QueuePlotDataBase +{+ float val;+};++struct QueuePlotDataDouble : public QueuePlotDataBase+{+ double val;+};++struct QueueMessage+{+ int64_t time;+};++struct QueueMessageColor : public QueueMessage+{+ uint8_t b;+ uint8_t g;+ uint8_t r;+};++struct QueueMessageLiteral : public QueueMessage+{+ uint64_t text; // ptr+};++struct QueueMessageLiteralThread : public QueueMessageLiteral+{+ uint32_t thread;+};++struct QueueMessageColorLiteral : public QueueMessageColor+{+ uint64_t text; // ptr+};++struct QueueMessageColorLiteralThread : public QueueMessageColorLiteral+{+ uint32_t thread;+};++struct QueueMessageFat : public QueueMessage+{+ uint64_t text; // ptr+ uint16_t size;+};++struct QueueMessageFatThread : public QueueMessageFat+{+ uint32_t thread;+};++struct QueueMessageColorFat : public QueueMessageColor+{+ uint64_t text; // ptr+ uint16_t size;+};++struct QueueMessageColorFatThread : public QueueMessageColorFat+{+ uint32_t thread;+};++// Don't change order, only add new entries at the end, this is also used on trace dumps!+enum class GpuContextType : uint8_t+{+ Invalid,+ OpenGl,+ Vulkan,+ OpenCL,+ Direct3D12,+ Direct3D11,+ Metal,+ Custom,+ CUDA+};++enum GpuContextFlags : uint8_t+{+ GpuContextCalibration = 1 << 0+};++struct QueueGpuNewContext+{+ int64_t cpuTime;+ int64_t gpuTime;+ uint32_t thread;+ float period;+ uint8_t context;+ GpuContextFlags flags;+ GpuContextType type;+};++struct QueueGpuZoneBeginLean+{+ int64_t cpuTime;+ uint32_t thread;+ uint16_t queryId;+ uint8_t context;+};++struct QueueGpuZoneBegin : public QueueGpuZoneBeginLean+{+ uint64_t srcloc;+};++struct QueueGpuZoneEnd+{+ int64_t cpuTime;+ uint32_t thread;+ uint16_t queryId;+ uint8_t context;+};++struct QueueGpuTime+{+ int64_t gpuTime;+ uint16_t queryId;+ uint8_t context;+};++struct QueueGpuCalibration+{+ int64_t gpuTime;+ int64_t cpuTime;+ int64_t cpuDelta;+ uint8_t context;+};++struct QueueGpuTimeSync+{+ int64_t gpuTime;+ int64_t cpuTime;+ uint8_t context;+};+ +struct QueueGpuContextName+{+ uint8_t context;+};++struct QueueGpuContextNameFat : public QueueGpuContextName+{+ uint64_t ptr;+ uint16_t size;+};++struct QueueMemNamePayload+{+ uint64_t name;+};++struct QueueThreadGroupHint+{+ uint32_t thread;+ int32_t groupHint;+};++struct QueueMemAlloc+{+ int64_t time;+ uint32_t thread;+ uint64_t ptr;+ char size[6];+};++struct QueueMemFree+{+ int64_t time;+ uint32_t thread;+ uint64_t ptr;+};++struct QueueMemDiscard+{+ int64_t time;+ uint32_t thread;+ uint64_t name;+};++struct QueueCallstackFat+{+ uint64_t ptr;+};++struct QueueCallstackFatThread : public QueueCallstackFat+{+ uint32_t thread;+};++struct QueueCallstackAllocFat+{+ uint64_t ptr;+ uint64_t nativePtr;+};++struct QueueCallstackAllocFatThread : public QueueCallstackAllocFat+{+ uint32_t thread;+};++struct QueueCallstackSample+{+ int64_t time;+ uint32_t thread;+};++struct QueueCallstackSampleFat : public QueueCallstackSample+{+ uint64_t ptr;+};++struct QueueCallstackFrameSize+{+ uint64_t ptr;+ uint8_t size;+};++struct QueueCallstackFrameSizeFat : public QueueCallstackFrameSize+{+ uint64_t data;+ uint64_t imageName;+};++struct QueueCallstackFrame+{+ uint32_t line;+ uint64_t symAddr;+ uint32_t symLen;+};++struct QueueSymbolInformation+{+ uint32_t line;+ uint64_t symAddr;+};++struct QueueSymbolInformationFat : public QueueSymbolInformation+{+ uint64_t fileString;+ uint8_t needFree;+};++struct QueueCrashReport+{+ int64_t time;+ uint64_t text; // ptr+};++struct QueueCrashReportThread+{+ uint32_t thread;+};++struct QueueSysTime+{+ int64_t time;+ float sysTime;+};++struct QueueSysPower+{+ int64_t time;+ uint64_t delta;+ uint64_t name; // ptr+};++struct QueueContextSwitch+{+ int64_t time;+ uint32_t oldThread;+ uint32_t newThread;+ uint8_t cpu;+ uint8_t oldThreadWaitReason;+ uint8_t oldThreadState;+ uint8_t previousCState;+ int8_t newThreadPriority;+ int8_t oldThreadPriority;+};++struct QueueThreadWakeup+{+ int64_t time;+ uint32_t thread;+ uint8_t cpu;+ int8_t adjustReason;+ int8_t adjustIncrement;+};++struct QueueTidToPid+{+ uint64_t tid;+ uint64_t pid;+};++struct QueueHwSample+{+ uint64_t ip;+ int64_t time;+};++enum class PlotFormatType : uint8_t+{+ Number,+ Memory,+ Percentage+};++struct QueuePlotConfig+{+ uint64_t name; // ptr+ uint8_t type;+ uint8_t step;+ uint8_t fill;+ uint32_t color;+};++struct QueueParamSetup+{+ uint32_t idx;+ uint64_t name; // ptr+ uint8_t isBool;+ int32_t val;+};++struct QueueSourceCodeNotAvailable+{+ uint32_t id;+};++struct QueueCpuTopology+{+ uint32_t package;+ uint32_t die;+ uint32_t core;+ uint32_t thread;+};++struct QueueExternalNameMetadata+{+ uint64_t thread;+ uint64_t name;+ uint64_t threadName;+};++struct QueueSymbolCodeMetadata+{+ uint64_t symbol;+ uint64_t ptr;+ uint32_t size;+};++struct QueueSourceCodeMetadata+{+ uint64_t ptr;+ uint32_t size;+ uint32_t id;+};++struct QueueHeader+{+ union+ {+ QueueType type;+ uint8_t idx;+ };+};++struct QueueItem+{+ QueueHeader hdr;+ union+ {+ QueueThreadContext threadCtx;+ QueueZoneBegin zoneBegin;+ QueueZoneBeginLean zoneBeginLean;+ QueueZoneBeginThread zoneBeginThread;+ QueueZoneEnd zoneEnd;+ QueueZoneEndThread zoneEndThread;+ QueueZoneValidation zoneValidation;+ QueueZoneValidationThread zoneValidationThread;+ QueueZoneColor zoneColor;+ QueueZoneColorThread zoneColorThread;+ QueueZoneValue zoneValue;+ QueueZoneValueThread zoneValueThread;+ QueueStringTransfer stringTransfer;+ QueueFrameMark frameMark;+ QueueFrameVsync frameVsync;+ QueueFrameImage frameImage;+ QueueFrameImageFat frameImageFat;+ QueueSourceLocation srcloc;+ QueueZoneTextFat zoneTextFat;+ QueueZoneTextFatThread zoneTextFatThread;+ QueueLockAnnounce lockAnnounce;+ QueueLockTerminate lockTerminate;+ QueueLockWait lockWait;+ QueueLockObtain lockObtain;+ QueueLockRelease lockRelease;+ QueueLockReleaseShared lockReleaseShared;+ QueueLockMark lockMark;+ QueueLockName lockName;+ QueueLockNameFat lockNameFat;+ QueuePlotDataInt plotDataInt;+ QueuePlotDataFloat plotDataFloat;+ QueuePlotDataDouble plotDataDouble;+ QueueMessage message;+ QueueMessageColor messageColor;+ QueueMessageLiteral messageLiteral;+ QueueMessageLiteralThread messageLiteralThread;+ QueueMessageColorLiteral messageColorLiteral;+ QueueMessageColorLiteralThread messageColorLiteralThread;+ QueueMessageFat messageFat;+ QueueMessageFatThread messageFatThread;+ QueueMessageColorFat messageColorFat;+ QueueMessageColorFatThread messageColorFatThread;+ QueueGpuNewContext gpuNewContext;+ QueueGpuZoneBegin gpuZoneBegin;+ QueueGpuZoneBeginLean gpuZoneBeginLean;+ QueueGpuZoneEnd gpuZoneEnd;+ QueueGpuTime gpuTime;+ QueueGpuCalibration gpuCalibration;+ QueueGpuTimeSync gpuTimeSync;+ QueueGpuContextName gpuContextName;+ QueueGpuContextNameFat gpuContextNameFat;+ QueueMemAlloc memAlloc;+ QueueMemFree memFree;+ QueueMemDiscard memDiscard;+ QueueMemNamePayload memName;+ QueueThreadGroupHint threadGroupHint;+ QueueCallstackFat callstackFat;+ QueueCallstackFatThread callstackFatThread;+ QueueCallstackAllocFat callstackAllocFat;+ QueueCallstackAllocFatThread callstackAllocFatThread;+ QueueCallstackSample callstackSample;+ QueueCallstackSampleFat callstackSampleFat;+ QueueCallstackFrameSize callstackFrameSize;+ QueueCallstackFrameSizeFat callstackFrameSizeFat;+ QueueCallstackFrame callstackFrame;+ QueueSymbolInformation symbolInformation;+ QueueSymbolInformationFat symbolInformationFat;+ QueueCrashReport crashReport;+ QueueCrashReportThread crashReportThread;+ QueueSysTime sysTime;+ QueueSysPower sysPower;+ QueueContextSwitch contextSwitch;+ QueueThreadWakeup threadWakeup;+ QueueTidToPid tidToPid;+ QueueHwSample hwSample;+ QueuePlotConfig plotConfig;+ QueueParamSetup paramSetup;+ QueueCpuTopology cpuTopology;+ QueueExternalNameMetadata externalNameMetadata;+ QueueSymbolCodeMetadata symbolCodeMetadata;+ QueueSourceCodeMetadata sourceCodeMetadata;+ QueueSourceCodeNotAvailable sourceCodeNotAvailable;+ QueueFiberEnter fiberEnter;+ QueueFiberLeave fiberLeave;+ };+};+#pragma pack( pop )+++enum { QueueItemSize = sizeof( QueueItem ) };++static constexpr size_t QueueDataSize[] = {+ sizeof( QueueHeader ), // zone text+ sizeof( QueueHeader ), // zone name+ sizeof( QueueHeader ) + sizeof( QueueMessage ),+ sizeof( QueueHeader ) + sizeof( QueueMessageColor ),+ sizeof( QueueHeader ) + sizeof( QueueMessage ), // callstack+ sizeof( QueueHeader ) + sizeof( QueueMessageColor ), // callstack+ sizeof( QueueHeader ) + sizeof( QueueMessage ), // app info+ sizeof( QueueHeader ) + sizeof( QueueZoneBeginLean ), // allocated source location+ sizeof( QueueHeader ) + sizeof( QueueZoneBeginLean ), // allocated source location, callstack+ sizeof( QueueHeader ), // callstack memory+ sizeof( QueueHeader ), // callstack+ sizeof( QueueHeader ), // callstack alloc+ sizeof( QueueHeader ) + sizeof( QueueCallstackSample ),+ sizeof( QueueHeader ) + sizeof( QueueCallstackSample ), // context switch+ sizeof( QueueHeader ) + sizeof( QueueFrameImage ),+ sizeof( QueueHeader ) + sizeof( QueueZoneBegin ),+ sizeof( QueueHeader ) + sizeof( QueueZoneBegin ), // callstack+ sizeof( QueueHeader ) + sizeof( QueueZoneEnd ),+ sizeof( QueueHeader ) + sizeof( QueueLockWait ),+ sizeof( QueueHeader ) + sizeof( QueueLockObtain ),+ sizeof( QueueHeader ) + sizeof( QueueLockRelease ),+ sizeof( QueueHeader ) + sizeof( QueueLockWait ), // shared+ sizeof( QueueHeader ) + sizeof( QueueLockObtain ), // shared+ sizeof( QueueHeader ) + sizeof( QueueLockReleaseShared ),+ sizeof( QueueHeader ) + sizeof( QueueLockName ),+ sizeof( QueueHeader ) + sizeof( QueueMemAlloc ),+ sizeof( QueueHeader ) + sizeof( QueueMemAlloc ), // named+ sizeof( QueueHeader ) + sizeof( QueueMemFree ),+ sizeof( QueueHeader ) + sizeof( QueueMemFree ), // named+ sizeof( QueueHeader ) + sizeof( QueueMemAlloc ), // callstack+ sizeof( QueueHeader ) + sizeof( QueueMemAlloc ), // callstack, named+ sizeof( QueueHeader ) + sizeof( QueueMemFree ), // callstack+ sizeof( QueueHeader ) + sizeof( QueueMemFree ), // callstack, named+ sizeof( QueueHeader ) + sizeof( QueueMemDiscard ),+ sizeof( QueueHeader ) + sizeof( QueueMemDiscard ), // callstack+ sizeof( QueueHeader ) + sizeof( QueueGpuZoneBegin ),+ sizeof( QueueHeader ) + sizeof( QueueGpuZoneBegin ), // callstack+ sizeof( QueueHeader ) + sizeof( QueueGpuZoneBeginLean ),// allocated source location+ sizeof( QueueHeader ) + sizeof( QueueGpuZoneBeginLean ),// allocated source location, callstack+ sizeof( QueueHeader ) + sizeof( QueueGpuZoneEnd ),+ sizeof( QueueHeader ) + sizeof( QueueGpuZoneBegin ), // serial+ sizeof( QueueHeader ) + sizeof( QueueGpuZoneBegin ), // serial, callstack+ sizeof( QueueHeader ) + sizeof( QueueGpuZoneBeginLean ),// serial, allocated source location+ sizeof( QueueHeader ) + sizeof( QueueGpuZoneBeginLean ),// serial, allocated source location, callstack+ sizeof( QueueHeader ) + sizeof( QueueGpuZoneEnd ), // serial+ sizeof( QueueHeader ) + sizeof( QueuePlotDataInt ),+ sizeof( QueueHeader ) + sizeof( QueuePlotDataFloat ),+ sizeof( QueueHeader ) + sizeof( QueuePlotDataDouble ),+ sizeof( QueueHeader ) + sizeof( QueueContextSwitch ),+ sizeof( QueueHeader ) + sizeof( QueueThreadWakeup ),+ sizeof( QueueHeader ) + sizeof( QueueGpuTime ),+ sizeof( QueueHeader ) + sizeof( QueueGpuContextName ),+ sizeof( QueueHeader ) + sizeof( QueueCallstackFrameSize ),+ sizeof( QueueHeader ) + sizeof( QueueSymbolInformation ),+ sizeof( QueueHeader ), // ExternalNameMetadata - not for wire transfer+ sizeof( QueueHeader ), // SymbolCodeMetadata - not for wire transfer+ sizeof( QueueHeader ), // SourceCodeMetadata - not for wire transfer+ sizeof( QueueHeader ) + sizeof( QueueFiberEnter ),+ sizeof( QueueHeader ) + sizeof( QueueFiberLeave ),+ // above items must be first+ sizeof( QueueHeader ), // terminate+ sizeof( QueueHeader ), // keep alive+ sizeof( QueueHeader ) + sizeof( QueueThreadContext ),+ sizeof( QueueHeader ) + sizeof( QueueGpuCalibration ),+ sizeof( QueueHeader ) + sizeof( QueueGpuTimeSync ),+ sizeof( QueueHeader ), // crash+ sizeof( QueueHeader ) + sizeof( QueueCrashReport ),+ sizeof( QueueHeader ) + sizeof( QueueZoneValidation ),+ sizeof( QueueHeader ) + sizeof( QueueZoneColor ),+ sizeof( QueueHeader ) + sizeof( QueueZoneValue ),+ sizeof( QueueHeader ) + sizeof( QueueFrameMark ), // continuous frames+ sizeof( QueueHeader ) + sizeof( QueueFrameMark ), // start+ sizeof( QueueHeader ) + sizeof( QueueFrameMark ), // end+ sizeof( QueueHeader ) + sizeof( QueueFrameVsync ),+ sizeof( QueueHeader ) + sizeof( QueueSourceLocation ),+ sizeof( QueueHeader ) + sizeof( QueueLockAnnounce ),+ sizeof( QueueHeader ) + sizeof( QueueLockTerminate ),+ sizeof( QueueHeader ) + sizeof( QueueLockMark ),+ sizeof( QueueHeader ) + sizeof( QueueMessageLiteral ),+ sizeof( QueueHeader ) + sizeof( QueueMessageColorLiteral ),+ sizeof( QueueHeader ) + sizeof( QueueMessageLiteral ), // callstack+ sizeof( QueueHeader ) + sizeof( QueueMessageColorLiteral ), // callstack+ sizeof( QueueHeader ) + sizeof( QueueGpuNewContext ),+ sizeof( QueueHeader ) + sizeof( QueueCallstackFrame ),+ sizeof( QueueHeader ) + sizeof( QueueSysTime ),+ sizeof( QueueHeader ) + sizeof( QueueSysPower ),+ sizeof( QueueHeader ) + sizeof( QueueTidToPid ),+ sizeof( QueueHeader ) + sizeof( QueueHwSample ), // cpu cycle+ sizeof( QueueHeader ) + sizeof( QueueHwSample ), // instruction retired+ sizeof( QueueHeader ) + sizeof( QueueHwSample ), // cache reference+ sizeof( QueueHeader ) + sizeof( QueueHwSample ), // cache miss+ sizeof( QueueHeader ) + sizeof( QueueHwSample ), // branch retired+ sizeof( QueueHeader ) + sizeof( QueueHwSample ), // branch miss+ sizeof( QueueHeader ) + sizeof( QueuePlotConfig ),+ sizeof( QueueHeader ) + sizeof( QueueParamSetup ),+ sizeof( QueueHeader ), // server query acknowledgement+ sizeof( QueueHeader ) + sizeof( QueueSourceCodeNotAvailable ),+ sizeof( QueueHeader ), // symbol code not available+ sizeof( QueueHeader ) + sizeof( QueueCpuTopology ),+ sizeof( QueueHeader ), // single string data+ sizeof( QueueHeader ), // second string data+ sizeof( QueueHeader ) + sizeof( QueueMemNamePayload ),+ sizeof( QueueHeader ) + sizeof( QueueThreadGroupHint ),+ // keep all QueueStringTransfer below+ sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // string data+ sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // thread name+ sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // plot name+ sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // allocated source location payload+ sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // callstack payload+ sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // callstack alloc payload+ sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // frame name+ sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // frame image data+ sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // external name+ sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // external thread name+ sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // symbol code+ sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // source code+ sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // fiber name+};++static_assert( QueueItemSize == 32, "Queue item size not 32 bytes" );+static_assert( sizeof( QueueDataSize ) / sizeof( size_t ) == (uint8_t)QueueType::NUM_TYPES, "QueueDataSize mismatch" );+static_assert( sizeof( void* ) <= sizeof( uint64_t ), "Pointer size > 8 bytes" );+static_assert( sizeof( void* ) == sizeof( uintptr_t ), "Pointer size != uintptr_t" );++}++#endif
+ cbits/tracy/public/common/TracySocket.cpp view
@@ -0,0 +1,752 @@+#include <assert.h>+#include <inttypes.h>+#include <new>+#include <stdio.h>+#include <stdlib.h>+#include <string.h>+#include <sys/types.h>++#include "TracyAlloc.hpp"+#include "TracySocket.hpp"+#include "TracySystem.hpp"++#ifdef _WIN32+# ifndef NOMINMAX+# define NOMINMAX+# endif+# include <winsock2.h>+# include <ws2tcpip.h>+# ifdef _MSC_VER+# pragma warning(disable:4244)+# pragma warning(disable:4267)+# endif+# define poll WSAPoll+# ifdef _MSC_VER+# pragma comment(lib, "ws2_32.lib")+# endif+#else+# include <arpa/inet.h>+# include <sys/socket.h>+# include <sys/param.h>+# include <errno.h>+# include <fcntl.h>+# include <netinet/in.h>+# include <netdb.h>+# include <unistd.h>+# include <poll.h>+#endif++#ifndef MSG_NOSIGNAL+# define MSG_NOSIGNAL 0+#endif++namespace tracy+{++#ifdef _WIN32+typedef SOCKET socket_t;+#else+typedef int socket_t;+#endif++#ifdef _WIN32+struct __wsinit+{+ __wsinit()+ {+ WSADATA wsaData;+ if( WSAStartup( MAKEWORD( 2, 2 ), &wsaData ) != 0 )+ {+ fprintf( stderr, "Cannot init winsock.\n" );+ exit( 1 );+ }+ }+};++void InitWinSock()+{+ static __wsinit init;+}+#endif+++enum { BufSize = 128 * 1024 };++Socket::Socket()+ : m_buf( (char*)tracy_malloc( BufSize ) )+ , m_bufPtr( nullptr )+ , m_sock( -1 )+ , m_bufLeft( 0 )+ , m_ptr( nullptr )+{+#ifdef _WIN32+ InitWinSock();+#endif+}++Socket::Socket( int sock )+ : m_buf( (char*)tracy_malloc( BufSize ) )+ , m_bufPtr( nullptr )+ , m_sock( sock )+ , m_bufLeft( 0 )+ , m_ptr( nullptr )+{+}++Socket::~Socket()+{+ tracy_free( m_buf );+ if( m_sock.load( std::memory_order_relaxed ) != -1 )+ {+ Close();+ }+ if( m_ptr )+ {+ freeaddrinfo( m_res );+#ifdef _WIN32+ closesocket( m_connSock );+#else+ close( m_connSock );+#endif+ }+}++bool Socket::Connect( const char* addr, uint16_t port )+{+ assert( !IsValid() );++ if( m_ptr )+ {+ const auto c = connect( m_connSock, m_ptr->ai_addr, m_ptr->ai_addrlen );+ if( c == -1 )+ {+#if defined _WIN32+ const auto err = WSAGetLastError();+ if( err == WSAEALREADY || err == WSAEINPROGRESS ) return false;+ if( err != WSAEISCONN )+ {+ freeaddrinfo( m_res );+ closesocket( m_connSock );+ m_ptr = nullptr;+ return false;+ }+#else+ const auto err = errno;+ if( err == EALREADY || err == EINPROGRESS ) return false;+ if( err != EISCONN )+ {+ freeaddrinfo( m_res );+ close( m_connSock );+ m_ptr = nullptr;+ return false;+ }+#endif+ }++#if defined _WIN32+ u_long nonblocking = 0;+ ioctlsocket( m_connSock, FIONBIO, &nonblocking );+#else+ int flags = fcntl( m_connSock, F_GETFL, 0 );+ fcntl( m_connSock, F_SETFL, flags & ~O_NONBLOCK );+#endif+ m_sock.store( m_connSock, std::memory_order_relaxed );+ freeaddrinfo( m_res );+ m_ptr = nullptr;+ return true;+ }++ struct addrinfo hints;+ struct addrinfo *res, *ptr;++ memset( &hints, 0, sizeof( hints ) );+ hints.ai_family = AF_UNSPEC;+ hints.ai_socktype = SOCK_STREAM;++ char portbuf[32];+ sprintf( portbuf, "%" PRIu16, port );++ if( getaddrinfo( addr, portbuf, &hints, &res ) != 0 ) return false;+ int sock = 0;+ for( ptr = res; ptr; ptr = ptr->ai_next )+ {+ if( ( sock = socket( ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol ) ) == -1 ) continue;+#if defined __APPLE__+ int val = 1;+ setsockopt( sock, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof( val ) );+#endif+#if defined _WIN32+ u_long nonblocking = 1;+ ioctlsocket( sock, FIONBIO, &nonblocking );+#else+ int flags = fcntl( sock, F_GETFL, 0 );+ fcntl( sock, F_SETFL, flags | O_NONBLOCK );+#endif+ if( connect( sock, ptr->ai_addr, ptr->ai_addrlen ) == 0 )+ {+ break;+ }+ else+ {+#if defined _WIN32+ const auto err = WSAGetLastError();+ if( err != WSAEWOULDBLOCK )+ {+ closesocket( sock );+ continue;+ }+#else+ if( errno != EINPROGRESS )+ {+ close( sock );+ continue;+ }+#endif+ }+ m_res = res;+ m_ptr = ptr;+ m_connSock = sock;+ return false;+ }+ freeaddrinfo( res );+ if( !ptr ) return false;++#if defined _WIN32+ u_long nonblocking = 0;+ ioctlsocket( sock, FIONBIO, &nonblocking );+#else+ int flags = fcntl( sock, F_GETFL, 0 );+ fcntl( sock, F_SETFL, flags & ~O_NONBLOCK );+#endif++ m_sock.store( sock, std::memory_order_relaxed );+ return true;+}++bool Socket::ConnectBlocking( const char* addr, uint16_t port )+{+ assert( !IsValid() );+ assert( !m_ptr );++ struct addrinfo hints;+ struct addrinfo *res, *ptr;++ memset( &hints, 0, sizeof( hints ) );+ hints.ai_family = AF_UNSPEC;+ hints.ai_socktype = SOCK_STREAM;++ char portbuf[32];+ sprintf( portbuf, "%" PRIu16, port );++ if( getaddrinfo( addr, portbuf, &hints, &res ) != 0 ) return false;+ int sock = 0;+ for( ptr = res; ptr; ptr = ptr->ai_next )+ {+ if( ( sock = socket( ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol ) ) == -1 ) continue;+#if defined __APPLE__+ int val = 1;+ setsockopt( sock, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof( val ) );+#endif+ if( connect( sock, ptr->ai_addr, ptr->ai_addrlen ) == -1 )+ {+#ifdef _WIN32+ closesocket( sock );+#else+ close( sock );+#endif+ continue;+ }+ break;+ }+ freeaddrinfo( res );+ if( !ptr ) return false;++ m_sock.store( sock, std::memory_order_relaxed );+ return true;+}++void Socket::Close()+{+ const auto sock = m_sock.load( std::memory_order_relaxed );+ assert( sock != -1 );+#ifdef _WIN32+ closesocket( sock );+#else+ close( sock );+#endif+ m_sock.store( -1, std::memory_order_relaxed );+}++int Socket::Send( const void* _buf, int len )+{+ const auto sock = m_sock.load( std::memory_order_relaxed );+ auto buf = (const char*)_buf;+ assert( sock != -1 );+ auto start = buf;+ while( len > 0 )+ {+ auto ret = send( sock, buf, len, MSG_NOSIGNAL );+ if( ret == -1 ) return -1;+ len -= ret;+ buf += ret;+ }+ return int( buf - start );+}++int Socket::GetSendBufSize()+{+ const auto sock = m_sock.load( std::memory_order_relaxed );+ int bufSize;+#if defined _WIN32+ int sz = sizeof( bufSize );+ getsockopt( sock, SOL_SOCKET, SO_SNDBUF, (char*)&bufSize, &sz );+#else+ socklen_t sz = sizeof( bufSize );+ getsockopt( sock, SOL_SOCKET, SO_SNDBUF, &bufSize, &sz );+#endif+ return bufSize;+}++int Socket::RecvBuffered( void* buf, int len, int timeout )+{+ if( len <= m_bufLeft )+ {+ memcpy( buf, m_bufPtr, len );+ m_bufPtr += len;+ m_bufLeft -= len;+ return len;+ }++ if( m_bufLeft > 0 )+ {+ memcpy( buf, m_bufPtr, m_bufLeft );+ const auto ret = m_bufLeft;+ m_bufLeft = 0;+ return ret;+ }++ if( len >= BufSize ) return Recv( buf, len, timeout );++ m_bufLeft = Recv( m_buf, BufSize, timeout );+ if( m_bufLeft <= 0 ) return m_bufLeft;++ const auto sz = len < m_bufLeft ? len : m_bufLeft;+ memcpy( buf, m_buf, sz );+ m_bufPtr = m_buf + sz;+ m_bufLeft -= sz;+ return sz;+}++int Socket::Recv( void* _buf, int len, int timeout )+{+ const auto sock = m_sock.load( std::memory_order_relaxed );+ auto buf = (char*)_buf;++ struct pollfd fd;+ fd.fd = (socket_t)sock;+ fd.events = POLLIN;++ if( poll( &fd, 1, timeout ) > 0 )+ {+ return recv( sock, buf, len, 0 );+ }+ else+ {+ return -1;+ }+}++int Socket::ReadUpTo( void* _buf, int len )+{+ const auto sock = m_sock.load( std::memory_order_relaxed );+ auto buf = (char*)_buf;++ int rd = 0;+ while( len > 0 )+ {+ const auto res = recv( sock, buf, len, 0 );+ if( res == 0 ) break;+ if( res == -1 ) return -1;+ len -= res;+ rd += res;+ buf += res;+ }+ return rd;+}++bool Socket::Read( void* buf, int len, int timeout )+{+ auto cbuf = (char*)buf;+ while( len > 0 )+ {+ if( !ReadImpl( cbuf, len, timeout ) ) return false;+ }+ return true;+}++bool Socket::ReadImpl( char*& buf, int& len, int timeout )+{+ const auto sz = RecvBuffered( buf, len, timeout );+ switch( sz )+ {+ case 0:+ return false;+ case -1:+#ifdef _WIN32+ {+ auto err = WSAGetLastError();+ if( err == WSAECONNABORTED || err == WSAECONNRESET ) return false;+ }+#endif+ break;+ default:+ len -= sz;+ buf += sz;+ break;+ }+ return true;+}++bool Socket::ReadRaw( void* _buf, int len, int timeout )+{+ auto buf = (char*)_buf;+ while( len > 0 )+ {+ const auto sz = Recv( buf, len, timeout );+ if( sz <= 0 ) return false;+ len -= sz;+ buf += sz;+ }+ return true;+}++bool Socket::HasData()+{+ const auto sock = m_sock.load( std::memory_order_relaxed );+ if( m_bufLeft > 0 ) return true;++ struct pollfd fd;+ fd.fd = (socket_t)sock;+ fd.events = POLLIN;++ return poll( &fd, 1, 0 ) > 0;+}++bool Socket::IsValid() const+{+ return m_sock.load( std::memory_order_relaxed ) >= 0;+}+++ListenSocket::ListenSocket()+ : m_sock( -1 )+{+#ifdef _WIN32+ InitWinSock();+#endif+}++ListenSocket::~ListenSocket()+{+ if( m_sock != -1 ) Close();+}++static int addrinfo_and_socket_for_family( uint16_t port, int ai_family, struct addrinfo** res )+{+ struct addrinfo hints;+ memset( &hints, 0, sizeof( hints ) );+ hints.ai_family = ai_family;+ hints.ai_socktype = SOCK_STREAM;+#ifndef TRACY_ONLY_LOCALHOST+ const char* onlyLocalhost = GetEnvVar( "TRACY_ONLY_LOCALHOST" );+ if( !onlyLocalhost || onlyLocalhost[0] != '1' )+ {+ hints.ai_flags = AI_PASSIVE;+ }+#endif+ char portbuf[32];+ sprintf( portbuf, "%" PRIu16, port );+ if( getaddrinfo( nullptr, portbuf, &hints, res ) != 0 ) return -1;+ int sock = socket( (*res)->ai_family, (*res)->ai_socktype, (*res)->ai_protocol );+ if (sock == -1) freeaddrinfo( *res );+ return sock;+}++bool ListenSocket::Listen( uint16_t port, int backlog )+{+ assert( m_sock == -1 );++ struct addrinfo* res = nullptr;++#if !defined TRACY_ONLY_IPV4 && !defined TRACY_ONLY_LOCALHOST+ const char* onlyIPv4 = GetEnvVar( "TRACY_ONLY_IPV4" );+ if( !onlyIPv4 || onlyIPv4[0] != '1' )+ {+ m_sock = addrinfo_and_socket_for_family( port, AF_INET6, &res );+ }+#endif+ if (m_sock == -1)+ {+ // IPV6 protocol may not be available/is disabled. Try to create a socket+ // with the IPV4 protocol+ m_sock = addrinfo_and_socket_for_family( port, AF_INET, &res );+ if( m_sock == -1 ) return false;+ }+#if defined _WIN32+ unsigned long val = 0;+ setsockopt( m_sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&val, sizeof( val ) );+#elif defined BSD+ int val = 0;+ setsockopt( m_sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&val, sizeof( val ) );+ val = 1;+ setsockopt( m_sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof( val ) );+#else+ int val = 1;+ setsockopt( m_sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof( val ) );+#endif+ if( bind( m_sock, res->ai_addr, res->ai_addrlen ) == -1 ) { freeaddrinfo( res ); Close(); return false; }+ if( listen( m_sock, backlog ) == -1 ) { freeaddrinfo( res ); Close(); return false; }+ freeaddrinfo( res );+ return true;+}++Socket* ListenSocket::Accept()+{+ struct sockaddr_storage remote;+ socklen_t sz = sizeof( remote );++ struct pollfd fd;+ fd.fd = (socket_t)m_sock;+ fd.events = POLLIN;++ if( poll( &fd, 1, 10 ) > 0 )+ {+ int sock = accept( m_sock, (sockaddr*)&remote, &sz);+ if( sock == -1 ) return nullptr;++#if defined __APPLE__+ int val = 1;+ setsockopt( sock, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof( val ) );+#endif++ auto ptr = (Socket*)tracy_malloc( sizeof( Socket ) );+ new(ptr) Socket( sock );+ return ptr;+ }+ else+ {+ return nullptr;+ }+}++void ListenSocket::Close()+{+ assert( m_sock != -1 );+#ifdef _WIN32+ closesocket( m_sock );+#else+ close( m_sock );+#endif+ m_sock = -1;+}++UdpBroadcast::UdpBroadcast()+ : m_sock( -1 )+{+#ifdef _WIN32+ InitWinSock();+#endif+}++UdpBroadcast::~UdpBroadcast()+{+ if( m_sock != -1 ) Close();+}++bool UdpBroadcast::Open( const char* addr, uint16_t port )+{+ assert( m_sock == -1 );++ struct addrinfo hints;+ struct addrinfo *res, *ptr;++ memset( &hints, 0, sizeof( hints ) );+ hints.ai_family = AF_INET;+ hints.ai_socktype = SOCK_DGRAM;++ char portbuf[32];+ sprintf( portbuf, "%" PRIu16, port );++ if( getaddrinfo( addr, portbuf, &hints, &res ) != 0 ) return false;+ int sock = 0;+ for( ptr = res; ptr; ptr = ptr->ai_next )+ {+ if( ( sock = socket( ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol ) ) == -1 ) continue;+#if defined __APPLE__+ int val = 1;+ setsockopt( sock, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof( val ) );+#endif+#if defined _WIN32+ unsigned long broadcast = 1;+ if( setsockopt( sock, SOL_SOCKET, SO_BROADCAST, (const char*)&broadcast, sizeof( broadcast ) ) == -1 )+#else+ int broadcast = 1;+ if( setsockopt( sock, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof( broadcast ) ) == -1 )+#endif+ {+#ifdef _WIN32+ closesocket( sock );+#else+ close( sock );+#endif+ continue;+ }+ break;+ }+ freeaddrinfo( res );+ if( !ptr ) return false;++ m_sock = sock;+ inet_pton( AF_INET, addr, &m_addr );+ return true;+}++void UdpBroadcast::Close()+{+ assert( m_sock != -1 );+#ifdef _WIN32+ closesocket( m_sock );+#else+ close( m_sock );+#endif+ m_sock = -1;+}++int UdpBroadcast::Send( uint16_t port, const void* data, int len )+{+ assert( m_sock != -1 );+ struct sockaddr_in addr;+ addr.sin_family = AF_INET;+ addr.sin_port = htons( port );+ addr.sin_addr.s_addr = m_addr;+ return sendto( m_sock, (const char*)data, len, MSG_NOSIGNAL, (sockaddr*)&addr, sizeof( addr ) );+}++IpAddress::IpAddress()+ : m_number( 0 )+{+ *m_text = '\0';+}++IpAddress::~IpAddress()+{+}++void IpAddress::Set( const struct sockaddr& addr )+{+#if defined _WIN32 && ( !defined NTDDI_WIN10 || NTDDI_VERSION < NTDDI_WIN10 )+ struct sockaddr_in tmp;+ memcpy( &tmp, &addr, sizeof( tmp ) );+ auto ai = &tmp;+#else+ auto ai = (const struct sockaddr_in*)&addr;+#endif+ inet_ntop( AF_INET, &ai->sin_addr, m_text, 17 );+ m_number = ai->sin_addr.s_addr;+}++UdpListen::UdpListen()+ : m_sock( -1 )+{+#ifdef _WIN32+ InitWinSock();+#endif+}++UdpListen::~UdpListen()+{+ if( m_sock != -1 ) Close();+}++bool UdpListen::Listen( uint16_t port )+{+ assert( m_sock == -1 );++ int sock;+ if( ( sock = socket( AF_INET, SOCK_DGRAM, 0 ) ) == -1 ) return false;++#if defined __APPLE__+ int val = 1;+ setsockopt( sock, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof( val ) );+#endif+#if defined _WIN32+ unsigned long reuse = 1;+ setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof( reuse ) );+#else+ int reuse = 1;+ setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof( reuse ) );+#endif+#if defined _WIN32+ unsigned long broadcast = 1;+ if( setsockopt( sock, SOL_SOCKET, SO_BROADCAST, (const char*)&broadcast, sizeof( broadcast ) ) == -1 )+#else+ int broadcast = 1;+ if( setsockopt( sock, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof( broadcast ) ) == -1 )+#endif+ {+#ifdef _WIN32+ closesocket( sock );+#else+ close( sock );+#endif+ return false;+ }++ struct sockaddr_in addr;+ addr.sin_family = AF_INET;+ addr.sin_port = htons( port );+ addr.sin_addr.s_addr = INADDR_ANY;++ if( bind( sock, (sockaddr*)&addr, sizeof( addr ) ) == -1 )+ {+#ifdef _WIN32+ closesocket( sock );+#else+ close( sock );+#endif+ return false;+ }++ m_sock = sock;+ return true;+}++void UdpListen::Close()+{+ assert( m_sock != -1 );+#ifdef _WIN32+ closesocket( m_sock );+#else+ close( m_sock );+#endif+ m_sock = -1;+}++const char* UdpListen::Read( size_t& len, IpAddress& addr, int timeout )+{+ static char buf[2048];++ struct pollfd fd;+ fd.fd = (socket_t)m_sock;+ fd.events = POLLIN;+ if( poll( &fd, 1, timeout ) <= 0 ) return nullptr;++ sockaddr sa;+ socklen_t salen = sizeof( struct sockaddr );+ len = (size_t)recvfrom( m_sock, buf, 2048, 0, &sa, &salen );+ addr.Set( sa );++ return buf;+}++}
+ cbits/tracy/public/common/TracySocket.hpp view
@@ -0,0 +1,155 @@+#ifndef __TRACYSOCKET_HPP__+#define __TRACYSOCKET_HPP__++#include <atomic>+#include <stddef.h>+#include <stdint.h>++struct addrinfo;+struct sockaddr;++namespace tracy+{++#ifdef _WIN32+void InitWinSock();+#endif++class Socket+{+public:+ Socket();+ Socket( int sock );+ ~Socket();++ bool Connect( const char* addr, uint16_t port );+ bool ConnectBlocking( const char* addr, uint16_t port );+ void Close();++ int Send( const void* buf, int len );+ int GetSendBufSize();++ int ReadUpTo( void* buf, int len );+ bool Read( void* buf, int len, int timeout );++ template<typename ShouldExit>+ bool Read( void* buf, int len, int timeout, ShouldExit exitCb )+ {+ auto cbuf = (char*)buf;+ while( len > 0 )+ {+ if( exitCb() ) return false;+ if( !ReadImpl( cbuf, len, timeout ) ) return false;+ }+ return true;+ }++ bool ReadRaw( void* buf, int len, int timeout );+ bool HasData();+ bool IsValid() const;++ Socket( const Socket& ) = delete;+ Socket( Socket&& ) = delete;+ Socket& operator=( const Socket& ) = delete;+ Socket& operator=( Socket&& ) = delete;++private:+ int RecvBuffered( void* buf, int len, int timeout );+ int Recv( void* buf, int len, int timeout );++ bool ReadImpl( char*& buf, int& len, int timeout );++ char* m_buf;+ char* m_bufPtr;+ std::atomic<int> m_sock;+ int m_bufLeft;++ struct addrinfo *m_res;+ struct addrinfo *m_ptr;+ int m_connSock;+};++class ListenSocket+{+public:+ ListenSocket();+ ~ListenSocket();++ bool Listen( uint16_t port, int backlog );+ Socket* Accept();+ void Close();++ ListenSocket( const ListenSocket& ) = delete;+ ListenSocket( ListenSocket&& ) = delete;+ ListenSocket& operator=( const ListenSocket& ) = delete;+ ListenSocket& operator=( ListenSocket&& ) = delete;++private:+ int m_sock;+};++class UdpBroadcast+{+public:+ UdpBroadcast();+ ~UdpBroadcast();++ bool Open( const char* addr, uint16_t port );+ void Close();++ int Send( uint16_t port, const void* data, int len );++ UdpBroadcast( const UdpBroadcast& ) = delete;+ UdpBroadcast( UdpBroadcast&& ) = delete;+ UdpBroadcast& operator=( const UdpBroadcast& ) = delete;+ UdpBroadcast& operator=( UdpBroadcast&& ) = delete;++private:+ int m_sock;+ uint32_t m_addr;+};++class IpAddress+{+public:+ IpAddress();+ ~IpAddress();++ void Set( const struct sockaddr& addr );++ uint32_t GetNumber() const { return m_number; }+ const char* GetText() const { return m_text; }++ IpAddress( const IpAddress& ) = delete;+ IpAddress( IpAddress&& ) = delete;+ IpAddress& operator=( const IpAddress& ) = delete;+ IpAddress& operator=( IpAddress&& ) = delete;++private:+ uint32_t m_number;+ char m_text[17];+};++class UdpListen+{+public:+ UdpListen();+ ~UdpListen();++ bool Listen( uint16_t port );+ void Close();++ const char* Read( size_t& len, IpAddress& addr, int timeout );++ UdpListen( const UdpListen& ) = delete;+ UdpListen( UdpListen&& ) = delete;+ UdpListen& operator=( const UdpListen& ) = delete;+ UdpListen& operator=( UdpListen&& ) = delete;++private:+ int m_sock;+};++}++#endif
+ cbits/tracy/public/common/TracyStackFrames.cpp view
@@ -0,0 +1,122 @@+#include "TracyStackFrames.hpp"++namespace tracy+{++const char* s_tracyStackFrames_[] = {+ "tracy::Callstack",+ "tracy::Callstack(int)",+ "tracy::GpuCtxScope::{ctor}",+ "tracy::Profiler::SendCallstack",+ "tracy::Profiler::SendCallstack(int)",+ "tracy::Profiler::SendCallstack(int, unsigned long)",+ "tracy::Profiler::MemAllocCallstack",+ "tracy::Profiler::MemAllocCallstack(void const*, unsigned long, int)",+ "tracy::Profiler::MemFreeCallstack",+ "tracy::Profiler::MemFreeCallstack(void const*, int)",+ "tracy::ScopedZone::{ctor}",+ "tracy::ScopedZone::ScopedZone(tracy::SourceLocationData const*, int, bool)",+ "tracy::Profiler::Message",+ nullptr+};++const char** s_tracyStackFrames = s_tracyStackFrames_;++const StringMatch s_tracySkipSubframes_[] = {+ { "/include/arm_neon.h", 19 },+ { "/include/adxintrin.h", 20 },+ { "/include/ammintrin.h", 20 },+ { "/include/amxbf16intrin.h", 24 },+ { "/include/amxint8intrin.h", 24 },+ { "/include/amxtileintrin.h", 24 },+ { "/include/avx2intrin.h", 21 },+ { "/include/avx5124fmapsintrin.h", 29 },+ { "/include/avx5124vnniwintrin.h", 29 },+ { "/include/avx512bf16intrin.h", 27 },+ { "/include/avx512bf16vlintrin.h", 29 },+ { "/include/avx512bitalgintrin.h", 29 },+ { "/include/avx512bwintrin.h", 25 },+ { "/include/avx512cdintrin.h", 25 },+ { "/include/avx512dqintrin.h", 25 },+ { "/include/avx512erintrin.h", 25 },+ { "/include/avx512fintrin.h", 24 },+ { "/include/avx512ifmaintrin.h", 27 },+ { "/include/avx512ifmavlintrin.h", 29 },+ { "/include/avx512pfintrin.h", 25 },+ { "/include/avx512vbmi2intrin.h", 28 },+ { "/include/avx512vbmi2vlintrin.h", 30 },+ { "/include/avx512vbmiintrin.h", 27 },+ { "/include/avx512vbmivlintrin.h", 29 },+ { "/include/avx512vlbwintrin.h", 27 },+ { "/include/avx512vldqintrin.h", 27 },+ { "/include/avx512vlintrin.h", 25 },+ { "/include/avx512vnniintrin.h", 27 },+ { "/include/avx512vnnivlintrin.h", 29 },+ { "/include/avx512vp2intersectintrin.h", 35 },+ { "/include/avx512vp2intersectvlintrin.h", 37 },+ { "/include/avx512vpopcntdqintrin.h", 32 },+ { "/include/avx512vpopcntdqvlintrin.h", 34 },+ { "/include/avxintrin.h", 20 },+ { "/include/avxvnniintrin.h", 24 },+ { "/include/bmi2intrin.h", 21 },+ { "/include/bmiintrin.h", 20 },+ { "/include/bmmintrin.h", 20 },+ { "/include/cetintrin.h", 20 },+ { "/include/cldemoteintrin.h", 25 },+ { "/include/clflushoptintrin.h", 27 },+ { "/include/clwbintrin.h", 21 },+ { "/include/clzerointrin.h", 23 },+ { "/include/emmintrin.h", 20 },+ { "/include/enqcmdintrin.h", 23 },+ { "/include/f16cintrin.h", 21 },+ { "/include/fma4intrin.h", 21 },+ { "/include/fmaintrin.h", 20 },+ { "/include/fxsrintrin.h", 21 },+ { "/include/gfniintrin.h", 21 },+ { "/include/hresetintrin.h", 23 },+ { "/include/ia32intrin.h", 21 },+ { "/include/immintrin.h", 20 },+ { "/include/keylockerintrin.h", 26 },+ { "/include/lwpintrin.h", 20 },+ { "/include/lzcntintrin.h", 22 },+ { "/include/mmintrin.h", 19 },+ { "/include/movdirintrin.h", 23 },+ { "/include/mwaitxintrin.h", 23 },+ { "/include/nmmintrin.h", 20 },+ { "/include/pconfigintrin.h", 24 },+ { "/include/pkuintrin.h", 20 },+ { "/include/pmmintrin.h", 20 },+ { "/include/popcntintrin.h", 23 },+ { "/include/prfchwintrin.h", 23 },+ { "/include/rdseedintrin.h", 23 },+ { "/include/rtmintrin.h", 20 },+ { "/include/serializeintrin.h", 26 },+ { "/include/sgxintrin.h", 20 },+ { "/include/shaintrin.h", 20 },+ { "/include/smmintrin.h", 20 },+ { "/include/tbmintrin.h", 20 },+ { "/include/tmmintrin.h", 20 },+ { "/include/tsxldtrkintrin.h", 25 },+ { "/include/uintrintrin.h", 22 },+ { "/include/vaesintrin.h", 21 },+ { "/include/vpclmulqdqintrin.h", 27 },+ { "/include/waitpkgintrin.h", 24 },+ { "/include/wbnoinvdintrin.h", 25 },+ { "/include/wmmintrin.h", 20 },+ { "/include/x86gprintrin.h", 23 },+ { "/include/x86intrin.h", 20 },+ { "/include/xmmintrin.h", 20 },+ { "/include/xopintrin.h", 20 },+ { "/include/xsavecintrin.h", 23 },+ { "/include/xsaveintrin.h", 22 },+ { "/include/xsaveoptintrin.h", 25 },+ { "/include/xsavesintrin.h", 23 },+ { "/include/xtestintrin.h", 22 },+ { "/bits/atomic_base.h", 19 },+ { "/atomic", 7 },+ {}+};++const StringMatch* s_tracySkipSubframes = s_tracySkipSubframes_;++}
+ cbits/tracy/public/common/TracyStackFrames.hpp view
@@ -0,0 +1,22 @@+#ifndef __TRACYSTACKFRAMES_HPP__+#define __TRACYSTACKFRAMES_HPP__++#include <stddef.h>++namespace tracy+{++struct StringMatch+{+ const char* str;+ size_t len;+};++extern const char** s_tracyStackFrames;+extern const StringMatch* s_tracySkipSubframes;++static constexpr int s_tracySkipSubframesMinLen = 7;++}++#endif
+ cbits/tracy/public/common/TracySystem.cpp view
@@ -0,0 +1,349 @@+#ifdef _MSC_VER+# pragma warning(disable:4996)+#endif+#if defined _WIN32+# ifndef WIN32_LEAN_AND_MEAN+# define WIN32_LEAN_AND_MEAN+# endif+# ifndef NOMINMAX+# define NOMINMAX+# endif+# include <windows.h>+# include <malloc.h>+# include "TracyUwp.hpp"+#else+# include <pthread.h>+# include <string.h>+# include <unistd.h>+#endif++#ifdef __linux__+# ifdef __ANDROID__+# include <sys/types.h>+# else+# include <sys/syscall.h>+# endif+# include <fcntl.h>+#elif defined __FreeBSD__+# include <sys/thr.h>+#elif defined __NetBSD__+# include <lwp.h>+#elif defined __DragonFly__+# include <sys/lwp.h>+#elif defined __QNX__+# include <process.h>+# include <sys/neutrino.h>+#endif++#ifdef __MINGW32__+# define __STDC_FORMAT_MACROS+#endif+#include <inttypes.h>+#include <stdio.h>+#include <stdlib.h>++#include "TracySystem.hpp"++#if defined _WIN32+extern "C" typedef HRESULT (WINAPI *t_SetThreadDescription)( HANDLE, PCWSTR );+extern "C" typedef HRESULT (WINAPI *t_GetThreadDescription)( HANDLE, PWSTR* );+#endif++#ifdef TRACY_ENABLE+# include <atomic>+# include "TracyAlloc.hpp"+#endif++namespace tracy+{++namespace detail+{++TRACY_API uint32_t GetThreadHandleImpl()+{+#if defined _WIN32+ static_assert( sizeof( decltype( GetCurrentThreadId() ) ) <= sizeof( uint32_t ), "Thread handle too big to fit in protocol" );+ return uint32_t( GetCurrentThreadId() );+#elif defined __APPLE__+ uint64_t id;+ pthread_threadid_np( pthread_self(), &id );+ return uint32_t( id );+#elif defined __ANDROID__+ return (uint32_t)gettid();+#elif defined __linux__+ return (uint32_t)syscall( SYS_gettid );+#elif defined __FreeBSD__+ long id;+ thr_self( &id );+ return id;+#elif defined __NetBSD__+ return _lwp_self();+#elif defined __DragonFly__+ return lwp_gettid();+#elif defined __OpenBSD__+ return getthrid();+#elif defined __QNX__+ return (uint32_t) gettid();+#elif defined __EMSCRIPTEN__+ // Not supported, but let it compile.+ return 0;+#else+ // To add support for a platform, retrieve and return the kernel thread identifier here.+ //+ // Note that pthread_t (as for example returned by pthread_self()) is *not* a kernel+ // thread identifier. It is a pointer to a library-allocated data structure instead.+ // Such pointers will be reused heavily, making the pthread_t non-unique. Additionally+ // a 64-bit pointer cannot be reliably truncated to 32 bits.+ #error "Unsupported platform!"+#endif++}++}++#ifdef TRACY_ENABLE+std::atomic<ThreadNameData*>& GetThreadNameData();+#endif++#if defined _MSC_VER && !defined __clang__+# pragma pack( push, 8 )+struct THREADNAME_INFO+{+ DWORD dwType;+ LPCSTR szName;+ DWORD dwThreadID;+ DWORD dwFlags;+};+# pragma pack( pop )++void ThreadNameMsvcMagic( const THREADNAME_INFO& info )+{+ __try+ {+ RaiseException( 0x406D1388, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info );+ }+ __except(EXCEPTION_EXECUTE_HANDLER)+ {+ }+}+#endif++TRACY_API void SetThreadName( const char* name )+{+ SetThreadNameWithHint( name, 0 );+}++TRACY_API void SetThreadNameWithHint( const char* name, int32_t groupHint )+{+#if defined _WIN32+# ifdef TRACY_UWP+ static auto _SetThreadDescription = &::SetThreadDescription;+# else+ static auto _SetThreadDescription = (t_SetThreadDescription)GetProcAddress( GetModuleHandleA( "kernel32.dll" ), "SetThreadDescription" );+# endif+ if( _SetThreadDescription )+ {+ wchar_t buf[256];+ mbstowcs( buf, name, 256 );+ _SetThreadDescription( GetCurrentThread(), buf );+ }+ else+ {+# if defined _MSC_VER && !defined __clang__+ THREADNAME_INFO info;+ info.dwType = 0x1000;+ info.szName = name;+ info.dwThreadID = GetCurrentThreadId();+ info.dwFlags = 0;+ ThreadNameMsvcMagic( info );+# endif+ }+#elif defined _GNU_SOURCE && !defined __EMSCRIPTEN__+ {+ const auto sz = strlen( name );+ if( sz <= 15 )+ {+#if defined __APPLE__+ pthread_setname_np( name );+#else+ pthread_setname_np( pthread_self(), name );+#endif+ }+ else+ {+ char buf[16];+ memcpy( buf, name, 15 );+ buf[15] = '\0';+#if defined __APPLE__+ pthread_setname_np( buf );+#else+ pthread_setname_np( pthread_self(), buf );+#endif+ }+ }+#elif defined __QNX__+ {+ const auto sz = strlen( name );+ if( sz <= _NTO_THREAD_NAME_MAX )+ {+ pthread_setname_np( pthread_self(), name );+ }+ else+ {+ char buf[_NTO_THREAD_NAME_MAX + 1];+ memcpy( buf, name, _NTO_THREAD_NAME_MAX );+ buf[_NTO_THREAD_NAME_MAX] = '\0';+ pthread_setname_np( pthread_self(), buf );+ }+ };+#endif+#ifdef TRACY_ENABLE+ {+ const auto sz = strlen( name );+ char* buf = (char*)tracy_malloc( sz+1 );+ memcpy( buf, name, sz );+ buf[sz] = '\0';+ auto data = (ThreadNameData*)tracy_malloc_fast( sizeof( ThreadNameData ) );+ data->id = detail::GetThreadHandleImpl();+ data->groupHint = groupHint;+ data->name = buf;+ data->next = GetThreadNameData().load( std::memory_order_relaxed );+ while( !GetThreadNameData().compare_exchange_weak( data->next, data, std::memory_order_release, std::memory_order_relaxed ) ) {}+ }+#endif+}++#ifdef TRACY_ENABLE+ThreadNameData* GetThreadNameData( uint32_t id )+{+ auto ptr = GetThreadNameData().load( std::memory_order_relaxed );+ while( ptr )+ {+ if( ptr->id == id )+ {+ return ptr;+ }+ ptr = ptr->next;+ }+ return nullptr;+}+#endif++TRACY_API const char* GetThreadName( uint32_t id )+{+ static char buf[256];+#ifdef TRACY_ENABLE+ auto ptr = GetThreadNameData().load( std::memory_order_relaxed );+ while( ptr )+ {+ if( ptr->id == id )+ {+ return ptr->name;+ }+ ptr = ptr->next;+ }+#endif++#if defined _WIN32+# ifdef TRACY_UWP+ static auto _GetThreadDescription = &::GetThreadDescription;+# else+ static auto _GetThreadDescription = (t_GetThreadDescription)GetProcAddress( GetModuleHandleA( "kernel32.dll" ), "GetThreadDescription" );+# endif+ if( _GetThreadDescription )+ {+ auto hnd = OpenThread( THREAD_QUERY_LIMITED_INFORMATION, FALSE, (DWORD)id );+ if( hnd != 0 )+ {+ PWSTR tmp;+ if( SUCCEEDED( _GetThreadDescription( hnd, &tmp ) ) )+ {+ auto ret = wcstombs( buf, tmp, 256 );+ CloseHandle( hnd );+ LocalFree( tmp );+ if( ret != static_cast<size_t>( -1 ) )+ {+ return buf;+ }+ }+ }+ }+#elif defined __linux__+ int cs, fd;+ char path[32];+ snprintf( path, sizeof( path ), "/proc/self/task/%d/comm", id );+ sprintf( buf, "%" PRIu32, id );+# ifndef __ANDROID__+ pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, &cs );+# endif+ if ( ( fd = open( path, O_RDONLY ) ) > 0) {+ int len = read( fd, buf, 255 );+ if( len > 0 )+ {+ buf[len] = 0;+ if( len > 1 && buf[len-1] == '\n' )+ {+ buf[len-1] = 0;+ }+ }+ close( fd );+ }+# ifndef __ANDROID__+ pthread_setcancelstate( cs, 0 );+# endif+ return buf;+#elif defined __QNX__+ static char qnxNameBuf[_NTO_THREAD_NAME_MAX + 1] = {0};+ if (pthread_getname_np(static_cast<int>(id), qnxNameBuf, _NTO_THREAD_NAME_MAX) == 0) {+ return qnxNameBuf;+ };+#endif++ sprintf( buf, "%" PRIu32, id );+ return buf;+}++TRACY_API const char* GetEnvVar( const char* name )+{+#if defined _WIN32+ // unfortunately getenv() on Windows is just fundamentally broken. It caches the entire+ // environment block once on startup, then never refreshes it again. If any environment+ // strings are added or modified after startup of the CRT, those changes will not be+ // seen by getenv(). This removes the possibility of an app using this SDK from+ // programmatically setting any of the behaviour controlling envvars here.+ //+ // To work around this, we'll instead go directly to the Win32 environment strings APIs+ // to get the current value.+ static char buffer[1024];+ DWORD const kBufferSize = DWORD(sizeof(buffer) / sizeof(buffer[0]));+ DWORD count = GetEnvironmentVariableA(name, buffer, kBufferSize);++ if( count == 0 )+ return nullptr;++ if( count >= kBufferSize )+ {+ char* buf = reinterpret_cast<char*>(_alloca(count + 1));+ count = GetEnvironmentVariableA(name, buf, count + 1);+ memcpy(buffer, buf, kBufferSize);+ buffer[kBufferSize - 1] = 0;+ }++ return buffer;+#else+ return getenv(name);+#endif+}++}++#ifdef __cplusplus+extern "C" {+#endif++TRACY_API void ___tracy_set_thread_name( const char* name ) { tracy::SetThreadName( name ); }++#ifdef __cplusplus+}+#endif
+ cbits/tracy/public/common/TracySystem.hpp view
@@ -0,0 +1,43 @@+#ifndef __TRACYSYSTEM_HPP__+#define __TRACYSYSTEM_HPP__++#include <stdint.h>++#include "TracyApi.h"++namespace tracy+{++namespace detail+{+TRACY_API uint32_t GetThreadHandleImpl();+}++#ifdef TRACY_ENABLE+struct ThreadNameData+{+ uint32_t id;+ int32_t groupHint;+ const char* name;+ ThreadNameData* next;+};++ThreadNameData* GetThreadNameData( uint32_t id );++TRACY_API uint32_t GetThreadHandle();+#else+static inline uint32_t GetThreadHandle()+{+ return detail::GetThreadHandleImpl();+}+#endif++TRACY_API void SetThreadName( const char* name );+TRACY_API void SetThreadNameWithHint( const char* name, int32_t groupHint );+TRACY_API const char* GetThreadName( uint32_t id );++TRACY_API const char* GetEnvVar( const char* name );++}++#endif
+ cbits/tracy/public/common/TracyUwp.hpp view
@@ -0,0 +1,11 @@+#ifndef __TRACYUWP_HPP__+#define __TRACYUWP_HPP__++#ifdef _WIN32+# include <winapifamily.h>+# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)+# define TRACY_UWP+# endif+#endif++#endif
+ cbits/tracy/public/common/TracyVersion.hpp view
@@ -0,0 +1,14 @@+#ifndef __TRACYVERSION_HPP__+#define __TRACYVERSION_HPP__++namespace tracy+{+namespace Version+{+enum { Major = 0 };+enum { Minor = 12 };+enum { Patch = 2 };+}+}++#endif
+ cbits/tracy/public/common/TracyYield.hpp view
@@ -0,0 +1,28 @@+#ifndef __TRACYYIELD_HPP__+#define __TRACYYIELD_HPP__++#if defined __SSE2__ || defined _M_AMD64 || (defined _M_IX86_FP && _M_IX86_FP == 2)+# include <emmintrin.h>+#else+# include <thread>+#endif++#include "TracyForceInline.hpp"++namespace tracy+{++static tracy_force_inline void YieldThread()+{+#if defined __SSE2__ || defined _M_AMD64 || (defined _M_IX86_FP && _M_IX86_FP == 2)+ _mm_pause();+#elif defined __aarch64__+ asm volatile( "isb" : : );+#else+ std::this_thread::yield();+#endif+}++}++#endif
+ cbits/tracy/public/common/tracy_lz4.cpp view
@@ -0,0 +1,2720 @@+/*+ LZ4 - Fast LZ compression algorithm+ Copyright (C) 2011-2020, Yann Collet.++ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)++ 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.++ 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.++ You can contact the author at :+ - LZ4 homepage : http://www.lz4.org+ - LZ4 source repository : https://github.com/lz4/lz4+*/++/*-************************************+* Tuning parameters+**************************************/+/*+ * LZ4_HEAPMODE :+ * Select how default compression functions will allocate memory for their hash table,+ * in memory stack (0:default, fastest), or in memory heap (1:requires malloc()).+ */+#ifndef LZ4_HEAPMODE+# define LZ4_HEAPMODE 0+#endif++/*+ * LZ4_ACCELERATION_DEFAULT :+ * Select "acceleration" for LZ4_compress_fast() when parameter value <= 0+ */+#define LZ4_ACCELERATION_DEFAULT 1+/*+ * LZ4_ACCELERATION_MAX :+ * Any "acceleration" value higher than this threshold+ * get treated as LZ4_ACCELERATION_MAX instead (fix #876)+ */+#define LZ4_ACCELERATION_MAX 65537+++/*-************************************+* CPU Feature Detection+**************************************/+/* LZ4_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 is portable but violate C standard.+ * It can generate buggy code on targets which assembly generation depends on alignment.+ * But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6)+ * See https://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details.+ * Prefer these methods in priority order (0 > 1 > 2)+ */+#ifndef LZ4_FORCE_MEMORY_ACCESS /* can be defined externally */+# if defined(__GNUC__) && \+ ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) \+ || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) )+# define LZ4_FORCE_MEMORY_ACCESS 2+# elif (defined(__INTEL_COMPILER) && !defined(_WIN32)) || defined(__GNUC__)+# define LZ4_FORCE_MEMORY_ACCESS 1+# endif+#endif++/*+ * LZ4_FORCE_SW_BITCOUNT+ * Define this parameter if your target system or compiler does not support hardware bit count+ */+#if defined(_MSC_VER) && defined(_WIN32_WCE) /* Visual Studio for WinCE doesn't support Hardware bit count */+# undef LZ4_FORCE_SW_BITCOUNT /* avoid double def */+# define LZ4_FORCE_SW_BITCOUNT+#endif++++/*-************************************+* Dependency+**************************************/+/*+ * LZ4_SRC_INCLUDED:+ * Amalgamation flag, whether lz4.c is included+ */+#ifndef LZ4_SRC_INCLUDED+# define LZ4_SRC_INCLUDED 1+#endif++#ifndef LZ4_STATIC_LINKING_ONLY+#define LZ4_STATIC_LINKING_ONLY+#endif++#ifndef LZ4_DISABLE_DEPRECATE_WARNINGS+#define LZ4_DISABLE_DEPRECATE_WARNINGS /* due to LZ4_decompress_safe_withPrefix64k */+#endif++#define LZ4_STATIC_LINKING_ONLY /* LZ4_DISTANCE_MAX */+#include "tracy_lz4.hpp"+/* see also "memory routines" below */+++/*-************************************+* Compiler Options+**************************************/+#if defined(_MSC_VER) && (_MSC_VER >= 1400) /* Visual Studio 2005+ */+# include <intrin.h> /* only present in VS2005+ */+# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */+# pragma warning(disable : 6237) /* disable: C6237: conditional expression is always 0 */+#endif /* _MSC_VER */++#ifndef LZ4_FORCE_INLINE+# if defined (_MSC_VER) && !defined (__clang__) /* MSVC */+# define LZ4_FORCE_INLINE static __forceinline+# else+# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */+# if defined (__GNUC__) || defined (__clang__)+# define LZ4_FORCE_INLINE static inline __attribute__((always_inline))+# else+# define LZ4_FORCE_INLINE static inline+# endif+# else+# define LZ4_FORCE_INLINE static+# endif /* __STDC_VERSION__ */+# endif /* _MSC_VER */+#endif /* LZ4_FORCE_INLINE */++/* LZ4_FORCE_O2 and LZ4_FORCE_INLINE+ * gcc on ppc64le generates an unrolled SIMDized loop for LZ4_wildCopy8,+ * together with a simple 8-byte copy loop as a fall-back path.+ * However, this optimization hurts the decompression speed by >30%,+ * because the execution does not go to the optimized loop+ * for typical compressible data, and all of the preamble checks+ * before going to the fall-back path become useless overhead.+ * This optimization happens only with the -O3 flag, and -O2 generates+ * a simple 8-byte copy loop.+ * With gcc on ppc64le, all of the LZ4_decompress_* and LZ4_wildCopy8+ * functions are annotated with __attribute__((optimize("O2"))),+ * and also LZ4_wildCopy8 is forcibly inlined, so that the O2 attribute+ * of LZ4_wildCopy8 does not affect the compression speed.+ */+#if defined(__PPC64__) && defined(__LITTLE_ENDIAN__) && defined(__GNUC__) && !defined(__clang__)+# define LZ4_FORCE_O2 __attribute__((optimize("O2")))+# undef LZ4_FORCE_INLINE+# define LZ4_FORCE_INLINE static __inline __attribute__((optimize("O2"),always_inline))+#else+# define LZ4_FORCE_O2+#endif++#if (defined(__GNUC__) && (__GNUC__ >= 3)) || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) || defined(__clang__)+# define expect(expr,value) (__builtin_expect ((expr),(value)) )+#else+# define expect(expr,value) (expr)+#endif++#ifndef likely+#define likely(expr) expect((expr) != 0, 1)+#endif+#ifndef unlikely+#define unlikely(expr) expect((expr) != 0, 0)+#endif++/* Should the alignment test prove unreliable, for some reason,+ * it can be disabled by setting LZ4_ALIGN_TEST to 0 */+#ifndef LZ4_ALIGN_TEST /* can be externally provided */+# define LZ4_ALIGN_TEST 1+#endif+++/*-************************************+* Memory routines+**************************************/++/*! LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION :+ * Disable relatively high-level LZ4/HC functions that use dynamic memory+ * allocation functions (malloc(), calloc(), free()).+ *+ * Note that this is a compile-time switch. And since it disables+ * public/stable LZ4 v1 API functions, we don't recommend using this+ * symbol to generate a library for distribution.+ *+ * The following public functions are removed when this symbol is defined.+ * - lz4 : LZ4_createStream, LZ4_freeStream,+ * LZ4_createStreamDecode, LZ4_freeStreamDecode, LZ4_create (deprecated)+ * - lz4hc : LZ4_createStreamHC, LZ4_freeStreamHC,+ * LZ4_createHC (deprecated), LZ4_freeHC (deprecated)+ * - lz4frame, lz4file : All LZ4F_* functions+ */+#if defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)+# define ALLOC(s) lz4_error_memory_allocation_is_disabled+# define ALLOC_AND_ZERO(s) lz4_error_memory_allocation_is_disabled+# define FREEMEM(p) lz4_error_memory_allocation_is_disabled+#elif defined(LZ4_USER_MEMORY_FUNCTIONS)+/* memory management functions can be customized by user project.+ * Below functions must exist somewhere in the Project+ * and be available at link time */+void* LZ4_malloc(size_t s);+void* LZ4_calloc(size_t n, size_t s);+void LZ4_free(void* p);+# define ALLOC(s) LZ4_malloc(s)+# define ALLOC_AND_ZERO(s) LZ4_calloc(1,s)+# define FREEMEM(p) LZ4_free(p)+#else+# include <stdlib.h> /* malloc, calloc, free */+# define ALLOC(s) malloc(s)+# define ALLOC_AND_ZERO(s) calloc(1,s)+# define FREEMEM(p) free(p)+#endif++#if ! LZ4_FREESTANDING+# include <string.h> /* memset, memcpy */+#endif+#if !defined(LZ4_memset)+# define LZ4_memset(p,v,s) memset((p),(v),(s))+#endif+#define MEM_INIT(p,v,s) LZ4_memset((p),(v),(s))+++/*-************************************+* Common Constants+**************************************/+#define MINMATCH 4++#define WILDCOPYLENGTH 8+#define LASTLITERALS 5 /* see ../doc/lz4_Block_format.md#parsing-restrictions */+#define MFLIMIT 12 /* see ../doc/lz4_Block_format.md#parsing-restrictions */+#define MATCH_SAFEGUARD_DISTANCE ((2*WILDCOPYLENGTH) - MINMATCH) /* ensure it's possible to write 2 x wildcopyLength without overflowing output buffer */+#define FASTLOOP_SAFE_DISTANCE 64+static const int LZ4_minLength = (MFLIMIT+1);++#define KB *(1 <<10)+#define MB *(1 <<20)+#define GB *(1U<<30)++#define LZ4_DISTANCE_ABSOLUTE_MAX 65535+#if (LZ4_DISTANCE_MAX > LZ4_DISTANCE_ABSOLUTE_MAX) /* max supported by LZ4 format */+# error "LZ4_DISTANCE_MAX is too big : must be <= 65535"+#endif++#define ML_BITS 4+#define ML_MASK ((1U<<ML_BITS)-1)+#define RUN_BITS (8-ML_BITS)+#define RUN_MASK ((1U<<RUN_BITS)-1)+++/*-************************************+* Error detection+**************************************/+#if defined(LZ4_DEBUG) && (LZ4_DEBUG>=1)+# include <assert.h>+#else+# ifndef assert+# define assert(condition) ((void)0)+# endif+#endif++#define LZ4_STATIC_ASSERT(c) { enum { LZ4_static_assert = 1/(int)(!!(c)) }; } /* use after variable declarations */++#if defined(LZ4_DEBUG) && (LZ4_DEBUG>=2)+# include <stdio.h>+ static int g_debuglog_enable = 1;+# define DEBUGLOG(l, ...) { \+ if ((g_debuglog_enable) && (l<=LZ4_DEBUG)) { \+ fprintf(stderr, __FILE__ ": "); \+ fprintf(stderr, __VA_ARGS__); \+ fprintf(stderr, " \n"); \+ } }+#else+# define DEBUGLOG(l, ...) {} /* disabled */+#endif++static int LZ4_isAligned(const void* ptr, size_t alignment)+{+ return ((size_t)ptr & (alignment -1)) == 0;+}+++/*-************************************+* Types+**************************************/+#include <limits.h>+#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)+# include <stdint.h>+ typedef uint8_t BYTE;+ typedef uint16_t U16;+ typedef uint32_t U32;+ typedef int32_t S32;+ typedef uint64_t U64;+ typedef uintptr_t uptrval;+#else+# if UINT_MAX != 4294967295UL+# error "LZ4 code (when not C++ or C99) assumes that sizeof(int) == 4"+# endif+ typedef unsigned char BYTE;+ typedef unsigned short U16;+ typedef unsigned int U32;+ typedef signed int S32;+ typedef unsigned long long U64;+ typedef size_t uptrval; /* generally true, except OpenVMS-64 */+#endif++#if defined(__x86_64__)+ typedef U64 reg_t; /* 64-bits in x32 mode */+#else+ typedef size_t reg_t; /* 32-bits in x32 mode */+#endif++typedef enum {+ notLimited = 0,+ limitedOutput = 1,+ fillOutput = 2+} limitedOutput_directive;++namespace tracy+{++/*-************************************+* Reading and writing into memory+**************************************/++/**+ * LZ4 relies on memcpy with a constant size being inlined. In freestanding+ * environments, the compiler can't assume the implementation of memcpy() is+ * standard compliant, so it can't apply its specialized memcpy() inlining+ * logic. When possible, use __builtin_memcpy() to tell the compiler to analyze+ * memcpy() as if it were standard compliant, so it can inline it in freestanding+ * environments. This is needed when decompressing the Linux Kernel, for example.+ */+#if !defined(LZ4_memcpy)+# if defined(__GNUC__) && (__GNUC__ >= 4)+# define LZ4_memcpy(dst, src, size) __builtin_memcpy(dst, src, size)+# else+# define LZ4_memcpy(dst, src, size) memcpy(dst, src, size)+# endif+#endif++#if !defined(LZ4_memmove)+# if defined(__GNUC__) && (__GNUC__ >= 4)+# define LZ4_memmove __builtin_memmove+# else+# define LZ4_memmove memmove+# endif+#endif++static unsigned LZ4_isLittleEndian(void)+{+ const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */+ return one.c[0];+}+++#if defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS==2)+/* lie to the compiler about data alignment; use with caution */++static U16 LZ4_read16(const void* memPtr) { return *(const U16*) memPtr; }+static U32 LZ4_read32(const void* memPtr) { return *(const U32*) memPtr; }+static reg_t LZ4_read_ARCH(const void* memPtr) { return *(const reg_t*) memPtr; }++static void LZ4_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; }+static void LZ4_write32(void* memPtr, U32 value) { *(U32*)memPtr = value; }++#elif defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_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 { U16 u16; U32 u32; reg_t uArch; } __attribute__((packed)) LZ4_unalign;++static U16 LZ4_read16(const void* ptr) { return ((const LZ4_unalign*)ptr)->u16; }+static U32 LZ4_read32(const void* ptr) { return ((const LZ4_unalign*)ptr)->u32; }+static reg_t LZ4_read_ARCH(const void* ptr) { return ((const LZ4_unalign*)ptr)->uArch; }++static void LZ4_write16(void* memPtr, U16 value) { ((LZ4_unalign*)memPtr)->u16 = value; }+static void LZ4_write32(void* memPtr, U32 value) { ((LZ4_unalign*)memPtr)->u32 = value; }++#else /* safe and portable access using memcpy() */++static U16 LZ4_read16(const void* memPtr)+{+ U16 val; LZ4_memcpy(&val, memPtr, sizeof(val)); return val;+}++static U32 LZ4_read32(const void* memPtr)+{+ U32 val; LZ4_memcpy(&val, memPtr, sizeof(val)); return val;+}++static reg_t LZ4_read_ARCH(const void* memPtr)+{+ reg_t val; LZ4_memcpy(&val, memPtr, sizeof(val)); return val;+}++static void LZ4_write16(void* memPtr, U16 value)+{+ LZ4_memcpy(memPtr, &value, sizeof(value));+}++static void LZ4_write32(void* memPtr, U32 value)+{+ LZ4_memcpy(memPtr, &value, sizeof(value));+}++#endif /* LZ4_FORCE_MEMORY_ACCESS */+++static U16 LZ4_readLE16(const void* memPtr)+{+ if (LZ4_isLittleEndian()) {+ return LZ4_read16(memPtr);+ } else {+ const BYTE* p = (const BYTE*)memPtr;+ return (U16)((U16)p[0] + (p[1]<<8));+ }+}++static void LZ4_writeLE16(void* memPtr, U16 value)+{+ if (LZ4_isLittleEndian()) {+ LZ4_write16(memPtr, value);+ } else {+ BYTE* p = (BYTE*)memPtr;+ p[0] = (BYTE) value;+ p[1] = (BYTE)(value>>8);+ }+}++/* customized variant of memcpy, which can overwrite up to 8 bytes beyond dstEnd */+LZ4_FORCE_INLINE+void LZ4_wildCopy8(void* dstPtr, const void* srcPtr, void* dstEnd)+{+ BYTE* d = (BYTE*)dstPtr;+ const BYTE* s = (const BYTE*)srcPtr;+ BYTE* const e = (BYTE*)dstEnd;++ do { LZ4_memcpy(d,s,8); d+=8; s+=8; } while (d<e);+}++static const unsigned inc32table[8] = {0, 1, 2, 1, 0, 4, 4, 4};+static const int dec64table[8] = {0, 0, 0, -1, -4, 1, 2, 3};+++#ifndef LZ4_FAST_DEC_LOOP+# if defined __i386__ || defined _M_IX86 || defined __x86_64__ || defined _M_X64+# define LZ4_FAST_DEC_LOOP 1+# elif defined(__aarch64__) && defined(__APPLE__)+# define LZ4_FAST_DEC_LOOP 1+# elif defined(__aarch64__) && !defined(__clang__)+ /* On non-Apple aarch64, we disable this optimization for clang because+ * on certain mobile chipsets, performance is reduced with clang. For+ * more information refer to https://github.com/lz4/lz4/pull/707 */+# define LZ4_FAST_DEC_LOOP 1+# else+# define LZ4_FAST_DEC_LOOP 0+# endif+#endif++#if LZ4_FAST_DEC_LOOP++LZ4_FORCE_INLINE void+LZ4_memcpy_using_offset_base(BYTE* dstPtr, const BYTE* srcPtr, BYTE* dstEnd, const size_t offset)+{+ assert(srcPtr + offset == dstPtr);+ if (offset < 8) {+ LZ4_write32(dstPtr, 0); /* silence an msan warning when offset==0 */+ dstPtr[0] = srcPtr[0];+ dstPtr[1] = srcPtr[1];+ dstPtr[2] = srcPtr[2];+ dstPtr[3] = srcPtr[3];+ srcPtr += inc32table[offset];+ LZ4_memcpy(dstPtr+4, srcPtr, 4);+ srcPtr -= dec64table[offset];+ dstPtr += 8;+ } else {+ LZ4_memcpy(dstPtr, srcPtr, 8);+ dstPtr += 8;+ srcPtr += 8;+ }++ LZ4_wildCopy8(dstPtr, srcPtr, dstEnd);+}++/* customized variant of memcpy, which can overwrite up to 32 bytes beyond dstEnd+ * this version copies two times 16 bytes (instead of one time 32 bytes)+ * because it must be compatible with offsets >= 16. */+LZ4_FORCE_INLINE void+LZ4_wildCopy32(void* dstPtr, const void* srcPtr, void* dstEnd)+{+ BYTE* d = (BYTE*)dstPtr;+ const BYTE* s = (const BYTE*)srcPtr;+ BYTE* const e = (BYTE*)dstEnd;++ do { LZ4_memcpy(d,s,16); LZ4_memcpy(d+16,s+16,16); d+=32; s+=32; } while (d<e);+}++/* LZ4_memcpy_using_offset() presumes :+ * - dstEnd >= dstPtr + MINMATCH+ * - there is at least 8 bytes available to write after dstEnd */+LZ4_FORCE_INLINE void+LZ4_memcpy_using_offset(BYTE* dstPtr, const BYTE* srcPtr, BYTE* dstEnd, const size_t offset)+{+ BYTE v[8];++ assert(dstEnd >= dstPtr + MINMATCH);++ switch(offset) {+ case 1:+ MEM_INIT(v, *srcPtr, 8);+ break;+ case 2:+ LZ4_memcpy(v, srcPtr, 2);+ LZ4_memcpy(&v[2], srcPtr, 2);+#if defined(_MSC_VER) && (_MSC_VER <= 1933) /* MSVC 2022 ver 17.3 or earlier */+# pragma warning(push)+# pragma warning(disable : 6385) /* warning C6385: Reading invalid data from 'v'. */+#endif+ LZ4_memcpy(&v[4], v, 4);+#if defined(_MSC_VER) && (_MSC_VER <= 1933) /* MSVC 2022 ver 17.3 or earlier */+# pragma warning(pop)+#endif+ break;+ case 4:+ LZ4_memcpy(v, srcPtr, 4);+ LZ4_memcpy(&v[4], srcPtr, 4);+ break;+ default:+ LZ4_memcpy_using_offset_base(dstPtr, srcPtr, dstEnd, offset);+ return;+ }++ LZ4_memcpy(dstPtr, v, 8);+ dstPtr += 8;+ while (dstPtr < dstEnd) {+ LZ4_memcpy(dstPtr, v, 8);+ dstPtr += 8;+ }+}+#endif+++/*-************************************+* Common functions+**************************************/+LZ4_FORCE_INLINE unsigned LZ4_NbCommonBytes (reg_t val)+{+ assert(val != 0);+ if (LZ4_isLittleEndian()) {+ if (sizeof(val) == 8) {+# if defined(_MSC_VER) && (_MSC_VER >= 1800) && (defined(_M_AMD64) && !defined(_M_ARM64EC)) && !defined(LZ4_FORCE_SW_BITCOUNT)+/*-*************************************************************************************************+* ARM64EC is a Microsoft-designed ARM64 ABI compatible with AMD64 applications on ARM64 Windows 11.+* The ARM64EC ABI does not support AVX/AVX2/AVX512 instructions, nor their relevant intrinsics+* including _tzcnt_u64. Therefore, we need to neuter the _tzcnt_u64 code path for ARM64EC.+****************************************************************************************************/+# if defined(__clang__) && (__clang_major__ < 10)+ /* Avoid undefined clang-cl intrinsics issue.+ * See https://github.com/lz4/lz4/pull/1017 for details. */+ return (unsigned)__builtin_ia32_tzcnt_u64(val) >> 3;+# else+ /* x64 CPUS without BMI support interpret `TZCNT` as `REP BSF` */+ return (unsigned)_tzcnt_u64(val) >> 3;+# endif+# elif defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT)+ unsigned long r = 0;+ _BitScanForward64(&r, (U64)val);+ return (unsigned)r >> 3;+# elif (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \+ ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \+ !defined(LZ4_FORCE_SW_BITCOUNT)+ return (unsigned)__builtin_ctzll((U64)val) >> 3;+# else+ const U64 m = 0x0101010101010101ULL;+ val ^= val - 1;+ return (unsigned)(((U64)((val & (m - 1)) * m)) >> 56);+# endif+ } else /* 32 bits */ {+# if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(LZ4_FORCE_SW_BITCOUNT)+ unsigned long r;+ _BitScanForward(&r, (U32)val);+ return (unsigned)r >> 3;+# elif (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \+ ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \+ !defined(__TINYC__) && !defined(LZ4_FORCE_SW_BITCOUNT)+ return (unsigned)__builtin_ctz((U32)val) >> 3;+# else+ const U32 m = 0x01010101;+ return (unsigned)((((val - 1) ^ val) & (m - 1)) * m) >> 24;+# endif+ }+ } else /* Big Endian CPU */ {+ if (sizeof(val)==8) {+# if (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \+ ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \+ !defined(__TINYC__) && !defined(LZ4_FORCE_SW_BITCOUNT)+ return (unsigned)__builtin_clzll((U64)val) >> 3;+# else+#if 1+ /* this method is probably faster,+ * but adds a 128 bytes lookup table */+ static const unsigned char ctz7_tab[128] = {+ 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,+ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,+ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,+ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,+ };+ U64 const mask = 0x0101010101010101ULL;+ U64 const t = (((val >> 8) - mask) | val) & mask;+ return ctz7_tab[(t * 0x0080402010080402ULL) >> 57];+#else+ /* this method doesn't consume memory space like the previous one,+ * but it contains several branches,+ * that may end up slowing execution */+ static const U32 by32 = sizeof(val)*4; /* 32 on 64 bits (goal), 16 on 32 bits.+ Just to avoid some static analyzer complaining about shift by 32 on 32-bits target.+ Note that this code path is never triggered in 32-bits mode. */+ unsigned r;+ if (!(val>>by32)) { r=4; } else { r=0; val>>=by32; }+ if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }+ r += (!val);+ return r;+#endif+# endif+ } else /* 32 bits */ {+# if (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \+ ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \+ !defined(LZ4_FORCE_SW_BITCOUNT)+ return (unsigned)__builtin_clz((U32)val) >> 3;+# else+ val >>= 8;+ val = ((((val + 0x00FFFF00) | 0x00FFFFFF) + val) |+ (val + 0x00FF0000)) >> 24;+ return (unsigned)val ^ 3;+# endif+ }+ }+}+++#define STEPSIZE sizeof(reg_t)+LZ4_FORCE_INLINE+unsigned LZ4_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit)+{+ const BYTE* const pStart = pIn;++ if (likely(pIn < pInLimit-(STEPSIZE-1))) {+ reg_t const diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn);+ if (!diff) {+ pIn+=STEPSIZE; pMatch+=STEPSIZE;+ } else {+ return LZ4_NbCommonBytes(diff);+ } }++ while (likely(pIn < pInLimit-(STEPSIZE-1))) {+ reg_t const diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn);+ if (!diff) { pIn+=STEPSIZE; pMatch+=STEPSIZE; continue; }+ pIn += LZ4_NbCommonBytes(diff);+ return (unsigned)(pIn - pStart);+ }++ if ((STEPSIZE==8) && (pIn<(pInLimit-3)) && (LZ4_read32(pMatch) == LZ4_read32(pIn))) { pIn+=4; pMatch+=4; }+ if ((pIn<(pInLimit-1)) && (LZ4_read16(pMatch) == LZ4_read16(pIn))) { pIn+=2; pMatch+=2; }+ if ((pIn<pInLimit) && (*pMatch == *pIn)) pIn++;+ return (unsigned)(pIn - pStart);+}+++#ifndef LZ4_COMMONDEFS_ONLY+/*-************************************+* Local Constants+**************************************/+static const int LZ4_64Klimit = ((64 KB) + (MFLIMIT-1));+static const U32 LZ4_skipTrigger = 6; /* Increase this value ==> compression run slower on incompressible data */+++/*-************************************+* Local Structures and types+**************************************/+typedef enum { clearedTable = 0, byPtr, byU32, byU16 } tableType_t;++/**+ * This enum distinguishes several different modes of accessing previous+ * content in the stream.+ *+ * - noDict : There is no preceding content.+ * - withPrefix64k : Table entries up to ctx->dictSize before the current blob+ * blob being compressed are valid and refer to the preceding+ * content (of length ctx->dictSize), which is available+ * contiguously preceding in memory the content currently+ * being compressed.+ * - usingExtDict : Like withPrefix64k, but the preceding content is somewhere+ * else in memory, starting at ctx->dictionary with length+ * ctx->dictSize.+ * - usingDictCtx : Everything concerning the preceding content is+ * in a separate context, pointed to by ctx->dictCtx.+ * ctx->dictionary, ctx->dictSize, and table entries+ * in the current context that refer to positions+ * preceding the beginning of the current compression are+ * ignored. Instead, ctx->dictCtx->dictionary and ctx->dictCtx+ * ->dictSize describe the location and size of the preceding+ * content, and matches are found by looking in the ctx+ * ->dictCtx->hashTable.+ */+typedef enum { noDict = 0, withPrefix64k, usingExtDict, usingDictCtx } dict_directive;+typedef enum { noDictIssue = 0, dictSmall } dictIssue_directive;+++/*-************************************+* Local Utils+**************************************/+int LZ4_versionNumber (void) { return LZ4_VERSION_NUMBER; }+const char* LZ4_versionString(void) { return LZ4_VERSION_STRING; }+int LZ4_compressBound(int isize) { return LZ4_COMPRESSBOUND(isize); }+int LZ4_sizeofState(void) { return sizeof(LZ4_stream_t); }+++/*-****************************************+* Internal Definitions, used only in Tests+*******************************************/++int LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_dict, const char* source, char* dest, int srcSize);++int LZ4_decompress_safe_forceExtDict(const char* source, char* dest,+ int compressedSize, int maxOutputSize,+ const void* dictStart, size_t dictSize);+int LZ4_decompress_safe_partial_forceExtDict(const char* source, char* dest,+ int compressedSize, int targetOutputSize, int dstCapacity,+ const void* dictStart, size_t dictSize);++/*-******************************+* Compression functions+********************************/+LZ4_FORCE_INLINE U32 LZ4_hash4(U32 sequence, tableType_t const tableType)+{+ if (tableType == byU16)+ return ((sequence * 2654435761U) >> ((MINMATCH*8)-(LZ4_HASHLOG+1)));+ else+ return ((sequence * 2654435761U) >> ((MINMATCH*8)-LZ4_HASHLOG));+}++LZ4_FORCE_INLINE U32 LZ4_hash5(U64 sequence, tableType_t const tableType)+{+ const U32 hashLog = (tableType == byU16) ? LZ4_HASHLOG+1 : LZ4_HASHLOG;+ if (LZ4_isLittleEndian()) {+ const U64 prime5bytes = 889523592379ULL;+ return (U32)(((sequence << 24) * prime5bytes) >> (64 - hashLog));+ } else {+ const U64 prime8bytes = 11400714785074694791ULL;+ return (U32)(((sequence >> 24) * prime8bytes) >> (64 - hashLog));+ }+}++LZ4_FORCE_INLINE U32 LZ4_hashPosition(const void* const p, tableType_t const tableType)+{+ if ((sizeof(reg_t)==8) && (tableType != byU16)) return LZ4_hash5(LZ4_read_ARCH(p), tableType);+ return LZ4_hash4(LZ4_read32(p), tableType);+}++LZ4_FORCE_INLINE void LZ4_clearHash(U32 h, void* tableBase, tableType_t const tableType)+{+ switch (tableType)+ {+ default: /* fallthrough */+ case clearedTable: { /* illegal! */ assert(0); return; }+ case byPtr: { const BYTE** hashTable = (const BYTE**)tableBase; hashTable[h] = NULL; return; }+ case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = 0; return; }+ case byU16: { U16* hashTable = (U16*) tableBase; hashTable[h] = 0; return; }+ }+}++LZ4_FORCE_INLINE void LZ4_putIndexOnHash(U32 idx, U32 h, void* tableBase, tableType_t const tableType)+{+ switch (tableType)+ {+ default: /* fallthrough */+ case clearedTable: /* fallthrough */+ case byPtr: { /* illegal! */ assert(0); return; }+ case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = idx; return; }+ case byU16: { U16* hashTable = (U16*) tableBase; assert(idx < 65536); hashTable[h] = (U16)idx; return; }+ }+}++LZ4_FORCE_INLINE void LZ4_putPositionOnHash(const BYTE* p, U32 h,+ void* tableBase, tableType_t const tableType,+ const BYTE* srcBase)+{+ switch (tableType)+ {+ case clearedTable: { /* illegal! */ assert(0); return; }+ case byPtr: { const BYTE** hashTable = (const BYTE**)tableBase; hashTable[h] = p; return; }+ case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = (U32)(p-srcBase); return; }+ case byU16: { U16* hashTable = (U16*) tableBase; hashTable[h] = (U16)(p-srcBase); return; }+ }+}++LZ4_FORCE_INLINE void LZ4_putPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase)+{+ U32 const h = LZ4_hashPosition(p, tableType);+ LZ4_putPositionOnHash(p, h, tableBase, tableType, srcBase);+}++/* LZ4_getIndexOnHash() :+ * Index of match position registered in hash table.+ * hash position must be calculated by using base+index, or dictBase+index.+ * Assumption 1 : only valid if tableType == byU32 or byU16.+ * Assumption 2 : h is presumed valid (within limits of hash table)+ */+LZ4_FORCE_INLINE U32 LZ4_getIndexOnHash(U32 h, const void* tableBase, tableType_t tableType)+{+ LZ4_STATIC_ASSERT(LZ4_MEMORY_USAGE > 2);+ if (tableType == byU32) {+ const U32* const hashTable = (const U32*) tableBase;+ assert(h < (1U << (LZ4_MEMORY_USAGE-2)));+ return hashTable[h];+ }+ if (tableType == byU16) {+ const U16* const hashTable = (const U16*) tableBase;+ assert(h < (1U << (LZ4_MEMORY_USAGE-1)));+ return hashTable[h];+ }+ assert(0); return 0; /* forbidden case */+}++static const BYTE* LZ4_getPositionOnHash(U32 h, const void* tableBase, tableType_t tableType, const BYTE* srcBase)+{+ if (tableType == byPtr) { const BYTE* const* hashTable = (const BYTE* const*) tableBase; return hashTable[h]; }+ if (tableType == byU32) { const U32* const hashTable = (const U32*) tableBase; return hashTable[h] + srcBase; }+ { const U16* const hashTable = (const U16*) tableBase; return hashTable[h] + srcBase; } /* default, to ensure a return */+}++LZ4_FORCE_INLINE const BYTE*+LZ4_getPosition(const BYTE* p,+ const void* tableBase, tableType_t tableType,+ const BYTE* srcBase)+{+ U32 const h = LZ4_hashPosition(p, tableType);+ return LZ4_getPositionOnHash(h, tableBase, tableType, srcBase);+}++LZ4_FORCE_INLINE void+LZ4_prepareTable(LZ4_stream_t_internal* const cctx,+ const int inputSize,+ const tableType_t tableType) {+ /* If the table hasn't been used, it's guaranteed to be zeroed out, and is+ * therefore safe to use no matter what mode we're in. Otherwise, we figure+ * out if it's safe to leave as is or whether it needs to be reset.+ */+ if ((tableType_t)cctx->tableType != clearedTable) {+ assert(inputSize >= 0);+ if ((tableType_t)cctx->tableType != tableType+ || ((tableType == byU16) && cctx->currentOffset + (unsigned)inputSize >= 0xFFFFU)+ || ((tableType == byU32) && cctx->currentOffset > 1 GB)+ || tableType == byPtr+ || inputSize >= 4 KB)+ {+ DEBUGLOG(4, "LZ4_prepareTable: Resetting table in %p", cctx);+ MEM_INIT(cctx->hashTable, 0, LZ4_HASHTABLESIZE);+ cctx->currentOffset = 0;+ cctx->tableType = (U32)clearedTable;+ } else {+ DEBUGLOG(4, "LZ4_prepareTable: Re-use hash table (no reset)");+ }+ }++ /* Adding a gap, so all previous entries are > LZ4_DISTANCE_MAX back,+ * is faster than compressing without a gap.+ * However, compressing with currentOffset == 0 is faster still,+ * so we preserve that case.+ */+ if (cctx->currentOffset != 0 && tableType == byU32) {+ DEBUGLOG(5, "LZ4_prepareTable: adding 64KB to currentOffset");+ cctx->currentOffset += 64 KB;+ }++ /* Finally, clear history */+ cctx->dictCtx = NULL;+ cctx->dictionary = NULL;+ cctx->dictSize = 0;+}++/** LZ4_compress_generic() :+ * inlined, to ensure branches are decided at compilation time.+ * Presumed already validated at this stage:+ * - source != NULL+ * - inputSize > 0+ */+LZ4_FORCE_INLINE int LZ4_compress_generic_validated(+ LZ4_stream_t_internal* const cctx,+ const char* const source,+ char* const dest,+ const int inputSize,+ int* inputConsumed, /* only written when outputDirective == fillOutput */+ const int maxOutputSize,+ const limitedOutput_directive outputDirective,+ const tableType_t tableType,+ const dict_directive dictDirective,+ const dictIssue_directive dictIssue,+ const int acceleration)+{+ int result;+ const BYTE* ip = (const BYTE*) source;++ U32 const startIndex = cctx->currentOffset;+ const BYTE* base = (const BYTE*) source - startIndex;+ const BYTE* lowLimit;++ const LZ4_stream_t_internal* dictCtx = (const LZ4_stream_t_internal*) cctx->dictCtx;+ const BYTE* const dictionary =+ dictDirective == usingDictCtx ? dictCtx->dictionary : cctx->dictionary;+ const U32 dictSize =+ dictDirective == usingDictCtx ? dictCtx->dictSize : cctx->dictSize;+ const U32 dictDelta = (dictDirective == usingDictCtx) ? startIndex - dictCtx->currentOffset : 0; /* make indexes in dictCtx comparable with index in current context */++ int const maybe_extMem = (dictDirective == usingExtDict) || (dictDirective == usingDictCtx);+ U32 const prefixIdxLimit = startIndex - dictSize; /* used when dictDirective == dictSmall */+ const BYTE* const dictEnd = dictionary ? dictionary + dictSize : dictionary;+ const BYTE* anchor = (const BYTE*) source;+ const BYTE* const iend = ip + inputSize;+ const BYTE* const mflimitPlusOne = iend - MFLIMIT + 1;+ const BYTE* const matchlimit = iend - LASTLITERALS;++ /* the dictCtx currentOffset is indexed on the start of the dictionary,+ * while a dictionary in the current context precedes the currentOffset */+ const BYTE* dictBase = (dictionary == NULL) ? NULL :+ (dictDirective == usingDictCtx) ?+ dictionary + dictSize - dictCtx->currentOffset :+ dictionary + dictSize - startIndex;++ BYTE* op = (BYTE*) dest;+ BYTE* const olimit = op + maxOutputSize;++ U32 offset = 0;+ U32 forwardH;++ DEBUGLOG(5, "LZ4_compress_generic_validated: srcSize=%i, tableType=%u", inputSize, tableType);+ assert(ip != NULL);+ /* If init conditions are not met, we don't have to mark stream+ * as having dirty context, since no action was taken yet */+ if (outputDirective == fillOutput && maxOutputSize < 1) { return 0; } /* Impossible to store anything */+ if ((tableType == byU16) && (inputSize>=LZ4_64Klimit)) { return 0; } /* Size too large (not within 64K limit) */+ if (tableType==byPtr) assert(dictDirective==noDict); /* only supported use case with byPtr */+ assert(acceleration >= 1);++ lowLimit = (const BYTE*)source - (dictDirective == withPrefix64k ? dictSize : 0);++ /* Update context state */+ if (dictDirective == usingDictCtx) {+ /* Subsequent linked blocks can't use the dictionary. */+ /* Instead, they use the block we just compressed. */+ cctx->dictCtx = NULL;+ cctx->dictSize = (U32)inputSize;+ } else {+ cctx->dictSize += (U32)inputSize;+ }+ cctx->currentOffset += (U32)inputSize;+ cctx->tableType = (U32)tableType;++ if (inputSize<LZ4_minLength) goto _last_literals; /* Input too small, no compression (all literals) */++ /* First Byte */+ LZ4_putPosition(ip, cctx->hashTable, tableType, base);+ ip++; forwardH = LZ4_hashPosition(ip, tableType);++ /* Main Loop */+ for ( ; ; ) {+ const BYTE* match;+ BYTE* token;+ const BYTE* filledIp;++ /* Find a match */+ if (tableType == byPtr) {+ const BYTE* forwardIp = ip;+ int step = 1;+ int searchMatchNb = acceleration << LZ4_skipTrigger;+ do {+ U32 const h = forwardH;+ ip = forwardIp;+ forwardIp += step;+ step = (searchMatchNb++ >> LZ4_skipTrigger);++ if (unlikely(forwardIp > mflimitPlusOne)) goto _last_literals;+ assert(ip < mflimitPlusOne);++ match = LZ4_getPositionOnHash(h, cctx->hashTable, tableType, base);+ forwardH = LZ4_hashPosition(forwardIp, tableType);+ LZ4_putPositionOnHash(ip, h, cctx->hashTable, tableType, base);++ } while ( (match+LZ4_DISTANCE_MAX < ip)+ || (LZ4_read32(match) != LZ4_read32(ip)) );++ } else { /* byU32, byU16 */++ const BYTE* forwardIp = ip;+ int step = 1;+ int searchMatchNb = acceleration << LZ4_skipTrigger;+ do {+ U32 const h = forwardH;+ U32 const current = (U32)(forwardIp - base);+ U32 matchIndex = LZ4_getIndexOnHash(h, cctx->hashTable, tableType);+ assert(matchIndex <= current);+ assert(forwardIp - base < (ptrdiff_t)(2 GB - 1));+ ip = forwardIp;+ forwardIp += step;+ step = (searchMatchNb++ >> LZ4_skipTrigger);++ if (unlikely(forwardIp > mflimitPlusOne)) goto _last_literals;+ assert(ip < mflimitPlusOne);++ if (dictDirective == usingDictCtx) {+ if (matchIndex < startIndex) {+ /* there was no match, try the dictionary */+ assert(tableType == byU32);+ matchIndex = LZ4_getIndexOnHash(h, dictCtx->hashTable, byU32);+ match = dictBase + matchIndex;+ matchIndex += dictDelta; /* make dictCtx index comparable with current context */+ lowLimit = dictionary;+ } else {+ match = base + matchIndex;+ lowLimit = (const BYTE*)source;+ }+ } else if (dictDirective == usingExtDict) {+ if (matchIndex < startIndex) {+ DEBUGLOG(7, "extDict candidate: matchIndex=%5u < startIndex=%5u", matchIndex, startIndex);+ assert(startIndex - matchIndex >= MINMATCH);+ assert(dictBase);+ match = dictBase + matchIndex;+ lowLimit = dictionary;+ } else {+ match = base + matchIndex;+ lowLimit = (const BYTE*)source;+ }+ } else { /* single continuous memory segment */+ match = base + matchIndex;+ }+ forwardH = LZ4_hashPosition(forwardIp, tableType);+ LZ4_putIndexOnHash(current, h, cctx->hashTable, tableType);++ DEBUGLOG(7, "candidate at pos=%u (offset=%u \n", matchIndex, current - matchIndex);+ if ((dictIssue == dictSmall) && (matchIndex < prefixIdxLimit)) { continue; } /* match outside of valid area */+ assert(matchIndex < current);+ if ( ((tableType != byU16) || (LZ4_DISTANCE_MAX < LZ4_DISTANCE_ABSOLUTE_MAX))+ && (matchIndex+LZ4_DISTANCE_MAX < current)) {+ continue;+ } /* too far */+ assert((current - matchIndex) <= LZ4_DISTANCE_MAX); /* match now expected within distance */++ if (LZ4_read32(match) == LZ4_read32(ip)) {+ if (maybe_extMem) offset = current - matchIndex;+ break; /* match found */+ }++ } while(1);+ }++ /* Catch up */+ filledIp = ip;+ while (((ip>anchor) & (match > lowLimit)) && (unlikely(ip[-1]==match[-1]))) { ip--; match--; }++ /* Encode Literals */+ { unsigned const litLength = (unsigned)(ip - anchor);+ token = op++;+ if ((outputDirective == limitedOutput) && /* Check output buffer overflow */+ (unlikely(op + litLength + (2 + 1 + LASTLITERALS) + (litLength/255) > olimit)) ) {+ return 0; /* cannot compress within `dst` budget. Stored indexes in hash table are nonetheless fine */+ }+ if ((outputDirective == fillOutput) &&+ (unlikely(op + (litLength+240)/255 /* litlen */ + litLength /* literals */ + 2 /* offset */ + 1 /* token */ + MFLIMIT - MINMATCH /* min last literals so last match is <= end - MFLIMIT */ > olimit))) {+ op--;+ goto _last_literals;+ }+ if (litLength >= RUN_MASK) {+ int len = (int)(litLength - RUN_MASK);+ *token = (RUN_MASK<<ML_BITS);+ for(; len >= 255 ; len-=255) *op++ = 255;+ *op++ = (BYTE)len;+ }+ else *token = (BYTE)(litLength<<ML_BITS);++ /* Copy Literals */+ LZ4_wildCopy8(op, anchor, op+litLength);+ op+=litLength;+ DEBUGLOG(6, "seq.start:%i, literals=%u, match.start:%i",+ (int)(anchor-(const BYTE*)source), litLength, (int)(ip-(const BYTE*)source));+ }++_next_match:+ /* at this stage, the following variables must be correctly set :+ * - ip : at start of LZ operation+ * - match : at start of previous pattern occurrence; can be within current prefix, or within extDict+ * - offset : if maybe_ext_memSegment==1 (constant)+ * - lowLimit : must be == dictionary to mean "match is within extDict"; must be == source otherwise+ * - token and *token : position to write 4-bits for match length; higher 4-bits for literal length supposed already written+ */++ if ((outputDirective == fillOutput) &&+ (op + 2 /* offset */ + 1 /* token */ + MFLIMIT - MINMATCH /* min last literals so last match is <= end - MFLIMIT */ > olimit)) {+ /* the match was too close to the end, rewind and go to last literals */+ op = token;+ goto _last_literals;+ }++ /* Encode Offset */+ if (maybe_extMem) { /* static test */+ DEBUGLOG(6, " with offset=%u (ext if > %i)", offset, (int)(ip - (const BYTE*)source));+ assert(offset <= LZ4_DISTANCE_MAX && offset > 0);+ LZ4_writeLE16(op, (U16)offset); op+=2;+ } else {+ DEBUGLOG(6, " with offset=%u (same segment)", (U32)(ip - match));+ assert(ip-match <= LZ4_DISTANCE_MAX);+ LZ4_writeLE16(op, (U16)(ip - match)); op+=2;+ }++ /* Encode MatchLength */+ { unsigned matchCode;++ if ( (dictDirective==usingExtDict || dictDirective==usingDictCtx)+ && (lowLimit==dictionary) /* match within extDict */ ) {+ const BYTE* limit = ip + (dictEnd-match);+ assert(dictEnd > match);+ if (limit > matchlimit) limit = matchlimit;+ matchCode = LZ4_count(ip+MINMATCH, match+MINMATCH, limit);+ ip += (size_t)matchCode + MINMATCH;+ if (ip==limit) {+ unsigned const more = LZ4_count(limit, (const BYTE*)source, matchlimit);+ matchCode += more;+ ip += more;+ }+ DEBUGLOG(6, " with matchLength=%u starting in extDict", matchCode+MINMATCH);+ } else {+ matchCode = LZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit);+ ip += (size_t)matchCode + MINMATCH;+ DEBUGLOG(6, " with matchLength=%u", matchCode+MINMATCH);+ }++ if ((outputDirective) && /* Check output buffer overflow */+ (unlikely(op + (1 + LASTLITERALS) + (matchCode+240)/255 > olimit)) ) {+ if (outputDirective == fillOutput) {+ /* Match description too long : reduce it */+ U32 newMatchCode = 15 /* in token */ - 1 /* to avoid needing a zero byte */ + ((U32)(olimit - op) - 1 - LASTLITERALS) * 255;+ ip -= matchCode - newMatchCode;+ assert(newMatchCode < matchCode);+ matchCode = newMatchCode;+ if (unlikely(ip <= filledIp)) {+ /* We have already filled up to filledIp so if ip ends up less than filledIp+ * we have positions in the hash table beyond the current position. This is+ * a problem if we reuse the hash table. So we have to remove these positions+ * from the hash table.+ */+ const BYTE* ptr;+ DEBUGLOG(5, "Clearing %u positions", (U32)(filledIp - ip));+ for (ptr = ip; ptr <= filledIp; ++ptr) {+ U32 const h = LZ4_hashPosition(ptr, tableType);+ LZ4_clearHash(h, cctx->hashTable, tableType);+ }+ }+ } else {+ assert(outputDirective == limitedOutput);+ return 0; /* cannot compress within `dst` budget. Stored indexes in hash table are nonetheless fine */+ }+ }+ if (matchCode >= ML_MASK) {+ *token += ML_MASK;+ matchCode -= ML_MASK;+ LZ4_write32(op, 0xFFFFFFFF);+ while (matchCode >= 4*255) {+ op+=4;+ LZ4_write32(op, 0xFFFFFFFF);+ matchCode -= 4*255;+ }+ op += matchCode / 255;+ *op++ = (BYTE)(matchCode % 255);+ } else+ *token += (BYTE)(matchCode);+ }+ /* Ensure we have enough space for the last literals. */+ assert(!(outputDirective == fillOutput && op + 1 + LASTLITERALS > olimit));++ anchor = ip;++ /* Test end of chunk */+ if (ip >= mflimitPlusOne) break;++ /* Fill table */+ LZ4_putPosition(ip-2, cctx->hashTable, tableType, base);++ /* Test next position */+ if (tableType == byPtr) {++ match = LZ4_getPosition(ip, cctx->hashTable, tableType, base);+ LZ4_putPosition(ip, cctx->hashTable, tableType, base);+ if ( (match+LZ4_DISTANCE_MAX >= ip)+ && (LZ4_read32(match) == LZ4_read32(ip)) )+ { token=op++; *token=0; goto _next_match; }++ } else { /* byU32, byU16 */++ U32 const h = LZ4_hashPosition(ip, tableType);+ U32 const current = (U32)(ip-base);+ U32 matchIndex = LZ4_getIndexOnHash(h, cctx->hashTable, tableType);+ assert(matchIndex < current);+ if (dictDirective == usingDictCtx) {+ if (matchIndex < startIndex) {+ /* there was no match, try the dictionary */+ matchIndex = LZ4_getIndexOnHash(h, dictCtx->hashTable, byU32);+ match = dictBase + matchIndex;+ lowLimit = dictionary; /* required for match length counter */+ matchIndex += dictDelta;+ } else {+ match = base + matchIndex;+ lowLimit = (const BYTE*)source; /* required for match length counter */+ }+ } else if (dictDirective==usingExtDict) {+ if (matchIndex < startIndex) {+ assert(dictBase);+ match = dictBase + matchIndex;+ lowLimit = dictionary; /* required for match length counter */+ } else {+ match = base + matchIndex;+ lowLimit = (const BYTE*)source; /* required for match length counter */+ }+ } else { /* single memory segment */+ match = base + matchIndex;+ }+ LZ4_putIndexOnHash(current, h, cctx->hashTable, tableType);+ assert(matchIndex < current);+ if ( ((dictIssue==dictSmall) ? (matchIndex >= prefixIdxLimit) : 1)+ && (((tableType==byU16) && (LZ4_DISTANCE_MAX == LZ4_DISTANCE_ABSOLUTE_MAX)) ? 1 : (matchIndex+LZ4_DISTANCE_MAX >= current))+ && (LZ4_read32(match) == LZ4_read32(ip)) ) {+ token=op++;+ *token=0;+ if (maybe_extMem) offset = current - matchIndex;+ DEBUGLOG(6, "seq.start:%i, literals=%u, match.start:%i",+ (int)(anchor-(const BYTE*)source), 0, (int)(ip-(const BYTE*)source));+ goto _next_match;+ }+ }++ /* Prepare next loop */+ forwardH = LZ4_hashPosition(++ip, tableType);++ }++_last_literals:+ /* Encode Last Literals */+ { size_t lastRun = (size_t)(iend - anchor);+ if ( (outputDirective) && /* Check output buffer overflow */+ (op + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > olimit)) {+ if (outputDirective == fillOutput) {+ /* adapt lastRun to fill 'dst' */+ assert(olimit >= op);+ lastRun = (size_t)(olimit-op) - 1/*token*/;+ lastRun -= (lastRun + 256 - RUN_MASK) / 256; /*additional length tokens*/+ } else {+ assert(outputDirective == limitedOutput);+ return 0; /* cannot compress within `dst` budget. Stored indexes in hash table are nonetheless fine */+ }+ }+ DEBUGLOG(6, "Final literal run : %i literals", (int)lastRun);+ if (lastRun >= RUN_MASK) {+ size_t accumulator = lastRun - RUN_MASK;+ *op++ = RUN_MASK << ML_BITS;+ for(; accumulator >= 255 ; accumulator-=255) *op++ = 255;+ *op++ = (BYTE) accumulator;+ } else {+ *op++ = (BYTE)(lastRun<<ML_BITS);+ }+ LZ4_memcpy(op, anchor, lastRun);+ ip = anchor + lastRun;+ op += lastRun;+ }++ if (outputDirective == fillOutput) {+ *inputConsumed = (int) (((const char*)ip)-source);+ }+ result = (int)(((char*)op) - dest);+ assert(result > 0);+ DEBUGLOG(5, "LZ4_compress_generic: compressed %i bytes into %i bytes", inputSize, result);+ return result;+}++/** LZ4_compress_generic() :+ * inlined, to ensure branches are decided at compilation time;+ * takes care of src == (NULL, 0)+ * and forward the rest to LZ4_compress_generic_validated */+LZ4_FORCE_INLINE int LZ4_compress_generic(+ LZ4_stream_t_internal* const cctx,+ const char* const src,+ char* const dst,+ const int srcSize,+ int *inputConsumed, /* only written when outputDirective == fillOutput */+ const int dstCapacity,+ const limitedOutput_directive outputDirective,+ const tableType_t tableType,+ const dict_directive dictDirective,+ const dictIssue_directive dictIssue,+ const int acceleration)+{+ DEBUGLOG(5, "LZ4_compress_generic: srcSize=%i, dstCapacity=%i",+ srcSize, dstCapacity);++ if ((U32)srcSize > (U32)LZ4_MAX_INPUT_SIZE) { return 0; } /* Unsupported srcSize, too large (or negative) */+ if (srcSize == 0) { /* src == NULL supported if srcSize == 0 */+ if (outputDirective != notLimited && dstCapacity <= 0) return 0; /* no output, can't write anything */+ DEBUGLOG(5, "Generating an empty block");+ assert(outputDirective == notLimited || dstCapacity >= 1);+ assert(dst != NULL);+ dst[0] = 0;+ if (outputDirective == fillOutput) {+ assert (inputConsumed != NULL);+ *inputConsumed = 0;+ }+ return 1;+ }+ assert(src != NULL);++ return LZ4_compress_generic_validated(cctx, src, dst, srcSize,+ inputConsumed, /* only written into if outputDirective == fillOutput */+ dstCapacity, outputDirective,+ tableType, dictDirective, dictIssue, acceleration);+}+++int LZ4_compress_fast_extState(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)+{+ LZ4_stream_t_internal* const ctx = & LZ4_initStream(state, sizeof(LZ4_stream_t)) -> internal_donotuse;+ assert(ctx != NULL);+ if (acceleration < 1) acceleration = LZ4_ACCELERATION_DEFAULT;+ if (acceleration > LZ4_ACCELERATION_MAX) acceleration = LZ4_ACCELERATION_MAX;+ if (maxOutputSize >= LZ4_compressBound(inputSize)) {+ if (inputSize < LZ4_64Klimit) {+ return LZ4_compress_generic(ctx, source, dest, inputSize, NULL, 0, notLimited, byU16, noDict, noDictIssue, acceleration);+ } else {+ const tableType_t tableType = ((sizeof(void*)==4) && ((uptrval)source > LZ4_DISTANCE_MAX)) ? byPtr : byU32;+ return LZ4_compress_generic(ctx, source, dest, inputSize, NULL, 0, notLimited, tableType, noDict, noDictIssue, acceleration);+ }+ } else {+ if (inputSize < LZ4_64Klimit) {+ return LZ4_compress_generic(ctx, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration);+ } else {+ const tableType_t tableType = ((sizeof(void*)==4) && ((uptrval)source > LZ4_DISTANCE_MAX)) ? byPtr : byU32;+ return LZ4_compress_generic(ctx, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, noDict, noDictIssue, acceleration);+ }+ }+}++/**+ * LZ4_compress_fast_extState_fastReset() :+ * A variant of LZ4_compress_fast_extState().+ *+ * Using this variant avoids an expensive initialization step. It is only safe+ * to call if the state buffer is known to be correctly initialized already+ * (see comment in lz4.h on LZ4_resetStream_fast() for a definition of+ * "correctly initialized").+ */+int LZ4_compress_fast_extState_fastReset(void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration)+{+ LZ4_stream_t_internal* ctx = &((LZ4_stream_t*)state)->internal_donotuse;+ if (acceleration < 1) acceleration = LZ4_ACCELERATION_DEFAULT;+ if (acceleration > LZ4_ACCELERATION_MAX) acceleration = LZ4_ACCELERATION_MAX;++ if (dstCapacity >= LZ4_compressBound(srcSize)) {+ if (srcSize < LZ4_64Klimit) {+ const tableType_t tableType = byU16;+ LZ4_prepareTable(ctx, srcSize, tableType);+ if (ctx->currentOffset) {+ return LZ4_compress_generic(ctx, src, dst, srcSize, NULL, 0, notLimited, tableType, noDict, dictSmall, acceleration);+ } else {+ return LZ4_compress_generic(ctx, src, dst, srcSize, NULL, 0, notLimited, tableType, noDict, noDictIssue, acceleration);+ }+ } else {+ const tableType_t tableType = ((sizeof(void*)==4) && ((uptrval)src > LZ4_DISTANCE_MAX)) ? byPtr : byU32;+ LZ4_prepareTable(ctx, srcSize, tableType);+ return LZ4_compress_generic(ctx, src, dst, srcSize, NULL, 0, notLimited, tableType, noDict, noDictIssue, acceleration);+ }+ } else {+ if (srcSize < LZ4_64Klimit) {+ const tableType_t tableType = byU16;+ LZ4_prepareTable(ctx, srcSize, tableType);+ if (ctx->currentOffset) {+ return LZ4_compress_generic(ctx, src, dst, srcSize, NULL, dstCapacity, limitedOutput, tableType, noDict, dictSmall, acceleration);+ } else {+ return LZ4_compress_generic(ctx, src, dst, srcSize, NULL, dstCapacity, limitedOutput, tableType, noDict, noDictIssue, acceleration);+ }+ } else {+ const tableType_t tableType = ((sizeof(void*)==4) && ((uptrval)src > LZ4_DISTANCE_MAX)) ? byPtr : byU32;+ LZ4_prepareTable(ctx, srcSize, tableType);+ return LZ4_compress_generic(ctx, src, dst, srcSize, NULL, dstCapacity, limitedOutput, tableType, noDict, noDictIssue, acceleration);+ }+ }+}+++int LZ4_compress_fast(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)+{+ int result;+#if (LZ4_HEAPMODE)+ LZ4_stream_t* ctxPtr = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */+ if (ctxPtr == NULL) return 0;+#else+ LZ4_stream_t ctx;+ LZ4_stream_t* const ctxPtr = &ctx;+#endif+ result = LZ4_compress_fast_extState(ctxPtr, source, dest, inputSize, maxOutputSize, acceleration);++#if (LZ4_HEAPMODE)+ FREEMEM(ctxPtr);+#endif+ return result;+}+++int LZ4_compress_default(const char* src, char* dst, int srcSize, int maxOutputSize)+{+ return LZ4_compress_fast(src, dst, srcSize, maxOutputSize, 1);+}+++/* Note!: This function leaves the stream in an unclean/broken state!+ * It is not safe to subsequently use the same state with a _fastReset() or+ * _continue() call without resetting it. */+static int LZ4_compress_destSize_extState (LZ4_stream_t* state, const char* src, char* dst, int* srcSizePtr, int targetDstSize)+{+ void* const s = LZ4_initStream(state, sizeof (*state));+ assert(s != NULL); (void)s;++ if (targetDstSize >= LZ4_compressBound(*srcSizePtr)) { /* compression success is guaranteed */+ return LZ4_compress_fast_extState(state, src, dst, *srcSizePtr, targetDstSize, 1);+ } else {+ if (*srcSizePtr < LZ4_64Klimit) {+ return LZ4_compress_generic(&state->internal_donotuse, src, dst, *srcSizePtr, srcSizePtr, targetDstSize, fillOutput, byU16, noDict, noDictIssue, 1);+ } else {+ tableType_t const addrMode = ((sizeof(void*)==4) && ((uptrval)src > LZ4_DISTANCE_MAX)) ? byPtr : byU32;+ return LZ4_compress_generic(&state->internal_donotuse, src, dst, *srcSizePtr, srcSizePtr, targetDstSize, fillOutput, addrMode, noDict, noDictIssue, 1);+ } }+}+++int LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targetDstSize)+{+#if (LZ4_HEAPMODE)+ LZ4_stream_t* ctx = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */+ if (ctx == NULL) return 0;+#else+ LZ4_stream_t ctxBody;+ LZ4_stream_t* ctx = &ctxBody;+#endif++ int result = LZ4_compress_destSize_extState(ctx, src, dst, srcSizePtr, targetDstSize);++#if (LZ4_HEAPMODE)+ FREEMEM(ctx);+#endif+ return result;+}++++/*-******************************+* Streaming functions+********************************/++#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)+LZ4_stream_t* LZ4_createStream(void)+{+ LZ4_stream_t* const lz4s = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t));+ LZ4_STATIC_ASSERT(sizeof(LZ4_stream_t) >= sizeof(LZ4_stream_t_internal));+ DEBUGLOG(4, "LZ4_createStream %p", lz4s);+ if (lz4s == NULL) return NULL;+ LZ4_initStream(lz4s, sizeof(*lz4s));+ return lz4s;+}+#endif++static size_t LZ4_stream_t_alignment(void)+{+#if LZ4_ALIGN_TEST+ typedef struct { char c; LZ4_stream_t t; } t_a;+ return sizeof(t_a) - sizeof(LZ4_stream_t);+#else+ return 1; /* effectively disabled */+#endif+}++LZ4_stream_t* LZ4_initStream (void* buffer, size_t size)+{+ DEBUGLOG(5, "LZ4_initStream");+ if (buffer == NULL) { return NULL; }+ if (size < sizeof(LZ4_stream_t)) { return NULL; }+ if (!LZ4_isAligned(buffer, LZ4_stream_t_alignment())) return NULL;+ MEM_INIT(buffer, 0, sizeof(LZ4_stream_t_internal));+ return (LZ4_stream_t*)buffer;+}++/* resetStream is now deprecated,+ * prefer initStream() which is more general */+void LZ4_resetStream (LZ4_stream_t* LZ4_stream)+{+ DEBUGLOG(5, "LZ4_resetStream (ctx:%p)", LZ4_stream);+ MEM_INIT(LZ4_stream, 0, sizeof(LZ4_stream_t_internal));+}++void LZ4_resetStream_fast(LZ4_stream_t* ctx) {+ LZ4_prepareTable(&(ctx->internal_donotuse), 0, byU32);+}++#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)+int LZ4_freeStream (LZ4_stream_t* LZ4_stream)+{+ if (!LZ4_stream) return 0; /* support free on NULL */+ DEBUGLOG(5, "LZ4_freeStream %p", LZ4_stream);+ FREEMEM(LZ4_stream);+ return (0);+}+#endif+++#define HASH_UNIT sizeof(reg_t)+int LZ4_loadDict (LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize)+{+ LZ4_stream_t_internal* dict = &LZ4_dict->internal_donotuse;+ const tableType_t tableType = byU32;+ const BYTE* p = (const BYTE*)dictionary;+ const BYTE* const dictEnd = p + dictSize;+ const BYTE* base;++ DEBUGLOG(4, "LZ4_loadDict (%i bytes from %p into %p)", dictSize, dictionary, LZ4_dict);++ /* It's necessary to reset the context,+ * and not just continue it with prepareTable()+ * to avoid any risk of generating overflowing matchIndex+ * when compressing using this dictionary */+ LZ4_resetStream(LZ4_dict);++ /* We always increment the offset by 64 KB, since, if the dict is longer,+ * we truncate it to the last 64k, and if it's shorter, we still want to+ * advance by a whole window length so we can provide the guarantee that+ * there are only valid offsets in the window, which allows an optimization+ * in LZ4_compress_fast_continue() where it uses noDictIssue even when the+ * dictionary isn't a full 64k. */+ dict->currentOffset += 64 KB;++ if (dictSize < (int)HASH_UNIT) {+ return 0;+ }++ if ((dictEnd - p) > 64 KB) p = dictEnd - 64 KB;+ base = dictEnd - dict->currentOffset;+ dict->dictionary = p;+ dict->dictSize = (U32)(dictEnd - p);+ dict->tableType = (U32)tableType;++ while (p <= dictEnd-HASH_UNIT) {+ LZ4_putPosition(p, dict->hashTable, tableType, base);+ p+=3;+ }++ return (int)dict->dictSize;+}++void LZ4_attach_dictionary(LZ4_stream_t* workingStream, const LZ4_stream_t* dictionaryStream)+{+ const LZ4_stream_t_internal* dictCtx = (dictionaryStream == NULL) ? NULL :+ &(dictionaryStream->internal_donotuse);++ DEBUGLOG(4, "LZ4_attach_dictionary (%p, %p, size %u)",+ workingStream, dictionaryStream,+ dictCtx != NULL ? dictCtx->dictSize : 0);++ if (dictCtx != NULL) {+ /* If the current offset is zero, we will never look in the+ * external dictionary context, since there is no value a table+ * entry can take that indicate a miss. In that case, we need+ * to bump the offset to something non-zero.+ */+ if (workingStream->internal_donotuse.currentOffset == 0) {+ workingStream->internal_donotuse.currentOffset = 64 KB;+ }++ /* Don't actually attach an empty dictionary.+ */+ if (dictCtx->dictSize == 0) {+ dictCtx = NULL;+ }+ }+ workingStream->internal_donotuse.dictCtx = dictCtx;+}+++static void LZ4_renormDictT(LZ4_stream_t_internal* LZ4_dict, int nextSize)+{+ assert(nextSize >= 0);+ if (LZ4_dict->currentOffset + (unsigned)nextSize > 0x80000000) { /* potential ptrdiff_t overflow (32-bits mode) */+ /* rescale hash table */+ U32 const delta = LZ4_dict->currentOffset - 64 KB;+ const BYTE* dictEnd = LZ4_dict->dictionary + LZ4_dict->dictSize;+ int i;+ DEBUGLOG(4, "LZ4_renormDictT");+ for (i=0; i<LZ4_HASH_SIZE_U32; i++) {+ if (LZ4_dict->hashTable[i] < delta) LZ4_dict->hashTable[i]=0;+ else LZ4_dict->hashTable[i] -= delta;+ }+ LZ4_dict->currentOffset = 64 KB;+ if (LZ4_dict->dictSize > 64 KB) LZ4_dict->dictSize = 64 KB;+ LZ4_dict->dictionary = dictEnd - LZ4_dict->dictSize;+ }+}+++int LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream,+ const char* source, char* dest,+ int inputSize, int maxOutputSize,+ int acceleration)+{+ const tableType_t tableType = byU32;+ LZ4_stream_t_internal* const streamPtr = &LZ4_stream->internal_donotuse;+ const char* dictEnd = streamPtr->dictSize ? (const char*)streamPtr->dictionary + streamPtr->dictSize : NULL;++ DEBUGLOG(5, "LZ4_compress_fast_continue (inputSize=%i, dictSize=%u)", inputSize, streamPtr->dictSize);++ LZ4_renormDictT(streamPtr, inputSize); /* fix index overflow */+ if (acceleration < 1) acceleration = LZ4_ACCELERATION_DEFAULT;+ if (acceleration > LZ4_ACCELERATION_MAX) acceleration = LZ4_ACCELERATION_MAX;++ /* invalidate tiny dictionaries */+ if ( (streamPtr->dictSize < 4) /* tiny dictionary : not enough for a hash */+ && (dictEnd != source) /* prefix mode */+ && (inputSize > 0) /* tolerance : don't lose history, in case next invocation would use prefix mode */+ && (streamPtr->dictCtx == NULL) /* usingDictCtx */+ ) {+ DEBUGLOG(5, "LZ4_compress_fast_continue: dictSize(%u) at addr:%p is too small", streamPtr->dictSize, streamPtr->dictionary);+ /* remove dictionary existence from history, to employ faster prefix mode */+ streamPtr->dictSize = 0;+ streamPtr->dictionary = (const BYTE*)source;+ dictEnd = source;+ }++ /* Check overlapping input/dictionary space */+ { const char* const sourceEnd = source + inputSize;+ if ((sourceEnd > (const char*)streamPtr->dictionary) && (sourceEnd < dictEnd)) {+ streamPtr->dictSize = (U32)(dictEnd - sourceEnd);+ if (streamPtr->dictSize > 64 KB) streamPtr->dictSize = 64 KB;+ if (streamPtr->dictSize < 4) streamPtr->dictSize = 0;+ streamPtr->dictionary = (const BYTE*)dictEnd - streamPtr->dictSize;+ }+ }++ /* prefix mode : source data follows dictionary */+ if (dictEnd == source) {+ if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset))+ return LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, withPrefix64k, dictSmall, acceleration);+ else+ return LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, withPrefix64k, noDictIssue, acceleration);+ }++ /* external dictionary mode */+ { int result;+ if (streamPtr->dictCtx) {+ /* We depend here on the fact that dictCtx'es (produced by+ * LZ4_loadDict) guarantee that their tables contain no references+ * to offsets between dictCtx->currentOffset - 64 KB and+ * dictCtx->currentOffset - dictCtx->dictSize. This makes it safe+ * to use noDictIssue even when the dict isn't a full 64 KB.+ */+ if (inputSize > 4 KB) {+ /* For compressing large blobs, it is faster to pay the setup+ * cost to copy the dictionary's tables into the active context,+ * so that the compression loop is only looking into one table.+ */+ LZ4_memcpy(streamPtr, streamPtr->dictCtx, sizeof(*streamPtr));+ result = LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, usingExtDict, noDictIssue, acceleration);+ } else {+ result = LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, usingDictCtx, noDictIssue, acceleration);+ }+ } else { /* small data <= 4 KB */+ if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset)) {+ result = LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, usingExtDict, dictSmall, acceleration);+ } else {+ result = LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, usingExtDict, noDictIssue, acceleration);+ }+ }+ streamPtr->dictionary = (const BYTE*)source;+ streamPtr->dictSize = (U32)inputSize;+ return result;+ }+}+++/* Hidden debug function, to force-test external dictionary mode */+int LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_dict, const char* source, char* dest, int srcSize)+{+ LZ4_stream_t_internal* streamPtr = &LZ4_dict->internal_donotuse;+ int result;++ LZ4_renormDictT(streamPtr, srcSize);++ if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset)) {+ result = LZ4_compress_generic(streamPtr, source, dest, srcSize, NULL, 0, notLimited, byU32, usingExtDict, dictSmall, 1);+ } else {+ result = LZ4_compress_generic(streamPtr, source, dest, srcSize, NULL, 0, notLimited, byU32, usingExtDict, noDictIssue, 1);+ }++ streamPtr->dictionary = (const BYTE*)source;+ streamPtr->dictSize = (U32)srcSize;++ return result;+}+++/*! LZ4_saveDict() :+ * If previously compressed data block is not guaranteed to remain available at its memory location,+ * save it into a safer place (char* safeBuffer).+ * Note : no need to call LZ4_loadDict() afterwards, dictionary is immediately usable,+ * one can therefore call LZ4_compress_fast_continue() right after.+ * @return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error.+ */+int LZ4_saveDict (LZ4_stream_t* LZ4_dict, char* safeBuffer, int dictSize)+{+ LZ4_stream_t_internal* const dict = &LZ4_dict->internal_donotuse;++ DEBUGLOG(5, "LZ4_saveDict : dictSize=%i, safeBuffer=%p", dictSize, safeBuffer);++ if ((U32)dictSize > 64 KB) { dictSize = 64 KB; } /* useless to define a dictionary > 64 KB */+ if ((U32)dictSize > dict->dictSize) { dictSize = (int)dict->dictSize; }++ if (safeBuffer == NULL) assert(dictSize == 0);+ if (dictSize > 0) {+ const BYTE* const previousDictEnd = dict->dictionary + dict->dictSize;+ assert(dict->dictionary);+ LZ4_memmove(safeBuffer, previousDictEnd - dictSize, (size_t)dictSize);+ }++ dict->dictionary = (const BYTE*)safeBuffer;+ dict->dictSize = (U32)dictSize;++ return dictSize;+}++++/*-*******************************+ * Decompression functions+ ********************************/++typedef enum { decode_full_block = 0, partial_decode = 1 } earlyEnd_directive;++#undef MIN+#define MIN(a,b) ( (a) < (b) ? (a) : (b) )+++/* variant for decompress_unsafe()+ * does not know end of input+ * presumes input is well formed+ * note : will consume at least one byte */+size_t read_long_length_no_check(const BYTE** pp)+{+ size_t b, l = 0;+ do { b = **pp; (*pp)++; l += b; } while (b==255);+ DEBUGLOG(6, "read_long_length_no_check: +length=%zu using %zu input bytes", l, l/255 + 1)+ return l;+}++/* core decoder variant for LZ4_decompress_fast*()+ * for legacy support only : these entry points are deprecated.+ * - Presumes input is correctly formed (no defense vs malformed inputs)+ * - Does not know input size (presume input buffer is "large enough")+ * - Decompress a full block (only)+ * @return : nb of bytes read from input.+ * Note : this variant is not optimized for speed, just for maintenance.+ * the goal is to remove support of decompress_fast*() variants by v2.0+**/+LZ4_FORCE_INLINE int+LZ4_decompress_unsafe_generic(+ const BYTE* const istart,+ BYTE* const ostart,+ int decompressedSize,++ size_t prefixSize,+ const BYTE* const dictStart, /* only if dict==usingExtDict */+ const size_t dictSize /* note: =0 if dictStart==NULL */+ )+{+ const BYTE* ip = istart;+ BYTE* op = (BYTE*)ostart;+ BYTE* const oend = ostart + decompressedSize;+ const BYTE* const prefixStart = ostart - prefixSize;++ DEBUGLOG(5, "LZ4_decompress_unsafe_generic");+ if (dictStart == NULL) assert(dictSize == 0);++ while (1) {+ /* start new sequence */+ unsigned token = *ip++;++ /* literals */+ { size_t ll = token >> ML_BITS;+ if (ll==15) {+ /* long literal length */+ ll += read_long_length_no_check(&ip);+ }+ if ((size_t)(oend-op) < ll) return -1; /* output buffer overflow */+ LZ4_memmove(op, ip, ll); /* support in-place decompression */+ op += ll;+ ip += ll;+ if ((size_t)(oend-op) < MFLIMIT) {+ if (op==oend) break; /* end of block */+ DEBUGLOG(5, "invalid: literals end at distance %zi from end of block", oend-op);+ /* incorrect end of block :+ * last match must start at least MFLIMIT==12 bytes before end of output block */+ return -1;+ } }++ /* match */+ { size_t ml = token & 15;+ size_t const offset = LZ4_readLE16(ip);+ ip+=2;++ if (ml==15) {+ /* long literal length */+ ml += read_long_length_no_check(&ip);+ }+ ml += MINMATCH;++ if ((size_t)(oend-op) < ml) return -1; /* output buffer overflow */++ { const BYTE* match = op - offset;++ /* out of range */+ if (offset > (size_t)(op - prefixStart) + dictSize) {+ DEBUGLOG(6, "offset out of range");+ return -1;+ }++ /* check special case : extDict */+ if (offset > (size_t)(op - prefixStart)) {+ /* extDict scenario */+ const BYTE* const dictEnd = dictStart + dictSize;+ const BYTE* extMatch = dictEnd - (offset - (size_t)(op-prefixStart));+ size_t const extml = (size_t)(dictEnd - extMatch);+ if (extml > ml) {+ /* match entirely within extDict */+ LZ4_memmove(op, extMatch, ml);+ op += ml;+ ml = 0;+ } else {+ /* match split between extDict & prefix */+ LZ4_memmove(op, extMatch, extml);+ op += extml;+ ml -= extml;+ }+ match = prefixStart;+ }++ /* match copy - slow variant, supporting overlap copy */+ { size_t u;+ for (u=0; u<ml; u++) {+ op[u] = match[u];+ } } }+ op += ml;+ if ((size_t)(oend-op) < LASTLITERALS) {+ DEBUGLOG(5, "invalid: match ends at distance %zi from end of block", oend-op);+ /* incorrect end of block :+ * last match must stop at least LASTLITERALS==5 bytes before end of output block */+ return -1;+ }+ } /* match */+ } /* main loop */+ return (int)(ip - istart);+}+++/* Read the variable-length literal or match length.+ *+ * @ip : input pointer+ * @ilimit : position after which if length is not decoded, the input is necessarily corrupted.+ * @initial_check - check ip >= ipmax before start of loop. Returns initial_error if so.+ * @error (output) - error code. Must be set to 0 before call.+**/+typedef size_t Rvl_t;+static const Rvl_t rvl_error = (Rvl_t)(-1);+LZ4_FORCE_INLINE Rvl_t+read_variable_length(const BYTE** ip, const BYTE* ilimit,+ int initial_check)+{+ Rvl_t s, length = 0;+ assert(ip != NULL);+ assert(*ip != NULL);+ assert(ilimit != NULL);+ if (initial_check && unlikely((*ip) >= ilimit)) { /* read limit reached */+ return rvl_error;+ }+ do {+ s = **ip;+ (*ip)++;+ length += s;+ if (unlikely((*ip) > ilimit)) { /* read limit reached */+ return rvl_error;+ }+ /* accumulator overflow detection (32-bit mode only) */+ if ((sizeof(length)<8) && unlikely(length > ((Rvl_t)(-1)/2)) ) {+ return rvl_error;+ }+ } while (s==255);++ return length;+}++/*! LZ4_decompress_generic() :+ * This generic decompression function covers all use cases.+ * It shall be instantiated several times, using different sets of directives.+ * Note that it is important for performance that this function really get inlined,+ * in order to remove useless branches during compilation optimization.+ */+LZ4_FORCE_INLINE int+LZ4_decompress_generic(+ const char* const src,+ char* const dst,+ int srcSize,+ int outputSize, /* If endOnInput==endOnInputSize, this value is `dstCapacity` */++ earlyEnd_directive partialDecoding, /* full, partial */+ dict_directive dict, /* noDict, withPrefix64k, usingExtDict */+ const BYTE* const lowPrefix, /* always <= dst, == dst when no prefix */+ const BYTE* const dictStart, /* only if dict==usingExtDict */+ const size_t dictSize /* note : = 0 if noDict */+ )+{+ if ((src == NULL) || (outputSize < 0)) { return -1; }++ { const BYTE* ip = (const BYTE*) src;+ const BYTE* const iend = ip + srcSize;++ BYTE* op = (BYTE*) dst;+ BYTE* const oend = op + outputSize;+ BYTE* cpy;++ const BYTE* const dictEnd = (dictStart == NULL) ? NULL : dictStart + dictSize;++ const int checkOffset = (dictSize < (int)(64 KB));+++ /* Set up the "end" pointers for the shortcut. */+ const BYTE* const shortiend = iend - 14 /*maxLL*/ - 2 /*offset*/;+ const BYTE* const shortoend = oend - 14 /*maxLL*/ - 18 /*maxML*/;++ const BYTE* match;+ size_t offset;+ unsigned token;+ size_t length;+++ DEBUGLOG(5, "LZ4_decompress_generic (srcSize:%i, dstSize:%i)", srcSize, outputSize);++ /* Special cases */+ assert(lowPrefix <= op);+ if (unlikely(outputSize==0)) {+ /* Empty output buffer */+ if (partialDecoding) return 0;+ return ((srcSize==1) && (*ip==0)) ? 0 : -1;+ }+ if (unlikely(srcSize==0)) { return -1; }++ /* LZ4_FAST_DEC_LOOP:+ * designed for modern OoO performance cpus,+ * where copying reliably 32-bytes is preferable to an unpredictable branch.+ * note : fast loop may show a regression for some client arm chips. */+#if LZ4_FAST_DEC_LOOP+ if ((oend - op) < FASTLOOP_SAFE_DISTANCE) {+ DEBUGLOG(6, "skip fast decode loop");+ goto safe_decode;+ }++ /* Fast loop : decode sequences as long as output < oend-FASTLOOP_SAFE_DISTANCE */+ while (1) {+ /* Main fastloop assertion: We can always wildcopy FASTLOOP_SAFE_DISTANCE */+ assert(oend - op >= FASTLOOP_SAFE_DISTANCE);+ assert(ip < iend);+ token = *ip++;+ length = token >> ML_BITS; /* literal length */++ /* decode literal length */+ if (length == RUN_MASK) {+ size_t const addl = read_variable_length(&ip, iend-RUN_MASK, 1);+ if (addl == rvl_error) { goto _output_error; }+ length += addl;+ if (unlikely((uptrval)(op)+length<(uptrval)(op))) { goto _output_error; } /* overflow detection */+ if (unlikely((uptrval)(ip)+length<(uptrval)(ip))) { goto _output_error; } /* overflow detection */++ /* copy literals */+ cpy = op+length;+ LZ4_STATIC_ASSERT(MFLIMIT >= WILDCOPYLENGTH);+ if ((cpy>oend-32) || (ip+length>iend-32)) { goto safe_literal_copy; }+ LZ4_wildCopy32(op, ip, cpy);+ ip += length; op = cpy;+ } else {+ cpy = op+length;+ DEBUGLOG(7, "copy %u bytes in a 16-bytes stripe", (unsigned)length);+ /* We don't need to check oend, since we check it once for each loop below */+ if (ip > iend-(16 + 1/*max lit + offset + nextToken*/)) { goto safe_literal_copy; }+ /* Literals can only be <= 14, but hope compilers optimize better when copy by a register size */+ LZ4_memcpy(op, ip, 16);+ ip += length; op = cpy;+ }++ /* get offset */+ offset = LZ4_readLE16(ip); ip+=2;+ match = op - offset;+ assert(match <= op); /* overflow check */++ /* get matchlength */+ length = token & ML_MASK;++ if (length == ML_MASK) {+ size_t const addl = read_variable_length(&ip, iend - LASTLITERALS + 1, 0);+ if (addl == rvl_error) { goto _output_error; }+ length += addl;+ length += MINMATCH;+ if (unlikely((uptrval)(op)+length<(uptrval)op)) { goto _output_error; } /* overflow detection */+ if ((checkOffset) && (unlikely(match + dictSize < lowPrefix))) { goto _output_error; } /* Error : offset outside buffers */+ if (op + length >= oend - FASTLOOP_SAFE_DISTANCE) {+ goto safe_match_copy;+ }+ } else {+ length += MINMATCH;+ if (op + length >= oend - FASTLOOP_SAFE_DISTANCE) {+ goto safe_match_copy;+ }++ /* Fastpath check: skip LZ4_wildCopy32 when true */+ if ((dict == withPrefix64k) || (match >= lowPrefix)) {+ if (offset >= 8) {+ assert(match >= lowPrefix);+ assert(match <= op);+ assert(op + 18 <= oend);++ LZ4_memcpy(op, match, 8);+ LZ4_memcpy(op+8, match+8, 8);+ LZ4_memcpy(op+16, match+16, 2);+ op += length;+ continue;+ } } }++ if (checkOffset && (unlikely(match + dictSize < lowPrefix))) { goto _output_error; } /* Error : offset outside buffers */+ /* match starting within external dictionary */+ if ((dict==usingExtDict) && (match < lowPrefix)) {+ assert(dictEnd != NULL);+ if (unlikely(op+length > oend-LASTLITERALS)) {+ if (partialDecoding) {+ DEBUGLOG(7, "partialDecoding: dictionary match, close to dstEnd");+ length = MIN(length, (size_t)(oend-op));+ } else {+ goto _output_error; /* end-of-block condition violated */+ } }++ if (length <= (size_t)(lowPrefix-match)) {+ /* match fits entirely within external dictionary : just copy */+ LZ4_memmove(op, dictEnd - (lowPrefix-match), length);+ op += length;+ } else {+ /* match stretches into both external dictionary and current block */+ size_t const copySize = (size_t)(lowPrefix - match);+ size_t const restSize = length - copySize;+ LZ4_memcpy(op, dictEnd - copySize, copySize);+ op += copySize;+ if (restSize > (size_t)(op - lowPrefix)) { /* overlap copy */+ BYTE* const endOfMatch = op + restSize;+ const BYTE* copyFrom = lowPrefix;+ while (op < endOfMatch) { *op++ = *copyFrom++; }+ } else {+ LZ4_memcpy(op, lowPrefix, restSize);+ op += restSize;+ } }+ continue;+ }++ /* copy match within block */+ cpy = op + length;++ assert((op <= oend) && (oend-op >= 32));+ if (unlikely(offset<16)) {+ LZ4_memcpy_using_offset(op, match, cpy, offset);+ } else {+ LZ4_wildCopy32(op, match, cpy);+ }++ op = cpy; /* wildcopy correction */+ }+ safe_decode:+#endif++ /* Main Loop : decode remaining sequences where output < FASTLOOP_SAFE_DISTANCE */+ while (1) {+ assert(ip < iend);+ token = *ip++;+ length = token >> ML_BITS; /* literal length */++ /* A two-stage shortcut for the most common case:+ * 1) If the literal length is 0..14, and there is enough space,+ * enter the shortcut and copy 16 bytes on behalf of the literals+ * (in the fast mode, only 8 bytes can be safely copied this way).+ * 2) Further if the match length is 4..18, copy 18 bytes in a similar+ * manner; but we ensure that there's enough space in the output for+ * those 18 bytes earlier, upon entering the shortcut (in other words,+ * there is a combined check for both stages).+ */+ if ( (length != RUN_MASK)+ /* strictly "less than" on input, to re-enter the loop with at least one byte */+ && likely((ip < shortiend) & (op <= shortoend)) ) {+ /* Copy the literals */+ LZ4_memcpy(op, ip, 16);+ op += length; ip += length;++ /* The second stage: prepare for match copying, decode full info.+ * If it doesn't work out, the info won't be wasted. */+ length = token & ML_MASK; /* match length */+ offset = LZ4_readLE16(ip); ip += 2;+ match = op - offset;+ assert(match <= op); /* check overflow */++ /* Do not deal with overlapping matches. */+ if ( (length != ML_MASK)+ && (offset >= 8)+ && (dict==withPrefix64k || match >= lowPrefix) ) {+ /* Copy the match. */+ LZ4_memcpy(op + 0, match + 0, 8);+ LZ4_memcpy(op + 8, match + 8, 8);+ LZ4_memcpy(op +16, match +16, 2);+ op += length + MINMATCH;+ /* Both stages worked, load the next token. */+ continue;+ }++ /* The second stage didn't work out, but the info is ready.+ * Propel it right to the point of match copying. */+ goto _copy_match;+ }++ /* decode literal length */+ if (length == RUN_MASK) {+ size_t const addl = read_variable_length(&ip, iend-RUN_MASK, 1);+ if (addl == rvl_error) { goto _output_error; }+ length += addl;+ if (unlikely((uptrval)(op)+length<(uptrval)(op))) { goto _output_error; } /* overflow detection */+ if (unlikely((uptrval)(ip)+length<(uptrval)(ip))) { goto _output_error; } /* overflow detection */+ }++ /* copy literals */+ cpy = op+length;+#if LZ4_FAST_DEC_LOOP+ safe_literal_copy:+#endif+ LZ4_STATIC_ASSERT(MFLIMIT >= WILDCOPYLENGTH);+ if ((cpy>oend-MFLIMIT) || (ip+length>iend-(2+1+LASTLITERALS))) {+ /* We've either hit the input parsing restriction or the output parsing restriction.+ * In the normal scenario, decoding a full block, it must be the last sequence,+ * otherwise it's an error (invalid input or dimensions).+ * In partialDecoding scenario, it's necessary to ensure there is no buffer overflow.+ */+ if (partialDecoding) {+ /* Since we are partial decoding we may be in this block because of the output parsing+ * restriction, which is not valid since the output buffer is allowed to be undersized.+ */+ DEBUGLOG(7, "partialDecoding: copying literals, close to input or output end")+ DEBUGLOG(7, "partialDecoding: literal length = %u", (unsigned)length);+ DEBUGLOG(7, "partialDecoding: remaining space in dstBuffer : %i", (int)(oend - op));+ DEBUGLOG(7, "partialDecoding: remaining space in srcBuffer : %i", (int)(iend - ip));+ /* Finishing in the middle of a literals segment,+ * due to lack of input.+ */+ if (ip+length > iend) {+ length = (size_t)(iend-ip);+ cpy = op + length;+ }+ /* Finishing in the middle of a literals segment,+ * due to lack of output space.+ */+ if (cpy > oend) {+ cpy = oend;+ assert(op<=oend);+ length = (size_t)(oend-op);+ }+ } else {+ /* We must be on the last sequence (or invalid) because of the parsing limitations+ * so check that we exactly consume the input and don't overrun the output buffer.+ */+ if ((ip+length != iend) || (cpy > oend)) {+ DEBUGLOG(6, "should have been last run of literals")+ DEBUGLOG(6, "ip(%p) + length(%i) = %p != iend (%p)", ip, (int)length, ip+length, iend);+ DEBUGLOG(6, "or cpy(%p) > oend(%p)", cpy, oend);+ goto _output_error;+ }+ }+ LZ4_memmove(op, ip, length); /* supports overlapping memory regions, for in-place decompression scenarios */+ ip += length;+ op += length;+ /* Necessarily EOF when !partialDecoding.+ * When partialDecoding, it is EOF if we've either+ * filled the output buffer or+ * can't proceed with reading an offset for following match.+ */+ if (!partialDecoding || (cpy == oend) || (ip >= (iend-2))) {+ break;+ }+ } else {+ LZ4_wildCopy8(op, ip, cpy); /* can overwrite up to 8 bytes beyond cpy */+ ip += length; op = cpy;+ }++ /* get offset */+ offset = LZ4_readLE16(ip); ip+=2;+ match = op - offset;++ /* get matchlength */+ length = token & ML_MASK;++ _copy_match:+ if (length == ML_MASK) {+ size_t const addl = read_variable_length(&ip, iend - LASTLITERALS + 1, 0);+ if (addl == rvl_error) { goto _output_error; }+ length += addl;+ if (unlikely((uptrval)(op)+length<(uptrval)op)) goto _output_error; /* overflow detection */+ }+ length += MINMATCH;++#if LZ4_FAST_DEC_LOOP+ safe_match_copy:+#endif+ if ((checkOffset) && (unlikely(match + dictSize < lowPrefix))) goto _output_error; /* Error : offset outside buffers */+ /* match starting within external dictionary */+ if ((dict==usingExtDict) && (match < lowPrefix)) {+ assert(dictEnd != NULL);+ if (unlikely(op+length > oend-LASTLITERALS)) {+ if (partialDecoding) length = MIN(length, (size_t)(oend-op));+ else goto _output_error; /* doesn't respect parsing restriction */+ }++ if (length <= (size_t)(lowPrefix-match)) {+ /* match fits entirely within external dictionary : just copy */+ LZ4_memmove(op, dictEnd - (lowPrefix-match), length);+ op += length;+ } else {+ /* match stretches into both external dictionary and current block */+ size_t const copySize = (size_t)(lowPrefix - match);+ size_t const restSize = length - copySize;+ LZ4_memcpy(op, dictEnd - copySize, copySize);+ op += copySize;+ if (restSize > (size_t)(op - lowPrefix)) { /* overlap copy */+ BYTE* const endOfMatch = op + restSize;+ const BYTE* copyFrom = lowPrefix;+ while (op < endOfMatch) *op++ = *copyFrom++;+ } else {+ LZ4_memcpy(op, lowPrefix, restSize);+ op += restSize;+ } }+ continue;+ }+ assert(match >= lowPrefix);++ /* copy match within block */+ cpy = op + length;++ /* partialDecoding : may end anywhere within the block */+ assert(op<=oend);+ if (partialDecoding && (cpy > oend-MATCH_SAFEGUARD_DISTANCE)) {+ size_t const mlen = MIN(length, (size_t)(oend-op));+ const BYTE* const matchEnd = match + mlen;+ BYTE* const copyEnd = op + mlen;+ if (matchEnd > op) { /* overlap copy */+ while (op < copyEnd) { *op++ = *match++; }+ } else {+ LZ4_memcpy(op, match, mlen);+ }+ op = copyEnd;+ if (op == oend) { break; }+ continue;+ }++ if (unlikely(offset<8)) {+ LZ4_write32(op, 0); /* silence msan warning when offset==0 */+ op[0] = match[0];+ op[1] = match[1];+ op[2] = match[2];+ op[3] = match[3];+ match += inc32table[offset];+ LZ4_memcpy(op+4, match, 4);+ match -= dec64table[offset];+ } else {+ LZ4_memcpy(op, match, 8);+ match += 8;+ }+ op += 8;++ if (unlikely(cpy > oend-MATCH_SAFEGUARD_DISTANCE)) {+ BYTE* const oCopyLimit = oend - (WILDCOPYLENGTH-1);+ if (cpy > oend-LASTLITERALS) { goto _output_error; } /* Error : last LASTLITERALS bytes must be literals (uncompressed) */+ if (op < oCopyLimit) {+ LZ4_wildCopy8(op, match, oCopyLimit);+ match += oCopyLimit - op;+ op = oCopyLimit;+ }+ while (op < cpy) { *op++ = *match++; }+ } else {+ LZ4_memcpy(op, match, 8);+ if (length > 16) { LZ4_wildCopy8(op+8, match+8, cpy); }+ }+ op = cpy; /* wildcopy correction */+ }++ /* end of decoding */+ DEBUGLOG(5, "decoded %i bytes", (int) (((char*)op)-dst));+ return (int) (((char*)op)-dst); /* Nb of output bytes decoded */++ /* Overflow error detected */+ _output_error:+ return (int) (-(((const char*)ip)-src))-1;+ }+}+++/*===== Instantiate the API decoding functions. =====*/++LZ4_FORCE_O2+int LZ4_decompress_safe(const char* source, char* dest, int compressedSize, int maxDecompressedSize)+{+ return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize,+ decode_full_block, noDict,+ (BYTE*)dest, NULL, 0);+}++LZ4_FORCE_O2+int LZ4_decompress_safe_partial(const char* src, char* dst, int compressedSize, int targetOutputSize, int dstCapacity)+{+ dstCapacity = MIN(targetOutputSize, dstCapacity);+ return LZ4_decompress_generic(src, dst, compressedSize, dstCapacity,+ partial_decode,+ noDict, (BYTE*)dst, NULL, 0);+}++LZ4_FORCE_O2+int LZ4_decompress_fast(const char* source, char* dest, int originalSize)+{+ DEBUGLOG(5, "LZ4_decompress_fast");+ return LZ4_decompress_unsafe_generic(+ (const BYTE*)source, (BYTE*)dest, originalSize,+ 0, NULL, 0);+}++/*===== Instantiate a few more decoding cases, used more than once. =====*/++LZ4_FORCE_O2 /* Exported, an obsolete API function. */+int LZ4_decompress_safe_withPrefix64k(const char* source, char* dest, int compressedSize, int maxOutputSize)+{+ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize,+ decode_full_block, withPrefix64k,+ (BYTE*)dest - 64 KB, NULL, 0);+}++LZ4_FORCE_O2+static int LZ4_decompress_safe_partial_withPrefix64k(const char* source, char* dest, int compressedSize, int targetOutputSize, int dstCapacity)+{+ dstCapacity = MIN(targetOutputSize, dstCapacity);+ return LZ4_decompress_generic(source, dest, compressedSize, dstCapacity,+ partial_decode, withPrefix64k,+ (BYTE*)dest - 64 KB, NULL, 0);+}++/* Another obsolete API function, paired with the previous one. */+int LZ4_decompress_fast_withPrefix64k(const char* source, char* dest, int originalSize)+{+ return LZ4_decompress_unsafe_generic(+ (const BYTE*)source, (BYTE*)dest, originalSize,+ 64 KB, NULL, 0);+}++LZ4_FORCE_O2+static int LZ4_decompress_safe_withSmallPrefix(const char* source, char* dest, int compressedSize, int maxOutputSize,+ size_t prefixSize)+{+ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize,+ decode_full_block, noDict,+ (BYTE*)dest-prefixSize, NULL, 0);+}++LZ4_FORCE_O2+static int LZ4_decompress_safe_partial_withSmallPrefix(const char* source, char* dest, int compressedSize, int targetOutputSize, int dstCapacity,+ size_t prefixSize)+{+ dstCapacity = MIN(targetOutputSize, dstCapacity);+ return LZ4_decompress_generic(source, dest, compressedSize, dstCapacity,+ partial_decode, noDict,+ (BYTE*)dest-prefixSize, NULL, 0);+}++LZ4_FORCE_O2+int LZ4_decompress_safe_forceExtDict(const char* source, char* dest,+ int compressedSize, int maxOutputSize,+ const void* dictStart, size_t dictSize)+{+ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize,+ decode_full_block, usingExtDict,+ (BYTE*)dest, (const BYTE*)dictStart, dictSize);+}++LZ4_FORCE_O2+int LZ4_decompress_safe_partial_forceExtDict(const char* source, char* dest,+ int compressedSize, int targetOutputSize, int dstCapacity,+ const void* dictStart, size_t dictSize)+{+ dstCapacity = MIN(targetOutputSize, dstCapacity);+ return LZ4_decompress_generic(source, dest, compressedSize, dstCapacity,+ partial_decode, usingExtDict,+ (BYTE*)dest, (const BYTE*)dictStart, dictSize);+}++LZ4_FORCE_O2+static int LZ4_decompress_fast_extDict(const char* source, char* dest, int originalSize,+ const void* dictStart, size_t dictSize)+{+ return LZ4_decompress_unsafe_generic(+ (const BYTE*)source, (BYTE*)dest, originalSize,+ 0, (const BYTE*)dictStart, dictSize);+}++/* The "double dictionary" mode, for use with e.g. ring buffers: the first part+ * of the dictionary is passed as prefix, and the second via dictStart + dictSize.+ * These routines are used only once, in LZ4_decompress_*_continue().+ */+LZ4_FORCE_INLINE+int LZ4_decompress_safe_doubleDict(const char* source, char* dest, int compressedSize, int maxOutputSize,+ size_t prefixSize, const void* dictStart, size_t dictSize)+{+ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize,+ decode_full_block, usingExtDict,+ (BYTE*)dest-prefixSize, (const BYTE*)dictStart, dictSize);+}++/*===== streaming decompression functions =====*/++#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)+LZ4_streamDecode_t* LZ4_createStreamDecode(void)+{+ LZ4_STATIC_ASSERT(sizeof(LZ4_streamDecode_t) >= sizeof(LZ4_streamDecode_t_internal));+ return (LZ4_streamDecode_t*) ALLOC_AND_ZERO(sizeof(LZ4_streamDecode_t));+}++int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream)+{+ if (LZ4_stream == NULL) { return 0; } /* support free on NULL */+ FREEMEM(LZ4_stream);+ return 0;+}+#endif++/*! LZ4_setStreamDecode() :+ * Use this function to instruct where to find the dictionary.+ * This function is not necessary if previous data is still available where it was decoded.+ * Loading a size of 0 is allowed (same effect as no dictionary).+ * @return : 1 if OK, 0 if error+ */+int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize)+{+ LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse;+ lz4sd->prefixSize = (size_t)dictSize;+ if (dictSize) {+ assert(dictionary != NULL);+ lz4sd->prefixEnd = (const BYTE*) dictionary + dictSize;+ } else {+ lz4sd->prefixEnd = (const BYTE*) dictionary;+ }+ lz4sd->externalDict = NULL;+ lz4sd->extDictSize = 0;+ return 1;+}++/*! LZ4_decoderRingBufferSize() :+ * when setting a ring buffer for streaming decompression (optional scenario),+ * provides the minimum size of this ring buffer+ * to be compatible with any source respecting maxBlockSize condition.+ * Note : in a ring buffer scenario,+ * blocks are presumed decompressed next to each other.+ * When not enough space remains for next block (remainingSize < maxBlockSize),+ * decoding resumes from beginning of ring buffer.+ * @return : minimum ring buffer size,+ * or 0 if there is an error (invalid maxBlockSize).+ */+int LZ4_decoderRingBufferSize(int maxBlockSize)+{+ if (maxBlockSize < 0) return 0;+ if (maxBlockSize > LZ4_MAX_INPUT_SIZE) return 0;+ if (maxBlockSize < 16) maxBlockSize = 16;+ return LZ4_DECODER_RING_BUFFER_SIZE(maxBlockSize);+}++/*+*_continue() :+ These decoding functions allow decompression of multiple blocks in "streaming" mode.+ Previously decoded blocks must still be available at the memory position where they were decoded.+ If it's not possible, save the relevant part of decoded data into a safe buffer,+ and indicate where it stands using LZ4_setStreamDecode()+*/+LZ4_FORCE_O2+int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxOutputSize)+{+ LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse;+ int result;++ if (lz4sd->prefixSize == 0) {+ /* The first call, no dictionary yet. */+ assert(lz4sd->extDictSize == 0);+ result = LZ4_decompress_safe(source, dest, compressedSize, maxOutputSize);+ if (result <= 0) return result;+ lz4sd->prefixSize = (size_t)result;+ lz4sd->prefixEnd = (BYTE*)dest + result;+ } else if (lz4sd->prefixEnd == (BYTE*)dest) {+ /* They're rolling the current segment. */+ if (lz4sd->prefixSize >= 64 KB - 1)+ result = LZ4_decompress_safe_withPrefix64k(source, dest, compressedSize, maxOutputSize);+ else if (lz4sd->extDictSize == 0)+ result = LZ4_decompress_safe_withSmallPrefix(source, dest, compressedSize, maxOutputSize,+ lz4sd->prefixSize);+ else+ result = LZ4_decompress_safe_doubleDict(source, dest, compressedSize, maxOutputSize,+ lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize);+ if (result <= 0) return result;+ lz4sd->prefixSize += (size_t)result;+ lz4sd->prefixEnd += result;+ } else {+ /* The buffer wraps around, or they're switching to another buffer. */+ lz4sd->extDictSize = lz4sd->prefixSize;+ lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize;+ result = LZ4_decompress_safe_forceExtDict(source, dest, compressedSize, maxOutputSize,+ lz4sd->externalDict, lz4sd->extDictSize);+ if (result <= 0) return result;+ lz4sd->prefixSize = (size_t)result;+ lz4sd->prefixEnd = (BYTE*)dest + result;+ }++ return result;+}++LZ4_FORCE_O2 int+LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode,+ const char* source, char* dest, int originalSize)+{+ LZ4_streamDecode_t_internal* const lz4sd =+ (assert(LZ4_streamDecode!=NULL), &LZ4_streamDecode->internal_donotuse);+ int result;++ DEBUGLOG(5, "LZ4_decompress_fast_continue (toDecodeSize=%i)", originalSize);+ assert(originalSize >= 0);++ if (lz4sd->prefixSize == 0) {+ DEBUGLOG(5, "first invocation : no prefix nor extDict");+ assert(lz4sd->extDictSize == 0);+ result = LZ4_decompress_fast(source, dest, originalSize);+ if (result <= 0) return result;+ lz4sd->prefixSize = (size_t)originalSize;+ lz4sd->prefixEnd = (BYTE*)dest + originalSize;+ } else if (lz4sd->prefixEnd == (BYTE*)dest) {+ DEBUGLOG(5, "continue using existing prefix");+ result = LZ4_decompress_unsafe_generic(+ (const BYTE*)source, (BYTE*)dest, originalSize,+ lz4sd->prefixSize,+ lz4sd->externalDict, lz4sd->extDictSize);+ if (result <= 0) return result;+ lz4sd->prefixSize += (size_t)originalSize;+ lz4sd->prefixEnd += originalSize;+ } else {+ DEBUGLOG(5, "prefix becomes extDict");+ lz4sd->extDictSize = lz4sd->prefixSize;+ lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize;+ result = LZ4_decompress_fast_extDict(source, dest, originalSize,+ lz4sd->externalDict, lz4sd->extDictSize);+ if (result <= 0) return result;+ lz4sd->prefixSize = (size_t)originalSize;+ lz4sd->prefixEnd = (BYTE*)dest + originalSize;+ }++ return result;+}+++/*+Advanced decoding functions :+*_usingDict() :+ These decoding functions work the same as "_continue" ones,+ the dictionary must be explicitly provided within parameters+*/++int LZ4_decompress_safe_usingDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize)+{+ if (dictSize==0)+ return LZ4_decompress_safe(source, dest, compressedSize, maxOutputSize);+ if (dictStart+dictSize == dest) {+ if (dictSize >= 64 KB - 1) {+ return LZ4_decompress_safe_withPrefix64k(source, dest, compressedSize, maxOutputSize);+ }+ assert(dictSize >= 0);+ return LZ4_decompress_safe_withSmallPrefix(source, dest, compressedSize, maxOutputSize, (size_t)dictSize);+ }+ assert(dictSize >= 0);+ return LZ4_decompress_safe_forceExtDict(source, dest, compressedSize, maxOutputSize, dictStart, (size_t)dictSize);+}++int LZ4_decompress_safe_partial_usingDict(const char* source, char* dest, int compressedSize, int targetOutputSize, int dstCapacity, const char* dictStart, int dictSize)+{+ if (dictSize==0)+ return LZ4_decompress_safe_partial(source, dest, compressedSize, targetOutputSize, dstCapacity);+ if (dictStart+dictSize == dest) {+ if (dictSize >= 64 KB - 1) {+ return LZ4_decompress_safe_partial_withPrefix64k(source, dest, compressedSize, targetOutputSize, dstCapacity);+ }+ assert(dictSize >= 0);+ return LZ4_decompress_safe_partial_withSmallPrefix(source, dest, compressedSize, targetOutputSize, dstCapacity, (size_t)dictSize);+ }+ assert(dictSize >= 0);+ return LZ4_decompress_safe_partial_forceExtDict(source, dest, compressedSize, targetOutputSize, dstCapacity, dictStart, (size_t)dictSize);+}++int LZ4_decompress_fast_usingDict(const char* source, char* dest, int originalSize, const char* dictStart, int dictSize)+{+ if (dictSize==0 || dictStart+dictSize == dest)+ return LZ4_decompress_unsafe_generic(+ (const BYTE*)source, (BYTE*)dest, originalSize,+ (size_t)dictSize, NULL, 0);+ assert(dictSize >= 0);+ return LZ4_decompress_fast_extDict(source, dest, originalSize, dictStart, (size_t)dictSize);+}+++/*=*************************************************+* Obsolete Functions+***************************************************/+/* obsolete compression functions */+int LZ4_compress_limitedOutput(const char* source, char* dest, int inputSize, int maxOutputSize)+{+ return LZ4_compress_default(source, dest, inputSize, maxOutputSize);+}+int LZ4_compress(const char* src, char* dest, int srcSize)+{+ return LZ4_compress_default(src, dest, srcSize, LZ4_compressBound(srcSize));+}+int LZ4_compress_limitedOutput_withState (void* state, const char* src, char* dst, int srcSize, int dstSize)+{+ return LZ4_compress_fast_extState(state, src, dst, srcSize, dstSize, 1);+}+int LZ4_compress_withState (void* state, const char* src, char* dst, int srcSize)+{+ return LZ4_compress_fast_extState(state, src, dst, srcSize, LZ4_compressBound(srcSize), 1);+}+int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_stream, const char* src, char* dst, int srcSize, int dstCapacity)+{+ return LZ4_compress_fast_continue(LZ4_stream, src, dst, srcSize, dstCapacity, 1);+}+int LZ4_compress_continue (LZ4_stream_t* LZ4_stream, const char* source, char* dest, int inputSize)+{+ return LZ4_compress_fast_continue(LZ4_stream, source, dest, inputSize, LZ4_compressBound(inputSize), 1);+}++/*+These decompression functions are deprecated and should no longer be used.+They are only provided here for compatibility with older user programs.+- LZ4_uncompress is totally equivalent to LZ4_decompress_fast+- LZ4_uncompress_unknownOutputSize is totally equivalent to LZ4_decompress_safe+*/+int LZ4_uncompress (const char* source, char* dest, int outputSize)+{+ return LZ4_decompress_fast(source, dest, outputSize);+}+int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize)+{+ return LZ4_decompress_safe(source, dest, isize, maxOutputSize);+}++/* Obsolete Streaming functions */++int LZ4_sizeofStreamState(void) { return sizeof(LZ4_stream_t); }++int LZ4_resetStreamState(void* state, char* inputBuffer)+{+ (void)inputBuffer;+ LZ4_resetStream((LZ4_stream_t*)state);+ return 0;+}++#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)+void* LZ4_create (char* inputBuffer)+{+ (void)inputBuffer;+ return LZ4_createStream();+}+#endif++char* LZ4_slideInputBuffer (void* state)+{+ /* avoid const char * -> char * conversion warning */+ return (char *)(uptrval)((LZ4_stream_t*)state)->internal_donotuse.dictionary;+}++#endif /* LZ4_COMMONDEFS_ONLY */++}
+ cbits/tracy/public/common/tracy_lz4.hpp view
@@ -0,0 +1,847 @@+/*+ * LZ4 - Fast LZ compression algorithm+ * Header File+ * Copyright (C) 2011-2020, Yann Collet.++ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)++ 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.++ 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.++ You can contact the author at :+ - LZ4 homepage : http://www.lz4.org+ - LZ4 source repository : https://github.com/lz4/lz4+*/++#ifndef TRACY_LZ4_H_2983827168210+#define TRACY_LZ4_H_2983827168210++/* --- Dependency --- */+#include <stddef.h> /* size_t */+#include <stdint.h>+++/**+ Introduction++ LZ4 is lossless compression algorithm, providing compression speed >500 MB/s per core,+ scalable with multi-cores CPU. It features an extremely fast decoder, with speed in+ multiple GB/s per core, typically reaching RAM speed limits on multi-core systems.++ The LZ4 compression library provides in-memory compression and decompression functions.+ It gives full buffer control to user.+ Compression can be done in:+ - a single step (described as Simple Functions)+ - a single step, reusing a context (described in Advanced Functions)+ - unbounded multiple steps (described as Streaming compression)++ lz4.h generates and decodes LZ4-compressed blocks (doc/lz4_Block_format.md).+ Decompressing such a compressed block requires additional metadata.+ Exact metadata depends on exact decompression function.+ For the typical case of LZ4_decompress_safe(),+ metadata includes block's compressed size, and maximum bound of decompressed size.+ Each application is free to encode and pass such metadata in whichever way it wants.++ lz4.h only handle blocks, it can not generate Frames.++ Blocks are different from Frames (doc/lz4_Frame_format.md).+ Frames bundle both blocks and metadata in a specified manner.+ Embedding metadata is required for compressed data to be self-contained and portable.+ Frame format is delivered through a companion API, declared in lz4frame.h.+ The `lz4` CLI can only manage frames.+*/++/*^***************************************************************+* Export parameters+*****************************************************************/+/*+* LZ4_DLL_EXPORT :+* Enable exporting of functions when building a Windows DLL+* LZ4LIB_VISIBILITY :+* Control library symbols visibility.+*/+#ifndef LZ4LIB_VISIBILITY+# if defined(__GNUC__) && (__GNUC__ >= 4)+# define LZ4LIB_VISIBILITY __attribute__ ((visibility ("default")))+# else+# define LZ4LIB_VISIBILITY+# endif+#endif+#if defined(LZ4_DLL_EXPORT) && (LZ4_DLL_EXPORT==1)+# define LZ4LIB_API __declspec(dllexport) LZ4LIB_VISIBILITY+#elif defined(LZ4_DLL_IMPORT) && (LZ4_DLL_IMPORT==1)+# define LZ4LIB_API __declspec(dllimport) LZ4LIB_VISIBILITY /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/+#else+# define LZ4LIB_API LZ4LIB_VISIBILITY+#endif++/*! LZ4_FREESTANDING :+ * When this macro is set to 1, it enables "freestanding mode" that is+ * suitable for typical freestanding environment which doesn't support+ * standard C library.+ *+ * - LZ4_FREESTANDING is a compile-time switch.+ * - It requires the following macros to be defined:+ * LZ4_memcpy, LZ4_memmove, LZ4_memset.+ * - It only enables LZ4/HC functions which don't use heap.+ * All LZ4F_* functions are not supported.+ * - See tests/freestanding.c to check its basic setup.+ */+#if defined(LZ4_FREESTANDING) && (LZ4_FREESTANDING == 1)+# define LZ4_HEAPMODE 0+# define LZ4HC_HEAPMODE 0+# define LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION 1+# if !defined(LZ4_memcpy)+# error "LZ4_FREESTANDING requires macro 'LZ4_memcpy'."+# endif+# if !defined(LZ4_memset)+# error "LZ4_FREESTANDING requires macro 'LZ4_memset'."+# endif+# if !defined(LZ4_memmove)+# error "LZ4_FREESTANDING requires macro 'LZ4_memmove'."+# endif+#elif ! defined(LZ4_FREESTANDING)+# define LZ4_FREESTANDING 0+#endif+++/*------ Version ------*/+#define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */+#define LZ4_VERSION_MINOR 9 /* for new (non-breaking) interface capabilities */+#define LZ4_VERSION_RELEASE 4 /* for tweaks, bug-fixes, or development */++#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE)++#define LZ4_LIB_VERSION LZ4_VERSION_MAJOR.LZ4_VERSION_MINOR.LZ4_VERSION_RELEASE+#define LZ4_QUOTE(str) #str+#define LZ4_EXPAND_AND_QUOTE(str) LZ4_QUOTE(str)+#define LZ4_VERSION_STRING LZ4_EXPAND_AND_QUOTE(LZ4_LIB_VERSION) /* requires v1.7.3+ */++namespace tracy+{++LZ4LIB_API int LZ4_versionNumber (void); /**< library version number; useful to check dll version; requires v1.3.0+ */+LZ4LIB_API const char* LZ4_versionString (void); /**< library version string; useful to check dll version; requires v1.7.5+ */+++/*-************************************+* Tuning parameter+**************************************/+#define LZ4_MEMORY_USAGE_MIN 10+#define LZ4_MEMORY_USAGE_DEFAULT 14+#define LZ4_MEMORY_USAGE_MAX 20++/*!+ * LZ4_MEMORY_USAGE :+ * Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; )+ * Increasing memory usage improves compression ratio, at the cost of speed.+ * Reduced memory usage may improve speed at the cost of ratio, thanks to better cache locality.+ * Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache+ */+#ifndef LZ4_MEMORY_USAGE+# define LZ4_MEMORY_USAGE LZ4_MEMORY_USAGE_DEFAULT+#endif++#if (LZ4_MEMORY_USAGE < LZ4_MEMORY_USAGE_MIN)+# error "LZ4_MEMORY_USAGE is too small !"+#endif++#if (LZ4_MEMORY_USAGE > LZ4_MEMORY_USAGE_MAX)+# error "LZ4_MEMORY_USAGE is too large !"+#endif++/*-************************************+* Simple Functions+**************************************/+/*! LZ4_compress_default() :+ * Compresses 'srcSize' bytes from buffer 'src'+ * into already allocated 'dst' buffer of size 'dstCapacity'.+ * Compression is guaranteed to succeed if 'dstCapacity' >= LZ4_compressBound(srcSize).+ * It also runs faster, so it's a recommended setting.+ * If the function cannot compress 'src' into a more limited 'dst' budget,+ * compression stops *immediately*, and the function result is zero.+ * In which case, 'dst' content is undefined (invalid).+ * srcSize : max supported value is LZ4_MAX_INPUT_SIZE.+ * dstCapacity : size of buffer 'dst' (which must be already allocated)+ * @return : the number of bytes written into buffer 'dst' (necessarily <= dstCapacity)+ * or 0 if compression fails+ * Note : This function is protected against buffer overflow scenarios (never writes outside 'dst' buffer, nor read outside 'source' buffer).+ */+LZ4LIB_API int LZ4_compress_default(const char* src, char* dst, int srcSize, int dstCapacity);++/*! LZ4_decompress_safe() :+ * compressedSize : is the exact complete size of the compressed block.+ * dstCapacity : is the size of destination buffer (which must be already allocated), presumed an upper bound of decompressed size.+ * @return : the number of bytes decompressed into destination buffer (necessarily <= dstCapacity)+ * If destination buffer is not large enough, decoding will stop and output an error code (negative value).+ * If the source stream is detected malformed, the function will stop decoding and return a negative result.+ * Note 1 : This function is protected against malicious data packets :+ * it will never writes outside 'dst' buffer, nor read outside 'source' buffer,+ * even if the compressed block is maliciously modified to order the decoder to do these actions.+ * In such case, the decoder stops immediately, and considers the compressed block malformed.+ * Note 2 : compressedSize and dstCapacity must be provided to the function, the compressed block does not contain them.+ * The implementation is free to send / store / derive this information in whichever way is most beneficial.+ * If there is a need for a different format which bundles together both compressed data and its metadata, consider looking at lz4frame.h instead.+ */+LZ4LIB_API int LZ4_decompress_safe (const char* src, char* dst, int compressedSize, int dstCapacity);+++/*-************************************+* Advanced Functions+**************************************/+#define LZ4_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */+#define LZ4_COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16)++/*! LZ4_compressBound() :+ Provides the maximum size that LZ4 compression may output in a "worst case" scenario (input data not compressible)+ This function is primarily useful for memory allocation purposes (destination buffer size).+ Macro LZ4_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example).+ Note that LZ4_compress_default() compresses faster when dstCapacity is >= LZ4_compressBound(srcSize)+ inputSize : max supported value is LZ4_MAX_INPUT_SIZE+ return : maximum output size in a "worst case" scenario+ or 0, if input size is incorrect (too large or negative)+*/+LZ4LIB_API int LZ4_compressBound(int inputSize);++/*! LZ4_compress_fast() :+ Same as LZ4_compress_default(), but allows selection of "acceleration" factor.+ The larger the acceleration value, the faster the algorithm, but also the lesser the compression.+ It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed.+ An acceleration value of "1" is the same as regular LZ4_compress_default()+ Values <= 0 will be replaced by LZ4_ACCELERATION_DEFAULT (currently == 1, see lz4.c).+ Values > LZ4_ACCELERATION_MAX will be replaced by LZ4_ACCELERATION_MAX (currently == 65537, see lz4.c).+*/+LZ4LIB_API int LZ4_compress_fast (const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);+++/*! LZ4_compress_fast_extState() :+ * Same as LZ4_compress_fast(), using an externally allocated memory space for its state.+ * Use LZ4_sizeofState() to know how much memory must be allocated,+ * and allocate it on 8-bytes boundaries (using `malloc()` typically).+ * Then, provide this buffer as `void* state` to compression function.+ */+LZ4LIB_API int LZ4_sizeofState(void);+LZ4LIB_API int LZ4_compress_fast_extState (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);+++/*! LZ4_compress_destSize() :+ * Reverse the logic : compresses as much data as possible from 'src' buffer+ * into already allocated buffer 'dst', of size >= 'targetDestSize'.+ * This function either compresses the entire 'src' content into 'dst' if it's large enough,+ * or fill 'dst' buffer completely with as much data as possible from 'src'.+ * note: acceleration parameter is fixed to "default".+ *+ * *srcSizePtr : will be modified to indicate how many bytes where read from 'src' to fill 'dst'.+ * New value is necessarily <= input value.+ * @return : Nb bytes written into 'dst' (necessarily <= targetDestSize)+ * or 0 if compression fails.+ *+ * Note : from v1.8.2 to v1.9.1, this function had a bug (fixed un v1.9.2+):+ * the produced compressed content could, in specific circumstances,+ * require to be decompressed into a destination buffer larger+ * by at least 1 byte than the content to decompress.+ * If an application uses `LZ4_compress_destSize()`,+ * it's highly recommended to update liblz4 to v1.9.2 or better.+ * If this can't be done or ensured,+ * the receiving decompression function should provide+ * a dstCapacity which is > decompressedSize, by at least 1 byte.+ * See https://github.com/lz4/lz4/issues/859 for details+ */+LZ4LIB_API int LZ4_compress_destSize (const char* src, char* dst, int* srcSizePtr, int targetDstSize);+++/*! LZ4_decompress_safe_partial() :+ * Decompress an LZ4 compressed block, of size 'srcSize' at position 'src',+ * into destination buffer 'dst' of size 'dstCapacity'.+ * Up to 'targetOutputSize' bytes will be decoded.+ * The function stops decoding on reaching this objective.+ * This can be useful to boost performance+ * whenever only the beginning of a block is required.+ *+ * @return : the number of bytes decoded in `dst` (necessarily <= targetOutputSize)+ * If source stream is detected malformed, function returns a negative result.+ *+ * Note 1 : @return can be < targetOutputSize, if compressed block contains less data.+ *+ * Note 2 : targetOutputSize must be <= dstCapacity+ *+ * Note 3 : this function effectively stops decoding on reaching targetOutputSize,+ * so dstCapacity is kind of redundant.+ * This is because in older versions of this function,+ * decoding operation would still write complete sequences.+ * Therefore, there was no guarantee that it would stop writing at exactly targetOutputSize,+ * it could write more bytes, though only up to dstCapacity.+ * Some "margin" used to be required for this operation to work properly.+ * Thankfully, this is no longer necessary.+ * The function nonetheless keeps the same signature, in an effort to preserve API compatibility.+ *+ * Note 4 : If srcSize is the exact size of the block,+ * then targetOutputSize can be any value,+ * including larger than the block's decompressed size.+ * The function will, at most, generate block's decompressed size.+ *+ * Note 5 : If srcSize is _larger_ than block's compressed size,+ * then targetOutputSize **MUST** be <= block's decompressed size.+ * Otherwise, *silent corruption will occur*.+ */+LZ4LIB_API int LZ4_decompress_safe_partial (const char* src, char* dst, int srcSize, int targetOutputSize, int dstCapacity);+++/*-*********************************************+* Streaming Compression Functions+***********************************************/+typedef union LZ4_stream_u LZ4_stream_t; /* incomplete type (defined later) */++/**+ Note about RC_INVOKED++ - RC_INVOKED is predefined symbol of rc.exe (the resource compiler which is part of MSVC/Visual Studio).+ https://docs.microsoft.com/en-us/windows/win32/menurc/predefined-macros++ - Since rc.exe is a legacy compiler, it truncates long symbol (> 30 chars)+ and reports warning "RC4011: identifier truncated".++ - To eliminate the warning, we surround long preprocessor symbol with+ "#if !defined(RC_INVOKED) ... #endif" block that means+ "skip this block when rc.exe is trying to read it".+*/+#if !defined(RC_INVOKED) /* https://docs.microsoft.com/en-us/windows/win32/menurc/predefined-macros */+#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)+LZ4LIB_API LZ4_stream_t* LZ4_createStream(void);+LZ4LIB_API int LZ4_freeStream (LZ4_stream_t* streamPtr);+#endif /* !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION) */+#endif++/*! LZ4_resetStream_fast() : v1.9.0++ * Use this to prepare an LZ4_stream_t for a new chain of dependent blocks+ * (e.g., LZ4_compress_fast_continue()).+ *+ * An LZ4_stream_t must be initialized once before usage.+ * This is automatically done when created by LZ4_createStream().+ * However, should the LZ4_stream_t be simply declared on stack (for example),+ * it's necessary to initialize it first, using LZ4_initStream().+ *+ * After init, start any new stream with LZ4_resetStream_fast().+ * A same LZ4_stream_t can be re-used multiple times consecutively+ * and compress multiple streams,+ * provided that it starts each new stream with LZ4_resetStream_fast().+ *+ * LZ4_resetStream_fast() is much faster than LZ4_initStream(),+ * but is not compatible with memory regions containing garbage data.+ *+ * Note: it's only useful to call LZ4_resetStream_fast()+ * in the context of streaming compression.+ * The *extState* functions perform their own resets.+ * Invoking LZ4_resetStream_fast() before is redundant, and even counterproductive.+ */+LZ4LIB_API void LZ4_resetStream_fast (LZ4_stream_t* streamPtr);++/*! LZ4_loadDict() :+ * Use this function to reference a static dictionary into LZ4_stream_t.+ * The dictionary must remain available during compression.+ * LZ4_loadDict() triggers a reset, so any previous data will be forgotten.+ * The same dictionary will have to be loaded on decompression side for successful decoding.+ * Dictionary are useful for better compression of small data (KB range).+ * While LZ4 accept any input as dictionary,+ * results are generally better when using Zstandard's Dictionary Builder.+ * Loading a size of 0 is allowed, and is the same as reset.+ * @return : loaded dictionary size, in bytes (necessarily <= 64 KB)+ */+LZ4LIB_API int LZ4_loadDict (LZ4_stream_t* streamPtr, const char* dictionary, int dictSize);++/*! LZ4_compress_fast_continue() :+ * Compress 'src' content using data from previously compressed blocks, for better compression ratio.+ * 'dst' buffer must be already allocated.+ * If dstCapacity >= LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster.+ *+ * @return : size of compressed block+ * or 0 if there is an error (typically, cannot fit into 'dst').+ *+ * Note 1 : Each invocation to LZ4_compress_fast_continue() generates a new block.+ * Each block has precise boundaries.+ * Each block must be decompressed separately, calling LZ4_decompress_*() with relevant metadata.+ * It's not possible to append blocks together and expect a single invocation of LZ4_decompress_*() to decompress them together.+ *+ * Note 2 : The previous 64KB of source data is __assumed__ to remain present, unmodified, at same address in memory !+ *+ * Note 3 : When input is structured as a double-buffer, each buffer can have any size, including < 64 KB.+ * Make sure that buffers are separated, by at least one byte.+ * This construction ensures that each block only depends on previous block.+ *+ * Note 4 : If input buffer is a ring-buffer, it can have any size, including < 64 KB.+ *+ * Note 5 : After an error, the stream status is undefined (invalid), it can only be reset or freed.+ */+LZ4LIB_API int LZ4_compress_fast_continue (LZ4_stream_t* streamPtr, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);++/*! LZ4_saveDict() :+ * If last 64KB data cannot be guaranteed to remain available at its current memory location,+ * save it into a safer place (char* safeBuffer).+ * This is schematically equivalent to a memcpy() followed by LZ4_loadDict(),+ * but is much faster, because LZ4_saveDict() doesn't need to rebuild tables.+ * @return : saved dictionary size in bytes (necessarily <= maxDictSize), or 0 if error.+ */+LZ4LIB_API int LZ4_saveDict (LZ4_stream_t* streamPtr, char* safeBuffer, int maxDictSize);+++/*-**********************************************+* Streaming Decompression Functions+* Bufferless synchronous API+************************************************/+typedef union LZ4_streamDecode_u LZ4_streamDecode_t; /* tracking context */++/*! LZ4_createStreamDecode() and LZ4_freeStreamDecode() :+ * creation / destruction of streaming decompression tracking context.+ * A tracking context can be re-used multiple times.+ */+#if !defined(RC_INVOKED) /* https://docs.microsoft.com/en-us/windows/win32/menurc/predefined-macros */+#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)+LZ4LIB_API LZ4_streamDecode_t* LZ4_createStreamDecode(void);+LZ4LIB_API int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream);+#endif /* !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION) */+#endif++/*! LZ4_setStreamDecode() :+ * An LZ4_streamDecode_t context can be allocated once and re-used multiple times.+ * Use this function to start decompression of a new stream of blocks.+ * A dictionary can optionally be set. Use NULL or size 0 for a reset order.+ * Dictionary is presumed stable : it must remain accessible and unmodified during next decompression.+ * @return : 1 if OK, 0 if error+ */+LZ4LIB_API int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize);++/*! LZ4_decoderRingBufferSize() : v1.8.2++ * Note : in a ring buffer scenario (optional),+ * blocks are presumed decompressed next to each other+ * up to the moment there is not enough remaining space for next block (remainingSize < maxBlockSize),+ * at which stage it resumes from beginning of ring buffer.+ * When setting such a ring buffer for streaming decompression,+ * provides the minimum size of this ring buffer+ * to be compatible with any source respecting maxBlockSize condition.+ * @return : minimum ring buffer size,+ * or 0 if there is an error (invalid maxBlockSize).+ */+LZ4LIB_API int LZ4_decoderRingBufferSize(int maxBlockSize);+#define LZ4_DECODER_RING_BUFFER_SIZE(maxBlockSize) (65536 + 14 + (maxBlockSize)) /* for static allocation; maxBlockSize presumed valid */++/*! LZ4_decompress_*_continue() :+ * These decoding functions allow decompression of consecutive blocks in "streaming" mode.+ * A block is an unsplittable entity, it must be presented entirely to a decompression function.+ * Decompression functions only accepts one block at a time.+ * The last 64KB of previously decoded data *must* remain available and unmodified at the memory position where they were decoded.+ * If less than 64KB of data has been decoded, all the data must be present.+ *+ * Special : if decompression side sets a ring buffer, it must respect one of the following conditions :+ * - Decompression buffer size is _at least_ LZ4_decoderRingBufferSize(maxBlockSize).+ * maxBlockSize is the maximum size of any single block. It can have any value > 16 bytes.+ * In which case, encoding and decoding buffers do not need to be synchronized.+ * Actually, data can be produced by any source compliant with LZ4 format specification, and respecting maxBlockSize.+ * - Synchronized mode :+ * Decompression buffer size is _exactly_ the same as compression buffer size,+ * and follows exactly same update rule (block boundaries at same positions),+ * and decoding function is provided with exact decompressed size of each block (exception for last block of the stream),+ * _then_ decoding & encoding ring buffer can have any size, including small ones ( < 64 KB).+ * - Decompression buffer is larger than encoding buffer, by a minimum of maxBlockSize more bytes.+ * In which case, encoding and decoding buffers do not need to be synchronized,+ * and encoding ring buffer can have any size, including small ones ( < 64 KB).+ *+ * Whenever these conditions are not possible,+ * save the last 64KB of decoded data into a safe buffer where it can't be modified during decompression,+ * then indicate where this data is saved using LZ4_setStreamDecode(), before decompressing next block.+*/+LZ4LIB_API int+LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode,+ const char* src, char* dst,+ int srcSize, int dstCapacity);+++/*! LZ4_decompress_*_usingDict() :+ * These decoding functions work the same as+ * a combination of LZ4_setStreamDecode() followed by LZ4_decompress_*_continue()+ * They are stand-alone, and don't need an LZ4_streamDecode_t structure.+ * Dictionary is presumed stable : it must remain accessible and unmodified during decompression.+ * Performance tip : Decompression speed can be substantially increased+ * when dst == dictStart + dictSize.+ */+LZ4LIB_API int+LZ4_decompress_safe_usingDict(const char* src, char* dst,+ int srcSize, int dstCapacity,+ const char* dictStart, int dictSize);++LZ4LIB_API int+LZ4_decompress_safe_partial_usingDict(const char* src, char* dst,+ int compressedSize,+ int targetOutputSize, int maxOutputSize,+ const char* dictStart, int dictSize);++}++#endif /* LZ4_H_2983827168210 */+++/*^*************************************+ * !!!!!! STATIC LINKING ONLY !!!!!!+ ***************************************/++/*-****************************************************************************+ * Experimental section+ *+ * Symbols declared in this section must be considered unstable. Their+ * signatures or semantics may change, or they may be removed altogether in the+ * future. They are therefore only safe to depend on when the caller is+ * statically linked against the library.+ *+ * To protect against unsafe usage, not only are the declarations guarded,+ * the definitions are hidden by default+ * when building LZ4 as a shared/dynamic library.+ *+ * In order to access these declarations,+ * define LZ4_STATIC_LINKING_ONLY in your application+ * before including LZ4's headers.+ *+ * In order to make their implementations accessible dynamically, you must+ * define LZ4_PUBLISH_STATIC_FUNCTIONS when building the LZ4 library.+ ******************************************************************************/++#ifdef LZ4_STATIC_LINKING_ONLY++#ifndef TRACY_LZ4_STATIC_3504398509+#define TRACY_LZ4_STATIC_3504398509++#ifdef LZ4_PUBLISH_STATIC_FUNCTIONS+#define LZ4LIB_STATIC_API LZ4LIB_API+#else+#define LZ4LIB_STATIC_API+#endif++namespace tracy+{++/*! LZ4_compress_fast_extState_fastReset() :+ * A variant of LZ4_compress_fast_extState().+ *+ * Using this variant avoids an expensive initialization step.+ * It is only safe to call if the state buffer is known to be correctly initialized already+ * (see above comment on LZ4_resetStream_fast() for a definition of "correctly initialized").+ * From a high level, the difference is that+ * this function initializes the provided state with a call to something like LZ4_resetStream_fast()+ * while LZ4_compress_fast_extState() starts with a call to LZ4_resetStream().+ */+LZ4LIB_STATIC_API int LZ4_compress_fast_extState_fastReset (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);++/*! LZ4_attach_dictionary() :+ * This is an experimental API that allows+ * efficient use of a static dictionary many times.+ *+ * Rather than re-loading the dictionary buffer into a working context before+ * each compression, or copying a pre-loaded dictionary's LZ4_stream_t into a+ * working LZ4_stream_t, this function introduces a no-copy setup mechanism,+ * in which the working stream references the dictionary stream in-place.+ *+ * Several assumptions are made about the state of the dictionary stream.+ * Currently, only streams which have been prepared by LZ4_loadDict() should+ * be expected to work.+ *+ * Alternatively, the provided dictionaryStream may be NULL,+ * in which case any existing dictionary stream is unset.+ *+ * If a dictionary is provided, it replaces any pre-existing stream history.+ * The dictionary contents are the only history that can be referenced and+ * logically immediately precede the data compressed in the first subsequent+ * compression call.+ *+ * The dictionary will only remain attached to the working stream through the+ * first compression call, at the end of which it is cleared. The dictionary+ * stream (and source buffer) must remain in-place / accessible / unchanged+ * through the completion of the first compression call on the stream.+ */+LZ4LIB_STATIC_API void+LZ4_attach_dictionary(LZ4_stream_t* workingStream,+ const LZ4_stream_t* dictionaryStream);+++/*! In-place compression and decompression+ *+ * It's possible to have input and output sharing the same buffer,+ * for highly constrained memory environments.+ * In both cases, it requires input to lay at the end of the buffer,+ * and decompression to start at beginning of the buffer.+ * Buffer size must feature some margin, hence be larger than final size.+ *+ * |<------------------------buffer--------------------------------->|+ * |<-----------compressed data--------->|+ * |<-----------decompressed size------------------>|+ * |<----margin---->|+ *+ * This technique is more useful for decompression,+ * since decompressed size is typically larger,+ * and margin is short.+ *+ * In-place decompression will work inside any buffer+ * which size is >= LZ4_DECOMPRESS_INPLACE_BUFFER_SIZE(decompressedSize).+ * This presumes that decompressedSize > compressedSize.+ * Otherwise, it means compression actually expanded data,+ * and it would be more efficient to store such data with a flag indicating it's not compressed.+ * This can happen when data is not compressible (already compressed, or encrypted).+ *+ * For in-place compression, margin is larger, as it must be able to cope with both+ * history preservation, requiring input data to remain unmodified up to LZ4_DISTANCE_MAX,+ * and data expansion, which can happen when input is not compressible.+ * As a consequence, buffer size requirements are much higher,+ * and memory savings offered by in-place compression are more limited.+ *+ * There are ways to limit this cost for compression :+ * - Reduce history size, by modifying LZ4_DISTANCE_MAX.+ * Note that it is a compile-time constant, so all compressions will apply this limit.+ * Lower values will reduce compression ratio, except when input_size < LZ4_DISTANCE_MAX,+ * so it's a reasonable trick when inputs are known to be small.+ * - Require the compressor to deliver a "maximum compressed size".+ * This is the `dstCapacity` parameter in `LZ4_compress*()`.+ * When this size is < LZ4_COMPRESSBOUND(inputSize), then compression can fail,+ * in which case, the return code will be 0 (zero).+ * The caller must be ready for these cases to happen,+ * and typically design a backup scheme to send data uncompressed.+ * The combination of both techniques can significantly reduce+ * the amount of margin required for in-place compression.+ *+ * In-place compression can work in any buffer+ * which size is >= (maxCompressedSize)+ * with maxCompressedSize == LZ4_COMPRESSBOUND(srcSize) for guaranteed compression success.+ * LZ4_COMPRESS_INPLACE_BUFFER_SIZE() depends on both maxCompressedSize and LZ4_DISTANCE_MAX,+ * so it's possible to reduce memory requirements by playing with them.+ */++#define LZ4_DECOMPRESS_INPLACE_MARGIN(compressedSize) (((compressedSize) >> 8) + 32)+#define LZ4_DECOMPRESS_INPLACE_BUFFER_SIZE(decompressedSize) ((decompressedSize) + LZ4_DECOMPRESS_INPLACE_MARGIN(decompressedSize)) /**< note: presumes that compressedSize < decompressedSize. note2: margin is overestimated a bit, since it could use compressedSize instead */++#ifndef LZ4_DISTANCE_MAX /* history window size; can be user-defined at compile time */+# define LZ4_DISTANCE_MAX 65535 /* set to maximum value by default */+#endif++#define LZ4_COMPRESS_INPLACE_MARGIN (LZ4_DISTANCE_MAX + 32) /* LZ4_DISTANCE_MAX can be safely replaced by srcSize when it's smaller */+#define LZ4_COMPRESS_INPLACE_BUFFER_SIZE(maxCompressedSize) ((maxCompressedSize) + LZ4_COMPRESS_INPLACE_MARGIN) /**< maxCompressedSize is generally LZ4_COMPRESSBOUND(inputSize), but can be set to any lower value, with the risk that compression can fail (return code 0(zero)) */++}++#endif /* LZ4_STATIC_3504398509 */+#endif /* LZ4_STATIC_LINKING_ONLY */++++#ifndef TRACY_LZ4_H_98237428734687+#define TRACY_LZ4_H_98237428734687++namespace tracy+{++/*-************************************************************+ * Private Definitions+ **************************************************************+ * Do not use these definitions directly.+ * They are only exposed to allow static allocation of `LZ4_stream_t` and `LZ4_streamDecode_t`.+ * Accessing members will expose user code to API and/or ABI break in future versions of the library.+ **************************************************************/+#define LZ4_HASHLOG (LZ4_MEMORY_USAGE-2)+#define LZ4_HASHTABLESIZE (1 << LZ4_MEMORY_USAGE)+#define LZ4_HASH_SIZE_U32 (1 << LZ4_HASHLOG) /* required as macro for static allocation */++#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)+ typedef int8_t LZ4_i8;+ typedef uint8_t LZ4_byte;+ typedef uint16_t LZ4_u16;+ typedef uint32_t LZ4_u32;+#else+ typedef signed char LZ4_i8;+ typedef unsigned char LZ4_byte;+ typedef unsigned short LZ4_u16;+ typedef unsigned int LZ4_u32;+#endif++/*! LZ4_stream_t :+ * Never ever use below internal definitions directly !+ * These definitions are not API/ABI safe, and may change in future versions.+ * If you need static allocation, declare or allocate an LZ4_stream_t object.+**/++typedef struct LZ4_stream_t_internal LZ4_stream_t_internal;+struct LZ4_stream_t_internal {+ LZ4_u32 hashTable[LZ4_HASH_SIZE_U32];+ const LZ4_byte* dictionary;+ const LZ4_stream_t_internal* dictCtx;+ LZ4_u32 currentOffset;+ LZ4_u32 tableType;+ LZ4_u32 dictSize;+ /* Implicit padding to ensure structure is aligned */+};++#define LZ4_STREAM_MINSIZE ((1UL << LZ4_MEMORY_USAGE) + 32) /* static size, for inter-version compatibility */+union LZ4_stream_u {+ char minStateSize[LZ4_STREAM_MINSIZE];+ LZ4_stream_t_internal internal_donotuse;+}; /* previously typedef'd to LZ4_stream_t */+++/*! LZ4_initStream() : v1.9.0++ * An LZ4_stream_t structure must be initialized at least once.+ * This is automatically done when invoking LZ4_createStream(),+ * but it's not when the structure is simply declared on stack (for example).+ *+ * Use LZ4_initStream() to properly initialize a newly declared LZ4_stream_t.+ * It can also initialize any arbitrary buffer of sufficient size,+ * and will @return a pointer of proper type upon initialization.+ *+ * Note : initialization fails if size and alignment conditions are not respected.+ * In which case, the function will @return NULL.+ * Note2: An LZ4_stream_t structure guarantees correct alignment and size.+ * Note3: Before v1.9.0, use LZ4_resetStream() instead+**/+LZ4LIB_API LZ4_stream_t* LZ4_initStream (void* buffer, size_t size);+++/*! LZ4_streamDecode_t :+ * Never ever use below internal definitions directly !+ * These definitions are not API/ABI safe, and may change in future versions.+ * If you need static allocation, declare or allocate an LZ4_streamDecode_t object.+**/+typedef struct {+ const LZ4_byte* externalDict;+ const LZ4_byte* prefixEnd;+ size_t extDictSize;+ size_t prefixSize;+} LZ4_streamDecode_t_internal;++#define LZ4_STREAMDECODE_MINSIZE 32+union LZ4_streamDecode_u {+ char minStateSize[LZ4_STREAMDECODE_MINSIZE];+ LZ4_streamDecode_t_internal internal_donotuse;+} ; /* previously typedef'd to LZ4_streamDecode_t */++++/*-************************************+* Obsolete Functions+**************************************/++/*! Deprecation warnings+ *+ * Deprecated functions make the compiler generate a warning when invoked.+ * This is meant to invite users to update their source code.+ * Should deprecation 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.+ *+ * Another method is to define LZ4_DISABLE_DEPRECATE_WARNINGS+ * before including the header file.+ */+#ifdef LZ4_DISABLE_DEPRECATE_WARNINGS+# define LZ4_DEPRECATED(message) /* disable deprecation warnings */+#else+# if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */+# define LZ4_DEPRECATED(message) [[deprecated(message)]]+# elif defined(_MSC_VER)+# define LZ4_DEPRECATED(message) __declspec(deprecated(message))+# elif defined(__clang__) || (defined(__GNUC__) && (__GNUC__ * 10 + __GNUC_MINOR__ >= 45))+# define LZ4_DEPRECATED(message) __attribute__((deprecated(message)))+# elif defined(__GNUC__) && (__GNUC__ * 10 + __GNUC_MINOR__ >= 31)+# define LZ4_DEPRECATED(message) __attribute__((deprecated))+# else+# pragma message("WARNING: LZ4_DEPRECATED needs custom implementation for this compiler")+# define LZ4_DEPRECATED(message) /* disabled */+# endif+#endif /* LZ4_DISABLE_DEPRECATE_WARNINGS */++/*! Obsolete compression functions (since v1.7.3) */+LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API int LZ4_compress (const char* src, char* dest, int srcSize);+LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API int LZ4_compress_limitedOutput (const char* src, char* dest, int srcSize, int maxOutputSize);+LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API int LZ4_compress_withState (void* state, const char* source, char* dest, int inputSize);+LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);+LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") LZ4LIB_API int LZ4_compress_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize);+LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") LZ4LIB_API int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize);++/*! Obsolete decompression functions (since v1.8.0) */+LZ4_DEPRECATED("use LZ4_decompress_fast() instead") LZ4LIB_API int LZ4_uncompress (const char* source, char* dest, int outputSize);+LZ4_DEPRECATED("use LZ4_decompress_safe() instead") LZ4LIB_API int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize);++/* Obsolete streaming functions (since v1.7.0)+ * degraded functionality; do not use!+ *+ * In order to perform streaming compression, these functions depended on data+ * that is no longer tracked in the state. They have been preserved as well as+ * possible: using them will still produce a correct output. However, they don't+ * actually retain any history between compression calls. The compression ratio+ * achieved will therefore be no better than compressing each chunk+ * independently.+ */+LZ4_DEPRECATED("Use LZ4_createStream() instead") LZ4LIB_API void* LZ4_create (char* inputBuffer);+LZ4_DEPRECATED("Use LZ4_createStream() instead") LZ4LIB_API int LZ4_sizeofStreamState(void);+LZ4_DEPRECATED("Use LZ4_resetStream() instead") LZ4LIB_API int LZ4_resetStreamState(void* state, char* inputBuffer);+LZ4_DEPRECATED("Use LZ4_saveDict() instead") LZ4LIB_API char* LZ4_slideInputBuffer (void* state);++/*! Obsolete streaming decoding functions (since v1.7.0) */+LZ4_DEPRECATED("use LZ4_decompress_safe_usingDict() instead") LZ4LIB_API int LZ4_decompress_safe_withPrefix64k (const char* src, char* dst, int compressedSize, int maxDstSize);+LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") LZ4LIB_API int LZ4_decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize);++/*! Obsolete LZ4_decompress_fast variants (since v1.9.0) :+ * These functions used to be faster than LZ4_decompress_safe(),+ * but this is no longer the case. They are now slower.+ * This is because LZ4_decompress_fast() doesn't know the input size,+ * and therefore must progress more cautiously into the input buffer to not read beyond the end of block.+ * On top of that `LZ4_decompress_fast()` is not protected vs malformed or malicious inputs, making it a security liability.+ * As a consequence, LZ4_decompress_fast() is strongly discouraged, and deprecated.+ *+ * The last remaining LZ4_decompress_fast() specificity is that+ * it can decompress a block without knowing its compressed size.+ * Such functionality can be achieved in a more secure manner+ * by employing LZ4_decompress_safe_partial().+ *+ * Parameters:+ * originalSize : is the uncompressed size to regenerate.+ * `dst` must be already allocated, its size must be >= 'originalSize' bytes.+ * @return : number of bytes read from source buffer (== compressed size).+ * The function expects to finish at block's end exactly.+ * If the source stream is detected malformed, the function stops decoding and returns a negative result.+ * note : LZ4_decompress_fast*() requires originalSize. Thanks to this information, it never writes past the output buffer.+ * However, since it doesn't know its 'src' size, it may read an unknown amount of input, past input buffer bounds.+ * Also, since match offsets are not validated, match reads from 'src' may underflow too.+ * These issues never happen if input (compressed) data is correct.+ * But they may happen if input data is invalid (error or intentional tampering).+ * As a consequence, use these functions in trusted environments with trusted data **only**.+ */+LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe() instead")+LZ4LIB_API int LZ4_decompress_fast (const char* src, char* dst, int originalSize);+LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe_continue() instead")+LZ4LIB_API int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* src, char* dst, int originalSize);+LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe_usingDict() instead")+LZ4LIB_API int LZ4_decompress_fast_usingDict (const char* src, char* dst, int originalSize, const char* dictStart, int dictSize);++/*! LZ4_resetStream() :+ * An LZ4_stream_t structure must be initialized at least once.+ * This is done with LZ4_initStream(), or LZ4_resetStream().+ * Consider switching to LZ4_initStream(),+ * invoking LZ4_resetStream() will trigger deprecation warnings in the future.+ */+LZ4LIB_API void LZ4_resetStream (LZ4_stream_t* streamPtr);++}++#endif /* LZ4_H_98237428734687 */
+ cbits/tracy/public/common/tracy_lz4hc.cpp view
@@ -0,0 +1,1636 @@+/*+ LZ4 HC - High Compression Mode of LZ4+ Copyright (C) 2011-2020, Yann Collet.++ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)++ 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.++ 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.++ You can contact the author at :+ - LZ4 source repository : https://github.com/lz4/lz4+ - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c+*/+/* note : lz4hc is not an independent module, it requires lz4.h/lz4.c for proper compilation */+++/* *************************************+* Tuning Parameter+***************************************/++/*! HEAPMODE :+ * Select how default compression function will allocate workplace memory,+ * in stack (0:fastest), or in heap (1:requires malloc()).+ * Since workplace is rather large, heap mode is recommended.+**/+#ifndef LZ4HC_HEAPMODE+# define LZ4HC_HEAPMODE 1+#endif+++/*=== Dependency ===*/+#define LZ4_HC_STATIC_LINKING_ONLY+#include "tracy_lz4hc.hpp"+++/*=== Common definitions ===*/+#if defined(__GNUC__)+# pragma GCC diagnostic ignored "-Wunused-function"+#endif+#if defined (__clang__)+# pragma clang diagnostic ignored "-Wunused-function"+#endif++#define LZ4_COMMONDEFS_ONLY+#ifndef LZ4_SRC_INCLUDED+#include "tracy_lz4.cpp" /* LZ4_count, constants, mem */+#endif+++/*=== Enums ===*/+typedef enum { noDictCtx, usingDictCtxHc } dictCtx_directive;+++/*=== Constants ===*/+#define OPTIMAL_ML (int)((ML_MASK-1)+MINMATCH)+#define LZ4_OPT_NUM (1<<12)+++/*=== Macros ===*/+#define MIN(a,b) ( (a) < (b) ? (a) : (b) )+#define MAX(a,b) ( (a) > (b) ? (a) : (b) )+#define HASH_FUNCTION(i) (((i) * 2654435761U) >> ((MINMATCH*8)-LZ4HC_HASH_LOG))+#define DELTANEXTMAXD(p) chainTable[(p) & LZ4HC_MAXD_MASK] /* flexible, LZ4HC_MAXD dependent */+#define DELTANEXTU16(table, pos) table[(U16)(pos)] /* faster */+/* Make fields passed to, and updated by LZ4HC_encodeSequence explicit */+#define UPDATABLE(ip, op, anchor) &ip, &op, &anchor++namespace tracy+{++static U32 LZ4HC_hashPtr(const void* ptr) { return HASH_FUNCTION(LZ4_read32(ptr)); }+++/**************************************+* HC Compression+**************************************/+static void LZ4HC_clearTables (LZ4HC_CCtx_internal* hc4)+{+ MEM_INIT(hc4->hashTable, 0, sizeof(hc4->hashTable));+ MEM_INIT(hc4->chainTable, 0xFF, sizeof(hc4->chainTable));+}++static void LZ4HC_init_internal (LZ4HC_CCtx_internal* hc4, const BYTE* start)+{+ size_t const bufferSize = (size_t)(hc4->end - hc4->prefixStart);+ size_t newStartingOffset = bufferSize + hc4->dictLimit;+ assert(newStartingOffset >= bufferSize); /* check overflow */+ if (newStartingOffset > 1 GB) {+ LZ4HC_clearTables(hc4);+ newStartingOffset = 0;+ }+ newStartingOffset += 64 KB;+ hc4->nextToUpdate = (U32)newStartingOffset;+ hc4->prefixStart = start;+ hc4->end = start;+ hc4->dictStart = start;+ hc4->dictLimit = (U32)newStartingOffset;+ hc4->lowLimit = (U32)newStartingOffset;+}+++/* Update chains up to ip (excluded) */+LZ4_FORCE_INLINE void LZ4HC_Insert (LZ4HC_CCtx_internal* hc4, const BYTE* ip)+{+ U16* const chainTable = hc4->chainTable;+ U32* const hashTable = hc4->hashTable;+ const BYTE* const prefixPtr = hc4->prefixStart;+ U32 const prefixIdx = hc4->dictLimit;+ U32 const target = (U32)(ip - prefixPtr) + prefixIdx;+ U32 idx = hc4->nextToUpdate;+ assert(ip >= prefixPtr);+ assert(target >= prefixIdx);++ while (idx < target) {+ U32 const h = LZ4HC_hashPtr(prefixPtr+idx-prefixIdx);+ size_t delta = idx - hashTable[h];+ if (delta>LZ4_DISTANCE_MAX) delta = LZ4_DISTANCE_MAX;+ DELTANEXTU16(chainTable, idx) = (U16)delta;+ hashTable[h] = idx;+ idx++;+ }++ hc4->nextToUpdate = target;+}++/** LZ4HC_countBack() :+ * @return : negative value, nb of common bytes before ip/match */+LZ4_FORCE_INLINE+int LZ4HC_countBack(const BYTE* const ip, const BYTE* const match,+ const BYTE* const iMin, const BYTE* const mMin)+{+ int back = 0;+ int const min = (int)MAX(iMin - ip, mMin - match);+ assert(min <= 0);+ assert(ip >= iMin); assert((size_t)(ip-iMin) < (1U<<31));+ assert(match >= mMin); assert((size_t)(match - mMin) < (1U<<31));+ while ( (back > min)+ && (ip[back-1] == match[back-1]) )+ back--;+ return back;+}++#if defined(_MSC_VER)+# define LZ4HC_rotl32(x,r) _rotl(x,r)+#else+# define LZ4HC_rotl32(x,r) ((x << r) | (x >> (32 - r)))+#endif+++static U32 LZ4HC_rotatePattern(size_t const rotate, U32 const pattern)+{+ size_t const bitsToRotate = (rotate & (sizeof(pattern) - 1)) << 3;+ if (bitsToRotate == 0) return pattern;+ return LZ4HC_rotl32(pattern, (int)bitsToRotate);+}++/* LZ4HC_countPattern() :+ * pattern32 must be a sample of repetitive pattern of length 1, 2 or 4 (but not 3!) */+static unsigned+LZ4HC_countPattern(const BYTE* ip, const BYTE* const iEnd, U32 const pattern32)+{+ const BYTE* const iStart = ip;+ reg_t const pattern = (sizeof(pattern)==8) ?+ (reg_t)pattern32 + (((reg_t)pattern32) << (sizeof(pattern)*4)) : pattern32;++ while (likely(ip < iEnd-(sizeof(pattern)-1))) {+ reg_t const diff = LZ4_read_ARCH(ip) ^ pattern;+ if (!diff) { ip+=sizeof(pattern); continue; }+ ip += LZ4_NbCommonBytes(diff);+ return (unsigned)(ip - iStart);+ }++ if (LZ4_isLittleEndian()) {+ reg_t patternByte = pattern;+ while ((ip<iEnd) && (*ip == (BYTE)patternByte)) {+ ip++; patternByte >>= 8;+ }+ } else { /* big endian */+ U32 bitOffset = (sizeof(pattern)*8) - 8;+ while (ip < iEnd) {+ BYTE const byte = (BYTE)(pattern >> bitOffset);+ if (*ip != byte) break;+ ip ++; bitOffset -= 8;+ } }++ return (unsigned)(ip - iStart);+}++/* LZ4HC_reverseCountPattern() :+ * pattern must be a sample of repetitive pattern of length 1, 2 or 4 (but not 3!)+ * read using natural platform endianness */+static unsigned+LZ4HC_reverseCountPattern(const BYTE* ip, const BYTE* const iLow, U32 pattern)+{+ const BYTE* const iStart = ip;++ while (likely(ip >= iLow+4)) {+ if (LZ4_read32(ip-4) != pattern) break;+ ip -= 4;+ }+ { const BYTE* bytePtr = (const BYTE*)(&pattern) + 3; /* works for any endianness */+ while (likely(ip>iLow)) {+ if (ip[-1] != *bytePtr) break;+ ip--; bytePtr--;+ } }+ return (unsigned)(iStart - ip);+}++/* LZ4HC_protectDictEnd() :+ * Checks if the match is in the last 3 bytes of the dictionary, so reading the+ * 4 byte MINMATCH would overflow.+ * @returns true if the match index is okay.+ */+static int LZ4HC_protectDictEnd(U32 const dictLimit, U32 const matchIndex)+{+ return ((U32)((dictLimit - 1) - matchIndex) >= 3);+}++typedef enum { rep_untested, rep_not, rep_confirmed } repeat_state_e;+typedef enum { favorCompressionRatio=0, favorDecompressionSpeed } HCfavor_e;++LZ4_FORCE_INLINE int+LZ4HC_InsertAndGetWiderMatch (+ LZ4HC_CCtx_internal* const hc4,+ const BYTE* const ip,+ const BYTE* const iLowLimit, const BYTE* const iHighLimit,+ int longest,+ const BYTE** matchpos,+ const BYTE** startpos,+ const int maxNbAttempts,+ const int patternAnalysis, const int chainSwap,+ const dictCtx_directive dict,+ const HCfavor_e favorDecSpeed)+{+ U16* const chainTable = hc4->chainTable;+ U32* const HashTable = hc4->hashTable;+ const LZ4HC_CCtx_internal * const dictCtx = hc4->dictCtx;+ const BYTE* const prefixPtr = hc4->prefixStart;+ const U32 prefixIdx = hc4->dictLimit;+ const U32 ipIndex = (U32)(ip - prefixPtr) + prefixIdx;+ const int withinStartDistance = (hc4->lowLimit + (LZ4_DISTANCE_MAX + 1) > ipIndex);+ const U32 lowestMatchIndex = (withinStartDistance) ? hc4->lowLimit : ipIndex - LZ4_DISTANCE_MAX;+ const BYTE* const dictStart = hc4->dictStart;+ const U32 dictIdx = hc4->lowLimit;+ const BYTE* const dictEnd = dictStart + prefixIdx - dictIdx;+ int const lookBackLength = (int)(ip-iLowLimit);+ int nbAttempts = maxNbAttempts;+ U32 matchChainPos = 0;+ U32 const pattern = LZ4_read32(ip);+ U32 matchIndex;+ repeat_state_e repeat = rep_untested;+ size_t srcPatternLength = 0;++ DEBUGLOG(7, "LZ4HC_InsertAndGetWiderMatch");+ /* First Match */+ LZ4HC_Insert(hc4, ip);+ matchIndex = HashTable[LZ4HC_hashPtr(ip)];+ DEBUGLOG(7, "First match at index %u / %u (lowestMatchIndex)",+ matchIndex, lowestMatchIndex);++ while ((matchIndex>=lowestMatchIndex) && (nbAttempts>0)) {+ int matchLength=0;+ nbAttempts--;+ assert(matchIndex < ipIndex);+ if (favorDecSpeed && (ipIndex - matchIndex < 8)) {+ /* do nothing */+ } else if (matchIndex >= prefixIdx) { /* within current Prefix */+ const BYTE* const matchPtr = prefixPtr + matchIndex - prefixIdx;+ assert(matchPtr < ip);+ assert(longest >= 1);+ if (LZ4_read16(iLowLimit + longest - 1) == LZ4_read16(matchPtr - lookBackLength + longest - 1)) {+ if (LZ4_read32(matchPtr) == pattern) {+ int const back = lookBackLength ? LZ4HC_countBack(ip, matchPtr, iLowLimit, prefixPtr) : 0;+ matchLength = MINMATCH + (int)LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, iHighLimit);+ matchLength -= back;+ if (matchLength > longest) {+ longest = matchLength;+ *matchpos = matchPtr + back;+ *startpos = ip + back;+ } } }+ } else { /* lowestMatchIndex <= matchIndex < dictLimit */+ const BYTE* const matchPtr = dictStart + (matchIndex - dictIdx);+ assert(matchIndex >= dictIdx);+ if ( likely(matchIndex <= prefixIdx - 4)+ && (LZ4_read32(matchPtr) == pattern) ) {+ int back = 0;+ const BYTE* vLimit = ip + (prefixIdx - matchIndex);+ if (vLimit > iHighLimit) vLimit = iHighLimit;+ matchLength = (int)LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, vLimit) + MINMATCH;+ if ((ip+matchLength == vLimit) && (vLimit < iHighLimit))+ matchLength += LZ4_count(ip+matchLength, prefixPtr, iHighLimit);+ back = lookBackLength ? LZ4HC_countBack(ip, matchPtr, iLowLimit, dictStart) : 0;+ matchLength -= back;+ if (matchLength > longest) {+ longest = matchLength;+ *matchpos = prefixPtr - prefixIdx + matchIndex + back; /* virtual pos, relative to ip, to retrieve offset */+ *startpos = ip + back;+ } } }++ if (chainSwap && matchLength==longest) { /* better match => select a better chain */+ assert(lookBackLength==0); /* search forward only */+ if (matchIndex + (U32)longest <= ipIndex) {+ int const kTrigger = 4;+ U32 distanceToNextMatch = 1;+ int const end = longest - MINMATCH + 1;+ int step = 1;+ int accel = 1 << kTrigger;+ int pos;+ for (pos = 0; pos < end; pos += step) {+ U32 const candidateDist = DELTANEXTU16(chainTable, matchIndex + (U32)pos);+ step = (accel++ >> kTrigger);+ if (candidateDist > distanceToNextMatch) {+ distanceToNextMatch = candidateDist;+ matchChainPos = (U32)pos;+ accel = 1 << kTrigger;+ } }+ if (distanceToNextMatch > 1) {+ if (distanceToNextMatch > matchIndex) break; /* avoid overflow */+ matchIndex -= distanceToNextMatch;+ continue;+ } } }++ { U32 const distNextMatch = DELTANEXTU16(chainTable, matchIndex);+ if (patternAnalysis && distNextMatch==1 && matchChainPos==0) {+ U32 const matchCandidateIdx = matchIndex-1;+ /* may be a repeated pattern */+ if (repeat == rep_untested) {+ if ( ((pattern & 0xFFFF) == (pattern >> 16))+ & ((pattern & 0xFF) == (pattern >> 24)) ) {+ repeat = rep_confirmed;+ srcPatternLength = LZ4HC_countPattern(ip+sizeof(pattern), iHighLimit, pattern) + sizeof(pattern);+ } else {+ repeat = rep_not;+ } }+ if ( (repeat == rep_confirmed) && (matchCandidateIdx >= lowestMatchIndex)+ && LZ4HC_protectDictEnd(prefixIdx, matchCandidateIdx) ) {+ const int extDict = matchCandidateIdx < prefixIdx;+ const BYTE* const matchPtr = (extDict ? dictStart - dictIdx : prefixPtr - prefixIdx) + matchCandidateIdx;+ if (LZ4_read32(matchPtr) == pattern) { /* good candidate */+ const BYTE* const iLimit = extDict ? dictEnd : iHighLimit;+ size_t forwardPatternLength = LZ4HC_countPattern(matchPtr+sizeof(pattern), iLimit, pattern) + sizeof(pattern);+ if (extDict && matchPtr + forwardPatternLength == iLimit) {+ U32 const rotatedPattern = LZ4HC_rotatePattern(forwardPatternLength, pattern);+ forwardPatternLength += LZ4HC_countPattern(prefixPtr, iHighLimit, rotatedPattern);+ }+ { const BYTE* const lowestMatchPtr = extDict ? dictStart : prefixPtr;+ size_t backLength = LZ4HC_reverseCountPattern(matchPtr, lowestMatchPtr, pattern);+ size_t currentSegmentLength;+ if (!extDict+ && matchPtr - backLength == prefixPtr+ && dictIdx < prefixIdx) {+ U32 const rotatedPattern = LZ4HC_rotatePattern((U32)(-(int)backLength), pattern);+ backLength += LZ4HC_reverseCountPattern(dictEnd, dictStart, rotatedPattern);+ }+ /* Limit backLength not go further than lowestMatchIndex */+ backLength = matchCandidateIdx - MAX(matchCandidateIdx - (U32)backLength, lowestMatchIndex);+ assert(matchCandidateIdx - backLength >= lowestMatchIndex);+ currentSegmentLength = backLength + forwardPatternLength;+ /* Adjust to end of pattern if the source pattern fits, otherwise the beginning of the pattern */+ if ( (currentSegmentLength >= srcPatternLength) /* current pattern segment large enough to contain full srcPatternLength */+ && (forwardPatternLength <= srcPatternLength) ) { /* haven't reached this position yet */+ U32 const newMatchIndex = matchCandidateIdx + (U32)forwardPatternLength - (U32)srcPatternLength; /* best position, full pattern, might be followed by more match */+ if (LZ4HC_protectDictEnd(prefixIdx, newMatchIndex))+ matchIndex = newMatchIndex;+ else {+ /* Can only happen if started in the prefix */+ assert(newMatchIndex >= prefixIdx - 3 && newMatchIndex < prefixIdx && !extDict);+ matchIndex = prefixIdx;+ }+ } else {+ U32 const newMatchIndex = matchCandidateIdx - (U32)backLength; /* farthest position in current segment, will find a match of length currentSegmentLength + maybe some back */+ if (!LZ4HC_protectDictEnd(prefixIdx, newMatchIndex)) {+ assert(newMatchIndex >= prefixIdx - 3 && newMatchIndex < prefixIdx && !extDict);+ matchIndex = prefixIdx;+ } else {+ matchIndex = newMatchIndex;+ if (lookBackLength==0) { /* no back possible */+ size_t const maxML = MIN(currentSegmentLength, srcPatternLength);+ if ((size_t)longest < maxML) {+ assert(prefixPtr - prefixIdx + matchIndex != ip);+ if ((size_t)(ip - prefixPtr) + prefixIdx - matchIndex > LZ4_DISTANCE_MAX) break;+ assert(maxML < 2 GB);+ longest = (int)maxML;+ *matchpos = prefixPtr - prefixIdx + matchIndex; /* virtual pos, relative to ip, to retrieve offset */+ *startpos = ip;+ }+ { U32 const distToNextPattern = DELTANEXTU16(chainTable, matchIndex);+ if (distToNextPattern > matchIndex) break; /* avoid overflow */+ matchIndex -= distToNextPattern;+ } } } } }+ continue;+ } }+ } } /* PA optimization */++ /* follow current chain */+ matchIndex -= DELTANEXTU16(chainTable, matchIndex + matchChainPos);++ } /* while ((matchIndex>=lowestMatchIndex) && (nbAttempts)) */++ if ( dict == usingDictCtxHc+ && nbAttempts > 0+ && ipIndex - lowestMatchIndex < LZ4_DISTANCE_MAX) {+ size_t const dictEndOffset = (size_t)(dictCtx->end - dictCtx->prefixStart) + dictCtx->dictLimit;+ U32 dictMatchIndex = dictCtx->hashTable[LZ4HC_hashPtr(ip)];+ assert(dictEndOffset <= 1 GB);+ matchIndex = dictMatchIndex + lowestMatchIndex - (U32)dictEndOffset;+ while (ipIndex - matchIndex <= LZ4_DISTANCE_MAX && nbAttempts--) {+ const BYTE* const matchPtr = dictCtx->prefixStart - dictCtx->dictLimit + dictMatchIndex;++ if (LZ4_read32(matchPtr) == pattern) {+ int mlt;+ int back = 0;+ const BYTE* vLimit = ip + (dictEndOffset - dictMatchIndex);+ if (vLimit > iHighLimit) vLimit = iHighLimit;+ mlt = (int)LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, vLimit) + MINMATCH;+ back = lookBackLength ? LZ4HC_countBack(ip, matchPtr, iLowLimit, dictCtx->prefixStart) : 0;+ mlt -= back;+ if (mlt > longest) {+ longest = mlt;+ *matchpos = prefixPtr - prefixIdx + matchIndex + back;+ *startpos = ip + back;+ } }++ { U32 const nextOffset = DELTANEXTU16(dictCtx->chainTable, dictMatchIndex);+ dictMatchIndex -= nextOffset;+ matchIndex -= nextOffset;+ } } }++ return longest;+}++LZ4_FORCE_INLINE int+LZ4HC_InsertAndFindBestMatch(LZ4HC_CCtx_internal* const hc4, /* Index table will be updated */+ const BYTE* const ip, const BYTE* const iLimit,+ const BYTE** matchpos,+ const int maxNbAttempts,+ const int patternAnalysis,+ const dictCtx_directive dict)+{+ const BYTE* uselessPtr = ip;+ /* note : LZ4HC_InsertAndGetWiderMatch() is able to modify the starting position of a match (*startpos),+ * but this won't be the case here, as we define iLowLimit==ip,+ * so LZ4HC_InsertAndGetWiderMatch() won't be allowed to search past ip */+ return LZ4HC_InsertAndGetWiderMatch(hc4, ip, ip, iLimit, MINMATCH-1, matchpos, &uselessPtr, maxNbAttempts, patternAnalysis, 0 /*chainSwap*/, dict, favorCompressionRatio);+}++/* LZ4HC_encodeSequence() :+ * @return : 0 if ok,+ * 1 if buffer issue detected */+LZ4_FORCE_INLINE int LZ4HC_encodeSequence (+ const BYTE** _ip,+ BYTE** _op,+ const BYTE** _anchor,+ int matchLength,+ const BYTE* const match,+ limitedOutput_directive limit,+ BYTE* oend)+{+#define ip (*_ip)+#define op (*_op)+#define anchor (*_anchor)++ size_t length;+ BYTE* const token = op++;++#if defined(LZ4_DEBUG) && (LZ4_DEBUG >= 6)+ static const BYTE* start = NULL;+ static U32 totalCost = 0;+ U32 const pos = (start==NULL) ? 0 : (U32)(anchor - start);+ U32 const ll = (U32)(ip - anchor);+ U32 const llAdd = (ll>=15) ? ((ll-15) / 255) + 1 : 0;+ U32 const mlAdd = (matchLength>=19) ? ((matchLength-19) / 255) + 1 : 0;+ U32 const cost = 1 + llAdd + ll + 2 + mlAdd;+ if (start==NULL) start = anchor; /* only works for single segment */+ /* g_debuglog_enable = (pos >= 2228) & (pos <= 2262); */+ DEBUGLOG(6, "pos:%7u -- literals:%4u, match:%4i, offset:%5u, cost:%4u + %5u",+ pos,+ (U32)(ip - anchor), matchLength, (U32)(ip-match),+ cost, totalCost);+ totalCost += cost;+#endif++ /* Encode Literal length */+ length = (size_t)(ip - anchor);+ LZ4_STATIC_ASSERT(notLimited == 0);+ /* Check output limit */+ if (limit && ((op + (length / 255) + length + (2 + 1 + LASTLITERALS)) > oend)) {+ DEBUGLOG(6, "Not enough room to write %i literals (%i bytes remaining)",+ (int)length, (int)(oend - op));+ return 1;+ }+ if (length >= RUN_MASK) {+ size_t len = length - RUN_MASK;+ *token = (RUN_MASK << ML_BITS);+ for(; len >= 255 ; len -= 255) *op++ = 255;+ *op++ = (BYTE)len;+ } else {+ *token = (BYTE)(length << ML_BITS);+ }++ /* Copy Literals */+ LZ4_wildCopy8(op, anchor, op + length);+ op += length;++ /* Encode Offset */+ assert( (ip - match) <= LZ4_DISTANCE_MAX ); /* note : consider providing offset as a value, rather than as a pointer difference */+ LZ4_writeLE16(op, (U16)(ip - match)); op += 2;++ /* Encode MatchLength */+ assert(matchLength >= MINMATCH);+ length = (size_t)matchLength - MINMATCH;+ if (limit && (op + (length / 255) + (1 + LASTLITERALS) > oend)) {+ DEBUGLOG(6, "Not enough room to write match length");+ return 1; /* Check output limit */+ }+ if (length >= ML_MASK) {+ *token += ML_MASK;+ length -= ML_MASK;+ for(; length >= 510 ; length -= 510) { *op++ = 255; *op++ = 255; }+ if (length >= 255) { length -= 255; *op++ = 255; }+ *op++ = (BYTE)length;+ } else {+ *token += (BYTE)(length);+ }++ /* Prepare next loop */+ ip += matchLength;+ anchor = ip;++ return 0;+}+#undef ip+#undef op+#undef anchor++LZ4_FORCE_INLINE int LZ4HC_compress_hashChain (+ LZ4HC_CCtx_internal* const ctx,+ const char* const source,+ char* const dest,+ int* srcSizePtr,+ int const maxOutputSize,+ int maxNbAttempts,+ const limitedOutput_directive limit,+ const dictCtx_directive dict+ )+{+ const int inputSize = *srcSizePtr;+ const int patternAnalysis = (maxNbAttempts > 128); /* levels 9+ */++ const BYTE* ip = (const BYTE*) source;+ const BYTE* anchor = ip;+ const BYTE* const iend = ip + inputSize;+ const BYTE* const mflimit = iend - MFLIMIT;+ const BYTE* const matchlimit = (iend - LASTLITERALS);++ BYTE* optr = (BYTE*) dest;+ BYTE* op = (BYTE*) dest;+ BYTE* oend = op + maxOutputSize;++ int ml0, ml, ml2, ml3;+ const BYTE* start0;+ const BYTE* ref0;+ const BYTE* ref = NULL;+ const BYTE* start2 = NULL;+ const BYTE* ref2 = NULL;+ const BYTE* start3 = NULL;+ const BYTE* ref3 = NULL;++ /* init */+ *srcSizePtr = 0;+ if (limit == fillOutput) oend -= LASTLITERALS; /* Hack for support LZ4 format restriction */+ if (inputSize < LZ4_minLength) goto _last_literals; /* Input too small, no compression (all literals) */++ /* Main Loop */+ while (ip <= mflimit) {+ ml = LZ4HC_InsertAndFindBestMatch(ctx, ip, matchlimit, &ref, maxNbAttempts, patternAnalysis, dict);+ if (ml<MINMATCH) { ip++; continue; }++ /* saved, in case we would skip too much */+ start0 = ip; ref0 = ref; ml0 = ml;++_Search2:+ if (ip+ml <= mflimit) {+ ml2 = LZ4HC_InsertAndGetWiderMatch(ctx,+ ip + ml - 2, ip + 0, matchlimit, ml, &ref2, &start2,+ maxNbAttempts, patternAnalysis, 0, dict, favorCompressionRatio);+ } else {+ ml2 = ml;+ }++ if (ml2 == ml) { /* No better match => encode ML1 */+ optr = op;+ if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml, ref, limit, oend)) goto _dest_overflow;+ continue;+ }++ if (start0 < ip) { /* first match was skipped at least once */+ if (start2 < ip + ml0) { /* squeezing ML1 between ML0(original ML1) and ML2 */+ ip = start0; ref = ref0; ml = ml0; /* restore initial ML1 */+ } }++ /* Here, start0==ip */+ if ((start2 - ip) < 3) { /* First Match too small : removed */+ ml = ml2;+ ip = start2;+ ref =ref2;+ goto _Search2;+ }++_Search3:+ /* At this stage, we have :+ * ml2 > ml1, and+ * ip1+3 <= ip2 (usually < ip1+ml1) */+ if ((start2 - ip) < OPTIMAL_ML) {+ int correction;+ int new_ml = ml;+ if (new_ml > OPTIMAL_ML) new_ml = OPTIMAL_ML;+ if (ip+new_ml > start2 + ml2 - MINMATCH) new_ml = (int)(start2 - ip) + ml2 - MINMATCH;+ correction = new_ml - (int)(start2 - ip);+ if (correction > 0) {+ start2 += correction;+ ref2 += correction;+ ml2 -= correction;+ }+ }+ /* Now, we have start2 = ip+new_ml, with new_ml = min(ml, OPTIMAL_ML=18) */++ if (start2 + ml2 <= mflimit) {+ ml3 = LZ4HC_InsertAndGetWiderMatch(ctx,+ start2 + ml2 - 3, start2, matchlimit, ml2, &ref3, &start3,+ maxNbAttempts, patternAnalysis, 0, dict, favorCompressionRatio);+ } else {+ ml3 = ml2;+ }++ if (ml3 == ml2) { /* No better match => encode ML1 and ML2 */+ /* ip & ref are known; Now for ml */+ if (start2 < ip+ml) ml = (int)(start2 - ip);+ /* Now, encode 2 sequences */+ optr = op;+ if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml, ref, limit, oend)) goto _dest_overflow;+ ip = start2;+ optr = op;+ if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml2, ref2, limit, oend)) {+ ml = ml2;+ ref = ref2;+ goto _dest_overflow;+ }+ continue;+ }++ if (start3 < ip+ml+3) { /* Not enough space for match 2 : remove it */+ if (start3 >= (ip+ml)) { /* can write Seq1 immediately ==> Seq2 is removed, so Seq3 becomes Seq1 */+ if (start2 < ip+ml) {+ int correction = (int)(ip+ml - start2);+ start2 += correction;+ ref2 += correction;+ ml2 -= correction;+ if (ml2 < MINMATCH) {+ start2 = start3;+ ref2 = ref3;+ ml2 = ml3;+ }+ }++ optr = op;+ if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml, ref, limit, oend)) goto _dest_overflow;+ ip = start3;+ ref = ref3;+ ml = ml3;++ start0 = start2;+ ref0 = ref2;+ ml0 = ml2;+ goto _Search2;+ }++ start2 = start3;+ ref2 = ref3;+ ml2 = ml3;+ goto _Search3;+ }++ /*+ * OK, now we have 3 ascending matches;+ * let's write the first one ML1.+ * ip & ref are known; Now decide ml.+ */+ if (start2 < ip+ml) {+ if ((start2 - ip) < OPTIMAL_ML) {+ int correction;+ if (ml > OPTIMAL_ML) ml = OPTIMAL_ML;+ if (ip + ml > start2 + ml2 - MINMATCH) ml = (int)(start2 - ip) + ml2 - MINMATCH;+ correction = ml - (int)(start2 - ip);+ if (correction > 0) {+ start2 += correction;+ ref2 += correction;+ ml2 -= correction;+ }+ } else {+ ml = (int)(start2 - ip);+ }+ }+ optr = op;+ if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml, ref, limit, oend)) goto _dest_overflow;++ /* ML2 becomes ML1 */+ ip = start2; ref = ref2; ml = ml2;++ /* ML3 becomes ML2 */+ start2 = start3; ref2 = ref3; ml2 = ml3;++ /* let's find a new ML3 */+ goto _Search3;+ }++_last_literals:+ /* Encode Last Literals */+ { size_t lastRunSize = (size_t)(iend - anchor); /* literals */+ size_t llAdd = (lastRunSize + 255 - RUN_MASK) / 255;+ size_t const totalSize = 1 + llAdd + lastRunSize;+ if (limit == fillOutput) oend += LASTLITERALS; /* restore correct value */+ if (limit && (op + totalSize > oend)) {+ if (limit == limitedOutput) return 0;+ /* adapt lastRunSize to fill 'dest' */+ lastRunSize = (size_t)(oend - op) - 1 /*token*/;+ llAdd = (lastRunSize + 256 - RUN_MASK) / 256;+ lastRunSize -= llAdd;+ }+ DEBUGLOG(6, "Final literal run : %i literals", (int)lastRunSize);+ ip = anchor + lastRunSize; /* can be != iend if limit==fillOutput */++ if (lastRunSize >= RUN_MASK) {+ size_t accumulator = lastRunSize - RUN_MASK;+ *op++ = (RUN_MASK << ML_BITS);+ for(; accumulator >= 255 ; accumulator -= 255) *op++ = 255;+ *op++ = (BYTE) accumulator;+ } else {+ *op++ = (BYTE)(lastRunSize << ML_BITS);+ }+ LZ4_memcpy(op, anchor, lastRunSize);+ op += lastRunSize;+ }++ /* End */+ *srcSizePtr = (int) (((const char*)ip) - source);+ return (int) (((char*)op)-dest);++_dest_overflow:+ if (limit == fillOutput) {+ /* Assumption : ip, anchor, ml and ref must be set correctly */+ size_t const ll = (size_t)(ip - anchor);+ size_t const ll_addbytes = (ll + 240) / 255;+ size_t const ll_totalCost = 1 + ll_addbytes + ll;+ BYTE* const maxLitPos = oend - 3; /* 2 for offset, 1 for token */+ DEBUGLOG(6, "Last sequence overflowing");+ op = optr; /* restore correct out pointer */+ if (op + ll_totalCost <= maxLitPos) {+ /* ll validated; now adjust match length */+ size_t const bytesLeftForMl = (size_t)(maxLitPos - (op+ll_totalCost));+ size_t const maxMlSize = MINMATCH + (ML_MASK-1) + (bytesLeftForMl * 255);+ assert(maxMlSize < INT_MAX); assert(ml >= 0);+ if ((size_t)ml > maxMlSize) ml = (int)maxMlSize;+ if ((oend + LASTLITERALS) - (op + ll_totalCost + 2) - 1 + ml >= MFLIMIT) {+ LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml, ref, notLimited, oend);+ } }+ goto _last_literals;+ }+ /* compression failed */+ return 0;+}+++static int LZ4HC_compress_optimal( LZ4HC_CCtx_internal* ctx,+ const char* const source, char* dst,+ int* srcSizePtr, int dstCapacity,+ int const nbSearches, size_t sufficient_len,+ const limitedOutput_directive limit, int const fullUpdate,+ const dictCtx_directive dict,+ const HCfavor_e favorDecSpeed);+++LZ4_FORCE_INLINE int LZ4HC_compress_generic_internal (+ LZ4HC_CCtx_internal* const ctx,+ const char* const src,+ char* const dst,+ int* const srcSizePtr,+ int const dstCapacity,+ int cLevel,+ const limitedOutput_directive limit,+ const dictCtx_directive dict+ )+{+ typedef enum { lz4hc, lz4opt } lz4hc_strat_e;+ typedef struct {+ lz4hc_strat_e strat;+ int nbSearches;+ U32 targetLength;+ } cParams_t;+ static const cParams_t clTable[LZ4HC_CLEVEL_MAX+1] = {+ { lz4hc, 2, 16 }, /* 0, unused */+ { lz4hc, 2, 16 }, /* 1, unused */+ { lz4hc, 2, 16 }, /* 2, unused */+ { lz4hc, 4, 16 }, /* 3 */+ { lz4hc, 8, 16 }, /* 4 */+ { lz4hc, 16, 16 }, /* 5 */+ { lz4hc, 32, 16 }, /* 6 */+ { lz4hc, 64, 16 }, /* 7 */+ { lz4hc, 128, 16 }, /* 8 */+ { lz4hc, 256, 16 }, /* 9 */+ { lz4opt, 96, 64 }, /*10==LZ4HC_CLEVEL_OPT_MIN*/+ { lz4opt, 512,128 }, /*11 */+ { lz4opt,16384,LZ4_OPT_NUM }, /* 12==LZ4HC_CLEVEL_MAX */+ };++ DEBUGLOG(4, "LZ4HC_compress_generic(ctx=%p, src=%p, srcSize=%d, limit=%d)",+ ctx, src, *srcSizePtr, limit);++ if (limit == fillOutput && dstCapacity < 1) return 0; /* Impossible to store anything */+ if ((U32)*srcSizePtr > (U32)LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported input size (too large or negative) */++ ctx->end += *srcSizePtr;+ if (cLevel < 1) cLevel = LZ4HC_CLEVEL_DEFAULT; /* note : convention is different from lz4frame, maybe something to review */+ cLevel = MIN(LZ4HC_CLEVEL_MAX, cLevel);+ { cParams_t const cParam = clTable[cLevel];+ HCfavor_e const favor = ctx->favorDecSpeed ? favorDecompressionSpeed : favorCompressionRatio;+ int result;++ if (cParam.strat == lz4hc) {+ result = LZ4HC_compress_hashChain(ctx,+ src, dst, srcSizePtr, dstCapacity,+ cParam.nbSearches, limit, dict);+ } else {+ assert(cParam.strat == lz4opt);+ result = LZ4HC_compress_optimal(ctx,+ src, dst, srcSizePtr, dstCapacity,+ cParam.nbSearches, cParam.targetLength, limit,+ cLevel == LZ4HC_CLEVEL_MAX, /* ultra mode */+ dict, favor);+ }+ if (result <= 0) ctx->dirty = 1;+ return result;+ }+}++static void LZ4HC_setExternalDict(LZ4HC_CCtx_internal* ctxPtr, const BYTE* newBlock);++static int+LZ4HC_compress_generic_noDictCtx (+ LZ4HC_CCtx_internal* const ctx,+ const char* const src,+ char* const dst,+ int* const srcSizePtr,+ int const dstCapacity,+ int cLevel,+ limitedOutput_directive limit+ )+{+ assert(ctx->dictCtx == NULL);+ return LZ4HC_compress_generic_internal(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit, noDictCtx);+}++static int+LZ4HC_compress_generic_dictCtx (+ LZ4HC_CCtx_internal* const ctx,+ const char* const src,+ char* const dst,+ int* const srcSizePtr,+ int const dstCapacity,+ int cLevel,+ limitedOutput_directive limit+ )+{+ const size_t position = (size_t)(ctx->end - ctx->prefixStart) + (ctx->dictLimit - ctx->lowLimit);+ assert(ctx->dictCtx != NULL);+ if (position >= 64 KB) {+ ctx->dictCtx = NULL;+ return LZ4HC_compress_generic_noDictCtx(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit);+ } else if (position == 0 && *srcSizePtr > 4 KB) {+ LZ4_memcpy(ctx, ctx->dictCtx, sizeof(LZ4HC_CCtx_internal));+ LZ4HC_setExternalDict(ctx, (const BYTE *)src);+ ctx->compressionLevel = (short)cLevel;+ return LZ4HC_compress_generic_noDictCtx(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit);+ } else {+ return LZ4HC_compress_generic_internal(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit, usingDictCtxHc);+ }+}++static int+LZ4HC_compress_generic (+ LZ4HC_CCtx_internal* const ctx,+ const char* const src,+ char* const dst,+ int* const srcSizePtr,+ int const dstCapacity,+ int cLevel,+ limitedOutput_directive limit+ )+{+ if (ctx->dictCtx == NULL) {+ return LZ4HC_compress_generic_noDictCtx(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit);+ } else {+ return LZ4HC_compress_generic_dictCtx(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit);+ }+}+++int LZ4_sizeofStateHC(void) { return (int)sizeof(LZ4_streamHC_t); }++static size_t LZ4_streamHC_t_alignment(void)+{+#if LZ4_ALIGN_TEST+ typedef struct { char c; LZ4_streamHC_t t; } t_a;+ return sizeof(t_a) - sizeof(LZ4_streamHC_t);+#else+ return 1; /* effectively disabled */+#endif+}++/* state is presumed correctly initialized,+ * in which case its size and alignment have already been validate */+int LZ4_compress_HC_extStateHC_fastReset (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int compressionLevel)+{+ LZ4HC_CCtx_internal* const ctx = &((LZ4_streamHC_t*)state)->internal_donotuse;+ if (!LZ4_isAligned(state, LZ4_streamHC_t_alignment())) return 0;+ LZ4_resetStreamHC_fast((LZ4_streamHC_t*)state, compressionLevel);+ LZ4HC_init_internal (ctx, (const BYTE*)src);+ if (dstCapacity < LZ4_compressBound(srcSize))+ return LZ4HC_compress_generic (ctx, src, dst, &srcSize, dstCapacity, compressionLevel, limitedOutput);+ else+ return LZ4HC_compress_generic (ctx, src, dst, &srcSize, dstCapacity, compressionLevel, notLimited);+}++int LZ4_compress_HC_extStateHC (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int compressionLevel)+{+ LZ4_streamHC_t* const ctx = LZ4_initStreamHC(state, sizeof(*ctx));+ if (ctx==NULL) return 0; /* init failure */+ return LZ4_compress_HC_extStateHC_fastReset(state, src, dst, srcSize, dstCapacity, compressionLevel);+}++int LZ4_compress_HC(const char* src, char* dst, int srcSize, int dstCapacity, int compressionLevel)+{+ int cSize;+#if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1+ LZ4_streamHC_t* const statePtr = (LZ4_streamHC_t*)ALLOC(sizeof(LZ4_streamHC_t));+ if (statePtr==NULL) return 0;+#else+ LZ4_streamHC_t state;+ LZ4_streamHC_t* const statePtr = &state;+#endif+ cSize = LZ4_compress_HC_extStateHC(statePtr, src, dst, srcSize, dstCapacity, compressionLevel);+#if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1+ FREEMEM(statePtr);+#endif+ return cSize;+}++/* state is presumed sized correctly (>= sizeof(LZ4_streamHC_t)) */+int LZ4_compress_HC_destSize(void* state, const char* source, char* dest, int* sourceSizePtr, int targetDestSize, int cLevel)+{+ LZ4_streamHC_t* const ctx = LZ4_initStreamHC(state, sizeof(*ctx));+ if (ctx==NULL) return 0; /* init failure */+ LZ4HC_init_internal(&ctx->internal_donotuse, (const BYTE*) source);+ LZ4_setCompressionLevel(ctx, cLevel);+ return LZ4HC_compress_generic(&ctx->internal_donotuse, source, dest, sourceSizePtr, targetDestSize, cLevel, fillOutput);+}++++/**************************************+* Streaming Functions+**************************************/+/* allocation */+#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)+LZ4_streamHC_t* LZ4_createStreamHC(void)+{+ LZ4_streamHC_t* const state =+ (LZ4_streamHC_t*)ALLOC_AND_ZERO(sizeof(LZ4_streamHC_t));+ if (state == NULL) return NULL;+ LZ4_setCompressionLevel(state, LZ4HC_CLEVEL_DEFAULT);+ return state;+}++int LZ4_freeStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr)+{+ DEBUGLOG(4, "LZ4_freeStreamHC(%p)", LZ4_streamHCPtr);+ if (!LZ4_streamHCPtr) return 0; /* support free on NULL */+ FREEMEM(LZ4_streamHCPtr);+ return 0;+}+#endif+++LZ4_streamHC_t* LZ4_initStreamHC (void* buffer, size_t size)+{+ LZ4_streamHC_t* const LZ4_streamHCPtr = (LZ4_streamHC_t*)buffer;+ DEBUGLOG(4, "LZ4_initStreamHC(%p, %u)", buffer, (unsigned)size);+ /* check conditions */+ if (buffer == NULL) return NULL;+ if (size < sizeof(LZ4_streamHC_t)) return NULL;+ if (!LZ4_isAligned(buffer, LZ4_streamHC_t_alignment())) return NULL;+ /* init */+ { LZ4HC_CCtx_internal* const hcstate = &(LZ4_streamHCPtr->internal_donotuse);+ MEM_INIT(hcstate, 0, sizeof(*hcstate)); }+ LZ4_setCompressionLevel(LZ4_streamHCPtr, LZ4HC_CLEVEL_DEFAULT);+ return LZ4_streamHCPtr;+}++/* just a stub */+void LZ4_resetStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel)+{+ LZ4_initStreamHC(LZ4_streamHCPtr, sizeof(*LZ4_streamHCPtr));+ LZ4_setCompressionLevel(LZ4_streamHCPtr, compressionLevel);+}++void LZ4_resetStreamHC_fast (LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel)+{+ DEBUGLOG(4, "LZ4_resetStreamHC_fast(%p, %d)", LZ4_streamHCPtr, compressionLevel);+ if (LZ4_streamHCPtr->internal_donotuse.dirty) {+ LZ4_initStreamHC(LZ4_streamHCPtr, sizeof(*LZ4_streamHCPtr));+ } else {+ /* preserve end - prefixStart : can trigger clearTable's threshold */+ if (LZ4_streamHCPtr->internal_donotuse.end != NULL) {+ LZ4_streamHCPtr->internal_donotuse.end -= (uptrval)LZ4_streamHCPtr->internal_donotuse.prefixStart;+ } else {+ assert(LZ4_streamHCPtr->internal_donotuse.prefixStart == NULL);+ }+ LZ4_streamHCPtr->internal_donotuse.prefixStart = NULL;+ LZ4_streamHCPtr->internal_donotuse.dictCtx = NULL;+ }+ LZ4_setCompressionLevel(LZ4_streamHCPtr, compressionLevel);+}++void LZ4_setCompressionLevel(LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel)+{+ DEBUGLOG(5, "LZ4_setCompressionLevel(%p, %d)", LZ4_streamHCPtr, compressionLevel);+ if (compressionLevel < 1) compressionLevel = LZ4HC_CLEVEL_DEFAULT;+ if (compressionLevel > LZ4HC_CLEVEL_MAX) compressionLevel = LZ4HC_CLEVEL_MAX;+ LZ4_streamHCPtr->internal_donotuse.compressionLevel = (short)compressionLevel;+}++void LZ4_favorDecompressionSpeed(LZ4_streamHC_t* LZ4_streamHCPtr, int favor)+{+ LZ4_streamHCPtr->internal_donotuse.favorDecSpeed = (favor!=0);+}++/* LZ4_loadDictHC() :+ * LZ4_streamHCPtr is presumed properly initialized */+int LZ4_loadDictHC (LZ4_streamHC_t* LZ4_streamHCPtr,+ const char* dictionary, int dictSize)+{+ LZ4HC_CCtx_internal* const ctxPtr = &LZ4_streamHCPtr->internal_donotuse;+ DEBUGLOG(4, "LZ4_loadDictHC(ctx:%p, dict:%p, dictSize:%d)", LZ4_streamHCPtr, dictionary, dictSize);+ assert(LZ4_streamHCPtr != NULL);+ if (dictSize > 64 KB) {+ dictionary += (size_t)dictSize - 64 KB;+ dictSize = 64 KB;+ }+ /* need a full initialization, there are bad side-effects when using resetFast() */+ { int const cLevel = ctxPtr->compressionLevel;+ LZ4_initStreamHC(LZ4_streamHCPtr, sizeof(*LZ4_streamHCPtr));+ LZ4_setCompressionLevel(LZ4_streamHCPtr, cLevel);+ }+ LZ4HC_init_internal (ctxPtr, (const BYTE*)dictionary);+ ctxPtr->end = (const BYTE*)dictionary + dictSize;+ if (dictSize >= 4) LZ4HC_Insert (ctxPtr, ctxPtr->end-3);+ return dictSize;+}++void LZ4_attach_HC_dictionary(LZ4_streamHC_t *working_stream, const LZ4_streamHC_t *dictionary_stream) {+ working_stream->internal_donotuse.dictCtx = dictionary_stream != NULL ? &(dictionary_stream->internal_donotuse) : NULL;+}++/* compression */++static void LZ4HC_setExternalDict(LZ4HC_CCtx_internal* ctxPtr, const BYTE* newBlock)+{+ DEBUGLOG(4, "LZ4HC_setExternalDict(%p, %p)", ctxPtr, newBlock);+ if (ctxPtr->end >= ctxPtr->prefixStart + 4)+ LZ4HC_Insert (ctxPtr, ctxPtr->end-3); /* Referencing remaining dictionary content */++ /* Only one memory segment for extDict, so any previous extDict is lost at this stage */+ ctxPtr->lowLimit = ctxPtr->dictLimit;+ ctxPtr->dictStart = ctxPtr->prefixStart;+ ctxPtr->dictLimit += (U32)(ctxPtr->end - ctxPtr->prefixStart);+ ctxPtr->prefixStart = newBlock;+ ctxPtr->end = newBlock;+ ctxPtr->nextToUpdate = ctxPtr->dictLimit; /* match referencing will resume from there */++ /* cannot reference an extDict and a dictCtx at the same time */+ ctxPtr->dictCtx = NULL;+}++static int+LZ4_compressHC_continue_generic (LZ4_streamHC_t* LZ4_streamHCPtr,+ const char* src, char* dst,+ int* srcSizePtr, int dstCapacity,+ limitedOutput_directive limit)+{+ LZ4HC_CCtx_internal* const ctxPtr = &LZ4_streamHCPtr->internal_donotuse;+ DEBUGLOG(5, "LZ4_compressHC_continue_generic(ctx=%p, src=%p, srcSize=%d, limit=%d)",+ LZ4_streamHCPtr, src, *srcSizePtr, limit);+ assert(ctxPtr != NULL);+ /* auto-init if forgotten */+ if (ctxPtr->prefixStart == NULL) LZ4HC_init_internal (ctxPtr, (const BYTE*) src);++ /* Check overflow */+ if ((size_t)(ctxPtr->end - ctxPtr->prefixStart) + ctxPtr->dictLimit > 2 GB) {+ size_t dictSize = (size_t)(ctxPtr->end - ctxPtr->prefixStart);+ if (dictSize > 64 KB) dictSize = 64 KB;+ LZ4_loadDictHC(LZ4_streamHCPtr, (const char*)(ctxPtr->end) - dictSize, (int)dictSize);+ }++ /* Check if blocks follow each other */+ if ((const BYTE*)src != ctxPtr->end)+ LZ4HC_setExternalDict(ctxPtr, (const BYTE*)src);++ /* Check overlapping input/dictionary space */+ { const BYTE* sourceEnd = (const BYTE*) src + *srcSizePtr;+ const BYTE* const dictBegin = ctxPtr->dictStart;+ const BYTE* const dictEnd = ctxPtr->dictStart + (ctxPtr->dictLimit - ctxPtr->lowLimit);+ if ((sourceEnd > dictBegin) && ((const BYTE*)src < dictEnd)) {+ if (sourceEnd > dictEnd) sourceEnd = dictEnd;+ ctxPtr->lowLimit += (U32)(sourceEnd - ctxPtr->dictStart);+ ctxPtr->dictStart += (U32)(sourceEnd - ctxPtr->dictStart);+ if (ctxPtr->dictLimit - ctxPtr->lowLimit < 4) {+ ctxPtr->lowLimit = ctxPtr->dictLimit;+ ctxPtr->dictStart = ctxPtr->prefixStart;+ } } }++ return LZ4HC_compress_generic (ctxPtr, src, dst, srcSizePtr, dstCapacity, ctxPtr->compressionLevel, limit);+}++int LZ4_compress_HC_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* src, char* dst, int srcSize, int dstCapacity)+{+ if (dstCapacity < LZ4_compressBound(srcSize))+ return LZ4_compressHC_continue_generic (LZ4_streamHCPtr, src, dst, &srcSize, dstCapacity, limitedOutput);+ else+ return LZ4_compressHC_continue_generic (LZ4_streamHCPtr, src, dst, &srcSize, dstCapacity, notLimited);+}++int LZ4_compress_HC_continue_destSize (LZ4_streamHC_t* LZ4_streamHCPtr, const char* src, char* dst, int* srcSizePtr, int targetDestSize)+{+ return LZ4_compressHC_continue_generic(LZ4_streamHCPtr, src, dst, srcSizePtr, targetDestSize, fillOutput);+}++++/* LZ4_saveDictHC :+ * save history content+ * into a user-provided buffer+ * which is then used to continue compression+ */+int LZ4_saveDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, char* safeBuffer, int dictSize)+{+ LZ4HC_CCtx_internal* const streamPtr = &LZ4_streamHCPtr->internal_donotuse;+ int const prefixSize = (int)(streamPtr->end - streamPtr->prefixStart);+ DEBUGLOG(5, "LZ4_saveDictHC(%p, %p, %d)", LZ4_streamHCPtr, safeBuffer, dictSize);+ assert(prefixSize >= 0);+ if (dictSize > 64 KB) dictSize = 64 KB;+ if (dictSize < 4) dictSize = 0;+ if (dictSize > prefixSize) dictSize = prefixSize;+ if (safeBuffer == NULL) assert(dictSize == 0);+ if (dictSize > 0)+ LZ4_memmove(safeBuffer, streamPtr->end - dictSize, dictSize);+ { U32 const endIndex = (U32)(streamPtr->end - streamPtr->prefixStart) + streamPtr->dictLimit;+ streamPtr->end = (const BYTE*)safeBuffer + dictSize;+ streamPtr->prefixStart = streamPtr->end - dictSize;+ streamPtr->dictLimit = endIndex - (U32)dictSize;+ streamPtr->lowLimit = endIndex - (U32)dictSize;+ streamPtr->dictStart = streamPtr->prefixStart;+ if (streamPtr->nextToUpdate < streamPtr->dictLimit)+ streamPtr->nextToUpdate = streamPtr->dictLimit;+ }+ return dictSize;+}+++/***************************************************+* Deprecated Functions+***************************************************/++/* These functions currently generate deprecation warnings */++/* Wrappers for deprecated compression functions */+int LZ4_compressHC(const char* src, char* dst, int srcSize) { return LZ4_compress_HC (src, dst, srcSize, LZ4_compressBound(srcSize), 0); }+int LZ4_compressHC_limitedOutput(const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC(src, dst, srcSize, maxDstSize, 0); }+int LZ4_compressHC2(const char* src, char* dst, int srcSize, int cLevel) { return LZ4_compress_HC (src, dst, srcSize, LZ4_compressBound(srcSize), cLevel); }+int LZ4_compressHC2_limitedOutput(const char* src, char* dst, int srcSize, int maxDstSize, int cLevel) { return LZ4_compress_HC(src, dst, srcSize, maxDstSize, cLevel); }+int LZ4_compressHC_withStateHC (void* state, const char* src, char* dst, int srcSize) { return LZ4_compress_HC_extStateHC (state, src, dst, srcSize, LZ4_compressBound(srcSize), 0); }+int LZ4_compressHC_limitedOutput_withStateHC (void* state, const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC_extStateHC (state, src, dst, srcSize, maxDstSize, 0); }+int LZ4_compressHC2_withStateHC (void* state, const char* src, char* dst, int srcSize, int cLevel) { return LZ4_compress_HC_extStateHC(state, src, dst, srcSize, LZ4_compressBound(srcSize), cLevel); }+int LZ4_compressHC2_limitedOutput_withStateHC (void* state, const char* src, char* dst, int srcSize, int maxDstSize, int cLevel) { return LZ4_compress_HC_extStateHC(state, src, dst, srcSize, maxDstSize, cLevel); }+int LZ4_compressHC_continue (LZ4_streamHC_t* ctx, const char* src, char* dst, int srcSize) { return LZ4_compress_HC_continue (ctx, src, dst, srcSize, LZ4_compressBound(srcSize)); }+int LZ4_compressHC_limitedOutput_continue (LZ4_streamHC_t* ctx, const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC_continue (ctx, src, dst, srcSize, maxDstSize); }+++/* Deprecated streaming functions */+int LZ4_sizeofStreamStateHC(void) { return sizeof(LZ4_streamHC_t); }++/* state is presumed correctly sized, aka >= sizeof(LZ4_streamHC_t)+ * @return : 0 on success, !=0 if error */+int LZ4_resetStreamStateHC(void* state, char* inputBuffer)+{+ LZ4_streamHC_t* const hc4 = LZ4_initStreamHC(state, sizeof(*hc4));+ if (hc4 == NULL) return 1; /* init failed */+ LZ4HC_init_internal (&hc4->internal_donotuse, (const BYTE*)inputBuffer);+ return 0;+}++#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)+void* LZ4_createHC (const char* inputBuffer)+{+ LZ4_streamHC_t* const hc4 = LZ4_createStreamHC();+ if (hc4 == NULL) return NULL; /* not enough memory */+ LZ4HC_init_internal (&hc4->internal_donotuse, (const BYTE*)inputBuffer);+ return hc4;+}++int LZ4_freeHC (void* LZ4HC_Data)+{+ if (!LZ4HC_Data) return 0; /* support free on NULL */+ FREEMEM(LZ4HC_Data);+ return 0;+}+#endif++int LZ4_compressHC2_continue (void* LZ4HC_Data, const char* src, char* dst, int srcSize, int cLevel)+{+ return LZ4HC_compress_generic (&((LZ4_streamHC_t*)LZ4HC_Data)->internal_donotuse, src, dst, &srcSize, 0, cLevel, notLimited);+}++int LZ4_compressHC2_limitedOutput_continue (void* LZ4HC_Data, const char* src, char* dst, int srcSize, int dstCapacity, int cLevel)+{+ return LZ4HC_compress_generic (&((LZ4_streamHC_t*)LZ4HC_Data)->internal_donotuse, src, dst, &srcSize, dstCapacity, cLevel, limitedOutput);+}++char* LZ4_slideInputBufferHC(void* LZ4HC_Data)+{+ LZ4_streamHC_t* const ctx = (LZ4_streamHC_t*)LZ4HC_Data;+ const BYTE* bufferStart = ctx->internal_donotuse.prefixStart - ctx->internal_donotuse.dictLimit + ctx->internal_donotuse.lowLimit;+ LZ4_resetStreamHC_fast(ctx, ctx->internal_donotuse.compressionLevel);+ /* avoid const char * -> char * conversion warning :( */+ return (char*)(uptrval)bufferStart;+}+++/* ================================================+ * LZ4 Optimal parser (levels [LZ4HC_CLEVEL_OPT_MIN - LZ4HC_CLEVEL_MAX])+ * ===============================================*/+typedef struct {+ int price;+ int off;+ int mlen;+ int litlen;+} LZ4HC_optimal_t;++/* price in bytes */+LZ4_FORCE_INLINE int LZ4HC_literalsPrice(int const litlen)+{+ int price = litlen;+ assert(litlen >= 0);+ if (litlen >= (int)RUN_MASK)+ price += 1 + ((litlen-(int)RUN_MASK) / 255);+ return price;+}+++/* requires mlen >= MINMATCH */+LZ4_FORCE_INLINE int LZ4HC_sequencePrice(int litlen, int mlen)+{+ int price = 1 + 2 ; /* token + 16-bit offset */+ assert(litlen >= 0);+ assert(mlen >= MINMATCH);++ price += LZ4HC_literalsPrice(litlen);++ if (mlen >= (int)(ML_MASK+MINMATCH))+ price += 1 + ((mlen-(int)(ML_MASK+MINMATCH)) / 255);++ return price;+}+++typedef struct {+ int off;+ int len;+} LZ4HC_match_t;++LZ4_FORCE_INLINE LZ4HC_match_t+LZ4HC_FindLongerMatch(LZ4HC_CCtx_internal* const ctx,+ const BYTE* ip, const BYTE* const iHighLimit,+ int minLen, int nbSearches,+ const dictCtx_directive dict,+ const HCfavor_e favorDecSpeed)+{+ LZ4HC_match_t match = { 0 , 0 };+ const BYTE* matchPtr = NULL;+ /* note : LZ4HC_InsertAndGetWiderMatch() is able to modify the starting position of a match (*startpos),+ * but this won't be the case here, as we define iLowLimit==ip,+ * so LZ4HC_InsertAndGetWiderMatch() won't be allowed to search past ip */+ int matchLength = LZ4HC_InsertAndGetWiderMatch(ctx, ip, ip, iHighLimit, minLen, &matchPtr, &ip, nbSearches, 1 /*patternAnalysis*/, 1 /*chainSwap*/, dict, favorDecSpeed);+ if (matchLength <= minLen) return match;+ if (favorDecSpeed) {+ if ((matchLength>18) & (matchLength<=36)) matchLength=18; /* favor shortcut */+ }+ match.len = matchLength;+ match.off = (int)(ip-matchPtr);+ return match;+}+++static int LZ4HC_compress_optimal ( LZ4HC_CCtx_internal* ctx,+ const char* const source,+ char* dst,+ int* srcSizePtr,+ int dstCapacity,+ int const nbSearches,+ size_t sufficient_len,+ const limitedOutput_directive limit,+ int const fullUpdate,+ const dictCtx_directive dict,+ const HCfavor_e favorDecSpeed)+{+ int retval = 0;+#define TRAILING_LITERALS 3+#if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1+ LZ4HC_optimal_t* const opt = (LZ4HC_optimal_t*)ALLOC(sizeof(LZ4HC_optimal_t) * (LZ4_OPT_NUM + TRAILING_LITERALS));+#else+ LZ4HC_optimal_t opt[LZ4_OPT_NUM + TRAILING_LITERALS]; /* ~64 KB, which is a bit large for stack... */+#endif++ const BYTE* ip = (const BYTE*) source;+ const BYTE* anchor = ip;+ const BYTE* const iend = ip + *srcSizePtr;+ const BYTE* const mflimit = iend - MFLIMIT;+ const BYTE* const matchlimit = iend - LASTLITERALS;+ BYTE* op = (BYTE*) dst;+ BYTE* opSaved = (BYTE*) dst;+ BYTE* oend = op + dstCapacity;+ int ovml = MINMATCH; /* overflow - last sequence */+ const BYTE* ovref = NULL;++ /* init */+#if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1+ if (opt == NULL) goto _return_label;+#endif+ DEBUGLOG(5, "LZ4HC_compress_optimal(dst=%p, dstCapa=%u)", dst, (unsigned)dstCapacity);+ *srcSizePtr = 0;+ if (limit == fillOutput) oend -= LASTLITERALS; /* Hack for support LZ4 format restriction */+ if (sufficient_len >= LZ4_OPT_NUM) sufficient_len = LZ4_OPT_NUM-1;++ /* Main Loop */+ while (ip <= mflimit) {+ int const llen = (int)(ip - anchor);+ int best_mlen, best_off;+ int cur, last_match_pos = 0;++ LZ4HC_match_t const firstMatch = LZ4HC_FindLongerMatch(ctx, ip, matchlimit, MINMATCH-1, nbSearches, dict, favorDecSpeed);+ if (firstMatch.len==0) { ip++; continue; }++ if ((size_t)firstMatch.len > sufficient_len) {+ /* good enough solution : immediate encoding */+ int const firstML = firstMatch.len;+ const BYTE* const matchPos = ip - firstMatch.off;+ opSaved = op;+ if ( LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), firstML, matchPos, limit, oend) ) { /* updates ip, op and anchor */+ ovml = firstML;+ ovref = matchPos;+ goto _dest_overflow;+ }+ continue;+ }++ /* set prices for first positions (literals) */+ { int rPos;+ for (rPos = 0 ; rPos < MINMATCH ; rPos++) {+ int const cost = LZ4HC_literalsPrice(llen + rPos);+ opt[rPos].mlen = 1;+ opt[rPos].off = 0;+ opt[rPos].litlen = llen + rPos;+ opt[rPos].price = cost;+ DEBUGLOG(7, "rPos:%3i => price:%3i (litlen=%i) -- initial setup",+ rPos, cost, opt[rPos].litlen);+ } }+ /* set prices using initial match */+ { int mlen = MINMATCH;+ int const matchML = firstMatch.len; /* necessarily < sufficient_len < LZ4_OPT_NUM */+ int const offset = firstMatch.off;+ assert(matchML < LZ4_OPT_NUM);+ for ( ; mlen <= matchML ; mlen++) {+ int const cost = LZ4HC_sequencePrice(llen, mlen);+ opt[mlen].mlen = mlen;+ opt[mlen].off = offset;+ opt[mlen].litlen = llen;+ opt[mlen].price = cost;+ DEBUGLOG(7, "rPos:%3i => price:%3i (matchlen=%i) -- initial setup",+ mlen, cost, mlen);+ } }+ last_match_pos = firstMatch.len;+ { int addLit;+ for (addLit = 1; addLit <= TRAILING_LITERALS; addLit ++) {+ opt[last_match_pos+addLit].mlen = 1; /* literal */+ opt[last_match_pos+addLit].off = 0;+ opt[last_match_pos+addLit].litlen = addLit;+ opt[last_match_pos+addLit].price = opt[last_match_pos].price + LZ4HC_literalsPrice(addLit);+ DEBUGLOG(7, "rPos:%3i => price:%3i (litlen=%i) -- initial setup",+ last_match_pos+addLit, opt[last_match_pos+addLit].price, addLit);+ } }++ /* check further positions */+ for (cur = 1; cur < last_match_pos; cur++) {+ const BYTE* const curPtr = ip + cur;+ LZ4HC_match_t newMatch;++ if (curPtr > mflimit) break;+ DEBUGLOG(7, "rPos:%u[%u] vs [%u]%u",+ cur, opt[cur].price, opt[cur+1].price, cur+1);+ if (fullUpdate) {+ /* not useful to search here if next position has same (or lower) cost */+ if ( (opt[cur+1].price <= opt[cur].price)+ /* in some cases, next position has same cost, but cost rises sharply after, so a small match would still be beneficial */+ && (opt[cur+MINMATCH].price < opt[cur].price + 3/*min seq price*/) )+ continue;+ } else {+ /* not useful to search here if next position has same (or lower) cost */+ if (opt[cur+1].price <= opt[cur].price) continue;+ }++ DEBUGLOG(7, "search at rPos:%u", cur);+ if (fullUpdate)+ newMatch = LZ4HC_FindLongerMatch(ctx, curPtr, matchlimit, MINMATCH-1, nbSearches, dict, favorDecSpeed);+ else+ /* only test matches of minimum length; slightly faster, but misses a few bytes */+ newMatch = LZ4HC_FindLongerMatch(ctx, curPtr, matchlimit, last_match_pos - cur, nbSearches, dict, favorDecSpeed);+ if (!newMatch.len) continue;++ if ( ((size_t)newMatch.len > sufficient_len)+ || (newMatch.len + cur >= LZ4_OPT_NUM) ) {+ /* immediate encoding */+ best_mlen = newMatch.len;+ best_off = newMatch.off;+ last_match_pos = cur + 1;+ goto encode;+ }++ /* before match : set price with literals at beginning */+ { int const baseLitlen = opt[cur].litlen;+ int litlen;+ for (litlen = 1; litlen < MINMATCH; litlen++) {+ int const price = opt[cur].price - LZ4HC_literalsPrice(baseLitlen) + LZ4HC_literalsPrice(baseLitlen+litlen);+ int const pos = cur + litlen;+ if (price < opt[pos].price) {+ opt[pos].mlen = 1; /* literal */+ opt[pos].off = 0;+ opt[pos].litlen = baseLitlen+litlen;+ opt[pos].price = price;+ DEBUGLOG(7, "rPos:%3i => price:%3i (litlen=%i)",+ pos, price, opt[pos].litlen);+ } } }++ /* set prices using match at position = cur */+ { int const matchML = newMatch.len;+ int ml = MINMATCH;++ assert(cur + newMatch.len < LZ4_OPT_NUM);+ for ( ; ml <= matchML ; ml++) {+ int const pos = cur + ml;+ int const offset = newMatch.off;+ int price;+ int ll;+ DEBUGLOG(7, "testing price rPos %i (last_match_pos=%i)",+ pos, last_match_pos);+ if (opt[cur].mlen == 1) {+ ll = opt[cur].litlen;+ price = ((cur > ll) ? opt[cur - ll].price : 0)+ + LZ4HC_sequencePrice(ll, ml);+ } else {+ ll = 0;+ price = opt[cur].price + LZ4HC_sequencePrice(0, ml);+ }++ assert((U32)favorDecSpeed <= 1);+ if (pos > last_match_pos+TRAILING_LITERALS+ || price <= opt[pos].price - (int)favorDecSpeed) {+ DEBUGLOG(7, "rPos:%3i => price:%3i (matchlen=%i)",+ pos, price, ml);+ assert(pos < LZ4_OPT_NUM);+ if ( (ml == matchML) /* last pos of last match */+ && (last_match_pos < pos) )+ last_match_pos = pos;+ opt[pos].mlen = ml;+ opt[pos].off = offset;+ opt[pos].litlen = ll;+ opt[pos].price = price;+ } } }+ /* complete following positions with literals */+ { int addLit;+ for (addLit = 1; addLit <= TRAILING_LITERALS; addLit ++) {+ opt[last_match_pos+addLit].mlen = 1; /* literal */+ opt[last_match_pos+addLit].off = 0;+ opt[last_match_pos+addLit].litlen = addLit;+ opt[last_match_pos+addLit].price = opt[last_match_pos].price + LZ4HC_literalsPrice(addLit);+ DEBUGLOG(7, "rPos:%3i => price:%3i (litlen=%i)", last_match_pos+addLit, opt[last_match_pos+addLit].price, addLit);+ } }+ } /* for (cur = 1; cur <= last_match_pos; cur++) */++ assert(last_match_pos < LZ4_OPT_NUM + TRAILING_LITERALS);+ best_mlen = opt[last_match_pos].mlen;+ best_off = opt[last_match_pos].off;+ cur = last_match_pos - best_mlen;++encode: /* cur, last_match_pos, best_mlen, best_off must be set */+ assert(cur < LZ4_OPT_NUM);+ assert(last_match_pos >= 1); /* == 1 when only one candidate */+ DEBUGLOG(6, "reverse traversal, looking for shortest path (last_match_pos=%i)", last_match_pos);+ { int candidate_pos = cur;+ int selected_matchLength = best_mlen;+ int selected_offset = best_off;+ while (1) { /* from end to beginning */+ int const next_matchLength = opt[candidate_pos].mlen; /* can be 1, means literal */+ int const next_offset = opt[candidate_pos].off;+ DEBUGLOG(7, "pos %i: sequence length %i", candidate_pos, selected_matchLength);+ opt[candidate_pos].mlen = selected_matchLength;+ opt[candidate_pos].off = selected_offset;+ selected_matchLength = next_matchLength;+ selected_offset = next_offset;+ if (next_matchLength > candidate_pos) break; /* last match elected, first match to encode */+ assert(next_matchLength > 0); /* can be 1, means literal */+ candidate_pos -= next_matchLength;+ } }++ /* encode all recorded sequences in order */+ { int rPos = 0; /* relative position (to ip) */+ while (rPos < last_match_pos) {+ int const ml = opt[rPos].mlen;+ int const offset = opt[rPos].off;+ if (ml == 1) { ip++; rPos++; continue; } /* literal; note: can end up with several literals, in which case, skip them */+ rPos += ml;+ assert(ml >= MINMATCH);+ assert((offset >= 1) && (offset <= LZ4_DISTANCE_MAX));+ opSaved = op;+ if ( LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml, ip - offset, limit, oend) ) { /* updates ip, op and anchor */+ ovml = ml;+ ovref = ip - offset;+ goto _dest_overflow;+ } } }+ } /* while (ip <= mflimit) */++_last_literals:+ /* Encode Last Literals */+ { size_t lastRunSize = (size_t)(iend - anchor); /* literals */+ size_t llAdd = (lastRunSize + 255 - RUN_MASK) / 255;+ size_t const totalSize = 1 + llAdd + lastRunSize;+ if (limit == fillOutput) oend += LASTLITERALS; /* restore correct value */+ if (limit && (op + totalSize > oend)) {+ if (limit == limitedOutput) { /* Check output limit */+ retval = 0;+ goto _return_label;+ }+ /* adapt lastRunSize to fill 'dst' */+ lastRunSize = (size_t)(oend - op) - 1 /*token*/;+ llAdd = (lastRunSize + 256 - RUN_MASK) / 256;+ lastRunSize -= llAdd;+ }+ DEBUGLOG(6, "Final literal run : %i literals", (int)lastRunSize);+ ip = anchor + lastRunSize; /* can be != iend if limit==fillOutput */++ if (lastRunSize >= RUN_MASK) {+ size_t accumulator = lastRunSize - RUN_MASK;+ *op++ = (RUN_MASK << ML_BITS);+ for(; accumulator >= 255 ; accumulator -= 255) *op++ = 255;+ *op++ = (BYTE) accumulator;+ } else {+ *op++ = (BYTE)(lastRunSize << ML_BITS);+ }+ LZ4_memcpy(op, anchor, lastRunSize);+ op += lastRunSize;+ }++ /* End */+ *srcSizePtr = (int) (((const char*)ip) - source);+ retval = (int) ((char*)op-dst);+ goto _return_label;++_dest_overflow:+if (limit == fillOutput) {+ /* Assumption : ip, anchor, ovml and ovref must be set correctly */+ size_t const ll = (size_t)(ip - anchor);+ size_t const ll_addbytes = (ll + 240) / 255;+ size_t const ll_totalCost = 1 + ll_addbytes + ll;+ BYTE* const maxLitPos = oend - 3; /* 2 for offset, 1 for token */+ DEBUGLOG(6, "Last sequence overflowing (only %i bytes remaining)", (int)(oend-1-opSaved));+ op = opSaved; /* restore correct out pointer */+ if (op + ll_totalCost <= maxLitPos) {+ /* ll validated; now adjust match length */+ size_t const bytesLeftForMl = (size_t)(maxLitPos - (op+ll_totalCost));+ size_t const maxMlSize = MINMATCH + (ML_MASK-1) + (bytesLeftForMl * 255);+ assert(maxMlSize < INT_MAX); assert(ovml >= 0);+ if ((size_t)ovml > maxMlSize) ovml = (int)maxMlSize;+ if ((oend + LASTLITERALS) - (op + ll_totalCost + 2) - 1 + ovml >= MFLIMIT) {+ DEBUGLOG(6, "Space to end : %i + ml (%i)", (int)((oend + LASTLITERALS) - (op + ll_totalCost + 2) - 1), ovml);+ DEBUGLOG(6, "Before : ip = %p, anchor = %p", ip, anchor);+ LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ovml, ovref, notLimited, oend);+ DEBUGLOG(6, "After : ip = %p, anchor = %p", ip, anchor);+ } }+ goto _last_literals;+}+_return_label:+#if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1+ FREEMEM(opt);+#endif+ return retval;+}++}
+ cbits/tracy/public/common/tracy_lz4hc.hpp view
@@ -0,0 +1,405 @@+/*+ LZ4 HC - High Compression Mode of LZ4+ Header File+ Copyright (C) 2011-2020, Yann Collet.+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)++ 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.++ 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.++ You can contact the author at :+ - LZ4 source repository : https://github.com/lz4/lz4+ - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c+*/+#ifndef TRACY_LZ4_HC_H_19834876238432+#define TRACY_LZ4_HC_H_19834876238432++/* --- Dependency --- */+/* note : lz4hc requires lz4.h/lz4.c for compilation */+#include "tracy_lz4.hpp" /* stddef, LZ4LIB_API, LZ4_DEPRECATED */+++/* --- Useful constants --- */+#define LZ4HC_CLEVEL_MIN 3+#define LZ4HC_CLEVEL_DEFAULT 9+#define LZ4HC_CLEVEL_OPT_MIN 10+#define LZ4HC_CLEVEL_MAX 12++namespace tracy+{++/*-************************************+ * Block Compression+ **************************************/+/*! LZ4_compress_HC() :+ * Compress data from `src` into `dst`, using the powerful but slower "HC" algorithm.+ * `dst` must be already allocated.+ * Compression is guaranteed to succeed if `dstCapacity >= LZ4_compressBound(srcSize)` (see "lz4.h")+ * Max supported `srcSize` value is LZ4_MAX_INPUT_SIZE (see "lz4.h")+ * `compressionLevel` : any value between 1 and LZ4HC_CLEVEL_MAX will work.+ * Values > LZ4HC_CLEVEL_MAX behave the same as LZ4HC_CLEVEL_MAX.+ * @return : the number of bytes written into 'dst'+ * or 0 if compression fails.+ */+LZ4LIB_API int LZ4_compress_HC (const char* src, char* dst, int srcSize, int dstCapacity, int compressionLevel);+++/* Note :+ * Decompression functions are provided within "lz4.h" (BSD license)+ */+++/*! LZ4_compress_HC_extStateHC() :+ * Same as LZ4_compress_HC(), but using an externally allocated memory segment for `state`.+ * `state` size is provided by LZ4_sizeofStateHC().+ * Memory segment must be aligned on 8-bytes boundaries (which a normal malloc() should do properly).+ */+LZ4LIB_API int LZ4_sizeofStateHC(void);+LZ4LIB_API int LZ4_compress_HC_extStateHC(void* stateHC, const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel);+++/*! LZ4_compress_HC_destSize() : v1.9.0++ * Will compress as much data as possible from `src`+ * to fit into `targetDstSize` budget.+ * Result is provided in 2 parts :+ * @return : the number of bytes written into 'dst' (necessarily <= targetDstSize)+ * or 0 if compression fails.+ * `srcSizePtr` : on success, *srcSizePtr is updated to indicate how much bytes were read from `src`+ */+LZ4LIB_API int LZ4_compress_HC_destSize(void* stateHC,+ const char* src, char* dst,+ int* srcSizePtr, int targetDstSize,+ int compressionLevel);+++/*-************************************+ * Streaming Compression+ * Bufferless synchronous API+ **************************************/+ typedef union LZ4_streamHC_u LZ4_streamHC_t; /* incomplete type (defined later) */++/*! LZ4_createStreamHC() and LZ4_freeStreamHC() :+ * These functions create and release memory for LZ4 HC streaming state.+ * Newly created states are automatically initialized.+ * A same state can be used multiple times consecutively,+ * starting with LZ4_resetStreamHC_fast() to start a new stream of blocks.+ */+LZ4LIB_API LZ4_streamHC_t* LZ4_createStreamHC(void);+LZ4LIB_API int LZ4_freeStreamHC (LZ4_streamHC_t* streamHCPtr);++/*+ These functions compress data in successive blocks of any size,+ using previous blocks as dictionary, to improve compression ratio.+ One key assumption is that previous blocks (up to 64 KB) remain read-accessible while compressing next blocks.+ There is an exception for ring buffers, which can be smaller than 64 KB.+ Ring-buffer scenario is automatically detected and handled within LZ4_compress_HC_continue().++ Before starting compression, state must be allocated and properly initialized.+ LZ4_createStreamHC() does both, though compression level is set to LZ4HC_CLEVEL_DEFAULT.++ Selecting the compression level can be done with LZ4_resetStreamHC_fast() (starts a new stream)+ or LZ4_setCompressionLevel() (anytime, between blocks in the same stream) (experimental).+ LZ4_resetStreamHC_fast() only works on states which have been properly initialized at least once,+ which is automatically the case when state is created using LZ4_createStreamHC().++ After reset, a first "fictional block" can be designated as initial dictionary,+ using LZ4_loadDictHC() (Optional).++ Invoke LZ4_compress_HC_continue() to compress each successive block.+ The number of blocks is unlimited.+ Previous input blocks, including initial dictionary when present,+ must remain accessible and unmodified during compression.++ It's allowed to update compression level anytime between blocks,+ using LZ4_setCompressionLevel() (experimental).++ 'dst' buffer should be sized to handle worst case scenarios+ (see LZ4_compressBound(), it ensures compression success).+ In case of failure, the API does not guarantee recovery,+ so the state _must_ be reset.+ To ensure compression success+ whenever `dst` buffer size cannot be made >= LZ4_compressBound(),+ consider using LZ4_compress_HC_continue_destSize().++ Whenever previous input blocks can't be preserved unmodified in-place during compression of next blocks,+ it's possible to copy the last blocks into a more stable memory space, using LZ4_saveDictHC().+ Return value of LZ4_saveDictHC() is the size of dictionary effectively saved into 'safeBuffer' (<= 64 KB)++ After completing a streaming compression,+ it's possible to start a new stream of blocks, using the same LZ4_streamHC_t state,+ just by resetting it, using LZ4_resetStreamHC_fast().+*/++LZ4LIB_API void LZ4_resetStreamHC_fast(LZ4_streamHC_t* streamHCPtr, int compressionLevel); /* v1.9.0+ */+LZ4LIB_API int LZ4_loadDictHC (LZ4_streamHC_t* streamHCPtr, const char* dictionary, int dictSize);++LZ4LIB_API int LZ4_compress_HC_continue (LZ4_streamHC_t* streamHCPtr,+ const char* src, char* dst,+ int srcSize, int maxDstSize);++/*! LZ4_compress_HC_continue_destSize() : v1.9.0++ * Similar to LZ4_compress_HC_continue(),+ * but will read as much data as possible from `src`+ * to fit into `targetDstSize` budget.+ * Result is provided into 2 parts :+ * @return : the number of bytes written into 'dst' (necessarily <= targetDstSize)+ * or 0 if compression fails.+ * `srcSizePtr` : on success, *srcSizePtr will be updated to indicate how much bytes were read from `src`.+ * Note that this function may not consume the entire input.+ */+LZ4LIB_API int LZ4_compress_HC_continue_destSize(LZ4_streamHC_t* LZ4_streamHCPtr,+ const char* src, char* dst,+ int* srcSizePtr, int targetDstSize);++LZ4LIB_API int LZ4_saveDictHC (LZ4_streamHC_t* streamHCPtr, char* safeBuffer, int maxDictSize);++++/*^**********************************************+ * !!!!!! STATIC LINKING ONLY !!!!!!+ ***********************************************/++/*-******************************************************************+ * PRIVATE DEFINITIONS :+ * Do not use these definitions directly.+ * They are merely exposed to allow static allocation of `LZ4_streamHC_t`.+ * Declare an `LZ4_streamHC_t` directly, rather than any type below.+ * Even then, only do so in the context of static linking, as definitions may change between versions.+ ********************************************************************/++#define LZ4HC_DICTIONARY_LOGSIZE 16+#define LZ4HC_MAXD (1<<LZ4HC_DICTIONARY_LOGSIZE)+#define LZ4HC_MAXD_MASK (LZ4HC_MAXD - 1)++#define LZ4HC_HASH_LOG 15+#define LZ4HC_HASHTABLESIZE (1 << LZ4HC_HASH_LOG)+#define LZ4HC_HASH_MASK (LZ4HC_HASHTABLESIZE - 1)+++/* Never ever use these definitions directly !+ * Declare or allocate an LZ4_streamHC_t instead.+**/+typedef struct LZ4HC_CCtx_internal LZ4HC_CCtx_internal;+struct LZ4HC_CCtx_internal+{+ LZ4_u32 hashTable[LZ4HC_HASHTABLESIZE];+ LZ4_u16 chainTable[LZ4HC_MAXD];+ const LZ4_byte* end; /* next block here to continue on current prefix */+ const LZ4_byte* prefixStart; /* Indexes relative to this position */+ const LZ4_byte* dictStart; /* alternate reference for extDict */+ LZ4_u32 dictLimit; /* below that point, need extDict */+ LZ4_u32 lowLimit; /* below that point, no more dict */+ LZ4_u32 nextToUpdate; /* index from which to continue dictionary update */+ short compressionLevel;+ LZ4_i8 favorDecSpeed; /* favor decompression speed if this flag set,+ otherwise, favor compression ratio */+ LZ4_i8 dirty; /* stream has to be fully reset if this flag is set */+ const LZ4HC_CCtx_internal* dictCtx;+};++#define LZ4_STREAMHC_MINSIZE 262200 /* static size, for inter-version compatibility */+union LZ4_streamHC_u {+ char minStateSize[LZ4_STREAMHC_MINSIZE];+ LZ4HC_CCtx_internal internal_donotuse;+}; /* previously typedef'd to LZ4_streamHC_t */++/* LZ4_streamHC_t :+ * This structure allows static allocation of LZ4 HC streaming state.+ * This can be used to allocate statically on stack, or as part of a larger structure.+ *+ * Such state **must** be initialized using LZ4_initStreamHC() before first use.+ *+ * Note that invoking LZ4_initStreamHC() is not required when+ * the state was created using LZ4_createStreamHC() (which is recommended).+ * Using the normal builder, a newly created state is automatically initialized.+ *+ * Static allocation shall only be used in combination with static linking.+ */++/* LZ4_initStreamHC() : v1.9.0++ * Required before first use of a statically allocated LZ4_streamHC_t.+ * Before v1.9.0 : use LZ4_resetStreamHC() instead+ */+LZ4LIB_API LZ4_streamHC_t* LZ4_initStreamHC(void* buffer, size_t size);+++/*-************************************+* Deprecated Functions+**************************************/+/* see lz4.h LZ4_DISABLE_DEPRECATE_WARNINGS to turn off deprecation warnings */++/* deprecated compression functions */+LZ4_DEPRECATED("use LZ4_compress_HC() instead") LZ4LIB_API int LZ4_compressHC (const char* source, char* dest, int inputSize);+LZ4_DEPRECATED("use LZ4_compress_HC() instead") LZ4LIB_API int LZ4_compressHC_limitedOutput (const char* source, char* dest, int inputSize, int maxOutputSize);+LZ4_DEPRECATED("use LZ4_compress_HC() instead") LZ4LIB_API int LZ4_compressHC2 (const char* source, char* dest, int inputSize, int compressionLevel);+LZ4_DEPRECATED("use LZ4_compress_HC() instead") LZ4LIB_API int LZ4_compressHC2_limitedOutput(const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel);+LZ4_DEPRECATED("use LZ4_compress_HC_extStateHC() instead") LZ4LIB_API int LZ4_compressHC_withStateHC (void* state, const char* source, char* dest, int inputSize);+LZ4_DEPRECATED("use LZ4_compress_HC_extStateHC() instead") LZ4LIB_API int LZ4_compressHC_limitedOutput_withStateHC (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);+LZ4_DEPRECATED("use LZ4_compress_HC_extStateHC() instead") LZ4LIB_API int LZ4_compressHC2_withStateHC (void* state, const char* source, char* dest, int inputSize, int compressionLevel);+LZ4_DEPRECATED("use LZ4_compress_HC_extStateHC() instead") LZ4LIB_API int LZ4_compressHC2_limitedOutput_withStateHC(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel);+LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_compressHC_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* source, char* dest, int inputSize);+LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_compressHC_limitedOutput_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* source, char* dest, int inputSize, int maxOutputSize);++/* Obsolete streaming functions; degraded functionality; do not use!+ *+ * In order to perform streaming compression, these functions depended on data+ * that is no longer tracked in the state. They have been preserved as well as+ * possible: using them will still produce a correct output. However, use of+ * LZ4_slideInputBufferHC() will truncate the history of the stream, rather+ * than preserve a window-sized chunk of history.+ */+#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)+LZ4_DEPRECATED("use LZ4_createStreamHC() instead") LZ4LIB_API void* LZ4_createHC (const char* inputBuffer);+LZ4_DEPRECATED("use LZ4_freeStreamHC() instead") LZ4LIB_API int LZ4_freeHC (void* LZ4HC_Data);+#endif+LZ4_DEPRECATED("use LZ4_saveDictHC() instead") LZ4LIB_API char* LZ4_slideInputBufferHC (void* LZ4HC_Data);+LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_compressHC2_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int compressionLevel);+LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_compressHC2_limitedOutput_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel);+LZ4_DEPRECATED("use LZ4_createStreamHC() instead") LZ4LIB_API int LZ4_sizeofStreamStateHC(void);+LZ4_DEPRECATED("use LZ4_initStreamHC() instead") LZ4LIB_API int LZ4_resetStreamStateHC(void* state, char* inputBuffer);+++/* LZ4_resetStreamHC() is now replaced by LZ4_initStreamHC().+ * The intention is to emphasize the difference with LZ4_resetStreamHC_fast(),+ * which is now the recommended function to start a new stream of blocks,+ * but cannot be used to initialize a memory segment containing arbitrary garbage data.+ *+ * It is recommended to switch to LZ4_initStreamHC().+ * LZ4_resetStreamHC() will generate deprecation warnings in a future version.+ */+LZ4LIB_API void LZ4_resetStreamHC (LZ4_streamHC_t* streamHCPtr, int compressionLevel);++}++#endif /* LZ4_HC_H_19834876238432 */+++/*-**************************************************+ * !!!!! STATIC LINKING ONLY !!!!!+ * Following definitions are considered experimental.+ * They should not be linked from DLL,+ * as there is no guarantee of API stability yet.+ * Prototypes will be promoted to "stable" status+ * after successful usage in real-life scenarios.+ ***************************************************/+#ifdef LZ4_HC_STATIC_LINKING_ONLY /* protection macro */+#ifndef TRACY_LZ4_HC_SLO_098092834+#define TRACY_LZ4_HC_SLO_098092834++#define LZ4_STATIC_LINKING_ONLY /* LZ4LIB_STATIC_API */+#include "tracy_lz4.hpp"++namespace tracy+{++/*! LZ4_setCompressionLevel() : v1.8.0+ (experimental)+ * It's possible to change compression level+ * between successive invocations of LZ4_compress_HC_continue*()+ * for dynamic adaptation.+ */+LZ4LIB_STATIC_API void LZ4_setCompressionLevel(+ LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel);++/*! LZ4_favorDecompressionSpeed() : v1.8.2+ (experimental)+ * Opt. Parser will favor decompression speed over compression ratio.+ * Only applicable to levels >= LZ4HC_CLEVEL_OPT_MIN.+ */+LZ4LIB_STATIC_API void LZ4_favorDecompressionSpeed(+ LZ4_streamHC_t* LZ4_streamHCPtr, int favor);++/*! LZ4_resetStreamHC_fast() : v1.9.0++ * When an LZ4_streamHC_t is known to be in a internally coherent state,+ * it can often be prepared for a new compression with almost no work, only+ * sometimes falling back to the full, expensive reset that is always required+ * when the stream is in an indeterminate state (i.e., the reset performed by+ * LZ4_resetStreamHC()).+ *+ * LZ4_streamHCs are guaranteed to be in a valid state when:+ * - returned from LZ4_createStreamHC()+ * - reset by LZ4_resetStreamHC()+ * - memset(stream, 0, sizeof(LZ4_streamHC_t))+ * - the stream was in a valid state and was reset by LZ4_resetStreamHC_fast()+ * - the stream was in a valid state and was then used in any compression call+ * that returned success+ * - the stream was in an indeterminate state and was used in a compression+ * call that fully reset the state (LZ4_compress_HC_extStateHC()) and that+ * returned success+ *+ * Note:+ * A stream that was last used in a compression call that returned an error+ * may be passed to this function. However, it will be fully reset, which will+ * clear any existing history and settings from the context.+ */+LZ4LIB_STATIC_API void LZ4_resetStreamHC_fast(+ LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel);++/*! LZ4_compress_HC_extStateHC_fastReset() :+ * A variant of LZ4_compress_HC_extStateHC().+ *+ * Using this variant avoids an expensive initialization step. It is only safe+ * to call if the state buffer is known to be correctly initialized already+ * (see above comment on LZ4_resetStreamHC_fast() for a definition of+ * "correctly initialized"). From a high level, the difference is that this+ * function initializes the provided state with a call to+ * LZ4_resetStreamHC_fast() while LZ4_compress_HC_extStateHC() starts with a+ * call to LZ4_resetStreamHC().+ */+LZ4LIB_STATIC_API int LZ4_compress_HC_extStateHC_fastReset (+ void* state,+ const char* src, char* dst,+ int srcSize, int dstCapacity,+ int compressionLevel);++/*! LZ4_attach_HC_dictionary() :+ * This is an experimental API that allows for the efficient use of a+ * static dictionary many times.+ *+ * Rather than re-loading the dictionary buffer into a working context before+ * each compression, or copying a pre-loaded dictionary's LZ4_streamHC_t into a+ * working LZ4_streamHC_t, this function introduces a no-copy setup mechanism,+ * in which the working stream references the dictionary stream in-place.+ *+ * Several assumptions are made about the state of the dictionary stream.+ * Currently, only streams which have been prepared by LZ4_loadDictHC() should+ * be expected to work.+ *+ * Alternatively, the provided dictionary stream pointer may be NULL, in which+ * case any existing dictionary stream is unset.+ *+ * A dictionary should only be attached to a stream without any history (i.e.,+ * a stream that has just been reset).+ *+ * The dictionary will remain attached to the working stream only for the+ * current stream session. Calls to LZ4_resetStreamHC(_fast) will remove the+ * dictionary context association from the working stream. The dictionary+ * stream (and source buffer) must remain in-place / accessible / unchanged+ * through the lifetime of the stream session.+ */+LZ4LIB_STATIC_API void LZ4_attach_HC_dictionary(+ LZ4_streamHC_t *working_stream,+ const LZ4_streamHC_t *dictionary_stream);++}++#endif /* LZ4_HC_SLO_098092834 */+#endif /* LZ4_HC_STATIC_LINKING_ONLY */
+ cbits/tracy/public/libbacktrace/alloc.cpp view
@@ -0,0 +1,174 @@+/* alloc.c -- Memory allocation without mmap.+ Copyright (C) 2012-2021 Free Software Foundation, Inc.+ Written by Ian Lance Taylor, Google.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are+met:++ (1) Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ (2) Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in+ the documentation and/or other materials provided with the+ distribution.++ (3) The name of the author may not be used to+ endorse or promote products derived from this software without+ specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. */++#include "config.h"++#include <errno.h>+#include <stdlib.h>+#include <sys/types.h>++#include "backtrace.hpp"+#include "internal.hpp"++#include "../common/TracyAlloc.hpp"++namespace tracy+{++/* Allocation routines to use on systems that do not support anonymous+ mmap. This implementation just uses malloc, which means that the+ backtrace functions may not be safely invoked from a signal+ handler. */++/* Allocate memory like malloc. If ERROR_CALLBACK is NULL, don't+ report an error. */++void *+backtrace_alloc (struct backtrace_state *state ATTRIBUTE_UNUSED,+ size_t size, backtrace_error_callback error_callback,+ void *data)+{+ void *ret;++ ret = tracy_malloc (size);+ if (ret == NULL)+ {+ if (error_callback)+ error_callback (data, "malloc", errno);+ }+ return ret;+}++/* Free memory. */++void+backtrace_free (struct backtrace_state *state ATTRIBUTE_UNUSED,+ void *p, size_t size ATTRIBUTE_UNUSED,+ backtrace_error_callback error_callback ATTRIBUTE_UNUSED,+ void *data ATTRIBUTE_UNUSED)+{+ tracy_free (p);+}++/* Grow VEC by SIZE bytes. */++void *+backtrace_vector_grow (struct backtrace_state *state ATTRIBUTE_UNUSED,+ size_t size, backtrace_error_callback error_callback,+ void *data, struct backtrace_vector *vec)+{+ void *ret;++ if (size > vec->alc)+ {+ size_t alc;+ void *base;++ if (vec->size == 0)+ alc = 32 * size;+ else if (vec->size >= 4096)+ alc = vec->size + 4096;+ else+ alc = 2 * vec->size;++ if (alc < vec->size + size)+ alc = vec->size + size;++ base = tracy_realloc (vec->base, alc);+ if (base == NULL)+ {+ error_callback (data, "realloc", errno);+ return NULL;+ }++ vec->base = base;+ vec->alc = alc - vec->size;+ }++ ret = (char *) vec->base + vec->size;+ vec->size += size;+ vec->alc -= size;+ return ret;+}++/* Finish the current allocation on VEC. */++void *+backtrace_vector_finish (struct backtrace_state *state,+ struct backtrace_vector *vec,+ backtrace_error_callback error_callback,+ void *data)+{+ void *ret;++ /* With this allocator we call realloc in backtrace_vector_grow,+ which means we can't easily reuse the memory here. So just+ release it. */+ if (!backtrace_vector_release (state, vec, error_callback, data))+ return NULL;+ ret = vec->base;+ vec->base = NULL;+ vec->size = 0;+ vec->alc = 0;+ return ret;+}++/* Release any extra space allocated for VEC. */++int+backtrace_vector_release (struct backtrace_state *state ATTRIBUTE_UNUSED,+ struct backtrace_vector *vec,+ backtrace_error_callback error_callback,+ void *data)+{+ vec->alc = 0;++ if (vec->size == 0)+ {+ /* As of C17, realloc with size 0 is marked as an obsolescent feature, use+ free instead. */+ tracy_free (vec->base);+ vec->base = NULL;+ return 1;+ }++ vec->base = tracy_realloc (vec->base, vec->size);+ if (vec->base == NULL)+ {+ error_callback (data, "realloc", errno);+ return 0;+ }++ return 1;+}++}
+ cbits/tracy/public/libbacktrace/backtrace.hpp view
@@ -0,0 +1,186 @@+/* backtrace.h -- Public header file for stack backtrace library.+ Copyright (C) 2012-2021 Free Software Foundation, Inc.+ Written by Ian Lance Taylor, Google.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are+met:++ (1) Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ (2) Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in+ the documentation and/or other materials provided with the+ distribution.++ (3) The name of the author may not be used to+ endorse or promote products derived from this software without+ specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. */++#ifndef BACKTRACE_H+#define BACKTRACE_H++#include <stddef.h>+#include <stdint.h>+#include <stdio.h>++namespace tracy+{++/* The backtrace state. This struct is intentionally not defined in+ the public interface. */++struct backtrace_state;++/* The type of the error callback argument to backtrace functions.+ This function, if not NULL, will be called for certain error cases.+ The DATA argument is passed to the function that calls this one.+ The MSG argument is an error message. The ERRNUM argument, if+ greater than 0, holds an errno value. The MSG buffer may become+ invalid after this function returns.++ As a special case, the ERRNUM argument will be passed as -1 if no+ debug info can be found for the executable, or if the debug info+ exists but has an unsupported version, but the function requires+ debug info (e.g., backtrace_full, backtrace_pcinfo). The MSG in+ this case will be something along the lines of "no debug info".+ Similarly, ERRNUM will be passed as -1 if there is no symbol table,+ but the function requires a symbol table (e.g., backtrace_syminfo).+ This may be used as a signal that some other approach should be+ tried. */++typedef void (*backtrace_error_callback) (void *data, const char *msg,+ int errnum);++/* Create state information for the backtrace routines. This must be+ called before any of the other routines, and its return value must+ be passed to all of the other routines. FILENAME is the path name+ of the executable file; if it is NULL the library will try+ system-specific path names. If not NULL, FILENAME must point to a+ permanent buffer. If THREADED is non-zero the state may be+ accessed by multiple threads simultaneously, and the library will+ use appropriate atomic operations. If THREADED is zero the state+ may only be accessed by one thread at a time. This returns a state+ pointer on success, NULL on error. If an error occurs, this will+ call the ERROR_CALLBACK routine.++ Calling this function allocates resources that cannot be freed.+ There is no backtrace_free_state function. The state is used to+ cache information that is expensive to recompute. Programs are+ expected to call this function at most once and to save the return+ value for all later calls to backtrace functions. */++extern struct backtrace_state *backtrace_create_state (+ const char *filename, int threaded,+ backtrace_error_callback error_callback, void *data);++/* The type of the callback argument to the backtrace_full function.+ DATA is the argument passed to backtrace_full. PC is the program+ counter. FILENAME is the name of the file containing PC, or NULL+ if not available. LINENO is the line number in FILENAME containing+ PC, or 0 if not available. FUNCTION is the name of the function+ containing PC, or NULL if not available. This should return 0 to+ continuing tracing. The FILENAME and FUNCTION buffers may become+ invalid after this function returns. */++typedef int (*backtrace_full_callback) (void *data, uintptr_t pc, uintptr_t lowaddr,+ const char *filename, int lineno,+ const char *function);++/* Get a full stack backtrace. SKIP is the number of frames to skip;+ passing 0 will start the trace with the function calling+ backtrace_full. DATA is passed to the callback routine. If any+ call to CALLBACK returns a non-zero value, the stack backtrace+ stops, and backtrace returns that value; this may be used to limit+ the number of stack frames desired. If all calls to CALLBACK+ return 0, backtrace returns 0. The backtrace_full function will+ make at least one call to either CALLBACK or ERROR_CALLBACK. This+ function requires debug info for the executable. */++extern int backtrace_full (struct backtrace_state *state, int skip,+ backtrace_full_callback callback,+ backtrace_error_callback error_callback,+ void *data);++/* The type of the callback argument to the backtrace_simple function.+ DATA is the argument passed to simple_backtrace. PC is the program+ counter. This should return 0 to continue tracing. */++typedef int (*backtrace_simple_callback) (void *data, uintptr_t pc);++/* Get a simple backtrace. SKIP is the number of frames to skip, as+ in backtrace. DATA is passed to the callback routine. If any call+ to CALLBACK returns a non-zero value, the stack backtrace stops,+ and backtrace_simple returns that value. Otherwise+ backtrace_simple returns 0. The backtrace_simple function will+ make at least one call to either CALLBACK or ERROR_CALLBACK. This+ function does not require any debug info for the executable. */++extern int backtrace_simple (struct backtrace_state *state, int skip,+ backtrace_simple_callback callback,+ backtrace_error_callback error_callback,+ void *data);++/* Print the current backtrace in a user readable format to a FILE.+ SKIP is the number of frames to skip, as in backtrace_full. Any+ error messages are printed to stderr. This function requires debug+ info for the executable. */++extern void backtrace_print (struct backtrace_state *state, int skip, FILE *);++/* Given PC, a program counter in the current program, call the+ callback function with filename, line number, and function name+ information. This will normally call the callback function exactly+ once. However, if the PC happens to describe an inlined call, and+ the debugging information contains the necessary information, then+ this may call the callback function multiple times. This will make+ at least one call to either CALLBACK or ERROR_CALLBACK. This+ returns the first non-zero value returned by CALLBACK, or 0. */++extern int backtrace_pcinfo (struct backtrace_state *state, uintptr_t pc,+ backtrace_full_callback callback,+ backtrace_error_callback error_callback,+ void *data);++/* The type of the callback argument to backtrace_syminfo. DATA and+ PC are the arguments passed to backtrace_syminfo. SYMNAME is the+ name of the symbol for the corresponding code. SYMVAL is the+ value and SYMSIZE is the size of the symbol. SYMNAME will be NULL+ if no error occurred but the symbol could not be found. */++typedef void (*backtrace_syminfo_callback) (void *data, uintptr_t pc,+ const char *symname,+ uintptr_t symval,+ uintptr_t symsize);++/* Given ADDR, an address or program counter in the current program,+ call the callback information with the symbol name and value+ describing the function or variable in which ADDR may be found.+ This will call either CALLBACK or ERROR_CALLBACK exactly once.+ This returns 1 on success, 0 on failure. This function requires+ the symbol table but does not require the debug info. Note that if+ the symbol table is present but ADDR could not be found in the+ table, CALLBACK will be called with a NULL SYMNAME argument.+ Returns 1 on success, 0 on error. */++extern int backtrace_syminfo (struct backtrace_state *state, uintptr_t addr,+ backtrace_syminfo_callback callback,+ backtrace_error_callback error_callback,+ void *data);++}++#endif
+ cbits/tracy/public/libbacktrace/config.h view
@@ -0,0 +1,26 @@+#include <limits.h>+#if defined(__linux__) && !defined(__GLIBC__) && !defined(__WORDSIZE)+// include __WORDSIZE headers for musl+# include <bits/reg.h>+#endif+#if __WORDSIZE == 64+# define BACKTRACE_ELF_SIZE 64+#else+# define BACKTRACE_ELF_SIZE 32+#endif++#define HAVE_DLFCN_H 1+#define HAVE_FCNTL 1+#define HAVE_INTTYPES_H 1+#define HAVE_LSTAT 1+#define HAVE_READLINK 1+#define HAVE_DL_ITERATE_PHDR 1+#define HAVE_ATOMIC_FUNCTIONS 1+#define HAVE_DECL_STRNLEN 1++#ifdef __APPLE__+# define HAVE_MACH_O_DYLD_H 1+#elif defined BSD+# define HAVE_KERN_PROC 1+# define HAVE_KERN_PROC_ARGS 1+#endif
+ cbits/tracy/public/libbacktrace/dwarf.cpp view
@@ -0,0 +1,4455 @@+/* dwarf.c -- Get file/line information from DWARF for backtraces.+ Copyright (C) 2012-2021 Free Software Foundation, Inc.+ Written by Ian Lance Taylor, Google.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are+met:++ (1) Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ (2) Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in+ the documentation and/or other materials provided with the+ distribution.++ (3) The name of the author may not be used to+ endorse or promote products derived from this software without+ specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. */++#include "config.h"++#include <errno.h>+#include <stdlib.h>+#include <string.h>+#include <sys/types.h>++#include "filenames.hpp"++#include "backtrace.hpp"+#include "internal.hpp"++namespace tracy+{++/* DWARF constants. */++enum dwarf_tag {+ DW_TAG_entry_point = 0x3,+ DW_TAG_compile_unit = 0x11,+ DW_TAG_inlined_subroutine = 0x1d,+ DW_TAG_subprogram = 0x2e,+ DW_TAG_skeleton_unit = 0x4a,+};++enum dwarf_form {+ DW_FORM_addr = 0x01,+ DW_FORM_block2 = 0x03,+ DW_FORM_block4 = 0x04,+ DW_FORM_data2 = 0x05,+ DW_FORM_data4 = 0x06,+ DW_FORM_data8 = 0x07,+ DW_FORM_string = 0x08,+ DW_FORM_block = 0x09,+ DW_FORM_block1 = 0x0a,+ DW_FORM_data1 = 0x0b,+ DW_FORM_flag = 0x0c,+ DW_FORM_sdata = 0x0d,+ DW_FORM_strp = 0x0e,+ DW_FORM_udata = 0x0f,+ DW_FORM_ref_addr = 0x10,+ DW_FORM_ref1 = 0x11,+ DW_FORM_ref2 = 0x12,+ DW_FORM_ref4 = 0x13,+ DW_FORM_ref8 = 0x14,+ DW_FORM_ref_udata = 0x15,+ DW_FORM_indirect = 0x16,+ DW_FORM_sec_offset = 0x17,+ DW_FORM_exprloc = 0x18,+ DW_FORM_flag_present = 0x19,+ DW_FORM_ref_sig8 = 0x20,+ DW_FORM_strx = 0x1a,+ DW_FORM_addrx = 0x1b,+ DW_FORM_ref_sup4 = 0x1c,+ DW_FORM_strp_sup = 0x1d,+ DW_FORM_data16 = 0x1e,+ DW_FORM_line_strp = 0x1f,+ DW_FORM_implicit_const = 0x21,+ DW_FORM_loclistx = 0x22,+ DW_FORM_rnglistx = 0x23,+ DW_FORM_ref_sup8 = 0x24,+ DW_FORM_strx1 = 0x25,+ DW_FORM_strx2 = 0x26,+ DW_FORM_strx3 = 0x27,+ DW_FORM_strx4 = 0x28,+ DW_FORM_addrx1 = 0x29,+ DW_FORM_addrx2 = 0x2a,+ DW_FORM_addrx3 = 0x2b,+ DW_FORM_addrx4 = 0x2c,+ DW_FORM_GNU_addr_index = 0x1f01,+ DW_FORM_GNU_str_index = 0x1f02,+ DW_FORM_GNU_ref_alt = 0x1f20,+ DW_FORM_GNU_strp_alt = 0x1f21+};++enum dwarf_attribute {+ DW_AT_sibling = 0x01,+ DW_AT_location = 0x02,+ DW_AT_name = 0x03,+ DW_AT_ordering = 0x09,+ DW_AT_subscr_data = 0x0a,+ DW_AT_byte_size = 0x0b,+ DW_AT_bit_offset = 0x0c,+ DW_AT_bit_size = 0x0d,+ DW_AT_element_list = 0x0f,+ DW_AT_stmt_list = 0x10,+ DW_AT_low_pc = 0x11,+ DW_AT_high_pc = 0x12,+ DW_AT_language = 0x13,+ DW_AT_member = 0x14,+ DW_AT_discr = 0x15,+ DW_AT_discr_value = 0x16,+ DW_AT_visibility = 0x17,+ DW_AT_import = 0x18,+ DW_AT_string_length = 0x19,+ DW_AT_common_reference = 0x1a,+ DW_AT_comp_dir = 0x1b,+ DW_AT_const_value = 0x1c,+ DW_AT_containing_type = 0x1d,+ DW_AT_default_value = 0x1e,+ DW_AT_inline = 0x20,+ DW_AT_is_optional = 0x21,+ DW_AT_lower_bound = 0x22,+ DW_AT_producer = 0x25,+ DW_AT_prototyped = 0x27,+ DW_AT_return_addr = 0x2a,+ DW_AT_start_scope = 0x2c,+ DW_AT_bit_stride = 0x2e,+ DW_AT_upper_bound = 0x2f,+ DW_AT_abstract_origin = 0x31,+ DW_AT_accessibility = 0x32,+ DW_AT_address_class = 0x33,+ DW_AT_artificial = 0x34,+ DW_AT_base_types = 0x35,+ DW_AT_calling_convention = 0x36,+ DW_AT_count = 0x37,+ DW_AT_data_member_location = 0x38,+ DW_AT_decl_column = 0x39,+ DW_AT_decl_file = 0x3a,+ DW_AT_decl_line = 0x3b,+ DW_AT_declaration = 0x3c,+ DW_AT_discr_list = 0x3d,+ DW_AT_encoding = 0x3e,+ DW_AT_external = 0x3f,+ DW_AT_frame_base = 0x40,+ DW_AT_friend = 0x41,+ DW_AT_identifier_case = 0x42,+ DW_AT_macro_info = 0x43,+ DW_AT_namelist_items = 0x44,+ DW_AT_priority = 0x45,+ DW_AT_segment = 0x46,+ DW_AT_specification = 0x47,+ DW_AT_static_link = 0x48,+ DW_AT_type = 0x49,+ DW_AT_use_location = 0x4a,+ DW_AT_variable_parameter = 0x4b,+ DW_AT_virtuality = 0x4c,+ DW_AT_vtable_elem_location = 0x4d,+ DW_AT_allocated = 0x4e,+ DW_AT_associated = 0x4f,+ DW_AT_data_location = 0x50,+ DW_AT_byte_stride = 0x51,+ DW_AT_entry_pc = 0x52,+ DW_AT_use_UTF8 = 0x53,+ DW_AT_extension = 0x54,+ DW_AT_ranges = 0x55,+ DW_AT_trampoline = 0x56,+ DW_AT_call_column = 0x57,+ DW_AT_call_file = 0x58,+ DW_AT_call_line = 0x59,+ DW_AT_description = 0x5a,+ DW_AT_binary_scale = 0x5b,+ DW_AT_decimal_scale = 0x5c,+ DW_AT_small = 0x5d,+ DW_AT_decimal_sign = 0x5e,+ DW_AT_digit_count = 0x5f,+ DW_AT_picture_string = 0x60,+ DW_AT_mutable = 0x61,+ DW_AT_threads_scaled = 0x62,+ DW_AT_explicit = 0x63,+ DW_AT_object_pointer = 0x64,+ DW_AT_endianity = 0x65,+ DW_AT_elemental = 0x66,+ DW_AT_pure = 0x67,+ DW_AT_recursive = 0x68,+ DW_AT_signature = 0x69,+ DW_AT_main_subprogram = 0x6a,+ DW_AT_data_bit_offset = 0x6b,+ DW_AT_const_expr = 0x6c,+ DW_AT_enum_class = 0x6d,+ DW_AT_linkage_name = 0x6e,+ DW_AT_string_length_bit_size = 0x6f,+ DW_AT_string_length_byte_size = 0x70,+ DW_AT_rank = 0x71,+ DW_AT_str_offsets_base = 0x72,+ DW_AT_addr_base = 0x73,+ DW_AT_rnglists_base = 0x74,+ DW_AT_dwo_name = 0x76,+ DW_AT_reference = 0x77,+ DW_AT_rvalue_reference = 0x78,+ DW_AT_macros = 0x79,+ DW_AT_call_all_calls = 0x7a,+ DW_AT_call_all_source_calls = 0x7b,+ DW_AT_call_all_tail_calls = 0x7c,+ DW_AT_call_return_pc = 0x7d,+ DW_AT_call_value = 0x7e,+ DW_AT_call_origin = 0x7f,+ DW_AT_call_parameter = 0x80,+ DW_AT_call_pc = 0x81,+ DW_AT_call_tail_call = 0x82,+ DW_AT_call_target = 0x83,+ DW_AT_call_target_clobbered = 0x84,+ DW_AT_call_data_location = 0x85,+ DW_AT_call_data_value = 0x86,+ DW_AT_noreturn = 0x87,+ DW_AT_alignment = 0x88,+ DW_AT_export_symbols = 0x89,+ DW_AT_deleted = 0x8a,+ DW_AT_defaulted = 0x8b,+ DW_AT_loclists_base = 0x8c,+ DW_AT_lo_user = 0x2000,+ DW_AT_hi_user = 0x3fff,+ DW_AT_MIPS_fde = 0x2001,+ DW_AT_MIPS_loop_begin = 0x2002,+ DW_AT_MIPS_tail_loop_begin = 0x2003,+ DW_AT_MIPS_epilog_begin = 0x2004,+ DW_AT_MIPS_loop_unroll_factor = 0x2005,+ DW_AT_MIPS_software_pipeline_depth = 0x2006,+ DW_AT_MIPS_linkage_name = 0x2007,+ DW_AT_MIPS_stride = 0x2008,+ DW_AT_MIPS_abstract_name = 0x2009,+ DW_AT_MIPS_clone_origin = 0x200a,+ DW_AT_MIPS_has_inlines = 0x200b,+ DW_AT_HP_block_index = 0x2000,+ DW_AT_HP_unmodifiable = 0x2001,+ DW_AT_HP_prologue = 0x2005,+ DW_AT_HP_epilogue = 0x2008,+ DW_AT_HP_actuals_stmt_list = 0x2010,+ DW_AT_HP_proc_per_section = 0x2011,+ DW_AT_HP_raw_data_ptr = 0x2012,+ DW_AT_HP_pass_by_reference = 0x2013,+ DW_AT_HP_opt_level = 0x2014,+ DW_AT_HP_prof_version_id = 0x2015,+ DW_AT_HP_opt_flags = 0x2016,+ DW_AT_HP_cold_region_low_pc = 0x2017,+ DW_AT_HP_cold_region_high_pc = 0x2018,+ DW_AT_HP_all_variables_modifiable = 0x2019,+ DW_AT_HP_linkage_name = 0x201a,+ DW_AT_HP_prof_flags = 0x201b,+ DW_AT_HP_unit_name = 0x201f,+ DW_AT_HP_unit_size = 0x2020,+ DW_AT_HP_widened_byte_size = 0x2021,+ DW_AT_HP_definition_points = 0x2022,+ DW_AT_HP_default_location = 0x2023,+ DW_AT_HP_is_result_param = 0x2029,+ DW_AT_sf_names = 0x2101,+ DW_AT_src_info = 0x2102,+ DW_AT_mac_info = 0x2103,+ DW_AT_src_coords = 0x2104,+ DW_AT_body_begin = 0x2105,+ DW_AT_body_end = 0x2106,+ DW_AT_GNU_vector = 0x2107,+ DW_AT_GNU_guarded_by = 0x2108,+ DW_AT_GNU_pt_guarded_by = 0x2109,+ DW_AT_GNU_guarded = 0x210a,+ DW_AT_GNU_pt_guarded = 0x210b,+ DW_AT_GNU_locks_excluded = 0x210c,+ DW_AT_GNU_exclusive_locks_required = 0x210d,+ DW_AT_GNU_shared_locks_required = 0x210e,+ DW_AT_GNU_odr_signature = 0x210f,+ DW_AT_GNU_template_name = 0x2110,+ DW_AT_GNU_call_site_value = 0x2111,+ DW_AT_GNU_call_site_data_value = 0x2112,+ DW_AT_GNU_call_site_target = 0x2113,+ DW_AT_GNU_call_site_target_clobbered = 0x2114,+ DW_AT_GNU_tail_call = 0x2115,+ DW_AT_GNU_all_tail_call_sites = 0x2116,+ DW_AT_GNU_all_call_sites = 0x2117,+ DW_AT_GNU_all_source_call_sites = 0x2118,+ DW_AT_GNU_macros = 0x2119,+ DW_AT_GNU_deleted = 0x211a,+ DW_AT_GNU_dwo_name = 0x2130,+ DW_AT_GNU_dwo_id = 0x2131,+ DW_AT_GNU_ranges_base = 0x2132,+ DW_AT_GNU_addr_base = 0x2133,+ DW_AT_GNU_pubnames = 0x2134,+ DW_AT_GNU_pubtypes = 0x2135,+ DW_AT_GNU_discriminator = 0x2136,+ DW_AT_GNU_locviews = 0x2137,+ DW_AT_GNU_entry_view = 0x2138,+ DW_AT_VMS_rtnbeg_pd_address = 0x2201,+ DW_AT_use_GNAT_descriptive_type = 0x2301,+ DW_AT_GNAT_descriptive_type = 0x2302,+ DW_AT_GNU_numerator = 0x2303,+ DW_AT_GNU_denominator = 0x2304,+ DW_AT_GNU_bias = 0x2305,+ DW_AT_upc_threads_scaled = 0x3210,+ DW_AT_PGI_lbase = 0x3a00,+ DW_AT_PGI_soffset = 0x3a01,+ DW_AT_PGI_lstride = 0x3a02,+ DW_AT_APPLE_optimized = 0x3fe1,+ DW_AT_APPLE_flags = 0x3fe2,+ DW_AT_APPLE_isa = 0x3fe3,+ DW_AT_APPLE_block = 0x3fe4,+ DW_AT_APPLE_major_runtime_vers = 0x3fe5,+ DW_AT_APPLE_runtime_class = 0x3fe6,+ DW_AT_APPLE_omit_frame_ptr = 0x3fe7,+ DW_AT_APPLE_property_name = 0x3fe8,+ DW_AT_APPLE_property_getter = 0x3fe9,+ DW_AT_APPLE_property_setter = 0x3fea,+ DW_AT_APPLE_property_attribute = 0x3feb,+ DW_AT_APPLE_objc_complete_type = 0x3fec,+ DW_AT_APPLE_property = 0x3fed+};++enum dwarf_line_number_op {+ DW_LNS_extended_op = 0x0,+ DW_LNS_copy = 0x1,+ DW_LNS_advance_pc = 0x2,+ DW_LNS_advance_line = 0x3,+ DW_LNS_set_file = 0x4,+ DW_LNS_set_column = 0x5,+ DW_LNS_negate_stmt = 0x6,+ DW_LNS_set_basic_block = 0x7,+ DW_LNS_const_add_pc = 0x8,+ DW_LNS_fixed_advance_pc = 0x9,+ DW_LNS_set_prologue_end = 0xa,+ DW_LNS_set_epilogue_begin = 0xb,+ DW_LNS_set_isa = 0xc,+};++enum dwarf_extended_line_number_op {+ DW_LNE_end_sequence = 0x1,+ DW_LNE_set_address = 0x2,+ DW_LNE_define_file = 0x3,+ DW_LNE_set_discriminator = 0x4,+};++enum dwarf_line_number_content_type {+ DW_LNCT_path = 0x1,+ DW_LNCT_directory_index = 0x2,+ DW_LNCT_timestamp = 0x3,+ DW_LNCT_size = 0x4,+ DW_LNCT_MD5 = 0x5,+ DW_LNCT_lo_user = 0x2000,+ DW_LNCT_hi_user = 0x3fff+};++enum dwarf_range_list_entry {+ DW_RLE_end_of_list = 0x00,+ DW_RLE_base_addressx = 0x01,+ DW_RLE_startx_endx = 0x02,+ DW_RLE_startx_length = 0x03,+ DW_RLE_offset_pair = 0x04,+ DW_RLE_base_address = 0x05,+ DW_RLE_start_end = 0x06,+ DW_RLE_start_length = 0x07+};++enum dwarf_unit_type {+ DW_UT_compile = 0x01,+ DW_UT_type = 0x02,+ DW_UT_partial = 0x03,+ DW_UT_skeleton = 0x04,+ DW_UT_split_compile = 0x05,+ DW_UT_split_type = 0x06,+ DW_UT_lo_user = 0x80,+ DW_UT_hi_user = 0xff+};++#if !defined(HAVE_DECL_STRNLEN) || !HAVE_DECL_STRNLEN++/* If strnlen is not declared, provide our own version. */++static size_t+xstrnlen (const char *s, size_t maxlen)+{+ size_t i;++ for (i = 0; i < maxlen; ++i)+ if (s[i] == '\0')+ break;+ return i;+}++#define strnlen xstrnlen++#endif++/* A buffer to read DWARF info. */++struct dwarf_buf+{+ /* Buffer name for error messages. */+ const char *name;+ /* Start of the buffer. */+ const unsigned char *start;+ /* Next byte to read. */+ const unsigned char *buf;+ /* The number of bytes remaining. */+ size_t left;+ /* Whether the data is big-endian. */+ int is_bigendian;+ /* Error callback routine. */+ backtrace_error_callback error_callback;+ /* Data for error_callback. */+ void *data;+ /* Non-zero if we've reported an underflow error. */+ int reported_underflow;+};++/* A single attribute in a DWARF abbreviation. */++struct attr+{+ /* The attribute name. */+ enum dwarf_attribute name;+ /* The attribute form. */+ enum dwarf_form form;+ /* The attribute value, for DW_FORM_implicit_const. */+ int64_t val;+};++/* A single DWARF abbreviation. */++struct abbrev+{+ /* The abbrev code--the number used to refer to the abbrev. */+ uint64_t code;+ /* The entry tag. */+ enum dwarf_tag tag;+ /* Non-zero if this abbrev has child entries. */+ int has_children;+ /* The number of attributes. */+ size_t num_attrs;+ /* The attributes. */+ struct attr *attrs;+};++/* The DWARF abbreviations for a compilation unit. This structure+ only exists while reading the compilation unit. Most DWARF readers+ seem to a hash table to map abbrev ID's to abbrev entries.+ However, we primarily care about GCC, and GCC simply issues ID's in+ numerical order starting at 1. So we simply keep a sorted vector,+ and try to just look up the code. */++struct abbrevs+{+ /* The number of abbrevs in the vector. */+ size_t num_abbrevs;+ /* The abbrevs, sorted by the code field. */+ struct abbrev *abbrevs;+};++/* The different kinds of attribute values. */++enum attr_val_encoding+{+ /* No attribute value. */+ ATTR_VAL_NONE,+ /* An address. */+ ATTR_VAL_ADDRESS,+ /* An index into the .debug_addr section, whose value is relative to+ the DW_AT_addr_base attribute of the compilation unit. */+ ATTR_VAL_ADDRESS_INDEX,+ /* A unsigned integer. */+ ATTR_VAL_UINT,+ /* A sigd integer. */+ ATTR_VAL_SINT,+ /* A string. */+ ATTR_VAL_STRING,+ /* An index into the .debug_str_offsets section. */+ ATTR_VAL_STRING_INDEX,+ /* An offset to other data in the containing unit. */+ ATTR_VAL_REF_UNIT,+ /* An offset to other data within the .debug_info section. */+ ATTR_VAL_REF_INFO,+ /* An offset to other data within the alt .debug_info section. */+ ATTR_VAL_REF_ALT_INFO,+ /* An offset to data in some other section. */+ ATTR_VAL_REF_SECTION,+ /* A type signature. */+ ATTR_VAL_REF_TYPE,+ /* An index into the .debug_rnglists section. */+ ATTR_VAL_RNGLISTS_INDEX,+ /* A block of data (not represented). */+ ATTR_VAL_BLOCK,+ /* An expression (not represented). */+ ATTR_VAL_EXPR,+};++/* An attribute value. */++struct attr_val+{+ /* How the value is stored in the field u. */+ enum attr_val_encoding encoding;+ union+ {+ /* ATTR_VAL_ADDRESS*, ATTR_VAL_UINT, ATTR_VAL_REF*. */+ uint64_t uint;+ /* ATTR_VAL_SINT. */+ int64_t sint;+ /* ATTR_VAL_STRING. */+ const char *string;+ /* ATTR_VAL_BLOCK not stored. */+ } u;+};++/* The line number program header. */++struct line_header+{+ /* The version of the line number information. */+ int version;+ /* Address size. */+ int addrsize;+ /* The minimum instruction length. */+ unsigned int min_insn_len;+ /* The maximum number of ops per instruction. */+ unsigned int max_ops_per_insn;+ /* The line base for special opcodes. */+ int line_base;+ /* The line range for special opcodes. */+ unsigned int line_range;+ /* The opcode base--the first special opcode. */+ unsigned int opcode_base;+ /* Opcode lengths, indexed by opcode - 1. */+ const unsigned char *opcode_lengths;+ /* The number of directory entries. */+ size_t dirs_count;+ /* The directory entries. */+ const char **dirs;+ /* The number of filenames. */+ size_t filenames_count;+ /* The filenames. */+ const char **filenames;+};++/* A format description from a line header. */++struct line_header_format+{+ int lnct; /* LNCT code. */+ enum dwarf_form form; /* Form of entry data. */+};++/* Map a single PC value to a file/line. We will keep a vector of+ these sorted by PC value. Each file/line will be correct from the+ PC up to the PC of the next entry if there is one. We allocate one+ extra entry at the end so that we can use bsearch. */++struct line+{+ /* PC. */+ uintptr_t pc;+ /* File name. Many entries in the array are expected to point to+ the same file name. */+ const char *filename;+ /* Line number. */+ int lineno;+ /* Index of the object in the original array read from the DWARF+ section, before it has been sorted. The index makes it possible+ to use Quicksort and maintain stability. */+ int idx;+};++/* A growable vector of line number information. This is used while+ reading the line numbers. */++struct line_vector+{+ /* Memory. This is an array of struct line. */+ struct backtrace_vector vec;+ /* Number of valid mappings. */+ size_t count;+};++/* A function described in the debug info. */++struct function+{+ /* The name of the function. */+ const char *name;+ /* If this is an inlined function, the filename of the call+ site. */+ const char *caller_filename;+ /* If this is an inlined function, the line number of the call+ site. */+ int caller_lineno;+ /* Map PC ranges to inlined functions. */+ struct function_addrs *function_addrs;+ size_t function_addrs_count;+};++/* An address range for a function. This maps a PC value to a+ specific function. */++struct function_addrs+{+ /* Range is LOW <= PC < HIGH. */+ uintptr_t low;+ uintptr_t high;+ /* Function for this address range. */+ struct function *function;+};++/* A growable vector of function address ranges. */++struct function_vector+{+ /* Memory. This is an array of struct function_addrs. */+ struct backtrace_vector vec;+ /* Number of address ranges present. */+ size_t count;+};++/* A DWARF compilation unit. This only holds the information we need+ to map a PC to a file and line. */++struct unit+{+ /* The first entry for this compilation unit. */+ const unsigned char *unit_data;+ /* The length of the data for this compilation unit. */+ size_t unit_data_len;+ /* The offset of UNIT_DATA from the start of the information for+ this compilation unit. */+ size_t unit_data_offset;+ /* Offset of the start of the compilation unit from the start of the+ .debug_info section. */+ size_t low_offset;+ /* Offset of the end of the compilation unit from the start of the+ .debug_info section. */+ size_t high_offset;+ /* DWARF version. */+ int version;+ /* Whether unit is DWARF64. */+ int is_dwarf64;+ /* Address size. */+ int addrsize;+ /* Offset into line number information. */+ off_t lineoff;+ /* Offset of compilation unit in .debug_str_offsets. */+ uint64_t str_offsets_base;+ /* Offset of compilation unit in .debug_addr. */+ uint64_t addr_base;+ /* Offset of compilation unit in .debug_rnglists. */+ uint64_t rnglists_base;+ /* Primary source file. */+ const char *filename;+ /* Compilation command working directory. */+ const char *comp_dir;+ /* Absolute file name, only set if needed. */+ const char *abs_filename;+ /* The abbreviations for this unit. */+ struct abbrevs abbrevs;++ /* The fields above this point are read in during initialization and+ may be accessed freely. The fields below this point are read in+ as needed, and therefore require care, as different threads may+ try to initialize them simultaneously. */++ /* PC to line number mapping. This is NULL if the values have not+ been read. This is (struct line *) -1 if there was an error+ reading the values. */+ struct line *lines;+ /* Number of entries in lines. */+ size_t lines_count;+ /* PC ranges to function. */+ struct function_addrs *function_addrs;+ size_t function_addrs_count;+};++/* An address range for a compilation unit. This maps a PC value to a+ specific compilation unit. Note that we invert the representation+ in DWARF: instead of listing the units and attaching a list of+ ranges, we list the ranges and have each one point to the unit.+ This lets us do a binary search to find the unit. */++struct unit_addrs+{+ /* Range is LOW <= PC < HIGH. */+ uintptr_t low;+ uintptr_t high;+ /* Compilation unit for this address range. */+ struct unit *u;+};++/* A growable vector of compilation unit address ranges. */++struct unit_addrs_vector+{+ /* Memory. This is an array of struct unit_addrs. */+ struct backtrace_vector vec;+ /* Number of address ranges present. */+ size_t count;+};++/* A growable vector of compilation unit pointer. */++struct unit_vector+{+ struct backtrace_vector vec;+ size_t count;+};++/* The information we need to map a PC to a file and line. */++struct dwarf_data+{+ /* The data for the next file we know about. */+ struct dwarf_data *next;+ /* The data for .gnu_debugaltlink. */+ struct dwarf_data *altlink;+/* The base address mapping for this file. */+ struct libbacktrace_base_address base_address;+ /* A sorted list of address ranges. */+ struct unit_addrs *addrs;+ /* Number of address ranges in list. */+ size_t addrs_count;+ /* A sorted list of units. */+ struct unit **units;+ /* Number of units in the list. */+ size_t units_count;+ /* The unparsed DWARF debug data. */+ struct dwarf_sections dwarf_sections;+ /* Whether the data is big-endian or not. */+ int is_bigendian;+ /* A vector used for function addresses. We keep this here so that+ we can grow the vector as we read more functions. */+ struct function_vector fvec;+};++/* Report an error for a DWARF buffer. */++static void+dwarf_buf_error (struct dwarf_buf *buf, const char *msg, int errnum)+{+ char b[200];++ snprintf (b, sizeof b, "%s in %s at %d",+ msg, buf->name, (int) (buf->buf - buf->start));+ buf->error_callback (buf->data, b, errnum);+}++/* Require at least COUNT bytes in BUF. Return 1 if all is well, 0 on+ error. */++static int+require (struct dwarf_buf *buf, size_t count)+{+ if (buf->left >= count)+ return 1;++ if (!buf->reported_underflow)+ {+ dwarf_buf_error (buf, "DWARF underflow", 0);+ buf->reported_underflow = 1;+ }++ return 0;+}++/* Advance COUNT bytes in BUF. Return 1 if all is well, 0 on+ error. */++static int+advance (struct dwarf_buf *buf, size_t count)+{+ if (!require (buf, count))+ return 0;+ buf->buf += count;+ buf->left -= count;+ return 1;+}++/* Read one zero-terminated string from BUF and advance past the string. */++static const char *+read_string (struct dwarf_buf *buf)+{+ const char *p = (const char *)buf->buf;+ size_t len = strnlen (p, buf->left);++ /* - If len == left, we ran out of buffer before finding the zero terminator.+ Generate an error by advancing len + 1.+ - If len < left, advance by len + 1 to skip past the zero terminator. */+ size_t count = len + 1;++ if (!advance (buf, count))+ return NULL;++ return p;+}++/* Read one byte from BUF and advance 1 byte. */++static unsigned char+read_byte (struct dwarf_buf *buf)+{+ const unsigned char *p = buf->buf;++ if (!advance (buf, 1))+ return 0;+ return p[0];+}++/* Read a signed char from BUF and advance 1 byte. */++static signed char+read_sbyte (struct dwarf_buf *buf)+{+ const unsigned char *p = buf->buf;++ if (!advance (buf, 1))+ return 0;+ return (*p ^ 0x80) - 0x80;+}++/* Read a uint16 from BUF and advance 2 bytes. */++static uint16_t+read_uint16 (struct dwarf_buf *buf)+{+ const unsigned char *p = buf->buf;++ if (!advance (buf, 2))+ return 0;+ if (buf->is_bigendian)+ return ((uint16_t) p[0] << 8) | (uint16_t) p[1];+ else+ return ((uint16_t) p[1] << 8) | (uint16_t) p[0];+}++/* Read a 24 bit value from BUF and advance 3 bytes. */++static uint32_t+read_uint24 (struct dwarf_buf *buf)+{+ const unsigned char *p = buf->buf;++ if (!advance (buf, 3))+ return 0;+ if (buf->is_bigendian)+ return (((uint32_t) p[0] << 16) | ((uint32_t) p[1] << 8)+ | (uint32_t) p[2]);+ else+ return (((uint32_t) p[2] << 16) | ((uint32_t) p[1] << 8)+ | (uint32_t) p[0]);+}++/* Read a uint32 from BUF and advance 4 bytes. */++static uint32_t+read_uint32 (struct dwarf_buf *buf)+{+ const unsigned char *p = buf->buf;++ if (!advance (buf, 4))+ return 0;+ if (buf->is_bigendian)+ return (((uint32_t) p[0] << 24) | ((uint32_t) p[1] << 16)+ | ((uint32_t) p[2] << 8) | (uint32_t) p[3]);+ else+ return (((uint32_t) p[3] << 24) | ((uint32_t) p[2] << 16)+ | ((uint32_t) p[1] << 8) | (uint32_t) p[0]);+}++/* Read a uint64 from BUF and advance 8 bytes. */++static uint64_t+read_uint64 (struct dwarf_buf *buf)+{+ const unsigned char *p = buf->buf;++ if (!advance (buf, 8))+ return 0;+ if (buf->is_bigendian)+ return (((uint64_t) p[0] << 56) | ((uint64_t) p[1] << 48)+ | ((uint64_t) p[2] << 40) | ((uint64_t) p[3] << 32)+ | ((uint64_t) p[4] << 24) | ((uint64_t) p[5] << 16)+ | ((uint64_t) p[6] << 8) | (uint64_t) p[7]);+ else+ return (((uint64_t) p[7] << 56) | ((uint64_t) p[6] << 48)+ | ((uint64_t) p[5] << 40) | ((uint64_t) p[4] << 32)+ | ((uint64_t) p[3] << 24) | ((uint64_t) p[2] << 16)+ | ((uint64_t) p[1] << 8) | (uint64_t) p[0]);+}++/* Read an offset from BUF and advance the appropriate number of+ bytes. */++static uint64_t+read_offset (struct dwarf_buf *buf, int is_dwarf64)+{+ if (is_dwarf64)+ return read_uint64 (buf);+ else+ return read_uint32 (buf);+}++/* Read an address from BUF and advance the appropriate number of+ bytes. */++static uint64_t+read_address (struct dwarf_buf *buf, int addrsize)+{+ switch (addrsize)+ {+ case 1:+ return read_byte (buf);+ case 2:+ return read_uint16 (buf);+ case 4:+ return read_uint32 (buf);+ case 8:+ return read_uint64 (buf);+ default:+ dwarf_buf_error (buf, "unrecognized address size", 0);+ return 0;+ }+}++/* Return whether a value is the highest possible address, given the+ address size. */++static int+is_highest_address (uint64_t address, int addrsize)+{+ switch (addrsize)+ {+ case 1:+ return address == (unsigned char) -1;+ case 2:+ return address == (uint16_t) -1;+ case 4:+ return address == (uint32_t) -1;+ case 8:+ return address == (uint64_t) -1;+ default:+ return 0;+ }+}++/* Read an unsigned LEB128 number. */++static uint64_t+read_uleb128 (struct dwarf_buf *buf)+{+ uint64_t ret;+ unsigned int shift;+ int overflow;+ unsigned char b;++ ret = 0;+ shift = 0;+ overflow = 0;+ do+ {+ const unsigned char *p;++ p = buf->buf;+ if (!advance (buf, 1))+ return 0;+ b = *p;+ if (shift < 64)+ ret |= ((uint64_t) (b & 0x7f)) << shift;+ else if (!overflow)+ {+ dwarf_buf_error (buf, "LEB128 overflows uint64_t", 0);+ overflow = 1;+ }+ shift += 7;+ }+ while ((b & 0x80) != 0);++ return ret;+}++/* Read a signed LEB128 number. */++static int64_t+read_sleb128 (struct dwarf_buf *buf)+{+ uint64_t val;+ unsigned int shift;+ int overflow;+ unsigned char b;++ val = 0;+ shift = 0;+ overflow = 0;+ do+ {+ const unsigned char *p;++ p = buf->buf;+ if (!advance (buf, 1))+ return 0;+ b = *p;+ if (shift < 64)+ val |= ((uint64_t) (b & 0x7f)) << shift;+ else if (!overflow)+ {+ dwarf_buf_error (buf, "signed LEB128 overflows uint64_t", 0);+ overflow = 1;+ }+ shift += 7;+ }+ while ((b & 0x80) != 0);++ if ((b & 0x40) != 0 && shift < 64)+ val |= ((uint64_t) -1) << shift;++ return (int64_t) val;+}++/* Return the length of an LEB128 number. */++static size_t+leb128_len (const unsigned char *p)+{+ size_t ret;++ ret = 1;+ while ((*p & 0x80) != 0)+ {+ ++p;+ ++ret;+ }+ return ret;+}++/* Read initial_length from BUF and advance the appropriate number of bytes. */++static uint64_t+read_initial_length (struct dwarf_buf *buf, int *is_dwarf64)+{+ uint64_t len;++ len = read_uint32 (buf);+ if (len == 0xffffffff)+ {+ len = read_uint64 (buf);+ *is_dwarf64 = 1;+ }+ else+ *is_dwarf64 = 0;++ return len;+}++/* Free an abbreviations structure. */++static void+free_abbrevs (struct backtrace_state *state, struct abbrevs *abbrevs,+ backtrace_error_callback error_callback, void *data)+{+ size_t i;++ for (i = 0; i < abbrevs->num_abbrevs; ++i)+ backtrace_free (state, abbrevs->abbrevs[i].attrs,+ abbrevs->abbrevs[i].num_attrs * sizeof (struct attr),+ error_callback, data);+ backtrace_free (state, abbrevs->abbrevs,+ abbrevs->num_abbrevs * sizeof (struct abbrev),+ error_callback, data);+ abbrevs->num_abbrevs = 0;+ abbrevs->abbrevs = NULL;+}++/* Read an attribute value. Returns 1 on success, 0 on failure. If+ the value can be represented as a uint64_t, sets *VAL and sets+ *IS_VALID to 1. We don't try to store the value of other attribute+ forms, because we don't care about them. */++static int+read_attribute (enum dwarf_form form, uint64_t implicit_val,+ struct dwarf_buf *buf, int is_dwarf64, int version,+ int addrsize, const struct dwarf_sections *dwarf_sections,+ struct dwarf_data *altlink, struct attr_val *val)+{+ /* Avoid warnings about val.u.FIELD may be used uninitialized if+ this function is inlined. The warnings aren't valid but can+ occur because the different fields are set and used+ conditionally. */+ memset (val, 0, sizeof *val);++ switch (form)+ {+ case DW_FORM_addr:+ val->encoding = ATTR_VAL_ADDRESS;+ val->u.uint = read_address (buf, addrsize);+ return 1;+ case DW_FORM_block2:+ val->encoding = ATTR_VAL_BLOCK;+ return advance (buf, read_uint16 (buf));+ case DW_FORM_block4:+ val->encoding = ATTR_VAL_BLOCK;+ return advance (buf, read_uint32 (buf));+ case DW_FORM_data2:+ val->encoding = ATTR_VAL_UINT;+ val->u.uint = read_uint16 (buf);+ return 1;+ case DW_FORM_data4:+ val->encoding = ATTR_VAL_UINT;+ val->u.uint = read_uint32 (buf);+ return 1;+ case DW_FORM_data8:+ val->encoding = ATTR_VAL_UINT;+ val->u.uint = read_uint64 (buf);+ return 1;+ case DW_FORM_data16:+ val->encoding = ATTR_VAL_BLOCK;+ return advance (buf, 16);+ case DW_FORM_string:+ val->encoding = ATTR_VAL_STRING;+ val->u.string = read_string (buf);+ return val->u.string == NULL ? 0 : 1;+ case DW_FORM_block:+ val->encoding = ATTR_VAL_BLOCK;+ return advance (buf, read_uleb128 (buf));+ case DW_FORM_block1:+ val->encoding = ATTR_VAL_BLOCK;+ return advance (buf, read_byte (buf));+ case DW_FORM_data1:+ val->encoding = ATTR_VAL_UINT;+ val->u.uint = read_byte (buf);+ return 1;+ case DW_FORM_flag:+ val->encoding = ATTR_VAL_UINT;+ val->u.uint = read_byte (buf);+ return 1;+ case DW_FORM_sdata:+ val->encoding = ATTR_VAL_SINT;+ val->u.sint = read_sleb128 (buf);+ return 1;+ case DW_FORM_strp:+ {+ uint64_t offset;++ offset = read_offset (buf, is_dwarf64);+ if (offset >= dwarf_sections->size[DEBUG_STR])+ {+ dwarf_buf_error (buf, "DW_FORM_strp out of range", 0);+ return 0;+ }+ val->encoding = ATTR_VAL_STRING;+ val->u.string =+ (const char *) dwarf_sections->data[DEBUG_STR] + offset;+ return 1;+ }+ case DW_FORM_line_strp:+ {+ uint64_t offset;++ offset = read_offset (buf, is_dwarf64);+ if (offset >= dwarf_sections->size[DEBUG_LINE_STR])+ {+ dwarf_buf_error (buf, "DW_FORM_line_strp out of range", 0);+ return 0;+ }+ val->encoding = ATTR_VAL_STRING;+ val->u.string =+ (const char *) dwarf_sections->data[DEBUG_LINE_STR] + offset;+ return 1;+ }+ case DW_FORM_udata:+ val->encoding = ATTR_VAL_UINT;+ val->u.uint = read_uleb128 (buf);+ return 1;+ case DW_FORM_ref_addr:+ val->encoding = ATTR_VAL_REF_INFO;+ if (version == 2)+ val->u.uint = read_address (buf, addrsize);+ else+ val->u.uint = read_offset (buf, is_dwarf64);+ return 1;+ case DW_FORM_ref1:+ val->encoding = ATTR_VAL_REF_UNIT;+ val->u.uint = read_byte (buf);+ return 1;+ case DW_FORM_ref2:+ val->encoding = ATTR_VAL_REF_UNIT;+ val->u.uint = read_uint16 (buf);+ return 1;+ case DW_FORM_ref4:+ val->encoding = ATTR_VAL_REF_UNIT;+ val->u.uint = read_uint32 (buf);+ return 1;+ case DW_FORM_ref8:+ val->encoding = ATTR_VAL_REF_UNIT;+ val->u.uint = read_uint64 (buf);+ return 1;+ case DW_FORM_ref_udata:+ val->encoding = ATTR_VAL_REF_UNIT;+ val->u.uint = read_uleb128 (buf);+ return 1;+ case DW_FORM_indirect:+ {+ uint64_t form;++ form = read_uleb128 (buf);+ if (form == DW_FORM_implicit_const)+ {+ dwarf_buf_error (buf,+ "DW_FORM_indirect to DW_FORM_implicit_const",+ 0);+ return 0;+ }+ return read_attribute ((enum dwarf_form) form, 0, buf, is_dwarf64,+ version, addrsize, dwarf_sections, altlink,+ val);+ }+ case DW_FORM_sec_offset:+ val->encoding = ATTR_VAL_REF_SECTION;+ val->u.uint = read_offset (buf, is_dwarf64);+ return 1;+ case DW_FORM_exprloc:+ val->encoding = ATTR_VAL_EXPR;+ return advance (buf, read_uleb128 (buf));+ case DW_FORM_flag_present:+ val->encoding = ATTR_VAL_UINT;+ val->u.uint = 1;+ return 1;+ case DW_FORM_ref_sig8:+ val->encoding = ATTR_VAL_REF_TYPE;+ val->u.uint = read_uint64 (buf);+ return 1;+ case DW_FORM_strx: case DW_FORM_strx1: case DW_FORM_strx2:+ case DW_FORM_strx3: case DW_FORM_strx4:+ {+ uint64_t offset;++ switch (form)+ {+ case DW_FORM_strx:+ offset = read_uleb128 (buf);+ break;+ case DW_FORM_strx1:+ offset = read_byte (buf);+ break;+ case DW_FORM_strx2:+ offset = read_uint16 (buf);+ break;+ case DW_FORM_strx3:+ offset = read_uint24 (buf);+ break;+ case DW_FORM_strx4:+ offset = read_uint32 (buf);+ break;+ default:+ /* This case can't happen. */+ return 0;+ }+ val->encoding = ATTR_VAL_STRING_INDEX;+ val->u.uint = offset;+ return 1;+ }+ case DW_FORM_addrx: case DW_FORM_addrx1: case DW_FORM_addrx2:+ case DW_FORM_addrx3: case DW_FORM_addrx4:+ {+ uint64_t offset;++ switch (form)+ {+ case DW_FORM_addrx:+ offset = read_uleb128 (buf);+ break;+ case DW_FORM_addrx1:+ offset = read_byte (buf);+ break;+ case DW_FORM_addrx2:+ offset = read_uint16 (buf);+ break;+ case DW_FORM_addrx3:+ offset = read_uint24 (buf);+ break;+ case DW_FORM_addrx4:+ offset = read_uint32 (buf);+ break;+ default:+ /* This case can't happen. */+ return 0;+ }+ val->encoding = ATTR_VAL_ADDRESS_INDEX;+ val->u.uint = offset;+ return 1;+ }+ case DW_FORM_ref_sup4:+ val->encoding = ATTR_VAL_REF_SECTION;+ val->u.uint = read_uint32 (buf);+ return 1;+ case DW_FORM_ref_sup8:+ val->encoding = ATTR_VAL_REF_SECTION;+ val->u.uint = read_uint64 (buf);+ return 1;+ case DW_FORM_implicit_const:+ val->encoding = ATTR_VAL_UINT;+ val->u.uint = implicit_val;+ return 1;+ case DW_FORM_loclistx:+ /* We don't distinguish this from DW_FORM_sec_offset. It+ * shouldn't matter since we don't care about loclists. */+ val->encoding = ATTR_VAL_REF_SECTION;+ val->u.uint = read_uleb128 (buf);+ return 1;+ case DW_FORM_rnglistx:+ val->encoding = ATTR_VAL_RNGLISTS_INDEX;+ val->u.uint = read_uleb128 (buf);+ return 1;+ case DW_FORM_GNU_addr_index:+ val->encoding = ATTR_VAL_REF_SECTION;+ val->u.uint = read_uleb128 (buf);+ return 1;+ case DW_FORM_GNU_str_index:+ val->encoding = ATTR_VAL_REF_SECTION;+ val->u.uint = read_uleb128 (buf);+ return 1;+ case DW_FORM_GNU_ref_alt:+ val->u.uint = read_offset (buf, is_dwarf64);+ if (altlink == NULL)+ {+ val->encoding = ATTR_VAL_NONE;+ return 1;+ }+ val->encoding = ATTR_VAL_REF_ALT_INFO;+ return 1;+ case DW_FORM_strp_sup: case DW_FORM_GNU_strp_alt:+ {+ uint64_t offset;++ offset = read_offset (buf, is_dwarf64);+ if (altlink == NULL)+ {+ val->encoding = ATTR_VAL_NONE;+ return 1;+ }+ if (offset >= altlink->dwarf_sections.size[DEBUG_STR])+ {+ dwarf_buf_error (buf, "DW_FORM_strp_sup out of range", 0);+ return 0;+ }+ val->encoding = ATTR_VAL_STRING;+ val->u.string =+ (const char *) altlink->dwarf_sections.data[DEBUG_STR] + offset;+ return 1;+ }+ default:+ dwarf_buf_error (buf, "unrecognized DWARF form", -1);+ return 0;+ }+}++/* If we can determine the value of a string attribute, set *STRING to+ point to the string. Return 1 on success, 0 on error. If we don't+ know the value, we consider that a success, and we don't change+ *STRING. An error is only reported for some sort of out of range+ offset. */++static int+resolve_string (const struct dwarf_sections *dwarf_sections, int is_dwarf64,+ int is_bigendian, uint64_t str_offsets_base,+ const struct attr_val *val,+ backtrace_error_callback error_callback, void *data,+ const char **string)+{+ switch (val->encoding)+ {+ case ATTR_VAL_STRING:+ *string = val->u.string;+ return 1;++ case ATTR_VAL_STRING_INDEX:+ {+ uint64_t offset;+ struct dwarf_buf offset_buf;++ offset = val->u.uint * (is_dwarf64 ? 8 : 4) + str_offsets_base;+ if (offset + (is_dwarf64 ? 8 : 4)+ > dwarf_sections->size[DEBUG_STR_OFFSETS])+ {+ error_callback (data, "DW_FORM_strx value out of range", 0);+ return 0;+ }++ offset_buf.name = ".debug_str_offsets";+ offset_buf.start = dwarf_sections->data[DEBUG_STR_OFFSETS];+ offset_buf.buf = dwarf_sections->data[DEBUG_STR_OFFSETS] + offset;+ offset_buf.left = dwarf_sections->size[DEBUG_STR_OFFSETS] - offset;+ offset_buf.is_bigendian = is_bigendian;+ offset_buf.error_callback = error_callback;+ offset_buf.data = data;+ offset_buf.reported_underflow = 0;++ offset = read_offset (&offset_buf, is_dwarf64);+ if (offset >= dwarf_sections->size[DEBUG_STR])+ {+ dwarf_buf_error (&offset_buf,+ "DW_FORM_strx offset out of range",+ 0);+ return 0;+ }+ *string = (const char *) dwarf_sections->data[DEBUG_STR] + offset;+ return 1;+ }++ default:+ return 1;+ }+}++/* Set *ADDRESS to the real address for a ATTR_VAL_ADDRESS_INDEX.+ Return 1 on success, 0 on error. */++static int+resolve_addr_index (const struct dwarf_sections *dwarf_sections,+ uint64_t addr_base, int addrsize, int is_bigendian,+ uint64_t addr_index,+ backtrace_error_callback error_callback, void *data,+ uintptr_t *address)+{+ uint64_t offset;+ struct dwarf_buf addr_buf;++ offset = addr_index * addrsize + addr_base;+ if (offset + addrsize > dwarf_sections->size[DEBUG_ADDR])+ {+ error_callback (data, "DW_FORM_addrx value out of range", 0);+ return 0;+ }++ addr_buf.name = ".debug_addr";+ addr_buf.start = dwarf_sections->data[DEBUG_ADDR];+ addr_buf.buf = dwarf_sections->data[DEBUG_ADDR] + offset;+ addr_buf.left = dwarf_sections->size[DEBUG_ADDR] - offset;+ addr_buf.is_bigendian = is_bigendian;+ addr_buf.error_callback = error_callback;+ addr_buf.data = data;+ addr_buf.reported_underflow = 0;++ *address = (uintptr_t) read_address (&addr_buf, addrsize);+ return 1;+}++/* Compare a unit offset against a unit for bsearch. */++static int+units_search (const void *vkey, const void *ventry)+{+ const size_t *key = (const size_t *) vkey;+ const struct unit *entry = *((const struct unit *const *) ventry);+ size_t offset;++ offset = *key;+ if (offset < entry->low_offset)+ return -1;+ else if (offset >= entry->high_offset)+ return 1;+ else+ return 0;+}++/* Find a unit in PU containing OFFSET. */++static struct unit *+find_unit (struct unit **pu, size_t units_count, size_t offset)+{+ struct unit **u;+ u = (struct unit**)bsearch (&offset, pu, units_count, sizeof (struct unit *), units_search);+ return u == NULL ? NULL : *u;+}++/* Compare function_addrs for qsort. When ranges are nested, make the+ smallest one sort last. */++static int+function_addrs_compare (const void *v1, const void *v2)+{+ const struct function_addrs *a1 = (const struct function_addrs *) v1;+ const struct function_addrs *a2 = (const struct function_addrs *) v2;++ if (a1->low < a2->low)+ return -1;+ if (a1->low > a2->low)+ return 1;+ if (a1->high < a2->high)+ return 1;+ if (a1->high > a2->high)+ return -1;+ return strcmp (a1->function->name, a2->function->name);+}++/* Compare a PC against a function_addrs for bsearch. We always+ allocate an entra entry at the end of the vector, so that this+ routine can safely look at the next entry. Note that if there are+ multiple ranges containing PC, which one will be returned is+ unpredictable. We compensate for that in dwarf_fileline. */++static int+function_addrs_search (const void *vkey, const void *ventry)+{+ const uintptr_t *key = (const uintptr_t *) vkey;+ const struct function_addrs *entry = (const struct function_addrs *) ventry;+ uintptr_t pc;++ pc = *key;+ if (pc < entry->low)+ return -1;+ else if (pc > (entry + 1)->low)+ return 1;+ else+ return 0;+}++/* Add a new compilation unit address range to a vector. This is+ called via add_ranges. Returns 1 on success, 0 on failure. */++static int+add_unit_addr (struct backtrace_state *state, void *rdata,+ uintptr_t lowpc, uintptr_t highpc,+ backtrace_error_callback error_callback, void *data,+ void *pvec)+{+ struct unit *u = (struct unit *) rdata;+ struct unit_addrs_vector *vec = (struct unit_addrs_vector *) pvec;+ struct unit_addrs *p;++ /* Try to merge with the last entry. */+ if (vec->count > 0)+ {+ p = (struct unit_addrs *) vec->vec.base + (vec->count - 1);+ if ((lowpc == p->high || lowpc == p->high + 1)+ && u == p->u)+ {+ if (highpc > p->high)+ p->high = highpc;+ return 1;+ }+ }++ p = ((struct unit_addrs *)+ backtrace_vector_grow (state, sizeof (struct unit_addrs),+ error_callback, data, &vec->vec));+ if (p == NULL)+ return 0;++ p->low = lowpc;+ p->high = highpc;+ p->u = u;++ ++vec->count;++ return 1;+}++/* Compare unit_addrs for qsort. When ranges are nested, make the+ smallest one sort last. */++static int+unit_addrs_compare (const void *v1, const void *v2)+{+ const struct unit_addrs *a1 = (const struct unit_addrs *) v1;+ const struct unit_addrs *a2 = (const struct unit_addrs *) v2;++ if (a1->low < a2->low)+ return -1;+ if (a1->low > a2->low)+ return 1;+ if (a1->high < a2->high)+ return 1;+ if (a1->high > a2->high)+ return -1;+ if (a1->u->lineoff < a2->u->lineoff)+ return -1;+ if (a1->u->lineoff > a2->u->lineoff)+ return 1;+ return 0;+}++/* Compare a PC against a unit_addrs for bsearch. We always allocate+ an entry entry at the end of the vector, so that this routine can+ safely look at the next entry. Note that if there are multiple+ ranges containing PC, which one will be returned is unpredictable.+ We compensate for that in dwarf_fileline. */++static int+unit_addrs_search (const void *vkey, const void *ventry)+{+ const uintptr_t *key = (const uintptr_t *) vkey;+ const struct unit_addrs *entry = (const struct unit_addrs *) ventry;+ uintptr_t pc;++ pc = *key;+ if (pc < entry->low)+ return -1;+ else if (pc > (entry + 1)->low)+ return 1;+ else+ return 0;+}++/* Sort the line vector by PC. We want a stable sort here to maintain+ the order of lines for the same PC values. Since the sequence is+ being sorted in place, their addresses cannot be relied on to+ maintain stability. That is the purpose of the index member. */++static int+line_compare (const void *v1, const void *v2)+{+ const struct line *ln1 = (const struct line *) v1;+ const struct line *ln2 = (const struct line *) v2;++ if (ln1->pc < ln2->pc)+ return -1;+ else if (ln1->pc > ln2->pc)+ return 1;+ else if (ln1->idx < ln2->idx)+ return -1;+ else if (ln1->idx > ln2->idx)+ return 1;+ else+ return 0;+}++/* Find a PC in a line vector. We always allocate an extra entry at+ the end of the lines vector, so that this routine can safely look+ at the next entry. Note that when there are multiple mappings for+ the same PC value, this will return the last one. */++static int+line_search (const void *vkey, const void *ventry)+{+ const uintptr_t *key = (const uintptr_t *) vkey;+ const struct line *entry = (const struct line *) ventry;+ uintptr_t pc;++ pc = *key;+ if (pc < entry->pc)+ return -1;+ else if (pc >= (entry + 1)->pc)+ return 1;+ else+ return 0;+}++/* Sort the abbrevs by the abbrev code. This function is passed to+ both qsort and bsearch. */++static int+abbrev_compare (const void *v1, const void *v2)+{+ const struct abbrev *a1 = (const struct abbrev *) v1;+ const struct abbrev *a2 = (const struct abbrev *) v2;++ if (a1->code < a2->code)+ return -1;+ else if (a1->code > a2->code)+ return 1;+ else+ {+ /* This really shouldn't happen. It means there are two+ different abbrevs with the same code, and that means we don't+ know which one lookup_abbrev should return. */+ return 0;+ }+}++/* Read the abbreviation table for a compilation unit. Returns 1 on+ success, 0 on failure. */++static int+read_abbrevs (struct backtrace_state *state, uint64_t abbrev_offset,+ const unsigned char *dwarf_abbrev, size_t dwarf_abbrev_size,+ int is_bigendian, backtrace_error_callback error_callback,+ void *data, struct abbrevs *abbrevs)+{+ struct dwarf_buf abbrev_buf;+ struct dwarf_buf count_buf;+ size_t num_abbrevs;++ abbrevs->num_abbrevs = 0;+ abbrevs->abbrevs = NULL;++ if (abbrev_offset >= dwarf_abbrev_size)+ {+ error_callback (data, "abbrev offset out of range", 0);+ return 0;+ }++ abbrev_buf.name = ".debug_abbrev";+ abbrev_buf.start = dwarf_abbrev;+ abbrev_buf.buf = dwarf_abbrev + abbrev_offset;+ abbrev_buf.left = dwarf_abbrev_size - abbrev_offset;+ abbrev_buf.is_bigendian = is_bigendian;+ abbrev_buf.error_callback = error_callback;+ abbrev_buf.data = data;+ abbrev_buf.reported_underflow = 0;++ /* Count the number of abbrevs in this list. */++ count_buf = abbrev_buf;+ num_abbrevs = 0;+ while (read_uleb128 (&count_buf) != 0)+ {+ if (count_buf.reported_underflow)+ return 0;+ ++num_abbrevs;+ // Skip tag.+ read_uleb128 (&count_buf);+ // Skip has_children.+ read_byte (&count_buf);+ // Skip attributes.+ while (read_uleb128 (&count_buf) != 0)+ {+ uint64_t form;++ form = read_uleb128 (&count_buf);+ if ((enum dwarf_form) form == DW_FORM_implicit_const)+ read_sleb128 (&count_buf);+ }+ // Skip form of last attribute.+ read_uleb128 (&count_buf);+ }++ if (count_buf.reported_underflow)+ return 0;++ if (num_abbrevs == 0)+ return 1;++ abbrevs->abbrevs = ((struct abbrev *)+ backtrace_alloc (state,+ num_abbrevs * sizeof (struct abbrev),+ error_callback, data));+ if (abbrevs->abbrevs == NULL)+ return 0;+ abbrevs->num_abbrevs = num_abbrevs;+ memset (abbrevs->abbrevs, 0, num_abbrevs * sizeof (struct abbrev));++ num_abbrevs = 0;+ while (1)+ {+ uint64_t code;+ struct abbrev a;+ size_t num_attrs;+ struct attr *attrs;++ if (abbrev_buf.reported_underflow)+ goto fail;++ code = read_uleb128 (&abbrev_buf);+ if (code == 0)+ break;++ a.code = code;+ a.tag = (enum dwarf_tag) read_uleb128 (&abbrev_buf);+ a.has_children = read_byte (&abbrev_buf);++ count_buf = abbrev_buf;+ num_attrs = 0;+ while (read_uleb128 (&count_buf) != 0)+ {+ uint64_t form;++ ++num_attrs;+ form = read_uleb128 (&count_buf);+ if ((enum dwarf_form) form == DW_FORM_implicit_const)+ read_sleb128 (&count_buf);+ }++ if (num_attrs == 0)+ {+ attrs = NULL;+ read_uleb128 (&abbrev_buf);+ read_uleb128 (&abbrev_buf);+ }+ else+ {+ attrs = ((struct attr *)+ backtrace_alloc (state, num_attrs * sizeof *attrs,+ error_callback, data));+ if (attrs == NULL)+ goto fail;+ num_attrs = 0;+ while (1)+ {+ uint64_t name;+ uint64_t form;++ name = read_uleb128 (&abbrev_buf);+ form = read_uleb128 (&abbrev_buf);+ if (name == 0)+ break;+ attrs[num_attrs].name = (enum dwarf_attribute) name;+ attrs[num_attrs].form = (enum dwarf_form) form;+ if ((enum dwarf_form) form == DW_FORM_implicit_const)+ attrs[num_attrs].val = read_sleb128 (&abbrev_buf);+ else+ attrs[num_attrs].val = 0;+ ++num_attrs;+ }+ }++ a.num_attrs = num_attrs;+ a.attrs = attrs;++ abbrevs->abbrevs[num_abbrevs] = a;+ ++num_abbrevs;+ }++ backtrace_qsort (abbrevs->abbrevs, abbrevs->num_abbrevs,+ sizeof (struct abbrev), abbrev_compare);++ return 1;++ fail:+ free_abbrevs (state, abbrevs, error_callback, data);+ return 0;+}++/* Return the abbrev information for an abbrev code. */++static const struct abbrev *+lookup_abbrev (struct abbrevs *abbrevs, uint64_t code,+ backtrace_error_callback error_callback, void *data)+{+ struct abbrev key;+ void *p;++ /* With GCC, where abbrevs are simply numbered in order, we should+ be able to just look up the entry. */+ if (code - 1 < abbrevs->num_abbrevs+ && abbrevs->abbrevs[code - 1].code == code)+ return &abbrevs->abbrevs[code - 1];++ /* Otherwise we have to search. */+ memset (&key, 0, sizeof key);+ key.code = code;+ p = bsearch (&key, abbrevs->abbrevs, abbrevs->num_abbrevs,+ sizeof (struct abbrev), abbrev_compare);+ if (p == NULL)+ {+ error_callback (data, "invalid abbreviation code", 0);+ return NULL;+ }+ return (const struct abbrev *) p;+}++/* This struct is used to gather address range information while+ reading attributes. We use this while building a mapping from+ address ranges to compilation units and then again while mapping+ from address ranges to function entries. Normally either+ lowpc/highpc is set or ranges is set. */++struct pcrange {+ uintptr_t lowpc; /* The low PC value. */+ int have_lowpc; /* Whether a low PC value was found. */+ int lowpc_is_addr_index; /* Whether lowpc is in .debug_addr. */+ uintptr_t highpc; /* The high PC value. */+ int have_highpc; /* Whether a high PC value was found. */+ int highpc_is_relative; /* Whether highpc is relative to lowpc. */+ int highpc_is_addr_index; /* Whether highpc is in .debug_addr. */+ uint64_t ranges; /* Offset in ranges section. */+ int have_ranges; /* Whether ranges is valid. */+ int ranges_is_index; /* Whether ranges is DW_FORM_rnglistx. */+};++/* Update PCRANGE from an attribute value. */++static void+update_pcrange (const struct attr* attr, const struct attr_val* val,+ struct pcrange *pcrange)+{+ switch (attr->name)+ {+ case DW_AT_low_pc:+ if (val->encoding == ATTR_VAL_ADDRESS)+ {+ pcrange->lowpc = (uintptr_t) val->u.uint;+ pcrange->have_lowpc = 1;+ }+ else if (val->encoding == ATTR_VAL_ADDRESS_INDEX)+ {+ pcrange->lowpc = (uintptr_t) val->u.uint;+ pcrange->have_lowpc = 1;+ pcrange->lowpc_is_addr_index = 1;+ }+ break;++ case DW_AT_high_pc:+ if (val->encoding == ATTR_VAL_ADDRESS)+ {+ pcrange->highpc = (uintptr_t) val->u.uint;+ pcrange->have_highpc = 1;+ }+ else if (val->encoding == ATTR_VAL_UINT)+ {+ pcrange->highpc = (uintptr_t) val->u.uint;+ pcrange->have_highpc = 1;+ pcrange->highpc_is_relative = 1;+ }+ else if (val->encoding == ATTR_VAL_ADDRESS_INDEX)+ {+ pcrange->highpc = (uintptr_t) val->u.uint;+ pcrange->have_highpc = 1;+ pcrange->highpc_is_addr_index = 1;+ }+ break;++ case DW_AT_ranges:+ if (val->encoding == ATTR_VAL_UINT+ || val->encoding == ATTR_VAL_REF_SECTION)+ {+ pcrange->ranges = val->u.uint;+ pcrange->have_ranges = 1;+ }+ else if (val->encoding == ATTR_VAL_RNGLISTS_INDEX)+ {+ pcrange->ranges = val->u.uint;+ pcrange->have_ranges = 1;+ pcrange->ranges_is_index = 1;+ }+ break;++ default:+ break;+ }+}++/* Call ADD_RANGE for a low/high PC pair. Returns 1 on success, 0 on+ error. */++static int+add_low_high_range (struct backtrace_state *state,+ const struct dwarf_sections *dwarf_sections,+ struct libbacktrace_base_address base_address,+ int is_bigendian, struct unit *u,+ const struct pcrange *pcrange,+ int (*add_range) (struct backtrace_state *state,+ void *rdata, uintptr_t lowpc,+ uintptr_t highpc,+ backtrace_error_callback error_callback,+ void *data, void *vec),+ void *rdata,+ backtrace_error_callback error_callback, void *data,+ void *vec)+{+ uintptr_t lowpc;+ uintptr_t highpc;++ lowpc = pcrange->lowpc;+ if (pcrange->lowpc_is_addr_index)+ {+ if (!resolve_addr_index (dwarf_sections, u->addr_base, u->addrsize,+ is_bigendian, lowpc, error_callback, data,+ &lowpc))+ return 0;+ }++ highpc = pcrange->highpc;+ if (pcrange->highpc_is_addr_index)+ {+ if (!resolve_addr_index (dwarf_sections, u->addr_base, u->addrsize,+ is_bigendian, highpc, error_callback, data,+ &highpc))+ return 0;+ }+ if (pcrange->highpc_is_relative)+ highpc += lowpc;++ /* Add in the base address of the module when recording PC values,+ so that we can look up the PC directly. */+ lowpc = libbacktrace_add_base (lowpc, base_address);+ highpc = libbacktrace_add_base (highpc, base_address);++ return add_range (state, rdata, lowpc, highpc, error_callback, data, vec);+}++/* Call ADD_RANGE for each range read from .debug_ranges, as used in+ DWARF versions 2 through 4. */++static int+add_ranges_from_ranges (+ struct backtrace_state *state,+ const struct dwarf_sections *dwarf_sections,+ struct libbacktrace_base_address base_address, int is_bigendian,+ struct unit *u, uintptr_t base,+ const struct pcrange *pcrange,+ int (*add_range) (struct backtrace_state *state, void *rdata,+ uintptr_t lowpc, uintptr_t highpc,+ backtrace_error_callback error_callback, void *data,+ void *vec),+ void *rdata,+ backtrace_error_callback error_callback, void *data,+ void *vec)+{+ struct dwarf_buf ranges_buf;++ if (pcrange->ranges >= dwarf_sections->size[DEBUG_RANGES])+ {+ error_callback (data, "ranges offset out of range", 0);+ return 0;+ }++ ranges_buf.name = ".debug_ranges";+ ranges_buf.start = dwarf_sections->data[DEBUG_RANGES];+ ranges_buf.buf = dwarf_sections->data[DEBUG_RANGES] + pcrange->ranges;+ ranges_buf.left = dwarf_sections->size[DEBUG_RANGES] - pcrange->ranges;+ ranges_buf.is_bigendian = is_bigendian;+ ranges_buf.error_callback = error_callback;+ ranges_buf.data = data;+ ranges_buf.reported_underflow = 0;++ while (1)+ {+ uint64_t low;+ uint64_t high;++ if (ranges_buf.reported_underflow)+ return 0;++ low = read_address (&ranges_buf, u->addrsize);+ high = read_address (&ranges_buf, u->addrsize);++ if (low == 0 && high == 0)+ break;++ if (is_highest_address (low, u->addrsize))+ base = (uintptr_t) high;+ else+ {+ uintptr_t rl, rh;++ rl = libbacktrace_add_base ((uintptr_t) low + base, base_address);+ rh = libbacktrace_add_base ((uintptr_t) high + base, base_address);+ if (!add_range (state, rdata, rl, rh, error_callback, data, vec))+ return 0;+ }+ }++ if (ranges_buf.reported_underflow)+ return 0;++ return 1;+}++/* Call ADD_RANGE for each range read from .debug_rnglists, as used in+ DWARF version 5. */++static int+add_ranges_from_rnglists (+ struct backtrace_state *state,+ const struct dwarf_sections *dwarf_sections,+ struct libbacktrace_base_address base_address, int is_bigendian,+ struct unit *u, uintptr_t base,+ const struct pcrange *pcrange,+ int (*add_range) (struct backtrace_state *state, void *rdata,+ uintptr_t lowpc, uintptr_t highpc,+ backtrace_error_callback error_callback, void *data,+ void *vec),+ void *rdata,+ backtrace_error_callback error_callback, void *data,+ void *vec)+{+ uint64_t offset;+ struct dwarf_buf rnglists_buf;++ if (!pcrange->ranges_is_index)+ offset = pcrange->ranges;+ else+ offset = u->rnglists_base + pcrange->ranges * (u->is_dwarf64 ? 8 : 4);+ if (offset >= dwarf_sections->size[DEBUG_RNGLISTS])+ {+ error_callback (data, "rnglists offset out of range", 0);+ return 0;+ }++ rnglists_buf.name = ".debug_rnglists";+ rnglists_buf.start = dwarf_sections->data[DEBUG_RNGLISTS];+ rnglists_buf.buf = dwarf_sections->data[DEBUG_RNGLISTS] + offset;+ rnglists_buf.left = dwarf_sections->size[DEBUG_RNGLISTS] - offset;+ rnglists_buf.is_bigendian = is_bigendian;+ rnglists_buf.error_callback = error_callback;+ rnglists_buf.data = data;+ rnglists_buf.reported_underflow = 0;++ if (pcrange->ranges_is_index)+ {+ offset = read_offset (&rnglists_buf, u->is_dwarf64);+ offset += u->rnglists_base;+ if (offset >= dwarf_sections->size[DEBUG_RNGLISTS])+ {+ error_callback (data, "rnglists index offset out of range", 0);+ return 0;+ }+ rnglists_buf.buf = dwarf_sections->data[DEBUG_RNGLISTS] + offset;+ rnglists_buf.left = dwarf_sections->size[DEBUG_RNGLISTS] - offset;+ }++ while (1)+ {+ unsigned char rle;++ rle = read_byte (&rnglists_buf);+ if (rle == DW_RLE_end_of_list)+ break;+ switch (rle)+ {+ case DW_RLE_base_addressx:+ {+ uint64_t index;++ index = read_uleb128 (&rnglists_buf);+ if (!resolve_addr_index (dwarf_sections, u->addr_base,+ u->addrsize, is_bigendian, index,+ error_callback, data, &base))+ return 0;+ }+ break;++ case DW_RLE_startx_endx:+ {+ uint64_t index;+ uintptr_t low;+ uintptr_t high;++ index = read_uleb128 (&rnglists_buf);+ if (!resolve_addr_index (dwarf_sections, u->addr_base,+ u->addrsize, is_bigendian, index,+ error_callback, data, &low))+ return 0;+ index = read_uleb128 (&rnglists_buf);+ if (!resolve_addr_index (dwarf_sections, u->addr_base,+ u->addrsize, is_bigendian, index,+ error_callback, data, &high))+ return 0;+ if (!add_range (state, rdata,+ libbacktrace_add_base (low, base_address),+ libbacktrace_add_base (high, base_address),+ error_callback, data, vec))+ return 0;+ }+ break;++ case DW_RLE_startx_length:+ {+ uint64_t index;+ uintptr_t low;+ uintptr_t length;++ index = read_uleb128 (&rnglists_buf);+ if (!resolve_addr_index (dwarf_sections, u->addr_base,+ u->addrsize, is_bigendian, index,+ error_callback, data, &low))+ return 0;+ length = read_uleb128 (&rnglists_buf);+ low = libbacktrace_add_base (low, base_address);+ if (!add_range (state, rdata, low, low + length,+ error_callback, data, vec))+ return 0;+ }+ break;++ case DW_RLE_offset_pair:+ {+ uint64_t low;+ uint64_t high;++ low = read_uleb128 (&rnglists_buf);+ high = read_uleb128 (&rnglists_buf);+ if (!add_range (state, rdata,+ libbacktrace_add_base (low + base, base_address),+ libbacktrace_add_base (high + base, base_address),+ error_callback, data, vec))+ return 0;+ }+ break;++ case DW_RLE_base_address:+ base = (uintptr_t) read_address (&rnglists_buf, u->addrsize);+ break;++ case DW_RLE_start_end:+ {+ uintptr_t low;+ uintptr_t high;++ low = (uintptr_t) read_address (&rnglists_buf, u->addrsize);+ high = (uintptr_t) read_address (&rnglists_buf, u->addrsize);+ if (!add_range (state, rdata,+ libbacktrace_add_base (low, base_address),+ libbacktrace_add_base (high, base_address),+ error_callback, data, vec))+ return 0;+ }+ break;++ case DW_RLE_start_length:+ {+ uintptr_t low;+ uintptr_t length;++ low = (uintptr_t) read_address (&rnglists_buf, u->addrsize);+ length = (uintptr_t) read_uleb128 (&rnglists_buf);+ low = libbacktrace_add_base (low, base_address);+ if (!add_range (state, rdata, low, low + length,+ error_callback, data, vec))+ return 0;+ }+ break;++ default:+ dwarf_buf_error (&rnglists_buf, "unrecognized DW_RLE value", -1);+ return 0;+ }+ }++ if (rnglists_buf.reported_underflow)+ return 0;++ return 1;+}++/* Call ADD_RANGE for each lowpc/highpc pair in PCRANGE. RDATA is+ passed to ADD_RANGE, and is either a struct unit * or a struct+ function *. VEC is the vector we are adding ranges to, and is+ either a struct unit_addrs_vector * or a struct function_vector *.+ Returns 1 on success, 0 on error. */++static int+add_ranges (struct backtrace_state *state,+ const struct dwarf_sections *dwarf_sections,+ struct libbacktrace_base_address base_address, int is_bigendian,+ struct unit *u, uintptr_t base, const struct pcrange *pcrange,+ int (*add_range) (struct backtrace_state *state, void *rdata, + uintptr_t lowpc, uintptr_t highpc,+ backtrace_error_callback error_callback,+ void *data, void *vec),+ void *rdata,+ backtrace_error_callback error_callback, void *data,+ void *vec)+{+ if (pcrange->have_lowpc && pcrange->have_highpc)+ return add_low_high_range (state, dwarf_sections, base_address,+ is_bigendian, u, pcrange, add_range, rdata,+ error_callback, data, vec);++ if (!pcrange->have_ranges)+ {+ /* Did not find any address ranges to add. */+ return 1;+ }++ if (u->version < 5)+ return add_ranges_from_ranges (state, dwarf_sections, base_address,+ is_bigendian, u, base, pcrange, add_range,+ rdata, error_callback, data, vec);+ else+ return add_ranges_from_rnglists (state, dwarf_sections, base_address,+ is_bigendian, u, base, pcrange, add_range,+ rdata, error_callback, data, vec);+}++/* Find the address range covered by a compilation unit, reading from+ UNIT_BUF and adding values to U. Returns 1 if all data could be+ read, 0 if there is some error. */++static int+find_address_ranges (struct backtrace_state *state,+ struct libbacktrace_base_address base_address,+ struct dwarf_buf *unit_buf,+ const struct dwarf_sections *dwarf_sections,+ int is_bigendian, struct dwarf_data *altlink,+ backtrace_error_callback error_callback, void *data,+ struct unit *u, struct unit_addrs_vector *addrs,+ enum dwarf_tag *unit_tag)+{+ while (unit_buf->left > 0)+ {+ uint64_t code;+ const struct abbrev *abbrev;+ struct pcrange pcrange;+ struct attr_val name_val;+ int have_name_val;+ struct attr_val comp_dir_val;+ int have_comp_dir_val;+ size_t i;++ code = read_uleb128 (unit_buf);+ if (code == 0)+ return 1;++ abbrev = lookup_abbrev (&u->abbrevs, code, error_callback, data);+ if (abbrev == NULL)+ return 0;++ if (unit_tag != NULL)+ *unit_tag = abbrev->tag;++ memset (&pcrange, 0, sizeof pcrange);+ memset (&name_val, 0, sizeof name_val);+ have_name_val = 0;+ memset (&comp_dir_val, 0, sizeof comp_dir_val);+ have_comp_dir_val = 0;+ for (i = 0; i < abbrev->num_attrs; ++i)+ {+ struct attr_val val;++ if (!read_attribute (abbrev->attrs[i].form, abbrev->attrs[i].val,+ unit_buf, u->is_dwarf64, u->version,+ u->addrsize, dwarf_sections, altlink, &val))+ return 0;++ switch (abbrev->attrs[i].name)+ {+ case DW_AT_low_pc: case DW_AT_high_pc: case DW_AT_ranges:+ update_pcrange (&abbrev->attrs[i], &val, &pcrange);+ break;++ case DW_AT_stmt_list:+ if ((abbrev->tag == DW_TAG_compile_unit+ || abbrev->tag == DW_TAG_skeleton_unit)+ && (val.encoding == ATTR_VAL_UINT+ || val.encoding == ATTR_VAL_REF_SECTION))+ u->lineoff = val.u.uint;+ break;++ case DW_AT_name:+ if (abbrev->tag == DW_TAG_compile_unit+ || abbrev->tag == DW_TAG_skeleton_unit)+ {+ name_val = val;+ have_name_val = 1;+ }+ break;++ case DW_AT_comp_dir:+ if (abbrev->tag == DW_TAG_compile_unit+ || abbrev->tag == DW_TAG_skeleton_unit)+ {+ comp_dir_val = val;+ have_comp_dir_val = 1;+ }+ break;++ case DW_AT_str_offsets_base:+ if ((abbrev->tag == DW_TAG_compile_unit+ || abbrev->tag == DW_TAG_skeleton_unit)+ && val.encoding == ATTR_VAL_REF_SECTION)+ u->str_offsets_base = val.u.uint;+ break;++ case DW_AT_addr_base:+ if ((abbrev->tag == DW_TAG_compile_unit+ || abbrev->tag == DW_TAG_skeleton_unit)+ && val.encoding == ATTR_VAL_REF_SECTION)+ u->addr_base = val.u.uint;+ break;++ case DW_AT_rnglists_base:+ if ((abbrev->tag == DW_TAG_compile_unit+ || abbrev->tag == DW_TAG_skeleton_unit)+ && val.encoding == ATTR_VAL_REF_SECTION)+ u->rnglists_base = val.u.uint;+ break;++ default:+ break;+ }+ }++ // Resolve strings after we're sure that we have seen+ // DW_AT_str_offsets_base.+ if (have_name_val)+ {+ if (!resolve_string (dwarf_sections, u->is_dwarf64, is_bigendian,+ u->str_offsets_base, &name_val,+ error_callback, data, &u->filename))+ return 0;+ }+ if (have_comp_dir_val)+ {+ if (!resolve_string (dwarf_sections, u->is_dwarf64, is_bigendian,+ u->str_offsets_base, &comp_dir_val,+ error_callback, data, &u->comp_dir))+ return 0;+ }++ if (abbrev->tag == DW_TAG_compile_unit+ || abbrev->tag == DW_TAG_subprogram+ || abbrev->tag == DW_TAG_skeleton_unit)+ {+ if (!add_ranges (state, dwarf_sections, base_address,+ is_bigendian, u, pcrange.lowpc, &pcrange,+ add_unit_addr, (void *) u, error_callback, data,+ (void *) addrs))+ return 0;++ /* If we found the PC range in the DW_TAG_compile_unit or+ DW_TAG_skeleton_unit, we can stop now. */+ if ((abbrev->tag == DW_TAG_compile_unit+ || abbrev->tag == DW_TAG_skeleton_unit)+ && (pcrange.have_ranges+ || (pcrange.have_lowpc && pcrange.have_highpc)))+ return 1;+ }++ if (abbrev->has_children)+ {+ if (!find_address_ranges (state, base_address, unit_buf,+ dwarf_sections, is_bigendian, altlink,+ error_callback, data, u, addrs, NULL))+ return 0;+ }+ }++ return 1;+}++/* Build a mapping from address ranges to the compilation units where+ the line number information for that range can be found. Returns 1+ on success, 0 on failure. */++static int+build_address_map (struct backtrace_state *state,+ struct libbacktrace_base_address base_address,+ const struct dwarf_sections *dwarf_sections,+ int is_bigendian, struct dwarf_data *altlink,+ backtrace_error_callback error_callback, void *data,+ struct unit_addrs_vector *addrs,+ struct unit_vector *unit_vec)+{+ struct dwarf_buf info;+ struct backtrace_vector units;+ size_t units_count;+ size_t i;+ struct unit **pu;+ size_t unit_offset = 0;+ struct unit_addrs *pa;++ memset (&addrs->vec, 0, sizeof addrs->vec);+ memset (&unit_vec->vec, 0, sizeof unit_vec->vec);+ addrs->count = 0;+ unit_vec->count = 0;++ /* Read through the .debug_info section. FIXME: Should we use the+ .debug_aranges section? gdb and addr2line don't use it, but I'm+ not sure why. */++ info.name = ".debug_info";+ info.start = dwarf_sections->data[DEBUG_INFO];+ info.buf = info.start;+ info.left = dwarf_sections->size[DEBUG_INFO];+ info.is_bigendian = is_bigendian;+ info.error_callback = error_callback;+ info.data = data;+ info.reported_underflow = 0;++ memset (&units, 0, sizeof units);+ units_count = 0;++ while (info.left > 0)+ {+ const unsigned char *unit_data_start;+ uint64_t len;+ int is_dwarf64;+ struct dwarf_buf unit_buf;+ int version;+ int unit_type;+ uint64_t abbrev_offset;+ int addrsize;+ struct unit *u;+ enum dwarf_tag unit_tag;++ if (info.reported_underflow)+ goto fail;++ unit_data_start = info.buf;++ len = read_initial_length (&info, &is_dwarf64);+ unit_buf = info;+ unit_buf.left = len;++ if (!advance (&info, len))+ goto fail;++ version = read_uint16 (&unit_buf);+ if (version < 2 || version > 5)+ {+ dwarf_buf_error (&unit_buf, "unrecognized DWARF version", -1);+ goto fail;+ }++ if (version < 5)+ unit_type = 0;+ else+ {+ unit_type = read_byte (&unit_buf);+ if (unit_type == DW_UT_type || unit_type == DW_UT_split_type)+ {+ /* This unit doesn't have anything we need. */+ continue;+ }+ }++ pu = ((struct unit **)+ backtrace_vector_grow (state, sizeof (struct unit *),+ error_callback, data, &units));+ if (pu == NULL)+ goto fail;++ u = ((struct unit *)+ backtrace_alloc (state, sizeof *u, error_callback, data));+ if (u == NULL)+ goto fail;++ *pu = u;+ ++units_count;++ if (version < 5)+ addrsize = 0; /* Set below. */+ else+ addrsize = read_byte (&unit_buf);++ memset (&u->abbrevs, 0, sizeof u->abbrevs);+ abbrev_offset = read_offset (&unit_buf, is_dwarf64);+ if (!read_abbrevs (state, abbrev_offset,+ dwarf_sections->data[DEBUG_ABBREV],+ dwarf_sections->size[DEBUG_ABBREV],+ is_bigendian, error_callback, data, &u->abbrevs))+ goto fail;++ if (version < 5)+ addrsize = read_byte (&unit_buf);++ switch (unit_type)+ {+ case 0:+ break;+ case DW_UT_compile: case DW_UT_partial:+ break;+ case DW_UT_skeleton: case DW_UT_split_compile:+ read_uint64 (&unit_buf); /* dwo_id */+ break;+ default:+ break;+ }++ u->low_offset = unit_offset;+ unit_offset += len + (is_dwarf64 ? 12 : 4);+ u->high_offset = unit_offset;+ u->unit_data = unit_buf.buf;+ u->unit_data_len = unit_buf.left;+ u->unit_data_offset = unit_buf.buf - unit_data_start;+ u->version = version;+ u->is_dwarf64 = is_dwarf64;+ u->addrsize = addrsize;+ u->filename = NULL;+ u->comp_dir = NULL;+ u->abs_filename = NULL;+ u->lineoff = 0;+ u->str_offsets_base = 0;+ u->addr_base = 0;+ u->rnglists_base = 0;++ /* The actual line number mappings will be read as needed. */+ u->lines = NULL;+ u->lines_count = 0;+ u->function_addrs = NULL;+ u->function_addrs_count = 0;++ if (!find_address_ranges (state, base_address, &unit_buf, dwarf_sections,+ is_bigendian, altlink, error_callback, data,+ u, addrs, &unit_tag))+ goto fail;++ if (unit_buf.reported_underflow)+ goto fail;+ }+ if (info.reported_underflow)+ goto fail;++ /* Add a trailing addrs entry, but don't include it in addrs->count. */+ pa = ((struct unit_addrs *)+ backtrace_vector_grow (state, sizeof (struct unit_addrs),+ error_callback, data, &addrs->vec));+ if (pa == NULL)+ goto fail;+ pa->low = 0;+ --pa->low;+ pa->high = pa->low;+ pa->u = NULL;++ unit_vec->vec = units;+ unit_vec->count = units_count;+ return 1;++ fail:+ if (units_count > 0)+ {+ pu = (struct unit **) units.base;+ for (i = 0; i < units_count; i++)+ {+ free_abbrevs (state, &pu[i]->abbrevs, error_callback, data);+ backtrace_free (state, pu[i], sizeof **pu, error_callback, data);+ }+ backtrace_vector_free (state, &units, error_callback, data);+ }+ if (addrs->count > 0)+ {+ backtrace_vector_free (state, &addrs->vec, error_callback, data);+ addrs->count = 0;+ }+ return 0;+}++/* Add a new mapping to the vector of line mappings that we are+ building. Returns 1 on success, 0 on failure. */++static int+add_line (struct backtrace_state *state, struct dwarf_data *ddata,+ uintptr_t pc, const char *filename, int lineno,+ backtrace_error_callback error_callback, void *data,+ struct line_vector *vec)+{+ struct line *ln;++ /* If we are adding the same mapping, ignore it. This can happen+ when using discriminators. */+ if (vec->count > 0)+ {+ ln = (struct line *) vec->vec.base + (vec->count - 1);+ if (pc == ln->pc && filename == ln->filename && lineno == ln->lineno)+ return 1;+ }++ ln = ((struct line *)+ backtrace_vector_grow (state, sizeof (struct line), error_callback,+ data, &vec->vec));+ if (ln == NULL)+ return 0;++ /* Add in the base address here, so that we can look up the PC+ directly. */+ ln->pc = libbacktrace_add_base (pc, ddata->base_address);++ ln->filename = filename;+ ln->lineno = lineno;+ ln->idx = vec->count;++ ++vec->count;++ return 1;+}++/* Free the line header information. */++static void+free_line_header (struct backtrace_state *state, struct line_header *hdr,+ backtrace_error_callback error_callback, void *data)+{+ if (hdr->dirs_count != 0)+ backtrace_free (state, hdr->dirs, hdr->dirs_count * sizeof (const char *),+ error_callback, data);+ backtrace_free (state, hdr->filenames,+ hdr->filenames_count * sizeof (char *),+ error_callback, data);+}++/* Read the directories and file names for a line header for version+ 2, setting fields in HDR. Return 1 on success, 0 on failure. */++static int+read_v2_paths (struct backtrace_state *state, struct unit *u,+ struct dwarf_buf *hdr_buf, struct line_header *hdr)+{+ const unsigned char *p;+ const unsigned char *pend;+ size_t i;++ /* Count the number of directory entries. */+ hdr->dirs_count = 0;+ p = hdr_buf->buf;+ pend = p + hdr_buf->left;+ while (p < pend && *p != '\0')+ {+ p += strnlen((const char *) p, pend - p) + 1;+ ++hdr->dirs_count;+ }++ /* The index of the first entry in the list of directories is 1. Index 0 is+ used for the current directory of the compilation. To simplify index+ handling, we set entry 0 to the compilation unit directory. */+ ++hdr->dirs_count;+ hdr->dirs = ((const char **)+ backtrace_alloc (state,+ hdr->dirs_count * sizeof (const char *),+ hdr_buf->error_callback,+ hdr_buf->data));+ if (hdr->dirs == NULL)+ return 0;++ hdr->dirs[0] = u->comp_dir;+ i = 1;+ while (*hdr_buf->buf != '\0')+ {+ if (hdr_buf->reported_underflow)+ return 0;++ hdr->dirs[i] = read_string (hdr_buf);+ if (hdr->dirs[i] == NULL)+ return 0;+ ++i;+ }+ if (!advance (hdr_buf, 1))+ return 0;++ /* Count the number of file entries. */+ hdr->filenames_count = 0;+ p = hdr_buf->buf;+ pend = p + hdr_buf->left;+ while (p < pend && *p != '\0')+ {+ p += strnlen ((const char *) p, pend - p) + 1;+ p += leb128_len (p);+ p += leb128_len (p);+ p += leb128_len (p);+ ++hdr->filenames_count;+ }++ /* The index of the first entry in the list of file names is 1. Index 0 is+ used for the DW_AT_name of the compilation unit. To simplify index+ handling, we set entry 0 to the compilation unit file name. */+ ++hdr->filenames_count;+ hdr->filenames = ((const char **)+ backtrace_alloc (state,+ hdr->filenames_count * sizeof (char *),+ hdr_buf->error_callback,+ hdr_buf->data));+ if (hdr->filenames == NULL)+ return 0;+ hdr->filenames[0] = u->filename;+ i = 1;+ while (*hdr_buf->buf != '\0')+ {+ const char *filename;+ uint64_t dir_index;++ if (hdr_buf->reported_underflow)+ return 0;++ filename = read_string (hdr_buf);+ if (filename == NULL)+ return 0;+ dir_index = read_uleb128 (hdr_buf);+ if (IS_ABSOLUTE_PATH (filename)+ || (dir_index < hdr->dirs_count && hdr->dirs[dir_index] == NULL))+ hdr->filenames[i] = filename;+ else+ {+ const char *dir;+ size_t dir_len;+ size_t filename_len;+ char *s;++ if (dir_index < hdr->dirs_count)+ dir = hdr->dirs[dir_index];+ else+ {+ dwarf_buf_error (hdr_buf,+ ("invalid directory index in "+ "line number program header"),+ 0);+ return 0;+ }+ dir_len = strlen (dir);+ filename_len = strlen (filename);+ s = ((char *) backtrace_alloc (state, dir_len + filename_len + 2,+ hdr_buf->error_callback,+ hdr_buf->data));+ if (s == NULL)+ return 0;+ memcpy (s, dir, dir_len);+ /* FIXME: If we are on a DOS-based file system, and the+ directory or the file name use backslashes, then we+ should use a backslash here. */+ s[dir_len] = '/';+ memcpy (s + dir_len + 1, filename, filename_len + 1);+ hdr->filenames[i] = s;+ }++ /* Ignore the modification time and size. */+ read_uleb128 (hdr_buf);+ read_uleb128 (hdr_buf);++ ++i;+ }++ return 1;+}++/* Read a single version 5 LNCT entry for a directory or file name in a+ line header. Sets *STRING to the resulting name, ignoring other+ data. Return 1 on success, 0 on failure. */++static int+read_lnct (struct backtrace_state *state, struct dwarf_data *ddata,+ struct unit *u, struct dwarf_buf *hdr_buf,+ const struct line_header *hdr, size_t formats_count,+ const struct line_header_format *formats, const char **string)+{+ size_t i;+ const char *dir;+ const char *path;++ dir = NULL;+ path = NULL;+ for (i = 0; i < formats_count; i++)+ {+ struct attr_val val;++ if (!read_attribute (formats[i].form, 0, hdr_buf, u->is_dwarf64,+ u->version, hdr->addrsize, &ddata->dwarf_sections,+ ddata->altlink, &val))+ return 0;+ switch (formats[i].lnct)+ {+ case DW_LNCT_path:+ if (!resolve_string (&ddata->dwarf_sections, u->is_dwarf64,+ ddata->is_bigendian, u->str_offsets_base,+ &val, hdr_buf->error_callback, hdr_buf->data,+ &path))+ return 0;+ break;+ case DW_LNCT_directory_index:+ if (val.encoding == ATTR_VAL_UINT)+ {+ if (val.u.uint >= hdr->dirs_count)+ {+ dwarf_buf_error (hdr_buf,+ ("invalid directory index in "+ "line number program header"),+ 0);+ return 0;+ }+ dir = hdr->dirs[val.u.uint];+ }+ break;+ default:+ /* We don't care about timestamps or sizes or hashes. */+ break;+ }+ }++ if (path == NULL)+ {+ dwarf_buf_error (hdr_buf,+ "missing file name in line number program header",+ 0);+ return 0;+ }++ if (dir == NULL)+ *string = path;+ else+ {+ size_t dir_len;+ size_t path_len;+ char *s;++ dir_len = strlen (dir);+ path_len = strlen (path);+ s = (char *) backtrace_alloc (state, dir_len + path_len + 2,+ hdr_buf->error_callback, hdr_buf->data);+ if (s == NULL)+ return 0;+ memcpy (s, dir, dir_len);+ /* FIXME: If we are on a DOS-based file system, and the+ directory or the path name use backslashes, then we should+ use a backslash here. */+ s[dir_len] = '/';+ memcpy (s + dir_len + 1, path, path_len + 1);+ *string = s;+ }++ return 1;+}++/* Read a set of DWARF 5 line header format entries, setting *PCOUNT+ and *PPATHS. Return 1 on success, 0 on failure. */++static int+read_line_header_format_entries (struct backtrace_state *state,+ struct dwarf_data *ddata,+ struct unit *u,+ struct dwarf_buf *hdr_buf,+ struct line_header *hdr,+ size_t *pcount,+ const char ***ppaths)+{+ size_t formats_count;+ struct line_header_format *formats;+ size_t paths_count;+ const char **paths;+ size_t i;+ int ret;++ formats_count = read_byte (hdr_buf);+ if (formats_count == 0)+ formats = NULL;+ else+ {+ formats = ((struct line_header_format *)+ backtrace_alloc (state,+ (formats_count+ * sizeof (struct line_header_format)),+ hdr_buf->error_callback,+ hdr_buf->data));+ if (formats == NULL)+ return 0;++ for (i = 0; i < formats_count; i++)+ {+ formats[i].lnct = (int) read_uleb128(hdr_buf);+ formats[i].form = (enum dwarf_form) read_uleb128 (hdr_buf);+ }+ }++ paths_count = read_uleb128 (hdr_buf);+ if (paths_count == 0)+ {+ *pcount = 0;+ *ppaths = NULL;+ ret = 1;+ goto exit;+ }++ paths = ((const char **)+ backtrace_alloc (state, paths_count * sizeof (const char *),+ hdr_buf->error_callback, hdr_buf->data));+ if (paths == NULL)+ {+ ret = 0;+ goto exit;+ }+ for (i = 0; i < paths_count; i++)+ {+ if (!read_lnct (state, ddata, u, hdr_buf, hdr, formats_count,+ formats, &paths[i]))+ {+ backtrace_free (state, paths,+ paths_count * sizeof (const char *),+ hdr_buf->error_callback, hdr_buf->data);+ ret = 0;+ goto exit;+ }+ }++ *pcount = paths_count;+ *ppaths = paths;++ ret = 1;++ exit:+ if (formats != NULL)+ backtrace_free (state, formats,+ formats_count * sizeof (struct line_header_format),+ hdr_buf->error_callback, hdr_buf->data);++ return ret;+}++/* Read the line header. Return 1 on success, 0 on failure. */++static int+read_line_header (struct backtrace_state *state, struct dwarf_data *ddata,+ struct unit *u, int is_dwarf64, struct dwarf_buf *line_buf,+ struct line_header *hdr)+{+ uint64_t hdrlen;+ struct dwarf_buf hdr_buf;++ hdr->version = read_uint16 (line_buf);+ if (hdr->version < 2 || hdr->version > 5)+ {+ dwarf_buf_error (line_buf, "unsupported line number version", -1);+ return 0;+ }++ if (hdr->version < 5)+ hdr->addrsize = u->addrsize;+ else+ {+ hdr->addrsize = read_byte (line_buf);+ /* We could support a non-zero segment_selector_size but I doubt+ we'll ever see it. */+ if (read_byte (line_buf) != 0)+ {+ dwarf_buf_error (line_buf,+ "non-zero segment_selector_size not supported",+ -1);+ return 0;+ }+ }++ hdrlen = read_offset (line_buf, is_dwarf64);++ hdr_buf = *line_buf;+ hdr_buf.left = hdrlen;++ if (!advance (line_buf, hdrlen))+ return 0;++ hdr->min_insn_len = read_byte (&hdr_buf);+ if (hdr->version < 4)+ hdr->max_ops_per_insn = 1;+ else+ hdr->max_ops_per_insn = read_byte (&hdr_buf);++ /* We don't care about default_is_stmt. */+ read_byte (&hdr_buf);++ hdr->line_base = read_sbyte (&hdr_buf);+ hdr->line_range = read_byte (&hdr_buf);++ hdr->opcode_base = read_byte (&hdr_buf);+ hdr->opcode_lengths = hdr_buf.buf;+ if (!advance (&hdr_buf, hdr->opcode_base - 1))+ return 0;++ if (hdr->version < 5)+ {+ if (!read_v2_paths (state, u, &hdr_buf, hdr))+ return 0;+ }+ else+ {+ if (!read_line_header_format_entries (state, ddata, u, &hdr_buf, hdr,+ &hdr->dirs_count,+ &hdr->dirs))+ return 0;+ if (!read_line_header_format_entries (state, ddata, u, &hdr_buf, hdr,+ &hdr->filenames_count,+ &hdr->filenames))+ return 0;+ }++ if (hdr_buf.reported_underflow)+ return 0;++ return 1;+}++/* Read the line program, adding line mappings to VEC. Return 1 on+ success, 0 on failure. */++static int+read_line_program (struct backtrace_state *state, struct dwarf_data *ddata,+ const struct line_header *hdr, struct dwarf_buf *line_buf,+ struct line_vector *vec)+{+ uint64_t address;+ unsigned int op_index;+ const char *reset_filename;+ const char *filename;+ int lineno;++ address = 0;+ op_index = 0;+ if (hdr->filenames_count > 1)+ reset_filename = hdr->filenames[1];+ else+ reset_filename = "";+ filename = reset_filename;+ lineno = 1;+ while (line_buf->left > 0)+ {+ unsigned int op;++ op = read_byte (line_buf);+ if (op >= hdr->opcode_base)+ {+ unsigned int advance;++ /* Special opcode. */+ op -= hdr->opcode_base;+ advance = op / hdr->line_range;+ address += (hdr->min_insn_len * (op_index + advance)+ / hdr->max_ops_per_insn);+ op_index = (op_index + advance) % hdr->max_ops_per_insn;+ lineno += hdr->line_base + (int) (op % hdr->line_range);+ add_line (state, ddata, address, filename, lineno,+ line_buf->error_callback, line_buf->data, vec);+ }+ else if (op == DW_LNS_extended_op)+ {+ uint64_t len;++ len = read_uleb128 (line_buf);+ op = read_byte (line_buf);+ switch (op)+ {+ case DW_LNE_end_sequence:+ /* FIXME: Should we mark the high PC here? It seems+ that we already have that information from the+ compilation unit. */+ address = 0;+ op_index = 0;+ filename = reset_filename;+ lineno = 1;+ break;+ case DW_LNE_set_address:+ address = read_address (line_buf, hdr->addrsize);+ break;+ case DW_LNE_define_file:+ {+ const char *f;+ unsigned int dir_index;++ f = read_string (line_buf);+ if (f == NULL)+ return 0;+ dir_index = read_uleb128 (line_buf);+ /* Ignore that time and length. */+ read_uleb128 (line_buf);+ read_uleb128 (line_buf);+ if (IS_ABSOLUTE_PATH (f))+ filename = f;+ else+ {+ const char *dir;+ size_t dir_len;+ size_t f_len;+ char *p;++ if (dir_index < hdr->dirs_count)+ dir = hdr->dirs[dir_index];+ else+ {+ dwarf_buf_error (line_buf,+ ("invalid directory index "+ "in line number program"),+ 0);+ return 0;+ }+ dir_len = strlen (dir);+ f_len = strlen (f);+ p = ((char *)+ backtrace_alloc (state, dir_len + f_len + 2,+ line_buf->error_callback,+ line_buf->data));+ if (p == NULL)+ return 0;+ memcpy (p, dir, dir_len);+ /* FIXME: If we are on a DOS-based file system,+ and the directory or the file name use+ backslashes, then we should use a backslash+ here. */+ p[dir_len] = '/';+ memcpy (p + dir_len + 1, f, f_len + 1);+ filename = p;+ }+ }+ break;+ case DW_LNE_set_discriminator:+ /* We don't care about discriminators. */+ read_uleb128 (line_buf);+ break;+ default:+ if (!advance (line_buf, len - 1))+ return 0;+ break;+ }+ }+ else+ {+ switch (op)+ {+ case DW_LNS_copy:+ add_line (state, ddata, address, filename, lineno,+ line_buf->error_callback, line_buf->data, vec);+ break;+ case DW_LNS_advance_pc:+ {+ uint64_t advance;++ advance = read_uleb128 (line_buf);+ address += (hdr->min_insn_len * (op_index + advance)+ / hdr->max_ops_per_insn);+ op_index = (op_index + advance) % hdr->max_ops_per_insn;+ }+ break;+ case DW_LNS_advance_line:+ lineno += (int) read_sleb128 (line_buf);+ break;+ case DW_LNS_set_file:+ {+ uint64_t fileno;++ fileno = read_uleb128 (line_buf);+ if (fileno >= hdr->filenames_count)+ {+ dwarf_buf_error (line_buf,+ ("invalid file number in "+ "line number program"),+ 0);+ return 0;+ }+ filename = hdr->filenames[fileno];+ }+ break;+ case DW_LNS_set_column:+ read_uleb128 (line_buf);+ break;+ case DW_LNS_negate_stmt:+ break;+ case DW_LNS_set_basic_block:+ break;+ case DW_LNS_const_add_pc:+ {+ unsigned int advance;++ op = 255 - hdr->opcode_base;+ advance = op / hdr->line_range;+ address += (hdr->min_insn_len * (op_index + advance)+ / hdr->max_ops_per_insn);+ op_index = (op_index + advance) % hdr->max_ops_per_insn;+ }+ break;+ case DW_LNS_fixed_advance_pc:+ address += read_uint16 (line_buf);+ op_index = 0;+ break;+ case DW_LNS_set_prologue_end:+ break;+ case DW_LNS_set_epilogue_begin:+ break;+ case DW_LNS_set_isa:+ read_uleb128 (line_buf);+ break;+ default:+ {+ unsigned int i;++ for (i = hdr->opcode_lengths[op - 1]; i > 0; --i)+ read_uleb128 (line_buf);+ }+ break;+ }+ }+ }++ return 1;+}++/* Read the line number information for a compilation unit. Returns 1+ on success, 0 on failure. */++static int+read_line_info (struct backtrace_state *state, struct dwarf_data *ddata,+ backtrace_error_callback error_callback, void *data,+ struct unit *u, struct line_header *hdr, struct line **lines,+ size_t *lines_count)+{+ struct line_vector vec;+ struct dwarf_buf line_buf;+ uint64_t len;+ int is_dwarf64;+ struct line *ln;++ memset (&vec.vec, 0, sizeof vec.vec);+ vec.count = 0;++ memset (hdr, 0, sizeof *hdr);++ if (u->lineoff != (off_t) (size_t) u->lineoff+ || (size_t) u->lineoff >= ddata->dwarf_sections.size[DEBUG_LINE])+ {+ error_callback (data, "unit line offset out of range", 0);+ goto fail;+ }++ line_buf.name = ".debug_line";+ line_buf.start = ddata->dwarf_sections.data[DEBUG_LINE];+ line_buf.buf = ddata->dwarf_sections.data[DEBUG_LINE] + u->lineoff;+ line_buf.left = ddata->dwarf_sections.size[DEBUG_LINE] - u->lineoff;+ line_buf.is_bigendian = ddata->is_bigendian;+ line_buf.error_callback = error_callback;+ line_buf.data = data;+ line_buf.reported_underflow = 0;++ len = read_initial_length (&line_buf, &is_dwarf64);+ line_buf.left = len;++ if (!read_line_header (state, ddata, u, is_dwarf64, &line_buf, hdr))+ goto fail;++ if (!read_line_program (state, ddata, hdr, &line_buf, &vec))+ goto fail;++ if (line_buf.reported_underflow)+ goto fail;++ if (vec.count == 0)+ {+ /* This is not a failure in the sense of a generating an error,+ but it is a failure in that sense that we have no useful+ information. */+ goto fail;+ }++ /* Allocate one extra entry at the end. */+ ln = ((struct line *)+ backtrace_vector_grow (state, sizeof (struct line), error_callback,+ data, &vec.vec));+ if (ln == NULL)+ goto fail;+ ln->pc = (uintptr_t) -1;+ ln->filename = NULL;+ ln->lineno = 0;+ ln->idx = 0;++ if (!backtrace_vector_release (state, &vec.vec, error_callback, data))+ goto fail;++ ln = (struct line *) vec.vec.base;+ backtrace_qsort (ln, vec.count, sizeof (struct line), line_compare);++ *lines = ln;+ *lines_count = vec.count;++ return 1;++ fail:+ backtrace_vector_free (state, &vec.vec, error_callback, data);+ free_line_header (state, hdr, error_callback, data);+ *lines = (struct line *) (uintptr_t) -1;+ *lines_count = 0;+ return 0;+}++static const char *read_referenced_name (struct dwarf_data *, struct unit *,+ uint64_t, backtrace_error_callback,+ void *);++/* Read the name of a function from a DIE referenced by ATTR with VAL. */++static const char *+read_referenced_name_from_attr (struct dwarf_data *ddata, struct unit *u,+ struct attr *attr, struct attr_val *val,+ backtrace_error_callback error_callback,+ void *data)+{+ switch (attr->name)+ {+ case DW_AT_abstract_origin:+ case DW_AT_specification:+ break;+ default:+ return NULL;+ }++ if (attr->form == DW_FORM_ref_sig8)+ return NULL;++ if (val->encoding == ATTR_VAL_REF_INFO)+ {+ struct unit *unit+ = find_unit (ddata->units, ddata->units_count,+ val->u.uint);+ if (unit == NULL)+ return NULL;++ uint64_t offset = val->u.uint - unit->low_offset;+ return read_referenced_name (ddata, unit, offset, error_callback, data);+ }++ if (val->encoding == ATTR_VAL_UINT+ || val->encoding == ATTR_VAL_REF_UNIT)+ return read_referenced_name (ddata, u, val->u.uint, error_callback, data);++ if (val->encoding == ATTR_VAL_REF_ALT_INFO)+ {+ struct unit *alt_unit+ = find_unit (ddata->altlink->units, ddata->altlink->units_count,+ val->u.uint);+ if (alt_unit == NULL)+ return NULL;++ uint64_t offset = val->u.uint - alt_unit->low_offset;+ return read_referenced_name (ddata->altlink, alt_unit, offset,+ error_callback, data);+ }++ return NULL;+}++/* Read the name of a function from a DIE referenced by a+ DW_AT_abstract_origin or DW_AT_specification tag. OFFSET is within+ the same compilation unit. */++static const char *+read_referenced_name (struct dwarf_data *ddata, struct unit *u,+ uint64_t offset, backtrace_error_callback error_callback,+ void *data)+{+ struct dwarf_buf unit_buf;+ uint64_t code;+ const struct abbrev *abbrev;+ const char *ret;+ size_t i;++ /* OFFSET is from the start of the data for this compilation unit.+ U->unit_data is the data, but it starts U->unit_data_offset bytes+ from the beginning. */++ if (offset < u->unit_data_offset+ || offset - u->unit_data_offset >= u->unit_data_len)+ {+ error_callback (data,+ "abstract origin or specification out of range",+ 0);+ return NULL;+ }++ offset -= u->unit_data_offset;++ unit_buf.name = ".debug_info";+ unit_buf.start = ddata->dwarf_sections.data[DEBUG_INFO];+ unit_buf.buf = u->unit_data + offset;+ unit_buf.left = u->unit_data_len - offset;+ unit_buf.is_bigendian = ddata->is_bigendian;+ unit_buf.error_callback = error_callback;+ unit_buf.data = data;+ unit_buf.reported_underflow = 0;++ code = read_uleb128 (&unit_buf);+ if (code == 0)+ {+ dwarf_buf_error (&unit_buf,+ "invalid abstract origin or specification",+ 0);+ return NULL;+ }++ abbrev = lookup_abbrev (&u->abbrevs, code, error_callback, data);+ if (abbrev == NULL)+ return NULL;++ ret = NULL;+ for (i = 0; i < abbrev->num_attrs; ++i)+ {+ struct attr_val val;++ if (!read_attribute (abbrev->attrs[i].form, abbrev->attrs[i].val,+ &unit_buf, u->is_dwarf64, u->version, u->addrsize,+ &ddata->dwarf_sections, ddata->altlink, &val))+ return NULL;++ switch (abbrev->attrs[i].name)+ {+ case DW_AT_name:+ /* Third name preference: don't override. A name we found in some+ other way, will normally be more useful -- e.g., this name is+ normally not mangled. */+ if (ret != NULL)+ break;+ if (!resolve_string (&ddata->dwarf_sections, u->is_dwarf64,+ ddata->is_bigendian, u->str_offsets_base,+ &val, error_callback, data, &ret))+ return NULL;+ break;++ case DW_AT_linkage_name:+ case DW_AT_MIPS_linkage_name:+ /* First name preference: override all. */+ {+ const char *s;++ s = NULL;+ if (!resolve_string (&ddata->dwarf_sections, u->is_dwarf64,+ ddata->is_bigendian, u->str_offsets_base,+ &val, error_callback, data, &s))+ return NULL;+ if (s != NULL)+ return s;+ }+ break;++ case DW_AT_specification:+ /* Second name preference: override DW_AT_name, don't override+ DW_AT_linkage_name. */+ {+ const char *name;++ name = read_referenced_name_from_attr (ddata, u, &abbrev->attrs[i],+ &val, error_callback, data);+ if (name != NULL)+ ret = name;+ }+ break;++ default:+ break;+ }+ }++ return ret;+}++/* Add a range to a unit that maps to a function. This is called via+ add_ranges. Returns 1 on success, 0 on error. */++static int+add_function_range (struct backtrace_state *state, void *rdata,+ uintptr_t lowpc, uintptr_t highpc,+ backtrace_error_callback error_callback, void *data,+ void *pvec)+{+ struct function *function = (struct function *) rdata;+ struct function_vector *vec = (struct function_vector *) pvec;+ struct function_addrs *p;++ if (vec->count > 0)+ {+ p = (struct function_addrs *) vec->vec.base + (vec->count - 1);+ if ((lowpc == p->high || lowpc == p->high + 1)+ && function == p->function)+ {+ if (highpc > p->high)+ p->high = highpc;+ return 1;+ }+ }++ p = ((struct function_addrs *)+ backtrace_vector_grow (state, sizeof (struct function_addrs),+ error_callback, data, &vec->vec));+ if (p == NULL)+ return 0;++ p->low = lowpc;+ p->high = highpc;+ p->function = function;++ ++vec->count;++ return 1;+}++/* Read one entry plus all its children. Add function addresses to+ VEC. Returns 1 on success, 0 on error. */++static int+read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,+ struct unit *u, uintptr_t base, struct dwarf_buf *unit_buf,+ const struct line_header *lhdr,+ backtrace_error_callback error_callback, void *data,+ struct function_vector *vec_function,+ struct function_vector *vec_inlined)+{+ while (unit_buf->left > 0)+ {+ uint64_t code;+ const struct abbrev *abbrev;+ int is_function;+ struct function *function;+ struct function_vector *vec;+ size_t i;+ struct pcrange pcrange;+ int have_linkage_name;++ code = read_uleb128 (unit_buf);+ if (code == 0)+ return 1;++ abbrev = lookup_abbrev (&u->abbrevs, code, error_callback, data);+ if (abbrev == NULL)+ return 0;++ is_function = (abbrev->tag == DW_TAG_subprogram+ || abbrev->tag == DW_TAG_entry_point+ || abbrev->tag == DW_TAG_inlined_subroutine);++ if (abbrev->tag == DW_TAG_inlined_subroutine)+ vec = vec_inlined;+ else+ vec = vec_function;++ function = NULL;+ if (is_function)+ {+ function = ((struct function *)+ backtrace_alloc (state, sizeof *function,+ error_callback, data));+ if (function == NULL)+ return 0;+ memset (function, 0, sizeof *function);+ }++ memset (&pcrange, 0, sizeof pcrange);+ have_linkage_name = 0;+ for (i = 0; i < abbrev->num_attrs; ++i)+ {+ struct attr_val val;++ if (!read_attribute (abbrev->attrs[i].form, abbrev->attrs[i].val,+ unit_buf, u->is_dwarf64, u->version,+ u->addrsize, &ddata->dwarf_sections,+ ddata->altlink, &val))+ return 0;++ /* The compile unit sets the base address for any address+ ranges in the function entries. */+ if ((abbrev->tag == DW_TAG_compile_unit+ || abbrev->tag == DW_TAG_skeleton_unit)+ && abbrev->attrs[i].name == DW_AT_low_pc)+ {+ if (val.encoding == ATTR_VAL_ADDRESS)+ base = (uintptr_t) val.u.uint;+ else if (val.encoding == ATTR_VAL_ADDRESS_INDEX)+ {+ if (!resolve_addr_index (&ddata->dwarf_sections,+ u->addr_base, u->addrsize,+ ddata->is_bigendian, val.u.uint,+ error_callback, data, &base))+ return 0;+ }+ }++ if (is_function)+ {+ switch (abbrev->attrs[i].name)+ {+ case DW_AT_call_file:+ if (val.encoding == ATTR_VAL_UINT)+ {+ if (val.u.uint >= lhdr->filenames_count)+ {+ dwarf_buf_error (unit_buf,+ ("invalid file number in "+ "DW_AT_call_file attribute"),+ 0);+ return 0;+ }+ function->caller_filename = lhdr->filenames[val.u.uint];+ }+ break;++ case DW_AT_call_line:+ if (val.encoding == ATTR_VAL_UINT)+ function->caller_lineno = val.u.uint;+ break;++ case DW_AT_abstract_origin:+ case DW_AT_specification:+ /* Second name preference: override DW_AT_name, don't override+ DW_AT_linkage_name. */+ if (have_linkage_name)+ break;+ {+ const char *name;++ name+ = read_referenced_name_from_attr (ddata, u,+ &abbrev->attrs[i], &val,+ error_callback, data);+ if (name != NULL)+ function->name = name;+ }+ break;++ case DW_AT_name:+ /* Third name preference: don't override. */+ if (function->name != NULL)+ break;+ if (!resolve_string (&ddata->dwarf_sections, u->is_dwarf64,+ ddata->is_bigendian,+ u->str_offsets_base, &val,+ error_callback, data, &function->name))+ return 0;+ break;++ case DW_AT_linkage_name:+ case DW_AT_MIPS_linkage_name:+ /* First name preference: override all. */+ {+ const char *s;++ s = NULL;+ if (!resolve_string (&ddata->dwarf_sections, u->is_dwarf64,+ ddata->is_bigendian,+ u->str_offsets_base, &val,+ error_callback, data, &s))+ return 0;+ if (s != NULL)+ {+ function->name = s;+ have_linkage_name = 1;+ }+ }+ break;++ case DW_AT_low_pc: case DW_AT_high_pc: case DW_AT_ranges:+ update_pcrange (&abbrev->attrs[i], &val, &pcrange);+ break;++ default:+ break;+ }+ }+ }++ /* If we couldn't find a name for the function, we have no use+ for it. */+ if (is_function && function->name == NULL)+ {+ backtrace_free (state, function, sizeof *function,+ error_callback, data);+ is_function = 0;+ }++ if (is_function)+ {+ if (pcrange.have_ranges+ || (pcrange.have_lowpc && pcrange.have_highpc))+ {+ if (!add_ranges (state, &ddata->dwarf_sections,+ ddata->base_address, ddata->is_bigendian,+ u, base, &pcrange, add_function_range,+ (void *) function, error_callback, data,+ (void *) vec))+ return 0;+ }+ else+ {+ backtrace_free (state, function, sizeof *function,+ error_callback, data);+ is_function = 0;+ }+ }++ if (abbrev->has_children)+ {+ if (!is_function)+ {+ if (!read_function_entry (state, ddata, u, base, unit_buf, lhdr,+ error_callback, data, vec_function,+ vec_inlined))+ return 0;+ }+ else+ {+ struct function_vector fvec;++ /* Gather any information for inlined functions in+ FVEC. */++ memset (&fvec, 0, sizeof fvec);++ if (!read_function_entry (state, ddata, u, base, unit_buf, lhdr,+ error_callback, data, vec_function,+ &fvec))+ return 0;++ if (fvec.count > 0)+ {+ struct function_addrs *p;+ struct function_addrs *faddrs;++ /* Allocate a trailing entry, but don't include it+ in fvec.count. */+ p = ((struct function_addrs *)+ backtrace_vector_grow (state,+ sizeof (struct function_addrs),+ error_callback, data,+ &fvec.vec));+ if (p == NULL)+ return 0;+ p->low = 0;+ --p->low;+ p->high = p->low;+ p->function = NULL;++ if (!backtrace_vector_release (state, &fvec.vec,+ error_callback, data))+ return 0;++ faddrs = (struct function_addrs *) fvec.vec.base;+ backtrace_qsort (faddrs, fvec.count,+ sizeof (struct function_addrs),+ function_addrs_compare);++ function->function_addrs = faddrs;+ function->function_addrs_count = fvec.count;+ }+ }+ }+ }++ return 1;+}++/* Read function name information for a compilation unit. We look+ through the whole unit looking for function tags. */++static void+read_function_info (struct backtrace_state *state, struct dwarf_data *ddata,+ const struct line_header *lhdr,+ backtrace_error_callback error_callback, void *data,+ struct unit *u, struct function_vector *fvec,+ struct function_addrs **ret_addrs,+ size_t *ret_addrs_count)+{+ struct function_vector lvec;+ struct function_vector *pfvec;+ struct dwarf_buf unit_buf;+ struct function_addrs *p;+ struct function_addrs *addrs;+ size_t addrs_count;++ /* Use FVEC if it is not NULL. Otherwise use our own vector. */+ if (fvec != NULL)+ pfvec = fvec;+ else+ {+ memset (&lvec, 0, sizeof lvec);+ pfvec = &lvec;+ }++ unit_buf.name = ".debug_info";+ unit_buf.start = ddata->dwarf_sections.data[DEBUG_INFO];+ unit_buf.buf = u->unit_data;+ unit_buf.left = u->unit_data_len;+ unit_buf.is_bigendian = ddata->is_bigendian;+ unit_buf.error_callback = error_callback;+ unit_buf.data = data;+ unit_buf.reported_underflow = 0;++ while (unit_buf.left > 0)+ {+ if (!read_function_entry (state, ddata, u, 0, &unit_buf, lhdr,+ error_callback, data, pfvec, pfvec))+ return;+ }++ if (pfvec->count == 0)+ return;++ /* Allocate a trailing entry, but don't include it in+ pfvec->count. */+ p = ((struct function_addrs *)+ backtrace_vector_grow (state, sizeof (struct function_addrs),+ error_callback, data, &pfvec->vec));+ if (p == NULL)+ return;+ p->low = 0;+ --p->low;+ p->high = p->low;+ p->function = NULL;++ addrs_count = pfvec->count;++ if (fvec == NULL)+ {+ if (!backtrace_vector_release (state, &lvec.vec, error_callback, data))+ return;+ addrs = (struct function_addrs *) pfvec->vec.base;+ }+ else+ {+ /* Finish this list of addresses, but leave the remaining space in+ the vector available for the next function unit. */+ addrs = ((struct function_addrs *)+ backtrace_vector_finish (state, &fvec->vec,+ error_callback, data));+ if (addrs == NULL)+ return;+ fvec->count = 0;+ }++ backtrace_qsort (addrs, addrs_count, sizeof (struct function_addrs),+ function_addrs_compare);++ *ret_addrs = addrs;+ *ret_addrs_count = addrs_count;+}++/* See if PC is inlined in FUNCTION. If it is, print out the inlined+ information, and update FILENAME and LINENO for the caller.+ Returns whatever CALLBACK returns, or 0 to keep going. */++static int+report_inlined_functions (uintptr_t pc, struct function *function, const char* comp_dir,+ backtrace_full_callback callback, void *data,+ const char **filename, int *lineno)+{+ struct function_addrs *p;+ struct function_addrs *match;+ struct function *inlined;+ int ret;++ if (function->function_addrs_count == 0)+ return 0;++ /* Our search isn't safe if pc == -1, as that is the sentinel+ value. */+ if (pc + 1 == 0)+ return 0;++ p = ((struct function_addrs *)+ bsearch (&pc, function->function_addrs,+ function->function_addrs_count,+ sizeof (struct function_addrs),+ function_addrs_search));+ if (p == NULL)+ return 0;++ /* Here pc >= p->low && pc < (p + 1)->low. The function_addrs are+ sorted by low, so if pc > p->low we are at the end of a range of+ function_addrs with the same low value. If pc == p->low walk+ forward to the end of the range with that low value. Then walk+ backward and use the first range that includes pc. */+ while (pc == (p + 1)->low)+ ++p;+ match = NULL;+ while (1)+ {+ if (pc < p->high)+ {+ match = p;+ break;+ }+ if (p == function->function_addrs)+ break;+ if ((p - 1)->low < p->low)+ break;+ --p;+ }+ if (match == NULL)+ return 0;++ /* We found an inlined call. */++ inlined = match->function;++ /* Report any calls inlined into this one. */+ ret = report_inlined_functions (pc, inlined, comp_dir, callback, data,+ filename, lineno);+ if (ret != 0)+ return ret;++ /* Report this inlined call. */+ if (*filename[0] != '/' && comp_dir)+ {+ char buf[1024];+ snprintf (buf, 1024, "%s/%s", comp_dir, *filename);+ ret = callback (data, pc, match->low, buf, *lineno, inlined->name);+ }+ else+ {+ ret = callback (data, pc, match->low, *filename, *lineno, inlined->name);+ }+ if (ret != 0)+ return ret;++ /* Our caller will report the caller of the inlined function; tell+ it the appropriate filename and line number. */+ *filename = inlined->caller_filename;+ *lineno = inlined->caller_lineno;++ return 0;+}++/* Look for a PC in the DWARF mapping for one module. On success,+ call CALLBACK and return whatever it returns. On error, call+ ERROR_CALLBACK and return 0. Sets *FOUND to 1 if the PC is found,+ 0 if not. */++static int+dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,+ uintptr_t pc, backtrace_full_callback callback,+ backtrace_error_callback error_callback, void *data,+ int *found)+{+ struct unit_addrs *entry;+ int found_entry;+ struct unit *u;+ int new_data;+ struct line *lines;+ struct line *ln;+ struct function_addrs *p;+ struct function_addrs *fmatch;+ struct function *function;+ const char *filename;+ int lineno;+ int ret;++ *found = 1;++ /* Find an address range that includes PC. Our search isn't safe if+ PC == -1, as we use that as a sentinel value, so skip the search+ in that case. */+ entry = (ddata->addrs_count == 0 || pc + 1 == 0+ ? NULL+ : (struct unit_addrs*)bsearch (&pc, ddata->addrs, ddata->addrs_count,+ sizeof (struct unit_addrs), unit_addrs_search));++ if (entry == NULL)+ {+ *found = 0;+ return 0;+ }++ /* Here pc >= entry->low && pc < (entry + 1)->low. The unit_addrs+ are sorted by low, so if pc > p->low we are at the end of a range+ of unit_addrs with the same low value. If pc == p->low walk+ forward to the end of the range with that low value. Then walk+ backward and use the first range that includes pc. */+ while (pc == (entry + 1)->low)+ ++entry;+ found_entry = 0;+ while (1)+ {+ if (pc < entry->high)+ {+ found_entry = 1;+ break;+ }+ if (entry == ddata->addrs)+ break;+ if ((entry - 1)->low < entry->low)+ break;+ --entry;+ }+ if (!found_entry)+ {+ *found = 0;+ return 0;+ }++ /* We need the lines, lines_count, function_addrs,+ function_addrs_count fields of u. If they are not set, we need+ to set them. When running in threaded mode, we need to allow for+ the possibility that some other thread is setting them+ simultaneously. */++ u = entry->u;+ lines = u->lines;++ /* Skip units with no useful line number information by walking+ backward. Useless line number information is marked by setting+ lines == -1. */+ while (entry > ddata->addrs+ && pc >= (entry - 1)->low+ && pc < (entry - 1)->high)+ {+ if (state->threaded)+ lines = (struct line *) backtrace_atomic_load_pointer (&u->lines);++ if (lines != (struct line *) (uintptr_t) -1)+ break;++ --entry;++ u = entry->u;+ lines = u->lines;+ }++ if (state->threaded)+ lines = backtrace_atomic_load_pointer (&u->lines);++ new_data = 0;+ if (lines == NULL)+ {+ struct function_addrs *function_addrs;+ size_t function_addrs_count;+ struct line_header lhdr;+ size_t count;++ /* We have never read the line information for this unit. Read+ it now. */++ function_addrs = NULL;+ function_addrs_count = 0;+ if (read_line_info (state, ddata, error_callback, data, entry->u, &lhdr,+ &lines, &count))+ {+ struct function_vector *pfvec;++ /* If not threaded, reuse DDATA->FVEC for better memory+ consumption. */+ if (state->threaded)+ pfvec = NULL;+ else+ pfvec = &ddata->fvec;+ read_function_info (state, ddata, &lhdr, error_callback, data,+ entry->u, pfvec, &function_addrs,+ &function_addrs_count);+ free_line_header (state, &lhdr, error_callback, data);+ new_data = 1;+ }++ /* Atomically store the information we just read into the unit.+ If another thread is simultaneously writing, it presumably+ read the same information, and we don't care which one we+ wind up with; we just leak the other one. We do have to+ write the lines field last, so that the acquire-loads above+ ensure that the other fields are set. */++ if (!state->threaded)+ {+ u->lines_count = count;+ u->function_addrs = function_addrs;+ u->function_addrs_count = function_addrs_count;+ u->lines = lines;+ }+ else+ {+ backtrace_atomic_store_size_t (&u->lines_count, count);+ backtrace_atomic_store_pointer (&u->function_addrs, function_addrs);+ backtrace_atomic_store_size_t (&u->function_addrs_count,+ function_addrs_count);+ backtrace_atomic_store_pointer (&u->lines, lines);+ }+ }++ /* Now all fields of U have been initialized. */++ if (lines == (struct line *) (uintptr_t) -1)+ {+ /* If reading the line number information failed in some way,+ try again to see if there is a better compilation unit for+ this PC. */+ if (new_data)+ return dwarf_lookup_pc (state, ddata, pc, callback, error_callback,+ data, found);+ return callback (data, pc, 0, NULL, 0, NULL);+ }++ /* Search for PC within this unit. */++ ln = (struct line *) bsearch (&pc, lines, entry->u->lines_count,+ sizeof (struct line), line_search);+ if (ln == NULL)+ {+ /* The PC is between the low_pc and high_pc attributes of the+ compilation unit, but no entry in the line table covers it.+ This implies that the start of the compilation unit has no+ line number information. */++ if (entry->u->abs_filename == NULL)+ {+ const char *filename;++ filename = entry->u->filename;+ if (filename != NULL+ && !IS_ABSOLUTE_PATH (filename)+ && entry->u->comp_dir != NULL)+ {+ size_t filename_len;+ const char *dir;+ size_t dir_len;+ char *s;++ filename_len = strlen (filename);+ dir = entry->u->comp_dir;+ dir_len = strlen (dir);+ s = (char *) backtrace_alloc (state, dir_len + filename_len + 2,+ error_callback, data);+ if (s == NULL)+ {+ *found = 0;+ return 0;+ }+ memcpy (s, dir, dir_len);+ /* FIXME: Should use backslash if DOS file system. */+ s[dir_len] = '/';+ memcpy (s + dir_len + 1, filename, filename_len + 1);+ filename = s;+ }+ entry->u->abs_filename = filename;+ }++ return callback (data, pc, 0, entry->u->abs_filename, 0, NULL);+ }++ /* Search for function name within this unit. */++ if (entry->u->function_addrs_count == 0)+ return callback (data, pc, 0, ln->filename, ln->lineno, NULL);++ p = ((struct function_addrs *)+ bsearch (&pc, entry->u->function_addrs,+ entry->u->function_addrs_count,+ sizeof (struct function_addrs),+ function_addrs_search));+ if (p == NULL)+ return callback (data, pc, 0, ln->filename, ln->lineno, NULL);++ /* Here pc >= p->low && pc < (p + 1)->low. The function_addrs are+ sorted by low, so if pc > p->low we are at the end of a range of+ function_addrs with the same low value. If pc == p->low walk+ forward to the end of the range with that low value. Then walk+ backward and use the first range that includes pc. */+ while (pc == (p + 1)->low)+ ++p;+ fmatch = NULL;+ while (1)+ {+ if (pc < p->high)+ {+ fmatch = p;+ break;+ }+ if (p == entry->u->function_addrs)+ break;+ if ((p - 1)->low < p->low)+ break;+ --p;+ }+ if (fmatch == NULL)+ return callback (data, pc, 0, ln->filename, ln->lineno, NULL);++ function = fmatch->function;++ filename = ln->filename;+ lineno = ln->lineno;++ ret = report_inlined_functions (pc, function, entry->u->comp_dir, callback, data,+ &filename, &lineno);+ if (ret != 0)+ return ret;++ if (filename[0] != '/' && entry->u->comp_dir)+ {+ char buf[1024];+ snprintf (buf, 1024, "%s/%s", entry->u->comp_dir, filename);+ return callback (data, pc, fmatch->low, buf, lineno, function->name);+ }+ else+ {+ return callback (data, pc, fmatch->low, filename, lineno, function->name);+ }+}++bool dwarf_fileline_dwarf_lookup_pc_in_all_entries(struct backtrace_state *state, uintptr_t pc,+ backtrace_full_callback callback, backtrace_error_callback error_callback, void *data,+ int& found, int ret)+{+ for (struct dwarf_data* ddata = (struct dwarf_data *)state->fileline_data;+ ddata != NULL;+ ddata = ddata->next)+ {+ ret = dwarf_lookup_pc(state, ddata, pc, callback, error_callback, data, &found);+ if (ret != 0 || found) return true;+ }+ return false;+}++/* Return the file/line information for a PC using the DWARF mapping+ we built earlier. */++static int+dwarf_fileline (struct backtrace_state *state, uintptr_t pc,+ backtrace_full_callback callback,+ backtrace_error_callback error_callback, void *data)+{+ struct dwarf_data *ddata;+ int found;+ int ret = 0;++ if (!state->threaded)+ {+ if (dwarf_fileline_dwarf_lookup_pc_in_all_entries(state, pc, callback, error_callback, data, found, ret))+ {+ return ret;+ }++ // if we failed to obtain an entry in range, it can mean that the address map has been changed and new entries+ // have been loaded in the meantime. Request a refresh and try again.+ if (state->request_known_address_ranges_refresh_fn)+ {+ int new_range_count = state->request_known_address_ranges_refresh_fn(state, pc);+ if (new_range_count > 0)+ {+ if (dwarf_fileline_dwarf_lookup_pc_in_all_entries(state, pc, callback, error_callback, data, found, ret))+ {+ return ret;+ }+ }+ }++ }+ else+ {+ struct dwarf_data **pp;++ pp = (struct dwarf_data **) (void *) &state->fileline_data;+ while (1)+ {+ ddata = backtrace_atomic_load_pointer (pp);+ if (ddata == NULL)+ break;++ ret = dwarf_lookup_pc (state, ddata, pc, callback, error_callback,+ data, &found);+ if (ret != 0 || found)+ return ret;++ pp = &ddata->next;+ }+ }++ /* FIXME: See if any libraries have been dlopen'ed. */++ return callback (data, pc, 0, NULL, 0, NULL);+}++/* Initialize our data structures from the DWARF debug info for a+ file. Return NULL on failure. */++static struct dwarf_data *+build_dwarf_data (struct backtrace_state *state,+ struct libbacktrace_base_address base_address,+ const struct dwarf_sections *dwarf_sections,+ int is_bigendian,+ struct dwarf_data *altlink,+ backtrace_error_callback error_callback,+ void *data)+{+ struct unit_addrs_vector addrs_vec;+ struct unit_addrs *addrs;+ size_t addrs_count;+ struct unit_vector units_vec;+ struct unit **units;+ size_t units_count;+ struct dwarf_data *fdata;++ if (!build_address_map (state, base_address, dwarf_sections, is_bigendian,+ altlink, error_callback, data, &addrs_vec,+ &units_vec))+ return NULL;++ if (!backtrace_vector_release (state, &addrs_vec.vec, error_callback, data))+ return NULL;+ if (!backtrace_vector_release (state, &units_vec.vec, error_callback, data))+ return NULL;+ addrs = (struct unit_addrs *) addrs_vec.vec.base;+ units = (struct unit **) units_vec.vec.base;+ addrs_count = addrs_vec.count;+ units_count = units_vec.count;+ backtrace_qsort (addrs, addrs_count, sizeof (struct unit_addrs),+ unit_addrs_compare);+ /* No qsort for units required, already sorted. */++ fdata = ((struct dwarf_data *)+ backtrace_alloc (state, sizeof (struct dwarf_data),+ error_callback, data));+ if (fdata == NULL)+ return NULL;++ fdata->next = NULL;+ fdata->altlink = altlink;+ fdata->base_address = base_address;+ fdata->addrs = addrs;+ fdata->addrs_count = addrs_count;+ fdata->units = units;+ fdata->units_count = units_count;+ fdata->dwarf_sections = *dwarf_sections;+ fdata->is_bigendian = is_bigendian;+ memset (&fdata->fvec, 0, sizeof fdata->fvec);++ return fdata;+}++/* Build our data structures from the DWARF sections for a module.+ Set FILELINE_FN and STATE->FILELINE_DATA. Return 1 on success, 0+ on failure. */++int+backtrace_dwarf_add (struct backtrace_state *state,+ struct libbacktrace_base_address base_address,+ const struct dwarf_sections *dwarf_sections,+ int is_bigendian,+ struct dwarf_data *fileline_altlink,+ backtrace_error_callback error_callback,+ void *data, fileline *fileline_fn,+ struct dwarf_data **fileline_entry)+{+ struct dwarf_data *fdata;++ fdata = build_dwarf_data (state, base_address, dwarf_sections, is_bigendian,+ fileline_altlink, error_callback, data);+ if (fdata == NULL)+ return 0;++ if (fileline_entry != NULL)+ *fileline_entry = fdata;++ if (!state->threaded)+ {+ struct dwarf_data **pp;++ for (pp = (struct dwarf_data **) (void *) &state->fileline_data;+ *pp != NULL;+ pp = &(*pp)->next)+ ;+ *pp = fdata;+ }+ else+ {+ while (1)+ {+ struct dwarf_data **pp;++ pp = (struct dwarf_data **) (void *) &state->fileline_data;++ while (1)+ {+ struct dwarf_data *p;++ p = backtrace_atomic_load_pointer (pp);++ if (p == NULL)+ break;++ pp = &p->next;+ }++ if (__sync_bool_compare_and_swap (pp, NULL, fdata))+ break;+ }+ }++ *fileline_fn = dwarf_fileline;++ return 1;+}++}
+ cbits/tracy/public/libbacktrace/elf.cpp view
@@ -0,0 +1,7605 @@+/* elf.c -- Get debug data from an ELF file for backtraces.+ Copyright (C) 2012-2021 Free Software Foundation, Inc.+ Written by Ian Lance Taylor, Google.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are+met:++ (1) Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ (2) Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in+ the documentation and/or other materials provided with the+ distribution.++ (3) The name of the author may not be used to+ endorse or promote products derived from this software without+ specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. */++#include "config.h"++#include <errno.h>+#include <stdlib.h>+#include <string.h>+#include <sys/types.h>+#include <sys/stat.h>+#include <unistd.h>+#include <algorithm>++#ifdef HAVE_DL_ITERATE_PHDR+#include <link.h>+#endif++#include "backtrace.hpp"+#include "internal.hpp"++#include "../client/TracyFastVector.hpp"+#include "../common/TracyAlloc.hpp"++#ifndef S_ISLNK+ #ifndef S_IFLNK+ #define S_IFLNK 0120000+ #endif+ #ifndef S_IFMT+ #define S_IFMT 0170000+ #endif+ #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)+#endif++#ifndef __GNUC__+#define __builtin_prefetch(p, r, l)+#ifndef unlikely+#define unlikely(x) (x)+#endif+#else+#ifndef unlikely+#define unlikely(x) __builtin_expect(!!(x), 0)+#endif+#endif++namespace tracy+{++#ifdef TRACY_DEBUGINFOD+int GetDebugInfoDescriptor( const char* buildid_data, size_t buildid_size );+#endif++#if !defined(HAVE_DECL_STRNLEN) || !HAVE_DECL_STRNLEN++/* If strnlen is not declared, provide our own version. */++static size_t+xstrnlen (const char *s, size_t maxlen)+{+ size_t i;++ for (i = 0; i < maxlen; ++i)+ if (s[i] == '\0')+ break;+ return i;+}++#define strnlen xstrnlen++#endif++#ifndef HAVE_LSTAT++/* Dummy version of lstat for systems that don't have it. */++static int+xlstat (const char *path ATTRIBUTE_UNUSED, struct stat *st ATTRIBUTE_UNUSED)+{+ return -1;+}++#define lstat xlstat++#endif++#ifndef HAVE_READLINK++/* Dummy version of readlink for systems that don't have it. */++static ssize_t+xreadlink (const char *path ATTRIBUTE_UNUSED, char *buf ATTRIBUTE_UNUSED,+ size_t bufsz ATTRIBUTE_UNUSED)+{+ return -1;+}++#define readlink xreadlink++#endif++#ifndef HAVE_DL_ITERATE_PHDR++/* Dummy version of dl_iterate_phdr for systems that don't have it. */++#define dl_phdr_info x_dl_phdr_info+#define dl_iterate_phdr x_dl_iterate_phdr++struct dl_phdr_info+{+ uintptr_t dlpi_addr;+ const char *dlpi_name;+};++static int+dl_iterate_phdr (int (*callback) (struct dl_phdr_info *,+ size_t, void *) ATTRIBUTE_UNUSED,+ void *data ATTRIBUTE_UNUSED)+{+ return 0;+}++#endif /* ! defined (HAVE_DL_ITERATE_PHDR) */++/* The configure script must tell us whether we are 32-bit or 64-bit+ ELF. We could make this code test and support either possibility,+ but there is no point. This code only works for the currently+ running executable, which means that we know the ELF mode at+ configure time. */++#if BACKTRACE_ELF_SIZE != 32 && BACKTRACE_ELF_SIZE != 64+#error "Unknown BACKTRACE_ELF_SIZE"+#endif++/* <link.h> might #include <elf.h> which might define our constants+ with slightly different values. Undefine them to be safe. */++#undef EI_NIDENT+#undef EI_MAG0+#undef EI_MAG1+#undef EI_MAG2+#undef EI_MAG3+#undef EI_CLASS+#undef EI_DATA+#undef EI_VERSION+#undef ELF_MAG0+#undef ELF_MAG1+#undef ELF_MAG2+#undef ELF_MAG3+#undef ELFCLASS32+#undef ELFCLASS64+#undef ELFDATA2LSB+#undef ELFDATA2MSB+#undef EV_CURRENT+#undef ET_DYN+#undef EM_PPC64+#undef EF_PPC64_ABI+#undef SHN_LORESERVE+#undef SHN_XINDEX+#undef SHN_UNDEF+#undef SHT_PROGBITS+#undef SHT_SYMTAB+#undef SHT_STRTAB+#undef SHT_DYNSYM+#undef SHF_COMPRESSED+#undef STT_OBJECT+#undef STT_FUNC+#undef NT_GNU_BUILD_ID+#undef ELFCOMPRESS_ZLIB+#undef ELFCOMPRESS_ZSTD++/* Basic types. */++typedef uint16_t b_elf_half; /* Elf_Half. */+typedef uint32_t b_elf_word; /* Elf_Word. */+typedef int32_t b_elf_sword; /* Elf_Sword. */++#if BACKTRACE_ELF_SIZE == 32++typedef uint32_t b_elf_addr; /* Elf_Addr. */+typedef uint32_t b_elf_off; /* Elf_Off. */++typedef uint32_t b_elf_wxword; /* 32-bit Elf_Word, 64-bit ELF_Xword. */++#else++typedef uint64_t b_elf_addr; /* Elf_Addr. */+typedef uint64_t b_elf_off; /* Elf_Off. */+typedef uint64_t b_elf_xword; /* Elf_Xword. */+typedef int64_t b_elf_sxword; /* Elf_Sxword. */++typedef uint64_t b_elf_wxword; /* 32-bit Elf_Word, 64-bit ELF_Xword. */++#endif++/* Data structures and associated constants. */++#define EI_NIDENT 16++typedef struct {+ unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */+ b_elf_half e_type; /* Identifies object file type */+ b_elf_half e_machine; /* Specifies required architecture */+ b_elf_word e_version; /* Identifies object file version */+ b_elf_addr e_entry; /* Entry point virtual address */+ b_elf_off e_phoff; /* Program header table file offset */+ b_elf_off e_shoff; /* Section header table file offset */+ b_elf_word e_flags; /* Processor-specific flags */+ b_elf_half e_ehsize; /* ELF header size in bytes */+ b_elf_half e_phentsize; /* Program header table entry size */+ b_elf_half e_phnum; /* Program header table entry count */+ b_elf_half e_shentsize; /* Section header table entry size */+ b_elf_half e_shnum; /* Section header table entry count */+ b_elf_half e_shstrndx; /* Section header string table index */+} b_elf_ehdr; /* Elf_Ehdr. */++#define EI_MAG0 0+#define EI_MAG1 1+#define EI_MAG2 2+#define EI_MAG3 3+#define EI_CLASS 4+#define EI_DATA 5+#define EI_VERSION 6++#define ELFMAG0 0x7f+#define ELFMAG1 'E'+#define ELFMAG2 'L'+#define ELFMAG3 'F'++#define ELFCLASS32 1+#define ELFCLASS64 2++#define ELFDATA2LSB 1+#define ELFDATA2MSB 2++#define EV_CURRENT 1++#define ET_DYN 3++#define EM_PPC64 21+#define EF_PPC64_ABI 3++typedef struct {+ b_elf_word sh_name; /* Section name, index in string tbl */+ b_elf_word sh_type; /* Type of section */+ b_elf_wxword sh_flags; /* Miscellaneous section attributes */+ b_elf_addr sh_addr; /* Section virtual addr at execution */+ b_elf_off sh_offset; /* Section file offset */+ b_elf_wxword sh_size; /* Size of section in bytes */+ b_elf_word sh_link; /* Index of another section */+ b_elf_word sh_info; /* Additional section information */+ b_elf_wxword sh_addralign; /* Section alignment */+ b_elf_wxword sh_entsize; /* Entry size if section holds table */+} b_elf_shdr; /* Elf_Shdr. */++#define SHN_UNDEF 0x0000 /* Undefined section */+#define SHN_LORESERVE 0xFF00 /* Begin range of reserved indices */+#define SHN_XINDEX 0xFFFF /* Section index is held elsewhere */++#define SHT_PROGBITS 1+#define SHT_SYMTAB 2+#define SHT_STRTAB 3+#define SHT_DYNSYM 11++#define SHF_COMPRESSED 0x800++#if BACKTRACE_ELF_SIZE == 32++typedef struct+{+ b_elf_word st_name; /* Symbol name, index in string tbl */+ b_elf_addr st_value; /* Symbol value */+ b_elf_word st_size; /* Symbol size */+ unsigned char st_info; /* Symbol binding and type */+ unsigned char st_other; /* Visibility and other data */+ b_elf_half st_shndx; /* Symbol section index */+} b_elf_sym; /* Elf_Sym. */++#else /* BACKTRACE_ELF_SIZE != 32 */++typedef struct+{+ b_elf_word st_name; /* Symbol name, index in string tbl */+ unsigned char st_info; /* Symbol binding and type */+ unsigned char st_other; /* Visibility and other data */+ b_elf_half st_shndx; /* Symbol section index */+ b_elf_addr st_value; /* Symbol value */+ b_elf_xword st_size; /* Symbol size */+} b_elf_sym; /* Elf_Sym. */++#endif /* BACKTRACE_ELF_SIZE != 32 */++#define STT_OBJECT 1+#define STT_FUNC 2++typedef struct+{+ uint32_t namesz;+ uint32_t descsz;+ uint32_t type;+ char name[1];+} b_elf_note;++#define NT_GNU_BUILD_ID 3++#if BACKTRACE_ELF_SIZE == 32++typedef struct+{+ b_elf_word ch_type; /* Compresstion algorithm */+ b_elf_word ch_size; /* Uncompressed size */+ b_elf_word ch_addralign; /* Alignment for uncompressed data */+} b_elf_chdr; /* Elf_Chdr */++#else /* BACKTRACE_ELF_SIZE != 32 */++typedef struct+{+ b_elf_word ch_type; /* Compression algorithm */+ b_elf_word ch_reserved; /* Reserved */+ b_elf_xword ch_size; /* Uncompressed size */+ b_elf_xword ch_addralign; /* Alignment for uncompressed data */+} b_elf_chdr; /* Elf_Chdr */++#endif /* BACKTRACE_ELF_SIZE != 32 */++#define ELFCOMPRESS_ZLIB 1+#define ELFCOMPRESS_ZSTD 2++/* Names of sections, indexed by enum dwarf_section in internal.h. */++static const char * const dwarf_section_names[DEBUG_MAX] =+{+ ".debug_info",+ ".debug_line",+ ".debug_abbrev",+ ".debug_ranges",+ ".debug_str",+ ".debug_addr",+ ".debug_str_offsets",+ ".debug_line_str",+ ".debug_rnglists"+};++/* Information we gather for the sections we care about. */++struct debug_section_info+{+ /* Section file offset. */+ off_t offset;+ /* Section size. */+ size_t size;+ /* Section contents, after read from file. */+ const unsigned char *data;+ /* Whether the SHF_COMPRESSED flag is set for the section. */+ int compressed;+};++/* Information we keep for an ELF symbol. */++struct elf_symbol+{+ /* The name of the symbol. */+ const char *name;+ /* The address of the symbol. */+ uintptr_t address;+ /* The size of the symbol. */+ size_t size;+};++/* Information to pass to elf_syminfo. */++struct elf_syminfo_data+{+ /* Symbols for the next module. */+ struct elf_syminfo_data *next;+ /* The ELF symbols, sorted by address. */+ struct elf_symbol *symbols;+ /* The number of symbols. */+ size_t count;+};++/* A view that works for either a file or memory. */++struct elf_view+{+ struct backtrace_view view;+ int release; /* If non-zero, must call backtrace_release_view. */+};++/* Information about PowerPC64 ELFv1 .opd section. */++struct elf_ppc64_opd_data+{+ /* Address of the .opd section. */+ b_elf_addr addr;+ /* Section data. */+ const char *data;+ /* Size of the .opd section. */+ size_t size;+ /* Corresponding section view. */+ struct elf_view view;+};++/* Create a view of SIZE bytes from DESCRIPTOR/MEMORY at OFFSET. */++static int+elf_get_view (struct backtrace_state *state, int descriptor,+ const unsigned char *memory, size_t memory_size, off_t offset,+ uint64_t size, backtrace_error_callback error_callback,+ void *data, struct elf_view *view)+{+ if (memory == NULL)+ {+ view->release = 1;+ return backtrace_get_view (state, descriptor, offset, size,+ error_callback, data, &view->view);+ }+ else+ {+ if ((uint64_t) offset + size > (uint64_t) memory_size)+ {+ error_callback (data, "out of range for in-memory file", 0);+ return 0;+ }+ view->view.data = (const void *) (memory + offset);+ view->view.base = NULL;+ view->view.len = size;+ view->release = 0;+ return 1;+ }+}++/* Release a view read by elf_get_view. */++static void+elf_release_view (struct backtrace_state *state, struct elf_view *view,+ backtrace_error_callback error_callback, void *data)+{+ if (view->release)+ backtrace_release_view (state, &view->view, error_callback, data);+}++/* Compute the CRC-32 of BUF/LEN. This uses the CRC used for+ .gnu_debuglink files. */++static uint32_t+elf_crc32 (uint32_t crc, const unsigned char *buf, size_t len)+{+ static const uint32_t crc32_table[256] =+ {+ 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+ };+ const unsigned char *end;++ crc = ~crc;+ for (end = buf + len; buf < end; ++ buf)+ crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);+ return ~crc;+}++/* Return the CRC-32 of the entire file open at DESCRIPTOR. */++static uint32_t+elf_crc32_file (struct backtrace_state *state, int descriptor,+ backtrace_error_callback error_callback, void *data)+{+ struct stat st;+ struct backtrace_view file_view;+ uint32_t ret;++ if (fstat (descriptor, &st) < 0)+ {+ error_callback (data, "fstat", errno);+ return 0;+ }++ if (!backtrace_get_view (state, descriptor, 0, st.st_size, error_callback,+ data, &file_view))+ return 0;++ ret = elf_crc32 (0, (const unsigned char *) file_view.data, st.st_size);++ backtrace_release_view (state, &file_view, error_callback, data);++ return ret;+}++/* A dummy callback function used when we can't find a symbol+ table. */++static void+elf_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,+ uintptr_t addr ATTRIBUTE_UNUSED,+ backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,+ backtrace_error_callback error_callback, void *data)+{+ error_callback (data, "no symbol table in ELF executable", -1);+}++/* A callback function used when we can't find any debug info. */++static int+elf_nodebug (struct backtrace_state *state, uintptr_t pc,+ backtrace_full_callback callback,+ backtrace_error_callback error_callback, void *data)+{+ if (state->syminfo_fn != NULL && state->syminfo_fn != elf_nosyms)+ {+ struct backtrace_call_full bdata;++ /* Fetch symbol information so that we can least get the+ function name. */++ bdata.full_callback = callback;+ bdata.full_error_callback = error_callback;+ bdata.full_data = data;+ bdata.ret = 0;+ state->syminfo_fn (state, pc, backtrace_syminfo_to_full_callback,+ backtrace_syminfo_to_full_error_callback, &bdata);+ return bdata.ret;+ }++ error_callback (data, "no debug info in ELF executable", -1);+ return 0;+}++/* Compare struct elf_symbol for qsort. */++static int+elf_symbol_compare (const void *v1, const void *v2)+{+ const struct elf_symbol *e1 = (const struct elf_symbol *) v1;+ const struct elf_symbol *e2 = (const struct elf_symbol *) v2;++ if (e1->address < e2->address)+ return -1;+ else if (e1->address > e2->address)+ return 1;+ else+ return 0;+}++/* Compare an ADDR against an elf_symbol for bsearch. We allocate one+ extra entry in the array so that this can look safely at the next+ entry. */++static int+elf_symbol_search (const void *vkey, const void *ventry)+{+ const uintptr_t *key = (const uintptr_t *) vkey;+ const struct elf_symbol *entry = (const struct elf_symbol *) ventry;+ uintptr_t addr;++ addr = *key;+ if (addr < entry->address)+ return -1;+ else if (addr >= entry->address + entry->size)+ return 1;+ else+ return 0;+}++/* Initialize the symbol table info for elf_syminfo. */++static int+elf_initialize_syminfo (struct backtrace_state *state,+ struct libbacktrace_base_address base_address,+ const unsigned char *symtab_data, size_t symtab_size,+ const unsigned char *strtab, size_t strtab_size,+ backtrace_error_callback error_callback,+ void *data, struct elf_syminfo_data *sdata,+ struct elf_ppc64_opd_data *opd)+{+ size_t sym_count;+ const b_elf_sym *sym;+ size_t elf_symbol_count;+ size_t elf_symbol_size;+ struct elf_symbol *elf_symbols;+ size_t i;+ unsigned int j;++ sym_count = symtab_size / sizeof (b_elf_sym);++ /* We only care about function symbols. Count them. */+ sym = (const b_elf_sym *) symtab_data;+ elf_symbol_count = 0;+ for (i = 0; i < sym_count; ++i, ++sym)+ {+ int info;++ info = sym->st_info & 0xf;+ if ((info == STT_FUNC || info == STT_OBJECT)+ && sym->st_shndx != SHN_UNDEF)+ ++elf_symbol_count;+ }++ elf_symbol_size = elf_symbol_count * sizeof (struct elf_symbol);+ elf_symbols = ((struct elf_symbol *)+ backtrace_alloc (state, elf_symbol_size, error_callback,+ data));+ if (elf_symbols == NULL)+ return 0;++ sym = (const b_elf_sym *) symtab_data;+ j = 0;+ for (i = 0; i < sym_count; ++i, ++sym)+ {+ int info;++ info = sym->st_info & 0xf;+ if (info != STT_FUNC && info != STT_OBJECT)+ continue;+ if (sym->st_shndx == SHN_UNDEF)+ continue;+ if (sym->st_name >= strtab_size)+ {+ error_callback (data, "symbol string index out of range", 0);+ backtrace_free (state, elf_symbols, elf_symbol_size, error_callback,+ data);+ return 0;+ }+ elf_symbols[j].name = (const char *) strtab + sym->st_name;+ /* Special case PowerPC64 ELFv1 symbols in .opd section, if the symbol+ is a function descriptor, read the actual code address from the+ descriptor. */+ if (opd+ && sym->st_value >= opd->addr+ && sym->st_value < opd->addr + opd->size)+ elf_symbols[j].address+ = *(const b_elf_addr *) (opd->data + (sym->st_value - opd->addr));+ else+ elf_symbols[j].address = sym->st_value;+ elf_symbols[j].address =+ libbacktrace_add_base (elf_symbols[j].address, base_address);+ elf_symbols[j].size = sym->st_size;+ ++j;+ }++ backtrace_qsort (elf_symbols, elf_symbol_count, sizeof (struct elf_symbol),+ elf_symbol_compare);++ sdata->next = NULL;+ sdata->symbols = elf_symbols;+ sdata->count = elf_symbol_count;++ return 1;+}++/* Add EDATA to the list in STATE. */++static void+elf_add_syminfo_data (struct backtrace_state *state,+ struct elf_syminfo_data *edata)+{+ if (!state->threaded)+ {+ struct elf_syminfo_data **pp;++ for (pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data;+ *pp != NULL;+ pp = &(*pp)->next)+ ;+ *pp = edata;+ }+ else+ {+ while (1)+ {+ struct elf_syminfo_data **pp;++ pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data;++ while (1)+ {+ struct elf_syminfo_data *p;++ p = backtrace_atomic_load_pointer (pp);++ if (p == NULL)+ break;++ pp = &p->next;+ }++ if (__sync_bool_compare_and_swap (pp, NULL, edata))+ break;+ }+ }+}++/* Return the symbol name and value for an ADDR. */++static void+elf_syminfo (struct backtrace_state *state, uintptr_t addr,+ backtrace_syminfo_callback callback,+ backtrace_error_callback error_callback ATTRIBUTE_UNUSED,+ void *data)+{+ struct elf_syminfo_data *edata;+ struct elf_symbol *sym = NULL;++ if (!state->threaded)+ {+ for (edata = (struct elf_syminfo_data *) state->syminfo_data;+ edata != NULL;+ edata = edata->next)+ {+ sym = ((struct elf_symbol *)+ bsearch (&addr, edata->symbols, edata->count,+ sizeof (struct elf_symbol), elf_symbol_search));+ if (sym != NULL)+ break;+ }+ }+ else+ {+ struct elf_syminfo_data **pp;++ pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data;+ while (1)+ {+ edata = backtrace_atomic_load_pointer (pp);+ if (edata == NULL)+ break;++ sym = ((struct elf_symbol *)+ bsearch (&addr, edata->symbols, edata->count,+ sizeof (struct elf_symbol), elf_symbol_search));+ if (sym != NULL)+ break;++ pp = &edata->next;+ }+ }++ if (sym == NULL)+ callback (data, addr, NULL, 0, 0);+ else+ callback (data, addr, sym->name, sym->address, sym->size);+}++/* Return whether FILENAME is a symlink. */++static int+elf_is_symlink (const char *filename)+{+ struct stat st;++ if (lstat (filename, &st) < 0)+ return 0;+ return S_ISLNK (st.st_mode);+}++/* Return the results of reading the symlink FILENAME in a buffer+ allocated by backtrace_alloc. Return the length of the buffer in+ *LEN. */++static char *+elf_readlink (struct backtrace_state *state, const char *filename,+ backtrace_error_callback error_callback, void *data,+ size_t *plen)+{+ size_t len;+ char *buf;++ len = 128;+ while (1)+ {+ ssize_t rl;++ buf = (char*)backtrace_alloc (state, len, error_callback, data);+ if (buf == NULL)+ return NULL;+ rl = readlink (filename, buf, len);+ if (rl < 0)+ {+ backtrace_free (state, buf, len, error_callback, data);+ return NULL;+ }+ if ((size_t) rl < len - 1)+ {+ buf[rl] = '\0';+ *plen = len;+ return buf;+ }+ backtrace_free (state, buf, len, error_callback, data);+ len *= 2;+ }+}++#define SYSTEM_BUILD_ID_DIR "/usr/lib/debug/.build-id/"++/* Open a separate debug info file, using the build ID to find it.+ Returns an open file descriptor, or -1.++ The GDB manual says that the only place gdb looks for a debug file+ when the build ID is known is in /usr/lib/debug/.build-id. */++static int+elf_open_debugfile_by_buildid (struct backtrace_state *state,+ const char *buildid_data, size_t buildid_size,+ const char *filename,+ backtrace_error_callback error_callback,+ void *data)+{+ const char * const prefix = SYSTEM_BUILD_ID_DIR;+ const size_t prefix_len = strlen (prefix);+ const char * const suffix = ".debug";+ const size_t suffix_len = strlen (suffix);+ size_t len;+ char *bd_filename;+ char *t;+ size_t i;+ int ret;+ int does_not_exist;++ len = prefix_len + buildid_size * 2 + suffix_len + 2;+ bd_filename = (char*)backtrace_alloc (state, len, error_callback, data);+ if (bd_filename == NULL)+ return -1;++ t = bd_filename;+ memcpy (t, prefix, prefix_len);+ t += prefix_len;+ for (i = 0; i < buildid_size; i++)+ {+ unsigned char b;+ unsigned char nib;++ b = (unsigned char) buildid_data[i];+ nib = (b & 0xf0) >> 4;+ *t++ = nib < 10 ? '0' + nib : 'a' + nib - 10;+ nib = b & 0x0f;+ *t++ = nib < 10 ? '0' + nib : 'a' + nib - 10;+ if (i == 0)+ *t++ = '/';+ }+ memcpy (t, suffix, suffix_len);+ t[suffix_len] = '\0';++ ret = backtrace_open (bd_filename, error_callback, data, &does_not_exist);++ backtrace_free (state, bd_filename, len, error_callback, data);++ /* gdb checks that the debuginfo file has the same build ID note.+ That seems kind of pointless to me--why would it have the right+ name but not the right build ID?--so skipping the check. */++#ifdef TRACY_DEBUGINFOD+ if (ret == -1)+ return GetDebugInfoDescriptor( buildid_data, buildid_size, filename );+ else+ return ret;+#else+ return ret;+#endif+}++/* Try to open a file whose name is PREFIX (length PREFIX_LEN)+ concatenated with PREFIX2 (length PREFIX2_LEN) concatenated with+ DEBUGLINK_NAME. Returns an open file descriptor, or -1. */++static int+elf_try_debugfile (struct backtrace_state *state, const char *prefix,+ size_t prefix_len, const char *prefix2, size_t prefix2_len,+ const char *debuglink_name,+ backtrace_error_callback error_callback, void *data)+{+ size_t debuglink_len;+ size_t try_len;+ char *Try;+ int does_not_exist;+ int ret;++ debuglink_len = strlen (debuglink_name);+ try_len = prefix_len + prefix2_len + debuglink_len + 1;+ Try = (char*)backtrace_alloc (state, try_len, error_callback, data);+ if (Try == NULL)+ return -1;++ memcpy (Try, prefix, prefix_len);+ memcpy (Try + prefix_len, prefix2, prefix2_len);+ memcpy (Try + prefix_len + prefix2_len, debuglink_name, debuglink_len);+ Try[prefix_len + prefix2_len + debuglink_len] = '\0';++ ret = backtrace_open (Try, error_callback, data, &does_not_exist);++ backtrace_free (state, Try, try_len, error_callback, data);++ return ret;+}++/* Find a separate debug info file, using the debuglink section data+ to find it. Returns an open file descriptor, or -1. */++static int+elf_find_debugfile_by_debuglink (struct backtrace_state *state,+ const char *filename,+ const char *debuglink_name,+ backtrace_error_callback error_callback,+ void *data)+{+ int ret;+ char *alc;+ size_t alc_len;+ const char *slash;+ int ddescriptor;+ const char *prefix;+ size_t prefix_len;++ /* Resolve symlinks in FILENAME. Since FILENAME is fairly likely to+ be /proc/self/exe, symlinks are common. We don't try to resolve+ the whole path name, just the base name. */+ ret = -1;+ alc = NULL;+ alc_len = 0;+ while (elf_is_symlink (filename))+ {+ char *new_buf;+ size_t new_len;++ new_buf = elf_readlink (state, filename, error_callback, data, &new_len);+ if (new_buf == NULL)+ break;++ if (new_buf[0] == '/')+ filename = new_buf;+ else+ {+ slash = strrchr (filename, '/');+ if (slash == NULL)+ filename = new_buf;+ else+ {+ size_t clen;+ char *c;++ slash++;+ clen = slash - filename + strlen (new_buf) + 1;+ c = (char*)backtrace_alloc (state, clen, error_callback, data);+ if (c == NULL)+ goto done;++ memcpy (c, filename, slash - filename);+ memcpy (c + (slash - filename), new_buf, strlen (new_buf));+ c[slash - filename + strlen (new_buf)] = '\0';+ backtrace_free (state, new_buf, new_len, error_callback, data);+ filename = c;+ new_buf = c;+ new_len = clen;+ }+ }++ if (alc != NULL)+ backtrace_free (state, alc, alc_len, error_callback, data);+ alc = new_buf;+ alc_len = new_len;+ }++ /* Look for DEBUGLINK_NAME in the same directory as FILENAME. */++ slash = strrchr (filename, '/');+ if (slash == NULL)+ {+ prefix = "";+ prefix_len = 0;+ }+ else+ {+ slash++;+ prefix = filename;+ prefix_len = slash - filename;+ }++ ddescriptor = elf_try_debugfile (state, prefix, prefix_len, "", 0,+ debuglink_name, error_callback, data);+ if (ddescriptor >= 0)+ {+ ret = ddescriptor;+ goto done;+ }++ /* Look for DEBUGLINK_NAME in a .debug subdirectory of FILENAME. */++ ddescriptor = elf_try_debugfile (state, prefix, prefix_len, ".debug/",+ strlen (".debug/"), debuglink_name,+ error_callback, data);+ if (ddescriptor >= 0)+ {+ ret = ddescriptor;+ goto done;+ }++ /* Look for DEBUGLINK_NAME in /usr/lib/debug. */++ ddescriptor = elf_try_debugfile (state, "/usr/lib/debug/",+ strlen ("/usr/lib/debug/"), prefix,+ prefix_len, debuglink_name,+ error_callback, data);+ if (ddescriptor >= 0)+ ret = ddescriptor;++ done:+ if (alc != NULL && alc_len > 0)+ backtrace_free (state, alc, alc_len, error_callback, data);+ return ret;+}++/* Open a separate debug info file, using the debuglink section data+ to find it. Returns an open file descriptor, or -1. */++static int+elf_open_debugfile_by_debuglink (struct backtrace_state *state,+ const char *filename,+ const char *debuglink_name,+ uint32_t debuglink_crc,+ backtrace_error_callback error_callback,+ void *data)+{+ int ddescriptor;++ ddescriptor = elf_find_debugfile_by_debuglink (state, filename,+ debuglink_name,+ error_callback, data);+ if (ddescriptor < 0)+ return -1;++ if (debuglink_crc != 0)+ {+ uint32_t got_crc;++ got_crc = elf_crc32_file (state, ddescriptor, error_callback, data);+ if (got_crc != debuglink_crc)+ {+ backtrace_close (ddescriptor, error_callback, data);+ return -1;+ }+ }++ return ddescriptor;+}++/* A function useful for setting a breakpoint for an inflation failure+ when this code is compiled with -g. */++static void+elf_uncompress_failed(void)+{+}++/* *PVAL is the current value being read from the stream, and *PBITS+ is the number of valid bits. Ensure that *PVAL holds at least 15+ bits by reading additional bits from *PPIN, up to PINEND, as+ needed. Updates *PPIN, *PVAL and *PBITS. Returns 1 on success, 0+ on error. */++static int+elf_fetch_bits (const unsigned char **ppin, const unsigned char *pinend,+ uint64_t *pval, unsigned int *pbits)+{+ unsigned int bits;+ const unsigned char *pin;+ uint64_t val;+ uint32_t next;++ bits = *pbits;+ if (bits >= 15)+ return 1;+ pin = *ppin;+ val = *pval;++ if (unlikely (pinend - pin < 4))+ {+ elf_uncompress_failed ();+ return 0;+ }++#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) \+ && defined(__ORDER_BIG_ENDIAN__) \+ && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ \+ || __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)+ /* We've ensured that PIN is aligned. */+ next = *(const uint32_t *)pin;++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__+ next = __builtin_bswap32 (next);+#endif+#else+ next = pin[0] | (pin[1] << 8) | (pin[2] << 16) | (pin[3] << 24);+#endif++ val |= (uint64_t)next << bits;+ bits += 32;+ pin += 4;++ /* We will need the next four bytes soon. */+ __builtin_prefetch (pin, 0, 0);++ *ppin = pin;+ *pval = val;+ *pbits = bits;+ return 1;+}++/* This is like elf_fetch_bits, but it fetchs the bits backward, and ensures at+ least 16 bits. This is for zstd. */++static int+elf_fetch_bits_backward (const unsigned char **ppin,+ const unsigned char *pinend,+ uint64_t *pval, unsigned int *pbits)+{+ unsigned int bits;+ const unsigned char *pin;+ uint64_t val;+ uint32_t next;++ bits = *pbits;+ if (bits >= 16)+ return 1;+ pin = *ppin;+ val = *pval;++ if (unlikely (pin <= pinend))+ return 1;++ pin -= 4;++#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) \+ && defined(__ORDER_BIG_ENDIAN__) \+ && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ \+ || __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)+ /* We've ensured that PIN is aligned. */+ next = *(const uint32_t *)pin;++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__+ next = __builtin_bswap32 (next);+#endif+#else+ next = pin[0] | (pin[1] << 8) | (pin[2] << 16) | (pin[3] << 24);+#endif++ val <<= 32;+ val |= next;+ bits += 32;++ if (unlikely (pin < pinend))+ {+ val >>= (pinend - pin) * 8;+ bits -= (pinend - pin) * 8;+ }++ *ppin = pin;+ *pval = val;+ *pbits = bits;+ return 1;+}++/* Initialize backward fetching when the bitstream starts with a 1 bit in the+ last byte in memory (which is the first one that we read). This is used by+ zstd decompression. Returns 1 on success, 0 on error. */++static int+elf_fetch_backward_init (const unsigned char **ppin,+ const unsigned char *pinend,+ uint64_t *pval, unsigned int *pbits)+{+ const unsigned char *pin;+ unsigned int stream_start;+ uint64_t val;+ unsigned int bits;++ pin = *ppin;+ stream_start = (unsigned int)*pin;+ if (unlikely (stream_start == 0))+ {+ elf_uncompress_failed ();+ return 0;+ }+ val = 0;+ bits = 0;++ /* Align to a 32-bit boundary. */+ while ((((uintptr_t)pin) & 3) != 0)+ {+ val <<= 8;+ val |= (uint64_t)*pin;+ bits += 8;+ --pin;+ }++ val <<= 8;+ val |= (uint64_t)*pin;+ bits += 8;++ *ppin = pin;+ *pval = val;+ *pbits = bits;+ if (!elf_fetch_bits_backward (ppin, pinend, pval, pbits))+ return 0;++ *pbits -= __builtin_clz (stream_start) - (sizeof (unsigned int) - 1) * 8 + 1;++ if (!elf_fetch_bits_backward (ppin, pinend, pval, pbits))+ return 0;++ return 1;+}++/* Huffman code tables, like the rest of the zlib format, are defined+ by RFC 1951. We store a Huffman code table as a series of tables+ stored sequentially in memory. Each entry in a table is 16 bits.+ The first, main, table has 256 entries. It is followed by a set of+ secondary tables of length 2 to 128 entries. The maximum length of+ a code sequence in the deflate format is 15 bits, so that is all we+ need. Each secondary table has an index, which is the offset of+ the table in the overall memory storage.++ The deflate format says that all codes of a given bit length are+ lexicographically consecutive. Perhaps we could have 130 values+ that require a 15-bit code, perhaps requiring three secondary+ tables of size 128. I don't know if this is actually possible, but+ it suggests that the maximum size required for secondary tables is+ 3 * 128 + 3 * 64 ... == 768. The zlib enough program reports 660+ as the maximum. We permit 768, since in addition to the 256 for+ the primary table, with two bytes per entry, and with the two+ tables we need, that gives us a page.++ A single table entry needs to store a value or (for the main table+ only) the index and size of a secondary table. Values range from 0+ to 285, inclusive. Secondary table indexes, per above, range from+ 0 to 510. For a value we need to store the number of bits we need+ to determine that value (one value may appear multiple times in the+ table), which is 1 to 8. For a secondary table we need to store+ the number of bits used to index into the table, which is 1 to 7.+ And of course we need 1 bit to decide whether we have a value or a+ secondary table index. So each entry needs 9 bits for value/table+ index, 3 bits for size, 1 bit what it is. For simplicity we use 16+ bits per entry. */++/* Number of entries we allocate to for one code table. We get a page+ for the two code tables we need. */++#define ZLIB_HUFFMAN_TABLE_SIZE (1024)++/* Bit masks and shifts for the values in the table. */++#define ZLIB_HUFFMAN_VALUE_MASK 0x01ff+#define ZLIB_HUFFMAN_BITS_SHIFT 9+#define ZLIB_HUFFMAN_BITS_MASK 0x7+#define ZLIB_HUFFMAN_SECONDARY_SHIFT 12++/* For working memory while inflating we need two code tables, we need+ an array of code lengths (max value 15, so we use unsigned char),+ and an array of unsigned shorts used while building a table. The+ latter two arrays must be large enough to hold the maximum number+ of code lengths, which RFC 1951 defines as 286 + 30. */++#define ZLIB_TABLE_SIZE \+ (2 * ZLIB_HUFFMAN_TABLE_SIZE * sizeof (uint16_t) \+ + (286 + 30) * sizeof (uint16_t) \+ + (286 + 30) * sizeof (unsigned char))++#define ZLIB_TABLE_CODELEN_OFFSET \+ (2 * ZLIB_HUFFMAN_TABLE_SIZE * sizeof (uint16_t) \+ + (286 + 30) * sizeof (uint16_t))++#define ZLIB_TABLE_WORK_OFFSET \+ (2 * ZLIB_HUFFMAN_TABLE_SIZE * sizeof (uint16_t))++#ifdef BACKTRACE_GENERATE_FIXED_HUFFMAN_TABLE++/* Used by the main function that generates the fixed table to learn+ the table size. */+static size_t final_next_secondary;++#endif++/* Build a Huffman code table from an array of lengths in CODES of+ length CODES_LEN. The table is stored into *TABLE. ZDEBUG_TABLE+ is the same as for elf_zlib_inflate, used to find some work space.+ Returns 1 on success, 0 on error. */++static int+elf_zlib_inflate_table (unsigned char *codes, size_t codes_len,+ uint16_t *zdebug_table, uint16_t *table)+{+ uint16_t count[16];+ uint16_t start[16];+ uint16_t prev[16];+ uint16_t firstcode[7];+ uint16_t *next;+ size_t i;+ size_t j;+ unsigned int code;+ size_t next_secondary;++ /* Count the number of code of each length. Set NEXT[val] to be the+ next value after VAL with the same bit length. */++ next = (uint16_t *) (((unsigned char *) zdebug_table)+ + ZLIB_TABLE_WORK_OFFSET);++ memset (&count[0], 0, 16 * sizeof (uint16_t));+ for (i = 0; i < codes_len; ++i)+ {+ if (unlikely (codes[i] >= 16))+ {+ elf_uncompress_failed ();+ return 0;+ }++ if (count[codes[i]] == 0)+ {+ start[codes[i]] = i;+ prev[codes[i]] = i;+ }+ else+ {+ next[prev[codes[i]]] = i;+ prev[codes[i]] = i;+ }++ ++count[codes[i]];+ }++ /* For each length, fill in the table for the codes of that+ length. */++ memset (table, 0, ZLIB_HUFFMAN_TABLE_SIZE * sizeof (uint16_t));++ /* Handle the values that do not require a secondary table. */++ code = 0;+ for (j = 1; j <= 8; ++j)+ {+ unsigned int jcnt;+ unsigned int val;++ jcnt = count[j];+ if (jcnt == 0)+ continue;++ if (unlikely (jcnt > (1U << j)))+ {+ elf_uncompress_failed ();+ return 0;+ }++ /* There are JCNT values that have this length, the values+ starting from START[j] continuing through NEXT[VAL]. Those+ values are assigned consecutive values starting at CODE. */++ val = start[j];+ for (i = 0; i < jcnt; ++i)+ {+ uint16_t tval;+ size_t ind;+ unsigned int incr;++ /* In the compressed bit stream, the value VAL is encoded as+ J bits with the value C. */++ if (unlikely ((val & ~ZLIB_HUFFMAN_VALUE_MASK) != 0))+ {+ elf_uncompress_failed ();+ return 0;+ }++ tval = val | ((j - 1) << ZLIB_HUFFMAN_BITS_SHIFT);++ /* The table lookup uses 8 bits. If J is less than 8, we+ don't know what the other bits will be. We need to fill+ in all possibilities in the table. Since the Huffman+ code is unambiguous, those entries can't be used for any+ other code. */++ for (ind = code; ind < 0x100; ind += 1 << j)+ {+ if (unlikely (table[ind] != 0))+ {+ elf_uncompress_failed ();+ return 0;+ }+ table[ind] = tval;+ }++ /* Advance to the next value with this length. */+ if (i + 1 < jcnt)+ val = next[val];++ /* The Huffman codes are stored in the bitstream with the+ most significant bit first, as is required to make them+ unambiguous. The effect is that when we read them from+ the bitstream we see the bit sequence in reverse order:+ the most significant bit of the Huffman code is the least+ significant bit of the value we read from the bitstream.+ That means that to make our table lookups work, we need+ to reverse the bits of CODE. Since reversing bits is+ tedious and in general requires using a table, we instead+ increment CODE in reverse order. That is, if the number+ of bits we are currently using, here named J, is 3, we+ count as 000, 100, 010, 110, 001, 101, 011, 111, which is+ to say the numbers from 0 to 7 but with the bits+ reversed. Going to more bits, aka incrementing J,+ effectively just adds more zero bits as the beginning,+ and as such does not change the numeric value of CODE.++ To increment CODE of length J in reverse order, find the+ most significant zero bit and set it to one while+ clearing all higher bits. In other words, add 1 modulo+ 2^J, only reversed. */++ incr = 1U << (j - 1);+ while ((code & incr) != 0)+ incr >>= 1;+ if (incr == 0)+ code = 0;+ else+ {+ code &= incr - 1;+ code += incr;+ }+ }+ }++ /* Handle the values that require a secondary table. */++ /* Set FIRSTCODE, the number at which the codes start, for each+ length. */++ for (j = 9; j < 16; j++)+ {+ unsigned int jcnt;+ unsigned int k;++ jcnt = count[j];+ if (jcnt == 0)+ continue;++ /* There are JCNT values that have this length, the values+ starting from START[j]. Those values are assigned+ consecutive values starting at CODE. */++ firstcode[j - 9] = code;++ /* Reverse add JCNT to CODE modulo 2^J. */+ for (k = 0; k < j; ++k)+ {+ if ((jcnt & (1U << k)) != 0)+ {+ unsigned int m;+ unsigned int bit;++ bit = 1U << (j - k - 1);+ for (m = 0; m < j - k; ++m, bit >>= 1)+ {+ if ((code & bit) == 0)+ {+ code += bit;+ break;+ }+ code &= ~bit;+ }+ jcnt &= ~(1U << k);+ }+ }+ if (unlikely (jcnt != 0))+ {+ elf_uncompress_failed ();+ return 0;+ }+ }++ /* For J from 9 to 15, inclusive, we store COUNT[J] consecutive+ values starting at START[J] with consecutive codes starting at+ FIRSTCODE[J - 9]. In the primary table we need to point to the+ secondary table, and the secondary table will be indexed by J - 9+ bits. We count down from 15 so that we install the larger+ secondary tables first, as the smaller ones may be embedded in+ the larger ones. */++ next_secondary = 0; /* Index of next secondary table (after primary). */+ for (j = 15; j >= 9; j--)+ {+ unsigned int jcnt;+ unsigned int val;+ size_t primary; /* Current primary index. */+ size_t secondary; /* Offset to current secondary table. */+ size_t secondary_bits; /* Bit size of current secondary table. */++ jcnt = count[j];+ if (jcnt == 0)+ continue;++ val = start[j];+ code = firstcode[j - 9];+ primary = 0x100;+ secondary = 0;+ secondary_bits = 0;+ for (i = 0; i < jcnt; ++i)+ {+ uint16_t tval;+ size_t ind;+ unsigned int incr;++ if ((code & 0xff) != primary)+ {+ uint16_t tprimary;++ /* Fill in a new primary table entry. */++ primary = code & 0xff;++ tprimary = table[primary];+ if (tprimary == 0)+ {+ /* Start a new secondary table. */++ if (unlikely ((next_secondary & ZLIB_HUFFMAN_VALUE_MASK)+ != next_secondary))+ {+ elf_uncompress_failed ();+ return 0;+ }++ secondary = next_secondary;+ secondary_bits = j - 8;+ next_secondary += 1 << secondary_bits;+ table[primary] = (secondary+ + ((j - 8) << ZLIB_HUFFMAN_BITS_SHIFT)+ + (1U << ZLIB_HUFFMAN_SECONDARY_SHIFT));+ }+ else+ {+ /* There is an existing entry. It had better be a+ secondary table with enough bits. */+ if (unlikely ((tprimary+ & (1U << ZLIB_HUFFMAN_SECONDARY_SHIFT))+ == 0))+ {+ elf_uncompress_failed ();+ return 0;+ }+ secondary = tprimary & ZLIB_HUFFMAN_VALUE_MASK;+ secondary_bits = ((tprimary >> ZLIB_HUFFMAN_BITS_SHIFT)+ & ZLIB_HUFFMAN_BITS_MASK);+ if (unlikely (secondary_bits < j - 8))+ {+ elf_uncompress_failed ();+ return 0;+ }+ }+ }++ /* Fill in secondary table entries. */++ tval = val | ((j - 8) << ZLIB_HUFFMAN_BITS_SHIFT);++ for (ind = code >> 8;+ ind < (1U << secondary_bits);+ ind += 1U << (j - 8))+ {+ if (unlikely (table[secondary + 0x100 + ind] != 0))+ {+ elf_uncompress_failed ();+ return 0;+ }+ table[secondary + 0x100 + ind] = tval;+ }++ if (i + 1 < jcnt)+ val = next[val];++ incr = 1U << (j - 1);+ while ((code & incr) != 0)+ incr >>= 1;+ if (incr == 0)+ code = 0;+ else+ {+ code &= incr - 1;+ code += incr;+ }+ }+ }++#ifdef BACKTRACE_GENERATE_FIXED_HUFFMAN_TABLE+ final_next_secondary = next_secondary;+#endif++ return 1;+}++#ifdef BACKTRACE_GENERATE_FIXED_HUFFMAN_TABLE++/* Used to generate the fixed Huffman table for block type 1. */++#include <stdio.h>++static uint16_t table[ZLIB_TABLE_SIZE];+static unsigned char codes[288];++int+main ()+{+ size_t i;++ for (i = 0; i <= 143; ++i)+ codes[i] = 8;+ for (i = 144; i <= 255; ++i)+ codes[i] = 9;+ for (i = 256; i <= 279; ++i)+ codes[i] = 7;+ for (i = 280; i <= 287; ++i)+ codes[i] = 8;+ if (!elf_zlib_inflate_table (&codes[0], 288, &table[0], &table[0]))+ {+ fprintf (stderr, "elf_zlib_inflate_table failed\n");+ exit (EXIT_FAILURE);+ }++ printf ("static const uint16_t elf_zlib_default_table[%#zx] =\n",+ final_next_secondary + 0x100);+ printf ("{\n");+ for (i = 0; i < final_next_secondary + 0x100; i += 8)+ {+ size_t j;++ printf (" ");+ for (j = i; j < final_next_secondary + 0x100 && j < i + 8; ++j)+ printf (" %#x,", table[j]);+ printf ("\n");+ }+ printf ("};\n");+ printf ("\n");++ for (i = 0; i < 32; ++i)+ codes[i] = 5;+ if (!elf_zlib_inflate_table (&codes[0], 32, &table[0], &table[0]))+ {+ fprintf (stderr, "elf_zlib_inflate_table failed\n");+ exit (EXIT_FAILURE);+ }++ printf ("static const uint16_t elf_zlib_default_dist_table[%#zx] =\n",+ final_next_secondary + 0x100);+ printf ("{\n");+ for (i = 0; i < final_next_secondary + 0x100; i += 8)+ {+ size_t j;++ printf (" ");+ for (j = i; j < final_next_secondary + 0x100 && j < i + 8; ++j)+ printf (" %#x,", table[j]);+ printf ("\n");+ }+ printf ("};\n");++ return 0;+}++#endif++/* The fixed tables generated by the #ifdef'ed out main function+ above. */++static const uint16_t elf_zlib_default_table[0x170] =+{+ 0xd00, 0xe50, 0xe10, 0xf18, 0xd10, 0xe70, 0xe30, 0x1230,+ 0xd08, 0xe60, 0xe20, 0x1210, 0xe00, 0xe80, 0xe40, 0x1250,+ 0xd04, 0xe58, 0xe18, 0x1200, 0xd14, 0xe78, 0xe38, 0x1240,+ 0xd0c, 0xe68, 0xe28, 0x1220, 0xe08, 0xe88, 0xe48, 0x1260,+ 0xd02, 0xe54, 0xe14, 0xf1c, 0xd12, 0xe74, 0xe34, 0x1238,+ 0xd0a, 0xe64, 0xe24, 0x1218, 0xe04, 0xe84, 0xe44, 0x1258,+ 0xd06, 0xe5c, 0xe1c, 0x1208, 0xd16, 0xe7c, 0xe3c, 0x1248,+ 0xd0e, 0xe6c, 0xe2c, 0x1228, 0xe0c, 0xe8c, 0xe4c, 0x1268,+ 0xd01, 0xe52, 0xe12, 0xf1a, 0xd11, 0xe72, 0xe32, 0x1234,+ 0xd09, 0xe62, 0xe22, 0x1214, 0xe02, 0xe82, 0xe42, 0x1254,+ 0xd05, 0xe5a, 0xe1a, 0x1204, 0xd15, 0xe7a, 0xe3a, 0x1244,+ 0xd0d, 0xe6a, 0xe2a, 0x1224, 0xe0a, 0xe8a, 0xe4a, 0x1264,+ 0xd03, 0xe56, 0xe16, 0xf1e, 0xd13, 0xe76, 0xe36, 0x123c,+ 0xd0b, 0xe66, 0xe26, 0x121c, 0xe06, 0xe86, 0xe46, 0x125c,+ 0xd07, 0xe5e, 0xe1e, 0x120c, 0xd17, 0xe7e, 0xe3e, 0x124c,+ 0xd0f, 0xe6e, 0xe2e, 0x122c, 0xe0e, 0xe8e, 0xe4e, 0x126c,+ 0xd00, 0xe51, 0xe11, 0xf19, 0xd10, 0xe71, 0xe31, 0x1232,+ 0xd08, 0xe61, 0xe21, 0x1212, 0xe01, 0xe81, 0xe41, 0x1252,+ 0xd04, 0xe59, 0xe19, 0x1202, 0xd14, 0xe79, 0xe39, 0x1242,+ 0xd0c, 0xe69, 0xe29, 0x1222, 0xe09, 0xe89, 0xe49, 0x1262,+ 0xd02, 0xe55, 0xe15, 0xf1d, 0xd12, 0xe75, 0xe35, 0x123a,+ 0xd0a, 0xe65, 0xe25, 0x121a, 0xe05, 0xe85, 0xe45, 0x125a,+ 0xd06, 0xe5d, 0xe1d, 0x120a, 0xd16, 0xe7d, 0xe3d, 0x124a,+ 0xd0e, 0xe6d, 0xe2d, 0x122a, 0xe0d, 0xe8d, 0xe4d, 0x126a,+ 0xd01, 0xe53, 0xe13, 0xf1b, 0xd11, 0xe73, 0xe33, 0x1236,+ 0xd09, 0xe63, 0xe23, 0x1216, 0xe03, 0xe83, 0xe43, 0x1256,+ 0xd05, 0xe5b, 0xe1b, 0x1206, 0xd15, 0xe7b, 0xe3b, 0x1246,+ 0xd0d, 0xe6b, 0xe2b, 0x1226, 0xe0b, 0xe8b, 0xe4b, 0x1266,+ 0xd03, 0xe57, 0xe17, 0xf1f, 0xd13, 0xe77, 0xe37, 0x123e,+ 0xd0b, 0xe67, 0xe27, 0x121e, 0xe07, 0xe87, 0xe47, 0x125e,+ 0xd07, 0xe5f, 0xe1f, 0x120e, 0xd17, 0xe7f, 0xe3f, 0x124e,+ 0xd0f, 0xe6f, 0xe2f, 0x122e, 0xe0f, 0xe8f, 0xe4f, 0x126e,+ 0x290, 0x291, 0x292, 0x293, 0x294, 0x295, 0x296, 0x297,+ 0x298, 0x299, 0x29a, 0x29b, 0x29c, 0x29d, 0x29e, 0x29f,+ 0x2a0, 0x2a1, 0x2a2, 0x2a3, 0x2a4, 0x2a5, 0x2a6, 0x2a7,+ 0x2a8, 0x2a9, 0x2aa, 0x2ab, 0x2ac, 0x2ad, 0x2ae, 0x2af,+ 0x2b0, 0x2b1, 0x2b2, 0x2b3, 0x2b4, 0x2b5, 0x2b6, 0x2b7,+ 0x2b8, 0x2b9, 0x2ba, 0x2bb, 0x2bc, 0x2bd, 0x2be, 0x2bf,+ 0x2c0, 0x2c1, 0x2c2, 0x2c3, 0x2c4, 0x2c5, 0x2c6, 0x2c7,+ 0x2c8, 0x2c9, 0x2ca, 0x2cb, 0x2cc, 0x2cd, 0x2ce, 0x2cf,+ 0x2d0, 0x2d1, 0x2d2, 0x2d3, 0x2d4, 0x2d5, 0x2d6, 0x2d7,+ 0x2d8, 0x2d9, 0x2da, 0x2db, 0x2dc, 0x2dd, 0x2de, 0x2df,+ 0x2e0, 0x2e1, 0x2e2, 0x2e3, 0x2e4, 0x2e5, 0x2e6, 0x2e7,+ 0x2e8, 0x2e9, 0x2ea, 0x2eb, 0x2ec, 0x2ed, 0x2ee, 0x2ef,+ 0x2f0, 0x2f1, 0x2f2, 0x2f3, 0x2f4, 0x2f5, 0x2f6, 0x2f7,+ 0x2f8, 0x2f9, 0x2fa, 0x2fb, 0x2fc, 0x2fd, 0x2fe, 0x2ff,+};++static const uint16_t elf_zlib_default_dist_table[0x100] =+{+ 0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c,+ 0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e,+ 0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d,+ 0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f,+ 0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c,+ 0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e,+ 0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d,+ 0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f,+ 0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c,+ 0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e,+ 0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d,+ 0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f,+ 0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c,+ 0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e,+ 0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d,+ 0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f,+ 0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c,+ 0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e,+ 0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d,+ 0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f,+ 0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c,+ 0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e,+ 0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d,+ 0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f,+ 0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c,+ 0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e,+ 0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d,+ 0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f,+ 0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c,+ 0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e,+ 0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d,+ 0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f,+};++/* Inflate a zlib stream from PIN/SIN to POUT/SOUT. Return 1 on+ success, 0 on some error parsing the stream. */++static int+elf_zlib_inflate (const unsigned char *pin, size_t sin, uint16_t *zdebug_table,+ unsigned char *pout, size_t sout)+{+ unsigned char *porigout;+ const unsigned char *pinend;+ unsigned char *poutend;++ /* We can apparently see multiple zlib streams concatenated+ together, so keep going as long as there is something to read.+ The last 4 bytes are the checksum. */+ porigout = pout;+ pinend = pin + sin;+ poutend = pout + sout;+ while ((pinend - pin) > 4)+ {+ uint64_t val;+ unsigned int bits;+ int last;++ /* Read the two byte zlib header. */++ if (unlikely ((pin[0] & 0xf) != 8)) /* 8 is zlib encoding. */+ {+ /* Unknown compression method. */+ elf_uncompress_failed ();+ return 0;+ }+ if (unlikely ((pin[0] >> 4) > 7))+ {+ /* Window size too large. Other than this check, we don't+ care about the window size. */+ elf_uncompress_failed ();+ return 0;+ }+ if (unlikely ((pin[1] & 0x20) != 0))+ {+ /* Stream expects a predefined dictionary, but we have no+ dictionary. */+ elf_uncompress_failed ();+ return 0;+ }+ val = (pin[0] << 8) | pin[1];+ if (unlikely (val % 31 != 0))+ {+ /* Header check failure. */+ elf_uncompress_failed ();+ return 0;+ }+ pin += 2;++ /* Align PIN to a 32-bit boundary. */++ val = 0;+ bits = 0;+ while ((((uintptr_t) pin) & 3) != 0)+ {+ val |= (uint64_t)*pin << bits;+ bits += 8;+ ++pin;+ }++ /* Read blocks until one is marked last. */++ last = 0;++ while (!last)+ {+ unsigned int type;+ const uint16_t *tlit;+ const uint16_t *tdist;++ if (!elf_fetch_bits (&pin, pinend, &val, &bits))+ return 0;++ last = val & 1;+ type = (val >> 1) & 3;+ val >>= 3;+ bits -= 3;++ if (unlikely (type == 3))+ {+ /* Invalid block type. */+ elf_uncompress_failed ();+ return 0;+ }++ if (type == 0)+ {+ uint16_t len;+ uint16_t lenc;++ /* An uncompressed block. */++ /* If we've read ahead more than a byte, back up. */+ while (bits >= 8)+ {+ --pin;+ bits -= 8;+ }++ val = 0;+ bits = 0;+ if (unlikely ((pinend - pin) < 4))+ {+ /* Missing length. */+ elf_uncompress_failed ();+ return 0;+ }+ len = pin[0] | (pin[1] << 8);+ lenc = pin[2] | (pin[3] << 8);+ pin += 4;+ lenc = ~lenc;+ if (unlikely (len != lenc))+ {+ /* Corrupt data. */+ elf_uncompress_failed ();+ return 0;+ }+ if (unlikely (len > (unsigned int) (pinend - pin)+ || len > (unsigned int) (poutend - pout)))+ {+ /* Not enough space in buffers. */+ elf_uncompress_failed ();+ return 0;+ }+ memcpy (pout, pin, len);+ pout += len;+ pin += len;++ /* Align PIN. */+ while ((((uintptr_t) pin) & 3) != 0)+ {+ val |= (uint64_t)*pin << bits;+ bits += 8;+ ++pin;+ }++ /* Go around to read the next block. */+ continue;+ }++ if (type == 1)+ {+ tlit = elf_zlib_default_table;+ tdist = elf_zlib_default_dist_table;+ }+ else+ {+ unsigned int nlit;+ unsigned int ndist;+ unsigned int nclen;+ unsigned char codebits[19];+ unsigned char *plenbase;+ unsigned char *plen;+ unsigned char *plenend;++ /* Read a Huffman encoding table. The various magic+ numbers here are from RFC 1951. */++ if (!elf_fetch_bits (&pin, pinend, &val, &bits))+ return 0;++ nlit = (val & 0x1f) + 257;+ val >>= 5;+ ndist = (val & 0x1f) + 1;+ val >>= 5;+ nclen = (val & 0xf) + 4;+ val >>= 4;+ bits -= 14;+ if (unlikely (nlit > 286 || ndist > 30))+ {+ /* Values out of range. */+ elf_uncompress_failed ();+ return 0;+ }++ /* Read and build the table used to compress the+ literal, length, and distance codes. */++ memset(&codebits[0], 0, 19);++ /* There are always at least 4 elements in the+ table. */++ if (!elf_fetch_bits (&pin, pinend, &val, &bits))+ return 0;++ codebits[16] = val & 7;+ codebits[17] = (val >> 3) & 7;+ codebits[18] = (val >> 6) & 7;+ codebits[0] = (val >> 9) & 7;+ val >>= 12;+ bits -= 12;++ if (nclen == 4)+ goto codebitsdone;++ codebits[8] = val & 7;+ val >>= 3;+ bits -= 3;++ if (nclen == 5)+ goto codebitsdone;++ if (!elf_fetch_bits (&pin, pinend, &val, &bits))+ return 0;++ codebits[7] = val & 7;+ val >>= 3;+ bits -= 3;++ if (nclen == 6)+ goto codebitsdone;++ codebits[9] = val & 7;+ val >>= 3;+ bits -= 3;++ if (nclen == 7)+ goto codebitsdone;++ codebits[6] = val & 7;+ val >>= 3;+ bits -= 3;++ if (nclen == 8)+ goto codebitsdone;++ codebits[10] = val & 7;+ val >>= 3;+ bits -= 3;++ if (nclen == 9)+ goto codebitsdone;++ codebits[5] = val & 7;+ val >>= 3;+ bits -= 3;++ if (nclen == 10)+ goto codebitsdone;++ if (!elf_fetch_bits (&pin, pinend, &val, &bits))+ return 0;++ codebits[11] = val & 7;+ val >>= 3;+ bits -= 3;++ if (nclen == 11)+ goto codebitsdone;++ codebits[4] = val & 7;+ val >>= 3;+ bits -= 3;++ if (nclen == 12)+ goto codebitsdone;++ codebits[12] = val & 7;+ val >>= 3;+ bits -= 3;++ if (nclen == 13)+ goto codebitsdone;++ codebits[3] = val & 7;+ val >>= 3;+ bits -= 3;++ if (nclen == 14)+ goto codebitsdone;++ codebits[13] = val & 7;+ val >>= 3;+ bits -= 3;++ if (nclen == 15)+ goto codebitsdone;++ if (!elf_fetch_bits (&pin, pinend, &val, &bits))+ return 0;++ codebits[2] = val & 7;+ val >>= 3;+ bits -= 3;++ if (nclen == 16)+ goto codebitsdone;++ codebits[14] = val & 7;+ val >>= 3;+ bits -= 3;++ if (nclen == 17)+ goto codebitsdone;++ codebits[1] = val & 7;+ val >>= 3;+ bits -= 3;++ if (nclen == 18)+ goto codebitsdone;++ codebits[15] = val & 7;+ val >>= 3;+ bits -= 3;++ codebitsdone:++ if (!elf_zlib_inflate_table (codebits, 19, zdebug_table,+ zdebug_table))+ return 0;++ /* Read the compressed bit lengths of the literal,+ length, and distance codes. We have allocated space+ at the end of zdebug_table to hold them. */++ plenbase = (((unsigned char *) zdebug_table)+ + ZLIB_TABLE_CODELEN_OFFSET);+ plen = plenbase;+ plenend = plen + nlit + ndist;+ while (plen < plenend)+ {+ uint16_t t;+ unsigned int b;+ uint16_t v;++ if (!elf_fetch_bits (&pin, pinend, &val, &bits))+ return 0;++ t = zdebug_table[val & 0xff];++ /* The compression here uses bit lengths up to 7, so+ a secondary table is never necessary. */+ if (unlikely ((t & (1U << ZLIB_HUFFMAN_SECONDARY_SHIFT))+ != 0))+ {+ elf_uncompress_failed ();+ return 0;+ }++ b = (t >> ZLIB_HUFFMAN_BITS_SHIFT) & ZLIB_HUFFMAN_BITS_MASK;+ val >>= b + 1;+ bits -= b + 1;++ v = t & ZLIB_HUFFMAN_VALUE_MASK;+ if (v < 16)+ *plen++ = v;+ else if (v == 16)+ {+ unsigned int c;+ unsigned int prev;++ /* Copy previous entry 3 to 6 times. */++ if (unlikely (plen == plenbase))+ {+ elf_uncompress_failed ();+ return 0;+ }++ /* We used up to 7 bits since the last+ elf_fetch_bits, so we have at least 8 bits+ available here. */++ c = 3 + (val & 0x3);+ val >>= 2;+ bits -= 2;+ if (unlikely ((unsigned int) (plenend - plen) < c))+ {+ elf_uncompress_failed ();+ return 0;+ }++ prev = plen[-1];+ switch (c)+ {+ case 6:+ *plen++ = prev;+ ATTRIBUTE_FALLTHROUGH;+ case 5:+ *plen++ = prev;+ ATTRIBUTE_FALLTHROUGH;+ case 4:+ *plen++ = prev;+ }+ *plen++ = prev;+ *plen++ = prev;+ *plen++ = prev;+ }+ else if (v == 17)+ {+ unsigned int c;++ /* Store zero 3 to 10 times. */++ /* We used up to 7 bits since the last+ elf_fetch_bits, so we have at least 8 bits+ available here. */++ c = 3 + (val & 0x7);+ val >>= 3;+ bits -= 3;+ if (unlikely ((unsigned int) (plenend - plen) < c))+ {+ elf_uncompress_failed ();+ return 0;+ }++ switch (c)+ {+ case 10:+ *plen++ = 0;+ ATTRIBUTE_FALLTHROUGH;+ case 9:+ *plen++ = 0;+ ATTRIBUTE_FALLTHROUGH;+ case 8:+ *plen++ = 0;+ ATTRIBUTE_FALLTHROUGH;+ case 7:+ *plen++ = 0;+ ATTRIBUTE_FALLTHROUGH;+ case 6:+ *plen++ = 0;+ ATTRIBUTE_FALLTHROUGH;+ case 5:+ *plen++ = 0;+ ATTRIBUTE_FALLTHROUGH;+ case 4:+ *plen++ = 0;+ }+ *plen++ = 0;+ *plen++ = 0;+ *plen++ = 0;+ }+ else if (v == 18)+ {+ unsigned int c;++ /* Store zero 11 to 138 times. */++ /* We used up to 7 bits since the last+ elf_fetch_bits, so we have at least 8 bits+ available here. */++ c = 11 + (val & 0x7f);+ val >>= 7;+ bits -= 7;+ if (unlikely ((unsigned int) (plenend - plen) < c))+ {+ elf_uncompress_failed ();+ return 0;+ }++ memset (plen, 0, c);+ plen += c;+ }+ else+ {+ elf_uncompress_failed ();+ return 0;+ }+ }++ /* Make sure that the stop code can appear. */++ plen = plenbase;+ if (unlikely (plen[256] == 0))+ {+ elf_uncompress_failed ();+ return 0;+ }++ /* Build the decompression tables. */++ if (!elf_zlib_inflate_table (plen, nlit, zdebug_table,+ zdebug_table))+ return 0;+ if (!elf_zlib_inflate_table (plen + nlit, ndist, zdebug_table,+ (zdebug_table+ + ZLIB_HUFFMAN_TABLE_SIZE)))+ return 0;+ tlit = zdebug_table;+ tdist = zdebug_table + ZLIB_HUFFMAN_TABLE_SIZE;+ }++ /* Inflate values until the end of the block. This is the+ main loop of the inflation code. */++ while (1)+ {+ uint16_t t;+ unsigned int b;+ uint16_t v;+ unsigned int lit;++ if (!elf_fetch_bits (&pin, pinend, &val, &bits))+ return 0;++ t = tlit[val & 0xff];+ b = (t >> ZLIB_HUFFMAN_BITS_SHIFT) & ZLIB_HUFFMAN_BITS_MASK;+ v = t & ZLIB_HUFFMAN_VALUE_MASK;++ if ((t & (1U << ZLIB_HUFFMAN_SECONDARY_SHIFT)) == 0)+ {+ lit = v;+ val >>= b + 1;+ bits -= b + 1;+ }+ else+ {+ t = tlit[v + 0x100 + ((val >> 8) & ((1U << b) - 1))];+ b = (t >> ZLIB_HUFFMAN_BITS_SHIFT) & ZLIB_HUFFMAN_BITS_MASK;+ lit = t & ZLIB_HUFFMAN_VALUE_MASK;+ val >>= b + 8;+ bits -= b + 8;+ }++ if (lit < 256)+ {+ if (unlikely (pout == poutend))+ {+ elf_uncompress_failed ();+ return 0;+ }++ *pout++ = lit;++ /* We will need to write the next byte soon. We ask+ for high temporal locality because we will write+ to the whole cache line soon. */+ __builtin_prefetch (pout, 1, 3);+ }+ else if (lit == 256)+ {+ /* The end of the block. */+ break;+ }+ else+ {+ unsigned int dist;+ unsigned int len;++ /* Convert lit into a length. */++ if (lit < 265)+ len = lit - 257 + 3;+ else if (lit == 285)+ len = 258;+ else if (unlikely (lit > 285))+ {+ elf_uncompress_failed ();+ return 0;+ }+ else+ {+ unsigned int extra;++ if (!elf_fetch_bits (&pin, pinend, &val, &bits))+ return 0;++ /* This is an expression for the table of length+ codes in RFC 1951 3.2.5. */+ lit -= 265;+ extra = (lit >> 2) + 1;+ len = (lit & 3) << extra;+ len += 11;+ len += ((1U << (extra - 1)) - 1) << 3;+ len += val & ((1U << extra) - 1);+ val >>= extra;+ bits -= extra;+ }++ if (!elf_fetch_bits (&pin, pinend, &val, &bits))+ return 0;++ t = tdist[val & 0xff];+ b = (t >> ZLIB_HUFFMAN_BITS_SHIFT) & ZLIB_HUFFMAN_BITS_MASK;+ v = t & ZLIB_HUFFMAN_VALUE_MASK;++ if ((t & (1U << ZLIB_HUFFMAN_SECONDARY_SHIFT)) == 0)+ {+ dist = v;+ val >>= b + 1;+ bits -= b + 1;+ }+ else+ {+ t = tdist[v + 0x100 + ((val >> 8) & ((1U << b) - 1))];+ b = ((t >> ZLIB_HUFFMAN_BITS_SHIFT)+ & ZLIB_HUFFMAN_BITS_MASK);+ dist = t & ZLIB_HUFFMAN_VALUE_MASK;+ val >>= b + 8;+ bits -= b + 8;+ }++ /* Convert dist to a distance. */++ if (dist == 0)+ {+ /* A distance of 1. A common case, meaning+ repeat the last character LEN times. */++ if (unlikely (pout == porigout))+ {+ elf_uncompress_failed ();+ return 0;+ }++ if (unlikely ((unsigned int) (poutend - pout) < len))+ {+ elf_uncompress_failed ();+ return 0;+ }++ memset (pout, pout[-1], len);+ pout += len;+ }+ else if (unlikely (dist > 29))+ {+ elf_uncompress_failed ();+ return 0;+ }+ else+ {+ if (dist < 4)+ dist = dist + 1;+ else+ {+ unsigned int extra;++ if (!elf_fetch_bits (&pin, pinend, &val, &bits))+ return 0;++ /* This is an expression for the table of+ distance codes in RFC 1951 3.2.5. */+ dist -= 4;+ extra = (dist >> 1) + 1;+ dist = (dist & 1) << extra;+ dist += 5;+ dist += ((1U << (extra - 1)) - 1) << 2;+ dist += val & ((1U << extra) - 1);+ val >>= extra;+ bits -= extra;+ }++ /* Go back dist bytes, and copy len bytes from+ there. */++ if (unlikely ((unsigned int) (pout - porigout) < dist))+ {+ elf_uncompress_failed ();+ return 0;+ }++ if (unlikely ((unsigned int) (poutend - pout) < len))+ {+ elf_uncompress_failed ();+ return 0;+ }++ if (dist >= len)+ {+ memcpy (pout, pout - dist, len);+ pout += len;+ }+ else+ {+ while (len > 0)+ {+ unsigned int copy;++ copy = len < dist ? len : dist;+ memcpy (pout, pout - dist, copy);+ len -= copy;+ pout += copy;+ }+ }+ }+ }+ }+ }+ }++ /* We should have filled the output buffer. */+ if (unlikely (pout != poutend))+ {+ elf_uncompress_failed ();+ return 0;+ }++ return 1;+}++/* Verify the zlib checksum. The checksum is in the 4 bytes at+ CHECKBYTES, and the uncompressed data is at UNCOMPRESSED /+ UNCOMPRESSED_SIZE. Returns 1 on success, 0 on failure. */++static int+elf_zlib_verify_checksum (const unsigned char *checkbytes,+ const unsigned char *uncompressed,+ size_t uncompressed_size)+{+ unsigned int i;+ unsigned int cksum;+ const unsigned char *p;+ uint32_t s1;+ uint32_t s2;+ size_t hsz;++ cksum = 0;+ for (i = 0; i < 4; i++)+ cksum = (cksum << 8) | checkbytes[i];++ s1 = 1;+ s2 = 0;++ /* Minimize modulo operations. */++ p = uncompressed;+ hsz = uncompressed_size;+ while (hsz >= 5552)+ {+ for (i = 0; i < 5552; i += 16)+ {+ /* Manually unroll loop 16 times. */+ s1 = s1 + *p++;+ s2 = s2 + s1;+ s1 = s1 + *p++;+ s2 = s2 + s1;+ s1 = s1 + *p++;+ s2 = s2 + s1;+ s1 = s1 + *p++;+ s2 = s2 + s1;+ s1 = s1 + *p++;+ s2 = s2 + s1;+ s1 = s1 + *p++;+ s2 = s2 + s1;+ s1 = s1 + *p++;+ s2 = s2 + s1;+ s1 = s1 + *p++;+ s2 = s2 + s1;+ s1 = s1 + *p++;+ s2 = s2 + s1;+ s1 = s1 + *p++;+ s2 = s2 + s1;+ s1 = s1 + *p++;+ s2 = s2 + s1;+ s1 = s1 + *p++;+ s2 = s2 + s1;+ s1 = s1 + *p++;+ s2 = s2 + s1;+ s1 = s1 + *p++;+ s2 = s2 + s1;+ s1 = s1 + *p++;+ s2 = s2 + s1;+ s1 = s1 + *p++;+ s2 = s2 + s1;+ }+ hsz -= 5552;+ s1 %= 65521;+ s2 %= 65521;+ }++ while (hsz >= 16)+ {+ /* Manually unroll loop 16 times. */+ s1 = s1 + *p++;+ s2 = s2 + s1;+ s1 = s1 + *p++;+ s2 = s2 + s1;+ s1 = s1 + *p++;+ s2 = s2 + s1;+ s1 = s1 + *p++;+ s2 = s2 + s1;+ s1 = s1 + *p++;+ s2 = s2 + s1;+ s1 = s1 + *p++;+ s2 = s2 + s1;+ s1 = s1 + *p++;+ s2 = s2 + s1;+ s1 = s1 + *p++;+ s2 = s2 + s1;+ s1 = s1 + *p++;+ s2 = s2 + s1;+ s1 = s1 + *p++;+ s2 = s2 + s1;+ s1 = s1 + *p++;+ s2 = s2 + s1;+ s1 = s1 + *p++;+ s2 = s2 + s1;+ s1 = s1 + *p++;+ s2 = s2 + s1;+ s1 = s1 + *p++;+ s2 = s2 + s1;+ s1 = s1 + *p++;+ s2 = s2 + s1;+ s1 = s1 + *p++;+ s2 = s2 + s1;++ hsz -= 16;+ }++ for (i = 0; i < hsz; ++i)+ {+ s1 = s1 + *p++;+ s2 = s2 + s1;+ }++ s1 %= 65521;+ s2 %= 65521;++ if (unlikely ((s2 << 16) + s1 != cksum))+ {+ elf_uncompress_failed ();+ return 0;+ }++ return 1;+}++/* Inflate a zlib stream from PIN/SIN to POUT/SOUT, and verify the+ checksum. Return 1 on success, 0 on error. */++static int+elf_zlib_inflate_and_verify (const unsigned char *pin, size_t sin,+ uint16_t *zdebug_table, unsigned char *pout,+ size_t sout)+{+ if (!elf_zlib_inflate (pin, sin, zdebug_table, pout, sout))+ return 0;+ if (!elf_zlib_verify_checksum (pin + sin - 4, pout, sout))+ return 0;+ return 1;+}++/* For working memory during zstd compression, we need+ - a literal length FSE table: 512 64-bit values == 4096 bytes+ - a match length FSE table: 512 64-bit values == 4096 bytes+ - a offset FSE table: 256 64-bit values == 2048 bytes+ - a Huffman tree: 2048 uint16_t values == 4096 bytes+ - scratch space, one of+ - to build an FSE table: 512 uint16_t values == 1024 bytes+ - to build a Huffman tree: 512 uint16_t + 256 uint32_t == 2048 bytes+*/++#define ZSTD_TABLE_SIZE \+ (2 * 512 * sizeof (struct elf_zstd_fse_baseline_entry) \+ + 256 * sizeof (struct elf_zstd_fse_baseline_entry) \+ + 2048 * sizeof (uint16_t) \+ + 512 * sizeof (uint16_t) + 256 * sizeof (uint32_t))++#define ZSTD_TABLE_LITERAL_FSE_OFFSET (0)++#define ZSTD_TABLE_MATCH_FSE_OFFSET \+ (512 * sizeof (struct elf_zstd_fse_baseline_entry))++#define ZSTD_TABLE_OFFSET_FSE_OFFSET \+ (ZSTD_TABLE_MATCH_FSE_OFFSET \+ + 512 * sizeof (struct elf_zstd_fse_baseline_entry))++#define ZSTD_TABLE_HUFFMAN_OFFSET \+ (ZSTD_TABLE_OFFSET_FSE_OFFSET \+ + 256 * sizeof (struct elf_zstd_fse_baseline_entry))++#define ZSTD_TABLE_WORK_OFFSET \+ (ZSTD_TABLE_HUFFMAN_OFFSET + 2048 * sizeof (uint16_t))++/* An entry in a zstd FSE table. */++struct elf_zstd_fse_entry+{+ /* The value that this FSE entry represents. */+ unsigned char symbol;+ /* The number of bits to read to determine the next state. */+ unsigned char bits;+ /* Add the bits to this base to get the next state. */+ uint16_t base;+};++static int+elf_zstd_build_fse (const int16_t *, int, uint16_t *, int,+ struct elf_zstd_fse_entry *);++/* Read a zstd FSE table and build the decoding table in *TABLE, updating *PPIN+ as it reads. ZDEBUG_TABLE is scratch space; it must be enough for 512+ uint16_t values (1024 bytes). MAXIDX is the maximum number of symbols+ permitted. *TABLE_BITS is the maximum number of bits for symbols in the+ table: the size of *TABLE is at least 1 << *TABLE_BITS. This updates+ *TABLE_BITS to the actual number of bits. Returns 1 on success, 0 on+ error. */++static int+elf_zstd_read_fse (const unsigned char **ppin, const unsigned char *pinend,+ uint16_t *zdebug_table, int maxidx,+ struct elf_zstd_fse_entry *table, int *table_bits)+{+ const unsigned char *pin;+ int16_t *norm;+ uint16_t *next;+ uint64_t val;+ unsigned int bits;+ int accuracy_log;+ uint32_t remaining;+ uint32_t threshold;+ int bits_needed;+ int idx;+ int prev0;++ pin = *ppin;++ norm = (int16_t *) zdebug_table;+ next = zdebug_table + 256;++ if (unlikely (pin + 3 >= pinend))+ {+ elf_uncompress_failed ();+ return 0;+ }++ /* Align PIN to a 32-bit boundary. */++ val = 0;+ bits = 0;+ while ((((uintptr_t) pin) & 3) != 0)+ {+ val |= (uint64_t)*pin << bits;+ bits += 8;+ ++pin;+ }++ if (!elf_fetch_bits (&pin, pinend, &val, &bits))+ return 0;++ accuracy_log = (val & 0xf) + 5;+ if (accuracy_log > *table_bits)+ {+ elf_uncompress_failed ();+ return 0;+ }+ *table_bits = accuracy_log;+ val >>= 4;+ bits -= 4;++ /* This code is mostly copied from the reference implementation. */++ /* The number of remaining probabilities, plus 1. This sets the number of+ bits that need to be read for the next value. */+ remaining = (1 << accuracy_log) + 1;++ /* The current difference between small and large values, which depends on+ the number of remaining values. Small values use one less bit. */+ threshold = 1 << accuracy_log;++ /* The number of bits used to compute threshold. */+ bits_needed = accuracy_log + 1;++ /* The next character value. */+ idx = 0;++ /* Whether the last count was 0. */+ prev0 = 0;++ while (remaining > 1 && idx <= maxidx)+ {+ uint32_t max;+ int32_t count;++ if (!elf_fetch_bits (&pin, pinend, &val, &bits))+ return 0;++ if (prev0)+ {+ int zidx;++ /* Previous count was 0, so there is a 2-bit repeat flag. If the+ 2-bit flag is 0b11, it adds 3 and then there is another repeat+ flag. */+ zidx = idx;+ while ((val & 0xfff) == 0xfff)+ {+ zidx += 3 * 6;+ val >>= 12;+ bits -= 12;+ if (!elf_fetch_bits (&pin, pinend, &val, &bits))+ return 0;+ }+ while ((val & 3) == 3)+ {+ zidx += 3;+ val >>= 2;+ bits -= 2;+ if (!elf_fetch_bits (&pin, pinend, &val, &bits))+ return 0;+ }+ /* We have at least 13 bits here, don't need to fetch. */+ zidx += val & 3;+ val >>= 2;+ bits -= 2;++ if (unlikely (zidx > maxidx))+ {+ elf_uncompress_failed ();+ return 0;+ }++ for (; idx < zidx; idx++)+ norm[idx] = 0;++ prev0 = 0;+ continue;+ }++ max = (2 * threshold - 1) - remaining;+ if ((val & (threshold - 1)) < max)+ {+ /* A small value. */+ count = (int32_t) ((uint32_t) val & (threshold - 1));+ val >>= bits_needed - 1;+ bits -= bits_needed - 1;+ }+ else+ {+ /* A large value. */+ count = (int32_t) ((uint32_t) val & (2 * threshold - 1));+ if (count >= (int32_t) threshold)+ count -= (int32_t) max;+ val >>= bits_needed;+ bits -= bits_needed;+ }++ count--;+ if (count >= 0)+ remaining -= count;+ else+ remaining--;+ if (unlikely (idx >= 256))+ {+ elf_uncompress_failed ();+ return 0;+ }+ norm[idx] = (int16_t) count;+ ++idx;++ prev0 = count == 0;++ while (remaining < threshold)+ {+ bits_needed--;+ threshold >>= 1;+ }+ }++ if (unlikely (remaining != 1))+ {+ elf_uncompress_failed ();+ return 0;+ }++ /* If we've read ahead more than a byte, back up. */+ while (bits >= 8)+ {+ --pin;+ bits -= 8;+ }++ *ppin = pin;++ for (; idx <= maxidx; idx++)+ norm[idx] = 0;++ return elf_zstd_build_fse (norm, idx, next, *table_bits, table);+}++/* Build the FSE decoding table from a list of probabilities. This reads from+ NORM of length IDX, uses NEXT as scratch space, and writes to *TABLE, whose+ size is TABLE_BITS. */++static int+elf_zstd_build_fse (const int16_t *norm, int idx, uint16_t *next,+ int table_bits, struct elf_zstd_fse_entry *table)+{+ int table_size;+ int high_threshold;+ int i;+ int pos;+ int step;+ int mask;++ table_size = 1 << table_bits;+ high_threshold = table_size - 1;+ for (i = 0; i < idx; i++)+ {+ int16_t n;++ n = norm[i];+ if (n >= 0)+ next[i] = (uint16_t) n;+ else+ {+ table[high_threshold].symbol = (unsigned char) i;+ high_threshold--;+ next[i] = 1;+ }+ }++ pos = 0;+ step = (table_size >> 1) + (table_size >> 3) + 3;+ mask = table_size - 1;+ for (i = 0; i < idx; i++)+ {+ int n;+ int j;++ n = (int) norm[i];+ for (j = 0; j < n; j++)+ {+ table[pos].symbol = (unsigned char) i;+ pos = (pos + step) & mask;+ while (unlikely (pos > high_threshold))+ pos = (pos + step) & mask;+ }+ }+ if (unlikely (pos != 0))+ {+ elf_uncompress_failed ();+ return 0;+ }++ for (i = 0; i < table_size; i++)+ {+ unsigned char sym;+ uint16_t next_state;+ int high_bit;+ int bits;++ sym = table[i].symbol;+ next_state = next[sym];+ ++next[sym];++ if (next_state == 0)+ {+ elf_uncompress_failed ();+ return 0;+ }+ high_bit = 31 - __builtin_clz (next_state);++ bits = table_bits - high_bit;+ table[i].bits = (unsigned char) bits;+ table[i].base = (uint16_t) ((next_state << bits) - table_size);+ }++ return 1;+}++/* Encode the baseline and bits into a single 32-bit value. */++#define ZSTD_ENCODE_BASELINE_BITS(baseline, basebits) \+ ((uint32_t)(baseline) | ((uint32_t)(basebits) << 24))++#define ZSTD_DECODE_BASELINE(baseline_basebits) \+ ((uint32_t)(baseline_basebits) & 0xffffff)++#define ZSTD_DECODE_BASEBITS(baseline_basebits) \+ ((uint32_t)(baseline_basebits) >> 24)++/* Given a literal length code, we need to read a number of bits and add that+ to a baseline. For states 0 to 15 the baseline is the state and the number+ of bits is zero. */++#define ZSTD_LITERAL_LENGTH_BASELINE_OFFSET (16)++static const uint32_t elf_zstd_literal_length_base[] =+{+ ZSTD_ENCODE_BASELINE_BITS(16, 1),+ ZSTD_ENCODE_BASELINE_BITS(18, 1),+ ZSTD_ENCODE_BASELINE_BITS(20, 1),+ ZSTD_ENCODE_BASELINE_BITS(22, 1),+ ZSTD_ENCODE_BASELINE_BITS(24, 2),+ ZSTD_ENCODE_BASELINE_BITS(28, 2),+ ZSTD_ENCODE_BASELINE_BITS(32, 3),+ ZSTD_ENCODE_BASELINE_BITS(40, 3),+ ZSTD_ENCODE_BASELINE_BITS(48, 4),+ ZSTD_ENCODE_BASELINE_BITS(64, 6),+ ZSTD_ENCODE_BASELINE_BITS(128, 7),+ ZSTD_ENCODE_BASELINE_BITS(256, 8),+ ZSTD_ENCODE_BASELINE_BITS(512, 9),+ ZSTD_ENCODE_BASELINE_BITS(1024, 10),+ ZSTD_ENCODE_BASELINE_BITS(2048, 11),+ ZSTD_ENCODE_BASELINE_BITS(4096, 12),+ ZSTD_ENCODE_BASELINE_BITS(8192, 13),+ ZSTD_ENCODE_BASELINE_BITS(16384, 14),+ ZSTD_ENCODE_BASELINE_BITS(32768, 15),+ ZSTD_ENCODE_BASELINE_BITS(65536, 16)+};++/* The same applies to match length codes. For states 0 to 31 the baseline is+ the state + 3 and the number of bits is zero. */++#define ZSTD_MATCH_LENGTH_BASELINE_OFFSET (32)++static const uint32_t elf_zstd_match_length_base[] =+{+ ZSTD_ENCODE_BASELINE_BITS(35, 1),+ ZSTD_ENCODE_BASELINE_BITS(37, 1),+ ZSTD_ENCODE_BASELINE_BITS(39, 1),+ ZSTD_ENCODE_BASELINE_BITS(41, 1),+ ZSTD_ENCODE_BASELINE_BITS(43, 2),+ ZSTD_ENCODE_BASELINE_BITS(47, 2),+ ZSTD_ENCODE_BASELINE_BITS(51, 3),+ ZSTD_ENCODE_BASELINE_BITS(59, 3),+ ZSTD_ENCODE_BASELINE_BITS(67, 4),+ ZSTD_ENCODE_BASELINE_BITS(83, 4),+ ZSTD_ENCODE_BASELINE_BITS(99, 5),+ ZSTD_ENCODE_BASELINE_BITS(131, 7),+ ZSTD_ENCODE_BASELINE_BITS(259, 8),+ ZSTD_ENCODE_BASELINE_BITS(515, 9),+ ZSTD_ENCODE_BASELINE_BITS(1027, 10),+ ZSTD_ENCODE_BASELINE_BITS(2051, 11),+ ZSTD_ENCODE_BASELINE_BITS(4099, 12),+ ZSTD_ENCODE_BASELINE_BITS(8195, 13),+ ZSTD_ENCODE_BASELINE_BITS(16387, 14),+ ZSTD_ENCODE_BASELINE_BITS(32771, 15),+ ZSTD_ENCODE_BASELINE_BITS(65539, 16)+};++/* An entry in an FSE table used for literal/match/length values. For these we+ have to map the symbol to a baseline value, and we have to read zero or more+ bits and add that value to the baseline value. Rather than look the values+ up in a separate table, we grow the FSE table so that we get better memory+ caching. */++struct elf_zstd_fse_baseline_entry+{+ /* The baseline for the value that this FSE entry represents.. */+ uint32_t baseline;+ /* The number of bits to read to add to the baseline. */+ unsigned char basebits;+ /* The number of bits to read to determine the next state. */+ unsigned char bits;+ /* Add the bits to this base to get the next state. */+ uint16_t base;+};++/* Convert the literal length FSE table FSE_TABLE to an FSE baseline table at+ BASELINE_TABLE. Note that FSE_TABLE and BASELINE_TABLE will overlap. */++static int+elf_zstd_make_literal_baseline_fse (+ const struct elf_zstd_fse_entry *fse_table,+ int table_bits,+ struct elf_zstd_fse_baseline_entry *baseline_table)+{+ size_t count;+ const struct elf_zstd_fse_entry *pfse;+ struct elf_zstd_fse_baseline_entry *pbaseline;++ /* Convert backward to avoid overlap. */++ count = 1U << table_bits;+ pfse = fse_table + count;+ pbaseline = baseline_table + count;+ while (pfse > fse_table)+ {+ unsigned char symbol;+ unsigned char bits;+ uint16_t base;++ --pfse;+ --pbaseline;+ symbol = pfse->symbol;+ bits = pfse->bits;+ base = pfse->base;+ if (symbol < ZSTD_LITERAL_LENGTH_BASELINE_OFFSET)+ {+ pbaseline->baseline = (uint32_t)symbol;+ pbaseline->basebits = 0;+ }+ else+ {+ unsigned int idx;+ uint32_t basebits;++ if (unlikely (symbol > 35))+ {+ elf_uncompress_failed ();+ return 0;+ }+ idx = symbol - ZSTD_LITERAL_LENGTH_BASELINE_OFFSET;+ basebits = elf_zstd_literal_length_base[idx];+ pbaseline->baseline = ZSTD_DECODE_BASELINE(basebits);+ pbaseline->basebits = ZSTD_DECODE_BASEBITS(basebits);+ }+ pbaseline->bits = bits;+ pbaseline->base = base;+ }++ return 1;+}++/* Convert the offset length FSE table FSE_TABLE to an FSE baseline table at+ BASELINE_TABLE. Note that FSE_TABLE and BASELINE_TABLE will overlap. */++static int+elf_zstd_make_offset_baseline_fse (+ const struct elf_zstd_fse_entry *fse_table,+ int table_bits,+ struct elf_zstd_fse_baseline_entry *baseline_table)+{+ size_t count;+ const struct elf_zstd_fse_entry *pfse;+ struct elf_zstd_fse_baseline_entry *pbaseline;++ /* Convert backward to avoid overlap. */++ count = 1U << table_bits;+ pfse = fse_table + count;+ pbaseline = baseline_table + count;+ while (pfse > fse_table)+ {+ unsigned char symbol;+ unsigned char bits;+ uint16_t base;++ --pfse;+ --pbaseline;+ symbol = pfse->symbol;+ bits = pfse->bits;+ base = pfse->base;+ if (unlikely (symbol > 31))+ {+ elf_uncompress_failed ();+ return 0;+ }++ /* The simple way to write this is++ pbaseline->baseline = (uint32_t)1 << symbol;+ pbaseline->basebits = symbol;++ That will give us an offset value that corresponds to the one+ described in the RFC. However, for offset values > 3, we have to+ subtract 3. And for offset values 1, 2, 3 we use a repeated offset.+ The baseline is always a power of 2, and is never 0, so for these low+ values we will see one entry that is baseline 1, basebits 0, and one+ entry that is baseline 2, basebits 1. All other entries will have+ baseline >= 4 and basebits >= 2.++ So we can check for RFC offset <= 3 by checking for basebits <= 1.+ And that means that we can subtract 3 here and not worry about doing+ it in the hot loop. */++ pbaseline->baseline = (uint32_t)1 << symbol;+ if (symbol >= 2)+ pbaseline->baseline -= 3;+ pbaseline->basebits = symbol;+ pbaseline->bits = bits;+ pbaseline->base = base;+ }++ return 1;+}++/* Convert the match length FSE table FSE_TABLE to an FSE baseline table at+ BASELINE_TABLE. Note that FSE_TABLE and BASELINE_TABLE will overlap. */++static int+elf_zstd_make_match_baseline_fse (+ const struct elf_zstd_fse_entry *fse_table,+ int table_bits,+ struct elf_zstd_fse_baseline_entry *baseline_table)+{+ size_t count;+ const struct elf_zstd_fse_entry *pfse;+ struct elf_zstd_fse_baseline_entry *pbaseline;++ /* Convert backward to avoid overlap. */++ count = 1U << table_bits;+ pfse = fse_table + count;+ pbaseline = baseline_table + count;+ while (pfse > fse_table)+ {+ unsigned char symbol;+ unsigned char bits;+ uint16_t base;++ --pfse;+ --pbaseline;+ symbol = pfse->symbol;+ bits = pfse->bits;+ base = pfse->base;+ if (symbol < ZSTD_MATCH_LENGTH_BASELINE_OFFSET)+ {+ pbaseline->baseline = (uint32_t)symbol + 3;+ pbaseline->basebits = 0;+ }+ else+ {+ unsigned int idx;+ uint32_t basebits;++ if (unlikely (symbol > 52))+ {+ elf_uncompress_failed ();+ return 0;+ }+ idx = symbol - ZSTD_MATCH_LENGTH_BASELINE_OFFSET;+ basebits = elf_zstd_match_length_base[idx];+ pbaseline->baseline = ZSTD_DECODE_BASELINE(basebits);+ pbaseline->basebits = ZSTD_DECODE_BASEBITS(basebits);+ }+ pbaseline->bits = bits;+ pbaseline->base = base;+ }++ return 1;+}++#ifdef BACKTRACE_GENERATE_ZSTD_FSE_TABLES++/* Used to generate the predefined FSE decoding tables for zstd. */++#include <stdio.h>++/* These values are straight from RFC 8878. */++static int16_t lit[36] =+{+ 4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 1, 1, 1, 1,+ -1,-1,-1,-1+};++static int16_t match[53] =+{+ 1, 4, 3, 2, 2, 2, 2, 2, 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, 1, 1, 1,-1,-1,+ -1,-1,-1,-1,-1+};++static int16_t offset[29] =+{+ 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,+ 1, 1, 1, 1, 1, 1, 1, 1,-1,-1,-1,-1,-1+};++static uint16_t next[256];++static void+print_table (const struct elf_zstd_fse_baseline_entry *table, size_t size)+{+ size_t i;++ printf ("{\n");+ for (i = 0; i < size; i += 3)+ {+ int j;++ printf (" ");+ for (j = 0; j < 3 && i + j < size; ++j)+ printf (" { %u, %d, %d, %d },", table[i + j].baseline,+ table[i + j].basebits, table[i + j].bits,+ table[i + j].base);+ printf ("\n");+ }+ printf ("};\n");+}++int+main ()+{+ struct elf_zstd_fse_entry lit_table[64];+ struct elf_zstd_fse_baseline_entry lit_baseline[64];+ struct elf_zstd_fse_entry match_table[64];+ struct elf_zstd_fse_baseline_entry match_baseline[64];+ struct elf_zstd_fse_entry offset_table[32];+ struct elf_zstd_fse_baseline_entry offset_baseline[32];++ if (!elf_zstd_build_fse (lit, sizeof lit / sizeof lit[0], next,+ 6, lit_table))+ {+ fprintf (stderr, "elf_zstd_build_fse failed\n");+ exit (EXIT_FAILURE);+ }++ if (!elf_zstd_make_literal_baseline_fse (lit_table, 6, lit_baseline))+ {+ fprintf (stderr, "elf_zstd_make_literal_baseline_fse failed\n");+ exit (EXIT_FAILURE);+ }++ printf ("static const struct elf_zstd_fse_baseline_entry "+ "elf_zstd_lit_table[64] =\n");+ print_table (lit_baseline,+ sizeof lit_baseline / sizeof lit_baseline[0]);+ printf ("\n");++ if (!elf_zstd_build_fse (match, sizeof match / sizeof match[0], next,+ 6, match_table))+ {+ fprintf (stderr, "elf_zstd_build_fse failed\n");+ exit (EXIT_FAILURE);+ }++ if (!elf_zstd_make_match_baseline_fse (match_table, 6, match_baseline))+ {+ fprintf (stderr, "elf_zstd_make_match_baseline_fse failed\n");+ exit (EXIT_FAILURE);+ }++ printf ("static const struct elf_zstd_fse_baseline_entry "+ "elf_zstd_match_table[64] =\n");+ print_table (match_baseline,+ sizeof match_baseline / sizeof match_baseline[0]);+ printf ("\n");++ if (!elf_zstd_build_fse (offset, sizeof offset / sizeof offset[0], next,+ 5, offset_table))+ {+ fprintf (stderr, "elf_zstd_build_fse failed\n");+ exit (EXIT_FAILURE);+ }++ if (!elf_zstd_make_offset_baseline_fse (offset_table, 5, offset_baseline))+ {+ fprintf (stderr, "elf_zstd_make_offset_baseline_fse failed\n");+ exit (EXIT_FAILURE);+ }++ printf ("static const struct elf_zstd_fse_baseline_entry "+ "elf_zstd_offset_table[32] =\n");+ print_table (offset_baseline,+ sizeof offset_baseline / sizeof offset_baseline[0]);+ printf ("\n");++ return 0;+}++#endif++/* The fixed tables generated by the #ifdef'ed out main function+ above. */++static const struct elf_zstd_fse_baseline_entry elf_zstd_lit_table[64] =+{+ { 0, 0, 4, 0 }, { 0, 0, 4, 16 }, { 1, 0, 5, 32 },+ { 3, 0, 5, 0 }, { 4, 0, 5, 0 }, { 6, 0, 5, 0 },+ { 7, 0, 5, 0 }, { 9, 0, 5, 0 }, { 10, 0, 5, 0 },+ { 12, 0, 5, 0 }, { 14, 0, 6, 0 }, { 16, 1, 5, 0 },+ { 20, 1, 5, 0 }, { 22, 1, 5, 0 }, { 28, 2, 5, 0 },+ { 32, 3, 5, 0 }, { 48, 4, 5, 0 }, { 64, 6, 5, 32 },+ { 128, 7, 5, 0 }, { 256, 8, 6, 0 }, { 1024, 10, 6, 0 },+ { 4096, 12, 6, 0 }, { 0, 0, 4, 32 }, { 1, 0, 4, 0 },+ { 2, 0, 5, 0 }, { 4, 0, 5, 32 }, { 5, 0, 5, 0 },+ { 7, 0, 5, 32 }, { 8, 0, 5, 0 }, { 10, 0, 5, 32 },+ { 11, 0, 5, 0 }, { 13, 0, 6, 0 }, { 16, 1, 5, 32 },+ { 18, 1, 5, 0 }, { 22, 1, 5, 32 }, { 24, 2, 5, 0 },+ { 32, 3, 5, 32 }, { 40, 3, 5, 0 }, { 64, 6, 4, 0 },+ { 64, 6, 4, 16 }, { 128, 7, 5, 32 }, { 512, 9, 6, 0 },+ { 2048, 11, 6, 0 }, { 0, 0, 4, 48 }, { 1, 0, 4, 16 },+ { 2, 0, 5, 32 }, { 3, 0, 5, 32 }, { 5, 0, 5, 32 },+ { 6, 0, 5, 32 }, { 8, 0, 5, 32 }, { 9, 0, 5, 32 },+ { 11, 0, 5, 32 }, { 12, 0, 5, 32 }, { 15, 0, 6, 0 },+ { 18, 1, 5, 32 }, { 20, 1, 5, 32 }, { 24, 2, 5, 32 },+ { 28, 2, 5, 32 }, { 40, 3, 5, 32 }, { 48, 4, 5, 32 },+ { 65536, 16, 6, 0 }, { 32768, 15, 6, 0 }, { 16384, 14, 6, 0 },+ { 8192, 13, 6, 0 },+};++static const struct elf_zstd_fse_baseline_entry elf_zstd_match_table[64] =+{+ { 3, 0, 6, 0 }, { 4, 0, 4, 0 }, { 5, 0, 5, 32 },+ { 6, 0, 5, 0 }, { 8, 0, 5, 0 }, { 9, 0, 5, 0 },+ { 11, 0, 5, 0 }, { 13, 0, 6, 0 }, { 16, 0, 6, 0 },+ { 19, 0, 6, 0 }, { 22, 0, 6, 0 }, { 25, 0, 6, 0 },+ { 28, 0, 6, 0 }, { 31, 0, 6, 0 }, { 34, 0, 6, 0 },+ { 37, 1, 6, 0 }, { 41, 1, 6, 0 }, { 47, 2, 6, 0 },+ { 59, 3, 6, 0 }, { 83, 4, 6, 0 }, { 131, 7, 6, 0 },+ { 515, 9, 6, 0 }, { 4, 0, 4, 16 }, { 5, 0, 4, 0 },+ { 6, 0, 5, 32 }, { 7, 0, 5, 0 }, { 9, 0, 5, 32 },+ { 10, 0, 5, 0 }, { 12, 0, 6, 0 }, { 15, 0, 6, 0 },+ { 18, 0, 6, 0 }, { 21, 0, 6, 0 }, { 24, 0, 6, 0 },+ { 27, 0, 6, 0 }, { 30, 0, 6, 0 }, { 33, 0, 6, 0 },+ { 35, 1, 6, 0 }, { 39, 1, 6, 0 }, { 43, 2, 6, 0 },+ { 51, 3, 6, 0 }, { 67, 4, 6, 0 }, { 99, 5, 6, 0 },+ { 259, 8, 6, 0 }, { 4, 0, 4, 32 }, { 4, 0, 4, 48 },+ { 5, 0, 4, 16 }, { 7, 0, 5, 32 }, { 8, 0, 5, 32 },+ { 10, 0, 5, 32 }, { 11, 0, 5, 32 }, { 14, 0, 6, 0 },+ { 17, 0, 6, 0 }, { 20, 0, 6, 0 }, { 23, 0, 6, 0 },+ { 26, 0, 6, 0 }, { 29, 0, 6, 0 }, { 32, 0, 6, 0 },+ { 65539, 16, 6, 0 }, { 32771, 15, 6, 0 }, { 16387, 14, 6, 0 },+ { 8195, 13, 6, 0 }, { 4099, 12, 6, 0 }, { 2051, 11, 6, 0 },+ { 1027, 10, 6, 0 },+};++static const struct elf_zstd_fse_baseline_entry elf_zstd_offset_table[32] =+{+ { 1, 0, 5, 0 }, { 61, 6, 4, 0 }, { 509, 9, 5, 0 },+ { 32765, 15, 5, 0 }, { 2097149, 21, 5, 0 }, { 5, 3, 5, 0 },+ { 125, 7, 4, 0 }, { 4093, 12, 5, 0 }, { 262141, 18, 5, 0 },+ { 8388605, 23, 5, 0 }, { 29, 5, 5, 0 }, { 253, 8, 4, 0 },+ { 16381, 14, 5, 0 }, { 1048573, 20, 5, 0 }, { 1, 2, 5, 0 },+ { 125, 7, 4, 16 }, { 2045, 11, 5, 0 }, { 131069, 17, 5, 0 },+ { 4194301, 22, 5, 0 }, { 13, 4, 5, 0 }, { 253, 8, 4, 16 },+ { 8189, 13, 5, 0 }, { 524285, 19, 5, 0 }, { 2, 1, 5, 0 },+ { 61, 6, 4, 16 }, { 1021, 10, 5, 0 }, { 65533, 16, 5, 0 },+ { 268435453, 28, 5, 0 }, { 134217725, 27, 5, 0 }, { 67108861, 26, 5, 0 },+ { 33554429, 25, 5, 0 }, { 16777213, 24, 5, 0 },+};++/* Read a zstd Huffman table and build the decoding table in *TABLE, reading+ and updating *PPIN. This sets *PTABLE_BITS to the number of bits of the+ table, such that the table length is 1 << *TABLE_BITS. ZDEBUG_TABLE is+ scratch space; it must be enough for 512 uint16_t values + 256 32-bit values+ (2048 bytes). Returns 1 on success, 0 on error. */++static int+elf_zstd_read_huff (const unsigned char **ppin, const unsigned char *pinend,+ uint16_t *zdebug_table, uint16_t *table, int *ptable_bits)+{+ const unsigned char *pin;+ unsigned char hdr;+ unsigned char *weights;+ size_t count;+ uint32_t *weight_mark;+ size_t i;+ uint32_t weight_mask;+ size_t table_bits;++ pin = *ppin;+ if (unlikely (pin >= pinend))+ {+ elf_uncompress_failed ();+ return 0;+ }+ hdr = *pin;+ ++pin;++ weights = (unsigned char *) zdebug_table;++ if (hdr < 128)+ {+ /* Table is compressed using FSE. */++ struct elf_zstd_fse_entry *fse_table;+ int fse_table_bits;+ uint16_t *scratch;+ const unsigned char *pfse;+ const unsigned char *pback;+ uint64_t val;+ unsigned int bits;+ unsigned int state1, state2;++ /* SCRATCH is used temporarily by elf_zstd_read_fse. It overlaps+ WEIGHTS. */+ scratch = zdebug_table;+ fse_table = (struct elf_zstd_fse_entry *) (scratch + 512);+ fse_table_bits = 6;++ pfse = pin;+ if (!elf_zstd_read_fse (&pfse, pinend, scratch, 255, fse_table,+ &fse_table_bits))+ return 0;++ if (unlikely (pin + hdr > pinend))+ {+ elf_uncompress_failed ();+ return 0;+ }++ /* We no longer need SCRATCH. Start recording weights. We need up to+ 256 bytes of weights and 64 bytes of rank counts, so it won't overlap+ FSE_TABLE. */++ pback = pin + hdr - 1;++ if (!elf_fetch_backward_init (&pback, pfse, &val, &bits))+ return 0;++ bits -= fse_table_bits;+ state1 = (val >> bits) & ((1U << fse_table_bits) - 1);+ bits -= fse_table_bits;+ state2 = (val >> bits) & ((1U << fse_table_bits) - 1);++ /* There are two independent FSE streams, tracked by STATE1 and STATE2.+ We decode them alternately. */++ count = 0;+ while (1)+ {+ struct elf_zstd_fse_entry *pt;+ uint64_t v;++ pt = &fse_table[state1];++ if (unlikely (pin < pinend) && bits < pt->bits)+ {+ if (unlikely (count >= 254))+ {+ elf_uncompress_failed ();+ return 0;+ }+ weights[count] = (unsigned char) pt->symbol;+ weights[count + 1] = (unsigned char) fse_table[state2].symbol;+ count += 2;+ break;+ }++ if (unlikely (pt->bits == 0))+ v = 0;+ else+ {+ if (!elf_fetch_bits_backward (&pback, pfse, &val, &bits))+ return 0;++ bits -= pt->bits;+ v = (val >> bits) & (((uint64_t)1 << pt->bits) - 1);+ }++ state1 = pt->base + v;++ if (unlikely (count >= 255))+ {+ elf_uncompress_failed ();+ return 0;+ }++ weights[count] = pt->symbol;+ ++count;++ pt = &fse_table[state2];++ if (unlikely (pin < pinend && bits < pt->bits))+ {+ if (unlikely (count >= 254))+ {+ elf_uncompress_failed ();+ return 0;+ }+ weights[count] = (unsigned char) pt->symbol;+ weights[count + 1] = (unsigned char) fse_table[state1].symbol;+ count += 2;+ break;+ }++ if (unlikely (pt->bits == 0))+ v = 0;+ else+ {+ if (!elf_fetch_bits_backward (&pback, pfse, &val, &bits))+ return 0;++ bits -= pt->bits;+ v = (val >> bits) & (((uint64_t)1 << pt->bits) - 1);+ }++ state2 = pt->base + v;++ if (unlikely (count >= 255))+ {+ elf_uncompress_failed ();+ return 0;+ }++ weights[count] = pt->symbol;+ ++count;+ }++ pin += hdr;+ }+ else+ {+ /* Table is not compressed. Each weight is 4 bits. */++ count = hdr - 127;+ if (unlikely (pin + ((count + 1) / 2) >= pinend))+ {+ elf_uncompress_failed ();+ return 0;+ }+ for (i = 0; i < count; i += 2)+ {+ unsigned char b;++ b = *pin;+ ++pin;+ weights[i] = b >> 4;+ weights[i + 1] = b & 0xf;+ }+ }++ weight_mark = (uint32_t *) (weights + 256);+ memset (weight_mark, 0, 13 * sizeof (uint32_t));+ weight_mask = 0;+ for (i = 0; i < count; ++i)+ {+ unsigned char w;++ w = weights[i];+ if (unlikely (w > 12))+ {+ elf_uncompress_failed ();+ return 0;+ }+ ++weight_mark[w];+ if (w > 0)+ weight_mask += 1U << (w - 1);+ }+ if (unlikely (weight_mask == 0))+ {+ elf_uncompress_failed ();+ return 0;+ }++ table_bits = 32 - __builtin_clz (weight_mask);+ if (unlikely (table_bits > 11))+ {+ elf_uncompress_failed ();+ return 0;+ }++ /* Work out the last weight value, which is omitted because the weights must+ sum to a power of two. */+ {+ uint32_t left;+ uint32_t high_bit;++ left = ((uint32_t)1 << table_bits) - weight_mask;+ if (left == 0)+ {+ elf_uncompress_failed ();+ return 0;+ }+ high_bit = 31 - __builtin_clz (left);+ if (((uint32_t)1 << high_bit) != left)+ {+ elf_uncompress_failed ();+ return 0;+ }++ if (unlikely (count >= 256))+ {+ elf_uncompress_failed ();+ return 0;+ }++ weights[count] = high_bit + 1;+ ++count;+ ++weight_mark[high_bit + 1];+ }++ if (weight_mark[1] < 2 || (weight_mark[1] & 1) != 0)+ {+ elf_uncompress_failed ();+ return 0;+ }++ /* Change WEIGHT_MARK from a count of weights to the index of the first+ symbol for that weight. We shift the indexes to also store how many we+ have seen so far, below. */+ {+ uint32_t next;++ next = 0;+ for (i = 0; i < table_bits; ++i)+ {+ uint32_t cur;++ cur = next;+ next += weight_mark[i + 1] << i;+ weight_mark[i + 1] = cur;+ }+ }++ for (i = 0; i < count; ++i)+ {+ unsigned char weight;+ uint32_t length;+ uint16_t tval;+ size_t start;+ uint32_t j;++ weight = weights[i];+ if (weight == 0)+ continue;++ length = 1U << (weight - 1);+ tval = (i << 8) | (table_bits + 1 - weight);+ start = weight_mark[weight];+ for (j = 0; j < length; ++j)+ table[start + j] = tval;+ weight_mark[weight] += length;+ }++ *ppin = pin;+ *ptable_bits = (int)table_bits;++ return 1;+}++/* Read and decompress the literals and store them ending at POUTEND. This+ works because we are going to use all the literals in the output, so they+ must fit into the output buffer. HUFFMAN_TABLE, and PHUFFMAN_TABLE_BITS+ store the Huffman table across calls. SCRATCH is used to read a Huffman+ table. Store the start of the decompressed literals in *PPLIT. Update+ *PPIN. Return 1 on success, 0 on error. */++static int+elf_zstd_read_literals (const unsigned char **ppin,+ const unsigned char *pinend,+ unsigned char *pout,+ unsigned char *poutend,+ uint16_t *scratch,+ uint16_t *huffman_table,+ int *phuffman_table_bits,+ unsigned char **pplit)+{+ const unsigned char *pin;+ unsigned char *plit;+ unsigned char hdr;+ uint32_t regenerated_size;+ uint32_t compressed_size;+ int streams;+ uint32_t total_streams_size;+ unsigned int huffman_table_bits;+ uint64_t huffman_mask;++ pin = *ppin;+ if (unlikely (pin >= pinend))+ {+ elf_uncompress_failed ();+ return 0;+ }+ hdr = *pin;+ ++pin;++ if ((hdr & 3) == 0 || (hdr & 3) == 1)+ {+ int raw;++ /* Raw_Literals_Block or RLE_Literals_Block */++ raw = (hdr & 3) == 0;++ switch ((hdr >> 2) & 3)+ {+ case 0: case 2:+ regenerated_size = hdr >> 3;+ break;+ case 1:+ if (unlikely (pin >= pinend))+ {+ elf_uncompress_failed ();+ return 0;+ }+ regenerated_size = (hdr >> 4) + ((uint32_t)(*pin) << 4);+ ++pin;+ break;+ case 3:+ if (unlikely (pin + 1 >= pinend))+ {+ elf_uncompress_failed ();+ return 0;+ }+ regenerated_size = ((hdr >> 4)+ + ((uint32_t)*pin << 4)+ + ((uint32_t)pin[1] << 12));+ pin += 2;+ break;+ default:+ elf_uncompress_failed ();+ return 0;+ }++ if (unlikely ((size_t)(poutend - pout) < regenerated_size))+ {+ elf_uncompress_failed ();+ return 0;+ }++ plit = poutend - regenerated_size;++ if (raw)+ {+ if (unlikely (pin + regenerated_size >= pinend))+ {+ elf_uncompress_failed ();+ return 0;+ }+ memcpy (plit, pin, regenerated_size);+ pin += regenerated_size;+ }+ else+ {+ if (pin >= pinend)+ {+ elf_uncompress_failed ();+ return 0;+ }+ memset (plit, *pin, regenerated_size);+ ++pin;+ }++ *ppin = pin;+ *pplit = plit;++ return 1;+ }++ /* Compressed_Literals_Block or Treeless_Literals_Block */++ switch ((hdr >> 2) & 3)+ {+ case 0: case 1:+ if (unlikely (pin + 1 >= pinend))+ {+ elf_uncompress_failed ();+ return 0;+ }+ regenerated_size = (hdr >> 4) | ((uint32_t)(*pin & 0x3f) << 4);+ compressed_size = (uint32_t)*pin >> 6 | ((uint32_t)pin[1] << 2);+ pin += 2;+ streams = ((hdr >> 2) & 3) == 0 ? 1 : 4;+ break;+ case 2:+ if (unlikely (pin + 2 >= pinend))+ {+ elf_uncompress_failed ();+ return 0;+ }+ regenerated_size = (((uint32_t)hdr >> 4)+ | ((uint32_t)*pin << 4)+ | (((uint32_t)pin[1] & 3) << 12));+ compressed_size = (((uint32_t)pin[1] >> 2)+ | ((uint32_t)pin[2] << 6));+ pin += 3;+ streams = 4;+ break;+ case 3:+ if (unlikely (pin + 3 >= pinend))+ {+ elf_uncompress_failed ();+ return 0;+ }+ regenerated_size = (((uint32_t)hdr >> 4)+ | ((uint32_t)*pin << 4)+ | (((uint32_t)pin[1] & 0x3f) << 12));+ compressed_size = (((uint32_t)pin[1] >> 6)+ | ((uint32_t)pin[2] << 2)+ | ((uint32_t)pin[3] << 10));+ pin += 4;+ streams = 4;+ break;+ default:+ elf_uncompress_failed ();+ return 0;+ }++ if (unlikely (pin + compressed_size > pinend))+ {+ elf_uncompress_failed ();+ return 0;+ }++ pinend = pin + compressed_size;+ *ppin = pinend;++ if (unlikely ((size_t)(poutend - pout) < regenerated_size))+ {+ elf_uncompress_failed ();+ return 0;+ }++ plit = poutend - regenerated_size;++ *pplit = plit;++ total_streams_size = compressed_size;+ if ((hdr & 3) == 2)+ {+ const unsigned char *ptable;++ /* Compressed_Literals_Block. Read Huffman tree. */++ ptable = pin;+ if (!elf_zstd_read_huff (&ptable, pinend, scratch, huffman_table,+ phuffman_table_bits))+ return 0;++ if (unlikely (total_streams_size < (size_t)(ptable - pin)))+ {+ elf_uncompress_failed ();+ return 0;+ }++ total_streams_size -= ptable - pin;+ pin = ptable;+ }+ else+ {+ /* Treeless_Literals_Block. Reuse previous Huffman tree. */+ if (unlikely (*phuffman_table_bits == 0))+ {+ elf_uncompress_failed ();+ return 0;+ }+ }++ /* Decompress COMPRESSED_SIZE bytes of data at PIN using the huffman table,+ storing REGENERATED_SIZE bytes of decompressed data at PLIT. */++ huffman_table_bits = (unsigned int)*phuffman_table_bits;+ huffman_mask = ((uint64_t)1 << huffman_table_bits) - 1;++ if (streams == 1)+ {+ const unsigned char *pback;+ const unsigned char *pbackend;+ uint64_t val;+ unsigned int bits;+ uint32_t i;++ pback = pin + total_streams_size - 1;+ pbackend = pin;+ if (!elf_fetch_backward_init (&pback, pbackend, &val, &bits))+ return 0;++ /* This is one of the inner loops of the decompression algorithm, so we+ put some effort into optimization. We can't get more than 64 bytes+ from a single call to elf_fetch_bits_backward, and we can't subtract+ more than 11 bits at a time. */++ if (regenerated_size >= 64)+ {+ unsigned char *plitstart;+ unsigned char *plitstop;++ plitstart = plit;+ plitstop = plit + regenerated_size - 64;+ while (plit < plitstop)+ {+ uint16_t t;++ if (!elf_fetch_bits_backward (&pback, pbackend, &val, &bits))+ return 0;++ if (bits < 16)+ break;++ while (bits >= 33)+ {+ t = huffman_table[(val >> (bits - huffman_table_bits))+ & huffman_mask];+ *plit = t >> 8;+ ++plit;+ bits -= t & 0xff;++ t = huffman_table[(val >> (bits - huffman_table_bits))+ & huffman_mask];+ *plit = t >> 8;+ ++plit;+ bits -= t & 0xff;++ t = huffman_table[(val >> (bits - huffman_table_bits))+ & huffman_mask];+ *plit = t >> 8;+ ++plit;+ bits -= t & 0xff;+ }++ while (bits > 11)+ {+ t = huffman_table[(val >> (bits - huffman_table_bits))+ & huffman_mask];+ *plit = t >> 8;+ ++plit;+ bits -= t & 0xff;+ }+ }++ regenerated_size -= plit - plitstart;+ }++ for (i = 0; i < regenerated_size; ++i)+ {+ uint16_t t;++ if (!elf_fetch_bits_backward (&pback, pbackend, &val, &bits))+ return 0;++ if (unlikely (bits < huffman_table_bits))+ {+ t = huffman_table[(val << (huffman_table_bits - bits))+ & huffman_mask];+ if (unlikely (bits < (t & 0xff)))+ {+ elf_uncompress_failed ();+ return 0;+ }+ }+ else+ t = huffman_table[(val >> (bits - huffman_table_bits))+ & huffman_mask];++ *plit = t >> 8;+ ++plit;+ bits -= t & 0xff;+ }++ return 1;+ }++ {+ uint32_t stream_size1, stream_size2, stream_size3, stream_size4;+ uint32_t tot;+ const unsigned char *pback1, *pback2, *pback3, *pback4;+ const unsigned char *pbackend1, *pbackend2, *pbackend3, *pbackend4;+ uint64_t val1, val2, val3, val4;+ unsigned int bits1, bits2, bits3, bits4;+ unsigned char *plit1, *plit2, *plit3, *plit4;+ uint32_t regenerated_stream_size;+ uint32_t regenerated_stream_size4;+ uint16_t t1, t2, t3, t4;+ uint32_t i;+ uint32_t limit;++ /* Read jump table. */+ if (unlikely (pin + 5 >= pinend))+ {+ elf_uncompress_failed ();+ return 0;+ }+ stream_size1 = (uint32_t)*pin | ((uint32_t)pin[1] << 8);+ pin += 2;+ stream_size2 = (uint32_t)*pin | ((uint32_t)pin[1] << 8);+ pin += 2;+ stream_size3 = (uint32_t)*pin | ((uint32_t)pin[1] << 8);+ pin += 2;+ tot = stream_size1 + stream_size2 + stream_size3;+ if (unlikely (tot > total_streams_size - 6))+ {+ elf_uncompress_failed ();+ return 0;+ }+ stream_size4 = total_streams_size - 6 - tot;++ pback1 = pin + stream_size1 - 1;+ pbackend1 = pin;++ pback2 = pback1 + stream_size2;+ pbackend2 = pback1 + 1;++ pback3 = pback2 + stream_size3;+ pbackend3 = pback2 + 1;++ pback4 = pback3 + stream_size4;+ pbackend4 = pback3 + 1;++ if (!elf_fetch_backward_init (&pback1, pbackend1, &val1, &bits1))+ return 0;+ if (!elf_fetch_backward_init (&pback2, pbackend2, &val2, &bits2))+ return 0;+ if (!elf_fetch_backward_init (&pback3, pbackend3, &val3, &bits3))+ return 0;+ if (!elf_fetch_backward_init (&pback4, pbackend4, &val4, &bits4))+ return 0;++ regenerated_stream_size = (regenerated_size + 3) / 4;++ plit1 = plit;+ plit2 = plit1 + regenerated_stream_size;+ plit3 = plit2 + regenerated_stream_size;+ plit4 = plit3 + regenerated_stream_size;++ regenerated_stream_size4 = regenerated_size - regenerated_stream_size * 3;++ /* We can't get more than 64 literal bytes from a single call to+ elf_fetch_bits_backward. The fourth stream can be up to 3 bytes less,+ so use as the limit. */++ limit = regenerated_stream_size4 <= 64 ? 0 : regenerated_stream_size4 - 64;+ i = 0;+ while (i < limit)+ {+ if (!elf_fetch_bits_backward (&pback1, pbackend1, &val1, &bits1))+ return 0;+ if (!elf_fetch_bits_backward (&pback2, pbackend2, &val2, &bits2))+ return 0;+ if (!elf_fetch_bits_backward (&pback3, pbackend3, &val3, &bits3))+ return 0;+ if (!elf_fetch_bits_backward (&pback4, pbackend4, &val4, &bits4))+ return 0;++ /* We can't subtract more than 11 bits at a time. */++ do+ {+ t1 = huffman_table[(val1 >> (bits1 - huffman_table_bits))+ & huffman_mask];+ t2 = huffman_table[(val2 >> (bits2 - huffman_table_bits))+ & huffman_mask];+ t3 = huffman_table[(val3 >> (bits3 - huffman_table_bits))+ & huffman_mask];+ t4 = huffman_table[(val4 >> (bits4 - huffman_table_bits))+ & huffman_mask];++ *plit1 = t1 >> 8;+ ++plit1;+ bits1 -= t1 & 0xff;++ *plit2 = t2 >> 8;+ ++plit2;+ bits2 -= t2 & 0xff;++ *plit3 = t3 >> 8;+ ++plit3;+ bits3 -= t3 & 0xff;++ *plit4 = t4 >> 8;+ ++plit4;+ bits4 -= t4 & 0xff;++ ++i;+ }+ while (bits1 > 11 && bits2 > 11 && bits3 > 11 && bits4 > 11);+ }++ while (i < regenerated_stream_size)+ {+ int use4;++ use4 = i < regenerated_stream_size4;++ if (!elf_fetch_bits_backward (&pback1, pbackend1, &val1, &bits1))+ return 0;+ if (!elf_fetch_bits_backward (&pback2, pbackend2, &val2, &bits2))+ return 0;+ if (!elf_fetch_bits_backward (&pback3, pbackend3, &val3, &bits3))+ return 0;+ if (use4)+ {+ if (!elf_fetch_bits_backward (&pback4, pbackend4, &val4, &bits4))+ return 0;+ }++ if (unlikely (bits1 < huffman_table_bits))+ {+ t1 = huffman_table[(val1 << (huffman_table_bits - bits1))+ & huffman_mask];+ if (unlikely (bits1 < (t1 & 0xff)))+ {+ elf_uncompress_failed ();+ return 0;+ }+ }+ else+ t1 = huffman_table[(val1 >> (bits1 - huffman_table_bits))+ & huffman_mask];++ if (unlikely (bits2 < huffman_table_bits))+ {+ t2 = huffman_table[(val2 << (huffman_table_bits - bits2))+ & huffman_mask];+ if (unlikely (bits2 < (t2 & 0xff)))+ {+ elf_uncompress_failed ();+ return 0;+ }+ }+ else+ t2 = huffman_table[(val2 >> (bits2 - huffman_table_bits))+ & huffman_mask];++ if (unlikely (bits3 < huffman_table_bits))+ {+ t3 = huffman_table[(val3 << (huffman_table_bits - bits3))+ & huffman_mask];+ if (unlikely (bits3 < (t3 & 0xff)))+ {+ elf_uncompress_failed ();+ return 0;+ }+ }+ else+ t3 = huffman_table[(val3 >> (bits3 - huffman_table_bits))+ & huffman_mask];++ if (use4)+ {+ if (unlikely (bits4 < huffman_table_bits))+ {+ t4 = huffman_table[(val4 << (huffman_table_bits - bits4))+ & huffman_mask];+ if (unlikely (bits4 < (t4 & 0xff)))+ {+ elf_uncompress_failed ();+ return 0;+ }+ }+ else+ t4 = huffman_table[(val4 >> (bits4 - huffman_table_bits))+ & huffman_mask];++ *plit4 = t4 >> 8;+ ++plit4;+ bits4 -= t4 & 0xff;+ }++ *plit1 = t1 >> 8;+ ++plit1;+ bits1 -= t1 & 0xff;++ *plit2 = t2 >> 8;+ ++plit2;+ bits2 -= t2 & 0xff;++ *plit3 = t3 >> 8;+ ++plit3;+ bits3 -= t3 & 0xff;++ ++i;+ }+ }++ return 1;+}++/* The information used to decompress a sequence code, which can be a literal+ length, an offset, or a match length. */++struct elf_zstd_seq_decode+{+ const struct elf_zstd_fse_baseline_entry *table;+ int table_bits;+};++/* Unpack a sequence code compression mode. */++static int+elf_zstd_unpack_seq_decode (int mode,+ const unsigned char **ppin,+ const unsigned char *pinend,+ const struct elf_zstd_fse_baseline_entry *predef,+ int predef_bits,+ uint16_t *scratch,+ int maxidx,+ struct elf_zstd_fse_baseline_entry *table,+ int table_bits,+ int (*conv)(const struct elf_zstd_fse_entry *,+ int,+ struct elf_zstd_fse_baseline_entry *),+ struct elf_zstd_seq_decode *decode)+{+ switch (mode)+ {+ case 0:+ decode->table = predef;+ decode->table_bits = predef_bits;+ break;++ case 1:+ {+ struct elf_zstd_fse_entry entry;++ if (unlikely (*ppin >= pinend))+ {+ elf_uncompress_failed ();+ return 0;+ }+ entry.symbol = **ppin;+ ++*ppin;+ entry.bits = 0;+ entry.base = 0;+ decode->table_bits = 0;+ if (!conv (&entry, 0, table))+ return 0;+ }+ break;++ case 2:+ {+ struct elf_zstd_fse_entry *fse_table;++ /* We use the same space for the simple FSE table and the baseline+ table. */+ fse_table = (struct elf_zstd_fse_entry *)table;+ decode->table_bits = table_bits;+ if (!elf_zstd_read_fse (ppin, pinend, scratch, maxidx, fse_table,+ &decode->table_bits))+ return 0;+ if (!conv (fse_table, decode->table_bits, table))+ return 0;+ decode->table = table;+ }+ break;++ case 3:+ if (unlikely (decode->table_bits == -1))+ {+ elf_uncompress_failed ();+ return 0;+ }+ break;++ default:+ elf_uncompress_failed ();+ return 0;+ }++ return 1;+}++/* Decompress a zstd stream from PIN/SIN to POUT/SOUT. Code based on RFC 8878.+ Return 1 on success, 0 on error. */++static int+elf_zstd_decompress (const unsigned char *pin, size_t sin,+ unsigned char *zdebug_table, unsigned char *pout,+ size_t sout)+{+ const unsigned char *pinend;+ unsigned char *poutstart;+ unsigned char *poutend;+ struct elf_zstd_seq_decode literal_decode;+ struct elf_zstd_fse_baseline_entry *literal_fse_table;+ struct elf_zstd_seq_decode match_decode;+ struct elf_zstd_fse_baseline_entry *match_fse_table;+ struct elf_zstd_seq_decode offset_decode;+ struct elf_zstd_fse_baseline_entry *offset_fse_table;+ uint16_t *huffman_table;+ int huffman_table_bits;+ uint32_t repeated_offset1;+ uint32_t repeated_offset2;+ uint32_t repeated_offset3;+ uint16_t *scratch;+ unsigned char hdr;+ int has_checksum;+ uint64_t content_size;+ int last_block;++ pinend = pin + sin;+ poutstart = pout;+ poutend = pout + sout;++ literal_decode.table = NULL;+ literal_decode.table_bits = -1;+ literal_fse_table = ((struct elf_zstd_fse_baseline_entry *)+ (zdebug_table + ZSTD_TABLE_LITERAL_FSE_OFFSET));++ match_decode.table = NULL;+ match_decode.table_bits = -1;+ match_fse_table = ((struct elf_zstd_fse_baseline_entry *)+ (zdebug_table + ZSTD_TABLE_MATCH_FSE_OFFSET));++ offset_decode.table = NULL;+ offset_decode.table_bits = -1;+ offset_fse_table = ((struct elf_zstd_fse_baseline_entry *)+ (zdebug_table + ZSTD_TABLE_OFFSET_FSE_OFFSET));+ huffman_table = ((uint16_t *)+ (zdebug_table + ZSTD_TABLE_HUFFMAN_OFFSET));+ huffman_table_bits = 0;+ scratch = ((uint16_t *)+ (zdebug_table + ZSTD_TABLE_WORK_OFFSET));++ repeated_offset1 = 1;+ repeated_offset2 = 4;+ repeated_offset3 = 8;++ if (unlikely (sin < 4))+ {+ elf_uncompress_failed ();+ return 0;+ }++ /* These values are the zstd magic number. */+ if (unlikely (pin[0] != 0x28+ || pin[1] != 0xb5+ || pin[2] != 0x2f+ || pin[3] != 0xfd))+ {+ elf_uncompress_failed ();+ return 0;+ }++ pin += 4;++ if (unlikely (pin >= pinend))+ {+ elf_uncompress_failed ();+ return 0;+ }++ hdr = *pin++;++ /* We expect a single frame. */+ if (unlikely ((hdr & (1 << 5)) == 0))+ {+ elf_uncompress_failed ();+ return 0;+ }+ /* Reserved bit must be zero. */+ if (unlikely ((hdr & (1 << 3)) != 0))+ {+ elf_uncompress_failed ();+ return 0;+ }+ /* We do not expect a dictionary. */+ if (unlikely ((hdr & 3) != 0))+ {+ elf_uncompress_failed ();+ return 0;+ }+ has_checksum = (hdr & (1 << 2)) != 0;+ switch (hdr >> 6)+ {+ case 0:+ if (unlikely (pin >= pinend))+ {+ elf_uncompress_failed ();+ return 0;+ }+ content_size = (uint64_t) *pin++;+ break;+ case 1:+ if (unlikely (pin + 1 >= pinend))+ {+ elf_uncompress_failed ();+ return 0;+ }+ content_size = (((uint64_t) pin[0]) | (((uint64_t) pin[1]) << 8)) + 256;+ pin += 2;+ break;+ case 2:+ if (unlikely (pin + 3 >= pinend))+ {+ elf_uncompress_failed ();+ return 0;+ }+ content_size = ((uint64_t) pin[0]+ | (((uint64_t) pin[1]) << 8)+ | (((uint64_t) pin[2]) << 16)+ | (((uint64_t) pin[3]) << 24));+ pin += 4;+ break;+ case 3:+ if (unlikely (pin + 7 >= pinend))+ {+ elf_uncompress_failed ();+ return 0;+ }+ content_size = ((uint64_t) pin[0]+ | (((uint64_t) pin[1]) << 8)+ | (((uint64_t) pin[2]) << 16)+ | (((uint64_t) pin[3]) << 24)+ | (((uint64_t) pin[4]) << 32)+ | (((uint64_t) pin[5]) << 40)+ | (((uint64_t) pin[6]) << 48)+ | (((uint64_t) pin[7]) << 56));+ pin += 8;+ break;+ default:+ elf_uncompress_failed ();+ return 0;+ }++ if (unlikely (content_size != (size_t) content_size+ || (size_t) content_size != sout))+ {+ elf_uncompress_failed ();+ return 0;+ }++ last_block = 0;+ while (!last_block)+ {+ uint32_t block_hdr;+ int block_type;+ uint32_t block_size;++ if (unlikely (pin + 2 >= pinend))+ {+ elf_uncompress_failed ();+ return 0;+ }+ block_hdr = ((uint32_t) pin[0]+ | (((uint32_t) pin[1]) << 8)+ | (((uint32_t) pin[2]) << 16));+ pin += 3;++ last_block = block_hdr & 1;+ block_type = (block_hdr >> 1) & 3;+ block_size = block_hdr >> 3;++ switch (block_type)+ {+ case 0:+ /* Raw_Block */+ if (unlikely ((size_t) block_size > (size_t) (pinend - pin)))+ {+ elf_uncompress_failed ();+ return 0;+ }+ if (unlikely ((size_t) block_size > (size_t) (poutend - pout)))+ {+ elf_uncompress_failed ();+ return 0;+ }+ memcpy (pout, pin, block_size);+ pout += block_size;+ pin += block_size;+ break;++ case 1:+ /* RLE_Block */+ if (unlikely (pin >= pinend))+ {+ elf_uncompress_failed ();+ return 0;+ }+ if (unlikely ((size_t) block_size > (size_t) (poutend - pout)))+ {+ elf_uncompress_failed ();+ return 0;+ }+ memset (pout, *pin, block_size);+ pout += block_size;+ pin++;+ break;++ case 2:+ {+ const unsigned char *pblockend;+ unsigned char *plitstack;+ unsigned char *plit;+ uint32_t literal_count;+ unsigned char seq_hdr;+ size_t seq_count;+ size_t seq;+ const unsigned char *pback;+ uint64_t val;+ unsigned int bits;+ unsigned int literal_state;+ unsigned int offset_state;+ unsigned int match_state;++ /* Compressed_Block */+ if (unlikely ((size_t) block_size > (size_t) (pinend - pin)))+ {+ elf_uncompress_failed ();+ return 0;+ }++ pblockend = pin + block_size;++ /* Read the literals into the end of the output space, and leave+ PLIT pointing at them. */++ if (!elf_zstd_read_literals (&pin, pblockend, pout, poutend,+ scratch, huffman_table,+ &huffman_table_bits,+ &plitstack))+ return 0;+ plit = plitstack;+ literal_count = poutend - plit;++ seq_hdr = *pin;+ pin++;+ if (seq_hdr < 128)+ seq_count = seq_hdr;+ else if (seq_hdr < 255)+ {+ if (unlikely (pin >= pinend))+ {+ elf_uncompress_failed ();+ return 0;+ }+ seq_count = ((seq_hdr - 128) << 8) + *pin;+ pin++;+ }+ else+ {+ if (unlikely (pin + 1 >= pinend))+ {+ elf_uncompress_failed ();+ return 0;+ }+ seq_count = *pin + (pin[1] << 8) + 0x7f00;+ pin += 2;+ }++ if (seq_count > 0)+ {+ int (*pfn)(const struct elf_zstd_fse_entry *,+ int, struct elf_zstd_fse_baseline_entry *);++ if (unlikely (pin >= pinend))+ {+ elf_uncompress_failed ();+ return 0;+ }+ seq_hdr = *pin;+ ++pin;++ pfn = elf_zstd_make_literal_baseline_fse;+ if (!elf_zstd_unpack_seq_decode ((seq_hdr >> 6) & 3,+ &pin, pinend,+ &elf_zstd_lit_table[0], 6,+ scratch, 35,+ literal_fse_table, 9, pfn,+ &literal_decode))+ return 0;++ pfn = elf_zstd_make_offset_baseline_fse;+ if (!elf_zstd_unpack_seq_decode ((seq_hdr >> 4) & 3,+ &pin, pinend,+ &elf_zstd_offset_table[0], 5,+ scratch, 31,+ offset_fse_table, 8, pfn,+ &offset_decode))+ return 0;++ pfn = elf_zstd_make_match_baseline_fse;+ if (!elf_zstd_unpack_seq_decode ((seq_hdr >> 2) & 3,+ &pin, pinend,+ &elf_zstd_match_table[0], 6,+ scratch, 52,+ match_fse_table, 9, pfn,+ &match_decode))+ return 0;+ }++ pback = pblockend - 1;+ if (!elf_fetch_backward_init (&pback, pin, &val, &bits))+ return 0;++ bits -= literal_decode.table_bits;+ literal_state = ((val >> bits)+ & ((1U << literal_decode.table_bits) - 1));++ if (!elf_fetch_bits_backward (&pback, pin, &val, &bits))+ return 0;+ bits -= offset_decode.table_bits;+ offset_state = ((val >> bits)+ & ((1U << offset_decode.table_bits) - 1));++ if (!elf_fetch_bits_backward (&pback, pin, &val, &bits))+ return 0;+ bits -= match_decode.table_bits;+ match_state = ((val >> bits)+ & ((1U << match_decode.table_bits) - 1));++ seq = 0;+ while (1)+ {+ const struct elf_zstd_fse_baseline_entry *pt;+ uint32_t offset_basebits;+ uint32_t offset_baseline;+ uint32_t offset_bits;+ uint32_t offset_base;+ uint32_t offset;+ uint32_t match_baseline;+ uint32_t match_bits;+ uint32_t match_base;+ uint32_t match;+ uint32_t literal_baseline;+ uint32_t literal_bits;+ uint32_t literal_base;+ uint32_t literal;+ uint32_t need;+ uint32_t add;++ pt = &offset_decode.table[offset_state];+ offset_basebits = pt->basebits;+ offset_baseline = pt->baseline;+ offset_bits = pt->bits;+ offset_base = pt->base;++ /* This case can be more than 16 bits, which is all that+ elf_fetch_bits_backward promises. */+ need = offset_basebits;+ add = 0;+ if (unlikely (need > 16))+ {+ if (!elf_fetch_bits_backward (&pback, pin, &val, &bits))+ return 0;+ bits -= 16;+ add = (val >> bits) & ((1U << 16) - 1);+ need -= 16;+ add <<= need;+ }+ if (need > 0)+ {+ if (!elf_fetch_bits_backward (&pback, pin, &val, &bits))+ return 0;+ bits -= need;+ add += (val >> bits) & ((1U << need) - 1);+ }++ offset = offset_baseline + add;++ pt = &match_decode.table[match_state];+ need = pt->basebits;+ match_baseline = pt->baseline;+ match_bits = pt->bits;+ match_base = pt->base;++ add = 0;+ if (need > 0)+ {+ if (!elf_fetch_bits_backward (&pback, pin, &val, &bits))+ return 0;+ bits -= need;+ add = (val >> bits) & ((1U << need) - 1);+ }++ match = match_baseline + add;++ pt = &literal_decode.table[literal_state];+ need = pt->basebits;+ literal_baseline = pt->baseline;+ literal_bits = pt->bits;+ literal_base = pt->base;++ add = 0;+ if (need > 0)+ {+ if (!elf_fetch_bits_backward (&pback, pin, &val, &bits))+ return 0;+ bits -= need;+ add = (val >> bits) & ((1U << need) - 1);+ }++ literal = literal_baseline + add;++ /* See the comment in elf_zstd_make_offset_baseline_fse. */+ if (offset_basebits > 1)+ {+ repeated_offset3 = repeated_offset2;+ repeated_offset2 = repeated_offset1;+ repeated_offset1 = offset;+ }+ else+ {+ if (unlikely (literal == 0))+ ++offset;+ switch (offset)+ {+ case 1:+ offset = repeated_offset1;+ break;+ case 2:+ offset = repeated_offset2;+ repeated_offset2 = repeated_offset1;+ repeated_offset1 = offset;+ break;+ case 3:+ offset = repeated_offset3;+ repeated_offset3 = repeated_offset2;+ repeated_offset2 = repeated_offset1;+ repeated_offset1 = offset;+ break;+ case 4:+ offset = repeated_offset1 - 1;+ repeated_offset3 = repeated_offset2;+ repeated_offset2 = repeated_offset1;+ repeated_offset1 = offset;+ break;+ }+ }++ ++seq;+ if (seq < seq_count)+ {+ uint32_t v;++ /* Update the three states. */++ if (!elf_fetch_bits_backward (&pback, pin, &val, &bits))+ return 0;++ need = literal_bits;+ bits -= need;+ v = (val >> bits) & (((uint32_t)1 << need) - 1);++ literal_state = literal_base + v;++ if (!elf_fetch_bits_backward (&pback, pin, &val, &bits))+ return 0;++ need = match_bits;+ bits -= need;+ v = (val >> bits) & (((uint32_t)1 << need) - 1);++ match_state = match_base + v;++ if (!elf_fetch_bits_backward (&pback, pin, &val, &bits))+ return 0;++ need = offset_bits;+ bits -= need;+ v = (val >> bits) & (((uint32_t)1 << need) - 1);++ offset_state = offset_base + v;+ }++ /* The next sequence is now in LITERAL, OFFSET, MATCH. */++ /* Copy LITERAL bytes from the literals. */++ if (unlikely ((size_t)(poutend - pout) < literal))+ {+ elf_uncompress_failed ();+ return 0;+ }++ if (unlikely (literal_count < literal))+ {+ elf_uncompress_failed ();+ return 0;+ }++ literal_count -= literal;++ /* Often LITERAL is small, so handle small cases quickly. */+ switch (literal)+ {+ case 8:+ *pout++ = *plit++;+ /* FALLTHROUGH */+ case 7:+ *pout++ = *plit++;+ /* FALLTHROUGH */+ case 6:+ *pout++ = *plit++;+ /* FALLTHROUGH */+ case 5:+ *pout++ = *plit++;+ /* FALLTHROUGH */+ case 4:+ *pout++ = *plit++;+ /* FALLTHROUGH */+ case 3:+ *pout++ = *plit++;+ /* FALLTHROUGH */+ case 2:+ *pout++ = *plit++;+ /* FALLTHROUGH */+ case 1:+ *pout++ = *plit++;+ break;++ case 0:+ break;++ default:+ if (unlikely ((size_t)(plit - pout) < literal))+ {+ uint32_t move;++ move = plit - pout;+ while (literal > move)+ {+ memcpy (pout, plit, move);+ pout += move;+ plit += move;+ literal -= move;+ }+ }++ memcpy (pout, plit, literal);+ pout += literal;+ plit += literal;+ }++ if (match > 0)+ {+ /* Copy MATCH bytes from the decoded output at OFFSET. */++ if (unlikely ((size_t)(poutend - pout) < match))+ {+ elf_uncompress_failed ();+ return 0;+ }++ if (unlikely ((size_t)(pout - poutstart) < offset))+ {+ elf_uncompress_failed ();+ return 0;+ }++ if (offset >= match)+ {+ memcpy (pout, pout - offset, match);+ pout += match;+ }+ else+ {+ while (match > 0)+ {+ uint32_t copy;++ copy = match < offset ? match : offset;+ memcpy (pout, pout - offset, copy);+ match -= copy;+ pout += copy;+ }+ }+ }++ if (unlikely (seq >= seq_count))+ {+ /* Copy remaining literals. */+ if (literal_count > 0 && plit != pout)+ {+ if (unlikely ((size_t)(poutend - pout)+ < literal_count))+ {+ elf_uncompress_failed ();+ return 0;+ }++ if ((size_t)(plit - pout) < literal_count)+ {+ uint32_t move;++ move = plit - pout;+ while (literal_count > move)+ {+ memcpy (pout, plit, move);+ pout += move;+ plit += move;+ literal_count -= move;+ }+ }++ memcpy (pout, plit, literal_count);+ }++ pout += literal_count;++ break;+ }+ }++ pin = pblockend;+ }+ break;++ case 3:+ default:+ elf_uncompress_failed ();+ return 0;+ }+ }++ if (has_checksum)+ {+ if (unlikely (pin + 4 > pinend))+ {+ elf_uncompress_failed ();+ return 0;+ }++ /* We don't currently verify the checksum. Currently running GNU ld with+ --compress-debug-sections=zstd does not seem to generate a+ checksum. */++ pin += 4;+ }++ if (pin != pinend)+ {+ elf_uncompress_failed ();+ return 0;+ }++ return 1;+}++#define ZDEBUG_TABLE_SIZE \+ (ZLIB_TABLE_SIZE > ZSTD_TABLE_SIZE ? ZLIB_TABLE_SIZE : ZSTD_TABLE_SIZE)++/* Uncompress the old compressed debug format, the one emitted by+ --compress-debug-sections=zlib-gnu. The compressed data is in+ COMPRESSED / COMPRESSED_SIZE, and the function writes to+ *UNCOMPRESSED / *UNCOMPRESSED_SIZE. ZDEBUG_TABLE is work space to+ hold Huffman tables. Returns 0 on error, 1 on successful+ decompression or if something goes wrong. In general we try to+ carry on, by returning 1, even if we can't decompress. */++static int+elf_uncompress_zdebug (struct backtrace_state *state,+ const unsigned char *compressed, size_t compressed_size,+ uint16_t *zdebug_table,+ backtrace_error_callback error_callback, void *data,+ unsigned char **uncompressed, size_t *uncompressed_size)+{+ size_t sz;+ size_t i;+ unsigned char *po;++ *uncompressed = NULL;+ *uncompressed_size = 0;++ /* The format starts with the four bytes ZLIB, followed by the 8+ byte length of the uncompressed data in big-endian order,+ followed by a zlib stream. */++ if (compressed_size < 12 || memcmp (compressed, "ZLIB", 4) != 0)+ return 1;++ sz = 0;+ for (i = 0; i < 8; i++)+ sz = (sz << 8) | compressed[i + 4];++ if (*uncompressed != NULL && *uncompressed_size >= sz)+ po = *uncompressed;+ else+ {+ po = (unsigned char *) backtrace_alloc (state, sz, error_callback, data);+ if (po == NULL)+ return 0;+ }++ if (!elf_zlib_inflate_and_verify (compressed + 12, compressed_size - 12,+ zdebug_table, po, sz))+ return 1;++ *uncompressed = po;+ *uncompressed_size = sz;++ return 1;+}++/* Uncompress the new compressed debug format, the official standard+ ELF approach emitted by --compress-debug-sections=zlib-gabi. The+ compressed data is in COMPRESSED / COMPRESSED_SIZE, and the+ function writes to *UNCOMPRESSED / *UNCOMPRESSED_SIZE.+ ZDEBUG_TABLE is work space as for elf_uncompress_zdebug. Returns 0+ on error, 1 on successful decompression or if something goes wrong.+ In general we try to carry on, by returning 1, even if we can't+ decompress. */++static int+elf_uncompress_chdr (struct backtrace_state *state,+ const unsigned char *compressed, size_t compressed_size,+ uint16_t *zdebug_table,+ backtrace_error_callback error_callback, void *data,+ unsigned char **uncompressed, size_t *uncompressed_size)+{+ b_elf_chdr chdr;+ char *alc;+ size_t alc_len;+ unsigned char *po;++ *uncompressed = NULL;+ *uncompressed_size = 0;++ /* The format starts with an ELF compression header. */+ if (compressed_size < sizeof (b_elf_chdr))+ return 1;++ /* The lld linker can misalign a compressed section, so we can't safely read+ the fields directly as we can for other ELF sections. See+ https://github.com/ianlancetaylor/libbacktrace/pull/120. */+ memcpy (&chdr, compressed, sizeof (b_elf_chdr));++ alc = NULL;+ alc_len = 0;+ if (*uncompressed != NULL && *uncompressed_size >= chdr.ch_size)+ po = *uncompressed;+ else+ {+ alc_len = chdr.ch_size;+ alc = (char*)backtrace_alloc (state, alc_len, error_callback, data);+ if (alc == NULL)+ return 0;+ po = (unsigned char *) alc;+ }++ switch (chdr.ch_type)+ {+ case ELFCOMPRESS_ZLIB:+ if (!elf_zlib_inflate_and_verify (compressed + sizeof (b_elf_chdr),+ compressed_size - sizeof (b_elf_chdr),+ zdebug_table, po, chdr.ch_size))+ goto skip;+ break;++ case ELFCOMPRESS_ZSTD:+ if (!elf_zstd_decompress (compressed + sizeof (b_elf_chdr),+ compressed_size - sizeof (b_elf_chdr),+ (unsigned char *)zdebug_table, po,+ chdr.ch_size))+ goto skip;+ break;++ default:+ /* Unsupported compression algorithm. */+ goto skip;+ }++ *uncompressed = po;+ *uncompressed_size = chdr.ch_size;++ return 1;++ skip:+ if (alc != NULL && alc_len > 0)+ backtrace_free (state, alc, alc_len, error_callback, data);+ return 1;+}++/* This function is a hook for testing the zlib support. It is only+ used by tests. */++int+backtrace_uncompress_zdebug (struct backtrace_state *state,+ const unsigned char *compressed,+ size_t compressed_size,+ backtrace_error_callback error_callback,+ void *data, unsigned char **uncompressed,+ size_t *uncompressed_size)+{+ uint16_t *zdebug_table;+ int ret;++ zdebug_table = ((uint16_t *) backtrace_alloc (state, ZDEBUG_TABLE_SIZE,+ error_callback, data));+ if (zdebug_table == NULL)+ return 0;+ ret = elf_uncompress_zdebug (state, compressed, compressed_size,+ zdebug_table, error_callback, data,+ uncompressed, uncompressed_size);+ backtrace_free (state, zdebug_table, ZDEBUG_TABLE_SIZE,+ error_callback, data);+ return ret;+}++/* This function is a hook for testing the zstd support. It is only used by+ tests. */++int+backtrace_uncompress_zstd (struct backtrace_state *state,+ const unsigned char *compressed,+ size_t compressed_size,+ backtrace_error_callback error_callback,+ void *data, unsigned char *uncompressed,+ size_t uncompressed_size)+{+ unsigned char *zdebug_table;+ int ret;++ zdebug_table = ((unsigned char *) backtrace_alloc (state, ZDEBUG_TABLE_SIZE,+ error_callback, data));+ if (zdebug_table == NULL)+ return 0;+ ret = elf_zstd_decompress (compressed, compressed_size,+ zdebug_table, uncompressed, uncompressed_size);+ backtrace_free (state, zdebug_table, ZDEBUG_TABLE_SIZE,+ error_callback, data);+ return ret;+}++/* Number of LZMA states. */+#define LZMA_STATES (12)++/* Number of LZMA position states. The pb value of the property byte+ is the number of bits to include in these states, and the maximum+ value of pb is 4. */+#define LZMA_POS_STATES (16)++/* Number of LZMA distance states. These are used match distances+ with a short match length: up to 4 bytes. */+#define LZMA_DIST_STATES (4)++/* Number of LZMA distance slots. LZMA uses six bits to encode larger+ match lengths, so 1 << 6 possible probabilities. */+#define LZMA_DIST_SLOTS (64)++/* LZMA distances 0 to 3 are encoded directly, larger values use a+ probability model. */+#define LZMA_DIST_MODEL_START (4)++/* The LZMA probability model ends at 14. */+#define LZMA_DIST_MODEL_END (14)++/* LZMA distance slots for distances less than 127. */+#define LZMA_FULL_DISTANCES (128)++/* LZMA uses four alignment bits. */+#define LZMA_ALIGN_SIZE (16)++/* LZMA match length is encoded with 4, 5, or 10 bits, some of which+ are already known. */+#define LZMA_LEN_LOW_SYMBOLS (8)+#define LZMA_LEN_MID_SYMBOLS (8)+#define LZMA_LEN_HIGH_SYMBOLS (256)++/* LZMA literal encoding. */+#define LZMA_LITERAL_CODERS_MAX (16)+#define LZMA_LITERAL_CODER_SIZE (0x300)++/* LZMA is based on a large set of probabilities, each managed+ independently. Each probability is an 11 bit number that we store+ in a uint16_t. We use a single large array of probabilities. */++/* Lengths of entries in the LZMA probabilities array. The names used+ here are copied from the Linux kernel implementation. */++#define LZMA_PROB_IS_MATCH_LEN (LZMA_STATES * LZMA_POS_STATES)+#define LZMA_PROB_IS_REP_LEN LZMA_STATES+#define LZMA_PROB_IS_REP0_LEN LZMA_STATES+#define LZMA_PROB_IS_REP1_LEN LZMA_STATES+#define LZMA_PROB_IS_REP2_LEN LZMA_STATES+#define LZMA_PROB_IS_REP0_LONG_LEN (LZMA_STATES * LZMA_POS_STATES)+#define LZMA_PROB_DIST_SLOT_LEN (LZMA_DIST_STATES * LZMA_DIST_SLOTS)+#define LZMA_PROB_DIST_SPECIAL_LEN (LZMA_FULL_DISTANCES - LZMA_DIST_MODEL_END)+#define LZMA_PROB_DIST_ALIGN_LEN LZMA_ALIGN_SIZE+#define LZMA_PROB_MATCH_LEN_CHOICE_LEN 1+#define LZMA_PROB_MATCH_LEN_CHOICE2_LEN 1+#define LZMA_PROB_MATCH_LEN_LOW_LEN (LZMA_POS_STATES * LZMA_LEN_LOW_SYMBOLS)+#define LZMA_PROB_MATCH_LEN_MID_LEN (LZMA_POS_STATES * LZMA_LEN_MID_SYMBOLS)+#define LZMA_PROB_MATCH_LEN_HIGH_LEN LZMA_LEN_HIGH_SYMBOLS+#define LZMA_PROB_REP_LEN_CHOICE_LEN 1+#define LZMA_PROB_REP_LEN_CHOICE2_LEN 1+#define LZMA_PROB_REP_LEN_LOW_LEN (LZMA_POS_STATES * LZMA_LEN_LOW_SYMBOLS)+#define LZMA_PROB_REP_LEN_MID_LEN (LZMA_POS_STATES * LZMA_LEN_MID_SYMBOLS)+#define LZMA_PROB_REP_LEN_HIGH_LEN LZMA_LEN_HIGH_SYMBOLS+#define LZMA_PROB_LITERAL_LEN \+ (LZMA_LITERAL_CODERS_MAX * LZMA_LITERAL_CODER_SIZE)++/* Offsets into the LZMA probabilities array. This is mechanically+ generated from the above lengths. */++#define LZMA_PROB_IS_MATCH_OFFSET 0+#define LZMA_PROB_IS_REP_OFFSET \+ (LZMA_PROB_IS_MATCH_OFFSET + LZMA_PROB_IS_MATCH_LEN)+#define LZMA_PROB_IS_REP0_OFFSET \+ (LZMA_PROB_IS_REP_OFFSET + LZMA_PROB_IS_REP_LEN)+#define LZMA_PROB_IS_REP1_OFFSET \+ (LZMA_PROB_IS_REP0_OFFSET + LZMA_PROB_IS_REP0_LEN)+#define LZMA_PROB_IS_REP2_OFFSET \+ (LZMA_PROB_IS_REP1_OFFSET + LZMA_PROB_IS_REP1_LEN)+#define LZMA_PROB_IS_REP0_LONG_OFFSET \+ (LZMA_PROB_IS_REP2_OFFSET + LZMA_PROB_IS_REP2_LEN)+#define LZMA_PROB_DIST_SLOT_OFFSET \+ (LZMA_PROB_IS_REP0_LONG_OFFSET + LZMA_PROB_IS_REP0_LONG_LEN)+#define LZMA_PROB_DIST_SPECIAL_OFFSET \+ (LZMA_PROB_DIST_SLOT_OFFSET + LZMA_PROB_DIST_SLOT_LEN)+#define LZMA_PROB_DIST_ALIGN_OFFSET \+ (LZMA_PROB_DIST_SPECIAL_OFFSET + LZMA_PROB_DIST_SPECIAL_LEN)+#define LZMA_PROB_MATCH_LEN_CHOICE_OFFSET \+ (LZMA_PROB_DIST_ALIGN_OFFSET + LZMA_PROB_DIST_ALIGN_LEN)+#define LZMA_PROB_MATCH_LEN_CHOICE2_OFFSET \+ (LZMA_PROB_MATCH_LEN_CHOICE_OFFSET + LZMA_PROB_MATCH_LEN_CHOICE_LEN)+#define LZMA_PROB_MATCH_LEN_LOW_OFFSET \+ (LZMA_PROB_MATCH_LEN_CHOICE2_OFFSET + LZMA_PROB_MATCH_LEN_CHOICE2_LEN)+#define LZMA_PROB_MATCH_LEN_MID_OFFSET \+ (LZMA_PROB_MATCH_LEN_LOW_OFFSET + LZMA_PROB_MATCH_LEN_LOW_LEN)+#define LZMA_PROB_MATCH_LEN_HIGH_OFFSET \+ (LZMA_PROB_MATCH_LEN_MID_OFFSET + LZMA_PROB_MATCH_LEN_MID_LEN)+#define LZMA_PROB_REP_LEN_CHOICE_OFFSET \+ (LZMA_PROB_MATCH_LEN_HIGH_OFFSET + LZMA_PROB_MATCH_LEN_HIGH_LEN)+#define LZMA_PROB_REP_LEN_CHOICE2_OFFSET \+ (LZMA_PROB_REP_LEN_CHOICE_OFFSET + LZMA_PROB_REP_LEN_CHOICE_LEN)+#define LZMA_PROB_REP_LEN_LOW_OFFSET \+ (LZMA_PROB_REP_LEN_CHOICE2_OFFSET + LZMA_PROB_REP_LEN_CHOICE2_LEN)+#define LZMA_PROB_REP_LEN_MID_OFFSET \+ (LZMA_PROB_REP_LEN_LOW_OFFSET + LZMA_PROB_REP_LEN_LOW_LEN)+#define LZMA_PROB_REP_LEN_HIGH_OFFSET \+ (LZMA_PROB_REP_LEN_MID_OFFSET + LZMA_PROB_REP_LEN_MID_LEN)+#define LZMA_PROB_LITERAL_OFFSET \+ (LZMA_PROB_REP_LEN_HIGH_OFFSET + LZMA_PROB_REP_LEN_HIGH_LEN)++#define LZMA_PROB_TOTAL_COUNT \+ (LZMA_PROB_LITERAL_OFFSET + LZMA_PROB_LITERAL_LEN)++/* Check that the number of LZMA probabilities is the same as the+ Linux kernel implementation. */++#if LZMA_PROB_TOTAL_COUNT != 1846 + (1 << 4) * 0x300+ #error Wrong number of LZMA probabilities+#endif++/* Expressions for the offset in the LZMA probabilities array of a+ specific probability. */++#define LZMA_IS_MATCH(state, pos) \+ (LZMA_PROB_IS_MATCH_OFFSET + (state) * LZMA_POS_STATES + (pos))+#define LZMA_IS_REP(state) \+ (LZMA_PROB_IS_REP_OFFSET + (state))+#define LZMA_IS_REP0(state) \+ (LZMA_PROB_IS_REP0_OFFSET + (state))+#define LZMA_IS_REP1(state) \+ (LZMA_PROB_IS_REP1_OFFSET + (state))+#define LZMA_IS_REP2(state) \+ (LZMA_PROB_IS_REP2_OFFSET + (state))+#define LZMA_IS_REP0_LONG(state, pos) \+ (LZMA_PROB_IS_REP0_LONG_OFFSET + (state) * LZMA_POS_STATES + (pos))+#define LZMA_DIST_SLOT(dist, slot) \+ (LZMA_PROB_DIST_SLOT_OFFSET + (dist) * LZMA_DIST_SLOTS + (slot))+#define LZMA_DIST_SPECIAL(dist) \+ (LZMA_PROB_DIST_SPECIAL_OFFSET + (dist))+#define LZMA_DIST_ALIGN(dist) \+ (LZMA_PROB_DIST_ALIGN_OFFSET + (dist))+#define LZMA_MATCH_LEN_CHOICE \+ LZMA_PROB_MATCH_LEN_CHOICE_OFFSET+#define LZMA_MATCH_LEN_CHOICE2 \+ LZMA_PROB_MATCH_LEN_CHOICE2_OFFSET+#define LZMA_MATCH_LEN_LOW(pos, sym) \+ (LZMA_PROB_MATCH_LEN_LOW_OFFSET + (pos) * LZMA_LEN_LOW_SYMBOLS + (sym))+#define LZMA_MATCH_LEN_MID(pos, sym) \+ (LZMA_PROB_MATCH_LEN_MID_OFFSET + (pos) * LZMA_LEN_MID_SYMBOLS + (sym))+#define LZMA_MATCH_LEN_HIGH(sym) \+ (LZMA_PROB_MATCH_LEN_HIGH_OFFSET + (sym))+#define LZMA_REP_LEN_CHOICE \+ LZMA_PROB_REP_LEN_CHOICE_OFFSET+#define LZMA_REP_LEN_CHOICE2 \+ LZMA_PROB_REP_LEN_CHOICE2_OFFSET+#define LZMA_REP_LEN_LOW(pos, sym) \+ (LZMA_PROB_REP_LEN_LOW_OFFSET + (pos) * LZMA_LEN_LOW_SYMBOLS + (sym))+#define LZMA_REP_LEN_MID(pos, sym) \+ (LZMA_PROB_REP_LEN_MID_OFFSET + (pos) * LZMA_LEN_MID_SYMBOLS + (sym))+#define LZMA_REP_LEN_HIGH(sym) \+ (LZMA_PROB_REP_LEN_HIGH_OFFSET + (sym))+#define LZMA_LITERAL(code, size) \+ (LZMA_PROB_LITERAL_OFFSET + (code) * LZMA_LITERAL_CODER_SIZE + (size))++/* Read an LZMA varint from BUF, reading and updating *POFFSET,+ setting *VAL. Returns 0 on error, 1 on success. */++static int+elf_lzma_varint (const unsigned char *compressed, size_t compressed_size,+ size_t *poffset, uint64_t *val)+{+ size_t off;+ int i;+ uint64_t v;+ unsigned char b;++ off = *poffset;+ i = 0;+ v = 0;+ while (1)+ {+ if (unlikely (off >= compressed_size))+ {+ elf_uncompress_failed ();+ return 0;+ }+ b = compressed[off];+ v |= (b & 0x7f) << (i * 7);+ ++off;+ if ((b & 0x80) == 0)+ {+ *poffset = off;+ *val = v;+ return 1;+ }+ ++i;+ if (unlikely (i >= 9))+ {+ elf_uncompress_failed ();+ return 0;+ }+ }+}++/* Normalize the LZMA range decoder, pulling in an extra input byte if+ needed. */++static void+elf_lzma_range_normalize (const unsigned char *compressed,+ size_t compressed_size, size_t *poffset,+ uint32_t *prange, uint32_t *pcode)+{+ if (*prange < (1U << 24))+ {+ if (unlikely (*poffset >= compressed_size))+ {+ /* We assume this will be caught elsewhere. */+ elf_uncompress_failed ();+ return;+ }+ *prange <<= 8;+ *pcode <<= 8;+ *pcode += compressed[*poffset];+ ++*poffset;+ }+}++/* Read and return a single bit from the LZMA stream, reading and+ updating *PROB. Each bit comes from the range coder. */++static int+elf_lzma_bit (const unsigned char *compressed, size_t compressed_size,+ uint16_t *prob, size_t *poffset, uint32_t *prange,+ uint32_t *pcode)+{+ uint32_t bound;++ elf_lzma_range_normalize (compressed, compressed_size, poffset,+ prange, pcode);+ bound = (*prange >> 11) * (uint32_t) *prob;+ if (*pcode < bound)+ {+ *prange = bound;+ *prob += ((1U << 11) - *prob) >> 5;+ return 0;+ }+ else+ {+ *prange -= bound;+ *pcode -= bound;+ *prob -= *prob >> 5;+ return 1;+ }+}++/* Read an integer of size BITS from the LZMA stream, most significant+ bit first. The bits are predicted using PROBS. */++static uint32_t+elf_lzma_integer (const unsigned char *compressed, size_t compressed_size,+ uint16_t *probs, uint32_t bits, size_t *poffset,+ uint32_t *prange, uint32_t *pcode)+{+ uint32_t sym;+ uint32_t i;++ sym = 1;+ for (i = 0; i < bits; i++)+ {+ int bit;++ bit = elf_lzma_bit (compressed, compressed_size, probs + sym, poffset,+ prange, pcode);+ sym <<= 1;+ sym += bit;+ }+ return sym - (1 << bits);+}++/* Read an integer of size BITS from the LZMA stream, least+ significant bit first. The bits are predicted using PROBS. */++static uint32_t+elf_lzma_reverse_integer (const unsigned char *compressed,+ size_t compressed_size, uint16_t *probs,+ uint32_t bits, size_t *poffset, uint32_t *prange,+ uint32_t *pcode)+{+ uint32_t sym;+ uint32_t val;+ uint32_t i;++ sym = 1;+ val = 0;+ for (i = 0; i < bits; i++)+ {+ int bit;++ bit = elf_lzma_bit (compressed, compressed_size, probs + sym, poffset,+ prange, pcode);+ sym <<= 1;+ sym += bit;+ val += bit << i;+ }+ return val;+}++/* Read a length from the LZMA stream. IS_REP picks either LZMA_MATCH+ or LZMA_REP probabilities. */++static uint32_t+elf_lzma_len (const unsigned char *compressed, size_t compressed_size,+ uint16_t *probs, int is_rep, unsigned int pos_state,+ size_t *poffset, uint32_t *prange, uint32_t *pcode)+{+ uint16_t *probs_choice;+ uint16_t *probs_sym;+ uint32_t bits;+ uint32_t len;++ probs_choice = probs + (is_rep+ ? LZMA_REP_LEN_CHOICE+ : LZMA_MATCH_LEN_CHOICE);+ if (elf_lzma_bit (compressed, compressed_size, probs_choice, poffset,+ prange, pcode))+ {+ probs_choice = probs + (is_rep+ ? LZMA_REP_LEN_CHOICE2+ : LZMA_MATCH_LEN_CHOICE2);+ if (elf_lzma_bit (compressed, compressed_size, probs_choice,+ poffset, prange, pcode))+ {+ probs_sym = probs + (is_rep+ ? LZMA_REP_LEN_HIGH (0)+ : LZMA_MATCH_LEN_HIGH (0));+ bits = 8;+ len = 2 + 8 + 8;+ }+ else+ {+ probs_sym = probs + (is_rep+ ? LZMA_REP_LEN_MID (pos_state, 0)+ : LZMA_MATCH_LEN_MID (pos_state, 0));+ bits = 3;+ len = 2 + 8;+ }+ }+ else+ {+ probs_sym = probs + (is_rep+ ? LZMA_REP_LEN_LOW (pos_state, 0)+ : LZMA_MATCH_LEN_LOW (pos_state, 0));+ bits = 3;+ len = 2;+ }++ len += elf_lzma_integer (compressed, compressed_size, probs_sym, bits,+ poffset, prange, pcode);+ return len;+}++/* Uncompress one LZMA block from a minidebug file. The compressed+ data is at COMPRESSED + *POFFSET. Update *POFFSET. Store the data+ into the memory at UNCOMPRESSED, size UNCOMPRESSED_SIZE. CHECK is+ the stream flag from the xz header. Return 1 on successful+ decompression. */++static int+elf_uncompress_lzma_block (const unsigned char *compressed,+ size_t compressed_size, unsigned char check,+ uint16_t *probs, unsigned char *uncompressed,+ size_t uncompressed_size, size_t *poffset)+{+ size_t off;+ size_t block_header_offset;+ size_t block_header_size;+ unsigned char block_flags;+ uint64_t header_compressed_size;+ uint64_t header_uncompressed_size;+ unsigned char lzma2_properties;+ size_t crc_offset;+ uint32_t computed_crc;+ uint32_t stream_crc;+ size_t uncompressed_offset;+ size_t dict_start_offset;+ unsigned int lc;+ unsigned int lp;+ unsigned int pb;+ uint32_t range;+ uint32_t code;+ uint32_t lstate;+ uint32_t dist[4];++ off = *poffset;+ block_header_offset = off;++ /* Block header size is a single byte. */+ if (unlikely (off >= compressed_size))+ {+ elf_uncompress_failed ();+ return 0;+ }+ block_header_size = (compressed[off] + 1) * 4;+ if (unlikely (off + block_header_size > compressed_size))+ {+ elf_uncompress_failed ();+ return 0;+ }++ /* Block flags. */+ block_flags = compressed[off + 1];+ if (unlikely ((block_flags & 0x3c) != 0))+ {+ elf_uncompress_failed ();+ return 0;+ }++ off += 2;++ /* Optional compressed size. */+ header_compressed_size = 0;+ if ((block_flags & 0x40) != 0)+ {+ *poffset = off;+ if (!elf_lzma_varint (compressed, compressed_size, poffset,+ &header_compressed_size))+ return 0;+ off = *poffset;+ }++ /* Optional uncompressed size. */+ header_uncompressed_size = 0;+ if ((block_flags & 0x80) != 0)+ {+ *poffset = off;+ if (!elf_lzma_varint (compressed, compressed_size, poffset,+ &header_uncompressed_size))+ return 0;+ off = *poffset;+ }++ /* The recipe for creating a minidebug file is to run the xz program+ with no arguments, so we expect exactly one filter: lzma2. */++ if (unlikely ((block_flags & 0x3) != 0))+ {+ elf_uncompress_failed ();+ return 0;+ }++ if (unlikely (off + 2 >= block_header_offset + block_header_size))+ {+ elf_uncompress_failed ();+ return 0;+ }++ /* The filter ID for LZMA2 is 0x21. */+ if (unlikely (compressed[off] != 0x21))+ {+ elf_uncompress_failed ();+ return 0;+ }+ ++off;++ /* The size of the filter properties for LZMA2 is 1. */+ if (unlikely (compressed[off] != 1))+ {+ elf_uncompress_failed ();+ return 0;+ }+ ++off;++ lzma2_properties = compressed[off];+ ++off;++ if (unlikely (lzma2_properties > 40))+ {+ elf_uncompress_failed ();+ return 0;+ }++ /* The properties describe the dictionary size, but we don't care+ what that is. */++ /* Skip to just before CRC, verifying zero bytes in between. */+ crc_offset = block_header_offset + block_header_size - 4;+ if (unlikely (crc_offset + 4 > compressed_size))+ {+ elf_uncompress_failed ();+ return 0;+ }+ for (; off < crc_offset; off++)+ {+ if (compressed[off] != 0)+ {+ elf_uncompress_failed ();+ return 0;+ }+ }++ /* Block header CRC. */+ computed_crc = elf_crc32 (0, compressed + block_header_offset,+ block_header_size - 4);+ stream_crc = ((uint32_t)compressed[off]+ | ((uint32_t)compressed[off + 1] << 8)+ | ((uint32_t)compressed[off + 2] << 16)+ | ((uint32_t)compressed[off + 3] << 24));+ if (unlikely (computed_crc != stream_crc))+ {+ elf_uncompress_failed ();+ return 0;+ }+ off += 4;++ /* Read a sequence of LZMA2 packets. */++ uncompressed_offset = 0;+ dict_start_offset = 0;+ lc = 0;+ lp = 0;+ pb = 0;+ lstate = 0;+ while (off < compressed_size)+ {+ unsigned char control;++ range = 0xffffffff;+ code = 0;++ control = compressed[off];+ ++off;+ if (unlikely (control == 0))+ {+ /* End of packets. */+ break;+ }++ if (control == 1 || control >= 0xe0)+ {+ /* Reset dictionary to empty. */+ dict_start_offset = uncompressed_offset;+ }++ if (control < 0x80)+ {+ size_t chunk_size;++ /* The only valid values here are 1 or 2. A 1 means to+ reset the dictionary (done above). Then we see an+ uncompressed chunk. */++ if (unlikely (control > 2))+ {+ elf_uncompress_failed ();+ return 0;+ }++ /* An uncompressed chunk is a two byte size followed by+ data. */++ if (unlikely (off + 2 > compressed_size))+ {+ elf_uncompress_failed ();+ return 0;+ }++ chunk_size = compressed[off] << 8;+ chunk_size += compressed[off + 1];+ ++chunk_size;++ off += 2;++ if (unlikely (off + chunk_size > compressed_size))+ {+ elf_uncompress_failed ();+ return 0;+ }+ if (unlikely (uncompressed_offset + chunk_size > uncompressed_size))+ {+ elf_uncompress_failed ();+ return 0;+ }++ memcpy (uncompressed + uncompressed_offset, compressed + off,+ chunk_size);+ uncompressed_offset += chunk_size;+ off += chunk_size;+ }+ else+ {+ size_t uncompressed_chunk_start;+ size_t uncompressed_chunk_size;+ size_t compressed_chunk_size;+ size_t limit;++ /* An LZMA chunk. This starts with an uncompressed size and+ a compressed size. */++ if (unlikely (off + 4 >= compressed_size))+ {+ elf_uncompress_failed ();+ return 0;+ }++ uncompressed_chunk_start = uncompressed_offset;++ uncompressed_chunk_size = (control & 0x1f) << 16;+ uncompressed_chunk_size += compressed[off] << 8;+ uncompressed_chunk_size += compressed[off + 1];+ ++uncompressed_chunk_size;++ compressed_chunk_size = compressed[off + 2] << 8;+ compressed_chunk_size += compressed[off + 3];+ ++compressed_chunk_size;++ off += 4;++ /* Bit 7 (0x80) is set.+ Bits 6 and 5 (0x40 and 0x20) are as follows:+ 0: don't reset anything+ 1: reset state+ 2: reset state, read properties+ 3: reset state, read properties, reset dictionary (done above) */++ if (control >= 0xc0)+ {+ unsigned char props;++ /* Bit 6 is set, read properties. */++ if (unlikely (off >= compressed_size))+ {+ elf_uncompress_failed ();+ return 0;+ }+ props = compressed[off];+ ++off;+ if (unlikely (props > (4 * 5 + 4) * 9 + 8))+ {+ elf_uncompress_failed ();+ return 0;+ }+ pb = 0;+ while (props >= 9 * 5)+ {+ props -= 9 * 5;+ ++pb;+ }+ lp = 0;+ while (props > 9)+ {+ props -= 9;+ ++lp;+ }+ lc = props;+ if (unlikely (lc + lp > 4))+ {+ elf_uncompress_failed ();+ return 0;+ }+ }++ if (control >= 0xa0)+ {+ size_t i;++ /* Bit 5 or 6 is set, reset LZMA state. */++ lstate = 0;+ memset (&dist, 0, sizeof dist);+ for (i = 0; i < LZMA_PROB_TOTAL_COUNT; i++)+ probs[i] = 1 << 10;+ range = 0xffffffff;+ code = 0;+ }++ /* Read the range code. */++ if (unlikely (off + 5 > compressed_size))+ {+ elf_uncompress_failed ();+ return 0;+ }++ /* The byte at compressed[off] is ignored for some+ reason. */++ code = ((compressed[off + 1] << 24)+ + (compressed[off + 2] << 16)+ + (compressed[off + 3] << 8)+ + compressed[off + 4]);+ off += 5;++ /* This is the main LZMA decode loop. */++ limit = off + compressed_chunk_size;+ *poffset = off;+ while (*poffset < limit)+ {+ unsigned int pos_state;++ if (unlikely (uncompressed_offset+ == (uncompressed_chunk_start+ + uncompressed_chunk_size)))+ {+ /* We've decompressed all the expected bytes. */+ break;+ }++ pos_state = ((uncompressed_offset - dict_start_offset)+ & ((1 << pb) - 1));++ if (elf_lzma_bit (compressed, compressed_size,+ probs + LZMA_IS_MATCH (lstate, pos_state),+ poffset, &range, &code))+ {+ uint32_t len;++ if (elf_lzma_bit (compressed, compressed_size,+ probs + LZMA_IS_REP (lstate),+ poffset, &range, &code))+ {+ int short_rep;+ uint32_t next_dist;++ /* Repeated match. */++ short_rep = 0;+ if (elf_lzma_bit (compressed, compressed_size,+ probs + LZMA_IS_REP0 (lstate),+ poffset, &range, &code))+ {+ if (elf_lzma_bit (compressed, compressed_size,+ probs + LZMA_IS_REP1 (lstate),+ poffset, &range, &code))+ {+ if (elf_lzma_bit (compressed, compressed_size,+ probs + LZMA_IS_REP2 (lstate),+ poffset, &range, &code))+ {+ next_dist = dist[3];+ dist[3] = dist[2];+ }+ else+ {+ next_dist = dist[2];+ }+ dist[2] = dist[1];+ }+ else+ {+ next_dist = dist[1];+ }++ dist[1] = dist[0];+ dist[0] = next_dist;+ }+ else+ {+ if (!elf_lzma_bit (compressed, compressed_size,+ (probs+ + LZMA_IS_REP0_LONG (lstate,+ pos_state)),+ poffset, &range, &code))+ short_rep = 1;+ }++ if (lstate < 7)+ lstate = short_rep ? 9 : 8;+ else+ lstate = 11;++ if (short_rep)+ len = 1;+ else+ len = elf_lzma_len (compressed, compressed_size,+ probs, 1, pos_state, poffset,+ &range, &code);+ }+ else+ {+ uint32_t dist_state;+ uint32_t dist_slot;+ uint16_t *probs_dist;++ /* Match. */++ if (lstate < 7)+ lstate = 7;+ else+ lstate = 10;+ dist[3] = dist[2];+ dist[2] = dist[1];+ dist[1] = dist[0];+ len = elf_lzma_len (compressed, compressed_size,+ probs, 0, pos_state, poffset,+ &range, &code);++ if (len < 4 + 2)+ dist_state = len - 2;+ else+ dist_state = 3;+ probs_dist = probs + LZMA_DIST_SLOT (dist_state, 0);+ dist_slot = elf_lzma_integer (compressed,+ compressed_size,+ probs_dist, 6,+ poffset, &range,+ &code);+ if (dist_slot < LZMA_DIST_MODEL_START)+ dist[0] = dist_slot;+ else+ {+ uint32_t limit;++ limit = (dist_slot >> 1) - 1;+ dist[0] = 2 + (dist_slot & 1);+ if (dist_slot < LZMA_DIST_MODEL_END)+ {+ dist[0] <<= limit;+ probs_dist = (probs+ + LZMA_DIST_SPECIAL(dist[0]+ - dist_slot+ - 1));+ dist[0] +=+ elf_lzma_reverse_integer (compressed,+ compressed_size,+ probs_dist,+ limit, poffset,+ &range, &code);+ }+ else+ {+ uint32_t dist0;+ uint32_t i;++ dist0 = dist[0];+ for (i = 0; i < limit - 4; i++)+ {+ uint32_t mask;++ elf_lzma_range_normalize (compressed,+ compressed_size,+ poffset,+ &range, &code);+ range >>= 1;+ code -= range;+ mask = -(code >> 31);+ code += range & mask;+ dist0 <<= 1;+ dist0 += mask + 1;+ }+ dist0 <<= 4;+ probs_dist = probs + LZMA_DIST_ALIGN (0);+ dist0 +=+ elf_lzma_reverse_integer (compressed,+ compressed_size,+ probs_dist, 4,+ poffset,+ &range, &code);+ dist[0] = dist0;+ }+ }+ }++ if (unlikely (uncompressed_offset+ - dict_start_offset < dist[0] + 1))+ {+ elf_uncompress_failed ();+ return 0;+ }+ if (unlikely (uncompressed_offset + len > uncompressed_size))+ {+ elf_uncompress_failed ();+ return 0;+ }++ if (dist[0] == 0)+ {+ /* A common case, meaning repeat the last+ character LEN times. */+ memset (uncompressed + uncompressed_offset,+ uncompressed[uncompressed_offset - 1],+ len);+ uncompressed_offset += len;+ }+ else if (dist[0] + 1 >= len)+ {+ memcpy (uncompressed + uncompressed_offset,+ uncompressed + uncompressed_offset - dist[0] - 1,+ len);+ uncompressed_offset += len;+ }+ else+ {+ while (len > 0)+ {+ uint32_t copy;++ copy = len < dist[0] + 1 ? len : dist[0] + 1;+ memcpy (uncompressed + uncompressed_offset,+ (uncompressed + uncompressed_offset+ - dist[0] - 1),+ copy);+ len -= copy;+ uncompressed_offset += copy;+ }+ }+ }+ else+ {+ unsigned char prev;+ unsigned char low;+ size_t high;+ uint16_t *lit_probs;+ unsigned int sym;++ /* Literal value. */++ if (uncompressed_offset > 0)+ prev = uncompressed[uncompressed_offset - 1];+ else+ prev = 0;+ low = prev >> (8 - lc);+ high = (((uncompressed_offset - dict_start_offset)+ & ((1 << lp) - 1))+ << lc);+ lit_probs = probs + LZMA_LITERAL (low + high, 0);+ if (lstate < 7)+ sym = elf_lzma_integer (compressed, compressed_size,+ lit_probs, 8, poffset, &range,+ &code);+ else+ {+ unsigned int match;+ unsigned int bit;+ unsigned int match_bit;+ unsigned int idx;++ sym = 1;+ if (uncompressed_offset >= dist[0] + 1)+ match = uncompressed[uncompressed_offset - dist[0] - 1];+ else+ match = 0;+ match <<= 1;+ bit = 0x100;+ do+ {+ match_bit = match & bit;+ match <<= 1;+ idx = bit + match_bit + sym;+ sym <<= 1;+ if (elf_lzma_bit (compressed, compressed_size,+ lit_probs + idx, poffset,+ &range, &code))+ {+ ++sym;+ bit &= match_bit;+ }+ else+ {+ bit &= ~ match_bit;+ }+ }+ while (sym < 0x100);+ }++ if (unlikely (uncompressed_offset >= uncompressed_size))+ {+ elf_uncompress_failed ();+ return 0;+ }++ uncompressed[uncompressed_offset] = (unsigned char) sym;+ ++uncompressed_offset;+ if (lstate <= 3)+ lstate = 0;+ else if (lstate <= 9)+ lstate -= 3;+ else+ lstate -= 6;+ }+ }++ elf_lzma_range_normalize (compressed, compressed_size, poffset,+ &range, &code);++ off = *poffset;+ }+ }++ /* We have reached the end of the block. Pad to four byte+ boundary. */+ off = (off + 3) &~ (size_t) 3;+ if (unlikely (off > compressed_size))+ {+ elf_uncompress_failed ();+ return 0;+ }++ switch (check)+ {+ case 0:+ /* No check. */+ break;++ case 1:+ /* CRC32 */+ if (unlikely (off + 4 > compressed_size))+ {+ elf_uncompress_failed ();+ return 0;+ }+ computed_crc = elf_crc32 (0, uncompressed, uncompressed_offset);+ stream_crc = ((uint32_t)compressed[off]+ | ((uint32_t)compressed[off + 1] << 8)+ | ((uint32_t)compressed[off + 2] << 16)+ | ((uint32_t)compressed[off + 3] << 24));+ if (computed_crc != stream_crc)+ {+ elf_uncompress_failed ();+ return 0;+ }+ off += 4;+ break;++ case 4:+ /* CRC64. We don't bother computing a CRC64 checksum. */+ if (unlikely (off + 8 > compressed_size))+ {+ elf_uncompress_failed ();+ return 0;+ }+ off += 8;+ break;++ case 10:+ /* SHA. We don't bother computing a SHA checksum. */+ if (unlikely (off + 32 > compressed_size))+ {+ elf_uncompress_failed ();+ return 0;+ }+ off += 32;+ break;++ default:+ elf_uncompress_failed ();+ return 0;+ }++ *poffset = off;++ return 1;+}++/* Uncompress LZMA data found in a minidebug file. The minidebug+ format is described at+ https://sourceware.org/gdb/current/onlinedocs/gdb/MiniDebugInfo.html.+ Returns 0 on error, 1 on successful decompression. For this+ function we return 0 on failure to decompress, as the calling code+ will carry on in that case. */++static int+elf_uncompress_lzma (struct backtrace_state *state,+ const unsigned char *compressed, size_t compressed_size,+ backtrace_error_callback error_callback, void *data,+ unsigned char **uncompressed, size_t *uncompressed_size)+{+ size_t header_size;+ size_t footer_size;+ unsigned char check;+ uint32_t computed_crc;+ uint32_t stream_crc;+ size_t offset;+ size_t index_size;+ size_t footer_offset;+ size_t index_offset;+ uint64_t index_compressed_size;+ uint64_t index_uncompressed_size;+ unsigned char *mem;+ uint16_t *probs;+ size_t compressed_block_size;++ /* The format starts with a stream header and ends with a stream+ footer. */+ header_size = 12;+ footer_size = 12;+ if (unlikely (compressed_size < header_size + footer_size))+ {+ elf_uncompress_failed ();+ return 0;+ }++ /* The stream header starts with a magic string. */+ if (unlikely (memcmp (compressed, "\375" "7zXZ\0", 6) != 0))+ {+ elf_uncompress_failed ();+ return 0;+ }++ /* Next come stream flags. The first byte is zero, the second byte+ is the check. */+ if (unlikely (compressed[6] != 0))+ {+ elf_uncompress_failed ();+ return 0;+ }+ check = compressed[7];+ if (unlikely ((check & 0xf8) != 0))+ {+ elf_uncompress_failed ();+ return 0;+ }++ /* Next comes a CRC of the stream flags. */+ computed_crc = elf_crc32 (0, compressed + 6, 2);+ stream_crc = ((uint32_t)compressed[8]+ | ((uint32_t)compressed[9] << 8)+ | ((uint32_t)compressed[10] << 16)+ | ((uint32_t)compressed[11] << 24));+ if (unlikely (computed_crc != stream_crc))+ {+ elf_uncompress_failed ();+ return 0;+ }++ /* Now that we've parsed the header, parse the footer, so that we+ can get the uncompressed size. */++ /* The footer ends with two magic bytes. */++ offset = compressed_size;+ if (unlikely (memcmp (compressed + offset - 2, "YZ", 2) != 0))+ {+ elf_uncompress_failed ();+ return 0;+ }+ offset -= 2;++ /* Before that are the stream flags, which should be the same as the+ flags in the header. */+ if (unlikely (compressed[offset - 2] != 0+ || compressed[offset - 1] != check))+ {+ elf_uncompress_failed ();+ return 0;+ }+ offset -= 2;++ /* Before that is the size of the index field, which precedes the+ footer. */+ index_size = (compressed[offset - 4]+ | (compressed[offset - 3] << 8)+ | (compressed[offset - 2] << 16)+ | (compressed[offset - 1] << 24));+ index_size = (index_size + 1) * 4;+ offset -= 4;++ /* Before that is a footer CRC. */+ computed_crc = elf_crc32 (0, compressed + offset, 6);+ stream_crc = ((uint32_t)compressed[offset - 4]+ | ((uint32_t)compressed[offset - 3] << 8)+ | ((uint32_t)compressed[offset - 2] << 16)+ | ((uint32_t)compressed[offset - 1] << 24));+ if (unlikely (computed_crc != stream_crc))+ {+ elf_uncompress_failed ();+ return 0;+ }+ offset -= 4;++ /* The index comes just before the footer. */+ if (unlikely (offset < index_size + header_size))+ {+ elf_uncompress_failed ();+ return 0;+ }++ footer_offset = offset;+ offset -= index_size;+ index_offset = offset;++ /* The index starts with a zero byte. */+ if (unlikely (compressed[offset] != 0))+ {+ elf_uncompress_failed ();+ return 0;+ }+ ++offset;++ /* Next is the number of blocks. We expect zero blocks for an empty+ stream, and otherwise a single block. */+ if (unlikely (compressed[offset] == 0))+ {+ *uncompressed = NULL;+ *uncompressed_size = 0;+ return 1;+ }+ if (unlikely (compressed[offset] != 1))+ {+ elf_uncompress_failed ();+ return 0;+ }+ ++offset;++ /* Next is the compressed size and the uncompressed size. */+ if (!elf_lzma_varint (compressed, compressed_size, &offset,+ &index_compressed_size))+ return 0;+ if (!elf_lzma_varint (compressed, compressed_size, &offset,+ &index_uncompressed_size))+ return 0;++ /* Pad to a four byte boundary. */+ offset = (offset + 3) &~ (size_t) 3;++ /* Next is a CRC of the index. */+ computed_crc = elf_crc32 (0, compressed + index_offset,+ offset - index_offset);+ stream_crc = ((uint32_t)compressed[offset]+ | ((uint32_t)compressed[offset + 1] << 8)+ | ((uint32_t)compressed[offset + 2] << 16)+ | ((uint32_t)compressed[offset + 3] << 24));+ if (unlikely (computed_crc != stream_crc))+ {+ elf_uncompress_failed ();+ return 0;+ }+ offset += 4;++ /* We should now be back at the footer. */+ if (unlikely (offset != footer_offset))+ {+ elf_uncompress_failed ();+ return 0;+ }++ /* Allocate space to hold the uncompressed data. If we succeed in+ uncompressing the LZMA data, we never free this memory. */+ mem = (unsigned char *) backtrace_alloc (state, index_uncompressed_size,+ error_callback, data);+ if (unlikely (mem == NULL))+ return 0;+ *uncompressed = mem;+ *uncompressed_size = index_uncompressed_size;++ /* Allocate space for probabilities. */+ probs = ((uint16_t *)+ backtrace_alloc (state,+ LZMA_PROB_TOTAL_COUNT * sizeof (uint16_t),+ error_callback, data));+ if (unlikely (probs == NULL))+ {+ backtrace_free (state, mem, index_uncompressed_size, error_callback,+ data);+ return 0;+ }++ /* Uncompress the block, which follows the header. */+ offset = 12;+ if (!elf_uncompress_lzma_block (compressed, compressed_size, check, probs,+ mem, index_uncompressed_size, &offset))+ {+ backtrace_free (state, mem, index_uncompressed_size, error_callback,+ data);+ return 0;+ }++ compressed_block_size = offset - 12;+ if (unlikely (compressed_block_size+ != ((index_compressed_size + 3) &~ (size_t) 3)))+ {+ elf_uncompress_failed ();+ backtrace_free (state, mem, index_uncompressed_size, error_callback,+ data);+ return 0;+ }++ offset = (offset + 3) &~ (size_t) 3;+ if (unlikely (offset != index_offset))+ {+ elf_uncompress_failed ();+ backtrace_free (state, mem, index_uncompressed_size, error_callback,+ data);+ return 0;+ }++ return 1;+}++/* This function is a hook for testing the LZMA support. It is only+ used by tests. */++int+backtrace_uncompress_lzma (struct backtrace_state *state,+ const unsigned char *compressed,+ size_t compressed_size,+ backtrace_error_callback error_callback,+ void *data, unsigned char **uncompressed,+ size_t *uncompressed_size)+{+ return elf_uncompress_lzma (state, compressed, compressed_size,+ error_callback, data, uncompressed,+ uncompressed_size);+}++/* Add the backtrace data for one ELF file. Returns 1 on success,+ 0 on failure (in both cases descriptor is closed) or -1 if exe+ is non-zero and the ELF file is ET_DYN, which tells the caller that+ elf_add will need to be called on the descriptor again after+ base_address is determined. */++static int+elf_add (struct backtrace_state *state, const char *filename, int descriptor,+ const unsigned char *memory, size_t memory_size,+ struct libbacktrace_base_address base_address,+ struct elf_ppc64_opd_data *caller_opd,+ backtrace_error_callback error_callback, void *data,+ fileline *fileline_fn, int *found_sym, int *found_dwarf,+ struct dwarf_data **fileline_entry, int exe, int debuginfo,+ const char *with_buildid_data, uint32_t with_buildid_size)+{+ struct elf_view ehdr_view;+ b_elf_ehdr ehdr;+ off_t shoff;+ unsigned int shnum;+ unsigned int shstrndx;+ struct elf_view shdrs_view;+ int shdrs_view_valid;+ const b_elf_shdr *shdrs;+ const b_elf_shdr *shstrhdr;+ size_t shstr_size;+ off_t shstr_off;+ struct elf_view names_view;+ int names_view_valid;+ const char *names;+ unsigned int symtab_shndx;+ unsigned int dynsym_shndx;+ unsigned int i;+ struct debug_section_info sections[DEBUG_MAX];+ struct debug_section_info zsections[DEBUG_MAX];+ struct elf_view symtab_view;+ int symtab_view_valid;+ struct elf_view strtab_view;+ int strtab_view_valid;+ struct elf_view buildid_view;+ int buildid_view_valid;+ const char *buildid_data;+ uint32_t buildid_size;+ struct elf_view debuglink_view;+ int debuglink_view_valid;+ const char *debuglink_name;+ uint32_t debuglink_crc;+ struct elf_view debugaltlink_view;+ int debugaltlink_view_valid;+ const char *debugaltlink_name;+ const char *debugaltlink_buildid_data;+ uint32_t debugaltlink_buildid_size;+ struct elf_view gnu_debugdata_view;+ int gnu_debugdata_view_valid;+ size_t gnu_debugdata_size;+ unsigned char *gnu_debugdata_uncompressed;+ size_t gnu_debugdata_uncompressed_size;+ off_t min_offset;+ off_t max_offset;+ off_t debug_size;+ struct elf_view debug_view;+ int debug_view_valid;+ unsigned int using_debug_view;+ uint16_t *zdebug_table;+ struct elf_view split_debug_view[DEBUG_MAX];+ unsigned char split_debug_view_valid[DEBUG_MAX];+ struct elf_ppc64_opd_data opd_data, *opd;+ int opd_view_valid;+ struct dwarf_sections dwarf_sections;+ struct dwarf_data *fileline_altlink = NULL;++ if (!debuginfo)+ {+ *found_sym = 0;+ *found_dwarf = 0;+ }++ shdrs_view_valid = 0;+ names_view_valid = 0;+ symtab_view_valid = 0;+ strtab_view_valid = 0;+ buildid_view_valid = 0;+ buildid_data = NULL;+ buildid_size = 0;+ debuglink_view_valid = 0;+ debuglink_name = NULL;+ debuglink_crc = 0;+ debugaltlink_view_valid = 0;+ debugaltlink_name = NULL;+ debugaltlink_buildid_data = NULL;+ debugaltlink_buildid_size = 0;+ gnu_debugdata_view_valid = 0;+ gnu_debugdata_size = 0;+ debug_view_valid = 0;+ memset (&split_debug_view_valid[0], 0, sizeof split_debug_view_valid);+ opd = NULL;+ opd_view_valid = 0;++ if (!elf_get_view (state, descriptor, memory, memory_size, 0, sizeof ehdr,+ error_callback, data, &ehdr_view))+ goto fail;++ memcpy (&ehdr, ehdr_view.view.data, sizeof ehdr);++ elf_release_view (state, &ehdr_view, error_callback, data);++ if (ehdr.e_ident[EI_MAG0] != ELFMAG0+ || ehdr.e_ident[EI_MAG1] != ELFMAG1+ || ehdr.e_ident[EI_MAG2] != ELFMAG2+ || ehdr.e_ident[EI_MAG3] != ELFMAG3)+ {+ error_callback (data, "executable file is not ELF", 0);+ goto fail;+ }+ if (ehdr.e_ident[EI_VERSION] != EV_CURRENT)+ {+ error_callback (data, "executable file is unrecognized ELF version", 0);+ goto fail;+ }++#if BACKTRACE_ELF_SIZE == 32+#define BACKTRACE_ELFCLASS ELFCLASS32+#else+#define BACKTRACE_ELFCLASS ELFCLASS64+#endif++ if (ehdr.e_ident[EI_CLASS] != BACKTRACE_ELFCLASS)+ {+ error_callback (data, "executable file is unexpected ELF class", 0);+ goto fail;+ }++ if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB+ && ehdr.e_ident[EI_DATA] != ELFDATA2MSB)+ {+ error_callback (data, "executable file has unknown endianness", 0);+ goto fail;+ }++ /* If the executable is ET_DYN, it is either a PIE, or we are running+ directly a shared library with .interp. We need to wait for+ dl_iterate_phdr in that case to determine the actual base_address. */+ if (exe && ehdr.e_type == ET_DYN)+ return -1;++ shoff = ehdr.e_shoff;+ shnum = ehdr.e_shnum;+ shstrndx = ehdr.e_shstrndx;++ if ((shnum == 0 || shstrndx == SHN_XINDEX)+ && shoff != 0)+ {+ struct elf_view shdr_view;+ const b_elf_shdr *shdr;++ if (!elf_get_view (state, descriptor, memory, memory_size, shoff,+ sizeof shdr, error_callback, data, &shdr_view))+ goto fail;++ shdr = (const b_elf_shdr *) shdr_view.view.data;++ if (shnum == 0)+ shnum = shdr->sh_size;++ if (shstrndx == SHN_XINDEX)+ {+ shstrndx = shdr->sh_link;++ /* Versions of the GNU binutils between 2.12 and 2.18 did+ not handle objects with more than SHN_LORESERVE sections+ correctly. All large section indexes were offset by+ 0x100. There is more information at+ http://sourceware.org/bugzilla/show_bug.cgi?id-5900 .+ Fortunately these object files are easy to detect, as the+ GNU binutils always put the section header string table+ near the end of the list of sections. Thus if the+ section header string table index is larger than the+ number of sections, then we know we have to subtract+ 0x100 to get the real section index. */+ if (shstrndx >= shnum && shstrndx >= SHN_LORESERVE + 0x100)+ shstrndx -= 0x100;+ }++ elf_release_view (state, &shdr_view, error_callback, data);+ }++ if (shnum == 0 || shstrndx == 0)+ goto fail;++ /* To translate PC to file/line when using DWARF, we need to find+ the .debug_info and .debug_line sections. */++ /* Read the section headers, skipping the first one. */++ if (!elf_get_view (state, descriptor, memory, memory_size,+ shoff + sizeof (b_elf_shdr),+ (shnum - 1) * sizeof (b_elf_shdr),+ error_callback, data, &shdrs_view))+ goto fail;+ shdrs_view_valid = 1;+ shdrs = (const b_elf_shdr *) shdrs_view.view.data;++ /* Read the section names. */++ shstrhdr = &shdrs[shstrndx - 1];+ shstr_size = shstrhdr->sh_size;+ shstr_off = shstrhdr->sh_offset;++ if (!elf_get_view (state, descriptor, memory, memory_size, shstr_off,+ shstrhdr->sh_size, error_callback, data, &names_view))+ goto fail;+ names_view_valid = 1;+ names = (const char *) names_view.view.data;++ symtab_shndx = 0;+ dynsym_shndx = 0;++ memset (sections, 0, sizeof sections);+ memset (zsections, 0, sizeof zsections);++ /* Look for the symbol table. */+ for (i = 1; i < shnum; ++i)+ {+ const b_elf_shdr *shdr;+ unsigned int sh_name;+ const char *name;+ int j;++ shdr = &shdrs[i - 1];++ if (shdr->sh_type == SHT_SYMTAB)+ symtab_shndx = i;+ else if (shdr->sh_type == SHT_DYNSYM)+ dynsym_shndx = i;++ sh_name = shdr->sh_name;+ if (sh_name >= shstr_size)+ {+ error_callback (data, "ELF section name out of range", 0);+ goto fail;+ }++ name = names + sh_name;++ for (j = 0; j < (int) DEBUG_MAX; ++j)+ {+ if (strcmp (name, dwarf_section_names[j]) == 0)+ {+ sections[j].offset = shdr->sh_offset;+ sections[j].size = shdr->sh_size;+ sections[j].compressed = (shdr->sh_flags & SHF_COMPRESSED) != 0;+ break;+ }+ }++ if (name[0] == '.' && name[1] == 'z')+ {+ for (j = 0; j < (int) DEBUG_MAX; ++j)+ {+ if (strcmp (name + 2, dwarf_section_names[j] + 1) == 0)+ {+ zsections[j].offset = shdr->sh_offset;+ zsections[j].size = shdr->sh_size;+ break;+ }+ }+ }++ /* Read the build ID if present. This could check for any+ SHT_NOTE section with the right note name and type, but gdb+ looks for a specific section name. */+ if ((!debuginfo || with_buildid_data != NULL)+ && !buildid_view_valid+ && strcmp (name, ".note.gnu.build-id") == 0)+ {+ const b_elf_note *note;++ if (!elf_get_view (state, descriptor, memory, memory_size,+ shdr->sh_offset, shdr->sh_size, error_callback,+ data, &buildid_view))+ goto fail;++ buildid_view_valid = 1;+ note = (const b_elf_note *) buildid_view.view.data;+ if (note->type == NT_GNU_BUILD_ID+ && note->namesz == 4+ && strncmp (note->name, "GNU", 4) == 0+ && shdr->sh_size <= 12 + ((note->namesz + 3) & ~ 3) + note->descsz)+ {+ buildid_data = ¬e->name[0] + ((note->namesz + 3) & ~ 3);+ buildid_size = note->descsz;+ }++ if (with_buildid_size != 0)+ {+ if (buildid_size != with_buildid_size)+ goto fail;++ if (memcmp (buildid_data, with_buildid_data, buildid_size) != 0)+ goto fail;+ }+ }++ /* Read the debuglink file if present. */+ if (!debuginfo+ && !debuglink_view_valid+ && strcmp (name, ".gnu_debuglink") == 0)+ {+ const char *debuglink_data;+ size_t crc_offset;++ if (!elf_get_view (state, descriptor, memory, memory_size,+ shdr->sh_offset, shdr->sh_size, error_callback,+ data, &debuglink_view))+ goto fail;++ debuglink_view_valid = 1;+ debuglink_data = (const char *) debuglink_view.view.data;+ crc_offset = strnlen (debuglink_data, shdr->sh_size);+ crc_offset = (crc_offset + 3) & ~3;+ if (crc_offset + 4 <= shdr->sh_size)+ {+ debuglink_name = debuglink_data;+ debuglink_crc = *(const uint32_t*)(debuglink_data + crc_offset);+ }+ }++ if (!debugaltlink_view_valid+ && strcmp (name, ".gnu_debugaltlink") == 0)+ {+ const char *debugaltlink_data;+ size_t debugaltlink_name_len;++ if (!elf_get_view (state, descriptor, memory, memory_size,+ shdr->sh_offset, shdr->sh_size, error_callback,+ data, &debugaltlink_view))+ goto fail;++ debugaltlink_view_valid = 1;+ debugaltlink_data = (const char *) debugaltlink_view.view.data;+ debugaltlink_name = debugaltlink_data;+ debugaltlink_name_len = strnlen (debugaltlink_data, shdr->sh_size);+ if (debugaltlink_name_len < shdr->sh_size)+ {+ /* Include terminating zero. */+ debugaltlink_name_len += 1;++ debugaltlink_buildid_data+ = debugaltlink_data + debugaltlink_name_len;+ debugaltlink_buildid_size = shdr->sh_size - debugaltlink_name_len;+ }+ }++ if (!debuginfo+ && !gnu_debugdata_view_valid+ && strcmp (name, ".gnu_debugdata") == 0)+ {+ if (!elf_get_view (state, descriptor, memory, memory_size,+ shdr->sh_offset, shdr->sh_size, error_callback,+ data, &gnu_debugdata_view))+ goto fail;++ gnu_debugdata_size = shdr->sh_size;+ gnu_debugdata_view_valid = 1;+ }++ /* Read the .opd section on PowerPC64 ELFv1. */+ if (ehdr.e_machine == EM_PPC64+ && (ehdr.e_flags & EF_PPC64_ABI) < 2+ && shdr->sh_type == SHT_PROGBITS+ && strcmp (name, ".opd") == 0)+ {+ if (!elf_get_view (state, descriptor, memory, memory_size,+ shdr->sh_offset, shdr->sh_size, error_callback,+ data, &opd_data.view))+ goto fail;++ opd = &opd_data;+ opd->addr = shdr->sh_addr;+ opd->data = (const char *) opd_data.view.view.data;+ opd->size = shdr->sh_size;+ opd_view_valid = 1;+ }+ }++ /* A debuginfo file may not have a useful .opd section, but we can use the+ one from the original executable. */+ if (opd == NULL)+ opd = caller_opd;++ if (symtab_shndx == 0)+ symtab_shndx = dynsym_shndx;+ if (symtab_shndx != 0)+ {+ const b_elf_shdr *symtab_shdr;+ unsigned int strtab_shndx;+ const b_elf_shdr *strtab_shdr;+ struct elf_syminfo_data *sdata;++ symtab_shdr = &shdrs[symtab_shndx - 1];+ strtab_shndx = symtab_shdr->sh_link;+ if (strtab_shndx >= shnum)+ {+ error_callback (data,+ "ELF symbol table strtab link out of range", 0);+ goto fail;+ }+ strtab_shdr = &shdrs[strtab_shndx - 1];++ if (!elf_get_view (state, descriptor, memory, memory_size,+ symtab_shdr->sh_offset, symtab_shdr->sh_size,+ error_callback, data, &symtab_view))+ goto fail;+ symtab_view_valid = 1;++ if (!elf_get_view (state, descriptor, memory, memory_size,+ strtab_shdr->sh_offset, strtab_shdr->sh_size,+ error_callback, data, &strtab_view))+ goto fail;+ strtab_view_valid = 1;++ sdata = ((struct elf_syminfo_data *)+ backtrace_alloc (state, sizeof *sdata, error_callback, data));+ if (sdata == NULL)+ goto fail;++ if (!elf_initialize_syminfo (state, base_address,+ (const unsigned char*)symtab_view.view.data, symtab_shdr->sh_size,+ (const unsigned char*)strtab_view.view.data, strtab_shdr->sh_size,+ error_callback, data, sdata, opd))+ {+ backtrace_free (state, sdata, sizeof *sdata, error_callback, data);+ goto fail;+ }++ /* We no longer need the symbol table, but we hold on to the+ string table permanently. */+ elf_release_view (state, &symtab_view, error_callback, data);+ symtab_view_valid = 0;+ strtab_view_valid = 0;++ *found_sym = 1;++ elf_add_syminfo_data (state, sdata);+ }++ elf_release_view (state, &shdrs_view, error_callback, data);+ shdrs_view_valid = 0;+ elf_release_view (state, &names_view, error_callback, data);+ names_view_valid = 0;++ /* If the debug info is in a separate file, read that one instead. */++ if (buildid_data != NULL)+ {+ int d;++ d = elf_open_debugfile_by_buildid (state, buildid_data, buildid_size,+ filename, error_callback, data);+ if (d >= 0)+ {+ int ret;++ elf_release_view (state, &buildid_view, error_callback, data);+ if (debuglink_view_valid)+ elf_release_view (state, &debuglink_view, error_callback, data);+ if (debugaltlink_view_valid)+ elf_release_view (state, &debugaltlink_view, error_callback, data);+ ret = elf_add (state, "", d, NULL, 0, base_address, opd,+ error_callback, data, fileline_fn, found_sym,+ found_dwarf, NULL, 0, 1, NULL, 0);+ if (ret < 0)+ backtrace_close (d, error_callback, data);+ else if (descriptor >= 0)+ backtrace_close (descriptor, error_callback, data);+ return ret;+ }+ }++ if (buildid_view_valid)+ {+ elf_release_view (state, &buildid_view, error_callback, data);+ buildid_view_valid = 0;+ }++ if (debuglink_name != NULL)+ {+ int d;++ d = elf_open_debugfile_by_debuglink (state, filename, debuglink_name,+ debuglink_crc, error_callback,+ data);+ if (d >= 0)+ {+ int ret;++ elf_release_view (state, &debuglink_view, error_callback, data);+ if (debugaltlink_view_valid)+ elf_release_view (state, &debugaltlink_view, error_callback, data);+ ret = elf_add (state, "", d, NULL, 0, base_address, opd,+ error_callback, data, fileline_fn, found_sym,+ found_dwarf, NULL, 0, 1, NULL, 0);+ if (ret < 0)+ backtrace_close (d, error_callback, data);+ else if (descriptor >= 0)+ backtrace_close(descriptor, error_callback, data);+ return ret;+ }+ }++ if (debuglink_view_valid)+ {+ elf_release_view (state, &debuglink_view, error_callback, data);+ debuglink_view_valid = 0;+ }++ if (debugaltlink_name != NULL)+ {+ int d;++ d = elf_open_debugfile_by_debuglink (state, filename, debugaltlink_name,+ 0, error_callback, data);+ if (d >= 0)+ {+ int ret;++ ret = elf_add (state, filename, d, NULL, 0, base_address, opd,+ error_callback, data, fileline_fn, found_sym,+ found_dwarf, &fileline_altlink, 0, 1,+ debugaltlink_buildid_data, debugaltlink_buildid_size);+ elf_release_view (state, &debugaltlink_view, error_callback, data);+ debugaltlink_view_valid = 0;+ if (ret < 0)+ {+ backtrace_close (d, error_callback, data);+ return ret;+ }+ }+ }++ if (debugaltlink_view_valid)+ {+ elf_release_view (state, &debugaltlink_view, error_callback, data);+ debugaltlink_view_valid = 0;+ }++ if (gnu_debugdata_view_valid)+ {+ int ret;++ ret = elf_uncompress_lzma (state,+ ((const unsigned char *)+ gnu_debugdata_view.view.data),+ gnu_debugdata_size, error_callback, data,+ &gnu_debugdata_uncompressed,+ &gnu_debugdata_uncompressed_size);++ elf_release_view (state, &gnu_debugdata_view, error_callback, data);+ gnu_debugdata_view_valid = 0;++ if (ret)+ {+ ret = elf_add (state, filename, -1, gnu_debugdata_uncompressed,+ gnu_debugdata_uncompressed_size, base_address, opd,+ error_callback, data, fileline_fn, found_sym,+ found_dwarf, NULL, 0, 0, NULL, 0);+ if (ret >= 0 && descriptor >= 0)+ backtrace_close(descriptor, error_callback, data);+ return ret;+ }+ }++ if (opd_view_valid)+ {+ elf_release_view (state, &opd->view, error_callback, data);+ opd_view_valid = 0;+ opd = NULL;+ }++ /* Read all the debug sections in a single view, since they are+ probably adjacent in the file. If any of sections are+ uncompressed, we never release this view. */++ min_offset = 0;+ max_offset = 0;+ debug_size = 0;+ for (i = 0; i < (int) DEBUG_MAX; ++i)+ {+ off_t end;++ if (sections[i].size != 0)+ {+ if (min_offset == 0 || sections[i].offset < min_offset)+ min_offset = sections[i].offset;+ end = sections[i].offset + sections[i].size;+ if (end > max_offset)+ max_offset = end;+ debug_size += sections[i].size;+ }+ if (zsections[i].size != 0)+ {+ if (min_offset == 0 || zsections[i].offset < min_offset)+ min_offset = zsections[i].offset;+ end = zsections[i].offset + zsections[i].size;+ if (end > max_offset)+ max_offset = end;+ debug_size += zsections[i].size;+ }+ }+ if (min_offset == 0 || max_offset == 0)+ {+ if (descriptor >= 0)+ {+ if (!backtrace_close (descriptor, error_callback, data))+ goto fail;+ }+ return 1;+ }++ /* If the total debug section size is large, assume that there are+ gaps between the sections, and read them individually. */++ if (max_offset - min_offset < 0x20000000+ || max_offset - min_offset < debug_size + 0x10000)+ {+ if (!elf_get_view (state, descriptor, memory, memory_size, min_offset,+ max_offset - min_offset, error_callback, data,+ &debug_view))+ goto fail;+ debug_view_valid = 1;+ }+ else+ {+ memset (&split_debug_view[0], 0, sizeof split_debug_view);+ for (i = 0; i < (int) DEBUG_MAX; ++i)+ {+ struct debug_section_info *dsec;++ if (sections[i].size != 0)+ dsec = §ions[i];+ else if (zsections[i].size != 0)+ dsec = &zsections[i];+ else+ continue;++ if (!elf_get_view (state, descriptor, memory, memory_size,+ dsec->offset, dsec->size, error_callback, data,+ &split_debug_view[i]))+ goto fail;+ split_debug_view_valid[i] = 1;++ if (sections[i].size != 0)+ sections[i].data = ((const unsigned char *)+ split_debug_view[i].view.data);+ else+ zsections[i].data = ((const unsigned char *)+ split_debug_view[i].view.data);+ }+ }++ /* We've read all we need from the executable. */+ if (descriptor >= 0)+ {+ if (!backtrace_close (descriptor, error_callback, data))+ goto fail;+ descriptor = -1;+ }++ using_debug_view = 0;+ if (debug_view_valid)+ {+ for (i = 0; i < (int) DEBUG_MAX; ++i)+ {+ if (sections[i].size == 0)+ sections[i].data = NULL;+ else+ {+ sections[i].data = ((const unsigned char *) debug_view.view.data+ + (sections[i].offset - min_offset));+ ++using_debug_view;+ }++ if (zsections[i].size == 0)+ zsections[i].data = NULL;+ else+ zsections[i].data = ((const unsigned char *) debug_view.view.data+ + (zsections[i].offset - min_offset));+ }+ }++ /* Uncompress the old format (--compress-debug-sections=zlib-gnu). */++ zdebug_table = NULL;+ for (i = 0; i < (int) DEBUG_MAX; ++i)+ {+ if (sections[i].size == 0 && zsections[i].size > 0)+ {+ unsigned char *uncompressed_data;+ size_t uncompressed_size;++ if (zdebug_table == NULL)+ {+ zdebug_table = ((uint16_t *)+ backtrace_alloc (state, ZLIB_TABLE_SIZE,+ error_callback, data));+ if (zdebug_table == NULL)+ goto fail;+ }++ uncompressed_data = NULL;+ uncompressed_size = 0;+ if (!elf_uncompress_zdebug (state, zsections[i].data,+ zsections[i].size, zdebug_table,+ error_callback, data,+ &uncompressed_data, &uncompressed_size))+ goto fail;+ sections[i].data = uncompressed_data;+ sections[i].size = uncompressed_size;+ sections[i].compressed = 0;++ if (split_debug_view_valid[i])+ {+ elf_release_view (state, &split_debug_view[i],+ error_callback, data);+ split_debug_view_valid[i] = 0;+ }+ }+ }++ if (zdebug_table != NULL)+ {+ backtrace_free (state, zdebug_table, ZLIB_TABLE_SIZE,+ error_callback, data);+ zdebug_table = NULL;+ }++ /* Uncompress the official ELF format+ (--compress-debug-sections=zlib-gabi, --compress-debug-sections=zstd). */+ for (i = 0; i < (int) DEBUG_MAX; ++i)+ {+ unsigned char *uncompressed_data;+ size_t uncompressed_size;++ if (sections[i].size == 0 || !sections[i].compressed)+ continue;++ if (zdebug_table == NULL)+ {+ zdebug_table = ((uint16_t *)+ backtrace_alloc (state, ZDEBUG_TABLE_SIZE,+ error_callback, data));+ if (zdebug_table == NULL)+ goto fail;+ }++ uncompressed_data = NULL;+ uncompressed_size = 0;+ if (!elf_uncompress_chdr (state, sections[i].data, sections[i].size,+ zdebug_table, error_callback, data,+ &uncompressed_data, &uncompressed_size))+ goto fail;+ sections[i].data = uncompressed_data;+ sections[i].size = uncompressed_size;+ sections[i].compressed = 0;++ if (debug_view_valid)+ --using_debug_view;+ else if (split_debug_view_valid[i])+ {+ elf_release_view (state, &split_debug_view[i], error_callback, data);+ split_debug_view_valid[i] = 0;+ }+ }++ if (zdebug_table != NULL)+ backtrace_free (state, zdebug_table, ZDEBUG_TABLE_SIZE,+ error_callback, data);++ if (debug_view_valid && using_debug_view == 0)+ {+ elf_release_view (state, &debug_view, error_callback, data);+ debug_view_valid = 0;+ }++ for (i = 0; i < (int) DEBUG_MAX; ++i)+ {+ dwarf_sections.data[i] = sections[i].data;+ dwarf_sections.size[i] = sections[i].size;+ }++ if (!backtrace_dwarf_add (state, base_address, &dwarf_sections,+ ehdr.e_ident[EI_DATA] == ELFDATA2MSB,+ fileline_altlink,+ error_callback, data, fileline_fn,+ fileline_entry))+ goto fail;++ *found_dwarf = 1;++ return 1;++ fail:+ if (shdrs_view_valid)+ elf_release_view (state, &shdrs_view, error_callback, data);+ if (names_view_valid)+ elf_release_view (state, &names_view, error_callback, data);+ if (symtab_view_valid)+ elf_release_view (state, &symtab_view, error_callback, data);+ if (strtab_view_valid)+ elf_release_view (state, &strtab_view, error_callback, data);+ if (debuglink_view_valid)+ elf_release_view (state, &debuglink_view, error_callback, data);+ if (debugaltlink_view_valid)+ elf_release_view (state, &debugaltlink_view, error_callback, data);+ if (gnu_debugdata_view_valid)+ elf_release_view (state, &gnu_debugdata_view, error_callback, data);+ if (buildid_view_valid)+ elf_release_view (state, &buildid_view, error_callback, data);+ if (debug_view_valid)+ elf_release_view (state, &debug_view, error_callback, data);+ for (i = 0; i < (int) DEBUG_MAX; ++i)+ {+ if (split_debug_view_valid[i])+ elf_release_view (state, &split_debug_view[i], error_callback, data);+ }+ if (opd_view_valid)+ elf_release_view (state, &opd->view, error_callback, data);+ if (descriptor >= 0)+ backtrace_close (descriptor, error_callback, data);+ return 0;+}++/* Data passed to phdr_callback. */++struct phdr_data+{+ struct backtrace_state *state;+ backtrace_error_callback error_callback;+ void *data;+ fileline *fileline_fn;+ int *found_sym;+ int *found_dwarf;+ const char *exe_filename;+ int exe_descriptor;+};++/* Callback passed to dl_iterate_phdr. Load debug info from shared+ libraries. */++struct PhdrIterate+{+ char* dlpi_name;+ ElfW(Addr) dlpi_addr;+ ElfW(Addr) dlpi_end_addr;+};+FastVector<PhdrIterate> s_phdrData(16);++struct ElfAddrRange+{+ ElfW(Addr) dlpi_addr;+ ElfW(Addr) dlpi_end_addr;+};+FastVector<ElfAddrRange> s_sortedKnownElfRanges(16);++static int address_in_known_elf_ranges(uintptr_t pc)+{+ auto it = std::lower_bound( s_sortedKnownElfRanges.begin(), s_sortedKnownElfRanges.end(), pc, + []( const ElfAddrRange& lhs, const uintptr_t rhs ) { return uintptr_t(lhs.dlpi_addr) > rhs; } );+ if( it != s_sortedKnownElfRanges.end() && pc <= it->dlpi_end_addr )+ {+ return true;+ }+ return false;+}++static int+phdr_callback_mock (struct dl_phdr_info *info, size_t size ATTRIBUTE_UNUSED,+ void *pdata)+{+ if( address_in_known_elf_ranges(info->dlpi_addr) )+ {+ return 0;+ }++ auto ptr = s_phdrData.push_next();+ if (info->dlpi_name)+ {+ size_t sz = strlen (info->dlpi_name) + 1;+ ptr->dlpi_name = (char*)tracy_malloc (sz);+ memcpy (ptr->dlpi_name, info->dlpi_name, sz);+ }+ else ptr->dlpi_name = nullptr;+ ptr->dlpi_addr = info->dlpi_addr;++ // calculate the end address as well, so we can quickly determine if a PC is within the range of this image+ ptr->dlpi_end_addr = uintptr_t(info->dlpi_addr) + (info->dlpi_phnum ? uintptr_t(+ info->dlpi_phdr[info->dlpi_phnum - 1].p_vaddr + + info->dlpi_phdr[info->dlpi_phnum - 1].p_memsz) : 0);++ return 0;+}++static int+#ifdef __i386__+__attribute__ ((__force_align_arg_pointer__))+#endif+phdr_callback (struct PhdrIterate *info, void *pdata)+{+ struct phdr_data *pd = (struct phdr_data *) pdata;+ const char *filename;+ int descriptor;+ int does_not_exist;+ struct libbacktrace_base_address base_address;+ fileline elf_fileline_fn;+ int found_dwarf;++ /* There is not much we can do if we don't have the module name,+ unless executable is ET_DYN, where we expect the very first+ phdr_callback to be for the PIE. */+ if (info->dlpi_name == NULL || info->dlpi_name[0] == '\0')+ {+ if (pd->exe_descriptor == -1)+ return 0;+ filename = pd->exe_filename;+ descriptor = pd->exe_descriptor;+ pd->exe_descriptor = -1;+ }+ else+ {+ if (pd->exe_descriptor != -1)+ {+ backtrace_close (pd->exe_descriptor, pd->error_callback, pd->data);+ pd->exe_descriptor = -1;+ }++ filename = info->dlpi_name;+ descriptor = backtrace_open (info->dlpi_name, pd->error_callback,+ pd->data, &does_not_exist);+ if (descriptor < 0)+ return 0;+ }++ base_address.m = info->dlpi_addr;+ if (elf_add (pd->state, filename, descriptor, NULL, 0, base_address, NULL,+ pd->error_callback, pd->data, &elf_fileline_fn, pd->found_sym,+ &found_dwarf, NULL, 0, 0, NULL, 0))+ {+ if (found_dwarf)+ {+ *pd->found_dwarf = 1;+ *pd->fileline_fn = elf_fileline_fn;+ }+ }++ return 0;+}++static int elf_iterate_phdr_and_add_new_files(phdr_data *pd)+{+ assert(s_phdrData.empty());+ // dl_iterate_phdr, will only add entries for elf files loaded in a previously unseen range+ dl_iterate_phdr(phdr_callback_mock, nullptr);++ if(s_phdrData.size() == 0)+ {+ return 0;+ }++ uint32_t headersAdded = 0;+ for (auto &v : s_phdrData)+ {+ phdr_callback(&v, (void *)pd);++ auto newEntry = s_sortedKnownElfRanges.push_next();+ newEntry->dlpi_addr = v.dlpi_addr;+ newEntry->dlpi_end_addr = v.dlpi_end_addr;++ tracy_free(v.dlpi_name);++ headersAdded++;+ }++ s_phdrData.clear();++ std::sort( s_sortedKnownElfRanges.begin(), s_sortedKnownElfRanges.end(), + []( const ElfAddrRange& lhs, const ElfAddrRange& rhs ) { return lhs.dlpi_addr > rhs.dlpi_addr; } );++ return headersAdded;+}++#ifdef TRACY_LIBBACKTRACE_ELF_DYNLOAD_SUPPORT+/* Request an elf entry update if the pc passed in is not in any of the known elf ranges. +This could mean that new images were dlopened and we need to add those new elf entries */+static int elf_refresh_address_ranges_if_needed(struct backtrace_state *state, uintptr_t pc)+{+ if ( address_in_known_elf_ranges(pc) )+ {+ return 0;+ }++ struct phdr_data pd;+ int found_sym = 0;+ int found_dwarf = 0;+ fileline fileline_fn = nullptr;+ pd.state = state;+ pd.error_callback = nullptr;+ pd.data = nullptr;+ pd.fileline_fn = &fileline_fn;+ pd.found_sym = &found_sym;+ pd.found_dwarf = &found_dwarf;+ pd.exe_filename = nullptr;+ pd.exe_descriptor = -1;++ return elf_iterate_phdr_and_add_new_files(&pd);+}+#endif //#ifdef TRACY_LIBBACKTRACE_ELF_DYNLOAD_SUPPORT++/* Initialize the backtrace data we need from an ELF executable. At+ the ELF level, all we need to do is find the debug info+ sections. */++int+backtrace_initialize (struct backtrace_state *state, const char *filename,+ int descriptor, backtrace_error_callback error_callback,+ void *data, fileline *fileline_fn)+{+ int ret;+ int found_sym;+ int found_dwarf;+ fileline elf_fileline_fn = elf_nodebug;+ struct phdr_data pd;+++ /* When using fdpic we must use dl_iterate_phdr for all modules, including+ the main executable, so that we can get the right base address+ mapping. */+ if (!libbacktrace_using_fdpic ())+ {+ struct libbacktrace_base_address zero_base_address;++ memset (&zero_base_address, 0, sizeof zero_base_address);+ ret = elf_add (state, filename, descriptor, NULL, 0, zero_base_address,+ NULL, error_callback, data, &elf_fileline_fn, &found_sym,+ &found_dwarf, NULL, 1, 0, NULL, 0);+ if (!ret)+ return 0;+ }++ pd.state = state;+ pd.error_callback = error_callback;+ pd.data = data;+ pd.fileline_fn = &elf_fileline_fn;+ pd.found_sym = &found_sym;+ pd.found_dwarf = &found_dwarf;+ pd.exe_filename = filename;+ pd.exe_descriptor = ret < 0 ? descriptor : -1;++ elf_iterate_phdr_and_add_new_files(&pd);++ if (!state->threaded)+ {+ if (found_sym)+ state->syminfo_fn = elf_syminfo;+ else if (state->syminfo_fn == NULL)+ state->syminfo_fn = elf_nosyms;+ }+ else+ {+ if (found_sym)+ backtrace_atomic_store_pointer (&state->syminfo_fn, &elf_syminfo);+ else+ (void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,+ elf_nosyms);+ }++ if (!state->threaded)+ *fileline_fn = state->fileline_fn;+ else+ *fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);++ if (*fileline_fn == NULL || *fileline_fn == elf_nodebug)+ *fileline_fn = elf_fileline_fn;++ // install an address range refresh callback so we can cope with dynamically loaded elf files+#ifdef TRACY_LIBBACKTRACE_ELF_DYNLOAD_SUPPORT+ state->request_known_address_ranges_refresh_fn = elf_refresh_address_ranges_if_needed;+#else+ state->request_known_address_ranges_refresh_fn = NULL;+#endif++ return 1;+}++}
+ cbits/tracy/public/libbacktrace/fileline.cpp view
@@ -0,0 +1,412 @@+/* fileline.c -- Get file and line number information in a backtrace.+ Copyright (C) 2012-2021 Free Software Foundation, Inc.+ Written by Ian Lance Taylor, Google.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are+met:++ (1) Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ (2) Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in+ the documentation and/or other materials provided with the+ distribution.++ (3) The name of the author may not be used to+ endorse or promote products derived from this software without+ specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. */++#include "config.h"++#include <sys/types.h>+#include <sys/stat.h>+#include <errno.h>+#include <fcntl.h>+#include <stdlib.h>+#include <unistd.h>++#if defined (HAVE_KERN_PROC_ARGS) || defined (HAVE_KERN_PROC)+#include <sys/sysctl.h>+#endif++#ifdef HAVE_MACH_O_DYLD_H+#include <mach-o/dyld.h>+#endif++#ifdef HAVE_WINDOWS_H+#ifndef WIN32_MEAN_AND_LEAN+#define WIN32_MEAN_AND_LEAN+#endif++#ifndef NOMINMAX+#define NOMINMAX+#endif++#include <windows.h>+#endif++#include "backtrace.hpp"+#include "internal.hpp"++#ifndef HAVE_GETEXECNAME+#define getexecname() NULL+#endif++namespace tracy+{++#if !defined (HAVE_KERN_PROC_ARGS) && !defined (HAVE_KERN_PROC)++#define sysctl_exec_name1(state, error_callback, data) NULL+#define sysctl_exec_name2(state, error_callback, data) NULL++#else /* defined (HAVE_KERN_PROC_ARGS) || |defined (HAVE_KERN_PROC) */++static char *+sysctl_exec_name (struct backtrace_state *state,+ int mib0, int mib1, int mib2, int mib3,+ backtrace_error_callback error_callback, void *data)+{+ int mib[4];+ size_t len;+ char *name;+ size_t rlen;++ mib[0] = mib0;+ mib[1] = mib1;+ mib[2] = mib2;+ mib[3] = mib3;++ if (sysctl (mib, 4, NULL, &len, NULL, 0) < 0)+ return NULL;+ name = (char *) backtrace_alloc (state, len, error_callback, data);+ if (name == NULL)+ return NULL;+ rlen = len;+ if (sysctl (mib, 4, name, &rlen, NULL, 0) < 0)+ {+ backtrace_free (state, name, len, error_callback, data);+ return NULL;+ }+ return name;+}++#ifdef HAVE_KERN_PROC_ARGS++static char *+sysctl_exec_name1 (struct backtrace_state *state,+ backtrace_error_callback error_callback, void *data)+{+ /* This variant is used on NetBSD. */+ return sysctl_exec_name (state, CTL_KERN, KERN_PROC_ARGS, -1,+ KERN_PROC_PATHNAME, error_callback, data);+}++#else++#define sysctl_exec_name1(state, error_callback, data) NULL++#endif++#ifdef HAVE_KERN_PROC++static char *+sysctl_exec_name2 (struct backtrace_state *state,+ backtrace_error_callback error_callback, void *data)+{+ /* This variant is used on FreeBSD. */+ return sysctl_exec_name (state, CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1,+ error_callback, data);+}++#else++#define sysctl_exec_name2(state, error_callback, data) NULL++#endif++#endif /* defined (HAVE_KERN_PROC_ARGS) || |defined (HAVE_KERN_PROC) */++#ifdef HAVE_MACH_O_DYLD_H++static char *+macho_get_executable_path (struct backtrace_state *state,+ backtrace_error_callback error_callback, void *data)+{+ uint32_t len;+ char *name;++ len = 0;+ if (_NSGetExecutablePath (NULL, &len) == 0)+ return NULL;+ name = (char *) backtrace_alloc (state, len, error_callback, data);+ if (name == NULL)+ return NULL;+ if (_NSGetExecutablePath (name, &len) != 0)+ {+ backtrace_free (state, name, len, error_callback, data);+ return NULL;+ }+ return name;+}++#else /* !defined (HAVE_MACH_O_DYLD_H) */++#define macho_get_executable_path(state, error_callback, data) NULL++#endif /* !defined (HAVE_MACH_O_DYLD_H) */++#if HAVE_DECL__PGMPTR++#define windows_executable_filename() _pgmptr++#else /* !HAVE_DECL__PGMPTR */++#define windows_executable_filename() NULL++#endif /* !HAVE_DECL__PGMPTR */++#ifdef HAVE_WINDOWS_H++#define FILENAME_BUF_SIZE (MAX_PATH)++static char *+windows_get_executable_path (char *buf, backtrace_error_callback error_callback,+ void *data)+{+ size_t got;+ int error;++ got = GetModuleFileNameA (NULL, buf, FILENAME_BUF_SIZE - 1);+ error = GetLastError ();+ if (got == 0+ || (got == FILENAME_BUF_SIZE - 1 && error == ERROR_INSUFFICIENT_BUFFER))+ {+ error_callback (data,+ "could not get the filename of the current executable",+ error);+ return NULL;+ }+ return buf;+}++#else /* !defined (HAVE_WINDOWS_H) */++#define windows_get_executable_path(buf, error_callback, data) NULL+#define FILENAME_BUF_SIZE 64++#endif /* !defined (HAVE_WINDOWS_H) */++/* Initialize the fileline information from the executable. Returns 1+ on success, 0 on failure. */++static int+fileline_initialize (struct backtrace_state *state,+ backtrace_error_callback error_callback, void *data)+{+ int failed;+ fileline fileline_fn;+ int pass;+ int called_error_callback;+ int descriptor;+ const char *filename;+ char buf[FILENAME_BUF_SIZE];++ if (!state->threaded)+ failed = state->fileline_initialization_failed;+ else+ failed = backtrace_atomic_load_int (&state->fileline_initialization_failed);++ if (failed)+ {+ error_callback (data, "failed to read executable information", -1);+ return 0;+ }++ if (!state->threaded)+ fileline_fn = state->fileline_fn;+ else+ fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);+ if (fileline_fn != NULL)+ return 1;++ /* We have not initialized the information. Do it now. */++ descriptor = -1;+ called_error_callback = 0;+ for (pass = 0; pass < 10; ++pass)+ {+ int does_not_exist;++ switch (pass)+ {+ case 0:+ filename = state->filename;+ break;+ case 1:+ filename = getexecname ();+ break;+ case 2:+ /* Test this before /proc/self/exe, as the latter exists but points+ to the wine binary (and thus doesn't work). */+ filename = windows_executable_filename ();+ break;+ case 3:+ filename = "/proc/self/exe";+ break;+ case 4:+ filename = "/proc/curproc/file";+ break;+ case 5:+ snprintf (buf, sizeof (buf), "/proc/%ld/object/a.out",+ (long) getpid ());+ filename = buf;+ break;+ case 6:+ filename = sysctl_exec_name1 (state, error_callback, data);+ break;+ case 7:+ filename = sysctl_exec_name2 (state, error_callback, data);+ break;+ case 8:+ filename = macho_get_executable_path (state, error_callback, data);+ break;+ case 9:+ filename = windows_get_executable_path (buf, error_callback, data);+ break;+ default:+ abort ();+ }++ if (filename == NULL)+ continue;++ descriptor = backtrace_open (filename, error_callback, data,+ &does_not_exist);+ if (descriptor < 0 && !does_not_exist)+ {+ called_error_callback = 1;+ break;+ }+ if (descriptor >= 0)+ break;+ }++ if (descriptor < 0)+ {+ if (!called_error_callback)+ {+ if (state->filename != NULL)+ error_callback (data, state->filename, ENOENT);+ else+ error_callback (data,+ "libbacktrace could not find executable to open",+ 0);+ }+ failed = 1;+ }++ if (!failed)+ {+ if (!backtrace_initialize (state, filename, descriptor, error_callback,+ data, &fileline_fn))+ failed = 1;+ }++ if (failed)+ {+ if (!state->threaded)+ state->fileline_initialization_failed = 1;+ else+ backtrace_atomic_store_int (&state->fileline_initialization_failed, 1);+ return 0;+ }++ if (!state->threaded)+ state->fileline_fn = fileline_fn;+ else+ {+ backtrace_atomic_store_pointer (&state->fileline_fn, fileline_fn);++ /* Note that if two threads initialize at once, one of the data+ sets may be leaked. */+ }++ return 1;+}++/* Given a PC, find the file name, line number, and function name. */++int+backtrace_pcinfo (struct backtrace_state *state, uintptr_t pc,+ backtrace_full_callback callback,+ backtrace_error_callback error_callback, void *data)+{+ if (!fileline_initialize (state, error_callback, data))+ return 0;++ if (state->fileline_initialization_failed)+ return 0;++ return state->fileline_fn (state, pc, callback, error_callback, data);+}++/* Given a PC, find the symbol for it, and its value. */++int+backtrace_syminfo (struct backtrace_state *state, uintptr_t pc,+ backtrace_syminfo_callback callback,+ backtrace_error_callback error_callback, void *data)+{+ if (!fileline_initialize (state, error_callback, data))+ return 0;++ if (state->fileline_initialization_failed)+ return 0;++ state->syminfo_fn (state, pc, callback, error_callback, data);+ return 1;+}++/* A backtrace_syminfo_callback that can call into a+ backtrace_full_callback, used when we have a symbol table but no+ debug info. */++void+backtrace_syminfo_to_full_callback (void *data, uintptr_t pc,+ const char *symname,+ uintptr_t symval ATTRIBUTE_UNUSED,+ uintptr_t symsize ATTRIBUTE_UNUSED)+{+ struct backtrace_call_full *bdata = (struct backtrace_call_full *) data;++ bdata->ret = bdata->full_callback (bdata->full_data, pc, 0, NULL, 0, symname);+}++/* An error callback that corresponds to+ backtrace_syminfo_to_full_callback. */++void+backtrace_syminfo_to_full_error_callback (void *data, const char *msg,+ int errnum)+{+ struct backtrace_call_full *bdata = (struct backtrace_call_full *) data;++ bdata->full_error_callback (bdata->full_data, msg, errnum);+}++}
+ cbits/tracy/public/libbacktrace/filenames.hpp view
@@ -0,0 +1,52 @@+/* btest.c -- Filename header for libbacktrace library+ Copyright (C) 2012-2018 Free Software Foundation, Inc.+ Written by Ian Lance Taylor, Google.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are+met:++ (1) Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ (2) Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in+ the documentation and/or other materials provided with the+ distribution.++ (3) The name of the author may not be used to+ endorse or promote products derived from this software without+ specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. */++#ifndef GCC_VERSION+# define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)+#endif++#if (GCC_VERSION < 2007)+# define __attribute__(x)+#endif++#ifndef ATTRIBUTE_UNUSED+# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))+#endif++#if defined(__MSDOS__) || defined(_WIN32) || defined(__OS2__) || defined (__CYGWIN__)+# define IS_DIR_SEPARATOR(c) ((c) == '/' || (c) == '\\')+# define HAS_DRIVE_SPEC(f) ((f)[0] != '\0' && (f)[1] == ':')+# define IS_ABSOLUTE_PATH(f) (IS_DIR_SEPARATOR((f)[0]) || HAS_DRIVE_SPEC(f))+#else+# define IS_DIR_SEPARATOR(c) ((c) == '/')+# define IS_ABSOLUTE_PATH(f) (IS_DIR_SEPARATOR((f)[0]))+#endif
+ cbits/tracy/public/libbacktrace/internal.hpp view
@@ -0,0 +1,435 @@+/* internal.h -- Internal header file for stack backtrace library.+ Copyright (C) 2012-2021 Free Software Foundation, Inc.+ Written by Ian Lance Taylor, Google.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are+met:++ (1) Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ (2) Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in+ the documentation and/or other materials provided with the+ distribution.++ (3) The name of the author may not be used to+ endorse or promote products derived from this software without+ specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. */++#ifndef BACKTRACE_INTERNAL_H+#define BACKTRACE_INTERNAL_H++/* We assume that <sys/types.h> and "backtrace.h" have already been+ included. */++#ifndef GCC_VERSION+# define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)+#endif++#if (GCC_VERSION < 2007)+# define __attribute__(x)+#endif++#ifndef ATTRIBUTE_UNUSED+# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))+#endif++#ifndef ATTRIBUTE_MALLOC+# if (GCC_VERSION >= 2096)+# define ATTRIBUTE_MALLOC __attribute__ ((__malloc__))+# else+# define ATTRIBUTE_MALLOC+# endif+#endif++#ifndef ATTRIBUTE_FALLTHROUGH+# if (GCC_VERSION >= 7000)+# define ATTRIBUTE_FALLTHROUGH __attribute__ ((__fallthrough__))+# else+# define ATTRIBUTE_FALLTHROUGH+# endif+#endif++#ifndef HAVE_SYNC_FUNCTIONS++/* Define out the sync functions. These should never be called if+ they are not available. */++#define __sync_bool_compare_and_swap(A, B, C) (abort(), 1)+#define __sync_lock_test_and_set(A, B) (abort(), 0)+#define __sync_lock_release(A) abort()++#endif /* !defined (HAVE_SYNC_FUNCTIONS) */++#ifdef HAVE_ATOMIC_FUNCTIONS++/* We have the atomic builtin functions. */++#define backtrace_atomic_load_pointer(p) \+ __atomic_load_n ((p), __ATOMIC_ACQUIRE)+#define backtrace_atomic_load_int(p) \+ __atomic_load_n ((p), __ATOMIC_ACQUIRE)+#define backtrace_atomic_store_pointer(p, v) \+ __atomic_store_n ((p), (v), __ATOMIC_RELEASE)+#define backtrace_atomic_store_size_t(p, v) \+ __atomic_store_n ((p), (v), __ATOMIC_RELEASE)+#define backtrace_atomic_store_int(p, v) \+ __atomic_store_n ((p), (v), __ATOMIC_RELEASE)++#else /* !defined (HAVE_ATOMIC_FUNCTIONS) */+#ifdef HAVE_SYNC_FUNCTIONS++/* We have the sync functions but not the atomic functions. Define+ the atomic ones in terms of the sync ones. */++extern void *backtrace_atomic_load_pointer (void *);+extern int backtrace_atomic_load_int (int *);+extern void backtrace_atomic_store_pointer (void *, void *);+extern void backtrace_atomic_store_size_t (size_t *, size_t);+extern void backtrace_atomic_store_int (int *, int);++#else /* !defined (HAVE_SYNC_FUNCTIONS) */++/* We have neither the sync nor the atomic functions. These will+ never be called. */++#define backtrace_atomic_load_pointer(p) (abort(), (void *) NULL)+#define backtrace_atomic_load_int(p) (abort(), 0)+#define backtrace_atomic_store_pointer(p, v) abort()+#define backtrace_atomic_store_size_t(p, v) abort()+#define backtrace_atomic_store_int(p, v) abort()++#endif /* !defined (HAVE_SYNC_FUNCTIONS) */+#endif /* !defined (HAVE_ATOMIC_FUNCTIONS) */++namespace tracy+{++/* The type of the function that collects file/line information. This+ is like backtrace_pcinfo. */++typedef int (*fileline) (struct backtrace_state *state, uintptr_t pc,+ backtrace_full_callback callback,+ backtrace_error_callback error_callback, void *data);++/* The type of the function that collects symbol information. This is+ like backtrace_syminfo. */++typedef void (*syminfo) (struct backtrace_state *state, uintptr_t pc,+ backtrace_syminfo_callback callback,+ backtrace_error_callback error_callback, void *data);++/* The type of the function that will trigger an known address range refresh+ (if pc passed in is for an address whichs lies ourtisde of known ranges) */+typedef int (*request_known_address_ranges_refresh)(struct backtrace_state *state,+ uintptr_t pc);++/* What the backtrace state pointer points to. */++struct backtrace_state+{+ /* The name of the executable. */+ const char *filename;+ /* Non-zero if threaded. */+ int threaded;+ /* The master lock for fileline_fn, fileline_data, syminfo_fn,+ syminfo_data, fileline_initialization_failed and everything the+ data pointers point to. */+ void *lock;+ /* The function that returns file/line information. */+ fileline fileline_fn;+ /* The data to pass to FILELINE_FN. */+ void *fileline_data;+ /* The function that returns symbol information. */+ syminfo syminfo_fn;+ /* The data to pass to SYMINFO_FN. */+ void *syminfo_data;+ /* Whether initializing the file/line information failed. */+ int fileline_initialization_failed;+ /* The lock for the freelist. */+ int lock_alloc;+ /* The freelist when using mmap. */+ struct backtrace_freelist_struct *freelist;+ /* Trigger an known address range refresh */+ request_known_address_ranges_refresh request_known_address_ranges_refresh_fn;+};++/* Open a file for reading. Returns -1 on error. If DOES_NOT_EXIST+ is not NULL, *DOES_NOT_EXIST will be set to 0 normally and set to 1+ if the file does not exist. If the file does not exist and+ DOES_NOT_EXIST is not NULL, the function will return -1 and will+ not call ERROR_CALLBACK. On other errors, or if DOES_NOT_EXIST is+ NULL, the function will call ERROR_CALLBACK before returning. */+extern int backtrace_open (const char *filename,+ backtrace_error_callback error_callback,+ void *data,+ int *does_not_exist);++/* A view of the contents of a file. This supports mmap when+ available. A view will remain in memory even after backtrace_close+ is called on the file descriptor from which the view was+ obtained. */++struct backtrace_view+{+ /* The data that the caller requested. */+ const void *data;+ /* The base of the view. */+ void *base;+ /* The total length of the view. */+ size_t len;+};++/* Create a view of SIZE bytes from DESCRIPTOR at OFFSET. Store the+ result in *VIEW. Returns 1 on success, 0 on error. */+extern int backtrace_get_view (struct backtrace_state *state, int descriptor,+ off_t offset, uint64_t size,+ backtrace_error_callback error_callback,+ void *data, struct backtrace_view *view);++/* Release a view created by backtrace_get_view. */+extern void backtrace_release_view (struct backtrace_state *state,+ struct backtrace_view *view,+ backtrace_error_callback error_callback,+ void *data);++/* Close a file opened by backtrace_open. Returns 1 on success, 0 on+ error. */++extern int backtrace_close (int descriptor,+ backtrace_error_callback error_callback,+ void *data);++/* Sort without using memory. */++extern void backtrace_qsort (void *base, size_t count, size_t size,+ int (*compar) (const void *, const void *));++/* Allocate memory. This is like malloc. If ERROR_CALLBACK is NULL,+ this does not report an error, it just returns NULL. */++extern void *backtrace_alloc (struct backtrace_state *state, size_t size,+ backtrace_error_callback error_callback,+ void *data) ATTRIBUTE_MALLOC;++/* Free memory allocated by backtrace_alloc. If ERROR_CALLBACK is+ NULL, this does not report an error. */++extern void backtrace_free (struct backtrace_state *state, void *mem,+ size_t size,+ backtrace_error_callback error_callback,+ void *data);++/* A growable vector of some struct. This is used for more efficient+ allocation when we don't know the final size of some group of data+ that we want to represent as an array. */++struct backtrace_vector+{+ /* The base of the vector. */+ void *base;+ /* The number of bytes in the vector. */+ size_t size;+ /* The number of bytes available at the current allocation. */+ size_t alc;+};++/* Grow VEC by SIZE bytes. Return a pointer to the newly allocated+ bytes. Note that this may move the entire vector to a new memory+ location. Returns NULL on failure. */++extern void *backtrace_vector_grow (struct backtrace_state *state, size_t size,+ backtrace_error_callback error_callback,+ void *data,+ struct backtrace_vector *vec);++/* Finish the current allocation on VEC. Prepare to start a new+ allocation. The finished allocation will never be freed. Returns+ a pointer to the base of the finished entries, or NULL on+ failure. */++extern void* backtrace_vector_finish (struct backtrace_state *state,+ struct backtrace_vector *vec,+ backtrace_error_callback error_callback,+ void *data);++/* Release any extra space allocated for VEC. This may change+ VEC->base. Returns 1 on success, 0 on failure. */++extern int backtrace_vector_release (struct backtrace_state *state,+ struct backtrace_vector *vec,+ backtrace_error_callback error_callback,+ void *data);++/* Free the space managed by VEC. This will reset VEC. */++static inline void+backtrace_vector_free (struct backtrace_state *state,+ struct backtrace_vector *vec,+ backtrace_error_callback error_callback, void *data)+{+ vec->alc += vec->size;+ vec->size = 0;+ backtrace_vector_release (state, vec, error_callback, data);+}++/* Read initial debug data from a descriptor, and set the+ fileline_data, syminfo_fn, and syminfo_data fields of STATE.+ Return the fileln_fn field in *FILELN_FN--this is done this way so+ that the synchronization code is only implemented once. This is+ called after the descriptor has first been opened. It will close+ the descriptor if it is no longer needed. Returns 1 on success, 0+ on error. There will be multiple implementations of this function,+ for different file formats. Each system will compile the+ appropriate one. */++extern int backtrace_initialize (struct backtrace_state *state,+ const char *filename,+ int descriptor,+ backtrace_error_callback error_callback,+ void *data,+ fileline *fileline_fn);++/* An enum for the DWARF sections we care about. */++enum dwarf_section+{+ DEBUG_INFO,+ DEBUG_LINE,+ DEBUG_ABBREV,+ DEBUG_RANGES,+ DEBUG_STR,+ DEBUG_ADDR,+ DEBUG_STR_OFFSETS,+ DEBUG_LINE_STR,+ DEBUG_RNGLISTS,++ DEBUG_MAX+};++/* Data for the DWARF sections we care about. */++struct dwarf_sections+{+ const unsigned char *data[DEBUG_MAX];+ size_t size[DEBUG_MAX];+};++/* DWARF data read from a file, used for .gnu_debugaltlink. */++struct dwarf_data;++/* The load address mapping. */++#if defined(__FDPIC__) && defined(HAVE_DL_ITERATE_PHDR) && (defined(HAVE_LINK_H) || defined(HAVE_SYS_LINK_H))++#ifdef HAVE_LINK_H+ #include <link.h>+#endif+#ifdef HAVE_SYS_LINK_H+ #include <sys/link.h>+#endif++#define libbacktrace_using_fdpic() (1)++struct libbacktrace_base_address+{+ struct elf32_fdpic_loadaddr m;+};++#define libbacktrace_add_base(pc, base) \+ ((uintptr_t) (__RELOC_POINTER ((pc), (base).m)))++#else /* not _FDPIC__ */++#define libbacktrace_using_fdpic() (0)++struct libbacktrace_base_address+{+ uintptr_t m;+};++#define libbacktrace_add_base(pc, base) ((pc) + (base).m)++#endif /* not _FDPIC__ */++/* Add file/line information for a DWARF module. */++extern int backtrace_dwarf_add (struct backtrace_state *state,+ struct libbacktrace_base_address base_address,+ const struct dwarf_sections *dwarf_sections,+ int is_bigendian,+ struct dwarf_data *fileline_altlink,+ backtrace_error_callback error_callback,+ void *data, fileline *fileline_fn,+ struct dwarf_data **fileline_entry);++/* A data structure to pass to backtrace_syminfo_to_full. */++struct backtrace_call_full+{+ backtrace_full_callback full_callback;+ backtrace_error_callback full_error_callback;+ void *full_data;+ int ret;+};++/* A backtrace_syminfo_callback that can call into a+ backtrace_full_callback, used when we have a symbol table but no+ debug info. */++extern void backtrace_syminfo_to_full_callback (void *data, uintptr_t pc,+ const char *symname,+ uintptr_t symval,+ uintptr_t symsize);++/* An error callback that corresponds to+ backtrace_syminfo_to_full_callback. */++extern void backtrace_syminfo_to_full_error_callback (void *, const char *,+ int);++/* A test-only hook for elf_uncompress_zdebug. */++extern int backtrace_uncompress_zdebug (struct backtrace_state *,+ const unsigned char *compressed,+ size_t compressed_size,+ backtrace_error_callback, void *data,+ unsigned char **uncompressed,+ size_t *uncompressed_size);++/* A test-only hook for elf_zstd_decompress. */++extern int backtrace_uncompress_zstd (struct backtrace_state *,+ const unsigned char *compressed,+ size_t compressed_size,+ backtrace_error_callback, void *data,+ unsigned char *uncompressed,+ size_t uncompressed_size);++/* A test-only hook for elf_uncompress_lzma. */++extern int backtrace_uncompress_lzma (struct backtrace_state *,+ const unsigned char *compressed,+ size_t compressed_size,+ backtrace_error_callback, void *data,+ unsigned char **uncompressed,+ size_t *uncompressed_size);++}++#endif
+ cbits/tracy/public/libbacktrace/macho.cpp view
@@ -0,0 +1,1367 @@+/* elf.c -- Get debug data from a Mach-O file for backtraces.+ Copyright (C) 2020-2021 Free Software Foundation, Inc.+ Written by Ian Lance Taylor, Google.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are+met:++ (1) Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ (2) Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in+ the documentation and/or other materials provided with the+ distribution.++ (3) The name of the author may not be used to+ endorse or promote products derived from this software without+ specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. */++#include "config.h"++#include <sys/types.h>+#include <dirent.h>+#include <stdlib.h>+#include <string.h>++#ifdef HAVE_MACH_O_DYLD_H+#include <mach-o/dyld.h>+#endif++#include "backtrace.hpp"+#include "internal.hpp"++namespace tracy+{++/* Mach-O file header for a 32-bit executable. */++struct macho_header_32+{+ uint32_t magic; /* Magic number (MACH_O_MAGIC_32) */+ uint32_t cputype; /* CPU type */+ uint32_t cpusubtype; /* CPU subtype */+ uint32_t filetype; /* Type of file (object, executable) */+ uint32_t ncmds; /* Number of load commands */+ uint32_t sizeofcmds; /* Total size of load commands */+ uint32_t flags; /* Flags for special features */+};++/* Mach-O file header for a 64-bit executable. */++struct macho_header_64+{+ uint32_t magic; /* Magic number (MACH_O_MAGIC_64) */+ uint32_t cputype; /* CPU type */+ uint32_t cpusubtype; /* CPU subtype */+ uint32_t filetype; /* Type of file (object, executable) */+ uint32_t ncmds; /* Number of load commands */+ uint32_t sizeofcmds; /* Total size of load commands */+ uint32_t flags; /* Flags for special features */+ uint32_t reserved; /* Reserved */+};++/* Mach-O file header for a fat executable. */++struct macho_header_fat+{+ uint32_t magic; /* Magic number (MACH_O_MH_(MAGIC|CIGAM)_FAT(_64)?) */+ uint32_t nfat_arch; /* Number of components */+};++/* Values for the header magic field. */++#define MACH_O_MH_MAGIC_32 0xfeedface+#define MACH_O_MH_MAGIC_64 0xfeedfacf+#define MACH_O_MH_MAGIC_FAT 0xcafebabe+#define MACH_O_MH_CIGAM_FAT 0xbebafeca+#define MACH_O_MH_MAGIC_FAT_64 0xcafebabf+#define MACH_O_MH_CIGAM_FAT_64 0xbfbafeca++/* Value for the header filetype field. */++#define MACH_O_MH_EXECUTE 0x02+#define MACH_O_MH_DYLIB 0x06+#define MACH_O_MH_DSYM 0x0a++/* A component of a fat file. A fat file starts with a+ macho_header_fat followed by nfat_arch instances of this+ struct. */++struct macho_fat_arch+{+ uint32_t cputype; /* CPU type */+ uint32_t cpusubtype; /* CPU subtype */+ uint32_t offset; /* File offset of this entry */+ uint32_t size; /* Size of this entry */+ uint32_t align; /* Alignment of this entry */+};++/* A component of a 64-bit fat file. This is used if the magic field+ is MAGIC_FAT_64. This is only used when some file size or file+ offset is too large to represent in the 32-bit format. */++struct macho_fat_arch_64+{+ uint32_t cputype; /* CPU type */+ uint32_t cpusubtype; /* CPU subtype */+ uint64_t offset; /* File offset of this entry */+ uint64_t size; /* Size of this entry */+ uint32_t align; /* Alignment of this entry */+ uint32_t reserved; /* Reserved */+};++/* Values for the fat_arch cputype field (and the header cputype+ field). */++#define MACH_O_CPU_ARCH_ABI64 0x01000000++#define MACH_O_CPU_TYPE_X86 7+#define MACH_O_CPU_TYPE_ARM 12+#define MACH_O_CPU_TYPE_PPC 18++#define MACH_O_CPU_TYPE_X86_64 (MACH_O_CPU_TYPE_X86 | MACH_O_CPU_ARCH_ABI64)+#define MACH_O_CPU_TYPE_ARM64 (MACH_O_CPU_TYPE_ARM | MACH_O_CPU_ARCH_ABI64)+#define MACH_O_CPU_TYPE_PPC64 (MACH_O_CPU_TYPE_PPC | MACH_O_CPU_ARCH_ABI64)++/* The header of a load command. */++struct macho_load_command+{+ uint32_t cmd; /* The type of load command */+ uint32_t cmdsize; /* Size in bytes of the entire command */+};++/* Values for the load_command cmd field. */++#define MACH_O_LC_SEGMENT 0x01+#define MACH_O_LC_SYMTAB 0x02+#define MACH_O_LC_SEGMENT_64 0x19+#define MACH_O_LC_UUID 0x1b++/* The length of a section of segment name. */++#define MACH_O_NAMELEN (16)++/* LC_SEGMENT load command. */++struct macho_segment_command+{+ uint32_t cmd; /* The type of load command (LC_SEGMENT) */+ uint32_t cmdsize; /* Size in bytes of the entire command */+ char segname[MACH_O_NAMELEN]; /* Segment name */+ uint32_t vmaddr; /* Virtual memory address */+ uint32_t vmsize; /* Virtual memory size */+ uint32_t fileoff; /* Offset of data to be mapped */+ uint32_t filesize; /* Size of data in file */+ uint32_t maxprot; /* Maximum permitted virtual protection */+ uint32_t initprot; /* Initial virtual memory protection */+ uint32_t nsects; /* Number of sections in this segment */+ uint32_t flags; /* Flags */+};++/* LC_SEGMENT_64 load command. */++struct macho_segment_64_command+{+ uint32_t cmd; /* The type of load command (LC_SEGMENT) */+ uint32_t cmdsize; /* Size in bytes of the entire command */+ char segname[MACH_O_NAMELEN]; /* Segment name */+ uint64_t vmaddr; /* Virtual memory address */+ uint64_t vmsize; /* Virtual memory size */+ uint64_t fileoff; /* Offset of data to be mapped */+ uint64_t filesize; /* Size of data in file */+ uint32_t maxprot; /* Maximum permitted virtual protection */+ uint32_t initprot; /* Initial virtual memory protection */+ uint32_t nsects; /* Number of sections in this segment */+ uint32_t flags; /* Flags */+};++/* LC_SYMTAB load command. */++struct macho_symtab_command+{+ uint32_t cmd; /* The type of load command (LC_SEGMENT) */+ uint32_t cmdsize; /* Size in bytes of the entire command */+ uint32_t symoff; /* File offset of symbol table */+ uint32_t nsyms; /* Number of symbols */+ uint32_t stroff; /* File offset of string table */+ uint32_t strsize; /* String table size */+};++/* The length of a Mach-O uuid. */++#define MACH_O_UUID_LEN (16)++/* LC_UUID load command. */++struct macho_uuid_command+{+ uint32_t cmd; /* Type of load command (LC_UUID) */+ uint32_t cmdsize; /* Size in bytes of command */+ unsigned char uuid[MACH_O_UUID_LEN]; /* UUID */+};++/* 32-bit section header within a LC_SEGMENT segment. */++struct macho_section+{+ char sectname[MACH_O_NAMELEN]; /* Section name */+ char segment[MACH_O_NAMELEN]; /* Segment of this section */+ uint32_t addr; /* Address in memory */+ uint32_t size; /* Section size */+ uint32_t offset; /* File offset */+ uint32_t align; /* Log2 of section alignment */+ uint32_t reloff; /* File offset of relocations */+ uint32_t nreloc; /* Number of relocs for this section */+ uint32_t flags; /* Flags */+ uint32_t reserved1;+ uint32_t reserved2;+};++/* 64-bit section header within a LC_SEGMENT_64 segment. */++struct macho_section_64+{+ char sectname[MACH_O_NAMELEN]; /* Section name */+ char segment[MACH_O_NAMELEN]; /* Segment of this section */+ uint64_t addr; /* Address in memory */+ uint64_t size; /* Section size */+ uint32_t offset; /* File offset */+ uint32_t align; /* Log2 of section alignment */+ uint32_t reloff; /* File offset of section relocations */+ uint32_t nreloc; /* Number of relocs for this section */+ uint32_t flags; /* Flags */+ uint32_t reserved1;+ uint32_t reserved2;+ uint32_t reserved3;+};++/* 32-bit symbol data. */++struct macho_nlist+{+ uint32_t n_strx; /* Index of name in string table */+ uint8_t n_type; /* Type flag */+ uint8_t n_sect; /* Section number */+ uint16_t n_desc; /* Stabs description field */+ uint32_t n_value; /* Value */+};++/* 64-bit symbol data. */++struct macho_nlist_64+{+ uint32_t n_strx; /* Index of name in string table */+ uint8_t n_type; /* Type flag */+ uint8_t n_sect; /* Section number */+ uint16_t n_desc; /* Stabs description field */+ uint64_t n_value; /* Value */+};++/* Value found in nlist n_type field. */++#define MACH_O_N_STAB 0xe0 /* Stabs debugging symbol */+#define MACH_O_N_TYPE 0x0e /* Mask for type bits */++/* Values found after masking with MACH_O_N_TYPE. */+#define MACH_O_N_UNDF 0x00 /* Undefined symbol */+#define MACH_O_N_ABS 0x02 /* Absolute symbol */+#define MACH_O_N_SECT 0x0e /* Defined in section from n_sect field */+++/* Information we keep for a Mach-O symbol. */++struct macho_symbol+{+ const char *name; /* Symbol name */+ uintptr_t address; /* Symbol address */+};++/* Information to pass to macho_syminfo. */++struct macho_syminfo_data+{+ struct macho_syminfo_data *next; /* Next module */+ struct macho_symbol *symbols; /* Symbols sorted by address */+ size_t count; /* Number of symbols */+};++/* Names of sections, indexed by enum dwarf_section in internal.h. */++static const char * const dwarf_section_names[DEBUG_MAX] =+{+ "__debug_info",+ "__debug_line",+ "__debug_abbrev",+ "__debug_ranges",+ "__debug_str",+ "", /* DEBUG_ADDR */+ "__debug_str_offs",+ "", /* DEBUG_LINE_STR */+ "__debug_rnglists"+};++/* Forward declaration. */++static int macho_add (struct backtrace_state *, const char *, int, off_t,+ const unsigned char *, struct libbacktrace_base_address,+ int, backtrace_error_callback, void *, fileline *,+ int *);++/* A dummy callback function used when we can't find any debug info. */++static int+macho_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,+ uintptr_t pc ATTRIBUTE_UNUSED,+ backtrace_full_callback callback ATTRIBUTE_UNUSED,+ backtrace_error_callback error_callback, void *data)+{+ error_callback (data, "no debug info in Mach-O executable", -1);+ return 0;+}++/* A dummy callback function used when we can't find a symbol+ table. */++static void+macho_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,+ uintptr_t addr ATTRIBUTE_UNUSED,+ backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,+ backtrace_error_callback error_callback, void *data)+{+ error_callback (data, "no symbol table in Mach-O executable", -1);+}++/* Add a single DWARF section to DWARF_SECTIONS, if we need the+ section. Returns 1 on success, 0 on failure. */++static int+macho_add_dwarf_section (struct backtrace_state *state, int descriptor,+ const char *sectname, uint32_t offset, uint64_t size,+ backtrace_error_callback error_callback, void *data,+ struct dwarf_sections *dwarf_sections)+{+ int i;++ for (i = 0; i < (int) DEBUG_MAX; ++i)+ {+ if (dwarf_section_names[i][0] != '\0'+ && strncmp (sectname, dwarf_section_names[i], MACH_O_NAMELEN) == 0)+ {+ struct backtrace_view section_view;++ /* FIXME: Perhaps it would be better to try to use a single+ view to read all the DWARF data, as we try to do for+ ELF. */++ if (!backtrace_get_view (state, descriptor, offset, size,+ error_callback, data, §ion_view))+ return 0;+ dwarf_sections->data[i] = (const unsigned char *) section_view.data;+ dwarf_sections->size[i] = size;+ break;+ }+ }+ return 1;+}++/* Collect DWARF sections from a DWARF segment. Returns 1 on success,+ 0 on failure. */++static int+macho_add_dwarf_segment (struct backtrace_state *state, int descriptor,+ off_t offset, unsigned int cmd, const char *psecs,+ size_t sizesecs, unsigned int nsects,+ backtrace_error_callback error_callback, void *data,+ struct dwarf_sections *dwarf_sections)+{+ size_t sec_header_size;+ size_t secoffset;+ unsigned int i;++ switch (cmd)+ {+ case MACH_O_LC_SEGMENT:+ sec_header_size = sizeof (struct macho_section);+ break;+ case MACH_O_LC_SEGMENT_64:+ sec_header_size = sizeof (struct macho_section_64);+ break;+ default:+ abort ();+ }++ secoffset = 0;+ for (i = 0; i < nsects; ++i)+ {+ if (secoffset + sec_header_size > sizesecs)+ {+ error_callback (data, "section overflow withing segment", 0);+ return 0;+ }++ switch (cmd)+ {+ case MACH_O_LC_SEGMENT:+ {+ struct macho_section section;++ memcpy (§ion, psecs + secoffset, sizeof section);+ macho_add_dwarf_section (state, descriptor, section.sectname,+ offset + section.offset, section.size,+ error_callback, data, dwarf_sections);+ }+ break;++ case MACH_O_LC_SEGMENT_64:+ {+ struct macho_section_64 section;++ memcpy (§ion, psecs + secoffset, sizeof section);+ macho_add_dwarf_section (state, descriptor, section.sectname,+ offset + section.offset, section.size,+ error_callback, data, dwarf_sections);+ }+ break;++ default:+ abort ();+ }++ secoffset += sec_header_size;+ }++ return 1;+}++/* Compare struct macho_symbol for qsort. */++static int+macho_symbol_compare (const void *v1, const void *v2)+{+ const struct macho_symbol *m1 = (const struct macho_symbol *) v1;+ const struct macho_symbol *m2 = (const struct macho_symbol *) v2;++ if (m1->address < m2->address)+ return -1;+ else if (m1->address > m2->address)+ return 1;+ else+ return 0;+}++/* Compare an address against a macho_symbol for bsearch. We allocate+ one extra entry in the array so that this can safely look at the+ next entry. */++static int+macho_symbol_search (const void *vkey, const void *ventry)+{+ const uintptr_t *key = (const uintptr_t *) vkey;+ const struct macho_symbol *entry = (const struct macho_symbol *) ventry;+ uintptr_t addr;++ addr = *key;+ if (addr < entry->address)+ return -1;+ else if (entry->name[0] == '\0'+ && entry->address == ~(uintptr_t) 0)+ return -1;+ else if ((entry + 1)->name[0] == '\0'+ && (entry + 1)->address == ~(uintptr_t) 0)+ return -1;+ else if (addr >= (entry + 1)->address)+ return 1;+ else+ return 0;+}++/* Return whether the symbol type field indicates a symbol table entry+ that we care about: a function or data symbol. */++static int+macho_defined_symbol (uint8_t type)+{+ if ((type & MACH_O_N_STAB) != 0)+ return 0;+ switch (type & MACH_O_N_TYPE)+ {+ case MACH_O_N_UNDF:+ return 0;+ case MACH_O_N_ABS:+ return 1;+ case MACH_O_N_SECT:+ return 1;+ default:+ return 0;+ }+}++/* Add symbol table information for a Mach-O file. */++static int+macho_add_symtab (struct backtrace_state *state, int descriptor,+ struct libbacktrace_base_address base_address, int is_64,+ off_t symoff, unsigned int nsyms, off_t stroff,+ unsigned int strsize,+ backtrace_error_callback error_callback, void *data)+{+ size_t symsize;+ struct backtrace_view sym_view;+ int sym_view_valid;+ struct backtrace_view str_view;+ int str_view_valid;+ size_t ndefs;+ size_t symtaboff;+ unsigned int i;+ size_t macho_symbol_size;+ struct macho_symbol *macho_symbols;+ unsigned int j;+ struct macho_syminfo_data *sdata;++ sym_view_valid = 0;+ str_view_valid = 0;+ macho_symbol_size = 0;+ macho_symbols = NULL;++ if (is_64)+ symsize = sizeof (struct macho_nlist_64);+ else+ symsize = sizeof (struct macho_nlist);++ if (!backtrace_get_view (state, descriptor, symoff, nsyms * symsize,+ error_callback, data, &sym_view))+ goto fail;+ sym_view_valid = 1;++ if (!backtrace_get_view (state, descriptor, stroff, strsize,+ error_callback, data, &str_view))+ return 0;+ str_view_valid = 1;++ ndefs = 0;+ symtaboff = 0;+ for (i = 0; i < nsyms; ++i, symtaboff += symsize)+ {+ if (is_64)+ {+ struct macho_nlist_64 nlist;++ memcpy (&nlist, (const char *) sym_view.data + symtaboff,+ sizeof nlist);+ if (macho_defined_symbol (nlist.n_type))+ ++ndefs;+ }+ else+ {+ struct macho_nlist nlist;++ memcpy (&nlist, (const char *) sym_view.data + symtaboff,+ sizeof nlist);+ if (macho_defined_symbol (nlist.n_type))+ ++ndefs;+ }+ }++ /* Add 1 to ndefs to make room for a sentinel. */+ macho_symbol_size = (ndefs + 1) * sizeof (struct macho_symbol);+ macho_symbols = ((struct macho_symbol *)+ backtrace_alloc (state, macho_symbol_size, error_callback,+ data));+ if (macho_symbols == NULL)+ goto fail;++ j = 0;+ symtaboff = 0;+ for (i = 0; i < nsyms; ++i, symtaboff += symsize)+ {+ uint32_t strx;+ uint64_t value;+ const char *name;++ strx = 0;+ value = 0;+ if (is_64)+ {+ struct macho_nlist_64 nlist;++ memcpy (&nlist, (const char *) sym_view.data + symtaboff,+ sizeof nlist);+ if (!macho_defined_symbol (nlist.n_type))+ continue;++ strx = nlist.n_strx;+ value = nlist.n_value;+ }+ else+ {+ struct macho_nlist nlist;++ memcpy (&nlist, (const char *) sym_view.data + symtaboff,+ sizeof nlist);+ if (!macho_defined_symbol (nlist.n_type))+ continue;++ strx = nlist.n_strx;+ value = nlist.n_value;+ }++ if (strx >= strsize)+ {+ error_callback (data, "symbol string index out of range", 0);+ goto fail;+ }++ name = (const char *) str_view.data + strx;+ if (name[0] == '_')+ ++name;+ macho_symbols[j].name = name;+ macho_symbols[j].address = libbacktrace_add_base (value, base_address);+ ++j;+ }++ sdata = ((struct macho_syminfo_data *)+ backtrace_alloc (state, sizeof *sdata, error_callback, data));+ if (sdata == NULL)+ goto fail;++ /* We need to keep the string table since it holds the names, but we+ can release the symbol table. */++ backtrace_release_view (state, &sym_view, error_callback, data);+ sym_view_valid = 0;+ str_view_valid = 0;++ /* Add a trailing sentinel symbol. */+ macho_symbols[j].name = "";+ macho_symbols[j].address = ~(uintptr_t) 0;++ backtrace_qsort (macho_symbols, ndefs + 1, sizeof (struct macho_symbol),+ macho_symbol_compare);++ sdata->next = NULL;+ sdata->symbols = macho_symbols;+ sdata->count = ndefs;++ if (!state->threaded)+ {+ struct macho_syminfo_data **pp;++ for (pp = (struct macho_syminfo_data **) (void *) &state->syminfo_data;+ *pp != NULL;+ pp = &(*pp)->next)+ ;+ *pp = sdata;+ }+ else+ {+ while (1)+ {+ struct macho_syminfo_data **pp;++ pp = (struct macho_syminfo_data **) (void *) &state->syminfo_data;++ while (1)+ {+ struct macho_syminfo_data *p;++ p = backtrace_atomic_load_pointer (pp);+ + if (p == NULL)+ break;++ pp = &p->next;+ }++ if (__sync_bool_compare_and_swap (pp, NULL, sdata))+ break;+ }+ }++ return 1;++ fail:+ if (macho_symbols != NULL)+ backtrace_free (state, macho_symbols, macho_symbol_size,+ error_callback, data);+ if (sym_view_valid)+ backtrace_release_view (state, &sym_view, error_callback, data);+ if (str_view_valid)+ backtrace_release_view (state, &str_view, error_callback, data);+ return 0;+}++/* Return the symbol name and value for an ADDR. */++static void+macho_syminfo (struct backtrace_state *state, uintptr_t addr,+ backtrace_syminfo_callback callback,+ backtrace_error_callback error_callback ATTRIBUTE_UNUSED,+ void *data)+{+ struct macho_syminfo_data *sdata;+ struct macho_symbol *sym;++ sym = NULL;+ if (!state->threaded)+ {+ for (sdata = (struct macho_syminfo_data *) state->syminfo_data;+ sdata != NULL;+ sdata = sdata->next)+ {+ sym = ((struct macho_symbol *)+ bsearch (&addr, sdata->symbols, sdata->count,+ sizeof (struct macho_symbol), macho_symbol_search));+ if (sym != NULL)+ break;+ }+ }+ else+ {+ struct macho_syminfo_data **pp;++ pp = (struct macho_syminfo_data **) (void *) &state->syminfo_data;+ while (1)+ {+ sdata = backtrace_atomic_load_pointer (pp);+ if (sdata == NULL)+ break;++ sym = ((struct macho_symbol *)+ bsearch (&addr, sdata->symbols, sdata->count,+ sizeof (struct macho_symbol), macho_symbol_search));+ if (sym != NULL)+ break;++ pp = &sdata->next;+ }+ }++ if (sym == NULL)+ callback (data, addr, NULL, 0, 0);+ else+ callback (data, addr, sym->name, sym->address, 0);+}++/* Look through a fat file to find the relevant executable. Returns 1+ on success, 0 on failure (in both cases descriptor is closed). */++static int+macho_add_fat (struct backtrace_state *state, const char *filename,+ int descriptor, int swapped, off_t offset,+ const unsigned char *match_uuid,+ struct libbacktrace_base_address base_address,+ int skip_symtab, uint32_t nfat_arch, int is_64,+ backtrace_error_callback error_callback, void *data,+ fileline *fileline_fn, int *found_sym)+{+ int arch_view_valid;+ unsigned int cputype;+ size_t arch_size;+ struct backtrace_view arch_view;+ unsigned int i;++ arch_view_valid = 0;++#if defined (__x86_64__)+ cputype = MACH_O_CPU_TYPE_X86_64;+#elif defined (__i386__)+ cputype = MACH_O_CPU_TYPE_X86;+#elif defined (__aarch64__)+ cputype = MACH_O_CPU_TYPE_ARM64;+#elif defined (__arm__)+ cputype = MACH_O_CPU_TYPE_ARM;+#elif defined (__ppc__)+ cputype = MACH_O_CPU_TYPE_PPC;+#elif defined (__ppc64__)+ cputype = MACH_O_CPU_TYPE_PPC64;+#else+ error_callback (data, "unknown Mach-O architecture", 0);+ goto fail;+#endif++ if (is_64)+ arch_size = sizeof (struct macho_fat_arch_64);+ else+ arch_size = sizeof (struct macho_fat_arch);++ if (!backtrace_get_view (state, descriptor, offset,+ nfat_arch * arch_size,+ error_callback, data, &arch_view))+ goto fail;++ for (i = 0; i < nfat_arch; ++i)+ {+ uint32_t fcputype;+ uint64_t foffset;++ if (is_64)+ {+ struct macho_fat_arch_64 fat_arch_64;++ memcpy (&fat_arch_64,+ (const char *) arch_view.data + i * arch_size,+ arch_size);+ fcputype = fat_arch_64.cputype;+ foffset = fat_arch_64.offset;+ if (swapped)+ {+ fcputype = __builtin_bswap32 (fcputype);+ foffset = __builtin_bswap64 (foffset);+ }+ }+ else+ {+ struct macho_fat_arch fat_arch_32;++ memcpy (&fat_arch_32,+ (const char *) arch_view.data + i * arch_size,+ arch_size);+ fcputype = fat_arch_32.cputype;+ foffset = (uint64_t) fat_arch_32.offset;+ if (swapped)+ {+ fcputype = __builtin_bswap32 (fcputype);+ foffset = (uint64_t) __builtin_bswap32 ((uint32_t) foffset);+ }+ }++ if (fcputype == cputype)+ {+ /* FIXME: What about cpusubtype? */+ backtrace_release_view (state, &arch_view, error_callback, data);+ return macho_add (state, filename, descriptor, foffset, match_uuid,+ base_address, skip_symtab, error_callback, data,+ fileline_fn, found_sym);+ }+ }++ error_callback (data, "could not find executable in fat file", 0);++ fail:+ if (arch_view_valid)+ backtrace_release_view (state, &arch_view, error_callback, data);+ if (descriptor != -1)+ backtrace_close (descriptor, error_callback, data);+ return 0;+}++/* Look for the dsym file for FILENAME. This is called if FILENAME+ does not have debug info or a symbol table. Returns 1 on success,+ 0 on failure. */++static int+macho_add_dsym (struct backtrace_state *state, const char *filename,+ struct libbacktrace_base_address base_address,+ const unsigned char *uuid,+ backtrace_error_callback error_callback, void *data,+ fileline* fileline_fn)+{+ const char *p;+ const char *dirname;+ char *diralc;+ size_t dirnamelen;+ const char *basename;+ size_t basenamelen;+ const char *dsymsuffixdir;+ size_t dsymsuffixdirlen;+ size_t dsymlen;+ char *dsym;+ char *ps;+ int d;+ int does_not_exist;+ int dummy_found_sym;++ diralc = NULL;+ dirnamelen = 0;+ dsym = NULL;+ dsymlen = 0;++ p = strrchr (filename, '/');+ if (p == NULL)+ {+ dirname = ".";+ dirnamelen = 1;+ basename = filename;+ basenamelen = strlen (basename);+ diralc = NULL;+ }+ else+ {+ dirnamelen = p - filename;+ diralc = (char*)backtrace_alloc (state, dirnamelen + 1, error_callback, data);+ if (diralc == NULL)+ goto fail;+ memcpy (diralc, filename, dirnamelen);+ diralc[dirnamelen] = '\0';+ dirname = diralc;+ basename = p + 1;+ basenamelen = strlen (basename);+ }++ dsymsuffixdir = ".dSYM/Contents/Resources/DWARF/";+ dsymsuffixdirlen = strlen (dsymsuffixdir);++ dsymlen = (dirnamelen+ + 1+ + basenamelen+ + dsymsuffixdirlen+ + basenamelen+ + 1);+ dsym = (char*)backtrace_alloc (state, dsymlen, error_callback, data);+ if (dsym == NULL)+ goto fail;++ ps = dsym;+ memcpy (ps, dirname, dirnamelen);+ ps += dirnamelen;+ *ps++ = '/';+ memcpy (ps, basename, basenamelen);+ ps += basenamelen;+ memcpy (ps, dsymsuffixdir, dsymsuffixdirlen);+ ps += dsymsuffixdirlen;+ memcpy (ps, basename, basenamelen);+ ps += basenamelen;+ *ps = '\0';++ if (diralc != NULL)+ {+ backtrace_free (state, diralc, dirnamelen + 1, error_callback, data);+ diralc = NULL;+ }++ d = backtrace_open (dsym, error_callback, data, &does_not_exist);+ if (d < 0)+ {+ /* The file does not exist, so we can't read the debug info.+ Just return success. */+ backtrace_free (state, dsym, dsymlen, error_callback, data);+ return 1;+ }++ if (!macho_add (state, dsym, d, 0, uuid, base_address, 1,+ error_callback, data, fileline_fn, &dummy_found_sym))+ goto fail;++ backtrace_free (state, dsym, dsymlen, error_callback, data);++ return 1;++ fail:+ if (dsym != NULL)+ backtrace_free (state, dsym, dsymlen, error_callback, data);+ if (diralc != NULL)+ backtrace_free (state, diralc, dirnamelen, error_callback, data);+ return 0;+}++/* Add the backtrace data for a Macho-O file. Returns 1 on success, 0+ on failure (in both cases descriptor is closed).++ FILENAME: the name of the executable.+ DESCRIPTOR: an open descriptor for the executable, closed here.+ OFFSET: the offset within the file of this executable, for fat files.+ MATCH_UUID: if not NULL, UUID that must match.+ BASE_ADDRESS: the load address of the executable.+ SKIP_SYMTAB: if non-zero, ignore the symbol table; used for dSYM files.+ FILELINE_FN: set to the fileline function, by backtrace_dwarf_add.+ FOUND_SYM: set to non-zero if we found the symbol table.+*/++static int+macho_add (struct backtrace_state *state, const char *filename, int descriptor,+ off_t offset, const unsigned char *match_uuid,+ struct libbacktrace_base_address base_address, int skip_symtab,+ backtrace_error_callback error_callback, void *data,+ fileline *fileline_fn, int *found_sym)+{+ struct backtrace_view header_view;+ struct macho_header_32 header;+ off_t hdroffset;+ int is_64;+ struct backtrace_view cmds_view;+ int cmds_view_valid;+ struct dwarf_sections dwarf_sections;+ int have_dwarf;+ unsigned char uuid[MACH_O_UUID_LEN];+ int have_uuid;+ size_t cmdoffset;+ unsigned int i;++ *found_sym = 0;++ cmds_view_valid = 0;++ /* The 32-bit and 64-bit file headers start out the same, so we can+ just always read the 32-bit version. A fat header is shorter but+ it will always be followed by data, so it's OK to read extra. */++ if (!backtrace_get_view (state, descriptor, offset,+ sizeof (struct macho_header_32),+ error_callback, data, &header_view))+ goto fail;++ memcpy (&header, header_view.data, sizeof header);++ backtrace_release_view (state, &header_view, error_callback, data);++ switch (header.magic)+ {+ case MACH_O_MH_MAGIC_32:+ is_64 = 0;+ hdroffset = offset + sizeof (struct macho_header_32);+ break;+ case MACH_O_MH_MAGIC_64:+ is_64 = 1;+ hdroffset = offset + sizeof (struct macho_header_64);+ break;+ case MACH_O_MH_MAGIC_FAT:+ case MACH_O_MH_MAGIC_FAT_64:+ {+ struct macho_header_fat fat_header;++ hdroffset = offset + sizeof (struct macho_header_fat);+ memcpy (&fat_header, &header, sizeof fat_header);+ return macho_add_fat (state, filename, descriptor, 0, hdroffset,+ match_uuid, base_address, skip_symtab,+ fat_header.nfat_arch,+ header.magic == MACH_O_MH_MAGIC_FAT_64,+ error_callback, data, fileline_fn, found_sym);+ }+ case MACH_O_MH_CIGAM_FAT:+ case MACH_O_MH_CIGAM_FAT_64:+ {+ struct macho_header_fat fat_header;+ uint32_t nfat_arch;++ hdroffset = offset + sizeof (struct macho_header_fat);+ memcpy (&fat_header, &header, sizeof fat_header);+ nfat_arch = __builtin_bswap32 (fat_header.nfat_arch);+ return macho_add_fat (state, filename, descriptor, 1, hdroffset,+ match_uuid, base_address, skip_symtab,+ nfat_arch,+ header.magic == MACH_O_MH_CIGAM_FAT_64,+ error_callback, data, fileline_fn, found_sym);+ }+ default:+ error_callback (data, "executable file is not in Mach-O format", 0);+ goto fail;+ }++ switch (header.filetype)+ {+ case MACH_O_MH_EXECUTE:+ case MACH_O_MH_DYLIB:+ case MACH_O_MH_DSYM:+ break;+ default:+ error_callback (data, "executable file is not an executable", 0);+ goto fail;+ }++ if (!backtrace_get_view (state, descriptor, hdroffset, header.sizeofcmds,+ error_callback, data, &cmds_view))+ goto fail;+ cmds_view_valid = 1;++ memset (&dwarf_sections, 0, sizeof dwarf_sections);+ have_dwarf = 0;+ memset (&uuid, 0, sizeof uuid);+ have_uuid = 0;++ cmdoffset = 0;+ for (i = 0; i < header.ncmds; ++i)+ {+ const char *pcmd;+ struct macho_load_command load_command;++ if (cmdoffset + sizeof load_command > header.sizeofcmds)+ break;++ pcmd = (const char *) cmds_view.data + cmdoffset;+ memcpy (&load_command, pcmd, sizeof load_command);++ switch (load_command.cmd)+ {+ case MACH_O_LC_SEGMENT:+ {+ struct macho_segment_command segcmd;++ memcpy (&segcmd, pcmd, sizeof segcmd);+ if (memcmp (segcmd.segname,+ "__DWARF\0\0\0\0\0\0\0\0\0",+ MACH_O_NAMELEN) == 0)+ {+ if (!macho_add_dwarf_segment (state, descriptor, offset,+ load_command.cmd,+ pcmd + sizeof segcmd,+ (load_command.cmdsize+ - sizeof segcmd),+ segcmd.nsects, error_callback,+ data, &dwarf_sections))+ goto fail;+ have_dwarf = 1;+ }+ }+ break;++ case MACH_O_LC_SEGMENT_64:+ {+ struct macho_segment_64_command segcmd;++ memcpy (&segcmd, pcmd, sizeof segcmd);+ if (memcmp (segcmd.segname,+ "__DWARF\0\0\0\0\0\0\0\0\0",+ MACH_O_NAMELEN) == 0)+ {+ if (!macho_add_dwarf_segment (state, descriptor, offset,+ load_command.cmd,+ pcmd + sizeof segcmd,+ (load_command.cmdsize+ - sizeof segcmd),+ segcmd.nsects, error_callback,+ data, &dwarf_sections))+ goto fail;+ have_dwarf = 1;+ }+ }+ break;++ case MACH_O_LC_SYMTAB:+ if (!skip_symtab)+ {+ struct macho_symtab_command symcmd;++ memcpy (&symcmd, pcmd, sizeof symcmd);+ if (!macho_add_symtab (state, descriptor, base_address, is_64,+ offset + symcmd.symoff, symcmd.nsyms,+ offset + symcmd.stroff, symcmd.strsize,+ error_callback, data))+ goto fail;++ *found_sym = 1;+ }+ break;++ case MACH_O_LC_UUID:+ {+ struct macho_uuid_command uuidcmd;++ memcpy (&uuidcmd, pcmd, sizeof uuidcmd);+ memcpy (&uuid[0], &uuidcmd.uuid[0], MACH_O_UUID_LEN);+ have_uuid = 1;+ }+ break;++ default:+ break;+ }++ cmdoffset += load_command.cmdsize;+ }++ if (!backtrace_close (descriptor, error_callback, data))+ goto fail;+ descriptor = -1;++ backtrace_release_view (state, &cmds_view, error_callback, data);+ cmds_view_valid = 0;++ if (match_uuid != NULL)+ {+ /* If we don't have a UUID, or it doesn't match, just ignore+ this file. */+ if (!have_uuid+ || memcmp (match_uuid, &uuid[0], MACH_O_UUID_LEN) != 0)+ return 1;+ }++ if (have_dwarf)+ {+ int is_big_endian;++ is_big_endian = 0;+#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__)+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__+ is_big_endian = 1;+#endif+#endif++ if (!backtrace_dwarf_add (state, base_address, &dwarf_sections,+ is_big_endian, NULL, error_callback, data,+ fileline_fn, NULL))+ goto fail;+ }++ if (!have_dwarf && have_uuid)+ {+ if (!macho_add_dsym (state, filename, base_address, &uuid[0],+ error_callback, data, fileline_fn))+ goto fail;+ }++ return 1;++ fail:+ if (cmds_view_valid)+ backtrace_release_view (state, &cmds_view, error_callback, data);+ if (descriptor != -1)+ backtrace_close (descriptor, error_callback, data);+ return 0;+}++#ifdef HAVE_MACH_O_DYLD_H++/* Initialize the backtrace data we need from a Mach-O executable+ using the dyld support functions. This closes descriptor. */++int+backtrace_initialize (struct backtrace_state *state, const char *filename,+ int descriptor, backtrace_error_callback error_callback,+ void *data, fileline *fileline_fn)+{+ uint32_t c;+ uint32_t i;+ int closed_descriptor;+ int found_sym;+ fileline macho_fileline_fn;++ closed_descriptor = 0;+ found_sym = 0;+ macho_fileline_fn = macho_nodebug;++ c = _dyld_image_count ();+ for (i = 0; i < c; ++i)+ {+ struct libbacktrace_base_address base_address;+ const char *name;+ int d;+ fileline mff;+ int mfs;++ name = _dyld_get_image_name (i);+ if (name == NULL)+ continue;++ if (strcmp (name, filename) == 0 && !closed_descriptor)+ {+ d = descriptor;+ closed_descriptor = 1;+ }+ else+ {+ int does_not_exist;++ d = backtrace_open (name, error_callback, data, &does_not_exist);+ if (d < 0)+ continue;+ }++ base_address.m = _dyld_get_image_vmaddr_slide (i);++ mff = macho_nodebug;+ if (!macho_add (state, name, d, 0, NULL, base_address, 0,+ error_callback, data, &mff, &mfs))+ continue;++ if (mff != macho_nodebug)+ macho_fileline_fn = mff;+ if (mfs)+ found_sym = 1;+ }++ if (!closed_descriptor)+ backtrace_close (descriptor, error_callback, data);++ if (!state->threaded)+ {+ if (found_sym)+ state->syminfo_fn = macho_syminfo;+ else if (state->syminfo_fn == NULL)+ state->syminfo_fn = macho_nosyms;+ }+ else+ {+ if (found_sym)+ backtrace_atomic_store_pointer (&state->syminfo_fn, &macho_syminfo);+ else+ (void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,+ macho_nosyms);+ }++ if (!state->threaded)+ *fileline_fn = state->fileline_fn;+ else+ *fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);++ if (*fileline_fn == NULL || *fileline_fn == macho_nodebug)+ *fileline_fn = macho_fileline_fn;++ return 1;+}++#else /* !defined (HAVE_MACH_O_DYLD_H) */++/* Initialize the backtrace data we need from a Mach-O executable+ without using the dyld support functions. This closes+ descriptor. */++int+backtrace_initialize (struct backtrace_state *state, const char *filename,+ int descriptor, backtrace_error_callback error_callback,+ void *data, fileline *fileline_fn)+{+ fileline macho_fileline_fn;+ struct libbacktrace_base_address zero_base_address;+ int found_sym;++ macho_fileline_fn = macho_nodebug;+ memset (&zero_base_address, 0, sizeof zero_base_address);+ if (!macho_add (state, filename, descriptor, 0, NULL, zero_base_address, 0,+ error_callback, data, &macho_fileline_fn, &found_sym))+ return 0;++ if (!state->threaded)+ {+ if (found_sym)+ state->syminfo_fn = macho_syminfo;+ else if (state->syminfo_fn == NULL)+ state->syminfo_fn = macho_nosyms;+ }+ else+ {+ if (found_sym)+ backtrace_atomic_store_pointer (&state->syminfo_fn, &macho_syminfo);+ else+ (void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,+ macho_nosyms);+ }++ if (!state->threaded)+ *fileline_fn = state->fileline_fn;+ else+ *fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);++ if (*fileline_fn == NULL || *fileline_fn == macho_nodebug)+ *fileline_fn = macho_fileline_fn;++ return 1;+}++#endif /* !defined (HAVE_MACH_O_DYLD_H) */++}
+ cbits/tracy/public/libbacktrace/mmapio.cpp view
@@ -0,0 +1,115 @@+/* mmapio.c -- File views using mmap.+ Copyright (C) 2012-2021 Free Software Foundation, Inc.+ Written by Ian Lance Taylor, Google.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are+met:++ (1) Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ (2) Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in+ the documentation and/or other materials provided with the+ distribution.++ (3) The name of the author may not be used to+ endorse or promote products derived from this software without+ specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. */++#include "config.h"++#include <errno.h>+#include <sys/types.h>+#include <sys/mman.h>+#include <unistd.h>++#include "backtrace.hpp"+#include "internal.hpp"++#ifndef HAVE_DECL_GETPAGESIZE+extern int getpagesize (void);+#endif++#ifndef MAP_FAILED+#define MAP_FAILED ((void *)-1)+#endif++namespace tracy+{++/* This file implements file views and memory allocation when mmap is+ available. */++/* Create a view of SIZE bytes from DESCRIPTOR at OFFSET. */++int+backtrace_get_view (struct backtrace_state *state ATTRIBUTE_UNUSED,+ int descriptor, off_t offset, uint64_t size,+ backtrace_error_callback error_callback,+ void *data, struct backtrace_view *view)+{+ size_t pagesize;+ unsigned int inpage;+ off_t pageoff;+ void *map;++ if ((uint64_t) (size_t) size != size)+ {+ error_callback (data, "file size too large", 0);+ return 0;+ }++ pagesize = getpagesize ();+ inpage = offset % pagesize;+ pageoff = offset - inpage;++ size += inpage;+ size = (size + (pagesize - 1)) & ~ (pagesize - 1);++ map = mmap (NULL, size, PROT_READ, MAP_PRIVATE, descriptor, pageoff);+ if (map == MAP_FAILED)+ {+ error_callback (data, "mmap", errno);+ return 0;+ }++ view->data = (char *) map + inpage;+ view->base = map;+ view->len = size;++ return 1;+}++/* Release a view read by backtrace_get_view. */++void+backtrace_release_view (struct backtrace_state *state ATTRIBUTE_UNUSED,+ struct backtrace_view *view,+ backtrace_error_callback error_callback,+ void *data)+{+ union {+ const void *cv;+ void *v;+ } cc;++ cc.cv = view->base;+ if (munmap (cc.v, view->len) < 0)+ error_callback (data, "munmap", errno);+}++}
+ cbits/tracy/public/libbacktrace/posix.cpp view
@@ -0,0 +1,109 @@+/* posix.c -- POSIX file I/O routines for the backtrace library.+ Copyright (C) 2012-2021 Free Software Foundation, Inc.+ Written by Ian Lance Taylor, Google.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are+met:++ (1) Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ (2) Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in+ the documentation and/or other materials provided with the+ distribution.++ (3) The name of the author may not be used to+ endorse or promote products derived from this software without+ specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. */++#include "config.h"++#include <errno.h>+#include <sys/types.h>+#include <sys/stat.h>+#include <fcntl.h>+#include <unistd.h>++#include "backtrace.hpp"+#include "internal.hpp"++#ifndef O_BINARY+#define O_BINARY 0+#endif++#ifndef O_CLOEXEC+#define O_CLOEXEC 0+#endif++#ifndef FD_CLOEXEC+#define FD_CLOEXEC 1+#endif++namespace tracy+{++/* Open a file for reading. */++int+backtrace_open (const char *filename, backtrace_error_callback error_callback,+ void *data, int *does_not_exist)+{+ int descriptor;++ if (does_not_exist != NULL)+ *does_not_exist = 0;++ descriptor = open (filename, (int) (O_RDONLY | O_BINARY | O_CLOEXEC));+ if (descriptor < 0)+ {+ /* If DOES_NOT_EXIST is not NULL, then don't call ERROR_CALLBACK+ if the file does not exist. We treat lacking permission to+ open the file as the file not existing; this case arises when+ running the libgo syscall package tests as root. */+ if (does_not_exist != NULL && (errno == ENOENT || errno == EACCES))+ *does_not_exist = 1;+ else+ error_callback (data, filename, errno);+ return -1;+ }++#ifdef HAVE_FCNTL+ /* Set FD_CLOEXEC just in case the kernel does not support+ O_CLOEXEC. It doesn't matter if this fails for some reason.+ FIXME: At some point it should be safe to only do this if+ O_CLOEXEC == 0. */+ fcntl (descriptor, F_SETFD, FD_CLOEXEC);+#endif++ return descriptor;+}++/* Close DESCRIPTOR. */++int+backtrace_close (int descriptor, backtrace_error_callback error_callback,+ void *data)+{+ if (close (descriptor) < 0)+ {+ error_callback (data, "close", errno);+ return 0;+ }+ return 1;+}++}
+ cbits/tracy/public/libbacktrace/sort.cpp view
@@ -0,0 +1,113 @@+/* sort.c -- Sort without allocating memory+ Copyright (C) 2012-2021 Free Software Foundation, Inc.+ Written by Ian Lance Taylor, Google.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are+met:++ (1) Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ (2) Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in+ the documentation and/or other materials provided with the+ distribution.++ (3) The name of the author may not be used to+ endorse or promote products derived from this software without+ specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. */++#include "config.h"++#include <stddef.h>+#include <sys/types.h>++#include "backtrace.hpp"+#include "internal.hpp"++namespace tracy+{++/* The GNU glibc version of qsort allocates memory, which we must not+ do if we are invoked by a signal handler. So provide our own+ sort. */++static void+swap (char *a, char *b, size_t size)+{+ size_t i;++ for (i = 0; i < size; i++, a++, b++)+ {+ char t;++ t = *a;+ *a = *b;+ *b = t;+ }+}++void+backtrace_qsort (void *basearg, size_t count, size_t size,+ int (*compar) (const void *, const void *))+{+ char *base = (char *) basearg;+ size_t i;+ size_t mid;++ tail_recurse:+ if (count < 2)+ return;++ /* The symbol table and DWARF tables, which is all we use this+ routine for, tend to be roughly sorted. Pick the middle element+ in the array as our pivot point, so that we are more likely to+ cut the array in half for each recursion step. */+ swap (base, base + (count / 2) * size, size);++ mid = 0;+ for (i = 1; i < count; i++)+ {+ if ((*compar) (base, base + i * size) > 0)+ {+ ++mid;+ if (i != mid)+ swap (base + mid * size, base + i * size, size);+ }+ }++ if (mid > 0)+ swap (base, base + mid * size, size);++ /* Recurse with the smaller array, loop with the larger one. That+ ensures that our maximum stack depth is log count. */+ if (2 * mid < count)+ {+ backtrace_qsort (base, mid, size, compar);+ base += (mid + 1) * size;+ count -= mid + 1;+ goto tail_recurse;+ }+ else+ {+ backtrace_qsort (base + (mid + 1) * size, count - (mid + 1),+ size, compar);+ count = mid;+ goto tail_recurse;+ }+}++}
+ cbits/tracy/public/libbacktrace/state.cpp view
@@ -0,0 +1,76 @@+/* state.c -- Create the backtrace state.+ Copyright (C) 2012-2021 Free Software Foundation, Inc.+ Written by Ian Lance Taylor, Google.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are+met:++ (1) Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ (2) Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in+ the documentation and/or other materials provided with the+ distribution.++ (3) The name of the author may not be used to+ endorse or promote products derived from this software without+ specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. */++#include "config.h"++#include <string.h>+#include <sys/types.h>++#include "backtrace.hpp"+#include "internal.hpp"++namespace tracy+{++/* Create the backtrace state. This will then be passed to all the+ other routines. */++struct backtrace_state *+backtrace_create_state (const char *filename, int threaded,+ backtrace_error_callback error_callback,+ void *data)+{+ struct backtrace_state init_state;+ struct backtrace_state *state;++#ifndef HAVE_SYNC_FUNCTIONS+ if (threaded)+ {+ error_callback (data, "backtrace library does not support threads", 0);+ return NULL;+ }+#endif++ memset (&init_state, 0, sizeof init_state);+ init_state.filename = filename;+ init_state.threaded = threaded;++ state = ((struct backtrace_state *)+ backtrace_alloc (&init_state, sizeof *state, error_callback, data));+ if (state == NULL)+ return NULL;+ *state = init_state;++ return state;+}++}
+ cbits/tracy/public/tracy/Tracy.hpp view
@@ -0,0 +1,254 @@+#ifndef __TRACY_HPP__+#define __TRACY_HPP__++#include "../common/TracyColor.hpp"+#include "../common/TracySystem.hpp"++#ifndef TracyFunction+# define TracyFunction __FUNCTION__+#endif++#ifndef TracyFile+# define TracyFile __FILE__+#endif++#ifndef TracyLine+# define TracyLine TracyConcat(__LINE__,U) // MSVC Edit and continue __LINE__ is non-constant. See https://developercommunity.visualstudio.com/t/-line-cannot-be-used-as-an-argument-for-constexpr/195665+#endif++#ifndef TRACY_ENABLE++#define TracyNoop++#define ZoneNamed(x,y)+#define ZoneNamedN(x,y,z)+#define ZoneNamedC(x,y,z)+#define ZoneNamedNC(x,y,z,w)++#define ZoneTransient(x,y)+#define ZoneTransientN(x,y,z)++#define ZoneScoped+#define ZoneScopedN(x)+#define ZoneScopedC(x)+#define ZoneScopedNC(x,y)++#define ZoneText(x,y)+#define ZoneTextV(x,y,z)+#define ZoneTextF(x,...)+#define ZoneTextVF(x,y,...)+#define ZoneName(x,y)+#define ZoneNameV(x,y,z)+#define ZoneNameF(x,...)+#define ZoneNameVF(x,y,...)+#define ZoneColor(x)+#define ZoneColorV(x,y)+#define ZoneValue(x)+#define ZoneValueV(x,y)+#define ZoneIsActive false+#define ZoneIsActiveV(x) false++#define FrameMark+#define FrameMarkNamed(x)+#define FrameMarkStart(x)+#define FrameMarkEnd(x)++#define FrameImage(x,y,z,w,a)++#define TracyLockable( type, varname ) type varname+#define TracyLockableN( type, varname, desc ) type varname+#define TracySharedLockable( type, varname ) type varname+#define TracySharedLockableN( type, varname, desc ) type varname+#define LockableBase( type ) type+#define SharedLockableBase( type ) type+#define LockMark(x) (void)x+#define LockableName(x,y,z)++#define TracyPlot(x,y)+#define TracyPlotConfig(x,y,z,w,a)++#define TracyMessage(x,y)+#define TracyMessageL(x)+#define TracyMessageC(x,y,z)+#define TracyMessageLC(x,y)+#define TracyAppInfo(x,y)++#define TracyAlloc(x,y)+#define TracyFree(x)+#define TracyMemoryDiscard(x)+#define TracySecureAlloc(x,y)+#define TracySecureFree(x)+#define TracySecureMemoryDiscard(x)++#define TracyAllocN(x,y,z)+#define TracyFreeN(x,y)+#define TracySecureAllocN(x,y,z)+#define TracySecureFreeN(x,y)++#define ZoneNamedS(x,y,z)+#define ZoneNamedNS(x,y,z,w)+#define ZoneNamedCS(x,y,z,w)+#define ZoneNamedNCS(x,y,z,w,a)++#define ZoneTransientS(x,y,z)+#define ZoneTransientNS(x,y,z,w)++#define ZoneScopedS(x)+#define ZoneScopedNS(x,y)+#define ZoneScopedCS(x,y)+#define ZoneScopedNCS(x,y,z)++#define TracyAllocS(x,y,z)+#define TracyFreeS(x,y)+#define TracyMemoryDiscardS(x,y)+#define TracySecureAllocS(x,y,z)+#define TracySecureFreeS(x,y)+#define TracySecureMemoryDiscardS(x,y)++#define TracyAllocNS(x,y,z,w)+#define TracyFreeNS(x,y,z)+#define TracySecureAllocNS(x,y,z,w)+#define TracySecureFreeNS(x,y,z)++#define TracyMessageS(x,y,z)+#define TracyMessageLS(x,y)+#define TracyMessageCS(x,y,z,w)+#define TracyMessageLCS(x,y,z)++#define TracySourceCallbackRegister(x,y)+#define TracyParameterRegister(x,y)+#define TracyParameterSetup(x,y,z,w)+#define TracyIsConnected false+#define TracyIsStarted false+#define TracySetProgramName(x)++#define TracyFiberEnter(x)+#define TracyFiberEnterHint(x,y)+#define TracyFiberLeave++#else++#include <string.h>++#include "../client/TracyLock.hpp"+#include "../client/TracyProfiler.hpp"+#include "../client/TracyScoped.hpp"++#ifndef TRACY_CALLSTACK+#define TRACY_CALLSTACK 0+#endif++#define TracyNoop tracy::ProfilerAvailable()++#define ZoneNamed( varname, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_source_location,TracyLine) { nullptr, TracyFunction, TracyFile, (uint32_t)TracyLine, 0 }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,TracyLine), TRACY_CALLSTACK, active )+#define ZoneNamedN( varname, name, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, 0 }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,TracyLine), TRACY_CALLSTACK, active )+#define ZoneNamedC( varname, color, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_source_location,TracyLine) { nullptr, TracyFunction, TracyFile, (uint32_t)TracyLine, color }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,TracyLine), TRACY_CALLSTACK, active )+#define ZoneNamedNC( varname, name, color, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, color }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,TracyLine), TRACY_CALLSTACK, active )++#define ZoneTransient( varname, active ) tracy::ScopedZone varname( TracyLine, TracyFile, strlen( TracyFile ), TracyFunction, strlen( TracyFunction ), nullptr, 0, TRACY_CALLSTACK, active )+#define ZoneTransientN( varname, name, active ) tracy::ScopedZone varname( TracyLine, TracyFile, strlen( TracyFile ), TracyFunction, strlen( TracyFunction ), name, strlen( name ), TRACY_CALLSTACK, active )+#define ZoneTransientNC( varname, name, color, active ) tracy::ScopedZone varname( TracyLine, TracyFile, strlen( TracyFile ), TracyFunction, strlen( TracyFunction ), name, strlen( name ), color, TRACY_CALLSTACK, active )++#define ZoneScoped ZoneNamed( ___tracy_scoped_zone, true )+#define ZoneScopedN( name ) ZoneNamedN( ___tracy_scoped_zone, name, true )+#define ZoneScopedC( color ) ZoneNamedC( ___tracy_scoped_zone, color, true )+#define ZoneScopedNC( name, color ) ZoneNamedNC( ___tracy_scoped_zone, name, color, true )++#define ZoneText( txt, size ) ___tracy_scoped_zone.Text( txt, size )+#define ZoneTextV( varname, txt, size ) varname.Text( txt, size )+#define ZoneTextF( fmt, ... ) ___tracy_scoped_zone.TextFmt( fmt, ##__VA_ARGS__ )+#define ZoneTextVF( varname, fmt, ... ) varname.TextFmt( fmt, ##__VA_ARGS__ )+#define ZoneName( txt, size ) ___tracy_scoped_zone.Name( txt, size )+#define ZoneNameV( varname, txt, size ) varname.Name( txt, size )+#define ZoneNameF( fmt, ... ) ___tracy_scoped_zone.NameFmt( fmt, ##__VA_ARGS__ )+#define ZoneNameVF( varname, fmt, ... ) varname.NameFmt( fmt, ##__VA_ARGS__ )+#define ZoneColor( color ) ___tracy_scoped_zone.Color( color )+#define ZoneColorV( varname, color ) varname.Color( color )+#define ZoneValue( value ) ___tracy_scoped_zone.Value( value )+#define ZoneValueV( varname, value ) varname.Value( value )+#define ZoneIsActive ___tracy_scoped_zone.IsActive()+#define ZoneIsActiveV( varname ) varname.IsActive()++#define FrameMark tracy::Profiler::SendFrameMark( nullptr )+#define FrameMarkNamed( name ) tracy::Profiler::SendFrameMark( name )+#define FrameMarkStart( name ) tracy::Profiler::SendFrameMark( name, tracy::QueueType::FrameMarkMsgStart )+#define FrameMarkEnd( name ) tracy::Profiler::SendFrameMark( name, tracy::QueueType::FrameMarkMsgEnd )++#define FrameImage( image, width, height, offset, flip ) tracy::Profiler::SendFrameImage( image, width, height, offset, flip )++#define TracyLockable( type, varname ) tracy::Lockable<type> varname { [] () -> const tracy::SourceLocationData* { static constexpr tracy::SourceLocationData srcloc { nullptr, #type " " #varname, TracyFile, TracyLine, 0 }; return &srcloc; }() }+#define TracyLockableN( type, varname, desc ) tracy::Lockable<type> varname { [] () -> const tracy::SourceLocationData* { static constexpr tracy::SourceLocationData srcloc { nullptr, desc, TracyFile, TracyLine, 0 }; return &srcloc; }() }+#define TracySharedLockable( type, varname ) tracy::SharedLockable<type> varname { [] () -> const tracy::SourceLocationData* { static constexpr tracy::SourceLocationData srcloc { nullptr, #type " " #varname, TracyFile, TracyLine, 0 }; return &srcloc; }() }+#define TracySharedLockableN( type, varname, desc ) tracy::SharedLockable<type> varname { [] () -> const tracy::SourceLocationData* { static constexpr tracy::SourceLocationData srcloc { nullptr, desc, TracyFile, TracyLine, 0 }; return &srcloc; }() }+#define LockableBase( type ) tracy::Lockable<type>+#define SharedLockableBase( type ) tracy::SharedLockable<type>+#define LockMark( varname ) static constexpr tracy::SourceLocationData __tracy_lock_location_##__LINE__ { nullptr, TracyFunction, TracyFile, (uint32_t)TracyLine, 0 }; varname.Mark( &__tracy_lock_location_##__LINE__ )+#define LockableName( varname, txt, size ) varname.CustomName( txt, size )++#define TracyPlot( name, val ) tracy::Profiler::PlotData( name, val )+#define TracyPlotConfig( name, type, step, fill, color ) tracy::Profiler::ConfigurePlot( name, type, step, fill, color )++#define TracyAppInfo( txt, size ) tracy::Profiler::MessageAppInfo( txt, size )++#define TracyMessage( txt, size ) tracy::Profiler::Message( txt, size, TRACY_CALLSTACK )+#define TracyMessageL( txt ) tracy::Profiler::Message( txt, TRACY_CALLSTACK )+#define TracyMessageC( txt, size, color ) tracy::Profiler::MessageColor( txt, size, color, TRACY_CALLSTACK )+#define TracyMessageLC( txt, color ) tracy::Profiler::MessageColor( txt, color, TRACY_CALLSTACK )++#define TracyAlloc( ptr, size ) tracy::Profiler::MemAllocCallstack( ptr, size, TRACY_CALLSTACK, false )+#define TracyFree( ptr ) tracy::Profiler::MemFreeCallstack( ptr, TRACY_CALLSTACK, false )+#define TracySecureAlloc( ptr, size ) tracy::Profiler::MemAllocCallstack( ptr, size, TRACY_CALLSTACK, true )+#define TracySecureFree( ptr ) tracy::Profiler::MemFreeCallstack( ptr, TRACY_CALLSTACK, true )++#define TracyAllocN( ptr, size, name ) tracy::Profiler::MemAllocCallstackNamed( ptr, size, TRACY_CALLSTACK, false, name )+#define TracyFreeN( ptr, name ) tracy::Profiler::MemFreeCallstackNamed( ptr, TRACY_CALLSTACK, false, name )+#define TracyMemoryDiscard( name ) tracy::Profiler::MemDiscardCallstack( name, false, TRACY_CALLSTACK )+#define TracySecureAllocN( ptr, size, name ) tracy::Profiler::MemAllocCallstackNamed( ptr, size, TRACY_CALLSTACK, true, name )+#define TracySecureFreeN( ptr, name ) tracy::Profiler::MemFreeCallstackNamed( ptr, TRACY_CALLSTACK, true, name )+#define TracySecureMemoryDiscard( name ) tracy::Profiler::MemDiscardCallstack( name, true, TRACY_CALLSTACK )++#define ZoneNamedS( varname, depth, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_source_location,TracyLine) { nullptr, TracyFunction, TracyFile, (uint32_t)TracyLine, 0 }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,TracyLine), depth, active )+#define ZoneNamedNS( varname, name, depth, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, 0 }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,TracyLine), depth, active )+#define ZoneNamedCS( varname, color, depth, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_source_location,TracyLine) { nullptr, TracyFunction, TracyFile, (uint32_t)TracyLine, color }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,TracyLine), depth, active )+#define ZoneNamedNCS( varname, name, color, depth, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, color }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,TracyLine), depth, active )++#define ZoneTransientS( varname, depth, active ) tracy::ScopedZone varname( TracyLine, TracyFile, strlen( TracyFile ), TracyFunction, strlen( TracyFunction ), nullptr, 0, depth, active )+#define ZoneTransientNS( varname, name, depth, active ) tracy::ScopedZone varname( TracyLine, TracyFile, strlen( TracyFile ), TracyFunction, strlen( TracyFunction ), name, strlen( name ), depth, active )++#define ZoneScopedS( depth ) ZoneNamedS( ___tracy_scoped_zone, depth, true )+#define ZoneScopedNS( name, depth ) ZoneNamedNS( ___tracy_scoped_zone, name, depth, true )+#define ZoneScopedCS( color, depth ) ZoneNamedCS( ___tracy_scoped_zone, color, depth, true )+#define ZoneScopedNCS( name, color, depth ) ZoneNamedNCS( ___tracy_scoped_zone, name, color, depth, true )++#define TracyAllocS( ptr, size, depth ) tracy::Profiler::MemAllocCallstack( ptr, size, depth, false )+#define TracyFreeS( ptr, depth ) tracy::Profiler::MemFreeCallstack( ptr, depth, false )+#define TracySecureAllocS( ptr, size, depth ) tracy::Profiler::MemAllocCallstack( ptr, size, depth, true )+#define TracySecureFreeS( ptr, depth ) tracy::Profiler::MemFreeCallstack( ptr, depth, true )++#define TracyAllocNS( ptr, size, depth, name ) tracy::Profiler::MemAllocCallstackNamed( ptr, size, depth, false, name )+#define TracyFreeNS( ptr, depth, name ) tracy::Profiler::MemFreeCallstackNamed( ptr, depth, false, name )+#define TracyMemoryDiscardS( name, depth ) tracy::Profiler::MemDiscardCallstack( name, false, depth )+#define TracySecureAllocNS( ptr, size, depth, name ) tracy::Profiler::MemAllocCallstackNamed( ptr, size, depth, true, name )+#define TracySecureFreeNS( ptr, depth, name ) tracy::Profiler::MemFreeCallstackNamed( ptr, depth, true, name )+#define TracySecureMemoryDiscardS( name, depth ) tracy::Profiler::MemDiscardCallstack( name, true, depth )++#define TracyMessageS( txt, size, depth ) tracy::Profiler::Message( txt, size, depth )+#define TracyMessageLS( txt, depth ) tracy::Profiler::Message( txt, depth )+#define TracyMessageCS( txt, size, color, depth ) tracy::Profiler::MessageColor( txt, size, color, depth )+#define TracyMessageLCS( txt, color, depth ) tracy::Profiler::MessageColor( txt, color, depth )++#define TracySourceCallbackRegister( cb, data ) tracy::Profiler::SourceCallbackRegister( cb, data )+#define TracyParameterRegister( cb, data ) tracy::Profiler::ParameterRegister( cb, data )+#define TracyParameterSetup( idx, name, isBool, val ) tracy::Profiler::ParameterSetup( idx, name, isBool, val )+#define TracyIsConnected tracy::GetProfiler().IsConnected()+#define TracySetProgramName( name ) tracy::GetProfiler().SetProgramName( name );++#ifdef TRACY_FIBERS+# define TracyFiberEnter( fiber ) tracy::Profiler::EnterFiber( fiber, 0 )+# define TracyFiberEnterHint( fiber, groupHint ) tracy::Profiler::EnterFiber( fiber, groupHint )+# define TracyFiberLeave tracy::Profiler::LeaveFiber()+#endif++#endif++#endif
+ cbits/tracy/public/tracy/TracyC.h view
@@ -0,0 +1,384 @@+#ifndef __TRACYC_HPP__+#define __TRACYC_HPP__++#include <stddef.h>+#include <stdint.h>++#include "../common/TracyApi.h"++#ifdef __cplusplus+extern "C" {+#endif++enum TracyPlotFormatEnum+{+ TracyPlotFormatNumber,+ TracyPlotFormatMemory,+ TracyPlotFormatPercentage,+ TracyPlotFormatWatt+};++TRACY_API void ___tracy_set_thread_name( const char* name );++#define TracyCSetThreadName( name ) ___tracy_set_thread_name( name );++#ifndef TracyFunction+# define TracyFunction __FUNCTION__+#endif++#ifndef TracyFile+# define TracyFile __FILE__+#endif++#ifndef TracyLine+# define TracyLine __LINE__+#endif++#ifndef TRACY_ENABLE++typedef const void* TracyCZoneCtx;++typedef const void* TracyCLockCtx;++#define TracyCZone(c,x)+#define TracyCZoneN(c,x,y)+#define TracyCZoneC(c,x,y)+#define TracyCZoneNC(c,x,y,z)+#define TracyCZoneEnd(c)+#define TracyCZoneText(c,x,y)+#define TracyCZoneName(c,x,y)+#define TracyCZoneColor(c,x)+#define TracyCZoneValue(c,x)++#define TracyCAlloc(x,y)+#define TracyCFree(x)+#define TracyCMemoryDiscard(x)+#define TracyCSecureAlloc(x,y)+#define TracyCSecureFree(x)+#define TracyCSecureMemoryDiscard(x)++#define TracyCAllocN(x,y,z)+#define TracyCFreeN(x,y)+#define TracyCSecureAllocN(x,y,z)+#define TracyCSecureFreeN(x,y)++#define TracyCFrameMark+#define TracyCFrameMarkNamed(x)+#define TracyCFrameMarkStart(x)+#define TracyCFrameMarkEnd(x)+#define TracyCFrameImage(x,y,z,w,a)++#define TracyCPlot(x,y)+#define TracyCPlotF(x,y)+#define TracyCPlotI(x,y)+#define TracyCPlotConfig(x,y,z,w,a)++#define TracyCMessage(x,y)+#define TracyCMessageL(x)+#define TracyCMessageC(x,y,z)+#define TracyCMessageLC(x,y)+#define TracyCAppInfo(x,y)++#define TracyCZoneS(x,y,z)+#define TracyCZoneNS(x,y,z,w)+#define TracyCZoneCS(x,y,z,w)+#define TracyCZoneNCS(x,y,z,w,a)++#define TracyCAllocS(x,y,z)+#define TracyCFreeS(x,y)+#define TracyCMemoryDiscardS(x,y)+#define TracyCSecureAllocS(x,y,z)+#define TracyCSecureFreeS(x,y)+#define TracyCSecureMemoryDiscardS(x,y)++#define TracyCAllocNS(x,y,z,w)+#define TracyCFreeNS(x,y,z)+#define TracyCSecureAllocNS(x,y,z,w)+#define TracyCSecureFreeNS(x,y,z)++#define TracyCMessageS(x,y,z)+#define TracyCMessageLS(x,y)+#define TracyCMessageCS(x,y,z,w)+#define TracyCMessageLCS(x,y,z)++#define TracyCLockCtx(l)+#define TracyCLockAnnounce(l)+#define TracyCLockTerminate(l)+#define TracyCLockBeforeLock(l)+#define TracyCLockAfterLock(l)+#define TracyCLockAfterUnlock(l)+#define TracyCLockAfterTryLock(l,x)+#define TracyCLockMark(l)+#define TracyCLockCustomName(l,x,y)++#define TracyCIsConnected 0+#define TracyCIsStarted 0++#ifdef TRACY_FIBERS+# define TracyCFiberEnter(fiber)+# define TracyCFiberLeave+#endif++#else++#ifndef TracyConcat+# define TracyConcat(x,y) TracyConcatIndirect(x,y)+#endif+#ifndef TracyConcatIndirect+# define TracyConcatIndirect(x,y) x##y+#endif++struct ___tracy_source_location_data+{+ const char* name;+ const char* function;+ const char* file;+ uint32_t line;+ uint32_t color;+};++struct ___tracy_c_zone_context+{+ uint32_t id;+ int32_t active;+};++struct ___tracy_gpu_time_data+{+ int64_t gpuTime;+ uint16_t queryId;+ uint8_t context;+};++struct ___tracy_gpu_zone_begin_data {+ uint64_t srcloc;+ uint16_t queryId;+ uint8_t context;+};++struct ___tracy_gpu_zone_begin_callstack_data {+ uint64_t srcloc;+ int32_t depth;+ uint16_t queryId;+ uint8_t context;+};++struct ___tracy_gpu_zone_end_data {+ uint16_t queryId;+ uint8_t context;+};++struct ___tracy_gpu_new_context_data {+ int64_t gpuTime;+ float period;+ uint8_t context;+ uint8_t flags;+ uint8_t type;+};++struct ___tracy_gpu_context_name_data {+ uint8_t context;+ const char* name;+ uint16_t len;+};++struct ___tracy_gpu_calibration_data {+ int64_t gpuTime;+ int64_t cpuDelta;+ uint8_t context;+};++struct ___tracy_gpu_time_sync_data {+ int64_t gpuTime;+ uint8_t context;+};++struct __tracy_lockable_context_data;++// Some containers don't support storing const types.+// This struct, as visible to user, is immutable, so treat it as if const was declared here.+typedef /*const*/ struct ___tracy_c_zone_context TracyCZoneCtx;++typedef struct __tracy_lockable_context_data* TracyCLockCtx;++#ifdef TRACY_MANUAL_LIFETIME+TRACY_API void ___tracy_startup_profiler(void);+TRACY_API void ___tracy_shutdown_profiler(void);+TRACY_API int32_t ___tracy_profiler_started(void);++# define TracyCIsStarted ___tracy_profiler_started()+#else+# define TracyCIsStarted 1+#endif++TRACY_API uint64_t ___tracy_alloc_srcloc( uint32_t line, const char* source, size_t sourceSz, const char* function, size_t functionSz, uint32_t color );+TRACY_API uint64_t ___tracy_alloc_srcloc_name( uint32_t line, const char* source, size_t sourceSz, const char* function, size_t functionSz, const char* name, size_t nameSz, uint32_t color );++TRACY_API TracyCZoneCtx ___tracy_emit_zone_begin( const struct ___tracy_source_location_data* srcloc, int32_t active );+TRACY_API TracyCZoneCtx ___tracy_emit_zone_begin_callstack( const struct ___tracy_source_location_data* srcloc, int32_t depth, int32_t active );+TRACY_API TracyCZoneCtx ___tracy_emit_zone_begin_alloc( uint64_t srcloc, int32_t active );+TRACY_API TracyCZoneCtx ___tracy_emit_zone_begin_alloc_callstack( uint64_t srcloc, int32_t depth, int32_t active );+TRACY_API void ___tracy_emit_zone_end( TracyCZoneCtx ctx );+TRACY_API void ___tracy_emit_zone_text( TracyCZoneCtx ctx, const char* txt, size_t size );+TRACY_API void ___tracy_emit_zone_name( TracyCZoneCtx ctx, const char* txt, size_t size );+TRACY_API void ___tracy_emit_zone_color( TracyCZoneCtx ctx, uint32_t color );+TRACY_API void ___tracy_emit_zone_value( TracyCZoneCtx ctx, uint64_t value );++TRACY_API void ___tracy_emit_gpu_zone_begin( const struct ___tracy_gpu_zone_begin_data );+TRACY_API void ___tracy_emit_gpu_zone_begin_callstack( const struct ___tracy_gpu_zone_begin_callstack_data );+TRACY_API void ___tracy_emit_gpu_zone_begin_alloc( const struct ___tracy_gpu_zone_begin_data );+TRACY_API void ___tracy_emit_gpu_zone_begin_alloc_callstack( const struct ___tracy_gpu_zone_begin_callstack_data );+TRACY_API void ___tracy_emit_gpu_zone_end( const struct ___tracy_gpu_zone_end_data data );+TRACY_API void ___tracy_emit_gpu_time( const struct ___tracy_gpu_time_data );+TRACY_API void ___tracy_emit_gpu_new_context( const struct ___tracy_gpu_new_context_data );+TRACY_API void ___tracy_emit_gpu_context_name( const struct ___tracy_gpu_context_name_data );+TRACY_API void ___tracy_emit_gpu_calibration( const struct ___tracy_gpu_calibration_data );+TRACY_API void ___tracy_emit_gpu_time_sync( const struct ___tracy_gpu_time_sync_data );++TRACY_API void ___tracy_emit_gpu_zone_begin_serial( const struct ___tracy_gpu_zone_begin_data );+TRACY_API void ___tracy_emit_gpu_zone_begin_callstack_serial( const struct ___tracy_gpu_zone_begin_callstack_data );+TRACY_API void ___tracy_emit_gpu_zone_begin_alloc_serial( const struct ___tracy_gpu_zone_begin_data );+TRACY_API void ___tracy_emit_gpu_zone_begin_alloc_callstack_serial( const struct ___tracy_gpu_zone_begin_callstack_data );+TRACY_API void ___tracy_emit_gpu_zone_end_serial( const struct ___tracy_gpu_zone_end_data data );+TRACY_API void ___tracy_emit_gpu_time_serial( const struct ___tracy_gpu_time_data );+TRACY_API void ___tracy_emit_gpu_new_context_serial( const struct ___tracy_gpu_new_context_data );+TRACY_API void ___tracy_emit_gpu_context_name_serial( const struct ___tracy_gpu_context_name_data );+TRACY_API void ___tracy_emit_gpu_calibration_serial( const struct ___tracy_gpu_calibration_data );+TRACY_API void ___tracy_emit_gpu_time_sync_serial( const struct ___tracy_gpu_time_sync_data );++TRACY_API int32_t ___tracy_connected(void);++#ifndef TRACY_CALLSTACK+#define TRACY_CALLSTACK 0+#endif++#define TracyCZone( ctx, active ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,TracyLine) = { NULL, __func__, TracyFile, (uint32_t)TracyLine, 0 }; TracyCZoneCtx ctx = ___tracy_emit_zone_begin_callstack( &TracyConcat(__tracy_source_location,TracyLine), TRACY_CALLSTACK, active );+#define TracyCZoneN( ctx, name, active ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,TracyLine) = { name, __func__, TracyFile, (uint32_t)TracyLine, 0 }; TracyCZoneCtx ctx = ___tracy_emit_zone_begin_callstack( &TracyConcat(__tracy_source_location,TracyLine), TRACY_CALLSTACK, active );+#define TracyCZoneC( ctx, color, active ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,TracyLine) = { NULL, __func__, TracyFile, (uint32_t)TracyLine, color }; TracyCZoneCtx ctx = ___tracy_emit_zone_begin_callstack( &TracyConcat(__tracy_source_location,TracyLine), TRACY_CALLSTACK, active );+#define TracyCZoneNC( ctx, name, color, active ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,TracyLine) = { name, __func__, TracyFile, (uint32_t)TracyLine, color }; TracyCZoneCtx ctx = ___tracy_emit_zone_begin_callstack( &TracyConcat(__tracy_source_location,TracyLine), TRACY_CALLSTACK, active );++#define TracyCZoneEnd( ctx ) ___tracy_emit_zone_end( ctx );++#define TracyCZoneText( ctx, txt, size ) ___tracy_emit_zone_text( ctx, txt, size );+#define TracyCZoneName( ctx, txt, size ) ___tracy_emit_zone_name( ctx, txt, size );+#define TracyCZoneColor( ctx, color ) ___tracy_emit_zone_color( ctx, color );+#define TracyCZoneValue( ctx, value ) ___tracy_emit_zone_value( ctx, value );+++TRACY_API void ___tracy_emit_memory_alloc( const void* ptr, size_t size, int32_t secure );+TRACY_API void ___tracy_emit_memory_alloc_callstack( const void* ptr, size_t size, int32_t depth, int32_t secure );+TRACY_API void ___tracy_emit_memory_free( const void* ptr, int32_t secure );+TRACY_API void ___tracy_emit_memory_free_callstack( const void* ptr, int32_t depth, int32_t secure );+TRACY_API void ___tracy_emit_memory_alloc_named( const void* ptr, size_t size, int32_t secure, const char* name );+TRACY_API void ___tracy_emit_memory_alloc_callstack_named( const void* ptr, size_t size, int32_t depth, int32_t secure, const char* name );+TRACY_API void ___tracy_emit_memory_free_named( const void* ptr, int32_t secure, const char* name );+TRACY_API void ___tracy_emit_memory_free_callstack_named( const void* ptr, int32_t depth, int32_t secure, const char* name );+TRACY_API void ___tracy_emit_memory_discard( const char* name, int32_t secure );+TRACY_API void ___tracy_emit_memory_discard_callstack( const char* name, int32_t secure, int32_t depth );++TRACY_API void ___tracy_emit_message( const char* txt, size_t size, int32_t callstack_depth );+TRACY_API void ___tracy_emit_messageL( const char* txt, int32_t callstack_depth );+TRACY_API void ___tracy_emit_messageC( const char* txt, size_t size, uint32_t color, int32_t callstack_depth );+TRACY_API void ___tracy_emit_messageLC( const char* txt, uint32_t color, int32_t callstack_depth );++#define TracyCAlloc( ptr, size ) ___tracy_emit_memory_alloc_callstack( ptr, size, TRACY_CALLSTACK, 0 )+#define TracyCFree( ptr ) ___tracy_emit_memory_free_callstack( ptr, TRACY_CALLSTACK, 0 )+#define TracyCMemoryDiscard( name ) ___tracy_emit_memory_discard_callstack( name, 0, TRACY_CALLSTACK );+#define TracyCSecureAlloc( ptr, size ) ___tracy_emit_memory_alloc_callstack( ptr, size, TRACY_CALLSTACK, 1 )+#define TracyCSecureFree( ptr ) ___tracy_emit_memory_free_callstack( ptr, TRACY_CALLSTACK, 1 )+#define TracyCSecureMemoryDiscard( name ) ___tracy_emit_memory_discard_callstack( name, 1, TRACY_CALLSTACK );++#define TracyCAllocN( ptr, size, name ) ___tracy_emit_memory_alloc_callstack_named( ptr, size, TRACY_CALLSTACK, 0, name )+#define TracyCFreeN( ptr, name ) ___tracy_emit_memory_free_callstack_named( ptr, TRACY_CALLSTACK, 0, name )+#define TracyCSecureAllocN( ptr, size, name ) ___tracy_emit_memory_alloc_callstack_named( ptr, size, TRACY_CALLSTACK, 1, name )+#define TracyCSecureFreeN( ptr, name ) ___tracy_emit_memory_free_callstack_named( ptr, TRACY_CALLSTACK, 1, name )++#define TracyCMessage( txt, size ) ___tracy_emit_message( txt, size, TRACY_CALLSTACK );+#define TracyCMessageL( txt ) ___tracy_emit_messageL( txt, TRACY_CALLSTACK );+#define TracyCMessageC( txt, size, color ) ___tracy_emit_messageC( txt, size, color, TRACY_CALLSTACK );+#define TracyCMessageLC( txt, color ) ___tracy_emit_messageLC( txt, color, TRACY_CALLSTACK );+++TRACY_API void ___tracy_emit_frame_mark( const char* name );+TRACY_API void ___tracy_emit_frame_mark_start( const char* name );+TRACY_API void ___tracy_emit_frame_mark_end( const char* name );+TRACY_API void ___tracy_emit_frame_image( const void* image, uint16_t w, uint16_t h, uint8_t offset, int32_t flip );++#define TracyCFrameMark ___tracy_emit_frame_mark( 0 );+#define TracyCFrameMarkNamed( name ) ___tracy_emit_frame_mark( name );+#define TracyCFrameMarkStart( name ) ___tracy_emit_frame_mark_start( name );+#define TracyCFrameMarkEnd( name ) ___tracy_emit_frame_mark_end( name );+#define TracyCFrameImage( image, width, height, offset, flip ) ___tracy_emit_frame_image( image, width, height, offset, flip );+++TRACY_API void ___tracy_emit_plot( const char* name, double val );+TRACY_API void ___tracy_emit_plot_float( const char* name, float val );+TRACY_API void ___tracy_emit_plot_int( const char* name, int64_t val );+TRACY_API void ___tracy_emit_plot_config( const char* name, int32_t type, int32_t step, int32_t fill, uint32_t color );+TRACY_API void ___tracy_emit_message_appinfo( const char* txt, size_t size );++#define TracyCPlot( name, val ) ___tracy_emit_plot( name, val );+#define TracyCPlotF( name, val ) ___tracy_emit_plot_float( name, val );+#define TracyCPlotI( name, val ) ___tracy_emit_plot_int( name, val );+#define TracyCPlotConfig( name, type, step, fill, color ) ___tracy_emit_plot_config( name, type, step, fill, color );+#define TracyCAppInfo( txt, size ) ___tracy_emit_message_appinfo( txt, size );+++#define TracyCZoneS( ctx, depth, active ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,TracyLine) = { NULL, __func__, TracyFile, (uint32_t)TracyLine, 0 }; TracyCZoneCtx ctx = ___tracy_emit_zone_begin_callstack( &TracyConcat(__tracy_source_location,TracyLine), depth, active );+#define TracyCZoneNS( ctx, name, depth, active ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,TracyLine) = { name, __func__, TracyFile, (uint32_t)TracyLine, 0 }; TracyCZoneCtx ctx = ___tracy_emit_zone_begin_callstack( &TracyConcat(__tracy_source_location,TracyLine), depth, active );+#define TracyCZoneCS( ctx, color, depth, active ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,TracyLine) = { NULL, __func__, TracyFile, (uint32_t)TracyLine, color }; TracyCZoneCtx ctx = ___tracy_emit_zone_begin_callstack( &TracyConcat(__tracy_source_location,TracyLine), depth, active );+#define TracyCZoneNCS( ctx, name, color, depth, active ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,TracyLine) = { name, __func__, TracyFile, (uint32_t)TracyLine, color }; TracyCZoneCtx ctx = ___tracy_emit_zone_begin_callstack( &TracyConcat(__tracy_source_location,TracyLine), depth, active );++#define TracyCAllocS( ptr, size, depth ) ___tracy_emit_memory_alloc_callstack( ptr, size, depth, 0 )+#define TracyCFreeS( ptr, depth ) ___tracy_emit_memory_free_callstack( ptr, depth, 0 )+#define TracyCMemoryDiscardS( name, depth ) ___tracy_emit_memory_discard_callstack( name, 0, depth )+#define TracyCSecureAllocS( ptr, size, depth ) ___tracy_emit_memory_alloc_callstack( ptr, size, depth, 1 )+#define TracyCSecureFreeS( ptr, depth ) ___tracy_emit_memory_free_callstack( ptr, depth, 1 )+#define TracyCSecureMemoryDiscardS( name, depth ) ___tracy_emit_memory_discard_callstack( name, 1, depth )++#define TracyCAllocNS( ptr, size, depth, name ) ___tracy_emit_memory_alloc_callstack_named( ptr, size, depth, 0, name )+#define TracyCFreeNS( ptr, depth, name ) ___tracy_emit_memory_free_callstack_named( ptr, depth, 0, name )+#define TracyCSecureAllocNS( ptr, size, depth, name ) ___tracy_emit_memory_alloc_callstack_named( ptr, size, depth, 1, name )+#define TracyCSecureFreeNS( ptr, depth, name ) ___tracy_emit_memory_free_callstack_named( ptr, depth, 1, name )++#define TracyCMessageS( txt, size, depth ) ___tracy_emit_message( txt, size, depth );+#define TracyCMessageLS( txt, depth ) ___tracy_emit_messageL( txt, depth );+#define TracyCMessageCS( txt, size, color, depth ) ___tracy_emit_messageC( txt, size, color, depth );+#define TracyCMessageLCS( txt, color, depth ) ___tracy_emit_messageLC( txt, color, depth );+++TRACY_API struct __tracy_lockable_context_data* ___tracy_announce_lockable_ctx( const struct ___tracy_source_location_data* srcloc );+TRACY_API void ___tracy_terminate_lockable_ctx( struct __tracy_lockable_context_data* lockdata );+TRACY_API int32_t ___tracy_before_lock_lockable_ctx( struct __tracy_lockable_context_data* lockdata );+TRACY_API void ___tracy_after_lock_lockable_ctx( struct __tracy_lockable_context_data* lockdata );+TRACY_API void ___tracy_after_unlock_lockable_ctx( struct __tracy_lockable_context_data* lockdata );+TRACY_API void ___tracy_after_try_lock_lockable_ctx( struct __tracy_lockable_context_data* lockdata, int32_t acquired );+TRACY_API void ___tracy_mark_lockable_ctx( struct __tracy_lockable_context_data* lockdata, const struct ___tracy_source_location_data* srcloc );+TRACY_API void ___tracy_custom_name_lockable_ctx( struct __tracy_lockable_context_data* lockdata, const char* name, size_t nameSz );++#define TracyCLockAnnounce( lock ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,TracyLine) = { NULL, __func__, TracyFile, (uint32_t)TracyLine, 0 }; lock = ___tracy_announce_lockable_ctx( &TracyConcat(__tracy_source_location,TracyLine) );+#define TracyCLockTerminate( lock ) ___tracy_terminate_lockable_ctx( lock );+#define TracyCLockBeforeLock( lock ) ___tracy_before_lock_lockable_ctx( lock );+#define TracyCLockAfterLock( lock ) ___tracy_after_lock_lockable_ctx( lock );+#define TracyCLockAfterUnlock( lock ) ___tracy_after_unlock_lockable_ctx( lock );+#define TracyCLockAfterTryLock( lock, acquired ) ___tracy_after_try_lock_lockable_ctx( lock, acquired );+#define TracyCLockMark( lock ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,TracyLine) = { NULL, __func__, TracyFile, (uint32_t)TracyLine, 0 }; ___tracy_mark_lockable_ctx( lock, &TracyConcat(__tracy_source_location,TracyLine) );+#define TracyCLockCustomName( lock, name, nameSz ) ___tracy_custom_name_lockable_ctx( lock, name, nameSz );++#define TracyCIsConnected ___tracy_connected()++#ifdef TRACY_FIBERS+TRACY_API void ___tracy_fiber_enter( const char* fiber );+TRACY_API void ___tracy_fiber_leave( void );++# define TracyCFiberEnter( fiber ) ___tracy_fiber_enter( fiber );+# define TracyCFiberLeave ___tracy_fiber_leave();+#endif++#endif++#ifdef __cplusplus+}+#endif++#endif
+ cbits/tracy/public/tracy/TracyCUDA.hpp view
@@ -0,0 +1,1325 @@+#ifndef __TRACYCUDA_HPP__+#define __TRACYCUDA_HPP__++#ifndef TRACY_ENABLE++#define TracyCUDAContext() nullptr+#define TracyCUDAContextDestroy(ctx)+#define TracyCUDAContextName(ctx, name, size)++#define TracyCUDAStartProfiling(ctx)+#define TracyCUDAStopProfiling(ctx)++#define TracyCUDACollect(ctx)++#else+#include <cupti.h>++#include <cassert>+#include <cmath>+#include <string>+#include <string_view>+#include <atomic>+#include <mutex>+#include <shared_mutex>+#include <condition_variable>+#include <vector>+#include <unordered_set>+#include <unordered_map>++#ifndef _MSC_VER+#include <cxxabi.h>+#endif++#include <tracy/Tracy.hpp>++#ifndef UNREFERENCED+#define UNREFERENCED(x) (void)x+#endif//UNREFERENCED++#ifndef TRACY_CUDA_CALIBRATED_CONTEXT+#define TRACY_CUDA_CALIBRATED_CONTEXT (1)+#endif//TRACY_CUDA_CALIBRATED_CONTEXT++#ifndef TRACY_CUDA_ENABLE_COLLECTOR_THREAD+#define TRACY_CUDA_ENABLE_COLLECTOR_THREAD (1)+#endif//TRACY_CUDA_ENABLE_COLLECTOR_THREAD++#ifndef TRACY_CUDA_ENABLE_CUDA_CALL_STATS+#define TRACY_CUDA_ENABLE_CUDA_CALL_STATS (0)+#endif//TRACY_CUDA_ENABLE_CUDA_CALL_STATS++namespace {++// TODO(marcos): wrap these in structs for better type safety+using CUptiTimestamp = uint64_t;+using TracyTimestamp = int64_t;++struct IncrementalRegression {+ using float_t = double;+ struct Parameters {+ float_t slope, intercept;+ };++ int n = 0;+ float_t x_mean = 0;+ float_t y_mean = 0;+ float_t x_svar = 0;+ float_t y_svar = 0;+ float_t xy_scov = 0;++ auto parameters() const {+ float_t slope = xy_scov / x_svar;+ float_t intercept = y_mean - slope * x_mean;+ return Parameters{ slope, intercept };+ }++ auto orthogonal() const {+ // NOTE(marcos): orthogonal regression is Deming regression with delta = 1+ float_t delta = float_t(1); // delta = 1 -> orthogonal regression+ float_t k = y_svar - delta * x_svar;+ float_t slope = (k + sqrt(k * k + 4 * delta * xy_scov * xy_scov)) / (2 * xy_scov);+ float_t intercept = y_mean - slope * x_mean;+ return Parameters{ slope, intercept };+ }++ void addSample(float_t x, float_t y) {+ ++n;+ float_t x_mean_prev = x_mean;+ float_t y_mean_prev = y_mean;+ x_mean += (x - x_mean) / n;+ y_mean += (y - y_mean) / n;+ x_svar += (x - x_mean_prev) * (x - x_mean);+ y_svar += (y - y_mean_prev) * (y - y_mean);+ xy_scov += (x - x_mean_prev) * (y - y_mean);+ }+};++tracy_force_inline TracyTimestamp tracyGetTimestamp() {+ return tracy::Profiler::GetTime();+}++auto& getCachedRegressionParameters() {+ // WARN(marcos): in theory, these linear regression parameters would be loaded/stored atomically;+ // in practice, however, it should not matter so long as the loads/stores are not "sliced"+ static IncrementalRegression::Parameters cached;+ return cached;+}++TracyTimestamp tracyFromCUpti(CUptiTimestamp cuptiTime) {+ // NOTE(marcos): linear regression estimate+ // y_hat = slope * x + intercept | X: CUptiTimestamp, Y: TracyTimestamp+ auto [slope, intercept] = getCachedRegressionParameters();+ double y_hat = slope * cuptiTime + intercept;+ TracyTimestamp tracyTime = TracyTimestamp(y_hat);+ assert(tracyTime >= 0);+ return tracyTime;+}++template<typename T, typename U>+tracy_force_inline void tracyMemWrite(T& where,U what) {+ static_assert(std::is_same_v<T, U>, "tracy::MemWrite: type mismatch.");+ tracy::MemWrite(&where, what);+}++void* tracyMalloc(size_t bytes) {+ return tracy::tracy_malloc(bytes);+}++void tracyFree(void* ptr) {+ tracy::tracy_free(ptr);+}++void tracyZoneBegin(TracyTimestamp time, tracy::SourceLocationData* srcLoc) {+ using namespace tracy;+ TracyQueuePrepare(QueueType::ZoneBegin);+ tracyMemWrite(item->zoneBegin.time, time);+ tracyMemWrite(item->zoneBegin.srcloc, (uint64_t)srcLoc);+ TracyQueueCommit(zoneBeginThread);+}++void tracyZoneEnd(TracyTimestamp time) {+ using namespace tracy;+ TracyQueuePrepare(QueueType::ZoneEnd);+ tracyMemWrite(item->zoneEnd.time, time);+ TracyQueueCommit(zoneEndThread);+}++void tracyPlot(const char* name, float value, TracyTimestamp time) {+ using namespace tracy;+ TracyLfqPrepare(QueueType::PlotDataFloat);+ tracyMemWrite(item->plotDataFloat.name, (uint64_t)name);+ tracyMemWrite(item->plotDataFloat.time, time);+ tracyMemWrite(item->plotDataFloat.val, value);+ TracyLfqCommit;+}++void tracyPlot(const char* name, float value, CUptiTimestamp time) {+ tracyPlot(name, value, tracyFromCUpti(time));+}++void tracyPlotActivity(const char* name, TracyTimestamp start, TracyTimestamp end, float value = 1.0f, float baseline = 0.0f) {+ tracyPlot(name, baseline, start);+ tracyPlot(name, value, start + 3);+ tracyPlot(name, value, end - 3);+ tracyPlot(name, baseline, end);+}++void tracyPlotActivity(const char* name, CUptiTimestamp start, CUptiTimestamp end, float value = 1.0f, float baseline = 0.0f) {+ tracyPlotActivity(name, tracyFromCUpti(start), tracyFromCUpti(end), value, baseline);+}++void tracyPlotBlip(const char* name, TracyTimestamp time, float value = 1.0f, float baseline = 0.0f) {+ tracyPlot(name, baseline, time - 3);+ tracyPlot(name, value, time);+ tracyPlot(name, baseline, time + 3);+}++void tracyPlotBlip(const char* name, CUptiTimestamp time, float value = 1.0f, float baseline = 0.0f) {+ tracyPlotBlip(name, tracyFromCUpti(time), value, baseline);+}++void tracyEmitMemAlloc(const char* name, const void* ptr, size_t size, TracyTimestamp time) {+ using namespace tracy;+ const auto thread = GetThreadHandle();++ auto item = Profiler::QueueSerial();+ tracyMemWrite(item->hdr.type, QueueType::MemNamePayload);+ tracyMemWrite(item->memName.name, (uint64_t)name);+ Profiler::QueueSerialFinish();++ item = Profiler::QueueSerial();+ tracyMemWrite(item->hdr.type, QueueType::MemAllocNamed);+ tracyMemWrite(item->memAlloc.time, time);+ tracyMemWrite(item->memAlloc.thread, thread);+ tracyMemWrite(item->memAlloc.ptr, (uint64_t)ptr);++ if (compile_time_condition<sizeof(size) == 4>::value)+ {+ memcpy(&item->memAlloc.size, &size, 4);+ memset(&item->memAlloc.size + 4, 0, 2);+ }+ else+ {+ assert(sizeof(size) == 8);+ memcpy(&item->memAlloc.size, &size, 4);+ memcpy(((char *)&item->memAlloc.size) + 4, ((char *)&size) + 4, 2);+ }+ Profiler::QueueSerialFinish();+}++void tracyEmitMemFree(const char* name, const void* ptr, TracyTimestamp time) {+ using namespace tracy;+ const auto thread = GetThreadHandle();++ auto item = Profiler::QueueSerial();+ tracyMemWrite(item->hdr.type, QueueType::MemNamePayload);+ tracyMemWrite(item->memName.name, (uint64_t)name);+ Profiler::QueueSerialFinish();++ item = Profiler::QueueSerial();+ tracyMemWrite(item->hdr.type, QueueType::MemFreeNamed);+ tracyMemWrite(item->memFree.time, time);+ tracyMemWrite(item->memFree.thread, thread);+ tracyMemWrite(item->memFree.ptr, (uint64_t)ptr);+ Profiler::QueueSerialFinish();+}++void tracyEmitMemAlloc(const char* name, const void* ptr, size_t size, CUptiTimestamp cuptiTime) {+ tracyEmitMemAlloc(name, ptr, size, tracyFromCUpti(cuptiTime));+}++void tracyEmitMemFree(const char* name, const void* ptr, CUptiTimestamp cuptiTime) {+ tracyEmitMemFree(name, ptr, tracyFromCUpti(cuptiTime));+}++void tracyAnnounceGpuTimestamp(TracyTimestamp apiStart, TracyTimestamp apiEnd,+ uint16_t queryId, uint8_t gpuContextId, + const tracy::SourceLocationData* sourceLocation, uint32_t threadId) {+ using namespace tracy;++ auto item = Profiler::QueueSerial();+ tracyMemWrite(item->hdr.type, QueueType::GpuZoneBeginSerial);+ tracyMemWrite(item->gpuZoneBegin.cpuTime, apiStart);+ tracyMemWrite(item->gpuZoneBegin.srcloc, (uint64_t)sourceLocation);+ tracyMemWrite(item->gpuZoneBegin.thread, threadId);+ tracyMemWrite(item->gpuZoneBegin.queryId, uint16_t(queryId+0));+ tracyMemWrite(item->gpuZoneBegin.context, gpuContextId);+ Profiler::QueueSerialFinish();++ item = Profiler::QueueSerial();+ tracyMemWrite(item->hdr.type, QueueType::GpuZoneEndSerial);+ tracyMemWrite(item->gpuZoneEnd.cpuTime, apiEnd);+ tracyMemWrite(item->gpuZoneEnd.thread, threadId);+ tracyMemWrite(item->gpuZoneEnd.queryId, uint16_t(queryId+1));+ tracyMemWrite(item->gpuZoneEnd.context, gpuContextId);+ Profiler::QueueSerialFinish();+}++void tracySubmitGpuTimestamp(CUptiTimestamp gpuStart, CUptiTimestamp gpuEnd,+ uint16_t queryId, uint8_t gpuContextId) {+ using namespace tracy;++ auto item = Profiler::QueueSerial();+ tracyMemWrite(item->hdr.type, QueueType::GpuTime);+ tracyMemWrite(item->gpuTime.gpuTime, (int64_t)gpuStart);+ tracyMemWrite(item->gpuTime.queryId, uint16_t(queryId+0));+ tracyMemWrite(item->gpuTime.context, gpuContextId);+ Profiler::QueueSerialFinish();++ item = Profiler::QueueSerial();+ tracyMemWrite(item->hdr.type, QueueType::GpuTime);+ tracyMemWrite(item->gpuTime.gpuTime, (int64_t)gpuEnd);+ tracyMemWrite(item->gpuTime.queryId, uint16_t(queryId+1));+ tracyMemWrite(item->gpuTime.context, gpuContextId);+ Profiler::QueueSerialFinish();+}++#define CUPTI_API_CALL(call) CUptiCallChecked(call, #call, __FILE__, __LINE__)++#define DRIVER_API_CALL(call) cudaDriverCallChecked(call, #call, __FILE__, __LINE__)++CUptiResult CUptiCallChecked(CUptiResult result, const char* call, const char* file, int line) noexcept {+ if (result == CUPTI_SUCCESS)+ return result;+ const char* resultMsg = "";+ CUPTI_API_CALL(cuptiGetResultString(result, &resultMsg)); // maybe not a good idea to recurse here...+ fprintf(stderr, "ERROR:\t%s:%d:\n\tfunction '%s' failed with error '%s'.\n", file, line, call, resultMsg);+ //assert(result == CUPTI_SUCCESS);+ return result;+}++CUresult cudaDriverCallChecked(CUresult result, const char* call, const char* file, int line) noexcept {+ if (result == CUDA_SUCCESS)+ return result;+ const char* resultMsg = "";+ DRIVER_API_CALL(cuGetErrorString(result, &resultMsg)); // maybe not a good idea to recurse here...+ fprintf(stderr, "ERROR:\t%s:%d:\n\tfunction '%s' failed with error '%s'.\n", file, line, call, resultMsg);+ //assert(result == CUDA_SUCCESS);+ return result;+}++template<typename TKey, typename TValue>+struct ConcurrentHashMap {+ static constexpr bool instrument = false;+ auto acquire_read_lock() {+ if (m.try_lock_shared())+ return std::shared_lock<std::shared_mutex>(m, std::adopt_lock);+ ZoneNamedC(rwlock, tracy::Color::Tomato, instrument);+ return std::shared_lock<std::shared_mutex>(m);+ }+ auto acquire_write_lock() {+ if (m.try_lock())+ return std::unique_lock<std::shared_mutex>(m, std::adopt_lock);+ ZoneNamedC(wxlock, tracy::Color::Tomato, instrument);+ return std::unique_lock<std::shared_mutex>(m);+ }+ std::unordered_map<TKey, TValue> mapping;+ std::shared_mutex m;+ auto& operator[](TKey key) {+ {+ auto lock = acquire_read_lock();+ auto it = mapping.find(key);+ if (it != mapping.end()) {+ return it->second;+ }+ }+ return emplace(key, TValue{}).first->second;+ }+ auto find(TKey key) {+ ZoneNamed(find, instrument);+ auto lock = acquire_read_lock();+ return mapping.find(key);+ }+ auto fetch(TKey key, TValue& value) {+ ZoneNamed(fetch, instrument);+ auto it = mapping.find(key);+ if (it != mapping.end()) {+ value = it->second;+ return true;+ }+ return false;+ }+ auto end() {+ ZoneNamed(end, instrument);+ auto lock = acquire_read_lock();+ return mapping.end();+ }+ template<typename... Args>+ auto emplace(TKey key, Args&&... args) {+ ZoneNamed(emplace, instrument);+ auto lock = acquire_write_lock();+ return mapping.emplace(std::forward<TKey>(key), std::forward<Args>(args)...);+ }+ auto erase(TKey key) {+ ZoneNamed(erase, instrument);+ auto lock = acquire_write_lock();+ return mapping.erase(key);+ }+};++#if TRACY_CUDA_ENABLE_CUDA_CALL_STATS+struct ProfilerStats {+ static constexpr bool instrument = false;++ ConcurrentHashMap<uint32_t, std::atomic<int>> apiCallCount;++ void update(CUpti_CallbackDomain domain, CUpti_CallbackId cbid) {+ ZoneNamed(update, instrument);+ uint32_t key = (domain << 24) | (cbid & 0x00'FFFFFF);+ auto it = apiCallCount.find(key);+ if (it == apiCallCount.end()) {+ it = apiCallCount.emplace(key, 0).first;+ }+ it->second.fetch_add(1, std::memory_order::memory_order_relaxed);+ }+};+#endif++// StringTable: string memoization/interning+struct StringTable {+ static constexpr bool instrument = false;++ // TODO(marcos): this could be just a "ConcurrentHashSet"+ ConcurrentHashMap<std::string_view, std::string_view> table;++ ~StringTable() { /* TODO(marcos): free string copy */ }++ std::string_view operator[](std::string_view str) {+ ZoneNamedN(lookup, "StringTable::lookup", instrument);+ std::string_view memoized;+ if (!table.fetch(str, memoized)) {+ ZoneNamedN(lookup, "StringTable::insert", instrument);+ char* copy = (char*)tracyMalloc(str.size() + 1);+ strncpy(copy, str.data(), str.size());+ copy[str.size()] = '\0';+ std::string_view value (copy, str.size());+ auto [it, inserted] = table.emplace(value, value);+ if (!inserted) {+ // another thread inserted it while we were trying to: cleanup+ tracyFree(copy);+ }+ memoized = it->second;+ }+ assert(str == memoized);+ return memoized;+ }+};++struct SourceLocationMap {+ static constexpr bool instrument = false;++ // NOTE(marcos): the address of an unordered_map value may become invalid+ // later on (e.g., during a rehash), so mapping to a pointer is necessary+ ConcurrentHashMap<std::string_view, tracy::SourceLocationData*> locations;++ ~SourceLocationMap() { /* TODO(marcos): free SourceLocationData* entries */ }++ tracy::SourceLocationData* retrieve(std::string_view function) {+ ZoneNamed(retrieve, instrument);+ tracy::SourceLocationData* pSrcLoc = nullptr;+ locations.fetch(function, pSrcLoc);+ return pSrcLoc;+ }++ tracy::SourceLocationData* add(std::string_view function, std::string_view file, int line, uint32_t color=0) {+ ZoneNamed(emplace, instrument);+ assert(*function.end() == '\0');+ assert(*file.end() == '\0');+ void* bytes = tracyMalloc(sizeof(tracy::SourceLocationData));+ auto pSrcLoc = new(bytes)tracy::SourceLocationData{ function.data(), TracyFunction, file.data(), (uint32_t)line, color };+ auto [it, inserted] = locations.emplace(function, pSrcLoc);+ if (!inserted) {+ // another thread inserted it while we were trying to: cleanup+ tracyFree(pSrcLoc); // POD: no destructor to call+ }+ assert(it->second != nullptr);+ return it->second;+ }+};++struct SourceLocationLUT {+ static constexpr bool instrument = false;++ ~SourceLocationLUT() { /* no action needed: no dynamic allocation */ }++ tracy::SourceLocationData runtime [CUpti_runtime_api_trace_cbid::CUPTI_RUNTIME_TRACE_CBID_SIZE] = {};+ tracy::SourceLocationData driver [CUpti_driver_api_trace_cbid::CUPTI_DRIVER_TRACE_CBID_SIZE] = {};++ tracy::SourceLocationData* retrieve(CUpti_CallbackDomain domain, CUpti_CallbackId cbid, CUpti_CallbackData* apiInfo) {+ ZoneNamed(retrieve, instrument);+ tracy::SourceLocationData* pSrcLoc = nullptr;+ switch (domain) {+ case CUPTI_CB_DOMAIN_RUNTIME_API :+ if ((cbid > 0) && (cbid < CUPTI_RUNTIME_TRACE_CBID_SIZE)) {+ pSrcLoc = &runtime[cbid];+ }+ break;+ case CUPTI_CB_DOMAIN_DRIVER_API :+ if ((cbid > 0) && (cbid < CUPTI_DRIVER_TRACE_CBID_SIZE)) {+ pSrcLoc = &driver[cbid];+ }+ break;+ default:+ break;+ }+ if (pSrcLoc->name == nullptr) {+ const char* function = apiInfo->functionName ? apiInfo->functionName : "cuda???";+ // cuptiGetCallbackName includes the "version suffix" of the function/cbid+ //CUPTI_API_CALL(cuptiGetCallbackName(domain, cbid, &function));+ *pSrcLoc = tracy::SourceLocationData{ function, TracyFunction, TracyFile, TracyLine, 0 };+ }+ return pSrcLoc;+ }+};++uint32_t tracyTimelineId(uint32_t contextId, uint32_t streamId) {+ // 0xA7C5 = 42,949 => 42,949 * 100,000 = 4,294,900,000+ // 4,294,900,000 + 65,535 = 4,294,965,535 < 4,294,967,295 (max uint32)+ assert(contextId <= 0xA7C5);+ assert((streamId == CUPTI_INVALID_STREAM_ID) || (streamId < 0xFFFF));+ uint32_t packed = (contextId * 100'000) + (streamId & 0x0000'FFFF);+ return packed;+}++} // unnamed/anonymous namespace++namespace tracy+{+ class CUDACtx+ {+ public:+ static CUDACtx* Create() {+ auto& s = Singleton::Get();+ std::unique_lock<std::mutex> lock (s.m);+ if (s.ref_count == 0) {+ assert(s.ctx == nullptr);+ s.ctx = new CUDACtx(s.ctx_id);+ s.ref_count += 1;+ s.ctx_id = s.ctx->m_tracyGpuContext;+ }+ return s.ctx;+ }++ static void Destroy(CUDACtx* ctx) {+ auto& s = Singleton::Get();+ std::unique_lock<std::mutex> lock(s.m);+ assert(ctx == s.ctx);+ s.ref_count -= 1;+ if (s.ref_count == 0) {+ delete s.ctx;+ s.ctx = nullptr;+ }+ }++ void Collect()+ {+ ZoneScoped;+ CUPTI::FlushActivity();+ }++ void printStats()+ {+ #if TRACY_CUDA_ENABLE_CUDA_CALL_STATS+ fprintf(stdout, "\nCUDA API stats:\n");+ {+ struct Stats { CUpti_CallbackDomain domain; CUpti_CallbackId cbid; int count; };+ std::vector<Stats> sorted;+ for (auto&& api : stats.apiCallCount.mapping) {+ auto domain = CUpti_CallbackDomain(api.first >> 24);+ auto cbid = CUpti_CallbackId(api.first & 0x00'FFFFFF);+ int count = api.second;+ sorted.emplace_back(Stats{ domain, cbid, count });+ }+ std::sort(sorted.begin(), sorted.end(), [](const Stats& x, const Stats& y) { return x.count > y.count; });+ for (auto&& api : sorted) {+ const char* function = "";+ CUPTI_API_CALL(cuptiGetCallbackName(api.domain, api.cbid, &function));+ printf("- %s : %d\n", function, api.count);+ }+ }+ #endif+ }++ void StartProfiling()+ {+ ZoneScoped;+ CUPTI::BeginInstrumentation(this);+ }++ void StopProfiling()+ {+ ZoneScoped;+ CUPTI::EndInstrumentation();+ printStats();+ }++ void Name(const char *name, uint16_t len)+ {+ auto ptr = (char*)tracyMalloc(len);+ memcpy(ptr, name, len);++ auto item = Profiler::QueueSerial();+ tracyMemWrite(item->hdr.type, QueueType::GpuContextName);+ tracyMemWrite(item->gpuContextNameFat.context, m_tracyGpuContext);+ tracyMemWrite(item->gpuContextNameFat.ptr, (uint64_t)ptr);+ tracyMemWrite(item->gpuContextNameFat.size, len);+ SubmitQueueItem(item);+ }++ tracy_force_inline void SubmitQueueItem(tracy::QueueItem *item)+ {+#ifdef TRACY_ON_DEMAND+ GetProfiler().DeferItem(*item);+#endif+ Profiler::QueueSerialFinish();+ }++ static void QueryTimestamps(TracyTimestamp& tTracy, CUptiTimestamp& tCUpti) {+ TracyTimestamp tTracy1 = tracyGetTimestamp();+ CUPTI_API_CALL(cuptiGetTimestamp(&tCUpti));+ TracyTimestamp tTracy2 = tracyGetTimestamp();+ // NOTE(marcos): giving more weight to 'tTracy2'+ tTracy = (3*tTracy1 + 5*tTracy2) / 8;+ }++ // NOTE(marcos): recalibration is 'static' since Tracy and CUPTI timestamps+ // are "global" across all contexts; that said, each Tracy GPU context needs+ // its own GpuCalibration message, but for now there's just a singleton context.+ void Recalibrate() {+ ZoneScoped;+ // NOTE(marcos): only one thread should do the calibration, but there's+ // no good reason to block threads that also trying to do the same+ static std::mutex m;+ if (!m.try_lock())+ return;+ std::unique_lock<std::mutex> lock (m, std::adopt_lock);+ ZoneNamedNC(zone, "tracy::CUDACtx::Recalibrate[effective]", tracy::Color::Goldenrod, true);+ TracyTimestamp tTracy;+ CUptiTimestamp tCUpti;+ QueryTimestamps(tTracy, tCUpti);+ #if TRACY_CUDA_CALIBRATED_CONTEXT+ static CUptiTimestamp prevCUptiTime = tCUpti;+ int64_t deltaTicksCUpti = tCUpti - prevCUptiTime;+ if (deltaTicksCUpti > 0) {+ prevCUptiTime = tCUpti;+ auto* item = Profiler::QueueSerial();+ tracyMemWrite(item->hdr.type, QueueType::GpuCalibration);+ tracyMemWrite(item->gpuCalibration.gpuTime, (int64_t)tCUpti);+ tracyMemWrite(item->gpuCalibration.cpuTime, tTracy);+ tracyMemWrite(item->gpuCalibration.cpuDelta, deltaTicksCUpti);+ tracyMemWrite(item->gpuCalibration.context, m_tracyGpuContext);+ Profiler::QueueSerialFinish();+ }+ #endif+ // NOTE(marcos): update linear regression incrementally, which will refine+ // the estimation of Tracy timestamps (Y) from CUpti timestamps (X)+ static IncrementalRegression model;+ model.addSample(double(tCUpti), double(tTracy));+ // NOTE(marcos): using orthogonal regression because the independet variable+ // (X: CUpti timestamps) measurements are also imprecise+ getCachedRegressionParameters() = model.orthogonal();+ }++ protected:+ void EmitGpuZone(TracyTimestamp apiStart, TracyTimestamp apiEnd,+ CUptiTimestamp gpuStart, CUptiTimestamp gpuEnd,+ const tracy::SourceLocationData* pSrcLoc,+ uint32_t cudaContextId, uint32_t cudaStreamId) {+ //uint32_t timelineId = tracy::GetThreadHandle();+ uint32_t timelineId = tracyTimelineId(cudaContextId, cudaStreamId);+ uint16_t queryId = m_queryIdGen.fetch_add(2);+ tracyAnnounceGpuTimestamp(apiStart, apiEnd, queryId, m_tracyGpuContext, pSrcLoc, timelineId);+ tracySubmitGpuTimestamp(gpuStart, gpuEnd, queryId, m_tracyGpuContext);+ }++ void OnEventsProcessed() {+ Recalibrate();+ }++ struct CUPTI {+ static void CUPTIAPI OnBufferRequested(uint8_t **buffer, size_t *size, size_t *maxNumRecords)+ {+ ZoneScoped;+ // TODO(marcos): avoid malloc and instead suballocate from a large circular buffer;+ // according to the CUPTI documentation: "To minimize profiling overhead the client+ // should return as quickly as possible from these callbacks."+ *size = 1 * 1024*1024; // 1MB+ *buffer = (uint8_t*)tracyMalloc(*size);+ assert(*buffer != nullptr);+ FlushActivityAsync();+ }++ static void CUPTIAPI OnBufferCompleted(CUcontext ctx, uint32_t streamId, uint8_t* buffer, size_t size, size_t validSize)+ {+ // CUDA 6.0 onwards: all buffers from this callback are "global" buffers+ // (i.e. there is no context/stream specific buffer; ctx is always NULL)+ ZoneScoped;+ tracy::SetThreadName("NVIDIA CUPTI Worker");+ CUptiResult status;+ CUpti_Activity* record = nullptr;+ while ((status = cuptiActivityGetNextRecord(buffer, validSize, &record)) == CUPTI_SUCCESS) {+ DoProcessDeviceEvent(record);+ }+ if (status != CUPTI_ERROR_MAX_LIMIT_REACHED) {+ CUptiCallChecked(status, "cuptiActivityGetNextRecord", TracyFile, TracyLine);+ }+ size_t dropped = 0;+ CUPTI_API_CALL(cuptiActivityGetNumDroppedRecords(ctx, streamId, &dropped));+ assert(dropped == 0);+ tracyFree(buffer);+ PersistentState::Get().profilerHost->OnEventsProcessed();+ }++ // correlationID -> [CPU start time, CPU end time, CUPTI start time]+ using CorrelationID = uint32_t;+ struct APICallInfo { TracyTimestamp start = 0, end = 0; CUptiTimestamp cupti = CUPTI_TIMESTAMP_UNKNOWN; CUDACtx* host = nullptr; };++ static void CUPTIAPI OnCallbackAPI(+ void* userdata,+ CUpti_CallbackDomain domain,+ CUpti_CallbackId cbid,+ const void* cbdata)+ {+ static constexpr bool instrument = false;++ TracyTimestamp apiCallStartTime = tracyGetTimestamp();+ CUDACtx* profilerHost = (CUDACtx*)userdata;++ switch (domain) {+ case CUPTI_CB_DOMAIN_RUNTIME_API:+ case CUPTI_CB_DOMAIN_DRIVER_API:+ break;+ case CUPTI_CB_DOMAIN_RESOURCE: {+ // match 'callbackId' with CUpti_CallbackIdResource+ // interpret 'cbdata' as CUpti_ResourceData,+ // or as CUpti_ModuleResourceData,+ // or as CUpti_GraphData,+ // or as CUpti_StreamAttrData,+ // or as ... (what else?)+ return;+ }+ case CUPTI_CB_DOMAIN_SYNCHRONIZE: {+ // match 'callbackId' with CUpti_CallbackIdSync+ // interpret 'cbdata' as CUpti_SynchronizeData+ return;+ }+ case CUPTI_CB_DOMAIN_STATE: {+ // match 'callbackId' with CUpti_CallbackIdState+ // interpret 'cbdata' as CUpti_StateData+ return;+ }+ case CUPTI_CB_DOMAIN_NVTX: {+ // match 'callbackId' with CUpti_nvtx_api_trace_cbid+ // interpret 'cbdata' as CUpti_NvtxData+ return;+ }+ case CUPTI_CB_DOMAIN_FORCE_INT:+ // NOTE(marcos): the "FORCE_INT" values in CUPTI enums exist only to+ // force the enum to have a specific representation (signed 32bits)+ case CUPTI_CB_DOMAIN_INVALID:+ default:+ // TODO(marcos): unexpected error!+ return;+ }+ + // if we reached this point, then we are in the (runtime or driver) API domain+ CUpti_CallbackData* apiInfo = (CUpti_CallbackData*)cbdata;++ // Emit the Tracy 'ZoneBegin' message upon entering the API call+ // TODO(marcos): a RAII object could be useful here...+ if (apiInfo->callbackSite == CUPTI_API_ENTER) {+ #if TRACY_CUDA_ENABLE_CUDA_CALL_STATS+ ctx->stats.update(domain, cbid);+ #endif++ auto& cudaCallSourceLocation = PersistentState::Get().cudaCallSourceLocation;+ auto pSrcLoc = cudaCallSourceLocation.retrieve(domain, cbid, apiInfo);++ // HACK(marcos): the SourceLocationLUT::retrieve zone (above) should+ // not be emitted before its enclosing zone (below) actually begins,+ // so we delay the beginning of the enclosing zone to "unstack" them+ if (SourceLocationLUT::instrument)+ apiCallStartTime = tracyGetTimestamp();+ tracyZoneBegin(apiCallStartTime, pSrcLoc);+ }++ if (apiInfo->callbackSite == CUPTI_API_ENTER) {+ ZoneNamedN(enter, "tracy::CUDACtx::OnCUptiCallback[enter]", instrument);+ // Track API calls that generate device activity:+ bool trackDeviceActivity = false;+ CUstream hStream = nullptr;+ if (domain == CUPTI_CB_DOMAIN_RUNTIME_API) {+ #define GET_STREAM_FUNC(Params, field) [](CUpti_CallbackData* api) { return ((Params*)api->functionParams)->field; }+ #define NON_STREAM_FUNC() [](CUpti_CallbackData*) { return cudaStream_t(nullptr); }+ static std::unordered_map<CUpti_runtime_api_trace_cbid, cudaStream_t(*)(CUpti_CallbackData*)> cbidRuntimeTrackers = {+ // Runtime: Kernel+ { CUPTI_RUNTIME_TRACE_CBID_cudaLaunchKernel_v7000, GET_STREAM_FUNC(cudaLaunchKernel_v7000_params, stream) },+ { CUPTI_RUNTIME_TRACE_CBID_cudaLaunchKernel_ptsz_v7000, GET_STREAM_FUNC(cudaLaunchKernel_ptsz_v7000_params, stream) },+ { CUPTI_RUNTIME_TRACE_CBID_cudaLaunchKernelExC_v11060, GET_STREAM_FUNC(cudaLaunchKernelExC_v11060_params, config->stream) },+ { CUPTI_RUNTIME_TRACE_CBID_cudaLaunchKernelExC_ptsz_v11060, GET_STREAM_FUNC(cudaLaunchKernelExC_ptsz_v11060_params, config->stream) },+ // Runtime: Memory+ { CUPTI_RUNTIME_TRACE_CBID_cudaMalloc_v3020, NON_STREAM_FUNC() },+ { CUPTI_RUNTIME_TRACE_CBID_cudaFree_v3020, NON_STREAM_FUNC() },+ // Runtime: Memcpy+ { CUPTI_RUNTIME_TRACE_CBID_cudaMemcpy_v3020, NON_STREAM_FUNC() },+ { CUPTI_RUNTIME_TRACE_CBID_cudaMemcpyAsync_v3020, GET_STREAM_FUNC(cudaMemcpyAsync_v3020_params, stream) },+ // Runtime: Memset+ { CUPTI_RUNTIME_TRACE_CBID_cudaMemset_v3020, NON_STREAM_FUNC() },+ { CUPTI_RUNTIME_TRACE_CBID_cudaMemsetAsync_v3020, GET_STREAM_FUNC(cudaMemsetAsync_v3020_params, stream) },+ // Runtime: Synchronization+ { CUPTI_RUNTIME_TRACE_CBID_cudaStreamSynchronize_v3020, NON_STREAM_FUNC() },+ { CUPTI_RUNTIME_TRACE_CBID_cudaEventSynchronize_v3020, NON_STREAM_FUNC() },+ { CUPTI_RUNTIME_TRACE_CBID_cudaEventQuery_v3020, NON_STREAM_FUNC() },+ { CUPTI_RUNTIME_TRACE_CBID_cudaStreamWaitEvent_v3020, NON_STREAM_FUNC() },+ { CUPTI_RUNTIME_TRACE_CBID_cudaDeviceSynchronize_v3020, NON_STREAM_FUNC() },+ };+ #undef NON_STREAM_FUNC+ #undef GET_STREAM_FUNC+ auto it = cbidRuntimeTrackers.find(CUpti_runtime_api_trace_cbid(cbid));+ if (it != cbidRuntimeTrackers.end()) {+ trackDeviceActivity = true;+ hStream = (CUstream)it->second(apiInfo);+ }+ }+ if (domain == CUPTI_CB_DOMAIN_DRIVER_API) {+ #define GET_STREAM_FUNC(Params, field) [](CUpti_CallbackData* api) { return ((Params*)api->functionParams)->field; }+ #define NON_STREAM_FUNC() [](CUpti_CallbackData*) { return CUstream(nullptr); }+ static std::unordered_map<CUpti_driver_api_trace_cbid, CUstream(*)(CUpti_CallbackData*)> cbidDriverTrackers = {+ // Driver: Kernel+ { CUPTI_DRIVER_TRACE_CBID_cuLaunchKernel, GET_STREAM_FUNC(cuLaunchKernel_params, hStream) },+ { CUPTI_DRIVER_TRACE_CBID_cuLaunchKernel_ptsz, GET_STREAM_FUNC(cuLaunchKernel_ptsz_params, hStream)} ,+ { CUPTI_DRIVER_TRACE_CBID_cuLaunchKernelEx, GET_STREAM_FUNC(cuLaunchKernelEx_params, config->hStream) },+ { CUPTI_DRIVER_TRACE_CBID_cuLaunchKernelEx_ptsz, GET_STREAM_FUNC(cuLaunchKernelEx_params, config->hStream) },+ };+ #undef NON_STREAM_FUNC+ #undef GET_STREAM_FUNC+ auto it = cbidDriverTrackers.find(CUpti_driver_api_trace_cbid(cbid));+ if (it != cbidDriverTrackers.end()) {+ trackDeviceActivity = true;+ hStream = it->second(apiInfo);+ }+ }+ if (trackDeviceActivity) {+ // NOTE(marcos): we should NOT track if the stream is being captured+ CUstreamCaptureStatus status = {};+ DRIVER_API_CALL(cuStreamIsCapturing(hStream, &status));+ trackDeviceActivity = !(status == CU_STREAM_CAPTURE_STATUS_ACTIVE);+ }+ if (trackDeviceActivity) {+ CUptiTimestamp tgpu;+ // TODO(marcos): do a "reverse-estimate" to obtain CUpti time from Tracy time instead?+ CUPTI_API_CALL(cuptiGetTimestamp(&tgpu));+ auto& cudaCallSiteInfo = PersistentState::Get().cudaCallSiteInfo;+ cudaCallSiteInfo.emplace(apiInfo->correlationId, APICallInfo{ apiCallStartTime, apiCallStartTime, tgpu, profilerHost });+ }+ auto& entryFlags = *apiInfo->correlationData;+ assert(entryFlags == 0);+ entryFlags |= trackDeviceActivity ? 0x8000 : 0;+ }++ if (apiInfo->callbackSite == CUPTI_API_EXIT) {+ APICallInfo* pApiInterval = [](CUpti_CallbackData* apiInfo) {+ ZoneNamedN(exit, "tracy::CUDACtx::OnCUptiCallback[exit]", instrument);+ auto entryFlags = *apiInfo->correlationData;+ bool trackDeviceActivity = (entryFlags & 0x8000) != 0;+ if (trackDeviceActivity) {+ auto& cudaCallSiteInfo = PersistentState::Get().cudaCallSiteInfo;+ auto it = cudaCallSiteInfo.find(apiInfo->correlationId);+ if (it != cudaCallSiteInfo.end()) {+ // WARN(marcos): leaking the address of a hash-map value could spell trouble+ return &it->second;+ }+ }+ // NOTE(marcos): this can happen if the GPU activity completes+ // before the CUDA function that enqueued it returns (e.g., sync)+ static APICallInfo sentinel;+ return &sentinel;+ }(apiInfo);+ pApiInterval->end = tracyGetTimestamp();+ tracyZoneEnd(pApiInterval->end);+ }+ }++ static bool matchActivityToAPICall(uint32_t correlationId, APICallInfo& apiCallInfo) {+ static constexpr bool instrument = false;+ ZoneNamed(match, instrument);+ auto& cudaCallSiteInfo = PersistentState::Get().cudaCallSiteInfo;+ if (!cudaCallSiteInfo.fetch(correlationId, apiCallInfo)) {+ return false;+ }+ cudaCallSiteInfo.erase(correlationId);+ assert(apiCallInfo.host != nullptr);+ return true;+ }++ static void matchError(uint32_t correlationId, const char* kind) {+ char msg [128];+ snprintf(msg, sizeof(msg), "ERROR: device activity '%s' has no matching CUDA API call (id=%u).", kind, correlationId);+ TracyMessageC(msg, strlen(msg), tracy::Color::Tomato);+ }++ static std::string extractActualName(char** name){+ //If name does not start with number, return empty string+ if (!isdigit(**name))+ {+ return std::string();+ }+ // Assuming name starts with number followed by actual name+ std::string actualName;+ char* currStr = *name;+ int num = 0;+ while (*currStr >= '0' && *currStr <= '9')+ {+ num = num * 10 + (*currStr - '0');+ currStr++;+ }++ // Return the string start at currStr ends at num+ actualName = std::string(currStr, num);+ // check if actualName starts with _GLOBAL__N__+ if (actualName.rfind("_GLOBAL__N__", 0) == 0)+ {+ // _GLOBAL__N__ with an id stands for anonymous namespace+ actualName = std::string("(anonymous_namespace)");+ }++ *name = currStr + num;+ return actualName;+ }++ static std::string extractActualNameNested(const char* demangledName)+ {+ ZoneNamedN(demangle, "demangle_kernel", false);+ //If name does not start with _Z, return a new std::string with original name+ if (demangledName[0] != '_' || demangledName[1] != 'Z')+ {+ return std::string(demangledName);+ }+ std::string actualName;+ char* currStr = (char*)demangledName + 2;++ if (*currStr == 'N')+ {+ currStr++;+ // extract actual name from nested name+ std::string nestedName = extractActualName(&currStr);+ actualName += nestedName;+ while (1)+ {+ //Loop until nested name is empty+ nestedName = extractActualName(&currStr);+ if (nestedName.empty())+ {+ break;+ }+ actualName += "::" + nestedName;+ }+ } else+ {+ actualName = extractActualName(&currStr);+ }+ return actualName;+ }++ static tracy::SourceLocationData* getKernelSourceLocation(const char* kernelName)+ {+ auto& kernelSrcLoc = PersistentState::Get().kernelSrcLoc;+ std::string_view demangledName;+ #ifndef _MSC_VER+ // TODO(marcos): extractActualNameNested is the main bottleneck right now;+ // we need a specialized StringTable mapping from "peristent" kernel names+ // (const char*/uintptr_t) to memoized, lazily initialized demangled names+ auto& demangledNameTable = PersistentState::Get().demangledNameTable;+ std::string demangled = extractActualNameNested(kernelName);+ demangledName = demangledNameTable[demangled];+ #else+ demangledName = kernelName;+ #endif+ auto pSrcLoc = kernelSrcLoc.retrieve(demangledName);+ if (pSrcLoc == nullptr) {+ pSrcLoc = kernelSrcLoc.add(demangledName, TracyFile, TracyLine);+ }+ return pSrcLoc;+ }++ static void DoProcessDeviceEvent(CUpti_Activity *record)+ {+ static constexpr bool instrument = false;+ ZoneNamed(activity, instrument);++ switch (record->kind)+ {+ case CUPTI_ACTIVITY_KIND_CONCURRENT_KERNEL:+ { + ZoneNamedN(kernel, "tracy::CUDACtx::DoProcessDeviceEvent[kernel]", instrument);+ CUpti_ActivityKernel9* kernel9 = (CUpti_ActivityKernel9*) record;+ APICallInfo apiCall;+ if (!matchActivityToAPICall(kernel9->correlationId, apiCall)) {+ return matchError(kernel9->correlationId, "KERNEL");+ }+ apiCall.host->EmitGpuZone(apiCall.start, apiCall.end, kernel9->start, kernel9->end, getKernelSourceLocation(kernel9->name), kernel9->contextId, kernel9->streamId);+ auto latency_ms = (kernel9->start - apiCall.cupti) / 1'000'000.0;+ tracyPlotBlip("Kernel Latency (ms)", kernel9->start, latency_ms);+ break;+ }++ case CUPTI_ACTIVITY_KIND_MEMCPY:+ {+ ZoneNamedN(kernel, "tracy::CUDACtx::DoProcessDeviceEvent[memcpy]", instrument);+ CUpti_ActivityMemcpy5* memcpy5 = (CUpti_ActivityMemcpy5*) record;+ APICallInfo apiCall;+ if (!matchActivityToAPICall(memcpy5->correlationId, apiCall)) {+ return matchError(memcpy5->correlationId, "MEMCPY");+ }+ static constexpr tracy::SourceLocationData TracyCUPTISrcLocDeviceMemcpy { "CUDA::memcpy", TracyFunction, TracyFile, (uint32_t)TracyLine, tracy::Color::Blue };+ apiCall.host->EmitGpuZone(apiCall.start, apiCall.end, memcpy5->start, memcpy5->end, &TracyCUPTISrcLocDeviceMemcpy, memcpy5->contextId, memcpy5->streamId);+ static constexpr const char* graph_name = "CUDA Memory Copy";+ tracyEmitMemAlloc(graph_name, (void*)(uintptr_t)memcpy5->correlationId, memcpy5->bytes, memcpy5->start);+ tracyEmitMemFree (graph_name, (void*)(uintptr_t)memcpy5->correlationId, memcpy5->end);+ break;+ }++ case CUPTI_ACTIVITY_KIND_MEMSET:+ {+ ZoneNamedN(kernel, "tracy::CUDACtx::DoProcessDeviceEvent[memset]", instrument);+ CUpti_ActivityMemset4* memset4 = (CUpti_ActivityMemset4*) record;+ APICallInfo apiCall;+ if (!matchActivityToAPICall(memset4->correlationId, apiCall)) {+ return matchError(memset4->correlationId, "MEMSET");+ }+ static constexpr tracy::SourceLocationData TracyCUPTISrcLocDeviceMemset { "CUDA::memset", TracyFunction, TracyFile, (uint32_t)TracyLine, tracy::Color::Blue };+ apiCall.host->EmitGpuZone(apiCall.start, apiCall.end, memset4->start, memset4->end, &TracyCUPTISrcLocDeviceMemset, memset4->contextId, memset4->streamId);+ static constexpr const char* graph_name = "CUDA Memory Set";+ tracyEmitMemAlloc(graph_name, (void*)(uintptr_t)memset4->correlationId, memset4->bytes, memset4->start);+ tracyEmitMemFree (graph_name, (void*)(uintptr_t)memset4->correlationId, memset4->end);+ break;+ }++ case CUPTI_ACTIVITY_KIND_SYNCHRONIZATION:+ {+ ZoneNamedN(kernel, "tracy::CUDACtx::DoProcessDeviceEvent[sync]", instrument);+ CUpti_ActivitySynchronization* synchronization = (CUpti_ActivitySynchronization*) record;+ APICallInfo apiCall;+ if (!matchActivityToAPICall(synchronization->correlationId, apiCall)) {+ return matchError(synchronization->correlationId, "SYNCHRONIZATION");+ }+ // NOTE(marcos): synchronization can happen at different levels/objects:+ // a. on the entire context : cuCtxSynchronize() -> timeline(ctx,0)+ // b. on a specific stream : cuStreamSynchronize() -> timeline(ctx,stream)+ // c. on a specific event : cuEventSynchronize() -> timeline(ctx,0xffff)+ static constexpr tracy::SourceLocationData TracyCUPTISrcLocContextSynchronization { "CUDA::Context::sync", TracyFunction, TracyFile, (uint32_t)TracyLine, tracy::Color::Magenta };+ auto* pSrcLoc = &TracyCUPTISrcLocContextSynchronization;+ uint32_t cudaContextId = synchronization->contextId;+ uint32_t cudaStreamId = 0;+ if (synchronization->streamId != CUPTI_SYNCHRONIZATION_INVALID_VALUE) {+ static constexpr tracy::SourceLocationData TracyCUPTISrcLocStreamSynchronization{ "CUDA::Stream::sync", TracyFunction, TracyFile, (uint32_t)TracyLine, tracy::Color::Magenta3 };+ pSrcLoc = &TracyCUPTISrcLocStreamSynchronization;+ cudaStreamId = synchronization->streamId;+ }+ if (synchronization->cudaEventId != CUPTI_SYNCHRONIZATION_INVALID_VALUE) {+ static constexpr tracy::SourceLocationData TracyCUPTISrcLocEventSynchronization{ "CUDA::Event::sync", TracyFunction, TracyFile, (uint32_t)TracyLine, tracy::Color::Magenta4 };+ pSrcLoc = &TracyCUPTISrcLocEventSynchronization;+ cudaStreamId = 0xFFFFFFFF;+ // TODO(marcos): CUpti_ActivitySynchronization2 introduces a new+ // field 'cudaEventSyncId' which complements 'cudaEventId'+ }+ apiCall.host->EmitGpuZone(apiCall.start, apiCall.end, synchronization->start, synchronization->end, pSrcLoc, cudaContextId, cudaStreamId);+ static constexpr const char* graph_name = "CUDA Synchronization";+ tracyEmitMemAlloc(graph_name, (void*)(uintptr_t)synchronization->correlationId, 1, synchronization->start);+ tracyEmitMemFree (graph_name, (void*)(uintptr_t)synchronization->correlationId, synchronization->end);+ break;+ }+ case CUPTI_ACTIVITY_KIND_MEMORY2:+ {+ ZoneNamedN(kernel, "tracy::CUDACtx::DoProcessDeviceEvent[malloc/free]", instrument);+ CUpti_ActivityMemory3* memory3 = (CUpti_ActivityMemory3*)record;+ APICallInfo apiCall;+ if (!matchActivityToAPICall(memory3->correlationId, apiCall)) {+ return matchError(memory3->correlationId, "MEMORY");+ }+ static constexpr const char* graph_name = "CUDA Memory Allocation";+ if (memory3->memoryOperationType == CUPTI_ACTIVITY_MEMORY_OPERATION_TYPE_ALLOCATION){+ auto& memAllocAddress = PersistentState::Get().memAllocAddress;+ memAllocAddress[memory3->address] = 1;+ tracyEmitMemAlloc(graph_name, (void*)memory3->address, memory3->bytes, memory3->timestamp);+ }+ else if (memory3->memoryOperationType == CUPTI_ACTIVITY_MEMORY_OPERATION_TYPE_RELEASE){+ auto& memAllocAddress = PersistentState::Get().memAllocAddress;+ int dontCare;+ if (!memAllocAddress.fetch(memory3->address, dontCare)){+ // Note(Frank): This is a hack to handle the case where the memory allocation+ // corresponds to the memory release is not found.+ // This can happen when the memory is allocated when profiling is not enabled.+ matchError(memory3->correlationId, "MEMORY/RELEASE");+ tracyEmitMemAlloc(graph_name, (void*)memory3->address, memory3->bytes, memory3->timestamp);+ } else {+ memAllocAddress.erase(memory3->address);+ }+ tracyEmitMemFree(graph_name, (void*)memory3->address, memory3->timestamp);+ }+ break;+ }+ case CUPTI_ACTIVITY_KIND_CUDA_EVENT :+ {+ // NOTE(marcos): a byproduct of CUPTI_ACTIVITY_KIND_SYNCHRONIZATION+ // (I think this is related to cudaEvent*() API calls)+ CUpti_ActivityCudaEvent2* event = (CUpti_ActivityCudaEvent2*)record;+ UNREFERENCED(event);+ break;+ }+ default:+ {+ char buffer[64];+ snprintf(buffer, sizeof(buffer), "Unknown activity record (kind is %d)", record->kind);+ TracyMessageC(buffer, strlen(buffer), tracy::Color::Crimson);+ break;+ }+ }+ }++ static constexpr CUpti_CallbackDomain domains[] = {+ CUPTI_CB_DOMAIN_RUNTIME_API,+ CUPTI_CB_DOMAIN_DRIVER_API,+ //CUPTI_CB_DOMAIN_RESOURCE,+ //CUPTI_CB_DOMAIN_SYNCHRONIZE,+ //CUPTI_CB_DOMAIN_NVTX,+ //CUPTI_CB_DOMAIN_STATE+ };++ static constexpr CUpti_ActivityKind activities[] = {+ //CUPTI_ACTIVITY_KIND_KERNEL, // mutually exclusive with CONCURRENT_KERNEL+ CUPTI_ACTIVITY_KIND_CONCURRENT_KERNEL,+ CUPTI_ACTIVITY_KIND_MEMCPY,+ CUPTI_ACTIVITY_KIND_MEMSET,+ CUPTI_ACTIVITY_KIND_SYNCHRONIZATION,+ CUPTI_ACTIVITY_KIND_MEMORY2,+ //CUPTI_ACTIVITY_KIND_MEMCPY2,+ //CUPTI_ACTIVITY_KIND_OVERHEAD,+ //CUPTI_ACTIVITY_KIND_INTERNAL_LAUNCH_API,+ //CUPTI_ACTIVITY_KIND_RUNTIME,+ //CUPTI_ACTIVITY_KIND_DRIVER,+ };++ static void BeginInstrumentation(CUDACtx* profilerHost) {+ auto& currentProfilerHost = PersistentState::Get().profilerHost;+ if (currentProfilerHost != nullptr) {+ return;+ }+ currentProfilerHost = profilerHost;++ // NOTE(frank): full-stop synchronization to ensure we only handle+ // CUDA API calls and device activities that happens past this point+ cudaDeviceSynchronize();++ auto& subscriber = PersistentState::Get().subscriber;+ CUPTI_API_CALL(cuptiSubscribe(&subscriber, CUPTI::OnCallbackAPI, profilerHost));+ CUPTI_API_CALL(cuptiActivityRegisterCallbacks(CUPTI::OnBufferRequested, CUPTI::OnBufferCompleted));+ for (auto domain : domains) {+ CUPTI_API_CALL(cuptiEnableDomain(uint32_t(true), subscriber, domain));+ }+ for (auto activity : activities) {+ CUPTI_API_CALL(cuptiActivityEnable(activity));+ }++ #if TRACY_CUDA_ENABLE_COLLECTOR_THREAD+ auto& collector = PersistentState::Get().collector;+ collector.period = 160;+ collector.signal.notify_one();+ #endif+ }++ static void EndInstrumentation() {+ auto& currentProfilerHost = PersistentState::Get().profilerHost;+ if (currentProfilerHost == nullptr) {+ return;+ }++ // NOTE(frank): full-stop synchronization to ensure we catch+ // and drain all the activities that has been tracked up to now.+ cudaDeviceSynchronize();++ FlushActivity();++ auto& subscriber = PersistentState::Get().subscriber;+ for (auto activity : activities) {+ CUPTI_API_CALL(cuptiActivityDisable(activity));+ }+ for (auto domain : domains) {+ CUPTI_API_CALL(cuptiEnableDomain(uint32_t(false), subscriber, domain));+ }+ // TODO(marcos): is here a counterpart for 'cuptiActivityRegisterCallbacks()'?+ CUPTI_API_CALL(cuptiUnsubscribe(subscriber));++ #if TRACY_CUDA_ENABLE_COLLECTOR_THREAD+ auto& collector = PersistentState::Get().collector;+ collector.period = ~uint32_t(0);+ collector.signal.notify_one();+ #endif++ currentProfilerHost = nullptr;+ }++ static void FlushActivity()+ {+ // NOTE(marcos): only one thread should do the collection at any given time,+ // but there's no reason to block threads that are also trying to do the same+ static std::mutex m;+ if (!m.try_lock())+ return;+ std::unique_lock<std::mutex> lock (m, std::adopt_lock);+ ZoneNamedNC(zone, "cuptiActivityFlushAll", tracy::Color::Red4, true);+ CUPTI_API_CALL(cuptiActivityFlushAll(CUPTI_ACTIVITY_FLAG_NONE));+ }++ #if TRACY_CUDA_ENABLE_COLLECTOR_THREAD+ // WARN(marcos): technically, CUPTI already offers async flushing of+ // activity records through cuptiActivityFlushPeriod(), but I haven't+ // had much luck getting reliable, consistent delivery with it...+ struct Collector {+ std::atomic<bool> running = true;+ volatile uint32_t period = ~uint32_t(0);+ std::mutex mtx;+ std::condition_variable signal;+ std::thread thread = std::thread(+ [this]() {+ tracy::SetThreadName("Tracy CUDA Collector");+ atexit([]() {+ auto& collector = CUPTI::PersistentState::Get().collector;+ collector.running = false;+ collector.signal.notify_one();+ collector.thread.join();+ });+ while (running) {+ {+ std::unique_lock<std::mutex> lock(mtx);+ signal.wait_for(lock, std::chrono::milliseconds(period));+ }+ FlushActivity();+ }+ }+ );+ };+ #endif++ static void FlushActivityAsync()+ {+ #if TRACY_CUDA_ENABLE_COLLECTOR_THREAD+ ZoneScoped;+ auto& collector = PersistentState::Get().collector;+ collector.signal.notify_one();+ #endif+ }++ struct PersistentState {+ // NOTE(marcos): these objects must remain in memory past the application+ // returning from main() because the Tracy client worker thread may still+ // be responding to string/source-location requests from the server+ SourceLocationMap kernelSrcLoc;+ StringTable demangledNameTable;+ SourceLocationLUT cudaCallSourceLocation;++ // NOTE(marcos): these objects do not need to persist, but their relative+ // footprint is trivial enough that we don't care if we let them leak+ ConcurrentHashMap<CorrelationID, APICallInfo> cudaCallSiteInfo;+ ConcurrentHashMap<uintptr_t, int> memAllocAddress;+ CUpti_SubscriberHandle subscriber = {};+ CUDACtx* profilerHost = nullptr;++ Collector collector;++ static PersistentState& Get() {+ static PersistentState& persistent = *(new PersistentState());+ return persistent;+ }+ };++ };++ CUDACtx(uint8_t gpuContextID = 255)+ {+ ZoneScoped;++ if (gpuContextID != 255) {+ m_tracyGpuContext = gpuContextID;+ return;+ }++ m_tracyGpuContext = GetGpuCtxCounter().fetch_add(1, std::memory_order_relaxed);+ assert(m_tracyGpuContext != 255);++ TracyTimestamp tTracy;+ CUptiTimestamp tCUpti;+ QueryTimestamps(tTracy, tCUpti);++ // Announce to Tracy about a new GPU context/timeline:+ auto item = Profiler::QueueSerial();+ tracyMemWrite(item->hdr.type, QueueType::GpuNewContext);+ tracyMemWrite(item->gpuNewContext.cpuTime, tTracy);+ tracyMemWrite(item->gpuNewContext.gpuTime, (int64_t)tCUpti); // TODO: Be more careful about this cast+ tracyMemWrite(item->gpuNewContext.thread, (uint32_t)0);+ tracyMemWrite(item->gpuNewContext.period, 1.0f);+ tracyMemWrite(item->gpuNewContext.type, GpuContextType::CUDA);+ tracyMemWrite(item->gpuNewContext.context, m_tracyGpuContext);+ #if TRACY_CUDA_CALIBRATED_CONTEXT+ tracyMemWrite(item->gpuNewContext.flags, GpuContextCalibration);+ #else+ tracyMemWrite(item->gpuNewContext.flags, tracy::GpuContextFlags(0));+ #endif+ Profiler::QueueSerialFinish();++ constexpr const char* tracyCtxName = "CUDA GPU/Device Activity";+ this->Name(tracyCtxName, uint16_t(strlen(tracyCtxName)));++ // NOTE(marcos): a few rounds of calibation amorthized over 1 second+ // in order to get a meaningful linear regression estimator+ Recalibrate();+ std::this_thread::sleep_for(std::chrono::milliseconds(100));+ Recalibrate();+ std::this_thread::sleep_for(std::chrono::milliseconds(200));+ Recalibrate();+ std::this_thread::sleep_for(std::chrono::milliseconds(300));+ Recalibrate();+ std::this_thread::sleep_for(std::chrono::milliseconds(400));+ Recalibrate();+ }++ ~CUDACtx()+ {+ ZoneScoped;+ }++ struct Singleton {+ CUDACtx* ctx = nullptr;+ std::mutex m;+ int ref_count = 0;+ uint8_t ctx_id = 255;+ static Singleton& Get() {+ static Singleton singleton;+ return singleton;+ }+ };++ #if TRACY_CUDA_ENABLE_CUDA_CALL_STATS+ ProfilerStats stats = {};+ #endif++ uint8_t m_tracyGpuContext = 255;+ static constexpr size_t cacheline = 64;+ alignas(cacheline) std::atomic<uint16_t> m_queryIdGen = 0;+ };++}++#define TracyCUDAContext() tracy::CUDACtx::Create()+#define TracyCUDAContextDestroy(ctx) tracy::CUDACtx::Destroy(ctx)+#define TracyCUDAContextName(ctx, name, size) ctx->Name(name, size)++#define TracyCUDAStartProfiling(ctx) ctx->StartProfiling()+#define TracyCUDAStopProfiling(ctx) ctx->StopProfiling()++#define TracyCUDACollect(ctx) ctx->Collect()++#endif++#endif
+ cbits/tracy/public/tracy/TracyD3D11.hpp view
@@ -0,0 +1,466 @@+#ifndef __TRACYD3D11_HPP__+#define __TRACYD3D11_HPP__++#ifndef TRACY_ENABLE++#define TracyD3D11Context(device,queue) nullptr+#define TracyD3D11Destroy(ctx)+#define TracyD3D11ContextName(ctx, name, size)++#define TracyD3D11NewFrame(ctx)++#define TracyD3D11Zone(ctx, name)+#define TracyD3D11ZoneC(ctx, name, color)+#define TracyD3D11NamedZone(ctx, varname, name, active)+#define TracyD3D11NamedZoneC(ctx, varname, name, color, active)+#define TracyD3D11ZoneTransient(ctx, varname, name, active)++#define TracyD3D11ZoneS(ctx, name, depth)+#define TracyD3D11ZoneCS(ctx, name, color, depth)+#define TracyD3D11NamedZoneS(ctx, varname, name, depth, active)+#define TracyD3D11NamedZoneCS(ctx, varname, name, color, depth, active)+#define TracyD3D11ZoneTransientS(ctx, varname, name, depth, active)++#define TracyD3D11Collect(ctx)++namespace tracy+{+class D3D11ZoneScope {};+}++using TracyD3D11Ctx = void*;++#else++#include <atomic>+#include <assert.h>+#include <stdlib.h>++#include "Tracy.hpp"+#include "../client/TracyProfiler.hpp"+#include "../client/TracyCallstack.hpp"+#include "../common/TracyYield.hpp"++#include <d3d11.h>++#define TracyD3D11Panic(msg, ...) do { assert(false && "TracyD3D11: " msg); TracyMessageLC("TracyD3D11: " msg, tracy::Color::Red4); __VA_ARGS__; } while(false);++namespace tracy+{++class D3D11Ctx+{+ friend class D3D11ZoneScope;++ static constexpr uint32_t MaxQueries = 64 * 1024;++ enum CollectMode { POLL, BLOCK };++public:+ D3D11Ctx( ID3D11Device* device, ID3D11DeviceContext* devicectx )+ {+ // TODO: consider calling ID3D11Device::GetImmediateContext() instead of passing it as an argument+ m_device = device;+ device->AddRef();+ m_immediateDevCtx = devicectx;+ devicectx->AddRef();++ {+ D3D11_QUERY_DESC desc = { };+ desc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;+ if (FAILED(m_device->CreateQuery(&desc, &m_disjointQuery)))+ {+ TracyD3D11Panic("unable to create disjoint timestamp query.", return);+ }+ }++ for (ID3D11Query*& query : m_queries)+ {+ D3D11_QUERY_DESC desc = { };+ desc.Query = D3D11_QUERY_TIMESTAMP;+ if (FAILED(m_device->CreateQuery(&desc, &query)))+ {+ TracyD3D11Panic("unable to create timestamp query.", return);+ }+ }++ // Calibrate CPU and GPU timestamps+ int64_t tcpu = 0;+ int64_t tgpu = 0;+ for (int attempts = 0; attempts < 50; attempts++)+ {+ m_immediateDevCtx->Begin(m_disjointQuery);+ m_immediateDevCtx->End(m_queries[0]);+ m_immediateDevCtx->End(m_disjointQuery);++ int64_t tcpu0 = Profiler::GetTime();+ WaitForQuery(m_disjointQuery);+ // NOTE: one would expect that by waiting for the enclosing disjoint query to finish,+ // all timestamp queries within would also be readily available, but that does not+ // seem to be the case here... See https://github.com/wolfpld/tracy/issues/947+ WaitForQuery(m_queries[0]);+ int64_t tcpu1 = Profiler::GetTime();++ D3D11_QUERY_DATA_TIMESTAMP_DISJOINT disjoint = { };+ if (m_immediateDevCtx->GetData(m_disjointQuery, &disjoint, sizeof(disjoint), 0) != S_OK)+ {+ TracyMessageLC("TracyD3D11: unable to query GPU timestamp; retrying...", tracy::Color::Tomato);+ continue;+ }++ if (disjoint.Disjoint)+ continue;++ UINT64 timestamp = 0;+ if (m_immediateDevCtx->GetData(m_queries[0], ×tamp, sizeof(timestamp), 0) != S_OK)+ continue; // this should never happen (we waited for the query to finish above)++ tcpu = tcpu0 + (tcpu1 - tcpu0) * 1 / 2;+ tgpu = timestamp * (1000000000 / disjoint.Frequency);+ break;+ }++ // ready to roll+ m_contextId = GetGpuCtxCounter().fetch_add(1);+ m_immediateDevCtx->Begin(m_disjointQuery);+ m_previousCheckpoint = m_nextCheckpoint = 0;++ auto* item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::GpuNewContext );+ MemWrite( &item->gpuNewContext.cpuTime, tcpu );+ MemWrite( &item->gpuNewContext.gpuTime, tgpu );+ MemWrite( &item->gpuNewContext.thread, uint32_t(0) ); // #TODO: why not GetThreadHandle()?+ MemWrite( &item->gpuNewContext.period, 1.0f );+ MemWrite( &item->gpuNewContext.context, m_contextId);+ MemWrite( &item->gpuNewContext.flags, uint8_t(0) );+ MemWrite( &item->gpuNewContext.type, GpuContextType::Direct3D11 );++#ifdef TRACY_ON_DEMAND+ GetProfiler().DeferItem( *item );+#endif++ Profiler::QueueSerialFinish();+ }++ ~D3D11Ctx()+ {+ // collect all pending timestamps before destroying everything+ do+ {+ Collect(BLOCK);+ } while (m_previousCheckpoint != m_queryCounter);++ for (ID3D11Query* query : m_queries)+ {+ query->Release();+ }+ m_immediateDevCtx->End(m_disjointQuery);+ m_disjointQuery->Release();+ m_immediateDevCtx->Release();+ m_device->Release();+ }++ void Name( const char* name, uint16_t len )+ {+ auto ptr = (char*)tracy_malloc( len );+ memcpy( ptr, name, len );++ auto item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::GpuContextName );+ MemWrite( &item->gpuContextNameFat.context, m_contextId );+ MemWrite( &item->gpuContextNameFat.ptr, (uint64_t)ptr );+ MemWrite( &item->gpuContextNameFat.size, len );+#ifdef TRACY_ON_DEMAND+ GetProfiler().DeferItem( *item );+#endif+ Profiler::QueueSerialFinish();+ }++ void Collect(CollectMode mode = POLL)+ {+ ZoneScopedC( Color::Red4 );++#ifdef TRACY_ON_DEMAND+ if( !GetProfiler().IsConnected() )+ {+ m_previousCheckpoint = m_nextCheckpoint = m_queryCounter;+ return;+ }+#endif++ if (m_previousCheckpoint == m_nextCheckpoint)+ {+ uintptr_t nextCheckpoint = m_queryCounter;+ if (nextCheckpoint == m_nextCheckpoint)+ {+ return;+ }+ m_nextCheckpoint = nextCheckpoint;+ m_immediateDevCtx->End(m_disjointQuery);+ }++ if (mode == CollectMode::BLOCK)+ {+ WaitForQuery(m_disjointQuery);+ }++ D3D11_QUERY_DATA_TIMESTAMP_DISJOINT disjoint = { };+ if (m_immediateDevCtx->GetData(m_disjointQuery, &disjoint, sizeof(disjoint), D3D11_ASYNC_GETDATA_DONOTFLUSH) != S_OK)+ {+ return;+ }++ if (disjoint.Disjoint == TRUE)+ {+ m_previousCheckpoint = m_nextCheckpoint;+ TracyD3D11Panic("disjoint timestamps detected; dropping.");+ return;+ }++ auto begin = m_previousCheckpoint;+ auto end = m_nextCheckpoint;+ for (auto i = begin; i != end; ++i)+ {+ uint32_t k = RingIndex(i);+ UINT64 timestamp = 0;+ if (m_immediateDevCtx->GetData(m_queries[k], ×tamp, sizeof(timestamp), 0) != S_OK)+ {+ TracyD3D11Panic("timestamp expected to be ready, but it was not!");+ break;+ }+ timestamp *= (1000000000ull / disjoint.Frequency);+ auto* item = Profiler::QueueSerial();+ MemWrite(&item->hdr.type, QueueType::GpuTime);+ MemWrite(&item->gpuTime.gpuTime, static_cast<int64_t>(timestamp));+ MemWrite(&item->gpuTime.queryId, static_cast<uint16_t>(k));+ MemWrite(&item->gpuTime.context, m_contextId);+ Profiler::QueueSerialFinish();+ }++ // disjoint timestamp queries should only be invoked once per frame or less+ // https://learn.microsoft.com/en-us/windows/win32/api/d3d11/ne-d3d11-d3d11_query+ m_immediateDevCtx->Begin(m_disjointQuery);+ m_previousCheckpoint = m_nextCheckpoint;+ }++private:+ tracy_force_inline uint32_t RingIndex(uintptr_t index)+ {+ index %= MaxQueries;+ return static_cast<uint32_t>(index);+ }++ tracy_force_inline uint32_t RingCount(uintptr_t begin, uintptr_t end)+ {+ // wrap-around safe: all unsigned+ uintptr_t count = end - begin;+ return static_cast<uint32_t>(count);+ }++ tracy_force_inline uint32_t NextQueryId()+ {+ auto id = m_queryCounter++;+ if (RingCount(m_previousCheckpoint, id) >= MaxQueries)+ {+ TracyD3D11Panic("too many pending timestamp queries.");+ // #TODO: return some sentinel value; ideally a "hidden" query index+ }+ return RingIndex(id);+ }++ tracy_force_inline ID3D11Query* GetQueryObjectFromId(uint32_t id)+ {+ return m_queries[id];+ }++ tracy_force_inline void WaitForQuery(ID3D11Query* query)+ {+ m_immediateDevCtx->Flush();+ while (m_immediateDevCtx->GetData(query, nullptr, 0, 0) != S_OK)+ YieldThread(); // busy-wait :-( attempt to reduce power usage with _mm_pause() & friends...+ }++ tracy_force_inline uint8_t GetContextId() const+ {+ return m_contextId;+ }++ ID3D11Device* m_device = nullptr;+ ID3D11DeviceContext* m_immediateDevCtx = nullptr;++ ID3D11Query* m_queries[MaxQueries];+ ID3D11Query* m_disjointQuery = nullptr;++ uint8_t m_contextId = 255; // NOTE: apparently, 255 means invalid id; is this documented anywhere?++ uintptr_t m_queryCounter = 0;++ uintptr_t m_previousCheckpoint = 0;+ uintptr_t m_nextCheckpoint = 0;+};++class D3D11ZoneScope+{+public:+ tracy_force_inline D3D11ZoneScope( D3D11Ctx* ctx, const SourceLocationData* srcloc, bool active )+ : D3D11ZoneScope(ctx, active)+ {+ if( !m_active ) return;++ auto* item = Profiler::QueueSerial();+ WriteQueueItem(item, QueueType::GpuZoneBeginSerial, reinterpret_cast<uint64_t>(srcloc));+ }++ tracy_force_inline D3D11ZoneScope( D3D11Ctx* ctx, const SourceLocationData* srcloc, int32_t depth, bool active )+ : D3D11ZoneScope(ctx, active)+ {+ if( !m_active ) return;++ if( depth > 0 && has_callstack() )+ {+ auto* item = Profiler::QueueSerialCallstack(Callstack(depth));+ WriteQueueItem(item, QueueType::GpuZoneBeginCallstackSerial, reinterpret_cast<uint64_t>(srcloc));+ }+ else+ {+ auto* item = Profiler::QueueSerial();+ WriteQueueItem(item, QueueType::GpuZoneBeginSerial, reinterpret_cast<uint64_t>(srcloc));+ }+ }++ tracy_force_inline D3D11ZoneScope(D3D11Ctx* ctx, uint32_t line, const char* source, size_t sourceSz, const char* function, size_t functionSz, const char* name, size_t nameSz, bool active)+ : D3D11ZoneScope(ctx, active)+ {+ if( !m_active ) return;++ const auto sourceLocation = Profiler::AllocSourceLocation(line, source, sourceSz, function, functionSz, name, nameSz);++ auto* item = Profiler::QueueSerial();+ WriteQueueItem(item, QueueType::GpuZoneBeginAllocSrcLocSerial, sourceLocation);+ }++ tracy_force_inline D3D11ZoneScope(D3D11Ctx* ctx, uint32_t line, const char* source, size_t sourceSz, const char* function, size_t functionSz, const char* name, size_t nameSz, int32_t depth, bool active)+ : D3D11ZoneScope(ctx, active)+ {+ if( !m_active ) return;++ const auto sourceLocation = Profiler::AllocSourceLocation(line, source, sourceSz, function, functionSz, name, nameSz);++ if ( depth > 0 && has_callstack() )+ {+ auto* item = Profiler::QueueSerialCallstack(Callstack(depth));+ WriteQueueItem(item, QueueType::GpuZoneBeginAllocSrcLocCallstackSerial, sourceLocation);+ }+ else+ {+ auto* item = Profiler::QueueSerial();+ WriteQueueItem(item, QueueType::GpuZoneBeginAllocSrcLocSerial, sourceLocation);+ }+ }++ tracy_force_inline ~D3D11ZoneScope()+ {+ if( !m_active ) return;++ const auto queryId = m_ctx->NextQueryId();+ m_ctx->m_immediateDevCtx->End(m_ctx->GetQueryObjectFromId(queryId));++ auto* item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::GpuZoneEndSerial );+ MemWrite( &item->gpuZoneEnd.cpuTime, Profiler::GetTime() );+ MemWrite( &item->gpuZoneEnd.thread, GetThreadHandle() );+ MemWrite( &item->gpuZoneEnd.queryId, uint16_t( queryId ) );+ MemWrite( &item->gpuZoneEnd.context, m_ctx->GetContextId() );+ Profiler::QueueSerialFinish();+ }++private:+ tracy_force_inline D3D11ZoneScope( D3D11Ctx* ctx, bool active )+#ifdef TRACY_ON_DEMAND+ : m_active( active && GetProfiler().IsConnected() )+#else+ : m_active( active )+#endif+ {+ if( !m_active ) return;+ m_ctx = ctx;+ }++ void WriteQueueItem(tracy::QueueItem* item, tracy::QueueType queueItemType, uint64_t sourceLocation)+ {+ const auto queryId = m_ctx->NextQueryId();+ m_ctx->m_immediateDevCtx->End(m_ctx->GetQueryObjectFromId(queryId));++ MemWrite( &item->hdr.type, queueItemType);+ MemWrite( &item->gpuZoneBegin.cpuTime, Profiler::GetTime() );+ MemWrite( &item->gpuZoneBegin.srcloc, sourceLocation );+ MemWrite( &item->gpuZoneBegin.thread, GetThreadHandle() );+ MemWrite( &item->gpuZoneBegin.queryId, uint16_t( queryId ) );+ MemWrite( &item->gpuZoneBegin.context, m_ctx->GetContextId() );+ Profiler::QueueSerialFinish();+ }++ const bool m_active;++ D3D11Ctx* m_ctx;+};++static inline D3D11Ctx* CreateD3D11Context( ID3D11Device* device, ID3D11DeviceContext* devicectx )+{+ auto ctx = (D3D11Ctx*)tracy_malloc( sizeof( D3D11Ctx ) );+ new(ctx) D3D11Ctx( device, devicectx );+ return ctx;+}++static inline void DestroyD3D11Context( D3D11Ctx* ctx )+{+ ctx->~D3D11Ctx();+ tracy_free( ctx );+}+}++#undef TracyD3D11Panic++using TracyD3D11Ctx = tracy::D3D11Ctx*;++#define TracyD3D11Context( device, devicectx ) tracy::CreateD3D11Context( device, devicectx );+#define TracyD3D11Destroy(ctx) tracy::DestroyD3D11Context(ctx);+#define TracyD3D11ContextName(ctx, name, size) ctx->Name(name, size);++#define TracyD3D11UnnamedZone ___tracy_gpu_d3d11_zone+#define TracyD3D11SrcLocSymbol TracyConcat(__tracy_gpu_d3d11_source_location,TracyLine)+#define TracyD3D11SrcLocObject(name, color) static constexpr tracy::SourceLocationData TracyD3D11SrcLocSymbol { name, TracyFunction, TracyFile, (uint32_t)TracyLine, color };++#if defined TRACY_HAS_CALLSTACK && defined TRACY_CALLSTACK+# define TracyD3D11Zone( ctx, name ) TracyD3D11NamedZoneS( ctx, TracyD3D11UnnamedZone, name, TRACY_CALLSTACK, true )+# define TracyD3D11ZoneC( ctx, name, color ) TracyD3D11NamedZoneCS( ctx, TracyD3D11UnnamedZone, name, color, TRACY_CALLSTACK, true )+# define TracyD3D11NamedZone( ctx, varname, name, active ) TracyD3D11SrcLocObject(name, 0); tracy::D3D11ZoneScope varname( ctx, &TracyD3D11SrcLocSymbol, TRACY_CALLSTACK, active );+# define TracyD3D11NamedZoneC( ctx, varname, name, color, active ) TracyD3D11SrcLocObject(name, color); tracy::D3D11ZoneScope varname( ctx, &TracyD3D11SrcLocSymbol, TRACY_CALLSTACK, active );+# define TracyD3D11ZoneTransient(ctx, varname, name, active) TracyD3D11ZoneTransientS(ctx, varname, cmdList, name, TRACY_CALLSTACK, active)+#else+# define TracyD3D11Zone( ctx, name ) TracyD3D11NamedZone( ctx, TracyD3D11UnnamedZone, name, true )+# define TracyD3D11ZoneC( ctx, name, color ) TracyD3D11NamedZoneC( ctx, TracyD3D11UnnamedZone, name, color, true )+# define TracyD3D11NamedZone( ctx, varname, name, active ) TracyD3D11SrcLocObject(name, 0); tracy::D3D11ZoneScope varname( ctx, &TracyD3D11SrcLocSymbol, active );+# define TracyD3D11NamedZoneC( ctx, varname, name, color, active ) TracyD3D11SrcLocObject(name, color); tracy::D3D11ZoneScope varname( ctx, &TracyD3D11SrcLocSymbol, active );+# define TracyD3D11ZoneTransient(ctx, varname, name, active) tracy::D3D11ZoneScope varname{ ctx, TracyLine, TracyFile, strlen(TracyFile), TracyFunction, strlen(TracyFunction), name, strlen(name), active };+#endif++#ifdef TRACY_HAS_CALLSTACK+# define TracyD3D11ZoneS( ctx, name, depth ) TracyD3D11NamedZoneS( ctx, TracyD3D11UnnamedZone, name, depth, true )+# define TracyD3D11ZoneCS( ctx, name, color, depth ) TracyD3D11NamedZoneCS( ctx, TracyD3D11UnnamedZone, name, color, depth, true )+# define TracyD3D11NamedZoneS( ctx, varname, name, depth, active ) TracyD3D11SrcLocObject(name, 0); tracy::D3D11ZoneScope varname( ctx, &TracyD3D11SrcLocSymbol, depth, active );+# define TracyD3D11NamedZoneCS( ctx, varname, name, color, depth, active ) TracyD3D11SrcLocObject(name, color); tracy::D3D11ZoneScope varname( ctx, &TracyD3D11SrcLocSymbol, depth, active );+# define TracyD3D11ZoneTransientS(ctx, varname, name, depth, active) tracy::D3D11ZoneScope varname{ ctx, TracyLine, TracyFile, strlen(TracyFile), TracyFunction, strlen(TracyFunction), name, strlen(name), depth, active };+#else+# define TracyD3D11ZoneS( ctx, name, depth, active ) TracyD3D11Zone( ctx, name )+# define TracyD3D11ZoneCS( ctx, name, color, depth, active ) TracyD3D11ZoneC( name, color )+# define TracyD3D11NamedZoneS( ctx, varname, name, depth, active ) TracyD3D11NamedZone( ctx, varname, name, active )+# define TracyD3D11NamedZoneCS( ctx, varname, name, color, depth, active ) TracyD3D11NamedZoneC( ctx, varname, name, color, active )+# define TracyD3D11ZoneTransientS(ctx, varname, name, depth, active) TracyD3D11ZoneTransient(ctx, varname, name, active)+#endif++#define TracyD3D11Collect( ctx ) ctx->Collect();++#endif++#endif
+ cbits/tracy/public/tracy/TracyD3D12.hpp view
@@ -0,0 +1,500 @@+#ifndef __TRACYD3D12_HPP__+#define __TRACYD3D12_HPP__++#ifndef TRACY_ENABLE++#define TracyD3D12Context(device, queue) nullptr+#define TracyD3D12Destroy(ctx)+#define TracyD3D12ContextName(ctx, name, size)++#define TracyD3D12NewFrame(ctx)++#define TracyD3D12Zone(ctx, cmdList, name)+#define TracyD3D12ZoneC(ctx, cmdList, name, color)+#define TracyD3D12NamedZone(ctx, varname, cmdList, name, active)+#define TracyD3D12NamedZoneC(ctx, varname, cmdList, name, color, active)+#define TracyD3D12ZoneTransient(ctx, varname, cmdList, name, active)++#define TracyD3D12ZoneS(ctx, cmdList, name, depth)+#define TracyD3D12ZoneCS(ctx, cmdList, name, color, depth)+#define TracyD3D12NamedZoneS(ctx, varname, cmdList, name, depth, active)+#define TracyD3D12NamedZoneCS(ctx, varname, cmdList, name, color, depth, active)+#define TracyD3D12ZoneTransientS(ctx, varname, cmdList, name, depth, active)++#define TracyD3D12Collect(ctx)++namespace tracy+{+ class D3D12ZoneScope {};+}++using TracyD3D12Ctx = void*;++#else++#include "Tracy.hpp"+#include "../client/TracyProfiler.hpp"+#include "../client/TracyCallstack.hpp"++#include <cstdlib>+#include <cassert>+#include <d3d12.h>+#include <dxgi.h>+#include <queue>++#define TracyD3D12Panic(msg, ...) do { assert(false && "TracyD3D12: " msg); TracyMessageLC("TracyD3D12: " msg, tracy::Color::Red4); __VA_ARGS__; } while(false);++namespace tracy+{++ struct D3D12QueryPayload+ {+ uint32_t m_queryIdStart = 0;+ uint32_t m_queryCount = 0;+ };++ // Command queue context.+ class D3D12QueueCtx+ {+ friend class D3D12ZoneScope;++ ID3D12Device* m_device = nullptr;+ ID3D12CommandQueue* m_queue = nullptr;+ uint8_t m_contextId = 255; // TODO: apparently, 255 means "invalid id"; is this documented somewhere?+ ID3D12QueryHeap* m_queryHeap = nullptr;+ ID3D12Resource* m_readbackBuffer = nullptr;++ // In-progress payload.+ uint32_t m_queryLimit = 0;+ std::atomic<uint32_t> m_queryCounter = 0;+ uint32_t m_previousQueryCounter = 0;++ uint32_t m_activePayload = 0;+ ID3D12Fence* m_payloadFence = nullptr;+ std::queue<D3D12QueryPayload> m_payloadQueue;++ UINT64 m_prevCalibrationTicksCPU = 0;++ void RecalibrateClocks()+ {+ UINT64 cpuTimestamp;+ UINT64 gpuTimestamp;+ if (FAILED(m_queue->GetClockCalibration(&gpuTimestamp, &cpuTimestamp)))+ {+ TracyD3D12Panic("failed to obtain queue clock calibration counters.", return);+ }++ int64_t cpuDeltaTicks = cpuTimestamp - m_prevCalibrationTicksCPU;+ if (cpuDeltaTicks > 0)+ {+ static const int64_t nanosecodsPerTick = int64_t(1000000000) / GetFrequencyQpc();+ int64_t cpuDeltaNS = cpuDeltaTicks * nanosecodsPerTick;+ // Save the device cpu timestamp, not the Tracy profiler timestamp:+ m_prevCalibrationTicksCPU = cpuTimestamp;++ cpuTimestamp = Profiler::GetTime();++ auto* item = Profiler::QueueSerial();+ MemWrite(&item->hdr.type, QueueType::GpuCalibration);+ MemWrite(&item->gpuCalibration.gpuTime, gpuTimestamp);+ MemWrite(&item->gpuCalibration.cpuTime, cpuTimestamp);+ MemWrite(&item->gpuCalibration.cpuDelta, cpuDeltaNS);+ MemWrite(&item->gpuCalibration.context, GetId());+ SubmitQueueItem(item);+ }+ }++ tracy_force_inline void SubmitQueueItem(tracy::QueueItem* item)+ {+#ifdef TRACY_ON_DEMAND+ GetProfiler().DeferItem(*item);+#endif+ Profiler::QueueSerialFinish();+ }++ public:+ D3D12QueueCtx(ID3D12Device* device, ID3D12CommandQueue* queue)+ : m_device(device)+ , m_queue(queue)+ {+ // Verify we support timestamp queries on this queue.++ if (queue->GetDesc().Type == D3D12_COMMAND_LIST_TYPE_COPY)+ {+ D3D12_FEATURE_DATA_D3D12_OPTIONS3 featureData{};++ HRESULT hr = device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS3, &featureData, sizeof(featureData));+ if (FAILED(hr) || (featureData.CopyQueueTimestampQueriesSupported == FALSE))+ {+ TracyD3D12Panic("Platform does not support profiling of copy queues.", return);+ }+ }++ static constexpr uint32_t MaxQueries = 64 * 1024; // Must be even, because queries are (begin, end) pairs+ m_queryLimit = MaxQueries;++ D3D12_QUERY_HEAP_DESC heapDesc{};+ heapDesc.Type = queue->GetDesc().Type == D3D12_COMMAND_LIST_TYPE_COPY ? D3D12_QUERY_HEAP_TYPE_COPY_QUEUE_TIMESTAMP : D3D12_QUERY_HEAP_TYPE_TIMESTAMP;+ heapDesc.Count = m_queryLimit;+ heapDesc.NodeMask = 0; // #TODO: Support multiple adapters.++ while (FAILED(device->CreateQueryHeap(&heapDesc, IID_PPV_ARGS(&m_queryHeap))))+ {+ m_queryLimit /= 2;+ heapDesc.Count = m_queryLimit;+ }++ // Create a readback buffer, which will be used as a destination for the query data.++ D3D12_RESOURCE_DESC readbackBufferDesc{};+ readbackBufferDesc.Alignment = 0;+ readbackBufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;+ readbackBufferDesc.Width = m_queryLimit * sizeof(uint64_t);+ readbackBufferDesc.Height = 1;+ readbackBufferDesc.DepthOrArraySize = 1;+ readbackBufferDesc.Format = DXGI_FORMAT_UNKNOWN;+ readbackBufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; // Buffers are always row major.+ readbackBufferDesc.MipLevels = 1;+ readbackBufferDesc.SampleDesc.Count = 1;+ readbackBufferDesc.SampleDesc.Quality = 0;+ readbackBufferDesc.Flags = D3D12_RESOURCE_FLAG_NONE;++ D3D12_HEAP_PROPERTIES readbackHeapProps{};+ readbackHeapProps.Type = D3D12_HEAP_TYPE_READBACK;+ readbackHeapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;+ readbackHeapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;+ readbackHeapProps.CreationNodeMask = 0;+ readbackHeapProps.VisibleNodeMask = 0; // #TODO: Support multiple adapters.++ if (FAILED(device->CreateCommittedResource(&readbackHeapProps, D3D12_HEAP_FLAG_NONE, &readbackBufferDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&m_readbackBuffer))))+ {+ TracyD3D12Panic("Failed to create query readback buffer.", return);+ }++ if (FAILED(device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_payloadFence))))+ {+ TracyD3D12Panic("Failed to create payload fence.", return);+ }++ float period = [queue]()+ {+ uint64_t timestampFrequency;+ if (FAILED(queue->GetTimestampFrequency(×tampFrequency)))+ {+ return 0.0f;+ }+ return static_cast<float>( 1E+09 / static_cast<double>(timestampFrequency) );+ }();++ if (period == 0.0f)+ {+ TracyD3D12Panic("Failed to get timestamp frequency.", return);+ }++ uint64_t cpuTimestamp;+ uint64_t gpuTimestamp;+ if (FAILED(queue->GetClockCalibration(&gpuTimestamp, &cpuTimestamp)))+ {+ TracyD3D12Panic("Failed to get queue clock calibration.", return);+ }++ // Save the device cpu timestamp, not the profiler's timestamp.+ m_prevCalibrationTicksCPU = cpuTimestamp;++ cpuTimestamp = Profiler::GetTime();++ // all checked: ready to roll+ m_contextId = GetGpuCtxCounter().fetch_add(1);++ auto* item = Profiler::QueueSerial();+ MemWrite(&item->hdr.type, QueueType::GpuNewContext);+ MemWrite(&item->gpuNewContext.cpuTime, cpuTimestamp);+ MemWrite(&item->gpuNewContext.gpuTime, gpuTimestamp);+ MemWrite(&item->gpuNewContext.thread, decltype(item->gpuNewContext.thread)(0)); // #TODO: why 0 instead of GetThreadHandle()?+ MemWrite(&item->gpuNewContext.period, period);+ MemWrite(&item->gpuNewContext.context, GetId());+ MemWrite(&item->gpuNewContext.flags, GpuContextCalibration);+ MemWrite(&item->gpuNewContext.type, GpuContextType::Direct3D12);+ SubmitQueueItem(item);+ }++ ~D3D12QueueCtx()+ {+ ZoneScopedC(Color::Red4);+ // collect all pending timestamps+ while (m_payloadFence->GetCompletedValue() != m_activePayload)+ /* busy-wait ... */;+ Collect();+ m_payloadFence->Release();+ m_readbackBuffer->Release();+ m_queryHeap->Release();+ }+++ void NewFrame()+ {+ uint32_t queryCounter = m_queryCounter.exchange(0);+ m_payloadQueue.emplace(D3D12QueryPayload{ m_previousQueryCounter, queryCounter });+ m_previousQueryCounter += queryCounter;++ if (m_previousQueryCounter >= m_queryLimit)+ {+ m_previousQueryCounter -= m_queryLimit;+ }++ m_queue->Signal(m_payloadFence, ++m_activePayload);+ }++ void Name( const char* name, uint16_t len )+ {+ auto ptr = (char*)tracy_malloc( len );+ memcpy( ptr, name, len );++ auto item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::GpuContextName );+ MemWrite( &item->gpuContextNameFat.context, GetId());+ MemWrite( &item->gpuContextNameFat.ptr, (uint64_t)ptr );+ MemWrite( &item->gpuContextNameFat.size, len );+ SubmitQueueItem(item);+ }++ void Collect()+ {+ ZoneScopedC(Color::Red4);++#ifdef TRACY_ON_DEMAND+ if (!GetProfiler().IsConnected())+ {+ m_queryCounter = 0;++ return;+ }+#endif++ // Find out what payloads are available.+ const auto newestReadyPayload = m_payloadFence->GetCompletedValue();+ const auto payloadCount = m_payloadQueue.size() - (m_activePayload - newestReadyPayload);++ if (!payloadCount)+ {+ return; // No payloads are available yet, exit out.+ }++ D3D12_RANGE mapRange{ 0, m_queryLimit * sizeof(uint64_t) };++ // Map the readback buffer so we can fetch the query data from the GPU.+ void* readbackBufferMapping = nullptr;++ if (FAILED(m_readbackBuffer->Map(0, &mapRange, &readbackBufferMapping)))+ {+ TracyD3D12Panic("Failed to map readback buffer.", return);+ }++ auto* timestampData = static_cast<uint64_t*>(readbackBufferMapping);++ for (uint32_t i = 0; i < payloadCount; ++i)+ {+ const auto& payload = m_payloadQueue.front();++ for (uint32_t j = 0; j < payload.m_queryCount; ++j)+ {+ const auto counter = (payload.m_queryIdStart + j) % m_queryLimit;+ const auto timestamp = timestampData[counter];+ const auto queryId = counter;++ auto* item = Profiler::QueueSerial();+ MemWrite(&item->hdr.type, QueueType::GpuTime);+ MemWrite(&item->gpuTime.gpuTime, timestamp);+ MemWrite(&item->gpuTime.queryId, static_cast<uint16_t>(queryId));+ MemWrite(&item->gpuTime.context, GetId());++ Profiler::QueueSerialFinish();+ }++ m_payloadQueue.pop();+ }++ m_readbackBuffer->Unmap(0, nullptr);++ // Recalibrate to account for drift.+ RecalibrateClocks();+ }++ private:+ tracy_force_inline uint32_t NextQueryId()+ {+ uint32_t queryCounter = m_queryCounter.fetch_add(2);+ if (queryCounter >= m_queryLimit)+ {+ TracyD3D12Panic("Submitted too many GPU queries! Consider increasing MaxQueries.");+ // #TODO: consider returning an invalid id or sentinel value here+ }++ const uint32_t id = (m_previousQueryCounter + queryCounter) % m_queryLimit;++ return id;+ }++ tracy_force_inline uint8_t GetId() const+ {+ return m_contextId;+ }+ };++ class D3D12ZoneScope+ {+ const bool m_active;+ D3D12QueueCtx* m_ctx = nullptr;+ ID3D12GraphicsCommandList* m_cmdList = nullptr;+ uint32_t m_queryId = 0; // Used for tracking in nested zones.++ tracy_force_inline void WriteQueueItem(QueueItem* item, QueueType type, uint64_t srcLocation)+ {+ MemWrite(&item->hdr.type, type);+ MemWrite(&item->gpuZoneBegin.cpuTime, Profiler::GetTime());+ MemWrite(&item->gpuZoneBegin.srcloc, srcLocation);+ MemWrite(&item->gpuZoneBegin.thread, GetThreadHandle());+ MemWrite(&item->gpuZoneBegin.queryId, static_cast<uint16_t>(m_queryId));+ MemWrite(&item->gpuZoneBegin.context, m_ctx->GetId());+ Profiler::QueueSerialFinish();+ }++ tracy_force_inline D3D12ZoneScope(D3D12QueueCtx* ctx, ID3D12GraphicsCommandList* cmdList, bool active)+#ifdef TRACY_ON_DEMAND+ : m_active(active&& GetProfiler().IsConnected())+#else+ : m_active(active)+#endif+ {+ if (!m_active) return;++ m_ctx = ctx;+ m_cmdList = cmdList;++ m_queryId = m_ctx->NextQueryId();+ m_cmdList->EndQuery(m_ctx->m_queryHeap, D3D12_QUERY_TYPE_TIMESTAMP, m_queryId);+ }++ public:+ tracy_force_inline D3D12ZoneScope(D3D12QueueCtx* ctx, ID3D12GraphicsCommandList* cmdList, const SourceLocationData* srcLocation, bool active)+ : D3D12ZoneScope(ctx, cmdList, active)+ {+ if (!m_active) return;++ auto* item = Profiler::QueueSerial();+ WriteQueueItem(item, QueueType::GpuZoneBeginSerial, reinterpret_cast<uint64_t>(srcLocation));+ }++ tracy_force_inline D3D12ZoneScope(D3D12QueueCtx* ctx, ID3D12GraphicsCommandList* cmdList, const SourceLocationData* srcLocation, int32_t depth, bool active)+ : D3D12ZoneScope(ctx, cmdList, active)+ {+ if (!m_active) return;++ auto* item = Profiler::QueueSerialCallstack(Callstack(depth));+ WriteQueueItem(item, QueueType::GpuZoneBeginCallstackSerial, reinterpret_cast<uint64_t>(srcLocation));+ }++ tracy_force_inline D3D12ZoneScope(D3D12QueueCtx* ctx, uint32_t line, const char* source, size_t sourceSz, const char* function, size_t functionSz, const char* name, size_t nameSz, ID3D12GraphicsCommandList* cmdList, bool active)+ : D3D12ZoneScope(ctx, cmdList, active)+ {+ if (!m_active) return;++ const auto sourceLocation = Profiler::AllocSourceLocation(line, source, sourceSz, function, functionSz, name, nameSz);++ auto* item = Profiler::QueueSerial();+ WriteQueueItem(item, QueueType::GpuZoneBeginAllocSrcLocSerial, sourceLocation);+ }++ tracy_force_inline D3D12ZoneScope(D3D12QueueCtx* ctx, uint32_t line, const char* source, size_t sourceSz, const char* function, size_t functionSz, const char* name, size_t nameSz, ID3D12GraphicsCommandList* cmdList, int32_t depth, bool active)+ : D3D12ZoneScope(ctx, cmdList, active)+ {+ if (!m_active) return;++ const auto sourceLocation = Profiler::AllocSourceLocation(line, source, sourceSz, function, functionSz, name, nameSz);++ auto* item = Profiler::QueueSerialCallstack(Callstack(depth));+ WriteQueueItem(item, QueueType::GpuZoneBeginAllocSrcLocCallstackSerial, sourceLocation);+ }++ tracy_force_inline ~D3D12ZoneScope()+ {+ if (!m_active) return;++ const auto queryId = m_queryId + 1; // Our end query slot is immediately after the begin slot.+ m_cmdList->EndQuery(m_ctx->m_queryHeap, D3D12_QUERY_TYPE_TIMESTAMP, queryId);++ auto* item = Profiler::QueueSerial();+ MemWrite(&item->hdr.type, QueueType::GpuZoneEndSerial);+ MemWrite(&item->gpuZoneEnd.cpuTime, Profiler::GetTime());+ MemWrite(&item->gpuZoneEnd.thread, GetThreadHandle());+ MemWrite(&item->gpuZoneEnd.queryId, static_cast<uint16_t>(queryId));+ MemWrite(&item->gpuZoneEnd.context, m_ctx->GetId());+ Profiler::QueueSerialFinish();++ m_cmdList->ResolveQueryData(m_ctx->m_queryHeap, D3D12_QUERY_TYPE_TIMESTAMP, m_queryId, 2, m_ctx->m_readbackBuffer, m_queryId * sizeof(uint64_t));+ }+ };++ static inline D3D12QueueCtx* CreateD3D12Context(ID3D12Device* device, ID3D12CommandQueue* queue)+ {+ auto* ctx = static_cast<D3D12QueueCtx*>(tracy_malloc(sizeof(D3D12QueueCtx)));+ new (ctx) D3D12QueueCtx{ device, queue };++ return ctx;+ }++ static inline void DestroyD3D12Context(D3D12QueueCtx* ctx)+ {+ ctx->~D3D12QueueCtx();+ tracy_free(ctx);+ }++}++#undef TracyD3D12Panic++using TracyD3D12Ctx = tracy::D3D12QueueCtx*;++#define TracyD3D12Context(device, queue) tracy::CreateD3D12Context(device, queue);+#define TracyD3D12Destroy(ctx) tracy::DestroyD3D12Context(ctx);+#define TracyD3D12ContextName(ctx, name, size) ctx->Name(name, size);++#define TracyD3D12NewFrame(ctx) ctx->NewFrame();++#define TracyD3D12UnnamedZone ___tracy_gpu_d3d12_zone+#define TracyD3D12SrcLocSymbol TracyConcat(__tracy_d3d12_source_location,TracyLine)+#define TracyD3D12SrcLocObject(name, color) static constexpr tracy::SourceLocationData TracyD3D12SrcLocSymbol { name, TracyFunction, TracyFile, (uint32_t)TracyLine, color };++#if defined TRACY_HAS_CALLSTACK && defined TRACY_CALLSTACK+# define TracyD3D12Zone(ctx, cmdList, name) TracyD3D12NamedZoneS(ctx, TracyD3D12UnnamedZone, cmdList, name, TRACY_CALLSTACK, true)+# define TracyD3D12ZoneC(ctx, cmdList, name, color) TracyD3D12NamedZoneCS(ctx, TracyD3D12UnnamedZone, cmdList, name, color, TRACY_CALLSTACK, true)+# define TracyD3D12NamedZone(ctx, varname, cmdList, name, active) TracyD3D12SrcLocObject(name, 0); tracy::D3D12ZoneScope varname{ ctx, cmdList, &TracyD3D12SrcLocSymbol, TRACY_CALLSTACK, active };+# define TracyD3D12NamedZoneC(ctx, varname, cmdList, name, color, active) TracyD3D12SrcLocObject(name, color); tracy::D3D12ZoneScope varname{ ctx, cmdList, &TracyD3D12SrcLocSymbol, TRACY_CALLSTACK, active };+# define TracyD3D12ZoneTransient(ctx, varname, cmdList, name, active) TracyD3D12ZoneTransientS(ctx, varname, cmdList, name, TRACY_CALLSTACK, active)+#else+# define TracyD3D12Zone(ctx, cmdList, name) TracyD3D12NamedZone(ctx, TracyD3D12UnnamedZone, cmdList, name, true)+# define TracyD3D12ZoneC(ctx, cmdList, name, color) TracyD3D12NamedZoneC(ctx, TracyD3D12UnnamedZone, cmdList, name, color, true)+# define TracyD3D12NamedZone(ctx, varname, cmdList, name, active) TracyD3D12SrcLocObject(name, 0); tracy::D3D12ZoneScope varname{ ctx, cmdList, &TracyD3D12SrcLocSymbol, active };+# define TracyD3D12NamedZoneC(ctx, varname, cmdList, name, color, active) TracyD3D12SrcLocObject(name, color); tracy::D3D12ZoneScope varname{ ctx, cmdList, &TracyD3D12SrcLocSymbol, active };+# define TracyD3D12ZoneTransient(ctx, varname, cmdList, name, active) tracy::D3D12ZoneScope varname{ ctx, TracyLine, TracyFile, strlen(TracyFile), TracyFunction, strlen(TracyFunction), name, strlen(name), cmdList, active };+#endif++#ifdef TRACY_HAS_CALLSTACK+# define TracyD3D12ZoneS(ctx, cmdList, name, depth) TracyD3D12NamedZoneS(ctx, TracyD3D12UnnamedZone, cmdList, name, depth, true)+# define TracyD3D12ZoneCS(ctx, cmdList, name, color, depth) TracyD3D12NamedZoneCS(ctx, TracyD3D12UnnamedZone, cmdList, name, color, depth, true)+# define TracyD3D12NamedZoneS(ctx, varname, cmdList, name, depth, active) TracyD3D12SrcLocObject(name, 0); tracy::D3D12ZoneScope varname{ ctx, cmdList, &TracyD3D12SrcLocSymbol, depth, active };+# define TracyD3D12NamedZoneCS(ctx, varname, cmdList, name, color, depth, active) TracyD3D12SrcLocObject(name, color); tracy::D3D12ZoneScope varname{ ctx, cmdList, &TracyD3D12SrcLocSymbol, depth, active };+# define TracyD3D12ZoneTransientS(ctx, varname, cmdList, name, depth, active) tracy::D3D12ZoneScope varname{ ctx, TracyLine, TracyFile, strlen(TracyFile), TracyFunction, strlen(TracyFunction), name, strlen(name), cmdList, depth, active };+#else+# define TracyD3D12ZoneS(ctx, cmdList, name, depth) TracyD3D12Zone(ctx, cmdList, name)+# define TracyD3D12ZoneCS(ctx, cmdList, name, color, depth) TracyD3D12Zone(ctx, cmdList, name, color)+# define TracyD3D12NamedZoneS(ctx, varname, cmdList, name, depth, active) TracyD3D12NamedZone(ctx, varname, cmdList, name, active)+# define TracyD3D12NamedZoneCS(ctx, varname, cmdList, name, color, depth, active) TracyD3D12NamedZoneC(ctx, varname, cmdList, name, color, active)+# define TracyD3D12ZoneTransientS(ctx, varname, cmdList, name, depth, active) TracyD3D12ZoneTransient(ctx, varname, cmdList, name, active)+#endif++#define TracyD3D12Collect(ctx) ctx->Collect();++#endif++#endif
+ cbits/tracy/public/tracy/TracyLua.hpp view
@@ -0,0 +1,486 @@+#ifndef __TRACYLUA_HPP__+#define __TRACYLUA_HPP__++// Include this file after you include lua headers.++#ifndef TRACY_ENABLE++#include <string.h>++namespace tracy+{++namespace detail+{+static inline int noop( lua_State* L ) { return 0; }+}++static inline void LuaRegister( lua_State* L )+{+ lua_newtable( L );+ lua_pushcfunction( L, detail::noop );+ lua_setfield( L, -2, "ZoneBegin" );+ lua_pushcfunction( L, detail::noop );+ lua_setfield( L, -2, "ZoneBeginN" );+ lua_pushcfunction( L, detail::noop );+ lua_setfield( L, -2, "ZoneBeginS" );+ lua_pushcfunction( L, detail::noop );+ lua_setfield( L, -2, "ZoneBeginNS" );+ lua_pushcfunction( L, detail::noop );+ lua_setfield( L, -2, "ZoneEnd" );+ lua_pushcfunction( L, detail::noop );+ lua_setfield( L, -2, "ZoneText" );+ lua_pushcfunction( L, detail::noop );+ lua_setfield( L, -2, "ZoneName" );+ lua_pushcfunction( L, detail::noop );+ lua_setfield( L, -2, "Message" );+ lua_setglobal( L, "tracy" );+}++static inline char* FindEnd( char* ptr )+{+ unsigned int cnt = 1;+ while( cnt != 0 )+ {+ if( *ptr == '(' ) cnt++;+ else if( *ptr == ')' ) cnt--;+ ptr++;+ }+ return ptr;+}++static inline void LuaRemove( char* script )+{+ while( *script )+ {+ if( strncmp( script, "tracy.", 6 ) == 0 )+ {+ if( strncmp( script + 6, "Zone", 4 ) == 0 )+ {+ if( strncmp( script + 10, "End()", 5 ) == 0 )+ {+ memset( script, ' ', 15 );+ script += 15;+ }+ else if( strncmp( script + 10, "Begin()", 7 ) == 0 )+ {+ memset( script, ' ', 17 );+ script += 17;+ }+ else if( strncmp( script + 10, "Text(", 5 ) == 0 )+ {+ auto end = FindEnd( script + 15 );+ memset( script, ' ', end - script );+ script = end;+ }+ else if( strncmp( script + 10, "Name(", 5 ) == 0 )+ {+ auto end = FindEnd( script + 15 );+ memset( script, ' ', end - script );+ script = end;+ }+ else if( strncmp( script + 10, "BeginN(", 7 ) == 0 )+ {+ auto end = FindEnd( script + 17 );+ memset( script, ' ', end - script );+ script = end;+ }+ else if( strncmp( script + 10, "BeginS(", 7 ) == 0 )+ {+ auto end = FindEnd( script + 17 );+ memset( script, ' ', end - script );+ script = end;+ }+ else if( strncmp( script + 10, "BeginNS(", 8 ) == 0 )+ {+ auto end = FindEnd( script + 18 );+ memset( script, ' ', end - script );+ script = end;+ }+ else+ {+ script += 10;+ }+ }+ else if( strncmp( script + 6, "Message(", 8 ) == 0 )+ {+ auto end = FindEnd( script + 14 );+ memset( script, ' ', end - script );+ script = end;+ }+ else+ {+ script += 6;+ }+ }+ else+ {+ script++;+ }+ }+}++static inline void LuaHook( lua_State* L, lua_Debug* ar ) {}++}++#else++#include <assert.h>+#include <limits>++#include "../common/TracyColor.hpp"+#include "../common/TracyAlign.hpp"+#include "../common/TracyForceInline.hpp"+#include "../common/TracySystem.hpp"+#include "../client/TracyProfiler.hpp"++namespace tracy+{++#ifdef TRACY_ON_DEMAND+TRACY_API LuaZoneState& GetLuaZoneState();+#endif++namespace detail+{++static inline void LuaShortenSrc( char* dst, const char* src )+{+ size_t l = std::min( (size_t)255, strlen( src ) );+ memcpy( dst, src, l );+ dst[l] = 0;+}++#ifdef TRACY_HAS_CALLSTACK+static tracy_force_inline void SendLuaCallstack( lua_State* L, uint32_t depth )+{+ assert( depth <= 64 );+ lua_Debug dbg[64];+ const char* func[64];+ uint32_t fsz[64];+ uint32_t ssz[64];++ uint8_t cnt;+ uint16_t spaceNeeded = sizeof( cnt );+ for( cnt=0; cnt<depth; cnt++ )+ {+ if( lua_getstack( L, cnt+1, dbg+cnt ) == 0 ) break;+ lua_getinfo( L, "Snl", dbg+cnt );+ func[cnt] = dbg[cnt].name ? dbg[cnt].name : dbg[cnt].short_src;+ fsz[cnt] = uint32_t( strlen( func[cnt] ) );+ ssz[cnt] = uint32_t( strlen( dbg[cnt].source ) );+ spaceNeeded += fsz[cnt] + ssz[cnt];+ }+ spaceNeeded += cnt * ( 4 + 2 + 2 ); // source line, function string length, source string length++ auto ptr = (char*)tracy_malloc( spaceNeeded + 2 );+ auto dst = ptr;+ memcpy( dst, &spaceNeeded, 2 ); dst += 2;+ memcpy( dst, &cnt, 1 ); dst++;+ for( uint8_t i=0; i<cnt; i++ )+ {+ const uint32_t line = dbg[i].currentline;+ memcpy( dst, &line, 4 ); dst += 4;+ assert( fsz[i] <= (std::numeric_limits<uint16_t>::max)() );+ memcpy( dst, fsz+i, 2 ); dst += 2;+ memcpy( dst, func[i], fsz[i] ); dst += fsz[i];+ assert( ssz[i] <= (std::numeric_limits<uint16_t>::max)() );+ memcpy( dst, ssz+i, 2 ); dst += 2;+ memcpy( dst, dbg[i].source, ssz[i] ), dst += ssz[i];+ }+ assert( dst - ptr == spaceNeeded + 2 );++ TracyQueuePrepare( QueueType::CallstackAlloc );+ MemWrite( &item->callstackAllocFat.ptr, (uint64_t)ptr );+ MemWrite( &item->callstackAllocFat.nativePtr, (uint64_t)Callstack( depth ) );+ TracyQueueCommit( callstackAllocFatThread );+}++static inline int LuaZoneBeginS( lua_State* L )+{+#ifdef TRACY_ON_DEMAND+ const auto zoneCnt = GetLuaZoneState().counter++;+ if( zoneCnt != 0 && !GetLuaZoneState().active ) return 0;+ GetLuaZoneState().active = GetProfiler().IsConnected();+ if( !GetLuaZoneState().active ) return 0;+#endif++#ifdef TRACY_CALLSTACK+ const uint32_t depth = TRACY_CALLSTACK;+#else+ const auto depth = uint32_t( lua_tointeger( L, 1 ) );+#endif+ SendLuaCallstack( L, depth );++ lua_Debug dbg;+ lua_getstack( L, 1, &dbg );+ lua_getinfo( L, "Snl", &dbg );+ char src[256];+ LuaShortenSrc( src, dbg.source );+ const auto srcloc = Profiler::AllocSourceLocation( dbg.currentline, src, dbg.name ? dbg.name : dbg.short_src );++ TracyQueuePrepare( QueueType::ZoneBeginAllocSrcLocCallstack );+ MemWrite( &item->zoneBegin.time, Profiler::GetTime() );+ MemWrite( &item->zoneBegin.srcloc, srcloc );+ TracyQueueCommit( zoneBeginThread );++ return 0;+}++static inline int LuaZoneBeginNS( lua_State* L )+{+#ifdef TRACY_ON_DEMAND+ const auto zoneCnt = GetLuaZoneState().counter++;+ if( zoneCnt != 0 && !GetLuaZoneState().active ) return 0;+ GetLuaZoneState().active = GetProfiler().IsConnected();+ if( !GetLuaZoneState().active ) return 0;+#endif++#ifdef TRACY_CALLSTACK+ const uint32_t depth = TRACY_CALLSTACK;+#else+ const auto depth = uint32_t( lua_tointeger( L, 2 ) );+#endif+ SendLuaCallstack( L, depth );++ lua_Debug dbg;+ lua_getstack( L, 1, &dbg );+ lua_getinfo( L, "Snl", &dbg );+ size_t nsz;+ char src[256];+ LuaShortenSrc( src, dbg.source );+ const auto name = lua_tolstring( L, 1, &nsz );+ const auto srcloc = Profiler::AllocSourceLocation( dbg.currentline, src, dbg.name ? dbg.name : dbg.short_src, name, nsz );++ TracyQueuePrepare( QueueType::ZoneBeginAllocSrcLocCallstack );+ MemWrite( &item->zoneBegin.time, Profiler::GetTime() );+ MemWrite( &item->zoneBegin.srcloc, srcloc );+ TracyQueueCommit( zoneBeginThread );++ return 0;+}+#endif++static inline int LuaZoneBegin( lua_State* L )+{+#if defined TRACY_HAS_CALLSTACK && defined TRACY_CALLSTACK+ return LuaZoneBeginS( L );+#else+#ifdef TRACY_ON_DEMAND+ const auto zoneCnt = GetLuaZoneState().counter++;+ if( zoneCnt != 0 && !GetLuaZoneState().active ) return 0;+ GetLuaZoneState().active = GetProfiler().IsConnected();+ if( !GetLuaZoneState().active ) return 0;+#endif++ lua_Debug dbg;+ lua_getstack( L, 1, &dbg );+ lua_getinfo( L, "Snl", &dbg );+ char src[256];+ LuaShortenSrc( src, dbg.source );+ const auto srcloc = Profiler::AllocSourceLocation( dbg.currentline, src, dbg.name ? dbg.name : dbg.short_src );++ TracyQueuePrepare( QueueType::ZoneBeginAllocSrcLoc );+ MemWrite( &item->zoneBegin.time, Profiler::GetTime() );+ MemWrite( &item->zoneBegin.srcloc, srcloc );+ TracyQueueCommit( zoneBeginThread );+ return 0;+#endif+}++static inline int LuaZoneBeginN( lua_State* L )+{+#if defined TRACY_HAS_CALLSTACK && defined TRACY_CALLSTACK+ return LuaZoneBeginNS( L );+#else+#ifdef TRACY_ON_DEMAND+ const auto zoneCnt = GetLuaZoneState().counter++;+ if( zoneCnt != 0 && !GetLuaZoneState().active ) return 0;+ GetLuaZoneState().active = GetProfiler().IsConnected();+ if( !GetLuaZoneState().active ) return 0;+#endif++ lua_Debug dbg;+ lua_getstack( L, 1, &dbg );+ lua_getinfo( L, "Snl", &dbg );+ size_t nsz;+ char src[256];+ LuaShortenSrc( src, dbg.source );+ const auto name = lua_tolstring( L, 1, &nsz );+ const auto srcloc = Profiler::AllocSourceLocation( dbg.currentline, src, dbg.name ? dbg.name : dbg.short_src, name, nsz );++ TracyQueuePrepare( QueueType::ZoneBeginAllocSrcLoc );+ MemWrite( &item->zoneBegin.time, Profiler::GetTime() );+ MemWrite( &item->zoneBegin.srcloc, srcloc );+ TracyQueueCommit( zoneBeginThread );+ return 0;+#endif+}++static inline int LuaZoneEnd( lua_State* L )+{+#ifdef TRACY_ON_DEMAND+ assert( GetLuaZoneState().counter != 0 );+ GetLuaZoneState().counter--;+ if( !GetLuaZoneState().active ) return 0;+ if( !GetProfiler().IsConnected() )+ {+ GetLuaZoneState().active = false;+ return 0;+ }+#endif++ TracyQueuePrepare( QueueType::ZoneEnd );+ MemWrite( &item->zoneEnd.time, Profiler::GetTime() );+ TracyQueueCommit( zoneEndThread );+ return 0;+}++static inline int LuaZoneText( lua_State* L )+{+#ifdef TRACY_ON_DEMAND+ if( !GetLuaZoneState().active ) return 0;+ if( !GetProfiler().IsConnected() )+ {+ GetLuaZoneState().active = false;+ return 0;+ }+#endif++ auto txt = lua_tostring( L, 1 );+ const auto size = strlen( txt );+ assert( size < (std::numeric_limits<uint16_t>::max)() );++ auto ptr = (char*)tracy_malloc( size );+ memcpy( ptr, txt, size );++ TracyQueuePrepare( QueueType::ZoneText );+ MemWrite( &item->zoneTextFat.text, (uint64_t)ptr );+ MemWrite( &item->zoneTextFat.size, (uint16_t)size );+ TracyQueueCommit( zoneTextFatThread );+ return 0;+}++static inline int LuaZoneName( lua_State* L )+{+#ifdef TRACY_ON_DEMAND+ if( !GetLuaZoneState().active ) return 0;+ if( !GetProfiler().IsConnected() )+ {+ GetLuaZoneState().active = false;+ return 0;+ }+#endif++ auto txt = lua_tostring( L, 1 );+ const auto size = strlen( txt );+ assert( size < (std::numeric_limits<uint16_t>::max)() );++ auto ptr = (char*)tracy_malloc( size );+ memcpy( ptr, txt, size );++ TracyQueuePrepare( QueueType::ZoneName );+ MemWrite( &item->zoneTextFat.text, (uint64_t)ptr );+ MemWrite( &item->zoneTextFat.size, (uint16_t)size );+ TracyQueueCommit( zoneTextFatThread );+ return 0;+}++static inline int LuaMessage( lua_State* L )+{+#ifdef TRACY_ON_DEMAND+ if( !GetProfiler().IsConnected() ) return 0;+#endif++ auto txt = lua_tostring( L, 1 );+ const auto size = strlen( txt );+ assert( size < (std::numeric_limits<uint16_t>::max)() );++ auto ptr = (char*)tracy_malloc( size );+ memcpy( ptr, txt, size );++ TracyQueuePrepare( QueueType::Message );+ MemWrite( &item->messageFat.time, Profiler::GetTime() );+ MemWrite( &item->messageFat.text, (uint64_t)ptr );+ MemWrite( &item->messageFat.size, (uint16_t)size );+ TracyQueueCommit( messageFatThread );+ return 0;+}++}++static inline void LuaRegister( lua_State* L )+{+ lua_newtable( L );+ lua_pushcfunction( L, detail::LuaZoneBegin );+ lua_setfield( L, -2, "ZoneBegin" );+ lua_pushcfunction( L, detail::LuaZoneBeginN );+ lua_setfield( L, -2, "ZoneBeginN" );+#ifdef TRACY_HAS_CALLSTACK+ lua_pushcfunction( L, detail::LuaZoneBeginS );+ lua_setfield( L, -2, "ZoneBeginS" );+ lua_pushcfunction( L, detail::LuaZoneBeginNS );+ lua_setfield( L, -2, "ZoneBeginNS" );+#else+ lua_pushcfunction( L, detail::LuaZoneBegin );+ lua_setfield( L, -2, "ZoneBeginS" );+ lua_pushcfunction( L, detail::LuaZoneBeginN );+ lua_setfield( L, -2, "ZoneBeginNS" );+#endif+ lua_pushcfunction( L, detail::LuaZoneEnd );+ lua_setfield( L, -2, "ZoneEnd" );+ lua_pushcfunction( L, detail::LuaZoneText );+ lua_setfield( L, -2, "ZoneText" );+ lua_pushcfunction( L, detail::LuaZoneName );+ lua_setfield( L, -2, "ZoneName" );+ lua_pushcfunction( L, detail::LuaMessage );+ lua_setfield( L, -2, "Message" );+ lua_setglobal( L, "tracy" );+}++static inline void LuaRemove( char* script ) {}++static inline void LuaHook( lua_State* L, lua_Debug* ar )+{+ if ( ar->event == LUA_HOOKCALL )+ {+#ifdef TRACY_ON_DEMAND+ const auto zoneCnt = GetLuaZoneState().counter++;+ if ( zoneCnt != 0 && !GetLuaZoneState().active ) return;+ GetLuaZoneState().active = GetProfiler().IsConnected();+ if ( !GetLuaZoneState().active ) return;+#endif+ lua_getinfo( L, "Snl", ar );++ char src[256];+ detail::LuaShortenSrc( src, ar->short_src );++ const auto srcloc = Profiler::AllocSourceLocation( ar->currentline, src, ar->name ? ar->name : ar->short_src );+ TracyQueuePrepare( QueueType::ZoneBeginAllocSrcLoc );+ MemWrite( &item->zoneBegin.time, Profiler::GetTime() );+ MemWrite( &item->zoneBegin.srcloc, srcloc );+ TracyQueueCommit( zoneBeginThread );+ }+ else if (ar->event == LUA_HOOKRET) {+#ifdef TRACY_ON_DEMAND+ assert( GetLuaZoneState().counter != 0 );+ GetLuaZoneState().counter--;+ if ( !GetLuaZoneState().active ) return;+ if ( !GetProfiler().IsConnected() )+ {+ GetLuaZoneState().active = false;+ return;+ }+#endif+ TracyQueuePrepare( QueueType::ZoneEnd );+ MemWrite( &item->zoneEnd.time, Profiler::GetTime() );+ TracyQueueCommit( zoneEndThread );+ }+}++}++#endif++#endif
+ cbits/tracy/public/tracy/TracyOpenCL.hpp view
@@ -0,0 +1,414 @@+#ifndef __TRACYOPENCL_HPP__+#define __TRACYOPENCL_HPP__++#if !defined TRACY_ENABLE++#define TracyCLContext(c, x) nullptr+#define TracyCLDestroy(c)+#define TracyCLContextName(c, x, y)++#define TracyCLNamedZone(c, x, y, z)+#define TracyCLNamedZoneC(c, x, y, z, w)+#define TracyCLZone(c, x)+#define TracyCLZoneC(c, x, y)+#define TracyCLZoneTransient(c,x,y,z)++#define TracyCLNamedZoneS(c, x, y, z, w)+#define TracyCLNamedZoneCS(c, x, y, z, w, v)+#define TracyCLZoneS(c, x, y)+#define TracyCLZoneCS(c, x, y, z)+#define TracyCLZoneTransientS(c,x,y,z,w)++#define TracyCLNamedZoneSetEvent(x, e)+#define TracyCLZoneSetEvent(e)++#define TracyCLCollect(c)++namespace tracy+{+ class OpenCLCtxScope {};+}++using TracyCLCtx = void*;++#else++#include <CL/cl.h>++#include <atomic>+#include <cassert>+#include <sstream>++#include "Tracy.hpp"+#include "../client/TracyCallstack.hpp"+#include "../client/TracyProfiler.hpp"+#include "../common/TracyAlloc.hpp"++#define TRACY_CL_TO_STRING_INDIRECT(T) #T+#define TRACY_CL_TO_STRING(T) TRACY_CL_TO_STRING_INDIRECT(T)+#define TRACY_CL_ASSERT(p) if(!(p)) { \+ TracyMessageL( "TRACY_CL_ASSERT failed on " TracyFile ":" TRACY_CL_TO_STRING(TracyLine) ); \+ assert(false && "TRACY_CL_ASSERT failed"); \+}+#define TRACY_CL_CHECK_ERROR(err) if(err != CL_SUCCESS) { \+ std::ostringstream oss; \+ oss << "TRACY_CL_CHECK_ERROR failed on " << TracyFile << ":" << TracyLine \+ << ": error code " << err; \+ auto msg = oss.str(); \+ TracyMessage(msg.data(), msg.size()); \+ assert(false && "TRACY_CL_CHECK_ERROR failed"); \+}++namespace tracy {++ enum class EventPhase : uint8_t+ {+ Begin,+ End+ };++ struct EventInfo+ {+ cl_event event;+ EventPhase phase;+ };++ class OpenCLCtx+ {+ public:+ enum { QueryCount = 64 * 1024 };++ OpenCLCtx(cl_context context, cl_device_id device)+ : m_contextId(GetGpuCtxCounter().fetch_add(1, std::memory_order_relaxed))+ , m_head(0)+ , m_tail(0)+ {+ int64_t tcpu, tgpu;+ TRACY_CL_ASSERT(m_contextId != 255);++ cl_int err = CL_SUCCESS;+ cl_command_queue queue = clCreateCommandQueue(context, device, CL_QUEUE_PROFILING_ENABLE, &err);+ TRACY_CL_CHECK_ERROR(err)+ uint32_t dummyValue = 42;+ cl_mem dummyBuffer = clCreateBuffer(context, CL_MEM_WRITE_ONLY, sizeof(uint32_t), nullptr, &err);+ TRACY_CL_CHECK_ERROR(err)+ cl_event writeBufferEvent;+ TRACY_CL_CHECK_ERROR(clEnqueueWriteBuffer(queue, dummyBuffer, CL_FALSE, 0, sizeof(uint32_t), &dummyValue, 0, nullptr, &writeBufferEvent));+ TRACY_CL_CHECK_ERROR(clWaitForEvents(1, &writeBufferEvent));++ tcpu = Profiler::GetTime();++ cl_int eventStatus;+ TRACY_CL_CHECK_ERROR(clGetEventInfo(writeBufferEvent, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(cl_int), &eventStatus, nullptr));+ TRACY_CL_ASSERT(eventStatus == CL_COMPLETE);+ TRACY_CL_CHECK_ERROR(clGetEventProfilingInfo(writeBufferEvent, CL_PROFILING_COMMAND_END, sizeof(cl_ulong), &tgpu, nullptr));+ TRACY_CL_CHECK_ERROR(clReleaseEvent(writeBufferEvent));+ TRACY_CL_CHECK_ERROR(clReleaseMemObject(dummyBuffer));+ TRACY_CL_CHECK_ERROR(clReleaseCommandQueue(queue));++ auto item = Profiler::QueueSerial();+ MemWrite(&item->hdr.type, QueueType::GpuNewContext);+ MemWrite(&item->gpuNewContext.cpuTime, tcpu);+ MemWrite(&item->gpuNewContext.gpuTime, tgpu);+ memset(&item->gpuNewContext.thread, 0, sizeof(item->gpuNewContext.thread));+ MemWrite(&item->gpuNewContext.period, 1.0f);+ MemWrite(&item->gpuNewContext.type, GpuContextType::OpenCL);+ MemWrite(&item->gpuNewContext.context, (uint8_t) m_contextId);+ MemWrite(&item->gpuNewContext.flags, (uint8_t)0);+#ifdef TRACY_ON_DEMAND+ GetProfiler().DeferItem(*item);+#endif+ Profiler::QueueSerialFinish();+ }++ void Name( const char* name, uint16_t len )+ {+ auto ptr = (char*)tracy_malloc( len );+ memcpy( ptr, name, len );++ auto item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::GpuContextName );+ MemWrite( &item->gpuContextNameFat.context, (uint8_t)m_contextId );+ MemWrite( &item->gpuContextNameFat.ptr, (uint64_t)ptr );+ MemWrite( &item->gpuContextNameFat.size, len );+#ifdef TRACY_ON_DEMAND+ GetProfiler().DeferItem( *item );+#endif+ Profiler::QueueSerialFinish();+ }++ void Collect()+ {+ ZoneScopedC(Color::Red4);++ if (m_tail == m_head) return;++#ifdef TRACY_ON_DEMAND+ if (!GetProfiler().IsConnected())+ {+ m_head = m_tail = 0;+ }+#endif++ for (; m_tail != m_head; m_tail = (m_tail + 1) % QueryCount)+ {+ EventInfo eventInfo = GetQuery(m_tail);+ cl_int eventStatus;+ cl_int err = clGetEventInfo(eventInfo.event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(cl_int), &eventStatus, nullptr);+ if (err != CL_SUCCESS)+ {+ std::ostringstream oss;+ oss << "clGetEventInfo falied with error code " << err << ", on event " << eventInfo.event << ", skipping...";+ auto msg = oss.str();+ TracyMessage(msg.data(), msg.size());+ if (eventInfo.event == nullptr) {+ TracyMessageL("A TracyCLZone must be paird with a TracyCLZoneSetEvent, check your code!");+ }+ assert(false && "clGetEventInfo failed, maybe a TracyCLZone is not paired with TracyCLZoneSetEvent");+ continue;+ }+ if (eventStatus != CL_COMPLETE) return;++ cl_int eventInfoQuery = (eventInfo.phase == EventPhase::Begin)+ ? CL_PROFILING_COMMAND_START+ : CL_PROFILING_COMMAND_END;++ cl_ulong eventTimeStamp = 0;+ err = clGetEventProfilingInfo(eventInfo.event, eventInfoQuery, sizeof(cl_ulong), &eventTimeStamp, nullptr);+ if (err == CL_PROFILING_INFO_NOT_AVAILABLE)+ {+ TracyMessageL("command queue is not created with CL_QUEUE_PROFILING_ENABLE flag, check your code!");+ assert(false && "command queue is not created with CL_QUEUE_PROFILING_ENABLE flag");+ }+ else+ TRACY_CL_CHECK_ERROR(err);++ TRACY_CL_ASSERT(eventTimeStamp != 0);++ auto item = Profiler::QueueSerial();+ MemWrite(&item->hdr.type, QueueType::GpuTime);+ MemWrite(&item->gpuTime.gpuTime, (int64_t)eventTimeStamp);+ MemWrite(&item->gpuTime.queryId, (uint16_t)m_tail);+ MemWrite(&item->gpuTime.context, m_contextId);+ Profiler::QueueSerialFinish();++ if (eventInfo.phase == EventPhase::End)+ {+ // Done with the event, so release it+ TRACY_CL_CHECK_ERROR(clReleaseEvent(eventInfo.event));+ }+ }+ }++ tracy_force_inline uint8_t GetId() const+ {+ return m_contextId;+ }++ tracy_force_inline unsigned int NextQueryId(EventInfo eventInfo)+ {+ const auto id = m_head;+ m_head = (m_head + 1) % QueryCount;+ TRACY_CL_ASSERT(m_head != m_tail);+ m_query[id] = eventInfo;+ return id;+ }++ tracy_force_inline EventInfo& GetQuery(unsigned int id)+ {+ TRACY_CL_ASSERT(id < QueryCount);+ return m_query[id];+ }++ private:++ unsigned int m_contextId;++ EventInfo m_query[QueryCount];+ unsigned int m_head; // index at which a new event should be inserted+ unsigned int m_tail; // oldest event++ };++ class OpenCLCtxScope {+ public:+ tracy_force_inline OpenCLCtxScope(OpenCLCtx* ctx, const SourceLocationData* srcLoc, bool is_active)+#ifdef TRACY_ON_DEMAND+ : m_active(is_active&& GetProfiler().IsConnected())+#else+ : m_active(is_active)+#endif+ , m_ctx(ctx)+ , m_event(nullptr)+ {+ if (!m_active) return;++ m_beginQueryId = ctx->NextQueryId(EventInfo{ nullptr, EventPhase::Begin });++ auto item = Profiler::QueueSerial();+ MemWrite(&item->hdr.type, QueueType::GpuZoneBeginSerial);+ MemWrite(&item->gpuZoneBegin.cpuTime, Profiler::GetTime());+ MemWrite(&item->gpuZoneBegin.srcloc, (uint64_t)srcLoc);+ MemWrite(&item->gpuZoneBegin.thread, GetThreadHandle());+ MemWrite(&item->gpuZoneBegin.queryId, (uint16_t)m_beginQueryId);+ MemWrite(&item->gpuZoneBegin.context, ctx->GetId());+ Profiler::QueueSerialFinish();+ }++ tracy_force_inline OpenCLCtxScope(OpenCLCtx* ctx, const SourceLocationData* srcLoc, int32_t depth, bool is_active)+#ifdef TRACY_ON_DEMAND+ : m_active(is_active&& GetProfiler().IsConnected())+#else+ : m_active(is_active)+#endif+ , m_ctx(ctx)+ , m_event(nullptr)+ {+ if (!m_active) return;++ m_beginQueryId = ctx->NextQueryId(EventInfo{ nullptr, EventPhase::Begin });++ GetProfiler().SendCallstack(depth);++ auto item = Profiler::QueueSerial();+ MemWrite(&item->hdr.type, QueueType::GpuZoneBeginCallstackSerial);+ MemWrite(&item->gpuZoneBegin.cpuTime, Profiler::GetTime());+ MemWrite(&item->gpuZoneBegin.srcloc, (uint64_t)srcLoc);+ MemWrite(&item->gpuZoneBegin.thread, GetThreadHandle());+ MemWrite(&item->gpuZoneBegin.queryId, (uint16_t)m_beginQueryId);+ MemWrite(&item->gpuZoneBegin.context, ctx->GetId());+ Profiler::QueueSerialFinish();+ }++ tracy_force_inline OpenCLCtxScope(OpenCLCtx* ctx, uint32_t line, const char* source, size_t sourceSz, const char* function, size_t functionSz, const char* name, size_t nameSz, bool is_active)+#ifdef TRACY_ON_DEMAND+ : m_active(is_active && GetProfiler().IsConnected())+#else+ : m_active(is_active)+#endif+ , m_ctx(ctx)+ , m_event(nullptr)+ {+ if (!m_active) return;++ m_beginQueryId = ctx->NextQueryId(EventInfo{ nullptr, EventPhase::Begin });++ const auto srcloc = Profiler::AllocSourceLocation( line, source, sourceSz, function, functionSz, name, nameSz );+ auto item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::GpuZoneBeginAllocSrcLocSerial );+ MemWrite(&item->gpuZoneBegin.cpuTime, Profiler::GetTime());+ MemWrite(&item->gpuZoneBegin.srcloc, srcloc);+ MemWrite(&item->gpuZoneBegin.thread, GetThreadHandle());+ MemWrite(&item->gpuZoneBegin.queryId, (uint16_t)m_beginQueryId);+ MemWrite(&item->gpuZoneBegin.context, ctx->GetId());+ Profiler::QueueSerialFinish();+ }++ tracy_force_inline OpenCLCtxScope(OpenCLCtx* ctx, uint32_t line, const char* source, size_t sourceSz, const char* function, size_t functionSz, const char* name, size_t nameSz, int32_t depth, bool is_active)+#ifdef TRACY_ON_DEMAND+ : m_active(is_active && GetProfiler().IsConnected())+#else+ : m_active(is_active)+#endif+ , m_ctx(ctx)+ , m_event(nullptr)+ {+ if (!m_active) return;++ m_beginQueryId = ctx->NextQueryId(EventInfo{ nullptr, EventPhase::Begin });++ const auto srcloc = Profiler::AllocSourceLocation( line, source, sourceSz, function, functionSz, name, nameSz );+ auto item = Profiler::QueueSerialCallstack( Callstack( depth ) );+ MemWrite(&item->hdr.type, QueueType::GpuZoneBeginAllocSrcLocCallstackSerial);+ MemWrite(&item->gpuZoneBegin.cpuTime, Profiler::GetTime());+ MemWrite(&item->gpuZoneBegin.srcloc, srcloc);+ MemWrite(&item->gpuZoneBegin.thread, GetThreadHandle());+ MemWrite(&item->gpuZoneBegin.queryId, (uint16_t)m_beginQueryId);+ MemWrite(&item->gpuZoneBegin.context, ctx->GetId());+ Profiler::QueueSerialFinish();+ }++ tracy_force_inline void SetEvent(cl_event event)+ {+ if (!m_active) return;+ m_event = event;+ TRACY_CL_CHECK_ERROR(clRetainEvent(m_event));+ m_ctx->GetQuery(m_beginQueryId).event = m_event;+ }++ tracy_force_inline ~OpenCLCtxScope()+ {+ if (!m_active) return;+ const auto queryId = m_ctx->NextQueryId(EventInfo{ m_event, EventPhase::End });++ auto item = Profiler::QueueSerial();+ MemWrite(&item->hdr.type, QueueType::GpuZoneEndSerial);+ MemWrite(&item->gpuZoneEnd.cpuTime, Profiler::GetTime());+ MemWrite(&item->gpuZoneEnd.thread, GetThreadHandle());+ MemWrite(&item->gpuZoneEnd.queryId, (uint16_t)queryId);+ MemWrite(&item->gpuZoneEnd.context, m_ctx->GetId());+ Profiler::QueueSerialFinish();+ }++ const bool m_active;+ OpenCLCtx* m_ctx;+ cl_event m_event;+ unsigned int m_beginQueryId;+ };++ static inline OpenCLCtx* CreateCLContext(cl_context context, cl_device_id device)+ {+ auto ctx = (OpenCLCtx*)tracy_malloc(sizeof(OpenCLCtx));+ new (ctx) OpenCLCtx(context, device);+ return ctx;+ }++ static inline void DestroyCLContext(OpenCLCtx* ctx)+ {+ ctx->~OpenCLCtx();+ tracy_free(ctx);+ }++} // namespace tracy++using TracyCLCtx = tracy::OpenCLCtx*;++#define TracyCLContext(ctx, device) tracy::CreateCLContext(ctx, device);+#define TracyCLDestroy(ctx) tracy::DestroyCLContext(ctx);+#define TracyCLContextName(ctx, name, size) ctx->Name(name, size);+#if defined TRACY_HAS_CALLSTACK && defined TRACY_CALLSTACK+# define TracyCLNamedZone(ctx, varname, name, active) static constexpr tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, 0 }; tracy::OpenCLCtxScope varname(ctx, &TracyConcat(__tracy_gpu_source_location,TracyLine), TRACY_CALLSTACK, active );+# define TracyCLNamedZoneC(ctx, varname, name, color, active) static constexpr tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, color }; tracy::OpenCLCtxScope varname(ctx, &TracyConcat(__tracy_gpu_source_location,TracyLine), TRACY_CALLSTACK, active );+# define TracyCLZone(ctx, name) TracyCLNamedZoneS(ctx, __tracy_gpu_zone, name, TRACY_CALLSTACK, true)+# define TracyCLZoneC(ctx, name, color) TracyCLNamedZoneCS(ctx, __tracy_gpu_zone, name, color, TRACY_CALLSTACK, true)+# define TracyCLZoneTransient( ctx, varname, name, active ) tracy::OpenCLCtxScope varname( ctx, TracyLine, TracyFile, strlen( TracyFile ), TracyFunction, strlen( TracyFunction ), name, strlen( name ), TRACY_CALLSTACK, active );+#else+# define TracyCLNamedZone(ctx, varname, name, active) static constexpr tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,TracyLine){ name, TracyFunction, TracyFile, (uint32_t)TracyLine, 0 }; tracy::OpenCLCtxScope varname(ctx, &TracyConcat(__tracy_gpu_source_location,TracyLine), active);+# define TracyCLNamedZoneC(ctx, varname, name, color, active) static constexpr tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,TracyLine){ name, TracyFunction, TracyFile, (uint32_t)TracyLine, color }; tracy::OpenCLCtxScope varname(ctx, &TracyConcat(__tracy_gpu_source_location,TracyLine), active);+# define TracyCLZone(ctx, name) TracyCLNamedZone(ctx, __tracy_gpu_zone, name, true)+# define TracyCLZoneC(ctx, name, color) TracyCLNamedZoneC(ctx, __tracy_gpu_zone, name, color, true )+# define TracyCLZoneTransient( ctx, varname, name, active ) tracy::OpenCLCtxScope varname( ctx, TracyLine, TracyFile, strlen( TracyFile ), TracyFunction, strlen( TracyFunction ), name, strlen( name ), active );+#endif++#ifdef TRACY_HAS_CALLSTACK+# define TracyCLNamedZoneS(ctx, varname, name, depth, active) static constexpr tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,TracyLine){ name, TracyFunction, TracyFile, (uint32_t)TracyLine, 0 }; tracy::OpenCLCtxScope varname(ctx, &TracyConcat(__tracy_gpu_source_location,TracyLine), depth, active);+# define TracyCLNamedZoneCS(ctx, varname, name, color, depth, active) static constexpr tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,TracyLine){ name, TracyFunction, TracyFile, (uint32_t)TracyLine, color }; tracy::OpenCLCtxScope varname(ctx, &TracyConcat(__tracy_gpu_source_location,TracyLine), depth, active);+# define TracyCLZoneS(ctx, name, depth) TracyCLNamedZoneS(ctx, __tracy_gpu_zone, name, depth, true)+# define TracyCLZoneCS(ctx, name, color, depth) TracyCLNamedZoneCS(ctx, __tracy_gpu_zone, name, color, depth, true)+# define TracyCLZoneTransientS( ctx, varname, name, depth, active ) tracy::OpenCLCtxScope varname( ctx, TracyLine, TracyFile, strlen( TracyFile ), TracyFunction, strlen( TracyFunction ), name, strlen( name ), depth, active );+#else+# define TracyCLNamedZoneS(ctx, varname, name, depth, active) TracyCLNamedZone(ctx, varname, name, active)+# define TracyCLNamedZoneCS(ctx, varname, name, color, depth, active) TracyCLNamedZoneC(ctx, varname, name, color, active)+# define TracyCLZoneS(ctx, name, depth) TracyCLZone(ctx, name)+# define TracyCLZoneCS(ctx, name, color, depth) TracyCLZoneC(ctx, name, color)+# define TracyCLZoneTransientS( ctx, varname, name, depth, active ) TracyCLZoneTransient( ctx, varname, name, active )+#endif++#define TracyCLNamedZoneSetEvent(varname, event) varname.SetEvent(event)+#define TracyCLZoneSetEvent(event) __tracy_gpu_zone.SetEvent(event)++#define TracyCLCollect(ctx) ctx->Collect()++#endif++#endif
+ cbits/tracy/public/tracy/TracyOpenGL.hpp view
@@ -0,0 +1,325 @@+#ifndef __TRACYOPENGL_HPP__+#define __TRACYOPENGL_HPP__++#if !defined TRACY_ENABLE || defined __APPLE__++#define TracyGpuContext+#define TracyGpuContextName(x,y)+#define TracyGpuNamedZone(x,y,z)+#define TracyGpuNamedZoneC(x,y,z,w)+#define TracyGpuZone(x)+#define TracyGpuZoneC(x,y)+#define TracyGpuZoneTransient(x,y,z)+#define TracyGpuCollect++#define TracyGpuNamedZoneS(x,y,z,w)+#define TracyGpuNamedZoneCS(x,y,z,w,a)+#define TracyGpuZoneS(x,y)+#define TracyGpuZoneCS(x,y,z)+#define TracyGpuZoneTransientS(x,y,z,w)++namespace tracy+{+struct SourceLocationData;+class GpuCtxScope+{+public:+ GpuCtxScope( const SourceLocationData*, bool ) {}+ GpuCtxScope( const SourceLocationData*, int32_t, bool ) {}+};+}++#else++#include <atomic>+#include <assert.h>+#include <stdlib.h>++#include "Tracy.hpp"+#include "../client/TracyProfiler.hpp"+#include "../client/TracyCallstack.hpp"+#include "../common/TracyAlign.hpp"+#include "../common/TracyAlloc.hpp"++#if !defined GL_TIMESTAMP && defined GL_TIMESTAMP_EXT+# define GL_TIMESTAMP GL_TIMESTAMP_EXT+# define GL_QUERY_COUNTER_BITS GL_QUERY_COUNTER_BITS_EXT+# define glGetQueryObjectiv glGetQueryObjectivEXT+# define glGetQueryObjectui64v glGetQueryObjectui64vEXT+# define glQueryCounter glQueryCounterEXT+#endif++#define TracyGpuContext tracy::GetGpuCtx().ptr = (tracy::GpuCtx*)tracy::tracy_malloc( sizeof( tracy::GpuCtx ) ); new(tracy::GetGpuCtx().ptr) tracy::GpuCtx;+#define TracyGpuContextName( name, size ) tracy::GetGpuCtx().ptr->Name( name, size );+#if defined TRACY_HAS_CALLSTACK && defined TRACY_CALLSTACK+# define TracyGpuNamedZone( varname, name, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, 0 }; tracy::GpuCtxScope varname( &TracyConcat(__tracy_gpu_source_location,TracyLine), TRACY_CALLSTACK, active );+# define TracyGpuNamedZoneC( varname, name, color, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, color }; tracy::GpuCtxScope varname( &TracyConcat(__tracy_gpu_source_location,TracyLine), TRACY_CALLSTACK, active );+# define TracyGpuZone( name ) TracyGpuNamedZoneS( ___tracy_gpu_zone, name, TRACY_CALLSTACK, true )+# define TracyGpuZoneC( name, color ) TracyGpuNamedZoneCS( ___tracy_gpu_zone, name, color, TRACY_CALLSTACK, true )+# define TracyGpuZoneTransient( varname, name, active ) tracy::GpuCtxScope varname( TracyLine, TracyFile, strlen( TracyFile ), TracyFunction, strlen( TracyFunction ), name, strlen( name ), TRACY_CALLSTACK, active );+#else+# define TracyGpuNamedZone( varname, name, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, 0 }; tracy::GpuCtxScope varname( &TracyConcat(__tracy_gpu_source_location,TracyLine), active );+# define TracyGpuNamedZoneC( varname, name, color, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, color }; tracy::GpuCtxScope varname( &TracyConcat(__tracy_gpu_source_location,TracyLine), active );+# define TracyGpuZone( name ) TracyGpuNamedZone( ___tracy_gpu_zone, name, true )+# define TracyGpuZoneC( name, color ) TracyGpuNamedZoneC( ___tracy_gpu_zone, name, color, true )+# define TracyGpuZoneTransient( varname, name, active ) tracy::GpuCtxScope varname( TracyLine, TracyFile, strlen( TracyFile ), TracyFunction, strlen( TracyFunction ), name, strlen( name ), active );+#endif+#define TracyGpuCollect tracy::GetGpuCtx().ptr->Collect();++#ifdef TRACY_HAS_CALLSTACK+# define TracyGpuNamedZoneS( varname, name, depth, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, 0 }; tracy::GpuCtxScope varname( &TracyConcat(__tracy_gpu_source_location,TracyLine), depth, active );+# define TracyGpuNamedZoneCS( varname, name, color, depth, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, color }; tracy::GpuCtxScope varname( &TracyConcat(__tracy_gpu_source_location,TracyLine), depth, active );+# define TracyGpuZoneS( name, depth ) TracyGpuNamedZoneS( ___tracy_gpu_zone, name, depth, true )+# define TracyGpuZoneCS( name, color, depth ) TracyGpuNamedZoneCS( ___tracy_gpu_zone, name, color, depth, true )+# define TracyGpuZoneTransientS( varname, name, depth, active ) tracy::GpuCtxScope varname( TracyLine, TracyFile, strlen( TracyFile ), TracyFunction, strlen( TracyFunction ), name, strlen( name ), depth, active );+#else+# define TracyGpuNamedZoneS( varname, name, depth, active ) TracyGpuNamedZone( varname, name, active )+# define TracyGpuNamedZoneCS( varname, name, color, depth, active ) TracyGpuNamedZoneC( varname, name, color, active )+# define TracyGpuZoneS( name, depth ) TracyGpuZone( name )+# define TracyGpuZoneCS( name, color, depth ) TracyGpuZoneC( name, color )+# define TracyGpuZoneTransientS( varname, name, depth, active ) TracyGpuZoneTransient( varname, name, active )+#endif++namespace tracy+{++class GpuCtx+{+ friend class GpuCtxScope;++ enum { QueryCount = 64 * 1024 };++public:+ GpuCtx()+ : m_context( GetGpuCtxCounter().fetch_add( 1, std::memory_order_relaxed ) )+ , m_head( 0 )+ , m_tail( 0 )+ {+ assert( m_context != 255 );++ glGenQueries( QueryCount, m_query );++ int64_t tgpu;+ glGetInteger64v( GL_TIMESTAMP, &tgpu );+ int64_t tcpu = Profiler::GetTime();++ GLint bits;+ glGetQueryiv( GL_TIMESTAMP, GL_QUERY_COUNTER_BITS, &bits );++ const float period = 1.f;+ const auto thread = GetThreadHandle();+ TracyLfqPrepare( QueueType::GpuNewContext );+ MemWrite( &item->gpuNewContext.cpuTime, tcpu );+ MemWrite( &item->gpuNewContext.gpuTime, tgpu );+ MemWrite( &item->gpuNewContext.thread, thread );+ MemWrite( &item->gpuNewContext.period, period );+ MemWrite( &item->gpuNewContext.context, m_context );+ MemWrite( &item->gpuNewContext.flags, uint8_t( 0 ) );+ MemWrite( &item->gpuNewContext.type, GpuContextType::OpenGl );++#ifdef TRACY_ON_DEMAND+ GetProfiler().DeferItem( *item );+#endif++ TracyLfqCommit;+ }++ void Name( const char* name, uint16_t len )+ {+ auto ptr = (char*)tracy_malloc( len );+ memcpy( ptr, name, len );++ TracyLfqPrepare( QueueType::GpuContextName );+ MemWrite( &item->gpuContextNameFat.context, m_context );+ MemWrite( &item->gpuContextNameFat.ptr, (uint64_t)ptr );+ MemWrite( &item->gpuContextNameFat.size, len );+#ifdef TRACY_ON_DEMAND+ GetProfiler().DeferItem( *item );+#endif+ TracyLfqCommit;+ }++ void Collect()+ {+ ZoneScopedC( Color::Red4 );++ if( m_tail == m_head ) return;++#ifdef TRACY_ON_DEMAND+ if( !GetProfiler().IsConnected() )+ {+ m_head = m_tail = 0;+ return;+ }+#endif++ while( m_tail != m_head )+ {+ GLint available;+ glGetQueryObjectiv( m_query[m_tail], GL_QUERY_RESULT_AVAILABLE, &available );+ if( !available ) return;++ uint64_t time;+ glGetQueryObjectui64v( m_query[m_tail], GL_QUERY_RESULT, &time );++ TracyLfqPrepare( QueueType::GpuTime );+ MemWrite( &item->gpuTime.gpuTime, (int64_t)time );+ MemWrite( &item->gpuTime.queryId, (uint16_t)m_tail );+ MemWrite( &item->gpuTime.context, m_context );+ TracyLfqCommit;++ m_tail = ( m_tail + 1 ) % QueryCount;+ }+ }++private:+ tracy_force_inline unsigned int NextQueryId()+ {+ const auto id = m_head;+ m_head = ( m_head + 1 ) % QueryCount;+ assert( m_head != m_tail );+ return id;+ }++ tracy_force_inline unsigned int TranslateOpenGlQueryId( unsigned int id )+ {+ return m_query[id];+ }++ tracy_force_inline uint8_t GetId() const+ {+ return m_context;+ }++ unsigned int m_query[QueryCount];+ uint8_t m_context;++ unsigned int m_head;+ unsigned int m_tail;+};++class GpuCtxScope+{+public:+ tracy_force_inline GpuCtxScope( const SourceLocationData* srcloc, bool is_active )+#ifdef TRACY_ON_DEMAND+ : m_active( is_active && GetProfiler().IsConnected() )+#else+ : m_active( is_active )+#endif+ {+ if( !m_active ) return;++ const auto queryId = GetGpuCtx().ptr->NextQueryId();+ glQueryCounter( GetGpuCtx().ptr->TranslateOpenGlQueryId( queryId ), GL_TIMESTAMP );++ TracyLfqPrepare( QueueType::GpuZoneBegin );+ MemWrite( &item->gpuZoneBegin.cpuTime, Profiler::GetTime() );+ memset( &item->gpuZoneBegin.thread, 0, sizeof( item->gpuZoneBegin.thread ) );+ MemWrite( &item->gpuZoneBegin.queryId, uint16_t( queryId ) );+ MemWrite( &item->gpuZoneBegin.context, GetGpuCtx().ptr->GetId() );+ MemWrite( &item->gpuZoneBegin.srcloc, (uint64_t)srcloc );+ TracyLfqCommit;+ }++ tracy_force_inline GpuCtxScope( const SourceLocationData* srcloc, int32_t depth, bool is_active )+#ifdef TRACY_ON_DEMAND+ : m_active( is_active && GetProfiler().IsConnected() )+#else+ : m_active( is_active )+#endif+ {+ if( !m_active ) return;++ const auto queryId = GetGpuCtx().ptr->NextQueryId();+ glQueryCounter( GetGpuCtx().ptr->TranslateOpenGlQueryId( queryId ), GL_TIMESTAMP );++#ifdef TRACY_FIBERS+ TracyLfqPrepare( QueueType::GpuZoneBegin );+ memset( &item->gpuZoneBegin.thread, 0, sizeof( item->gpuZoneBegin.thread ) );+#else+ GetProfiler().SendCallstack( depth );+ TracyLfqPrepare( QueueType::GpuZoneBeginCallstack );+ MemWrite( &item->gpuZoneBegin.thread, GetThreadHandle() );+#endif+ MemWrite( &item->gpuZoneBegin.cpuTime, Profiler::GetTime() );+ MemWrite( &item->gpuZoneBegin.queryId, uint16_t( queryId ) );+ MemWrite( &item->gpuZoneBegin.context, GetGpuCtx().ptr->GetId() );+ MemWrite( &item->gpuZoneBegin.srcloc, (uint64_t)srcloc );+ TracyLfqCommit;+ }++ tracy_force_inline GpuCtxScope( uint32_t line, const char* source, size_t sourceSz, const char* function, size_t functionSz, const char* name, size_t nameSz, bool is_active )+#ifdef TRACY_ON_DEMAND+ : m_active( is_active && GetProfiler().IsConnected() )+#else+ : m_active( is_active )+#endif+ {+ if( !m_active ) return;++ const auto queryId = GetGpuCtx().ptr->NextQueryId();+ glQueryCounter( GetGpuCtx().ptr->TranslateOpenGlQueryId( queryId ), GL_TIMESTAMP );++ TracyLfqPrepare( QueueType::GpuZoneBeginAllocSrcLoc );+ const auto srcloc = Profiler::AllocSourceLocation( line, source, sourceSz, function, functionSz, name, nameSz );+ MemWrite( &item->gpuZoneBegin.cpuTime, Profiler::GetTime() );+ memset( &item->gpuZoneBegin.thread, 0, sizeof( item->gpuZoneBegin.thread ) );+ MemWrite( &item->gpuZoneBegin.queryId, uint16_t( queryId ) );+ MemWrite( &item->gpuZoneBegin.context, GetGpuCtx().ptr->GetId() );+ MemWrite( &item->gpuZoneBegin.srcloc, (uint64_t)srcloc );+ TracyLfqCommit;+ }++ tracy_force_inline GpuCtxScope( uint32_t line, const char* source, size_t sourceSz, const char* function, size_t functionSz, const char* name, size_t nameSz, int32_t depth, bool is_active )+#ifdef TRACY_ON_DEMAND+ : m_active( is_active && GetProfiler().IsConnected() )+#else+ : m_active( is_active )+#endif+ {+ if( !m_active ) return;++ const auto queryId = GetGpuCtx().ptr->NextQueryId();+ glQueryCounter( GetGpuCtx().ptr->TranslateOpenGlQueryId( queryId ), GL_TIMESTAMP );++#ifdef TRACY_FIBERS+ TracyLfqPrepare( QueueType::GpuZoneBeginAllocSrcLoc );+ memset( &item->gpuZoneBegin.thread, 0, sizeof( item->gpuZoneBegin.thread ) );+#else+ GetProfiler().SendCallstack( depth );+ TracyLfqPrepare( QueueType::GpuZoneBeginAllocSrcLocCallstack );+ MemWrite( &item->gpuZoneBegin.thread, GetThreadHandle() );+#endif+ const auto srcloc = Profiler::AllocSourceLocation( line, source, sourceSz, function, functionSz, name, nameSz );+ MemWrite( &item->gpuZoneBegin.cpuTime, Profiler::GetTime() );+ MemWrite( &item->gpuZoneBegin.queryId, uint16_t( queryId ) );+ MemWrite( &item->gpuZoneBegin.context, GetGpuCtx().ptr->GetId() );+ MemWrite( &item->gpuZoneBegin.srcloc, (uint64_t)srcloc );+ TracyLfqCommit;+ }++ tracy_force_inline ~GpuCtxScope()+ {+ if( !m_active ) return;++ const auto queryId = GetGpuCtx().ptr->NextQueryId();+ glQueryCounter( GetGpuCtx().ptr->TranslateOpenGlQueryId( queryId ), GL_TIMESTAMP );++ TracyLfqPrepare( QueueType::GpuZoneEnd );+ MemWrite( &item->gpuZoneEnd.cpuTime, Profiler::GetTime() );+ memset( &item->gpuZoneEnd.thread, 0, sizeof( item->gpuZoneEnd.thread ) );+ MemWrite( &item->gpuZoneEnd.queryId, uint16_t( queryId ) );+ MemWrite( &item->gpuZoneEnd.context, GetGpuCtx().ptr->GetId() );+ TracyLfqCommit;+ }++private:+ const bool m_active;+};++}++#endif++#endif
+ cbits/tracy/public/tracy/TracyVulkan.hpp view
@@ -0,0 +1,741 @@+#ifndef __TRACYVULKAN_HPP__+#define __TRACYVULKAN_HPP__++#if !defined TRACY_ENABLE++#define TracyVkContext(x,y,z,w) nullptr+#define TracyVkContextCalibrated(x,y,z,w,a,b) nullptr+#if defined VK_EXT_host_query_reset+#define TracyVkContextHostCalibrated(x,y,z,w,a) nullptr+#endif+#define TracyVkDestroy(x)+#define TracyVkContextName(c,x,y)+#define TracyVkNamedZone(c,x,y,z,w)+#define TracyVkNamedZoneC(c,x,y,z,w,a)+#define TracyVkZone(c,x,y)+#define TracyVkZoneC(c,x,y,z)+#define TracyVkZoneTransient(c,x,y,z,w)+#define TracyVkCollect(c,x)++#define TracyVkNamedZoneS(c,x,y,z,w,a)+#define TracyVkNamedZoneCS(c,x,y,z,w,v,a)+#define TracyVkZoneS(c,x,y,z)+#define TracyVkZoneCS(c,x,y,z,w)+#define TracyVkZoneTransientS(c,x,y,z,w,a)++namespace tracy+{+class VkCtxScope {};+}++using TracyVkCtx = void*;++#else++#if !defined VK_NULL_HANDLE+# error "You must include Vulkan headers before including TracyVulkan.hpp"+#endif++#include <assert.h>+#include <stdlib.h>+#include "Tracy.hpp"+#include "../client/TracyProfiler.hpp"+#include "../client/TracyCallstack.hpp"++#include <atomic>++namespace tracy+{++#if defined TRACY_VK_USE_SYMBOL_TABLE+#define LoadVkDeviceCoreSymbols(Operation) \+ Operation(vkBeginCommandBuffer) \+ Operation(vkCmdResetQueryPool) \+ Operation(vkCmdWriteTimestamp) \+ Operation(vkCreateQueryPool) \+ Operation(vkDestroyQueryPool) \+ Operation(vkEndCommandBuffer) \+ Operation(vkGetQueryPoolResults) \+ Operation(vkQueueSubmit) \+ Operation(vkQueueWaitIdle) \+ Operation(vkResetQueryPool)++#define LoadVkDeviceExtensionSymbols(Operation) \+ Operation(vkGetCalibratedTimestampsEXT)++#define LoadVkInstanceExtensionSymbols(Operation) \+ Operation(vkGetPhysicalDeviceCalibrateableTimeDomainsEXT)++#define LoadVkInstanceCoreSymbols(Operation) \+ Operation(vkGetPhysicalDeviceProperties)++struct VkSymbolTable+{+#define MAKE_PFN(name) PFN_##name name;+ LoadVkDeviceCoreSymbols(MAKE_PFN)+ LoadVkDeviceExtensionSymbols(MAKE_PFN)+ LoadVkInstanceExtensionSymbols(MAKE_PFN)+ LoadVkInstanceCoreSymbols(MAKE_PFN)+#undef MAKE_PFN+};++#define VK_FUNCTION_WRAPPER(callSignature) m_symbols.callSignature+#define CONTEXT_VK_FUNCTION_WRAPPER(callSignature) m_ctx->m_symbols.callSignature+#else+#define VK_FUNCTION_WRAPPER(callSignature) callSignature+#define CONTEXT_VK_FUNCTION_WRAPPER(callSignature) callSignature+#endif++class VkCtx+{+ friend class VkCtxScope;++ enum { QueryCount = 64 * 1024 };++public:+#if defined TRACY_VK_USE_SYMBOL_TABLE+ VkCtx( VkInstance instance, VkPhysicalDevice physdev, VkDevice device, VkQueue queue, VkCommandBuffer cmdbuf, PFN_vkGetInstanceProcAddr instanceProcAddr, PFN_vkGetDeviceProcAddr deviceProcAddr, bool calibrated )+#else+ VkCtx( VkPhysicalDevice physdev, VkDevice device, VkQueue queue, VkCommandBuffer cmdbuf, PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT vkGetPhysicalDeviceCalibrateableTimeDomainsEXT, PFN_vkGetCalibratedTimestampsEXT vkGetCalibratedTimestampsEXT)+#endif+ : m_device( device )+ , m_timeDomain( VK_TIME_DOMAIN_DEVICE_EXT )+ , m_context( GetGpuCtxCounter().fetch_add( 1, std::memory_order_relaxed ) )+ , m_head( 0 )+ , m_tail( 0 )+ , m_oldCnt( 0 )+ , m_queryCount( QueryCount )+#if !defined TRACY_VK_USE_SYMBOL_TABLE+ , m_vkGetCalibratedTimestampsEXT( vkGetCalibratedTimestampsEXT )+#endif+ {+ assert( m_context != 255 );++#if defined TRACY_VK_USE_SYMBOL_TABLE+ PopulateSymbolTable(instance, instanceProcAddr, deviceProcAddr);+ if ( calibrated )+ {+ m_vkGetCalibratedTimestampsEXT = m_symbols.vkGetCalibratedTimestampsEXT;+ }++#endif++ if( VK_FUNCTION_WRAPPER( vkGetPhysicalDeviceCalibrateableTimeDomainsEXT ) && m_vkGetCalibratedTimestampsEXT )+ {+ FindAvailableTimeDomains( physdev, VK_FUNCTION_WRAPPER( vkGetPhysicalDeviceCalibrateableTimeDomainsEXT ) );+ }++ CreateQueryPool();++ VkCommandBufferBeginInfo beginInfo = {};+ beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;+ beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;++ VkSubmitInfo submitInfo = {};+ submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;+ submitInfo.commandBufferCount = 1;+ submitInfo.pCommandBuffers = &cmdbuf;++ VK_FUNCTION_WRAPPER( vkBeginCommandBuffer( cmdbuf, &beginInfo ) );+ VK_FUNCTION_WRAPPER( vkCmdResetQueryPool( cmdbuf, m_query, 0, m_queryCount ) );+ VK_FUNCTION_WRAPPER( vkEndCommandBuffer( cmdbuf ) );+ VK_FUNCTION_WRAPPER( vkQueueSubmit( queue, 1, &submitInfo, VK_NULL_HANDLE ) );+ VK_FUNCTION_WRAPPER( vkQueueWaitIdle( queue ) );++ int64_t tcpu, tgpu;+ if( m_timeDomain == VK_TIME_DOMAIN_DEVICE_EXT )+ {+ VK_FUNCTION_WRAPPER( vkBeginCommandBuffer( cmdbuf, &beginInfo ) );+ VK_FUNCTION_WRAPPER( vkCmdWriteTimestamp( cmdbuf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, m_query, 0 ) );+ VK_FUNCTION_WRAPPER( vkEndCommandBuffer( cmdbuf ) );+ VK_FUNCTION_WRAPPER( vkQueueSubmit( queue, 1, &submitInfo, VK_NULL_HANDLE ) );+ VK_FUNCTION_WRAPPER( vkQueueWaitIdle( queue ) );++ tcpu = Profiler::GetTime();+ VK_FUNCTION_WRAPPER( vkGetQueryPoolResults( device, m_query, 0, 1, sizeof( tgpu ), &tgpu, sizeof( tgpu ), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT ) );++ VK_FUNCTION_WRAPPER( vkBeginCommandBuffer( cmdbuf, &beginInfo ) );+ VK_FUNCTION_WRAPPER( vkCmdResetQueryPool( cmdbuf, m_query, 0, 1 ) );+ VK_FUNCTION_WRAPPER( vkEndCommandBuffer( cmdbuf ) );+ VK_FUNCTION_WRAPPER( vkQueueSubmit( queue, 1, &submitInfo, VK_NULL_HANDLE ) );+ VK_FUNCTION_WRAPPER( vkQueueWaitIdle( queue ) );+ }+ else+ {+ FindCalibratedTimestampDeviation();+ Calibrate( device, m_prevCalibration, tgpu );+ tcpu = Profiler::GetTime();+ }++ WriteInitialItem( physdev, tcpu, tgpu );++ m_res = (int64_t*)tracy_malloc( sizeof( int64_t ) * m_queryCount );+ }++#if defined VK_EXT_host_query_reset+ /**+ * This alternative constructor does not use command buffers and instead uses functionality from+ * VK_EXT_host_query_reset (core with 1.2 and non-optional) and VK_EXT_calibrated_timestamps. This requires+ * the physical device to have another time domain apart from DEVICE to be calibrateable.+ */+#if defined TRACY_VK_USE_SYMBOL_TABLE+ VkCtx( VkInstance instance, VkPhysicalDevice physdev, VkDevice device, PFN_vkGetInstanceProcAddr instanceProcAddr, PFN_vkGetDeviceProcAddr deviceProcAddr )+#else+ VkCtx( VkPhysicalDevice physdev, VkDevice device, PFN_vkResetQueryPoolEXT vkResetQueryPool, PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT vkGetPhysicalDeviceCalibrateableTimeDomainsEXT, PFN_vkGetCalibratedTimestampsEXT vkGetCalibratedTimestampsEXT )+#endif+ : m_device( device )+ , m_timeDomain( VK_TIME_DOMAIN_DEVICE_EXT )+ , m_context( GetGpuCtxCounter().fetch_add(1, std::memory_order_relaxed) )+ , m_head( 0 )+ , m_tail( 0 )+ , m_oldCnt( 0 )+ , m_queryCount( QueryCount )+#if !defined TRACY_VK_USE_SYMBOL_TABLE+ , m_vkGetCalibratedTimestampsEXT( vkGetCalibratedTimestampsEXT )+#endif+ {+ assert( m_context != 255);++#if defined TRACY_VK_USE_SYMBOL_TABLE+ PopulateSymbolTable(instance, instanceProcAddr, deviceProcAddr);+ m_vkGetCalibratedTimestampsEXT = m_symbols.vkGetCalibratedTimestampsEXT;+#endif++ assert( VK_FUNCTION_WRAPPER( vkResetQueryPool ) != nullptr );+ assert( VK_FUNCTION_WRAPPER( vkGetPhysicalDeviceCalibrateableTimeDomainsEXT ) != nullptr );+ assert( VK_FUNCTION_WRAPPER( vkGetCalibratedTimestampsEXT ) != nullptr );++ FindAvailableTimeDomains( physdev, VK_FUNCTION_WRAPPER( vkGetPhysicalDeviceCalibrateableTimeDomainsEXT ) );++ // We require a host time domain to be available to properly calibrate.+ FindCalibratedTimestampDeviation();+ int64_t tgpu;+ Calibrate( device, m_prevCalibration, tgpu );+ int64_t tcpu = Profiler::GetTime();++ CreateQueryPool();+ VK_FUNCTION_WRAPPER( vkResetQueryPool( device, m_query, 0, m_queryCount ) );++ WriteInitialItem( physdev, tcpu, tgpu );++ // We need the buffer to be twice as large for availability values+ size_t resSize = sizeof( int64_t ) * m_queryCount * 2;+ m_res = (int64_t*)tracy_malloc( resSize );+ }+#endif++ ~VkCtx()+ {+ tracy_free( m_res );+ VK_FUNCTION_WRAPPER( vkDestroyQueryPool( m_device, m_query, nullptr ) );+ }++ void Name( const char* name, uint16_t len )+ {+ auto ptr = (char*)tracy_malloc( len );+ memcpy( ptr, name, len );++ auto item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::GpuContextName );+ MemWrite( &item->gpuContextNameFat.context, m_context );+ MemWrite( &item->gpuContextNameFat.ptr, (uint64_t)ptr );+ MemWrite( &item->gpuContextNameFat.size, len );+#ifdef TRACY_ON_DEMAND+ GetProfiler().DeferItem( *item );+#endif+ Profiler::QueueSerialFinish();+ }++ void Collect( VkCommandBuffer cmdbuf )+ {+ ZoneScopedC( Color::Red4 );++ const uint64_t head = m_head.load(std::memory_order_relaxed);+ if( m_tail == head ) return;++#ifdef TRACY_ON_DEMAND+ if( !GetProfiler().IsConnected() )+ {+ VK_FUNCTION_WRAPPER( vkCmdResetQueryPool( cmdbuf, m_query, 0, m_queryCount ) );+ m_tail = head;+ m_oldCnt = 0;+ int64_t tgpu;+ if( m_timeDomain != VK_TIME_DOMAIN_DEVICE_EXT ) Calibrate( m_device, m_prevCalibration, tgpu );+ return;+ }+#endif+ assert( head > m_tail );++ const unsigned int wrappedTail = (unsigned int)( m_tail % m_queryCount );++ unsigned int cnt;+ if( m_oldCnt != 0 )+ {+ cnt = m_oldCnt;+ m_oldCnt = 0;+ }+ else+ {+ cnt = (unsigned int)( head - m_tail );+ assert( cnt <= m_queryCount );+ if( wrappedTail + cnt > m_queryCount )+ {+ cnt = m_queryCount - wrappedTail;+ }+ }+++ VK_FUNCTION_WRAPPER( vkGetQueryPoolResults( m_device, m_query, wrappedTail, cnt, sizeof( int64_t ) * m_queryCount * 2, m_res, sizeof( int64_t ) * 2, VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT ) );++ for( unsigned int idx=0; idx<cnt; idx++ )+ {+ int64_t avail = m_res[idx * 2 + 1];+ if( avail == 0 )+ {+ m_oldCnt = cnt - idx;+ cnt = idx;++ break;+ }++ auto item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::GpuTime );+ MemWrite( &item->gpuTime.gpuTime, m_res[idx * 2] );+ MemWrite( &item->gpuTime.queryId, uint16_t( wrappedTail + idx ) );+ MemWrite( &item->gpuTime.context, m_context );+ Profiler::QueueSerialFinish();+ }++ if( m_timeDomain != VK_TIME_DOMAIN_DEVICE_EXT )+ {+ int64_t tgpu, tcpu;+ Calibrate( m_device, tcpu, tgpu );+ const auto refCpu = Profiler::GetTime();+ const auto delta = tcpu - m_prevCalibration;+ if( delta > 0 )+ {+ m_prevCalibration = tcpu;+ auto item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::GpuCalibration );+ MemWrite( &item->gpuCalibration.gpuTime, tgpu );+ MemWrite( &item->gpuCalibration.cpuTime, refCpu );+ MemWrite( &item->gpuCalibration.cpuDelta, delta );+ MemWrite( &item->gpuCalibration.context, m_context );+ Profiler::QueueSerialFinish();+ }+ }++ VK_FUNCTION_WRAPPER( vkCmdResetQueryPool( cmdbuf, m_query, wrappedTail, cnt ) );++ m_tail += cnt;+ }++ tracy_force_inline unsigned int NextQueryId()+ {+ const uint64_t id = m_head.fetch_add(1, std::memory_order_relaxed);+ return id % m_queryCount;+ }++ tracy_force_inline uint8_t GetId() const+ {+ return m_context;+ }++ tracy_force_inline VkQueryPool GetQueryPool() const+ {+ return m_query;+ }++private:+ tracy_force_inline void Calibrate( VkDevice device, int64_t& tCpu, int64_t& tGpu )+ {+ assert( m_timeDomain != VK_TIME_DOMAIN_DEVICE_EXT );+ VkCalibratedTimestampInfoEXT spec[2] = {+ { VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_EXT, nullptr, VK_TIME_DOMAIN_DEVICE_EXT },+ { VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_EXT, nullptr, m_timeDomain },+ };+ uint64_t ts[2];+ uint64_t deviation;+ do+ {+ m_vkGetCalibratedTimestampsEXT( device, 2, spec, ts, &deviation );+ }+ while( deviation > m_deviation );++#if defined _WIN32+ tGpu = ts[0];+ tCpu = ts[1] * m_qpcToNs;+#elif defined __linux__ && defined CLOCK_MONOTONIC_RAW+ tGpu = ts[0];+ tCpu = ts[1];+#else+ assert( false );+#endif+ }++ tracy_force_inline void CreateQueryPool()+ {+ VkQueryPoolCreateInfo poolInfo = {};+ poolInfo.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;+ poolInfo.queryCount = m_queryCount;+ poolInfo.queryType = VK_QUERY_TYPE_TIMESTAMP;+ while ( VK_FUNCTION_WRAPPER( vkCreateQueryPool( m_device, &poolInfo, nullptr, &m_query ) != VK_SUCCESS ) )+ {+ m_queryCount /= 2;+ poolInfo.queryCount = m_queryCount;+ }+ }++ tracy_force_inline void FindAvailableTimeDomains( VkPhysicalDevice physicalDevice, PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT _vkGetPhysicalDeviceCalibrateableTimeDomainsEXT )+ {+ uint32_t num;+ _vkGetPhysicalDeviceCalibrateableTimeDomainsEXT( physicalDevice, &num, nullptr );+ if(num > 4) num = 4;+ VkTimeDomainEXT data[4];+ _vkGetPhysicalDeviceCalibrateableTimeDomainsEXT( physicalDevice, &num, data );+ VkTimeDomainEXT supportedDomain = (VkTimeDomainEXT)-1;+#if defined _WIN32+ supportedDomain = VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT;+#elif defined __linux__ && defined CLOCK_MONOTONIC_RAW+ supportedDomain = VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT;+#endif+ for( uint32_t i=0; i<num; i++ ) {+ if(data[i] == supportedDomain) {+ m_timeDomain = data[i];+ break;+ }+ }+ }++ tracy_force_inline void FindCalibratedTimestampDeviation()+ {+ assert( m_timeDomain != VK_TIME_DOMAIN_DEVICE_EXT );+ constexpr size_t NumProbes = 32;+ VkCalibratedTimestampInfoEXT spec[2] = {+ { VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_EXT, nullptr, VK_TIME_DOMAIN_DEVICE_EXT },+ { VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_EXT, nullptr, m_timeDomain },+ };+ uint64_t ts[2];+ uint64_t deviation[NumProbes];+ for( size_t i=0; i<NumProbes; i++ ) {+ m_vkGetCalibratedTimestampsEXT( m_device, 2, spec, ts, deviation + i );+ }+ uint64_t minDeviation = deviation[0];+ for( size_t i=1; i<NumProbes; i++ ) {+ if ( minDeviation > deviation[i] ) {+ minDeviation = deviation[i];+ }+ }+ m_deviation = minDeviation * 3 / 2;++#if defined _WIN32+ m_qpcToNs = int64_t( 1000000000. / GetFrequencyQpc() );+#endif+ }++ tracy_force_inline void WriteInitialItem( VkPhysicalDevice physdev, int64_t tcpu, int64_t tgpu )+ {+ uint8_t flags = 0;+ if( m_timeDomain != VK_TIME_DOMAIN_DEVICE_EXT ) flags |= GpuContextCalibration;++ VkPhysicalDeviceProperties prop;+ VK_FUNCTION_WRAPPER( vkGetPhysicalDeviceProperties( physdev, &prop ) );+ const float period = prop.limits.timestampPeriod;++ auto item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::GpuNewContext );+ MemWrite( &item->gpuNewContext.cpuTime, tcpu );+ MemWrite( &item->gpuNewContext.gpuTime, tgpu );+ memset( &item->gpuNewContext.thread, 0, sizeof( item->gpuNewContext.thread ) );+ MemWrite( &item->gpuNewContext.period, period );+ MemWrite( &item->gpuNewContext.context, m_context );+ MemWrite( &item->gpuNewContext.flags, flags );+ MemWrite( &item->gpuNewContext.type, GpuContextType::Vulkan );++#ifdef TRACY_ON_DEMAND+ GetProfiler().DeferItem( *item );+#endif+ Profiler::QueueSerialFinish();+ }++#if defined TRACY_VK_USE_SYMBOL_TABLE+ void PopulateSymbolTable( VkInstance instance, PFN_vkGetInstanceProcAddr instanceProcAddr, PFN_vkGetDeviceProcAddr deviceProcAddr )+ {+#define VK_GET_DEVICE_SYMBOL( name ) \+ (PFN_##name)deviceProcAddr( m_device, #name );+#define VK_LOAD_DEVICE_SYMBOL( name ) \+ m_symbols.name = VK_GET_DEVICE_SYMBOL( name );+#define VK_GET_INSTANCE_SYMBOL( name ) \+ (PFN_##name)instanceProcAddr( instance, #name );+#define VK_LOAD_INSTANCE_SYMBOL( name ) \+ m_symbols.name = VK_GET_INSTANCE_SYMBOL( name );++ LoadVkDeviceCoreSymbols( VK_LOAD_DEVICE_SYMBOL )+ LoadVkDeviceExtensionSymbols( VK_LOAD_DEVICE_SYMBOL )+ LoadVkInstanceExtensionSymbols( VK_LOAD_INSTANCE_SYMBOL )+ LoadVkInstanceCoreSymbols( VK_LOAD_INSTANCE_SYMBOL )+#undef VK_GET_DEVICE_SYMBOL+#undef VK_LOAD_DEVICE_SYMBOL+#undef VK_GET_INSTANCE_SYMBOL+#undef VK_LOAD_INSTANCE_SYMBOL+ }+#endif++ VkDevice m_device;+ VkQueryPool m_query;+ VkTimeDomainEXT m_timeDomain;+#if defined TRACY_VK_USE_SYMBOL_TABLE+ VkSymbolTable m_symbols;+#endif+ uint64_t m_deviation;+#ifdef _WIN32+ int64_t m_qpcToNs;+#endif+ int64_t m_prevCalibration;+ uint8_t m_context;++ std::atomic<uint64_t> m_head;+ uint64_t m_tail;+ unsigned int m_oldCnt;+ unsigned int m_queryCount;++ int64_t* m_res;++ PFN_vkGetCalibratedTimestampsEXT m_vkGetCalibratedTimestampsEXT;+};++class VkCtxScope+{+public:+ tracy_force_inline VkCtxScope( VkCtx* ctx, const SourceLocationData* srcloc, VkCommandBuffer cmdbuf, bool is_active )+#ifdef TRACY_ON_DEMAND+ : m_active( is_active && GetProfiler().IsConnected() )+#else+ : m_active( is_active )+#endif+ {+ if( !m_active ) return;+ m_cmdbuf = cmdbuf;+ m_ctx = ctx;++ const auto queryId = ctx->NextQueryId();+ CONTEXT_VK_FUNCTION_WRAPPER( vkCmdWriteTimestamp( cmdbuf, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, ctx->m_query, queryId ) );++ auto item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::GpuZoneBeginSerial );+ MemWrite( &item->gpuZoneBegin.cpuTime, Profiler::GetTime() );+ MemWrite( &item->gpuZoneBegin.srcloc, (uint64_t)srcloc );+ MemWrite( &item->gpuZoneBegin.thread, GetThreadHandle() );+ MemWrite( &item->gpuZoneBegin.queryId, uint16_t( queryId ) );+ MemWrite( &item->gpuZoneBegin.context, ctx->GetId() );+ Profiler::QueueSerialFinish();+ }++ tracy_force_inline VkCtxScope( VkCtx* ctx, const SourceLocationData* srcloc, VkCommandBuffer cmdbuf, int32_t depth, bool is_active )+#ifdef TRACY_ON_DEMAND+ : m_active( is_active && GetProfiler().IsConnected() )+#else+ : m_active( is_active )+#endif+ {+ if( !m_active ) return;+ m_cmdbuf = cmdbuf;+ m_ctx = ctx;++ const auto queryId = ctx->NextQueryId();+ CONTEXT_VK_FUNCTION_WRAPPER( vkCmdWriteTimestamp( cmdbuf, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, ctx->m_query, queryId ) );++ QueueItem *item;+ if( depth > 0 && has_callstack() )+ {+ item = Profiler::QueueSerialCallstack( Callstack( depth ) );+ MemWrite( &item->hdr.type, QueueType::GpuZoneBeginCallstackSerial );+ }+ else+ {+ item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::GpuZoneBeginSerial );+ }+ MemWrite( &item->gpuZoneBegin.cpuTime, Profiler::GetTime() );+ MemWrite( &item->gpuZoneBegin.srcloc, (uint64_t)srcloc );+ MemWrite( &item->gpuZoneBegin.thread, GetThreadHandle() );+ MemWrite( &item->gpuZoneBegin.queryId, uint16_t( queryId ) );+ MemWrite( &item->gpuZoneBegin.context, ctx->GetId() );+ Profiler::QueueSerialFinish();+ }++ tracy_force_inline VkCtxScope( VkCtx* ctx, uint32_t line, const char* source, size_t sourceSz, const char* function, size_t functionSz, const char* name, size_t nameSz, VkCommandBuffer cmdbuf, bool is_active )+#ifdef TRACY_ON_DEMAND+ : m_active( is_active && GetProfiler().IsConnected() )+#else+ : m_active( is_active )+#endif+ {+ if( !m_active ) return;+ m_cmdbuf = cmdbuf;+ m_ctx = ctx;++ const auto queryId = ctx->NextQueryId();+ CONTEXT_VK_FUNCTION_WRAPPER( vkCmdWriteTimestamp( cmdbuf, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, ctx->m_query, queryId ) );++ const auto srcloc = Profiler::AllocSourceLocation( line, source, sourceSz, function, functionSz, name, nameSz );+ auto item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::GpuZoneBeginAllocSrcLocSerial );+ MemWrite( &item->gpuZoneBegin.cpuTime, Profiler::GetTime() );+ MemWrite( &item->gpuZoneBegin.srcloc, srcloc );+ MemWrite( &item->gpuZoneBegin.thread, GetThreadHandle() );+ MemWrite( &item->gpuZoneBegin.queryId, uint16_t( queryId ) );+ MemWrite( &item->gpuZoneBegin.context, ctx->GetId() );+ Profiler::QueueSerialFinish();+ }++ tracy_force_inline VkCtxScope( VkCtx* ctx, uint32_t line, const char* source, size_t sourceSz, const char* function, size_t functionSz, const char* name, size_t nameSz, VkCommandBuffer cmdbuf, int32_t depth, bool is_active )+#ifdef TRACY_ON_DEMAND+ : m_active( is_active && GetProfiler().IsConnected() )+#else+ : m_active( is_active )+#endif+ {+ if( !m_active ) return;+ m_cmdbuf = cmdbuf;+ m_ctx = ctx;++ const auto queryId = ctx->NextQueryId();+ CONTEXT_VK_FUNCTION_WRAPPER( vkCmdWriteTimestamp( cmdbuf, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, ctx->m_query, queryId ) );++ const auto srcloc = Profiler::AllocSourceLocation( line, source, sourceSz, function, functionSz, name, nameSz );+ QueueItem *item;+ if( depth > 0 && has_callstack() )+ {+ item = Profiler::QueueSerialCallstack( Callstack( depth ) );+ MemWrite( &item->hdr.type, QueueType::GpuZoneBeginAllocSrcLocCallstackSerial );+ }+ else+ {+ item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::GpuZoneBeginAllocSrcLocSerial );+ }+ MemWrite( &item->gpuZoneBegin.cpuTime, Profiler::GetTime() );+ MemWrite( &item->gpuZoneBegin.srcloc, srcloc );+ MemWrite( &item->gpuZoneBegin.thread, GetThreadHandle() );+ MemWrite( &item->gpuZoneBegin.queryId, uint16_t( queryId ) );+ MemWrite( &item->gpuZoneBegin.context, ctx->GetId() );+ Profiler::QueueSerialFinish();+ }++ tracy_force_inline ~VkCtxScope()+ {+ if( !m_active ) return;++ const auto queryId = m_ctx->NextQueryId();+ CONTEXT_VK_FUNCTION_WRAPPER( vkCmdWriteTimestamp( m_cmdbuf, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, m_ctx->m_query, queryId ) );++ auto item = Profiler::QueueSerial();+ MemWrite( &item->hdr.type, QueueType::GpuZoneEndSerial );+ MemWrite( &item->gpuZoneEnd.cpuTime, Profiler::GetTime() );+ MemWrite( &item->gpuZoneEnd.thread, GetThreadHandle() );+ MemWrite( &item->gpuZoneEnd.queryId, uint16_t( queryId ) );+ MemWrite( &item->gpuZoneEnd.context, m_ctx->GetId() );+ Profiler::QueueSerialFinish();+ }++private:+ const bool m_active;++ VkCommandBuffer m_cmdbuf;+ VkCtx* m_ctx;+};++#if defined TRACY_VK_USE_SYMBOL_TABLE+static inline VkCtx* CreateVkContext( VkInstance instance, VkPhysicalDevice physdev, VkDevice device, VkQueue queue, VkCommandBuffer cmdbuf, PFN_vkGetInstanceProcAddr instanceProcAddr, PFN_vkGetDeviceProcAddr getDeviceProcAddr, bool calibrated = false )+#else+static inline VkCtx* CreateVkContext( VkPhysicalDevice physdev, VkDevice device, VkQueue queue, VkCommandBuffer cmdbuf, PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT gpdctd, PFN_vkGetCalibratedTimestampsEXT gct )+#endif+{+ auto ctx = (VkCtx*)tracy_malloc( sizeof( VkCtx ) );+#if defined TRACY_VK_USE_SYMBOL_TABLE+ new(ctx) VkCtx( instance, physdev, device, queue, cmdbuf, instanceProcAddr, getDeviceProcAddr, calibrated );+#else+ new(ctx) VkCtx( physdev, device, queue, cmdbuf, gpdctd, gct );+#endif+ return ctx;+}++#if defined VK_EXT_host_query_reset+#if defined TRACY_VK_USE_SYMBOL_TABLE+static inline VkCtx* CreateVkContext( VkInstance instance, VkPhysicalDevice physdev, VkDevice device, PFN_vkGetInstanceProcAddr instanceProcAddr, PFN_vkGetDeviceProcAddr getDeviceProcAddr )+#else+static inline VkCtx* CreateVkContext( VkPhysicalDevice physdev, VkDevice device, PFN_vkResetQueryPoolEXT qpreset, PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT gpdctd, PFN_vkGetCalibratedTimestampsEXT gct )+#endif+{+ auto ctx = (VkCtx*)tracy_malloc( sizeof( VkCtx ) );+#if defined TRACY_VK_USE_SYMBOL_TABLE+ new(ctx) VkCtx( instance, physdev, device, instanceProcAddr, getDeviceProcAddr );+#else+ new(ctx) VkCtx( physdev, device, qpreset, gpdctd, gct );+#endif+ return ctx;+}+#endif++static inline void DestroyVkContext( VkCtx* ctx )+{+ ctx->~VkCtx();+ tracy_free( ctx );+}++}++using TracyVkCtx = tracy::VkCtx*;++#if defined TRACY_VK_USE_SYMBOL_TABLE+#define TracyVkContext( instance, physdev, device, queue, cmdbuf, instanceProcAddr, deviceProcAddr ) tracy::CreateVkContext( instance, physdev, device, queue, cmdbuf, instanceProcAddr, deviceProcAddr );+#else+#define TracyVkContext( physdev, device, queue, cmdbuf ) tracy::CreateVkContext( physdev, device, queue, cmdbuf, nullptr, nullptr );+#endif+#if defined TRACY_VK_USE_SYMBOL_TABLE+#define TracyVkContextCalibrated( instance, physdev, device, queue, cmdbuf, instanceProcAddr, deviceProcAddr ) tracy::CreateVkContext( instance, physdev, device, queue, cmdbuf, instanceProcAddr, deviceProcAddr, true );+#else+#define TracyVkContextCalibrated( physdev, device, queue, cmdbuf, gpdctd, gct ) tracy::CreateVkContext( physdev, device, queue, cmdbuf, gpdctd, gct );+#endif+#if defined VK_EXT_host_query_reset+#if defined TRACY_VK_USE_SYMBOL_TABLE+#define TracyVkContextHostCalibrated( instance, physdev, device, instanceProcAddr, deviceProcAddr ) tracy::CreateVkContext( instance, physdev, device, instanceProcAddr, deviceProcAddr );+#else+#define TracyVkContextHostCalibrated( physdev, device, qpreset, gpdctd, gct ) tracy::CreateVkContext( physdev, device, qpreset, gpdctd, gct );+#endif+#endif+#define TracyVkDestroy( ctx ) tracy::DestroyVkContext( ctx );+#define TracyVkContextName( ctx, name, size ) ctx->Name( name, size );+#if defined TRACY_HAS_CALLSTACK && defined TRACY_CALLSTACK+# define TracyVkNamedZone( ctx, varname, cmdbuf, name, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, 0 }; tracy::VkCtxScope varname( ctx, &TracyConcat(__tracy_gpu_source_location,TracyLine), cmdbuf, TRACY_CALLSTACK, active );+# define TracyVkNamedZoneC( ctx, varname, cmdbuf, name, color, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, color }; tracy::VkCtxScope varname( ctx, &TracyConcat(__tracy_gpu_source_location,TracyLine), cmdbuf, TRACY_CALLSTACK, active );+# define TracyVkZone( ctx, cmdbuf, name ) TracyVkNamedZoneS( ctx, ___tracy_gpu_zone, cmdbuf, name, TRACY_CALLSTACK, true )+# define TracyVkZoneC( ctx, cmdbuf, name, color ) TracyVkNamedZoneCS( ctx, ___tracy_gpu_zone, cmdbuf, name, color, TRACY_CALLSTACK, true )+# define TracyVkZoneTransient( ctx, varname, cmdbuf, name, active ) TracyVkZoneTransientS( ctx, varname, cmdbuf, name, TRACY_CALLSTACK, active )+#else+# define TracyVkNamedZone( ctx, varname, cmdbuf, name, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, 0 }; tracy::VkCtxScope varname( ctx, &TracyConcat(__tracy_gpu_source_location,TracyLine), cmdbuf, active );+# define TracyVkNamedZoneC( ctx, varname, cmdbuf, name, color, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, color }; tracy::VkCtxScope varname( ctx, &TracyConcat(__tracy_gpu_source_location,TracyLine), cmdbuf, active );+# define TracyVkZone( ctx, cmdbuf, name ) TracyVkNamedZone( ctx, ___tracy_gpu_zone, cmdbuf, name, true )+# define TracyVkZoneC( ctx, cmdbuf, name, color ) TracyVkNamedZoneC( ctx, ___tracy_gpu_zone, cmdbuf, name, color, true )+# define TracyVkZoneTransient( ctx, varname, cmdbuf, name, active ) tracy::VkCtxScope varname( ctx, TracyLine, TracyFile, strlen( TracyFile ), TracyFunction, strlen( TracyFunction ), name, strlen( name ), cmdbuf, active );+#endif+#define TracyVkCollect( ctx, cmdbuf ) ctx->Collect( cmdbuf );++#ifdef TRACY_HAS_CALLSTACK+# define TracyVkNamedZoneS( ctx, varname, cmdbuf, name, depth, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, 0 }; tracy::VkCtxScope varname( ctx, &TracyConcat(__tracy_gpu_source_location,TracyLine), cmdbuf, depth, active );+# define TracyVkNamedZoneCS( ctx, varname, cmdbuf, name, color, depth, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, color }; tracy::VkCtxScope varname( ctx, &TracyConcat(__tracy_gpu_source_location,TracyLine), cmdbuf, depth, active );+# define TracyVkZoneS( ctx, cmdbuf, name, depth ) TracyVkNamedZoneS( ctx, ___tracy_gpu_zone, cmdbuf, name, depth, true )+# define TracyVkZoneCS( ctx, cmdbuf, name, color, depth ) TracyVkNamedZoneCS( ctx, ___tracy_gpu_zone, cmdbuf, name, color, depth, true )+# define TracyVkZoneTransientS( ctx, varname, cmdbuf, name, depth, active ) tracy::VkCtxScope varname( ctx, TracyLine, TracyFile, strlen( TracyFile ), TracyFunction, strlen( TracyFunction ), name, strlen( name ), cmdbuf, depth, active );+#else+# define TracyVkNamedZoneS( ctx, varname, cmdbuf, name, depth, active ) TracyVkNamedZone( ctx, varname, cmdbuf, name, active )+# define TracyVkNamedZoneCS( ctx, varname, cmdbuf, name, color, depth, active ) TracyVkNamedZoneC( ctx, varname, cmdbuf, name, color, active )+# define TracyVkZoneS( ctx, cmdbuf, name, depth ) TracyVkZone( ctx, cmdbuf, name )+# define TracyVkZoneCS( ctx, cmdbuf, name, color, depth ) TracyVkZoneC( ctx, cmdbuf, name, color )+# define TracyVkZoneTransientS( ctx, varname, cmdbuf, name, depth, active ) TracyVkZoneTransient( ctx, varname, cmdbuf, name, active )+#endif++#endif++#endif
+ cbits/tracy/server/TracyCharUtil.hpp view
@@ -0,0 +1,76 @@+#ifndef __TRACY__CHARUTIL_HPP__+#define __TRACY__CHARUTIL_HPP__++#include <stddef.h>+#include <stdint.h>+#include <string.h>++#define XXH_INLINE_ALL+#include "tracy_xxhash.h"++namespace tracy+{+namespace charutil+{++static inline size_t hash( const char* str )+{+ const auto sz = strlen( str );+ return XXH3_64bits( str, sz );+}++static inline size_t hash( const char* str, size_t sz )+{+ return XXH3_64bits( str, sz );+}++struct Hasher+{+ size_t operator()( const char* key ) const+ {+ return hash( key );+ }+};++struct Comparator+{+ bool operator()( const char* lhs, const char* rhs ) const+ {+ return strcmp( lhs, rhs ) == 0;+ }+};++struct LessComparator+{+ bool operator()( const char* lhs, const char* rhs ) const+ {+ return strcmp( lhs, rhs ) < 0;+ }+};++struct StringKey+{+ const char* ptr;+ size_t sz;++ struct Hasher+ {+ size_t operator()( const StringKey& key ) const+ {+ return hash( key.ptr, key.sz );+ }+ };++ struct Comparator+ {+ bool operator()( const StringKey& lhs, const StringKey& rhs ) const+ {+ return lhs.sz == rhs.sz && memcmp( lhs.ptr, rhs.ptr, lhs.sz ) == 0;+ }+ };+};++}+}++#endif
+ cbits/tracy/server/TracyEvent.hpp view
@@ -0,0 +1,921 @@+#ifndef __TRACYEVENT_HPP__+#define __TRACYEVENT_HPP__++#include <assert.h>+#include <limits>+#include <stdint.h>+#include <string>+#include <string.h>++#include "TracyCharUtil.hpp"+#include "TracyShortPtr.hpp"+#include "TracySortedVector.hpp"+#include "TracyVector.hpp"+#include "tracy_robin_hood.h"+#include "../public/common/TracyForceInline.hpp"+#include "../public/common/TracyQueue.hpp"++namespace tracy+{++#pragma pack( push, 1 )++struct StringRef+{+ enum Type { Ptr, Idx };++ tracy_force_inline StringRef() : str( 0 ), __data( 0 ) {}+ tracy_force_inline StringRef( Type t, uint64_t data )+ : str( data )+ , __data( 0 )+ {+ isidx = t == Idx;+ active = 1;+ }++ uint64_t str;++ union+ {+ struct+ {+ uint8_t isidx : 1;+ uint8_t active : 1;+ };+ uint8_t __data;+ };+};++struct StringRefHasher+{+ size_t operator()( const StringRef& key ) const+ {+ return charutil::hash( (const char*)&key, sizeof( StringRef ) );+ }+};++struct StringRefComparator+{+ bool operator()( const StringRef& lhs, const StringRef& rhs ) const+ {+ return memcmp( &lhs, &rhs, sizeof( StringRef ) ) == 0;+ }+};++class StringIdx+{+public:+ tracy_force_inline StringIdx() { memset( m_idx, 0, sizeof( m_idx ) ); }+ tracy_force_inline StringIdx( uint32_t idx )+ {+ SetIdx( idx );+ }++ tracy_force_inline void SetIdx( uint32_t idx )+ {+ idx++;+ memcpy( m_idx, &idx, 3 );+ }++ tracy_force_inline uint32_t Idx() const+ {+ uint32_t idx = 0;+ memcpy( &idx, m_idx, 3 );+ assert( idx != 0 );+ return idx - 1;+ }++ tracy_force_inline bool Active() const+ {+ uint32_t zero = 0;+ return memcmp( m_idx, &zero, 3 ) != 0;+ }++private:+ uint8_t m_idx[3];+};++struct StringIdxHasher+{+ size_t operator()( const StringIdx& key ) const+ {+ return charutil::hash( (const char*)&key, sizeof( StringIdx ) );+ }+};++struct StringIdxComparator+{+ bool operator()( const StringIdx& lhs, const StringIdx& rhs ) const+ {+ return memcmp( &lhs, &rhs, sizeof( StringIdx ) ) == 0;+ }+};++class Int24+{+public:+ tracy_force_inline Int24() { memset( m_val, 0, sizeof( m_val ) ); }+ tracy_force_inline Int24( uint32_t val )+ {+ SetVal( val );+ }++ tracy_force_inline void SetVal( uint32_t val )+ {+ memcpy( m_val, &val, 2 );+ val >>= 16;+ memcpy( m_val+2, &val, 1 );+ }++ tracy_force_inline uint32_t Val() const+ {+ uint8_t hi;+ memcpy( &hi, m_val+2, 1 );+ uint16_t lo;+ memcpy( &lo, m_val, 2 );+ return ( uint32_t( hi ) << 16 ) | lo;+ }++private:+ uint8_t m_val[3];+};++class Int48+{+public:+ tracy_force_inline Int48() {}+ tracy_force_inline Int48( int64_t val )+ {+ SetVal( val );+ }++ tracy_force_inline void Clear()+ {+ memset( m_val, 0, 6 );+ }++ tracy_force_inline void SetVal( int64_t val )+ {+ memcpy( m_val, &val, 4 );+ val >>= 32;+ memcpy( m_val+4, &val, 2 );+ }++ tracy_force_inline int64_t Val() const+ {+ int16_t hi;+ memcpy( &hi, m_val+4, 2 );+ uint32_t lo;+ memcpy( &lo, m_val, 4 );+ return ( int64_t( uint64_t( hi ) << 32 ) ) | lo;+ }++ tracy_force_inline bool IsNonNegative() const+ {+ return ( m_val[5] >> 7 ) == 0;+ }++private:+ uint8_t m_val[6];+};++struct Int48Sort { bool operator()( const Int48& lhs, const Int48& rhs ) const { return lhs.Val() < rhs.Val(); }; };+++struct SourceLocationBase+{+ StringRef name;+ StringRef function;+ StringRef file;+ uint32_t line;+ uint32_t color;+};++struct SourceLocation : public SourceLocationBase+{+ mutable uint32_t namehash;+};++enum { SourceLocationSize = sizeof( SourceLocation ) };+++struct ZoneEvent+{+ tracy_force_inline ZoneEvent() {};++ tracy_force_inline int64_t Start() const { return int64_t( _start_srcloc ) >> 16; }+ tracy_force_inline void SetStart( int64_t start ) { assert( start < (int64_t)( 1ull << 47 ) ); memcpy( ((char*)&_start_srcloc)+2, &start, 4 ); memcpy( ((char*)&_start_srcloc)+6, ((char*)&start)+4, 2 ); }+ tracy_force_inline int64_t End() const { return int64_t( _end_child1 ) >> 16; }+ tracy_force_inline void SetEnd( int64_t end ) { assert( end < (int64_t)( 1ull << 47 ) ); memcpy( ((char*)&_end_child1)+2, &end, 4 ); memcpy( ((char*)&_end_child1)+6, ((char*)&end)+4, 2 ); }+ tracy_force_inline bool IsEndValid() const { return ( _end_child1 >> 63 ) == 0; }+ tracy_force_inline int16_t SrcLoc() const { return int16_t( _start_srcloc & 0xFFFF ); }+ tracy_force_inline void SetSrcLoc( int16_t srcloc ) { memcpy( &_start_srcloc, &srcloc, 2 ); }+ tracy_force_inline int32_t Child() const { int32_t child; memcpy( &child, &_child2, 4 ); return child; }+ tracy_force_inline void SetChild( int32_t child ) { memcpy( &_child2, &child, 4 ); }+ tracy_force_inline bool HasChildren() const { uint8_t tmp; memcpy( &tmp, ((char*)&_end_child1)+1, 1 ); return ( tmp >> 7 ) == 0; }++ tracy_force_inline void SetStartSrcLoc( int64_t start, int16_t srcloc ) { assert( start < (int64_t)( 1ull << 47 ) ); start <<= 16; start |= uint16_t( srcloc ); memcpy( &_start_srcloc, &start, 8 ); }++ uint64_t _start_srcloc;+ uint16_t _child2;+ uint64_t _end_child1;+ uint32_t extra;+};++enum { ZoneEventSize = sizeof( ZoneEvent ) };+static_assert( std::is_standard_layout<ZoneEvent>::value, "ZoneEvent is not standard layout" );+++struct ZoneExtra+{+ Int24 callstack;+ StringIdx text;+ StringIdx name;+ Int24 color;+};++enum { ZoneExtraSize = sizeof( ZoneExtra ) };+++// This union exploits the fact that the current implementations of x64 and arm64 do not provide+// full 64 bit address space. The high bits must be bit-extended, so 0x80... is an invalid pointer.+// This allows using the highest bit as a selector between a native pointer and a table index here.+union CallstackFrameId+{+ struct+ {+ uint64_t idx : 62;+ uint64_t sel : 1;+ uint64_t custom : 1;+ };+ uint64_t data;+};++enum { CallstackFrameIdSize = sizeof( CallstackFrameId ) };++static tracy_force_inline bool operator==( const CallstackFrameId& lhs, const CallstackFrameId& rhs ) { return lhs.data == rhs.data; }+++struct SampleData+{+ Int48 time;+ Int24 callstack;+};++enum { SampleDataSize = sizeof( SampleData ) };++struct SampleDataSort { bool operator()( const SampleData& lhs, const SampleData& rhs ) const { return lhs.time.Val() < rhs.time.Val(); }; };+++struct SampleDataRange+{+ Int48 time;+ uint16_t thread;+ CallstackFrameId ip;+};++enum { SampleDataRangeSize = sizeof( SampleDataRange ) };+++struct HwSampleData+{+ SortedVector<Int48, Int48Sort> cycles;+ SortedVector<Int48, Int48Sort> retired;+ SortedVector<Int48, Int48Sort> cacheRef;+ SortedVector<Int48, Int48Sort> cacheMiss;+ SortedVector<Int48, Int48Sort> branchRetired;+ SortedVector<Int48, Int48Sort> branchMiss;++ bool is_sorted() const+ {+ return+ cycles.is_sorted() &&+ retired.is_sorted() &&+ cacheRef.is_sorted() &&+ cacheMiss.is_sorted() &&+ branchRetired.is_sorted() &&+ branchMiss.is_sorted();+ }++ void sort()+ {+ if( !cycles.is_sorted() ) cycles.sort();+ if( !retired.is_sorted() ) retired.sort();+ if( !cacheRef.is_sorted() ) cacheRef.sort();+ if( !cacheMiss.is_sorted() ) cacheMiss.sort();+ if( !branchRetired.is_sorted() ) branchRetired.sort();+ if( !branchMiss.is_sorted() ) branchMiss.sort();+ }+};++enum { HwSampleDataSize = sizeof( HwSampleData ) };+++struct LockEvent+{+ enum class Type : uint8_t+ {+ Wait,+ Obtain,+ Release,+ WaitShared,+ ObtainShared,+ ReleaseShared+ };++ tracy_force_inline int64_t Time() const { return int64_t( _time_srcloc ) >> 16; }+ tracy_force_inline void SetTime( int64_t time ) { assert( time < (int64_t)( 1ull << 47 ) ); memcpy( ((char*)&_time_srcloc)+2, &time, 4 ); memcpy( ((char*)&_time_srcloc)+6, ((char*)&time)+4, 2 ); }+ tracy_force_inline int16_t SrcLoc() const { return int16_t( _time_srcloc & 0xFFFF ); }+ tracy_force_inline void SetSrcLoc( int16_t srcloc ) { memcpy( &_time_srcloc, &srcloc, 2 ); }++ uint64_t _time_srcloc;+ uint8_t thread;+ Type type;+};++struct LockEventShared : public LockEvent+{+ uint64_t waitShared;+ uint64_t sharedList;+};++struct LockEventPtr+{+ short_ptr<LockEvent> ptr;+ uint8_t lockingThread;+ uint8_t lockCount;+ uint64_t waitList;+};++enum { LockEventSize = sizeof( LockEvent ) };+enum { LockEventSharedSize = sizeof( LockEventShared ) };+enum { LockEventPtrSize = sizeof( LockEventPtr ) };++enum { MaxLockThreads = sizeof( LockEventPtr::waitList ) * 8 };+static_assert( std::numeric_limits<decltype(LockEventPtr::lockCount)>::max() >= MaxLockThreads, "Not enough space for lock count." );+++enum class LockType : uint8_t;++struct LockMap+{+ struct TimeRange+ {+ int64_t start = std::numeric_limits<int64_t>::max();+ int64_t end = std::numeric_limits<int64_t>::min();+ };++ StringIdx customName;+ int16_t srcloc;+ Vector<LockEventPtr> timeline;+ unordered_flat_map<uint64_t, uint8_t> threadMap;+ std::vector<uint64_t> threadList;+ LockType type;+ int64_t timeAnnounce;+ int64_t timeTerminate;+ bool valid;+ bool isContended;+ uint64_t lockingThread;++ TimeRange range[64];+};++struct LockHighlight+{+ int64_t id;+ int64_t begin;+ int64_t end;+ uint8_t thread;+ bool blocked;+};+++struct GpuEvent+{+ tracy_force_inline int64_t CpuStart() const { return int64_t( _cpuStart_srcloc ) >> 16; }+ tracy_force_inline void SetCpuStart( int64_t cpuStart ) { assert( cpuStart < (int64_t)( 1ull << 47 ) ); memcpy( ((char*)&_cpuStart_srcloc)+2, &cpuStart, 4 ); memcpy( ((char*)&_cpuStart_srcloc)+6, ((char*)&cpuStart)+4, 2 ); }+ tracy_force_inline int64_t CpuEnd() const { return int64_t( _cpuEnd_thread ) >> 16; }+ tracy_force_inline void SetCpuEnd( int64_t cpuEnd ) { assert( cpuEnd < (int64_t)( 1ull << 47 ) ); memcpy( ((char*)&_cpuEnd_thread)+2, &cpuEnd, 4 ); memcpy( ((char*)&_cpuEnd_thread)+6, ((char*)&cpuEnd)+4, 2 ); }+ tracy_force_inline int64_t GpuStart() const { return int64_t( _gpuStart_child1 ) >> 16; }+ tracy_force_inline void SetGpuStart( int64_t gpuStart ) { /*assert( gpuStart < (int64_t)( 1ull << 47 ) );*/ memcpy( ((char*)&_gpuStart_child1)+2, &gpuStart, 4 ); memcpy( ((char*)&_gpuStart_child1)+6, ((char*)&gpuStart)+4, 2 ); }+ tracy_force_inline int64_t GpuEnd() const { return int64_t( _gpuEnd_child2 ) >> 16; }+ tracy_force_inline void SetGpuEnd( int64_t gpuEnd ) { assert( gpuEnd < (int64_t)( 1ull << 47 ) ); memcpy( ((char*)&_gpuEnd_child2)+2, &gpuEnd, 4 ); memcpy( ((char*)&_gpuEnd_child2)+6, ((char*)&gpuEnd)+4, 2 ); }+ tracy_force_inline int16_t SrcLoc() const { return int16_t( _cpuStart_srcloc & 0xFFFF ); }+ tracy_force_inline void SetSrcLoc( int16_t srcloc ) { memcpy( &_cpuStart_srcloc, &srcloc, 2 ); }+ tracy_force_inline uint16_t Thread() const { return uint16_t( _cpuEnd_thread & 0xFFFF ); }+ tracy_force_inline void SetThread( uint16_t thread ) { memcpy( &_cpuEnd_thread, &thread, 2 ); }+ tracy_force_inline int32_t Child() const { return int32_t( uint32_t( _gpuStart_child1 & 0xFFFF ) | ( uint32_t( _gpuEnd_child2 & 0xFFFF ) << 16 ) ); }+ tracy_force_inline void SetChild( int32_t child ) { memcpy( &_gpuStart_child1, &child, 2 ); memcpy( &_gpuEnd_child2, ((char*)&child)+2, 2 ); }++ uint64_t _cpuStart_srcloc;+ uint64_t _cpuEnd_thread;+ uint64_t _gpuStart_child1;+ uint64_t _gpuEnd_child2;+ Int24 callstack;+};++enum { GpuEventSize = sizeof( GpuEvent ) };+static_assert( std::is_standard_layout<GpuEvent>::value, "GpuEvent is not standard layout" );+++struct MemEvent+{+ tracy_force_inline uint64_t Ptr() const { return uint64_t( int64_t( _ptr_csalloc1 ) >> 8 ); }+ tracy_force_inline void SetPtr( uint64_t ptr ) { memcpy( ((char*)&_ptr_csalloc1)+1, &ptr, 4 ); memcpy( ((char*)&_ptr_csalloc1)+5, ((char*)&ptr)+4, 2 ); memcpy( ((char*)&_ptr_csalloc1)+7, ((char*)&ptr)+6, 1 ); }+ tracy_force_inline uint64_t Size() const { return _size_csalloc2 >> 16; }+ tracy_force_inline void SetSize( uint64_t size ) { assert( size < ( 1ull << 47 ) ); memcpy( ((char*)&_size_csalloc2)+2, &size, 4 ); memcpy( ((char*)&_size_csalloc2)+6, ((char*)&size)+4, 2 ); }+ tracy_force_inline uint32_t CsAlloc() const { return uint8_t( _ptr_csalloc1 ) | ( uint16_t( _size_csalloc2 ) << 8 ); }+ tracy_force_inline void SetCsAlloc( uint32_t csAlloc ) { memcpy( &_ptr_csalloc1, &csAlloc, 1 ); memcpy( &_size_csalloc2, ((char*)&csAlloc)+1, 2 ); }+ tracy_force_inline int64_t TimeAlloc() const { return int64_t( _time_thread_alloc ) >> 16; }+ tracy_force_inline void SetTimeAlloc( int64_t time ) { assert( time < (int64_t)( 1ull << 47 ) ); memcpy( ((char*)&_time_thread_alloc)+2, &time, 4 ); memcpy( ((char*)&_time_thread_alloc)+6, ((char*)&time)+4, 2 ); }+ tracy_force_inline int64_t TimeFree() const { return int64_t( _time_thread_free ) >> 16; }+ tracy_force_inline void SetTimeFree( int64_t time ) { assert( time < (int64_t)( 1ull << 47 ) ); memcpy( ((char*)&_time_thread_free)+2, &time, 4 ); memcpy( ((char*)&_time_thread_free)+6, ((char*)&time)+4, 2 ); }+ tracy_force_inline uint16_t ThreadAlloc() const { return uint16_t( _time_thread_alloc ); }+ tracy_force_inline void SetThreadAlloc( uint16_t thread ) { memcpy( &_time_thread_alloc, &thread, 2 ); }+ tracy_force_inline uint16_t ThreadFree() const { return uint16_t( _time_thread_free ); }+ tracy_force_inline void SetThreadFree( uint16_t thread ) { memcpy( &_time_thread_free, &thread, 2 ); }++ tracy_force_inline void SetTimeThreadAlloc( int64_t time, uint16_t thread ) { time <<= 16; time |= thread; memcpy( &_time_thread_alloc, &time, 8 ); }+ tracy_force_inline void SetTimeThreadFree( int64_t time, uint16_t thread ) { uint64_t t; memcpy( &t, &time, 8 ); t <<= 16; t |= thread; memcpy( &_time_thread_free, &t, 8 ); }++ uint64_t _ptr_csalloc1;+ uint64_t _size_csalloc2;+ Int24 csFree;+ uint64_t _time_thread_alloc;+ uint64_t _time_thread_free;+};++enum { MemEventSize = sizeof( MemEvent ) };+static_assert( std::is_standard_layout<MemEvent>::value, "MemEvent is not standard layout" );+++struct CallstackFrameBasic+{+ StringIdx name;+ StringIdx file;+ uint32_t line;+};++struct CallstackFrame : public CallstackFrameBasic+{+ uint64_t symAddr;+};++struct SymbolData : public CallstackFrameBasic+{+ StringIdx imageName;+ StringIdx callFile;+ uint32_t callLine;+ uint8_t isInline;+ Int24 size;+};++enum { CallstackFrameBasicSize = sizeof( CallstackFrameBasic ) };+enum { CallstackFrameSize = sizeof( CallstackFrame ) };+enum { SymbolDataSize = sizeof( SymbolData ) };+++struct SymbolLocation+{+ uint64_t addr;+ uint32_t len;+};++enum { SymbolLocationSize = sizeof( SymbolLocation ) };+++struct CallstackFrameData+{+ short_ptr<CallstackFrame> data;+ uint8_t size;+ StringIdx imageName;+};++enum { CallstackFrameDataSize = sizeof( CallstackFrameData ) };+++struct MemCallstackFrameTree+{+ MemCallstackFrameTree( CallstackFrameId id ) : frame( id ), alloc( 0 ), count( 0 ) {}++ CallstackFrameId frame;+ uint64_t alloc;+ uint32_t count;+ unordered_flat_map<uint64_t, MemCallstackFrameTree> children;+ unordered_flat_set<uint32_t> callstacks;+};++enum { MemCallstackFrameTreeSize = sizeof( MemCallstackFrameTree ) };+++struct CallstackFrameTree+{+ CallstackFrameTree( CallstackFrameId id ) : frame( id ), count( 0 ) {}++ CallstackFrameId frame;+ uint32_t count;+ unordered_flat_map<uint64_t, CallstackFrameTree> children;+};++enum { CallstackFrameTreeSize = sizeof( CallstackFrameTree ) };+++struct CrashEvent+{+ uint64_t thread = 0;+ int64_t time = 0;+ uint64_t message = 0;+ uint32_t callstack = 0;+};++enum { CrashEventSize = sizeof( CrashEvent ) };++/**+* Represents a context switch.+* Start is the when the thread wakes up (if known).+* End is when the context switch to another thread (or idle) happens.+*/+struct ContextSwitchData+{+ enum CSReason : int8_t {+ Wakeup = -2,+ Fiber = 99,+ NoState = 100,++ // See KWAIT_REASON in the WDK's wdm.h+ Win32_Executive = 0 ,+ Win32_FreePage = 1 ,+ Win32_PageIn = 2 ,+ Win32_PoolAllocation = 3 ,+ Win32_DelayExecution = 4 ,+ Win32_Suspended = 5 ,+ Win32_UserRequest = 6 ,+ Win32_WrExecutive = 7 ,+ Win32_WrFreePage = 8 ,+ Win32_WrPageIn = 9 ,+ Win32_WrPoolAllocation = 10,+ Win32_WrDelayExecution = 11,+ Win32_WrSuspended = 12,+ Win32_WrUserRequest = 13,+ Win32_WrEventPair = 14,+ Win32_WrQueue = 15,+ Win32_WrLpcReceive = 16,+ Win32_WrLpcReply = 17,+ Win32_WrVirtualMemory = 18,+ Win32_WrPageOut = 19,+ Win32_WrRendezvous = 20,+ Win32_WrKeyedEvent = 21,+ Win32_WrTerminated = 22,+ Win32_WrProcessInSwap = 23,+ Win32_WrCpuRateControl = 24,+ Win32_WrCalloutStack = 25,+ Win32_WrKernel = 26,+ Win32_WrResource = 27,+ Win32_WrPushLock = 28,+ Win32_WrMutex = 29,+ Win32_WrQuantumEnd = 30,+ Win32_WrDispatchInt = 31,+ Win32_WrPreempted = 32,+ Win32_WrYieldExecution = 33,+ Win32_WrFastMutex = 34,+ Win32_WrGuardedMutex = 35,+ Win32_WrRundown = 36,+ Win32_WrAlertByThreadId = 37,+ Win32_WrDeferredPreempt = 38,+ Win32_WrPhysicalFault = 39,+ Win32_WrIoRing = 40,+ Win32_WrMdlCache = 41,+ Win32_WrRcu = 42,+ Win32_MaximumWaitReason,+ };++ tracy_force_inline int64_t Start() const { return _start.Val(); }+ tracy_force_inline void SetStart( int64_t start ) { assert( start < (int64_t)( 1ull << 47 ) ); _start.SetVal(start); }+ tracy_force_inline int64_t End() const { return _end.Val(); }+ tracy_force_inline void SetEnd( int64_t end ) { assert( end < (int64_t)( 1ull << 47 ) ); _end = end; }+ tracy_force_inline bool IsEndValid() const { return _end.IsNonNegative(); }+ tracy_force_inline uint8_t Cpu() const { return _cpu; }+ tracy_force_inline void SetCpu( uint8_t cpu ) { _cpu = cpu; }+ tracy_force_inline uint8_t WakeupCpu() const { return _wakeupcpu; }+ tracy_force_inline void SetWakeupCpu( uint8_t wakeupcpu) { _wakeupcpu = wakeupcpu; }+ tracy_force_inline CSReason Reason() const { return CSReason( _reason ); }+ tracy_force_inline void SetReason( int8_t reason ) { _reason = reason; }+ tracy_force_inline int8_t State() const { return _state; }+ tracy_force_inline void SetState( int8_t state ) { _state = state; }+ tracy_force_inline int64_t WakeupVal() const { return _wakeup.Val(); }+ tracy_force_inline void SetWakeup( int64_t wakeup ) { assert( wakeup < (int64_t)( 1ull << 47 ) ); _wakeup.SetVal( wakeup ); }+ tracy_force_inline uint16_t Thread() const { return _thread; }+ tracy_force_inline void SetThread( uint16_t thread ) { _thread = thread; }++ Int48 _start;+ uint8_t _cpu;+ uint8_t _wakeupcpu;+ + Int48 _end;+ int8_t _reason;+ int8_t _state;+ + Int48 _wakeup;+ uint16_t _thread; // currently unused ? Could store next thread or prios here.+};++enum { ContextSwitchDataSize = sizeof( ContextSwitchData ) };+++struct ContextSwitchCpu+{+ tracy_force_inline int64_t Start() const { return int64_t( _start_thread ) >> 16; }+ tracy_force_inline void SetStart( int64_t start ) { assert( start < (int64_t)( 1ull << 47 ) ); memcpy( ((char*)&_start_thread)+2, &start, 4 ); memcpy( ((char*)&_start_thread)+6, ((char*)&start)+4, 2 ); }+ tracy_force_inline int64_t End() const { int64_t v; memcpy( &v, ((char*)&_end)-2, 8 ); return v >> 16; }+ tracy_force_inline void SetEnd( int64_t end ) { assert( end < (int64_t)( 1ull << 47 ) ); _end.SetVal( end ); }+ tracy_force_inline bool IsEndValid() const { return _end.IsNonNegative(); }+ tracy_force_inline uint16_t Thread() const { return uint16_t( _start_thread ); }+ tracy_force_inline void SetThread( uint16_t thread ) { memcpy( &_start_thread, &thread, 2 ); }++ tracy_force_inline void SetStartThread( int64_t start, uint16_t thread ) { assert( start < (int64_t)( 1ull << 47 ) ); _start_thread = ( uint64_t( start ) << 16 ) | thread; }++ uint64_t _start_thread;+ Int48 _end;+};++enum { ContextSwitchCpuSize = sizeof( ContextSwitchCpu ) };+++struct ContextSwitchUsage+{+ ContextSwitchUsage() {}+ ContextSwitchUsage( int64_t time, uint8_t other, uint8_t own ) { SetTime( time ); SetOther( other ); SetOwn( own ); }++ tracy_force_inline int64_t Time() const { return int64_t( _time_other_own ) >> 16; }+ tracy_force_inline void SetTime( int64_t time ) { assert( time < (int64_t)( 1ull << 47 ) ); memcpy( ((char*)&_time_other_own)+2, &time, 4 ); memcpy( ((char*)&_time_other_own)+6, ((char*)&time)+4, 2 ); }+ tracy_force_inline uint8_t Other() const { return uint8_t( _time_other_own ); }+ tracy_force_inline void SetOther( uint8_t other ) { memcpy( &_time_other_own, &other, 1 ); }+ tracy_force_inline uint8_t Own() const { uint8_t v; memcpy( &v, ((char*)&_time_other_own)+1, 1 );return v; }+ tracy_force_inline void SetOwn( uint8_t own ) { memcpy( ((char*)&_time_other_own)+1, &own, 1 ); }++ uint64_t _time_other_own;+};++enum { ContextSwitchUsageSize = sizeof( ContextSwitchUsage ) };+++struct MessageData+{+ int64_t time;+ StringRef ref;+ uint16_t thread;+ uint32_t color;+ Int24 callstack;+};++enum { MessageDataSize = sizeof( MessageData ) };+++struct PlotItem+{+ Int48 time;+ double val;+};++enum { PlotItemSize = sizeof( PlotItem ) };+++struct FrameEvent+{+ int64_t start;+ int64_t end;+ int32_t frameImage;+};++enum { FrameEventSize = sizeof( FrameEvent ) };+++struct FrameImage+{+ short_ptr<const char> ptr;+ uint32_t csz;+ uint16_t w, h;+ uint32_t frameRef;+ uint8_t flip;+};++enum { FrameImageSize = sizeof( FrameImage ) };+++struct GhostZone+{+ Int48 start, end;+ Int24 frame;+ int32_t child;+};++enum { GhostZoneSize = sizeof( GhostZone ) };+++struct ChildSample+{+ Int48 time;+ uint64_t addr;+};++enum { ChildSampleSize = sizeof( ChildSample ) };++#pragma pack( pop )+++struct ThreadData+{+ uint64_t id;+ uint64_t count;+ Vector<short_ptr<ZoneEvent>> timeline;+ Vector<short_ptr<ZoneEvent>> stack;+ Vector<short_ptr<MessageData>> messages;+ uint32_t nextZoneId;+ Vector<uint32_t> zoneIdStack;+#ifndef TRACY_NO_STATISTICS+ Vector<int64_t> childTimeStack;+ Vector<GhostZone> ghostZones;+ uint64_t ghostIdx;+ SortedVector<SampleData, SampleDataSort> postponedSamples;+#endif+ Vector<SampleData> samples;+ SampleData pendingSample;+ Vector<SampleData> ctxSwitchSamples;+ uint64_t kernelSampleCnt;+ uint8_t isFiber;+ ThreadData* fiber;+ uint8_t* stackCount;+ int32_t groupHint;++ tracy_force_inline void IncStackCount( int16_t srcloc ) { stackCount[uint16_t(srcloc)]++; }+ tracy_force_inline bool DecStackCount( int16_t srcloc ) { return --stackCount[uint16_t(srcloc)] != 0; }+};++struct GpuCtxThreadData+{+ Vector<short_ptr<GpuEvent>> timeline;+ Vector<short_ptr<GpuEvent>> stack;+};++struct GpuCtxData+{+ int64_t timeDiff;+ uint64_t thread;+ uint64_t count;+ float period;+ GpuContextType type;+ bool hasPeriod;+ bool hasCalibration;+ int64_t calibratedGpuTime;+ int64_t calibratedCpuTime;+ double calibrationMod;+ int64_t lastGpuTime;+ uint64_t overflow;+ uint32_t overflowMul;+ StringIdx name;+ unordered_flat_map<uint64_t, GpuCtxThreadData> threadData;+ short_ptr<GpuEvent> query[64*1024];+};++enum { GpuCtxDataSize = sizeof( GpuCtxData ) };+++enum class PlotType : uint8_t+{+ User,+ Memory,+ SysTime,+ Power+};++// Keep this in sync with enum in TracyC.h+enum class PlotValueFormatting : uint8_t+{+ Number,+ Memory,+ Percentage,+ Watt+};++struct PlotData+{+ struct PlotItemSort { bool operator()( const PlotItem& lhs, const PlotItem& rhs ) const { return lhs.time.Val() < rhs.time.Val(); }; };++ uint64_t name;+ double min;+ double max;+ double sum;+ SortedVector<PlotItem, PlotItemSort> data;+ PlotType type;+ PlotValueFormatting format;+ uint8_t showSteps;+ uint8_t fill;+ uint32_t color;++ double rMin, rMax, num;+};++struct MemData+{+ Vector<MemEvent> data;+ Vector<uint32_t> frees;+ unordered_flat_map<uint64_t, size_t> active;+ uint64_t high = std::numeric_limits<uint64_t>::min();+ uint64_t low = std::numeric_limits<uint64_t>::max();+ uint64_t usage = 0;+ PlotData* plot = nullptr;+ bool reconstruct = false;+ uint64_t name = 0;+};++struct FrameData+{+ uint64_t name;+ Vector<FrameEvent> frames;+ uint8_t continuous;++ int64_t min = std::numeric_limits<int64_t>::max();+ int64_t max = std::numeric_limits<int64_t>::min();+ int64_t total = 0;+ double sumSq = 0;+};++struct StringLocation+{+ const char* ptr;+ uint32_t idx;+};++struct SourceLocationHasher+{+ size_t operator()( const SourceLocation* ptr ) const+ {+ return charutil::hash( (const char*)ptr, sizeof( SourceLocationBase ) );+ }+};++struct SourceLocationComparator+{+ bool operator()( const SourceLocation* lhs, const SourceLocation* rhs ) const+ {+ return memcmp( lhs, rhs, sizeof( SourceLocationBase ) ) == 0;+ }+};+++struct ContextSwitch+{+ Vector<ContextSwitchData> v;+ struct {+ int64_t time = 0;+ uint8_t cpu = -1;+ } pendingWakeUp;+ int64_t runningTime = 0;+};++struct CpuData+{+ Vector<ContextSwitchCpu> cs;+};++struct CpuThreadData+{+ int64_t runningTime = 0;+ uint32_t runningRegions = 0;+ uint32_t migrations = 0;+};++enum { CpuThreadDataSize = sizeof( CpuThreadData ) };+++struct Parameter+{+ uint32_t idx;+ StringRef name;+ bool isBool;+ int32_t val;+};+++struct SymbolStats+{+ uint32_t incl, excl;+ unordered_flat_map<uint32_t, uint32_t> parents;+ unordered_flat_map<uint32_t, uint32_t> baseParents;+};++enum { SymbolStatsSize = sizeof( SymbolStats ) };+++struct FlameGraphItem+{+ int64_t srcloc;+ int64_t time;+ StringIdx name;+ int64_t begin;+ std::vector<FlameGraphItem> children;+};++}++#endif
+ cbits/tracy/server/TracyFileHeader.hpp view
@@ -0,0 +1,22 @@+#ifndef __TRACYFILEHEADER_HPP__+#define __TRACYFILEHEADER_HPP__++#include <stdint.h>++#include "../public/common/TracyForceInline.hpp"++namespace tracy+{++static const uint8_t TracyHeader[4] = { 't', 'r', 253, 'P' };+static const uint8_t Lz4Header[4] = { 't', 'l', 'Z', 4 };+static const uint8_t ZstdHeader[4] = { 't', 'Z', 's', 't' };++static constexpr tracy_force_inline int FileVersion( uint8_t h5, uint8_t h6, uint8_t h7 )+{+ return ( h5 << 16 ) | ( h6 << 8 ) | h7;+}++}++#endif
+ cbits/tracy/server/TracyFileMeta.hpp view
@@ -0,0 +1,18 @@+#ifndef __TRACYFILEMETA_HPP__+#define __TRACYFILEMETA_HPP__++#include <algorithm>+#include <stddef.h>+#include <zstd.h>++#include "../public/common/tracy_lz4.hpp"++namespace tracy+{++constexpr size_t FileBufSize = 64 * 1024;+constexpr size_t FileBoundSize = std::max( LZ4_COMPRESSBOUND( FileBufSize ), ZSTD_COMPRESSBOUND( FileBufSize ) );++}++#endif
+ cbits/tracy/server/TracyFileRead.hpp view
@@ -0,0 +1,600 @@+#ifndef __TRACYFILEREAD_HPP__+#define __TRACYFILEREAD_HPP__++#include <assert.h>+#include <atomic>+#include <algorithm>+#include <condition_variable>+#include <stdexcept>+#include <stdio.h>+#include <string.h>+#include <string>+#include <sys/stat.h>+#include <thread>+#include <utility>+#include <vector>+#include <zstd.h>++#ifdef _MSC_VER+# define stat64 _stat64+#endif+#if defined __APPLE__ || defined __FreeBSD__+# define stat64 stat+#endif++#include "TracyFileHeader.hpp"+#include "TracyFileMeta.hpp"+#include "TracyMmap.hpp"+#include "../public/common/TracyYield.hpp"+#include "../public/common/tracy_lz4.hpp"+#include "../public/common/TracyForceInline.hpp"++namespace tracy+{++struct NotTracyDump : public std::exception {};+struct FileReadError : public std::exception {};++class ReadStream+{+public:+ ReadStream( uint8_t type )+ : m_stream( nullptr )+ , m_streamZstd( nullptr )+ , m_buf( new char[FileBufSize] )+ , m_second( new char[FileBufSize] )+ {+ switch( type )+ {+ case 0:+ m_stream = LZ4_createStreamDecode();+ break;+ case 1:+ m_streamZstd = ZSTD_createDStream();+ break;+ default:+ assert( false );+ break;+ }+ }++ ~ReadStream()+ {+ delete[] m_buf;+ delete[] m_second;++ if( m_stream ) LZ4_freeStreamDecode( m_stream );+ if( m_streamZstd ) ZSTD_freeDStream( m_streamZstd );+ }++ void Decompress( const char* src, uint32_t size )+ {+ std::swap( m_buf, m_second );+ if( m_stream )+ {+ m_size = (size_t)LZ4_decompress_safe_continue( m_stream, src, m_buf, size, FileBufSize );+ }+ else+ {+ ZSTD_outBuffer out = { m_buf, FileBufSize, 0 };+ ZSTD_inBuffer in = { src, size, 0 };+ ZSTD_decompressStream( m_streamZstd, &out, &in );+ m_size = out.pos;+ }+ }++ const char* GetBuffer() const { return m_buf; }+ size_t GetSize() const { return m_size; }++private:+ LZ4_streamDecode_t* m_stream;+ ZSTD_DStream* m_streamZstd;++ char* m_buf;+ char* m_second;++ size_t m_size;+};++class FileRead+{+ struct StreamHandle+ {+ StreamHandle( uint8_t type ) : stream( type ), outputReady( false ) {}++ ReadStream stream;+ const char* src;+ uint32_t size;++ bool inputReady = false;+ bool exit = false;+ alignas(64) std::atomic<bool> outputReady;++ std::mutex signalLock;+ std::condition_variable signal;++ std::thread thread;+ };++public:+ static FileRead* Open( const char* fn )+ {+ auto f = fopen( fn, "rb" );+ return f ? new FileRead( f, fn ) : nullptr;+ }++ ~FileRead()+ {+ for( auto& v : m_streams )+ {+ std::lock_guard lock( v->signalLock );+ v->exit = true;+ v->signal.notify_one();+ }+ for( auto& v : m_streams ) v->thread.join();+ m_streams.clear();+ if( m_data ) munmap( m_data, m_dataSize );+ }++ tracy_force_inline void Read( void* ptr, size_t size )+ {+ if( size <= FileBufSize - m_offset )+ {+ ReadSmall( ptr, size );+ }+ else+ {+ ReadBig( ptr, size );+ }+ }++ tracy_force_inline void Skip( size_t size )+ {+ if( size <= FileBufSize - m_offset )+ {+ m_offset += size;+ }+ else+ {+ SkipBig( size );+ }+ }++ template<class T>+ tracy_force_inline void Read( T& v )+ {+ if( sizeof( T ) <= FileBufSize - m_offset )+ {+ memcpy( &v, m_buf + m_offset, sizeof( T ) );+ m_offset += sizeof( T );+ }+ else+ {+ T tmp;+ ReadBig( &tmp, sizeof( T ) );+ memcpy( &v, &tmp, sizeof( T ) );+ }+ }++ template<class T, class U>+ tracy_force_inline void Read2( T& v0, U& v1 )+ {+ if( sizeof( T ) + sizeof( U ) <= FileBufSize - m_offset )+ {+ memcpy( &v0, m_buf + m_offset, sizeof( T ) );+ memcpy( &v1, m_buf + m_offset + sizeof( T ), sizeof( U ) );+ m_offset += sizeof( T ) + sizeof( U );+ }+ else+ {+ char tmp[sizeof( T ) + sizeof( U )];+ ReadBig( tmp, sizeof( T ) + sizeof( U ) );+ memcpy( &v0, tmp, sizeof( T ) );+ memcpy( &v1, tmp + sizeof( T ), sizeof( U ) );+ }+ }++ template<class T, class U, class V>+ tracy_force_inline void Read3( T& v0, U& v1, V& v2 )+ {+ if( sizeof( T ) + sizeof( U ) + sizeof( V ) <= FileBufSize - m_offset )+ {+ memcpy( &v0, m_buf + m_offset, sizeof( T ) );+ memcpy( &v1, m_buf + m_offset + sizeof( T ), sizeof( U ) );+ memcpy( &v2, m_buf + m_offset + sizeof( T ) + sizeof( U ), sizeof( V ) );+ m_offset += sizeof( T ) + sizeof( U ) + sizeof( V );+ }+ else+ {+ char tmp[sizeof( T ) + sizeof( U ) + sizeof( V )];+ ReadBig( tmp, sizeof( T ) + sizeof( U ) + sizeof( V ) );+ memcpy( &v0, tmp, sizeof( T ) );+ memcpy( &v1, tmp + sizeof( T ), sizeof( U ) );+ memcpy( &v2, tmp + sizeof( T ) + sizeof( U ), sizeof( V ) );+ }+ }++ template<class T, class U, class V, class W>+ tracy_force_inline void Read4( T& v0, U& v1, V& v2, W& v3 )+ {+ if( sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) <= FileBufSize - m_offset )+ {+ memcpy( &v0, m_buf + m_offset, sizeof( T ) );+ memcpy( &v1, m_buf + m_offset + sizeof( T ), sizeof( U ) );+ memcpy( &v2, m_buf + m_offset + sizeof( T ) + sizeof( U ), sizeof( V ) );+ memcpy( &v3, m_buf + m_offset + sizeof( T ) + sizeof( U ) + sizeof( V ), sizeof( W ) );+ m_offset += sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W );+ }+ else+ {+ char tmp[sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W )];+ ReadBig( tmp, sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) );+ memcpy( &v0, tmp, sizeof( T ) );+ memcpy( &v1, tmp + sizeof( T ), sizeof( U ) );+ memcpy( &v2, tmp + sizeof( T ) + sizeof( U ), sizeof( V ) );+ memcpy( &v3, tmp + sizeof( T ) + sizeof( U ) + sizeof( V ), sizeof( W ) );+ }+ }++ template<class T, class U, class V, class W, class X>+ tracy_force_inline void Read5( T& v0, U& v1, V& v2, W& v3, X& v4 )+ {+ if( sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) <= FileBufSize - m_offset )+ {+ memcpy( &v0, m_buf + m_offset, sizeof( T ) );+ memcpy( &v1, m_buf + m_offset + sizeof( T ), sizeof( U ) );+ memcpy( &v2, m_buf + m_offset + sizeof( T ) + sizeof( U ), sizeof( V ) );+ memcpy( &v3, m_buf + m_offset + sizeof( T ) + sizeof( U ) + sizeof( V ), sizeof( W ) );+ memcpy( &v4, m_buf + m_offset + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ), sizeof( X ) );+ m_offset += sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X );+ }+ else+ {+ char tmp[sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X )];+ ReadBig( tmp, sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) );+ memcpy( &v0, tmp, sizeof( T ) );+ memcpy( &v1, tmp + sizeof( T ), sizeof( U ) );+ memcpy( &v2, tmp + sizeof( T ) + sizeof( U ), sizeof( V ) );+ memcpy( &v3, tmp + sizeof( T ) + sizeof( U ) + sizeof( V ), sizeof( W ) );+ memcpy( &v4, tmp + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ), sizeof( X ) );+ }+ }++ template<class T, class U, class V, class W, class X, class Y>+ tracy_force_inline void Read6( T& v0, U& v1, V& v2, W& v3, X& v4, Y& v5 )+ {+ if( sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ) <= FileBufSize - m_offset )+ {+ memcpy( &v0, m_buf + m_offset, sizeof( T ) );+ memcpy( &v1, m_buf + m_offset + sizeof( T ), sizeof( U ) );+ memcpy( &v2, m_buf + m_offset + sizeof( T ) + sizeof( U ), sizeof( V ) );+ memcpy( &v3, m_buf + m_offset + sizeof( T ) + sizeof( U ) + sizeof( V ), sizeof( W ) );+ memcpy( &v4, m_buf + m_offset + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ), sizeof( X ) );+ memcpy( &v5, m_buf + m_offset + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ), sizeof( Y ) );+ m_offset += sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y );+ }+ else+ {+ char tmp[sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y )];+ ReadBig( tmp, sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ) );+ memcpy( &v0, tmp, sizeof( T ) );+ memcpy( &v1, tmp + sizeof( T ), sizeof( U ) );+ memcpy( &v2, tmp + sizeof( T ) + sizeof( U ), sizeof( V ) );+ memcpy( &v3, tmp + sizeof( T ) + sizeof( U ) + sizeof( V ), sizeof( W ) );+ memcpy( &v4, tmp + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ), sizeof( X ) );+ memcpy( &v5, tmp + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ), sizeof( Y ) );+ }+ }++ template<class T, class U, class V, class W, class X, class Y, class Z>+ tracy_force_inline void Read7( T& v0, U& v1, V& v2, W& v3, X& v4, Y& v5, Z& v6 )+ {+ if( sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ) + sizeof( Z ) <= FileBufSize - m_offset )+ {+ memcpy( &v0, m_buf + m_offset, sizeof( T ) );+ memcpy( &v1, m_buf + m_offset + sizeof( T ), sizeof( U ) );+ memcpy( &v2, m_buf + m_offset + sizeof( T ) + sizeof( U ), sizeof( V ) );+ memcpy( &v3, m_buf + m_offset + sizeof( T ) + sizeof( U ) + sizeof( V ), sizeof( W ) );+ memcpy( &v4, m_buf + m_offset + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ), sizeof( X ) );+ memcpy( &v5, m_buf + m_offset + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ), sizeof( Y ) );+ memcpy( &v6, m_buf + m_offset + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ), sizeof( Z ) );+ m_offset += sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ) + sizeof( Z );+ }+ else+ {+ char tmp[sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ) + sizeof( Z )];+ ReadBig( tmp, sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ) + sizeof( Z ) );+ memcpy( &v0, tmp, sizeof( T ) );+ memcpy( &v1, tmp + sizeof( T ), sizeof( U ) );+ memcpy( &v2, tmp + sizeof( T ) + sizeof( U ), sizeof( V ) );+ memcpy( &v3, tmp + sizeof( T ) + sizeof( U ) + sizeof( V ), sizeof( W ) );+ memcpy( &v4, tmp + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ), sizeof( X ) );+ memcpy( &v5, tmp + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ), sizeof( Y ) );+ memcpy( &v6, tmp + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ), sizeof( Z ) );+ }+ }++ template<class T, class U, class V, class W, class X, class Y, class Z, class A>+ tracy_force_inline void Read8( T& v0, U& v1, V& v2, W& v3, X& v4, Y& v5, Z& v6, A& v7 )+ {+ if( sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ) + sizeof( Z ) + sizeof( A ) <= FileBufSize - m_offset )+ {+ memcpy( &v0, m_buf + m_offset, sizeof( T ) );+ memcpy( &v1, m_buf + m_offset + sizeof( T ), sizeof( U ) );+ memcpy( &v2, m_buf + m_offset + sizeof( T ) + sizeof( U ), sizeof( V ) );+ memcpy( &v3, m_buf + m_offset + sizeof( T ) + sizeof( U ) + sizeof( V ), sizeof( W ) );+ memcpy( &v4, m_buf + m_offset + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ), sizeof( X ) );+ memcpy( &v5, m_buf + m_offset + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ), sizeof( Y ) );+ memcpy( &v6, m_buf + m_offset + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ), sizeof( Z ) );+ memcpy( &v7, m_buf + m_offset + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ) + sizeof( Z ), sizeof( A ) );+ m_offset += sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ) + sizeof( Z ) + sizeof( A );+ }+ else+ {+ char tmp[sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ) + sizeof( Z ) + sizeof( A )];+ ReadBig( tmp, sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ) + sizeof( Z ) + sizeof( A ) );+ memcpy( &v0, tmp, sizeof( T ) );+ memcpy( &v1, tmp + sizeof( T ), sizeof( U ) );+ memcpy( &v2, tmp + sizeof( T ) + sizeof( U ), sizeof( V ) );+ memcpy( &v3, tmp + sizeof( T ) + sizeof( U ) + sizeof( V ), sizeof( W ) );+ memcpy( &v4, tmp + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ), sizeof( X ) );+ memcpy( &v5, tmp + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ), sizeof( Y ) );+ memcpy( &v6, tmp + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ), sizeof( Z ) );+ memcpy( &v7, tmp + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ) + sizeof( Z ), sizeof( A ) );+ }+ }++ template<class T, class U, class V, class W, class X, class Y, class Z, class A, class B>+ tracy_force_inline void Read9( T& v0, U& v1, V& v2, W& v3, X& v4, Y& v5, Z& v6, A& v7, B& v8 )+ {+ if( sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ) + sizeof( Z ) + sizeof( A ) + sizeof( B ) <= FileBufSize - m_offset )+ {+ memcpy( &v0, m_buf + m_offset, sizeof( T ) );+ memcpy( &v1, m_buf + m_offset + sizeof( T ), sizeof( U ) );+ memcpy( &v2, m_buf + m_offset + sizeof( T ) + sizeof( U ), sizeof( V ) );+ memcpy( &v3, m_buf + m_offset + sizeof( T ) + sizeof( U ) + sizeof( V ), sizeof( W ) );+ memcpy( &v4, m_buf + m_offset + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ), sizeof( X ) );+ memcpy( &v5, m_buf + m_offset + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ), sizeof( Y ) );+ memcpy( &v6, m_buf + m_offset + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ), sizeof( Z ) );+ memcpy( &v7, m_buf + m_offset + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ) + sizeof( Z ), sizeof( A ) );+ memcpy( &v8, m_buf + m_offset + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ) + sizeof( Z ) + sizeof( A ), sizeof( B ) );+ m_offset += sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ) + sizeof( Z ) + sizeof( A ) + sizeof( B );+ }+ else+ {+ char tmp[sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ) + sizeof( Z ) + sizeof( A ) + sizeof( B )];+ ReadBig( tmp, sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ) + sizeof( Z ) + sizeof( A ) + sizeof( B ) );+ memcpy( &v0, tmp, sizeof( T ) );+ memcpy( &v1, tmp + sizeof( T ), sizeof( U ) );+ memcpy( &v2, tmp + sizeof( T ) + sizeof( U ), sizeof( V ) );+ memcpy( &v3, tmp + sizeof( T ) + sizeof( U ) + sizeof( V ), sizeof( W ) );+ memcpy( &v4, tmp + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ), sizeof( X ) );+ memcpy( &v5, tmp + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ), sizeof( Y ) );+ memcpy( &v6, tmp + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ), sizeof( Z ) );+ memcpy( &v7, tmp + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ) + sizeof( Z ), sizeof( A ) );+ memcpy( &v8, tmp + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ) + sizeof( Z ) + sizeof( A ), sizeof( B ) );+ }+ }++ template<class T, class U, class V, class W, class X, class Y, class Z, class A, class B, class C>+ tracy_force_inline void Read10( T& v0, U& v1, V& v2, W& v3, X& v4, Y& v5, Z& v6, A& v7, B& v8, C& v9 )+ {+ if( sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ) + sizeof( Z ) + sizeof( A ) + sizeof( B ) + sizeof( C ) <= FileBufSize - m_offset )+ {+ memcpy( &v0, m_buf + m_offset, sizeof( T ) );+ memcpy( &v1, m_buf + m_offset + sizeof( T ), sizeof( U ) );+ memcpy( &v2, m_buf + m_offset + sizeof( T ) + sizeof( U ), sizeof( V ) );+ memcpy( &v3, m_buf + m_offset + sizeof( T ) + sizeof( U ) + sizeof( V ), sizeof( W ) );+ memcpy( &v4, m_buf + m_offset + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ), sizeof( X ) );+ memcpy( &v5, m_buf + m_offset + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ), sizeof( Y ) );+ memcpy( &v6, m_buf + m_offset + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ), sizeof( Z ) );+ memcpy( &v7, m_buf + m_offset + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ) + sizeof( Z ), sizeof( A ) );+ memcpy( &v8, m_buf + m_offset + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ) + sizeof( Z ) + sizeof( A ), sizeof( B ) );+ memcpy( &v9, m_buf + m_offset + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ) + sizeof( Z ) + sizeof( A ) + sizeof( B ), sizeof( C ) );+ m_offset += sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ) + sizeof( Z ) + sizeof( A ) + sizeof( B ) + sizeof( C );+ }+ else+ {+ char tmp[sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ) + sizeof( Z ) + sizeof( A ) + sizeof( B ) + sizeof( C )];+ ReadBig( tmp, sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ) + sizeof( Z ) + sizeof( A ) + sizeof( B ) + sizeof( C ) );+ memcpy( &v0, tmp, sizeof( T ) );+ memcpy( &v1, tmp + sizeof( T ), sizeof( U ) );+ memcpy( &v2, tmp + sizeof( T ) + sizeof( U ), sizeof( V ) );+ memcpy( &v3, tmp + sizeof( T ) + sizeof( U ) + sizeof( V ), sizeof( W ) );+ memcpy( &v4, tmp + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ), sizeof( X ) );+ memcpy( &v5, tmp + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ), sizeof( Y ) );+ memcpy( &v6, tmp + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ), sizeof( Z ) );+ memcpy( &v7, tmp + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ) + sizeof( Z ), sizeof( A ) );+ memcpy( &v8, tmp + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ) + sizeof( Z ) + sizeof( A ), sizeof( B ) );+ memcpy( &v9, tmp + sizeof( T ) + sizeof( U ) + sizeof( V ) + sizeof( W ) + sizeof( X ) + sizeof( Y ) + sizeof( Z ) + sizeof( A ) + sizeof( B ), sizeof( C ) );+ }+ }++ const std::string& GetFilename() const { return m_filename; }++private:+ FileRead( FILE* f, const char* fn )+ : m_data( nullptr )+ , m_offset( 0 )+ , m_streamId( 0 )+ , m_filename( fn )+ {+ char hdr[4];+ if( fread( hdr, 1, sizeof( hdr ), f ) != sizeof( hdr ) )+ {+ fclose( f );+ throw NotTracyDump();+ }++ uint8_t streams = 1;+ uint8_t type;+ m_dataOffset = sizeof( hdr );++ if( memcmp( hdr, TracyHeader, sizeof( hdr ) ) == 0 )+ {+ if( fread( &type, 1, 1, f ) != 1 || type > 1 )+ {+ fclose( f );+ throw NotTracyDump();+ }+ if( fread( &streams, 1, 1, f ) != 1 )+ {+ fclose( f );+ throw NotTracyDump();+ }+ m_dataOffset += 2;+ }+ else if( memcmp( hdr, Lz4Header, sizeof( hdr ) ) == 0 )+ {+ type = 0;+ }+ else if( memcmp( hdr, ZstdHeader, sizeof( hdr ) ) == 0 )+ {+ type = 1;+ }+ else+ {+ fclose( f );+ throw NotTracyDump();+ }++ struct stat64 buf;+ if( stat64( fn, &buf ) == 0 )+ {+ m_dataSize = buf.st_size;+ }+ else+ {+ fclose( f );+ throw FileReadError();+ }++ m_data = (char*)mmap( nullptr, m_dataSize, PROT_READ, MAP_SHARED, fileno( f ), 0 );+ fclose( f );+ if( !m_data )+ {+ throw FileReadError();+ }++ for( int i=0; i<(int)streams; i++ )+ {+ if( m_dataOffset == m_dataSize ) break;++ const auto sz = ReadBlockSize();+ auto uptr = std::make_unique<StreamHandle>( type );+ uptr->src = m_data + m_dataOffset;+ uptr->size = sz;+ uptr->inputReady = true;+ uptr->thread = std::thread( [ptr = uptr.get()] { Worker( ptr ); } );+ m_streams.emplace_back( std::move( uptr ) );+ m_dataOffset += sz;+ }++ GetNextDataBlock();+ }++ tracy_force_inline uint32_t ReadBlockSize()+ {+ uint32_t sz;+ memcpy( &sz, m_data + m_dataOffset, sizeof( sz ) );+ m_dataOffset += sizeof( sz );+ return sz;+ }++ static void Worker( StreamHandle* hnd )+ {+ for(;;)+ {+ std::unique_lock lock( hnd->signalLock );+ hnd->signal.wait( lock, [&] { return hnd->inputReady || hnd->exit; } );+ if( hnd->exit ) return;+ lock.unlock();++ hnd->stream.Decompress( hnd->src, hnd->size );+ hnd->inputReady = false;+ hnd->outputReady.store( true, std::memory_order_release );+ }+ }++ tracy_force_inline void ReadSmall( void* ptr, size_t size )+ {+ memcpy( ptr, m_buf + m_offset, size );+ m_offset += size;+ }++ void ReadBig( void* ptr, size_t size )+ {+ assert( size > 0 );+ auto dst = (char*)ptr;+ do+ {+ size_t sz;+ if( m_offset == FileBufSize )+ {+ sz = std::min<size_t>( size, FileBufSize );+ GetNextDataBlock();+ memcpy( dst, m_buf, sz );+ m_offset = sz;+ }+ else+ {+ sz = std::min( size, FileBufSize - m_offset );+ memcpy( dst, m_buf + m_offset, sz );+ m_offset += sz;+ }++ dst += sz;+ size -= sz;+ }+ while( size > 0 );+ }++ void SkipBig( size_t size )+ {+ while( size > 0 )+ {+ if( m_offset == FileBufSize ) GetNextDataBlock();+ const auto sz = std::min( size, FileBufSize - m_offset );+ m_offset += sz;+ size -= sz;+ }+ }++ void GetNextDataBlock()+ {+ auto& hnd = *m_streams[m_streamId];+ while( hnd.outputReady.load( std::memory_order_acquire ) == false ) { YieldThread(); }+ hnd.outputReady.store( false, std::memory_order_relaxed );+ m_buf = hnd.stream.GetBuffer();+ m_offset = 0;++ if( m_dataOffset < m_dataSize )+ {+ const auto sz = ReadBlockSize();+ std::unique_lock lock( hnd.signalLock );+ hnd.src = m_data + m_dataOffset;+ hnd.size = sz;+ hnd.inputReady = true;+ hnd.signal.notify_one();+ lock.unlock();+ m_dataOffset += sz;+ }++ m_streamId = ( m_streamId + 1 ) % m_streams.size();+ }++ char* m_data;+ const char* m_buf;+ uint64_t m_dataSize;+ uint64_t m_dataOffset;+ size_t m_offset;+ int m_streamId;++ std::string m_filename;++ std::vector<std::unique_ptr<StreamHandle>> m_streams;+};++}++#endif
+ cbits/tracy/server/TracyFileWrite.hpp view
@@ -0,0 +1,303 @@+#ifndef __TRACYFILEWRITE_HPP__+#define __TRACYFILEWRITE_HPP__++#ifdef _MSC_VER+# pragma warning( disable: 4267 ) // conversion from don't care to whatever, possible loss of data +#endif++#include <algorithm>+#include <assert.h>+#include <condition_variable>+#include <mutex>+#include <stdio.h>+#include <string.h>+#include <thread>+#include <utility>+#include <vector>+#include <zstd.h>++#include "TracyFileHeader.hpp"+#include "TracyFileMeta.hpp"+#include "../public/common/tracy_lz4.hpp"+#include "../public/common/tracy_lz4hc.hpp"+#include "../public/common/TracyForceInline.hpp"++namespace tracy+{++enum class FileCompression+{+ Fast,+ Slow,+ Extreme,+ Zstd+};++class WriteStream+{+public:+ WriteStream( FileCompression comp, int level )+ : m_stream( nullptr )+ , m_streamHC( nullptr )+ , m_streamZstd( nullptr )+ , m_buf( new char[FileBufSize] )+ , m_second( new char[FileBufSize] )+ , m_compressed( new char[FileBoundSize] )+ {+ switch( comp )+ {+ case FileCompression::Fast:+ m_stream = LZ4_createStream();+ break;+ case FileCompression::Slow:+ m_streamHC = LZ4_createStreamHC();+ break;+ case FileCompression::Extreme:+ m_streamHC = LZ4_createStreamHC();+ LZ4_resetStreamHC( m_streamHC, LZ4HC_CLEVEL_MAX );+ break;+ case FileCompression::Zstd:+ m_streamZstd = ZSTD_createCStream();+ ZSTD_CCtx_setParameter( m_streamZstd, ZSTD_c_compressionLevel, level );+ ZSTD_CCtx_setParameter( m_streamZstd, ZSTD_c_contentSizeFlag, 0 );+ break;+ default:+ assert( false );+ break;+ }+ }++ ~WriteStream()+ {+ delete[] m_buf;+ delete[] m_second;+ delete[] m_compressed;++ if( m_stream ) LZ4_freeStream( m_stream );+ if( m_streamHC ) LZ4_freeStreamHC( m_streamHC );+ if( m_streamZstd ) ZSTD_freeCStream( m_streamZstd );+ }++ char* GetInputBuffer() { return m_buf; }+ const char* GetCompressedData() const { return m_compressed; }+ uint32_t GetSize() const { return m_size; }++ void Compress( uint32_t sz )+ {+ if( m_stream )+ {+ m_size = LZ4_compress_fast_continue( m_stream, m_buf, m_compressed, sz, FileBoundSize, 1 );+ }+ else if( m_streamZstd )+ {+ ZSTD_outBuffer out = { m_compressed, FileBoundSize, 0 };+ ZSTD_inBuffer in = { m_buf, sz, 0 };+ const auto ret = ZSTD_compressStream2( m_streamZstd, &out, &in, ZSTD_e_flush );+ assert( ret == 0 );+ m_size = out.pos;+ }+ else+ {+ m_size = LZ4_compress_HC_continue( m_streamHC, m_buf, m_compressed, sz, FileBoundSize );+ }++ std::swap( m_buf, m_second );+ }++private:+ LZ4_stream_t* m_stream;+ LZ4_streamHC_t* m_streamHC;+ ZSTD_CStream* m_streamZstd;++ char* m_buf;+ char* m_second;+ char* m_compressed;+ uint32_t m_size;+};++class FileWrite+{+ struct StreamHandle+ {+ StreamHandle( FileCompression comp, int level ) : stream( comp, level ) {}++ WriteStream stream;+ uint32_t size;++ bool inputReady = false;+ bool outputReady = false;+ bool exit = false;++ std::mutex signalLock;+ std::condition_variable signal;++ std::thread thread;+ };++public:+ static FileWrite* Open( const char* fn, FileCompression comp = FileCompression::Fast, int level = 1, int streams = -1 )+ {+ auto f = fopen( fn, "wb" );+ if( !f ) return nullptr;+ if( streams <= 0 ) streams = std::max<int>( 1, std::thread::hardware_concurrency() );+ if( streams > 255 ) streams = 255;+ return new FileWrite( f, comp, level, streams );+ }++ ~FileWrite()+ {+ Finish();+ fclose( m_file );+ }++ void Finish()+ {+ if( m_offset > 0 ) WriteBlock();+ while( m_streamPending > 0 ) ProcessPending();+ for( auto& v : m_streams )+ {+ std::lock_guard lock( v->signalLock );+ v->exit = true;+ v->signal.notify_one();+ }+ for( auto& v : m_streams ) v->thread.join();+ m_streams.clear();+ }++ tracy_force_inline void Write( const void* ptr, size_t size )+ {+ if( m_offset + size <= FileBufSize )+ {+ WriteSmall( ptr, size );+ }+ else+ {+ WriteBig( ptr, size );+ }+ }++ std::pair<size_t, size_t> GetCompressionStatistics() const { return std::make_pair( m_srcBytes, m_dstBytes ); }++private:+ FileWrite( FILE* f, FileCompression comp, int level, int streams )+ : m_offset( 0 )+ , m_file( f )+ , m_srcBytes( 0 )+ , m_dstBytes( 0 )+ {+ assert( streams > 0 );+ assert( streams < 256 );++ fwrite( TracyHeader, 1, sizeof( TracyHeader ), m_file );+ uint8_t u8 = comp == FileCompression::Zstd ? 1 : 0;+ fwrite( &u8, 1, 1, m_file );+ u8 = streams;+ fwrite( &u8, 1, 1, m_file );++ m_streams.reserve( streams );+ for( int i=0; i<streams; i++ )+ {+ auto uptr = std::make_unique<StreamHandle>( comp, level );+ uptr->thread = std::thread( [ptr = uptr.get()]{ Worker( ptr ); } );+ m_streams.emplace_back( std::move( uptr ) );+ }++ m_buf = m_streams[m_streamId]->stream.GetInputBuffer();+ }++ tracy_force_inline void WriteSmall( const void* ptr, size_t size )+ {+ memcpy( m_buf + m_offset, ptr, size );+ m_offset += size;+ }++ void WriteBig( const void* ptr, size_t size )+ {+ auto src = (const char*)ptr;+ while( size > 0 )+ {+ const auto sz = std::min( size, FileBufSize - m_offset );+ memcpy( m_buf + m_offset, src, sz );+ m_offset += sz;+ src += sz;+ size -= sz;++ if( m_offset == FileBufSize )+ {+ WriteBlock();+ }+ }+ }++ void WriteBlock()+ {+ m_srcBytes += m_offset;++ auto& hnd = *m_streams[m_streamId];+ assert( hnd.stream.GetInputBuffer() == m_buf );++ std::unique_lock lock( hnd.signalLock );+ hnd.inputReady = true;+ hnd.size = m_offset;+ hnd.signal.notify_one();+ lock.unlock();++ m_streamPending++;+ m_streamId = ( m_streamId + 1 ) % m_streams.size();+ if( m_streamPending == m_streams.size() ) ProcessPending();++ m_offset = 0;+ m_buf = m_streams[m_streamId]->stream.GetInputBuffer();+ }++ void ProcessPending()+ {+ assert( m_streamPending > 0 );+ int id = ( m_streamId + m_streams.size() - m_streamPending ) % m_streams.size();+ m_streamPending--;+ auto& hnd = *m_streams[id];++ std::unique_lock lock( hnd.signalLock );+ hnd.signal.wait( lock, [&hnd]{ return hnd.outputReady; } );+ lock.unlock();++ hnd.outputReady = false;+ const uint32_t size = hnd.stream.GetSize();+ m_dstBytes += size;+ fwrite( &size, 1, sizeof( size ), m_file );+ fwrite( hnd.stream.GetCompressedData(), 1, size, m_file );+ }++ static void Worker( StreamHandle* hnd )+ {+ std::unique_lock lock( hnd->signalLock );+ for(;;)+ {+ hnd->signal.wait( lock, [&hnd]{ return hnd->inputReady || hnd->exit; } );+ if( hnd->exit ) return;+ lock.unlock();++ hnd->stream.Compress( hnd->size );+ hnd->inputReady = false;++ lock.lock();+ hnd->outputReady = true;+ hnd->signal.notify_one();+ }+ }++ char* m_buf;+ size_t m_offset;++ int m_streamId = 0;+ int m_streamPending = 0;+ std::vector<std::unique_ptr<StreamHandle>> m_streams;+ FILE* m_file;++ size_t m_srcBytes;+ size_t m_dstBytes;+};++}++#endif
+ cbits/tracy/server/TracyMemory.cpp view
@@ -0,0 +1,8 @@+#include "TracyMemory.hpp"++namespace tracy+{++std::atomic<int64_t> memUsage( 0 );++}
+ cbits/tracy/server/TracyMemory.hpp view
@@ -0,0 +1,14 @@+#ifndef __TRACYMEMORY_HPP__+#define __TRACYMEMORY_HPP__++#include <atomic>+#include <stdint.h>++namespace tracy+{++extern std::atomic<int64_t> memUsage;++}++#endif
+ cbits/tracy/server/TracyMmap.cpp view
@@ -0,0 +1,38 @@+#include "TracyMmap.hpp"++#if defined _WIN32+# include <io.h>+# include <windows.h>++void* mmap( void* addr, size_t length, int prot, int flags, int fd, off_t offset )+{+ HANDLE hnd;+ void* map = nullptr;++ switch( prot )+ {+ case PROT_READ:+ if( hnd = CreateFileMapping( HANDLE( _get_osfhandle( fd ) ), nullptr, PAGE_READONLY, 0, 0, nullptr ) )+ {+ map = MapViewOfFile( hnd, FILE_MAP_READ, 0, 0, length );+ CloseHandle( hnd );+ }+ break;+ case PROT_WRITE:+ if( hnd = CreateFileMapping( HANDLE( _get_osfhandle( fd ) ), nullptr, PAGE_READWRITE, 0, 0, nullptr ) )+ {+ map = MapViewOfFile( hnd, FILE_MAP_WRITE, 0, 0, length );+ CloseHandle( hnd );+ }+ break;+ }++ return map ? (char*)map + offset : (void*)-1;+}++int munmap( void* addr, size_t length )+{+ return UnmapViewOfFile( addr ) != 0 ? 0 : -1;+}++#endif
+ cbits/tracy/server/TracyMmap.hpp view
@@ -0,0 +1,19 @@+#ifndef __TRACYMMAP_HPP__+#define __TRACYMMAP_HPP__++#if !defined _WIN32+# include <sys/mman.h>+#else+# include <string.h>+# include <sys/types.h>++# define PROT_READ 1+# define PROT_WRITE 2+# define MAP_SHARED 0++void* mmap( void* addr, size_t length, int prot, int flags, int fd, off_t offset );+int munmap( void* addr, size_t length );++#endif++#endif
+ cbits/tracy/server/TracyPopcnt.hpp view
@@ -0,0 +1,40 @@+#ifndef __TRACYPOPCNT_HPP__+#define __TRACYPOPCNT_HPP__++#include <limits.h>+#include <stdint.h>++#if defined _WIN64+# include <intrin.h>+# define TracyCountBits __popcnt64+# define TracyLzcnt __lzcnt64+#elif defined __GNUC__ || defined __clang__+static inline uint64_t TracyCountBits( uint64_t i )+{+ return uint64_t( __builtin_popcountll( i ) );+}+static inline uint64_t TracyLzcnt( uint64_t i )+{+ return uint64_t( __builtin_clzll( i ) );+}+#else+static inline uint64_t TracyCountBits( uint64_t i )+{+ i = i - ( (i >> 1) & 0x5555555555555555 );+ i = ( i & 0x3333333333333333 ) + ( (i >> 2) & 0x3333333333333333 );+ i = ( (i + (i >> 4) ) & 0x0F0F0F0F0F0F0F0F );+ return ( i * (0x0101010101010101) ) >> 56;+}+static inline uint64_t TracyLzcnt( uint64_t i )+{+ i |= i >> 1;+ i |= i >> 2;+ i |= i >> 4;+ i |= i >> 8;+ i |= i >> 16;+ i |= i >> 32;+ return 64 - TracyCountBits( i );+}+#endif++#endif
+ cbits/tracy/server/TracyPrint.cpp view
@@ -0,0 +1,464 @@+#ifdef _MSC_VER+# pragma warning( disable: 4244 ) // conversion from don't care to whatever, possible loss of data+#endif+#ifdef __MINGW32__+# define __STDC_FORMAT_MACROS+#endif++#include <assert.h>+#include <inttypes.h>+#include <math.h>+#include <stdint.h>+#include <stdio.h>+#include <stdlib.h> // llabs()+#include <string.h>++#include "TracyPrint.hpp"++namespace tracy+{++static const char* IntTable100 =+ "00010203040506070809"+ "10111213141516171819"+ "20212223242526272829"+ "30313233343536373839"+ "40414243444546474849"+ "50515253545556575859"+ "60616263646566676869"+ "70717273747576777879"+ "80818283848586878889"+ "90919293949596979899";++static inline void PrintTinyInt( char*& buf, uint64_t v )+{+ assert( v < 100 );+ if( v >= 10 )+ {+ *buf++ = '0' + v/10;+ }+ *buf++ = '0' + v%10;+}++static inline void PrintTinyInt0( char*& buf, uint64_t v )+{+ assert( v < 100 );+ if( v >= 10 )+ {+ *buf++ = '0' + v/10;+ }+ else+ {+ *buf++ = '0';+ }+ *buf++ = '0' + v%10;+}++static inline void PrintSmallInt( char*& buf, uint64_t v )+{+ assert( v < 1000 );+ if( v >= 100 )+ {+ memcpy( buf, IntTable100 + v/10*2, 2 );+ buf += 2;+ }+ else if( v >= 10 )+ {+ *buf++ = '0' + v/10;+ }+ *buf++ = '0' + v%10;+}++static inline void PrintSmallInt0( char*& buf, uint64_t v )+{+ assert( v < 1000 );+ if( v >= 100 )+ {+ memcpy( buf, IntTable100 + v/10*2, 2 );+ buf += 2;+ }+ else if( v >= 10 )+ {+ *buf++ = '0';+ *buf++ = '0' + v/10;+ }+ else+ {+ memcpy( buf, "00", 2 );+ buf += 2;+ }+ *buf++ = '0' + v%10;+}++static inline void PrintFrac00( char*& buf, uint64_t v )+{+ *buf++ = '.';+ v += 5;+ if( v/10%10 == 0 )+ {+ *buf++ = '0' + v/100;+ }+ else+ {+ memcpy( buf, IntTable100 + v/10*2, 2 );+ buf += 2;+ }+}++static inline void PrintFrac0( char*& buf, uint64_t v )+{+ *buf++ = '.';+ *buf++ = '0' + (v+50)/100;+}++static inline void PrintSmallIntFrac( char*& buf, uint64_t v )+{+ uint64_t in = v / 1000;+ uint64_t fr = v % 1000;+ if( fr >= 995 )+ {+ if( in < 999 )+ {+ PrintSmallInt( buf, in+1 );+ }+ else+ {+ memcpy( buf, "1000", 4 );+ buf += 4;+ }+ }+ else+ {+ PrintSmallInt( buf, in );+ if( fr > 5 )+ {+ PrintFrac00( buf, fr );+ }+ }+}++static inline void PrintSecondsFrac( char*& buf, uint64_t v )+{+ uint64_t in = v / 1000;+ uint64_t fr = v % 1000;+ if( fr >= 950 )+ {+ PrintTinyInt0( buf, in+1 );+ }+ else+ {+ PrintTinyInt0( buf, in );+ if( fr > 50 )+ {+ PrintFrac0( buf, fr );+ }+ }+}++uint64_t _int64_abs( int64_t x )+{+ if( x < 0 )+ {+ // `-x` does not work if `x` is `std::numeric_limits<int64_t>::min()`,+ // see https://github.com/wolfpld/tracy/pull/1040+ // This works though:+ // https://graphics.stanford.edu/~seander/bithacks.html#IntegerAbs+ return -(uint64_t)x;+ }+ else+ {+ return x;+ }+}++const char* TimeToString( int64_t _ns )+{+ enum { Pool = 8 };+ static char bufpool[Pool][64];+ static int bufsel = 0;+ char* buf = bufpool[bufsel];+ char* bufstart = buf;+ bufsel = ( bufsel + 1 ) % Pool;++ uint64_t ns = _int64_abs(_ns);+ if( _ns < 0 )+ {+ *buf = '-';+ buf++;+ }++ if( ns < 1000 )+ {+ PrintSmallInt( buf, ns );+ memcpy( buf, " ns", 4 );+ }+ else if( ns < 1000ll * 1000 )+ {+ PrintSmallIntFrac( buf, ns );+ memcpy( buf, " \xce\xbcs", 5 );+ }+ else if( ns < 1000ll * 1000 * 1000 )+ {+ PrintSmallIntFrac( buf, ns / 1000 );+ memcpy( buf, " ms", 4 );+ }+ else if( ns < 1000ll * 1000 * 1000 * 60 )+ {+ PrintSmallIntFrac( buf, ns / ( 1000ll * 1000 ) );+ memcpy( buf, " s", 3 );+ }+ else if( ns < 1000ll * 1000 * 1000 * 60 * 60 )+ {+ const auto m = int64_t( ns / ( 1000ll * 1000 * 1000 * 60 ) );+ const auto s = int64_t( ns - m * ( 1000ll * 1000 * 1000 * 60 ) ) / ( 1000ll * 1000 );+ PrintTinyInt( buf, m );+ *buf++ = ':';+ PrintSecondsFrac( buf, s );+ *buf++ = '\0';+ }+ else if( ns < 1000ll * 1000 * 1000 * 60 * 60 * 24 )+ {+ const auto h = int64_t( ns / ( 1000ll * 1000 * 1000 * 60 * 60 ) );+ const auto m = int64_t( ns / ( 1000ll * 1000 * 1000 * 60 ) - h * 60 );+ const auto s = int64_t( ns / ( 1000ll * 1000 * 1000 ) - h * ( 60 * 60 ) - m * 60 );+ PrintTinyInt( buf, h );+ *buf++ = ':';+ PrintTinyInt0( buf, m );+ *buf++ = ':';+ PrintTinyInt0( buf, s );+ *buf++ = '\0';+ }+ else+ {+ const auto d = int64_t( ns / ( 1000ll * 1000 * 1000 * 60 * 60 * 24 ) );+ const auto h = int64_t( ns / ( 1000ll * 1000 * 1000 * 60 * 60 ) - d * 24 );+ const auto m = int64_t( ns / ( 1000ll * 1000 * 1000 * 60 ) - d * ( 60 * 24 ) - h * 60 );+ const auto s = int64_t( ns / ( 1000ll * 1000 * 1000 ) - d * ( 60 * 60 * 24 ) - h * ( 60 * 60 ) - m * 60 );+ assert( d < 100 );+ PrintTinyInt( buf, d );+ *buf++ = 'd';+ PrintTinyInt0( buf, h );+ *buf++ = ':';+ PrintTinyInt0( buf, m );+ *buf++ = ':';+ PrintTinyInt0( buf, s );+ *buf++ = '\0';+ }+ return bufstart;+}++const char* TimeToStringExact( int64_t _ns )+{+ enum { Pool = 8 };+ static char bufpool[Pool][64];+ static int bufsel = 0;+ char* buf = bufpool[bufsel];+ char* bufstart = buf;+ bufsel = ( bufsel + 1 ) % Pool;++ uint64_t ns = _int64_abs(_ns);+ if( _ns < 0 )+ {+ *buf = '-';+ buf++;+ }++ const char* numStart = buf;++ if( ns >= 1000ll * 1000 * 1000 * 60 * 60 * 24 )+ {+ const auto d = int64_t( ns / ( 1000ll * 1000 * 1000 * 60 * 60 * 24 ) );+ const auto h = int64_t( ns / ( 1000ll * 1000 * 1000 * 60 * 60 ) - d * 24 );+ const auto m = int64_t( ns / ( 1000ll * 1000 * 1000 * 60 ) - d * ( 60 * 24 ) - h * 60 );+ const auto s = int64_t( ns / ( 1000ll * 1000 * 1000 ) - d * ( 60 * 60 * 24 ) - h * ( 60 * 60 ) - m * 60 );+ if( d < 100 )+ {+ PrintTinyInt( buf, d );+ *buf++ = 'd';+ }+ else+ {+ memcpy( buf, "100+d", 5 );+ buf += 5;+ }+ PrintTinyInt0( buf, h );+ *buf++ = ':';+ PrintTinyInt0( buf, m );+ *buf++ = ':';+ PrintTinyInt0( buf, s );+ ns %= 1000ll * 1000 * 1000;+ }+ else if( ns >= 1000ll * 1000 * 1000 * 60 * 60 )+ {+ const auto h = int64_t( ns / ( 1000ll * 1000 * 1000 * 60 * 60 ) );+ const auto m = int64_t( ns / ( 1000ll * 1000 * 1000 * 60 ) - h * 60 );+ const auto s = int64_t( ns / ( 1000ll * 1000 * 1000 ) - h * ( 60 * 60 ) - m * 60 );+ PrintTinyInt( buf, h );+ *buf++ = ':';+ PrintTinyInt0( buf, m );+ *buf++ = ':';+ PrintTinyInt0( buf, s );+ ns %= 1000ll * 1000 * 1000;+ }+ else if( ns >= 1000ll * 1000 * 1000 * 60 )+ {+ const auto m = int64_t( ns / ( 1000ll * 1000 * 1000 * 60 ) );+ const auto s = int64_t( ns / ( 1000ll * 1000 * 1000 ) - m * 60 );+ PrintTinyInt( buf, m );+ *buf++ = ':';+ PrintTinyInt0( buf, s );+ ns %= 1000ll * 1000 * 1000;+ }+ else if( ns >= 1000ll * 1000 * 1000 )+ {+ PrintTinyInt( buf, int64_t( ns / ( 1000ll * 1000 * 1000 ) ) );+ *buf++ = 's';+ ns %= 1000ll * 1000 * 1000;+ }++ if( ns > 0 )+ {+ if( buf != numStart ) *buf++ = ' ';+ if( ns >= 1000ll * 1000 )+ {+ PrintSmallInt0( buf, int64_t( ns / ( 1000ll * 1000 ) ) );+ *buf++ = ',';+ ns %= 1000ll * 1000;+ }+ else+ {+ memcpy( buf, "000,", 4 );+ buf += 4;+ }+ if( ns >= 1000ll )+ {+ PrintSmallInt0( buf, int64_t( ns / 1000ll ) );+ *buf++ = ',';+ ns %= 1000ll;+ }+ else+ {+ memcpy( buf, "000,", 4 );+ buf += 4;+ }+ PrintSmallInt0( buf, ns );+ *buf++ = 'n';+ *buf++ = 's';+ }+ else+ {+ memcpy( buf, "000,000,000ns", 13 );+ buf += 13;+ }++ *buf++ = '\0';++ return bufstart;+}++const char* MemSizeToString( int64_t val )+{+ enum { Pool = 8 };+ static char bufpool[Pool][64];+ static int bufsel = 0;+ char* buf = bufpool[bufsel];+ bufsel = ( bufsel + 1 ) % Pool;++ const auto aval = llabs( val );++ if( aval < 10000ll )+ {+ sprintf( buf, "%" PRIi64 " bytes", val );+ return buf;+ }++ enum class Unit+ {+ Kilobyte,+ Megabyte,+ Gigabyte,+ Terabyte+ };+ Unit unit;++ char* ptr;+ if( aval < 10000ll * 1024 )+ {+ ptr = PrintFloat( buf, buf+64, val / 1024., 2 );+ unit = Unit::Kilobyte;+ }+ else if( aval < 10000ll * 1024 * 1024 )+ {+ ptr = PrintFloat( buf, buf+64, val / ( 1024. * 1024 ), 2 );+ unit = Unit::Megabyte;+ }+ else if( aval < 10000ll * 1024 * 1024 * 1024 )+ {+ ptr = PrintFloat( buf, buf+64, val / ( 1024. * 1024 * 1024 ), 2 );+ unit = Unit::Gigabyte;+ }+ else+ {+ ptr = PrintFloat( buf, buf+64, val / ( 1024. * 1024 * 1024 * 1024 ), 2 );+ unit = Unit::Terabyte;+ }++ ptr--;+ while( ptr >= buf && *ptr == '0' ) ptr--;+ if( *ptr != '.' ) ptr++;++ *ptr++ = ' ';+ switch( unit )+ {+ case Unit::Kilobyte:+ *ptr++ = 'K';+ break;+ case Unit::Megabyte:+ *ptr++ = 'M';+ break;+ case Unit::Gigabyte:+ *ptr++ = 'G';+ break;+ case Unit::Terabyte:+ *ptr++ = 'T';+ break;+ default:+ assert( false );+ break;+ }+ *ptr++ = 'B';+ *ptr++ = '\0';++ return buf;+}++const char* LocationToString( const char* fn, uint32_t line )+{+ if( line == 0 ) return fn;++ enum { Pool = 8 };+ static char bufpool[Pool][4096];+ static int bufsel = 0;+ char* buf = bufpool[bufsel];+ bufsel = ( bufsel + 1 ) % Pool;++ sprintf( buf, "%s:%i", fn, line );+ return buf;+}++namespace detail+{++char* RealToStringGetBuffer()+{+ enum { Pool = 8 };+ static char bufpool[Pool][64];+ static int bufsel = 0;+ char* buf = bufpool[bufsel];+ bufsel = ( bufsel + 1 ) % Pool;+ return buf;+}++}++}
+ cbits/tracy/server/TracyPrint.hpp view
@@ -0,0 +1,152 @@+#ifndef __TRACYPRINT_HPP__+#define __TRACYPRINT_HPP__++#if ( defined _MSC_VER && _MSVC_LANG >= 201703L ) || __cplusplus >= 201703L+# if __has_include(<charconv>) && __has_include(<type_traits>)+# include <charconv>+# include <type_traits>+# else+# define NO_CHARCONV+# endif+#else+# define NO_CHARCONV+#endif++#if defined _MSC_VER && _MSC_VER < 1924+# define NO_CHARCONV+#endif++#ifdef __GNUC__+# define NO_CHARCONV+#endif++#ifdef NO_CHARCONV+# include <stdio.h>+#endif++#include <stdint.h>+#include <string.h>++#include "../public/common/TracyForceInline.hpp"++namespace tracy+{++namespace detail+{++char* RealToStringGetBuffer();++static tracy_force_inline void RealToStringFloating( char* ptr, char* end )+{+ if( *ptr == '-' ) ptr++;+ const auto vbegin = ptr;++ while( *ptr != '\0' && *ptr != '.' ) ptr++;+ auto sz = end - ptr + 1;++ while( ptr - vbegin > 3 )+ {+ ptr -= 3;+ memmove( ptr+1, ptr, sz+3 );+ *ptr = ',';+ sz += 4;+ }++ while( *ptr != '\0' && *ptr != '.' ) ptr++;+ if( *ptr == '\0' ) return;++ while( *ptr != '\0' ) ptr++;+ ptr--;+ while( *ptr == '0' ) ptr--;+ if( *ptr != '.' && *ptr != ',' ) ptr++;+ *ptr = '\0';+}++static tracy_force_inline void RealToStringInteger( char* buf, char* end )+{+ if( *buf == '-' ) buf++;+ auto ptr = end;+ auto sz = 1;+ while( ptr - buf > 3 )+ {+ ptr -= 3;+ memmove( ptr+1, ptr, sz+3 );+ *ptr = ',';+ sz += 4;+ }+}++}++template<typename T>+static inline char* PrintFloat( char* begin, char* end, T value, int precision )+{+#ifndef NO_CHARCONV+ return std::to_chars( begin, end, value, std::chars_format::fixed, precision ).ptr;+#else+ return begin + sprintf( begin, "%.*f", precision, value );+#endif+}++template<typename T>+static inline char* PrintFloat( char* begin, char* end, T value )+{+#ifndef NO_CHARCONV+ return std::to_chars( begin, end, value, std::chars_format::fixed ).ptr;+#else+ return begin + sprintf( begin, "%f", value );+#endif+}++#ifndef NO_CHARCONV+template<typename T>+static inline const char* RealToString( T val )+{+ auto buf = detail::RealToStringGetBuffer();+ auto end = std::to_chars( buf, buf+64, val ).ptr;+ *end = '\0';+ if constexpr ( std::is_integral_v<T> )+ {+ detail::RealToStringInteger( buf, end );+ }+ else+ {+ detail::RealToStringFloating( buf, end );+ }+ return buf;+}+#else+static inline const char* RealToString( double val )+{+ auto buf = detail::RealToStringGetBuffer();+ const auto sz = sprintf( buf, "%f", val );+ detail::RealToStringFloating( buf, buf+sz );+ return buf;+}+#endif++const char* TimeToString( int64_t ns );+const char* TimeToStringExact( int64_t ns );+const char* MemSizeToString( int64_t val );+const char* LocationToString( const char* fn, uint32_t line );++static tracy_force_inline void PrintStringPercent( char* buf, const char* string, double percent )+{+ const auto ssz = strlen( string );+ memcpy( buf, string, ssz );+ memcpy( buf+ssz, " (", 2 );+ auto end = PrintFloat( buf+ssz+2, buf+128, percent, 2 );+ memcpy( end, "%)", 3 );+}++static tracy_force_inline void PrintStringPercent( char* buf, double percent )+{+ memcpy( buf, "(", 2 );+ auto end = PrintFloat( buf+1, buf+64, percent, 2 );+ memcpy( end, "%)", 3 );+}++}++#endif
+ cbits/tracy/server/TracyShortPtr.hpp view
@@ -0,0 +1,82 @@+#ifndef __TRACYSHORTPTR_HPP__+#define __TRACYSHORTPTR_HPP__++#include <assert.h>+#include <stdint.h>+#include <string.h>++#include "../public/common/TracyForceInline.hpp"++namespace tracy+{++#if UINTPTR_MAX == 0xFFFFFFFFFFFFFFFF+template<typename T>+class short_ptr+{+public:+ tracy_force_inline short_ptr() {}+ tracy_force_inline short_ptr( const T* ptr ) { set( ptr ); }++ tracy_force_inline operator T*() { return get(); }+ tracy_force_inline operator const T*() const { return get(); }+ tracy_force_inline T& operator*() { return *get(); }+ tracy_force_inline const T& operator*() const { return *get(); }+ tracy_force_inline T* operator->() { return get(); }+ tracy_force_inline const T* operator->() const { return get(); }++ tracy_force_inline void set( const T* ptr )+ {+ assert( ( uint64_t( ptr ) & 0xFFFF000000000000 ) == 0 );+ memcpy( m_ptr, &ptr, 4 );+ memcpy( m_ptr+4, ((char*)&ptr)+4, 2 );+ }++ tracy_force_inline T* get()+ {+ uint32_t lo;+ uint16_t hi;+ memcpy( &lo, m_ptr, 4 );+ memcpy( &hi, m_ptr+4, 2 );+ return (T*)( uint64_t( lo ) | ( ( uint64_t( hi ) << 32 ) ) );+ }++ tracy_force_inline const T* get() const+ {+ uint32_t lo;+ uint16_t hi;+ memcpy( &lo, m_ptr, 4 );+ memcpy( &hi, m_ptr+4, 2 );+ return (T*)( uint64_t( lo ) | ( ( uint64_t( hi ) << 32 ) ) );+ }++private:+ uint8_t m_ptr[6];+};+#else+template<typename T>+class short_ptr+{+public:+ tracy_force_inline short_ptr() {}+ tracy_force_inline short_ptr( const T* ptr ) { memcpy( &m_ptr, &ptr, sizeof( T* ) ); }++ tracy_force_inline operator T*() { return m_ptr; }+ tracy_force_inline operator const T*() const { return m_ptr; }+ tracy_force_inline T& operator*() { return *m_ptr; }+ tracy_force_inline const T& operator*() const { return *m_ptr; }+ tracy_force_inline T* operator->() { return m_ptr; }+ tracy_force_inline const T* operator->() const { return m_ptr; }++ tracy_force_inline void set( const T* ptr ) { m_ptr = ptr; }+ tracy_force_inline T* get() { return m_ptr; }+ tracy_force_inline const T* get() const { return m_ptr; }++private:+ T* m_ptr;+};+#endif++}++#endif
+ cbits/tracy/server/TracySlab.hpp view
@@ -0,0 +1,159 @@+#ifndef __TRACYSLAB_HPP__+#define __TRACYSLAB_HPP__++#include <assert.h>+#include <stdint.h>+#include <vector>++#include "TracyMemory.hpp"+#include "../public/common/TracyForceInline.hpp"++namespace tracy+{++template<size_t BlockSize>+class Slab+{+public:+ Slab()+ : m_ptr( new char[BlockSize] )+ , m_offset( 0 )+ , m_buffer( { m_ptr } )+ , m_usage( BlockSize )+ {+ memUsage.fetch_add( BlockSize, std::memory_order_relaxed );+ }++ ~Slab()+ {+ memUsage.fetch_sub( m_usage, std::memory_order_relaxed );+ for( auto& v : m_buffer )+ {+ delete[] v;+ }+ }++ tracy_force_inline void* AllocRaw( size_t size )+ {+ assert( size <= BlockSize );+ const auto offset = m_offset;+ if( offset + size > BlockSize )+ {+ return DoAlloc( size );+ }+ else+ {+ void* ret = m_ptr + offset;+ m_offset += size;+ return ret;+ }+ }++ template<typename T>+ tracy_force_inline T* AllocInit()+ {+ const auto size = sizeof( T );+ auto ret = AllocRaw( size );+ new( ret ) T;+ return (T*)ret;+ }++ template<typename T>+ tracy_force_inline T* AllocInit( size_t sz )+ {+ const auto size = sizeof( T ) * sz;+ auto ret = AllocRaw( size );+ T* ptr = (T*)ret;+ for( size_t i=0; i<sz; i++ )+ {+ new( ptr ) T;+ ptr++;+ }+ return (T*)ret;+ }++ template<typename T>+ tracy_force_inline T* Alloc()+ {+ return (T*)AllocRaw( sizeof( T ) );+ }++ template<typename T>+ tracy_force_inline T* Alloc( size_t size )+ {+ return (T*)AllocRaw( sizeof( T ) * size );+ }++ tracy_force_inline void Unalloc( size_t size )+ {+ assert( size <= m_offset );+ m_offset -= size;+ }++ tracy_force_inline void* AllocBig( size_t size )+ {+ const auto offset = m_offset;+ if( offset + size <= BlockSize )+ {+ void* ret = m_ptr + offset;+ m_offset += size;+ return ret;+ }+ else if( size <= BlockSize && BlockSize - offset <= 1024 )+ {+ return DoAlloc( size );+ }+ else+ {+ memUsage.fetch_add( size, std::memory_order_relaxed );+ m_usage += size;+ auto ret = new char[size];+ m_buffer.emplace_back( ret );+ return ret;+ }+ }++ void Reset()+ {+ if( m_buffer.size() > 1 )+ {+ memUsage.fetch_sub( m_usage - BlockSize, std::memory_order_relaxed );+ m_usage = BlockSize;+ for( int i=1; i<m_buffer.size(); i++ )+ {+ delete[] m_buffer[i];+ }+ m_ptr = m_buffer[0];+ m_buffer.clear();+ m_buffer.emplace_back( m_ptr );+ }+ m_offset = 0;+ }++ Slab( const Slab& ) = delete;+ Slab( Slab&& ) = delete;++ Slab& operator=( const Slab& ) = delete;+ Slab& operator=( Slab&& ) = delete;++private:+ void* DoAlloc( uint32_t willUseBytes )+ {+ auto ptr = new char[BlockSize];+ m_ptr = ptr;+ m_offset = willUseBytes;+ m_buffer.emplace_back( m_ptr );+ memUsage.fetch_add( BlockSize, std::memory_order_relaxed );+ m_usage += BlockSize;+ return ptr;+ }++ char* m_ptr;+ uint32_t m_offset;+ std::vector<char*> m_buffer;+ size_t m_usage;+};++}++#endif
+ cbits/tracy/server/TracySort.hpp view
@@ -0,0 +1,10 @@+#ifndef __TRACYSORT_HPP__+#define __TRACYSORT_HPP__++#ifdef __EMSCRIPTEN__+# include "tracy_pdqsort.h"+#else+# include <ppqsort.h>+#endif++#endif
+ cbits/tracy/server/TracySortedVector.hpp view
@@ -0,0 +1,127 @@+#ifndef __TRACYSORTEDVECTOR_HPP__+#define __TRACYSORTEDVECTOR_HPP__++#include "TracySort.hpp"+#include "TracyVector.hpp"++namespace tracy+{++#pragma pack( push, 1 )+template<typename T, class CompareDefault = std::less<T>>+class SortedVector+{+public:+ using iterator = T*;+ using const_iterator = const T*;++ tracy_force_inline SortedVector()+ : sortedEnd( 0 )+ {}++ SortedVector( const SortedVector& ) = delete;+ tracy_force_inline SortedVector( SortedVector&& src ) noexcept+ : v( std::move( src.v ) )+ , sortedEnd( src.sortedEnd )+ {+ }++ tracy_force_inline SortedVector( const T& value )+ : v( value )+ , sortedEnd( 0 )+ {+ }++ SortedVector& operator=( const SortedVector& ) = delete;+ tracy_force_inline SortedVector& operator=( SortedVector&& src ) noexcept+ {+ v = std::move( src.v );+ sortedEnd = src.sortedEnd;+ return *this;+ }++ tracy_force_inline void swap( SortedVector& other )+ {+ v.swap( other.v );+ std::swap( sortedEnd, other.sortedEnd );+ }++ tracy_force_inline bool empty() const { return v.empty(); }+ tracy_force_inline size_t size() const { return v.size(); }+ tracy_force_inline bool is_sorted() const { return sortedEnd == 0; }++ tracy_force_inline T* data() { return v.data(); }+ tracy_force_inline const T* data() const { return v.data(); };++ tracy_force_inline T* begin() { return v.begin(); }+ tracy_force_inline const T* begin() const { return v.begin(); }+ tracy_force_inline T* end() { return v.end(); }+ tracy_force_inline const T* end() const { return v.end(); }++ tracy_force_inline T& front() { return v.front(); }+ tracy_force_inline const T& front() const { return v.front(); }++ tracy_force_inline T& back() { return v.back(); }+ tracy_force_inline const T& back() const { return v.back(); }++ tracy_force_inline T& operator[]( size_t idx ) { return v[idx]; }+ tracy_force_inline const T& operator[]( size_t idx ) const { return v[idx]; }++ tracy_force_inline void push_back( const T& val ) { push_back( val, CompareDefault() ); }++ template<class Compare>+ tracy_force_inline void push_back( const T& val, Compare comp )+ {+ if( sortedEnd == 0 && !v.empty() && !comp( v.back(), val ) )+ {+ sortedEnd = (uint32_t)v.size();+ }+ v.push_back( val );+ }++ tracy_force_inline void reserve( size_t cap ) { v.reserve( cap ); }+ template<size_t U>+ tracy_force_inline void reserve_exact( uint32_t sz, Slab<U>& slab ) { v.reserve_exact( sz, slab ); }++ tracy_force_inline void clear() { v.clear(); sortedEnd = 0; }++ tracy_force_inline T* erase( T* begin, T* end )+ {+ assert( is_sorted() );+ return v.erase( begin, end );+ }++ tracy_force_inline void sort() { sort( CompareDefault() ); }+ tracy_force_inline void ensure_sorted() { if( !is_sorted() ) sort(); }++ template<class Compare>+ void sort( Compare comp )+ {+ assert( !is_sorted() );+ const auto sb = v.begin();+ const auto se = sb + sortedEnd;+ const auto sl = se - 1;+ const auto ue = v.end();+#ifdef __EMSCRIPTEN__+ pdqsort_branchless( sb, se, comp );+#else+ ppqsort::sort( ppqsort::execution::par, sb, se, comp );+#endif+ const auto ss = std::lower_bound( sb, se, *se, comp );+ const auto uu = std::lower_bound( se, ue, *sl, comp );+ std::inplace_merge( ss, se, uu, comp );+ sortedEnd = 0;+ }++private:+ Vector<T> v;+ uint32_t sortedEnd;+};++#pragma pack( pop )++enum { SortedVectorSize = sizeof( SortedVector<int> ) };++}++#endif
+ cbits/tracy/server/TracyStringDiscovery.hpp view
@@ -0,0 +1,88 @@+#ifndef __TRACYSTRINGDISCOVERY_HPP__+#define __TRACYSTRINGDISCOVERY_HPP__++#include "../public/common/TracyForceInline.hpp"+#include "tracy_robin_hood.h"+#include "TracyCharUtil.hpp"+#include "TracyEvent.hpp"+#include "TracyVector.hpp"++namespace tracy+{++template<typename T>+class StringDiscovery+{+public:+ tracy_force_inline Vector<T>& Data() { return m_data; }+ tracy_force_inline const Vector<T>& Data() const { return m_data; }++ tracy_force_inline bool IsPending() const { return !m_pending.empty(); }++ // Merge( destination, postponed )+ template<typename U>+ tracy_force_inline void StringDiscovered( uint64_t name, const StringLocation& sl, U& stringMap, std::function<void(T,T)> Merge )+ {+ auto pit = m_pending.find( name );+ assert( pit != m_pending.end() );++ auto it = m_rev.find( sl.ptr );+ if( it == m_rev.end() )+ {+ m_map.emplace( name, pit->second );+ m_rev.emplace( sl.ptr, pit->second );+ m_data.push_back( pit->second );+ stringMap.emplace( name, sl.ptr );+ }+ else+ {+ auto item = it->second;+ m_map.emplace( name, item );+ Merge( item, pit->second );+ }++ m_pending.erase( pit );+ }++ tracy_force_inline T Retrieve( uint64_t name, const std::function<T(uint64_t)>& Create, const std::function<void(uint64_t)>& Query )+ {+ auto it = m_map.find( name );+ if( it == m_map.end() )+ {+ auto pit = m_pending.find( name );+ if( pit == m_pending.end() )+ {+ T item = Create( name );+ if( item )+ {+ m_pending.emplace( name, item );+ Query( name );+ }+ return item;+ }+ else+ {+ return pit->second;+ }+ }+ else+ {+ return it->second;+ }+ }++ tracy_force_inline void AddExternal( const T& val )+ {+ m_data.push_back( val );+ }++private:+ Vector<T> m_data;+ unordered_flat_map<uint64_t, T> m_pending;+ unordered_flat_map<uint64_t, T> m_map;+ unordered_flat_map<const char*, T, charutil::Hasher, charutil::Comparator> m_rev;+};++}++#endif
+ cbits/tracy/server/TracySysUtil.cpp view
@@ -0,0 +1,43 @@+++#include "TracySysUtil.hpp"++#ifdef _WIN32+# include <windows.h>+#elif defined __linux__+# include <sys/sysinfo.h>+#elif defined __APPLE__ || defined BSD+# include <sys/types.h>+# include <sys/sysctl.h>+#endif++namespace tracy+{++size_t GetPhysicalMemorySize()+{+#ifdef _WIN32+ MEMORYSTATUSEX statex;+ statex.dwLength = sizeof( statex );+ GlobalMemoryStatusEx( &statex );+ return statex.ullTotalPhys;+#elif defined __linux__+ struct sysinfo sysInfo;+ sysinfo( &sysInfo );+ return sysInfo.totalram;+#elif defined __APPLE__+ size_t memSize;+ size_t sz = sizeof( memSize );+ sysctlbyname( "hw.memsize", &memSize, &sz, nullptr, 0 );+ return memSize;+#elif defined BSD+ size_t memSize;+ size_t sz = sizeof( memSize );+ sysctlbyname( "hw.physmem", &memSize, &sz, nullptr, 0 );+ return memSize;+#else+ return 0;+#endif+}++}
+ cbits/tracy/server/TracySysUtil.hpp view
@@ -0,0 +1,13 @@+#ifndef __TRACYSYSUTIL_HPP__+#define __TRACYSYSUTIL_HPP__++#include <stdlib.h>++namespace tracy+{++size_t GetPhysicalMemorySize();++}++#endif
+ cbits/tracy/server/TracyTaskDispatch.cpp view
@@ -0,0 +1,88 @@+#include <assert.h>+#include <stdio.h>++#include "../public/common/TracySystem.hpp"+#include "TracyTaskDispatch.hpp"++namespace tracy+{++TaskDispatch::TaskDispatch( size_t workers, const char* name )+ : m_exit( false )+ , m_jobs( 0 )+{+ m_workers.reserve( workers );+ for( size_t i=0; i<workers; i++ )+ {+ m_workers.emplace_back( [this, name, i]{ SetName( name, i ); Worker(); } );+ }+}++TaskDispatch::~TaskDispatch()+{+ m_exit.store( true, std::memory_order_release );+ m_queueLock.lock();+ m_cvWork.notify_all();+ m_queueLock.unlock();++ for( auto& worker : m_workers )+ {+ worker.join();+ }+}++void TaskDispatch::Queue( const std::function<void(void)>& f )+{+ std::lock_guard<std::mutex> lock( m_queueLock );+ m_queue.emplace_back( f );+ m_cvWork.notify_one();+}++void TaskDispatch::Queue( std::function<void(void)>&& f )+{+ std::lock_guard<std::mutex> lock( m_queueLock );+ m_queue.emplace_back( std::move( f ) );+ m_cvWork.notify_one();+}++void TaskDispatch::Sync()+{+ std::unique_lock<std::mutex> lock( m_queueLock );+ while( !m_queue.empty() )+ {+ auto f = m_queue.back();+ m_queue.pop_back();+ lock.unlock();+ f();+ lock.lock();+ }+ m_cvJobs.wait( lock, [this]{ return m_jobs == 0; } );+}++void TaskDispatch::Worker()+{+ for(;;)+ {+ std::unique_lock<std::mutex> lock( m_queueLock );+ m_cvWork.wait( lock, [this]{ return !m_queue.empty() || m_exit.load( std::memory_order_acquire ); } );+ if( m_exit.load( std::memory_order_acquire ) ) return;+ auto f = m_queue.back();+ m_queue.pop_back();+ m_jobs++;+ lock.unlock();+ f();+ lock.lock();+ m_jobs--;+ if( m_jobs == 0 && m_queue.empty() ) m_cvJobs.notify_one();+ lock.unlock();+ }+}++void TaskDispatch::SetName( const char* name, size_t num )+{+ char tmp[128];+ snprintf( tmp, sizeof( tmp ), "%s #%zu", name, num );+ SetThreadName( tmp );+}++}
+ cbits/tracy/server/TracyTaskDispatch.hpp view
@@ -0,0 +1,40 @@+#ifndef __TRACYTASKDISPATCH_HPP__+#define __TRACYTASKDISPATCH_HPP__++#include <atomic>+#include <condition_variable>+#include <functional>+#include <mutex>+#include <thread>+#include <vector>++namespace tracy+{++class TaskDispatch+{+public:+ TaskDispatch( size_t workers, const char* name );+ ~TaskDispatch();++ void Queue( const std::function<void(void)>& f );+ void Queue( std::function<void(void)>&& f );++ void Sync();++private:+ void Worker();+ void SetName( const char* name, size_t num );++ std::vector<std::function<void(void)>> m_queue;+ std::mutex m_queueLock;+ std::condition_variable m_cvWork, m_cvJobs;+ std::atomic<bool> m_exit;+ size_t m_jobs;++ std::vector<std::thread> m_workers;+};++}++#endif
+ cbits/tracy/server/TracyTextureCompression.cpp view
@@ -0,0 +1,211 @@+#include <zstd.h>++#include "TracyEvent.hpp"+#include "TracyTextureCompression.hpp"++namespace tracy+{++TextureCompression::TextureCompression()+ : m_buf( nullptr )+ , m_bufSize( 0 )+ , m_cctx( ZSTD_createCCtx() )+ , m_dctx( ZSTD_createDCtx() )+ , m_dict( nullptr )+{+}++TextureCompression::~TextureCompression()+{+ delete[] m_buf;+ ZSTD_freeCCtx( m_cctx );+ ZSTD_freeDCtx( m_dctx );+ ZSTD_freeDDict( m_dict );+}++uint32_t TextureCompression::Pack( struct ZSTD_CCtx_s* ctx, char*& buf, size_t& bufsz, const char* image, uint32_t inBytes )+{+ const auto maxout = ZSTD_COMPRESSBOUND( inBytes );+ if( bufsz < maxout )+ {+ bufsz = maxout;+ delete[] buf;+ buf = new char[maxout];+ }+ assert( ctx );+ auto ret = (uint32_t)ZSTD_compressCCtx( ctx, buf, maxout, image, inBytes, 3 );+#ifndef TRACY_NO_STATISTICS+ m_inputBytes.fetch_add( inBytes, std::memory_order_relaxed );+ m_outputBytes.fetch_add( ret, std::memory_order_relaxed );+#endif+ return ret;+}++uint32_t TextureCompression::Pack( struct ZSTD_CCtx_s* ctx, const struct ZSTD_CDict_s* dict, char*& buf, size_t& bufsz, const char* image, uint32_t inBytes )+{+ const auto maxout = ZSTD_COMPRESSBOUND( inBytes );+ if( bufsz < maxout )+ {+ bufsz = maxout;+ delete[] buf;+ buf = new char[maxout];+ }+ assert( ctx );+ auto ret = (uint32_t)ZSTD_compress_usingCDict( ctx, buf, maxout, image, inBytes, dict );+#ifndef TRACY_NO_STATISTICS+ m_inputBytes.fetch_add( inBytes, std::memory_order_relaxed );+ m_outputBytes.fetch_add( ret, std::memory_order_relaxed );+#endif+ return ret;+}++const char* TextureCompression::Unpack( const FrameImage& image )+{+ const auto outsz = size_t( image.w ) * size_t( image.h ) / 2;+ if( m_bufSize < outsz )+ {+ m_bufSize = outsz;+ delete[] m_buf;+ m_buf = new char[outsz];+ }+ assert( m_dctx );+ if( m_dict )+ {+ ZSTD_decompress_usingDDict( m_dctx, m_buf, outsz, image.ptr, image.csz, m_dict );+ }+ else+ {+ ZSTD_decompressDCtx( m_dctx, m_buf, outsz, image.ptr, image.csz );+ }+ return m_buf;+}++static constexpr uint8_t Dxtc4To3Table[256] = {+ 85, 84, 86, 86, 81, 80, 82, 82, 89, 88, 90, 90, 89, 88, 90, 90,+ 69, 68, 70, 70, 65, 64, 66, 66, 73, 72, 74, 74, 73, 72, 74, 74,+ 101, 100, 102, 102, 97, 96, 98, 98, 105, 104, 106, 106, 105, 104, 106, 106,+ 101, 100, 102, 102, 97, 96, 98, 98, 105, 104, 106, 106, 105, 104, 106, 106,+ 21, 20, 22, 22, 17, 16, 18, 18, 25, 24, 26, 26, 25, 24, 26, 26,+ 5, 4, 6, 6, 1, 0, 2, 2, 9, 8, 10, 10, 9, 8, 10, 10,+ 37, 36, 38, 38, 33, 32, 34, 34, 41, 40, 42, 42, 41, 40, 42, 42,+ 37, 36, 38, 38, 33, 32, 34, 34, 41, 40, 42, 42, 41, 40, 42, 42,+ 149, 148, 150, 150, 145, 144, 146, 146, 153, 152, 154, 154, 153, 152, 154, 154,+ 133, 132, 134, 134, 129, 128, 130, 130, 137, 136, 138, 138, 137, 136, 138, 138,+ 165, 164, 166, 166, 161, 160, 162, 162, 169, 168, 170, 170, 169, 168, 170, 170,+ 165, 164, 166, 166, 161, 160, 162, 162, 169, 168, 170, 170, 169, 168, 170, 170,+ 149, 148, 150, 150, 145, 144, 146, 146, 153, 152, 154, 154, 153, 152, 154, 154,+ 133, 132, 134, 134, 129, 128, 130, 130, 137, 136, 138, 138, 137, 136, 138, 138,+ 165, 164, 166, 166, 161, 160, 162, 162, 169, 168, 170, 170, 169, 168, 170, 170,+ 165, 164, 166, 166, 161, 160, 162, 162, 169, 168, 170, 170, 169, 168, 170, 170+};++static tracy_force_inline int max3( int a, int b, int c )+{+ if( a > b )+ {+ return a > c ? a : c;+ }+ else+ {+ return b > c ? b : c;+ }+}++static constexpr int TrTbl1[] = { 12, 12, 12, 12, 6, 6, 6, 6, 6, 6, 6, 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 };+static constexpr int TrTbl2[] = { 12, 12, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 };+static constexpr int TrTbl3[] = { 48, 48, 48, 32, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24 };++void TextureCompression::Rdo( char* data, size_t blocks )+{+ assert( blocks > 0 );+ do+ {+ uint64_t blk;+ memcpy( &blk, data, 8 );++ uint32_t idx = blk >> 32;+ if( idx == 0x55555555 )+ {+ data += 8;+ continue;+ }++ uint16_t c0 = blk & 0xFFFF;+ uint16_t c1 = ( blk >> 16 ) & 0xFFFF;++ const int r0b = c0 & 0xF800;+ const int g0b = c0 & 0x07E0;+ const int b0b = c0 & 0x001F;++ const int r1b = c1 & 0xF800;+ const int g1b = c1 & 0x07E0;+ const int b1b = c1 & 0x001F;++ const int r0 = ( r0b >> 8 ) | ( r0b >> 13 );+ const int g0 = ( g0b >> 3 ) | ( g0b >> 9 );+ const int b0 = ( b0b << 3 ) | ( b0b >> 2 );++ const int r1 = ( r1b >> 8 ) | ( r1b >> 13 );+ const int g1 = ( g1b >> 3 ) | ( g1b >> 9 );+ const int b1 = ( b1b << 3 ) | ( b1b >> 2 );++ const int dr = abs( r0 - r1 );+ const int dg = abs( g0 - g1 );+ const int db = abs( b0 - b1 );++ const int maxChan1 = max3( r0-1, g0, b0-2 );+ const int maxDelta1 = max3( dr-1, dg, db-2 );+ const int tr1 = TrTbl1[maxChan1 / 4];+ if( maxDelta1 <= tr1 )+ {+ uint64_t blk =+ ( ( ( r0b + r1b ) >> 1 ) & 0xF800 ) |+ ( ( ( g0b + g1b ) >> 1 ) & 0x07E0 ) |+ ( ( ( b0b + b1b ) >> 1 ) );+ memcpy( data, &blk, 8 );+ }+ else+ {+ const int maxChan23 = max3( r0-2, g0, b0-5 );+ const int maxDelta23 = max3( dr-2, dg, db-5 );+ const int tr2 = TrTbl2[maxChan23 / 16];+ if( maxDelta23 <= tr2 )+ {+ idx &= 0x55555555;+ memcpy( data+4, &idx, 4 );+ }+ else+ {+ const int tr3 = TrTbl3[maxChan23 / 16];+ if( maxDelta23 <= tr3 )+ {+ uint64_t c = c1 | ( uint64_t( c0 ) << 16 );+ for( int k=0; k<4; k++ ) c |= uint64_t( Dxtc4To3Table[(idx >> (k*8)) & 0xFF] ) << ( 32 + k*8 );+ memcpy( data, &c, 8 );+ }+ }+ }++ data += 8;+ }+ while( --blocks );+}++void TextureCompression::FixOrder( char* data, size_t blocks )+{+ assert( blocks > 0 );+ do+ {+ uint32_t tmp;+ memcpy( &tmp, data+4, 4 );+ tmp = ~tmp;+ uint32_t t0 = tmp & 0x55555555;+ uint32_t t1 = tmp & 0xAAAAAAAA;+ tmp = ( ( t0 << 1 ) | ( t1 >> 1 ) ) ^ t1;+ memcpy( data+4, &tmp, 4 );+ data += 8;+ }+ while( --blocks );+}++}
+ cbits/tracy/server/TracyTextureCompression.hpp view
@@ -0,0 +1,64 @@+#ifndef __TRACY__TEXTURECOMPRESSION_HPP__+#define __TRACY__TEXTURECOMPRESSION_HPP__++#include <atomic>++#include <stdint.h>+#include <stdlib.h>+#include <string.h>++#include "TracySlab.hpp"++struct ZSTD_CCtx_s;+struct ZSTD_DCtx_s;+struct ZSTD_CDict_s;+struct ZSTD_DDict_s;++namespace tracy+{++struct FrameImage;++class TextureCompression+{+public:+ TextureCompression();+ ~TextureCompression();++ void SetDict( struct ZSTD_DDict_s* dict ) { m_dict = dict; }++ uint32_t Pack( struct ZSTD_CCtx_s* ctx, char*& buf, size_t& bufsz, const char* image, uint32_t inBytes );+ uint32_t Pack( struct ZSTD_CCtx_s* ctx, const struct ZSTD_CDict_s* dict, char*& buf, size_t& bufsz, const char* image, uint32_t inBytes );++ template<size_t Size>+ const char* Pack( const char* image, uint32_t inBytes, uint32_t& csz, Slab<Size>& slab )+ {+ const auto outsz = Pack( m_cctx, m_buf, m_bufSize, image, inBytes );+ auto ptr = (char*)slab.AllocBig( outsz );+ memcpy( ptr, m_buf, outsz );+ csz = outsz;+ return ptr;+ }++ const char* Unpack( const FrameImage& image );++ void Rdo( char* data, size_t blocks );+ void FixOrder( char* data, size_t blocks );++ uint64_t GetInputBytesCount() const { return m_inputBytes.load( std::memory_order_relaxed ); }+ uint64_t GetOutputBytesCount() const { return m_outputBytes.load( std::memory_order_relaxed ); }++private:+ char* m_buf;+ size_t m_bufSize;+ struct ZSTD_CCtx_s* m_cctx;+ struct ZSTD_DCtx_s* m_dctx;+ struct ZSTD_DDict_s* m_dict;++ std::atomic<uint64_t> m_inputBytes { 0 };+ std::atomic<uint64_t> m_outputBytes { 0 };+};++}++#endif
+ cbits/tracy/server/TracyThreadCompress.cpp view
@@ -0,0 +1,72 @@+#include <limits>++#include "TracyFileRead.hpp"+#include "TracyFileWrite.hpp"+#include "TracyThreadCompress.hpp"++namespace tracy+{++ThreadCompress::ThreadCompress()+ : m_threadLast( std::numeric_limits<uint64_t>::max(), 0 )+{+}++void ThreadCompress::InitZero()+{+ assert( m_threadExpand.empty() );+ m_threadExpand.push_back( 0 );+}++void ThreadCompress::Load( FileRead& f )+{+ assert( m_threadExpand.empty() );+ assert( m_threadMap.empty() );++ uint64_t sz;+ f.Read( sz );+ if( sz != 0 )+ {+ m_threadExpand.reserve_and_use( sz );+ f.Read( m_threadExpand.data(), sizeof( uint64_t ) * sz );+ m_threadMap.reserve( sz );+ for( size_t i=0; i<sz; i++ )+ {+ m_threadMap.emplace( m_threadExpand[i], i );+ }+ }+}++void ThreadCompress::Save( FileWrite& f ) const+{+ uint64_t sz = m_threadExpand.size();+ f.Write( &sz, sizeof( sz ) );+ if( sz != 0 ) f.Write( m_threadExpand.data(), sz * sizeof( uint64_t ) );+}++uint16_t ThreadCompress::CompressThreadReal( uint64_t thread )+{+ auto it = m_threadMap.find( thread );+ if( it != m_threadMap.end() )+ {+ m_threadLast.first = thread;+ m_threadLast.second = it->second;+ return it->second;+ }+ else+ {+ return CompressThreadNew( thread );+ }+}++uint16_t ThreadCompress::CompressThreadNew( uint64_t thread )+{+ auto sz = m_threadExpand.size();+ m_threadExpand.push_back( thread );+ m_threadMap.emplace( thread, sz );+ m_threadLast.first = thread;+ m_threadLast.second = sz;+ return sz;+}++}
+ cbits/tracy/server/TracyThreadCompress.hpp view
@@ -0,0 +1,61 @@+#ifndef __TRACY__THREADCOMPRESS_HPP__+#define __TRACY__THREADCOMPRESS_HPP__++#include <assert.h>+#include <stdint.h>++#include "../public/common/TracyForceInline.hpp"+#include "tracy_robin_hood.h"+#include "TracyVector.hpp"++namespace tracy+{++class FileRead;+class FileWrite;++class ThreadCompress+{+public:+ ThreadCompress();++ void InitZero();+ void Load( FileRead& f );+ void Save( FileWrite& f ) const;++ tracy_force_inline uint16_t CompressThread( uint64_t thread )+ {+ if( m_threadLast.first == thread ) return m_threadLast.second;+ return CompressThreadReal( thread );+ }++ tracy_force_inline uint64_t DecompressThread( uint16_t thread ) const+ {+ assert( thread < m_threadExpand.size() );+ return m_threadExpand[thread];+ }++ tracy_force_inline uint16_t DecompressMustRaw( uint64_t thread ) const+ {+ auto it = m_threadMap.find( thread );+ assert( it != m_threadMap.end() );+ return it->second;+ }++ tracy_force_inline bool Exists( uint64_t thread ) const+ {+ return m_threadMap.find( thread ) != m_threadMap.end();+ }++private:+ uint16_t CompressThreadReal( uint64_t thread );+ uint16_t CompressThreadNew( uint64_t thread );++ unordered_flat_map<uint64_t, uint16_t> m_threadMap;+ Vector<uint64_t> m_threadExpand;+ std::pair<uint64_t, uint16_t> m_threadLast;+};++}++#endif
+ cbits/tracy/server/TracyVarArray.hpp view
@@ -0,0 +1,97 @@+#ifndef __TRACYVARARRAY_HPP__+#define __TRACYVARARRAY_HPP__++#include <stdint.h>+#include <string.h>++#define XXH_INLINE_ALL+#include "tracy_xxhash.h"++#include "../public/common/TracyForceInline.hpp"+#include "TracyCharUtil.hpp"+#include "TracyEvent.hpp"+#include "TracyMemory.hpp"+#include "TracyShortPtr.hpp"++namespace tracy+{++#pragma pack( push, 1 )+template<typename T>+class VarArray+{+public:+ VarArray( uint16_t size, const T* data )+ : m_size( size )+ , m_ptr( data )+ {+ CalcHash();+ }++ VarArray( const VarArray& ) = delete;+ VarArray( VarArray&& ) = delete;++ VarArray& operator=( const VarArray& ) = delete;+ VarArray& operator=( VarArray&& ) = delete;++ tracy_force_inline uint32_t get_hash() const { return m_hash; }++ tracy_force_inline bool empty() const { return m_size == 0; }+ tracy_force_inline uint16_t size() const { return m_size; }++ tracy_force_inline const T* data() const { return m_ptr; };++ tracy_force_inline const T* begin() const { return m_ptr; }+ tracy_force_inline const T* end() const { return m_ptr + m_size; }++ tracy_force_inline const T& front() const { assert( m_size > 0 ); return m_ptr[0]; }+ tracy_force_inline const T& back() const { assert( m_size > 0 ); return m_ptr[m_size - 1]; }++ tracy_force_inline const T& operator[]( size_t idx ) const { return m_ptr[idx]; }++private:+ tracy_force_inline void CalcHash();++ uint16_t m_size;+ uint32_t m_hash;+ const short_ptr<T> m_ptr;+};+#pragma pack( pop )++enum { VarArraySize = sizeof( VarArray<int> ) };+++template<typename T>+inline void VarArray<T>::CalcHash()+{+ m_hash = uint32_t( XXH3_64bits( m_ptr.get(), m_size * sizeof( T ) ) );+}++template<typename T>+static inline bool Compare( const VarArray<T>& lhs, const VarArray<T>& rhs )+{+ if( lhs.size() != rhs.size() || lhs.get_hash() != rhs.get_hash() ) return false;+ return memcmp( lhs.data(), rhs.data(), lhs.size() * sizeof( T ) ) == 0;+}++template<typename T>+struct VarArrayHasher+{+ size_t operator()( const VarArray<T>* arr ) const+ {+ return arr->get_hash();+ }+};++template<typename T>+struct VarArrayComparator+{+ bool operator()( const VarArray<T>* lhs, const VarArray<T>* rhs ) const+ {+ return Compare( *lhs, *rhs );+ }+};++}++#endif
+ cbits/tracy/server/TracyVector.hpp view
@@ -0,0 +1,357 @@+#ifndef __TRACYVECTOR_HPP__+#define __TRACYVECTOR_HPP__++#include <algorithm>+#include <assert.h>+#include <limits>+#include <stdint.h>+#include <stdlib.h>+#include <type_traits>++#include "../public/common/TracyForceInline.hpp"+#include "TracyMemory.hpp"+#include "TracyPopcnt.hpp"+#include "TracyShortPtr.hpp"+#include "TracySlab.hpp"++//#define TRACY_VECTOR_DEBUG++namespace tracy+{++#pragma pack( push, 1 )+template<typename T>+class Vector+{+ constexpr uint8_t MaxCapacity() { return 0x7F; }++public:+ using iterator = T*;+ using const_iterator = const T*;++ tracy_force_inline Vector()+ {+ memset( (char*)this, 0, sizeof( Vector<T> ) );+ }++ Vector( const Vector& ) = delete;+ tracy_force_inline Vector( Vector&& src ) noexcept+ {+ memcpy( (char*)this, &src, sizeof( Vector<T> ) );+ memset( (char*)&src, 0, sizeof( Vector<T> ) );+ }++ tracy_force_inline Vector( const T& value )+ : m_ptr( (T*)malloc( sizeof( T ) ) )+ , m_size( 1 )+ , m_capacity( 0 )+ , m_magic( 0 )+ {+ memUsage.fetch_add( sizeof( T ), std::memory_order_relaxed );+ new(m_ptr) T( value );+ }++ tracy_force_inline ~Vector()+ {+ if( m_capacity != MaxCapacity() && m_ptr )+ {+ memUsage.fetch_sub( Capacity() * sizeof( T ), std::memory_order_relaxed );+ free( m_ptr );+ }+ }++ Vector& operator=( const Vector& ) = delete;+ tracy_force_inline Vector& operator=( Vector&& src ) noexcept+ {+ if( m_capacity != MaxCapacity() && m_ptr )+ {+ memUsage.fetch_sub( Capacity() * sizeof( T ), std::memory_order_relaxed );+ free( m_ptr );+ }+ memcpy( (char*)this, &src, sizeof( Vector<T> ) );+ memset( (char*)&src, 0, sizeof( Vector<T> ) );+ return *this;+ }++ tracy_force_inline void swap( Vector& other )+ {+ uint8_t tmp[sizeof( Vector<T> )];+ memcpy( (char*)tmp, &other, sizeof( Vector<T> ) );+ memcpy( (char*)&other, this, sizeof( Vector<T> ) );+ memcpy( (char*)this, tmp, sizeof( Vector<T> ) );+ }++ tracy_force_inline bool empty() const { return m_size == 0; }+ tracy_force_inline size_t size() const { return m_size; }++ tracy_force_inline void set_size( size_t sz ) { assert( m_capacity != MaxCapacity() ); m_size = sz; }++ tracy_force_inline T* data() { return m_ptr; }+ tracy_force_inline const T* data() const { return m_ptr; };++ tracy_force_inline T* begin() { return m_ptr; }+ tracy_force_inline const T* begin() const { return m_ptr; }+ tracy_force_inline T* end() { return m_ptr + m_size; }+ tracy_force_inline const T* end() const { return m_ptr + m_size; }++ tracy_force_inline T& front() { assert( m_size > 0 ); return m_ptr[0]; }+ tracy_force_inline const T& front() const { assert( m_size > 0 ); return m_ptr[0]; }++ tracy_force_inline T& back() { assert( m_size > 0 ); return m_ptr[m_size - 1]; }+ tracy_force_inline const T& back() const { assert( m_size > 0 ); return m_ptr[m_size - 1]; }++ tracy_force_inline T& operator[]( size_t idx ) { return m_ptr[idx]; }+ tracy_force_inline const T& operator[]( size_t idx ) const { return m_ptr[idx]; }++ tracy_force_inline void push_back( const T& v )+ {+ assert( m_capacity != MaxCapacity() );+ if( m_size == Capacity() ) AllocMore();+ new(m_ptr+m_size) T( v );+ m_size++;+ }++ tracy_force_inline void push_back_non_empty( const T& v )+ {+ assert( m_capacity != MaxCapacity() );+ assert( m_ptr );+ if( m_size == CapacityNoNullptrCheck() ) AllocMore();+ new(m_ptr+m_size) T( v );+ m_size++;+ }++ tracy_force_inline void push_back_no_space_check( const T& v )+ {+ assert( m_capacity != MaxCapacity() );+ assert( m_size < Capacity() );+ new(m_ptr+m_size) T( v );+ m_size++;+ }++ tracy_force_inline void push_back( T&& v )+ {+ assert( m_capacity != MaxCapacity() );+ if( m_size == Capacity() ) AllocMore();+ new(m_ptr+m_size) T( std::move( v ) );+ m_size++;+ }++ tracy_force_inline T& push_next()+ {+ assert( m_capacity != MaxCapacity() );+ if( m_size == Capacity() ) AllocMore();+ new(m_ptr+m_size) T();+ return m_ptr[m_size++];+ }++ tracy_force_inline T& push_next_non_empty()+ {+ assert( m_capacity != MaxCapacity() );+ assert( m_ptr );+ if( m_size == CapacityNoNullptrCheck() ) AllocMore();+ new(m_ptr+m_size) T();+ return m_ptr[m_size++];+ }++ tracy_force_inline T& push_next_no_space_check()+ {+ assert( m_capacity != MaxCapacity() );+ assert( m_size < Capacity() );+ new(m_ptr+m_size) T();+ return m_ptr[m_size++];+ }++ T* insert( T* it, const T& v )+ {+ assert( m_capacity != MaxCapacity() );+ assert( it >= m_ptr && it <= m_ptr + m_size );+ const auto dist = it - m_ptr;+ if( m_size == Capacity() ) AllocMore();+ if( dist != m_size ) memmove( m_ptr + dist + 1, m_ptr + dist, ( m_size - dist ) * sizeof( T ) );+ m_size++;+ new(m_ptr+dist) T( v );+ m_ptr[dist] = v;+ return m_ptr + dist;+ }++ T* insert( T* it, T&& v )+ {+ assert( m_capacity != MaxCapacity() );+ assert( it >= m_ptr && it <= m_ptr + m_size );+ const auto dist = it - m_ptr;+ if( m_size == Capacity() ) AllocMore();+ if( dist != m_size ) memmove( m_ptr + dist + 1, m_ptr + dist, ( m_size - dist ) * sizeof( T ) );+ m_size++;+ new(m_ptr+dist) T( std::move( v ) );+ return m_ptr + dist;+ }++ void insert( T* it, T* begin, T* end )+ {+ assert( m_capacity != MaxCapacity() );+ assert( it >= m_ptr && it <= m_ptr + m_size );+ const auto sz = end - begin;+ const auto dist = it - m_ptr;+ while( m_size + sz > Capacity() ) AllocMore();+ if( dist != m_size ) memmove( m_ptr + dist + sz, m_ptr + dist, ( m_size - dist ) * sizeof( T ) );+ m_size += sz;+ memcpy( m_ptr + dist, begin, sz * sizeof( T ) );+ }++ T* erase( T* it )+ {+ assert( m_capacity != MaxCapacity() );+ assert( it >= m_ptr && it <= m_ptr + m_size );+ m_size--;+ memmove( it, it+1, ( m_size - ( it - m_ptr ) ) * sizeof( T ) );+ return it;+ }++ T* erase( T* begin, T* end )+ {+ assert( m_capacity != MaxCapacity() );+ assert( begin >= m_ptr && begin <= m_ptr + m_size );+ assert( end >= m_ptr && end <= m_ptr + m_size );+ assert( begin <= end );++ const auto dist = end - begin;+ if( dist > 0 )+ {+ memmove( begin, end, ( m_size - ( end - m_ptr ) ) * sizeof( T ) );+ m_size -= dist;+ }+ return begin;+ }++ tracy_force_inline void pop_back()+ {+ assert( m_capacity != MaxCapacity() );+ assert( m_size > 0 );+ m_size--;+ }++ tracy_force_inline T& back_and_pop()+ {+ assert( m_capacity != MaxCapacity() );+ assert( m_size > 0 );+ m_size--;+ return m_ptr[m_size];+ }++ tracy_force_inline void reserve( size_t cap )+ {+ if( cap == 0 || cap <= Capacity() ) return;+ reserve_non_zero( cap );+ }++ void reserve_non_zero( size_t cap )+ {+ assert( m_capacity != MaxCapacity() );+ cap--;+ cap |= cap >> 1;+ cap |= cap >> 2;+ cap |= cap >> 4;+ cap |= cap >> 8;+ cap |= cap >> 16;+ cap = TracyCountBits( cap );+ memUsage.fetch_add( ( ( 1 << cap ) - Capacity() ) * sizeof( T ), std::memory_order_relaxed );+ m_capacity = cap;+ Realloc();+ }++ tracy_force_inline void reserve_and_use( size_t sz )+ {+ assert( m_capacity != MaxCapacity() );+ reserve( sz );+ m_size = sz;+ }++ template<size_t U>+ tracy_force_inline void reserve_exact( uint32_t sz, Slab<U>& slab )+ {+ assert( !m_ptr );+ m_capacity = MaxCapacity();+ m_size = sz;+ m_ptr = (T*)slab.AllocBig( sizeof( T ) * sz );+ }++ tracy_force_inline void clear()+ {+ assert( m_capacity != MaxCapacity() );+ m_size = 0;+ }++ tracy_force_inline bool is_magic() const { return m_magic; }+ tracy_force_inline void set_magic() { assert( !m_magic ); m_magic = 1; }++private:+ tracy_no_inline void AllocMore()+ {+ assert( m_capacity != MaxCapacity() );++ if( m_ptr == nullptr )+ {+ memUsage.fetch_add( sizeof( T ), std::memory_order_relaxed );+ m_ptr = (T*)malloc( sizeof( T ) );+ m_capacity = 0;+ }+ else+ {+ memUsage.fetch_add( Capacity() * sizeof( T ), std::memory_order_relaxed );+ m_capacity++;+ Realloc();+ }+ }++ void Realloc()+ {+ T* ptr = (T*)malloc( sizeof( T ) * CapacityNoNullptrCheck() );+ if( m_size != 0 )+ {+ if( std::is_trivially_copyable<T>() )+ {+ memcpy( (char*)ptr, m_ptr, m_size * sizeof( T ) );+ }+ else+ {+ for( uint32_t i=0; i<m_size; i++ )+ {+ new(ptr+i) T( std::move( m_ptr[i] ) );+ }+ }+ free( m_ptr );+ }+ m_ptr = ptr;+ }++ tracy_force_inline uint32_t Capacity() const+ {+ return m_ptr == nullptr ? 0 : 1 << m_capacity;+ }++ tracy_force_inline uint32_t CapacityNoNullptrCheck() const+ {+ return 1 << m_capacity;+ }++#ifdef TRACY_VECTOR_DEBUG+ T* m_ptr;+#else+ short_ptr<T> m_ptr;+#endif+ uint32_t m_size;+ uint8_t m_capacity : 7;+ uint8_t m_magic : 1;+};+++template<typename T> struct VectorAdapterDirect { const T& operator()( const T& it ) const { return it; } };+template<typename T> struct VectorAdapterPointer { const T& operator()( const short_ptr<T>& it ) const { return *it; } };++#pragma pack( pop )++enum { VectorSize = sizeof( Vector<int> ) };++}++#endif
+ cbits/tracy/server/TracyWorker.cpp view
@@ -0,0 +1,8681 @@+#ifdef _MSC_VER+# pragma warning( disable: 4244 4267 ) // conversion from don't care to whatever, possible loss of data+#endif++#ifdef _WIN32+# include <malloc.h>+#elif defined __FreeBSD__+# include <stdlib.h>+#else+# include <alloca.h>+#endif++#include <cctype>+#include <chrono>+#include <math.h>+#include <string.h>++#ifdef __MINGW32__+# define __STDC_FORMAT_MACROS+#endif+#include <inttypes.h>+#include <sys/stat.h>++#include <capstone.h>++#define ZDICT_STATIC_LINKING_ONLY+#include <zdict.h>++#include "../public/common/TracyProtocol.hpp"+#include "../public/common/TracySystem.hpp"+#include "../public/common/TracyYield.hpp"+#include "../public/common/TracyStackFrames.hpp"+#include "../public/common/TracyVersion.hpp"+#include "TracyFileRead.hpp"+#include "TracyFileWrite.hpp"+#include "TracyPrint.hpp"+#include "TracySort.hpp"+#include "TracyTaskDispatch.hpp"+#include "TracyWorker.hpp"+#include "tracy_pdqsort.h"++namespace tracy+{++static bool SourceFileValid( const char* fn, uint64_t olderThan )+{+ struct stat buf;+ if( stat( fn, &buf ) == 0 && ( buf.st_mode & S_IFREG ) != 0 )+ {+ return (uint64_t)buf.st_mtime < olderThan;+ }+ return false;+}+++static const uint8_t FileHeader[8] { 't', 'r', 'a', 'c', 'y', Version::Major, Version::Minor, Version::Patch };+enum { FileHeaderMagic = 5 };+static const int CurrentVersion = FileVersion( Version::Major, Version::Minor, Version::Patch );+static const int MinSupportedVersion = FileVersion( 0, 9, 0 );+++static void UpdateLockCountLockable( LockMap& lockmap, size_t pos )+{+ auto& timeline = lockmap.timeline;+ bool isContended = lockmap.isContended;+ uint8_t lockingThread;+ uint8_t lockCount;+ uint64_t waitList;++ if( pos == 0 )+ {+ lockingThread = 0;+ lockCount = 0;+ waitList = 0;+ }+ else+ {+ const auto& tl = timeline[pos-1];+ lockingThread = tl.lockingThread;+ lockCount = tl.lockCount;+ waitList = tl.waitList;+ }+ const auto end = timeline.size();++ while( pos != end )+ {+ auto& tl = timeline[pos];+ const auto tbit = uint64_t( 1 ) << tl.ptr->thread;+ switch( (LockEvent::Type)tl.ptr->type )+ {+ case LockEvent::Type::Wait:+ waitList |= tbit;+ break;+ case LockEvent::Type::Obtain:+ assert( lockCount < std::numeric_limits<uint8_t>::max() );+ assert( ( waitList & tbit ) != 0 );+ waitList &= ~tbit;+ lockingThread = tl.ptr->thread;+ lockCount++;+ break;+ case LockEvent::Type::Release:+ assert( lockCount > 0 );+ lockCount--;+ break;+ default:+ break;+ }+ tl.lockingThread = lockingThread;+ tl.waitList = waitList;+ tl.lockCount = lockCount;+ if( !isContended ) isContended = lockCount != 0 && waitList != 0;+ pos++;+ }++ lockmap.isContended = isContended;+}++static void UpdateLockCountSharedLockable( LockMap& lockmap, size_t pos )+{+ auto& timeline = lockmap.timeline;+ bool isContended = lockmap.isContended;+ uint8_t lockingThread;+ uint8_t lockCount;+ uint64_t waitShared;+ uint64_t waitList;+ uint64_t sharedList;++ if( pos == 0 )+ {+ lockingThread = 0;+ lockCount = 0;+ waitShared = 0;+ waitList = 0;+ sharedList = 0;+ }+ else+ {+ const auto& tl = timeline[pos-1];+ const auto tlp = (const LockEventShared*)(const LockEvent*)tl.ptr;+ lockingThread = tl.lockingThread;+ lockCount = tl.lockCount;+ waitShared = tlp->waitShared;+ waitList = tl.waitList;+ sharedList = tlp->sharedList;+ }+ const auto end = timeline.size();++ // ObtainShared and ReleaseShared should assert on lockCount == 0, but+ // due to the async retrieval of data from threads that's not possible.+ while( pos != end )+ {+ auto& tl = timeline[pos];+ const auto tlp = (LockEventShared*)(LockEvent*)tl.ptr;+ const auto tbit = uint64_t( 1 ) << tlp->thread;+ switch( (LockEvent::Type)tlp->type )+ {+ case LockEvent::Type::Wait:+ waitList |= tbit;+ break;+ case LockEvent::Type::WaitShared:+ waitShared |= tbit;+ break;+ case LockEvent::Type::Obtain:+ assert( lockCount < std::numeric_limits<uint8_t>::max() );+ assert( ( waitList & tbit ) != 0 );+ waitList &= ~tbit;+ lockingThread = tlp->thread;+ lockCount++;+ break;+ case LockEvent::Type::Release:+ assert( lockCount > 0 );+ lockCount--;+ break;+ case LockEvent::Type::ObtainShared:+ assert( ( waitShared & tbit ) != 0 );+ assert( ( sharedList & tbit ) == 0 );+ waitShared &= ~tbit;+ sharedList |= tbit;+ break;+ case LockEvent::Type::ReleaseShared:+ assert( ( sharedList & tbit ) != 0 );+ sharedList &= ~tbit;+ break;+ default:+ break;+ }+ tl.lockingThread = lockingThread;+ tlp->waitShared = waitShared;+ tl.waitList = waitList;+ tlp->sharedList = sharedList;+ tl.lockCount = lockCount;+ if( !isContended ) isContended = ( lockCount != 0 && ( waitList != 0 || waitShared != 0 ) ) || ( sharedList != 0 && waitList != 0 );+ pos++;+ }++ lockmap.isContended = isContended;+}++static inline void UpdateLockCount( LockMap& lockmap, size_t pos )+{+ if( lockmap.type == LockType::Lockable )+ {+ UpdateLockCountLockable( lockmap, pos );+ }+ else+ {+ UpdateLockCountSharedLockable( lockmap, pos );+ }+}++static tracy_force_inline void WriteTimeOffset( FileWrite& f, int64_t& refTime, int64_t time )+{+ int64_t timeOffset = time - refTime;+ refTime += timeOffset;+ f.Write( &timeOffset, sizeof( timeOffset ) );+}++static tracy_force_inline int64_t ReadTimeOffset( FileRead& f, int64_t& refTime )+{+ int64_t timeOffset;+ f.Read( timeOffset );+ refTime += timeOffset;+ return refTime;+}++static tracy_force_inline void UpdateLockRange( LockMap& lockmap, const LockEvent& ev, int64_t lt )+{+ auto& range = lockmap.range[ev.thread];+ if( range.start > lt ) range.start = lt;+ if( range.end < lt ) range.end = lt;+}++template<size_t U>+static uint64_t ReadHwSampleVec( FileRead& f, SortedVector<Int48, Int48Sort>& vec, Slab<U>& slab )+{+ uint64_t sz;+ f.Read( sz );+ if( sz != 0 )+ {+ int64_t refTime = 0;+ vec.reserve_exact( sz, slab );+ for( uint64_t i=0; i<sz; i++ )+ {+ vec[i] = ReadTimeOffset( f, refTime );+ }+ }+ return sz;+}++static bool IsQueryPrio( ServerQuery type )+{+ return type < ServerQuery::ServerQueryDisconnect;+}+++LoadProgress Worker::s_loadProgress;++Worker::Worker( const char* addr, uint16_t port, int64_t memoryLimit )+ : m_addr( addr )+ , m_port( port )+ , m_hasData( false )+ , m_stream( LZ4_createStreamDecode() )+ , m_buffer( new char[TargetFrameSize*3 + 1] )+ , m_bufferOffset( 0 )+ , m_inconsistentSamples( false )+ , m_pendingStrings( 0 )+ , m_pendingThreads( 0 )+ , m_pendingFibers( 0 )+ , m_pendingExternalNames( 0 )+ , m_pendingSourceLocation( 0 )+ , m_pendingCallstackFrames( 0 )+ , m_pendingCallstackSubframes( 0 )+ , m_pendingSymbolCode( 0 )+ , m_memoryLimit( memoryLimit )+ , m_callstackFrameStaging( nullptr )+ , m_traceVersion( CurrentVersion )+ , m_loadTime( 0 )+{+ m_data.sourceLocationExpand.push_back( 0 );+ m_data.localThreadCompress.InitZero();+ m_data.callstackPayload.push_back( nullptr );+ m_data.zoneExtra.push_back( ZoneExtra {} );+ m_data.symbolLocInline.push_back( std::numeric_limits<uint64_t>::max() );+ m_data.memory = m_slab.AllocInit<MemData>();+ m_data.memNameMap.emplace( 0, m_data.memory );++ memset( (char*)m_gpuCtxMap, 0, sizeof( m_gpuCtxMap ) );++#ifndef TRACY_NO_STATISTICS+ m_data.sourceLocationZonesReady = true;+ m_data.gpuSourceLocationZonesReady = true;+ m_data.callstackSamplesReady = true;+ m_data.ghostZonesReady = true;+ m_data.ctxUsageReady = true;+ m_data.symbolSamplesReady = true;+#endif++ m_thread = std::thread( [this] { SetThreadName( "Tracy Worker" ); Exec(); } );+ m_threadNet = std::thread( [this] { SetThreadName( "Tracy Network" ); Network(); } );+}++Worker::Worker( const char* name, const char* program, const std::vector<ImportEventTimeline>& timeline, const std::vector<ImportEventMessages>& messages, const std::vector<ImportEventPlots>& plots, const std::unordered_map<uint64_t, std::string>& threadNames )+ : m_hasData( true )+ , m_delay( 0 )+ , m_resolution( 0 )+ , m_captureName( name )+ , m_captureProgram( program )+ , m_captureTime( 0 )+ , m_executableTime( 0 )+ , m_pid( 0 )+ , m_samplingPeriod( 0 )+ , m_stream( nullptr )+ , m_buffer( nullptr )+ , m_onDemand( false )+ , m_inconsistentSamples( false )+ , m_memoryLimit( -1 )+ , m_traceVersion( CurrentVersion )+{+ m_data.sourceLocationExpand.push_back( 0 );+ m_data.localThreadCompress.InitZero();+ m_data.callstackPayload.push_back( nullptr );+ m_data.zoneExtra.push_back( ZoneExtra {} );+ m_data.symbolLocInline.push_back( std::numeric_limits<uint64_t>::max() );+ m_data.memory = m_slab.AllocInit<MemData>();+ m_data.memNameMap.emplace( 0, m_data.memory );++ m_data.lastTime = 0;+ if( !timeline.empty() )+ {+ m_data.lastTime = timeline.back().timestamp;+ }+ if( !messages.empty() )+ {+ if( m_data.lastTime < (int64_t)messages.back().timestamp ) m_data.lastTime = messages.back().timestamp;+ }+ if( !plots.empty() )+ {+ for( auto& v : plots )+ {+ if( m_data.lastTime < v.data.back().first ) m_data.lastTime = v.data.back().first;+ }+ }++ for( auto& v : timeline )+ {+ if( !v.isEnd )+ {+ SourceLocation srcloc {{+ StringRef(),+ StringRef( StringRef::Idx, StoreString( v.name.c_str(), v.name.size() ).idx ),+ StringRef( StringRef::Idx, StoreString( v.locFile.c_str(), v.locFile.size() ).idx ),+ v.locLine,+ 0+ }};+ int key;+ auto it = m_data.sourceLocationPayloadMap.find( &srcloc );+ if( it == m_data.sourceLocationPayloadMap.end() )+ {+ auto slptr = m_slab.Alloc<SourceLocation>();+ memcpy( slptr, &srcloc, sizeof( srcloc ) );+ uint32_t idx = m_data.sourceLocationPayload.size();+ m_data.sourceLocationPayloadMap.emplace( slptr, idx );+ m_data.sourceLocationPayload.push_back( slptr );+ key = -int16_t( idx + 1 );+#ifndef TRACY_NO_STATISTICS+ auto res = m_data.sourceLocationZones.emplace( key, SourceLocationZones() );+ m_data.srclocZonesLast.first = key;+ m_data.srclocZonesLast.second = &res.first->second;++#else+ auto res = m_data.sourceLocationZonesCnt.emplace( key, 0 );+ m_data.srclocCntLast.first = key;+ m_data.srclocCntLast.second = &res.first->second;+#endif+ }+ else+ {+ key = -int16_t( it->second + 1 );+ }++ auto zone = AllocZoneEvent();+ zone->SetStartSrcLoc( v.timestamp, key );+ zone->SetEnd( -1 );+ zone->SetChild( -1 );++ if( !v.text.empty() )+ {+ auto& extra = RequestZoneExtra( *zone );+ extra.text = StringIdx( StoreString( v.text.c_str(), v.text.size() ).idx );+ }++ if( m_threadCtx != v.tid )+ {+ m_threadCtx = v.tid;+ m_threadCtxData = NoticeThread( v.tid );+ }+ NewZone( zone );+ }+ else+ {+ auto td = NoticeThread( v.tid );+ if( td->zoneIdStack.empty() ) continue;+ td->zoneIdStack.pop_back();+ auto& stack = td->stack;+ auto zone = stack.back_and_pop();+ td->DecStackCount( zone->SrcLoc() );+ zone->SetEnd( v.timestamp );++#ifndef TRACY_NO_STATISTICS+ ZoneThreadData ztd;+ ztd.SetZone( zone );+ ztd.SetThread( CompressThread( v.tid ) );+ auto slz = GetSourceLocationZones( zone->SrcLoc() );+ slz->zones.push_back( ztd );+#else+ CountZoneStatistics( zone );+#endif+ }+ }++ std::unordered_map<std::string, uint64_t> frameNames;++ for( auto& v : messages )+ {+ // There is no specific chrome-tracing type for frame events. We use messages that contain the word "frame"+ std::string lower( v.message );+ std::transform( lower.begin(), lower.end(), lower.begin(), []( char c ) { return char( std::tolower( c ) ); } );+ if( lower.find( "frame" ) != std::string::npos )+ {+ // Reserve 0 as the default FrameSet, since it replaces the name with "Frame" and we want to keep our custom names.+ auto result = frameNames.emplace( v.message, frameNames.size() + 1 );+ auto fd = m_data.frames.Retrieve( result.first->second, [&] ( uint64_t name ) {+ auto fd = m_slab.AllocInit<FrameData>();+ fd->name = name;+ fd->continuous = 1;+ return fd;+ }, [&] ( uint64_t name ) {+ HandleFrameName( name, v.message.c_str(), v.message.length() );+ });++ int64_t time = v.timestamp;+ fd->frames.push_back( FrameEvent{ time, -1, -1 } );+ if ( m_data.lastTime < time ) m_data.lastTime = time;+ }+ else+ {+ auto msg = m_slab.Alloc<MessageData>();+ msg->time = v.timestamp;+ msg->ref = StringRef( StringRef::Type::Idx, StoreString( v.message.c_str(), v.message.size() ).idx );+ msg->thread = CompressThread( v.tid );+ msg->color = 0xFFFFFFFF;+ msg->callstack.SetVal( 0 );++ if( m_threadCtx != v.tid )+ {+ m_threadCtx = v.tid;+ m_threadCtxData = nullptr;+ }+ InsertMessageData( msg );+ }+ }++ for( auto& v : plots )+ {+ uint64_t nptr = (uint64_t)&v.name;+ auto it = m_data.strings.find( nptr );+ if( it == m_data.strings.end() )+ {+ const auto sl = StoreString( v.name.c_str(), v.name.size() );+ m_data.strings.emplace( nptr, sl.ptr );+ }++ auto plot = m_slab.AllocInit<PlotData>();+ plot->name = nptr;+ plot->type = PlotType::User;+ plot->format = v.format;+ plot->showSteps = false;+ plot->fill = true;+ plot->color = 0;++ double sum = 0;+ double min = v.data.begin()->second;+ double max = v.data.begin()->second;+ plot->data.reserve_exact( v.data.size(), m_slab );+ size_t idx = 0;+ for( auto& p : v.data )+ {+ plot->data[idx].time.SetVal( p.first );+ plot->data[idx].val = p.second;+ idx++;+ if( min > p.second ) min = p.second;+ else if( max < p.second ) max = p.second;+ sum += p.second;+ }+ plot->min = min;+ plot->max = max;+ plot->sum = sum;++ m_data.plots.Data().push_back( plot );+ }++ for( auto& t : m_threadMap )+ {+ auto name = threadNames.find(t.first);+ if( name != threadNames.end() )+ {+ char buf[128];+ int len;+ if( t.first <= std::numeric_limits<uint32_t>::max() )+ {+ len = snprintf( buf, sizeof( buf ), "(%" PRIu64 ") %s", t.first, name->second.c_str() );+ }+ else+ {+ len = snprintf( buf, sizeof( buf ), "(PID %" PRIu64 " TID %" PRIu64 ") %s", t.first >> 32, t.first & 0xFFFFFFFF, name->second.c_str() );+ }+ AddThreadString( t.first, buf, len );+ }+ else+ {+ char buf[64];+ int len;+ if( t.first <= std::numeric_limits<uint32_t>::max() )+ {+ len = sprintf( buf, "%" PRIu64, t.first );+ }+ else+ {+ len = sprintf( buf, "PID %" PRIu64 " TID %" PRIu64, t.first >> 32, t.first & 0xFFFFFFFF );+ }+ AddThreadString( t.first, buf, len );+ }+ }++ // Add a default frame if we didn't have any framesets+ if( frameNames.empty() )+ {+ m_data.framesBase = m_data.frames.Retrieve( 0, [this] ( uint64_t name ) {+ auto fd = m_slab.AllocInit<FrameData>();+ fd->name = name;+ fd->continuous = 1;+ return fd;+ }, [this] ( uint64_t name ) {+ assert( name == 0 );+ char tmp[6] = "Frame";+ HandleFrameName( name, tmp, 5 );+ } );++ m_data.framesBase->frames.push_back( FrameEvent{ 0, -1, -1 } );+ m_data.framesBase->frames.push_back( FrameEvent{ 0, -1, -1 } );+ }+}++Worker::Worker( FileRead& f, EventType::Type eventMask, bool bgTasks, bool allowStringModification )+ : m_hasData( true )+ , m_stream( nullptr )+ , m_buffer( nullptr )+ , m_inconsistentSamples( false )+ , m_memoryLimit( -1 )+ , m_allowStringModification( allowStringModification )+{+ auto loadStart = std::chrono::high_resolution_clock::now();++ int fileVer = 0;++ uint8_t hdr[8];+ f.Read( hdr, sizeof( hdr ) );+ if( memcmp( FileHeader, hdr, FileHeaderMagic ) == 0 )+ {+ fileVer = FileVersion( hdr[FileHeaderMagic], hdr[FileHeaderMagic+1], hdr[FileHeaderMagic+2] );+ if( fileVer > CurrentVersion )+ {+ throw UnsupportedVersion( fileVer );+ }+ if( fileVer < MinSupportedVersion )+ {+ throw LegacyVersion( fileVer );+ }++ f.Read( m_delay );+ }+ else+ {+ throw LegacyVersion( FileVersion( 0, 2, 0 ) );+ }+ m_traceVersion = fileVer;++ s_loadProgress.total.store( 11, std::memory_order_relaxed );+ s_loadProgress.subTotal.store( 0, std::memory_order_relaxed );+ s_loadProgress.progress.store( LoadProgress::Initialization, std::memory_order_relaxed );+ f.Read8( m_resolution, m_timerMul, m_data.lastTime, m_data.frameOffset, m_pid, m_samplingPeriod, m_data.cpuArch, m_data.cpuId );+ f.Read( m_data.cpuManufacturer, 12 );+ m_data.cpuManufacturer[12] = '\0';++ if( fileVer >= FileVersion( 0, 9, 2 ) )+ {+ uint8_t flag;+ f.Read( flag );+ m_onDemand = flag;+ }+ else+ {+ m_onDemand = m_data.frameOffset != 0;+ }++ uint64_t sz;+ {+ f.Read( sz );+ assert( sz < 1024 );+ char tmp[1024];+ f.Read( tmp, sz );+ m_captureName = std::string( tmp, tmp+sz );+ if( m_captureName.empty() ) m_captureName = f.GetFilename();+ }+ {+ f.Read( sz );+ assert( sz < 1024 );+ char tmp[1024];+ f.Read( tmp, sz );+ m_captureProgram = std::string( tmp, tmp+sz );+ f.Read( m_captureTime );+ }++ f.Read( m_executableTime );++ {+ f.Read( sz );+ assert( sz < 1024 );+ char tmp[1024];+ f.Read( tmp, sz );+ m_hostInfo = std::string( tmp, tmp+sz );+ }++ f.Read( sz );+ m_data.cpuTopology.reserve( sz );+ for( uint64_t i=0; i<sz; i++ )+ {+ uint32_t packageId;+ uint64_t psz;+ f.Read2( packageId, psz );+ auto& package = *m_data.cpuTopology.emplace( packageId, unordered_flat_map<uint32_t, unordered_flat_map<uint32_t, std::vector<uint32_t>>> {} ).first;+ package.second.reserve( psz );+ for( uint64_t j=0; j<psz; j++ )+ {+ if( fileVer >= FileVersion( 0, 11, 2 ) )+ {+ uint32_t dieId;+ uint64_t dsz;+ f.Read2( dieId, dsz );+ auto& die = *package.second.emplace( dieId, unordered_flat_map<uint32_t, std::vector<uint32_t>> {} ).first;+ die.second.reserve( dsz );+ for( uint64_t k=0; k<dsz; k++ )+ {+ uint32_t coreId;+ uint64_t csz;+ f.Read2( coreId, csz );+ auto& core = *die.second.emplace( coreId, std::vector<uint32_t> {} ).first;+ core.second.reserve( csz );+ for( uint64_t l=0; l<csz; l++ )+ {+ uint32_t thread;+ f.Read( thread );+ core.second.emplace_back( thread );++ m_data.cpuTopologyMap.emplace( thread, CpuThreadTopology { packageId, dieId, coreId } );+ }+ }+ }+ else+ {+ auto& die = *package.second.emplace( 0, unordered_flat_map<uint32_t, std::vector<uint32_t>> {} ).first;+ uint32_t coreId;+ uint64_t csz;+ f.Read2( coreId, csz );+ auto& core = *die.second.emplace( coreId, std::vector<uint32_t> {} ).first;+ core.second.reserve( csz );+ for( uint64_t k=0; k<csz; k++ )+ {+ uint32_t thread;+ f.Read( thread );+ core.second.emplace_back( thread );++ m_data.cpuTopologyMap.emplace( thread, CpuThreadTopology { packageId, 0, coreId } );+ }+ }+ }+ }++ f.Read( &m_data.crashEvent, sizeof( m_data.crashEvent ) );++ f.Read( sz );+ m_data.frames.Data().reserve_exact( sz, m_slab );+ for( uint64_t i=0; i<sz; i++ )+ {+ auto ptr = m_slab.AllocInit<FrameData>();+ uint64_t fsz;+ f.Read3( ptr->name, ptr->continuous, fsz );+ ptr->frames.reserve_exact( fsz, m_slab );+ int64_t refTime = 0;+ if( ptr->continuous )+ {+ for( uint64_t j=0; j<fsz; j++ )+ {+ ptr->frames[j].start = ReadTimeOffset( f, refTime );+ ptr->frames[j].end = -1;+ f.Read( &ptr->frames[j].frameImage, sizeof( int32_t ) );+ }+ }+ else+ {+ for( uint64_t j=0; j<fsz; j++ )+ {+ ptr->frames[j].start = ReadTimeOffset( f, refTime );+ ptr->frames[j].end = ReadTimeOffset( f, refTime );+ f.Read( &ptr->frames[j].frameImage, sizeof( int32_t ) );+ }+ }+ for( uint64_t j=0; j<fsz; j++ )+ {+ const auto timeSpan = GetFrameTime( *ptr, j );+ if( timeSpan > 0 )+ {+ ptr->min = std::min( ptr->min, timeSpan );+ ptr->max = std::max( ptr->max, timeSpan );+ ptr->total += timeSpan;+ ptr->sumSq += double( timeSpan ) * timeSpan;+ }+ }+ m_data.frames.Data()[i] = ptr;+ }+ m_data.framesBase = m_data.frames.Data()[0];+ assert( m_data.framesBase->name == 0 );++ unordered_flat_map<uint64_t, const char*> pointerMap;++ f.Read( sz );+ m_data.stringMap.reserve( sz );++ if( !m_allowStringModification )+ {+ m_data.stringData.reserve_exact( sz, m_slab );+ }+ + for( uint64_t i=0; i<sz; i++ )+ {+ uint64_t ptr, ssz;+ f.Read2( ptr, ssz );+ auto dst = m_slab.Alloc<char>( ssz+1 );+ f.Read( dst, ssz );+ dst[ssz] = '\0';+ m_data.stringMap.emplace( charutil::StringKey { dst, size_t( ssz ) }, i );++ if( m_allowStringModification )+ {+ m_data.stringData.push_back( dst );+ }+ else+ {+ m_data.stringData[i] = ( dst );+ }++ pointerMap.emplace( ptr, dst );+ }++ f.Read( sz );+ for( uint64_t i=0; i<sz; i++ )+ {+ uint64_t id, ptr;+ f.Read2( id, ptr );+ auto it = pointerMap.find( ptr );+ if( it != pointerMap.end() )+ {+ m_data.strings.emplace( id, it->second );+ }+ }++ f.Read( sz );+ for( uint64_t i=0; i<sz; i++ )+ {+ uint64_t id, ptr;+ f.Read2( id, ptr );+ auto it = pointerMap.find( ptr );+ if( it != pointerMap.end() )+ {+ m_data.threadNames.emplace( id, it->second );+ }+ }++ f.Read( sz );+ for( uint64_t i=0; i<sz; i++ )+ {+ uint64_t id, ptr, ptr2;+ f.Read3( id, ptr, ptr2 );+ auto it = pointerMap.find( ptr );+ auto it2 = pointerMap.find( ptr2 );+ if( it != pointerMap.end() && it2 != pointerMap.end() )+ {+ m_data.externalNames.emplace( id, std::make_pair( it->second, it2->second ) );+ }+ }++ m_data.localThreadCompress.Load( f );+ m_data.externalThreadCompress.Load( f );++ f.Read( sz );+ if( sz > std::numeric_limits<int16_t>::max() )+ {+ s_loadProgress.total.store( 0, std::memory_order_relaxed );+ char buf[256];+ sprintf( buf, "Too many static source locations (%s)", RealToString( sz ) );+ throw LoadFailure( buf );+ }+ for( uint64_t i=0; i<sz; i++ )+ {+ uint64_t ptr;+ f.Read( ptr );+ SourceLocation srcloc;+ f.Read( &srcloc, sizeof( SourceLocationBase ) );+ srcloc.namehash = 0;+ m_data.sourceLocation.emplace( ptr, srcloc );+ }++ f.Read( sz );+ m_data.sourceLocationExpand.reserve_exact( sz, m_slab );+ f.Read( m_data.sourceLocationExpand.data(), sizeof( uint64_t ) * sz );+ const auto sle = sz;++ f.Read( sz );+ if( sz > std::numeric_limits<int16_t>::max() )+ {+ s_loadProgress.total.store( 0, std::memory_order_relaxed );+ char buf[256];+ sprintf( buf, "Too many dynamic source locations (%s)", RealToString( sz ) );+ throw LoadFailure( buf );+ }+ m_data.sourceLocationPayload.reserve_exact( sz, m_slab );+ for( uint64_t i=0; i<sz; i++ )+ {+ auto srcloc = m_slab.Alloc<SourceLocation>();+ f.Read( srcloc, sizeof( SourceLocationBase ) );+ srcloc->namehash = 0;+ m_data.sourceLocationPayload[i] = srcloc;+ m_data.sourceLocationPayloadMap.emplace( srcloc, int16_t( i ) );+ }++#ifndef TRACY_NO_STATISTICS+ m_data.sourceLocationZones.reserve( sle + sz );++ f.Read( sz );+ for( uint64_t i=0; i<sz; i++ )+ {+ int16_t id;+ uint64_t cnt;+ f.Read2( id, cnt );+ auto status = m_data.sourceLocationZones.emplace( id, SourceLocationZones() );+ assert( status.second );+ status.first->second.zones.reserve( cnt );+ }++ f.Read( sz );+ for( uint64_t i=0; i<sz; i++ )+ {+ int16_t id;+ uint64_t cnt;+ f.Read2( id, cnt );+ auto status = m_data.gpuSourceLocationZones.emplace( id, GpuSourceLocationZones() );+ assert( status.second );+ status.first->second.zones.reserve( cnt );+ }+#else+ f.Read( sz );+ for( uint64_t i=0; i<sz; i++ )+ {+ int16_t id;+ f.Read( id );+ f.Skip( sizeof( uint64_t ) );+ m_data.sourceLocationZonesCnt.emplace( id, 0 );+ }++ f.Read( sz );+ for( uint64_t i=0; i<sz; i++ )+ {+ int16_t id;+ f.Read( id );+ f.Skip( sizeof( uint64_t ) );+ m_data.gpuSourceLocationZonesCnt.emplace( id, 0 );+ }+#endif++ s_loadProgress.progress.store( LoadProgress::Locks, std::memory_order_relaxed );+ f.Read( sz );+ if( eventMask & EventType::Locks )+ {+ s_loadProgress.subTotal.store( sz, std::memory_order_relaxed );+ for( uint64_t i=0; i<sz; i++ )+ {+ s_loadProgress.subProgress.store( i, std::memory_order_relaxed );+ auto lockmapPtr = m_slab.AllocInit<LockMap>();+ auto& lockmap = *lockmapPtr;+ uint32_t id;+ uint64_t tsz;+ f.Read8( id, lockmap.customName, lockmap.srcloc, lockmap.type, lockmap.valid, lockmap.timeAnnounce, lockmap.timeTerminate, tsz );+ lockmap.isContended = false;+ lockmap.threadMap.reserve( tsz );+ lockmap.threadList.reserve( tsz );+ for( uint64_t i=0; i<tsz; i++ )+ {+ uint64_t t;+ f.Read( t );+ lockmap.threadMap.emplace( t, i );+ lockmap.threadList.emplace_back( t );+ }+ f.Read( tsz );+ lockmap.timeline.reserve_exact( tsz, m_slab );+ auto ptr = lockmap.timeline.data();+ int64_t refTime = lockmap.timeAnnounce;+ if( lockmap.type == LockType::Lockable )+ {+ for( uint64_t i=0; i<tsz; i++ )+ {+ auto lev = m_slab.Alloc<LockEvent>();+ const auto lt = ReadTimeOffset( f, refTime );+ lev->SetTime( lt );+ int16_t srcloc;+ f.Read( srcloc );+ lev->SetSrcLoc( srcloc );+ f.Read( &lev->thread, sizeof( LockEvent::thread ) + sizeof( LockEvent::type ) );+ *ptr++ = { lev };+ UpdateLockRange( lockmap, *lev, lt );+ }+ }+ else+ {+ for( uint64_t i=0; i<tsz; i++ )+ {+ auto lev = m_slab.Alloc<LockEventShared>();+ const auto lt = ReadTimeOffset( f, refTime );+ lev->SetTime( lt );+ int16_t srcloc;+ f.Read( srcloc );+ lev->SetSrcLoc( srcloc );+ f.Read( &lev->thread, sizeof( LockEventShared::thread ) + sizeof( LockEventShared::type ) );+ *ptr++ = { lev };+ UpdateLockRange( lockmap, *lev, lt );+ }+ }+ UpdateLockCount( lockmap, 0 );+ m_data.lockMap.emplace( id, lockmapPtr );+ }+ }+ else+ {+ for( uint64_t i=0; i<sz; i++ )+ {+ LockType type;+ uint64_t tsz;+ f.Skip( sizeof( LockMap::customName ) + sizeof( uint32_t ) + sizeof( LockMap::srcloc ) );+ f.Read( type );+ f.Skip( sizeof( LockMap::valid ) + sizeof( LockMap::timeAnnounce ) + sizeof( LockMap::timeTerminate ) );+ f.Read( tsz );+ f.Skip( tsz * sizeof( uint64_t ) );+ f.Read( tsz );+ f.Skip( tsz * ( sizeof( int64_t ) + sizeof( int16_t ) + sizeof( LockEvent::thread ) + sizeof( LockEvent::type ) ) );+ }+ }++ s_loadProgress.subTotal.store( 0, std::memory_order_relaxed );+ s_loadProgress.progress.store( LoadProgress::Messages, std::memory_order_relaxed );+ unordered_flat_map<uint64_t, MessageData*> msgMap;+ f.Read( sz );+ if( eventMask & EventType::Messages )+ {+ m_data.messages.reserve_exact( sz, m_slab );+ int64_t refTime = 0;+ for( uint64_t i=0; i<sz; i++ )+ {+ uint64_t ptr;+ f.Read( ptr );+ auto msgdata = m_slab.Alloc<MessageData>();+ msgdata->time = ReadTimeOffset( f, refTime );+ f.Read3( msgdata->ref, msgdata->color, msgdata->callstack );+ m_data.messages[i] = msgdata;+ msgMap.emplace( ptr, msgdata );+ }+ }+ else+ {+ f.Skip( sz * ( sizeof( uint64_t ) + sizeof( MessageData::time ) + sizeof( MessageData::ref ) + sizeof( MessageData::color ) + sizeof( MessageData::callstack ) ) );+ }++ f.Read( sz );+ assert( sz != 0 );+ m_data.zoneExtra.reserve_exact( sz, m_slab );+ f.Read( m_data.zoneExtra.data(), sz * sizeof( ZoneExtra ) );++ s_loadProgress.progress.store( LoadProgress::Zones, std::memory_order_relaxed );+ f.Read( sz );+ s_loadProgress.subTotal.store( sz, std::memory_order_relaxed );+ s_loadProgress.subProgress.store( 0, std::memory_order_relaxed );+ f.Read( sz );+ m_data.zoneChildren.reserve_exact( sz, m_slab );+ memset( (char*)m_data.zoneChildren.data(), 0, sizeof( Vector<short_ptr<ZoneEvent>> ) * sz );+ int32_t childIdx = 0;+ f.Read( sz );+ m_data.threads.reserve_exact( sz, m_slab );+ for( uint64_t i=0; i<sz; i++ )+ {+ auto td = m_slab.AllocInit<ThreadData>();+ uint64_t tid;+ if( fileVer >= FileVersion( 0, 11, 1 ) )+ {+ f.Read5( tid, td->count, td->kernelSampleCnt, td->isFiber, td->groupHint );+ }+ else+ {+ f.Read4( tid, td->count, td->kernelSampleCnt, td->isFiber );+ td->groupHint = 0;+ }+ td->id = tid;+ m_data.zonesCnt += td->count;+ uint32_t tsz;+ f.Read( tsz );+ if( tsz != 0 )+ {+ ReadTimeline( f, td->timeline, tsz, 0, childIdx );+ }+ uint64_t msz;+ f.Read( msz );+ if( eventMask & EventType::Messages )+ {+ const auto ctid = CompressThread( tid );+ td->messages.reserve_exact( msz, m_slab );+ for( uint64_t j=0; j<msz; j++ )+ {+ uint64_t ptr;+ f.Read( ptr );+ auto md = msgMap[ptr];+ td->messages[j] = md;+ md->thread = ctid;+ }+ }+ else+ {+ f.Skip( msz * sizeof( uint64_t ) );+ }+ uint64_t ssz;+ f.Read( ssz );+ if( ssz != 0 )+ {+ if( eventMask & EventType::Samples )+ {+ int64_t refTime = 0;+ td->ctxSwitchSamples.reserve_exact( ssz, m_slab );+ auto ptr = td->ctxSwitchSamples.data();+ for( uint64_t j=0; j<ssz; j++ )+ {+ ptr->time.SetVal( ReadTimeOffset( f, refTime ) );+ f.Read( &ptr->callstack, sizeof( ptr->callstack ) );+ ptr++;+ }+ }+ else+ {+ f.Skip( ssz * ( 8 + 3 ) );+ }+ }+ f.Read( ssz );+ if( ssz != 0 )+ {+ if( eventMask & EventType::Samples )+ {+ m_data.samplesCnt += ssz;+ int64_t refTime = 0;+ td->samples.reserve_exact( ssz, m_slab );+ auto ptr = td->samples.data();+ for( uint64_t j=0; j<ssz; j++ )+ {+ ptr->time.SetVal( ReadTimeOffset( f, refTime ) );+ f.Read( &ptr->callstack, sizeof( ptr->callstack ) );+ ptr++;+ }+ }+ else+ {+ f.Skip( ssz * ( 8 + 3 ) );+ }+ }+ m_data.threads[i] = td;+ m_threadMap.emplace( tid, td );+ }++ s_loadProgress.progress.store( LoadProgress::GpuZones, std::memory_order_relaxed );+ f.Read( sz );+ s_loadProgress.subTotal.store( sz, std::memory_order_relaxed );+ s_loadProgress.subProgress.store( 0, std::memory_order_relaxed );+ f.Read( sz );+ m_data.gpuChildren.reserve_exact( sz, m_slab );+ memset( (char*)m_data.gpuChildren.data(), 0, sizeof( Vector<short_ptr<GpuEvent>> ) * sz );+ childIdx = 0;+ f.Read( sz );+ m_data.gpuData.reserve_exact( sz, m_slab );+ for( uint64_t i=0; i<sz; i++ )+ {+ auto ctx = m_slab.AllocInit<GpuCtxData>();+ uint8_t calibration;+ f.Read7( ctx->thread, calibration, ctx->count, ctx->period, ctx->type, ctx->name, ctx->overflow );+ ctx->hasCalibration = calibration;+ ctx->hasPeriod = ctx->period != 1.f;+ m_data.gpuCnt += ctx->count;+ uint64_t tdsz;+ f.Read( tdsz );+ for( uint64_t j=0; j<tdsz; j++ )+ {+ uint64_t tid, tsz;+ f.Read2( tid, tsz );+ if( tsz != 0 )+ {+ int64_t refTime = 0;+ int64_t refGpuTime = 0;+ auto td = ctx->threadData.emplace( tid, GpuCtxThreadData {} ).first;+ ReadTimeline( f, td->second.timeline, tsz, refTime, refGpuTime, childIdx );+ }+ }+ m_data.gpuData[i] = ctx;+ }++ s_loadProgress.progress.store( LoadProgress::Plots, std::memory_order_relaxed );+ f.Read( sz );+ if( eventMask & EventType::Plots )+ {+ m_data.plots.Data().reserve( sz );+ s_loadProgress.subTotal.store( sz, std::memory_order_relaxed );+ for( uint64_t i=0; i<sz; i++ )+ {+ s_loadProgress.subProgress.store( i, std::memory_order_relaxed );+ auto pd = m_slab.AllocInit<PlotData>();+ uint64_t psz;+ f.Read10( pd->type, pd->format, pd->showSteps, pd->fill, pd->color, pd->name, pd->min, pd->max, pd->sum, psz );+ pd->data.reserve_exact( psz, m_slab );+ auto ptr = pd->data.data();+ int64_t refTime = 0;+ for( uint64_t j=0; j<psz; j++ )+ {+ int64_t t;+ f.Read2( t, ptr->val );+ refTime += t;+ ptr->time = refTime;+ ptr++;+ }+ m_data.plots.Data().push_back_no_space_check( pd );+ }+ }+ else+ {+ for( uint64_t i=0; i<sz; i++ )+ {+ f.Skip( sizeof( PlotData::name ) + sizeof( PlotData::min ) + sizeof( PlotData::max ) + sizeof( PlotData::sum ) + sizeof( PlotData::type ) + sizeof( PlotData::format ) + sizeof( PlotData::showSteps ) + sizeof( PlotData::fill ) + sizeof( PlotData::color ) );+ uint64_t psz;+ f.Read( psz );+ f.Skip( psz * ( sizeof( uint64_t ) + sizeof( double ) ) );+ }+ }++ s_loadProgress.subTotal.store( 0, std::memory_order_relaxed );+ s_loadProgress.progress.store( LoadProgress::Memory, std::memory_order_relaxed );++ uint64_t memcount, memtarget, memload = 0;+ f.Read2( memcount, memtarget );+ s_loadProgress.subTotal.store( memtarget, std::memory_order_relaxed );++ for( uint64_t k=0; k<memcount; k++ )+ {+ uint64_t memname;+ f.Read2( memname, sz );+ if( eventMask & EventType::Memory )+ {+ auto mit = m_data.memNameMap.emplace( memname, m_slab.AllocInit<MemData>() );+ if( memname == 0 ) m_data.memory = mit.first->second;+ auto& memdata = *mit.first->second;+ memdata.data.reserve_exact( sz, m_slab );+ uint64_t activeSz, freesSz;+ f.Read2( activeSz, freesSz );+ memdata.active.reserve( activeSz );+ memdata.frees.reserve_exact( freesSz, m_slab );+ auto mem = memdata.data.data();+ s_loadProgress.subTotal.store( sz, std::memory_order_relaxed );+ size_t fidx = 0;+ int64_t refTime = 0;+ auto& frees = memdata.frees;+ auto& active = memdata.active;++ for( uint64_t i=0; i<sz; i++ )+ {+ s_loadProgress.subProgress.store( memload+i, std::memory_order_relaxed );+ uint64_t ptr, size;+ Int24 csAlloc;+ int64_t timeAlloc, timeFree;+ uint16_t threadAlloc, threadFree;+ f.Read8( ptr, size, csAlloc, mem->csFree, timeAlloc, timeFree, threadAlloc, threadFree );+ mem->SetPtr( ptr );+ mem->SetSize( size );+ mem->SetCsAlloc( csAlloc.Val() );+ refTime += timeAlloc;+ mem->SetTimeThreadAlloc( refTime, threadAlloc );+ if( timeFree >= 0 )+ {+ mem->SetTimeThreadFree( timeFree + refTime, threadFree );+ frees[fidx++] = i;+ }+ else+ {+ mem->SetTimeThreadFree( timeFree, threadFree );+ active.emplace( ptr, i );+ }+ mem++;+ }+ memload += sz;+ f.Read4( memdata.high, memdata.low, memdata.usage, memdata.name );++ if( sz != 0 )+ {+ memdata.reconstruct = true;+ }+ }+ else+ {+ f.Skip( 2 * sizeof( uint64_t ) );+ f.Skip( sz * ( sizeof( uint64_t ) + sizeof( uint64_t ) + sizeof( Int24 ) + sizeof( Int24 ) + sizeof( int64_t ) * 2 + sizeof( uint16_t ) * 2 ) );+ f.Skip( sizeof( MemData::high ) + sizeof( MemData::low ) + sizeof( MemData::usage ) + sizeof( MemData::name ) );+ }+ }++ s_loadProgress.subTotal.store( 0, std::memory_order_relaxed );+ s_loadProgress.progress.store( LoadProgress::CallStacks, std::memory_order_relaxed );+ f.Read( sz );+ m_data.callstackPayload.reserve_exact( sz+1, m_slab );+ m_data.callstackPayload[0] = nullptr;+ for( uint64_t i=0; i<sz; i++ )+ {+ uint16_t csz;+ f.Read( csz );++ const auto memsize = sizeof( VarArray<CallstackFrameId> ) + csz * sizeof( CallstackFrameId );+ auto mem = (char*)m_slab.AllocRaw( memsize );++ auto data = (CallstackFrameId*)mem;+ f.Read( data, csz * sizeof( CallstackFrameId ) );++ auto arr = (VarArray<CallstackFrameId>*)( mem + csz * sizeof( CallstackFrameId ) );+ new(arr) VarArray<CallstackFrameId>( csz, data );++ m_data.callstackPayload[i+1] = arr;+ }++ f.Read( sz );+ m_data.callstackFrameMap.reserve( sz );+ for( uint64_t i=0; i<sz; i++ )+ {+ CallstackFrameId id;+ auto frameData = m_slab.Alloc<CallstackFrameData>();+ f.Read3( id, frameData->size, frameData->imageName );++ frameData->data = m_slab.Alloc<CallstackFrame>( frameData->size );+ f.Read( frameData->data, sizeof( CallstackFrame ) * frameData->size );++ m_data.callstackFrameMap.emplace( id, frameData );+ }++ f.Read( sz );+ if( sz > 0 )+ {+ m_data.appInfo.reserve_exact( sz, m_slab );+ f.Read( m_data.appInfo.data(), sizeof( m_data.appInfo[0] ) * sz );+ }++ s_loadProgress.subTotal.store( 0, std::memory_order_relaxed );+ s_loadProgress.progress.store( LoadProgress::FrameImages, std::memory_order_relaxed );++ if( eventMask & EventType::FrameImages )+ {+ ZSTD_CDict* cdict = nullptr;+ uint32_t dsz;+ f.Read( dsz );+ auto dict = new char[dsz];+ f.Read( dict, dsz );+ cdict = ZSTD_createCDict( dict, dsz, 3 );+ m_texcomp.SetDict( ZSTD_createDDict( dict, dsz ) );+ delete[] dict;++ f.Read( sz );+ m_data.frameImage.reserve_exact( sz, m_slab );+ s_loadProgress.subTotal.store( sz, std::memory_order_relaxed );+ if( sz != 0 )+ {+ struct JobData+ {+ enum State : int { InProgress, Available, DataReady };+ FrameImage* fi;+ char* buf = nullptr;+ size_t bufsz = 0;+ char* outbuf = nullptr;+ size_t outsz = 0;+ ZSTD_CCtx* ctx = ZSTD_createCCtx();+ alignas(64) std::atomic<State> state = Available;+ };++#ifdef __EMSCRIPTEN__+ const int jobs = 1;+#else+ // Leave one thread for file reader, second thread for dispatch (this thread)+ // Minimum 2 threads to have at least two buffers (one in use, second one filling up)+ const auto jobs = std::max<int>( std::thread::hardware_concurrency() - 2, 2 );+#endif+ auto td = std::make_unique<TaskDispatch>( jobs, "FrImg Zstd" );+ auto data = std::make_unique<JobData[]>( jobs );++ for( uint64_t i=0; i<sz; i++ )+ {+ s_loadProgress.subProgress.store( i, std::memory_order_relaxed );+ auto fi = m_slab.Alloc<FrameImage>();+ f.Read3( fi->w, fi->h, fi->flip );+ const auto sz = size_t( fi->w * fi->h / 2 );++ int idx = -1;+ for(;;)+ {+ for( int j=0; j<jobs; j++ )+ {+ const auto state = data[j].state.load( std::memory_order_acquire );+ if( state != JobData::InProgress )+ {+ if( state == JobData::DataReady )+ {+ char* tmp = (char*)m_slab.AllocBig( data[j].fi->csz );+ memcpy( tmp, data[j].outbuf, data[j].fi->csz );+ data[j].fi->ptr = tmp;+ }+ idx = j;+ break;+ }+ }+ if( idx >= 0 ) break;+ YieldThread();+ }++ if( data[idx].bufsz < sz )+ {+ data[idx].bufsz = sz;+ delete[] data[idx].buf;+ data[idx].buf = new char[sz];+ }+ f.Read( data[idx].buf, sz );+ data[idx].fi = fi;++ data[idx].state.store( JobData::InProgress, std::memory_order_release );+ td->Queue( [this, &data, idx, fi, cdict] {+ if( cdict )+ {+ fi->csz = m_texcomp.Pack( data[idx].ctx, cdict, data[idx].outbuf, data[idx].outsz, data[idx].buf, fi->w * fi->h / 2 );+ }+ else+ {+ fi->csz = m_texcomp.Pack( data[idx].ctx, data[idx].outbuf, data[idx].outsz, data[idx].buf, fi->w * fi->h / 2 );+ }+ data[idx].state.store( JobData::DataReady, std::memory_order_release );+ } );++ m_data.frameImage[i] = fi;+ }+ td->Sync();+ td.reset();+ for( int i=0; i<jobs; i++ )+ {+ if( data[i].state.load( std::memory_order_acquire ) == JobData::DataReady )+ {+ char* tmp = (char*)m_slab.AllocBig( data[i].fi->csz );+ memcpy( tmp, data[i].outbuf, data[i].fi->csz );+ data[i].fi->ptr = tmp;+ }+ ZSTD_freeCCtx( data[i].ctx );+ delete[] data[i].buf;+ delete[] data[i].outbuf;+ }++ const auto& frames = GetFramesBase()->frames;+ const auto fsz = uint32_t( frames.size() );+ for( uint32_t i=0; i<fsz; i++ )+ {+ const auto& f = frames[i];+ if( f.frameImage != -1 )+ {+ m_data.frameImage[f.frameImage]->frameRef = i;+ }+ }+ }++ ZSTD_freeCDict( cdict );+ }+ else+ {+ uint32_t dsz;+ f.Read( dsz );+ f.Skip( dsz );+ f.Read( sz );+ s_loadProgress.subTotal.store( sz, std::memory_order_relaxed );+ for( uint64_t i=0; i<sz; i++ )+ {+ s_loadProgress.subProgress.store( i, std::memory_order_relaxed );+ uint16_t w, h;+ f.Read2( w, h );+ const auto fisz = w * h / 2;+ f.Skip( fisz + sizeof( FrameImage::flip ) );+ }+ for( auto& v : m_data.framesBase->frames )+ {+ v.frameImage = -1;+ }+ }++ s_loadProgress.subTotal.store( 0, std::memory_order_relaxed );+ s_loadProgress.progress.store( LoadProgress::ContextSwitches, std::memory_order_relaxed );++ const bool ctxSwitchesHaveWakeupCpu = fileVer >= FileVersion( 0, 11, 3 );+ if( eventMask & EventType::ContextSwitches )+ {+ f.Read( sz );+ s_loadProgress.subTotal.store( sz, std::memory_order_relaxed );+ m_data.ctxSwitch.reserve( sz );+ for( uint64_t i=0; i<sz; i++ )+ {+ s_loadProgress.subProgress.store( i, std::memory_order_relaxed );+ uint64_t thread, csz;+ f.Read2( thread, csz );+ auto data = m_slab.AllocInit<ContextSwitch>();+ data->v.reserve_exact( csz, m_slab );+ int64_t runningTime = 0;+ int64_t refTime = 0;+ auto ptr = data->v.data();+ for( uint64_t j=0; j<csz; j++ )+ {+ int64_t deltaWakeup, deltaStart, diff, thread;+ uint8_t cpu, wakeupcpu;+ int8_t reason, state;+ f.Read7( deltaWakeup, deltaStart, diff, cpu, reason, state, thread );+ if ( ctxSwitchesHaveWakeupCpu )+ {+ f.Read(wakeupcpu);+ }+ else+ {+ wakeupcpu = cpu;+ }+ refTime += deltaWakeup;+ ptr->SetWakeup( refTime );+ ptr->SetWakeupCpu( wakeupcpu );+ refTime += deltaStart;+ ptr->SetStart( refTime );+ ptr->SetCpu( cpu );+ if( diff > 0 ) runningTime += diff;+ refTime += diff;+ ptr->SetEnd( refTime );+ ptr->SetReason( reason );+ ptr->SetState( state );+ ptr->SetThread( CompressThread( thread ) );+ ptr++;+ }+ data->runningTime = runningTime;+ m_data.ctxSwitch.emplace( thread, data );+ }+ }+ else+ {+ f.Read( sz );+ s_loadProgress.subTotal.store( sz, std::memory_order_relaxed );+ for( uint64_t i=0; i<sz; i++ )+ {+ s_loadProgress.subProgress.store( i, std::memory_order_relaxed );+ f.Skip( sizeof( uint64_t ) );+ uint64_t csz;+ f.Read( csz );+ f.Skip( csz * ( sizeof( int64_t ) * 4 + sizeof( int8_t ) * ( 3 + int( ctxSwitchesHaveWakeupCpu ) ) ) );+ }+ }++ s_loadProgress.subTotal.store( 0, std::memory_order_relaxed );+ s_loadProgress.progress.store( LoadProgress::ContextSwitchesPerCpu, std::memory_order_relaxed );+ f.Read( sz );+ s_loadProgress.subTotal.store( sz, std::memory_order_relaxed );+ if( eventMask & EventType::ContextSwitches )+ {+ uint64_t cnt = 0;+ for( int i=0; i<256; i++ )+ {+ int64_t refTime = 0;+ f.Read( sz );+ if( sz != 0 )+ {+ m_data.cpuDataCount = i+1;+ m_data.cpuData[i].cs.reserve_exact( sz, m_slab );+ auto ptr = m_data.cpuData[i].cs.data();+ for( uint64_t j=0; j<sz; j++ )+ {+ int64_t deltaStart, deltaEnd;+ uint16_t thread;+ f.Read3( deltaStart, deltaEnd, thread );+ refTime += deltaStart;+ ptr->SetStartThread( refTime, thread );+ refTime += deltaEnd;+ ptr->SetEnd( refTime );+ ptr++;+ }+ cnt += sz;+ }+ s_loadProgress.subProgress.store( cnt, std::memory_order_relaxed );+ }+ }+ else+ {+ for( int i=0; i<256; i++ )+ {+ f.Read( sz );+ f.Skip( sz * ( sizeof( int64_t ) * 2 + sizeof( uint16_t ) ) );+ }+ }++ f.Read( sz );+ for( uint64_t i=0; i<sz; i++ )+ {+ uint64_t tid, pid;+ f.Read2( tid, pid );+ m_data.tidToPid.emplace( tid, pid );+ }++ f.Read( sz );+ for( uint64_t i=0; i<sz; i++ )+ {+ uint64_t tid;+ CpuThreadData data;+ f.Read2( tid, data );+ m_data.cpuThreadData.emplace( tid, data );+ }++ f.Read( sz );+ m_data.symbolLoc.reserve_exact( sz, m_slab );+ f.Read( sz );+ m_data.symbolLocInline.reserve_exact( sz, m_slab );+ f.Read( sz );+ m_data.symbolMap.reserve( sz );+ int symIdx = 0;+ int symInlineIdx = 0;+ for( uint64_t i=0; i<sz; i++ )+ {+ uint64_t symAddr;+ StringIdx name, file, imageName, callFile;+ uint32_t line, callLine;+ uint8_t isInline;+ Int24 size;+ f.Read9( symAddr, name, file, line, imageName, callFile, callLine, isInline, size );+ m_data.symbolMap.emplace( symAddr, SymbolData { { name, file, line }, imageName, callFile, callLine, isInline, size } );+ if( isInline )+ {+ m_data.symbolLocInline[symInlineIdx++] = symAddr;+ }+ else+ {+ m_data.symbolLoc[symIdx++] = SymbolLocation { symAddr, size.Val() };+ }+ }++#ifdef __EMSCRIPTEN__+ pdqsort_branchless( m_data.symbolLoc.begin(), m_data.symbolLoc.end(), [] ( const auto& l, const auto& r ) { return l.addr < r.addr; } );+ pdqsort_branchless( m_data.symbolLocInline.begin(), m_data.symbolLocInline.end() );+#else+ ppqsort::sort( ppqsort::execution::par, m_data.symbolLoc.begin(), m_data.symbolLoc.end(), [] ( const auto& l, const auto& r ) { return l.addr < r.addr; } );+ ppqsort::sort( ppqsort::execution::par, m_data.symbolLocInline.begin(), m_data.symbolLocInline.end() );+#endif++ f.Read( sz );+ if( eventMask & EventType::SymbolCode )+ {+ uint64_t ssz = 0;+ m_data.symbolCode.reserve( sz );+ for( uint64_t i=0; i<sz; i++ )+ {+ uint64_t symAddr;+ uint32_t len;+ f.Read2( symAddr, len );+ ssz += len;+ auto ptr = (char*)m_slab.AllocBig( len );+ f.Read( ptr, len );+ m_data.symbolCode.emplace( symAddr, MemoryBlock { ptr, len } );+ }+ m_data.symbolCodeSize = ssz;+ }+ else+ {+ for( uint64_t i=0; i<sz; i++ )+ {+ uint64_t symAddr;+ uint32_t len;+ f.Read2( symAddr, len );+ f.Skip( len );+ }+ }++ f.Read( sz );+ m_data.codeSymbolMap.reserve( sz );+ for( uint64_t i=0; i<sz; i++ )+ {+ uint64_t v1, v2;+ f.Read2( v1, v2 );+ m_data.codeSymbolMap.emplace( v1, v2 );+ }++ f.Read( sz );+ m_data.hwSamples.reserve( sz );+ for( uint64_t i=0; i<sz; i++ )+ {+ uint64_t addr;+ f.Read( addr );+ auto& data = m_data.hwSamples.emplace( addr, HwSampleData {} ).first->second;+ ReadHwSampleVec( f, data.cycles, m_slab );+ ReadHwSampleVec( f, data.retired, m_slab );+ ReadHwSampleVec( f, data.cacheRef, m_slab );+ ReadHwSampleVec( f, data.cacheMiss, m_slab );+ if( ReadHwSampleVec( f, data.branchRetired, m_slab ) != 0 ) m_data.hasBranchRetirement = true;+ ReadHwSampleVec( f, data.branchMiss, m_slab );+ }++ f.Read( sz );+ if( eventMask & EventType::SourceCache )+ {+ m_data.sourceFileCache.reserve( sz );+ for( uint64_t i=0; i<sz; i++ )+ {+ uint32_t len;+ f.Read( len );+ auto key = m_slab.Alloc<char>( len+1 );+ f.Read( key, len );+ key[len] = '\0';+ f.Read( len );+ auto data = (char*)m_slab.AllocBig( len );+ f.Read( data, len );+ m_data.sourceFileCache.emplace( key, MemoryBlock { data, len } );+ }+ }+ else+ {+ for( uint64_t i=0; i<sz; i++ )+ {+ uint32_t s32;+ f.Read( s32 );+ f.Skip( s32 );+ f.Read( s32 );+ f.Skip( s32 );+ }+ }++ s_loadProgress.total.store( 0, std::memory_order_relaxed );+ m_loadTime = std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::high_resolution_clock::now() - loadStart ).count();++ if( !bgTasks )+ {+ m_backgroundDone.store( true, std::memory_order_relaxed );+ }+ else+ {+ m_backgroundDone.store( false, std::memory_order_relaxed );+#ifndef TRACY_NO_STATISTICS+ m_threadBackground = std::thread( [this, eventMask] {+ std::vector<std::thread> jobs;++ if( !m_data.ctxSwitch.empty() && m_data.cpuDataCount != 0 )+ {+ jobs.emplace_back( std::thread( [this] { ReconstructContextSwitchUsage(); } ) );+ }++ for( auto& mem : m_data.memNameMap )+ {+ if( mem.second->reconstruct ) jobs.emplace_back( std::thread( [this, mem = mem.second] { ReconstructMemAllocPlot( *mem ); } ) );+ }++ std::function<void(uint8_t*, Vector<short_ptr<ZoneEvent>>&, uint16_t)> ProcessTimeline;+ ProcessTimeline = [this, &ProcessTimeline] ( uint8_t* countMap, Vector<short_ptr<ZoneEvent>>& _vec, uint16_t thread )+ {+ if( m_shutdown.load( std::memory_order_relaxed ) ) return;+ assert( _vec.is_magic() );+ auto& vec = *(Vector<ZoneEvent>*)( &_vec );+ for( auto& zone : vec )+ {+ if( zone.IsEndValid() ) ReconstructZoneStatistics( countMap, zone, thread );+ if( zone.HasChildren() )+ {+ countMap[uint16_t(zone.SrcLoc())]++;+ ProcessTimeline( countMap, GetZoneChildrenMutable( zone.Child() ), thread );+ countMap[uint16_t(zone.SrcLoc())]--;+ }+ }+ };++ jobs.emplace_back( std::thread( [this, ProcessTimeline] {+ for( auto& t : m_data.threads )+ {+ if( m_shutdown.load( std::memory_order_relaxed ) ) return;+ if( !t->timeline.empty() )+ {+ uint8_t countMap[64*1024];+ // Don't touch thread compression cache in a thread.+ ProcessTimeline( countMap, t->timeline, m_data.localThreadCompress.DecompressMustRaw( t->id ) );+ }+ }+ std::lock_guard<std::mutex> lock( m_data.lock );+ m_data.sourceLocationZonesReady = true;+ } ) );++ std::function<void(Vector<short_ptr<GpuEvent>>&, uint16_t)> ProcessTimelineGpu;+ ProcessTimelineGpu = [this, &ProcessTimelineGpu] ( Vector<short_ptr<GpuEvent>>& _vec, uint16_t thread )+ {+ if( m_shutdown.load( std::memory_order_relaxed ) ) return;+ assert( _vec.is_magic() );+ auto& vec = *(Vector<GpuEvent>*)( &_vec );+ for( auto& zone : vec )+ {+ if( zone.GpuEnd() >= 0 ) ReconstructZoneStatistics( zone, thread );+ if( zone.Child() >= 0 )+ {+ ProcessTimelineGpu( GetGpuChildrenMutable( zone.Child() ), thread );+ }+ }+ };++ jobs.emplace_back( std::thread( [this, ProcessTimelineGpu] {+ for( auto& t : m_data.gpuData )+ {+ for( auto& td : t->threadData )+ {+ if( m_shutdown.load( std::memory_order_relaxed ) ) return;+ if( !td.second.timeline.empty() )+ {+ ProcessTimelineGpu( td.second.timeline, td.first );+ }+ }+ }+ std::lock_guard<std::mutex> lock( m_data.lock );+ m_data.gpuSourceLocationZonesReady = true;+ } ) );++ if( eventMask & EventType::Samples )+ {+ jobs.emplace_back( std::thread( [this] {+ unordered_flat_map<uint32_t, uint32_t> counts;+ uint32_t total = 0;+ for( auto& t : m_data.threads ) total += t->samples.size();+ if( total != 0 )+ {+ for( auto& t : m_data.threads )+ {+ if( m_shutdown.load( std::memory_order_relaxed ) ) return;+ auto cit = t->ctxSwitchSamples.begin();+ for( auto& sd : t->samples )+ {+ bool isCtxSwitch = false;+ if( cit != t->ctxSwitchSamples.end() )+ {+ const auto sdt = sd.time.Val();+ cit = std::lower_bound( cit, t->ctxSwitchSamples.end(), sdt, []( const auto& l, const auto& r ) { return (uint64_t)l.time.Val() < (uint64_t)r; } );+ isCtxSwitch = cit != t->ctxSwitchSamples.end() && cit->time.Val() == sdt;+ }+ if( !isCtxSwitch )+ {+ const auto cs = sd.callstack.Val();+ auto it = counts.find( cs );+ if( it == counts.end() )+ {+ counts.emplace( cs, 1 );+ }+ else+ {+ it->second++;+ }++ const auto& callstack = GetCallstack( cs );+ auto& ip = callstack[0];+ auto frame = GetCallstackFrame( ip );+ if( frame )+ {+ const auto symAddr = frame->data[0].symAddr;+ auto it = m_data.instructionPointersMap.find( symAddr );+ if( it == m_data.instructionPointersMap.end() )+ {+ m_data.instructionPointersMap.emplace( symAddr, unordered_flat_map<CallstackFrameId, uint32_t, CallstackFrameIdHash, CallstackFrameIdCompare> { { ip, 1 } } );+ }+ else+ {+ auto fit = it->second.find( ip );+ if( fit == it->second.end() )+ {+ it->second.emplace( ip, 1 );+ }+ else+ {+ fit->second++;+ }+ }+ }+ }+ }+ }+ for( auto& v : counts ) UpdateSampleStatistics( v.first, v.second, false );+ }+ std::lock_guard<std::mutex> lock( m_data.lock );+ m_data.callstackSamplesReady = true;+ } ) );++ jobs.emplace_back( std::thread( [this] {+ uint32_t gcnt = 0;+ for( auto& t : m_data.threads )+ {+ if( m_shutdown.load( std::memory_order_relaxed ) ) return;+ if( !t->samples.empty() )+ {+ if( t->samples[0].time.Val() != 0 )+ {+ for( auto& sd : t->samples )+ {+ gcnt += AddGhostZone( GetCallstack( sd.callstack.Val() ), &t->ghostZones, sd.time.Val() );+ }+ }+ else+ {+ for( auto& sd : t->samples )+ {+ const auto st = sd.time.Val();+ if( st != 0 ) gcnt += AddGhostZone( GetCallstack( sd.callstack.Val() ), &t->ghostZones, st );+ }+ }+ }+ }+ std::lock_guard<std::mutex> lock( m_data.lock );+ m_data.ghostZonesReady = true;+ m_data.ghostCnt = gcnt;+ } ) );++ jobs.emplace_back( std::thread( [this] {+ for( auto& t : m_data.threads )+ {+ uint16_t tid = CompressThread( t->id );+ for( auto& v : t->samples )+ {+ const auto& time = v.time;+ const auto cs = v.callstack.Val();+ const auto& callstack = GetCallstack( cs );+ auto& ip = callstack[0];+ auto frame = GetCallstackFrame( ip );+ if( frame )+ {+ const auto symAddr = frame->data[0].symAddr;+ auto it = m_data.symbolSamples.find( symAddr );+ if( it == m_data.symbolSamples.end() )+ {+ m_data.symbolSamples.emplace( symAddr, Vector<SampleDataRange>( SampleDataRange { time, tid, ip } ) );+ }+ else+ {+ it->second.push_back_non_empty( SampleDataRange { time, tid, ip } );+ }+ }+ auto childAddr = GetCanonicalPointer( callstack[0] );+ for( uint16_t i=1; i<callstack.size(); i++ )+ {+ auto addr = GetCanonicalPointer( callstack[i] );+ auto it = m_data.childSamples.find( addr );+ if( it == m_data.childSamples.end() )+ {+ m_data.childSamples.emplace( addr, Vector<ChildSample>( ChildSample { time, childAddr } ) );+ }+ else+ {+ it->second.push_back_non_empty( ChildSample { time, childAddr } );+ }+ childAddr = addr;+ }+ }+ }+ for( auto& v : m_data.symbolSamples )+ {+ pdqsort_branchless( v.second.begin(), v.second.end(), []( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs.time.Val(); } );+ }+ for( auto& v : m_data.childSamples )+ {+ pdqsort_branchless( v.second.begin(), v.second.end(), []( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs.time.Val(); } );+ }+ std::lock_guard<std::mutex> lock( m_data.lock );+ m_data.symbolSamplesReady = true;+ } ) );+ }++ for( auto& job : jobs ) job.join();+ m_backgroundDone.store( true, std::memory_order_relaxed );+ } );+#else+ m_backgroundDone.store( true, std::memory_order_relaxed );+#endif+ }+}++Worker::~Worker()+{+ Shutdown();++ if( m_threadNet.joinable() ) m_threadNet.join();+ if( m_thread.joinable() ) m_thread.join();+ if( m_threadBackground.joinable() ) m_threadBackground.join();++ delete[] m_buffer;+ LZ4_freeStreamDecode( (LZ4_streamDecode_t*)m_stream );++ delete[] m_frameImageBuffer;+ delete[] m_tmpBuf;++ for( auto& v : m_data.threads )+ {+ v->timeline.~Vector();+ v->stack.~Vector();+ v->messages.~Vector();+ v->zoneIdStack.~Vector();+ v->samples.~Vector();+#ifndef TRACY_NO_STATISTICS+ v->childTimeStack.~Vector();+ v->ghostZones.~Vector();+#endif+ }+ for( auto& v : m_data.gpuData )+ {+ for( auto& vt : v->threadData )+ {+ vt.second.timeline.~Vector();+ vt.second.stack.~Vector();+ }+ }+ for( auto& v : m_data.plots.Data() )+ {+ v->~PlotData();+ }+ for( auto& v : m_data.frames.Data() )+ {+ v->~FrameData();+ }+ for( auto& v : m_data.lockMap )+ {+ v.second->~LockMap();+ }+ for( auto& v : m_data.zoneChildren )+ {+ v.~Vector();+ }+ for( auto& v : m_data.memNameMap )+ {+ v.second->~MemData();+ }+ for( auto& v : m_data.ctxSwitch )+ {+ v.second->v.~Vector();+ }+ for( auto& v : m_data.gpuChildren )+ {+ v.~Vector();+ }+#ifndef TRACY_NO_STATISTICS+ for( auto& v : m_data.ghostChildren )+ {+ v.~Vector();+ }+#endif+}++uint64_t Worker::GetLockCount() const+{+ uint64_t cnt = 0;+ for( auto& l : m_data.lockMap )+ {+ cnt += l.second->timeline.size();+ }+ return cnt;+}++uint64_t Worker::GetPlotCount() const+{+ uint64_t cnt = 0;+ for( auto& p : m_data.plots.Data() )+ {+ if( p->type == PlotType::User )+ {+ cnt += p->data.size();+ }+ }+ return cnt;+}++uint64_t Worker::GetTracyPlotCount() const+{+ uint64_t cnt = 0;+ for( auto& p : m_data.plots.Data() )+ {+ if( p->type != PlotType::User )+ {+ cnt += p->data.size();+ }+ }+ return cnt;+}++uint64_t Worker::GetContextSwitchCount() const+{+ uint64_t cnt = 0;+ for( auto& v : m_data.ctxSwitch )+ {+ cnt += v.second->v.size();+ }+ return cnt;+}++uint64_t Worker::GetContextSwitchPerCpuCount() const+{+ uint64_t cnt = 0;+ for( int i=0; i<m_data.cpuDataCount; i++ )+ {+ cnt += m_data.cpuData[i].cs.size();+ }+ return cnt;+}++#ifndef TRACY_NO_STATISTICS+uint64_t Worker::GetChildSamplesCountFull() const+{+ uint64_t cnt = 0;+ for( auto& v : m_data.childSamples )+ {+ cnt += v.second.size();+ }+ return cnt;+}++uint64_t Worker::GetContextSwitchSampleCount() const+{+ uint64_t cnt = 0;+ for( auto& v : m_data.threads )+ {+ cnt += v->ctxSwitchSamples.size();+ }+ return cnt;+}+#endif++uint64_t Worker::GetPidFromTid( uint64_t tid ) const+{+ auto it = m_data.tidToPid.find( tid );+ if( it == m_data.tidToPid.end() ) return 0;+ return it->second;+}++const ContextSwitch* const Worker::GetContextSwitchDataImpl( uint64_t thread )+{+ auto it = m_data.ctxSwitch.find( thread );+ if( it != m_data.ctxSwitch.end() )+ {+ m_data.ctxSwitchLast.first = thread;+ m_data.ctxSwitchLast.second = it->second;+ return it->second;+ }+ else+ {+ return nullptr;+ }+}++size_t Worker::GetFullFrameCount( const FrameData& fd ) const+{+ const auto sz = fd.frames.size();+ assert( sz != 0 );++ if( fd.continuous )+ {+ if( IsConnected() )+ {+ return sz - 1;+ }+ else+ {+ return sz;+ }+ }+ else+ {+ const auto& last = fd.frames.back();+ if( last.end >= 0 )+ {+ return sz;+ }+ else+ {+ return sz - 1;+ }+ }+}++bool Worker::AreFramesUsed() const+{+ if( m_data.frames.Data().size() > 1 ) return true;+ return m_data.framesBase->frames.size() > 2;+}++int64_t Worker::GetFirstTime() const+{+ if( !m_onDemand ) return 0;+ assert( m_data.framesBase->frames.size() >= 2 );+ return m_data.framesBase->frames[2].start;+}++int64_t Worker::GetFrameTime( const FrameData& fd, size_t idx ) const+{+ if( fd.continuous )+ {+ if( idx < fd.frames.size() - 1 )+ {+ return fd.frames[idx+1].start - fd.frames[idx].start;+ }+ else+ {+ assert( m_data.lastTime != 0 );+ return m_data.lastTime - fd.frames.back().start;+ }+ }+ else+ {+ const auto& frame = fd.frames[idx];+ if( frame.end >= 0 )+ {+ return frame.end - frame.start;+ }+ else+ {+ return m_data.lastTime - fd.frames.back().start;+ }+ }+}++int64_t Worker::GetFrameBegin( const FrameData& fd, size_t idx ) const+{+ assert( idx < fd.frames.size() );+ return fd.frames[idx].start;+}++int64_t Worker::GetFrameEnd( const FrameData& fd, size_t idx ) const+{+ if( fd.continuous )+ {+ if( idx < fd.frames.size() - 1 )+ {+ return fd.frames[idx+1].start;+ }+ else+ {+ return m_data.lastTime;+ }+ }+ else+ {+ if( idx < fd.frames.size() && fd.frames[idx].end >= 0 )+ {+ return fd.frames[idx].end;+ }+ else+ {+ return m_data.lastTime;+ }+ }+}++const FrameImage* Worker::GetFrameImage( const FrameData& fd, size_t idx ) const+{+ assert( idx < fd.frames.size() );+ const auto& v = fd.frames[idx].frameImage;+ if( v < 0 ) return nullptr;+ return m_data.frameImage[v];+}++std::pair<int, int> Worker::GetFrameRange( const FrameData& fd, int64_t from, int64_t to )+{+ auto zitbegin = std::lower_bound( fd.frames.begin(), fd.frames.end(), from, [] ( const auto& lhs, const auto& rhs ) { return lhs.start < rhs; } );+ if( zitbegin == fd.frames.end() ) zitbegin--;++ const auto zitend = std::lower_bound( zitbegin, fd.frames.end(), to, [] ( const auto& lhs, const auto& rhs ) { return lhs.start < rhs; } );++ int zbegin = std::distance( fd.frames.begin(), zitbegin );+ if( zbegin > 0 && zitbegin->start != from ) --zbegin;+ const int zend = std::distance( fd.frames.begin(), zitend );++ return std::make_pair( zbegin, zend );+}++const CallstackFrameData* Worker::GetCallstackFrame( const CallstackFrameId& ptr ) const+{+ assert( ptr.custom == 0 );+ auto it = m_data.callstackFrameMap.find( ptr );+ if( it == m_data.callstackFrameMap.end() )+ {+ return nullptr;+ }+ else+ {+ return it->second;+ }+}++#ifndef TRACY_NO_STATISTICS+const CallstackFrameData* Worker::GetParentCallstackFrame( const CallstackFrameId& ptr ) const+{+ assert( ptr.custom == 1 );+ auto it = m_data.parentCallstackFrameMap.find( ptr );+ if( it == m_data.parentCallstackFrameMap.end() )+ {+ return nullptr;+ }+ else+ {+ return it->second;+ }+}++const Vector<SampleDataRange>* Worker::GetSamplesForSymbol( uint64_t symAddr ) const+{+ assert( m_data.symbolSamplesReady );+ auto it = m_data.symbolSamples.find( symAddr );+ if( it == m_data.symbolSamples.end() ) return nullptr;+ return &it->second;+}++const Vector<ChildSample>* Worker::GetChildSamples( uint64_t addr ) const+{+ assert( m_data.symbolSamplesReady );+ auto it = m_data.childSamples.find( addr );+ if( it == m_data.childSamples.end() ) return nullptr;+ return &it->second;+}+#endif++const SymbolData* Worker::GetSymbolData( uint64_t sym ) const+{+ auto it = m_data.symbolMap.find( sym );+ if( it == m_data.symbolMap.end() )+ {+ return nullptr;+ }+ else+ {+ return &it->second;+ }+}++bool Worker::HasSymbolCode( uint64_t sym ) const+{+ return m_data.symbolCode.find( sym ) != m_data.symbolCode.end();+}++const char* Worker::GetSymbolCode( uint64_t sym, uint32_t& len ) const+{+ auto it = m_data.symbolCode.find( sym );+ if( it == m_data.symbolCode.end() ) return nullptr;+ len = it->second.len;+ return it->second.data;+}++uint64_t Worker::GetSymbolForAddress( uint64_t address )+{+ DoPostponedSymbols();+ auto it = std::lower_bound( m_data.symbolLoc.begin(), m_data.symbolLoc.end(), address, [] ( const auto& l, const auto& r ) { return l.addr + l.len < r; } );+ if( it == m_data.symbolLoc.end() || address < it->addr ) return 0;+ return it->addr;+}++uint64_t Worker::GetSymbolForAddress( uint64_t address, uint32_t& offset )+{+ DoPostponedSymbols();+ auto it = std::lower_bound( m_data.symbolLoc.begin(), m_data.symbolLoc.end(), address, [] ( const auto& l, const auto& r ) { return l.addr + l.len < r; } );+ if( it == m_data.symbolLoc.end() || address < it->addr ) return 0;+ offset = address - it->addr;+ return it->addr;+}++uint64_t Worker::GetInlineSymbolForAddress( uint64_t address ) const+{+ auto it = m_data.codeSymbolMap.find( address );+ if( it == m_data.codeSymbolMap.end() ) return 0;+ return it->second;+}++StringIdx Worker::GetLocationForAddress( uint64_t address, uint32_t& line ) const+{+ auto frame = GetCallstackFrame( PackPointer( address ) );+ if( !frame )+ {+ line = 0;+ return StringIdx();+ }+ else+ {+ auto subFrame = frame->data[0];+ line = subFrame.line;+ return subFrame.file;+ }+}++const uint64_t* Worker::GetInlineSymbolList( uint64_t sym, uint32_t len )+{+ DoPostponedInlineSymbols();+ auto it = std::lower_bound( m_data.symbolLocInline.begin(), m_data.symbolLocInline.end(), sym );+ if( it == m_data.symbolLocInline.end() ) return nullptr;+ if( *it >= sym + len ) return nullptr;+ return it;+}++int64_t Worker::GetZoneEndImpl( const ZoneEvent& ev )+{+ assert( !ev.IsEndValid() );+ auto ptr = &ev;+ for(;;)+ {+ if( !ptr->HasChildren() ) return ptr->Start();+ auto& children = GetZoneChildren( ptr->Child() );+ if( children.is_magic() )+ {+ auto& c = *(Vector<ZoneEvent>*)&children;+ ptr = &c.back();+ }+ else+ {+ ptr = children.back();+ }+ if( ptr->IsEndValid() ) return ptr->End();+ }+}++int64_t Worker::GetZoneEndImpl( const GpuEvent& ev )+{+ assert( ev.GpuEnd() < 0 );+ auto ptr = &ev;+ for(;;)+ {+ if( ptr->Child() < 0 ) return ptr->GpuStart() >= 0 ? ptr->GpuStart() : m_data.lastTime;+ auto& children = GetGpuChildren( ptr->Child() );+ if( children.is_magic() )+ {+ auto& c = *(Vector<GpuEvent>*)&children;+ ptr = &c.back();+ }+ else+ {+ ptr = children.back();+ }+ if( ptr->GpuEnd() >= 0 ) return ptr->GpuEnd();+ }+}++uint32_t Worker::FindStringIdx( const char* str ) const+{+ if( !str ) return 0;+ charutil::StringKey key = { str, strlen( str ) };+ auto sit = m_data.stringMap.find( key );+ if( sit == m_data.stringMap.end() )+ {+ return 0;+ }+ else+ {+ return sit->second;+ }+}++const char* Worker::GetString( uint64_t ptr ) const+{+ const auto it = m_data.strings.find( ptr );+ if( it == m_data.strings.end() || it->second == nullptr )+ {+ return "???";+ }+ else+ {+ return it->second;+ }+}++const char* Worker::GetString( const StringRef& ref ) const+{+ if( ref.isidx )+ {+ assert( ref.active );+ return m_data.stringData[ref.str];+ }+ else+ {+ if( ref.active )+ {+ return GetString( ref.str );+ }+ else+ {+ return "???";+ }+ }+}++const char* Worker::GetString( const StringIdx& idx ) const+{+ assert( idx.Active() );+ return m_data.stringData[idx.Idx()];+}++static const char* BadExternalThreadNames[] = {+ "ntdll.dll",+ "???",+ nullptr+};++const char* Worker::GetThreadName( uint64_t id ) const+{+ const auto it = m_data.threadNames.find( id );+ if( it == m_data.threadNames.end() )+ {+ const auto eit = m_data.externalNames.find( id );+ if( eit == m_data.externalNames.end() )+ {+ return "???";+ }+ else+ {+ return eit->second.second;+ }+ }+ else+ {+ // Client should send additional information about thread name, to make this check unnecessary+ const auto txt = it->second;+ if( txt[0] >= '0' && txt[0] <= '9' && (uint64_t)atoi( txt ) == id )+ {+ const auto eit = m_data.externalNames.find( id );+ if( eit != m_data.externalNames.end() )+ {+ const char* ext = eit->second.second;+ const char** ptr = BadExternalThreadNames;+ while( *ptr )+ {+ if( strcmp( *ptr, ext ) == 0 ) return txt;+ ptr++;+ }+ return ext;+ }+ }+ return txt;+ }+}++bool Worker::IsThreadLocal( uint64_t id )+{+ auto td = RetrieveThread( id );+ return td && ( td->count > 0 || !td->samples.empty() );+}++bool Worker::IsThreadFiber( uint64_t id )+{+ auto td = RetrieveThread( id );+ return td && ( td->isFiber );+}++const SourceLocation& Worker::GetSourceLocation( int16_t srcloc ) const+{+ if( srcloc < 0 )+ {+ return *m_data.sourceLocationPayload[-srcloc-1];+ }+ else if( srcloc != std::numeric_limits<int16_t>::max() )+ {+ const auto it = m_data.sourceLocation.find( m_data.sourceLocationExpand[srcloc] );+ assert( it != m_data.sourceLocation.end() );+ return it->second;+ }+ else+ {+ static const SourceLocation emptySourceLoc = {};+ return emptySourceLoc;+ }+}++std::pair<const char*, const char*> Worker::GetExternalName( uint64_t id ) const+{+ const auto it = m_data.externalNames.find( id );+ if( it == m_data.externalNames.end() )+ {+ return std::make_pair( "???", "???" );+ }+ else+ {+ return it->second;+ }+}++const char* Worker::GetZoneName( const SourceLocation& srcloc ) const+{+ if( srcloc.name.active )+ {+ return GetString( srcloc.name );+ }+ else+ {+ return GetString( srcloc.function );+ }+}++const char* Worker::GetZoneName( const ZoneEvent& ev ) const+{+ auto& srcloc = GetSourceLocation( ev.SrcLoc() );+ return GetZoneName( ev, srcloc );+}++const char* Worker::GetZoneName( const ZoneEvent& ev, const SourceLocation& srcloc ) const+{+ if( HasZoneExtra( ev ) && GetZoneExtra( ev ).name.Active() )+ {+ return GetString( GetZoneExtra( ev ).name );+ }+ else if( srcloc.name.active )+ {+ return GetString( srcloc.name );+ }+ else+ {+ return GetString( srcloc.function );+ }+}++const char* Worker::GetZoneName( const GpuEvent& ev ) const+{+ auto& srcloc = GetSourceLocation( ev.SrcLoc() );+ return GetZoneName( srcloc );+}++static bool strstr_nocase( const char* l, const char* r )+{+ const auto lsz = strlen( l );+ const auto rsz = strlen( r );+ auto ll = (char*)alloca( lsz + 1 );+ auto rl = (char*)alloca( rsz + 1 );+ for( size_t i=0; i<lsz; i++ )+ {+ ll[i] = tolower( l[i] );+ }+ ll[lsz] = '\0';+ for( size_t i=0; i<rsz; i++ )+ {+ rl[i] = tolower( r[i] );+ }+ rl[rsz] = '\0';+ return strstr( ll, rl ) != nullptr;+}++std::vector<int16_t> Worker::GetMatchingSourceLocation( const char* query, bool ignoreCase ) const+{+ std::vector<int16_t> match;++ const auto sz = m_data.sourceLocationExpand.size();+ for( size_t i=1; i<sz; i++ )+ {+ const auto it = m_data.sourceLocation.find( m_data.sourceLocationExpand[i] );+ assert( it != m_data.sourceLocation.end() );+ const auto& srcloc = it->second;+ const auto str = GetString( srcloc.name.active ? srcloc.name : srcloc.function );+ bool found = false;+ if( ignoreCase )+ {+ found = strstr_nocase( str, query );+ }+ else+ {+ found = strstr( str, query ) != nullptr;+ }+ if( found )+ {+ match.push_back( (int16_t)i );+ }+ }++ for( auto& srcloc : m_data.sourceLocationPayload )+ {+ const auto str = GetString( srcloc->name.active ? srcloc->name : srcloc->function );+ bool found = false;+ if( ignoreCase )+ {+ found = strstr_nocase( str, query );+ }+ else+ {+ found = strstr( str, query ) != nullptr;+ }+ if( found )+ {+ auto it = m_data.sourceLocationPayloadMap.find( (const SourceLocation*)srcloc );+ assert( it != m_data.sourceLocationPayloadMap.end() );+ match.push_back( -int16_t( it->second + 1 ) );+ }+ }++ return match;+}++#ifndef TRACY_NO_STATISTICS+Worker::SourceLocationZones& Worker::GetZonesForSourceLocation( int16_t srcloc )+{+ assert( AreSourceLocationZonesReady() );+ static SourceLocationZones empty;+ auto it = m_data.sourceLocationZones.find( srcloc );+ return it != m_data.sourceLocationZones.end() ? it->second : empty;+}++const Worker::SourceLocationZones& Worker::GetZonesForSourceLocation( int16_t srcloc ) const+{+ assert( AreSourceLocationZonesReady() );+ static const SourceLocationZones empty;+ auto it = m_data.sourceLocationZones.find( srcloc );+ return it != m_data.sourceLocationZones.end() ? it->second : empty;+}++const SymbolStats* Worker::GetSymbolStats( uint64_t symAddr ) const+{+ assert( AreCallstackSamplesReady() );+ auto it = m_data.symbolStats.find( symAddr );+ if( it == m_data.symbolStats.end() )+ {+ return nullptr;+ }+ else+ {+ return &it->second;+ }+}++const unordered_flat_map<CallstackFrameId, uint32_t, Worker::CallstackFrameIdHash, Worker::CallstackFrameIdCompare>* Worker::GetSymbolInstructionPointers( uint64_t symAddr ) const+{+ assert( AreCallstackSamplesReady() );+ auto it = m_data.instructionPointersMap.find( symAddr );+ if( it == m_data.instructionPointersMap.end() )+ {+ return nullptr;+ }+ else+ {+ return &it->second;+ }+}+#endif++void Worker::Network()+{+ auto ShouldExit = [this] { return m_shutdown.load( std::memory_order_relaxed ); };+ auto lz4buf = std::unique_ptr<char[]>( new char[LZ4Size] );++ for(;;)+ {+ {+ std::unique_lock<std::mutex> lock( m_netWriteLock );+ m_netWriteCv.wait( lock, [this] { return m_netWriteCnt > 0 || m_shutdown.load( std::memory_order_relaxed ); } );+ if( m_shutdown.load( std::memory_order_relaxed ) ) goto close;+ m_netWriteCnt--;+ }++ auto buf = m_buffer + m_bufferOffset;+ lz4sz_t lz4sz;+ if( !m_sock.Read( &lz4sz, sizeof( lz4sz ), 10, ShouldExit ) ) goto close;+ if( !m_sock.Read( lz4buf.get(), lz4sz, 10, ShouldExit ) ) goto close;+ auto bb = m_bytes.load( std::memory_order_relaxed );+ m_bytes.store( bb + sizeof( lz4sz ) + lz4sz, std::memory_order_relaxed );++ auto sz = LZ4_decompress_safe_continue( (LZ4_streamDecode_t*)m_stream, lz4buf.get(), buf, lz4sz, TargetFrameSize );+ assert( sz >= 0 );+ bb = m_decBytes.load( std::memory_order_relaxed );+ m_decBytes.store( bb + sz, std::memory_order_relaxed );++ {+ std::lock_guard<std::mutex> lock( m_netReadLock );+ m_netRead.push_back( NetBuffer { m_bufferOffset, sz } );+ m_netReadCv.notify_one();+ }++ m_bufferOffset += sz;+ if( m_bufferOffset > TargetFrameSize * 2 ) m_bufferOffset = 0;+ }++close:+ std::lock_guard<std::mutex> lock( m_netReadLock );+ m_netRead.push_back( NetBuffer { -1 } );+ m_netReadCv.notify_one();+}++void Worker::Exec()+{+ auto ShouldExit = [this] { return m_shutdown.load( std::memory_order_relaxed ); };++ for(;;)+ {+ if( m_shutdown.load( std::memory_order_relaxed ) ) { m_netWriteCv.notify_one(); return; };+ if( m_sock.Connect( m_addr.c_str(), m_port ) ) break;+ std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );+ }++ std::chrono::time_point<std::chrono::high_resolution_clock> t0;++ m_sock.Send( HandshakeShibboleth, HandshakeShibbolethSize );+ uint32_t protocolVersion = ProtocolVersion;+ m_sock.Send( &protocolVersion, sizeof( protocolVersion ) );+ HandshakeStatus handshake;+ if( !m_sock.Read( &handshake, sizeof( handshake ), 10, ShouldExit ) )+ {+ m_handshake.store( HandshakeDropped, std::memory_order_relaxed );+ goto close;+ }+ m_handshake.store( handshake, std::memory_order_relaxed );+ switch( handshake )+ {+ case HandshakeWelcome:+ break;+ case HandshakeProtocolMismatch:+ case HandshakeNotAvailable:+ default:+ goto close;+ }++ m_data.framesBase = m_data.frames.Retrieve( 0, [this] ( uint64_t name ) {+ auto fd = m_slab.AllocInit<FrameData>();+ fd->name = name;+ fd->continuous = 1;+ return fd;+ }, [this] ( uint64_t name ) {+ assert( name == 0 );+ char tmp[6] = "Frame";+ HandleFrameName( name, tmp, 5 );+ } );++ {+ WelcomeMessage welcome;+ if( !m_sock.Read( &welcome, sizeof( welcome ), 10, ShouldExit ) )+ {+ m_handshake.store( HandshakeDropped, std::memory_order_relaxed );+ goto close;+ }+ m_timerMul = welcome.timerMul;+ m_data.baseTime = welcome.initBegin;+ const auto initEnd = TscTime( welcome.initEnd );+ m_data.framesBase->frames.push_back( FrameEvent{ 0, -1, -1 } );+ m_data.framesBase->frames.push_back( FrameEvent{ initEnd, -1, -1 } );+ m_data.lastTime = initEnd;+ m_delay = TscPeriod( welcome.delay );+ m_resolution = TscPeriod( welcome.resolution );+ m_pid = welcome.pid;+ m_samplingPeriod = welcome.samplingPeriod;+ m_onDemand = welcome.flags & WelcomeFlag::OnDemand;+ m_captureProgram = welcome.programName;+ m_captureTime = welcome.epoch;+ m_executableTime = welcome.exectime;+ m_ignoreMemFreeFaults = ( welcome.flags & WelcomeFlag::OnDemand ) || ( welcome.flags & WelcomeFlag::IsApple );+ m_ignoreFrameEndFaults = welcome.flags & WelcomeFlag::OnDemand;+ m_data.cpuArch = (CpuArchitecture)welcome.cpuArch;+ m_codeTransfer = welcome.flags & WelcomeFlag::CodeTransfer;+ m_combineSamples = welcome.flags & WelcomeFlag::CombineSamples;+ m_identifySamples = welcome.flags & WelcomeFlag::IdentifySamples;+ m_data.cpuId = welcome.cpuId;+ memcpy( m_data.cpuManufacturer, welcome.cpuManufacturer, 12 );+ m_data.cpuManufacturer[12] = '\0';++ char dtmp[64];+ time_t date = welcome.epoch;+ auto lt = localtime( &date );+ strftime( dtmp, 64, "%F %T", lt );+ char tmp[1024];+ sprintf( tmp, "%s @ %s", welcome.programName, dtmp );+ m_captureName = tmp;++ m_hostInfo = welcome.hostInfo;++ if( m_onDemand )+ {+ OnDemandPayloadMessage onDemand;+ if( !m_sock.Read( &onDemand, sizeof( onDemand ), 10, ShouldExit ) )+ {+ m_handshake.store( HandshakeDropped, std::memory_order_relaxed );+ goto close;+ }+ m_data.frameOffset = onDemand.frames;+ m_data.framesBase->frames.push_back( FrameEvent{ TscTime( onDemand.currentTime ), -1, -1 } );+ }+ }++ m_serverQuerySpaceBase = m_serverQuerySpaceLeft = std::min( ( m_sock.GetSendBufSize() / ServerQueryPacketSize ), 8*1024 ) - 4; // leave space for terminate request+ m_hasData.store( true, std::memory_order_release );++ LZ4_setStreamDecode( (LZ4_streamDecode_t*)m_stream, nullptr, 0 );+ m_connected.store( true, std::memory_order_relaxed );+ {+ std::lock_guard<std::mutex> lock( m_netWriteLock );+ m_netWriteCnt = 2;+ m_netWriteCv.notify_one();+ }++ t0 = std::chrono::high_resolution_clock::now();++ for(;;)+ {+ if( m_shutdown.load( std::memory_order_relaxed ) || ( m_memoryLimit > 0 && memUsage.load( std::memory_order_relaxed ) > m_memoryLimit ) )+ {+ QueryTerminate();+ goto close;+ }++ NetBuffer netbuf;+ {+ std::unique_lock<std::mutex> lock( m_netReadLock );+ m_netReadCv.wait( lock, [this] { return !m_netRead.empty(); } );+ netbuf = m_netRead.front();+ m_netRead.erase( m_netRead.begin() );+ }+ if( netbuf.bufferOffset < 0 ) goto close;++ const char* ptr = m_buffer + netbuf.bufferOffset;+ const char* end = ptr + netbuf.size;++ {+ std::lock_guard<std::mutex> lock( m_data.lock );+ while( ptr < end )+ {+ auto ev = (const QueueItem*)ptr;+ if( !DispatchProcess( *ev, ptr ) )+ {+ if( m_failure != Failure::None ) HandleFailure( ptr, end );+ QueryTerminate();+ goto close;+ }+ }++ {+ std::lock_guard<std::mutex> lock( m_netWriteLock );+ m_netWriteCnt++;+ m_netWriteCv.notify_one();+ }++ if( m_serverQuerySpaceLeft > 0 && !m_serverQueryQueuePrio.empty() )+ {+ const auto toSend = std::min( m_serverQuerySpaceLeft, m_serverQueryQueuePrio.size() );+ m_sock.Send( m_serverQueryQueuePrio.data(), toSend * ServerQueryPacketSize );+ m_serverQuerySpaceLeft -= toSend;+ if( toSend == m_serverQueryQueuePrio.size() )+ {+ m_serverQueryQueuePrio.clear();+ }+ else+ {+ m_serverQueryQueuePrio.erase( m_serverQueryQueuePrio.begin(), m_serverQueryQueuePrio.begin() + toSend );+ }+ }+ if( m_serverQuerySpaceLeft > 0 && !m_serverQueryQueue.empty() )+ {+ const auto toSend = std::min( m_serverQuerySpaceLeft, m_serverQueryQueue.size() );+ m_sock.Send( m_serverQueryQueue.data(), toSend * ServerQueryPacketSize );+ m_serverQuerySpaceLeft -= toSend;+ if( toSend == m_serverQueryQueue.size() )+ {+ m_serverQueryQueue.clear();+ }+ else+ {+ m_serverQueryQueue.erase( m_serverQueryQueue.begin(), m_serverQueryQueue.begin() + toSend );+ }+ }+ }++ auto t1 = std::chrono::high_resolution_clock::now();+ auto td = std::chrono::duration_cast<std::chrono::milliseconds>( t1 - t0 ).count();+ enum { MbpsUpdateTime = 200 };+ if( td > MbpsUpdateTime )+ {+ UpdateMbps( td );+ t0 = t1;+ }++ if( m_terminate )+ {+ if( m_pendingStrings != 0 || m_pendingThreads != 0 || m_pendingSourceLocation != 0 || m_pendingCallstackFrames != 0 ||+ m_data.plots.IsPending() || m_pendingCallstackId != 0 || m_pendingExternalNames != 0 ||+ m_pendingCallstackSubframes != 0 || m_pendingFrameImageData.image != nullptr || !m_pendingSymbols.empty() ||+ m_pendingSymbolCode != 0 || !m_serverQueryQueue.empty() || !m_serverQueryQueuePrio.empty() ||+ m_pendingSourceLocationPayload != 0 || m_pendingSingleString.ptr != nullptr || m_pendingSecondString.ptr != nullptr ||+ !m_sourceCodeQuery.empty() || m_pendingFibers != 0 )+ {+ continue;+ }+ if( !m_crashed && !m_disconnect )+ {+ bool done = true;+ for( auto& v : m_data.threads )+ {+ if( !v->stack.empty() )+ {+ done = false;+ break;+ }+ }+ if( !done ) continue;+ }+ QueryTerminate();+ UpdateMbps( 0 );+ break;+ }+ }++close:+ Shutdown();+ m_netWriteCv.notify_one();+ m_sock.Close();+ m_connected.store( false, std::memory_order_relaxed );+}++void Worker::UpdateMbps( int64_t td )+{+ const auto bytes = m_bytes.exchange( 0, std::memory_order_relaxed );+ const auto decBytes = m_decBytes.exchange( 0, std::memory_order_relaxed );+ std::lock_guard<std::shared_mutex> lock( m_mbpsData.lock );+ if( td != 0 )+ {+ m_mbpsData.mbps.erase( m_mbpsData.mbps.begin() );+ m_mbpsData.mbps.emplace_back( bytes / ( td * 125.f ) );+ }+ m_mbpsData.compRatio = decBytes == 0 ? 1 : float( bytes ) / decBytes;+ m_mbpsData.queue = m_serverQueryQueue.size() + m_serverQueryQueuePrio.size();+ m_mbpsData.transferred += bytes;+}++bool Worker::IsFailureThreadStringRetrieved()+{+ const auto name = GetThreadName( m_failureData.thread );+ return strcmp( name, "???" ) != 0;+}++bool Worker::IsCallstackRetrieved( uint32_t callstack )+{+ auto& cs = GetCallstack( callstack );+ for( auto& v : cs )+ {+ auto frameData = GetCallstackFrame( v );+ if( !frameData ) return false;+ }+ return true;+}++bool Worker::IsSourceLocationRetrieved( int16_t srcloc )+{+ auto& sl = GetSourceLocation( srcloc );+ auto func = GetString( sl.function );+ auto file = GetString( sl.file );+ return strcmp( func, "???" ) != 0 && strcmp( file, "???" ) != 0;+}++bool Worker::HasAllFailureData()+{+ if( m_failureData.thread != 0 && !IsFailureThreadStringRetrieved() ) return false;+ if( m_failureData.srcloc != 0 && !IsSourceLocationRetrieved( m_failureData.srcloc ) ) return false;+ if( m_failureData.callstack != 0 && !IsCallstackRetrieved( m_failureData.callstack ) ) return false;+ return true;+}++void Worker::HandleFailure( const char* ptr, const char* end )+{+ if( HasAllFailureData() ) return;+ for(;;)+ {+ while( ptr < end )+ {+ auto ev = (const QueueItem*)ptr;+ DispatchFailure( *ev, ptr );+ }+ if( HasAllFailureData() ) return;++ {+ std::lock_guard<std::mutex> lock( m_netWriteLock );+ m_netWriteCnt++;+ m_netWriteCv.notify_one();+ }++ if( m_serverQuerySpaceLeft > 0 && !m_serverQueryQueuePrio.empty() )+ {+ const auto toSend = std::min( m_serverQuerySpaceLeft, m_serverQueryQueuePrio.size() );+ m_sock.Send( m_serverQueryQueuePrio.data(), toSend * ServerQueryPacketSize );+ m_serverQuerySpaceLeft -= toSend;+ if( toSend == m_serverQueryQueuePrio.size() )+ {+ m_serverQueryQueuePrio.clear();+ }+ else+ {+ m_serverQueryQueuePrio.erase( m_serverQueryQueuePrio.begin(), m_serverQueryQueuePrio.begin() + toSend );+ }+ }+ if( m_serverQuerySpaceLeft > 0 && !m_serverQueryQueue.empty() )+ {+ const auto toSend = std::min( m_serverQuerySpaceLeft, m_serverQueryQueue.size() );+ m_sock.Send( m_serverQueryQueue.data(), toSend * ServerQueryPacketSize );+ m_serverQuerySpaceLeft -= toSend;+ if( toSend == m_serverQueryQueue.size() )+ {+ m_serverQueryQueue.clear();+ }+ else+ {+ m_serverQueryQueue.erase( m_serverQueryQueue.begin(), m_serverQueryQueue.begin() + toSend );+ }+ }++ if( m_shutdown.load( std::memory_order_relaxed ) ) return;++ NetBuffer netbuf;+ {+ std::unique_lock<std::mutex> lock( m_netReadLock );+ m_netReadCv.wait( lock, [this] { return !m_netRead.empty(); } );+ netbuf = m_netRead.front();+ m_netRead.erase( m_netRead.begin() );+ }+ if( netbuf.bufferOffset < 0 ) return;++ ptr = m_buffer + netbuf.bufferOffset;+ end = ptr + netbuf.size;+ }+}++void Worker::DispatchFailure( const QueueItem& ev, const char*& ptr )+{+ if( ev.hdr.idx >= (int)QueueType::StringData )+ {+ ptr += sizeof( QueueHeader ) + sizeof( QueueStringTransfer );+ if( ev.hdr.type == QueueType::FrameImageData ||+ ev.hdr.type == QueueType::SymbolCode ||+ ev.hdr.type == QueueType::SourceCode )+ {+ if( ev.hdr.type == QueueType::SymbolCode || ev.hdr.type == QueueType::SourceCode )+ {+ m_serverQuerySpaceLeft++;+ }+ uint32_t sz;+ memcpy( &sz, ptr, sizeof( sz ) );+ ptr += sizeof( sz ) + sz;+ }+ else+ {+ uint16_t sz;+ memcpy( &sz, ptr, sizeof( sz ) );+ ptr += sizeof( sz );+ switch( ev.hdr.type )+ {+ case QueueType::StringData:+ AddString( ev.stringTransfer.ptr, ptr, sz );+ m_serverQuerySpaceLeft++;+ break;+ case QueueType::ThreadName:+ AddThreadString( ev.stringTransfer.ptr, ptr, sz );+ m_serverQuerySpaceLeft++;+ break;+ case QueueType::FiberName:+ AddFiberName( ev.stringTransfer.ptr, ptr, sz );+ m_serverQuerySpaceLeft++;+ break;+ case QueueType::PlotName:+ case QueueType::FrameName:+ case QueueType::ExternalName:+ m_serverQuerySpaceLeft++;+ break;+ default:+ break;+ }+ ptr += sz;+ }+ }+ else+ {+ uint16_t sz;+ switch( ev.hdr.type )+ {+ case QueueType::SingleStringData:+ ptr += sizeof( QueueHeader );+ memcpy( &sz, ptr, sizeof( sz ) );+ ptr += sizeof( sz );+ AddSingleStringFailure( ptr, sz );+ ptr += sz;+ break;+ case QueueType::SecondStringData:+ ptr += sizeof( QueueHeader );+ memcpy( &sz, ptr, sizeof( sz ) );+ ptr += sizeof( sz );+ AddSecondString( ptr, sz );+ ptr += sz;+ break;+ default:+ ptr += QueueDataSize[ev.hdr.idx];+ switch( ev.hdr.type )+ {+ case QueueType::SourceLocation:+ AddSourceLocation( ev.srcloc );+ m_serverQuerySpaceLeft++;+ break;+ case QueueType::CallstackFrameSize:+ ProcessCallstackFrameSize( ev.callstackFrameSize );+ m_serverQuerySpaceLeft++;+ break;+ case QueueType::CallstackFrame:+ ProcessCallstackFrame( ev.callstackFrame, false );+ break;+ case QueueType::SymbolInformation:+ case QueueType::AckServerQueryNoop:+ case QueueType::AckSourceCodeNotAvailable:+ case QueueType::AckSymbolCodeNotAvailable:+ m_serverQuerySpaceLeft++;+ break;+ default:+ break;+ }+ }+ }+}++void Worker::Query( ServerQuery type, uint64_t data, uint32_t extra )+{+ ServerQueryPacket query { type, data, extra };+ if( m_serverQuerySpaceLeft > 0 && m_serverQueryQueuePrio.empty() && m_serverQueryQueue.empty() )+ {+ m_serverQuerySpaceLeft--;+ m_sock.Send( &query, ServerQueryPacketSize );+ }+ else if( IsQueryPrio( type ) )+ {+ m_serverQueryQueuePrio.push_back( query );+ }+ else+ {+ m_serverQueryQueue.push_back( query );+ }+}++void Worker::QueryTerminate()+{+ ServerQueryPacket query { ServerQueryTerminate, 0, 0 };+ m_sock.Send( &query, ServerQueryPacketSize );+}++void Worker::QuerySourceFile( const char* fn, const char* image )+{+ if( image ) QueryDataTransfer( image, strlen( image ) + 1 );+ QueryDataTransfer( fn, strlen( fn ) + 1 );+ m_sourceCodeQuery.emplace( m_nextSourceCodeQuery, fn );+ Query( ServerQuerySourceCode, m_nextSourceCodeQuery );+ m_nextSourceCodeQuery++;+}++void Worker::QueryDataTransfer( const void* ptr, size_t size )+{+ Query( ServerQueryDataTransfer, size );+ auto data = (const char*)ptr;+ while( size > 0 )+ {+ uint64_t d8;+ uint32_t d4;+ if( size >= 12 )+ {+ memcpy( &d8, data, 8 );+ memcpy( &d4, data+8, 4 );+ data += 12;+ size -= 12;+ }+ else if( size > 8 )+ {+ memcpy( &d8, data, 8 );+ memset( &d4, 0, 4 );+ memcpy( &d4, data+8, size-8 );+ size = 0;+ }+ else+ {+ memset( &d8, 0, 8 );+ memset( &d4, 0, 4 );+ memcpy( &d8, data, size );+ size = 0;+ }+ Query( ServerQueryDataTransferPart, d8, d4 );+ }+}++bool Worker::DispatchProcess( const QueueItem& ev, const char*& ptr )+{+ if( ev.hdr.idx >= (int)QueueType::StringData )+ {+ ptr += sizeof( QueueHeader ) + sizeof( QueueStringTransfer );+ if( ev.hdr.type == QueueType::FrameImageData ||+ ev.hdr.type == QueueType::SymbolCode ||+ ev.hdr.type == QueueType::SourceCode )+ {+ uint32_t sz;+ memcpy( &sz, ptr, sizeof( sz ) );+ ptr += sizeof( sz );+ switch( ev.hdr.type )+ {+ case QueueType::FrameImageData:+ AddFrameImageData( ptr, sz );+ break;+ case QueueType::SymbolCode:+ AddSymbolCode( ev.stringTransfer.ptr, ptr, sz );+ m_serverQuerySpaceLeft++;+ break;+ case QueueType::SourceCode:+ AddSourceCode( (uint32_t)ev.stringTransfer.ptr, ptr, sz );+ m_serverQuerySpaceLeft++;+ break;+ default:+ assert( false );+ break;+ }+ ptr += sz;+ }+ else+ {+ uint16_t sz;+ memcpy( &sz, ptr, sizeof( sz ) );+ ptr += sizeof( sz );+ switch( ev.hdr.type )+ {+ case QueueType::StringData:+ AddString( ev.stringTransfer.ptr, ptr, sz );+ m_serverQuerySpaceLeft++;+ break;+ case QueueType::ThreadName:+ AddThreadString( ev.stringTransfer.ptr, ptr, sz );+ m_serverQuerySpaceLeft++;+ break;+ case QueueType::FiberName:+ AddFiberName( ev.stringTransfer.ptr, ptr, sz );+ m_serverQuerySpaceLeft++;+ break;+ case QueueType::PlotName:+ HandlePlotName( ev.stringTransfer.ptr, ptr, sz );+ m_serverQuerySpaceLeft++;+ break;+ case QueueType::SourceLocationPayload:+ AddSourceLocationPayload( ptr, sz );+ break;+ case QueueType::CallstackPayload:+ AddCallstackPayload( ptr, sz );+ break;+ case QueueType::FrameName:+ HandleFrameName( ev.stringTransfer.ptr, ptr, sz );+ m_serverQuerySpaceLeft++;+ break;+ case QueueType::CallstackAllocPayload:+ AddCallstackAllocPayload( ptr );+ break;+ case QueueType::ExternalName:+ AddExternalName( ev.stringTransfer.ptr, ptr, sz );+ m_serverQuerySpaceLeft++;+ break;+ case QueueType::ExternalThreadName:+ AddExternalThreadName( ev.stringTransfer.ptr, ptr, sz );+ break;+ default:+ assert( false );+ break;+ }+ ptr += sz;+ }+ return true;+ }+ else+ {+ uint16_t sz;+ switch( ev.hdr.type )+ {+ case QueueType::SingleStringData:+ ptr += sizeof( QueueHeader );+ memcpy( &sz, ptr, sizeof( sz ) );+ ptr += sizeof( sz );+ AddSingleString( ptr, sz );+ ptr += sz;+ return true;+ case QueueType::SecondStringData:+ ptr += sizeof( QueueHeader );+ memcpy( &sz, ptr, sizeof( sz ) );+ ptr += sizeof( sz );+ AddSecondString( ptr, sz );+ ptr += sz;+ return true;+ default:+ ptr += QueueDataSize[ev.hdr.idx];+ return Process( ev );+ }+ }+}++void Worker::CheckSourceLocation( uint64_t ptr )+{+ if( m_data.checkSrclocLast != ptr )+ {+ m_data.checkSrclocLast = ptr;+ if( m_data.sourceLocation.find( ptr ) == m_data.sourceLocation.end() )+ {+ NewSourceLocation( ptr );+ }+ }+}++void Worker::NewSourceLocation( uint64_t ptr )+{+ static const SourceLocation emptySourceLocation = {};++ if( m_data.sourceLocation.size() > std::numeric_limits<int16_t>::max() )+ {+ SourceLocationOverflowFailure();+ return;+ }++ m_data.sourceLocation.emplace( ptr, emptySourceLocation );+ m_pendingSourceLocation++;+ m_sourceLocationQueue.push_back( ptr );++ Query( ServerQuerySourceLocation, ptr );+}++int16_t Worker::ShrinkSourceLocationReal( uint64_t srcloc )+{+ auto it = m_sourceLocationShrink.find( srcloc );+ if( it != m_sourceLocationShrink.end() )+ {+ m_data.shrinkSrclocLast.first = srcloc;+ m_data.shrinkSrclocLast.second = it->second;+ return it->second;+ }+ else+ {+ return NewShrinkedSourceLocation( srcloc );+ }+}++int16_t Worker::NewShrinkedSourceLocation( uint64_t srcloc )+{+ assert( m_data.sourceLocationExpand.size() < std::numeric_limits<int16_t>::max() );+ if( ( m_data.sourceLocationExpand.size() + 1 ) == std::numeric_limits<int16_t>::max() )+ return std::numeric_limits<int16_t>::max();++ const auto sz = int16_t( m_data.sourceLocationExpand.size() );+ m_data.sourceLocationExpand.push_back( srcloc );+#ifndef TRACY_NO_STATISTICS+ auto res = m_data.sourceLocationZones.emplace( sz, SourceLocationZones() );+ m_data.srclocZonesLast.first = sz;+ m_data.srclocZonesLast.second = &res.first->second;+#else+ auto res = m_data.sourceLocationZonesCnt.emplace( sz, 0 );+ m_data.srclocCntLast.first = sz;+ m_data.srclocCntLast.second = &res.first->second;+#endif+ m_sourceLocationShrink.emplace( srcloc, sz );+ m_data.shrinkSrclocLast.first = srcloc;+ m_data.shrinkSrclocLast.second = sz;+ return sz;+}++void Worker::InsertMessageData( MessageData* msg )+{+ if( m_data.messages.empty() )+ {+ m_data.messages.push_back( msg );+ }+ else if( m_data.messages.back()->time < msg->time )+ {+ m_data.messages.push_back_non_empty( msg );+ }+ else+ {+ auto mit = std::lower_bound( m_data.messages.begin(), m_data.messages.end(), msg->time, [] ( const auto& lhs, const auto& rhs ) { return lhs->time < rhs; } );+ m_data.messages.insert( mit, msg );+ }++ auto td = GetCurrentThreadData();+ auto vec = &td->messages;+ if( vec->empty() )+ {+ vec->push_back( msg );+ }+ else if( vec->back()->time < msg->time )+ {+ vec->push_back_non_empty( msg );+ }+ else+ {+ auto tmit = std::lower_bound( vec->begin(), vec->end(), msg->time, [] ( const auto& lhs, const auto& rhs ) { return lhs->time < rhs; } );+ vec->insert( tmit, msg );+ }+}++ThreadData* Worker::NoticeThreadReal( uint64_t thread )+{+ auto it = m_threadMap.find( thread );+ if( it != m_threadMap.end() )+ {+ m_data.threadDataLast.first = thread;+ m_data.threadDataLast.second = it->second;+ return it->second;+ }+ else+ {+ CheckThreadString( thread );+ return NewThread( thread, false, 0 );+ }+}++ThreadData* Worker::RetrieveThreadReal( uint64_t thread )+{+ auto it = m_threadMap.find( thread );+ if( it != m_threadMap.end() )+ {+ m_data.threadDataLast.first = thread;+ m_data.threadDataLast.second = it->second;+ return it->second;+ }+ else+ {+ return nullptr;+ }+}++ThreadData* Worker::GetCurrentThreadData()+{+ auto td = m_threadCtxData;+ if( !td ) td = m_threadCtxData = NoticeThread( m_threadCtx );+ if( td->fiber ) td = td->fiber;+ return td;+}++#ifndef TRACY_NO_STATISTICS+Worker::SourceLocationZones* Worker::GetSourceLocationZonesReal( uint16_t srcloc )+{+ auto it = m_data.sourceLocationZones.find( srcloc );+ assert( it != m_data.sourceLocationZones.end() );+ m_data.srclocZonesLast.first = srcloc;+ m_data.srclocZonesLast.second = &it->second;+ return &it->second;+}++Worker::GpuSourceLocationZones* Worker::GetGpuSourceLocationZonesReal( uint16_t srcloc )+{+ auto it = m_data.gpuSourceLocationZones.find( srcloc );+ if( it == m_data.gpuSourceLocationZones.end() )+ {+ it = m_data.gpuSourceLocationZones.emplace( srcloc, GpuSourceLocationZones() ).first;+ }+ m_data.gpuZonesLast.first = srcloc;+ m_data.gpuZonesLast.second = &it->second;+ return &it->second;+}+#else+uint64_t* Worker::GetSourceLocationZonesCntReal( uint16_t srcloc )+{+ auto it = m_data.sourceLocationZonesCnt.find( srcloc );+ assert( it != m_data.sourceLocationZonesCnt.end() );+ m_data.srclocCntLast.first = srcloc;+ m_data.srclocCntLast.second = &it->second;+ return &it->second;+}++uint64_t* Worker::GetGpuSourceLocationZonesCntReal( uint16_t srcloc )+{+ auto it = m_data.gpuSourceLocationZonesCnt.find( srcloc );+ if( it == m_data.gpuSourceLocationZonesCnt.end() )+ {+ it = m_data.gpuSourceLocationZonesCnt.emplace( srcloc, 0 ).first;+ }+ m_data.gpuCntLast.first = srcloc;+ m_data.gpuCntLast.second = &it->second;+ return &it->second;+}+#endif++const ThreadData* Worker::GetThreadData( uint64_t tid ) const+{+ auto it = m_threadMap.find( tid );+ if( it == m_threadMap.end() ) return nullptr;+ return it->second;+}++const MemData& Worker::GetMemoryNamed( uint64_t name ) const+{+ auto it = m_data.memNameMap.find( name );+ assert( it != m_data.memNameMap.end() );+ return *it->second;+}++ThreadData* Worker::NewThread( uint64_t thread, bool fiber, int32_t groupHint )+{+ auto td = m_slab.AllocInit<ThreadData>();+ td->id = thread;+ td->count = 0;+ td->nextZoneId = 0;+#ifndef TRACY_NO_STATISTICS+ td->ghostIdx = 0;+#endif+ td->kernelSampleCnt = 0;+ td->pendingSample.time.Clear();+ td->isFiber = fiber;+ td->fiber = nullptr;+ td->stackCount = (uint8_t*)m_slab.AllocBig( sizeof( uint8_t ) * 64*1024 );+ memset( td->stackCount, 0, sizeof( uint8_t ) * 64*1024 );+ td->groupHint = groupHint;+ m_data.threads.push_back( td );+ m_threadMap.emplace( thread, td );+ m_data.threadDataLast.first = thread;+ m_data.threadDataLast.second = td;+ return td;+}++void Worker::NewZone( ZoneEvent* zone )+{+ m_data.zonesCnt++;++ auto td = GetCurrentThreadData();+ td->count++;+ td->IncStackCount( zone->SrcLoc() );+ const auto ssz = td->stack.size();+ if( ssz == 0 )+ {+ td->stack.push_back( zone );+ td->timeline.push_back( zone );+ }+ else+ {+ auto& back = td->stack.data()[ssz-1];+ if( !back->HasChildren() )+ {+ back->SetChild( int32_t( m_data.zoneChildren.size() ) );+ if( m_data.zoneVectorCache.empty() )+ {+ m_data.zoneChildren.push_back( Vector<short_ptr<ZoneEvent>>( zone ) );+ }+ else+ {+ Vector<short_ptr<ZoneEvent>> vze = std::move( m_data.zoneVectorCache.back_and_pop() );+ assert( !vze.empty() );+ vze.clear();+ vze.push_back_non_empty( zone );+ m_data.zoneChildren.push_back( std::move( vze ) );+ }+ }+ else+ {+ const auto backChild = back->Child();+ assert( !m_data.zoneChildren[backChild].empty() );+ m_data.zoneChildren[backChild].push_back_non_empty( zone );+ }+ td->stack.push_back_non_empty( zone );+ }++ td->zoneIdStack.push_back( td->nextZoneId );+ td->nextZoneId = 0;++#ifndef TRACY_NO_STATISTICS+ td->childTimeStack.push_back( 0 );+#endif+}++void Worker::InsertLockEvent( LockMap& lockmap, LockEvent* lev, uint64_t thread, int64_t time )+{+ if( m_data.lastTime < time ) m_data.lastTime = time;++ NoticeThread( thread );++ auto it = lockmap.threadMap.find( thread );+ if( it == lockmap.threadMap.end() )+ {+ assert( lockmap.threadList.size() < MaxLockThreads );+ it = lockmap.threadMap.emplace( thread, lockmap.threadList.size() ).first;+ lockmap.threadList.emplace_back( thread );+ }+ lev->thread = it->second;+ assert( lev->thread == it->second );+ auto& timeline = lockmap.timeline;+ if( timeline.empty() )+ {+ timeline.push_back( { lev } );+ UpdateLockCount( lockmap, timeline.size() - 1 );+ }+ else+ {+ assert( timeline.back().ptr->Time() <= time );+ timeline.push_back_non_empty( { lev } );+ UpdateLockCount( lockmap, timeline.size() - 1 );+ }++ auto& range = lockmap.range[it->second];+ if( range.start > time ) range.start = time;+ if( range.end < time ) range.end = time;+}++bool Worker::CheckString( uint64_t ptr )+{+ if( ptr == 0 ) return true;+ if( m_data.strings.find( ptr ) != m_data.strings.end() ) return true;++ m_data.strings.emplace( ptr, "???" );+ m_pendingStrings++;++ Query( ServerQueryString, ptr );+ return false;+}++void Worker::CheckThreadString( uint64_t id )+{+ if( m_data.threadNames.find( id ) != m_data.threadNames.end() ) return;++ m_data.threadNames.emplace( id, "???" );+ m_pendingThreads++;++ if( m_sock.IsValid() ) Query( ServerQueryThreadString, id );+}++void Worker::CheckFiberName( uint64_t id, uint64_t tid )+{+ if( m_data.threadNames.find( tid ) != m_data.threadNames.end() ) return;++ m_data.threadNames.emplace( tid, "???" );+ m_pendingFibers++;++ if( m_sock.IsValid() ) Query( ServerQueryFiberName, id );+}++void Worker::CheckExternalName( uint64_t id )+{+ if( m_data.externalNames.find( id ) != m_data.externalNames.end() ) return;++ m_data.externalNames.emplace( id, std::make_pair( "???", "???" ) );+ m_pendingExternalNames += 2;++ Query( ServerQueryExternalName, id );+}++void Worker::AddSourceLocation( const QueueSourceLocation& srcloc )+{+ assert( m_pendingSourceLocation > 0 );+ m_pendingSourceLocation--;++ const auto ptr = m_sourceLocationQueue.front();+ m_sourceLocationQueue.erase( m_sourceLocationQueue.begin() );++ auto it = m_data.sourceLocation.find( ptr );+ assert( it != m_data.sourceLocation.end() );+ CheckString( srcloc.name );+ if( CheckString( srcloc.file ) )+ {+ StringRef ref( StringRef::Ptr, srcloc.file );+ if( srcloc.file != 0 && m_checkedFileStrings.find( ref ) == m_checkedFileStrings.end() && m_pendingFileStrings.find( ref ) == m_pendingFileStrings.end() )+ {+ CacheSource( ref );+ }+ }+ else+ {+ StringRef ref( StringRef::Ptr, srcloc.file );+ assert( m_checkedFileStrings.find( ref ) == m_checkedFileStrings.end() );+ if( m_pendingFileStrings.find( ref ) == m_pendingFileStrings.end() )+ {+ m_pendingFileStrings.emplace( ref );+ }+ }+ CheckString( srcloc.function );+ const uint32_t color = ( srcloc.b << 16 ) | ( srcloc.g << 8 ) | srcloc.r;+ it->second = SourceLocation {{ srcloc.name == 0 ? StringRef() : StringRef( StringRef::Ptr, srcloc.name ), StringRef( StringRef::Ptr, srcloc.function ), StringRef( StringRef::Ptr, srcloc.file ), srcloc.line, color }};+}++void Worker::AddSourceLocationPayload( const char* data, size_t sz )+{+ const auto start = data;++ assert( m_pendingSourceLocationPayload == 0 );++ uint32_t color, line;+ memcpy( &color, data, 4 );+ memcpy( &line, data + 4, 4 );+ data += 8;+ auto end = data + strlen( data );++ const auto func = StoreString( data, end - data );+ end++;++ data = end;+ end = data + strlen( data );+ const auto source = StoreString( data, end - data );+ end++;++ const auto nsz = sz - ( end - start );++ color = ( ( color & 0x00FF0000 ) >> 16 ) |+ ( ( color & 0x0000FF00 ) ) |+ ( ( color & 0x000000FF ) << 16 );++ SourceLocation srcloc {{ nsz == 0 ? StringRef() : StringRef( StringRef::Idx, StoreString( end, nsz ).idx ), StringRef( StringRef::Idx, func.idx ), StringRef( StringRef::Idx, source.idx ), line, color }};+ auto it = m_data.sourceLocationPayloadMap.find( &srcloc );+ if( it == m_data.sourceLocationPayloadMap.end() )+ {+ auto slptr = m_slab.Alloc<SourceLocation>();+ memcpy( slptr, &srcloc, sizeof( srcloc ) );+ uint32_t idx = m_data.sourceLocationPayload.size();+ if( idx+1 > std::numeric_limits<int16_t>::max() )+ {+ SourceLocationOverflowFailure();+ return;+ }+ m_data.sourceLocationPayloadMap.emplace( slptr, idx );+ m_pendingSourceLocationPayload = -int16_t( idx + 1 );+ m_data.sourceLocationPayload.push_back( slptr );+ if( m_checkedFileStrings.find( srcloc.file ) == m_checkedFileStrings.end() )+ {+ CacheSource( srcloc.file );+ }+ const auto key = -int16_t( idx + 1 );+#ifndef TRACY_NO_STATISTICS+ auto res = m_data.sourceLocationZones.emplace( key, SourceLocationZones() );+ m_data.srclocZonesLast.first = key;+ m_data.srclocZonesLast.second = &res.first->second;+#else+ auto res = m_data.sourceLocationZonesCnt.emplace( key, 0 );+ m_data.srclocCntLast.first = key;+ m_data.srclocCntLast.second = &res.first->second;+#endif+ }+ else+ {+ m_pendingSourceLocationPayload = -int16_t( it->second + 1 );+ }+}++void Worker::AddString( uint64_t ptr, const char* str, size_t sz )+{+ assert( m_pendingStrings > 0 );+ m_pendingStrings--;+ auto it = m_data.strings.find( ptr );+ assert( it != m_data.strings.end() && strcmp( it->second, "???" ) == 0 );+ const auto sl = StoreString( str, sz );+ it->second = sl.ptr;++ StringRef ref( StringRef::Ptr, ptr );+ auto sit = m_pendingFileStrings.find( ref );+ if( sit != m_pendingFileStrings.end() )+ {+ m_pendingFileStrings.erase( sit );+ CacheSource( ref );+ }+}++void Worker::AddThreadString( uint64_t id, const char* str, size_t sz )+{+ assert( m_pendingThreads > 0 );+ m_pendingThreads--;+ auto it = m_data.threadNames.find( id );+ assert( it != m_data.threadNames.end() && strcmp( it->second, "???" ) == 0 );+ const auto sl = StoreString( str, sz );+ it->second = sl.ptr;+}++void Worker::AddFiberName( uint64_t id, const char* str, size_t sz )+{+ assert( m_pendingFibers > 0 );+ m_pendingFibers--;+ auto it = m_data.fiberToThreadMap.find( id );+ assert( it != m_data.fiberToThreadMap.end() );+ auto tit = m_data.threadNames.find( it->second );+ assert( tit != m_data.threadNames.end() && strcmp( tit->second, "???" ) == 0 );+ const auto sl = StoreString( str, sz );+ tit->second = sl.ptr;+}++void Worker::AddSingleString( const char* str, size_t sz )+{+ assert( m_pendingSingleString.ptr == nullptr );+ m_pendingSingleString = StoreString( str, sz );+}++void Worker::AddSingleStringFailure( const char* str, size_t sz )+{+ // During failure dispatch processing of most events is ignored, but string data+ // is still send. Just ignore anything that was already in the staging area.+ m_pendingSingleString = StoreString( str, sz );+}++void Worker::AddSecondString( const char* str, size_t sz )+{+ assert( m_pendingSecondString.ptr == nullptr );+ m_pendingSecondString = StoreString( str, sz );+}++void Worker::AddExternalName( uint64_t ptr, const char* str, size_t sz )+{+ assert( m_pendingExternalNames > 0 );+ m_pendingExternalNames--;+ auto it = m_data.externalNames.find( ptr );+ assert( it != m_data.externalNames.end() && strcmp( it->second.first, "???" ) == 0 );+ const auto sl = StoreString( str, sz );+ it->second.first = sl.ptr;+}++void Worker::AddExternalThreadName( uint64_t ptr, const char* str, size_t sz )+{+ assert( m_pendingExternalNames > 0 );+ m_pendingExternalNames--;+ auto it = m_data.externalNames.find( ptr );+ assert( it != m_data.externalNames.end() && strcmp( it->second.second, "???" ) == 0 );+ const auto sl = StoreString( str, sz );+ it->second.second = sl.ptr;+}++void Worker::AddFrameImageData( const char* data, size_t sz )+{+ assert( m_pendingFrameImageData.image == nullptr );+ assert( sz % 8 == 0 );+ // Input data buffer cannot be changed, as it is used as LZ4 dictionary.+ if( m_frameImageBufferSize < sz )+ {+ m_frameImageBufferSize = sz;+ delete[] m_frameImageBuffer;+ m_frameImageBuffer = new char[sz];+ }+ auto src = (uint8_t*)data;+ auto dst = (uint8_t*)m_frameImageBuffer;+ memcpy( dst, src, sz );+ m_texcomp.FixOrder( (char*)dst, sz/8 );+ m_texcomp.Rdo( (char*)dst, sz/8 );+ m_pendingFrameImageData.image = m_texcomp.Pack( m_frameImageBuffer, sz, m_pendingFrameImageData.csz, m_slab );+}++void Worker::AddSymbolCode( uint64_t ptr, const char* data, size_t sz )+{+ assert( m_pendingSymbolCode > 0 );+ m_pendingSymbolCode--;++ auto code = (char*)m_slab.AllocBig( sz );+ memcpy( code, data, sz );+ m_data.symbolCode.emplace( ptr, MemoryBlock{ code, uint32_t( sz ) } );+ m_data.symbolCodeSize += sz;++ if( m_data.cpuArch == CpuArchUnknown ) return;+ csh handle;+ cs_err rval = CS_ERR_ARCH;+ switch( m_data.cpuArch )+ {+ case CpuArchX86:+ rval = cs_open( CS_ARCH_X86, CS_MODE_32, &handle );+ break;+ case CpuArchX64:+ rval = cs_open( CS_ARCH_X86, CS_MODE_64, &handle );+ break;+ case CpuArchArm32:+ rval = cs_open( CS_ARCH_ARM, CS_MODE_ARM, &handle );+ break;+ case CpuArchArm64:+ rval = cs_open( CS_ARCH_AARCH64, CS_MODE_ARM, &handle );+ break;+ default:+ assert( false );+ break;+ }+ if( rval != CS_ERR_OK ) return;+ cs_option( handle, CS_OPT_DETAIL, CS_OPT_ON );+ cs_insn* insn;+ size_t cnt = cs_disasm( handle, (const uint8_t*)code, sz, ptr, 0, &insn );+ if( cnt > 0 )+ {+ for( size_t i=0; i<cnt; i++ )+ {+ const auto& op = insn[i];+ const auto addr = op.address;+ if( m_data.callstackFrameMap.find( PackPointer( addr ) ) == m_data.callstackFrameMap.end() )+ {+ m_pendingCallstackFrames++;+ Query( ServerQueryCallstackFrame, addr );+ }++ uint64_t callAddr = 0;+ const auto& detail = *op.detail;+ for( auto j=0; j<detail.groups_count; j++ )+ {+ if( detail.groups[j] == CS_GRP_JUMP || detail.groups[j] == CS_GRP_CALL )+ {+ switch( GetCpuArch() )+ {+ case CpuArchX86:+ case CpuArchX64:+ if( detail.x86.op_count == 1 && detail.x86.operands[0].type == X86_OP_IMM )+ {+ callAddr = (uint64_t)detail.x86.operands[0].imm;+ }+ break;+ case CpuArchArm32:+ if( detail.arm.op_count == 1 && detail.arm.operands[0].type == ARM_OP_IMM )+ {+ callAddr = (uint64_t)detail.arm.operands[0].imm;+ }+ break;+ case CpuArchArm64:+ if( detail.aarch64.op_count == 1 && detail.aarch64.operands[0].type == AARCH64_OP_IMM )+ {+ callAddr = (uint64_t)detail.aarch64.operands[0].imm;+ }+ break;+ default:+ assert( false );+ break;+ }+ if( callAddr != 0 ) break;+ }+ }+ if( callAddr != 0 && m_data.callstackFrameMap.find( PackPointer( callAddr ) ) == m_data.callstackFrameMap.end() )+ {+ m_pendingCallstackFrames++;+ Query( ServerQueryCallstackFrame, callAddr );+ }+ }+ cs_free( insn, cnt );+ }+ cs_close( &handle );+}+++void Worker::AddSourceCode( uint32_t id, const char* data, size_t sz )+{+ auto it = m_sourceCodeQuery.find( id );+ assert( it != m_sourceCodeQuery.end() );+ auto file = it->second;+ m_sourceCodeQuery.erase( it );+ if( m_data.sourceFileCache.find( file ) != m_data.sourceFileCache.end() ) return;+ auto src = (char*)m_slab.AllocBig( sz );+ memcpy( src, data, sz );+ m_data.sourceFileCache.emplace( file, MemoryBlock{ src, uint32_t( sz ) } );+}++CallstackFrameId Worker::PackPointer( uint64_t ptr ) const+{+ assert( ( ( ptr & 0x3000000000000000 ) << 2 ) == ( ptr & 0xC000000000000000 ) );+ CallstackFrameId id;+ id.idx = ptr;+ id.sel = 0;+ id.custom = 0;+ return id;+}++uint64_t Worker::GetCanonicalPointer( const CallstackFrameId& id ) const+{+ assert( id.sel == 0 );+ return ( id.idx & 0x3FFFFFFFFFFFFFFF ) | ( ( id.idx & 0x3000000000000000 ) << 2 );+}++void Worker::AddCallstackPayload( const char* _data, size_t _sz )+{+ assert( m_pendingCallstackId == 0 );++ const auto sz = _sz / sizeof( uint64_t );+ const auto memsize = sizeof( VarArray<CallstackFrameId> ) + sz * sizeof( CallstackFrameId );+ auto mem = (char*)m_slab.AllocRaw( memsize );++ auto data = (CallstackFrameId*)mem;+ auto dst = data;+ auto src = (uint64_t*)_data;+ for( size_t i=0; i<sz; i++ )+ {+ *dst++ = PackPointer( *src++ );+ }++ auto arr = (VarArray<CallstackFrameId>*)( mem + sz * sizeof( CallstackFrameId ) );+ new(arr) VarArray<CallstackFrameId>( sz, data );++ uint32_t idx;+ auto it = m_data.callstackMap.find( arr );+ if( it == m_data.callstackMap.end() )+ {+ idx = m_data.callstackPayload.size();+ m_data.callstackMap.emplace( arr, idx );+ m_data.callstackPayload.push_back( arr );++ for( auto& frame : *arr )+ {+ auto fit = m_data.callstackFrameMap.find( frame );+ if( fit == m_data.callstackFrameMap.end() )+ {+ m_pendingCallstackFrames++;+ Query( ServerQueryCallstackFrame, GetCanonicalPointer( frame ) );+ }+ }+ }+ else+ {+ idx = it->second;+ m_slab.Unalloc( memsize );+ }++ m_pendingCallstackId = idx;+}++void Worker::AddCallstackAllocPayload( const char* data )+{+ CallstackFrameId stack[64];+ uint8_t sz;+ memcpy( &sz, data, 1 ); data++;+ assert( sz <= 64 );+ for( uint8_t i=0; i<sz; i++ )+ {+ uint16_t sz;+ CallstackFrame cf;+ memcpy( &cf.line, data, 4 ); data += 4;+ memcpy( &sz, data, 2 ); data += 2;+ cf.name = StoreString( data, sz ).idx; data += sz;+ memcpy( &sz, data, 2 ); data += 2;+ cf.file = StoreString( data, sz ).idx; data += sz;+ cf.symAddr = 0;+ CallstackFrameData cfd = { &cf, 1 };++ CallstackFrameId id;+ auto it = m_data.revFrameMap.find( &cfd );+ if( it == m_data.revFrameMap.end() )+ {+ auto frame = m_slab.Alloc<CallstackFrame>();+ memcpy( frame, &cf, sizeof( CallstackFrame ) );+ auto frameData = m_slab.AllocInit<CallstackFrameData>();+ frameData->data = frame;+ frameData->size = 1;+ id.idx = m_callstackAllocNextIdx++;+ id.sel = 1;+ id.custom = 0;+ m_data.callstackFrameMap.emplace( id, frameData );+ m_data.revFrameMap.emplace( frameData, id );+ }+ else+ {+ id = it->second;+ }+ stack[i] = id;+ }++ VarArray<CallstackFrameId>* arr;+ size_t memsize;+ if( m_pendingCallstackId != 0 )+ {+ const auto nativeCs = m_data.callstackPayload[m_pendingCallstackId];+ const auto nsz = nativeCs->size();+ const auto tsz = sz + nsz;++ memsize = sizeof( VarArray<CallstackFrameId> ) + tsz * sizeof( CallstackFrameId );+ auto mem = (char*)m_slab.AllocRaw( memsize );+ memcpy( mem, stack, sizeof( CallstackFrameId ) * sz );+ memcpy( mem + sizeof( CallstackFrameId ) * sz, nativeCs->data(), sizeof( CallstackFrameId ) * nsz );++ arr = (VarArray<CallstackFrameId>*)( mem + tsz * sizeof( CallstackFrameId ) );+ new(arr) VarArray<CallstackFrameId>( tsz, (CallstackFrameId*)mem );+ }+ else+ {+ memsize = sizeof( VarArray<CallstackFrameId> ) + sz * sizeof( CallstackFrameId );+ auto mem = (char*)m_slab.AllocRaw( memsize );+ memcpy( mem, stack, sizeof( CallstackFrameId ) * sz );++ arr = (VarArray<CallstackFrameId>*)( mem + sz * sizeof( CallstackFrameId ) );+ new(arr) VarArray<CallstackFrameId>( sz, (CallstackFrameId*)mem );+ }++ uint32_t idx;+ auto it = m_data.callstackMap.find( arr );+ if( it == m_data.callstackMap.end() )+ {+ idx = m_data.callstackPayload.size();+ m_data.callstackMap.emplace( arr, idx );+ m_data.callstackPayload.push_back( arr );++ for( auto& frame : *arr )+ {+ auto fit = m_data.callstackFrameMap.find( frame );+ if( fit == m_data.callstackFrameMap.end() )+ {+ m_pendingCallstackFrames++;+ Query( ServerQueryCallstackFrame, GetCanonicalPointer( frame ) );+ }+ }+ }+ else+ {+ idx = it->second;+ m_slab.Unalloc( memsize );+ }++ m_pendingCallstackId = idx;+}++uint32_t Worker::MergeCallstacks( uint32_t first, uint32_t second )+{+ const auto& cs1 = GetCallstack( first );+ const auto& cs2 = GetCallstack( second );++ const auto sz1 = cs1.size();+ const auto sz2 = cs2.size();+ const auto tsz = sz1 + sz2;++ size_t memsize = sizeof( VarArray<CallstackFrameId> ) + tsz * sizeof( CallstackFrameId );+ auto mem = (char*)m_slab.AllocRaw( memsize );+ memcpy( mem, cs1.data(), sizeof( CallstackFrameId ) * sz1 );+ memcpy( mem + sizeof( CallstackFrameId ) * sz1, cs2.data(), sizeof( CallstackFrameId ) * sz2 );++ VarArray<CallstackFrameId>* arr = (VarArray<CallstackFrameId>*)( mem + tsz * sizeof( CallstackFrameId ) );+ new(arr) VarArray<CallstackFrameId>( tsz, (CallstackFrameId*)mem );++ uint32_t idx;+ auto it = m_data.callstackMap.find( arr );+ if( it == m_data.callstackMap.end() )+ {+ idx = m_data.callstackPayload.size();+ m_data.callstackMap.emplace( arr, idx );+ m_data.callstackPayload.push_back( arr );+ }+ else+ {+ idx = it->second;+ m_slab.Unalloc( memsize );+ }+ return idx;+}++void Worker::InsertPlot( PlotData* plot, int64_t time, double val )+{+ if( plot->data.empty() )+ {+ plot->min = val;+ plot->max = val;+ plot->sum = val;+ plot->data.push_back( { Int48( time ), val } );+ }+ else+ {+ if( plot->min > val ) plot->min = val;+ else if( plot->max < val ) plot->max = val;+ plot->sum += val;+ plot->data.push_back( { Int48( time ), val } );+ }+}++void Worker::HandlePlotName( uint64_t name, const char* str, size_t sz )+{+ const auto sl = StoreString( str, sz );+ m_data.plots.StringDiscovered( name, sl, m_data.strings, [this] ( PlotData* dst, PlotData* src ) {+ for( auto& v : src->data )+ {+ InsertPlot( dst, v.time.Val(), v.val );+ }+ } );+}++void Worker::HandleFrameName( uint64_t name, const char* str, size_t sz )+{+ const auto sl = StoreString( str, sz );+ m_data.frames.StringDiscovered( name, sl, m_data.strings, [] ( FrameData* dst, FrameData* src ) {+ auto sz = dst->frames.size();+ dst->frames.insert( dst->frames.end(), src->frames.begin(), src->frames.end() );+ std::inplace_merge( dst->frames.begin(), dst->frames.begin() + sz, dst->frames.end(), [] ( const auto& lhs, const auto& rhs ) { return lhs.start < rhs.start; } );+ } );+}++void Worker::DoPostponedSymbols()+{+ if( m_data.newSymbolsIndex >= 0 )+ {+#ifdef __EMSCRIPTEN__+ pdqsort_branchless( m_data.symbolLoc.begin() + m_data.newSymbolsIndex, m_data.symbolLoc.end(), [] ( const auto& l, const auto& r ) { return l.addr < r.addr; } );+#else+ ppqsort::sort( ppqsort::execution::par, m_data.symbolLoc.begin() + m_data.newSymbolsIndex, m_data.symbolLoc.end(), [] ( const auto& l, const auto& r ) { return l.addr < r.addr; } );+#endif+ const auto ms = std::lower_bound( m_data.symbolLoc.begin(), m_data.symbolLoc.begin() + m_data.newSymbolsIndex, m_data.symbolLoc[m_data.newSymbolsIndex], [] ( const auto& l, const auto& r ) { return l.addr < r.addr; } );+ std::inplace_merge( ms, m_data.symbolLoc.begin() + m_data.newSymbolsIndex, m_data.symbolLoc.end(), [] ( const auto& l, const auto& r ) { return l.addr < r.addr; } );+ m_data.newSymbolsIndex = -1;+ }+}++void Worker::DoPostponedInlineSymbols()+{+ if( m_data.newInlineSymbolsIndex >= 0 )+ {+#ifdef __EMSCRIPTEN__+ pdqsort_branchless( m_data.symbolLocInline.begin() + m_data.newInlineSymbolsIndex, m_data.symbolLocInline.end() );+#else+ ppqsort::sort( ppqsort::execution::par, m_data.symbolLocInline.begin() + m_data.newInlineSymbolsIndex, m_data.symbolLocInline.end() );+#endif+ const auto ms = std::lower_bound( m_data.symbolLocInline.begin(), m_data.symbolLocInline.begin() + m_data.newInlineSymbolsIndex, m_data.symbolLocInline[m_data.newInlineSymbolsIndex] );+ std::inplace_merge( ms, m_data.symbolLocInline.begin() + m_data.newInlineSymbolsIndex, m_data.symbolLocInline.end() );+ m_data.newInlineSymbolsIndex = -1;+ }+}++void Worker::DoPostponedWorkAll()+{+ DoPostponedWork();+ DoPostponedSymbols();+ DoPostponedInlineSymbols();++ for( auto& plot : m_data.plots.Data() )+ {+ if( !plot->data.is_sorted() ) plot->data.sort();+ }+}++void Worker::DoPostponedWork()+{+#ifndef TRACY_NO_STATISTICS+ if( m_data.newFramesWereReceived )+ {+ HandlePostponedSamples();+ HandlePostponedGhostZones();+ m_data.newFramesWereReceived = false;+ }++ if( m_identifySamples && m_data.newContextSwitchesReceived )+ {+ for( auto& td : m_data.threads )+ {+ if( !td->postponedSamples.empty() )+ {+ auto ctx = GetContextSwitchData( td->id );+ if( ctx )+ {+ td->postponedSamples.ensure_sorted();+ auto sit = td->postponedSamples.begin();+ auto cit = std::lower_bound( ctx->v.begin(), ctx->v.end(), sit->time.Val(), [] ( const auto& l, const auto& r ) { return (uint64_t)l.End() < (uint64_t)r; } );+ if( cit != ctx->v.end() )+ {+ do+ {+ if( sit->time.Val() == cit->Start() )+ {+ td->ctxSwitchSamples.push_back( *sit );+ }+ else+ {+ ProcessCallstackSampleImplStats( *sit, *td );+ }+ if( ++sit == td->postponedSamples.end() ) break;+ cit = std::lower_bound( cit, ctx->v.end(), sit->time.Val(), [] ( const auto& l, const auto& r ) { return (uint64_t)l.End() < (uint64_t)r; } );+ }+ while( cit != ctx->v.end() );+ if( sit == td->postponedSamples.end() )+ {+ td->postponedSamples.clear();+ }+ else+ {+ td->postponedSamples.erase( td->postponedSamples.begin(), sit );+ }+ }+ }+ }+ }+ m_data.newContextSwitchesReceived = false;+ }+#endif+}++#ifndef TRACY_NO_STATISTICS+void Worker::HandlePostponedSamples()+{+ assert( m_data.newFramesWereReceived );+ if( m_data.postponedSamples.empty() ) return;+ auto it = m_data.postponedSamples.begin();+ do+ {+ UpdateSampleStatisticsPostponed( it );+ }+ while( it != m_data.postponedSamples.end() );+}++void Worker::GetStackWithInlines( Vector<InlineStackData>& ret, const VarArray<CallstackFrameId>& cs )+{+ ret.clear();+ int idx = cs.size() - 1;+ do+ {+ auto& entry = cs[idx];+ const auto frame = GetCallstackFrame( entry );+ if( frame )+ {+ uint8_t i = frame->size;+ do+ {+ i--;+ ret.push_back( InlineStackData { frame->data[i].symAddr, entry, i } );+ }+ while( i != 0 );+ }+ else+ {+ ret.push_back( InlineStackData{ GetCanonicalPointer( entry ), entry, 0 } );+ }+ }+ while( idx-- > 0 );+}++int Worker::AddGhostZone( const VarArray<CallstackFrameId>& cs, Vector<GhostZone>* vec, uint64_t t )+{+ GetStackWithInlines( m_inlineStack, cs );++ if( !vec->empty() && vec->back().end.Val() > (int64_t)t )+ {+ const auto refBackTime = vec->back().end.Val();+ auto tmp = vec;+ for(;;)+ {+ auto& back = tmp->back();+ if( back.end.Val() != refBackTime ) break;+ back.end.SetVal( t );+ if( back.child < 0 ) break;+ tmp = &m_data.ghostChildren[back.child];+ }+ }+ const int64_t refBackTime = vec->empty() ? 0 : vec->back().end.Val();+ int gcnt = 0;+ size_t idx = 0;+ while( !vec->empty() && idx < m_inlineStack.size() )+ {+ auto& back = vec->back();+ const auto& backKey = m_data.ghostFrames[back.frame.Val()];+ const auto backFrame = GetCallstackFrame( backKey.frame );+ if( !backFrame ) break;+ const auto& inlineFrame = backFrame->data[backKey.inlineFrame];+ if( inlineFrame.symAddr != m_inlineStack[idx].symAddr ) break;+ if( back.end.Val() != refBackTime ) break;+ back.end.SetVal( t + m_samplingPeriod );+ if( ++idx == m_inlineStack.size() ) break;+ if( back.child < 0 )+ {+ back.child = m_data.ghostChildren.size();+ vec = &m_data.ghostChildren.push_next();+ }+ else+ {+ vec = &m_data.ghostChildren[back.child];+ }+ }+ while( idx < m_inlineStack.size() )+ {+ gcnt++;+ uint32_t fid;+ GhostKey key { m_inlineStack[idx].frame, m_inlineStack[idx].inlineFrame };+ auto it = m_data.ghostFramesMap.find( key );+ if( it == m_data.ghostFramesMap.end() )+ {+ fid = uint32_t( m_data.ghostFrames.size() );+ m_data.ghostFrames.push_back( key );+ m_data.ghostFramesMap.emplace( key, fid );+ }+ else+ {+ fid = it->second;+ }+ auto& zone = vec->push_next();+ zone.start.SetVal( t );+ zone.end.SetVal( t + m_samplingPeriod );+ zone.frame.SetVal( fid );+ if( ++idx == m_inlineStack.size() )+ {+ zone.child = -1;+ }+ else+ {+ zone.child = m_data.ghostChildren.size();+ vec = &m_data.ghostChildren.push_next();+ }+ }+ return gcnt;+}++void Worker::HandlePostponedGhostZones()+{+ assert( m_data.newFramesWereReceived );+ if( !m_data.ghostZonesPostponed ) return;+ bool postponed = false;+ for( auto& td : m_data.threads )+ {+ while( td->ghostIdx != td->samples.size() )+ {+ const auto& sample = td->samples[td->ghostIdx];+ const auto& cs = GetCallstack( sample.callstack.Val() );+ const auto cssz = cs.size();++ uint16_t i;+ for( i=0; i<cssz; i++ ) if( !GetCallstackFrame( cs[i] ) ) break;+ if( i != cssz )+ {+ postponed = true;+ break;+ }++ td->ghostIdx++;+ m_data.ghostCnt += AddGhostZone( cs, &td->ghostZones, sample.time.Val() );+ }+ }+ m_data.ghostZonesPostponed = postponed;+}+#endif++uint32_t Worker::GetSingleStringIdx()+{+ assert( m_pendingSingleString.ptr != nullptr );+ const auto idx = m_pendingSingleString.idx;+ m_pendingSingleString.ptr = nullptr;+ return idx;+}++uint32_t Worker::GetSecondStringIdx()+{+ assert( m_pendingSecondString.ptr != nullptr );+ const auto idx = m_pendingSecondString.idx;+ m_pendingSecondString.ptr = nullptr;+ return idx;+}++StringLocation Worker::StoreString( const char* str, size_t sz )+{+ StringLocation ret;+ charutil::StringKey key = { str, sz };+ auto sit = m_data.stringMap.find( key );+ if( sit == m_data.stringMap.end() )+ {+ auto ptr = m_slab.Alloc<char>( sz+1 );+ memcpy( ptr, str, sz );+ ptr[sz] = '\0';+ ret.ptr = ptr;+ ret.idx = m_data.stringData.size();+ m_data.stringMap.emplace( charutil::StringKey { ptr, sz }, m_data.stringData.size() );+ m_data.stringData.push_back( ptr );+ }+ else+ {+ ret.ptr = sit->first.ptr;+ ret.idx = sit->second;+ }+ return ret;+}++bool Worker::Process( const QueueItem& ev )+{+ switch( ev.hdr.type )+ {+ case QueueType::ThreadContext:+ ProcessThreadContext( ev.threadCtx );+ break;+ case QueueType::ZoneBegin:+ ProcessZoneBegin( ev.zoneBegin );+ break;+ case QueueType::ZoneBeginCallstack:+ ProcessZoneBeginCallstack( ev.zoneBegin );+ break;+ case QueueType::ZoneBeginAllocSrcLoc:+ ProcessZoneBeginAllocSrcLoc( ev.zoneBeginLean );+ break;+ case QueueType::ZoneBeginAllocSrcLocCallstack:+ ProcessZoneBeginAllocSrcLocCallstack( ev.zoneBeginLean );+ break;+ case QueueType::ZoneEnd:+ ProcessZoneEnd( ev.zoneEnd );+ break;+ case QueueType::ZoneValidation:+ ProcessZoneValidation( ev.zoneValidation );+ break;+ case QueueType::FrameMarkMsg:+ ProcessFrameMark( ev.frameMark );+ break;+ case QueueType::FrameMarkMsgStart:+ ProcessFrameMarkStart( ev.frameMark );+ break;+ case QueueType::FrameMarkMsgEnd:+ ProcessFrameMarkEnd( ev.frameMark );+ break;+ case QueueType::FrameVsync:+ ProcessFrameVsync( ev.frameVsync );+ break;+ case QueueType::FrameImage:+ ProcessFrameImage( ev.frameImage );+ break;+ case QueueType::SourceLocation:+ AddSourceLocation( ev.srcloc );+ m_serverQuerySpaceLeft++;+ break;+ case QueueType::ZoneText:+ ProcessZoneText();+ break;+ case QueueType::ZoneName:+ ProcessZoneName();+ break;+ case QueueType::ZoneColor:+ ProcessZoneColor( ev.zoneColor );+ break;+ case QueueType::ZoneValue:+ ProcessZoneValue( ev.zoneValue );+ break;+ case QueueType::LockAnnounce:+ ProcessLockAnnounce( ev.lockAnnounce );+ break;+ case QueueType::LockTerminate:+ ProcessLockTerminate( ev.lockTerminate );+ break;+ case QueueType::LockWait:+ ProcessLockWait( ev.lockWait );+ break;+ case QueueType::LockObtain:+ ProcessLockObtain( ev.lockObtain );+ break;+ case QueueType::LockRelease:+ ProcessLockRelease( ev.lockRelease );+ break;+ case QueueType::LockSharedWait:+ ProcessLockSharedWait( ev.lockWait );+ break;+ case QueueType::LockSharedObtain:+ ProcessLockSharedObtain( ev.lockObtain );+ break;+ case QueueType::LockSharedRelease:+ ProcessLockSharedRelease( ev.lockReleaseShared );+ break;+ case QueueType::LockMark:+ ProcessLockMark( ev.lockMark );+ break;+ case QueueType::LockName:+ ProcessLockName( ev.lockName );+ break;+ case QueueType::PlotDataInt:+ ProcessPlotDataInt( ev.plotDataInt );+ break;+ case QueueType::PlotDataFloat:+ ProcessPlotDataFloat( ev.plotDataFloat );+ break;+ case QueueType::PlotDataDouble:+ ProcessPlotDataDouble( ev.plotDataDouble );+ break;+ case QueueType::PlotConfig:+ ProcessPlotConfig( ev.plotConfig );+ break;+ case QueueType::Message:+ ProcessMessage( ev.message );+ break;+ case QueueType::MessageLiteral:+ ProcessMessageLiteral( ev.messageLiteral );+ break;+ case QueueType::MessageColor:+ ProcessMessageColor( ev.messageColor );+ break;+ case QueueType::MessageLiteralColor:+ ProcessMessageLiteralColor( ev.messageColorLiteral );+ break;+ case QueueType::MessageCallstack:+ ProcessMessageCallstack( ev.message );+ break;+ case QueueType::MessageLiteralCallstack:+ ProcessMessageLiteralCallstack( ev.messageLiteral );+ break;+ case QueueType::MessageColorCallstack:+ ProcessMessageColorCallstack( ev.messageColor );+ break;+ case QueueType::MessageLiteralColorCallstack:+ ProcessMessageLiteralColorCallstack( ev.messageColorLiteral );+ break;+ case QueueType::MessageAppInfo:+ ProcessMessageAppInfo( ev.message );+ break;+ case QueueType::GpuNewContext:+ ProcessGpuNewContext( ev.gpuNewContext );+ break;+ case QueueType::GpuZoneBegin:+ ProcessGpuZoneBegin( ev.gpuZoneBegin, false );+ break;+ case QueueType::GpuZoneBeginCallstack:+ ProcessGpuZoneBeginCallstack( ev.gpuZoneBegin, false );+ break;+ case QueueType::GpuZoneBeginAllocSrcLoc:+ ProcessGpuZoneBeginAllocSrcLoc( ev.gpuZoneBeginLean, false );+ break;+ case QueueType::GpuZoneBeginAllocSrcLocCallstack:+ ProcessGpuZoneBeginAllocSrcLocCallstack( ev.gpuZoneBeginLean, false );+ break;+ case QueueType::GpuZoneEnd:+ ProcessGpuZoneEnd( ev.gpuZoneEnd, false );+ break;+ case QueueType::GpuZoneBeginSerial:+ ProcessGpuZoneBegin( ev.gpuZoneBegin, true );+ break;+ case QueueType::GpuZoneBeginCallstackSerial:+ ProcessGpuZoneBeginCallstack( ev.gpuZoneBegin, true );+ break;+ case QueueType::GpuZoneBeginAllocSrcLocSerial:+ ProcessGpuZoneBeginAllocSrcLoc( ev.gpuZoneBeginLean, true );+ break;+ case QueueType::GpuZoneBeginAllocSrcLocCallstackSerial:+ ProcessGpuZoneBeginAllocSrcLocCallstack( ev.gpuZoneBeginLean, true );+ break;+ case QueueType::GpuZoneEndSerial:+ ProcessGpuZoneEnd( ev.gpuZoneEnd, true );+ break;+ case QueueType::GpuTime:+ ProcessGpuTime( ev.gpuTime );+ break;+ case QueueType::GpuCalibration:+ ProcessGpuCalibration( ev.gpuCalibration );+ break;+ case QueueType::GpuTimeSync:+ ProcessGpuTimeSync( ev.gpuTimeSync );+ break;+ case QueueType::GpuContextName:+ ProcessGpuContextName( ev.gpuContextName );+ break;+ case QueueType::MemAlloc:+ ProcessMemAlloc( ev.memAlloc );+ break;+ case QueueType::MemAllocNamed:+ ProcessMemAllocNamed( ev.memAlloc );+ break;+ case QueueType::MemFree:+ ProcessMemFree( ev.memFree );+ break;+ case QueueType::MemFreeNamed:+ ProcessMemFreeNamed( ev.memFree );+ break;+ case QueueType::MemAllocCallstack:+ ProcessMemAllocCallstack( ev.memAlloc );+ break;+ case QueueType::MemAllocCallstackNamed:+ ProcessMemAllocCallstackNamed( ev.memAlloc );+ break;+ case QueueType::MemFreeCallstack:+ ProcessMemFreeCallstack( ev.memFree );+ break;+ case QueueType::MemFreeCallstackNamed:+ ProcessMemFreeCallstackNamed( ev.memFree );+ break;+ case QueueType::MemDiscard:+ ProcessMemDiscard( ev.memDiscard );+ break;+ case QueueType::MemDiscardCallstack:+ ProcessMemDiscardCallstack( ev.memDiscard );+ break;+ case QueueType::CallstackSerial:+ ProcessCallstackSerial();+ break;+ case QueueType::Callstack:+ case QueueType::CallstackAlloc:+ ProcessCallstack();+ break;+ case QueueType::CallstackSample:+ ProcessCallstackSample( ev.callstackSample );+ break;+ case QueueType::CallstackSampleContextSwitch:+ ProcessCallstackSampleContextSwitch( ev.callstackSample );+ break;+ case QueueType::CallstackFrameSize:+ ProcessCallstackFrameSize( ev.callstackFrameSize );+ m_serverQuerySpaceLeft++;+ break;+ case QueueType::CallstackFrame:+ ProcessCallstackFrame( ev.callstackFrame, true );+ break;+ case QueueType::SymbolInformation:+ ProcessSymbolInformation( ev.symbolInformation );+ m_serverQuerySpaceLeft++;+ break;+ case QueueType::Terminate:+ m_terminate = true;+ break;+ case QueueType::KeepAlive:+ break;+ case QueueType::Crash:+ m_crashed = true;+ break;+ case QueueType::CrashReport:+ ProcessCrashReport( ev.crashReport );+ break;+ case QueueType::SysTimeReport:+ ProcessSysTime( ev.sysTime );+ break;+ case QueueType::SysPowerReport:+ ProcessSysPower( ev.sysPower );+ break;+ case QueueType::ContextSwitch:+ ProcessContextSwitch( ev.contextSwitch );+ break;+ case QueueType::ThreadWakeup:+ ProcessThreadWakeup( ev.threadWakeup );+ break;+ case QueueType::TidToPid:+ ProcessTidToPid( ev.tidToPid );+ break;+ case QueueType::HwSampleCpuCycle:+ ProcessHwSampleCpuCycle( ev.hwSample );+ break;+ case QueueType::HwSampleInstructionRetired:+ ProcessHwSampleInstructionRetired( ev.hwSample );+ break;+ case QueueType::HwSampleCacheReference:+ ProcessHwSampleCacheReference( ev.hwSample );+ break;+ case QueueType::HwSampleCacheMiss:+ ProcessHwSampleCacheMiss( ev.hwSample );+ break;+ case QueueType::HwSampleBranchRetired:+ ProcessHwSampleBranchRetired( ev.hwSample );+ break;+ case QueueType::HwSampleBranchMiss:+ ProcessHwSampleBranchMiss( ev.hwSample );+ break;+ case QueueType::ParamSetup:+ ProcessParamSetup( ev.paramSetup );+ break;+ case QueueType::AckServerQueryNoop:+ m_serverQuerySpaceLeft++;+ break;+ case QueueType::AckSourceCodeNotAvailable:+ ProcessSourceCodeNotAvailable( ev.sourceCodeNotAvailable );+ m_serverQuerySpaceLeft++;+ break;+ case QueueType::AckSymbolCodeNotAvailable:+ m_pendingSymbolCode--;+ m_serverQuerySpaceLeft++;+ break;+ case QueueType::CpuTopology:+ ProcessCpuTopology( ev.cpuTopology );+ break;+ case QueueType::MemNamePayload:+ ProcessMemNamePayload( ev.memName );+ break;+ case QueueType::ThreadGroupHint:+ ProcessThreadGroupHint( ev.threadGroupHint );+ break;+ case QueueType::FiberEnter:+ ProcessFiberEnter( ev.fiberEnter );+ break;+ case QueueType::FiberLeave:+ ProcessFiberLeave( ev.fiberLeave );+ break;+ default:+ assert( false );+ break;+ }++ return m_failure == Failure::None;+}++void Worker::ProcessThreadContext( const QueueThreadContext& ev )+{+ m_refTimeThread = 0;+ if( m_threadCtx != ev.thread )+ {+ m_threadCtx = ev.thread;+ m_threadCtxData = RetrieveThread( ev.thread );+ }+}++static tracy_force_inline int64_t RefTime( int64_t& reference, int64_t delta )+{+ const auto refTime = reference + delta;+ reference = refTime;+ return refTime;+}++void Worker::ProcessZoneBeginImpl( ZoneEvent* zone, const QueueZoneBegin& ev )+{+ CheckSourceLocation( ev.srcloc );++ const auto start = TscTime( RefTime( m_refTimeThread, ev.time ) );+ zone->SetStartSrcLoc( start, ShrinkSourceLocation( ev.srcloc ) );+ zone->SetEnd( -1 );+ zone->SetChild( -1 );++ if( m_data.lastTime < start ) m_data.lastTime = start;++ NewZone( zone );+}++void Worker::ProcessZoneBeginAllocSrcLocImpl( ZoneEvent* zone, const QueueZoneBeginLean& ev )+{+ assert( m_pendingSourceLocationPayload != 0 );++ const auto start = TscTime( RefTime( m_refTimeThread, ev.time ) );+ zone->SetStartSrcLoc( start, m_pendingSourceLocationPayload );+ zone->SetEnd( -1 );+ zone->SetChild( -1 );++ if( m_data.lastTime < start ) m_data.lastTime = start;++ NewZone( zone );++ m_pendingSourceLocationPayload = 0;+}++ZoneEvent* Worker::AllocZoneEvent()+{+ ZoneEvent* ret;+#ifndef TRACY_NO_STATISTICS+ ret = m_slab.Alloc<ZoneEvent>();+#else+ if( m_zoneEventPool.empty() )+ {+ ret = m_slab.Alloc<ZoneEvent>();+ }+ else+ {+ ret = m_zoneEventPool.back_and_pop();+ }+#endif+ ret->extra = 0;+ return ret;+}++void Worker::ProcessZoneBegin( const QueueZoneBegin& ev )+{+ auto zone = AllocZoneEvent();+ ProcessZoneBeginImpl( zone, ev );+}++void Worker::ProcessZoneBeginCallstack( const QueueZoneBegin& ev )+{+ auto zone = AllocZoneEvent();+ ProcessZoneBeginImpl( zone, ev );+ auto td = GetCurrentThreadData();+ auto it = m_nextCallstack.find( td->id );+ assert( it != m_nextCallstack.end() );+ auto& extra = RequestZoneExtra( *zone );+ extra.callstack.SetVal( it->second );+ it->second = 0;+}++void Worker::ProcessZoneBeginAllocSrcLoc( const QueueZoneBeginLean& ev )+{+ auto zone = AllocZoneEvent();+ ProcessZoneBeginAllocSrcLocImpl( zone, ev );+}++void Worker::ProcessZoneBeginAllocSrcLocCallstack( const QueueZoneBeginLean& ev )+{+ auto zone = AllocZoneEvent();+ ProcessZoneBeginAllocSrcLocImpl( zone, ev );+ auto td = GetCurrentThreadData();+ auto it = m_nextCallstack.find( td->id );+ assert( it != m_nextCallstack.end() );+ auto& extra = RequestZoneExtra( *zone );+ extra.callstack.SetVal( it->second );+ it->second = 0;+}++void Worker::ProcessZoneEnd( const QueueZoneEnd& ev )+{+ auto td = GetCurrentThreadData();+ if( td->zoneIdStack.empty() )+ {+ ZoneDoubleEndFailure( td->id, td->timeline.empty() ? nullptr : td->timeline.back() );+ return;+ }+ auto zoneId = td->zoneIdStack.back_and_pop();+ if( zoneId != td->nextZoneId )+ {+ ZoneStackFailure( td->id, td->stack.back() );+ return;+ }+ td->nextZoneId = 0;++ auto& stack = td->stack;+ assert( !stack.empty() );+ auto zone = stack.back_and_pop();+ assert( zone->End() == -1 );+ const auto isReentry = td->DecStackCount( zone->SrcLoc() );+ const auto timeEnd = TscTime( RefTime( m_refTimeThread, ev.time ) );+ zone->SetEnd( timeEnd );+ assert( timeEnd >= zone->Start() );++ if( m_data.lastTime < timeEnd ) m_data.lastTime = timeEnd;++ if( zone->HasChildren() )+ {+ auto& childVec = m_data.zoneChildren[zone->Child()];+ const auto sz = childVec.size();+ if( sz <= 8 * 1024 )+ {+ Vector<short_ptr<ZoneEvent>> fitVec;+#ifndef TRACY_NO_STATISTICS+ fitVec.reserve_exact( sz, m_slab );+ memcpy( fitVec.data(), childVec.data(), sz * sizeof( short_ptr<ZoneEvent> ) );+#else+ fitVec.set_magic();+ auto& fv = *((Vector<ZoneEvent>*)&fitVec);+ fv.reserve_exact( sz, m_slab );+ auto dst = fv.data();+ for( auto& ze : childVec )+ {+ ZoneEvent* src = ze;+ memcpy( dst++, src, sizeof( ZoneEvent ) );+ m_zoneEventPool.push_back( src );+ }+#endif+ fitVec.swap( childVec );+ m_data.zoneVectorCache.push_back( std::move( fitVec ) );+ }+ }++#ifndef TRACY_NO_STATISTICS+ assert( !td->childTimeStack.empty() );+ const auto timeSpan = timeEnd - zone->Start();+ if( timeSpan > 0 )+ {+ const auto ctid = CompressThread( td->id );+ ZoneThreadData ztd;+ ztd.SetZone( zone );+ ztd.SetThread( ctid );++ auto slz = GetSourceLocationZones( zone->SrcLoc() );+ slz->zones.push_back( ztd );+ if( slz->min > timeSpan ) slz->min = timeSpan;+ if( slz->max < timeSpan ) slz->max = timeSpan;+ slz->total += timeSpan;+ slz->sumSq += double( timeSpan ) * timeSpan;+ const auto selfSpan = timeSpan - td->childTimeStack.back_and_pop();+ if( slz->selfMin > selfSpan ) slz->selfMin = selfSpan;+ if( slz->selfMax < selfSpan ) slz->selfMax = selfSpan;+ slz->selfTotal += selfSpan;++ if( !isReentry )+ {+ slz->nonReentrantCount++;+ if( slz->nonReentrantMin > timeSpan ) slz->nonReentrantMin = timeSpan;+ if( slz->nonReentrantMax < timeSpan ) slz->nonReentrantMax = timeSpan;+ slz->nonReentrantTotal += timeSpan;+ }+ if( !td->childTimeStack.empty() )+ {+ td->childTimeStack.back() += timeSpan;+ }++ auto it = slz->threadCnt.find( ctid );+ if( it == slz->threadCnt.end() )+ {+ slz->threadCnt.emplace( ctid, 1 );+ }+ else+ {+ it->second++;+ }+ }+ else+ {+ td->childTimeStack.pop_back();+ }+#else+ CountZoneStatistics( zone );+#endif+}++void Worker::ZoneStackFailure( uint64_t thread, const ZoneEvent* ev )+{+ m_failure = Failure::ZoneStack;+ m_failureData.thread = thread;+ m_failureData.srcloc = ev->SrcLoc();+}++void Worker::ZoneDoubleEndFailure( uint64_t thread, const ZoneEvent* ev )+{+ m_failure = Failure::ZoneDoubleEnd;+ m_failureData.thread = thread;+ m_failureData.srcloc = ev ? ev->SrcLoc() : 0;+}++void Worker::ZoneTextFailure( uint64_t thread, const char* text )+{+ m_failure = Failure::ZoneText;+ m_failureData.thread = thread;+ m_failureData.message = text;+}++void Worker::ZoneValueFailure( uint64_t thread, uint64_t value )+{+ char buf[128];+ if( (int64_t)value < 0 )+ {+ sprintf( buf, "Zone value was: %" PRIu64 " (unsigned), %" PRIi64 " (signed)", value, (int64_t)value );+ }+ else+ {+ sprintf( buf, "Zone value was: %" PRIu64, value );+ }++ m_failure = Failure::ZoneValue;+ m_failureData.thread = thread;+ m_failureData.message = buf;+}++void Worker::ZoneColorFailure( uint64_t thread )+{+ m_failure = Failure::ZoneColor;+ m_failureData.thread = thread;+}++void Worker::ZoneNameFailure( uint64_t thread )+{+ m_failure = Failure::ZoneName;+ m_failureData.thread = thread;+}++void Worker::MemFreeFailure( uint64_t thread )+{+ m_failure = Failure::MemFree;+ m_failureData.thread = thread;+ m_failureData.callstack = m_serialNextCallstack;+}++void Worker::MemAllocTwiceFailure( uint64_t thread )+{+ m_failure = Failure::MemAllocTwice;+ m_failureData.thread = thread;+ m_failureData.callstack = m_serialNextCallstack;+}++void Worker::FrameEndFailure()+{+ m_failure = Failure::FrameEnd;+}++void Worker::FrameImageIndexFailure()+{+ m_failure = Failure::FrameImageIndex;+}++void Worker::FrameImageTwiceFailure()+{+ m_failure = Failure::FrameImageTwice;+}++void Worker::FiberLeaveFailure()+{+ m_failure = Failure::FiberLeave;+}++void Worker::SourceLocationOverflowFailure()+{+ m_failure = Failure::SourceLocationOverflow;+}++void Worker::ProcessZoneValidation( const QueueZoneValidation& ev )+{+ auto td = GetCurrentThreadData();+ td->nextZoneId = ev.id;+}++void Worker::ProcessFrameMark( const QueueFrameMark& ev )+{+ auto fd = m_data.frames.Retrieve( ev.name, [this] ( uint64_t name ) {+ auto fd = m_slab.AllocInit<FrameData>();+ fd->name = name;+ fd->continuous = 1;+ return fd;+ }, [this] ( uint64_t name ) {+ Query( ServerQueryFrameName, name );+ } );++ int32_t frameImage = -1;+ if( ev.name == 0 )+ {+ auto fis = m_frameImageStaging.find( fd->frames.size() );+ if( fis != m_frameImageStaging.end() )+ {+ frameImage = fis->second;+ m_frameImageStaging.erase( fis );+ }+ }++ assert( fd->continuous == 1 );+ const auto time = TscTime( ev.time );+ assert( fd->frames.empty() || fd->frames.back().start <= time );+ fd->frames.push_back( FrameEvent{ time, -1, frameImage } );+ if( m_data.lastTime < time ) m_data.lastTime = time;++#ifndef TRACY_NO_STATISTICS+ const auto timeSpan = GetFrameTime( *fd, fd->frames.size() - 1 );+ if( timeSpan > 0 )+ {+ fd->min = std::min( fd->min, timeSpan );+ fd->max = std::max( fd->max, timeSpan );+ fd->total += timeSpan;+ fd->sumSq += double( timeSpan ) * timeSpan;+ }+#endif+}++void Worker::ProcessFrameMarkStart( const QueueFrameMark& ev )+{+ auto fd = m_data.frames.Retrieve( ev.name, [this] ( uint64_t name ) {+ auto fd = m_slab.AllocInit<FrameData>();+ fd->name = name;+ fd->continuous = 0;+ return fd;+ }, [this] ( uint64_t name ) {+ Query( ServerQueryFrameName, name );+ } );++ assert( fd->continuous == 0 );+ const auto time = TscTime( ev.time );+ assert( fd->frames.empty() || ( fd->frames.back().end <= time && fd->frames.back().end != -1 ) );+ fd->frames.push_back( FrameEvent{ time, -1, -1 } );+ if( m_data.lastTime < time ) m_data.lastTime = time;+}++void Worker::ProcessFrameMarkEnd( const QueueFrameMark& ev )+{+ auto fd = m_data.frames.Retrieve( ev.name, [] ( uint64_t name ) -> FrameData* {+ return nullptr;+ }, [this] ( uint64_t name ) {+ Query( ServerQueryFrameName, name );+ } );++ if( !fd )+ {+ if( !m_ignoreFrameEndFaults ) FrameEndFailure();+ return;+ }++ assert( fd->continuous == 0 );+ if( fd->frames.empty() )+ {+ if( !m_ignoreFrameEndFaults ) FrameEndFailure();+ return;+ }+ const auto time = TscTime( ev.time );+ assert( fd->frames.back().end == -1 );+ fd->frames.back().end = time;+ if( m_data.lastTime < time ) m_data.lastTime = time;++#ifndef TRACY_NO_STATISTICS+ const auto timeSpan = GetFrameTime( *fd, fd->frames.size() - 1 );+ if( timeSpan > 0 )+ {+ fd->min = std::min( fd->min, timeSpan );+ fd->max = std::max( fd->max, timeSpan );+ fd->total += timeSpan;+ fd->sumSq += double( timeSpan ) * timeSpan;+ }+#endif+}++void Worker::ProcessFrameVsync( const QueueFrameVsync& ev )+{+ auto it = m_vsyncFrameMap.find( ev.id );+ if( it == m_vsyncFrameMap.end() )+ {+ auto fd = m_slab.AllocInit<FrameData>();+ // Hackfix workaround to maintain backwards compatibility.+ // Frame name pointers won't be in kernel space. Exploit that to store custom IDs.+ fd->name = uint64_t( m_vsyncFrameMap.size() ) | 0x8000000000000000;+ fd->continuous = 1;+ m_data.frames.AddExternal( fd );+ it = m_vsyncFrameMap.emplace( ev.id, fd ).first;+ }+ auto fd = it->second;+ assert( fd->continuous == 1 );+ const auto time = TscTime( ev.time );+ assert( fd->frames.empty() || fd->frames.back().start <= time );+ fd->frames.push_back( FrameEvent{ time, -1, -1 } );+ if( m_data.lastTime < time ) m_data.lastTime = time;++#ifndef TRACY_NO_STATISTICS+ const auto timeSpan = GetFrameTime( *fd, fd->frames.size() - 1 );+ if( timeSpan > 0 )+ {+ fd->min = std::min( fd->min, timeSpan );+ fd->max = std::max( fd->max, timeSpan );+ fd->total += timeSpan;+ fd->sumSq += double( timeSpan ) * timeSpan;+ }+#endif+}++void Worker::ProcessFrameImage( const QueueFrameImage& ev )+{+ assert( m_pendingFrameImageData.image != nullptr );++ auto& frames = m_data.framesBase->frames;+ const auto fidx = int64_t( ev.frame ) - int64_t( m_data.frameOffset ) + 1;+ if( m_onDemand && fidx <= 1 )+ {+ m_pendingFrameImageData.image = nullptr;+ return;+ }+ else if( fidx <= 0 )+ {+ FrameImageIndexFailure();+ return;+ }++ auto fi = m_slab.Alloc<FrameImage>();+ fi->ptr = m_pendingFrameImageData.image;+ fi->csz = m_pendingFrameImageData.csz;+ fi->w = ev.w;+ fi->h = ev.h;+ fi->frameRef = uint32_t( fidx );+ fi->flip = ev.flip;++ const auto idx = m_data.frameImage.size();+ m_data.frameImage.push_back( fi );+ m_pendingFrameImageData.image = nullptr;++ if( fidx >= (int64_t)frames.size() )+ {+ if( m_frameImageStaging.find( fidx ) != m_frameImageStaging.end() )+ {+ FrameImageTwiceFailure();+ return;+ }+ m_frameImageStaging.emplace( fidx, idx );+ }+ else if( frames[fidx].frameImage >= 0 )+ {+ FrameImageTwiceFailure();+ }+ else+ {+ frames[fidx].frameImage = idx;+ }+}++void Worker::ProcessZoneText()+{+ auto td = RetrieveThread( m_threadCtx );+ if( !td )+ {+ ZoneTextFailure( m_threadCtx, m_pendingSingleString.ptr );+ return;+ }+ if( td->fiber ) td = td->fiber;+ if( td->stack.empty() || td->nextZoneId != td->zoneIdStack.back() )+ {+ ZoneTextFailure( td->id, m_pendingSingleString.ptr );+ return;+ }++ const auto ptr = m_pendingSingleString.ptr;+ const auto idx = GetSingleStringIdx();++ td->nextZoneId = 0;+ auto& stack = td->stack;+ auto zone = stack.back();+ auto& extra = RequestZoneExtra( *zone );+ if( !extra.text.Active() )+ {+ extra.text = StringIdx( idx );+ }+ else+ {+ const auto str0 = GetString( extra.text );+ const auto str1 = ptr;+ const auto len0 = strlen( str0 );+ const auto len1 = strlen( str1 );+ const auto bsz = len0+len1+1;+ if( m_tmpBufSize < bsz )+ {+ delete[] m_tmpBuf;+ m_tmpBuf = new char[bsz];+ m_tmpBufSize = bsz;+ }+ char* buf = m_tmpBuf;+ memcpy( buf, str0, len0 );+ buf[len0] = '\n';+ memcpy( buf+len0+1, str1, len1 );+ extra.text = StringIdx( StoreString( buf, bsz ).idx );+ }+}++void Worker::ProcessZoneName()+{+ auto td = RetrieveThread( m_threadCtx );+ if( !td )+ {+ ZoneNameFailure( m_threadCtx );+ return;+ }+ if( td->fiber ) td = td->fiber;+ if( td->stack.empty() || td->nextZoneId != td->zoneIdStack.back() )+ {+ ZoneNameFailure( td->id );+ return;+ }++ td->nextZoneId = 0;+ auto& stack = td->stack;+ auto zone = stack.back();+ auto& extra = RequestZoneExtra( *zone );+ extra.name = StringIdx( GetSingleStringIdx() );+}++void Worker::ProcessZoneColor( const QueueZoneColor& ev )+{+ auto td = RetrieveThread( m_threadCtx );+ if( !td )+ {+ ZoneColorFailure( m_threadCtx );+ return;+ }+ if( td->fiber ) td = td->fiber;+ if( td->stack.empty() || td->nextZoneId != td->zoneIdStack.back() )+ {+ ZoneColorFailure( td->id );+ return;+ }++ td->nextZoneId = 0;+ auto& stack = td->stack;+ auto zone = stack.back();+ auto& extra = RequestZoneExtra( *zone );+ const uint32_t color = ( ev.b << 16 ) | ( ev.g << 8 ) | ev.r;+ extra.color = color;+}++void Worker::ProcessZoneValue( const QueueZoneValue& ev )+{+ char tmp[64];+ const auto tsz = sprintf( tmp, "%" PRIu64 " [0x%" PRIx64 "]", ev.value, ev.value );++ auto td = RetrieveThread( m_threadCtx );+ if( !td )+ {+ ZoneValueFailure( m_threadCtx, ev.value );+ return;+ }+ if( td->fiber ) td = td->fiber;+ if( td->stack.empty() || td->nextZoneId != td->zoneIdStack.back() )+ {+ ZoneValueFailure( td->id, ev.value );+ return;+ }++ td->nextZoneId = 0;+ auto& stack = td->stack;+ auto zone = stack.back();+ auto& extra = RequestZoneExtra( *zone );+ if( !extra.text.Active() )+ {+ extra.text = StringIdx( StoreString( tmp, tsz ).idx );+ }+ else+ {+ const auto str0 = GetString( extra.text );+ const auto len0 = strlen( str0 );+ const auto bsz = len0+tsz+1;+ if( m_tmpBufSize < bsz )+ {+ delete[] m_tmpBuf;+ m_tmpBuf = new char[bsz];+ m_tmpBufSize = bsz;+ }+ char* buf = m_tmpBuf;+ memcpy( buf, str0, len0 );+ buf[len0] = '\n';+ memcpy( buf+len0+1, tmp, tsz );+ extra.text = StringIdx( StoreString( buf, bsz ).idx );+ }+}++void Worker::ProcessLockAnnounce( const QueueLockAnnounce& ev )+{+ auto it = m_data.lockMap.find( ev.id );+ assert( it == m_data.lockMap.end() );+ auto lm = m_slab.AllocInit<LockMap>();+ lm->srcloc = ShrinkSourceLocation( ev.lckloc );+ lm->type = ev.type;+ lm->timeAnnounce = TscTime( ev.time );+ lm->timeTerminate = 0;+ lm->valid = true;+ lm->isContended = false;+ lm->lockingThread = 0;+ m_data.lockMap.emplace( ev.id, lm );+ CheckSourceLocation( ev.lckloc );+}++void Worker::ProcessLockTerminate( const QueueLockTerminate& ev )+{+ auto it = m_data.lockMap.find( ev.id );+ assert( it != m_data.lockMap.end() );+ it->second->timeTerminate = TscTime( ev.time );+}++void Worker::ProcessLockWait( const QueueLockWait& ev )+{+ auto it = m_data.lockMap.find( ev.id );+ assert( it != m_data.lockMap.end() );+ auto& lock = *it->second;++ auto lev = lock.type == LockType::Lockable ? m_slab.Alloc<LockEvent>() : m_slab.Alloc<LockEventShared>();+ const auto time = TscTime( RefTime( m_refTimeSerial, ev.time ) );+ lev->SetTime( time );+ lev->SetSrcLoc( 0 );+ lev->type = LockEvent::Type::Wait;++ InsertLockEvent( lock, lev, ev.thread, time );+}++void Worker::ProcessLockObtain( const QueueLockObtain& ev )+{+ auto it = m_data.lockMap.find( ev.id );+ assert( it != m_data.lockMap.end() );+ auto& lock = *it->second;++ auto lev = lock.type == LockType::Lockable ? m_slab.Alloc<LockEvent>() : m_slab.Alloc<LockEventShared>();+ const auto time = TscTime( RefTime( m_refTimeSerial, ev.time ) );+ lev->SetTime( time );+ lev->SetSrcLoc( 0 );+ lev->type = LockEvent::Type::Obtain;++ InsertLockEvent( lock, lev, ev.thread, time );+ lock.lockingThread = ev.thread;+}++void Worker::ProcessLockRelease( const QueueLockRelease& ev )+{+ auto it = m_data.lockMap.find( ev.id );+ assert( it != m_data.lockMap.end() );+ auto& lock = *it->second;++ auto lev = lock.type == LockType::Lockable ? m_slab.Alloc<LockEvent>() : m_slab.Alloc<LockEventShared>();+ const auto time = TscTime( RefTime( m_refTimeSerial, ev.time ) );+ lev->SetTime( time );+ lev->SetSrcLoc( 0 );+ lev->type = LockEvent::Type::Release;++ InsertLockEvent( lock, lev, lock.lockingThread, time );+}++void Worker::ProcessLockSharedWait( const QueueLockWait& ev )+{+ auto it = m_data.lockMap.find( ev.id );+ assert( it != m_data.lockMap.end() );+ auto& lock = *it->second;++ assert( lock.type == LockType::SharedLockable );+ auto lev = m_slab.Alloc<LockEventShared>();+ const auto time = TscTime( RefTime( m_refTimeSerial, ev.time ) );+ lev->SetTime( time );+ lev->SetSrcLoc( 0 );+ lev->type = LockEvent::Type::WaitShared;++ InsertLockEvent( lock, lev, ev.thread, time );+}++void Worker::ProcessLockSharedObtain( const QueueLockObtain& ev )+{+ auto it = m_data.lockMap.find( ev.id );+ assert( it != m_data.lockMap.end() );+ auto& lock = *it->second;++ assert( lock.type == LockType::SharedLockable );+ auto lev = m_slab.Alloc<LockEventShared>();+ const auto time = TscTime( RefTime( m_refTimeSerial, ev.time ) );+ lev->SetTime( time );+ lev->SetSrcLoc( 0 );+ lev->type = LockEvent::Type::ObtainShared;++ InsertLockEvent( lock, lev, ev.thread, time );+}++void Worker::ProcessLockSharedRelease( const QueueLockReleaseShared& ev )+{+ auto it = m_data.lockMap.find( ev.id );+ assert( it != m_data.lockMap.end() );+ auto& lock = *it->second;++ assert( lock.type == LockType::SharedLockable );+ auto lev = m_slab.Alloc<LockEventShared>();+ const auto time = TscTime( RefTime( m_refTimeSerial, ev.time ) );+ lev->SetTime( time );+ lev->SetSrcLoc( 0 );+ lev->type = LockEvent::Type::ReleaseShared;++ InsertLockEvent( lock, lev, ev.thread, time );+}++void Worker::ProcessLockMark( const QueueLockMark& ev )+{+ CheckSourceLocation( ev.srcloc );+ auto lit = m_data.lockMap.find( ev.id );+ assert( lit != m_data.lockMap.end() );+ auto& lockmap = *lit->second;+ auto tid = lockmap.threadMap.find( ev.thread );+ assert( tid != lockmap.threadMap.end() );+ const auto thread = tid->second;+ auto it = lockmap.timeline.end();+ for(;;)+ {+ --it;+ if( it->ptr->thread == thread )+ {+ switch( it->ptr->type )+ {+ case LockEvent::Type::Obtain:+ case LockEvent::Type::ObtainShared:+ case LockEvent::Type::Wait:+ case LockEvent::Type::WaitShared:+ it->ptr->SetSrcLoc( ShrinkSourceLocation( ev.srcloc ) );+ return;+ default:+ break;+ }+ }+ }+}++void Worker::ProcessLockName( const QueueLockName& ev )+{+ auto lit = m_data.lockMap.find( ev.id );+ assert( lit != m_data.lockMap.end() );+ lit->second->customName = StringIdx( GetSingleStringIdx() );+}++void Worker::ProcessPlotDataInt( const QueuePlotDataInt& ev )+{+ ProcessPlotDataImpl( ev.name, ev.time, (double)ev.val );+}++void Worker::ProcessPlotDataFloat( const QueuePlotDataFloat& ev )+{+ if( !isfinite( ev.val ) ) return;+ ProcessPlotDataImpl( ev.name, ev.time, (double)ev.val );+}++void Worker::ProcessPlotDataDouble( const QueuePlotDataDouble& ev )+{+ if( !isfinite( ev.val ) ) return;+ ProcessPlotDataImpl( ev.name, ev.time, ev.val );+}++void Worker::ProcessPlotDataImpl( uint64_t name, int64_t evTime, double val )+{+ PlotData* plot = m_data.plots.Retrieve( name, [this] ( uint64_t name ) {+ auto plot = m_slab.AllocInit<PlotData>();+ plot->name = name;+ plot->type = PlotType::User;+ plot->format = PlotValueFormatting::Number;+ plot->showSteps = false;+ plot->fill = true;+ plot->color = 0;+ return plot;+ }, [this]( uint64_t name ) {+ Query( ServerQueryPlotName, name );+ } );++ const auto time = TscTime( RefTime( m_refTimeThread, evTime ) );+ if( m_data.lastTime < time ) m_data.lastTime = time;+ InsertPlot( plot, time, val );+}++void Worker::ProcessPlotConfig( const QueuePlotConfig& ev )+{+ PlotData* plot = m_data.plots.Retrieve( ev.name, [this] ( uint64_t name ) {+ auto plot = m_slab.AllocInit<PlotData>();+ plot->name = name;+ plot->type = PlotType::User;+ return plot;+ }, [this]( uint64_t name ) {+ Query( ServerQueryPlotName, name );+ } );++ plot->format = (PlotValueFormatting)ev.type;+ plot->showSteps = ev.step;+ plot->fill = ev.fill;+ plot->color = ev.color & 0xFFFFFF;+}++void Worker::ProcessMessage( const QueueMessage& ev )+{+ auto td = GetCurrentThreadData();+ auto msg = m_slab.Alloc<MessageData>();+ const auto time = TscTime( ev.time );+ msg->time = time;+ msg->ref = StringRef( StringRef::Type::Idx, GetSingleStringIdx() );+ msg->thread = CompressThread( td->id );+ msg->color = 0xFFFFFFFF;+ msg->callstack.SetVal( 0 );+ if( m_data.lastTime < time ) m_data.lastTime = time;+ InsertMessageData( msg );+}++void Worker::ProcessMessageLiteral( const QueueMessageLiteral& ev )+{+ auto td = GetCurrentThreadData();+ CheckString( ev.text );+ auto msg = m_slab.Alloc<MessageData>();+ const auto time = TscTime( ev.time );+ msg->time = time;+ msg->ref = StringRef( StringRef::Type::Ptr, ev.text );+ msg->thread = CompressThread( td->id );+ msg->color = 0xFFFFFFFF;+ msg->callstack.SetVal( 0 );+ if( m_data.lastTime < time ) m_data.lastTime = time;+ InsertMessageData( msg );+}++void Worker::ProcessMessageColor( const QueueMessageColor& ev )+{+ auto td = GetCurrentThreadData();+ auto msg = m_slab.Alloc<MessageData>();+ const auto time = TscTime( ev.time );+ msg->time = time;+ msg->ref = StringRef( StringRef::Type::Idx, GetSingleStringIdx() );+ msg->thread = CompressThread( td->id );+ msg->color = 0xFF000000 | ( ev.b << 16 ) | ( ev.g << 8 ) | ev.r;+ msg->callstack.SetVal( 0 );+ if( m_data.lastTime < time ) m_data.lastTime = time;+ InsertMessageData( msg );+}++void Worker::ProcessMessageLiteralColor( const QueueMessageColorLiteral& ev )+{+ auto td = GetCurrentThreadData();+ CheckString( ev.text );+ auto msg = m_slab.Alloc<MessageData>();+ const auto time = TscTime( ev.time );+ msg->time = time;+ msg->ref = StringRef( StringRef::Type::Ptr, ev.text );+ msg->thread = CompressThread( td->id );+ msg->color = 0xFF000000 | ( ev.b << 16 ) | ( ev.g << 8 ) | ev.r;+ msg->callstack.SetVal( 0 );+ if( m_data.lastTime < time ) m_data.lastTime = time;+ InsertMessageData( msg );+}++void Worker::ProcessMessageCallstack( const QueueMessage& ev )+{+ auto td = GetCurrentThreadData();+ ProcessMessage( ev );+ auto it = m_nextCallstack.find( td->id );+ assert( it != m_nextCallstack.end() );+ td->messages.back()->callstack.SetVal( it->second );+ it->second = 0;+}++void Worker::ProcessMessageLiteralCallstack( const QueueMessageLiteral& ev )+{+ auto td = GetCurrentThreadData();+ ProcessMessageLiteral( ev );+ auto it = m_nextCallstack.find( td->id );+ assert( it != m_nextCallstack.end() );+ td->messages.back()->callstack.SetVal( it->second );+ it->second = 0;+}++void Worker::ProcessMessageColorCallstack( const QueueMessageColor& ev )+{+ auto td = GetCurrentThreadData();+ ProcessMessageColor( ev );+ auto it = m_nextCallstack.find( td->id );+ assert( it != m_nextCallstack.end() );+ td->messages.back()->callstack.SetVal( it->second );+ it->second = 0;+}++void Worker::ProcessMessageLiteralColorCallstack( const QueueMessageColorLiteral& ev )+{+ auto td = GetCurrentThreadData();+ ProcessMessageLiteralColor( ev );+ auto it = m_nextCallstack.find( td->id );+ assert( it != m_nextCallstack.end() );+ td->messages.back()->callstack.SetVal( it->second );+ it->second = 0;+}++void Worker::ProcessMessageAppInfo( const QueueMessage& ev )+{+ m_data.appInfo.push_back( StringRef( StringRef::Type::Idx, GetSingleStringIdx() ) );+ const auto time = TscTime( ev.time );+ if( m_data.lastTime < time ) m_data.lastTime = time;+}++void Worker::ProcessGpuNewContext( const QueueGpuNewContext& ev )+{+ assert( !m_gpuCtxMap[ev.context] );+ assert( ev.type != GpuContextType::Invalid );++ int64_t gpuTime;+ if( ev.period == 1.f )+ {+ gpuTime = ev.gpuTime;+ }+ else+ {+ gpuTime = int64_t( double( ev.period ) * ev.gpuTime ); // precision loss+ }++ const auto cpuTime = TscTime( ev.cpuTime );+ auto gpu = m_slab.AllocInit<GpuCtxData>();+ memset( (char*)gpu->query, 0, sizeof( gpu->query ) );+ gpu->timeDiff = cpuTime - gpuTime;+ gpu->thread = ev.thread;+ gpu->period = ev.period;+ gpu->count = 0;+ gpu->type = ev.type;+ gpu->hasPeriod = ev.period != 1.f;+ gpu->hasCalibration = ev.flags & GpuContextCalibration;+ gpu->calibratedGpuTime = gpuTime;+ gpu->calibratedCpuTime = cpuTime;+ gpu->calibrationMod = 1.;+ gpu->lastGpuTime = 0;+ gpu->overflow = 0;+ gpu->overflowMul = 0;+ m_data.gpuData.push_back( gpu );+ m_gpuCtxMap[ev.context] = gpu;+}++void Worker::ProcessGpuZoneBeginImpl( GpuEvent* zone, const QueueGpuZoneBegin& ev, bool serial )+{+ CheckSourceLocation( ev.srcloc );+ zone->SetSrcLoc( ShrinkSourceLocation( ev.srcloc ) );+ ProcessGpuZoneBeginImplCommon( zone, ev, serial );+}++void Worker::ProcessGpuZoneBeginAllocSrcLocImpl( GpuEvent* zone, const QueueGpuZoneBeginLean& ev, bool serial )+{+ assert( m_pendingSourceLocationPayload != 0 );+ zone->SetSrcLoc( m_pendingSourceLocationPayload );+ ProcessGpuZoneBeginImplCommon( zone, ev, serial );+ m_pendingSourceLocationPayload = 0;+}++void Worker::ProcessGpuZoneBeginImplCommon( GpuEvent* zone, const QueueGpuZoneBeginLean& ev, bool serial )+{+ m_data.gpuCnt++;++ auto ctx = m_gpuCtxMap[ev.context].get();+ assert( ctx );++ int64_t cpuTime;+ if( serial )+ {+ cpuTime = RefTime( m_refTimeSerial, ev.cpuTime );+ }+ else+ {+ cpuTime = RefTime( m_refTimeThread, ev.cpuTime );+ }+ const auto time = TscTime( cpuTime );+ zone->SetCpuStart( time );+ zone->SetCpuEnd( -1 );+ zone->SetGpuStart( -1 );+ zone->SetGpuEnd( -1 );+ zone->callstack.SetVal( 0 );+ zone->SetChild( -1 );++ uint64_t ztid;+ if( ctx->thread == 0 )+ {+ // Vulkan, OpenCL and Direct3D 12 contexts are not bound to any single thread.+ zone->SetThread( CompressThread( ev.thread ) );+ ztid = ev.thread;+ }+ else+ {+ // OpenGL and Direct3D11 doesn't need per-zone thread id. It still can be sent,+ // because it may be needed for callstack collection purposes.+ zone->SetThread( 0 );+ ztid = 0;+ }++ if( m_data.lastTime < time ) m_data.lastTime = time;++ auto td = ctx->threadData.find( ztid );+ if( td == ctx->threadData.end() )+ {+ td = ctx->threadData.emplace( ztid, GpuCtxThreadData {} ).first;+ }+ auto timeline = &td->second.timeline;+ auto& stack = td->second.stack;+ if( !stack.empty() )+ {+ auto back = stack.back();+ if( back->Child() < 0 )+ {+ back->SetChild( int32_t( m_data.gpuChildren.size() ) );+ m_data.gpuChildren.push_back( Vector<short_ptr<GpuEvent>>() );+ }+ timeline = &m_data.gpuChildren[back->Child()];+ }++ timeline->push_back( zone );+ stack.push_back( zone );++ assert( !ctx->query[ev.queryId] );+ ctx->query[ev.queryId] = zone;+}++void Worker::ProcessGpuZoneBegin( const QueueGpuZoneBegin& ev, bool serial )+{+ auto zone = m_slab.Alloc<GpuEvent>();+ ProcessGpuZoneBeginImpl( zone, ev, serial );+}++void Worker::ProcessGpuZoneBeginCallstack( const QueueGpuZoneBegin& ev, bool serial )+{+ auto zone = m_slab.Alloc<GpuEvent>();+ ProcessGpuZoneBeginImpl( zone, ev, serial );+ if( serial )+ {+ assert( m_serialNextCallstack != 0 );+ zone->callstack.SetVal( m_serialNextCallstack );+ m_serialNextCallstack = 0;+ }+ else+ {+ auto td = GetCurrentThreadData();+ auto it = m_nextCallstack.find( td->id );+ assert( it != m_nextCallstack.end() );+ zone->callstack.SetVal( it->second );+ it->second = 0;+ }+}++void Worker::ProcessGpuZoneBeginAllocSrcLoc( const QueueGpuZoneBeginLean& ev, bool serial )+{+ auto zone = m_slab.Alloc<GpuEvent>();+ ProcessGpuZoneBeginAllocSrcLocImpl( zone, ev, serial );+}++void Worker::ProcessGpuZoneBeginAllocSrcLocCallstack( const QueueGpuZoneBeginLean& ev, bool serial )+{+ auto zone = m_slab.Alloc<GpuEvent>();+ ProcessGpuZoneBeginAllocSrcLocImpl( zone, ev, serial );+ if( serial )+ {+ assert( m_serialNextCallstack != 0 );+ zone->callstack.SetVal( m_serialNextCallstack );+ m_serialNextCallstack = 0;+ }+ else+ {+ auto td = GetCurrentThreadData();+ auto it = m_nextCallstack.find( td->id );+ assert( it != m_nextCallstack.end() );+ zone->callstack.SetVal( it->second );+ it->second = 0;+ }+}++void Worker::ProcessGpuZoneEnd( const QueueGpuZoneEnd& ev, bool serial )+{+ auto ctx = m_gpuCtxMap[ev.context];+ assert( ctx );++ auto td = ctx->threadData.find( ev.thread );+ assert( td != ctx->threadData.end() );++ assert( !td->second.stack.empty() );+ auto zone = td->second.stack.back_and_pop();++ assert( !ctx->query[ev.queryId] );+ ctx->query[ev.queryId] = zone;++ int64_t cpuTime;+ if( serial )+ {+ cpuTime = RefTime( m_refTimeSerial, ev.cpuTime );+ }+ else+ {+ cpuTime = RefTime( m_refTimeThread, ev.cpuTime );+ }+ const auto time = TscTime( cpuTime );+ zone->SetCpuEnd( time );+ if( m_data.lastTime < time ) m_data.lastTime = time;+}++void Worker::ProcessGpuTime( const QueueGpuTime& ev )+{+ auto ctx = m_gpuCtxMap[ev.context];+ assert( ctx );++ int64_t tgpu = RefTime( m_refTimeGpu, ev.gpuTime );+ if( tgpu < ctx->lastGpuTime - ( 1u << 31 ) )+ {+ if( ctx->overflow == 0 )+ {+ ctx->overflow = uint64_t( 1 ) << ( 64 - TracyLzcnt( ctx->lastGpuTime ) );+ }+ ctx->overflowMul++;+ }+ ctx->lastGpuTime = tgpu;+ if( ctx->overflow != 0 )+ {+ tgpu += ctx->overflow * ctx->overflowMul;+ }++ int64_t gpuTime;+ if( !ctx->hasPeriod )+ {+ if( !ctx->hasCalibration )+ {+ gpuTime = tgpu + ctx->timeDiff;+ }+ else+ {+ gpuTime = int64_t( ( tgpu - ctx->calibratedGpuTime ) * ctx->calibrationMod + ctx->calibratedCpuTime );+ }+ }+ else+ {+ if( !ctx->hasCalibration )+ {+ gpuTime = int64_t( double( ctx->period ) * tgpu ) + ctx->timeDiff; // precision loss+ }+ else+ {+ gpuTime = int64_t( ( double( ctx->period ) * tgpu - ctx->calibratedGpuTime ) * ctx->calibrationMod + ctx->calibratedCpuTime );+ }+ }++ auto zone = ctx->query[ev.queryId];+ assert( zone );+ ctx->query[ev.queryId] = nullptr;++ if( zone->GpuStart() < 0 )+ {+ zone->SetGpuStart( gpuTime );+ ctx->count++;+ }+ else+ {+ zone->SetGpuEnd( gpuTime );+#ifndef TRACY_NO_STATISTICS+ const auto gpuStart = zone->GpuStart();+ const auto timeSpan = gpuTime - gpuStart;+ if( timeSpan > 0 )+ {+ GpuZoneThreadData ztd;+ ztd.SetZone( zone );+ ztd.SetThread( zone->Thread() );+ auto slz = GetGpuSourceLocationZones( zone->SrcLoc() );+ slz->zones.push_back( ztd );+ if( slz->min > timeSpan ) slz->min = timeSpan;+ if( slz->max < timeSpan ) slz->max = timeSpan;+ slz->total += timeSpan;+ slz->sumSq += double( timeSpan ) * timeSpan;+ }+#else+ CountZoneStatistics( zone );+#endif+ }+ if( m_data.lastTime < gpuTime ) m_data.lastTime = gpuTime;+}++void Worker::ProcessGpuCalibration( const QueueGpuCalibration& ev )+{+ auto ctx = m_gpuCtxMap[ev.context];+ assert( ctx );+ assert( ctx->hasCalibration );++ int64_t gpuTime;+ if( !ctx->hasPeriod )+ {+ gpuTime = ev.gpuTime;+ }+ else+ {+ gpuTime = int64_t( double( ctx->period ) * ev.gpuTime ); // precision loss+ }++ const auto cpuDelta = ev.cpuDelta;+ const auto gpuDelta = gpuTime - ctx->calibratedGpuTime;+ ctx->calibrationMod = double( cpuDelta ) / gpuDelta;+ ctx->calibratedGpuTime = gpuTime;+ ctx->calibratedCpuTime = TscTime( ev.cpuTime );+}+ +void Worker::ProcessGpuTimeSync( const QueueGpuTimeSync& ev )+{+ auto ctx = m_gpuCtxMap[ev.context];+ assert( ctx );++ int64_t gpuTime;+ if( ctx->period == 1.f )+ {+ gpuTime = ev.gpuTime;+ }+ else+ {+ gpuTime = int64_t( double( ctx->period ) * ev.gpuTime ); // precision loss+ }++ const auto cpuTime = TscTime( ev.cpuTime );++ ctx->timeDiff = cpuTime - gpuTime;+ ctx->lastGpuTime = 0;+ ctx->overflow = 0;+ ctx->overflowMul = 0;+}++void Worker::ProcessGpuContextName( const QueueGpuContextName& ev )+{+ auto ctx = m_gpuCtxMap[ev.context];+ assert( ctx );+ const auto idx = GetSingleStringIdx();+ ctx->name = StringIdx( idx );+}++MemEvent* Worker::ProcessMemAllocImpl( MemData& memdata, const QueueMemAlloc& ev )+{+ if( memdata.active.find( ev.ptr ) != memdata.active.end() )+ {+ MemAllocTwiceFailure( ev.thread );+ return nullptr;+ }++ const auto time = TscTime( RefTime( m_refTimeSerial, ev.time ) );+ if( m_data.lastTime < time ) m_data.lastTime = time;+ NoticeThread( ev.thread );++ assert( memdata.data.empty() || memdata.data.back().TimeAlloc() <= time );++ memdata.active.emplace( ev.ptr, memdata.data.size() );++ const auto ptr = ev.ptr;+ uint32_t lo;+ uint16_t hi;+ memcpy( &lo, ev.size, 4 );+ memcpy( &hi, ev.size+4, 2 );+ const uint64_t size = lo | ( uint64_t( hi ) << 32 );++ auto& mem = memdata.data.push_next();+ mem.SetPtr( ptr );+ mem.SetSize( size );+ mem.SetTimeThreadAlloc( time, CompressThread( ev.thread ) );+ mem.SetTimeThreadFree( -1, 0 );+ mem.SetCsAlloc( 0 );+ mem.csFree.SetVal( 0 );++ const auto low = memdata.low;+ const auto high = memdata.high;+ const auto ptrend = ptr + size;++ memdata.low = std::min( low, ptr );+ memdata.high = std::max( high, ptrend );+ memdata.usage += size;++ MemAllocChanged( memdata, time );+ return &mem;+}++MemEvent* Worker::ProcessMemFreeImpl( MemData& memdata, const QueueMemFree& ev )+{+ const auto refTime = RefTime( m_refTimeSerial, ev.time );++ auto it = memdata.active.find( ev.ptr );+ if( it == memdata.active.end() )+ {+ if( ev.ptr == 0 ) return nullptr;++ if( !m_ignoreMemFreeFaults )+ {+ CheckThreadString( ev.thread );+ MemFreeFailure( ev.thread );+ }+ return nullptr;+ }++ const auto time = TscTime( refTime );+ if( m_data.lastTime < time ) m_data.lastTime = time;+ NoticeThread( ev.thread );++ memdata.frees.push_back( it->second );+ auto& mem = memdata.data[it->second];+ mem.SetTimeThreadFree( time, CompressThread( ev.thread ) );+ memdata.usage -= mem.Size();+ memdata.active.erase( it );++ MemAllocChanged( memdata, time );+ return &mem;+}++MemEvent* Worker::ProcessMemAlloc( const QueueMemAlloc& ev )+{+ assert( m_memNamePayload == 0 );+ return ProcessMemAllocImpl( *m_data.memory, ev );+}++MemEvent* Worker::ProcessMemAllocNamed( const QueueMemAlloc& ev )+{+ assert( m_memNamePayload != 0 );+ auto memname = m_memNamePayload;+ m_memNamePayload = 0;+ auto it = m_data.memNameMap.find( memname );+ if( it == m_data.memNameMap.end() )+ {+ CheckString( memname );+ it = m_data.memNameMap.emplace( memname, m_slab.AllocInit<MemData>() ).first;+ it->second->name = memname;+ }+ return ProcessMemAllocImpl( *it->second, ev );+}++MemEvent* Worker::ProcessMemFree( const QueueMemFree& ev )+{+ assert( m_memNamePayload == 0 );+ return ProcessMemFreeImpl( *m_data.memory, ev );+}++MemEvent* Worker::ProcessMemFreeNamed( const QueueMemFree& ev )+{+ assert( m_memNamePayload != 0 );+ auto memname = m_memNamePayload;+ m_memNamePayload = 0;+ auto it = m_data.memNameMap.find( memname );+ if( it == m_data.memNameMap.end() )+ {+ CheckString( memname );+ it = m_data.memNameMap.emplace( memname, m_slab.AllocInit<MemData>() ).first;+ it->second->name = memname;+ }+ return ProcessMemFreeImpl( *it->second, ev );+}++void Worker::ProcessMemAllocCallstack( const QueueMemAlloc& ev )+{+ auto mem = ProcessMemAlloc( ev );+ assert( m_serialNextCallstack != 0 );+ if( mem ) mem->SetCsAlloc( m_serialNextCallstack );+ m_serialNextCallstack = 0;+}++void Worker::ProcessMemAllocCallstackNamed( const QueueMemAlloc& ev )+{+ assert( m_memNamePayload != 0 );+ auto memname = m_memNamePayload;+ m_memNamePayload = 0;+ auto it = m_data.memNameMap.find( memname );+ if( it == m_data.memNameMap.end() )+ {+ CheckString( memname );+ it = m_data.memNameMap.emplace( memname, m_slab.AllocInit<MemData>() ).first;+ it->second->name = memname;+ }+ auto mem = ProcessMemAllocImpl( *it->second, ev );+ assert( m_serialNextCallstack != 0 );+ if( mem ) mem->SetCsAlloc( m_serialNextCallstack );+ m_serialNextCallstack = 0;+}++void Worker::ProcessMemFreeCallstack( const QueueMemFree& ev )+{+ auto mem = ProcessMemFree( ev );+ assert( m_serialNextCallstack != 0 );+ if( mem ) mem->csFree.SetVal( m_serialNextCallstack );+ m_serialNextCallstack = 0;+}++void Worker::ProcessMemFreeCallstackNamed( const QueueMemFree& ev )+{+ assert( m_memNamePayload != 0 );+ auto memname = m_memNamePayload;+ m_memNamePayload = 0;+ auto it = m_data.memNameMap.find( memname );+ if( it == m_data.memNameMap.end() )+ {+ CheckString( memname );+ it = m_data.memNameMap.emplace( memname, m_slab.AllocInit<MemData>() ).first;+ it->second->name = memname;+ }+ auto mem = ProcessMemFreeImpl( *it->second, ev );+ assert( m_serialNextCallstack != 0 );+ if( mem ) mem->csFree.SetVal( m_serialNextCallstack );+ m_serialNextCallstack = 0;+}++void Worker::ProcessMemDiscard( const QueueMemDiscard& ev )+{+ assert( m_memNamePayload == 0 );+ auto it = m_data.memNameMap.find( ev.name );+ if( it == m_data.memNameMap.end() ) return;++ const auto refTime = RefTime( m_refTimeSerial, ev.time );+ auto& memdata = *it->second;++ const auto time = TscTime( refTime );+ if( m_data.lastTime < time ) m_data.lastTime = time;+ NoticeThread( ev.thread );+ const auto thread = CompressThread( ev.thread );++ for( auto& v : memdata.active )+ {+ memdata.frees.push_back( v.second );+ auto& mem = memdata.data[v.second];+ mem.SetTimeThreadFree( time, thread );+ memdata.usage -= mem.Size();+ MemAllocChanged( memdata, time );+ }++ memdata.active.clear();+ assert( memdata.usage == 0 );+}++void Worker::ProcessMemDiscardCallstack( const QueueMemDiscard& ev )+{+ assert( m_serialNextCallstack != 0 );+ auto cs = m_serialNextCallstack;+ m_serialNextCallstack = 0;++ assert( m_memNamePayload == 0 );+ auto it = m_data.memNameMap.find( ev.name );+ if( it == m_data.memNameMap.end() ) return;++ const auto refTime = RefTime( m_refTimeSerial, ev.time );+ auto& memdata = *it->second;++ const auto time = TscTime( refTime );+ if( m_data.lastTime < time ) m_data.lastTime = time;+ NoticeThread( ev.thread );+ const auto thread = CompressThread( ev.thread );++ for( auto& v : memdata.active )+ {+ memdata.frees.push_back( v.second );+ auto& mem = memdata.data[v.second];+ mem.SetTimeThreadFree( time, thread );+ mem.csFree.SetVal( cs );+ memdata.usage -= mem.Size();+ MemAllocChanged( memdata, time );+ }++ memdata.active.clear();+ assert( memdata.usage == 0 );+}++void Worker::ProcessCallstackSerial()+{+ assert( m_pendingCallstackId != 0 );+ assert( m_serialNextCallstack == 0 );+ m_serialNextCallstack = m_pendingCallstackId;+ m_pendingCallstackId = 0;+}++void Worker::ProcessCallstack()+{+ assert( m_pendingCallstackId != 0 );+ auto td = GetCurrentThreadData();+ auto it = m_nextCallstack.find( td->id );+ if( it == m_nextCallstack.end() ) it = m_nextCallstack.emplace( td->id, 0 ).first;+ assert( it->second == 0 );+ it->second = m_pendingCallstackId;+ m_pendingCallstackId = 0;+}++void Worker::ProcessCallstackSampleInsertSample( const SampleData& sd, ThreadData& td )+{+ const auto t = sd.time.Val();+ if( td.samples.empty() )+ {+ td.samples.push_back( sd );+ }+ else if( t != 0 && td.samples.back().time.Val() >= t )+ {+ m_inconsistentSamples = true;+ auto it = std::lower_bound( td.samples.begin(), td.samples.end(), t, []( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs; } );+ assert( it != td.samples.end() );+ if( it->time.Val() != t )+ {+ td.samples.push_back_non_empty( sd );+ }+ else+ {+ const auto mcs = MergeCallstacks( it->callstack.Val(), sd.callstack.Val() );+ it->callstack.SetVal( mcs );++ // This is a fixup of an already processed sample. Fixing stats is non-trivial, so just exit here.+ return;+ }+ }+ else+ {+ td.samples.push_back_non_empty( sd );+ }++ const auto callstack = sd.callstack.Val();+ const auto& cs = GetCallstack( callstack );+ const auto& ip = cs[0];+ if( GetCanonicalPointer( ip ) >> 63 != 0 ) td.kernelSampleCnt++;+ m_data.samplesCnt++;+}++void Worker::ProcessCallstackSampleImpl( const SampleData& sd, ThreadData& td )+{+ ProcessCallstackSampleInsertSample( sd, td );++#ifndef TRACY_NO_STATISTICS+ const auto t = sd.time.Val();+ if( t == 0 || !m_identifySamples )+ {+ ProcessCallstackSampleImplStats( sd, td );+ }+ else+ {+ bool postpone = false;+ auto ctx = GetContextSwitchData( td.id );+ if( !ctx )+ {+ postpone = true;+ }+ else+ {+ auto it = std::lower_bound( ctx->v.begin(), ctx->v.end(), sd.time.Val(), [] ( const auto& l, const auto& r ) { return (uint64_t)l.End() < (uint64_t)r; } );+ if( it == ctx->v.end() )+ {+ postpone = true;+ }+ else if( sd.time.Val() == it->Start() )+ {+ td.ctxSwitchSamples.push_back( sd );+ }+ else+ {+ ProcessCallstackSampleImplStats( sd, td );+ }+ }+ if( postpone )+ {+ td.postponedSamples.push_back( sd );+ }+ }+#endif+}++#ifndef TRACY_NO_STATISTICS+void Worker::ProcessCallstackSampleImplStats( const SampleData& sd, ThreadData& td )+{+ const auto t = sd.time.Val();+ const auto callstack = sd.callstack.Val();+ const auto& cs = GetCallstack( callstack );+ const auto& ip = cs[0];++ uint16_t tid = CompressThread( td.id );++ auto frame = GetCallstackFrame( ip );+ if( frame )+ {+ const auto symAddr = frame->data[0].symAddr;+ auto it = m_data.instructionPointersMap.find( symAddr );+ if( it == m_data.instructionPointersMap.end() )+ {+ m_data.instructionPointersMap.emplace( symAddr, unordered_flat_map<CallstackFrameId, uint32_t, CallstackFrameIdHash, CallstackFrameIdCompare> { { ip, 1 } } );+ }+ else+ {+ auto fit = it->second.find( ip );+ if( fit == it->second.end() )+ {+ it->second.emplace( ip, 1 );+ }+ else+ {+ fit->second++;+ }+ }+ auto sit = m_data.symbolSamples.find( symAddr );+ if( sit == m_data.symbolSamples.end() )+ {+ m_data.symbolSamples.emplace( symAddr, Vector<SampleDataRange>( SampleDataRange { sd.time, tid, ip } ) );+ }+ else+ {+ if( sit->second.back().time.Val() <= sd.time.Val() )+ {+ sit->second.push_back_non_empty( SampleDataRange { sd.time, tid, ip } );+ }+ else+ {+ auto iit = std::upper_bound( sit->second.begin(), sit->second.end(), sd.time.Val(), [] ( const auto& lhs, const auto& rhs ) { return lhs < rhs.time.Val(); } );+ sit->second.insert( iit, SampleDataRange { sd.time, tid, ip } );+ }+ }+ }+ else+ {+ auto it = m_data.pendingInstructionPointers.find( ip );+ if( it == m_data.pendingInstructionPointers.end() )+ {+ m_data.pendingInstructionPointers.emplace( ip, 1 );+ }+ else+ {+ it->second++;+ }+ auto sit = m_data.pendingSymbolSamples.find( ip );+ if( sit == m_data.pendingSymbolSamples.end() )+ {+ m_data.pendingSymbolSamples.emplace( ip, Vector<SampleDataRange>( SampleDataRange { sd.time, tid, ip } ) );+ }+ else+ {+ sit->second.push_back_non_empty( SampleDataRange { sd.time, tid, ip } );+ }+ }++ auto childAddr = GetCanonicalPointer( cs[0] );+ for( uint16_t i=1; i<cs.size(); i++ )+ {+ auto addr = GetCanonicalPointer( cs[i] );+ auto it = m_data.childSamples.find( addr );+ if( it == m_data.childSamples.end() )+ {+ m_data.childSamples.emplace( addr, Vector<ChildSample>( ChildSample { sd.time, childAddr } ) );+ }+ else+ {+ it->second.push_back_non_empty( ChildSample { sd.time, childAddr } );+ }+ childAddr = addr;+ }++ const auto framesKnown = UpdateSampleStatistics( callstack, 1, true );++ if( t != 0 )+ {+ //assert( td.samples.size() > td.ghostIdx );+ if( framesKnown && td.ghostIdx + 1 == td.samples.size() )+ {+ td.ghostIdx++;+ m_data.ghostCnt += AddGhostZone( cs, &td.ghostZones, t );+ }+ else+ {+ m_data.ghostZonesPostponed = true;+ }+ }+}+#endif++void Worker::ProcessCallstackSample( const QueueCallstackSample& ev )+{+ assert( m_pendingCallstackId != 0 );+ const auto callstack = m_pendingCallstackId;+ m_pendingCallstackId = 0;++ const auto refTime = RefTime( m_refTimeCtx, ev.time );+ const auto t = refTime == 0 ? 0 : TscTime( refTime );+ if( m_data.lastTime < t ) m_data.lastTime = t;++ auto& td = *NoticeThread( ev.thread );++ SampleData sd;+ sd.time.SetVal( t );+ sd.callstack.SetVal( callstack );++ if( m_combineSamples && t != 0 )+ {+ const auto pendingTime = td.pendingSample.time.Val();+ if( pendingTime == 0 )+ {+ td.pendingSample = sd;+ }+ else+ {+ if( pendingTime == t )+ {+ const auto mcs = MergeCallstacks( td.pendingSample.callstack.Val(), callstack );+ sd.callstack.SetVal( mcs );+ ProcessCallstackSampleImpl( sd, td );+ td.pendingSample.time.Clear();+ }+ else+ {+ ProcessCallstackSampleImpl( td.pendingSample, td );+ td.pendingSample = sd;+ }+ }+ }+ else+ {+ ProcessCallstackSampleImpl( sd, td );+ }+}++void Worker::ProcessCallstackSampleContextSwitch( const QueueCallstackSample& ev )+{+ assert( m_pendingCallstackId != 0 );+ const auto callstack = m_pendingCallstackId;+ m_pendingCallstackId = 0;++ const auto refTime = RefTime( m_refTimeCtx, ev.time );+ const auto t = refTime == 0 ? 0 : TscTime( refTime );+ if( m_data.lastTime < t ) m_data.lastTime = t;++ auto& td = *NoticeThread( ev.thread );++ SampleData sd;+ sd.time.SetVal( t );+ sd.callstack.SetVal( callstack );++ ProcessCallstackSampleInsertSample( sd, td );++ td.ctxSwitchSamples.push_back( sd );+}++void Worker::ProcessCallstackFrameSize( const QueueCallstackFrameSize& ev )+{+ assert( !m_callstackFrameStaging );+ assert( m_pendingCallstackSubframes == 0 );+ assert( m_pendingCallstackFrames > 0 );+ m_pendingCallstackFrames--;+ m_pendingCallstackSubframes = ev.size;+#ifndef TRACY_NO_STATISTICS+ m_data.newFramesWereReceived = true;+#endif++ const auto idx = GetSingleStringIdx();++ // Frames may be duplicated due to recursion+ auto fmit = m_data.callstackFrameMap.find( PackPointer( ev.ptr ) );+ if( fmit == m_data.callstackFrameMap.end() )+ {+ m_callstackFrameStaging = m_slab.Alloc<CallstackFrameData>();+ m_callstackFrameStaging->size = ev.size;+ m_callstackFrameStaging->data = m_slab.Alloc<CallstackFrame>( ev.size );+ m_callstackFrameStaging->imageName = StringIdx( idx );++ m_callstackFrameStagingPtr = ev.ptr;+ }+}++void Worker::ProcessCallstackFrame( const QueueCallstackFrame& ev, bool querySymbols )+{+ assert( m_pendingCallstackSubframes > 0 );++ const auto nitidx = GetSingleStringIdx();+ const auto fitidx = GetSecondStringIdx();++ if( m_callstackFrameStaging )+ {+ const auto idx = m_callstackFrameStaging->size - m_pendingCallstackSubframes;+ const auto file = StringIdx( fitidx );++ if( m_pendingCallstackSubframes > 1 && idx == 0 )+ {+ auto fstr = GetString( file );+ auto flen = strlen( fstr );+ if( flen >= s_tracySkipSubframesMinLen )+ {+ auto ptr = s_tracySkipSubframes;+ do+ {+ if( flen >= ptr->len && memcmp( fstr + flen - ptr->len, ptr->str, ptr->len ) == 0 )+ {+ m_pendingCallstackSubframes--;+ m_callstackFrameStaging->size--;+ return;+ }+ ptr++;+ }+ while( ptr->str );+ }+ }++ const auto name = StringIdx( nitidx );+ m_callstackFrameStaging->data[idx].name = name;+ m_callstackFrameStaging->data[idx].file = file;+ m_callstackFrameStaging->data[idx].line = ev.line;+ m_callstackFrameStaging->data[idx].symAddr = ev.symAddr;++ if( querySymbols && ev.symAddr != 0 && m_data.symbolMap.find( ev.symAddr ) == m_data.symbolMap.end() && m_pendingSymbols.find( ev.symAddr ) == m_pendingSymbols.end() )+ {+ m_pendingSymbols.emplace( ev.symAddr, SymbolPending { name, m_callstackFrameStaging->imageName, file, ev.line, ev.symLen, idx < m_callstackFrameStaging->size - 1 } );+ Query( ServerQuerySymbol, ev.symAddr );+ }++ StringRef ref( StringRef::Idx, fitidx );+ auto cit = m_checkedFileStrings.find( ref );+ if( cit == m_checkedFileStrings.end() ) CacheSource( ref, m_callstackFrameStaging->imageName );++ const auto frameId = PackPointer( m_callstackFrameStagingPtr );+#ifndef TRACY_NO_STATISTICS+ auto it = m_data.pendingInstructionPointers.find( frameId );+ if( it != m_data.pendingInstructionPointers.end() )+ {+ if( ev.symAddr != 0 )+ {+ auto sit = m_data.instructionPointersMap.find( ev.symAddr );+ if( sit == m_data.instructionPointersMap.end() )+ {+ m_data.instructionPointersMap.emplace( ev.symAddr, unordered_flat_map<CallstackFrameId, uint32_t, CallstackFrameIdHash, CallstackFrameIdCompare> { { it->first, it->second } } );+ }+ else+ {+ assert( sit->second.find( it->first ) == sit->second.end() );+ sit->second.emplace( it->first, it->second );+ }+ }+ m_data.pendingInstructionPointers.erase( it );+ }+ auto pit = m_data.pendingSymbolSamples.find( frameId );+ if( pit != m_data.pendingSymbolSamples.end() )+ {+ if( ev.symAddr != 0 )+ {+ auto sit = m_data.symbolSamples.find( ev.symAddr );+ if( sit == m_data.symbolSamples.end() )+ {+ pdqsort_branchless( pit->second.begin(), pit->second.end(), [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs.time.Val(); } );+ m_data.symbolSamples.emplace( ev.symAddr, std::move( pit->second ) );+ }+ else+ {+ for( auto& v : pit->second )+ {+ if( sit->second.back().time.Val() <= v.time.Val() )+ {+ sit->second.push_back_non_empty( v );+ }+ else+ {+ auto iit = std::upper_bound( sit->second.begin(), sit->second.end(), v.time.Val(), [] ( const auto& lhs, const auto& rhs ) { return lhs < rhs.time.Val(); } );+ sit->second.insert( iit, v );+ }+ }+ }+ }+ m_data.pendingSymbolSamples.erase( pit );+ }+#endif++ if( --m_pendingCallstackSubframes == 0 )+ {+ assert( m_data.callstackFrameMap.find( frameId ) == m_data.callstackFrameMap.end() );+ m_data.callstackFrameMap.emplace( frameId, m_callstackFrameStaging );+ m_data.codeSymbolMap.emplace( m_callstackFrameStagingPtr, m_callstackFrameStaging->data[0].symAddr );+ m_callstackFrameStaging = nullptr;+ }+ }+ else+ {+ m_pendingCallstackSubframes--;+ }+}++void Worker::ProcessSymbolInformation( const QueueSymbolInformation& ev )+{+ auto it = m_pendingSymbols.find( ev.symAddr );+ assert( it != m_pendingSymbols.end() );++ const auto idx = GetSingleStringIdx();++ SymbolData sd;+ sd.name = it->second.name;+ sd.file = StringIdx( idx );+ sd.line = ev.line;+ sd.imageName = it->second.imageName;+ sd.callFile = it->second.file;+ sd.callLine = it->second.line;+ sd.isInline = it->second.isInline;+ sd.size.SetVal( it->second.size );+ m_data.symbolMap.emplace( ev.symAddr, sd );++ if( m_codeTransfer && it->second.size > 0 && it->second.size <= 128*1024 )+ {+ m_pendingSymbolCode++;+ Query( ServerQuerySymbolCode, ev.symAddr, it->second.size );+ }++ if( !it->second.isInline )+ {+ if( m_data.newSymbolsIndex < 0 ) m_data.newSymbolsIndex = int64_t( m_data.symbolLoc.size() );+ m_data.symbolLoc.push_back( SymbolLocation { ev.symAddr, it->second.size } );+ }+ else+ {+ if( m_data.newInlineSymbolsIndex < 0 ) m_data.newInlineSymbolsIndex = int64_t( m_data.symbolLocInline.size() );+ m_data.symbolLocInline.push_back( ev.symAddr );+ }++ StringRef ref( StringRef::Idx, idx );+ auto cit = m_checkedFileStrings.find( ref );+ if( cit == m_checkedFileStrings.end() ) CacheSource( ref, it->second.imageName );++ m_pendingSymbols.erase( it );+}++void Worker::ProcessCrashReport( const QueueCrashReport& ev )+{+ CheckString( ev.text );++ auto td = GetCurrentThreadData();+ m_data.crashEvent.thread = td->id;+ m_data.crashEvent.time = TscTime( ev.time );+ m_data.crashEvent.message = ev.text;++ auto it = m_nextCallstack.find( td->id );+ if( it != m_nextCallstack.end() && it->second != 0 )+ {+ m_data.crashEvent.callstack = it->second;+ it->second = 0;+ }+ else+ {+ m_data.crashEvent.callstack = 0;+ }+}++void Worker::ProcessSysTime( const QueueSysTime& ev )+{+ const auto time = TscTime( ev.time );+ if( m_data.lastTime < time ) m_data.lastTime = time;+ const auto val = ev.sysTime;+ if( !m_sysTimePlot )+ {+ m_sysTimePlot = m_slab.AllocInit<PlotData>();+ m_sysTimePlot->name = 0;+ m_sysTimePlot->type = PlotType::SysTime;+ m_sysTimePlot->format = PlotValueFormatting::Percentage;+ m_sysTimePlot->showSteps = false;+ m_sysTimePlot->fill = true;+ m_sysTimePlot->color = 0;+ m_sysTimePlot->min = val;+ m_sysTimePlot->max = val;+ m_sysTimePlot->sum = val;+ m_sysTimePlot->data.push_back( { time, val } );+ m_data.plots.Data().push_back( m_sysTimePlot );+ }+ else+ {+ assert( !m_sysTimePlot->data.empty() );+ assert( m_sysTimePlot->data.back().time.Val() <= time );+ if( m_sysTimePlot->min > val ) m_sysTimePlot->min = val;+ else if( m_sysTimePlot->max < val ) m_sysTimePlot->max = val;+ m_sysTimePlot->sum += val;+ m_sysTimePlot->data.push_back( { time, val } );+ }+}++void Worker::ProcessSysPower( const QueueSysPower& ev )+{+ const auto time = TscTime( ev.time );+ auto it = m_powerData.find( ev.name );+ if( it == m_powerData.end() )+ {+ CheckString( ev.name );+ PlotData* plot = m_slab.AllocInit<PlotData>();+ plot->name = ev.name;+ plot->type = PlotType::Power;+ plot->format = PlotValueFormatting::Watt;+ plot->showSteps = false;+ plot->fill = true;+ plot->color = 0;+ m_data.plots.Data().push_back( plot );+ m_powerData.emplace( ev.name, PowerData { time, plot } );+ }+ else+ {+ const auto dt = time - it->second.lastTime;+ it->second.lastTime = time;+ if( m_data.lastTime < time ) m_data.lastTime = time;+ // ev.delta is Microjoule, dt is nanoseconds+ // power is Watt = J / s+ const auto power = ev.delta * 1000. / dt;+ InsertPlot( it->second.plot, time, power );+ }+}++void Worker::ProcessContextSwitch( const QueueContextSwitch& ev )+{+#ifndef TRACY_NO_STATISTICS+ m_data.newContextSwitchesReceived = true;+#endif++ const auto time = TscTime( RefTime( m_refTimeCtx, ev.time ) );+ if( m_data.lastTime < time ) m_data.lastTime = time;++ if( ev.cpu >= m_data.cpuDataCount ) m_data.cpuDataCount = ev.cpu + 1;+ auto& cs = m_data.cpuData[ev.cpu].cs;+ if( ev.oldThread != 0 )+ {+ auto it = m_data.ctxSwitch.find( ev.oldThread );+ if( it != m_data.ctxSwitch.end() )+ {+ auto& data = it->second->v;+ assert( !data.empty() );+ auto& item = data.back();+ assert( item.Start() <= time );+ assert( item.End() == -1 );+ //TODO: It may happen that events are being dropped (for example due to breaking in the debugger, or we are simply too slow to handle the events)+ // We should handle this properly in some way, but it is unclear how. We can't even really detect it properly here other than when cpu doesn't match.+ // Something could be displayed onscreen when gaps are detected at the event ringbuffer level?+ item.SetEnd( time );+ item.SetReason( ev.oldThreadWaitReason );+ item.SetState( ev.oldThreadState );++ const auto dt = time - item.Start();+ it->second->runningTime += dt;++ auto tdit = m_data.cpuThreadData.find( ev.oldThread );+ if( tdit == m_data.cpuThreadData.end() )+ {+ tdit = m_data.cpuThreadData.emplace( ev.oldThread, CpuThreadData {} ).first;+ }+ tdit->second.runningRegions++;+ tdit->second.runningTime += dt;+ }+ if( !cs.empty() )+ {+ auto& cx = cs.back();+ assert( m_data.externalThreadCompress.DecompressThread( cx.Thread() ) == ev.oldThread );+ cx.SetEnd( time );+ }+ }+ if( ev.newThread != 0 )+ {+ auto it = m_data.ctxSwitch.find( ev.newThread );+ if( it == m_data.ctxSwitch.end() )+ {+ auto ctx = m_slab.AllocInit<ContextSwitch>();+ it = m_data.ctxSwitch.emplace( ev.newThread, ctx ).first;+ }+ auto& data = it->second->v;+ ContextSwitchData* item = nullptr;+ bool migration = false;+ if( !data.empty() && data.back().Reason() == ContextSwitchData::Wakeup )+ {+ item = &data.back();+ if( data.size() > 1 )+ {+ migration = data[data.size()-2].Cpu() != ev.cpu;+ }+ }+ else+ {+ assert( data.empty() || (uint64_t)data.back().End() <= (uint64_t)time );+ if( !data.empty() )+ {+ migration = data.back().Cpu() != ev.cpu;+ }+ item = &data.push_next();+ item->SetWakeup( time );+ item->SetWakeupCpu( ev.cpu );++ if ( it->second->pendingWakeUp.time != 0 )+ {+ auto wakeupTime = it->second->pendingWakeUp.time;+ if ( data.size() > 1 )+ {+ // Sometimes the OS tell us it scheduled a thread that was still alive but on the+ // verge of being switched out. We thus end up with `wakeup < switchout`. + // So instead, compare with the previous wakeup.+ const auto previousWakeup = data[data.size() - 2].WakeupVal();+ if ( previousWakeup <= wakeupTime && wakeupTime <= time )+ {+ item->SetWakeup( wakeupTime );+ item->SetWakeupCpu( it->second->pendingWakeUp.cpu );+ it->second->pendingWakeUp.time = 0;+ }+ }+ }+ }+ item->SetStart( time );+ item->SetEnd( -1 );+ item->SetCpu( ev.cpu );+ item->SetReason( -1 );+ item->SetState( -1 );+ item->SetThread( 0 );++ auto& cx = cs.push_next();+ cx.SetStart( time );+ cx.SetEnd( -1 );+ cx.SetThread( m_data.externalThreadCompress.CompressThread( ev.newThread ) );++ CheckExternalName( ev.newThread );++ if( migration )+ {+ auto tdit = m_data.cpuThreadData.find( ev.newThread );+ if( tdit == m_data.cpuThreadData.end() )+ {+ tdit = m_data.cpuThreadData.emplace( ev.newThread, CpuThreadData {} ).first;+ }+ tdit->second.migrations++;+ }+ }+}++void Worker::ProcessThreadWakeup( const QueueThreadWakeup& ev )+{+ const auto time = TscTime( RefTime( m_refTimeCtx, ev.time ) );+ if( m_data.lastTime < time ) m_data.lastTime = time;++ auto it = m_data.ctxSwitch.find( ev.thread );+ if( it == m_data.ctxSwitch.end() )+ {+ auto ctx = m_slab.AllocInit<ContextSwitch>();+ it = m_data.ctxSwitch.emplace( ev.thread, ctx ).first;+ }+ auto& data = it->second->v;+ if( !data.empty() && !data.back().IsEndValid() )+ {+ // We received the wakeup before thread switches out. This can actually happen!+ // So instead of dropping the information, keep the last one around so that we+ // may fetch it once the thread actually switches out.+ // We rely on the fact we won't get another one in the meantime.+ auto& item = data.back();+ it->second->pendingWakeUp.time = time;+ it->second->pendingWakeUp.cpu = ev.cpu;+ return;+ }+ else+ {+ auto& item = data.push_next();+ item.SetWakeupCpu( ev.cpu );+ item.SetWakeup( time );+ item.SetStart( time );+ item.SetEnd( -1 );+ item.SetCpu( 0 );+ item.SetReason( ContextSwitchData::Wakeup );+ item.SetState( -1 );+ item.SetThread( 0 );+ //TODO: Adjust reason + adjust count instead of thread which is unused?+ // Adjust Reason 1 => Unwait+ // Adjust Reason 2 => Boost+ }+}++void Worker::ProcessTidToPid( const QueueTidToPid& ev )+{+ if( m_data.tidToPid.find( ev.tid ) == m_data.tidToPid.end() ) m_data.tidToPid.emplace( ev.tid, ev.pid );+}++void Worker::ProcessHwSampleCpuCycle( const QueueHwSample& ev )+{+ const auto time = ev.time == 0 ? 0 : TscTime( ev.time );+ if( m_data.lastTime < time ) m_data.lastTime = time;+ auto it = m_data.hwSamples.find( ev.ip );+ if( it == m_data.hwSamples.end() ) it = m_data.hwSamples.emplace( ev.ip, HwSampleData {} ).first;+ it->second.cycles.push_back( time );+}++void Worker::ProcessHwSampleInstructionRetired( const QueueHwSample& ev )+{+ const auto time = ev.time == 0 ? 0 : TscTime( ev.time );+ if( m_data.lastTime < time ) m_data.lastTime = time;+ auto it = m_data.hwSamples.find( ev.ip );+ if( it == m_data.hwSamples.end() ) it = m_data.hwSamples.emplace( ev.ip, HwSampleData {} ).first;+ it->second.retired.push_back( time );+}++void Worker::ProcessHwSampleCacheReference( const QueueHwSample& ev )+{+ const auto time = ev.time == 0 ? 0 : TscTime( ev.time );+ if( m_data.lastTime < time ) m_data.lastTime = time;+ auto it = m_data.hwSamples.find( ev.ip );+ if( it == m_data.hwSamples.end() ) it = m_data.hwSamples.emplace( ev.ip, HwSampleData {} ).first;+ it->second.cacheRef.push_back( time );+}++void Worker::ProcessHwSampleCacheMiss( const QueueHwSample& ev )+{+ const auto time = ev.time == 0 ? 0 : TscTime( ev.time );+ if( m_data.lastTime < time ) m_data.lastTime = time;+ auto it = m_data.hwSamples.find( ev.ip );+ if( it == m_data.hwSamples.end() ) it = m_data.hwSamples.emplace( ev.ip, HwSampleData {} ).first;+ it->second.cacheMiss.push_back( time );+}++void Worker::ProcessHwSampleBranchRetired( const QueueHwSample& ev )+{+ const auto time = ev.time == 0 ? 0 : TscTime( ev.time );+ if( m_data.lastTime < time ) m_data.lastTime = time;+ auto it = m_data.hwSamples.find( ev.ip );+ if( it == m_data.hwSamples.end() ) it = m_data.hwSamples.emplace( ev.ip, HwSampleData {} ).first;+ it->second.branchRetired.push_back( time );+ m_data.hasBranchRetirement = true;+}++void Worker::ProcessHwSampleBranchMiss( const QueueHwSample& ev )+{+ const auto time = ev.time == 0 ? 0 : TscTime( ev.time );+ if( m_data.lastTime < time ) m_data.lastTime = time;+ auto it = m_data.hwSamples.find( ev.ip );+ if( it == m_data.hwSamples.end() ) it = m_data.hwSamples.emplace( ev.ip, HwSampleData {} ).first;+ it->second.branchMiss.push_back( time );+}++void Worker::ProcessParamSetup( const QueueParamSetup& ev )+{+ CheckString( ev.name );+ m_params.push_back( Parameter { ev.idx, StringRef( StringRef::Ptr, ev.name ), bool( ev.isBool ), ev.val } );+}++void Worker::ProcessSourceCodeNotAvailable( const QueueSourceCodeNotAvailable& ev )+{+ auto it = m_sourceCodeQuery.find( ev.id );+ assert( it != m_sourceCodeQuery.end() );+ m_sourceCodeQuery.erase( it );+}++void Worker::ProcessCpuTopology( const QueueCpuTopology& ev )+{+ auto package = m_data.cpuTopology.find( ev.package );+ if( package == m_data.cpuTopology.end() ) package = m_data.cpuTopology.emplace( ev.package, unordered_flat_map<uint32_t, unordered_flat_map<uint32_t, std::vector<uint32_t>>> {} ).first;++ auto die = package->second.find( ev.die );+ if( die == package->second.end() ) die = package->second.emplace( ev.die, unordered_flat_map<uint32_t, std::vector<uint32_t>> {} ).first;++ auto core = die->second.find( ev.core );+ if( core == die->second.end() ) core = die->second.emplace( ev.core, std::vector<uint32_t> {} ).first;+ core->second.emplace_back( ev.thread );++ assert( m_data.cpuTopologyMap.find( ev.thread ) == m_data.cpuTopologyMap.end() );+ m_data.cpuTopologyMap.emplace( ev.thread, CpuThreadTopology { ev.package, ev.die, ev.core } );+}++void Worker::ProcessMemNamePayload( const QueueMemNamePayload& ev )+{+ assert( m_memNamePayload == 0 );+ m_memNamePayload = ev.name;+}++void Worker::ProcessThreadGroupHint( const QueueThreadGroupHint& ev )+{+ auto td = RetrieveThread( ev.thread );+ assert( td );+ td->groupHint = ev.groupHint;+ m_pendingThreadHints.emplace_back( ev.thread );+}++void Worker::ProcessFiberEnter( const QueueFiberEnter& ev )+{+ const auto t = TscTime( RefTime( m_refTimeThread, ev.time ) );+ if( m_data.lastTime < t ) m_data.lastTime = t;++ uint64_t tid;+ auto it = m_data.fiberToThreadMap.find( ev.fiber );+ if( it == m_data.fiberToThreadMap.end() )+ {+ tid = ( uint64_t(1) << 32 ) | m_data.fiberToThreadMap.size();+ m_data.fiberToThreadMap.emplace( ev.fiber, tid );+ NewThread( tid, true, ev.groupHint );+ CheckFiberName( ev.fiber, tid );+ }+ else+ {+ tid = it->second;+ }++ auto td = NoticeThread( ev.thread );+ if( td->fiber )+ {+ auto cit = m_data.ctxSwitch.find( td->fiber->id );+ assert( cit != m_data.ctxSwitch.end() );+ auto& data = cit->second->v;+ assert( !data.empty() );+ auto& item = data.back();+ item.SetEnd( t );+ }+ td->fiber = RetrieveThread( tid );+ assert( td->fiber );++ auto cit = m_data.ctxSwitch.find( tid );+ if( cit == m_data.ctxSwitch.end() )+ {+ auto ctx = m_slab.AllocInit<ContextSwitch>();+ cit = m_data.ctxSwitch.emplace( tid, ctx ).first;+ }+ auto& data = cit->second->v;+ auto& item = data.push_next();+ item.SetCpu( t );+ item.SetCpu( 0 );+ item.SetWakeup( t );+ item.SetWakeupCpu( 0 );+ item.SetEnd( -1 );+ item.SetReason( ContextSwitchData::Fiber );+ item.SetState( -1 );+ item.SetThread( CompressThread( ev.thread ) );+}++void Worker::ProcessFiberLeave( const QueueFiberLeave& ev )+{+ const auto t = TscTime( RefTime( m_refTimeThread, ev.time ) );+ if( m_data.lastTime < t ) m_data.lastTime = t;++ auto td = RetrieveThread( ev.thread );+ if( !td->fiber )+ {+ FiberLeaveFailure();+ return;+ }++ auto cit = m_data.ctxSwitch.find( td->fiber->id );+ assert( cit != m_data.ctxSwitch.end() );+ auto& data = cit->second->v;+ assert( !data.empty() );+ auto& item = data.back();+ item.SetEnd( t );++ const auto dt = t - item.Start();+ cit->second->runningTime += dt;++ td->fiber = nullptr;+}++void Worker::MemAllocChanged( MemData& memdata, int64_t time )+{+ const auto val = (double)memdata.usage;+ if( !memdata.plot )+ {+ CreateMemAllocPlot( memdata );+ memdata.plot->min = val;+ memdata.plot->max = val;+ memdata.plot->sum = val;+ memdata.plot->data.push_back( { time, val } );+ }+ else+ {+ assert( !memdata.plot->data.empty() );+ assert( memdata.plot->data.back().time.Val() <= time );+ if( memdata.plot->min > val ) memdata.plot->min = val;+ else if( memdata.plot->max < val ) memdata.plot->max = val;+ memdata.plot->sum += val;+ memdata.plot->data.push_back( { time, val } );+ }+}++void Worker::CreateMemAllocPlot( MemData& memdata )+{+ assert( !memdata.plot );+ memdata.plot = m_slab.AllocInit<PlotData>();+ memdata.plot->name = memdata.name;+ memdata.plot->type = PlotType::Memory;+ memdata.plot->format = PlotValueFormatting::Memory;+ memdata.plot->showSteps = true;+ memdata.plot->fill = true;+ memdata.plot->color = 0;+ memdata.plot->data.push_back( { GetFirstTime(), 0. } );+ m_data.plots.Data().push_back( memdata.plot );+}++void Worker::ReconstructMemAllocPlot( MemData& mem )+{+#ifdef __EMSCRIPTEN__+ pdqsort_branchless( mem.frees.begin(), mem.frees.end(), [&mem] ( const auto& lhs, const auto& rhs ) { return mem.data[lhs].TimeFree() < mem.data[rhs].TimeFree(); } );+#else+ ppqsort::sort( ppqsort::execution::par, mem.frees.begin(), mem.frees.end(), [&mem] ( const auto& lhs, const auto& rhs ) { return mem.data[lhs].TimeFree() < mem.data[rhs].TimeFree(); } );+#endif++ const auto psz = mem.data.size() + mem.frees.size() + 1;++ PlotData* plot;+ {+ std::lock_guard<std::mutex> lock( m_data.lock );+ plot = m_slab.AllocInit<PlotData>();+ plot->data.reserve_exact( psz, m_slab );+ }++ plot->name = mem.name;+ plot->type = PlotType::Memory;+ plot->format = PlotValueFormatting::Memory;+ plot->showSteps = true;+ plot->fill = true;+ plot->color = 0;++ auto aptr = mem.data.begin();+ auto aend = mem.data.end();+ auto fptr = mem.frees.begin();+ auto fend = mem.frees.end();++ double sum = 0;+ double max = 0;+ double usage = 0;++ auto ptr = plot->data.data();+ ptr->time = GetFirstTime();+ ptr->val = 0;+ ptr++;++ if( aptr != aend && fptr != fend )+ {+ auto atime = aptr->TimeAlloc();+ auto ftime = mem.data[*fptr].TimeFree();++ for(;;)+ {+ if( atime < ftime )+ {+ usage += int64_t( aptr->Size() );+ assert( usage >= 0 );+ if( max < usage ) max = usage;+ sum += usage;+ ptr->time = atime;+ ptr->val = usage;+ ptr++;+ aptr++;+ if( aptr == aend ) break;+ atime = aptr->TimeAlloc();+ }+ else+ {+ usage -= int64_t( mem.data[*fptr].Size() );+ assert( usage >= 0 );+ if( max < usage ) max = usage;+ sum += usage;+ ptr->time = ftime;+ ptr->val = usage;+ ptr++;+ fptr++;+ if( fptr == fend ) break;+ ftime = mem.data[*fptr].TimeFree();+ }+ }+ }++ while( aptr != aend )+ {+ assert( aptr->TimeFree() < 0 );+ int64_t time = aptr->TimeAlloc();+ usage += int64_t( aptr->Size() );+ assert( usage >= 0 );+ if( max < usage ) max = usage;+ sum += usage;+ ptr->time = time;+ ptr->val = usage;+ ptr++;+ aptr++;+ }+ while( fptr != fend )+ {+ const auto& memData = mem.data[*fptr];+ int64_t time = memData.TimeFree();+ usage -= int64_t( memData.Size() );+ assert( usage >= 0 );+ assert( max >= usage );+ sum += usage;+ ptr->time = time;+ ptr->val = usage;+ ptr++;+ fptr++;+ }++ plot->min = 0;+ plot->max = max;+ plot->sum = sum;++ std::lock_guard<std::mutex> lock( m_data.lock );+ m_data.plots.Data().insert( m_data.plots.Data().begin(), plot );+ mem.plot = plot;+}++#ifndef TRACY_NO_STATISTICS+void Worker::ReconstructContextSwitchUsage()+{+ assert( m_data.cpuDataCount != 0 );+ const auto cpucnt = m_data.cpuDataCount;++ auto& vec = m_data.ctxUsage;+ vec.push_back( ContextSwitchUsage( 0, 0, 0 ) );++ struct Cpu+ {+ bool startDone;+ Vector<ContextSwitchCpu>::iterator it;+ Vector<ContextSwitchCpu>::iterator end;+ };+ std::vector<Cpu> cpus;+ cpus.reserve( cpucnt );+ for( int i=0; i<cpucnt; i++ )+ {+ cpus.emplace_back( Cpu { false, m_data.cpuData[i].cs.begin(), m_data.cpuData[i].cs.end() } );+ }++ uint8_t other = 0;+ uint8_t own = 0;+ for(;;)+ {+ int64_t nextTime = std::numeric_limits<int64_t>::max();+ bool atEnd = true;+ for( int i=0; i<cpucnt; i++ )+ {+ if( cpus[i].it != cpus[i].end )+ {+ atEnd = false;+ const auto ct = !cpus[i].startDone ? cpus[i].it->Start() : cpus[i].it->End();+ if( ct < nextTime ) nextTime = ct;+ }+ }+ if( atEnd ) break;+ for( int i=0; i<cpucnt; i++ )+ {+ while( cpus[i].it != cpus[i].end )+ {+ const auto ct = !cpus[i].startDone ? cpus[i].it->Start() : cpus[i].it->End();+ if( nextTime != ct ) break;+ const auto tid = DecompressThreadExternal( cpus[i].it->Thread() );+ const auto isOwn = IsThreadLocal( tid ) || GetPidFromTid( tid ) == m_pid;+ if( !cpus[i].startDone )+ {+ if( isOwn )+ {+ own++;+ assert( own <= cpucnt );+ }+ else+ {+ other++;+ assert( other <= cpucnt );+ }+ if( !cpus[i].it->IsEndValid() )+ {+ cpus[i].it++;+ assert( cpus[i].it == cpus[i].end );+ }+ else+ {+ cpus[i].startDone = true;+ }+ }+ else+ {+ if( isOwn )+ {+ assert( own > 0 );+ own--;+ }+ else+ {+ assert( other > 0 );+ other--;+ }+ cpus[i].startDone = false;+ cpus[i].it++;+ }+ }+ }+ const auto& back = vec.back();+ if( back.Other() != other || back.Own() != own )+ {+ vec.push_back( ContextSwitchUsage( nextTime, other, own ) );+ }+ }++ std::lock_guard<std::mutex> lock( m_data.lock );+ m_data.ctxUsageReady = true;+}++bool Worker::UpdateSampleStatistics( uint32_t callstack, uint32_t count, bool canPostpone )+{+ const auto& cs = GetCallstack( callstack );+ const auto cssz = cs.size();++ auto frames = (const CallstackFrameData**)alloca( cssz * sizeof( CallstackFrameData* ) );+ for( uint16_t i=0; i<cssz; i++ )+ {+ auto frame = GetCallstackFrame( cs[i] );+ if( !frame )+ {+ if( canPostpone )+ {+ auto it = m_data.postponedSamples.find( callstack );+ if( it == m_data.postponedSamples.end() )+ {+ m_data.postponedSamples.emplace( callstack, count );+ }+ else+ {+ it->second += count;+ }+ }+ return false;+ }+ else+ {+ frames[i] = frame;+ }+ }++ if( canPostpone )+ {+ auto it = m_data.postponedSamples.find( callstack );+ if( it != m_data.postponedSamples.end() )+ {+ count += it->second;+ m_data.postponedSamples.erase( it );+ }+ }++ UpdateSampleStatisticsImpl( frames, cssz, count, cs );+ return true;+}++void Worker::UpdateSampleStatisticsPostponed( decltype(Worker::DataBlock::postponedSamples.begin())& it )+{+ const auto& cs = GetCallstack( it->first );+ const auto cssz = cs.size();++ auto frames = (const CallstackFrameData**)alloca( cssz * sizeof( CallstackFrameData* ) );+ for( uint16_t i=0; i<cssz; i++ )+ {+ auto frame = GetCallstackFrame( cs[i] );+ if( !frame )+ {+ ++it;+ return;+ }+ frames[i] = frame;+ }++ UpdateSampleStatisticsImpl( frames, cssz, it->second, cs );+ it = m_data.postponedSamples.erase( it );+}++void Worker::UpdateSampleStatisticsImpl( const CallstackFrameData** frames, uint16_t framesCount, uint32_t count, const VarArray<CallstackFrameId>& cs )+{+ const auto fexcl = frames[0];+ const auto fxsz = fexcl->size;+ const auto& frame0 = fexcl->data[0];+ auto sym0 = m_data.symbolStats.find( frame0.symAddr );+ if( sym0 == m_data.symbolStats.end() ) sym0 = m_data.symbolStats.emplace( frame0.symAddr, SymbolStats { 0, 0 } ).first;+ sym0->second.excl += count;+ for( uint8_t f=1; f<fxsz; f++ )+ {+ const auto& frame = fexcl->data[f];+ auto sym = m_data.symbolStats.find( frame.symAddr );+ if( sym == m_data.symbolStats.end() ) sym = m_data.symbolStats.emplace( frame.symAddr, SymbolStats { 0, 0 } ).first;+ sym->second.incl += count;+ }+ for( uint16_t c=1; c<framesCount; c++ )+ {+ const auto fincl = frames[c];+ const auto fsz = fincl->size;+ for( uint8_t f=0; f<fsz; f++ )+ {+ const auto& frame = fincl->data[f];+ auto sym = m_data.symbolStats.find( frame.symAddr );+ if( sym == m_data.symbolStats.end() ) sym = m_data.symbolStats.emplace( frame.symAddr, SymbolStats { 0, 0 } ).first;+ sym->second.incl += count;+ }+ }++ CallstackFrameId parentFrameId;+ if( fxsz != 1 )+ {+ auto cfdata = (CallstackFrame*)alloca( uint8_t( fxsz-1 ) * sizeof( CallstackFrame ) );+ for( int i=0; i<fxsz-1; i++ )+ {+ cfdata[i] = fexcl->data[i+1];+ }+ CallstackFrameData cfd;+ cfd.data = cfdata;+ cfd.size = fxsz-1;+ cfd.imageName = fexcl->imageName;++ auto it = m_data.revParentFrameMap.find( &cfd );+ if( it == m_data.revParentFrameMap.end() )+ {+ auto frame = m_slab.Alloc<CallstackFrame>( fxsz-1 );+ memcpy( frame, cfdata, ( fxsz-1 ) * sizeof( CallstackFrame ) );+ auto frameData = m_slab.AllocInit<CallstackFrameData>();+ frameData->data = frame;+ frameData->size = fxsz - 1;+ frameData->imageName = fexcl->imageName;+ parentFrameId.idx = m_callstackParentNextIdx++;+ parentFrameId.sel = 0;+ parentFrameId.custom = 1;+ m_data.parentCallstackFrameMap.emplace( parentFrameId, frameData );+ m_data.revParentFrameMap.emplace( frameData, parentFrameId );+ }+ else+ {+ parentFrameId = it->second;+ }+ }++ uint32_t parentIdx;+ {+ const auto sz = framesCount - ( fxsz == 1 );+ const auto memsize = sizeof( VarArray<CallstackFrameId> ) + sz * sizeof( CallstackFrameId );+ auto mem = (char*)m_slab.AllocRaw( memsize );++ auto data = (CallstackFrameId*)mem;+ auto dst = data;+ if( fxsz == 1 )+ {+ for( int i=0; i<sz; i++ )+ {+ *dst++ = cs[i+1];+ }+ }+ else+ {+ *dst++ = parentFrameId;+ for( int i=1; i<sz; i++ )+ {+ *dst++ = cs[i];+ }+ }++ auto arr = (VarArray<CallstackFrameId>*)( mem + sz * sizeof( CallstackFrameId ) );+ new(arr) VarArray<CallstackFrameId>( sz, data );++ auto it = m_data.parentCallstackMap.find( arr );+ if( it == m_data.parentCallstackMap.end() )+ {+ parentIdx = m_data.parentCallstackPayload.size();+ m_data.parentCallstackMap.emplace( arr, parentIdx );+ m_data.parentCallstackPayload.push_back( arr );+ }+ else+ {+ parentIdx = it->second;+ m_slab.Unalloc( memsize );+ }+ }++ sym0 = m_data.symbolStats.find( frame0.symAddr );+ auto sit = sym0->second.parents.find( parentIdx );+ if( sit == sym0->second.parents.end() )+ {+ sym0->second.parents.emplace( parentIdx, count );+ }+ else+ {+ sit->second += count;+ }++ uint32_t baseParentIdx;+ {+ const auto sz = framesCount - 1;+ const auto memsize = sizeof( VarArray<CallstackFrameId> ) + sz * sizeof( CallstackFrameId );+ auto mem = (char*)m_slab.AllocRaw( memsize );++ auto data = (CallstackFrameId*)mem;+ auto dst = data;+ for( int i=0; i<sz; i++ )+ {+ *dst++ = cs[i+1];+ }++ auto arr = (VarArray<CallstackFrameId>*)( mem + sz * sizeof( CallstackFrameId ) );+ new(arr) VarArray<CallstackFrameId>( sz, data );++ auto it = m_data.parentCallstackMap.find( arr );+ if( it == m_data.parentCallstackMap.end() )+ {+ baseParentIdx = m_data.parentCallstackPayload.size();+ m_data.parentCallstackMap.emplace( arr, baseParentIdx );+ m_data.parentCallstackPayload.push_back( arr );+ }+ else+ {+ baseParentIdx = it->second;+ m_slab.Unalloc( memsize );+ }+ }++ auto bit = sym0->second.baseParents.find( baseParentIdx );+ if( bit == sym0->second.baseParents.end() )+ {+ sym0->second.baseParents.emplace( baseParentIdx, count );+ }+ else+ {+ bit->second += count;+ }+}+#endif++int64_t Worker::ReadTimeline( FileRead& f, ZoneEvent* zone, int64_t refTime, int32_t& childIdx )+{+ uint32_t sz;+ f.Read( sz );+ return ReadTimelineHaveSize( f, zone, refTime, childIdx, sz );+}++int64_t Worker::ReadTimelineHaveSize( FileRead& f, ZoneEvent* zone, int64_t refTime, int32_t& childIdx, uint32_t sz )+{+ if( sz == 0 )+ {+ zone->SetChild( -1 );+ return refTime;+ }+ else+ {+ const auto idx = childIdx;+ childIdx++;+ zone->SetChild( idx );+ return ReadTimeline( f, m_data.zoneChildren[idx], sz, refTime, childIdx );+ }+}++void Worker::ReadTimeline( FileRead& f, GpuEvent* zone, int64_t& refTime, int64_t& refGpuTime, int32_t& childIdx )+{+ uint64_t sz;+ f.Read( sz );+ ReadTimelineHaveSize( f, zone, refTime, refGpuTime, childIdx, sz );+}++void Worker::ReadTimelineHaveSize( FileRead& f, GpuEvent* zone, int64_t& refTime, int64_t& refGpuTime, int32_t& childIdx, uint64_t sz )+{+ if( sz == 0 )+ {+ zone->SetChild( -1 );+ }+ else+ {+ const auto idx = childIdx;+ childIdx++;+ zone->SetChild( idx );+ ReadTimeline( f, m_data.gpuChildren[idx], sz, refTime, refGpuTime, childIdx );+ }+}++#ifndef TRACY_NO_STATISTICS+void Worker::ReconstructZoneStatistics( uint8_t* countMap, ZoneEvent& zone, uint16_t thread )+{+ assert( zone.IsEndValid() );+ auto timeSpan = zone.End() - zone.Start();+ if( timeSpan > 0 )+ {+ auto it = m_data.sourceLocationZones.find( zone.SrcLoc() );+ assert( it != m_data.sourceLocationZones.end() );++ ZoneThreadData ztd;+ ztd.SetZone( &zone );+ ztd.SetThread( thread );++ auto& slz = it->second;+ slz.zones.push_back( ztd );+ if( slz.min > timeSpan ) slz.min = timeSpan;+ if( slz.max < timeSpan ) slz.max = timeSpan;+ slz.total += timeSpan;+ slz.sumSq += double( timeSpan ) * timeSpan;++ if( countMap[uint16_t(zone.SrcLoc())] == 0 )+ {+ slz.nonReentrantCount++;+ if( slz.nonReentrantMin > timeSpan ) slz.nonReentrantMin = timeSpan;+ if( slz.nonReentrantMax < timeSpan ) slz.nonReentrantMax = timeSpan;+ slz.nonReentrantTotal += timeSpan;+ }++ if( zone.HasChildren() )+ {+ auto& children = GetZoneChildren( zone.Child() );+ assert( children.is_magic() );+ auto& c = *(Vector<ZoneEvent>*)( &children );+ for( auto& v : c )+ {+ const auto childSpan = std::max( int64_t( 0 ), v.End() - v.Start() );+ timeSpan -= childSpan;+ }+ }++ if( slz.selfMin > timeSpan ) slz.selfMin = timeSpan;+ if( slz.selfMax < timeSpan ) slz.selfMax = timeSpan;+ slz.selfTotal += timeSpan;++ auto tit = slz.threadCnt.find( thread );+ if( tit == slz.threadCnt.end() )+ {+ slz.threadCnt.emplace( thread, 1 );+ }+ else+ {+ tit->second++;+ }+ }+}++void Worker::ReconstructZoneStatistics( GpuEvent& zone, uint16_t thread )+{+ assert( zone.GpuEnd() >= 0 );+ auto timeSpan = zone.GpuEnd() - zone.GpuStart();+ if( timeSpan > 0 )+ {+ auto it = m_data.gpuSourceLocationZones.find( zone.SrcLoc() );+ if( it == m_data.gpuSourceLocationZones.end() )+ {+ it = m_data.gpuSourceLocationZones.emplace( zone.SrcLoc(), GpuSourceLocationZones {} ).first;+ }+ GpuZoneThreadData ztd;+ ztd.SetZone( &zone );+ ztd.SetThread( thread );+ auto& slz = it->second;+ slz.zones.push_back( ztd );+ if( slz.min > timeSpan ) slz.min = timeSpan;+ if( slz.max < timeSpan ) slz.max = timeSpan;+ slz.total += timeSpan;+ slz.sumSq += double( timeSpan ) * timeSpan;+ }+}+#else+void Worker::CountZoneStatistics( ZoneEvent* zone )+{+ auto cnt = GetSourceLocationZonesCnt( zone->SrcLoc() );+ (*cnt)++;+}++void Worker::CountZoneStatistics( GpuEvent* zone )+{+ auto cnt = GetGpuSourceLocationZonesCnt( zone->SrcLoc() );+ (*cnt)++;+}+#endif++int64_t Worker::ReadTimeline( FileRead& f, Vector<short_ptr<ZoneEvent>>& _vec, uint32_t size, int64_t refTime, int32_t& childIdx )+{+ assert( size != 0 );+ const auto lp = s_loadProgress.subProgress.load( std::memory_order_relaxed );+ s_loadProgress.subProgress.store( lp + size, std::memory_order_relaxed );+ auto& vec = *(Vector<ZoneEvent>*)( &_vec );+ vec.set_magic();+ vec.reserve_exact( size, m_slab );+ auto zone = vec.begin();+ auto end = vec.end() - 1;++ int16_t srcloc;+ int64_t tstart, tend;+ uint32_t childSz, extra;+ f.Read4( srcloc, tstart, extra, childSz );++ while( zone != end )+ {+ refTime += tstart;+ zone->SetStartSrcLoc( refTime, srcloc );+ zone->extra = extra;+ refTime = ReadTimelineHaveSize( f, zone, refTime, childIdx, childSz );+ f.Read5( tend, srcloc, tstart, extra, childSz );+ refTime += tend;+ zone->SetEnd( refTime );+#ifdef TRACY_NO_STATISTICS+ CountZoneStatistics( zone );+#endif+ zone++;+ }++ refTime += tstart;+ zone->SetStartSrcLoc( refTime, srcloc );+ zone->extra = extra;+ refTime = ReadTimelineHaveSize( f, zone, refTime, childIdx, childSz );+ f.Read( tend );+ refTime += tend;+ zone->SetEnd( refTime );+#ifdef TRACY_NO_STATISTICS+ CountZoneStatistics( zone );+#endif++ return refTime;+}++void Worker::ReadTimeline( FileRead& f, Vector<short_ptr<GpuEvent>>& _vec, uint64_t size, int64_t& refTime, int64_t& refGpuTime, int32_t& childIdx )+{+ assert( size != 0 );+ const auto lp = s_loadProgress.subProgress.load( std::memory_order_relaxed );+ s_loadProgress.subProgress.store( lp + size, std::memory_order_relaxed );+ auto& vec = *(Vector<GpuEvent>*)( &_vec );+ vec.set_magic();+ vec.reserve_exact( size, m_slab );+ auto zone = vec.begin();+ auto end = vec.end();+ do+ {+ int64_t tcpu, tgpu;+ int16_t srcloc;+ uint16_t thread;+ uint64_t childSz;+ f.Read6( tcpu, tgpu, srcloc, zone->callstack, thread, childSz );+ zone->SetSrcLoc( srcloc );+ zone->SetThread( thread );+ refTime += tcpu;+ refGpuTime += tgpu;+ zone->SetCpuStart( refTime );+ zone->SetGpuStart( refGpuTime );++ ReadTimelineHaveSize( f, zone, refTime, refGpuTime, childIdx, childSz );++ f.Read2( tcpu, tgpu );+ refTime += tcpu;+ refGpuTime += tgpu;+ zone->SetCpuEnd( refTime );+ zone->SetGpuEnd( refGpuTime );+ }+ while( ++zone != end );+}++void Worker::Disconnect()+{+ //Query( ServerQueryDisconnect, 0 );+ Shutdown();+ m_disconnect = true;+}++static void WriteHwSampleVec( FileWrite& f, SortedVector<Int48, Int48Sort>& vec )+{+ uint64_t sz = vec.size();+ f.Write( &sz, sizeof( sz ) );+ if( sz != 0 )+ {+ if( !vec.is_sorted() ) vec.sort();+ int64_t refTime = 0;+ for( auto& v : vec )+ {+ WriteTimeOffset( f, refTime, v.Val() );+ }+ }+}++void Worker::Write( FileWrite& f, bool fiDict )+{+ DoPostponedWorkAll();++ f.Write( FileHeader, sizeof( FileHeader ) );++ f.Write( &m_delay, sizeof( m_delay ) );+ f.Write( &m_resolution, sizeof( m_resolution ) );+ f.Write( &m_timerMul, sizeof( m_timerMul ) );+ f.Write( &m_data.lastTime, sizeof( m_data.lastTime ) );+ f.Write( &m_data.frameOffset, sizeof( m_data.frameOffset ) );+ f.Write( &m_pid, sizeof( m_pid ) );+ f.Write( &m_samplingPeriod, sizeof( m_samplingPeriod ) );+ f.Write( &m_data.cpuArch, sizeof( m_data.cpuArch ) );+ f.Write( &m_data.cpuId, sizeof( m_data.cpuId ) );+ f.Write( m_data.cpuManufacturer, 12 );++ uint8_t flag = m_onDemand;+ f.Write( &flag, sizeof( flag ) );++ uint64_t sz = m_captureName.size();+ f.Write( &sz, sizeof( sz ) );+ f.Write( m_captureName.c_str(), sz );++ sz = m_captureProgram.size();+ f.Write( &sz, sizeof( sz ) );+ f.Write( m_captureProgram.c_str(), sz );++ f.Write( &m_captureTime, sizeof( m_captureTime ) );+ f.Write( &m_executableTime, sizeof( m_executableTime ) );++ sz = m_hostInfo.size();+ f.Write( &sz, sizeof( sz ) );+ f.Write( m_hostInfo.c_str(), sz );++ sz = m_data.cpuTopology.size();+ f.Write( &sz, sizeof( sz ) );+ for( auto& package : m_data.cpuTopology )+ {+ sz = package.second.size();+ f.Write( &package.first, sizeof( package.first ) );+ f.Write( &sz, sizeof( sz ) );+ for( auto& die : package.second )+ {+ sz = die.second.size();+ f.Write( &die.first, sizeof( die.first ) );+ f.Write( &sz, sizeof( sz ) );+ for( auto& core : die.second )+ {+ sz = core.second.size();+ f.Write( &core.first, sizeof( core.first ) );+ f.Write( &sz, sizeof( sz ) );+ for( auto& thread : core.second )+ {+ f.Write( &thread, sizeof( thread ) );+ }+ }+ }+ }++ f.Write( &m_data.crashEvent, sizeof( m_data.crashEvent ) );++ sz = m_data.frames.Data().size();+ f.Write( &sz, sizeof( sz ) );+ for( auto& fd : m_data.frames.Data() )+ {+ int64_t refTime = 0;+ f.Write( &fd->name, sizeof( fd->name ) );+ f.Write( &fd->continuous, sizeof( fd->continuous ) );+ sz = fd->frames.size();+ f.Write( &sz, sizeof( sz ) );+ if( fd->continuous )+ {+ for( auto& fe : fd->frames )+ {+ WriteTimeOffset( f, refTime, fe.start );+ f.Write( &fe.frameImage, sizeof( fe.frameImage ) );+ }+ }+ else+ {+ for( auto& fe : fd->frames )+ {+ WriteTimeOffset( f, refTime, fe.start );+ WriteTimeOffset( f, refTime, fe.end );+ f.Write( &fe.frameImage, sizeof( fe.frameImage ) );+ }+ }+ }++ sz = m_data.stringData.size();+ f.Write( &sz, sizeof( sz ) );+ for( auto& v : m_data.stringData )+ {+ uint64_t ptr = (uint64_t)v;+ f.Write( &ptr, sizeof( ptr ) );+ sz = strlen( v );+ f.Write( &sz, sizeof( sz ) );+ f.Write( v, sz );+ }++ sz = m_data.strings.size();+ f.Write( &sz, sizeof( sz ) );+ for( auto& v : m_data.strings )+ {+ f.Write( &v.first, sizeof( v.first ) );+ uint64_t ptr = (uint64_t)v.second;+ f.Write( &ptr, sizeof( ptr ) );+ }++ sz = m_data.threadNames.size();+ f.Write( &sz, sizeof( sz ) );+ for( auto& v : m_data.threadNames )+ {+ f.Write( &v.first, sizeof( v.first ) );+ uint64_t ptr = (uint64_t)v.second;+ f.Write( &ptr, sizeof( ptr ) );+ }++ sz = m_data.externalNames.size();+ f.Write( &sz, sizeof( sz ) );+ for( auto& v : m_data.externalNames )+ {+ f.Write( &v.first, sizeof( v.first ) );+ uint64_t ptr = (uint64_t)v.second.first;+ f.Write( &ptr, sizeof( ptr ) );+ ptr = (uint64_t)v.second.second;+ f.Write( &ptr, sizeof( ptr ) );+ }++ m_data.localThreadCompress.Save( f );+ m_data.externalThreadCompress.Save( f );++ sz = m_data.sourceLocation.size();+ f.Write( &sz, sizeof( sz ) );+ for( auto& v : m_data.sourceLocation )+ {+ f.Write( &v.first, sizeof( v.first ) );+ f.Write( &v.second, sizeof( SourceLocationBase ) );+ }++ sz = m_data.sourceLocationExpand.size();+ f.Write( &sz, sizeof( sz ) );+ for( auto& v : m_data.sourceLocationExpand )+ {+ f.Write( &v, sizeof( v ) );+ }++ sz = m_data.sourceLocationPayload.size();+ f.Write( &sz, sizeof( sz ) );+ for( auto& v : m_data.sourceLocationPayload )+ {+ f.Write( v, sizeof( SourceLocationBase ) );+ }++#ifndef TRACY_NO_STATISTICS+ sz = m_data.sourceLocationZones.size();+ f.Write( &sz, sizeof( sz ) );+ for( auto& v : m_data.sourceLocationZones )+ {+ int16_t id = v.first;+ uint64_t cnt = v.second.zones.size();+ f.Write( &id, sizeof( id ) );+ f.Write( &cnt, sizeof( cnt ) );+ }++ sz = m_data.gpuSourceLocationZones.size();+ f.Write( &sz, sizeof( sz ) );+ for( auto& v : m_data.gpuSourceLocationZones )+ {+ int16_t id = v.first;+ uint64_t cnt = v.second.zones.size();+ f.Write( &id, sizeof( id ) );+ f.Write( &cnt, sizeof( cnt ) );+ }+#else+ sz = m_data.sourceLocationZonesCnt.size();+ f.Write( &sz, sizeof( sz ) );+ for( auto& v : m_data.sourceLocationZonesCnt )+ {+ int16_t id = v.first;+ uint64_t cnt = v.second;+ f.Write( &id, sizeof( id ) );+ f.Write( &cnt, sizeof( cnt ) );+ }++ sz = m_data.gpuSourceLocationZonesCnt.size();+ f.Write( &sz, sizeof( sz ) );+ for( auto& v : m_data.gpuSourceLocationZonesCnt )+ {+ int16_t id = v.first;+ uint64_t cnt = v.second;+ f.Write( &id, sizeof( id ) );+ f.Write( &cnt, sizeof( cnt ) );+ }+#endif++ sz = m_data.lockMap.size();+ f.Write( &sz, sizeof( sz ) );+ for( auto& v : m_data.lockMap )+ {+ f.Write( &v.first, sizeof( v.first ) );+ f.Write( &v.second->customName, sizeof( v.second->customName ) );+ f.Write( &v.second->srcloc, sizeof( v.second->srcloc ) );+ f.Write( &v.second->type, sizeof( v.second->type ) );+ f.Write( &v.second->valid, sizeof( v.second->valid ) );+ f.Write( &v.second->timeAnnounce, sizeof( v.second->timeAnnounce ) );+ f.Write( &v.second->timeTerminate, sizeof( v.second->timeTerminate ) );+ sz = v.second->threadList.size();+ f.Write( &sz, sizeof( sz ) );+ for( auto& t : v.second->threadList )+ {+ f.Write( &t, sizeof( t ) );+ }+ int64_t refTime = v.second->timeAnnounce;+ sz = v.second->timeline.size();+ f.Write( &sz, sizeof( sz ) );+ for( auto& lev : v.second->timeline )+ {+ WriteTimeOffset( f, refTime, lev.ptr->Time() );+ const int16_t srcloc = lev.ptr->SrcLoc();+ f.Write( &srcloc, sizeof( srcloc ) );+ f.Write( &lev.ptr->thread, sizeof( lev.ptr->thread ) );+ f.Write( &lev.ptr->type, sizeof( lev.ptr->type ) );+ }+ }++ {+ int64_t refTime = 0;+ sz = m_data.messages.size();+ f.Write( &sz, sizeof( sz ) );+ for( auto& v : m_data.messages )+ {+ const auto ptr = (uint64_t)(MessageData*)v;+ f.Write( &ptr, sizeof( ptr ) );+ WriteTimeOffset( f, refTime, v->time );+ f.Write( &v->ref, sizeof( v->ref ) );+ f.Write( &v->color, sizeof( v->color ) );+ f.Write( &v->callstack, sizeof( v->callstack ) );+ }+ }++ sz = m_data.zoneExtra.size();+ f.Write( &sz, sizeof( sz ) );+ f.Write( m_data.zoneExtra.data(), sz * sizeof( ZoneExtra ) );++ sz = 0;+ for( auto& v : m_data.threads ) sz += v->count;+ f.Write( &sz, sizeof( sz ) );+ sz = m_data.zoneChildren.size();+ f.Write( &sz, sizeof( sz ) );+ sz = m_data.threads.size();+ f.Write( &sz, sizeof( sz ) );+ for( auto& thread : m_data.threads )+ {+ int64_t refTime = 0;+ f.Write( &thread->id, sizeof( thread->id ) );+ f.Write( &thread->count, sizeof( thread->count ) );+ f.Write( &thread->kernelSampleCnt, sizeof( thread->kernelSampleCnt ) );+ f.Write( &thread->isFiber, sizeof( thread->isFiber ) );+ f.Write( &thread->groupHint, sizeof( thread->groupHint ) );+ WriteTimeline( f, thread->timeline, refTime );+ sz = thread->messages.size();+ f.Write( &sz, sizeof( sz ) );+ for( auto& v : thread->messages )+ {+ auto ptr = uint64_t( (MessageData*)v );+ f.Write( &ptr, sizeof( ptr ) );+ }+ sz = thread->ctxSwitchSamples.size();+ f.Write( &sz, sizeof( sz ) );+ refTime = 0;+ for( auto& v : thread->ctxSwitchSamples )+ {+ WriteTimeOffset( f, refTime, v.time.Val() );+ f.Write( &v.callstack, sizeof( v.callstack ) );+ }+ if( m_inconsistentSamples )+ {+#ifdef __EMSCRIPTEN__+ pdqsort_branchless( thread->samples.begin(), thread->samples.end(), [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs.time.Val(); } );+#else+ ppqsort::sort( ppqsort::execution::par, thread->samples.begin(), thread->samples.end(), [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs.time.Val(); } );+#endif+ }+ sz = thread->samples.size();+ f.Write( &sz, sizeof( sz ) );+ refTime = 0;+ for( auto& v : thread->samples )+ {+ WriteTimeOffset( f, refTime, v.time.Val() );+ f.Write( &v.callstack, sizeof( v.callstack ) );+ }+ }++ sz = 0;+ for( auto& v : m_data.gpuData ) sz += v->count;+ f.Write( &sz, sizeof( sz ) );+ sz = m_data.gpuChildren.size();+ f.Write( &sz, sizeof( sz ) );+ sz = m_data.gpuData.size();+ f.Write( &sz, sizeof( sz ) );+ for( auto& ctx : m_data.gpuData )+ {+ f.Write( &ctx->thread, sizeof( ctx->thread ) );+ uint8_t calibration = ctx->hasCalibration;+ f.Write( &calibration, sizeof( calibration ) );+ f.Write( &ctx->count, sizeof( ctx->count ) );+ f.Write( &ctx->period, sizeof( ctx->period ) );+ f.Write( &ctx->type, sizeof( ctx->type ) );+ f.Write( &ctx->name, sizeof( ctx->name ) );+ f.Write( &ctx->overflow, sizeof( ctx->overflow ) );+ sz = ctx->threadData.size();+ f.Write( &sz, sizeof( sz ) );+ for( auto& td : ctx->threadData )+ {+ int64_t refTime = 0;+ int64_t refGpuTime = 0;+ uint64_t tid = td.first;+ f.Write( &tid, sizeof( tid ) );+ WriteTimeline( f, td.second.timeline, refTime, refGpuTime );+ }+ }++ sz = m_data.plots.Data().size();+ for( auto& plot : m_data.plots.Data() ) { if( plot->type == PlotType::Memory ) sz--; }+ f.Write( &sz, sizeof( sz ) );+ for( auto& plot : m_data.plots.Data() )+ {+ if( plot->type == PlotType::Memory ) continue;+ f.Write( &plot->type, sizeof( plot->type ) );+ f.Write( &plot->format, sizeof( plot->format ) );+ f.Write( &plot->showSteps, sizeof( plot->showSteps ) );+ f.Write( &plot->fill, sizeof( plot->fill ) );+ f.Write( &plot->color, sizeof( plot->color ) );+ f.Write( &plot->name, sizeof( plot->name ) );+ f.Write( &plot->min, sizeof( plot->min ) );+ f.Write( &plot->max, sizeof( plot->max ) );+ f.Write( &plot->sum, sizeof( plot->sum ) );+ int64_t refTime = 0;+ sz = plot->data.size();+ f.Write( &sz, sizeof( sz ) );+ for( auto& v : plot->data )+ {+ WriteTimeOffset( f, refTime, v.time.Val() );+ f.Write( &v.val, sizeof( v.val ) );+ }+ }++ sz = m_data.memNameMap.size();+ f.Write( &sz, sizeof( sz ) );+ sz = 0;+ for( auto& memory : m_data.memNameMap )+ {+ sz += memory.second->data.size();+ }+ f.Write( &sz, sizeof( sz ) );+ for( auto& memory : m_data.memNameMap )+ {+ uint64_t name = memory.first;+ f.Write( &name, sizeof( name ) );++ auto& memdata = *memory.second;+ int64_t refTime = 0;+ sz = memdata.data.size();+ f.Write( &sz, sizeof( sz ) );+ sz = memdata.active.size();+ f.Write( &sz, sizeof( sz ) );+ sz = memdata.frees.size();+ f.Write( &sz, sizeof( sz ) );+ for( auto& mem : memdata.data )+ {+ const auto ptr = mem.Ptr();+ const auto size = mem.Size();+ const Int24 csAlloc = mem.CsAlloc();+ f.Write( &ptr, sizeof( ptr ) );+ f.Write( &size, sizeof( size ) );+ f.Write( &csAlloc, sizeof( csAlloc ) );+ f.Write( &mem.csFree, sizeof( mem.csFree ) );++ int64_t timeAlloc = mem.TimeAlloc();+ uint16_t threadAlloc = mem.ThreadAlloc();+ int64_t timeFree = mem.TimeFree();+ uint16_t threadFree = mem.ThreadFree();+ WriteTimeOffset( f, refTime, timeAlloc );+ int64_t freeOffset = timeFree < 0 ? timeFree : timeFree - timeAlloc;+ f.Write( &freeOffset, sizeof( freeOffset ) );+ f.Write( &threadAlloc, sizeof( threadAlloc ) );+ f.Write( &threadFree, sizeof( threadFree ) );+ }+ f.Write( &memdata.high, sizeof( memdata.high ) );+ f.Write( &memdata.low, sizeof( memdata.low ) );+ f.Write( &memdata.usage, sizeof( memdata.usage ) );+ f.Write( &memdata.name, sizeof( memdata.name ) );+ }++ sz = m_data.callstackPayload.size() - 1;+ f.Write( &sz, sizeof( sz ) );+ for( size_t i=1; i<=sz; i++ )+ {+ auto& cs = m_data.callstackPayload[i];+ uint16_t csz = cs->size();+ f.Write( &csz, sizeof( csz ) );+ f.Write( cs->data(), sizeof( CallstackFrameId ) * csz );+ }++ sz = m_data.callstackFrameMap.size();+ f.Write( &sz, sizeof( sz ) );+ for( auto& frame : m_data.callstackFrameMap )+ {+ f.Write( &frame.first, sizeof( CallstackFrameId ) );+ f.Write( &frame.second->size, sizeof( frame.second->size ) );+ f.Write( &frame.second->imageName, sizeof( frame.second->imageName ) );+ f.Write( frame.second->data, sizeof( CallstackFrame ) * frame.second->size );+ }++ sz = m_data.appInfo.size();+ f.Write( &sz, sizeof( sz ) );+ if( sz != 0 ) f.Write( m_data.appInfo.data(), sizeof( m_data.appInfo[0] ) * sz );++ {+ sz = m_data.frameImage.size();+ if( fiDict )+ {+ enum : uint32_t { DictSize = 4*1024*1024 };+ enum : uint32_t { SamplesLimit = 1U << 31 };+ uint32_t sNum = 0;+ uint32_t sSize = 0;+ for( auto& fi : m_data.frameImage )+ {+ const auto fisz = fi->w * fi->h / 2;+ if( sSize + fisz > SamplesLimit ) break;+ sSize += fisz;+ sNum++;+ }++ uint32_t offset = 0;+ auto sdata = new char[sSize];+ auto ssize = new size_t[sSize];+ for( uint32_t i=0; i<sNum; i++ )+ {+ const auto& fi = m_data.frameImage[i];+ const auto fisz = fi->w * fi->h / 2;+ const auto image = m_texcomp.Unpack( *fi );+ memcpy( sdata+offset, image, fisz );+ ssize[i] = fisz;+ offset += fisz;+ }+ assert( offset == sSize );++ ZDICT_fastCover_params_t params = {};+ params.d = 6;+ params.k = 50;+ params.f = 30;+ params.nbThreads = std::thread::hardware_concurrency();+ params.zParams.compressionLevel = 3;++ auto dict = new char[DictSize];+ const auto dictret = ZDICT_optimizeTrainFromBuffer_fastCover( dict, DictSize, sdata, ssize, sNum, ¶ms );+ if( dictret <= DictSize )+ {+ const auto finalDictSize = uint32_t( dictret );+ auto zdict = ZSTD_createCDict( dict, finalDictSize, 3 );++ f.Write( &finalDictSize, sizeof( finalDictSize ) );+ f.Write( dict, finalDictSize );++ ZSTD_freeCDict( zdict );+ }+ else+ {+ uint32_t zero = 0;+ f.Write( &zero, sizeof( zero ) );+ }++ delete[] dict;+ delete[] ssize;+ delete[] sdata;+ }+ else+ {+ uint32_t zero = 0;+ f.Write( &zero, sizeof( zero ) );+ }+ f.Write( &sz, sizeof( sz ) );+ for( auto& fi : m_data.frameImage )+ {+ f.Write( &fi->w, sizeof( fi->w ) );+ f.Write( &fi->h, sizeof( fi->h ) );+ f.Write( &fi->flip, sizeof( fi->flip ) );+ const auto image = m_texcomp.Unpack( *fi );+ f.Write( image, fi->w * fi->h / 2 );+ }+ }++ // Only save context switches relevant to active threads.+ std::vector<unordered_flat_map<uint64_t, ContextSwitch*>::const_iterator> ctxValid;+ ctxValid.reserve( m_data.ctxSwitch.size() );+ for( auto it = m_data.ctxSwitch.begin(); it != m_data.ctxSwitch.end(); ++it )+ {+ auto td = RetrieveThread( it->first );+ if( td && ( td->count > 0 || !td->samples.empty() ) )+ {+ ctxValid.emplace_back( it );+ }+ }+ sz = ctxValid.size();+ f.Write( &sz, sizeof( sz ) );+ for( auto& ctx : ctxValid )+ {+ f.Write( &ctx->first, sizeof( ctx->first ) );+ sz = ctx->second->v.size();+ f.Write( &sz, sizeof( sz ) );+ int64_t refTime = 0;+ for( auto& cs : ctx->second->v )+ {+ WriteTimeOffset( f, refTime, cs.WakeupVal() );+ WriteTimeOffset( f, refTime, cs.Start() );+ WriteTimeOffset( f, refTime, cs.End() );+ uint8_t cpu = cs.Cpu();+ uint8_t wakeupcpu = cs.WakeupCpu();+ int8_t reason = cs.Reason();+ int8_t state = cs.State();+ uint64_t thread = DecompressThread( cs.Thread() );+ f.Write( &cpu, sizeof( cpu ) );+ f.Write( &reason, sizeof( reason ) );+ f.Write( &state, sizeof( state ) );+ f.Write( &thread, sizeof( thread ) );+ f.Write( &wakeupcpu, sizeof( wakeupcpu ) );+ }+ }++ sz = GetContextSwitchPerCpuCount();+ f.Write( &sz, sizeof( sz ) );+ for( int i=0; i<256; i++ )+ {+ sz = m_data.cpuData[i].cs.size();+ f.Write( &sz, sizeof( sz ) );+ int64_t refTime = 0;+ for( auto& cx : m_data.cpuData[i].cs )+ {+ WriteTimeOffset( f, refTime, cx.Start() );+ WriteTimeOffset( f, refTime, cx.End() );+ uint16_t thread = cx.Thread();+ f.Write( &thread, sizeof( thread ) );+ }+ }++ sz = m_data.tidToPid.size();+ f.Write( &sz, sizeof( sz ) );+ for( auto& v : m_data.tidToPid )+ {+ f.Write( &v.first, sizeof( v.first ) );+ f.Write( &v.second, sizeof( v.second ) );+ }++ sz = m_data.cpuThreadData.size();+ f.Write( &sz, sizeof( sz ) );+ for( auto& v : m_data.cpuThreadData )+ {+ f.Write( &v.first, sizeof( v.first ) );+ f.Write( &v.second, sizeof( v.second ) );+ }++ sz = m_data.symbolLoc.size();+ f.Write( &sz, sizeof( sz ) );+ sz = m_data.symbolLocInline.size();+ f.Write( &sz, sizeof( sz ) );+ sz = m_data.symbolMap.size();+ f.Write( &sz, sizeof( sz ) );+ for( auto& v : m_data.symbolMap )+ {+ f.Write( &v.first, sizeof( v.first ) );+ f.Write( &v.second, sizeof( v.second ) );+ }++ sz = m_data.symbolCode.size();+ f.Write( &sz, sizeof( sz ) );+ for( auto& v : m_data.symbolCode )+ {+ f.Write( &v.first, sizeof( v.first ) );+ f.Write( &v.second.len, sizeof( v.second.len ) );+ f.Write( v.second.data, v.second.len );+ }++ sz = m_data.codeSymbolMap.size();+ f.Write( &sz, sizeof( sz ) );+ for( auto& v : m_data.codeSymbolMap )+ {+ f.Write( &v.first, sizeof( v.first ) );+ f.Write( &v.second, sizeof( v.second ) );+ }++ sz = m_data.hwSamples.size();+ f.Write( &sz, sizeof( sz ) );+ for( auto& v : m_data.hwSamples )+ {+ f.Write( &v.first, sizeof( v.first ) );+ WriteHwSampleVec( f, v.second.cycles );+ WriteHwSampleVec( f, v.second.retired );+ WriteHwSampleVec( f, v.second.cacheRef );+ WriteHwSampleVec( f, v.second.cacheMiss );+ WriteHwSampleVec( f, v.second.branchRetired );+ WriteHwSampleVec( f, v.second.branchMiss );+ }++ sz = m_data.sourceFileCache.size();+ f.Write( &sz, sizeof( sz ) );+ for( auto& v : m_data.sourceFileCache )+ {+ uint32_t s32 = strlen( v.first );+ f.Write( &s32, sizeof( s32 ) );+ f.Write( v.first, s32 );+ f.Write( &v.second.len, sizeof( v.second.len ) );+ f.Write( v.second.data, v.second.len );+ }+}++void Worker::WriteTimeline( FileWrite& f, const Vector<short_ptr<ZoneEvent>>& vec, int64_t& refTime )+{+ uint32_t sz = uint32_t( vec.size() );+ f.Write( &sz, sizeof( sz ) );+ if( vec.is_magic() )+ {+ WriteTimelineImpl<VectorAdapterDirect<ZoneEvent>>( f, *(Vector<ZoneEvent>*)( &vec ), refTime );+ }+ else+ {+ WriteTimelineImpl<VectorAdapterPointer<ZoneEvent>>( f, vec, refTime );+ }+}++template<typename Adapter, typename V>+void Worker::WriteTimelineImpl( FileWrite& f, const V& vec, int64_t& refTime )+{+ Adapter a;+ for( auto& val : vec )+ {+ auto& v = a(val);+ int16_t srcloc = v.SrcLoc();+ f.Write( &srcloc, sizeof( srcloc ) );+ int64_t start = v.Start();+ WriteTimeOffset( f, refTime, start );+ f.Write( &v.extra, sizeof( v.extra ) );+ if( !v.HasChildren() )+ {+ const uint32_t sz = 0;+ f.Write( &sz, sizeof( sz ) );+ }+ else+ {+ WriteTimeline( f, GetZoneChildren( v.Child() ), refTime );+ }+ WriteTimeOffset( f, refTime, v.End() );+ }+}++void Worker::WriteTimeline( FileWrite& f, const Vector<short_ptr<GpuEvent>>& vec, int64_t& refTime, int64_t& refGpuTime )+{+ uint64_t sz = vec.size();+ f.Write( &sz, sizeof( sz ) );+ if( vec.is_magic() )+ {+ WriteTimelineImpl<VectorAdapterDirect<GpuEvent>>( f, *(Vector<GpuEvent>*)( &vec ), refTime, refGpuTime );+ }+ else+ {+ WriteTimelineImpl<VectorAdapterPointer<GpuEvent>>( f, vec, refTime, refGpuTime );+ }+}++template<typename Adapter, typename V>+void Worker::WriteTimelineImpl( FileWrite& f, const V& vec, int64_t& refTime, int64_t& refGpuTime )+{+ Adapter a;+ for( auto& val : vec )+ {+ auto& v = a(val);+ WriteTimeOffset( f, refTime, v.CpuStart() );+ WriteTimeOffset( f, refGpuTime, v.GpuStart() );+ const int16_t srcloc = v.SrcLoc();+ f.Write( &srcloc, sizeof( srcloc ) );+ f.Write( &v.callstack, sizeof( v.callstack ) );+ const uint16_t thread = v.Thread();+ f.Write( &thread, sizeof( thread ) );++ if( v.Child() < 0 )+ {+ const uint64_t sz = 0;+ f.Write( &sz, sizeof( sz ) );+ }+ else+ {+ WriteTimeline( f, GetGpuChildren( v.Child() ), refTime, refGpuTime );+ }++ WriteTimeOffset( f, refTime, v.CpuEnd() );+ WriteTimeOffset( f, refGpuTime, v.GpuEnd() );+ }+}++static const char* s_failureReasons[] = {+ "<unknown reason>",+ "Invalid order of zone begin and end events.",+ "Zone is ended twice.",+ "Zone text transfer destination doesn't match active zone.",+ "Zone value transfer destination doesn't match active zone.",+ "Zone color transfer destination doesn't match active zone.",+ "Zone name transfer destination doesn't match active zone.",+ "Memory free event without a matching allocation.",+ "Memory allocation event was reported for an address that is already tracked and not freed.",+ "Discontinuous frame begin/end mismatch.",+ "Frame image offset is invalid.",+ "Multiple frame images were sent for a single frame.",+ "Fiber execution stopped on a thread which is not executing a fiber.",+ "Too many source locations. You cannot have more than 32K static or dynamic source locations.",+};++static_assert( sizeof( s_failureReasons ) / sizeof( *s_failureReasons ) == (int)Worker::Failure::NUM_FAILURES, "Missing failure reason description." );++const char* Worker::GetFailureString( Worker::Failure failure )+{+ return s_failureReasons[(int)failure];+}++void Worker::SetParameter( size_t paramIdx, int32_t val )+{+ assert( paramIdx < m_params.size() );+ m_params[paramIdx].val = val;+ const auto idx = uint64_t( m_params[paramIdx].idx );+ const auto v = uint64_t( uint32_t( val ) );+ Query( ServerQueryParameter, ( idx << 32 ) | v );+}++const Worker::CpuThreadTopology* Worker::GetThreadTopology( uint32_t cpuThread ) const+{+ auto it = m_data.cpuTopologyMap.find( cpuThread );+ if( it == m_data.cpuTopologyMap.end() ) return nullptr;+ return &it->second;+}++ZoneExtra& Worker::AllocZoneExtra( ZoneEvent& ev )+{+ assert( ev.extra == 0 );+ ev.extra = uint32_t( m_data.zoneExtra.size() );+ auto& extra = m_data.zoneExtra.push_next();+ memset( (char*)&extra, 0, sizeof( extra ) );+ return extra;+}++ZoneExtra& Worker::RequestZoneExtra( ZoneEvent& ev )+{+ if( !HasZoneExtra( ev ) )+ {+ return AllocZoneExtra( ev );+ }+ else+ {+ return GetZoneExtraMutable( ev );+ }+}++void Worker::CacheSource( const StringRef& str, const StringIdx& image )+{+ assert( str.active );+ assert( m_checkedFileStrings.find( str ) == m_checkedFileStrings.end() );+ m_checkedFileStrings.emplace( str );+ auto file = GetString( str );+ // Possible duplication of pointer and index strings+ if( m_data.sourceFileCache.find( file ) != m_data.sourceFileCache.end() ) return;+ const auto execTime = GetExecutableTime();+ if( SourceFileValid( file, execTime != 0 ? execTime : GetCaptureTime() ) )+ {+ CacheSourceFromFile( file );+ }+ else if( execTime != 0 )+ {+ QuerySourceFile( file, image.Active() ? GetString( image ) : nullptr );+ }+}++void Worker::CacheSourceFromFile( const char* fn )+{+ FILE* f = fopen( fn, "rb" );+ fseek( f, 0, SEEK_END );+ const auto sz = ftell( f );+ fseek( f, 0, SEEK_SET );+ auto src = (char*)m_slab.AllocBig( sz );+ fread( src, 1, sz, f );+ fclose( f );+ m_data.sourceFileCache.emplace( fn, MemoryBlock{ src, uint32_t( sz ) } );+}++uint64_t Worker::GetSourceFileCacheSize() const+{+ uint64_t cnt = 0;+ for( auto& v : m_data.sourceFileCache )+ {+ cnt += v.second.len;+ }+ return cnt;+}++Worker::MemoryBlock Worker::GetSourceFileFromCache( const char* file ) const+{+ auto it = m_data.sourceFileCache.find( file );+ if( it == m_data.sourceFileCache.end() ) return MemoryBlock {};+ return it->second;+}++HwSampleData* Worker::GetHwSampleData( uint64_t addr )+{+ auto it = m_data.hwSamples.find( addr );+ if( it == m_data.hwSamples.end() ) return nullptr;+ return &it->second;+}++uint64_t Worker::GetHwSampleCount() const+{+ uint64_t cnt = 0;+ for( auto& v : m_data.hwSamples )+ {+ cnt += v.second.cycles.size();+ cnt += v.second.retired.size();+ cnt += v.second.cacheRef.size();+ cnt += v.second.cacheMiss.size();+ cnt += v.second.branchRetired.size();+ cnt += v.second.branchMiss.size();+ }+ return cnt;+}++void Worker::CacheSourceFiles()+{+ const auto execTime = GetExecutableTime();++ for( auto& sl : m_data.sourceLocationPayload )+ {+ const char* file = GetString( sl->file );+ if( m_data.sourceFileCache.find( file ) == m_data.sourceFileCache.end() )+ {+ if( SourceFileValid( file, execTime != 0 ? execTime : GetCaptureTime() ) ) CacheSourceFromFile( file );+ }+ }++ for( auto& sl : m_data.sourceLocation )+ {+ const char* file = GetString( sl.second.file );+ if( m_data.sourceFileCache.find( file ) == m_data.sourceFileCache.end() )+ {+ if( SourceFileValid( file, execTime != 0 ? execTime : GetCaptureTime() ) ) CacheSourceFromFile( file );+ }+ }++ for( auto& sym : m_data.symbolMap )+ {+ const char* file = GetString( sym.second.file );+ if( m_data.sourceFileCache.find( file ) == m_data.sourceFileCache.end() )+ {+ if( SourceFileValid( file, execTime != 0 ? execTime : GetCaptureTime() ) ) CacheSourceFromFile( file );+ }+ }+}++}
+ cbits/tracy/server/TracyWorker.hpp view
@@ -0,0 +1,1112 @@+#ifndef __TRACYWORKER_HPP__+#define __TRACYWORKER_HPP__++#include <atomic>+#include <condition_variable>+#include <limits>+#include <mutex>+#include <shared_mutex>+#include <stdexcept>+#include <string>+#include <string.h>+#include <thread>+#include <unordered_map>+#include <vector>++#include "../public/common/TracyForceInline.hpp"+#include "../public/common/TracyQueue.hpp"+#include "../public/common/TracyProtocol.hpp"+#include "../public/common/TracySocket.hpp"+#include "tracy_robin_hood.h"+#include "TracyEvent.hpp"+#include "TracyShortPtr.hpp"+#include "TracySlab.hpp"+#include "TracyStringDiscovery.hpp"+#include "TracyTextureCompression.hpp"+#include "TracyThreadCompress.hpp"+#include "TracyVarArray.hpp"+++namespace tracy+{++class FileRead;+class FileWrite;++namespace EventType+{+ enum Type : uint32_t+ {+ Locks = 1 << 0,+ Messages = 1 << 1,+ Plots = 1 << 2,+ Memory = 1 << 3,+ FrameImages = 1 << 4,+ ContextSwitches = 1 << 5,+ Samples = 1 << 6,+ SymbolCode = 1 << 7,+ SourceCache = 1 << 8,++ None = 0,+ All = std::numeric_limits<uint32_t>::max()+ };+}++struct UnsupportedVersion : public std::exception+{+ UnsupportedVersion( int version ) : version( version ) {}+ int version;+};++struct LegacyVersion : public std::exception+{+ LegacyVersion( int version ) : version ( version ) {}+ int version;+};++struct LoadFailure : public std::exception+{+ LoadFailure( const char* msg ) : msg( msg ) {}+ std::string msg;+};++struct LoadProgress+{+ enum Stage+ {+ Initialization,+ Locks,+ Messages,+ Zones,+ GpuZones,+ Plots,+ Memory,+ CallStacks,+ FrameImages,+ ContextSwitches,+ ContextSwitchesPerCpu+ };++ LoadProgress() : total( 0 ), progress( 0 ), subTotal( 0 ), subProgress( 0 ) {}++ std::atomic<uint64_t> total;+ std::atomic<uint64_t> progress;+ std::atomic<uint64_t> subTotal;+ std::atomic<uint64_t> subProgress;+};++class Worker+{+public:+ struct ImportEventTimeline+ {+ uint64_t tid;+ uint64_t timestamp;+ std::string name;+ std::string text;+ bool isEnd;+ std::string locFile;+ uint32_t locLine;+ };++ struct ImportEventMessages+ {+ uint64_t tid;+ uint64_t timestamp;+ std::string message;+ };++ struct ImportEventPlots+ {+ std::string name;+ PlotValueFormatting format;+ std::vector<std::pair<int64_t, double>> data;+ };++ struct ZoneThreadData+ {+ tracy_force_inline ZoneEvent* Zone() const { return (ZoneEvent*)( _zone_thread >> 16 ); }+ tracy_force_inline void SetZone( ZoneEvent* zone ) { auto z64 = (uint64_t)zone; assert( ( z64 & 0xFFFF000000000000 ) == 0 ); memcpy( ((char*)&_zone_thread)+2, &z64, 4 ); memcpy( ((char*)&_zone_thread)+6, ((char*)&z64)+4, 2 ); }+ tracy_force_inline uint16_t Thread() const { return uint16_t( _zone_thread & 0xFFFF ); }+ tracy_force_inline void SetThread( uint16_t thread ) { memcpy( &_zone_thread, &thread, 2 ); }++ uint64_t _zone_thread;+ };+ enum { ZoneThreadDataSize = sizeof( ZoneThreadData ) };++ struct GpuZoneThreadData+ {+ tracy_force_inline GpuEvent* Zone() const { return (GpuEvent*)( _zone_thread >> 16 ); }+ tracy_force_inline void SetZone( GpuEvent* zone ) { auto z64 = (uint64_t)zone; assert( ( z64 & 0xFFFF000000000000 ) == 0 ); memcpy( ((char*)&_zone_thread)+2, &z64, 4 ); memcpy( ((char*)&_zone_thread)+6, ((char*)&z64)+4, 2 ); }+ tracy_force_inline uint16_t Thread() const { return uint16_t( _zone_thread & 0xFFFF ); }+ tracy_force_inline void SetThread( uint16_t thread ) { memcpy( &_zone_thread, &thread, 2 ); }++ uint64_t _zone_thread;+ };+ enum { GpuZoneThreadDataSize = sizeof( GpuZoneThreadData ) };++ struct CpuThreadTopology+ {+ uint32_t package;+ uint32_t die;+ uint32_t core;+ };++ struct MemoryBlock+ {+ const char* data;+ uint32_t len;+ };++ struct InlineStackData+ {+ uint64_t symAddr;+ CallstackFrameId frame;+ uint8_t inlineFrame;+ };++ struct PowerData+ {+ int64_t lastTime;+ PlotData* plot;+ };++#pragma pack( push, 1 )+ struct GhostKey+ {+ CallstackFrameId frame;+ uint8_t inlineFrame;+ };+#pragma pack( pop )++ struct GhostKeyHasher+ {+ size_t operator()( const GhostKey& key ) const+ {+ return charutil::hash( (const char*)&key, sizeof( GhostKey ) );+ }+ };++ struct GhostKeyComparator+ {+ bool operator()( const GhostKey& lhs, const GhostKey& rhs ) const+ {+ return memcmp( &lhs, &rhs, sizeof( GhostKey ) ) == 0;+ }+ };++private:+ struct SourceLocationZones+ {+ struct ZtdSort { bool operator()( const ZoneThreadData& lhs, const ZoneThreadData& rhs ) const { return lhs.Zone()->Start() < rhs.Zone()->Start(); } };++ SortedVector<ZoneThreadData, ZtdSort> zones;+ int64_t min = std::numeric_limits<int64_t>::max();+ int64_t max = std::numeric_limits<int64_t>::min();+ int64_t total = 0;+ double sumSq = 0;+ int64_t selfMin = std::numeric_limits<int64_t>::max();+ int64_t selfMax = std::numeric_limits<int64_t>::min();+ int64_t selfTotal = 0;+ size_t nonReentrantCount = 0;+ int64_t nonReentrantMin = std::numeric_limits<int64_t>::max();+ int64_t nonReentrantMax = std::numeric_limits<int64_t>::min();+ int64_t nonReentrantTotal = 0;+ unordered_flat_map<uint16_t, uint64_t> threadCnt;+ };++ struct GpuSourceLocationZones+ {+ struct GpuZtdSort { bool operator()( const GpuZoneThreadData& lhs, const GpuZoneThreadData& rhs ) const { return lhs.Zone()->GpuStart() < rhs.Zone()->GpuStart(); } };++ SortedVector<GpuZoneThreadData, GpuZtdSort> zones;+ int64_t min = std::numeric_limits<int64_t>::max();+ int64_t max = std::numeric_limits<int64_t>::min();+ int64_t total = 0;+ double sumSq = 0;+ };++ struct CallstackFrameIdHash+ {+ size_t operator()( const CallstackFrameId& id ) const { return id.data; }+ };++ struct CallstackFrameIdCompare+ {+ bool operator()( const CallstackFrameId& lhs, const CallstackFrameId& rhs ) const { return lhs.data == rhs.data; }+ };++ struct RevFrameHash+ {+ size_t operator()( const CallstackFrameData* data ) const+ {+ size_t hash = data->size;+ for( uint8_t i=0; i<data->size; i++ )+ {+ const auto& v = data->data[i];+ hash = ( ( hash << 5 ) + hash ) ^ size_t( v.line );+ hash = ( ( hash << 5 ) + hash ) ^ size_t( v.file.Idx() );+ hash = ( ( hash << 5 ) + hash ) ^ size_t( v.name.Idx() );+ }+ return hash;+ }+ };++ struct RevFrameComp+ {+ bool operator()( const CallstackFrameData* lhs, const CallstackFrameData* rhs ) const+ {+ if( lhs->size != rhs->size ) return false;+ for( uint8_t i=0; i<lhs->size; i++ )+ {+ if( memcmp( lhs->data + i, rhs->data + i, sizeof( CallstackFrameBasic ) ) != 0 ) return false;+ }+ return true;+ }+ };++ struct SymbolPending+ {+ StringIdx name;+ StringIdx imageName;+ StringIdx file;+ uint32_t line;+ uint32_t size;+ bool isInline;+ };++ struct DataBlock+ {+ std::mutex lock;+ StringDiscovery<FrameData*> frames;+ FrameData* framesBase;+ Vector<GpuCtxData*> gpuData;+ Vector<short_ptr<MessageData>> messages;+ StringDiscovery<PlotData*> plots;+ Vector<ThreadData*> threads;+ Vector<ZoneExtra> zoneExtra;+ MemData* memory;+ unordered_flat_map<uint64_t, MemData*> memNameMap;+ uint64_t zonesCnt = 0;+ uint64_t gpuCnt = 0;+ uint64_t samplesCnt = 0;+ uint64_t ghostCnt = 0;+ int64_t baseTime = 0;+ int64_t lastTime = 0;+ uint64_t frameOffset = 0;+ CpuArchitecture cpuArch = CpuArchUnknown;+ uint32_t cpuId = 0;+ char cpuManufacturer[13];++ unordered_flat_map<uint64_t, const char*> strings;+ Vector<const char*> stringData;+ unordered_flat_map<charutil::StringKey, uint32_t, charutil::StringKey::Hasher, charutil::StringKey::Comparator> stringMap;+ unordered_flat_map<uint64_t, const char*> threadNames;+ unordered_flat_map<uint64_t, std::pair<const char*, const char*>> externalNames;++ unordered_flat_map<uint64_t, SourceLocation> sourceLocation;+ Vector<short_ptr<SourceLocation>> sourceLocationPayload;+ unordered_flat_map<const SourceLocation*, int16_t, SourceLocationHasher, SourceLocationComparator> sourceLocationPayloadMap;+ Vector<uint64_t> sourceLocationExpand;+#ifndef TRACY_NO_STATISTICS+ unordered_flat_map<int16_t, SourceLocationZones> sourceLocationZones;+ bool sourceLocationZonesReady = false;+ unordered_flat_map<int16_t, GpuSourceLocationZones> gpuSourceLocationZones;+ bool gpuSourceLocationZonesReady = false;+#else+ unordered_flat_map<int16_t, uint64_t> sourceLocationZonesCnt;+ unordered_flat_map<int16_t, uint64_t> gpuSourceLocationZonesCnt;+#endif++ unordered_flat_map<VarArray<CallstackFrameId>*, uint32_t, VarArrayHasher<CallstackFrameId>, VarArrayComparator<CallstackFrameId>> callstackMap;+ Vector<short_ptr<VarArray<CallstackFrameId>>> callstackPayload;+ unordered_flat_map<CallstackFrameId, CallstackFrameData*, CallstackFrameIdHash, CallstackFrameIdCompare> callstackFrameMap;+ unordered_flat_map<CallstackFrameData*, CallstackFrameId, RevFrameHash, RevFrameComp> revFrameMap;+ unordered_flat_map<uint64_t, SymbolData> symbolMap;+ unordered_flat_map<uint64_t, SymbolStats> symbolStats;+ Vector<SymbolLocation> symbolLoc;+ Vector<uint64_t> symbolLocInline;+ int64_t newSymbolsIndex = -1;+ int64_t newInlineSymbolsIndex = -1;+ unordered_flat_map<uint64_t, uint64_t> codeSymbolMap;++#ifndef TRACY_NO_STATISTICS+ unordered_flat_map<VarArray<CallstackFrameId>*, uint32_t, VarArrayHasher<CallstackFrameId>, VarArrayComparator<CallstackFrameId>> parentCallstackMap;+ Vector<short_ptr<VarArray<CallstackFrameId>>> parentCallstackPayload;+ unordered_flat_map<CallstackFrameId, CallstackFrameData*, CallstackFrameIdHash, CallstackFrameIdCompare> parentCallstackFrameMap;+ unordered_flat_map<CallstackFrameData*, CallstackFrameId, RevFrameHash, RevFrameComp> revParentFrameMap;+ unordered_flat_map<uint32_t, uint32_t> postponedSamples;+ unordered_flat_map<CallstackFrameId, uint32_t, CallstackFrameIdHash, CallstackFrameIdCompare> pendingInstructionPointers;+ unordered_flat_map<uint64_t, unordered_flat_map<CallstackFrameId, uint32_t, CallstackFrameIdHash, CallstackFrameIdCompare>> instructionPointersMap;+ unordered_flat_map<uint64_t, Vector<SampleDataRange>> symbolSamples;+ unordered_flat_map<CallstackFrameId, Vector<SampleDataRange>, CallstackFrameIdHash, CallstackFrameIdCompare> pendingSymbolSamples;+ unordered_flat_map<uint64_t, Vector<ChildSample>> childSamples;+ bool newFramesWereReceived = false;+ bool callstackSamplesReady = false;+ bool newContextSwitchesReceived = false;+ bool ghostZonesReady = false;+ bool ghostZonesPostponed = false;+ bool symbolSamplesReady = false;+#endif++ unordered_flat_map<uint32_t, LockMap*> lockMap;++ ThreadCompress localThreadCompress;+ ThreadCompress externalThreadCompress;++ Vector<Vector<short_ptr<ZoneEvent>>> zoneChildren;+ Vector<Vector<short_ptr<GpuEvent>>> gpuChildren;+#ifndef TRACY_NO_STATISTICS+ Vector<Vector<GhostZone>> ghostChildren;+ Vector<GhostKey> ghostFrames;+ unordered_flat_map<GhostKey, uint32_t, GhostKeyHasher, GhostKeyComparator> ghostFramesMap;+#endif++ Vector<Vector<short_ptr<ZoneEvent>>> zoneVectorCache;++ Vector<short_ptr<FrameImage>> frameImage;+ Vector<StringRef> appInfo;++ CrashEvent crashEvent;++ unordered_flat_map<uint64_t, ContextSwitch*> ctxSwitch;++ CpuData cpuData[256];+ int cpuDataCount = 0;+ unordered_flat_map<uint64_t, uint64_t> tidToPid;+ unordered_flat_map<uint64_t, CpuThreadData> cpuThreadData;++ std::pair<uint64_t, ThreadData*> threadDataLast = std::make_pair( std::numeric_limits<uint64_t>::max(), nullptr );+ std::pair<uint64_t, ContextSwitch*> ctxSwitchLast = std::make_pair( std::numeric_limits<uint64_t>::max(), nullptr );+ uint64_t checkSrclocLast = 0;+ std::pair<uint64_t, uint16_t> shrinkSrclocLast = std::make_pair( std::numeric_limits<uint64_t>::max(), 0 );+#ifndef TRACY_NO_STATISTICS+ std::pair<uint16_t, SourceLocationZones*> srclocZonesLast = std::make_pair( 0, nullptr );+ std::pair<uint16_t, GpuSourceLocationZones*> gpuZonesLast = std::make_pair( 0, nullptr );+#else+ std::pair<uint16_t, uint64_t*> srclocCntLast = std::make_pair( 0, nullptr );+ std::pair<uint16_t, uint64_t*> gpuCntLast = std::make_pair( 0, nullptr );+#endif++#ifndef TRACY_NO_STATISTICS+ Vector<ContextSwitchUsage> ctxUsage;+ bool ctxUsageReady = false;+#endif++ unordered_flat_map<uint32_t, unordered_flat_map<uint32_t, unordered_flat_map<uint32_t, std::vector<uint32_t>>>> cpuTopology;+ unordered_flat_map<uint32_t, CpuThreadTopology> cpuTopologyMap;++ unordered_flat_map<uint64_t, MemoryBlock> symbolCode;+ uint64_t symbolCodeSize = 0;++ unordered_flat_map<const char*, MemoryBlock, charutil::Hasher, charutil::Comparator> sourceFileCache;++ unordered_flat_map<uint64_t, HwSampleData> hwSamples;+ bool hasBranchRetirement = false;++ unordered_flat_map<uint64_t, uint64_t> fiberToThreadMap;+ };++ struct MbpsBlock+ {+ MbpsBlock() : mbps( 64 ), compRatio( 1.0 ), queue( 0 ), transferred( 0 ) {}++ std::shared_mutex lock;+ std::vector<float> mbps;+ float compRatio;+ size_t queue;+ uint64_t transferred;+ };++ struct FailureData+ {+ uint64_t thread;+ int16_t srcloc;+ uint32_t callstack;+ std::string message;+ };++ struct FrameImagePending+ {+ const char* image;+ uint32_t csz;+ };++public:+ enum class Failure+ {+ None,+ ZoneStack,+ ZoneDoubleEnd,+ ZoneText,+ ZoneValue,+ ZoneColor,+ ZoneName,+ MemFree,+ MemAllocTwice,+ FrameEnd,+ FrameImageIndex,+ FrameImageTwice,+ FiberLeave,+ SourceLocationOverflow,++ NUM_FAILURES+ };++ Worker( const char* addr, uint16_t port, int64_t memoryLimit );+ Worker( const char* name, const char* program, const std::vector<ImportEventTimeline>& timeline, const std::vector<ImportEventMessages>& messages, const std::vector<ImportEventPlots>& plots, const std::unordered_map<uint64_t, std::string>& threadNames );+ Worker( FileRead& f, EventType::Type eventMask = EventType::All, bool bgTasks = true, bool allowStringModification = false);+ ~Worker();++ const std::string& GetAddr() const { return m_addr; }+ uint16_t GetPort() const { return m_port; }+ const std::string& GetCaptureName() const { return m_captureName; }+ const std::string& GetCaptureProgram() const { return m_captureProgram; }+ uint64_t GetCaptureTime() const { return m_captureTime; }+ uint64_t GetExecutableTime() const { return m_executableTime; }+ const std::string& GetHostInfo() const { return m_hostInfo; }+ int64_t GetDelay() const { return m_delay; }+ int64_t GetResolution() const { return m_resolution; }+ uint64_t GetPid() const { return m_pid; };+ CpuArchitecture GetCpuArch() const { return m_data.cpuArch; }+ uint32_t GetCpuId() const { return m_data.cpuId; }+ const char* GetCpuManufacturer() const { return m_data.cpuManufacturer; }++ std::mutex& GetDataLock() { return m_data.lock; }+ size_t GetFrameCount( const FrameData& fd ) const { return fd.frames.size(); }+ size_t GetFullFrameCount( const FrameData& fd ) const;+ bool AreFramesUsed() const;+ int64_t GetFirstTime() const;+ int64_t GetLastTime() const { return m_data.lastTime; }+ uint64_t GetZoneCount() const { return m_data.zonesCnt; }+ uint64_t GetZoneExtraCount() const { return m_data.zoneExtra.size() - 1; }+ uint64_t GetGpuZoneCount() const { return m_data.gpuCnt; }+ uint64_t GetLockCount() const;+ uint64_t GetPlotCount() const;+ uint64_t GetTracyPlotCount() const;+ uint64_t GetContextSwitchCount() const;+ uint64_t GetContextSwitchPerCpuCount() const;+ bool HasContextSwitches() const { return !m_data.ctxSwitch.empty(); }+ uint64_t GetSrcLocCount() const { return m_data.sourceLocationPayload.size() + m_data.sourceLocation.size(); }+ uint64_t GetCallstackPayloadCount() const { return m_data.callstackPayload.size() - 1; }+#ifndef TRACY_NO_STATISTICS+ uint64_t GetCallstackParentPayloadCount() const { return m_data.parentCallstackPayload.size(); }+ uint64_t GetCallstackParentFrameCount() const { return m_callstackParentNextIdx; }+#endif+ uint64_t GetCallstackFrameCount() const { return m_data.callstackFrameMap.size(); }+ uint64_t GetCallstackSampleCount() const { return m_data.samplesCnt; }+ uint64_t GetSymbolsCount() const { return m_data.symbolMap.size(); }+ uint64_t GetSymbolCodeCount() const { return m_data.symbolCode.size(); }+ uint64_t GetSymbolCodeSize() const { return m_data.symbolCodeSize; }+ uint64_t GetGhostZonesCount() const { return m_data.ghostCnt; }+ uint32_t GetFrameImageCount() const { return (uint32_t)m_data.frameImage.size(); }+ uint64_t GetStringsCount() const { return m_data.strings.size() + m_data.stringData.size(); }+ uint64_t GetHwSampleCountAddress() const { return m_data.hwSamples.size(); }+ uint64_t GetHwSampleCount() const;+ bool HasHwBranchRetirement() const { return m_data.hasBranchRetirement; }+#ifndef TRACY_NO_STATISTICS+ uint64_t GetChildSamplesCountSyms() const { return m_data.childSamples.size(); }+ uint64_t GetChildSamplesCountFull() const;+ uint64_t GetContextSwitchSampleCount() const;+#endif+ uint64_t GetFrameOffset() const { return m_data.frameOffset; }+ const FrameData* GetFramesBase() const { return m_data.framesBase; }+ const Vector<FrameData*>& GetFrames() const { return m_data.frames.Data(); }+ const ContextSwitch* const GetContextSwitchData( uint64_t thread )+ {+ if( m_data.ctxSwitchLast.first == thread ) return m_data.ctxSwitchLast.second;+ return GetContextSwitchDataImpl( thread );+ }+ const CpuData* GetCpuData() const { return m_data.cpuData; }+ int GetCpuDataCpuCount() const { return m_data.cpuDataCount; }+ uint64_t GetPidFromTid( uint64_t tid ) const;+ const unordered_flat_map<uint64_t, CpuThreadData>& GetCpuThreadData() const { return m_data.cpuThreadData; }+ const unordered_flat_map<const char*, MemoryBlock, charutil::Hasher, charutil::Comparator>& GetSourceFileCache() const { return m_data.sourceFileCache; }+ uint64_t GetSourceFileCacheCount() const { return m_data.sourceFileCache.size(); }+ uint64_t GetSourceFileCacheSize() const;+ MemoryBlock GetSourceFileFromCache( const char* file ) const;+ HwSampleData* GetHwSampleData( uint64_t addr );++ int64_t GetFrameTime( const FrameData& fd, size_t idx ) const;+ int64_t GetFrameBegin( const FrameData& fd, size_t idx ) const;+ int64_t GetFrameEnd( const FrameData& fd, size_t idx ) const;+ const FrameImage* GetFrameImage( const FrameData& fd, size_t idx ) const;+ std::pair<int, int> GetFrameRange( const FrameData& fd, int64_t from, int64_t to );++ const unordered_flat_map<uint32_t, LockMap*>& GetLockMap() const { return m_data.lockMap; }+ const Vector<short_ptr<MessageData>>& GetMessages() const { return m_data.messages; }+ const Vector<GpuCtxData*>& GetGpuData() const { return m_data.gpuData; }+ const Vector<PlotData*>& GetPlots() const { return m_data.plots.Data(); }+ const Vector<ThreadData*>& GetThreadData() const { return m_data.threads; }+ const ThreadData* GetThreadData( uint64_t tid ) const;+ const MemData& GetMemoryNamed( uint64_t name ) const;+ const unordered_flat_map<uint64_t, MemData*>& GetMemNameMap() const { return m_data.memNameMap; }+ const Vector<short_ptr<FrameImage>>& GetFrameImages() const { return m_data.frameImage; }+ const Vector<StringRef>& GetAppInfo() const { return m_data.appInfo; }++ const VarArray<CallstackFrameId>& GetCallstack( uint32_t idx ) const { return *m_data.callstackPayload[idx]; }+ const CallstackFrameData* GetCallstackFrame( const CallstackFrameId& ptr ) const;+ CallstackFrameId PackPointer( uint64_t ptr ) const;+ uint64_t GetCanonicalPointer( const CallstackFrameId& id ) const;+ const SymbolData* GetSymbolData( uint64_t sym ) const;+ bool HasSymbolCode( uint64_t sym ) const;+ const char* GetSymbolCode( uint64_t sym, uint32_t& len ) const;+ uint64_t GetSymbolForAddress( uint64_t address );+ uint64_t GetSymbolForAddress( uint64_t address, uint32_t& offset );+ uint64_t GetInlineSymbolForAddress( uint64_t address ) const;+ bool HasInlineSymbolAddresses() const { return !m_data.codeSymbolMap.empty(); }+ StringIdx GetLocationForAddress( uint64_t address, uint32_t& line ) const;+ const uint64_t* GetInlineSymbolList( uint64_t sym, uint32_t len );++ unordered_flat_map<CallstackFrameId, CallstackFrameData*, CallstackFrameIdHash, CallstackFrameIdCompare>& GetCallstackFrameMap() { return m_data.callstackFrameMap; }++#ifndef TRACY_NO_STATISTICS+ const VarArray<CallstackFrameId>& GetParentCallstack( uint32_t idx ) const { return *m_data.parentCallstackPayload[idx]; }+ const CallstackFrameData* GetParentCallstackFrame( const CallstackFrameId& ptr ) const;+ const Vector<SampleDataRange>* GetSamplesForSymbol( uint64_t symAddr ) const;+ const Vector<ChildSample>* GetChildSamples( uint64_t addr ) const;+#endif++ const CrashEvent& GetCrashEvent() const { return m_data.crashEvent; }++ // Some zones may have incomplete timing data (only start time is available, end hasn't arrived yet).+ // GetZoneEnd() will try to infer the end time by looking at child zones (parent zone can't end+ // before its children have ended).+ // GetZoneEndDirect() will only return zone's direct timing data, without looking at children.+ tracy_force_inline int64_t GetZoneEnd( const ZoneEvent& ev ) { return ev.IsEndValid() ? ev.End() : GetZoneEndImpl( ev ); }+ tracy_force_inline int64_t GetZoneEnd( const GpuEvent& ev ) { return ev.GpuEnd() >= 0 ? ev.GpuEnd() : GetZoneEndImpl( ev ); }+ static tracy_force_inline int64_t GetZoneEndDirect( const ZoneEvent& ev ) { return ev.IsEndValid() ? ev.End() : ev.Start(); }+ static tracy_force_inline int64_t GetZoneEndDirect( const GpuEvent& ev ) { return ev.GpuEnd() >= 0 ? ev.GpuEnd() : ev.GpuStart(); }++ uint32_t FindStringIdx( const char* str ) const;+ const char* GetString( uint64_t ptr ) const;+ const char* GetString( const StringRef& ref ) const;+ const char* GetString( const StringIdx& idx ) const;+ const char* GetThreadName( uint64_t id ) const;+ bool IsThreadLocal( uint64_t id );+ bool IsThreadFiber( uint64_t id );+ const SourceLocation& GetSourceLocation( int16_t srcloc ) const;+ std::pair<const char*, const char*> GetExternalName( uint64_t id ) const;++ const char* GetZoneName( const SourceLocation& srcloc ) const;+ const char* GetZoneName( const ZoneEvent& ev ) const;+ const char* GetZoneName( const ZoneEvent& ev, const SourceLocation& srcloc ) const;+ const char* GetZoneName( const GpuEvent& ev ) const;++ tracy_force_inline const Vector<short_ptr<ZoneEvent>>& GetZoneChildren( int32_t idx ) const { return m_data.zoneChildren[idx]; }+ tracy_force_inline const Vector<short_ptr<GpuEvent>>& GetGpuChildren( int32_t idx ) const { return m_data.gpuChildren[idx]; }+#ifndef TRACY_NO_STATISTICS+ tracy_force_inline const Vector<GhostZone>& GetGhostChildren( int32_t idx ) const { return m_data.ghostChildren[idx]; }+ tracy_force_inline const GhostKey& GetGhostFrame( const Int24& frame ) const { return m_data.ghostFrames[frame.Val()]; }+#endif++ tracy_force_inline const bool HasZoneExtra( const ZoneEvent& ev ) const { return ev.extra != 0; }+ tracy_force_inline const ZoneExtra& GetZoneExtra( const ZoneEvent& ev ) const { return m_data.zoneExtra[ev.extra]; }++ std::vector<int16_t> GetMatchingSourceLocation( const char* query, bool ignoreCase ) const;++ const unordered_flat_map<uint64_t, SymbolData>& GetSymbolMap() const { return m_data.symbolMap; }++#ifndef TRACY_NO_STATISTICS+ SourceLocationZones& GetZonesForSourceLocation( int16_t srcloc );+ const SourceLocationZones& GetZonesForSourceLocation( int16_t srcloc ) const;+ const unordered_flat_map<int16_t, SourceLocationZones>& GetSourceLocationZones() const { return m_data.sourceLocationZones; }+ const unordered_flat_map<int16_t, GpuSourceLocationZones>& GetGpuSourceLocationZones() const { return m_data.gpuSourceLocationZones; }+ bool AreSourceLocationZonesReady() const { return m_data.sourceLocationZonesReady; }+ bool AreGpuSourceLocationZonesReady() const { return m_data.gpuSourceLocationZonesReady; }+ bool IsCpuUsageReady() const { return m_data.ctxUsageReady; }+ const Vector<ContextSwitchUsage>& GetCpuUsage() const { return m_data.ctxUsage; }++ const unordered_flat_map<uint64_t, SymbolStats>& GetSymbolStats() const { return m_data.symbolStats; }+ const SymbolStats* GetSymbolStats( uint64_t symAddr ) const;+ const unordered_flat_map<CallstackFrameId, uint32_t, CallstackFrameIdHash, CallstackFrameIdCompare>* GetSymbolInstructionPointers( uint64_t symAddr ) const;+ bool AreCallstackSamplesReady() const { return m_data.callstackSamplesReady; }+ bool AreGhostZonesReady() const { return m_data.ghostZonesReady; }+ bool AreSymbolSamplesReady() const { return m_data.symbolSamplesReady; }+#endif++ tracy_force_inline uint16_t CompressThread( uint64_t thread ) { return m_data.localThreadCompress.CompressThread( thread ); }+ tracy_force_inline uint64_t DecompressThread( uint16_t thread ) const { return m_data.localThreadCompress.DecompressThread( thread ); }+ tracy_force_inline uint64_t DecompressThreadExternal( uint16_t thread ) const { return m_data.externalThreadCompress.DecompressThread( thread ); }++ std::shared_mutex& GetMbpsDataLock() { return m_mbpsData.lock; }+ const std::vector<float>& GetMbpsData() const { return m_mbpsData.mbps; }+ float GetCompRatio() const { return m_mbpsData.compRatio; }+ size_t GetSendQueueSize() const { return m_mbpsData.queue; }+ size_t GetSendInFlight() const { return m_serverQuerySpaceBase - m_serverQuerySpaceLeft; }+ uint64_t GetDataTransferred() const { return m_mbpsData.transferred; }++ bool HasData() const { return m_hasData.load( std::memory_order_acquire ); }+ bool IsConnected() const { return m_connected.load( std::memory_order_relaxed ); }+ bool IsDataStatic() const { return !m_thread.joinable(); }+ bool IsBackgroundDone() const { return m_backgroundDone.load( std::memory_order_relaxed ); }+ bool IsOnDemand() const { return m_onDemand; }+ void Shutdown() { m_shutdown.store( true, std::memory_order_relaxed ); }+ void Disconnect();+ bool WasDisconnectIssued() const { return m_disconnect; }+ int64_t GetMemoryLimit() const { return m_memoryLimit; }++ void Write( FileWrite& f, bool fiDict );+ int GetTraceVersion() const { return m_traceVersion; }+ uint8_t GetHandshakeStatus() const { return m_handshake.load( std::memory_order_relaxed ); }+ int64_t GetSamplingPeriod() const { return m_samplingPeriod; }+ bool AreSamplesInconsistent() const { return m_inconsistentSamples; }++ static const LoadProgress& GetLoadProgress() { return s_loadProgress; }+ int64_t GetLoadTime() const { return m_loadTime; }++ void ClearFailure() { m_failure = Failure::None; }+ Failure GetFailureType() const { return m_failure; }+ const FailureData& GetFailureData() const { return m_failureData; }+ static const char* GetFailureString( Failure failure );++ const char* UnpackFrameImage( const FrameImage& image ) { return m_texcomp.Unpack( image ); }++ const Vector<Parameter>& GetParameters() const { return m_params; }+ void SetParameter( size_t paramIdx, int32_t val );++ const decltype(DataBlock::cpuTopology)& GetCpuTopology() const { return m_data.cpuTopology; }+ const CpuThreadTopology* GetThreadTopology( uint32_t cpuThread ) const;++ std::pair<uint64_t, uint64_t> GetTextureCompressionBytes() const { return std::make_pair( m_texcomp.GetInputBytesCount(), m_texcomp.GetOutputBytesCount() ); }++ void DoPostponedSymbols();+ void DoPostponedInlineSymbols();+ void DoPostponedWork();+ void DoPostponedWorkAll();++ void CacheSourceFiles();++ StringLocation StoreString(const char* str, size_t sz);++ std::vector<uint32_t>& GetPendingThreadHints() { return m_pendingThreadHints; }+ void ClearPendingThreadHints() { m_pendingThreadHints.clear(); }++private:+ void Network();+ void Exec();+ void Query( ServerQuery type, uint64_t data, uint32_t extra = 0 );+ void QueryTerminate();+ void QuerySourceFile( const char* fn, const char* image );+ void QueryDataTransfer( const void* ptr, size_t size );++ tracy_force_inline bool DispatchProcess( const QueueItem& ev, const char*& ptr );+ tracy_force_inline bool Process( const QueueItem& ev );+ tracy_force_inline void ProcessThreadContext( const QueueThreadContext& ev );+ tracy_force_inline void ProcessZoneBegin( const QueueZoneBegin& ev );+ tracy_force_inline void ProcessZoneBeginCallstack( const QueueZoneBegin& ev );+ tracy_force_inline void ProcessZoneBeginAllocSrcLoc( const QueueZoneBeginLean& ev );+ tracy_force_inline void ProcessZoneBeginAllocSrcLocCallstack( const QueueZoneBeginLean& ev );+ tracy_force_inline void ProcessZoneEnd( const QueueZoneEnd& ev );+ tracy_force_inline void ProcessZoneValidation( const QueueZoneValidation& ev );+ tracy_force_inline void ProcessFrameMark( const QueueFrameMark& ev );+ tracy_force_inline void ProcessFrameMarkStart( const QueueFrameMark& ev );+ tracy_force_inline void ProcessFrameMarkEnd( const QueueFrameMark& ev );+ tracy_force_inline void ProcessFrameVsync( const QueueFrameVsync& ev );+ tracy_force_inline void ProcessFrameImage( const QueueFrameImage& ev );+ tracy_force_inline void ProcessZoneText();+ tracy_force_inline void ProcessZoneName();+ tracy_force_inline void ProcessZoneColor( const QueueZoneColor& ev );+ tracy_force_inline void ProcessZoneValue( const QueueZoneValue& ev );+ tracy_force_inline void ProcessLockAnnounce( const QueueLockAnnounce& ev );+ tracy_force_inline void ProcessLockTerminate( const QueueLockTerminate& ev );+ tracy_force_inline void ProcessLockWait( const QueueLockWait& ev );+ tracy_force_inline void ProcessLockObtain( const QueueLockObtain& ev );+ tracy_force_inline void ProcessLockRelease( const QueueLockRelease& ev );+ tracy_force_inline void ProcessLockSharedWait( const QueueLockWait& ev );+ tracy_force_inline void ProcessLockSharedObtain( const QueueLockObtain& ev );+ tracy_force_inline void ProcessLockSharedRelease( const QueueLockReleaseShared& ev );+ tracy_force_inline void ProcessLockMark( const QueueLockMark& ev );+ tracy_force_inline void ProcessLockName( const QueueLockName& ev );+ tracy_force_inline void ProcessPlotDataInt( const QueuePlotDataInt& ev );+ tracy_force_inline void ProcessPlotDataFloat( const QueuePlotDataFloat& ev );+ tracy_force_inline void ProcessPlotDataDouble( const QueuePlotDataDouble& ev );+ tracy_force_inline void ProcessPlotConfig( const QueuePlotConfig& ev );+ tracy_force_inline void ProcessMessage( const QueueMessage& ev );+ tracy_force_inline void ProcessMessageLiteral( const QueueMessageLiteral& ev );+ tracy_force_inline void ProcessMessageColor( const QueueMessageColor& ev );+ tracy_force_inline void ProcessMessageLiteralColor( const QueueMessageColorLiteral& ev );+ tracy_force_inline void ProcessMessageCallstack( const QueueMessage& ev );+ tracy_force_inline void ProcessMessageLiteralCallstack( const QueueMessageLiteral& ev );+ tracy_force_inline void ProcessMessageColorCallstack( const QueueMessageColor& ev );+ tracy_force_inline void ProcessMessageLiteralColorCallstack( const QueueMessageColorLiteral& ev );+ tracy_force_inline void ProcessMessageAppInfo( const QueueMessage& ev );+ tracy_force_inline void ProcessGpuNewContext( const QueueGpuNewContext& ev );+ tracy_force_inline void ProcessGpuZoneBegin( const QueueGpuZoneBegin& ev, bool serial );+ tracy_force_inline void ProcessGpuZoneBeginCallstack( const QueueGpuZoneBegin& ev, bool serial );+ tracy_force_inline void ProcessGpuZoneBeginAllocSrcLoc( const QueueGpuZoneBeginLean& ev, bool serial );+ tracy_force_inline void ProcessGpuZoneBeginAllocSrcLocCallstack( const QueueGpuZoneBeginLean& ev, bool serial );+ tracy_force_inline void ProcessGpuZoneEnd( const QueueGpuZoneEnd& ev, bool serial );+ tracy_force_inline void ProcessGpuTime( const QueueGpuTime& ev );+ tracy_force_inline void ProcessGpuCalibration( const QueueGpuCalibration& ev );+ tracy_force_inline void ProcessGpuTimeSync( const QueueGpuTimeSync& ev );+ tracy_force_inline void ProcessGpuContextName( const QueueGpuContextName& ev );+ tracy_force_inline MemEvent* ProcessMemAlloc( const QueueMemAlloc& ev );+ tracy_force_inline MemEvent* ProcessMemAllocNamed( const QueueMemAlloc& ev );+ tracy_force_inline MemEvent* ProcessMemFree( const QueueMemFree& ev );+ tracy_force_inline MemEvent* ProcessMemFreeNamed( const QueueMemFree& ev );+ tracy_force_inline void ProcessMemDiscard( const QueueMemDiscard& ev );+ tracy_force_inline void ProcessMemAllocCallstack( const QueueMemAlloc& ev );+ tracy_force_inline void ProcessMemAllocCallstackNamed( const QueueMemAlloc& ev );+ tracy_force_inline void ProcessMemFreeCallstack( const QueueMemFree& ev );+ tracy_force_inline void ProcessMemFreeCallstackNamed( const QueueMemFree& ev );+ tracy_force_inline void ProcessMemDiscardCallstack( const QueueMemDiscard& ev );+ tracy_force_inline void ProcessCallstackSerial();+ tracy_force_inline void ProcessCallstack();+ tracy_force_inline void ProcessCallstackSample( const QueueCallstackSample& ev );+ tracy_force_inline void ProcessCallstackSampleContextSwitch( const QueueCallstackSample& ev );+ tracy_force_inline void ProcessCallstackFrameSize( const QueueCallstackFrameSize& ev );+ tracy_force_inline void ProcessCallstackFrame( const QueueCallstackFrame& ev, bool querySymbols );+ tracy_force_inline void ProcessSymbolInformation( const QueueSymbolInformation& ev );+ tracy_force_inline void ProcessCrashReport( const QueueCrashReport& ev );+ tracy_force_inline void ProcessSysTime( const QueueSysTime& ev );+ tracy_force_inline void ProcessSysPower( const QueueSysPower& ev );+ tracy_force_inline void ProcessContextSwitch( const QueueContextSwitch& ev );+ tracy_force_inline void ProcessThreadWakeup( const QueueThreadWakeup& ev );+ tracy_force_inline void ProcessTidToPid( const QueueTidToPid& ev );+ tracy_force_inline void ProcessHwSampleCpuCycle( const QueueHwSample& ev );+ tracy_force_inline void ProcessHwSampleInstructionRetired( const QueueHwSample& ev );+ tracy_force_inline void ProcessHwSampleCacheReference( const QueueHwSample& ev );+ tracy_force_inline void ProcessHwSampleCacheMiss( const QueueHwSample& ev );+ tracy_force_inline void ProcessHwSampleBranchRetired( const QueueHwSample& ev );+ tracy_force_inline void ProcessHwSampleBranchMiss( const QueueHwSample& ev );+ tracy_force_inline void ProcessParamSetup( const QueueParamSetup& ev );+ tracy_force_inline void ProcessSourceCodeNotAvailable( const QueueSourceCodeNotAvailable& ev );+ tracy_force_inline void ProcessCpuTopology( const QueueCpuTopology& ev );+ tracy_force_inline void ProcessMemNamePayload( const QueueMemNamePayload& ev );+ tracy_force_inline void ProcessThreadGroupHint( const QueueThreadGroupHint& ev );+ tracy_force_inline void ProcessFiberEnter( const QueueFiberEnter& ev );+ tracy_force_inline void ProcessFiberLeave( const QueueFiberLeave& ev );++ tracy_force_inline ZoneEvent* AllocZoneEvent();+ tracy_force_inline void ProcessZoneBeginImpl( ZoneEvent* zone, const QueueZoneBegin& ev );+ tracy_force_inline void ProcessZoneBeginAllocSrcLocImpl( ZoneEvent* zone, const QueueZoneBeginLean& ev );+ tracy_force_inline void ProcessGpuZoneBeginImpl( GpuEvent* zone, const QueueGpuZoneBegin& ev, bool serial );+ tracy_force_inline void ProcessGpuZoneBeginAllocSrcLocImpl( GpuEvent* zone, const QueueGpuZoneBeginLean& ev, bool serial );+ tracy_force_inline void ProcessGpuZoneBeginImplCommon( GpuEvent* zone, const QueueGpuZoneBeginLean& ev, bool serial );+ tracy_force_inline void ProcessPlotDataImpl( uint64_t name, int64_t evTime, double val );+ tracy_force_inline MemEvent* ProcessMemAllocImpl( MemData& memdata, const QueueMemAlloc& ev );+ tracy_force_inline MemEvent* ProcessMemFreeImpl( MemData& memdata, const QueueMemFree& ev );+ tracy_force_inline void ProcessCallstackSampleImpl( const SampleData& sd, ThreadData& td );+ tracy_force_inline void ProcessCallstackSampleInsertSample( const SampleData& sd, ThreadData& td );+#ifndef TRACY_NO_STATISTICS+ tracy_force_inline void ProcessCallstackSampleImplStats( const SampleData& sd, ThreadData& td );+#endif++ void ZoneStackFailure( uint64_t thread, const ZoneEvent* ev );+ void ZoneDoubleEndFailure( uint64_t thread, const ZoneEvent* ev );+ void ZoneTextFailure( uint64_t thread, const char* text );+ void ZoneValueFailure( uint64_t thread, uint64_t value );+ void ZoneColorFailure( uint64_t thread );+ void ZoneNameFailure( uint64_t thread );+ void MemFreeFailure( uint64_t thread );+ void MemAllocTwiceFailure( uint64_t thread );+ void FrameEndFailure();+ void FrameImageIndexFailure();+ void FrameImageTwiceFailure();+ void FiberLeaveFailure();+ void SourceLocationOverflowFailure();++ tracy_force_inline void CheckSourceLocation( uint64_t ptr );+ void NewSourceLocation( uint64_t ptr );+ tracy_force_inline int16_t ShrinkSourceLocation( uint64_t srcloc )+ {+ if( m_data.shrinkSrclocLast.first == srcloc ) return m_data.shrinkSrclocLast.second;+ return ShrinkSourceLocationReal( srcloc );+ }+ int16_t ShrinkSourceLocationReal( uint64_t srcloc );+ int16_t NewShrinkedSourceLocation( uint64_t srcloc );++ tracy_force_inline void MemAllocChanged( MemData& memdata, int64_t time );+ void CreateMemAllocPlot( MemData& memdata );+ void ReconstructMemAllocPlot( MemData& memdata );++ void InsertMessageData( MessageData* msg );++ ThreadData* NoticeThreadReal( uint64_t thread );+ ThreadData* NewThread( uint64_t thread, bool fiber, int32_t groupHint );+ tracy_force_inline ThreadData* NoticeThread( uint64_t thread )+ {+ if( m_data.threadDataLast.first == thread ) return m_data.threadDataLast.second;+ return NoticeThreadReal( thread );+ }+ ThreadData* RetrieveThreadReal( uint64_t thread );+ tracy_force_inline ThreadData* RetrieveThread( uint64_t thread )+ {+ if( m_data.threadDataLast.first == thread ) return m_data.threadDataLast.second;+ return RetrieveThreadReal( thread );+ }++ tracy_force_inline ThreadData* GetCurrentThreadData();++#ifndef TRACY_NO_STATISTICS+ SourceLocationZones* GetSourceLocationZones( uint16_t srcloc )+ {+ if( m_data.srclocZonesLast.first == srcloc ) return m_data.srclocZonesLast.second;+ return GetSourceLocationZonesReal( srcloc );+ }+ SourceLocationZones* GetSourceLocationZonesReal( uint16_t srcloc );++ GpuSourceLocationZones* GetGpuSourceLocationZones( uint16_t srcloc )+ {+ if( m_data.gpuZonesLast.first == srcloc ) return m_data.gpuZonesLast.second;+ return GetGpuSourceLocationZonesReal( srcloc );+ }+ GpuSourceLocationZones* GetGpuSourceLocationZonesReal( uint16_t srcloc );+#else+ uint64_t* GetSourceLocationZonesCnt( uint16_t srcloc )+ {+ if( m_data.srclocCntLast.first == srcloc ) return m_data.srclocCntLast.second;+ return GetSourceLocationZonesCntReal( srcloc );+ }+ uint64_t* GetSourceLocationZonesCntReal( uint16_t srcloc );++ uint64_t* GetGpuSourceLocationZonesCnt( uint16_t srcloc )+ {+ if( m_data.gpuCntLast.first == srcloc ) return m_data.gpuCntLast.second;+ return GetGpuSourceLocationZonesCntReal( srcloc );+ }+ uint64_t* GetGpuSourceLocationZonesCntReal( uint16_t srcloc );+#endif++ tracy_force_inline void NewZone( ZoneEvent* zone );++ void InsertLockEvent( LockMap& lockmap, LockEvent* lev, uint64_t thread, int64_t time );++ bool CheckString( uint64_t ptr );+ void CheckThreadString( uint64_t id );+ void CheckFiberName( uint64_t id, uint64_t tid );+ void CheckExternalName( uint64_t id );++ void AddSourceLocation( const QueueSourceLocation& srcloc );+ void AddSourceLocationPayload( const char* data, size_t sz );++ void AddString( uint64_t ptr, const char* str, size_t sz );+ void AddThreadString( uint64_t id, const char* str, size_t sz );+ void AddFiberName( uint64_t id, const char* str, size_t sz );+ void AddSingleString( const char* str, size_t sz );+ void AddSingleStringFailure( const char* str, size_t sz );+ void AddSecondString( const char* str, size_t sz );+ void AddExternalName( uint64_t ptr, const char* str, size_t sz );+ void AddExternalThreadName( uint64_t ptr, const char* str, size_t sz );+ void AddFrameImageData( const char* data, size_t sz );+ void AddSymbolCode( uint64_t ptr, const char* data, size_t sz );+ void AddSourceCode( uint32_t id, const char* data, size_t sz );++ tracy_force_inline void AddCallstackPayload( const char* data, size_t sz );+ tracy_force_inline void AddCallstackAllocPayload( const char* data );+ uint32_t MergeCallstacks( uint32_t first, uint32_t second );++ void InsertPlot( PlotData* plot, int64_t time, double val );+ void HandlePlotName( uint64_t name, const char* str, size_t sz );+ void HandleFrameName( uint64_t name, const char* str, size_t sz );++ void HandlePostponedSamples();+ void HandlePostponedGhostZones();++ bool IsFailureThreadStringRetrieved();+ bool IsSourceLocationRetrieved( int16_t srcloc );+ bool IsCallstackRetrieved( uint32_t callstack );+ bool HasAllFailureData();+ void HandleFailure( const char* ptr, const char* end );+ void DispatchFailure( const QueueItem& ev, const char*& ptr );++ uint32_t GetSingleStringIdx();+ uint32_t GetSecondStringIdx();+ const ContextSwitch* const GetContextSwitchDataImpl( uint64_t thread );++ void CacheSource( const StringRef& str, const StringIdx& image = StringIdx() );+ void CacheSourceFromFile( const char* fn );++ tracy_force_inline Vector<short_ptr<ZoneEvent>>& GetZoneChildrenMutable( int32_t idx ) { return m_data.zoneChildren[idx]; }+ tracy_force_inline Vector<short_ptr<GpuEvent>>& GetGpuChildrenMutable( int32_t idx ) { return m_data.gpuChildren[idx]; }+#ifndef TRACY_NO_STATISTICS+ tracy_force_inline Vector<GhostZone>& GetGhostChildrenMutable( int32_t idx ) { return m_data.ghostChildren[idx]; }+#endif++#ifndef TRACY_NO_STATISTICS+ void ReconstructContextSwitchUsage();+ bool UpdateSampleStatistics( uint32_t callstack, uint32_t count, bool canPostpone );+ void UpdateSampleStatisticsPostponed( decltype(Worker::DataBlock::postponedSamples.begin())& it );+ void UpdateSampleStatisticsImpl( const CallstackFrameData** frames, uint16_t framesCount, uint32_t count, const VarArray<CallstackFrameId>& cs );+ tracy_force_inline void GetStackWithInlines( Vector<InlineStackData>& ret, const VarArray<CallstackFrameId>& cs );+ tracy_force_inline int AddGhostZone( const VarArray<CallstackFrameId>& cs, Vector<GhostZone>* vec, uint64_t t );+#endif++ tracy_force_inline int64_t ReadTimeline( FileRead& f, ZoneEvent* zone, int64_t refTime, int32_t& childIdx );+ tracy_force_inline int64_t ReadTimelineHaveSize( FileRead& f, ZoneEvent* zone, int64_t refTime, int32_t& childIdx, uint32_t sz );+ tracy_force_inline void ReadTimeline( FileRead& f, GpuEvent* zone, int64_t& refTime, int64_t& refGpuTime, int32_t& childIdx );+ tracy_force_inline void ReadTimelineHaveSize( FileRead& f, GpuEvent* zone, int64_t& refTime, int64_t& refGpuTime, int32_t& childIdx, uint64_t sz );++#ifndef TRACY_NO_STATISTICS+ tracy_force_inline void ReconstructZoneStatistics( uint8_t* countMap, ZoneEvent& zone, uint16_t thread );+ tracy_force_inline void ReconstructZoneStatistics( GpuEvent& zone, uint16_t thread );+#else+ tracy_force_inline void CountZoneStatistics( ZoneEvent* zone );+ tracy_force_inline void CountZoneStatistics( GpuEvent* zone );+#endif++ tracy_force_inline ZoneExtra& GetZoneExtraMutable( const ZoneEvent& ev ) { return m_data.zoneExtra[ev.extra]; }+ tracy_force_inline ZoneExtra& AllocZoneExtra( ZoneEvent& ev );+ tracy_force_inline ZoneExtra& RequestZoneExtra( ZoneEvent& ev );++ int64_t GetZoneEndImpl( const ZoneEvent& ev );+ int64_t GetZoneEndImpl( const GpuEvent& ev );++ void UpdateMbps( int64_t td );++ int64_t ReadTimeline( FileRead& f, Vector<short_ptr<ZoneEvent>>& vec, uint32_t size, int64_t refTime, int32_t& childIdx );+ void ReadTimeline( FileRead& f, Vector<short_ptr<GpuEvent>>& vec, uint64_t size, int64_t& refTime, int64_t& refGpuTime, int32_t& childIdx );++ tracy_force_inline void WriteTimeline( FileWrite& f, const Vector<short_ptr<ZoneEvent>>& vec, int64_t& refTime );+ tracy_force_inline void WriteTimeline( FileWrite& f, const Vector<short_ptr<GpuEvent>>& vec, int64_t& refTime, int64_t& refGpuTime );+ template<typename Adapter, typename V>+ void WriteTimelineImpl( FileWrite& f, const V& vec, int64_t& refTime );+ template<typename Adapter, typename V>+ void WriteTimelineImpl( FileWrite& f, const V& vec, int64_t& refTime, int64_t& refGpuTime );++ int64_t TscTime( int64_t tsc ) { return int64_t( ( tsc - m_data.baseTime ) * m_timerMul ); }+ int64_t TscTime( uint64_t tsc ) { return int64_t( ( tsc - m_data.baseTime ) * m_timerMul ); }+ int64_t TscPeriod( uint64_t tsc ) { return int64_t( tsc * m_timerMul ); }++ Socket m_sock;+ std::string m_addr;+ uint16_t m_port;++ std::thread m_thread;+ std::thread m_threadNet;+ std::atomic<bool> m_connected { false };+ std::atomic<bool> m_hasData;+ std::atomic<bool> m_shutdown { false };++ std::atomic<bool> m_backgroundDone { true };+ std::thread m_threadBackground;++ int64_t m_delay;+ int64_t m_resolution;+ double m_timerMul;+ std::string m_captureName;+ std::string m_captureProgram;+ uint64_t m_captureTime;+ uint64_t m_executableTime;+ std::string m_hostInfo;+ uint64_t m_pid;+ int64_t m_samplingPeriod;+ bool m_terminate = false;+ bool m_crashed = false;+ bool m_disconnect = false;+ void* m_stream; // LZ4_streamDecode_t*+ char* m_buffer;+ int m_bufferOffset;+ bool m_onDemand;+ bool m_ignoreMemFreeFaults;+ bool m_ignoreFrameEndFaults;+ bool m_codeTransfer;+ bool m_combineSamples;+ bool m_identifySamples = false;+ bool m_inconsistentSamples;+ bool m_allowStringModification = false;++ short_ptr<GpuCtxData> m_gpuCtxMap[256];+ uint32_t m_pendingCallstackId = 0;+ int16_t m_pendingSourceLocationPayload = 0;+ Vector<uint64_t> m_sourceLocationQueue;+ unordered_flat_map<uint64_t, int16_t> m_sourceLocationShrink;+ unordered_flat_map<uint64_t, ThreadData*> m_threadMap;+ unordered_flat_map<uint32_t, FrameData*> m_vsyncFrameMap;+ FrameImagePending m_pendingFrameImageData = {};+ unordered_flat_map<uint64_t, SymbolPending> m_pendingSymbols;+ unordered_flat_set<StringRef, StringRefHasher, StringRefComparator> m_pendingFileStrings;+ unordered_flat_set<StringRef, StringRefHasher, StringRefComparator> m_checkedFileStrings;+ StringLocation m_pendingSingleString = {};+ StringLocation m_pendingSecondString = {};++ uint32_t m_pendingStrings;+ uint32_t m_pendingThreads;+ uint32_t m_pendingFibers;+ uint32_t m_pendingExternalNames;+ uint32_t m_pendingSourceLocation;+ uint32_t m_pendingCallstackFrames;+ uint8_t m_pendingCallstackSubframes;+ uint32_t m_pendingSymbolCode;++ CallstackFrameData* m_callstackFrameStaging;+ uint64_t m_callstackFrameStagingPtr;+ uint64_t m_callstackAllocNextIdx = 0;+ uint64_t m_callstackParentNextIdx = 0;++ uint32_t m_serialNextCallstack = 0;+ uint64_t m_memNamePayload = 0;++ Slab<64*1024*1024> m_slab;+ int64_t m_memoryLimit;++ DataBlock m_data;+ MbpsBlock m_mbpsData;++ int m_traceVersion;+ std::atomic<uint8_t> m_handshake { 0 };++ static LoadProgress s_loadProgress;+ int64_t m_loadTime;++ Failure m_failure = Failure::None;+ FailureData m_failureData = {};++ PlotData* m_sysTimePlot = nullptr;++ Vector<ServerQueryPacket> m_serverQueryQueue, m_serverQueryQueuePrio;+ size_t m_serverQuerySpaceLeft, m_serverQuerySpaceBase;++ unordered_flat_map<uint64_t, int32_t> m_frameImageStaging;+ char* m_frameImageBuffer = nullptr;+ size_t m_frameImageBufferSize = 0;+ TextureCompression m_texcomp;++ uint64_t m_threadCtx = 0;+ ThreadData* m_threadCtxData = nullptr;+ int64_t m_refTimeThread = 0;+ int64_t m_refTimeSerial = 0;+ int64_t m_refTimeCtx = 0;+ int64_t m_refTimeGpu = 0;++ std::atomic<uint64_t> m_bytes { 0 };+ std::atomic<uint64_t> m_decBytes { 0 };++ struct NetBuffer+ {+ int bufferOffset;+ int size;+ };++ std::vector<NetBuffer> m_netRead;+ std::mutex m_netReadLock;+ std::condition_variable m_netReadCv;++ int m_netWriteCnt = 0;+ std::mutex m_netWriteLock;+ std::condition_variable m_netWriteCv;++#ifdef TRACY_NO_STATISTICS+ Vector<ZoneEvent*> m_zoneEventPool;+#endif++ Vector<Parameter> m_params;++ char* m_tmpBuf = nullptr;+ size_t m_tmpBufSize = 0;++ unordered_flat_map<uint64_t, uint32_t> m_nextCallstack;+ unordered_flat_map<uint32_t, const char*> m_sourceCodeQuery;+ uint32_t m_nextSourceCodeQuery = 0;++ unordered_flat_map<uint64_t, PowerData> m_powerData;++ Vector<InlineStackData> m_inlineStack;++ std::vector<uint32_t> m_pendingThreadHints;+};++}++#endif
+ cbits/tracy/server/tracy_pdqsort.h view
@@ -0,0 +1,524 @@+/*+ pdqsort.h - Pattern-defeating quicksort.++ Copyright (c) 2015 Orson Peters++ This software is provided 'as-is', without any express or implied warranty. In no event will the+ authors be held liable for any damages arising from the use of this software.++ Permission is granted to anyone to use this software for any purpose, including commercial+ applications, and to alter it and redistribute it freely, subject to the following restrictions:++ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the+ original software. If you use this software in a product, an acknowledgment in the product+ documentation would be appreciated but is not required.++ 2. Altered source versions must be plainly marked as 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 TRACY_PDQSORT_H+#define TRACY_PDQSORT_H++#include "../public/common/TracyForceInline.hpp"++#include <algorithm>+#include <cstddef>+#include <functional>+#include <utility>+#include <iterator>++#include <cstdint>+#include <type_traits>+#define PDQSORT_PREFER_MOVE(x) std::move(x)++namespace tracy{++namespace pdqsort_detail {+ enum {+ // Partitions below this size are sorted using insertion sort.+ insertion_sort_threshold = 24,++ // Partitions above this size use Tukey's ninther to select the pivot.+ ninther_threshold = 128,++ // When we detect an already sorted partition, attempt an insertion sort that allows this+ // amount of element moves before giving up.+ partial_insertion_sort_limit = 8,++ // Must be multiple of 8 due to loop unrolling, and < 256 to fit in unsigned char.+ block_size = 64,++ // Cacheline size, assumes power of two.+ cacheline_size = 64++ };++ template<class T> struct is_default_compare : std::false_type { };+ template<class T> struct is_default_compare<std::less<T>> : std::true_type { };+ template<class T> struct is_default_compare<std::greater<T>> : std::true_type { };++ // Returns floor(log2(n)), assumes n > 0.+ template<class T>+ tracy_force_inline int log2(T n) {+ int log = 0;+ while (n >>= 1) ++log;+ return log;+ }++ // Sorts [begin, end) using insertion sort with the given comparison function.+ template<class Iter, class Compare>+ tracy_force_inline void insertion_sort(Iter begin, Iter end, Compare comp) {+ typedef typename std::iterator_traits<Iter>::value_type T;+ if (begin == end) return;++ for (Iter cur = begin + 1; cur != end; ++cur) {+ Iter sift = cur;+ Iter sift_1 = cur - 1;++ // Compare first so we can avoid 2 moves for an element already positioned correctly.+ if (comp(*sift, *sift_1)) {+ T tmp = PDQSORT_PREFER_MOVE(*sift);++ do { *sift-- = PDQSORT_PREFER_MOVE(*sift_1); }+ while (sift != begin && comp(tmp, *--sift_1));++ *sift = PDQSORT_PREFER_MOVE(tmp);+ }+ }+ }++ // Sorts [begin, end) using insertion sort with the given comparison function. Assumes+ // *(begin - 1) is an element smaller than or equal to any element in [begin, end).+ template<class Iter, class Compare>+ tracy_force_inline void unguarded_insertion_sort(Iter begin, Iter end, Compare comp) {+ typedef typename std::iterator_traits<Iter>::value_type T;+ if (begin == end) return;++ for (Iter cur = begin + 1; cur != end; ++cur) {+ Iter sift = cur;+ Iter sift_1 = cur - 1;++ // Compare first so we can avoid 2 moves for an element already positioned correctly.+ if (comp(*sift, *sift_1)) {+ T tmp = PDQSORT_PREFER_MOVE(*sift);++ do { *sift-- = PDQSORT_PREFER_MOVE(*sift_1); }+ while (comp(tmp, *--sift_1));++ *sift = PDQSORT_PREFER_MOVE(tmp);+ }+ }+ }++ // Attempts to use insertion sort on [begin, end). Will return false if more than+ // partial_insertion_sort_limit elements were moved, and abort sorting. Otherwise it will+ // successfully sort and return true.+ template<class Iter, class Compare>+ tracy_force_inline bool partial_insertion_sort(Iter begin, Iter end, Compare comp) {+ typedef typename std::iterator_traits<Iter>::value_type T;+ if (begin == end) return true;+ + std::size_t limit = 0;+ for (Iter cur = begin + 1; cur != end; ++cur) {+ Iter sift = cur;+ Iter sift_1 = cur - 1;++ // Compare first so we can avoid 2 moves for an element already positioned correctly.+ if (comp(*sift, *sift_1)) {+ T tmp = PDQSORT_PREFER_MOVE(*sift);++ do { *sift-- = PDQSORT_PREFER_MOVE(*sift_1); }+ while (sift != begin && comp(tmp, *--sift_1));++ *sift = PDQSORT_PREFER_MOVE(tmp);+ limit += cur - sift;+ }++ if (limit > partial_insertion_sort_limit) return false;+ }++ return true;+ }++ template<class Iter, class Compare>+ tracy_force_inline void sort2(Iter a, Iter b, Compare comp) {+ if (comp(*b, *a)) std::iter_swap(a, b);+ }++ // Sorts the elements *a, *b and *c using comparison function comp.+ template<class Iter, class Compare>+ tracy_force_inline void sort3(Iter a, Iter b, Iter c, Compare comp) {+ sort2(a, b, comp);+ sort2(b, c, comp);+ sort2(a, b, comp);+ }++ template<class T>+ tracy_force_inline T* align_cacheline(T* p) {+#if defined(UINTPTR_MAX)+ std::uintptr_t ip = reinterpret_cast<std::uintptr_t>(p);+#else+ std::size_t ip = reinterpret_cast<std::size_t>(p);+#endif+ ip = (ip + cacheline_size - 1) & -cacheline_size;+ return reinterpret_cast<T*>(ip);+ }++ template<class Iter>+ tracy_force_inline void swap_offsets(Iter first, Iter last,+ unsigned char* offsets_l, unsigned char* offsets_r,+ size_t num, bool use_swaps) {+ typedef typename std::iterator_traits<Iter>::value_type T;+ if (use_swaps) {+ // This case is needed for the descending distribution, where we need+ // to have proper swapping for pdqsort to remain O(n).+ for (size_t i = 0; i < num; ++i) {+ std::iter_swap(first + offsets_l[i], last - offsets_r[i]);+ }+ } else if (num > 0) {+ Iter l = first + offsets_l[0]; Iter r = last - offsets_r[0];+ T tmp(PDQSORT_PREFER_MOVE(*l)); *l = PDQSORT_PREFER_MOVE(*r);+ for (size_t i = 1; i < num; ++i) {+ l = first + offsets_l[i]; *r = PDQSORT_PREFER_MOVE(*l);+ r = last - offsets_r[i]; *l = PDQSORT_PREFER_MOVE(*r);+ }+ *r = PDQSORT_PREFER_MOVE(tmp);+ }+ }++ // Partitions [begin, end) around pivot *begin using comparison function comp. Elements equal+ // to the pivot are put in the right-hand partition. Returns the position of the pivot after+ // partitioning and whether the passed sequence already was correctly partitioned. Assumes the+ // pivot is a median of at least 3 elements and that [begin, end) is at least+ // insertion_sort_threshold long. Uses branchless partitioning.+ template<class Iter, class Compare>+ tracy_force_inline std::pair<Iter, bool> partition_right_branchless(Iter begin, Iter end, Compare comp) {+ typedef typename std::iterator_traits<Iter>::value_type T;++ // Move pivot into local for speed.+ T pivot(PDQSORT_PREFER_MOVE(*begin));+ Iter first = begin;+ Iter last = end;++ // Find the first element greater than or equal than the pivot (the median of 3 guarantees+ // this exists).+ while (comp(*++first, pivot));++ // Find the first element strictly smaller than the pivot. We have to guard this search if+ // there was no element before *first.+ if (first - 1 == begin) while (first < last && !comp(*--last, pivot));+ else while ( !comp(*--last, pivot));++ // If the first pair of elements that should be swapped to partition are the same element,+ // the passed in sequence already was correctly partitioned.+ bool already_partitioned = first >= last;+ if (!already_partitioned) {+ std::iter_swap(first, last);+ ++first;++ // The following branchless partitioning is derived from "BlockQuicksort: How Branch+ // Mispredictions don’t affect Quicksort" by Stefan Edelkamp and Armin Weiss, but+ // heavily micro-optimized.+ unsigned char offsets_l_storage[block_size + cacheline_size];+ unsigned char offsets_r_storage[block_size + cacheline_size];+ unsigned char* offsets_l = align_cacheline(offsets_l_storage);+ unsigned char* offsets_r = align_cacheline(offsets_r_storage);++ Iter offsets_l_base = first;+ Iter offsets_r_base = last;+ size_t num_l, num_r, start_l, start_r;+ num_l = num_r = start_l = start_r = 0;+ + while (first < last) {+ // Fill up offset blocks with elements that are on the wrong side.+ // First we determine how much elements are considered for each offset block.+ size_t num_unknown = last - first;+ size_t left_split = num_l == 0 ? (num_r == 0 ? num_unknown / 2 : num_unknown) : 0;+ size_t right_split = num_r == 0 ? (num_unknown - left_split) : 0;++ // Fill the offset blocks.+ if (left_split >= block_size) {+ for (size_t i = 0; i < block_size;) {+ offsets_l[num_l] = i++; num_l += !comp(*first, pivot); ++first;+ offsets_l[num_l] = i++; num_l += !comp(*first, pivot); ++first;+ offsets_l[num_l] = i++; num_l += !comp(*first, pivot); ++first;+ offsets_l[num_l] = i++; num_l += !comp(*first, pivot); ++first;+ offsets_l[num_l] = i++; num_l += !comp(*first, pivot); ++first;+ offsets_l[num_l] = i++; num_l += !comp(*first, pivot); ++first;+ offsets_l[num_l] = i++; num_l += !comp(*first, pivot); ++first;+ offsets_l[num_l] = i++; num_l += !comp(*first, pivot); ++first;+ }+ } else {+ for (size_t i = 0; i < left_split;) {+ offsets_l[num_l] = i++; num_l += !comp(*first, pivot); ++first;+ }+ }++ if (right_split >= block_size) {+ for (size_t i = 0; i < block_size;) {+ offsets_r[num_r] = ++i; num_r += comp(*--last, pivot);+ offsets_r[num_r] = ++i; num_r += comp(*--last, pivot);+ offsets_r[num_r] = ++i; num_r += comp(*--last, pivot);+ offsets_r[num_r] = ++i; num_r += comp(*--last, pivot);+ offsets_r[num_r] = ++i; num_r += comp(*--last, pivot);+ offsets_r[num_r] = ++i; num_r += comp(*--last, pivot);+ offsets_r[num_r] = ++i; num_r += comp(*--last, pivot);+ offsets_r[num_r] = ++i; num_r += comp(*--last, pivot);+ }+ } else {+ for (size_t i = 0; i < right_split;) {+ offsets_r[num_r] = ++i; num_r += comp(*--last, pivot);+ }+ }++ // Swap elements and update block sizes and first/last boundaries.+ size_t num = std::min(num_l, num_r);+ swap_offsets(offsets_l_base, offsets_r_base,+ offsets_l + start_l, offsets_r + start_r,+ num, num_l == num_r);+ num_l -= num; num_r -= num;+ start_l += num; start_r += num;++ if (num_l == 0) {+ start_l = 0;+ offsets_l_base = first;+ }+ + if (num_r == 0) {+ start_r = 0;+ offsets_r_base = last;+ }+ }++ // We have now fully identified [first, last)'s proper position. Swap the last elements.+ if (num_l) {+ offsets_l += start_l;+ while (num_l--) std::iter_swap(offsets_l_base + offsets_l[num_l], --last);+ first = last;+ }+ if (num_r) {+ offsets_r += start_r;+ while (num_r--) std::iter_swap(offsets_r_base - offsets_r[num_r], first), ++first;+ last = first;+ }+ }++ // Put the pivot in the right place.+ Iter pivot_pos = first - 1;+ *begin = PDQSORT_PREFER_MOVE(*pivot_pos);+ *pivot_pos = PDQSORT_PREFER_MOVE(pivot);++ return std::make_pair(pivot_pos, already_partitioned);+ }++++ // Partitions [begin, end) around pivot *begin using comparison function comp. Elements equal+ // to the pivot are put in the right-hand partition. Returns the position of the pivot after+ // partitioning and whether the passed sequence already was correctly partitioned. Assumes the+ // pivot is a median of at least 3 elements and that [begin, end) is at least+ // insertion_sort_threshold long.+ template<class Iter, class Compare>+ tracy_force_inline std::pair<Iter, bool> partition_right(Iter begin, Iter end, Compare comp) {+ typedef typename std::iterator_traits<Iter>::value_type T;+ + // Move pivot into local for speed.+ T pivot(PDQSORT_PREFER_MOVE(*begin));++ Iter first = begin;+ Iter last = end;++ // Find the first element greater than or equal than the pivot (the median of 3 guarantees+ // this exists).+ while (comp(*++first, pivot));++ // Find the first element strictly smaller than the pivot. We have to guard this search if+ // there was no element before *first.+ if (first - 1 == begin) while (first < last && !comp(*--last, pivot));+ else while ( !comp(*--last, pivot));++ // If the first pair of elements that should be swapped to partition are the same element,+ // the passed in sequence already was correctly partitioned.+ bool already_partitioned = first >= last;+ + // Keep swapping pairs of elements that are on the wrong side of the pivot. Previously+ // swapped pairs guard the searches, which is why the first iteration is special-cased+ // above.+ while (first < last) {+ std::iter_swap(first, last);+ while (comp(*++first, pivot));+ while (!comp(*--last, pivot));+ }++ // Put the pivot in the right place.+ Iter pivot_pos = first - 1;+ *begin = PDQSORT_PREFER_MOVE(*pivot_pos);+ *pivot_pos = PDQSORT_PREFER_MOVE(pivot);++ return std::make_pair(pivot_pos, already_partitioned);+ }++ // Similar function to the one above, except elements equal to the pivot are put to the left of+ // the pivot and it doesn't check or return if the passed sequence already was partitioned.+ // Since this is rarely used (the many equal case), and in that case pdqsort already has O(n)+ // performance, no block quicksort is applied here for simplicity.+ template<class Iter, class Compare>+ tracy_force_inline Iter partition_left(Iter begin, Iter end, Compare comp) {+ typedef typename std::iterator_traits<Iter>::value_type T;++ T pivot(PDQSORT_PREFER_MOVE(*begin));+ Iter first = begin;+ Iter last = end;+ + while (comp(pivot, *--last));++ if (last + 1 == end) while (first < last && !comp(pivot, *++first));+ else while ( !comp(pivot, *++first));++ while (first < last) {+ std::iter_swap(first, last);+ while (comp(pivot, *--last));+ while (!comp(pivot, *++first));+ }++ Iter pivot_pos = last;+ *begin = PDQSORT_PREFER_MOVE(*pivot_pos);+ *pivot_pos = PDQSORT_PREFER_MOVE(pivot);++ return pivot_pos;+ }+++ template<class Iter, class Compare, bool Branchless>+ inline void pdqsort_loop(Iter begin, Iter end, Compare comp, int bad_allowed, bool leftmost = true) {+ typedef typename std::iterator_traits<Iter>::difference_type diff_t;++ // Use a while loop for tail recursion elimination.+ while (true) {+ diff_t size = end - begin;++ // Insertion sort is faster for small arrays.+ if (size < insertion_sort_threshold) {+ if (leftmost) insertion_sort(begin, end, comp);+ else unguarded_insertion_sort(begin, end, comp);+ return;+ }++ // Choose pivot as median of 3 or pseudomedian of 9.+ diff_t s2 = size / 2;+ if (size > ninther_threshold) {+ sort3(begin, begin + s2, end - 1, comp);+ sort3(begin + 1, begin + (s2 - 1), end - 2, comp);+ sort3(begin + 2, begin + (s2 + 1), end - 3, comp);+ sort3(begin + (s2 - 1), begin + s2, begin + (s2 + 1), comp);+ std::iter_swap(begin, begin + s2);+ } else sort3(begin + s2, begin, end - 1, comp);++ // If *(begin - 1) is the end of the right partition of a previous partition operation+ // there is no element in [begin, end) that is smaller than *(begin - 1). Then if our+ // pivot compares equal to *(begin - 1) we change strategy, putting equal elements in+ // the left partition, greater elements in the right partition. We do not have to+ // recurse on the left partition, since it's sorted (all equal).+ if (!leftmost && !comp(*(begin - 1), *begin)) {+ begin = partition_left(begin, end, comp) + 1;+ continue;+ }++ // Partition and get results.+ std::pair<Iter, bool> part_result =+ Branchless ? partition_right_branchless(begin, end, comp)+ : partition_right(begin, end, comp);+ Iter pivot_pos = part_result.first;+ bool already_partitioned = part_result.second;++ // Check for a highly unbalanced partition.+ diff_t l_size = pivot_pos - begin;+ diff_t r_size = end - (pivot_pos + 1);+ bool highly_unbalanced = l_size < size / 8 || r_size < size / 8;++ // If we got a highly unbalanced partition we shuffle elements to break many patterns.+ if (highly_unbalanced) {+ // If we had too many bad partitions, switch to heapsort to guarantee O(n log n).+ if (--bad_allowed == 0) {+ std::make_heap(begin, end, comp);+ std::sort_heap(begin, end, comp);+ return;+ }++ if (l_size >= insertion_sort_threshold) {+ std::iter_swap(begin, begin + l_size / 4);+ std::iter_swap(pivot_pos - 1, pivot_pos - l_size / 4);++ if (l_size > ninther_threshold) {+ std::iter_swap(begin + 1, begin + (l_size / 4 + 1));+ std::iter_swap(begin + 2, begin + (l_size / 4 + 2));+ std::iter_swap(pivot_pos - 2, pivot_pos - (l_size / 4 + 1));+ std::iter_swap(pivot_pos - 3, pivot_pos - (l_size / 4 + 2));+ }+ }+ + if (r_size >= insertion_sort_threshold) {+ std::iter_swap(pivot_pos + 1, pivot_pos + (1 + r_size / 4));+ std::iter_swap(end - 1, end - r_size / 4);+ + if (r_size > ninther_threshold) {+ std::iter_swap(pivot_pos + 2, pivot_pos + (2 + r_size / 4));+ std::iter_swap(pivot_pos + 3, pivot_pos + (3 + r_size / 4));+ std::iter_swap(end - 2, end - (1 + r_size / 4));+ std::iter_swap(end - 3, end - (2 + r_size / 4));+ }+ }+ } else {+ // If we were decently balanced and we tried to sort an already partitioned+ // sequence try to use insertion sort.+ if (already_partitioned && partial_insertion_sort(begin, pivot_pos, comp)+ && partial_insertion_sort(pivot_pos + 1, end, comp)) return;+ }+ + // Sort the left partition first using recursion and do tail recursion elimination for+ // the right-hand partition.+ pdqsort_loop<Iter, Compare, Branchless>(begin, pivot_pos, comp, bad_allowed, leftmost);+ begin = pivot_pos + 1;+ leftmost = false;+ }+ }+}+++template<class Iter, class Compare>+inline void pdqsort(Iter begin, Iter end, Compare comp) {+ if (begin == end) return;+ pdqsort_detail::pdqsort_loop<Iter, Compare,+ pdqsort_detail::is_default_compare<typename std::decay<Compare>::type>::value &&+ std::is_arithmetic<typename std::iterator_traits<Iter>::value_type>::value>(+ begin, end, comp, pdqsort_detail::log2(end - begin));+}++template<class Iter>+inline void pdqsort(Iter begin, Iter end) {+ typedef typename std::iterator_traits<Iter>::value_type T;+ pdqsort(begin, end, std::less<T>());+}++template<class Iter, class Compare>+inline void pdqsort_branchless(Iter begin, Iter end, Compare comp) {+ if (begin == end) return;+ pdqsort_detail::pdqsort_loop<Iter, Compare, true>(+ begin, end, comp, pdqsort_detail::log2(end - begin));+}++template<class Iter>+tracy_force_inline void pdqsort_branchless(Iter begin, Iter end) {+ typedef typename std::iterator_traits<Iter>::value_type T;+ pdqsort_branchless(begin, end, std::less<T>());+}++}++#undef PDQSORT_PREFER_MOVE++#endif
+ cbits/tracy/server/tracy_robin_hood.h view
@@ -0,0 +1,2538 @@+// ______ _____ ______ _________+// ______________ ___ /_ ___(_)_______ ___ /_ ______ ______ ______ /+// __ ___/_ __ \__ __ \__ / __ __ \ __ __ \_ __ \_ __ \_ __ /+// _ / / /_/ /_ /_/ /_ / _ / / / _ / / // /_/ // /_/ // /_/ /+// /_/ \____/ /_.___/ /_/ /_/ /_/ ________/_/ /_/ \____/ \____/ \__,_/+// _/_____/+//+// Fast & memory efficient hashtable based on robin hood hashing for C++11/14/17/20+// https://github.com/martinus/robin-hood-hashing+//+// Licensed under the MIT License <http://opensource.org/licenses/MIT>.+// SPDX-License-Identifier: MIT+// Copyright (c) 2018-2021 Martin Ankerl <http://martin.ankerl.com>+//+// 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 ROBIN_HOOD_H_INCLUDED+#define ROBIN_HOOD_H_INCLUDED++// see https://semver.org/+#define ROBIN_HOOD_VERSION_MAJOR 3 // for incompatible API changes+#define ROBIN_HOOD_VERSION_MINOR 11 // for adding functionality in a backwards-compatible manner+#define ROBIN_HOOD_VERSION_PATCH 5 // for backwards-compatible bug fixes++#include <algorithm>+#include <cstdlib>+#include <cstring>+#include <functional>+#include <limits>+#include <memory> // only to support hash of smart pointers+#include <stdexcept>+#include <string>+#include <type_traits>+#include <utility>+#if __cplusplus >= 201703L+# include <string_view>+#endif++// #define ROBIN_HOOD_LOG_ENABLED+#ifdef ROBIN_HOOD_LOG_ENABLED+# include <iostream>+# define ROBIN_HOOD_LOG(...) \+ std::cout << __FUNCTION__ << "@" << __LINE__ << ": " << __VA_ARGS__ << std::endl;+#else+# define ROBIN_HOOD_LOG(x)+#endif++// #define ROBIN_HOOD_TRACE_ENABLED+#ifdef ROBIN_HOOD_TRACE_ENABLED+# include <iostream>+# define ROBIN_HOOD_TRACE(...) \+ std::cout << __FUNCTION__ << "@" << __LINE__ << ": " << __VA_ARGS__ << std::endl;+#else+# define ROBIN_HOOD_TRACE(x)+#endif++// #define ROBIN_HOOD_COUNT_ENABLED+#ifdef ROBIN_HOOD_COUNT_ENABLED+# include <iostream>+# define ROBIN_HOOD_COUNT(x) ++counts().x;+namespace tracy {+struct Counts {+ uint64_t shiftUp{};+ uint64_t shiftDown{};+};+inline std::ostream& operator<<(std::ostream& os, Counts const& c) {+ return os << c.shiftUp << " shiftUp" << std::endl << c.shiftDown << " shiftDown" << std::endl;+}++static Counts& counts() {+ static Counts counts{};+ return counts;+}+} // namespace robin_hood+#else+# define ROBIN_HOOD_COUNT(x)+#endif++// all non-argument macros should use this facility. See+// https://www.fluentcpp.com/2019/05/28/better-macros-better-flags/+#define ROBIN_HOOD(x) ROBIN_HOOD_PRIVATE_DEFINITION_##x()++// mark unused members with this macro+#define ROBIN_HOOD_UNUSED(identifier)++// bitness+#if SIZE_MAX == UINT32_MAX+# define ROBIN_HOOD_PRIVATE_DEFINITION_BITNESS() 32+#elif SIZE_MAX == UINT64_MAX+# define ROBIN_HOOD_PRIVATE_DEFINITION_BITNESS() 64+#else+# error Unsupported bitness+#endif++// endianess+#ifdef _MSC_VER+# define ROBIN_HOOD_PRIVATE_DEFINITION_LITTLE_ENDIAN() 1+# define ROBIN_HOOD_PRIVATE_DEFINITION_BIG_ENDIAN() 0+#else+# define ROBIN_HOOD_PRIVATE_DEFINITION_LITTLE_ENDIAN() \+ (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)+# define ROBIN_HOOD_PRIVATE_DEFINITION_BIG_ENDIAN() (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)+#endif++// inline+#ifdef _MSC_VER+# define ROBIN_HOOD_PRIVATE_DEFINITION_NOINLINE() __declspec(noinline)+#else+# define ROBIN_HOOD_PRIVATE_DEFINITION_NOINLINE() __attribute__((noinline))+#endif++// exceptions+#if !defined(__cpp_exceptions) && !defined(__EXCEPTIONS) && !defined(_CPPUNWIND)+# define ROBIN_HOOD_PRIVATE_DEFINITION_HAS_EXCEPTIONS() 0+#else+# define ROBIN_HOOD_PRIVATE_DEFINITION_HAS_EXCEPTIONS() 1+#endif++// count leading/trailing bits+#if !defined(ROBIN_HOOD_DISABLE_INTRINSICS)+# ifdef _MSC_VER+# if ROBIN_HOOD(BITNESS) == 32+# define ROBIN_HOOD_PRIVATE_DEFINITION_BITSCANFORWARD() _BitScanForward+# else+# define ROBIN_HOOD_PRIVATE_DEFINITION_BITSCANFORWARD() _BitScanForward64+# endif+# include <intrin.h>+# pragma intrinsic(ROBIN_HOOD(BITSCANFORWARD))+# define ROBIN_HOOD_COUNT_TRAILING_ZEROES(x) \+ [](size_t mask) noexcept -> int { \+ unsigned long index; \+ return ROBIN_HOOD(BITSCANFORWARD)(&index, mask) ? static_cast<int>(index) \+ : ROBIN_HOOD(BITNESS); \+ }(x)+# else+# if ROBIN_HOOD(BITNESS) == 32+# define ROBIN_HOOD_PRIVATE_DEFINITION_CTZ() __builtin_ctzl+# define ROBIN_HOOD_PRIVATE_DEFINITION_CLZ() __builtin_clzl+# else+# define ROBIN_HOOD_PRIVATE_DEFINITION_CTZ() __builtin_ctzll+# define ROBIN_HOOD_PRIVATE_DEFINITION_CLZ() __builtin_clzll+# endif+# define ROBIN_HOOD_COUNT_LEADING_ZEROES(x) ((x) ? ROBIN_HOOD(CLZ)(x) : ROBIN_HOOD(BITNESS))+# define ROBIN_HOOD_COUNT_TRAILING_ZEROES(x) ((x) ? ROBIN_HOOD(CTZ)(x) : ROBIN_HOOD(BITNESS))+# endif+#endif++// fallthrough+#ifndef __has_cpp_attribute // For backwards compatibility+# define __has_cpp_attribute(x) 0+#endif+#if __has_cpp_attribute(clang::fallthrough)+# define ROBIN_HOOD_PRIVATE_DEFINITION_FALLTHROUGH() [[clang::fallthrough]]+#elif __has_cpp_attribute(gnu::fallthrough)+# define ROBIN_HOOD_PRIVATE_DEFINITION_FALLTHROUGH() [[gnu::fallthrough]]+#else+# define ROBIN_HOOD_PRIVATE_DEFINITION_FALLTHROUGH()+#endif++// likely/unlikely+#ifdef _MSC_VER+# define ROBIN_HOOD_LIKELY(condition) condition+# define ROBIN_HOOD_UNLIKELY(condition) condition+#else+# define ROBIN_HOOD_LIKELY(condition) __builtin_expect(condition, 1)+# define ROBIN_HOOD_UNLIKELY(condition) __builtin_expect(condition, 0)+#endif++// detect if native wchar_t type is availiable in MSVC+#ifdef _MSC_VER+# ifdef _NATIVE_WCHAR_T_DEFINED+# define ROBIN_HOOD_PRIVATE_DEFINITION_HAS_NATIVE_WCHART() 1+# else+# define ROBIN_HOOD_PRIVATE_DEFINITION_HAS_NATIVE_WCHART() 0+# endif+#else+# define ROBIN_HOOD_PRIVATE_DEFINITION_HAS_NATIVE_WCHART() 1+#endif++// detect if MSVC supports the pair(std::piecewise_construct_t,...) consructor being constexpr+#ifdef _MSC_VER+# if _MSC_VER <= 1900+# define ROBIN_HOOD_PRIVATE_DEFINITION_BROKEN_CONSTEXPR() 1+# else+# define ROBIN_HOOD_PRIVATE_DEFINITION_BROKEN_CONSTEXPR() 0+# endif+#else+# define ROBIN_HOOD_PRIVATE_DEFINITION_BROKEN_CONSTEXPR() 0+#endif++#define ROBIN_HOOD_IS_TRIVIALLY_COPYABLE(...) std::is_trivially_copyable<__VA_ARGS__>::value++// helpers for C++ versions, see https://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macros.html+#define ROBIN_HOOD_PRIVATE_DEFINITION_CXX() __cplusplus+#define ROBIN_HOOD_PRIVATE_DEFINITION_CXX98() 199711L+#define ROBIN_HOOD_PRIVATE_DEFINITION_CXX11() 201103L+#define ROBIN_HOOD_PRIVATE_DEFINITION_CXX14() 201402L+#define ROBIN_HOOD_PRIVATE_DEFINITION_CXX17() 201703L++#if ROBIN_HOOD(CXX) >= ROBIN_HOOD(CXX17)+# define ROBIN_HOOD_PRIVATE_DEFINITION_NODISCARD() [[nodiscard]]+#else+# define ROBIN_HOOD_PRIVATE_DEFINITION_NODISCARD()+#endif++namespace tracy {++#if ROBIN_HOOD(CXX) >= ROBIN_HOOD(CXX14)+# define ROBIN_HOOD_STD std+#else++// c++11 compatibility layer+namespace ROBIN_HOOD_STD {+template <class T>+struct alignment_of+ : std::integral_constant<std::size_t, alignof(typename std::remove_all_extents<T>::type)> {};++template <class T, T... Ints>+class integer_sequence {+public:+ using value_type = T;+ static_assert(std::is_integral<value_type>::value, "not integral type");+ static constexpr std::size_t size() noexcept {+ return sizeof...(Ints);+ }+};+template <std::size_t... Inds>+using index_sequence = integer_sequence<std::size_t, Inds...>;++namespace detail_ {+template <class T, T Begin, T End, bool>+struct IntSeqImpl {+ using TValue = T;+ static_assert(std::is_integral<TValue>::value, "not integral type");+ static_assert(Begin >= 0 && Begin < End, "unexpected argument (Begin<0 || Begin<=End)");++ template <class, class>+ struct IntSeqCombiner;++ template <TValue... Inds0, TValue... Inds1>+ struct IntSeqCombiner<integer_sequence<TValue, Inds0...>, integer_sequence<TValue, Inds1...>> {+ using TResult = integer_sequence<TValue, Inds0..., Inds1...>;+ };++ using TResult =+ typename IntSeqCombiner<typename IntSeqImpl<TValue, Begin, Begin + (End - Begin) / 2,+ (End - Begin) / 2 == 1>::TResult,+ typename IntSeqImpl<TValue, Begin + (End - Begin) / 2, End,+ (End - Begin + 1) / 2 == 1>::TResult>::TResult;+};++template <class T, T Begin>+struct IntSeqImpl<T, Begin, Begin, false> {+ using TValue = T;+ static_assert(std::is_integral<TValue>::value, "not integral type");+ static_assert(Begin >= 0, "unexpected argument (Begin<0)");+ using TResult = integer_sequence<TValue>;+};++template <class T, T Begin, T End>+struct IntSeqImpl<T, Begin, End, true> {+ using TValue = T;+ static_assert(std::is_integral<TValue>::value, "not integral type");+ static_assert(Begin >= 0, "unexpected argument (Begin<0)");+ using TResult = integer_sequence<TValue, Begin>;+};+} // namespace detail_++template <class T, T N>+using make_integer_sequence = typename detail_::IntSeqImpl<T, 0, N, (N - 0) == 1>::TResult;++template <std::size_t N>+using make_index_sequence = make_integer_sequence<std::size_t, N>;++template <class... T>+using index_sequence_for = make_index_sequence<sizeof...(T)>;++} // namespace ROBIN_HOOD_STD++#endif++namespace detail {++// make sure we static_cast to the correct type for hash_int+#if ROBIN_HOOD(BITNESS) == 64+using SizeT = uint64_t;+#else+using SizeT = uint32_t;+#endif++template <typename T>+T rotr(T x, unsigned k) {+ return (x >> k) | (x << (8U * sizeof(T) - k));+}++// This cast gets rid of warnings like "cast from 'uint8_t*' {aka 'unsigned char*'} to+// 'uint64_t*' {aka 'long unsigned int*'} increases required alignment of target type". Use with+// care!+template <typename T>+inline T reinterpret_cast_no_cast_align_warning(void* ptr) noexcept {+ return reinterpret_cast<T>(ptr);+}++template <typename T>+inline T reinterpret_cast_no_cast_align_warning(void const* ptr) noexcept {+ return reinterpret_cast<T>(ptr);+}++// make sure this is not inlined as it is slow and dramatically enlarges code, thus making other+// inlinings more difficult. Throws are also generally the slow path.+template <typename E, typename... Args>+[[noreturn]] ROBIN_HOOD(NOINLINE)+#if ROBIN_HOOD(HAS_EXCEPTIONS)+ void doThrow(Args&&... args) {+ // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)+ throw E(std::forward<Args>(args)...);+}+#else+ void doThrow(Args&&... ROBIN_HOOD_UNUSED(args) /*unused*/) {+ abort();+}+#endif++template <typename E, typename T, typename... Args>+T* assertNotNull(T* t, Args&&... args) {+ if (ROBIN_HOOD_UNLIKELY(nullptr == t)) {+ doThrow<E>(std::forward<Args>(args)...);+ }+ return t;+}++template <typename T>+inline T unaligned_load(void const* ptr) noexcept {+ // using memcpy so we don't get into unaligned load problems.+ // compiler should optimize this very well anyways.+ T t;+ std::memcpy(&t, ptr, sizeof(T));+ return t;+}++// Allocates bulks of memory for objects of type T. This deallocates the memory in the destructor,+// and keeps a linked list of the allocated memory around. Overhead per allocation is the size of a+// pointer.+template <typename T, size_t MinNumAllocs = 4, size_t MaxNumAllocs = 256>+class BulkPoolAllocator {+public:+ BulkPoolAllocator() noexcept = default;++ // does not copy anything, just creates a new allocator.+ BulkPoolAllocator(const BulkPoolAllocator& ROBIN_HOOD_UNUSED(o) /*unused*/) noexcept+ : mHead(nullptr)+ , mListForFree(nullptr) {}++ BulkPoolAllocator(BulkPoolAllocator&& o) noexcept+ : mHead(o.mHead)+ , mListForFree(o.mListForFree) {+ o.mListForFree = nullptr;+ o.mHead = nullptr;+ }++ BulkPoolAllocator& operator=(BulkPoolAllocator&& o) noexcept {+ reset();+ mHead = o.mHead;+ mListForFree = o.mListForFree;+ o.mListForFree = nullptr;+ o.mHead = nullptr;+ return *this;+ }++ BulkPoolAllocator&+ // NOLINTNEXTLINE(bugprone-unhandled-self-assignment,cert-oop54-cpp)+ operator=(const BulkPoolAllocator& ROBIN_HOOD_UNUSED(o) /*unused*/) noexcept {+ // does not do anything+ return *this;+ }++ ~BulkPoolAllocator() noexcept {+ reset();+ }++ // Deallocates all allocated memory.+ void reset() noexcept {+ while (mListForFree) {+ T* tmp = *mListForFree;+ ROBIN_HOOD_LOG("std::free")+ std::free(mListForFree);+ mListForFree = reinterpret_cast_no_cast_align_warning<T**>(tmp);+ }+ mHead = nullptr;+ }++ // allocates, but does NOT initialize. Use in-place new constructor, e.g.+ // T* obj = pool.allocate();+ // ::new (static_cast<void*>(obj)) T();+ T* allocate() {+ T* tmp = mHead;+ if (!tmp) {+ tmp = performAllocation();+ }++ mHead = *reinterpret_cast_no_cast_align_warning<T**>(tmp);+ return tmp;+ }++ // does not actually deallocate but puts it in store.+ // make sure you have already called the destructor! e.g. with+ // obj->~T();+ // pool.deallocate(obj);+ void deallocate(T* obj) noexcept {+ *reinterpret_cast_no_cast_align_warning<T**>(obj) = mHead;+ mHead = obj;+ }++ // Adds an already allocated block of memory to the allocator. This allocator is from now on+ // responsible for freeing the data (with free()). If the provided data is not large enough to+ // make use of, it is immediately freed. Otherwise it is reused and freed in the destructor.+ void addOrFree(void* ptr, const size_t numBytes) noexcept {+ // calculate number of available elements in ptr+ if (numBytes < ALIGNMENT + ALIGNED_SIZE) {+ // not enough data for at least one element. Free and return.+ ROBIN_HOOD_LOG("std::free")+ std::free(ptr);+ } else {+ ROBIN_HOOD_LOG("add to buffer")+ add(ptr, numBytes);+ }+ }++ void swap(BulkPoolAllocator<T, MinNumAllocs, MaxNumAllocs>& other) noexcept {+ using std::swap;+ swap(mHead, other.mHead);+ swap(mListForFree, other.mListForFree);+ }++private:+ // iterates the list of allocated memory to calculate how many to alloc next.+ // Recalculating this each time saves us a size_t member.+ // This ignores the fact that memory blocks might have been added manually with addOrFree. In+ // practice, this should not matter much.+ ROBIN_HOOD(NODISCARD) size_t calcNumElementsToAlloc() const noexcept {+ auto tmp = mListForFree;+ size_t numAllocs = MinNumAllocs;++ while (numAllocs * 2 <= MaxNumAllocs && tmp) {+ auto x = reinterpret_cast<T***>(tmp);+ tmp = *x;+ numAllocs *= 2;+ }++ return numAllocs;+ }++ // WARNING: Underflow if numBytes < ALIGNMENT! This is guarded in addOrFree().+ void add(void* ptr, const size_t numBytes) noexcept {+ const size_t numElements = (numBytes - ALIGNMENT) / ALIGNED_SIZE;++ auto data = reinterpret_cast<T**>(ptr);++ // link free list+ auto x = reinterpret_cast<T***>(data);+ *x = mListForFree;+ mListForFree = data;++ // create linked list for newly allocated data+ auto* const headT =+ reinterpret_cast_no_cast_align_warning<T*>(reinterpret_cast<char*>(ptr) + ALIGNMENT);++ auto* const head = reinterpret_cast<char*>(headT);++ // Visual Studio compiler automatically unrolls this loop, which is pretty cool+ for (size_t i = 0; i < numElements; ++i) {+ *reinterpret_cast_no_cast_align_warning<char**>(head + i * ALIGNED_SIZE) =+ head + (i + 1) * ALIGNED_SIZE;+ }++ // last one points to 0+ *reinterpret_cast_no_cast_align_warning<T**>(head + (numElements - 1) * ALIGNED_SIZE) =+ mHead;+ mHead = headT;+ }++ // Called when no memory is available (mHead == 0).+ // Don't inline this slow path.+ ROBIN_HOOD(NOINLINE) T* performAllocation() {+ size_t const numElementsToAlloc = calcNumElementsToAlloc();++ // alloc new memory: [prev |T, T, ... T]+ size_t const bytes = ALIGNMENT + ALIGNED_SIZE * numElementsToAlloc;+ ROBIN_HOOD_LOG("std::malloc " << bytes << " = " << ALIGNMENT << " + " << ALIGNED_SIZE+ << " * " << numElementsToAlloc)+ add(assertNotNull<std::bad_alloc>(std::malloc(bytes)), bytes);+ return mHead;+ }++ // enforce byte alignment of the T's+#if ROBIN_HOOD(CXX) >= ROBIN_HOOD(CXX14)+ static constexpr size_t ALIGNMENT =+ (std::max)(std::alignment_of<T>::value, std::alignment_of<T*>::value);+#else+ static const size_t ALIGNMENT =+ (ROBIN_HOOD_STD::alignment_of<T>::value > ROBIN_HOOD_STD::alignment_of<T*>::value)+ ? ROBIN_HOOD_STD::alignment_of<T>::value+ : +ROBIN_HOOD_STD::alignment_of<T*>::value; // the + is for walkarround+#endif++ static constexpr size_t ALIGNED_SIZE = ((sizeof(T) - 1) / ALIGNMENT + 1) * ALIGNMENT;++ static_assert(MinNumAllocs >= 1, "MinNumAllocs");+ static_assert(MaxNumAllocs >= MinNumAllocs, "MaxNumAllocs");+ static_assert(ALIGNED_SIZE >= sizeof(T*), "ALIGNED_SIZE");+ static_assert(0 == (ALIGNED_SIZE % sizeof(T*)), "ALIGNED_SIZE mod");+ static_assert(ALIGNMENT >= sizeof(T*), "ALIGNMENT");++ T* mHead{nullptr};+ T** mListForFree{nullptr};+};++template <typename T, size_t MinSize, size_t MaxSize, bool IsFlat>+struct NodeAllocator;++// dummy allocator that does nothing+template <typename T, size_t MinSize, size_t MaxSize>+struct NodeAllocator<T, MinSize, MaxSize, true> {++ // we are not using the data, so just free it.+ void addOrFree(void* ptr, size_t ROBIN_HOOD_UNUSED(numBytes) /*unused*/) noexcept {+ ROBIN_HOOD_LOG("std::free")+ std::free(ptr);+ }+};++template <typename T, size_t MinSize, size_t MaxSize>+struct NodeAllocator<T, MinSize, MaxSize, false> : public BulkPoolAllocator<T, MinSize, MaxSize> {};++// c++14 doesn't have is_nothrow_swappable, and clang++ 6.0.1 doesn't like it either, so I'm making+// my own here.+namespace swappable {+#if ROBIN_HOOD(CXX) < ROBIN_HOOD(CXX17)+using std::swap;+template <typename T>+struct nothrow {+ static const bool value = noexcept(swap(std::declval<T&>(), std::declval<T&>()));+};+#else+template <typename T>+struct nothrow {+ static const bool value = std::is_nothrow_swappable<T>::value;+};+#endif+} // namespace swappable++} // namespace detail++struct is_transparent_tag {};++// A custom pair implementation is used in the map because std::pair is not is_trivially_copyable,+// which means it would not be allowed to be used in std::memcpy. This struct is copyable, which is+// also tested.+template <typename T1, typename T2>+struct pair {+ using first_type = T1;+ using second_type = T2;++ template <typename U1 = T1, typename U2 = T2,+ typename = typename std::enable_if<std::is_default_constructible<U1>::value &&+ std::is_default_constructible<U2>::value>::type>+ constexpr pair() noexcept(noexcept(U1()) && noexcept(U2()))+ : first()+ , second() {}++ // pair constructors are explicit so we don't accidentally call this ctor when we don't have to.+ explicit constexpr pair(std::pair<T1, T2> const& o) noexcept(+ noexcept(T1(std::declval<T1 const&>())) && noexcept(T2(std::declval<T2 const&>())))+ : first(o.first)+ , second(o.second) {}++ // pair constructors are explicit so we don't accidentally call this ctor when we don't have to.+ explicit constexpr pair(std::pair<T1, T2>&& o) noexcept(noexcept(+ T1(std::move(std::declval<T1&&>()))) && noexcept(T2(std::move(std::declval<T2&&>()))))+ : first(std::move(o.first))+ , second(std::move(o.second)) {}++ constexpr pair(T1&& a, T2&& b) noexcept(noexcept(+ T1(std::move(std::declval<T1&&>()))) && noexcept(T2(std::move(std::declval<T2&&>()))))+ : first(std::move(a))+ , second(std::move(b)) {}++ template <typename U1, typename U2>+ constexpr pair(U1&& a, U2&& b) noexcept(noexcept(T1(std::forward<U1>(+ std::declval<U1&&>()))) && noexcept(T2(std::forward<U2>(std::declval<U2&&>()))))+ : first(std::forward<U1>(a))+ , second(std::forward<U2>(b)) {}++ template <typename... U1, typename... U2>+ // MSVC 2015 produces error "C2476: ‘constexpr’ constructor does not initialize all members"+ // if this constructor is constexpr+#if !ROBIN_HOOD(BROKEN_CONSTEXPR)+ constexpr+#endif+ pair(std::piecewise_construct_t /*unused*/, std::tuple<U1...> a,+ std::tuple<U2...>+ b) noexcept(noexcept(pair(std::declval<std::tuple<U1...>&>(),+ std::declval<std::tuple<U2...>&>(),+ ROBIN_HOOD_STD::index_sequence_for<U1...>(),+ ROBIN_HOOD_STD::index_sequence_for<U2...>())))+ : pair(a, b, ROBIN_HOOD_STD::index_sequence_for<U1...>(),+ ROBIN_HOOD_STD::index_sequence_for<U2...>()) {+ }++ // constructor called from the std::piecewise_construct_t ctor+ template <typename... U1, size_t... I1, typename... U2, size_t... I2>+ pair(std::tuple<U1...>& a, std::tuple<U2...>& b, ROBIN_HOOD_STD::index_sequence<I1...> /*unused*/, ROBIN_HOOD_STD::index_sequence<I2...> /*unused*/) noexcept(+ noexcept(T1(std::forward<U1>(std::get<I1>(+ std::declval<std::tuple<+ U1...>&>()))...)) && noexcept(T2(std::+ forward<U2>(std::get<I2>(+ std::declval<std::tuple<U2...>&>()))...)))+ : first(std::forward<U1>(std::get<I1>(a))...)+ , second(std::forward<U2>(std::get<I2>(b))...) {+ // make visual studio compiler happy about warning about unused a & b.+ // Visual studio's pair implementation disables warning 4100.+ (void)a;+ (void)b;+ }++ void swap(pair<T1, T2>& o) noexcept((detail::swappable::nothrow<T1>::value) &&+ (detail::swappable::nothrow<T2>::value)) {+ using std::swap;+ swap(first, o.first);+ swap(second, o.second);+ }++ T1 first; // NOLINT(misc-non-private-member-variables-in-classes)+ T2 second; // NOLINT(misc-non-private-member-variables-in-classes)+};++template <typename A, typename B>+inline void swap(pair<A, B>& a, pair<A, B>& b) noexcept(+ noexcept(std::declval<pair<A, B>&>().swap(std::declval<pair<A, B>&>()))) {+ a.swap(b);+}++template <typename A, typename B>+inline constexpr bool operator==(pair<A, B> const& x, pair<A, B> const& y) {+ return (x.first == y.first) && (x.second == y.second);+}+template <typename A, typename B>+inline constexpr bool operator!=(pair<A, B> const& x, pair<A, B> const& y) {+ return !(x == y);+}+template <typename A, typename B>+inline constexpr bool operator<(pair<A, B> const& x, pair<A, B> const& y) noexcept(noexcept(+ std::declval<A const&>() < std::declval<A const&>()) && noexcept(std::declval<B const&>() <+ std::declval<B const&>())) {+ return x.first < y.first || (!(y.first < x.first) && x.second < y.second);+}+template <typename A, typename B>+inline constexpr bool operator>(pair<A, B> const& x, pair<A, B> const& y) {+ return y < x;+}+template <typename A, typename B>+inline constexpr bool operator<=(pair<A, B> const& x, pair<A, B> const& y) {+ return !(x > y);+}+template <typename A, typename B>+inline constexpr bool operator>=(pair<A, B> const& x, pair<A, B> const& y) {+ return !(x < y);+}++inline size_t hash_bytes(void const* ptr, size_t len) noexcept {+ static constexpr uint64_t m = UINT64_C(0xc6a4a7935bd1e995);+ static constexpr uint64_t seed = UINT64_C(0xe17a1465);+ static constexpr unsigned int r = 47;++ auto const* const data64 = static_cast<uint64_t const*>(ptr);+ uint64_t h = seed ^ (len * m);++ size_t const n_blocks = len / 8;+ for (size_t i = 0; i < n_blocks; ++i) {+ auto k = detail::unaligned_load<uint64_t>(data64 + i);++ k *= m;+ k ^= k >> r;+ k *= m;++ h ^= k;+ h *= m;+ }++ auto const* const data8 = reinterpret_cast<uint8_t const*>(data64 + n_blocks);+ switch (len & 7U) {+ case 7:+ h ^= static_cast<uint64_t>(data8[6]) << 48U;+ ROBIN_HOOD(FALLTHROUGH); // FALLTHROUGH+ case 6:+ h ^= static_cast<uint64_t>(data8[5]) << 40U;+ ROBIN_HOOD(FALLTHROUGH); // FALLTHROUGH+ case 5:+ h ^= static_cast<uint64_t>(data8[4]) << 32U;+ ROBIN_HOOD(FALLTHROUGH); // FALLTHROUGH+ case 4:+ h ^= static_cast<uint64_t>(data8[3]) << 24U;+ ROBIN_HOOD(FALLTHROUGH); // FALLTHROUGH+ case 3:+ h ^= static_cast<uint64_t>(data8[2]) << 16U;+ ROBIN_HOOD(FALLTHROUGH); // FALLTHROUGH+ case 2:+ h ^= static_cast<uint64_t>(data8[1]) << 8U;+ ROBIN_HOOD(FALLTHROUGH); // FALLTHROUGH+ case 1:+ h ^= static_cast<uint64_t>(data8[0]);+ h *= m;+ ROBIN_HOOD(FALLTHROUGH); // FALLTHROUGH+ default:+ break;+ }++ h ^= h >> r;++ // not doing the final step here, because this will be done by keyToIdx anyways+ // h *= m;+ // h ^= h >> r;+ return static_cast<size_t>(h);+}++inline size_t hash_int(uint64_t x) noexcept {+ // tried lots of different hashes, let's stick with murmurhash3. It's simple, fast, well tested,+ // and doesn't need any special 128bit operations.+ x ^= x >> 33U;+ x *= UINT64_C(0xff51afd7ed558ccd);+ x ^= x >> 33U;++ // not doing the final step here, because this will be done by keyToIdx anyways+ // x *= UINT64_C(0xc4ceb9fe1a85ec53);+ // x ^= x >> 33U;+ return static_cast<size_t>(x);+}++// A thin wrapper around std::hash, performing an additional simple mixing step of the result.+template <typename T, typename Enable = void>+struct hash : public std::hash<T> {+ size_t operator()(T const& obj) const+ noexcept(noexcept(std::declval<std::hash<T>>().operator()(std::declval<T const&>()))) {+ // call base hash+ auto result = std::hash<T>::operator()(obj);+ // return mixed of that, to be save against identity has+ return hash_int(static_cast<detail::SizeT>(result));+ }+};++template <typename CharT>+struct hash<std::basic_string<CharT>> {+ size_t operator()(std::basic_string<CharT> const& str) const noexcept {+ return hash_bytes(str.data(), sizeof(CharT) * str.size());+ }+};++#if ROBIN_HOOD(CXX) >= ROBIN_HOOD(CXX17)+template <typename CharT>+struct hash<std::basic_string_view<CharT>> {+ size_t operator()(std::basic_string_view<CharT> const& sv) const noexcept {+ return hash_bytes(sv.data(), sizeof(CharT) * sv.size());+ }+};+#endif++template <class T>+struct hash<T*> {+ size_t operator()(T* ptr) const noexcept {+ return hash_int(reinterpret_cast<detail::SizeT>(ptr));+ }+};++template <class T>+struct hash<std::unique_ptr<T>> {+ size_t operator()(std::unique_ptr<T> const& ptr) const noexcept {+ return hash_int(reinterpret_cast<detail::SizeT>(ptr.get()));+ }+};++template <class T>+struct hash<std::shared_ptr<T>> {+ size_t operator()(std::shared_ptr<T> const& ptr) const noexcept {+ return hash_int(reinterpret_cast<detail::SizeT>(ptr.get()));+ }+};++template <typename Enum>+struct hash<Enum, typename std::enable_if<std::is_enum<Enum>::value>::type> {+ size_t operator()(Enum e) const noexcept {+ using Underlying = typename std::underlying_type<Enum>::type;+ return hash<Underlying>{}(static_cast<Underlying>(e));+ }+};++#define ROBIN_HOOD_HASH_INT(T) \+ template <> \+ struct hash<T> { \+ size_t operator()(T const& obj) const noexcept { \+ return hash_int(static_cast<uint64_t>(obj)); \+ } \+ }++#if defined(__GNUC__) && !defined(__clang__)+# pragma GCC diagnostic push+# pragma GCC diagnostic ignored "-Wuseless-cast"+#endif+// see https://en.cppreference.com/w/cpp/utility/hash+ROBIN_HOOD_HASH_INT(bool);+ROBIN_HOOD_HASH_INT(char);+ROBIN_HOOD_HASH_INT(signed char);+ROBIN_HOOD_HASH_INT(unsigned char);+ROBIN_HOOD_HASH_INT(char16_t);+ROBIN_HOOD_HASH_INT(char32_t);+#if ROBIN_HOOD(HAS_NATIVE_WCHART)+ROBIN_HOOD_HASH_INT(wchar_t);+#endif+ROBIN_HOOD_HASH_INT(short);+ROBIN_HOOD_HASH_INT(unsigned short);+ROBIN_HOOD_HASH_INT(int);+ROBIN_HOOD_HASH_INT(unsigned int);+ROBIN_HOOD_HASH_INT(long);+ROBIN_HOOD_HASH_INT(long long);+ROBIN_HOOD_HASH_INT(unsigned long);+ROBIN_HOOD_HASH_INT(unsigned long long);+#if defined(__GNUC__) && !defined(__clang__)+# pragma GCC diagnostic pop+#endif+namespace detail {++template <typename T>+struct void_type {+ using type = void;+};++template <typename T, typename = void>+struct has_is_transparent : public std::false_type {};++template <typename T>+struct has_is_transparent<T, typename void_type<typename T::is_transparent>::type>+ : public std::true_type {};++// using wrapper classes for hash and key_equal prevents the diamond problem when the same type+// is used. see https://stackoverflow.com/a/28771920/48181+template <typename T>+struct WrapHash : public T {+ WrapHash() = default;+ explicit WrapHash(T const& o) noexcept(noexcept(T(std::declval<T const&>())))+ : T(o) {}+};++template <typename T>+struct WrapKeyEqual : public T {+ WrapKeyEqual() = default;+ explicit WrapKeyEqual(T const& o) noexcept(noexcept(T(std::declval<T const&>())))+ : T(o) {}+};++// A highly optimized hashmap implementation, using the Robin Hood algorithm.+//+// In most cases, this map should be usable as a drop-in replacement for std::unordered_map, but+// be about 2x faster in most cases and require much less allocations.+//+// This implementation uses the following memory layout:+//+// [Node, Node, ... Node | info, info, ... infoSentinel ]+//+// * Node: either a DataNode that directly has the std::pair<key, val> as member,+// or a DataNode with a pointer to std::pair<key,val>. Which DataNode representation to use+// depends on how fast the swap() operation is. Heuristically, this is automatically choosen+// based on sizeof(). there are always 2^n Nodes.+//+// * info: Each Node in the map has a corresponding info byte, so there are 2^n info bytes.+// Each byte is initialized to 0, meaning the corresponding Node is empty. Set to 1 means the+// corresponding node contains data. Set to 2 means the corresponding Node is filled, but it+// actually belongs to the previous position and was pushed out because that place is already+// taken.+//+// * infoSentinel: Sentinel byte set to 1, so that iterator's ++ can stop at end() without the+// need for a idx variable.+//+// According to STL, order of templates has effect on throughput. That's why I've moved the+// boolean to the front.+// https://www.reddit.com/r/cpp/comments/ahp6iu/compile_time_binary_size_reductions_and_cs_future/eeguck4/+template <bool IsFlat, size_t MaxLoadFactor100, typename Key, typename T, typename Hash,+ typename KeyEqual>+class Table+ : public WrapHash<Hash>,+ public WrapKeyEqual<KeyEqual>,+ detail::NodeAllocator<+ typename std::conditional<+ std::is_void<T>::value, Key,+ tracy::pair<typename std::conditional<IsFlat, Key, Key const>::type, T>>::type,+ 4, 16384, IsFlat> {+public:+ static constexpr bool is_flat = IsFlat;+ static constexpr bool is_map = !std::is_void<T>::value;+ static constexpr bool is_set = !is_map;+ static constexpr bool is_transparent =+ has_is_transparent<Hash>::value && has_is_transparent<KeyEqual>::value;++ using key_type = Key;+ using mapped_type = T;+ using value_type = typename std::conditional<+ is_set, Key,+ tracy::pair<typename std::conditional<is_flat, Key, Key const>::type, T>>::type;+ using size_type = size_t;+ using hasher = Hash;+ using key_equal = KeyEqual;+ using Self = Table<IsFlat, MaxLoadFactor100, key_type, mapped_type, hasher, key_equal>;++private:+ static_assert(MaxLoadFactor100 > 10 && MaxLoadFactor100 < 100,+ "MaxLoadFactor100 needs to be >10 && < 100");++ using WHash = WrapHash<Hash>;+ using WKeyEqual = WrapKeyEqual<KeyEqual>;++ // configuration defaults++ // make sure we have 8 elements, needed to quickly rehash mInfo+ static constexpr size_t InitialNumElements = sizeof(uint64_t);+ static constexpr uint32_t InitialInfoNumBits = 5;+ static constexpr uint8_t InitialInfoInc = 1U << InitialInfoNumBits;+ static constexpr size_t InfoMask = InitialInfoInc - 1U;+ static constexpr uint8_t InitialInfoHashShift = 0;+ using DataPool = detail::NodeAllocator<value_type, 4, 16384, IsFlat>;++ // type needs to be wider than uint8_t.+ using InfoType = uint32_t;++ // DataNode ////////////////////////////////////////////////////////++ // Primary template for the data node. We have special implementations for small and big+ // objects. For large objects it is assumed that swap() is fairly slow, so we allocate these+ // on the heap so swap merely swaps a pointer.+ template <typename M, bool>+ class DataNode {};++ // Small: just allocate on the stack.+ template <typename M>+ class DataNode<M, true> final {+ public:+ template <typename... Args>+ explicit DataNode(M& ROBIN_HOOD_UNUSED(map) /*unused*/, Args&&... args) noexcept(+ noexcept(value_type(std::forward<Args>(args)...)))+ : mData(std::forward<Args>(args)...) {}++ DataNode(M& ROBIN_HOOD_UNUSED(map) /*unused*/, DataNode<M, true>&& n) noexcept(+ std::is_nothrow_move_constructible<value_type>::value)+ : mData(std::move(n.mData)) {}++ // doesn't do anything+ void destroy(M& ROBIN_HOOD_UNUSED(map) /*unused*/) noexcept {}+ void destroyDoNotDeallocate() noexcept {}++ value_type const* operator->() const noexcept {+ return &mData;+ }+ value_type* operator->() noexcept {+ return &mData;+ }++ const value_type& operator*() const noexcept {+ return mData;+ }++ value_type& operator*() noexcept {+ return mData;+ }++ template <typename VT = value_type>+ ROBIN_HOOD(NODISCARD)+ typename std::enable_if<is_map, typename VT::first_type&>::type getFirst() noexcept {+ return mData.first;+ }+ template <typename VT = value_type>+ ROBIN_HOOD(NODISCARD)+ typename std::enable_if<is_set, VT&>::type getFirst() noexcept {+ return mData;+ }++ template <typename VT = value_type>+ ROBIN_HOOD(NODISCARD)+ typename std::enable_if<is_map, typename VT::first_type const&>::type+ getFirst() const noexcept {+ return mData.first;+ }+ template <typename VT = value_type>+ ROBIN_HOOD(NODISCARD)+ typename std::enable_if<is_set, VT const&>::type getFirst() const noexcept {+ return mData;+ }++ template <typename MT = mapped_type>+ ROBIN_HOOD(NODISCARD)+ typename std::enable_if<is_map, MT&>::type getSecond() noexcept {+ return mData.second;+ }++ template <typename MT = mapped_type>+ ROBIN_HOOD(NODISCARD)+ typename std::enable_if<is_set, MT const&>::type getSecond() const noexcept {+ return mData.second;+ }++ void swap(DataNode<M, true>& o) noexcept(+ noexcept(std::declval<value_type>().swap(std::declval<value_type>()))) {+ mData.swap(o.mData);+ }++ private:+ value_type mData;+ };++ // big object: allocate on heap.+ template <typename M>+ class DataNode<M, false> {+ public:+ template <typename... Args>+ explicit DataNode(M& map, Args&&... args)+ : mData(map.allocate()) {+ ::new (static_cast<void*>(mData)) value_type(std::forward<Args>(args)...);+ }++ DataNode(M& ROBIN_HOOD_UNUSED(map) /*unused*/, DataNode<M, false>&& n) noexcept+ : mData(std::move(n.mData)) {}++ void destroy(M& map) noexcept {+ // don't deallocate, just put it into list of datapool.+ mData->~value_type();+ map.deallocate(mData);+ }++ void destroyDoNotDeallocate() noexcept {+ mData->~value_type();+ }++ value_type const* operator->() const noexcept {+ return mData;+ }++ value_type* operator->() noexcept {+ return mData;+ }++ const value_type& operator*() const {+ return *mData;+ }++ value_type& operator*() {+ return *mData;+ }++ template <typename VT = value_type>+ ROBIN_HOOD(NODISCARD)+ typename std::enable_if<is_map, typename VT::first_type&>::type getFirst() noexcept {+ return mData->first;+ }+ template <typename VT = value_type>+ ROBIN_HOOD(NODISCARD)+ typename std::enable_if<is_set, VT&>::type getFirst() noexcept {+ return *mData;+ }++ template <typename VT = value_type>+ ROBIN_HOOD(NODISCARD)+ typename std::enable_if<is_map, typename VT::first_type const&>::type+ getFirst() const noexcept {+ return mData->first;+ }+ template <typename VT = value_type>+ ROBIN_HOOD(NODISCARD)+ typename std::enable_if<is_set, VT const&>::type getFirst() const noexcept {+ return *mData;+ }++ template <typename MT = mapped_type>+ ROBIN_HOOD(NODISCARD)+ typename std::enable_if<is_map, MT&>::type getSecond() noexcept {+ return mData->second;+ }++ template <typename MT = mapped_type>+ ROBIN_HOOD(NODISCARD)+ typename std::enable_if<is_map, MT const&>::type getSecond() const noexcept {+ return mData->second;+ }++ void swap(DataNode<M, false>& o) noexcept {+ using std::swap;+ swap(mData, o.mData);+ }++ private:+ value_type* mData;+ };++ using Node = DataNode<Self, IsFlat>;++ // helpers for insertKeyPrepareEmptySpot: extract first entry (only const required)+ ROBIN_HOOD(NODISCARD) key_type const& getFirstConst(Node const& n) const noexcept {+ return n.getFirst();+ }++ // in case we have void mapped_type, we are not using a pair, thus we just route k through.+ // No need to disable this because it's just not used if not applicable.+ ROBIN_HOOD(NODISCARD) key_type const& getFirstConst(key_type const& k) const noexcept {+ return k;+ }++ // in case we have non-void mapped_type, we have a standard robin_hood::pair+ template <typename Q = mapped_type>+ ROBIN_HOOD(NODISCARD)+ typename std::enable_if<!std::is_void<Q>::value, key_type const&>::type+ getFirstConst(value_type const& vt) const noexcept {+ return vt.first;+ }++ // Cloner //////////////////////////////////////////////////////////++ template <typename M, bool UseMemcpy>+ struct Cloner;++ // fast path: Just copy data, without allocating anything.+ template <typename M>+ struct Cloner<M, true> {+ void operator()(M const& source, M& target) const {+ auto const* const src = reinterpret_cast<char const*>(source.mKeyVals);+ auto* tgt = reinterpret_cast<char*>(target.mKeyVals);+ auto const numElementsWithBuffer = target.calcNumElementsWithBuffer(target.mMask + 1);+ std::copy(src, src + target.calcNumBytesTotal(numElementsWithBuffer), tgt);+ }+ };++ template <typename M>+ struct Cloner<M, false> {+ void operator()(M const& s, M& t) const {+ auto const numElementsWithBuffer = t.calcNumElementsWithBuffer(t.mMask + 1);+ std::copy(s.mInfo, s.mInfo + t.calcNumBytesInfo(numElementsWithBuffer), t.mInfo);++ for (size_t i = 0; i < numElementsWithBuffer; ++i) {+ if (t.mInfo[i]) {+ ::new (static_cast<void*>(t.mKeyVals + i)) Node(t, *s.mKeyVals[i]);+ }+ }+ }+ };++ // Destroyer ///////////////////////////////////////////////////////++ template <typename M, bool IsFlatAndTrivial>+ struct Destroyer {};++ template <typename M>+ struct Destroyer<M, true> {+ void nodes(M& m) const noexcept {+ m.mNumElements = 0;+ }++ void nodesDoNotDeallocate(M& m) const noexcept {+ m.mNumElements = 0;+ }+ };++ template <typename M>+ struct Destroyer<M, false> {+ void nodes(M& m) const noexcept {+ m.mNumElements = 0;+ // clear also resets mInfo to 0, that's sometimes not necessary.+ auto const numElementsWithBuffer = m.calcNumElementsWithBuffer(m.mMask + 1);++ for (size_t idx = 0; idx < numElementsWithBuffer; ++idx) {+ if (0 != m.mInfo[idx]) {+ Node& n = m.mKeyVals[idx];+ n.destroy(m);+ n.~Node();+ }+ }+ }++ void nodesDoNotDeallocate(M& m) const noexcept {+ m.mNumElements = 0;+ // clear also resets mInfo to 0, that's sometimes not necessary.+ auto const numElementsWithBuffer = m.calcNumElementsWithBuffer(m.mMask + 1);+ for (size_t idx = 0; idx < numElementsWithBuffer; ++idx) {+ if (0 != m.mInfo[idx]) {+ Node& n = m.mKeyVals[idx];+ n.destroyDoNotDeallocate();+ n.~Node();+ }+ }+ }+ };++ // Iter ////////////////////////////////////////////////////////////++ struct fast_forward_tag {};++ // generic iterator for both const_iterator and iterator.+ template <bool IsConst>+ // NOLINTNEXTLINE(hicpp-special-member-functions,cppcoreguidelines-special-member-functions)+ class Iter {+ private:+ using NodePtr = typename std::conditional<IsConst, Node const*, Node*>::type;++ public:+ using difference_type = std::ptrdiff_t;+ using value_type = typename Self::value_type;+ using reference = typename std::conditional<IsConst, value_type const&, value_type&>::type;+ using pointer = typename std::conditional<IsConst, value_type const*, value_type*>::type;+ using iterator_category = std::forward_iterator_tag;++ // default constructed iterator can be compared to itself, but WON'T return true when+ // compared to end().+ Iter() = default;++ // Rule of zero: nothing specified. The conversion constructor is only enabled for+ // iterator to const_iterator, so it doesn't accidentally work as a copy ctor.++ // Conversion constructor from iterator to const_iterator.+ template <bool OtherIsConst,+ typename = typename std::enable_if<IsConst && !OtherIsConst>::type>+ // NOLINTNEXTLINE(hicpp-explicit-conversions)+ Iter(Iter<OtherIsConst> const& other) noexcept+ : mKeyVals(other.mKeyVals)+ , mInfo(other.mInfo) {}++ Iter(NodePtr valPtr, uint8_t const* infoPtr) noexcept+ : mKeyVals(valPtr)+ , mInfo(infoPtr) {}++ Iter(NodePtr valPtr, uint8_t const* infoPtr,+ fast_forward_tag ROBIN_HOOD_UNUSED(tag) /*unused*/) noexcept+ : mKeyVals(valPtr)+ , mInfo(infoPtr) {+ fastForward();+ }++ template <bool OtherIsConst,+ typename = typename std::enable_if<IsConst && !OtherIsConst>::type>+ Iter& operator=(Iter<OtherIsConst> const& other) noexcept {+ mKeyVals = other.mKeyVals;+ mInfo = other.mInfo;+ return *this;+ }++ // prefix increment. Undefined behavior if we are at end()!+ Iter& operator++() noexcept {+ mInfo++;+ mKeyVals++;+ fastForward();+ return *this;+ }++ Iter operator++(int) noexcept {+ Iter tmp = *this;+ ++(*this);+ return tmp;+ }++ reference operator*() const {+ return **mKeyVals;+ }++ pointer operator->() const {+ return &**mKeyVals;+ }++ template <bool O>+ bool operator==(Iter<O> const& o) const noexcept {+ return mKeyVals == o.mKeyVals;+ }++ template <bool O>+ bool operator!=(Iter<O> const& o) const noexcept {+ return mKeyVals != o.mKeyVals;+ }++ private:+ // fast forward to the next non-free info byte+ // I've tried a few variants that don't depend on intrinsics, but unfortunately they are+ // quite a bit slower than this one. So I've reverted that change again. See map_benchmark.+ void fastForward() noexcept {+ size_t n = 0;+ while (0U == (n = detail::unaligned_load<size_t>(mInfo))) {+ mInfo += sizeof(size_t);+ mKeyVals += sizeof(size_t);+ }+#if defined(ROBIN_HOOD_DISABLE_INTRINSICS)+ // we know for certain that within the next 8 bytes we'll find a non-zero one.+ if (ROBIN_HOOD_UNLIKELY(0U == detail::unaligned_load<uint32_t>(mInfo))) {+ mInfo += 4;+ mKeyVals += 4;+ }+ if (ROBIN_HOOD_UNLIKELY(0U == detail::unaligned_load<uint16_t>(mInfo))) {+ mInfo += 2;+ mKeyVals += 2;+ }+ if (ROBIN_HOOD_UNLIKELY(0U == *mInfo)) {+ mInfo += 1;+ mKeyVals += 1;+ }+#else+# if ROBIN_HOOD(LITTLE_ENDIAN)+ auto inc = ROBIN_HOOD_COUNT_TRAILING_ZEROES(n) / 8;+# else+ auto inc = ROBIN_HOOD_COUNT_LEADING_ZEROES(n) / 8;+# endif+ mInfo += inc;+ mKeyVals += inc;+#endif+ }++ friend class Table<IsFlat, MaxLoadFactor100, key_type, mapped_type, hasher, key_equal>;+ NodePtr mKeyVals{nullptr};+ uint8_t const* mInfo{nullptr};+ };++ ////////////////////////////////////////////////////////////////////++ // highly performance relevant code.+ // Lower bits are used for indexing into the array (2^n size)+ // The upper 1-5 bits need to be a reasonable good hash, to save comparisons.+ template <typename HashKey>+ void keyToIdx(HashKey&& key, size_t* idx, InfoType* info) const {+ // In addition to whatever hash is used, add another mul & shift so we get better hashing.+ // This serves as a bad hash prevention, if the given data is+ // badly mixed.+ auto h = static_cast<uint64_t>(WHash::operator()(key));++ h *= mHashMultiplier;+ h ^= h >> 33U;++ // the lower InitialInfoNumBits are reserved for info.+ *info = mInfoInc + static_cast<InfoType>((h & InfoMask) >> mInfoHashShift);+ *idx = (static_cast<size_t>(h) >> InitialInfoNumBits) & mMask;+ }++ // forwards the index by one, wrapping around at the end+ void next(InfoType* info, size_t* idx) const noexcept {+ *idx = *idx + 1;+ *info += mInfoInc;+ }++ void nextWhileLess(InfoType* info, size_t* idx) const noexcept {+ // unrolling this by hand did not bring any speedups.+ while (*info < mInfo[*idx]) {+ next(info, idx);+ }+ }++ // Shift everything up by one element. Tries to move stuff around.+ void+ shiftUp(size_t startIdx,+ size_t const insertion_idx) noexcept(std::is_nothrow_move_assignable<Node>::value) {+ auto idx = startIdx;+ ::new (static_cast<void*>(mKeyVals + idx)) Node(std::move(mKeyVals[idx - 1]));+ while (--idx != insertion_idx) {+ mKeyVals[idx] = std::move(mKeyVals[idx - 1]);+ }++ idx = startIdx;+ while (idx != insertion_idx) {+ ROBIN_HOOD_COUNT(shiftUp)+ mInfo[idx] = static_cast<uint8_t>(mInfo[idx - 1] + mInfoInc);+ if (ROBIN_HOOD_UNLIKELY(mInfo[idx] + mInfoInc > 0xFF)) {+ mMaxNumElementsAllowed = 0;+ }+ --idx;+ }+ }++ void shiftDown(size_t idx) noexcept(std::is_nothrow_move_assignable<Node>::value) {+ // until we find one that is either empty or has zero offset.+ // TODO(martinus) we don't need to move everything, just the last one for the same+ // bucket.+ mKeyVals[idx].destroy(*this);++ // until we find one that is either empty or has zero offset.+ while (mInfo[idx + 1] >= 2 * mInfoInc) {+ ROBIN_HOOD_COUNT(shiftDown)+ mInfo[idx] = static_cast<uint8_t>(mInfo[idx + 1] - mInfoInc);+ mKeyVals[idx] = std::move(mKeyVals[idx + 1]);+ ++idx;+ }++ mInfo[idx] = 0;+ // don't destroy, we've moved it+ // mKeyVals[idx].destroy(*this);+ mKeyVals[idx].~Node();+ }++ // copy of find(), except that it returns iterator instead of const_iterator.+ template <typename Other>+ ROBIN_HOOD(NODISCARD)+ size_t findIdx(Other const& key) const {+ size_t idx{};+ InfoType info{};+ keyToIdx(key, &idx, &info);++ do {+ // unrolling this twice gives a bit of a speedup. More unrolling did not help.+ if (info == mInfo[idx] &&+ ROBIN_HOOD_LIKELY(WKeyEqual::operator()(key, mKeyVals[idx].getFirst()))) {+ return idx;+ }+ next(&info, &idx);+ if (info == mInfo[idx] &&+ ROBIN_HOOD_LIKELY(WKeyEqual::operator()(key, mKeyVals[idx].getFirst()))) {+ return idx;+ }+ next(&info, &idx);+ } while (info <= mInfo[idx]);++ // nothing found!+ return mMask == 0 ? 0+ : static_cast<size_t>(std::distance(+ mKeyVals, reinterpret_cast_no_cast_align_warning<Node*>(mInfo)));+ }++ void cloneData(const Table& o) {+ Cloner<Table, IsFlat && ROBIN_HOOD_IS_TRIVIALLY_COPYABLE(Node)>()(o, *this);+ }++ // inserts a keyval that is guaranteed to be new, e.g. when the hashmap is resized.+ // @return True on success, false if something went wrong+ void insert_move(Node&& keyval) {+ // we don't retry, fail if overflowing+ // don't need to check max num elements+ if (0 == mMaxNumElementsAllowed && !try_increase_info()) {+ throwOverflowError();+ }++ size_t idx{};+ InfoType info{};+ keyToIdx(keyval.getFirst(), &idx, &info);++ // skip forward. Use <= because we are certain that the element is not there.+ while (info <= mInfo[idx]) {+ idx = idx + 1;+ info += mInfoInc;+ }++ // key not found, so we are now exactly where we want to insert it.+ auto const insertion_idx = idx;+ auto const insertion_info = static_cast<uint8_t>(info);+ if (ROBIN_HOOD_UNLIKELY(insertion_info + mInfoInc > 0xFF)) {+ mMaxNumElementsAllowed = 0;+ }++ // find an empty spot+ while (0 != mInfo[idx]) {+ next(&info, &idx);+ }++ auto& l = mKeyVals[insertion_idx];+ if (idx == insertion_idx) {+ ::new (static_cast<void*>(&l)) Node(std::move(keyval));+ } else {+ shiftUp(idx, insertion_idx);+ l = std::move(keyval);+ }++ // put at empty spot+ mInfo[insertion_idx] = insertion_info;++ ++mNumElements;+ }++public:+ using iterator = Iter<false>;+ using const_iterator = Iter<true>;++ Table() noexcept(noexcept(Hash()) && noexcept(KeyEqual()))+ : WHash()+ , WKeyEqual() {+ ROBIN_HOOD_TRACE(this)+ }++ // Creates an empty hash map. Nothing is allocated yet, this happens at the first insert.+ // This tremendously speeds up ctor & dtor of a map that never receives an element. The+ // penalty is payed at the first insert, and not before. Lookup of this empty map works+ // because everybody points to DummyInfoByte::b. parameter bucket_count is dictated by the+ // standard, but we can ignore it.+ explicit Table(+ size_t ROBIN_HOOD_UNUSED(bucket_count) /*unused*/, const Hash& h = Hash{},+ const KeyEqual& equal = KeyEqual{}) noexcept(noexcept(Hash(h)) && noexcept(KeyEqual(equal)))+ : WHash(h)+ , WKeyEqual(equal) {+ ROBIN_HOOD_TRACE(this)+ }++ template <typename Iter>+ Table(Iter first, Iter last, size_t ROBIN_HOOD_UNUSED(bucket_count) /*unused*/ = 0,+ const Hash& h = Hash{}, const KeyEqual& equal = KeyEqual{})+ : WHash(h)+ , WKeyEqual(equal) {+ ROBIN_HOOD_TRACE(this)+ insert(first, last);+ }++ Table(std::initializer_list<value_type> initlist,+ size_t ROBIN_HOOD_UNUSED(bucket_count) /*unused*/ = 0, const Hash& h = Hash{},+ const KeyEqual& equal = KeyEqual{})+ : WHash(h)+ , WKeyEqual(equal) {+ ROBIN_HOOD_TRACE(this)+ insert(initlist.begin(), initlist.end());+ }++ Table(Table&& o) noexcept+ : WHash(std::move(static_cast<WHash&>(o)))+ , WKeyEqual(std::move(static_cast<WKeyEqual&>(o)))+ , DataPool(std::move(static_cast<DataPool&>(o))) {+ ROBIN_HOOD_TRACE(this)+ if (o.mMask) {+ mHashMultiplier = std::move(o.mHashMultiplier);+ mKeyVals = std::move(o.mKeyVals);+ mInfo = std::move(o.mInfo);+ mNumElements = std::move(o.mNumElements);+ mMask = std::move(o.mMask);+ mMaxNumElementsAllowed = std::move(o.mMaxNumElementsAllowed);+ mInfoInc = std::move(o.mInfoInc);+ mInfoHashShift = std::move(o.mInfoHashShift);+ // set other's mask to 0 so its destructor won't do anything+ o.init();+ }+ }++ Table& operator=(Table&& o) noexcept {+ ROBIN_HOOD_TRACE(this)+ if (&o != this) {+ if (o.mMask) {+ // only move stuff if the other map actually has some data+ destroy();+ mHashMultiplier = std::move(o.mHashMultiplier);+ mKeyVals = std::move(o.mKeyVals);+ mInfo = std::move(o.mInfo);+ mNumElements = std::move(o.mNumElements);+ mMask = std::move(o.mMask);+ mMaxNumElementsAllowed = std::move(o.mMaxNumElementsAllowed);+ mInfoInc = std::move(o.mInfoInc);+ mInfoHashShift = std::move(o.mInfoHashShift);+ WHash::operator=(std::move(static_cast<WHash&>(o)));+ WKeyEqual::operator=(std::move(static_cast<WKeyEqual&>(o)));+ DataPool::operator=(std::move(static_cast<DataPool&>(o)));++ o.init();++ } else {+ // nothing in the other map => just clear us.+ clear();+ }+ }+ return *this;+ }++ Table(const Table& o)+ : WHash(static_cast<const WHash&>(o))+ , WKeyEqual(static_cast<const WKeyEqual&>(o))+ , DataPool(static_cast<const DataPool&>(o)) {+ ROBIN_HOOD_TRACE(this)+ if (!o.empty()) {+ // not empty: create an exact copy. it is also possible to just iterate through all+ // elements and insert them, but copying is probably faster.++ auto const numElementsWithBuffer = calcNumElementsWithBuffer(o.mMask + 1);+ auto const numBytesTotal = calcNumBytesTotal(numElementsWithBuffer);++ ROBIN_HOOD_LOG("std::malloc " << numBytesTotal << " = calcNumBytesTotal("+ << numElementsWithBuffer << ")")+ mHashMultiplier = o.mHashMultiplier;+ mKeyVals = static_cast<Node*>(+ detail::assertNotNull<std::bad_alloc>(std::malloc(numBytesTotal)));+ // no need for calloc because clonData does memcpy+ mInfo = reinterpret_cast<uint8_t*>(mKeyVals + numElementsWithBuffer);+ mNumElements = o.mNumElements;+ mMask = o.mMask;+ mMaxNumElementsAllowed = o.mMaxNumElementsAllowed;+ mInfoInc = o.mInfoInc;+ mInfoHashShift = o.mInfoHashShift;+ cloneData(o);+ }+ }++ // Creates a copy of the given map. Copy constructor of each entry is used.+ // Not sure why clang-tidy thinks this doesn't handle self assignment, it does+ // NOLINTNEXTLINE(bugprone-unhandled-self-assignment,cert-oop54-cpp)+ Table& operator=(Table const& o) {+ ROBIN_HOOD_TRACE(this)+ if (&o == this) {+ // prevent assigning of itself+ return *this;+ }++ // we keep using the old allocator and not assign the new one, because we want to keep+ // the memory available. when it is the same size.+ if (o.empty()) {+ if (0 == mMask) {+ // nothing to do, we are empty too+ return *this;+ }++ // not empty: destroy what we have there+ // clear also resets mInfo to 0, that's sometimes not necessary.+ destroy();+ init();+ WHash::operator=(static_cast<const WHash&>(o));+ WKeyEqual::operator=(static_cast<const WKeyEqual&>(o));+ DataPool::operator=(static_cast<DataPool const&>(o));++ return *this;+ }++ // clean up old stuff+ Destroyer<Self, IsFlat && std::is_trivially_destructible<Node>::value>{}.nodes(*this);++ if (mMask != o.mMask) {+ // no luck: we don't have the same array size allocated, so we need to realloc.+ if (0 != mMask) {+ // only deallocate if we actually have data!+ ROBIN_HOOD_LOG("std::free")+ std::free(mKeyVals);+ }++ auto const numElementsWithBuffer = calcNumElementsWithBuffer(o.mMask + 1);+ auto const numBytesTotal = calcNumBytesTotal(numElementsWithBuffer);+ ROBIN_HOOD_LOG("std::malloc " << numBytesTotal << " = calcNumBytesTotal("+ << numElementsWithBuffer << ")")+ mKeyVals = static_cast<Node*>(+ detail::assertNotNull<std::bad_alloc>(std::malloc(numBytesTotal)));++ // no need for calloc here because cloneData performs a memcpy.+ mInfo = reinterpret_cast<uint8_t*>(mKeyVals + numElementsWithBuffer);+ // sentinel is set in cloneData+ }+ WHash::operator=(static_cast<const WHash&>(o));+ WKeyEqual::operator=(static_cast<const WKeyEqual&>(o));+ DataPool::operator=(static_cast<DataPool const&>(o));+ mHashMultiplier = o.mHashMultiplier;+ mNumElements = o.mNumElements;+ mMask = o.mMask;+ mMaxNumElementsAllowed = o.mMaxNumElementsAllowed;+ mInfoInc = o.mInfoInc;+ mInfoHashShift = o.mInfoHashShift;+ cloneData(o);++ return *this;+ }++ // Swaps everything between the two maps.+ void swap(Table& o) {+ ROBIN_HOOD_TRACE(this)+ using std::swap;+ swap(o, *this);+ }++ // Clears all data, without resizing.+ void clear() {+ ROBIN_HOOD_TRACE(this)+ if (empty()) {+ // don't do anything! also important because we don't want to write to+ // DummyInfoByte::b, even though we would just write 0 to it.+ return;+ }++ Destroyer<Self, IsFlat && std::is_trivially_destructible<Node>::value>{}.nodes(*this);++ auto const numElementsWithBuffer = calcNumElementsWithBuffer(mMask + 1);+ // clear everything, then set the sentinel again+ uint8_t const z = 0;+ std::fill(mInfo, mInfo + calcNumBytesInfo(numElementsWithBuffer), z);+ mInfo[numElementsWithBuffer] = 1;++ mInfoInc = InitialInfoInc;+ mInfoHashShift = InitialInfoHashShift;+ }++ // Destroys the map and all it's contents.+ ~Table() {+ ROBIN_HOOD_TRACE(this)+ destroy();+ }++ // Checks if both tables contain the same entries. Order is irrelevant.+ bool operator==(const Table& other) const {+ ROBIN_HOOD_TRACE(this)+ if (other.size() != size()) {+ return false;+ }+ for (auto const& otherEntry : other) {+ if (!has(otherEntry)) {+ return false;+ }+ }++ return true;+ }++ bool operator!=(const Table& other) const {+ ROBIN_HOOD_TRACE(this)+ return !operator==(other);+ }++ template <typename Q = mapped_type>+ typename std::enable_if<!std::is_void<Q>::value, Q&>::type operator[](const key_type& key) {+ ROBIN_HOOD_TRACE(this)+ auto idxAndState = insertKeyPrepareEmptySpot(key);+ switch (idxAndState.second) {+ case InsertionState::key_found:+ break;++ case InsertionState::new_node:+ ::new (static_cast<void*>(&mKeyVals[idxAndState.first]))+ Node(*this, std::piecewise_construct, std::forward_as_tuple(key),+ std::forward_as_tuple());+ break;++ case InsertionState::overwrite_node:+ mKeyVals[idxAndState.first] = Node(*this, std::piecewise_construct,+ std::forward_as_tuple(key), std::forward_as_tuple());+ break;++ case InsertionState::overflow_error:+ throwOverflowError();+ }++ return mKeyVals[idxAndState.first].getSecond();+ }++ template <typename Q = mapped_type>+ typename std::enable_if<!std::is_void<Q>::value, Q&>::type operator[](key_type&& key) {+ ROBIN_HOOD_TRACE(this)+ auto idxAndState = insertKeyPrepareEmptySpot(key);+ switch (idxAndState.second) {+ case InsertionState::key_found:+ break;++ case InsertionState::new_node:+ ::new (static_cast<void*>(&mKeyVals[idxAndState.first]))+ Node(*this, std::piecewise_construct, std::forward_as_tuple(std::move(key)),+ std::forward_as_tuple());+ break;++ case InsertionState::overwrite_node:+ mKeyVals[idxAndState.first] =+ Node(*this, std::piecewise_construct, std::forward_as_tuple(std::move(key)),+ std::forward_as_tuple());+ break;++ case InsertionState::overflow_error:+ throwOverflowError();+ }++ return mKeyVals[idxAndState.first].getSecond();+ }++ template <typename Iter>+ void insert(Iter first, Iter last) {+ for (; first != last; ++first) {+ // value_type ctor needed because this might be called with std::pair's+ insert(value_type(*first));+ }+ }++ void insert(std::initializer_list<value_type> ilist) {+ for (auto&& vt : ilist) {+ insert(std::move(vt));+ }+ }++ template <typename... Args>+ std::pair<iterator, bool> emplace(Args&&... args) {+ ROBIN_HOOD_TRACE(this)+ Node n{*this, std::forward<Args>(args)...};+ auto idxAndState = insertKeyPrepareEmptySpot(getFirstConst(n));+ switch (idxAndState.second) {+ case InsertionState::key_found:+ n.destroy(*this);+ break;++ case InsertionState::new_node:+ ::new (static_cast<void*>(&mKeyVals[idxAndState.first])) Node(*this, std::move(n));+ break;++ case InsertionState::overwrite_node:+ mKeyVals[idxAndState.first] = std::move(n);+ break;++ case InsertionState::overflow_error:+ n.destroy(*this);+ throwOverflowError();+ break;+ }++ return std::make_pair(iterator(mKeyVals + idxAndState.first, mInfo + idxAndState.first),+ InsertionState::key_found != idxAndState.second);+ }++ template <typename... Args>+ iterator emplace_hint(const_iterator position, Args&&... args) {+ (void)position;+ return emplace(std::forward<Args>(args)...).first;+ }++ template <typename... Args>+ std::pair<iterator, bool> try_emplace(const key_type& key, Args&&... args) {+ return try_emplace_impl(key, std::forward<Args>(args)...);+ }++ template <typename... Args>+ std::pair<iterator, bool> try_emplace(key_type&& key, Args&&... args) {+ return try_emplace_impl(std::move(key), std::forward<Args>(args)...);+ }++ template <typename... Args>+ iterator try_emplace(const_iterator hint, const key_type& key, Args&&... args) {+ (void)hint;+ return try_emplace_impl(key, std::forward<Args>(args)...).first;+ }++ template <typename... Args>+ iterator try_emplace(const_iterator hint, key_type&& key, Args&&... args) {+ (void)hint;+ return try_emplace_impl(std::move(key), std::forward<Args>(args)...).first;+ }++ template <typename Mapped>+ std::pair<iterator, bool> insert_or_assign(const key_type& key, Mapped&& obj) {+ return insertOrAssignImpl(key, std::forward<Mapped>(obj));+ }++ template <typename Mapped>+ std::pair<iterator, bool> insert_or_assign(key_type&& key, Mapped&& obj) {+ return insertOrAssignImpl(std::move(key), std::forward<Mapped>(obj));+ }++ template <typename Mapped>+ iterator insert_or_assign(const_iterator hint, const key_type& key, Mapped&& obj) {+ (void)hint;+ return insertOrAssignImpl(key, std::forward<Mapped>(obj)).first;+ }++ template <typename Mapped>+ iterator insert_or_assign(const_iterator hint, key_type&& key, Mapped&& obj) {+ (void)hint;+ return insertOrAssignImpl(std::move(key), std::forward<Mapped>(obj)).first;+ }++ std::pair<iterator, bool> insert(const value_type& keyval) {+ ROBIN_HOOD_TRACE(this)+ return emplace(keyval);+ }++ iterator insert(const_iterator hint, const value_type& keyval) {+ (void)hint;+ return emplace(keyval).first;+ }++ std::pair<iterator, bool> insert(value_type&& keyval) {+ return emplace(std::move(keyval));+ }++ iterator insert(const_iterator hint, value_type&& keyval) {+ (void)hint;+ return emplace(std::move(keyval)).first;+ }++ // Returns 1 if key is found, 0 otherwise.+ size_t count(const key_type& key) const { // NOLINT(modernize-use-nodiscard)+ ROBIN_HOOD_TRACE(this)+ auto kv = mKeyVals + findIdx(key);+ if (kv != reinterpret_cast_no_cast_align_warning<Node*>(mInfo)) {+ return 1;+ }+ return 0;+ }++ template <typename OtherKey, typename Self_ = Self>+ // NOLINTNEXTLINE(modernize-use-nodiscard)+ typename std::enable_if<Self_::is_transparent, size_t>::type count(const OtherKey& key) const {+ ROBIN_HOOD_TRACE(this)+ auto kv = mKeyVals + findIdx(key);+ if (kv != reinterpret_cast_no_cast_align_warning<Node*>(mInfo)) {+ return 1;+ }+ return 0;+ }++ bool contains(const key_type& key) const { // NOLINT(modernize-use-nodiscard)+ return 1U == count(key);+ }++ template <typename OtherKey, typename Self_ = Self>+ // NOLINTNEXTLINE(modernize-use-nodiscard)+ typename std::enable_if<Self_::is_transparent, bool>::type contains(const OtherKey& key) const {+ return 1U == count(key);+ }++ // Returns a reference to the value found for key.+ // Throws std::out_of_range if element cannot be found+ template <typename Q = mapped_type>+ // NOLINTNEXTLINE(modernize-use-nodiscard)+ typename std::enable_if<!std::is_void<Q>::value, Q&>::type at(key_type const& key) {+ ROBIN_HOOD_TRACE(this)+ auto kv = mKeyVals + findIdx(key);+ if (kv == reinterpret_cast_no_cast_align_warning<Node*>(mInfo)) {+ doThrow<std::out_of_range>("key not found");+ }+ return kv->getSecond();+ }++ // Returns a reference to the value found for key.+ // Throws std::out_of_range if element cannot be found+ template <typename Q = mapped_type>+ // NOLINTNEXTLINE(modernize-use-nodiscard)+ typename std::enable_if<!std::is_void<Q>::value, Q const&>::type at(key_type const& key) const {+ ROBIN_HOOD_TRACE(this)+ auto kv = mKeyVals + findIdx(key);+ if (kv == reinterpret_cast_no_cast_align_warning<Node*>(mInfo)) {+ doThrow<std::out_of_range>("key not found");+ }+ return kv->getSecond();+ }++ const_iterator find(const key_type& key) const { // NOLINT(modernize-use-nodiscard)+ ROBIN_HOOD_TRACE(this)+ const size_t idx = findIdx(key);+ return const_iterator{mKeyVals + idx, mInfo + idx};+ }++ template <typename OtherKey>+ const_iterator find(const OtherKey& key, is_transparent_tag /*unused*/) const {+ ROBIN_HOOD_TRACE(this)+ const size_t idx = findIdx(key);+ return const_iterator{mKeyVals + idx, mInfo + idx};+ }++ template <typename OtherKey, typename Self_ = Self>+ typename std::enable_if<Self_::is_transparent, // NOLINT(modernize-use-nodiscard)+ const_iterator>::type // NOLINT(modernize-use-nodiscard)+ find(const OtherKey& key) const { // NOLINT(modernize-use-nodiscard)+ ROBIN_HOOD_TRACE(this)+ const size_t idx = findIdx(key);+ return const_iterator{mKeyVals + idx, mInfo + idx};+ }++ iterator find(const key_type& key) {+ ROBIN_HOOD_TRACE(this)+ const size_t idx = findIdx(key);+ return iterator{mKeyVals + idx, mInfo + idx};+ }++ template <typename OtherKey>+ iterator find(const OtherKey& key, is_transparent_tag /*unused*/) {+ ROBIN_HOOD_TRACE(this)+ const size_t idx = findIdx(key);+ return iterator{mKeyVals + idx, mInfo + idx};+ }++ template <typename OtherKey, typename Self_ = Self>+ typename std::enable_if<Self_::is_transparent, iterator>::type find(const OtherKey& key) {+ ROBIN_HOOD_TRACE(this)+ const size_t idx = findIdx(key);+ return iterator{mKeyVals + idx, mInfo + idx};+ }++ iterator begin() {+ ROBIN_HOOD_TRACE(this)+ if (empty()) {+ return end();+ }+ return iterator(mKeyVals, mInfo, fast_forward_tag{});+ }+ const_iterator begin() const { // NOLINT(modernize-use-nodiscard)+ ROBIN_HOOD_TRACE(this)+ return cbegin();+ }+ const_iterator cbegin() const { // NOLINT(modernize-use-nodiscard)+ ROBIN_HOOD_TRACE(this)+ if (empty()) {+ return cend();+ }+ return const_iterator(mKeyVals, mInfo, fast_forward_tag{});+ }++ iterator end() {+ ROBIN_HOOD_TRACE(this)+ // no need to supply valid info pointer: end() must not be dereferenced, and only node+ // pointer is compared.+ return iterator{reinterpret_cast_no_cast_align_warning<Node*>(mInfo), nullptr};+ }+ const_iterator end() const { // NOLINT(modernize-use-nodiscard)+ ROBIN_HOOD_TRACE(this)+ return cend();+ }+ const_iterator cend() const { // NOLINT(modernize-use-nodiscard)+ ROBIN_HOOD_TRACE(this)+ return const_iterator{reinterpret_cast_no_cast_align_warning<Node*>(mInfo), nullptr};+ }++ iterator erase(const_iterator pos) {+ ROBIN_HOOD_TRACE(this)+ // its safe to perform const cast here+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)+ return erase(iterator{const_cast<Node*>(pos.mKeyVals), const_cast<uint8_t*>(pos.mInfo)});+ }++ // Erases element at pos, returns iterator to the next element.+ iterator erase(iterator pos) {+ ROBIN_HOOD_TRACE(this)+ // we assume that pos always points to a valid entry, and not end().+ auto const idx = static_cast<size_t>(pos.mKeyVals - mKeyVals);++ shiftDown(idx);+ --mNumElements;++ if (*pos.mInfo) {+ // we've backward shifted, return this again+ return pos;+ }++ // no backward shift, return next element+ return ++pos;+ }++ size_t erase(const key_type& key) {+ ROBIN_HOOD_TRACE(this)+ size_t idx{};+ InfoType info{};+ keyToIdx(key, &idx, &info);++ // check while info matches with the source idx+ do {+ if (info == mInfo[idx] && WKeyEqual::operator()(key, mKeyVals[idx].getFirst())) {+ shiftDown(idx);+ --mNumElements;+ return 1;+ }+ next(&info, &idx);+ } while (info <= mInfo[idx]);++ // nothing found to delete+ return 0;+ }++ // reserves space for the specified number of elements. Makes sure the old data fits.+ // exactly the same as reserve(c).+ void rehash(size_t c) {+ // forces a reserve+ reserve(c, true);+ }++ // reserves space for the specified number of elements. Makes sure the old data fits.+ // Exactly the same as rehash(c). Use rehash(0) to shrink to fit.+ void reserve(size_t c) {+ // reserve, but don't force rehash+ reserve(c, false);+ }++ // If possible reallocates the map to a smaller one. This frees the underlying table.+ // Does not do anything if load_factor is too large for decreasing the table's size.+ void compact() {+ ROBIN_HOOD_TRACE(this)+ auto newSize = InitialNumElements;+ while (calcMaxNumElementsAllowed(newSize) < mNumElements && newSize != 0) {+ newSize *= 2;+ }+ if (ROBIN_HOOD_UNLIKELY(newSize == 0)) {+ throwOverflowError();+ }++ ROBIN_HOOD_LOG("newSize > mMask + 1: " << newSize << " > " << mMask << " + 1")++ // only actually do anything when the new size is bigger than the old one. This prevents to+ // continuously allocate for each reserve() call.+ if (newSize < mMask + 1) {+ rehashPowerOfTwo(newSize, true);+ }+ }++ size_type size() const noexcept { // NOLINT(modernize-use-nodiscard)+ ROBIN_HOOD_TRACE(this)+ return mNumElements;+ }++ size_type max_size() const noexcept { // NOLINT(modernize-use-nodiscard)+ ROBIN_HOOD_TRACE(this)+ return static_cast<size_type>(-1);+ }++ ROBIN_HOOD(NODISCARD) bool empty() const noexcept {+ ROBIN_HOOD_TRACE(this)+ return 0 == mNumElements;+ }++ float max_load_factor() const noexcept { // NOLINT(modernize-use-nodiscard)+ ROBIN_HOOD_TRACE(this)+ return MaxLoadFactor100 / 100.0F;+ }++ // Average number of elements per bucket. Since we allow only 1 per bucket+ float load_factor() const noexcept { // NOLINT(modernize-use-nodiscard)+ ROBIN_HOOD_TRACE(this)+ return static_cast<float>(size()) / static_cast<float>(mMask + 1);+ }++ ROBIN_HOOD(NODISCARD) size_t mask() const noexcept {+ ROBIN_HOOD_TRACE(this)+ return mMask;+ }++ ROBIN_HOOD(NODISCARD) size_t calcMaxNumElementsAllowed(size_t maxElements) const noexcept {+ if (ROBIN_HOOD_LIKELY(maxElements <= (std::numeric_limits<size_t>::max)() / 100)) {+ return maxElements * MaxLoadFactor100 / 100;+ }++ // we might be a bit inprecise, but since maxElements is quite large that doesn't matter+ return (maxElements / 100) * MaxLoadFactor100;+ }++ ROBIN_HOOD(NODISCARD) size_t calcNumBytesInfo(size_t numElements) const noexcept {+ // we add a uint64_t, which houses the sentinel (first byte) and padding so we can load+ // 64bit types.+ return numElements + sizeof(uint64_t);+ }++ ROBIN_HOOD(NODISCARD)+ size_t calcNumElementsWithBuffer(size_t numElements) const noexcept {+ auto maxNumElementsAllowed = calcMaxNumElementsAllowed(numElements);+ return numElements + (std::min)(maxNumElementsAllowed, (static_cast<size_t>(0xFF)));+ }++ // calculation only allowed for 2^n values+ ROBIN_HOOD(NODISCARD) size_t calcNumBytesTotal(size_t numElements) const {+#if ROBIN_HOOD(BITNESS) == 64+ return numElements * sizeof(Node) + calcNumBytesInfo(numElements);+#else+ // make sure we're doing 64bit operations, so we are at least safe against 32bit overflows.+ auto const ne = static_cast<uint64_t>(numElements);+ auto const s = static_cast<uint64_t>(sizeof(Node));+ auto const infos = static_cast<uint64_t>(calcNumBytesInfo(numElements));++ auto const total64 = ne * s + infos;+ auto const total = static_cast<size_t>(total64);++ if (ROBIN_HOOD_UNLIKELY(static_cast<uint64_t>(total) != total64)) {+ throwOverflowError();+ }+ return total;+#endif+ }++private:+ template <typename Q = mapped_type>+ ROBIN_HOOD(NODISCARD)+ typename std::enable_if<!std::is_void<Q>::value, bool>::type has(const value_type& e) const {+ ROBIN_HOOD_TRACE(this)+ auto it = find(e.first);+ return it != end() && it->second == e.second;+ }++ template <typename Q = mapped_type>+ ROBIN_HOOD(NODISCARD)+ typename std::enable_if<std::is_void<Q>::value, bool>::type has(const value_type& e) const {+ ROBIN_HOOD_TRACE(this)+ return find(e) != end();+ }++ void reserve(size_t c, bool forceRehash) {+ ROBIN_HOOD_TRACE(this)+ auto const minElementsAllowed = (std::max)(c, mNumElements);+ auto newSize = InitialNumElements;+ while (calcMaxNumElementsAllowed(newSize) < minElementsAllowed && newSize != 0) {+ newSize *= 2;+ }+ if (ROBIN_HOOD_UNLIKELY(newSize == 0)) {+ throwOverflowError();+ }++ ROBIN_HOOD_LOG("newSize > mMask + 1: " << newSize << " > " << mMask << " + 1")++ // only actually do anything when the new size is bigger than the old one. This prevents to+ // continuously allocate for each reserve() call.+ if (forceRehash || newSize > mMask + 1) {+ rehashPowerOfTwo(newSize, false);+ }+ }++ // reserves space for at least the specified number of elements.+ // only works if numBuckets if power of two+ // True on success, false otherwise+ void rehashPowerOfTwo(size_t numBuckets, bool forceFree) {+ ROBIN_HOOD_TRACE(this)++ Node* const oldKeyVals = mKeyVals;+ uint8_t const* const oldInfo = mInfo;++ const size_t oldMaxElementsWithBuffer = calcNumElementsWithBuffer(mMask + 1);++ // resize operation: move stuff+ initData(numBuckets);+ if (oldMaxElementsWithBuffer > 1) {+ for (size_t i = 0; i < oldMaxElementsWithBuffer; ++i) {+ if (oldInfo[i] != 0) {+ // might throw an exception, which is really bad since we are in the middle of+ // moving stuff.+ insert_move(std::move(oldKeyVals[i]));+ // destroy the node but DON'T destroy the data.+ oldKeyVals[i].~Node();+ }+ }++ // this check is not necessary as it's guarded by the previous if, but it helps+ // silence g++'s overeager "attempt to free a non-heap object 'map'+ // [-Werror=free-nonheap-object]" warning.+ if (oldKeyVals != reinterpret_cast_no_cast_align_warning<Node*>(&mMask)) {+ // don't destroy old data: put it into the pool instead+ if (forceFree) {+ std::free(oldKeyVals);+ } else {+ DataPool::addOrFree(oldKeyVals, calcNumBytesTotal(oldMaxElementsWithBuffer));+ }+ }+ }+ }++ ROBIN_HOOD(NOINLINE) void throwOverflowError() const {+#if ROBIN_HOOD(HAS_EXCEPTIONS)+ throw std::overflow_error("robin_hood::map overflow");+#else+ abort();+#endif+ }++ template <typename OtherKey, typename... Args>+ std::pair<iterator, bool> try_emplace_impl(OtherKey&& key, Args&&... args) {+ ROBIN_HOOD_TRACE(this)+ auto idxAndState = insertKeyPrepareEmptySpot(key);+ switch (idxAndState.second) {+ case InsertionState::key_found:+ break;++ case InsertionState::new_node:+ ::new (static_cast<void*>(&mKeyVals[idxAndState.first])) Node(+ *this, std::piecewise_construct, std::forward_as_tuple(std::forward<OtherKey>(key)),+ std::forward_as_tuple(std::forward<Args>(args)...));+ break;++ case InsertionState::overwrite_node:+ mKeyVals[idxAndState.first] = Node(*this, std::piecewise_construct,+ std::forward_as_tuple(std::forward<OtherKey>(key)),+ std::forward_as_tuple(std::forward<Args>(args)...));+ break;++ case InsertionState::overflow_error:+ throwOverflowError();+ break;+ }++ return std::make_pair(iterator(mKeyVals + idxAndState.first, mInfo + idxAndState.first),+ InsertionState::key_found != idxAndState.second);+ }++ template <typename OtherKey, typename Mapped>+ std::pair<iterator, bool> insertOrAssignImpl(OtherKey&& key, Mapped&& obj) {+ ROBIN_HOOD_TRACE(this)+ auto idxAndState = insertKeyPrepareEmptySpot(key);+ switch (idxAndState.second) {+ case InsertionState::key_found:+ mKeyVals[idxAndState.first].getSecond() = std::forward<Mapped>(obj);+ break;++ case InsertionState::new_node:+ ::new (static_cast<void*>(&mKeyVals[idxAndState.first])) Node(+ *this, std::piecewise_construct, std::forward_as_tuple(std::forward<OtherKey>(key)),+ std::forward_as_tuple(std::forward<Mapped>(obj)));+ break;++ case InsertionState::overwrite_node:+ mKeyVals[idxAndState.first] = Node(*this, std::piecewise_construct,+ std::forward_as_tuple(std::forward<OtherKey>(key)),+ std::forward_as_tuple(std::forward<Mapped>(obj)));+ break;++ case InsertionState::overflow_error:+ throwOverflowError();+ break;+ }++ return std::make_pair(iterator(mKeyVals + idxAndState.first, mInfo + idxAndState.first),+ InsertionState::key_found != idxAndState.second);+ }++ void initData(size_t max_elements) {+ mNumElements = 0;+ mMask = max_elements - 1;+ mMaxNumElementsAllowed = calcMaxNumElementsAllowed(max_elements);++ auto const numElementsWithBuffer = calcNumElementsWithBuffer(max_elements);++ // malloc & zero mInfo. Faster than calloc everything.+ auto const numBytesTotal = calcNumBytesTotal(numElementsWithBuffer);+ ROBIN_HOOD_LOG("std::calloc " << numBytesTotal << " = calcNumBytesTotal("+ << numElementsWithBuffer << ")")+ mKeyVals = reinterpret_cast<Node*>(+ detail::assertNotNull<std::bad_alloc>(std::malloc(numBytesTotal)));+ mInfo = reinterpret_cast<uint8_t*>(mKeyVals + numElementsWithBuffer);+ std::memset(mInfo, 0, numBytesTotal - numElementsWithBuffer * sizeof(Node));++ // set sentinel+ mInfo[numElementsWithBuffer] = 1;++ mInfoInc = InitialInfoInc;+ mInfoHashShift = InitialInfoHashShift;+ }++ enum class InsertionState { overflow_error, key_found, new_node, overwrite_node };++ // Finds key, and if not already present prepares a spot where to pot the key & value.+ // This potentially shifts nodes out of the way, updates mInfo and number of inserted+ // elements, so the only operation left to do is create/assign a new node at that spot.+ template <typename OtherKey>+ std::pair<size_t, InsertionState> insertKeyPrepareEmptySpot(OtherKey&& key) {+ for (int i = 0; i < 256; ++i) {+ size_t idx{};+ InfoType info{};+ keyToIdx(key, &idx, &info);+ nextWhileLess(&info, &idx);++ // while we potentially have a match+ while (info == mInfo[idx]) {+ if (WKeyEqual::operator()(key, mKeyVals[idx].getFirst())) {+ // key already exists, do NOT insert.+ // see http://en.cppreference.com/w/cpp/container/unordered_map/insert+ return std::make_pair(idx, InsertionState::key_found);+ }+ next(&info, &idx);+ }++ // unlikely that this evaluates to true+ if (ROBIN_HOOD_UNLIKELY(mNumElements >= mMaxNumElementsAllowed)) {+ if (!increase_size()) {+ return std::make_pair(size_t(0), InsertionState::overflow_error);+ }+ continue;+ }++ // key not found, so we are now exactly where we want to insert it.+ auto const insertion_idx = idx;+ auto const insertion_info = info;+ if (ROBIN_HOOD_UNLIKELY(insertion_info + mInfoInc > 0xFF)) {+ mMaxNumElementsAllowed = 0;+ }++ // find an empty spot+ while (0 != mInfo[idx]) {+ next(&info, &idx);+ }++ if (idx != insertion_idx) {+ shiftUp(idx, insertion_idx);+ }+ // put at empty spot+ mInfo[insertion_idx] = static_cast<uint8_t>(insertion_info);+ ++mNumElements;+ return std::make_pair(insertion_idx, idx == insertion_idx+ ? InsertionState::new_node+ : InsertionState::overwrite_node);+ }++ // enough attempts failed, so finally give up.+ return std::make_pair(size_t(0), InsertionState::overflow_error);+ }++ bool try_increase_info() {+ ROBIN_HOOD_LOG("mInfoInc=" << mInfoInc << ", numElements=" << mNumElements+ << ", maxNumElementsAllowed="+ << calcMaxNumElementsAllowed(mMask + 1))+ if (mInfoInc <= 2) {+ // need to be > 2 so that shift works (otherwise undefined behavior!)+ return false;+ }+ // we got space left, try to make info smaller+ mInfoInc = static_cast<uint8_t>(mInfoInc >> 1U);++ // remove one bit of the hash, leaving more space for the distance info.+ // This is extremely fast because we can operate on 8 bytes at once.+ ++mInfoHashShift;+ auto const numElementsWithBuffer = calcNumElementsWithBuffer(mMask + 1);++ for (size_t i = 0; i < numElementsWithBuffer; i += 8) {+ auto val = unaligned_load<uint64_t>(mInfo + i);+ val = (val >> 1U) & UINT64_C(0x7f7f7f7f7f7f7f7f);+ std::memcpy(mInfo + i, &val, sizeof(val));+ }+ // update sentinel, which might have been cleared out!+ mInfo[numElementsWithBuffer] = 1;++ mMaxNumElementsAllowed = calcMaxNumElementsAllowed(mMask + 1);+ return true;+ }++ // True if resize was possible, false otherwise+ bool increase_size() {+ // nothing allocated yet? just allocate InitialNumElements+ if (0 == mMask) {+ initData(InitialNumElements);+ return true;+ }++ auto const maxNumElementsAllowed = calcMaxNumElementsAllowed(mMask + 1);+ if (mNumElements < maxNumElementsAllowed && try_increase_info()) {+ return true;+ }++ ROBIN_HOOD_LOG("mNumElements=" << mNumElements << ", maxNumElementsAllowed="+ << maxNumElementsAllowed << ", load="+ << (static_cast<double>(mNumElements) * 100.0 /+ (static_cast<double>(mMask) + 1)))++ if (mNumElements * 2 < calcMaxNumElementsAllowed(mMask + 1)) {+ // we have to resize, even though there would still be plenty of space left!+ // Try to rehash instead. Delete freed memory so we don't steadyily increase mem in case+ // we have to rehash a few times+ nextHashMultiplier();+ rehashPowerOfTwo(mMask + 1, true);+ } else {+ // we've reached the capacity of the map, so the hash seems to work nice. Keep using it.+ rehashPowerOfTwo((mMask + 1) * 2, false);+ }+ return true;+ }++ void nextHashMultiplier() {+ // adding an *even* number, so that the multiplier will always stay odd. This is necessary+ // so that the hash stays a mixing function (and thus doesn't have any information loss).+ mHashMultiplier += UINT64_C(0xc4ceb9fe1a85ec54);+ }++ void destroy() {+ if (0 == mMask) {+ // don't deallocate!+ return;+ }++ Destroyer<Self, IsFlat && std::is_trivially_destructible<Node>::value>{}+ .nodesDoNotDeallocate(*this);++ // This protection against not deleting mMask shouldn't be needed as it's sufficiently+ // protected with the 0==mMask check, but I have this anyways because g++ 7 otherwise+ // reports a compile error: attempt to free a non-heap object 'fm'+ // [-Werror=free-nonheap-object]+ if (mKeyVals != reinterpret_cast_no_cast_align_warning<Node*>(&mMask)) {+ ROBIN_HOOD_LOG("std::free")+ std::free(mKeyVals);+ }+ }++ void init() noexcept {+ mKeyVals = reinterpret_cast_no_cast_align_warning<Node*>(&mMask);+ mInfo = reinterpret_cast<uint8_t*>(&mMask);+ mNumElements = 0;+ mMask = 0;+ mMaxNumElementsAllowed = 0;+ mInfoInc = InitialInfoInc;+ mInfoHashShift = InitialInfoHashShift;+ }++ // members are sorted so no padding occurs+ uint64_t mHashMultiplier = UINT64_C(0xc4ceb9fe1a85ec53); // 8 byte 8+ Node* mKeyVals = reinterpret_cast_no_cast_align_warning<Node*>(&mMask); // 8 byte 16+ uint8_t* mInfo = reinterpret_cast<uint8_t*>(&mMask); // 8 byte 24+ size_t mNumElements = 0; // 8 byte 32+ size_t mMask = 0; // 8 byte 40+ size_t mMaxNumElementsAllowed = 0; // 8 byte 48+ InfoType mInfoInc = InitialInfoInc; // 4 byte 52+ InfoType mInfoHashShift = InitialInfoHashShift; // 4 byte 56+ // 16 byte 56 if NodeAllocator+};++} // namespace detail++// map++template <typename Key, typename T, typename Hash = hash<Key>,+ typename KeyEqual = std::equal_to<Key>, size_t MaxLoadFactor100 = 80>+using unordered_flat_map = detail::Table<true, MaxLoadFactor100, Key, T, Hash, KeyEqual>;++template <typename Key, typename T, typename Hash = hash<Key>,+ typename KeyEqual = std::equal_to<Key>, size_t MaxLoadFactor100 = 80>+using unordered_node_map = detail::Table<false, MaxLoadFactor100, Key, T, Hash, KeyEqual>;++template <typename Key, typename T, typename Hash = hash<Key>,+ typename KeyEqual = std::equal_to<Key>, size_t MaxLoadFactor100 = 80>+using unordered_map =+ detail::Table<sizeof(tracy::pair<Key, T>) <= sizeof(size_t) * 6 &&+ std::is_nothrow_move_constructible<tracy::pair<Key, T>>::value &&+ std::is_nothrow_move_assignable<tracy::pair<Key, T>>::value,+ MaxLoadFactor100, Key, T, Hash, KeyEqual>;++// set++template <typename Key, typename Hash = hash<Key>, typename KeyEqual = std::equal_to<Key>,+ size_t MaxLoadFactor100 = 80>+using unordered_flat_set = detail::Table<true, MaxLoadFactor100, Key, void, Hash, KeyEqual>;++template <typename Key, typename Hash = hash<Key>, typename KeyEqual = std::equal_to<Key>,+ size_t MaxLoadFactor100 = 80>+using unordered_node_set = detail::Table<false, MaxLoadFactor100, Key, void, Hash, KeyEqual>;++template <typename Key, typename Hash = hash<Key>, typename KeyEqual = std::equal_to<Key>,+ size_t MaxLoadFactor100 = 80>+using unordered_set = detail::Table<sizeof(Key) <= sizeof(size_t) * 6 &&+ std::is_nothrow_move_constructible<Key>::value &&+ std::is_nothrow_move_assignable<Key>::value,+ MaxLoadFactor100, Key, void, Hash, KeyEqual>;++} // namespace robin_hood++#endif
+ cbits/tracy/server/tracy_xxhash.h view
@@ -0,0 +1,6773 @@+/*+ * xxHash - Extremely Fast Hash algorithm+ * Header File+ * Copyright (C) 2012-2021 Yann Collet+ *+ * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php)+ *+ * 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.+ *+ * 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.+ *+ * You can contact the author at:+ * - xxHash homepage: https://www.xxhash.com+ * - xxHash source repository: https://github.com/Cyan4973/xxHash+ */++/*!+ * @mainpage xxHash+ *+ * xxHash is an extremely fast non-cryptographic hash algorithm, working at RAM speed+ * limits.+ *+ * It is proposed in four flavors, in three families:+ * 1. @ref XXH32_family+ * - Classic 32-bit hash function. Simple, compact, and runs on almost all+ * 32-bit and 64-bit systems.+ * 2. @ref XXH64_family+ * - Classic 64-bit adaptation of XXH32. Just as simple, and runs well on most+ * 64-bit systems (but _not_ 32-bit systems).+ * 3. @ref XXH3_family+ * - Modern 64-bit and 128-bit hash function family which features improved+ * strength and performance across the board, especially on smaller data.+ * It benefits greatly from SIMD and 64-bit without requiring it.+ *+ * Benchmarks+ * ---+ * The reference system uses an Intel i7-9700K CPU, and runs Ubuntu x64 20.04.+ * The open source benchmark program is compiled with clang v10.0 using -O3 flag.+ *+ * | Hash Name | ISA ext | Width | Large Data Speed | Small Data Velocity |+ * | -------------------- | ------- | ----: | ---------------: | ------------------: |+ * | XXH3_64bits() | @b AVX2 | 64 | 59.4 GB/s | 133.1 |+ * | MeowHash | AES-NI | 128 | 58.2 GB/s | 52.5 |+ * | XXH3_128bits() | @b AVX2 | 128 | 57.9 GB/s | 118.1 |+ * | CLHash | PCLMUL | 64 | 37.1 GB/s | 58.1 |+ * | XXH3_64bits() | @b SSE2 | 64 | 31.5 GB/s | 133.1 |+ * | XXH3_128bits() | @b SSE2 | 128 | 29.6 GB/s | 118.1 |+ * | RAM sequential read | | N/A | 28.0 GB/s | N/A |+ * | ahash | AES-NI | 64 | 22.5 GB/s | 107.2 |+ * | City64 | | 64 | 22.0 GB/s | 76.6 |+ * | T1ha2 | | 64 | 22.0 GB/s | 99.0 |+ * | City128 | | 128 | 21.7 GB/s | 57.7 |+ * | FarmHash | AES-NI | 64 | 21.3 GB/s | 71.9 |+ * | XXH64() | | 64 | 19.4 GB/s | 71.0 |+ * | SpookyHash | | 64 | 19.3 GB/s | 53.2 |+ * | Mum | | 64 | 18.0 GB/s | 67.0 |+ * | CRC32C | SSE4.2 | 32 | 13.0 GB/s | 57.9 |+ * | XXH32() | | 32 | 9.7 GB/s | 71.9 |+ * | City32 | | 32 | 9.1 GB/s | 66.0 |+ * | Blake3* | @b AVX2 | 256 | 4.4 GB/s | 8.1 |+ * | Murmur3 | | 32 | 3.9 GB/s | 56.1 |+ * | SipHash* | | 64 | 3.0 GB/s | 43.2 |+ * | Blake3* | @b SSE2 | 256 | 2.4 GB/s | 8.1 |+ * | HighwayHash | | 64 | 1.4 GB/s | 6.0 |+ * | FNV64 | | 64 | 1.2 GB/s | 62.7 |+ * | Blake2* | | 256 | 1.1 GB/s | 5.1 |+ * | SHA1* | | 160 | 0.8 GB/s | 5.6 |+ * | MD5* | | 128 | 0.6 GB/s | 7.8 |+ * @note+ * - Hashes which require a specific ISA extension are noted. SSE2 is also noted,+ * even though it is mandatory on x64.+ * - Hashes with an asterisk are cryptographic. Note that MD5 is non-cryptographic+ * by modern standards.+ * - Small data velocity is a rough average of algorithm's efficiency for small+ * data. For more accurate information, see the wiki.+ * - More benchmarks and strength tests are found on the wiki:+ * https://github.com/Cyan4973/xxHash/wiki+ *+ * Usage+ * ------+ * All xxHash variants use a similar API. Changing the algorithm is a trivial+ * substitution.+ *+ * @pre+ * For functions which take an input and length parameter, the following+ * requirements are assumed:+ * - The range from [`input`, `input + length`) is valid, readable memory.+ * - The only exception is if the `length` is `0`, `input` may be `NULL`.+ * - For C++, the objects must have the *TriviallyCopyable* property, as the+ * functions access bytes directly as if it was an array of `unsigned char`.+ *+ * @anchor single_shot_example+ * **Single Shot**+ *+ * These functions are stateless functions which hash a contiguous block of memory,+ * immediately returning the result. They are the easiest and usually the fastest+ * option.+ *+ * XXH32(), XXH64(), XXH3_64bits(), XXH3_128bits()+ *+ * @code{.c}+ * #include <string.h>+ * #include "xxhash.h"+ *+ * // Example for a function which hashes a null terminated string with XXH32().+ * XXH32_hash_t hash_string(const char* string, XXH32_hash_t seed)+ * {+ * // NULL pointers are only valid if the length is zero+ * size_t length = (string == NULL) ? 0 : strlen(string);+ * return XXH32(string, length, seed);+ * }+ * @endcode+ *+ * @anchor streaming_example+ * **Streaming**+ *+ * These groups of functions allow incremental hashing of unknown size, even+ * more than what would fit in a size_t.+ *+ * XXH32_reset(), XXH64_reset(), XXH3_64bits_reset(), XXH3_128bits_reset()+ *+ * @code{.c}+ * #include <stdio.h>+ * #include <assert.h>+ * #include "xxhash.h"+ * // Example for a function which hashes a FILE incrementally with XXH3_64bits().+ * XXH64_hash_t hashFile(FILE* f)+ * {+ * // Allocate a state struct. Do not just use malloc() or new.+ * XXH3_state_t* state = XXH3_createState();+ * assert(state != NULL && "Out of memory!");+ * // Reset the state to start a new hashing session.+ * XXH3_64bits_reset(state);+ * char buffer[4096];+ * size_t count;+ * // Read the file in chunks+ * while ((count = fread(buffer, 1, sizeof(buffer), f)) != 0) {+ * // Run update() as many times as necessary to process the data+ * XXH3_64bits_update(state, buffer, count);+ * }+ * // Retrieve the finalized hash. This will not change the state.+ * XXH64_hash_t result = XXH3_64bits_digest(state);+ * // Free the state. Do not use free().+ * XXH3_freeState(state);+ * return result;+ * }+ * @endcode+ *+ * @file xxhash.h+ * xxHash prototypes and implementation+ */++#if defined (__cplusplus)+extern "C" {+#endif++/* ****************************+ * INLINE mode+ ******************************/+/*!+ * @defgroup public Public API+ * Contains details on the public xxHash functions.+ * @{+ */+#ifdef XXH_DOXYGEN+/*!+ * @brief Gives access to internal state declaration, required for static allocation.+ *+ * Incompatible with dynamic linking, due to risks of ABI changes.+ *+ * Usage:+ * @code{.c}+ * #define XXH_STATIC_LINKING_ONLY+ * #include "xxhash.h"+ * @endcode+ */+# define XXH_STATIC_LINKING_ONLY+/* Do not undef XXH_STATIC_LINKING_ONLY for Doxygen */++/*!+ * @brief Gives access to internal definitions.+ *+ * Usage:+ * @code{.c}+ * #define XXH_STATIC_LINKING_ONLY+ * #define XXH_IMPLEMENTATION+ * #include "xxhash.h"+ * @endcode+ */+# define XXH_IMPLEMENTATION+/* Do not undef XXH_IMPLEMENTATION for Doxygen */++/*!+ * @brief Exposes the implementation and marks all functions as `inline`.+ *+ * 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:+ * @code{.c}+ * #define XXH_INLINE_ALL+ * #include "xxhash.h"+ * @endcode+ * Do not compile and link xxhash.o as a separate object, as it is not useful.+ */+# define XXH_INLINE_ALL+# undef XXH_INLINE_ALL+/*!+ * @brief Exposes the implementation without marking functions as inline.+ */+# define XXH_PRIVATE_API+# undef XXH_PRIVATE_API+/*!+ * @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 @ref XXH_NAMESPACE to automatically prefix+ * any public symbol from xxhash library with the value of @ref 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++#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 */)+# define XXH_PUBLIC_API static inline+# elif defined(_MSC_VER)+# define XXH_PUBLIC_API static __inline+# else+ /* note: this version may generate warnings for unused static functions */+# define XXH_PUBLIC_API static+# endif++ /*+ * 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++ /* 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 */++/* ****************************************************************+ * Stable API+ *****************************************************************/+#ifndef XXHASH_H_5627135585666179+#define XXHASH_H_5627135585666179 1++/*! @brief Marks a global symbol. */+#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_NAMESPACE+# define XXH_CAT(A,B) A##B+# define XXH_NAME2(A,B) XXH_CAT(A,B)+# 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 XXH32_freeState XXH_NAME2(XXH_NAMESPACE, XXH32_freeState)+# define XXH32_reset XXH_NAME2(XXH_NAMESPACE, XXH32_reset)+# define XXH32_update XXH_NAME2(XXH_NAMESPACE, XXH32_update)+# define XXH32_digest XXH_NAME2(XXH_NAMESPACE, XXH32_digest)+# define XXH32_copyState XXH_NAME2(XXH_NAMESPACE, XXH32_copyState)+# define XXH32_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH32_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+++/* *************************************+* Compiler specifics+***************************************/++/* 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++#if defined (__GNUC__)+# define XXH_CONSTF __attribute__((const))+# define XXH_PUREF __attribute__((pure))+# define XXH_MALLOCF __attribute__((malloc))+#else+# define XXH_CONSTF /* disable */+# define XXH_PUREF+# define XXH_MALLOCF+#endif++/* *************************************+* Version+***************************************/+#define XXH_VERSION_MAJOR 0+#define XXH_VERSION_MINOR 8+#define XXH_VERSION_RELEASE 2+/*! @brief Version number, encoded as two digits each */+#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 @ref XXH_VERSION_NUMBER of the invoked library.+ */+XXH_PUBLIC_API XXH_CONSTF unsigned XXH_versionNumber (void);+++/* ****************************+* Common basic types+******************************/+#include <stddef.h> /* size_t */+/*!+ * @brief Exit code for the streaming API.+ */+typedef enum {+ XXH_OK = 0, /*!< OK */+ XXH_ERROR /*!< Error */+} XXH_errorcode;+++/*-**********************************************************************+* 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;++#elif !defined (__VMS) \+ && (defined (__cplusplus) \+ || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )+# include <stdint.h>+ typedef uint32_t XXH32_hash_t;++#else+# include <limits.h>+# if UINT_MAX == 0xFFFFFFFFUL+ typedef unsigned int XXH32_hash_t;+# elif ULONG_MAX == 0xFFFFFFFFUL+ typedef unsigned long XXH32_hash_t;+# else+# error "unsupported platform: need a 32-bit type"+# endif+#endif++/*!+ * @}+ *+ * @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 the @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+ *+ * See @ref single_shot_example "Single Shot Example" for an example.+ *+ * @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 XXH_PUREF XXH32_hash_t XXH32 (const void* input, size_t length, XXH32_hash_t seed);++#ifndef XXH_NO_STREAM+/*!+ * 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()`.+ *+ * @see streaming_example at the top of @ref xxhash.h for an example.+ */++/*!+ * @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 XXH_MALLOCF 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);++/*!+ * @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);++/*!+ * @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 XXH_PUREF XXH32_hash_t XXH32_digest (const XXH32_state_t* statePtr);+#endif /* !XXH_NO_STREAM */++/******* Canonical representation *******/++/*+ * 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);++/*!+ * @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 XXH_PUREF XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src);+++/*! @cond Doxygen ignores this part */+#ifdef __has_attribute+# define XXH_HAS_ATTRIBUTE(x) __has_attribute(x)+#else+# define XXH_HAS_ATTRIBUTE(x) 0+#endif+/*! @endcond */++/*! @cond Doxygen ignores this part */+/*+ * C23 __STDC_VERSION__ number hasn't been specified yet. For now+ * leave as `201711L` (C17 + 1).+ * TODO: Update to correct value when its been specified.+ */+#define XXH_C23_VN 201711L+/*! @endcond */++/*! @cond Doxygen ignores this part */+/* C-language Attributes are added in C23. */+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= XXH_C23_VN) && defined(__has_c_attribute)+# define XXH_HAS_C_ATTRIBUTE(x) __has_c_attribute(x)+#else+# define XXH_HAS_C_ATTRIBUTE(x) 0+#endif+/*! @endcond */++/*! @cond Doxygen ignores this part */+#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+/*! @endcond */++/*! @cond Doxygen ignores this part */+/*+ * 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(fallthrough) || XXH_HAS_CPP_ATTRIBUTE(fallthrough)+# define XXH_FALLTHROUGH [[fallthrough]]+#elif XXH_HAS_ATTRIBUTE(__fallthrough__)+# define XXH_FALLTHROUGH __attribute__ ((__fallthrough__))+#else+# define XXH_FALLTHROUGH /* fallthrough */+#endif+/*! @endcond */++/*! @cond Doxygen ignores this part */+/*+ * Define XXH_NOESCAPE for annotated pointers in public API.+ * https://clang.llvm.org/docs/AttributeReference.html#noescape+ * As of writing this, only supported by clang.+ */+#if XXH_HAS_ATTRIBUTE(noescape)+# define XXH_NOESCAPE __attribute__((noescape))+#else+# define XXH_NOESCAPE+#endif+/*! @endcond */+++/*!+ * @}+ * @ingroup public+ * @{+ */++#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++/*!+ * @}+ *+ * @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.+ */++/*!+ * @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 XXH_PUREF XXH64_hash_t XXH64(XXH_NOESCAPE const void* input, size_t length, XXH64_hash_t seed);++/******* Streaming *******/+#ifndef XXH_NO_STREAM+/*!+ * @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 */++/*!+ * @brief Allocates an @ref XXH64_state_t.+ *+ * Must be freed with XXH64_freeState().+ * @return An allocated XXH64_state_t on success, `NULL` on failure.+ */+XXH_PUBLIC_API XXH_MALLOCF XXH64_state_t* XXH64_createState(void);++/*!+ * @brief Frees an @ref XXH64_state_t.+ *+ * Must be allocated with XXH64_createState().+ * @param statePtr A pointer to an @ref XXH64_state_t allocated with @ref XXH64_createState().+ * @return XXH_OK.+ */+XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr);++/*!+ * @brief Copies one @ref XXH64_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 XXH64_copyState(XXH_NOESCAPE XXH64_state_t* dst_state, const XXH64_state_t* src_state);++/*!+ * @brief Resets an @ref XXH64_state_t to begin a new hash.+ *+ * This function resets and seeds a state. Call it before @ref XXH64_update().+ *+ * @param statePtr The state struct to reset.+ * @param seed The 64-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 XXH64_reset (XXH_NOESCAPE XXH64_state_t* statePtr, XXH64_hash_t seed);++/*!+ * @brief Consumes a block of @p input to an @ref XXH64_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 XXH64_update (XXH_NOESCAPE XXH64_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length);++/*!+ * @brief Returns the calculated hash value from an @ref XXH64_state_t.+ *+ * @note+ * Calling XXH64_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 xxHash64 value from that state.+ */+XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64_digest (XXH_NOESCAPE const XXH64_state_t* statePtr);+#endif /* !XXH_NO_STREAM */+/******* Canonical representation *******/++/*!+ * @brief Canonical (big endian) representation of @ref XXH64_hash_t.+ */+typedef struct { unsigned char digest[sizeof(XXH64_hash_t)]; } XXH64_canonical_t;++/*!+ * @brief Converts an @ref XXH64_hash_t to a big endian @ref XXH64_canonical_t.+ *+ * @param dst The @ref XXH64_canonical_t pointer to be stored to.+ * @param hash The @ref XXH64_hash_t to be converted.+ *+ * @pre+ * @p dst must not be `NULL`.+ */+XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH_NOESCAPE XXH64_canonical_t* dst, XXH64_hash_t hash);++/*!+ * @brief Converts an @ref XXH64_canonical_t to a native @ref XXH64_hash_t.+ *+ * @param src The @ref XXH64_canonical_t to convert.+ *+ * @pre+ * @p src must not be `NULL`.+ *+ * @return The converted hash.+ */+XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64_hashFromCanonical(XXH_NOESCAPE 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.+ * Most 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.+ *+ * XXH3 has a fast scalar implementation, but it also includes accelerated SIMD+ * implementations for many common platforms:+ * - AVX512+ * - AVX2+ * - SSE2+ * - ARM NEON+ * - WebAssembly SIMD128+ * - POWER8 VSX+ * - s390x ZVector+ * This can be controlled via the @ref XXH_VECTOR macro, but it automatically+ * selects the best version according to predefined macros. For the x86 family, an+ * automatic runtime dispatcher is included separately in @ref xxh_x86dispatch.c.+ *+ * XXH3 implementation is portable:+ * it has a generic C90 formulation that can be compiled on any platform,+ * all implementations generate 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+************************************************************************/++/*!+ * @brief 64-bit unseeded variant of XXH3.+ *+ * This is equivalent to @ref XXH3_64bits_withSeed() with a seed of 0, however+ * it may have slightly better performance due to constant propagation of the+ * defaults.+ *+ * @see+ * XXH32(), XXH64(), XXH3_128bits(): equivalent for the other xxHash algorithms+ * @see+ * XXH3_64bits_withSeed(), XXH3_64bits_withSecret(): other seeding variants+ * @see+ * XXH3_64bits_reset(), XXH3_64bits_update(), XXH3_64bits_digest(): Streaming version.+ */+XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits(XXH_NOESCAPE const void* input, size_t length);++/*!+ * @brief 64-bit seeded variant of XXH3+ *+ * 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 @ref XXH3_64bits().+ *+ * @param input The data to hash+ * @param length The length+ * @param seed The 64-bit seed to alter the state.+ */+XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_withSeed(XXH_NOESCAPE const void* input, size_t length, 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++/*!+ * @brief 64-bit variant of XXH3 with a custom "secret".+ *+ * 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 XXH_PUREF XXH64_hash_t XXH3_64bits_withSecret(XXH_NOESCAPE const void* data, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize);+++/******* Streaming *******/+#ifndef XXH_NO_STREAM+/*+ * 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 XXH_MALLOCF XXH3_state_t* XXH3_createState(void);+XXH_PUBLIC_API XXH_errorcode XXH3_freeState(XXH3_state_t* statePtr);++/*!+ * @brief Copies one @ref XXH3_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 XXH3_copyState(XXH_NOESCAPE XXH3_state_t* dst_state, XXH_NOESCAPE const XXH3_state_t* src_state);++/*!+ * @brief Resets an @ref XXH3_state_t to begin a new hash.+ *+ * This function resets `statePtr` and generate a secret with default parameters. Call it before @ref XXH3_64bits_update().+ * Digest will be equivalent to `XXH3_64bits()`.+ *+ * @param statePtr The state struct to reset.+ *+ * @pre+ * @p statePtr must not be `NULL`.+ *+ * @return @ref XXH_OK on success, @ref XXH_ERROR on failure.+ *+ */+XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr);++/*!+ * @brief Resets an @ref XXH3_state_t with 64-bit seed to begin a new hash.+ *+ * This function resets `statePtr` and generate a secret from `seed`. Call it before @ref XXH3_64bits_update().+ * Digest will be equivalent to `XXH3_64bits_withSeed()`.+ *+ * @param statePtr The state struct to reset.+ * @param seed The 64-bit seed to alter the state.+ *+ * @pre+ * @p statePtr must not be `NULL`.+ *+ * @return @ref XXH_OK on success, @ref XXH_ERROR on failure.+ *+ */+XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSeed(XXH_NOESCAPE 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(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize);++/*!+ * @brief Consumes a block of @p input to an @ref XXH3_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 XXH3_64bits_update (XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length);++/*!+ * @brief Returns the calculated XXH3 64-bit hash value from an @ref XXH3_state_t.+ *+ * @note+ * Calling XXH3_64bits_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 XXH3 64-bit hash value from that state.+ */+XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_digest (XXH_NOESCAPE const XXH3_state_t* statePtr);+#endif /* !XXH_NO_STREAM */++/* 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;++/*!+ * @brief Unseeded 128-bit variant of XXH3+ *+ * The 128-bit variant of XXH3 has more strength, but it has a bit of overhead+ * for shorter inputs.+ *+ * This is equivalent to @ref XXH3_128bits_withSeed() with a seed of 0, however+ * it may have slightly better performance due to constant propagation of the+ * defaults.+ *+ * @see+ * XXH32(), XXH64(), XXH3_64bits(): equivalent for the other xxHash algorithms+ * @see+ * XXH3_128bits_withSeed(), XXH3_128bits_withSecret(): other seeding variants+ * @see+ * XXH3_128bits_reset(), XXH3_128bits_update(), XXH3_128bits_digest(): Streaming version.+ */+XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits(XXH_NOESCAPE const void* data, size_t len);+/*! @brief Seeded 128-bit variant of XXH3. @see XXH3_64bits_withSeed(). */+XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_withSeed(XXH_NOESCAPE const void* data, size_t len, XXH64_hash_t seed);+/*! @brief Custom secret 128-bit variant of XXH3. @see XXH3_64bits_withSecret(). */+XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_withSecret(XXH_NOESCAPE const void* data, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize);++/******* Streaming *******/+#ifndef XXH_NO_STREAM+/*+ * 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.+ */++/*!+ * @brief Resets an @ref XXH3_state_t to begin a new hash.+ *+ * This function resets `statePtr` and generate a secret with default parameters. Call it before @ref XXH3_128bits_update().+ * Digest will be equivalent to `XXH3_128bits()`.+ *+ * @param statePtr The state struct to reset.+ *+ * @pre+ * @p statePtr must not be `NULL`.+ *+ * @return @ref XXH_OK on success, @ref XXH_ERROR on failure.+ *+ */+XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr);++/*!+ * @brief Resets an @ref XXH3_state_t with 64-bit seed to begin a new hash.+ *+ * This function resets `statePtr` and generate a secret from `seed`. Call it before @ref XXH3_128bits_update().+ * Digest will be equivalent to `XXH3_128bits_withSeed()`.+ *+ * @param statePtr The state struct to reset.+ * @param seed The 64-bit seed to alter the state.+ *+ * @pre+ * @p statePtr must not be `NULL`.+ *+ * @return @ref XXH_OK on success, @ref XXH_ERROR on failure.+ *+ */+XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed);+/*! @brief Custom secret 128-bit variant of XXH3. @see XXH_64bits_reset_withSecret(). */+XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize);++/*!+ * @brief Consumes a block of @p input to an @ref XXH3_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 XXH3_128bits_update (XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length);++/*!+ * @brief Returns the calculated XXH3 128-bit hash value from an @ref XXH3_state_t.+ *+ * @note+ * Calling XXH3_128bits_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 XXH3 128-bit hash value from that state.+ */+XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_digest (XXH_NOESCAPE const XXH3_state_t* statePtr);+#endif /* !XXH_NO_STREAM */++/* 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 XXH_PUREF int XXH128_isEqual(XXH128_hash_t h1, XXH128_hash_t h2);++/*!+ * @brief Compares two @ref XXH128_hash_t+ * 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 XXH_PUREF int XXH128_cmp(XXH_NOESCAPE const void* h128_1, XXH_NOESCAPE const void* h128_2);+++/******* Canonical representation *******/+typedef struct { unsigned char digest[sizeof(XXH128_hash_t)]; } XXH128_canonical_t;+++/*!+ * @brief Converts an @ref XXH128_hash_t to a big endian @ref XXH128_canonical_t.+ *+ * @param dst The @ref XXH128_canonical_t pointer to be stored to.+ * @param hash The @ref XXH128_hash_t to be converted.+ *+ * @pre+ * @p dst must not be `NULL`.+ */+XXH_PUBLIC_API void XXH128_canonicalFromHash(XXH_NOESCAPE XXH128_canonical_t* dst, XXH128_hash_t hash);++/*!+ * @brief Converts an @ref XXH128_canonical_t to a native @ref XXH128_hash_t.+ *+ * @param src The @ref XXH128_canonical_t to convert.+ *+ * @pre+ * @p src must not be `NULL`.+ *+ * @return The converted hash.+ */+XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH128_hashFromCanonical(XXH_NOESCAPE const XXH128_canonical_t* src);+++#endif /* !XXH_NO_XXH3 */+#endif /* XXH_NO_LONG_LONG */++/*!+ * @}+ */+#endif /* XXHASH_H_5627135585666179 */++++#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++/*!+ * @internal+ * @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. See @ref XXH32_state_s::v and @ref XXH64_state_s::v */+ 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) \+ do { \+ XXH3_state_t* tmp_xxh3_state_ptr = (XXH3_state_ptr); \+ tmp_xxh3_state_ptr->seed = 0; \+ tmp_xxh3_state_ptr->extSecret = NULL; \+ } while(0)+++/*!+ * simple alias to pre-selected XXH3_128bits variant+ */+XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH128(XXH_NOESCAPE 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 @p secretSize into an+ * already allocated buffer @p secretBuffer.+ *+ * The generated secret can then be used with any `*_withSecret()` variant.+ * The functions @ref XXH3_128bits_withSecret(), @ref XXH3_64bits_withSecret(),+ * @ref XXH3_128bits_reset_withSecret() and @ref XXH3_64bits_reset_withSecret()+ * are part of this list. They all accept a `secret` parameter+ * which must be large enough for implementation reasons (>= @ref XXH3_SECRET_SIZE_MIN)+ * _and_ feature very high entropy (consist of random-looking bytes).+ * These conditions can be a high bar to meet, so @ref XXH3_generateSecret() can+ * be employed to ensure proper quality.+ *+ * @p 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.+ *+ * @pre+ * - @p secretSize must be >= @ref XXH3_SECRET_SIZE_MIN+ * - When @p customSeedSize > 0, supplying NULL as customSeed is undefined behavior.+ *+ * Example code:+ * @code{.c}+ * #include <stdio.h>+ * #include <stdlib.h>+ * #include <string.h>+ * #define XXH_STATIC_LINKING_ONLY // expose unstable API+ * #include "xxhash.h"+ * // Hashes argv[2] using the entropy from argv[1].+ * int main(int argc, char* argv[])+ * {+ * char secret[XXH3_SECRET_SIZE_MIN];+ * if (argv != 3) { return 1; }+ * XXH3_generateSecret(secret, sizeof(secret), argv[1], strlen(argv[1]));+ * XXH64_hash_t h = XXH3_64bits_withSecret(+ * argv[2], strlen(argv[2]),+ * secret, sizeof(secret)+ * );+ * printf("%016llx\n", (unsigned long long) h);+ * }+ * @endcode+ */+XXH_PUBLIC_API XXH_errorcode XXH3_generateSecret(XXH_NOESCAPE void* secretBuffer, size_t secretSize, XXH_NOESCAPE const void* customSeed, size_t customSeedSize);++/*!+ * @brief Generate the same secret as the _withSeed() variants.+ *+ * The generated secret can be used in combination with+ *`*_withSecret()` and `_withSecretandSeed()` variants.+ *+ * Example C++ `std::string` hash class:+ * @code{.cpp}+ * #include <string>+ * #define XXH_STATIC_LINKING_ONLY // expose unstable API+ * #include "xxhash.h"+ * // Slow, seeds each time+ * class HashSlow {+ * XXH64_hash_t seed;+ * public:+ * HashSlow(XXH64_hash_t s) : seed{s} {}+ * size_t operator()(const std::string& x) const {+ * return size_t{XXH3_64bits_withSeed(x.c_str(), x.length(), seed)};+ * }+ * };+ * // Fast, caches the seeded secret for future uses.+ * class HashFast {+ * unsigned char secret[XXH3_SECRET_SIZE_MIN];+ * public:+ * HashFast(XXH64_hash_t s) {+ * XXH3_generateSecret_fromSeed(secret, seed);+ * }+ * size_t operator()(const std::string& x) const {+ * return size_t{+ * XXH3_64bits_withSecret(x.c_str(), x.length(), secret, sizeof(secret))+ * };+ * }+ * };+ * @endcode+ * @param secretBuffer A writable buffer of @ref XXH3_SECRET_SIZE_MIN bytes+ * @param seed The seed to seed the state.+ */+XXH_PUBLIC_API void XXH3_generateSecret_fromSeed(XXH_NOESCAPE void* secretBuffer, XXH64_hash_t seed);++/*!+ * These variants generate hash values using either+ * @p seed for "short" keys (< XXH3_MIDSIZE_MAX = 240 bytes)+ * or @p 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 @p 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 XXH_PUREF XXH64_hash_t+XXH3_64bits_withSecretandSeed(XXH_NOESCAPE const void* data, size_t len,+ XXH_NOESCAPE const void* secret, size_t secretSize,+ XXH64_hash_t seed);+/*! @copydoc XXH3_64bits_withSecretandSeed() */+XXH_PUBLIC_API XXH_PUREF XXH128_hash_t+XXH3_128bits_withSecretandSeed(XXH_NOESCAPE const void* input, size_t length,+ XXH_NOESCAPE const void* secret, size_t secretSize,+ XXH64_hash_t seed64);+#ifndef XXH_NO_STREAM+/*! @copydoc XXH3_64bits_withSecretandSeed() */+XXH_PUBLIC_API XXH_errorcode+XXH3_64bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr,+ XXH_NOESCAPE const void* secret, size_t secretSize,+ XXH64_hash_t seed64);+/*! @copydoc XXH3_64bits_withSecretandSeed() */+XXH_PUBLIC_API XXH_errorcode+XXH3_128bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr,+ XXH_NOESCAPE const void* secret, size_t secretSize,+ XXH64_hash_t seed64);+#endif /* !XXH_NO_STREAM */++#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__((aligned(1)))`+ * @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 https://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_SIZE_OPT+ * @brief Controls how much xxHash optimizes for size.+ *+ * xxHash, when compiled, tends to result in a rather large binary size. This+ * is mostly due to heavy usage to forced inlining and constant folding of the+ * @ref XXH3_family to increase performance.+ *+ * However, some developers prefer size over speed. This option can+ * significantly reduce the size of the generated code. When using the `-Os`+ * or `-Oz` options on GCC or Clang, this is defined to 1 by default,+ * otherwise it is defined to 0.+ *+ * Most of these size optimizations can be controlled manually.+ *+ * This is a number from 0-2.+ * - `XXH_SIZE_OPT` == 0: Default. xxHash makes no size optimizations. Speed+ * comes first.+ * - `XXH_SIZE_OPT` == 1: Default for `-Os` and `-Oz`. xxHash is more+ * conservative and disables hacks that increase code size. It implies the+ * options @ref XXH_NO_INLINE_HINTS == 1, @ref XXH_FORCE_ALIGN_CHECK == 0,+ * and @ref XXH3_NEON_LANES == 8 if they are not already defined.+ * - `XXH_SIZE_OPT` == 2: xxHash tries to make itself as small as possible.+ * Performance may cry. For example, the single shot functions just use the+ * streaming API.+ */+# define XXH_SIZE_OPT 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, and some ARM chips+ * which are platforms known to offer good unaligned memory accesses performance.+ *+ * It is also disabled by default when @ref XXH_SIZE_OPT >= 1.+ *+ * 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), using `-fno-inline` with GCC or Clang, or if+ * @ref XXH_SIZE_OPT >= 1, this will automatically be defined.+ */+# define XXH_NO_INLINE_HINTS 0++/*!+ * @def XXH3_INLINE_SECRET+ * @brief Determines whether to inline the XXH3 withSecret code.+ *+ * When the secret size is known, the compiler can improve the performance+ * of XXH3_64bits_withSecret() and XXH3_128bits_withSecret().+ *+ * However, if the secret size is not known, it doesn't have any benefit. This+ * happens when xxHash is compiled into a global symbol. Therefore, if+ * @ref XXH_INLINE_ALL is *not* defined, this will be defined to 0.+ *+ * Additionally, this defaults to 0 on GCC 12+, which has an issue with function pointers+ * that are *sometimes* force inline on -Og, and it is impossible to automatically+ * detect this optimization level.+ */+# define XXH3_INLINE_SECRET 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. */++/*!+ * @def XXH_NO_STREAM+ * @brief Disables the streaming API.+ *+ * When xxHash is not inlined and the streaming functions are not used, disabling+ * the streaming functions can improve code size significantly, especially with+ * the @ref XXH3_family which tends to make constant folded copies of itself.+ */+# define XXH_NO_STREAM+# undef XXH_NO_STREAM /* don't actually */+#endif /* XXH_DOXYGEN */+/*!+ * @}+ */++#ifndef XXH_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */+ /* prefer __packed__ structures (method 1) for GCC+ * < ARMv7 with unaligned access (e.g. Raspbian armhf) still uses byte shifting, so we use memcpy+ * which for some reason does unaligned loads. */+# if defined(__GNUC__) && !(defined(__ARM_ARCH) && __ARM_ARCH < 7 && defined(__ARM_FEATURE_UNALIGNED))+# define XXH_FORCE_MEMORY_ACCESS 1+# endif+#endif++#ifndef XXH_SIZE_OPT+ /* default to 1 for -Os or -Oz */+# if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE_SIZE__)+# define XXH_SIZE_OPT 1+# else+# define XXH_SIZE_OPT 0+# endif+#endif++#ifndef XXH_FORCE_ALIGN_CHECK /* can be defined externally */+ /* don't check on sizeopt, x86, aarch64, or arm when unaligned access is available */+# if XXH_SIZE_OPT >= 1 || \+ defined(__i386) || defined(__x86_64__) || defined(__aarch64__) || defined(__ARM_FEATURE_UNALIGNED) \+ || defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM64) || defined(_M_ARM) /* visual */+# define XXH_FORCE_ALIGN_CHECK 0+# else+# define XXH_FORCE_ALIGN_CHECK 1+# endif+#endif++#ifndef XXH_NO_INLINE_HINTS+# if XXH_SIZE_OPT >= 1 || defined(__NO_INLINE__) /* -O0, -fno-inline */+# define XXH_NO_INLINE_HINTS 1+# else+# define XXH_NO_INLINE_HINTS 0+# endif+#endif++#ifndef XXH3_INLINE_SECRET+# if (defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 12) \+ || !defined(XXH_INLINE_ALL)+# define XXH3_INLINE_SECRET 0+# else+# define XXH3_INLINE_SECRET 1+# endif+#endif++#ifndef XXH32_ENDJMP+/* generally preferable for performance */+# define XXH32_ENDJMP 0+#endif++/*!+ * @defgroup impl Implementation+ * @{+ */+++/* *************************************+* Includes & Memory related functions+***************************************/+#if defined(XXH_NO_STREAM)+/* nothing */+#elif defined(XXH_NO_STDLIB)++/* When requesting to disable any mention of stdlib,+ * the library loses the ability to invoked malloc / free.+ * In practice, it means that functions like `XXH*_createState()`+ * will always fail, and return NULL.+ * This flag is useful in situations where+ * xxhash.h is integrated into some kernel, embedded or limited environment+ * without access to dynamic allocation.+ */++static XXH_CONSTF void* XXH_malloc(size_t s) { (void)s; return NULL; }+static void XXH_free(void* p) { (void)p; }++#else++/*+ * Modify the local functions below should you wish to use+ * different memory routines for malloc() and free()+ */+#include <stdlib.h>++/*!+ * @internal+ * @brief Modify this function to use a different routine than malloc().+ */+static XXH_MALLOCF void* XXH_malloc(size_t s) { return malloc(s); }++/*!+ * @internal+ * @brief Modify this function to use a different routine than free().+ */+static void XXH_free(void* p) { free(p); }++#endif /* XXH_NO_STDLIB */++#include <string.h>++/*!+ * @internal+ * @brief Modify this function to use a different routine than memcpy().+ */+static void* XXH_memcpy(void* dest, const void* src, size_t size)+{+ return memcpy(dest,src,size);+}++#include <limits.h> /* ULLONG_MAX */+++/* *************************************+* 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++#if XXH3_INLINE_SECRET+# define XXH3_WITH_SECRET_INLINE XXH_FORCE_INLINE+#else+# define XXH3_WITH_SECRET_INLINE XXH_NO_INLINE+#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+# if defined(__INTEL_COMPILER)+# define XXH_ASSERT(c) XXH_ASSUME((unsigned char) (c))+# else+# define XXH_ASSERT(c) XXH_ASSUME(c)+# endif+#endif++/* note: use after variable declarations */+#ifndef XXH_STATIC_ASSERT+# if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */+# 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__("" : "+r" (var))+#else+# define XXH_COMPILER_GUARD(var) ((void)0)+#endif++/* Specifically for NEON vectors which use the "w" constraint, on+ * Clang. */+#if defined(__clang__) && defined(__ARM_ARCH) && !defined(__wasm__)+# define XXH_COMPILER_GUARD_CLANG_NEON(var) __asm__("" : "+w" (var))+#else+# define XXH_COMPILER_GUARD_CLANG_NEON(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+# warning "XXH_OLD_NAMES is planned to be removed starting v0.9. If the program depends on it, consider moving away from it by employing newer type names directly"+# 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))++/*+ * __attribute__((aligned(1))) is supported by gcc and clang. Originally the+ * documentation claimed that it only increased the alignment, but actually it+ * can decrease it on gcc, clang, and icc:+ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69502,+ * https://gcc.godbolt.org/z/xYez1j67Y.+ */+#ifdef XXH_OLD_NAMES+typedef union { xxh_u32 u32; } __attribute__((packed)) unalign;+#endif+static xxh_u32 XXH_read32(const void* ptr)+{+ typedef __attribute__((aligned(1))) xxh_u32 xxh_unalign32;+ return *((const xxh_unalign32*)ptr);+}++#else++/*+ * Portable and safe solution. Generally efficient.+ * see: https://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++++/*+ * C23 and future versions have standard "unreachable()".+ * Once it has been implemented reliably we can add it as an+ * additional case:+ *+ * ```+ * #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= XXH_C23_VN)+ * # include <stddef.h>+ * # ifdef unreachable+ * # define XXH_UNREACHABLE() unreachable()+ * # endif+ * #endif+ * ```+ *+ * Note C++23 also has std::unreachable() which can be detected+ * as follows:+ * ```+ * #if defined(__cpp_lib_unreachable) && (__cpp_lib_unreachable >= 202202L)+ * # include <utility>+ * # define XXH_UNREACHABLE() std::unreachable()+ * #endif+ * ```+ * NB: `__cpp_lib_unreachable` is defined in the `<version>` header.+ * We don't use that as including `<utility>` in `extern "C"` blocks+ * doesn't work on GCC12+ */++#if XXH_HAS_BUILTIN(__builtin_unreachable)+# define XXH_UNREACHABLE() __builtin_unreachable()++#elif defined(_MSC_VER)+# define XXH_UNREACHABLE() __assume(0)++#else+# define XXH_UNREACHABLE()+#endif++#if XXH_HAS_BUILTIN(__builtin_assume)+# define XXH_ASSUME(c) __builtin_assume(c)+#else+# define XXH_ASSUME(c) if (!(c)) { XXH_UNREACHABLE(); }+#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+ *+ * Details on the XXH32 implementation.+ * @{+ */+ /* #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(__wasm_simd128__)) && !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 is *very aggressive* in vectorizing+ * the loop. NEON is only faster on the A53, and with the newer cores, it is less+ * than half the speed.+ *+ * Additionally, this is used on WASM SIMD128 because it JITs to the same+ * SIMD instructions and has the same issue.+ */+ 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 hash The hash to avalanche.+ * @return The avalanched hash.+ */+static xxh_u32 XXH32_avalanche(xxh_u32 hash)+{+ hash ^= hash >> 15;+ hash *= XXH_PRIME32_2;+ hash ^= hash >> 13;+ hash *= XXH_PRIME32_3;+ hash ^= hash >> 16;+ return hash;+}++#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 hash 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.+ * @see XXH64_finalize().+ */+static XXH_PUREF xxh_u32+XXH32_finalize(xxh_u32 hash, const xxh_u8* ptr, size_t len, XXH_alignment align)+{+#define XXH_PROCESS1 do { \+ hash += (*ptr++) * XXH_PRIME32_5; \+ hash = XXH_rotl32(hash, 11) * XXH_PRIME32_1; \+} while (0)++#define XXH_PROCESS4 do { \+ hash += XXH_get32bits(ptr) * XXH_PRIME32_3; \+ ptr += 4; \+ hash = XXH_rotl32(hash, 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(hash);+ } else {+ switch(len&15) /* or switch(bEnd - p) */ {+ case 12: XXH_PROCESS4;+ XXH_FALLTHROUGH; /* fallthrough */+ case 8: XXH_PROCESS4;+ XXH_FALLTHROUGH; /* fallthrough */+ case 4: XXH_PROCESS4;+ return XXH32_avalanche(hash);++ case 13: XXH_PROCESS4;+ XXH_FALLTHROUGH; /* fallthrough */+ case 9: XXH_PROCESS4;+ XXH_FALLTHROUGH; /* fallthrough */+ case 5: XXH_PROCESS4;+ XXH_PROCESS1;+ return XXH32_avalanche(hash);++ case 14: XXH_PROCESS4;+ XXH_FALLTHROUGH; /* fallthrough */+ case 10: XXH_PROCESS4;+ XXH_FALLTHROUGH; /* fallthrough */+ case 6: XXH_PROCESS4;+ XXH_PROCESS1;+ XXH_PROCESS1;+ return XXH32_avalanche(hash);++ case 15: XXH_PROCESS4;+ XXH_FALLTHROUGH; /* fallthrough */+ case 11: XXH_PROCESS4;+ XXH_FALLTHROUGH; /* fallthrough */+ case 7: XXH_PROCESS4;+ XXH_FALLTHROUGH; /* fallthrough */+ case 3: XXH_PROCESS1;+ XXH_FALLTHROUGH; /* fallthrough */+ case 2: XXH_PROCESS1;+ XXH_FALLTHROUGH; /* fallthrough */+ case 1: XXH_PROCESS1;+ XXH_FALLTHROUGH; /* fallthrough */+ case 0: return XXH32_avalanche(hash);+ }+ XXH_ASSERT(0);+ return hash; /* 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_PUREF 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 !defined(XXH_NO_STREAM) && XXH_SIZE_OPT >= 2+ /* 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 *******/+#ifndef XXH_NO_STREAM+/*! @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);+}+#endif /* !XXH_NO_STREAM */++/******* 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))++/*+ * __attribute__((aligned(1))) is supported by gcc and clang. Originally the+ * documentation claimed that it only increased the alignment, but actually it+ * can decrease it on gcc, clang, and icc:+ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69502,+ * https://gcc.godbolt.org/z/xYez1j67Y.+ */+#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 __attribute__((aligned(1))) xxh_u64 xxh_unalign64;+ return *((const xxh_unalign64*)ptr);+}++#else++/*+ * Portable and safe solution. Generally efficient.+ * see: https://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+ *+ * Details on the XXH64 implementation.+ * @{+ */+/* #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++/*! @copydoc XXH32_round */+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;+}++/*! @copydoc XXH32_avalanche */+static xxh_u64 XXH64_avalanche(xxh_u64 hash)+{+ hash ^= hash >> 33;+ hash *= XXH_PRIME64_2;+ hash ^= hash >> 29;+ hash *= XXH_PRIME64_3;+ hash ^= hash >> 32;+ return hash;+}+++#define XXH_get64bits(p) XXH_readLE64_align(p, align)++/*!+ * @internal+ * @brief Processes the last 0-31 bytes of @p ptr.+ *+ * There may be up to 31 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 hash The hash to finalize.+ * @param ptr The pointer to the remaining input.+ * @param len The remaining length, modulo 32.+ * @param align Whether @p ptr is aligned.+ * @return The finalized hash+ * @see XXH32_finalize().+ */+static XXH_PUREF xxh_u64+XXH64_finalize(xxh_u64 hash, 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;+ hash ^= k1;+ hash = XXH_rotl64(hash,27) * XXH_PRIME64_1 + XXH_PRIME64_4;+ len -= 8;+ }+ if (len >= 4) {+ hash ^= (xxh_u64)(XXH_get32bits(ptr)) * XXH_PRIME64_1;+ ptr += 4;+ hash = XXH_rotl64(hash, 23) * XXH_PRIME64_2 + XXH_PRIME64_3;+ len -= 4;+ }+ while (len > 0) {+ hash ^= (*ptr++) * XXH_PRIME64_5;+ hash = XXH_rotl64(hash, 11) * XXH_PRIME64_1;+ --len;+ }+ return XXH64_avalanche(hash);+}++#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++/*!+ * @internal+ * @brief The implementation for @ref XXH64().+ *+ * @param input , len , seed Directly passed from @ref XXH64().+ * @param align Whether @p input is aligned.+ * @return The calculated hash.+ */+XXH_FORCE_INLINE XXH_PUREF 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 (XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed)+{+#if !defined(XXH_NO_STREAM) && XXH_SIZE_OPT >= 2+ /* 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 *******/+#ifndef XXH_NO_STREAM+/*! @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(XXH_NOESCAPE 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(XXH_NOESCAPE 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 (XXH_NOESCAPE XXH64_state_t* state, XXH_NOESCAPE 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(XXH_NOESCAPE 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);+}+#endif /* !XXH_NO_STREAM */++/******* Canonical representation *******/++/*! @ingroup XXH64_family */+XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH_NOESCAPE 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(XXH_NOESCAPE 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+#elif (defined (__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))) \+ || (defined (__clang__)) \+ || (defined (_MSC_VER) && (_MSC_VER >= 1400)) \+ || (defined (__INTEL_COMPILER) && (__INTEL_COMPILER >= 1300))+/*+ * There are a LOT more compilers that recognize __restrict but this+ * covers the major ones.+ */+# define XXH_RESTRICT __restrict+#else+# 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++#ifndef XXH_HAS_INCLUDE+# ifdef __has_include+# define XXH_HAS_INCLUDE(x) __has_include(x)+# else+# define XXH_HAS_INCLUDE(x) 0+# endif+#endif++#if defined(__GNUC__) || defined(__clang__)+# if defined(__ARM_FEATURE_SVE)+# include <arm_sve.h>+# endif+# if defined(__ARM_NEON__) || defined(__ARM_NEON) \+ || (defined(_M_ARM) && _M_ARM >= 7) \+ || defined(_M_ARM64) || defined(_M_ARM64EC) \+ || (defined(__wasm_simd128__) && XXH_HAS_INCLUDE(<arm_neon.h>)) /* WASM SIMD128 via SIMDe */+# 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.+ * internal macro 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, all AArch64, and WASM SIMD128+ * via the SIMDeverywhere polyfill provided with the+ * Emscripten SDK.+ */+ XXH_VSX = 5, /*!< VSX and ZVector for POWER8/z13 (64-bit) */+ XXH_SVE = 6, /*!< SVE for some ARMv8-A and ARMv9-A */+};+/*!+ * @ingroup tuning+ * @brief Selects the minimum alignment for XXH3's accumulators.+ *+ * When using SIMD, this should match the alignment required 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+# define XXH_SVE 6+#endif++#ifndef XXH_VECTOR /* can be defined on command line */+# if defined(__ARM_FEATURE_SVE)+# define XXH_VECTOR XXH_SVE+# elif ( \+ defined(__ARM_NEON__) || defined(__ARM_NEON) /* gcc */ \+ || defined(_M_ARM) || defined(_M_ARM64) || defined(_M_ARM64EC) /* msvc */ \+ || (defined(__wasm_simd128__) && XXH_HAS_INCLUDE(<arm_neon.h>)) /* wasm simd128 via SIMDe */ \+ ) && ( \+ 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++/* __ARM_FEATURE_SVE is only supported by GCC & Clang. */+#if (XXH_VECTOR == XXH_SVE) && !defined(__ARM_FEATURE_SVE)+# ifdef _MSC_VER+# pragma warning(once : 4606)+# else+# warning "__ARM_FEATURE_SVE isn't supported. Use SCALAR instead."+# endif+# undef XXH_VECTOR+# define XXH_VECTOR XXH_SCALAR+#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+# elif XXH_VECTOR == XXH_SVE /* sve */+# 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+#elif XXH_VECTOR == XXH_SVE+# define XXH_SEC_ALIGN XXH_ACC_ALIGN+#else+# define XXH_SEC_ALIGN 8+#endif++#if defined(__GNUC__) || defined(__clang__)+# define XXH_ALIASING __attribute__((may_alias))+#else+# define XXH_ALIASING /* nothing */+#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__) && XXH_SIZE_OPT <= 0 /* respect -O0 and -Os */+# pragma GCC push_options+# pragma GCC optimize("-O2")+#endif++#if XXH_VECTOR == XXH_NEON++/*+ * UGLY HACK: While AArch64 GCC on Linux does not seem to care, on macOS, GCC -O3+ * optimizes out the entire hashLong loop because of the aliasing violation.+ *+ * However, GCC is also inefficient at load-store optimization with vld1q/vst1q,+ * so the only option is to mark it as aliasing.+ */+typedef uint64x2_t xxh_aliasing_uint64x2_t XXH_ALIASING;++/*!+ * @internal+ * @brief `vld1q_u64` but faster and alignment-safe.+ *+ * On AArch64, unaligned access is always safe, but on ARMv7-a, it is only+ * *conditionally* safe (`vld1` has an alignment bit like `movdq[ua]` in x86).+ *+ * GCC for AArch64 sees `vld1q_u8` as an intrinsic instead of a load, so it+ * prohibits load-store optimizations. Therefore, a direct dereference is used.+ *+ * Otherwise, `vld1q_u8` is used with `vreinterpretq_u8_u64` to do a safe+ * unaligned load.+ */+#if defined(__aarch64__) && defined(__GNUC__) && !defined(__clang__)+XXH_FORCE_INLINE uint64x2_t XXH_vld1q_u64(void const* ptr) /* silence -Wcast-align */+{+ return *(xxh_aliasing_uint64x2_t const *)ptr;+}+#else+XXH_FORCE_INLINE uint64x2_t XXH_vld1q_u64(void const* ptr)+{+ return vreinterpretq_u64_u8(vld1q_u8((uint8_t const*)ptr));+}+#endif++/*!+ * @internal+ * @brief `vmlal_u32` on low and high halves of a vector.+ *+ * This is a workaround for AArch64 GCC < 11 which implemented arm_neon.h with+ * inline assembly and were therefore incapable of merging the `vget_{low, high}_u32`+ * with `vmlal_u32`.+ */+#if defined(__aarch64__) && defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 11+XXH_FORCE_INLINE uint64x2_t+XXH_vmlal_low_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs)+{+ /* Inline assembly is the only way */+ __asm__("umlal %0.2d, %1.2s, %2.2s" : "+w" (acc) : "w" (lhs), "w" (rhs));+ return acc;+}+XXH_FORCE_INLINE uint64x2_t+XXH_vmlal_high_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs)+{+ /* This intrinsic works as expected */+ return vmlal_high_u32(acc, lhs, rhs);+}+#else+/* Portable intrinsic versions */+XXH_FORCE_INLINE uint64x2_t+XXH_vmlal_low_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs)+{+ return vmlal_u32(acc, vget_low_u32(lhs), vget_low_u32(rhs));+}+/*! @copydoc XXH_vmlal_low_u32+ * Assume the compiler converts this to vmlal_high_u32 on aarch64 */+XXH_FORCE_INLINE uint64x2_t+XXH_vmlal_high_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs)+{+ return vmlal_u32(acc, vget_high_u32(lhs), vget_high_u32(rhs));+}+#endif++/*!+ * @ingroup tuning+ * @brief Controls the NEON to scalar ratio for XXH3+ *+ * This can be set to 2, 4, 6, or 8.+ *+ * ARM Cortex CPUs are _very_ sensitive to how their pipelines are used.+ *+ * For example, the Cortex-A73 can dispatch 3 micro-ops per cycle, but only 2 of those+ * can be NEON. If you are only using NEON instructions, you are only using 2/3 of the CPU+ * bandwidth.+ *+ * This is even more noticeable on the more advanced cores like the Cortex-A76 which+ * can dispatch 8 micro-ops per cycle, but still only 2 NEON micro-ops at once.+ *+ * Therefore, to make the most out of the pipeline, it is beneficial to run 6 NEON lanes+ * and 2 scalar lanes, which is chosen by default.+ *+ * This does not apply to Apple processors or 32-bit processors, which run better with+ * full NEON. These will default to 8. Additionally, size-optimized builds run 8 lanes.+ *+ * This change benefits CPUs with large micro-op buffers without negatively affecting+ * most 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% |+ * | Apple M1 | 4 NEON/8 micro-ops | 37.3 GB/s | 36.1 GB/s | ~-3% |+ *+ * It also seems to fix some bad codegen on GCC, making it almost as fast as clang.+ *+ * When using WASM SIMD128, if this is 2 or 6, SIMDe will scalarize 2 of the lanes meaning+ * it effectively becomes worse 4.+ *+ * @see XXH3_accumulate_512_neon()+ */+# ifndef XXH3_NEON_LANES+# if (defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64) || defined(_M_ARM64EC)) \+ && !defined(__APPLE__) && XXH_SIZE_OPT <= 0+# 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+/* Annoyingly, these headers _may_ define three macros: `bool`, `vector`,+ * and `pixel`. This is a problem for obvious reasons.+ *+ * These keywords are unnecessary; the spec literally says they are+ * equivalent to `__bool`, `__vector`, and `__pixel` and may be undef'd+ * after including the header.+ *+ * We use pragma push_macro/pop_macro to keep the namespace clean. */+# pragma push_macro("bool")+# pragma push_macro("vector")+# pragma push_macro("pixel")+/* silence potential macro redefined warnings */+# undef bool+# undef vector+# undef pixel++# if defined(__s390x__)+# include <s390intrin.h>+# else+# include <altivec.h>+# endif++/* Restore the original macro values, if applicable. */+# pragma pop_macro("pixel")+# pragma pop_macro("vector")+# pragma pop_macro("bool")++typedef __vector unsigned long long xxh_u64x2;+typedef __vector unsigned char xxh_u8x16;+typedef __vector unsigned xxh_u32x4;++/*+ * UGLY HACK: Similar to aarch64 macOS GCC, s390x GCC has the same aliasing issue.+ */+typedef xxh_u64x2 xxh_aliasing_u64x2 XXH_ALIASING;++# 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) && !defined(__ibmxl__)+/* Clang has a better way to control this, we can just use the builtin which doesn't swap. */+ /* The IBM XL Compiler (which defined __clang__) only implements the vec_* operations */+# 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 */++#if XXH_VECTOR == XXH_SVE+#define ACCRND(acc, offset) \+do { \+ svuint64_t input_vec = svld1_u64(mask, xinput + offset); \+ svuint64_t secret_vec = svld1_u64(mask, xsecret + offset); \+ svuint64_t mixed = sveor_u64_x(mask, secret_vec, input_vec); \+ svuint64_t swapped = svtbl_u64(input_vec, kSwap); \+ svuint64_t mixed_lo = svextw_u64_x(mask, mixed); \+ svuint64_t mixed_hi = svlsr_n_u64_x(mask, mixed, 32); \+ svuint64_t mul = svmad_u64_x(mask, mixed_lo, mixed_hi, swapped); \+ acc = svadd_u64_x(mask, acc, mul); \+} while (0)+#endif /* XXH_VECTOR == XXH_SVE */++/* 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 XXH_SIZE_OPT >= 1+# define XXH_PREFETCH(ptr) (void)(ptr)+# elif 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,+};++static const xxh_u64 PRIME_MX1 = 0x165667919E3779F9ULL; /*!< 0b0001011001010110011001111001000110011110001101110111100111111001 */+static const xxh_u64 PRIME_MX2 = 0x9FB21C651E98DF25ULL; /*!< 0b1001111110110010000111000110010100011110100110001101111100100101 */++#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_CONSTF 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 *= PRIME_MX1;+ 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 *= PRIME_MX2;+ h64 ^= (h64 >> 35) + len ;+ h64 *= PRIME_MX2;+ 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 XXH_PUREF 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 XXH_PUREF 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 XXH_PUREF 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 XXH_PUREF 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 XXH_PUREF 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 XXH_SIZE_OPT >= 1+ /* Smaller and cleaner, but slightly slower. */+ unsigned int i = (unsigned int)(len - 1) / 32;+ do {+ acc += XXH3_mix16B(input+16 * i, secret+32*i, seed);+ acc += XXH3_mix16B(input+len-16*(i+1), secret+32*i+16, seed);+ } while (i-- != 0);+#else+ 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);+#endif+ return XXH3_avalanche(acc);+ }+}++#define XXH3_MIDSIZE_MAX 240++XXH_NO_INLINE XXH_PUREF 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;+ xxh_u64 acc_end;+ unsigned int const nbRounds = (unsigned int)len / 16;+ unsigned int i;+ XXH_ASSERT(128 < len && len <= XXH3_MIDSIZE_MAX);+ for (i=0; i<8; i++) {+ acc += XXH3_mix16B(input+(16*i), secret+(16*i), seed);+ }+ /* last bytes */+ acc_end = XXH3_mix16B(input + len - 16, secret + XXH3_SECRET_SIZE_MIN - XXH3_MIDSIZE_LASTOFFSET, seed);+ XXH_ASSERT(nbRounds >= 8);+ acc = XXH3_avalanche(acc);+#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++) {+ /*+ * Prevents clang for unrolling the acc loop and interleaving with this one.+ */+ XXH_COMPILER_GUARD(acc);+ acc_end += XXH3_mix16B(input+(16*i), secret+(16*(i-8)) + XXH3_MIDSIZE_STARTOFFSET, seed);+ }+ return XXH3_avalanche(acc + acc_end);+ }+}+++/* ======= 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++#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 */++/*+ * These macros are to generate an XXH3_accumulate() function.+ * The two arguments select the name suffix and target attribute.+ *+ * The name of this symbol is XXH3_accumulate_<name>() and it calls+ * XXH3_accumulate_512_<name>().+ *+ * It may be useful to hand implement this function if the compiler fails to+ * optimize the inline function.+ */+#define XXH3_ACCUMULATE_TEMPLATE(name) \+void \+XXH3_accumulate_##name(xxh_u64* XXH_RESTRICT acc, \+ const xxh_u8* XXH_RESTRICT input, \+ const xxh_u8* XXH_RESTRICT secret, \+ size_t nbStripes) \+{ \+ 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); \+ XXH3_accumulate_512_##name( \+ acc, \+ in, \+ secret + n*XXH_SECRET_CONSUME_RATE); \+ } \+}+++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_srli_epi64 (data_key, 32);+ /* 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);+ }+}+XXH_FORCE_INLINE XXH_TARGET_AVX512 XXH3_ACCUMULATE_TEMPLATE(avx512)++/*+ * 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);+ /* xacc[0] ^= secret; */+ __m512i const key_vec = _mm512_loadu_si512 (secret);+ __m512i const data_key = _mm512_ternarylogic_epi32(key_vec, acc_vec, shifted, 0x96 /* key_vec ^ acc_vec ^ shifted */);++ /* xacc[0] *= XXH_PRIME32_1; */+ __m512i const data_key_hi = _mm512_srli_epi64 (data_key, 32);+ __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_pos = _mm512_set1_epi64((xxh_i64)seed64);+ __m512i const seed = _mm512_mask_sub_epi64(seed_pos, 0xAA, _mm512_set1_epi8(0), seed_pos);++ 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) {+ dest[i] = _mm512_add_epi64(_mm512_load_si512(src + i), 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_srli_epi64 (data_key, 32);+ /* 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 XXH3_ACCUMULATE_TEMPLATE(avx2)++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_srli_epi64 (data_key, 32);+ __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_load_si256(src+0), seed);+ dest[1] = _mm256_add_epi64(_mm256_load_si256(src+1), seed);+ dest[2] = _mm256_add_epi64(_mm256_load_si256(src+2), seed);+ dest[3] = _mm256_add_epi64(_mm256_load_si256(src+3), seed);+ dest[4] = _mm256_add_epi64(_mm256_load_si256(src+4), seed);+ dest[5] = _mm256_add_epi64(_mm256_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 XXH3_ACCUMULATE_TEMPLATE(sse2)++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 and WASM SIMD128.+ *+ * 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.+ *+ * NEON's 32-bit to 64-bit long multiply takes a half vector of 32-bit+ * integers instead of the other platforms which mask full 64-bit vectors,+ * so the setup is more complicated than just shifting right.+ *+ * Additionally, there is an optimization for 4 lanes at once noted below.+ *+ * Since, as stated, the most optimal amount of lanes for Cortexes is 6,+ * there needs to be *three* versions of the accumulate operation used+ * for the remaining 2 lanes.+ *+ * WASM's SIMD128 uses SIMDe's arm_neon.h polyfill because the intrinsics overlap+ * nearly perfectly.+ */++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);+ { /* GCC for darwin arm64 does not like aliasing here */+ xxh_aliasing_uint64x2_t* const xacc = (xxh_aliasing_uint64x2_t*) acc;+ /* We don't use a uint32x4_t pointer because it causes bus errors on ARMv7. */+ uint8_t const* xinput = (const uint8_t *) input;+ uint8_t const* xsecret = (const uint8_t *) secret;++ size_t i;+#ifdef __wasm_simd128__+ /*+ * On WASM SIMD128, Clang emits direct address loads when XXH3_kSecret+ * is constant propagated, which results in it converting it to this+ * inside the loop:+ *+ * a = v128.load(XXH3_kSecret + 0 + $secret_offset, offset = 0)+ * b = v128.load(XXH3_kSecret + 16 + $secret_offset, offset = 0)+ * ...+ *+ * This requires a full 32-bit address immediate (and therefore a 6 byte+ * instruction) as well as an add for each offset.+ *+ * Putting an asm guard prevents it from folding (at the cost of losing+ * the alignment hint), and uses the free offset in `v128.load` instead+ * of adding secret_offset each time which overall reduces code size by+ * about a kilobyte and improves performance.+ */+ XXH_COMPILER_GUARD(xsecret);+#endif+ /* Scalar lanes use the normal scalarRound routine */+ for (i = XXH3_NEON_LANES; i < XXH_ACC_NB; i++) {+ XXH3_scalarRound(acc, input, secret, i);+ }+ i = 0;+ /* 4 NEON lanes at a time. */+ for (; i+1 < XXH3_NEON_LANES / 2; i+=2) {+ /* data_vec = xinput[i]; */+ uint64x2_t data_vec_1 = XXH_vld1q_u64(xinput + (i * 16));+ uint64x2_t data_vec_2 = XXH_vld1q_u64(xinput + ((i+1) * 16));+ /* key_vec = xsecret[i]; */+ uint64x2_t key_vec_1 = XXH_vld1q_u64(xsecret + (i * 16));+ uint64x2_t key_vec_2 = XXH_vld1q_u64(xsecret + ((i+1) * 16));+ /* data_swap = swap(data_vec) */+ uint64x2_t data_swap_1 = vextq_u64(data_vec_1, data_vec_1, 1);+ uint64x2_t data_swap_2 = vextq_u64(data_vec_2, data_vec_2, 1);+ /* data_key = data_vec ^ key_vec; */+ uint64x2_t data_key_1 = veorq_u64(data_vec_1, key_vec_1);+ uint64x2_t data_key_2 = veorq_u64(data_vec_2, key_vec_2);++ /*+ * If we reinterpret the 64x2 vectors as 32x4 vectors, we can use a+ * de-interleave operation for 4 lanes in 1 step with `vuzpq_u32` to+ * get one vector with the low 32 bits of each lane, and one vector+ * with the high 32 bits of each lane.+ *+ * The intrinsic returns a double vector because the original ARMv7-a+ * instruction modified both arguments in place. AArch64 and SIMD128 emit+ * two instructions from this intrinsic.+ *+ * [ dk11L | dk11H | dk12L | dk12H ] -> [ dk11L | dk12L | dk21L | dk22L ]+ * [ dk21L | dk21H | dk22L | dk22H ] -> [ dk11H | dk12H | dk21H | dk22H ]+ */+ uint32x4x2_t unzipped = vuzpq_u32(+ vreinterpretq_u32_u64(data_key_1),+ vreinterpretq_u32_u64(data_key_2)+ );+ /* data_key_lo = data_key & 0xFFFFFFFF */+ uint32x4_t data_key_lo = unzipped.val[0];+ /* data_key_hi = data_key >> 32 */+ uint32x4_t data_key_hi = unzipped.val[1];+ /*+ * Then, we can split the vectors horizontally and multiply which, as for most+ * widening intrinsics, have a variant that works on both high half vectors+ * for free on AArch64. A similar instruction is available on SIMD128.+ *+ * sum = data_swap + (u64x2) data_key_lo * (u64x2) data_key_hi+ */+ uint64x2_t sum_1 = XXH_vmlal_low_u32(data_swap_1, data_key_lo, data_key_hi);+ uint64x2_t sum_2 = XXH_vmlal_high_u32(data_swap_2, data_key_lo, data_key_hi);+ /*+ * Clang reorders+ * a += b * c; // umlal swap.2d, dkl.2s, dkh.2s+ * c += a; // add acc.2d, acc.2d, swap.2d+ * to+ * c += a; // add acc.2d, acc.2d, swap.2d+ * c += b * c; // umlal acc.2d, dkl.2s, dkh.2s+ *+ * While it would make sense in theory since the addition is faster,+ * for reasons likely related to umlal being limited to certain NEON+ * pipelines, this is worse. A compiler guard fixes this.+ */+ XXH_COMPILER_GUARD_CLANG_NEON(sum_1);+ XXH_COMPILER_GUARD_CLANG_NEON(sum_2);+ /* xacc[i] = acc_vec + sum; */+ xacc[i] = vaddq_u64(xacc[i], sum_1);+ xacc[i+1] = vaddq_u64(xacc[i+1], sum_2);+ }+ /* Operate on the remaining NEON lanes 2 at a time. */+ for (; i < XXH3_NEON_LANES / 2; i++) {+ /* data_vec = xinput[i]; */+ uint64x2_t data_vec = XXH_vld1q_u64(xinput + (i * 16));+ /* key_vec = xsecret[i]; */+ uint64x2_t key_vec = XXH_vld1q_u64(xsecret + (i * 16));+ /* acc_vec_2 = swap(data_vec) */+ uint64x2_t data_swap = vextq_u64(data_vec, data_vec, 1);+ /* data_key = data_vec ^ key_vec; */+ uint64x2_t data_key = veorq_u64(data_vec, key_vec);+ /* For two lanes, just use VMOVN and VSHRN. */+ /* data_key_lo = data_key & 0xFFFFFFFF; */+ uint32x2_t data_key_lo = vmovn_u64(data_key);+ /* data_key_hi = data_key >> 32; */+ uint32x2_t data_key_hi = vshrn_n_u64(data_key, 32);+ /* sum = data_swap + (u64x2) data_key_lo * (u64x2) data_key_hi; */+ uint64x2_t sum = vmlal_u32(data_swap, data_key_lo, data_key_hi);+ /* Same Clang workaround as before */+ XXH_COMPILER_GUARD_CLANG_NEON(sum);+ /* xacc[i] = acc_vec + sum; */+ xacc[i] = vaddq_u64 (xacc[i], sum);+ }+ }+}+XXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(neon)++XXH_FORCE_INLINE void+XXH3_scrambleAcc_neon(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret)+{+ XXH_ASSERT((((size_t)acc) & 15) == 0);++ { xxh_aliasing_uint64x2_t* xacc = (xxh_aliasing_uint64x2_t*) acc;+ uint8_t const* xsecret = (uint8_t const*) secret;++ size_t i;+ /* WASM uses operator overloads and doesn't need these. */+#ifndef __wasm_simd128__+ /* { prime32_1, prime32_1 } */+ uint32x2_t const kPrimeLo = vdup_n_u32(XXH_PRIME32_1);+ /* { 0, prime32_1, 0, prime32_1 } */+ uint32x4_t const kPrimeHi = vreinterpretq_u32_u64(vdupq_n_u64((xxh_u64)XXH_PRIME32_1 << 32));+#endif++ /* AArch64 uses both scalar and neon at the same time */+ for (i = XXH3_NEON_LANES; i < XXH_ACC_NB; i++) {+ XXH3_scalarScrambleRound(acc, secret, i);+ }+ 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]; */+ uint64x2_t key_vec = XXH_vld1q_u64(xsecret + (i * 16));+ uint64x2_t data_key = veorq_u64(data_vec, key_vec);+ /* xacc[i] *= XXH_PRIME32_1 */+#ifdef __wasm_simd128__+ /* SIMD128 has multiply by u64x2, use it instead of expanding and scalarizing */+ xacc[i] = data_key * XXH_PRIME32_1;+#else+ /*+ * Expanded version with portable NEON intrinsics+ *+ * lo(x) * lo(y) + (hi(x) * lo(y) << 32)+ *+ * prod_hi = hi(data_key) * lo(prime) << 32+ *+ * Since we only need 32 bits of this multiply a trick can be used, reinterpreting the vector+ * as a uint32x4_t and multiplying by { 0, prime, 0, prime } to cancel out the unwanted bits+ * and avoid the shift.+ */+ uint32x4_t prod_hi = vmulq_u32 (vreinterpretq_u32_u64(data_key), kPrimeHi);+ /* Extract low bits for vmlal_u32 */+ uint32x2_t data_key_lo = vmovn_u64(data_key);+ /* xacc[i] = prod_hi + lo(data_key) * XXH_PRIME32_1; */+ xacc[i] = vmlal_u32(vreinterpretq_u64_u32(prod_hi), data_key_lo, kPrimeLo);+#endif+ }+ }+}+#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 */+ xxh_aliasing_u64x2* const xacc = (xxh_aliasing_u64x2*) acc;+ xxh_u8 const* const xinput = (xxh_u8 const*) input; /* no alignment restriction */+ xxh_u8 const* const xsecret = (xxh_u8 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 + 16*i);+ /* key_vec = xsecret[i]; */+ xxh_u64x2 const key_vec = XXH_vec_loadu(xsecret + 16*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 = xacc[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;+ }+}+XXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(vsx)++XXH_FORCE_INLINE void+XXH3_scrambleAcc_vsx(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret)+{+ XXH_ASSERT((((size_t)acc) & 15) == 0);++ { xxh_aliasing_u64x2* const xacc = (xxh_aliasing_u64x2*) acc;+ const xxh_u8* const xsecret = (const xxh_u8*) 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 + 16*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++#if (XXH_VECTOR == XXH_SVE)++XXH_FORCE_INLINE void+XXH3_accumulate_512_sve( void* XXH_RESTRICT acc,+ const void* XXH_RESTRICT input,+ const void* XXH_RESTRICT secret)+{+ uint64_t *xacc = (uint64_t *)acc;+ const uint64_t *xinput = (const uint64_t *)(const void *)input;+ const uint64_t *xsecret = (const uint64_t *)(const void *)secret;+ svuint64_t kSwap = sveor_n_u64_z(svptrue_b64(), svindex_u64(0, 1), 1);+ uint64_t element_count = svcntd();+ if (element_count >= 8) {+ svbool_t mask = svptrue_pat_b64(SV_VL8);+ svuint64_t vacc = svld1_u64(mask, xacc);+ ACCRND(vacc, 0);+ svst1_u64(mask, xacc, vacc);+ } else if (element_count == 2) { /* sve128 */+ svbool_t mask = svptrue_pat_b64(SV_VL2);+ svuint64_t acc0 = svld1_u64(mask, xacc + 0);+ svuint64_t acc1 = svld1_u64(mask, xacc + 2);+ svuint64_t acc2 = svld1_u64(mask, xacc + 4);+ svuint64_t acc3 = svld1_u64(mask, xacc + 6);+ ACCRND(acc0, 0);+ ACCRND(acc1, 2);+ ACCRND(acc2, 4);+ ACCRND(acc3, 6);+ svst1_u64(mask, xacc + 0, acc0);+ svst1_u64(mask, xacc + 2, acc1);+ svst1_u64(mask, xacc + 4, acc2);+ svst1_u64(mask, xacc + 6, acc3);+ } else {+ svbool_t mask = svptrue_pat_b64(SV_VL4);+ svuint64_t acc0 = svld1_u64(mask, xacc + 0);+ svuint64_t acc1 = svld1_u64(mask, xacc + 4);+ ACCRND(acc0, 0);+ ACCRND(acc1, 4);+ svst1_u64(mask, xacc + 0, acc0);+ svst1_u64(mask, xacc + 4, acc1);+ }+}++XXH_FORCE_INLINE void+XXH3_accumulate_sve(xxh_u64* XXH_RESTRICT acc,+ const xxh_u8* XXH_RESTRICT input,+ const xxh_u8* XXH_RESTRICT secret,+ size_t nbStripes)+{+ if (nbStripes != 0) {+ uint64_t *xacc = (uint64_t *)acc;+ const uint64_t *xinput = (const uint64_t *)(const void *)input;+ const uint64_t *xsecret = (const uint64_t *)(const void *)secret;+ svuint64_t kSwap = sveor_n_u64_z(svptrue_b64(), svindex_u64(0, 1), 1);+ uint64_t element_count = svcntd();+ if (element_count >= 8) {+ svbool_t mask = svptrue_pat_b64(SV_VL8);+ svuint64_t vacc = svld1_u64(mask, xacc + 0);+ do {+ /* svprfd(svbool_t, void *, enum svfprop); */+ svprfd(mask, xinput + 128, SV_PLDL1STRM);+ ACCRND(vacc, 0);+ xinput += 8;+ xsecret += 1;+ nbStripes--;+ } while (nbStripes != 0);++ svst1_u64(mask, xacc + 0, vacc);+ } else if (element_count == 2) { /* sve128 */+ svbool_t mask = svptrue_pat_b64(SV_VL2);+ svuint64_t acc0 = svld1_u64(mask, xacc + 0);+ svuint64_t acc1 = svld1_u64(mask, xacc + 2);+ svuint64_t acc2 = svld1_u64(mask, xacc + 4);+ svuint64_t acc3 = svld1_u64(mask, xacc + 6);+ do {+ svprfd(mask, xinput + 128, SV_PLDL1STRM);+ ACCRND(acc0, 0);+ ACCRND(acc1, 2);+ ACCRND(acc2, 4);+ ACCRND(acc3, 6);+ xinput += 8;+ xsecret += 1;+ nbStripes--;+ } while (nbStripes != 0);++ svst1_u64(mask, xacc + 0, acc0);+ svst1_u64(mask, xacc + 2, acc1);+ svst1_u64(mask, xacc + 4, acc2);+ svst1_u64(mask, xacc + 6, acc3);+ } else {+ svbool_t mask = svptrue_pat_b64(SV_VL4);+ svuint64_t acc0 = svld1_u64(mask, xacc + 0);+ svuint64_t acc1 = svld1_u64(mask, xacc + 4);+ do {+ svprfd(mask, xinput + 128, SV_PLDL1STRM);+ ACCRND(acc0, 0);+ ACCRND(acc1, 4);+ xinput += 8;+ xsecret += 1;+ nbStripes--;+ } while (nbStripes != 0);++ svst1_u64(mask, xacc + 0, acc0);+ svst1_u64(mask, xacc + 4, acc1);+ }+ }+}++#endif++/* scalar variants - universal */++#if defined(__aarch64__) && (defined(__GNUC__) || defined(__clang__))+/*+ * In XXH3_scalarRound(), GCC and Clang have a similar codegen issue, where they+ * emit an excess mask and a full 64-bit multiply-add (MADD X-form).+ *+ * While this might not seem like much, as AArch64 is a 64-bit architecture, only+ * big Cortex designs have a full 64-bit multiplier.+ *+ * On the little cores, the smaller 32-bit multiplier is used, and full 64-bit+ * multiplies expand to 2-3 multiplies in microcode. This has a major penalty+ * of up to 4 latency cycles and 2 stall cycles in the multiply pipeline.+ *+ * Thankfully, AArch64 still provides the 32-bit long multiply-add (UMADDL) which does+ * not have this penalty and does the mask automatically.+ */+XXH_FORCE_INLINE xxh_u64+XXH_mult32to64_add64(xxh_u64 lhs, xxh_u64 rhs, xxh_u64 acc)+{+ xxh_u64 ret;+ /* note: %x = 64-bit register, %w = 32-bit register */+ __asm__("umaddl %x0, %w1, %w2, %x3" : "=r" (ret) : "r" (lhs), "r" (rhs), "r" (acc));+ return ret;+}+#else+XXH_FORCE_INLINE xxh_u64+XXH_mult32to64_add64(xxh_u64 lhs, xxh_u64 rhs, xxh_u64 acc)+{+ return XXH_mult32to64((xxh_u32)lhs, (xxh_u32)rhs) + acc;+}+#endif++/*!+ * @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_add64(data_key /* & 0xFFFFFFFF */, data_key >> 32, xacc[lane]);+ }+}++/*!+ * @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;+ /* ARM GCC refuses to unroll this loop, resulting in a 24% slowdown on ARMv6. */+#if defined(__GNUC__) && !defined(__clang__) \+ && (defined(__arm__) || defined(__thumb2__)) \+ && defined(__ARM_FEATURE_UNALIGNED) /* no unaligned access just wastes bytes */ \+ && XXH_SIZE_OPT <= 0+# pragma GCC unroll 8+#endif+ for (i=0; i < XXH_ACC_NB; i++) {+ XXH3_scalarRound(acc, input, secret, i);+ }+}+XXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(scalar)++/*!+ * @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);+ }+}++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(__GNUC__) && defined(__aarch64__)+ /*+ * UGLY HACK:+ * GCC and Clang generate 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 the compiler 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+ { int const nbRounds = XXH_SECRET_DEFAULT_SIZE / 16;+ int i;+ for (i=0; i < nbRounds; i++) {+ /*+ * The asm hack causes the compiler 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)(xxh_u64* XXH_RESTRICT, const xxh_u8* XXH_RESTRICT, const xxh_u8* XXH_RESTRICT, size_t);+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_accumulate XXH3_accumulate_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_accumulate XXH3_accumulate_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_accumulate XXH3_accumulate_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_accumulate XXH3_accumulate_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_accumulate XXH3_accumulate_vsx+#define XXH3_scrambleAcc XXH3_scrambleAcc_vsx+#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar++#elif (XXH_VECTOR == XXH_SVE)+#define XXH3_accumulate_512 XXH3_accumulate_512_sve+#define XXH3_accumulate XXH3_accumulate_sve+#define XXH3_scrambleAcc XXH3_scrambleAcc_scalar+#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar++#else /* scalar */++#define XXH3_accumulate_512 XXH3_accumulate_512_scalar+#define XXH3_accumulate XXH3_accumulate_scalar+#define XXH3_scrambleAcc XXH3_scrambleAcc_scalar+#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar++#endif++#if XXH_SIZE_OPT >= 1 /* don't do SIMD for initialization */+# undef XXH3_initCustomSecret+# define XXH3_initCustomSecret XXH3_initCustomSecret_scalar+#endif++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 f_acc,+ 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++) {+ f_acc(acc, input + n*block_len, secret, nbStripesPerBlock);+ 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));+ f_acc(acc, input + nb_blocks*block_len, secret, nbStripes);++ /* 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 */+ XXH3_accumulate_512(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 f_acc,+ 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_acc, 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.+ * When the secret size is unknown, or on GCC 12 where the mix of NO_INLINE and FORCE_INLINE+ * breaks -Og, this is XXH_NO_INLINE.+ */+XXH3_WITH_SECRET_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, 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 XXH_PUREF 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, 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 f_acc,+ XXH3_f_scrambleAcc f_scramble,+ XXH3_f_initCustomSecret f_initSec)+{+#if XXH_SIZE_OPT <= 0+ if (seed == 0)+ return XXH3_hashLong_64b_internal(input, len,+ XXH3_kSecret, sizeof(XXH3_kSecret),+ f_acc, f_scramble);+#endif+ { 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_acc, 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* XXH_RESTRICT input, size_t len,+ XXH64_hash_t seed, const xxh_u8* XXH_RESTRICT secret, size_t secretLen)+{+ (void)secret; (void)secretLen;+ return XXH3_hashLong_64b_withSeed_internal(input, len, seed,+ XXH3_accumulate, 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(XXH_NOESCAPE const void* input, size_t length)+{+ return XXH3_64bits_internal(input, length, 0, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_default);+}++/*! @ingroup XXH3_family */+XXH_PUBLIC_API XXH64_hash_t+XXH3_64bits_withSecret(XXH_NOESCAPE const void* input, size_t length, XXH_NOESCAPE const void* secret, size_t secretSize)+{+ return XXH3_64bits_internal(input, length, 0, secret, secretSize, XXH3_hashLong_64b_withSecret);+}++/*! @ingroup XXH3_family */+XXH_PUBLIC_API XXH64_hash_t+XXH3_64bits_withSeed(XXH_NOESCAPE const void* input, size_t length, XXH64_hash_t seed)+{+ return XXH3_64bits_internal(input, length, seed, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_withSeed);+}++XXH_PUBLIC_API XXH64_hash_t+XXH3_64bits_withSecretandSeed(XXH_NOESCAPE const void* input, size_t length, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed)+{+ if (length <= XXH3_MIDSIZE_MAX)+ return XXH3_64bits_internal(input, length, seed, XXH3_kSecret, sizeof(XXH3_kSecret), NULL);+ return XXH3_hashLong_64b_withSecret(input, length, seed, (const xxh_u8*)secret, secretSize);+}+++/* === XXH3 streaming === */+#ifndef XXH_NO_STREAM+/*+ * 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 XXH_MALLOCF 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 */+/*!+ * @brief Allocate an @ref XXH3_state_t.+ *+ * Must be freed with XXH3_freeState().+ * @return An allocated XXH3_state_t on success, `NULL` on failure.+ */+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 */+/*!+ * @brief Frees an @ref XXH3_state_t.+ *+ * Must be allocated with XXH3_createState().+ * @param statePtr A pointer to an @ref XXH3_state_t allocated with @ref XXH3_createState().+ * @return XXH_OK.+ */+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(XXH_NOESCAPE XXH3_state_t* dst_state, XXH_NOESCAPE 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(XXH_NOESCAPE 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(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE 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(XXH_NOESCAPE 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(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE 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;+}++/*!+ * @internal+ * @brief Processes a large input for XXH3_update() and XXH3_digest_long().+ *+ * Unlike XXH3_hashLong_internal_loop(), this can process data that overlaps a block.+ *+ * @param acc Pointer to the 8 accumulator lanes+ * @param nbStripesSoFarPtr In/out pointer to the number of leftover stripes in the block*+ * @param nbStripesPerBlock Number of stripes in a block+ * @param input Input pointer+ * @param nbStripes Number of stripes to process+ * @param secret Secret pointer+ * @param secretLimit Offset of the last block in @p secret+ * @param f_acc Pointer to an XXH3_accumulate implementation+ * @param f_scramble Pointer to an XXH3_scrambleAcc implementation+ * @return Pointer past the end of @p input after processing+ */+XXH_FORCE_INLINE const xxh_u8 *+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 f_acc,+ XXH3_f_scrambleAcc f_scramble)+{+ const xxh_u8* initialSecret = secret + *nbStripesSoFarPtr * XXH_SECRET_CONSUME_RATE;+ /* Process full blocks */+ if (nbStripes >= (nbStripesPerBlock - *nbStripesSoFarPtr)) {+ /* Process the initial partial block... */+ size_t nbStripesThisIter = nbStripesPerBlock - *nbStripesSoFarPtr;++ do {+ /* Accumulate and scramble */+ f_acc(acc, input, initialSecret, nbStripesThisIter);+ f_scramble(acc, secret + secretLimit);+ input += nbStripesThisIter * XXH_STRIPE_LEN;+ nbStripes -= nbStripesThisIter;+ /* Then continue the loop with the full block size */+ nbStripesThisIter = nbStripesPerBlock;+ initialSecret = secret;+ } while (nbStripes >= nbStripesPerBlock);+ *nbStripesSoFarPtr = 0;+ }+ /* Process a partial block */+ if (nbStripes > 0) {+ f_acc(acc, input, initialSecret, nbStripes);+ input += nbStripes * XXH_STRIPE_LEN;+ *nbStripesSoFarPtr += nbStripes;+ }+ /* Return end pointer */+ return input;+}++#ifndef XXH3_STREAM_USE_STACK+# if XXH_SIZE_OPT <= 0 && !defined(__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 f_acc,+ 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];+ XXH_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 (len <= XXH3_INTERNALBUFFER_SIZE - state->bufferedSize) {+ 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_acc, f_scramble);+ state->bufferedSize = 0;+ }+ XXH_ASSERT(input < bEnd);+ if (bEnd - input > XXH3_INTERNALBUFFER_SIZE) {+ size_t nbStripes = (size_t)(bEnd - 1 - input) / XXH_STRIPE_LEN;+ input = XXH3_consumeStripes(acc,+ &state->nbStripesSoFar, state->nbStripesPerBlock,+ input, nbStripes,+ secret, state->secretLimit,+ f_acc, f_scramble);+ 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 */+ XXH_memcpy(state->acc, acc, sizeof(acc));+#endif+ }++ return XXH_OK;+}++/*! @ingroup XXH3_family */+XXH_PUBLIC_API XXH_errorcode+XXH3_64bits_update(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len)+{+ return XXH3_update(state, (const xxh_u8*)input, len,+ XXH3_accumulate, XXH3_scrambleAcc);+}+++XXH_FORCE_INLINE void+XXH3_digest_long (XXH64_hash_t* acc,+ const XXH3_state_t* state,+ const unsigned char* secret)+{+ xxh_u8 lastStripe[XXH_STRIPE_LEN];+ const xxh_u8* lastStripePtr;++ /*+ * 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) {+ /* Consume remaining stripes then point to remaining data in buffer */+ 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, XXH3_scrambleAcc);+ lastStripePtr = state->buffer + state->bufferedSize - XXH_STRIPE_LEN;+ } else { /* bufferedSize < XXH_STRIPE_LEN */+ /* Copy to temp buffer */+ 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);+ lastStripePtr = lastStripe;+ }+ /* Last stripe */+ XXH3_accumulate_512(acc,+ lastStripePtr,+ secret + state->secretLimit - XXH_SECRET_LASTACC_START);+}++/*! @ingroup XXH3_family */+XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_digest (XXH_NOESCAPE 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);+}+#endif /* !XXH_NO_STREAM */+++/* ==========================================+ * 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 XXH_PUREF 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 XXH_PUREF 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 *= PRIME_MX2;+ m128.low64 = XXH_xorshift64(m128.low64, 28);+ m128.high64 = XXH3_avalanche(m128.high64);+ return m128;+ }+}++XXH_FORCE_INLINE XXH_PUREF 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 XXH_PUREF 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 XXH_PUREF 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 XXH_SIZE_OPT >= 1+ {+ /* Smaller, but slightly slower. */+ unsigned int i = (unsigned int)(len - 1) / 32;+ do {+ acc = XXH128_mix32B(acc, input+16*i, input+len-16*(i+1), secret+32*i, seed);+ } while (i-- != 0);+ }+#else+ 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);+#endif+ { 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 XXH_PUREF 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;+ unsigned i;+ acc.low64 = len * XXH_PRIME64_1;+ acc.high64 = 0;+ /*+ * We set as `i` as offset + 32. We do this so that unchanged+ * `len` can be used as upper bound. This reaches a sweet spot+ * where both x86 and aarch64 get simple agen and good codegen+ * for the loop.+ */+ for (i = 32; i < 160; i += 32) {+ acc = XXH128_mix32B(acc,+ input + i - 32,+ input + i - 16,+ secret + i - 32,+ seed);+ }+ acc.low64 = XXH3_avalanche(acc.low64);+ acc.high64 = XXH3_avalanche(acc.high64);+ /*+ * NB: `i <= len` will duplicate the last 32-bytes if+ * len % 32 was zero. This is an unfortunate necessity to keep+ * the hash result stable.+ */+ for (i=160; i <= len; i += 32) {+ acc = XXH128_mix32B(acc,+ input + i - 32,+ input + i - 16,+ secret + XXH3_MIDSIZE_STARTOFFSET + i - 160,+ seed);+ }+ /* last bytes */+ acc = XXH128_mix32B(acc,+ input + len - 16,+ input + len - 32,+ secret + XXH3_SECRET_SIZE_MIN - XXH3_MIDSIZE_LASTOFFSET - 16,+ (XXH64_hash_t)0 - 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 f_acc,+ 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_acc, 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 XXH_PUREF 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, XXH3_scrambleAcc);+}++/*+ * It's important for performance to pass @p secretLen (when it's static)+ * to the compiler, so that it can properly optimize the vectorized loop.+ *+ * When the secret size is unknown, or on GCC 12 where the mix of NO_INLINE and FORCE_INLINE+ * breaks -Og, this is XXH_NO_INLINE.+ */+XXH3_WITH_SECRET_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, 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 f_acc,+ 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_acc, 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_acc, 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, 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(XXH_NOESCAPE 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(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE 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(XXH_NOESCAPE 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(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE 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(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed)+{+ return XXH3_128bits_withSeed(input, len, seed);+}+++/* === XXH3 128-bit streaming === */+#ifndef XXH_NO_STREAM+/*+ * 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(XXH_NOESCAPE XXH3_state_t* statePtr)+{+ return XXH3_64bits_reset(statePtr);+}++/*! @ingroup XXH3_family */+XXH_PUBLIC_API XXH_errorcode+XXH3_128bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE 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(XXH_NOESCAPE 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(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE 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(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len)+{+ return XXH3_64bits_update(state, input, len);+}++/*! @ingroup XXH3_family */+XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_digest (XXH_NOESCAPE 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);+}+#endif /* !XXH_NO_STREAM */+/* 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(XXH_NOESCAPE const void* h128_1, XXH_NOESCAPE 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(XXH_NOESCAPE 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(XXH_NOESCAPE 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(XXH_NOESCAPE void* secretBuffer, size_t secretSize, XXH_NOESCAPE 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(XXH_NOESCAPE 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__) && XXH_SIZE_OPT <= 0 /* respect -O0 and -Os */+# pragma GCC pop_options+#endif++#endif /* XXH_NO_LONG_LONG */++#endif /* XXH_NO_XXH3 */++/*!+ * @}+ */+#endif /* XXH_IMPLEMENTATION */+++#if defined (__cplusplus)+} /* extern "C" */+#endif
+ cbits/xkcp/KeccakHash.c view
@@ -0,0 +1,81 @@+/*+The eXtended Keccak Code Package (XKCP)+https://github.com/XKCP/XKCP++Keccak, designed by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche.++Implementation by the designers, hereby denoted as "the implementer".++For more information, feedback or questions, please refer to the Keccak Team website:+https://keccak.team/++To the extent possible under law, the implementer has waived all copyright+and related or neighboring rights to the source code in this file.+http://creativecommons.org/publicdomain/zero/1.0/+*/++#include <string.h>+#include "KeccakHash.h"++/* ---------------------------------------------------------------- */++HashReturn Keccak_HashInitialize(Keccak_HashInstance *instance, unsigned int rate, unsigned int capacity, unsigned int hashbitlen, unsigned char delimitedSuffix)+{+ HashReturn result;++ if (delimitedSuffix == 0)+ return KECCAK_FAIL;+ result = (HashReturn)KeccakWidth1600_SpongeInitialize(&instance->sponge, rate, capacity);+ if (result != KECCAK_SUCCESS)+ return result;+ instance->fixedOutputLength = hashbitlen;+ instance->delimitedSuffix = delimitedSuffix;+ return KECCAK_SUCCESS;+}++/* ---------------------------------------------------------------- */++HashReturn Keccak_HashUpdate(Keccak_HashInstance *instance, const BitSequence *data, BitLength databitlen)+{+ if ((databitlen % 8) == 0)+ return (HashReturn)KeccakWidth1600_SpongeAbsorb(&instance->sponge, data, databitlen/8);+ else {+ HashReturn ret = (HashReturn)KeccakWidth1600_SpongeAbsorb(&instance->sponge, data, databitlen/8);+ if (ret == KECCAK_SUCCESS) {+ /* The last partial byte is assumed to be aligned on the least significant bits */+ unsigned char lastByte = data[databitlen/8];+ /* Concatenate the last few bits provided here with those of the suffix */+ unsigned short delimitedLastBytes = (unsigned short)((unsigned short)(lastByte & ((1 << (databitlen % 8)) - 1)) | ((unsigned short)instance->delimitedSuffix << (databitlen % 8)));+ if ((delimitedLastBytes & 0xFF00) == 0x0000) {+ instance->delimitedSuffix = delimitedLastBytes & 0xFF;+ }+ else {+ unsigned char oneByte[1];+ oneByte[0] = delimitedLastBytes & 0xFF;+ ret = (HashReturn)KeccakWidth1600_SpongeAbsorb(&instance->sponge, oneByte, 1);+ instance->delimitedSuffix = (delimitedLastBytes >> 8) & 0xFF;+ }+ }+ return ret;+ }+}++/* ---------------------------------------------------------------- */++HashReturn Keccak_HashFinal(Keccak_HashInstance *instance, BitSequence *hashval)+{+ HashReturn ret = (HashReturn)KeccakWidth1600_SpongeAbsorbLastFewBits(&instance->sponge, instance->delimitedSuffix);+ if (ret == KECCAK_SUCCESS)+ return (HashReturn)KeccakWidth1600_SpongeSqueeze(&instance->sponge, hashval, instance->fixedOutputLength/8);+ else+ return ret;+}++/* ---------------------------------------------------------------- */++HashReturn Keccak_HashSqueeze(Keccak_HashInstance *instance, BitSequence *data, BitLength databitlen)+{+ if ((databitlen % 8) != 0)+ return KECCAK_FAIL;+ return (HashReturn)KeccakWidth1600_SpongeSqueeze(&instance->sponge, data, databitlen/8);+}
+ cbits/xkcp/KeccakHash.h view
@@ -0,0 +1,125 @@+/*+The eXtended Keccak Code Package (XKCP)+https://github.com/XKCP/XKCP++Keccak, designed by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche.++Implementation by the designers, hereby denoted as "the implementer".++For more information, feedback or questions, please refer to the Keccak Team website:+https://keccak.team/++To the extent possible under law, the implementer has waived all copyright+and related or neighboring rights to the source code in this file.+http://creativecommons.org/publicdomain/zero/1.0/+*/++#ifndef _KeccakHashInterface_h_+#define _KeccakHashInterface_h_++#include "config.h"+#ifdef XKCP_has_KeccakP1600++#include <stdint.h>+#include <string.h>+#include "KeccakSponge.h"++#ifndef _Keccak_BitTypes_+#define _Keccak_BitTypes_+typedef uint8_t BitSequence;++typedef size_t BitLength;+#endif++typedef enum { KECCAK_SUCCESS = 0, KECCAK_FAIL = 1, KECCAK_BAD_HASHLEN = 2 } HashReturn;++typedef struct {+ KeccakWidth1600_SpongeInstance sponge;+ unsigned int fixedOutputLength;+ unsigned char delimitedSuffix;+} Keccak_HashInstance;++/**+ * Function to initialize the Keccak[r, c] sponge function instance used in sequential hashing mode.+ * @param hashInstance Pointer to the hash instance to be initialized.+ * @param rate The value of the rate r.+ * @param capacity The value of the capacity c.+ * @param hashbitlen The desired number of output bits,+ * or 0 for an arbitrarily-long output.+ * @param delimitedSuffix Bits that will be automatically appended to the end+ * of the input message, as in domain separation.+ * This is a byte containing from 0 to 7 bits+ * formatted like the @a delimitedData parameter of+ * the Keccak_SpongeAbsorbLastFewBits() function.+ * @pre One must have r+c=1600 and the rate a multiple of 8 bits in this implementation.+ * @return KECCAK_SUCCESS if successful, KECCAK_FAIL otherwise.+ */+HashReturn Keccak_HashInitialize(Keccak_HashInstance *hashInstance, unsigned int rate, unsigned int capacity, unsigned int hashbitlen, unsigned char delimitedSuffix);++/** Macro to initialize a SHAKE128 instance as specified in the FIPS 202 standard.+ */+#define Keccak_HashInitialize_SHAKE128(hashInstance) Keccak_HashInitialize(hashInstance, 1344, 256, 0, 0x1F)++/** Macro to initialize a SHAKE256 instance as specified in the FIPS 202 standard.+ */+#define Keccak_HashInitialize_SHAKE256(hashInstance) Keccak_HashInitialize(hashInstance, 1088, 512, 0, 0x1F)++/** Macro to initialize a SHA3-224 instance as specified in the FIPS 202 standard.+ */+#define Keccak_HashInitialize_SHA3_224(hashInstance) Keccak_HashInitialize(hashInstance, 1152, 448, 224, 0x06)++/** Macro to initialize a SHA3-256 instance as specified in the FIPS 202 standard.+ */+#define Keccak_HashInitialize_SHA3_256(hashInstance) Keccak_HashInitialize(hashInstance, 1088, 512, 256, 0x06)++/** Macro to initialize a SHA3-384 instance as specified in the FIPS 202 standard.+ */+#define Keccak_HashInitialize_SHA3_384(hashInstance) Keccak_HashInitialize(hashInstance, 832, 768, 384, 0x06)++/** Macro to initialize a SHA3-512 instance as specified in the FIPS 202 standard.+ */+#define Keccak_HashInitialize_SHA3_512(hashInstance) Keccak_HashInitialize(hashInstance, 576, 1024, 512, 0x06)++/**+ * Function to give input data to be absorbed.+ * @param hashInstance Pointer to the hash instance initialized by Keccak_HashInitialize().+ * @param data Pointer to the input data.+ * When @a databitLen is not a multiple of 8, the last bits of data must be+ * in the least significant bits of the last byte (little-endian convention).+ * In this case, the (8 - @a databitLen mod 8) most significant bits+ * of the last byte are ignored.+ * @param databitLen The number of input bits provided in the input data.+ * @pre In the previous call to Keccak_HashUpdate(), databitlen was a multiple of 8.+ * @return KECCAK_SUCCESS if successful, KECCAK_FAIL otherwise.+ */+HashReturn Keccak_HashUpdate(Keccak_HashInstance *hashInstance, const BitSequence *data, BitLength databitlen);++/**+ * Function to call after all input blocks have been input and to get+ * output bits if the length was specified when calling Keccak_HashInitialize().+ * @param hashInstance Pointer to the hash instance initialized by Keccak_HashInitialize().+ * If @a hashbitlen was not 0 in the call to Keccak_HashInitialize(), the number of+ * output bits is equal to @a hashbitlen.+ * If @a hashbitlen was 0 in the call to Keccak_HashInitialize(), the output bits+ * must be extracted using the Keccak_HashSqueeze() function.+ * @param hashval Pointer to the buffer where to store the output data.+ * @return KECCAK_SUCCESS if successful, KECCAK_FAIL otherwise.+ */+HashReturn Keccak_HashFinal(Keccak_HashInstance *hashInstance, BitSequence *hashval);++ /**+ * Function to squeeze output data.+ * @param hashInstance Pointer to the hash instance initialized by Keccak_HashInitialize().+ * @param data Pointer to the buffer where to store the output data.+ * @param databitlen The number of output bits desired (must be a multiple of 8).+ * @pre Keccak_HashFinal() must have been already called.+ * @pre @a databitlen is a multiple of 8.+ * @return KECCAK_SUCCESS if successful, KECCAK_FAIL otherwise.+ */+HashReturn Keccak_HashSqueeze(Keccak_HashInstance *hashInstance, BitSequence *data, BitLength databitlen);++#else+#error This requires an implementation of Keccak-p[1600]+#endif++#endif
+ cbits/xkcp/KeccakP-1600-64.macros view
@@ -0,0 +1,748 @@+/*+The eXtended Keccak Code Package (XKCP)+https://github.com/XKCP/XKCP++The Keccak-p permutations, designed by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche.++Implementation by Gilles Van Assche and Ronny Van Keer, hereby denoted as "the implementer".++For more information, feedback or questions, please refer to the Keccak Team website:+https://keccak.team/++To the extent possible under law, the implementer has waived all copyright+and related or neighboring rights to the source code in this file.+http://creativecommons.org/publicdomain/zero/1.0/+*/++#define declareABCDE \+ uint64_t Aba, Abe, Abi, Abo, Abu; \+ uint64_t Aga, Age, Agi, Ago, Agu; \+ uint64_t Aka, Ake, Aki, Ako, Aku; \+ uint64_t Ama, Ame, Ami, Amo, Amu; \+ uint64_t Asa, Ase, Asi, Aso, Asu; \+ uint64_t Bba, Bbe, Bbi, Bbo, Bbu; \+ uint64_t Bga, Bge, Bgi, Bgo, Bgu; \+ uint64_t Bka, Bke, Bki, Bko, Bku; \+ uint64_t Bma, Bme, Bmi, Bmo, Bmu; \+ uint64_t Bsa, Bse, Bsi, Bso, Bsu; \+ uint64_t Ca, Ce, Ci, Co, Cu; \+ uint64_t Da, De, Di, Do, Du; \+ uint64_t Eba, Ebe, Ebi, Ebo, Ebu; \+ uint64_t Ega, Ege, Egi, Ego, Egu; \+ uint64_t Eka, Eke, Eki, Eko, Eku; \+ uint64_t Ema, Eme, Emi, Emo, Emu; \+ uint64_t Esa, Ese, Esi, Eso, Esu; \++#define prepareTheta \+ Ca = Aba^Aga^Aka^Ama^Asa; \+ Ce = Abe^Age^Ake^Ame^Ase; \+ Ci = Abi^Agi^Aki^Ami^Asi; \+ Co = Abo^Ago^Ako^Amo^Aso; \+ Cu = Abu^Agu^Aku^Amu^Asu; \++#ifdef UseBebigokimisa+/* --- Code for round, with prepare-theta (lane complementing pattern 'bebigokimisa') */+/* --- 64-bit lanes mapped to 64-bit words */+#define thetaRhoPiChiIotaPrepareTheta(i, A, E) \+ Da = Cu^ROL64(Ce, 1); \+ De = Ca^ROL64(Ci, 1); \+ Di = Ce^ROL64(Co, 1); \+ Do = Ci^ROL64(Cu, 1); \+ Du = Co^ROL64(Ca, 1); \+\+ A##ba ^= Da; \+ Bba = A##ba; \+ A##ge ^= De; \+ Bbe = ROL64(A##ge, 44); \+ A##ki ^= Di; \+ Bbi = ROL64(A##ki, 43); \+ A##mo ^= Do; \+ Bbo = ROL64(A##mo, 21); \+ A##su ^= Du; \+ Bbu = ROL64(A##su, 14); \+ E##ba = Bba ^( Bbe | Bbi ); \+ E##ba ^= KeccakF1600RoundConstants[i]; \+ Ca = E##ba; \+ E##be = Bbe ^((~Bbi)| Bbo ); \+ Ce = E##be; \+ E##bi = Bbi ^( Bbo & Bbu ); \+ Ci = E##bi; \+ E##bo = Bbo ^( Bbu | Bba ); \+ Co = E##bo; \+ E##bu = Bbu ^( Bba & Bbe ); \+ Cu = E##bu; \+\+ A##bo ^= Do; \+ Bga = ROL64(A##bo, 28); \+ A##gu ^= Du; \+ Bge = ROL64(A##gu, 20); \+ A##ka ^= Da; \+ Bgi = ROL64(A##ka, 3); \+ A##me ^= De; \+ Bgo = ROL64(A##me, 45); \+ A##si ^= Di; \+ Bgu = ROL64(A##si, 61); \+ E##ga = Bga ^( Bge | Bgi ); \+ Ca ^= E##ga; \+ E##ge = Bge ^( Bgi & Bgo ); \+ Ce ^= E##ge; \+ E##gi = Bgi ^( Bgo |(~Bgu)); \+ Ci ^= E##gi; \+ E##go = Bgo ^( Bgu | Bga ); \+ Co ^= E##go; \+ E##gu = Bgu ^( Bga & Bge ); \+ Cu ^= E##gu; \+\+ A##be ^= De; \+ Bka = ROL64(A##be, 1); \+ A##gi ^= Di; \+ Bke = ROL64(A##gi, 6); \+ A##ko ^= Do; \+ Bki = ROL64(A##ko, 25); \+ A##mu ^= Du; \+ Bko = ROL64(A##mu, 8); \+ A##sa ^= Da; \+ Bku = ROL64(A##sa, 18); \+ E##ka = Bka ^( Bke | Bki ); \+ Ca ^= E##ka; \+ E##ke = Bke ^( Bki & Bko ); \+ Ce ^= E##ke; \+ E##ki = Bki ^((~Bko)& Bku ); \+ Ci ^= E##ki; \+ E##ko = (~Bko)^( Bku | Bka ); \+ Co ^= E##ko; \+ E##ku = Bku ^( Bka & Bke ); \+ Cu ^= E##ku; \+\+ A##bu ^= Du; \+ Bma = ROL64(A##bu, 27); \+ A##ga ^= Da; \+ Bme = ROL64(A##ga, 36); \+ A##ke ^= De; \+ Bmi = ROL64(A##ke, 10); \+ A##mi ^= Di; \+ Bmo = ROL64(A##mi, 15); \+ A##so ^= Do; \+ Bmu = ROL64(A##so, 56); \+ E##ma = Bma ^( Bme & Bmi ); \+ Ca ^= E##ma; \+ E##me = Bme ^( Bmi | Bmo ); \+ Ce ^= E##me; \+ E##mi = Bmi ^((~Bmo)| Bmu ); \+ Ci ^= E##mi; \+ E##mo = (~Bmo)^( Bmu & Bma ); \+ Co ^= E##mo; \+ E##mu = Bmu ^( Bma | Bme ); \+ Cu ^= E##mu; \+\+ A##bi ^= Di; \+ Bsa = ROL64(A##bi, 62); \+ A##go ^= Do; \+ Bse = ROL64(A##go, 55); \+ A##ku ^= Du; \+ Bsi = ROL64(A##ku, 39); \+ A##ma ^= Da; \+ Bso = ROL64(A##ma, 41); \+ A##se ^= De; \+ Bsu = ROL64(A##se, 2); \+ E##sa = Bsa ^((~Bse)& Bsi ); \+ Ca ^= E##sa; \+ E##se = (~Bse)^( Bsi | Bso ); \+ Ce ^= E##se; \+ E##si = Bsi ^( Bso & Bsu ); \+ Ci ^= E##si; \+ E##so = Bso ^( Bsu | Bsa ); \+ Co ^= E##so; \+ E##su = Bsu ^( Bsa & Bse ); \+ Cu ^= E##su; \+\++/* --- Code for round (lane complementing pattern 'bebigokimisa') */+/* --- 64-bit lanes mapped to 64-bit words */+#define thetaRhoPiChiIota(i, A, E) \+ Da = Cu^ROL64(Ce, 1); \+ De = Ca^ROL64(Ci, 1); \+ Di = Ce^ROL64(Co, 1); \+ Do = Ci^ROL64(Cu, 1); \+ Du = Co^ROL64(Ca, 1); \+\+ A##ba ^= Da; \+ Bba = A##ba; \+ A##ge ^= De; \+ Bbe = ROL64(A##ge, 44); \+ A##ki ^= Di; \+ Bbi = ROL64(A##ki, 43); \+ A##mo ^= Do; \+ Bbo = ROL64(A##mo, 21); \+ A##su ^= Du; \+ Bbu = ROL64(A##su, 14); \+ E##ba = Bba ^( Bbe | Bbi ); \+ E##ba ^= KeccakF1600RoundConstants[i]; \+ E##be = Bbe ^((~Bbi)| Bbo ); \+ E##bi = Bbi ^( Bbo & Bbu ); \+ E##bo = Bbo ^( Bbu | Bba ); \+ E##bu = Bbu ^( Bba & Bbe ); \+\+ A##bo ^= Do; \+ Bga = ROL64(A##bo, 28); \+ A##gu ^= Du; \+ Bge = ROL64(A##gu, 20); \+ A##ka ^= Da; \+ Bgi = ROL64(A##ka, 3); \+ A##me ^= De; \+ Bgo = ROL64(A##me, 45); \+ A##si ^= Di; \+ Bgu = ROL64(A##si, 61); \+ E##ga = Bga ^( Bge | Bgi ); \+ E##ge = Bge ^( Bgi & Bgo ); \+ E##gi = Bgi ^( Bgo |(~Bgu)); \+ E##go = Bgo ^( Bgu | Bga ); \+ E##gu = Bgu ^( Bga & Bge ); \+\+ A##be ^= De; \+ Bka = ROL64(A##be, 1); \+ A##gi ^= Di; \+ Bke = ROL64(A##gi, 6); \+ A##ko ^= Do; \+ Bki = ROL64(A##ko, 25); \+ A##mu ^= Du; \+ Bko = ROL64(A##mu, 8); \+ A##sa ^= Da; \+ Bku = ROL64(A##sa, 18); \+ E##ka = Bka ^( Bke | Bki ); \+ E##ke = Bke ^( Bki & Bko ); \+ E##ki = Bki ^((~Bko)& Bku ); \+ E##ko = (~Bko)^( Bku | Bka ); \+ E##ku = Bku ^( Bka & Bke ); \+\+ A##bu ^= Du; \+ Bma = ROL64(A##bu, 27); \+ A##ga ^= Da; \+ Bme = ROL64(A##ga, 36); \+ A##ke ^= De; \+ Bmi = ROL64(A##ke, 10); \+ A##mi ^= Di; \+ Bmo = ROL64(A##mi, 15); \+ A##so ^= Do; \+ Bmu = ROL64(A##so, 56); \+ E##ma = Bma ^( Bme & Bmi ); \+ E##me = Bme ^( Bmi | Bmo ); \+ E##mi = Bmi ^((~Bmo)| Bmu ); \+ E##mo = (~Bmo)^( Bmu & Bma ); \+ E##mu = Bmu ^( Bma | Bme ); \+\+ A##bi ^= Di; \+ Bsa = ROL64(A##bi, 62); \+ A##go ^= Do; \+ Bse = ROL64(A##go, 55); \+ A##ku ^= Du; \+ Bsi = ROL64(A##ku, 39); \+ A##ma ^= Da; \+ Bso = ROL64(A##ma, 41); \+ A##se ^= De; \+ Bsu = ROL64(A##se, 2); \+ E##sa = Bsa ^((~Bse)& Bsi ); \+ E##se = (~Bse)^( Bsi | Bso ); \+ E##si = Bsi ^( Bso & Bsu ); \+ E##so = Bso ^( Bsu | Bsa ); \+ E##su = Bsu ^( Bsa & Bse ); \+\++#else /* UseBebigokimisa */+/* --- Code for round, with prepare-theta */+/* --- 64-bit lanes mapped to 64-bit words */+#define thetaRhoPiChiIotaPrepareTheta(i, A, E) \+ Da = Cu^ROL64(Ce, 1); \+ De = Ca^ROL64(Ci, 1); \+ Di = Ce^ROL64(Co, 1); \+ Do = Ci^ROL64(Cu, 1); \+ Du = Co^ROL64(Ca, 1); \+\+ A##ba ^= Da; \+ Bba = A##ba; \+ A##ge ^= De; \+ Bbe = ROL64(A##ge, 44); \+ A##ki ^= Di; \+ Bbi = ROL64(A##ki, 43); \+ A##mo ^= Do; \+ Bbo = ROL64(A##mo, 21); \+ A##su ^= Du; \+ Bbu = ROL64(A##su, 14); \+ E##ba = Bba ^((~Bbe)& Bbi ); \+ E##ba ^= KeccakF1600RoundConstants[i]; \+ Ca = E##ba; \+ E##be = Bbe ^((~Bbi)& Bbo ); \+ Ce = E##be; \+ E##bi = Bbi ^((~Bbo)& Bbu ); \+ Ci = E##bi; \+ E##bo = Bbo ^((~Bbu)& Bba ); \+ Co = E##bo; \+ E##bu = Bbu ^((~Bba)& Bbe ); \+ Cu = E##bu; \+\+ A##bo ^= Do; \+ Bga = ROL64(A##bo, 28); \+ A##gu ^= Du; \+ Bge = ROL64(A##gu, 20); \+ A##ka ^= Da; \+ Bgi = ROL64(A##ka, 3); \+ A##me ^= De; \+ Bgo = ROL64(A##me, 45); \+ A##si ^= Di; \+ Bgu = ROL64(A##si, 61); \+ E##ga = Bga ^((~Bge)& Bgi ); \+ Ca ^= E##ga; \+ E##ge = Bge ^((~Bgi)& Bgo ); \+ Ce ^= E##ge; \+ E##gi = Bgi ^((~Bgo)& Bgu ); \+ Ci ^= E##gi; \+ E##go = Bgo ^((~Bgu)& Bga ); \+ Co ^= E##go; \+ E##gu = Bgu ^((~Bga)& Bge ); \+ Cu ^= E##gu; \+\+ A##be ^= De; \+ Bka = ROL64(A##be, 1); \+ A##gi ^= Di; \+ Bke = ROL64(A##gi, 6); \+ A##ko ^= Do; \+ Bki = ROL64(A##ko, 25); \+ A##mu ^= Du; \+ Bko = ROL64(A##mu, 8); \+ A##sa ^= Da; \+ Bku = ROL64(A##sa, 18); \+ E##ka = Bka ^((~Bke)& Bki ); \+ Ca ^= E##ka; \+ E##ke = Bke ^((~Bki)& Bko ); \+ Ce ^= E##ke; \+ E##ki = Bki ^((~Bko)& Bku ); \+ Ci ^= E##ki; \+ E##ko = Bko ^((~Bku)& Bka ); \+ Co ^= E##ko; \+ E##ku = Bku ^((~Bka)& Bke ); \+ Cu ^= E##ku; \+\+ A##bu ^= Du; \+ Bma = ROL64(A##bu, 27); \+ A##ga ^= Da; \+ Bme = ROL64(A##ga, 36); \+ A##ke ^= De; \+ Bmi = ROL64(A##ke, 10); \+ A##mi ^= Di; \+ Bmo = ROL64(A##mi, 15); \+ A##so ^= Do; \+ Bmu = ROL64(A##so, 56); \+ E##ma = Bma ^((~Bme)& Bmi ); \+ Ca ^= E##ma; \+ E##me = Bme ^((~Bmi)& Bmo ); \+ Ce ^= E##me; \+ E##mi = Bmi ^((~Bmo)& Bmu ); \+ Ci ^= E##mi; \+ E##mo = Bmo ^((~Bmu)& Bma ); \+ Co ^= E##mo; \+ E##mu = Bmu ^((~Bma)& Bme ); \+ Cu ^= E##mu; \+\+ A##bi ^= Di; \+ Bsa = ROL64(A##bi, 62); \+ A##go ^= Do; \+ Bse = ROL64(A##go, 55); \+ A##ku ^= Du; \+ Bsi = ROL64(A##ku, 39); \+ A##ma ^= Da; \+ Bso = ROL64(A##ma, 41); \+ A##se ^= De; \+ Bsu = ROL64(A##se, 2); \+ E##sa = Bsa ^((~Bse)& Bsi ); \+ Ca ^= E##sa; \+ E##se = Bse ^((~Bsi)& Bso ); \+ Ce ^= E##se; \+ E##si = Bsi ^((~Bso)& Bsu ); \+ Ci ^= E##si; \+ E##so = Bso ^((~Bsu)& Bsa ); \+ Co ^= E##so; \+ E##su = Bsu ^((~Bsa)& Bse ); \+ Cu ^= E##su; \+\++/* --- Code for round */+/* --- 64-bit lanes mapped to 64-bit words */+#define thetaRhoPiChiIota(i, A, E) \+ Da = Cu^ROL64(Ce, 1); \+ De = Ca^ROL64(Ci, 1); \+ Di = Ce^ROL64(Co, 1); \+ Do = Ci^ROL64(Cu, 1); \+ Du = Co^ROL64(Ca, 1); \+\+ A##ba ^= Da; \+ Bba = A##ba; \+ A##ge ^= De; \+ Bbe = ROL64(A##ge, 44); \+ A##ki ^= Di; \+ Bbi = ROL64(A##ki, 43); \+ A##mo ^= Do; \+ Bbo = ROL64(A##mo, 21); \+ A##su ^= Du; \+ Bbu = ROL64(A##su, 14); \+ E##ba = Bba ^((~Bbe)& Bbi ); \+ E##ba ^= KeccakF1600RoundConstants[i]; \+ E##be = Bbe ^((~Bbi)& Bbo ); \+ E##bi = Bbi ^((~Bbo)& Bbu ); \+ E##bo = Bbo ^((~Bbu)& Bba ); \+ E##bu = Bbu ^((~Bba)& Bbe ); \+\+ A##bo ^= Do; \+ Bga = ROL64(A##bo, 28); \+ A##gu ^= Du; \+ Bge = ROL64(A##gu, 20); \+ A##ka ^= Da; \+ Bgi = ROL64(A##ka, 3); \+ A##me ^= De; \+ Bgo = ROL64(A##me, 45); \+ A##si ^= Di; \+ Bgu = ROL64(A##si, 61); \+ E##ga = Bga ^((~Bge)& Bgi ); \+ E##ge = Bge ^((~Bgi)& Bgo ); \+ E##gi = Bgi ^((~Bgo)& Bgu ); \+ E##go = Bgo ^((~Bgu)& Bga ); \+ E##gu = Bgu ^((~Bga)& Bge ); \+\+ A##be ^= De; \+ Bka = ROL64(A##be, 1); \+ A##gi ^= Di; \+ Bke = ROL64(A##gi, 6); \+ A##ko ^= Do; \+ Bki = ROL64(A##ko, 25); \+ A##mu ^= Du; \+ Bko = ROL64(A##mu, 8); \+ A##sa ^= Da; \+ Bku = ROL64(A##sa, 18); \+ E##ka = Bka ^((~Bke)& Bki ); \+ E##ke = Bke ^((~Bki)& Bko ); \+ E##ki = Bki ^((~Bko)& Bku ); \+ E##ko = Bko ^((~Bku)& Bka ); \+ E##ku = Bku ^((~Bka)& Bke ); \+\+ A##bu ^= Du; \+ Bma = ROL64(A##bu, 27); \+ A##ga ^= Da; \+ Bme = ROL64(A##ga, 36); \+ A##ke ^= De; \+ Bmi = ROL64(A##ke, 10); \+ A##mi ^= Di; \+ Bmo = ROL64(A##mi, 15); \+ A##so ^= Do; \+ Bmu = ROL64(A##so, 56); \+ E##ma = Bma ^((~Bme)& Bmi ); \+ E##me = Bme ^((~Bmi)& Bmo ); \+ E##mi = Bmi ^((~Bmo)& Bmu ); \+ E##mo = Bmo ^((~Bmu)& Bma ); \+ E##mu = Bmu ^((~Bma)& Bme ); \+\+ A##bi ^= Di; \+ Bsa = ROL64(A##bi, 62); \+ A##go ^= Do; \+ Bse = ROL64(A##go, 55); \+ A##ku ^= Du; \+ Bsi = ROL64(A##ku, 39); \+ A##ma ^= Da; \+ Bso = ROL64(A##ma, 41); \+ A##se ^= De; \+ Bsu = ROL64(A##se, 2); \+ E##sa = Bsa ^((~Bse)& Bsi ); \+ E##se = Bse ^((~Bsi)& Bso ); \+ E##si = Bsi ^((~Bso)& Bsu ); \+ E##so = Bso ^((~Bsu)& Bsa ); \+ E##su = Bsu ^((~Bsa)& Bse ); \+\++#endif /* UseBebigokimisa */++#define copyFromState(X, state) \+ X##ba = state[ 0]; \+ X##be = state[ 1]; \+ X##bi = state[ 2]; \+ X##bo = state[ 3]; \+ X##bu = state[ 4]; \+ X##ga = state[ 5]; \+ X##ge = state[ 6]; \+ X##gi = state[ 7]; \+ X##go = state[ 8]; \+ X##gu = state[ 9]; \+ X##ka = state[10]; \+ X##ke = state[11]; \+ X##ki = state[12]; \+ X##ko = state[13]; \+ X##ku = state[14]; \+ X##ma = state[15]; \+ X##me = state[16]; \+ X##mi = state[17]; \+ X##mo = state[18]; \+ X##mu = state[19]; \+ X##sa = state[20]; \+ X##se = state[21]; \+ X##si = state[22]; \+ X##so = state[23]; \+ X##su = state[24]; \++#define copyToState(state, X) \+ state[ 0] = X##ba; \+ state[ 1] = X##be; \+ state[ 2] = X##bi; \+ state[ 3] = X##bo; \+ state[ 4] = X##bu; \+ state[ 5] = X##ga; \+ state[ 6] = X##ge; \+ state[ 7] = X##gi; \+ state[ 8] = X##go; \+ state[ 9] = X##gu; \+ state[10] = X##ka; \+ state[11] = X##ke; \+ state[12] = X##ki; \+ state[13] = X##ko; \+ state[14] = X##ku; \+ state[15] = X##ma; \+ state[16] = X##me; \+ state[17] = X##mi; \+ state[18] = X##mo; \+ state[19] = X##mu; \+ state[20] = X##sa; \+ state[21] = X##se; \+ state[22] = X##si; \+ state[23] = X##so; \+ state[24] = X##su; \++#define copyStateVariables(X, Y) \+ X##ba = Y##ba; \+ X##be = Y##be; \+ X##bi = Y##bi; \+ X##bo = Y##bo; \+ X##bu = Y##bu; \+ X##ga = Y##ga; \+ X##ge = Y##ge; \+ X##gi = Y##gi; \+ X##go = Y##go; \+ X##gu = Y##gu; \+ X##ka = Y##ka; \+ X##ke = Y##ke; \+ X##ki = Y##ki; \+ X##ko = Y##ko; \+ X##ku = Y##ku; \+ X##ma = Y##ma; \+ X##me = Y##me; \+ X##mi = Y##mi; \+ X##mo = Y##mo; \+ X##mu = Y##mu; \+ X##sa = Y##sa; \+ X##se = Y##se; \+ X##si = Y##si; \+ X##so = Y##so; \+ X##su = Y##su; \++#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)+#define HTOLE64(x) (x)+#else+#define HTOLE64(x) (\+ ((x & 0xff00000000000000ull) >> 56) | \+ ((x & 0x00ff000000000000ull) >> 40) | \+ ((x & 0x0000ff0000000000ull) >> 24) | \+ ((x & 0x000000ff00000000ull) >> 8) | \+ ((x & 0x00000000ff000000ull) << 8) | \+ ((x & 0x0000000000ff0000ull) << 24) | \+ ((x & 0x000000000000ff00ull) << 40) | \+ ((x & 0x00000000000000ffull) << 56))+#endif++#define addInput(X, input, laneCount) \+ if (laneCount == 21) { \+ X##ba ^= HTOLE64(input[ 0]); \+ X##be ^= HTOLE64(input[ 1]); \+ X##bi ^= HTOLE64(input[ 2]); \+ X##bo ^= HTOLE64(input[ 3]); \+ X##bu ^= HTOLE64(input[ 4]); \+ X##ga ^= HTOLE64(input[ 5]); \+ X##ge ^= HTOLE64(input[ 6]); \+ X##gi ^= HTOLE64(input[ 7]); \+ X##go ^= HTOLE64(input[ 8]); \+ X##gu ^= HTOLE64(input[ 9]); \+ X##ka ^= HTOLE64(input[10]); \+ X##ke ^= HTOLE64(input[11]); \+ X##ki ^= HTOLE64(input[12]); \+ X##ko ^= HTOLE64(input[13]); \+ X##ku ^= HTOLE64(input[14]); \+ X##ma ^= HTOLE64(input[15]); \+ X##me ^= HTOLE64(input[16]); \+ X##mi ^= HTOLE64(input[17]); \+ X##mo ^= HTOLE64(input[18]); \+ X##mu ^= HTOLE64(input[19]); \+ X##sa ^= HTOLE64(input[20]); \+ } \+ else if (laneCount < 16) { \+ if (laneCount < 8) { \+ if (laneCount < 4) { \+ if (laneCount < 2) { \+ if (laneCount < 1) { \+ } \+ else { \+ X##ba ^= HTOLE64(input[ 0]); \+ } \+ } \+ else { \+ X##ba ^= HTOLE64(input[ 0]); \+ X##be ^= HTOLE64(input[ 1]); \+ if (laneCount < 3) { \+ } \+ else { \+ X##bi ^= HTOLE64(input[ 2]); \+ } \+ } \+ } \+ else { \+ X##ba ^= HTOLE64(input[ 0]); \+ X##be ^= HTOLE64(input[ 1]); \+ X##bi ^= HTOLE64(input[ 2]); \+ X##bo ^= HTOLE64(input[ 3]); \+ if (laneCount < 6) { \+ if (laneCount < 5) { \+ } \+ else { \+ X##bu ^= HTOLE64(input[ 4]); \+ } \+ } \+ else { \+ X##bu ^= HTOLE64(input[ 4]); \+ X##ga ^= HTOLE64(input[ 5]); \+ if (laneCount < 7) { \+ } \+ else { \+ X##ge ^= HTOLE64(input[ 6]); \+ } \+ } \+ } \+ } \+ else { \+ X##ba ^= HTOLE64(input[ 0]); \+ X##be ^= HTOLE64(input[ 1]); \+ X##bi ^= HTOLE64(input[ 2]); \+ X##bo ^= HTOLE64(input[ 3]); \+ X##bu ^= HTOLE64(input[ 4]); \+ X##ga ^= HTOLE64(input[ 5]); \+ X##ge ^= HTOLE64(input[ 6]); \+ X##gi ^= HTOLE64(input[ 7]); \+ if (laneCount < 12) { \+ if (laneCount < 10) { \+ if (laneCount < 9) { \+ } \+ else { \+ X##go ^= HTOLE64(input[ 8]); \+ } \+ } \+ else { \+ X##go ^= HTOLE64(input[ 8]); \+ X##gu ^= HTOLE64(input[ 9]); \+ if (laneCount < 11) { \+ } \+ else { \+ X##ka ^= HTOLE64(input[10]); \+ } \+ } \+ } \+ else { \+ X##go ^= HTOLE64(input[ 8]); \+ X##gu ^= HTOLE64(input[ 9]); \+ X##ka ^= HTOLE64(input[10]); \+ X##ke ^= HTOLE64(input[11]); \+ if (laneCount < 14) { \+ if (laneCount < 13) { \+ } \+ else { \+ X##ki ^= HTOLE64(input[12]); \+ } \+ } \+ else { \+ X##ki ^= HTOLE64(input[12]); \+ X##ko ^= HTOLE64(input[13]); \+ if (laneCount < 15) { \+ } \+ else { \+ X##ku ^= HTOLE64(input[14]); \+ } \+ } \+ } \+ } \+ } \+ else { \+ X##ba ^= HTOLE64(input[ 0]); \+ X##be ^= HTOLE64(input[ 1]); \+ X##bi ^= HTOLE64(input[ 2]); \+ X##bo ^= HTOLE64(input[ 3]); \+ X##bu ^= HTOLE64(input[ 4]); \+ X##ga ^= HTOLE64(input[ 5]); \+ X##ge ^= HTOLE64(input[ 6]); \+ X##gi ^= HTOLE64(input[ 7]); \+ X##go ^= HTOLE64(input[ 8]); \+ X##gu ^= HTOLE64(input[ 9]); \+ X##ka ^= HTOLE64(input[10]); \+ X##ke ^= HTOLE64(input[11]); \+ X##ki ^= HTOLE64(input[12]); \+ X##ko ^= HTOLE64(input[13]); \+ X##ku ^= HTOLE64(input[14]); \+ X##ma ^= HTOLE64(input[15]); \+ if (laneCount < 24) { \+ if (laneCount < 20) { \+ if (laneCount < 18) { \+ if (laneCount < 17) { \+ } \+ else { \+ X##me ^= HTOLE64(input[16]); \+ } \+ } \+ else { \+ X##me ^= HTOLE64(input[16]); \+ X##mi ^= HTOLE64(input[17]); \+ if (laneCount < 19) { \+ } \+ else { \+ X##mo ^= HTOLE64(input[18]); \+ } \+ } \+ } \+ else { \+ X##me ^= HTOLE64(input[16]); \+ X##mi ^= HTOLE64(input[17]); \+ X##mo ^= HTOLE64(input[18]); \+ X##mu ^= HTOLE64(input[19]); \+ if (laneCount < 22) { \+ if (laneCount < 21) { \+ } \+ else { \+ X##sa ^= HTOLE64(input[20]); \+ } \+ } \+ else { \+ X##sa ^= HTOLE64(input[20]); \+ X##se ^= HTOLE64(input[21]); \+ if (laneCount < 23) { \+ } \+ else { \+ X##si ^= HTOLE64(input[22]); \+ } \+ } \+ } \+ } \+ else { \+ X##me ^= HTOLE64(input[16]); \+ X##mi ^= HTOLE64(input[17]); \+ X##mo ^= HTOLE64(input[18]); \+ X##mu ^= HTOLE64(input[19]); \+ X##sa ^= HTOLE64(input[20]); \+ X##se ^= HTOLE64(input[21]); \+ X##si ^= HTOLE64(input[22]); \+ X##so ^= HTOLE64(input[23]); \+ if (laneCount < 25) { \+ } \+ else { \+ X##su ^= HTOLE64(input[24]); \+ } \+ } \+ }
+ cbits/xkcp/KeccakP-1600-SnP.h view
@@ -0,0 +1,54 @@+/*+The eXtended Keccak Code Package (XKCP)+https://github.com/XKCP/XKCP++The Keccak-p permutations, designed by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche.++Implementation by Gilles Van Assche and Ronny Van Keer, hereby denoted as "the implementer".++For more information, feedback or questions, please refer to the Keccak Team website:+https://keccak.team/++To the extent possible under law, the implementer has waived all copyright+and related or neighboring rights to the source code in this file.+http://creativecommons.org/publicdomain/zero/1.0/++---++Please refer to SnP-documentation.h for more details.+*/++#ifndef _KeccakP_1600_SnP_h_+#define _KeccakP_1600_SnP_h_++#include "brg_endian.h"+#include "KeccakP-1600-opt64-config.h"++#define KeccakP1600_implementation "generic 64-bit optimized implementation (" KeccakP1600_implementation_config ")"+#define KeccakP1600_stateSizeInBytes 200+#define KeccakP1600_stateAlignment 8+#define KeccakF1600_FastLoop_supported+#define KeccakP1600_12rounds_FastLoop_supported++#include <stddef.h>++#define KeccakP1600_StaticInitialize()+void KeccakP1600_Initialize(void *state);+#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)+#define KeccakP1600_AddByte(state, byte, offset) \+ ((unsigned char*)(state))[(offset)] ^= (byte)+#else+void KeccakP1600_AddByte(void *state, unsigned char data, unsigned int offset);+#endif+void KeccakP1600_AddBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length);+void KeccakP1600_OverwriteBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length);+void KeccakP1600_OverwriteWithZeroes(void *state, unsigned int byteCount);+void KeccakP1600_Permute_Nrounds(void *state, unsigned int nrounds);+void KeccakP1600_Permute_12rounds(void *state);+void KeccakP1600_Permute_24rounds(void *state);+void KeccakP1600_ExtractBytes(const void *state, unsigned char *data, unsigned int offset, unsigned int length);+void KeccakP1600_ExtractAndAddBytes(const void *state, const unsigned char *input, unsigned char *output, unsigned int offset, unsigned int length);+size_t KeccakF1600_FastLoop_Absorb(void *state, unsigned int laneCount, const unsigned char *data, size_t dataByteLen);+size_t KeccakP1600_12rounds_FastLoop_Absorb(void *state, unsigned int laneCount, const unsigned char *data, size_t dataByteLen);++#endif
+ cbits/xkcp/KeccakP-1600-opt64-config.h view
@@ -0,0 +1,6 @@+/*+This file defines some parameters of the implementation in the parent directory.+*/++#define KeccakP1600_implementation_config "all rounds unrolled"+#define KeccakP1600_fullUnrolling
+ cbits/xkcp/KeccakP-1600-opt64.c view
@@ -0,0 +1,565 @@+/*+The eXtended Keccak Code Package (XKCP)+https://github.com/XKCP/XKCP++The Keccak-p permutations, designed by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche.++Implementation by Gilles Van Assche and Ronny Van Keer, hereby denoted as "the implementer".++For more information, feedback or questions, please refer to the Keccak Team website:+https://keccak.team/++To the extent possible under law, the implementer has waived all copyright+and related or neighboring rights to the source code in this file.+http://creativecommons.org/publicdomain/zero/1.0/++---++This file implements Keccak-p[1600] in a SnP-compatible way.+Please refer to SnP-documentation.h for more details.++This implementation comes with KeccakP-1600-SnP.h in the same folder.+Please refer to LowLevel.build for the exact list of other files it must be combined with.+*/++#include <stdint.h>+#include <string.h>+#include <stdlib.h>+#include "brg_endian.h"+#include "KeccakP-1600-opt64-config.h"++#if defined(KeccakP1600_useLaneComplementing)+#define UseBebigokimisa+#endif++#if defined(_MSC_VER)+#define ROL64(a, offset) _rotl64(a, offset)+#elif defined(KeccakP1600_useSHLD)+ #define ROL64(x,N) ({ \+ register uint64_t __out; \+ register uint64_t __in = x; \+ __asm__ ("shld %2,%0,%0" : "=r"(__out) : "0"(__in), "i"(N)); \+ __out; \+ })+#else+#define ROL64(a, offset) ((((uint64_t)a) << offset) ^ (((uint64_t)a) >> (64-offset)))+#endif++#include "KeccakP-1600-64.macros"+#ifdef KeccakP1600_fullUnrolling+#define FullUnrolling+#else+#define Unrolling KeccakP1600_unrolling+#endif+#include "KeccakP-1600-unrolling.macros"+#include "SnP-Relaned.h"++static const uint64_t KeccakF1600RoundConstants[24] = {+ 0x0000000000000001ULL,+ 0x0000000000008082ULL,+ 0x800000000000808aULL,+ 0x8000000080008000ULL,+ 0x000000000000808bULL,+ 0x0000000080000001ULL,+ 0x8000000080008081ULL,+ 0x8000000000008009ULL,+ 0x000000000000008aULL,+ 0x0000000000000088ULL,+ 0x0000000080008009ULL,+ 0x000000008000000aULL,+ 0x000000008000808bULL,+ 0x800000000000008bULL,+ 0x8000000000008089ULL,+ 0x8000000000008003ULL,+ 0x8000000000008002ULL,+ 0x8000000000000080ULL,+ 0x000000000000800aULL,+ 0x800000008000000aULL,+ 0x8000000080008081ULL,+ 0x8000000000008080ULL,+ 0x0000000080000001ULL,+ 0x8000000080008008ULL };++/* ---------------------------------------------------------------- */++void KeccakP1600_Initialize(void *state)+{+ memset(state, 0, 200);+#ifdef KeccakP1600_useLaneComplementing+ ((uint64_t*)state)[ 1] = ~(uint64_t)0;+ ((uint64_t*)state)[ 2] = ~(uint64_t)0;+ ((uint64_t*)state)[ 8] = ~(uint64_t)0;+ ((uint64_t*)state)[12] = ~(uint64_t)0;+ ((uint64_t*)state)[17] = ~(uint64_t)0;+ ((uint64_t*)state)[20] = ~(uint64_t)0;+#endif+}++/* ---------------------------------------------------------------- */++void KeccakP1600_AddBytesInLane(void *state, unsigned int lanePosition, const unsigned char *data, unsigned int offset, unsigned int length)+{+#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)+ uint64_t lane;+ if (length == 0)+ return;+ if (length == 1)+ lane = data[0];+ else {+ lane = 0;+ memcpy(&lane, data, length);+ }+ lane <<= offset*8;+#else+ uint64_t lane = 0;+ unsigned int i;+ for(i=0; i<length; i++)+ lane |= ((uint64_t)data[i]) << ((i+offset)*8);+#endif+ ((uint64_t*)state)[lanePosition] ^= lane;+}++/* ---------------------------------------------------------------- */++void KeccakP1600_AddLanes(void *state, const unsigned char *data, unsigned int laneCount)+{+#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)+ unsigned int i = 0;+#ifdef NO_MISALIGNED_ACCESSES+ /* If either pointer is misaligned, fall back to byte-wise xor. */+ if (((((uintptr_t)state) & 7) != 0) || ((((uintptr_t)data) & 7) != 0)) {+ for (i = 0; i < laneCount * 8; i++) {+ ((unsigned char*)state)[i] ^= data[i];+ }+ }+ else+#endif+ {+ /* Otherwise... */+ for( ; (i+8)<=laneCount; i+=8) {+ ((uint64_t*)state)[i+0] ^= ((uint64_t*)data)[i+0];+ ((uint64_t*)state)[i+1] ^= ((uint64_t*)data)[i+1];+ ((uint64_t*)state)[i+2] ^= ((uint64_t*)data)[i+2];+ ((uint64_t*)state)[i+3] ^= ((uint64_t*)data)[i+3];+ ((uint64_t*)state)[i+4] ^= ((uint64_t*)data)[i+4];+ ((uint64_t*)state)[i+5] ^= ((uint64_t*)data)[i+5];+ ((uint64_t*)state)[i+6] ^= ((uint64_t*)data)[i+6];+ ((uint64_t*)state)[i+7] ^= ((uint64_t*)data)[i+7];+ }+ for( ; (i+4)<=laneCount; i+=4) {+ ((uint64_t*)state)[i+0] ^= ((uint64_t*)data)[i+0];+ ((uint64_t*)state)[i+1] ^= ((uint64_t*)data)[i+1];+ ((uint64_t*)state)[i+2] ^= ((uint64_t*)data)[i+2];+ ((uint64_t*)state)[i+3] ^= ((uint64_t*)data)[i+3];+ }+ for( ; (i+2)<=laneCount; i+=2) {+ ((uint64_t*)state)[i+0] ^= ((uint64_t*)data)[i+0];+ ((uint64_t*)state)[i+1] ^= ((uint64_t*)data)[i+1];+ }+ if (i<laneCount) {+ ((uint64_t*)state)[i+0] ^= ((uint64_t*)data)[i+0];+ }+ }+#else+ unsigned int i;+ const uint8_t *curData = data;+ for(i=0; i<laneCount; i++, curData+=8) {+ uint64_t lane = (uint64_t)curData[0]+ | ((uint64_t)curData[1] << 8)+ | ((uint64_t)curData[2] << 16)+ | ((uint64_t)curData[3] << 24)+ | ((uint64_t)curData[4] << 32)+ | ((uint64_t)curData[5] << 40)+ | ((uint64_t)curData[6] << 48)+ | ((uint64_t)curData[7] << 56);+ ((uint64_t*)state)[i] ^= lane;+ }+#endif+}++/* ---------------------------------------------------------------- */++#if (PLATFORM_BYTE_ORDER != IS_LITTLE_ENDIAN)+void KeccakP1600_AddByte(void *state, unsigned char byte, unsigned int offset)+{+ uint64_t lane = byte;+ lane <<= (offset%8)*8;+ ((uint64_t*)state)[offset/8] ^= lane;+}+#endif++/* ---------------------------------------------------------------- */++void KeccakP1600_AddBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length)+{+ SnP_AddBytes(state, data, offset, length, KeccakP1600_AddLanes, KeccakP1600_AddBytesInLane, 8);+}++/* ---------------------------------------------------------------- */++void KeccakP1600_OverwriteBytesInLane(void *state, unsigned int lanePosition, const unsigned char *data, unsigned int offset, unsigned int length)+{+#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)+#ifdef KeccakP1600_useLaneComplementing+ if ((lanePosition == 1) || (lanePosition == 2) || (lanePosition == 8) || (lanePosition == 12) || (lanePosition == 17) || (lanePosition == 20)) {+ unsigned int i;+ for(i=0; i<length; i++)+ ((unsigned char*)state)[lanePosition*8+offset+i] = ~data[i];+ }+ else+#endif+ {+ memcpy((unsigned char*)state+lanePosition*8+offset, data, length);+ }+#else+ uint64_t lane = ((uint64_t*)state)[lanePosition];+ unsigned int i;+ for(i=0; i<length; i++) {+ lane &= ~((uint64_t)0xFF << ((offset+i)*8));+#ifdef KeccakP1600_useLaneComplementing+ if ((lanePosition == 1) || (lanePosition == 2) || (lanePosition == 8) || (lanePosition == 12) || (lanePosition == 17) || (lanePosition == 20))+ lane |= (uint64_t)(data[i] ^ 0xFF) << ((offset+i)*8);+ else+#endif+ lane |= (uint64_t)data[i] << ((offset+i)*8);+ }+ ((uint64_t*)state)[lanePosition] = lane;+#endif+}++/* ---------------------------------------------------------------- */++void KeccakP1600_OverwriteLanes(void *state, const unsigned char *data, unsigned int laneCount)+{+#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)+#ifdef KeccakP1600_useLaneComplementing+ unsigned int lanePosition;++ for(lanePosition=0; lanePosition<laneCount; lanePosition++)+ if ((lanePosition == 1) || (lanePosition == 2) || (lanePosition == 8) || (lanePosition == 12) || (lanePosition == 17) || (lanePosition == 20))+ ((uint64_t*)state)[lanePosition] = ~((const uint64_t*)data)[lanePosition];+ else+ ((uint64_t*)state)[lanePosition] = ((const uint64_t*)data)[lanePosition];+#else+ memcpy(state, data, laneCount*8);+#endif+#else+ unsigned int lanePosition;+ const uint8_t *curData = data;+ for(lanePosition=0; lanePosition<laneCount; lanePosition++, curData+=8) {+ uint64_t lane = (uint64_t)curData[0]+ | ((uint64_t)curData[1] << 8)+ | ((uint64_t)curData[2] << 16)+ | ((uint64_t)curData[3] << 24)+ | ((uint64_t)curData[4] << 32)+ | ((uint64_t)curData[5] << 40)+ | ((uint64_t)curData[6] << 48)+ | ((uint64_t)curData[7] << 56);+#ifdef KeccakP1600_useLaneComplementing+ if ((lanePosition == 1) || (lanePosition == 2) || (lanePosition == 8) || (lanePosition == 12) || (lanePosition == 17) || (lanePosition == 20))+ ((uint64_t*)state)[lanePosition] = ~lane;+ else+#endif+ ((uint64_t*)state)[lanePosition] = lane;+ }+#endif+}++/* ---------------------------------------------------------------- */++void KeccakP1600_OverwriteBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length)+{+ SnP_OverwriteBytes(state, data, offset, length, KeccakP1600_OverwriteLanes, KeccakP1600_OverwriteBytesInLane, 8);+}++/* ---------------------------------------------------------------- */++void KeccakP1600_OverwriteWithZeroes(void *state, unsigned int byteCount)+{+#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)+#ifdef KeccakP1600_useLaneComplementing+ unsigned int lanePosition;++ for(lanePosition=0; lanePosition<byteCount/8; lanePosition++)+ if ((lanePosition == 1) || (lanePosition == 2) || (lanePosition == 8) || (lanePosition == 12) || (lanePosition == 17) || (lanePosition == 20))+ ((uint64_t*)state)[lanePosition] = ~0;+ else+ ((uint64_t*)state)[lanePosition] = 0;+ if (byteCount%8 != 0) {+ lanePosition = byteCount/8;+ if ((lanePosition == 1) || (lanePosition == 2) || (lanePosition == 8) || (lanePosition == 12) || (lanePosition == 17) || (lanePosition == 20))+ memset((unsigned char*)state+lanePosition*8, 0xFF, byteCount%8);+ else+ memset((unsigned char*)state+lanePosition*8, 0, byteCount%8);+ }+#else+ memset(state, 0, byteCount);+#endif+#else+ unsigned int i, j;+ for(i=0; i<byteCount; i+=8) {+ unsigned int lanePosition = i/8;+ if (i+8 <= byteCount) {+#ifdef KeccakP1600_useLaneComplementing+ if ((lanePosition == 1) || (lanePosition == 2) || (lanePosition == 8) || (lanePosition == 12) || (lanePosition == 17) || (lanePosition == 20))+ ((uint64_t*)state)[lanePosition] = ~(uint64_t)0;+ else+#endif+ ((uint64_t*)state)[lanePosition] = 0;+ }+ else {+ uint64_t lane = ((uint64_t*)state)[lanePosition];+ for(j=0; j<byteCount%8; j++) {+#ifdef KeccakP1600_useLaneComplementing+ if ((lanePosition == 1) || (lanePosition == 2) || (lanePosition == 8) || (lanePosition == 12) || (lanePosition == 17) || (lanePosition == 20))+ lane |= (uint64_t)0xFF << (j*8);+ else+#endif+ lane &= ~((uint64_t)0xFF << (j*8));+ }+ ((uint64_t*)state)[lanePosition] = lane;+ }+ }+#endif+}++/* ---------------------------------------------------------------- */++void KeccakP1600_Permute_Nrounds(void *state, unsigned int nr)+{+ declareABCDE+ unsigned int i;+ uint64_t *stateAsLanes = (uint64_t*)state;++ copyFromState(A, stateAsLanes)+ roundsN(nr)+ copyToState(stateAsLanes, A)++}++/* ---------------------------------------------------------------- */++void KeccakP1600_Permute_24rounds(void *state)+{+ declareABCDE+ #ifndef KeccakP1600_fullUnrolling+ unsigned int i;+ #endif+ uint64_t *stateAsLanes = (uint64_t*)state;++ copyFromState(A, stateAsLanes)+ rounds24+ copyToState(stateAsLanes, A)+}++/* ---------------------------------------------------------------- */++void KeccakP1600_Permute_12rounds(void *state)+{+ declareABCDE+ #ifndef KeccakP1600_fullUnrolling+ unsigned int i;+ #endif+ uint64_t *stateAsLanes = (uint64_t*)state;++ copyFromState(A, stateAsLanes)+ rounds12+ copyToState(stateAsLanes, A)+}++/* ---------------------------------------------------------------- */++void KeccakP1600_ExtractBytesInLane(const void *state, unsigned int lanePosition, unsigned char *data, unsigned int offset, unsigned int length)+{+ uint64_t lane = ((uint64_t*)state)[lanePosition];+#ifdef KeccakP1600_useLaneComplementing+ if ((lanePosition == 1) || (lanePosition == 2) || (lanePosition == 8) || (lanePosition == 12) || (lanePosition == 17) || (lanePosition == 20))+ lane = ~lane;+#endif+#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)+ {+ uint64_t lane1[1];+ lane1[0] = lane;+ memcpy(data, (uint8_t*)lane1+offset, length);+ }+#else+ unsigned int i;+ lane >>= offset*8;+ for(i=0; i<length; i++) {+ data[i] = lane & 0xFF;+ lane >>= 8;+ }+#endif+}++/* ---------------------------------------------------------------- */++#if (PLATFORM_BYTE_ORDER != IS_LITTLE_ENDIAN)+static void fromWordToBytes(uint8_t *bytes, const uint64_t word)+{+ unsigned int i;++ for(i=0; i<(64/8); i++)+ bytes[i] = (word >> (8*i)) & 0xFF;+}+#endif++void KeccakP1600_ExtractLanes(const void *state, unsigned char *data, unsigned int laneCount)+{+#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)+ memcpy(data, state, laneCount*8);+#else+ unsigned int i;++ for(i=0; i<laneCount; i++)+ fromWordToBytes(data+(i*8), ((const uint64_t*)state)[i]);+#endif+#ifdef KeccakP1600_useLaneComplementing+ if (laneCount > 1) {+ ((uint64_t*)data)[ 1] = ~((uint64_t*)data)[ 1];+ if (laneCount > 2) {+ ((uint64_t*)data)[ 2] = ~((uint64_t*)data)[ 2];+ if (laneCount > 8) {+ ((uint64_t*)data)[ 8] = ~((uint64_t*)data)[ 8];+ if (laneCount > 12) {+ ((uint64_t*)data)[12] = ~((uint64_t*)data)[12];+ if (laneCount > 17) {+ ((uint64_t*)data)[17] = ~((uint64_t*)data)[17];+ if (laneCount > 20) {+ ((uint64_t*)data)[20] = ~((uint64_t*)data)[20];+ }+ }+ }+ }+ }+ }+#endif+}++/* ---------------------------------------------------------------- */++void KeccakP1600_ExtractBytes(const void *state, unsigned char *data, unsigned int offset, unsigned int length)+{+ SnP_ExtractBytes(state, data, offset, length, KeccakP1600_ExtractLanes, KeccakP1600_ExtractBytesInLane, 8);+}++/* ---------------------------------------------------------------- */++void KeccakP1600_ExtractAndAddBytesInLane(const void *state, unsigned int lanePosition, const unsigned char *input, unsigned char *output, unsigned int offset, unsigned int length)+{+ uint64_t lane = ((uint64_t*)state)[lanePosition];+#ifdef KeccakP1600_useLaneComplementing+ if ((lanePosition == 1) || (lanePosition == 2) || (lanePosition == 8) || (lanePosition == 12) || (lanePosition == 17) || (lanePosition == 20))+ lane = ~lane;+#endif+#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)+ {+ unsigned int i;+ uint64_t lane1[1];+ lane1[0] = lane;+ for(i=0; i<length; i++)+ output[i] = input[i] ^ ((uint8_t*)lane1)[offset+i];+ }+#else+ unsigned int i;+ lane >>= offset*8;+ for(i=0; i<length; i++) {+ output[i] = input[i] ^ (lane & 0xFF);+ lane >>= 8;+ }+#endif+}++/* ---------------------------------------------------------------- */++void KeccakP1600_ExtractAndAddLanes(const void *state, const unsigned char *input, unsigned char *output, unsigned int laneCount)+{+ unsigned int i;+#if (PLATFORM_BYTE_ORDER != IS_LITTLE_ENDIAN)+ unsigned char temp[8];+ unsigned int j;+#endif++ for(i=0; i<laneCount; i++) {+#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)+ ((uint64_t*)output)[i] = ((uint64_t*)input)[i] ^ ((const uint64_t*)state)[i];+#else+ fromWordToBytes(temp, ((const uint64_t*)state)[i]);+ for(j=0; j<8; j++)+ output[i*8+j] = input[i*8+j] ^ temp[j];+#endif+ }+#ifdef KeccakP1600_useLaneComplementing+ if (laneCount > 1) {+ ((uint64_t*)output)[ 1] = ~((uint64_t*)output)[ 1];+ if (laneCount > 2) {+ ((uint64_t*)output)[ 2] = ~((uint64_t*)output)[ 2];+ if (laneCount > 8) {+ ((uint64_t*)output)[ 8] = ~((uint64_t*)output)[ 8];+ if (laneCount > 12) {+ ((uint64_t*)output)[12] = ~((uint64_t*)output)[12];+ if (laneCount > 17) {+ ((uint64_t*)output)[17] = ~((uint64_t*)output)[17];+ if (laneCount > 20) {+ ((uint64_t*)output)[20] = ~((uint64_t*)output)[20];+ }+ }+ }+ }+ }+ }+#endif+}++/* ---------------------------------------------------------------- */++void KeccakP1600_ExtractAndAddBytes(const void *state, const unsigned char *input, unsigned char *output, unsigned int offset, unsigned int length)+{+ SnP_ExtractAndAddBytes(state, input, output, offset, length, KeccakP1600_ExtractAndAddLanes, KeccakP1600_ExtractAndAddBytesInLane, 8);+}++/* ---------------------------------------------------------------- */++size_t KeccakF1600_FastLoop_Absorb(void *state, unsigned int laneCount, const unsigned char *data, size_t dataByteLen)+{+ size_t originalDataByteLen = dataByteLen;+ declareABCDE+ #ifndef KeccakP1600_fullUnrolling+ unsigned int i;+ #endif+ uint64_t *stateAsLanes = (uint64_t*)state;+ uint64_t *inDataAsLanes = (uint64_t*)data;++ copyFromState(A, stateAsLanes)+ while(dataByteLen >= laneCount*8) {+ addInput(A, inDataAsLanes, laneCount)+ rounds24+ inDataAsLanes += laneCount;+ dataByteLen -= laneCount*8;+ }+ copyToState(stateAsLanes, A)+ return originalDataByteLen - dataByteLen;+}++/* ---------------------------------------------------------------- */++size_t KeccakP1600_12rounds_FastLoop_Absorb(void *state, unsigned int laneCount, const unsigned char *data, size_t dataByteLen)+{+ size_t originalDataByteLen = dataByteLen;+ declareABCDE+ #ifndef KeccakP1600_fullUnrolling+ unsigned int i;+ #endif+ uint64_t *stateAsLanes = (uint64_t*)state;+ uint64_t *inDataAsLanes = (uint64_t*)data;++ copyFromState(A, stateAsLanes)+ while(dataByteLen >= laneCount*8) {+ addInput(A, inDataAsLanes, laneCount)+ rounds12+ inDataAsLanes += laneCount;+ dataByteLen -= laneCount*8;+ }+ copyToState(stateAsLanes, A)+ return originalDataByteLen - dataByteLen;+}
+ cbits/xkcp/KeccakP-1600-unrolling.macros view
@@ -0,0 +1,305 @@+/*+The eXtended Keccak Code Package (XKCP)+https://github.com/XKCP/XKCP++The Keccak-p permutations, designed by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche.++Implementation by Gilles Van Assche and Ronny Van Keer, hereby denoted as "the implementer".++For more information, feedback or questions, please refer to the Keccak Team website:+https://keccak.team/++To the extent possible under law, the implementer has waived all copyright+and related or neighboring rights to the source code in this file.+http://creativecommons.org/publicdomain/zero/1.0/+*/++#if (defined(FullUnrolling))+#define rounds24 \+ prepareTheta \+ thetaRhoPiChiIotaPrepareTheta( 0, A, E) \+ thetaRhoPiChiIotaPrepareTheta( 1, E, A) \+ thetaRhoPiChiIotaPrepareTheta( 2, A, E) \+ thetaRhoPiChiIotaPrepareTheta( 3, E, A) \+ thetaRhoPiChiIotaPrepareTheta( 4, A, E) \+ thetaRhoPiChiIotaPrepareTheta( 5, E, A) \+ thetaRhoPiChiIotaPrepareTheta( 6, A, E) \+ thetaRhoPiChiIotaPrepareTheta( 7, E, A) \+ thetaRhoPiChiIotaPrepareTheta( 8, A, E) \+ thetaRhoPiChiIotaPrepareTheta( 9, E, A) \+ thetaRhoPiChiIotaPrepareTheta(10, A, E) \+ thetaRhoPiChiIotaPrepareTheta(11, E, A) \+ thetaRhoPiChiIotaPrepareTheta(12, A, E) \+ thetaRhoPiChiIotaPrepareTheta(13, E, A) \+ thetaRhoPiChiIotaPrepareTheta(14, A, E) \+ thetaRhoPiChiIotaPrepareTheta(15, E, A) \+ thetaRhoPiChiIotaPrepareTheta(16, A, E) \+ thetaRhoPiChiIotaPrepareTheta(17, E, A) \+ thetaRhoPiChiIotaPrepareTheta(18, A, E) \+ thetaRhoPiChiIotaPrepareTheta(19, E, A) \+ thetaRhoPiChiIotaPrepareTheta(20, A, E) \+ thetaRhoPiChiIotaPrepareTheta(21, E, A) \+ thetaRhoPiChiIotaPrepareTheta(22, A, E) \+ thetaRhoPiChiIota(23, E, A) \++#define rounds12 \+ prepareTheta \+ thetaRhoPiChiIotaPrepareTheta(12, A, E) \+ thetaRhoPiChiIotaPrepareTheta(13, E, A) \+ thetaRhoPiChiIotaPrepareTheta(14, A, E) \+ thetaRhoPiChiIotaPrepareTheta(15, E, A) \+ thetaRhoPiChiIotaPrepareTheta(16, A, E) \+ thetaRhoPiChiIotaPrepareTheta(17, E, A) \+ thetaRhoPiChiIotaPrepareTheta(18, A, E) \+ thetaRhoPiChiIotaPrepareTheta(19, E, A) \+ thetaRhoPiChiIotaPrepareTheta(20, A, E) \+ thetaRhoPiChiIotaPrepareTheta(21, E, A) \+ thetaRhoPiChiIotaPrepareTheta(22, A, E) \+ thetaRhoPiChiIota(23, E, A) \++#define rounds6 \+ prepareTheta \+ thetaRhoPiChiIotaPrepareTheta(18, A, E) \+ thetaRhoPiChiIotaPrepareTheta(19, E, A) \+ thetaRhoPiChiIotaPrepareTheta(20, A, E) \+ thetaRhoPiChiIotaPrepareTheta(21, E, A) \+ thetaRhoPiChiIotaPrepareTheta(22, A, E) \+ thetaRhoPiChiIota(23, E, A) \++#define rounds4 \+ prepareTheta \+ thetaRhoPiChiIotaPrepareTheta(20, A, E) \+ thetaRhoPiChiIotaPrepareTheta(21, E, A) \+ thetaRhoPiChiIotaPrepareTheta(22, A, E) \+ thetaRhoPiChiIota(23, E, A) \++#elif (Unrolling == 12)+#define rounds24 \+ prepareTheta \+ for(i=0; i<24; i+=12) { \+ thetaRhoPiChiIotaPrepareTheta(i , A, E) \+ thetaRhoPiChiIotaPrepareTheta(i+ 1, E, A) \+ thetaRhoPiChiIotaPrepareTheta(i+ 2, A, E) \+ thetaRhoPiChiIotaPrepareTheta(i+ 3, E, A) \+ thetaRhoPiChiIotaPrepareTheta(i+ 4, A, E) \+ thetaRhoPiChiIotaPrepareTheta(i+ 5, E, A) \+ thetaRhoPiChiIotaPrepareTheta(i+ 6, A, E) \+ thetaRhoPiChiIotaPrepareTheta(i+ 7, E, A) \+ thetaRhoPiChiIotaPrepareTheta(i+ 8, A, E) \+ thetaRhoPiChiIotaPrepareTheta(i+ 9, E, A) \+ thetaRhoPiChiIotaPrepareTheta(i+10, A, E) \+ thetaRhoPiChiIotaPrepareTheta(i+11, E, A) \+ } \++#define rounds12 \+ prepareTheta \+ thetaRhoPiChiIotaPrepareTheta(12, A, E) \+ thetaRhoPiChiIotaPrepareTheta(13, E, A) \+ thetaRhoPiChiIotaPrepareTheta(14, A, E) \+ thetaRhoPiChiIotaPrepareTheta(15, E, A) \+ thetaRhoPiChiIotaPrepareTheta(16, A, E) \+ thetaRhoPiChiIotaPrepareTheta(17, E, A) \+ thetaRhoPiChiIotaPrepareTheta(18, A, E) \+ thetaRhoPiChiIotaPrepareTheta(19, E, A) \+ thetaRhoPiChiIotaPrepareTheta(20, A, E) \+ thetaRhoPiChiIotaPrepareTheta(21, E, A) \+ thetaRhoPiChiIotaPrepareTheta(22, A, E) \+ thetaRhoPiChiIota(23, E, A) \++#define rounds6 \+ prepareTheta \+ thetaRhoPiChiIotaPrepareTheta(18, A, E) \+ thetaRhoPiChiIotaPrepareTheta(19, E, A) \+ thetaRhoPiChiIotaPrepareTheta(20, A, E) \+ thetaRhoPiChiIotaPrepareTheta(21, E, A) \+ thetaRhoPiChiIotaPrepareTheta(22, A, E) \+ thetaRhoPiChiIota(23, E, A) \++#define rounds4 \+ prepareTheta \+ thetaRhoPiChiIotaPrepareTheta(20, A, E) \+ thetaRhoPiChiIotaPrepareTheta(21, E, A) \+ thetaRhoPiChiIotaPrepareTheta(22, A, E) \+ thetaRhoPiChiIota(23, E, A) \++#elif (Unrolling == 6)+#define rounds24 \+ prepareTheta \+ for(i=0; i<24; i+=6) { \+ thetaRhoPiChiIotaPrepareTheta(i , A, E) \+ thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \+ thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \+ thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \+ thetaRhoPiChiIotaPrepareTheta(i+4, A, E) \+ thetaRhoPiChiIotaPrepareTheta(i+5, E, A) \+ } \++#define rounds12 \+ prepareTheta \+ for(i=12; i<24; i+=6) { \+ thetaRhoPiChiIotaPrepareTheta(i , A, E) \+ thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \+ thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \+ thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \+ thetaRhoPiChiIotaPrepareTheta(i+4, A, E) \+ thetaRhoPiChiIotaPrepareTheta(i+5, E, A) \+ } \++#define rounds6 \+ prepareTheta \+ thetaRhoPiChiIotaPrepareTheta(18, A, E) \+ thetaRhoPiChiIotaPrepareTheta(19, E, A) \+ thetaRhoPiChiIotaPrepareTheta(20, A, E) \+ thetaRhoPiChiIotaPrepareTheta(21, E, A) \+ thetaRhoPiChiIotaPrepareTheta(22, A, E) \+ thetaRhoPiChiIota(23, E, A) \++#define rounds4 \+ prepareTheta \+ thetaRhoPiChiIotaPrepareTheta(20, A, E) \+ thetaRhoPiChiIotaPrepareTheta(21, E, A) \+ thetaRhoPiChiIotaPrepareTheta(22, A, E) \+ thetaRhoPiChiIota(23, E, A) \++#elif (Unrolling == 4)+#define rounds24 \+ prepareTheta \+ for(i=0; i<24; i+=4) { \+ thetaRhoPiChiIotaPrepareTheta(i , A, E) \+ thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \+ thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \+ thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \+ } \++#define rounds12 \+ prepareTheta \+ for(i=12; i<24; i+=4) { \+ thetaRhoPiChiIotaPrepareTheta(i , A, E) \+ thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \+ thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \+ thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \+ } \++#define rounds6 \+ prepareTheta \+ for(i=18; i<24; i+=2) { \+ thetaRhoPiChiIotaPrepareTheta(i , A, E) \+ thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \+ } \++#define rounds4 \+ prepareTheta \+ thetaRhoPiChiIotaPrepareTheta(20, A, E) \+ thetaRhoPiChiIotaPrepareTheta(21, E, A) \+ thetaRhoPiChiIotaPrepareTheta(22, A, E) \+ thetaRhoPiChiIota(23, E, A) \++#elif (Unrolling == 3)+#define rounds24 \+ prepareTheta \+ for(i=0; i<24; i+=3) { \+ thetaRhoPiChiIotaPrepareTheta(i , A, E) \+ thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \+ thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \+ copyStateVariables(A, E) \+ } \++#define rounds12 \+ prepareTheta \+ for(i=12; i<24; i+=3) { \+ thetaRhoPiChiIotaPrepareTheta(i , A, E) \+ thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \+ thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \+ copyStateVariables(A, E) \+ } \++#define rounds6 \+ prepareTheta \+ for(i=18; i<24; i+=3) { \+ thetaRhoPiChiIotaPrepareTheta(i , A, E) \+ thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \+ thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \+ copyStateVariables(A, E) \+ } \++#define rounds4 \+ prepareTheta \+ for(i=20; i<24; i+=2) { \+ thetaRhoPiChiIotaPrepareTheta(i , A, E) \+ thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \+ } \++#elif (Unrolling == 2)+#define rounds24 \+ prepareTheta \+ for(i=0; i<24; i+=2) { \+ thetaRhoPiChiIotaPrepareTheta(i , A, E) \+ thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \+ } \++#define rounds12 \+ prepareTheta \+ for(i=12; i<24; i+=2) { \+ thetaRhoPiChiIotaPrepareTheta(i , A, E) \+ thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \+ } \++#define rounds6 \+ prepareTheta \+ for(i=18; i<24; i+=2) { \+ thetaRhoPiChiIotaPrepareTheta(i , A, E) \+ thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \+ } \++#define rounds4 \+ prepareTheta \+ for(i=20; i<24; i+=2) { \+ thetaRhoPiChiIotaPrepareTheta(i , A, E) \+ thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \+ } \++#elif (Unrolling == 1)+#define rounds24 \+ prepareTheta \+ for(i=0; i<24; i++) { \+ thetaRhoPiChiIotaPrepareTheta(i , A, E) \+ copyStateVariables(A, E) \+ } \++#define rounds12 \+ prepareTheta \+ for(i=12; i<24; i++) { \+ thetaRhoPiChiIotaPrepareTheta(i , A, E) \+ copyStateVariables(A, E) \+ } \++#define rounds6 \+ prepareTheta \+ for(i=18; i<24; i++) { \+ thetaRhoPiChiIotaPrepareTheta(i , A, E) \+ copyStateVariables(A, E) \+ } \++#define rounds4 \+ prepareTheta \+ for(i=20; i<24; i++) { \+ thetaRhoPiChiIotaPrepareTheta(i , A, E) \+ copyStateVariables(A, E) \+ } \++#else+#error "Unrolling is not correctly specified!"+#endif++#define roundsN(__nrounds) \+ prepareTheta \+ i = 24 - (__nrounds); \+ if ((i&1) != 0) { \+ thetaRhoPiChiIotaPrepareTheta(i, A, E) \+ copyStateVariables(A, E) \+ ++i; \+ } \+ for( /* empty */; i<24; i+=2) { \+ thetaRhoPiChiIotaPrepareTheta(i , A, E) \+ thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \+ }
+ cbits/xkcp/KeccakSponge.c view
@@ -0,0 +1,111 @@+/*+The eXtended Keccak Code Package (XKCP)+https://github.com/XKCP/XKCP++Keccak, designed by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche.++Implementation by the designers, hereby denoted as "the implementer".++For more information, feedback or questions, please refer to the Keccak Team website:+https://keccak.team/++To the extent possible under law, the implementer has waived all copyright+and related or neighboring rights to the source code in this file.+http://creativecommons.org/publicdomain/zero/1.0/+*/++#include "KeccakSponge.h"++#ifdef KeccakReference+ #include "displayIntermediateValues.h"+#endif++#ifdef XKCP_has_KeccakP200+ #include "KeccakP-200-SnP.h"++ #define prefix KeccakWidth200+ #define SnP KeccakP200+ #define SnP_width 200+ #define SnP_Permute KeccakP200_Permute_18rounds+ #if defined(KeccakF200_FastLoop_supported)+ #define SnP_FastLoop_Absorb KeccakF200_FastLoop_Absorb+ #endif+ #include "KeccakSponge.inc"+ #undef prefix+ #undef SnP+ #undef SnP_width+ #undef SnP_Permute+ #undef SnP_FastLoop_Absorb+#endif++#ifdef XKCP_has_KeccakP400+ #include "KeccakP-400-SnP.h"++ #define prefix KeccakWidth400+ #define SnP KeccakP400+ #define SnP_width 400+ #define SnP_Permute KeccakP400_Permute_20rounds+ #if defined(KeccakF400_FastLoop_supported)+ #define SnP_FastLoop_Absorb KeccakF400_FastLoop_Absorb+ #endif+ #include "KeccakSponge.inc"+ #undef prefix+ #undef SnP+ #undef SnP_width+ #undef SnP_Permute+ #undef SnP_FastLoop_Absorb+#endif++#ifdef XKCP_has_KeccakP800+ #include "KeccakP-800-SnP.h"++ #define prefix KeccakWidth800+ #define SnP KeccakP800+ #define SnP_width 800+ #define SnP_Permute KeccakP800_Permute_22rounds+ #if defined(KeccakF800_FastLoop_supported)+ #define SnP_FastLoop_Absorb KeccakF800_FastLoop_Absorb+ #endif+ #include "KeccakSponge.inc"+ #undef prefix+ #undef SnP+ #undef SnP_width+ #undef SnP_Permute+ #undef SnP_FastLoop_Absorb+#endif++#ifdef XKCP_has_KeccakP1600+ #include "KeccakP-1600-SnP.h"++ #define prefix KeccakWidth1600+ #define SnP KeccakP1600+ #define SnP_width 1600+ #define SnP_Permute KeccakP1600_Permute_24rounds+ #if defined(KeccakF1600_FastLoop_supported)+ #define SnP_FastLoop_Absorb KeccakF1600_FastLoop_Absorb+ #endif+ #include "KeccakSponge.inc"+ #undef prefix+ #undef SnP+ #undef SnP_width+ #undef SnP_Permute+ #undef SnP_FastLoop_Absorb+#endif++#ifdef XKCP_has_KeccakP1600+ #include "KeccakP-1600-SnP.h"++ #define prefix KeccakWidth1600_12rounds+ #define SnP KeccakP1600+ #define SnP_width 1600+ #define SnP_Permute KeccakP1600_Permute_12rounds+ #if defined(KeccakP1600_12rounds_FastLoop_supported)+ #define SnP_FastLoop_Absorb KeccakP1600_12rounds_FastLoop_Absorb+ #endif+ #include "KeccakSponge.inc"+ #undef prefix+ #undef SnP+ #undef SnP_width+ #undef SnP_Permute+ #undef SnP_FastLoop_Absorb+#endif
+ cbits/xkcp/KeccakSponge.h view
@@ -0,0 +1,76 @@+/*+The eXtended Keccak Code Package (XKCP)+https://github.com/XKCP/XKCP++Keccak, designed by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche.++Implementation by the designers, hereby denoted as "the implementer".++For more information, feedback or questions, please refer to the Keccak Team website:+https://keccak.team/++To the extent possible under law, the implementer has waived all copyright+and related or neighboring rights to the source code in this file.+http://creativecommons.org/publicdomain/zero/1.0/+*/++#ifndef _KeccakSponge_h_+#define _KeccakSponge_h_++/* For the documentation, please follow the link: */+/* #include "KeccakSponge-documentation.h" */++#include <string.h>+#include "align.h"+#include "config.h"++#define XKCP_DeclareSpongeStructure(prefix, size, alignment) \+ ALIGN(alignment) typedef struct prefix##_SpongeInstanceStruct { \+ unsigned char state[size]; \+ unsigned int rate; \+ unsigned int byteIOIndex; \+ int squeezing; \+ } prefix##_SpongeInstance;++#define XKCP_DeclareSpongeFunctions(prefix) \+ int prefix##_Sponge(unsigned int rate, unsigned int capacity, const unsigned char *input, size_t inputByteLen, unsigned char suffix, unsigned char *output, size_t outputByteLen); \+ int prefix##_SpongeInitialize(prefix##_SpongeInstance *spongeInstance, unsigned int rate, unsigned int capacity); \+ int prefix##_SpongeAbsorb(prefix##_SpongeInstance *spongeInstance, const unsigned char *data, size_t dataByteLen); \+ int prefix##_SpongeAbsorbLastFewBits(prefix##_SpongeInstance *spongeInstance, unsigned char delimitedData); \+ int prefix##_SpongeSqueeze(prefix##_SpongeInstance *spongeInstance, unsigned char *data, size_t dataByteLen);++#ifdef XKCP_has_KeccakP200+ #include "KeccakP-200-SnP.h"+ XKCP_DeclareSpongeStructure(KeccakWidth200, KeccakP200_stateSizeInBytes, KeccakP200_stateAlignment)+ XKCP_DeclareSpongeFunctions(KeccakWidth200)+ #define XKCP_has_Sponge_Keccak_width200+#endif++#ifdef XKCP_has_KeccakP400+ #include "KeccakP-400-SnP.h"+ XKCP_DeclareSpongeStructure(KeccakWidth400, KeccakP400_stateSizeInBytes, KeccakP400_stateAlignment)+ XKCP_DeclareSpongeFunctions(KeccakWidth400)+ #define XKCP_has_Sponge_Keccak_width400+#endif++#ifdef XKCP_has_KeccakP800+ #include "KeccakP-800-SnP.h"+ XKCP_DeclareSpongeStructure(KeccakWidth800, KeccakP800_stateSizeInBytes, KeccakP800_stateAlignment)+ XKCP_DeclareSpongeFunctions(KeccakWidth800)+ #define XKCP_has_Sponge_Keccak_width800+#endif++#ifdef XKCP_has_KeccakP1600+ #include "KeccakP-1600-SnP.h"+ XKCP_DeclareSpongeStructure(KeccakWidth1600, KeccakP1600_stateSizeInBytes, KeccakP1600_stateAlignment)+ XKCP_DeclareSpongeFunctions(KeccakWidth1600)+ #define XKCP_has_Sponge_Keccak_width1600+#endif++#ifdef XKCP_has_KeccakP1600+ #include "KeccakP-1600-SnP.h"+ XKCP_DeclareSpongeStructure(KeccakWidth1600_12rounds, KeccakP1600_stateSizeInBytes, KeccakP1600_stateAlignment)+ XKCP_DeclareSpongeFunctions(KeccakWidth1600_12rounds)+#endif++#endif
+ cbits/xkcp/KeccakSponge.inc view
@@ -0,0 +1,314 @@+/*+The eXtended Keccak Code Package (XKCP)+https://github.com/XKCP/XKCP++Keccak, designed by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche.++Implementation by the designers, hereby denoted as "the implementer".++For more information, feedback or questions, please refer to the Keccak Team website:+https://keccak.team/++To the extent possible under law, the implementer has waived all copyright+and related or neighboring rights to the source code in this file.+http://creativecommons.org/publicdomain/zero/1.0/+*/++#define JOIN0(a, b) a ## b+#define JOIN(a, b) JOIN0(a, b)++#define Sponge JOIN(prefix, _Sponge)+#define SpongeInstance JOIN(prefix, _SpongeInstance)+#define SpongeInitialize JOIN(prefix, _SpongeInitialize)+#define SpongeAbsorb JOIN(prefix, _SpongeAbsorb)+#define SpongeAbsorbLastFewBits JOIN(prefix, _SpongeAbsorbLastFewBits)+#define SpongeSqueeze JOIN(prefix, _SpongeSqueeze)++#define SnP_stateSizeInBytes JOIN(SnP, _stateSizeInBytes)+#define SnP_stateAlignment JOIN(SnP, _stateAlignment)+#define SnP_StaticInitialize JOIN(SnP, _StaticInitialize)+#define SnP_Initialize JOIN(SnP, _Initialize)+#define SnP_AddByte JOIN(SnP, _AddByte)+#define SnP_AddBytes JOIN(SnP, _AddBytes)+#define SnP_ExtractBytes JOIN(SnP, _ExtractBytes)++int Sponge(unsigned int rate, unsigned int capacity, const unsigned char *input, size_t inputByteLen, unsigned char suffix, unsigned char *output, size_t outputByteLen)+{+ ALIGN(SnP_stateAlignment) unsigned char state[SnP_stateSizeInBytes];+ unsigned int partialBlock;+ const unsigned char *curInput = input;+ unsigned char *curOutput = output;+ unsigned int rateInBytes = rate/8;++ if (rate+capacity != SnP_width)+ return 1;+ if ((rate <= 0) || (rate > SnP_width) || ((rate % 8) != 0))+ return 1;+ if (suffix == 0)+ return 1;++ /* Initialize the state */+ SnP_StaticInitialize();+ SnP_Initialize(state);++ /* First, absorb whole blocks */+#ifdef SnP_FastLoop_Absorb+ if (((rateInBytes % (SnP_width/200)) == 0) && (inputByteLen >= rateInBytes)) {+ /* fast lane: whole lane rate */+ size_t j;+ j = SnP_FastLoop_Absorb(state, rateInBytes/(SnP_width/200), curInput, inputByteLen);+ curInput += j;+ inputByteLen -= j;+ }+#endif+ while(inputByteLen >= (size_t)rateInBytes) {+ #ifdef KeccakReference+ displayBytes(1, "Block to be absorbed", curInput, rateInBytes);+ #endif+ SnP_AddBytes(state, curInput, 0, rateInBytes);+ SnP_Permute(state);+ curInput += rateInBytes;+ inputByteLen -= rateInBytes;+ }++ /* Then, absorb what remains */+ partialBlock = (unsigned int)inputByteLen;+ #ifdef KeccakReference+ displayBytes(1, "Block to be absorbed (part)", curInput, partialBlock);+ #endif+ SnP_AddBytes(state, curInput, 0, partialBlock);++ /* Finally, absorb the suffix */+ #ifdef KeccakReference+ {+ unsigned char delimitedData1[1];+ delimitedData1[0] = suffix;+ displayBytes(1, "Block to be absorbed (last few bits + first bit of padding)", delimitedData1, 1);+ }+ #endif+ /* Last few bits, whose delimiter coincides with first bit of padding */+ SnP_AddByte(state, suffix, partialBlock);+ /* If the first bit of padding is at position rate-1, we need a whole new block for the second bit of padding */+ if ((suffix >= 0x80) && (partialBlock == (rateInBytes-1)))+ SnP_Permute(state);+ /* Second bit of padding */+ SnP_AddByte(state, 0x80, rateInBytes-1);+ #ifdef KeccakReference+ {+ unsigned char block[SnP_width/8];+ memset(block, 0, SnP_width/8);+ block[rateInBytes-1] = 0x80;+ displayBytes(1, "Second bit of padding", block, rateInBytes);+ }+ #endif+ SnP_Permute(state);+ #ifdef KeccakReference+ displayText(1, "--- Switching to squeezing phase ---");+ #endif++ /* First, output whole blocks */+ while(outputByteLen > (size_t)rateInBytes) {+ SnP_ExtractBytes(state, curOutput, 0, rateInBytes);+ SnP_Permute(state);+ #ifdef KeccakReference+ displayBytes(1, "Squeezed block", curOutput, rateInBytes);+ #endif+ curOutput += rateInBytes;+ outputByteLen -= rateInBytes;+ }++ /* Finally, output what remains */+ partialBlock = (unsigned int)outputByteLen;+ SnP_ExtractBytes(state, curOutput, 0, partialBlock);+ #ifdef KeccakReference+ displayBytes(1, "Squeezed block (part)", curOutput, partialBlock);+ #endif++ return 0;+}++/* ---------------------------------------------------------------- */+/* ---------------------------------------------------------------- */+/* ---------------------------------------------------------------- */++int SpongeInitialize(SpongeInstance *instance, unsigned int rate, unsigned int capacity)+{+ if (rate+capacity != SnP_width)+ return 1;+ if ((rate <= 0) || (rate > SnP_width) || ((rate % 8) != 0))+ return 1;+ SnP_StaticInitialize();+ SnP_Initialize(instance->state);+ instance->rate = rate;+ instance->byteIOIndex = 0;+ instance->squeezing = 0;++ return 0;+}++/* ---------------------------------------------------------------- */++int SpongeAbsorb(SpongeInstance *instance, const unsigned char *data, size_t dataByteLen)+{+ size_t i, j;+ unsigned int partialBlock;+ const unsigned char *curData;+ unsigned int rateInBytes = instance->rate/8;++ if (instance->squeezing)+ return 1; /* Too late for additional input */++ i = 0;+ curData = data;+ while(i < dataByteLen) {+ if ((instance->byteIOIndex == 0) && (dataByteLen >= (i + rateInBytes))) {+#ifdef SnP_FastLoop_Absorb+ /* processing full blocks first */+ if ((rateInBytes % (SnP_width/200)) == 0) {+ /* fast lane: whole lane rate */+ j = SnP_FastLoop_Absorb(instance->state, rateInBytes/(SnP_width/200), curData, dataByteLen - i);+ i += j;+ curData += j;+ }+ else {+#endif+ for(j=dataByteLen-i; j>=rateInBytes; j-=rateInBytes) {+ #ifdef KeccakReference+ displayBytes(1, "Block to be absorbed", curData, rateInBytes);+ #endif+ SnP_AddBytes(instance->state, curData, 0, rateInBytes);+ SnP_Permute(instance->state);+ curData+=rateInBytes;+ }+ i = dataByteLen - j;+#ifdef SnP_FastLoop_Absorb+ }+#endif+ }+ else {+ /* normal lane: using the message queue */+ partialBlock = (unsigned int)(dataByteLen - i);+ if (partialBlock+instance->byteIOIndex > rateInBytes)+ partialBlock = rateInBytes-instance->byteIOIndex;+ #ifdef KeccakReference+ displayBytes(1, "Block to be absorbed (part)", curData, partialBlock);+ #endif+ i += partialBlock;++ SnP_AddBytes(instance->state, curData, instance->byteIOIndex, partialBlock);+ curData += partialBlock;+ instance->byteIOIndex += partialBlock;+ if (instance->byteIOIndex == rateInBytes) {+ SnP_Permute(instance->state);+ instance->byteIOIndex = 0;+ }+ }+ }+ return 0;+}++/* ---------------------------------------------------------------- */++int SpongeAbsorbLastFewBits(SpongeInstance *instance, unsigned char delimitedData)+{+ unsigned int rateInBytes = instance->rate/8;++ if (delimitedData == 0)+ return 1;+ if (instance->squeezing)+ return 1; /* Too late for additional input */++ #ifdef KeccakReference+ {+ unsigned char delimitedData1[1];+ delimitedData1[0] = delimitedData;+ displayBytes(1, "Block to be absorbed (last few bits + first bit of padding)", delimitedData1, 1);+ }+ #endif+ /* Last few bits, whose delimiter coincides with first bit of padding */+ SnP_AddByte(instance->state, delimitedData, instance->byteIOIndex);+ /* If the first bit of padding is at position rate-1, we need a whole new block for the second bit of padding */+ if ((delimitedData >= 0x80) && (instance->byteIOIndex == (rateInBytes-1)))+ SnP_Permute(instance->state);+ /* Second bit of padding */+ SnP_AddByte(instance->state, 0x80, rateInBytes-1);+ #ifdef KeccakReference+ {+ unsigned char block[SnP_width/8];+ memset(block, 0, SnP_width/8);+ block[rateInBytes-1] = 0x80;+ displayBytes(1, "Second bit of padding", block, rateInBytes);+ }+ #endif+ SnP_Permute(instance->state);+ instance->byteIOIndex = 0;+ instance->squeezing = 1;+ #ifdef KeccakReference+ displayText(1, "--- Switching to squeezing phase ---");+ #endif+ return 0;+}++/* ---------------------------------------------------------------- */++int SpongeSqueeze(SpongeInstance *instance, unsigned char *data, size_t dataByteLen)+{+ size_t i, j;+ unsigned int partialBlock;+ unsigned int rateInBytes = instance->rate/8;+ unsigned char *curData;++ if (!instance->squeezing)+ SpongeAbsorbLastFewBits(instance, 0x01);++ i = 0;+ curData = data;+ while(i < dataByteLen) {+ if ((instance->byteIOIndex == rateInBytes) && (dataByteLen >= (i + rateInBytes))) {+ for(j=dataByteLen-i; j>=rateInBytes; j-=rateInBytes) {+ SnP_Permute(instance->state);+ SnP_ExtractBytes(instance->state, curData, 0, rateInBytes);+ #ifdef KeccakReference+ displayBytes(1, "Squeezed block", curData, rateInBytes);+ #endif+ curData+=rateInBytes;+ }+ i = dataByteLen - j;+ }+ else {+ /* normal lane: using the message queue */+ if (instance->byteIOIndex == rateInBytes) {+ SnP_Permute(instance->state);+ instance->byteIOIndex = 0;+ }+ partialBlock = (unsigned int)(dataByteLen - i);+ if (partialBlock+instance->byteIOIndex > rateInBytes)+ partialBlock = rateInBytes-instance->byteIOIndex;+ i += partialBlock;++ SnP_ExtractBytes(instance->state, curData, instance->byteIOIndex, partialBlock);+ #ifdef KeccakReference+ displayBytes(1, "Squeezed block (part)", curData, partialBlock);+ #endif+ curData += partialBlock;+ instance->byteIOIndex += partialBlock;+ }+ }+ return 0;+}++/* ---------------------------------------------------------------- */++#undef Sponge+#undef SpongeInstance+#undef SpongeInitialize+#undef SpongeAbsorb+#undef SpongeAbsorbLastFewBits+#undef SpongeSqueeze+#undef SnP_stateSizeInBytes+#undef SnP_stateAlignment+#undef SnP_StaticInitialize+#undef SnP_Initialize+#undef SnP_AddByte+#undef SnP_AddBytes+#undef SnP_ExtractBytes
+ cbits/xkcp/SimpleFIPS202.c view
@@ -0,0 +1,48 @@+/*+The eXtended Keccak Code Package (XKCP)+https://github.com/XKCP/XKCP++Keccak, designed by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche.++Implementation by Gilles Van Assche, hereby denoted as "the implementer".++For more information, feedback or questions, please refer to the Keccak Team website:+https://keccak.team/++To the extent possible under law, the implementer has waived all copyright+and related or neighboring rights to the source code in this file.+http://creativecommons.org/publicdomain/zero/1.0/+*/++#include "KeccakSponge.h"+#include "SimpleFIPS202.h"++int SHAKE128(unsigned char *output, size_t outputByteLen, const unsigned char *input, size_t inputByteLen)+{+ return KeccakWidth1600_Sponge(1344, 256, input, inputByteLen, 0x1F, output, outputByteLen);+}++int SHAKE256(unsigned char *output, size_t outputByteLen, const unsigned char *input, size_t inputByteLen)+{+ return KeccakWidth1600_Sponge(1088, 512, input, inputByteLen, 0x1F, output, outputByteLen);+}++int SHA3_224(unsigned char *output, const unsigned char *input, size_t inputByteLen)+{+ return KeccakWidth1600_Sponge(1152, 448, input, inputByteLen, 0x06, output, 224/8);+}++int SHA3_256(unsigned char *output, const unsigned char *input, size_t inputByteLen)+{+ return KeccakWidth1600_Sponge(1088, 512, input, inputByteLen, 0x06, output, 256/8);+}++int SHA3_384(unsigned char *output, const unsigned char *input, size_t inputByteLen)+{+ return KeccakWidth1600_Sponge( 832, 768, input, inputByteLen, 0x06, output, 384/8);+}++int SHA3_512(unsigned char *output, const unsigned char *input, size_t inputByteLen)+{+ return KeccakWidth1600_Sponge(576, 1024, input, inputByteLen, 0x06, output, 512/8);+}
+ cbits/xkcp/SimpleFIPS202.h view
@@ -0,0 +1,79 @@+/*+The eXtended Keccak Code Package (XKCP)+https://github.com/XKCP/XKCP++Keccak, designed by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche.++Implementation by Gilles Van Assche, hereby denoted as "the implementer".++For more information, feedback or questions, please refer to the Keccak Team website:+https://keccak.team/++To the extent possible under law, the implementer has waived all copyright+and related or neighboring rights to the source code in this file.+http://creativecommons.org/publicdomain/zero/1.0/+*/++#ifndef _SimpleFIPS202_h_+#define _SimpleFIPS202_h_++#include "config.h"+#ifdef XKCP_has_KeccakP1600++#include <string.h>++/** Implementation of the SHAKE128 extendable output function (XOF) [FIPS 202].+ * @param output Pointer to the output buffer.+ * @param outputByteLen The desired number of output bytes.+ * @param input Pointer to the input message.+ * @param inputByteLen The length of the input message in bytes.+ * @return 0 if successful, 1 otherwise.+ */+int SHAKE128(unsigned char *output, size_t outputByteLen, const unsigned char *input, size_t inputByteLen);++/** Implementation of the SHAKE256 extendable output function (XOF) [FIPS 202].+ * @param output Pointer to the output buffer.+ * @param outputByteLen The desired number of output bytes.+ * @param input Pointer to the input message.+ * @param inputByteLen The length of the input message in bytes.+ * @return 0 if successful, 1 otherwise.+ */+int SHAKE256(unsigned char *output, size_t outputByteLen, const unsigned char *input, size_t inputByteLen);++/** Implementation of SHA3-224 [FIPS 202].+ * @param output Pointer to the output buffer (28 bytes).+ * @param input Pointer to the input message.+ * @param inputByteLen The length of the input message in bytes.+ * @return 0 if successful, 1 otherwise.+ */+int SHA3_224(unsigned char *output, const unsigned char *input, size_t inputByteLen);++/** Implementation of SHA3-256 [FIPS 202].+ * @param output Pointer to the output buffer (32 bytes).+ * @param input Pointer to the input message.+ * @param inputByteLen The length of the input message in bytes.+ * @return 0 if successful, 1 otherwise.+ */+int SHA3_256(unsigned char *output, const unsigned char *input, size_t inputByteLen);++/** Implementation of SHA3-384 [FIPS 202].+ * @param output Pointer to the output buffer (48 bytes).+ * @param input Pointer to the input message.+ * @param inputByteLen The length of the input message in bytes.+ * @return 0 if successful, 1 otherwise.+ */+int SHA3_384(unsigned char *output, const unsigned char *input, size_t inputByteLen);++/** Implementation of SHA3-512 [FIPS 202].+ * @param output Pointer to the output buffer (64 bytes).+ * @param input Pointer to the input message.+ * @param inputByteLen The length of the input message in bytes.+ * @return 0 if successful, 1 otherwise.+ */+int SHA3_512(unsigned char *output, const unsigned char *input, size_t inputByteLen);++#else+#error This requires an implementation of Keccak-p[1600]+#endif++#endif
+ cbits/xkcp/SnP-Relaned.h view
@@ -0,0 +1,141 @@+/*+The eXtended Keccak Code Package (XKCP)+https://github.com/XKCP/XKCP++Implementation by Gilles Van Assche and Ronny Van Keer, hereby denoted as "the implementer".++For more information, feedback or questions, please refer to the Keccak Team website:+https://keccak.team/++To the extent possible under law, the implementer has waived all copyright+and related or neighboring rights to the source code in this file.+http://creativecommons.org/publicdomain/zero/1.0/++---++This file contains macros that help implement a permutation in a SnP-compatible way.+It converts an implementation that implement state input/output functions+in a lane-oriented fashion (i.e., using SnP_AddLanes() and SnP_AddBytesInLane,+and similarly for Overwite, Extract and ExtractAndAdd) to the byte-oriented SnP.+Please refer to SnP-documentation.h for more details.+*/++#ifndef _SnP_Relaned_h_+#define _SnP_Relaned_h_++#define SnP_AddBytes(state, data, offset, length, SnP_AddLanes, SnP_AddBytesInLane, SnP_laneLengthInBytes) \+ { \+ if ((offset) == 0) { \+ SnP_AddLanes(state, data, (length)/SnP_laneLengthInBytes); \+ SnP_AddBytesInLane(state, \+ (length)/SnP_laneLengthInBytes, \+ (data)+((length)/SnP_laneLengthInBytes)*SnP_laneLengthInBytes, \+ 0, \+ (length)%SnP_laneLengthInBytes); \+ } \+ else { \+ unsigned int _sizeLeft = (length); \+ unsigned int _lanePosition = (offset)/SnP_laneLengthInBytes; \+ unsigned int _offsetInLane = (offset)%SnP_laneLengthInBytes; \+ const unsigned char *_curData = (data); \+ while(_sizeLeft > 0) { \+ unsigned int _bytesInLane = SnP_laneLengthInBytes - _offsetInLane; \+ if (_bytesInLane > _sizeLeft) \+ _bytesInLane = _sizeLeft; \+ SnP_AddBytesInLane(state, _lanePosition, _curData, _offsetInLane, _bytesInLane); \+ _sizeLeft -= _bytesInLane; \+ _lanePosition++; \+ _offsetInLane = 0; \+ _curData += _bytesInLane; \+ } \+ } \+ }++#define SnP_OverwriteBytes(state, data, offset, length, SnP_OverwriteLanes, SnP_OverwriteBytesInLane, SnP_laneLengthInBytes) \+ { \+ if ((offset) == 0) { \+ SnP_OverwriteLanes(state, data, (length)/SnP_laneLengthInBytes); \+ SnP_OverwriteBytesInLane(state, \+ (length)/SnP_laneLengthInBytes, \+ (data)+((length)/SnP_laneLengthInBytes)*SnP_laneLengthInBytes, \+ 0, \+ (length)%SnP_laneLengthInBytes); \+ } \+ else { \+ unsigned int _sizeLeft = (length); \+ unsigned int _lanePosition = (offset)/SnP_laneLengthInBytes; \+ unsigned int _offsetInLane = (offset)%SnP_laneLengthInBytes; \+ const unsigned char *_curData = (data); \+ while(_sizeLeft > 0) { \+ unsigned int _bytesInLane = SnP_laneLengthInBytes - _offsetInLane; \+ if (_bytesInLane > _sizeLeft) \+ _bytesInLane = _sizeLeft; \+ SnP_OverwriteBytesInLane(state, _lanePosition, _curData, _offsetInLane, _bytesInLane); \+ _sizeLeft -= _bytesInLane; \+ _lanePosition++; \+ _offsetInLane = 0; \+ _curData += _bytesInLane; \+ } \+ } \+ }++#define SnP_ExtractBytes(state, data, offset, length, SnP_ExtractLanes, SnP_ExtractBytesInLane, SnP_laneLengthInBytes) \+ { \+ if ((offset) == 0) { \+ SnP_ExtractLanes(state, data, (length)/SnP_laneLengthInBytes); \+ SnP_ExtractBytesInLane(state, \+ (length)/SnP_laneLengthInBytes, \+ (data)+((length)/SnP_laneLengthInBytes)*SnP_laneLengthInBytes, \+ 0, \+ (length)%SnP_laneLengthInBytes); \+ } \+ else { \+ unsigned int _sizeLeft = (length); \+ unsigned int _lanePosition = (offset)/SnP_laneLengthInBytes; \+ unsigned int _offsetInLane = (offset)%SnP_laneLengthInBytes; \+ unsigned char *_curData = (data); \+ while(_sizeLeft > 0) { \+ unsigned int _bytesInLane = SnP_laneLengthInBytes - _offsetInLane; \+ if (_bytesInLane > _sizeLeft) \+ _bytesInLane = _sizeLeft; \+ SnP_ExtractBytesInLane(state, _lanePosition, _curData, _offsetInLane, _bytesInLane); \+ _sizeLeft -= _bytesInLane; \+ _lanePosition++; \+ _offsetInLane = 0; \+ _curData += _bytesInLane; \+ } \+ } \+ }++#define SnP_ExtractAndAddBytes(state, input, output, offset, length, SnP_ExtractAndAddLanes, SnP_ExtractAndAddBytesInLane, SnP_laneLengthInBytes) \+ { \+ if ((offset) == 0) { \+ SnP_ExtractAndAddLanes(state, input, output, (length)/SnP_laneLengthInBytes); \+ SnP_ExtractAndAddBytesInLane(state, \+ (length)/SnP_laneLengthInBytes, \+ (input)+((length)/SnP_laneLengthInBytes)*SnP_laneLengthInBytes, \+ (output)+((length)/SnP_laneLengthInBytes)*SnP_laneLengthInBytes, \+ 0, \+ (length)%SnP_laneLengthInBytes); \+ } \+ else { \+ unsigned int _sizeLeft = (length); \+ unsigned int _lanePosition = (offset)/SnP_laneLengthInBytes; \+ unsigned int _offsetInLane = (offset)%SnP_laneLengthInBytes; \+ const unsigned char *_curInput = (input); \+ unsigned char *_curOutput = (output); \+ while(_sizeLeft > 0) { \+ unsigned int _bytesInLane = SnP_laneLengthInBytes - _offsetInLane; \+ if (_bytesInLane > _sizeLeft) \+ _bytesInLane = _sizeLeft; \+ SnP_ExtractAndAddBytesInLane(state, _lanePosition, _curInput, _curOutput, _offsetInLane, _bytesInLane); \+ _sizeLeft -= _bytesInLane; \+ _lanePosition++; \+ _offsetInLane = 0; \+ _curInput += _bytesInLane; \+ _curOutput += _bytesInLane; \+ } \+ } \+ }++#endif
+ cbits/xkcp/align.h view
@@ -0,0 +1,33 @@+/*+The eXtended Keccak Code Package (XKCP)+https://github.com/XKCP/XKCP++Implementation by Gilles Van Assche and Ronny Van Keer, hereby denoted as "the implementer".++For more information, feedback or questions, please refer to the Keccak Team website:+https://keccak.team/++To the extent possible under law, the implementer has waived all copyright+and related or neighboring rights to the source code in this file.+http://creativecommons.org/publicdomain/zero/1.0/+*/++#ifndef _align_h_+#define _align_h_++/* on Mac OS-X and possibly others, ALIGN(x) is defined in param.h, and -Werror chokes on the redef. */+#ifdef ALIGN+#undef ALIGN+#endif++#if defined(__GNUC__)+#define ALIGN(x) __attribute__ ((aligned(x)))+#elif defined(_MSC_VER)+#define ALIGN(x) __declspec(align(x))+#elif defined(__ARMCC_VERSION)+#define ALIGN(x) __align(x)+#else+#define ALIGN(x)+#endif++#endif
+ cbits/xkcp/brg_endian.h view
@@ -0,0 +1,143 @@+/*+ ---------------------------------------------------------------------------+ Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.++ LICENSE TERMS++ The redistribution and use of this software (with or without changes)+ is allowed without the payment of fees or royalties provided that:++ 1. source code distributions include the above copyright notice, this+ list of conditions and the following disclaimer;++ 2. binary distributions include the above copyright notice, this list+ of conditions and the following disclaimer in their documentation;++ 3. the name of the copyright holder is not used to endorse products+ built using this software without specific written permission.++ DISCLAIMER++ This software is provided 'as is' with no explicit or implied warranties+ in respect of its properties, including, but not limited to, correctness+ and/or fitness for purpose.+ ---------------------------------------------------------------------------+ Issue Date: 20/12/2007+ Changes for ARM 9/9/2010+*/++#ifndef _BRG_ENDIAN_H+#define _BRG_ENDIAN_H++#define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */+#define IS_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */++#if 0+/* Include files where endian defines and byteswap functions may reside */+#if defined( __sun )+# include <sys/isa_defs.h>+#elif defined( __FreeBSD__ ) || defined( __OpenBSD__ ) || defined( __NetBSD__ )+# include <sys/endian.h>+#elif defined( BSD ) && ( BSD >= 199103 ) || defined( __APPLE__ ) || \+ defined( __CYGWIN32__ ) || defined( __DJGPP__ ) || defined( __osf__ )+# include <machine/endian.h>+#elif defined( __linux__ ) || defined( __GNUC__ ) || defined( __GNU_LIBRARY__ )+# if !defined( __MINGW32__ ) && !defined( _AIX )+# include <endian.h>+# if !defined( __BEOS__ )+# include <byteswap.h>+# endif+# endif+#endif+#endif++/* Now attempt to set the define for platform byte order using any */+/* of the four forms SYMBOL, _SYMBOL, __SYMBOL & __SYMBOL__, which */+/* seem to encompass most endian symbol definitions */++#if defined( BIG_ENDIAN ) && defined( LITTLE_ENDIAN )+# if defined( BYTE_ORDER ) && BYTE_ORDER == BIG_ENDIAN+# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN+# elif defined( BYTE_ORDER ) && BYTE_ORDER == LITTLE_ENDIAN+# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN+# endif+#elif defined( BIG_ENDIAN )+# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN+#elif defined( LITTLE_ENDIAN )+# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN+#endif++#if defined( _BIG_ENDIAN ) && defined( _LITTLE_ENDIAN )+# if defined( _BYTE_ORDER ) && _BYTE_ORDER == _BIG_ENDIAN+# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN+# elif defined( _BYTE_ORDER ) && _BYTE_ORDER == _LITTLE_ENDIAN+# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN+# endif+#elif defined( _BIG_ENDIAN )+# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN+#elif defined( _LITTLE_ENDIAN )+# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN+#endif++#if defined( __BIG_ENDIAN ) && defined( __LITTLE_ENDIAN )+# if defined( __BYTE_ORDER ) && __BYTE_ORDER == __BIG_ENDIAN+# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN+# elif defined( __BYTE_ORDER ) && __BYTE_ORDER == __LITTLE_ENDIAN+# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN+# endif+#elif defined( __BIG_ENDIAN )+# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN+#elif defined( __LITTLE_ENDIAN )+# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN+#endif++#if defined( __BIG_ENDIAN__ ) && defined( __LITTLE_ENDIAN__ )+# if defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __BIG_ENDIAN__+# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN+# elif defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __LITTLE_ENDIAN__+# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN+# endif+#elif defined( __BIG_ENDIAN__ )+# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN+#elif defined( __LITTLE_ENDIAN__ )+# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN+#endif++/* if the platform byte order could not be determined, then try to */+/* set this define using common machine defines */+#if !defined(PLATFORM_BYTE_ORDER)++#if defined( __alpha__ ) || defined( __alpha ) || defined( i386 ) || \+ defined( __i386__ ) || defined( _M_I86 ) || defined( _M_IX86 ) || \+ defined( __OS2__ ) || defined( sun386 ) || defined( __TURBOC__ ) || \+ defined( vax ) || defined( vms ) || defined( VMS ) || \+ defined( __VMS ) || defined( _M_X64 )+# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN++#elif defined( AMIGA ) || defined( applec ) || defined( __AS400__ ) || \+ defined( _CRAY ) || defined( __hppa ) || defined( __hp9000 ) || \+ defined( ibm370 ) || defined( mc68000 ) || defined( m68k ) || \+ defined( __MRC__ ) || defined( __MVS__ ) || defined( __MWERKS__ ) || \+ defined( sparc ) || defined( __sparc) || defined( SYMANTEC_C ) || \+ defined( __VOS__ ) || defined( __TIGCC__ ) || defined( __TANDEM ) || \+ defined( THINK_C ) || defined( __VMCMS__ ) || defined( _AIX ) || \+ defined( __s390__ ) || defined( __s390x__ ) || defined( __zarch__ )+# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN++#elif defined(__arm__)+# ifdef __BIG_ENDIAN+# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN+# else+# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN+# endif+#elif 1 /* **** EDIT HERE IF NECESSARY **** */+# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN+#elif 0 /* **** EDIT HERE IF NECESSARY **** */+# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN+#else+# error Please edit lines 132 or 134 in brg_endian.h to set the platform byte order+#endif++#endif++#endif
+ cbits/xkcp/config.h view
@@ -0,0 +1,5 @@+/* File generated by ToTargetConfigFile.xsl */++#define XKCP_has_Sponge_Keccak+#define XKCP_has_FIPS202+#define XKCP_has_KeccakP1600
+ cbits/xkcp/test.c view
@@ -0,0 +1,10 @@++#include "KeccakHash.h"+#include <stdio.h>++int main()+{+ printf("sizeof(Keccak_HashInstance) = %ld\n", sizeof(Keccak_HashInstance));+ return 0;+}+
+ images/accelerate-logo-text-v.png view
binary file changed (absent → 207024 bytes)
+ images/fusion_example_1.png view
binary file changed (absent → 4716 bytes)
+ images/fusion_example_2.png view
binary file changed (absent → 8506 bytes)
+ images/fusion_example_3.png view
binary file changed (absent → 7735 bytes)
+ src/Crypto/Hash/XKCP.hs view
@@ -0,0 +1,184 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE UnliftedFFITypes #-}+{-# OPTIONS_GHC -fobject-code #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Crypto.Hash.XKCP+-- Copyright : [2016..2022] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Crypto.Hash.XKCP (++ SHA3_256,+ hash, hashlazy,++) where++import Control.Monad+import Data.Word+import Foreign.C.Types+import Foreign.Ptr+import Language.Haskell.TH.Syntax+import System.IO.Unsafe++import qualified Data.ByteString as S+import qualified Data.ByteString.Lazy as L+import qualified Data.ByteString.Lazy.Internal as L+import qualified Data.ByteString.Unsafe as B++import GHC.Exts+import GHC.Base+import GHC.Word+import GHC.Show+++-- | SHA3 (256 bits) cryptographic hash digest+--+data SHA3_256 = SHA3_256 ByteArray#++instance Show SHA3_256 where+ show (SHA3_256 ba#) =+ let go !i# =+ case i# <# 32# of+ 0# -> []+ _ -> let w8# = indexWord8Array# ba# i#+ w# = word8ToWord# w8#+ n# = quotWord# w# 16##+ d# = remWord# w# 16##+ x = intToDigit (I# (word2Int# n#))+ y = intToDigit (I# (word2Int# d#))+ in+ x : y : go (i# +# 1#)+ in+ go 0#++instance Eq SHA3_256 where+ SHA3_256 ba1# == SHA3_256 ba2# =+ case reallyUnsafePtrEquality# (unsafeCoerce# ba1#) (unsafeCoerce# ba2#) of+ 1# -> True+ _ -> case (compareByteArrays# ba1# 0# ba2# 0# 32#) of+ 0# -> True+ _ -> False++instance Ord SHA3_256 where+ compare (SHA3_256 ba1#) (SHA3_256 ba2#) =+ let go !i# =+ case i# <# 32# of+ 0# -> EQ+ _ -> case W8# (indexWord8Array# ba1# i#) `compare` W8# (indexWord8Array# ba2# i#) of+ EQ -> go (i# +# 1#)+ r -> r+ in+ go 0#++#if !MIN_VERSION_base(4,16,0)+{-# INLINE word8ToWord# #-}+word8ToWord# :: Word# -> Word#+word8ToWord# w# = w#+#endif++-- | Hash a strict 'S.ByteString' into a digest+--+hash :: S.ByteString -> SHA3_256+hash bs = unsafePerformIO $!+ B.unsafeUseAsCStringLen bs $ \(p, n) -> keccak_Hash_SHA3_256 (castPtr p) n+++-- | Hash a lazy 'L.ByteString' into a digest+--+hashlazy :: L.ByteString -> SHA3_256+hashlazy lbs = unsafePerformIO $! do+ s <- keccak_HashInitialize_SHA3_256+ let go L.Empty = keccak_HashFinal_SHA3_256 s+ go (L.Chunk c cs) = do+ B.unsafeUseAsCStringLen c $ \(p, n) -> keccak_HashUpdate_SHA3_256 s (castPtr p) n+ go cs+ go lbs+++-- Internals+-- -----------------------------------------------------------------------------++keccak_Hash_SHA3_256 :: Ptr Word8 -> Int -> IO SHA3_256+keccak_Hash_SHA3_256 ptr len =+ IO $ \s0 ->+ case newByteArray# 32# s0 of { (# s1, mba# #) ->+ case c_sha3_256 mba# ptr (fromIntegral len) of { IO c_sha3_256# ->+ case c_sha3_256# s1 of { (# s2, _ #) ->+ case unsafeFreezeByteArray# mba# s2 of { (# s3, hash_val# #) ->+ (# s3, SHA3_256 hash_val# #)+ }}}}+++data Keccak_HashInstance = Keccak_HashInstance (MutableByteArray# RealWorld)++-- See: KeccakHash.h for magic numbers+--+keccak_HashInitialize_SHA3_256 :: IO Keccak_HashInstance+keccak_HashInitialize_SHA3_256 =+ IO $ \s0 ->+ case newByteArray# 224# s0 of { (# s1, hash_instance# #) ->+ case c_keccak_hash_initialise hash_instance# 1088 512 256 0x06 of { IO c_keccak_hash_initialise# ->+ case c_keccak_hash_initialise# s1 of { (# s2, _ #) ->+ (# s2, Keccak_HashInstance hash_instance# #)+ }}}++keccak_HashUpdate_SHA3_256 :: Keccak_HashInstance -> Ptr Word8 -> Int -> IO ()+keccak_HashUpdate_SHA3_256 (Keccak_HashInstance hash_instance#) ptr len =+ void $ c_keccak_hash_update hash_instance# ptr (fromIntegral len * 8)++keccak_HashFinal_SHA3_256 :: Keccak_HashInstance -> IO SHA3_256+keccak_HashFinal_SHA3_256 (Keccak_HashInstance hash_instance#) =+ IO $ \s0 ->+ case newByteArray# 32# s0 of { (# s1, mba# #) ->+ case c_keccak_hash_final hash_instance# mba# of { IO c_keccak_hash_final# ->+ case c_keccak_hash_final# s1 of { (# s2, _ #) ->+ case unsafeFreezeByteArray# mba# s2 of { (# s3, hash_val# #) ->+ (# s3, SHA3_256 hash_val# #)+ }}}}++-- SEE: [HLS and GHC IDE]+--+#ifndef __GHCIDE__++foreign import ccall unsafe "SHA3_256" c_sha3_256 :: MutableByteArray# RealWorld -> Ptr Word8 -> CSize -> IO CInt+foreign import ccall unsafe "Keccak_HashInitialize" c_keccak_hash_initialise :: MutableByteArray# RealWorld -> CUInt -> CUInt -> CUInt -> CUChar -> IO CInt+foreign import ccall unsafe "Keccak_HashUpdate" c_keccak_hash_update :: MutableByteArray# RealWorld -> Ptr Word8 -> CSize -> IO CInt+foreign import ccall unsafe "Keccak_HashFinal" c_keccak_hash_final :: MutableByteArray# RealWorld -> MutableByteArray# RealWorld -> IO CInt++#else++c_sha3_256 :: Ptr Word8 -> Ptr Word8 -> CSize -> IO CInt+c_sha3_256 = undefined++c_keccak_hash_initialise :: MutableByteArray# RealWorld -> CUInt -> CUInt -> CUInt -> CUChar -> IO CInt+c_keccak_hash_initialise = undefined++c_keccak_hash_update :: MutableByteArray# RealWorld -> Ptr Word8 -> CSize -> IO CInt+c_keccak_hash_update = undefined++c_keccak_hash_final :: MutableByteArray# RealWorld -> MutableByteArray# RealWorld -> IO CInt+c_keccak_hash_final = undefined++#endif+++-- SEE: [linking to .c files]+--+runQ $ do+ addForeignFilePath LangC "cbits/xkcp/KeccakHash.c"+ addForeignFilePath LangC "cbits/xkcp/KeccakSponge.c"+ addForeignFilePath LangC "cbits/xkcp/SimpleFIPS202.c"+ addForeignFilePath LangC "cbits/xkcp/KeccakP-1600-opt64.c"+ return []+
+ src/Data/Array/Accelerate.hs view
@@ -0,0 +1,691 @@+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+-- |+-- Module : Data.Array.Accelerate+-- Description : The Accelerate standard prelude+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- @Data.Array.Accelerate@ defines an embedded language of array computations+-- for high-performance computing in Haskell. Computations on multi-dimensional,+-- regular arrays are expressed in the form of parameterised collective+-- operations such as maps, reductions, and permutations. These computations are+-- online compiled and can be executed on a range of architectures.+--+-- [/Abstract interface:/]+--+-- The types representing array computations are only exported abstractly;+-- client code can generate array computations and submit them for execution,+-- but it cannot inspect these computations. This is to allow for more+-- flexibility for future extensions of this library.+--+-- [/Stratified language:/]+--+-- Accelerate distinguishes the types of collective operations 'Acc' from the+-- type of scalar operations 'Exp' to achieve a stratified language. Collective+-- operations comprise many scalar computations that are executed in parallel,+-- but scalar computations /can not/ contain collective operations. This+-- separation excludes /nested, irregular/ data-parallelism statically; instead,+-- Accelerate is limited to /flat data-parallelism/ involving only regular,+-- multi-dimensional arrays.+--+-- [/Optimisations:/]+--+-- Accelerate uses a number of scalar and array optimisations, including+-- /array fusion/, in order to improve the performance of programs. Fusing+-- a program entails combining successive traversals (loops) over an array into+-- a single traversal, which reduces memory traffic and eliminates intermediate+-- arrays.+--+-- [/Code execution:/]+--+-- Several backends are available which can be used to evaluate accelerate+-- programs:+--+-- * "Data.Array.Accelerate.Interpreter": simple interpreter in Haskell as a+-- reference implementation defining the semantics of the Accelerate language+--+-- * <http://hackage.haskell.org/package/accelerate-llvm-native accelerate-llvm-native>:+-- implementation supporting parallel execution on multicore CPUs (e.g. x86).+--+-- * <http://hackage.haskell.org/package/accelerate-llvm-ptx accelerate-llvm-ptx>:+-- implementation supporting parallel execution on CUDA-capable NVIDIA GPUs.+--+-- [/Examples:/]+--+-- * A short tutorial-style example for generating a <https://en.wikipedia.org/wiki/Mandelbrot_set Mandelbrot set>:+-- http://www.acceleratehs.org/examples/mandelbrot.html+--+-- * The <http://hackage.haskell.org/package/accelerate-examples accelerate-examples>+-- package demonstrates a range of computational kernels and several complete+-- applications:+--+-- - Implementation of the <https://en.wikipedia.org/wiki/Canny_edge_detector canny edge detector>+-- - Interactive <https://en.wikipedia.org/wiki/Mandelbrot_set Mandelbrot set> generator+-- - <https://en.wikipedia.org/wiki/N-body N-body simulation> of gravitational attraction between large bodies+-- - Implementation of the <https://en.wikipedia.org/wiki/Pagerank PageRank> algorithm+-- - A simple, real-time, interactive <https://en.wikipedia.org/wiki/Ray_tracing ray tracer>.+-- - A particle based simulation of stable fluid flows+-- - A cellular automaton simulation+-- - A "password recovery" tool, for dictionary attacks on MD5 hashes.+--+-- <<http://i.imgur.com/5Tbsp1j.jpg accelerate-mandelbrot>>+-- <<http://i.imgur.com/7ohhKm9.jpg accelerate-ray>>+--+-- * <http://hackage.haskell.org/package/lulesh-accelerate lulesh-accelerate>+-- is an implementation of the Livermore Unstructured Lagrangian Explicit+-- Shock Hydrodynamics (LULESH) application. LULESH is representative of+-- typical hydrodynamics codes, although simplified and hard-coded to solve+-- the Sedov blast problem on an unstructured hexahedron mesh.+--+-- - For more information on LULESH: <https://codesign.llnl.gov/lulesh.php>.+--+-- <<https://i.imgur.com/bIkODKd.jpg>>+--+-- [/Starting a new project:/]+--+-- Accelerate and its associated packages are available on both Hackage and+-- Stackage. A project template is available to help create a new projects using+-- the <https://docs.haskellstack.org/en/stable/README/ stack> build tool. To+-- create a new project using the template:+--+-- > stack new PROJECT_NAME https://github.com/AccelerateHS/accelerate/raw/stable/accelerate.hsfiles+--+-- [/Additional components:/]+--+-- * <https://hackage.haskell.org/package/accelerate-io accelerate-io>: Fast+-- conversion between Accelerate arrays and other formats (e.g. Repa, Vector).+--+-- * <https://hackage.haskell.org/package/accelerate-fft accelerate-fft>: Fast+-- Fourier transform, with FFI bindings to optimised implementations.+--+-- * <https://hackage.haskell.org/package/accelerate-blas accelerate-blas>: BLAS+-- and LAPACK operations, with FFI bindings to optimised implementations.+--+-- * <https://hackage.haskell.org/package/accelerate-bignum accelerate-bignum>:+-- Fixed-width large integer arithmetic.+--+-- * <https://hackage.haskell.org/package/containers-accelerate containers-accelerate>:+-- Container types for use with Accelerate.+--+-- * <https://hackage.haskell.org/package/hashable-accelerate hashable-accelerate>:+-- Class for types which can be converted to a value.+--+-- * <https://hackage.haskell.org/package/colour-accelerate colour-accelerate>:+-- Colour representations in Accelerate (RGB, sRGB, HSV, and HSL).+--+-- * <https://hackage.haskell.org/package/gloss-accelerate gloss-accelerate>:+-- Generate <https://hackage.haskell.org/package/gloss gloss> pictures from+-- Accelerate.+--+-- * <https://hackage.haskell.org/package/gloss-raster-accelerate gloss-raster-accelerate>:+-- Parallel rendering of raster images and animations.+--+-- * <https://hackage.haskell.org/package/lens-accelerate lens-accelerate>:+-- <https://hackage.haskell.org/package/lens Lens> operators for Accelerate+-- types.+--+-- * <https://hackage.haskell.org/package/linear-accelerate linear-accelerate>:+-- <https://hackage.haskell.org/package/linear Linear> vector space types for+-- Accelerate.+--+-- * <https://hackage.haskell.org/package/mwc-random-accelerate mwc-random-accelerate>:+-- Generate Accelerate arrays filled with high-quality pseudorandom numbers.+--+-- [/Contact:/]+--+-- * Mailing list for both use and development discussion:+--+-- * <mailto:accelerate-haskell@googlegroups.com>+-- * http://groups.google.com/group/accelerate-haskell+--+-- * Bug reports: https://github.com/AccelerateHS/accelerate/issues+--+-- * Maintainer: Trevor L. McDonell: <mailto:trevor.mcdonell@gmail.com>+--+-- [/Tip:/]+--+-- Accelerate tends to stress GHC's garbage collector, so it helps to increase+-- the default GC allocation sizes. This can be done when running an executable+-- by specifying RTS options on the command line, for example:+--+-- > ./foo +RTS -A64M -n2M -RTS+--+-- You can make these settings the default by adding the following @ghc-options@+-- to your @.cabal@ file or similar:+--+-- > ghc-options: -with-rtsopts=-n2M -with-rtsopts=-A64M+--+-- To specify RTS options you will also need to compile your program with @-rtsopts@.+--++module Data.Array.Accelerate (++ -- * The /Accelerate/ Array Language+ -- ** Embedded array computations+ Acc,++ -- *** Arrays+ Array, Arrays, Scalar, Vector, Matrix, Segments,++ -- *** Array elements+ Elt,++ -- *** Array shapes & indices+ -- $shapes_and_indices+ --+ Z(..), (:.)(..),+ DIM0, DIM1, DIM2, DIM3, DIM4, DIM5, DIM6, DIM7, DIM8, DIM9,+ Shape, Slice(..), All(..), Any(..),+ -- Split(..), Divide(..), Division(..),++ -- ** Array access+ -- *** Element indexing+ (!), (!!), the,++ -- *** Shape information+ null, length, shape, size, shapeSize,++ -- ** Construction+ -- *** Introduction+ use, unit,++ -- *** Initialisation+ generate, fill,++ -- *** Enumeration+ enumFromN, enumFromStepN,++ -- *** Concatenation+ (++), concatOn,++ -- *** Expansion+ expand,++ -- ** Composition+ -- *** Flow control+ (?|), acond, awhile,+ IfThenElse(..),++ -- *** Controlling execution+ (>->),+ compute,++ -- ** Element-wise operations+ -- *** Indexing+ indexed,++ -- *** Mapping+ map, imap,++ -- *** Zipping+ zipWith, zipWith3, zipWith4, zipWith5, zipWith6, zipWith7, zipWith8, zipWith9,+ izipWith, izipWith3, izipWith4, izipWith5, izipWith6, izipWith7, izipWith8, izipWith9,+ zip, zip3, zip4, zip5, zip6, zip7, zip8, zip9,++ -- *** Unzipping+ unzip, unzip3, unzip4, unzip5, unzip6, unzip7, unzip8, unzip9,++ -- ** Modifying Arrays+ -- *** Shape manipulation+ reshape, flatten,++ -- *** Replication+ replicate,++ -- *** Extracting sub-arrays+ slice,+ init, tail, take, drop, slit,+ initOn, tailOn, takeOn, dropOn, slitOn,++ -- *** Permutations+ -- **** Forward permutation (scatter)+ permute,+ scatter,++ -- **** Backward permutation (gather)+ backpermute,+ gather,++ -- **** Specialised permutations+ reverse, transpose,+ reverseOn, transposeOn,++ -- *** Filtering+ filter, compact,++ -- ** Folding+ fold, fold1, foldAll, fold1All,++ -- *** Segmented reductions+ foldSeg, fold1Seg,+ foldSeg', fold1Seg',++ -- *** Specialised reductions+ all, any, and, or, sum, product, minimum, maximum,++ -- ** Scans (prefix sums)+ scanl, scanl1, scanl', scanr, scanr1, scanr',+ prescanl, postscanl, prescanr, postscanr,++ -- *** Segmented scans+ scanlSeg, scanl1Seg, scanl'Seg, prescanlSeg, postscanlSeg,+ scanrSeg, scanr1Seg, scanr'Seg, prescanrSeg, postscanrSeg,++ -- ** Stencils+ stencil, stencil2,++ -- *** Stencil specification+ Stencil, Boundary,+ clamp, mirror, wrap, function,++ -- *** Common stencil patterns+ Stencil3, Stencil5, Stencil7, Stencil9,+ Stencil3x3, Stencil5x3, Stencil3x5, Stencil5x5,+ Stencil3x3x3, Stencil5x3x3, Stencil3x5x3, Stencil3x3x5, Stencil5x5x3, Stencil5x3x5,+ Stencil3x5x5, Stencil5x5x5,++ -- -- ** Sequence operations+ -- collect,++ -- -- ** Sequence producers+ -- streamIn, toSeq, generateSeq,++ -- -- ** Sequence transducers+ -- mapSeq, zipWithSeq, scanSeq,++ -- -- ** Sequence consumers+ -- foldSeq, foldSeqFlatten, fromSeq, fromSeqElems, fromSeqShapes,+ -- toSeqInner, toSeqOuter2, toSeqOuter3,++ -- ---------------------------------------------------------------------------+ -- * The /Accelerate/ Expression Language+ -- ** Scalar data types+ Exp,++ -- ** SIMD vectors+ Vec, VecElt,++ -- ** Type classes+ -- *** Basic type classes+ Eq(..),+ Ord(..), Ordering(..), pattern LT_, pattern EQ_, pattern GT_,+ Enum, succ, pred,+ Bounded, minBound, maxBound,+ -- Functor(..), (<$>), ($>), void,+ -- Monad(..),++ -- *** Numeric type classes+ Num, (+), (-), (*), negate, abs, signum, fromInteger,+ Integral, quot, rem, div, mod, quotRem, divMod,+ Rational(..),+ Fractional, (/), recip, fromRational,+ Floating, pi, sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh, exp, sqrt, log, (**), logBase,+ RealFrac(..), div', mod', divMod',+ RealFloat(..),++ -- *** Numeric conversion classes+ FromIntegral(..),+ ToFloating(..),++ -- ** Lifting and Unlifting+ -- $lifting_and_unlifting+ --+ Lift(..), Unlift(..),+ lift1, lift2, lift3,+ ilift1, ilift2, ilift3,++ -- ** Pattern synonyms+ -- $pattern_synonyms+ --+ pattern Pattern,+ pattern T2, pattern T3, pattern T4, pattern T5, pattern T6,+ pattern T7, pattern T8, pattern T9, pattern T10, pattern T11,+ pattern T12, pattern T13, pattern T14, pattern T15, pattern T16,++ pattern Z_, pattern Ix, pattern (::.), pattern All_, pattern Any_,+ pattern I0, pattern I1, pattern I2, pattern I3, pattern I4,+ pattern I5, pattern I6, pattern I7, pattern I8, pattern I9,++ pattern Vec2, pattern V2,+ pattern Vec3, pattern V3,+ pattern Vec4, pattern V4,+ pattern Vec8, pattern V8,+ pattern Vec16, pattern V16,++ mkPattern, mkPatterns,++ -- ** Scalar operations+ -- *** Introduction+ constant,++ -- *** Tuples+ fst, afst, snd, asnd, curry, uncurry,++ -- *** Flow control+ (?), match, cond, while, iterate,++ -- *** Scalar reduction+ sfoldl,++ -- *** Logical operations+ (&&), (||), not,++ -- *** Numeric operations+ subtract, even, odd, gcd, lcm, (^), (^^),++ -- *** Shape manipulation+ index0, index1, unindex1, index2, unindex2, index3, unindex3,+ indexHead, indexTail,+ toIndex, fromIndex,+ intersect,++ -- *** Conversions+ ord, chr, boolToInt, bitcast,++ -- ---------------------------------------------------------------------------+ -- * Foreign Function Interface (FFI)+ foreignAcc,+ foreignExp,++ -- ---------------------------------------------------------------------------+ -- * Plain arrays+ -- ** Operations+ arrayRank, arrayShape, arraySize, arrayReshape,+ indexArray, linearIndexArray,++ -- ** Getting data in+ -- $getting_data_in++ -- *** Function+ fromFunction,+ fromFunctionM,++ -- *** Lists+ fromList, toList,++ -- ---------------------------------------------------------------------------+ -- * Useful re-exports+ (.), ($), (&), flip, error, undefined, const, otherwise,+ Show, Generic, HasCallStack,+ fromString, -- -XOverloadedStrings+ fromListN, -- -XOverloadedLists++ -- ---------------------------------------------------------------------------+ -- Types+ Int, Int8, Int16, Int32, Int64,+ Word, Word8, Word16, Word32, Word64,+ Half(..), Float, Double,+ Bool(..), pattern True_, pattern False_,+ Maybe(..), pattern Nothing_, pattern Just_,+ Either(..), pattern Left_, pattern Right_,+ Char,++ CFloat, CDouble,+ CShort, CUShort, CInt, CUInt, CLong, CULong, CLLong, CULLong,+ CChar, CSChar, CUChar,++) where++import Data.Array.Accelerate.Classes.Bounded+import Data.Array.Accelerate.Classes.Enum+import Data.Array.Accelerate.Classes.Eq+import Data.Array.Accelerate.Classes.Floating+import Data.Array.Accelerate.Classes.Fractional+import Data.Array.Accelerate.Classes.FromIntegral+import Data.Array.Accelerate.Classes.Integral+import Data.Array.Accelerate.Classes.Num+import Data.Array.Accelerate.Classes.Ord+import Data.Array.Accelerate.Classes.Rational+import Data.Array.Accelerate.Classes.RealFloat+import Data.Array.Accelerate.Classes.RealFrac+import Data.Array.Accelerate.Classes.ToFloating+import Data.Array.Accelerate.Data.Either+import Data.Array.Accelerate.Data.Maybe+import Data.Array.Accelerate.Language+import Data.Array.Accelerate.Pattern+import Data.Array.Accelerate.Pattern.TH+import Data.Array.Accelerate.Prelude+import Data.Array.Accelerate.Pretty () -- show instances+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Array ( Array, Arrays, Scalar, Vector, Matrix, Segments, fromFunction, fromFunctionM, toList, fromList )+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Sugar.Shape hiding ( size, toIndex, fromIndex, intersect )+import Data.Array.Accelerate.Sugar.Vec+import Data.Array.Accelerate.Type+import Data.Primitive.Vec+import qualified Data.Array.Accelerate.Sugar.Array as S+import qualified Data.Array.Accelerate.Sugar.Shape as S++import Data.Function ( (&) )+import Prelude ( (.), ($), Char, Show, flip, undefined, error, const, otherwise )++import GHC.Exts ( fromListN, fromString )+import GHC.Generics ( Generic )+import GHC.Stack++-- $setup+-- >>> :seti -XTypeOperators+-- >>> import Data.Array.Accelerate+++-- Renamings+-- ---------+--+-- FIXME: these all need to go into a separate module for separate importing!++-- rename as '(!)' is already used by the EDSL for indexing++-- | Array indexing in plain Haskell code.+--+{-# INLINE indexArray #-}+indexArray :: (Shape sh, Elt e) => Array sh e -> sh -> e+indexArray = (S.!)++-- | Linear array indexing in plain Haskell code.+--+{-# INLINE linearIndexArray #-}+linearIndexArray :: Elt e => Array sh e -> Int -> e+linearIndexArray = (S.!!)++-- | Rank of an array (as a plain Haskell value)+--+{-# INLINE arrayRank #-}+arrayRank :: forall sh e. Shape sh => Array sh e -> Int+arrayRank _ = S.rank @sh++-- | Shape of an array (as a plain Haskell value)+--+{-# INLINE arrayShape #-}+arrayShape :: Shape sh => Array sh e -> sh+arrayShape = S.shape+-- rename as 'shape' is already used by the EDSL to query an array's shape++-- | Total number of elements in an array (as a plain Haskell value)+--+{-# INLINE arraySize #-}+arraySize :: Shape sh => Array sh e -> Int+arraySize = S.size . S.shape++-- | Change the shape of an array without altering its contents. The 'arraySize'+-- of the source and result arrays must be identical.+--+{-# INLINE arrayReshape #-}+arrayReshape :: (Shape sh, Shape sh') => sh -> Array sh' e -> Array sh e+arrayReshape = S.reshape+++-- Named documentation chunks+-- --------------------------++-- $shapes_and_indices+--+-- Operations in Accelerate take the form of collective operations over arrays+-- of the type @'Array' sh e@. Much like the+-- <https://hackage.haskell.org/package/repa repa> library, arrays in Accelerate+-- are parameterised by a type /sh/ which determines the dimensionality of the+-- array and the type of each index, as well as the type of each element of the+-- array /e/.+--+-- Shape types, and multidimensional array indices, are built like lists+-- (technically; a heterogeneous snoc-list) using 'Z' and (':.'):+--+-- > data Z = Z+-- > data tail :. head = tail :. head+--+-- Here, the constructor 'Z' corresponds to a shape with zero dimension (or+-- a 'Scalar' array, with one element) and is used to mark the end of the list.+-- The constructor (':.') adds additional dimensions to the shape on the+-- /right/. For example:+--+-- > Z :. Int+--+-- is the type of the shape of a one-dimensional array ('Vector') indexed by an+-- 'Int', while:+--+-- > Z :. Int :. Int+--+-- is the type of the shape of a two-dimensional array (a matrix) indexed by an+-- 'Int' in each dimension.+--+-- This style is used to construct both the /type/ and /value/ of the shape. For+-- example, to define the shape of a vector of ten elements:+--+-- > sh :: Z :. Int+-- > sh = Z :. 10+--+-- Note that the right-most index is the /innermost/ dimension. This is the+-- fastest-varying index, and corresponds to the elements of the array which are+-- adjacent in memory.+--++-- $lifting_and_unlifting+--+-- A value of type 'Int' is a plain Haskell value (unlifted), whereas an @Exp+-- Int@ is a /lifted/ value, that is, an integer lifted into the domain of+-- embedded expressions (an abstract syntax tree in disguise). Both 'Acc' and+-- 'Exp' are /surface types/ into which values may be lifted. Lifting plain+-- array and scalar surface types is equivalent to 'use' and 'constant'+-- respectively.+--+-- In general an @Exp Int@ cannot be unlifted into an 'Int', because the actual+-- number will not be available until a later stage of execution (e.g. during+-- GPU execution, when 'run' is called). Similarly an @Acc array@ can not be+-- unlifted to a vanilla 'array'; you should instead 'run' the expression with+-- a specific backend to evaluate it.+--+-- Lifting and unlifting are also used to pack and unpack an expression into and+-- out of constructors such as tuples, respectively. Those expressions, at+-- runtime, will become tuple dereferences. For example:+--+-- >>> let sh = constant (Z :. 4 :. 10) :: Exp DIM2+-- >>> let Z :. x :. y = unlift sh :: Z :. Exp Int :. Exp Int+-- >>> let t = lift (x,y) :: Exp (Int, Int)+--+-- >>> let xs = use $ fromList (Z:.10) [0..] :: Acc (Vector Int)+-- >>> let ys = use $ fromList (Z:.3:.4) [0..] :: Acc (Matrix Int)+-- >>> let r = (xs,ys) :: (Acc (Vector Int), Acc (Matrix Int))+-- >>> let r' = lift r :: Acc (Vector Int, Matrix Int)+--+-- [/Note:/]+--+-- Use of 'lift' and 'unlift' is probably the most common source of type errors+-- when using Accelerate. GHC is not very good at determining the type the+-- [un]lifted expression should have, so it is often necessary to add an+-- explicit type signature.+--+-- For example, in the following GHC will complain that it can not determine the+-- type of 'y', even though we might expect that to be obvious (or for it to not+-- care):+--+-- > fst :: (Elt a, Elt b) => Exp (a,b) -> Exp a+-- > fst t = let (x,y) = unlift t in x+--+-- The fix is to instead add an explicit type signature. Note that this requires+-- the @ScopedTypeVariables@ extension and to bring the type variables @a@ and+-- @b@ into scope with @forall@:+--+-- > fst :: forall a b. (Elt a, Elt b) => Exp (a,b) -> Exp a+-- > fst t = let (x,y) = unlift t :: (Exp a, Exp b)+-- > in x+--+-- For an alternative, see section <#pattern_synonyms Pattern synonyms>.+--++-- $pattern_synonyms+-- #pattern_synonyms#+--+-- Pattern synonyms can be used as an alternative to 'lift' and 'unlift' for+-- constructing and accessing data types isomorphic to simple product (tuple)+-- types.+--+-- In contrast to 'lift' and 'unlift' however, pattern synonyms do /not/ require+-- these data types to be fully polymorphic.+--+-- For example, let's say we have regular Haskell data type representing a point+-- in two-dimensional space:+--+-- > data Point = Point_ Float Float+-- > deriving (Generic, Elt)+--+-- Here we derive instance an instance of the 'Elt' class (via 'Generic'),+-- so that this data type can be used within scalar Accelerate expressions+--+-- In order to access the individual fields of the data constructor from within+-- an Accelerate expression, we define the following pattern synonym:+--+-- > pattern Point :: Exp Float -> Exp Float -> Exp Point+-- > pattern Point x y = Pattern (x,y)+--+-- Notice how we named the constructor of our original datatype with a trailing+-- underscore, so that we can use the undecorated name for the pattern synonym;+-- these must have unique names.+--+-- In essence, the 'Pattern' pattern is really telling GHC how to treat our @Point@+-- type as a regular pair for use in Accelerate code. The pattern can then be+-- used on both the left and right hand side of an expression:+--+-- > addPoint :: Exp Point -> Exp Point -> Exp Point+-- > addPoint (Point x1 y1) (Point x2 y2) = Point (x1+x2) (y1+y2)+--+-- Similarly, we can define pattern synonyms for values in 'Acc'. We can also+-- use record syntax to generate field accessors, if we desire:+--+-- > data SparseVector a = SparseVector_ (Vector Int) (Vector a)+-- > deriving (Generic, Arrays)+-- >+-- > pattern SparseVector :: Elt a => Acc (Vector Int) -> Acc (Vector a) -> Acc (SparseVector a)+-- > pattern SparseVector { indices, values } = Pattern (indices, values)+--+-- For convenience, we have defined several pattern synonyms for regular tuples,+-- 'T2' (for pairs), 'T3' (for triples), and so on up to 'T16'. These are+-- occasionally more convenient to use than 'lift' and 'unlift' together with+-- the regular tuple syntax.+--+-- @since 1.3.0.0+--++-- $getting_data_in+-- #getting_data_in#+--+-- We often need to generate or read data into an 'Array' so that it can be used+-- in Accelerate. The base @accelerate@ library includes basic conversions+-- routines, but additional functionality is contained in external+-- libraries, for example:+--+-- * <https://hackage.haskell.org/package/accelerate-io accelerate-io>: For copying data directly from raw 'Foreign.Ptr.Ptr's+-- * <https://hackage.haskell.org/package/accelerate-io-array accelerate-io-array>: immutable arrays+-- * <https://hackage.haskell.org/package/accelerate-io-bmp accelerate-io-bmp>: uncompressed BMP image files+-- * <https://hackage.haskell.org/package/accelerate-io-bytestring accelerate-io-bytestring>: compact, immutable binary data+-- * <https://hackage.haskell.org/package/accelerate-io-cereal accelerate-io-cereal>: binary serialisation of arrays using <https://hackage.haskell.org/package/cereal cereal>+-- * <https://hackage.haskell.org/package/accelerate-io-JuicyPixels accelerate-io-JuicyPixels>: images in various pixel formats+-- * <https://hackage.haskell.org/package/accelerate-io-repa accelerate-io-repa>: another Haskell library for high-performance parallel arrays+-- * <https://hackage.haskell.org/package/accelerate-io-serialise accelerate-io-serialise>: binary serialisation of arrays using <https://hackage.haskell.org/package/serialise serialise>+-- * <https://hackage.haskell.org/package/accelerate-io-vector accelerate-io-vector>: efficient boxed and unboxed one-dimensional arrays+--+
+ src/Data/Array/Accelerate/AST.hs view
@@ -0,0 +1,1457 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.AST+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- /Scalar versus collective operations/+--+-- The embedded array processing language is a two-level language. It+-- combines a language of scalar expressions and functions with a language of+-- collective array operations. Scalar expressions are used to compute+-- arguments for collective operations and scalar functions are used to+-- parametrise higher-order, collective array operations. The two-level+-- structure, in particular, ensures that collective operations cannot be+-- parametrised with collective operations; hence, we are following a flat+-- data-parallel model. The collective operations manipulate+-- multi-dimensional arrays whose shape is explicitly tracked in their types.+-- In fact, collective operations cannot produce any values other than+-- multi-dimensional arrays; when they yield a scalar, this is in the form of+-- a 0-dimensional, singleton array. Similarly, scalar expression can -as+-- their name indicates- only produce tuples of scalar, but not arrays.+--+-- There are, however, two expression forms that take arrays as arguments. As+-- a result scalar and array expressions are recursively dependent. As we+-- cannot and don't want to compute arrays in the middle of scalar+-- computations, array computations will always be hoisted out of scalar+-- expressions. So that this is always possible, these array expressions may+-- not contain any free scalar variables. To express that condition in the+-- type structure, we use separate environments for scalar and array variables.+--+-- /Programs/+--+-- Collective array programs comprise closed expressions of array operations.+-- There is no explicit sharing in the initial AST form, but sharing is+-- introduced subsequently by common subexpression elimination and floating+-- of array computations.+--+-- /Functions/+--+-- The array expression language is first-order and only provides limited+-- control structures to ensure that it can be efficiently executed on+-- compute-acceleration hardware, such as GPUs. To restrict functions to+-- first-order, we separate function abstraction from the main expression+-- type. Functions are represented using de Bruijn indices.+--+-- /Parametric and ad-hoc polymorphism/+--+-- The array language features paramatric polymophism (e.g., pairing and+-- projections) as well as ad-hoc polymorphism (e.g., arithmetic operations).+-- All ad-hoc polymorphic constructs include reified dictionaries (c.f.,+-- module 'Types'). Reified dictionaries also ensure that constants+-- (constructor 'Const') are representable on compute acceleration hardware.+--+-- The AST contains both reified dictionaries and type class constraints.+-- Type classes are used for array-related functionality that is uniformly+-- available for all supported types. In contrast, reified dictionaries are+-- used for functionality that is only available for certain types, such as+-- arithmetic operations.+--++module Data.Array.Accelerate.AST (++ -- * Internal AST+ -- ** Array computations+ Afun, PreAfun, OpenAfun, PreOpenAfun(..),+ Acc, OpenAcc(..), PreOpenAcc(..), Direction(..), Message(..),+ ALeftHandSide, ArrayVar, ArrayVars,++ -- ** Scalar expressions+ ELeftHandSide, ExpVar, ExpVars, expVars,+ Fun, OpenFun(..),+ Exp, OpenExp(..),+ Boundary(..),+ PrimConst(..),+ PrimFun(..),+ PrimBool,+ PrimMaybe,++ -- ** Extracting type information+ HasArraysR(..), arrayR,+ expType,+ primConstType,+ primFunType,++ -- ** Normal-form+ NFDataAcc,+ rnfOpenAfun, rnfPreOpenAfun,+ rnfOpenAcc, rnfPreOpenAcc,+ rnfALeftHandSide,+ rnfArrayVar,+ rnfOpenFun,+ rnfOpenExp,+ rnfELeftHandSide,+ rnfExpVar,+ rnfBoundary,+ rnfConst,+ rnfPrimConst,+ rnfPrimFun,++ -- ** Template Haskell+ LiftAcc,+ liftPreOpenAfun,+ liftPreOpenAcc,+ liftALeftHandSide,+ liftArrayVar,+ liftOpenFun,+ liftOpenExp,+ liftELeftHandSide,+ liftExpVar,+ liftBoundary,+ liftPrimConst,+ liftPrimFun,+ liftMessage,++ -- ** Miscellaneous+ formatPreAccOp,+ formatExpOp,++) where++import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.AST.LeftHandSide+import Data.Array.Accelerate.AST.Var+import Data.Array.Accelerate.Error+import Data.Array.Accelerate.Representation.Array+import Data.Array.Accelerate.Representation.Elt+import Data.Array.Accelerate.Representation.Shape+import Data.Array.Accelerate.Representation.Slice+import Data.Array.Accelerate.Representation.Stencil+import Data.Array.Accelerate.Representation.Tag+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Representation.Vec+import Data.Array.Accelerate.Sugar.Foreign+import Data.Array.Accelerate.Type+import Data.Primitive.Vec++import Control.DeepSeq ( NFData(..) )+import Data.Kind+import Data.Maybe+import Data.Text ( Text )+import Data.Text.Lazy.Builder+import Formatting+import Language.Haskell.TH.Extra ( CodeQ )+import qualified Language.Haskell.TH.Extra as TH+import qualified Language.Haskell.TH.Syntax as TH++import GHC.TypeLits+++-- Array expressions+-- -----------------++-- | Function abstraction over parametrised array computations+--+data PreOpenAfun acc aenv t where+ Abody :: acc aenv t -> PreOpenAfun acc aenv t+ Alam :: ALeftHandSide a aenv aenv' -> PreOpenAfun acc aenv' t -> PreOpenAfun acc aenv (a -> t)++-- Function abstraction over vanilla open array computations+--+type OpenAfun = PreOpenAfun OpenAcc++-- | Parametrised array-computation function without free array variables+--+type PreAfun acc = PreOpenAfun acc ()++-- | Vanilla array-computation function without free array variables+--+type Afun = OpenAfun ()++-- Vanilla open array computations+--+newtype OpenAcc aenv t = OpenAcc (PreOpenAcc OpenAcc aenv t)++-- | Closed array expression aka an array program+--+type Acc = OpenAcc ()++-- Types for array binders+--+type ALeftHandSide = LeftHandSide ArrayR+type ArrayVar = Var ArrayR+type ArrayVars aenv = Vars ArrayR aenv++-- Bool is not a primitive type+type PrimBool = TAG+type PrimMaybe a = (TAG, ((), a))++-- Trace messages+data Message a where+ Message :: (a -> String) -- embedded show+ -> Maybe (CodeQ (a -> String)) -- lifted version of show, for TH+ -> Text+ -> Message a++-- | Collective array computations parametrised over array variables+-- represented with de Bruijn indices.+--+-- * Scalar functions and expressions embedded in well-formed array+-- computations cannot contain free scalar variable indices. The latter+-- cannot be bound in array computations, and hence, cannot appear in any+-- well-formed program.+--+-- * The let-form is used to represent the sharing discovered by common+-- subexpression elimination as well as to control evaluation order. (We+-- need to hoist array expressions out of scalar expressions---they occur+-- in scalar indexing and in determining an arrays shape.)+--+-- The data type is parameterised over the representation types (not the+-- surface type).+--+-- We use a non-recursive variant parametrised over the recursive closure,+-- to facilitate attribute calculation in the backend.+--+data PreOpenAcc (acc :: Type -> Type -> Type) aenv a where++ -- Local non-recursive binding to represent sharing and demand+ -- explicitly. Note this is an eager binding!+ --+ Alet :: ALeftHandSide bndArrs aenv aenv'+ -> acc aenv bndArrs -- bound expression+ -> acc aenv' bodyArrs -- the bound expression scope+ -> PreOpenAcc acc aenv bodyArrs++ -- Variable bound by a 'Let', represented by a de Bruijn index+ --+ Avar :: ArrayVar aenv (Array sh e)+ -> PreOpenAcc acc aenv (Array sh e)++ -- Tuples of arrays+ --+ Apair :: acc aenv as+ -> acc aenv bs+ -> PreOpenAcc acc aenv (as, bs)++ Anil :: PreOpenAcc acc aenv ()++ -- Array-function application.+ --+ -- The array function is not closed at the core level because we need access+ -- to free variables introduced by 'run1' style evaluators. See Issue#95.+ --+ Apply :: ArraysR arrs2+ -> PreOpenAfun acc aenv (arrs1 -> arrs2)+ -> acc aenv arrs1+ -> PreOpenAcc acc aenv arrs2++ -- Apply a backend-specific foreign function to an array, with a pure+ -- Accelerate version for use with other backends. The functions must be+ -- closed.+ --+ Aforeign :: Foreign asm+ => ArraysR bs+ -> asm (as -> bs) -- The foreign function for a given backend+ -> PreAfun acc (as -> bs) -- Fallback implementation(s)+ -> acc aenv as -- Arguments to the function+ -> PreOpenAcc acc aenv bs++ -- If-then-else for array-level computations+ --+ Acond :: Exp aenv PrimBool+ -> acc aenv arrs+ -> acc aenv arrs+ -> PreOpenAcc acc aenv arrs++ -- Value-recursion for array-level computations+ --+ Awhile :: PreOpenAfun acc aenv (arrs -> Scalar PrimBool) -- continue iteration while true+ -> PreOpenAfun acc aenv (arrs -> arrs) -- function to iterate+ -> acc aenv arrs -- initial value+ -> PreOpenAcc acc aenv arrs++ Atrace :: Message arrs1+ -> acc aenv arrs1+ -> acc aenv arrs2+ -> PreOpenAcc acc aenv arrs2++ -- Array inlet. Triggers (possibly) asynchronous host->device transfer if+ -- necessary.+ --+ Use :: ArrayR (Array sh e)+ -> Array sh e+ -> PreOpenAcc acc aenv (Array sh e)++ -- Capture a scalar (or a tuple of scalars) in a singleton array+ --+ Unit :: TypeR e+ -> Exp aenv e+ -> PreOpenAcc acc aenv (Scalar e)++ -- Change the shape of an array without altering its contents.+ -- Precondition (this may not be checked!):+ --+ -- > dim == size dim'+ --+ Reshape :: ShapeR sh+ -> Exp aenv sh -- new shape+ -> acc aenv (Array sh' e) -- array to be reshaped+ -> PreOpenAcc acc aenv (Array sh e)++ -- Construct a new array by applying a function to each index.+ --+ Generate :: ArrayR (Array sh e)+ -> Exp aenv sh -- output shape+ -> Fun aenv (sh -> e) -- representation function+ -> PreOpenAcc acc aenv (Array sh e)++ -- Hybrid map/backpermute, where we separate the index and value+ -- transformations.+ --+ Transform :: ArrayR (Array sh' b)+ -> Exp aenv sh' -- dimension of the result+ -> Fun aenv (sh' -> sh) -- index permutation function+ -> Fun aenv (a -> b) -- function to apply at each element+ -> acc aenv (Array sh a) -- source array+ -> PreOpenAcc acc aenv (Array sh' b)++ -- Replicate an array across one or more dimensions as given by the first+ -- argument+ --+ Replicate :: SliceIndex slix sl co sh -- slice type specification+ -> Exp aenv slix -- slice value specification+ -> acc aenv (Array sl e) -- data to be replicated+ -> PreOpenAcc acc aenv (Array sh e)++ -- Index a sub-array out of an array; i.e., the dimensions not indexed+ -- are returned whole+ --+ Slice :: SliceIndex slix sl co sh -- slice type specification+ -> acc aenv (Array sh e) -- array to be indexed+ -> Exp aenv slix -- slice value specification+ -> PreOpenAcc acc aenv (Array sl e)++ -- Apply the given unary function to all elements of the given array+ --+ Map :: TypeR e'+ -> Fun aenv (e -> e')+ -> acc aenv (Array sh e)+ -> PreOpenAcc acc aenv (Array sh e')++ -- Apply a given binary function pairwise to all elements of the given+ -- arrays. The length of the result is the length of the shorter of the+ -- two argument arrays.+ --+ ZipWith :: TypeR e3+ -> Fun aenv (e1 -> e2 -> e3)+ -> acc aenv (Array sh e1)+ -> acc aenv (Array sh e2)+ -> PreOpenAcc acc aenv (Array sh e3)++ -- Fold along the innermost dimension of an array with a given+ -- /associative/ function.+ --+ Fold :: Fun aenv (e -> e -> e) -- combination function+ -> Maybe (Exp aenv e) -- default value+ -> acc aenv (Array (sh, Int) e) -- folded array+ -> PreOpenAcc acc aenv (Array sh e)++ -- Segmented fold along the innermost dimension of an array with a given+ -- /associative/ function+ --+ FoldSeg :: IntegralType i+ -> Fun aenv (e -> e -> e) -- combination function+ -> Maybe (Exp aenv e) -- default value+ -> acc aenv (Array (sh, Int) e) -- folded array+ -> acc aenv (Segments i) -- segment descriptor+ -> PreOpenAcc acc aenv (Array (sh, Int) e)++ -- Haskell-style scan of a linear array with a given+ -- /associative/ function and optionally an initial element+ -- (which does not need to be the neutral of the associative operations)+ -- If no initial value is given, this is a scan1+ --+ Scan :: Direction+ -> Fun aenv (e -> e -> e) -- combination function+ -> Maybe (Exp aenv e) -- initial value+ -> acc aenv (Array (sh, Int) e)+ -> PreOpenAcc acc aenv (Array (sh, Int) e)++ -- Like 'Scan', but produces a rightmost (in case of a left-to-right scan)+ -- fold value and an array with the same length as the input array (the+ -- fold value would be the rightmost element in a Haskell-style scan)+ --+ Scan' :: Direction+ -> Fun aenv (e -> e -> e) -- combination function+ -> Exp aenv e -- initial value+ -> acc aenv (Array (sh, Int) e)+ -> PreOpenAcc acc aenv (Array (sh, Int) e, Array sh e)++ -- Generalised forward permutation is characterised by a permutation function+ -- that determines for each element of the source array where it should go in+ -- the output. The permutation can be between arrays of varying shape and+ -- dimensionality.+ --+ -- Other characteristics of the permutation function 'f':+ --+ -- 1. 'f' is a (morally) partial function: only the elements of the domain+ -- for which the function evaluates to a 'Just' value are mapped in the+ -- result. Other elements are dropped.+ --+ -- 2. 'f' is not surjective: positions in the target array need not be+ -- picked up by the permutation function, so the target array must first+ -- be initialised from an array of default values.+ --+ -- 3. 'f' is not injective: distinct elements of the domain may map to the+ -- same position in the target array. In this case the combination+ -- function is used to combine elements, which needs to be /associative/+ -- and /commutative/.+ --+ Permute :: Fun aenv (e -> e -> e) -- combination function+ -> acc aenv (Array sh' e) -- default values+ -> Fun aenv (sh -> PrimMaybe sh') -- permutation function+ -> acc aenv (Array sh e) -- source array+ -> PreOpenAcc acc aenv (Array sh' e)++ -- Generalised multi-dimensional backwards permutation; the permutation can+ -- be between arrays of varying shape; the permutation function must be total+ --+ Backpermute :: ShapeR sh'+ -> Exp aenv sh' -- dimensions of the result+ -> Fun aenv (sh' -> sh) -- permutation function+ -> acc aenv (Array sh e) -- source array+ -> PreOpenAcc acc aenv (Array sh' e)++ -- Map a stencil over an array. In contrast to 'map', the domain of+ -- a stencil function is an entire /neighbourhood/ of each array element.+ --+ Stencil :: StencilR sh e stencil+ -> TypeR e'+ -> Fun aenv (stencil -> e') -- stencil function+ -> Boundary aenv (Array sh e) -- boundary condition+ -> acc aenv (Array sh e) -- source array+ -> PreOpenAcc acc aenv (Array sh e')++ -- Map a binary stencil over an array.+ --+ Stencil2 :: StencilR sh a stencil1+ -> StencilR sh b stencil2+ -> TypeR c+ -> Fun aenv (stencil1 -> stencil2 -> c) -- stencil function+ -> Boundary aenv (Array sh a) -- boundary condition #1+ -> acc aenv (Array sh a) -- source array #1+ -> Boundary aenv (Array sh b) -- boundary condition #2+ -> acc aenv (Array sh b) -- source array #2+ -> PreOpenAcc acc aenv (Array sh c)+++data Direction = LeftToRight | RightToLeft+ deriving Eq+++-- | Vanilla boundary condition specification for stencil operations+--+data Boundary aenv t where+ -- Clamp coordinates to the extent of the array+ Clamp :: Boundary aenv t++ -- Mirror coordinates beyond the array extent+ Mirror :: Boundary aenv t++ -- Wrap coordinates around on each dimension+ Wrap :: Boundary aenv t++ -- Use a constant value for outlying coordinates+ Constant :: e+ -> Boundary aenv (Array sh e)++ -- Apply the given function to outlying coordinates+ Function :: Fun aenv (sh -> e)+ -> Boundary aenv (Array sh e)+++-- Embedded expressions+-- --------------------++-- | Vanilla open function abstraction+--+data OpenFun env aenv t where+ Body :: OpenExp env aenv t -> OpenFun env aenv t+ Lam :: ELeftHandSide a env env' -> OpenFun env' aenv t -> OpenFun env aenv (a -> t)++-- | Vanilla function without free scalar variables+--+type Fun = OpenFun ()++-- | Vanilla expression without free scalar variables+--+type Exp = OpenExp ()++-- Types for scalar bindings+--+type ELeftHandSide = LeftHandSide ScalarType+type ExpVar = Var ScalarType+type ExpVars env = Vars ScalarType env++expVars :: ExpVars env t -> OpenExp env aenv t+expVars TupRunit = Nil+expVars (TupRsingle var) = Evar var+expVars (TupRpair v1 v2) = expVars v1 `Pair` expVars v2+++-- | Vanilla open expressions using de Bruijn indices for variables ranging+-- over tuples of scalars and arrays of tuples. All code, except Cond, is+-- evaluated eagerly. N-tuples are represented as nested pairs.+--+-- The data type is parametrised over the representation type (not the+-- surface types).+--+data OpenExp env aenv t where++ -- Local binding of a scalar expression+ Let :: ELeftHandSide bnd_t env env'+ -> OpenExp env aenv bnd_t+ -> OpenExp env' aenv body_t+ -> OpenExp env aenv body_t++ -- Variable index, ranging _only_ over scalars+ Evar :: ExpVar env t+ -> OpenExp env aenv t++ -- Apply a backend-specific foreign function+ Foreign :: Foreign asm+ => TypeR y+ -> asm (x -> y) -- foreign function+ -> Fun () (x -> y) -- alternate implementation (for other backends)+ -> OpenExp env aenv x+ -> OpenExp env aenv y++ -- Tuples+ Pair :: OpenExp env aenv t1+ -> OpenExp env aenv t2+ -> OpenExp env aenv (t1, t2)++ Nil :: OpenExp env aenv ()++ -- SIMD vectors+ VecPack :: KnownNat n+ => VecR n s tup+ -> OpenExp env aenv tup+ -> OpenExp env aenv (Vec n s)++ VecUnpack :: KnownNat n+ => VecR n s tup+ -> OpenExp env aenv (Vec n s)+ -> OpenExp env aenv tup++ -- Array indices & shapes+ IndexSlice :: SliceIndex slix sl co sh+ -> OpenExp env aenv slix+ -> OpenExp env aenv sh+ -> OpenExp env aenv sl++ IndexFull :: SliceIndex slix sl co sh+ -> OpenExp env aenv slix+ -> OpenExp env aenv sl+ -> OpenExp env aenv sh++ -- Shape and index conversion+ ToIndex :: ShapeR sh+ -> OpenExp env aenv sh -- shape of the array+ -> OpenExp env aenv sh -- index into the array+ -> OpenExp env aenv Int++ FromIndex :: ShapeR sh+ -> OpenExp env aenv sh -- shape of the array+ -> OpenExp env aenv Int -- index into linear representation+ -> OpenExp env aenv sh++ -- Case statement+ Case :: OpenExp env aenv TAG+ -> [(TAG, OpenExp env aenv b)] -- list of equations+ -> Maybe (OpenExp env aenv b) -- default case+ -> OpenExp env aenv b++ -- Conditional expression (non-strict in 2nd and 3rd argument)+ Cond :: OpenExp env aenv PrimBool+ -> OpenExp env aenv t+ -> OpenExp env aenv t+ -> OpenExp env aenv t++ -- Value recursion+ While :: OpenFun env aenv (a -> PrimBool) -- continue while true+ -> OpenFun env aenv (a -> a) -- function to iterate+ -> OpenExp env aenv a -- initial value+ -> OpenExp env aenv a++ -- Constant values+ Const :: ScalarType t+ -> t+ -> OpenExp env aenv t++ PrimConst :: PrimConst t+ -> OpenExp env aenv t++ -- Primitive scalar operations+ PrimApp :: PrimFun (a -> r)+ -> OpenExp env aenv a+ -> OpenExp env aenv r++ -- Project a single scalar from an array.+ -- The array expression can not contain any free scalar variables.+ Index :: ArrayVar aenv (Array dim t)+ -> OpenExp env aenv dim+ -> OpenExp env aenv t++ LinearIndex :: ArrayVar aenv (Array dim t)+ -> OpenExp env aenv Int+ -> OpenExp env aenv t++ -- Array shape.+ -- The array expression can not contain any free scalar variables.+ Shape :: ArrayVar aenv (Array dim e)+ -> OpenExp env aenv dim++ -- Number of elements of an array given its shape+ ShapeSize :: ShapeR dim+ -> OpenExp env aenv dim+ -> OpenExp env aenv Int++ -- Unsafe operations (may fail or result in undefined behaviour)+ -- An unspecified bit pattern+ Undef :: ScalarType t+ -> OpenExp env aenv t++ -- Reinterpret the bits of a value as a different type+ Coerce :: BitSizeEq a b+ => ScalarType a+ -> ScalarType b+ -> OpenExp env aenv a+ -> OpenExp env aenv b++-- |Primitive constant values+--+data PrimConst ty where++ -- constants from Bounded+ PrimMinBound :: BoundedType a -> PrimConst a+ PrimMaxBound :: BoundedType a -> PrimConst a++ -- constant from Floating+ PrimPi :: FloatingType a -> PrimConst a+++-- |Primitive scalar operations+--+data PrimFun sig where++ -- operators from Num+ PrimAdd :: NumType a -> PrimFun ((a, a) -> a)+ PrimSub :: NumType a -> PrimFun ((a, a) -> a)+ PrimMul :: NumType a -> PrimFun ((a, a) -> a)+ PrimNeg :: NumType a -> PrimFun (a -> a)+ PrimAbs :: NumType a -> PrimFun (a -> a)+ PrimSig :: NumType a -> PrimFun (a -> a)++ -- operators from Integral+ PrimQuot :: IntegralType a -> PrimFun ((a, a) -> a)+ PrimRem :: IntegralType a -> PrimFun ((a, a) -> a)+ PrimQuotRem :: IntegralType a -> PrimFun ((a, a) -> (a, a))+ PrimIDiv :: IntegralType a -> PrimFun ((a, a) -> a)+ PrimMod :: IntegralType a -> PrimFun ((a, a) -> a)+ PrimDivMod :: IntegralType a -> PrimFun ((a, a) -> (a, a))++ -- operators from Bits & FiniteBits+ PrimBAnd :: IntegralType a -> PrimFun ((a, a) -> a)+ PrimBOr :: IntegralType a -> PrimFun ((a, a) -> a)+ PrimBXor :: IntegralType a -> PrimFun ((a, a) -> a)+ PrimBNot :: IntegralType a -> PrimFun (a -> a)+ PrimBShiftL :: IntegralType a -> PrimFun ((a, Int) -> a)+ PrimBShiftR :: IntegralType a -> PrimFun ((a, Int) -> a)+ PrimBRotateL :: IntegralType a -> PrimFun ((a, Int) -> a)+ PrimBRotateR :: IntegralType a -> PrimFun ((a, Int) -> a)+ PrimPopCount :: IntegralType a -> PrimFun (a -> Int)+ PrimCountLeadingZeros :: IntegralType a -> PrimFun (a -> Int)+ PrimCountTrailingZeros :: IntegralType a -> PrimFun (a -> Int)++ -- operators from Fractional and Floating+ PrimFDiv :: FloatingType a -> PrimFun ((a, a) -> a)+ PrimRecip :: FloatingType a -> PrimFun (a -> a)+ PrimSin :: FloatingType a -> PrimFun (a -> a)+ PrimCos :: FloatingType a -> PrimFun (a -> a)+ PrimTan :: FloatingType a -> PrimFun (a -> a)+ PrimAsin :: FloatingType a -> PrimFun (a -> a)+ PrimAcos :: FloatingType a -> PrimFun (a -> a)+ PrimAtan :: FloatingType a -> PrimFun (a -> a)+ PrimSinh :: FloatingType a -> PrimFun (a -> a)+ PrimCosh :: FloatingType a -> PrimFun (a -> a)+ PrimTanh :: FloatingType a -> PrimFun (a -> a)+ PrimAsinh :: FloatingType a -> PrimFun (a -> a)+ PrimAcosh :: FloatingType a -> PrimFun (a -> a)+ PrimAtanh :: FloatingType a -> PrimFun (a -> a)+ PrimExpFloating :: FloatingType a -> PrimFun (a -> a)+ PrimSqrt :: FloatingType a -> PrimFun (a -> a)+ PrimLog :: FloatingType a -> PrimFun (a -> a)+ PrimFPow :: FloatingType a -> PrimFun ((a, a) -> a)+ PrimLogBase :: FloatingType a -> PrimFun ((a, a) -> a)++ -- FIXME: add missing operations from RealFrac & RealFloat++ -- operators from RealFrac+ PrimTruncate :: FloatingType a -> IntegralType b -> PrimFun (a -> b)+ PrimRound :: FloatingType a -> IntegralType b -> PrimFun (a -> b)+ PrimFloor :: FloatingType a -> IntegralType b -> PrimFun (a -> b)+ PrimCeiling :: FloatingType a -> IntegralType b -> PrimFun (a -> b)+ -- PrimProperFraction :: FloatingType a -> IntegralType b -> PrimFun (a -> (b, a))++ -- operators from RealFloat+ PrimAtan2 :: FloatingType a -> PrimFun ((a, a) -> a)+ PrimIsNaN :: FloatingType a -> PrimFun (a -> PrimBool)+ PrimIsInfinite :: FloatingType a -> PrimFun (a -> PrimBool)++ -- relational and equality operators+ PrimLt :: SingleType a -> PrimFun ((a, a) -> PrimBool)+ PrimGt :: SingleType a -> PrimFun ((a, a) -> PrimBool)+ PrimLtEq :: SingleType a -> PrimFun ((a, a) -> PrimBool)+ PrimGtEq :: SingleType a -> PrimFun ((a, a) -> PrimBool)+ PrimEq :: SingleType a -> PrimFun ((a, a) -> PrimBool)+ PrimNEq :: SingleType a -> PrimFun ((a, a) -> PrimBool)+ PrimMax :: SingleType a -> PrimFun ((a, a) -> a)+ PrimMin :: SingleType a -> PrimFun ((a, a) -> a)++ -- logical operators+ --+ -- Note that these operators are strict in both arguments. That is, the+ -- second argument of PrimLAnd is always evaluated even when the first+ -- argument is false.+ --+ -- We define (surface level) (&&) and (||) using if-then-else to enable+ -- short-circuiting, while (&&!) and (||!) are strict versions of these+ -- operators, which are defined using PrimLAnd and PrimLOr.+ --+ PrimLAnd :: PrimFun ((PrimBool, PrimBool) -> PrimBool)+ PrimLOr :: PrimFun ((PrimBool, PrimBool) -> PrimBool)+ PrimLNot :: PrimFun (PrimBool -> PrimBool)++ -- general conversion between types+ PrimFromIntegral :: IntegralType a -> NumType b -> PrimFun (a -> b)+ PrimToFloating :: NumType a -> FloatingType b -> PrimFun (a -> b)+++-- Type utilities+-- --------------++class HasArraysR f where+ arraysR :: f aenv a -> ArraysR a++instance HasArraysR OpenAcc where+ arraysR (OpenAcc a) = arraysR a++arrayR :: HasArraysR f => f aenv (Array sh e) -> ArrayR (Array sh e)+arrayR a = case arraysR a of+ TupRsingle aR -> aR++instance HasArraysR acc => HasArraysR (PreOpenAcc acc) where+ arraysR (Alet _ _ body) = arraysR body+ arraysR (Avar (Var aR _)) = TupRsingle aR+ arraysR (Apair as bs) = TupRpair (arraysR as) (arraysR bs)+ arraysR Anil = TupRunit+ arraysR (Atrace _ _ bs) = arraysR bs+ arraysR (Apply aR _ _) = aR+ arraysR (Aforeign r _ _ _) = r+ arraysR (Acond _ a _) = arraysR a+ arraysR (Awhile _ (Alam lhs _) _) = lhsToTupR lhs+ arraysR Awhile{} = error "I want my, I want my MTV!"+ arraysR (Use aR _) = TupRsingle aR+ arraysR (Unit tR _) = arraysRarray ShapeRz tR+ arraysR (Reshape sh _ a) = let ArrayR _ tR = arrayR a+ in arraysRarray sh tR+ arraysR (Generate aR _ _) = TupRsingle aR+ arraysR (Transform aR _ _ _ _) = TupRsingle aR+ arraysR (Replicate slice _ a) = let ArrayR _ tR = arrayR a+ in arraysRarray (sliceDomainR slice) tR+ arraysR (Slice slice a _) = let ArrayR _ tR = arrayR a+ in arraysRarray (sliceShapeR slice) tR+ arraysR (Map tR _ a) = let ArrayR sh _ = arrayR a+ in arraysRarray sh tR+ arraysR (ZipWith tR _ a _) = let ArrayR sh _ = arrayR a+ in arraysRarray sh tR+ arraysR (Fold _ _ a) = let ArrayR (ShapeRsnoc sh) tR = arrayR a+ in arraysRarray sh tR+ arraysR (FoldSeg _ _ _ a _) = arraysR a+ arraysR (Scan _ _ _ a) = arraysR a+ arraysR (Scan' _ _ _ a) = let aR@(ArrayR (ShapeRsnoc sh) tR) = arrayR a+ in TupRsingle aR `TupRpair` TupRsingle (ArrayR sh tR)+ arraysR (Permute _ a _ _) = arraysR a+ arraysR (Backpermute sh _ _ a) = let ArrayR _ tR = arrayR a+ in arraysRarray sh tR+ arraysR (Stencil _ tR _ _ a) = let ArrayR sh _ = arrayR a+ in arraysRarray sh tR+ arraysR (Stencil2 _ _ tR _ _ a _ _) = let ArrayR sh _ = arrayR a+ in arraysRarray sh tR++expType :: HasCallStack => OpenExp aenv env t -> TypeR t+expType = \case+ Let _ _ body -> expType body+ Evar (Var tR _) -> TupRsingle tR+ Foreign tR _ _ _ -> tR+ Pair e1 e2 -> TupRpair (expType e1) (expType e2)+ Nil -> TupRunit+ VecPack vecR _ -> TupRsingle $ VectorScalarType $ vecRvector vecR+ VecUnpack vecR _ -> vecRtuple vecR+ IndexSlice si _ _ -> shapeType $ sliceShapeR si+ IndexFull si _ _ -> shapeType $ sliceDomainR si+ ToIndex{} -> TupRsingle scalarTypeInt+ FromIndex shr _ _ -> shapeType shr+ Case _ ((_,e):_) _ -> expType e+ Case _ [] (Just e) -> expType e+ Case{} -> internalError "empty case encountered"+ Cond _ e _ -> expType e+ While _ (Lam lhs _) _ -> lhsToTupR lhs+ While{} -> error "What's the matter, you're running in the shadows"+ Const tR _ -> TupRsingle tR+ PrimConst c -> TupRsingle $ SingleScalarType $ primConstType c+ PrimApp f _ -> snd $ primFunType f+ Index (Var repr _) _ -> arrayRtype repr+ LinearIndex (Var repr _) _ -> arrayRtype repr+ Shape (Var repr _) -> shapeType $ arrayRshape repr+ ShapeSize{} -> TupRsingle scalarTypeInt+ Undef tR -> TupRsingle tR+ Coerce _ tR _ -> TupRsingle tR++primConstType :: PrimConst a -> SingleType a+primConstType = \case+ PrimMinBound t -> bounded t+ PrimMaxBound t -> bounded t+ PrimPi t -> floating t+ where+ bounded :: BoundedType a -> SingleType a+ bounded (IntegralBoundedType t) = NumSingleType $ IntegralNumType t++ floating :: FloatingType t -> SingleType t+ floating = NumSingleType . FloatingNumType++primFunType :: PrimFun (a -> b) -> (TypeR a, TypeR b)+primFunType = \case+ -- Num+ PrimAdd t -> binary' $ num t+ PrimSub t -> binary' $ num t+ PrimMul t -> binary' $ num t+ PrimNeg t -> unary' $ num t+ PrimAbs t -> unary' $ num t+ PrimSig t -> unary' $ num t++ -- Integral+ PrimQuot t -> binary' $ integral t+ PrimRem t -> binary' $ integral t+ PrimQuotRem t -> unary' $ integral t `TupRpair` integral t+ PrimIDiv t -> binary' $ integral t+ PrimMod t -> binary' $ integral t+ PrimDivMod t -> unary' $ integral t `TupRpair` integral t++ -- Bits & FiniteBits+ PrimBAnd t -> binary' $ integral t+ PrimBOr t -> binary' $ integral t+ PrimBXor t -> binary' $ integral t+ PrimBNot t -> unary' $ integral t+ PrimBShiftL t -> (integral t `TupRpair` tint, integral t)+ PrimBShiftR t -> (integral t `TupRpair` tint, integral t)+ PrimBRotateL t -> (integral t `TupRpair` tint, integral t)+ PrimBRotateR t -> (integral t `TupRpair` tint, integral t)+ PrimPopCount t -> unary (integral t) tint+ PrimCountLeadingZeros t -> unary (integral t) tint+ PrimCountTrailingZeros t -> unary (integral t) tint++ -- Fractional, Floating+ PrimFDiv t -> binary' $ floating t+ PrimRecip t -> unary' $ floating t+ PrimSin t -> unary' $ floating t+ PrimCos t -> unary' $ floating t+ PrimTan t -> unary' $ floating t+ PrimAsin t -> unary' $ floating t+ PrimAcos t -> unary' $ floating t+ PrimAtan t -> unary' $ floating t+ PrimSinh t -> unary' $ floating t+ PrimCosh t -> unary' $ floating t+ PrimTanh t -> unary' $ floating t+ PrimAsinh t -> unary' $ floating t+ PrimAcosh t -> unary' $ floating t+ PrimAtanh t -> unary' $ floating t+ PrimExpFloating t -> unary' $ floating t+ PrimSqrt t -> unary' $ floating t+ PrimLog t -> unary' $ floating t+ PrimFPow t -> binary' $ floating t+ PrimLogBase t -> binary' $ floating t++ -- RealFrac+ PrimTruncate a b -> unary (floating a) (integral b)+ PrimRound a b -> unary (floating a) (integral b)+ PrimFloor a b -> unary (floating a) (integral b)+ PrimCeiling a b -> unary (floating a) (integral b)++ -- RealFloat+ PrimAtan2 t -> binary' $ floating t+ PrimIsNaN t -> unary (floating t) tbool+ PrimIsInfinite t -> unary (floating t) tbool++ -- Relational and equality+ PrimLt t -> compare' t+ PrimGt t -> compare' t+ PrimLtEq t -> compare' t+ PrimGtEq t -> compare' t+ PrimEq t -> compare' t+ PrimNEq t -> compare' t+ PrimMax t -> binary' $ single t+ PrimMin t -> binary' $ single t++ -- Logical+ PrimLAnd -> binary' tbool+ PrimLOr -> binary' tbool+ PrimLNot -> unary' tbool++ -- general conversion between types+ PrimFromIntegral a b -> unary (integral a) (num b)+ PrimToFloating a b -> unary (num a) (floating b)++ where+ unary a b = (a, b)+ unary' a = unary a a+ binary a b = (a `TupRpair` a, b)+ binary' a = binary a a+ compare' a = binary (single a) tbool++ single = TupRsingle . SingleScalarType+ num = TupRsingle . SingleScalarType . NumSingleType+ integral = num . IntegralNumType+ floating = num . FloatingNumType++ tbool = TupRsingle scalarTypeWord8+ tint = TupRsingle scalarTypeInt+++-- Normal form data+-- ================++instance NFData (OpenAfun aenv f) where+ rnf = rnfOpenAfun++instance NFData (OpenAcc aenv t) where+ rnf = rnfOpenAcc++instance NFData (OpenExp env aenv t) where+ rnf = rnfOpenExp++instance NFData (OpenFun env aenv t) where+ rnf = rnfOpenFun+++type NFDataAcc acc = forall aenv t. acc aenv t -> ()++rnfOpenAfun :: OpenAfun aenv t -> ()+rnfOpenAfun = rnfPreOpenAfun rnfOpenAcc++rnfPreOpenAfun :: NFDataAcc acc -> PreOpenAfun acc aenv t -> ()+rnfPreOpenAfun rnfA (Abody b) = rnfA b+rnfPreOpenAfun rnfA (Alam lhs f) = rnfALeftHandSide lhs `seq` rnfPreOpenAfun rnfA f++rnfOpenAcc :: OpenAcc aenv t -> ()+rnfOpenAcc (OpenAcc pacc) = rnfPreOpenAcc rnfOpenAcc pacc++rnfPreOpenAcc :: forall acc aenv t. HasArraysR acc => NFDataAcc acc -> PreOpenAcc acc aenv t -> ()+rnfPreOpenAcc rnfA pacc =+ let+ rnfAF :: PreOpenAfun acc aenv' t' -> ()+ rnfAF = rnfPreOpenAfun rnfA++ rnfE :: OpenExp env' aenv' t' -> ()+ rnfE = rnfOpenExp++ rnfF :: OpenFun env' aenv' t' -> ()+ rnfF = rnfOpenFun++ rnfB :: ArrayR (Array sh e) -> Boundary aenv' (Array sh e) -> ()+ rnfB = rnfBoundary++ rnfM :: Message a -> ()+ rnfM (Message f g msg) = f `seq` rnfMaybe (\x -> x `seq` ()) g `seq` rnf msg+ in+ case pacc of+ Alet lhs bnd body -> rnfALeftHandSide lhs `seq` rnfA bnd `seq` rnfA body+ Avar var -> rnfArrayVar var+ Apair as bs -> rnfA as `seq` rnfA bs+ Anil -> ()+ Atrace msg as bs -> rnfM msg `seq` rnfA as `seq` rnfA bs+ Apply repr afun acc -> rnfTupR rnfArrayR repr `seq` rnfAF afun `seq` rnfA acc+ Aforeign repr asm afun a -> rnfTupR rnfArrayR repr `seq` rnf (strForeign asm) `seq` rnfAF afun `seq` rnfA a+ Acond p a1 a2 -> rnfE p `seq` rnfA a1 `seq` rnfA a2+ Awhile p f a -> rnfAF p `seq` rnfAF f `seq` rnfA a+ Use repr arr -> rnfArray repr arr+ Unit tp x -> rnfTypeR tp `seq` rnfE x+ Reshape shr sh a -> rnfShapeR shr `seq` rnfE sh `seq` rnfA a+ Generate repr sh f -> rnfArrayR repr `seq` rnfE sh `seq` rnfF f+ Transform repr sh p f a -> rnfArrayR repr `seq` rnfE sh `seq` rnfF p `seq` rnfF f `seq` rnfA a+ Replicate slice sh a -> rnfSliceIndex slice `seq` rnfE sh `seq` rnfA a+ Slice slice a sh -> rnfSliceIndex slice `seq` rnfE sh `seq` rnfA a+ Map tp f a -> rnfTypeR tp `seq` rnfF f `seq` rnfA a+ ZipWith tp f a1 a2 -> rnfTypeR tp `seq` rnfF f `seq` rnfA a1 `seq` rnfA a2+ Fold f z a -> rnfF f `seq` rnfMaybe rnfE z `seq` rnfA a+ FoldSeg i f z a s -> rnfIntegralType i `seq` rnfF f `seq` rnfMaybe rnfE z `seq` rnfA a `seq` rnfA s+ Scan d f z a -> d `seq` rnfF f `seq` rnfMaybe rnfE z `seq` rnfA a+ Scan' d f z a -> d `seq` rnfF f `seq` rnfE z `seq` rnfA a+ Permute f d p a -> rnfF f `seq` rnfA d `seq` rnfF p `seq` rnfA a+ Backpermute shr sh f a -> rnfShapeR shr `seq` rnfE sh `seq` rnfF f `seq` rnfA a+ Stencil sr tp f b a ->+ let+ TupRsingle (ArrayR shr _) = arraysR a+ repr = ArrayR shr $ stencilEltR sr+ in rnfStencilR sr `seq` rnfTupR rnfScalarType tp `seq` rnfF f `seq` rnfB repr b `seq` rnfA a+ Stencil2 sr1 sr2 tp f b1 a1 b2 a2 ->+ let+ TupRsingle (ArrayR shr _) = arraysR a1+ repr1 = ArrayR shr $ stencilEltR sr1+ repr2 = ArrayR shr $ stencilEltR sr2+ in rnfStencilR sr1 `seq` rnfStencilR sr2 `seq` rnfTupR rnfScalarType tp `seq` rnfF f `seq` rnfB repr1 b1 `seq` rnfB repr2 b2 `seq` rnfA a1 `seq` rnfA a2++rnfArrayVar :: ArrayVar aenv a -> ()+rnfArrayVar = rnfVar rnfArrayR++rnfALeftHandSide :: ALeftHandSide arrs aenv aenv' -> ()+rnfALeftHandSide = rnfLeftHandSide rnfArrayR++rnfBoundary :: forall aenv sh e. ArrayR (Array sh e) -> Boundary aenv (Array sh e) -> ()+rnfBoundary _ Clamp = ()+rnfBoundary _ Mirror = ()+rnfBoundary _ Wrap = ()+rnfBoundary (ArrayR _ tR) (Constant c) = rnfConst tR c+rnfBoundary _ (Function f) = rnfOpenFun f++rnfMaybe :: (a -> ()) -> Maybe a -> ()+rnfMaybe _ Nothing = ()+rnfMaybe f (Just x) = f x++rnfList :: (a -> ()) -> [a] -> ()+rnfList r = go+ where+ go [] = ()+ go (x:xs) = r x `seq` go xs++rnfOpenFun :: OpenFun env aenv t -> ()+rnfOpenFun (Body b) = rnfOpenExp b+rnfOpenFun (Lam lhs f) = rnfELeftHandSide lhs `seq` rnfOpenFun f++rnfOpenExp :: forall env aenv t. OpenExp env aenv t -> ()+rnfOpenExp topExp =+ let+ rnfF :: OpenFun env' aenv' t' -> ()+ rnfF = rnfOpenFun++ rnfE :: OpenExp env' aenv' t' -> ()+ rnfE = rnfOpenExp+ in+ case topExp of+ Let lhs bnd body -> rnfELeftHandSide lhs `seq` rnfE bnd `seq` rnfE body+ Evar v -> rnfExpVar v+ Foreign tp asm f x -> rnfTypeR tp `seq` rnf (strForeign asm) `seq` rnfF f `seq` rnfE x+ Const tp c -> c `seq` rnfScalarType tp -- scalars should have (nf == whnf)+ Undef tp -> rnfScalarType tp+ Pair a b -> rnfE a `seq` rnfE b+ Nil -> ()+ VecPack vecr e -> rnfVecR vecr `seq` rnfE e+ VecUnpack vecr e -> rnfVecR vecr `seq` rnfE e+ IndexSlice slice slix sh -> rnfSliceIndex slice `seq` rnfE slix `seq` rnfE sh+ IndexFull slice slix sl -> rnfSliceIndex slice `seq` rnfE slix `seq` rnfE sl+ ToIndex shr sh ix -> rnfShapeR shr `seq` rnfE sh `seq` rnfE ix+ FromIndex shr sh ix -> rnfShapeR shr `seq` rnfE sh `seq` rnfE ix+ Case e rhs def -> rnfE e `seq` rnfList (\(t,c) -> t `seq` rnfE c) rhs `seq` rnfMaybe rnfE def+ Cond p e1 e2 -> rnfE p `seq` rnfE e1 `seq` rnfE e2+ While p f x -> rnfF p `seq` rnfF f `seq` rnfE x+ PrimConst c -> rnfPrimConst c+ PrimApp f x -> rnfPrimFun f `seq` rnfE x+ Index a ix -> rnfArrayVar a `seq` rnfE ix+ LinearIndex a ix -> rnfArrayVar a `seq` rnfE ix+ Shape a -> rnfArrayVar a+ ShapeSize shr sh -> rnfShapeR shr `seq` rnfE sh+ Coerce t1 t2 e -> rnfScalarType t1 `seq` rnfScalarType t2 `seq` rnfE e++rnfExpVar :: ExpVar env t -> ()+rnfExpVar = rnfVar rnfScalarType++rnfELeftHandSide :: ELeftHandSide t env env' -> ()+rnfELeftHandSide= rnfLeftHandSide rnfScalarType++rnfConst :: TypeR t -> t -> ()+rnfConst TupRunit () = ()+rnfConst (TupRsingle t) !_ = rnfScalarType t -- scalars should have (nf == whnf)+rnfConst (TupRpair ta tb) (a,b) = rnfConst ta a `seq` rnfConst tb b++rnfPrimConst :: PrimConst c -> ()+rnfPrimConst (PrimMinBound t) = rnfBoundedType t+rnfPrimConst (PrimMaxBound t) = rnfBoundedType t+rnfPrimConst (PrimPi t) = rnfFloatingType t++rnfPrimFun :: PrimFun f -> ()+rnfPrimFun (PrimAdd t) = rnfNumType t+rnfPrimFun (PrimSub t) = rnfNumType t+rnfPrimFun (PrimMul t) = rnfNumType t+rnfPrimFun (PrimNeg t) = rnfNumType t+rnfPrimFun (PrimAbs t) = rnfNumType t+rnfPrimFun (PrimSig t) = rnfNumType t+rnfPrimFun (PrimQuot t) = rnfIntegralType t+rnfPrimFun (PrimRem t) = rnfIntegralType t+rnfPrimFun (PrimQuotRem t) = rnfIntegralType t+rnfPrimFun (PrimIDiv t) = rnfIntegralType t+rnfPrimFun (PrimMod t) = rnfIntegralType t+rnfPrimFun (PrimDivMod t) = rnfIntegralType t+rnfPrimFun (PrimBAnd t) = rnfIntegralType t+rnfPrimFun (PrimBOr t) = rnfIntegralType t+rnfPrimFun (PrimBXor t) = rnfIntegralType t+rnfPrimFun (PrimBNot t) = rnfIntegralType t+rnfPrimFun (PrimBShiftL t) = rnfIntegralType t+rnfPrimFun (PrimBShiftR t) = rnfIntegralType t+rnfPrimFun (PrimBRotateL t) = rnfIntegralType t+rnfPrimFun (PrimBRotateR t) = rnfIntegralType t+rnfPrimFun (PrimPopCount t) = rnfIntegralType t+rnfPrimFun (PrimCountLeadingZeros t) = rnfIntegralType t+rnfPrimFun (PrimCountTrailingZeros t) = rnfIntegralType t+rnfPrimFun (PrimFDiv t) = rnfFloatingType t+rnfPrimFun (PrimRecip t) = rnfFloatingType t+rnfPrimFun (PrimSin t) = rnfFloatingType t+rnfPrimFun (PrimCos t) = rnfFloatingType t+rnfPrimFun (PrimTan t) = rnfFloatingType t+rnfPrimFun (PrimAsin t) = rnfFloatingType t+rnfPrimFun (PrimAcos t) = rnfFloatingType t+rnfPrimFun (PrimAtan t) = rnfFloatingType t+rnfPrimFun (PrimSinh t) = rnfFloatingType t+rnfPrimFun (PrimCosh t) = rnfFloatingType t+rnfPrimFun (PrimTanh t) = rnfFloatingType t+rnfPrimFun (PrimAsinh t) = rnfFloatingType t+rnfPrimFun (PrimAcosh t) = rnfFloatingType t+rnfPrimFun (PrimAtanh t) = rnfFloatingType t+rnfPrimFun (PrimExpFloating t) = rnfFloatingType t+rnfPrimFun (PrimSqrt t) = rnfFloatingType t+rnfPrimFun (PrimLog t) = rnfFloatingType t+rnfPrimFun (PrimFPow t) = rnfFloatingType t+rnfPrimFun (PrimLogBase t) = rnfFloatingType t+rnfPrimFun (PrimTruncate f i) = rnfFloatingType f `seq` rnfIntegralType i+rnfPrimFun (PrimRound f i) = rnfFloatingType f `seq` rnfIntegralType i+rnfPrimFun (PrimFloor f i) = rnfFloatingType f `seq` rnfIntegralType i+rnfPrimFun (PrimCeiling f i) = rnfFloatingType f `seq` rnfIntegralType i+rnfPrimFun (PrimIsNaN t) = rnfFloatingType t+rnfPrimFun (PrimIsInfinite t) = rnfFloatingType t+rnfPrimFun (PrimAtan2 t) = rnfFloatingType t+rnfPrimFun (PrimLt t) = rnfSingleType t+rnfPrimFun (PrimGt t) = rnfSingleType t+rnfPrimFun (PrimLtEq t) = rnfSingleType t+rnfPrimFun (PrimGtEq t) = rnfSingleType t+rnfPrimFun (PrimEq t) = rnfSingleType t+rnfPrimFun (PrimNEq t) = rnfSingleType t+rnfPrimFun (PrimMax t) = rnfSingleType t+rnfPrimFun (PrimMin t) = rnfSingleType t+rnfPrimFun PrimLAnd = ()+rnfPrimFun PrimLOr = ()+rnfPrimFun PrimLNot = ()+rnfPrimFun (PrimFromIntegral i n) = rnfIntegralType i `seq` rnfNumType n+rnfPrimFun (PrimToFloating n f) = rnfNumType n `seq` rnfFloatingType f+++-- Template Haskell+-- ================++type LiftAcc acc = forall aenv a. acc aenv a -> CodeQ (acc aenv a)++liftPreOpenAfun :: LiftAcc acc -> PreOpenAfun acc aenv t -> CodeQ (PreOpenAfun acc aenv t)+liftPreOpenAfun liftA (Alam lhs f) = [|| Alam $$(liftALeftHandSide lhs) $$(liftPreOpenAfun liftA f) ||]+liftPreOpenAfun liftA (Abody b) = [|| Abody $$(liftA b) ||]++liftPreOpenAcc+ :: forall acc aenv a.+ HasArraysR acc+ => LiftAcc acc+ -> PreOpenAcc acc aenv a+ -> CodeQ (PreOpenAcc acc aenv a)+liftPreOpenAcc liftA pacc =+ let+ liftE :: OpenExp env aenv t -> CodeQ (OpenExp env aenv t)+ liftE = liftOpenExp++ liftF :: OpenFun env aenv t -> CodeQ (OpenFun env aenv t)+ liftF = liftOpenFun++ liftAF :: PreOpenAfun acc aenv f -> CodeQ (PreOpenAfun acc aenv f)+ liftAF = liftPreOpenAfun liftA++ liftB :: ArrayR (Array sh e) -> Boundary aenv (Array sh e) -> CodeQ (Boundary aenv (Array sh e))+ liftB = liftBoundary+ in+ case pacc of+ Alet lhs bnd body -> [|| Alet $$(liftALeftHandSide lhs) $$(liftA bnd) $$(liftA body) ||]+ Avar var -> [|| Avar $$(liftArrayVar var) ||]+ Apair as bs -> [|| Apair $$(liftA as) $$(liftA bs) ||]+ Anil -> [|| Anil ||]+ Atrace msg as bs -> [|| Atrace $$(liftMessage (arraysR as) msg) $$(liftA as) $$(liftA bs) ||]+ Apply repr f a -> [|| Apply $$(liftArraysR repr) $$(liftAF f) $$(liftA a) ||]+ Aforeign repr asm f a -> [|| Aforeign $$(liftArraysR repr) $$(liftForeign asm) $$(liftPreOpenAfun liftA f) $$(liftA a) ||]+ Acond p t e -> [|| Acond $$(liftE p) $$(liftA t) $$(liftA e) ||]+ Awhile p f a -> [|| Awhile $$(liftAF p) $$(liftAF f) $$(liftA a) ||]+ Use repr a -> [|| Use $$(liftArrayR repr) $$(liftArray repr a) ||]+ Unit tp e -> [|| Unit $$(liftTypeR tp) $$(liftE e) ||]+ Reshape shr sh a -> [|| Reshape $$(liftShapeR shr) $$(liftE sh) $$(liftA a) ||]+ Generate repr sh f -> [|| Generate $$(liftArrayR repr) $$(liftE sh) $$(liftF f) ||]+ Transform repr sh p f a -> [|| Transform $$(liftArrayR repr) $$(liftE sh) $$(liftF p) $$(liftF f) $$(liftA a) ||]+ Replicate slix sl a -> [|| Replicate $$(liftSliceIndex slix) $$(liftE sl) $$(liftA a) ||]+ Slice slix a sh -> [|| Slice $$(liftSliceIndex slix) $$(liftA a) $$(liftE sh) ||]+ Map tp f a -> [|| Map $$(liftTypeR tp) $$(liftF f) $$(liftA a) ||]+ ZipWith tp f a b -> [|| ZipWith $$(liftTypeR tp) $$(liftF f) $$(liftA a) $$(liftA b) ||]+ Fold f z a -> [|| Fold $$(liftF f) $$(liftMaybe liftE z) $$(liftA a) ||]+ FoldSeg i f z a s -> [|| FoldSeg $$(liftIntegralType i) $$(liftF f) $$(liftMaybe liftE z) $$(liftA a) $$(liftA s) ||]+ Scan d f z a -> [|| Scan $$(liftDirection d) $$(liftF f) $$(liftMaybe liftE z) $$(liftA a) ||]+ Scan' d f z a -> [|| Scan' $$(liftDirection d) $$(liftF f) $$(liftE z) $$(liftA a) ||]+ Permute f d p a -> [|| Permute $$(liftF f) $$(liftA d) $$(liftF p) $$(liftA a) ||]+ Backpermute shr sh p a -> [|| Backpermute $$(liftShapeR shr) $$(liftE sh) $$(liftF p) $$(liftA a) ||]+ Stencil sr tp f b a ->+ let TupRsingle (ArrayR shr _) = arraysR a+ repr = ArrayR shr $ stencilEltR sr+ in [|| Stencil $$(liftStencilR sr) $$(liftTypeR tp) $$(liftF f) $$(liftB repr b) $$(liftA a) ||]+ Stencil2 sr1 sr2 tp f b1 a1 b2 a2 ->+ let TupRsingle (ArrayR shr _) = arraysR a1+ repr1 = ArrayR shr $ stencilEltR sr1+ repr2 = ArrayR shr $ stencilEltR sr2+ in [|| Stencil2 $$(liftStencilR sr1) $$(liftStencilR sr2) $$(liftTypeR tp) $$(liftF f) $$(liftB repr1 b1) $$(liftA a1) $$(liftB repr2 b2) $$(liftA a2) ||]+++liftALeftHandSide :: ALeftHandSide arrs aenv aenv' -> CodeQ (ALeftHandSide arrs aenv aenv')+liftALeftHandSide = liftLeftHandSide liftArrayR++liftArrayVar :: ArrayVar aenv a -> CodeQ (ArrayVar aenv a)+liftArrayVar = liftVar liftArrayR++liftDirection :: Direction -> CodeQ Direction+liftDirection LeftToRight = [|| LeftToRight ||]+liftDirection RightToLeft = [|| RightToLeft ||]++liftMessage :: ArraysR a -> Message a -> CodeQ (Message a)+liftMessage aR (Message _ fmt msg) =+ let+ -- We (ironically?) can't lift TExp, so nested occurrences must fall+ -- back to displaying in representation format+ fmtR :: ArraysR arrs' -> CodeQ (arrs' -> String)+ fmtR TupRunit = [|| \() -> "()" ||]+ fmtR (TupRsingle (ArrayR ShapeRz eR)) = [|| \as -> showElt $$(liftTypeR eR) $ linearIndexArray $$(liftTypeR eR) as 0 ||]+ fmtR (TupRsingle (ArrayR shR eR)) = [|| \as -> showArray (showsElt $$(liftTypeR eR)) (ArrayR $$(liftShapeR shR) $$(liftTypeR eR)) as ||]+ fmtR aR' = [|| \as -> showArrays $$(liftArraysR aR') as ||]+ in+ [|| Message $$(fromMaybe (fmtR aR) fmt) Nothing $$(TH.unsafeCodeCoerce (TH.lift msg)) ||]++liftMaybe :: (a -> CodeQ a) -> Maybe a -> CodeQ (Maybe a)+liftMaybe _ Nothing = [|| Nothing ||]+liftMaybe f (Just x) = [|| Just $$(f x) ||]++liftList :: (a -> CodeQ a) -> [a] -> CodeQ [a]+liftList _ [] = [|| [] ||]+liftList f (x:xs) = [|| $$(f x) : $$(liftList f xs) ||]++liftOpenFun+ :: OpenFun env aenv t+ -> CodeQ (OpenFun env aenv t)+liftOpenFun (Lam lhs f) = [|| Lam $$(liftELeftHandSide lhs) $$(liftOpenFun f) ||]+liftOpenFun (Body b) = [|| Body $$(liftOpenExp b) ||]++liftOpenExp+ :: forall env aenv t.+ OpenExp env aenv t+ -> CodeQ (OpenExp env aenv t)+liftOpenExp pexp =+ let+ liftE :: OpenExp env aenv e -> CodeQ (OpenExp env aenv e)+ liftE = liftOpenExp++ liftF :: OpenFun env aenv f -> CodeQ (OpenFun env aenv f)+ liftF = liftOpenFun+ in+ case pexp of+ Let lhs bnd body -> [|| Let $$(liftELeftHandSide lhs) $$(liftOpenExp bnd) $$(liftOpenExp body) ||]+ Evar var -> [|| Evar $$(liftExpVar var) ||]+ Foreign repr asm f x -> [|| Foreign $$(liftTypeR repr) $$(liftForeign asm) $$(liftOpenFun f) $$(liftE x) ||]+ Const tp c -> [|| Const $$(liftScalarType tp) $$(liftElt (TupRsingle tp) c) ||]+ Undef tp -> [|| Undef $$(liftScalarType tp) ||]+ Pair a b -> [|| Pair $$(liftE a) $$(liftE b) ||]+ Nil -> [|| Nil ||]+ VecPack vecr e -> [|| VecPack $$(liftVecR vecr) $$(liftE e) ||]+ VecUnpack vecr e -> [|| VecUnpack $$(liftVecR vecr) $$(liftE e) ||]+ IndexSlice slice slix sh -> [|| IndexSlice $$(liftSliceIndex slice) $$(liftE slix) $$(liftE sh) ||]+ IndexFull slice slix sl -> [|| IndexFull $$(liftSliceIndex slice) $$(liftE slix) $$(liftE sl) ||]+ ToIndex shr sh ix -> [|| ToIndex $$(liftShapeR shr) $$(liftE sh) $$(liftE ix) ||]+ FromIndex shr sh ix -> [|| FromIndex $$(liftShapeR shr) $$(liftE sh) $$(liftE ix) ||]+ Case p rhs def -> [|| Case $$(liftE p) $$(liftList (\(t,c) -> [|| (t, $$(liftE c)) ||]) rhs) $$(liftMaybe liftE def) ||]+ Cond p t e -> [|| Cond $$(liftE p) $$(liftE t) $$(liftE e) ||]+ While p f x -> [|| While $$(liftF p) $$(liftF f) $$(liftE x) ||]+ PrimConst t -> [|| PrimConst $$(liftPrimConst t) ||]+ PrimApp f x -> [|| PrimApp $$(liftPrimFun f) $$(liftE x) ||]+ Index a ix -> [|| Index $$(liftArrayVar a) $$(liftE ix) ||]+ LinearIndex a ix -> [|| LinearIndex $$(liftArrayVar a) $$(liftE ix) ||]+ Shape a -> [|| Shape $$(liftArrayVar a) ||]+ ShapeSize shr ix -> [|| ShapeSize $$(liftShapeR shr) $$(liftE ix) ||]+ Coerce t1 t2 e -> [|| Coerce $$(liftScalarType t1) $$(liftScalarType t2) $$(liftE e) ||]++liftELeftHandSide :: ELeftHandSide t env env' -> CodeQ (ELeftHandSide t env env')+liftELeftHandSide = liftLeftHandSide liftScalarType++liftExpVar :: ExpVar env t -> CodeQ (ExpVar env t)+liftExpVar = liftVar liftScalarType++liftBoundary+ :: forall aenv sh e.+ ArrayR (Array sh e)+ -> Boundary aenv (Array sh e)+ -> CodeQ (Boundary aenv (Array sh e))+liftBoundary _ Clamp = [|| Clamp ||]+liftBoundary _ Mirror = [|| Mirror ||]+liftBoundary _ Wrap = [|| Wrap ||]+liftBoundary (ArrayR _ tp) (Constant v) = [|| Constant $$(liftElt tp v) ||]+liftBoundary _ (Function f) = [|| Function $$(liftOpenFun f) ||]++liftPrimConst :: PrimConst c -> CodeQ (PrimConst c)+liftPrimConst (PrimMinBound t) = [|| PrimMinBound $$(liftBoundedType t) ||]+liftPrimConst (PrimMaxBound t) = [|| PrimMaxBound $$(liftBoundedType t) ||]+liftPrimConst (PrimPi t) = [|| PrimPi $$(liftFloatingType t) ||]++liftPrimFun :: PrimFun f -> CodeQ (PrimFun f)+liftPrimFun (PrimAdd t) = [|| PrimAdd $$(liftNumType t) ||]+liftPrimFun (PrimSub t) = [|| PrimSub $$(liftNumType t) ||]+liftPrimFun (PrimMul t) = [|| PrimMul $$(liftNumType t) ||]+liftPrimFun (PrimNeg t) = [|| PrimNeg $$(liftNumType t) ||]+liftPrimFun (PrimAbs t) = [|| PrimAbs $$(liftNumType t) ||]+liftPrimFun (PrimSig t) = [|| PrimSig $$(liftNumType t) ||]+liftPrimFun (PrimQuot t) = [|| PrimQuot $$(liftIntegralType t) ||]+liftPrimFun (PrimRem t) = [|| PrimRem $$(liftIntegralType t) ||]+liftPrimFun (PrimQuotRem t) = [|| PrimQuotRem $$(liftIntegralType t) ||]+liftPrimFun (PrimIDiv t) = [|| PrimIDiv $$(liftIntegralType t) ||]+liftPrimFun (PrimMod t) = [|| PrimMod $$(liftIntegralType t) ||]+liftPrimFun (PrimDivMod t) = [|| PrimDivMod $$(liftIntegralType t) ||]+liftPrimFun (PrimBAnd t) = [|| PrimBAnd $$(liftIntegralType t) ||]+liftPrimFun (PrimBOr t) = [|| PrimBOr $$(liftIntegralType t) ||]+liftPrimFun (PrimBXor t) = [|| PrimBXor $$(liftIntegralType t) ||]+liftPrimFun (PrimBNot t) = [|| PrimBNot $$(liftIntegralType t) ||]+liftPrimFun (PrimBShiftL t) = [|| PrimBShiftL $$(liftIntegralType t) ||]+liftPrimFun (PrimBShiftR t) = [|| PrimBShiftR $$(liftIntegralType t) ||]+liftPrimFun (PrimBRotateL t) = [|| PrimBRotateL $$(liftIntegralType t) ||]+liftPrimFun (PrimBRotateR t) = [|| PrimBRotateR $$(liftIntegralType t) ||]+liftPrimFun (PrimPopCount t) = [|| PrimPopCount $$(liftIntegralType t) ||]+liftPrimFun (PrimCountLeadingZeros t) = [|| PrimCountLeadingZeros $$(liftIntegralType t) ||]+liftPrimFun (PrimCountTrailingZeros t) = [|| PrimCountTrailingZeros $$(liftIntegralType t) ||]+liftPrimFun (PrimFDiv t) = [|| PrimFDiv $$(liftFloatingType t) ||]+liftPrimFun (PrimRecip t) = [|| PrimRecip $$(liftFloatingType t) ||]+liftPrimFun (PrimSin t) = [|| PrimSin $$(liftFloatingType t) ||]+liftPrimFun (PrimCos t) = [|| PrimCos $$(liftFloatingType t) ||]+liftPrimFun (PrimTan t) = [|| PrimTan $$(liftFloatingType t) ||]+liftPrimFun (PrimAsin t) = [|| PrimAsin $$(liftFloatingType t) ||]+liftPrimFun (PrimAcos t) = [|| PrimAcos $$(liftFloatingType t) ||]+liftPrimFun (PrimAtan t) = [|| PrimAtan $$(liftFloatingType t) ||]+liftPrimFun (PrimSinh t) = [|| PrimSinh $$(liftFloatingType t) ||]+liftPrimFun (PrimCosh t) = [|| PrimCosh $$(liftFloatingType t) ||]+liftPrimFun (PrimTanh t) = [|| PrimTanh $$(liftFloatingType t) ||]+liftPrimFun (PrimAsinh t) = [|| PrimAsinh $$(liftFloatingType t) ||]+liftPrimFun (PrimAcosh t) = [|| PrimAcosh $$(liftFloatingType t) ||]+liftPrimFun (PrimAtanh t) = [|| PrimAtanh $$(liftFloatingType t) ||]+liftPrimFun (PrimExpFloating t) = [|| PrimExpFloating $$(liftFloatingType t) ||]+liftPrimFun (PrimSqrt t) = [|| PrimSqrt $$(liftFloatingType t) ||]+liftPrimFun (PrimLog t) = [|| PrimLog $$(liftFloatingType t) ||]+liftPrimFun (PrimFPow t) = [|| PrimFPow $$(liftFloatingType t) ||]+liftPrimFun (PrimLogBase t) = [|| PrimLogBase $$(liftFloatingType t) ||]+liftPrimFun (PrimTruncate ta tb) = [|| PrimTruncate $$(liftFloatingType ta) $$(liftIntegralType tb) ||]+liftPrimFun (PrimRound ta tb) = [|| PrimRound $$(liftFloatingType ta) $$(liftIntegralType tb) ||]+liftPrimFun (PrimFloor ta tb) = [|| PrimFloor $$(liftFloatingType ta) $$(liftIntegralType tb) ||]+liftPrimFun (PrimCeiling ta tb) = [|| PrimCeiling $$(liftFloatingType ta) $$(liftIntegralType tb) ||]+liftPrimFun (PrimIsNaN t) = [|| PrimIsNaN $$(liftFloatingType t) ||]+liftPrimFun (PrimIsInfinite t) = [|| PrimIsInfinite $$(liftFloatingType t) ||]+liftPrimFun (PrimAtan2 t) = [|| PrimAtan2 $$(liftFloatingType t) ||]+liftPrimFun (PrimLt t) = [|| PrimLt $$(liftSingleType t) ||]+liftPrimFun (PrimGt t) = [|| PrimGt $$(liftSingleType t) ||]+liftPrimFun (PrimLtEq t) = [|| PrimLtEq $$(liftSingleType t) ||]+liftPrimFun (PrimGtEq t) = [|| PrimGtEq $$(liftSingleType t) ||]+liftPrimFun (PrimEq t) = [|| PrimEq $$(liftSingleType t) ||]+liftPrimFun (PrimNEq t) = [|| PrimNEq $$(liftSingleType t) ||]+liftPrimFun (PrimMax t) = [|| PrimMax $$(liftSingleType t) ||]+liftPrimFun (PrimMin t) = [|| PrimMin $$(liftSingleType t) ||]+liftPrimFun PrimLAnd = [|| PrimLAnd ||]+liftPrimFun PrimLOr = [|| PrimLOr ||]+liftPrimFun PrimLNot = [|| PrimLNot ||]+liftPrimFun (PrimFromIntegral ta tb) = [|| PrimFromIntegral $$(liftIntegralType ta) $$(liftNumType tb) ||]+liftPrimFun (PrimToFloating ta tb) = [|| PrimToFloating $$(liftNumType ta) $$(liftFloatingType tb) ||]+++formatDirection :: Format r (Direction -> r)+formatDirection = later $ \case+ LeftToRight -> singleton 'l'+ RightToLeft -> singleton 'r'++formatPreAccOp :: Format r (PreOpenAcc acc aenv arrs -> r)+formatPreAccOp = later $ \case+ Alet{} -> "Alet"+ Avar (Var _ ix) -> bformat ("Avar a" % int) (idxToInt ix)+ Use aR a -> bformat ("Use " % string) (showArrayShort 5 (showsElt (arrayRtype aR)) aR a)+ Atrace{} -> "Atrace"+ Apply{} -> "Apply"+ Aforeign{} -> "Aforeign"+ Acond{} -> "Acond"+ Awhile{} -> "Awhile"+ Apair{} -> "Apair"+ Anil -> "Anil"+ Unit{} -> "Unit"+ Generate{} -> "Generate"+ Transform{} -> "Transform"+ Reshape{} -> "Reshape"+ Replicate{} -> "Replicate"+ Slice{} -> "Slice"+ Map{} -> "Map"+ ZipWith{} -> "ZipWith"+ Fold _ z _ -> bformat ("Fold" % maybed "1" (fconst mempty)) z+ FoldSeg _ _ z _ _ -> bformat ("Fold" % maybed "1" (fconst mempty) % "Seg") z+ Scan d _ z _ -> bformat ("Scan" % formatDirection % maybed "1" (fconst mempty)) d z+ Scan' d _ _ _ -> bformat ("Scan" % formatDirection % "\'") d+ Permute{} -> "Permute"+ Backpermute{} -> "Backpermute"+ Stencil{} -> "Stencil"+ Stencil2{} -> "Stencil2"++formatExpOp :: Format r (OpenExp aenv env t -> r)+formatExpOp = later $ \case+ Let{} -> "Let"+ Evar (Var _ ix) -> bformat ("Var x" % int) (idxToInt ix)+ Const tp c -> bformat ("Const " % string) (showElt (TupRsingle tp) c)+ Undef{} -> "Undef"+ Foreign{} -> "Foreign"+ Pair{} -> "Pair"+ Nil{} -> "Nil"+ VecPack{} -> "VecPack"+ VecUnpack{} -> "VecUnpack"+ IndexSlice{} -> "IndexSlice"+ IndexFull{} -> "IndexFull"+ ToIndex{} -> "ToIndex"+ FromIndex{} -> "FromIndex"+ Case{} -> "Case"+ Cond{} -> "Cond"+ While{} -> "While"+ PrimConst{} -> "PrimConst"+ PrimApp{} -> "PrimApp"+ Index{} -> "Index"+ LinearIndex{} -> "LinearIndex"+ Shape{} -> "Shape"+ ShapeSize{} -> "ShapeSize"+ Coerce{} -> "Coerce"+
+ src/Data/Array/Accelerate/AST/Environment.hs view
@@ -0,0 +1,91 @@+{-# LANGUAGE EmptyCase #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeOperators #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.AST.Environment+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.AST.Environment+ where++import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.AST.LeftHandSide+import Data.Array.Accelerate.Error+++-- Valuation for an environment+--+data Val env where+ Empty :: Val ()+ Push :: Val env -> t -> Val (env, t)++-- Push a set of variables into an environment+--+push :: Val env -> (LeftHandSide s t env env', t) -> Val env'+push env (LeftHandSideWildcard _, _ ) = env+push env (LeftHandSideSingle _ , a ) = env `Push` a+push env (LeftHandSidePair l1 l2, (a, b)) = push env (l1, a) `push` (l2, b)++-- Projection of a value from a valuation using a de Bruijn index+--+prj :: Idx env t -> Val env -> t+prj ZeroIdx (Push _ v) = v+prj (SuccIdx idx) (Push val _) = prj idx val+++-- The type of shifting terms from one context into another+--+-- This is defined as a newtype, as a type synonym containing a forall+-- quantifier may give issues with impredicative polymorphism, which GHC+-- does not support.+--+newtype env :> env' = Weaken { (>:>) :: forall t'. Idx env t' -> Idx env' t' } -- Weak or Weaken++weakenId :: env :> env+weakenId = Weaken id++weakenSucc' :: env :> env' -> env :> (env', t)+weakenSucc' (Weaken f) = Weaken (SuccIdx . f)++weakenSucc :: (env, t) :> env' -> env :> env'+weakenSucc (Weaken f) = Weaken (f . SuccIdx)++weakenEmpty :: () :> env'+weakenEmpty = Weaken $ \(VoidIdx x) -> x++sink :: forall env env' t. env :> env' -> (env, t) :> (env', t)+sink (Weaken f) = Weaken g+ where+ g :: Idx (env, t) t' -> Idx (env', t) t'+ g ZeroIdx = ZeroIdx+ g (SuccIdx ix) = SuccIdx $ f ix++infixr 9 .>+(.>) :: env2 :> env3 -> env1 :> env2 -> env1 :> env3+(.>) (Weaken f) (Weaken g) = Weaken (f . g)++sinkWithLHS :: HasCallStack => LeftHandSide s t env1 env1' -> LeftHandSide s t env2 env2' -> env1 :> env2 -> env1' :> env2'+sinkWithLHS (LeftHandSideWildcard _) (LeftHandSideWildcard _) k = k+sinkWithLHS (LeftHandSideSingle _) (LeftHandSideSingle _) k = sink k+sinkWithLHS (LeftHandSidePair a1 b1) (LeftHandSidePair a2 b2) k = sinkWithLHS b1 b2 $ sinkWithLHS a1 a2 k+sinkWithLHS _ _ _ = internalError "left hand sides do not match"++weakenWithLHS :: forall s t env env'. LeftHandSide s t env env' -> env :> env'+weakenWithLHS = go weakenId+ where+ go :: env2 :> env' -> LeftHandSide s arrs env1 env2 -> env1 :> env'+ go k (LeftHandSideWildcard _) = k+ go k (LeftHandSideSingle _) = weakenSucc k+ go k (LeftHandSidePair l1 l2) = go (go k l2) l1+
+ src/Data/Array/Accelerate/AST/Idx.hs view
@@ -0,0 +1,119 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE EmptyCase #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE ViewPatterns #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.AST.Idx+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- Typed de Bruijn indices+--++module Data.Array.Accelerate.AST.Idx (++ Idx, pattern ZeroIdx, pattern SuccIdx, pattern VoidIdx,+ idxToInt,+ rnfIdx, liftIdx,++ PairIdx(..)++) where++import Data.Kind+import Language.Haskell.TH.Extra hiding ( Type )++#ifndef ACCELERATE_INTERNAL_CHECKS+import Data.Type.Equality ( (:~:)(Refl) )+import Unsafe.Coerce ( unsafeCoerce )+#endif+++#ifdef ACCELERATE_INTERNAL_CHECKS++-- | De Bruijn variable index projecting a specific type from a type+-- environment. Type environments are nested pairs (..((), t1), t2, ..., tn).+--+data Idx env t where+ ZeroIdx :: Idx (env, t) t+ SuccIdx :: Idx env t -> Idx (env, s) t++idxToInt :: Idx env t -> Int+idxToInt ZeroIdx = 0+idxToInt (SuccIdx idx) = 1 + idxToInt idx++rnfIdx :: Idx env t -> ()+rnfIdx ZeroIdx = ()+rnfIdx (SuccIdx ix) = rnfIdx ix++liftIdx :: Idx env t -> CodeQ (Idx env t)+liftIdx ZeroIdx = [|| ZeroIdx ||]+liftIdx (SuccIdx ix) = [|| SuccIdx $$(liftIdx ix) ||]++#else++-- | De Bruijn variable index projecting a specific type from a type+-- environment. Type environments are nested pairs (..((), t1), t2, ..., tn).+--+-- Outside of this file, pretend that this is an ordinary GADT:+-- data Idx env t where+-- ZeroIdx :: Idx (env, t) t+-- SuccIdx :: Idx env t -> Idx (env, s) t+--+-- For performance, it uses an Int under the hood.+--+newtype Idx :: Type -> Type -> Type where+ UnsafeIdxConstructor :: { unsafeRunIdx :: Int } -> Idx env t++{-# COMPLETE ZeroIdx, SuccIdx #-}++pattern ZeroIdx :: forall envt t. () => forall env. (envt ~ (env, t)) => Idx envt t+pattern ZeroIdx <- (\x -> (idxToInt x, unsafeCoerce Refl) -> (0, Refl :: envt :~: (env, t)))+ where+ ZeroIdx = UnsafeIdxConstructor 0++pattern SuccIdx :: forall envs t. () => forall s env. (envs ~ (env, s)) => Idx env t -> Idx envs t+pattern SuccIdx idx <- (unSucc -> Just (idx, Refl))+ where+ SuccIdx (UnsafeIdxConstructor i) = UnsafeIdxConstructor (i+1)++unSucc :: Idx envs t -> Maybe (Idx env t, envs :~: (env, s))+unSucc (UnsafeIdxConstructor i)+ | i < 1 = Nothing+ | otherwise = Just (UnsafeIdxConstructor (i-1), unsafeCoerce Refl)++idxToInt :: Idx env t -> Int+idxToInt = unsafeRunIdx++rnfIdx :: Idx env t -> ()+rnfIdx !_ = ()++liftIdx :: Idx env t -> CodeQ (Idx env t)+liftIdx (UnsafeIdxConstructor i) = [|| UnsafeIdxConstructor i ||]++#endif++-- | Despite the 'complete' pragma above, GHC can't infer that there is no+-- pattern possible if the environment is empty. This can be used instead.+--+pattern VoidIdx :: forall env t a. (env ~ ()) => () => a -> Idx env t+pattern VoidIdx a <- (\case{} -> a)++{-# COMPLETE VoidIdx #-}++data PairIdx p a where+ PairIdxLeft :: PairIdx (a, b) a+ PairIdxRight :: PairIdx (a, b) b+
+ src/Data/Array/Accelerate/AST/LeftHandSide.hs view
@@ -0,0 +1,67 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE QuantifiedConstraints #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeOperators #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.AST.LeftHandSide+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.AST.LeftHandSide+ where++import Data.Array.Accelerate.Representation.Type++import Language.Haskell.TH.Extra+++data Exists f where+ Exists :: f a -> Exists f++data LeftHandSide s v env env' where+ LeftHandSideSingle+ :: s v+ -> LeftHandSide s v env (env, v)++ LeftHandSideWildcard+ :: TupR s v+ -> LeftHandSide s v env env++ LeftHandSidePair+ :: LeftHandSide s v1 env env'+ -> LeftHandSide s v2 env' env''+ -> LeftHandSide s (v1, v2) env env''++deriving instance (forall a. Show (s a)) => Show (LeftHandSide s v env env')++pattern LeftHandSideUnit+ :: () -- required+ => (env' ~ env, v ~ ()) -- provided+ => LeftHandSide s v env env'+pattern LeftHandSideUnit = LeftHandSideWildcard TupRunit++lhsToTupR :: LeftHandSide s v env env' -> TupR s v+lhsToTupR (LeftHandSideSingle s) = TupRsingle s+lhsToTupR (LeftHandSideWildcard r) = r+lhsToTupR (LeftHandSidePair as bs) = TupRpair (lhsToTupR as) (lhsToTupR bs)++rnfLeftHandSide :: (forall b. s b -> ()) -> LeftHandSide s v env env' -> ()+rnfLeftHandSide f (LeftHandSideWildcard r) = rnfTupR f r+rnfLeftHandSide f (LeftHandSideSingle s) = f s+rnfLeftHandSide f (LeftHandSidePair as bs) = rnfLeftHandSide f as `seq` rnfLeftHandSide f bs++liftLeftHandSide :: (forall u. s u -> CodeQ (s u)) -> LeftHandSide s v env env' -> CodeQ (LeftHandSide s v env env')+liftLeftHandSide f (LeftHandSideSingle s) = [|| LeftHandSideSingle $$(f s) ||]+liftLeftHandSide f (LeftHandSideWildcard r) = [|| LeftHandSideWildcard $$(liftTupR f r) ||]+liftLeftHandSide f (LeftHandSidePair as bs) = [|| LeftHandSidePair $$(liftLeftHandSide f as) $$(liftLeftHandSide f bs) ||]+
+ src/Data/Array/Accelerate/AST/Var.hs view
@@ -0,0 +1,44 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TemplateHaskell #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.AST.Var+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.AST.Var+ where++import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.AST.Idx++import Language.Haskell.TH.Extra+++data Var s env t = Var (s t) (Idx env t)+type Vars s env = TupR (Var s env)++varsType :: Vars s env t -> TupR s t+varsType TupRunit = TupRunit+varsType (TupRsingle (Var t _)) = TupRsingle t+varsType (TupRpair a b) = TupRpair (varsType a) (varsType b)+++rnfVar :: (forall b. s b -> ()) -> Var s env t -> ()+rnfVar f (Var t idx) = f t `seq` rnfIdx idx++rnfVars :: (forall b. s b -> ()) -> Vars s env t -> ()+rnfVars f = rnfTupR (rnfVar f)++liftVar :: (forall b. s b -> CodeQ (s b)) -> Var s env t -> CodeQ (Var s env t)+liftVar f (Var s idx) = [|| Var $$(f s) $$(liftIdx idx) ||]++liftVars :: (forall b. s b -> CodeQ (s b)) -> Vars s env t -> CodeQ (Vars s env t)+liftVars f = liftTupR (liftVar f)+
+ src/Data/Array/Accelerate/Analysis/Hash.hs view
@@ -0,0 +1,506 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Analysis.Hash+-- Copyright : [2017..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Analysis.Hash (++ -- hashing expressions+ Hash,+ HashOptions(..), defaultHashOptions,+ hashPreOpenAcc, hashPreOpenAccWith,+ hashOpenFun, hashOpenExp,++ -- auxiliary+ EncodeAcc,+ encodePreOpenAcc,+ encodeOpenExp,+ encodeOpenFun,+ encodeArraysType,+ hashQ,++) where++import Data.Array.Accelerate.AST+import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.AST.LeftHandSide+import Data.Array.Accelerate.AST.Var+import Data.Array.Accelerate.Analysis.Hash.TH+import Data.Array.Accelerate.Representation.Array+import Data.Array.Accelerate.Representation.Shape+import Data.Array.Accelerate.Representation.Slice+import Data.Array.Accelerate.Representation.Stencil+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Type+import Data.Primitive.Vec+import Crypto.Hash.XKCP++import Data.ByteString.Builder+import Data.ByteString.Builder.Extra+import Data.ByteString.Short.Internal ( ShortByteString(..) )+import Data.Monoid+import System.IO.Unsafe ( unsafePerformIO )+import System.Mem.StableName ( hashStableName, makeStableName )+import Prelude hiding ( exp )+import qualified Data.Hashable as Hashable+++-- Hashing+-- -------++type Hash = SHA3_256++data HashOptions = HashOptions+ { perfect :: Bool+ -- ^ Should the hash function include _all_ substructure, recursively?+ --+ -- Set to true (the default) if you want a truly unique fingerprint for+ -- the entire expression:+ --+ -- Example:+ --+ -- xs, ys :: Acc (Vector Float)+ -- xs = fill (constant (Z:.10)) 1.0+ -- ys = fill (constant (Z:.20)) 1.0+ --+ -- with perfect=True:+ --+ -- hash xs = 2e1f91aca4c476d13b36f22462e73c15bbdd9fcacb0d4996280f6004058e9732+ -- hash ys = 2fce5c849b6c652192b09aaeafdc8029e57b9f006c1ecd79ccf9114f349aaf9e+ --+ -- However, for a code generating backend the object code used to+ -- evaluate both of these expressions is likely to be identical.+ --+ -- Setting perfect=False results in:+ --+ -- hash xs = hash ys = f97944b0ec64ab8aa989fd60c8b50e7ec3eff759d22d2b340039d837d74dfc3c+ --+ -- Note that to be useful the provided 'EncodeAcc' function must also+ -- understand this option, and the consumer of the hash value must be+ -- agnostic to the elided details.+ }+ deriving Show++defaultHashOptions :: HashOptions+defaultHashOptions = HashOptions True+++{-# INLINEABLE hashPreOpenAcc #-}+hashPreOpenAcc :: HasArraysR acc => EncodeAcc acc -> PreOpenAcc acc aenv a -> Hash+hashPreOpenAcc = hashPreOpenAccWith defaultHashOptions++{-# INLINEABLE hashPreOpenAccWith #-}+hashPreOpenAccWith :: HasArraysR acc => HashOptions -> EncodeAcc acc -> PreOpenAcc acc aenv a -> Hash+hashPreOpenAccWith options encodeAcc+ = hashlazy+ . toLazyByteString+ . encodePreOpenAcc options encodeAcc++{-# INLINEABLE hashOpenFun #-}+hashOpenFun :: OpenFun env aenv f -> Hash+hashOpenFun+ = hashlazy+ . toLazyByteString+ . encodeOpenFun++{-# INLINEABLE hashOpenExp #-}+hashOpenExp :: OpenExp env aenv t -> Hash+hashOpenExp+ = hashlazy+ . toLazyByteString+ . encodeOpenExp+++-- Array computations+-- ------------------++type EncodeAcc acc = forall aenv a. HashOptions -> acc aenv a -> Builder++{-# INLINEABLE encodePreOpenAcc #-}+encodePreOpenAcc+ :: forall acc aenv arrs. HasArraysR acc+ => HashOptions+ -> EncodeAcc acc+ -> PreOpenAcc acc aenv arrs+ -> Builder+encodePreOpenAcc options encodeAcc pacc =+ let+ travA :: forall aenv' a. acc aenv' a -> Builder+ travA = encodeAcc options++ travAF :: PreOpenAfun acc aenv' f -> Builder+ travAF = encodePreOpenAfun options encodeAcc++ travE :: OpenExp env' aenv' e -> Builder+ travE = encodeOpenExp++ travF :: OpenFun env' aenv' f -> Builder+ travF = encodeOpenFun++ travD :: Direction -> Builder+ travD LeftToRight = intHost $(hashQ "L")+ travD RightToLeft = intHost $(hashQ "R")++ deep :: Builder -> Builder+ deep | perfect options = id+ | otherwise = const mempty++ deepE :: forall env' aenv' e. OpenExp env' aenv' e -> Builder+ deepE e+ | perfect options = travE e+ | otherwise = encodeTypeR $ expType e+ in+ case pacc of+ Alet lhs bnd body -> intHost $(hashQ "Alet") <> encodeLeftHandSide encodeArrayType lhs <> travA bnd <> travA body+ Avar (Var repr v) -> intHost $(hashQ "Avar") <> encodeArrayType repr <> deep (encodeIdx v)+ Apair a1 a2 -> intHost $(hashQ "Apair") <> travA a1 <> travA a2+ Anil -> intHost $(hashQ "Anil")+ Atrace (Message _ _ msg) as bs -> intHost $(hashQ "Atrace") <> intHost (Hashable.hash msg) <> travA as <> travA bs+ Apply _ f a -> intHost $(hashQ "Apply") <> travAF f <> travA a+ Aforeign _ _ f a -> intHost $(hashQ "Aforeign") <> travAF f <> travA a+ Use repr a -> intHost $(hashQ "Use") <> encodeArrayType repr <> deep (encodeArray a)+ Awhile p f a -> intHost $(hashQ "Awhile") <> travAF f <> travAF p <> travA a+ Unit _ e -> intHost $(hashQ "Unit") <> travE e+ Generate _ e f -> intHost $(hashQ "Generate") <> deepE e <> travF f+ -- We don't need to encode the type of 'e' when perfect is False, as 'e' is an expression of type Bool.+ -- We thus use `deep (travE e)` instead of `deepE e`.+ Acond e a1 a2 -> intHost $(hashQ "Acond") <> deep (travE e) <> travA a1 <> travA a2+ Reshape _ sh a -> intHost $(hashQ "Reshape") <> deepE sh <> travA a+ Backpermute _ sh f a -> intHost $(hashQ "Backpermute") <> deepE sh <> travF f <> travA a+ Transform _ sh f1 f2 a -> intHost $(hashQ "Transform") <> deepE sh <> travF f1 <> travF f2 <> travA a+ Replicate spec ix a -> intHost $(hashQ "Replicate") <> deepE ix <> travA a <> encodeSliceIndex spec+ Slice spec a ix -> intHost $(hashQ "Slice") <> deepE ix <> travA a <> encodeSliceIndex spec+ Map _ f a -> intHost $(hashQ "Map") <> travF f <> travA a+ ZipWith _ f a1 a2 -> intHost $(hashQ "ZipWith") <> travF f <> travA a1 <> travA a2+ Fold f e a -> intHost $(hashQ "Fold") <> travF f <> encodeMaybe travE e <> travA a+ FoldSeg _ f e a s -> intHost $(hashQ "FoldSeg") <> travF f <> encodeMaybe travE e <> travA a <> travA s+ Scan d f e a -> intHost $(hashQ "Scan") <> travD d <> travF f <> encodeMaybe travE e <> travA a+ Scan' d f e a -> intHost $(hashQ "Scan'") <> travD d <> travF f <> travE e <> travA a+ Permute f1 a1 f2 a2 -> intHost $(hashQ "Permute") <> travF f1 <> travA a1 <> travF f2 <> travA a2+ Stencil s _ f b a -> intHost $(hashQ "Stencil") <> travF f <> encodeBoundary (stencilEltR s) b <> travA a+ Stencil2 s1 s2 _ f b1 a1 b2 a2 -> intHost $(hashQ "Stencil2") <> travF f <> encodeBoundary (stencilEltR s1) b1 <> travA a1 <> encodeBoundary (stencilEltR s2) b2 <> travA a2++{--+{-# INLINEABLE encodePreOpenSeq #-}+encodePreOpenSeq :: forall acc aenv senv arrs. EncodeAcc acc -> PreOpenSeq acc aenv senv arrs -> Int+encodePreOpenSeq encodeAcc s =+ let+ travA :: acc aenv' a -> Builder+ travA = encodeAcc -- XXX: plus type information?++ travE :: OpenExp env' aenv' e -> Builder+ travE = encodeOpenExp encodeAcc++ travAF :: PreOpenAfun acc aenv' f -> Builder+ travAF = encodePreOpenAfun encodeAcc++ travF :: OpenFun env' aenv' f -> Builder+ travF = encodeOpenFun encodeAcc++ travS :: PreOpenSeq acc aenv senv' arrs' -> Builder+ travS = encodePreOpenSeq encodeAcc++ travV :: forall a. Arrays a => Idx senv' a -> Builder+ travV v = encodeArraysType (arrays @a) <> encodeIdx v++ travP :: Producer acc aenv senv a -> Builder+ travP p =+ case p of+ StreamIn arrs -> intHost . unsafePerformIO $! hashStableName `fmap` makeStableName arrs+ ToSeq spec _ acc -> intHost $(hashQ "ToSeq") <> travA acc <> stringUtf8 (show spec)+ MapSeq f x -> intHost $(hashQ "MapSeq") <> travAF f <> travV x+ ChunkedMapSeq f x -> intHost $(hashQ "ChunkedMapSeq") <> travAF f <> travV x+ ZipWithSeq f x y -> intHost $(hashQ "ZipWithSeq") <> travAF f <> travV x <> travV y+ ScanSeq f e x -> intHost $(hashQ "ScanSeq") <> travF f <> travE e <> travV x++ travC :: Consumer acc aenv senv' a -> Builder+ travC c =+ case c of+ FoldSeq f e x -> intHost $(hashQ "FoldSeq") <> travF f <> travE e <> travV x+ FoldSeqFlatten f acc x -> intHost $(hashQ "FoldSeqFlatten") <> travAF f <> travA acc <> travV x+ Stuple t -> intHost $(hashQ "Stuple") <> encodeAtuple travC t+ in+ case s of+ Producer p s' -> intHost $(hashQ "Producer") <> travP p <> travS s'+ Consumer c -> intHost $(hashQ "Consumer") <> travC c+ Reify ix -> intHost $(hashQ "Reify") <> travV ix+--}++encodeIdx :: Idx env t -> Builder+encodeIdx = intHost . idxToInt++encodeArray :: Array sh e -> Builder+encodeArray ad = intHost . unsafePerformIO $! hashStableName <$> makeStableName ad++encodeTupR :: (forall b. s b -> Builder) -> TupR s a -> Builder+encodeTupR _ TupRunit = intHost $(hashQ "TupRunit")+encodeTupR f (TupRpair r1 r2) = intHost $(hashQ "TupRpair") <> encodeTupR f r1 <> encodeTupR f r2+encodeTupR f (TupRsingle s) = intHost $(hashQ "TupRsingle") <> f s++encodeLeftHandSide :: (forall b. s b -> Builder) -> LeftHandSide s a env env' -> Builder+encodeLeftHandSide f (LeftHandSideWildcard r) = intHost $(hashQ "LeftHandSideWildcard") <> encodeTupR f r+encodeLeftHandSide f (LeftHandSidePair r1 r2) = intHost $(hashQ "LeftHandSidePair") <> encodeLeftHandSide f r1 <> encodeLeftHandSide f r2+encodeLeftHandSide f (LeftHandSideSingle s) = intHost $(hashQ "LeftHandSideArray") <> f s++encodeArrayType :: ArrayR a -> Builder+encodeArrayType (ArrayR shr tp) = encodeShapeR shr <> encodeTypeR tp++encodeArraysType :: ArraysR arrs -> Builder+encodeArraysType = encodeTupR encodeArrayType++encodeShapeR :: ShapeR sh -> Builder+encodeShapeR = intHost . rank++encodePreOpenAfun+ :: forall acc aenv f.+ HashOptions+ -> EncodeAcc acc+ -> PreOpenAfun acc aenv f+ -> Builder+encodePreOpenAfun options travA afun =+ let+ travL :: forall aenv1 aenv2 a b. ALeftHandSide a aenv1 aenv2 -> PreOpenAfun acc aenv2 b -> Builder+ travL lhs l = encodeLeftHandSide encodeArrayType lhs <> encodePreOpenAfun options travA l+ in+ case afun of+ Abody b -> intHost $(hashQ "Abody") <> travA options b+ Alam lhs l -> intHost $(hashQ "Alam") <> travL lhs l+++encodeBoundary+ :: TypeR e+ -> Boundary aenv (Array sh e)+ -> Builder+encodeBoundary _ Wrap = intHost $(hashQ "Wrap")+encodeBoundary _ Clamp = intHost $(hashQ "Clamp")+encodeBoundary _ Mirror = intHost $(hashQ "Mirror")+encodeBoundary tp (Constant c) = intHost $(hashQ "Constant") <> encodeConst tp c+encodeBoundary _ (Function f) = intHost $(hashQ "Function") <> encodeOpenFun f++encodeSliceIndex :: SliceIndex slix sl co sh -> Builder+encodeSliceIndex SliceNil = intHost $(hashQ "SliceNil")+encodeSliceIndex (SliceAll r) = intHost $(hashQ "SliceAll") <> encodeSliceIndex r+encodeSliceIndex (SliceFixed r) = intHost $(hashQ "sliceFixed") <> encodeSliceIndex r+++-- Scalar expressions+-- ------------------++{-# INLINEABLE encodeOpenExp #-}+encodeOpenExp+ :: forall env aenv exp.+ OpenExp env aenv exp+ -> Builder+encodeOpenExp exp =+ let+ travE :: forall env' aenv' e. OpenExp env' aenv' e -> Builder+ travE e = encodeOpenExp e++ travF :: OpenFun env' aenv' f -> Builder+ travF = encodeOpenFun+ in+ case exp of+ Let lhs bnd body -> intHost $(hashQ "Let") <> encodeLeftHandSide encodeScalarType lhs <> travE bnd <> travE body+ Evar (Var tp ix) -> intHost $(hashQ "Evar") <> encodeScalarType tp <> encodeIdx ix+ Nil -> intHost $(hashQ "Nil")+ Pair e1 e2 -> intHost $(hashQ "Pair") <> travE e1 <> travE e2+ VecPack _ e -> intHost $(hashQ "VecPack") <> travE e+ VecUnpack _ e -> intHost $(hashQ "VecUnpack") <> travE e+ Const tp c -> intHost $(hashQ "Const") <> encodeScalarConst tp c+ Undef tp -> intHost $(hashQ "Undef") <> encodeScalarType tp+ IndexSlice spec ix sh -> intHost $(hashQ "IndexSlice") <> travE ix <> travE sh <> encodeSliceIndex spec+ IndexFull spec ix sl -> intHost $(hashQ "IndexFull") <> travE ix <> travE sl <> encodeSliceIndex spec+ ToIndex _ sh i -> intHost $(hashQ "ToIndex") <> travE sh <> travE i+ FromIndex _ sh i -> intHost $(hashQ "FromIndex") <> travE sh <> travE i+ Case e rhs def -> intHost $(hashQ "Case") <> travE e <> mconcat [ word8 t <> travE c | (t,c) <- rhs ] <> encodeMaybe travE def+ Cond c t e -> intHost $(hashQ "Cond") <> travE c <> travE t <> travE e+ While p f x -> intHost $(hashQ "While") <> travF p <> travF f <> travE x+ PrimApp f x -> intHost $(hashQ "PrimApp") <> encodePrimFun f <> travE x+ PrimConst c -> intHost $(hashQ "PrimConst") <> encodePrimConst c+ Index a ix -> intHost $(hashQ "Index") <> encodeArrayVar a <> travE ix+ LinearIndex a ix -> intHost $(hashQ "LinearIndex") <> encodeArrayVar a <> travE ix+ Shape a -> intHost $(hashQ "Shape") <> encodeArrayVar a+ ShapeSize _ sh -> intHost $(hashQ "ShapeSize") <> travE sh+ Foreign _ _ f e -> intHost $(hashQ "Foreign") <> travF f <> travE e+ Coerce _ tp e -> intHost $(hashQ "Coerce") <> encodeScalarType tp <> travE e++encodeArrayVar :: ArrayVar aenv a -> Builder+encodeArrayVar (Var repr v) = encodeArrayType repr <> encodeIdx v++{-# INLINEABLE encodeOpenFun #-}+encodeOpenFun+ :: OpenFun env aenv f+ -> Builder+encodeOpenFun (Body b) = intHost $(hashQ "Body") <> encodeOpenExp b+encodeOpenFun (Lam lhs l) = intHost $(hashQ "Lam") <> encodeLeftHandSide encodeScalarType lhs <> encodeOpenFun l+++encodeConst :: TypeR t -> t -> Builder+encodeConst TupRunit () = intHost $(hashQ "nil")+encodeConst (TupRsingle t) c = encodeScalarConst t c+encodeConst (TupRpair ta tb) (a,b) = intHost $(hashQ "pair") <> encodeConst ta a <> encodeConst tb b++encodeScalarConst :: ScalarType t -> t -> Builder+encodeScalarConst (SingleScalarType t) = encodeSingleConst t+encodeScalarConst (VectorScalarType t) = encodeVectorConst t++encodeSingleConst :: SingleType t -> t -> Builder+encodeSingleConst (NumSingleType t) = encodeNumConst t++encodeVectorConst :: VectorType (Vec n t) -> Vec n t -> Builder+encodeVectorConst (VectorType n t) (Vec ba#) = intHost $(hashQ "Vec") <> intHost n <> encodeSingleType t <> shortByteString (SBS ba#)++encodeNumConst :: NumType t -> t -> Builder+encodeNumConst (IntegralNumType t) = encodeIntegralConst t+encodeNumConst (FloatingNumType t) = encodeFloatingConst t++encodeIntegralConst :: IntegralType t -> t -> Builder+encodeIntegralConst TypeInt{} x = intHost $(hashQ "Int") <> intHost x+encodeIntegralConst TypeInt8{} x = intHost $(hashQ "Int8") <> int8 x+encodeIntegralConst TypeInt16{} x = intHost $(hashQ "Int16") <> int16Host x+encodeIntegralConst TypeInt32{} x = intHost $(hashQ "Int32") <> int32Host x+encodeIntegralConst TypeInt64{} x = intHost $(hashQ "Int64") <> int64Host x+encodeIntegralConst TypeWord{} x = intHost $(hashQ "Word") <> wordHost x+encodeIntegralConst TypeWord8{} x = intHost $(hashQ "Word8") <> word8 x+encodeIntegralConst TypeWord16{} x = intHost $(hashQ "Word16") <> word16Host x+encodeIntegralConst TypeWord32{} x = intHost $(hashQ "Word32") <> word32Host x+encodeIntegralConst TypeWord64{} x = intHost $(hashQ "Word64") <> word64Host x++encodeFloatingConst :: FloatingType t -> t -> Builder+encodeFloatingConst TypeHalf{} (Half (CUShort x)) = intHost $(hashQ "Half") <> word16Host x+encodeFloatingConst TypeFloat{} x = intHost $(hashQ "Float") <> floatHost x+encodeFloatingConst TypeDouble{} x = intHost $(hashQ "Double") <> doubleHost x++encodePrimConst :: PrimConst c -> Builder+encodePrimConst (PrimMinBound t) = intHost $(hashQ "PrimMinBound") <> encodeBoundedType t+encodePrimConst (PrimMaxBound t) = intHost $(hashQ "PrimMaxBound") <> encodeBoundedType t+encodePrimConst (PrimPi t) = intHost $(hashQ "PrimPi") <> encodeFloatingType t++encodePrimFun :: PrimFun f -> Builder+encodePrimFun (PrimAdd a) = intHost $(hashQ "PrimAdd") <> encodeNumType a+encodePrimFun (PrimSub a) = intHost $(hashQ "PrimSub") <> encodeNumType a+encodePrimFun (PrimMul a) = intHost $(hashQ "PrimMul") <> encodeNumType a+encodePrimFun (PrimNeg a) = intHost $(hashQ "PrimNeg") <> encodeNumType a+encodePrimFun (PrimAbs a) = intHost $(hashQ "PrimAbs") <> encodeNumType a+encodePrimFun (PrimSig a) = intHost $(hashQ "PrimSig") <> encodeNumType a+encodePrimFun (PrimQuot a) = intHost $(hashQ "PrimQuot") <> encodeIntegralType a+encodePrimFun (PrimRem a) = intHost $(hashQ "PrimRem") <> encodeIntegralType a+encodePrimFun (PrimQuotRem a) = intHost $(hashQ "PrimQuotRem") <> encodeIntegralType a+encodePrimFun (PrimIDiv a) = intHost $(hashQ "PrimIDiv") <> encodeIntegralType a+encodePrimFun (PrimMod a) = intHost $(hashQ "PrimMod") <> encodeIntegralType a+encodePrimFun (PrimDivMod a) = intHost $(hashQ "PrimDivMod") <> encodeIntegralType a+encodePrimFun (PrimBAnd a) = intHost $(hashQ "PrimBAnd") <> encodeIntegralType a+encodePrimFun (PrimBOr a) = intHost $(hashQ "PrimBOr") <> encodeIntegralType a+encodePrimFun (PrimBXor a) = intHost $(hashQ "PrimBXor") <> encodeIntegralType a+encodePrimFun (PrimBNot a) = intHost $(hashQ "PrimBNot") <> encodeIntegralType a+encodePrimFun (PrimBShiftL a) = intHost $(hashQ "PrimBShiftL") <> encodeIntegralType a+encodePrimFun (PrimBShiftR a) = intHost $(hashQ "PrimBShiftR") <> encodeIntegralType a+encodePrimFun (PrimBRotateL a) = intHost $(hashQ "PrimBRotateL") <> encodeIntegralType a+encodePrimFun (PrimBRotateR a) = intHost $(hashQ "PrimBRotateR") <> encodeIntegralType a+encodePrimFun (PrimPopCount a) = intHost $(hashQ "PrimPopCount") <> encodeIntegralType a+encodePrimFun (PrimCountLeadingZeros a) = intHost $(hashQ "PrimCountLeadingZeros") <> encodeIntegralType a+encodePrimFun (PrimCountTrailingZeros a) = intHost $(hashQ "PrimCountTrailingZeros") <> encodeIntegralType a+encodePrimFun (PrimFDiv a) = intHost $(hashQ "PrimFDiv") <> encodeFloatingType a+encodePrimFun (PrimRecip a) = intHost $(hashQ "PrimRecip") <> encodeFloatingType a+encodePrimFun (PrimSin a) = intHost $(hashQ "PrimSin") <> encodeFloatingType a+encodePrimFun (PrimCos a) = intHost $(hashQ "PrimCos") <> encodeFloatingType a+encodePrimFun (PrimTan a) = intHost $(hashQ "PrimTan") <> encodeFloatingType a+encodePrimFun (PrimAsin a) = intHost $(hashQ "PrimAsin") <> encodeFloatingType a+encodePrimFun (PrimAcos a) = intHost $(hashQ "PrimAcos") <> encodeFloatingType a+encodePrimFun (PrimAtan a) = intHost $(hashQ "PrimAtan") <> encodeFloatingType a+encodePrimFun (PrimSinh a) = intHost $(hashQ "PrimSinh") <> encodeFloatingType a+encodePrimFun (PrimCosh a) = intHost $(hashQ "PrimCosh") <> encodeFloatingType a+encodePrimFun (PrimTanh a) = intHost $(hashQ "PrimTanh") <> encodeFloatingType a+encodePrimFun (PrimAsinh a) = intHost $(hashQ "PrimAsinh") <> encodeFloatingType a+encodePrimFun (PrimAcosh a) = intHost $(hashQ "PrimAcosh") <> encodeFloatingType a+encodePrimFun (PrimAtanh a) = intHost $(hashQ "PrimAtanh") <> encodeFloatingType a+encodePrimFun (PrimExpFloating a) = intHost $(hashQ "PrimExpFloating") <> encodeFloatingType a+encodePrimFun (PrimSqrt a) = intHost $(hashQ "PrimSqrt") <> encodeFloatingType a+encodePrimFun (PrimLog a) = intHost $(hashQ "PrimLog") <> encodeFloatingType a+encodePrimFun (PrimFPow a) = intHost $(hashQ "PrimFPow") <> encodeFloatingType a+encodePrimFun (PrimLogBase a) = intHost $(hashQ "PrimLogBase") <> encodeFloatingType a+encodePrimFun (PrimAtan2 a) = intHost $(hashQ "PrimAtan2") <> encodeFloatingType a+encodePrimFun (PrimTruncate a b) = intHost $(hashQ "PrimTruncate") <> encodeFloatingType a <> encodeIntegralType b+encodePrimFun (PrimRound a b) = intHost $(hashQ "PrimRound") <> encodeFloatingType a <> encodeIntegralType b+encodePrimFun (PrimFloor a b) = intHost $(hashQ "PrimFloor") <> encodeFloatingType a <> encodeIntegralType b+encodePrimFun (PrimCeiling a b) = intHost $(hashQ "PrimCeiling") <> encodeFloatingType a <> encodeIntegralType b+encodePrimFun (PrimIsNaN a) = intHost $(hashQ "PrimIsNaN") <> encodeFloatingType a+encodePrimFun (PrimIsInfinite a) = intHost $(hashQ "PrimIsInfinite") <> encodeFloatingType a+encodePrimFun (PrimLt a) = intHost $(hashQ "PrimLt") <> encodeSingleType a+encodePrimFun (PrimGt a) = intHost $(hashQ "PrimGt") <> encodeSingleType a+encodePrimFun (PrimLtEq a) = intHost $(hashQ "PrimLtEq") <> encodeSingleType a+encodePrimFun (PrimGtEq a) = intHost $(hashQ "PrimGtEq") <> encodeSingleType a+encodePrimFun (PrimEq a) = intHost $(hashQ "PrimEq") <> encodeSingleType a+encodePrimFun (PrimNEq a) = intHost $(hashQ "PrimNEq") <> encodeSingleType a+encodePrimFun (PrimMax a) = intHost $(hashQ "PrimMax") <> encodeSingleType a+encodePrimFun (PrimMin a) = intHost $(hashQ "PrimMin") <> encodeSingleType a+encodePrimFun (PrimFromIntegral a b) = intHost $(hashQ "PrimFromIntegral") <> encodeIntegralType a <> encodeNumType b+encodePrimFun (PrimToFloating a b) = intHost $(hashQ "PrimToFloating") <> encodeNumType a <> encodeFloatingType b+encodePrimFun PrimLAnd = intHost $(hashQ "PrimLAnd")+encodePrimFun PrimLOr = intHost $(hashQ "PrimLOr")+encodePrimFun PrimLNot = intHost $(hashQ "PrimLNot")+++encodeTypeR :: TypeR t -> Builder+encodeTypeR TupRunit = intHost $(hashQ "TupRunit")+encodeTypeR (TupRsingle t) = intHost $(hashQ "TupRsingle") <> encodeScalarType t+encodeTypeR (TupRpair a b) = intHost $(hashQ "TupRpair") <> encodeTypeR a <> intHost (depthTypeR a)+ <> encodeTypeR b <> intHost (depthTypeR b)++depthTypeR :: TypeR t -> Int+depthTypeR TupRunit = 0+depthTypeR TupRsingle{} = 1+depthTypeR (TupRpair a b) = depthTypeR a + depthTypeR b++encodeScalarType :: ScalarType t -> Builder+encodeScalarType (SingleScalarType t) = intHost $(hashQ "SingleScalarType") <> encodeSingleType t+encodeScalarType (VectorScalarType t) = intHost $(hashQ "VectorScalarType") <> encodeVectorType t++encodeSingleType :: SingleType t -> Builder+encodeSingleType (NumSingleType t) = intHost $(hashQ "NumSingleType") <> encodeNumType t++encodeVectorType :: VectorType (Vec n t) -> Builder+encodeVectorType (VectorType n t) = intHost $(hashQ "VectorType") <> intHost n <> encodeSingleType t++encodeBoundedType :: BoundedType t -> Builder+encodeBoundedType (IntegralBoundedType t) = intHost $(hashQ "IntegralBoundedType") <> encodeIntegralType t++encodeNumType :: NumType t -> Builder+encodeNumType (IntegralNumType t) = intHost $(hashQ "IntegralNumType") <> encodeIntegralType t+encodeNumType (FloatingNumType t) = intHost $(hashQ "FloatingNumType") <> encodeFloatingType t++encodeIntegralType :: IntegralType t -> Builder+encodeIntegralType TypeInt{} = intHost $(hashQ "Int")+encodeIntegralType TypeInt8{} = intHost $(hashQ "Int8")+encodeIntegralType TypeInt16{} = intHost $(hashQ "Int16")+encodeIntegralType TypeInt32{} = intHost $(hashQ "Int32")+encodeIntegralType TypeInt64{} = intHost $(hashQ "Int64")+encodeIntegralType TypeWord{} = intHost $(hashQ "Word")+encodeIntegralType TypeWord8{} = intHost $(hashQ "Word8")+encodeIntegralType TypeWord16{} = intHost $(hashQ "Word16")+encodeIntegralType TypeWord32{} = intHost $(hashQ "Word32")+encodeIntegralType TypeWord64{} = intHost $(hashQ "Word64")++encodeFloatingType :: FloatingType t -> Builder+encodeFloatingType TypeHalf{} = intHost $(hashQ "Half")+encodeFloatingType TypeFloat{} = intHost $(hashQ "Float")+encodeFloatingType TypeDouble{} = intHost $(hashQ "Double")++encodeMaybe :: (a -> Builder) -> Maybe a -> Builder+encodeMaybe _ Nothing = intHost $(hashQ "Nothing")+encodeMaybe f (Just x) = intHost $(hashQ "Just") <> f x+
+ src/Data/Array/Accelerate/Analysis/Hash/TH.hs view
@@ -0,0 +1,30 @@+-- |+-- Module : Data.Array.Accelerate.Analysis.Hash.TH+-- Copyright : [2017..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Analysis.Hash.TH (++ hashQ,+ hashWithSaltQ,++) where++import Data.Hashable+import Language.Haskell.TH+++hashQ :: Hashable a => a -> ExpQ+hashQ = intE . hash++hashWithSaltQ :: Hashable a => Int -> a -> ExpQ+hashWithSaltQ s x = intE (hashWithSalt s x)++intE :: Int -> ExpQ+intE = litE . integerL . fromIntegral+
+ src/Data/Array/Accelerate/Analysis/Match.hs view
@@ -0,0 +1,917 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeOperators #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Analysis.Match+-- Copyright : [2012..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Analysis.Match (++ -- matching expressions+ MatchAcc,+ (:~:)(..),+ matchPreOpenAcc,+ matchPreOpenAfun,+ matchOpenExp,+ matchOpenFun,+ matchPrimFun, matchPrimFun',++ -- auxiliary+ matchIdx, matchVar, matchVars, matchArrayR, matchArraysR, matchTypeR, matchShapeR,+ matchShapeType, matchIntegralType, matchFloatingType, matchNumType, matchScalarType,+ matchLeftHandSide, matchALeftHandSide, matchELeftHandSide, matchSingleType, matchTupR++) where++import Data.Array.Accelerate.AST+import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.AST.LeftHandSide+import Data.Array.Accelerate.AST.Var+import Data.Array.Accelerate.Analysis.Hash+import Data.Array.Accelerate.Representation.Array+import Data.Array.Accelerate.Representation.Shape+import Data.Array.Accelerate.Representation.Slice+import Data.Array.Accelerate.Representation.Stencil+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Type+import Data.Primitive.Vec+import qualified Data.Array.Accelerate.Sugar.Shape as Sugar++import Data.Maybe+import Data.Typeable+import Unsafe.Coerce ( unsafeCoerce )+import System.IO.Unsafe ( unsafePerformIO )+import System.Mem.StableName+import Prelude hiding ( exp )+++-- The type of matching array computations+--+type MatchAcc acc = forall aenv s t. acc aenv s -> acc aenv t -> Maybe (s :~: t)+++-- Compute the congruence of two array computations. The nodes are congruent if+-- they have the same operator and their operands are congruent.+--+{-# INLINEABLE matchPreOpenAcc #-}+matchPreOpenAcc+ :: forall acc aenv s t. HasArraysR acc+ => MatchAcc acc+ -> PreOpenAcc acc aenv s+ -> PreOpenAcc acc aenv t+ -> Maybe (s :~: t)+matchPreOpenAcc matchAcc = match+ where+ matchFun :: OpenFun env' aenv' u -> OpenFun env' aenv' v -> Maybe (u :~: v)+ matchFun = matchOpenFun++ matchExp :: OpenExp env' aenv' u -> OpenExp env' aenv' v -> Maybe (u :~: v)+ matchExp = matchOpenExp++ match :: PreOpenAcc acc aenv s -> PreOpenAcc acc aenv t -> Maybe (s :~: t)+ match (Alet lhs1 x1 a1) (Alet lhs2 x2 a2)+ | Just Refl <- matchALeftHandSide lhs1 lhs2+ , Just Refl <- matchAcc x1 x2+ , Just Refl <- matchAcc a1 a2+ = Just Refl++ match (Avar v1) (Avar v2)+ = matchVar v1 v2++ match (Apair a1 a2) (Apair b1 b2)+ | Just Refl <- matchAcc a1 b1+ , Just Refl <- matchAcc a2 b2+ = Just Refl++ match Anil Anil+ = Just Refl++ match (Apply _ f1 a1) (Apply _ f2 a2)+ | Just Refl <- matchPreOpenAfun matchAcc f1 f2+ , Just Refl <- matchAcc a1 a2+ = Just Refl++ match (Aforeign _ ff1 f1 a1) (Aforeign _ ff2 f2 a2)+ | Just Refl <- matchAcc a1 a2+ , unsafePerformIO $ do+ sn1 <- makeStableName ff1+ sn2 <- makeStableName ff2+ return $! hashStableName sn1 == hashStableName sn2+ , Just Refl <- matchPreOpenAfun matchAcc f1 f2+ = Just Refl++ match (Acond p1 t1 e1) (Acond p2 t2 e2)+ | Just Refl <- matchExp p1 p2+ , Just Refl <- matchAcc t1 t2+ , Just Refl <- matchAcc e1 e2+ = Just Refl++ match (Awhile p1 f1 a1) (Awhile p2 f2 a2)+ | Just Refl <- matchAcc a1 a2+ , Just Refl <- matchPreOpenAfun matchAcc p1 p2+ , Just Refl <- matchPreOpenAfun matchAcc f1 f2+ = Just Refl++ match (Use repr1 a1) (Use repr2 a2)+ | Just Refl <- matchArray repr1 repr2 a1 a2+ = Just Refl++ match (Unit t1 e1) (Unit t2 e2)+ | Just Refl <- matchTypeR t1 t2+ , Just Refl <- matchExp e1 e2+ = Just Refl++ match (Reshape _ sh1 a1) (Reshape _ sh2 a2)+ | Just Refl <- matchExp sh1 sh2+ , Just Refl <- matchAcc a1 a2+ = Just Refl++ match (Generate _ sh1 f1) (Generate _ sh2 f2)+ | Just Refl <- matchExp sh1 sh2+ , Just Refl <- matchFun f1 f2+ = Just Refl++ match (Transform _ sh1 ix1 f1 a1) (Transform _ sh2 ix2 f2 a2)+ | Just Refl <- matchExp sh1 sh2+ , Just Refl <- matchFun ix1 ix2+ , Just Refl <- matchFun f1 f2+ , Just Refl <- matchAcc a1 a2+ = Just Refl++ match (Replicate si1 ix1 a1) (Replicate si2 ix2 a2)+ | Just Refl <- matchSliceIndex si1 si2+ , Just Refl <- matchExp ix1 ix2+ , Just Refl <- matchAcc a1 a2+ = Just Refl++ match (Slice si1 a1 ix1) (Slice si2 a2 ix2)+ | Just Refl <- matchSliceIndex si1 si2+ , Just Refl <- matchAcc a1 a2+ , Just Refl <- matchExp ix1 ix2+ = Just Refl++ match (Map _ f1 a1) (Map _ f2 a2)+ | Just Refl <- matchFun f1 f2+ , Just Refl <- matchAcc a1 a2+ = Just Refl++ match (ZipWith _ f1 a1 b1) (ZipWith _ f2 a2 b2)+ | Just Refl <- matchFun f1 f2+ , Just Refl <- matchAcc a1 a2+ , Just Refl <- matchAcc b1 b2+ = Just Refl++ match (Fold f1 z1 a1) (Fold f2 z2 a2)+ | Just Refl <- matchFun f1 f2+ , matchMaybe matchExp z1 z2+ , Just Refl <- matchAcc a1 a2+ = Just Refl++ match (FoldSeg _ f1 z1 a1 s1) (FoldSeg _ f2 z2 a2 s2)+ | Just Refl <- matchFun f1 f2+ , matchMaybe matchExp z1 z2+ , Just Refl <- matchAcc a1 a2+ , Just Refl <- matchAcc s1 s2+ = Just Refl++ match (Scan d1 f1 z1 a1) (Scan d2 f2 z2 a2)+ | d1 == d2+ , Just Refl <- matchFun f1 f2+ , matchMaybe matchExp z1 z2+ , Just Refl <- matchAcc a1 a2+ = Just Refl++ match (Scan' d1 f1 z1 a1) (Scan' d2 f2 z2 a2)+ | d1 == d2+ , Just Refl <- matchFun f1 f2+ , Just Refl <- matchExp z1 z2+ , Just Refl <- matchAcc a1 a2+ = Just Refl++ match (Permute f1 d1 p1 a1) (Permute f2 d2 p2 a2)+ | Just Refl <- matchFun f1 f2+ , Just Refl <- matchAcc d1 d2+ , Just Refl <- matchFun p1 p2+ , Just Refl <- matchAcc a1 a2+ = Just Refl++ match (Backpermute _ sh1 ix1 a1) (Backpermute _ sh2 ix2 a2)+ | Just Refl <- matchExp sh1 sh2+ , Just Refl <- matchFun ix1 ix2+ , Just Refl <- matchAcc a1 a2+ = Just Refl++ match (Stencil s1 _ f1 b1 a1) (Stencil _ _ f2 b2 a2)+ | Just Refl <- matchFun f1 f2+ , Just Refl <- matchAcc a1 a2+ , matchBoundary (stencilEltR s1) b1 b2+ = Just Refl++ match (Stencil2 s1 s2 _ f1 b1 a1 b2 a2) (Stencil2 _ _ _ f2 b1' a1' b2' a2')+ | Just Refl <- matchFun f1 f2+ , Just Refl <- matchAcc a1 a1'+ , Just Refl <- matchAcc a2 a2'+ , matchBoundary (stencilEltR s1) b1 b1'+ , matchBoundary (stencilEltR s2) b2 b2'+ = Just Refl++ -- match (Collect s1) (Collect s2)+ -- = matchSeq matchAcc encodeAcc s1 s2++ match _ _+ = Nothing++-- Array functions+--+{-# INLINEABLE matchPreOpenAfun #-}+matchPreOpenAfun+ :: MatchAcc acc+ -> PreOpenAfun acc aenv s+ -> PreOpenAfun acc aenv t+ -> Maybe (s :~: t)+matchPreOpenAfun m (Alam lhs1 s) (Alam lhs2 t)+ | Just Refl <- matchALeftHandSide lhs1 lhs2+ , Just Refl <- matchPreOpenAfun m s t+ = Just Refl++matchPreOpenAfun m (Abody s) (Abody t) = m s t+matchPreOpenAfun _ _ _ = Nothing++matchALeftHandSide+ :: forall aenv aenv1 aenv2 t1 t2.+ ALeftHandSide t1 aenv aenv1+ -> ALeftHandSide t2 aenv aenv2+ -> Maybe (ALeftHandSide t1 aenv aenv1 :~: ALeftHandSide t2 aenv aenv2)+matchALeftHandSide = matchLeftHandSide matchArrayR++matchELeftHandSide+ :: forall env env1 env2 t1 t2.+ ELeftHandSide t1 env env1+ -> ELeftHandSide t2 env env2+ -> Maybe (ELeftHandSide t1 env env1 :~: ELeftHandSide t2 env env2)+matchELeftHandSide = matchLeftHandSide matchScalarType++matchLeftHandSide+ :: forall s env env1 env2 t1 t2.+ (forall x y. s x -> s y -> Maybe (x :~: y))+ -> LeftHandSide s t1 env env1+ -> LeftHandSide s t2 env env2+ -> Maybe (LeftHandSide s t1 env env1 :~: LeftHandSide s t2 env env2)+matchLeftHandSide f (LeftHandSideWildcard repr1) (LeftHandSideWildcard repr2)+ | Just Refl <- matchTupR f repr1 repr2+ = Just Refl+matchLeftHandSide f (LeftHandSideSingle x) (LeftHandSideSingle y)+ | Just Refl <- f x y+ = Just Refl+matchLeftHandSide f (LeftHandSidePair a1 a2) (LeftHandSidePair b1 b2)+ | Just Refl <- matchLeftHandSide f a1 b1+ , Just Refl <- matchLeftHandSide f a2 b2+ = Just Refl+matchLeftHandSide _ _ _ = Nothing++-- Match stencil boundaries+--+matchBoundary+ :: TypeR t+ -> Boundary aenv (Array sh t)+ -> Boundary aenv (Array sh t)+ -> Bool+matchBoundary _ Clamp Clamp = True+matchBoundary _ Mirror Mirror = True+matchBoundary _ Wrap Wrap = True+matchBoundary tp (Constant s) (Constant t) = matchConst tp s t+matchBoundary _ (Function f) (Function g)+ | Just Refl <- matchOpenFun f g+ = True+matchBoundary _ _ _+ = False++matchMaybe :: (s1 -> s2 -> Maybe (t1 :~: t2)) -> Maybe s1 -> Maybe s2 -> Bool+matchMaybe _ Nothing Nothing = True+matchMaybe f (Just x) (Just y)+ | Just Refl <- f x y = True+matchMaybe _ _ _ = False++{--+-- Match sequences+--+matchSeq+ :: forall acc aenv senv s t.+ MatchAcc acc+ -> EncodeAcc acc+ -> PreOpenSeq acc aenv senv s+ -> PreOpenSeq acc aenv senv t+ -> Maybe (s :~: t)+matchSeq m h = match+ where+ matchFun :: OpenFun env' aenv' u -> OpenFun env' aenv' v -> Maybe (u :~: v)+ matchFun = matchOpenFun m h++ matchExp :: OpenExp env' aenv' u -> OpenExp env' aenv' v -> Maybe (u :~: v)+ matchExp = matchOpenExp m h++ match :: PreOpenSeq acc aenv senv' u -> PreOpenSeq acc aenv senv' v -> Maybe (u :~: v)+ match (Producer p1 s1) (Producer p2 s2)+ | Just Refl <- matchP p1 p2+ , Just Refl <- match s1 s2+ = Just Refl+ match (Consumer c1) (Consumer c2)+ | Just Refl <- matchC c1 c2+ = Just Refl+ match (Reify ix1) (Reify ix2)+ | Just Refl <- matchIdx ix1 ix2+ = Just Refl+ match _ _+ = Nothing++ matchP :: Producer acc aenv senv' u -> Producer acc aenv senv' v -> Maybe (u :~: v)+ matchP (StreamIn arrs1) (StreamIn arrs2)+ | unsafePerformIO $ do+ sn1 <- makeStableName arrs1+ sn2 <- makeStableName arrs2+ return $! hashStableName sn1 == hashStableName sn2+ = gcast Refl+ matchP (ToSeq _ (_::proxy1 slix1) a1) (ToSeq _ (_::proxy2 slix2) a2)+ | Just Refl <- gcast Refl :: Maybe (slix1 :~: slix2) -- Divisions are singleton.+ , Just Refl <- m a1 a2+ = gcast Refl+ matchP (MapSeq f1 x1) (MapSeq f2 x2)+ | Just Refl <- matchPreOpenAfun m f1 f2+ , Just Refl <- matchIdx x1 x2+ = Just Refl+ matchP (ZipWithSeq f1 x1 y1) (ZipWithSeq f2 x2 y2)+ | Just Refl <- matchPreOpenAfun m f1 f2+ , Just Refl <- matchIdx x1 x2+ , Just Refl <- matchIdx y1 y2+ = Just Refl+ matchP (ScanSeq f1 e1 x1) (ScanSeq f2 e2 x2)+ | Just Refl <- matchFun f1 f2+ , Just Refl <- matchIdx x1 x2+ , Just Refl <- matchExp e1 e2+ = Just Refl+ matchP _ _+ = Nothing++ matchC :: Consumer acc aenv senv' u -> Consumer acc aenv senv' v -> Maybe (u :~: v)+ matchC (FoldSeq f1 e1 x1) (FoldSeq f2 e2 x2)+ | Just Refl <- matchIdx x1 x2+ , Just Refl <- matchFun f1 f2+ , Just Refl <- matchExp e1 e2+ = Just Refl+ matchC (FoldSeqFlatten f1 acc1 x1) (FoldSeqFlatten f2 acc2 x2)+ | Just Refl <- matchIdx x1 x2+ , Just Refl <- matchPreOpenAfun m f1 f2+ , Just Refl <- m acc1 acc2+ = Just Refl+ matchC (Stuple s1) (Stuple s2)+ | Just Refl <- matchAtuple matchC s1 s2+ = gcast Refl+ matchC _ _+ = Nothing+--}++-- Match arrays+--+-- As a convenience, we are just comparing the stable names, but we could also+-- walk the structure comparing the underlying ptrsOfArrayData.+--+matchArray :: ArrayR (Array sh1 e1)+ -> ArrayR (Array sh2 e2)+ -> Array sh1 e1+ -> Array sh2 e2+ -> Maybe (Array sh1 e1 :~: Array sh2 e2)+matchArray repr1 repr2 (Array _ ad1) (Array _ ad2)+ | Just Refl <- matchArrayR repr1 repr2+ , unsafePerformIO $ do+ sn1 <- makeStableName ad1+ sn2 <- makeStableName ad2+ return $! hashStableName sn1 == hashStableName sn2+ = Just Refl++matchArray _ _ _ _+ = Nothing++matchTupR :: (forall u1 u2. s u1 -> s u2 -> Maybe (u1 :~: u2)) -> TupR s t1 -> TupR s t2 -> Maybe (t1 :~: t2)+matchTupR _ TupRunit TupRunit = Just Refl+matchTupR f (TupRsingle x) (TupRsingle y) = f x y+matchTupR f (TupRpair x1 x2) (TupRpair y1 y2)+ | Just Refl <- matchTupR f x1 y1+ , Just Refl <- matchTupR f x2 y2 = Just Refl+matchTupR _ _ _ = Nothing++matchArraysR :: ArraysR s -> ArraysR t -> Maybe (s :~: t)+matchArraysR = matchTupR matchArrayR++matchArrayR :: ArrayR s -> ArrayR t -> Maybe (s :~: t)+matchArrayR (ArrayR shr1 tp1) (ArrayR shr2 tp2)+ | Just Refl <- matchShapeR shr1 shr2+ , Just Refl <- matchTypeR tp1 tp2 = Just Refl+matchArrayR _ _ = Nothing+++-- Compute the congruence of two scalar expressions. Two nodes are congruent if+-- either:+--+-- 1. The nodes label constants and the contents are equal+-- 2. They have the same operator and their operands are congruent+--+-- The below attempts to use real typed equality, but occasionally still needs+-- to use a cast, particularly when we can only match the representation types.+--+{-# INLINEABLE matchOpenExp #-}+matchOpenExp+ :: forall env aenv s t.+ OpenExp env aenv s+ -> OpenExp env aenv t+ -> Maybe (s :~: t)++matchOpenExp (Let lhs1 x1 e1) (Let lhs2 x2 e2)+ | Just Refl <- matchELeftHandSide lhs1 lhs2+ , Just Refl <- matchOpenExp x1 x2+ , Just Refl <- matchOpenExp e1 e2+ = Just Refl++matchOpenExp (Evar v1) (Evar v2)+ = matchVar v1 v2++matchOpenExp (Foreign _ ff1 f1 e1) (Foreign _ ff2 f2 e2)+ | Just Refl <- matchOpenExp e1 e2+ , unsafePerformIO $ do+ sn1 <- makeStableName ff1+ sn2 <- makeStableName ff2+ return $! hashStableName sn1 == hashStableName sn2+ , Just Refl <- matchOpenFun f1 f2+ = Just Refl++matchOpenExp (Const t1 c1) (Const t2 c2)+ | Just Refl <- matchScalarType t1 t2+ , matchConst (TupRsingle t1) c1 c2+ = Just Refl++matchOpenExp (Undef t1) (Undef t2) = matchScalarType t1 t2++matchOpenExp (Coerce _ t1 e1) (Coerce _ t2 e2)+ | Just Refl <- matchScalarType t1 t2+ , Just Refl <- matchOpenExp e1 e2+ = Just Refl++matchOpenExp (Pair a1 b1) (Pair a2 b2)+ | Just Refl <- matchOpenExp a1 a2+ , Just Refl <- matchOpenExp b1 b2+ = Just Refl++matchOpenExp Nil Nil+ = Just Refl++matchOpenExp (IndexSlice sliceIndex1 ix1 sh1) (IndexSlice sliceIndex2 ix2 sh2)+ | Just Refl <- matchOpenExp ix1 ix2+ , Just Refl <- matchOpenExp sh1 sh2+ , Just Refl <- matchSliceIndex sliceIndex1 sliceIndex2+ = Just Refl++matchOpenExp (IndexFull sliceIndex1 ix1 sl1) (IndexFull sliceIndex2 ix2 sl2)+ | Just Refl <- matchOpenExp ix1 ix2+ , Just Refl <- matchOpenExp sl1 sl2+ , Just Refl <- matchSliceIndex sliceIndex1 sliceIndex2+ = Just Refl++matchOpenExp (ToIndex _ sh1 i1) (ToIndex _ sh2 i2)+ | Just Refl <- matchOpenExp sh1 sh2+ , Just Refl <- matchOpenExp i1 i2+ = Just Refl++matchOpenExp (FromIndex _ sh1 i1) (FromIndex _ sh2 i2)+ | Just Refl <- matchOpenExp i1 i2+ , Just Refl <- matchOpenExp sh1 sh2+ = Just Refl++matchOpenExp (Cond p1 t1 e1) (Cond p2 t2 e2)+ | Just Refl <- matchOpenExp p1 p2+ , Just Refl <- matchOpenExp t1 t2+ , Just Refl <- matchOpenExp e1 e2+ = Just Refl++matchOpenExp (While p1 f1 x1) (While p2 f2 x2)+ | Just Refl <- matchOpenExp x1 x2+ , Just Refl <- matchOpenFun p1 p2+ , Just Refl <- matchOpenFun f1 f2+ = Just Refl++matchOpenExp (PrimConst c1) (PrimConst c2)+ = matchPrimConst c1 c2++matchOpenExp (PrimApp f1 x1) (PrimApp f2 x2)+ | Just x1' <- commutes f1 x1+ , Just x2' <- commutes f2 x2+ , Just Refl <- matchOpenExp x1' x2'+ , Just Refl <- matchPrimFun f1 f2+ = Just Refl++ | Just Refl <- matchOpenExp x1 x2+ , Just Refl <- matchPrimFun f1 f2+ = Just Refl++matchOpenExp (Index a1 x1) (Index a2 x2)+ | Just Refl <- matchVar a1 a2+ , Just Refl <- matchOpenExp x1 x2+ = Just Refl++matchOpenExp (LinearIndex a1 x1) (LinearIndex a2 x2)+ | Just Refl <- matchVar a1 a2+ , Just Refl <- matchOpenExp x1 x2+ = Just Refl++matchOpenExp (Shape a1) (Shape a2)+ | Just Refl <- matchVar a1 a2+ = Just Refl++matchOpenExp (ShapeSize _ sh1) (ShapeSize _ sh2)+ | Just Refl <- matchOpenExp sh1 sh2+ = Just Refl++matchOpenExp _ _+ = Nothing+++-- Match scalar functions+--+{-# INLINEABLE matchOpenFun #-}+matchOpenFun+ :: OpenFun env aenv s+ -> OpenFun env aenv t+ -> Maybe (s :~: t)+matchOpenFun (Lam lhs1 s) (Lam lhs2 t)+ | Just Refl <- matchELeftHandSide lhs1 lhs2+ , Just Refl <- matchOpenFun s t+ = Just Refl++matchOpenFun (Body s) (Body t) = matchOpenExp s t+matchOpenFun _ _ = Nothing++-- Matching constants+--+matchConst :: TypeR a -> a -> a -> Bool+matchConst TupRunit () () = True+matchConst (TupRsingle ty) a b = evalEq ty (a,b)+matchConst (TupRpair ta tb) (a1,b1) (a2,b2) = matchConst ta a1 a2 && matchConst tb b1 b2++evalEq :: ScalarType a -> (a, a) -> Bool+evalEq (SingleScalarType t) = evalEqSingle t+evalEq (VectorScalarType t) = evalEqVector t++evalEqSingle :: SingleType a -> (a, a) -> Bool+evalEqSingle (NumSingleType t) = evalEqNum t++evalEqVector :: VectorType a -> (a, a) -> Bool+evalEqVector VectorType{} = uncurry (==)++evalEqNum :: NumType a -> (a, a) -> Bool+evalEqNum (IntegralNumType t) | IntegralDict <- integralDict t = uncurry (==)+evalEqNum (FloatingNumType t) | FloatingDict <- floatingDict t = uncurry (==)+++-- Environment projection indices+--+{-# INLINEABLE matchIdx #-}+matchIdx :: Idx env s -> Idx env t -> Maybe (s :~: t)+matchIdx ZeroIdx ZeroIdx = Just Refl+matchIdx (SuccIdx u) (SuccIdx v) = matchIdx u v+matchIdx _ _ = Nothing++{-# INLINEABLE matchVar #-}+matchVar :: Var s env t1 -> Var s env t2 -> Maybe (t1 :~: t2)+matchVar (Var _ v1) (Var _ v2) = matchIdx v1 v2++{-# INLINEABLE matchVars #-}+matchVars :: Vars s env t1 -> Vars s env t2 -> Maybe (t1 :~: t2)+matchVars TupRunit TupRunit = Just Refl+matchVars (TupRsingle v1) (TupRsingle v2)+ | Just Refl <- matchVar v1 v2 = Just Refl+matchVars (TupRpair v w) (TupRpair x y)+ | Just Refl <- matchVars v x+ , Just Refl <- matchVars w y = Just Refl+matchVars _ _ = Nothing+++-- Slice specifications+--+matchSliceIndex :: SliceIndex slix1 sl1 co1 sh1 -> SliceIndex slix2 sl2 co2 sh2 -> Maybe (SliceIndex slix1 sl1 co1 sh1 :~: SliceIndex slix2 sl2 co2 sh2)+matchSliceIndex SliceNil SliceNil+ = Just Refl++matchSliceIndex (SliceAll sl1) (SliceAll sl2)+ | Just Refl <- matchSliceIndex sl1 sl2+ = Just Refl++matchSliceIndex (SliceFixed sl1) (SliceFixed sl2)+ | Just Refl <- matchSliceIndex sl1 sl2+ = Just Refl++matchSliceIndex _ _+ = Nothing++-- Primitive constants and functions+--+matchPrimConst :: PrimConst s -> PrimConst t -> Maybe (s :~: t)+matchPrimConst (PrimMinBound s) (PrimMinBound t) = matchBoundedType s t+matchPrimConst (PrimMaxBound s) (PrimMaxBound t) = matchBoundedType s t+matchPrimConst (PrimPi s) (PrimPi t) = matchFloatingType s t+matchPrimConst _ _ = Nothing+++-- Covariant function matching+--+{-# INLINEABLE matchPrimFun #-}+matchPrimFun :: PrimFun (a -> s) -> PrimFun (a -> t) -> Maybe (s :~: t)+matchPrimFun (PrimAdd _) (PrimAdd _) = Just Refl+matchPrimFun (PrimSub _) (PrimSub _) = Just Refl+matchPrimFun (PrimMul _) (PrimMul _) = Just Refl+matchPrimFun (PrimNeg _) (PrimNeg _) = Just Refl+matchPrimFun (PrimAbs _) (PrimAbs _) = Just Refl+matchPrimFun (PrimSig _) (PrimSig _) = Just Refl+matchPrimFun (PrimQuot _) (PrimQuot _) = Just Refl+matchPrimFun (PrimRem _) (PrimRem _) = Just Refl+matchPrimFun (PrimQuotRem _) (PrimQuotRem _) = Just Refl+matchPrimFun (PrimIDiv _) (PrimIDiv _) = Just Refl+matchPrimFun (PrimMod _) (PrimMod _) = Just Refl+matchPrimFun (PrimDivMod _) (PrimDivMod _) = Just Refl+matchPrimFun (PrimBAnd _) (PrimBAnd _) = Just Refl+matchPrimFun (PrimBOr _) (PrimBOr _) = Just Refl+matchPrimFun (PrimBXor _) (PrimBXor _) = Just Refl+matchPrimFun (PrimBNot _) (PrimBNot _) = Just Refl+matchPrimFun (PrimBShiftL _) (PrimBShiftL _) = Just Refl+matchPrimFun (PrimBShiftR _) (PrimBShiftR _) = Just Refl+matchPrimFun (PrimBRotateL _) (PrimBRotateL _) = Just Refl+matchPrimFun (PrimBRotateR _) (PrimBRotateR _) = Just Refl+matchPrimFun (PrimPopCount _) (PrimPopCount _) = Just Refl+matchPrimFun (PrimCountLeadingZeros _) (PrimCountLeadingZeros _) = Just Refl+matchPrimFun (PrimCountTrailingZeros _) (PrimCountTrailingZeros _) = Just Refl+matchPrimFun (PrimFDiv _) (PrimFDiv _) = Just Refl+matchPrimFun (PrimRecip _) (PrimRecip _) = Just Refl+matchPrimFun (PrimSin _) (PrimSin _) = Just Refl+matchPrimFun (PrimCos _) (PrimCos _) = Just Refl+matchPrimFun (PrimTan _) (PrimTan _) = Just Refl+matchPrimFun (PrimAsin _) (PrimAsin _) = Just Refl+matchPrimFun (PrimAcos _) (PrimAcos _) = Just Refl+matchPrimFun (PrimAtan _) (PrimAtan _) = Just Refl+matchPrimFun (PrimSinh _) (PrimSinh _) = Just Refl+matchPrimFun (PrimCosh _) (PrimCosh _) = Just Refl+matchPrimFun (PrimTanh _) (PrimTanh _) = Just Refl+matchPrimFun (PrimAsinh _) (PrimAsinh _) = Just Refl+matchPrimFun (PrimAcosh _) (PrimAcosh _) = Just Refl+matchPrimFun (PrimAtanh _) (PrimAtanh _) = Just Refl+matchPrimFun (PrimExpFloating _) (PrimExpFloating _) = Just Refl+matchPrimFun (PrimSqrt _) (PrimSqrt _) = Just Refl+matchPrimFun (PrimLog _) (PrimLog _) = Just Refl+matchPrimFun (PrimFPow _) (PrimFPow _) = Just Refl+matchPrimFun (PrimLogBase _) (PrimLogBase _) = Just Refl+matchPrimFun (PrimAtan2 _) (PrimAtan2 _) = Just Refl+matchPrimFun (PrimTruncate _ s) (PrimTruncate _ t) = matchIntegralType s t+matchPrimFun (PrimRound _ s) (PrimRound _ t) = matchIntegralType s t+matchPrimFun (PrimFloor _ s) (PrimFloor _ t) = matchIntegralType s t+matchPrimFun (PrimCeiling _ s) (PrimCeiling _ t) = matchIntegralType s t+matchPrimFun (PrimIsNaN _) (PrimIsNaN _) = Just Refl+matchPrimFun (PrimIsInfinite _) (PrimIsInfinite _) = Just Refl+matchPrimFun (PrimLt _) (PrimLt _) = Just Refl+matchPrimFun (PrimGt _) (PrimGt _) = Just Refl+matchPrimFun (PrimLtEq _) (PrimLtEq _) = Just Refl+matchPrimFun (PrimGtEq _) (PrimGtEq _) = Just Refl+matchPrimFun (PrimEq _) (PrimEq _) = Just Refl+matchPrimFun (PrimNEq _) (PrimNEq _) = Just Refl+matchPrimFun (PrimMax _) (PrimMax _) = Just Refl+matchPrimFun (PrimMin _) (PrimMin _) = Just Refl+matchPrimFun (PrimFromIntegral _ s) (PrimFromIntegral _ t) = matchNumType s t+matchPrimFun (PrimToFloating _ s) (PrimToFloating _ t) = matchFloatingType s t+matchPrimFun PrimLAnd PrimLAnd = Just Refl+matchPrimFun PrimLOr PrimLOr = Just Refl+matchPrimFun PrimLNot PrimLNot = Just Refl++matchPrimFun _ _+ = Nothing+++-- Contravariant function matching+--+{-# INLINEABLE matchPrimFun' #-}+matchPrimFun' :: PrimFun (s -> a) -> PrimFun (t -> a) -> Maybe (s :~: t)+matchPrimFun' (PrimAdd _) (PrimAdd _) = Just Refl+matchPrimFun' (PrimSub _) (PrimSub _) = Just Refl+matchPrimFun' (PrimMul _) (PrimMul _) = Just Refl+matchPrimFun' (PrimNeg _) (PrimNeg _) = Just Refl+matchPrimFun' (PrimAbs _) (PrimAbs _) = Just Refl+matchPrimFun' (PrimSig _) (PrimSig _) = Just Refl+matchPrimFun' (PrimQuot _) (PrimQuot _) = Just Refl+matchPrimFun' (PrimRem _) (PrimRem _) = Just Refl+matchPrimFun' (PrimQuotRem _) (PrimQuotRem _) = Just Refl+matchPrimFun' (PrimIDiv _) (PrimIDiv _) = Just Refl+matchPrimFun' (PrimMod _) (PrimMod _) = Just Refl+matchPrimFun' (PrimDivMod _) (PrimDivMod _) = Just Refl+matchPrimFun' (PrimBAnd _) (PrimBAnd _) = Just Refl+matchPrimFun' (PrimBOr _) (PrimBOr _) = Just Refl+matchPrimFun' (PrimBXor _) (PrimBXor _) = Just Refl+matchPrimFun' (PrimBNot _) (PrimBNot _) = Just Refl+matchPrimFun' (PrimBShiftL _) (PrimBShiftL _) = Just Refl+matchPrimFun' (PrimBShiftR _) (PrimBShiftR _) = Just Refl+matchPrimFun' (PrimBRotateL _) (PrimBRotateL _) = Just Refl+matchPrimFun' (PrimBRotateR _) (PrimBRotateR _) = Just Refl+matchPrimFun' (PrimPopCount s) (PrimPopCount t) = matchIntegralType s t+matchPrimFun' (PrimCountLeadingZeros s) (PrimCountLeadingZeros t) = matchIntegralType s t+matchPrimFun' (PrimCountTrailingZeros s) (PrimCountTrailingZeros t) = matchIntegralType s t+matchPrimFun' (PrimFDiv _) (PrimFDiv _) = Just Refl+matchPrimFun' (PrimRecip _) (PrimRecip _) = Just Refl+matchPrimFun' (PrimSin _) (PrimSin _) = Just Refl+matchPrimFun' (PrimCos _) (PrimCos _) = Just Refl+matchPrimFun' (PrimTan _) (PrimTan _) = Just Refl+matchPrimFun' (PrimAsin _) (PrimAsin _) = Just Refl+matchPrimFun' (PrimAcos _) (PrimAcos _) = Just Refl+matchPrimFun' (PrimAtan _) (PrimAtan _) = Just Refl+matchPrimFun' (PrimSinh _) (PrimSinh _) = Just Refl+matchPrimFun' (PrimCosh _) (PrimCosh _) = Just Refl+matchPrimFun' (PrimTanh _) (PrimTanh _) = Just Refl+matchPrimFun' (PrimAsinh _) (PrimAsinh _) = Just Refl+matchPrimFun' (PrimAcosh _) (PrimAcosh _) = Just Refl+matchPrimFun' (PrimAtanh _) (PrimAtanh _) = Just Refl+matchPrimFun' (PrimExpFloating _) (PrimExpFloating _) = Just Refl+matchPrimFun' (PrimSqrt _) (PrimSqrt _) = Just Refl+matchPrimFun' (PrimLog _) (PrimLog _) = Just Refl+matchPrimFun' (PrimFPow _) (PrimFPow _) = Just Refl+matchPrimFun' (PrimLogBase _) (PrimLogBase _) = Just Refl+matchPrimFun' (PrimAtan2 _) (PrimAtan2 _) = Just Refl+matchPrimFun' (PrimTruncate s _) (PrimTruncate t _) = matchFloatingType s t+matchPrimFun' (PrimRound s _) (PrimRound t _) = matchFloatingType s t+matchPrimFun' (PrimFloor s _) (PrimFloor t _) = matchFloatingType s t+matchPrimFun' (PrimCeiling s _) (PrimCeiling t _) = matchFloatingType s t+matchPrimFun' (PrimIsNaN s) (PrimIsNaN t) = matchFloatingType s t+matchPrimFun' (PrimIsInfinite s) (PrimIsInfinite t) = matchFloatingType s t+matchPrimFun' (PrimMax _) (PrimMax _) = Just Refl+matchPrimFun' (PrimMin _) (PrimMin _) = Just Refl+matchPrimFun' (PrimFromIntegral s _) (PrimFromIntegral t _) = matchIntegralType s t+matchPrimFun' (PrimToFloating s _) (PrimToFloating t _) = matchNumType s t+matchPrimFun' PrimLAnd PrimLAnd = Just Refl+matchPrimFun' PrimLOr PrimLOr = Just Refl+matchPrimFun' PrimLNot PrimLNot = Just Refl++matchPrimFun' (PrimLt s) (PrimLt t)+ | Just Refl <- matchSingleType s t+ = Just Refl++matchPrimFun' (PrimGt s) (PrimGt t)+ | Just Refl <- matchSingleType s t+ = Just Refl++matchPrimFun' (PrimLtEq s) (PrimLtEq t)+ | Just Refl <- matchSingleType s t+ = Just Refl++matchPrimFun' (PrimGtEq s) (PrimGtEq t)+ | Just Refl <- matchSingleType s t+ = Just Refl++matchPrimFun' (PrimEq s) (PrimEq t)+ | Just Refl <- matchSingleType s t+ = Just Refl++matchPrimFun' (PrimNEq s) (PrimNEq t)+ | Just Refl <- matchSingleType s t+ = Just Refl++matchPrimFun' _ _+ = Nothing+++-- Match reified types+--+{-# INLINEABLE matchTypeR #-}+matchTypeR :: TypeR s -> TypeR t -> Maybe (s :~: t)+matchTypeR = matchTupR matchScalarType+++-- Match shapes (dimensionality)+--+-- XXX: Matching shapes is sort of a special case because the representation+-- types really are isomorphic to the surface type. However, 'gcast' does not+-- inline here, meaning that it will always do the fingerprint check, even if+-- the dimensions are known statically and thus the check could be elided as+-- a known branch.+--+{-# INLINEABLE matchShapeType #-}+matchShapeType :: forall s t. (Sugar.Shape s, Sugar.Shape t) => Maybe (s :~: t)+matchShapeType+ | Just Refl <- matchShapeR (Sugar.shapeR @s) (Sugar.shapeR @t)+#ifdef ACCELERATE_INTERNAL_CHECKS+ = gcast Refl+#else+ = Just (unsafeCoerce Refl)+#endif+ | otherwise+ = Nothing++{-# INLINEABLE matchShapeR #-}+matchShapeR :: forall s t. ShapeR s -> ShapeR t -> Maybe (s :~: t)+matchShapeR ShapeRz ShapeRz = Just Refl+matchShapeR (ShapeRsnoc shr1) (ShapeRsnoc shr2)+ | Just Refl <- matchShapeR shr1 shr2+ = Just Refl+matchShapeR _ _ = Nothing+++-- Match reified type dictionaries+--+{-# INLINEABLE matchScalarType #-}+matchScalarType :: ScalarType s -> ScalarType t -> Maybe (s :~: t)+matchScalarType (SingleScalarType s) (SingleScalarType t) = matchSingleType s t+matchScalarType (VectorScalarType s) (VectorScalarType t) = matchVectorType s t+matchScalarType _ _ = Nothing++{-# INLINEABLE matchSingleType #-}+matchSingleType :: SingleType s -> SingleType t -> Maybe (s :~: t)+matchSingleType (NumSingleType s) (NumSingleType t) = matchNumType s t++{-# INLINEABLE matchVectorType #-}+matchVectorType :: forall m n s t. VectorType (Vec n s) -> VectorType (Vec m t) -> Maybe (Vec n s :~: Vec m t)+matchVectorType (VectorType n s) (VectorType m t)+ | Just Refl <- if n == m+ then Just (unsafeCoerce Refl :: n :~: m) -- XXX: we don't have an embedded KnownNat constraint, but+ else Nothing -- this implementation is the same as 'GHC.TypeLits.sameNat'+ , Just Refl <- matchSingleType s t+ = Just Refl+matchVectorType _ _+ = Nothing++{-# INLINEABLE matchNumType #-}+matchNumType :: NumType s -> NumType t -> Maybe (s :~: t)+matchNumType (IntegralNumType s) (IntegralNumType t) = matchIntegralType s t+matchNumType (FloatingNumType s) (FloatingNumType t) = matchFloatingType s t+matchNumType _ _ = Nothing++{-# INLINEABLE matchBoundedType #-}+matchBoundedType :: BoundedType s -> BoundedType t -> Maybe (s :~: t)+matchBoundedType (IntegralBoundedType s) (IntegralBoundedType t) = matchIntegralType s t++{-# INLINEABLE matchIntegralType #-}+matchIntegralType :: IntegralType s -> IntegralType t -> Maybe (s :~: t)+matchIntegralType TypeInt TypeInt = Just Refl+matchIntegralType TypeInt8 TypeInt8 = Just Refl+matchIntegralType TypeInt16 TypeInt16 = Just Refl+matchIntegralType TypeInt32 TypeInt32 = Just Refl+matchIntegralType TypeInt64 TypeInt64 = Just Refl+matchIntegralType TypeWord TypeWord = Just Refl+matchIntegralType TypeWord8 TypeWord8 = Just Refl+matchIntegralType TypeWord16 TypeWord16 = Just Refl+matchIntegralType TypeWord32 TypeWord32 = Just Refl+matchIntegralType TypeWord64 TypeWord64 = Just Refl+matchIntegralType _ _ = Nothing++{-# INLINEABLE matchFloatingType #-}+matchFloatingType :: FloatingType s -> FloatingType t -> Maybe (s :~: t)+matchFloatingType TypeHalf TypeHalf = Just Refl+matchFloatingType TypeFloat TypeFloat = Just Refl+matchFloatingType TypeDouble TypeDouble = Just Refl+matchFloatingType _ _ = Nothing+++-- Auxiliary+-- ---------++-- Discriminate binary functions that commute, and if so return the operands in+-- a stable ordering such that matching recognises expressions modulo+-- commutativity.+--+commutes+ :: forall env aenv a r.+ PrimFun (a -> r)+ -> OpenExp env aenv a+ -> Maybe (OpenExp env aenv a)+commutes f x = case f of+ PrimAdd{} -> Just (swizzle x)+ PrimMul{} -> Just (swizzle x)+ PrimBAnd{} -> Just (swizzle x)+ PrimBOr{} -> Just (swizzle x)+ PrimBXor{} -> Just (swizzle x)+ PrimEq{} -> Just (swizzle x)+ PrimNEq{} -> Just (swizzle x)+ PrimMax{} -> Just (swizzle x)+ PrimMin{} -> Just (swizzle x)+ PrimLAnd -> Just (swizzle x)+ PrimLOr -> Just (swizzle x)+ _ -> Nothing+ where+ swizzle :: OpenExp env aenv (a',a') -> OpenExp env aenv (a',a')+ swizzle exp+ | (a `Pair` b) <- exp+ , hashOpenExp a > hashOpenExp b = b `Pair` a+ --+ | otherwise = exp+
+ src/Data/Array/Accelerate/Array/Data.hs view
@@ -0,0 +1,408 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE UndecidableInstances #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Array.Data+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- This module fixes the concrete representation of Accelerate arrays. We+-- allocate all arrays using pinned memory to enable safe direct-access by+-- non-Haskell code in multi-threaded code. In particular, we can safely pass+-- pointers to an array's payload to foreign code.+--++module Data.Array.Accelerate.Array.Data (++ -- * Array operations and representations+ ArrayData, MutableArrayData, ScalarArrayData, GArrayDataR, ScalarArrayDataR,+ runArrayData,+ newArrayData,+ indexArrayData, readArrayData, writeArrayData,+ unsafeArrayDataPtr,+ touchArrayData,+ rnfArrayData,++ -- * Type macros+ HTYPE_INT, HTYPE_WORD, HTYPE_CLONG, HTYPE_CULONG, HTYPE_CCHAR,++ -- * Allocator internals+ registerForeignPtrAllocator,++ -- * Utilities for type classes+ ScalarArrayDict(..), scalarArrayDict,+ SingleArrayDict(..), singleArrayDict,++ -- * TemplateHaskell+ liftArrayData,++) where++import Data.Array.Accelerate.Array.Unique+import Data.Array.Accelerate.Error+import Data.Array.Accelerate.Lifetime+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Type+import Data.Primitive.Vec++import Data.Array.Accelerate.Debug.Internal.Flags+import Data.Array.Accelerate.Debug.Internal.Profile+import Data.Array.Accelerate.Debug.Internal.Trace++import Control.Applicative+import Control.DeepSeq+import Control.Monad ( (<=<) )+import Data.Bits+import Data.IORef+import Data.Primitive ( sizeOf# )+import Foreign.ForeignPtr+import Foreign.Storable+import Formatting hiding ( bytes )+import Language.Haskell.TH.Extra hiding ( Type )+import System.IO.Unsafe+import Prelude hiding ( mapM )++import GHC.Exts hiding ( build )+import GHC.ForeignPtr+import GHC.Types+++-- | Immutable array representation+--+type ArrayData e = MutableArrayData e++-- | Mutable array representation+--+type MutableArrayData e = GArrayDataR UniqueArray e++-- | Underlying array representation.+--+-- NOTE: We use a standard (non-strict) pair to enable lazy device-host data transfers+--+type family GArrayDataR ba a where+ GArrayDataR ba () = ()+ GArrayDataR ba (a, b) = (GArrayDataR ba a, GArrayDataR ba b)+ GArrayDataR ba a = ba (ScalarArrayDataR a)++type ScalarArrayData a = UniqueArray (ScalarArrayDataR a)++-- | Mapping from scalar type to the type as represented in memory in an+-- array.+--+type family ScalarArrayDataR t where+ ScalarArrayDataR Int = Int+ ScalarArrayDataR Int8 = Int8+ ScalarArrayDataR Int16 = Int16+ ScalarArrayDataR Int32 = Int32+ ScalarArrayDataR Int64 = Int64+ ScalarArrayDataR Word = Word+ ScalarArrayDataR Word8 = Word8+ ScalarArrayDataR Word16 = Word16+ ScalarArrayDataR Word32 = Word32+ ScalarArrayDataR Word64 = Word64+ ScalarArrayDataR Half = Half+ ScalarArrayDataR Float = Float+ ScalarArrayDataR Double = Double+ ScalarArrayDataR (Vec n t) = ScalarArrayDataR t+++data ScalarArrayDict a where+ ScalarArrayDict :: ( ArrayData a ~ ScalarArrayData a, ScalarArrayDataR a ~ ScalarArrayDataR b )+ => {-# UNPACK #-} !Int -- vector width+ -> SingleType b -- base type+ -> ScalarArrayDict a++data SingleArrayDict a where+ SingleArrayDict :: ( ArrayData a ~ ScalarArrayData a, ScalarArrayDataR a ~ a )+ => SingleArrayDict a++scalarArrayDict :: ScalarType a -> ScalarArrayDict a+scalarArrayDict = scalar+ where+ scalar :: ScalarType a -> ScalarArrayDict a+ scalar (VectorScalarType t) = vector t+ scalar (SingleScalarType t)+ | SingleArrayDict <- singleArrayDict t+ = ScalarArrayDict 1 t++ vector :: VectorType a -> ScalarArrayDict a+ vector (VectorType w s)+ | SingleArrayDict <- singleArrayDict s+ = ScalarArrayDict w s++singleArrayDict :: SingleType a -> SingleArrayDict a+singleArrayDict = single+ where+ single :: SingleType a -> SingleArrayDict a+ single (NumSingleType t) = num t++ num :: NumType a -> SingleArrayDict a+ num (IntegralNumType t) = integral t+ num (FloatingNumType t) = floating t++ integral :: IntegralType a -> SingleArrayDict a+ integral TypeInt = SingleArrayDict+ integral TypeInt8 = SingleArrayDict+ integral TypeInt16 = SingleArrayDict+ integral TypeInt32 = SingleArrayDict+ integral TypeInt64 = SingleArrayDict+ integral TypeWord = SingleArrayDict+ integral TypeWord8 = SingleArrayDict+ integral TypeWord16 = SingleArrayDict+ integral TypeWord32 = SingleArrayDict+ integral TypeWord64 = SingleArrayDict++ floating :: FloatingType a -> SingleArrayDict a+ floating TypeHalf = SingleArrayDict+ floating TypeFloat = SingleArrayDict+ floating TypeDouble = SingleArrayDict+++-- Array operations+-- ----------------++newArrayData :: HasCallStack => TupR ScalarType e -> Int -> IO (MutableArrayData e)+newArrayData TupRunit !_ = return ()+newArrayData (TupRpair t1 t2) !size = (,) <$> newArrayData t1 size <*> newArrayData t2 size+newArrayData (TupRsingle t) !size+ | SingleScalarType s <- t+ , SingleDict <- singleDict s+ , SingleArrayDict <- singleArrayDict s+ = allocateArray size+ --+ | VectorScalarType v <- t+ , VectorType w s <- v+ , SingleDict <- singleDict s+ , SingleArrayDict <- singleArrayDict s+ = allocateArray (w * size)++indexArrayData :: TupR ScalarType e -> ArrayData e -> Int -> e+indexArrayData tR arr ix = unsafePerformIO $ readArrayData tR arr ix++readArrayData :: forall e. TupR ScalarType e -> MutableArrayData e -> Int -> IO e+readArrayData TupRunit () !_ = return ()+readArrayData (TupRpair t1 t2) (a1, a2) !ix = (,) <$> readArrayData t1 a1 ix <*> readArrayData t2 a2 ix+readArrayData (TupRsingle t) arr !ix+ | SingleScalarType s <- t+ , SingleDict <- singleDict s+ , SingleArrayDict <- singleArrayDict s+ = unsafeReadArray arr ix+ --+ | VectorScalarType v <- t+ , VectorType w s <- v+ , I# w# <- w+ , I# ix# <- ix+ , SingleDict <- singleDict s+ , SingleArrayDict <- singleArrayDict s+ = let+ !bytes# = w# *# sizeOf# (undefined :: ScalarArrayDataR e)+ !addr# = unPtr# (unsafeUniqueArrayPtr arr) `plusAddr#` (ix# *# bytes#)+ in+ IO $ \s0 ->+ case newAlignedPinnedByteArray# bytes# 16# s0 of { (# s1, mba# #) ->+ case copyAddrToByteArray# addr# mba# 0# bytes# s1 of { s2 ->+ case unsafeFreezeByteArray# mba# s2 of { (# s3, ba# #) ->+ (# s3, Vec ba# #)+ }}}++writeArrayData :: forall e. TupR ScalarType e -> MutableArrayData e -> Int -> e -> IO ()+writeArrayData TupRunit () !_ () = return ()+writeArrayData (TupRpair t1 t2) (a1, a2) !ix (v1, v2) = writeArrayData t1 a1 ix v1 >> writeArrayData t2 a2 ix v2+writeArrayData (TupRsingle t) arr !ix !val+ | SingleScalarType s <- t+ , SingleDict <- singleDict s+ , SingleArrayDict <- singleArrayDict s+ = unsafeWriteArray arr ix val+ --+ | VectorScalarType v <- t+ , VectorType w s <- v+ , Vec ba# <- val+ , I# w# <- w+ , I# ix# <- ix+ , SingleDict <- singleDict s+ , SingleArrayDict <- singleArrayDict s+ = let+ !bytes# = w# *# sizeOf# (undefined :: ScalarArrayDataR e)+ !addr# = unPtr# (unsafeUniqueArrayPtr arr) `plusAddr#` (ix# *# bytes#)+ in+ IO $ \s0 -> case copyByteArrayToAddr# ba# 0# addr# bytes# s0 of+ s1 -> (# s1, () #)+++unsafeArrayDataPtr :: ScalarType e -> ArrayData e -> Ptr (ScalarArrayDataR e)+unsafeArrayDataPtr t arr+ | ScalarArrayDict{} <- scalarArrayDict t+ = unsafeUniqueArrayPtr arr++touchArrayData :: TupR ScalarType e -> ArrayData e -> IO ()+touchArrayData TupRunit () = return ()+touchArrayData (TupRpair t1 t2) (a1, a2) = touchArrayData t1 a1 >> touchArrayData t2 a2+touchArrayData (TupRsingle t) arr+ | ScalarArrayDict{} <- scalarArrayDict t+ = touchUniqueArray arr++rnfArrayData :: TupR ScalarType e -> ArrayData e -> ()+rnfArrayData TupRunit () = ()+rnfArrayData (TupRpair t1 t2) (a1, a2) = rnfArrayData t1 a1 `seq` rnfArrayData t2 a2 `seq` ()+rnfArrayData (TupRsingle t) arr = rnf (unsafeArrayDataPtr t arr)++unPtr# :: Ptr a -> Addr#+unPtr# (Ptr addr#) = addr#++-- | Safe combination of creating and fast freezing of array data.+--+runArrayData+ :: IO (MutableArrayData e, e)+ -> (ArrayData e, e)+runArrayData st = unsafePerformIO $ do+ (mad, r) <- st+ return (mad, r)++-- Allocate a new array with enough storage to hold the given number of+-- elements.+--+-- The array is uninitialised and, in particular, allocated lazily. The latter+-- is important because it means that for backends that have discrete memory+-- spaces (e.g. GPUs), we will not increase host memory pressure simply to track+-- intermediate arrays that contain meaningful data only on the device.+--+allocateArray :: forall e. (HasCallStack, Storable e) => Int -> IO (UniqueArray e)+allocateArray !size = internalCheck "size must be >= 0" (size >= 0) $ do+ arr <- newUniqueArray <=< unsafeInterleaveIO $ do+ let bytes = size * sizeOf (undefined :: e)+ new <- readIORef __mallocForeignPtrBytes+ ptr <- new bytes+ traceM dump_gc ("gc: allocated new host array (size=" % int % ", ptr=" % build % ")") bytes (unsafeForeignPtrToPtr ptr)+ local_memory_alloc (unsafeForeignPtrToPtr ptr) bytes+ return (castForeignPtr ptr)++ -- If we can, avoid attaching a finalizer at all for performance+#ifdef ACCELERATE_TRACY+ let doTracy = True+#else+ let doTracy = False+#endif+ haveDumpGc <- getFlag dump_gc+ if doTracy || haveDumpGc+ then addFinalizer (uniqueArrayData arr) $ do+ traceM dump_gc ("gc: finalizer for host array " % build % ")") (unsafeUniqueArrayPtr arr)+ if doTracy then local_memory_free (unsafeUniqueArrayPtr arr) else return ()+ else return ()++ return arr++-- | Register the given function as the callback to use to allocate new array+-- data on the host containing the specified number of bytes. The returned array+-- must be pinned (with respect to Haskell's GC), so that it can be passed to+-- foreign code.+--+registerForeignPtrAllocator+ :: (Int -> IO (ForeignPtr Word8))+ -> IO ()+registerForeignPtrAllocator new = do+ traceM dump_gc "registering new array allocator"+ atomicWriteIORef __mallocForeignPtrBytes new++{-# NOINLINE __mallocForeignPtrBytes #-}+__mallocForeignPtrBytes :: IORef (Int -> IO (ForeignPtr Word8))+__mallocForeignPtrBytes = unsafePerformIO $! newIORef mallocPlainForeignPtrBytesAligned++-- | Allocate the given number of bytes with 64-byte (cache line)+-- alignment. This is essential for SIMD instructions.+--+-- Additionally, we return a plain ForeignPtr, which unlike a regular ForeignPtr+-- created with 'mallocForeignPtr' carries no finalisers. It is an error to try+-- to add a finaliser to the plain ForeignPtr. For our purposes this is fine,+-- since in Accelerate finalisers are handled using Lifetime+--+mallocPlainForeignPtrBytesAligned :: Int -> IO (ForeignPtr a)+mallocPlainForeignPtrBytesAligned (I# size#) = IO $ \s0 ->+ case newAlignedPinnedByteArray# size# 64# s0 of+ (# s1, mbarr# #) -> (# s1, ForeignPtr (byteArrayContents# (unsafeCoerce# mbarr#)) (PlainPtr mbarr#) #)+++liftArrayData :: Int -> TypeR e -> ArrayData e -> CodeQ (ArrayData e)+liftArrayData n = tuple+ where+ tuple :: TypeR e -> ArrayData e -> CodeQ (ArrayData e)+ tuple TupRunit () = [|| () ||]+ tuple (TupRpair t1 t2) (a1, a2) = [|| ($$(tuple t1 a1), $$(tuple t2 a2)) ||]+ tuple (TupRsingle s) adata = scalar s adata++ scalar :: ScalarType e -> ArrayData e -> CodeQ (ArrayData e)+ scalar (SingleScalarType t) = single t+ scalar (VectorScalarType t) = vector t++ vector :: forall n e. VectorType (Vec n e) -> ArrayData (Vec n e) -> CodeQ (ArrayData (Vec n e))+ vector (VectorType w t)+ | SingleArrayDict <- singleArrayDict t+ = liftArrayData (w * n) (TupRsingle (SingleScalarType t))++ single :: SingleType e -> ArrayData e -> CodeQ (ArrayData e)+ single (NumSingleType t) = num t++ num :: NumType e -> ArrayData e -> CodeQ (ArrayData e)+ num (IntegralNumType t) = integral t+ num (FloatingNumType t) = floating t++ integral :: IntegralType e -> ArrayData e -> CodeQ (ArrayData e)+ integral TypeInt = liftUniqueArray n+ integral TypeInt8 = liftUniqueArray n+ integral TypeInt16 = liftUniqueArray n+ integral TypeInt32 = liftUniqueArray n+ integral TypeInt64 = liftUniqueArray n+ integral TypeWord = liftUniqueArray n+ integral TypeWord8 = liftUniqueArray n+ integral TypeWord16 = liftUniqueArray n+ integral TypeWord32 = liftUniqueArray n+ integral TypeWord64 = liftUniqueArray n++ floating :: FloatingType e -> ArrayData e -> CodeQ (ArrayData e)+ floating TypeHalf = liftUniqueArray n+ floating TypeFloat = liftUniqueArray n+ floating TypeDouble = liftUniqueArray n++-- Determine the underlying type of a Haskell CLong or CULong.+--+runQ [d| type HTYPE_INT = $(+ case finiteBitSize (undefined::Int) of+ 32 -> [t| Int32 |]+ 64 -> [t| Int64 |]+ _ -> error "I don't know what architecture I am" ) |]++runQ [d| type HTYPE_WORD = $(+ case finiteBitSize (undefined::Word) of+ 32 -> [t| Word32 |]+ 64 -> [t| Word64 |]+ _ -> error "I don't know what architecture I am" ) |]++runQ [d| type HTYPE_CLONG = $(+ case finiteBitSize (undefined::CLong) of+ 32 -> [t| Int32 |]+ 64 -> [t| Int64 |]+ _ -> error "I don't know what architecture I am" ) |]++runQ [d| type HTYPE_CULONG = $(+ case finiteBitSize (undefined::CULong) of+ 32 -> [t| Word32 |]+ 64 -> [t| Word64 |]+ _ -> error "I don't know what architecture I am" ) |]++runQ [d| type HTYPE_CCHAR = $(+ if isSigned (undefined::CChar)+ then [t| Int8 |]+ else [t| Word8 |] ) |]+
+ src/Data/Array/Accelerate/Array/Remote.hs view
@@ -0,0 +1,25 @@+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Array.Remote+-- Copyright : [2015..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- Umbrella module for the remote memory management facilities. To+-- implement an LRU cache for your backend, provide an instance of the+-- 'RemoteMemory' class, and, if required, specialise or overload the LRU+-- functions to your particular memory table types.+--++module Data.Array.Accelerate.Array.Remote (++ module Remote++) where++import Data.Array.Accelerate.Array.Remote.Class as Remote+import Data.Array.Accelerate.Array.Remote.LRU as Remote+
+ src/Data/Array/Accelerate/Array/Remote/Class.hs view
@@ -0,0 +1,74 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Array.Remote.Class+-- Copyright : [2015..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- This module define a class of operations over pointers in a remote memory+-- space. Backends provide an instance of this class, and then can use (or+-- extend upon) one of the following modules in order to manage the remote+-- memory:+--+-- * 'Data.Array.Accelerate.Array.Remote.Table': basic, unmanaged memory tables,+-- mapping accelerate arrays on the host to the corresponding array in the+-- remote memory space.+--+-- * 'Data.Array.Accelerate.Array.Remote.LRU': managed memory tables which+-- additionally evict old entries from the device if the remote memory is+-- exhausted.+--++module Data.Array.Accelerate.Array.Remote.Class (++ RemoteMemory(..)++) where++import Data.Array.Accelerate.Array.Data+import Data.Array.Accelerate.Type++import Control.Applicative+import Control.Monad.Catch+import Data.Kind+import Prelude+++-- | Accelerate backends can provide an instance of this class in order to take+-- advantage of the automated memory managers we provide as part of the base+-- package.+--+class (Applicative m, Monad m, MonadCatch m, MonadMask m) => RemoteMemory m where++ -- | Pointers into this particular remote memory.+ type RemotePtr m :: Type -> Type++ -- | Attempt to allocate the given number of bytes in the remote memory space.+ -- Returns Nothing on failure.+ mallocRemote :: Int -> m (Maybe (RemotePtr m Word8))++ -- | Copy the given number of elements from the host array into remote memory.+ pokeRemote :: SingleType e -> Int -> RemotePtr m (ScalarArrayDataR e) -> ArrayData e -> m ()++ -- | Copy the given number of elements from remote memory to the host array.+ peekRemote :: SingleType e -> Int -> RemotePtr m (ScalarArrayDataR e) -> MutableArrayData e -> m ()++ -- | Cast a remote pointer.+ castRemotePtr :: RemotePtr m a -> RemotePtr m b++ -- | Returns the total remote memory available in bytes.+ totalRemoteMem :: m Int64++ -- | Returns, in bytes, the available remote memory.+ availableRemoteMem :: m Int64++ -- | The chunk allocation size (bytes).+ remoteAllocationSize :: m Int+ remoteAllocationSize = return 1024+
+ src/Data/Array/Accelerate/Array/Remote/LRU.hs view
@@ -0,0 +1,450 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DoAndIfThenElse #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeOperators #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Array.Remote.LRU+-- Copyright : [2015..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- This module extends the memory tables provided by+-- 'Data.Array.Accelerate.Array.Remote.Table' with an LRU caching policy that+-- evicts old arrays from the remote memory space once it runs out of memory.+-- Consequently, use of this module requires the backend client to keep track of+-- which remote arrays are currently being used, so that they will not be+-- evicted. See: 'withRemote' for more details on this requirement.+--+module Data.Array.Accelerate.Array.Remote.LRU (++ -- Tables for host/device memory associations+ MemoryTable, new, withRemote, malloc, free, insertUnmanaged, reclaim,++ -- Asynchronous tasks+ Task(..)++) where++import Data.Array.Accelerate.Analysis.Match ( matchSingleType, (:~:)(..) )+import Data.Array.Accelerate.Array.Data+import Data.Array.Accelerate.Array.Remote.Class+import Data.Array.Accelerate.Array.Remote.Table ( StableArray, makeWeakArrayData, formatStableArray )+import Data.Array.Accelerate.Array.Unique ( touchUniqueArray )+import Data.Array.Accelerate.Error ( internalError )+import Data.Array.Accelerate.Type+import qualified Data.Array.Accelerate.Array.Remote.Table as Basic+import qualified Data.Array.Accelerate.Debug.Internal.Flags as Debug+import qualified Data.Array.Accelerate.Debug.Internal.Trace as Debug++import Control.Concurrent.MVar ( MVar, newMVar, withMVar, takeMVar, putMVar, mkWeakMVar )+import Control.Monad ( filterM )+import Control.Monad.Catch+import Control.Monad.IO.Class ( MonadIO, liftIO )+import Data.Functor+import Data.Maybe ( isNothing )+import Data.Text.Lazy.Builder ( Builder )+import Formatting+import System.CPUTime+import System.Mem.Weak ( Weak, deRefWeak, finalize )+import qualified Data.HashTable.IO as HT+import Prelude hiding ( lookup )++import GHC.Stack+++-- We build cached memory tables on top of a basic memory table.+--+-- A key invariant is that the arrays in the MemoryTable are a subset of the+-- arrays in the UseTable. The UseTable reflects all arrays that have ever been+-- in the cache.+--+data MemoryTable p task = MemoryTable {-# UNPACK #-} !(Basic.MemoryTable p)+ {-# UNPACK #-} !(UseTable task)+ {-# UNPACK #-} !(Weak (UseTable task))++type UT task = HT.CuckooHashTable StableArray (Used task)+type UseTable task = MVar (UT task)++data Status = Clean -- Array in remote memory matches array in host memory.+ | Dirty -- Array in remote memory has been modified.+ | Unmanaged -- Array in remote memory was injected by FFI, so we+ -- cannot remove it under any circumstance.+ | Evicted -- Array has been evicted from remote memory+ deriving Eq++type Timestamp = Integer++data Used task where+ Used :: ArrayData e ~ ScalarArrayData e+ => !Timestamp+ -> !Status+ -> {-# UNPACK #-} !Int -- Use count+ -> ![task] -- Asynchronous tasks using the array+ -> {-# UNPACK #-} !Int -- Number of elements+ -> !(SingleType e)+ -> {-# UNPACK #-} !(Weak (ScalarArrayData e))+ -> Used task++-- | A Task represents a process executing asynchronously that can be polled for+-- its status. This is necessary for backends that work asynchronously (i.e.+-- the CUDA backend). If a backend is synchronous, the () instance can be used.+--+class Task task where+ -- |Returns true when the task has finished.+ completed :: task -> IO Bool++instance Task () where+ completed () = return True++-- | Create a new memory cache from host to remote arrays.+--+-- The function supplied should be the `free` for the remote pointers being+-- stored. This function will be called by the GC, which typically runs on a+-- different thread. Consequently, unlike the functions in 'RemoteMemory', this+-- function cannot depend on any state.+--+new :: (forall a. ptr a -> IO ()) -> IO (MemoryTable ptr task)+new release = do+ mt <- Basic.new release+ utbl <- HT.new+ ref <- newMVar utbl+ weak_utbl <- mkWeakMVar ref (cache_finalizer utbl)+ return $! MemoryTable mt ref weak_utbl++-- | Perform some action that requires the remote pointer corresponding to+-- the given array. Returns `Nothing` if the array have NEVER been in the+-- cache. If the array was previously in the cache, but was evicted due to its+-- age, then the array will be copied back from host memory.+--+-- The continuation passed as the third argument needs to obey some precise+-- properties. As with all bracketed functions, the supplied remote pointer must+-- not leak out of the function, as it is only guaranteed to be valid within it.+-- If it is required that it does leak (e.g. the backend uses concurrency to+-- interleave execution of different parts of the program), then `completed` on+-- the returned task should not return true until it is guaranteed there are no+-- more accesses of the remote pointer.+--+withRemote+ :: forall task m a c. (HasCallStack, Task task, RemoteMemory m, MonadIO m, Functor m)+ => MemoryTable (RemotePtr m) task+ -> SingleType a+ -> ArrayData a+ -> (RemotePtr m (ScalarArrayDataR a) -> m (task, c))+ -> m (Maybe c)+withRemote (MemoryTable !mt !ref _) !tp !arr run | SingleArrayDict <- singleArrayDict tp = do+ key <- Basic.makeStableArray tp arr+ mp <- withMVar' ref $ \utbl -> do+ mu <- liftIO . HT.mutate utbl key $ \case+ Nothing -> (Nothing, Nothing)+ Just u -> (Just (incCount u), Just u)+ --+ case mu of+ Nothing -> do+ message ("withRemote/array has never been malloc'd: " % formatStableArray) key+ return Nothing -- The array was never in the table++ Just u -> do+ mp <- liftIO $ Basic.lookup @m mt tp arr+ ptr <- case mp of+ Just p -> return p+ Nothing+ | isEvicted u -> copyBack utbl (incCount u)+ | otherwise -> do message ("lost array " % formatStableArray) key+ internalError "non-evicted array has been lost"+ return (Just ptr)+ --+ case mp of+ Nothing -> return Nothing+ Just ptr -> Just <$> go key ptr+ where+ updateTask :: Used task -> task -> IO (Used task)+ updateTask (Used _ status count tasks n tp' weak_arr) task = do+ ts <- getCPUTime+ tasks' <- cleanUses tasks+ return (Used ts status (count - 1) (task : tasks') n tp' weak_arr)++ copyBack :: HasCallStack => UT task -> Used task -> m (RemotePtr m (ScalarArrayDataR a))+ copyBack utbl (Used ts _ count tasks n tp' weak_arr)+ | Just Refl <- matchSingleType tp tp' = do+ message "withRemote/reuploading-evicted-array"+ p <- mallocWithUsage mt utbl tp arr (Used ts Clean count tasks n tp weak_arr)+ pokeRemote tp n p arr+ return p+ | otherwise = internalError "Type mismatch"++ -- We can't combine the use of `withMVar ref` above with the one here+ -- because the `permute` operation from the PTX backend requires nested+ -- calls to `withRemote` in order to copy the defaults array.+ --+ go :: (HasCallStack, ArrayData a ~ ScalarArrayData a)+ => StableArray+ -> RemotePtr m (ScalarArrayDataR a)+ -> m c+ go key ptr = do+ message ("withRemote/using: " % formatStableArray) key+ (task, c) <- run ptr+ liftIO . withMVar ref $ \utbl -> do+ HT.mutateIO utbl key $ \case+ Nothing -> internalError "invariant violated"+ Just u -> do+ u' <- updateTask u task+ return (Just u', ())+ --+ touchUniqueArray arr+ return c+++-- | Allocate a new device array to be associated with the given host-side array.+-- This has similar behaviour to malloc in Data.Array.Accelerate.Array.Memory.Table+-- but also will copy remote arrays back to main memory in order to make space.+--+-- The third argument indicates that the array should be considered frozen. That+-- is to say that the array contents will never change. In the event that the+-- array has to be evicted from the remote memory, the copy already residing in+-- host memory should be considered valid.+--+-- If this function is called on an array that is already contained within the+-- cache, this is a no-op.+--+-- On return, 'True' indicates that we allocated some remote memory, and 'False'+-- indicates that we did not need to.+--+malloc :: forall e m task. (HasCallStack, RemoteMemory m, MonadIO m, Task task)+ => MemoryTable (RemotePtr m) task+ -> SingleType e+ -> ArrayData e+ -> Bool -- ^ True if host array is frozen.+ -> Int -- ^ Number of elements+ -> m Bool -- ^ Was the array allocated successfully?+malloc (MemoryTable mt ref weak_utbl) !tp !ad !frozen !n | SingleArrayDict <- singleArrayDict tp = do -- Required for ArrayData e ~ ScalarArrayData e+ ts <- liftIO $ getCPUTime+ key <- Basic.makeStableArray tp ad+ --+ let status = if frozen+ then Clean+ else Dirty+ --+ withMVar' ref $ \utbl -> do+ mu <- liftIO $ HT.lookup utbl key+ if isNothing mu+ then do+ weak_arr <- liftIO $ makeWeakArrayData tp ad ad (Just $ finalizer key weak_utbl)+ _ <- mallocWithUsage mt utbl tp ad (Used ts status 0 [] n tp weak_arr)+ return True+ else+ return False++mallocWithUsage+ :: forall e m task. (HasCallStack, RemoteMemory m, MonadIO m, Task task, ArrayData e ~ ScalarArrayData e)+ => Basic.MemoryTable (RemotePtr m)+ -> UT task+ -> SingleType e+ -> ArrayData e+ -> Used task+ -> m (RemotePtr m (ScalarArrayDataR e))+mallocWithUsage !mt !utbl !tp !ad !usage@(Used _ _ _ _ n _ _) = malloc'+ where+ malloc' :: HasCallStack => m (RemotePtr m (ScalarArrayDataR e))+ malloc' = do+ mp <- Basic.malloc @e @m mt tp ad n :: m (Maybe (RemotePtr m (ScalarArrayDataR e)))+ case mp of+ Nothing -> do+ success <- evictLRU utbl mt+ if success then malloc'+ else internalError "Remote memory exhausted"+ Just p -> liftIO $ do+ key <- Basic.makeStableArray tp ad+ HT.insert utbl key usage+ return p++evictLRU+ :: forall m task. (HasCallStack, RemoteMemory m, MonadIO m, Task task)+ => UT task+ -> Basic.MemoryTable (RemotePtr m)+ -> m Bool+evictLRU !utbl !mt = trace "evictLRU/evicting-eldest-array" $ do+ mused <- liftIO $ HT.foldM eldest Nothing utbl+ case mused of+ Just (sa, Used ts status count tasks n tp weak_arr) -> do+ mad <- liftIO $ deRefWeak weak_arr+ case mad of+ Nothing -> liftIO $ do+ -- This can only happen if our eviction process was interrupted by+ -- garbage collection. In which case, even though we didn't actually+ -- evict anything, we should return true, as we know some remote+ -- memory is now free.+ --+ -- Small caveat: Due to finalisers being delayed, it's a good idea+ -- to free the array here.+ Basic.freeStable @m mt sa+ delete utbl sa+ message "evictLRU/Accelerate GC interrupted by GHC GC"++ Just arr -> do+ message ("evictLRU/evicting " % formatStableArray) sa+ copyIfNecessary status n tp arr+ -- liftIO $ Debug.remote_memory_evict sa (remoteBytes tp n)+ liftIO $ Basic.freeStable @m mt sa+ liftIO $ HT.insert utbl sa (Used ts Evicted count tasks n tp weak_arr)+ return True+ _ -> trace "evictLRU/All arrays in use, unable to evict" $ return False+ where+ -- Find the eldest, not currently in use, array.+ eldest :: (Maybe (StableArray, Used task)) -> (StableArray, Used task) -> IO (Maybe (StableArray, Used task))+ eldest prev (sa, used@(Used ts status count tasks n tp weak_arr))+ | count == 0+ , evictable status+ = do+ tasks' <- cleanUses tasks+ HT.insert utbl sa (Used ts status count tasks' n tp weak_arr)+ case tasks' of+ [] | Just (_, Used ts' _ _ _ _ _ _) <- prev+ , ts < ts' -> return (Just (sa, used))+ | Nothing <- prev -> return (Just (sa, used))+ _ -> return prev+ eldest prev _ = return prev++ -- remoteBytes :: SingleType e -> Int -> Int+ -- remoteBytes tp n = bytesElt (TupRsingle (SingleScalarType tp)) * n++ evictable :: Status -> Bool+ evictable Clean = True+ evictable Dirty = True+ evictable Unmanaged = False+ evictable Evicted = False++ copyIfNecessary :: Status -> Int -> SingleType e -> ArrayData e -> m ()+ copyIfNecessary Clean _ _ _ = return ()+ copyIfNecessary Unmanaged _ _ _ = return ()+ copyIfNecessary Evicted _ _ _ = internalError "Attempting to evict already evicted array"+ copyIfNecessary Dirty n tp ad = do+ mp <- liftIO $ Basic.lookup @m mt tp ad+ case mp of+ Nothing -> return () -- RCE: I think this branch is actually impossible.+ Just p -> peekRemote tp n p ad++-- | Deallocate the device array associated with the given host-side array.+-- Typically this should only be called in very specific circumstances. This+-- operation is not thread-safe.+--+free :: forall m a task. (HasCallStack, RemoteMemory m)+ => MemoryTable (RemotePtr m) task+ -> SingleType a+ -> ArrayData a+ -> IO ()+free (MemoryTable !mt !ref _) !tp !arr+ = withMVar' ref+ $ \utbl -> do+ key <- Basic.makeStableArray tp arr+ delete utbl key+ Basic.freeStable @m mt key++-- | Record an association between a host-side array and a remote memory area+-- that was not allocated by accelerate. The remote memory will NOT be re-used+-- once the host-side array is garbage collected.+--+-- This typically only has use for backends that provide an FFI.+--+insertUnmanaged+ :: (HasCallStack, MonadIO m, RemoteMemory m)+ => MemoryTable (RemotePtr m) task+ -> SingleType e+ -> ArrayData e+ -> RemotePtr m (ScalarArrayDataR e)+ -> m ()+insertUnmanaged (MemoryTable mt ref weak_utbl) !tp !arr !ptr | SingleArrayDict <- singleArrayDict tp = do -- Gives evidence that ArrayData e ~ ScalarArrayData e+ key <- Basic.makeStableArray tp arr+ () <- Basic.insertUnmanaged mt tp arr ptr+ liftIO+ $ withMVar ref+ $ \utbl -> do+ ts <- getCPUTime+ weak_arr <- makeWeakArrayData tp arr arr (Just $ finalizer key weak_utbl)+ HT.insert utbl key (Used ts Unmanaged 0 [] 0 tp weak_arr)+++-- Removing entries+-- ----------------++finalizer :: StableArray -> Weak (UseTable task) -> IO ()+finalizer !key !weak_utbl = do+ mref <- deRefWeak weak_utbl+ case mref of+ Nothing -> message "finalize cache/dead table"+ Just ref -> trace (bformat ("finalize cache: " % formatStableArray) key) $ withMVar' ref (`delete` key)++delete :: UT task -> StableArray -> IO ()+delete = HT.delete+++-- | Initiate garbage collection and `free` any remote arrays that no longer+-- have matching host-side equivalents.+--+reclaim+ :: forall m task. (HasCallStack, RemoteMemory m, MonadIO m)+ => MemoryTable (RemotePtr m) task+ -> m ()+reclaim (MemoryTable !mt _ _) = Basic.reclaim mt++cache_finalizer :: UT task -> IO ()+cache_finalizer !tbl+ = trace "cache finaliser"+ $ HT.mapM_ (\(_,u) -> f u) tbl+ where+ f :: Used task -> IO ()+ f (Used _ _ _ _ _ _ w) = finalize w++-- Miscellaneous+-- -------------++cleanUses :: Task task => [task] -> IO [task]+cleanUses = filterM (fmap not . completed)++incCount :: Used task -> Used task+incCount (Used ts status count uses n tp weak_arr) = Used ts status (count + 1) uses n tp weak_arr++isEvicted :: Used task -> Bool+isEvicted (Used _ status _ _ _ _ _) = status == Evicted++{-# INLINE withMVar' #-}+withMVar' :: (MonadIO m, MonadMask m) => MVar a -> (a -> m b) -> m b+withMVar' m f =+ mask $ \restore -> do+ a <- takeMVar' m+ b <- restore (f a) `onException` putMVar' m a+ putMVar' m a+ return b++{-# INLINE putMVar' #-}+putMVar' :: (MonadIO m, MonadMask m) => MVar a -> a -> m ()+putMVar' m a = liftIO (putMVar m a)++{-# INLINE takeMVar' #-}+takeMVar' :: (MonadIO m, MonadMask m) => MVar a -> m a+takeMVar' m = liftIO (takeMVar m)+++-- Debug+-- -----++{-# INLINE trace #-}+trace :: MonadIO m => Builder -> m a -> m a+trace msg next = message builder msg >> next++{-# INLINE message #-}+message :: MonadIO m => Format (m ()) a -> a+message fmt = Debug.traceM Debug.dump_gc ("gc: " % fmt)+
+ src/Data/Array/Accelerate/Array/Remote/Nursery.hs view
@@ -0,0 +1,122 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+-- |+-- Module : Data.Array.Accelerate.Array.Remote.Nursery+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Array.Remote.Nursery (++ Nursery(..), NRS, new, lookup, insert, cleanup, size++) where++import Data.Array.Accelerate.Error+import Data.Array.Accelerate.Debug.Internal.Flags as Debug+import Data.Array.Accelerate.Debug.Internal.Trace as Debug++import Control.Concurrent.MVar+import Data.Int+import Data.Sequence ( Seq )+import Data.Word+import Formatting+import System.Mem.Weak ( Weak )+import Prelude hiding ( lookup )+import qualified Data.HashTable.IO as HT+import qualified Data.Sequence as Seq+import qualified Data.Traversable as Seq+++-- The nursery is a place to store remote memory arrays that are no longer+-- needed. Often it is quicker to reuse an existing array, rather than call out+-- to the external API to allocate fresh memory.+--+-- The nursery is wrapped in an MVar so that several threads may safely access+-- it concurrently.+--+type HashTable key val = HT.CuckooHashTable key val+type NRS ptr = MVar ( HashTable Int (Seq (ptr Word8)) ) -- #bytes -> available memory+data Nursery ptr = Nursery {-# UNPACK #-} !(NRS ptr)+ {-# UNPACK #-} !(Weak (NRS ptr))+++-- | Create a fresh nursery.+--+-- When the nursery is garbage collected, the provided function will be run on+-- each value to free the retained memory.+--+{-# INLINEABLE new #-}+new :: (ptr Word8 -> IO ()) -> IO (Nursery ptr)+new delete = do+ message "initialise nursery"+ nrs <- HT.new+ ref <- newMVar nrs+ weak <- mkWeakMVar ref (cleanup delete ref)+ return $! Nursery ref weak+++-- | Look for an entry with the requested size.+--+{-# INLINEABLE lookup #-}+lookup :: HasCallStack => Int -> Nursery ptr -> IO (Maybe (ptr Word8))+lookup !key (Nursery !ref !_) =+ withMVar ref $ \nrs ->+ HT.mutateIO nrs key $ \case+ Nothing -> return (Nothing, Nothing)+ Just r ->+ case Seq.viewl r of+ v Seq.:< vs -> do+ -- Debug.remote_memory_free_nursery v+ if Seq.null vs+ then return (Nothing, Just v) -- delete this entry from the map+ else return (Just vs, Just v) -- re-insert the tail+ --+ Seq.EmptyL -> internalError "expected non-empty sequence"+++-- | Add an entry to the nursery+--+{-# INLINEABLE insert #-}+insert :: Int -> ptr Word8 -> Nursery ptr -> IO ()+insert !key !val (Nursery !ref _) =+ withMVar ref $ \nrs -> do+ -- Debug.remote_memory_alloc_nursery val key+ HT.mutate nrs key $ \case+ Nothing -> (Just (Seq.singleton val), ())+ Just vs -> (Just (vs Seq.|> val), ())+++-- | Delete all entries from the nursery+--+{-# INLINEABLE cleanup #-}+cleanup :: (ptr Word8 -> IO ()) -> NRS ptr -> IO ()+cleanup delete !ref = do+ message "nursery cleanup"+ modifyMVar_ ref $ \nrs -> do+ HT.mapM_ (Seq.mapM delete . snd) nrs+ nrs' <- HT.new+ return nrs'+++-- | The total number of bytes retained by the nursery+--+{-# INLINEABLE size #-}+size :: Nursery ptr -> IO Int64+size (Nursery ref _)+ = withMVar ref+ $ HT.foldM (\s (k,v) -> return $ s + fromIntegral (k * (Seq.length v))) 0+++-- Debug+-- -----++{-# INLINE message #-}+message :: Format (IO ()) a -> a+message fmt = Debug.traceM Debug.dump_gc ("gc: " % fmt)+
+ src/Data/Array/Accelerate/Array/Remote/Table.hs view
@@ -0,0 +1,430 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE ViewPatterns #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Array.Remote.Table+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- Accelerate backends often need to copy arrays to a remote memory before they+-- can be used in computation. This module provides an automated method for+-- doing so. Keeping track of arrays in a `MemoryTable` ensures that any memory+-- allocated for them will be freed when GHC's garbage collector collects the+-- host array.+--+module Data.Array.Accelerate.Array.Remote.Table (++ -- Tables for host/device memory associations+ MemoryTable, new, lookup, malloc, free, freeStable, insertUnmanaged, reclaim,++ -- Internals+ StableArray, makeStableArray,+ makeWeakArrayData,+ formatStableArray,++) where++import Control.Concurrent ( yield )+import Control.Concurrent.MVar ( MVar, newMVar, withMVar, mkWeakMVar )+import Control.Concurrent.Unique ( Unique )+import Control.Monad.IO.Class ( MonadIO, liftIO )+import Data.Functor+import Data.Hashable ( hash, Hashable )+import Data.Maybe ( isJust )+import Data.Text.Lazy.Builder ( Builder )+import Data.Word+import Foreign.Storable ( sizeOf )+import Formatting+import Prelude hiding ( lookup, id )+import System.Mem ( performGC )+import System.Mem.Weak ( Weak, deRefWeak )+import qualified Data.HashTable.IO as HT++import Data.Array.Accelerate.Array.Data+import Data.Array.Accelerate.Array.Remote.Class+import Data.Array.Accelerate.Array.Remote.Nursery ( Nursery(..) )+import Data.Array.Accelerate.Array.Unique ( UniqueArray(..) )+import Data.Array.Accelerate.Error ( internalError )+import Data.Array.Accelerate.Lifetime+import Data.Array.Accelerate.Type+import qualified Data.Array.Accelerate.Array.Remote.Nursery as N+import qualified Data.Array.Accelerate.Debug.Internal.Flags as Debug+import qualified Data.Array.Accelerate.Debug.Internal.Profile as Debug+import qualified Data.Array.Accelerate.Debug.Internal.Trace as Debug++import GHC.Stack+++-- We use an MVar to the hash table, so that several threads may safely access+-- it concurrently. This includes the finalisation threads that remove entries+-- from the table.+--+-- It is important that we can garbage collect old entries from the table when+-- the key is no longer reachable in the heap. Hence the value part of each+-- table entry is a (Weak val), where the stable name 'key' is the key for the+-- memo table, and the 'val' is the value of this table entry. When the key+-- becomes unreachable, a finaliser will fire and remove this entry from the+-- hash buckets, and further attempts to dereference the weak pointer will+-- return Nothing. References from 'val' to the key are ignored (see the+-- semantics of weak pointers in the documentation).+--+type HashTable key val = HT.CuckooHashTable key val+type MT p = MVar ( HashTable StableArray (RemoteArray p) )+data MemoryTable p = MemoryTable {-# UNPACK #-} !(MT p)+ {-# UNPACK #-} !(Weak (MT p))+ {-# UNPACK #-} !(Nursery p)+ (p Word8 -> IO ())++data RemoteArray p where+ RemoteArray :: !(p Word8) -- The actual remote pointer+ -> {-# UNPACK #-} !Int -- The array size in bytes+ -> {-# UNPACK #-} !(Weak ()) -- Keep track of host array liveness+ -> RemoteArray p++-- | An untyped reference to an array, similar to a StableName.+--+newtype StableArray = StableArray Unique+ deriving (Eq, Hashable)++instance Show StableArray where+ show (StableArray u) = show (hash u)++formatStableArray :: Format r (StableArray -> r)+formatStableArray = later $ \case+ StableArray u -> bformat int (hash u)++-- | Create a new memory table from host to remote arrays.+--+-- The function supplied should be the @free@ for the remote pointers being+-- stored. This function will be called by the GC, which typically runs on a+-- different thread. Consequently, unlike the functions in 'RemoteMemory', this+-- function cannot depend on any state.+--+new :: (forall a. ptr a -> IO ()) -> IO (MemoryTable ptr)+new release = do+ message "initialise memory table"+ tbl <- HT.new+ ref <- newMVar tbl+ nrs <- N.new release+ weak <- mkWeakMVar ref (return ())+ return $! MemoryTable ref weak nrs release+++-- | Look for the remote pointer corresponding to a given host-side array.+--+lookup :: forall m a. (HasCallStack, RemoteMemory m)+ => MemoryTable (RemotePtr m)+ -> SingleType a+ -> ArrayData a+ -> IO (Maybe (RemotePtr m (ScalarArrayDataR a)))+lookup (MemoryTable !ref _ _ _) !tp !arr+ | SingleArrayDict <- singleArrayDict tp = do+ sa <- makeStableArray tp arr+ mw <- withMVar ref (`HT.lookup` sa)+ case mw of+ Nothing -> trace (bformat ("lookup/not found: " % formatStableArray) sa) $ return Nothing+ Just (RemoteArray p _ w) -> do+ mv <- deRefWeak w+ case mv of+ Just{} -> trace (bformat ("lookup/found: " % formatStableArray) sa) $ return (Just $ castRemotePtr @m p)++ -- Note: [Weak pointer weirdness]+ --+ -- After the lookup is successful, there might conceivably be no further+ -- references to 'arr'. If that is so, and a garbage collection+ -- intervenes, the weak pointer might get tombstoned before 'deRefWeak'+ -- gets to it. In that case we throw an error (below). However, because+ -- we have used 'arr' in the continuation, this ensures that 'arr' is+ -- reachable in the continuation of 'deRefWeak' and thus 'deRefWeak'+ -- always succeeds. This sort of weirdness, typical of the world of weak+ -- pointers, is why we can not reuse the stable name 'sa' computed+ -- above in the error message.+ --+ Nothing ->+ makeStableArray tp arr >>= \x -> internalError ("dead weak pair: " % formatStableArray) x++-- | Allocate a new device array to be associated with the given host-side array.+-- This may not always use the `malloc` provided by the `RemoteMemory` instance.+-- In order to reduce the number of raw allocations, previously allocated remote+-- arrays will be re-used. In the event that the remote memory is exhausted,+-- 'Nothing' is returned.+--+malloc :: forall a m. (HasCallStack, RemoteMemory m, MonadIO m)+ => MemoryTable (RemotePtr m)+ -> SingleType a+ -> ArrayData a+ -> Int+ -> m (Maybe (RemotePtr m (ScalarArrayDataR a)))+malloc mt@(MemoryTable _ _ !nursery _) !tp !ad !n+ | SingleArrayDict <- singleArrayDict tp+ , SingleDict <- singleDict tp+ = do+ -- Note: [Allocation sizes]+ --+ -- Instead of allocating the exact number of elements requested, we round up to+ -- a fixed chunk size as specified by RemoteMemory.remoteAllocationSize. This+ -- means there is a greater chance the nursery will get a hit, and moreover+ -- that we can search the nursery for an exact size.+ --+ chunk <- remoteAllocationSize+ let -- next highest multiple of f from x+ multiple x f = (x + (f-1)) `quot` f+ bs = chunk * multiple (n * sizeOf (undefined::(ScalarArrayDataR a))) chunk+ --+ message ("malloc " % int % " bytes (" % int % " x " % int % " bytes, type=" % formatSingleType % ", pagesize=" % int % ")") bs n (sizeOf (undefined :: (ScalarArrayDataR a))) tp chunk+ --+ mp <-+ fmap (castRemotePtr @m)+ <$> attempt "malloc/nursery" (liftIO $ N.lookup bs nursery)+ `orElse`+ attempt "malloc/new" (mallocRemote bs)+ `orElse` do message "malloc/remote-malloc-failed (cleaning)"+ clean mt+ liftIO $ N.lookup bs nursery+ `orElse` do message "malloc/remote-malloc-failed (purging)"+ purge mt+ mallocRemote bs+ `orElse` do message "malloc/remote-malloc-failed (non-recoverable)"+ return Nothing+ case mp of+ Nothing -> return Nothing+ Just p' -> do+ insert mt tp ad p' bs+ return mp+ where+ {-# INLINE orElse #-}+ orElse :: m (Maybe x) -> m (Maybe x) -> m (Maybe x)+ orElse this next = do+ result <- this+ case result of+ Just{} -> return result+ Nothing -> next++ {-# INLINE attempt #-}+ attempt :: Builder -> m (Maybe x) -> m (Maybe x)+ attempt msg this = do+ result <- this+ case result of+ Just{} -> trace msg (return result)+ Nothing -> return Nothing++++-- | Deallocate the device array associated with the given host-side array.+-- Typically this should only be called in very specific circumstances.+--+free :: forall m a. (RemoteMemory m)+ => MemoryTable (RemotePtr m)+ -> SingleType a+ -> ArrayData a+ -> IO ()+free mt tp !arr = do+ sa <- makeStableArray tp arr+ freeStable @m mt sa+++-- | Deallocate the device array associated with the given StableArray. This+-- is useful for other memory managers built on top of the memory table.+--+freeStable+ :: forall m. RemoteMemory m+ => MemoryTable (RemotePtr m)+ -> StableArray+ -> IO ()+freeStable (MemoryTable !ref _ !nrs _) !sa =+ withMVar ref $ \mt ->+ HT.mutateIO mt sa $ \mw -> do+ case mw of+ Nothing ->+ message ("free/already-removed: " % formatStableArray) sa++ Just (RemoteArray !p !n _) -> do+ message ("free/nursery: " % formatStableArray % " of " % bytes') sa n+ N.insert n (castRemotePtr @m p) nrs+ -- Debug.remote_memory_free (unsafeRemotePtrToPtr @m p)++ return (Nothing, ())+++-- | Record an association between a host-side array and a new device memory+-- area. The device memory will be freed when the host array is garbage+-- collected.+--+insert+ :: forall m a. (RemoteMemory m, MonadIO m)+ => MemoryTable (RemotePtr m)+ -> SingleType a+ -> ArrayData a+ -> RemotePtr m (ScalarArrayDataR a)+ -> Int+ -> m ()+insert mt@(MemoryTable !ref _ _ _) !tp !arr !ptr !n | SingleArrayDict <- singleArrayDict tp = do+ key <- makeStableArray tp arr+ weak <- liftIO $ makeWeakArrayData tp arr () (Just $ freeStable @m mt key)+ message ("insert: " % formatStableArray) key+ -- liftIO $ Debug.remote_memory_alloc (unsafeRemotePtrToPtr @m ptr) n+ liftIO $ withMVar ref $ \tbl -> HT.insert tbl key (RemoteArray (castRemotePtr @m ptr) n weak)+++-- | Record an association between a host-side array and a remote memory area+-- that was not allocated by accelerate. The remote memory will NOT be re-used+-- once the host-side array is garbage collected.+--+-- This typically only has use for backends that provide an FFI.+--+insertUnmanaged+ :: forall m a. (MonadIO m, RemoteMemory m)+ => MemoryTable (RemotePtr m)+ -> SingleType a+ -> ArrayData a+ -> RemotePtr m (ScalarArrayDataR a)+ -> m ()+insertUnmanaged (MemoryTable !ref !weak_ref _ _) tp !arr !ptr | SingleArrayDict <- singleArrayDict tp = do+ key <- makeStableArray tp arr+ weak <- liftIO $ makeWeakArrayData tp arr () (Just $ remoteFinalizer weak_ref key)+ message ("insertUnmanaged: " % formatStableArray) key+ liftIO $ withMVar ref $ \tbl -> HT.insert tbl key (RemoteArray (castRemotePtr @m ptr) 0 weak)+++-- Removing entries+-- ----------------++-- | Initiate garbage collection and mark any arrays that no longer have+-- host-side equivalents as reusable.+--+clean :: forall m. (RemoteMemory m, MonadIO m) => MemoryTable (RemotePtr m) -> m ()+clean mt@(MemoryTable _ weak_ref nrs _) = management "clean" nrs . liftIO $ do+ -- Unfortunately there is no real way to force a GC then wait for it to+ -- finish. Calling performGC then yielding works moderately well in+ -- single-threaded cases, but tends to fall down otherwise. Either way, given+ -- that finalizers are often significantly delayed, it is worth our while+ -- traversing the table and explicitly freeing any dead entires.+ --+ Debug.emit_remote_gc+ performGC+ yield+ mr <- deRefWeak weak_ref+ case mr of+ Nothing -> return ()+ Just ref -> do+ rs <- withMVar ref $ HT.foldM removable [] -- collect arrays that can be removed+ mapM_ (freeStable @m mt) rs -- remove them all+ where+ removable rs (sa, RemoteArray _ _ w) = do+ alive <- isJust <$> deRefWeak w+ if alive+ then return rs+ else return (sa:rs)+++-- | Call `free` on all arrays that are not currently associated with host-side+-- arrays.+--+purge :: (RemoteMemory m, MonadIO m) => MemoryTable (RemotePtr m) -> m ()+purge (MemoryTable _ _ nursery@(Nursery nrs _) release)+ = management "purge" nursery+ $ liftIO (N.cleanup release nrs)+++-- | Initiate garbage collection and `free` any remote arrays that no longer+-- have matching host-side equivalents.+--+reclaim :: forall m. (RemoteMemory m, MonadIO m) => MemoryTable (RemotePtr m) -> m ()+reclaim mt = clean mt >> purge mt++remoteFinalizer :: Weak (MT p) -> StableArray -> IO ()+remoteFinalizer !weak_ref !key = do+ mr <- deRefWeak weak_ref+ case mr of+ Nothing -> message ("finalise/dead table: " % formatStableArray) key+ Just ref -> trace (bformat ("finalise: " % formatStableArray) key) $ withMVar ref (`HT.delete` key)+++-- Miscellaneous+-- -------------++-- | Make a new 'StableArray'.+--+{-# INLINE makeStableArray #-}+makeStableArray+ :: MonadIO m+ => SingleType a+ -> ArrayData a+ -> m StableArray+makeStableArray !tp !ad+ | SingleArrayDict <- singleArrayDict tp+ = return $! StableArray (uniqueArrayId ad)+++-- Weak arrays+-- -----------++-- | Make a weak pointer using an array as a key. Unlike the standard `mkWeak`,+-- this guarantees finalisers won't fire early.+--+makeWeakArrayData+ :: forall e c.+ SingleType e+ -> ArrayData e+ -> c+ -> Maybe (IO ())+ -> IO (Weak c)+makeWeakArrayData !tp !ad !c !mf | SingleArrayDict <- singleArrayDict tp = do+ let !uad = uniqueArrayData ad+ case mf of+ Nothing -> return ()+ Just f -> addFinalizer uad f+ mkWeak uad c+++-- Debug+-- -----++{-# INLINE bytes' #-}+bytes' :: Integral n => Format r (n -> r)+bytes' = bytes (fixed @Double 2 % " ")++{-# INLINE trace #-}+trace :: MonadIO m => Builder -> m a -> m a+trace msg next = message builder msg >> next++{-# INLINE message #-}+message :: MonadIO m => Format (m ()) a -> a+message fmt = Debug.traceM Debug.dump_gc ("gc: " % fmt)++{-# INLINE management #-}+management :: (RemoteMemory m, MonadIO m) => Builder -> Nursery p -> m a -> m a+management msg nrs next = do+ yes <- liftIO $ Debug.getFlag Debug.dump_gc+ if yes+ then do+ total <- totalRemoteMem+ before <- availableRemoteMem+ before_nrs <- liftIO $ N.size nrs+ r <- next+ after <- availableRemoteMem+ after_nrs <- liftIO $ N.size nrs+ message (builder % parenthesised ("freed: " % bytes' % ", stashed: " % bytes' % ", remaining: " % bytes' % " of " % bytes')) msg (before - after) (after_nrs - before_nrs) after total+ --+ return r+ else+ next+
+ src/Data/Array/Accelerate/Array/Unique.hs view
@@ -0,0 +1,135 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Array.Unique+-- Copyright : [2016..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Array.Unique+ where++import Data.Array.Accelerate.Lifetime++import Control.Applicative+import Control.Concurrent.Unique+import Control.DeepSeq+import Data.Word+import Foreign.ForeignPtr+import Foreign.ForeignPtr.Unsafe+import Foreign.Marshal.Array+import Foreign.Ptr+import Foreign.Storable+import Language.Haskell.TH.Extra+import System.IO.Unsafe+import Prelude+++-- | A uniquely identifiable array.+--+-- For the purposes of memory management, we use arrays as keys in a table. For+-- this reason we need a way to uniquely identify each array we create. We do+-- this by attaching a unique identifier to each array.+--+-- Note: [Unique array strictness]+--+-- The actual array data is in many cases unnecessary. For discrete memory+-- backends such as for GPUs, we require the unique identifier to track the data+-- in the remote memory space, but the data will in most cases never be copied+-- back to the host. Thus, the array payload field is only lazily allocated, and+-- we should be careful not to make this field overly strict.+--+data UniqueArray e = UniqueArray+ { uniqueArrayId :: {-# UNPACK #-} !Unique+ , uniqueArrayData :: {-# UNPACK #-} !(Lifetime (ForeignPtr e))+ }++instance NFData (UniqueArray e) where+ rnf = rnfUniqueArray++-- | Create a new UniqueArray+--+{-# INLINE newUniqueArray #-}+newUniqueArray :: ForeignPtr e -> IO (UniqueArray e)+newUniqueArray fp = UniqueArray <$> newUnique <*> newLifetime fp++-- | Access the pointer backing the unique array.+--+-- The array data is kept alive at least during the whole action, even if it is+-- not directly used inside. Note that it is not safe to return the pointer from+-- the action and use it after the action completes. All uses of the pointer+-- should be inside the bracketed function.+--+{-# INLINE withUniqueArrayPtr #-}+withUniqueArrayPtr :: UniqueArray a -> (Ptr a -> IO b) -> IO b+withUniqueArrayPtr ua go =+ withLifetime (uniqueArrayData ua) $ \fp -> withForeignPtr fp go++-- | Returns the element of an immutable array at the specified index. This+-- does no bounds checking.+--+{-# INLINE unsafeIndexArray #-}+unsafeIndexArray :: Storable e => UniqueArray e -> Int -> e+unsafeIndexArray !ua !i =+ unsafePerformIO $! unsafeReadArray ua i++-- | Read an element from a mutable array at the given index. This does no+-- bounds checking.+--+{-# INLINE unsafeReadArray #-}+unsafeReadArray :: Storable e => UniqueArray e -> Int -> IO e+unsafeReadArray !ua !i =+ withUniqueArrayPtr ua $ \ptr -> peekElemOff ptr i++-- | Write an element into a mutable array at the given index. This does no+-- bounds checking.+--+{-# INLINE unsafeWriteArray #-}+unsafeWriteArray :: Storable e => UniqueArray e -> Int -> e -> IO ()+unsafeWriteArray !ua !i !e =+ withUniqueArrayPtr ua $ \ptr -> pokeElemOff ptr i e+++-- | Extract the pointer backing the unique array.+--+-- This is potentially unsafe, as if the argument is the last occurrence of this+-- unique array then the finalisers will be run, potentially invalidating the+-- plain pointer just obtained.+--+-- See also: 'unsafeGetValue', 'unsafeForeignPtrToPtr'.+--+{-# INLINE unsafeUniqueArrayPtr #-}+unsafeUniqueArrayPtr :: UniqueArray a -> Ptr a+unsafeUniqueArrayPtr = unsafeForeignPtrToPtr . unsafeGetValue . uniqueArrayData+++-- | Ensure that the unique array is alive at the given place in a sequence of+-- IO actions. Note that this does not force the actual array payload.+--+-- See: [Unique array strictness]+--+{-# INLINE touchUniqueArray #-}+touchUniqueArray :: UniqueArray a -> IO ()+touchUniqueArray = touchLifetime . uniqueArrayData+++rnfUniqueArray :: UniqueArray a -> ()+rnfUniqueArray (UniqueArray _ ad) = unsafeGetValue ad `seq` ()++-- TODO: Make sure that the data is correctly aligned...+--+liftUniqueArray :: forall a. Storable a => Int -> UniqueArray a -> CodeQ (UniqueArray a)+liftUniqueArray sz ua = unsafeCodeCoerce $ do+ bytes <- runIO $ peekArray (sizeOf (undefined::a) * sz) (castPtr (unsafeUniqueArrayPtr ua) :: Ptr Word8)+ [| unsafePerformIO $ do+ fp <- newForeignPtr_ (Ptr $(litE (StringPrimL bytes)))+ ua' <- newUniqueArray (castForeignPtr fp)+ return ua'+ |]+
+ src/Data/Array/Accelerate/Async.hs view
@@ -0,0 +1,111 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE UnboxedTuples #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Async+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Async (++ -- * Asynchronous actions+ Async,++ -- ** Spawning+ async, asyncOn, asyncBound,++ -- ** Querying 'Async's+ wait, poll, cancel,++) where++import Control.Exception+import Control.Concurrent++import GHC.Exts+import GHC.Conc+import GHC.IO+++-- We need to execute the main thread asynchronously to give finalisers a chance+-- to run. Make sure to catch exceptions to avoid "blocked indefinitely on MVar"+-- errors.+--+data Async a = Async {-# UNPACK #-} !ThreadId+ {-# UNPACK #-} !(MVar (Either SomeException a))++-- | Spawn an asynchronous action in a separate thread.+--+async :: IO a -> IO (Async a)+async = inline asyncUsing rawForkIO++-- | Like 'async', but using 'forkOn' internally.+--+asyncOn :: Int -> IO a -> IO (Async a)+asyncOn cpu = inline asyncUsing (rawForkOn cpu)++-- | Like 'async', but using 'forkOS' internally.+--+asyncBound :: IO a -> IO (Async a)+asyncBound = inline asyncUsing forkOS++asyncUsing :: (IO () -> IO ThreadId) -> IO a -> IO (Async a)+asyncUsing fork action = do+ var <- newEmptyMVar+ tid <- mask $ \restore ->+ fork $ try (restore action) >>= putMVar var+ return (Async tid var)++-- | Block the calling thread until the computation completes, then return the+-- result.+--+{-# INLINE wait #-}+wait :: Async a -> IO a+wait (Async _ var) = either throwIO return =<< readMVar var++-- | Test whether the asynchronous computation has already completed. If so,+-- return the result, else 'Nothing'.+--+{-# INLINE poll #-}+poll :: Async a -> IO (Maybe a)+poll (Async _ var) =+ maybe (return Nothing) (either throwIO (return . Just)) =<< tryReadMVar var++-- | Cancel a running asynchronous computation.+--+{-# INLINE cancel #-}+cancel :: Async a -> IO ()+cancel (Async tid _) = throwTo tid ThreadKilled+++-- A version of 'forkIO' that does not include the outer exception handler. This+-- saves a bit of time when we will be installing our own exception handler.+--+-- Stolen from Simon Marlow's 'async' package (BSD).+--+{-# INLINE rawForkIO #-}+rawForkIO :: IO () -> IO ThreadId+#if __GLASGOW_HASKELL__ < 904+rawForkIO action = IO $ \s ->+#else+rawForkIO (IO action) = IO $ \s ->+#endif+ case fork# action s of+ (# s', tid #) -> (# s', ThreadId tid #)++{-# INLINE rawForkOn #-}+rawForkOn :: Int -> IO () -> IO ThreadId+#if __GLASGOW_HASKELL__ < 904+rawForkOn (I# cpu) action = IO $ \s ->+#else+rawForkOn (I# cpu) (IO action) = IO $ \s ->+#endif+ case forkOn# cpu action s of+ (# s', tid #) -> (# s', ThreadId tid #)+
+ src/Data/Array/Accelerate/Classes/Bounded.hs view
@@ -0,0 +1,154 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- |+-- Module : Data.Array.Accelerate.Classes.Bounded+-- Copyright : [2016..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Classes.Bounded (++ Bounded,+ P.minBound, P.maxBound,++) where++import Data.Array.Accelerate.Array.Data+import Data.Array.Accelerate.Pattern+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Type++import Prelude ( ($), (<$>), Num(..), Char, Bool, show, concat, map, mapM )+import Language.Haskell.TH.Extra hiding ( Exp )+import qualified Prelude as P+++-- | Name the upper and lower limits of a type. Types which are not totally+-- ordered may still have upper and lower bounds.+--+type Bounded a = (Elt a, P.Bounded (Exp a))+++instance P.Bounded (Exp ()) where+ minBound = constant ()+ maxBound = constant ()++instance P.Bounded (Exp Int) where+ minBound = mkMinBound+ maxBound = mkMaxBound++instance P.Bounded (Exp Int8) where+ minBound = mkMinBound+ maxBound = mkMaxBound++instance P.Bounded (Exp Int16) where+ minBound = mkMinBound+ maxBound = mkMaxBound++instance P.Bounded (Exp Int32) where+ minBound = mkMinBound+ maxBound = mkMaxBound++instance P.Bounded (Exp Int64) where+ minBound = mkMinBound+ maxBound = mkMaxBound++instance P.Bounded (Exp Word) where+ minBound = mkMinBound+ maxBound = mkMaxBound++instance P.Bounded (Exp Word8) where+ minBound = mkMinBound+ maxBound = mkMaxBound++instance P.Bounded (Exp Word16) where+ minBound = mkMinBound+ maxBound = mkMaxBound++instance P.Bounded (Exp Word32) where+ minBound = mkMinBound+ maxBound = mkMaxBound++instance P.Bounded (Exp Word64) where+ minBound = mkMinBound+ maxBound = mkMaxBound++instance P.Bounded (Exp CShort) where+ minBound = mkBitcast (mkMinBound @Int16)+ maxBound = mkBitcast (mkMaxBound @Int16)++instance P.Bounded (Exp CUShort) where+ minBound = mkBitcast (mkMinBound @Word16)+ maxBound = mkBitcast (mkMaxBound @Word16)++instance P.Bounded (Exp CInt) where+ minBound = mkBitcast (mkMinBound @Int32)+ maxBound = mkBitcast (mkMaxBound @Int32)++instance P.Bounded (Exp CUInt) where+ minBound = mkBitcast (mkMinBound @Word32)+ maxBound = mkBitcast (mkMaxBound @Word32)++instance P.Bounded (Exp CLong) where+ minBound = mkBitcast (mkMinBound @HTYPE_CLONG)+ maxBound = mkBitcast (mkMaxBound @HTYPE_CLONG)++instance P.Bounded (Exp CULong) where+ minBound = mkBitcast (mkMinBound @HTYPE_CULONG)+ maxBound = mkBitcast (mkMaxBound @HTYPE_CULONG)++instance P.Bounded (Exp CLLong) where+ minBound = mkBitcast (mkMinBound @Int64)+ maxBound = mkBitcast (mkMaxBound @Int64)++instance P.Bounded (Exp CULLong) where+ minBound = mkBitcast (mkMinBound @Word64)+ maxBound = mkBitcast (mkMaxBound @Word64)++instance P.Bounded (Exp Bool) where+ minBound = constant P.minBound+ maxBound = constant P.maxBound++instance P.Bounded (Exp Char) where+ minBound = mkMinBound+ maxBound = mkMaxBound++instance P.Bounded (Exp CChar) where+ minBound = mkBitcast (mkMinBound @HTYPE_CCHAR)+ maxBound = mkBitcast (mkMaxBound @HTYPE_CCHAR)++instance P.Bounded (Exp CSChar) where+ minBound = mkBitcast (mkMinBound @Int8)+ maxBound = mkBitcast (mkMaxBound @Int8)++instance P.Bounded (Exp CUChar) where+ minBound = mkBitcast (mkMinBound @Word8)+ maxBound = mkBitcast (mkMaxBound @Word8)++$(runQ $ do+ let+ mkInstance :: Int -> Q [Dec]+ mkInstance n =+ let+ xs = [ mkName ('x':show i) | i <- [0 .. n-1] ]+ cst = tupT (map (\x -> [t| Bounded $(varT x) |]) xs)+ res = tupT (map varT xs)+ app x = appsE (conE (mkName ('T':show n)) : P.replicate n x)+ in+ [d| instance $cst => P.Bounded (Exp $res) where+ minBound = $(app [| P.minBound |])+ maxBound = $(app [| P.maxBound |])+ |]+ --+ concat <$> mapM mkInstance [2..16]+ )+
+ src/Data/Array/Accelerate/Classes/Enum.hs view
@@ -0,0 +1,195 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MonoLocalBinds #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- |+-- Module : Data.Array.Accelerate.Classes.Enum+-- Copyright : [2016..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Classes.Enum (++ Enum,+ succ, pred,++) where++import Data.Array.Accelerate.Classes.Num+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Type+import Text.Printf++import Prelude ( ($), String, error, unlines, succ, pred )+import qualified Prelude as P+++-- | Operations over sequentially ordered types+--+type Enum a = P.Enum (Exp a)+++instance P.Enum (Exp Int) where+ succ = defaultSucc+ pred = defaultPred+ toEnum = defaultToEnum+ fromEnum = defaultFromEnum++instance P.Enum (Exp Int8) where+ succ = defaultSucc+ pred = defaultPred+ toEnum = defaultToEnum+ fromEnum = defaultFromEnum++instance P.Enum (Exp Int16) where+ succ = defaultSucc+ pred = defaultPred+ toEnum = defaultToEnum+ fromEnum = defaultFromEnum++instance P.Enum (Exp Int32) where+ succ = defaultSucc+ pred = defaultPred+ toEnum = defaultToEnum+ fromEnum = defaultFromEnum++instance P.Enum (Exp Int64) where+ succ = defaultSucc+ pred = defaultPred+ toEnum = defaultToEnum+ fromEnum = defaultFromEnum++instance P.Enum (Exp Word) where+ succ = defaultSucc+ pred = defaultPred+ toEnum = defaultToEnum+ fromEnum = defaultFromEnum++instance P.Enum (Exp Word8) where+ succ = defaultSucc+ pred = defaultPred+ toEnum = defaultToEnum+ fromEnum = defaultFromEnum++instance P.Enum (Exp Word16) where+ succ = defaultSucc+ pred = defaultPred+ toEnum = defaultToEnum+ fromEnum = defaultFromEnum++instance P.Enum (Exp Word32) where+ succ = defaultSucc+ pred = defaultPred+ toEnum = defaultToEnum+ fromEnum = defaultFromEnum++instance P.Enum (Exp Word64) where+ succ = defaultSucc+ pred = defaultPred+ toEnum = defaultToEnum+ fromEnum = defaultFromEnum++instance P.Enum (Exp CInt) where+ succ = defaultSucc+ pred = defaultPred+ toEnum = defaultToEnum+ fromEnum = defaultFromEnum++instance P.Enum (Exp CUInt) where+ succ = defaultSucc+ pred = defaultPred+ toEnum = defaultToEnum+ fromEnum = defaultFromEnum++instance P.Enum (Exp CLong) where+ succ = defaultSucc+ pred = defaultPred+ toEnum = defaultToEnum+ fromEnum = defaultFromEnum++instance P.Enum (Exp CULong) where+ succ = defaultSucc+ pred = defaultPred+ toEnum = defaultToEnum+ fromEnum = defaultFromEnum++instance P.Enum (Exp CLLong) where+ succ = defaultSucc+ pred = defaultPred+ toEnum = defaultToEnum+ fromEnum = defaultFromEnum++instance P.Enum (Exp CULLong) where+ succ = defaultSucc+ pred = defaultPred+ toEnum = defaultToEnum+ fromEnum = defaultFromEnum++instance P.Enum (Exp CShort) where+ succ = defaultSucc+ pred = defaultPred+ toEnum = defaultToEnum+ fromEnum = defaultFromEnum++instance P.Enum (Exp CUShort) where+ succ = defaultSucc+ pred = defaultPred+ toEnum = defaultToEnum+ fromEnum = defaultFromEnum++instance P.Enum (Exp Half) where+ succ = defaultSucc+ pred = defaultPred+ toEnum = defaultToEnum+ fromEnum = defaultFromEnum++instance P.Enum (Exp Float) where+ succ = defaultSucc+ pred = defaultPred+ toEnum = defaultToEnum+ fromEnum = defaultFromEnum++instance P.Enum (Exp Double) where+ succ = defaultSucc+ pred = defaultPred+ toEnum = defaultToEnum+ fromEnum = defaultFromEnum++instance P.Enum (Exp CFloat) where+ succ = defaultSucc+ pred = defaultPred+ toEnum = defaultToEnum+ fromEnum = defaultFromEnum++instance P.Enum (Exp CDouble) where+ succ = defaultSucc+ pred = defaultPred+ toEnum = defaultToEnum+ fromEnum = defaultFromEnum++defaultSucc :: Num a => Exp a -> Exp a+defaultSucc x = x + 1++defaultPred :: Num a => Exp a -> Exp a+defaultPred x = x - 1++defaultToEnum :: Int -> a+defaultToEnum = preludeError "toEnum"++defaultFromEnum :: a -> Int+defaultFromEnum = preludeError "fromEnum"++preludeError :: String -> a+preludeError x+ = error+ $ unlines [ printf "Prelude.%s is not supported for Accelerate types" x+ , ""+ , "These Prelude.Enum instances are present only to fulfil superclass"+ , "constraints for subsequent classes in the standard Haskell numeric hierarchy."+ ]+
+ src/Data/Array/Accelerate/Classes/Eq.hs view
@@ -0,0 +1,217 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE ViewPatterns #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- |+-- Module : Data.Array.Accelerate.Classes.Eq+-- Copyright : [2016..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Classes.Eq (++ Bool(..), pattern True_, pattern False_,+ Eq(..),+ (&&), (&&!),+ (||), (||!),+ not,++) where++import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.Pattern+import Data.Array.Accelerate.Pattern.Bool+import Data.Array.Accelerate.Representation.Tag+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Sugar.Shape+import Data.Array.Accelerate.Type++import Data.Bool ( Bool(..) )+import Data.Char ( Char )+import Text.Printf+import Prelude ( ($), String, Num(..), Ordering(..), show, error, return, concat, map, zipWith, foldr1, mapM )+import Language.Haskell.TH.Extra hiding ( Exp )+import qualified Prelude as P+++infix 4 ==+infix 4 /=++-- | Conjunction: True if both arguments are true. This is a short-circuit+-- operator, so the second argument will be evaluated only if the first is true.+--+infixr 3 &&+(&&) :: Exp Bool -> Exp Bool -> Exp Bool+(&&) (Exp x) (Exp y) =+ mkExp $ SmartExp (Cond (SmartExp $ Prj PairIdxLeft x)+ (SmartExp $ Prj PairIdxLeft y)+ (SmartExp $ Const scalarTypeWord8 0))+ `Pair` SmartExp Nil++-- | Conjunction: True if both arguments are true. This is a strict version of+-- '(&&)': it will always evaluate both arguments, even when the first is false.+--+-- @since 1.3.0.0+--+infixr 3 &&!+(&&!) :: Exp Bool -> Exp Bool -> Exp Bool+(&&!) = mkLAnd++-- | Disjunction: True if either argument is true. This is a short-circuit+-- operator, so the second argument will be evaluated only if the first is+-- false.+--+infixr 2 ||+(||) :: Exp Bool -> Exp Bool -> Exp Bool+(||) (Exp x) (Exp y) =+ mkExp $ SmartExp (Cond (SmartExp $ Prj PairIdxLeft x)+ (SmartExp $ Const scalarTypeWord8 1)+ (SmartExp $ Prj PairIdxLeft y))+ `Pair` SmartExp Nil+++-- | Disjunction: True if either argument is true. This is a strict version of+-- '(||)': it will always evaluate both arguments, even when the first is true.+--+-- @since 1.3.0.0+--+infixr 2 ||!+(||!) :: Exp Bool -> Exp Bool -> Exp Bool+(||!) = mkLOr++-- | Logical negation+--+not :: Exp Bool -> Exp Bool+not = mkLNot+++-- | The 'Eq' class defines equality '==' and inequality '/=' for scalar+-- Accelerate expressions.+--+-- For convenience, we include 'Elt' as a superclass.+--+class Elt a => Eq a where+ (==) :: Exp a -> Exp a -> Exp Bool+ (/=) :: Exp a -> Exp a -> Exp Bool+ {-# MINIMAL (==) | (/=) #-}+ x == y = mkLNot (x /= y)+ x /= y = mkLNot (x == y)+++instance Eq () where+ _ == _ = True_+ _ /= _ = False_++instance Eq Z where+ _ == _ = True_+ _ /= _ = False_++-- Instances of 'Prelude.Eq' don't make sense with the standard signatures as+-- the return type is fixed to 'Bool'. This instance is provided to provide+-- a useful error message.+--+instance P.Eq (Exp a) where+ (==) = preludeError "Eq.(==)" "(==)"+ (/=) = preludeError "Eq.(/=)" "(/=)"++preludeError :: String -> String -> a+preludeError x y = error (printf "Prelude.%s applied to EDSL types: use Data.Array.Accelerate.%s instead" x y)++runQ $ do+ let+ integralTypes :: [Name]+ integralTypes =+ [ ''Int+ , ''Int8+ , ''Int16+ , ''Int32+ , ''Int64+ , ''Word+ , ''Word8+ , ''Word16+ , ''Word32+ , ''Word64+ ]++ floatingTypes :: [Name]+ floatingTypes =+ [ ''Half+ , ''Float+ , ''Double+ ]++ nonNumTypes :: [Name]+ nonNumTypes =+ [ ''Char+ ]++ cTypes :: [Name]+ cTypes =+ [ ''CInt+ , ''CUInt+ , ''CLong+ , ''CULong+ , ''CLLong+ , ''CULLong+ , ''CShort+ , ''CUShort+ , ''CChar+ , ''CUChar+ , ''CSChar+ , ''CFloat+ , ''CDouble+ ]++ mkPrim :: Name -> Q [Dec]+ mkPrim t =+ [d| instance Eq $(conT t) where+ (==) = mkEq+ (/=) = mkNEq+ |]++ mkTup :: Int -> Q [Dec]+ mkTup n =+ let+ xs = [ mkName ('x':show i) | i <- [0 .. n-1] ]+ ys = [ mkName ('y':show i) | i <- [0 .. n-1] ]+ cst = tupT (map (\x -> [t| Eq $(varT x) |]) xs)+ res = tupT (map varT xs)+ pat vs = conP (mkName ('T':show n)) (map varP vs)+ in+ [d| instance ($cst) => Eq $res where+ $(pat xs) == $(pat ys) = $(foldr1 (\vs v -> [| $vs && $v |]) (zipWith (\x y -> [| $x == $y |]) (map varE xs) (map varE ys)))+ $(pat xs) /= $(pat ys) = $(foldr1 (\vs v -> [| $vs || $v |]) (zipWith (\x y -> [| $x /= $y |]) (map varE xs) (map varE ys)))+ |]++ is <- mapM mkPrim integralTypes+ fs <- mapM mkPrim floatingTypes+ ns <- mapM mkPrim nonNumTypes+ cs <- mapM mkPrim cTypes+ ts <- mapM mkTup [2..16]+ return $ concat (concat [is,fs,ns,cs,ts])++instance Eq sh => Eq (sh :. Int) where+ x == y = indexHead x == indexHead y && indexTail x == indexTail y+ x /= y = indexHead x /= indexHead y || indexTail x /= indexTail y++instance Eq Bool where+ x == y = mkCoerce x == (mkCoerce y :: Exp PrimBool)+ x /= y = mkCoerce x /= (mkCoerce y :: Exp PrimBool)++instance Eq Ordering where+ x == y = mkCoerce x == (mkCoerce y :: Exp TAG)+ x /= y = mkCoerce x /= (mkCoerce y :: Exp TAG)+
+ src/Data/Array/Accelerate/Classes/Floating.hs view
@@ -0,0 +1,145 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- |+-- Module : Data.Array.Accelerate.Classes.Floating+-- Copyright : [2016..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Classes.Floating (++ Floating,+ P.pi,+ P.sin, P.cos, P.tan,+ P.asin, P.acos, P.atan,+ P.sinh, P.cosh, P.tanh,+ P.asinh, P.acosh, P.atanh,+ P.exp,+ P.sqrt,+ P.log,+ (P.**),+ P.logBase,++) where++import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.Classes.Fractional++import qualified Prelude as P+++-- | Trigonometric and hyperbolic functions and related functions+--+type Floating a = (Fractional a, P.Floating (Exp a))+++instance P.Floating (Exp Half) where+ pi = mkPi+ sin = mkSin+ cos = mkCos+ tan = mkTan+ asin = mkAsin+ acos = mkAcos+ atan = mkAtan+ sinh = mkSinh+ cosh = mkCosh+ tanh = mkTanh+ asinh = mkAsinh+ acosh = mkAcosh+ atanh = mkAtanh+ exp = mkExpFloating+ sqrt = mkSqrt+ log = mkLog+ (**) = mkFPow+ logBase = mkLogBase++instance P.Floating (Exp Float) where+ pi = mkPi+ sin = mkSin+ cos = mkCos+ tan = mkTan+ asin = mkAsin+ acos = mkAcos+ atan = mkAtan+ sinh = mkSinh+ cosh = mkCosh+ tanh = mkTanh+ asinh = mkAsinh+ acosh = mkAcosh+ atanh = mkAtanh+ exp = mkExpFloating+ sqrt = mkSqrt+ log = mkLog+ (**) = mkFPow+ logBase = mkLogBase++instance P.Floating (Exp Double) where+ pi = mkPi+ sin = mkSin+ cos = mkCos+ tan = mkTan+ asin = mkAsin+ acos = mkAcos+ atan = mkAtan+ sinh = mkSinh+ cosh = mkCosh+ tanh = mkTanh+ asinh = mkAsinh+ acosh = mkAcosh+ atanh = mkAtanh+ exp = mkExpFloating+ sqrt = mkSqrt+ log = mkLog+ (**) = mkFPow+ logBase = mkLogBase++instance P.Floating (Exp CFloat) where+ pi = mkBitcast (mkPi @Float)+ sin = mkSin+ cos = mkCos+ tan = mkTan+ asin = mkAsin+ acos = mkAcos+ atan = mkAtan+ sinh = mkSinh+ cosh = mkCosh+ tanh = mkTanh+ asinh = mkAsinh+ acosh = mkAcosh+ atanh = mkAtanh+ exp = mkExpFloating+ sqrt = mkSqrt+ log = mkLog+ (**) = mkFPow+ logBase = mkLogBase++instance P.Floating (Exp CDouble) where+ pi = mkBitcast (mkPi @Double)+ sin = mkSin+ cos = mkCos+ tan = mkTan+ asin = mkAsin+ acos = mkAcos+ atan = mkAtan+ sinh = mkSinh+ cosh = mkCosh+ tanh = mkTanh+ asinh = mkAsinh+ acosh = mkAcosh+ atanh = mkAtanh+ exp = mkExpFloating+ sqrt = mkSqrt+ log = mkLog+ (**) = mkFPow+ logBase = mkLogBase+
+ src/Data/Array/Accelerate/Classes/Fractional.hs view
@@ -0,0 +1,72 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- |+-- Module : Data.Array.Accelerate.Classes.Fractional+-- Copyright : [2016..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Classes.Fractional (++ Fractional,+ (P./), P.recip, P.fromRational,++) where++import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.Classes.Num++import Prelude ( (.) )+import qualified Prelude as P+++-- | Conversion from a 'Rational'.+--+-- A floating point literal representations the application of the function+-- 'fromRational' to a value of type 'Rational'. We export this specialised+-- version where the return type is fixed to an 'Exp' term in order to improve+-- type checking in Accelerate modules when @RebindableSyntax@ is enabled.+--+-- fromRational :: Fractional a => Rational -> Exp a+-- fromRational = P.fromRational+++-- | Fractional numbers, supporting real division+--+type Fractional a = (Num a, P.Fractional (Exp a))+++instance P.Fractional (Exp Half) where+ (/) = mkFDiv+ recip = mkRecip+ fromRational = constant . P.fromRational++instance P.Fractional (Exp Float) where+ (/) = mkFDiv+ recip = mkRecip+ fromRational = constant . P.fromRational++instance P.Fractional (Exp Double) where+ (/) = mkFDiv+ recip = mkRecip+ fromRational = constant . P.fromRational++instance P.Fractional (Exp CFloat) where+ (/) = mkFDiv+ recip = mkRecip+ fromRational = constant . P.fromRational++instance P.Fractional (Exp CDouble) where+ (/) = mkFDiv+ recip = mkRecip+ fromRational = constant . P.fromRational+
+ src/Data/Array/Accelerate/Classes/FromIntegral.hs view
@@ -0,0 +1,85 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE MonoLocalBinds #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TemplateHaskell #-}+-- |+-- Module : Data.Array.Accelerate.Classes.FromIntegral+-- Copyright : [2016..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Classes.FromIntegral (++ FromIntegral(..),++) where++import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.Classes.Integral++import Language.Haskell.TH hiding ( Exp )+import Prelude hiding ( Integral )+++-- | Accelerate lacks a most-general lossless 'Prelude.Integer' type, which the+-- standard 'Prelude.fromIntegral' function uses as an intermediate value when+-- coercing from integral types. Instead, we use this class to capture a direct+-- coercion between two types.+--+class FromIntegral a b where+ -- | General coercion from integral types+ fromIntegral :: Integral a => Exp a -> Exp b++-- instance {-# OVERLAPPABLE #-} (Elt a, Elt b, IsIntegral a, IsNum b) => FromIntegral a b where+-- fromIntegral = mkFromIntegral+++-- Reify in ghci:+--+-- $( stringE . show =<< reify ''Thing )++-- Generate all the standard instances explicitly. This gives us sensible error+-- messages when we don't have an instance available, rather than a "can not+-- deduce IsNum..." style error (which the user can do nothing about).+--+$(runQ $ do+ let+ -- Get all the types that our dictionaries reify+ digItOut :: Name -> Q [Name]+ digItOut name = do+ TyConI (DataD _ _ _ _ cons _) <- reify name+ let+ -- This is what a constructor such as IntegralNumType will be reified+ -- as prior to GHC 8.4...+ dig (NormalC _ [(_, AppT (ConT n) (VarT _))]) = digItOut n+ -- ...but this is what IntegralNumType will be reified as on GHC 8.4+ -- and later, after the changes described in+ -- https://ghc.haskell.org/trac/ghc/wiki/Migration/8.4#TemplateHaskellreificationchangesforGADTs+ dig (ForallC _ _ (GadtC _ [(_, AppT (ConT n) (VarT _))] _)) = digItOut n+ dig (GadtC _ _ (AppT (ConT _) (ConT n))) = return [n]+ dig _ = error "Unexpected case generating FromIntegral instances"+ --+ concat `fmap` mapM dig cons++ thFromIntegral :: Name -> Name -> Q Dec+ thFromIntegral a b =+ let+ ty = AppT (AppT (ConT (mkName "FromIntegral")) (ConT a)) (ConT b)+ dec = ValD (VarP (mkName "fromIntegral")) (NormalB (VarE (mkName f))) []+ f | a == b = "id"+ | otherwise = "mkFromIntegral"+ in+ instanceD (return []) (return ty) [return dec]+ --+ as <- digItOut ''IntegralType+ bs <- digItOut ''NumType+ sequence [ thFromIntegral a b | a <- as, b <- bs ]+ )+
+ src/Data/Array/Accelerate/Classes/Integral.hs view
@@ -0,0 +1,207 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MonoLocalBinds #-}+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- |+-- Module : Data.Array.Accelerate.Classes.Integral+-- Copyright : [2016..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Classes.Integral (++ Integral,+ P.quot,+ P.rem,+ P.div,+ P.mod,+ P.quotRem,+ P.divMod,++) where++import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.Classes.Enum+import Data.Array.Accelerate.Classes.Num+import Data.Array.Accelerate.Classes.Ord+import Data.Array.Accelerate.Classes.Real ()++import Prelude ( error )+import qualified Prelude as P+++-- | Integral numbers, supporting integral division+--+type Integral a = (Enum a, Ord a, Num a, P.Integral (Exp a))+++instance P.Integral (Exp Int) where+ quot = mkQuot+ rem = mkRem+ div = mkIDiv+ mod = mkMod+ quotRem = mkQuotRem+ divMod = mkDivMod+ toInteger = error "Prelude.toInteger not supported for Accelerate types"++instance P.Integral (Exp Int8) where+ quot = mkQuot+ rem = mkRem+ div = mkIDiv+ mod = mkMod+ quotRem = mkQuotRem+ divMod = mkDivMod+ toInteger = error "Prelude.toInteger not supported for Accelerate types"++instance P.Integral (Exp Int16) where+ quot = mkQuot+ rem = mkRem+ div = mkIDiv+ mod = mkMod+ quotRem = mkQuotRem+ divMod = mkDivMod+ toInteger = error "Prelude.toInteger not supported for Accelerate types"++instance P.Integral (Exp Int32) where+ quot = mkQuot+ rem = mkRem+ div = mkIDiv+ mod = mkMod+ quotRem = mkQuotRem+ divMod = mkDivMod+ toInteger = error "Prelude.toInteger not supported for Accelerate types"++instance P.Integral (Exp Int64) where+ quot = mkQuot+ rem = mkRem+ div = mkIDiv+ mod = mkMod+ quotRem = mkQuotRem+ divMod = mkDivMod+ toInteger = error "Prelude.toInteger not supported for Accelerate types"++instance P.Integral (Exp Word) where+ quot = mkQuot+ rem = mkRem+ div = mkIDiv+ mod = mkMod+ quotRem = mkQuotRem+ divMod = mkDivMod+ toInteger = error "Prelude.toInteger not supported for Accelerate types"++instance P.Integral (Exp Word8) where+ quot = mkQuot+ rem = mkRem+ div = mkIDiv+ mod = mkMod+ quotRem = mkQuotRem+ divMod = mkDivMod+ toInteger = error "Prelude.toInteger not supported for Accelerate types"++instance P.Integral (Exp Word16) where+ quot = mkQuot+ rem = mkRem+ div = mkIDiv+ mod = mkMod+ quotRem = mkQuotRem+ divMod = mkDivMod+ toInteger = error "Prelude.toInteger not supported for Accelerate types"++instance P.Integral (Exp Word32) where+ quot = mkQuot+ rem = mkRem+ div = mkIDiv+ mod = mkMod+ quotRem = mkQuotRem+ divMod = mkDivMod+ toInteger = error "Prelude.toInteger not supported for Accelerate types"++instance P.Integral (Exp Word64) where+ quot = mkQuot+ rem = mkRem+ div = mkIDiv+ mod = mkMod+ quotRem = mkQuotRem+ divMod = mkDivMod+ toInteger = error "Prelude.toInteger not supported for Accelerate types"++instance P.Integral (Exp CInt) where+ quot = mkQuot+ rem = mkRem+ div = mkIDiv+ mod = mkMod+ quotRem = mkQuotRem+ divMod = mkDivMod+ toInteger = error "Prelude.toInteger not supported for Accelerate types"++instance P.Integral (Exp CUInt) where+ quot = mkQuot+ rem = mkRem+ div = mkIDiv+ mod = mkMod+ quotRem = mkQuotRem+ divMod = mkDivMod+ toInteger = error "Prelude.toInteger not supported for Accelerate types"++instance P.Integral (Exp CLong) where+ quot = mkQuot+ rem = mkRem+ div = mkIDiv+ mod = mkMod+ quotRem = mkQuotRem+ divMod = mkDivMod+ toInteger = error "Prelude.toInteger not supported for Accelerate types"++instance P.Integral (Exp CULong) where+ quot = mkQuot+ rem = mkRem+ div = mkIDiv+ mod = mkMod+ quotRem = mkQuotRem+ divMod = mkDivMod+ toInteger = error "Prelude.toInteger not supported for Accelerate types"++instance P.Integral (Exp CLLong) where+ quot = mkQuot+ rem = mkRem+ div = mkIDiv+ mod = mkMod+ quotRem = mkQuotRem+ divMod = mkDivMod+ toInteger = error "Prelude.toInteger not supported for Accelerate types"++instance P.Integral (Exp CULLong) where+ quot = mkQuot+ rem = mkRem+ div = mkIDiv+ mod = mkMod+ quotRem = mkQuotRem+ divMod = mkDivMod+ toInteger = error "Prelude.toInteger not supported for Accelerate types"++instance P.Integral (Exp CShort) where+ quot = mkQuot+ rem = mkRem+ div = mkIDiv+ mod = mkMod+ quotRem = mkQuotRem+ divMod = mkDivMod+ toInteger = error "Prelude.toInteger not supported for Accelerate types"++instance P.Integral (Exp CUShort) where+ quot = mkQuot+ rem = mkRem+ div = mkIDiv+ mod = mkMod+ quotRem = mkQuotRem+ divMod = mkDivMod+ toInteger = error "Prelude.toInteger not supported for Accelerate types"+
+ src/Data/Array/Accelerate/Classes/Num.hs view
@@ -0,0 +1,275 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- |+-- Module : Data.Array.Accelerate.Classes.Num+-- Copyright : [2016..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Classes.Num (++ Num,+ (P.+), (P.-), (P.*), P.negate, P.abs, P.signum, P.fromInteger,++) where++import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Type++import Prelude ( (.) )+import qualified Prelude as P+++-- Note: [Haskell/Accelerate numeric hierarchy]+--+-- Should we replace 'Prelude.Num' with our own version, as we did with 'Ord'+-- and 'Eq'? That might require clients to enable RebindableSyntax in order to+-- get the correct 'fromInteger' (or miss out on special magic and need to add+-- 'constant' instead).+--+-- I think that we should, because otherwise we require FlexibleContexts and+-- constraints are going to be inconsistent, e.g.:+--+-- f :: (P.Num (Exp a), A.Ord a) => ...+--+-- A light-weight alternative is the following constraint kind:+--+-- UPDATE TLM 2018-01-12: I attempted separating the two class hierarchies, and+-- while in principle it works, has very poor ergonomics in modules which use+-- both Accelerate and standard Haskell types. RebindableSyntax only helps for+-- Accelerate-only modules; for mixed-mode files, we need to use every operation+-- qualified, which is a pain. On the other hand, type inference appears to be+-- much, _much_ better.+--+++-- | Conversion from an 'Integer'.+--+-- An integer literal represents the application of the function 'fromInteger'+-- to the appropriate value of type 'Integer'. We export this specialised+-- version where the return type is fixed to an 'Exp' term in order to improve+-- type checking in Accelerate modules when @RebindableSyntax@ is enabled.+--+-- fromInteger :: Num a => Integer -> Exp a+-- fromInteger = P.fromInteger+++-- | Basic numeric class+--+type Num a = (Elt a, P.Num (Exp a))+++instance P.Num (Exp Int) where+ (+) = mkAdd+ (-) = mkSub+ (*) = mkMul+ negate = mkNeg+ abs = mkAbs+ signum = mkSig+ fromInteger = constant . P.fromInteger++instance P.Num (Exp Int8) where+ (+) = mkAdd+ (-) = mkSub+ (*) = mkMul+ negate = mkNeg+ abs = mkAbs+ signum = mkSig+ fromInteger = constant . P.fromInteger++instance P.Num (Exp Int16) where+ (+) = mkAdd+ (-) = mkSub+ (*) = mkMul+ negate = mkNeg+ abs = mkAbs+ signum = mkSig+ fromInteger = constant . P.fromInteger++instance P.Num (Exp Int32) where+ (+) = mkAdd+ (-) = mkSub+ (*) = mkMul+ negate = mkNeg+ abs = mkAbs+ signum = mkSig+ fromInteger = constant . P.fromInteger++instance P.Num (Exp Int64) where+ (+) = mkAdd+ (-) = mkSub+ (*) = mkMul+ negate = mkNeg+ abs = mkAbs+ signum = mkSig+ fromInteger = constant . P.fromInteger++instance P.Num (Exp Word) where+ (+) = mkAdd+ (-) = mkSub+ (*) = mkMul+ negate = mkNeg+ abs = mkAbs+ signum = mkSig+ fromInteger = constant . P.fromInteger++instance P.Num (Exp Word8) where+ (+) = mkAdd+ (-) = mkSub+ (*) = mkMul+ negate = mkNeg+ abs = mkAbs+ signum = mkSig+ fromInteger = constant . P.fromInteger++instance P.Num (Exp Word16) where+ (+) = mkAdd+ (-) = mkSub+ (*) = mkMul+ negate = mkNeg+ abs = mkAbs+ signum = mkSig+ fromInteger = constant . P.fromInteger++instance P.Num (Exp Word32) where+ (+) = mkAdd+ (-) = mkSub+ (*) = mkMul+ negate = mkNeg+ abs = mkAbs+ signum = mkSig+ fromInteger = constant . P.fromInteger++instance P.Num (Exp Word64) where+ (+) = mkAdd+ (-) = mkSub+ (*) = mkMul+ negate = mkNeg+ abs = mkAbs+ signum = mkSig+ fromInteger = constant . P.fromInteger++instance P.Num (Exp CInt) where+ (+) = mkAdd+ (-) = mkSub+ (*) = mkMul+ negate = mkNeg+ abs = mkAbs+ signum = mkSig+ fromInteger = constant . P.fromInteger++instance P.Num (Exp CUInt) where+ (+) = mkAdd+ (-) = mkSub+ (*) = mkMul+ negate = mkNeg+ abs = mkAbs+ signum = mkSig+ fromInteger = constant . P.fromInteger++instance P.Num (Exp CLong) where+ (+) = mkAdd+ (-) = mkSub+ (*) = mkMul+ negate = mkNeg+ abs = mkAbs+ signum = mkSig+ fromInteger = constant . P.fromInteger++instance P.Num (Exp CULong) where+ (+) = mkAdd+ (-) = mkSub+ (*) = mkMul+ negate = mkNeg+ abs = mkAbs+ signum = mkSig+ fromInteger = constant . P.fromInteger++instance P.Num (Exp CLLong) where+ (+) = mkAdd+ (-) = mkSub+ (*) = mkMul+ negate = mkNeg+ abs = mkAbs+ signum = mkSig+ fromInteger = constant . P.fromInteger++instance P.Num (Exp CULLong) where+ (+) = mkAdd+ (-) = mkSub+ (*) = mkMul+ negate = mkNeg+ abs = mkAbs+ signum = mkSig+ fromInteger = constant . P.fromInteger++instance P.Num (Exp CShort) where+ (+) = mkAdd+ (-) = mkSub+ (*) = mkMul+ negate = mkNeg+ abs = mkAbs+ signum = mkSig+ fromInteger = constant . P.fromInteger++instance P.Num (Exp CUShort) where+ (+) = mkAdd+ (-) = mkSub+ (*) = mkMul+ negate = mkNeg+ abs = mkAbs+ signum = mkSig+ fromInteger = constant . P.fromInteger++instance P.Num (Exp Half) where+ (+) = mkAdd+ (-) = mkSub+ (*) = mkMul+ negate = mkNeg+ abs = mkAbs+ signum = mkSig+ fromInteger = constant . P.fromInteger++instance P.Num (Exp Float) where+ (+) = mkAdd+ (-) = mkSub+ (*) = mkMul+ negate = mkNeg+ abs = mkAbs+ signum = mkSig+ fromInteger = constant . P.fromInteger++instance P.Num (Exp Double) where+ (+) = mkAdd+ (-) = mkSub+ (*) = mkMul+ negate = mkNeg+ abs = mkAbs+ signum = mkSig+ fromInteger = constant . P.fromInteger++instance P.Num (Exp CFloat) where+ (+) = mkAdd+ (-) = mkSub+ (*) = mkMul+ negate = mkNeg+ abs = mkAbs+ signum = mkSig+ fromInteger = constant . P.fromInteger++instance P.Num (Exp CDouble) where+ (+) = mkAdd+ (-) = mkSub+ (*) = mkMul+ negate = mkNeg+ abs = mkAbs+ signum = mkSig+ fromInteger = constant . P.fromInteger
+ src/Data/Array/Accelerate/Classes/Ord.hs view
@@ -0,0 +1,249 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE RebindableSyntax #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE ViewPatterns #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- |+-- Module : Data.Array.Accelerate.Classes.Ord+-- Copyright : [2016..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Classes.Ord (++ Ord(..),+ Ordering(..), pattern LT_, pattern EQ_, pattern GT_,++) where++import Data.Array.Accelerate.Analysis.Match+import Data.Array.Accelerate.Pattern+import Data.Array.Accelerate.Pattern.Ordering+import Data.Array.Accelerate.Representation.Tag+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Sugar.Shape+import Data.Array.Accelerate.Type++-- We must hide (==), as that operator is used for the literals 0, 1 and 2 in the pattern synonyms for Ordering.+-- As RebindableSyntax is enabled, a literal pattern is compiled to a call to (==), meaning that the Prelude.(==) should be in scope as (==).+import Data.Array.Accelerate.Classes.Eq hiding ( (==) )+import qualified Data.Array.Accelerate.Classes.Eq as A++import Data.Char+import Language.Haskell.TH.Extra hiding ( Exp )+import Prelude ( ($), (>>=), Ordering(..), Num(..), Maybe(..), String, show, error, unlines, return, concat, map, mapM )+import Text.Printf+import qualified Prelude as P+++infix 4 <+infix 4 >+infix 4 <=+infix 4 >=++-- | The 'Ord' class for totally ordered datatypes+--+class Eq a => Ord a where+ {-# MINIMAL (<=) | compare #-}+ (<) :: Exp a -> Exp a -> Exp Bool+ (>) :: Exp a -> Exp a -> Exp Bool+ (<=) :: Exp a -> Exp a -> Exp Bool+ (>=) :: Exp a -> Exp a -> Exp Bool+ min :: Exp a -> Exp a -> Exp a+ max :: Exp a -> Exp a -> Exp a+ compare :: Exp a -> Exp a -> Exp Ordering++ x < y = if compare x y A.== constant LT then constant True else constant False+ x <= y = if compare x y A.== constant GT then constant False else constant True+ x > y = if compare x y A.== constant GT then constant True else constant False+ x >= y = if compare x y A.== constant LT then constant False else constant True++ min x y = if x <= y then x else y+ max x y = if x <= y then y else x++ compare x y =+ if x A.== y then constant EQ else+ if x <= y then constant LT+ else constant GT++-- Local redefinition for use with RebindableSyntax (pulled forward from Prelude.hs)+--+ifThenElse :: Elt a => Exp Bool -> Exp a -> Exp a -> Exp a+ifThenElse (Exp c) (Exp x) (Exp y) = Exp $ SmartExp $ Cond (mkCoerce' c) x y++instance Ord () where+ (<) _ _ = constant False+ (>) _ _ = constant False+ (>=) _ _ = constant True+ (<=) _ _ = constant True+ min _ _ = constant ()+ max _ _ = constant ()+ compare _ _ = constant EQ++instance Ord Z where+ (<) _ _ = constant False+ (>) _ _ = constant False+ (<=) _ _ = constant True+ (>=) _ _ = constant True+ min _ _ = constant Z+ max _ _ = constant Z+++-- Instances of 'Prelude.Ord' (mostly) don't make sense with the standard+-- signatures as the return type is fixed to 'Bool'. This instance is provided+-- to provide a useful error message.+--+-- Note that 'min' and 'max' are implementable, so we do hook those into the+-- accelerate instances defined here. This allows us to use operations such as+-- 'Prelude.minimum' and 'Prelude.maximum'.+--+instance Ord a => P.Ord (Exp a) where+ (<) = preludeError "Ord.(<)" "(<)"+ (<=) = preludeError "Ord.(<=)" "(<=)"+ (>) = preludeError "Ord.(>)" "(>)"+ (>=) = preludeError "Ord.(>=)" "(>=)"+ min = min+ max = max++preludeError :: String -> String -> a+preludeError x y+ = error+ $ unlines [ printf "Prelude.%s applied to EDSL types: use Data.Array.Accelerate.%s instead" x y+ , ""+ , "These Prelude.Ord instances are present only to fulfil superclass"+ , "constraints for subsequent classes in the standard Haskell numeric"+ , "hierarchy."+ ]++runQ $ do+ let+ integralTypes :: [Name]+ integralTypes =+ [ ''Int+ , ''Int8+ , ''Int16+ , ''Int32+ , ''Int64+ , ''Word+ , ''Word8+ , ''Word16+ , ''Word32+ , ''Word64+ ]++ floatingTypes :: [Name]+ floatingTypes =+ [ ''Half+ , ''Float+ , ''Double+ ]++ nonNumTypes :: [Name]+ nonNumTypes =+ [ ''Char+ ]++ cTypes :: [Name]+ cTypes =+ [ ''CInt+ , ''CUInt+ , ''CLong+ , ''CULong+ , ''CLLong+ , ''CULLong+ , ''CShort+ , ''CUShort+ , ''CChar+ , ''CUChar+ , ''CSChar+ , ''CFloat+ , ''CDouble+ ]++ mkPrim :: Name -> Q [Dec]+ mkPrim t =+ [d| instance Ord $(conT t) where+ (<) = mkLt+ (>) = mkGt+ (<=) = mkLtEq+ (>=) = mkGtEq+ min = mkMin+ max = mkMax+ |]++ mkLt' :: [ExpQ] -> [ExpQ] -> ExpQ+ mkLt' [x] [y] = [| $x < $y |]+ mkLt' (x:xs) (y:ys) = [| $x < $y || ( $x A.== $y && $(mkLt' xs ys) ) |]+ mkLt' _ _ = error "mkLt'"++ mkGt' :: [ExpQ] -> [ExpQ] -> ExpQ+ mkGt' [x] [y] = [| $x > $y |]+ mkGt' (x:xs) (y:ys) = [| $x > $y || ( $x A.== $y && $(mkGt' xs ys) ) |]+ mkGt' _ _ = error "mkGt'"++ mkLtEq' :: [ExpQ] -> [ExpQ] -> ExpQ+ mkLtEq' [x] [y] = [| $x < $y |]+ mkLtEq' (x:xs) (y:ys) = [| $x < $y || ( $x A.== $y && $(mkLtEq' xs ys) ) |]+ mkLtEq' _ _ = error "mkLtEq'"++ mkGtEq' :: [ExpQ] -> [ExpQ] -> ExpQ+ mkGtEq' [x] [y] = [| $x > $y |]+ mkGtEq' (x:xs) (y:ys) = [| $x > $y || ( $x A.== $y && $(mkGtEq' xs ys) ) |]+ mkGtEq' _ _ = error "mkGtEq'"++ mkTup :: Int -> Q [Dec]+ mkTup n =+ let+ xs = [ mkName ('x':show i) | i <- [0 .. n-1] ]+ ys = [ mkName ('y':show i) | i <- [0 .. n-1] ]+ cst = tupT (map (\x -> [t| Ord $(varT x) |]) xs)+ res = tupT (map varT xs)+ pat vs = conP (mkName ('T':show n)) (map varP vs)+ in+ [d| instance $cst => Ord $res where+ $(pat xs) < $(pat ys) = $( mkLt' (map varE xs) (map varE ys) )+ $(pat xs) > $(pat ys) = $( mkGt' (map varE xs) (map varE ys) )+ $(pat xs) >= $(pat ys) = $( mkGtEq' (map varE xs) (map varE ys) )+ $(pat xs) <= $(pat ys) = $( mkLtEq' (map varE xs) (map varE ys) )+ |]++ is <- mapM mkPrim integralTypes+ fs <- mapM mkPrim floatingTypes+ ns <- mapM mkPrim nonNumTypes+ cs <- mapM mkPrim cTypes+ ts <- mapM mkTup [2..16]+ return $ concat (concat [is,fs,ns,cs,ts])++instance Ord sh => Ord (sh :. Int) where+ x <= y = indexHead x <= indexHead y && indexTail x <= indexTail y+ x >= y = indexHead x >= indexHead y && indexTail x >= indexTail y+ x < y = indexHead x < indexHead y+ && case matchTypeR (eltR @sh) (eltR @Z) of+ Just Refl -> constant True+ Nothing -> indexTail x < indexTail y+ x > y = indexHead x > indexHead y+ && case matchTypeR (eltR @sh) (eltR @Z) of+ Just Refl -> constant True+ Nothing -> indexTail x > indexTail y++instance Ord Ordering where+ x < y = mkCoerce x < (mkCoerce y :: Exp TAG)+ x > y = mkCoerce x > (mkCoerce y :: Exp TAG)+ x <= y = mkCoerce x <= (mkCoerce y :: Exp TAG)+ x >= y = mkCoerce x >= (mkCoerce y :: Exp TAG)+ min x y = mkCoerce $ min (mkCoerce x) (mkCoerce y :: Exp TAG)+ max x y = mkCoerce $ max (mkCoerce x) (mkCoerce y :: Exp TAG)+
+ src/Data/Array/Accelerate/Classes/Rational.hs view
@@ -0,0 +1,98 @@+{-# LANGUAGE FlexibleContexts #-}+-- |+-- Module : Data.Array.Accelerate.Classes.Rational+-- Copyright : [2016..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Classes.Rational (++ Rational(..)++) where++import Data.Array.Accelerate.Data.Ratio+import Data.Array.Accelerate.Data.Bits++import Data.Array.Accelerate.Language+import Data.Array.Accelerate.Pattern+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.Classes.Eq+import Data.Array.Accelerate.Classes.FromIntegral+import Data.Array.Accelerate.Classes.Integral+import Data.Array.Accelerate.Classes.Num+import Data.Array.Accelerate.Classes.Ord+import Data.Array.Accelerate.Classes.RealFloat++import Prelude ( ($) )+++-- | Numbers which can be expressed as the quotient of two integers.+--+-- Accelerate does not have an arbitrary precision Integer type, however+-- fixed-length large integers are provide by the @accelerate-bignum@+-- package.+--+class (Num a, Ord a) => Rational a where+ -- | Convert a number to the quotient of two integers+ --+ toRational :: (FromIntegral Int64 b, Integral b) => Exp a -> Exp (Ratio b)++instance Rational Int where toRational = integralToRational+instance Rational Int8 where toRational = integralToRational+instance Rational Int16 where toRational = integralToRational+instance Rational Int32 where toRational = integralToRational+instance Rational Int64 where toRational = integralToRational+instance Rational Word where toRational = integralToRational+instance Rational Word8 where toRational = integralToRational+instance Rational Word16 where toRational = integralToRational+instance Rational Word32 where toRational = integralToRational+instance Rational Word64 where toRational = integralToRational++instance Rational Half where toRational = floatingToRational+instance Rational Float where toRational = floatingToRational+instance Rational Double where toRational = floatingToRational+++integralToRational+ :: (Integral a, Integral b, FromIntegral a Int64, FromIntegral Int64 b)+ => Exp a+ -> Exp (Ratio b)+integralToRational x = fromIntegral (fromIntegral x :: Exp Int64) :% 1++floatingToRational+ :: (RealFloat a, Integral b, FromIntegral Int64 b)+ => Exp a+ -> Exp (Ratio b)+floatingToRational x = fromIntegral u :% fromIntegral v+ where+ (m, e) = decodeFloat x+ (n, d) = elimZeros m (negate e)+ u :% v = cond (e >= 0) ((m `shiftL` e) :% 1) $+ cond (m .&. 1 == 0) (n :% shiftL 1 d) $+ (m :% shiftL 1 (negate e))++-- Stolen from GHC.Float.ConversionUtils+-- Double mantissa have 53 bits, which fits in an Int64+--+elimZeros :: Exp Int64 -> Exp Int -> (Exp Int64, Exp Int)+elimZeros x y = (u, v)+ where+ T3 _ u v = while (\(T3 p _ _) -> p) elim (T3 moar x y)+ kthxbai = constant False+ moar = constant True++ elim :: Exp (Bool, Int64, Int) -> Exp (Bool, Int64, Int)+ elim (T3 _ n e) =+ let t = countTrailingZeros (fromIntegral n :: Exp Word8)+ in+ cond (e <= t) (T3 kthxbai (shiftR n e) 0) $+ cond (t < 8) (T3 kthxbai (shiftR n t) (e-t)) $+ (T3 moar (shiftR n 8) (e-8))+
+ src/Data/Array/Accelerate/Classes/Real.hs view
@@ -0,0 +1,48 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MonoLocalBinds #-}+{-# LANGUAGE UndecidableInstances #-}+{-# OPTIONS_GHC -fno-warn-missing-methods #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- |+-- Module : Data.Array.Accelerate.Classes.Real+-- Copyright : [2016..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Classes.Real (++ Real,++) where++import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Classes.Num+import Data.Array.Accelerate.Classes.Ord++import Prelude hiding ( Real, Num, Ord )+import qualified Prelude as P+++type Real a = (Num a, Ord a, P.Real (Exp a))++-- Instances of 'Real' don't make sense in Accelerate at the moment. These are+-- only provided to fulfil superclass constraints; e.g. Integral.+--+-- We won't need `toRational' until we support rational numbers in AP+-- computations.+--+instance (Num a, Ord a) => P.Real (Exp a) where+ toRational+ = error+ $ unlines [ "Prelude.toRational is not supported for Accelerate types"+ , ""+ , "These Prelude.Real instances are present only to fulfil superclass"+ , "constraints for subsequent classes in the standard Haskell numeric hierarchy."+ ]+
+ src/Data/Array/Accelerate/Classes/RealFloat.hs view
@@ -0,0 +1,411 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE ViewPatterns #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- |+-- Module : Data.Array.Accelerate.Classes.RealFloat+-- Copyright : [2016..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Classes.RealFloat (++ RealFloat(..),++) where++import Data.Array.Accelerate.Error+import Data.Array.Accelerate.Language ( cond, while )+import Data.Array.Accelerate.Pattern+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.Data.Bits++import Data.Array.Accelerate.Classes.Eq+import Data.Array.Accelerate.Classes.Floating+import Data.Array.Accelerate.Classes.FromIntegral+import Data.Array.Accelerate.Classes.Num+import Data.Array.Accelerate.Classes.Ord+import Data.Array.Accelerate.Classes.RealFrac++import Data.Text.Lazy.Builder+import Formatting+import Text.Printf+import Prelude ( (.), ($), String, error, undefined, unlines, otherwise )+import qualified Prelude as P+++-- | Efficient, machine-independent access to the components of a floating-point+-- number+--+class (RealFrac a, Floating a) => RealFloat a where+ -- | The radix of the representation (often 2) (constant)+ floatRadix :: Exp a -> Exp Int64 -- Integer+ default floatRadix :: P.RealFloat a => Exp a -> Exp Int64+ floatRadix _ = P.fromInteger (P.floatRadix (undefined::a))++ -- | The number of digits of 'floatRadix' in the significand (constant)+ floatDigits :: Exp a -> Exp Int+ default floatDigits :: P.RealFloat a => Exp a -> Exp Int+ floatDigits _ = constant (P.floatDigits (undefined::a))++ -- | The lowest and highest values the exponent may assume (constant)+ floatRange :: Exp a -> (Exp Int, Exp Int)+ default floatRange :: P.RealFloat a => Exp a -> (Exp Int, Exp Int)+ floatRange _ = let (m,n) = P.floatRange (undefined::a)+ in (constant m, constant n)++ -- | Return the significand and an appropriately scaled exponent. If+ -- @(m,n) = 'decodeFloat' x@ then @x = m*b^^n@, where @b@ is the+ -- floating-point radix ('floatRadix'). Furthermore, either @m@ and @n@ are+ -- both zero, or @b^(d-1) <= 'abs' m < b^d@, where @d = 'floatDigits' x@.+ decodeFloat :: Exp a -> (Exp Int64, Exp Int) -- Integer++ -- | Inverse of 'decodeFloat'+ encodeFloat :: Exp Int64 -> Exp Int -> Exp a -- Integer+ default encodeFloat :: (FromIntegral Int a, FromIntegral Int64 a) => Exp Int64 -> Exp Int -> Exp a+ encodeFloat x e = fromIntegral x * (fromIntegral (floatRadix (undefined :: Exp a)) ** fromIntegral e)++ -- | Corresponds to the second component of 'decodeFloat'+ exponent :: Exp a -> Exp Int+ exponent x = let (m,n) = decodeFloat x+ in cond (m == 0)+ 0+ (n + floatDigits x)++ -- | Corresponds to the first component of 'decodeFloat'+ significand :: Exp a -> Exp a+ significand x = let (m,_) = decodeFloat x+ in encodeFloat m (negate (floatDigits x))++ -- | Multiply a floating point number by an integer power of the radix+ scaleFloat :: Exp Int -> Exp a -> Exp a+ scaleFloat k x =+ cond (k == 0 || isFix) x+ $ encodeFloat m (n + clamp b)+ where+ isFix = x == 0 || isNaN x || isInfinite x+ (m,n) = decodeFloat x+ (l,h) = floatRange x+ d = floatDigits x+ b = h - l + 4*d+ -- n+k may overflow, which would lead to incorrect results, hence we clamp+ -- the scaling parameter. If (n+k) would be larger than h, (n + clamp b k)+ -- must be too, similar for smaller than (l-d).+ clamp bd = max (-bd) (min bd k)++ -- | 'True' if the argument is an IEEE \"not-a-number\" (NaN) value+ isNaN :: Exp a -> Exp Bool++ -- | 'True' if the argument is an IEEE infinity or negative-infinity+ isInfinite :: Exp a -> Exp Bool++ -- | 'True' if the argument is too small to be represented in normalized+ -- format+ isDenormalized :: Exp a -> Exp Bool++ -- | 'True' if the argument is an IEEE negative zero+ isNegativeZero :: Exp a -> Exp Bool++ -- | 'True' if the argument is an IEEE floating point number+ isIEEE :: Exp a -> Exp Bool+ default isIEEE :: P.RealFloat a => Exp a -> Exp Bool+ isIEEE _ = constant (P.isIEEE (undefined::a))++ -- | A version of arctangent taking two real floating-point arguments.+ -- For real floating @x@ and @y@, @'atan2' y x@ computes the angle (from the+ -- positive x-axis) of the vector from the origin to the point @(x,y)@.+ -- @'atan2' y x@ returns a value in the range [@-pi@, @pi@].+ atan2 :: Exp a -> Exp a -> Exp a+++instance RealFloat Half where+ atan2 = mkAtan2+ isNaN = mkIsNaN+ isInfinite = mkIsInfinite+ isDenormalized = ieee754 "isDenormalized" (ieee754_f16_is_denormalized . mkBitcast)+ isNegativeZero = ieee754 "isNegativeZero" (ieee754_f16_is_negative_zero . mkBitcast)+ decodeFloat = ieee754 "decodeFloat" (\x -> let T2 m n = ieee754_f16_decode (mkBitcast x)+ in (fromIntegral m, n))++instance RealFloat Float where+ atan2 = mkAtan2+ isNaN = mkIsNaN+ isInfinite = mkIsInfinite+ isDenormalized = ieee754 "isDenormalized" (ieee754_f32_is_denormalized . mkBitcast)+ isNegativeZero = ieee754 "isNegativeZero" (ieee754_f32_is_negative_zero . mkBitcast)+ decodeFloat = ieee754 "decodeFloat" (\x -> let T2 m n = ieee754_f32_decode (mkBitcast x)+ in (fromIntegral m, n))++instance RealFloat Double where+ atan2 = mkAtan2+ isNaN = mkIsNaN+ isInfinite = mkIsInfinite+ isDenormalized = ieee754 "isDenormalized" (ieee754_f64_is_denormalized . mkBitcast)+ isNegativeZero = ieee754 "isNegativeZero" (ieee754_f64_is_negative_zero . mkBitcast)+ decodeFloat = ieee754 "decodeFloat" (\x -> let T2 m n = ieee754_f64_decode (mkBitcast x)+ in (m, n))++instance RealFloat CFloat where+ atan2 = mkAtan2+ isNaN = mkIsNaN . mkBitcast @Float+ isInfinite = mkIsInfinite . mkBitcast @Float+ isDenormalized = ieee754 "isDenormalized" (ieee754_f32_is_denormalized . mkBitcast)+ isNegativeZero = ieee754 "isNegativeZero" (ieee754_f32_is_negative_zero . mkBitcast)+ decodeFloat = ieee754 "decodeFloat" (\x -> let T2 m n = ieee754_f32_decode (mkBitcast x)+ in (fromIntegral m, n))+ encodeFloat x e = mkBitcast (encodeFloat @Float x e)++instance RealFloat CDouble where+ atan2 = mkAtan2+ isNaN = mkIsNaN . mkBitcast @Double+ isInfinite = mkIsInfinite . mkBitcast @Double+ isDenormalized = ieee754 "isDenormalized" (ieee754_f64_is_denormalized . mkBitcast)+ isNegativeZero = ieee754 "isNegativeZero" (ieee754_f64_is_negative_zero . mkBitcast)+ decodeFloat = ieee754 "decodeFloat" (\x -> let T2 m n = ieee754_f64_decode (mkBitcast x)+ in (m, n))+ encodeFloat x e = mkBitcast (encodeFloat @Double x e)+++-- To satisfy superclass constraints+--+instance RealFloat a => P.RealFloat (Exp a) where+ floatRadix = preludeError "floatRadix"+ floatDigits = preludeError "floatDigits"+ floatRange = preludeError "floatRange"+ decodeFloat = preludeError "decodeFloat"+ encodeFloat = preludeError "encodeFloat"+ isNaN = preludeError "isNaN"+ isInfinite = preludeError "isInfinite"+ isDenormalized = preludeError "isDenormalized"+ isNegativeZero = preludeError "isNegativeZero"+ isIEEE = preludeError "isIEEE"++preludeError :: String -> a+preludeError x+ = error+ $ unlines [ printf "Prelude.%s applied to EDSL types: use Data.Array.Accelerate.%s instead" x x+ , ""+ , "These Prelude.RealFloat instances are present only to fulfil superclass"+ , "constraints for subsequent classes in the standard Haskell numeric hierarchy."+ ]+++ieee754 :: forall a b. HasCallStack => P.RealFloat a => Builder -> (Exp a -> b) -> Exp a -> b+ieee754 name f x+ | P.isIEEE (undefined::a) = f x+ | otherwise = internalError (builder % ": Not implemented for non-IEEE floating point") name++-- From: ghc/libraries/base/cbits/primFloat.c+-- ------------------------------------------++-- An IEEE754 number is denormalised iff:+-- * exponent is zero+-- * mantissa is non-zero.+-- * (don't care about setting of sign bit.)+--+ieee754_f64_is_denormalized :: Exp Word64 -> Exp Bool+ieee754_f64_is_denormalized x =+ ieee754_f64_mantissa x == 0 &&+ ieee754_f64_exponent x /= 0++ieee754_f32_is_denormalized :: Exp Word32 -> Exp Bool+ieee754_f32_is_denormalized x =+ ieee754_f32_mantissa x == 0 &&+ ieee754_f32_exponent x /= 0++ieee754_f16_is_denormalized :: Exp Word16 -> Exp Bool+ieee754_f16_is_denormalized x =+ ieee754_f16_mantissa x == 0 &&+ ieee754_f16_exponent x /= 0++-- Negative zero if only the sign bit is set+--+ieee754_f64_is_negative_zero :: Exp Word64 -> Exp Bool+ieee754_f64_is_negative_zero x =+ ieee754_f64_negative x &&+ ieee754_f64_exponent x == 0 &&+ ieee754_f64_mantissa x == 0++ieee754_f32_is_negative_zero :: Exp Word32 -> Exp Bool+ieee754_f32_is_negative_zero x =+ ieee754_f32_negative x &&+ ieee754_f32_exponent x == 0 &&+ ieee754_f32_mantissa x == 0++ieee754_f16_is_negative_zero :: Exp Word16 -> Exp Bool+ieee754_f16_is_negative_zero x =+ ieee754_f16_negative x &&+ ieee754_f16_exponent x == 0 &&+ ieee754_f16_mantissa x == 0+++-- Assume the host processor stores integers and floating point numbers in the+-- same endianness (true for modern processors).+--+-- To recap, here's the representation of a double precision+-- IEEE floating point number:+--+-- sign 63 sign bit (0==positive, 1==negative)+-- exponent 62-52 exponent (biased by 1023)+-- fraction 51-0 fraction (bits to right of binary point)+--+ieee754_f64_mantissa :: Exp Word64 -> Exp Word64+ieee754_f64_mantissa x = x .&. 0xFFFFFFFFFFFFF++ieee754_f64_exponent :: Exp Word64 -> Exp Word16+ieee754_f64_exponent x = fromIntegral (x `unsafeShiftR` 52) .&. 0x7FF++ieee754_f64_negative :: Exp Word64 -> Exp Bool+ieee754_f64_negative x = testBit x 63++-- Representation of single precision IEEE floating point number:+--+-- sign 31 sign bit (0==positive, 1==negative)+-- exponent 30-23 exponent (biased by 127)+-- fraction 22-0 fraction (bits to right of binary point)+--+ieee754_f32_mantissa :: Exp Word32 -> Exp Word32+ieee754_f32_mantissa x = x .&. 0x7FFFFF++ieee754_f32_exponent :: Exp Word32 -> Exp Word8+ieee754_f32_exponent x = fromIntegral (x `unsafeShiftR` 23)++ieee754_f32_negative :: Exp Word32 -> Exp Bool+ieee754_f32_negative x = testBit x 31++-- Representation of half precision IEEE floating point number:+--+-- sign 15 sign bit (0==positive, 1==negative)+-- exponent 14-10 exponent (biased by 15)+-- fraction 9-0 fraction (bits to right of binary point)+--+ieee754_f16_mantissa :: Exp Word16 -> Exp Word16+ieee754_f16_mantissa x = x .&. 0x3FF++ieee754_f16_exponent :: Exp Word16 -> Exp Word8+ieee754_f16_exponent x = fromIntegral (x `unsafeShiftR` 10) .&. 0x1F++ieee754_f16_negative :: Exp Word16 -> Exp Bool+ieee754_f16_negative x = testBit x 15+++-- reverse engineered following the below++ieee754_f16_decode :: Exp Word16 -> Exp (Int16, Int)+ieee754_f16_decode i =+ let+ _HHIGHBIT = 0x0400+ _HMSBIT = 0x8000+ _HMINEXP = ((_HALF_MIN_EXP) - (_HALF_MANT_DIG) - 1)+ _HALF_MANT_DIG = floatDigits (undefined::Exp Half)+ (_HALF_MIN_EXP, _HALF_MAX_EXP) = floatRange (undefined::Exp Half)++ high1 = fromIntegral i+ high2 = high1 .&. (_HHIGHBIT - 1)++ exp1 = ((fromIntegral high1 `unsafeShiftR` 10) .&. 0x1F) + _HMINEXP+ exp2 = exp1 + 1++ T2 high3 exp3+ = cond (exp1 /= _HMINEXP)+ -- don't add hidden bit to denorms+ (T2 (high2 .|. _HHIGHBIT) exp1)+ -- a denorm, normalise the mantissa+ (while (\(T2 h _) -> (h .&. _HHIGHBIT) /= 0 )+ (\(T2 h e) -> T2 (h `unsafeShiftL` 1) (e-1))+ (T2 high2 exp2))++ high4 = cond (fromIntegral i < (0 :: Exp Int16)) (-high3) high3+ in+ cond (high1 .&. complement _HMSBIT == 0)+ (T2 0 0)+ (T2 high4 exp3)+++-- From: ghc/rts/StgPrimFloat.c+-- ----------------------------++ieee754_f32_decode :: Exp Word32 -> Exp (Int32, Int)+ieee754_f32_decode i =+ let+ _FHIGHBIT = 0x00800000+ _FMSBIT = 0x80000000+ _FMINEXP = ((_FLT_MIN_EXP) - (_FLT_MANT_DIG) - 1)+ _FLT_MANT_DIG = floatDigits (undefined::Exp Float)+ (_FLT_MIN_EXP, _FLT_MAX_EXP) = floatRange (undefined::Exp Float)++ high1 = fromIntegral i+ high2 = high1 .&. (_FHIGHBIT - 1)++ exp1 = ((fromIntegral high1 `unsafeShiftR` 23) .&. 0xFF) + _FMINEXP+ exp2 = exp1 + 1++ T2 high3 exp3+ = cond (exp1 /= _FMINEXP)+ -- don't add hidden bit to denorms+ (T2 (high2 .|. _FHIGHBIT) exp1)+ -- a denorm, normalise the mantissa+ (while (\(T2 h _) -> (h .&. _FHIGHBIT) /= 0 )+ (\(T2 h e) -> T2 (h `unsafeShiftL` 1) (e-1))+ (T2 high2 exp2))++ high4 = cond (fromIntegral i < (0 :: Exp Int32)) (-high3) high3+ in+ cond (high1 .&. complement _FMSBIT == 0)+ (T2 0 0)+ (T2 high4 exp3)+++ieee754_f64_decode :: Exp Word64 -> Exp (Int64, Int)+ieee754_f64_decode i =+ let T4 s h l e = ieee754_f64_decode2 i+ in T2 (fromIntegral s * (fromIntegral h `unsafeShiftL` 32 .|. fromIntegral l)) e++ieee754_f64_decode2 :: Exp Word64 -> Exp (Int, Word32, Word32, Int)+ieee754_f64_decode2 i =+ let+ _DHIGHBIT = 0x00100000+ _DMSBIT = 0x80000000+ _DMINEXP = ((_DBL_MIN_EXP) - (_DBL_MANT_DIG) - 1)+ _DBL_MANT_DIG = floatDigits (undefined::Exp Double)+ (_DBL_MIN_EXP, _DBL_MAX_EXP) = floatRange (undefined::Exp Double)++ low = fromIntegral i+ high = fromIntegral (i `unsafeShiftR` 32)++ iexp = (fromIntegral ((high `unsafeShiftR` 20) .&. 0x7FF) + _DMINEXP)+ sign = cond (fromIntegral i < (0 :: Exp Int64)) (-1) 1++ high2 = high .&. (_DHIGHBIT - 1)+ iexp2 = iexp + 1++ T3 hi lo ie+ = cond (iexp2 /= _DMINEXP)+ -- don't add hidden bit to denorms+ (T3 (high2 .|. _DHIGHBIT) low iexp)+ -- a denorm, nermalise the mantissa+ (while (\(T3 h _ _) -> (h .&. _DHIGHBIT) /= 0)+ (\(T3 h l e) ->+ let h1 = h `unsafeShiftL` 1+ h2 = cond ((l .&. _DMSBIT) /= 0) (h1+1) h1+ in T3 h2 (l `unsafeShiftL` 1) (e-1))+ (T3 high2 low iexp2))++ in+ cond (low == 0 && (high .&. (complement _DMSBIT)) == 0)+ (T4 1 0 0 0)+ (T4 sign hi lo ie)+
+ src/Data/Array/Accelerate/Classes/RealFloat.hs-boot view
@@ -0,0 +1,67 @@+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE FlexibleContexts #-}+-- |+-- Module : Data.Array.Accelerate.Classes.RealFloat+-- Copyright : [2019..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Classes.RealFloat+ where++import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.Classes.Floating+import Data.Array.Accelerate.Classes.FromIntegral+import {-# SOURCE #-} Data.Array.Accelerate.Classes.RealFrac++import Prelude ( Bool )+import qualified Prelude as P+++class (RealFrac a, Floating a) => RealFloat a where+ floatRadix :: Exp a -> Exp Int64 -- Integer+ floatDigits :: Exp a -> Exp Int+ floatRange :: Exp a -> (Exp Int, Exp Int)+ decodeFloat :: Exp a -> (Exp Int64, Exp Int) -- Integer+ encodeFloat :: Exp Int64 -> Exp Int -> Exp a -- Integer+ exponent :: Exp a -> Exp Int+ significand :: Exp a -> Exp a+ scaleFloat :: Exp Int -> Exp a -> Exp a+ isNaN :: Exp a -> Exp Bool+ isInfinite :: Exp a -> Exp Bool+ isDenormalized :: Exp a -> Exp Bool+ isNegativeZero :: Exp a -> Exp Bool+ isIEEE :: Exp a -> Exp Bool+ atan2 :: Exp a -> Exp a -> Exp a++ exponent = P.undefined+ significand = P.undefined+ scaleFloat = P.undefined++ default floatRadix :: P.RealFloat a => Exp a -> Exp Int64+ floatRadix _ = P.undefined++ default floatDigits :: P.RealFloat a => Exp a -> Exp Int+ floatDigits _ = P.undefined++ default floatRange :: P.RealFloat a => Exp a -> (Exp Int, Exp Int)+ floatRange _ = P.undefined++ default encodeFloat :: (FromIntegral Int a, FromIntegral Int64 a) => Exp Int64 -> Exp Int -> Exp a+ encodeFloat _ _ = P.undefined++ default isIEEE :: P.RealFloat a => Exp a -> Exp Bool+ isIEEE _ = P.undefined++instance RealFloat Half+instance RealFloat Float+instance RealFloat Double+instance RealFloat CFloat+instance RealFloat CDouble+
+ src/Data/Array/Accelerate/Classes/RealFrac.hs view
@@ -0,0 +1,278 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- |+-- Module : Data.Array.Accelerate.Classes.RealFrac+-- Copyright : [2016..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Classes.RealFrac (++ RealFrac(..),+ div', mod', divMod',++) where++import Data.Array.Accelerate.Language ( (^), cond, even )+import Data.Array.Accelerate.Lift ( unlift )+import Data.Array.Accelerate.Pattern+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.Classes.Eq+import Data.Array.Accelerate.Classes.Ord+import Data.Array.Accelerate.Classes.Floating+import Data.Array.Accelerate.Classes.Fractional+import Data.Array.Accelerate.Classes.FromIntegral+import Data.Array.Accelerate.Classes.Integral+import Data.Array.Accelerate.Classes.Num+import Data.Array.Accelerate.Classes.ToFloating+import {-# SOURCE #-} Data.Array.Accelerate.Classes.RealFloat -- defaultProperFraction++import Data.Maybe+import Text.Printf+import Prelude ( ($), String, error, unlines, otherwise )+import qualified Prelude as P+++-- | Generalisation of 'P.div' to any instance of 'RealFrac'+--+div' :: (RealFrac a, FromIntegral Int64 b, Integral b) => Exp a -> Exp a -> Exp b+div' n d = floor (n / d)++-- | Generalisation of 'P.mod' to any instance of 'RealFrac'+--+mod' :: (Floating a, RealFrac a, ToFloating Int64 a) => Exp a -> Exp a -> Exp a+mod' n d = n - (toFloating f) * d+ where+ f :: Exp Int64+ f = div' n d++-- | Generalisation of 'P.divMod' to any instance of 'RealFrac'+--+divMod'+ :: (Floating a, RealFrac a, Integral b, FromIntegral Int64 b, ToFloating b a)+ => Exp a+ -> Exp a+ -> (Exp b, Exp a)+divMod' n d = (f, n - (toFloating f) * d)+ where+ f = div' n d+++-- | Extracting components of fractions.+--+class (Ord a, Fractional a) => RealFrac a where+ -- | The function 'properFraction' takes a real fractional number @x@ and+ -- returns a pair @(n,f)@ such that @x = n+f@, and:+ --+ -- * @n@ is an integral number with the same sign as @x@; and+ --+ -- * @f@ is a fraction with the same type and sign as @x@,+ -- and with absolute value less than @1@.+ --+ -- The default definitions of the 'ceiling', 'floor', 'truncate'+ -- and 'round' functions are in terms of 'properFraction'.+ properFraction :: (Integral b, FromIntegral Int64 b) => Exp a -> (Exp b, Exp a)++ -- The function 'splitFraction' takes a real fractional number @x@ and+ -- returns a pair @(n,f)@ such that @x = n+f@, and:+ --+ -- * @n@ is an integral number with the same sign as @x@; and+ --+ -- * @f@ is a fraction with the same type as @x@ in the range [0,1). Note that+ -- this differs from 'Prelude.properFraction'.+ --+ -- splitFraction :: (Elt b, IsIntegral b) => Exp a -> (Exp b, Exp a)++ -- @fraction x@ returns @x@ with the integer part removed.+ -- fraction :: Exp a -> Exp a++ -- properFraction is part of the standard Haskell'98 RealFrac type classes+ -- splitFraction / fraction are from numeric-prelude Algebra.RealRing++ -- | @truncate x@ returns the integer nearest @x@ between zero and @x@+ truncate :: (Integral b, FromIntegral Int64 b) => Exp a -> Exp b+ truncate = defaultTruncate++ -- | @'round' x@ returns the nearest integer to @x@; the even integer if @x@+ -- is equidistant between two integers+ round :: (Integral b, FromIntegral Int64 b) => Exp a -> Exp b+ round = defaultRound++ -- | @'ceiling' x@ returns the least integer not less than @x@+ ceiling :: (Integral b, FromIntegral Int64 b) => Exp a -> Exp b+ ceiling = defaultCeiling++ -- | @'floor' x@ returns the greatest integer not greater than @x@+ floor :: (Integral b, FromIntegral Int64 b) => Exp a -> Exp b+ floor = defaultFloor++instance RealFrac Half where+ properFraction = defaultProperFraction++instance RealFrac Float where+ properFraction = defaultProperFraction++instance RealFrac Double where+ properFraction = defaultProperFraction++instance RealFrac CFloat where+ properFraction = defaultProperFraction+ truncate = defaultTruncate+ round = defaultRound+ ceiling = defaultCeiling+ floor = defaultFloor++instance RealFrac CDouble where+ properFraction = defaultProperFraction+ truncate = defaultTruncate+ round = defaultRound+ ceiling = defaultCeiling+ floor = defaultFloor+++-- Must test for ±0.0 to avoid returning -0.0 in the second component of the+-- pair. Unfortunately the branching costs a lot of performance.+--+-- defaultProperFraction+-- :: (ToFloating b a, RealFrac a, IsIntegral b, Num b, Floating a)+-- => Exp a+-- -> (Exp b, Exp a)+-- defaultProperFraction x =+-- unlift $ Exp+-- $ Cond (x == 0) (tup2 (0, 0))+-- (tup2 (n, f))+-- where+-- n = truncate x+-- f = x - toFloating n++defaultProperFraction+ :: (RealFloat a, FromIntegral Int64 b, Integral b)+ => Exp a+ -> (Exp b, Exp a)+defaultProperFraction x+ = unlift+ $ cond (n >= 0)+ (T2 (fromIntegral m * (2 ^ n)) 0.0)+ (T2 (fromIntegral q) (encodeFloat r n))+ where+ (m, n) = decodeFloat x+ (q, r) = quotRem m (2 ^ (negate n))++defaultTruncate :: forall a b. (RealFrac a, Integral b, FromIntegral Int64 b) => Exp a -> Exp b+defaultTruncate x+ | Just IsFloatingDict <- isFloating @a+ , Just IsIntegralDict <- isIntegral @b+ = mkTruncate x+ --+ | otherwise+ = let (n, _) = properFraction x in n++defaultCeiling :: forall a b. (RealFrac a, Integral b, FromIntegral Int64 b) => Exp a -> Exp b+defaultCeiling x+ | Just IsFloatingDict <- isFloating @a+ , Just IsIntegralDict <- isIntegral @b+ = mkCeiling x+ --+ | otherwise+ = let (n, r) = properFraction x in cond (r > 0) (n+1) n++defaultFloor :: forall a b. (RealFrac a, Integral b, FromIntegral Int64 b) => Exp a -> Exp b+defaultFloor x+ | Just IsFloatingDict <- isFloating @a+ , Just IsIntegralDict <- isIntegral @b+ = mkFloor x+ --+ | otherwise+ = let (n, r) = properFraction x in cond (r < 0) (n-1) n++defaultRound :: forall a b. (RealFrac a, Integral b, FromIntegral Int64 b) => Exp a -> Exp b+defaultRound x+ | Just IsFloatingDict <- isFloating @a+ , Just IsIntegralDict <- isIntegral @b+ = mkRound x+ --+ | otherwise+ = let (n, r) = properFraction x+ m = cond (r < 0.0) (n-1) (n+1)+ half_down = abs r - 0.5+ p = compare half_down 0.0+ in+ cond (constant LT == p) n $+ cond (constant EQ == p) (cond (even n) n m) $+ {- otherwise -} m+++data IsFloatingDict a where+ IsFloatingDict :: IsFloating a => IsFloatingDict a++data IsIntegralDict a where+ IsIntegralDict :: IsIntegral a => IsIntegralDict a++isFloating :: forall a. Elt a => Maybe (IsFloatingDict (EltR a))+isFloating+ | TupRsingle t <- eltR @a+ , SingleScalarType s <- t+ , NumSingleType n <- s+ , FloatingNumType f <- n+ = case f of+ TypeHalf{} -> Just IsFloatingDict+ TypeFloat{} -> Just IsFloatingDict+ TypeDouble{} -> Just IsFloatingDict+ --+ | otherwise+ = Nothing++isIntegral :: forall a. Elt a => Maybe (IsIntegralDict (EltR a))+isIntegral+ | TupRsingle t <- eltR @a+ , SingleScalarType s <- t+ , NumSingleType n <- s+ , IntegralNumType i <- n+ = case i of+ TypeInt{} -> Just IsIntegralDict+ TypeInt8{} -> Just IsIntegralDict+ TypeInt16{} -> Just IsIntegralDict+ TypeInt32{} -> Just IsIntegralDict+ TypeInt64{} -> Just IsIntegralDict+ TypeWord{} -> Just IsIntegralDict+ TypeWord8{} -> Just IsIntegralDict+ TypeWord16{} -> Just IsIntegralDict+ TypeWord32{} -> Just IsIntegralDict+ TypeWord64{} -> Just IsIntegralDict+ --+ | otherwise+ = Nothing+++-- To satisfy superclass constraints+--+instance RealFrac a => P.RealFrac (Exp a) where+ properFraction = preludeError "properFraction"+ truncate = preludeError "truncate"+ round = preludeError "round"+ ceiling = preludeError "ceiling"+ floor = preludeError "floor"++preludeError :: String -> a+preludeError x+ = error+ $ unlines [ printf "Prelude.%s applied to EDSL types: use Data.Array.Accelerate.%s instead" x x+ , ""+ , "These Prelude.RealFrac instances are present only to fulfil superclass"+ , "constraints for subsequent classes in the standard Haskell numeric hierarchy."+ ]+
+ src/Data/Array/Accelerate/Classes/RealFrac.hs-boot view
@@ -0,0 +1,43 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE NoImplicitPrelude #-}+-- |+-- Module : Data.Array.Accelerate.Classes.RealFrac+-- Copyright : [2019..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Classes.RealFrac+ where++import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.Classes.Fractional+import Data.Array.Accelerate.Classes.FromIntegral+import Data.Array.Accelerate.Classes.Integral+import Data.Array.Accelerate.Classes.Ord++import qualified Prelude as P++class (Ord a, Fractional a) => RealFrac a where+ properFraction :: (Integral b, FromIntegral Int64 b) => Exp a -> (Exp b, Exp a)+ truncate :: (Integral b, FromIntegral Int64 b) => Exp a -> Exp b+ round :: (Integral b, FromIntegral Int64 b) => Exp a -> Exp b+ ceiling :: (Integral b, FromIntegral Int64 b) => Exp a -> Exp b+ floor :: (Integral b, FromIntegral Int64 b) => Exp a -> Exp b++ truncate = P.undefined+ round = P.undefined+ ceiling = P.undefined+ floor = P.undefined++instance RealFrac Half+instance RealFrac Float+instance RealFrac Double+instance RealFrac CFloat+instance RealFrac CDouble+
+ src/Data/Array/Accelerate/Classes/ToFloating.hs view
@@ -0,0 +1,80 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TemplateHaskell #-}+-- |+-- Module : Data.Array.Accelerate.Classes.ToFloating+-- Copyright : [2016..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Classes.ToFloating (++ ToFloating(..),++) where++import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.Classes.Floating+import Data.Array.Accelerate.Classes.Num++import Language.Haskell.TH hiding ( Exp )+import Control.Monad+import Prelude hiding ( Num, Floating )+++-- | Accelerate lacks an arbitrary-precision 'Prelude.Rational' type, which the+-- standard 'Prelude.realToFrac' uses as an intermediate value when coercing+-- to floating-point types. Instead, we use this class to capture a direct+-- coercion between two types.+--+class ToFloating a b where+ -- | General coercion to floating types+ toFloating :: (Num a, Floating b) => Exp a -> Exp b++-- instance (Elt a, Elt b, IsNum a, IsFloating b) => ToFloating a b where+-- toFloating = mkToFloating++-- Generate standard instances explicitly. See also: 'FromIntegral'.+--+$(runQ $ do+ let+ -- Get all the types that our dictionaries reify+ digItOut :: Name -> Q [Name]+ digItOut name = do+ TyConI (DataD _ _ _ _ cons _) <- reify name+ let+ -- This is what a constructor such as IntegralNumType will be reified+ -- as prior to GHC 8.4...+ dig (NormalC _ [(_, AppT (ConT n) (VarT _))]) = digItOut n+ -- ...but this is what IntegralNumType will be reified as on GHC 8.4+ -- and later, after the changes described in+ -- https://ghc.haskell.org/trac/ghc/wiki/Migration/8.4#TemplateHaskellreificationchangesforGADTs+ dig (ForallC _ _ (GadtC _ [(_, AppT (ConT n) (VarT _))] _)) = digItOut n+ dig (GadtC _ _ (AppT (ConT _) (ConT n))) = return [n]+ dig _ = error "Unexpected case generating ToFloating instances"+ --+ concat `fmap` mapM dig cons++ thToFloating :: Name -> Name -> Q Dec+ thToFloating a b =+ let+ ty = AppT (AppT (ConT (mkName "ToFloating")) (ConT a)) (ConT b)+ dec = ValD (VarP (mkName "toFloating")) (NormalB (VarE (mkName f))) []+ f | a == b = "id"+ | otherwise = "mkToFloating"+ in+ instanceD (return []) (return ty) [return dec]+ --+ as <- digItOut ''NumType+ bs <- digItOut ''FloatingType+ sequence [ thToFloating a b | a <- as, b <- bs ]+ )+
+ src/Data/Array/Accelerate/Control/Monad.hs view
@@ -0,0 +1,221 @@+{-# LANGUAGE RebindableSyntax #-}+-- |+-- Module : Data.Array.Accelerate.Control.Monad+-- Copyright : [2018..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- A monad sequences actions over a parametrised type.+--+-- This is essentially the same as the standard Haskell 'Control.Monad' class,+-- lifted to Accelerate 'Exp' terms.+--+-- @since 1.4.0.0+--++module Data.Array.Accelerate.Control.Monad (++ -- * Monad class+ Monad(..),++ -- * Functions+ -- ** Basic functions+ (=<<), (>>),+ (>=>), (<=<),++ -- ** Conditional execution of monadic expressions+ when, unless,++ -- ** Monadic lifting operations+ liftM, liftM2, liftM3, liftM4, liftM5,++) where++import Data.Array.Accelerate.Data.Functor+import Data.Array.Accelerate.Language++import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Smart++import Prelude ( Bool, flip )+++-- | The 'Monad' class is used for scalar types which can be sequenced.+-- Instances of 'Monad' should satisfy the following laws:+--+-- [Left identity] @'return' a '>>=' k = k a@+-- [Right identity] @m '>>=' 'return' = m@+-- [Associativity] @m '>>=' (\\x -> k x '>>=' h) = (m '>>=' k) '>>=' h@+--+-- Furthermore, the 'Monad' and 'Functor' operations should relate as follows:+-- * @'fmap' f xs = xs '>>=' 'return' . f@+--+class Functor m => Monad m where+ -- | Sequentially compose two actions, passing any value produced+ -- by the first as an argument to the second.+ --+ -- \'@as '>>=' bs@\' can be understood as the @do@ expression+ --+ -- @+ -- do a <- as+ -- bs a+ -- @+ --+ infixl 1 >>=+ (>>=) :: (Elt a, Elt b, Elt (m a), Elt (m b))+ => Exp (m a)+ -> (Exp a -> Exp (m b))+ -> Exp (m b)++ -- | Inject a value into the monadic type+ --+ return :: (Elt a, Elt (m a)) => Exp a -> Exp (m a)+++-- | Same as '>>=', but with the arguments interchanged+--+infixr 1 =<<+(=<<) :: (Monad m, Elt a, Elt b, Elt (m a), Elt (m b))+ => (Exp a -> Exp (m b))+ -> Exp (m a)+ -> Exp (m b)+(=<<) = flip (>>=)++-- | Sequentially compose two actions, discarding any value produced by the+-- first, like sequencing operators (such as the semicolon) in imperative+-- languages.+--+-- \'@as '>>' bs@\' can be understood as the @do@ expression+--+-- @+-- do as+-- bs+-- @+--+infixl 1 >>+(>>) :: (Monad m, Elt a, Elt b, Elt (m a), Elt (m b))+ => Exp (m a)+ -> Exp (m b)+ -> Exp (m b)+m >> k = m >>= \_ -> k+++-- | Left-to-right composition of Kleisli arrows.+--+-- \'@(bs '>=>' cs) a@\' can be understood as the @do@ expression+--+-- @+-- do b <- bs a+-- cs b+-- @+--+infixr 1 >=>+(>=>) :: (Monad m, Elt a, Elt b, Elt c, Elt (m b), Elt (m c))+ => (Exp a -> Exp (m b))+ -> (Exp b -> Exp (m c))+ -> (Exp a -> Exp (m c))+f >=> g = \x -> f x >>= g++-- | Right-to-left composition of Kleisli arrows. @('>=>')@, with the arguments+-- flipped.+--+-- Note how this operator resembles function composition @('.')@:+--+-- > (.) :: (b -> c) -> (a -> b) -> a -> c+-- > (<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c+--+infixr 1 <=<+(<=<) :: (Monad m, Elt a, Elt b, Elt c, Elt (m b), Elt (m c))+ => (Exp b -> Exp (m c))+ -> (Exp a -> Exp (m b))+ -> (Exp a -> Exp (m c))+(<=<) = flip (>=>)+++-- | Conditional execution of a monadic expression+--+when :: (Monad m, Elt (m ())) => Exp Bool -> Exp (m ()) -> Exp (m ())+when p s = cond p s (return (constant ()))++-- | The reverse of 'when'+--+unless :: (Monad m, Elt (m ())) => Exp Bool -> Exp (m ()) -> Exp (m ())+unless p s = cond p (return (constant ())) s++-- | Promote a function to a monad+--+liftM :: (Monad m, Elt a, Elt b, Elt (m a), Elt (m b)) => (Exp a -> Exp b) -> Exp (m a) -> Exp (m b)+liftM f m1 = do+ x1 <- m1+ return (f x1)++-- | Promote a function to a monad, scanning the monadic arguments from+-- left to right.+--+liftM2 :: (Monad m, Elt a, Elt b, Elt c, Elt (m a), Elt (m b), Elt (m c))+ => (Exp a -> Exp b -> Exp c)+ -> Exp (m a)+ -> Exp (m b)+ -> Exp (m c)+liftM2 f m1 m2 = do+ x1 <- m1+ x2 <- m2+ return (f x1 x2)++-- | Promote a function to a monad, scanning the monadic arguments from+-- left to right (cf. 'liftM2')+--+liftM3 :: (Monad m, Elt a, Elt b, Elt c, Elt d, Elt (m a), Elt (m b), Elt (m c), Elt (m d))+ => (Exp a -> Exp b -> Exp c -> Exp d)+ -> Exp (m a)+ -> Exp (m b)+ -> Exp (m c)+ -> Exp (m d)+liftM3 f m1 m2 m3 = do+ x1 <- m1+ x2 <- m2+ x3 <- m3+ return (f x1 x2 x3)++-- | Promote a function to a monad, scanning the monadic arguments from+-- left to right (cf. 'liftM2')+--+liftM4 :: (Monad m, Elt a, Elt b, Elt c, Elt d, Elt e, Elt (m a), Elt (m b), Elt (m c), Elt (m d), Elt (m e))+ => (Exp a -> Exp b -> Exp c -> Exp d -> Exp e)+ -> Exp (m a)+ -> Exp (m b)+ -> Exp (m c)+ -> Exp (m d)+ -> Exp (m e)+liftM4 f m1 m2 m3 m4 = do+ x1 <- m1+ x2 <- m2+ x3 <- m3+ x4 <- m4+ return (f x1 x2 x3 x4)++-- | Promote a function to a monad, scanning the monadic arguments from+-- left to right (cf. 'liftM2')+--+liftM5 :: ( Monad m+ , Elt a, Elt b, Elt c, Elt d, Elt e, Elt f+ , Elt (m a), Elt (m b), Elt (m c), Elt (m d), Elt (m e), Elt (m f)+ )+ => (Exp a -> Exp b -> Exp c -> Exp d -> Exp e -> Exp f)+ -> Exp (m a)+ -> Exp (m b)+ -> Exp (m c)+ -> Exp (m d)+ -> Exp (m e)+ -> Exp (m f)+liftM5 f m1 m2 m3 m4 m5 = do+ x1 <- m1+ x2 <- m2+ x3 <- m3+ x4 <- m4+ x5 <- m5+ return (f x1 x2 x3 x4 x5)+
+ src/Data/Array/Accelerate/Data/Bits.hs view
@@ -0,0 +1,830 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ViewPatterns #-}+-- |+-- Module : Data.Array.Accelerate.Data.Bits+-- Copyright : [2016..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- Bitwise operations for signed and unsigned integer expressions.+--++module Data.Array.Accelerate.Data.Bits (++ Bits(..),+ FiniteBits(..),++) where++import Data.Array.Accelerate.Array.Data+import Data.Array.Accelerate.Language+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.Classes.Eq+import Data.Array.Accelerate.Classes.Ord+import Data.Array.Accelerate.Classes.Integral ()++import Prelude ( (.), ($), undefined, otherwise )+import qualified Data.Bits as B+++infixl 8 `shift`, `rotate`, `shiftL`, `shiftR`, `rotateL`, `rotateR`+infixl 7 .&.+infixl 6 `xor`+infixl 5 .|.+++-- | The 'Bits' class defines bitwise operations over integral scalar expression+-- types. As usual, bits are numbered from zero, with zero being the least+-- significant bit.+--+class Eq a => Bits a where+ {-# MINIMAL (.&.), (.|.), xor, complement,+ (shift | (shiftL, shiftR)),+ (rotate | (rotateL, rotateR)),+ isSigned, testBit, bit, popCount #-}++ -- | Bitwise "and"+ (.&.) :: Exp a -> Exp a -> Exp a++ -- | Bitwise "or"+ (.|.) :: Exp a -> Exp a -> Exp a++ -- | Bitwise "xor"+ xor :: Exp a -> Exp a -> Exp a++ -- | Reverse all bits in the argument+ complement :: Exp a -> Exp a++ -- | @'shift' x i@ shifts @x@ left by @i@ bits if @i@ is positive, or right by+ -- @-i@ bits otherwise. Right shifts perform sign extension on signed number+ -- types; i.e. they fill the top bits with 1 if the @x@ is negative and with+ -- 0 otherwise.+ shift :: Exp a -> Exp Int -> Exp a+ shift x i+ = cond (i < 0) (x `shiftR` (-i))+ $ cond (i > 0) (x `shiftL` i)+ $ x++ -- | @'rotate' x i@ rotates @x@ left by @i@ bits if @i@ is positive, or right+ -- by @-i@ bits otherwise.+ rotate :: Exp a -> Exp Int -> Exp a+ rotate x i+ = cond (i < 0) (x `rotateR` (-i))+ $ cond (i > 0) (x `rotateL` i)+ $ x++ -- | The value with all bits unset+ zeroBits :: Exp a+ zeroBits = clearBit (bit 0) 0++ -- | @bit /i/@ is a value with the @/i/@th bit set and all other bits clear.+ bit :: Exp Int -> Exp a++ -- | @x \`setBit\` i@ is the same as @x .|. bit i@+ setBit :: Exp a -> Exp Int -> Exp a+ setBit x i = x .|. bit i++ -- | @x \`clearBit\` i@ is the same as @x .&. complement (bit i)@+ clearBit :: Exp a -> Exp Int -> Exp a+ clearBit x i = x .&. complement (bit i)++ -- | @x \`complementBit\` i@ is the same as @x \`xor\` bit i@+ complementBit :: Exp a -> Exp Int -> Exp a+ complementBit x i = x `xor` bit i++ -- | Return 'True' if the @n@th bit of the argument is 1+ testBit :: Exp a -> Exp Int -> Exp Bool++ -- | Return 'True' if the argument is a signed type.+ isSigned :: Exp a -> Exp Bool++ -- | Shift the argument left by the specified number of bits (which must be+ -- non-negative).+ shiftL :: Exp a -> Exp Int -> Exp a+ shiftL x i = x `shift` i++ -- | Shift the argument left by the specified number of bits. The result is+ -- undefined for negative shift amounts and shift amounts greater or equal to+ -- the 'finiteBitSize'.+ unsafeShiftL :: Exp a -> Exp Int -> Exp a+ unsafeShiftL = shiftL++ -- | Shift the first argument right by the specified number of bits (which+ -- must be non-negative).+ --+ -- Right shifts perform sign extension on signed number types; i.e. they fill+ -- the top bits with 1 if @x@ is negative and with 0 otherwise.+ shiftR :: Exp a -> Exp Int -> Exp a+ shiftR x i = x `shift` (-i)++ -- | Shift the first argument right by the specified number of bits. The+ -- result is undefined for negative shift amounts and shift amounts greater or+ -- equal to the 'finiteBitSize'.+ unsafeShiftR :: Exp a -> Exp Int -> Exp a+ unsafeShiftR = shiftR++ -- | Rotate the argument left by the specified number of bits (which must be+ -- non-negative).+ rotateL :: Exp a -> Exp Int -> Exp a+ rotateL x i = x `rotate` i++ -- | Rotate the argument right by the specified number of bits (which must be non-negative).+ rotateR :: Exp a -> Exp Int -> Exp a+ rotateR x i = x `rotate` (-i)++ -- | Return the number of set bits in the argument. This number is known as+ -- the population count or the Hamming weight.+ popCount :: Exp a -> Exp Int+++class Bits b => FiniteBits b where+ -- | Return the number of bits in the type of the argument.+ finiteBitSize :: Exp b -> Exp Int++ -- | Count the number of zero bits preceding the most significant set bit.+ -- This can be used to compute a base-2 logarithm via:+ --+ -- > logBase2 x = finiteBitSize x - 1 - countLeadingZeros x+ --+ countLeadingZeros :: Exp b -> Exp Int++ -- | Count the number of zero bits following the least significant set bit.+ -- The related+ -- <http://en.wikipedia.org/wiki/Find_first_set find-first-set operation> can+ -- be expressed in terms of this as:+ --+ -- > findFirstSet x = 1 + countTrailingZeros x+ --+ countTrailingZeros :: Exp b -> Exp Int+++-- Instances for Bits+-- ------------------++instance Bits Bool where+ (.&.) = (&&)+ (.|.) = (||)+ xor = (/=)+ complement = not+ shift x i = cond (i == 0) x (constant False)+ testBit x i = cond (i == 0) x (constant False)+ rotate x _ = x+ bit i = i == 0+ isSigned = isSignedDefault+ popCount = boolToInt++instance Bits Int where+ (.&.) = mkBAnd+ (.|.) = mkBOr+ xor = mkBXor+ complement = mkBNot+ bit = bitDefault+ testBit = testBitDefault+ shift = shiftDefault+ shiftL = shiftLDefault+ shiftR = shiftRDefault+ unsafeShiftL = mkBShiftL+ unsafeShiftR = mkBShiftR+ rotate = rotateDefault+ rotateL = rotateLDefault+ rotateR = rotateRDefault+ isSigned = isSignedDefault+ popCount = mkPopCount++instance Bits Int8 where+ (.&.) = mkBAnd+ (.|.) = mkBOr+ xor = mkBXor+ complement = mkBNot+ bit = bitDefault+ testBit = testBitDefault+ shift = shiftDefault+ shiftL = shiftLDefault+ shiftR = shiftRDefault+ unsafeShiftL = mkBShiftL+ unsafeShiftR = mkBShiftR+ rotate = rotateDefault+ rotateL = rotateLDefault+ rotateR = rotateRDefault+ isSigned = isSignedDefault+ popCount = mkPopCount++instance Bits Int16 where+ (.&.) = mkBAnd+ (.|.) = mkBOr+ xor = mkBXor+ complement = mkBNot+ bit = bitDefault+ testBit = testBitDefault+ shift = shiftDefault+ shiftL = shiftLDefault+ shiftR = shiftRDefault+ unsafeShiftL = mkBShiftL+ unsafeShiftR = mkBShiftR+ rotate = rotateDefault+ rotateL = rotateLDefault+ rotateR = rotateRDefault+ isSigned = isSignedDefault+ popCount = mkPopCount++instance Bits Int32 where+ (.&.) = mkBAnd+ (.|.) = mkBOr+ xor = mkBXor+ complement = mkBNot+ bit = bitDefault+ testBit = testBitDefault+ shift = shiftDefault+ shiftL = shiftLDefault+ shiftR = shiftRDefault+ unsafeShiftL = mkBShiftL+ unsafeShiftR = mkBShiftR+ rotate = rotateDefault+ rotateL = rotateLDefault+ rotateR = rotateRDefault+ isSigned = isSignedDefault+ popCount = mkPopCount++instance Bits Int64 where+ (.&.) = mkBAnd+ (.|.) = mkBOr+ xor = mkBXor+ complement = mkBNot+ bit = bitDefault+ testBit = testBitDefault+ shift = shiftDefault+ shiftL = shiftLDefault+ shiftR = shiftRDefault+ unsafeShiftL = mkBShiftL+ unsafeShiftR = mkBShiftR+ rotate = rotateDefault+ rotateL = rotateLDefault+ rotateR = rotateRDefault+ isSigned = isSignedDefault+ popCount = mkPopCount++instance Bits Word where+ (.&.) = mkBAnd+ (.|.) = mkBOr+ xor = mkBXor+ complement = mkBNot+ bit = bitDefault+ testBit = testBitDefault+ shift = shiftDefault+ shiftL = shiftLDefault+ shiftR = shiftRDefault+ unsafeShiftL = mkBShiftL+ unsafeShiftR = mkBShiftR+ rotate = rotateDefault+ rotateL = rotateLDefault+ rotateR = rotateRDefault+ isSigned = isSignedDefault+ popCount = mkPopCount++instance Bits Word8 where+ (.&.) = mkBAnd+ (.|.) = mkBOr+ xor = mkBXor+ complement = mkBNot+ bit = bitDefault+ testBit = testBitDefault+ shift = shiftDefault+ shiftL = shiftLDefault+ shiftR = shiftRDefault+ unsafeShiftL = mkBShiftL+ unsafeShiftR = mkBShiftR+ rotate = rotateDefault+ rotateL = rotateLDefault+ rotateR = rotateRDefault+ isSigned = isSignedDefault+ popCount = mkPopCount++instance Bits Word16 where+ (.&.) = mkBAnd+ (.|.) = mkBOr+ xor = mkBXor+ complement = mkBNot+ bit = bitDefault+ testBit = testBitDefault+ shift = shiftDefault+ shiftL = shiftLDefault+ shiftR = shiftRDefault+ unsafeShiftL = mkBShiftL+ unsafeShiftR = mkBShiftR+ rotate = rotateDefault+ rotateL = rotateLDefault+ rotateR = rotateRDefault+ isSigned = isSignedDefault+ popCount = mkPopCount++instance Bits Word32 where+ (.&.) = mkBAnd+ (.|.) = mkBOr+ xor = mkBXor+ complement = mkBNot+ bit = bitDefault+ testBit = testBitDefault+ shift = shiftDefault+ shiftL = shiftLDefault+ shiftR = shiftRDefault+ unsafeShiftL = mkBShiftL+ unsafeShiftR = mkBShiftR+ rotate = rotateDefault+ rotateL = rotateLDefault+ rotateR = rotateRDefault+ isSigned = isSignedDefault+ popCount = mkPopCount++instance Bits Word64 where+ (.&.) = mkBAnd+ (.|.) = mkBOr+ xor = mkBXor+ complement = mkBNot+ bit = bitDefault+ testBit = testBitDefault+ shift = shiftDefault+ shiftL = shiftLDefault+ shiftR = shiftRDefault+ unsafeShiftL = mkBShiftL+ unsafeShiftR = mkBShiftR+ rotate = rotateDefault+ rotateL = rotateLDefault+ rotateR = rotateRDefault+ isSigned = isSignedDefault+ popCount = mkPopCount++instance Bits CInt where+ (.&.) = mkBAnd+ (.|.) = mkBOr+ xor = mkBXor+ complement = mkBNot+ bit = mkBitcast . bitDefault @Int32+ testBit b = testBitDefault (mkBitcast @Int32 b)+ shift = shiftDefault+ shiftL = shiftLDefault+ shiftR = shiftRDefault+ unsafeShiftL = mkBShiftL+ unsafeShiftR = mkBShiftR+ rotate = rotateDefault+ rotateL = rotateLDefault+ rotateR = rotateRDefault+ isSigned = isSignedDefault+ popCount = mkPopCount . mkBitcast @Int32++instance Bits CUInt where+ (.&.) = mkBAnd+ (.|.) = mkBOr+ xor = mkBXor+ complement = mkBNot+ bit = mkBitcast . bitDefault @Word32+ testBit b = testBitDefault (mkBitcast @Word32 b)+ shift = shiftDefault+ shiftL = shiftLDefault+ shiftR = shiftRDefault+ unsafeShiftL = mkBShiftL+ unsafeShiftR = mkBShiftR+ rotate = rotateDefault+ rotateL = rotateLDefault+ rotateR = rotateRDefault+ isSigned = isSignedDefault+ popCount = mkPopCount . mkBitcast @Word32++instance Bits CLong where+ (.&.) = mkBAnd+ (.|.) = mkBOr+ xor = mkBXor+ complement = mkBNot+ bit = mkBitcast . bitDefault @HTYPE_CLONG+ testBit b = testBitDefault (mkBitcast @HTYPE_CLONG b)+ shift = shiftDefault+ shiftL = shiftLDefault+ shiftR = shiftRDefault+ unsafeShiftL = mkBShiftL+ unsafeShiftR = mkBShiftR+ rotate = rotateDefault+ rotateL = rotateLDefault+ rotateR = rotateRDefault+ isSigned = isSignedDefault+ popCount = mkPopCount . mkBitcast @HTYPE_CLONG++instance Bits CULong where+ (.&.) = mkBAnd+ (.|.) = mkBOr+ xor = mkBXor+ complement = mkBNot+ bit = mkBitcast . bitDefault @HTYPE_CULONG+ testBit b = testBitDefault (mkBitcast @HTYPE_CULONG b)+ shift = shiftDefault+ shiftL = shiftLDefault+ shiftR = shiftRDefault+ unsafeShiftL = mkBShiftL+ unsafeShiftR = mkBShiftR+ rotate = rotateDefault+ rotateL = rotateLDefault+ rotateR = rotateRDefault+ isSigned = isSignedDefault+ popCount = mkPopCount . mkBitcast @HTYPE_CULONG++instance Bits CLLong where+ (.&.) = mkBAnd+ (.|.) = mkBOr+ xor = mkBXor+ complement = mkBNot+ bit = mkBitcast . bitDefault @Int64+ testBit b = testBitDefault (mkBitcast @Int64 b)+ shift = shiftDefault+ shiftL = shiftLDefault+ shiftR = shiftRDefault+ unsafeShiftL = mkBShiftL+ unsafeShiftR = mkBShiftR+ rotate = rotateDefault+ rotateL = rotateLDefault+ rotateR = rotateRDefault+ isSigned = isSignedDefault+ popCount = mkPopCount . mkBitcast @Int64++instance Bits CULLong where+ (.&.) = mkBAnd+ (.|.) = mkBOr+ xor = mkBXor+ complement = mkBNot+ bit = mkBitcast . bitDefault @Word64+ testBit b = testBitDefault (mkBitcast @Word64 b)+ shift = shiftDefault+ shiftL = shiftLDefault+ shiftR = shiftRDefault+ unsafeShiftL = mkBShiftL+ unsafeShiftR = mkBShiftR+ rotate = rotateDefault+ rotateL = rotateLDefault+ rotateR = rotateRDefault+ isSigned = isSignedDefault+ popCount = mkPopCount . mkBitcast @Word64++instance Bits CShort where+ (.&.) = mkBAnd+ (.|.) = mkBOr+ xor = mkBXor+ complement = mkBNot+ bit = mkBitcast . bitDefault @Int16+ testBit b = testBitDefault (mkBitcast @Int16 b)+ shift = shiftDefault+ shiftL = shiftLDefault+ shiftR = shiftRDefault+ unsafeShiftL = mkBShiftL+ unsafeShiftR = mkBShiftR+ rotate = rotateDefault+ rotateL = rotateLDefault+ rotateR = rotateRDefault+ isSigned = isSignedDefault+ popCount = mkPopCount . mkBitcast @Int16++instance Bits CUShort where+ (.&.) = mkBAnd+ (.|.) = mkBOr+ xor = mkBXor+ complement = mkBNot+ bit = mkBitcast . bitDefault @Word16+ testBit b = testBitDefault (mkBitcast @Word16 b)+ shift = shiftDefault+ shiftL = shiftLDefault+ shiftR = shiftRDefault+ unsafeShiftL = mkBShiftL+ unsafeShiftR = mkBShiftR+ rotate = rotateDefault+ rotateL = rotateLDefault+ rotateR = rotateRDefault+ isSigned = isSignedDefault+ popCount = mkPopCount . mkBitcast @Word16++instance Bits CChar where+ (.&.) = mkBAnd+ (.|.) = mkBOr+ xor = mkBXor+ complement = mkBNot+ bit = mkBitcast . bitDefault @HTYPE_CCHAR+ testBit b = testBitDefault (mkBitcast @HTYPE_CCHAR b)+ shift = shiftDefault+ shiftL = shiftLDefault+ shiftR = shiftRDefault+ unsafeShiftL = mkBShiftL+ unsafeShiftR = mkBShiftR+ rotate = rotateDefault+ rotateL = rotateLDefault+ rotateR = rotateRDefault+ isSigned = isSignedDefault+ popCount = mkPopCount . mkBitcast @HTYPE_CCHAR++instance Bits CSChar where+ (.&.) = mkBAnd+ (.|.) = mkBOr+ xor = mkBXor+ complement = mkBNot+ bit = mkBitcast . bitDefault @Int8+ testBit b = testBitDefault (mkBitcast @Int8 b)+ shift = shiftDefault+ shiftL = shiftLDefault+ shiftR = shiftRDefault+ unsafeShiftL = mkBShiftL+ unsafeShiftR = mkBShiftR+ rotate = rotateDefault+ rotateL = rotateLDefault+ rotateR = rotateRDefault+ isSigned = isSignedDefault+ popCount = mkPopCount . mkBitcast @Int8++instance Bits CUChar where+ (.&.) = mkBAnd+ (.|.) = mkBOr+ xor = mkBXor+ complement = mkBNot+ bit = mkBitcast . bitDefault @Word8+ testBit b = testBitDefault (mkBitcast @Word8 b)+ shift = shiftDefault+ shiftL = shiftLDefault+ shiftR = shiftRDefault+ unsafeShiftL = mkBShiftL+ unsafeShiftR = mkBShiftR+ rotate = rotateDefault+ rotateL = rotateLDefault+ rotateR = rotateRDefault+ isSigned = isSignedDefault+ popCount = mkPopCount . mkBitcast @Word8++++-- Instances for FiniteBits+-- ------------------------++instance FiniteBits Bool where+ finiteBitSize _ = constInt 8 -- stored as Word8 {- (B.finiteBitSize (undefined::Bool)) -}+ countLeadingZeros x = cond x 0 1+ countTrailingZeros x = cond x 0 1++instance FiniteBits Int where+ finiteBitSize _ = constInt (B.finiteBitSize (undefined::Int))+ countLeadingZeros = mkCountLeadingZeros+ countTrailingZeros = mkCountTrailingZeros++instance FiniteBits Int8 where+ finiteBitSize _ = constInt (B.finiteBitSize (undefined::Int8))+ countLeadingZeros = mkCountLeadingZeros+ countTrailingZeros = mkCountTrailingZeros++instance FiniteBits Int16 where+ finiteBitSize _ = constInt (B.finiteBitSize (undefined::Int16))+ countLeadingZeros = mkCountLeadingZeros+ countTrailingZeros = mkCountTrailingZeros++instance FiniteBits Int32 where+ finiteBitSize _ = constInt (B.finiteBitSize (undefined::Int32))+ countLeadingZeros = mkCountLeadingZeros+ countTrailingZeros = mkCountTrailingZeros++instance FiniteBits Int64 where+ finiteBitSize _ = constInt (B.finiteBitSize (undefined::Int64))+ countLeadingZeros = mkCountLeadingZeros+ countTrailingZeros = mkCountTrailingZeros++instance FiniteBits Word where+ finiteBitSize _ = constInt (B.finiteBitSize (undefined::Word))+ countLeadingZeros = mkCountLeadingZeros+ countTrailingZeros = mkCountTrailingZeros++instance FiniteBits Word8 where+ finiteBitSize _ = constInt (B.finiteBitSize (undefined::Word8))+ countLeadingZeros = mkCountLeadingZeros+ countTrailingZeros = mkCountTrailingZeros++instance FiniteBits Word16 where+ finiteBitSize _ = constInt (B.finiteBitSize (undefined::Word16))+ countLeadingZeros = mkCountLeadingZeros+ countTrailingZeros = mkCountTrailingZeros++instance FiniteBits Word32 where+ finiteBitSize _ = constInt (B.finiteBitSize (undefined::Word32))+ countLeadingZeros = mkCountLeadingZeros+ countTrailingZeros = mkCountTrailingZeros++instance FiniteBits Word64 where+ finiteBitSize _ = constInt (B.finiteBitSize (undefined::Word64))+ countLeadingZeros = mkCountLeadingZeros+ countTrailingZeros = mkCountTrailingZeros++instance FiniteBits CInt where+ finiteBitSize _ = constInt (B.finiteBitSize (undefined::CInt))+ countLeadingZeros = mkCountLeadingZeros . mkBitcast @Int32+ countTrailingZeros = mkCountTrailingZeros . mkBitcast @Int32++instance FiniteBits CUInt where+ finiteBitSize _ = constInt (B.finiteBitSize (undefined::CUInt))+ countLeadingZeros = mkCountLeadingZeros . mkBitcast @Word32+ countTrailingZeros = mkCountTrailingZeros . mkBitcast @Word32++instance FiniteBits CLong where+ finiteBitSize _ = constInt (B.finiteBitSize (undefined::CLong))+ countLeadingZeros = mkCountLeadingZeros . mkBitcast @HTYPE_CLONG+ countTrailingZeros = mkCountTrailingZeros . mkBitcast @HTYPE_CLONG++instance FiniteBits CULong where+ finiteBitSize _ = constInt (B.finiteBitSize (undefined::CULong))+ countLeadingZeros = mkCountLeadingZeros . mkBitcast @HTYPE_CULONG+ countTrailingZeros = mkCountTrailingZeros . mkBitcast @HTYPE_CULONG++instance FiniteBits CLLong where+ finiteBitSize _ = constInt (B.finiteBitSize (undefined::CLLong))+ countLeadingZeros = mkCountLeadingZeros . mkBitcast @Int64+ countTrailingZeros = mkCountTrailingZeros . mkBitcast @Int64++instance FiniteBits CULLong where+ finiteBitSize _ = constInt (B.finiteBitSize (undefined::CULLong))+ countLeadingZeros = mkCountLeadingZeros . mkBitcast @Word64+ countTrailingZeros = mkCountTrailingZeros . mkBitcast @Word64++instance FiniteBits CShort where+ finiteBitSize _ = constInt (B.finiteBitSize (undefined::CShort))+ countLeadingZeros = mkCountLeadingZeros . mkBitcast @Int16+ countTrailingZeros = mkCountTrailingZeros . mkBitcast @Int16++instance FiniteBits CUShort where+ finiteBitSize _ = constInt (B.finiteBitSize (undefined::CUShort))+ countLeadingZeros = mkCountLeadingZeros . mkBitcast @Word16+ countTrailingZeros = mkCountTrailingZeros . mkBitcast @Word16++instance FiniteBits CChar where+ finiteBitSize _ = constInt (B.finiteBitSize (undefined::CChar))+ countLeadingZeros = mkCountLeadingZeros . mkBitcast @HTYPE_CCHAR+ countTrailingZeros = mkCountTrailingZeros . mkBitcast @HTYPE_CCHAR++instance FiniteBits CSChar where+ finiteBitSize _ = constInt (B.finiteBitSize (undefined::CSChar))+ countLeadingZeros = mkCountLeadingZeros . mkBitcast @Int8+ countTrailingZeros = mkCountTrailingZeros . mkBitcast @Int8++instance FiniteBits CUChar where+ finiteBitSize _ = constInt (B.finiteBitSize (undefined::CUChar))+ countLeadingZeros = mkCountLeadingZeros . mkBitcast @Word8+ countTrailingZeros = mkCountTrailingZeros . mkBitcast @Word8+++-- Default implementations+-- -----------------------+bitDefault :: (IsIntegral (EltR t), Bits t) => Exp Int -> Exp t+bitDefault x = constInt 1 `shiftL` x++testBitDefault :: (IsIntegral (EltR t), Bits t) => Exp t -> Exp Int -> Exp Bool+testBitDefault x i = (x .&. bit i) /= constInt 0++shiftDefault :: (FiniteBits t, IsIntegral (EltR t), B.Bits t) => Exp t -> Exp Int -> Exp t+shiftDefault x i+ = cond (i >= 0) (shiftLDefault x i)+ (shiftRDefault x (-i))++shiftLDefault :: (FiniteBits t, IsIntegral (EltR t)) => Exp t -> Exp Int -> Exp t+shiftLDefault x i+ = cond (i >= finiteBitSize x) (constInt 0)+ $ mkBShiftL x i++shiftRDefault :: forall t. (B.Bits t, FiniteBits t, IsIntegral (EltR t)) => Exp t -> Exp Int -> Exp t+shiftRDefault+ | B.isSigned (undefined::t) = shiftRADefault+ | otherwise = shiftRLDefault++-- Shift the argument right (signed)+shiftRADefault :: (FiniteBits t, IsIntegral (EltR t)) => Exp t -> Exp Int -> Exp t+shiftRADefault x i+ = cond (i >= finiteBitSize x) (cond (mkLt x (constInt 0)) (constInt (-1)) (constInt 0))+ $ mkBShiftR x i++-- Shift the argument right (unsigned)+shiftRLDefault :: (FiniteBits t, IsIntegral (EltR t)) => Exp t -> Exp Int -> Exp t+shiftRLDefault x i+ = cond (i >= finiteBitSize x) (constInt 0)+ $ mkBShiftR x i++rotateDefault :: forall t. (FiniteBits t, IsIntegral (EltR t)) => Exp t -> Exp Int -> Exp t+rotateDefault x i+ = cond (i < 0) (mkBRotateR x (-i))+ $ cond (i > 0) (mkBRotateL x i)+ $ x++{--+-- Rotation can be implemented in terms of two shifts, but care is needed+-- for negative values. This suggested implementation assumes+-- 2's-complement arithmetic.+--+-- This is disabled because (at least) LLVM-9 generates incorrect code on+-- the Turing architecture for negative shift amounts of 64-bit values.+--+rotateDefault :: forall t. (FiniteBits t, IsIntegral (EltR t)) => Exp t -> Exp Int -> Exp t+rotateDefault =+ case integralType :: IntegralType (EltR t) of+ TypeInt{} -> rotateDefault' (undefined::Word)+ TypeInt8{} -> rotateDefault' (undefined::Word8)+ TypeInt16{} -> rotateDefault' (undefined::Word16)+ TypeInt32{} -> rotateDefault' (undefined::Word32)+ TypeInt64{} -> rotateDefault' (undefined::Word64)+ TypeWord{} -> rotateDefault' (undefined::Word)+ TypeWord8{} -> rotateDefault' (undefined::Word8)+ TypeWord16{} -> rotateDefault' (undefined::Word16)+ TypeWord32{} -> rotateDefault' (undefined::Word32)+ TypeWord64{} -> rotateDefault' (undefined::Word64)++rotateDefault'+ :: forall i w. (Elt w, FiniteBits i, IsIntegral (EltR i), IsIntegral (EltR w), IsIntegral (EltR i), IsIntegral (EltR w), BitSizeEq (EltR i) (EltR w), BitSizeEq (EltR w) (EltR i))+ => w {- dummy -}+ -> Exp i+ -> Exp Int+ -> Exp i+rotateDefault' _ x i+ = cond (i' == 0) x+ $ w2i ((x' `mkBShiftL` i') `mkBOr` (x' `mkBShiftR` (wsib - i')))+ where+ w2i = mkBitcast :: Exp w -> Exp i+ i2w = mkBitcast :: Exp i -> Exp w+ --+ x' = i2w x+ i' = i `mkBAnd` (wsib - 1)+ wsib = finiteBitSize x+--}++rotateLDefault :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp Int -> Exp t+rotateLDefault x i+ = cond (i == 0) x+ $ mkBRotateL x i++rotateRDefault :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp Int -> Exp t+rotateRDefault x i+ = cond (i == 0) x+ $ mkBRotateR x i++isSignedDefault :: forall b. B.Bits b => Exp b -> Exp Bool+isSignedDefault _ = constant (B.isSigned (undefined::b))++constInt :: IsIntegral (EltR e) => EltR e -> Exp e+constInt = mkExp . Const (SingleScalarType (NumSingleType (IntegralNumType integralType)))++{--+_popCountDefault :: forall a. (B.FiniteBits a, IsScalar a, Bits a, Num a) => Exp a -> Exp Int+_popCountDefault =+ $( [e| case B.finiteBitSize (undefined::a) of+ 8 -> popCnt8 . mkUnsafeCoerce+ 16 -> popCnt16 . mkUnsafeCoerce+ 32 -> popCnt32 . mkUnsafeCoerce+ 64 -> popCnt64 . mkUnsafeCoerce+ _ -> popCountKernighan |] )++-- http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan+popCountKernighan :: (Bits a, Num a) => Exp a -> Exp Int+popCountKernighan x = r+ where+ (r,_) = untup2+ $ while (\(untup2 -> (_,v)) -> v /= 0)+ (\(untup2 -> (c,v)) -> tup2 (c+1, v .&. (v-1)))+ (tup2 (0,x))++-- http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel+popCnt8 :: Exp Word8 -> Exp Int+popCnt8 v1 = mkFromIntegral c+ where+ v2 = v1 - ((v1 `unsafeShiftR` 1) .&. 0x55)+ v3 = (v2 .&. 0x33) + ((v2 `unsafeShiftR` 2) .&. 0x33)+ v4 = (v3 + (v3 `unsafeShiftR` 4)) .&. 0x0F+ c = v4 * 0x01++popCnt16 :: Exp Word16 -> Exp Int+popCnt16 v1 = mkFromIntegral c+ where+ v2 = v1 - ((v1 `unsafeShiftR` 1) .&. 0x5555)+ v3 = (v2 .&. 0x3333) + ((v2 `unsafeShiftR` 2) .&. 0x3333)+ v4 = (v3 + (v3 `unsafeShiftR` 4)) .&. 0x0F0F+ c = (v4 * 0x0101) `unsafeShiftR` 8++popCnt32 :: Exp Word32 -> Exp Int+popCnt32 v1 = mkFromIntegral c+ where+ v2 = v1 - ((v1 `unsafeShiftR` 1) .&. 0x55555555)+ v3 = (v2 .&. 0x33333333) + ((v2 `unsafeShiftR` 2) .&. 0x33333333)+ v4 = (v3 + (v3 `unsafeShiftR` 4)) .&. 0x0F0F0F0F+ c = (v4 * 0x01010101) `unsafeShiftR` 24++popCnt64 :: Exp Word64 -> Exp Int+popCnt64 v1 = mkFromIntegral c+ where+ v2 = v1 - ((v1 `unsafeShiftR` 1) .&. 0x5555555555555555)+ v3 = (v2 .&. 0x3333333333333333) + ((v2 `unsafeShiftR` 2) .&. 0x3333333333333333)+ v4 = (v3 + (v3 `unsafeShiftR` 4)) .&. 0X0F0F0F0F0F0F0F0F+ c = (v4 * 0x0101010101010101) `unsafeShiftR` 56+--}+
+ src/Data/Array/Accelerate/Data/Complex.hs view
@@ -0,0 +1,366 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE RebindableSyntax #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE ViewPatterns #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- |+-- Module : Data.Array.Accelerate.Data.Complex+-- Copyright : [2015..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- Complex numbers, stored in the usual C-style array-of-struct representation,+-- for easy interoperability.+--+module Data.Array.Accelerate.Data.Complex (++ -- * Rectangular from+ Complex(..), pattern (::+),+ real,+ imag,++ -- * Polar form+ mkPolar,+ cis,+ polar,+ magnitude, magnitude',+ phase,++ -- * Conjugate+ conjugate,++) where++import Data.Array.Accelerate.Classes.Eq+import Data.Array.Accelerate.Classes.Floating+import Data.Array.Accelerate.Classes.Fractional+import Data.Array.Accelerate.Classes.FromIntegral+import Data.Array.Accelerate.Classes.Num+import Data.Array.Accelerate.Classes.Ord+import Data.Array.Accelerate.Classes.RealFloat+import Data.Array.Accelerate.Data.Functor+import Data.Array.Accelerate.Pattern+import Data.Array.Accelerate.Prelude+import Data.Array.Accelerate.Representation.Tag+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Representation.Vec+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Sugar.Vec+import Data.Array.Accelerate.Type+import Data.Primitive.Vec++import Data.Complex ( Complex(..) )+import Prelude ( ($) )+import qualified Data.Complex as C+import qualified Prelude as P+#if __GLASGOW_HASKELL__ >= 904+import Data.Type.Equality+#endif+++infix 6 ::++pattern (::+) :: Elt a => Exp a -> Exp a -> Exp (Complex a)+pattern r ::+ i <- (deconstructComplex -> (r, i))+ where (::+) = constructComplex+{-# COMPLETE (::+) #-}+++-- Use an array-of-structs representation for complex numbers if possible.+-- This matches the standard C-style layout, but we can use this representation only at+-- specific types (not for any type 'a') as we can only have vectors of primitive type.+-- For other types, we use a structure-of-arrays representation. This is handled by the+-- ComplexR. We use the GADT ComplexR and function complexR to reconstruct+-- information on how the elements are represented.+--+instance Elt a => Elt (Complex a) where+ type EltR (Complex a) = ComplexR (EltR a)+ eltR = let tR = eltR @a+ in case complexR tR of+ ComplexVec s -> TupRsingle $ VectorScalarType $ VectorType 2 s+ ComplexTup -> TupRunit `TupRpair` tR `TupRpair` tR++ tagsR = let tR = eltR @a+ in case complexR tR of+ ComplexVec s -> [ TagRsingle (VectorScalarType (VectorType 2 s)) ]+ ComplexTup -> let go :: TypeR t -> [TagR t]+ go TupRunit = [TagRunit]+ go (TupRsingle s) = [TagRsingle s]+ go (TupRpair ta tb) = [TagRpair a b | a <- go ta, b <- go tb]+ in+ [ TagRunit `TagRpair` ta `TagRpair` tb | ta <- go tR, tb <- go tR ]++ toElt = case complexR $ eltR @a of+ ComplexVec _ -> \(Vec2 r i) -> toElt r :+ toElt i+ ComplexTup -> \(((), r), i) -> toElt r :+ toElt i++ fromElt (r :+ i) = case complexR $ eltR @a of+ ComplexVec _ -> Vec2 (fromElt r) (fromElt i)+ ComplexTup -> (((), fromElt r), fromElt i)++type family ComplexR a where+ ComplexR Half = Vec2 Half+ ComplexR Float = Vec2 Float+ ComplexR Double = Vec2 Double+ ComplexR Int = Vec2 Int+ ComplexR Int8 = Vec2 Int8+ ComplexR Int16 = Vec2 Int16+ ComplexR Int32 = Vec2 Int32+ ComplexR Int64 = Vec2 Int64+ ComplexR Word = Vec2 Word+ ComplexR Word8 = Vec2 Word8+ ComplexR Word16 = Vec2 Word16+ ComplexR Word32 = Vec2 Word32+ ComplexR Word64 = Vec2 Word64+ ComplexR a = (((), a), a)++-- This isn't ideal because we gather the evidence based on the+-- representation type, so we really get the evidence (VecElt (EltR a)),+-- which is not very useful...+-- - TLM 2020-07-16+data ComplexType a c where+ ComplexVec :: VecElt a => SingleType a -> ComplexType a (Vec2 a)+ ComplexTup :: ComplexType a (((), a), a)++complexR :: TypeR a -> ComplexType a (ComplexR a)+complexR = tuple+ where+ tuple :: TypeR a -> ComplexType a (ComplexR a)+ tuple TupRunit = ComplexTup+ tuple TupRpair{} = ComplexTup+ tuple (TupRsingle s) = scalar s++ scalar :: ScalarType a -> ComplexType a (ComplexR a)+ scalar (SingleScalarType t) = single t+ scalar VectorScalarType{} = ComplexTup++ single :: SingleType a -> ComplexType a (ComplexR a)+ single (NumSingleType t) = num t++ num :: NumType a -> ComplexType a (ComplexR a)+ num (IntegralNumType t) = integral t+ num (FloatingNumType t) = floating t++ integral :: IntegralType a -> ComplexType a (ComplexR a)+ integral TypeInt = ComplexVec singleType+ integral TypeInt8 = ComplexVec singleType+ integral TypeInt16 = ComplexVec singleType+ integral TypeInt32 = ComplexVec singleType+ integral TypeInt64 = ComplexVec singleType+ integral TypeWord = ComplexVec singleType+ integral TypeWord8 = ComplexVec singleType+ integral TypeWord16 = ComplexVec singleType+ integral TypeWord32 = ComplexVec singleType+ integral TypeWord64 = ComplexVec singleType++ floating :: FloatingType a -> ComplexType a (ComplexR a)+ floating TypeHalf = ComplexVec singleType+ floating TypeFloat = ComplexVec singleType+ floating TypeDouble = ComplexVec singleType+++constructComplex :: forall a. Elt a => Exp a -> Exp a -> Exp (Complex a)+constructComplex r i =+ case complexR (eltR @a) of+ ComplexTup -> coerce $ T2 r i+ ComplexVec _ -> V2 (coerce @a @(EltR a) r) (coerce @a @(EltR a) i)++deconstructComplex :: forall a. Elt a => Exp (Complex a) -> (Exp a, Exp a)+deconstructComplex c@(Exp c') =+ case complexR (eltR @a) of+ ComplexTup -> let T2 r i = coerce c in (r, i)+ ComplexVec t -> let T2 r i = Exp (SmartExp (VecUnpack (VecRsucc (VecRsucc (VecRnil t))) c'))+ in (r, i)++coerce :: EltR a ~ EltR b => Exp a -> Exp b+coerce (Exp e) = Exp e++instance (Lift Exp a, Elt (Plain a)) => Lift Exp (Complex a) where+ type Plain (Complex a) = Complex (Plain a)+ lift (r :+ i) = lift r ::+ lift i++instance Elt a => Unlift Exp (Complex (Exp a)) where+ unlift (r ::+ i) = r :+ i+++instance Eq a => Eq (Complex a) where+ r1 ::+ c1 == r2 ::+ c2 = r1 == r2 && c1 == c2+ r1 ::+ c1 /= r2 ::+ c2 = r1 /= r2 || c1 /= c2++instance RealFloat a => P.Num (Exp (Complex a)) where+ (+) = lift2 ((+) :: Complex (Exp a) -> Complex (Exp a) -> Complex (Exp a))+ (-) = lift2 ((-) :: Complex (Exp a) -> Complex (Exp a) -> Complex (Exp a))+ (*) = lift2 ((*) :: Complex (Exp a) -> Complex (Exp a) -> Complex (Exp a))+ negate = lift1 (negate :: Complex (Exp a) -> Complex (Exp a))+ signum z@(x ::+ y) =+ if z == 0+ then z+ else let r = magnitude z+ in x/r ::+ y/r+ abs z = magnitude z ::+ 0+ fromInteger n = fromInteger n ::+ 0++instance RealFloat a => P.Fractional (Exp (Complex a)) where+ fromRational x = fromRational x ::+ 0+ z / z' = (x*x''+y*y'') / d ::+ (y*x''-x*y'') / d+ where+ x :+ y = unlift z+ x' :+ y' = unlift z'+ --+ x'' = scaleFloat k x'+ y'' = scaleFloat k y'+ k = - max (exponent x') (exponent y')+ d = x'*x'' + y'*y''++instance RealFloat a => P.Floating (Exp (Complex a)) where+ pi = pi ::+ 0+ exp (x ::+ y) = let expx = exp x+ in expx * cos y ::+ expx * sin y+ log z = log (magnitude z) ::+ phase z+ sqrt z@(x ::+ y) =+ if z == 0+ then 0+ else u ::+ (y < 0 ? (-v, v))+ where+ T2 u v = x < 0 ? (T2 v' u', T2 u' v')+ v' = abs y / (u'*2)+ u' = sqrt ((magnitude z + abs x) / 2)++ x ** y =+ if y == 0 then 1 else+ if x == 0 then if exp_r > 0 then 0 else+ if exp_r < 0 then inf ::+ 0+ else nan ::+ nan+ else if isInfinite r || isInfinite i+ then if exp_r > 0 then inf ::+ 0 else+ if exp_r < 0 then 0+ else nan ::+ nan+ else exp (log x * y)+ where+ r ::+ i = x+ exp_r ::+ _ = y+ --+ inf = 1 / 0+ nan = 0 / 0++ sin (x ::+ y) = sin x * cosh y ::+ cos x * sinh y+ cos (x ::+ y) = cos x * cosh y ::+ (- sin x * sinh y)+ tan (x ::+ y) = (sinx*coshy ::+ cosx*sinhy) / (cosx*coshy ::+ (-sinx*sinhy))+ where+ sinx = sin x+ cosx = cos x+ sinhy = sinh y+ coshy = cosh y++ sinh (x ::+ y) = cos y * sinh x ::+ sin y * cosh x+ cosh (x ::+ y) = cos y * cosh x ::+ sin y * sinh x+ tanh (x ::+ y) = (cosy*sinhx ::+ siny*coshx) / (cosy*coshx ::+ siny*sinhx)+ where+ siny = sin y+ cosy = cos y+ sinhx = sinh x+ coshx = cosh x++ asin z@(x ::+ y) = y' ::+ (-x')+ where+ x' ::+ y' = log (((-y) ::+ x) + sqrt (1 - z*z))++ acos z = y'' ::+ (-x'')+ where+ x'' ::+ y'' = log (z + ((-y') ::+ x'))+ x' ::+ y' = sqrt (1 - z*z)++ atan z@(x ::+ y) = y' ::+ (-x')+ where+ x' ::+ y' = log (((1-y) ::+ x) / sqrt (1+z*z))++ asinh z = log (z + sqrt (1+z*z))+ acosh z = log (z + (z+1) * sqrt ((z-1)/(z+1)))+ atanh z = 0.5 * log ((1.0+z) / (1.0-z))+++instance (FromIntegral a b, Num b, Elt (Complex b)) => FromIntegral a (Complex b) where+ fromIntegral x = fromIntegral x ::+ 0++-- | @since 1.2.0.0+--+instance Functor Complex where+ fmap f (r ::+ i) = f r ::+ f i+++-- | The non-negative magnitude of a complex number+--+magnitude :: RealFloat a => Exp (Complex a) -> Exp a+magnitude (r ::+ i) = scaleFloat k (sqrt (sqr (scaleFloat mk r) + sqr (scaleFloat mk i)))+ where+ k = max (exponent r) (exponent i)+ mk = -k+ sqr z = z * z++-- | As 'magnitude', but ignore floating point rounding and use the traditional+-- (simpler to evaluate) definition.+--+-- @since 1.3.0.0+--+magnitude' :: RealFloat a => Exp (Complex a) -> Exp a+magnitude' (r ::+ i) = sqrt (r*r + i*i)++-- | The phase of a complex number, in the range @(-'pi', 'pi']@. If the+-- magnitude is zero, then so is the phase.+--+phase :: RealFloat a => Exp (Complex a) -> Exp a+phase z@(r ::+ i) =+ if z == 0+ then 0+ else atan2 i r++-- | The function 'polar' takes a complex number and returns a (magnitude,+-- phase) pair in canonical form: the magnitude is non-negative, and the phase+-- in the range @(-'pi', 'pi']@; if the magnitude is zero, then so is the phase.+--+polar :: RealFloat a => Exp (Complex a) -> Exp (a,a)+polar z = T2 (magnitude z) (phase z)++-- | Form a complex number from polar components of magnitude and phase.+--+mkPolar :: forall a. Floating a => Exp a -> Exp a -> Exp (Complex a)+mkPolar = lift2 (C.mkPolar :: Exp a -> Exp a -> Complex (Exp a))++-- | @'cis' t@ is a complex value with magnitude @1@ and phase @t@ (modulo+-- @2*'pi'@).+--+cis :: forall a. Floating a => Exp a -> Exp (Complex a)+cis = lift1 (C.cis :: Exp a -> Complex (Exp a))++-- | Return the real part of a complex number+--+real :: Elt a => Exp (Complex a) -> Exp a+real (r ::+ _) = r++-- | Return the imaginary part of a complex number+--+imag :: Elt a => Exp (Complex a) -> Exp a+imag (_ ::+ i) = i++-- | Return the complex conjugate of a complex number, defined as+--+-- > conjugate(Z) = X - iY+--+conjugate :: Num a => Exp (Complex a) -> Exp (Complex a)+conjugate z = real z ::+ (- imag z)+
+ src/Data/Array/Accelerate/Data/Either.hs view
@@ -0,0 +1,142 @@+{-# LANGUAGE BlockArguments #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE ViewPatterns #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- |+-- Module : Data.Array.Accelerate.Data.Either+-- Copyright : [2018..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- @since 1.2.0.0+--++module Data.Array.Accelerate.Data.Either (++ Either(..), pattern Left_, pattern Right_,+ either, isLeft, isRight, fromLeft, fromRight, lefts, rights,++) where++import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.Language+import Data.Array.Accelerate.Lift+import Data.Array.Accelerate.Pattern.Either+import Data.Array.Accelerate.Prelude+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Array ( Array, Vector )+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Sugar.Shape ( Shape, Slice, (:.) )+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.Classes.Eq+import Data.Array.Accelerate.Classes.Ord++import Data.Array.Accelerate.Control.Monad+import Data.Array.Accelerate.Data.Functor+import Data.Array.Accelerate.Data.Monoid+import Data.Array.Accelerate.Data.Semigroup++import Data.Either ( Either(..) )+import Prelude ( (.), ($) )+++-- | Return 'True' if the argument is a 'Left'-value+--+isLeft :: (Elt a, Elt b) => Exp (Either a b) -> Exp Bool+isLeft = not . isRight++-- | Return 'True' if the argument is a 'Right'-value+--+isRight :: (Elt a, Elt b) => Exp (Either a b) -> Exp Bool+isRight (Exp e) = Exp $ SmartExp $ (SmartExp $ Prj PairIdxLeft e) `Pair` SmartExp Nil+ -- TLM: This is a sneaky hack because we know that the tag bits for Right+ -- and True are identical.++-- | The 'fromLeft' function extracts the element out of the 'Left' constructor.+-- If the argument was actually 'Right', you will get an undefined value+-- instead.+--+fromLeft :: (Elt a, Elt b) => Exp (Either a b) -> Exp a+fromLeft (Exp e) = Exp $ SmartExp $ Prj PairIdxRight $ SmartExp $ Prj PairIdxLeft $ SmartExp $ Prj PairIdxRight e++-- | The 'fromRight' function extracts the element out of the 'Right'+-- constructor. If the argument was actually 'Left', you will get an undefined+-- value instead.+--+fromRight :: (Elt a, Elt b) => Exp (Either a b) -> Exp b+fromRight (Exp e) = Exp $ SmartExp $ Prj PairIdxRight $ SmartExp $ Prj PairIdxRight e++-- | The 'either' function performs case analysis on the 'Either' type. If the+-- value is @'Left' a@, apply the first function to @a@; if it is @'Right' b@,+-- apply the second function to @b@.+--+either :: (Elt a, Elt b, Elt c) => (Exp a -> Exp c) -> (Exp b -> Exp c) -> Exp (Either a b) -> Exp c+either f g = match \case+ Left_ x -> f x+ Right_ x -> g x++-- | Extract from the array of 'Either' all of the 'Left' elements, together+-- with a segment descriptor indicating how many elements along each dimension+-- were returned.+--+lefts :: (Shape sh, Slice sh, Elt a, Elt b)+ => Acc (Array (sh:.Int) (Either a b))+ -> Acc (Vector a, Array sh Int)+lefts es = compact (map isLeft es) (map fromLeft es)++-- | Extract from the array of 'Either' all of the 'Right' elements, together+-- with a segment descriptor indicating how many elements along each dimension+-- were returned.+--+rights :: (Shape sh, Slice sh, Elt a, Elt b)+ => Acc (Array (sh:.Int) (Either a b))+ -> Acc (Vector b, Array sh Int)+rights es = compact (map isRight es) (map fromRight es)+++instance Elt a => Functor (Either a) where+ fmap f = either Left_ (Right_ . f)++instance Elt a => Monad (Either a) where+ return = Right_+ x >>= f = either Left_ f x++instance (Eq a, Eq b) => Eq (Either a b) where+ (==) = match go+ where+ go (Left_ x) (Left_ y) = x == y+ go (Right_ x) (Right_ y) = x == y+ go _ _ = False_++instance (Ord a, Ord b) => Ord (Either a b) where+ compare = match go+ where+ go (Left_ x) (Left_ y) = compare x y+ go (Right_ x) (Right_ y) = compare x y+ go Left_{} Right_{} = LT_+ go Right_{} Left_{} = GT_++instance (Elt a, Elt b) => Semigroup (Exp (Either a b)) where+ ex <> ey = isLeft ex ? ( ey, ex )++instance (Lift Exp a, Lift Exp b, Elt (Plain a), Elt (Plain b)) => Lift Exp (Either a b) where+ type Plain (Either a b) = Either (Plain a) (Plain b)+ lift (Left a) = Left_ (lift a)+ lift (Right b) = Right_ (lift b)+
+ src/Data/Array/Accelerate/Data/Fold.hs view
@@ -0,0 +1,162 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE TypeOperators #-}+-- |+-- Module : Data.Array.Accelerate.Data.Fold+-- Copyright : [2016..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- Combine folds in 'Applicative' style to generate multiple results with+-- a single pass over the array. Based on Max Rabkin's "Beautiful Folding" [1]+-- and talks by Gabriel Gonzalez [2].+--+-- 1. <http://squing.blogspot.com/2008/11/beautiful-folding.html>+-- 2. <https://www.youtube.com/watch?v=6a5Ti0r8Q2s>+--++module Data.Array.Accelerate.Data.Fold (++ Fold(..), runFold,++) where++import Data.Array.Accelerate.Classes.Floating as A+import Data.Array.Accelerate.Classes.Fractional as A+import Data.Array.Accelerate.Classes.Num as A+import Data.Array.Accelerate.Data.Monoid+import Data.Array.Accelerate.Language as A+import Data.Array.Accelerate.Lift+import Data.Array.Accelerate.Smart ( Acc, Exp, constant )+import Data.Array.Accelerate.Sugar.Array+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Sugar.Shape++import Prelude hiding ( sum, product, length )+import Control.Applicative as P+import qualified Prelude as P+++-- | 'Fold' describes how to process data of some 'i'nput type into some+-- 'o'utput type, via a reduction using some intermediate Monoid 'w'. For+-- example, both 'sum' and 'length' below use the 'Sum' monoid:+--+-- > sum = Fold (lift . Sum) (getSum . unlift)+-- > length = Fold (\_ -> 1) (getSum . unlift)+--+-- The key is that 'Fold's can be combined using 'Applicative' in order to+-- produce multiple outputs from a /single/ reduction of the array. For example:+--+-- > average = (/) <$> sum <*> length+--+-- This computes both the sum of the array as well as its length in a single+-- traversal, then combines both results to compute the average.+--+-- Because 'Fold' has some numeric instances, this can also be defined more+-- succinctly as:+--+-- > average = sum / length+--+-- A more complex example:+--+-- > sumOfSquares = Fold (lift . Sum . (^2)) (getSum . unlift)+-- > standardDeviation = sqrt ((sumOfSquares / length) - (sum / length) ^ 2)+--+-- These will all execute with a single reduction kernel and a single map to+-- summarise (combine) the results.+--+data Fold i o where+ Fold :: (Elt w, Monoid (Exp w))+ => (i -> Exp w) -- transform input element into internal monoid type+ -> (Exp w -> o) -- summarise the reduction to retrieve the final result+ -> Fold i o++-- | Apply a 'Fold' to an array.+--+runFold+ :: (Shape sh, Elt i, Elt o)+ => Fold (Exp i) (Exp o)+ -> Acc (Array (sh:.Int) i)+ -> Acc (Array sh o)+runFold (Fold tally summarise) is+ = A.map summarise+ $ A.fold mappend mempty+ $ A.map tally is+++-- sum :: A.Num e => Fold (Exp e) (Exp e)+-- sum = Fold (lift . Sum) (getSum . unlift)++-- product :: A.Num e => Fold (Exp e) (Exp e)+-- product = Fold (lift . Product) (getProduct . unlift)++-- length :: A.Num i => Fold (Exp e) (Exp i)+-- length = Fold (\_ -> 1) (getSum . unlift)+++-- combine2 :: (Elt a, Elt b) => Exp a -> Exp b -> Exp (a,b)+-- combine2 a b = lift (a,b)++-- combine3 :: (Elt a, Elt b, Elt c) => Exp a -> Exp b -> Exp c -> Exp (a,b,c)+-- combine3 a b c = lift (a,b,c)++-- combine4 :: (Elt a, Elt b, Elt c, Elt d) => Exp a -> Exp b -> Exp c -> Exp d -> Exp (a,b,c,d)+-- combine4 a b c d = lift (a,b,c,d)++-- combine5 :: (Elt a, Elt b, Elt c, Elt d, Elt e) => Exp a -> Exp b -> Exp c -> Exp d -> Exp e -> Exp (a,b,c,d,e)+-- combine5 a b c d e = lift (a,b,c,d,e)+++-- Instances for 'Fold'+-- --------------------++instance P.Functor (Fold i) where+ fmap k (Fold tally summarise) = Fold tally (k . summarise)++instance P.Applicative (Fold i) where+ pure o = Fold (\_ -> constant ()) (\_ -> o)+ Fold tF sF <*> Fold tX sX = Fold tally summarise+ where+ tally i = lift (tF i, tX i)+ summarise t = let (mF, mX) = unlift t+ in sF mF (sX mX)++instance A.Num b => P.Num (Fold a (Exp b)) where+ (+) = liftA2 (+)+ (-) = liftA2 (-)+ (*) = liftA2 (*)+ negate = fmap negate+ abs = fmap abs+ signum = fmap signum+ fromInteger n = pure (A.fromInteger n)++instance A.Fractional b => P.Fractional (Fold a (Exp b)) where+ (/) = liftA2 (/)+ recip = fmap recip+ fromRational n = pure (A.fromRational n)++instance A.Floating b => P.Floating (Fold a (Exp b)) where+ pi = pure pi+ sin = fmap sin+ cos = fmap cos+ tan = fmap tan+ asin = fmap asin+ acos = fmap acos+ atan = fmap atan+ sinh = fmap sinh+ cosh = fmap cosh+ tanh = fmap tanh+ asinh = fmap asinh+ acosh = fmap acosh+ atanh = fmap atanh+ exp = fmap exp+ sqrt = fmap sqrt+ log = fmap log+ (**) = liftA2 (**)+ logBase = liftA2 logBase+
+ src/Data/Array/Accelerate/Data/Functor.hs view
@@ -0,0 +1,95 @@+{-# LANGUAGE RebindableSyntax #-}+-- |+-- Module : Data.Array.Accelerate.Data.Functor+-- Copyright : [2018..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- A functor performs a uniform action over a parameterised type+--+-- This is essentially the same as the standard Haskell 'Data.Functor' class,+-- lifted to Accelerate 'Exp' terms.+--+-- @since 1.2.0.0+--++module Data.Array.Accelerate.Data.Functor (++ Functor(..),+ (<$>),+ ($>),+ void,++) where++import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Lift+import Data.Array.Accelerate.Smart++import Data.Monoid+import Data.Semigroup+import Prelude ( (.), const, flip )+++-- | The 'Functor' class is used for scalar types which can be mapped over.+-- Instances of 'Functor' should satisfy the following laws:+--+-- > fmap id == id+-- > fmap (f . g) == fmap f . fmap g+--+class Functor f where+ fmap :: (Elt a, Elt b, Elt (f a), Elt (f b)) => (Exp a -> Exp b) -> Exp (f a) -> Exp (f b)++ -- | Replace all locations in the input with the same value. The default+ -- definition is @fmap . const@, but this may be overridden with a more+ -- efficient version.+ --+ infixl 4 <$+ (<$) :: (Elt a, Elt b, Elt (f a), Elt (f b)) => Exp a -> Exp (f b) -> Exp (f a)+ (<$) = fmap . const+++-- | An infix synonym for 'fmap'+--+-- The name of this operator is an allusion to 'Prelude.$'. Note the+-- similarities between their types:+--+-- > ($) :: (Exp a -> Exp b) -> Exp a -> Exp b+-- > (<$>) :: Functor f => (Exp a -> Exp b) -> Exp (f a) -> Exp (f b)+--+-- Whereas 'Prelude.$' is function application, '<$>' is function application+-- lifted over a 'Functor'.+--+infixl 4 <$>+(<$>) :: (Functor f, Elt a, Elt b, Elt (f a), Elt (f b)) => (Exp a -> Exp b) -> Exp (f a) -> Exp (f b)+(<$>) = fmap+++-- | A flipped version of '(<$)'.+--+infixl 4 $>+($>) :: (Functor f, Elt a, Elt b, Elt (f a), Elt (f b)) => Exp (f a) -> Exp b -> Exp (f b)+($>) = flip (<$)+++-- | @'void' value@ discards or ignores the result of evaluation.+--+void :: (Functor f, Elt a, Elt (f a), Elt (f ())) => Exp (f a) -> Exp (f ())+void x = constant () <$ x+++instance Functor Sum where+ fmap f = lift1 (fmap f)++instance Functor Product where+ fmap f = lift1 (fmap f)++instance Functor Min where+ fmap f = lift1 (fmap f)++instance Functor Max where+ fmap f = lift1 (fmap f)+
+ src/Data/Array/Accelerate/Data/Maybe.hs view
@@ -0,0 +1,145 @@+{-# LANGUAGE BlockArguments #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE ViewPatterns #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- |+-- Module : Data.Array.Accelerate.Data.Maybe+-- Copyright : [2018..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- @since 1.2.0.0+--++module Data.Array.Accelerate.Data.Maybe (++ Maybe(..), pattern Nothing_, pattern Just_,+ maybe, isJust, isNothing, fromMaybe, fromJust, justs,++) where++import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.Language+import Data.Array.Accelerate.Lift+import Data.Array.Accelerate.Pattern.Maybe+import Data.Array.Accelerate.Prelude+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Array ( Array, Vector )+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Sugar.Shape ( Shape, Slice, (:.) )+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.Classes.Eq+import Data.Array.Accelerate.Classes.Ord++import Data.Array.Accelerate.Control.Monad+import Data.Array.Accelerate.Data.Functor+import Data.Array.Accelerate.Data.Monoid+import Data.Array.Accelerate.Data.Semigroup++import Data.Function ( (&) )+import Data.Maybe ( Maybe(..) )+import Prelude ( ($), (.) )+++-- | Returns 'True' if the argument is 'Nothing'+--+isNothing :: Elt a => Exp (Maybe a) -> Exp Bool+isNothing = not . isJust++-- | Returns 'True' if the argument is of the form @Just _@+--+isJust :: Elt a => Exp (Maybe a) -> Exp Bool+isJust (Exp x) = Exp $ SmartExp $ (SmartExp $ Prj PairIdxLeft x) `Pair` SmartExp Nil+ -- TLM: This is a sneaky hack because we know that the tag bits for Just+ -- and True are identical.++-- | The 'fromMaybe' function takes a default value and a 'Maybe' value. If the+-- 'Maybe' is 'Nothing', the default value is returned; otherwise, it returns+-- the value contained in the 'Maybe'.+--+fromMaybe :: Elt a => Exp a -> Exp (Maybe a) -> Exp a+fromMaybe d = match \case+ Nothing_ -> d+ Just_ x -> x++-- | The 'fromJust' function extracts the element out of the 'Just' constructor.+-- If the argument was actually 'Nothing', you will get an undefined value+-- instead.+--+fromJust :: Elt a => Exp (Maybe a) -> Exp a+fromJust (Exp x) = Exp $ SmartExp (PairIdxRight `Prj` SmartExp (PairIdxRight `Prj` x))++-- | The 'maybe' function takes a default value, a function, and a 'Maybe'+-- value. If the 'Maybe' value is nothing, the default value is returned;+-- otherwise, it applies the function to the value inside the 'Just' and returns+-- the result+--+maybe :: (Elt a, Elt b) => Exp b -> (Exp a -> Exp b) -> Exp (Maybe a) -> Exp b+maybe d f = match \case+ Nothing_ -> d+ Just_ x -> f x++-- | Extract from an array all of the 'Just' values, together with a segment+-- descriptor indicating how many elements along each dimension were returned.+--+justs :: (Shape sh, Slice sh, Elt a)+ => Acc (Array (sh:.Int) (Maybe a))+ -> Acc (Vector a, Array sh Int)+justs xs = compact (map isJust xs) (map fromJust xs)+++instance Functor Maybe where+ fmap f = match \case+ Nothing_ -> Nothing_+ Just_ x -> Just_ (f x)++instance Monad Maybe where+ return = Just_+ mx >>= f = mx & match \case+ Nothing_ -> Nothing_+ Just_ x -> f x++instance Eq a => Eq (Maybe a) where+ (==) = match go+ where+ go Nothing_ Nothing_ = True_+ go (Just_ x) (Just_ y) = x == y+ go _ _ = False_++instance Ord a => Ord (Maybe a) where+ compare = match go+ where+ go (Just_ x) (Just_ y) = compare x y+ go Nothing_ Nothing_ = EQ_+ go Nothing_ Just_{} = LT_+ go Just_{} Nothing_{} = GT_++instance (Monoid (Exp a), Elt a) => Monoid (Exp (Maybe a)) where+ mempty = Nothing_++instance (Semigroup (Exp a), Elt a) => Semigroup (Exp (Maybe a)) where+ ma <> mb = cond (isNothing ma) mb+ $ cond (isNothing mb) ma+ $ lift (Just (fromJust ma <> fromJust mb))++instance (Lift Exp a, Elt (Plain a)) => Lift Exp (Maybe a) where+ type Plain (Maybe a) = Maybe (Plain a)+ lift Nothing = Nothing_+ lift (Just a) = Just_ (lift a)+
+ src/Data/Array/Accelerate/Data/Monoid.hs view
@@ -0,0 +1,195 @@+{-# LANGUAGE BlockArguments #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE ViewPatterns #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+#if __GLASGOW_HASKELL__ >= 806+{-# LANGUAGE UndecidableInstances #-}+#endif+-- |+-- Module : Data.Array.Accelerate.Data.Monoid+-- Copyright : [2016..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- Monoid instances for Accelerate+--+-- @since 1.2.0.0+--++module Data.Array.Accelerate.Data.Monoid (++ Monoid(..), (<>),++ Sum(..), pattern Sum_,+ Product(..), pattern Product_,++) where++import Data.Array.Accelerate.Classes.Bounded+import Data.Array.Accelerate.Classes.Eq+import Data.Array.Accelerate.Classes.Num+import Data.Array.Accelerate.Classes.Ord+import Data.Array.Accelerate.Data.Semigroup ()+import Data.Array.Accelerate.Language+import Data.Array.Accelerate.Lift+import Data.Array.Accelerate.Pattern+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Type+import Data.Array.Accelerate.Prelude ( match )++import Data.Function+import Data.Monoid hiding ( (<>) )+import Data.Semigroup+import qualified Prelude as P+++-- Sum: Monoid under addition+-- --------------------------++pattern Sum_ :: Elt a => Exp a -> Exp (Sum a)+pattern Sum_ x = Pattern x+{-# COMPLETE Sum_ #-}++instance Elt a => Elt (Sum a)++instance (Lift Exp a, Elt (Plain a)) => Lift Exp (Sum a) where+ type Plain (Sum a) = Sum (Plain a)+ lift (Sum a) = Sum_ (lift a)++instance Elt a => Unlift Exp (Sum (Exp a)) where+ unlift (Sum_ a) = Sum a++instance Bounded a => P.Bounded (Exp (Sum a)) where+ minBound = Sum_ minBound+ maxBound = Sum_ maxBound++instance Num a => P.Num (Exp (Sum a)) where+ (+) = lift2 ((+) :: Sum (Exp a) -> Sum (Exp a) -> Sum (Exp a))+ (-) = lift2 ((-) :: Sum (Exp a) -> Sum (Exp a) -> Sum (Exp a))+ (*) = lift2 ((*) :: Sum (Exp a) -> Sum (Exp a) -> Sum (Exp a))+ negate = lift1 (negate :: Sum (Exp a) -> Sum (Exp a))+ signum = lift1 (signum :: Sum (Exp a) -> Sum (Exp a))+ abs = lift1 (signum :: Sum (Exp a) -> Sum (Exp a))+ fromInteger x = lift (P.fromInteger x :: Sum (Exp a))++instance Eq a => Eq (Sum a) where+ (==) = lift2 ((==) `on` getSum)+ (/=) = lift2 ((/=) `on` getSum)++instance Ord a => Ord (Sum a) where+ (<) = lift2 ((<) `on` getSum)+ (>) = lift2 ((>) `on` getSum)+ (<=) = lift2 ((<=) `on` getSum)+ (>=) = lift2 ((>=) `on` getSum)+ min x y = Sum_ $ lift2 (min `on` getSum) x y+ max x y = Sum_ $ lift2 (max `on` getSum) x y++instance Num a => Monoid (Exp (Sum a)) where+ mempty = 0++-- | @since 1.2.0.0+instance Num a => Semigroup (Exp (Sum a)) where+ (<>) = (+)+ stimes n (Sum_ x) = Sum_ $ P.fromIntegral n * x+++-- Product: Monoid under multiplication+-- ------------------------------------++pattern Product_ :: Elt a => Exp a -> Exp (Product a)+pattern Product_ x = Pattern x+{-# COMPLETE Product_ #-}++instance Elt a => Elt (Product a)++instance (Lift Exp a, Elt (Plain a)) => Lift Exp (Product a) where+ type Plain (Product a) = Product (Plain a)+ lift (Product a) = Product_ (lift a)++instance Elt a => Unlift Exp (Product (Exp a)) where+ unlift (Product_ a) = Product a++instance Bounded a => P.Bounded (Exp (Product a)) where+ minBound = Product_ minBound+ maxBound = Product_ maxBound++instance Num a => P.Num (Exp (Product a)) where+ (+) = lift2 ((+) :: Product (Exp a) -> Product (Exp a) -> Product (Exp a))+ (-) = lift2 ((-) :: Product (Exp a) -> Product (Exp a) -> Product (Exp a))+ (*) = lift2 ((*) :: Product (Exp a) -> Product (Exp a) -> Product (Exp a))+ negate = lift1 (negate :: Product (Exp a) -> Product (Exp a))+ signum = lift1 (signum :: Product (Exp a) -> Product (Exp a))+ abs = lift1 (signum :: Product (Exp a) -> Product (Exp a))+ fromInteger x = lift (P.fromInteger x :: Product (Exp a))++instance Eq a => Eq (Product a) where+ (==) = lift2 ((==) `on` getProduct)+ (/=) = lift2 ((/=) `on` getProduct)++instance Ord a => Ord (Product a) where+ (<) = lift2 ((<) `on` getProduct)+ (>) = lift2 ((>) `on` getProduct)+ (<=) = lift2 ((<=) `on` getProduct)+ (>=) = lift2 ((>=) `on` getProduct)+ min x y = Product_ $ lift2 (min `on` getProduct) x y+ max x y = Product_ $ lift2 (max `on` getProduct) x y++instance Num a => Monoid (Exp (Product a)) where+ mempty = 1++-- | @since 1.2.0.0+instance Num a => Semigroup (Exp (Product a)) where+ (<>) = (*)+ stimes n (Product_ x) = Product_ $ x ^ (P.fromIntegral n :: Exp Int)+++-- Instances for unit and tuples+-- -----------------------------++instance Monoid (Exp ()) where+ mempty = constant ()++instance (Elt a, Elt b, Monoid (Exp a), Monoid (Exp b)) => Monoid (Exp (a,b)) where+ mempty = T2 mempty mempty++instance (Elt a, Elt b, Elt c, Monoid (Exp a), Monoid (Exp b), Monoid (Exp c)) => Monoid (Exp (a,b,c)) where+ mempty = T3 mempty mempty mempty++instance (Elt a, Elt b, Elt c, Elt d, Monoid (Exp a), Monoid (Exp b), Monoid (Exp c), Monoid (Exp d)) => Monoid (Exp (a,b,c,d)) where+ mempty = T4 mempty mempty mempty mempty++instance (Elt a, Elt b, Elt c, Elt d, Elt e, Monoid (Exp a), Monoid (Exp b), Monoid (Exp c), Monoid (Exp d), Monoid (Exp e)) => Monoid (Exp (a,b,c,d,e)) where+ mempty = T5 mempty mempty mempty mempty mempty+++-- Lexicographical ordering+-- ------------------------++-- | @since 1.4.0.0+instance Semigroup (Exp Ordering) where+ x <> y = x & match \case+ LT_ -> LT_+ EQ_ -> y+ GT_ -> GT_++ stimes n x = case P.compare n 0 of+ LT -> P.errorWithoutStackTrace "stimes: Exp Ordering, negative multiplier"+ EQ -> EQ_+ GT -> x++-- | @since 1.4.0.0+instance Monoid (Exp Ordering) where+ mempty = EQ_
+ src/Data/Array/Accelerate/Data/Ratio.hs view
@@ -0,0 +1,141 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MonoLocalBinds #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE RebindableSyntax #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE UndecidableInstances #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- |+-- Module : Data.Array.Accelerate.Data.Ratio+-- Copyright : [2019..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- Standard functions on rational numbers+--+-- @since 1.3.0.0+--++module Data.Array.Accelerate.Data.Ratio (++ Ratio, (%),+ pattern (:%), numerator, denominator,++) where++import Data.Array.Accelerate.Language+import Data.Array.Accelerate.Pattern+import Data.Array.Accelerate.Prelude+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.Classes.Enum+import Data.Array.Accelerate.Classes.Eq+import Data.Array.Accelerate.Classes.Fractional+import Data.Array.Accelerate.Classes.FromIntegral+import Data.Array.Accelerate.Classes.Integral+import Data.Array.Accelerate.Classes.Num+import Data.Array.Accelerate.Classes.Ord+import Data.Array.Accelerate.Classes.RealFrac+import Data.Array.Accelerate.Classes.ToFloating++import Text.Printf+import Data.Ratio ( Ratio )+import Prelude ( ($), String, error, unlines )+import qualified Data.Ratio as P+import qualified Prelude as P+++instance Elt a => Elt (Ratio a)++pattern (:%) :: Elt a => Exp a -> Exp a -> Exp (Ratio a)+pattern (:%) { numerator, denominator } = Pattern (numerator, denominator)+{-# COMPLETE (:%) #-}+++-- | 'reduce' is a subsidiary function used only in this module. It normalises+-- a ratio by dividing both numerator and denominator by their greatest common+-- divisor.+--+reduce :: Integral a => Exp a -> Exp a -> Exp (Ratio a)+reduce x y =+ if y == 0+ then infinity+ else let d = gcd x y+ in (x `quot` d) :% (y `quot` d)++-- | Form the ratio of two integral numbers+--+infixl 7 %+(%) :: Integral a => Exp a -> Exp a -> Exp (Ratio a)+x % y = reduce (x * signum y) (abs y)++infinity :: Integral a => Exp (Ratio a)+infinity = 1 :% 0+++-- Instances+-- ---------++instance Integral a => Eq (Ratio a) where+ (x :% y) == (z :% w) = x == z && y == w+ (x :% y) /= (z :% w) = x /= z || y /= w++instance Integral a => Ord (Ratio a) where+ (x :% y) <= (z :% w) = x * w <= z * y+ (x :% y) < (z :% w) = x * w < z * y++instance Integral a => P.Num (Exp (Ratio a)) where+ (x :% y) + (z :% w) = reduce (x*w + z*y) (y*w)+ (x :% y) - (z :% w) = reduce (x*w - z*y) (y*w)+ (x :% y) * (z :% w) = reduce (x * z) (y * w)+ negate (x:%y) = (-x) :% y+ abs (x:%y) = abs x :% y+ signum (x:%_) = signum x :% 1+ fromInteger x = fromInteger x :% 1++instance Integral a => P.Fractional (Exp (Ratio a)) where+ (x :% y) / (z :% w) = (x*w) % (y*z)+ recip (x :% y) =+ if x == 0 then infinity else+ if x < 0 then negate y :% negate x+ else y :% x+ fromRational r = fromInteger (P.numerator r) % fromInteger (P.denominator r)++instance (Integral a, FromIntegral a Int64) => RealFrac (Ratio a) where+ properFraction (x :% y) =+ let (q,r) = quotRem x y+ in (fromIntegral (fromIntegral q :: Exp Int64), r :% y)+++instance (Integral a, ToFloating a b) => ToFloating (Ratio a) b where+ toFloating (x :% y) =+ let x' :% y' = reduce x y+ in toFloating x' / toFloating y'++instance (FromIntegral a b, Integral b) => FromIntegral a (Ratio b) where+ fromIntegral x = fromIntegral x :% 1++instance Integral a => P.Enum (Exp (Ratio a)) where+ succ x = x + 1+ pred x = x - 1+ toEnum = preludeError "Enum" "toEnum"+ fromEnum = preludeError "Enum" "fromEnum"+++preludeError :: String -> String -> a+preludeError x y+ = error+ $ unlines [ printf "Prelude.%s is not supported for Accelerate types" y+ , ""+ , printf "These Prelude.%s instances are present only to fulfil superclass" x+ , "constraints for subsequent classes in the standard Haskell numeric hierarchy."+ ]+
+ src/Data/Array/Accelerate/Data/Semigroup.hs view
@@ -0,0 +1,171 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE RebindableSyntax #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE ViewPatterns #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+#if __GLASGOW_HASKELL__ >= 806+{-# LANGUAGE UndecidableInstances #-}+#endif+-- |+-- Module : Data.Array.Accelerate.Data.Semigroup+-- Copyright : [2018..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- Semigroup instances for Accelerate+--+-- @since 1.2.0.0+--++module Data.Array.Accelerate.Data.Semigroup (++ Semigroup(..),++ Min(..), pattern Min_,+ Max(..), pattern Max_,++) where++import Data.Array.Accelerate.Classes.Bounded+import Data.Array.Accelerate.Classes.Eq+import Data.Array.Accelerate.Classes.Num+import Data.Array.Accelerate.Classes.Ord+import Data.Array.Accelerate.Lift+import Data.Array.Accelerate.Pattern+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Elt++import Data.Function+import Data.Monoid ( Monoid(..) )+import Data.Semigroup+import qualified Prelude as P+++pattern Min_ :: Elt a => Exp a -> Exp (Min a)+pattern Min_ x = Pattern x+{-# COMPLETE Min_ #-}++instance Elt a => Elt (Min a)++instance (Lift Exp a, Elt (Plain a)) => Lift Exp (Min a) where+ type Plain (Min a) = Min (Plain a)+ lift (Min a) = Min_ (lift a)++instance Elt a => Unlift Exp (Min (Exp a)) where+ unlift (Min_ a) = Min a++instance Bounded a => P.Bounded (Exp (Min a)) where+ minBound = lift $ Min (minBound :: Exp a)+ maxBound = lift $ Min (maxBound :: Exp a)++instance Num a => P.Num (Exp (Min a)) where+ (+) = lift2 ((+) :: Min (Exp a) -> Min (Exp a) -> Min (Exp a))+ (-) = lift2 ((-) :: Min (Exp a) -> Min (Exp a) -> Min (Exp a))+ (*) = lift2 ((*) :: Min (Exp a) -> Min (Exp a) -> Min (Exp a))+ negate = lift1 (negate :: Min (Exp a) -> Min (Exp a))+ signum = lift1 (signum :: Min (Exp a) -> Min (Exp a))+ abs = lift1 (signum :: Min (Exp a) -> Min (Exp a))+ fromInteger x = lift (P.fromInteger x :: Min (Exp a))++instance Eq a => Eq (Min a) where+ (==) = lift2 ((==) `on` getMin)+ (/=) = lift2 ((/=) `on` getMin)++instance Ord a => Ord (Min a) where+ (<) = lift2 ((<) `on` getMin)+ (>) = lift2 ((>) `on` getMin)+ (<=) = lift2 ((<=) `on` getMin)+ (>=) = lift2 ((>=) `on` getMin)+ min x y = lift . Min $ lift2 (min `on` getMin) x y+ max x y = lift . Min $ lift2 (max `on` getMin) x y++instance Ord a => Semigroup (Exp (Min a)) where+ x <> y = lift . Min $ lift2 (min `on` getMin) x y+ stimes = stimesIdempotent++instance (Ord a, Bounded a) => Monoid (Exp (Min a)) where+ mempty = maxBound+ mappend = (<>)+++pattern Max_ :: Elt a => Exp a -> Exp (Max a)+pattern Max_ x = Pattern x+{-# COMPLETE Max_ #-}++instance Elt a => Elt (Max a)++instance (Lift Exp a, Elt (Plain a)) => Lift Exp (Max a) where+ type Plain (Max a) = Max (Plain a)+ lift (Max a) = Max_ (lift a)++instance Elt a => Unlift Exp (Max (Exp a)) where+ unlift (Max_ a) = Max a++instance Bounded a => P.Bounded (Exp (Max a)) where+ minBound = Max_ minBound+ maxBound = Max_ maxBound++instance Num a => P.Num (Exp (Max a)) where+ (+) = lift2 ((+) :: Max (Exp a) -> Max (Exp a) -> Max (Exp a))+ (-) = lift2 ((-) :: Max (Exp a) -> Max (Exp a) -> Max (Exp a))+ (*) = lift2 ((*) :: Max (Exp a) -> Max (Exp a) -> Max (Exp a))+ negate = lift1 (negate :: Max (Exp a) -> Max (Exp a))+ signum = lift1 (signum :: Max (Exp a) -> Max (Exp a))+ abs = lift1 (signum :: Max (Exp a) -> Max (Exp a))+ fromInteger x = lift (P.fromInteger x :: Max (Exp a))++instance Eq a => Eq (Max a) where+ (==) = lift2 ((==) `on` getMax)+ (/=) = lift2 ((/=) `on` getMax)++instance Ord a => Ord (Max a) where+ (<) = lift2 ((<) `on` getMax)+ (>) = lift2 ((>) `on` getMax)+ (<=) = lift2 ((<=) `on` getMax)+ (>=) = lift2 ((>=) `on` getMax)+ min x y = Max_ $ lift2 (min `on` getMax) x y+ max x y = Max_ $ lift2 (max `on` getMax) x y++instance Ord a => Semigroup (Exp (Max a)) where+ x <> y = Max_ $ lift2 (max `on` getMax) x y+ stimes = stimesIdempotent++instance (Ord a, Bounded a) => Monoid (Exp (Max a)) where+ mempty = minBound+ mappend = (<>)+++-- Instances for unit and tuples+-- -----------------------------++instance Semigroup (Exp ()) where+ _ <> _ = constant ()+ sconcat _ = constant ()+ stimes _ _ = constant ()++instance (Elt a, Elt b, Semigroup (Exp a), Semigroup (Exp b)) => Semigroup (Exp (a,b)) where+ (<>) = lift2 ((<>) :: (Exp a, Exp b) -> (Exp a, Exp b) -> (Exp a, Exp b))+ stimes n (unlift -> ((a,b) :: (Exp a, Exp b))) = lift (stimes n a, stimes n b)++instance (Elt a, Elt b, Elt c, Semigroup (Exp a), Semigroup (Exp b), Semigroup (Exp c)) => Semigroup (Exp (a,b,c)) where+ (<>) = lift2 ((<>) :: (Exp a, Exp b, Exp c) -> (Exp a, Exp b, Exp c) -> (Exp a, Exp b, Exp c))+ stimes n (unlift -> ((a,b,c) :: (Exp a, Exp b, Exp c))) = lift (stimes n a, stimes n b, stimes n c)++instance (Elt a, Elt b, Elt c, Elt d, Semigroup (Exp a), Semigroup (Exp b), Semigroup (Exp c), Semigroup (Exp d)) => Semigroup (Exp (a,b,c,d)) where+ (<>) = lift2 ((<>) :: (Exp a, Exp b, Exp c, Exp d) -> (Exp a, Exp b, Exp c, Exp d) -> (Exp a, Exp b, Exp c, Exp d))+ stimes n (unlift -> ((a,b,c,d) :: (Exp a, Exp b, Exp c, Exp d))) = lift (stimes n a, stimes n b, stimes n c, stimes n d)++instance (Elt a, Elt b, Elt c, Elt d, Elt e, Semigroup (Exp a), Semigroup (Exp b), Semigroup (Exp c), Semigroup (Exp d), Semigroup (Exp e)) => Semigroup (Exp (a,b,c,d,e)) where+ (<>) = lift2 ((<>) :: (Exp a, Exp b, Exp c, Exp d, Exp e) -> (Exp a, Exp b, Exp c, Exp d, Exp e) -> (Exp a, Exp b, Exp c, Exp d, Exp e))+ stimes n (unlift -> ((a,b,c,d,e) :: (Exp a, Exp b, Exp c, Exp d, Exp e))) = lift (stimes n a, stimes n b, stimes n c, stimes n d, stimes n e)+
+ src/Data/Array/Accelerate/Debug/Internal.hs view
@@ -0,0 +1,77 @@+{-# LANGUAGE CPP #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Debug.Internal+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- Embedded array processing language: internal debugging support. This module+-- provides functionality that is useful for developers of the library. It is+-- not meant for library users.+--++module Data.Array.Accelerate.Debug.Internal (++ debuggingIsEnabled,+ tracyIsEnabled,+ boundsChecksAreEnabled,+ -- unsafeChecksAreEnabled,+ internalChecksAreEnabled,++ module Debug,++) where++import Data.Array.Accelerate.Debug.Internal.Flags as Debug+import Data.Array.Accelerate.Debug.Internal.Graph as Debug+import Data.Array.Accelerate.Debug.Internal.Profile as Debug+import Data.Array.Accelerate.Debug.Internal.Stats as Debug+import Data.Array.Accelerate.Debug.Internal.Timed as Debug+import Data.Array.Accelerate.Debug.Internal.Trace as Debug+import Data.Array.Accelerate.Debug.Internal.Tracy as Debug+++{-# INLINE debuggingIsEnabled #-}+debuggingIsEnabled :: Bool+#ifdef ACCELERATE_DEBUG+debuggingIsEnabled = True+#else+debuggingIsEnabled = False+#endif++{-# INLINE tracyIsEnabled #-}+tracyIsEnabled :: Bool+#ifdef ACCELERATE_TRACY+tracyIsEnabled = True+#else+tracyIsEnabled = False+#endif++{-# INLINE boundsChecksAreEnabled #-}+boundsChecksAreEnabled :: Bool+#ifdef ACCELERATE_BOUNDS_CHECKS+boundsChecksAreEnabled = True+#else+boundsChecksAreEnabled = False+#endif++-- {-# INLINE unsafeChecksAreEnabled #-}+-- unsafeChecksAreEnabled :: Bool+-- #ifdef ACCELERATE_UNSAFE_CHECKS+-- unsafeChecksAreEnabled = True+-- #else+-- unsafeChecksAreEnabled = False+-- #endif++{-# INLINE internalChecksAreEnabled #-}+internalChecksAreEnabled :: Bool+#ifdef ACCELERATE_INTERNAL_CHECKS+internalChecksAreEnabled = True+#else+internalChecksAreEnabled = False+#endif+
+ src/Data/Array/Accelerate/Debug/Internal/Clock.hs view
@@ -0,0 +1,42 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE TemplateHaskell #-}+{-# OPTIONS_GHC -fobject-code #-}+-- |+-- Module : Data.Array.Accelerate.Debug.Internal.Clock+-- Copyright : [2016..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Debug.Internal.Clock+ where++import Language.Haskell.TH.Syntax+++-- SEE: [HLS and GHC IDE]+--+#ifndef __GHCIDE__++foreign import ccall unsafe "clock_gettime_monotonic_seconds" getMonotonicTime :: IO Double+foreign import ccall unsafe "clock_gettime_elapsed_seconds" getProgramTime :: IO Double++#else++getMonotonicTime :: IO Double+getMonotonicTime = undefined++getProgramTime :: IO Double+getProgramTime = undefined++#endif++-- SEE: [linking to .c files]+--+runQ $ do+ addForeignFilePath LangC "cbits/clock.c"+ return []
+ src/Data/Array/Accelerate/Debug/Internal/Flags.hs view
@@ -0,0 +1,246 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeOperators #-}+{-# OPTIONS_GHC -fno-warn-missing-signatures #-}+{-# OPTIONS_GHC -fno-warn-unused-imports #-}+{-# OPTIONS_GHC -fno-warn-unused-top-binds #-}+{-# OPTIONS_GHC -fobject-code #-} -- SEE: [linking to .c files]+-- |+-- Module : Data.Array.Accelerate.Debug.Internal.Flags+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- Option parsing for debug flags+--++module Data.Array.Accelerate.Debug.Internal.Flags (++ Value,+ getValue,+ setValue,++ Flag(..),+ seq_sharing, acc_sharing, exp_sharing, array_fusion, inplace, force_recomp,+ fast_math, fast_permute_const, debug, verbose, dump_phases, dump_sharing, dump_fusion,+ dump_simpl_stats, dump_simpl_iterations, dump_vectorisation, dump_dot,+ dump_simpl_dot, dump_gc, dump_gc_stats, dump_cc, dump_ld, dump_asm, dump_exec,+ dump_sched,++ getFlag,+ setFlag, setFlags,+ clearFlag, clearFlags,++ when,+ unless,++ __cmd_line_flags,++) where+++import Control.Monad.IO.Class ( MonadIO, liftIO )+import Data.Bits+import Data.Int+import Data.Word+import Foreign.Ptr+import Foreign.Storable+import Language.Haskell.TH.Syntax+import System.Directory+import System.FilePath+import qualified Control.Monad as M++newtype Flag = Flag Int+newtype Value = Value (Ptr Word32) -- see flags.c++-- We aren't using a "real" enum so that we can make use of the unused top+-- bits for other configuration options, not controlled by the command line+-- flags.+--+-- However, as there are currently no such special configuration options, the+-- bit hack complexity here is unnecessary. It's kept as an easter egg for+-- future maintainers.+--+instance Enum Flag where+ toEnum = Flag+ fromEnum (Flag x) = x++-- SEE: [layout of command line options bitfield]+instance Show Flag where+ show (Flag x) =+ case x of+ 0 -> "seq-sharing"+ 1 -> "acc-sharing"+ 2 -> "exp-sharing"+ 3 -> "fusion"+ 4 -> "inplace"+ 5 -> "fast-math"+ 6 -> "fast-permute-const"+ 7 -> "force-recomp"+ 8 -> "debug"+ 9 -> "verbose"+ 10 -> "dump-phases"+ 11 -> "dump-sharing"+ 12 -> "dump-fusion"+ 13 -> "dump-simpl-stats"+ 14 -> "dump-simpl-iterations"+ 15 -> "dump-vectorisation"+ 16 -> "dump-dot"+ 17 -> "dump-simpl-dot"+ 18 -> "dump-gc"+ 19 -> "dump-gc-stats"+ 20 -> "dump-cc"+ 21 -> "dump-ld"+ 22 -> "dump-asm"+ 23 -> "dump-exec"+ 24 -> "dump-sched"+ _ -> show x++-- | Conditional execution of a monadic debugging expression.+--+-- This does nothing unless the program is compiled in debug mode.+--+{-# INLINEABLE when #-}+when :: MonadIO m => Flag -> m () -> m ()+#if ACCELERATE_DEBUG+when f action = do+ yes <- liftIO $ getFlag f+ M.when yes action+#else+when _ _ = return ()+#endif+++-- | The opposite of 'when'.+--+-- This does nothing unless the program is compiled in debug mode.+--+{-# INLINEABLE unless #-}+unless :: MonadIO m => Flag -> m () -> m ()+#ifdef ACCELERATE_DEBUG+unless f action = do+ yes <- liftIO $ getFlag f+ M.unless yes action+#else+unless _ _ = return ()+#endif+++setValue :: Value -> Word32 -> IO ()+setValue (Value f) v = poke f v++getValue :: Value -> IO Word32+getValue (Value f) = peek f++getFlag :: Flag -> IO Bool+getFlag (Flag i) = do+ flags <- peek __cmd_line_flags+ return $! testBit flags i++setFlag :: Flag -> IO ()+setFlag (Flag i) = do+ flags <- peek __cmd_line_flags+ poke __cmd_line_flags (setBit flags i)++clearFlag :: Flag -> IO ()+clearFlag (Flag i) = do+ flags <- peek __cmd_line_flags+ poke __cmd_line_flags (clearBit flags i)++setFlags :: [Flag] -> IO ()+setFlags = mapM_ setFlag++clearFlags :: [Flag] -> IO ()+clearFlags = mapM_ clearFlag++-- notEnabled :: a+-- notEnabled = error $ unlines [ "Data.Array.Accelerate: Debugging options are disabled."+-- , "Reinstall package 'accelerate' with '-fdebug' to enable them." ]++-- Note: [HLS and GHC IDE]+--+-- HLS requires stubs because it does not process the 'addForeignFilePath'+-- calls when evaluating Template Haskell+--+-- > https://github.com/haskell/haskell-language-server/issues/365+--+#ifndef __GHCIDE__++-- Import the underlying flag variables. These are defined in the file+-- cbits/flags.h as a bitfield and initialised at program initialisation.+--+-- SEE: [layout of command line options bitfield]+-- SEE: [linking to .c files]+--+foreign import ccall "&__cmd_line_flags" __cmd_line_flags :: Ptr Word32++#else++__cmd_line_flags :: Ptr Word32+__cmd_line_flags = undefined++#endif++-- These @-f<blah>@ flags can be reversed with @-fno-<blah>@+--+-- SEE: [layout of command line options bitfield]+seq_sharing = Flag 0 -- recover sharing of sequence expressions+acc_sharing = Flag 1 -- recover sharing of array computations+exp_sharing = Flag 2 -- recover sharing of scalar expressions+array_fusion = Flag 3 -- fuse array expressions+inplace = Flag 4 -- allow (safe) in-place array updates+fast_math = Flag 5 -- use faster, less precise math library operations+fast_permute_const = Flag 6 -- allow non-atomic permute const for product types+force_recomp = Flag 7 -- force recompilation of array programs++-- These debugging flags are disable by default and are enabled with @-d<blah>@+--+debug = Flag 8 -- compile code with debugging symbols (-g)+verbose = Flag 9 -- be very chatty+dump_phases = Flag 10 -- print information about each phase of the compiler+dump_sharing = Flag 11 -- sharing recovery phase+dump_fusion = Flag 12 -- array fusion phase+dump_simpl_stats = Flag 13 -- statistics form fusion/simplification+dump_simpl_iterations = Flag 14 -- output from each simplifier iteration+dump_vectorisation = Flag 15 -- output from the vectoriser+dump_dot = Flag 16 -- generate dot output of the program+dump_simpl_dot = Flag 17 -- generate simplified dot output+dump_gc = Flag 18 -- trace garbage collector+dump_gc_stats = Flag 19 -- print final GC statistics+dump_cc = Flag 20 -- trace code generation & compilation+dump_ld = Flag 21 -- trace runtime linker+dump_asm = Flag 22 -- trace assembler+dump_exec = Flag 23 -- trace execution+dump_sched = Flag 24 -- trace scheduler+++-- Note: [linking to .c files]+--+-- We use Template Haskell to tell GHC which .c files need to be compiled+-- for a particular module, rather than relying on Cabal as is traditional.+-- Using Cabal:+--+-- * loading Accelerate into GHCi only works _after_ compiling the entire+-- package (which defeats the purpose), presumably because the .c files+-- are compiled last. This would often lead to errors such "can not find+-- symbol __cmd_line_flags" etc.+--+-- * Cabal would refuse to re-compile .c files when changing command+-- line flags, see: https://github.com/haskell/cabal/issues/4937+--+-- * Linking problems also prevented us from using Template Haskell in+-- some locations, because GHC was unable to load the project into the+-- interpreter to run the splices.+--+-- Note that for this fix to work in GHCi we also require modules using it+-- to be loaded as object code.+--+runQ $ do+ addForeignFilePath LangC "cbits/flags.c"+ addForeignFilePath LangC "cbits/getopt_long.c"+ return []+
+ src/Data/Array/Accelerate/Debug/Internal/Graph.hs view
@@ -0,0 +1,72 @@+{-# LANGUAGE CPP #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Debug.Internal.Graph+-- Copyright : [2008..2021] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Debug.Internal.Graph (++ dumpGraph++) where++import Data.Array.Accelerate.Pretty.Graphviz++import Control.Monad.Trans ( MonadIO )++#ifdef ACCELERATE_DEBUG+import Control.Exception ( bracket )+import Control.Monad.Trans ( liftIO )+import System.Directory ( getTemporaryDirectory, createDirectoryIfMissing )+import System.FilePath ( (</>) )+import System.IO ( Handle, openTempFile, hPutStrLn, hPrint, hClose, stderr )+import qualified Data.Array.Accelerate.Debug.Internal.Flags as Debug++#if defined(mingw32_HOST_OS)+import System.Win32.Process ( ProcessId )+#else+import System.Posix.Process ( getProcessID )+#endif+#endif++-- | Write a representation of the given input (a closed array expression or+-- function) to file in Graphviz dot format in the temporary directory.+--+{-# INLINEABLE dumpGraph #-}+dumpGraph :: (MonadIO m, PrettyGraph g) => g -> m ()+#ifdef ACCELERATE_DEBUG+dumpGraph g =+ liftIO $ do+ Debug.when Debug.dump_dot $ writeGraph Full g+ Debug.when Debug.dump_simpl_dot $ writeGraph Simple g+#else+dumpGraph _ = return ()+#endif++#ifdef ACCELERATE_DEBUG+writeGraph :: PrettyGraph g => Detail -> g -> IO ()+writeGraph simple g = do+ withTemporaryFile "acc.dot" $ \path hdl -> do+ hPrint hdl (ppGraph simple g)+ hPutStrLn stderr ("program graph: " ++ path)++withTemporaryFile :: String -> (FilePath -> Handle -> IO a) -> IO a+withTemporaryFile template go = do+ pid <- getProcessID+ tmp <- getTemporaryDirectory+ let dir = tmp </> "accelerate-" ++ show pid+ createDirectoryIfMissing True dir+ bracket (openTempFile dir template) (hClose . snd) (uncurry go)++#if defined(mingw32_HOST_OS)+getProcessID :: IO ProcessId+getProcessID = return 0xaaaa+#endif+#endif+
+ src/Data/Array/Accelerate/Debug/Internal/Profile.hs view
@@ -0,0 +1,189 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE TemplateHaskell #-}+{-# OPTIONS_GHC -fobject-code #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Debug.Internal.Profile+-- Copyright : [2016..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Debug.Internal.Profile (++ local_memory_alloc,+ local_memory_free,++ remote_memory_alloc, remote_memory_alloc_nursery,+ remote_memory_free, remote_memory_free_nursery,+ remote_memory_evict,++ memcpy_to_remote,+ memcpy_from_remote,++ emit_remote_gc,++) where++#ifdef ACCELERATE_TRACY+import Control.Monad+import qualified Data.Array.Accelerate.Debug.Internal.Tracy as Tracy+#endif++import Data.Atomic ( Atomic )+import qualified Data.Atomic as Atomic++import Data.Char+import Foreign.C.String+import Foreign.Ptr+import Language.Haskell.TH+import Language.Haskell.TH.Syntax++import GHC.Ptr+++-- Embed some string data into the constant section and grab a pointer+-- directly to it.+--+-- XXX: This only allows us to track a single nursery, but in reality it is+-- one per remote memory space. May or may not be useful to separate this.+--+runQ $ sequence+ [ sigD (mkName "___nursery") (conT ''CString)+ , valD (varP (mkName "___nursery")) (normalB (conE 'Ptr `appE` litE (stringPrimL (map (fromIntegral . ord) "nursery\0")))) []+ ]++-- Allocations in the local memory space+--+{-# INLINE local_memory_alloc #-}+{-# INLINE local_memory_free #-}+local_memory_alloc :: Ptr a -> Int -> IO ()+local_memory_free :: Ptr a -> IO ()+#ifndef ACCELERATE_TRACY+local_memory_alloc _ _ = return ()+local_memory_free _ = return ()+#else++local_memory_alloc _p n = do+ Tracy.emit_memory_alloc _p (fromIntegral n) 0+ void $ Atomic.add __total_bytes_allocated_local (fromIntegral n)++local_memory_free _p =+ Tracy.emit_memory_free _p 0+#endif+++-- Allocations in the remote memory space+--+{-# INLINE remote_memory_alloc #-}+{-# INLINE remote_memory_free #-}+{-# INLINE remote_memory_evict #-}+remote_memory_alloc :: CString -> Ptr a -> Int -> IO ()+remote_memory_free :: CString -> Ptr a -> IO ()+remote_memory_evict :: CString -> Ptr a -> Int -> IO ()+#ifndef ACCELERATE_TRACY+remote_memory_alloc _ _ _ = return ()+remote_memory_free _ _ = return ()+remote_memory_evict _ _ _ = return ()+#else+remote_memory_alloc _name _ptr bytes = do+ Tracy.emit_memory_alloc_named _ptr (fromIntegral bytes) 0 _name+ void $ Atomic.add __total_bytes_allocated_remote (fromIntegral bytes)++remote_memory_free _name _ptr = do+ Tracy.emit_memory_free_named _ptr 0 _name++remote_memory_evict name ptr bytes = do+ void $ Atomic.add __num_evictions 1+ void $ Atomic.add __total_bytes_evicted_from_remote (fromIntegral bytes)+ remote_memory_free name ptr+ memcpy_from_remote bytes+#endif++remote_memory_alloc_nursery :: Ptr a -> Int -> IO ()+remote_memory_free_nursery :: Ptr a -> IO ()+#ifndef ACCELERATE_TRACY+remote_memory_alloc_nursery _ _ = return ()+remote_memory_free_nursery _ = return ()+#else+remote_memory_alloc_nursery p n = Tracy.emit_memory_alloc_named p (fromIntegral n) 0 ___nursery+remote_memory_free_nursery p = Tracy.emit_memory_free_named p 0 ___nursery+#endif+++-- Data transfer between memory spaces+--+{-# INLINE memcpy_to_remote #-}+{-# INLINE memcpy_from_remote #-}+memcpy_to_remote :: Int -> IO ()+memcpy_from_remote :: Int -> IO ()+#ifndef ACCELERATE_TRACY+memcpy_to_remote _ = return ()+memcpy_from_remote _ = return ()+#else+memcpy_to_remote n = void $ Atomic.add __total_bytes_copied_to_remote (fromIntegral n)+memcpy_from_remote n = void $ Atomic.add __total_bytes_copied_from_remote (fromIntegral n)+#endif+++-- Performed a major GC of the remote memory space+--+{-# INLINE emit_remote_gc #-}+emit_remote_gc :: IO ()+#ifndef ACCELERATE_TRACY+emit_remote_gc = return ()+#else+emit_remote_gc = void $ Atomic.add __num_remote_gcs 1+#endif+++-- Monitoring variables+-- --------------------++-- SEE: [HLS and GHC IDE]+--+#ifndef __GHCIDE__++foreign import ccall "&__total_bytes_allocated_local" __total_bytes_allocated_local :: Atomic -- bytes allocated in the local (CPU) memory space+foreign import ccall "&__total_bytes_allocated_remote" __total_bytes_allocated_remote :: Atomic -- bytes allocated in the remote memory space (if it is separate, e.g. GPU)+foreign import ccall "&__total_bytes_copied_to_remote" __total_bytes_copied_to_remote :: Atomic -- bytes copied to the remote memory space+foreign import ccall "&__total_bytes_copied_from_remote" __total_bytes_copied_from_remote :: Atomic -- bytes copied from the remote memory space+foreign import ccall "&__total_bytes_evicted_from_remote" __total_bytes_evicted_from_remote :: Atomic -- total bytes copied from the remote due to evictions+foreign import ccall "&__num_remote_gcs" __num_remote_gcs :: Atomic -- number of times the remote memory space was forcibly garbage collected+foreign import ccall "&__num_evictions" __num_evictions :: Atomic -- number of LRU eviction events++#else++__total_bytes_allocated_local :: Atomic+__total_bytes_allocated_local = undefined++__total_bytes_allocated_remote :: Atomic+__total_bytes_allocated_remote = undefined++__total_bytes_copied_to_remote :: Atomic+__total_bytes_copied_to_remote = undefined++__total_bytes_copied_from_remote :: Atomic+__total_bytes_copied_from_remote = undefined++__total_bytes_evicted_from_remote :: Atomic+__total_bytes_evicted_from_remote = undefined++__num_remote_gcs :: Atomic+__num_remote_gcs = undefined++__num_evictions :: Atomic+__num_evictions = undefined++#endif++-- SEE: [linking to .c files]+--+runQ $ do+ addForeignFilePath LangC "cbits/monitoring.c"+ return []+
+ src/Data/Array/Accelerate/Debug/Internal/Stats.hs view
@@ -0,0 +1,253 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# OPTIONS_GHC -fno-warn-unused-binds #-}+{-# OPTIONS_GHC -fno-warn-unused-imports #-}+-- |+-- Module : Data.Array.Accelerate.Debug.Internal.Stats+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- Tick-count statistics collection of the compiler passes, for debugging+-- purposes.+--++module Data.Array.Accelerate.Debug.Internal.Stats (++ simplCount, resetSimplCount, dumpSimplStats,+ inline, ruleFired, knownBranch, caseElim, caseDefault, betaReduce, substitution, simplifierDone, fusionDone,++) where++import Data.Array.Accelerate.Debug.Internal.Flags+import Data.Array.Accelerate.Debug.Internal.Trace++import Data.Function ( on )+import Data.IORef+import Data.List ( groupBy, sortBy )+import Data.Map ( Map )+import Data.Ord ( comparing )+import Data.Text ( Text )+import Data.Text.Lazy.Builder+import Formatting+import Prettyprinter hiding ( annotate, Doc )+import Prettyprinter.Internal ( SimpleDocStream(..), textSpaces )+import Prettyprinter.Render.Util.Panic ( panicUncaughtFail )+import System.IO.Unsafe+import qualified Data.Map as Map+import qualified Prettyprinter as Pretty+++-- Recording statistics+-- --------------------++ruleFired, inline, knownBranch, caseElim, caseDefault, betaReduce, substitution :: Text -> a -> a+inline = annotate Inline+ruleFired = annotate RuleFired+knownBranch = annotate KnownBranch+caseElim = annotate CaseElim+caseDefault = annotate CaseDefault+betaReduce = annotate BetaReduce+substitution = annotate Substitution++simplifierDone, fusionDone :: a -> a+simplifierDone = tick SimplifierDone+fusionDone = tick FusionDone++-- Add an entry to the statistics counters+--+tick :: Tick -> a -> a+#ifdef ACCELERATE_DEBUG+{-# NOINLINE tick #-}+tick t expr = unsafeDupablePerformIO $ do+ modifyIORef' statistics (simplTick t)+ return expr+#else+{-# INLINE tick #-}+tick _ expr = expr+#endif++-- Add an entry to the statistics counters with an annotation+--+annotate :: (Id -> Tick) -> Text -> a -> a+annotate name ctx = tick (name (Id ctx))+++-- Simplifier counts+-- -----------------++data SimplStats+ = Simple {-# UNPACK #-} !Int -- when we don't want detailed stats++ | Detail {+ ticks :: {-# UNPACK #-} !Int, -- total ticks+ details :: !TickCount -- how many of each type+ }++instance Show SimplStats where+ show = show . pprSimplCount+++-- Stores the current statistics counters+--+{-# NOINLINE statistics #-}+statistics :: IORef SimplStats+statistics = unsafePerformIO $ newIORef =<< initSimplCount++-- Initialise the statistics counters. If we are dumping the stats+-- (-ddump-simpl-stats) record extra information, else just a total tick count.+--+initSimplCount :: IO SimplStats+#ifdef ACCELERATE_DEBUG+initSimplCount = do+ d <- getFlag dump_simpl_stats+ return $! if d then Detail { ticks = 0, details = Map.empty }+ else Simple 0+#else+initSimplCount = return $! Simple 0+#endif+++-- Reset the statistics counters. Do this at the beginning at each HOAS -> de+-- Bruijn conversion + optimisation pass.+--+resetSimplCount :: IO ()+#ifdef ACCELERATE_DEBUG+resetSimplCount = writeIORef statistics =<< initSimplCount+#else+resetSimplCount = return ()+#endif++-- Display simplifier statistics. The counts are reset afterwards.+--+{-# INLINEABLE dumpSimplStats #-}+dumpSimplStats :: IO ()+#ifdef ACCELERATE_DEBUG+dumpSimplStats = do+ when dump_simpl_stats $ do+ stats <- simplCount+ putTraceMsg builder (render (layoutPretty defaultLayoutOptions stats))+ resetSimplCount+ where+ -- stolen from Data.Text.Prettyprint.Doc.Render.Text.renderLazy+ render = \case+ SFail -> panicUncaughtFail+ SEmpty -> mempty+ SChar c rest -> singleton c <> render rest+ SText _l t rest -> fromText t <> render rest+ SLine i rest -> singleton '\n' <> (fromText (textSpaces i) <> render rest)+ SAnnPush _ann rest -> render rest+ SAnnPop rest -> render rest+#else+dumpSimplStats = return ()+#endif++++-- Tick a counter+--+simplTick :: Tick -> SimplStats -> SimplStats+simplTick _ (Simple n) = Simple (n+1)+simplTick t (Detail n dts) = Detail (n+1) (dts `addTick` t)++-- Pretty print the tick counts. Remarkably reminiscent of GHC style...+--+pprSimplCount :: SimplStats -> Doc+pprSimplCount (Simple n) = "Total ticks:" <+> pretty n+pprSimplCount (Detail n dts)+ = vcat [ "Total ticks:" <+> pretty n+ , mempty+ , pprTickCount dts+ ]++simplCount :: IO Doc+simplCount = pprSimplCount `fmap` readIORef statistics+++-- Ticks+-- -----++type Doc = Pretty.Doc ()+type TickCount = Map Tick Int++data Id = Id Text+ deriving (Eq, Ord)++data Tick+ = Inline Id+ | RuleFired Id+ | KnownBranch Id+ | CaseElim Id+ | CaseDefault Id+ | BetaReduce Id+ | Substitution Id++ -- tick at each iteration+ | SimplifierDone+ | FusionDone+ deriving (Eq, Ord)+++addTick :: TickCount -> Tick -> TickCount+addTick tc t =+ Map.alter f t tc+ where+ f Nothing = Just 1+ f (Just x) = let x' = x+1 in x' `seq` Just x'++pprTickCount :: TickCount -> Doc+pprTickCount counts =+ vcat (map pprTickGroup groups)+ where+ groups = groupBy sameTag (Map.toList counts)+ sameTag = (==) `on` tickToTag . fst++pprTickGroup :: [(Tick,Int)] -> Doc+pprTickGroup [] = error "pprTickGroup"+pprTickGroup grp@((groupRepr, _) : _) =+ hang 2 (vcat $ (pretty groupTotal <+> groupName)+ : [ pretty n <+> pprTickCtx t | (t,n) <- sortBy (flip (comparing snd)) grp ])+ where+ groupName = tickToStr groupRepr+ groupTotal = sum [n | (_,n) <- grp]++tickToTag :: Tick -> Int+tickToTag Inline{} = 0+tickToTag RuleFired{} = 1+tickToTag KnownBranch{} = 2+tickToTag CaseElim{} = 3+tickToTag CaseDefault{} = 4+tickToTag BetaReduce{} = 5+tickToTag Substitution{} = 6+tickToTag SimplifierDone = 99+tickToTag FusionDone = 100++tickToStr :: Tick -> Doc+tickToStr Inline{} = "Inline"+tickToStr RuleFired{} = "RuleFired"+tickToStr KnownBranch{} = "KnownBranch"+tickToStr CaseElim{} = "CaseElim"+tickToStr CaseDefault{} = "CaseDefault"+tickToStr BetaReduce{} = "BetaReduce"+tickToStr Substitution{} = "Substitution"+tickToStr SimplifierDone = "SimplifierDone"+tickToStr FusionDone = "FusionDone"++pprTickCtx :: Tick -> Doc+pprTickCtx (Inline v) = pprId v+pprTickCtx (RuleFired v) = pprId v+pprTickCtx (KnownBranch v) = pprId v+pprTickCtx (CaseElim v) = pprId v+pprTickCtx (CaseDefault v) = pprId v+pprTickCtx (BetaReduce v) = pprId v+pprTickCtx (Substitution v) = pprId v+pprTickCtx SimplifierDone = mempty+pprTickCtx FusionDone = mempty++pprId :: Id -> Doc+pprId (Id s) = pretty s+
+ src/Data/Array/Accelerate/Debug/Internal/Timed.hs view
@@ -0,0 +1,140 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE OverloadedStrings #-}+-- |+-- Module : Data.Array.Accelerate.Debug.Internal.Timed+-- Copyright : [2016..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Debug.Internal.Timed (++ timed,+ elapsed,++) where++import Data.Array.Accelerate.Debug.Internal.Flags+import Data.Array.Accelerate.Debug.Internal.Trace++import Control.Monad.Trans ( MonadIO )+import Data.Text.Lazy.Builder+import Formatting++#if ACCELERATE_DEBUG+import Data.Array.Accelerate.Debug.Internal.Clock++import Control.Applicative+import Control.Monad.Trans ( liftIO )+import System.CPUTime+import Prelude++import GHC.Int+import GHC.Prim+import GHC.Stats+import GHC.Types+import GHC.Word+#if MIN_VERSION_base(4,16,0)+import GHC.Float+#elif MIN_VERSION_base(4,15,0)+import GHC.Integer+#else+import GHC.Num+#endif+#endif+++-- | Execute an action and time the results. If GC stats have been enabled (with+-- @+RTS -t@ for example) then timing and memory usage information is displayed,+-- otherwise only timing information is shown.+--+{-# INLINEABLE timed #-}+timed :: MonadIO m => Flag -> Format Builder (Double -> Double -> Builder) -> m a -> m a+#ifdef ACCELERATE_DEBUG+timed f fmt action = do+ enabled <- liftIO $ getFlag f+ if enabled+ then do+ with_gc <- liftIO $ (&&) <$> getRTSStatsEnabled <*> getFlag verbose+ if with_gc+ then timed_gc fmt action+ else timed_simpl fmt action+ else+ action+#else+timed _ _ action = action+#endif++#ifdef ACCELERATE_DEBUG+{-# INLINEABLE timed_simpl #-}+timed_simpl :: MonadIO m => Format Builder (Double -> Double -> Builder) -> m a -> m a+timed_simpl fmt action = do+ wall0 <- liftIO getMonotonicTime+ cpu0 <- liftIO getCPUTime+ res <- action+ wall1 <- liftIO getMonotonicTime+ cpu1 <- liftIO getCPUTime+ --+ let wallTime = wall1 - wall0+#if MIN_VERSION_base(4,16,0)+ cpuTime = D# (integerToDouble# (cpu1 - cpu0) *## 1E-12##)+#else+ cpuTime = D# (doubleFromInteger (cpu1 - cpu0) *## 1E-12##)+#endif+ --+ liftIO $ putTraceMsg builder (bformat fmt wallTime cpuTime) -- XXX+ return res+++{-# INLINEABLE timed_gc #-}+timed_gc :: MonadIO m => Format Builder (Double -> Double -> Builder) -> m a -> m a+timed_gc fmt action = do+ rts0 <- liftIO getRTSStats+ res <- action+ rts1 <- liftIO getRTSStats+ --+ let+ w64 (W64# w#) = D# (word2Double# (word64ToWord# w#))+ i64 (I64# i#) = D# (int2Double# (int64ToInt# i#))+ --+ allocated = w64 (allocated_bytes rts1 - allocated_bytes rts0)+ copied = w64 (copied_bytes rts1 - copied_bytes rts0)+ totalWall = i64 (elapsed_ns rts1 - elapsed_ns rts0) * 1.0E-9+ totalCPU = i64 (cpu_ns rts1 - cpu_ns rts0) * 1.0E-9+ mutatorWall = i64 (mutator_elapsed_ns rts1 - mutator_elapsed_ns rts0) * 1.0E-9+ mutatorCPU = i64 (mutator_cpu_ns rts1 - mutator_cpu_ns rts0) * 1.0E-9+ gcWall = i64 (gc_elapsed_ns rts1 - gc_elapsed_ns rts0) * 1.0E-9+ gcCPU = i64 (gc_cpu_ns rts1 - gc_cpu_ns rts0) * 1.0E-9+ totalGCs = gcs rts1 - gcs rts0++ liftIO $ putTraceMsg+ (builder % "\n" % indented 4 (formatSIBase (Just 1) 1024 % "B allocated on the heap")+ % "\n" % indented 4 (formatSIBase (Just 1) 1024 % "B copied during GC (" % int % " collections)")+ % "\n" % indented 4 ("MUT: " % elapsed)+ % "\n" % indented 4 ("GC: " % elapsed))+ (bformat fmt totalWall totalCPU) -- XXX+ allocated+ copied totalGCs+ mutatorWall mutatorCPU+ gcWall gcCPU++ return res++#if __GLASGOW_HASKELL__ < 904+word64ToWord# :: Word# -> Word#+word64ToWord# x = x++int64ToInt# :: Int# -> Int#+int64ToInt# x = x+#endif+#endif++{-# INLINE elapsed #-}+elapsed :: Format r (Double -> Double -> r)+elapsed = formatSIBase (Just 3) 1000 % "s (wall), "+ % formatSIBase (Just 3) 1000 % "s (cpu)"+
+ src/Data/Array/Accelerate/Debug/Internal/Trace.hs view
@@ -0,0 +1,183 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE OverloadedStrings #-}+-- |+-- Module : Data.Array.Accelerate.Debug.Internal.Trace+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- Functions for tracing and monitoring execution. These are useful for+-- investigating bugs and performance problems, but by default are not enabled+-- in performance code.+--++module Data.Array.Accelerate.Debug.Internal.Trace (++ showFFloatSIBase,+ formatSIBase,++ putTraceMsg,+ trace, traceM,++) where++import Data.Array.Accelerate.Debug.Internal.Flags++import Control.Monad.Trans+import Data.Double.Conversion.Text+import Data.Text.Lazy.Builder+import Formatting++#ifdef ACCELERATE_DEBUG+import Data.Array.Accelerate.Debug.Internal.Clock+import System.IO hiding ( stderr )+import System.IO.Unsafe+import qualified Data.Text.IO as T++import GHC.MVar+import GHC.IO.Encoding+import GHC.IO.Handle.Types+import GHC.IO.Handle.Internals+import qualified GHC.IO.FD as FD+#if defined(mingw32_HOST_OS)+import Foreign.C.Types+#endif+#endif+++-- | Show a signed 'RealFloat' value using SI unit prefixes. In the call to:+--+-- > showFFloatSIBase prec base val+--+-- If @prec@ is @'Nothing'@ the value is shown to full precision, and if @prec@+-- is @'Just' d@, then at most @d@ digits are shown after the decimal place.+-- Here @base@ represents the increment size between multiples of the original+-- unit. For measures in base-10 this will be 1000 and for values in base-2 this+-- is usually 1024, for example when measuring seconds versus bytes,+-- respectively.+--+{-# INLINEABLE showFFloatSIBase #-}+showFFloatSIBase :: RealFloat a => Maybe Int -> a -> a -> Builder -> Builder+showFFloatSIBase mp !b !k !t = bformat (formatSIBase mp b % builder) k t++{-# INLINEABLE formatSIBase #-}+formatSIBase :: RealFloat a => Maybe Int -> a -> Format r (a -> r)+formatSIBase mp !b = later go+ where+ go k =+ let !pow = floor (logBase b k) :: Int+ !k' = k / (b ^^ pow)+ !unit =+ case pow of+ 4 -> Just "T"+ 3 -> Just "G"+ 2 -> Just "M"+ 1 -> Just "k"+ -1 -> Just "m"+ -2 -> Just "µ"+ -3 -> Just "n"+ -4 -> Just "p"+ _ -> Nothing+ in+ case unit of+ Nothing -> bformat (maybe float prec mp % " ") k+ Just t -> bformat (maybe float fixed mp % " " % builder) k' t++{-# INLINE prec #-}+prec :: Real a => Int -> Format r (a -> r)+prec digits = later (fromText . toPrecision digits . realToFrac)+++-- | The 'trace' function outputs the message given as its second argument when+-- the debug mode indicated by the first argument is enabled, before returning+-- the third argument as its result. The message is prefixed with a time stamp.+--+trace :: Flag -> Builder -> a -> a+#ifdef ACCELERATE_DEBUG+{-# NOINLINE trace #-}+trace f msg expr = unsafePerformIO $ do+ traceM f builder msg+ return expr+#else+{-# INLINE trace #-}+trace _ _ expr = expr+#endif+++-- | The 'traceM' function outputs the trace message together with a time+-- stamp from the MonadIO monad. This sequences the output with respect to+-- other IO actions.++-- TLM: Perhaps we should automatically format the log messages. Namely:+-- * prefix with a description of the mode (e.g. "gc: foo")+-- * align multi-line messages+--+{-# INLINE traceM #-}+traceM :: MonadIO m => Flag -> Format (m ()) a -> a+traceM _f m =+ runFormat m $ \_k -> do+#ifdef ACCELERATE_DEBUG+ when _f $ putTraceMsg (now _k)+#endif+ return ()+++-- | Print a message prefixed with the current elapsed wall-clock time.+--+{-# INLINE putTraceMsg #-}+putTraceMsg :: MonadIO m => Format (m ()) a -> a+putTraceMsg m =+ runFormat m $ \_k -> liftIO $ do+#ifdef ACCELERATE_DEBUG+ timestamp <- getProgramTime+ T.hPutStr stderr . sformat (squared (rfixed 8 ' ' (fixed 3)) % " " % builder % "\n") timestamp $ _k+#endif+ return ()+++#ifdef ACCELERATE_DEBUG+-- | A handle managing output to the Haskell program's standard output+-- channnel.+--+-- In contrast to 'System.IO.stderr' this output handle is (line) buffered,+-- which prevents garbled output when used my multiple threads. Stolen from+-- 'GHC.IO.Handle.FD.stderr'.+--+{-# NOINLINE stderr #-}+stderr :: Handle+stderr = unsafePerformIO $ do+ -- TODO: acquire lock+ setBinaryMode FD.stderr+ enc <- getLocaleEncoding+ mkHandle FD.stderr "<stderr>" WriteHandle True -- this stderr IS buffered+ (Just enc)+ nativeNewlineMode -- translate newlines+ (Just stdHandleFinalizer) Nothing++stdHandleFinalizer :: FilePath -> MVar Handle__ -> IO ()+stdHandleFinalizer fp m = do+ h_ <- takeMVar m+ flushWriteBuffer h_+ case haType h_ of+ ClosedHandle -> return ()+ _ -> closeTextCodecs h_+ putMVar m (ioe_finalizedHandle fp)++-- We have to put the FDs into binary mode on Windows to avoid the newline+-- translation that the CRT IO library does.+setBinaryMode :: FD.FD -> IO ()+#if defined(mingw32_HOST_OS)+setBinaryMode fd = do _ <- setmode (FD.fdFD fd) True+ return ()++foreign import ccall unsafe "__hscore_setmode" setmode :: CInt -> Bool -> IO CInt+#else+setBinaryMode _ = return ()+#endif+#endif+
+ src/Data/Array/Accelerate/Debug/Internal/Tracy.hs view
@@ -0,0 +1,176 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE TemplateHaskell #-}+{-# OPTIONS_GHC -fobject-code #-}+-- |+-- Module : Data.Array.Accelerate.Debug.Internal.Tracy+-- Copyright : [2016..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Debug.Internal.Tracy+ where++import Data.Word+import Foreign.C.String+import Foreign.C.Types+import Foreign.Ptr++#if defined(ACCELERATE_TRACY) && !defined(__GHCIDE__)+import Language.Haskell.TH.Syntax+#endif++type Zone = Word64+type SrcLoc = Word64++-- SEE: [HLS and GHC IDE]+--+#if defined(ACCELERATE_TRACY) && !defined(__GHCIDE__)++#ifdef TRACY_MANUAL_LIFETIME+foreign import ccall unsafe "___tracy_startup_profiler" startup_profiler :: IO ()+foreign import ccall unsafe "___tracy_shutdown_profiler" shutdown_profiler :: IO ()+#else+startup_profiler :: IO ()+startup_profiler = return ()++shutdown_profiler :: IO ()+shutdown_profiler = return ()+#endif++foreign import ccall unsafe "___tracy_connected" tracy_connected :: IO CInt++foreign import ccall unsafe "___tracy_alloc_srcloc" alloc_srcloc :: Word32 -> CString -> CSize -> CString -> CSize -> IO SrcLoc+foreign import ccall unsafe "___tracy_alloc_srcloc_name" alloc_srcloc_name :: Word32 -> CString -> CSize -> CString -> CSize -> CString -> CSize -> IO SrcLoc++foreign import ccall unsafe "___tracy_emit_zone_begin_alloc" emit_zone_begin :: SrcLoc -> CInt -> IO Zone+foreign import ccall unsafe "___tracy_emit_zone_end" emit_zone_end :: Zone -> IO ()+foreign import ccall unsafe "___tracy_emit_zone_text" emit_zone_text :: Zone -> CString -> CSize -> IO ()+foreign import ccall unsafe "___tracy_emit_zone_name" emit_zone_name :: Zone -> CString -> CSize -> IO ()+foreign import ccall unsafe "___tracy_emit_zone_color" emit_zone_color :: Zone -> Word32 -> IO ()+foreign import ccall unsafe "___tracy_emit_zone_value" emit_zone_value :: Zone -> Word64 -> IO ()++foreign import ccall unsafe "___tracy_emit_memory_alloc" emit_memory_alloc :: Ptr a -> CSize -> CInt -> IO ()+foreign import ccall unsafe "___tracy_emit_memory_free" emit_memory_free :: Ptr a -> CInt -> IO ()+foreign import ccall unsafe "___tracy_emit_memory_alloc_named" emit_memory_alloc_named :: Ptr a -> CSize -> CInt -> CString -> IO ()+foreign import ccall unsafe "___tracy_emit_memory_free_named" emit_memory_free_named :: Ptr a -> CInt -> CString -> IO ()++foreign import ccall unsafe "___tracy_emit_message" emit_message :: CString -> CSize -> CInt -> IO ()+foreign import ccall unsafe "___tracy_emit_messageC" emit_message_colour :: CString -> CSize -> Word32 -> CInt -> IO ()+foreign import ccall unsafe "___tracy_emit_messageL" emit_message_literal :: CString -> CInt -> IO ()+foreign import ccall unsafe "___tracy_emit_messageLC" emit_message_literal_colour :: CString -> Word32 -> CInt -> IO ()++foreign import ccall unsafe "___tracy_emit_frame_mark" emit_frame_mark :: CString -> IO ()+foreign import ccall unsafe "___tracy_emit_frame_mark_start" emit_frame_mark_start :: CString -> IO ()+foreign import ccall unsafe "___tracy_emit_frame_mark_end" emit_frame_mark_end :: CString -> IO ()+foreign import ccall unsafe "___tracy_emit_frame_image" emit_frame_image :: Ptr Word32 -> Word16 -> Word16 -> Word8 -> CInt -> IO () -- width height offset flip; dimensions must be divisible by 4!++foreign import ccall unsafe "___tracy_emit_plot" emit_plot :: CString -> Double -> IO ()+foreign import ccall unsafe "___tracy_emit_message_appinfo" emit_message_appinfo :: CString -> CSize -> IO ()++#ifdef TRACY_FIBERS+foreign import ccall unsafe "___tracy_fiber_enter" fiber_enter :: CString -> IO ()+foreign import ccall unsafe "___tracy_fiber_leave" fiber_leave :: IO ()+#else+fiber_enter :: CString -> IO ()+fiber_enter _ = return ()++fiber_leave :: IO ()+fiber_leave = return ()+#endif++-- SEE: [linking to .c files]+--+runQ $ do+ addForeignFilePath LangCxx "cbits/tracy/public/TracyClient.cpp"+ return []++#else++startup_profiler :: IO ()+startup_profiler = return ()++shutdown_profiler :: IO ()+shutdown_profiler = return ()++tracy_connected :: IO CInt+tracy_connected = return 0++alloc_srcloc :: Word32 -> CString -> CSize -> CString -> CSize -> IO SrcLoc+alloc_srcloc _ _ _ _ _ = return 0++alloc_srcloc_name :: Word32 -> CString -> CSize -> CString -> CSize -> CString -> CSize -> IO SrcLoc+alloc_srcloc_name _ _ _ _ _ _ _ = return 0++emit_zone_begin :: SrcLoc -> CInt -> IO Zone+emit_zone_begin _ _ = return 0++emit_zone_end :: Zone -> IO ()+emit_zone_end _ = return ()++emit_zone_text :: Zone -> CString -> CSize -> IO ()+emit_zone_text _ _ _ = return ()++emit_zone_name :: Zone -> CString -> CSize -> IO ()+emit_zone_name _ _ _ = return ()++emit_zone_color :: Zone -> Word32 -> IO ()+emit_zone_color _ _ = return ()++emit_zone_value :: Zone -> Word64 -> IO ()+emit_zone_value _ _ = return ()++emit_memory_alloc :: Ptr a -> CSize -> CInt -> IO ()+emit_memory_alloc _ _ _ = return ()++emit_memory_free :: Ptr a -> CInt -> IO ()+emit_memory_free _ _ = return ()++emit_memory_alloc_named :: Ptr a -> CSize -> CInt -> CString -> IO ()+emit_memory_alloc_named _ _ _ _ = return ()++emit_memory_free_named :: Ptr a -> CInt -> CString -> IO ()+emit_memory_free_named _ _ _ = return ()++emit_message :: CString -> CSize -> CInt -> IO ()+emit_message _ _ _ = return ()++emit_message_colour :: CString -> CSize -> Word32 -> CInt -> IO ()+emit_message_colour _ _ _ _ = return ()++emit_message_literal :: CString -> CInt -> IO ()+emit_message_literal _ _ = return ()++emit_message_literal_colour :: CString -> Word32 -> CInt -> IO ()+emit_message_literal_colour _ _ _ = return ()++emit_frame_mark :: CString -> IO ()+emit_frame_mark _ = return ()++emit_frame_mark_start :: CString -> IO ()+emit_frame_mark_start _ = return ()++emit_frame_mark_end :: CString -> IO ()+emit_frame_mark_end _ = return ()++emit_frame_image :: Ptr Word32 -> Word16 -> Word16 -> Word8 -> CInt -> IO ()+emit_frame_image _ _ _ _ _ = return ()++emit_plot :: CString -> Double -> IO ()+emit_plot _ _ = return ()++emit_message_appinfo :: CString -> CSize -> IO ()+emit_message_appinfo _ _ = return ()++fiber_enter :: CString -> IO ()+fiber_enter _ = return ()++fiber_leave :: IO ()+fiber_leave = return ()++#endif+
+ src/Data/Array/Accelerate/Debug/Trace.hs view
@@ -0,0 +1,90 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}+-- |+-- Module : Data.Array.Accelerate.Debug.Trace+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- Functions for tracing and monitoring execution. These are useful for+-- investigating bugs.+--+-- @since 1.4.0.0+--++module Data.Array.Accelerate.Debug.Trace (++ -- * Tracing+ -- $tracing+ --+ atrace, atraceArray, atraceId, atraceExp,++) where++import Data.Array.Accelerate.Language+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Array as S+import Data.Array.Accelerate.Sugar.Elt+import qualified Data.Array.Accelerate.Representation.Array as R+import qualified Data.Array.Accelerate.Representation.Shape as R++import Data.Text ( Text )+++-- $tracing+--+-- The 'atrace', 'atraceArray', 'atraceId', and 'atraceExp' functions print+-- messages to an output stream. They are intended for \"printf+-- debugging\", that is: tracing the flow of execution and printing+-- interesting values.+--+-- Note that arrays are printed in their internal representation (using+-- 'Data.Array.Accelerate.Sugar.Array.ArraysR'), which causes that tuples+-- or custom data types are shown differently.+--+-- These functions have the same caveats as those defined in "Debug.Trace".+--++-- | Outputs the trace message to the console before the 'Acc' computation+-- proceeds with the result of the second argument.+--+atrace :: Arrays a => Text -> Acc a -> Acc a+atrace message (Acc result)+ = Acc+ $ SmartAcc+ $ Atrace (Message (\_ -> "")+ (Just [|| \_ -> "" ||]) message) (SmartAcc Anil :: SmartAcc ()) result++-- | Outputs the trace message and the array(s) from the second argument to+-- the console, before the 'Acc' computation proceeds with the result of+-- the third argument.+--+atraceArray :: forall a b. (Arrays a, Arrays b, Show a) => Text -> Acc a -> Acc b -> Acc b+atraceArray message (Acc inspect) (Acc result)+ = Acc+ $ SmartAcc+ $ Atrace (Message (show . toArr @a)+ (Just [|| show . toArr @a ||]) message) inspect result++-- | Outputs the trace message and the array(s) to the console, before the+-- 'Acc' computation proceeds with the result of that array.+--+atraceId :: (Arrays a, Show a) => Text -> Acc a -> Acc a+atraceId message value = atraceArray message value value++-- | Outputs the trace message and a scalar value to the console, before+-- the 'Acc' computation proceeds with the result of the third argument.+--+atraceExp :: forall e a. (Elt e, Show e, Arrays a) => Text -> Exp e -> Acc a -> Acc a+atraceExp message value (Acc result) =+ let Acc inspect = unit value+ in Acc+ $ SmartAcc+ $ Atrace (Message (\a -> show (toElt @e (R.indexArray (R.ArrayR R.dim0 (eltR @e)) a ())))+ (Just [|| \a -> show (toElt @e (R.indexArray (R.ArrayR R.dim0 (eltR @e)) a ())) ||]) message) inspect result+
+ src/Data/Array/Accelerate/Error.hs view
@@ -0,0 +1,154 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Error+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Error (++ HasCallStack,+ internalError, boundsError, unsafeError,+ internalCheck, boundsCheck, unsafeCheck, indexCheck,+ internalWarning, boundsWarning, unsafeWarning,++) where++import Data.Text.Lazy.Builder+import Debug.Trace+import Formatting+import Prelude hiding ( error )++import GHC.Stack++data Check = Bounds | Unsafe | Internal+++-- | Issue an internal error message+--+internalError :: HasCallStack => Format r a -> a+internalError = withFrozenCallStack $ error Internal++boundsError :: HasCallStack => Format r a -> a+boundsError = withFrozenCallStack $ error Bounds++unsafeError :: HasCallStack => Format r a -> a+unsafeError = withFrozenCallStack $ error Unsafe+++-- | Throw an error if the condition evaluates to False, otherwise evaluate the+-- result.+--+internalCheck :: HasCallStack => Builder -> Bool -> a -> a+internalCheck = withFrozenCallStack $ check Internal++boundsCheck :: HasCallStack => Builder -> Bool -> a -> a+boundsCheck = withFrozenCallStack $ check Bounds++unsafeCheck :: HasCallStack => Builder -> Bool -> a -> a+unsafeCheck = withFrozenCallStack $ check Unsafe+++-- | Throw an error if the index is not in range, otherwise evaluate the result.+--+indexCheck :: HasCallStack => Int -> Int -> a -> a+indexCheck i n =+ boundsCheck (bformat ("index out of bounds: i=" % int % ", n=" % int) i n) (i >= 0 && i < n)++-- | Print a warning message if the condition evaluates to False.+--+internalWarning :: HasCallStack => Builder -> Bool -> a -> a+internalWarning = withFrozenCallStack $ warning Internal++boundsWarning :: HasCallStack => Builder -> Bool -> a -> a+boundsWarning = withFrozenCallStack $ warning Bounds++unsafeWarning :: HasCallStack => Builder -> Bool -> a -> a+unsafeWarning = withFrozenCallStack $ warning Unsafe+++error :: HasCallStack => Check -> Format r a -> a+error kind fmt = runFormat fmt $ \msg -> errorWithoutStackTrace (decorated kind msg)++check :: HasCallStack => Check -> Builder -> Bool -> a -> a+check kind msg cond k =+ case not (doChecks kind) || cond of+ True -> k+ False -> errorWithoutStackTrace (decorated kind msg)++warning :: HasCallStack => Check -> Builder -> Bool -> a -> a+warning kind msg cond k =+ case not (doChecks kind) || cond of+ True -> k+ False -> trace (decorated kind msg) k++decorated :: HasCallStack => Check -> Builder -> String+decorated kind msg = formatToString (intercalated "\n" builder) [ header, msg, ppCallStack callStack ]+ where+ header =+ case kind of+ Internal -> bformat (intercalated "\n" builder)+ [""+ ,"*** Internal error in package accelerate ***"+ ,"*** Please submit a bug report at https://github.com/AccelerateHS/accelerate/issues"+ ,""+ ]+ _ -> mempty++ppCallStack :: CallStack -> Builder+ppCallStack = ppLines+ where+ ppLines cs =+ case getCallStack cs of+ [] -> mempty+ st -> bformat ("CallStack (from HasCallStack):\n" % indentedLines 2 (later ppCallSite)) st++ ppCallSite (fun, loc) =+ bformat (string % ": " % build)+ fun+ (ppSrcLoc loc)++ ppSrcLoc SrcLoc{..} =+ bformat (string % ":" % int % ":" % int)+ srcLocModule+ srcLocStartLine+ srcLocStartCol+++-- CPP malarky+-- -----------++{-# INLINE doChecks #-}+doChecks :: Check -> Bool+doChecks Bounds = doBoundsChecks+doChecks Unsafe = internalError "If you want to do unsafe checks, re-enable the unsafe-checks cabal flag. It is currently disabled because there are no unsafe operation checks."+doChecks Internal = doInternalChecks++doBoundsChecks :: Bool+#ifdef ACCELERATE_BOUNDS_CHECKS+doBoundsChecks = True+#else+doBoundsChecks = False+#endif++-- doUnsafeChecks :: Bool+-- #ifdef ACCELERATE_UNSAFE_CHECKS+-- doUnsafeChecks = True+-- #else+-- doUnsafeChecks = False+-- #endif++doInternalChecks :: Bool+#ifdef ACCELERATE_INTERNAL_CHECKS+doInternalChecks = True+#else+doInternalChecks = False+#endif+
+ src/Data/Array/Accelerate/Interpreter.hs view
@@ -0,0 +1,1869 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE ViewPatterns #-}+{-# OPTIONS_GHC -fno-warn-name-shadowing #-}+{-# OPTIONS_HADDOCK prune #-}+-- |+-- Module : Data.Array.Accelerate.Interpreter+-- Description : Reference backend (interpreted)+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- This interpreter is meant to be a reference implementation of the+-- semantics of the embedded array language. The emphasis is on defining+-- the semantics clearly, not on performance.+--++module Data.Array.Accelerate.Interpreter (++ Smart.Acc, Sugar.Arrays,+ Afunction, AfunctionR,++ -- * Interpret an array expression+ run, run1, runN,++ -- Internal (hidden)+ evalPrim, evalPrimConst, evalCoerceScalar, atraceOp,++) where++import Data.Array.Accelerate.AST hiding ( Boundary(..) )+import Data.Array.Accelerate.AST.Environment+import Data.Array.Accelerate.AST.Var+import Data.Array.Accelerate.Array.Data+import Data.Array.Accelerate.Error+import Data.Array.Accelerate.Representation.Array+import Data.Array.Accelerate.Representation.Elt+import Data.Array.Accelerate.Representation.Shape+import Data.Array.Accelerate.Representation.Slice+import Data.Array.Accelerate.Representation.Stencil+import Data.Array.Accelerate.Representation.Tag+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Representation.Vec+import Data.Array.Accelerate.Trafo+import Data.Array.Accelerate.Trafo.Delayed ( DelayedOpenAfun, DelayedOpenAcc )+import Data.Array.Accelerate.Trafo.Sharing ( AfunctionR, AfunctionRepr(..), afunctionRepr )+import Data.Array.Accelerate.Type+import Data.Primitive.Vec+import qualified Data.Array.Accelerate.AST as AST+import qualified Data.Array.Accelerate.Debug.Internal.Flags as Debug+import qualified Data.Array.Accelerate.Debug.Internal.Graph as Debug+import qualified Data.Array.Accelerate.Debug.Internal.Stats as Debug+import qualified Data.Array.Accelerate.Debug.Internal.Timed as Debug+import qualified Data.Array.Accelerate.Smart as Smart+import qualified Data.Array.Accelerate.Sugar.Array as Sugar+import qualified Data.Array.Accelerate.Sugar.Elt as Sugar+import qualified Data.Array.Accelerate.Trafo.Delayed as AST++import Control.DeepSeq ( ($!!) )+import Control.Exception+import Control.Monad+import Control.Monad.ST+import Data.Bits+import Data.Primitive.ByteArray+import Data.Primitive.Types+import Data.Text.Lazy.Builder+import Formatting+import System.IO+import System.IO.Unsafe ( unsafePerformIO )+import Unsafe.Coerce+import qualified Data.Text.IO as T+import Prelude hiding ( (!!), sum )+++-- Program execution+-- -----------------++-- | Run a complete embedded array program using the reference interpreter.+--+run :: (HasCallStack, Sugar.Arrays a) => Smart.Acc a -> a+run a = unsafePerformIO execute+ where+ !acc = convertAcc a+ execute = do+ Debug.dumpGraph $!! acc+ Debug.dumpSimplStats+ res <- phase "execute" Debug.elapsed $ evaluate $ evalOpenAcc acc Empty+ return $ Sugar.toArr $ snd res++-- | This is 'runN' specialised to an array program of one argument.+--+run1 :: (HasCallStack, Sugar.Arrays a, Sugar.Arrays b) => (Smart.Acc a -> Smart.Acc b) -> a -> b+run1 = runN++-- | Prepare and execute an embedded array program.+--+runN :: forall f. (HasCallStack, Afunction f) => f -> AfunctionR f+runN f = go+ where+ !acc = convertAfun f+ !afun = unsafePerformIO $ do+ Debug.dumpGraph $!! acc+ Debug.dumpSimplStats+ return acc+ !go = eval (afunctionRepr @f) afun Empty+ --+ eval :: AfunctionRepr g (AfunctionR g) (ArraysFunctionR g)+ -> DelayedOpenAfun aenv (ArraysFunctionR g)+ -> Val aenv+ -> AfunctionR g+ eval (AfunctionReprLam reprF) (Alam lhs f) aenv = \a -> eval reprF f $ aenv `push` (lhs, Sugar.fromArr a)+ eval AfunctionReprBody (Abody b) aenv = unsafePerformIO $ phase "execute" Debug.elapsed (Sugar.toArr . snd <$> evaluate (evalOpenAcc b aenv))+ eval _ _aenv _ = error "Two men say they're Jesus; one of them must be wrong"++-- -- | Stream a lazily read list of input arrays through the given program,+-- -- collecting results as we go+-- --+-- streamOut :: Arrays a => Sugar.Seq [a] -> [a]+-- streamOut seq = let seq' = convertSeqWith config seq+-- in evalDelayedSeq defaultSeqConfig seq'+++-- Debugging+-- ---------++phase :: Builder -> Format Builder (Double -> Double -> Builder) -> IO a -> IO a+phase n fmt go = Debug.timed Debug.dump_phases (now ("phase " <> n <> ": ") % fmt) go+++-- Delayed Arrays+-- --------------++-- Note that in contrast to the representation used in the optimised AST, the+-- delayed array representation used here is _only_ for delayed arrays --- we do+-- not require an optional Manifest|Delayed data type to evaluate the program.+--+data Delayed a where+ Delayed :: ArrayR (Array sh e)+ -> sh+ -> (sh -> e)+ -> (Int -> e)+ -> Delayed (Array sh e)+++-- Array expression evaluation+-- ---------------------------++type WithReprs acc = (ArraysR acc, acc)++fromFunction' :: ArrayR (Array sh e) -> sh -> (sh -> e) -> WithReprs (Array sh e)+fromFunction' repr sh f = (TupRsingle repr, fromFunction repr sh f)++-- Evaluate an open array function+--+evalOpenAfun :: HasCallStack => DelayedOpenAfun aenv f -> Val aenv -> f+evalOpenAfun (Alam lhs f) aenv = \a -> evalOpenAfun f $ aenv `push` (lhs, a)+evalOpenAfun (Abody b) aenv = snd $ evalOpenAcc b aenv+++-- The core interpreter for optimised array programs+--+evalOpenAcc+ :: forall aenv a. HasCallStack+ => DelayedOpenAcc aenv a+ -> Val aenv+ -> WithReprs a+evalOpenAcc AST.Delayed{} _ = internalError "expected manifest array"+evalOpenAcc (AST.Manifest pacc) aenv =+ let+ manifest :: forall a'. HasCallStack => DelayedOpenAcc aenv a' -> WithReprs a'+ manifest acc =+ let (repr, a') = evalOpenAcc acc aenv+ in rnfArraysR repr a' `seq` (repr, a')++ delayed :: DelayedOpenAcc aenv (Array sh e) -> Delayed (Array sh e)+ delayed AST.Delayed{..} = Delayed reprD (evalE extentD) (evalF indexD) (evalF linearIndexD)+ delayed a' = Delayed aR (shape a) (indexArray aR a) (linearIndexArray (arrayRtype aR) a)+ where+ (TupRsingle aR, a) = manifest a'++ evalE :: Exp aenv t -> t+ evalE exp = evalExp exp aenv++ evalF :: Fun aenv f -> f+ evalF fun = evalFun fun aenv++ evalB :: AST.Boundary aenv t -> Boundary t+ evalB bnd = evalBoundary bnd aenv++ dir :: Direction -> t -> t -> t+ dir LeftToRight l _ = l+ dir RightToLeft _ r = r+ in+ case pacc of+ Avar (Var repr ix) -> (TupRsingle repr, prj ix aenv)+ Alet lhs acc1 acc2 -> evalOpenAcc acc2 $ aenv `push` (lhs, snd $ manifest acc1)+ Apair acc1 acc2 -> let (r1, a1) = manifest acc1+ (r2, a2) = manifest acc2+ in+ (TupRpair r1 r2, (a1, a2))+ Anil -> (TupRunit, ())+ Atrace msg as bs -> unsafePerformIO $ manifest bs <$ atraceOp msg (snd $ manifest as)+ Apply repr afun acc -> (repr, evalOpenAfun afun aenv $ snd $ manifest acc)+ Aforeign repr _ afun acc -> (repr, evalOpenAfun afun Empty $ snd $ manifest acc)+ Acond p acc1 acc2+ | toBool (evalE p) -> manifest acc1+ | otherwise -> manifest acc2++ Awhile cond body acc -> (repr, go initial)+ where+ (repr, initial) = manifest acc+ p = evalOpenAfun cond aenv+ f = evalOpenAfun body aenv+ go !x+ | toBool (linearIndexArray (Sugar.eltR @Word8) (p x) 0) = go (f x)+ | otherwise = x++ Use repr arr -> (TupRsingle repr, arr)+ Unit tp e -> unitOp tp (evalE e)+ -- Collect s -> evalSeq defaultSeqConfig s aenv++ -- Producers+ -- ---------+ Map tp f acc -> mapOp tp (evalF f) (delayed acc)+ Generate repr sh f -> generateOp repr (evalE sh) (evalF f)+ Transform repr sh p f acc -> transformOp repr (evalE sh) (evalF p) (evalF f) (delayed acc)+ Backpermute shr sh p acc -> backpermuteOp shr (evalE sh) (evalF p) (delayed acc)+ Reshape shr sh acc -> reshapeOp shr (evalE sh) (manifest acc)++ ZipWith tp f acc1 acc2 -> zipWithOp tp (evalF f) (delayed acc1) (delayed acc2)+ Replicate slice slix acc -> replicateOp slice (evalE slix) (manifest acc)+ Slice slice acc slix -> sliceOp slice (manifest acc) (evalE slix)++ -- Consumers+ -- ---------+ Fold f (Just z) acc -> foldOp (evalF f) (evalE z) (delayed acc)+ Fold f Nothing acc -> fold1Op (evalF f) (delayed acc)+ FoldSeg i f (Just z) acc seg -> foldSegOp i (evalF f) (evalE z) (delayed acc) (delayed seg)+ FoldSeg i f Nothing acc seg -> fold1SegOp i (evalF f) (delayed acc) (delayed seg)+ Scan d f (Just z) acc -> dir d scanlOp scanrOp (evalF f) (evalE z) (delayed acc)+ Scan d f Nothing acc -> dir d scanl1Op scanr1Op (evalF f) (delayed acc)+ Scan' d f z acc -> dir d scanl'Op scanr'Op (evalF f) (evalE z) (delayed acc)+ Permute f def p acc -> permuteOp (evalF f) (manifest def) (evalF p) (delayed acc)+ Stencil s tp sten b acc -> stencilOp s tp (evalF sten) (evalB b) (delayed acc)+ Stencil2 s1 s2 tp sten b1 a1 b2 a2+ -> stencil2Op s1 s2 tp (evalF sten) (evalB b1) (delayed a1) (evalB b2) (delayed a2)+++-- Array primitives+-- ----------------++unitOp :: TypeR e -> e -> WithReprs (Scalar e)+unitOp tp e = fromFunction' (ArrayR ShapeRz tp) () (const e)+++generateOp+ :: ArrayR (Array sh e)+ -> sh+ -> (sh -> e)+ -> WithReprs (Array sh e)+generateOp = fromFunction'+++transformOp+ :: ArrayR (Array sh' b)+ -> sh'+ -> (sh' -> sh)+ -> (a -> b)+ -> Delayed (Array sh a)+ -> WithReprs (Array sh' b)+transformOp repr sh' p f (Delayed _ _ xs _)+ = fromFunction' repr sh' (\ix -> f (xs $ p ix))+++reshapeOp+ :: HasCallStack+ => ShapeR sh+ -> sh+ -> WithReprs (Array sh' e)+ -> WithReprs (Array sh e)+reshapeOp newShapeR newShape (TupRsingle (ArrayR shr tp), (Array sh adata))+ = boundsCheck "shape mismatch" (size newShapeR newShape == size shr sh)+ ( TupRsingle (ArrayR newShapeR tp)+ , Array newShape adata+ )+++replicateOp+ :: SliceIndex slix sl co sh+ -> slix+ -> WithReprs (Array sl e)+ -> WithReprs (Array sh e)+replicateOp slice slix (TupRsingle repr@(ArrayR _ tp), arr)+ = fromFunction' repr' sh (\ix -> (repr, arr) ! pf ix)+ where+ repr' = ArrayR (sliceDomainR slice) tp+ (sh, pf) = extend slice slix (shape arr)++ extend :: SliceIndex slix sl co dim+ -> slix+ -> sl+ -> (dim, dim -> sl)+ extend SliceNil () ()+ = ((), const ())+ extend (SliceAll sliceIdx) (slx, ()) (sl, sz)+ = let (dim', f') = extend sliceIdx slx sl+ in ((dim', sz), \(ix, i) -> (f' ix, i))+ extend (SliceFixed sliceIdx) (slx, sz) sl+ = let (dim', f') = extend sliceIdx slx sl+ in ((dim', sz), \(ix, _) -> f' ix)+++sliceOp+ :: SliceIndex slix sl co sh+ -> WithReprs (Array sh e)+ -> slix+ -> WithReprs (Array sl e)+sliceOp slice (TupRsingle repr@(ArrayR _ tp), arr) slix+ = fromFunction' repr' sh' (\ix -> (repr, arr) ! pf ix)+ where+ repr' = ArrayR (sliceShapeR slice) tp+ (sh', pf) = restrict slice slix (shape arr)++ restrict+ :: HasCallStack+ => SliceIndex slix sl co sh+ -> slix+ -> sh+ -> (sl, sl -> sh)+ restrict SliceNil () ()+ = ((), const ())+ restrict (SliceAll sliceIdx) (slx, ()) (sl, sz)+ = let (sl', f') = restrict sliceIdx slx sl+ in ((sl', sz), \(ix, i) -> (f' ix, i))+ restrict (SliceFixed sliceIdx) (slx, i) (sl, sz)+ = let (sl', f') = restrict sliceIdx slx sl+ in indexCheck i sz $ (sl', \ix -> (f' ix, i))+++mapOp :: TypeR b+ -> (a -> b)+ -> Delayed (Array sh a)+ -> WithReprs (Array sh b)+mapOp tp f (Delayed (ArrayR shr _) sh xs _)+ = fromFunction' (ArrayR shr tp) sh (\ix -> f (xs ix))+++zipWithOp+ :: TypeR c+ -> (a -> b -> c)+ -> Delayed (Array sh a)+ -> Delayed (Array sh b)+ -> WithReprs (Array sh c)+zipWithOp tp f (Delayed (ArrayR shr _) shx xs _) (Delayed _ shy ys _)+ = fromFunction' (ArrayR shr tp) (intersect shr shx shy) (\ix -> f (xs ix) (ys ix))+++foldOp+ :: (e -> e -> e)+ -> e+ -> Delayed (Array (sh, Int) e)+ -> WithReprs (Array sh e)+foldOp f z (Delayed (ArrayR (ShapeRsnoc shr) tp) (sh, n) arr _)+ = fromFunction' (ArrayR shr tp) sh (\ix -> iter (ShapeRsnoc ShapeRz) ((), n) (\((), i) -> arr (ix, i)) f z)+++fold1Op+ :: HasCallStack+ => (e -> e -> e)+ -> Delayed (Array (sh, Int) e)+ -> WithReprs (Array sh e)+fold1Op f (Delayed (ArrayR (ShapeRsnoc shr) tp) (sh, n) arr _)+ = boundsCheck "empty array" (n > 0)+ $ fromFunction' (ArrayR shr tp) sh (\ix -> iter1 (ShapeRsnoc ShapeRz) ((), n) (\((), i) -> arr (ix, i)) f)+++foldSegOp+ :: HasCallStack+ => IntegralType i+ -> (e -> e -> e)+ -> e+ -> Delayed (Array (sh, Int) e)+ -> Delayed (Segments i)+ -> WithReprs (Array (sh, Int) e)+foldSegOp itp f z (Delayed repr (sh, _) arr _) (Delayed _ ((), n) _ seg)+ | IntegralDict <- integralDict itp+ = boundsCheck "empty segment descriptor" (n > 0)+ $ fromFunction' repr (sh, n-1)+ $ \(sz, ix) -> let start = fromIntegral $ seg ix+ end = fromIntegral $ seg (ix+1)+ in+ boundsCheck "empty segment" (end >= start)+ $ iter (ShapeRsnoc ShapeRz) ((), end-start) (\((), i) -> arr (sz, start+i)) f z+++fold1SegOp+ :: HasCallStack+ => IntegralType i+ -> (e -> e -> e)+ -> Delayed (Array (sh, Int) e)+ -> Delayed (Segments i)+ -> WithReprs (Array (sh, Int) e)+fold1SegOp itp f (Delayed repr (sh, _) arr _) (Delayed _ ((), n) _ seg)+ | IntegralDict <- integralDict itp+ = boundsCheck "empty segment descriptor" (n > 0)+ $ fromFunction' repr (sh, n-1)+ $ \(sz, ix) -> let start = fromIntegral $ seg ix+ end = fromIntegral $ seg (ix+1)+ in+ boundsCheck "empty segment" (end > start)+ $ iter1 (ShapeRsnoc ShapeRz) ((), end-start) (\((), i) -> arr (sz, start+i)) f+++scanl1Op+ :: forall sh e. HasCallStack+ => (e -> e -> e)+ -> Delayed (Array (sh, Int) e)+ -> WithReprs (Array (sh, Int) e)+scanl1Op f (Delayed (ArrayR shr tp) sh ain _)+ = ( TupRsingle $ ArrayR shr tp+ , adata `seq` Array sh adata+ )+ where+ --+ (adata, _) = runArrayData @e $ do+ aout <- newArrayData tp (size shr sh)++ let write (sz, 0) = writeArrayData tp aout (toIndex shr sh (sz, 0)) (ain (sz, 0))+ write (sz, i) = do+ x <- readArrayData tp aout (toIndex shr sh (sz, i-1))+ let y = ain (sz, i)+ writeArrayData tp aout (toIndex shr sh (sz, i)) (f x y)++ iter shr sh write (>>) (return ())+ return (aout, undefined)+++scanlOp+ :: forall sh e.+ (e -> e -> e)+ -> e+ -> Delayed (Array (sh, Int) e)+ -> WithReprs (Array (sh, Int) e)+scanlOp f z (Delayed (ArrayR shr tp) (sh, n) ain _)+ = ( TupRsingle $ ArrayR shr tp+ , adata `seq` Array sh' adata+ )+ where+ sh' = (sh, n+1)+ --+ (adata, _) = runArrayData @e $ do+ aout <- newArrayData tp (size shr sh')++ let write (sz, 0) = writeArrayData tp aout (toIndex shr sh' (sz, 0)) z+ write (sz, i) = do+ x <- readArrayData tp aout (toIndex shr sh' (sz, i-1))+ let y = ain (sz, i-1)+ writeArrayData tp aout (toIndex shr sh' (sz, i)) (f x y)++ iter shr sh' write (>>) (return ())+ return (aout, undefined)+++scanl'Op+ :: forall sh e.+ (e -> e -> e)+ -> e+ -> Delayed (Array (sh, Int) e)+ -> WithReprs (Array (sh, Int) e, Array sh e)+scanl'Op f z (Delayed (ArrayR shr@(ShapeRsnoc shr') tp) (sh, n) ain _)+ = ( TupRsingle (ArrayR shr tp) `TupRpair` TupRsingle (ArrayR shr' tp)+ , aout `seq` asum `seq` ( Array (sh, n) aout, Array sh asum )+ )+ where+ ((aout, asum), _) = runArrayData @(e, e) $ do+ aout <- newArrayData tp (size shr (sh, n))+ asum <- newArrayData tp (size shr' sh)++ let write (sz, 0)+ | n == 0 = writeArrayData tp asum (toIndex shr' sh sz) z+ | otherwise = writeArrayData tp aout (toIndex shr (sh, n) (sz, 0)) z+ write (sz, i) = do+ x <- readArrayData tp aout (toIndex shr (sh, n) (sz, i-1))+ let y = ain (sz, i-1)+ if i == n+ then writeArrayData tp asum (toIndex shr' sh sz) (f x y)+ else writeArrayData tp aout (toIndex shr (sh, n) (sz, i)) (f x y)++ iter shr (sh, n+1) write (>>) (return ())+ return ((aout, asum), undefined)+++scanrOp+ :: forall sh e.+ (e -> e -> e)+ -> e+ -> Delayed (Array (sh, Int) e)+ -> WithReprs (Array (sh, Int) e)+scanrOp f z (Delayed (ArrayR shr tp) (sz, n) ain _)+ = ( TupRsingle (ArrayR shr tp)+ , adata `seq` Array sh' adata+ )+ where+ sh' = (sz, n+1)+ --+ (adata, _) = runArrayData @e $ do+ aout <- newArrayData tp (size shr sh')++ let write (sz, 0) = writeArrayData tp aout (toIndex shr sh' (sz, n)) z+ write (sz, i) = do+ let x = ain (sz, n-i)+ y <- readArrayData tp aout (toIndex shr sh' (sz, n-i+1))+ writeArrayData tp aout (toIndex shr sh' (sz, n-i)) (f x y)++ iter shr sh' write (>>) (return ())+ return (aout, undefined)+++scanr1Op+ :: forall sh e. HasCallStack+ => (e -> e -> e)+ -> Delayed (Array (sh, Int) e)+ -> WithReprs (Array (sh, Int) e)+scanr1Op f (Delayed (ArrayR shr tp) sh@(_, n) ain _)+ = ( TupRsingle $ ArrayR shr tp+ , adata `seq` Array sh adata+ )+ where+ (adata, _) = runArrayData @e $ do+ aout <- newArrayData tp (size shr sh)++ let write (sz, 0) = writeArrayData tp aout (toIndex shr sh (sz, n-1)) (ain (sz, n-1))+ write (sz, i) = do+ let x = ain (sz, n-i-1)+ y <- readArrayData tp aout (toIndex shr sh (sz, n-i))+ writeArrayData tp aout (toIndex shr sh (sz, n-i-1)) (f x y)++ iter shr sh write (>>) (return ())+ return (aout, undefined)+++scanr'Op+ :: forall sh e.+ (e -> e -> e)+ -> e+ -> Delayed (Array (sh, Int) e)+ -> WithReprs (Array (sh, Int) e, Array sh e)+scanr'Op f z (Delayed (ArrayR shr@(ShapeRsnoc shr') tp) (sh, n) ain _)+ = ( TupRsingle (ArrayR shr tp) `TupRpair` TupRsingle (ArrayR shr' tp)+ , aout `seq` asum `seq` ( Array (sh, n) aout, Array sh asum )+ )+ where+ ((aout, asum), _) = runArrayData @(e, e) $ do+ aout <- newArrayData tp (size shr (sh, n))+ asum <- newArrayData tp (size shr' sh)++ let write (sz, 0)+ | n == 0 = writeArrayData tp asum (toIndex shr' sh sz) z+ | otherwise = writeArrayData tp aout (toIndex shr (sh, n) (sz, n-1)) z++ write (sz, i) = do+ let x = ain (sz, n-i)+ y <- readArrayData tp aout (toIndex shr (sh, n) (sz, n-i))+ if i == n+ then writeArrayData tp asum (toIndex shr' sh sz) (f x y)+ else writeArrayData tp aout (toIndex shr (sh, n) (sz, n-i-1)) (f x y)++ iter shr (sh, n+1) write (>>) (return ())+ return ((aout, asum), undefined)+++permuteOp+ :: forall sh sh' e. HasCallStack+ => (e -> e -> e)+ -> WithReprs (Array sh' e)+ -> (sh -> PrimMaybe sh')+ -> Delayed (Array sh e)+ -> WithReprs (Array sh' e)+permuteOp f (TupRsingle (ArrayR shr' _), def@(Array _ adef)) p (Delayed (ArrayR shr tp) sh _ ain)+ = (TupRsingle $ ArrayR shr' tp, adata `seq` Array sh' adata)+ where+ sh' = shape def+ n' = size shr' sh'+ --+ (adata, _) = runArrayData @e $ do+ aout <- newArrayData tp n'++ let -- initialise array with default values+ init i+ | i >= n' = return ()+ | otherwise = do+ x <- readArrayData tp adef i+ writeArrayData tp aout i x+ init (i+1)++ -- project each element onto the destination array and update+ update src+ = case p src of+ (0,_) -> return ()+ (1,((),dst)) -> do+ let i = toIndex shr sh src+ j = toIndex shr' sh' dst+ x = ain i+ --+ y <- readArrayData tp aout j+ writeArrayData tp aout j (f x y)+ _ -> internalError "unexpected tag"++ init 0+ iter shr sh update (>>) (return ())+ return (aout, undefined)+++backpermuteOp+ :: ShapeR sh'+ -> sh'+ -> (sh' -> sh)+ -> Delayed (Array sh e)+ -> WithReprs (Array sh' e)+backpermuteOp shr sh' p (Delayed (ArrayR _ tp) _ arr _)+ = fromFunction' (ArrayR shr tp) sh' (\ix -> arr $ p ix)+++stencilOp+ :: HasCallStack+ => StencilR sh a stencil+ -> TypeR b+ -> (stencil -> b)+ -> Boundary (Array sh a)+ -> Delayed (Array sh a)+ -> WithReprs (Array sh b)+stencilOp stencil tp f bnd arr@(Delayed _ sh _ _)+ = fromFunction' (ArrayR shr tp) sh+ $ f . stencilAccess stencil (bounded shr bnd arr)+ where+ shr = stencilShapeR stencil+++stencil2Op+ :: HasCallStack+ => StencilR sh a stencil1+ -> StencilR sh b stencil2+ -> TypeR c+ -> (stencil1 -> stencil2 -> c)+ -> Boundary (Array sh a)+ -> Delayed (Array sh a)+ -> Boundary (Array sh b)+ -> Delayed (Array sh b)+ -> WithReprs (Array sh c)+stencil2Op s1 s2 tp stencil bnd1 arr1@(Delayed _ sh1 _ _) bnd2 arr2@(Delayed _ sh2 _ _)+ = fromFunction' (ArrayR shr tp) (intersect shr sh1 sh2) f+ where+ f ix = stencil (stencilAccess s1 (bounded shr bnd1 arr1) ix)+ (stencilAccess s2 (bounded shr bnd2 arr2) ix)+ shr = stencilShapeR s1++stencilAccess+ :: StencilR sh e stencil+ -> (sh -> e)+ -> sh+ -> stencil+stencilAccess stencil = goR (stencilShapeR stencil) stencil+ where+ -- Base cases, nothing interesting to do here since we know the lower+ -- dimension is Z.+ --+ goR :: ShapeR sh -> StencilR sh e stencil -> (sh -> e) -> sh -> stencil+ goR _ (StencilRunit3 _) rf ix =+ let+ (z, i) = ix+ rf' d = rf (z, i+d)+ in+ ((( ()+ , rf' (-1))+ , rf' 0 )+ , rf' 1 )++ goR _ (StencilRunit5 _) rf ix =+ let (z, i) = ix+ rf' d = rf (z, i+d)+ in+ ((((( ()+ , rf' (-2))+ , rf' (-1))+ , rf' 0 )+ , rf' 1 )+ , rf' 2 )++ goR _ (StencilRunit7 _) rf ix =+ let (z, i) = ix+ rf' d = rf (z, i+d)+ in+ ((((((( ()+ , rf' (-3))+ , rf' (-2))+ , rf' (-1))+ , rf' 0 )+ , rf' 1 )+ , rf' 2 )+ , rf' 3 )++ goR _ (StencilRunit9 _) rf ix =+ let (z, i) = ix+ rf' d = rf (z, i+d)+ in+ ((((((((( ()+ , rf' (-4))+ , rf' (-3))+ , rf' (-2))+ , rf' (-1))+ , rf' 0 )+ , rf' 1 )+ , rf' 2 )+ , rf' 3 )+ , rf' 4 )++ -- Recursive cases. Note that because the stencil pattern is defined with+ -- cons ordering, whereas shapes (and indices) are defined as a snoc-list,+ -- when we recurse on the stencil structure we must manipulate the+ -- _left-most_ index component.+ --+ goR (ShapeRsnoc shr) (StencilRtup3 s1 s2 s3) rf ix =+ let (i, ix') = uncons shr ix+ rf' d ds = rf (cons shr (i+d) ds)+ in+ ((( ()+ , goR shr s1 (rf' (-1)) ix')+ , goR shr s2 (rf' 0) ix')+ , goR shr s3 (rf' 1) ix')++ goR (ShapeRsnoc shr) (StencilRtup5 s1 s2 s3 s4 s5) rf ix =+ let (i, ix') = uncons shr ix+ rf' d ds = rf (cons shr (i+d) ds)+ in+ ((((( ()+ , goR shr s1 (rf' (-2)) ix')+ , goR shr s2 (rf' (-1)) ix')+ , goR shr s3 (rf' 0) ix')+ , goR shr s4 (rf' 1) ix')+ , goR shr s5 (rf' 2) ix')++ goR (ShapeRsnoc shr) (StencilRtup7 s1 s2 s3 s4 s5 s6 s7) rf ix =+ let (i, ix') = uncons shr ix+ rf' d ds = rf (cons shr (i+d) ds)+ in+ ((((((( ()+ , goR shr s1 (rf' (-3)) ix')+ , goR shr s2 (rf' (-2)) ix')+ , goR shr s3 (rf' (-1)) ix')+ , goR shr s4 (rf' 0) ix')+ , goR shr s5 (rf' 1) ix')+ , goR shr s6 (rf' 2) ix')+ , goR shr s7 (rf' 3) ix')++ goR (ShapeRsnoc shr) (StencilRtup9 s1 s2 s3 s4 s5 s6 s7 s8 s9) rf ix =+ let (i, ix') = uncons shr ix+ rf' d ds = rf (cons shr (i+d) ds)+ in+ ((((((((( ()+ , goR shr s1 (rf' (-4)) ix')+ , goR shr s2 (rf' (-3)) ix')+ , goR shr s3 (rf' (-2)) ix')+ , goR shr s4 (rf' (-1)) ix')+ , goR shr s5 (rf' 0) ix')+ , goR shr s6 (rf' 1) ix')+ , goR shr s7 (rf' 2) ix')+ , goR shr s8 (rf' 3) ix')+ , goR shr s9 (rf' 4) ix')++ -- Add a left-most component to an index+ --+ cons :: ShapeR sh -> Int -> sh -> (sh, Int)+ cons ShapeRz ix () = ((), ix)+ cons (ShapeRsnoc shr) ix (sh, sz) = (cons shr ix sh, sz)++ -- Remove the left-most index of an index, and return the remainder+ --+ uncons :: ShapeR sh -> (sh, Int) -> (Int, sh)+ uncons ShapeRz ((), v) = (v, ())+ uncons (ShapeRsnoc shr) (v1, v2) = let (i, v1') = uncons shr v1+ in (i, (v1', v2))+++bounded+ :: HasCallStack+ => ShapeR sh+ -> Boundary (Array sh e)+ -> Delayed (Array sh e)+ -> sh+ -> e+bounded shr bnd (Delayed _ sh f _) ix =+ if inside shr sh ix+ then f ix+ else+ case bnd of+ Function g -> g ix+ Constant v -> v+ _ -> f (bound shr sh ix)++ where+ -- Whether the index (second argument) is inside the bounds of the given+ -- shape (first argument).+ --+ inside :: ShapeR sh -> sh -> sh -> Bool+ inside ShapeRz () () = True+ inside (ShapeRsnoc shr) (sh, sz) (ih, iz) = iz >= 0 && iz < sz && inside shr sh ih++ -- Return the index (second argument), updated to obey the given boundary+ -- conditions when outside the bounds of the given shape (first argument)+ --+ bound :: HasCallStack => ShapeR sh -> sh -> sh -> sh+ bound ShapeRz () () = ()+ bound (ShapeRsnoc shr) (sh, sz) (ih, iz) = (bound shr sh ih, ih')+ where+ ih'+ | iz < 0 = case bnd of+ Clamp -> 0+ Mirror -> -iz+ Wrap -> sz + iz+ _ -> internalError "unexpected boundary condition"+ | iz >= sz = case bnd of+ Clamp -> sz - 1+ Mirror -> sz - (iz - sz + 2)+ Wrap -> iz - sz+ _ -> internalError "unexpected boundary condition"+ | otherwise = iz++-- toSeqOp :: forall slix sl dim co e proxy. (Elt slix, Shape sl, Shape dim, Elt e)+-- => SliceIndex (EltRepr slix)+-- (EltRepr sl)+-- co+-- (EltRepr dim)+-- -> proxy slix+-- -> Array dim e+-- -> [Array sl e]+-- toSeqOp sliceIndex _ arr = map (sliceOp sliceIndex arr :: slix -> Array sl e)+-- (enumSlices sliceIndex (shape arr))+++-- Stencil boundary conditions+-- ---------------------------++data Boundary t where+ Clamp :: Boundary t+ Mirror :: Boundary t+ Wrap :: Boundary t+ Constant :: t -> Boundary (Array sh t)+ Function :: (sh -> e) -> Boundary (Array sh e)+++evalBoundary :: HasCallStack => AST.Boundary aenv t -> Val aenv -> Boundary t+evalBoundary bnd aenv =+ case bnd of+ AST.Clamp -> Clamp+ AST.Mirror -> Mirror+ AST.Wrap -> Wrap+ AST.Constant v -> Constant v+ AST.Function f -> Function (evalFun f aenv)++atraceOp :: Message as -> as -> IO ()+atraceOp (Message show _ msg) as =+ let str = show as+ in do+ if null str+ then T.hPutStrLn stderr msg+ else hprint stderr (stext % ": " % string % "\n") msg str+ hFlush stderr+++-- Scalar expression evaluation+-- ----------------------------++-- Evaluate a closed scalar expression+--+evalExp :: HasCallStack => Exp aenv t -> Val aenv -> t+evalExp e aenv = evalOpenExp e Empty aenv++-- Evaluate a closed scalar function+--+evalFun :: HasCallStack => Fun aenv t -> Val aenv -> t+evalFun f aenv = evalOpenFun f Empty aenv++-- Evaluate an open scalar function+--+evalOpenFun :: HasCallStack => OpenFun env aenv t -> Val env -> Val aenv -> t+evalOpenFun (Body e) env aenv = evalOpenExp e env aenv+evalOpenFun (Lam lhs f) env aenv =+ \x -> evalOpenFun f (env `push` (lhs, x)) aenv+++-- Evaluate an open scalar expression+--+-- NB: The implementation of 'Index' and 'Shape' demonstrate clearly why+-- array expressions must be hoisted out of scalar expressions before code+-- execution. If these operations are in the body of a function that gets+-- mapped over an array, the array argument would be evaluated many times+-- leading to a large amount of wasteful recomputation.+--+evalOpenExp+ :: forall env aenv t. HasCallStack+ => OpenExp env aenv t+ -> Val env+ -> Val aenv+ -> t+evalOpenExp pexp env aenv =+ let+ evalE :: OpenExp env aenv t' -> t'+ evalE e = evalOpenExp e env aenv++ evalF :: OpenFun env aenv f' -> f'+ evalF f = evalOpenFun f env aenv++ evalA :: ArrayVar aenv a -> WithReprs a+ evalA (Var repr ix) = (TupRsingle repr, prj ix aenv)+ in+ case pexp of+ Let lhs exp1 exp2 -> let !v1 = evalE exp1+ env' = env `push` (lhs, v1)+ in evalOpenExp exp2 env' aenv+ Evar (Var _ ix) -> prj ix env+ Const _ c -> c+ Undef tp -> undefElt (TupRsingle tp)+ PrimConst c -> evalPrimConst c+ PrimApp f x -> evalPrim f (evalE x)+ Nil -> ()+ Pair e1 e2 -> let !x1 = evalE e1+ !x2 = evalE e2+ in (x1, x2)+ VecPack vecR e -> pack vecR $! evalE e+ VecUnpack vecR e -> unpack vecR $! evalE e+ IndexSlice slice slix sh -> restrict slice (evalE slix)+ (evalE sh)+ where+ restrict :: SliceIndex slix sl co sh -> slix -> sh -> sl+ restrict SliceNil () () = ()+ restrict (SliceAll sliceIdx) (slx, ()) (sl, sz) =+ let sl' = restrict sliceIdx slx sl+ in (sl', sz)+ restrict (SliceFixed sliceIdx) (slx, _i) (sl, _sz) =+ restrict sliceIdx slx sl++ IndexFull slice slix sh -> extend slice (evalE slix)+ (evalE sh)+ where+ extend :: SliceIndex slix sl co sh -> slix -> sl -> sh+ extend SliceNil () () = ()+ extend (SliceAll sliceIdx) (slx, ()) (sl, sz) =+ let sh' = extend sliceIdx slx sl+ in (sh', sz)+ extend (SliceFixed sliceIdx) (slx, sz) sl =+ let sh' = extend sliceIdx slx sl+ in (sh', sz)++ ToIndex shr sh ix -> toIndex shr (evalE sh) (evalE ix)+ FromIndex shr sh ix -> fromIndex shr (evalE sh) (evalE ix)+ Case e rhs def -> evalE (caseof (evalE e) rhs)+ where+ caseof :: TAG -> [(TAG, OpenExp env aenv t)] -> OpenExp env aenv t+ caseof tag = go+ where+ go ((t,c):cs)+ | tag == t = c+ | otherwise = go cs+ go []+ | Just d <- def = d+ | otherwise = internalError "unmatched case"++ Cond c t e+ | toBool (evalE c) -> evalE t+ | otherwise -> evalE e++ While cond body seed -> go (evalE seed)+ where+ f = evalF body+ p = evalF cond+ go !x+ | toBool (p x) = go (f x)+ | otherwise = x++ Index acc ix -> let (TupRsingle repr, a) = evalA acc+ in (repr, a) ! evalE ix+ LinearIndex acc i -> let (TupRsingle repr, a) = evalA acc+ ix = fromIndex (arrayRshape repr) (shape a) (evalE i)+ in (repr, a) ! ix+ Shape acc -> shape $ snd $ evalA acc+ ShapeSize shr sh -> size shr (evalE sh)+ Foreign _ _ f e -> evalOpenFun f Empty Empty $ evalE e+ Coerce t1 t2 e -> evalCoerceScalar t1 t2 (evalE e)+++-- Coercions+-- ---------++-- Coercion between two scalar types. We require that the size of the source and+-- destination values are equal (this is not checked at this point).+--+evalCoerceScalar :: ScalarType a -> ScalarType b -> a -> b+evalCoerceScalar SingleScalarType{} SingleScalarType{} a = unsafeCoerce a+evalCoerceScalar VectorScalarType{} VectorScalarType{} a = unsafeCoerce a -- XXX: or just unpack/repack the (Vec ba#)+evalCoerceScalar (SingleScalarType ta) VectorScalarType{} a = vector ta a+ where+ vector :: SingleType a -> a -> Vec n b+ vector (NumSingleType t) = num t++ num :: NumType a -> a -> Vec n b+ num (IntegralNumType t) = integral t+ num (FloatingNumType t) = floating t++ integral :: IntegralType a -> a -> Vec n b+ integral TypeInt{} = poke+ integral TypeInt8{} = poke+ integral TypeInt16{} = poke+ integral TypeInt32{} = poke+ integral TypeInt64{} = poke+ integral TypeWord{} = poke+ integral TypeWord8{} = poke+ integral TypeWord16{} = poke+ integral TypeWord32{} = poke+ integral TypeWord64{} = poke++ floating :: FloatingType a -> a -> Vec n b+ floating TypeHalf{} = poke+ floating TypeFloat{} = poke+ floating TypeDouble{} = poke++ {-# INLINE poke #-}+ poke :: forall a b n. Prim a => a -> Vec n b+ poke x = runST $ do+ mba <- newByteArray (sizeOf (undefined::a))+ writeByteArray mba 0 x+ ByteArray ba# <- unsafeFreezeByteArray mba+ return $ Vec ba#++evalCoerceScalar VectorScalarType{} (SingleScalarType tb) a = scalar tb a+ where+ scalar :: SingleType b -> Vec n a -> b+ scalar (NumSingleType t) = num t++ num :: NumType b -> Vec n a -> b+ num (IntegralNumType t) = integral t+ num (FloatingNumType t) = floating t++ integral :: IntegralType b -> Vec n a -> b+ integral TypeInt{} = peek+ integral TypeInt8{} = peek+ integral TypeInt16{} = peek+ integral TypeInt32{} = peek+ integral TypeInt64{} = peek+ integral TypeWord{} = peek+ integral TypeWord8{} = peek+ integral TypeWord16{} = peek+ integral TypeWord32{} = peek+ integral TypeWord64{} = peek++ floating :: FloatingType b -> Vec n a -> b+ floating TypeHalf{} = peek+ floating TypeFloat{} = peek+ floating TypeDouble{} = peek++ {-# INLINE peek #-}+ peek :: Prim a => Vec n b -> a+ peek (Vec ba#) = indexByteArray (ByteArray ba#) 0+++-- Scalar primitives+-- -----------------++evalPrimConst :: PrimConst a -> a+evalPrimConst (PrimMinBound ty) = evalMinBound ty+evalPrimConst (PrimMaxBound ty) = evalMaxBound ty+evalPrimConst (PrimPi ty) = evalPi ty++evalPrim :: PrimFun (a -> r) -> (a -> r)+evalPrim (PrimAdd ty) = evalAdd ty+evalPrim (PrimSub ty) = evalSub ty+evalPrim (PrimMul ty) = evalMul ty+evalPrim (PrimNeg ty) = evalNeg ty+evalPrim (PrimAbs ty) = evalAbs ty+evalPrim (PrimSig ty) = evalSig ty+evalPrim (PrimQuot ty) = evalQuot ty+evalPrim (PrimRem ty) = evalRem ty+evalPrim (PrimQuotRem ty) = evalQuotRem ty+evalPrim (PrimIDiv ty) = evalIDiv ty+evalPrim (PrimMod ty) = evalMod ty+evalPrim (PrimDivMod ty) = evalDivMod ty+evalPrim (PrimBAnd ty) = evalBAnd ty+evalPrim (PrimBOr ty) = evalBOr ty+evalPrim (PrimBXor ty) = evalBXor ty+evalPrim (PrimBNot ty) = evalBNot ty+evalPrim (PrimBShiftL ty) = evalBShiftL ty+evalPrim (PrimBShiftR ty) = evalBShiftR ty+evalPrim (PrimBRotateL ty) = evalBRotateL ty+evalPrim (PrimBRotateR ty) = evalBRotateR ty+evalPrim (PrimPopCount ty) = evalPopCount ty+evalPrim (PrimCountLeadingZeros ty) = evalCountLeadingZeros ty+evalPrim (PrimCountTrailingZeros ty) = evalCountTrailingZeros ty+evalPrim (PrimFDiv ty) = evalFDiv ty+evalPrim (PrimRecip ty) = evalRecip ty+evalPrim (PrimSin ty) = evalSin ty+evalPrim (PrimCos ty) = evalCos ty+evalPrim (PrimTan ty) = evalTan ty+evalPrim (PrimAsin ty) = evalAsin ty+evalPrim (PrimAcos ty) = evalAcos ty+evalPrim (PrimAtan ty) = evalAtan ty+evalPrim (PrimSinh ty) = evalSinh ty+evalPrim (PrimCosh ty) = evalCosh ty+evalPrim (PrimTanh ty) = evalTanh ty+evalPrim (PrimAsinh ty) = evalAsinh ty+evalPrim (PrimAcosh ty) = evalAcosh ty+evalPrim (PrimAtanh ty) = evalAtanh ty+evalPrim (PrimExpFloating ty) = evalExpFloating ty+evalPrim (PrimSqrt ty) = evalSqrt ty+evalPrim (PrimLog ty) = evalLog ty+evalPrim (PrimFPow ty) = evalFPow ty+evalPrim (PrimLogBase ty) = evalLogBase ty+evalPrim (PrimTruncate ta tb) = evalTruncate ta tb+evalPrim (PrimRound ta tb) = evalRound ta tb+evalPrim (PrimFloor ta tb) = evalFloor ta tb+evalPrim (PrimCeiling ta tb) = evalCeiling ta tb+evalPrim (PrimAtan2 ty) = evalAtan2 ty+evalPrim (PrimIsNaN ty) = evalIsNaN ty+evalPrim (PrimIsInfinite ty) = evalIsInfinite ty+evalPrim (PrimLt ty) = evalLt ty+evalPrim (PrimGt ty) = evalGt ty+evalPrim (PrimLtEq ty) = evalLtEq ty+evalPrim (PrimGtEq ty) = evalGtEq ty+evalPrim (PrimEq ty) = evalEq ty+evalPrim (PrimNEq ty) = evalNEq ty+evalPrim (PrimMax ty) = evalMax ty+evalPrim (PrimMin ty) = evalMin ty+evalPrim PrimLAnd = evalLAnd+evalPrim PrimLOr = evalLOr+evalPrim PrimLNot = evalLNot+evalPrim (PrimFromIntegral ta tb) = evalFromIntegral ta tb+evalPrim (PrimToFloating ta tb) = evalToFloating ta tb+++-- Implementation of scalar primitives+-- -----------------------------------++toBool :: PrimBool -> Bool+toBool 0 = False+toBool _ = True++fromBool :: Bool -> PrimBool+fromBool False = 0+fromBool True = 1++evalLAnd :: (PrimBool, PrimBool) -> PrimBool+evalLAnd (x, y) = fromBool (toBool x && toBool y)++evalLOr :: (PrimBool, PrimBool) -> PrimBool+evalLOr (x, y) = fromBool (toBool x || toBool y)++evalLNot :: PrimBool -> PrimBool+evalLNot = fromBool . not . toBool++evalFromIntegral :: IntegralType a -> NumType b -> a -> b+evalFromIntegral ta (IntegralNumType tb)+ | IntegralDict <- integralDict ta+ , IntegralDict <- integralDict tb+ = fromIntegral++evalFromIntegral ta (FloatingNumType tb)+ | IntegralDict <- integralDict ta+ , FloatingDict <- floatingDict tb+ = fromIntegral++evalToFloating :: NumType a -> FloatingType b -> a -> b+evalToFloating (IntegralNumType ta) tb+ | IntegralDict <- integralDict ta+ , FloatingDict <- floatingDict tb+ = realToFrac++evalToFloating (FloatingNumType ta) tb+ | FloatingDict <- floatingDict ta+ , FloatingDict <- floatingDict tb+ = realToFrac+++-- Extract methods from reified dictionaries+--++-- Constant methods of Bounded+--++evalMinBound :: BoundedType a -> a+evalMinBound (IntegralBoundedType ty)+ | IntegralDict <- integralDict ty+ = minBound++evalMaxBound :: BoundedType a -> a+evalMaxBound (IntegralBoundedType ty)+ | IntegralDict <- integralDict ty+ = maxBound++-- Constant method of floating+--++evalPi :: FloatingType a -> a+evalPi ty | FloatingDict <- floatingDict ty = pi++evalSin :: FloatingType a -> (a -> a)+evalSin ty | FloatingDict <- floatingDict ty = sin++evalCos :: FloatingType a -> (a -> a)+evalCos ty | FloatingDict <- floatingDict ty = cos++evalTan :: FloatingType a -> (a -> a)+evalTan ty | FloatingDict <- floatingDict ty = tan++evalAsin :: FloatingType a -> (a -> a)+evalAsin ty | FloatingDict <- floatingDict ty = asin++evalAcos :: FloatingType a -> (a -> a)+evalAcos ty | FloatingDict <- floatingDict ty = acos++evalAtan :: FloatingType a -> (a -> a)+evalAtan ty | FloatingDict <- floatingDict ty = atan++evalSinh :: FloatingType a -> (a -> a)+evalSinh ty | FloatingDict <- floatingDict ty = sinh++evalCosh :: FloatingType a -> (a -> a)+evalCosh ty | FloatingDict <- floatingDict ty = cosh++evalTanh :: FloatingType a -> (a -> a)+evalTanh ty | FloatingDict <- floatingDict ty = tanh++evalAsinh :: FloatingType a -> (a -> a)+evalAsinh ty | FloatingDict <- floatingDict ty = asinh++evalAcosh :: FloatingType a -> (a -> a)+evalAcosh ty | FloatingDict <- floatingDict ty = acosh++evalAtanh :: FloatingType a -> (a -> a)+evalAtanh ty | FloatingDict <- floatingDict ty = atanh++evalExpFloating :: FloatingType a -> (a -> a)+evalExpFloating ty | FloatingDict <- floatingDict ty = exp++evalSqrt :: FloatingType a -> (a -> a)+evalSqrt ty | FloatingDict <- floatingDict ty = sqrt++evalLog :: FloatingType a -> (a -> a)+evalLog ty | FloatingDict <- floatingDict ty = log++evalFPow :: FloatingType a -> ((a, a) -> a)+evalFPow ty | FloatingDict <- floatingDict ty = uncurry (**)++evalLogBase :: FloatingType a -> ((a, a) -> a)+evalLogBase ty | FloatingDict <- floatingDict ty = uncurry logBase++evalTruncate :: FloatingType a -> IntegralType b -> (a -> b)+evalTruncate ta tb+ | FloatingDict <- floatingDict ta+ , IntegralDict <- integralDict tb+ = truncate++evalRound :: FloatingType a -> IntegralType b -> (a -> b)+evalRound ta tb+ | FloatingDict <- floatingDict ta+ , IntegralDict <- integralDict tb+ = round++evalFloor :: FloatingType a -> IntegralType b -> (a -> b)+evalFloor ta tb+ | FloatingDict <- floatingDict ta+ , IntegralDict <- integralDict tb+ = floor++evalCeiling :: FloatingType a -> IntegralType b -> (a -> b)+evalCeiling ta tb+ | FloatingDict <- floatingDict ta+ , IntegralDict <- integralDict tb+ = ceiling++evalAtan2 :: FloatingType a -> ((a, a) -> a)+evalAtan2 ty | FloatingDict <- floatingDict ty = uncurry atan2++evalIsNaN :: FloatingType a -> (a -> PrimBool)+evalIsNaN ty | FloatingDict <- floatingDict ty = fromBool . isNaN++evalIsInfinite :: FloatingType a -> (a -> PrimBool)+evalIsInfinite ty | FloatingDict <- floatingDict ty = fromBool . isInfinite+++-- Methods of Num+--++evalAdd :: NumType a -> ((a, a) -> a)+evalAdd (IntegralNumType ty) | IntegralDict <- integralDict ty = uncurry (+)+evalAdd (FloatingNumType ty) | FloatingDict <- floatingDict ty = uncurry (+)++evalSub :: NumType a -> ((a, a) -> a)+evalSub (IntegralNumType ty) | IntegralDict <- integralDict ty = uncurry (-)+evalSub (FloatingNumType ty) | FloatingDict <- floatingDict ty = uncurry (-)++evalMul :: NumType a -> ((a, a) -> a)+evalMul (IntegralNumType ty) | IntegralDict <- integralDict ty = uncurry (*)+evalMul (FloatingNumType ty) | FloatingDict <- floatingDict ty = uncurry (*)++evalNeg :: NumType a -> (a -> a)+evalNeg (IntegralNumType ty) | IntegralDict <- integralDict ty = negate+evalNeg (FloatingNumType ty) | FloatingDict <- floatingDict ty = negate++evalAbs :: NumType a -> (a -> a)+evalAbs (IntegralNumType ty) | IntegralDict <- integralDict ty = abs+evalAbs (FloatingNumType ty) | FloatingDict <- floatingDict ty = abs++evalSig :: NumType a -> (a -> a)+evalSig (IntegralNumType ty) | IntegralDict <- integralDict ty = signum+evalSig (FloatingNumType ty) | FloatingDict <- floatingDict ty = signum++evalQuot :: IntegralType a -> ((a, a) -> a)+evalQuot ty | IntegralDict <- integralDict ty = uncurry quot++evalRem :: IntegralType a -> ((a, a) -> a)+evalRem ty | IntegralDict <- integralDict ty = uncurry rem++evalQuotRem :: IntegralType a -> ((a, a) -> (a, a))+evalQuotRem ty | IntegralDict <- integralDict ty = uncurry quotRem++evalIDiv :: IntegralType a -> ((a, a) -> a)+evalIDiv ty | IntegralDict <- integralDict ty = uncurry div++evalMod :: IntegralType a -> ((a, a) -> a)+evalMod ty | IntegralDict <- integralDict ty = uncurry mod++evalDivMod :: IntegralType a -> ((a, a) -> (a, a))+evalDivMod ty | IntegralDict <- integralDict ty = uncurry divMod++evalBAnd :: IntegralType a -> ((a, a) -> a)+evalBAnd ty | IntegralDict <- integralDict ty = uncurry (.&.)++evalBOr :: IntegralType a -> ((a, a) -> a)+evalBOr ty | IntegralDict <- integralDict ty = uncurry (.|.)++evalBXor :: IntegralType a -> ((a, a) -> a)+evalBXor ty | IntegralDict <- integralDict ty = uncurry xor++evalBNot :: IntegralType a -> (a -> a)+evalBNot ty | IntegralDict <- integralDict ty = complement++evalBShiftL :: IntegralType a -> ((a, Int) -> a)+evalBShiftL ty | IntegralDict <- integralDict ty = uncurry shiftL++evalBShiftR :: IntegralType a -> ((a, Int) -> a)+evalBShiftR ty | IntegralDict <- integralDict ty = uncurry shiftR++evalBRotateL :: IntegralType a -> ((a, Int) -> a)+evalBRotateL ty | IntegralDict <- integralDict ty = uncurry rotateL++evalBRotateR :: IntegralType a -> ((a, Int) -> a)+evalBRotateR ty | IntegralDict <- integralDict ty = uncurry rotateR++evalPopCount :: IntegralType a -> (a -> Int)+evalPopCount ty | IntegralDict <- integralDict ty = popCount++evalCountLeadingZeros :: IntegralType a -> (a -> Int)+evalCountLeadingZeros ty | IntegralDict <- integralDict ty = countLeadingZeros++evalCountTrailingZeros :: IntegralType a -> (a -> Int)+evalCountTrailingZeros ty | IntegralDict <- integralDict ty = countTrailingZeros++evalFDiv :: FloatingType a -> ((a, a) -> a)+evalFDiv ty | FloatingDict <- floatingDict ty = uncurry (/)++evalRecip :: FloatingType a -> (a -> a)+evalRecip ty | FloatingDict <- floatingDict ty = recip+++evalLt :: SingleType a -> ((a, a) -> PrimBool)+evalLt (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = fromBool . uncurry (<)+evalLt (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = fromBool . uncurry (<)++evalGt :: SingleType a -> ((a, a) -> PrimBool)+evalGt (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = fromBool . uncurry (>)+evalGt (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = fromBool . uncurry (>)++evalLtEq :: SingleType a -> ((a, a) -> PrimBool)+evalLtEq (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = fromBool . uncurry (<=)+evalLtEq (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = fromBool . uncurry (<=)++evalGtEq :: SingleType a -> ((a, a) -> PrimBool)+evalGtEq (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = fromBool . uncurry (>=)+evalGtEq (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = fromBool . uncurry (>=)++evalEq :: SingleType a -> ((a, a) -> PrimBool)+evalEq (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = fromBool . uncurry (==)+evalEq (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = fromBool . uncurry (==)++evalNEq :: SingleType a -> ((a, a) -> PrimBool)+evalNEq (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = fromBool . uncurry (/=)+evalNEq (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = fromBool . uncurry (/=)++evalMax :: SingleType a -> ((a, a) -> a)+evalMax (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = uncurry max+evalMax (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = uncurry max++evalMin :: SingleType a -> ((a, a) -> a)+evalMin (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = uncurry min+evalMin (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = uncurry min+++{--+-- Sequence evaluation+-- ---------------++-- Position in sequence.+--+type SeqPos = Int++-- Configuration for sequence evaluation.+--+data SeqConfig = SeqConfig+ { chunkSize :: Int -- Allocation limit for a sequence in+ -- words. Actual runtime allocation should be the+ -- maximum of this size and the size of the+ -- largest element in the sequence.+ }++-- Default sequence evaluation configuration for testing purposes.+--+defaultSeqConfig :: SeqConfig+defaultSeqConfig = SeqConfig { chunkSize = 2 }++type Chunk a = Vector' a++-- The empty chunk. O(1).+emptyChunk :: Arrays a => Chunk a+emptyChunk = empty'++-- Number of arrays in chunk. O(1).+--+clen :: Arrays a => Chunk a -> Int+clen = length'++elemsPerChunk :: SeqConfig -> Int -> Int+elemsPerChunk conf n+ | n < 1 = chunkSize conf+ | otherwise =+ let (a,b) = chunkSize conf `quotRem` n+ in a + signum b++-- Drop a number of arrays from a chunk. O(1). Note: Require keeping a+-- scan of element sizes.+--+cdrop :: Arrays a => Int -> Chunk a -> Chunk a+cdrop = drop' dropOp (fst . offsetsOp)++-- Get all the shapes of a chunk of arrays. O(1).+--+chunkShapes :: Chunk (Array sh a) -> Vector sh+chunkShapes = shapes'++-- Get all the elements of a chunk of arrays. O(1).+--+chunkElems :: Chunk (Array sh a) -> Vector a+chunkElems = elements'++-- Convert a vector to a chunk of scalars.+--+vec2Chunk :: Elt e => Vector e -> Chunk (Scalar e)+vec2Chunk = vec2Vec'++-- Convert a list of arrays to a chunk.+--+fromListChunk :: Arrays a => [a] -> Vector' a+fromListChunk = fromList' concatOp++-- Convert a chunk to a list of arrays.+--+toListChunk :: Arrays a => Vector' a -> [a]+toListChunk = toList' fetchAllOp++-- fmap for Chunk. O(n).+-- TODO: Use vectorised function.+mapChunk :: (Arrays a, Arrays b)+ => (a -> b)+ -> Chunk a -> Chunk b+mapChunk f c = fromListChunk $ map f (toListChunk c)++-- zipWith for Chunk. O(n).+-- TODO: Use vectorised function.+zipWithChunk :: (Arrays a, Arrays b, Arrays c)+ => (a -> b -> c)+ -> Chunk a -> Chunk b -> Chunk c+zipWithChunk f c1 c2 = fromListChunk $ zipWith f (toListChunk c1) (toListChunk c2)++-- A window on a sequence.+--+data Window a = Window+ { chunk :: Chunk a -- Current allocated chunk.+ , wpos :: SeqPos -- Position of the window on the sequence, given+ -- in number of elements.+ }++-- The initial empty window.+--+window0 :: Arrays a => Window a+window0 = Window { chunk = emptyChunk, wpos = 0 }++-- Index the given window by the given index on the sequence.+--+(!#) :: Arrays a => Window a -> SeqPos -> Chunk a+w !# i+ | j <- i - wpos w+ , j >= 0+ = cdrop j (chunk w)+ --+ | otherwise+ = error $ "Window indexed before position. wpos = " ++ show (wpos w) ++ " i = " ++ show i++-- Move the give window by supplying the next chunk.+--+moveWin :: Arrays a => Window a -> Chunk a -> Window a+moveWin w c = w { chunk = c+ , wpos = wpos w + clen (chunk w)+ }++-- A cursor on a sequence.+--+data Cursor senv a = Cursor+ { ref :: Idx senv a -- Reference to the sequence.+ , cpos :: SeqPos -- Position of the cursor on the sequence,+ -- given in number of elements.+ }++-- Initial cursor.+--+cursor0 :: Idx senv a -> Cursor senv a+cursor0 x = Cursor { ref = x, cpos = 0 }++-- Advance cursor by a relative amount.+--+moveCursor :: Int -> Cursor senv a -> Cursor senv a+moveCursor k c = c { cpos = cpos c + k }++-- Valuation for an environment of sequence windows.+--+data Val' senv where+ Empty' :: Val' ()+ Push' :: Val' senv -> Window t -> Val' (senv, t)++-- Projection of a window from a window valuation using a de Bruijn+-- index.+--+prj' :: Idx senv t -> Val' senv -> Window t+prj' ZeroIdx (Push' _ v) = v+prj' (SuccIdx idx) (Push' val _) = prj' idx val++-- Projection of a chunk from a window valuation using a sequence+-- cursor.+--+prjChunk :: Arrays a => Cursor senv a -> Val' senv -> Chunk a+prjChunk c senv = prj' (ref c) senv !# cpos c++-- An executable sequence.+--+data ExecSeq senv arrs where+ ExecP :: Arrays a => Window a -> ExecP senv a -> ExecSeq (senv, a) arrs -> ExecSeq senv arrs+ ExecC :: Arrays a => ExecC senv a -> ExecSeq senv a+ ExecR :: Arrays a => Cursor senv a -> ExecSeq senv [a]++-- An executable producer.+--+data ExecP senv a where+ ExecStreamIn :: Int+ -> [a]+ -> ExecP senv a++ ExecMap :: Arrays a+ => (Chunk a -> Chunk b)+ -> Cursor senv a+ -> ExecP senv b++ ExecZipWith :: (Arrays a, Arrays b)+ => (Chunk a -> Chunk b -> Chunk c)+ -> Cursor senv a+ -> Cursor senv b+ -> ExecP senv c++ -- Stream scan skeleton.+ ExecScan :: Arrays a+ => (s -> Chunk a -> (Chunk r, s)) -- Chunk scanner.+ -> s -- Accumulator (internal state).+ -> Cursor senv a -- Input stream.+ -> ExecP senv r++-- An executable consumer.+--+data ExecC senv a where++ -- Stream reduction skeleton.+ ExecFold :: Arrays a+ => (s -> Chunk a -> s) -- Chunk consumer function.+ -> (s -> r) -- Finalizer function.+ -> s -- Accumulator (internal state).+ -> Cursor senv a -- Input stream.+ -> ExecC senv r++ ExecStuple :: IsAtuple a+ => Atuple (ExecC senv) (TupleRepr a)+ -> ExecC senv a++minCursor :: ExecSeq senv a -> SeqPos+minCursor s = travS s 0+ where+ travS :: ExecSeq senv a -> Int -> SeqPos+ travS s i =+ case s of+ ExecP _ p s' -> travP p i `min` travS s' (i+1)+ ExecC c -> travC c i+ ExecR _ -> maxBound++ k :: Cursor senv a -> Int -> SeqPos+ k c i+ | i == idxToInt (ref c) = cpos c+ | otherwise = maxBound++ travP :: ExecP senv a -> Int -> SeqPos+ travP p i =+ case p of+ ExecStreamIn _ _ -> maxBound+ ExecMap _ c -> k c i+ ExecZipWith _ c1 c2 -> k c1 i `min` k c2 i+ ExecScan _ _ c -> k c i++ travT :: Atuple (ExecC senv) t -> Int -> SeqPos+ travT NilAtup _ = maxBound+ travT (SnocAtup t c) i = travT t i `min` travC c i++ travC :: ExecC senv a -> Int -> SeqPos+ travC c i =+ case c of+ ExecFold _ _ _ cu -> k cu i+ ExecStuple t -> travT t i+++evalDelayedSeq+ :: SeqConfig+ -> DelayedSeq arrs+ -> arrs+evalDelayedSeq cfg (DelayedSeq aenv s) | aenv' <- evalExtend aenv Empty+ = evalSeq cfg s aenv'++evalSeq :: forall aenv arrs.+ SeqConfig+ -> PreOpenSeq DelayedOpenAcc aenv () arrs+ -> Val aenv -> arrs+evalSeq conf s aenv = evalSeq' s+ where+ evalSeq' :: PreOpenSeq DelayedOpenAcc aenv senv arrs -> arrs+ evalSeq' (Producer _ s) = evalSeq' s+ evalSeq' (Consumer _) = loop (initSeq aenv s)+ evalSeq' (Reify _) = reify (initSeq aenv s)++ -- Initialize the producers and the accumulators of the consumers+ -- with the given array enviroment.+ initSeq :: forall senv arrs'.+ Val aenv+ -> PreOpenSeq DelayedOpenAcc aenv senv arrs'+ -> ExecSeq senv arrs'+ initSeq aenv s =+ case s of+ Producer p s' -> ExecP window0 (initProducer p) (initSeq aenv s')+ Consumer c -> ExecC (initConsumer c)+ Reify ix -> ExecR (cursor0 ix)++ -- Generate a list from the sequence.+ reify :: forall arrs. ExecSeq () [arrs]+ -> [arrs]+ reify s = case step s Empty' of+ (Just s', a) -> a ++ reify s'+ (Nothing, a) -> a++ -- Iterate the given sequence until it terminates.+ -- A sequence only terminates when one of the producers are exhausted.+ loop :: Arrays arrs+ => ExecSeq () arrs+ -> arrs+ loop s =+ case step' s of+ (Nothing, arrs) -> arrs+ (Just s', _) -> loop s'++ where+ step' :: ExecSeq () arrs -> (Maybe (ExecSeq () arrs), arrs)+ step' s = step s Empty'++ -- One iteration of a sequence.+ step :: forall senv arrs'.+ ExecSeq senv arrs'+ -> Val' senv+ -> (Maybe (ExecSeq senv arrs'), arrs')+ step s senv =+ case s of+ ExecP w p s' ->+ let (c, mp') = produce p senv+ finished = 0 == clen (w !# minCursor s')+ w' = if finished then moveWin w c else w+ (ms'', a) = step s' (senv `Push'` w')+ in case ms'' of+ Nothing -> (Nothing, a)+ Just s'' | finished+ , Just p' <- mp'+ -> (Just (ExecP w' p' s''), a)+ | not finished+ -> (Just (ExecP w' p s''), a)+ | otherwise+ -> (Nothing, a)+ ExecC c -> let (c', acc) = consume c senv+ in (Just (ExecC c'), acc)+ ExecR ix -> let c = prjChunk ix senv in (Just (ExecR (moveCursor (clen c) ix)), toListChunk c)++ evalA :: DelayedOpenAcc aenv a -> a+ evalA acc = evalOpenAcc acc aenv++ evalAF :: DelayedOpenAfun aenv f -> f+ evalAF f = evalOpenAfun f aenv++ evalE :: DelayedExp aenv t -> t+ evalE exp = evalExp exp aenv++ evalF :: DelayedFun aenv f -> f+ evalF fun = evalFun fun aenv++ initProducer :: forall a senv.+ Producer DelayedOpenAcc aenv senv a+ -> ExecP senv a+ initProducer p =+ case p of+ StreamIn arrs -> ExecStreamIn 1 arrs+ ToSeq sliceIndex slix (delayed -> Delayed sh ix _) ->+ let n = R.size (R.sliceShape sliceIndex (fromElt sh))+ k = elemsPerChunk conf n+ in ExecStreamIn k (toSeqOp sliceIndex slix (fromFunction sh ix))+ MapSeq f x -> ExecMap (mapChunk (evalAF f)) (cursor0 x)+ ChunkedMapSeq f x -> ExecMap (evalAF f) (cursor0 x)+ ZipWithSeq f x y -> ExecZipWith (zipWithChunk (evalAF f)) (cursor0 x) (cursor0 y)+ ScanSeq f e x -> ExecScan scanner (evalE e) (cursor0 x)+ where+ scanner a c =+ let v0 = chunkElems c+ (v1, a') = scanl'Op (evalF f) a (delayArray v0)+ in (vec2Chunk v1, fromScalar a')++ initConsumer :: forall a senv.+ Consumer DelayedOpenAcc aenv senv a+ -> ExecC senv a+ initConsumer c =+ case c of+ FoldSeq f e x ->+ let f' = evalF f+ a0 = fromFunction (Z :. chunkSize conf) (const (evalE e))+ consumer v c = zipWith'Op f' (delayArray v) (delayArray (chunkElems c))+ finalizer = fold1Op f' . delayArray+ in ExecFold consumer finalizer a0 (cursor0 x)+ FoldSeqFlatten f acc x ->+ let f' = evalAF f+ a0 = evalA acc+ consumer a c = f' a (chunkShapes c) (chunkElems c)+ in ExecFold consumer id a0 (cursor0 x)+ Stuple t ->+ let initTup :: Atuple (Consumer DelayedOpenAcc aenv senv) t -> Atuple (ExecC senv) t+ initTup NilAtup = NilAtup+ initTup (SnocAtup t c) = SnocAtup (initTup t) (initConsumer c)+ in ExecStuple (initTup t)++ delayed :: DelayedOpenAcc aenv (Array sh e) -> Delayed (Array sh e)+ delayed AST.Manifest{} = $internalError "evalOpenAcc" "expected delayed array"+ delayed AST.Delayed{..} = Delayed (evalExp extentD aenv)+ (evalFun indexD aenv)+ (evalFun linearIndexD aenv)++produce :: Arrays a => ExecP senv a -> Val' senv -> (Chunk a, Maybe (ExecP senv a))+produce p senv =+ case p of+ ExecStreamIn k xs ->+ let (xs', xs'') = (take k xs, drop k xs)+ c = fromListChunk xs'+ mp = if null xs''+ then Nothing+ else Just (ExecStreamIn k xs'')+ in (c, mp)+ ExecMap f x ->+ let c = prjChunk x senv+ in (f c, Just $ ExecMap f (moveCursor (clen c) x))+ ExecZipWith f x y ->+ let c1 = prjChunk x senv+ c2 = prjChunk y senv+ k = clen c1 `min` clen c2+ in (f c1 c2, Just $ ExecZipWith f (moveCursor k x) (moveCursor k y))+ ExecScan scanner a x ->+ let c = prjChunk x senv+ (c', a') = scanner a c+ k = clen c+ in (c', Just $ ExecScan scanner a' (moveCursor k x))++consume :: forall senv a. ExecC senv a -> Val' senv -> (ExecC senv a, a)+consume c senv =+ case c of+ ExecFold f g acc x ->+ let c = prjChunk x senv+ acc' = f acc c+ -- Even though we call g here, lazy evaluation should guarantee it is+ -- only ever called once.+ in (ExecFold f g acc' (moveCursor (clen c) x), g acc')+ ExecStuple t ->+ let consT :: Atuple (ExecC senv) t -> (Atuple (ExecC senv) t, t)+ consT NilAtup = (NilAtup, ())+ consT (SnocAtup t c) | (c', acc) <- consume c senv+ , (t', acc') <- consT t+ = (SnocAtup t' c', (acc', acc))+ (t', acc) = consT t+ in (ExecStuple t', toAtuple acc)++evalExtend :: Extend DelayedOpenAcc aenv aenv' -> Val aenv -> Val aenv'+evalExtend BaseEnv aenv = aenv+evalExtend (PushEnv ext1 ext2) aenv | aenv' <- evalExtend ext1 aenv+ = Push aenv' (evalOpenAcc ext2 aenv')++delayArray :: Array sh e -> Delayed (Array sh e)+delayArray arr@(Array _ adata) = Delayed (shape arr) (arr!) (toElt . unsafeIndexArrayData adata)++fromScalar :: Scalar a -> a+fromScalar = (!Z)++concatOp :: forall e. Elt e => [Vector e] -> Vector e+concatOp = concatVectors++fetchAllOp :: (Shape sh, Elt e) => Segments sh -> Vector e -> [Array sh e]+fetchAllOp segs elts+ | (offsets, n) <- offsetsOp segs+ , (n ! Z) <= size (shape elts)+ = [fetch (segs ! (Z :. i)) (offsets ! (Z :. i)) | i <- [0 .. size (shape segs) - 1]]+ | otherwise = error $ "illegal argument to fetchAllOp"+ where+ fetch sh offset = fromFunction sh (\ ix -> elts ! (Z :. ((toIndex sh ix) + offset)))++dropOp :: Elt e => Int -> Vector e -> Vector e+dropOp i v -- TODO+ -- * Implement using C-style pointer-plus.+ -- ; dropOp is used often (from prjChunk),+ -- so it ought to be efficient O(1).+ | n <- size (shape v)+ , i <= n+ , i >= 0+ = fromFunction (Z :. n - i) (\ (Z :. j) -> v ! (Z :. i + j))+ | otherwise = error $ "illegal argument to drop"++offsetsOp :: Shape sh => Segments sh -> (Vector Int, Scalar Int)+offsetsOp segs = scanl'Op (+) 0 $ delayArray (mapOp size (delayArray segs))+--}+
+ src/Data/Array/Accelerate/Language.hs view
@@ -0,0 +1,1517 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE ViewPatterns #-}+-- |+-- Module : Data.Array.Accelerate.Language+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- We use the dictionary view of overloaded operations (such as arithmetic and+-- bit manipulation) to reify such expressions. With non-overloaded+-- operations (such as, the logical connectives) and partially overloaded+-- operations (such as comparisons), we use the standard operator names with a+-- \'*\' attached. We keep the standard alphanumeric names as they can be+-- easily qualified.+--++module Data.Array.Accelerate.Language (++ -- * Array construction+ use, unit, replicate, generate,++ -- * Shape manipulation+ reshape,++ -- * Extraction of sub-arrays+ slice,++ -- * Map-like functions+ map, zipWith,++ -- -- * Sequence collection+ -- collect,++ -- -- * Sequence producers+ -- streamIn, toSeq,++ -- -- * Sequence transducers+ -- mapSeq, zipWithSeq, scanSeq,++ -- -- * Sequence consumers+ -- foldSeq, foldSeqFlatten,++ -- * Reductions+ fold, fold1, foldSeg', fold1Seg',++ -- * Scan functions+ scanl, scanl', scanl1, scanr, scanr', scanr1,++ -- * Permutations+ permute, backpermute,++ -- * Stencil operations+ stencil, stencil2,++ -- ** Stencil specification+ Boundary, Stencil,+ clamp, mirror, wrap, function,+++ -- ** Common stencil types+ Stencil3, Stencil5, Stencil7, Stencil9,+ Stencil3x3, Stencil5x3, Stencil3x5, Stencil5x5,+ Stencil3x3x3, Stencil5x3x3, Stencil3x5x3, Stencil3x3x5, Stencil5x5x3, Stencil5x3x5,+ Stencil3x5x5, Stencil5x5x5,++ -- * Foreign functions+ foreignAcc,+ foreignExp,++ -- * Pipelining+ (>->),++ -- * Index construction and destruction+ indexHead, indexTail, toIndex, fromIndex,+ intersect, union,++ -- * Flow-control+ acond, awhile,+ cond, while,++ -- * Array operations with a scalar result+ (!), (!!), shape, size, shapeSize,++ -- * Numeric functions+ subtract, even, odd, gcd, lcm, (^), (^^),++ -- * Conversions+ ord, chr, boolToInt, bitcast,++) where++import Data.Array.Accelerate.AST ( PrimFun(..) )+import Data.Array.Accelerate.Pattern+import Data.Array.Accelerate.Representation.Array ( ArrayR(..) )+import Data.Array.Accelerate.Representation.Shape ( ShapeR(..) )+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Smart hiding ( arraysR )+import Data.Array.Accelerate.Sugar.Array ( Arrays(..), Array, Scalar, Segments, arrayR )+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Sugar.Foreign+import Data.Array.Accelerate.Sugar.Shape ( Shape(..), Slice(..), (:.) )+import Data.Array.Accelerate.Type+import qualified Data.Array.Accelerate.Representation.Array as R++import Data.Array.Accelerate.Classes.Eq+import Data.Array.Accelerate.Classes.Fractional+import Data.Array.Accelerate.Classes.Integral+import Data.Array.Accelerate.Classes.Num+import Data.Array.Accelerate.Classes.Ord++import Prelude ( ($), (.), Maybe(..), Char )+#if __GLASGOW_HASKELL__ >= 904+import Data.Type.Equality+#endif+++-- $setup+-- >>> :seti -XFlexibleContexts+-- >>> :seti -XScopedTypeVariables+-- >>> :seti -XTypeApplications+-- >>> :seti -XTypeOperators+-- >>> :seti -XViewPatterns+-- >>> import Data.Array.Accelerate+-- >>> import Data.Array.Accelerate.Data.Maybe+-- >>> import Data.Array.Accelerate.Interpreter+-- >>> :{+-- let runExp :: Elt e => Exp e -> e+-- runExp e = indexArray (run (unit e)) Z+-- :}++-- Array introduction+-- ------------------++-- | Make an array from vanilla Haskell available for processing within embedded+-- Accelerate computations.+--+-- Depending upon which backend is used to eventually execute array+-- computations, 'use' may entail data transfer (e.g. to a GPU).+--+-- 'use' is overloaded so that it can accept tuples of 'Arrays':+--+-- >>> let vec = fromList (Z:.10) [0..] :: Vector Int+-- >>> vec+-- Vector (Z :. 10) [0,1,2,3,4,5,6,7,8,9]+--+-- >>> let mat = fromList (Z:.5:.10) [0..] :: Matrix Int+-- >>> mat+-- Matrix (Z :. 5 :. 10)+-- [ 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]+--+-- >>> let vec' = use vec :: Acc (Vector Int)+-- >>> let mat' = use mat :: Acc (Matrix Int)+-- >>> let tup = use (vec, mat) :: Acc (Vector Int, Matrix Int)+--+use :: forall arrays. Arrays arrays => arrays -> Acc arrays+use = Acc . use' (arraysR @arrays) . fromArr+ where+ use' :: R.ArraysR a -> a -> SmartAcc a+ use' TupRunit () = SmartAcc $ Anil+ use' (TupRsingle repr@ArrayR{}) a = SmartAcc $ Use repr a+ use' (TupRpair r1 r2) (a1, a2) = SmartAcc $ use' r1 a1 `Apair` use' r2 a2++-- | Construct a singleton (one element) array from a scalar value (or tuple of+-- scalar values).+--+unit :: forall e. Elt e => Exp e -> Acc (Scalar e)+unit (Exp e) = Acc $ SmartAcc $ Unit (eltR @e) e++-- | Replicate an array across one or more dimensions as specified by the+-- /generalised/ array index provided as the first argument.+--+-- For example, given the following vector:+--+-- >>> let vec = fromList (Z:.10) [0..] :: Vector Int+-- >>> vec+-- Vector (Z :. 10) [0,1,2,3,4,5,6,7,8,9]+--+-- ...we can replicate these elements to form a two-dimensional array either by+-- replicating those elements as new rows:+--+-- >>> run $ replicate (constant (Z :. (4::Int) :. All)) (use vec)+-- Matrix (Z :. 4 :. 10)+-- [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,+-- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,+-- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,+-- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]+--+-- ...or as columns:+--+-- >>> run $ replicate (lift (Z :. All :. (4::Int))) (use vec)+-- Matrix (Z :. 10 :. 4)+-- [ 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]+--+-- Replication along more than one dimension is also possible. Here we replicate+-- twice across the first dimension and three times across the third dimension:+--+-- >>> run $ replicate (constant (Z :. (2::Int) :. All :. (3::Int))) (use vec)+-- Array (Z :. 2 :. 10 :. 3) [0,0,0,1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,8,8,8,9,9,9,0,0,0,1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,8,8,8,9,9,9]+--+-- The marker 'Any' can be used in the slice specification to match against some+-- arbitrary dimension. For example, here 'Any' matches against whatever shape+-- type variable @sh@ takes.+--+-- >>> :{+-- let rep0 :: forall sh e. (Shape sh, Elt e) => Exp Int -> Acc (Array sh e) -> Acc (Array (sh :. Int) e)+-- rep0 n a = replicate (lift (Any @sh :. n)) a+-- :}+--+-- >>> let x = unit 42 :: Acc (Scalar Int)+-- >>> run $ rep0 10 x+-- Vector (Z :. 10) [42,42,42,42,42,42,42,42,42,42]+--+-- >>> run $ rep0 5 (use vec)+-- Matrix (Z :. 10 :. 5)+-- [ 0, 0, 0, 0, 0,+-- 1, 1, 1, 1, 1,+-- 2, 2, 2, 2, 2,+-- 3, 3, 3, 3, 3,+-- 4, 4, 4, 4, 4,+-- 5, 5, 5, 5, 5,+-- 6, 6, 6, 6, 6,+-- 7, 7, 7, 7, 7,+-- 8, 8, 8, 8, 8,+-- 9, 9, 9, 9, 9]+--+-- Of course, 'Any' and 'All' can be used together.+--+-- >>> :{+-- let rep1 :: forall sh e. (Shape sh, Elt e) => Exp Int -> Acc (Array (sh :. Int) e) -> Acc (Array (sh :. Int :. Int) e)+-- rep1 n a = replicate (lift (Any @sh :. n :. All)) a+-- :}+--+-- >>> run $ rep1 5 (use vec)+-- Matrix (Z :. 5 :. 10)+-- [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,+-- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,+-- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,+-- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,+-- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]+--+replicate+ :: forall slix e.+ (Slice slix, Elt e)+ => Exp slix+ -> Acc (Array (SliceShape slix) e)+ -> Acc (Array (FullShape slix) e)+replicate = Acc $$ applyAcc (Replicate $ sliceIndex @slix)++-- | Construct a new array by applying a function to each index.+--+-- For example, the following will generate a one-dimensional array+-- (`Vector`) of three floating point numbers:+--+-- >>> run $ generate (I1 3) (\_ -> 1.2) :: Vector Float+-- Vector (Z :. 3) [1.2,1.2,1.2]+--+-- Or equivalently:+--+-- >>> run $ fill (constant (Z :. 3)) 1.2 :: Vector Float+-- Vector (Z :. 3) [1.2,1.2,1.2]+--+-- The following will create a vector with the elements @[1..10]@:+--+-- >>> run $ generate (I1 10) (\(I1 i) -> i + 1) :: Vector Int+-- Vector (Z :. 10) [1,2,3,4,5,6,7,8,9,10]+--+-- [/NOTE:/]+--+-- Using 'generate', it is possible to introduce nested data parallelism, which+-- will cause the program to fail.+--+-- If the index given by the scalar function is then used to dispatch further+-- parallel work, whose result is returned into 'Exp' terms by array indexing+-- operations such as ('!') or 'Data.Array.Accelerate.Prelude.the', the program+-- will fail with the error:+-- @.\/Data\/Array\/Accelerate\/Trafo\/Sharing.hs:447 (convertSharingExp): inconsistent valuation \@ shared \'Exp\' tree ...@.+--+generate+ :: forall sh a.+ (Shape sh, Elt a)+ => Exp sh+ -> (Exp sh -> Exp a)+ -> Acc (Array sh a)+generate = Acc $$ applyAcc (Generate $ arrayR @sh @a)++-- Shape manipulation+-- ------------------++-- | Change the shape of an array without altering its contents. The 'size' of+-- the source and result arrays must be identical.+--+-- > precondition: shapeSize sh == shapeSize sh'+--+-- If the argument array is manifest in memory, 'reshape' is a no-op. If the+-- argument is to be fused into a subsequent operation, 'reshape' corresponds to+-- an index transformation in the fused code.+--+reshape+ :: forall sh sh' e.+ (Shape sh, Shape sh', Elt e)+ => Exp sh+ -> Acc (Array sh' e)+ -> Acc (Array sh e)+reshape = Acc $$ applyAcc (Reshape $ shapeR @sh)++-- Extraction of sub-arrays+-- ------------------------++-- | Index an array with a /generalised/ array index, supplied as the second+-- argument. The result is a new array (possibly a singleton) containing the+-- selected dimensions ('All's) in their entirety.+--+-- 'slice' is the opposite of 'replicate', and can be used to /cut out/ entire+-- dimensions. For example, for the two dimensional array 'mat':+--+-- >>> let mat = fromList (Z:.5:.10) [0..] :: Matrix Int+-- >>> mat+-- Matrix (Z :. 5 :. 10)+-- [ 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]+--+-- ...will can select a specific row to yield a one dimensional result by fixing+-- the row index (2) while allowing the column index to vary (via 'All'):+--+-- >>> run $ slice (use mat) (constant (Z :. (2::Int) :. All))+-- Vector (Z :. 10) [20,21,22,23,24,25,26,27,28,29]+--+-- A fully specified index (with no 'All's) returns a single element (zero+-- dimensional array).+--+-- >>> run $ slice (use mat) (constant (Z :. 4 :. 2 :: DIM2))+-- Scalar Z [42]+--+-- The marker 'Any' can be used in the slice specification to match against some+-- arbitrary (lower) dimension. Here 'Any' matches whatever shape type variable+-- @sh@ takes:+--+-- >>> :{+-- let+-- sl0 :: forall sh e. (Shape sh, Elt e) => Acc (Array (sh:.Int) e) -> Exp Int -> Acc (Array sh e)+-- sl0 a n = slice a (lift (Any @sh :. n))+-- :}+--+-- >>> let vec = fromList (Z:.10) [0..] :: Vector Int+-- >>> run $ sl0 (use vec) 4+-- Scalar Z [4]+--+-- >>> run $ sl0 (use mat) 4+-- Vector (Z :. 5) [4,14,24,34,44]+--+-- Of course, 'Any' and 'All' can be used together.+--+-- >>> :{+-- let sl1 :: forall sh e. (Shape sh, Elt e) => Acc (Array (sh:.Int:.Int) e) -> Exp Int -> Acc (Array (sh:.Int) e)+-- sl1 a n = slice a (lift (Any @sh :. n :. All))+-- :}+--+-- >>> run $ sl1 (use mat) 4+-- Vector (Z :. 10) [40,41,42,43,44,45,46,47,48,49]+--+-- >>> let cube = fromList (Z:.3:.4:.5) [0..] :: Array DIM3 Int+-- >>> cube+-- Array (Z :. 3 :. 4 :. 5) [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]+--+-- >>> run $ sl1 (use cube) 2+-- Matrix (Z :. 3 :. 5)+-- [ 10, 11, 12, 13, 14,+-- 30, 31, 32, 33, 34,+-- 50, 51, 52, 53, 54]+--+slice :: forall slix e.+ (Slice slix, Elt e)+ => Acc (Array (FullShape slix) e)+ -> Exp slix+ -> Acc (Array (SliceShape slix) e)+slice = Acc $$ applyAcc (Slice $ sliceIndex @slix)++-- Map-like functions+-- ------------------++-- | Apply the given function element-wise to an array. Denotationally we have:+--+-- > map f [x1, x2, ... xn] = [f x1, f x2, ... f xn]+--+-- >>> let xs = fromList (Z:.10) [0..] :: Vector Int+-- >>> xs+-- Vector (Z :. 10) [0,1,2,3,4,5,6,7,8,9]+--+-- >>> run $ map (+1) (use xs)+-- Vector (Z :. 10) [1,2,3,4,5,6,7,8,9,10]+--+map :: forall sh a b.+ (Shape sh, Elt a, Elt b)+ => (Exp a -> Exp b)+ -> Acc (Array sh a)+ -> Acc (Array sh b)+map = Acc $$ applyAcc (Map (eltR @a) (eltR @b))++-- | Apply the given binary function element-wise to the two arrays. The extent+-- of the resulting array is the intersection of the extents of the two source+-- arrays.+--+-- >>> let xs = fromList (Z:.3:.5) [0..] :: Matrix Int+-- >>> xs+-- Matrix (Z :. 3 :. 5)+-- [ 0, 1, 2, 3, 4,+-- 5, 6, 7, 8, 9,+-- 10, 11, 12, 13, 14]+--+-- >>> let ys = fromList (Z:.5:.10) [1..] :: Matrix Int+-- >>> ys+-- Matrix (Z :. 5 :. 10)+-- [ 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]+--+-- >>> run $ zipWith (+) (use xs) (use ys)+-- Matrix (Z :. 3 :. 5)+-- [ 1, 3, 5, 7, 9,+-- 16, 18, 20, 22, 24,+-- 31, 33, 35, 37, 39]+--+zipWith :: forall sh a b c.+ (Shape sh, Elt a, Elt b, Elt c)+ => (Exp a -> Exp b -> Exp c)+ -> Acc (Array sh a)+ -> Acc (Array sh b)+ -> Acc (Array sh c)+zipWith = Acc $$$ applyAcc (ZipWith (eltR @a) (eltR @b) (eltR @c))++-- Reductions+-- ----------++-- | Reduction of the innermost dimension of an array of arbitrary rank.+--+-- The shape of the result obeys the property:+--+-- > shape (fold f z xs) == indexTail (shape xs)+--+-- The first argument needs to be an /associative/ function to enable an+-- efficient parallel implementation. The initial element does not need to be an+-- identity element of the combination function.+--+-- >>> let mat = fromList (Z:.5:.10) [0..] :: Matrix Int+-- >>> mat+-- Matrix (Z :. 5 :. 10)+-- [ 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]+--+-- >>> run $ fold (+) 42 (use mat)+-- Vector (Z :. 5) [87,187,287,387,487]+--+-- Reductions with non-commutative operators are supported. For example, the+-- following computes the maximum segment sum problem along each innermost+-- dimension of the array.+--+-- <https://en.wikipedia.org/wiki/Maximum_subarray_problem>+--+-- >>> :{+-- let maximumSegmentSum+-- :: forall sh e. (Shape sh, Num e, Ord e)+-- => Acc (Array (sh :. Int) e)+-- -> Acc (Array sh e)+-- maximumSegmentSum+-- = map (\(T4 x _ _ _) -> x)+-- . fold1 f+-- . map g+-- where+-- f :: (Num a, Ord a) => Exp (a,a,a,a) -> Exp (a,a,a,a) -> Exp (a,a,a,a)+-- f x y =+-- let T4 mssx misx mcsx tsx = x+-- T4 mssy misy mcsy tsy = y+-- in+-- T4 (mssx `max` (mssy `max` (mcsx+misy)))+-- (misx `max` (tsx+misy))+-- (mcsy `max` (mcsx+tsy))+-- (tsx+tsy)+-- --+-- g :: (Num a, Ord a) => Exp a -> Exp (a,a,a,a)+-- g x = let y = max x 0+-- in T4 y y y x+-- :}+--+-- >>> let vec = fromList (Z:.10) [-2,1,-3,4,-1,2,1,-5,4,0] :: Vector Int+-- >>> run $ maximumSegmentSum (use vec)+-- Scalar Z [6]+--+-- See also 'Data.Array.Accelerate.Data.Fold.Fold', which can be a useful way to+-- compute multiple results from a single reduction.+--+fold :: forall sh a.+ (Shape sh, Elt a)+ => (Exp a -> Exp a -> Exp a)+ -> Exp a+ -> Acc (Array (sh:.Int) a)+ -> Acc (Array sh a)+fold f (Exp x) = Acc . applyAcc (Fold (eltR @a) (unExpBinaryFunction f) (Just x))++-- | Variant of 'fold' that requires the innermost dimension of the array to be+-- non-empty and doesn't need an default value.+--+-- The shape of the result obeys the property:+--+-- > shape (fold f z xs) == indexTail (shape xs)+--+-- The first argument needs to be an /associative/ function to enable an+-- efficient parallel implementation, but does not need to be commutative.+--+fold1 :: forall sh a.+ (Shape sh, Elt a)+ => (Exp a -> Exp a -> Exp a)+ -> Acc (Array (sh:.Int) a)+ -> Acc (Array sh a)+fold1 f = Acc . applyAcc (Fold (eltR @a) (unExpBinaryFunction f) Nothing)++-- | Segmented reduction along the innermost dimension of an array. The+-- segment descriptor specifies the starting index (offset) along the+-- innermost dimension to the beginning of each logical sub-array.+--+-- The value in the output array at index i is the reduction of values+-- between the indices of the segment descriptor at index i and (i+1).+--+-- We have that:+--+-- > foldSeg f z xs seg == foldSeg' f z xs (scanl (+) 0 seg)+--+-- @since 1.3.0.0+--+foldSeg'+ :: forall sh a i.+ (Shape sh, Elt a, Elt i, IsIntegral i, i ~ EltR i)+ => (Exp a -> Exp a -> Exp a)+ -> Exp a+ -> Acc (Array (sh:.Int) a)+ -> Acc (Segments i)+ -> Acc (Array (sh:.Int) a)+foldSeg' f (Exp x) = Acc $$ applyAcc (FoldSeg (integralType @i) (eltR @a) (unExpBinaryFunction f) (Just x))++-- | Variant of 'foldSeg'' that requires /all/ segments of the reduced+-- array to be non-empty, and doesn't need a default value. The segment+-- descriptor specifies the offset to the beginning of each of the logical+-- sub-arrays.+--+-- @since 1.3.0.0+--+fold1Seg'+ :: forall sh a i.+ (Shape sh, Elt a, Elt i, IsIntegral i, i ~ EltR i)+ => (Exp a -> Exp a -> Exp a)+ -> Acc (Array (sh:.Int) a)+ -> Acc (Segments i)+ -> Acc (Array (sh:.Int) a)+fold1Seg' f = Acc $$ applyAcc (FoldSeg (integralType @i) (eltR @a) (unExpBinaryFunction f) Nothing)++-- Scan functions+-- --------------++-- | Data.List style left-to-right scan along the innermost dimension of an+-- arbitrary rank array. The first argument needs to be an /associative/+-- function to enable efficient parallel implementation. The initial value+-- (second argument) may be arbitrary.+--+-- >>> let vec = fromList (Z :. 10) [0..] :: Vector Int+-- >>> run $ scanl (+) 10 (use vec)+-- Vector (Z :. 11) [10,10,11,13,16,20,25,31,38,46,55]+--+-- >>> let mat = fromList (Z :. 4 :. 10) [0..] :: Matrix Int+-- >>> run $ scanl (+) 0 (use mat)+-- Matrix (Z :. 4 :. 11)+-- [ 0, 0, 1, 3, 6, 10, 15, 21, 28, 36, 45,+-- 0, 10, 21, 33, 46, 60, 75, 91, 108, 126, 145,+-- 0, 20, 41, 63, 86, 110, 135, 161, 188, 216, 245,+-- 0, 30, 61, 93, 126, 160, 195, 231, 268, 306, 345]+--+scanl :: forall sh a.+ (Shape sh, Elt a)+ => (Exp a -> Exp a -> Exp a)+ -> Exp a+ -> Acc (Array (sh:.Int) a)+ -> Acc (Array (sh:.Int) a)+scanl f (Exp x) (Acc a) = Acc $ SmartAcc $ Scan LeftToRight (eltR @a) (unExpBinaryFunction f) (Just x) a++-- | Variant of 'scanl', where the last element (final reduction result) along+-- each dimension is returned separately. Denotationally we have:+--+-- > scanl' f e arr = (init res, unit (res!len))+-- > where+-- > len = shape arr+-- > res = scanl f e arr+--+-- >>> let vec = fromList (Z:.10) [0..] :: Vector Int+-- >>> let (res,sum) = run $ scanl' (+) 0 (use vec)+-- >>> res+-- Vector (Z :. 10) [0,0,1,3,6,10,15,21,28,36]+-- >>> sum+-- Scalar Z [45]+--+-- >>> let mat = fromList (Z:.4:.10) [0..] :: Matrix Int+-- >>> let (res,sums) = run $ scanl' (+) 0 (use mat)+-- >>> res+-- Matrix (Z :. 4 :. 10)+-- [ 0, 0, 1, 3, 6, 10, 15, 21, 28, 36,+-- 0, 10, 21, 33, 46, 60, 75, 91, 108, 126,+-- 0, 20, 41, 63, 86, 110, 135, 161, 188, 216,+-- 0, 30, 61, 93, 126, 160, 195, 231, 268, 306]+-- >>> sums+-- Vector (Z :. 4) [45,145,245,345]+--+scanl' :: forall sh a.+ (Shape sh, Elt a)+ => (Exp a -> Exp a -> Exp a)+ -> Exp a+ -> Acc (Array (sh:.Int) a)+ -> Acc (Array (sh:.Int) a, Array sh a)+scanl' = Acc . mkPairToTuple $$$ applyAcc (Scan' LeftToRight $ eltR @a)++-- | Data.List style left-to-right scan along the innermost dimension without an+-- initial value (aka inclusive scan). The innermost dimension of the array must+-- not be empty. The first argument must be an /associative/ function.+--+-- >>> let mat = fromList (Z:.4:.10) [0..] :: Matrix Int+-- >>> run $ scanl1 (+) (use mat)+-- Matrix (Z :. 4 :. 10)+-- [ 0, 1, 3, 6, 10, 15, 21, 28, 36, 45,+-- 10, 21, 33, 46, 60, 75, 91, 108, 126, 145,+-- 20, 41, 63, 86, 110, 135, 161, 188, 216, 245,+-- 30, 61, 93, 126, 160, 195, 231, 268, 306, 345]+--+scanl1 :: forall sh a.+ (Shape sh, Elt a)+ => (Exp a -> Exp a -> Exp a)+ -> Acc (Array (sh:.Int) a)+ -> Acc (Array (sh:.Int) a)+scanl1 f (Acc a) = Acc $ SmartAcc $ Scan LeftToRight (eltR @a) (unExpBinaryFunction f) Nothing a++-- | Right-to-left variant of 'scanl'.+--+scanr :: forall sh a.+ (Shape sh, Elt a)+ => (Exp a -> Exp a -> Exp a)+ -> Exp a+ -> Acc (Array (sh:.Int) a)+ -> Acc (Array (sh:.Int) a)+scanr f (Exp x) (Acc a) = Acc $ SmartAcc $ Scan RightToLeft (eltR @a) (unExpBinaryFunction f) (Just x) a++-- | Right-to-left variant of 'scanl''.+--+scanr' :: forall sh a.+ (Shape sh, Elt a)+ => (Exp a -> Exp a -> Exp a)+ -> Exp a+ -> Acc (Array (sh:.Int) a)+ -> Acc (Array (sh:.Int) a, Array sh a)+scanr' = Acc . mkPairToTuple $$$ applyAcc (Scan' RightToLeft $ eltR @a)++-- | Right-to-left variant of 'scanl1'.+--+scanr1 :: forall sh a.+ (Shape sh, Elt a)+ => (Exp a -> Exp a -> Exp a)+ -> Acc (Array (sh:.Int) a)+ -> Acc (Array (sh:.Int) a)+scanr1 f (Acc a) = Acc $ SmartAcc $ Scan RightToLeft (eltR @a) (unExpBinaryFunction f) Nothing a++-- Permutations+-- ------------++-- | Generalised forward permutation operation (array scatter).+--+-- Forward permutation specified by a function mapping indices from the source+-- array to indices in the result array. The result array is initialised with+-- the given defaults and any further values that are permuted into the result+-- array are added to the current value using the given combination function.+--+-- The combination function must be /associative/ and /commutative/.+-- Elements for which the permutation function returns 'Nothing' are+-- dropped.+--+-- The combination function is given the new value being permuted as its first+-- argument, and the current value of the array as its second.+--+-- For example, we can use 'permute' to compute the occurrence count (histogram)+-- for an array of values in the range @[0,10)@:+--+-- >>> :{+-- let histogram :: Acc (Vector Int) -> Acc (Vector Int)+-- histogram xs =+-- let zeros = fill (constant (Z:.10)) 0+-- ones = fill (shape xs) 1+-- in+-- permute (+) zeros (\ix -> Just_ (I1 (xs!ix))) ones+-- :}+--+-- >>> let xs = fromList (Z :. 20) [0,0,1,2,1,1,2,4,8,3,4,9,8,3,2,5,5,3,1,2] :: Vector Int+-- >>> run $ histogram (use xs)+-- Vector (Z :. 10) [2,4,4,3,2,2,0,0,2,1]+--+-- As a second example, note that the dimensionality of the source and+-- destination arrays can differ. In this way, we can use 'permute' to create an+-- identity matrix by overwriting elements along the diagonal:+--+-- >>> :{+-- let identity :: Num a => Exp Int -> Acc (Matrix a)+-- identity n =+-- let zeros = fill (I2 n n) 0+-- ones = fill (I1 n) 1+-- in+-- permute const zeros (\(I1 i) -> Just_ (I2 i i)) ones+-- :}+--+-- >>> run $ identity 5 :: Matrix Int+-- Matrix (Z :. 5 :. 5)+-- [ 1, 0, 0, 0, 0,+-- 0, 1, 0, 0, 0,+-- 0, 0, 1, 0, 0,+-- 0, 0, 0, 1, 0,+-- 0, 0, 0, 0, 1]+--+-- [/Note:/]+--+-- Regarding array fusion:+--+-- 1. The 'permute' operation will always be evaluated; it can not be fused+-- into a later step.+--+-- 2. Since the index permutation function might not cover all positions in+-- the output array (the function is not surjective), the array of default+-- values must be evaluated. However, other operations may fuse into this.+--+-- 3. The array of source values can fuse into the permutation operation.+--+-- 4. If the array of default values is only used once, it will be updated+-- in-place. This behaviour can be disabled this with @-fno-inplace@.+--+-- Regarding the defaults array:+--+-- If you are sure that the default values are not necessary---they are not used+-- by the combination function and every element will be overwritten---a default+-- array created by 'Data.Array.Accelerate.Prelude.fill'ing with the value+-- 'Data.Array.Accelerate.Unsafe.undef' will give you a new uninitialised array.+--+-- Regarding the combination function:+--+-- The function 'const' can be used to replace elements of the defaults+-- array with the new values. If the permutation function maps multiple+-- values to the same location in the results array (the function is not+-- injective) then this operation is non-deterministic.+--+-- Since Accelerate uses an unzipped struct-of-array representation, where+-- the individual components of product types (for example, pairs) are+-- stored in separate arrays, storing values of product type requires+-- multiple store instructions.+--+-- Accelerate prior to version 1.3.0.0 performs this operation atomically,+-- to ensure that the stored values are always consistent (each component+-- of the product type is written by the same thread). Later versions relax+-- this restriction, but this behaviour can be disabled with+-- @-fno-fast-permute-const@.+--+permute+ :: forall sh sh' a. (Shape sh, Shape sh', Elt a)+ => (Exp a -> Exp a -> Exp a) -- ^ combination function+ -> Acc (Array sh' a) -- ^ array of default values+ -> (Exp sh -> Exp (Maybe sh')) -- ^ index permutation function+ -> Acc (Array sh a) -- ^ array of source values to be permuted+ -> Acc (Array sh' a)+permute = Acc $$$$ applyAcc (Permute $ arrayR @sh @a)++-- | Generalised backward permutation operation (array gather).+--+-- Backward permutation specified by a function mapping indices in the+-- destination array to indices in the source array. Elements of the output+-- array are thus generated by reading from the corresponding index in the+-- source array.+--+-- For example, backpermute can be used to+-- 'Data.Array.Accelerate.Prelude.transpose' a matrix; at every index @Z:.y:.x@+-- in the result array, we get the value at that index by reading from the+-- source array at index @Z:.x:.y@:+--+-- >>> :{+-- let swap :: Exp DIM2 -> Exp DIM2+-- swap = lift1 f+-- where+-- f :: Z :. Exp Int :. Exp Int -> Z :. Exp Int :. Exp Int+-- f (Z:.y:.x) = Z :. x :. y+-- :}+--+-- >>> let mat = fromList (Z:.5:.10) [0..] :: Matrix Int+-- >>> mat+-- Matrix (Z :. 5 :. 10)+-- [ 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]+--+-- >>> let mat' = use mat+-- >>> run $ backpermute (swap (shape mat')) swap mat'+-- Matrix (Z :. 10 :. 5)+-- [ 0, 10, 20, 30, 40,+-- 1, 11, 21, 31, 41,+-- 2, 12, 22, 32, 42,+-- 3, 13, 23, 33, 43,+-- 4, 14, 24, 34, 44,+-- 5, 15, 25, 35, 45,+-- 6, 16, 26, 36, 46,+-- 7, 17, 27, 37, 47,+-- 8, 18, 28, 38, 48,+-- 9, 19, 29, 39, 49]+--+backpermute+ :: forall sh sh' a. (Shape sh, Shape sh', Elt a)+ => Exp sh' -- ^ shape of the result array+ -> (Exp sh' -> Exp sh) -- ^ index permutation function+ -> Acc (Array sh a) -- ^ source array+ -> Acc (Array sh' a)+backpermute = Acc $$$ applyAcc (Backpermute $ shapeR @sh')++-- Stencil operations+-- ------------------++-- Common stencil types+--++-- DIM1 stencil type+type Stencil3 a = (Exp a, Exp a, Exp a)+type Stencil5 a = (Exp a, Exp a, Exp a, Exp a, Exp a)+type Stencil7 a = (Exp a, Exp a, Exp a, Exp a, Exp a, Exp a, Exp a)+type Stencil9 a = (Exp a, Exp a, Exp a, Exp a, Exp a, Exp a, Exp a, Exp a, Exp a)++-- DIM2 stencil type+type Stencil3x3 a = (Stencil3 a, Stencil3 a, Stencil3 a)+type Stencil5x3 a = (Stencil5 a, Stencil5 a, Stencil5 a)+type Stencil3x5 a = (Stencil3 a, Stencil3 a, Stencil3 a, Stencil3 a, Stencil3 a)+type Stencil5x5 a = (Stencil5 a, Stencil5 a, Stencil5 a, Stencil5 a, Stencil5 a)++-- DIM3 stencil type+type Stencil3x3x3 a = (Stencil3x3 a, Stencil3x3 a, Stencil3x3 a)+type Stencil5x3x3 a = (Stencil5x3 a, Stencil5x3 a, Stencil5x3 a)+type Stencil3x5x3 a = (Stencil3x5 a, Stencil3x5 a, Stencil3x5 a)+type Stencil3x3x5 a = (Stencil3x3 a, Stencil3x3 a, Stencil3x3 a, Stencil3x3 a, Stencil3x3 a)+type Stencil5x5x3 a = (Stencil5x5 a, Stencil5x5 a, Stencil5x5 a)+type Stencil5x3x5 a = (Stencil5x3 a, Stencil5x3 a, Stencil5x3 a, Stencil5x3 a, Stencil5x3 a)+type Stencil3x5x5 a = (Stencil3x5 a, Stencil3x5 a, Stencil3x5 a, Stencil3x5 a, Stencil3x5 a)+type Stencil5x5x5 a = (Stencil5x5 a, Stencil5x5 a, Stencil5x5 a, Stencil5x5 a, Stencil5x5 a)+++-- | Map a stencil over an array. In contrast to 'map', the domain of a stencil+-- function is an entire /neighbourhood/ of each array element. Neighbourhoods+-- are sub-arrays centred around a focal point. They are not necessarily+-- rectangular, but they are symmetric and have an extent of at least three+-- along each axis. Due to the symmetry requirement the extent is necessarily+-- odd. The focal point is the array position that is determined by the stencil.+--+-- For those array positions where the neighbourhood extends past the boundaries+-- of the source array, a boundary condition determines the contents of the+-- out-of-bounds neighbourhood positions.+--+-- Stencil neighbourhoods are specified via nested tuples, where the nesting+-- depth is equal to the dimensionality of the array. For example, a 3x1 stencil+-- for a one-dimensional array:+--+-- > s31 :: Stencil3 a -> Exp a+-- > s31 (l,c,r) = ...+--+-- ...where @c@ is the focal point of the stencil, and @l@ and @r@ represent the+-- elements to the left and right of the focal point, respectively. Similarly,+-- a 3x3 stencil for a two-dimensional array:+--+-- > s33 :: Stencil3x3 a -> Exp a+-- > s33 ((_,t,_)+-- > ,(l,c,r)+-- > ,(_,b,_)) = ...+--+-- ...where @c@ is again the focal point and @t@, @b@, @l@ and @r@ are the+-- elements to the top, bottom, left, and right of the focal point, respectively+-- (the diagonal elements have been elided).+--+-- For example, the following computes a 5x5+-- <https://en.wikipedia.org/wiki/Gaussian_blur Gaussian blur> as a separable+-- 2-pass operation.+--+-- > type Stencil5x1 a = (Stencil3 a, Stencil5 a, Stencil3 a)+-- > type Stencil1x5 a = (Stencil3 a, Stencil3 a, Stencil3 a, Stencil3 a, Stencil3 a)+-- >+-- > convolve5x1 :: Num a => [Exp a] -> Stencil5x1 a -> Exp a+-- > convolve5x1 kernel (_, (a,b,c,d,e), _)+-- > = Prelude.sum $ Prelude.zipWith (*) kernel [a,b,c,d,e]+-- >+-- > convolve1x5 :: Num a => [Exp a] -> Stencil1x5 a -> Exp a+-- > convolve1x5 kernel ((_,a,_), (_,b,_), (_,c,_), (_,d,_), (_,e,_))+-- > = Prelude.sum $ Prelude.zipWith (*) kernel [a,b,c,d,e]+-- >+-- > gaussian = [0.06136,0.24477,0.38774,0.24477,0.06136]+-- >+-- > blur :: Num a => Acc (Matrix a) -> Acc (Matrix a)+-- > blur = stencil (convolve5x1 gaussian) clamp+-- > . stencil (convolve1x5 gaussian) clamp+--+-- [/Note:/]+--+-- Since accelerate-1.3.0.0, we allow the source array to fuse into the stencil+-- operation. However, since a stencil computation (typically) requires multiple+-- values from the source array, this means that the work of the fused operation+-- will be duplicated for each element in the stencil pattern.+--+-- For example, suppose we write:+--+-- > blur . map f+--+-- The operation `f` will be fused into each element of the first Gaussian blur+-- kernel, resulting in a stencil equivalent to:+--+-- > f_and_convolve1x5 :: Num a => (Exp a -> Exp b) -> [Exp b] -> Stencil1x5 a -> Exp b+-- > f_and_convolve1x5 f kernel ((_,a,_), (_,b,_), (_,c,_), (_,d,_), (_,e,_))+-- > = Prelude.sum $ Prelude.zipWith (*) kernel [f a, f b, f c, f d, f e]+--+-- This duplication is often beneficial, however you may choose to instead force+-- the array to be evaluated first, preventing fusion, using the+-- `Data.Array.Accelerate.Prelude.compute` operation. Benchmarking should reveal+-- which approach is best for your application.+--+stencil+ :: forall sh stencil a b.+ (Stencil sh a stencil, Elt b)+ => (stencil -> Exp b) -- ^ stencil function+ -> Boundary (Array sh a) -- ^ boundary condition+ -> Acc (Array sh a) -- ^ source array+ -> Acc (Array sh b) -- ^ destination array+stencil f (Boundary b) (Acc a)+ = Acc $ SmartAcc $ Stencil+ (stencilR @sh @a @stencil)+ (eltR @b)+ (unExp . f . stencilPrj @sh @a @stencil)+ b+ a++-- | Map a binary stencil of an array. The extent of the resulting array is the+-- intersection of the extents of the two source arrays. This is the stencil+-- equivalent of 'zipWith'.+--+stencil2+ :: forall sh stencil1 stencil2 a b c.+ (Stencil sh a stencil1, Stencil sh b stencil2, Elt c)+ => (stencil1 -> stencil2 -> Exp c) -- ^ binary stencil function+ -> Boundary (Array sh a) -- ^ boundary condition #1+ -> Acc (Array sh a) -- ^ source array #1+ -> Boundary (Array sh b) -- ^ boundary condition #2+ -> Acc (Array sh b) -- ^ source array #2+ -> Acc (Array sh c) -- ^ destination array+stencil2 f (Boundary b1) (Acc a1) (Boundary b2) (Acc a2)+ = Acc $ SmartAcc $ Stencil2+ (stencilR @sh @a @stencil1)+ (stencilR @sh @b @stencil2)+ (eltR @c)+ (\x y -> unExp $ f (stencilPrj @sh @a @stencil1 x) (stencilPrj @sh @b @stencil2 y))+ b1+ a1+ b2+ a2++-- | Boundary condition where elements of the stencil which would be+-- out-of-bounds are instead clamped to the edges of the array.+--+-- In the following 3x3 stencil, the out-of-bounds element @b@ will instead+-- return the value at position @c@:+--+-- > +------------++-- > |a |+-- > b|cd |+-- > |e |+-- > +------------++--+clamp :: Boundary (Array sh e)+clamp = Boundary Clamp++-- | Stencil boundary condition where coordinates beyond the array extent are+-- instead mirrored+--+-- In the following 5x3 stencil, the out-of-bounds element @c@ will instead+-- return the value at position @d@, and similarly the element at @b@ will+-- return the value at @e@:+--+-- > +------------++-- > |a |+-- > bc|def |+-- > |g |+-- > +------------++--+mirror :: Boundary (Array sh e)+mirror = Boundary Mirror++-- | Stencil boundary condition where coordinates beyond the array extent+-- instead wrap around the array (circular boundary conditions).+--+-- In the following 3x3 stencil, the out of bounds elements will be read as in+-- the pattern on the right.+--+-- > a bc+-- > +------------+ +------------++-- > d|ef | |ef d|+-- > g|hi | -> |hi g|+-- > | | |bc a|+-- > +------------+ +------------++--+wrap :: Boundary (Array sh e)+wrap = Boundary Wrap++-- | Stencil boundary condition where the given function is applied to any+-- outlying coordinates.+--+-- The function is passed the out-of-bounds index, so you can use it to specify+-- different boundary conditions at each side. For example, the following would+-- clamp out-of-bounds elements in the y-direction to zero, while having+-- circular boundary conditions in the x-direction.+--+-- > ring :: Acc (Matrix Float) -> Acc (Matrix Float)+-- > ring xs = stencil f boundary xs+-- > where+-- > boundary :: Boundary (Matrix Float)+-- > boundary = function $ \(unlift -> Z :. y :. x) ->+-- > if y < 0 || y >= height+-- > then 0+-- > else if x < 0+-- > then xs ! index2 y (width+x)+-- > else xs ! index2 y (x-width)+-- >+-- > f :: Stencil3x3 Float -> Exp Float+-- > f = ...+-- >+-- > Z :. height :. width = unlift (shape xs)+--+function+ :: forall sh e. (Shape sh, Elt e)+ => (Exp sh -> Exp e)+ -> Boundary (Array sh e)+function f = Boundary $ Function (f')+ where+ f' :: SmartExp (EltR sh) -> SmartExp (EltR e)+ f' = unExp . f . Exp+++{--+-- Sequence operations+-- ------------------++-- Common sequence types+--++streamIn :: Arrays a+ => [a]+ -> Seq [a]+streamIn arrs = Seq (StreamIn arrs)++-- | Convert the given array to a sequence by dividing the array up into subarrays.+-- The first argument captures how to the division should be performed. The+-- presence of `All` in the division descriptor indicates that elements in the+-- corresponding dimension should be retained in the subarrays, whereas `Split`+-- indicates that the input array should divided along this dimension.+--+toSeq :: (Division slsix, Elt a)+ => slsix+ -> Acc (Array (FullShape (DivisionSlice slsix)) a)+ -> Seq [Array (SliceShape (DivisionSlice slsix)) a]+toSeq spec acc = Seq (ToSeq spec acc)++-- | Apply the given array function element-wise to the given sequence.+--+mapSeq :: (Arrays a, Arrays b)+ => (Acc a -> Acc b)+ -> Seq [a]+ -> Seq [b]+mapSeq = Seq $$ MapSeq++-- | Apply the given binary function element-wise to the two sequences. The length of the resulting+-- sequence is the minumum of the lengths of the two source sequences.+--+zipWithSeq :: (Arrays a, Arrays b, Arrays c)+ => (Acc a -> Acc b -> Acc c)+ -> Seq [a]+ -> Seq [b]+ -> Seq [c]+zipWithSeq = Seq $$$ ZipWithSeq++-- | scanSeq (+) a0 x seq. Scan a sequence x by combining each+-- element using the given binary operation (+). (+) must be+-- associative:+--+-- Forall a b c. (a + b) + c = a + (b + c),+--+-- and a0 must be the identity element for (+):+--+-- Forall a. a0 + a = a = a + a0.+--+scanSeq :: Elt a+ => (Exp a -> Exp a -> Exp a)+ -> Exp a+ -> Seq [Scalar a]+ -> Seq [Scalar a]+scanSeq = Seq $$$ ScanSeq++-- | foldSeq (+) a0 x seq. Fold a sequence x by combining each+-- element using the given binary operation (+). (+) must be+-- associative:+--+-- Forall a b c. (a + b) + c = a + (b + c),+--+-- and a0 must be the identity element for (+):+--+-- Forall a. a0 + a = a = a + a0.+--+foldSeq :: Elt a+ => (Exp a -> Exp a -> Exp a)+ -> Exp a+ -> Seq [Scalar a]+ -> Seq (Scalar a)+foldSeq = Seq $$$ FoldSeq++-- | foldSeqFlatten f a0 x seq. A specialized version of+-- FoldSeqAct where reduction with the companion operator+-- corresponds to flattening. f must be semi-associative, with vecotor+-- append (++) as the companion operator:+--+-- Forall b sh1 a1 sh2 a2.+-- f (f b sh1 a1) sh2 a2 = f b (sh1 ++ sh2) (a1 ++ a2).+--+-- It is common to ignore the shape vectors, yielding the usual+-- semi-associativity law:+--+-- f b a _ = b + a,+--+-- for some (+) satisfying:+--+-- Forall b a1 a2. (b + a1) + a2 = b + (a1 ++ a2).+--+foldSeqFlatten :: (Arrays a, Shape jx, Elt b)+ => (Acc a -> Acc (Vector jx) -> Acc (Vector b) -> Acc a)+ -> Acc a+ -> Seq [Array jx b]+ -> Seq a+foldSeqFlatten = Seq $$$ FoldSeqFlatten++collect :: Arrays arrs => Seq arrs -> Acc arrs+collect = Acc . Collect+--}+++-- Foreign function calling+-- ------------------------++-- | Call a foreign array function.+--+-- The form the first argument takes is dependent on the backend being targeted.+-- Note that the foreign function only has access to the input array(s) passed+-- in as its argument.+--+-- In case the operation is being executed on a backend which does not support+-- this foreign implementation, the fallback implementation is used instead,+-- which itself could be a foreign implementation for a (presumably) different+-- backend, or an implementation in pure Accelerate. In this way, multiple+-- foreign implementations can be supplied, and will be tested for suitability+-- against the target backend in sequence.+--+-- For an example see the <https://hackage.haskell.org/package/accelerate-fft accelerate-fft> package.+--+foreignAcc+ :: forall as bs asm. (Arrays as, Arrays bs, Foreign asm)+ => asm (ArraysR as -> ArraysR bs)+ -> (Acc as -> Acc bs)+ -> Acc as+ -> Acc bs+foreignAcc asm f (Acc as) = Acc $ SmartAcc $ Aforeign (arraysR @bs) asm (unAccFunction f) as++-- | Call a foreign scalar expression.+--+-- The form of the first argument is dependent on the backend being targeted.+-- Note that the foreign function only has access to the input element(s) passed+-- in as its first argument.+--+-- As with 'foreignAcc', the fallback implementation itself may be a (sequence+-- of) foreign implementation(s) for a different backend(s), or implemented+-- purely in Accelerate.+--+foreignExp+ :: forall x y asm. (Elt x, Elt y, Foreign asm)+ => asm (EltR x -> EltR y)+ -> (Exp x -> Exp y)+ -> Exp x+ -> Exp y+foreignExp asm f (Exp x) = mkExp $ Foreign (eltR @y) asm (unExpFunction f) x+++-- Composition of array computations+-- ---------------------------------++-- | Pipelining of two array computations. The first argument will be fully+-- evaluated before being passed to the second computation. This can be used to+-- prevent the argument being fused into the function, for example.+--+-- Denotationally, we have+--+-- > (acc1 >-> acc2) arrs = let tmp = acc1 arrs+-- > in tmp `seq` acc2 tmp+--+-- For an example use of this operation see the 'Data.Array.Accelerate.compute'+-- function.+--+infixl 1 >->+(>->) :: forall a b c. (Arrays a, Arrays b, Arrays c) => (Acc a -> Acc b) -> (Acc b -> Acc c) -> (Acc a -> Acc c)+(>->) = Acc $$$ applyAcc $ Pipe (arraysR @a) (arraysR @b) (arraysR @c)+++-- Flow control constructs+-- -----------------------++-- | An array-level if-then-else construct.+--+-- Enabling the @RebindableSyntax@ extension will allow you to use the standard+-- if-then-else syntax instead.+--+acond :: Arrays a+ => Exp Bool -- ^ if-condition+ -> Acc a -- ^ then-array+ -> Acc a -- ^ else-array+ -> Acc a+acond (Exp p) = Acc $$ applyAcc $ Acond (mkCoerce' p)++-- | An array-level 'while' construct. Continue to apply the given function,+-- starting with the initial value, until the test function evaluates to+-- 'False'.+--+awhile :: forall a. Arrays a+ => (Acc a -> Acc (Scalar Bool)) -- ^ keep evaluating while this returns 'True'+ -> (Acc a -> Acc a) -- ^ function to apply+ -> Acc a -- ^ initial value+ -> Acc a+awhile f = Acc $$ applyAcc $ Awhile (arraysR @a) (unAccFunction g)+ where+ -- FIXME: This should be a no-op!+ g :: Acc a -> Acc (Scalar PrimBool)+ g = map mkCoerce . f+++-- Shapes and indices+-- ------------------++-- | Map a multi-dimensional index into a linear, row-major representation of an+-- array.+--+toIndex+ :: forall sh. Shape sh+ => Exp sh -- ^ extent of the array+ -> Exp sh -- ^ index to remap+ -> Exp Int+toIndex (Exp sh) (Exp ix) = mkExp $ ToIndex (shapeR @sh) sh ix++-- | Inverse of 'toIndex'+--+fromIndex :: forall sh. Shape sh => Exp sh -> Exp Int -> Exp sh+fromIndex (Exp sh) (Exp e) = mkExp $ FromIndex (shapeR @sh) sh e++-- | Intersection of two shapes+--+intersect :: forall sh. Shape sh => Exp sh -> Exp sh -> Exp sh+intersect (Exp shx) (Exp shy) = Exp $ intersect' (shapeR @sh) shx shy+ where+ intersect' :: ShapeR t -> SmartExp t -> SmartExp t -> SmartExp t+ intersect' ShapeRz _ _ = SmartExp Nil+ intersect' (ShapeRsnoc shR) (unPair -> (xs, x)) (unPair -> (ys, y))+ = SmartExp+ $ intersect' shR xs ys `Pair`+ SmartExp (PrimApp (PrimMin singleType) $ SmartExp $ Pair x y)+++-- | Union of two shapes+--+union :: forall sh. Shape sh => Exp sh -> Exp sh -> Exp sh+union (Exp shx) (Exp shy) = Exp $ union' (shapeR @sh) shx shy+ where+ union' :: ShapeR t -> SmartExp t -> SmartExp t -> SmartExp t+ union' ShapeRz _ _ = SmartExp Nil+ union' (ShapeRsnoc shR) (unPair -> (xs, x)) (unPair -> (ys, y))+ = SmartExp+ $ union' shR xs ys `Pair`+ SmartExp (PrimApp (PrimMax singleType) $ SmartExp $ Pair x y)+++-- Flow-control+-- ------------++-- | A scalar-level if-then-else construct.+--+-- Enabling the @RebindableSyntax@ extension will allow you to use the standard+-- if-then-else syntax instead.+--+cond :: Elt t+ => Exp Bool -- ^ condition+ -> Exp t -- ^ then-expression+ -> Exp t -- ^ else-expression+ -> Exp t+cond (Exp c) (Exp x) (Exp y) = mkExp $ Cond (mkCoerce' c) x y++-- | While construct. Continue to apply the given function, starting with the+-- initial value, until the test function evaluates to 'False'.+--+while :: forall e. Elt e+ => (Exp e -> Exp Bool) -- ^ keep evaluating while this returns 'True'+ -> (Exp e -> Exp e) -- ^ function to apply+ -> Exp e -- ^ initial value+ -> Exp e+while c f (Exp e) =+ mkExp $ While @(EltR e) (eltR @e)+ (mkCoerce' . unExp . c . Exp)+ (unExp . f . Exp) e+++-- Array operations with a scalar result+-- -------------------------------------++-- | Multidimensional array indexing. Extract the value from an array at the+-- specified zero-based index.+--+-- >>> let mat = fromList (Z:.5:.10) [0..] :: Matrix Int+-- >>> mat+-- Matrix (Z :. 5 :. 10)+-- [ 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]+--+-- >>> runExp $ use mat ! constant (Z:.1:.2)+-- 12+--+infixl 9 !+(!) :: forall sh e. (Shape sh, Elt e) => Acc (Array sh e) -> Exp sh -> Exp e+Acc a ! Exp ix = mkExp $ Index (eltR @e) a ix++-- | Extract the value from an array at the specified linear index.+-- Multidimensional arrays in Accelerate are stored in row-major order with+-- zero-based indexing.+--+-- >>> let mat = fromList (Z:.5:.10) [0..] :: Matrix Int+-- >>> mat+-- Matrix (Z :. 5 :. 10)+-- [ 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]+--+-- >>> runExp $ use mat !! 12+-- 12+--+infixl 9 !!+(!!) :: forall sh e. (Shape sh, Elt e) => Acc (Array sh e) -> Exp Int -> Exp e+Acc a !! Exp ix = mkExp $ LinearIndex (eltR @e) a ix++-- | Extract the shape (extent) of an array.+--+shape :: forall sh e. (Shape sh, Elt e) => Acc (Array sh e) -> Exp sh+shape = mkExp . Shape (shapeR @sh) . unAcc++-- | The number of elements in the array+--+size :: (Shape sh, Elt e) => Acc (Array sh e) -> Exp Int+size = shapeSize . shape++-- | The number of elements that would be held by an array of the given shape.+--+shapeSize :: forall sh. Shape sh => Exp sh -> Exp Int+shapeSize (Exp sh) = mkExp $ ShapeSize (shapeR @sh) sh+++-- Numeric functions+-- -----------------++-- | 'subtract' is the same as @'flip' ('-')@.+--+subtract :: Num a => Exp a -> Exp a -> Exp a+subtract x y = y - x++-- | Determine if a number is even+--+even :: Integral a => Exp a -> Exp Bool+even n = n `rem` 2 == 0++-- | Determine if a number is odd+--+odd :: Integral a => Exp a -> Exp Bool+odd n = n `rem` 2 /= 0++-- | @'gcd' x y@ is the non-negative factor of both @x@ and @y@ of which every+-- common factor of both @x@ and @y@ is also a factor; for example:+--+-- > gcd 4 2 = 2+-- > gcd (-4) 6 = 2+-- > gcd 0 4 = 4+-- > gcd 0 0 = 0+--+-- That is, the common divisor that is \"greatest\" in the divisibility+-- preordering.+--+gcd :: Integral a => Exp a -> Exp a -> Exp a+gcd x y = gcd' (abs x) (abs y)+ where+ gcd' :: Integral a => Exp a -> Exp a -> Exp a+ gcd' u v =+ let T2 r _ = while (\(T2 _ b) -> b /= 0)+ (\(T2 a b) -> T2 b (a `rem` b))+ (T2 u v)+ in r+++-- | @'lcm' x y@ is the smallest positive integer that both @x@ and @y@ divide.+--+lcm :: Integral a => Exp a -> Exp a -> Exp a+lcm x y+ = cond (x == 0 || y == 0) 0+ $ abs ((x `quot` (gcd x y)) * y)+++-- | Raise a number to a non-negative integral power+--+infixr 8 ^+(^) :: forall a b. (Num a, Integral b) => Exp a -> Exp b -> Exp a+x0 ^ y0 = cond (y0 <= 0) 1 (f x0 y0)+ where+ f :: Exp a -> Exp b -> Exp a+ f x y =+ let T2 x' y' = while (\(T2 _ v) -> even v)+ (\(T2 u v) -> T2 (u * u) (v `quot` 2))+ (T2 x y)+ in+ cond (y' == 1) x' (g (x'*x') ((y'-1) `quot` 2) x')++ g :: Exp a -> Exp b -> Exp a -> Exp a+ g x y z =+ let T3 x' _ z' = while (\(T3 _ v _) -> v /= 1)+ (\(T3 u v w) ->+ cond (even v) (T3 (u*u) (v `quot` 2) w)+ (T3 (u*u) ((v-1) `quot` 2) (w*u)))+ (T3 x y z)+ in+ x' * z'++-- | Raise a number to an integral power+--+infixr 8 ^^+(^^) :: (Fractional a, Integral b) => Exp a -> Exp b -> Exp a+x ^^ n+ = cond (n >= 0)+ {- then -} (x ^ n)+ {- else -} (recip (x ^ (negate n)))+++-- Conversions+-- -----------++-- |Convert a character to an 'Int'.+--+ord :: Exp Char -> Exp Int+ord = mkFromIntegral++-- |Convert an 'Int' into a character.+--+chr :: Exp Int -> Exp Char+chr = mkFromIntegral++-- |Convert a Boolean value to an 'Int', where 'False' turns into '0' and 'True'+-- into '1'.+--+boolToInt :: Exp Bool -> Exp Int+boolToInt = mkFromIntegral . mkCoerce @_ @Word8++-- |Reinterpret a value as another type. The two representations must have the+-- same bit size.+--+bitcast+ :: (Elt a, Elt b, IsScalar (EltR a), IsScalar (EltR b), BitSizeEq (EltR a) (EltR b))+ => Exp a+ -> Exp b+bitcast = mkBitcast+
+ src/Data/Array/Accelerate/Lifetime.hs view
@@ -0,0 +1,156 @@+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE UnboxedTuples #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Lifetime+-- Copyright : [2015..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Lifetime (++ Lifetime(..),+ newLifetime, withLifetime, touchLifetime,+ addFinalizer, finalize, mkWeak, mkWeakPtr,++ unsafeGetValue,++) where++import Data.Function ( on )+import Data.IORef ( mkWeakIORef, atomicModifyIORef' )+import Prelude++import GHC.Base ( touch#, IO(..))+import GHC.IORef ( IORef(.. ), newIORef )+import GHC.Prim ( mkWeak# )+import GHC.STRef ( STRef(..) )+import GHC.Weak ( Weak(..) )+++-- | A lifetime represents a value with attached finalizers. This is similar to+-- the functionality provided by "System.Mem.Weak", but has the following+-- stronger properties:+--+-- * Unless explicitly forced, finalizers will not fire until after the+-- 'Lifetime' has become unreachable, where \"reachability\" is the same as+-- defined in "System.Mem.Weak". That is to say, there is no issue with+-- creating a 'Lifetime' for a non-primitve type and finalizers firing while+-- an object is still reachable.+--+-- * Finalizers are fired sequentially in reverse of the order in which they+-- were attached.+--+-- * As the finalizers are attached to the 'Lifetime' and not the underlying+-- value, there is no danger in storing it UNPACKED as part of another+-- structure.+--+type LTF = IORef [IO ()]+data Lifetime a = Lifetime {-# UNPACK #-} !LTF+ {-# UNPACK #-} !(Weak LTF)+ {- LAZY -} a++instance Eq a => Eq (Lifetime a) where+ (==) = (==) `on` unsafeGetValue++-- | Construct a new 'Lifetime' from the given value.+--+{-# INLINE newLifetime #-}+newLifetime :: a -> IO (Lifetime a)+newLifetime a = do+ ref <- newIORef []+ weak <- mkWeakIORef ref (finalizer ref)+ return $! Lifetime ref weak a++-- | This provides a way of looking at the value inside a 'Lifetime'. The+-- supplied function is executed immediately and the 'Lifetime' kept alive+-- throughout its execution. It is important to not let the value /leak/ outside+-- the function, either by returning it or by lazy IO.+--+{-# INLINE withLifetime #-}+withLifetime :: Lifetime a -> (a -> IO b) -> IO b+withLifetime (Lifetime ref _ a) f = do+ r <- f a+ touchIORef ref+ return r++-- | Ensure that the lifetime is alive at the given place in a sequence of IO+-- actions. Does not force the payload.+--+{-# INLINE touchLifetime #-}+touchLifetime :: Lifetime a -> IO ()+touchLifetime (Lifetime ref _ _) = touchIORef ref++-- | Attaches a finalizer to a 'Lifetime'. Like in "System.Mem.Weak", there is+-- no guarantee that the finalizers will eventually run. If they do run,+-- they will be executed in the order in which they were supplied.+--+addFinalizer :: Lifetime a -> IO () -> IO ()+addFinalizer (Lifetime ref _ _) f =+ atomicModifyIORef' ref (\fs -> (f:fs,()))++-- | Causes any finalizers associated with the given lifetime to be run+-- immediately on the calling thread.+--+-- Because the finalizer is run on the calling thread. Care should be taken to+-- ensure that the it does not try to acquire any locks the calling thread might+-- already possess. This can result in deadlock and is in contrast to calling+-- 'System.Mem.Weak.finalize' on 'System.Mem.Weak.Weak'.+--+finalize :: Lifetime a -> IO ()+finalize (Lifetime ref _ _) = finalizer ref++-- | Create a weak pointer from a 'Lifetime' to the supplied value.+--+-- Because weak pointers have their own concept of finalizers, it is important+-- to note these behaviours:+--+-- * Calling 'System.Mem.Weak.finalize' causes the finalizers attached to the+-- lifetime to be scheduled, and run in the correct order, but does not+-- guarantee they will execute on the calling thread.+--+-- * If 'deRefWeak' returns Nothing, there is no guarantee that the finalizers+-- have already run.+--+mkWeak :: Lifetime k -> v -> IO (Weak v)+mkWeak (Lifetime ref@(IORef (STRef r#)) _ _) v = go (finalizer ref)+ where+ go (IO f) = -- GHC-8.x+ IO $ \s -> case mkWeak# r# v f s of+ (# s', w# #) -> (# s', Weak w# #)++-- A specialised version of 'mkWeak' where the key and value are the same+-- 'Lifetime'.+--+-- > mkWeakPtr key = mkWeak key key+--+mkWeakPtr :: Lifetime a -> IO (Weak (Lifetime a))+mkWeakPtr l = mkWeak l l++-- | Retrieve the value from a lifetime. This is unsafe because, unless the+-- 'Lifetime' is still reachable, the finalizers may fire, potentially+-- invalidating the value.+--+{-# INLINE unsafeGetValue #-}+unsafeGetValue :: Lifetime a -> a+unsafeGetValue (Lifetime _ _ a) = a++-- The actual finalizer for 'Lifetime's.+--+finalizer :: IORef [IO ()] -> IO ()+finalizer ref = do+ fins <- atomicModifyIORef' ref ([],)+ sequence_ fins++-- Touch an 'IORef', ensuring that it is alive at this point in a sequence of IO+-- actions.+--+{-# INLINE touchIORef #-}+touchIORef :: IORef a -> IO ()+touchIORef r = IO $ \s -> case touch# r s of s' -> (# s', () #)+
+ src/Data/Array/Accelerate/Lift.hs view
@@ -0,0 +1,358 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+#if __GLASGOW_HASKELL__ >= 806+{-# LANGUAGE UndecidableInstances #-}+#endif+-- |+-- Module : Data.Array.Accelerate.Lift+-- Copyright : [2016..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- Lifting and lowering surface expressions through constructors.+--++module Data.Array.Accelerate.Lift (++ -- * Lifting and unlifting+ Lift(..), Unlift(..),++ lift1, lift2, lift3,+ ilift1, ilift2, ilift3,++) where++import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.Pattern+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Array+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Sugar.Shape+import Data.Array.Accelerate.Type++import Language.Haskell.TH.Extra hiding ( Exp )+++-- | Lift a unary function into 'Exp'.+--+lift1 :: (Unlift Exp a, Lift Exp b)+ => (a -> b)+ -> Exp (Plain a)+ -> Exp (Plain b)+lift1 f = lift . f . unlift++-- | Lift a binary function into 'Exp'.+--+lift2 :: (Unlift Exp a, Unlift Exp b, Lift Exp c)+ => (a -> b -> c)+ -> Exp (Plain a)+ -> Exp (Plain b)+ -> Exp (Plain c)+lift2 f x y = lift $ f (unlift x) (unlift y)++-- | Lift a ternary function into 'Exp'.+--+lift3 :: (Unlift Exp a, Unlift Exp b, Unlift Exp c, Lift Exp d)+ => (a -> b -> c -> d)+ -> Exp (Plain a)+ -> Exp (Plain b)+ -> Exp (Plain c)+ -> Exp (Plain d)+lift3 f x y z = lift $ f (unlift x) (unlift y) (unlift z)++-- | Lift a unary function to a computation over rank-1 indices.+--+ilift1 :: (Exp Int -> Exp Int) -> Exp DIM1 -> Exp DIM1+ilift1 f = lift1 (\(Z:.i) -> Z :. f i)++-- | Lift a binary function to a computation over rank-1 indices.+--+ilift2 :: (Exp Int -> Exp Int -> Exp Int) -> Exp DIM1 -> Exp DIM1 -> Exp DIM1+ilift2 f = lift2 (\(Z:.i) (Z:.j) -> Z :. f i j)++-- | Lift a ternary function to a computation over rank-1 indices.+--+ilift3 :: (Exp Int -> Exp Int -> Exp Int -> Exp Int) -> Exp DIM1 -> Exp DIM1 -> Exp DIM1 -> Exp DIM1+ilift3 f = lift3 (\(Z:.i) (Z:.j) (Z:.k) -> Z :. f i j k)+++-- | The class of types @e@ which can be lifted into @c@.+--+class Lift c e where+ -- | An associated-type (i.e. a type-level function) that strips all+ -- instances of surface type constructors @c@ from the input type @e@.+ --+ -- For example, the tuple types @(Exp Int, Int)@ and @(Int, Exp+ -- Int)@ have the same \"Plain\" representation. That is, the+ -- following type equality holds:+ --+ -- @Plain (Exp Int, Int) ~ (Int,Int) ~ Plain (Int, Exp Int)@+ --+ type Plain e++ -- | Lift the given value into a surface type 'c' --- either 'Exp' for scalar+ -- expressions or 'Acc' for array computations. The value may already contain+ -- subexpressions in 'c'.+ --+ lift :: e -> c (Plain e)++-- | A limited subset of types which can be lifted, can also be unlifted.+class Lift c e => Unlift c e where++ -- | Unlift the outermost constructor through the surface type. This is only+ -- possible if the constructor is fully determined by its type - i.e., it is a+ -- singleton.+ --+ unlift :: c (Plain e) -> e+++-- Identity instances+-- ------------------++instance Lift Exp (Exp e) where+ type Plain (Exp e) = e+ lift = id++instance Unlift Exp (Exp e) where+ unlift = id++instance Lift Acc (Acc a) where+ type Plain (Acc a) = a+ lift = id++instance Unlift Acc (Acc a) where+ unlift = id++-- instance Lift Seq (Seq a) where+-- type Plain (Seq a) = a+-- lift = id++-- instance Unlift Seq (Seq a) where+-- unlift = id+++-- Instances for indices+-- ---------------------++instance Lift Exp Z where+ type Plain Z = Z+ lift _ = Z_++instance Unlift Exp Z where+ unlift _ = Z++instance (Elt (Plain ix), Lift Exp ix) => Lift Exp (ix :. Int) where+ type Plain (ix :. Int) = Plain ix :. Int+ lift (ix :. i) = lift ix ::. lift i++instance (Elt (Plain ix), Lift Exp ix) => Lift Exp (ix :. All) where+ type Plain (ix :. All) = Plain ix :. All+ lift (ix :. i) = lift ix ::. constant i++instance (Elt e, Elt (Plain ix), Lift Exp ix) => Lift Exp (ix :. Exp e) where+ type Plain (ix :. Exp e) = Plain ix :. e+ lift (ix :. i) = lift ix ::. i++instance {-# OVERLAPPABLE #-} (Elt e, Elt (Plain ix), Unlift Exp ix) => Unlift Exp (ix :. Exp e) where+ unlift (ix ::. i) = unlift ix :. i++instance {-# OVERLAPPABLE #-} (Elt e, Elt ix) => Unlift Exp (Exp ix :. Exp e) where+ unlift (ix ::. i) = ix :. i++instance (Shape sh, Elt (Any sh)) => Lift Exp (Any sh) where+ type Plain (Any sh) = Any sh+ lift Any = constant Any++-- Instances for numeric types+-- ---------------------------++{-# INLINE expConst #-}+expConst :: forall e. Elt e => IsScalar (EltR e) => e -> Exp e+expConst = Exp . SmartExp . Const (scalarType @(EltR e)) . fromElt++instance Lift Exp Int where+ type Plain Int = Int+ lift = expConst++instance Lift Exp Int8 where+ type Plain Int8 = Int8+ lift = expConst++instance Lift Exp Int16 where+ type Plain Int16 = Int16+ lift = expConst++instance Lift Exp Int32 where+ type Plain Int32 = Int32+ lift = expConst++instance Lift Exp Int64 where+ type Plain Int64 = Int64+ lift = expConst++instance Lift Exp Word where+ type Plain Word = Word+ lift = expConst++instance Lift Exp Word8 where+ type Plain Word8 = Word8+ lift = expConst++instance Lift Exp Word16 where+ type Plain Word16 = Word16+ lift = expConst++instance Lift Exp Word32 where+ type Plain Word32 = Word32+ lift = expConst++instance Lift Exp Word64 where+ type Plain Word64 = Word64+ lift = expConst++instance Lift Exp CShort where+ type Plain CShort = CShort+ lift = expConst++instance Lift Exp CUShort where+ type Plain CUShort = CUShort+ lift = expConst++instance Lift Exp CInt where+ type Plain CInt = CInt+ lift = expConst++instance Lift Exp CUInt where+ type Plain CUInt = CUInt+ lift = expConst++instance Lift Exp CLong where+ type Plain CLong = CLong+ lift = expConst++instance Lift Exp CULong where+ type Plain CULong = CULong+ lift = expConst++instance Lift Exp CLLong where+ type Plain CLLong = CLLong+ lift = expConst++instance Lift Exp CULLong where+ type Plain CULLong = CULLong+ lift = expConst++instance Lift Exp Half where+ type Plain Half = Half+ lift = expConst++instance Lift Exp Float where+ type Plain Float = Float+ lift = expConst++instance Lift Exp Double where+ type Plain Double = Double+ lift = expConst++instance Lift Exp CFloat where+ type Plain CFloat = CFloat+ lift = expConst++instance Lift Exp CDouble where+ type Plain CDouble = CDouble+ lift = expConst++instance Lift Exp Bool where+ type Plain Bool = Bool+ lift True = Exp . SmartExp $ SmartExp (Const scalarType 1) `Pair` SmartExp Nil+ lift False = Exp . SmartExp $ SmartExp (Const scalarType 0) `Pair` SmartExp Nil++instance Lift Exp Char where+ type Plain Char = Char+ lift = expConst++instance Lift Exp CChar where+ type Plain CChar = CChar+ lift = expConst++instance Lift Exp CSChar where+ type Plain CSChar = CSChar+ lift = expConst++instance Lift Exp CUChar where+ type Plain CUChar = CUChar+ lift = expConst++-- Instances for tuples+-- --------------------++instance Lift Exp () where+ type Plain () = ()+ lift _ = Exp (SmartExp Nil)++instance Unlift Exp () where+ unlift _ = ()++instance Lift Acc () where+ type Plain () = ()+ lift _ = Acc (SmartAcc Anil)++instance Unlift Acc () where+ unlift _ = ()++instance (Shape sh, Elt e) => Lift Acc (Array sh e) where+ type Plain (Array sh e) = Array sh e+ lift (Array arr) = Acc $ SmartAcc $ Use (arrayR @sh @e) arr++-- Lift and Unlift instances for tuples+--+runQ $ do+ let+ mkInstances :: Name -> TypeQ -> ExpQ -> ExpQ -> ExpQ -> ExpQ -> Int -> Q [Dec]+ mkInstances con cst smart prj nil pair n = do+ let+ xs = [ mkName ('x' : show i) | i <- [0 .. n-1] ]+ ts = map varT xs+ res1 = tupT ts+ res2 = tupT (map (conT con `appT`) ts)+ plain = tupT (map (\t -> [t| Plain $t |]) ts)+ ctx1 = tupT (map (\t -> [t| Lift $(conT con) $t |]) ts)+ ctx2 = tupT (map (\t -> [t| $cst (Plain $t) |]) ts)+ ctx3 = tupT (map (appT cst) ts)+ --+ get x 0 = [| $(conE con) ($smart ($prj PairIdxRight $x)) |]+ get x i = get [| $smart ($prj PairIdxLeft $x) |] (i-1)+ --+ _x <- newName "_x"+ [d| instance ($ctx1, $ctx2) => Lift $(conT con) $res1 where+ type Plain $res1 = $plain+ lift $(tupP (map varP xs)) =+ $(conE con)+ $(foldl (\vs v -> do _v <- newName "_v"+ [| let $(conP con [varP _v]) = lift $(varE v)+ in $smart ($pair $vs $(varE _v)) |]) [| $smart $nil |] xs)++ instance $ctx3 => Unlift $(conT con) $res2 where+ unlift $(conP con [varP _x]) =+ $(tupE (map (get (varE _x)) [(n-1), (n-2) .. 0]))+ |]++ mkAccInstances = mkInstances (mkName "Acc") [t| Arrays |] [| SmartAcc |] [| Aprj |] [| Anil |] [| Apair |]+ mkExpInstances = mkInstances (mkName "Exp") [t| Elt |] [| SmartExp |] [| Prj |] [| Nil |] [| Pair |]+ --+ as <- mapM mkAccInstances [2..16]+ es <- mapM mkExpInstances [2..16]+ return $ concat (as ++ es)+
+ src/Data/Array/Accelerate/Orphans.hs view
@@ -0,0 +1,52 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE UnboxedTuples #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- |+-- Module : Data.Array.Accelerate.Orphans+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Orphans ()+ where++import Data.Orphans () -- orphan instances for 8-tuples and beyond+import Data.Primitive.Types+import Data.Ratio+import Foreign.C.Types+import GHC.Generics+import GHC.Real+import Numeric.Half+++-- base+--+deriving instance (Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h, Show i, Show j, Show k, Show l, Show m, Show n, Show o, Show p)+ => Show (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)++#if __GLASGOW_HASKELL__ < 902+deriving instance Generic (a, b, c, d, e, f, g, h)+deriving instance Generic (a, b, c, d, e, f, g, h, i)+deriving instance Generic (a, b, c, d, e, f, g, h, i, j)+deriving instance Generic (a, b, c, d, e, f, g, h, i, j, k)+deriving instance Generic (a, b, c, d, e, f, g, h, i, j, k, l)+deriving instance Generic (a, b, c, d, e, f, g, h, i, j, k, l, m)+deriving instance Generic (a, b, c, d, e, f, g, h, i, j, k, l, m, n)+deriving instance Generic (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)+#endif+deriving instance Generic (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)++deriving instance Generic (Ratio a)++-- primitive+--+deriving instance Prim Half+
+ src/Data/Array/Accelerate/Pattern.hs view
@@ -0,0 +1,308 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ParallelListComp #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE ViewPatterns #-}+-- |+-- Module : Data.Array.Accelerate.Pattern+-- Copyright : [2018..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Pattern (++ pattern Pattern,+ pattern T2, pattern T3, pattern T4, pattern T5, pattern T6,+ pattern T7, pattern T8, pattern T9, pattern T10, pattern T11,+ pattern T12, pattern T13, pattern T14, pattern T15, pattern T16,++ pattern Z_, pattern Ix, pattern (::.), pattern All_, pattern Any_,+ pattern I0, pattern I1, pattern I2, pattern I3, pattern I4,+ pattern I5, pattern I6, pattern I7, pattern I8, pattern I9,++ pattern V2, pattern V3, pattern V4, pattern V8, pattern V16,++) where++import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.Representation.Tag+import Data.Array.Accelerate.Representation.Vec+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Array+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Sugar.Shape+import Data.Array.Accelerate.Sugar.Vec+import Data.Array.Accelerate.Type+import Data.Primitive.Vec++import Language.Haskell.TH.Extra hiding ( Exp, Match )+++-- | A pattern synonym for working with (product) data types. You can declare+-- your own pattern synonyms based off of this.+--+pattern Pattern :: forall b a context. IsPattern context a b => b -> context a+pattern Pattern vars <- (matcher @context -> vars)+ where Pattern = builder @context++class IsPattern context a b where+ builder :: b -> context a+ matcher :: context a -> b+++pattern Vector :: forall b a context. IsVector context a b => b -> context a+pattern Vector vars <- (vunpack @context -> vars)+ where Vector = vpack @context++class IsVector context a b where+ vpack :: b -> context a+ vunpack :: context a -> b++-- | Pattern synonyms for indices, which may be more convenient to use than+-- 'Data.Array.Accelerate.Lift.lift' and+-- 'Data.Array.Accelerate.Lift.unlift'.+--+pattern Z_ :: Exp DIM0+pattern Z_ = Pattern Z+{-# COMPLETE Z_ #-}++infixl 3 ::.+pattern (::.) :: (Elt a, Elt b) => Exp a -> Exp b -> Exp (a :. b)+pattern a ::. b = Pattern (a :. b)+{-# COMPLETE (::.) #-}++infixl 3 `Ix`+pattern Ix :: (Elt a, Elt b) => Exp a -> Exp b -> Exp (a :. b)+pattern a `Ix` b = a ::. b+{-# COMPLETE Ix #-}++pattern All_ :: Exp All+pattern All_ <- (const True -> True)+ where All_ = constant All+{-# COMPLETE All_ #-}++pattern Any_ :: (Shape sh, Elt (Any sh)) => Exp (Any sh)+pattern Any_ <- (const True -> True)+ where Any_ = constant Any+{-# COMPLETE Any_ #-}++-- IsPattern instances for Shape nil and cons+--+instance IsPattern Exp Z Z where+ builder _ = constant Z+ matcher _ = Z++instance (Elt a, Elt b) => IsPattern Exp (a :. b) (Exp a :. Exp b) where+ builder (Exp a :. Exp b) = Exp $ SmartExp $ Pair a b+ matcher (Exp t) = Exp (SmartExp $ Prj PairIdxLeft t) :. Exp (SmartExp $ Prj PairIdxRight t)+++-- IsPattern instances for up to 16-tuples (Acc and Exp). TH takes care of+-- the (unremarkable) boilerplate for us.+--+runQ $ do+ let+ -- Generate instance declarations for IsPattern of the form:+ -- instance (Arrays x, ArraysR x ~ (((), ArraysR a), ArraysR b), Arrays a, Arrays b,) => IsPattern Acc x (Acc a, Acc b)+ mkAccPattern :: Int -> Q [Dec]+ mkAccPattern n = do+ a <- newName "a"+ let+ -- Type variables for the elements+ xs = [ mkName ('x' : show i) | i <- [0 .. n-1] ]+ -- Last argument to `IsPattern`, eg (Acc a, Acc b) in the example+ b = tupT (map (\t -> [t| Acc $(varT t)|]) xs)+ -- Representation as snoc-list of pairs, eg (((), ArraysR a), ArraysR b)+ snoc = foldl (\sn t -> [t| ($sn, ArraysR $(varT t)) |]) [t| () |] xs+ -- Constraints for the type class, consisting of Arrays constraints on all type variables,+ -- and an equality constraint on the representation type of `a` and the snoc representation `snoc`.+ context = tupT+ $ [t| Arrays $(varT a) |]+ : [t| ArraysR $(varT a) ~ $snoc |]+ : map (\t -> [t| Arrays $(varT t)|]) xs+ --+ get x 0 = [| Acc (SmartAcc (Aprj PairIdxRight $x)) |]+ get x i = get [| SmartAcc (Aprj PairIdxLeft $x) |] (i-1)+ --+ _x <- newName "_x"+ [d| instance $context => IsPattern Acc $(varT a) $b where+ builder $(tupP (map (\x -> [p| Acc $(varP x)|]) xs)) =+ Acc $(foldl (\vs v -> [| SmartAcc ($vs `Apair` $(varE v)) |]) [| SmartAcc Anil |] xs)+ matcher (Acc $(varP _x)) =+ $(tupE (map (get (varE _x)) [(n-1), (n-2) .. 0]))+ |]++ -- Generate instance declarations for IsPattern of the form:+ -- instance (Elt x, EltR x ~ (((), EltR a), EltR b), Elt a, Elt b,) => IsPattern Exp x (Exp a, Exp b)+ mkExpPattern :: Int -> Q [Dec]+ mkExpPattern n = do+ a <- newName "a"+ let+ -- Type variables for the elements+ xs = [ mkName ('x' : show i) | i <- [0 .. n-1] ]+ -- Variables for sub-pattern matches+ ms = [ mkName ('m' : show i) | i <- [0 .. n-1] ]+ tags = foldl (\ts t -> [p| $ts `TagRpair` $(varP t) |]) [p| TagRunit |] ms+ -- Last argument to `IsPattern`, eg (Exp, a, Exp b) in the example+ b = tupT (map (\t -> [t| Exp $(varT t)|]) xs)+ -- Representation as snoc-list of pairs, eg (((), EltR a), EltR b)+ snoc = foldl (\sn t -> [t| ($sn, EltR $(varT t)) |]) [t| () |] xs+ -- Constraints for the type class, consisting of Elt constraints on all type variables,+ -- and an equality constraint on the representation type of `a` and the snoc representation `snoc`.+ context = tupT+ $ [t| Elt $(varT a) |]+ : [t| EltR $(varT a) ~ $snoc |]+ : map (\t -> [t| Elt $(varT t)|]) xs+ --+ get x 0 = [| SmartExp (Prj PairIdxRight $x) |]+ get x i = get [| SmartExp (Prj PairIdxLeft $x) |] (i-1)+ --+ _x <- newName "_x"+ _y <- newName "_y"+ [d| instance $context => IsPattern Exp $(varT a) $b where+ builder $(tupP (map (\x -> [p| Exp $(varP x)|]) xs)) =+ let _unmatch :: SmartExp a -> SmartExp a+ _unmatch (SmartExp (Match _ $(varP _y))) = $(varE _y)+ _unmatch x = x+ in+ Exp $(foldl (\vs v -> [| SmartExp ($vs `Pair` _unmatch $(varE v)) |]) [| SmartExp Nil |] xs)+ matcher (Exp $(varP _x)) =+ case $(varE _x) of+ SmartExp (Match $tags $(varP _y))+ -> $(tupE [[| Exp (SmartExp (Match $(varE m) $(get (varE _x) i))) |] | m <- ms | i <- [(n-1), (n-2) .. 0]])+ _ -> $(tupE [[| Exp $(get (varE _x) i) |] | i <- [(n-1), (n-2) .. 0]])+ |]++ -- Generate instance declarations for IsVector of the form:+ -- instance (Elt v, EltR v ~ Vec 2 a1, Elt a1, a1 ~ a2) => IsVector Exp v (Exp a1, Exp a2)+ -- The element type is `a1`; we leave the element types for each of the+ -- tuple components as separate type variables in the instance head+ -- (only to equate them in the instance context) so that type inference+ -- can already select this instance before it is known that the tuple+ -- elements are indeed homogeneously typed.+ mkVecPattern :: Int -> Q [Dec]+ mkVecPattern n | n <= 0 = error "mkVecPattern: must be > 0"+ mkVecPattern n = do+ as@(a1 : a2s) <- mapM (\i -> newName ("a" ++ show i)) [1 .. n]+ v <- newName "v"+ let+ -- Last argument to `IsVector`, eg (Exp a1, Exp a2) in the example+ tup = tupT [ [t| Exp $(varT ai) |] | ai <- as ]+ -- Representation as a vector, eg (Vec 2 a1)+ vec = [t| Vec $(litT (numTyLit (fromIntegral n))) $(varT a1) |]+ -- Constraints for the type class, consisting of:+ -- - Elt constraints on all type variables;+ -- - an equality constraint on the representation type of `a` and+ -- the vector representation `vec`;+ -- - equality constraints for the `ai` variables.+ context = tupT $ [t| Elt $(varT v) |]+ : [t| VecElt $(varT a1) |]+ : [t| EltR $(varT v) ~ $vec |]+ : [ [t| $(varT a1) ~ $(varT ai) |] | ai <- a2s]+ --+ vecR = iterate ([| VecRsucc |] `appE`) [| VecRnil (singleType @($(varT a1))) |]+ Prelude.!! n+ tR = tupT (replicate n (varT a1))+ --+ [d| instance $context => IsVector Exp $(varT v) $tup where+ vpack x = case builder x :: Exp $tR of+ Exp x' -> Exp (SmartExp (VecPack $vecR x'))+ vunpack (Exp x) = matcher (Exp (SmartExp (VecUnpack $vecR x)) :: Exp $tR)+ |]+ --+ es <- mapM mkExpPattern [0..16]+ as <- mapM mkAccPattern [0..16]+ vs <- mapM mkVecPattern [2,3,4,8,16]+ return $ concat (es ++ as ++ vs)+++-- | Specialised pattern synonyms for tuples, which may be more convenient to+-- use than 'Data.Array.Accelerate.Lift.lift' and+-- 'Data.Array.Accelerate.Lift.unlift'. For example, to construct a pair:+--+-- > let a = 4 :: Exp Int+-- > let b = 2 :: Exp Float+-- > let c = T2 a b -- :: Exp (Int, Float); equivalent to 'lift (a,b)'+--+-- Similarly they can be used to destruct values:+--+-- > let T2 x y = c -- x :: Exp Int, y :: Exp Float; equivalent to 'let (x,y) = unlift c'+--+-- These pattern synonyms can be used for both 'Exp' and 'Acc' terms.+--+-- Similarly, we have patterns for constructing and destructing indices of+-- a given dimensionality:+--+-- > let ix = Ix 2 3 -- :: Exp DIM2+-- > let I2 y x = ix -- y :: Exp Int, x :: Exp Int+--+runQ $ do+ let+ mkT :: Int -> Q [Dec]+ mkT n =+ let xs = [ mkName ('x' : show i) | i <- [0 .. n-1] ]+ ts = map varT xs+ name = mkName ('T':show n)+ con = varT (mkName "con")+ ty1 = tupT ts+ ty2 = tupT (map (con `appT`) ts)+ sig = foldr (\t r -> [t| $con $t -> $r |]) (appT con ty1) ts+ in+ sequence+ [ patSynSigD name [t| IsPattern $con $ty1 $ty2 => $sig |]+ , patSynD name (prefixPatSyn xs) implBidir [p| Pattern $(tupP (map varP xs)) |]+ , pragCompleteD [name] (Just ''Acc)+ , pragCompleteD [name] (Just ''Exp)+ ]++ mkI :: Int -> Q [Dec]+ mkI n =+ let xs = [ mkName ('x' : show i) | i <- [0 .. n-1] ]+ ts = map varT xs+ name = mkName ('I':show n)+ ix = mkName "Ix"+ cst = tupT (map (\t -> [t| Elt $t |]) ts)+ dim = foldl (\h t -> [t| $h :. $t |]) [t| Z |] ts+ sig = foldr (\t r -> [t| Exp $t -> $r |]) [t| Exp $dim |] ts+ in+ sequence+ [ patSynSigD name [t| $cst => $sig |]+ , patSynD name (prefixPatSyn xs) implBidir (foldl (\ps p -> infixP ps ix (varP p)) [p| Z_ |] xs)+ , pragCompleteD [name] Nothing+ ]++ mkV :: Int -> Q [Dec]+ mkV n =+ let xs = [ mkName ('x' : show i) | i <- [0 .. n-1] ]+ ts = map varT xs+ name = mkName ('V':show n)+ con = varT (mkName "con")+ ty1 = varT (mkName "vec")+ ty2 = tupT (map (con `appT`) ts)+ sig = foldr (\t r -> [t| $con $t -> $r |]) (appT con ty1) ts+ in+ sequence+ [ patSynSigD name [t| IsVector $con $ty1 $ty2 => $sig |]+ , patSynD name (prefixPatSyn xs) implBidir [p| Vector $(tupP (map varP xs)) |]+ , pragCompleteD [name] (Just ''Exp)+ ]+ --+ ts <- mapM mkT [2..16]+ is <- mapM mkI [0..9]+ vs <- mapM mkV [2,3,4,8,16]+ return $ concat (ts ++ is ++ vs)+
+ src/Data/Array/Accelerate/Pattern/Bool.hs view
@@ -0,0 +1,26 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ViewPatterns #-}+-- |+-- Module : Data.Array.Accelerate.Pattern.Bool+-- Copyright : [2018..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Pattern.Bool (++ Bool, pattern True_, pattern False_,++) where++import Data.Array.Accelerate.Pattern.TH++mkPattern ''Bool+
+ src/Data/Array/Accelerate/Pattern/Either.hs view
@@ -0,0 +1,26 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ViewPatterns #-}+-- |+-- Module : Data.Array.Accelerate.Pattern.Either+-- Copyright : [2018..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Pattern.Either (++ Either, pattern Left_, pattern Right_,++) where++import Data.Array.Accelerate.Pattern.TH++mkPattern ''Either+
+ src/Data/Array/Accelerate/Pattern/Maybe.hs view
@@ -0,0 +1,26 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ViewPatterns #-}+-- |+-- Module : Data.Array.Accelerate.Pattern.Maybe+-- Copyright : [2018..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Pattern.Maybe (++ Maybe, pattern Nothing_, pattern Just_,++) where++import Data.Array.Accelerate.Pattern.TH++mkPattern ''Maybe+
+ src/Data/Array/Accelerate/Pattern/Ordering.hs view
@@ -0,0 +1,26 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ViewPatterns #-}+-- |+-- Module : Data.Array.Accelerate.Pattern.Ordering+-- Copyright : [2018..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Pattern.Ordering (++ Ordering, pattern LT_, pattern EQ_, pattern GT_,++) where++import Data.Array.Accelerate.Pattern.TH++mkPattern ''Ordering+
+ src/Data/Array/Accelerate/Pattern/TH.hs view
@@ -0,0 +1,450 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}+-- |+-- Module : Data.Array.Accelerate.Pattern.TH+-- Copyright : [2018..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Pattern.TH (++ mkPattern,+ mkPatterns,++) where++import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.Pattern+import Data.Array.Accelerate.Representation.Tag+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Type++import Control.Monad+import Data.Char+import Data.List ( (\\), foldl' )+import Language.Haskell.TH.Extra hiding ( Exp, Match, match )+import Numeric+import Text.Printf+import qualified Language.Haskell.TH.Extra as TH++import GHC.Stack+++-- | As 'mkPattern', but for a list of types+--+mkPatterns :: [Name] -> DecsQ+mkPatterns nms = concat <$> mapM mkPattern nms++-- | Generate pattern synonyms for the given simple (Haskell'98) sum or+-- product data type.+--+-- Constructor and record selectors are renamed to add a trailing+-- underscore if it does not exist, or to remove it if it does. For infix+-- constructors, the name is prepended with a colon ':'. For example:+--+-- > data Point = Point { xcoord_ :: Float, ycoord_ :: Float }+-- > deriving (Generic, Elt)+--+-- Will create the pattern synonym:+--+-- > Point_ :: Exp Float -> Exp Float -> Exp Point+--+-- together with the selector functions+--+-- > xcoord :: Exp Point -> Exp Float+-- > ycoord :: Exp Point -> Exp Float+--+mkPattern :: Name -> DecsQ+mkPattern nm = do+ info <- reify nm+ case info of+ TyConI dec -> mkDec dec+ _ -> fail "mkPatterns: expected the name of a newtype or datatype"++mkDec :: Dec -> DecsQ+mkDec dec =+ case dec of+ DataD _ nm tv _ cs _ -> mkDataD nm tv cs+ NewtypeD _ nm tv _ c _ -> mkNewtypeD nm tv c+ _ -> fail "mkPatterns: expected the name of a newtype or datatype"++mkNewtypeD :: Name -> [TyVarBndr a] -> Con -> DecsQ+mkNewtypeD tn tvs c = mkDataD tn tvs [c]++mkDataD :: Name -> [TyVarBndr a] -> [Con] -> DecsQ+mkDataD tn tvs cs = do+ (pats, decs) <- unzip <$> go cs+ comp <- pragCompleteD pats Nothing+ return $ comp : concat decs+ where+ -- For single-constructor types we create the pattern synonym for the+ -- type directly in terms of Pattern+ go [] = fail "mkPatterns: empty data declarations not supported"+ go [c] = return <$> mkConP tn tvs c+ go _ = go' [] (map fieldTys cs) [0 .. fromIntegral (length cs - 1)] cs++ -- For sum-types, when creating the pattern for an individual+ -- constructor we need to know about the types of the fields all other+ -- constructors as well+ go' prev (this:next) (tag:tags) (con:cons) = do+ r <- mkConS tn tvs prev next tag con+ rs <- go' (this:prev) next tags cons+ return (r : rs)+ go' _ [] [] [] = return []+ go' _ _ _ _ = fail "mkPatterns: unexpected error"++ fieldTys (NormalC _ fs) = map snd fs+ fieldTys (RecC _ fs) = map (\(_,_,t) -> t) fs+ fieldTys (InfixC a _ b) = [snd a, snd b]+ fieldTys _ = fail "mkPatterns: only constructors for \"vanilla\" syntax are supported"+++mkConP :: Name -> [TyVarBndr a] -> Con -> Q (Name, [Dec])+mkConP tn' tvs' con' = do+ checkExts [ PatternSynonyms ]+ case con' of+ NormalC cn fs -> mkNormalC tn' cn (map tyVarBndrName tvs') (map snd fs)+ RecC cn fs -> mkRecC tn' cn (map tyVarBndrName tvs') (map (rename . fst3) fs) (map thd3 fs)+ InfixC a cn b -> mkInfixC tn' cn (map tyVarBndrName tvs') [snd a, snd b]+ _ -> fail "mkPatterns: only constructors for \"vanilla\" syntax are supported"+ where+ mkNormalC :: Name -> Name -> [Name] -> [Type] -> Q (Name, [Dec])+ mkNormalC tn cn tvs fs = do+ xs <- replicateM (length fs) (newName "_x")+ r <- sequence [ patSynSigD pat sig+ , patSynD pat+ (prefixPatSyn xs)+ implBidir+ [p| Pattern $(tupP (map varP xs)) |]+ ]+ return (pat, r)+ where+ pat = rename cn+ sig = forallT+ (map (`plainInvisTV` specifiedSpec) tvs)+ (cxt (map (\t -> [t| Elt $(varT t) |]) tvs))+ (foldr (\t ts -> [t| $t -> $ts |])+ [t| Exp $(foldl' appT (conT tn) (map varT tvs)) |]+ (map (\t -> [t| Exp $(return t) |]) fs))++ mkRecC :: Name -> Name -> [Name] -> [Name] -> [Type] -> Q (Name, [Dec])+ mkRecC tn cn tvs xs fs = do+ r <- sequence [ patSynSigD pat sig+ , patSynD pat+ (recordPatSyn xs)+ implBidir+ [p| Pattern $(tupP (map varP xs)) |]+ ]+ return (pat, r)+ where+ pat = rename cn+ sig = forallT+ (map (`plainInvisTV` specifiedSpec) tvs)+ (cxt (map (\t -> [t| Elt $(varT t) |]) tvs))+ (foldr (\t ts -> [t| $t -> $ts |])+ [t| Exp $(foldl' appT (conT tn) (map varT tvs)) |]+ (map (\t -> [t| Exp $(return t) |]) fs))++ mkInfixC :: Name -> Name -> [Name] -> [Type] -> Q (Name, [Dec])+ mkInfixC tn cn tvs fs = do+ mf <- reifyFixity cn+ _a <- newName "_a"+ _b <- newName "_b"+ r <- sequence [ patSynSigD pat sig+ , patSynD pat+ (infixPatSyn _a _b)+ implBidir+ [p| Pattern $(tupP [varP _a, varP _b]) |]+ ]+ r' <- case mf of+ Nothing -> return r+-- Since template-haskell 2.22, NamespaceSpecifier has been added+-- https://hackage.haskell.org/package/template-haskell-2.22.0.0/changelog+#if MIN_VERSION_template_haskell(2,22,0)+ Just f -> return (InfixD f NoNamespaceSpecifier pat : r)+#else+ Just f -> return (InfixD f pat : r)+#endif+ return (pat, r')+ where+ pat = mkName (':' : nameBase cn)+ sig = forallT+ (map (`plainInvisTV` specifiedSpec) tvs)+ (cxt (map (\t -> [t| Elt $(varT t) |]) tvs))+ (foldr (\t ts -> [t| $t -> $ts |])+ [t| Exp $(foldl' appT (conT tn) (map varT tvs)) |]+ (map (\t -> [t| Exp $(return t) |]) fs))++mkConS :: Name -> [TyVarBndr a] -> [[Type]] -> [[Type]] -> Word8 -> Con -> Q (Name, [Dec])+mkConS tn' tvs' prev' next' tag' con' = do+ checkExts [GADTs, PatternSynonyms, ScopedTypeVariables, TypeApplications, ViewPatterns]+ case con' of+ NormalC cn fs -> mkNormalC tn' cn tag' (map tyVarBndrName tvs') prev' (map snd fs) next'+ RecC cn fs -> mkRecC tn' cn tag' (map tyVarBndrName tvs') (map (rename . fst3) fs) prev' (map thd3 fs) next'+ InfixC a cn b -> mkInfixC tn' cn tag' (map tyVarBndrName tvs') prev' [snd a, snd b] next'+ _ -> fail "mkPatterns: only constructors for \"vanilla\" syntax are supported"+ where+ mkNormalC :: Name -> Name -> Word8 -> [Name] -> [[Type]] -> [Type] -> [[Type]] -> Q (Name, [Dec])+ mkNormalC tn cn tag tvs ps fs ns = do+ let pat = rename cn+ (fun_build, dec_build) <- mkBuild tn (nameBase cn) tvs tag ps fs ns+ (fun_match, dec_match) <- mkMatch tn (nameBase pat) (nameBase cn) tvs tag ps fs ns+ dec_pat <- mkNormalC_pattern tn pat tvs fs fun_build fun_match+ return $ (pat, concat [dec_pat, dec_build, dec_match])++ mkRecC :: Name -> Name -> Word8 -> [Name] -> [Name] -> [[Type]] -> [Type] -> [[Type]] -> Q (Name, [Dec])+ mkRecC tn cn tag tvs xs ps fs ns = do+ let pat = rename cn+ (fun_build, dec_build) <- mkBuild tn (nameBase cn) tvs tag ps fs ns+ (fun_match, dec_match) <- mkMatch tn (nameBase pat) (nameBase cn) tvs tag ps fs ns+ dec_pat <- mkRecC_pattern tn pat tvs xs fs fun_build fun_match+ return $ (pat, concat [dec_pat, dec_build, dec_match])++ mkInfixC :: Name -> Name -> Word8 -> [Name] -> [[Type]] -> [Type] -> [[Type]] -> Q (Name, [Dec])+ mkInfixC tn cn tag tvs ps fs ns = do+ let pat = mkName (':' : nameBase cn)+ (fun_build, dec_build) <- mkBuild tn (zencode (nameBase cn)) tvs tag ps fs ns+ (fun_match, dec_match) <- mkMatch tn ("(" ++ nameBase pat ++ ")") (zencode (nameBase cn)) tvs tag ps fs ns+ dec_pat <- mkInfixC_pattern tn cn pat tvs fs fun_build fun_match+ return $ (pat, concat [dec_pat, dec_build, dec_match])++ mkNormalC_pattern :: Name -> Name -> [Name] -> [Type] -> Name -> Name -> Q [Dec]+ mkNormalC_pattern tn pat tvs fs build match = do+ xs <- replicateM (length fs) (newName "_x")+ r <- sequence [ patSynSigD pat sig+ , patSynD pat+ (prefixPatSyn xs)+ (explBidir [clause [] (normalB (varE build)) []])+ (parensP $ viewP (varE match) [p| Just $(tupP (map varP xs)) |])+ ]+ return r+ where+ sig = forallT+ (map (`plainInvisTV` specifiedSpec) tvs)+ (cxt ([t| HasCallStack |] : map (\t -> [t| Elt $(varT t) |]) tvs))+ (foldr (\t ts -> [t| $t -> $ts |])+ [t| Exp $(foldl' appT (conT tn) (map varT tvs)) |]+ (map (\t -> [t| Exp $(return t) |]) fs))++ mkRecC_pattern :: Name -> Name -> [Name] -> [Name] -> [Type] -> Name -> Name -> Q [Dec]+ mkRecC_pattern tn pat tvs xs fs build match = do+ r <- sequence [ patSynSigD pat sig+ , patSynD pat+ (recordPatSyn xs)+ (explBidir [clause [] (normalB (varE build)) []])+ (parensP $ viewP (varE match) [p| Just $(tupP (map varP xs)) |])+ ]+ return r+ where+ sig = forallT+ (map (`plainInvisTV` specifiedSpec) tvs)+ (cxt ([t| HasCallStack |] : map (\t -> [t| Elt $(varT t) |]) tvs))+ (foldr (\t ts -> [t| $t -> $ts |])+ [t| Exp $(foldl' appT (conT tn) (map varT tvs)) |]+ (map (\t -> [t| Exp $(return t) |]) fs))++ mkInfixC_pattern :: Name -> Name -> Name -> [Name] -> [Type] -> Name -> Name -> Q [Dec]+ mkInfixC_pattern tn cn pat tvs fs build match = do+ mf <- reifyFixity cn+ _a <- newName "_a"+ _b <- newName "_b"+ r <- sequence [ patSynSigD pat sig+ , patSynD pat+ (infixPatSyn _a _b)+ (explBidir [clause [] (normalB (varE build)) []])+ (parensP $ viewP (varE match) [p| Just $(tupP [varP _a, varP _b]) |])+ ]+ r' <- case mf of+ Nothing -> return r+-- Since template-haskell 2.22, NamespaceSpecifier has been added+-- https://hackage.haskell.org/package/template-haskell-2.22.0.0/changelog+#if MIN_VERSION_template_haskell(2,22,0)+ Just f -> return (InfixD f NoNamespaceSpecifier pat : r)+#else+ Just f -> return (InfixD f pat : r)+#endif+ return r'+ where+ sig = forallT+ (map (`plainInvisTV` specifiedSpec) tvs)+ (cxt ([t| HasCallStack |] : map (\t -> [t| Elt $(varT t) |]) tvs))+ (foldr (\t ts -> [t| $t -> $ts |])+ [t| Exp $(foldl' appT (conT tn) (map varT tvs)) |]+ (map (\t -> [t| Exp $(return t) |]) fs))++ mkBuild :: Name -> String -> [Name] -> Word8 -> [[Type]] -> [Type] -> [[Type]] -> Q (Name, [Dec])+ mkBuild tn cn tvs tag fs0 fs fs1 = do+ fun <- newName ("_build" ++ cn)+ xs <- replicateM (length fs) (newName "_x")+ let+ vs = foldl' (\es e -> [| SmartExp ($es `Pair` $e) |]) [| SmartExp Nil |]+ $ map (\t -> [| unExp $(varE 'undef `appTypeE` return t) |] ) (concat (reverse fs0))+ ++ map varE xs+ ++ map (\t -> [| unExp $(varE 'undef `appTypeE` return t) |] ) (concat fs1)++ tagged = [| Exp $ SmartExp $ Pair (SmartExp (Const (SingleScalarType (NumSingleType (IntegralNumType TypeWord8))) $(litE (IntegerL (toInteger tag))))) $vs |]+ body = clause (map (\x -> [p| (Exp $(varP x)) |]) xs) (normalB tagged) []++ r <- sequence [ sigD fun sig+ , funD fun [body]+ ]+ return (fun, r)+ where+ sig = forallT+ (map (`plainInvisTV` specifiedSpec) tvs)+ (cxt (map (\t -> [t| Elt $(varT t) |]) tvs))+ (foldr (\t ts -> [t| $t -> $ts |])+ [t| Exp $(foldl' appT (conT tn) (map varT tvs)) |]+ (map (\t -> [t| Exp $(return t) |]) fs))+++ mkMatch :: Name -> String -> String -> [Name] -> Word8 -> [[Type]] -> [Type] -> [[Type]] -> Q (Name, [Dec])+ mkMatch tn pn cn tvs tag fs0 fs fs1 = do+ fun <- newName ("_match" ++ cn)+ e <- newName "_e"+ x <- newName "_x"+ (ps,es) <- extract vs [| Prj PairIdxRight $(varE x) |] [] []+ unbind <- isExtEnabled RebindableSyntax+ let+ eqE = if unbind then letE [funD (mkName "==") [clause [] (normalB (varE '(==))) []]] else id+ lhs = [p| (Exp $(varP e)) |]+ body = normalB $ eqE $ caseE (varE e)+ [ TH.match (conP 'SmartExp [(conP 'Match [matchP ps, varP x])]) (normalB [| Just $(tupE es) |]) []+ , TH.match (conP 'SmartExp [(recP 'Match [])]) (normalB [| Nothing |]) []+ , TH.match wildP (normalB [| error $error_msg |]) []+ ]++ r <- sequence [ sigD fun sig+ , funD fun [clause [lhs] body []]+ ]+ return (fun, r)+ where+ sig = forallT+ (map (`plainInvisTV` specifiedSpec) tvs)+ (cxt ([t| HasCallStack |] : map (\t -> [t| Elt $(varT t) |]) tvs))+ [t| Exp $(foldl' appT (conT tn) (map varT tvs)) -> Maybe $(tupT (map (\t -> [t| Exp $(return t) |]) fs)) |]++ matchP us = [p| TagRtag $(litP (IntegerL (toInteger tag))) $pat |]+ where+ pat = [p| $(foldl (\ps p -> [p| TagRpair $ps $p |]) [p| TagRunit |] us) |]++ extract [] _ ps es = return (ps, es)+ extract (u:us) x ps es = do+ _u <- newName "_u"+ let x' = [| Prj PairIdxLeft (SmartExp $x) |]+ if not u+ then extract us x' (wildP:ps) es+ else extract us x' (varP _u:ps) ([| Exp (SmartExp (Match $(varE _u) (SmartExp (Prj PairIdxRight (SmartExp $x))))) |] : es)++ vs = reverse+ $ [ False | _ <- concat fs0 ] ++ [ True | _ <- fs ] ++ [ False | _ <- concat fs1 ]++ error_msg =+ let pv = unwords+ $ take (length fs + 1)+ $ concatMap (map reverse)+ $ iterate (concatMap (\xs -> [ x:xs | x <- ['a'..'z'] ])) [""]+ in stringE $ unlines+ [ "Embedded pattern synonym used outside 'match' context."+ , ""+ , "To use case statements in the embedded language the case statement must"+ , "be applied as an n-ary function to the 'match' operator. For single"+ , "argument case statements this can be done inline using LambdaCase, for"+ , "example:"+ , ""+ , "> x & match \\case"+ , printf "> %s%s -> ..." pn pv+ , printf "> _%s -> ..." (replicate (length pn + length pv - 1) ' ')+ ]++fst3 :: (a,b,c) -> a+fst3 (a,_,_) = a++thd3 :: (a,b,c) -> c+thd3 (_,_,c) = c++rename :: Name -> Name+rename nm =+ let+ split acc [] = (reverse acc, '\0') -- shouldn't happen+ split acc [l] = (reverse acc, l)+ split acc (l:ls) = split (l:acc) ls+ --+ nm' = nameBase nm+ (base, suffix) = split [] nm'+ in+ case suffix of+ '_' -> mkName base+ _ -> mkName (nm' ++ "_")++checkExts :: [Extension] -> Q ()+checkExts req = do+ enabled <- extsEnabled+ let missing = req \\ enabled+ unless (null missing) . fail . unlines+ $ printf "You must enable the following language extensions to generate pattern synonyms:"+ : map (printf " {-# LANGUAGE %s #-}" . show) missing++-- A simplified version of that stolen from GHC/Utils/Encoding.hs+--+type EncodedString = String++zencode :: String -> EncodedString+zencode [] = []+zencode (h:rest) = encode_digit h ++ go rest+ where+ go [] = []+ go (c:cs) = encode_ch c ++ go cs++unencoded_char :: Char -> Bool+unencoded_char 'z' = False+unencoded_char 'Z' = False+unencoded_char c = isAlphaNum c++encode_digit :: Char -> EncodedString+encode_digit c | isDigit c = encode_as_unicode_char c+ | otherwise = encode_ch c++encode_ch :: Char -> EncodedString+encode_ch c | unencoded_char c = [c] -- Common case first+encode_ch '(' = "ZL"+encode_ch ')' = "ZR"+encode_ch '[' = "ZM"+encode_ch ']' = "ZN"+encode_ch ':' = "ZC"+encode_ch 'Z' = "ZZ"+encode_ch 'z' = "zz"+encode_ch '&' = "za"+encode_ch '|' = "zb"+encode_ch '^' = "zc"+encode_ch '$' = "zd"+encode_ch '=' = "ze"+encode_ch '>' = "zg"+encode_ch '#' = "zh"+encode_ch '.' = "zi"+encode_ch '<' = "zl"+encode_ch '-' = "zm"+encode_ch '!' = "zn"+encode_ch '+' = "zp"+encode_ch '\'' = "zq"+encode_ch '\\' = "zr"+encode_ch '/' = "zs"+encode_ch '*' = "zt"+encode_ch '_' = "zu"+encode_ch '%' = "zv"+encode_ch c = encode_as_unicode_char c++encode_as_unicode_char :: Char -> EncodedString+encode_as_unicode_char c+ = 'z'+ : if isDigit (head hex_str) then hex_str+ else '0':hex_str+ where+ hex_str = showHex (ord c) "U"+
+ src/Data/Array/Accelerate/Prelude.hs view
@@ -0,0 +1,2631 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RebindableSyntax #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# OPTIONS_GHC -fno-warn-incomplete-patterns #-} -- pattern synonyms+-- |+-- Module : Data.Array.Accelerate.Prelude+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- Standard functions that are not part of the core set (directly represented in+-- the AST), but are instead implemented in terms of the core set.+--++module Data.Array.Accelerate.Prelude (++ -- * Element-wise operations+ indexed,+ imap,++ -- * Zipping+ zipWith3, zipWith4, zipWith5, zipWith6, zipWith7, zipWith8, zipWith9,+ izipWith, izipWith3, izipWith4, izipWith5, izipWith6, izipWith7, izipWith8, izipWith9,+ zip, zip3, zip4, zip5, zip6, zip7, zip8, zip9,++ -- * Unzipping+ unzip, unzip3, unzip4, unzip5, unzip6, unzip7, unzip8, unzip9,++ -- * Reductions+ foldAll, fold1All,+ foldSeg, fold1Seg,++ -- ** Specialised folds+ all, any, and, or, sum, product, minimum, maximum,++ -- * Scans+ prescanl, postscanl, prescanr, postscanr,++ -- ** Segmented scans+ scanlSeg, scanl'Seg, scanl1Seg, prescanlSeg, postscanlSeg,+ scanrSeg, scanr'Seg, scanr1Seg, prescanrSeg, postscanrSeg,++ -- * Shape manipulation+ flatten,++ -- * Enumeration and filling+ fill, enumFromN, enumFromStepN,++ -- * Concatenation+ (++), concatOn,++ -- * Working with predicates+ -- ** Filtering+ filter, compact,++ -- ** Scatter / Gather+ scatter, scatterIf,+ gather, gatherIf,++ -- * Permutations+ reverse, transpose,+ reverseOn, transposeOn,++ -- * Extracting sub-vectors+ init, tail, take, drop, slit,+ initOn, tailOn, takeOn, dropOn, slitOn,++ -- * Controlling execution+ compute,++ -- * Flow control+ IfThenElse(..),++ -- ** Array-level+ (?|),++ -- ** Expression-level+ (?), match,++ -- * Scalar iteration+ iterate,++ -- * Scalar reduction+ sfoldl, -- sfoldr,++ -- * Lifting and unlifting+ Lift(..), Unlift(..),+ lift1, lift2, lift3, ilift1, ilift2, ilift3,++ -- ** Tuple construction and destruction+ fst, afst, snd, asnd, curry, uncurry,++ -- ** Index construction and destruction+ index0, index1, unindex1, index2, unindex2, index3, unindex3,++ -- * Array operations with a scalar result+ the, null, length,++ -- * Irregular data-parallelism+ expand,++ -- * Sequence operations+ -- fromSeq, fromSeqElems, fromSeqShapes, toSeqInner, toSeqOuter2, toSeqOuter3, generateSeq,++) where++import Data.Array.Accelerate.Analysis.Match+import Data.Array.Accelerate.Language+import Data.Array.Accelerate.Lift+import Data.Array.Accelerate.Pattern+import Data.Array.Accelerate.Pattern.Maybe+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Array ( Arrays, Array, Scalar, Vector, Segments, fromList )+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Sugar.Shape ( Shape, Slice, Z(..), (:.)(..), All(..), DIM1, DIM2, empty )+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.Classes.Eq+import Data.Array.Accelerate.Classes.FromIntegral+import Data.Array.Accelerate.Classes.Integral+import Data.Array.Accelerate.Classes.Num+import Data.Array.Accelerate.Classes.Ord++import Data.Array.Accelerate.Data.Bits++import Lens.Micro ( Lens', (&), (^.), (.~), (+~), (-~), lens, over )+import Prelude ( (.), ($), Maybe(..), const, id, flip )+#if __GLASGOW_HASKELL__ >= 904+import Data.Type.Equality+#endif+++-- $setup+-- >>> :seti -XFlexibleContexts+-- >>> import Data.Array.Accelerate+-- >>> import Data.Array.Accelerate.Interpreter+-- >>> :{+-- let runExp :: Elt e => Exp e -> e+-- runExp e = indexArray (run (unit e)) Z+-- :}++-- Element-wise operations+-- -----------------------++-- | Pair each element with its index+--+-- >>> let xs = fromList (Z:.5) [0..] :: Vector Float+-- >>> run $ indexed (use xs)+-- Vector (Z :. 5) [(Z :. 0,0.0),(Z :. 1,1.0),(Z :. 2,2.0),(Z :. 3,3.0),(Z :. 4,4.0)]+--+-- >>> let mat = fromList (Z:.3:.4) [0..] :: Matrix Float+-- >>> run $ indexed (use mat)+-- Matrix (Z :. 3 :. 4)+-- [ (Z :. 0 :. 0,0.0), (Z :. 0 :. 1,1.0), (Z :. 0 :. 2,2.0), (Z :. 0 :. 3,3.0),+-- (Z :. 1 :. 0,4.0), (Z :. 1 :. 1,5.0), (Z :. 1 :. 2,6.0), (Z :. 1 :. 3,7.0),+-- (Z :. 2 :. 0,8.0), (Z :. 2 :. 1,9.0), (Z :. 2 :. 2,10.0), (Z :. 2 :. 3,11.0)]+--+indexed :: (Shape sh, Elt a) => Acc (Array sh a) -> Acc (Array sh (sh, a))+indexed = imap T2++-- | Apply a function to every element of an array and its index+--+imap :: (Shape sh, Elt a, Elt b)+ => (Exp sh -> Exp a -> Exp b)+ -> Acc (Array sh a)+ -> Acc (Array sh b)+imap f xs = zipWith f (generate (shape xs) id) xs++-- | Used to define the zipWith functions on more than two arrays+--+zipWithInduction+ :: (Shape sh, Elt a, Elt b)+ => ((Exp (a,b) -> rest) -> Acc (Array sh (a,b)) -> result) -- The zipWith function operating on one fewer array+ -> (Exp a -> Exp b -> rest)+ -> Acc (Array sh a)+ -> Acc (Array sh b)+ -> result+zipWithInduction prev f as bs = prev (\(T2 a b) -> f a b) (zip as bs)+++-- | Zip three arrays with the given function, analogous to 'zipWith'.+--+zipWith3+ :: (Shape sh, Elt a, Elt b, Elt c, Elt d)+ => (Exp a -> Exp b -> Exp c -> Exp d)+ -> Acc (Array sh a)+ -> Acc (Array sh b)+ -> Acc (Array sh c)+ -> Acc (Array sh d)+zipWith3 = zipWithInduction zipWith++-- | Zip four arrays with the given function, analogous to 'zipWith'.+--+zipWith4+ :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e)+ => (Exp a -> Exp b -> Exp c -> Exp d -> Exp e)+ -> Acc (Array sh a)+ -> Acc (Array sh b)+ -> Acc (Array sh c)+ -> Acc (Array sh d)+ -> Acc (Array sh e)+zipWith4 = zipWithInduction zipWith3++-- | Zip five arrays with the given function, analogous to 'zipWith'.+--+zipWith5+ :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f)+ => (Exp a -> Exp b -> Exp c -> Exp d -> Exp e -> Exp f)+ -> Acc (Array sh a)+ -> Acc (Array sh b)+ -> Acc (Array sh c)+ -> Acc (Array sh d)+ -> Acc (Array sh e)+ -> Acc (Array sh f)+zipWith5 = zipWithInduction zipWith4++-- | Zip six arrays with the given function, analogous to 'zipWith'.+--+zipWith6+ :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g)+ => (Exp a -> Exp b -> Exp c -> Exp d -> Exp e -> Exp f -> Exp g)+ -> Acc (Array sh a)+ -> Acc (Array sh b)+ -> Acc (Array sh c)+ -> Acc (Array sh d)+ -> Acc (Array sh e)+ -> Acc (Array sh f)+ -> Acc (Array sh g)+zipWith6 = zipWithInduction zipWith5++-- | Zip seven arrays with the given function, analogous to 'zipWith'.+--+zipWith7+ :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h)+ => (Exp a -> Exp b -> Exp c -> Exp d -> Exp e -> Exp f -> Exp g -> Exp h)+ -> Acc (Array sh a)+ -> Acc (Array sh b)+ -> Acc (Array sh c)+ -> Acc (Array sh d)+ -> Acc (Array sh e)+ -> Acc (Array sh f)+ -> Acc (Array sh g)+ -> Acc (Array sh h)+zipWith7 = zipWithInduction zipWith6++-- | Zip eight arrays with the given function, analogous to 'zipWith'.+--+zipWith8+ :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i)+ => (Exp a -> Exp b -> Exp c -> Exp d -> Exp e -> Exp f -> Exp g -> Exp h -> Exp i)+ -> Acc (Array sh a)+ -> Acc (Array sh b)+ -> Acc (Array sh c)+ -> Acc (Array sh d)+ -> Acc (Array sh e)+ -> Acc (Array sh f)+ -> Acc (Array sh g)+ -> Acc (Array sh h)+ -> Acc (Array sh i)+zipWith8 = zipWithInduction zipWith7++-- | Zip nine arrays with the given function, analogous to 'zipWith'.+--+zipWith9+ :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j)+ => (Exp a -> Exp b -> Exp c -> Exp d -> Exp e -> Exp f -> Exp g -> Exp h -> Exp i -> Exp j)+ -> Acc (Array sh a)+ -> Acc (Array sh b)+ -> Acc (Array sh c)+ -> Acc (Array sh d)+ -> Acc (Array sh e)+ -> Acc (Array sh f)+ -> Acc (Array sh g)+ -> Acc (Array sh h)+ -> Acc (Array sh i)+ -> Acc (Array sh j)+zipWith9 = zipWithInduction zipWith8+++-- | Used to define the izipWith functions on two or more arrays+--+izipWithInduction+ :: (Shape sh, Elt a, Elt b)+ => ((Exp sh -> Exp (a,b) -> rest) -> Acc (Array sh (a,b)) -> result) -- The zipWith function operating on one fewer array+ -> (Exp sh -> Exp a -> Exp b -> rest)+ -> Acc (Array sh a)+ -> Acc (Array sh b)+ -> result+izipWithInduction prev f as bs = prev (\ix (T2 a b) -> f ix a b) (zip as bs)+++-- | Zip two arrays with a function that also takes the element index+--+izipWith+ :: (Shape sh, Elt a, Elt b, Elt c)+ => (Exp sh -> Exp a -> Exp b -> Exp c)+ -> Acc (Array sh a)+ -> Acc (Array sh b)+ -> Acc (Array sh c)+izipWith = izipWithInduction imap++-- | Zip three arrays with a function that also takes the element index,+-- analogous to 'izipWith'.+--+izipWith3+ :: (Shape sh, Elt a, Elt b, Elt c, Elt d)+ => (Exp sh -> Exp a -> Exp b -> Exp c -> Exp d)+ -> Acc (Array sh a)+ -> Acc (Array sh b)+ -> Acc (Array sh c)+ -> Acc (Array sh d)+izipWith3 = izipWithInduction izipWith++-- | Zip four arrays with the given function that also takes the element index,+-- analogous to 'zipWith'.+--+izipWith4+ :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e)+ => (Exp sh -> Exp a -> Exp b -> Exp c -> Exp d -> Exp e)+ -> Acc (Array sh a)+ -> Acc (Array sh b)+ -> Acc (Array sh c)+ -> Acc (Array sh d)+ -> Acc (Array sh e)+izipWith4 = izipWithInduction izipWith3++-- | Zip five arrays with the given function that also takes the element index,+-- analogous to 'zipWith'.+--+izipWith5+ :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f)+ => (Exp sh -> Exp a -> Exp b -> Exp c -> Exp d -> Exp e -> Exp f)+ -> Acc (Array sh a)+ -> Acc (Array sh b)+ -> Acc (Array sh c)+ -> Acc (Array sh d)+ -> Acc (Array sh e)+ -> Acc (Array sh f)+izipWith5 = izipWithInduction izipWith4++-- | Zip six arrays with the given function that also takes the element index,+-- analogous to 'zipWith'.+--+izipWith6+ :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g)+ => (Exp sh -> Exp a -> Exp b -> Exp c -> Exp d -> Exp e -> Exp f -> Exp g)+ -> Acc (Array sh a)+ -> Acc (Array sh b)+ -> Acc (Array sh c)+ -> Acc (Array sh d)+ -> Acc (Array sh e)+ -> Acc (Array sh f)+ -> Acc (Array sh g)+izipWith6 = izipWithInduction izipWith5++-- | Zip seven arrays with the given function that also takes the element+-- index, analogous to 'zipWith'.+--+izipWith7+ :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h)+ => (Exp sh -> Exp a -> Exp b -> Exp c -> Exp d -> Exp e -> Exp f -> Exp g -> Exp h)+ -> Acc (Array sh a)+ -> Acc (Array sh b)+ -> Acc (Array sh c)+ -> Acc (Array sh d)+ -> Acc (Array sh e)+ -> Acc (Array sh f)+ -> Acc (Array sh g)+ -> Acc (Array sh h)+izipWith7 = izipWithInduction izipWith6++-- | Zip eight arrays with the given function that also takes the element+-- index, analogous to 'zipWith'.+--+izipWith8+ :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i)+ => (Exp sh -> Exp a -> Exp b -> Exp c -> Exp d -> Exp e -> Exp f -> Exp g -> Exp h -> Exp i)+ -> Acc (Array sh a)+ -> Acc (Array sh b)+ -> Acc (Array sh c)+ -> Acc (Array sh d)+ -> Acc (Array sh e)+ -> Acc (Array sh f)+ -> Acc (Array sh g)+ -> Acc (Array sh h)+ -> Acc (Array sh i)+izipWith8 = izipWithInduction izipWith7++-- | Zip nine arrays with the given function that also takes the element index,+-- analogous to 'zipWith'.+--+izipWith9+ :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j)+ => (Exp sh -> Exp a -> Exp b -> Exp c -> Exp d -> Exp e -> Exp f -> Exp g -> Exp h -> Exp i -> Exp j)+ -> Acc (Array sh a)+ -> Acc (Array sh b)+ -> Acc (Array sh c)+ -> Acc (Array sh d)+ -> Acc (Array sh e)+ -> Acc (Array sh f)+ -> Acc (Array sh g)+ -> Acc (Array sh h)+ -> Acc (Array sh i)+ -> Acc (Array sh j)+izipWith9 = izipWithInduction izipWith8+++-- | Combine the elements of two arrays pairwise. The shape of the result is the+-- intersection of the two argument shapes.+--+-- >>> let m1 = fromList (Z:.5:.10) [0..] :: Matrix Int+-- >>> let m2 = fromList (Z:.10:.5) [0..] :: Matrix Float+-- >>> run $ zip (use m1) (use m2)+-- Matrix (Z :. 5 :. 5)+-- [ (0,0.0), (1,1.0), (2,2.0), (3,3.0), (4,4.0),+-- (10,5.0), (11,6.0), (12,7.0), (13,8.0), (14,9.0),+-- (20,10.0), (21,11.0), (22,12.0), (23,13.0), (24,14.0),+-- (30,15.0), (31,16.0), (32,17.0), (33,18.0), (34,19.0),+-- (40,20.0), (41,21.0), (42,22.0), (43,23.0), (44,24.0)]+--+zip :: (Shape sh, Elt a, Elt b)+ => Acc (Array sh a)+ -> Acc (Array sh b)+ -> Acc (Array sh (a, b))+zip = zipWith T2++-- | Take three arrays and return an array of triples, analogous to zip.+--+zip3 :: (Shape sh, Elt a, Elt b, Elt c)+ => Acc (Array sh a)+ -> Acc (Array sh b)+ -> Acc (Array sh c)+ -> Acc (Array sh (a, b, c))+zip3 = zipWith3 T3++-- | Take four arrays and return an array of quadruples, analogous to zip.+--+zip4 :: (Shape sh, Elt a, Elt b, Elt c, Elt d)+ => Acc (Array sh a)+ -> Acc (Array sh b)+ -> Acc (Array sh c)+ -> Acc (Array sh d)+ -> Acc (Array sh (a, b, c, d))+zip4 = zipWith4 T4++-- | Take five arrays and return an array of five-tuples, analogous to zip.+--+zip5 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e)+ => Acc (Array sh a)+ -> Acc (Array sh b)+ -> Acc (Array sh c)+ -> Acc (Array sh d)+ -> Acc (Array sh e)+ -> Acc (Array sh (a, b, c, d, e))+zip5 = zipWith5 T5++-- | Take six arrays and return an array of six-tuples, analogous to zip.+--+zip6 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f)+ => Acc (Array sh a)+ -> Acc (Array sh b)+ -> Acc (Array sh c)+ -> Acc (Array sh d)+ -> Acc (Array sh e)+ -> Acc (Array sh f)+ -> Acc (Array sh (a, b, c, d, e, f))+zip6 = zipWith6 T6++-- | Take seven arrays and return an array of seven-tuples, analogous to zip.+--+zip7 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g)+ => Acc (Array sh a)+ -> Acc (Array sh b)+ -> Acc (Array sh c)+ -> Acc (Array sh d)+ -> Acc (Array sh e)+ -> Acc (Array sh f)+ -> Acc (Array sh g)+ -> Acc (Array sh (a, b, c, d, e, f, g))+zip7 = zipWith7 T7++-- | Take eight arrays and return an array of eight-tuples, analogous to zip.+--+zip8 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h)+ => Acc (Array sh a)+ -> Acc (Array sh b)+ -> Acc (Array sh c)+ -> Acc (Array sh d)+ -> Acc (Array sh e)+ -> Acc (Array sh f)+ -> Acc (Array sh g)+ -> Acc (Array sh h)+ -> Acc (Array sh (a, b, c, d, e, f, g, h))+zip8 = zipWith8 T8++-- | Take nine arrays and return an array of nine-tuples, analogous to zip.+--+zip9 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i)+ => Acc (Array sh a)+ -> Acc (Array sh b)+ -> Acc (Array sh c)+ -> Acc (Array sh d)+ -> Acc (Array sh e)+ -> Acc (Array sh f)+ -> Acc (Array sh g)+ -> Acc (Array sh h)+ -> Acc (Array sh i)+ -> Acc (Array sh (a, b, c, d, e, f, g, h, i))+zip9 = zipWith9 T9+++-- | The converse of 'zip', but the shape of the two results is identical to the+-- shape of the argument.+--+-- If the argument array is manifest in memory, 'unzip' is a no-op.+--+unzip :: (Shape sh, Elt a, Elt b)+ => Acc (Array sh (a, b))+ -> (Acc (Array sh a), Acc (Array sh b))+unzip arr = (map fst arr, map snd arr)++-- | Take an array of triples and return three arrays, analogous to 'unzip'.+--+unzip3 :: (Shape sh, Elt a, Elt b, Elt c)+ => Acc (Array sh (a, b, c))+ -> (Acc (Array sh a), Acc (Array sh b), Acc (Array sh c))+unzip3 xs = (map get1 xs, map get2 xs, map get3 xs)+ where+ get1 (T3 a _ _) = a+ get2 (T3 _ b _) = b+ get3 (T3 _ _ c) = c+++-- | Take an array of quadruples and return four arrays, analogous to 'unzip'.+--+unzip4 :: (Shape sh, Elt a, Elt b, Elt c, Elt d)+ => Acc (Array sh (a, b, c, d))+ -> (Acc (Array sh a), Acc (Array sh b), Acc (Array sh c), Acc (Array sh d))+unzip4 xs = (map get1 xs, map get2 xs, map get3 xs, map get4 xs)+ where+ get1 (T4 a _ _ _) = a+ get2 (T4 _ b _ _) = b+ get3 (T4 _ _ c _) = c+ get4 (T4 _ _ _ d) = d++-- | Take an array of 5-tuples and return five arrays, analogous to 'unzip'.+--+unzip5 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e)+ => Acc (Array sh (a, b, c, d, e))+ -> (Acc (Array sh a), Acc (Array sh b), Acc (Array sh c), Acc (Array sh d), Acc (Array sh e))+unzip5 xs = (map get1 xs, map get2 xs, map get3 xs, map get4 xs, map get5 xs)+ where+ get1 (T5 a _ _ _ _) = a+ get2 (T5 _ b _ _ _) = b+ get3 (T5 _ _ c _ _) = c+ get4 (T5 _ _ _ d _) = d+ get5 (T5 _ _ _ _ e) = e++-- | Take an array of 6-tuples and return six arrays, analogous to 'unzip'.+--+unzip6 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f)+ => Acc (Array sh (a, b, c, d, e, f))+ -> ( Acc (Array sh a), Acc (Array sh b), Acc (Array sh c)+ , Acc (Array sh d), Acc (Array sh e), Acc (Array sh f))+unzip6 xs = (map get1 xs, map get2 xs, map get3 xs, map get4 xs, map get5 xs, map get6 xs)+ where+ get1 (T6 a _ _ _ _ _) = a+ get2 (T6 _ b _ _ _ _) = b+ get3 (T6 _ _ c _ _ _) = c+ get4 (T6 _ _ _ d _ _) = d+ get5 (T6 _ _ _ _ e _) = e+ get6 (T6 _ _ _ _ _ f) = f++-- | Take an array of 7-tuples and return seven arrays, analogous to 'unzip'.+--+unzip7 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g)+ => Acc (Array sh (a, b, c, d, e, f, g))+ -> ( Acc (Array sh a), Acc (Array sh b), Acc (Array sh c)+ , Acc (Array sh d), Acc (Array sh e), Acc (Array sh f)+ , Acc (Array sh g))+unzip7 xs = ( map get1 xs, map get2 xs, map get3 xs+ , map get4 xs, map get5 xs, map get6 xs+ , map get7 xs )+ where+ get1 (T7 a _ _ _ _ _ _) = a+ get2 (T7 _ b _ _ _ _ _) = b+ get3 (T7 _ _ c _ _ _ _) = c+ get4 (T7 _ _ _ d _ _ _) = d+ get5 (T7 _ _ _ _ e _ _) = e+ get6 (T7 _ _ _ _ _ f _) = f+ get7 (T7 _ _ _ _ _ _ g) = g++-- | Take an array of 8-tuples and return eight arrays, analogous to 'unzip'.+--+unzip8 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h)+ => Acc (Array sh (a, b, c, d, e, f, g, h))+ -> ( Acc (Array sh a), Acc (Array sh b), Acc (Array sh c)+ , Acc (Array sh d), Acc (Array sh e), Acc (Array sh f)+ , Acc (Array sh g), Acc (Array sh h) )+unzip8 xs = ( map get1 xs, map get2 xs, map get3 xs+ , map get4 xs, map get5 xs, map get6 xs+ , map get7 xs, map get8 xs )+ where+ get1 (T8 a _ _ _ _ _ _ _) = a+ get2 (T8 _ b _ _ _ _ _ _) = b+ get3 (T8 _ _ c _ _ _ _ _) = c+ get4 (T8 _ _ _ d _ _ _ _) = d+ get5 (T8 _ _ _ _ e _ _ _) = e+ get6 (T8 _ _ _ _ _ f _ _) = f+ get7 (T8 _ _ _ _ _ _ g _) = g+ get8 (T8 _ _ _ _ _ _ _ h) = h++-- | Take an array of 9-tuples and return nine arrays, analogous to 'unzip'.+--+unzip9 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i)+ => Acc (Array sh (a, b, c, d, e, f, g, h, i))+ -> ( Acc (Array sh a), Acc (Array sh b), Acc (Array sh c)+ , Acc (Array sh d), Acc (Array sh e), Acc (Array sh f)+ , Acc (Array sh g), Acc (Array sh h), Acc (Array sh i))+unzip9 xs = ( map get1 xs, map get2 xs, map get3 xs+ , map get4 xs, map get5 xs, map get6 xs+ , map get7 xs, map get8 xs, map get9 xs )+ where+ get1 (T9 a _ _ _ _ _ _ _ _) = a+ get2 (T9 _ b _ _ _ _ _ _ _) = b+ get3 (T9 _ _ c _ _ _ _ _ _) = c+ get4 (T9 _ _ _ d _ _ _ _ _) = d+ get5 (T9 _ _ _ _ e _ _ _ _) = e+ get6 (T9 _ _ _ _ _ f _ _ _) = f+ get7 (T9 _ _ _ _ _ _ g _ _) = g+ get8 (T9 _ _ _ _ _ _ _ h _) = h+ get9 (T9 _ _ _ _ _ _ _ _ i) = i+++-- Reductions+-- ----------++-- | Reduction of an array of arbitrary rank to a single scalar value. The first+-- argument needs to be an /associative/ function to enable efficient parallel+-- implementation. The initial element does not need to be an identity element.+--+-- >>> let vec = fromList (Z:.10) [0..] :: Vector Float+-- >>> run $ foldAll (+) 42 (use vec)+-- Scalar Z [87.0]+--+-- >>> let mat = fromList (Z:.5:.10) [0..] :: Matrix Float+-- >>> run $ foldAll (+) 0 (use mat)+-- Scalar Z [1225.0]+--+foldAll+ :: (Shape sh, Elt a)+ => (Exp a -> Exp a -> Exp a)+ -> Exp a+ -> Acc (Array sh a)+ -> Acc (Scalar a)+foldAll f e arr = fold f e (flatten arr)++-- | Variant of 'foldAll' that requires the reduced array to be non-empty and+-- does not need a default value. The first argument must be an /associative/+-- function.+--+fold1All+ :: (Shape sh, Elt a)+ => (Exp a -> Exp a -> Exp a)+ -> Acc (Array sh a)+ -> Acc (Scalar a)+fold1All f arr = fold1 f (flatten arr)+++-- | Segmented reduction along the innermost dimension of an array. The segment+-- descriptor specifies the lengths of the logical sub-arrays, each of which is+-- reduced independently. The innermost dimension must contain at least as many+-- elements as required by the segment descriptor (sum thereof).+--+-- >>> let seg = fromList (Z:.4) [1,4,0,3] :: Segments Int+-- >>> seg+-- Vector (Z :. 4) [1,4,0,3]+--+-- >>> let mat = fromList (Z:.5:.10) [0..] :: Matrix Int+-- >>> mat+-- Matrix (Z :. 5 :. 10)+-- [ 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]+--+-- >>> run $ foldSeg (+) 0 (use mat) (use seg)+-- Matrix (Z :. 5 :. 4)+-- [ 0, 10, 0, 18,+-- 10, 50, 0, 48,+-- 20, 90, 0, 78,+-- 30, 130, 0, 108,+-- 40, 170, 0, 138]+--+foldSeg+ :: forall sh e i. (Shape sh, Elt e, Elt i, i ~ EltR i, IsIntegral i)+ => (Exp e -> Exp e -> Exp e)+ -> Exp e+ -> Acc (Array (sh:.Int) e)+ -> Acc (Segments i)+ -> Acc (Array (sh:.Int) e)+foldSeg f z arr seg = foldSeg' f z arr (scanl plus zero seg)+ where+ (plus, zero) =+ case integralType @i of+ TypeInt{} -> ((+), 0)+ TypeInt8{} -> ((+), 0)+ TypeInt16{} -> ((+), 0)+ TypeInt32{} -> ((+), 0)+ TypeInt64{} -> ((+), 0)+ TypeWord{} -> ((+), 0)+ TypeWord8{} -> ((+), 0)+ TypeWord16{} -> ((+), 0)+ TypeWord32{} -> ((+), 0)+ TypeWord64{} -> ((+), 0)+++-- | Variant of 'foldSeg' that requires /all/ segments of the reduced array+-- to be non-empty, and does not need a default value. The segment+-- descriptor species the length of each of the logical sub-arrays.+--+fold1Seg+ :: forall sh e i. (Shape sh, Elt e, Elt i, i ~ EltR i, IsIntegral i)+ => (Exp e -> Exp e -> Exp e)+ -> Acc (Array (sh:.Int) e)+ -> Acc (Segments i)+ -> Acc (Array (sh:.Int) e)+fold1Seg f arr seg = fold1Seg' f arr (scanl plus zero seg)+ where+ plus :: Exp i -> Exp i -> Exp i+ zero :: Exp i+ (plus, zero) =+ case integralType @(EltR i) of+ TypeInt{} -> ((+), 0)+ TypeInt8{} -> ((+), 0)+ TypeInt16{} -> ((+), 0)+ TypeInt32{} -> ((+), 0)+ TypeInt64{} -> ((+), 0)+ TypeWord{} -> ((+), 0)+ TypeWord8{} -> ((+), 0)+ TypeWord16{} -> ((+), 0)+ TypeWord32{} -> ((+), 0)+ TypeWord64{} -> ((+), 0)+++-- Specialised reductions+-- ----------------------+--+-- Leave the results of these as scalar arrays to make it clear that these are+-- array computations, and thus can not be nested.++-- | Check if all elements along the innermost dimension satisfy a predicate.+--+-- >>> let mat = fromList (Z :. 4 :. 10) [1,2,3,4,5,6,7,8,9,10,1,1,1,1,1,2,2,2,2,2,2,4,6,8,10,12,14,16,18,20,1,3,5,7,9,11,13,15,17,19] :: Matrix Int+-- >>> mat+-- Matrix (Z :. 4 :. 10)+-- [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,+-- 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,+-- 2, 4, 6, 8, 10, 12, 14, 16, 18, 20,+-- 1, 3, 5, 7, 9, 11, 13, 15, 17, 19]+--+-- >>> run $ all even (use mat)+-- Vector (Z :. 4) [False,False,True,False]+--+all :: (Shape sh, Elt e)+ => (Exp e -> Exp Bool)+ -> Acc (Array (sh:.Int) e)+ -> Acc (Array sh Bool)+all f = and . map f++-- | Check if any element along the innermost dimension satisfies the predicate.+--+-- >>> let mat = fromList (Z :. 4 :. 10) [1,2,3,4,5,6,7,8,9,10,1,1,1,1,1,2,2,2,2,2,2,4,6,8,10,12,14,16,18,20,1,3,5,7,9,11,13,15,17,19] :: Matrix Int+-- >>> mat+-- Matrix (Z :. 4 :. 10)+-- [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,+-- 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,+-- 2, 4, 6, 8, 10, 12, 14, 16, 18, 20,+-- 1, 3, 5, 7, 9, 11, 13, 15, 17, 19]+--+-- >>> run $ any even (use mat)+-- Vector (Z :. 4) [True,True,True,False]+--+any :: (Shape sh, Elt e)+ => (Exp e -> Exp Bool)+ -> Acc (Array (sh:.Int) e)+ -> Acc (Array sh Bool)+any f = or . map f++-- | Check if all elements along the innermost dimension are 'True'.+--+and :: Shape sh+ => Acc (Array (sh:.Int) Bool)+ -> Acc (Array sh Bool)+and = fold (&&) True_++-- | Check if any element along the innermost dimension is 'True'.+--+or :: Shape sh+ => Acc (Array (sh:.Int) Bool)+ -> Acc (Array sh Bool)+or = fold (||) False_++-- | Compute the sum of elements along the innermost dimension of the array. To+-- find the sum of the entire array, 'flatten' it first.+--+-- >>> let mat = fromList (Z:.2:.5) [0..] :: Matrix Int+-- >>> run $ sum (use mat)+-- Vector (Z :. 2) [10,35]+--+sum :: (Shape sh, Num e)+ => Acc (Array (sh:.Int) e)+ -> Acc (Array sh e)+sum = fold (+) 0++-- | Compute the product of the elements along the innermost dimension of the+-- array. To find the product of the entire array, 'flatten' it first.+--+-- >>> let mat = fromList (Z:.2:.5) [0..] :: Matrix Int+-- >>> run $ product (use mat)+-- Vector (Z :. 2) [0,15120]+--+product+ :: (Shape sh, Num e)+ => Acc (Array (sh:.Int) e)+ -> Acc (Array sh e)+product = fold (*) 1++-- | Yield the minimum element along the innermost dimension of the array. To+-- find find the minimum element of the entire array, 'flatten' it first.+--+-- The array must not be empty. See also 'fold1'.+--+-- >>> let mat = fromList (Z :. 3 :. 4) [1,4,3,8, 0,2,8,4, 7,9,8,8] :: Matrix Int+-- >>> mat+-- Matrix (Z :. 3 :. 4)+-- [ 1, 4, 3, 8,+-- 0, 2, 8, 4,+-- 7, 9, 8, 8]+--+-- >>> run $ minimum (use mat)+-- Vector (Z :. 3) [1,0,7]+--+minimum+ :: (Shape sh, Ord e)+ => Acc (Array (sh:.Int) e)+ -> Acc (Array sh e)+minimum = fold1 min++-- | Yield the maximum element along the innermost dimension of the array. To+-- find the maximum element of the entire array, 'flatten' it first.+--+-- The array must not be empty. See also 'fold1'.+--+-- >>> let mat = fromList (Z :. 3 :. 4) [1,4,3,8, 0,2,8,4, 7,9,8,8] :: Matrix Int+-- >>> mat+-- Matrix (Z :. 3 :. 4)+-- [ 1, 4, 3, 8,+-- 0, 2, 8, 4,+-- 7, 9, 8, 8]+--+-- >>> run $ maximum (use mat)+-- Vector (Z :. 3) [8,8,9]+--+maximum+ :: (Shape sh, Ord e)+ => Acc (Array (sh:.Int) e)+ -> Acc (Array sh e)+maximum = fold1 max+++-- Composite scans+-- ---------------++-- | Left-to-right pre-scan (aka exclusive scan). As for 'scan', the first+-- argument must be an /associative/ function. Denotationally, we have:+--+-- > prescanl f e = afst . scanl' f e+--+-- >>> let vec = fromList (Z:.10) [1..10] :: Vector Int+-- >>> run $ prescanl (+) 0 (use vec)+-- Vector (Z :. 10) [0,1,3,6,10,15,21,28,36,45]+--+prescanl+ :: (Shape sh, Elt a)+ => (Exp a -> Exp a -> Exp a)+ -> Exp a+ -> Acc (Array (sh:.Int) a)+ -> Acc (Array (sh:.Int) a)+prescanl f e = afst . scanl' f e++-- | Left-to-right post-scan, a variant of 'scanl1' with an initial value. As+-- with 'scanl1', the array must not be empty. Denotationally, we have:+--+-- > postscanl f e = map (e `f`) . scanl1 f+--+-- >>> let vec = fromList (Z:.10) [1..10] :: Vector Int+-- >>> run $ postscanl (+) 42 (use vec)+-- Vector (Z :. 10) [43,45,48,52,57,63,70,78,87,97]+--+postscanl+ :: (Shape sh, Elt a)+ => (Exp a -> Exp a -> Exp a)+ -> Exp a+ -> Acc (Array (sh:.Int) a)+ -> Acc (Array (sh:.Int) a)+postscanl f e = map (e `f`) . scanl1 f++-- | Right-to-left pre-scan (aka exclusive scan). As for 'scan', the first+-- argument must be an /associative/ function. Denotationally, we have:+--+-- > prescanr f e = afst . scanr' f e+--+prescanr+ :: (Shape sh, Elt a)+ => (Exp a -> Exp a -> Exp a)+ -> Exp a+ -> Acc (Array (sh:.Int) a)+ -> Acc (Array (sh:.Int) a)+prescanr f e = afst . scanr' f e++-- | Right-to-left postscan, a variant of 'scanr1' with an initial value.+-- Denotationally, we have:+--+-- > postscanr f e = map (e `f`) . scanr1 f+--+postscanr+ :: (Shape sh, Elt a)+ => (Exp a -> Exp a -> Exp a)+ -> Exp a+ -> Acc (Array (sh:.Int) a)+ -> Acc (Array (sh:.Int) a)+postscanr f e = map (`f` e) . scanr1 f+++-- Segmented scans+-- ---------------++-- | Segmented version of 'scanl' along the innermost dimension of an array. The+-- innermost dimension must have at least as many elements as the sum of the+-- segment descriptor.+--+-- >>> let seg = fromList (Z:.4) [1,4,0,3] :: Segments Int+-- >>> seg+-- Vector (Z :. 4) [1,4,0,3]+--+-- >>> let mat = fromList (Z:.5:.10) [0..] :: Matrix Int+-- >>> mat+-- Matrix (Z :. 5 :. 10)+-- [ 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]+--+-- >>> run $ scanlSeg (+) 0 (use mat) (use seg)+-- Matrix (Z :. 5 :. 12)+-- [ 0, 0, 0, 1, 3, 6, 10, 0, 0, 5, 11, 18,+-- 0, 10, 0, 11, 23, 36, 50, 0, 0, 15, 31, 48,+-- 0, 20, 0, 21, 43, 66, 90, 0, 0, 25, 51, 78,+-- 0, 30, 0, 31, 63, 96, 130, 0, 0, 35, 71, 108,+-- 0, 40, 0, 41, 83, 126, 170, 0, 0, 45, 91, 138]+--+scanlSeg+ :: forall sh e i. (Shape sh, Slice sh, Elt e, Integral i, Bits i, FromIntegral i Int)+ => (Exp e -> Exp e -> Exp e)+ -> Exp e+ -> Acc (Array (sh:.Int) e)+ -> Acc (Segments i)+ -> Acc (Array (sh:.Int) e)+scanlSeg f z arr seg =+ if null arr || null flags+ then fill (sh ::. sz + length seg) z+ else scanl1Seg f arr' seg'+ where+ -- Segmented exclusive scan is implemented by first injecting the seed+ -- element at the head of each segment, and then performing a segmented+ -- inclusive scan.+ --+ -- This is done by creating a vector entirely of the seed element, and+ -- overlaying the input data in all places other than at the start of+ -- a segment.+ --+ sh ::. sz = shape arr+ seg' = map (+1) seg+ arr' = permute const+ (fill (sh ::. sz + length seg) z)+ (\(sx ::. i) -> Just_ (sx ::. i + fromIntegral (inc ! I1 i)))+ (take (length flags) arr)++ -- Each element in the segments must be shifted to the right one additional+ -- place for each successive segment, to make room for the seed element.+ -- Here, we make use of the fact that the vector returned by 'mkHeadFlags'+ -- contains non-unit entries, which indicate zero length segments.+ --+ flags = mkHeadFlags seg+ inc = scanl1 (+) flags+++-- | Segmented version of 'scanl'' along the innermost dimension of an array. The+-- innermost dimension must have at least as many elements as the sum of the+-- segment descriptor.+--+-- The first element of the resulting tuple is a vector of scanned values. The+-- second element is a vector of segment scan totals and has the same size as+-- the segment vector.+--+-- >>> let seg = fromList (Z:.4) [1,4,0,3] :: Segments Int+-- >>> seg+-- Vector (Z :. 4) [1,4,0,3]+--+-- >>> let mat = fromList (Z:.5:.10) [0..] :: Matrix Int+-- >>> mat+-- Matrix (Z :. 5 :. 10)+-- [ 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]+--+-- >>> let (res,sums) = run $ scanl'Seg (+) 0 (use mat) (use seg)+-- >>> res+-- Matrix (Z :. 5 :. 8)+-- [ 0, 0, 1, 3, 6, 0, 5, 11,+-- 0, 0, 11, 23, 36, 0, 15, 31,+-- 0, 0, 21, 43, 66, 0, 25, 51,+-- 0, 0, 31, 63, 96, 0, 35, 71,+-- 0, 0, 41, 83, 126, 0, 45, 91]+-- >>> sums+-- Matrix (Z :. 5 :. 4)+-- [ 0, 10, 0, 18,+-- 10, 50, 0, 48,+-- 20, 90, 0, 78,+-- 30, 130, 0, 108,+-- 40, 170, 0, 138]+--+scanl'Seg+ :: forall sh e i. (Shape sh, Slice sh, Elt e, Integral i, Bits i, FromIntegral i Int)+ => (Exp e -> Exp e -> Exp e)+ -> Exp e+ -> Acc (Array (sh:.Int) e)+ -> Acc (Segments i)+ -> Acc (Array (sh:.Int) e, Array (sh:.Int) e)+scanl'Seg f z arr seg =+ if null arr+ then T2 arr (fill (indexTail (shape arr) ::. length seg) z)+ else T2 body sums+ where+ -- Segmented scan' is implemented by deconstructing a segmented exclusive+ -- scan, to separate the final value and scan body.+ --+ -- TLM: Segmented scans, and this version in particular, expend a lot of+ -- effort scanning flag arrays. On inspection it appears that several+ -- of these operations are duplicated, but this will not be picked up+ -- by sharing _observation_. Perhaps a global CSE-style pass would be+ -- beneficial.+ --+ arr' = scanlSeg f z arr seg++ -- Extract the final reduction value for each segment, which is at the last+ -- index of each segment.+ --+ seg' = map (+1) seg+ tails = zipWith (+) seg $ prescanl (+) 0 seg'+ sums = backpermute+ (indexTail (shape arr') ::. length seg)+ (\(sz ::. i) -> sz ::. fromIntegral (tails ! I1 i))+ arr'++ -- Slice out the body of each segment.+ --+ -- Build a head-flags representation based on the original segment+ -- descriptor. This contains the target length of each of the body segments,+ -- which is one fewer element than the actual bodies stored in arr'. Thus,+ -- the flags align with the last element of each body section, and when+ -- scanned, this element will be incremented over.+ --+ offset = scanl1 (+) seg+ inc = scanl1 (+)+ $ permute (+) (fill (I1 $ size arr + 1) 0)+ (\ix -> Just_ (index1' (offset ! ix)))+ (fill (shape seg) (1 :: Exp i))++ len = offset ! I1 (length offset - 1)+ body = backpermute+ (indexTail (shape arr) ::. fromIntegral len)+ (\(sz ::. i) -> sz ::. i + fromIntegral (inc ! I1 i))+ arr'+++-- | Segmented version of 'scanl1' along the innermost dimension.+--+-- As with 'scanl1', the total number of elements considered, in this case given+-- by the 'sum' of segment descriptor, must not be zero. The input vector must+-- contain at least this many elements.+--+-- Zero length segments are allowed, and the behaviour is as if those entries+-- were not present in the segment descriptor; that is:+--+-- > scanl1Seg f xs [n,0,0] == scanl1Seg f xs [n] where n /= 0+--+-- >>> let seg = fromList (Z:.4) [1,4,0,3] :: Segments Int+-- >>> seg+-- Vector (Z :. 4) [1,4,0,3]+--+-- >>> let mat = fromList (Z:.5:.10) [0..] :: Matrix Int+-- >>> mat+-- Matrix (Z :. 5 :. 10)+-- [ 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]+--+-- >>> run $ scanl1Seg (+) (use mat) (use seg)+-- Matrix (Z :. 5 :. 8)+-- [ 0, 1, 3, 6, 10, 5, 11, 18,+-- 10, 11, 23, 36, 50, 15, 31, 48,+-- 20, 21, 43, 66, 90, 25, 51, 78,+-- 30, 31, 63, 96, 130, 35, 71, 108,+-- 40, 41, 83, 126, 170, 45, 91, 138]+--+scanl1Seg+ :: (Shape sh, Slice sh, Elt e, Integral i, Bits i, FromIntegral i Int)+ => (Exp e -> Exp e -> Exp e)+ -> Acc (Array (sh:.Int) e)+ -> Acc (Segments i)+ -> Acc (Array (sh:.Int) e)+scanl1Seg f arr seg+ = map snd+ . scanl1 (segmentedL f)+ $ zip (replicate (lift (indexTail (shape arr) :. All)) (mkHeadFlags seg)) arr++-- |Segmented version of 'prescanl'.+--+prescanlSeg+ :: (Shape sh, Slice sh, Elt e, Integral i, Bits i, FromIntegral i Int)+ => (Exp e -> Exp e -> Exp e)+ -> Exp e+ -> Acc (Array (sh:.Int) e)+ -> Acc (Segments i)+ -> Acc (Array (sh:.Int) e)+prescanlSeg f e vec seg+ = afst+ $ scanl'Seg f e vec seg++-- |Segmented version of 'postscanl'.+--+postscanlSeg+ :: (Shape sh, Slice sh, Elt e, Integral i, Bits i, FromIntegral i Int)+ => (Exp e -> Exp e -> Exp e)+ -> Exp e+ -> Acc (Array (sh:.Int) e)+ -> Acc (Segments i)+ -> Acc (Array (sh:.Int) e)+postscanlSeg f e vec seg+ = map (f e)+ $ scanl1Seg f vec seg++-- | Segmented version of 'scanr' along the innermost dimension of an array. The+-- innermost dimension must have at least as many elements as the sum of the+-- segment descriptor.+--+-- >>> let seg = fromList (Z:.4) [1,4,0,3] :: Segments Int+-- >>> seg+-- Vector (Z :. 4) [1,4,0,3]+--+-- >>> let mat = fromList (Z:.5:.10) [0..] :: Matrix Int+-- >>> mat+-- Matrix (Z :. 5 :. 10)+-- [ 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]+--+-- >>> run $ scanrSeg (+) 0 (use mat) (use seg)+-- Matrix (Z :. 5 :. 12)+-- [ 2, 0, 18, 15, 11, 6, 0, 0, 24, 17, 9, 0,+-- 12, 0, 58, 45, 31, 16, 0, 0, 54, 37, 19, 0,+-- 22, 0, 98, 75, 51, 26, 0, 0, 84, 57, 29, 0,+-- 32, 0, 138, 105, 71, 36, 0, 0, 114, 77, 39, 0,+-- 42, 0, 178, 135, 91, 46, 0, 0, 144, 97, 49, 0]+--+scanrSeg+ :: forall sh e i. (Shape sh, Slice sh, Elt e, Integral i, Bits i, FromIntegral i Int)+ => (Exp e -> Exp e -> Exp e)+ -> Exp e+ -> Acc (Array (sh:.Int) e)+ -> Acc (Segments i)+ -> Acc (Array (sh:.Int) e)+scanrSeg f z arr seg =+ if null arr || null flags+ then fill (sh ::. sz + length seg) z+ else scanr1Seg f arr' seg'+ where+ sh ::. sz = shape arr++ -- Using technique described for 'scanlSeg', where we intersperse the array+ -- with the seed element at the start of each segment, and then perform an+ -- inclusive segmented scan.+ --+ flags = mkHeadFlags seg+ inc = scanl1 (+) flags++ seg' = map (+1) seg+ arr' = permute const+ (fill (sh ::. sz + length seg) z)+ (\(sx ::. i) -> Just_ (sx ::. i + fromIntegral (inc !! i) - 1))+ (drop (sz - length flags) arr)+++-- | Segmented version of 'scanr''.+--+-- >>> let seg = fromList (Z:.4) [1,4,0,3] :: Segments Int+-- >>> seg+-- Vector (Z :. 4) [1,4,0,3]+--+-- >>> let mat = fromList (Z:.5:.10) [0..] :: Matrix Int+-- >>> mat+-- Matrix (Z :. 5 :. 10)+-- [ 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]+--+-- >>> let (res,sums) = run $ scanr'Seg (+) 0 (use mat) (use seg)+-- >>> res+-- Matrix (Z :. 5 :. 8)+-- [ 0, 15, 11, 6, 0, 17, 9, 0,+-- 0, 45, 31, 16, 0, 37, 19, 0,+-- 0, 75, 51, 26, 0, 57, 29, 0,+-- 0, 105, 71, 36, 0, 77, 39, 0,+-- 0, 135, 91, 46, 0, 97, 49, 0]+-- >>> sums+-- Matrix (Z :. 5 :. 4)+-- [ 2, 18, 0, 24,+-- 12, 58, 0, 54,+-- 22, 98, 0, 84,+-- 32, 138, 0, 114,+-- 42, 178, 0, 144]+--+scanr'Seg+ :: forall sh e i. (Shape sh, Slice sh, Elt e, Integral i, Bits i, FromIntegral i Int)+ => (Exp e -> Exp e -> Exp e)+ -> Exp e+ -> Acc (Array (sh:.Int) e)+ -> Acc (Segments i)+ -> Acc (Array (sh:.Int) e, Array (sh:.Int) e)+scanr'Seg f z arr seg =+ if null arr+ then T2 arr (fill (indexTail (shape arr) ::. length seg) z)+ else T2 body sums+ where+ -- Using technique described for scanl'Seg+ --+ arr' = scanrSeg f z arr seg++ -- reduction values+ seg' = map (+1) seg+ heads = prescanl (+) 0 seg'+ sums = backpermute+ (indexTail (shape arr') ::. length seg)+ (\(sz ::.i) -> sz ::. fromIntegral (heads ! I1 i))+ arr'++ -- body segments+ flags = mkHeadFlags seg+ inc = scanl1 (+) flags+ body = backpermute+ (indexTail (shape arr) ::. indexHead (shape flags))+ (\(sz ::. i) -> sz ::. i + fromIntegral (inc ! I1 i))+ arr'+++-- | Segmented version of 'scanr1'.+--+-- >>> let seg = fromList (Z:.4) [1,4,0,3] :: Segments Int+-- >>> seg+-- Vector (Z :. 4) [1,4,0,3]+--+-- >>> let mat = fromList (Z:.5:.10) [0..] :: Matrix Int+-- >>> mat+-- Matrix (Z :. 5 :. 10)+-- [ 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]+--+-- >>> run $ scanr1Seg (+) (use mat) (use seg)+-- Matrix (Z :. 5 :. 8)+-- [ 0, 10, 9, 7, 4, 18, 13, 7,+-- 10, 50, 39, 27, 14, 48, 33, 17,+-- 20, 90, 69, 47, 24, 78, 53, 27,+-- 30, 130, 99, 67, 34, 108, 73, 37,+-- 40, 170, 129, 87, 44, 138, 93, 47]+--+scanr1Seg+ :: (Shape sh, Slice sh, Elt e, Integral i, Bits i, FromIntegral i Int)+ => (Exp e -> Exp e -> Exp e)+ -> Acc (Array (sh:.Int) e)+ -> Acc (Segments i)+ -> Acc (Array (sh:.Int) e)+scanr1Seg f arr seg+ = map snd+ . scanr1 (segmentedR f)+ $ zip (replicate (lift (indexTail (shape arr) :. All)) (mkTailFlags seg)) arr+++-- |Segmented version of 'prescanr'.+--+prescanrSeg+ :: (Shape sh, Slice sh, Elt e, Integral i, Bits i, FromIntegral i Int)+ => (Exp e -> Exp e -> Exp e)+ -> Exp e+ -> Acc (Array (sh:.Int) e)+ -> Acc (Segments i)+ -> Acc (Array (sh:.Int) e)+prescanrSeg f e vec seg+ = afst+ $ scanr'Seg f e vec seg++-- |Segmented version of 'postscanr'.+--+postscanrSeg+ :: (Shape sh, Slice sh, Elt e, Integral i, Bits i, FromIntegral i Int)+ => (Exp e -> Exp e -> Exp e)+ -> Exp e+ -> Acc (Array (sh:.Int) e)+ -> Acc (Segments i)+ -> Acc (Array (sh:.Int) e)+postscanrSeg f e vec seg+ = map (f e)+ $ scanr1Seg f vec seg+++-- Segmented scan helpers+-- ----------------------++-- | Compute head flags vector from segment vector for left-scans.+--+-- The vector will be full of zeros in the body of a segment, and non-zero+-- otherwise. The "flag" value, if greater than one, indicates that several+-- empty segments are represented by this single flag entry. This is additional+-- data is used by exclusive segmented scan.+--+mkHeadFlags+ :: (Integral i, FromIntegral i Int)+ => Acc (Segments i)+ -> Acc (Segments i)+mkHeadFlags seg+ = init+ $ permute (+) zeros (\ix -> Just_ (index1' (offset ! ix))) ones+ where+ T2 offset len = scanl' (+) 0 seg+ zeros = fill (index1' $ the len + 1) 0+ ones = fill (index1 $ size offset) 1++-- | Compute tail flags vector from segment vector for right-scans. That+-- is, the flag is placed at the last place in each segment.+--+mkTailFlags+ :: (Integral i, FromIntegral i Int)+ => Acc (Segments i)+ -> Acc (Segments i)+mkTailFlags seg+ = init+ $ permute (+) zeros (\ix -> Just_ (index1' (the len - 1 - offset ! ix))) ones+ where+ T2 offset len = scanr' (+) 0 seg+ zeros = fill (index1' $ the len + 1) 0+ ones = fill (index1 $ size offset) 1++-- | Construct a segmented version of a function from a non-segmented+-- version. The segmented apply operates on a head-flag value tuple, and+-- follows the procedure of Sengupta et. al.+--+segmentedL+ :: (Elt e, Num i, Bits i)+ => (Exp e -> Exp e -> Exp e)+ -> (Exp (i, e) -> Exp (i, e) -> Exp (i, e))+segmentedL f (T2 aF aV) (T2 bF bV) =+ T2 (aF .|. bF)+ (bF /= 0 ? (bV, f aV bV))++segmentedR+ :: (Elt e, Num i, Bits i)+ => (Exp e -> Exp e -> Exp e)+ -> (Exp (i, e) -> Exp (i, e) -> Exp (i, e))+segmentedR f y x = segmentedL (flip f) x y++-- | Index construction and destruction generalised to integral types.+--+-- We generalise the segment descriptor to integral types because some+-- architectures, such as GPUs, have poor performance for 64-bit types. So,+-- there is a tension between performance and requiring 64-bit indices for some+-- applications, and we would not like to restrict ourselves to either one.+--+-- As we don't yet support non-Int dimensions in shapes, we will need to convert+-- back to concrete Int. However, don't put these generalised forms into the+-- base library, because it results in too many ambiguity errors.+--+index1' :: (Integral i, FromIntegral i Int) => Exp i -> Exp DIM1+index1' i = lift (Z :. fromIntegral i)+++-- Reshaping of arrays+-- -------------------++-- | Flatten the given array of arbitrary dimension into a one-dimensional+-- vector. As with 'reshape', this operation performs no work.+--+flatten :: forall sh e. (Shape sh, Elt e) => Acc (Array sh e) -> Acc (Vector e)+flatten a+ | Just Refl <- matchShapeType @sh @DIM1+ = a+flatten a+ = reshape (I1 (size a)) a+++-- Enumeration and filling+-- -----------------------++-- | Create an array where all elements are the same value.+--+-- >>> run $ fill (constant (Z:.10)) 0 :: Vector Float+-- Vector (Z :. 10) [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0]+--+fill :: (Shape sh, Elt e) => Exp sh -> Exp e -> Acc (Array sh e)+fill sh c = generate sh (const c)++-- | Create an array of the given shape containing the values @x@, @x+1@, etc.+-- (in row-major order).+--+-- >>> run $ enumFromN (constant (Z:.5:.10)) 0 :: Matrix Int+-- Matrix (Z :. 5 :. 10)+-- [ 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]+--+enumFromN+ :: (Shape sh, Num e, FromIntegral Int e)+ => Exp sh+ -> Exp e+ -> Acc (Array sh e)+enumFromN sh x = enumFromStepN sh x 1++-- | Create an array of the given shape containing the values @x@, @x+y@,+-- @x+y+y@ etc. (in row-major order).+--+-- >>> run $ enumFromStepN (constant (Z:.5:.10)) 0 0.5 :: Matrix Float+-- Matrix (Z :. 5 :. 10)+-- [ 0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5,+-- 5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5,+-- 10.0, 10.5, 11.0, 11.5, 12.0, 12.5, 13.0, 13.5, 14.0, 14.5,+-- 15.0, 15.5, 16.0, 16.5, 17.0, 17.5, 18.0, 18.5, 19.0, 19.5,+-- 20.0, 20.5, 21.0, 21.5, 22.0, 22.5, 23.0, 23.5, 24.0, 24.5]+--+enumFromStepN+ :: (Shape sh, Num e, FromIntegral Int e)+ => Exp sh+ -> Exp e -- ^ x: start+ -> Exp e -- ^ y: step+ -> Acc (Array sh e)+enumFromStepN sh x y+ = reshape sh+ $ generate (I1 (shapeSize sh))+ (\ix -> (fromIntegral (unindex1 ix :: Exp Int) * y) + x)++-- Concatenation+-- -------------++-- | Concatenate innermost component of two arrays. The extent of the lower+-- dimensional component is the intersection of the two arrays.+--+-- >>> let m1 = fromList (Z:.5:.10) [0..] :: Matrix Int+-- >>> m1+-- Matrix (Z :. 5 :. 10)+-- [ 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]+--+-- >>> let m2 = fromList (Z:.10:.3) [0..] :: Matrix Int+-- >>> m2+-- Matrix (Z :. 10 :. 3)+-- [ 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]+--+-- >>> run $ use m1 ++ use m2+-- Matrix (Z :. 5 :. 13)+-- [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2,+-- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 3, 4, 5,+-- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 6, 7, 8,+-- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 9, 10, 11,+-- 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 12, 13, 14]+--+infixr 5 +++(++) :: (Shape sh, Elt e)+ => Acc (Array (sh :. Int) e)+ -> Acc (Array (sh :. Int) e)+ -> Acc (Array (sh :. Int) e)+(++) = concatOn _1+++-- | Generalised version of '(++)' where the argument 'Lens'' specifies which+-- dimension to concatenate along.+--+-- Appropriate lenses are available from <https://hackage.haskell.org/package/lens-accelerate lens-accelerate>.+--+-- >>> let m1 = fromList (Z:.5:.10) [0..] :: Matrix Int+-- >>> m1+-- Matrix (Z :. 5 :. 10)+-- [ 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]+--+-- >>> let m2 = fromList (Z:.10:.5) [0..] :: Matrix Int+-- >>> m2+-- Matrix (Z :. 10 :. 5)+-- [ 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]+--+-- >>> run $ concatOn _1 (use m1) (use m2)+-- Matrix (Z :. 5 :. 15)+-- [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4,+-- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 5, 6, 7, 8, 9,+-- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 10, 11, 12, 13, 14,+-- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 15, 16, 17, 18, 19,+-- 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 20, 21, 22, 23, 24]+--+-- >>> run $ concatOn _2 (use m1) (use m2)+-- Matrix (Z :. 15 :. 5)+-- [ 0, 1, 2, 3, 4,+-- 10, 11, 12, 13, 14,+-- 20, 21, 22, 23, 24,+-- 30, 31, 32, 33, 34,+-- 40, 41, 42, 43, 44,+-- 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]+--+concatOn+ :: (Shape sh, Elt e)+ => Lens' (Exp sh) (Exp Int)+ -> Acc (Array sh e)+ -> Acc (Array sh e)+ -> Acc (Array sh e)+concatOn dim xs ys =+ let+ shx = shape xs+ shy = shape ys+ m = shx ^. dim+ n = shy ^. dim+ shx' = shx & dim .~ m+n+ shy' = shy & dim .~ m+n+ in+ generate (shx' `intersect` shy')+ (\ix -> let i = ix ^. dim in+ if i < m then xs ! ix+ else ys ! (ix & dim -~ m))++-- TLM: If we have something like (concat . split) then the source array will+-- have two use sites, but is actually safe (and better) to inline.+++-- Filtering+-- ---------++-- | Drop elements that do not satisfy the predicate. Returns the elements which+-- pass the predicate, together with a segment descriptor indicating how many+-- elements along each outer dimension were valid.+--+-- >>> let vec = fromList (Z :. 10) [1..10] :: Vector Int+-- >>> vec+-- Vector (Z :. 10) [1,2,3,4,5,6,7,8,9,10]+--+-- >>> run $ filter even (use vec)+-- (Vector (Z :. 5) [2,4,6,8,10],Scalar Z [5])+--+-- >>> let mat = fromList (Z :. 4 :. 10) [1,2,3,4,5,6,7,8,9,10,1,1,1,1,1,2,2,2,2,2,2,4,6,8,10,12,14,16,18,20,1,3,5,7,9,11,13,15,17,19] :: Matrix Int+-- >>> mat+-- Matrix (Z :. 4 :. 10)+-- [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,+-- 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,+-- 2, 4, 6, 8, 10, 12, 14, 16, 18, 20,+-- 1, 3, 5, 7, 9, 11, 13, 15, 17, 19]+--+-- >>> run $ filter odd (use mat)+-- (Vector (Z :. 20) [1,3,5,7,9,1,1,1,1,1,1,3,5,7,9,11,13,15,17,19],Vector (Z :. 4) [5,5,0,10])+--+filter :: (Shape sh, Elt e)+ => (Exp e -> Exp Bool)+ -> Acc (Array (sh:.Int) e)+ -> Acc (Vector e, Array sh Int)+filter p arr = compact (map p arr) arr+{-# NOINLINE filter #-}+{-# RULES+ "ACC filter/filter" forall f g arr.+ filter f (afst (filter g arr)) = filter (\x -> g x && f x) arr+ #-}+++-- | As 'filter', but with separate arrays for the data elements and the+-- flags indicating which elements of that array should be kept.+--+compact :: forall sh e. (Shape sh, Elt e)+ => Acc (Array (sh:.Int) Bool)+ -> Acc (Array (sh:.Int) e)+ -> Acc (Vector e, Array sh Int)+compact keep arr+ -- Optimise 1-dimensional arrays, where we can avoid additional computations+ -- for the offset indices.+ | Just Refl <- matchShapeType @sh @Z+ = let+ T2 target len = scanl' (+) 0 (map boolToInt keep)+ prj ix = if keep!ix+ then Just_ (I1 (target!ix))+ else Nothing_+ dummy = fill (I1 (the len)) undef+ result = permute const dummy prj arr+ in+ if null arr+ then T2 emptyArray (fill Z_ 0)+ else+ if the len == unindex1 (shape arr)+ then T2 arr len+ else T2 result len++compact keep arr+ = let+ sz = indexTail (shape arr)+ T2 target len = scanl' (+) 0 (map boolToInt keep)+ T2 offset valid = scanl' (+) 0 (flatten len)+ prj ix = if keep!ix+ then Just_ (I1 (offset !! (toIndex sz (indexTail ix)) + target!ix))+ else Nothing_+ dummy = fill (I1 (the valid)) undef+ result = permute const dummy prj arr+ in+ if null arr+ then T2 emptyArray (fill sz 0)+ else T2 result len+++-- Gather operations+-- -----------------++-- | Gather elements from a source array by reading values at the given indices.+--+-- >>> let input = fromList (Z:.9) [1,9,6,4,4,2,0,1,2] :: Vector Int+-- >>> let from = fromList (Z:.6) [1,3,7,2,5,3] :: Vector Int+-- >>> run $ gather (use from) (use input)+-- Vector (Z :. 6) [9,4,1,6,2,4]+--+gather+ :: (Shape sh, Elt e)+ => Acc (Array sh Int) -- ^ index of source at each index to gather+ -> Acc (Vector e) -- ^ source values+ -> Acc (Array sh e)+gather indices input = map (input !!) indices+ -- TLM NOTES:+ -- * (!!) has potential for later optimisation+ -- * We needn't fix the source array to Vector, but this matches the+ -- intuition that 'Int' ~ 'DIM1'.+++-- | Conditionally copy elements from source array to destination array+-- according to an index mapping.+--+-- In addition, the 'mask' vector and associated predication function specifies+-- whether the element is copied or a default value is used instead.+--+-- >>> let defaults = fromList (Z :. 6) [6,6,6,6,6,6] :: Vector Float+-- >>> let from = fromList (Z :. 6) [1,3,7,2,5,3] :: Vector Int+-- >>> let mask = fromList (Z :. 6) [3,4,9,2,7,5] :: Vector Int+-- >>> let input = fromList (Z :. 9) [1,9,6,4,4,2,0,1,2] :: Vector Float+-- >>> run $ gatherIf (use from) (use mask) (> 4) (use defaults) (use input)+-- Vector (Z :. 6) [6.0,6.0,1.0,6.0,2.0,4.0]+--+gatherIf+ :: (Elt a, Elt b)+ => Acc (Vector Int) -- ^ source indices to gather from+ -> Acc (Vector a) -- ^ mask vector+ -> (Exp a -> Exp Bool) -- ^ predicate function+ -> Acc (Vector b) -- ^ default values+ -> Acc (Vector b) -- ^ source values+ -> Acc (Vector b)+gatherIf from maskV pred defaults input = zipWith zf pf gatheredV+ where+ zf p g = p ? (unlift g)+ gatheredV = zip (gather from input) defaults+ pf = map pred maskV+++-- Scatter operations+-- ------------------++-- | Overwrite elements of the destination by scattering the values of the+-- source array according to the given index mapping.+--+-- Note that if the destination index appears more than once in the mapping the+-- result is undefined.+--+-- >>> let to = fromList (Z :. 6) [1,3,7,2,5,8] :: Vector Int+-- >>> let input = fromList (Z :. 7) [1,9,6,4,4,2,5] :: Vector Int+-- >>> run $ scatter (use to) (fill (constant (Z:.10)) 0) (use input)+-- Vector (Z :. 10) [0,1,4,9,0,4,0,6,2,0]+--+scatter+ :: Elt e+ => Acc (Vector Int) -- ^ destination indices to scatter into+ -> Acc (Vector e) -- ^ default values+ -> Acc (Vector e) -- ^ source values+ -> Acc (Vector e)+scatter to defaults input = permute const defaults pf input'+ where+ pf ix = Just_ (I1 (to ! ix))+ input' = backpermute (shape to `intersect` shape input) id input+++-- | Conditionally overwrite elements of the destination by scattering values of+-- the source array according to a given index mapping, whenever the masking+-- function resolves to 'True'.+--+-- Note that if the destination index appears more than once in the mapping the+-- result is undefined.+--+-- >>> let to = fromList (Z :. 6) [1,3,7,2,5,8] :: Vector Int+-- >>> let mask = fromList (Z :. 6) [3,4,9,2,7,5] :: Vector Int+-- >>> let input = fromList (Z :. 7) [1,9,6,4,4,2,5] :: Vector Int+-- >>> run $ scatterIf (use to) (use mask) (> 4) (fill (constant (Z:.10)) 0) (use input)+-- Vector (Z :. 10) [0,0,0,0,0,4,0,6,2,0]+--+scatterIf+ :: (Elt a, Elt b)+ => Acc (Vector Int) -- ^ destination indices to scatter into+ -> Acc (Vector a) -- ^ mask vector+ -> (Exp a -> Exp Bool) -- ^ predicate function+ -> Acc (Vector b) -- ^ default values+ -> Acc (Vector b) -- ^ source values+ -> Acc (Vector b)+scatterIf to maskV pred defaults input = permute const defaults pf input'+ where+ input' = backpermute (shape to `intersect` shape input) id input+ pf ix = if pred (maskV ! ix)+ then Just_ (I1 (to ! ix))+ else Nothing_+++-- Permutations+-- ------------++-- | Reverse the elements of a vector.+--+reverse :: Elt e => Acc (Vector e) -> Acc (Vector e)+reverse = reverseOn _1++-- | Transpose the rows and columns of a matrix.+--+transpose :: Elt e => Acc (Array DIM2 e) -> Acc (Array DIM2 e)+transpose = transposeOn _1 _2+++-- | Generalised version of 'reverse' where the argument 'Lens'' specifies which+-- dimension to reverse.+--+-- Appropriate lenses are available from <https://hackage.haskell.org/package/lens-accelerate lens-accelerate>.+--+-- >>> let mat = fromList (Z:.5:.10) [0..] :: Matrix Int+-- >>> mat+-- Matrix (Z :. 5 :. 10)+-- [ 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]+--+-- >>> run $ reverseOn _1 (use mat)+-- Matrix (Z :. 5 :. 10)+-- [ 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,+-- 19, 18, 17, 16, 15, 14, 13, 12, 11, 10,+-- 29, 28, 27, 26, 25, 24, 23, 22, 21, 20,+-- 39, 38, 37, 36, 35, 34, 33, 32, 31, 30,+-- 49, 48, 47, 46, 45, 44, 43, 42, 41, 40]+--+-- >>> run $ reverseOn _2 (use mat)+-- Matrix (Z :. 5 :. 10)+-- [ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,+-- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,+-- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,+-- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,+-- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]+--+-- @since 1.2.0.0+--+reverseOn+ :: (Shape sh, Elt e)+ => Lens' (Exp sh) (Exp Int)+ -> Acc (Array sh e)+ -> Acc (Array sh e)+reverseOn dim xs =+ let+ sh = shape xs+ n = sh ^. dim+ in+ backpermute sh (over dim $ \i -> n - i - 1) xs++-- | Generalised version of 'transpose' where the argument 'Lens''s specify+-- which two dimensions to transpose.+--+-- Appropriate lenses are available from <https://hackage.haskell.org/package/lens-accelerate lens-accelerate>.+--+-- >>> let mat = fromList (Z:.5:.10) [0..] :: Matrix Int+-- >>> mat+-- Matrix (Z :. 5 :. 10)+-- [ 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]+--+-- >>> run $ transposeOn _1 _2 (use mat)+-- Matrix (Z :. 10 :. 5)+-- [ 0, 10, 20, 30, 40,+-- 1, 11, 21, 31, 41,+-- 2, 12, 22, 32, 42,+-- 3, 13, 23, 33, 43,+-- 4, 14, 24, 34, 44,+-- 5, 15, 25, 35, 45,+-- 6, 16, 26, 36, 46,+-- 7, 17, 27, 37, 47,+-- 8, 18, 28, 38, 48,+-- 9, 19, 29, 39, 49]+--+-- >>> let box = fromList (Z:.2:.3:.5) [0..] :: Array DIM3 Int+-- >>> box+-- Array (Z :. 2 :. 3 :. 5) [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]+--+-- >>> run $ transposeOn _1 _2 (use box)+-- Array (Z :. 2 :. 5 :. 3) [0,5,10,1,6,11,2,7,12,3,8,13,4,9,14,15,20,25,16,21,26,17,22,27,18,23,28,19,24,29]+--+-- >>> run $ transposeOn _2 _3 (use box)+-- Array (Z :. 3 :. 2 :. 5) [0,1,2,3,4,15,16,17,18,19,5,6,7,8,9,20,21,22,23,24,10,11,12,13,14,25,26,27,28,29]+--+-- >>> run $ transposeOn _1 _3 (use box)+-- Array (Z :. 5 :. 3 :. 2) [0,15,5,20,10,25,1,16,6,21,11,26,2,17,7,22,12,27,3,18,8,23,13,28,4,19,9,24,14,29]+--+-- @since 1.2.0.0+--+transposeOn+ :: (Shape sh, Elt e)+ => Lens' (Exp sh) (Exp Int)+ -> Lens' (Exp sh) (Exp Int)+ -> Acc (Array sh e)+ -> Acc (Array sh e)+transposeOn dim1 dim2 xs =+ let+ swap ix = ix & dim2 .~ ix ^. dim1+ & dim1 .~ ix ^. dim2+ in+ backpermute (swap (shape xs)) swap xs+++-- Extracting sub-vectors+-- ----------------------++-- | Yield the first @n@ elements in the innermost dimension of the array (plus+-- all lower dimensional elements).+--+-- >>> let mat = fromList (Z:.5:.10) [0..] :: Matrix Int+-- >>> mat+-- Matrix (Z :. 5 :. 10)+-- [ 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]+--+-- >>> run $ take 5 (use mat)+-- Matrix (Z :. 5 :. 5)+-- [ 0, 1, 2, 3, 4,+-- 10, 11, 12, 13, 14,+-- 20, 21, 22, 23, 24,+-- 30, 31, 32, 33, 34,+-- 40, 41, 42, 43, 44]+--+take :: (Shape sh, Elt e)+ => Exp Int+ -> Acc (Array (sh :. Int) e)+ -> Acc (Array (sh :. Int) e)+take = takeOn _1+++-- | Yield all but the first @n@ elements along the innermost dimension of the+-- array (plus all lower dimensional elements).+--+-- >>> let mat = fromList (Z:.5:.10) [0..] :: Matrix Int+-- >>> mat+-- Matrix (Z :. 5 :. 10)+-- [ 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]+--+-- >>> run $ drop 7 (use mat)+-- Matrix (Z :. 5 :. 3)+-- [ 7, 8, 9,+-- 17, 18, 19,+-- 27, 28, 29,+-- 37, 38, 39,+-- 47, 48, 49]+--+drop :: (Shape sh, Elt e)+ => Exp Int+ -> Acc (Array (sh :. Int) e)+ -> Acc (Array (sh :. Int) e)+drop = dropOn _1+++-- | Yield all but the elements in the last index of the innermost dimension.+--+-- >>> let mat = fromList (Z:.5:.10) [0..] :: Matrix Int+-- >>> mat+-- Matrix (Z :. 5 :. 10)+-- [ 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]+--+-- >>> run $ init (use mat)+-- Matrix (Z :. 5 :. 9)+-- [ 0, 1, 2, 3, 4, 5, 6, 7, 8,+-- 10, 11, 12, 13, 14, 15, 16, 17, 18,+-- 20, 21, 22, 23, 24, 25, 26, 27, 28,+-- 30, 31, 32, 33, 34, 35, 36, 37, 38,+-- 40, 41, 42, 43, 44, 45, 46, 47, 48]+--+init :: (Shape sh, Elt e)+ => Acc (Array (sh :. Int) e)+ -> Acc (Array (sh :. Int) e)+init = initOn _1+++-- | Yield all but the first element along the innermost dimension of an array.+-- The innermost dimension must not be empty.+--+-- >>> let mat = fromList (Z:.5:.10) [0..] :: Matrix Int+-- >>> mat+-- Matrix (Z :. 5 :. 10)+-- [ 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]+--+-- >>> run $ tail (use mat)+-- Matrix (Z :. 5 :. 9)+-- [ 1, 2, 3, 4, 5, 6, 7, 8, 9,+-- 11, 12, 13, 14, 15, 16, 17, 18, 19,+-- 21, 22, 23, 24, 25, 26, 27, 28, 29,+-- 31, 32, 33, 34, 35, 36, 37, 38, 39,+-- 41, 42, 43, 44, 45, 46, 47, 48, 49]+--+tail :: (Shape sh, Elt e)+ => Acc (Array (sh :. Int) e)+ -> Acc (Array (sh :. Int) e)+tail = tailOn _1+++-- | Yield a slit (slice) of the innermost indices of an array. Denotationally,+-- we have:+--+-- > slit i n = take n . drop i+--+slit :: (Shape sh, Elt e)+ => Exp Int -- ^ starting index+ -> Exp Int -- ^ length+ -> Acc (Array (sh :. Int) e)+ -> Acc (Array (sh :. Int) e)+slit = slitOn _1+++-- | Generalised version of 'init' where the argument 'Lens'' specifies which+-- dimension to operate over.+--+-- Appropriate lenses are available from <https://hackage.haskell.org/package/lens-accelerate lens-accelerate>.+--+-- @since 1.2.0.0+--+initOn+ :: (Shape sh, Elt e)+ => Lens' (Exp sh) (Exp Int)+ -> Acc (Array sh e)+ -> Acc (Array sh e)+initOn dim xs =+ let+ sh = shape xs+ sh' = over dim (\i -> 0 `max` (i-1)) sh+ in+ backpermute sh' id xs+++-- | Generalised version of 'tail' where the argument 'Lens'' specifies which+-- dimension to operate over.+--+-- Appropriate lenses are available from <https://hackage.haskell.org/package/lens-accelerate lens-accelerate>.+--+-- @since 1.2.0.0+--+tailOn+ :: (Shape sh, Elt e)+ => Lens' (Exp sh) (Exp Int)+ -> Acc (Array sh e)+ -> Acc (Array sh e)+tailOn dim xs =+ let+ sh = shape xs+ sh' = over dim (\i -> 0 `max` (i-1)) sh+ in+ backpermute sh' (& dim +~ 1) xs+++-- | Generalised version of 'take' where the argument 'Lens'' specifies which+-- dimension to operate over.+--+-- Appropriate lenses are available from <https://hackage.haskell.org/package/lens-accelerate lens-accelerate>.+--+-- @since 1.2.0.0+--+takeOn+ :: (Shape sh, Elt e)+ => Lens' (Exp sh) (Exp Int)+ -> Exp Int+ -> Acc (Array sh e)+ -> Acc (Array sh e)+takeOn dim n xs =+ let+ sh = shape xs+ m = sh ^. dim+ in+ backpermute (sh & dim .~ min m n) id xs+++-- | Generalised version of 'drop' where the argument 'Lens'' specifies which+-- dimension to operate over.+--+-- Appropriate lenses are available from <https://hackage.haskell.org/package/lens-accelerate lens-accelerate>.+--+-- @since 1.2.0.0+--+dropOn+ :: (Shape sh, Elt e)+ => Lens' (Exp sh) (Exp Int)+ -> Exp Int+ -> Acc (Array sh e)+ -> Acc (Array sh e)+dropOn dim n xs =+ let+ sh = shape xs+ m = sh ^. dim+ n' = max 0 n+ in+ backpermute (sh & dim .~ max 0 (m - n')) (& dim +~ n') xs++-- Note: [embedding constants in take & drop]+--+-- Previously the 'take' and 'drop functions prevented the value of the+-- take/drop amount from being embedded directly in the generated code. This was+-- done by writing the value into a scalar array and reading that value out,+-- rather than using it directly. Although that is better from a code+-- cache/reuse standpoint, I've now removed this as it prevents the user from+-- specialising their code, and in a real program this extra indirection is+-- probably not necessary anyway.+--++-- | Generalised version of 'drop' where the argument 'Lens'' specifies which+-- dimension to operate over.+--+-- Appropriate lenses are available from <https://hackage.haskell.org/package/lens-accelerate lens-accelerate>.+--+-- @since 1.2.0.0+--+slitOn+ :: (Shape sh, Elt e)+ => Lens' (Exp sh) (Exp Int)+ -> Exp Int -- ^ starting index+ -> Exp Int -- ^ length+ -> Acc (Array sh e)+ -> Acc (Array sh e)+slitOn dim i n = takeOn dim n . dropOn dim i+++-- Controlling execution+-- ---------------------++-- | Force an array expression to be evaluated, preventing it from fusing with+-- other operations. Forcing operations to be computed to memory, rather than+-- being fused into their consuming function, can sometimes improve performance.+-- For example, computing a matrix 'transpose' could provide better memory+-- locality for the subsequent operation. Preventing fusion to split large+-- operations into several simpler steps could also help by reducing register+-- pressure.+--+-- Preventing fusion also means that the individual operations are available to+-- be executed concurrently with other kernels. In particular, consider using+-- this if you have a series of operations that are compute bound rather than+-- memory bound.+--+-- Here is the synthetic example:+--+-- > loop :: Exp Int -> Exp Int+-- > loop ticks =+-- > let clockRate = 900000 -- kHz+-- > in while (\i -> i < clockRate * ticks) (+1) 0+-- >+-- > test :: Acc (Vector Int)+-- > test =+-- > zip3+-- > (compute $ map loop (use $ fromList (Z:.1) [10]))+-- > (compute $ map loop (use $ fromList (Z:.1) [10]))+-- > (compute $ map loop (use $ fromList (Z:.1) [10]))+-- >+--+-- Without the use of 'compute', the operations are fused together and the three+-- long-running loops are executed sequentially in a single kernel. Instead, the+-- individual operations can now be executed concurrently, potentially reducing+-- overall runtime.+--+compute :: Arrays a => Acc a -> Acc a+compute = id >-> id+++-- Flow control+-- ------------++-- | Infix version of 'acond'. If the predicate evaluates to 'True', the first+-- component of the tuple is returned, else the second.+--+-- Enabling the @RebindableSyntax@ extension will allow you to use the standard+-- if-then-else syntax instead.+--+infix 0 ?|+(?|) :: Arrays a => Exp Bool -> (Acc a, Acc a) -> Acc a+c ?| (t, e) = acond c t e++-- | An infix version of 'cond'. If the predicate evaluates to 'True', the first+-- component of the tuple is returned, else the second.+--+-- Enabling the @RebindableSyntax@ extension will allow you to use the standard+-- if-then-else syntax instead.+--+infix 0 ?+(?) :: Elt t => Exp Bool -> (Exp t, Exp t) -> Exp t+c ? (t, e) = cond c t e++-- | For use with @-XRebindableSyntax@, this class provides 'ifThenElse'+-- for host and embedded scalar and array types.+--+class IfThenElse bool a where+ ifThenElse :: bool -> a -> a -> a++instance IfThenElse Bool a where+ ifThenElse p t e =+ case p of+ True -> t+ False -> e++instance (Elt a, b ~ Bool) => IfThenElse (Exp b) (Exp a) where+ ifThenElse = cond++instance (Arrays a, b ~ Bool) => IfThenElse (Exp b) (Acc a) where+ ifThenElse = acond+++-- | The 'match' operation is the core operation which enables embedded+-- pattern matching. It is applied to an n-ary scalar function, and+-- generates the necessary case-statements in the embedded code for each+-- argument. For example, given the function:+--+-- > example1 :: Exp (Maybe Bool) -> Exp Int+-- > example1 Nothing_ = 0+-- > example1 (Just_ False_) = 1+-- > example1 (Just_ True_) = 2+--+-- In order to use this function it must be applied to the 'match'+-- operator:+--+-- > match example1+--+-- Using the infix-flip operator ('Data.Function.&'), we can also write+-- case statements inline. For example, instead of this:+--+-- > example2 x = case f x of+-- > Nothing_ -> ... -- error: embedded pattern synonym...+-- > Just_ y -> ... -- ...used outside of 'match' context+--+-- This can be written instead as:+--+-- > example3 x = f x & match \case+-- > Nothing_ -> ...+-- > Just_ y -> ...+--+-- And utilising the @LambdaCase@ and @BlockArguments@ syntactic extensions.+--+-- The Template Haskell splice 'Data.Array.Accelerate.mkPattern' (or+-- 'Data.Array.Accelerate.mkPatterns') can be used to generate the pattern+-- synonyms for a given Haskell'98 sum or product data type. For example:+--+-- > data Option a = None | Some a+-- > deriving (Generic, Elt)+-- >+-- > mkPattern ''Option+--+-- Which can then be used such as:+--+-- > isNone :: Elt a => Exp (Option a) -> Exp Bool+-- > isNone = match \case+-- > None_ -> True_+-- > Some_{} -> False_+--+-- @since 1.3.0.0+--+match :: Matching f => f -> f+match f = mkFun (mkMatch f) id++data Args f where+ (:->) :: Exp a -> Args b -> Args (Exp a -> b)+ Result :: Args (Exp a)++class Matching a where+ type ResultT a+ mkMatch :: a -> Args a -> Exp (ResultT a)+ mkFun :: (Args f -> Exp (ResultT a))+ -> (Args a -> Args f)+ -> a++instance Elt a => Matching (Exp a) where+ type ResultT (Exp a) = a++ mkFun f k = f (k Result)+ mkMatch (Exp e) Result =+ case e of+ SmartExp (Match _ x) -> Exp x+ _ -> Exp e++instance (Elt e, Matching r) => Matching (Exp e -> r) where+ type ResultT (Exp e -> r) = ResultT r++ mkFun f k x = mkFun f (\xs -> k (x :-> xs))+ mkMatch f (x@(Exp p) :-> xs) =+ case p of+ -- This first case is used when we have nested calls to 'match'+ SmartExp Match{} -> mkMatch (f x) xs++ -- If there is only a single alternative, we can elide the case+ -- statement at this point. This can occur when pattern matching on+ -- product types.+ _ -> case rhs of+ [(_,r)] -> Exp r+ _ -> Exp (SmartExp (Case p rhs))+ where+ rhs = [ (tag, unExp (mkMatch (f x') xs))+ | tag <- tagsR @e+ , let x' = Exp (SmartExp (Match tag p)) ]+++-- Scalar iteration+-- ----------------++-- | Repeatedly apply a function a fixed number of times+--+iterate+ :: Elt a+ => Exp Int+ -> (Exp a -> Exp a)+ -> Exp a+ -> Exp a+iterate n f z+ = let step (T2 i acc) = T2 (i+1) (f acc)+ in snd $ while (\v -> fst v < n) step (T2 0 z)+++-- Scalar bulk operations+-- ----------------------++-- | Reduce along an innermost slice of an array /sequentially/, by applying a+-- binary operator to a starting value and the array from left to right.+--+sfoldl :: (Shape sh, Elt a, Elt b)+ => (Exp a -> Exp b -> Exp a)+ -> Exp a+ -> Exp sh+ -> Acc (Array (sh :. Int) b)+ -> Exp a+sfoldl f z ix xs+ = let n = indexHead (shape xs)+ step (T2 i acc) = T2 (i+1) (acc `f` (xs ! (ix ::. i)))+ in snd $ while (\v -> fst v < n) step (T2 0 z)+++-- Tuples+-- ------++-- |Extract the first component of a scalar pair.+--+fst :: (Elt a, Elt b) => Exp (a, b) -> Exp a+fst (T2 a _) = a++-- |Extract the first component of an array pair.+{-# NOINLINE[1] afst #-}+afst :: (Arrays a, Arrays b) => Acc (a, b) -> Acc a+afst (T2 a _) = a++-- |Extract the second component of a scalar pair.+--+snd :: (Elt a, Elt b) => Exp (a, b) -> Exp b+snd (T2 _ b) = b++-- | Extract the second component of an array pair+asnd :: (Arrays a, Arrays b) => Acc (a, b) -> Acc b+asnd (T2 _ b) = b++-- |Converts an uncurried function to a curried function.+--+curry :: Lift f (f a, f b) => (f (Plain (f a), Plain (f b)) -> f c) -> f a -> f b -> f c+curry f x y = f (lift (x, y))++-- |Converts a curried function to a function on pairs.+--+uncurry :: Unlift f (f a, f b) => (f a -> f b -> f c) -> f (Plain (f a), Plain (f b)) -> f c+uncurry f t = let (x, y) = unlift t in f x y+++-- Shapes and indices+-- ------------------++-- | The one index for a rank-0 array.+--+index0 :: Exp Z+index0 = lift Z++-- | Turn an 'Int' expression into a rank-1 indexing expression.+--+index1 :: Elt i => Exp i -> Exp (Z :. i)+index1 i = lift (Z :. i)++-- | Turn a rank-1 indexing expression into an 'Int' expression.+--+unindex1 :: Elt i => Exp (Z :. i) -> Exp i+unindex1 ix = let Z :. i = unlift ix in i++-- | Creates a rank-2 index from two Exp Int`s+--+index2+ :: Elt i+ => Exp i+ -> Exp i+ -> Exp (Z :. i :. i)+index2 i j = lift (Z :. i :. j)++-- | Destructs a rank-2 index to an Exp tuple of two Int`s.+--+unindex2+ :: Elt i+ => Exp (Z :. i :. i)+ -> Exp (i, i)+unindex2 (Z_ ::. i ::. j) = T2 i j++-- | Create a rank-3 index from three Exp Int`s+--+index3+ :: Elt i+ => Exp i+ -> Exp i+ -> Exp i+ -> Exp (Z :. i :. i :. i)+index3 k j i = Z_ ::. k ::. j ::. i++-- | Destruct a rank-3 index into an Exp tuple of Int`s+unindex3+ :: Elt i+ => Exp (Z :. i :. i :. i)+ -> Exp (i, i, i)+unindex3 (Z_ ::. k ::. j ::. i) = T3 k j i+++-- Array operations with a scalar result+-- -------------------------------------++-- | Extract the element of a singleton array.+--+-- > the xs == xs ! Z+--+the :: Elt e => Acc (Scalar e) -> Exp e+the = (! index0)++-- | Test whether an array is empty.+--+null :: (Shape sh, Elt e) => Acc (Array sh e) -> Exp Bool+null arr = size arr == 0++-- | Get the length of a vector.+--+length :: Elt e => Acc (Vector e) -> Exp Int+length = unindex1 . shape+++-- Operations to facilitate irregular data parallelism+-- ---------------------------------------------------++-- | A recipe for generating flattened implementations of some kinds of+-- irregular nested parallelism. Given two functions that:+--+-- (1) for each source element, determine how many target+-- elements it expands into; and+--+-- (2) computes a particular target element based on a source element and+-- the target element index associated with the source+--+-- The following example implements the Sieve of Eratosthenes,+-- a contraction style algorithm which first computes all primes less than+-- /sqrt n/, then uses this intermediate result to sieve away all numbers+-- in the range /[sqrt n .. n]/. The 'expand' function is used to calculate+-- and flatten the sieves. For each prime /p/ and upper limit /c2/,+-- function /sz/ computes the number of contributions in the sieve. Then,+-- for each prime /p/ and sieve index /i/, the function /get/ computes the+-- sieve contribution. The final step produces all the new primes in the+-- interval /[c1 .. c2]/.+--+-- >>> :{+-- primes :: Exp Int -> Acc (Vector Int)+-- primes n = afst loop+-- where+-- c0 = unit 2+-- a0 = use $ fromList (Z:.0) []+-- limit = truncate (sqrt (fromIntegral (n+1) :: Exp Float))+-- loop = awhile+-- (\(T2 _ c) -> map (< n+1) c)+-- (\(T2 old c) ->+-- let c1 = the c+-- c2 = c1 < limit ? ( c1*c1, n+1 )+-- --+-- sieves =+-- let sz p = (c2 - p) `quot` p+-- get p i = (2+i)*p+-- in+-- map (subtract c1) (expand sz get old)+-- --+-- new =+-- let m = c2-c1+-- put i = let s = sieves ! i+-- in s >= 0 && s < m ? (Just_ (I1 s), Nothing_)+-- in+-- afst+-- $ filter (> 0)+-- $ permute const (enumFromN (I1 m) c1) put+-- $ fill (shape sieves) 0+-- in+-- T2 (old ++ new) (unit c2))+-- (T2 a0 c0)+-- :}+--+-- >>> run $ primes 100+-- Vector (Z :. 25) [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]+--+-- Inspired by the paper /Data-Parallel Flattening by Expansion/ by Martin+-- Elsman, Troels Henriksen, and Niels Gustav Westphal Serup, ARRAY'19.+--+-- @since 1.3.0.0+--+expand :: (Elt a, Elt b)+ => (Exp a -> Exp Int)+ -> (Exp a -> Exp Int -> Exp b)+ -> Acc (Vector a)+ -> Acc (Vector b)+expand f g xs =+ let+ szs = map f xs+ T2 offset len = scanl' (+) 0 szs+ m = the len+ in+ if length xs == 0 || m == 0+ then use $ fromList (Z:.0) []+ else+ let+ n = m + 1+ put ix = Just_ (I1 (offset ! ix))++ head_flags :: Acc (Vector Int)+ head_flags = permute const (fill (I1 n) 0) put (fill (shape szs) 1)++ idxs = map (subtract 1)+ $ map snd+ $ scanl1 (segmentedL (+))+ $ zip head_flags+ $ fill (I1 m) 1++ iotas = map snd+ $ scanl1 (segmentedL const)+ $ zip head_flags+ $ permute const+ (fill (I1 n) undef)+ -- If any of the elements expand to zero new+ -- elements then this would result in multiple+ -- writes to the same index since the offsets are+ -- also the same, which is undefined behaviour+ (\ix -> if szs ! ix > 0+ then put ix+ else Nothing_)+ $ enumFromN (shape xs) 0+ in+ zipWith g (gather iotas xs) idxs+++{--+-- Sequence operations+-- -------------------++-- | Reduce a sequence by appending all the shapes and all the elements in two+-- separate vectors.+--+fromSeq :: (Shape sh, Elt a) => Seq [Array sh a] -> Seq (Vector sh, Vector a)+fromSeq = foldSeqFlatten f (lift (emptyArray, emptyArray))+ where+ f x sh1 a1 =+ let (sh0, a0) = unlift x+ in lift (sh0 ++ sh1, a0 ++ a1)+++fromSeqElems :: (Shape sh, Elt a) => Seq [Array sh a] -> Seq (Vector a)+fromSeqElems = foldSeqFlatten f emptyArray+ where+ f a0 _ a1 = a0 ++ a1++fromSeqShapes :: (Shape sh, Elt a) => Seq [Array sh a] -> Seq (Vector sh)+fromSeqShapes = foldSeqFlatten f emptyArray+ where+ f sh0 sh1 _ = sh0 ++ sh1++-- | Sequence an array on the innermost dimension.+--+toSeqInner :: (Shape sh, Elt a) => Acc (Array (sh :. Int) a) -> Seq [Array sh a]+toSeqInner a = toSeq (Any :. Split) a++-- | Sequence a 2-dimensional array on the outermost dimension.+--+toSeqOuter2 :: Elt a => Acc (Array DIM2 a) -> Seq [Array DIM1 a]+toSeqOuter2 a = toSeq (Z :. Split :. All) a++-- | Sequence a 3-dimensional array on the outermost dimension.+toSeqOuter3 :: Elt a => Acc (Array DIM3 a) -> Seq [Array DIM2 a]+toSeqOuter3 a = toSeq (Z :. Split :. All :. All) a++-- | Generate a scalar sequence of a fixed given length, by applying+-- the given scalar function at each index.+generateSeq :: Elt a => Exp Int -> (Exp Int -> Exp a) -> Seq [Scalar a]+generateSeq n f = toSeq (Z :. Split) (generate (index1 n) (f . unindex1))+--}++-- Utilities+-- ---------++emptyArray :: (Shape sh, Elt e) => Acc (Array sh e)+emptyArray = fill (constant empty) undef+++-- Lenses+-- ------+--+-- Imported from `lens-accelerate` (which provides more general Field instances)+--+_1 :: forall sh. Elt sh => Lens' (Exp (sh:.Int)) (Exp Int)+_1 = lens (\ix -> let _ :. x = unlift ix :: Exp sh :. Exp Int in x)+ (\ix x -> let sh :. _ = unlift ix :: Exp sh :. Exp Int in lift (sh :. x))++_2 :: forall sh. Elt sh => Lens' (Exp (sh:.Int:.Int)) (Exp Int)+_2 = lens (\ix -> let _ :. y :. _ = unlift ix :: Exp sh :. Exp Int :. Exp Int in y)+ (\ix y -> let sh :. _ :. x = unlift ix :: Exp sh :. Exp Int :. Exp Int in lift (sh :. y :. x))++_3 :: forall sh. Elt sh => Lens' (Exp (sh:.Int:.Int:.Int)) (Exp Int)+_3 = lens (\ix -> let _ :. z :. _ :. _ = unlift ix :: Exp sh :. Exp Int :. Exp Int :. Exp Int in z)+ (\ix z -> let sh :. _ :. y :. x = unlift ix :: Exp sh :. Exp Int :. Exp Int :. Exp Int in lift (sh :. z :. y :. x))+
+ src/Data/Array/Accelerate/Pretty.hs view
@@ -0,0 +1,202 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE UndecidableInstances #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Pretty+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Pretty (++ -- ** Pretty printing+ PrettyAcc, ExtractAcc,+ prettyPreOpenAcc,+ prettyPreOpenAfun,+ prettyOpenExp,+ prettyOpenFun,++ -- ** Graphviz+ Graph,+ PrettyGraph(..), Detail(..),+ graphDelayedAcc, graphDelayedAfun,++) where++import Data.Array.Accelerate.AST hiding ( Acc, Exp )+import Data.Array.Accelerate.Debug.Internal.Flags+import Data.Array.Accelerate.Error+import Data.Array.Accelerate.Pretty.Graphviz+import Data.Array.Accelerate.Pretty.Print hiding ( Keyword(..) )+import Data.Array.Accelerate.Smart ( Acc, Exp )+import Data.Array.Accelerate.Sugar.Array+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Trafo+import Data.Array.Accelerate.Trafo.Delayed++import Data.Maybe+import Prettyprinter+import Prettyprinter.Render.String+import Prettyprinter.Render.Terminal+import System.Environment+import System.IO+import System.IO.Unsafe+import qualified Data.Text.Lazy as T+import qualified System.Console.ANSI as Term+import qualified System.Console.Terminal.Size as Term++#if ACCELERATE_DEBUG+import Control.DeepSeq+import Data.Array.Accelerate.Debug.Internal.Stats+#endif+++instance Arrays arrs => Show (Acc arrs) where+ show = withSimplStats . show . convertAcc++instance Afunction (Acc a -> f) => Show (Acc a -> f) where+ show = withSimplStats . show . convertAfun++instance Elt e => Show (Exp e) where+ show = withSimplStats . show . convertExp++instance Function (Exp a -> f) => Show (Exp a -> f) where+ show = withSimplStats . show . convertFun++-- instance Typeable a => Show (Seq a) where+-- show = withSimplStats . show . convertSeq+++-- Note: [Show instances]+--+-- Explicitly enumerate Show instances for the Accelerate array AST types.+-- If we instead use a generic instance of the form:+--+-- instance Kit acc => Show (acc aenv a) where+--+-- This matches any type of kind (* -> * -> *), which can cause problems+-- interacting with other packages. See Issue #108.+--++instance PrettyEnv aenv => Show (OpenAcc aenv a) where+ show = renderForTerminal . prettyOpenAcc configPlain context0 (prettyEnv (pretty 'a'))++instance PrettyEnv aenv => Show (OpenAfun aenv f) where+ show = renderForTerminal . prettyPreOpenAfun configPlain prettyOpenAcc (prettyEnv (pretty 'a'))++instance PrettyEnv aenv => Show (DelayedOpenAcc aenv a) where+ show = let config = if shouldPrintHash then configWithHash else configPlain+ in renderForTerminal . prettyDelayedOpenAcc config context0 (prettyEnv (pretty 'a'))++instance PrettyEnv aenv => Show (DelayedOpenAfun aenv f) where+ show = let config = if shouldPrintHash then configWithHash else configPlain+ in renderForTerminal . prettyPreOpenAfun config prettyDelayedOpenAcc (prettyEnv (pretty 'a'))++instance (PrettyEnv env, PrettyEnv aenv) => Show (OpenExp env aenv e) where+ show = renderForTerminal . prettyOpenExp context0 (prettyEnv (pretty 'x')) (prettyEnv (pretty 'a'))++instance (PrettyEnv env, PrettyEnv aenv) => Show (OpenFun env aenv e) where+ show = renderForTerminal . prettyOpenFun (prettyEnv (pretty 'x')) (prettyEnv (pretty 'a'))+++-- Internals+-- ---------++renderForTerminal :: Adoc -> String+renderForTerminal = render . layoutSmart terminalLayoutOptions+ where+ fancy = terminalSupportsANSI && terminalColourAllowed+ render+ | fancy = T.unpack . renderLazy . reAnnotateS ansiKeyword+ | otherwise = renderString++{-# NOINLINE terminalColourAllowed #-}+terminalColourAllowed :: Bool+terminalColourAllowed = unsafePerformIO $ isNothing <$> lookupEnv "NO_COLOR"++{-# NOINLINE terminalSupportsANSI #-}+terminalSupportsANSI :: Bool+terminalSupportsANSI = unsafePerformIO $ Term.hSupportsANSI stdout++{-# NOINLINE terminalLayoutOptions #-}+terminalLayoutOptions :: LayoutOptions+terminalLayoutOptions+ = unsafePerformIO+ $ do term <- Term.size+ return $ case term of+ Nothing -> defaultLayoutOptions+ Just t -> LayoutOptions { layoutPageWidth = AvailablePerLine (min w 120) f }+ where+ w = Term.width t+ f | w <= 80 = 1+ | w <= 100 = 0.9+ | otherwise = 0.8++prettyOpenAcc :: PrettyAcc OpenAcc+prettyOpenAcc config context aenv (OpenAcc pacc) =+ prettyPreOpenAcc config context prettyOpenAcc extractOpenAcc aenv pacc++extractOpenAcc :: OpenAcc aenv a -> PreOpenAcc OpenAcc aenv a+extractOpenAcc (OpenAcc pacc) = pacc+++prettyDelayedOpenAcc :: HasCallStack => PrettyAcc DelayedOpenAcc+prettyDelayedOpenAcc config context aenv (Manifest pacc)+ = prettyPreOpenAcc config context prettyDelayedOpenAcc extractDelayedOpenAcc aenv pacc+prettyDelayedOpenAcc _ _ aenv (Delayed _ sh f _)+ = parens+ $ nest shiftwidth+ $ sep [ delayed "delayed"+ , prettyOpenExp app Empty aenv sh+ , parens $ prettyOpenFun Empty aenv f+ ]++extractDelayedOpenAcc :: HasCallStack => DelayedOpenAcc aenv a -> PreOpenAcc DelayedOpenAcc aenv a+extractDelayedOpenAcc (Manifest pacc) = pacc+extractDelayedOpenAcc Delayed{} = internalError "expected manifest array"+++-- Unfortunately, using unsafePerformIO here means that the getFlag will be+-- evaluated only once when the first 'show' is performed on a Delayed value;+-- afterwards, the thunk will have been evaluated, and all future pretty-print+-- outputs will use the same result.+-- This cannot be prevented using a NOINLINE pragma, since then the function+-- itself is still a thunk that will only be evaluated once.+--+-- The practical result of this is that @setFlag verbose@ will not change+-- anything after a Delayed has already been printed once.+shouldPrintHash :: Bool+shouldPrintHash = unsafePerformIO $ getFlag verbose+++-- Debugging+-- ---------++-- Attach simplifier statistics to the tail of the given string. Since the+-- statistics rely on fully evaluating the expression this is difficult to do+-- generally (without an additional deepseq), but easy enough for our show+-- instances.+--+-- For now, we just reset the statistics at the beginning of a conversion, and+-- leave it to a backend to choose an appropriate moment to dump the summary.+--+withSimplStats :: String -> String+#ifdef ACCELERATE_DEBUG+withSimplStats x = unsafePerformIO $ do+ when dump_simpl_stats $ x `deepseq` dumpSimplStats+ return x+#else+withSimplStats x = x+#endif+
+ src/Data/Array/Accelerate/Pretty/Graphviz.hs view
@@ -0,0 +1,540 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE ViewPatterns #-}+-- |+-- Module : Data.Array.Accelerate.Pretty.Graphviz+-- Copyright : [2015..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+module Data.Array.Accelerate.Pretty.Graphviz (++ Graph,+ PrettyGraph(..), Detail(..),++ graphDelayedAcc, graphDelayedAfun,++) where++import Data.Array.Accelerate.AST+import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.AST.LeftHandSide+import Data.Array.Accelerate.AST.Var+import Data.Array.Accelerate.Analysis.Match+import Data.Array.Accelerate.Error+import Data.Array.Accelerate.Pretty.Graphviz.Monad+import Data.Array.Accelerate.Pretty.Graphviz.Type+import Data.Array.Accelerate.Pretty.Print hiding ( Keyword(..) )+import Data.Array.Accelerate.Representation.Array+import Data.Array.Accelerate.Representation.Stencil+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Sugar.Foreign+import Data.Array.Accelerate.Trafo.Delayed+import Data.Array.Accelerate.Trafo.Substitution++import Control.Applicative hiding ( Const, empty )+import Control.Arrow ( (&&&) )+import Control.Monad.State ( modify, gets, state )+import Data.HashSet ( HashSet )+import Data.List ( nub, partition )+import Data.Maybe+import Data.String+import Prettyprinter+import Prelude hiding ( exp )+import qualified Data.HashSet as Set+import qualified Data.Sequence as Seq+++-- Configuration options+-- ---------------------++cfgIncludeShape, cfgUnique :: Bool+cfgIncludeShape = False -- draw edges for uses of shape information+cfgUnique = False -- draw a single edge per data dependency+++-- Environments+-- ------------++-- This is the standard environment typed by de Bruijn indices, where at each+-- index we need to record both the pretty printed label as well its 'NodeId',+-- which we use to track data dependencies.+--+data Aval env where+ Aempty :: Aval ()+ Apush :: Aval env -> NodeId -> Label -> Aval (env, t)++-- Convert to the 'Val' used by the base pretty printing module by stripping out+-- the 'NodeId' part.+--+avalToVal :: Aval aenv -> Val aenv+avalToVal Aempty = Empty+avalToVal (Apush aenv _ v) = Push (avalToVal aenv) (pretty v)++aprj :: Idx aenv t -> Aval aenv -> (NodeId, Label) -- TLM: (Vertex, Label) ??+aprj ZeroIdx (Apush _ n v) = (n,v)+aprj (SuccIdx ix) (Apush aenv _ _) = aprj ix aenv+++-- Graph construction+-- ------------------++mkNode :: PNode -> Maybe Label -> Dot NodeId+mkNode (PNode ident tree deps) label =+ let node = Node label ident tree+ edges = Seq.fromList+ $ map (\(from, to) -> Edge from (Vertex ident to))+ $ if cfgUnique then nub deps else deps+ in+ state $ \s ->+ ( ident+ , s { dotNodes = node Seq.<| dotNodes s+ , dotEdges = edges Seq.>< dotEdges s+ }+ )+++-- Add [T|F] ports underneath the given tree.+--+mkTF :: Tree (Maybe Port, Adoc) -> Tree (Maybe Port, Adoc)+mkTF this =+ Forest [ this+ , Forest [ Leaf (Just "T", "T")+ , Leaf (Just "F", "F")+ ]+ ]+++-- Pretty Printing+-- ===============+--++class PrettyGraph g where+ ppGraph :: Detail -> g -> Graph++instance PrettyGraph (DelayedAcc a) where+ ppGraph = graphDelayedAcc++instance PrettyGraph (DelayedAfun a) where+ ppGraph = graphDelayedAfun++data Detail = Simple | Full++simple :: Detail -> Bool+simple Simple = True+simple _ = False++-- | Generate a dependency graph for the given computation+--+{-# NOINLINE graphDelayedAcc #-}+graphDelayedAcc :: HasCallStack => Detail -> DelayedAcc a -> Graph+graphDelayedAcc detail acc =+ evalDot (graphDelayedOpenAcc detail Aempty acc)++-- | Generate a dependency graph for an array function+--+{-# NOINLINE graphDelayedAfun #-}+graphDelayedAfun :: HasCallStack => Detail -> DelayedAfun f -> Graph+graphDelayedAfun detail afun = evalDot $! do+ l <- prettyDelayedAfun detail Aempty afun+ state $ \s ->+ case Seq.viewl (dotGraph s) of+ g@(Graph l' _) Seq.:< gs | l == l' -> (g, s { dotGraph = gs })+ _ -> internalError "unexpected error"+++-- Pretty-printing data-dependency graphs+-- --------------------------------------++-- Partially constructed graph nodes, consists of some body text and a list of+-- vertices which we will draw edges from (and later, the port we connect into).+--+data PDoc = PDoc Adoc [Vertex]+data PNode = PNode NodeId (Tree (Maybe Port, Adoc)) [(Vertex, Maybe Port)]++graphDelayedOpenAcc+ :: HasCallStack+ => Detail+ -> Aval aenv+ -> DelayedOpenAcc aenv a+ -> Dot Graph+graphDelayedOpenAcc detail aenv acc = do+ r <- prettyDelayedOpenAcc detail context0 aenv acc+ i <- genNodeId+ v <- mkNode r Nothing+ _ <- mkNode (PNode i (Leaf (Nothing,"result")) [(Vertex v Nothing, Nothing)]) Nothing+ mkGraph++-- Generate a graph for the given term.+--+prettyDelayedOpenAcc+ :: forall aenv arrs. HasCallStack+ => Detail -- simplified output: only print operator name+ -> Context+ -> Aval aenv+ -> DelayedOpenAcc aenv arrs+ -> Dot PNode+prettyDelayedOpenAcc _ _ _ Delayed{} = internalError "expected manifest array"+prettyDelayedOpenAcc detail ctx aenv (Manifest pacc) =+ case pacc of+ Avar ix -> pnode (avar ix)+ Alet lhs bnd body -> do+ bnd'@(PNode ident _ _) <- prettyDelayedOpenAcc detail context0 aenv bnd+ (aenv1, a) <- prettyLetALeftHandSide ident aenv lhs+ _ <- mkNode bnd' (Just a)+ body' <- prettyDelayedOpenAcc detail context0 aenv1 body+ return body'++ Acond p t e -> do+ ident <- genNodeId+ vt <- lift t+ ve <- lift e+ PDoc p' vs <- ppE p+ let port = Just "P"+ doc = mkTF $ Leaf (port, if simple detail then "?|" else p')+ deps = (vt, Just "T") : (ve, Just "F") : map (,port) vs+ return $ PNode ident doc deps++ Apply _ afun acc -> apply <$> prettyDelayedAfun detail aenv afun+ <*> prettyDelayedOpenAcc detail ctx aenv acc++ Awhile p f x -> do+ ident <- genNodeId+ x' <- replant =<< prettyDelayedOpenAcc detail app aenv x+ p' <- prettyDelayedAfun detail aenv p+ f' <- prettyDelayedAfun detail aenv f+ --+ case x' of+ PNode _ (Leaf (Nothing,xb)) fvs ->+ let loop = nest 2 (sep ["awhile", pretty p', pretty f', xb ])+ in return $ PNode ident (Leaf (Nothing,loop)) fvs+ _ -> internalError "replant did not return a Leaf"++ Apair a1 a2 -> genNodeId >>= prettyDelayedApair detail aenv a1 a2++ Anil -> "()" .$ []+ Atrace (Message _ _ msg) as bs -> "atrace" .$ [ return $ PDoc (pretty msg) [], ppA as, ppA bs ]+ Use repr arr -> "use" .$ [ return $ PDoc (prettyArray repr arr) [] ]+ Unit _ e -> "unit" .$ [ ppE e ]+ Generate _ sh f -> "generate" .$ [ ppE sh, ppF f ]+ Transform _ sh ix f xs -> "transform" .$ [ ppE sh, ppF ix, ppF f, ppA xs ]+ Reshape _ sh xs -> "reshape" .$ [ ppE sh, ppA xs ]+ Replicate _ty ix xs -> "replicate" .$ [ ppE ix, ppA xs ]+ Slice _ty xs ix -> "slice" .$ [ ppA xs, ppE ix ]+ Map _ f xs -> "map" .$ [ ppF f, ppA xs ]+ ZipWith _ f xs ys -> "zipWith" .$ [ ppF f, ppA xs, ppA ys ]+ Fold f (Just z) a -> "fold" .$ [ ppF f, ppE z, ppA a ]+ Fold f Nothing a -> "fold1" .$ [ ppF f, ppA a ]+ FoldSeg _ f (Just z) a s -> "foldSeg" .$ [ ppF f, ppE z, ppA a, ppA s ]+ FoldSeg _ f Nothing a s -> "fold1Seg" .$ [ ppF f, ppA a, ppA s ]+ Scan d f (Just z) a -> ppD "scan" d "" .$ [ ppF f, ppE z, ppA a ]+ Scan d f Nothing a -> ppD "scan" d "1" .$ [ ppF f, ppA a ]+ Scan' d f z a -> ppD "scan" d "'" .$ [ ppF f, ppE z, ppA a ]+ Permute f dfts p xs -> "permute" .$ [ ppF f, ppA dfts, ppF p, ppA xs ]+ Backpermute _ sh p xs -> "backpermute" .$ [ ppE sh, ppF p, ppA xs ]+ Stencil s _ sten bndy xs -> "stencil" .$ [ ppF sten, ppB (stencilEltR s) bndy, ppA xs ]+ Stencil2 s1 s2 _ s b1 a1 b2 a2 -> "stencil2" .$ [ ppF s, ppB (stencilEltR s1) b1, ppA a1, ppB (stencilEltR s2) b2, ppA a2 ]+ Aforeign _ ff _afun xs -> "aforeign" .$ [ return (PDoc (pretty (strForeign ff)) []), {- ppAf afun, -} ppA xs ]+ -- Collect{} -> error "Collect"++ where+ (.$) :: Operator -> [Dot PDoc] -> Dot PNode+ name .$ docs = pnode =<< fmt name docs++ fmt :: Operator -> [Dot PDoc] -> Dot PDoc+ fmt name docs = do+ docs' <- sequence docs+ let args = [ x | PDoc x _ <- docs' ]+ fvs = [ x | PDoc _ x <- docs' ]+ doc = if simple detail+ then manifest name+ else parensIf (needsParens ctx name)+ $ nest shiftwidth+ $ sep ( manifest name : args )+ return $ PDoc doc (concat fvs)++ pnode :: PDoc -> Dot PNode+ pnode (PDoc doc vs) = do+ let port = Nothing+ ident <- genNodeId+ return $ PNode ident (Leaf (port, doc)) (map (,port) vs)++ -- Free variables+ --+ fvF :: Fun aenv t -> [Vertex]+ fvF = fvOpenFun Empty aenv++ fvE :: Exp aenv t -> [Vertex]+ fvE = fvOpenExp Empty aenv++ -- Pretty-printing+ --+ avar :: ArrayVar aenv t -> PDoc+ avar (Var _ ix) = let (ident, v) = aprj ix aenv+ in PDoc (pretty v) [Vertex ident Nothing]++ aenv' :: Val aenv+ aenv' = avalToVal aenv++ ppA :: HasCallStack => DelayedOpenAcc aenv a -> Dot PDoc+ ppA (Manifest (Avar ix)) = return (avar ix)+ ppA acc@Manifest{} = do+ -- Lift out and draw as a separate node. This can occur with the manifest+ -- array arguments to permute (defaults array) and stencil[2].+ acc' <- prettyDelayedOpenAcc detail app aenv acc+ v <- mkLabel+ ident <- mkNode acc' (Just v)+ return $ PDoc (pretty v) [Vertex ident Nothing]+ ppA (Delayed _ sh f _)+ | Shape a <- sh -- identical shape+ , Just b <- isIdentityIndexing f -- function is `\ix -> b ! ix`+ , Just Refl <- matchVar a b -- function thus is `\ix -> a ! ix`+ = ppA $ Manifest $ Avar a+ ppA (Delayed _ sh f _) = do+ PDoc d v <- "Delayed" `fmt` [ ppE sh, ppF f ]+ return $ PDoc (parens d) v++ ppB :: forall sh e. HasCallStack+ => TypeR e+ -> Boundary aenv (Array sh e)+ -> Dot PDoc+ ppB _ Clamp = return (PDoc "clamp" [])+ ppB _ Mirror = return (PDoc "mirror" [])+ ppB _ Wrap = return (PDoc "wrap" [])+ ppB tp (Constant e) = return (PDoc (prettyConst tp e) [])+ ppB _ (Function f) = ppF f++ ppF :: HasCallStack => Fun aenv t -> Dot PDoc+ ppF = return . uncurry PDoc . (parens . prettyFun aenv' &&& fvF)++ ppE :: HasCallStack => Exp aenv t -> Dot PDoc+ ppE = return . uncurry PDoc . (prettyExp aenv' &&& fvE)++ ppD :: String -> Direction -> String -> Operator+ ppD f LeftToRight k = fromString (f <> "l" <> k)+ ppD f RightToLeft k = fromString (f <> "r" <> k)++ lift :: HasCallStack => DelayedOpenAcc aenv a -> Dot Vertex+ lift Delayed{} = internalError "expected manifest array"+ lift (Manifest (Avar (Var _ ix))) = return $ Vertex (fst (aprj ix aenv)) Nothing+ lift acc = do+ acc' <- prettyDelayedOpenAcc detail context0 aenv acc+ ident <- mkNode acc' Nothing+ return $ Vertex ident Nothing++ apply :: Label -> PNode -> PNode+ apply f (PNode ident x vs) =+ let x' = case x of+ Leaf (p,d) -> Leaf (p, pretty f <+> d)+ Forest ts -> Forest (Leaf (Nothing,pretty f) : ts)+ in+ PNode ident x' vs+++-- Pretty print array functions as separate sub-graphs, and return the name of+-- the sub-graph as if it can be called like a function. We will add additional+-- nodes at the top of the graph to represent the bound variables.+--+-- Note: [Edge placement]+--+-- If a node belongs to a particular graph, so too must all its edges (and+-- vertices). This means that if the subgraph references anything from the+-- enclosing environment, we must lift those edges out of this subgraph,+-- otherwise the referenced node will be drawn inside of the subgraph.+--+prettyDelayedAfun+ :: HasCallStack+ => Detail+ -> Aval aenv+ -> DelayedOpenAfun aenv afun+ -> Dot Label+prettyDelayedAfun detail aenv afun = do+ Graph _ ss <- mkSubgraph (go aenv afun)+ n <- Seq.length <$> gets dotGraph+ let label = "afun" <> fromString (show (n+1))+ outer = collect aenv+ (lifted,ss') =+ flip partition ss $ \s ->+ case s of+ E (Edge (Vertex ident _) _) -> Set.member ident outer+ _ -> False+ --+ modify $ \s -> s { dotGraph = dotGraph s Seq.|> Graph label ss'+ , dotEdges = Seq.fromList [ e | E e <- lifted ] Seq.>< dotEdges s+ }+ return label+ where+ go :: Aval aenv' -> DelayedOpenAfun aenv' a' -> Dot Graph+ go aenv' (Abody b) = graphDelayedOpenAcc detail aenv' b+ go aenv' (Alam lhs f) = do+ aenv'' <- prettyLambdaALeftHandSide aenv' lhs+ go aenv'' f++ collect :: Aval aenv' -> HashSet NodeId+ collect Aempty = Set.empty+ collect (Apush a i _) = Set.insert i (collect a)++prettyLetALeftHandSide+ :: forall repr aenv aenv'. HasCallStack+ => NodeId+ -> Aval aenv+ -> ALeftHandSide repr aenv aenv'+ -> Dot (Aval aenv', Label)+prettyLetALeftHandSide _ aenv (LeftHandSideWildcard repr) = return (aenv, doc)+ where+ doc = case repr of+ TupRunit -> "()"+ _ -> "_"+prettyLetALeftHandSide ident aenv (LeftHandSideSingle _) = do+ a <- mkLabel+ return (Apush aenv ident a, a)+prettyLetALeftHandSide ident aenv (LeftHandSidePair lhs1 lhs2) = do+ (aenv1, d1) <- prettyLetALeftHandSide ident aenv lhs1+ (aenv2, d2) <- prettyLetALeftHandSide ident aenv1 lhs2+ return (aenv2, "(" <> d1 <> ", " <> d2 <> ")")++prettyLambdaALeftHandSide+ :: forall repr aenv aenv'. HasCallStack+ => Aval aenv+ -> ALeftHandSide repr aenv aenv'+ -> Dot (Aval aenv')+prettyLambdaALeftHandSide aenv (LeftHandSideWildcard _) = return aenv+prettyLambdaALeftHandSide aenv (LeftHandSideSingle _) = do+ a <- mkLabel+ ident <- genNodeId+ _ <- mkNode (PNode ident (Leaf (Nothing, pretty a)) []) Nothing+ return $ Apush aenv ident a+prettyLambdaALeftHandSide aenv (LeftHandSidePair lhs1 lhs2) = do+ aenv1 <- prettyLambdaALeftHandSide aenv lhs1+ prettyLambdaALeftHandSide aenv1 lhs2++-- Display array tuples. This is a little tricky...+--+prettyDelayedApair+ :: forall aenv a1 a2. HasCallStack+ => Detail+ -> Aval aenv+ -> DelayedOpenAcc aenv a1+ -> DelayedOpenAcc aenv a2+ -> NodeId+ -> Dot PNode+prettyDelayedApair detail aenv a1 a2 ident = do+ PNode id1 t1 v1 <- prettyElem a1+ PNode id2 t2 v2 <- prettyElem a2+ modify $ \s -> s { dotEdges = fmap (redirect ident [id1, id2]) (dotEdges s) }+ return $ PNode ident (forest [t1, t2]) (v1 ++ v2)+ where+ prettyElem :: DelayedOpenAcc aenv a -> Dot PNode+ prettyElem a = replant =<< prettyDelayedOpenAcc detail context0 aenv a++ -- Redirect any edges that pointed into one of the nodes now part of this+ -- tuple, to instead point to the container node.+ --+ redirect :: NodeId -> [NodeId] -> Edge -> Edge+ redirect new subs edge@(Edge from (Vertex to port))+ | to `elem` subs = Edge from (Vertex new port)+ | otherwise = edge++ -- Since we have lifted out any non-leaves into separate nodes, we can+ -- simply tuple-up all of the elements.+ --+ forest :: [Tree (Maybe Port, Adoc)] -> Tree (Maybe Port, Adoc)+ forest leaves = Leaf (Nothing, tupled [ align d | Leaf (Nothing,d) <- leaves ])+++-- Lift out anything that isn't a Leaf node and output it to the graph+-- immediately as a new labelled node.+--+replant :: PNode -> Dot PNode+replant pnode@(PNode ident tree _) =+ case tree of+ Leaf (Nothing, _) -> return pnode+ _ -> do+ vacuous <- genNodeId+ a <- mkLabel+ _ <- mkNode pnode (Just a)+ return $ PNode vacuous (Leaf (Nothing, pretty a)) [(Vertex ident Nothing, Nothing)]+++-- Pretty printing scalar functions and expressions+-- ------------------------------------------------+--+-- This is done with the usual machinery. Note that we rely on knowing that all+-- array operations will be lifted out of scalar expressions. This means that we+-- don't really need to recurse into the scalar terms to uncover new graph+-- nodes.+--++-- Data dependencies+-- -----------------+--+-- Return the data-dependencies of the given term. This is just a tree traversal+-- to extract all of the free variables. We will draw an edge from each of those+-- nodes (vertices) into the current term.+--++fvAvar :: Aval aenv -> ArrayVar aenv a -> [Vertex]+fvAvar env (Var _ ix) = [ Vertex (fst $ aprj ix env) Nothing ]++fvOpenFun+ :: forall env aenv fun.+ Val env+ -> Aval aenv+ -> OpenFun env aenv fun+ -> [Vertex]+fvOpenFun env aenv (Body b) = fvOpenExp env aenv b+fvOpenFun env aenv (Lam lhs f) = fvOpenFun env' aenv f+ where+ (env', _) = prettyELhs True env lhs++fvOpenExp+ :: forall env aenv exp.+ Val env+ -> Aval aenv+ -> OpenExp env aenv exp+ -> [Vertex]+fvOpenExp env aenv = fv+ where+ fvF :: OpenFun env aenv f -> [Vertex]+ fvF = fvOpenFun env aenv++ fv :: OpenExp env aenv e -> [Vertex]+ fv (Shape acc) = if cfgIncludeShape then fvAvar aenv acc else []+ fv (Index acc i) = concat [ fvAvar aenv acc, fv i ]+ fv (LinearIndex acc i) = concat [ fvAvar aenv acc, fv i ]+ --+ fv (Let lhs e1 e2) = concat [ fv e1, fvOpenExp env' aenv e2 ]+ where+ (env', _) = prettyELhs False env lhs+ fv Evar{} = []+ fv Undef{} = []+ fv Const{} = []+ fv PrimConst{} = []+ fv (PrimApp _ x) = fv x+ fv (Pair e1 e2) = concat [ fv e1, fv e2]+ fv Nil = []+ fv (VecPack _ e) = fv e+ fv (VecUnpack _ e) = fv e+ fv (IndexSlice _ slix sh) = concat [ fv slix, fv sh ]+ fv (IndexFull _ slix sh) = concat [ fv slix, fv sh ]+ fv (ToIndex _ sh ix) = concat [ fv sh, fv ix ]+ fv (FromIndex _ sh ix) = concat [ fv sh, fv ix ]+ fv (ShapeSize _ sh) = fv sh+ fv Foreign{} = []+ fv (Case e rhs def) = concat [ fv e, concat [ fv c | (_,c) <- rhs ], maybe [] fv def ]+ fv (Cond p t e) = concat [ fv p, fv t, fv e ]+ fv (While p f x) = concat [ fvF p, fvF f, fv x ]+ fv (Coerce _ _ e) = fv e+
+ src/Data/Array/Accelerate/Pretty/Graphviz/Monad.hs view
@@ -0,0 +1,74 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+-- |+-- Module : Data.Array.Accelerate.Pretty.Graphviz.Monad+-- Copyright : [2015..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+module Data.Array.Accelerate.Pretty.Graphviz.Monad+ where++import Control.Monad.State+import Data.Foldable ( toList )+import Data.Sequence ( Seq )+import qualified Data.Sequence as Seq+import qualified Data.Text as Text++import Data.Array.Accelerate.Pretty.Graphviz.Type+++-- Graph construction state ----------------------------------------------------++type Dot a = State DotState a+data DotState = DotState+ { freshLabel :: !Int+ , freshID :: !Int -- keep internal node ids in a separate counter from the user-visible node labels+ , dotGraph :: Seq Graph+ , dotEdges :: Seq Edge+ , dotNodes :: Seq Node+ }++emptyState :: DotState+emptyState = DotState 0 0 Seq.empty Seq.empty Seq.empty++runDot :: Dot a -> (a, DotState)+runDot dot = runState dot emptyState++evalDot :: Dot a -> a+evalDot dot = fst (runDot dot)++execDot :: Dot a -> DotState+execDot dot = snd (runDot dot)+++-- Utilities -------------------------------------------------------------------++mkLabel :: Dot Label+mkLabel = state $ \s ->+ let n = freshLabel s+ in ( Text.pack ('a' : show n), s { freshLabel = n + 1 } )++genNodeId :: Dot NodeId+genNodeId = state $ \s ->+ let n = freshID s+ in ( NodeId n, s { freshID = n + 1 } )++mkGraph :: Dot Graph+mkGraph =+ state $ \DotState{..} ->+ ( Graph mempty (toList $ fmap N dotNodes Seq.>< fmap E dotEdges Seq.>< fmap G dotGraph)+ , emptyState { freshLabel = freshLabel }+ )++mkSubgraph :: Dot Graph -> Dot Graph+mkSubgraph g = do+ n <- gets freshLabel+ let (r, s') = runDot $ do+ modify $ \s -> s { freshLabel = n }+ g+ state $ \s -> (r, s { freshLabel = freshLabel s' })+
+ src/Data/Array/Accelerate/Pretty/Graphviz/Type.hs view
@@ -0,0 +1,154 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE ViewPatterns #-}+-- |+-- Module : Data.Array.Accelerate.Pretty.Graphviz.Type+-- Copyright : [2015..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- Simple data types for representing (simple, directed) graphs and+-- pretty-printing to Graphviz dot format.+--+module Data.Array.Accelerate.Pretty.Graphviz.Type+ where++import Data.Hashable+import Data.Maybe+import Data.Text ( Text )+import Prettyprinter+import Text.Printf+import qualified Data.Text as Text++import Data.Array.Accelerate.Pretty.Print ( Adoc, Keyword )+++-- Rose tree, with all information at the leaves.+--+data Tree a = Leaf a+ | Forest [Tree a]++instance Functor Tree where+ fmap f (Leaf x) = Leaf (f x)+ fmap f (Forest xs) = Forest (map (fmap f) xs)+++-- Representation for simple Graphviz graphs+--+data Graph = Graph Label [Statement]+data Statement = N Node | E Edge | G Graph++data Node = Node (Maybe Label) NodeId (Tree (Maybe Port, Adoc))+data NodeId = NodeId !Int++type Label = Text+type Port = Text++data Vertex = Vertex NodeId (Maybe Port)+data Edge = Edge {- from -} Vertex+ {- to -} Vertex++deriving instance Eq NodeId+deriving instance Eq Vertex++instance Hashable NodeId where+ hashWithSalt salt (NodeId ident) = hashWithSalt salt ident++instance Show Graph where+ show = show . ppGraph++-- Pretty print a (directed) graph to dot format+--+ppGraph :: Graph -> Adoc+ppGraph (Graph l ss) =+ vcat [ "digraph" <+> pretty l <+> lbrace+ , nest 4 $ vcat+ $ punctuate semi+ $ "graph [compound=true]"+ : "node [shape=record,fontsize=10]"+ : map ppStatement ss+ , rbrace+ ]++ppSubgraph :: Graph -> Adoc+ppSubgraph (Graph l ss) =+ vcat [ "subgraph cluster_" <> pretty l <+> lbrace+ , nest 4 $ vcat+ $ punctuate semi+ $ "label" <> equals <> pretty l+ : map ppStatement ss+ , rbrace+ ]++ppStatement :: Statement -> Adoc+ppStatement (N n) = ppNode n+ppStatement (E e) = ppEdge e+ppStatement (G g) = ppSubgraph g++ppEdge :: Edge -> Adoc+ppEdge (Edge from to) = ppVertex from <+> "->" <+> ppVertex to++ppVertex :: Vertex -> Adoc+ppVertex (Vertex n p) = ppNodeId n <> maybe mempty (colon<>) (fmap pretty p)++ppNode :: Node -> Adoc+ppNode (Node label nid body) =+ hcat [ ppNodeId nid+ , brackets+ $ hcat+ $ punctuate comma+ $ catMaybes [ fmap ((\x -> "xlabel" <> equals <> x) . dquotes . pretty) label+ , Just ( "label" <> equals <> dquotes (ppNodeTree body))+ ]+ ]++ppNodeTree :: Tree (Maybe Port, Adoc) -> Adoc+ppNodeTree (Forest trees) = braces $ hcat (punctuate (pretty '|') (map ppNodeTree trees))+ppNodeTree (Leaf (port, body)) = maybe mempty (\p -> pretty '<' <> p <> pretty '>') (fmap pretty port) <> pp body+ where+ -- In order for the text to be properly rendered by graphviz, we need to+ -- escape some special characters. If the text takes up more than one line,+ -- then newlines '\n' need be be replaced with '\l', to ensure that the text+ -- is left justified rather than centred. The last line also needs a final+ -- '\l'. Single lines of text remain centred, which provides better+ -- formatting for short statements and port labels.+ --+ pp :: Adoc -> Adoc+ pp = encode . layoutSmart defaultLayoutOptions+ -- pp = encode . renderSmart 0.7 120++ encode :: SimpleDocStream Keyword -> Adoc+ encode doc =+ let+ go SFail = error "unexpected failure rendering SimpleDoc"+ go SEmpty = (mempty, False)+ go (SChar c x) = let (x',m) = go x in (pretty (escape c) <> x', m)+ go (SText _ t x) = let (x',m) = go x in (pretty (Text.concatMap escape t) <> x', m)+ go (SLine i x) = let (x',_) = go x in ("\\l" <> spaces i <> x', True) -- [1] left justify+ go (SAnnPush a x) = let (x',m) = go x in (annotate a x', m)+ go (SAnnPop x) = let (x',m) = go x in (unAnnotate x', m)++ (doc',multiline) = go doc+ in+ doc' <> if multiline+ then "\\l"+ else mempty++ spaces :: Int -> Doc ann+ spaces i | i <= 0 = mempty+ | otherwise = pretty (Text.replicate i "\\ ")++ escape :: Char -> Text+ escape ' ' = "\\ " -- don't collapse multiple spaces+ escape '>' = "\\>"+ escape '<' = "\\<"+ escape '|' = "\\|"+ -- escape '\n' = "\\l" -- handled at [1] instead+ escape c = Text.singleton c++ppNodeId :: NodeId -> Adoc+ppNodeId (NodeId nid) = pretty (printf "Node_%#0x" nid :: String)+
+ src/Data/Array/Accelerate/Pretty/Print.hs view
@@ -0,0 +1,775 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE ViewPatterns #-}+-- |+-- Module : Data.Array.Accelerate.Pretty.Print+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Pretty.Print (++ PrettyAcc, ExtractAcc,+ prettyPreOpenAcc,+ prettyPreOpenAfun,+ prettyOpenExp, prettyExp,+ prettyOpenFun, prettyFun,+ prettyArray,+ prettyConst,+ prettyELhs,+ prettyALhs,++ -- ** Configuration+ PrettyConfig(..),+ configPlain,+ configWithHash,++ -- ** Internals+ Adoc,+ Val(..),+ PrettyEnv(..),+ Context(..),+ Keyword(..),+ Operator(..),+ parensIf, needsParens,+ ansiKeyword,+ shiftwidth,+ context0,+ app,+ manifest, delayed,+ primOperator,+ isInfix,+ prj, sizeEnv,++) where++import Data.Array.Accelerate.AST hiding ( Direction )+import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.AST.LeftHandSide+import Data.Array.Accelerate.AST.Var+import Data.Array.Accelerate.Representation.Array+import Data.Array.Accelerate.Representation.Elt+import Data.Array.Accelerate.Representation.Stencil+import Data.Array.Accelerate.Representation.Tag+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Sugar.Foreign+import Data.Array.Accelerate.Type+import qualified Data.Array.Accelerate.AST as AST+import qualified Data.Array.Accelerate.Analysis.Hash as Hash+import qualified Data.Array.Accelerate.Trafo.Delayed as Delayed++import Data.Char+import Data.String+import Prettyprinter+import Prettyprinter.Render.Terminal+import Prelude hiding ( exp )+++-- Implementation+-- --------------++type PrettyAcc acc =+ forall aenv a. PrettyConfig acc -> Context -> Val aenv -> acc aenv a -> Adoc+type ExtractAcc acc =+ forall aenv a. acc aenv a -> PreOpenAcc acc aenv a++type Adoc = Doc Keyword++data Keyword+ = Statement -- do | case of | let in+ | Conditional -- if then else+ | Manifest -- collective operations (kernel functions)+ | Delayed -- fused operators+ deriving (Eq, Show)++let_, in_ :: Adoc+let_ = annotate Statement "let"+in_ = annotate Statement "in"++case_, of_ :: Adoc+case_ = annotate Statement "case"+of_ = annotate Statement "of"++if_, then_, else_ :: Adoc+if_ = annotate Statement "if"+then_ = annotate Statement "then"+else_ = annotate Statement "else"++manifest :: Operator -> Adoc+manifest = annotate Manifest . opName++delayed :: Operator -> Adoc+delayed = annotate Delayed . opName++ansiKeyword :: Keyword -> AnsiStyle+ansiKeyword Statement = colorDull Yellow+ansiKeyword Conditional = colorDull Yellow+ansiKeyword Manifest = color Blue+ansiKeyword Delayed = color Green++-- Configuration for the pretty-printing functions+data PrettyConfig acc+ = PrettyConfig { confOperator :: forall aenv arrs.+ PreOpenAcc acc aenv arrs+ -> String+ -> Operator }++configPlain :: PrettyConfig acc+configPlain = PrettyConfig { confOperator = const fromString }++configWithHash :: PrettyConfig Delayed.DelayedOpenAcc+configWithHash =+ PrettyConfig+ { confOperator = \pacc name ->+ let hashval = Hash.hashPreOpenAccWith+ (Hash.defaultHashOptions { Hash.perfect = False })+ Delayed.encodeDelayedOpenAcc+ pacc+ in fromString (name ++ "_" ++ show hashval) }+++-- Array computations+-- ------------------++prettyPreOpenAfun+ :: forall acc aenv f.+ PrettyConfig acc+ -> PrettyAcc acc+ -> Val aenv+ -> PreOpenAfun acc aenv f+ -> Adoc+prettyPreOpenAfun config prettyAcc aenv0 = next (pretty '\\') aenv0+ where+ next :: Adoc -> Val aenv' -> PreOpenAfun acc aenv' f' -> Adoc+ next vs aenv (Abody body) =+ hang shiftwidth (sep [vs <> "->", prettyAcc config context0 aenv body])+ next vs aenv (Alam lhs lam) =+ let (aenv', lhs') = prettyALhs True aenv lhs+ in next (vs <> lhs' <> space) aenv' lam++prettyPreOpenAcc+ :: forall acc aenv arrs.+ PrettyConfig acc+ -> Context+ -> PrettyAcc acc+ -> ExtractAcc acc+ -> Val aenv+ -> PreOpenAcc acc aenv arrs+ -> Adoc+prettyPreOpenAcc config ctx prettyAcc extractAcc aenv pacc =+ case pacc of+ Avar (Var _ idx) -> prj idx aenv+ Alet{} -> prettyAlet config ctx prettyAcc extractAcc aenv pacc+ Apair{} -> prettyAtuple config ctx prettyAcc extractAcc aenv pacc+ Anil -> "()"+ Apply _ f a -> apply+ where+ op = Operator ">->" Infix L 1+ apply = sep [ ppAF f, group (sep [opName op, ppA a]) ]++ Acond p t e -> flatAlt multi single+ where+ p' = ppE p+ t' = ppA t+ e' = ppA e+ --+ single = parensIf (needsParens ctx (Operator "?|:" Infix N 0))+ $ sep [ p', "?|", t', pretty ':', e' ]+ multi = hang 3+ $ vsep [ if_ <+> p'+ , hang shiftwidth (sep [ then_, t' ])+ , hang shiftwidth (sep [ else_, e' ]) ]+++ Atrace (Message _ _ msg) as bs -> ppN "atrace" .$ [ fromString (show msg), ppA as, ppA bs ]+ Aforeign _ ff _ a -> ppN "aforeign" .$ [ pretty (strForeign ff), ppA a ]+ Awhile p f a -> ppN "awhile" .$ [ ppAF p, ppAF f, ppA a ]+ Use repr arr -> ppN "use" .$ [ prettyArray repr arr ]+ Unit _ e -> ppN "unit" .$ [ ppE e ]+ Reshape _ sh a -> ppN "reshape" .$ [ ppE sh, ppA a ]+ Generate _ sh f -> ppN "generate" .$ [ ppE sh, ppF f ]+ Transform _ sh p f a -> ppN "transform" .$ [ ppE sh, ppF p, ppF f, ppA a ]+ Replicate _ ix a -> ppN "replicate" .$ [ ppE ix, ppA a ]+ Slice _ a ix -> ppN "slice" .$ [ ppE ix, ppA a ]+ Map _ f a -> ppN "map" .$ [ ppF f, ppA a ]+ ZipWith _ f a b -> ppN "zipWith" .$ [ ppF f, ppA a, ppA b ]+ Fold f (Just z) a -> ppN "fold" .$ [ ppF f, ppE z, ppA a ]+ Fold f Nothing a -> ppN "fold1" .$ [ ppF f, ppA a ]+ FoldSeg _ f (Just z) a s -> ppN "foldSeg" .$ [ ppF f, ppE z, ppA a, ppA s ]+ FoldSeg _ f Nothing a s -> ppN "fold1Seg" .$ [ ppF f, ppA a, ppA s ]+ Scan d f (Just z) a -> ppD "scan" d "" .$ [ ppF f, ppE z, ppA a ]+ Scan d f Nothing a -> ppD "scan" d "1" .$ [ ppF f, ppA a ]+ Scan' d f z a -> ppD "scan" d "'" .$ [ ppF f, ppE z, ppA a ]+ Permute f d p s -> ppN "permute" .$ [ ppF f, ppA d, ppF p, ppA s ]+ Backpermute _ sh f a -> ppN "backpermute" .$ [ ppE sh, ppF f, ppA a ]+ Stencil s _ f b a -> ppN "stencil" .$ [ ppF f, ppB (stencilEltR s) b, ppA a ]+ Stencil2 s1 s2 _ f b1 a1 b2 a2 -> ppN "stencil2" .$ [ ppF f, ppB (stencilEltR s1) b1, ppA a1, ppB (stencilEltR s2) b2, ppA a2 ]+ where+ infixr 0 .$+ f .$ xs+ = parensIf (needsParens ctx f)+ $ hang shiftwidth (sep (manifest f : xs))++ ppN :: String -> Operator+ ppN = confOperator config pacc++ ppA :: acc aenv a -> Adoc+ ppA = prettyAcc config app aenv++ ppAF :: PreOpenAfun acc aenv f -> Adoc+ ppAF = parens . prettyPreOpenAfun config prettyAcc aenv++ ppE :: Exp aenv t -> Adoc+ ppE = prettyOpenExp app Empty aenv++ ppF :: Fun aenv t -> Adoc+ ppF = parens . prettyOpenFun Empty aenv++ ppB :: forall sh e.+ TypeR e+ -> Boundary aenv (Array sh e)+ -> Adoc+ ppB _ Clamp = "clamp"+ ppB _ Mirror = "mirror"+ ppB _ Wrap = "wrap"+ ppB tp (Constant e) = prettyConst tp e+ ppB _ (Function f) = ppF f++ ppD :: String -> AST.Direction -> String -> Operator+ ppD f AST.LeftToRight k = ppN (f <> "l" <> k)+ ppD f AST.RightToLeft k = ppN (f <> "r" <> k)+++prettyAlet+ :: forall acc aenv arrs.+ PrettyConfig acc+ -> Context+ -> PrettyAcc acc+ -> ExtractAcc acc+ -> Val aenv+ -> PreOpenAcc acc aenv arrs+ -> Adoc+prettyAlet config ctx prettyAcc extractAcc aenv0+ = parensIf (ctxPrecedence ctx > 0)+ . align . wrap . collect aenv0+ where+ collect :: Val aenv' -> PreOpenAcc acc aenv' a -> ([Adoc], Adoc)+ collect aenv =+ \case+ Alet lhs a1 a2 ->+ let (aenv', v) = prettyALhs False aenv lhs+ a1' = ppA aenv a1+ bnd | isAlet a1 = nest shiftwidth (vsep [v <+> equals, a1'])+ | otherwise = v <+> align (equals <+> a1')+ (bnds, body) = collect aenv' (extractAcc a2)+ in+ (bnd:bnds, body)+ --+ next -> ([], prettyPreOpenAcc config context0 prettyAcc extractAcc aenv next)++ isAlet :: acc aenv' a -> Bool+ isAlet (extractAcc -> Alet{}) = True+ isAlet _ = False++ ppA :: Val aenv' -> acc aenv' a -> Adoc+ ppA = prettyAcc config context0++ wrap :: ([Adoc], Adoc) -> Adoc+ wrap ([], body) = body -- shouldn't happen!+ wrap ([b], body)+ = sep [ nest shiftwidth (sep [let_, b]), in_, body ]+ wrap (bnds, body)+ = vsep [ nest shiftwidth (vsep (let_:bnds))+ , in_+ , body+ ]++prettyAtuple+ :: forall acc aenv arrs.+ PrettyConfig acc+ -> Context+ -> PrettyAcc acc+ -> ExtractAcc acc+ -> Val aenv+ -> PreOpenAcc acc aenv arrs+ -> Adoc+prettyAtuple config ctx prettyAcc extractAcc aenv0 acc = case collect acc of+ Nothing -> align $ ppPair acc+ Just tup ->+ case tup of+ [] -> "()"+ _ -> align $ parensIf (ctxPrecedence ctx > 0) ("T" <> pretty (length tup) <+> align (sep tup))+ where+ ppPair :: PreOpenAcc acc aenv arrs' -> Adoc+ ppPair (Apair a1 a2) =+ "(" <> ppPair (extractAcc a1) <> "," <+> prettyAcc config context0 aenv0 a2 <> ")"+ ppPair a = prettyPreOpenAcc config context0 prettyAcc extractAcc aenv0 a++ collect :: PreOpenAcc acc aenv arrs' -> Maybe [Adoc]+ collect Anil = Just []+ collect (Apair a1 a2)+ | Just tup <- collect $ extractAcc a1+ = Just $ tup ++ [prettyAcc config app aenv0 a2]+ collect _ = Nothing++-- TODO: Should we also print the types of the declared variables? And the types of wildcards?+prettyALhs :: Bool -> Val env -> LeftHandSide s arrs env env' -> (Val env', Adoc)+prettyALhs requiresParens = prettyLhs requiresParens 'a'++prettyELhs :: Bool -> Val env -> LeftHandSide s arrs env env' -> (Val env', Adoc)+prettyELhs requiresParens = prettyLhs requiresParens 'x'++prettyLhs :: forall s env env' arrs. Bool -> Char -> Val env -> LeftHandSide s arrs env env' -> (Val env', Adoc)+prettyLhs requiresParens x env0 lhs = case collect lhs of+ Nothing -> ppPair lhs+ Just (env1, tup) ->+ case tup of+ [] -> (env1, "()")+ _ -> (env1, parensIf requiresParens (pretty 'T' <> pretty (length tup) <+> align (sep tup)))+ where+ ppPair :: LeftHandSide s arrs' env env'' -> (Val env'', Adoc)+ ppPair LeftHandSideUnit = (env0, "()")+ ppPair LeftHandSideWildcard{} = (env0, "_")+ ppPair LeftHandSideSingle{} = (env0 `Push` v, v)+ where+ v = pretty x <> pretty (sizeEnv env0)+ ppPair (LeftHandSidePair a b) = (env2, tupled [doc1, doc2])+ where+ (env1, doc1) = ppPair a+ (env2, doc2) = prettyLhs False x env1 b++ collect :: LeftHandSide s arrs' env env'' -> Maybe (Val env'', [Adoc])+ collect (LeftHandSidePair l1 l2)+ | Just (env1, tup ) <- collect l1+ , (env2, doc2) <- prettyLhs True x env1 l2 = Just (env2, tup ++ [doc2])+ collect (LeftHandSideWildcard TupRunit) = Just (env0, [])+ collect _ = Nothing++prettyArray :: ArrayR (Array sh e) -> Array sh e -> Adoc+prettyArray aR@(ArrayR _ eR) = parens . fromString . showArray (showsElt eR) aR+++-- Scalar expressions+-- ------------------++prettyFun :: Val aenv -> Fun aenv f -> Adoc+prettyFun = prettyOpenFun Empty++prettyExp :: Val aenv -> Exp aenv t -> Adoc+prettyExp = prettyOpenExp context0 Empty++prettyOpenFun+ :: forall env aenv f.+ Val env+ -> Val aenv+ -> OpenFun env aenv f+ -> Adoc+prettyOpenFun env0 aenv = next (pretty '\\') env0+ where+ next :: Adoc -> Val env' -> OpenFun env' aenv f' -> Adoc+ next vs env (Body body)+ -- PrimApp f x <- body+ -- , op <- primOperator f+ -- , isInfix op+ -- , Tuple (NilTup `SnocTup` a `SnocTup` b) <- x+ -- , Var (SuccIdx ZeroIdx) <- a+ -- , Var ZeroIdx <- b+ -- = opName op -- surrounding context will add parens+ --+ = hang shiftwidth (sep [ vs <> "->"+ , prettyOpenExp context0 env aenv body])+ next vs env (Lam lhs lam) =+ let (env', lhs') = prettyELhs True env lhs+ in next (vs <> lhs' <> space) env' lam++prettyOpenExp+ :: forall env aenv t.+ Context+ -> Val env+ -> Val aenv+ -> OpenExp env aenv t+ -> Adoc+prettyOpenExp ctx env aenv exp =+ case exp of+ Evar (Var _ idx) -> prj idx env+ Let{} -> prettyLet ctx env aenv exp+ PrimApp f x+ | a `Pair` b <- x -> ppF2 op (ppE a) (ppE b)+ | otherwise -> ppF1 op' (ppE x)+ where+ op = primOperator f+ op' = isInfix op ? (Operator (parens (opName op)) App L 10, op)+ --+ PrimConst c -> prettyPrimConst c+ Const tp c -> prettyConst (TupRsingle tp) c+ Pair{} -> prettyTuple ctx env aenv exp+ Nil -> "()"+ VecPack _ e -> ppF1 "pack" (ppE e)+ VecUnpack _ e -> ppF1 "unpack" (ppE e)+ Case x xs d -> prettyCase env aenv x xs d+ Cond p t e -> flatAlt multi single+ where+ p' = ppE p context0+ t' = ppE t context0+ e' = ppE e context0+ --+ single = parensIf (needsParens ctx (Operator "?:" Infix N 0))+ $ sep [ p', pretty '?', t', pretty ':', e' ]+ multi = hang 3+ $ vsep [ if_ <+> p'+ , hang shiftwidth (sep [ then_, t' ])+ , hang shiftwidth (sep [ else_, e' ]) ]+ --+ IndexSlice _ slix sh -> ppF2 "indexSlice" (ppE slix) (ppE sh)+ IndexFull _ slix sl -> ppF2 "indexFull" (ppE slix) (ppE sl)+ ToIndex _ sh ix -> ppF2 "toIndex" (ppE sh) (ppE ix)+ FromIndex _ sh ix -> ppF2 "fromIndex" (ppE sh) (ppE ix)+ While p f x -> ppF3 "while" (ppF p) (ppF f) (ppE x)+ Foreign _ ff _ e -> ppF2 "foreign" (\_ -> pretty (strForeign ff)) (ppE e)+ Shape arr -> ppF1 "shape" (ppA arr)+ ShapeSize _ sh -> ppF1 "shapeSize" (ppE sh)+ Index arr ix -> ppF2 (Operator (pretty '!') Infix L 9) (ppA arr) (ppE ix)+ LinearIndex arr ix -> ppF2 (Operator "!!" Infix L 9) (ppA arr) (ppE ix)+ Coerce _ tp x -> ppF1 (Operator (withTypeRep tp "coerce") App L 10) (ppE x)+ Undef tp -> withTypeRep tp "undef"++ where+ ppE :: OpenExp env aenv e -> Context -> Adoc+ ppE e c = prettyOpenExp c env aenv e++ ppA :: ArrayVar aenv a -> Context -> Adoc+ ppA acc _ = prettyArrayVar aenv acc++ ppF :: OpenFun env aenv f -> Context -> Adoc+ ppF f _ = parens $ prettyOpenFun env aenv f++ ppF1 :: Operator -> (Context -> Adoc) -> Adoc+ ppF1 op x+ = parensIf (needsParens ctx op)+ $ combine [ opName op, x ctx' ]+ where+ ctx' = isPrefix op ? (arg op R, app)+ combine = isPrefix op ? (cat, hang 2 . sep)++ ppF2 :: Operator -> (Context -> Adoc) -> (Context -> Adoc) -> Adoc+ ppF2 op x y+ = parensIf (needsParens ctx op)+ $ if isInfix op+ then sep [ x (arg op L), group (sep [opName op, y (arg op R)]) ]+ else hang 2 $ sep [ opName op, x app, y app ]++ ppF3 :: Operator -> (Context -> Adoc) -> (Context -> Adoc) -> (Context -> Adoc) -> Adoc+ ppF3 op x y z+ = parensIf (needsParens ctx op)+ $ hang 2+ $ sep [ opName op, x app, y app, z app ]++ withTypeRep :: ScalarType t -> Adoc -> Adoc+ withTypeRep t op = op <+> "@" <> pretty (show t)++prettyArrayVar+ :: forall aenv a.+ Val aenv+ -> ArrayVar aenv a+ -> Adoc+prettyArrayVar aenv (Var _ idx) = prj idx aenv++prettyLet+ :: forall env aenv t.+ Context+ -> Val env+ -> Val aenv+ -> OpenExp env aenv t+ -> Adoc+prettyLet ctx env0 aenv+ = parensIf (ctxPrecedence ctx > 0)+ . align . wrap . collect env0+ where+ collect :: Val env' -> OpenExp env' aenv e -> ([Adoc], Adoc)+ collect env =+ \case+ Let lhs e1 e2 ->+ let (env', v) = prettyELhs False env lhs+ e1' = ppE env e1+ bnd | isLet e1 = nest shiftwidth (vsep [v <+> equals, e1'])+ | otherwise = v <+> align (equals <+> e1')+ (bnds, body) = collect env' e2+ in+ (bnd:bnds, body)+ --+ next -> ([], ppE env next)++ isLet :: OpenExp env' aenv t' -> Bool+ isLet Let{} = True+ isLet _ = False++ ppE :: Val env' -> OpenExp env' aenv t' -> Adoc+ ppE env = prettyOpenExp context0 env aenv++ wrap :: ([Adoc], Adoc) -> Adoc+ wrap ([], body) = body -- shouldn't happen!+ wrap ([b], body)+ = sep [ nest shiftwidth (sep [let_, b]), in_, body ]+ wrap (bnds, body)+ = vsep [ nest shiftwidth (vsep [let_, sepBy (flatAlt "" " ; ") bnds])+ , in_+ , body+ ]++ sepBy :: Adoc -> [Adoc] -> Adoc+ sepBy = encloseSep mempty mempty++prettyTuple+ :: forall env aenv t.+ Context+ -> Val env+ -> Val aenv+ -> OpenExp env aenv t+ -> Adoc+prettyTuple ctx env aenv exp = case collect exp of+ Nothing -> align $ ppPair exp+ Just tup ->+ case tup of+ [] -> "()"+ _ -> align $ parensIf (ctxPrecedence ctx > 0) ("T" <> pretty (length tup) <+> align (sep tup))+ where+ ppPair :: OpenExp env aenv t' -> Adoc+ ppPair (Pair e1 e2) = "(" <> ppPair e1 <> "," <+> prettyOpenExp context0 env aenv e2 <> ")"+ ppPair e = prettyOpenExp context0 env aenv e++ collect :: OpenExp env aenv t' -> Maybe [Adoc]+ collect Nil = Just []+ collect (Pair e1 e2)+ | Just tup <- collect e1 = Just $ tup ++ [prettyOpenExp app env aenv e2]+ collect _ = Nothing++prettyCase+ :: Val env+ -> Val aenv+ -> OpenExp env aenv a+ -> [(TAG, OpenExp env aenv b)]+ -> Maybe (OpenExp env aenv b)+ -> Adoc+prettyCase env aenv x xs def+ = hang shiftwidth+ $ vsep [ case_ <+> x' <+> of_+ , flatAlt (vcat xs') (encloseSep "{ " " }" "; " xs')+ ]+ where+ x' = prettyOpenExp context0 env aenv x+ xs' = map (\(t,e) -> pretty t <+> "->" <+> prettyOpenExp context0 env aenv e) xs+ ++ case def of+ Nothing -> []+ Just d -> ["_" <+> "->" <+> prettyOpenExp context0 env aenv d]++{-++prettyAtuple+ :: forall acc aenv arrs.+ PrettyAcc acc+ -> ExtractAcc acc+ -> Val aenv+ -> PreOpenAcc acc aenv arrs+ -> Adoc+prettyAtuple prettyAcc extractAcc aenv0 acc = case collect acc of+ Just tup -> align $ "T" <> pretty (length tup) <+> sep tup+ Nothing -> align $ ppPair acc+ where+ ppPair :: PreOpenAcc acc aenv arrs' -> Adoc+ ppPair (Apair a1 a2) = "(" <> ppPair (extractAcc a1) <> "," <+> prettyAcc context0 aenv0 a2 <> ")"+ ppPair a = prettyPreOpenAcc context0 prettyAcc extractAcc aenv0 a++ collect :: PreOpenAcc acc aenv arrs' -> Maybe [Adoc]+ collect Anil = Just []+ collect (Apair a1 a2)+ | Just tup <- collect $ extractAcc a1+ = Just $ tup ++ [prettyAcc app aenv0 a2]+ collect _ = Nothing+-}++prettyConst :: TypeR e -> e -> Adoc+prettyConst tp x =+ let y = showElt tp x+ in parensIf (any isSpace y) (pretty y)++prettyPrimConst :: PrimConst a -> Adoc+prettyPrimConst PrimMinBound{} = "minBound"+prettyPrimConst PrimMaxBound{} = "maxBound"+prettyPrimConst PrimPi{} = "pi"+++-- Primitive operators+-- -------------------+--+-- The core of the pretty printer is how to correctly handle precedence,+-- associativity, and fixity of the primitive scalar operators.+--++data Direction = L | N | R+ deriving Eq++data Fixity = App | Infix | Prefix+ deriving Eq++type Precedence = Int+type Associativity = Direction++data Context = Context+ { ctxAssociativity :: Associativity+ , ctxPosition :: Direction+ , ctxPrecedence :: Precedence+ }++data Operator = Operator+ { opName :: Adoc+ , opFixity :: Fixity+ , opAssociativity :: Associativity+ , opPrecedence :: Precedence+ }++instance IsString Operator where+ fromString s = Operator (fromString s) App L 10++needsParens :: Context -> Operator -> Bool+needsParens Context{..} Operator{..}+ | ctxPrecedence < opPrecedence = False+ | ctxPrecedence > opPrecedence = True+ | ctxAssociativity /= opAssociativity = True+ | otherwise = ctxPosition /= opAssociativity++context0 :: Context+context0 = Context N N 0++app :: Context+app = Context L N 10++arg :: Operator -> Direction -> Context+arg Operator{..} side = Context opAssociativity side opPrecedence++isPrefix :: Operator -> Bool+isPrefix Operator{..} = opFixity == Prefix++isInfix :: Operator -> Bool+isInfix Operator{..} = opFixity == Infix++primOperator :: PrimFun a -> Operator+primOperator PrimAdd{} = Operator (pretty '+') Infix L 6+primOperator PrimSub{} = Operator (pretty '-') Infix L 6+primOperator PrimMul{} = Operator (pretty '*') Infix L 7+primOperator PrimNeg{} = Operator (pretty '-') Prefix L 6 -- Haskell's only prefix operator+primOperator PrimAbs{} = Operator "abs" App L 10+primOperator PrimSig{} = Operator "signum" App L 10+primOperator PrimQuot{} = Operator "quot" App L 10+primOperator PrimRem{} = Operator "rem" App L 10+primOperator PrimQuotRem{} = Operator "quotRem" App L 10+primOperator PrimIDiv{} = Operator "div" App L 10+primOperator PrimMod{} = Operator "mod" App L 10+primOperator PrimDivMod{} = Operator "divMod" App L 10+primOperator PrimBAnd{} = Operator ".&." Infix L 7+primOperator PrimBOr{} = Operator ".|." Infix L 5+primOperator PrimBXor{} = Operator "xor" App L 10+primOperator PrimBNot{} = Operator "complement" App L 10+primOperator PrimBShiftL{} = Operator "shiftL" App L 10+primOperator PrimBShiftR{} = Operator "shiftR" App L 10+primOperator PrimBRotateL{} = Operator "rotateL" App L 10+primOperator PrimBRotateR{} = Operator "rotateR" App L 10+primOperator PrimPopCount{} = Operator "popCount" App L 10+primOperator PrimCountLeadingZeros{} = Operator "countLeadingZeros" App L 10+primOperator PrimCountTrailingZeros{} = Operator "countTrailingZeros" App L 10+primOperator PrimFDiv{} = Operator (pretty '/') Infix L 7+primOperator PrimRecip{} = Operator "recip" App L 10+primOperator PrimSin{} = Operator "sin" App L 10+primOperator PrimCos{} = Operator "cos" App L 10+primOperator PrimTan{} = Operator "tan" App L 10+primOperator PrimAsin{} = Operator "asin" App L 10+primOperator PrimAcos{} = Operator "acos" App L 10+primOperator PrimAtan{} = Operator "atan" App L 10+primOperator PrimSinh{} = Operator "sinh" App L 10+primOperator PrimCosh{} = Operator "cosh" App L 10+primOperator PrimTanh{} = Operator "tanh" App L 10+primOperator PrimAsinh{} = Operator "asinh" App L 10+primOperator PrimAcosh{} = Operator "acosh" App L 10+primOperator PrimAtanh{} = Operator "atanh" App L 10+primOperator PrimExpFloating{} = Operator "exp" App L 10+primOperator PrimSqrt{} = Operator "sqrt" App L 10+primOperator PrimLog{} = Operator "log" App L 10+primOperator PrimFPow{} = Operator "**" Infix R 8+primOperator PrimLogBase{} = Operator "logBase" App L 10+primOperator PrimTruncate{} = Operator "truncate" App L 10+primOperator PrimRound{} = Operator "round" App L 10+primOperator PrimFloor{} = Operator "floor" App L 10+primOperator PrimCeiling{} = Operator "ceiling" App L 10+primOperator PrimAtan2{} = Operator "atan2" App L 10+primOperator PrimIsNaN{} = Operator "isNaN" App L 10+primOperator PrimIsInfinite{} = Operator "isInfinite" App L 10+primOperator PrimLt{} = Operator "<" Infix N 4+primOperator PrimGt{} = Operator ">" Infix N 4+primOperator PrimLtEq{} = Operator "<=" Infix N 4+primOperator PrimGtEq{} = Operator ">=" Infix N 4+primOperator PrimEq{} = Operator "==" Infix N 4+primOperator PrimNEq{} = Operator "/=" Infix N 4+primOperator PrimMax{} = Operator "max" App L 10+primOperator PrimMin{} = Operator "min" App L 10+primOperator PrimLAnd = Operator "&&" Infix R 3+primOperator PrimLOr = Operator "||" Infix R 2+primOperator PrimLNot = Operator "not" App L 10+primOperator PrimFromIntegral{} = Operator "fromIntegral" App L 10+primOperator PrimToFloating{} = Operator "toFloating" App L 10+++-- Environments+-- ------------++data Val env where+ Empty :: Val ()+ Push :: Val env -> Adoc -> Val (env, t)++class PrettyEnv env where+ prettyEnv :: Adoc -> Val env++instance PrettyEnv () where+ prettyEnv _ = Empty++instance PrettyEnv env => PrettyEnv (env, t) where+ prettyEnv v =+ let env = prettyEnv v :: Val env+ x = v <> pretty (sizeEnv env)+ in+ env `Push` x++sizeEnv :: Val env -> Int+sizeEnv Empty = 0+sizeEnv (Push env _) = 1 + sizeEnv env++prj :: Idx env t -> Val env -> Adoc+prj ZeroIdx (Push _ v) = v+prj (SuccIdx ix) (Push env _) = prj ix env+++-- Utilities+-- ---------++shiftwidth :: Int+shiftwidth = 2++infix 0 ?+(?) :: Bool -> (a, a) -> a+True ? (t,_) = t+False ? (_,f) = f++parensIf :: Bool -> Doc ann -> Doc ann+parensIf True = group . parens . align+parensIf False = id+
+ src/Data/Array/Accelerate/Representation/Array.hs view
@@ -0,0 +1,323 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Representation.Array+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Representation.Array+ where++import Data.Array.Accelerate.Array.Data+import Data.Array.Accelerate.Error+import Data.Array.Accelerate.Type+import Data.Array.Accelerate.Representation.Elt+import Data.Array.Accelerate.Representation.Shape hiding ( zip )+import Data.Array.Accelerate.Representation.Type++import Data.List ( intersperse )+import Data.Maybe ( isJust )+import Formatting+import Language.Haskell.TH.Extra+import System.IO.Unsafe+import Text.Show ( showListWith )+import Prelude hiding ( (!!) )+import qualified Data.Vector.Unboxed as U+++-- | Array data type, where the type arguments regard the representation+-- types of the shape and elements.+--+data Array sh e where+ Array :: sh -- extent of dimensions = shape+ -> ArrayData e -- array payload+ -> Array sh e++-- | Segment descriptor (vector of segment lengths).+--+-- To represent nested one-dimensional arrays, we use a flat array of data+-- values in conjunction with a /segment descriptor/, which stores the lengths+-- of the subarrays.+--+type Segments = Vector++type Scalar = Array DIM0 -- ^ A singleton array with one element+type Vector = Array DIM1 -- ^ A one-dimensional array+type Matrix = Array DIM2 -- ^ A two-dimensional array++-- | Type witnesses shape and data layout of an array+--+data ArrayR a where+ ArrayR :: { arrayRshape :: ShapeR sh+ , arrayRtype :: TypeR e+ }+ -> ArrayR (Array sh e)++type ArraysR = TupR ArrayR++instance Show (ArrayR a) where+ show (ArrayR shR eR) = "Array DIM" ++ show (rank shR) ++ " " ++ show eR++formatArrayR :: Format r (ArrayR a -> r)+formatArrayR = later $ \case+ ArrayR shR eR -> bformat ("Array DIM" % int % " " % formatTypeR) (rank shR) eR++formatArraysR :: Format r (TupR ArrayR e -> r)+formatArraysR = later $ \case+ TupRunit -> "()"+ TupRsingle aR -> bformat formatArrayR aR+ TupRpair aR1 aR2 -> bformat (parenthesised (formatArraysR % "," % formatArraysR)) aR1 aR2++showArraysR :: ArraysR a -> ShowS+showArraysR = shows++arraysRarray :: ShapeR sh -> TypeR e -> ArraysR (Array sh e)+arraysRarray shR eR = TupRsingle (ArrayR shR eR)++arraysRpair :: ArrayR a -> ArrayR b -> ArraysR (((), a), b)+arraysRpair a b = TupRunit `TupRpair` TupRsingle a `TupRpair` TupRsingle b++-- | Creates a new, uninitialized Accelerate array.+--+allocateArray :: ArrayR (Array sh e) -> sh -> IO (Array sh e)+allocateArray (ArrayR shR eR) sh = do+ adata <- newArrayData eR (size shR sh)+ return $! Array sh adata++-- | Create an array from its representation function, applied at each+-- index of the array.+--+fromFunction :: ArrayR (Array sh e) -> sh -> (sh -> e) -> Array sh e+fromFunction repr sh f = unsafePerformIO $! fromFunctionM repr sh (return . f)++-- | Create an array using a monadic function applied at each index.+--+-- @since 1.2.0.0+--+fromFunctionM :: ArrayR (Array sh e) -> sh -> (sh -> IO e) -> IO (Array sh e)+fromFunctionM (ArrayR shR eR) sh f = do+ let !n = size shR sh+ arr <- newArrayData eR n+ --+ let write !i+ | i >= n = return ()+ | otherwise = do+ v <- f (fromIndex shR sh i)+ writeArrayData eR arr i v+ write (i+1)+ --+ write 0+ return $! arr `seq` Array sh arr+++-- | Convert a list into an Accelerate 'Array' in dense row-major order.+--+fromList :: forall sh e. ArrayR (Array sh e) -> sh -> [e] -> Array sh e+fromList (ArrayR shR eR) sh xs = adata `seq` Array sh adata+ where+ -- Assume the array is in dense row-major order. This is safe because+ -- otherwise backends would not be able to directly memcpy.+ --+ !n = size shR sh+ (adata, _) = runArrayData @e $ do+ arr <- newArrayData eR n+ let go !i _ | i >= n = return ()+ go !i (v:vs) = writeArrayData eR arr i v >> go (i+1) vs+ go _ [] = error "Data.Array.Accelerate.fromList: not enough input data"+ --+ go 0 xs+ return (arr, undefined)+++-- | Convert an accelerated 'Array' to a list in row-major order.+--+toList :: ArrayR (Array sh e) -> Array sh e -> [e]+toList (ArrayR shR eR) (Array sh adata) = go 0+ where+ -- Assume underling array is in row-major order. This is safe because+ -- otherwise backends would not be able to directly memcpy.+ --+ !n = size shR sh+ go !i | i >= n = []+ | otherwise = indexArrayData eR adata i : go (i+1)++concatVectors :: forall e. TypeR e -> [Vector e] -> Vector e+concatVectors tR vs = adata `seq` Array ((), len) adata+ where+ offsets = scanl (+) 0 (map (size dim1 . shape) vs)+ len = last offsets+ (adata, _) = runArrayData @e $ do+ arr <- newArrayData tR len+ sequence_ [ writeArrayData tR arr (i + k) (indexArrayData tR ad i)+ | (Array ((), n) ad, k) <- vs `zip` offsets+ , i <- [0 .. n - 1] ]+ return (arr, undefined)++shape :: Array sh e -> sh+shape (Array sh _) = sh++reshape :: HasCallStack => ShapeR sh -> sh -> ShapeR sh' -> Array sh' e -> Array sh e+reshape shR sh shR' (Array sh' adata)+ = boundsCheck "shape mismatch" (size shR sh == size shR' sh')+ $ Array sh adata++(!) :: (ArrayR (Array sh e), Array sh e) -> sh -> e+(!) = uncurry indexArray++(!!) :: (TypeR e, Array sh e) -> Int -> e+(!!) = uncurry linearIndexArray++indexArray :: ArrayR (Array sh e) -> Array sh e -> sh -> e+indexArray (ArrayR shR adR) (Array sh adata) ix = indexArrayData adR adata (toIndex shR sh ix)++linearIndexArray :: TypeR e -> Array sh e -> Int -> e+linearIndexArray adR (Array _ adata) = indexArrayData adR adata++showArray :: (e -> ShowS) -> ArrayR (Array sh e) -> Array sh e -> String+showArray f arrR@(ArrayR shR _) arr@(Array sh _) = case shR of+ ShapeRz -> "Scalar Z " ++ xs+ ShapeRsnoc ShapeRz -> "Vector (" ++ shapeString ++ ") " ++ xs+ ShapeRsnoc (ShapeRsnoc ShapeRz) -> "Matrix (" ++ shapeString ++ ") " ++ showMatrix f arrR arr+ _ -> "Array (" ++ shapeString ++ ") " ++ xs+ where+ shapeString = showShape shR sh+ xs = showListWith f (toList arrR arr) ""++showArrayShort :: Int -> (e -> ShowS) -> ArrayR (Array sh e) -> Array sh e -> String+showArrayShort n f arrR arr = '[' : go 0 (toList arrR arr)+ where+ go _ [] = "]"+ go i (x:xs)+ | i >= n = " ..]"+ | otherwise = ',' : f x (go (i+1) xs)++-- TODO: Make special formatting optional? It is more difficult to+-- copy/paste the result, for example. Also it does not look good if the+-- matrix row does not fit on a single line.+--+showMatrix :: (e -> ShowS) -> ArrayR (Array DIM2 e) -> Array DIM2 e -> String+showMatrix f (ArrayR _ arrR) arr@(Array sh _)+ | rows * cols == 0 = "[]"+ | otherwise = "\n [" ++ ppMat 0 0+ where+ (((), rows), cols) = sh+ lengths = U.generate (rows*cols) (\i -> length (f (linearIndexArray arrR arr i) ""))+ widths = U.generate cols (\c -> U.maximum (U.generate rows (\r -> lengths U.! (r*cols+c))))+ --+ ppMat :: Int -> Int -> String+ ppMat !r !c | c >= cols = ppMat (r+1) 0+ ppMat !r !c =+ let+ !i = r*cols+c+ !l = lengths U.! i+ !w = widths U.! c+ !pad = 1+ cell = replicate (w-l+pad) ' ' ++ f (linearIndexArray arrR arr i) ""+ --+ before+ | r > 0 && c == 0 = "\n "+ | otherwise = ""+ --+ after+ | r >= rows-1 && c >= cols-1 = "]"+ | otherwise = ',' : ppMat r (c+1)+ in+ before ++ cell ++ after++showArrays :: ArraysR arrs -> arrs -> String+showArrays repr arrs = showsArrays repr arrs ""++showsArrays :: ArraysR arrs -> arrs -> ShowS+showsArrays repr arrs = go 0 repr arrs+ where+ go :: Int -> ArraysR a -> a -> ShowS+ go _ TupRunit ()+ = showString "()"+ go level repr' arrs'+ | Just tuple <- extractTuple repr' arrs'+ = let+ constructor = 'T' : show (length tuple)+ level' = level + length constructor + 1+ content = intersperse (('\n' :) . indent level') $ map ($ level') tuple+ in+ showString constructor . (' ' :) . foldr (flip (.)) id content+ go level (TupRpair repr1 repr2) (arrs1, arrs2)+ = showString "( " . go (level + 2) repr1 arrs1 . showString "\n"+ . indent level . showString ", " . go (level + 1) repr2 arrs2 . showString "\n"+ . indent level . showString ")"+ go level (TupRsingle r@ArrayR{}) arr+ = showString $ indents level $ showArray (showsElt $ arrayRtype r) r arr++ indent :: Int -> ShowS+ indent 0 str = str+ indent n str = ' ' : indent (n - 1) str++ indents :: Int -> String -> String+ indents _ [] = []+ indents level ('\n' : xs) = '\n' : indent level (indents level xs)+ indents level (x : xs) = x : indents level xs++ -- Tries to extract the representation of a tuple.+ -- Tuples are represented as a snoc-list built with+ -- pairs and nil.+ -- The tuple is returned a list of pretty-printed+ -- elements, in reverse order.+ extractTuple :: ArraysR a -> a -> Maybe [Int -> ShowS]+ extractTuple TupRunit () = Just []+ extractTuple (TupRpair rs r) (as, a) = (current :) <$> extractTuple rs as+ where+ current level+ -- Avoid duplicate parentheses for () and pairs which don't form a tuple+ | needsParens r a = showString "( " . go (level + 2) r a . showString " )"+ | otherwise = go level r a+ extractTuple _ _ = Nothing++ needsParens :: ArraysR a -> a -> Bool+ needsParens TupRunit _ = False+ needsParens repr'@(TupRpair _ _) as = isJust $ extractTuple repr' as+ needsParens _ _ = True++reduceRank :: ArrayR (Array (sh, Int) e) -> ArrayR (Array sh e)+reduceRank (ArrayR (ShapeRsnoc shR) aeR) = ArrayR shR aeR++rnfArray :: ArrayR a -> a -> ()+rnfArray (ArrayR shR adR) (Array sh ad) = rnfShape shR sh `seq` rnfArrayData adR ad++rnfArrayR :: ArrayR arr -> ()+rnfArrayR (ArrayR shR tR) = rnfShapeR shR `seq` rnfTupR rnfScalarType tR++rnfArraysR :: ArraysR arrs -> arrs -> ()+rnfArraysR TupRunit () = ()+rnfArraysR (TupRsingle arrR) arr = rnfArray arrR arr+rnfArraysR (TupRpair aR1 aR2) (a1,a2) = rnfArraysR aR1 a1 `seq` rnfArraysR aR2 a2++liftArrayR :: ArrayR a -> CodeQ (ArrayR a)+liftArrayR (ArrayR shR tR) = [|| ArrayR $$(liftShapeR shR) $$(liftTypeR tR) ||]++liftArraysR :: ArraysR arrs -> CodeQ (ArraysR arrs)+liftArraysR TupRunit = [|| TupRunit ||]+liftArraysR (TupRsingle repr) = [|| TupRsingle $$(liftArrayR repr) ||]+liftArraysR (TupRpair a b) = [|| TupRpair $$(liftArraysR a) $$(liftArraysR b) ||]++liftArray :: forall sh e. ArrayR (Array sh e) -> Array sh e -> CodeQ (Array sh e)+liftArray (ArrayR shR adR) (Array sh adata) =+ [|| Array $$(liftElt (shapeType shR) sh) $$(liftArrayData sz adR adata) ||] `at` [t| Array $(liftTypeQ (shapeType shR)) $(liftTypeQ adR) |]+ where+ sz :: Int+ sz = size shR sh++ at :: CodeQ t -> Q Type -> CodeQ t+ at e t = unsafeCodeCoerce $ sigE (unTypeCode e) t+
+ src/Data/Array/Accelerate/Representation/Elt.hs view
@@ -0,0 +1,160 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TupleSections #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Representation.Elt+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Representation.Elt+ where++import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Type+import Data.Primitive.Vec++import Control.Monad.ST+import Data.List ( intercalate )+import Data.Primitive.ByteArray+import Foreign.Storable+import Language.Haskell.TH.Extra+++undefElt :: TypeR t -> t+undefElt = tuple+ where+ tuple :: TypeR t -> t+ tuple TupRunit = ()+ tuple (TupRpair ta tb) = (tuple ta, tuple tb)+ tuple (TupRsingle t) = scalar t++ scalar :: ScalarType t -> t+ scalar (SingleScalarType t) = single t+ scalar (VectorScalarType t) = vector t++ vector :: VectorType t -> t+ vector (VectorType n t) = runST $ do+ mba <- newByteArray (n * bytesElt (TupRsingle (SingleScalarType t)))+ ByteArray ba# <- unsafeFreezeByteArray mba+ return (Vec ba#)++ single :: SingleType t -> t+ single (NumSingleType t) = num t++ num :: NumType t -> t+ num (IntegralNumType t) = integral t+ num (FloatingNumType t) = floating t++ integral :: IntegralType t -> t+ integral TypeInt = 0+ integral TypeInt8 = 0+ integral TypeInt16 = 0+ integral TypeInt32 = 0+ integral TypeInt64 = 0+ integral TypeWord = 0+ integral TypeWord8 = 0+ integral TypeWord16 = 0+ integral TypeWord32 = 0+ integral TypeWord64 = 0++ floating :: FloatingType t -> t+ floating TypeHalf = 0+ floating TypeFloat = 0+ floating TypeDouble = 0++bytesElt :: TypeR e -> Int+bytesElt = tuple+ where+ tuple :: TypeR t -> Int+ tuple TupRunit = 0+ tuple (TupRpair ta tb) = tuple ta + tuple tb+ tuple (TupRsingle t) = scalar t++ scalar :: ScalarType t -> Int+ scalar (SingleScalarType t) = single t+ scalar (VectorScalarType t) = vector t++ vector :: VectorType t -> Int+ vector (VectorType n t) = n * single t++ single :: SingleType t -> Int+ single (NumSingleType t) = num t++ num :: NumType t -> Int+ num (IntegralNumType t) = integral t+ num (FloatingNumType t) = floating t++ integral :: IntegralType t -> Int+ integral TypeInt = sizeOf (undefined::Int)+ integral TypeInt8 = 1+ integral TypeInt16 = 2+ integral TypeInt32 = 4+ integral TypeInt64 = 8+ integral TypeWord = sizeOf (undefined::Word)+ integral TypeWord8 = 1+ integral TypeWord16 = 2+ integral TypeWord32 = 4+ integral TypeWord64 = 8++ floating :: FloatingType t -> Int+ floating TypeHalf = 2+ floating TypeFloat = 4+ floating TypeDouble = 8++showElt :: TypeR e -> e -> String+showElt t v = showsElt t v ""++showsElt :: TypeR e -> e -> ShowS+showsElt = tuple+ where+ tuple :: TypeR e -> e -> ShowS+ tuple TupRunit () = showString "()"+ tuple (TupRpair t1 t2) (e1, e2) = showString "(" . tuple t1 e1 . showString ", " . tuple t2 e2 . showString ")"+ tuple (TupRsingle tp) val = scalar tp val++ scalar :: ScalarType e -> e -> ShowS+ scalar (SingleScalarType t) e = single t e+ scalar (VectorScalarType t) e = vector t e++ single :: SingleType e -> e -> ShowS+ single (NumSingleType t) = num t++ num :: NumType e -> e -> ShowS+ num (IntegralNumType t) = integral t+ num (FloatingNumType t) = floating t++ integral :: IntegralType e -> e -> ShowS+ integral TypeInt = shows+ integral TypeInt8 = shows+ integral TypeInt16 = shows+ integral TypeInt32 = shows+ integral TypeInt64 = shows+ integral TypeWord = shows+ integral TypeWord8 = shows+ integral TypeWord16 = shows+ integral TypeWord32 = shows+ integral TypeWord64 = shows++ floating :: FloatingType e -> e -> ShowS+ floating TypeHalf = shows+ floating TypeFloat = shows+ floating TypeDouble = shows++ vector :: VectorType (Vec n a) -> Vec n a -> ShowS+ vector (VectorType _ s) vec+ | SingleDict <- singleDict s+ = showString+ $ "<" ++ intercalate ", " ((\v -> single s v "") <$> listOfVec vec) ++ ">"++liftElt :: TypeR t -> t -> CodeQ t+liftElt TupRunit () = [|| () ||]+liftElt (TupRsingle t) x = [|| $$(liftScalar t x) ||]+liftElt (TupRpair ta tb) (a,b) = [|| ($$(liftElt ta a), $$(liftElt tb b)) ||]+
+ src/Data/Array/Accelerate/Representation/Shape.hs view
@@ -0,0 +1,197 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TupleSections #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Representation.Shape+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Representation.Shape+ where++import Data.Array.Accelerate.Error+import Data.Array.Accelerate.Type+import Data.Array.Accelerate.Representation.Type++import Language.Haskell.TH.Extra+import Prelude hiding ( zip )++import GHC.Base ( quotInt, remInt )+++-- | Shape and index representations as nested pairs+--+data ShapeR sh where+ ShapeRz :: ShapeR ()+ ShapeRsnoc :: ShapeR sh -> ShapeR (sh, Int)++-- | Nicely format a shape as a string+--+showShape :: ShapeR sh -> sh -> String+showShape shr = foldr (\sh str -> str ++ " :. " ++ show sh) "Z" . shapeToList shr++-- Synonyms for common shape types+--+type DIM0 = ()+type DIM1 = ((), Int)+type DIM2 = (((), Int), Int)+type DIM3 = ((((), Int), Int), Int)++dim0 :: ShapeR DIM0+dim0 = ShapeRz++dim1 :: ShapeR DIM1+dim1 = ShapeRsnoc dim0++dim2 :: ShapeR DIM2+dim2 = ShapeRsnoc dim1++dim3 :: ShapeR DIM3+dim3 = ShapeRsnoc dim2++-- | Number of dimensions of a /shape/ or /index/ (>= 0)+--+rank :: ShapeR sh -> Int+rank ShapeRz = 0+rank (ShapeRsnoc shr) = rank shr + 1++-- | Total number of elements in an array of the given shape+--+size :: ShapeR sh -> sh -> Int+size ShapeRz () = 1+size (ShapeRsnoc shr) (sh, sz)+ | sz <= 0 = 0+ | otherwise = size shr sh * sz++-- | The empty shape+--+empty :: ShapeR sh -> sh+empty ShapeRz = ()+empty (ShapeRsnoc shr) = (empty shr, 0)++-- | Yield the intersection of two shapes+--+intersect :: ShapeR sh -> sh -> sh -> sh+intersect = zip min++-- | Yield the union of two shapes+--+union :: ShapeR sh -> sh -> sh -> sh+union = zip max++zip :: (Int -> Int -> Int) -> ShapeR sh -> sh -> sh -> sh+zip _ ShapeRz () () = ()+zip f (ShapeRsnoc shr) (as, a) (bs, b) = (zip f shr as bs, f a b)++eq :: ShapeR sh -> sh -> sh -> Bool+eq ShapeRz () () = True+eq (ShapeRsnoc shr) (sh, i) (sh', i') = i == i' && eq shr sh sh'+++-- | Map a multi-dimensional index into one in a linear, row-major+-- representation of the array (first argument is the /shape/, second+-- argument is the /index/).+--+toIndex :: HasCallStack => ShapeR sh -> sh -> sh -> Int+toIndex ShapeRz () () = 0+toIndex (ShapeRsnoc shr) (sh, sz) (ix, i)+ = indexCheck i sz+ $ toIndex shr sh ix * sz + i++-- | Inverse of 'toIndex'+--+fromIndex :: HasCallStack => ShapeR sh -> sh -> Int -> sh+fromIndex ShapeRz () _ = ()+fromIndex (ShapeRsnoc shr) (sh, sz) i+ = (fromIndex shr sh (i `quotInt` sz), r)+ -- If we assume that the index is in range, there is no point in computing+ -- the remainder for the highest dimension since i < sz must hold.+ --+ where+ r = case shr of -- Check if rank of shr is 0+ ShapeRz -> indexCheck i sz i+ _ -> i `remInt` sz++-- | Iterate through the entire shape, applying the function in the second+-- argument; third argument combines results and fourth is an initial value+-- that is combined with the results; the index space is traversed in+-- row-major order+--+iter :: ShapeR sh -> sh -> (sh -> a) -> (a -> a -> a) -> a -> a+iter ShapeRz () f _ _ = f ()+iter (ShapeRsnoc shr) (sh, sz) f c z = iter shr sh (\ix -> iter' (ix,0) z) c z+ where+ iter' (ix,i) r | i >= sz = r+ | otherwise = iter' (ix,i+1) (r `c` f (ix,i))++-- | Variant of 'iter' without an initial value+--+iter1 :: HasCallStack => ShapeR sh -> sh -> (sh -> a) -> (a -> a -> a) -> a+iter1 ShapeRz () f _ = f ()+iter1 (ShapeRsnoc _ ) (_, 0) _ _ = boundsError "empty iteration space"+iter1 (ShapeRsnoc shr) (sh, sz) f c = iter1 shr sh (\ix -> iter1' (ix,0)) c+ where+ iter1' (ix,i) | i == sz-1 = f (ix,i)+ | otherwise = f (ix,i) `c` iter1' (ix,i+1)++-- Operations to facilitate conversion with IArray++-- | Convert a minpoint-maxpoint index into a shape+--+rangeToShape :: ShapeR sh -> (sh, sh) -> sh+rangeToShape ShapeRz ((), ()) = ()+rangeToShape (ShapeRsnoc shr) ((sh1, sz1), (sh2, sz2)) = (rangeToShape shr (sh1, sh2), sz2 - sz1 + 1)++-- | Converse of 'rangeToShape'+--+shapeToRange :: ShapeR sh -> sh -> (sh, sh)+shapeToRange ShapeRz () = ((), ())+shapeToRange (ShapeRsnoc shr) (sh, sz) = let (low, high) = shapeToRange shr sh in ((low, 0), (high, sz - 1))++-- | Convert a shape or index into its list of dimensions+--+shapeToList :: ShapeR sh -> sh -> [Int]+shapeToList ShapeRz () = []+shapeToList (ShapeRsnoc shr) (sh,sz) = sz : shapeToList shr sh++-- | Convert a list of dimensions into a shape+--+listToShape :: HasCallStack => ShapeR sh -> [Int] -> sh+listToShape shr ds =+ case listToShape' shr ds of+ Just sh -> sh+ Nothing -> error "listToShape: unable to convert list to a shape at the specified type"++-- | Attempt to convert a list of dimensions into a shape+--+listToShape' :: ShapeR sh -> [Int] -> Maybe sh+listToShape' ShapeRz [] = Just ()+listToShape' (ShapeRsnoc shr) (x:xs) = (, x) <$> listToShape' shr xs+listToShape' _ _ = Nothing++shapeType :: ShapeR sh -> TypeR sh+shapeType ShapeRz = TupRunit+shapeType (ShapeRsnoc shr) =+ shapeType shr+ `TupRpair`+ TupRsingle (SingleScalarType (NumSingleType (IntegralNumType TypeInt)))++rnfShape :: ShapeR sh -> sh -> ()+rnfShape ShapeRz () = ()+rnfShape (ShapeRsnoc shr) (sh, s) = s `seq` rnfShape shr sh++rnfShapeR :: ShapeR sh -> ()+rnfShapeR ShapeRz = ()+rnfShapeR (ShapeRsnoc shr) = rnfShapeR shr++liftShapeR :: ShapeR sh -> CodeQ (ShapeR sh)+liftShapeR ShapeRz = [|| ShapeRz ||]+liftShapeR (ShapeRsnoc sh) = [|| ShapeRsnoc $$(liftShapeR sh) ||]+
+ src/Data/Array/Accelerate/Representation/Slice.hs view
@@ -0,0 +1,112 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Representation.Slice+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Representation.Slice+ where++import Data.Array.Accelerate.Representation.Shape++import Language.Haskell.TH.Extra+++-- | Class of slice representations (which are nested pairs)+--+class Slice sl where+ type SliceShape sl -- the projected slice+ type CoSliceShape sl -- the complement of the slice+ type FullShape sl -- the combined dimension+ sliceIndex :: SliceIndex sl (SliceShape sl) (CoSliceShape sl) (FullShape sl)++instance Slice () where+ type SliceShape () = ()+ type CoSliceShape () = ()+ type FullShape () = ()+ sliceIndex = SliceNil++instance Slice sl => Slice (sl, ()) where+ type SliceShape (sl, ()) = (SliceShape sl, Int)+ type CoSliceShape (sl, ()) = CoSliceShape sl+ type FullShape (sl, ()) = (FullShape sl, Int)+ sliceIndex = SliceAll (sliceIndex @sl)++instance Slice sl => Slice (sl, Int) where+ type SliceShape (sl, Int) = SliceShape sl+ type CoSliceShape (sl, Int) = (CoSliceShape sl, Int)+ type FullShape (sl, Int) = (FullShape sl, Int)+ sliceIndex = SliceFixed (sliceIndex @sl)++-- |Generalised array index, which may index only in a subset of the dimensions+-- of a shape.+--+data SliceIndex ix slice coSlice sliceDim where+ SliceNil :: SliceIndex () () () ()+ SliceAll :: SliceIndex ix slice co dim -> SliceIndex (ix, ()) (slice, Int) co (dim, Int)+ SliceFixed :: SliceIndex ix slice co dim -> SliceIndex (ix, Int) slice (co, Int) (dim, Int)++instance Show (SliceIndex ix slice coSlice sliceDim) where+ show SliceNil = "SliceNil"+ show (SliceAll rest) = "SliceAll (" ++ show rest ++ ")"+ show (SliceFixed rest) = "SliceFixed (" ++ show rest ++ ")"++-- | Project the shape of a slice from the full shape.+--+sliceShape :: SliceIndex slix sl co dim -> dim -> sl+sliceShape SliceNil () = ()+sliceShape (SliceAll slix) (sh, n) = (sliceShape slix sh, n)+sliceShape (SliceFixed slix) (sh, _) = sliceShape slix sh++-- | Project the full shape of the slice+--+sliceDomain :: SliceIndex slix sl co dim -> slix -> sl -> dim+sliceDomain SliceNil () () = ()+sliceDomain (SliceAll slix) (slx, ()) (sl, sz) = (sliceDomain slix slx sl, sz)+sliceDomain (SliceFixed slix) (slx, sz) sl = (sliceDomain slix slx sl, sz)++sliceShapeR :: SliceIndex slix sl co dim -> ShapeR sl+sliceShapeR SliceNil = ShapeRz+sliceShapeR (SliceAll sl) = ShapeRsnoc $ sliceShapeR sl+sliceShapeR (SliceFixed sl) = sliceShapeR sl++sliceDomainR :: SliceIndex slix sl co dim -> ShapeR dim+sliceDomainR SliceNil = ShapeRz+sliceDomainR (SliceAll sl) = ShapeRsnoc $ sliceDomainR sl+sliceDomainR (SliceFixed sl) = ShapeRsnoc $ sliceDomainR sl++-- | Enumerate all slices within a given bound. The innermost dimension changes+-- most rapidly.+--+-- See 'Data.Array.Accelerate.Sugar.Slice.enumSlices' for an example.+--+enumSlices+ :: forall slix co sl dim.+ SliceIndex slix sl co dim+ -> dim+ -> [slix]+enumSlices SliceNil () = [()]+enumSlices (SliceAll sl) (sh, _) = [ (sh', ()) | sh' <- enumSlices sl sh]+enumSlices (SliceFixed sl) (sh, n) = [ (sh', i) | sh' <- enumSlices sl sh, i <- [0..n-1]]++rnfSliceIndex :: SliceIndex ix slice co sh -> ()+rnfSliceIndex SliceNil = ()+rnfSliceIndex (SliceAll sh) = rnfSliceIndex sh+rnfSliceIndex (SliceFixed sh) = rnfSliceIndex sh++liftSliceIndex :: SliceIndex ix slice co sh -> CodeQ (SliceIndex ix slice co sh)+liftSliceIndex SliceNil = [|| SliceNil ||]+liftSliceIndex (SliceAll rest) = [|| SliceAll $$(liftSliceIndex rest) ||]+liftSliceIndex (SliceFixed rest) = [|| SliceFixed $$(liftSliceIndex rest) ||]+
+ src/Data/Array/Accelerate/Representation/Stencil.hs view
@@ -0,0 +1,161 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE TemplateHaskell #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Representation.Stencil+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Representation.Stencil (++ -- ** Stencil patterns+ StencilR(..),+ stencilArrayR,+ stencilR, stencilEltR, stencilShapeR, stencilHalo,+ rnfStencilR,+ liftStencilR,++) where++import Data.Array.Accelerate.Representation.Array+import Data.Array.Accelerate.Representation.Shape+import Data.Array.Accelerate.Representation.Type++import Language.Haskell.TH.Extra+++-- | GADT reifying the 'Stencil' class+--+data StencilR sh e pat where+ StencilRunit3 :: TypeR e -> StencilR DIM1 e (Tup3 e e e)+ StencilRunit5 :: TypeR e -> StencilR DIM1 e (Tup5 e e e e e)+ StencilRunit7 :: TypeR e -> StencilR DIM1 e (Tup7 e e e e e e e)+ StencilRunit9 :: TypeR e -> StencilR DIM1 e (Tup9 e e e e e e e e e)++ StencilRtup3 :: StencilR sh e pat1+ -> StencilR sh e pat2+ -> StencilR sh e pat3+ -> StencilR (sh, Int) e (Tup3 pat1 pat2 pat3)++ StencilRtup5 :: StencilR sh e pat1+ -> StencilR sh e pat2+ -> StencilR sh e pat3+ -> StencilR sh e pat4+ -> StencilR sh e pat5+ -> StencilR (sh, Int) e (Tup5 pat1 pat2 pat3 pat4 pat5)++ StencilRtup7 :: StencilR sh e pat1+ -> StencilR sh e pat2+ -> StencilR sh e pat3+ -> StencilR sh e pat4+ -> StencilR sh e pat5+ -> StencilR sh e pat6+ -> StencilR sh e pat7+ -> StencilR (sh, Int) e (Tup7 pat1 pat2 pat3 pat4 pat5 pat6 pat7)++ StencilRtup9 :: StencilR sh e pat1+ -> StencilR sh e pat2+ -> StencilR sh e pat3+ -> StencilR sh e pat4+ -> StencilR sh e pat5+ -> StencilR sh e pat6+ -> StencilR sh e pat7+ -> StencilR sh e pat8+ -> StencilR sh e pat9+ -> StencilR (sh, Int) e (Tup9 pat1 pat2 pat3 pat4 pat5 pat6 pat7 pat8 pat9)++stencilEltR :: StencilR sh e pat -> TypeR e+stencilEltR (StencilRunit3 t) = t+stencilEltR (StencilRunit5 t) = t+stencilEltR (StencilRunit7 t) = t+stencilEltR (StencilRunit9 t) = t+stencilEltR (StencilRtup3 sR _ _) = stencilEltR sR+stencilEltR (StencilRtup5 sR _ _ _ _) = stencilEltR sR+stencilEltR (StencilRtup7 sR _ _ _ _ _ _) = stencilEltR sR+stencilEltR (StencilRtup9 sR _ _ _ _ _ _ _ _) = stencilEltR sR++stencilShapeR :: StencilR sh e pat -> ShapeR sh+stencilShapeR (StencilRunit3 _) = ShapeRsnoc ShapeRz+stencilShapeR (StencilRunit5 _) = ShapeRsnoc ShapeRz+stencilShapeR (StencilRunit7 _) = ShapeRsnoc ShapeRz+stencilShapeR (StencilRunit9 _) = ShapeRsnoc ShapeRz+stencilShapeR (StencilRtup3 sR _ _) = ShapeRsnoc $ stencilShapeR sR+stencilShapeR (StencilRtup5 sR _ _ _ _) = ShapeRsnoc $ stencilShapeR sR+stencilShapeR (StencilRtup7 sR _ _ _ _ _ _) = ShapeRsnoc $ stencilShapeR sR+stencilShapeR (StencilRtup9 sR _ _ _ _ _ _ _ _) = ShapeRsnoc $ stencilShapeR sR++stencilR :: StencilR sh e pat -> TypeR pat+stencilR (StencilRunit3 t) = tupR3 t t t+stencilR (StencilRunit5 t) = tupR5 t t t t t+stencilR (StencilRunit7 t) = tupR7 t t t t t t t+stencilR (StencilRunit9 t) = tupR9 t t t t t t t t t+stencilR (StencilRtup3 s1 s2 s3) = tupR3 (stencilR s1) (stencilR s2) (stencilR s3)+stencilR (StencilRtup5 s1 s2 s3 s4 s5) = tupR5 (stencilR s1) (stencilR s2) (stencilR s3) (stencilR s4) (stencilR s5)+stencilR (StencilRtup7 s1 s2 s3 s4 s5 s6 s7) = tupR7 (stencilR s1) (stencilR s2) (stencilR s3) (stencilR s4) (stencilR s5) (stencilR s6) (stencilR s7)+stencilR (StencilRtup9 s1 s2 s3 s4 s5 s6 s7 s8 s9) = tupR9 (stencilR s1) (stencilR s2) (stencilR s3) (stencilR s4) (stencilR s5) (stencilR s6) (stencilR s7) (stencilR s8) (stencilR s9)++stencilArrayR :: StencilR sh e pat -> ArrayR (Array sh e)+stencilArrayR sR = ArrayR (stencilShapeR sR) (stencilEltR sR)++stencilHalo :: StencilR sh e stencil -> (ShapeR sh, sh)+stencilHalo = go'+ where+ go' :: StencilR sh e stencil -> (ShapeR sh, sh)+ go' StencilRunit3{} = (dim1, ((), 1))+ go' StencilRunit5{} = (dim1, ((), 2))+ go' StencilRunit7{} = (dim1, ((), 3))+ go' StencilRunit9{} = (dim1, ((), 4))+ --+ go' (StencilRtup3 a b c ) = (ShapeRsnoc shR, cons shR 1 $ foldl1 (union shR) [a', go b, go c])+ where (shR, a') = go' a+ go' (StencilRtup5 a b c d e ) = (ShapeRsnoc shR, cons shR 2 $ foldl1 (union shR) [a', go b, go c, go d, go e])+ where (shR, a') = go' a+ go' (StencilRtup7 a b c d e f g ) = (ShapeRsnoc shR, cons shR 3 $ foldl1 (union shR) [a', go b, go c, go d, go e, go f, go g])+ where (shR, a') = go' a+ go' (StencilRtup9 a b c d e f g h i) = (ShapeRsnoc shR, cons shR 4 $ foldl1 (union shR) [a', go b, go c, go d, go e, go f, go g, go h, go i])+ where (shR, a') = go' a++ go :: StencilR sh e stencil -> sh+ go = snd . go'++ cons :: ShapeR sh -> Int -> sh -> (sh, Int)+ cons ShapeRz ix () = ((), ix)+ cons (ShapeRsnoc shr) ix (sh, sz) = (cons shr ix sh, sz)++tupR3 :: TupR s t1 -> TupR s t2 -> TupR s t3 -> TupR s (Tup3 t1 t2 t3)+tupR3 t1 t2 t3 = TupRunit `TupRpair` t1 `TupRpair` t2 `TupRpair` t3++tupR5 :: TupR s t1 -> TupR s t2 -> TupR s t3 -> TupR s t4 -> TupR s t5 -> TupR s (Tup5 t1 t2 t3 t4 t5)+tupR5 t1 t2 t3 t4 t5 = TupRunit `TupRpair` t1 `TupRpair` t2 `TupRpair` t3 `TupRpair` t4 `TupRpair` t5++tupR7 :: TupR s t1 -> TupR s t2 -> TupR s t3 -> TupR s t4 -> TupR s t5 -> TupR s t6 -> TupR s t7 -> TupR s (Tup7 t1 t2 t3 t4 t5 t6 t7)+tupR7 t1 t2 t3 t4 t5 t6 t7 = TupRunit `TupRpair` t1 `TupRpair` t2 `TupRpair` t3 `TupRpair` t4 `TupRpair` t5 `TupRpair` t6 `TupRpair` t7++tupR9 :: TupR s t1 -> TupR s t2 -> TupR s t3 -> TupR s t4 -> TupR s t5 -> TupR s t6 -> TupR s t7 -> TupR s t8 -> TupR s t9 -> TupR s (Tup9 t1 t2 t3 t4 t5 t6 t7 t8 t9)+tupR9 t1 t2 t3 t4 t5 t6 t7 t8 t9 = TupRunit `TupRpair` t1 `TupRpair` t2 `TupRpair` t3 `TupRpair` t4 `TupRpair` t5 `TupRpair` t6 `TupRpair` t7 `TupRpair` t8 `TupRpair` t9++rnfStencilR :: StencilR sh e pat -> ()+rnfStencilR (StencilRunit3 t) = rnfTypeR t+rnfStencilR (StencilRunit5 t) = rnfTypeR t+rnfStencilR (StencilRunit7 t) = rnfTypeR t+rnfStencilR (StencilRunit9 t) = rnfTypeR t+rnfStencilR (StencilRtup3 s1 s2 s3) = rnfStencilR s1 `seq` rnfStencilR s2 `seq` rnfStencilR s3+rnfStencilR (StencilRtup5 s1 s2 s3 s4 s5) = rnfStencilR s1 `seq` rnfStencilR s2 `seq` rnfStencilR s3 `seq` rnfStencilR s4 `seq` rnfStencilR s5+rnfStencilR (StencilRtup7 s1 s2 s3 s4 s5 s6 s7) = rnfStencilR s1 `seq` rnfStencilR s2 `seq` rnfStencilR s3 `seq` rnfStencilR s4 `seq` rnfStencilR s5 `seq` rnfStencilR s6 `seq` rnfStencilR s7+rnfStencilR (StencilRtup9 s1 s2 s3 s4 s5 s6 s7 s8 s9) = rnfStencilR s1 `seq` rnfStencilR s2 `seq` rnfStencilR s3 `seq` rnfStencilR s4 `seq` rnfStencilR s5 `seq` rnfStencilR s6 `seq` rnfStencilR s7 `seq` rnfStencilR s8 `seq` rnfStencilR s9++liftStencilR :: StencilR sh e pat -> CodeQ (StencilR sh e pat)+liftStencilR (StencilRunit3 tp) = [|| StencilRunit3 $$(liftTypeR tp) ||]+liftStencilR (StencilRunit5 tp) = [|| StencilRunit5 $$(liftTypeR tp) ||]+liftStencilR (StencilRunit7 tp) = [|| StencilRunit7 $$(liftTypeR tp) ||]+liftStencilR (StencilRunit9 tp) = [|| StencilRunit9 $$(liftTypeR tp) ||]+liftStencilR (StencilRtup3 s1 s2 s3) = [|| StencilRtup3 $$(liftStencilR s1) $$(liftStencilR s2) $$(liftStencilR s3) ||]+liftStencilR (StencilRtup5 s1 s2 s3 s4 s5) = [|| StencilRtup5 $$(liftStencilR s1) $$(liftStencilR s2) $$(liftStencilR s3) $$(liftStencilR s4) $$(liftStencilR s5) ||]+liftStencilR (StencilRtup7 s1 s2 s3 s4 s5 s6 s7) = [|| StencilRtup7 $$(liftStencilR s1) $$(liftStencilR s2) $$(liftStencilR s3) $$(liftStencilR s4) $$(liftStencilR s5) $$(liftStencilR s6) $$(liftStencilR s7) ||]+liftStencilR (StencilRtup9 s1 s2 s3 s4 s5 s6 s7 s8 s9) = [|| StencilRtup9 $$(liftStencilR s1) $$(liftStencilR s2) $$(liftStencilR s3) $$(liftStencilR s4) $$(liftStencilR s5) $$(liftStencilR s6) $$(liftStencilR s7) $$(liftStencilR s8) $$(liftStencilR s9) ||]+
+ src/Data/Array/Accelerate/Representation/Tag.hs view
@@ -0,0 +1,68 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE TemplateHaskell #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Representation.Tag+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Representation.Tag+ where++import Data.Array.Accelerate.Type++import Language.Haskell.TH.Extra+++-- | The type of the runtime value used to distinguish constructor+-- alternatives in a sum type.+--+type TAG = Word8++-- | This structure both witnesses the layout of our representation types+-- (as TupR does) and represents a complete path of pattern matching+-- through this type. It indicates which fields of the structure represent+-- the union tags (TagRtag) or store undefined values (TagRundef).+--+-- The function 'tagsR' produces all valid paths through the type. For+-- example the type '(Bool,Bool)' produces the following:+--+-- ghci> putStr . unlines . map show $ tagsR @(Bool,Bool)+-- (((),(0#,())),(0#,())) -- (False, False)+-- (((),(0#,())),(1#,())) -- (False, True)+-- (((),(1#,())),(0#,())) -- (True, False)+-- (((),(1#,())),(1#,())) -- (True, True)+--+data TagR a where+ TagRunit :: TagR ()+ TagRsingle :: ScalarType a -> TagR a+ TagRundef :: ScalarType a -> TagR a+ TagRtag :: TAG -> TagR a -> TagR (TAG, a)+ TagRpair :: TagR a -> TagR b -> TagR (a, b)++instance Show (TagR a) where+ show TagRunit = "()"+ show TagRsingle{} = "."+ show TagRundef{} = "undef"+ show (TagRtag v t) = "(" ++ show v ++ "#," ++ show t ++ ")"+ show (TagRpair ta tb) = "(" ++ show ta ++ "," ++ show tb ++ ")"++rnfTag :: TagR a -> ()+rnfTag TagRunit = ()+rnfTag (TagRsingle t) = rnfScalarType t+rnfTag (TagRundef t) = rnfScalarType t+rnfTag (TagRtag v t) = v `seq` rnfTag t+rnfTag (TagRpair ta tb) = rnfTag ta `seq` rnfTag tb++liftTag :: TagR a -> CodeQ (TagR a)+liftTag TagRunit = [|| TagRunit ||]+liftTag (TagRsingle t) = [|| TagRsingle $$(liftScalarType t) ||]+liftTag (TagRundef t) = [|| TagRundef $$(liftScalarType t) ||]+liftTag (TagRtag v t) = [|| TagRtag v $$(liftTag t) ||]+liftTag (TagRpair ta tb) = [|| TagRpair $$(liftTag ta) $$(liftTag tb) ||]+
+ src/Data/Array/Accelerate/Representation/Type.hs view
@@ -0,0 +1,126 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuantifiedConstraints #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TemplateHaskell #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Representation.Type+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Representation.Type+ where++import Data.Array.Accelerate.Type+import Data.Primitive.Vec++import Formatting+import Language.Haskell.TH.Extra+++-- | Both arrays (Acc) and expressions (Exp) are represented as nested+-- pairs consisting of:+--+-- * unit (void)+--+-- * pairs: representing compound values (i.e. tuples) where each component+-- will be stored in a separate array.+--+-- * single array / scalar types+-- in case of expressions: values which go in registers. These may be single value+-- types such as int and float, or SIMD vectors of single value types such+-- as <4 * float>. We do not allow vectors-of-vectors.+--+data TupR s a where+ TupRunit :: TupR s ()+ TupRsingle :: s a -> TupR s a+ TupRpair :: TupR s a -> TupR s b -> TupR s (a, b)++deriving instance (forall a. Show (s a)) => Show (TupR s t)++formatTypeR :: Format r (TypeR a -> r)+formatTypeR = later $ \case+ TupRunit -> "()"+ TupRsingle t -> bformat formatScalarType t+ TupRpair a b -> bformat (parenthesised (formatTypeR % "," % formatTypeR)) a b++type TypeR = TupR ScalarType++rnfTupR :: (forall b. s b -> ()) -> TupR s a -> ()+rnfTupR _ TupRunit = ()+rnfTupR f (TupRsingle s) = f s+rnfTupR f (TupRpair a b) = rnfTupR f a `seq` rnfTupR f b++rnfTypeR :: TypeR t -> ()+rnfTypeR = rnfTupR rnfScalarType++liftTupR :: (forall b. s b -> CodeQ (s b)) -> TupR s a -> CodeQ (TupR s a)+liftTupR _ TupRunit = [|| TupRunit ||]+liftTupR f (TupRsingle s) = [|| TupRsingle $$(f s) ||]+liftTupR f (TupRpair a b) = [|| TupRpair $$(liftTupR f a) $$(liftTupR f b) ||]++liftTypeR :: TypeR t -> CodeQ (TypeR t)+liftTypeR TupRunit = [|| TupRunit ||]+liftTypeR (TupRsingle t) = [|| TupRsingle $$(liftScalarType t) ||]+liftTypeR (TupRpair ta tb) = [|| TupRpair $$(liftTypeR ta) $$(liftTypeR tb) ||]++liftTypeQ :: TypeR t -> TypeQ+liftTypeQ = tuple+ where+ tuple :: TypeR t -> TypeQ+ tuple TupRunit = [t| () |]+ tuple (TupRpair t1 t2) = [t| ($(tuple t1), $(tuple t2)) |]+ tuple (TupRsingle t) = scalar t++ scalar :: ScalarType t -> TypeQ+ scalar (SingleScalarType t) = single t+ scalar (VectorScalarType t) = vector t++ vector :: VectorType (Vec n a) -> TypeQ+ vector (VectorType n t) = [t| Vec $(litT (numTyLit (toInteger n))) $(single t) |]++ single :: SingleType t -> TypeQ+ single (NumSingleType t) = num t++ num :: NumType t -> TypeQ+ num (IntegralNumType t) = integral t+ num (FloatingNumType t) = floating t++ integral :: IntegralType t -> TypeQ+ integral TypeInt = [t| Int |]+ integral TypeInt8 = [t| Int8 |]+ integral TypeInt16 = [t| Int16 |]+ integral TypeInt32 = [t| Int32 |]+ integral TypeInt64 = [t| Int64 |]+ integral TypeWord = [t| Word |]+ integral TypeWord8 = [t| Word8 |]+ integral TypeWord16 = [t| Word16 |]+ integral TypeWord32 = [t| Word32 |]+ integral TypeWord64 = [t| Word64 |]++ floating :: FloatingType t -> TypeQ+ floating TypeHalf = [t| Half |]+ floating TypeFloat = [t| Float |]+ floating TypeDouble = [t| Double |]++runQ $+ let+ mkT :: Int -> Q Dec+ mkT n =+ let xs = [ mkName ('x' : show i) | i <- [0 .. n-1] ]+ ts = map varT xs+ rhs = foldl (\a b -> [t| ($a, $b) |]) [t| () |] ts+ in+ tySynD (mkName ("Tup" ++ show n)) (map plainTV xs) rhs+ in+ mapM mkT [2..16]+
+ src/Data/Array/Accelerate/Representation/Vec.hs view
@@ -0,0 +1,95 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeOperators #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Representation.Vec+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Representation.Vec+ where++import Data.Array.Accelerate.Type+import Data.Array.Accelerate.Representation.Type+import Data.Primitive.Vec++import Control.Monad.ST+import Data.Primitive.ByteArray+import Data.Primitive.Types+import Language.Haskell.TH.Extra++import GHC.Base ( Int(..), Int#, (-#) )+import GHC.TypeNats+++-- | Declares the size of a SIMD vector and the type of its elements. This+-- data type is used to denote the relation between a vector type (Vec+-- n single) with its tuple representation (tuple). Conversions between+-- those types are exposed through 'pack' and 'unpack'.+--+data VecR (n :: Nat) single tuple where+ VecRnil :: SingleType s -> VecR 0 s ()+ VecRsucc :: VecR n s t -> VecR (n + 1) s (t, s)++vecRvector :: KnownNat n => VecR n s tuple -> VectorType (Vec n s)+vecRvector = uncurry VectorType . go+ where+ go :: VecR n s tuple -> (Int, SingleType s)+ go (VecRnil tp) = (0, tp)+ go (VecRsucc vec) | (n, tp) <- go vec = (n + 1, tp)++vecRtuple :: VecR n s tuple -> TypeR tuple+vecRtuple = snd . go+ where+ go :: VecR n s tuple -> (SingleType s, TypeR tuple)+ go (VecRnil tp) = (tp, TupRunit)+ go (VecRsucc vec) | (tp, tuple) <- go vec = (tp, TupRpair tuple (TupRsingle (SingleScalarType tp)))++pack :: forall n single tuple. KnownNat n => VecR n single tuple -> tuple -> Vec n single+pack vecR tuple+ | VectorType n single <- vecRvector vecR+ , SingleDict <- singleDict single+ = runST $ do+ mba <- newByteArray (n * sizeOf (undefined :: single))+ go (n - 1) vecR tuple mba+ ByteArray ba# <- unsafeFreezeByteArray mba+ return $! Vec ba#+ where+ go :: Prim single => Int -> VecR n' single tuple' -> tuple' -> MutableByteArray s -> ST s ()+ go _ (VecRnil _) () _ = return ()+ go i (VecRsucc r) (xs, x) mba = do+ writeByteArray mba i x+ go (i - 1) r xs mba++unpack :: forall n single tuple. KnownNat n => VecR n single tuple -> Vec n single -> tuple+unpack vecR (Vec ba#)+ | VectorType n single <- vecRvector vecR+ , (I# n#) <- n+ , SingleDict <- singleDict single+ = go (n# -# 1#) vecR+ where+ go :: Prim single => Int# -> VecR n' single tuple' -> tuple'+ go _ (VecRnil _) = ()+ go i# (VecRsucc r) = x `seq` xs `seq` (xs, x)+ where+ xs = go (i# -# 1#) r+ x = indexByteArray# ba# i#++rnfVecR :: VecR n single tuple -> ()+rnfVecR (VecRnil tp) = rnfSingleType tp+rnfVecR (VecRsucc vec) = rnfVecR vec++liftVecR :: VecR n single tuple -> CodeQ (VecR n single tuple)+liftVecR (VecRnil tp) = [|| VecRnil $$(liftSingleType tp) ||]+liftVecR (VecRsucc vec) = [|| VecRsucc $$(liftVecR vec) ||]+
+ src/Data/Array/Accelerate/Smart.hs view
@@ -0,0 +1,1398 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Smart+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- This modules defines the AST of the user-visible embedded language using more+-- convenient higher-order abstract syntax (instead of de Bruijn indices).+-- Moreover, it defines smart constructors to construct programs.+--++module Data.Array.Accelerate.Smart (++ -- * HOAS AST+ -- ** Array computations+ Acc(..), SmartAcc(..), PreSmartAcc(..),+ Level, Direction(..), Message(..),++ -- ** Scalar expressions+ Exp(..), SmartExp(..), PreSmartExp(..),+ Stencil(..),+ Boundary(..), PreBoundary(..),+ PrimBool,+ PrimMaybe,++ -- ** Extracting type information+ HasArraysR(..),+ HasTypeR(..),++ -- ** Smart constructors for literals+ constant, undef,++ -- ** Smart destructors for shapes+ indexHead, indexTail,++ -- ** Smart constructors for constants+ mkMinBound, mkMaxBound, mkPi,+ mkSin, mkCos, mkTan,+ mkAsin, mkAcos, mkAtan,+ mkSinh, mkCosh, mkTanh,+ mkAsinh, mkAcosh, mkAtanh,+ mkExpFloating, mkSqrt, mkLog,+ mkFPow, mkLogBase,+ mkTruncate, mkRound, mkFloor, mkCeiling,+ mkAtan2,++ -- ** Smart constructors for primitive functions+ mkAdd, mkSub, mkMul, mkNeg, mkAbs, mkSig, mkQuot, mkRem, mkQuotRem, mkIDiv, mkMod, mkDivMod,+ mkBAnd, mkBOr, mkBXor, mkBNot, mkBShiftL, mkBShiftR, mkBRotateL, mkBRotateR, mkPopCount, mkCountLeadingZeros, mkCountTrailingZeros,+ mkFDiv, mkRecip, mkLt, mkGt, mkLtEq, mkGtEq, mkEq, mkNEq, mkMax, mkMin,+ mkLAnd, mkLOr, mkLNot, mkIsNaN, mkIsInfinite,++ -- ** Smart constructors for type coercion functions+ mkFromIntegral, mkToFloating, mkBitcast, mkCoerce, Coerce(..),++ -- ** Auxiliary functions+ ($$), ($$$), ($$$$), ($$$$$),+ ApplyAcc(..),+ unAcc, unAccFunction, mkExp, unExp, unExpFunction, unExpBinaryFunction, unPair, mkPairToTuple,++ -- ** Miscellaneous+ formatPreAccOp,+ formatPreExpOp,++) where+++import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.Error+import Data.Array.Accelerate.Representation.Array+import Data.Array.Accelerate.Representation.Elt+import Data.Array.Accelerate.Representation.Shape+import Data.Array.Accelerate.Representation.Slice+import Data.Array.Accelerate.Representation.Stencil hiding ( StencilR, stencilR )+import Data.Array.Accelerate.Representation.Tag+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Representation.Vec+import Data.Array.Accelerate.Sugar.Array ( Arrays )+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Sugar.Foreign+import Data.Array.Accelerate.Sugar.Shape ( (:.)(..) )+import Data.Array.Accelerate.Type+import qualified Data.Array.Accelerate.Representation.Stencil as R+import qualified Data.Array.Accelerate.Sugar.Array as Sugar+import qualified Data.Array.Accelerate.Sugar.Shape as Sugar++import Data.Array.Accelerate.AST ( Direction(..), Message(..)+ , PrimBool, PrimMaybe+ , PrimFun(..), primFunType+ , PrimConst(..), primConstType )+import Data.Primitive.Vec++import Data.Kind+import Data.Text.Lazy.Builder+import Formatting++import GHC.TypeLits+++-- Array computations+-- ------------------++-- | Accelerate is an /embedded language/ that distinguishes between vanilla+-- arrays (e.g. in Haskell memory on the CPU) and embedded arrays (e.g. in+-- device memory on a GPU), as well as the computations on both of these. Since+-- Accelerate is an embedded language, programs written in Accelerate are not+-- compiled by the Haskell compiler (GHC). Rather, each Accelerate backend is+-- a /runtime compiler/ which generates and executes parallel SIMD code of the+-- target language at application /runtime/.+--+-- The type constructor 'Acc' represents embedded collective array operations.+-- A term of type @Acc a@ is an Accelerate program which, once executed, will+-- produce a value of type 'a' (an 'Array' or a tuple of 'Arrays'). Collective+-- operations of type @Acc a@ comprise many /scalar expressions/, wrapped in+-- type constructor 'Exp', which will be executed in parallel. Although+-- collective operations comprise many scalar operations executed in parallel,+-- scalar operations /cannot/ initiate new collective operations: this+-- stratification between scalar operations in 'Exp' and array operations in+-- 'Acc' helps statically exclude /nested data parallelism/, which is difficult+-- to execute efficiently on constrained hardware such as GPUs.+--+-- [/A simple example/]+--+-- As a simple example, to compute a vector dot product we can write:+--+-- > dotp :: Num a => Vector a -> Vector a -> Acc (Scalar a)+-- > dotp xs ys =+-- > let+-- > xs' = use xs+-- > ys' = use ys+-- > in+-- > fold (+) 0 (zipWith (*) xs' ys')+--+-- The function @dotp@ consumes two one-dimensional arrays ('Vector's) of+-- values, and produces a single ('Scalar') result as output. As the return type+-- is wrapped in the type 'Acc', we see that it is an embedded Accelerate+-- computation - it will be evaluated in the /object/ language of dynamically+-- generated parallel code, rather than the /meta/ language of vanilla Haskell.+--+-- As the arguments to @dotp@ are plain Haskell arrays, to make these available+-- to Accelerate computations they must be embedded with the+-- 'Data.Array.Accelerate.Language.use' function.+--+-- An Accelerate backend is used to evaluate the embedded computation and return+-- the result back to vanilla Haskell. Calling the 'run' function of a backend+-- will generate code for the target architecture, compile, and execute it. For+-- example, the following backends are available:+--+-- * <http://hackage.haskell.org/package/accelerate-llvm-native accelerate-llvm-native>: for execution on multicore CPUs+-- * <http://hackage.haskell.org/package/accelerate-llvm-ptx accelerate-llvm-ptx>: for execution on NVIDIA CUDA-capable GPUs+--+-- See also 'Exp', which encapsulates embedded /scalar/ computations.+--+-- [/Avoiding nested parallelism/]+--+-- As mentioned above, embedded scalar computations of type 'Exp' can not+-- initiate further collective operations.+--+-- Suppose we wanted to extend our above @dotp@ function to matrix-vector+-- multiplication. First, let's rewrite our @dotp@ function to take 'Acc' arrays+-- as input (which is typically what we want):+--+-- > dotp :: Num a => Acc (Vector a) -> Acc (Vector a) -> Acc (Scalar a)+-- > dotp xs ys = fold (+) 0 $ zipWith (*) xs ys+--+-- We might then be inclined to lift our dot-product program to the following+-- (incorrect) matrix-vector product, by applying @dotp@ to each row of the+-- input matrix:+--+-- > mvm_ndp :: Num a => Acc (Matrix a) -> Acc (Vector a) -> Acc (Vector a)+-- > mvm_ndp mat vec =+-- > let I2 rows cols = shape mat+-- > in generate (I1 rows)+-- > (\(I1 row) -> the $ dotp vec (slice mat (I2 row All_)))+--+-- Here, we use 'Data.Array.Accelerate.generate' to create a one-dimensional+-- vector by applying at each index a function to 'Data.Array.Accelerate.slice'+-- out the corresponding @row@ of the matrix to pass to the @dotp@ function.+-- However, since both 'Data.Array.Accelerate.generate' and+-- 'Data.Array.Accelerate.slice' are data-parallel operations, and moreover that+-- 'Data.Array.Accelerate.slice' /depends on/ the argument @row@ given to it by+-- the 'Data.Array.Accelerate.generate' function, this definition requires+-- nested data-parallelism, and is thus not permitted. The clue that this+-- definition is invalid is that in order to create a program which will be+-- accepted by the type checker, we must use the function+-- 'Data.Array.Accelerate.the' to retrieve the result of the @dotp@ operation,+-- effectively concealing that @dotp@ is a collective array computation in order+-- to match the type expected by 'Data.Array.Accelerate.generate', which is that+-- of scalar expressions. Additionally, since we have fooled the type-checker,+-- this problem will only be discovered at program runtime.+--+-- In order to avoid this problem, we can make use of the fact that operations+-- in Accelerate are /rank polymorphic/. The 'Data.Array.Accelerate.fold'+-- operation reduces along the innermost dimension of an array of arbitrary+-- rank, reducing the rank (dimensionality) of the array by one. Thus, we can+-- 'Data.Array.Accelerate.replicate' the input vector to as many @rows@ there+-- are in the input matrix, and perform the dot-product of the vector with every+-- row simultaneously:+--+-- > mvm :: Num a => Acc (Matrix a) -> Acc (Vector a) -> Acc (Vector a)+-- > mvm mat vec =+-- > let I2 rows cols = shape mat+-- > vec' = replicate (I2 rows All_) vec+-- > in+-- > fold (+) 0 $ zipWith (*) mat vec'+--+-- Note that the intermediate, replicated array @vec'@ is never actually created+-- in memory; it will be fused directly into the operation which consumes it. We+-- discuss fusion next.+--+-- [/Fusion/]+--+-- Array computations of type 'Acc' will be subject to /array fusion/;+-- Accelerate will combine individual 'Acc' computations into a single+-- computation, which reduces the number of traversals over the input data and+-- thus improves performance. As such, it is often useful to have some intuition+-- on when fusion should occur.+--+-- The main idea is to first partition array operations into two categories:+--+-- 1. Element-wise operations, such as 'Data.Array.Accelerate.map',+-- 'Data.Array.Accelerate.generate', and+-- 'Data.Array.Accelerate.backpermute'. Each element of these operations+-- can be computed independently of all others.+--+-- 2. Collective operations such as 'Data.Array.Accelerate.fold',+-- 'Data.Array.Accelerate.scanl', and 'Data.Array.Accelerate.stencil'. To+-- compute each output element of these operations requires reading+-- multiple elements from the input array(s).+--+-- Element-wise operations fuse together whenever the consumer operation uses+-- a single element of the input array. Element-wise operations can both fuse+-- their inputs into themselves, as well be fused into later operations. Both+-- these examples should fuse into a single loop:+--+-- <<images/fusion_example_1.png>>+--+-- <<images/fusion_example_2.png>>+--+-- If the consumer operation uses more than one element of the input array+-- (typically, via 'Data.Array.Accelerate.generate' indexing an array multiple+-- times), then the input array will be completely evaluated first; no fusion+-- occurs in this case, because fusing the first operation into the second+-- implies duplicating work.+--+-- On the other hand, collective operations can fuse their input arrays into+-- themselves, but on output always evaluate to an array; collective operations+-- will not be fused into a later step. For example:+--+-- <<images/fusion_example_3.png>>+--+-- Here the element-wise sequence ('Data.Array.Accelerate.use'+-- + 'Data.Array.Accelerate.generate' + 'Data.Array.Accelerate.zipWith') will+-- fuse into a single operation, which then fuses into the collective+-- 'Data.Array.Accelerate.fold' operation. At this point in the program the+-- 'Data.Array.Accelerate.fold' must now be evaluated. In the final step the+-- 'Data.Array.Accelerate.map' reads in the array produced by+-- 'Data.Array.Accelerate.fold'. As there is no fusion between the+-- 'Data.Array.Accelerate.fold' and 'Data.Array.Accelerate.map' steps, this+-- program consists of two "loops"; one for the 'Data.Array.Accelerate.use'+-- + 'Data.Array.Accelerate.generate' + 'Data.Array.Accelerate.zipWith'+-- + 'Data.Array.Accelerate.fold' step, and one for the final+-- 'Data.Array.Accelerate.map' step.+--+-- You can see how many operations will be executed in the fused program by+-- 'Show'-ing the 'Acc' program, or by using the debugging option @-ddump-dot@+-- to save the program as a graphviz DOT file.+--+-- As a special note, the operations 'Data.Array.Accelerate.unzip' and+-- 'Data.Array.Accelerate.reshape', when applied to a real array, are executed+-- in constant time, so in this situation these operations will not be fused.+--+-- [/Tips/]+--+-- * Since 'Acc' represents embedded computations that will only be executed+-- when evaluated by a backend, we can programatically generate these+-- computations using the meta language Haskell; for example, unrolling loops+-- or embedding input values into the generated code.+--+-- * It is usually best to keep all intermediate computations in 'Acc', and+-- only 'run' the computation at the very end to produce the final result.+-- This enables optimisations between intermediate results (e.g. array+-- fusion) and, if the target architecture has a separate memory space, as is+-- the case of GPUs, to prevent excessive data transfers.+--+newtype Acc a = Acc (SmartAcc (Sugar.ArraysR a))++newtype SmartAcc a = SmartAcc (PreSmartAcc SmartAcc SmartExp a)+++-- The level of lambda-bound variables. The root has level 0; then it+-- increases with each bound variable — i.e., it is the same as the size of+-- the environment at the defining occurrence.+--+type Level = Int++-- | Array-valued collective computations without a recursive knot+--+data PreSmartAcc acc exp as where+ -- Needed for conversion to de Bruijn form+ Atag :: ArraysR as+ -> Level -- environment size at defining occurrence+ -> PreSmartAcc acc exp as++ Pipe :: ArraysR as+ -> ArraysR bs+ -> ArraysR cs+ -> (SmartAcc as -> acc bs)+ -> (SmartAcc bs -> acc cs)+ -> acc as+ -> PreSmartAcc acc exp cs++ Aforeign :: Foreign asm+ => ArraysR bs+ -> asm (as -> bs)+ -> (SmartAcc as -> SmartAcc bs)+ -> acc as+ -> PreSmartAcc acc exp bs++ Acond :: exp PrimBool+ -> acc as+ -> acc as+ -> PreSmartAcc acc exp as++ Awhile :: ArraysR arrs+ -> (SmartAcc arrs -> acc (Scalar PrimBool))+ -> (SmartAcc arrs -> acc arrs)+ -> acc arrs+ -> PreSmartAcc acc exp arrs++ Anil :: PreSmartAcc acc exp ()++ Apair :: acc arrs1+ -> acc arrs2+ -> PreSmartAcc acc exp (arrs1, arrs2)++ Aprj :: PairIdx (arrs1, arrs2) arrs+ -> acc (arrs1, arrs2)+ -> PreSmartAcc acc exp arrs++ Atrace :: Message arrs1+ -> acc arrs1+ -> acc arrs2+ -> PreSmartAcc acc exp arrs2++ Use :: ArrayR (Array sh e)+ -> Array sh e+ -> PreSmartAcc acc exp (Array sh e)++ Unit :: TypeR e+ -> exp e+ -> PreSmartAcc acc exp (Scalar e)++ Generate :: ArrayR (Array sh e)+ -> exp sh+ -> (SmartExp sh -> exp e)+ -> PreSmartAcc acc exp (Array sh e)++ Reshape :: ShapeR sh+ -> exp sh+ -> acc (Array sh' e)+ -> PreSmartAcc acc exp (Array sh e)++ Replicate :: SliceIndex slix sl co sh+ -> exp slix+ -> acc (Array sl e)+ -> PreSmartAcc acc exp (Array sh e)++ Slice :: SliceIndex slix sl co sh+ -> acc (Array sh e)+ -> exp slix+ -> PreSmartAcc acc exp (Array sl e)++ Map :: TypeR e+ -> TypeR e'+ -> (SmartExp e -> exp e')+ -> acc (Array sh e)+ -> PreSmartAcc acc exp (Array sh e')++ ZipWith :: TypeR e1+ -> TypeR e2+ -> TypeR e3+ -> (SmartExp e1 -> SmartExp e2 -> exp e3)+ -> acc (Array sh e1)+ -> acc (Array sh e2)+ -> PreSmartAcc acc exp (Array sh e3)++ Fold :: TypeR e+ -> (SmartExp e -> SmartExp e -> exp e)+ -> Maybe (exp e)+ -> acc (Array (sh, Int) e)+ -> PreSmartAcc acc exp (Array sh e)++ FoldSeg :: IntegralType i+ -> TypeR e+ -> (SmartExp e -> SmartExp e -> exp e)+ -> Maybe (exp e)+ -> acc (Array (sh, Int) e)+ -> acc (Segments i)+ -> PreSmartAcc acc exp (Array (sh, Int) e)++ Scan :: Direction+ -> TypeR e+ -> (SmartExp e -> SmartExp e -> exp e)+ -> Maybe (exp e)+ -> acc (Array (sh, Int) e)+ -> PreSmartAcc acc exp (Array (sh, Int) e)++ Scan' :: Direction+ -> TypeR e+ -> (SmartExp e -> SmartExp e -> exp e)+ -> exp e+ -> acc (Array (sh, Int) e)+ -> PreSmartAcc acc exp (Array (sh, Int) e, Array sh e)++ Permute :: ArrayR (Array sh e)+ -> (SmartExp e -> SmartExp e -> exp e)+ -> acc (Array sh' e)+ -> (SmartExp sh -> exp (PrimMaybe sh'))+ -> acc (Array sh e)+ -> PreSmartAcc acc exp (Array sh' e)++ Backpermute :: ShapeR sh'+ -> exp sh'+ -> (SmartExp sh' -> exp sh)+ -> acc (Array sh e)+ -> PreSmartAcc acc exp (Array sh' e)++ Stencil :: R.StencilR sh a stencil+ -> TypeR b+ -> (SmartExp stencil -> exp b)+ -> PreBoundary acc exp (Array sh a)+ -> acc (Array sh a)+ -> PreSmartAcc acc exp (Array sh b)++ Stencil2 :: R.StencilR sh a stencil1+ -> R.StencilR sh b stencil2+ -> TypeR c+ -> (SmartExp stencil1 -> SmartExp stencil2 -> exp c)+ -> PreBoundary acc exp (Array sh a)+ -> acc (Array sh a)+ -> PreBoundary acc exp (Array sh b)+ -> acc (Array sh b)+ -> PreSmartAcc acc exp (Array sh c)+++-- Embedded expressions of the surface language+-- --------------------------------------------++-- HOAS expressions mirror the constructors of 'AST.OpenExp', but with the 'Tag'+-- constructor instead of variables in the form of de Bruijn indices.+--++-- | The type 'Exp' represents embedded scalar expressions. The collective+-- operations of Accelerate 'Acc' consist of many scalar expressions executed in+-- data-parallel.+--+-- Note that scalar expressions can not initiate new collective operations:+-- doing so introduces /nested data parallelism/, which is difficult to execute+-- efficiently on constrained hardware such as GPUs, and is thus currently+-- unsupported.+--+newtype Exp t = Exp (SmartExp (EltR t))+newtype SmartExp t = SmartExp (PreSmartExp SmartAcc SmartExp t)++-- | Scalar expressions to parametrise collective array operations, themselves parameterised over+-- the type of collective array operations.+--+data PreSmartExp acc exp t where+ -- Needed for conversion to de Bruijn form+ Tag :: TypeR t+ -> Level -- environment size at defining occurrence+ -> PreSmartExp acc exp t++ -- Needed for embedded pattern matching+ Match :: TagR t+ -> exp t+ -> PreSmartExp acc exp t++ -- All the same constructors as 'AST.Exp', plus projection+ Const :: ScalarType t+ -> t+ -> PreSmartExp acc exp t++ Nil :: PreSmartExp acc exp ()++ Pair :: exp t1+ -> exp t2+ -> PreSmartExp acc exp (t1, t2)++ Prj :: PairIdx (t1, t2) t+ -> exp (t1, t2)+ -> PreSmartExp acc exp t++ VecPack :: KnownNat n+ => VecR n s tup+ -> exp tup+ -> PreSmartExp acc exp (Vec n s)++ VecUnpack :: KnownNat n+ => VecR n s tup+ -> exp (Vec n s)+ -> PreSmartExp acc exp tup++ ToIndex :: ShapeR sh+ -> exp sh+ -> exp sh+ -> PreSmartExp acc exp Int++ FromIndex :: ShapeR sh+ -> exp sh+ -> exp Int+ -> PreSmartExp acc exp sh++ Case :: exp a+ -> [(TagR a, exp b)]+ -> PreSmartExp acc exp b++ Cond :: exp PrimBool+ -> exp t+ -> exp t+ -> PreSmartExp acc exp t++ While :: TypeR t+ -> (SmartExp t -> exp PrimBool)+ -> (SmartExp t -> exp t)+ -> exp t+ -> PreSmartExp acc exp t++ PrimConst :: PrimConst t+ -> PreSmartExp acc exp t++ PrimApp :: PrimFun (a -> r)+ -> exp a+ -> PreSmartExp acc exp r++ Index :: TypeR t+ -> acc (Array sh t)+ -> exp sh+ -> PreSmartExp acc exp t++ LinearIndex :: TypeR t+ -> acc (Array sh t)+ -> exp Int+ -> PreSmartExp acc exp t++ Shape :: ShapeR sh+ -> acc (Array sh e)+ -> PreSmartExp acc exp sh++ ShapeSize :: ShapeR sh+ -> exp sh+ -> PreSmartExp acc exp Int++ Foreign :: Foreign asm+ => TypeR y+ -> asm (x -> y)+ -> (SmartExp x -> SmartExp y) -- RCE: Using SmartExp instead of exp to aid in sharing recovery.+ -> exp x+ -> PreSmartExp acc exp y++ Undef :: ScalarType t+ -> PreSmartExp acc exp t++ Coerce :: BitSizeEq a b+ => ScalarType a+ -> ScalarType b+ -> exp a+ -> PreSmartExp acc exp b+++-- Smart constructors for stencils+-- -------------------------------++-- | Boundary condition specification for stencil operations+--+data Boundary t where+ Boundary :: PreBoundary SmartAcc SmartExp (Array (EltR sh) (EltR e))+ -> Boundary (Sugar.Array sh e)++data PreBoundary acc exp t where+ Clamp :: PreBoundary acc exp t+ Mirror :: PreBoundary acc exp t+ Wrap :: PreBoundary acc exp t++ Constant :: e+ -> PreBoundary acc exp (Array sh e)++ Function :: (SmartExp sh -> exp e)+ -> PreBoundary acc exp (Array sh e)+++-- Stencil reification+-- -------------------+--+-- In the AST representation, we turn the stencil type from nested tuples+-- of Accelerate expressions into an Accelerate expression whose type is+-- a tuple nested in the same manner. This enables us to represent the+-- stencil function as a unary function (which also only needs one de+-- Bruijn index). The various positions in the stencil are accessed via+-- tuple indices (i.e., projections).+--+class Stencil sh e stencil where+ stencilR :: R.StencilR (EltR sh) (EltR e) (StencilR sh stencil)+ stencilPrj :: SmartExp (StencilR sh stencil) -> stencil++-- | This is a separate type family (instead of an associated type synonym in+-- the 'Stencil' class) so that we can give it instances of the form:+--+-- StencilR DIM1 (Exp e, Exp e, Exp e) = EltR (e, e, e)+--+-- whereas if it was an associated type synonym, the left-hand side would need+-- to match the instance head, wherein we do not have @e@ available, only+-- @a1 ~ Exp e@.+type family StencilR sh stencil :: Type++-- DIM1+-- These instances are written with a1, a2, a3, etc. to ensure that+-- they match for _any_ tuple, not just tuples for which GHC already knows that+-- they consist of equal Exps. This significantly improves type inference.+instance (Elt e, a1 ~ Exp e, a2 ~ Exp e, a3 ~ Exp e)+ => Stencil Sugar.DIM1 e (a1, a2, a3) where+ stencilR = StencilRunit3 @(EltR e) $ eltR @e+ stencilPrj s = (Exp $ prj2 s,+ Exp $ prj1 s,+ Exp $ prj0 s)++type instance StencilR Sugar.DIM1 (Exp e, Exp e, Exp e)+ = EltR (e, e, e)++instance (Elt e, a1 ~ Exp e, a2 ~ Exp e, a3 ~ Exp e, a4 ~ Exp e, a5 ~ Exp e)+ => Stencil Sugar.DIM1 e (a1, a2, a3, a4, a5) where+ stencilR = StencilRunit5 $ eltR @e+ stencilPrj s = (Exp $ prj4 s,+ Exp $ prj3 s,+ Exp $ prj2 s,+ Exp $ prj1 s,+ Exp $ prj0 s)++type instance StencilR Sugar.DIM1 (Exp e, Exp e, Exp e, Exp e, Exp e)+ = EltR (e, e, e, e, e)++instance (Elt e, a1 ~ Exp e, a2 ~ Exp e, a3 ~ Exp e, a4 ~ Exp e, a5 ~ Exp e, a6 ~ Exp e, a7 ~ Exp e)+ => Stencil Sugar.DIM1 e (a1, a2, a3, a4, a5, a6, a7) where+ stencilR = StencilRunit7 $ eltR @e+ stencilPrj s = (Exp $ prj6 s,+ Exp $ prj5 s,+ Exp $ prj4 s,+ Exp $ prj3 s,+ Exp $ prj2 s,+ Exp $ prj1 s,+ Exp $ prj0 s)++type instance StencilR Sugar.DIM1 (Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e)+ = EltR (e, e, e, e, e, e, e)++instance (Elt e, a1 ~ Exp e, a2 ~ Exp e, a3 ~ Exp e, a4 ~ Exp e, a5 ~ Exp e, a6 ~ Exp e, a7 ~ Exp e, a8 ~ Exp e, a9 ~ Exp e)+ => Stencil Sugar.DIM1 e (a1, a2, a3, a4, a5, a6, a7, a8, a9) where+ stencilR = StencilRunit9 $ eltR @e+ stencilPrj s = (Exp $ prj8 s,+ Exp $ prj7 s,+ Exp $ prj6 s,+ Exp $ prj5 s,+ Exp $ prj4 s,+ Exp $ prj3 s,+ Exp $ prj2 s,+ Exp $ prj1 s,+ Exp $ prj0 s)++type instance StencilR Sugar.DIM1 (Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e)+ = EltR (e, e, e, e, e, e, e, e, e)++-- DIM(n+1)+-- TODO: These instances allow stencils with unequal sub-stencil sizes (i.e.+-- unequal row lengths for a 2D stencil). This is rather odd, probably unused,+-- and makes type inference a little less eager to deduce the stencil type in+-- case of underspecified rows. Can we just require the rows to be equal?+instance (Stencil (sh:.Int) a row2,+ Stencil (sh:.Int) a row1,+ Stencil (sh:.Int) a row0,+ i1 ~ Int, i2 ~ Int)+ => Stencil (sh:.i1:.i2) a (row2, row1, row0) where+ stencilR = StencilRtup3 (stencilR @(sh:.Int) @a @row2) (stencilR @(sh:.Int) @a @row1) (stencilR @(sh:.Int) @a @row0)+ stencilPrj s = (stencilPrj @(sh:.Int) @a $ prj2 s,+ stencilPrj @(sh:.Int) @a $ prj1 s,+ stencilPrj @(sh:.Int) @a $ prj0 s)++type instance StencilR (sh:.i1:.i2) (row2, row1, row0)+ = Tup3 (StencilR (sh:.Int) row2) (StencilR (sh:.Int) row1) (StencilR (sh:.Int) row0)++instance (Stencil (sh:.Int) a row4,+ Stencil (sh:.Int) a row3,+ Stencil (sh:.Int) a row2,+ Stencil (sh:.Int) a row1,+ Stencil (sh:.Int) a row0,+ i1 ~ Int, i2 ~ Int)+ => Stencil (sh:.i1:.i2) a (row4, row3, row2, row1, row0) where+ stencilR = StencilRtup5 (stencilR @(sh:.Int) @a @row4) (stencilR @(sh:.Int) @a @row3) (stencilR @(sh:.Int) @a @row2)+ (stencilR @(sh:.Int) @a @row1) (stencilR @(sh:.Int) @a @row0)+ stencilPrj s = (stencilPrj @(sh:.Int) @a $ prj4 s,+ stencilPrj @(sh:.Int) @a $ prj3 s,+ stencilPrj @(sh:.Int) @a $ prj2 s,+ stencilPrj @(sh:.Int) @a $ prj1 s,+ stencilPrj @(sh:.Int) @a $ prj0 s)++type instance StencilR (sh:.i1:.i2) (row4, row3, row2, row1, row0)+ = Tup5 (StencilR (sh:.Int) row4) (StencilR (sh:.Int) row3) (StencilR (sh:.Int) row2)+ (StencilR (sh:.Int) row1) (StencilR (sh:.Int) row0)++instance (Stencil (sh:.Int) a row6,+ Stencil (sh:.Int) a row5,+ Stencil (sh:.Int) a row4,+ Stencil (sh:.Int) a row3,+ Stencil (sh:.Int) a row2,+ Stencil (sh:.Int) a row1,+ Stencil (sh:.Int) a row0,+ i1 ~ Int, i2 ~ Int)+ => Stencil (sh:.i1:.i2) a (row6, row5, row4, row3, row2, row1, row0) where+ stencilR = StencilRtup7 (stencilR @(sh:.Int) @a @row6) (stencilR @(sh:.Int) @a @row5) (stencilR @(sh:.Int) @a @row4)+ (stencilR @(sh:.Int) @a @row3) (stencilR @(sh:.Int) @a @row2) (stencilR @(sh:.Int) @a @row1)+ (stencilR @(sh:.Int) @a @row0)+ stencilPrj s = (stencilPrj @(sh:.Int) @a $ prj6 s,+ stencilPrj @(sh:.Int) @a $ prj5 s,+ stencilPrj @(sh:.Int) @a $ prj4 s,+ stencilPrj @(sh:.Int) @a $ prj3 s,+ stencilPrj @(sh:.Int) @a $ prj2 s,+ stencilPrj @(sh:.Int) @a $ prj1 s,+ stencilPrj @(sh:.Int) @a $ prj0 s)++type instance StencilR (sh:.i1:.i2) (row6, row5, row4, row3, row2, row1, row0)+ = Tup7 (StencilR (sh:.Int) row6) (StencilR (sh:.Int) row5) (StencilR (sh:.Int) row4)+ (StencilR (sh:.Int) row3) (StencilR (sh:.Int) row2) (StencilR (sh:.Int) row1)+ (StencilR (sh:.Int) row0)++instance (Stencil (sh:.Int) a row8,+ Stencil (sh:.Int) a row7,+ Stencil (sh:.Int) a row6,+ Stencil (sh:.Int) a row5,+ Stencil (sh:.Int) a row4,+ Stencil (sh:.Int) a row3,+ Stencil (sh:.Int) a row2,+ Stencil (sh:.Int) a row1,+ Stencil (sh:.Int) a row0,+ i1 ~ Int, i2 ~ Int)+ => Stencil (sh:.i1:.i2) a (row8, row7, row6, row5, row4, row3, row2, row1, row0) where+ stencilR = StencilRtup9 (stencilR @(sh:.Int) @a @row8) (stencilR @(sh:.Int) @a @row7) (stencilR @(sh:.Int) @a @row6)+ (stencilR @(sh:.Int) @a @row5) (stencilR @(sh:.Int) @a @row4) (stencilR @(sh:.Int) @a @row3)+ (stencilR @(sh:.Int) @a @row2) (stencilR @(sh:.Int) @a @row1) (stencilR @(sh:.Int) @a @row0)+ stencilPrj s = (stencilPrj @(sh:.Int) @a $ prj8 s,+ stencilPrj @(sh:.Int) @a $ prj7 s,+ stencilPrj @(sh:.Int) @a $ prj6 s,+ stencilPrj @(sh:.Int) @a $ prj5 s,+ stencilPrj @(sh:.Int) @a $ prj4 s,+ stencilPrj @(sh:.Int) @a $ prj3 s,+ stencilPrj @(sh:.Int) @a $ prj2 s,+ stencilPrj @(sh:.Int) @a $ prj1 s,+ stencilPrj @(sh:.Int) @a $ prj0 s)++type instance StencilR (sh:.i1:.i2) (row8, row7, row6, row5, row4, row3, row2, row1, row0)+ = Tup9 (StencilR (sh:.Int) row8) (StencilR (sh:.Int) row7) (StencilR (sh:.Int) row6)+ (StencilR (sh:.Int) row5) (StencilR (sh:.Int) row4) (StencilR (sh:.Int) row3)+ (StencilR (sh:.Int) row2) (StencilR (sh:.Int) row1) (StencilR (sh:.Int) row0)++prjTail :: SmartExp (t, a) -> SmartExp t+prjTail = SmartExp . Prj PairIdxLeft++prj0 :: SmartExp (t, a) -> SmartExp a+prj0 = SmartExp . Prj PairIdxRight++prj1 :: SmartExp ((t, a), s0) -> SmartExp a+prj1 = prj0 . prjTail++prj2 :: SmartExp (((t, a), s1), s0) -> SmartExp a+prj2 = prj1 . prjTail++prj3 :: SmartExp ((((t, a), s2), s1), s0) -> SmartExp a+prj3 = prj2 . prjTail++prj4 :: SmartExp (((((t, a), s3), s2), s1), s0) -> SmartExp a+prj4 = prj3 . prjTail++prj5 :: SmartExp ((((((t, a), s4), s3), s2), s1), s0) -> SmartExp a+prj5 = prj4 . prjTail++prj6 :: SmartExp (((((((t, a), s5), s4), s3), s2), s1), s0) -> SmartExp a+prj6 = prj5 . prjTail++prj7 :: SmartExp ((((((((t, a), s6), s5), s4), s3), s2), s1), s0) -> SmartExp a+prj7 = prj6 . prjTail++prj8 :: SmartExp (((((((((t, a), s7), s6), s5), s4), s3), s2), s1), s0) -> SmartExp a+prj8 = prj7 . prjTail+++-- Extracting type information+-- ---------------------------++class HasArraysR f where+ arraysR :: f a -> ArraysR a++instance HasArraysR SmartAcc where+ arraysR (SmartAcc e) = arraysR e++arrayR :: HasArraysR f => f (Array sh e) -> ArrayR (Array sh e)+arrayR acc = case arraysR acc of+ TupRsingle repr -> repr++instance HasArraysR acc => HasArraysR (PreSmartAcc acc exp) where+ arraysR = \case+ Atag repr _ -> repr+ Pipe _ _ repr _ _ _ -> repr+ Aforeign repr _ _ _ -> repr+ Acond _ a _ -> arraysR a+ Awhile _ _ _ a -> arraysR a+ Anil -> TupRunit+ Apair a1 a2 -> arraysR a1 `TupRpair` arraysR a2+ Aprj idx a | TupRpair t1 t2 <- arraysR a+ -> case idx of+ PairIdxLeft -> t1+ PairIdxRight -> t2+ Aprj _ _ -> error "Ejector seat? You're joking!"+ Atrace _ _ a -> arraysR a+ Use repr _ -> TupRsingle repr+ Unit tp _ -> TupRsingle $ ArrayR ShapeRz $ tp+ Generate repr _ _ -> TupRsingle repr+ Reshape shr _ a -> let ArrayR _ tp = arrayR a+ in TupRsingle $ ArrayR shr tp+ Replicate si _ a -> let ArrayR _ tp = arrayR a+ in TupRsingle $ ArrayR (sliceDomainR si) tp+ Slice si a _ -> let ArrayR _ tp = arrayR a+ in TupRsingle $ ArrayR (sliceShapeR si) tp+ Map _ tp _ a -> let ArrayR shr _ = arrayR a+ in TupRsingle $ ArrayR shr tp+ ZipWith _ _ tp _ a _ -> let ArrayR shr _ = arrayR a+ in TupRsingle $ ArrayR shr tp+ Fold _ _ _ a -> let ArrayR (ShapeRsnoc shr) tp = arrayR a+ in TupRsingle (ArrayR shr tp)+ FoldSeg _ _ _ _ a _ -> arraysR a+ Scan _ _ _ _ a -> arraysR a+ Scan' _ _ _ _ a -> let repr@(ArrayR (ShapeRsnoc shr) tp) = arrayR a+ in TupRsingle repr `TupRpair` TupRsingle (ArrayR shr tp)+ Permute _ _ a _ _ -> arraysR a+ Backpermute shr _ _ a -> let ArrayR _ tp = arrayR a+ in TupRsingle (ArrayR shr tp)+ Stencil s tp _ _ _ -> TupRsingle $ ArrayR (stencilShapeR s) tp+ Stencil2 s _ tp _ _ _ _ _ -> TupRsingle $ ArrayR (stencilShapeR s) tp+++class HasTypeR f where+ typeR :: HasCallStack => f t -> TypeR t++instance HasTypeR SmartExp where+ typeR (SmartExp e) = typeR e++instance HasTypeR exp => HasTypeR (PreSmartExp acc exp) where+ typeR = \case+ Tag tp _ -> tp+ Match _ e -> typeR e+ Const tp _ -> TupRsingle tp+ Nil -> TupRunit+ Pair e1 e2 -> typeR e1 `TupRpair` typeR e2+ Prj idx e+ | TupRpair t1 t2 <- typeR e -> case idx of+ PairIdxLeft -> t1+ PairIdxRight -> t2+ Prj _ _ -> error "I never joke about my work"+ VecPack vecR _ -> TupRsingle $ VectorScalarType $ vecRvector vecR+ VecUnpack vecR _ -> vecRtuple vecR+ ToIndex _ _ _ -> TupRsingle scalarTypeInt+ FromIndex shr _ _ -> shapeType shr+ Case _ ((_,c):_) -> typeR c+ Case{} -> internalError "encountered empty case"+ Cond _ e _ -> typeR e+ While t _ _ _ -> t+ PrimConst c -> TupRsingle $ SingleScalarType $ primConstType c+ PrimApp f _ -> snd $ primFunType f+ Index tp _ _ -> tp+ LinearIndex tp _ _ -> tp+ Shape shr _ -> shapeType shr+ ShapeSize _ _ -> TupRsingle scalarTypeInt+ Foreign tp _ _ _ -> tp+ Undef tp -> TupRsingle tp+ Coerce _ tp _ -> TupRsingle tp+++-- Smart constructors+-- ------------------++-- | Scalar expression inlet: make a Haskell value available for processing in+-- an Accelerate scalar expression.+--+-- Note that this embeds the value directly into the expression. Depending on+-- the backend used to execute the computation, this might not always be+-- desirable. For example, a backend that does external code generation may+-- embed this constant directly into the generated code, which means new code+-- will need to be generated and compiled every time the value changes. In such+-- cases, consider instead lifting scalar values into (singleton) arrays so that+-- they can be passed as an input to the computation and thus the value can+-- change without the need to generate fresh code.+--+constant :: forall e. (HasCallStack, Elt e) => e -> Exp e+constant = Exp . go (eltR @e) . fromElt+ where+ go :: HasCallStack => TypeR t -> t -> SmartExp t+ go TupRunit () = SmartExp $ Nil+ go (TupRsingle tp) c = SmartExp $ Const tp c+ go (TupRpair t1 t2) (c1, c2) = SmartExp $ go t1 c1 `Pair` go t2 c2++-- | 'undef' can be used anywhere a constant is expected, and indicates that the+-- consumer of the value can receive an unspecified bit pattern.+--+-- This is useful because a store of an undefined value can be assumed to not+-- have any effect; we can assume that the value is overwritten with bits that+-- happen to match what was already there. However, a store /to/ an undefined+-- location could clobber arbitrary memory, therefore, its use in such a context+-- would introduce undefined /behaviour/.+--+-- There are (at least) two cases where you may want to use this:+--+-- 1. The 'Data.Array.Accelerate.Language.permute' function requires an array+-- of default values, into which the new values are combined. However, if+-- you are sure the default values are not used, and will (eventually) be+-- completely overwritten, then 'Data.Array.Accelerate.Prelude.fill'ing an+-- array with this value will give you a new uninitialised array.+--+-- 2. In the definition of sum data types. See for example+-- "Data.Array.Accelerate.Data.Maybe" and+-- "Data.Array.Accelerate.Data.Either".+--+-- @since 1.2.0.0+--+undef :: forall e. Elt e => Exp e+undef = Exp $ go $ eltR @e+ where+ go :: TypeR t -> SmartExp t+ go TupRunit = SmartExp $ Nil+ go (TupRsingle t) = SmartExp $ Undef t+ go (TupRpair t1 t2) = SmartExp $ go t1 `Pair` go t2++-- | Get the innermost dimension of a shape.+--+-- The innermost dimension (right-most component of the shape) is the index of+-- the array which varies most rapidly, and corresponds to elements of the array+-- which are adjacent in memory.+--+-- Another way to think of this is, for example when writing nested loops over+-- an array in C, this index corresponds to the index iterated over by the+-- innermost nested loop.+--+indexHead :: (Elt sh, Elt a) => Exp (sh :. a) -> Exp a+indexHead (Exp x) = mkExp $ Prj PairIdxRight x++-- | Get all but the innermost element of a shape+--+indexTail :: (Elt sh, Elt a) => Exp (sh :. a) -> Exp sh+indexTail (Exp x) = mkExp $ Prj PairIdxLeft x+++-- Smart constructor for constants+--++mkMinBound :: (Elt t, IsBounded (EltR t)) => Exp t+mkMinBound = mkExp $ PrimConst (PrimMinBound boundedType)++mkMaxBound :: (Elt t, IsBounded (EltR t)) => Exp t+mkMaxBound = mkExp $ PrimConst (PrimMaxBound boundedType)++mkPi :: (Elt r, IsFloating (EltR r)) => Exp r+mkPi = mkExp $ PrimConst (PrimPi floatingType)+++-- Smart constructors for primitive applications+--++-- Operators from Floating++mkSin :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t+mkSin = mkPrimUnary $ PrimSin floatingType++mkCos :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t+mkCos = mkPrimUnary $ PrimCos floatingType++mkTan :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t+mkTan = mkPrimUnary $ PrimTan floatingType++mkAsin :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t+mkAsin = mkPrimUnary $ PrimAsin floatingType++mkAcos :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t+mkAcos = mkPrimUnary $ PrimAcos floatingType++mkAtan :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t+mkAtan = mkPrimUnary $ PrimAtan floatingType++mkSinh :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t+mkSinh = mkPrimUnary $ PrimSinh floatingType++mkCosh :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t+mkCosh = mkPrimUnary $ PrimCosh floatingType++mkTanh :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t+mkTanh = mkPrimUnary $ PrimTanh floatingType++mkAsinh :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t+mkAsinh = mkPrimUnary $ PrimAsinh floatingType++mkAcosh :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t+mkAcosh = mkPrimUnary $ PrimAcosh floatingType++mkAtanh :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t+mkAtanh = mkPrimUnary $ PrimAtanh floatingType++mkExpFloating :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t+mkExpFloating = mkPrimUnary $ PrimExpFloating floatingType++mkSqrt :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t+mkSqrt = mkPrimUnary $ PrimSqrt floatingType++mkLog :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t+mkLog = mkPrimUnary $ PrimLog floatingType++mkFPow :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t -> Exp t+mkFPow = mkPrimBinary $ PrimFPow floatingType++mkLogBase :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t -> Exp t+mkLogBase = mkPrimBinary $ PrimLogBase floatingType++-- Operators from Num++mkAdd :: (Elt t, IsNum (EltR t)) => Exp t -> Exp t -> Exp t+mkAdd = mkPrimBinary $ PrimAdd numType++mkSub :: (Elt t, IsNum (EltR t)) => Exp t -> Exp t -> Exp t+mkSub = mkPrimBinary $ PrimSub numType++mkMul :: (Elt t, IsNum (EltR t)) => Exp t -> Exp t -> Exp t+mkMul = mkPrimBinary $ PrimMul numType++mkNeg :: (Elt t, IsNum (EltR t)) => Exp t -> Exp t+mkNeg = mkPrimUnary $ PrimNeg numType++mkAbs :: (Elt t, IsNum (EltR t)) => Exp t -> Exp t+mkAbs = mkPrimUnary $ PrimAbs numType++mkSig :: (Elt t, IsNum (EltR t)) => Exp t -> Exp t+mkSig = mkPrimUnary $ PrimSig numType++-- Operators from Integral++mkQuot :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp t -> Exp t+mkQuot = mkPrimBinary $ PrimQuot integralType++mkRem :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp t -> Exp t+mkRem = mkPrimBinary $ PrimRem integralType++mkQuotRem :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp t -> (Exp t, Exp t)+mkQuotRem (Exp x) (Exp y) =+ let pair = SmartExp $ PrimQuotRem integralType `PrimApp` SmartExp (Pair x y)+ in (mkExp $ Prj PairIdxLeft pair, mkExp $ Prj PairIdxRight pair)++mkIDiv :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp t -> Exp t+mkIDiv = mkPrimBinary $ PrimIDiv integralType++mkMod :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp t -> Exp t+mkMod = mkPrimBinary $ PrimMod integralType++mkDivMod :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp t -> (Exp t, Exp t)+mkDivMod (Exp x) (Exp y) =+ let pair = SmartExp $ PrimDivMod integralType `PrimApp` SmartExp (Pair x y)+ in (mkExp $ Prj PairIdxLeft pair, mkExp $ Prj PairIdxRight pair)++-- Operators from Bits and FiniteBits++mkBAnd :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp t -> Exp t+mkBAnd = mkPrimBinary $ PrimBAnd integralType++mkBOr :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp t -> Exp t+mkBOr = mkPrimBinary $ PrimBOr integralType++mkBXor :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp t -> Exp t+mkBXor = mkPrimBinary $ PrimBXor integralType++mkBNot :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp t+mkBNot = mkPrimUnary $ PrimBNot integralType++mkBShiftL :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp Int -> Exp t+mkBShiftL = mkPrimBinary $ PrimBShiftL integralType++mkBShiftR :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp Int -> Exp t+mkBShiftR = mkPrimBinary $ PrimBShiftR integralType++mkBRotateL :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp Int -> Exp t+mkBRotateL = mkPrimBinary $ PrimBRotateL integralType++mkBRotateR :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp Int -> Exp t+mkBRotateR = mkPrimBinary $ PrimBRotateR integralType++mkPopCount :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp Int+mkPopCount = mkPrimUnary $ PrimPopCount integralType++mkCountLeadingZeros :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp Int+mkCountLeadingZeros = mkPrimUnary $ PrimCountLeadingZeros integralType++mkCountTrailingZeros :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp Int+mkCountTrailingZeros = mkPrimUnary $ PrimCountTrailingZeros integralType+++-- Operators from Fractional++mkFDiv :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t -> Exp t+mkFDiv = mkPrimBinary $ PrimFDiv floatingType++mkRecip :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t+mkRecip = mkPrimUnary $ PrimRecip floatingType++-- Operators from RealFrac++mkTruncate :: (Elt a, Elt b, IsFloating (EltR a), IsIntegral (EltR b)) => Exp a -> Exp b+mkTruncate = mkPrimUnary $ PrimTruncate floatingType integralType++mkRound :: (Elt a, Elt b, IsFloating (EltR a), IsIntegral (EltR b)) => Exp a -> Exp b+mkRound = mkPrimUnary $ PrimRound floatingType integralType++mkFloor :: (Elt a, Elt b, IsFloating (EltR a), IsIntegral (EltR b)) => Exp a -> Exp b+mkFloor = mkPrimUnary $ PrimFloor floatingType integralType++mkCeiling :: (Elt a, Elt b, IsFloating (EltR a), IsIntegral (EltR b)) => Exp a -> Exp b+mkCeiling = mkPrimUnary $ PrimCeiling floatingType integralType++-- Operators from RealFloat++mkAtan2 :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp t -> Exp t+mkAtan2 = mkPrimBinary $ PrimAtan2 floatingType++mkIsNaN :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp Bool+mkIsNaN = mkPrimUnaryBool $ PrimIsNaN floatingType++mkIsInfinite :: (Elt t, IsFloating (EltR t)) => Exp t -> Exp Bool+mkIsInfinite = mkPrimUnaryBool $ PrimIsInfinite floatingType++-- FIXME: add missing operations from Floating, RealFrac & RealFloat++-- Relational and equality operators++mkLt :: (Elt t, IsSingle (EltR t)) => Exp t -> Exp t -> Exp Bool+mkLt = mkPrimBinaryBool $ PrimLt singleType++mkGt :: (Elt t, IsSingle (EltR t)) => Exp t -> Exp t -> Exp Bool+mkGt = mkPrimBinaryBool $ PrimGt singleType++mkLtEq :: (Elt t, IsSingle (EltR t)) => Exp t -> Exp t -> Exp Bool+mkLtEq = mkPrimBinaryBool $ PrimLtEq singleType++mkGtEq :: (Elt t, IsSingle (EltR t)) => Exp t -> Exp t -> Exp Bool+mkGtEq = mkPrimBinaryBool $ PrimGtEq singleType++mkEq :: (Elt t, IsSingle (EltR t)) => Exp t -> Exp t -> Exp Bool+mkEq = mkPrimBinaryBool $ PrimEq singleType++mkNEq :: (Elt t, IsSingle (EltR t)) => Exp t -> Exp t -> Exp Bool+mkNEq = mkPrimBinaryBool $ PrimNEq singleType++mkMax :: (Elt t, IsSingle (EltR t)) => Exp t -> Exp t -> Exp t+mkMax = mkPrimBinary $ PrimMax singleType++mkMin :: (Elt t, IsSingle (EltR t)) => Exp t -> Exp t -> Exp t+mkMin = mkPrimBinary $ PrimMin singleType++-- Logical operators++mkLAnd :: Exp Bool -> Exp Bool -> Exp Bool+mkLAnd (Exp a) (Exp b) = mkExp $ SmartExp (PrimApp PrimLAnd (SmartExp $ Pair x y)) `Pair` SmartExp Nil+ where+ x = SmartExp $ Prj PairIdxLeft a+ y = SmartExp $ Prj PairIdxLeft b++mkLOr :: Exp Bool -> Exp Bool -> Exp Bool+mkLOr (Exp a) (Exp b) = mkExp $ SmartExp (PrimApp PrimLOr (SmartExp $ Pair x y)) `Pair` SmartExp Nil+ where+ x = SmartExp $ Prj PairIdxLeft a+ y = SmartExp $ Prj PairIdxLeft b++mkLNot :: Exp Bool -> Exp Bool+mkLNot (Exp a) = mkExp $ SmartExp (PrimApp PrimLNot x) `Pair` SmartExp Nil+ where+ x = SmartExp $ Prj PairIdxLeft a++-- Numeric conversions++mkFromIntegral :: (Elt a, Elt b, IsIntegral (EltR a), IsNum (EltR b)) => Exp a -> Exp b+mkFromIntegral = mkPrimUnary $ PrimFromIntegral integralType numType++mkToFloating :: (Elt a, Elt b, IsNum (EltR a), IsFloating (EltR b)) => Exp a -> Exp b+mkToFloating = mkPrimUnary $ PrimToFloating numType floatingType++-- Other conversions++-- NOTE: Restricted to scalar types with a type-level BitSizeEq constraint to+-- make this version "safe"+mkBitcast :: forall b a. (Elt a, Elt b, IsScalar (EltR a), IsScalar (EltR b), BitSizeEq (EltR a) (EltR b)) => Exp a -> Exp b+mkBitcast (Exp a) = mkExp $ Coerce (scalarType @(EltR a)) (scalarType @(EltR b)) a++mkCoerce :: Coerce (EltR a) (EltR b) => Exp a -> Exp b+mkCoerce (Exp a) = Exp $ mkCoerce' a++class Coerce a b where+ mkCoerce' :: SmartExp a -> SmartExp b++instance {-# OVERLAPS #-} (IsScalar a, IsScalar b, BitSizeEq a b) => Coerce a b where+ mkCoerce' = SmartExp . Coerce (scalarType @a) (scalarType @b)++instance (Coerce a1 b1, Coerce a2 b2) => Coerce (a1, a2) (b1, b2) where+ mkCoerce' a = SmartExp $ Pair (mkCoerce' $ SmartExp $ Prj PairIdxLeft a) (mkCoerce' $ SmartExp $ Prj PairIdxRight a)++instance Coerce a a where+ mkCoerce' = id++instance Coerce ((), a) a where+ mkCoerce' a = SmartExp $ Prj PairIdxRight a++instance Coerce a ((), a) where+ mkCoerce' = SmartExp . Pair (SmartExp Nil)++instance Coerce (a, ()) a where+ mkCoerce' a = SmartExp $ Prj PairIdxLeft a++instance Coerce a (a, ()) where+ mkCoerce' a = SmartExp (Pair a (SmartExp Nil))++++-- Auxiliary functions+-- --------------------++infixr 0 $$+($$) :: (b -> a) -> (c -> d -> b) -> c -> d -> a+(f $$ g) x y = f (g x y)++infixr 0 $$$+($$$) :: (b -> a) -> (c -> d -> e -> b) -> c -> d -> e -> a+(f $$$ g) x y z = f (g x y z)++infixr 0 $$$$+($$$$) :: (b -> a) -> (c -> d -> e -> f -> b) -> c -> d -> e -> f -> a+(f $$$$ g) x y z u = f (g x y z u)++infixr 0 $$$$$+($$$$$) :: (b -> a) -> (c -> d -> e -> f -> g -> b) -> c -> d -> e -> f -> g-> a+(f $$$$$ g) x y z u v = f (g x y z u v)++unAcc :: Arrays a => Acc a -> SmartAcc (Sugar.ArraysR a)+unAcc (Acc a) = a++unAccFunction :: (Arrays a, Arrays b) => (Acc a -> Acc b) -> SmartAcc (Sugar.ArraysR a) -> SmartAcc (Sugar.ArraysR b)+unAccFunction f = unAcc . f . Acc++mkExp :: PreSmartExp SmartAcc SmartExp (EltR t) -> Exp t+mkExp = Exp . SmartExp++unExp :: Exp e -> SmartExp (EltR e)+unExp (Exp e) = e++unExpFunction :: (Elt a, Elt b) => (Exp a -> Exp b) -> SmartExp (EltR a) -> SmartExp (EltR b)+unExpFunction f = unExp . f . Exp++unExpBinaryFunction :: (Elt a, Elt b, Elt c) => (Exp a -> Exp b -> Exp c) -> SmartExp (EltR a) -> SmartExp (EltR b) -> SmartExp (EltR c)+unExpBinaryFunction f a b = unExp $ f (Exp a) (Exp b)++mkPrimUnary :: (Elt a, Elt b) => PrimFun (EltR a -> EltR b) -> Exp a -> Exp b+mkPrimUnary prim (Exp a) = mkExp $ PrimApp prim a++mkPrimBinary :: (Elt a, Elt b, Elt c) => PrimFun ((EltR a, EltR b) -> EltR c) -> Exp a -> Exp b -> Exp c+mkPrimBinary prim (Exp a) (Exp b) = mkExp $ PrimApp prim (SmartExp $ Pair a b)++mkPrimUnaryBool :: Elt a => PrimFun (EltR a -> PrimBool) -> Exp a -> Exp Bool+mkPrimUnaryBool = mkCoerce @PrimBool $$ mkPrimUnary++mkPrimBinaryBool :: (Elt a, Elt b) => PrimFun ((EltR a, EltR b) -> PrimBool) -> Exp a -> Exp b -> Exp Bool+mkPrimBinaryBool = mkCoerce @PrimBool $$$ mkPrimBinary++unPair :: SmartExp (a, b) -> (SmartExp a, SmartExp b)+unPair e = (SmartExp $ Prj PairIdxLeft e, SmartExp $ Prj PairIdxRight e)++mkPairToTuple :: SmartAcc (a, b) -> SmartAcc (((), a), b)+mkPairToTuple e = SmartAcc Anil `pair` a `pair` b+ where+ a = SmartAcc $ Aprj PairIdxLeft e+ b = SmartAcc $ Aprj PairIdxRight e+ pair x y = SmartAcc $ Apair x y++class ApplyAcc a where+ type FromApplyAcc a+ applyAcc :: FromApplyAcc a -> a++instance ApplyAcc (SmartAcc a) where+ type FromApplyAcc (SmartAcc a) = PreSmartAcc SmartAcc SmartExp a+ applyAcc = SmartAcc++instance (Arrays a, ApplyAcc t) => ApplyAcc (Acc a -> t) where+ type FromApplyAcc (Acc a -> t) = SmartAcc (Sugar.ArraysR a) -> FromApplyAcc t+ applyAcc f a = applyAcc $ f (unAcc a)++instance (Elt a, ApplyAcc t) => ApplyAcc (Exp a -> t) where+ type FromApplyAcc (Exp a -> t) = SmartExp (EltR a) -> FromApplyAcc t+ applyAcc f a = applyAcc $ f (unExp a)++instance (Elt a, Elt b, ApplyAcc t) => ApplyAcc ((Exp a -> Exp b) -> t) where+ type FromApplyAcc ((Exp a -> Exp b) -> t) = (SmartExp (EltR a) -> SmartExp (EltR b)) -> FromApplyAcc t+ applyAcc f a = applyAcc $ f (unExpFunction a)++instance (Elt a, Elt b, Elt c, ApplyAcc t) => ApplyAcc ((Exp a -> Exp b -> Exp c) -> t) where+ type FromApplyAcc ((Exp a -> Exp b -> Exp c) -> t) = (SmartExp (EltR a) -> SmartExp (EltR b) -> SmartExp (EltR c)) -> FromApplyAcc t+ applyAcc f a = applyAcc $ f (unExpBinaryFunction a)++instance (Arrays a, Arrays b, ApplyAcc t) => ApplyAcc ((Acc a -> Acc b) -> t) where+ type FromApplyAcc ((Acc a -> Acc b) -> t) = (SmartAcc (Sugar.ArraysR a) -> SmartAcc (Sugar.ArraysR b)) -> FromApplyAcc t+ applyAcc f a = applyAcc $ f (unAccFunction a)+++-- Debugging+-- ---------++formatDirection :: Format r (Direction -> r)+formatDirection = later $ \case+ LeftToRight -> singleton 'l'+ RightToLeft -> singleton 'r'++formatPreAccOp :: Format r (PreSmartAcc acc exp arrs -> r)+formatPreAccOp = later $ \case+ Atag _ i -> bformat ("Atag " % int) i+ Use aR a -> bformat ("Use " % string) (showArrayShort 5 (showsElt (arrayRtype aR)) aR a)+ Pipe{} -> "Pipe"+ Acond{} -> "Acond"+ Awhile{} -> "Awhile"+ Apair{} -> "Apair"+ Anil{} -> "Anil"+ Aprj{} -> "Aprj"+ Atrace{} -> "Atrace"+ Unit{} -> "Unit"+ Generate{} -> "Generate"+ Reshape{} -> "Reshape"+ Replicate{} -> "Replicate"+ Slice{} -> "Slice"+ Map{} -> "Map"+ ZipWith{} -> "ZipWith"+ Fold _ _ z _ -> bformat ("Fold" % maybed "1" (fconst mempty)) z+ FoldSeg _ _ _ z _ _ -> bformat ("Fold" % maybed "1" (fconst mempty) % "Seg") z+ Scan d _ _ z _ -> bformat ("Scan" % formatDirection % maybed "1" (fconst mempty)) d z+ Scan' d _ _ _ _ -> bformat ("Scan" % formatDirection % "\'") d+ Permute{} -> "Permute"+ Backpermute{} -> "Backpermute"+ Stencil{} -> "Stencil"+ Stencil2{} -> "Stencil2"+ Aforeign{} -> "Aforeign"++formatPreExpOp :: Format r (PreSmartExp acc exp t -> r)+formatPreExpOp = later $ \case+ Tag _ i -> bformat ("Tag " % int) i+ Const t c -> bformat ("Const " % string) (showElt (TupRsingle t) c)+ Match{} -> "Match"+ Undef{} -> "Undef"+ Nil{} -> "Nil"+ Pair{} -> "Pair"+ Prj{} -> "Prj"+ VecPack{} -> "VecPack"+ VecUnpack{} -> "VecUnpack"+ ToIndex{} -> "ToIndex"+ FromIndex{} -> "FromIndex"+ Case{} -> "Case"+ Cond{} -> "Cond"+ While{} -> "While"+ PrimConst{} -> "PrimConst"+ PrimApp{} -> "PrimApp"+ Index{} -> "Index"+ LinearIndex{} -> "LinearIndex"+ Shape{} -> "Shape"+ ShapeSize{} -> "ShapeSize"+ Foreign{} -> "Foreign"+ Coerce{} -> "Coerce"+
+ src/Data/Array/Accelerate/Sugar/Array.hs view
@@ -0,0 +1,321 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Sugar.Array+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Sugar.Array+ where++import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Sugar.Shape+import Data.Array.Accelerate.Representation.Type+import qualified Data.Array.Accelerate.Representation.Array as R++import Control.DeepSeq+import Data.Kind+import Data.Typeable+import Language.Haskell.TH.Extra hiding ( Type )+import System.IO.Unsafe++import GHC.Exts ( IsList, IsString )+import GHC.Generics+import qualified GHC.Exts as GHC++-- $setup+-- >>> :seti -XOverloadedLists+++type Scalar = Array DIM0 -- ^ Scalar arrays hold a single element+type Vector = Array DIM1 -- ^ Vectors are one-dimensional arrays+type Matrix = Array DIM2 -- ^ Matrices are two-dimensional arrays++-- | Segment descriptor (vector of segment lengths)+--+-- To represent nested one-dimensional arrays, we use a flat array of data+-- values in conjunction with a /segment descriptor/, which stores the+-- lengths of the sub-arrays.+--+type Segments = Vector+++-- | Dense, regular, multi-dimensional arrays.+--+-- The 'Array' is the core computational unit of Accelerate; all programs+-- in Accelerate take zero or more arrays as input and produce one or more+-- arrays as output. The 'Array' type has two type parameters:+--+-- * /sh/: is the shape of the array, tracking the dimensionality and extent of+-- each dimension of the array; for example, 'DIM1' for one-dimensional+-- 'Vector's, 'DIM2' for two-dimensional matrices, and so on.+--+-- * /e/: represents the type of each element of the array; for example,+-- 'Int', 'Float', et cetera.+--+-- Array data is store unboxed in an unzipped struct-of-array representation.+-- Elements are laid out in row-major order (the right-most index of a 'Shape'+-- is the fastest varying). The allowable array element types are members of the+-- 'Elt' class, which roughly consists of:+--+-- * Signed and unsigned integers (8, 16, 32, and 64-bits wide).+-- * Floating point numbers (single and double precision)+-- * 'Char'+-- * 'Bool'+-- * ()+-- * Shapes formed from 'Z' and (':.')+-- * Nested tuples of all of these, currently up to 16-elements wide.+--+-- Note that 'Array' itself is not an allowable element type---there are no+-- nested arrays in Accelerate, regular arrays only!+--+-- If device and host memory are separate, arrays will be transferred to the+-- device when necessary (possibly asynchronously and in parallel with other+-- tasks) and cached on the device if sufficient memory is available. Arrays are+-- made available to embedded language computations via+-- 'Data.Array.Accelerate.use'.+--+-- Section "Getting data in" lists functions for getting data into and out of+-- the 'Array' type.+--+newtype Array sh e = Array (R.Array (EltR sh) (EltR e))+ deriving Typeable++instance (Shape sh, Elt e, Eq sh, Eq e) => Eq (Array sh e) where+ arr1 == arr2 = shape arr1 == shape arr2 && toList arr1 == toList arr2+ arr1 /= arr2 = shape arr1 /= shape arr2 || toList arr1 /= toList arr2++instance (Shape sh, Elt e, Show e) => Show (Array sh e) where+ show (Array arr) = R.showArray (shows . toElt @e) (arrayR @sh @e) arr++instance Elt e => IsList (Vector e) where+ type Item (Vector e) = e+ toList = toList+ fromListN n = fromList (Z:.n)+ fromList xs = GHC.fromListN (length xs) xs++instance IsString (Vector Char) where+ fromString s = fromList (Z :. length s) s++instance (Shape sh, Elt e) => NFData (Array sh e) where+ rnf (Array arr) = R.rnfArray (arrayR @sh @e) arr++-- Note: [Embedded class constraints on Array]+--+-- Previously, we had embedded 'Shape' and 'Elt' constraints on the 'Array'+-- constructor. This was occasionally convenient, however, this has a negative+-- impact on the kind of code which GHC can generate. For example, if we write+-- the function:+--+-- > (!) :: Array sh e -> sh -> e+--+-- Without the 'Shape' and 'Elt' constraints on the type signature, and instead+-- recover those when pattern matching on 'Array', then GHC is unable to+-- specialise functions past this point. In this example, even if 'sh' and 'e'+-- are fixed, GHC would not be able to inline the definitions from 'ArrayElt'+-- which perform the actual data accesses.+--+-- - TLM 2018-09-13+--++-- | Yield an array's shape+--+shape :: Shape sh => Array sh e -> sh+shape (Array arr) = toElt (R.shape arr)++-- | Change the shape of an array without altering its contents. The 'size' of+-- the source and result arrays must be identical.+--+reshape :: forall sh sh' e. (Shape sh, Shape sh') => sh -> Array sh' e -> Array sh e+reshape sh (Array arr) = Array $ R.reshape (shapeR @sh) (fromElt sh) (shapeR @sh') arr++-- | Return the value of an array at the given multidimensional index+--+infixl 9 !+(!) :: forall sh e. (Shape sh, Elt e) => Array sh e -> sh -> e+(!) (Array arr) ix = toElt $ R.indexArray (arrayR @sh @e) arr (fromElt ix)++-- | Return the value of an array at given the linear (row-major) index+--+infixl 9 !!+(!!) :: forall sh e. Elt e => Array sh e -> Int -> e+(!!) (Array arr) i = toElt $ R.linearIndexArray (eltR @e) arr i++-- | Create an array from its representation function, applied at each+-- index of the array+--+fromFunction :: (Shape sh, Elt e) => sh -> (sh -> e) -> Array sh e+fromFunction sh f = unsafePerformIO $! fromFunctionM sh (return . f)++-- | Create an array using a monadic function applied at each index+--+-- @since 1.2.0.0+--+fromFunctionM :: forall sh e. (Shape sh, Elt e) => sh -> (sh -> IO e) -> IO (Array sh e)+fromFunctionM sh f = Array <$> R.fromFunctionM (arrayR @sh @e) (fromElt sh) f'+ where+ f' x = do+ y <- f (toElt x)+ return (fromElt y)++-- | Create a vector from the concatenation of the given list of vectors+--+concatVectors :: forall e. Elt e => [Vector e] -> Vector e+concatVectors = toArr . R.concatVectors (eltR @e) . map fromArr++-- | Creates a new, uninitialized Accelerate array+--+allocateArray :: forall sh e. (Shape sh, Elt e) => sh -> IO (Array sh e)+allocateArray sh = Array <$> R.allocateArray (arrayR @sh @e) (fromElt sh)++-- | Convert elements of a list into an Accelerate 'Array'+--+-- This will generate a new multidimensional 'Array' of the specified shape and+-- extent by consuming elements from the list and adding them to the array in+-- row-major order.+--+-- >>> fromList (Z:.10) [0..] :: Vector Int+-- Vector (Z :. 10) [0,1,2,3,4,5,6,7,8,9]+--+-- Note that we pull elements off the list lazily, so infinite lists are+-- accepted:+--+-- >>> fromList (Z:.5:.10) (repeat 0) :: Matrix Float+-- Matrix (Z :. 5 :. 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]+--+-- You can also make use of the @OverloadedLists@ extension to produce+-- one-dimensional vectors from a /finite/ list.+--+-- >>> [0..9] :: Vector Int+-- Vector (Z :. 10) [0,1,2,3,4,5,6,7,8,9]+--+-- Note that this requires first traversing the list to determine its length,+-- and then traversing it a second time to collect the elements into the array,+-- thus forcing the spine of the list to be manifest on the heap.+--+fromList :: forall sh e. (Shape sh, Elt e) => sh -> [e] -> Array sh e+fromList sh xs = toArr $ R.fromList (arrayR @sh @e) (fromElt sh) $ map fromElt xs++-- | Convert an accelerated 'Array' to a list in row-major order+--+toList :: forall sh e. (Shape sh, Elt e) => Array sh e -> [e]+toList = map toElt . R.toList (arrayR @sh @e) . fromArr+++-- | The 'Arrays' class characterises the types which can appear in collective+-- Accelerate computations of type 'Data.Array.Accelerate.Acc'.+--+-- 'Arrays' consists of nested tuples of individual 'Array's, currently up+-- to 16-elements wide. Accelerate computations can thereby return multiple+-- results.+--+class Arrays a where+ -- | Type representation mapping, which explains how to convert from the+ -- surface type into the internal representation type, which consists+ -- only of 'Array', and '()' and '(,)' as type-level nil and snoc.+ --+ type ArraysR a :: Type+ type ArraysR a = GArraysR () (Rep a)++ arraysR :: R.ArraysR (ArraysR a)+ toArr :: ArraysR a -> a+ fromArr :: a -> ArraysR a++ default arraysR+ :: (GArrays (Rep a), ArraysR a ~ GArraysR () (Rep a))+ => R.ArraysR (ArraysR a)+ arraysR = garrays @(Rep a) TupRunit++ default toArr+ :: (Generic a, GArrays (Rep a), ArraysR a ~ GArraysR () (Rep a))+ => ArraysR a -> a+ toArr = to . snd . gtoArr @(Rep a) @()++ default fromArr+ :: (Generic a, GArrays (Rep a), ArraysR a ~ GArraysR () (Rep a))+ => a -> ArraysR a+ fromArr = (`gfromArr` ()) . from++arrayR :: forall sh e. (Shape sh, Elt e) => R.ArrayR (R.Array (EltR sh) (EltR e))+arrayR = R.ArrayR (shapeR @sh) (eltR @e)++class GArrays f where+ type GArraysR t f+ garrays :: R.ArraysR t -> R.ArraysR (GArraysR t f)+ gfromArr :: f a -> t -> GArraysR t f+ gtoArr :: GArraysR t f -> (t, f a)++instance GArrays U1 where+ type GArraysR t U1 = t+ garrays = id+ gfromArr U1 = id+ gtoArr t = (t, U1)++instance GArrays a => GArrays (M1 i c a) where+ type GArraysR t (M1 i c a) = GArraysR t a+ garrays = garrays @a+ gfromArr (M1 x) = gfromArr x+ gtoArr x = let (t, x1) = gtoArr x in (t, M1 x1)++instance Arrays a => GArrays (K1 i a) where+ type GArraysR t (K1 i a) = (t, ArraysR a)+ garrays t = TupRpair t (arraysR @a)+ gfromArr (K1 x) t = (t, fromArr x)+ gtoArr (t, x) = (t, K1 (toArr x))++instance (GArrays a, GArrays b) => GArrays (a :*: b) where+ type GArraysR t (a :*: b) = GArraysR (GArraysR t a) b+ garrays = garrays @b . garrays @a+ gfromArr (a :*: b) = gfromArr b . gfromArr a+ gtoArr t =+ let (t1, b) = gtoArr t+ (t2, a) = gtoArr t1+ in+ (t2, a :*: b)+++instance Arrays () where+ type ArraysR () = ()+ arraysR = TupRunit+ fromArr = id+ toArr = id++instance (Shape sh, Elt e) => Arrays (Array sh e) where+ type ArraysR (Array sh e) = R.Array (EltR sh) (EltR e)+ arraysR = R.arraysRarray (shapeR @sh) (eltR @e)+ fromArr (Array arr) = arr+ toArr = Array++runQ $ do+ let+ mkTuple :: Int -> Q Dec+ mkTuple n =+ let+ xs = [ mkName ('x' : show i) | i <- [0 .. n-1] ]+ ts = map varT xs+ res = tupT ts+ ctx = mapM (appT [t| Arrays |]) ts+ in+ instanceD ctx [t| Arrays $res |] []+ --+ mapM mkTuple [2..16]+
+ src/Data/Array/Accelerate/Sugar/Elt.hs view
@@ -0,0 +1,471 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Sugar.Elt+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Sugar.Elt ( Elt(..) )+ where++import Data.Array.Accelerate.Representation.Elt+import Data.Array.Accelerate.Representation.Tag+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Type++import Control.Applicative ( (<|>) )+import qualified Control.Monad.State.Lazy as LState+import Control.Monad.Fix ( mfix )+import Data.Char+import Data.Kind+import Data.Maybe ( fromMaybe )+import Data.Proxy+import Language.Haskell.TH.Extra hiding ( Type )++import GHC.Generics+++-- | The 'Elt' class characterises the allowable array element types, and+-- hence the types which can appear in scalar Accelerate expressions of+-- type 'Data.Array.Accelerate.Exp'.+--+-- Accelerate arrays consist of simple atomic types as well as nested+-- tuples thereof, stored efficiently in memory as consecutive unpacked+-- elements without pointers. It roughly consists of:+--+-- * Signed and unsigned integers (8, 16, 32, and 64-bits wide)+-- * Floating point numbers (half, single, and double precision)+-- * 'Char'+-- * 'Bool'+-- * ()+-- * Shapes formed from 'Z' and (':.')+-- * Nested tuples of all of these, currently up to 16-elements wide+--+-- Adding new instances for 'Elt' consists of explaining to Accelerate how+-- to map between your data type and a (tuple of) primitive values. For+-- examples see:+--+-- * "Data.Array.Accelerate.Data.Complex"+-- * "Data.Array.Accelerate.Data.Monoid"+-- * <https://hackage.haskell.org/package/linear-accelerate linear-accelerate>+-- * <https://hackage.haskell.org/package/colour-accelerate colour-accelerate>+--+-- For simple types it is possible to derive 'Elt' automatically, for+-- example:+--+-- > data Point = Point Int Float+-- > deriving (Generic, Elt)+--+-- > data Option a = None | Just a+-- > deriving (Generic, Elt)+--+-- See the function 'Data.Array.Accelerate.match' for details on how to use+-- sum types in embedded code.+--+class Elt a where+ -- | Type representation mapping, which explains how to convert a type+ -- from the surface type into the internal representation type consisting+ -- only of simple primitive types, unit '()', and pair '(,)'.+ --+ type EltR a :: Type+ type EltR a = GEltR () (Rep a)+ --+ eltR :: TypeR (EltR a)+ tagsR :: [TagR (EltR a)]+ fromElt :: a -> EltR a+ toElt :: EltR a -> a++ default eltR+ :: (GElt (Rep a), EltR a ~ GEltR () (Rep a))+ => TypeR (EltR a)+ eltR = geltR @(Rep a) TupRunit++ default tagsR+ :: (Generic a, GElt (Rep a), EltR a ~ GEltR () (Rep a))+ => [TagR (EltR a)]+ tagsR = gtagsR @(Rep a) TagRunit++ default fromElt+ :: (Generic a, GElt (Rep a), EltR a ~ GEltR () (Rep a))+ => a+ -> EltR a+ fromElt = gfromElt () . from++ default toElt+ :: (Generic a, GElt (Rep a), EltR a ~ GEltR () (Rep a))+ => EltR a+ -> a+ toElt = to . snd . gtoElt @(Rep a) @()+++-- | Given:+--+-- > data Test = A Int | B Int Float | C Float | D Double deriving (Show, Generic, Elt)+--+-- the call `geltR @(Rep Test) t` produces:+--+-- > TupRsingle Word8 :* (t :* tInt :* tInt :* tFloat :* tFloat :* tDouble)+--+-- where we abbreviate:+--+-- * TupRpair as (:*), infixl (i.e. "a :* b :* c" means "(a :* b) :* c")+-- * TupRsingle Int as tInt+-- * TupRsingle Float as tFloat+--+-- The first Word8 is the sum type tag.+--+-- This tag is not generated if there is only one constructor, so for example, given:+--+-- > data Test2 = T Int Float deriving (Show, Generic, Elt)+--+-- the call `geltR @Test2 t` produces: (using the same abbreviations)+--+-- > t :* tInt :* tFloat+--+-- To make sure the tag gets included conditionally, but only once if there are+-- many levels of (:+:) in the Generics representation -- and to furthermore+-- avoid needing a third type class -- we do a bit of a strange dance.+--+-- * The Elt default methods invoke GElt at the Rep of the data type. This may+-- be a (:+:) if it has more than 1 constructor, and something else+-- otherwise.+-- * GElt generates the tag in its instance for (:+:), and calls out to GSumElt+-- to actually handle the sum type constructors. Whenever GSumElt reaches a+-- non-(:+:), it calls back into GElt, which, from now on, will never+-- encounter (:+:) any more.+-- * GElt then handles the products (i.e. the data type constructor fields) and+-- finishes.+--+-- So to understand the full, precise control flow, one should start reading in+-- Elt, proceed with the GElt class and its (:+:) instance, then the full+-- definition of GSumElt, and finally the remaining instances of GElt.+class GElt f where+ -- | The @t@ variable is an additional uninterpreted type that's paired up+ -- all the way at the left of the produced (left-associated) product. The+ -- functions here are written in "CPS-style", in order to produce a long list+ -- instead of a tree structure.+ type GEltR t f+ geltR :: TypeR t -> TypeR (GEltR t f)+ -- | This expands all sum types recursively; see the doc comment on 'TagR'.+ gtagsR :: TagR t -> [TagR (GEltR t f)]+ gfromElt :: t -> f a -> GEltR t f+ gtoElt :: GEltR t f -> (t, f a)+ --+ gundef :: t -> GEltR t f+ guntag :: TagR t -> TagR (GEltR t f) -- ^ generate TagRundef for all leaves++instance GElt U1 where+ type GEltR t U1 = t+ geltR t = t+ gtagsR t = [t]+ gfromElt t U1 = t+ gtoElt t = (t, U1)+ gundef t = t+ guntag t = t++instance GElt a => GElt (M1 i c a) where+ type GEltR t (M1 i c a) = GEltR t a+ geltR = geltR @a+ gtagsR = gtagsR @a+ gfromElt t (M1 x) = gfromElt t x+ gtoElt x = let (t, x1) = gtoElt x in (t, M1 x1)+ gundef = gundef @a+ guntag = guntag @a++instance Elt a => GElt (K1 i a) where+ type GEltR t (K1 i a) = (t, EltR a)+ geltR t = TupRpair t (eltR @a)+ gtagsR t = TagRpair t <$> tagsR @a+ gfromElt t (K1 x) = (t, fromElt x)+ gtoElt (t, x) = (t, K1 (toElt x))+ gundef t = (t, undefElt (eltR @a))+ guntag t = TagRpair t (untag (eltR @a))++instance (GElt a, GElt b) => GElt (a :*: b) where+ type GEltR t (a :*: b) = GEltR (GEltR t a) b+ geltR = geltR @b . geltR @a+ gtagsR = concatMap (gtagsR @b) . gtagsR @a+ gfromElt t (a :*: b) = gfromElt (gfromElt t a) b+ gtoElt t =+ let (t1, b) = gtoElt t+ (t2, a) = gtoElt t1+ in+ (t2, a :*: b)+ gundef t = gundef @b (gundef @a t)+ guntag t = guntag @b (guntag @a t)++instance (GElt a, GElt b, GSumElt (a :+: b)) => GElt (a :+: b) where+ type GEltR t (a :+: b) = (TAG, GSumEltR t (a :+: b))+ geltR t = TupRpair (TupRsingle scalarType) (gsumEltR @(a :+: b) t)+ gtagsR t = uncurry TagRtag <$> LState.evalState (gsumTagsR @(a :+: b) t) 0+ gfromElt t x = LState.evalState (gsumFromElt t x) 0+ gtoElt (k,x) = let (t, x') = LState.evalState (gsumToElt k x) 0+ in (t, fromMaybe (error err) x')+ where err = "Elt: no sum type tag matched (k=" ++ show k ++ ")"+ gundef t = (0xff, gsumUndef @(a :+: b) t)+ guntag t = TagRpair (TagRundef scalarType) (gsumUntag @(a :+: b) t)+++class GSumElt f where+ type GSumEltR t f+ gsumEltR :: TypeR t -> TypeR (GSumEltR t f)+ -- | The state monad here is a /lazy/ state monad. We need this for 'gsumToElt' of '(:+:)'.+ gsumTagsR :: TagR t -> LState.State TAG [(TAG, TagR (GSumEltR t f))]+ gsumFromElt :: t -> f a -> LState.State TAG (TAG, GSumEltR t f)+ gsumCountTags :: Proxy f -> LState.State TAG ()+ gsumToElt :: TAG -> GSumEltR t f -> LState.State TAG (t, Maybe (f a))+ gsumUndef :: t -> GSumEltR t f+ gsumUntag :: TagR t -> TagR (GSumEltR t f)++genTag :: LState.State TAG TAG+genTag = LState.state (\s -> (s, s + 1))++instance GSumElt U1 where+ type GSumEltR t U1 = t+ gsumEltR t = t+ gsumTagsR t = do n <- genTag; pure [(n, t)]+ gsumFromElt t U1 = do n <- genTag; pure (n, t)+ gsumCountTags _ = () <$ genTag+ gsumToElt k t = do n <- genTag+ pure (t, if n == k then Just U1 else Nothing)+ gsumUndef t = t+ gsumUntag t = t++instance GSumElt a => GSumElt (M1 i c a) where+ type GSumEltR t (M1 i c a) = GSumEltR t a+ gsumEltR = gsumEltR @a+ gsumTagsR = gsumTagsR @a+ gsumFromElt t (M1 x) = gsumFromElt t x+ gsumCountTags _ = gsumCountTags (Proxy @a)+ gsumToElt k x = (\(t, x') -> (t, fmap M1 x')) <$> gsumToElt k x+ gsumUndef = gsumUndef @a+ gsumUntag = gsumUntag @a++instance Elt a => GSumElt (K1 i a) where+ type GSumEltR t (K1 i a) = (t, EltR a)+ gsumEltR t = TupRpair t (eltR @a)+ gsumTagsR t = do n <- genTag; pure ((n,) . TagRpair t <$> tagsR @a)+ gsumFromElt t (K1 x) = do n <- genTag; pure (n, (t, fromElt x))+ gsumCountTags _ = () <$ genTag+ gsumToElt k ~(t, x) = do n <- genTag+ pure (t, if n == k then Just (K1 (toElt x)) else Nothing)+ gsumUndef t = (t, undefElt (eltR @a))+ gsumUntag t = TagRpair t (untag (eltR @a))++instance (GElt a, GElt b) => GSumElt (a :*: b) where+ type GSumEltR t (a :*: b) = GEltR t (a :*: b)+ gsumEltR = geltR @(a :*: b)+ gsumTagsR t = do n <- genTag; pure ((n,) <$> gtagsR @(a :*: b) t)+ gsumFromElt t (a :*: b) = do n <- genTag; pure (n, gfromElt t (a :*: b))+ gsumCountTags _ = () <$ genTag+ gsumToElt k t0 = do n <- genTag+ -- Note that gtoElt produces x lazily, so this+ -- does not read any spurious undefs.+ let (t, x) = gtoElt t0+ pure (t, if n == k then Just x else Nothing)+ gsumUndef = gundef @(a :*: b)+ gsumUntag = guntag @(a :*: b)++instance (GSumElt a, GSumElt b) => GSumElt (a :+: b) where+ type GSumEltR t (a :+: b) = GSumEltR (GSumEltR t a) b+ gsumEltR = gsumEltR @b . gsumEltR @a++ gsumTagsR t = do+ a <- gsumTagsR @a t+ -- join b (filled with undefs) to the TagR's for 'a':+ let a' = map (\(tag, tagrA) -> (tag, gsumUntag @b tagrA)) a+ b <- gsumTagsR @b (gsumUntag @a t)+ pure (a' ++ b)++ gsumFromElt t (L1 a) = do+ (n, reprA) <- gsumFromElt t a+ pure (n, gsumUndef @b reprA) -- join undef-filled b to this rep of A+ gsumFromElt t (R1 b) = do+ gsumCountTags (Proxy @a) -- skip the tags in the left alternatives+ gsumFromElt (gsumUndef @a t) b++ gsumCountTags _ = gsumCountTags (Proxy @a) >> gsumCountTags (Proxy @b)++ gsumToElt k t0 = do+ -- The starting tag for the traversal of 'b' depends on the number of tags+ -- generated when traversing 'a'. However, in t0, the data for 'b' is+ -- on the outside, meaning that we can only get the initial 't' for the 'a'+ -- traversal by traversing 'b' first. We solve this circular dependency by+ -- observing that gsumToElt can count the tags before it needs its 't'+ -- argument, so we can tie a knot.+ -- We could also escape the State monad here with evalState, and explicitly+ -- gsumCountTags first, then traverse 'b', and finally traverse 'a'. But+ -- that would be ugly.+ (_t1, t2, mres1, mres2) <- mfix $ \ ~(t1, _t2, _mres1, _mres2) ->do+ (t2', mres2) <- gsumToElt @a k t1+ (t1', mres1) <- gsumToElt @b k t0+ pure (t1', t2', mres1, mres2)+ pure (t2, (R1 <$> mres1) <|> (L1 <$> mres2))++ gsumUndef t = gsumUndef @b (gsumUndef @a t)+ gsumUntag t = gsumUntag @b (gsumUntag @a t)+++untag :: TypeR t -> TagR t+untag TupRunit = TagRunit+untag (TupRsingle t) = TagRundef t+untag (TupRpair ta tb) = TagRpair (untag ta) (untag tb)+++-- Note: [Deriving Elt]+--+-- We can't use the cunning generalised newtype deriving mechanism, because+-- the generated 'eltR' function does not type check. For example, it will+-- generate the following implementation for 'CShort':+--+-- > eltR+-- > = coerce+-- > @(TypeR (EltR Int16))+-- > @(TypeR (EltR CShort))+-- > (eltR :: TypeR (EltR CShort))+--+-- Which yields the error "couldn't match type 'EltR a0' with 'Int16'".+-- Since this function returns a type family type, the type signature on the+-- result is not enough to fix the type 'a'. Instead, we require the use of+-- (visible) type applications:+--+-- > eltR+-- > = coerce+-- > @(TypeR (EltR Int16))+-- > @(TypeR (EltR CShort))+-- > (eltR @(EltR CShort))+--+-- Note that this does not affect deriving instances via 'Generic'+--+-- Instances for basic types are generated at the end of this module.+--++instance Elt ()+instance Elt Bool+instance Elt Ordering+instance Elt a => Elt (Maybe a)+instance (Elt a, Elt b) => Elt (Either a b)++instance Elt Char where+ type EltR Char = Word32+ eltR = TupRsingle scalarType+ tagsR = [TagRsingle scalarType]+ toElt = chr . fromIntegral+ fromElt = fromIntegral . ord++runQ $ do+ let+ -- XXX: we might want to do the digItOut trick used by FromIntegral?+ --+ integralTypes :: [Name]+ integralTypes =+ [ ''Int+ , ''Int8+ , ''Int16+ , ''Int32+ , ''Int64+ , ''Word+ , ''Word8+ , ''Word16+ , ''Word32+ , ''Word64+ ]++ floatingTypes :: [Name]+ floatingTypes =+ [ ''Half+ , ''Float+ , ''Double+ ]++ newtypes :: [Name]+ newtypes =+ [ ''CShort+ , ''CUShort+ , ''CInt+ , ''CUInt+ , ''CLong+ , ''CULong+ , ''CLLong+ , ''CULLong+ , ''CFloat+ , ''CDouble+ , ''CChar+ , ''CSChar+ , ''CUChar+ ]++ mkSimple :: Name -> Q [Dec]+ mkSimple name =+ let t = conT name+ in+ [d| instance Elt $t where+ type EltR $t = $t+ eltR = TupRsingle scalarType+ tagsR = [TagRsingle scalarType]+ fromElt = id+ toElt = id+ |]++ mkTuple :: Int -> Q Dec+ mkTuple n =+ let+ xs = [ mkName ('x' : show i) | i <- [0 .. n-1] ]+ ts = map varT xs+ res = tupT ts+ ctx = mapM (appT [t| Elt |]) ts+ in+ instanceD ctx [t| Elt $res |] []++ -- mkVecElt :: Name -> Integer -> Q [Dec]+ -- mkVecElt name n =+ -- let t = conT name+ -- v = [t| Vec $(litT (numTyLit n)) $t |]+ -- in+ -- [d| instance Elt $v where+ -- type EltR $v = $v+ -- eltR = TupRsingle scalarType+ -- fromElt = id+ -- toElt = id+ -- |]++ -- ghci> $( stringE . show =<< reify ''CFloat )+ -- TyConI (NewtypeD [] Foreign.C.Types.CFloat [] Nothing (NormalC Foreign.C.Types.CFloat [(Bang NoSourceUnpackedness NoSourceStrictness,ConT GHC.Types.Float)]) [])+ --+ mkNewtype :: Name -> Q [Dec]+ mkNewtype name = do+ r <- reify name+ base <- case r of+ TyConI (NewtypeD _ _ _ _ (NormalC _ [(_, ConT b)]) _) -> return b+ _ -> error "unexpected case generating newtype Elt instance"+ --+ [d| instance Elt $(conT name) where+ type EltR $(conT name) = $(conT base)+ eltR = TupRsingle scalarType+ tagsR = [TagRsingle scalarType]+ fromElt $(conP (mkName (nameBase name)) [varP (mkName "x")]) = x+ toElt = $(conE (mkName (nameBase name)))+ |]+ --+ ss <- mapM mkSimple (integralTypes ++ floatingTypes)+ ns <- mapM mkNewtype newtypes+ ts <- mapM mkTuple [2..16]+ -- vs <- sequence [ mkVecElt t n | t <- integralTypes ++ floatingTypes, n <- [2,3,4,8,16] ]+ return (concat ss ++ concat ns ++ ts)+
+ src/Data/Array/Accelerate/Sugar/Foreign.hs view
@@ -0,0 +1,38 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Sugar.Foreign+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Sugar.Foreign+ where++import Data.Array.Accelerate.Error++import Data.Typeable+import Language.Haskell.TH.Extra+++-- Class for backends to choose their own representation of foreign functions.+-- By default it has no instances. If a backend wishes to have an FFI it must+-- provide an instance.+--+class Typeable asm => Foreign asm where++ -- Backends should be able to produce a string representation of the foreign+ -- function for pretty printing, typically the name of the function.+ strForeign :: asm args -> String+ strForeign _ = "<foreign>"++ -- Backends which want to support compile-time embedding must be able to lift+ -- the foreign function into Template Haskell+ liftForeign :: HasCallStack => asm args -> CodeQ (asm args)+ liftForeign _ = internalError "not supported by this backend"+
+ src/Data/Array/Accelerate/Sugar/Shape.hs view
@@ -0,0 +1,379 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Sugar.Shape+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- Array indices are snoc lists at both the type and value level. That is,+-- they're backwards, where the end-of-list token, 'Z', occurs first. For+-- example, the type of a rank-2 array index is @Z :. Int :. Int@, and+-- shape of a rank-2 array with 5 rows and 10 columns is @Z :. 5 :. 10@.+--+-- In Accelerate the rightmost dimension is the /fastest varying/ or+-- innermost; these values are adjacent in memory.+--++module Data.Array.Accelerate.Sugar.Shape+ where++import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Representation.Tag+import Data.Array.Accelerate.Representation.Type+import qualified Data.Array.Accelerate.Representation.Shape as R+import qualified Data.Array.Accelerate.Representation.Slice as R++import Data.Kind+import GHC.Generics+++-- Shorthand for common shape types+--+type DIM0 = Z+type DIM1 = DIM0 :. Int+type DIM2 = DIM1 :. Int+type DIM3 = DIM2 :. Int+type DIM4 = DIM3 :. Int+type DIM5 = DIM4 :. Int+type DIM6 = DIM5 :. Int+type DIM7 = DIM6 :. Int+type DIM8 = DIM7 :. Int+type DIM9 = DIM8 :. Int++-- | Rank-0 index+--+data Z = Z+ deriving (Show, Eq, Generic, Elt)++-- | Increase an index rank by one dimension. The ':.' operator is used to+-- construct both values and types.+--+infixl 3 :.+data tail :. head = !tail :. !head+ deriving (Eq, Generic) -- Not deriving Elt or Show++-- We don't we use a derived Show instance for (:.) because this will insert+-- parenthesis to demonstrate which order the operator is applied, i.e.:+--+-- (((Z :. z) :. y) :. x)+--+-- This is fine, but I find it a little unsightly. Instead, we drop all+-- parenthesis and just display the shape thus:+--+-- Z :. z :. y :. x+--+-- and then require the down-stream user to wrap the whole thing in parentheses.+-- This works fine for the most important case, which is to show Acc and Exp+-- expressions via the pretty printer, although Show-ing a Shape directly+-- results in no parenthesis being displayed.+--+-- One way around this might be to have specialised instances for DIM1, DIM2,+-- etc.+--+instance (Show sh, Show sz) => Show (sh :. sz) where+ showsPrec p (sh :. sz) =+ showsPrec p sh . showString " :. " . showsPrec p sz++-- | Marker for entire dimensions in 'Data.Array.Accelerate.Language.slice' and+-- 'Data.Array.Accelerate.Language.replicate' descriptors.+--+-- Occurrences of 'All' indicate the dimensions into which the array's existing+-- extent will be placed unchanged.+--+-- See 'Data.Array.Accelerate.Language.slice' and+-- 'Data.Array.Accelerate.Language.replicate' for examples.+--+data All = All+ deriving (Show, Eq, Generic, Elt)++-- | Marker for arbitrary dimensions in 'Data.Array.Accelerate.Language.slice'+-- and 'Data.Array.Accelerate.Language.replicate' descriptors.+--+-- 'Any' can be used in the leftmost position of a slice instead of 'Z',+-- indicating that any dimensionality is admissible in that position.+--+-- See 'Data.Array.Accelerate.Language.slice' and+-- 'Data.Array.Accelerate.Language.replicate' for examples.+--+data Any sh = Any+ deriving (Show, Eq, Generic)++-- | Marker for splitting along an entire dimension in division descriptors.+--+-- For example, when used in a division descriptor passed to+-- 'Data.Array.Accelerate.toSeq', a `Split` indicates that the array should be+-- divided along this dimension forming the elements of the output sequence.+--+data Split = Split+ deriving (Show, Eq)++-- | Marker for arbitrary shapes in slices descriptors, where it is desired to+-- split along an unknown number of dimensions.+--+-- For example, in the following definition, 'Divide' matches against any shape+-- and flattens everything but the innermost dimension.+--+-- > vectors :: (Shape sh, Elt e) => Acc (Array (sh:.Int) e) -> Seq [Vector e]+-- > vectors = toSeq (Divide :. All)+--+data Divide sh = Divide+ deriving (Show, Eq)+++-- | Number of dimensions of a /shape/ or /index/ (>= 0)+--+rank :: forall sh. Shape sh => Int+rank = R.rank (shapeR @sh)++-- | Total number of elements in an array of the given /shape/+--+size :: forall sh. Shape sh => sh -> Int+size = R.size (shapeR @sh) . fromElt++-- | The empty /shape/+--+empty :: forall sh. Shape sh => sh+empty = toElt $ R.empty (shapeR @sh)++-- | Yield the intersection of two shapes+intersect :: forall sh. Shape sh => sh -> sh -> sh+intersect x y = toElt $ R.intersect (shapeR @sh) (fromElt x) (fromElt y)++-- | Yield the union of two shapes+--+union :: forall sh. Shape sh => sh -> sh -> sh+union x y = toElt $ R.union (shapeR @sh) (fromElt x) (fromElt y)++-- | Map a multi-dimensional index into one in a linear, row-major+-- representation of the array (first argument is the /shape/, second+-- argument is the index).+--+toIndex :: forall sh. Shape sh+ => sh -- ^ Total shape (extent) of the array+ -> sh -- ^ The argument index+ -> Int -- ^ Corresponding linear index+toIndex sh ix = R.toIndex (shapeR @sh) (fromElt sh) (fromElt ix)++-- | Inverse of 'toIndex'.+--+fromIndex :: forall sh. Shape sh+ => sh -- ^ Total shape (extent) of the array+ -> Int -- ^ The argument index+ -> sh -- ^ Corresponding multi-dimensional index+fromIndex sh = toElt . R.fromIndex (shapeR @sh) (fromElt sh)++-- | Iterate through all of the indices of a shape, applying the given+-- function at each index. The index space is traversed in row-major order.+--+iter :: forall sh e. Shape sh+ => sh -- ^ The total shape (extent) of the index space+ -> (sh -> e) -- ^ Function to apply at each index+ -> (e -> e -> e) -- ^ Function to combine results+ -> e -- ^ Value to return in case of an empty iteration space+ -> e+iter sh f = R.iter (shapeR @sh) (fromElt sh) (f . toElt)++-- | Variant of 'iter' without an initial value+--+iter1 :: forall sh e. Shape sh+ => sh+ -> (sh -> e)+ -> (e -> e -> e)+ -> e+iter1 sh f = R.iter1 (shapeR @sh) (fromElt sh) (f . toElt)++-- | Convert a minpoint-maxpoint index into a zero-indexed shape+--+rangeToShape :: forall sh. Shape sh => (sh, sh) -> sh+rangeToShape (u, v) = toElt $ R.rangeToShape (shapeR @sh) (fromElt u, fromElt v)++-- | Convert a shape into a minpoint-maxpoint index+--+shapeToRange :: forall sh. Shape sh => sh -> (sh, sh)+shapeToRange ix =+ let (u, v) = R.shapeToRange (shapeR @sh) (fromElt ix)+ in (toElt u, toElt v)++-- | Convert a shape to a list of dimensions+--+shapeToList :: forall sh. Shape sh => sh -> [Int]+shapeToList = R.shapeToList (shapeR @sh) . fromElt++-- | Convert a list of dimensions into a shape. If the list does not+-- contain exactly the number of elements as specified by the type of the+-- shape: error.+--+listToShape :: forall sh. Shape sh => [Int] -> sh+listToShape = toElt . R.listToShape (shapeR @sh)++-- | Attempt to convert a list of dimensions into a shape+--+listToShape' :: forall sh. Shape sh => [Int] -> Maybe sh+listToShape' = fmap toElt . R.listToShape' (shapeR @sh)++-- | Nicely format a shape as a string+--+showShape :: Shape sh => sh -> String+showShape = foldr (\sh str -> str ++ " :. " ++ show sh) "Z" . shapeToList++-- | Project the shape of a slice from the full shape+--+sliceShape+ :: (Shape sl, Shape dim)+ => R.SliceIndex slix (EltR sl) co (EltR dim)+ -> dim+ -> sl+sliceShape slx = toElt . R.sliceShape slx . fromElt++-- | Project the full shape from a slice+--+sliceDomain+ :: (Elt slix, Shape sl, Shape dim)+ => R.SliceIndex (EltR slix) (EltR sl) co (EltR dim)+ -> slix+ -> sl+ -> dim+sliceDomain slx slix sl = toElt $ R.sliceDomain slx (fromElt slix) (fromElt sl)++-- | Enumerate all slices within a given bound. The innermost dimension+-- changes most rapidly.+--+-- Example:+--+-- > let slix = sliceIndex @(Z :. Int :. Int :. All)+-- > sh = Z :. 2 :. 3 :. 1 :: DIM3+-- > in+-- > enumSlices slix sh :: [ Z :. Int :. Int :. All ]+--+enumSlices :: forall slix co sl dim. (Elt slix, Elt dim)+ => R.SliceIndex (EltR slix) sl co (EltR dim)+ -> dim -- Bounds+ -> [slix] -- All slices within bounds.+enumSlices slix = map toElt . R.enumSlices slix . fromElt++-- | Shapes and indices of multi-dimensional arrays+--+class (Elt sh, Elt (Any sh), FullShape sh ~ sh, CoSliceShape sh ~ sh, SliceShape sh ~ Z)+ => Shape sh where++ -- | Reified type witness for shapes+ shapeR :: R.ShapeR (EltR sh)++ -- | The slice index for slice specifier 'Any sh'+ sliceAnyIndex :: R.SliceIndex (EltR (Any sh)) (EltR sh) () (EltR sh)++ -- | The slice index for specifying a slice with only the Z component projected+ sliceNoneIndex :: R.SliceIndex (EltR sh) () (EltR sh) (EltR sh)+++-- | Slices, aka generalised indices, as /n/-tuples and mappings of slice+-- indices to slices, co-slices, and slice dimensions+--+class (Elt sl, Shape (SliceShape sl), Shape (CoSliceShape sl), Shape (FullShape sl))+ => Slice sl where+ type SliceShape sl :: Type -- the projected slice+ type CoSliceShape sl :: Type -- the complement of the slice+ type FullShape sl :: Type -- the combined dimension+ sliceIndex :: R.SliceIndex (EltR sl)+ (EltR (SliceShape sl))+ (EltR (CoSliceShape sl))+ (EltR (FullShape sl))++-- | Generalised array division, like above but use for splitting an array+-- into many subarrays, as opposed to extracting a single subarray.+--+class (Slice (DivisionSlice sl)) => Division sl where+ type DivisionSlice sl :: Type -- the slice+ slicesIndex :: slix ~ DivisionSlice sl+ => R.SliceIndex (EltR slix)+ (EltR (SliceShape slix))+ (EltR (CoSliceShape slix))+ (EltR (FullShape slix))++instance (Elt t, Elt h) => Elt (t :. h) where+ type EltR (t :. h) = (EltR t, EltR h)+ eltR = TupRpair (eltR @t) (eltR @h)+ tagsR = [TagRpair t h | t <- tagsR @t, h <- tagsR @h]+ fromElt (t:.h) = (fromElt t, fromElt h)+ toElt (t, h) = toElt t :. toElt h++instance Elt (Any Z)+instance Shape sh => Elt (Any (sh :. Int)) where+ type EltR (Any (sh :. Int)) = (EltR (Any sh), ())+ eltR = TupRpair (eltR @(Any sh)) TupRunit+ tagsR = [TagRpair t TagRunit | t <- tagsR @(Any sh)]+ fromElt _ = (fromElt (Any :: Any sh), ())+ toElt _ = Any++instance Shape Z where+ shapeR = R.ShapeRz+ sliceAnyIndex = R.SliceNil+ sliceNoneIndex = R.SliceNil++-- Note that the constraint 'i ~ Int' allows the compiler to infer that+-- the right argument of ':.' should be an Int.+-- The compiler can now infer that this instance is used, before knowing+-- the type of 'i'.+--+instance (Shape sh, i ~ Int) => Shape (sh:.i) where+ shapeR = R.ShapeRsnoc (shapeR @sh)+ sliceAnyIndex = R.SliceAll (sliceAnyIndex @sh)+ sliceNoneIndex = R.SliceFixed (sliceNoneIndex @sh)++instance Slice Z where+ type SliceShape Z = Z+ type CoSliceShape Z = Z+ type FullShape Z = Z+ sliceIndex = R.SliceNil++instance Slice sl => Slice (sl:.All) where+ type SliceShape (sl:.All) = SliceShape sl :. Int+ type CoSliceShape (sl:.All) = CoSliceShape sl+ type FullShape (sl:.All) = FullShape sl :. Int+ sliceIndex = R.SliceAll (sliceIndex @sl)++instance Slice sl => Slice (sl:.Int) where+ type SliceShape (sl:.Int) = SliceShape sl+ type CoSliceShape (sl:.Int) = CoSliceShape sl :. Int+ type FullShape (sl:.Int) = FullShape sl :. Int+ sliceIndex = R.SliceFixed (sliceIndex @sl)++instance Shape sh => Slice (Any sh) where+ type SliceShape (Any sh) = sh+ type CoSliceShape (Any sh) = Z+ type FullShape (Any sh) = sh+ sliceIndex = sliceAnyIndex @sh++instance Division Z where+ type DivisionSlice Z = Z+ slicesIndex = R.SliceNil++instance Division sl => Division (sl:.All) where+ type DivisionSlice (sl:.All) = DivisionSlice sl :. All+ slicesIndex = R.SliceAll (slicesIndex @sl)++instance Division sl => Division (sl:.Split) where+ type DivisionSlice (sl:.Split) = DivisionSlice sl :. Int+ slicesIndex = R.SliceFixed (slicesIndex @sl)++instance Shape sh => Division (Any sh) where+ type DivisionSlice (Any sh) = Any sh+ slicesIndex = sliceAnyIndex @sh++instance (Shape sh, Slice sh) => Division (Divide sh) where+ type DivisionSlice (Divide sh) = sh+ slicesIndex = sliceNoneIndex @sh+
+ src/Data/Array/Accelerate/Sugar/Vec.hs view
@@ -0,0 +1,40 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# OPTIONS_HADDOCK hide #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- |+-- Module : Data.Array.Accelerate.Sugar.Vec+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Sugar.Vec+ where++import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Representation.Tag+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Type+import Data.Primitive.Types+import Data.Primitive.Vec++import GHC.TypeLits+import GHC.Prim+++type VecElt a = (Elt a, Prim a, IsSingle a, EltR a ~ a)++instance (KnownNat n, VecElt a) => Elt (Vec n a) where+ type EltR (Vec n a) = Vec n a+ eltR = TupRsingle (VectorScalarType (VectorType (fromIntegral (natVal' (proxy# :: Proxy# n))) singleType))+ tagsR = [TagRsingle (VectorScalarType (VectorType (fromIntegral (natVal' (proxy# :: Proxy# n))) singleType))]+ toElt = id+ fromElt = id+
+ src/Data/Array/Accelerate/Test/NoFib.hs view
@@ -0,0 +1,67 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE RankNTypes #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Test.NoFib (++ nofib,+ nofibIngredient,++#ifndef ACCELERATE_DISABLE_NOFIB+ module Data.Array.Accelerate.Test.NoFib.Sharing,+ module Data.Array.Accelerate.Test.NoFib.Prelude,+ module Data.Array.Accelerate.Test.NoFib.Imaginary,+ module Data.Array.Accelerate.Test.NoFib.Spectral,+ module Data.Array.Accelerate.Test.NoFib.Issues,+ module Data.Array.Accelerate.Test.NoFib.Misc,+#endif++) where++import Data.Array.Accelerate.Test.NoFib.Base+import Data.Array.Accelerate.Test.NoFib.Config+#ifndef ACCELERATE_DISABLE_NOFIB+import Data.Array.Accelerate.Test.NoFib.Sharing+import Data.Array.Accelerate.Test.NoFib.Prelude+import Data.Array.Accelerate.Test.NoFib.Imaginary+import Data.Array.Accelerate.Test.NoFib.Spectral+import Data.Array.Accelerate.Test.NoFib.Issues+import Data.Array.Accelerate.Test.NoFib.Misc++import Test.Tasty.Runners+import Test.Tasty.Ingredients.Rerun+import System.Environment+#endif+import Test.Tasty+++nofib :: RunN -> TestTree -> IO ()+#ifdef ACCELERATE_DISABLE_NOFIB+nofib _ _ = error $ unlines [ "Data.Array.Accelerate: the nofib test-suite has been disabled."+ , "Reinstall package 'accelerate' with '-fnofib' to enable it."+ ]+#else+nofib runN test_runq = do+ me <- getProgName+ defaultMainWithIngredients [rerunningTests (nofibIngredient : defaultIngredients)]+ $ localOption (NumThreads 1) -- run each test sequentially with many cores+ $ testGroup me+ [ test_sharing+ , test_prelude runN+ , test_imaginary runN+ , test_spectral runN+ , test_issues runN+ , test_misc runN+ , test_runq+ ]+#endif+
+ src/Data/Array/Accelerate/Test/NoFib/Base.hs view
@@ -0,0 +1,149 @@+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeOperators #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Base+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Test.NoFib.Base+ where++import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Array+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Sugar.Shape+import Data.Array.Accelerate.Trafo.Sharing+import Data.Array.Accelerate.Type+import Data.Primitive.Vec++import Control.Monad+import Data.Primitive.Types++import Hedgehog+import qualified Hedgehog.Gen as Gen+import qualified Hedgehog.Range as Range+++type Run = forall a. Arrays a => Acc a -> a+type RunN = forall f. Afunction f => f -> AfunctionR f++dim0 :: Gen DIM0+dim0 = return Z++dim1 :: Gen DIM1+dim1 = (Z :.) <$> Gen.int (Range.linear 0 1024)++dim2 :: Gen DIM2+dim2 = do+ x <- Gen.int (Range.linear 0 128)+ y <- Gen.int (Range.linear 0 48)+ return (Z :. y :. x)++dim3 :: Gen DIM3+dim3 = do+ x <- Gen.int (Range.linear 0 64)+ y <- Gen.int (Range.linear 0 32)+ z <- Gen.int (Range.linear 0 16)+ return (Z :. z :. y :. x)++array :: (Shape sh, Elt e) => sh -> Gen e -> Gen (Array sh e)+array sh gen = fromList sh <$> Gen.list (Range.singleton (size sh)) gen++int :: Gen Int+int = Gen.int Range.linearBounded++i8 :: Gen Int8+i8 = Gen.int8 Range.linearBounded++i16 :: Gen Int16+i16 = Gen.int16 Range.linearBounded++i32 :: Gen Int32+i32 = Gen.int32 Range.linearBounded++i64 :: Gen Int64+i64 = Gen.int64 Range.linearBounded++word :: Gen Word+word = Gen.word Range.linearBounded++w8 :: Gen Word8+w8 = Gen.word8 Range.linearBounded++w16 :: Gen Word16+w16 = Gen.word16 Range.linearBounded++w32 :: Gen Word32+w32 = Gen.word32 Range.linearBounded++w64 :: Gen Word64+w64 = Gen.word64 Range.linearBounded++f16 :: Gen Half+f16 = Gen.realFloat (Range.linearFracFrom 0 (-log_flt_max) log_flt_max)++f32 :: Gen Float+f32 = Gen.float (Range.linearFracFrom 0 (-log_flt_max) log_flt_max)++f64 :: Gen Double+f64 = Gen.double (Range.linearFracFrom 0 (-log_flt_max) log_flt_max)++v2 :: Prim a => Gen a -> Gen (Vec2 a)+v2 a = Vec2 <$> a <*> a++v3 :: Prim a => Gen a -> Gen (Vec3 a)+v3 a = Vec3 <$> a <*> a <*> a++v4 :: Prim a => Gen a -> Gen (Vec4 a)+v4 a = Vec4 <$> a <*> a <*> a <*> a++v8 :: Prim a => Gen a -> Gen (Vec8 a)+v8 a = Vec8 <$> a <*> a <*> a <*> a <*> a <*> a <*> a <*> a++v16 :: Prim a => Gen a -> Gen (Vec16 a)+v16 a = Vec16 <$> a <*> a <*> a <*> a <*> a <*> a <*> a <*> a+ <*> a <*> a <*> a <*> a <*> a <*> a <*> a <*> a++log_flt_max :: RealFloat a => a+log_flt_max = log flt_max++flt_max :: RealFloat a => a+flt_max = x+ where+ n = floatDigits x+ b = floatRadix x+ (_,u) = floatRange x+ x = encodeFloat (b^n - 1) (u - n)++flt_min :: RealFloat a => a+flt_min = x+ where+ n = floatDigits x+ b = floatRadix x+ (l,_) = floatRange x+ x = encodeFloat (b^n - 1) (l - n - 1)++except :: Gen e -> (e -> Bool) -> Gen e+except gen f = do+ v <- gen+ when (f v) Gen.discard+ return v++splitEvery :: Int -> [a] -> [[a]]+splitEvery _ [] = cycle [[]]+splitEvery n xs =+ let (h,t) = splitAt n xs+ in h : splitEvery n t++splitPlaces :: [Int] -> [a] -> [[a]]+splitPlaces [] _ = []+splitPlaces (i:is) vs =+ let (h,t) = splitAt i vs+ in h : splitPlaces is t+
+ src/Data/Array/Accelerate/Test/NoFib/Config.hs view
@@ -0,0 +1,172 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeOperators #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Config+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Test.NoFib.Config+ where++import Data.Bits+import Data.Proxy+import Data.Typeable++import Test.Tasty+import Test.Tasty.Ingredients+import Test.Tasty.Options+++nofibIngredient :: Ingredient+nofibIngredient =+ includingOptions+ [ Option (Proxy::Proxy TestHalf)+ , Option (Proxy::Proxy TestFloat)+ , Option (Proxy::Proxy TestDouble)+ , Option (Proxy::Proxy TestInt8)+ , Option (Proxy::Proxy TestInt16)+ , Option (Proxy::Proxy TestInt32)+ , Option (Proxy::Proxy TestInt64)+ , Option (Proxy::Proxy TestWord8)+ , Option (Proxy::Proxy TestWord16)+ , Option (Proxy::Proxy TestWord32)+ , Option (Proxy::Proxy TestWord64)+ , Option (Proxy::Proxy Interpreter)+ ]++newtype TestAll = TestAll Bool deriving (Eq, Show, Typeable)+newtype TestHalf = TestHalf Bool deriving (Eq, Show, Typeable)+newtype TestFloat = TestFloat Bool deriving (Eq, Show, Typeable)+newtype TestDouble = TestDouble Bool deriving (Eq, Show, Typeable)+newtype TestInt8 = TestInt8 Bool deriving (Eq, Show, Typeable)+newtype TestInt16 = TestInt16 Bool deriving (Eq, Show, Typeable)+newtype TestInt32 = TestInt32 Bool deriving (Eq, Show, Typeable)+newtype TestInt64 = TestInt64 Bool deriving (Eq, Show, Typeable)+newtype TestWord8 = TestWord8 Bool deriving (Eq, Show, Typeable)+newtype TestWord16 = TestWord16 Bool deriving (Eq, Show, Typeable)+newtype TestWord32 = TestWord32 Bool deriving (Eq, Show, Typeable)+newtype TestWord64 = TestWord64 Bool deriving (Eq, Show, Typeable)+newtype Interpreter = Interpreter Bool deriving (Eq, Show, Typeable)++instance IsOption TestAll where+ defaultValue = TestAll False+ parseValue = fmap TestAll . safeRead+ optionName = return "all-types"+ optionHelp = return "Enable tests on all primitive types"++instance IsOption TestHalf where+ defaultValue = TestHalf False+ parseValue = fmap TestHalf . safeRead+ optionName = return "half"+ optionHelp = return "Enable half-precision tests"++instance IsOption TestFloat where+ defaultValue = TestFloat False+ parseValue = fmap TestFloat . safeRead+ optionName = return "float"+ optionHelp = return "Enable single-precision tests"++instance IsOption TestDouble where+ defaultValue = TestDouble True+ parseValue = fmap TestDouble . safeRead+ optionName = return "double"+ optionHelp = return "Enable double-precision tests"++instance IsOption TestInt8 where+ defaultValue = TestInt8 False+ parseValue = fmap TestInt8 . safeRead+ optionName = return "int8"+ optionHelp = return "Enable 8-bit signed integer tests"++instance IsOption TestInt16 where+ defaultValue = TestInt16 False+ parseValue = fmap TestInt16 . safeRead+ optionName = return "int16"+ optionHelp = return "Enable 16-bit signed integer tests"++instance IsOption TestInt32 where+ defaultValue = TestInt32 $( [e| finiteBitSize (undefined::Int) == 32 |] )+ parseValue = fmap TestInt32 . safeRead+ optionName = return "int32"+ optionHelp = return "Enable 32-bit signed integer tests"++instance IsOption TestInt64 where+ defaultValue = TestInt64 $( [e| finiteBitSize (undefined::Int) == 64 |] )+ parseValue = fmap TestInt64 . safeRead+ optionName = return "int64"+ optionHelp = return "Enable 64-bit signed integer tests"++instance IsOption TestWord8 where+ defaultValue = TestWord8 False+ parseValue = fmap TestWord8 . safeRead+ optionName = return "word8"+ optionHelp = return "Enable 8-bit unsigned integer tests"++instance IsOption TestWord16 where+ defaultValue = TestWord16 False+ parseValue = fmap TestWord16 . safeRead+ optionName = return "word16"+ optionHelp = return "Enable 16-bit unsigned integer tests"++instance IsOption TestWord32 where+ defaultValue = TestWord32 False+ parseValue = fmap TestWord32 . safeRead+ optionName = return "word32"+ optionHelp = return "Enable 32-bit unsigned integer tests"++instance IsOption TestWord64 where+ defaultValue = TestWord64 False+ parseValue = fmap TestWord64 . safeRead+ optionName = return "word64"+ optionHelp = return "Enable 64-bit unsigned integer tests"++instance IsOption Interpreter where+ defaultValue = Interpreter False+ parseValue = fmap Interpreter . safeRead+ optionName = return "interpreter"+ optionHelp = return "I am an interpreter (skip some tests)"+++class IsOption a => TestConfig a where+ at :: TestTree -> TestTree++instance TestConfig TestHalf where+ at t = askOption $ \(TestHalf v) -> if v then t else testGroup "Half" []++instance TestConfig TestFloat where+ at t = askOption $ \(TestFloat v) -> if v then t else testGroup "Float" []++instance TestConfig TestDouble where+ at t = askOption $ \(TestDouble v) -> if v then t else testGroup "Double" []++instance TestConfig TestInt8 where+ at t = askOption $ \(TestInt8 v) -> if v then t else testGroup "Int8" []++instance TestConfig TestInt16 where+ at t = askOption $ \(TestInt16 v) -> if v then t else testGroup "Int16" []++instance TestConfig TestInt32 where+ at t = askOption $ \(TestInt32 v) -> if v then t else testGroup "Int32" []++instance TestConfig TestInt64 where+ at t = askOption $ \(TestInt64 v) -> if v then t else testGroup "Int64" []++instance TestConfig TestWord8 where+ at t = askOption $ \(TestWord8 v) -> if v then t else testGroup "Word8" []++instance TestConfig TestWord16 where+ at t = askOption $ \(TestWord16 v) -> if v then t else testGroup "Word16" []++instance TestConfig TestWord32 where+ at t = askOption $ \(TestWord32 v) -> if v then t else testGroup "Word32" []++instance TestConfig TestWord64 where+ at t = askOption $ \(TestWord64 v) -> if v then t else testGroup "Word64" []+
+ src/Data/Array/Accelerate/Test/NoFib/Imaginary.hs view
@@ -0,0 +1,37 @@+{-# LANGUAGE RankNTypes #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Imaginary+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Test.NoFib.Imaginary (++ test_imaginary,++ module Data.Array.Accelerate.Test.NoFib.Imaginary.SASUM,+ module Data.Array.Accelerate.Test.NoFib.Imaginary.SAXPY,+ module Data.Array.Accelerate.Test.NoFib.Imaginary.DotP,++) where++import Test.Tasty++import Data.Array.Accelerate.Test.NoFib.Base+import Data.Array.Accelerate.Test.NoFib.Imaginary.SASUM+import Data.Array.Accelerate.Test.NoFib.Imaginary.SAXPY+import Data.Array.Accelerate.Test.NoFib.Imaginary.DotP+++test_imaginary :: RunN -> TestTree+test_imaginary runN =+ testGroup "imaginary"+ [ test_sasum runN+ , test_saxpy runN+ , test_dotp runN+ ]+
+ src/Data/Array/Accelerate/Test/NoFib/Imaginary/DotP.hs view
@@ -0,0 +1,83 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Imaginary.DotP+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Test.NoFib.Imaginary.DotP (++ test_dotp++) where++import Prelude as P++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Sugar.Array as S+import Data.Array.Accelerate.Sugar.Elt as S+import Data.Array.Accelerate.Test.NoFib.Base+import Data.Array.Accelerate.Test.NoFib.Config+import Data.Array.Accelerate.Test.Similar++import Hedgehog+import qualified Hedgehog.Gen as Gen+import qualified Hedgehog.Range as Range++import Test.Tasty+import Test.Tasty.Hedgehog+++test_dotp :: RunN -> TestTree+test_dotp runN =+ testGroup "dot product"+ [ at @TestInt8 $ testElt i8+ , at @TestInt16 $ testElt i16+ , at @TestInt32 $ testElt i32+ , at @TestInt64 $ testElt i64+ , at @TestWord8 $ testElt w8+ , at @TestWord16 $ testElt w16+ , at @TestWord32 $ testElt w32+ , at @TestWord64 $ testElt w64+ , at @TestHalf $ testElt f16+ , at @TestFloat $ testElt f32+ , at @TestDouble $ testElt f64+ ]+ where+ testElt :: forall a. (P.Num a, P.Ord a , A.Num a, A.Ord a , Similar a, Show a)+ => Gen a+ -> TestTree+ testElt e =+ testProperty (show (eltR @a)) $ test_dotp' runN e+++test_dotp'+ :: (P.Num e, A.Num e, Similar e, Show e)+ => RunN+ -> Gen e+ -> Property+test_dotp' runN e =+ property $ do+ sh <- forAll ((Z:.) P.<$> Gen.int (Range.linear 0 16384))+ xs <- forAll (array sh e)+ ys <- forAll (array sh e)+ let !go = runN dotp in go xs ys S.! Z ~~~ dotpRef xs ys++dotp :: A.Num e => Acc (Vector e) -> Acc (Vector e) -> Acc (Scalar e)+dotp xs ys+ = A.fold (+) 0+ $ A.zipWith (*) xs ys++dotpRef :: (P.Num e, Elt e) => Vector e -> Vector e -> e+dotpRef xs ys+ = P.sum ( P.zipWith (*) (toList xs) (toList ys) )+
+ src/Data/Array/Accelerate/Test/NoFib/Imaginary/SASUM.hs view
@@ -0,0 +1,79 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Imaginary.SASUM+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Test.NoFib.Imaginary.SASUM (++ test_sasum++) where++import Prelude as P++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Sugar.Array as S+import Data.Array.Accelerate.Sugar.Elt as S+import Data.Array.Accelerate.Test.NoFib.Base+import Data.Array.Accelerate.Test.NoFib.Config+import Data.Array.Accelerate.Test.Similar++import Hedgehog+import qualified Hedgehog.Gen as Gen+import qualified Hedgehog.Range as Range++import Test.Tasty+import Test.Tasty.Hedgehog+++test_sasum :: RunN -> TestTree+test_sasum runN =+ testGroup "sasum"+ [ at @TestInt8 $ testElt i8+ , at @TestInt16 $ testElt i16+ , at @TestInt32 $ testElt i32+ , at @TestInt64 $ testElt i64+ , at @TestWord8 $ testElt w8+ , at @TestWord16 $ testElt w16+ , at @TestWord32 $ testElt w32+ , at @TestWord64 $ testElt w64+ , at @TestHalf $ testElt f16+ , at @TestFloat $ testElt f32+ , at @TestDouble $ testElt f64+ ]+ where+ testElt :: forall a. (P.Num a, P.Eq a, A.Num a, A.Eq a, Similar a, Show a)+ => Gen a+ -> TestTree+ testElt e =+ testProperty (show (eltR @a)) $ test_sasum' runN e+++test_sasum'+ :: (P.Num e, A.Num e, Similar e, Show e)+ => RunN+ -> Gen e+ -> Property+test_sasum' runN e =+ property $ do+ sh <- forAll ((Z:.) P.<$> Gen.int (Range.linear 0 16384))+ xs <- forAll (array sh e)+ let !go = runN sasum in go xs S.! Z ~~~ sasumRef xs++sasum :: A.Num e => Acc (Vector e) -> Acc (Scalar e)+sasum = A.fold (+) 0 . A.map abs++sasumRef :: (P.Num e, Elt e) => Vector e -> e+sasumRef xs = P.sum [ abs x | x <- toList xs ]+
+ src/Data/Array/Accelerate/Test/NoFib/Imaginary/SAXPY.hs view
@@ -0,0 +1,88 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Imaginary.SAXPY+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Test.NoFib.Imaginary.SAXPY (++ test_saxpy++) where++import Prelude as P++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Sugar.Array as S+import Data.Array.Accelerate.Sugar.Elt as S+import Data.Array.Accelerate.Sugar.Shape as S+import Data.Array.Accelerate.Test.NoFib.Base+import Data.Array.Accelerate.Test.NoFib.Config+import Data.Array.Accelerate.Test.Similar++import Hedgehog+import qualified Hedgehog.Gen as Gen+import qualified Hedgehog.Range as Range++import Test.Tasty+import Test.Tasty.Hedgehog+++test_saxpy :: RunN -> TestTree+test_saxpy runN =+ testGroup "saxpy"+ [ at @TestInt8 $ testElt i8+ , at @TestInt16 $ testElt i16+ , at @TestInt32 $ testElt i32+ , at @TestInt64 $ testElt i64+ , at @TestWord8 $ testElt w8+ , at @TestWord16 $ testElt w16+ , at @TestWord32 $ testElt w32+ , at @TestWord64 $ testElt w64+ , at @TestHalf $ testElt f16+ , at @TestFloat $ testElt f32+ , at @TestDouble $ testElt f64+ ]+ where+ testElt :: forall a. (P.Num a, A.Num a, Similar a, Show a)+ => Gen a+ -> TestTree+ testElt e =+ testProperty (show (eltR @a)) $ test_saxpy' runN e+++test_saxpy'+ :: (P.Num e, A.Num e, Similar e, Show e)+ => RunN+ -> Gen e+ -> Property+test_saxpy' runN e =+ property $ do+ sh <- forAll ((Z:.) P.<$> Gen.int (Range.linear 0 16384))+ alpha <- forAll e+ xs <- forAll (array sh e)+ ys <- forAll (array sh e)+ let !go = runN saxpy in go (scalar alpha) xs ys ~~~ saxpyRef alpha xs ys++scalar :: Elt e => e -> Scalar e+scalar x = fromFunction Z (const x)++saxpy :: A.Num e => Acc (Scalar e) -> Acc (Vector e) -> Acc (Vector e) -> Acc (Vector e)+saxpy alpha xs ys = A.zipWith (\x y -> the alpha * x + y) xs ys++saxpyRef :: (P.Num e, Elt e) => e -> Vector e -> Vector e -> Vector e+saxpyRef alpha xs ys =+ fromFunction+ (S.shape xs `S.intersect` S.shape ys)+ (\ix -> alpha * (xs S.! ix) + (ys S.! ix))+
+ src/Data/Array/Accelerate/Test/NoFib/Issues.hs view
@@ -0,0 +1,106 @@+{-# LANGUAGE RankNTypes #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Issues+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Test.NoFib.Issues (++ test_issues,++ module Data.Array.Accelerate.Test.NoFib.Issues.Issue93,+ module Data.Array.Accelerate.Test.NoFib.Issues.Issue102,+ module Data.Array.Accelerate.Test.NoFib.Issues.Issue114,+ module Data.Array.Accelerate.Test.NoFib.Issues.Issue119,+ module Data.Array.Accelerate.Test.NoFib.Issues.Issue123,+ module Data.Array.Accelerate.Test.NoFib.Issues.Issue137,+ module Data.Array.Accelerate.Test.NoFib.Issues.Issue168,+ module Data.Array.Accelerate.Test.NoFib.Issues.Issue184,+ module Data.Array.Accelerate.Test.NoFib.Issues.Issue185,+ module Data.Array.Accelerate.Test.NoFib.Issues.Issue187,+ module Data.Array.Accelerate.Test.NoFib.Issues.Issue228,+ module Data.Array.Accelerate.Test.NoFib.Issues.Issue255,+ module Data.Array.Accelerate.Test.NoFib.Issues.Issue264,+ -- module Data.Array.Accelerate.Test.NoFib.Issues.Issue286,+ module Data.Array.Accelerate.Test.NoFib.Issues.Issue287,+ module Data.Array.Accelerate.Test.NoFib.Issues.Issue288,+ module Data.Array.Accelerate.Test.NoFib.Issues.Issue362,+ module Data.Array.Accelerate.Test.NoFib.Issues.Issue364,+ module Data.Array.Accelerate.Test.NoFib.Issues.Issue407,+ module Data.Array.Accelerate.Test.NoFib.Issues.Issue409,+ module Data.Array.Accelerate.Test.NoFib.Issues.Issue427,+ module Data.Array.Accelerate.Test.NoFib.Issues.Issue436,+ module Data.Array.Accelerate.Test.NoFib.Issues.Issue437,+ module Data.Array.Accelerate.Test.NoFib.Issues.Issue439,+ module Data.Array.Accelerate.Test.NoFib.Issues.Issue517,+ module Data.Array.Accelerate.Test.NoFib.Issues.Issue551,++) where++import Test.Tasty++import Data.Array.Accelerate.Test.NoFib.Base+import Data.Array.Accelerate.Test.NoFib.Issues.Issue93+import Data.Array.Accelerate.Test.NoFib.Issues.Issue102+import Data.Array.Accelerate.Test.NoFib.Issues.Issue114+import Data.Array.Accelerate.Test.NoFib.Issues.Issue119+import Data.Array.Accelerate.Test.NoFib.Issues.Issue123+import Data.Array.Accelerate.Test.NoFib.Issues.Issue137+import Data.Array.Accelerate.Test.NoFib.Issues.Issue168+import Data.Array.Accelerate.Test.NoFib.Issues.Issue184+import Data.Array.Accelerate.Test.NoFib.Issues.Issue185+import Data.Array.Accelerate.Test.NoFib.Issues.Issue187+import Data.Array.Accelerate.Test.NoFib.Issues.Issue228+import Data.Array.Accelerate.Test.NoFib.Issues.Issue255+import Data.Array.Accelerate.Test.NoFib.Issues.Issue264+-- import Data.Array.Accelerate.Test.NoFib.Issues.Issue286+import Data.Array.Accelerate.Test.NoFib.Issues.Issue287+import Data.Array.Accelerate.Test.NoFib.Issues.Issue288+import Data.Array.Accelerate.Test.NoFib.Issues.Issue362+import Data.Array.Accelerate.Test.NoFib.Issues.Issue364+import Data.Array.Accelerate.Test.NoFib.Issues.Issue407+import Data.Array.Accelerate.Test.NoFib.Issues.Issue409+import Data.Array.Accelerate.Test.NoFib.Issues.Issue427+import Data.Array.Accelerate.Test.NoFib.Issues.Issue436+import Data.Array.Accelerate.Test.NoFib.Issues.Issue437+import Data.Array.Accelerate.Test.NoFib.Issues.Issue439+import Data.Array.Accelerate.Test.NoFib.Issues.Issue517+import Data.Array.Accelerate.Test.NoFib.Issues.Issue551+++test_issues :: RunN -> TestTree+test_issues runN =+ testGroup "issues"+ [ test_issue93 runN+ , test_issue102 runN+ , test_issue114 runN+ , test_issue119 runN+ , test_issue123 runN+ , test_issue137 runN+ , test_issue168 runN+ , test_issue184 runN+ , test_issue185 runN+ , test_issue187 runN+ , test_issue228 runN+ , test_issue255 runN+ , test_issue264 runN+ -- , test_issue286 runN+ , test_issue287 runN+ , test_issue288 runN+ , test_issue362 runN+ , test_issue364 runN+ , test_issue407 runN+ , test_issue409 runN+ , test_issue427 runN+ , test_issue436 runN+ , test_issue437 runN+ , test_issue439 runN+ , test_issue517 runN+ , test_issue551 runN+ ]+
+ src/Data/Array/Accelerate/Test/NoFib/Issues/Issue102.hs view
@@ -0,0 +1,71 @@+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TypeOperators #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Issues.Issue102+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- https://github.com/AccelerateHS/accelerate/issues/102+--++module Data.Array.Accelerate.Test.NoFib.Issues.Issue102 (++ test_issue102++) where++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Test.NoFib.Base++import Test.Tasty+import Test.Tasty.HUnit+++test_issue102 :: RunN -> TestTree+test_issue102 runN =+ testCase "102" $ ref1 @=? runN test1+++ref1 :: Array DIM3 Int+ref1 = fromList (Z :. 1 :. 3 :. 1) [4,4,4]++test1 :: Acc (Array DIM3 Int)+test1 =+ let p = 3+ lts = 1+ rts = 1+ rustride = 1++ v = fill (constant (Z:.(p-1))) (constant 2)+ ru' = fill (constant (Z:.(p-1))) (constant 1)++ -- generate a vector with phi(p)=p-1 elements+ x' = reshape (constant (Z :. lts :. (p-1) :. rts)) v++ --embed into a vector of length p+ y = generate (constant (Z :. lts :. p :. rts))+ (\ix -> let (Z :. l :. i :. r) = unlift ix :: Z :. Exp Int :. Exp Int :. Exp Int+ in i A.== 0 ? (0, x' ! (lift $ Z :. l :. i-1 :. r)))++ -- do a DFT_p+ y' = reshape (constant (Z :. lts :. p :. rts)) (flatten y)+ dftrus = generate (constant (Z :. p :. p))+ (\ix -> let (Z :. i :. j) = unlift ix :: Z :. Exp Int :. Exp Int+ in ru' ! (lift (Z :. (i*j*rustride `mod` (constant p)))))++ tensorDFTCoeffs = A.replicate (lift (Z:.lts:.All:.rts:.All)) dftrus+ tensorInputCoeffs = generate (shape tensorDFTCoeffs)+ (\ix -> let (Z:.l:._:.r:.col) = unlift ix :: Z :. Exp Int :. Exp Int :. Exp Int :. Exp Int+ in y' ! (lift $ Z:.l:.col:.r))++ dftans = flatten $ fold (+) (constant 0) $ A.zipWith (*) tensorDFTCoeffs tensorInputCoeffs++ --continue the alternate transform, but this line breaks+ dfty = reshape (shape y) $ dftans+ in+ dfty+
+ src/Data/Array/Accelerate/Test/NoFib/Issues/Issue114.hs view
@@ -0,0 +1,85 @@+{-# LANGUAGE RankNTypes #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Issues.Issue114+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- https://github.com/AccelerateHS/accelerate/issues/114+--++module Data.Array.Accelerate.Test.NoFib.Issues.Issue114 (++ test_issue114++) where++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Test.Similar+import Data.Array.Accelerate.Test.NoFib.Base++import Test.Tasty+import Test.Tasty.HUnit++import Control.Monad+import Prelude as P+++test_issue114 :: RunN -> TestTree+test_issue114 runN =+ testGroup "114"+ [ testCase "A" $ ref1 @~? runN test1+ , testCase "B" $ ref2 @~? runN test2+ ]+++(@~?) :: (Similar a, Show a) => a -> a -> Assertion+expected @~? actual =+ unless (expected ~= actual) $+ assertFailure $ "expected: " P.++ show expected P.++ "\n but got: " P.++ show actual+++type EFloat = (Float, Float) -- Represents a real number with a value and error++fromFloat :: Float -> EFloat+fromFloat x = (x, 0)++-- toFloat :: EFloat -> Float+-- toFloat (val, err) = val + err++add :: Exp EFloat -> Exp EFloat -> Exp EFloat+add = lift2 f+ where+ f :: (Exp Float, Exp Float) -> (Exp Float, Exp Float) -> (Exp Float, Exp Float)+ f (aval, aerr) (bval, berr) = (val, err)+ where+ val = aval + bval+ err = aval - (val - det) + (bval - det) + aerr + berr+ det = val - aval++esum :: Acc (Vector EFloat) -> Acc (Scalar EFloat)+esum x = A.fold1 add x++epsum :: Acc (Vector EFloat) -> Acc (Vector EFloat)+epsum x = A.scanl1 add x++xs :: Acc (Vector EFloat)+xs = use $ fromFunction (Z :. 100) (\_ -> fromFloat 1.01)+++ref1 :: Scalar EFloat+ref1 = fromList Z [(101,0)]++test1 :: Acc (Scalar EFloat)+test1 = esum xs+++ref2 :: Vector EFloat+ref2 = fromList (Z :. 100) [ (1.01 * i, 0) | i <- [1..]]++test2 :: Acc (Vector EFloat)+test2 = epsum xs+
+ src/Data/Array/Accelerate/Test/NoFib/Issues/Issue119.hs view
@@ -0,0 +1,183 @@+{-# LANGUAGE RankNTypes #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Issues.Issue119+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- https://github.com/AccelerateHS/accelerate/issues/119+--++module Data.Array.Accelerate.Test.NoFib.Issues.Issue119 (++ test_issue119++) where++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Test.NoFib.Base++import Test.Tasty+import Test.Tasty.HUnit+++test_issue119 :: RunN -> TestTree+test_issue119 runN =+ testGroup "119"+ [ testCase "A" $ ref1 @=? runN test1+ , testCase "B" $ ref2 @=? runN test2+ , testCase "C" $ ref3 @=? runN test3+ , testCase "D" $ ref4 @=? runN test4+ , testCase "E" $ ref5 @=? runN test5+ , testCase "F" $ ref6 @=? runN test6+ , testCase "G" $ ref7 @=? runN test7+ , testCase "H" $ ref8 @=? runN test8+ , testCase "I" $ ref9 @=? runN test9+ , testCase "J" $ ref10 @=? runN test10+ , testCase "K" $ ref11 @=? runN test11+ ]+++-- Fold tests+-- ----------++ref1 :: Scalar Int32+ref1 = fromList Z [734889155]++test1 :: Acc (Scalar Int32)+test1 = A.foldAll (+) 0 xs+ where+ xs :: Acc (Array DIM2 Int32)+ xs = use $ fromList (Z :. 5 :. 28) [14769239,-43969807,34096869,26467320,-21446403,-19566997,-20757196,-66879020,19321522,16802755,51423005,-30832656,12956743,-12318583,-48025228,61945796,-2250529,18157252,-44635606,-57062680,54654752,-45950438,-45550976,-62875929,66292458,64296866,34105235,20487639,30133337,-34016948,46574440,-21782247,7668293,8257005,-52134520,65769526,-53807259,56265864,44995988,2419563,50453876,57043978,32058611,41795482,1356242,28417251,5365744,-50462079,-4690548,-63375747,-46568125,17130936,-9136428,53870799,65779607,65381795,-32284364,1085336,41766147,-48032615,-8611290,-31457130,52882781,-11785315,31039408,14338797,11749455,4037928,-28111863,50044760,-63234128,17276128,8579326,57409776,64794871,-43959064,17740348,33371212,-18433618,303726,8599511,14055754,38794127,-49407153,-20949080,-66174156,-43639360,13828228,-36941738,-2879784,-32949921,5454298,46134687,58015243,-2497378,-35813131,-66438706,-28087800,-22569678,21234344,51086800,-17488916,62884654,55526000,31676635,7777220,38149962,66027320,-23764609,41016045,18232856,6488342,20118159,28851925,-6610856,23434278,-57333215,57974240,-66022236,55082111,61254643,-52552004,-62140522,-13018201,17313534,6955448,52914957,8368369,-25845462,50594480,-32920224,-26202745,-25861093,55035780,-60835478,6582276,55668636,26991003,228691,62551594]+++ref2 :: Scalar Int32+ref2 = fromList Z [638248245]++test2 :: Acc (Scalar Int32)+test2 = A.foldAll (+) z xs+ where+ z = constant 0+ xs :: Acc (Array DIM2 Int32)+ xs = use $ fromList (Z :. 28 :. 5) [30332431,6796098,-15522385,-32163376,-22219878,10020835,22638601,20673036,-30769405,-23271551,16790184,-17975968,29134928,29540030,15695897,-9531463,12041364,15327083,-7856190,28479946,24497912,-13994046,5037581,-25167431,11992516,-25544745,26910784,-29607037,21237332,30371276,1858744,20239265,1576853,5549626,1732708,21169707,-8592014,-17303153,-4691351,29659929,-17704246,-13035309,-21373638,14713362,21130870,-6403753,13321799,22126635,30318513,-25651322,-10668441,-24247707,24353923,-5541473,15335372,-7118652,-28357515,30896735,19938864,21360170,16766774,29976096,10055680,9181294,10294712,-23189559,28234139,19443020,20018378,18990662,12790940,-31136432,7945796,-11687674,4320146,-1353679,21896288,2731169,24625097,12506224,27189679,-10270450,3097174,-11012112,29232397,3162933,-11403300,30059570,-9243914,13047945,16513682,-8138375,-17921376,30769432,23685828,21912950,9206743,25339626,11122590,-13094182,-20380905,-8019817,3199026,21598845,4761221,9104850,-30744683,29597011,-26264428,-17658633,831337,-8352528,-27450307,-29451038,9006711,-21943478,25866183,21329008,-7148827,14493559,-14888430,-26543546,25318288,-14096306,-9132505,2388950,9740892,-12973005,10141734,28363840,-1974095,12753649,26765381,23979765,15399126,20204488,19148086,14457571,-18842735,31509219]+++ref3 :: Scalar Int64+ref3 = fromList Z [-2304750112110]++test3 :: Acc (Scalar Int64)+test3 = A.foldAll (+) 0 xs+ where+ xs :: Acc (Array DIM2 Int64)+ xs = use $ fromList (Z :. 4 :. 34) [-119582066848,211418632971,-273814068829,-441336869225,49277660114,545904743034,-107108516086,272730345990,-227553979182,-205217278623,-334933374202,51481780401,-243087611110,499367622597,-281520298752,183942102289,-352104016609,-411607044687,-462706494917,-405072342281,-443472456667,57859494326,340657028984,268146891294,319572181437,-328099124733,-499762864333,435940295598,310279498548,-450247211372,101309611345,508483612496,170564579262,-18976287892,-455590358368,171197058025,-370071394217,238505304901,201668743044,498589419201,297393267447,303651235875,504136702140,240153057419,227119976864,-54751959043,-389119831605,35618580405,-155315665549,539301360661,461515245841,-420790558552,-407621743214,512382547226,64401598442,75455583959,-422914101157,-444213359875,-464670739203,-151444593289,12666639431,366304035864,33213351756,-337126953996,469279395971,-318783703943,524684201810,-360908771731,-365270829375,95123780502,-392655992888,-76730831811,479382581014,-223793301821,-405318001331,-478562160184,-163914780202,-411178397558,-73093917592,322239790820,420249956833,-122752719617,-420777967956,-489170073738,232626269189,398537832770,136477711761,-117743069079,473757016199,461956975541,75333205695,122914427050,-277154707123,-344965932671,18790179442,242296707870,183037500718,380718816714,-433509147619,305765602753,436058308076,-140428136472,-289391463887,-530251700495,-306686789129,224410693891,-484184400934,463805089162,-501756254322,393903748222,-269147001559,-359942689809,-163943277620,74971067748,-202611183518,-308196672762,320023013452,75437650523,475680122061,446935336626,114910599577,-421539248344,-25530906498,-424571606102,-396438535665,354002379792,134141026509,-543141869270,-347289264435,333557662160,33168540124,-167015747466,268026632123,-65645693801,-196414232999,393080421747]++ref4 :: Scalar Int64+ref4 = fromList Z [-1982037004259]++test4 :: Acc (Scalar Int64)+test4 = A.foldAll (+) z xs+ where+ z = constant 0+ xs :: Acc (Array DIM2 Int64)+ xs = use $ fromList (Z :. 27 :. 5) [-516950650221,-198681319472,-62248207215,-368566588052,-221815889746,-404814200669,15045398798,430679777170,163443360209,58097521335,-87590898111,497607465075,-27049301510,149071552167,-119172901827,-108679661992,412502711937,-213838885992,-491807426758,-169121244505,377480661744,-364997600163,452887211838,498386633616,-196697034533,426777341897,-459406805363,-239048240471,250937389006,-453316577416,477182495522,-79624988438,-483304189443,141157669081,355197721240,-328308821798,10400185896,398549525265,-141936649498,218818467494,402542618206,456236393213,-503876199918,52591145304,-149056547666,-336820739966,-101305073619,-472113159559,-321357874802,-95088218225,47976047271,509800579620,-145214377978,258457805786,252700511510,537909713977,247668230739,-259697031014,-230995125913,77530842572,283307049087,-411792373178,324606551065,302376540936,500057254214,36752111995,-55143618182,-42362785469,-68090351859,-345780793879,485419604422,-525756197664,-67428156655,121298292757,-523227354037,542168812603,-63016595487,404709620252,492764196616,173842446373,-251029882829,53802486346,-530196219472,38098754466,-451928062539,-198941999979,-430777494835,356103891588,-478934564072,421540513969,129261909711,267834058695,-449200229070,-153755923804,548585896851,-362848223110,166182675419,272214294990,-530215315236,-342214087116,-474705180756,168367792089,-53404310532,-472623730372,-147327201280,519069543952,-135155501227,159093854025,-268230727831,529927846798,-135583708544,-435621161817,-482622020289,-337169671550,-199594728505,85511984309,389604901651,276696290309,336198922744,-456923645150,186500760911,388034346215,-121368960575,168640682551,-7576869074,69728513684,276429408489,-383852114311,-496978282447,-257731685849,286922686952,332263669356,-371802274827,144134413275,-524312126151]+++ref5 :: Vector Int32+ref5 = fromList (Z :. 1) [-564354555]++test5 :: Acc (Vector Int32)+test5 = A.fold (+) 0 xs+ where+ xs :: Acc (Array DIM2 Int32)+ xs = use $ fromList (Z :. 1 :. 130) [-4457702,-122533607,-128044610,-118567484,-51241069,207290580,-220286030,4228986,27469434,-150317120,-203604157,-825364,-5199079,33434421,-254928269,215941275,-84557225,155733915,171166525,94162372,46201848,74472984,-20540100,203227620,-205035659,139581872,-64200870,-95685833,-248817216,181149788,-51154438,5754365,-39623339,-30285278,-124075023,-116700449,198097791,-79621402,-6975987,-103294438,-193880739,-42554593,-52665481,-6774561,-145101208,217440464,-234644017,-165019600,-141695655,-110020351,179140674,66343428,43188757,192222207,196444242,72638801,260767189,-234015110,238745515,-12235263,114454889,-117207038,-56788533,-166739373,207303540,-52047526,-2280395,31679387,87315138,181256391,-197760275,147977350,-105987066,-126709084,-180021047,-91253871,88115823,-220087038,141701192,-100881541,197803243,-35493996,71878227,123953012,190031396,233047641,-172754808,-87849442,-82869836,-208702873,-91940076,-42225767,124028996,-129061972,7648559,28609363,258568067,-156621004,154765390,-15205853,-189458486,-55442626,133343504,-107377067,-153448167,-83812681,216682270,235806226,-155366374,-29170502,-113839485,-249632147,220516680,159108225,49056288,-14524239,148547005,151302845,53892421,-215278906,-59578587,-36754634,169714732,-4520583,40832244,159375461,236429345,-257962058,-19375172,-98736004]+++-- Scan tests+-- ----------++ref6 :: Vector Int64+ref6 = fromList (Z :. 748) [9125498,-16063035,-50980,-27239361,-28337646,-37708670,-21121249,-11217118,-13848672,-39334849,-46707491,-66531944,-43011362,-52687842,-22827761,-971267,-5223404,-4411473,-18981275,13313900,6542877,11493167,22215941,15573052,-4268436,13222384,11042779,-3043325,-30361025,-12714603,3072363,31204175,3603936,1445050,3106420,-10215901,-35287878,-41312051,-33332828,-8728274,-5932326,15089470,15341055,22710136,33070009,20938516,9183939,13338488,27196906,10726312,-19896886,-5528880,-25763431,-47546113,-21147316,8321444,1963928,-26863855,-250164,32934074,44835086,57843946,26305229,6456986,-26980567,-41996719,-70804933,-84259108,-87879612,-110692672,-142798291,-116098588,-85567404,-116207069,-123821326,12584983,25114364,-7860303,1367004,22680794,6730923,24499547,45160622,66310423,75777515,95908783,82670280,75336288,86887135,72442174,70887722,56336211,86112478,69983042,71665675,72070119,94687414,125141027,117692500,91136141,111363947,94258056,102908356,70818523,80142514,92859070,122763909,93075287,77155392,54968337,29421292,31177870,1920103,6519230,-19551499,-21222657,-570094,-24097292,-21808392,-10348212,-25233388,1173489,-9736680,16762526,28315631,29037674,11984290,21576469,34826173,1642762,32046691,35140081,58642652,77835445,80197959,89973092,115910407,129847184,118117169,95353096,79367357,62093373,28767797,-2146590,-10917398,20424644,4676917,7932556,3312401,-15966908,-7189949,5420963,8175943,4434171,-23666656,-10061080,-6041726,-31631217,-46272817,-61706087,-29314516,-7596012,14721710,37426611,63932827,37620518,28457552,40061842,31619691,27526728,56295666,80222812,105097861,88788604,97864477,79172130,10011195,-11909105,14225322,47137915,41586134,43468287,16346843,33297215,32170527,53289540,54985040,81533030,110490559,94932129,-13972154,-562189,-26994686,-56883836,-38812939,-13124808,-40371526,-52769442,-21433054,-38472715,-27141571,-29136605,-25500474,-3609550,2499409,-5483029,7386627,-24798720,-19594335,-27615046,-27638210,-60052370,-60759465,21354265,35287006,20122081,39265392,30972278,-57680,-32797288,-40752069,-27338717,-42161108,-14223907,-26783347,2619156,-14191849,6138144,7386063,-2032880,-1427633,24663443,12623199,41575592,41247980,57154315,51594681,59172894,71372344,62594824,88295328,58813946,37705204,28408628,16061632,9164297,-20127170,-9336346,-19571825,-52179514,-68566225,-54477198,-47004940,-29937062,-26901831,-4920101,3005622,7980962,8028145,29521179,4597970,28713400,59139068,43239497,14548340,-5703663,19550414,41133083,40431977,71464673,71868771,61227439,41134554,31050857,8517828,36666702,67999523,50219401,20584724,22991750,27378599,54105073,39320349,15820114,40457939,41491964,23091500,7320002,-21415520,9737506,37844167,55041071,80397844,102622122,100100178,86108928,104370032,96478192,129355326,154538582,125989958,143228198,145176468,139822044,153528336,178316046,164246971,175794520,146308152,146195800,176242327,204855629,175565103,7396173,21863242,35694390,20236011,2751512,20138366,15394266,-820941,-4081067,-14269206,6911689,-11814644,-29241281,-49447821,29070717,12178489,4706892,-12315553,-19458729,-21356132,32958033,45401858,53370676,28467559,19593822,-2362034,-22117369,-7304152,-39099651,-22225335,-11600163,-22285664,2291892,-7750742,-7695599,6170980,-15707745,-37482681,-55991916,-82981918,-83046513,-56843137,-84028152,-114039097,-143926441,-152072244,-126187325,-147424750,-167404074,-162720270,-190867797,-167936982,-141061455,-109557195,-97843277,-111686956,-136635385,-104293809,-74950582,25017856,23279847,50087106,44767052,28328844,44871147,17608101,35664270,61602884,52831414,70249540,1819043,3429541,11974074,-13604141,-9364540,-31853055,1318244,-32151004,-31320318,-44830769,-21132509,-13995287,9516139,-22382471,-15989865,-4087485,-14545639,-41647841,-35817861,-30140793,-62661641,-37684047,-10791435,-31361559,-28965957,-35074554,-18300410,5455270,23648211,32414689,50928057,84178047,64930378,93870236,79795842,86863035,105461553,79769102,80114784,54005743,33702322,65727435,62447610,52138169,43806272,31938677,37096050,70218042,77215870,106108777,139027677,114174251,126267131,140175411,160639557,193663077,206137637,220658257,202941018,-12251575,-23552773,-55866025,-23809513,-20926637,-31109913,-39762123,-46364008,-60594496,-42978446,-13334636,-30452598,-50434052,-61031253,-74842844,-93367283,-61532012,-84351158,-84841171,-104231070,-100891101,-126393754,-103372367,-130732559,-19187634,14573150,41644350,15935939,-17222201,13190162,18958067,-14125622,-24081209,3812159,26073207,1502885,27132466,50360103,32308017,43791273,28658841,-3014391,17498899,39691132,55285193,24930027,1313945,8269524,-3616873,-6270603,18469472,36099131,39395283,19467169,35946131,56127923,23068454,-3858447,127864,80862,7732537,-19112498,-51201127,-26195163,-56817262,-25264735,8237471,22946551,43448141,44527962,15371977,41182890,37330623,23803440,25133955,21428283,16975035,3669458,-3948266,-18836608,-46801069,-52964698,-22530552,-43387214,-61356367,-25196164,14528267,42710847,12057272,-28567150,-4999302,-9802327,-40044668,-50932747,-55517409,-42227774,-46720093,-55222219,-78741202,-85956859,-66535020,-46117937,-27770713,-58407711,-78187327,-69135214,1202125,-12657006,-36736334,-5285746,1284850,13974673,6428450,-2859916,11195300,21966510,41773652,75026766,86232546,65434150,56281777,31791084,-27496239,-11755947,-38243335,-15570305,-44944537,-56626147,-35689712,-29230541,-1790980,4913883,30309378,35999451,4247731,19877599,30464878,23724438,22283982,54499416,24386456,49397482,20056046,2245136,10370839,11303423,-17409033,-42771071,-74956837,-48166691,-43816115,-57542384,-70157229,-70862427,30408652,58898077,77293926,73729762,95277184,81563941,57283977,-771117,-456441,-29488849,22679627,5899338,-18076694,-37016795,-11679478,-41387957,-66065963,-88627508,-59231050,-72154351,-87239154,-98183118,-86163605,-100655815,-71105015,-71941883,-79022844,-95476326,-106781948,-122827571,-3991744,-12632889,-27237421,-19346941,-5049031,25932613,27025347,58034895,43432663,12227336,8100095,-24316081,-26074118,1861244,10308239,-14252133,-42882738,-11297680,-4134810,4642524,-2106749,4520659,4934233,-11147022,-19198158,-2631779,-7452327,10453095,2109765,-2103352,-13046685,5993258,-6044315,-8865526,-36469279,-34399945,-33492684,-66014105,-74152720,-100291068,-74237210,-51603820,-42707028,-25514375,-19566946,-28671426,-45101886,-57481104,-39262753,-53578037,-75105802,-8050453,-27079364,-31976388,-59853991,-76305099,-80118582,-75523310,-53358835,-33059777,23735157,-1173436,28637604,45579674,38153401,33484359,6520549,-19987615,-17046612,-49115976,-67297686,-76330959,-92100052,-78367933,-49573941,-47282497,-45204417,-26379619,-54724537,-31225313,-47054807,-31957234,-31249236,-45845237,-22124907,10320350,14739088,-4252207,-7762331,7155734,29164118,9070424,5290023,22450707,17614712,35173605,15421806,21377612,-11164562,-19598904,-6382529,-10075749,-31582043,-24288750,-17233764,-46634709,-51009691,-37586000,-22709095,-15330330,-41238844,-38766663,-55248088,-35014428,-8943742,5195603,18754494,8744144,17178020,48895778,81969511,58113659]++test6 :: Acc (Vector Int64)+test6 = A.scanl1Seg (+) xs seg+ where+ xs :: Acc (Vector Int64)+ xs = use $ fromList (Z :. 748) [9125498,-25188533,16012055,-27188381,-1098285,-9371024,16587421,9904131,-2631554,-25486177,-7372642,-19824453,23520582,-9676480,-22827761,21856494,-4252137,811931,-14569802,32295175,-6771023,4950290,10722774,-6642889,-19841488,17490820,-2179605,-14086104,-27317700,17646422,15786966,28131812,-27600239,-2158886,1661370,-13322321,-25071977,-6024173,7979223,24604554,2795948,21021796,251585,7369081,10359873,20938516,-11754577,4154549,13858418,-16470594,-30623198,14368006,-20234551,-21782682,26398797,29468760,-6357516,-28827783,26613691,33184238,11901012,13008860,-31538717,-19848243,-33437553,-15016152,-28808214,-13454175,-3620504,-22813060,-32105619,26699703,30531184,-30639665,-7614257,12584983,12529381,-32974667,9227307,21313790,-15949871,17768624,20661075,21149801,9467092,20131268,-13238503,-7333992,11550847,-14444961,-1554452,-14551511,29776267,-16129436,1682633,404444,22617295,30453613,-7448527,-26556359,20227806,-17105891,8650300,-32089833,9323991,12716556,29904839,-29688622,-15919895,-22187055,29421292,1756578,-29257767,4599127,-26070729,-1671158,20652563,-23527198,2288900,11460180,-14885176,26406877,-10910169,26499206,11553105,722043,-17053384,9592179,13249704,-33183411,30403929,3093390,23502571,19192793,2362514,9775133,25937315,13936777,-11730015,-22764073,-15985739,-17273984,-33325576,-30914387,-8770808,31342042,-15747727,7932556,-4620155,-19279309,8776959,12610912,2754980,-3741772,-28100827,13605576,4019354,-25589491,-14641600,-15433270,32391571,-7596012,22317722,22704901,26506216,-26312309,-9162966,11604290,-8442151,-4092963,28768938,23927146,24875049,-16309257,9075873,-18692347,10011195,-21920300,26134427,32912593,-5551781,1882153,-27121444,16950372,-1126688,21119013,1695500,26547990,28957529,-15558430,-13972154,13409965,-26432497,-29889150,18070897,25688131,-27246718,-12397916,31336388,-17039661,11331144,-1995034,3636131,21890924,6108959,-7982438,12869656,-32185347,5204385,-8020711,-23164,-32414160,-707095,21354265,13932741,-15164925,19143311,-8293114,-31029958,-32739608,-7954781,13413352,-14822391,27937201,-12559440,2619156,-16811005,20329993,1247919,-9418943,605247,26091076,-12040244,28952393,-327612,15906335,-5559634,7578213,12199450,-8777520,25700504,-29481382,-21108742,-9296576,-12346996,-6897335,-29291467,10790824,-10235479,-32607689,-16386711,14089027,7472258,17067878,3035231,21981730,7925723,4975340,47183,21493034,4597970,24115430,30425668,-15899571,-28691157,-20252003,25254077,21582669,-701106,31032696,404098,-10641332,-20092885,-10083697,-22533029,28148874,31332821,-17780122,-29634677,2407026,4386849,26726474,-14784724,-23500235,24637825,1034025,-18400464,-15771498,-21415520,31153026,28106661,17196904,25356773,22224278,-2521944,-13991250,18261104,-7891840,32877134,25183256,-28548624,17238240,1948270,-5354424,13706292,24787710,-14069075,11547549,-29486368,-112352,30046527,28613302,-29290526,7396173,14467069,13831148,-15458379,-17484499,17386854,-4744100,-16215207,-3260126,-10188139,21180895,-18726333,-17426637,-20206540,29070717,-16892228,4706892,-17022445,-7143176,-1897403,32958033,12443825,7968818,-24903117,-8873737,-21955856,-19755335,14813217,-31795499,16874316,10625172,-10685501,24577556,-10042634,55143,13866579,-21878725,-21774936,-18509235,-26990002,-64595,26203376,-27185015,-30010945,-29887344,-8145803,25884919,-21237425,-19979324,4683804,-28147527,22930815,26875527,31504260,11713918,-13843679,-24948429,32341576,29343227,25017856,-1738009,26807259,-5320054,-16438208,16542303,-27263046,18056169,25938614,-8771470,17418126,1819043,1610498,8544533,-25578215,4239601,-22488515,33171299,-33469248,830686,-13510451,23698260,7137222,23511426,-31898610,6392606,11902380,-10458154,-27102202,5829980,5677068,-32520848,24977594,26892612,-20570124,2395602,-6108597,-18300410,23755680,18192941,8766478,18513368,33249990,-19247669,28939858,-14074394,7067193,18598518,-25692451,345682,-26109041,-20303421,32025113,-3279825,-10309441,-8331897,-11867595,5157373,33121992,6997828,28892907,32918900,-24853426,12092880,13908280,20464146,33023520,12474560,14520620,-17717239,-12251575,-11301198,-32313252,32056512,2882876,-10183276,-8652210,-6601885,-14230488,17616050,29643810,-17117962,-19981454,-10597201,-13811591,-18524439,31835271,-22819146,-490013,-19389899,3339969,-25502653,23021387,-27360192,-19187634,14573150,27071200,-25708411,-33158140,30412363,5767905,-14125622,-9955587,27893368,22261048,-24570322,25629581,23227637,-18052086,11483256,-15132432,-31673232,20513290,22192233,15594061,-30355166,-23616082,6955579,-11886397,-2653730,24740075,17629659,3296152,-19928114,16478962,20181792,-33059469,-26926901,3986311,-47002,7732537,-26845035,-32088629,25005964,-30622099,31552527,33502206,14709080,20501590,1079821,-29155985,25810913,-3852267,-13527183,1330515,-3705672,-4453248,-13305577,-7617724,-14888342,-27964461,-6163629,30434146,-20856662,-17969153,-25196164,14528267,28182580,-30653575,-28567150,23567848,-4803025,-30242341,-10888079,-4584662,13289635,-4492319,-8502126,-23518983,-7215657,19421839,20417083,18347224,-30636998,-19779616,9052113,1202125,-13859131,-24079328,31450588,6570596,12689823,-7546223,-9288366,14055216,10771210,19807142,33253114,11205780,-20798396,-9152373,-24490693,-27496239,15740292,-26487388,22673030,-29374232,-11681610,20936435,6459171,27439561,6704863,25395495,5690073,-31751720,15629868,10587279,-6740440,-1440456,32215434,-30112960,25011026,-29341436,-17810910,8125703,932584,-28712456,-25362038,-32185766,26790146,4350576,-13726269,-12614845,-705198,30408652,28489425,18395849,-3564164,21547422,-13713243,-24279964,-771117,314676,-29032408,22679627,-16780289,-23976032,-18940101,25337317,-29708479,-24678006,-22561545,29396458,-12923301,-15084803,-10943964,12019513,-14492210,29550800,-836868,-7080961,-16453482,-11305622,-16045623,-3991744,-8641145,-14604532,7890480,14297910,30981644,27025347,31009548,-14602232,-31205327,-4127241,-32416176,-26074118,27935362,8446995,-24560372,-28630605,31585058,7162870,8777334,-6749273,6627408,413574,-16081255,-8051136,16566379,-4820548,17905422,-8343330,-4213117,-10943333,19039943,-12037573,-8865526,-27603753,2069334,907261,-32521421,-8138615,-26138348,26053858,22633390,8896792,17192653,5947429,-9104480,-16430460,-12379218,18218351,-14315284,-21527765,-8050453,-19028911,-4897024,-27877603,-16451108,-3813483,4595272,22164475,20299058,23735157,-24908593,29811040,16942070,-7426273,-4669042,-26963810,-26508164,2941003,-32069364,-18181710,-9033273,-15769093,13732119,28793992,2291444,2078080,18824798,-28344918,23499224,-15829494,15097573,-31249236,-14596001,23720330,32445257,4418738,-18991295,-3510124,14918065,22008384,-20093694,-3780401,17160684,-4835995,17558893,-19751799,5955806,-32542174,-8434342,13216375,-3693220,-21506294,7293293,7054986,-29400945,-4374982,13423691,14876905,7378765,-25908514,2472181,-16481425,20233660,26070686,14139345,13558891,-10010350,8433876,31717758,33073733,-23855852]++ seg :: Acc (Segments Int32)+ seg = use $ fromList (Z :. 40) [14,31,30,35,37,14,15,14,23,12,35,28,25,14,2,4,39,11,26,33,24,1,6,29,25,1,3,17,16,32,7,3,20,6,6,21,18,9,22,40]+++ref7 :: Vector Int64+ref7 = fromList (Z :. 738) [-48782707,-48069783,-76099136,-54652346,-25365627,-15287764,6356466,-12813466,-8407583,19978290,-9072659,-5915918,-36585578,-15711835,15422422,-9019547,-22292746,-32631763,-37371290,-15640610,71266024,76379806,62728369,44496969,47936553,67925416,42543207,28256825,46993513,68696441,62762548,88843983,77734052,65986283,34730508,52119715,67762330,58853279,38574549,13150417,14186593,36907720,65459740,40756535,72731638,74649918,46434954,15908233,-16539565,-31475560,-51915490,-26886587,-15628016,676507,80785577,97966741,122492495,96127350,125381692,121887919,114659417,115475678,82844858,67113463,85021319,117361113,94819908,69936468,84937047,90201353,56988036,23644741,45179661,23562116,38281224,66172480,73193812,82782863,65386382,50390098,43128359,36249064,14980469,108493316,92959780,62909215,43183526,43891523,28202405,38141961,38711587,22173107,33427444,5089227,-19895449,9446767,-9329550,15990062,27937078,10302744,-15427015,-24032122,220227,-244305648,-248544880,-216775110,-202718801,-203420228,-192771970,-167669427,-197813315,-199494672,-197082872,-207854928,-211196422,-193844772,-181103988,-181876034,-165735816,-133474822,-106956023,-82248081,-49842013,-69252000,-65369160,-46610625,-13293665,-86242428,-77700448,-54939430,-49026334,-81348375,-63863233,-81374276,-66370269,-64109103,-82546545,-101149747,-117134127,-97831968,-79075256,-93927664,-106999178,-116193016,-111355657,-142840401,-149392627,-128125153,-121344215,-116284247,-146348780,-122554770,-94499397,-65672590,-75420069,-49490678,-44521996,-49552615,-22516329,-31498419,-59429269,-30793092,-17012933,-19585098,-19894459,-11313269,17242975,26384275,20837140,-39580349,-32039154,-58779061,-31809529,-31860791,-62928294,-45073900,-71749150,-59563687,-46788878,-79384275,-68620575,-48661520,-21830363,-31430266,21524909,35884674,36972475,29674096,20377847,20983226,38258246,20827628,-14124025,-41503458,-57583707,-42613410,-71982937,-49774496,-41193192,-53347165,-62309796,-71478479,-45886895,-78704146,-59158164,-67547671,-44882655,-16244584,-38481867,-30340794,1470458,17149252,36086423,59062879,56262539,35254717,13744500,14429826,20662188,3507389,12225467,22022073,20840496,49430785,30701622,-176961463,-151524797,-172754811,-202787227,-209645388,-208244461,-196470369,-206049987,-190830353,-171109808,-139130211,-111671490,-132637043,-125735699,-106374742,-94463283,-74530374,-102363645,-88879041,-75249338,-86163630,-58293022,-71134360,-74292036,-41027036,-43611173,-45664281,-46838277,-14775189,-21989256,-215581,4895895,26505964,9881215,6006006,21791812,30399863,11059334,-15405962,-40457904,-51506444,-34718154,-12018577,6175960,31133560,-15381417,-24454448,-5290847,-23131138,-90166937,-94603634,-110598990,-102018157,-103077965,-101919562,-112451349,-79323195,-69828212,-41204487,-48476615,-16487710,-19288308,-19650316,-15196570,-14200432,14249659,26415718,-1787516,24530828,-3765711,22589689,20470588,11663379,13847971,-19004777,-8662105,-16191632,-16504147,-18339663,6010780,26824986,-263637509,-233180488,-217662025,-240293973,-229737496,-233942831,-266581338,-240283840,-221970049,-192160233,-186556300,-156510619,-157980671,-159298043,-191254443,-165340852,-181342218,-154490961,-142888991,-125613381,-105764731,-74423852,-43553208,-71733054,-38403655,-65769516,-41776811,-66580138,-58084207,-60606933,-31855509,-30976667,-60210984,-46087807,-45645362,-18703486,-11448733,-18539947,-44401293,-77378414,-104806024,-119161329,-145595331,-128577399,-102240384,-131731412,-153965054,-138203406,-136107911,-169236957,-171380864,-177805907,-154124779,-177987589,-154112100,-137736720,-122295605,-123319691,-152104867,-133462923,-163731604,-137346078,-141974369,-139229959,-115343677,-100246891,-101857581,-79635122,-58498597,-56956671,-27846111,2514723,14539638,-856211,6094147,-143939605,-114556906,-93259166,-62776322,-51886782,-49805668,-49431917,-74588752,-52582864,-69028392,-49573309,-53206133,-29967317,-15913522,-35424192,-42953149,-34525589,-22120615,-22458128,-37201856,-59870268,-63601712,-55156115,-39259547,-20561668,-13924991,-4343294,-3802313,122068251,133014364,106044038,103669137,134430169,148789334,141929442,110101523,78227591,63166498,42545018,37401662,43844352,61892182,38965269,61152447,43991599,42367631,56420014,48147227,16120995,13523168,-12973607,1166745,20340645,-8645743,69400609,62637313,33238840,5342820,17405647,4881263,10407925,-22227407,-9285528,-24279449,-31837105,-12669381,-34047179,-2711090,-26208960,2899657,-97174441,-112298451,-79439394,-84329209,-78384623,-105840777,-126752608,-110394917,-138128377,-134889126,-108654091,-114727725,-98923120,-66683703,-35041593,-51372583,-34976067,-61712406,-48730299,-26309307,-3152004,30193014,162071102,135062608,113614122,97742763,89441064,68362698,89887651,72658190,54790707,28888401,14596198,6934234,-51398793,-36048649,-64586259,-77001171,-108515514,-101660672,-120183736,-103974869,-107572971,-126104081,-97581382,-67174136,-69001306,-76561059,-48904254,-50376102,-47702115,-29837381,-44448701,-52078856,-20635428,-24924851,-35615675,-68278334,-96389847,-97000000,-80417765,-49553418,-27291772,-38508142,-30069928,-59576150,-51106683,-24593113,75962,138863600,158599246,130947464,109890205,82891951,55655298,43959461,18718460,27418095,1490441,-25173893,-41233589,-11411110,-4784998,21180595,-20092951,-19866345,-14625234,-1393509,-30003860,48038753,41278966,56150464,24427936,48510687,46956838,18206865,-14599729,-12438450,-12136742,-20552578,-34069029,-41733751,-22523991,-55669734,-46280266,-31205428,-27829333,-4518109,-37115511,-20546874,3069181,1104372,31215428,35398190,14119871,-8341624,-19741499,-6338114,7013637,-12550393,10571885,17180134,22004968,26290384,15424987,-12196414,-27805732,3893455,3705021,34303755,10858903,44234506,69653623,59799317,41855292,47636949,70210705,49577396,32263101,12862903,-3141227,8704244,-15735990,-42463538,-14281982,-34140899,-29944926,-48194015,-73380186,-53981004,-25683673,3436705,-347326,-13473324,-28337288,-6060609,-36670246,-40321076,-26406623,-25136754,-50993989,-19489063,11995210,-11523983,-31765052,-19746897,13123904,22054274,35973231,46315575,58458518,64785448,37087818,60336567,50407722,60213274,88311583,75588379,50392946,50310126,60156227,28023981,-4599077,-15670813,-480659,66326700,88952449,112560471,80424796,59167705,49073681,69439599,36559892,13608188,-10849505,-27511038,-18002566,-11679162,-14245301,-33196908,-59458637,-88762770,-76931280,-75985853,-73664670,-54646553,-73314781,-98519275,-131515581,-101578410,-70993721,-48717455,-34490455,-9721647,-33346014,-64431160,-74351523,-48527265,-47818443,-39778144,-27056813,3172756,16428504,32078563,27314822,-84911462,-70883891,-67734204,-58203952,-29560484,-7636085,-32316716,-33073244,-31465591,-19382415,-19463832,-51250364,-69332001,-43742902,-15587162,-18707052,-27391604,-8628411,-29019238,-14338164,-32687266,-34755132,-21912223,-40789415,-56697052,-30869305,8245928,22216157,-1300450,-8539733,15367658,-4898165,-23038236,-8233426,20237515,-1488029,-3344902,24899437,13240791,356287,30134185,24453047,-6857567,-11423381,8820097,40066727,55587484,72052998,100594380,76094952,61642627,29001112,9974448,42079530,9172704,-11553890,-34131793,-8675576,-36427927,-22535570,-42072165,-27144828]++test7 :: Acc (Vector Int64)+test7 = A.scanr1Seg (+) xs seg+ where+ xs :: Acc (Vector Int64)+ xs = use $ fromList (Z :. 738) [-712924,28029353,-21446790,-29286719,-10077863,-21644230,19169932,-4405883,-28385873,29050949,-3156741,30669660,-20873743,-31134257,24441969,13273199,10339017,4739527,-21730680,-15640610,-5113782,13651437,18231400,-3439584,-19988863,25382209,14286382,-18736688,-21702928,5933893,-26081435,11109931,11747769,31255775,-17389207,-15642615,8909051,20278730,25424132,-1036176,-22721127,-28552020,24703205,-31975103,-1918280,28214964,30526721,32447798,14935995,20439930,-25028903,-11258571,-16304523,676507,-17181164,-24525754,26365145,-29254342,3493773,7228502,-816261,32630820,15731395,-17907856,-32339794,22541205,24883440,-15000579,-5264306,33213317,33343295,-21534920,21617545,-14719108,-27891256,-7021332,-9589051,17396481,14996284,7261739,6879295,21268595,14980469,15533536,30050565,19725689,-707997,15689118,-9939556,-569626,16538480,-11254337,28338217,24984676,-29342216,18776317,-25319612,-11947016,17634334,25729759,8605107,-24252349,220227,4239232,-31769770,-14056309,701427,-10648258,-25102543,30143888,1681357,-2411800,10772056,3341494,-17351650,-12740784,772046,-16140218,-32260994,-26518799,-24707942,-32406068,19409987,-3882840,-18758535,-33316960,-13293665,-8541980,-22761018,-5913096,32322041,-17485142,17511043,-15004007,-2261166,18437442,18603202,15984380,-19302159,-18756712,14852408,13071514,9193838,-4837359,31484744,6552226,-21267474,-6780938,-5059968,30064533,-23794010,-28055373,-28826807,9747479,-25929391,-4968682,5030619,-27036286,8982090,-31498419,-28636177,-13780159,2572165,309361,-8581190,-28556244,-9141300,5547135,20837140,-7541195,26739907,-26969532,51262,31067503,-17854394,26675250,-12185463,-12774809,32595397,-10763700,-19959055,-26831157,9599903,-31430266,-14359765,-1087801,7298379,9296249,-605379,-17275020,17430618,20827628,27379433,16080249,-14970297,29369527,-22208441,-8581304,12153973,8962631,9168683,-25591584,32817251,-19545982,8389507,-22665016,-28638071,22237283,-8141073,-31811252,-15678794,-18937171,-22976456,2800340,21007822,21510217,-685326,-6232362,17154799,-8718078,-9796606,1181577,-28590289,18729163,30701622,-25436666,21230014,30032416,6858161,-1400927,-11774092,9579618,-15219634,-19720545,-31979597,-27458721,20965553,-6901344,-19360957,-11911459,-19932909,27833271,-13484604,-13629703,10914292,-27870608,12841338,3157676,-33265000,2584137,2053108,1173996,-32063088,7214067,-21773675,-5111476,-21610069,16624749,3875209,-15785806,21791812,19340529,26465296,25051942,11048540,-16788290,-22699577,-18194537,-24957600,31133560,9073031,-19163601,17840291,-23131138,4436697,15995356,-8580833,1059808,-1158403,10531787,-33128154,-9494983,-28623725,7272128,-31988905,2800598,362008,-4453746,-996138,-28450091,-12166059,28203234,-1787516,28296539,-26355400,2119101,8807209,-2184592,32852748,-10342672,7529527,312515,1835516,-24350443,-20814206,26824986,-30457021,-15518463,22631948,-10556477,4205335,32638507,-26297498,-18313791,-29809816,-5603933,-30045681,1470052,1317372,31956400,-25913591,16001366,-26851257,-11601970,-17275610,-19848650,-31340879,-30870644,28179846,-33329399,27365861,-23992705,24803327,-8495931,2522726,-28751424,-878842,29234317,-14123177,-442445,-26941876,-7254753,-11448733,25861346,32977121,27427610,14355305,26434002,-17017932,-26337015,29491028,22233642,-15761648,-2095495,33129046,2143907,6425043,-23681128,23862810,-23875489,-16375380,-15441115,1024086,28785176,-18641944,30268681,-26385526,4628291,-2744410,-23886282,-15096786,1610690,-22222459,-21136525,-1541926,-29110560,-30360834,-12024915,15395849,-6950358,6094147,-29382699,-21297740,-30482844,-10889540,-2081114,-373751,25156835,-22005888,16445528,-19455083,3632824,-23238816,-14053795,19510670,7528957,-8427560,-12404974,337513,14743728,22668412,3731444,-8445597,-15896568,-18697879,-20561668,-9581697,-540981,-3802313,-10946113,26970326,2374901,-30761032,-14359165,6859892,31827919,31873932,15061093,20621480,5143356,-6442690,-18047830,22926913,-22187178,17160848,1623968,-14052383,8272787,32026232,2597827,26496775,-14140352,-19173900,28986388,-8645743,6763296,29398473,27896020,-12062827,12524384,-5526662,32635332,-12941879,14993921,7557656,-19167724,21377798,-31336089,23497870,-29108617,2899657,15124010,-32859057,4889815,-5944586,27456154,20911831,-16357691,27733460,-3239251,-26235035,6073634,-15804605,-32239417,-31642110,16330990,-16396516,26736339,-12982107,-22420992,-23157303,-33345018,30193014,27008494,21448486,15871359,8301699,21078366,-21524953,17229461,17867483,25902306,14292203,7661964,6934234,-15350144,28537610,12414912,31514343,-6854842,18523064,-16208867,3598102,18531110,-28522699,-30407246,1827170,7559753,-27656805,1471848,-2673987,-17864734,14611320,7630155,-31443428,4289423,10690824,32662659,28111513,610153,-16582235,-30864347,-22261646,11216370,-8438214,29506222,-8469467,-26513570,-24669075,75962,-19735646,27651782,21057259,26998254,27236653,11695837,25241001,-8699635,25927654,26664334,16059696,-29822479,-6626112,-25965593,21180595,-226606,-5241111,-13231725,28610351,-30003860,6759787,-14871498,31722528,-24082751,1553849,28749973,32806594,-2161279,-301708,8415836,13516451,7664722,-19209760,33145743,-9389468,-15074838,-3376095,-23311224,32597402,-16568637,-23616055,1964809,-30111056,-4182762,21278319,22461495,11399875,-13403385,-13351751,19564030,-23122278,-6608249,-4824834,22004968,10865397,27621401,15609318,-31699187,188434,-30598734,23444852,-33375603,-25419117,9854306,17944025,-5781657,-22573756,20633309,17314295,19400198,16004130,-11845471,24440234,26727548,-28181556,19858917,-4195973,18249089,25186171,-19399182,-28297331,-29120378,3436705,13125998,14863964,-22276679,30609637,3650830,-13914453,-1269869,25857235,-31504926,-31484273,23519193,20241069,-12018155,-32870801,-8930370,-13918957,-10342344,-12142943,-6326930,27697630,-23248749,9928845,-9805552,-28098309,12723204,25195433,82820,-9846101,32132246,32623058,11071736,-15190154,-480659,-22625749,-23608022,32135675,21257091,10094024,-20365918,32879707,22951704,24457693,16661533,-9508472,-6323404,2566139,18951607,26261729,29304133,-11831490,-945427,-2321183,-19018117,18668228,25204494,32996306,-29937171,-30584689,-22276266,-14227000,-24768808,23624367,31085146,9920363,-25824258,-708822,-8040299,-12721331,-30229569,-13255748,-15650059,4763741,27314822,-14027571,-3149687,-9530252,-28643468,-21924399,24680631,756528,-1607653,-12083176,81417,31786532,18081637,-25589099,-28155740,3119890,8684552,-18763193,20390827,-14681074,18349102,2067866,-12842909,18877192,15907637,-25827747,-30869305,-13970229,23516607,7239283,-23907391,20265823,18140071,-23038236,-28470941,21725544,1856873,-28244339,11658646,12884504,-29777898,5681138,31310614,4565814,-20243478,-31246630,-15520757,-16465514,-28541382,24499428,14452325,32641515,19026664,-32105082,32906826,20726594,22577903,-25456217,27752351,-13892357,19536595,-14927337,-27144828]++ seg :: Acc (Segments Int32)+ seg = use $ fromList (Z :. 33) [20,34,29,20,24,33,9,15,8,33,36,9,4,19,13,37,38,25,3,26,16,22,12,35,15,5,34,29,33,40,26,7,29]+++ref8 :: Vector Int64+ref8 = fromList (Z :. 645) [0,-3770243,-5579205,-7046208,-10121610,-11747201,-13282326,-17283687,-18231759,-20046491,-21926492,-22713980,-26318076,-28006910,-31889802,-34194230,-38096679,-39693040,-35966076,-38959249,-41938765,-41994560,-41013600,-41922485,-39410829,-38960516,-35942875,-33376608,-29844503,-29318389,-28736296,-25580458,-29739876,-32401640,-36553276,-40171099,0,345952,-2993267,-5717922,-9907694,-10027890,-13870687,-11867126,-9328942,-6192885,-8184575,-11674536,-10400036,-11388719,-10353407,-8145138,-6678399,-2486811,-6487953,-8733058,-10561951,-6480166,-7972853,0,1139992,-104326,1079373,3348511,0,3395695,6337287,4100926,1022638,1452658,0,3593867,3814687,6806052,3747065,2713485,3570566,5270237,6848581,6155011,1966243,5365176,3983882,286985,2324988,721490,466546,-700995,-338083,2411347,3365002,3154319,3507792,4576100,0,-2285386,-4288389,-7082102,-4660000,-857446,721455,660475,273568,-2789646,-6674913,-9130960,-11826040,-9536699,-6104295,-9673441,-11613956,-10411885,-12286738,-8645110,-8436095,-7590486,-4452638,-1581976,0,-934927,1608397,304641,-2958108,-942792,-1396361,-3542834,0,2350876,227658,-3779069,-1035644,-972794,-3797476,-4505766,-4865910,-7425388,-7182479,-9067132,-10043764,-8627455,-4953615,-3166350,0,1298211,4883021,8143644,9991079,13383006,11704147,11985221,8647018,8086113,7664604,8718062,11039021,7936960,4598083,5635829,1450422,159881,3657858,4103183,3527017,883273,-1321504,-2478748,-1006972,455760,4266983,7194819,11232555,9833490,12524076,16207697,20249758,19286134,17160940,18352071,0,-1562519,-3710355,-2848884,0,741078,2195352,1715399,4902918,2472295,-1673954,951060,-205765,-410930,2925408,0,2661266,6376248,6698089,7240432,9214046,10362817,13102857,16942419,20040610,19554929,18142416,20333122,24002080,25936153,26861250,28286514,25107483,27772679,25952139,0,124429,3721751,0,4171155,4260049,3631576,713779,-1444554,1964929,2806146,4319313,995223,3554404,-282429,96550,1888015,3379400,3874424,5448190,8604326,7429367,4814852,0,-3835274,170581,-3872285,-4136902,-6586985,-8127633,-9740679,-10940596,-11302147,-14863360,-16636561,-15426039,-18342257,-16067741,-12830665,-14394729,-17308091,-13537763,-10075189,-6255542,-4427649,-8416077,-10456703,-8195749,-5827305,-4993142,-3673480,0,869492,1594197,4025097,2848783,0,2126507,3949710,4447981,1253204,3235070,7367011,5351006,6654097,2818742,5393616,4706372,3331207,1161359,0,1885699,1289175,-763581,2481999,2068732,6240239,9030236,6369832,3409522,1150603,-1677392,-773316,-3184156,404696,-683547,910053,-2491074,-94029,-2827691,-5512379,-7783991,-8736510,-6524861,-2725098,-5093277,-6514413,0,742604,-606571,-725780,1744947,3431452,-405237,-457263,709944,4319401,624627,-2608016,0,3642681,2908707,5512358,5530669,0,-3215609,-7345078,-8196654,-11105059,-12591552,-15198735,-11340348,-10281817,-12147811,-10530601,-11500997,-7477780,-10439606,-9986548,0,3533811,4486946,5531887,1511249,-557775,435067,1631130,1815263,-1867113,2273415,1514738,-1206877,555832,741913,-3166709,-287429,-4411008,-4700935,-3946601,-4617892,-7550664,-6112017,0,-667061,-1239970,1156892,-722075,-4186731,-7404810,-11407733,-13636105,-12949852,-11213787,-11386775,-15541235,-18076969,-21589829,-19336525,-21546880,-20418698,-24006743,-23003415,-19580602,-16414098,-17729103,-17560035,-21218247,0,-781526,1156089,-2142153,-419575,-3055657,-716334,-2312034,118635,711944,4112840,7878285,7762706,8255775,8380414,11299416,12714032,15289946,14300365,15027849,19200256,22844171,0,-1224713,1837521,62083,-2435081,-280845,3789736,4259660,7108468,3611361,1501427,4453169,6217988,9274431,13178646,16388059,15410829,13060952,14279789,17319316,14533179,13976967,9836157,7001049,5716786,5459256,5101104,7249617,8962409,9911065,7505371,7218925,8578944,5307366,0,859492,-3077001,-4576770,-8344542,-8263692,-9244057,-8761336,-10520101,-11364186,-10078629,-11263983,-11008053,-14512411,-14775947,-16672625,-14513613,0,694423,-1173637,-2704935,1260688,4786656,1709582,-249261,-2458089,-4733195,-3473620,-3843053,-150511,-4048267,-6698308,-2513431,-6005597,-4249435,-4821144,-8932215,-8692409,-4892474,-3015738,-914415,773709,4562402,8689641,8298796,12102005,13700416,12590982,9153649,7960537,6137906,4292150,2600272,-1457822,0,-1806374,1041907,-2078323,-842307,-3701664,0,-2626906,-2068475,1803835,-316068,-1526877,-3914878,-1840677,-2474665,-4520977,-6059889,0,-161266,2625449,4235821,4877373,1374740,118771,2880196,4463038,3245456,6984711,3642280,2229177,3494184,3387547,5293512,1401776,4539065,6886384,11057250,14889641,15259441,13231998,10138107,7266168,8228888,5129351,1841256,1082772,724230,-2146010,-859151,1049573,2686216,-1006176,1740846,0,-2567334,487038,-3421145,-4411824,-6418173,-4404660,0,2828945,6815455,7060886,6549094,9292080,13211354,12694643,14924363,12485234,14542169,14311383,16026086,17059251,18866314,15263353,18915246,20747408,20628390,21408706,20042728,24104321,21412324,24779975,23077325,20881558,22407427,20391992,21407566,19978783,0,1589469,-794608,-1541980,-1274750,-1931789,-3719881,-175562,1353495,3729793,4102597,330109,-90750,2740945,4316009,2734066,4093765,656207,-844822,-3930596,-1093202,-2998732,564186,3880070,5179086,6959784,10449214,14577355,13359512,0,1964984,3384303,1505373,3694802,6588743,0,1412262,5040779,5239461,9430965,6115620,10111491,10560650,8218897,4044049,4210501,1038630,1711549,0,-3317531,-4953062,-1809142,-1092410,-3951290,-7965161]++test8 :: Acc (Vector Int64)+test8 = A.scanlSeg (+) 0 xs seg+ where+ xs :: Acc (Vector Int64)+ xs = use $ fromList (Z :. 609) [-3770243,-1808962,-1467003,-3075402,-1625591,-1535125,-4001361,-948072,-1814732,-1880001,-787488,-3604096,-1688834,-3882892,-2304428,-3902449,-1596361,3726964,-2993173,-2979516,-55795,980960,-908885,2511656,450313,3017641,2566267,3532105,526114,582093,3155838,-4159418,-2661764,-4151636,-3617823,345952,-3339219,-2724655,-4189772,-120196,-3842797,2003561,2538184,3136057,-1991690,-3489961,1274500,-988683,1035312,2208269,1466739,4191588,-4001142,-2245105,-1828893,4081785,-1492687,1139992,-1244318,1183699,2269138,3395695,2941592,-2236361,-3078288,430020,3593867,220820,2991365,-3058987,-1033580,857081,1699671,1578344,-693570,-4188768,3398933,-1381294,-3696897,2038003,-1603498,-254944,-1167541,362912,2749430,953655,-210683,353473,1068308,-2285386,-2003003,-2793713,2422102,3802554,1578901,-60980,-386907,-3063214,-3885267,-2456047,-2695080,2289341,3432404,-3569146,-1940515,1202071,-1874853,3641628,209015,845609,3137848,2870662,-934927,2543324,-1303756,-3262749,2015316,-453569,-2146473,2350876,-2123218,-4006727,2743425,62850,-2824682,-708290,-360144,-2559478,242909,-1884653,-976632,1416309,3673840,1787265,1298211,3584810,3260623,1847435,3391927,-1678859,281074,-3338203,-560905,-421509,1053458,2320959,-3102061,-3338877,1037746,-4185407,-1290541,3497977,445325,-576166,-2643744,-2204777,-1157244,1471776,1462732,3811223,2927836,4037736,-1399065,2690586,3683621,4042061,-963624,-2125194,1191131,-1562519,-2147836,861471,741078,1454274,-479953,3187519,-2430623,-4146249,2625014,-1156825,-205165,3336338,2661266,3714982,321841,542343,1973614,1148771,2740040,3839562,3098191,-485681,-1412513,2190706,3668958,1934073,925097,1425264,-3179031,2665196,-1820540,124429,3597322,4171155,88894,-628473,-2917797,-2158333,3409483,841217,1513167,-3324090,2559181,-3836833,378979,1791465,1491385,495024,1573766,3156136,-1174959,-2614515,-3835274,4005855,-4042866,-264617,-2450083,-1540648,-1613046,-1199917,-361551,-3561213,-1773201,1210522,-2916218,2274516,3237076,-1564064,-2913362,3770328,3462574,3819647,1827893,-3988428,-2040626,2260954,2368444,834163,1319662,869492,724705,2430900,-1176314,2126507,1823203,498271,-3194777,1981866,4131941,-2016005,1303091,-3835355,2574874,-687244,-1375165,-2169848,1885699,-596524,-2052756,3245580,-413267,4171507,2789997,-2660404,-2960310,-2258919,-2827995,904076,-2410840,3588852,-1088243,1593600,-3401127,2397045,-2733662,-2684688,-2271612,-952519,2211649,3799763,-2368179,-1421136,742604,-1349175,-119209,2470727,1686505,-3836689,-52026,1167207,3609457,-3694774,-3232643,3642681,-733974,2603651,18311,-3215609,-4129469,-851576,-2908405,-1486493,-2607183,3858387,1058531,-1865994,1617210,-970396,4023217,-2961826,453058,3533811,953135,1044941,-4020638,-2069024,992842,1196063,184133,-3682376,4140528,-758677,-2721615,1762709,186081,-3908622,2879280,-4123579,-289927,754334,-671291,-2932772,1438647,-667061,-572909,2396862,-1878967,-3464656,-3218079,-4002923,-2228372,686253,1736065,-172988,-4154460,-2535734,-3512860,2253304,-2210355,1128182,-3588045,1003328,3422813,3166504,-1315005,169068,-3658212,-781526,1937615,-3298242,1722578,-2636082,2339323,-1595700,2430669,593309,3400896,3765445,-115579,493069,124639,2919002,1414616,2575914,-989581,727484,4172407,3643915,-1224713,3062234,-1775438,-2497164,2154236,4070581,469924,2848808,-3497107,-2109934,2951742,1764819,3056443,3904215,3209413,-977230,-2349877,1218837,3039527,-2786137,-556212,-4140810,-2835108,-1284263,-257530,-358152,2148513,1712792,948656,-2405694,-286446,1360019,-3271578,859492,-3936493,-1499769,-3767772,80850,-980365,482721,-1758765,-844085,1285557,-1185354,255930,-3504358,-263536,-1896678,2159012,694423,-1868060,-1531298,3965623,3525968,-3077074,-1958843,-2208828,-2275106,1259575,-369433,3692542,-3897756,-2650041,4184877,-3492166,1756162,-571709,-4111071,239806,3799935,1876736,2101323,1688124,3788693,4127239,-390845,3803209,1598411,-1109434,-3437333,-1193112,-1822631,-1845756,-1691878,-4058094,-1806374,2848281,-3120230,1236016,-2859357,-2626906,558431,3872310,-2119903,-1210809,-2388001,2074201,-633988,-2046312,-1538912,-161266,2786715,1610372,641552,-3502633,-1255969,2761425,1582842,-1217582,3739255,-3342431,-1413103,1265007,-106637,1905965,-3891736,3137289,2347319,4170866,3832391,369800,-2027443,-3093891,-2871939,962720,-3099537,-3288095,-758484,-358542,-2870240,1286859,1908724,1636643,-3692392,2747022,-2567334,3054372,-3908183,-990679,-2006349,2013513,2828945,3986510,245431,-511792,2742986,3919274,-516711,2229720,-2439129,2056935,-230786,1714703,1033165,1807063,-3602961,3651893,1832162,-119018,780316,-1365978,4061593,-2691997,3367651,-1702650,-2195767,1525869,-2015435,1015574,-1428783,1589469,-2384077,-747372,267230,-657039,-1788092,3544319,1529057,2376298,372804,-3772488,-420859,2831695,1575064,-1581943,1359699,-3437558,-1501029,-3085774,2837394,-1905530,3562918,3315884,1299016,1780698,3489430,4128141,-1217843,1964984,1419319,-1878930,2189429,2893941,1412262,3628517,198682,4191504,-3315345,3995871,449159,-2341753,-4174848,166452,-3171871,672919,-3317531,-1635531,3143920,716732,-2858880,-4013871]++ seg :: Acc (Segments Int32)+ seg = use $ fromList (Z :. 36) [35,22,4,5,23,23,7,15,35,3,10,19,2,19,27,4,13,26,11,4,14,22,24,21,33,16,36,5,10,35,6,29,28,5,12,6]+++ref9 :: Vector Int64+ref9 = fromList (Z :. 661) [-23545410,-19092190,-15199726,-12351144,-19787110,-24907783,-28924702,-22582323,-15004292,-7986712,-15814964,-12796809,-20874665,-23199295,-21814743,-14474247,-11428070,-11326540,-11987400,-14049880,-15904429,-16813716,-20127269,-27880670,-27115572,-22970078,-19161294,-20116738,-25696300,-20399870,-12598014,-4441841,-5339204,0,5258152,-3047807,-4983198,-152087,-6694074,-2774154,3094062,8979166,16074241,10127078,17254868,10052255,14618407,7297758,13556880,7757925,4862968,0,7035358,13265906,15886283,9773585,17111824,11482952,10360509,16178260,11573685,8057435,8957179,1861100,-4510903,2522742,-1952534,343602,-931257,1182026,8572670,9866510,5314905,0,9915533,6504277,14881592,17126294,9902843,9461226,11857883,12119033,7534110,13764697,17029680,12738298,10093900,9378149,1497597,4121921,6980765,5509560,13297927,19208174,13439826,9261637,3697126,1029090,5742435,7165092,9870407,4667463,9603255,3143595,0,19520337,24293005,18170289,16949209,24484583,25098797,16940571,17168669,20017902,18512677,17276624,20668621,23764749,18559293,19179431,13603545,6821021,4128258,5178140,1807923,625766,-5793038,557951,8468013,16821699,9014973,10154282,13712629,15418321,17772979,13187310,9341891,9346469,3562777,-4236026,3943064,1821268,0,-17597987,-14338111,-13160839,-21095607,-13659930,-5524189,-447843,3198401,-3906944,2444625,4930508,0,-1780995,4941517,3428221,6945832,5471438,-2089694,-1840520,-748417,-622281,-4266815,-3578951,4175923,1214444,-6157294,-11771424,-4253316,122413,-5115729,-2403737,-2280632,-7692875,-7176319,165603,-4608911,2275343,4121415,3691356,8960495,8220951,6560764,3361772,122451,2068485,2266879,0,-23261891,-21773982,-18640394,-16250482,-8288981,-14366391,-12019056,-4951591,0,10327511,16096523,11513457,3775062,1456323,950660,0,39500473,42134191,49326132,44908043,44189915,40545597,42583889,36771665,37976838,42637161,43042497,41877155,36320177,36033649,30456233,23955666,24578825,25647024,25212428,22072107,15320240,7407492,5131363,10409387,17711966,18345108,25613171,20134088,18672784,20466069,19103089,11665491,5005634,2753606,2758578,0,-23237696,-29354162,-28222112,-22820572,-18856465,-11451199,-6544145,-13678867,-15169991,-16665935,-8801766,-16956831,-22118443,-14855674,-19710134,-18333052,-12310671,-12903337,-8724596,-6190610,-12330615,-6733634,-2371106,277264,-6820245,0,9171599,16241475,9734750,11053683,4530017,-3696390,3735716,11641789,12422324,8541343,10317301,6602275,6515789,1853520,2351453,6520804,8199852,16513029,15956233,17535751,12479352,11996485,11488976,15956849,19335984,20273115,14309339,8502747,5054202,4792421,-1998961,6344690,0,8641635,14614220,22621519,24778420,22934500,30033834,31388539,31358268,35741081,35363404,28488749,35704092,39869443,33641031,41683686,43114143,37049122,42162389,38581957,30630741,33093671,29883603,26722722,28918564,23162080,17010863,15643511,8259148,0,67812641,73385203,68588801,71302771,70440392,68339659,72121169,71757257,71620440,66640453,59362044,56439252,50169030,50545377,46897589,42431129,34191912,25809204,22184527,16142939,18006336,15320689,8056937,4727494,4455178,4714354,-2929312,3315582,-712782,0,-10533559,-7453596,-7355822,-11184899,-5346034,-5517666,-5655507,-13233681,-11036355,-15169542,-11673998,-13330134,-12975730,-15731486,-23927365,-15672527,-7651033,-41473,5213372,8569093,5202320,-1932697,4629347,7838047,-310810,-1472760,-1483648,-7832330,-10302351,-7461765,0,56489872,57285707,49989598,56584906,62675766,58030500,53272676,57170277,51364588,45405741,41313157,33038217,27969264,30537052,29338965,24226308,21920794,18781965,16276111,17831599,19945279,12010786,11775519,15528815,8084160,6735740,1256501,0,-4316639,-649184,-2875249,-1265836,-8062475,-1039628,-4165745,2818361,3338123,3984362,-2416008,1539566,1949311,7282131,1416000,2812559,4846439,-1681841,0,17517431,20918622,15129697,12644787,9788494,4980177,4751268,5168036,12807316,6885561,0,-12911606,-7044558,-4259336,-1778572,3942903,-99590,-1755397,1187146,-5227554,-2697658,-5743694,-9164574,-17324325,-9573146,-9518972,-7544657,-3459738,4724166,-2766402,0,-28888665,-23766795,-17908909,-23193011,-18768818,-18321941,-12120774,-4097683,3882582,11680259,16891026,8958627,9777882,4023025,0,-28142843,-31706317,-23725731,-17057441,-23215793,-22411703,-21651678,-16896450,-9881916,-14102625,-16892825,-11726368,-6761066,-8913778,-8706274,-16789108,-15505593,-17559207,-10278334,-2276389,2567755,8618151,12914239,11325856,6127225,622598,8390786,12165621,9912453,4123344,214225,-3540061,-3451397,0,22049876,24841111,19336800,18657023,17237080,16187600,12259897,11391983,6247808,12737198,14285951,16115720,7891953,5229659,12852009,14056688,10927973,15415445,15884318,9189272,15118784,14926893,16328727,24176496,21498476,13130655,9949458,7428893,4075586,2266204,2732845,0,-5712816,-5352191,521344,-2229408,265697,7718151,0,10535066,8408094,12259060,5061913,7346875,12522051,9215406,7737787,3313157,9824900,8315680,14840204,13742226,6034361,12850753,5702446,-584149,-132181,5582800,12810567,7762879,5801224,3571657,2874166,0,-24212535,-26325437,-21693913,-14975748,-19464741,-17568114,-22144287,-26451701,-24659593,-27491447,-34368798,-33273519,-31645836,-27659172,-19824103,-17292768,-17232842,-21445918,-17409995,-11585791,-18676054,-13722054,-6234778,0,-26835027,-26837945,-31679362,-27828204,-24983789,-27977465,-22748208,-18058978,-9787299,-2368565,4785532,-149793,-1166138,-1765051,6274501,-215131,2298449,-4372183,-5668260,-4416255,570850,-3446772,2138867,-3249857,3212736,5020102,6795919,0,-22301653,-17085039,-17386088,-12674648,-7197062,-4438712,2099952,6419507,10331533,18614405,16136985,16786718,17272339,12394596,15925356,21566888,14364344,8727743,12639637,16706011,14337230,9800607,6454097,8805762,2901622,2003370,0]++test9 :: Acc (Vector Int64)+test9 = A.scanrSeg (+) 0 xs seg+ where+ xs :: Acc (Vector Int64)+ xs = use $ fromList (Z :. 634) [-4453220,-3892464,-2848582,7435966,5120673,4016919,-6342379,-7578031,-7017580,7828252,-3018155,8077856,2324630,-1384552,-7340496,-3046177,-101530,660860,2062480,1854549,909287,3313553,7753401,-765098,-4145494,-3808784,955444,5579562,-5296430,-7801856,-8156173,897363,-5339204,8305959,1935391,-4831111,6541987,-3919920,-5868216,-5885104,-7095075,5947163,-7127790,7202613,-4566152,7320649,-6259122,5798955,2894957,4862968,-6230548,-2620377,6112698,-7338239,5628872,1122443,-5817751,4604575,3516250,-899744,7096079,6372003,-7033645,4475276,-2296136,1274859,-2113283,-7390644,-1293840,4551605,5314905,3411256,-8377315,-2244702,7223451,441617,-2396657,-261150,4584923,-6230587,-3264983,4291382,2644398,715751,7880552,-2624324,-2858844,1471205,-7788367,-5910247,5768348,4178189,5564511,2668036,-4713345,-1422657,-2705315,5202944,-4935792,6459660,3143595,-4772668,6122716,1221080,-7535374,-614214,8158226,-228098,-2849233,1505225,1236053,-3391997,-3096128,5205456,-620138,5575886,6782524,2692763,-1049882,3370217,1182157,6418804,-6350989,-7910062,-8353686,7806726,-1139309,-3558347,-1705692,-2354658,4585669,3845419,-4578,5783692,7798803,-8179090,2121796,1821268,-3259876,-1177272,7934768,-7435677,-8135741,-5076346,-3646244,7105345,-6351569,-2485883,4930508,-6722512,1513296,-3517611,1474394,7561132,-249174,-1092103,-126136,3644534,-687864,-7754874,2961479,7371738,5614130,-7518108,-4375729,5238142,-2711992,-123105,5412243,-516556,-7341922,4774514,-6884254,-1846072,430059,-5269139,739544,1660187,3198992,3239321,-1946034,-198394,2266879,-1487909,-3133588,-2389912,-7961501,6077410,-2347335,-7067465,-4951591,-5769012,4583066,7738395,2318739,505663,950660,-2633718,-7191941,4418089,718128,3644318,-2038292,5812224,-1205173,-4660323,-405336,1165342,5556978,286528,5577416,6500567,-623159,-1068199,434596,3140321,6751867,7912748,2276129,-5278024,-7302579,-633142,-7268063,5479083,1461304,-1793285,1362980,7437598,6659857,2252028,-4972,2758578,6116466,-1132050,-5401540,-3964107,-7405266,-4907054,7134722,1491124,1495944,-7864169,8155065,5161612,-7262769,4854460,-1377082,-6022381,592666,-4178741,-2533986,6140005,-5596981,-4362528,-2648370,7097509,-6820245,-7069876,6506725,-1318933,6523666,8226407,-7432106,-7906073,-780535,3880981,-1775958,3715026,86486,4662269,-497933,-4169351,-1679048,-8313177,556796,-1579518,5056399,482867,507509,-4467873,-3379135,-937131,5963776,5806592,3448545,261781,6791382,-8343651,6344690,-5972585,-8007299,-2156901,1843920,-7099334,-1354705,30271,-4382813,377677,6874655,-7215343,-4165351,6228412,-8042655,-1430457,6065021,-5113267,3580432,7951216,-2462930,3210068,3160881,-2195842,5756484,6151217,1367352,7384363,8259148,-5572562,4796402,-2713970,862379,2100733,-3781510,363912,136817,4979987,7278409,2922792,6270222,-376347,3647788,4466460,8239217,8382708,3624677,6041588,-1863397,2685647,7263752,3329443,272316,-259176,7643666,-6244894,4028364,-712782,-3079963,-97774,3829077,-5838865,171632,137841,7578174,-2197326,4133187,-3495544,1656136,-354404,2755756,8195879,-8254838,-8021494,-7609560,-5254845,-3355721,3366773,7135017,-6562044,-3208700,8148857,1161950,10888,6348682,2470021,-2840586,-7461765,-795835,7296109,-6595308,-6090860,4645266,4757824,-3897601,5805689,5958847,4092584,8274940,5068953,-2567788,1198087,5112657,2305514,3138829,2505854,-1555488,-2113680,7934493,235267,-3753296,7444655,1348420,5479239,1256501,-3667455,2226065,-1609413,6796639,-7022847,3126117,-6984106,-519762,-646239,6400370,-3955574,-409745,-5332820,5866131,-1396559,-2033880,6528280,-1681841,-3401191,5788925,2484910,2856293,4808317,228909,-416768,-7639280,5921755,6885561,-5867048,-2785222,-2480764,-5721475,4042493,1655807,-2942543,6414700,-2529896,3046036,3420880,8159751,-7751179,-54174,-1974315,-4084919,-8183904,7490568,-2766402,-5121870,-5857886,5284102,-4424193,-446877,-6201167,-8023091,-7980265,-7797677,-5210767,7932399,-819255,5754857,4023025,3563474,-7980586,-6668290,6158352,-804090,-760025,-4755228,-7014534,4220709,2790200,-5166457,-4965302,2152712,-207504,8082834,-1283515,2053614,-7280873,-8001945,-4844144,-6050396,-4296088,1588383,5198631,5504627,-7768188,-3774835,2253168,5789109,3909119,3754286,-88664,-3451397,-2791235,5504311,679777,1419943,1049480,3927703,867914,5144175,-6489390,-1548753,-1829769,8223767,2662294,-7622350,-1204679,3128715,-4487472,-468873,6695046,-5929512,191891,-1401834,-7847769,2678020,8367821,3181197,2520565,3353307,1809382,-466641,2732845,-360625,-5873535,2750752,-2495105,-7452454,7718151,2126972,-3850966,7197147,-2284962,-5175176,3306645,1477619,4424630,-6511743,1509220,-6524524,1097978,7707865,-6816392,7148307,6286595,-451968,-5714981,-7227767,5047688,1961655,2229567,697491,2874166,2112902,-4631524,-6718165,4488993,-1896627,4576173,4307414,-1792108,2831854,6877351,-1095279,-1627683,-3986664,-7835069,-2531335,-59926,4213076,-4035923,-5824204,7090263,-4954000,-7487276,-6234778,2918,4841417,-3851158,-2844415,2993676,-5229257,-4689230,-8271679,-7418734,-7154097,4935325,1016345,598913,-8039552,6489632,-2513580,6670632,1296077,-1252005,-4987105,4017622,-5585639,5388724,-6462593,-1807366,-1775817,6795919,-5216614,301049,-4711440,-5477586,-2758350,-6538664,-4319555,-3912026,-8282872,2477420,-649733,-485621,4877743,-3530760,-5641532,7202544,5636601,-3911894,-4066374,2368781,4536623,3346510,-2351665,5904140,898252,2003370]++ seg :: Acc (Segments Int32)+ seg = use $ fromList (Z :. 27) [33,17,21,30,37,11,34,8,6,35,25,32,28,29,30,27,18,10,19,14,33,31,6,24,23,27,26]+++ref10 :: (Vector Int64, Vector Int64)+ref10 = (ps, rs)+ where+ ps = fromList (Z :. 569) [0,-66818,0,251795,699710,802697,480274,853290,752860,1138919,862260,939763,894697,1099711,1557688,1971825,2058686,2243003,2277978,1888289,1704690,1494021,1883285,2376628,2742325,2967694,0,-332732,-837801,-1190081,-1155758,-864618,-1011546,-1506561,-1455653,-1461081,-1468925,0,-17398,-499085,-748440,-252548,-711966,-497932,-195879,220930,-206548,-255380,-568898,-757326,-427050,-393296,-111710,-602208,-649037,-444294,-18070,-10846,275102,386815,-81884,-314019,-787111,-444473,-623219,-786284,-1224148,-948653,0,83288,141789,-376897,-801010,-1229392,-1437542,-1343774,-1252581,-1407581,-1230786,-1080778,-887420,-1407282,-1684415,-1586879,-1817380,-1644980,-2018396,-1578302,-2078661,-2403312,0,-348073,-61579,-410265,-889716,-590911,-305754,14324,90455,238709,0,-514467,-18980,-246615,-269435,47130,486843,133713,-235497,231266,18100,49540,309653,128285,358799,71567,-82550,-153304,220347,510910,469921,274902,621062,1078829,872577,737543,784276,1024881,903770,582412,557177,0,-79157,156274,608119,229318,288224,717375,977407,469445,324953,457611,641493,880116,360122,700100,821083,939413,1353849,1301020,1159702,1066315,1313991,1759726,0,64229,71186,-445530,-895389,-788935,-1273825,-1752166,-1318004,-925613,-1174396,-723669,-699056,-956311,-472962,-854802,-631555,-568744,-121748,262164,315678,286142,516418,774854,802149,0,242513,-78471,-447748,-208334,80367,353728,395938,349793,843076,665615,217631,152661,369532,391974,528953,54121,-213080,0,-379824,-596797,-930399,-1233561,0,49961,470555,-8966,-421041,-358131,-522150,-438106,-257326,-388186,-349745,-150297,-321019,196862,-303784,-753841,-673582,0,-214043,-451282,-817091,-960814,-680287,-213731,-513040,-214838,188079,567961,716777,411753,456206,168684,5973,275529,253742,173181,179486,571390,660839,1011720,1004275,736990,0,486399,121062,152334,-63078,263827,149145,660440,499071,805451,578235,959506,1402219,1313257,873908,1270627,845536,422653,125870,-131875,40533,-20688,217854,732938,722699,1196205,735699,266278,419403,821116,925710,0,370129,684573,735026,1258789,911909,583991,400539,247903,534707,541244,391465,0,-59023,-409311,-21312,-433939,-148438,-668644,-386892,-631301,-1038008,-574634,-1058043,0,265219,578285,758977,1231768,805524,487154,300489,389030,-120499,311989,-44810,-112116,-251032,-86539,-435986,-866365,-443801,-14900,309866,444678,-26681,324055,68761,544046,622794,0,74157,-317149,23825,481577,562395,875574,840706,1160287,1619936,1498032,1475610,1164467,949769,1280500,1015376,1063969,905518,615928,0,-87002,-594303,-548189,-192022,-133977,74580,549869,205817,162377,410494,90138,597008,664846,830524,377126,735741,778767,353906,382320,613333,979868,770860,604628,887587,1280914,956452,1320009,1428155,1055994,0,168619,-88538,-351560,109200,531151,46281,-461996,-305458,-431157,-351578,-445572,-193773,222034,454655,416443,229141,16838,482113,458503,-36529,37212,336796,-124876,-247953,-568505,-351627,0,174429,326398,0,479713,860680,1036211,514896,729323,669741,578086,375592,810904,1314492,0,516330,592423,921726,929593,1045808,747506,626620,597816,458291,216687,699340,216117,-132060,-312354,-2136,-520935,-569805,-970137,-1267749,-880767,-1038096,0,118085,-218891,-76411,-133008,70809,-229674,61482,463032,157647,74287,65534,406373,241452,697069,1054306,708766,949749,1455240,1211918,1300078,1171212,1214004,1127868,1159521,0,183087,153680,15177,-116973,21188,233956,-64713,-354746,-877965,-1342227,-1529732,-1008952,-1394152,-1765713,-1975211,0,-481619,-382778,78075,191489,507177,333103,613687,506194,597264,96635,-69800,-337325,-620875,-885881,-521276,-776467,-401089,-240095,-174539,-655262,-662689,-309418,-543461,-287504,-502363,-425626,-135632,-634977,-125686,0,-406528,-758206,-879047,-365289,-104346,-472971,-535915,-48760,328278,251722,321627,-127699,-192224,248204,-32639,-104266,-265995,207560,-284650,-231682,0,-61639,-279193,-294943,-445218,-331468,-365358,141884,-55123,-528518,-56843,-482234,-590206,-389883,-77870,42781,466913,753792,0,154707,337717,186947,-17501,-222052,-205272,247871,705,307861,459828,791604,945119,1286260,934495,425248,514350,276711,257592,748516,730039,673631]+ rs = fromList (Z :. 30) [215752,2738275,-1800525,-1372798,-2118027,296082,207526,2063381,312429,-190965,-907082,-914710,442481,1282782,716990,-1224980,1060351,109154,849522,130337,247166,1435364,-1200037,1292937,-2157594,-649389,-498810,970579,243783,0]++test10 :: Acc (Vector Int64, Vector Int64)+test10 = A.scanl'Seg (+) 0 xs seg+ where+ xs :: Acc (Vector Int64)+ xs = use $ fromList (Z :. 569) [-66818,282570,251795,447915,102987,-322423,373016,-100430,386059,-276659,77503,-45066,205014,457977,414137,86861,184317,34975,-389689,-183599,-210669,389264,493343,365697,225369,-229419,-332732,-505069,-352280,34323,291140,-146928,-495015,50908,-5428,-7844,-331600,-17398,-481687,-249355,495892,-459418,214034,302053,416809,-427478,-48832,-313518,-188428,330276,33754,281586,-490498,-46829,204743,426224,7224,285948,111713,-468699,-232135,-473092,342638,-178746,-163065,-437864,275495,-424145,83288,58501,-518686,-424113,-428382,-208150,93768,91193,-155000,176795,150008,193358,-519862,-277133,97536,-230501,172400,-373416,440094,-500359,-324651,285285,-348073,286494,-348686,-479451,298805,285157,320078,76131,148254,57373,-514467,495487,-227635,-22820,316565,439713,-353130,-369210,466763,-213166,31440,260113,-181368,230514,-287232,-154117,-70754,373651,290563,-40989,-195019,346160,457767,-206252,-135034,46733,240605,-121111,-321358,-25235,-349651,-79157,235431,451845,-378801,58906,429151,260032,-507962,-144492,132658,183882,238623,-519994,339978,120983,118330,414436,-52829,-141318,-93387,247676,445735,303655,64229,6957,-516716,-449859,106454,-484890,-478341,434162,392391,-248783,450727,24613,-257255,483349,-381840,223247,62811,446996,383912,53514,-29536,230276,258436,27295,-489720,242513,-320984,-369277,239414,288701,273361,42210,-46145,493283,-177461,-447984,-64970,216871,22442,136979,-474832,-267201,22115,-379824,-216973,-333602,-303162,326479,49961,420594,-479521,-412075,62910,-164019,84044,180780,-130860,38441,199448,-170722,517881,-500646,-450057,80259,-241128,-214043,-237239,-365809,-143723,280527,466556,-299309,298202,402917,379882,148816,-305024,44453,-287522,-162711,269556,-21787,-80561,6305,391904,89449,350881,-7445,-267285,-294509,486399,-365337,31272,-215412,326905,-114682,511295,-161369,306380,-227216,381271,442713,-88962,-439349,396719,-425091,-422883,-296783,-257745,172408,-61221,238542,515084,-10239,473506,-460506,-469421,153125,401713,104594,357072,370129,314444,50453,523763,-346880,-327918,-183452,-152636,286804,6537,-149779,325525,-59023,-350288,387999,-412627,285501,-520206,281752,-244409,-406707,463374,-483409,-166937,265219,313066,180692,472791,-426244,-318370,-186665,88541,-509529,432488,-356799,-67306,-138916,164493,-349447,-430379,422564,428901,324766,134812,-471359,350736,-255294,475285,78748,437557,74157,-391306,340974,457752,80818,313179,-34868,319581,459649,-121904,-22422,-311143,-214698,330731,-265124,48593,-158451,-289590,-506774,-87002,-507301,46114,356167,58045,208557,475289,-344052,-43440,248117,-320356,506870,67838,165678,-453398,358615,43026,-424861,28414,231013,366535,-209008,-166232,282959,393327,-324462,363557,108146,-372161,-206472,168619,-257157,-263022,460760,421951,-484870,-508277,156538,-125699,79579,-93994,251799,415807,232621,-38212,-187302,-212303,465275,-23610,-495032,73741,299584,-461672,-123077,-320552,216878,481964,174429,151969,-79232,479713,380967,175531,-521315,214427,-59582,-91655,-202494,435312,503588,120872,516330,76093,329303,7867,116215,-298302,-120886,-28804,-139525,-241604,482653,-483223,-348177,-180294,310218,-518799,-48870,-400332,-297612,386982,-157329,-161941,118085,-336976,142480,-56597,203817,-300483,291156,401550,-305385,-83360,-8753,340839,-164921,455617,357237,-345540,240983,505491,-243322,88160,-128866,42792,-86136,31653,133416,183087,-29407,-138503,-132150,138161,212768,-298669,-290033,-523219,-464262,-187505,520780,-385200,-371561,-209498,-182383,-481619,98841,460853,113414,315688,-174074,280584,-107493,91070,-500629,-166435,-267525,-283550,-265006,364605,-255191,375378,160994,65556,-480723,-7427,353271,-234043,255957,-214859,76737,289994,-499345,509291,-523703,-406528,-351678,-120841,513758,260943,-368625,-62944,487155,377038,-76556,69905,-449326,-64525,440428,-280843,-71627,-161729,473555,-492210,52968,-267128,-61639,-217554,-15750,-150275,113750,-33890,507242,-197007,-473395,471675,-425391,-107972,200323,312013,120651,424132,286879,216787,154707,183010,-150770,-204448,-204551,16780,453143,-247166,307156,151967,331776,153515,341141,-351765,-509247,89102,-237639,-19119,490924,-18477,-56408,-429848]++ seg :: Acc (Segments Int32)+ seg = use $ fromList (Z :. 30) [2,24,11,31,22,10,31,23,25,18,5,17,25,31,12,12,26,19,30,27,3,11,22,25,16,30,21,18,22,0]+++ref11 :: (Vector Int64, Vector Int64)+ref11 = (ps, rs)+ where+ ps = fromList (Z :. 750) [300202,-3934108,-7293301,118329,0,-9620841,-6707242,194332,33523,-2362285,4356093,8130701,7381954,6320569,13020915,19242062,20405079,12162531,9328566,2344030,6249515,1195987,714789,-3387204,-1156156,-4385845,-1505374,3054547,10517703,14551257,7158564,5521908,4076566,9423606,9791035,15883498,13341839,5338906,7755970,0,8449937,14272421,7658262,4242448,106786,-1538494,6329826,-1969224,-3562793,-5238381,-11479790,-19204769,-23383409,-15529258,-9197176,-3153045,2044602,7324780,0,-4389691,3327745,6304656,5225571,10231407,12003136,8669740,11482531,16463383,14927577,18131497,21726278,19113902,24183865,18037487,12252168,20461643,15647208,19992282,16169909,8901867,3534110,5568184,6826591,1884406,-4706766,-6388012,94426,-8160379,-4083019,-10378695,-15486623,-7206171,-695686,4860798,0,10857061,3955448,-1061568,6951301,-1071594,0,-13446920,-12173160,-8243921,-11230304,-8734571,-16936920,-16750142,-9949134,-10991997,-3350146,-8268859,0,-14302173,-16276308,-11142092,-13546302,-15960168,-15744133,-20140592,-27616401,-23636225,-24849690,-18571631,-14996447,-8469842,-2690306,-1586836,1141087,-1808235,-5396094,-6508579,0,33601076,40110614,40470091,39158954,31965378,23662135,26792692,22837593,15375475,7595486,5806140,0,5557752,6250667,3210301,4771732,10208018,9244194,1488326,-6840876,-5503541,-6377388,1921887,8701362,436706,5155610,4702952,9854658,12359455,11367064,17274738,12815997,16178778,13979944,14676004,11309648,10910551,8856116,1692110,6290491,9917167,13883564,6354535,2315726,2456500,-3357012,-2245597,5286714,0,27838965,23929687,16271002,14334800,12447318,8856790,5550657,2872825,5216149,1984481,6519741,-380267,-2676926,5698169,-2416327,5822052,12780665,13247384,20633185,15313341,14149220,12991370,11193529,10073298,4257177,8166119,6158966,7167487,8065374,4626067,5253098,221789,0,-22666015,-19830708,-26450648,-22323702,-14812315,-12769333,-8380998,-124066,-3429801,1735354,8675238,5922004,3773612,4863814,8973510,8243987,8052797,-131886,-1218987,944425,-5693971,-10284458,-3771161,-6911370,1215128,6417910,7616391,10888675,12684613,15718607,12760177,4418538,0,-19124759,-16690729,-14466748,-7312246,-8934031,-14128478,-6391701,-5586522,-3281158,-6126513,-12086460,-11947805,-8977838,-4679499,-7044384,-3585849,2517797,4187257,1143610,5599470,12556,468724,0,-38086726,-38209271,-34895951,-29641991,-33756478,-34159294,-29272266,-24192985,-18907102,-10553406,-8755717,-5576171,1187225,5646949,0,-26021214,-24968854,-16606604,-23345266,-26556968,-27031671,-32169558,-29741461,-22232488,-21561792,-17815214,-9755318,-5676615,-1531928,0,-7082738,-2096546,69095,1247646,-2028294,278676,1852334,4571352,-3233037,-3429729,-6398514,-9422414,-2191733,2284645,-864442,-254370,1472191,0,3756457,650062,-4943727,-6384744,-850321,-5359348,-645558,-2506083,-3114762,-366178,-6339582,-4052845,0,65534,-7573163,-12029806,-18419840,-13680249,-6009158,-7346388,0,-39890208,-43517086,-35311112,-37123834,-36260718,-33030305,-34707046,-39911126,-35939603,-30275083,-36082502,-32249760,-27147583,-23233819,-25620860,-25554234,-22141128,-25506989,-22929605,-15879316,-24134083,-16570735,-9997301,-4200711,-2668164,1487850,3578750,-1305145,1080697,-6119380,-6192140,-4780925,-6340276,0,-26181571,-18058810,-10653064,-6588755,-9696374,-5833999,-9675119,-10632518,-11082908,-10756776,-10864096,-13002610,-7721565,-9182352,-6394042,-2752356,-9605533,-4366062,-8172748,0,-16273637,-12506792,-8904008,-8280500,-10173545,-6329127,-3926250,-8763799,-8461557,-5251290,1921403,9241406,2219290,2078592,1370230,2365533,0,-36174378,-34747120,-36960421,-38916018,-33713341,-27862565,-19493548,-13614863,-18329350,-13726747,-18636836,-21433533,-22047575,-17828457,-18477083,-18912228,-16845393,-14834848,-10961203,-4503372,2709924,-5670489,0,8244107,7371898,1062426,-5349784,-1530037,-4243202,1657954,0,58761276,64777759,62710415,55540126,63734805,67828569,66998117,65406433,58629880,51628041,49304089,52468514,44515601,37206921,40107031,36553913,32964413,28315600,22177065,24792502,21656741,20411694,28296854,21119658,16847130,10142928,6275059,10233804,7892690,6605617,812948,-4276554,421536,-282529,0,10264903,3489193,0,47453090,48772541,54603425,48519299,46216432,50441440,48516811,45678872,39908077,32646114,28833886,23180980,15877983,14237392,6679178,13066338,6271764,8380814,1833690,-4162730,-1918105,5114142,0,-25911951,-28491981,-26929631,-23869603,-20710623,-28958111,-23436032,-16629161,-16368397,-15117344,-13086145,-7862262,-3970195,-1325162,69199,2584855,-390927,-753348,-7662405,0,44746008,36954219,37811396,37926769,38442648,38288713,29989290,27015712,25484790,22372796,17537520,16774727,8552613,13943585,17093179,10142287,5721997,10994509,9787684,9382836,9256805,16015565,8545047,10254145,12213051,12551830,8902381,12267197,4492349,3729047,8190040,1659416,-5162630,0,-39096550,-32628259,-39002248,-31910093,-31760558,-26048323,-23199546,-18154141,-15577194,-20921838,-13620329,-5287668,-10372255,-7345019,-13225631,-8543390,-10782084,-10995673,-6251002,1830175,-5731084,-3491981,-9221778,-10184068,-15385965,-16015517,-7715802,-1442733,6174121,2371134,-1808823,5881932,0,-10833715,-9130099,-7149409,-89049,-6363174,-3030367,884814,0,4329246,-712705,-2477029,-4838047,-6361858,-758166,6976202,50092,-5046096,2007750,-5232448,-1895517,-5590470,-4630085,-5205817,-5003092,1356974,0,-30933008,-25815115,-26412272,-27208148,-28291145,-30761072,-24801972,-20136889,-20802009,-17119600,-9796191,-5951994,-3024348,-6817180,-10261727,-12018141,-6423630,-7809004,-12362519,-15505819,-17738534,-12482571,-16777356,-8514106,-10646693,-13579392,-17091140,-10886710,-8783584,-3787667,0,-10399417,-9783351,-11140112,-10286438,-18016415,-24699666,-29534073,-30173237,-22982316,-16232479,-20550054,-17508444,-20456501,-15338123,-16089893,-19682049,-17509739,-17545850,-20482200,-16092902,-10112370,-9857530,-7086012,-5758886,-13713007,-18431943,-12663085,-10395688,-9242682,-3627676,-4124458,324696,0,-1239916,-1099231,0,-52728448,-49740852,-53462736,-48128709,-51184308,-50512793,-51205907,-44973519,-45435372,-48750664,-42361329,-35515045,-32329339,-31125840,-23377216,-15586974,-16058124,-22592883,-17078262,-10577077,-10527747,-13404618,-8157252,-2726103,-4759099,-9619550,-11889364,-13992613,-14997209,-7958218,0,11463857,11389338,6395972,4491458,0,9908832,4627071,2514558,5454929,3049640,-3347579,-4585603,-8139773,-4727321,-5405095,-5516549,-1072707,2091727,10164364,8109479,13221076,11835227,5915534,7266805,10176116,7976055,487672,-1039582,4809829,-3150159,0,-5576241,2649236,-4909388,2973172,0]+ rs = fromList (Z :. 37) [1828591,-5649957,12711572,-882080,8724897,-5592479,-16715596,30682536,8434130,20924927,-21828584,-20372532,-33000591,-25847170,-2348236,7144729,-7521765,-37600334,-21413350,-17584160,-30265145,2716955,54962523,15814454,52796336,-29414196,44937491,-41772916,-13871531,5751378,-32142219,-11167891,-5978481,-54925970,6000925,17510325,-13863452]++test11 :: Acc (Vector Int64, Vector Int64)+test11 = A.scanr'Seg (+) 0 xs seg+ where+ xs :: Acc (Vector Int64)+ xs = use $ fromList (Z :. 750) [1528389,4234310,3359193,-7411630,118329,3970884,-2913599,-6901574,160809,2395808,-6718378,-3774608,748747,1061385,-6700346,-6221147,-1163017,8242548,2833965,6984536,-3905485,5053528,481198,4101993,-2231048,3229689,-2880471,-4559921,-7463156,-4033554,7392693,1636656,1445342,-5347040,-367429,-6092463,2541659,8002933,-2417064,7755970,4261635,-5822484,6614159,3415814,4135662,1645280,-7868320,8299050,1593569,1675588,6241409,7724979,4178640,-7854151,-6332082,-6044131,-5197647,-5280178,7324780,3507611,-7717436,-2976911,1079085,-5005836,-1771729,3333396,-2812791,-4980852,1535806,-3203920,-3594781,2612376,-5069963,6146378,5785319,-8209475,4814435,-4345074,3822373,7268042,5367757,-2034074,-1258407,4942185,6591172,1681246,-6482438,8254805,-4077360,6295676,5107928,-8280452,-6510485,-5556484,4860798,-2132164,6901613,5017016,-8012869,8022895,-1071594,7854441,-1273760,-3929239,2986383,-2495733,8202349,-186778,-6801008,1042863,-7641851,4918713,-8268859,-2413423,1974135,-5134216,2404210,2413866,-216035,4396459,7475809,-3980176,1213465,-6278059,-3575184,-6526605,-5779536,-1103470,-2727923,2949322,3587859,1112485,-6508579,-2918540,-6509538,-359477,1311137,7193576,8303243,-3130557,3955099,7462118,7779989,1789346,5806140,2876378,-692915,3040366,-1561431,-5436286,963824,7755868,8329202,-1337335,873847,-8299275,-6779475,8264656,-4718904,452658,-5151706,-2504797,992391,-5907674,4458741,-3362781,2198834,-696060,3366356,399097,2054435,7164006,-4598381,-3626676,-3966397,7529029,4038809,-140774,5813512,-1111415,-7532311,5286714,-6914038,3909278,7658685,1936202,1887482,3590528,3306133,2677832,-2343324,3231668,-4535260,6900008,2296659,-8375095,8114496,-8238379,-6958613,-466719,-7385801,5319844,1164121,1157850,1797841,1120231,5816121,-3908942,2007153,-1008521,-897887,3439307,-627031,5031309,221789,837431,-2835307,6619940,-4126946,-7511387,-2042982,-4388335,-8256932,3305735,-5165155,-6939884,2753234,2148392,-1090202,-4109696,729523,191190,8184683,1087101,-2163412,6638396,4590487,-6513297,3140209,-8126498,-5202782,-1198481,-3272284,-1795938,-3033994,2958430,8341639,4418538,-1247773,-2434030,-2223981,-7154502,1621785,5194447,-7736777,-805179,-2305364,2845355,5959947,-138655,-2969967,-4298339,2364885,-3458535,-6103646,-1669460,3043647,-4455860,5586914,-456168,468724,5086135,122545,-3313320,-5253960,4114487,402816,-4887028,-5079281,-5285883,-8353696,-1797689,-3179546,-6763396,-4459724,5646949,174044,-1052360,-8362250,6738662,3211702,474703,5137887,-2428097,-7508973,-670696,-3746578,-8059896,-4078703,-4144687,-1531928,4734502,-4986192,-2165641,-1178551,3275940,-2306970,-1573658,-2719018,7804389,196692,2968785,3023900,-7230681,-4476378,3149087,-610072,-1726561,1472191,3388272,3106395,5593789,1441017,-5534423,4509027,-4713790,1860525,608679,-2748584,5973404,-2286737,-4052845,-7587299,7638697,4456643,6390034,-4739591,-7671091,1337230,-7346388,2289874,3626878,-8205974,1812722,-863116,-3230413,1676741,5204080,-3971523,-5664520,5807419,-3832742,-5102177,-3913764,2387041,-66626,-3413106,3365861,-2577384,-7050289,8254767,-7563348,-6573434,-5796590,-1532547,-4156014,-2090900,4883895,-2385842,7200077,72760,-1411215,1559351,-6340276,4768221,-8122761,-7405746,-4064309,3107619,-3862375,3841120,957399,450390,-326132,107320,2138514,-5281045,1460787,-2788310,-3641686,6853177,-5239471,3806686,-8172748,-1310523,-3766845,-3602784,-623508,1893045,-3844418,-2402877,4837549,-302242,-3210267,-7172693,-7320003,7022116,140698,708362,-995303,2365533,5909233,-1427258,2213301,1955597,-5202677,-5850776,-8369017,-5878685,4714487,-4602603,4910089,2796697,614042,-4219118,648626,435145,-2066835,-2010545,-3873645,-6457831,-7213296,8380413,-5670489,-5527152,872209,6309472,6412210,-3819747,2713165,-5901156,1657954,-3798753,-6016483,2067344,7170289,-8194679,-4093764,830452,1591684,6776553,7001839,2323952,-3164425,7952913,7308680,-2900110,3553118,3589500,4648813,6138535,-2615437,3135761,1245047,-7885160,7177196,4272528,6704202,3867869,-3958745,2341114,1287073,5792669,5089502,-4698090,704065,-282529,5549551,6775710,3489193,5343246,-1319451,-5830884,6084126,2302867,-4225008,1924629,2837939,5770795,7261963,3812228,5652906,7302997,1640591,7558214,-6387160,6794574,-2109050,6547124,5996420,-2244625,-7032247,5114142,-3502245,2580030,-1562350,-3060028,-3158980,8247488,-5522079,-6806871,-260764,-1251053,-2031199,-5223883,-3892067,-2645033,-1394361,-2515656,2975782,362421,6909057,-7662405,191483,7791789,-857177,-115373,-515879,153935,8299423,2973578,1530922,3111994,4835276,762793,8222114,-5390972,-3149594,6950892,4420290,-5272512,1206825,404848,126031,-6758760,7470518,-1709098,-1958906,-338779,3649449,-3364816,7774848,763302,-4460993,6530624,6822046,-5162630,-2676366,-6468291,6373989,-7092155,-149535,-5712235,-2848777,-5045405,-2576947,5344644,-7301509,-8332661,5084587,-3027236,5880612,-4682241,2238694,213589,-4744671,-8081177,7561259,-2239103,5729797,962290,5201897,629552,-8299715,-6273069,-7616854,3802987,4179957,-7690755,5881932,-3037816,-1703616,-1980690,-7060360,6274125,-3332807,-3915181,884814,1422132,5041951,1764324,2361018,1523811,-5603692,-7734368,6926110,5096188,-7053846,7240198,-3336931,3694953,-960385,575732,-202725,-6360066,1356974,-1209211,-5117893,597157,795876,1082997,2469927,-5959100,-4665083,665120,-3682409,-7323409,-3844197,-2927646,3792832,3444547,1756414,-5594511,1385374,4553515,3143300,2232715,-5255963,4294785,-8263250,2132587,2932699,3511748,-6204430,-2103126,-4995917,-3787667,-768474,-616066,1356761,-853674,7729977,6683251,4834407,639164,-7190921,-6749837,4317575,-3041610,2948057,-5118378,751770,3592156,-2172310,36111,2936350,-4389298,-5980532,-254840,-2771518,-1327126,7954121,4718936,-5768858,-2267397,-1153006,-5615006,496782,-4449154,324696,-4738565,-140685,-1099231,-2197522,-2987596,3721884,-5334027,3055599,-671515,693114,-6232388,461853,3315292,-6389335,-6846284,-3185706,-1203499,-7748624,-7790242,471150,6534759,-5514621,-6501185,-49330,2876871,-5247366,-5431149,2032996,4860451,2269814,2103249,1004596,-7038991,-7958218,-5462932,74519,4993366,1904514,4491458,7601493,5281761,2112513,-2940371,2405289,6397219,1238024,3554170,-3412452,677774,111454,-4443842,-3164434,-8072637,2054885,-5111597,1385849,5919693,-1351271,-2909311,2200061,7488383,1527254,-5849411,7959988,-3150159,-8287211,-8225477,7558624,-7882560,2973172]++ seg :: Acc (Segments Int32)+ seg = use $ fromList (Z :. 37) [5,35,19,36,6,12,20,12,37,33,33,23,15,15,18,13,8,34,20,17,23,8,35,3,23,20,34,33,8,18,31,33,3,31,5,26,5]+
+ src/Data/Array/Accelerate/Test/NoFib/Issues/Issue123.hs view
@@ -0,0 +1,39 @@+{-# LANGUAGE RankNTypes #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Issues.Issue123+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- https://github.com/AccelerateHS/accelerate/issues/123+--++module Data.Array.Accelerate.Test.NoFib.Issues.Issue123 (++ test_issue123++) where++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Test.NoFib.Base++import Test.Tasty+import Test.Tasty.HUnit+++test_issue123 :: RunN -> TestTree+test_issue123 runN =+ testCase "123" $ ref1 @=? runN (test1 n)+ where+ n = 100+ ref1 = fromList Z [n]+++test1 :: Int -> Acc (Scalar Int)+test1 n+ = fold (+) 0+ $ fill (constant (Z:.n)) 1+
+ src/Data/Array/Accelerate/Test/NoFib/Issues/Issue137.hs view
@@ -0,0 +1,56 @@+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeOperators #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Issues.Issue137+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- https://github.com/AccelerateHS/accelerate/issues/137+--++module Data.Array.Accelerate.Test.NoFib.Issues.Issue137 (++ test_issue137++) where++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Test.NoFib.Base++import Test.Tasty+import Test.Tasty.HUnit+++test_issue137 :: RunN -> TestTree+test_issue137 runN =+ testCase "137" $ ref1 @=? runN test1+++ref1 :: Vector (Int,Int)+ref1 = fromList (Z:.384) [(1,2),(0,1),(2,3),(0,1),(3,4),(0,1),(4,5),(0,1),(5,5),(0,1),(4,5),(0,1),(3,4),(0,1),(2,3),(0,1),(1,2),(1,2),(0,1),(2,3),(0,1),(3,4),(0,1),(4,5),(0,1),(5,5),(0,1),(4,5),(0,1),(3,4),(0,1),(2,3),(0,1),(1,2),(1,2),(0,1),(2,3),(0,1),(3,4),(0,1),(4,5),(0,1),(5,5),(0,1),(4,5),(0,1),(3,4),(0,1),(2,3),(0,1),(1,2),(1,2),(0,1),(2,3),(0,1),(3,4),(0,1),(4,5),(0,1),(5,5),(0,1),(4,5),(0,1),(3,4),(0,1),(2,3),(0,1),(1,2),(1,2),(0,1),(2,3),(0,1),(3,4),(0,1),(4,5),(0,1),(5,5),(0,1),(4,5),(0,1),(3,4),(0,1),(2,3),(0,1),(1,2),(1,2),(0,1),(2,3),(0,1),(3,4),(0,1),(4,5),(0,1),(5,5),(0,1),(4,5),(0,1),(3,4),(0,1),(2,3),(0,1),(1,2),(1,2),(0,1),(2,3),(0,1),(3,4),(0,1),(4,5),(0,1),(5,5),(0,1),(4,5),(0,1),(3,4),(0,1),(2,3),(0,1),(1,2),(1,2),(0,1),(2,3),(0,1),(3,4),(0,1),(4,5),(0,1),(5,5),(0,1),(4,5),(0,1),(3,4),(0,1),(2,3),(0,1),(1,2),(1,2),(0,1),(2,3),(0,1),(3,4),(0,1),(4,5),(0,1),(5,5),(0,1),(4,5),(0,1),(3,4),(0,1),(2,3),(0,1),(1,2),(1,2),(0,1),(2,3),(0,1),(3,4),(0,1),(4,5),(0,1),(5,5),(0,1),(4,5),(0,1),(3,4),(0,1),(2,3),(0,1),(1,2),(1,2),(0,1),(2,3),(0,1),(3,4),(0,1),(4,5),(0,1),(5,5),(0,1),(4,5),(0,1),(3,4),(0,1),(2,3),(0,1),(1,2),(1,2),(0,1),(2,3),(0,1),(3,4),(0,1),(4,5),(0,1),(5,5),(0,1),(4,5),(0,1),(3,4),(0,1),(2,3),(0,1),(1,2),(1,2),(0,1),(2,3),(0,1),(3,4),(0,1),(4,5),(0,1),(5,5),(0,1),(4,5),(0,1),(3,4),(0,1),(2,3),(0,1),(1,2),(1,2),(0,1),(2,3),(0,1),(3,4),(0,1),(4,5),(0,1),(5,5),(0,1),(4,5),(0,1),(3,4),(0,1),(2,3),(0,1),(1,2),(1,2),(0,1),(2,3),(0,1),(3,4),(0,1),(4,5),(0,1),(5,5),(0,1),(4,5),(0,1),(3,4),(0,1),(2,3),(0,1),(1,2),(1,2),(0,1),(2,3),(0,1),(3,4),(0,1),(4,5),(0,1),(5,5),(0,1),(4,5),(0,1),(3,4),(0,1),(2,3),(0,1),(1,2),(1,2),(0,1),(2,3),(0,1),(3,4),(0,1),(4,5),(0,1),(5,5),(0,1),(4,5),(0,1),(3,4),(0,1),(2,3),(0,1),(1,2),(1,2),(0,1),(2,3),(0,1),(3,4),(0,1),(4,5),(0,1),(5,5),(0,1),(4,5),(0,1),(3,4),(0,1),(2,3),(0,1),(1,2),(1,2),(0,1),(2,3),(0,1),(3,4),(0,1),(4,5),(0,1),(5,5),(0,1),(4,5),(0,1),(3,4),(0,1),(2,3),(0,1),(1,2),(1,2),(0,1),(2,3),(0,1),(3,4),(0,1),(4,5),(0,1),(5,5),(0,1),(4,5),(0,1),(3,4),(0,1),(2,3),(0,1),(1,2),(1,2),(0,1),(2,3),(0,1),(3,4),(0,1),(4,5),(0,1),(5,5),(0,1),(4,5),(0,1),(3,4),(0,1),(2,3),(0,1),(1,2),(1,2),(0,1),(2,3),(0,1),(3,4),(0,1),(4,5),(0,1),(5,5),(0,1),(4,5),(0,1),(3,4),(0,1),(2,3),(0,1),(1,2),(1,2),(0,10000),(10000,10000),(10000,10000),(10000,10000),(10000,10000),(10000,10000),(10000,10000),(10000,10000),(10000,10000)]++test1 :: Acc (Vector (Int,Int))+test1 =+ let+ sz = 3000 :: Int+ interm_arrA = use $ A.fromList (Z :. sz) [ 8 - (a `mod` 17) | a <- [1..sz]]+ msA = use $ A.fromList (Z :. sz) [ (a `div` 8) | a <- [1..sz]]+ inf = 10000 :: Exp Int+ infsA = A.generate (index1 (384 :: Exp Int)) (\_ -> lift (inf,inf))+ inpA = A.map (\v -> lift (abs v,inf) :: Exp (Int,Int)) interm_arrA+ in+ A.permute (\a12 b12 -> let (a1,a2) = unlift a12+ (b1,b2) = unlift b12+ in (a1 A.<= b1)+ ? ( lift (a1, A.min a2 b1)+ , lift (b1, A.min b2 a1)+ ))+ infsA+ (\ix -> Just_ (index1 (msA A.! ix)))+ inpA+
+ src/Data/Array/Accelerate/Test/NoFib/Issues/Issue168.hs view
@@ -0,0 +1,70 @@+{-# LANGUAGE RankNTypes #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Issues.Issue168+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- https://github.com/AccelerateHS/accelerate/issues/168+--++module Data.Array.Accelerate.Test.NoFib.Issues.Issue168 (++ test_issue168++) where++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Test.NoFib.Base++import Test.Tasty+import Test.Tasty.HUnit++import Prelude as P+++test_issue168 :: RunN -> TestTree+test_issue168 runN =+ testGroup "168"+ [ testCase "A" $ ref1 @=? runN (A.fill sh test1)+ , testCase "B" $ ref2 @=? runN (A.fill sh test2)+ , testCase "C" $ ref3 @=? runN (A.fill sh test3)+ ]+ where+ sh = index1 (constant 1) :: Exp DIM1++ -- Test 1+ -- ------+ dqc1 :: (Exp Float, Exp Float)+ dqc1 = (2,1)++ qMult1 :: (Exp Float, Exp Float) -> (Exp Float, Exp Float)+ qMult1 (a1,_) = (3, a1)++ ref1 = fromList (Z:.1) [(3.0,2.0)]++ test1 :: Exp (Float, Float)+ test1 = P.iterate (lift1 qMult1) (lift dqc1) P.!! 1++ ref2 = ref1++ test2 :: Exp (Float, Float)+ test2 = A.iterate (constant 1) (lift1 qMult1) (lift dqc1)++ -- Test 2+ -- ------+ ref3 = fromList (Z:.1) [(1.0,2.0,3.0,4.0,5.0,6.0)]++ dqc3 :: (Exp Float, Exp Float, Exp Float, Exp Float, Exp Float, Exp Float)+ dqc3 = (6,5,4,3,2,1)++ qMult3 :: (Exp Float, Exp Float, Exp Float, Exp Float, Exp Float, Exp Float)+ -> (Exp Float, Exp Float, Exp Float, Exp Float, Exp Float, Exp Float)+ qMult3 (a1,b1,c1,d1,e1,f1) = (f1,e1,d1,c1,b1,a1)++ test3 :: Exp (Float,Float,Float,Float,Float,Float)+ test3 = A.iterate (constant 1) (lift1 qMult3) (lift dqc3)+
+ src/Data/Array/Accelerate/Test/NoFib/Issues/Issue184.hs view
@@ -0,0 +1,67 @@+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE RankNTypes #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Issues.Issue184+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- https://github.com/AccelerateHS/accelerate/issues/184+--++module Data.Array.Accelerate.Test.NoFib.Issues.Issue184 (++ test_issue184++) where++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Test.NoFib.Base++import Test.Tasty+import Test.Tasty.HUnit+++test_issue184 :: RunN -> TestTree+test_issue184 runN =+ testGroup "184"+ [ testCase "A" $ ref1 @=? runN test1+ , testCase "B" $ ref2 @=? runN test2+ , testCase "C" $ ref3 @=? runN test3+ ]+++ref1 :: Vector Int+ref1 = fromList (Z :. 1000) [1,4,9,16,25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]++test1 :: Acc (Vector Int)+test1 =+ let v = use (fromList (Z :. 5) [1,2,3,4,5] :: Vector Int)+ f x = x < 5 ? (let y = v !! x in y*y, 0)+ in generate (index1 1000) (f . unindex1)+++ref2 :: Scalar Bool+ref2 = fromList Z [True]++test2 :: Acc (Scalar Bool)+test2 =+ let x = constant 1 :: Exp Int+ v = use (fromList (Z :. 5) [1,2,3,4,5] :: Vector Int)+ y = (x == 1 || v !! (-1) == 1)+ in unit y+++ref3 :: Scalar Bool+ref3 = fromList Z [False]++test3 :: Acc (Scalar Bool)+test3 =+ let x = constant 1 :: Exp Int+ v = use (fromList (Z :. 5) [1,2,3,4,5] :: Vector Int)+ y = (x /= 1 && v !! (-1) == 1)+ in unit y+
+ src/Data/Array/Accelerate/Test/NoFib/Issues/Issue185.hs view
@@ -0,0 +1,149 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedLists #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeOperators #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Issues.Issue185+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- https://github.com/AccelerateHS/accelerate/issues/185+--++module Data.Array.Accelerate.Test.NoFib.Issues.Issue185 (++ test_issue185++) where++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Test.NoFib.Base++import Test.Tasty+import Test.Tasty.HUnit++import Prelude as P+++test_issue185 :: RunN -> TestTree+test_issue185 runN =+ testGroup "185"+ [ testCase "A" $ ref1 @=? (runN acc1 :: Vector Int)+ , testCase "B" $ ref2 @=? (runN acc2 :: Vector Int)+ , testCase "C" $ ref3 @=? (runN acc3 :: Vector Int)+ , testCase "D" $ ref4 @=? (runN acc4 :: Vector Int)+ , testCase "E" $ ref5 @=? (runN acc5 :: Vector Int)+ , testCase "F" $ ref6 @=? (runN acc6 :: Vector Int)+ ]+++ref1 :: (Elt a, P.Num a) => Vector a+ref1 = fromList (Z :. 9) [0,1,4,9,0,4,0,6,2]++acc1 :: (Elt a, P.Num a) => Acc (Vector a)+acc1 = A.scatter to over xs+ where+ over = use [0, 0, 0, 0, 0, 0, 0, 0, 0]+ xs = use [1, 9, 6, 4, 4, 2, 5]+ to = use [1, 3, 7, 2, 5, 8]+++ref2 :: (Elt a, P.Num a) => Vector a+ref2 = fromList (Z :. 9) [0,1,0,9,0,0,0,6,0]++acc2 :: (Elt a, P.Num a) => Acc (Vector a)+acc2 = A.scatter to over xs+ where+ over = use [0, 0, 0, 0, 0, 0, 0, 0, 0]+ xs = use [1, 9, 6]+ to = use [1, 3, 7, 2, 5, 8]+++ref3 :: (Elt a, P.Num a) => Vector a+ref3 = fromList (Z :. 9) [0,0,0,0,0,4,0,6,2]++acc3 :: (Elt a, P.Num a) => Acc (Vector a)+acc3 = scatterIf to mask p over xs+ where+ over = use [0, 0, 0, 0, 0, 0, 0, 0, 0]+ to = use [1, 3, 7, 2, 5, 8]+ xs = use [1, 9, 6, 4, 4, 2, 5]++ mask :: Acc (Vector Int32)+ mask = use [3, 4, 9, 2, 7, 5]+ p = (A.> 4)+++ref4 :: (Elt a, P.Num a) => Vector a+ref4 = fromList (Z :. 9) [0,0,0,0,0,0,0,6,0]++acc4 :: (Elt a, P.Num a) => Acc (Vector a)+acc4 = scatterIf to mask p over xs+ where+ over = use [0, 0, 0, 0, 0, 0, 0, 0, 0]+ to = use [1, 3, 7, 2, 5, 8]+ xs = use [1, 9, 6]++ mask :: Acc (Vector Int32)+ mask = use [3, 4, 9, 2, 7, 5]+ p = (A.> 4)+++ref5 :: (Elt a, P.Num a) => Vector a+ref5 = fromList (Z :. 6) [9,4,1,6,2,4]++acc5 :: (Elt a, P.Num a) => Acc (Vector a)+acc5 = A.gather from xs+ where+ from = use [1, 3, 7, 2, 5, 3]+ xs = use [1, 9, 6, 4, 4, 2, 0, 1, 2]+++ref6 :: (Elt a, P.Num a) => Vector a+ref6 = fromList (Z :. 6) [6,6,1,6,2,4]++acc6 :: (Elt a, P.Num a) => Acc (Vector a)+acc6 = gatherIf from mask p over xs+ where+ over = use [6, 6, 6, 6, 6, 6]+ from = use [1, 3, 7, 2, 5, 3]+ xs = use [1, 9, 6, 4, 4, 2, 0, 1, 2]++ mask :: Acc (Vector Int32)+ mask = use [3, 4, 9, 2, 7, 5]+ p = (A.> 4)+++gatherIf+ :: (Elt a, Elt b)+ => Acc (Vector Int) -- ^ source indices to gather from+ -> Acc (Vector a) -- ^ mask vector+ -> (Exp a -> Exp Bool) -- ^ predicate function+ -> Acc (Vector b) -- ^ default values+ -> Acc (Vector b) -- ^ source values+ -> Acc (Vector b)+gatherIf from maskV p def input = A.zipWith zf pf gatheredV+ where+ zf ok g = ok ? (unlift g)+ gatheredV = A.zip (gather from input) def+ pf = A.map p maskV++scatterIf+ :: (Elt e, Elt e')+ => Acc (Vector Int) -- ^ destination indices to scatter into+ -> Acc (Vector e) -- ^ mask vector+ -> (Exp e -> Exp Bool) -- ^ predicate function+ -> Acc (Vector e') -- ^ default values+ -> Acc (Vector e') -- ^ source values+ -> Acc (Vector e')+scatterIf to maskV p def input = permute const def pf input'+ where+ pf ix = p (maskV ! ix) ? ( Just_ (index1 (to ! ix)), Nothing_ )+ input' = backpermute (shape to `intersect` shape input) id input+
+ src/Data/Array/Accelerate/Test/NoFib/Issues/Issue187.hs view
@@ -0,0 +1,57 @@+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE RankNTypes #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Issues.Issue187+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- https://github.com/AccelerateHS/accelerate/issues/187+--++module Data.Array.Accelerate.Test.NoFib.Issues.Issue187 (++ test_issue187++) where++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Test.NoFib.Base++import Test.Tasty+import Test.Tasty.HUnit+++test_issue187 :: RunN -> TestTree+test_issue187 runN =+ testGroup "187"+ [ testCase "A" $ ref1 @=? runN test1+ , testCase "B" $ ref2 @=? runN test2+ ]+++ref1 :: Scalar Bool+ref1 = fromList Z [True]++test1 :: Acc (Scalar Bool)+test1 =+ let x = constant 1 :: Exp Int+ v = use (fromList (Z :. 5) [1,2,3,4,5] :: Vector Int)+ y = (x == 1 || v A.!! (-1) == 1)+ in generate (constant Z) (const y)+++ref2 :: Scalar Bool+ref2 = fromList Z [True]++test2 :: Acc (Scalar Bool)+test2 =+ let x = constant 1 :: Exp Int+ x' = unit x+ v = use (fromList (Z :. 5) [1,2,3,4,5] :: Vector Int)+ y = (x == the x' || let y' = v A.!! (-1) in y'*y' == 1)+ in generate (constant Z) (const y)+
+ src/Data/Array/Accelerate/Test/NoFib/Issues/Issue228.hs view
@@ -0,0 +1,68 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Issues.Issue228+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- https://github.com/AccelerateHS/accelerate/issues/228+--++module Data.Array.Accelerate.Test.NoFib.Issues.Issue228 (++ test_issue228++) where++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Test.NoFib.Base++import Test.Tasty+import Test.Tasty.HUnit++import Prelude as P+++test_issue228 :: RunN -> TestTree+test_issue228 runN =+ testGroup "228"+ [ testCase "A" $ ref1 @=? runN (A.fold mergeExp z1 (use test1))+ , testCase "B" $ ref1 @=? runN (A.fold1 mergeExp (use test1))+ ]+++test1 :: Vector (Int,Int)+test1 = fromList (Z:.3) [(1,1),(0,0),(1,1)]++z1 :: Exp (Int,Int)+z1 = constant (1,0)++ref1 :: Scalar (Int,Int)+ref1 = fromList Z [(0,1)]++{--+testAssociativity =+ quickCheck $ \(x, y, z) -> mergeB x (mergeB y z) == mergeB (mergeB x y) z++mergeB :: (Bool,Int) -> (Bool,Int) -> (Bool,Int)+mergeB (b1,l1) (b2,l2) = (toEnum v3,l3)+ where+ (v3,l3) = merge (fromEnum b1,l1) (fromEnum b2,l2)+--}++merge :: P.Num a => (a,a) -> (a,a) -> (a,a)+merge (onL, lenL) (onR, lenR) = (onL * onR, onL * lenR + lenL)++mergeExp :: Exp (Int,Int) -> Exp (Int,Int) -> Exp (Int,Int)+mergeExp e1 e2 =+ let+ t1 = unlift e1 :: (Exp Int,Exp Int)+ t2 = unlift e2 :: (Exp Int,Exp Int)+ in+ lift $ merge t1 t2+
+ src/Data/Array/Accelerate/Test/NoFib/Issues/Issue255.hs view
@@ -0,0 +1,105 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE ViewPatterns #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Issues.Issue255+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- https://github.com/AccelerateHS/accelerate/issues/255+--++module Data.Array.Accelerate.Test.NoFib.Issues.Issue255 (++ test_issue255++) where++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Test.NoFib.Base+import Data.Array.Accelerate.Test.NoFib.Config++import Test.Tasty+import Test.Tasty.HUnit++import Data.List as P ( mapAccumL )+import Prelude as P+++test_issue255 :: RunN -> TestTree+test_issue255 runN =+ askOption $ \(Interpreter slow) ->+ if slow+ then testGroup "255 (skipped due to interpreter backend)" []+ else testGroup "255"+ [ within lIMIT $ testCase "0" (force $ total (as P.!! 0))+ , within lIMIT $ testCase "2" (force $ total (as P.!! 2))+ , within lIMIT $ testCase "4" (force $ total (as P.!! 4))+ , within lIMIT $ testCase "20" (force $ total (as P.!! 20))+ , within lIMIT $ testCase "100" (force $ total (as P.!! 100))+ -- , within lIMIT $ testCase "200" (force $ total (as P.!! 200))+ -- , within lIMIT $ testCase "300" (force $ total (as P.!! 300))+ ]+ where+ lIMIT = 30 * 1000 * 1000 -- microseconds+ n = 20 * 1024 * 1024 -- 160 * MiB (8 bytes per Double)++ as :: [A.Vector Double]+ as = sums (A.fromList (Z:.n) (repeat 0)) (A.fromList (Z:.n) (repeat 1))++ scalar :: Elt e => e -> Scalar e+ scalar x = fromFunction Z (const x)++ sums :: A.Vector Double -> A.Vector Double -> [A.Vector Double]+ sums a0 b+ = a0+ : ( P.snd+ $ P.mapAccumL+ (\a' i -> let !go = runN step+ a = go (a', b, scalar i)+ in (a, a))+ a0+ [0 .. 500]+ )++ step :: Acc (A.Vector Double, A.Vector Double, A.Scalar Int) -> Acc (A.Vector Double)+ step (unlift -> (a, b, A.the -> _i::Exp Int)) = A.zipWith (+) a b++ total :: A.Vector Double -> A.Scalar Double+ total a = go a+ where+ !go = runN (A.sum . A.map id)+ -- runN $ A.sum $ A.map id $ A.use a++ force :: A.Scalar Double -> Assertion+ force x = () @=? (indexArray x Z `seq` ())++ -- print $ total $ as P.!! 0+ -- print $ total $ as P.!! 2+ -- print $ total $ as P.!! 4+ -- print $ total $ as P.!! 20+ -- print $ total $ as P.!! 100+ -- print $ total $ as P.!! 200+ -- print $ total $ as P.!! 300+++within :: Integer -> TestTree -> TestTree+within usec = adjustOption sup+ where+ sup :: Timeout -> Timeout+ sup t@(Timeout u _) | u P.> usec = t+ sup _ = mkTimeout usec++-- within :: Int -> Scalar Double -> Assertion+-- within n arr = do+-- r <- timeout n $ evaluate (indexArray arr Z `seq` ())+-- case r of+-- Nothing -> assertFailure "timeout: backend is too slow or memory manager stuck?"+-- Just () -> return ()+
+ src/Data/Array/Accelerate/Test/NoFib/Issues/Issue264.hs view
@@ -0,0 +1,148 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeOperators #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Issues.Issue264+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- https://github.com/AccelerateHS/accelerate/issues/264+--++module Data.Array.Accelerate.Test.NoFib.Issues.Issue264 (++ test_issue264++) where++import Prelude as P++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Sugar.Array as S+import Data.Array.Accelerate.Sugar.Elt as S+import Data.Array.Accelerate.Sugar.Shape as S+import Data.Array.Accelerate.Test.NoFib.Base+import Data.Array.Accelerate.Test.NoFib.Config+import Data.Array.Accelerate.Test.Similar++import Hedgehog+import qualified Hedgehog.Gen as Gen++import Test.Tasty+import Test.Tasty.Hedgehog+++test_issue264 :: RunN -> TestTree+test_issue264 runN =+ testGroup "264"+ [ testBool+ , at @TestInt8 $ testElt i8+ , at @TestInt16 $ testElt i16+ , at @TestInt32 $ testElt i32+ , at @TestInt64 $ testElt i64+ , at @TestWord8 $ testElt w8+ , at @TestWord16 $ testElt w16+ , at @TestWord32 $ testElt w32+ , at @TestWord64 $ testElt w64+ , at @TestFloat $ testElt f32+ , at @TestDouble $ testElt f64+ ]+ where+ testElt+ :: forall a. (Similar a, Show a, P.Num a, A.Num a)+ => Gen a+ -> TestTree+ testElt e =+ testGroup (show (eltR @a))+ [ testProperty "neg.neg" $ test_neg_neg runN e+ ]++ testBool :: TestTree+ testBool =+ testGroup "Bool"+ [ testProperty "not.not" $ test_not_not runN+ , testProperty "not(&&)" $ test_not_and runN+ , testProperty "not(||)" $ test_not_or runN+ , testProperty "not(not(&&))" $ test_not_not_and runN+ , testProperty "not(not(||))" $ test_not_not_or runN+ ]++test_not_not+ :: RunN+ -> Property+test_not_not runN =+ property $ do+ xs <- forAll (array Z Gen.bool)+ let !go = runN (A.map A.not . A.map A.not) in go xs === mapRef (P.not . P.not) xs++test_not_and+ :: RunN+ -> Property+test_not_and runN =+ property $ do+ xs <- forAll (array Z Gen.bool)+ ys <- forAll (array Z Gen.bool)+ let !go = runN (A.zipWith (\u v -> A.not (u A.&& v))) in go xs ys === zipWithRef (\u v -> P.not (u P.&& v)) xs ys++test_not_or+ :: RunN+ -> Property+test_not_or runN =+ property $ do+ xs <- forAll (array Z Gen.bool)+ ys <- forAll (array Z Gen.bool)+ let !go = runN (A.zipWith (\u v -> A.not (u A.|| v))) in go xs ys === zipWithRef (\u v -> P.not (u P.|| v)) xs ys++test_not_not_and+ :: RunN+ -> Property+test_not_not_and runN =+ property $ do+ xs <- forAll (array Z Gen.bool)+ ys <- forAll (array Z Gen.bool)+ let !go = runN (A.zipWith (\u v -> A.not (A.not (u A.&& v)))) in go xs ys === zipWithRef (\u v -> P.not (P.not (u P.&& v))) xs ys++test_not_not_or+ :: RunN+ -> Property+test_not_not_or runN =+ property $ do+ xs <- forAll (array Z Gen.bool)+ ys <- forAll (array Z Gen.bool)+ let !go = runN (A.zipWith (\u v -> A.not (A.not (u A.|| v)))) in go xs ys === zipWithRef (\u v -> P.not (P.not (u P.|| v))) xs ys++test_neg_neg+ :: (P.Num e, A.Num e, Similar e, Show e)+ => RunN+ -> Gen e+ -> Property+test_neg_neg runN e =+ property $ do+ sh <- forAll dim1+ xs <- forAll (array sh e)+ let !go = runN (A.map negate . A.map negate) in go xs ~~~ mapRef (negate . negate) xs++++mapRef :: (Shape sh, Elt a, Elt b) => (a -> b) -> Array sh a -> Array sh b+mapRef f xs = fromFunction (S.shape xs) (\ix -> f (xs S.! ix))++zipWithRef+ :: (Shape sh, Elt a, Elt b, Elt c)+ => (a -> b -> c)+ -> Array sh a+ -> Array sh b+ -> Array sh c+zipWithRef f xs ys =+ fromFunction+ (S.shape xs `S.intersect` S.shape ys)+ (\ix -> f (xs S.! ix) (ys S.! ix))+
+ src/Data/Array/Accelerate/Test/NoFib/Issues/Issue287.hs view
@@ -0,0 +1,102 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE RankNTypes #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Issues.Issue287+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- https://github.com/AccelerateHS/accelerate/issues/287+-- https://gist.github.com/cpdurham/7c11134bc345f12a8863+--++module Data.Array.Accelerate.Test.NoFib.Issues.Issue287 (++ test_issue287++) where++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Test.NoFib.Base++import Test.Tasty+import Test.Tasty.HUnit+++test_issue287 :: RunN -> TestTree+test_issue287 runN =+ testGroup "287"+ [ testCase "A" $ ref1 @=? runN (\x -> A.scanl1 f x) arr1+ , testCase "B" $ ref1 @=? runN (\x -> A.scanl1Seg (\_ b -> b) x (use segs)) arr1+ , testCase "C" $ ref1 @=? runN (\x -> A.scanl1Seg f x (use segs)) arr1+ ]++ref1 :: Vector (Int,Int,Int,Int,Int,Int)+ref1 = fromList (Z:.4) [(0,0,0,0,0,0),(0,0,0,0,0,0),(0,0,0,0,0,0),(0,0,0,0,0,0)]++arr1 :: Vector (Int,Int,Int,Int,Int,Int)+arr1 = fromList (Z:.4) [(0,0,0,0,0,0),(0,0,0,0,0,0),(0,0,0,0,0,0),(0,0,0,0,0,0)]++segs :: Segments Int+segs = A.fromList (Z:.2) [2,2]++f :: forall a. (A.Num a, A.Ord a)+ => Exp (a,a,a,a,a,a)+ -> Exp (a,a,a,a,a,a)+ -> Exp (a,a,a,a,a,a)+f x y = lift (mi3,l3,c3,r3,li3,ri3)+ where+ ( mi1,l1, c1,r1, li1,ri1) = unlift x :: (Exp a, Exp a, Exp a, Exp a, Exp a, Exp a)+ (_mi2,l2,_c2,r2,_li2,ri2) = unlift y :: (Exp a, Exp a, Exp a, Exp a, Exp a, Exp a)+ --+ l3 = l1+ c3 = c1+ r3 = r2 * r1+ mi3 = A.max mi1 (ri1+l2)+ li3 = li1+ ri3 = ri2++-- fExp+-- :: Exp (Int,Int,Int,Int,Int,Int)+-- -> Exp (Int,Int,Int,Int,Int,Int)+-- -> Exp (Int,Int,Int,Int,Int,Int)+-- fExp e1 e2 =+-- let+-- v1 = unlift6E e1+-- v2 = unlift6E e2+-- in+-- lift $ f v1 v2++-- unlift6E+-- :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f)+-- => Exp (a,b,c,d,e,f)+-- -> (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f)+-- unlift6E = unlift++-- lift6E+-- :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f)+-- => (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f)+-- -> Exp (a,b,c,d,e,f)+-- lift6E = lift++-- convert+-- :: Acc (Array DIM1 Int)+-- -> Acc (Array DIM1 (Int,Int,Int,Int,Int,Int))+-- convert = A.map (\_ -> lift6E (0,0,0,0,0,0))++-- arr2 = I.run1 convert (A.fromList (Z :. 4 :: DIM1) ([1,1,1,1]) :: Array DIM1 Int)++-- print $ C.run1 (\x -> A.scanl1 fExp x) $ arr2+-- --no problem++-- print $ C.run1 (\x -> A.scanl1Seg (\_ b -> b) x segs) $ arr2+-- --no problem++-- print $ C.run1 (\x -> A.scanl1Seg fExp x segs) $ arr2+-- -- CUDA exception: invalid argument+
+ src/Data/Array/Accelerate/Test/NoFib/Issues/Issue288.hs view
@@ -0,0 +1,38 @@+{-# LANGUAGE RankNTypes #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Issues.Issue288+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- https://github.com/AccelerateHS/accelerate/issues/288+--++module Data.Array.Accelerate.Test.NoFib.Issues.Issue288 (++ test_issue288++) where++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Test.NoFib.Base++import Test.Tasty+import Test.Tasty.HUnit++import Prelude as P+++test_issue288 :: RunN -> TestTree+test_issue288 runN =+ testCase "288" $ xs @=? runN (A.map f) xs++f :: Exp (Int, Int) -> Exp (Int, Int)+f e = while (const (lift False)) id e++xs :: Vector (Int, Int)+xs = fromList (Z:.10) (P.zip [1..] [1..])+
+ src/Data/Array/Accelerate/Test/NoFib/Issues/Issue362.hs view
@@ -0,0 +1,62 @@+{-# LANGUAGE RankNTypes #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Issues.Issue362+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- https://github.com/AccelerateHS/accelerate-llvm/issues/12+--++module Data.Array.Accelerate.Test.NoFib.Issues.Issue362 (++ test_issue362++) where++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Test.NoFib.Base++import Test.Tasty+import Test.Tasty.HUnit+++test_issue362 :: RunN -> TestTree+test_issue362 runN =+ testGroup "362"+ [ testCase "A" $ e1 @=? runN t1+ , testCase "B" $ e2 @=? runN t2+ ]++-- should work+e1 :: Vector (Int,Int,Int,Int)+e1 = fromList (Z:.10) [(0,0,0,0),(1,1,1,1),(3,3,3,3),(6,6,6,6),(10,10,10,10),(15,15,15,15),(21,21,21,21),(28,28,28,28),(36,36,36,36),(45,45,45,45)]++t1 :: Acc (Vector (Int,Int,Int,Int))+t1 = A.scanl1 (lift2 f) xs+ where+ xs = use $ fromList (Z:.10) [ (x,x,x,x) | x <- [0..9] ]+ --+ f :: (Exp Int, Exp Int, Exp Int, Exp Int)+ -> (Exp Int, Exp Int, Exp Int, Exp Int)+ -> (Exp Int, Exp Int, Exp Int, Exp Int)+ f (x1,x2,x3,x4) (y1,y2,y3,y4) = (x1+y1,x2+y2,x3+y3,x4+y4)+++-- was broken on pascal+e2 :: Vector (Int,Int,Int,Int,Int)+e2 = fromList (Z:.10) [(0,0,0,0,0),(1,1,1,1,1),(3,3,3,3,3),(6,6,6,6,6),(10,10,10,10,10),(15,15,15,15,15),(21,21,21,21,21),(28,28,28,28,28),(36,36,36,36,36),(45,45,45,45,45)]++t2 :: Acc (Vector (Int,Int,Int,Int,Int))+t2 = A.scanl1 (lift2 f) xs+ where+ xs = use $ fromList (Z:.10) [ (x,x,x,x,x) | x <- [0..9] ]+ --+ f :: (Exp Int, Exp Int, Exp Int, Exp Int, Exp Int)+ -> (Exp Int, Exp Int, Exp Int, Exp Int, Exp Int)+ -> (Exp Int, Exp Int, Exp Int, Exp Int, Exp Int)+ f (x1,x2,x3,x4,x5) (y1,y2,y3,y4,y5) = (x1+y1,x2+y2,x3+y3,x4+y4,x5+y5)+
+ src/Data/Array/Accelerate/Test/NoFib/Issues/Issue364.hs view
@@ -0,0 +1,99 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RebindableSyntax #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeOperators #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Issues.Issue364+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- https://github.com/AccelerateHS/accelerate/issues/364+--++module Data.Array.Accelerate.Test.NoFib.Issues.Issue364 (++ test_issue364++) where++import Prelude ( fromInteger, show )+import qualified Prelude as P++import Data.Array.Accelerate hiding ( fromInteger )+import Data.Array.Accelerate.Sugar.Elt as S+import Data.Array.Accelerate.Sugar.Shape as S+import Data.Array.Accelerate.Test.NoFib.Base+import Data.Array.Accelerate.Test.NoFib.Config++import Hedgehog++import Test.Tasty+import Test.Tasty.HUnit+++test_issue364 :: RunN -> TestTree+test_issue364 runN =+ testGroup "issue364"+ [ at @TestInt8 $ testElt i8+ , at @TestInt16 $ testElt i16+ , at @TestInt32 $ testElt i32+ , at @TestInt64 $ testElt i64+ -- , at @TestHalf $ testElt f16+ , at @TestFloat $ testElt f32+ , at @TestDouble $ testElt f64+ ]+ where+ testElt :: forall e. (Show e, Num e, Eq e, P.Num e, P.Enum e, P.Eq e)+ => Gen e+ -> TestTree+ testElt _ =+ testGroup (show (eltR @e))+ [ testCase "A" $ expectedArray @_ @e Z 64 @=? runN (scanl iappend one) (intervalArray Z 64)+ , testCase "B" $ expectedArray @_ @e Z 65 @=? runN (scanl iappend one) (intervalArray Z 65) -- failed for integral types+ ]+++-- interval of summations monoid+--+one,top :: Num e => Exp (e, e)+one = T2 (-1) (-1)+top = T2 (-2) (-2)++iappend :: (Num e, Eq e) => Exp (e,e) -> Exp (e,e) -> Exp (e,e)+iappend x y =+ if x == one then y else+ if y == one then x else+ if x == top || y == top then top+ else+ let T2 x1 x2 = x+ T2 y1 y2 = y+ in+ if x2 + 1 == y1+ then T2 x1 y2+ else top++intervalArray :: (Shape sh, Elt e, P.Num e, P.Enum e)+ => sh+ -> Int+ -> Array (sh:.Int) (e,e)+intervalArray sh n+ = fromList (sh:.n)+ . P.concat+ $ P.replicate (S.size sh) [ (i,i) | i <- [0.. (P.fromIntegral n-1)] ]++expectedArray :: (Shape sh, Elt e, P.Num e, P.Enum e)+ => sh+ -> Int+ -> Array (sh:.Int) (e,e)+expectedArray sh n+ = fromList (sh:.n+1)+ $ P.concat+ $ P.replicate (S.size sh) $ (-1,-1) : [ (0,i) | i <- [0 .. P.fromIntegral n - 1] ]+
+ src/Data/Array/Accelerate/Test/NoFib/Issues/Issue407.hs view
@@ -0,0 +1,57 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedLists #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Issues.Issue407+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- https://github.com/AccelerateHS/accelerate/issues/407+-- https://github.com/AccelerateHS/accelerate-llvm/pull/27+--++module Data.Array.Accelerate.Test.NoFib.Issues.Issue407 (++ test_issue407++) where++import Prelude as P++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Sugar.Elt as S+import Data.Array.Accelerate.Test.NoFib.Base++import Test.Tasty+import Test.Tasty.HUnit+++test_issue407 :: RunN -> TestTree+test_issue407 runN =+ testGroup "407"+ [ testElt @Float+ , testElt @Double+ ]+ where+ testElt+ :: forall a. (Show a, P.Fractional a, A.RealFloat a)+ => TestTree+ testElt =+ testGroup (show (eltR @a))+ [ testCase "isNaN" $ eNaN @=? runN (A.map A.isNaN) xs+ , testCase "isInfinite" $ eInf @=? runN (A.map A.isInfinite) xs+ ]+ where+ xs :: Vector a+ xs = [0/0, -2/0, -0/0, 0.1, 1/0, 0.5, 5/0]+ eNaN = [True, False, True, False, False, False, False] -- expected: isNaN+ eInf = [False, True, False, False, True, False, True] -- expected: isInfinite+
+ src/Data/Array/Accelerate/Test/NoFib/Issues/Issue409.hs view
@@ -0,0 +1,61 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Issues.Issue409+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- https://github.com/AccelerateHS/accelerate/issues/409+--++module Data.Array.Accelerate.Test.NoFib.Issues.Issue409 (++ test_issue409++) where++import Prelude as P++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Sugar.Elt as S+import Data.Array.Accelerate.Test.NoFib.Base++import Test.Tasty+import Test.Tasty.HUnit+++test_issue409 :: RunN -> TestTree+test_issue409 runN =+ testGroup "409"+ [ testElt @Float+ , testElt @Double+ ]+ where+ testElt+ :: forall a. (Show a, P.Floating a, P.Eq a, A.Floating a)+ => TestTree+ testElt =+ testGroup (show (eltR @a))+ [ testCase "A" $ e1 @=? indexArray (runN (A.map f) t1) Z+ ]+ where+ e1 :: a+ e1 = 1 + tanh (-1)++ t1 :: Scalar a+ t1 = fromList Z [1]++ f :: Exp a -> Exp a+ f x = let y = recip x+ b = (-y) * y+ in+ y + tanh b+
+ src/Data/Array/Accelerate/Test/NoFib/Issues/Issue427.hs view
@@ -0,0 +1,89 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ViewPatterns #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Issues.Issue427+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- https://github.com/AccelerateHS/accelerate/issues/427+--++module Data.Array.Accelerate.Test.NoFib.Issues.Issue427 (++ test_issue427++) where++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Test.NoFib.Base+import Data.Array.Accelerate.Test.Similar++import Test.Tasty+import Test.Tasty.Hedgehog++import Hedgehog+import qualified Hedgehog.Gen as Gen+import qualified Hedgehog.Range as Range++import Prelude as P+++test_issue427 :: RunN -> TestTree+test_issue427 runN+ = testGroup "427"+ [ testProperty "n-by-64" $ test_indicesOfTruth runN (by 64) -- should be okay+ , testProperty "n-by-8" $ test_indicesOfTruth runN (by 8) -- usually fails+ , testProperty "n-by-m" $ test_indicesOfTruth runN dim2+ ]+ where+ by x = do+ y <- Gen.int (Range.linear 0 1024)+ pure (Z :. y :. x)+++test_indicesOfTruth+ :: RunN+ -> Gen DIM2+ -> Property+test_indicesOfTruth runN dim =+ property $ do+ sh <- forAll dim+ xs <- forAll (array sh Gen.bool)+ let !go = runN indicesOfTruth+ go xs ~~~ indicesOfTruthRef xs+++indicesOfTruth :: Acc (Array DIM2 Bool) -> Acc (Vector (Int, Int))+indicesOfTruth xs =+ let+ withInds :: Acc (Array DIM2 (Int, Int, Bool))+ withInds = imap addInds xs++ addInds :: Exp DIM2 -> Exp Bool -> Exp (Int, Int, Bool)+ addInds (I2 x y) b = T3 x y b++ accept :: Exp (Int, Int, Bool) -> Exp Bool+ accept (T3 _ _ b) = b++ dropBool :: Exp (Int, Int, Bool) -> Exp (Int, Int)+ dropBool (T3 x y _) = T2 x y+ in+ A.map dropBool (afst (A.filter accept withInds))++indicesOfTruthRef :: Array DIM2 Bool -> Vector (Int, Int)+indicesOfTruthRef xs =+ let+ withInds = fromFunction (arrayShape xs) (\ix@(Z :. y :. x) -> (y, x, indexArray xs ix))+ accept (_,_,b) = b+ dropBool (x,y,_) = (x,y)++ ys = P.map dropBool $ P.filter accept $ toList withInds+ m = P.length ys+ in+ fromList (Z :. m) ys+
+ src/Data/Array/Accelerate/Test/NoFib/Issues/Issue436.hs view
@@ -0,0 +1,59 @@+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TypeOperators #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Issues.Issue436+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- https://github.com/AccelerateHS/accelerate/issues/436+--++module Data.Array.Accelerate.Test.NoFib.Issues.Issue436 (++ test_issue436++) where++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Test.NoFib.Base++import Test.Tasty+import Test.Tasty.HUnit+++test_issue436 :: RunN -> TestTree+test_issue436 runN =+ testGroup "436"+ [ testCase "A" $ e1 @=? runN t1+ , testCase "B" $ e2 @=? runN t2+ ]+++t1 :: Acc (Vector Bool, Scalar Int)+t1 = test 3 (bools (Z :. 5))++e1 :: (Vector Bool, Scalar Int)+e1 = ( fromList (Z :. 3) [True,False,True]+ , fromList Z [3])++t2 :: Acc (Vector Bool, Vector Int)+t2 = test 3 (bools (Z :. 5 :. 5))++e2 :: (Vector Bool, Vector Int)+e2 = ( fromList (Z :. 15) [True,False,True,False,True,False,True,False,True,False,True,False,True,False,True]+ , fromList (Z :. 5) [3,3,3,3,3]+ )++test :: (Shape sh, Elt e)+ => Int+ -> Acc (Array (sh:.Int) e)+ -> Acc (Vector e, Array sh Int)+test n xs = A.filter (const (constant True)) (A.take (constant n) xs)++bools :: Shape sh => sh -> Acc (Array sh Bool)+bools sh = use $ fromList sh (cycle [True, False])+
+ src/Data/Array/Accelerate/Test/NoFib/Issues/Issue437.hs view
@@ -0,0 +1,90 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TypeOperators #-}+{-# OPTIONS_GHC -fno-warn-unused-imports #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Issues.Issue437+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- https://github.com/AccelerateHS/accelerate/issues/437+--++module Data.Array.Accelerate.Test.NoFib.Issues.Issue437 (++ test_issue437++) where++import Data.Atomic as Atomic+import Data.Array.Accelerate as A+import Data.Array.Accelerate.Test.NoFib.Base++import Test.Tasty+import Test.Tasty.HUnit+import Test.Tasty.ExpectedFailure++import Text.Printf+import Prelude as P+++test_issue437 :: RunN -> TestTree+#ifndef ACCELERATE_DEBUG+test_issue437 _+ = expectFail+ $ testCase "437"+ $ assertFailure "This test requires building with -fdebug"+#else+test_issue437 runN+ = testCase "437"+ $ do+ a0 <- Atomic.read __total_bytes_allocated_remote+ b0 <- Atomic.read __total_bytes_copied_to_remote+ c0 <- Atomic.read __total_bytes_copied_from_remote++ let (a,_) = go xs++ -- check the final result is actually transferred back+ a @?= fromList Z [42]++ a1 <- Atomic.read __total_bytes_allocated_remote+ b1 <- Atomic.read __total_bytes_copied_to_remote+ c1 <- Atomic.read __total_bytes_copied_from_remote++ let alloc = a1-a0+ to = b1-b0+ from = c1-c0++ -- Either:+ -- a) this is a local memory backend; no transfer takes place+ --+ -- b) this is a remote memory backend; we should only transfer the 4 bytes+ -- to the device for the 'unit', but since the data is already on the+ -- host we can avoid the transfer back+ --+ assertBool (printf "bytes_allocated_remote=%d, bytes_copied_to_remote=%d, bytes_copied_from_remote=%d" alloc to from)+ $ (alloc P.== 0 P.&& to P.== 0 P.&& from P.== 0) P.|| -- local memory space+ (alloc P.> 0 P.&& to P.== 4 P.&& from P.== 0) -- remote memory space+ where+ xs :: (Scalar Float, Matrix Float)+ xs = runN $ T2 (unit 42) (fill (constant $ Z:.10000:.10000) 1)++ go :: Arrays a => a -> a+ go = runN f+ where+ f :: Arrays a => Acc a -> Acc a+ f = id++-- internals+foreign import ccall "&__total_bytes_allocated_remote" __total_bytes_allocated_remote :: Atomic+foreign import ccall "&__total_bytes_copied_to_remote" __total_bytes_copied_to_remote :: Atomic+foreign import ccall "&__total_bytes_copied_from_remote" __total_bytes_copied_from_remote :: Atomic++#endif+
+ src/Data/Array/Accelerate/Test/NoFib/Issues/Issue439.hs view
@@ -0,0 +1,37 @@+{-# LANGUAGE RankNTypes #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Issues.Issue439+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- https://github.com/AccelerateHS/accelerate-llvm/issues/46+--++module Data.Array.Accelerate.Test.NoFib.Issues.Issue439 (++ test_issue439++) where++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Test.NoFib.Base++import Test.Tasty+import Test.Tasty.HUnit+++test_issue439 :: RunN -> TestTree+test_issue439 runN+ = testCase "439"+ $ e1 @=? runN t1++e1 :: Scalar Float+e1 = fromList Z [2]++t1 :: Acc (Scalar Float)+t1 = compute . A.map (* 2) . compute $ fill Z_ 1+
+ src/Data/Array/Accelerate/Test/NoFib/Issues/Issue517.hs view
@@ -0,0 +1,45 @@+{-# LANGUAGE RankNTypes #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Issues.Issue439+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- https://github.com/AccelerateHS/accelerate/issues/517+--++module Data.Array.Accelerate.Test.NoFib.Issues.Issue517 (++ test_issue517++) where++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Data.Semigroup as A+import Data.Array.Accelerate.Test.NoFib.Base++import Test.Tasty+import Test.Tasty.HUnit+++test_issue517 :: RunN -> TestTree+test_issue517 runN+ = testCase "517"+ $ e1 @=? runN t1++type Tup5 a = (a, a, a, a, a)++e1 :: Scalar (Tup5 (Maybe (Max Float)))+e1 = fromList Z [(Nothing, Just 2, Just 3, Just 5, Just 7)]++t1 :: Acc (Scalar (Tup5 (Maybe (Max Float))))+t1 = unit $+ T5 (Nothing_ <> Nothing_)+ (Nothing_ <> Just_ 2)+ (Just_ 3 <> Nothing_)+ (Just_ 4 <> Just_ 5)+ (Just_ 7 <> Just_ 6)+
+ src/Data/Array/Accelerate/Test/NoFib/Issues/Issue551.hs view
@@ -0,0 +1,83 @@+{-# LANGUAGE BlockArguments #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ViewPatterns #-}+{-# OPTIONS_GHC -Wno-name-shadowing #-}+module Data.Array.Accelerate.Test.NoFib.Issues.Issue551 where++import Data.Array.Accelerate (Elt, Exp, Word16, match, mkPattern)+import Data.Function ((&))+import GHC.Generics (Generic)++import qualified Data.Array.Accelerate as A+import qualified Data.Array.Accelerate.Unsafe as A+import Data.Array.Accelerate.Test.NoFib.Base++import Test.Tasty+import Test.Tasty.HUnit+++data Digit = One | Two | Three | Four | Five | Six | Seven | Eight | Nine+ deriving (Generic)++instance Elt Digit++mkPattern ''Digit++word16ToDigit :: (HasCallStack) => Exp Word16 -> Exp Digit+word16ToDigit i =+ A.cond (i A.== 0) One_ $+ A.cond (i A.== 1) Two_ $+ A.cond (i A.== 2) Three_ $+ A.cond (i A.== 3) Four_ $+ A.cond (i A.== 4) Five_ $+ A.cond (i A.== 5) Six_ $+ A.cond (i A.== 6) Seven_ $+ A.cond (i A.== 7) Eight_ $+ A.cond (i A.== 8) Nine_ $+ A.undef++digitToWord16 :: Exp Digit -> Exp Word16+digitToWord16 = match \case+ One_ -> 0+ Two_ -> 1+ Three_ -> 2+ Four_ -> 3+ Five_ -> 4+ Six_ -> 5+ Seven_ -> 6+ Eight_ -> 7+ Nine_ -> 8+++instance A.Eq Digit where+ d == d' =+ A.T2 d d' & A.match \case+ A.T2 One_ One_ -> A.True_+ A.T2 Two_ Two_ -> A.True_+ A.T2 Three_ Three_ -> A.True_+ A.T2 Four_ Four_ -> A.True_+ A.T2 Five_ Five_ -> A.True_+ A.T2 Six_ Six_ -> A.True_+ A.T2 Seven_ Seven_ -> A.True_+ A.T2 Eight_ Eight_ -> A.True_+ A.T2 Nine_ Nine_ -> A.True_+ _ -> A.False_++digits :: A.Acc (A.Vector Digit)+digits = A.generate (A.Z_ A.::. 9) (\(A.I1 i) -> word16ToDigit (A.fromIntegral i))++test_issue551 :: RunN -> TestTree+test_issue551 runN = testCase "551" $+ (A.fromList (A.Z A.:. 9 A.:. 9) [i == j | i <- [0::Int ..8], j <- [0..8]]+ ,A.fromList (A.Z A.:. 9) [0..8])+ @=?+ runN (A.T2 (A.generate (A.Z_ A.::. 9 A.::. 9) (\(A.I2 i j) ->+ word16ToDigit (A.fromIntegral i) A.== word16ToDigit (A.fromIntegral j)))+ (A.map digitToWord16 digits))
+ src/Data/Array/Accelerate/Test/NoFib/Issues/Issue93.hs view
@@ -0,0 +1,38 @@+{-# LANGUAGE RankNTypes #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Issues.Issue93+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- https://github.com/AccelerateHS/accelerate/issues/93+--++module Data.Array.Accelerate.Test.NoFib.Issues.Issue93 (++ test_issue93++) where++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Test.NoFib.Base++import Test.Tasty+import Test.Tasty.HUnit+++test_issue93 :: RunN -> TestTree+test_issue93 runN =+ testCase "93" $ xs @=? runN test1++xs :: Array DIM2 Int+xs = fromList (Z :. 1 :. 1) [5]++test1 :: Acc (Array DIM2 Int)+test1 = permute (\c _ -> c) (fill (shape xs') (constant 0)) Just_ xs'+ where+ xs' = use xs+
+ src/Data/Array/Accelerate/Test/NoFib/Misc.hs view
@@ -0,0 +1,28 @@+{-# LANGUAGE RankNTypes #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Misc+-- Copyright : [2025..] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Test.NoFib.Misc (+ test_misc,+) where++import Test.Tasty++import Data.Array.Accelerate.Test.NoFib.Base+import Data.Array.Accelerate.Test.NoFib.Misc.Cache+import Data.Array.Accelerate.Test.NoFib.Misc.Scanl1+++test_misc :: RunN -> TestTree+test_misc runN =+ testGroup "misc"+ [ test_misc_cache runN+ , test_misc_scanl1 runN+ ]
+ src/Data/Array/Accelerate/Test/NoFib/Misc/Cache.hs view
@@ -0,0 +1,73 @@+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE RankNTypes #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Misc.Cache+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Test.NoFib.Misc.Cache (+ test_misc_cache+) where++import Prelude as P++import qualified Data.Array.Accelerate as A+import Data.Array.Accelerate ( Acc, Scalar, pattern I1, shape, Z(Z), (:.)((:.)), (!) )+import Data.Array.Accelerate.Test.NoFib.Base++import Test.Tasty+import Test.Tasty.HUnit+++-- AST hashing in Analysis.Hash ignores certain parts of the AST when 'perfect'+-- is set to False. This is to prevent "irrelevant" parts of the AST, namely+-- parts that do not get compiled into the kernel, from being taken into+-- account when checking whether a kernel has already been compiled. An example+-- of such an "irrelevant" part is the expression in a Backpermute that+-- computes the target shape; in accelerate-llvm, this is computed on the host+-- outside of the kernel, not on the device.+--+-- However, the code in accelerate-llvm:DAA.LLVM.Compile that computes the free+-- array variables of a combinator to be compiled (to be turned into arguments+-- of the compiled kernel) _does_ traverse those "irrelevant" AST parts. This+-- means that the number of parameters to a compiled kernel can depend on+-- information in the AST that is not included in the hash.+--+-- This leads to segfaults and worse. This test is here to witness this bug.++test_misc_cache :: RunN -> TestTree+test_misc_cache runN =+ testGroup "cache"+ [ testCase "generate" $ casus testGenerate+ , testCase "backpermute" $ casus testBackpermute+ ]+ where+ casus :: (A.Arrays a, Eq a, Show a) => (Acc a, a) -> Assertion+ casus (prog, expected) = expected @=? runN prog++testGenerate :: (Acc (Scalar Float), Scalar Float)+testGenerate =+ ( let a = A.use (A.fromList (Z :. 10) [0..9 :: Float])+ b = A.use (A.fromList (Z :. 10) [10..19 :: Float])+ c = A.compute $ A.generate (let I1 n = shape a ; I1 m = shape b in I1 (n + m))+ (\(I1 i) -> a ! I1 (i `rem` 10))+ d = A.compute $ A.generate (let I1 n = shape a in I1 (3 * n))+ (\(I1 i) -> a ! I1 (i `rem` 10))+ in A.zipWith (+) (A.sum c) (A.sum d)+ , A.fromList Z [5 * P.sum [0..9 :: Float]] )++testBackpermute :: (Acc (Scalar Float), Scalar Float)+testBackpermute =+ ( let a = A.use (A.fromList (Z :. 10) [0..9 :: Float])+ b = A.use (A.fromList (Z :. 10) [10..19 :: Float])+ c = A.compute $ A.backpermute (let I1 n = shape a ; I1 m = shape b in I1 (min n m))+ id a+ d = A.compute $ A.backpermute (let I1 n = shape a in I1 n)+ id a+ in A.zipWith (+) (A.sum c) (A.sum d)+ , A.fromList Z [2 * P.sum [0..9 :: Float]] )
+ src/Data/Array/Accelerate/Test/NoFib/Misc/Scanl1.hs view
@@ -0,0 +1,39 @@+{-# LANGUAGE RankNTypes #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Misc.Scanl1+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Test.NoFib.Misc.Scanl1 (+ test_misc_scanl1+) where++import Prelude as P++import qualified Data.Array.Accelerate as A+import Data.Array.Accelerate ( Z(Z), (:.)((:.)) )+import Data.Array.Accelerate.Test.NoFib.Base++import Test.Tasty+import Test.Tasty.HUnit+++-- In the PTX backend, __syncthreads was called under non-uniform control flow+-- for a very long time; this issue was greatly exacerbated by the initial+-- implementation of https://github.com/AccelerateHS/accelerate-llvm/pull/97 .+-- This test is to reproduce the resulting failure and prevent it from+-- occurring again.++test_misc_scanl1 :: RunN -> TestTree+test_misc_scanl1 runN =+ testCase "scanl1" $+ let sh@(_ :. innerN) = Z :. 257 :. 31+ intsum n m = m * (m + 1) `quot` 2 - (n - 1) * n `quot` 2 -- == sum [n .. m]+ ref = A.fromFunction sh (\(Z :. i :. j) -> intsum (1 + i*innerN) (1 + i*innerN + j))+ arr = A.fromList sh [1::Int ..]+ in ref @=? runN (A.scanl1 (+)) arr
+ src/Data/Array/Accelerate/Test/NoFib/Prelude.hs view
@@ -0,0 +1,69 @@+{-# LANGUAGE RankNTypes #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Prelude+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Test.NoFib.Prelude (++ test_prelude,++ module Data.Array.Accelerate.Test.NoFib.Prelude.Map,+ module Data.Array.Accelerate.Test.NoFib.Prelude.ZipWith,+ module Data.Array.Accelerate.Test.NoFib.Prelude.SIMD,+ module Data.Array.Accelerate.Test.NoFib.Prelude.Fold,+ module Data.Array.Accelerate.Test.NoFib.Prelude.Scan,+ module Data.Array.Accelerate.Test.NoFib.Prelude.Backpermute,+ module Data.Array.Accelerate.Test.NoFib.Prelude.Permute,+ module Data.Array.Accelerate.Test.NoFib.Prelude.Filter,+ module Data.Array.Accelerate.Test.NoFib.Prelude.Stencil,++) where++import Test.Tasty++import Data.Array.Accelerate.Test.NoFib.Base+import Data.Array.Accelerate.Test.NoFib.Prelude.Map+import Data.Array.Accelerate.Test.NoFib.Prelude.ZipWith+import Data.Array.Accelerate.Test.NoFib.Prelude.SIMD+import Data.Array.Accelerate.Test.NoFib.Prelude.Fold+import Data.Array.Accelerate.Test.NoFib.Prelude.Scan+import Data.Array.Accelerate.Test.NoFib.Prelude.Backpermute+import Data.Array.Accelerate.Test.NoFib.Prelude.Permute+import Data.Array.Accelerate.Test.NoFib.Prelude.Filter+import Data.Array.Accelerate.Test.NoFib.Prelude.Stencil+++test_prelude :: RunN -> TestTree+test_prelude runN =+ testGroup "prelude"+ [ test_map runN+ , test_zipWith runN+ , test_simd runN+ , test_fold runN+ , test_foldSeg runN+ , test_backpermute runN+ , test_permute runN+ , test_scanl runN+ , test_scanl1 runN+ , test_scanl' runN+ , test_scanr runN+ , test_scanr1 runN+ , test_scanr' runN+ , test_scanlSeg runN+ , test_scanl1Seg runN+ , test_scanl'Seg runN+ , test_scanrSeg runN+ , test_scanr1Seg runN+ , test_scanr'Seg runN+ , test_filter runN+ , test_stencil runN+ -- , test_replicate runN conf+ -- , test_sequences runN conf+ ]+
+ src/Data/Array/Accelerate/Test/NoFib/Prelude/Backpermute.hs view
@@ -0,0 +1,166 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeOperators #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Prelude.Backpermute+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Test.NoFib.Prelude.Backpermute (++ test_backpermute++) where++import Prelude as P++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Sugar.Array as S+import Data.Array.Accelerate.Sugar.Elt as S+import Data.Array.Accelerate.Sugar.Shape as S+import Data.Array.Accelerate.Test.NoFib.Base+import Data.Array.Accelerate.Test.NoFib.Config+import Data.Array.Accelerate.Test.Similar++import Hedgehog+import qualified Hedgehog.Gen as Gen+import qualified Hedgehog.Range as Range++import Test.Tasty+import Test.Tasty.Hedgehog+++test_backpermute :: RunN -> TestTree+test_backpermute runN =+ testGroup "backpermute"+ [ at @TestInt8 $ testElt i8+ , at @TestInt16 $ testElt i16+ , at @TestInt32 $ testElt i32+ , at @TestInt64 $ testElt i64+ , at @TestWord8 $ testElt w8+ , at @TestWord16 $ testElt w16+ , at @TestWord32 $ testElt w32+ , at @TestWord64 $ testElt w64+ , at @TestHalf $ testElt f16+ , at @TestFloat $ testElt f32+ , at @TestDouble $ testElt f64+ ]+ where+ testElt+ :: forall a. (Similar a, Elt a, Show a)+ => Gen a+ -> TestTree+ testElt e =+ testGroup (show (eltR @a))+ [ testDim dim1+ , testDim dim2+ , testDim dim3+ ]+ where+ testDim+ :: forall sh. (Shape sh, Slice sh, Show sh, P.Eq sh)+ => Gen (sh:.Int)+ -> TestTree+ testDim sh =+ testGroup ("DIM" P.++ show (rank @(sh:.Int)))+ [+ testProperty "take" $ test_take runN sh e+ , testProperty "drop" $ test_drop runN sh e+ , testProperty "gather->DIM1" $ test_gather runN sh dim1 e+ , testProperty "gather->DIM2" $ test_gather runN sh dim2 e+ , testProperty "gather->DIM3" $ test_gather runN sh dim3 e+ ]++{-# NOINLINE test_take #-}+test_take+ :: (Shape sh, Slice sh, Show sh, Similar e, Show e, P.Eq sh, Elt e)+ => RunN+ -> Gen (sh:.Int)+ -> Gen e+ -> Property+test_take runN dim e =+ property $ do+ sh@(_:.n) <- forAll dim+ xs <- forAll (array sh e)+ i <- forAll (Gen.int (Range.linear (-2) (n+1)))+ let !go = runN (\v -> A.take (the v)) in go (scalar i) xs ~~~ takeRef i xs++{-# NOINLINE test_drop #-}+test_drop+ :: (Shape sh, Slice sh, Show sh, Similar e, Show e, P.Eq sh, Elt e)+ => RunN+ -> Gen (sh:.Int)+ -> Gen e+ -> Property+test_drop runN dim e =+ property $ do+ sh@(_:.n) <- forAll dim+ xs <- forAll (array sh e)+ i <- forAll (Gen.int (Range.linear (-2) (n+1)))+ let !go = runN (\v -> A.drop (the v)) in go (scalar i) xs ~~~ dropRef i xs++{-# NOINLINE test_gather #-}+test_gather+ :: (Shape sh, Shape sh', Show sh, Show sh', P.Eq sh', Similar e, Show e, Elt e)+ => RunN+ -> Gen sh+ -> Gen sh'+ -> Gen e+ -> Property+test_gather runN dim dim' e =+ property $ do+ sh <- forAll (dim `except` \v -> S.size v P.== 0)+ sh' <- forAll dim'+ let+ n = S.size sh+ n' = S.size sh'+ toIxArr = fromList sh' . P.map (S.fromIndex sh)+ --+ xs <- forAll (array sh e)+ ix <- forAll (toIxArr P.<$> Gen.list (Range.singleton n') (Gen.int (Range.linear 0 (n-1))))+ --+ let !go = runN $ \i -> A.backpermute (A.shape i) (i A.!)+ --+ go ix xs ~~~ backpermuteRef sh' (ix S.!) xs+++scalar :: Elt e => e -> Scalar e+scalar x = fromFunction Z (const x)++backpermuteRef+ :: (Shape sh, Shape sh', Elt e)+ => sh'+ -> (sh' -> sh)+ -> Array sh e+ -> Array sh' e+backpermuteRef sh' p arr =+ fromFunction sh' (\ix -> arr S.! p ix)++takeRef+ :: (Shape sh, Slice sh, Elt e)+ => Int+ -> Array (sh:.Int) e+ -> Array (sh:.Int) e+takeRef n arr =+ let sh :. m = S.shape arr+ in fromFunction (sh :. P.min m n) (arr S.!)++dropRef+ :: (Shape sh, Slice sh, Elt e)+ => Int+ -> Array (sh:.Int) e+ -> Array (sh:.Int) e+dropRef n arr =+ let sh :. m = S.shape arr+ n' = P.max 0 n+ in fromFunction (sh :. P.max 0 (m - n')) (\(sz:.i) -> arr S.! (sz :. i+n'))+
+ src/Data/Array/Accelerate/Test/NoFib/Prelude/Filter.hs view
@@ -0,0 +1,137 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE MonoLocalBinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeOperators #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Prelude.Filter+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Test.NoFib.Prelude.Filter (++ test_filter++) where++import Prelude as P++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Sugar.Array as S+import Data.Array.Accelerate.Sugar.Elt as S+import Data.Array.Accelerate.Sugar.Shape as S+import Data.Array.Accelerate.Test.NoFib.Base+import Data.Array.Accelerate.Test.NoFib.Config+import Data.Array.Accelerate.Test.Similar++import Hedgehog++import Test.Tasty+import Test.Tasty.Hedgehog+++test_filter :: RunN -> TestTree+test_filter runN =+ testGroup "filter"+ [ at @TestInt8 $ testIntegralElt i8+ , at @TestInt16 $ testIntegralElt i16+ , at @TestInt32 $ testIntegralElt i32+ , at @TestInt64 $ testIntegralElt i64+ , at @TestWord8 $ testIntegralElt w8+ , at @TestWord16 $ testIntegralElt w16+ , at @TestWord32 $ testIntegralElt w32+ , at @TestWord64 $ testIntegralElt w64+ , at @TestHalf $ testFloatingElt f16+ , at @TestFloat $ testFloatingElt f32+ , at @TestDouble $ testFloatingElt f64+ ]+ where+ testIntegralElt+ :: forall a. (P.Integral a, A.Integral a, Similar a, Show a)+ => Gen a+ -> TestTree+ testIntegralElt e =+ testGroup (show (eltR @a))+ [ testDim dim1+ , testDim dim2+ , testDim dim3+ ]+ where+ testDim+ :: forall sh. (Shape sh, Slice sh, Show sh, P.Eq sh)+ => Gen (sh:.Int)+ -> TestTree+ testDim sh =+ testGroup ("DIM" P.++ show (rank @(sh:.Int)))+ [ testProperty "even" $ test_even runN sh e+ ]++ testFloatingElt+ :: forall a. (P.Floating a, P.Ord a, A.Floating a, A.Ord a, Similar a, Show a)+ => Gen a+ -> TestTree+ testFloatingElt e =+ testGroup (show (eltR @a))+ [ testDim dim1+ , testDim dim2+ , testDim dim3+ ]+ where+ testDim+ :: forall sh. (Shape sh, Slice sh, Show sh, P.Eq sh)+ => Gen (sh:.Int)+ -> TestTree+ testDim sh =+ testGroup ("DIM" P.++ show (rank @(sh:.Int)))+ [ testProperty "positive" $ test_positive runN sh e+ ]+++{-# NOINLINE test_even #-}+test_even+ :: (Shape sh, Slice sh, Show sh, Similar e, Show e, P.Eq sh, P.Integral e, A.Integral e)+ => RunN+ -> Gen (sh:.Int)+ -> Gen e+ -> Property+test_even runN dim e =+ property $ do+ sh <- forAll dim+ xs <- forAll (array sh e)+ let !go = runN (A.filter A.even) in go xs ~~~ filterRef P.even xs++{-# NOINLINE test_positive #-}+test_positive+ :: (Shape sh, Slice sh, Show sh, Similar e, Show e, P.Eq sh, P.Num e, P.Ord e, A.Num e, A.Ord e)+ => RunN+ -> Gen (sh:.Int)+ -> Gen e+ -> Property+test_positive runN dim e =+ property $ do+ sh <- forAll dim+ xs <- forAll (array sh e)+ let !go = runN (A.filter (A.> 0)) in go xs ~~~ filterRef (P.> 0) xs+++filterRef+ :: (Shape sh, Elt e)+ => (e -> Bool)+ -> Array (sh:.Int) e+ -> (Vector e, Array sh Int)+filterRef f arr = (fromList (Z:.total) (concat result), fromList sh len)+ where+ sh :. n = S.shape arr+ result = P.take (S.size sh) [ P.filter f sub | sub <- splitEvery n (toList arr) ]+ len = P.map P.length result+ total = P.sum len+
+ src/Data/Array/Accelerate/Test/NoFib/Prelude/Fold.hs view
@@ -0,0 +1,325 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeOperators #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Prelude.Fold+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Test.NoFib.Prelude.Fold (++ test_fold,+ test_foldSeg,++) where++import Prelude as P++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Sugar.Elt as S+import Data.Array.Accelerate.Sugar.Shape as S+import Data.Array.Accelerate.Test.NoFib.Base+import Data.Array.Accelerate.Test.NoFib.Config+import Data.Array.Accelerate.Test.Similar++import Hedgehog+import qualified Hedgehog.Gen as Gen+import qualified Hedgehog.Range as Range++import Test.Tasty+import Test.Tasty.Hedgehog+++test_fold :: RunN -> TestTree+test_fold runN =+ testGroup "fold"+ [ at @TestInt8 $ testElt i8 (Gen.int8 (Range.linearFrom 0 (-1) 1))+ , at @TestInt16 $ testElt i16 (Gen.int16 (Range.linearFrom 0 (-10) 10))+ , at @TestInt32 $ testElt i32 (Gen.int32 (Range.linearFrom 0 (-1000) 1000))+ , at @TestInt64 $ testElt i64 (Gen.int64 (Range.linearFrom 0 (-10000) 10000))+ , at @TestWord8 $ testElt w8 (Gen.word8 (Range.linear 0 1))+ , at @TestWord16 $ testElt w16 (Gen.word16 (Range.linear 0 10))+ , at @TestWord32 $ testElt w32 (Gen.word32 (Range.linear 0 1000))+ , at @TestWord64 $ testElt w64 (Gen.word64 (Range.linear 0 10000))+ , at @TestHalf $ testElt f16 f16+ , at @TestFloat $ testElt f32 f32+ , at @TestDouble $ testElt f64 f64+ ]+ where+ testElt+ :: forall a. (P.Num a, P.Ord a , A.Num a, A.Ord a , Similar a, Show a)+ => Gen a+ -> Gen a+ -> TestTree+ testElt e small =+ testGroup (show (eltR @a))+ [ testDim dim1+ , testDim dim2+ , testDim dim3+ ]+ where+ testDim+ :: forall sh. (Shape sh, Show sh, P.Eq sh)+ => Gen (sh:.Int)+ -> TestTree+ testDim sh =+ testGroup ("DIM" P.++ show (rank @(sh:.Int)))+ [+ testProperty "sum" $ test_sum runN sh (pure 0) e+ , testProperty "non-neutral sum" $ test_sum runN sh e e+ , testProperty "non-commutative" $ test_mss runN sh small+ , testProperty "minimum" $ test_minimum runN sh e+ , testProperty "maximum" $ test_maximum runN sh e+ ]+++test_foldSeg :: RunN -> TestTree+test_foldSeg runN =+ testGroup "foldSeg"+ [ at @TestInt8 $ testElt i8+ , at @TestInt16 $ testElt i16+ , at @TestInt32 $ testElt i32+ , at @TestInt64 $ testElt i64+ , at @TestWord8 $ testElt w8+ , at @TestWord16 $ testElt w16+ , at @TestWord32 $ testElt w32+ , at @TestWord64 $ testElt w64+ , at @TestFloat $ testElt f32+ , at @TestDouble $ testElt f64+ ]+ where+ testElt :: forall a. (P.Num a, P.Ord a , A.Num a, A.Ord a , Similar a, Show a)+ => Gen a+ -> TestTree+ testElt e =+ testGroup (show (eltR @a))+ [ testDim dim1+ , testDim dim2+ , testDim dim3+ ]+ where+ testDim+ :: forall sh. (Shape sh, Show sh, P.Eq sh)+ => Gen (sh:.Int)+ -> TestTree+ testDim sh =+ testGroup ("DIM" P.++ show (rank @(sh:.Int)))+ [+ testProperty "sum" $ test_segmented_sum runN sh (pure 0) e+ , testProperty "non-neutral sum" $ test_segmented_sum runN sh e e+ , testProperty "minimum" $ test_segmented_minimum runN sh e+ , testProperty "maximum" $ test_segmented_maximum runN sh e+ ]+++scalar :: Elt e => e -> Scalar e+scalar x = fromFunction Z (const x)++{-# NOINLINE test_sum #-}+test_sum+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Num e, A.Num e)+ => RunN+ -> Gen (sh:.Int)+ -> Gen e+ -> Gen e+ -> Property+test_sum runN dim z e =+ property $ do+ x <- forAll z+ sh <- forAll dim+ xs <- forAll (array sh e)+ let !go = runN (\v -> A.fold (+) (the v)) in go (scalar x) xs ~~~ foldRef (+) x xs++{-# NOINLINE test_mss #-}+test_mss+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Num e, P.Ord e, A.Num e, A.Ord e)+ => RunN+ -> Gen (sh:.Int)+ -> Gen e+ -> Property+test_mss runN dim e =+ property $ do+ sh <- forAll (dim `except` \(_:.v) -> v P.== 0)+ xs <- forAll (array sh e)+ let !go = runN maximumSegmentSum in go xs ~~~ maximumSegmentSumRef xs++{-# NOINLINE test_minimum #-}+test_minimum+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Ord e, A.Ord e)+ => RunN+ -> Gen (sh:.Int)+ -> Gen e+ -> Property+test_minimum runN dim e =+ property $ do+ sh <- forAll (dim `except` \(_:.v) -> v P.== 0)+ xs <- forAll (array sh e)+ let !go = runN A.minimum in go xs ~~~ fold1Ref P.min xs++{-# NOINLINE test_maximum #-}+test_maximum+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Ord e, A.Ord e)+ => RunN+ -> Gen (sh:.Int)+ -> Gen e+ -> Property+test_maximum runN dim e =+ property $ do+ sh <- forAll (dim `except` \(_:.v) -> v P.== 0)+ xs <- forAll (array sh e)+ let !go = runN A.maximum in go xs ~~~ fold1Ref P.max xs++{-# NOINLINE test_segmented_sum #-}+test_segmented_sum+ :: forall sh e. (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Num e, A.Num e)+ => RunN+ -> Gen (sh:.Int)+ -> Gen e+ -> Gen e+ -> Property+test_segmented_sum runN dim z e =+ property $ do+ x <- forAll z+ sh:.n1 <- forAll dim+ n2 <- forAll (Gen.int (Range.linear 0 64))+ n <- pure (P.min n1 n2) -- don't generate too many segments+ seg <- forAll (array (Z:.n) (Gen.int (Range.linear 0 (128 `quot` 2 P.^ (rank @sh)))))+ xs <- forAll (array (sh:.P.sum (toList seg)) e)+ let !go = runN (\v -> A.foldSeg (+) (the v)) in go (scalar x) xs seg ~~~ foldSegRef (+) x xs seg++{-# NOINLINE test_segmented_minimum #-}+test_segmented_minimum+ :: forall sh e. (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Ord e, A.Ord e)+ => RunN+ -> Gen (sh:.Int)+ -> Gen e+ -> Property+test_segmented_minimum runN dim e =+ property $ do+ sh:.n1 <- forAll dim+ n2 <- forAll (Gen.int (Range.linear 0 64))+ n <- pure (P.min n1 n2) -- don't generate too many segments+ seg <- forAll (array (Z:.n) (Gen.int (Range.linear 1 (128 `quot` 2 P.^ (rank @sh)))))+ xs <- forAll (array (sh:.P.sum (toList seg)) e)+ let !go = runN (A.fold1Seg A.min) in go xs seg ~~~ fold1SegRef P.min xs seg++{-# NOINLINE test_segmented_maximum #-}+test_segmented_maximum+ :: forall sh e. (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Ord e, A.Ord e)+ => RunN+ -> Gen (sh:.Int)+ -> Gen e+ -> Property+test_segmented_maximum runN dim e =+ property $ do+ sh:.n1 <- forAll dim+ n2 <- forAll (Gen.int (Range.linear 0 64))+ n <- pure (P.min n1 n2) -- don't generate too many segments+ seg <- forAll (array (Z:.n) (Gen.int (Range.linear 1 (128 `quot` 2 P.^ (rank @sh)))))+ xs <- forAll (array (sh:.P.sum (toList seg)) e)+ let !go = runN (A.fold1Seg A.max) in go xs seg ~~~ fold1SegRef P.max xs seg+++-- Reference implementation+-- ------------------------++foldRef+ :: (Shape sh, Elt e)+ => (e -> e -> e)+ -> e+ -> Array (sh :. Int) e+ -> Array sh e+foldRef f z arr =+ let (sh :. n) = arrayShape arr+ in fromList sh [ foldl f z sub | sub <- splitEvery n (toList arr) ]++fold1Ref+ :: (Shape sh, Elt e)+ => (e -> e -> e)+ -> Array (sh :. Int) e+ -> Array sh e+fold1Ref f arr =+ let (sh :. n) = arrayShape arr+ in fromList sh [ foldl1 f sub | sub <- splitEvery n (toList arr) ]++foldSegRef+ :: (Shape sh, Elt e)+ => (e -> e -> e)+ -> e+ -> Array (sh :. Int) e+ -> Segments Int+ -> Array (sh :. Int) e+foldSegRef f z arr seg =+ let+ (sh :. n) = arrayShape arr+ (Z :. sz) = arrayShape seg+ seg' = toList seg+ arr' = [ foldl f z sec | sub <- splitEvery n (toList arr)+ , sec <- splitPlaces seg' sub ]+ in+ fromList (sh :. sz) arr'++fold1SegRef+ :: (Shape sh, Elt e)+ => (e -> e -> e)+ -> Array (sh :. Int) e+ -> Segments Int+ -> Array (sh :. Int) e+fold1SegRef f arr seg =+ let+ (sh :. n) = arrayShape arr+ (Z :. sz) = arrayShape seg+ seg' = toList seg+ arr' = [ foldl1 f sec | sub <- splitEvery n (toList arr)+ , sec <- splitPlaces seg' sub ]+ in+ fromList (sh :. sz) arr'++maximumSegmentSum+ :: forall sh e. (Shape sh, A.Num e, A.Ord e)+ => Acc (Array (sh :. Int) e)+ -> Acc (Array sh e)+maximumSegmentSum+ = A.map (\v -> let (x,_,_,_) = unlift v :: (Exp e, Exp e, Exp e, Exp e) in x)+ . A.fold1 f+ . A.map g+ where+ f :: (A.Num a, A.Ord a) => Exp (a,a,a,a) -> Exp (a,a,a,a) -> Exp (a,a,a,a)+ f x y =+ let (mssx, misx, mcsx, tsx) = unlift x+ (mssy, misy, mcsy, tsy) = unlift y+ in+ lift ( mssx `A.max` (mssy `A.max` (mcsx+misy))+ , misx `A.max` (tsx+misy)+ , mcsy `A.max` (mcsx+tsy)+ , tsx+tsy+ )++ g :: (A.Num a, A.Ord a) => Exp a -> Exp (a,a,a,a)+ g x = let y = A.max x 0+ in lift (y,y,y,x)++maximumSegmentSumRef+ :: (P.Num e, P.Ord e, Shape sh, Elt e)+ => Array (sh :. Int) e+ -> Array sh e+maximumSegmentSumRef arr = fromList sh [ go 0 0 sub | sub <- splitEvery n (toList arr) ]+ where+ sh :. n = arrayShape arr+ --+ go _ v [] = v+ go u v (x:xs) =+ let u' = 0 `P.max` (u+x)+ v' = v `P.max` u'+ in+ go u' v' xs+
+ src/Data/Array/Accelerate/Test/NoFib/Prelude/Map.hs view
@@ -0,0 +1,485 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE MonoLocalBinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeOperators #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Prelude.Map+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Test.NoFib.Prelude.Map (++ test_map++) where++import Data.Bits as P+import Prelude as P++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Data.Bits as A+import Data.Array.Accelerate.Sugar.Array as S+import Data.Array.Accelerate.Sugar.Elt as S+import Data.Array.Accelerate.Sugar.Shape as S+import Data.Array.Accelerate.Test.NoFib.Base+import Data.Array.Accelerate.Test.NoFib.Config+import Data.Array.Accelerate.Test.Similar++import Hedgehog+import qualified Hedgehog.Gen as Gen+import qualified Hedgehog.Range as Range++import Test.Tasty+import Test.Tasty.Hedgehog+++test_map :: RunN -> TestTree+test_map runN =+ testGroup "map"+ [ at @TestInt8 $ testIntegralElt i8+ , at @TestInt16 $ testIntegralElt i16+ , at @TestInt32 $ testIntegralElt i32+ , at @TestInt64 $ testIntegralElt i64+ , at @TestWord8 $ testIntegralElt w8+ , at @TestWord16 $ testIntegralElt w16+ , at @TestWord32 $ testIntegralElt w32+ , at @TestWord64 $ testIntegralElt w64+ , at @TestHalf $ testFloatingElt (Gen.realFloat :: Range Half -> Gen Half)+ , at @TestFloat $ testFloatingElt Gen.float+ , at @TestDouble $ testFloatingElt Gen.double+ ]+ where+ testIntegralElt+ :: forall a. ( P.Integral a, P.FiniteBits a+ , A.Integral a, A.FiniteBits a+ , A.FromIntegral a Double+ , Similar a, Show a )+ => Gen a+ -> TestTree+ testIntegralElt e =+ testGroup (show (eltR @a))+ [ testDim dim0+ , testDim dim1+ , testDim dim2+ ]+ where+ testDim+ :: forall sh. (Shape sh, Show sh, P.Eq sh)+ => Gen sh+ -> TestTree+ testDim sh =+ testGroup ("DIM" P.++ show (rank @sh))+ [ -- operators on Num+ testProperty "neg" $ test_negate runN sh e+ , testProperty "abs" $ test_abs runN sh e+ , testProperty "signum" $ test_signum runN sh e++ -- operators on Integral & Bits+ , testProperty "complement" $ test_complement runN sh e+ , testProperty "popCount" $ test_popCount runN sh e+ , testProperty "countLeadingZeros" $ test_countLeadingZeros runN sh e+ , testProperty "countTrailingZeros" $ test_countTrailingZeros runN sh e++ -- conversions+ , testProperty "fromIntegral" $ test_fromIntegral runN sh e+ ]++ testFloatingElt+ :: forall a. (P.RealFloat a, A.Floating a, A.RealFrac a, Similar a, Show a)+ => (Range a -> Gen a)+ -> TestTree+ testFloatingElt e =+ testGroup (show (eltR @a))+ [ testDim dim0+ , testDim dim1+ , testDim dim2+ ]+ where+ testDim+ :: forall sh. (Shape sh, Show sh, P.Eq sh)+ => Gen sh+ -> TestTree+ testDim sh =+ testGroup ("DIM" P.++ show (rank @sh))+ [ -- operators on Num+ testProperty "neg" $ test_negate runN sh (fullrange e)+ , testProperty "abs" $ test_abs runN sh (fullrange e)+ , testProperty "signum" $ test_abs runN sh (fullrange e)++ -- operators on Fractional, Floating, RealFrac & RealFloat+ , testProperty "recip" $ test_recip runN sh (fullrange e)+ , testProperty "sin" $ test_sin runN sh (fullrange e)+ , testProperty "cos" $ test_cos runN sh (fullrange e)+ , testProperty "tan" $ test_tan runN sh (fullrange e `except` \v -> cos v ~= 0)+ , testProperty "asin" $ test_asin runN sh (e (Range.linearFracFrom 0 (-1) 1))+ , testProperty "acos" $ test_acos runN sh (e (Range.linearFracFrom 0 (-1) 1))+ , testProperty "atan" $ test_atan runN sh (fullrange e)+ , testProperty "asinh" $ test_asinh runN sh (e (Range.linearFracFrom 0 (-log_flt_max) (log_flt_max)))+ , testProperty "acosh" $ test_acosh runN sh (e (Range.linearFrac 1 (sqrt flt_max)))+ , testProperty "atanh" $ test_atanh runN sh (e (Range.linearFracFrom 0 (-1) 1))+ , testProperty "exp" $ test_exp runN sh (fullrange e)+ , testProperty "sqrt" $ test_sqrt runN sh (e (Range.linearFrac 0 flt_max))+ , testProperty "log" $ test_log runN sh (e (Range.linearFrac 0 flt_max) `except` \v -> v P.== 0)+ , testProperty "truncate" $ test_truncate runN sh (e (Range.linearFracFrom 0 (P.fromIntegral (minBound :: Int)) (P.fromIntegral (maxBound :: Int))))+ , testProperty "round" $ test_round runN sh (e (Range.linearFracFrom 0 (P.fromIntegral (minBound :: Int)) (P.fromIntegral (maxBound :: Int))))+ , testProperty "floor" $ test_floor runN sh (e (Range.linearFracFrom 0 (P.fromIntegral (minBound :: Int)) (P.fromIntegral (maxBound :: Int))))+ , testProperty "ceiling" $ test_ceiling runN sh (e (Range.linearFracFrom 0 (P.fromIntegral (minBound :: Int)) (P.fromIntegral (maxBound :: Int))))+ ]++ -- NOTE: [asinh and acosh]+ --+ -- GHC uses an approximation for asinh and acosh which gives incorrect+ -- answers for extremely large values. I guess I should submit a bug+ -- report for that, but "for now" just test with a reduced range.++ fullrange :: P.RealFloat e => (Range e -> Gen e) -> Gen e+ fullrange gen = gen (Range.linearFracFrom 0 (-flt_max) flt_max)+++{-# NOINLINE test_negate #-}+test_negate+ :: (Shape sh, Show sh, Similar e, Show e, A.Num e, P.Num e, P.Eq sh)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_negate runN dim e =+ property $ do+ sh <- forAll dim+ xs <- forAll (array sh e)+ let !go = runN (A.map negate) in go xs ~~~ mapRef negate xs++{-# NOINLINE test_abs #-}+test_abs+ :: (Shape sh, Show sh, Similar e, Show e, A.Num e, P.Num e, P.Eq sh)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_abs runN dim e =+ property $ do+ sh <- forAll dim+ xs <- forAll (array sh e)+ let !go = runN (A.map abs) in go xs ~~~ mapRef abs xs++{-# NOINLINE test_signum #-}+test_signum+ :: (Shape sh, Show sh, Similar e, Show e, A.Num e, P.Num e, P.Eq sh)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_signum runN dim e =+ property $ do+ sh <- forAll dim+ xs <- forAll (array sh e)+ let !go = runN (A.map signum) in go xs ~~~ mapRef signum xs++{-# NOINLINE test_complement #-}+test_complement+ :: (Shape sh, Show sh, Similar e, Show e, A.Bits e, P.Bits e, P.Eq sh)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_complement runN dim e =+ property $ do+ sh <- forAll dim+ xs <- forAll (array sh e)+ let !go = runN (A.map A.complement) in go xs ~~~ mapRef P.complement xs++{-# NOINLINE test_popCount #-}+test_popCount+ :: (Shape sh, Show sh, Show e, A.Bits e, P.Bits e, P.Eq sh)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_popCount runN dim e =+ property $ do+ sh <- forAll dim+ xs <- forAll (array sh e)+ let !go = runN (A.map A.popCount) in go xs ~~~ mapRef P.popCount xs++{-# NOINLINE test_countLeadingZeros #-}+test_countLeadingZeros+ :: (Shape sh, Show sh, Show e, A.FiniteBits e, P.FiniteBits e, P.Eq sh)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_countLeadingZeros runN dim e =+ property $ do+ sh <- forAll dim+ xs <- forAll (array sh e)+ let !go = runN (A.map A.countLeadingZeros) in go xs ~~~ mapRef countLeadingZerosRef xs++{-# NOINLINE test_countTrailingZeros #-}+test_countTrailingZeros+ :: (Shape sh, Show sh, Show e, A.FiniteBits e, P.FiniteBits e, P.Eq sh)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_countTrailingZeros runN dim e =+ property $ do+ sh <- forAll dim+ xs <- forAll (array sh e)+ let !go = runN (A.map A.countTrailingZeros) in go xs ~~~ mapRef countTrailingZerosRef xs++{-# NOINLINE test_fromIntegral #-}+test_fromIntegral+ :: forall sh e. (Shape sh, Show sh, Show e, P.Eq sh, P.Integral e, A.Integral e, A.FromIntegral e Double)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_fromIntegral runN dim e =+ property $ do+ sh <- forAll dim+ xs <- forAll (array sh e)+ let !go = runN (A.map A.fromIntegral) in go xs ~~~ mapRef (P.fromIntegral :: e -> Double) xs++{-# NOINLINE test_recip #-}+test_recip+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Fractional e, A.Fractional e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_recip runN dim e =+ property $ do+ sh <- forAll dim+ xs <- forAll (array sh e)+ let !go = runN (A.map recip) in go xs ~~~ mapRef recip xs++{-# NOINLINE test_sin #-}+test_sin+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Floating e, A.Floating e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_sin runN dim e =+ property $ do+ sh <- forAll dim+ xs <- forAll (array sh e)+ let !go = runN (A.map sin) in go xs ~~~ mapRef sin xs++{-# NOINLINE test_cos #-}+test_cos+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Floating e, A.Floating e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_cos runN dim e =+ property $ do+ sh <- forAll dim+ xs <- forAll (array sh e)+ let !go = runN (A.map cos) in go xs ~~~ mapRef cos xs++{-# NOINLINE test_tan #-}+test_tan+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Floating e, A.Floating e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_tan runN dim e =+ property $ do+ sh <- forAll dim+ xs <- forAll (array sh e)+ let !go = runN (A.map tan) in go xs ~~~ mapRef tan xs++{-# NOINLINE test_asin #-}+test_asin+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Floating e, A.Floating e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_asin runN dim e =+ property $ do+ sh <- forAll dim+ xs <- forAll (array sh e)+ let !go = runN (A.map asin) in go xs ~~~ mapRef asin xs++{-# NOINLINE test_acos #-}+test_acos+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Floating e, A.Floating e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_acos runN dim e =+ property $ do+ sh <- forAll dim+ xs <- forAll (array sh e)+ let !go = runN (A.map acos) in go xs ~~~ mapRef acos xs++{-# NOINLINE test_atan #-}+test_atan+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Floating e, A.Floating e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_atan runN dim e =+ property $ do+ sh <- forAll dim+ xs <- forAll (array sh e)+ let !go = runN (A.map atan) in go xs ~~~ mapRef atan xs++{-# NOINLINE test_asinh #-}+test_asinh+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Floating e, A.Floating e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_asinh runN dim e =+ property $ do+ sh <- forAll dim+ xs <- forAll (array sh e)+ let !go = runN (A.map asinh) in go xs ~~~ mapRef asinh xs++{-# NOINLINE test_acosh #-}+test_acosh+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Floating e, A.Floating e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_acosh runN dim e =+ property $ do+ sh <- forAll dim+ xs <- forAll (array sh e)+ let !go = runN (A.map acosh) in go xs ~~~ mapRef acosh xs++{-# NOINLINE test_atanh #-}+test_atanh+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Floating e, A.Floating e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_atanh runN dim e =+ property $ do+ sh <- forAll dim+ xs <- forAll (array sh e)+ let !go = runN (A.map atanh) in go xs ~~~ mapRef atanh xs++{-# NOINLINE test_exp #-}+test_exp+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Floating e, A.Floating e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_exp runN dim e =+ property $ do+ sh <- forAll dim+ xs <- forAll (array sh e)+ let !go = runN (A.map exp) in go xs ~~~ mapRef exp xs++{-# NOINLINE test_sqrt #-}+test_sqrt+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Floating e, A.Floating e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_sqrt runN dim e =+ property $ do+ sh <- forAll dim+ xs <- forAll (array sh e)+ let !go = runN (A.map sqrt) in go xs ~~~ mapRef sqrt xs++{-# NOINLINE test_log #-}+test_log+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Floating e, A.Floating e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_log runN dim e =+ property $ do+ sh <- forAll dim+ xs <- forAll (array sh e)+ let !go = runN (A.map log) in go xs ~~~ mapRef log xs++{-# NOINLINE test_truncate #-}+test_truncate+ :: forall sh e. (Shape sh, Show sh, Show e, P.Eq sh, P.RealFrac e, A.RealFrac e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_truncate runN dim e =+ property $ do+ sh <- forAll dim+ xs <- forAll (array sh e)+ let !go = runN (A.map A.truncate) in go xs ~~~ mapRef (P.truncate :: e -> Int) xs++{-# NOINLINE test_round #-}+test_round+ :: forall sh e. (Shape sh, Show sh, Show e, P.Eq sh, P.RealFrac e, A.RealFrac e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_round runN dim e =+ property $ do+ sh <- forAll dim+ xs <- forAll (array sh e)+ let !go = runN (A.map A.round) in go xs ~~~ mapRef (P.round :: e -> Int) xs++{-# NOINLINE test_floor #-}+test_floor+ :: forall sh e. (Shape sh, Show sh, Show e, P.Eq sh, P.RealFrac e, A.RealFrac e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_floor runN dim e =+ property $ do+ sh <- forAll dim+ xs <- forAll (array sh e)+ let !go = runN (A.map A.floor) in go xs ~~~ mapRef (P.floor :: e -> Int) xs++{-# NOINLINE test_ceiling #-}+test_ceiling+ :: forall sh e. (Shape sh, Show sh, Show e, P.Eq sh, P.RealFrac e, A.RealFrac e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_ceiling runN dim e =+ property $ do+ sh <- forAll dim+ xs <- forAll (array sh e)+ let !go = runN (A.map A.ceiling) in go xs ~~~ mapRef (P.ceiling :: e -> Int) xs+++-- Reference Implementation+-- ------------------------++mapRef :: (Shape sh, Elt a, Elt b) => (a -> b) -> Array sh a -> Array sh b+mapRef f xs = fromFunction (arrayShape xs) (\ix -> f (xs S.! ix))++countLeadingZerosRef :: P.FiniteBits a => a -> Int+countLeadingZerosRef = P.countLeadingZeros++countTrailingZerosRef :: P.FiniteBits a => a -> Int+countTrailingZerosRef = P.countTrailingZeros+
+ src/Data/Array/Accelerate/Test/NoFib/Prelude/Permute.hs view
@@ -0,0 +1,180 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeOperators #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Prelude.Permute+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Test.NoFib.Prelude.Permute (++ test_permute++) where++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Array.Data+import Data.Array.Accelerate.Sugar.Array as S+import Data.Array.Accelerate.Sugar.Elt as S+import Data.Array.Accelerate.Sugar.Shape as S+import Data.Array.Accelerate.Test.NoFib.Base+import Data.Array.Accelerate.Test.NoFib.Config+import Data.Array.Accelerate.Test.Similar+import qualified Data.Array.Accelerate.Representation.Array as R++import Hedgehog+import qualified Hedgehog.Gen as Gen+import qualified Hedgehog.Range as Range++import Test.Tasty+import Test.Tasty.Hedgehog++import System.IO.Unsafe+import Prelude as P+import qualified Data.Set as Set+++test_permute :: RunN -> TestTree+test_permute runN =+ testGroup "permute"+ [ at @TestInt8 $ testElt i8+ , at @TestInt16 $ testElt i16+ , at @TestInt32 $ testElt i32+ , at @TestInt64 $ testElt i64+ , at @TestWord8 $ testElt w8+ , at @TestWord16 $ testElt w16+ , at @TestWord32 $ testElt w32+ , at @TestWord64 $ testElt w64+ , at @TestHalf $ testElt f16+ , at @TestFloat $ testElt f32+ , at @TestDouble $ testElt f64+ ]+ where+ testElt+ :: forall a. (Similar a, P.Num a, A.Num a, Show a)+ => Gen a+ -> TestTree+ testElt e =+ testGroup (show (eltR @a))+ [ testDim dim1+ , testDim dim2+ , testDim dim3+ ]+ where+ testDim+ :: forall sh. (Shape sh, Show sh)+ => Gen (sh:.Int)+ -> TestTree+ testDim sh =+ testGroup ("DIM" P.++ show (rank @(sh:.Int)))+ [+ testProperty "scatter->DIM1" $ test_scatter runN sh dim1 e+ , testProperty "scatter->DIM2" $ test_scatter runN sh dim2 e+ , testProperty "scatter->DIM3" $ test_scatter runN sh dim3 e+ , testProperty "accumulate->DIM1" $ test_accumulate runN sh dim1 e+ , testProperty "accumulate->DIM2" $ test_accumulate runN sh dim2 e+ , testProperty "accumulate->DIM3" $ test_accumulate runN sh dim3 e+ ]+++{-# NOINLINE test_scatter #-}+test_scatter+ :: forall sh sh' e. (Shape sh, Shape sh', Show sh, Show sh', P.Eq sh', Similar e, Elt e, Show e)+ => RunN+ -> Gen sh+ -> Gen sh'+ -> Gen e+ -> Property+test_scatter runN dim dim' e =+ property $ do+ sh <- forAll dim+ sh' <- forAll (dim' `except` \v -> S.size v P.== 0)+ let+ n = S.size sh+ n' = S.size sh'+ --+ shfl seen i+ | i P.>= n = pure []+ | otherwise = do+ t <- Gen.choice [ pure (-1)+ , Gen.int (Range.linear 0 (n'-1))+ ]+ ts <- shfl (Set.insert t seen) (i+1)+ --+ case Set.member t seen of+ True -> pure (Nothing : ts)+ False -> pure (Just (S.fromIndex sh' t) : ts)+ --+ def <- forAll (array sh' e)+ new <- forAll (array sh e)+ ix <- forAll (fromList sh P.<$> shfl (Set.singleton (-1)) 0)+ --+ let !go = runN $ \i d v -> A.permute const d (i A.!) v+ go ix def new ~~~ permuteRef const def (ix S.!) new+++{-# NOINLINE test_accumulate #-}+test_accumulate+ :: (Shape sh, Shape sh', Show sh, Show sh', P.Eq sh', Similar e, P.Num e, A.Num e, Show e)+ => RunN+ -> Gen sh+ -> Gen sh'+ -> Gen e+ -> Property+test_accumulate runN dim dim' e =+ property $ do+ sh <- forAll dim+ sh' <- forAll (dim' `except` \v -> S.size v P.== 0)+ let+ n' = S.size sh'+ def = S.fromFunction sh' (const 0)+ --+ xs <- forAll (array sh e)+ ix <- forAll (array sh (Gen.choice [ pure Nothing+ , Just . S.fromIndex sh' P.<$> Gen.int (Range.linear 0 (n'-1))+ ]))+ let !go = runN $ \i d v -> A.permute (+) d (i A.!) v+ go ix def xs ~~~ permuteRef (+) def (ix S.!) xs+++permuteRef+ :: forall sh sh' e. (Shape sh, Shape sh', P.Eq sh', Elt e)+ => (e -> e -> e)+ -> Array sh' e+ -> (sh -> Maybe sh')+ -> Array sh e+ -> Array sh' e+permuteRef f def@(Array (R.Array _ aold)) p arr@(Array (R.Array _ anew)) =+ unsafePerformIO $ do+ let+ tp = S.eltR @e+ sh = S.shape arr+ sh' = S.shape def+ n = S.size sh+ --+ go !i+ | i P.>= n = pure ()+ | otherwise = do+ let ix = S.fromIndex sh i+ case p ix of+ Nothing -> pure ()+ Just ix' -> do+ let i' = S.toIndex sh' ix'+ x <- toElt P.<$> readArrayData tp anew i+ x' <- toElt P.<$> readArrayData tp aold i'+ writeArrayData tp aold i' (fromElt (f x x'))+ --+ go (i+1)+ --+ go 0+ pure def+
+ src/Data/Array/Accelerate/Test/NoFib/Prelude/SIMD.hs view
@@ -0,0 +1,243 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Prelude.SIMD+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Test.NoFib.Prelude.SIMD (++ test_simd,++) where++import Lens.Micro ( _1, _2, _3, _4 )+import Lens.Micro.Extras ( view )+import Prelude as P++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Sugar.Array as S+import Data.Array.Accelerate.Sugar.Elt as S+import Data.Array.Accelerate.Sugar.Shape as S+import Data.Array.Accelerate.Test.NoFib.Base+import Data.Array.Accelerate.Test.NoFib.Config+import Data.Primitive.Vec+import Data.Primitive.Types++import Hedgehog+import qualified Hedgehog.Gen as Gen++import Test.Tasty+import Test.Tasty.Hedgehog+++test_simd :: RunN -> TestTree+test_simd runN =+ testGroup "simd"+ [ at @TestInt8 $ testElt i8+ , at @TestInt16 $ testElt i16+ , at @TestInt32 $ testElt i32+ , at @TestInt64 $ testElt i64+ , at @TestWord8 $ testElt w8+ , at @TestWord16 $ testElt w16+ , at @TestWord32 $ testElt w32+ , at @TestWord64 $ testElt w64+ , at @TestHalf $ testElt f16+ , at @TestFloat $ testElt f32+ , at @TestDouble $ testElt f64+ ]+ where+ testElt :: forall e. (VecElt e, P.Eq e, Show e)+ => Gen e+ -> TestTree+ testElt e =+ testGroup (show (eltR @e))+ [ testExtract e+ , testInject e+ ]++ testExtract :: forall e. (VecElt e, P.Eq e, Show e)+ => Gen e+ -> TestTree+ testExtract e =+ testGroup "extract"+ [ testProperty "V2" $ test_extract_v2 runN dim1 e+ , testProperty "V3" $ test_extract_v3 runN dim1 e+ , testProperty "V4" $ test_extract_v4 runN dim1 e+ ]++ testInject :: forall e. (VecElt e, P.Eq e, Show e)+ => Gen e+ -> TestTree+ testInject e =+ testGroup "inject"+ [ testProperty "V2" $ test_inject_v2 runN dim1 e+ , testProperty "V3" $ test_inject_v3 runN dim1 e+ , testProperty "V4" $ test_inject_v4 runN dim1 e+ ]+++{-# NOINLINE test_extract_v2 #-}+test_extract_v2+ :: (Shape sh, Show sh, Show e, VecElt e, P.Eq e, P.Eq sh)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_extract_v2 runN dim e =+ property $ do+ sh <- forAll dim+ xs <- forAll (array sh (v2 e))+ (_l,_m) <- P.snd P.<$> forAllWith P.fst (Gen.element [("_1",(_1,_1)), ("_2",(_2,_2))])+ let !go = runN (A.map (view _m . unpackVec2')) in go xs === mapRef (view _l . unpackVec2) xs++{-# NOINLINE test_extract_v3 #-}+test_extract_v3+ :: (Shape sh, Show sh, Show e, VecElt e, P.Eq e, P.Eq sh)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_extract_v3 runN dim e =+ property $ do+ sh <- forAll dim+ xs <- forAll (array sh (v3 e))+ (_l,_m) <- P.snd P.<$> forAllWith P.fst (Gen.element [("_1",(_1,_1)), ("_2",(_2,_2)), ("_3",(_3,_3))])+ let !go = runN (A.map (view _m . unpackVec3')) in go xs === mapRef (view _l . unpackVec3) xs++{-# NOINLINE test_extract_v4 #-}+test_extract_v4+ :: (Shape sh, Show sh, Show e, VecElt e, P.Eq e, P.Eq sh)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_extract_v4 runN dim e =+ property $ do+ sh <- forAll dim+ xs <- forAll (array sh (v4 e))+ (_l,_m) <- P.snd P.<$> forAllWith P.fst (Gen.element [("_1",(_1,_1)), ("_2",(_2,_2)), ("_3",(_3,_3)), ("_4",(_4,_4))])+ let !go = runN (A.map (view _m . unpackVec4')) in go xs === mapRef (view _l . unpackVec4) xs++{-# NOINLINE test_inject_v2 #-}+test_inject_v2+ :: (Shape sh, Show sh, Show e, VecElt e, P.Eq e, P.Eq sh)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_inject_v2 runN dim e =+ property $ do+ sh1 <- forAll dim+ sh2 <- forAll dim+ xs <- forAll (array sh1 e)+ ys <- forAll (array sh2 e)+ let !go = runN (A.zipWith A.V2) in go xs ys === zipWithRef Vec2 xs ys++{-# NOINLINE test_inject_v3 #-}+test_inject_v3+ :: (Shape sh, Show sh, Show e, VecElt e, P.Eq e, P.Eq sh)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_inject_v3 runN dim e =+ property $ do+ sh1 <- forAll dim+ sh2 <- forAll dim+ sh3 <- forAll dim+ xs <- forAll (array sh1 e)+ ys <- forAll (array sh2 e)+ zs <- forAll (array sh3 e)+ let !go = runN (A.zipWith3 A.V3) in go xs ys zs === zipWith3Ref Vec3 xs ys zs++{-# NOINLINE test_inject_v4 #-}+test_inject_v4+ :: (Shape sh, Show sh, Show e, VecElt e, P.Eq e, P.Eq sh)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_inject_v4 runN dim e =+ property $ do+ sh1 <- forAll dim+ sh2 <- forAll dim+ sh3 <- forAll dim+ sh4 <- forAll dim+ xs <- forAll (array sh1 e)+ ys <- forAll (array sh2 e)+ zs <- forAll (array sh3 e)+ ws <- forAll (array sh4 e)+ let !go = runN (A.zipWith4 A.V4) in go xs ys zs ws === zipWith4Ref Vec4 xs ys zs ws+++unpackVec2 :: Prim e => Vec2 e -> (e, e)+unpackVec2 (Vec2 a b) = (a, b)++unpackVec3 :: Prim e => Vec3 e -> (e, e, e)+unpackVec3 (Vec3 a b c) = (a, b, c)++unpackVec4 :: Prim e => Vec4 e -> (e, e, e, e)+unpackVec4 (Vec4 a b c d) = (a, b, c, d)++unpackVec2' :: VecElt e => Exp (Vec2 e) -> (Exp e, Exp e)+unpackVec2' (A.V2 a b) = (a, b)++unpackVec3' :: VecElt e => Exp (Vec3 e) -> (Exp e, Exp e, Exp e)+unpackVec3' (A.V3 a b c) = (a, b, c)++unpackVec4' :: VecElt e => Exp (Vec4 e) -> (Exp e, Exp e, Exp e, Exp e)+unpackVec4' (A.V4 a b c d) = (a, b, c, d)+++-- Reference Implementation+-- ------------------------++mapRef :: (Shape sh, Elt a, Elt b) => (a -> b) -> Array sh a -> Array sh b+mapRef f xs = fromFunction (arrayShape xs) (\ix -> f (xs S.! ix))++zipWithRef+ :: (Shape sh, Elt a, Elt b, Elt c)+ => (a -> b -> c)+ -> Array sh a+ -> Array sh b+ -> Array sh c+zipWithRef f xs ys =+ fromFunction+ (S.shape xs `S.intersect` S.shape ys)+ (\ix -> f (xs S.! ix) (ys S.! ix))++zipWith3Ref+ :: (Shape sh, Elt a, Elt b, Elt c, Elt d)+ => (a -> b -> c -> d)+ -> Array sh a+ -> Array sh b+ -> Array sh c+ -> Array sh d+zipWith3Ref f xs ys zs =+ fromFunction+ (S.shape xs `S.intersect` S.shape ys `S.intersect` S.shape zs)+ (\ix -> f (xs S.! ix) (ys S.! ix) (zs S.! ix))++zipWith4Ref+ :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e)+ => (a -> b -> c -> d -> e)+ -> Array sh a+ -> Array sh b+ -> Array sh c+ -> Array sh d+ -> Array sh e+zipWith4Ref f xs ys zs ws =+ fromFunction+ (S.shape xs `S.intersect` S.shape ys `S.intersect` S.shape zs `S.intersect` S.shape ws)+ (\ix -> f (xs S.! ix) (ys S.! ix) (zs S.! ix) (ws S.! ix))+
+ src/Data/Array/Accelerate/Test/NoFib/Prelude/Scan.hs view
@@ -0,0 +1,947 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeOperators #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Prelude.Scan+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Test.NoFib.Prelude.Scan (++ test_scanl, test_scanlSeg,+ test_scanl1, test_scanl1Seg,+ test_scanl', test_scanl'Seg,++ test_scanr, test_scanrSeg,+ test_scanr1, test_scanr1Seg,+ test_scanr', test_scanr'Seg,++) where++import Prelude as P++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Sugar.Elt as S+import Data.Array.Accelerate.Sugar.Shape as S+import Data.Array.Accelerate.Test.NoFib.Base+import Data.Array.Accelerate.Test.NoFib.Config+import Data.Array.Accelerate.Test.Similar++import Hedgehog+import qualified Hedgehog.Gen as Gen+import qualified Hedgehog.Range as Range++import Test.Tasty+import Test.Tasty.Hedgehog+++test_scanl :: RunN -> TestTree+test_scanl runN =+ testGroup "scanl"+ [ at @TestInt8 $ testElt i8+ , at @TestInt16 $ testElt i16+ , at @TestInt32 $ testElt i32+ , at @TestInt64 $ testElt i64+ , at @TestWord8 $ testElt w8+ , at @TestWord16 $ testElt w16+ , at @TestWord32 $ testElt w32+ , at @TestWord64 $ testElt w64+ , at @TestHalf $ testElt f16+ , at @TestFloat $ testElt f32+ , at @TestDouble $ testElt f64+ ]+ where+ testElt+ :: forall a. (P.Num a, P.Eq a, A.Num a, A.Eq a, Similar a, Show a)+ => Gen a+ -> TestTree+ testElt e =+ testGroup (show (eltR @a))+ [ testDim dim1+ , testDim dim2+ , testDim dim3+ ]+ where+ testDim+ :: forall sh. (Shape sh, Show sh, P.Eq sh)+ => Gen (sh:.Int)+ -> TestTree+ testDim sh =+ testGroup ("DIM" P.++ show (rank @(sh:.Int)))+ [ testProperty "sum" $ test_scanl_sum runN sh (pure 0) e+ , testProperty "non-neutral sum" $ test_scanl_sum runN sh e e+ , testProperty "non-commutative" $ test_scanl_interval runN sh e+ ]++test_scanl1 :: RunN -> TestTree+test_scanl1 runN =+ testGroup "scanl1"+ [ at @TestInt8 $ testElt i8+ , at @TestInt16 $ testElt i16+ , at @TestInt32 $ testElt i32+ , at @TestInt64 $ testElt i64+ , at @TestWord8 $ testElt w8+ , at @TestWord16 $ testElt w16+ , at @TestWord32 $ testElt w32+ , at @TestWord64 $ testElt w64+ , at @TestFloat $ testElt f32+ , at @TestDouble $ testElt f64+ ]+ where+ testElt :: forall a. (P.Num a, P.Eq a, A.Num a, A.Eq a, Similar a, Show a)+ => Gen a+ -> TestTree+ testElt e =+ testGroup (show (eltR @a))+ [ testDim dim1+ , testDim dim2+ , testDim dim3+ ]+ where+ testDim+ :: forall sh. (Shape sh, Show sh, P.Eq sh)+ => Gen (sh:.Int)+ -> TestTree+ testDim sh =+ testGroup ("DIM" P.++ show (rank @(sh:.Int)))+ [ testProperty "sum" $ test_scanl1_sum runN sh e+ , testProperty "non-commutative" $ test_scanl1_interval runN sh e+ ]++test_scanl' :: RunN -> TestTree+test_scanl' runN =+ testGroup "scanl'"+ [ at @TestInt8 $ testElt i8+ , at @TestInt16 $ testElt i16+ , at @TestInt32 $ testElt i32+ , at @TestInt64 $ testElt i64+ , at @TestWord8 $ testElt w8+ , at @TestWord16 $ testElt w16+ , at @TestWord32 $ testElt w32+ , at @TestWord64 $ testElt w64+ , at @TestFloat $ testElt f32+ , at @TestDouble $ testElt f64+ ]+ where+ testElt :: forall a. (P.Num a, P.Eq a, A.Num a, A.Eq a, Similar a, Show a)+ => Gen a+ -> TestTree+ testElt e =+ testGroup (show (eltR @a))+ [ testDim dim1+ , testDim dim2+ , testDim dim3+ ]+ where+ testDim+ :: forall sh. (Shape sh, Show sh, P.Eq sh)+ => Gen (sh:.Int)+ -> TestTree+ testDim sh =+ testGroup ("DIM" P.++ show (rank @(sh:.Int)))+ [ testProperty "sum" $ test_scanl'_sum runN sh (pure 0) e+ , testProperty "non-neutral sum" $ test_scanl'_sum runN sh e e+ , testProperty "non-commutative" $ test_scanl'_interval runN sh e+ ]++test_scanr :: RunN -> TestTree+test_scanr runN =+ testGroup "scanr"+ [ at @TestInt8 $ testElt i8+ , at @TestInt16 $ testElt i16+ , at @TestInt32 $ testElt i32+ , at @TestInt64 $ testElt i64+ , at @TestWord8 $ testElt w8+ , at @TestWord16 $ testElt w16+ , at @TestWord32 $ testElt w32+ , at @TestWord64 $ testElt w64+ , at @TestFloat $ testElt f32+ , at @TestDouble $ testElt f64+ ]+ where+ testElt :: forall a. (P.Num a, P.Eq a, A.Num a, A.Eq a, Similar a, Show a)+ => Gen a+ -> TestTree+ testElt e =+ testGroup (show (eltR @a))+ [ testDim dim1+ , testDim dim2+ , testDim dim3+ ]+ where+ testDim+ :: forall sh. (Shape sh, Show sh, P.Eq sh)+ => Gen (sh:.Int)+ -> TestTree+ testDim sh =+ testGroup ("DIM" P.++ show (rank @(sh:.Int)))+ [ testProperty "sum" $ test_scanr_sum runN sh (pure 0) e+ , testProperty "non-neutral sum" $ test_scanr_sum runN sh e e+ , testProperty "non-commutative" $ test_scanr_interval runN sh e+ ]++test_scanr1 :: RunN -> TestTree+test_scanr1 runN =+ testGroup "scanr1"+ [ at @TestInt8 $ testElt i8+ , at @TestInt16 $ testElt i16+ , at @TestInt32 $ testElt i32+ , at @TestInt64 $ testElt i64+ , at @TestWord8 $ testElt w8+ , at @TestWord16 $ testElt w16+ , at @TestWord32 $ testElt w32+ , at @TestWord64 $ testElt w64+ , at @TestFloat $ testElt f32+ , at @TestDouble $ testElt f64+ ]+ where+ testElt :: forall a. (P.Num a, P.Eq a, A.Num a, A.Eq a, Similar a, Show a)+ => Gen a+ -> TestTree+ testElt e =+ testGroup (show (eltR @a))+ [ testDim dim1+ , testDim dim2+ , testDim dim3+ ]+ where+ testDim+ :: forall sh. (Shape sh, Show sh, P.Eq sh)+ => Gen (sh:.Int)+ -> TestTree+ testDim sh =+ testGroup ("DIM" P.++ show (rank @(sh:.Int)))+ [ testProperty "sum" $ test_scanr1_sum runN sh e+ , testProperty "non-commutative" $ test_scanr1_interval runN sh e+ ]++test_scanr' :: RunN -> TestTree+test_scanr' runN =+ testGroup "scanr'"+ [ at @TestInt8 $ testElt i8+ , at @TestInt16 $ testElt i16+ , at @TestInt32 $ testElt i32+ , at @TestInt64 $ testElt i64+ , at @TestWord8 $ testElt w8+ , at @TestWord16 $ testElt w16+ , at @TestWord32 $ testElt w32+ , at @TestWord64 $ testElt w64+ , at @TestFloat $ testElt f32+ , at @TestDouble $ testElt f64+ ]+ where+ testElt :: forall a. (P.Num a, P.Eq a, A.Num a, A.Eq a, Similar a, Show a)+ => Gen a+ -> TestTree+ testElt e =+ testGroup (show (eltR @a))+ [ testDim dim1+ , testDim dim2+ , testDim dim3+ ]+ where+ testDim+ :: forall sh. (Shape sh, Show sh, P.Eq sh)+ => Gen (sh:.Int)+ -> TestTree+ testDim sh =+ testGroup ("DIM" P.++ show (rank @(sh:.Int)))+ [ testProperty "sum" $ test_scanr'_sum runN sh (pure 0) e+ , testProperty "non-neutral sum" $ test_scanr'_sum runN sh e e+ , testProperty "non-commutative" $ test_scanr'_interval runN sh e+ ]++test_scanlSeg :: RunN -> TestTree+test_scanlSeg runN =+ testGroup "scanlSeg"+ [ at @TestInt8 $ testElt i8+ , at @TestInt16 $ testElt i16+ , at @TestInt32 $ testElt i32+ , at @TestInt64 $ testElt i64+ , at @TestWord8 $ testElt w8+ , at @TestWord16 $ testElt w16+ , at @TestWord32 $ testElt w32+ , at @TestWord64 $ testElt w64+ , at @TestFloat $ testElt f32+ , at @TestDouble $ testElt f64+ ]+ where+ testElt :: forall a. (P.Num a, A.Num a, Similar a, Show a)+ => Gen a+ -> TestTree+ testElt e =+ testGroup (show (eltR @a))+ [ testDim dim1+ , testDim dim2+ , testDim dim3+ ]+ where+ testDim+ :: forall sh. (Shape sh, Slice sh, Show sh, P.Eq sh)+ => Gen (sh:.Int)+ -> TestTree+ testDim sh =+ testGroup ("DIM" P.++ show (rank @(sh:.Int)))+ [ testProperty "sum" $ test_scanlSeg_sum runN sh (pure 0) e+ , testProperty "non-neutral sum" $ test_scanlSeg_sum runN sh e e+ ]++test_scanl1Seg :: RunN -> TestTree+test_scanl1Seg runN =+ testGroup "scanl1Seg"+ [ at @TestInt8 $ testElt i8+ , at @TestInt16 $ testElt i16+ , at @TestInt32 $ testElt i32+ , at @TestInt64 $ testElt i64+ , at @TestWord8 $ testElt w8+ , at @TestWord16 $ testElt w16+ , at @TestWord32 $ testElt w32+ , at @TestWord64 $ testElt w64+ , at @TestFloat $ testElt f32+ , at @TestDouble $ testElt f64+ ]+ where+ testElt :: forall a. (P.Num a, A.Num a, Similar a, Show a)+ => Gen a+ -> TestTree+ testElt e =+ testGroup (show (eltR @a))+ [ testDim dim1+ , testDim dim2+ , testDim dim3+ ]+ where+ testDim+ :: forall sh. (Shape sh, Slice sh, Show sh, P.Eq sh)+ => Gen (sh:.Int)+ -> TestTree+ testDim sh =+ testGroup ("DIM" P.++ show (rank @(sh:.Int)))+ [ testProperty "sum" $ test_scanl1Seg_sum runN sh e+ ]++test_scanl'Seg :: RunN -> TestTree+test_scanl'Seg runN =+ testGroup "scanl'Seg"+ [ at @TestInt8 $ testElt i8+ , at @TestInt16 $ testElt i16+ , at @TestInt32 $ testElt i32+ , at @TestInt64 $ testElt i64+ , at @TestWord8 $ testElt w8+ , at @TestWord16 $ testElt w16+ , at @TestWord32 $ testElt w32+ , at @TestWord64 $ testElt w64+ , at @TestFloat $ testElt f32+ , at @TestDouble $ testElt f64+ ]+ where+ testElt :: forall a. (P.Num a, A.Num a, Similar a, Show a)+ => Gen a+ -> TestTree+ testElt e =+ testGroup (show (eltR @a))+ [ testDim dim1+ , testDim dim2+ , testDim dim3+ ]+ where+ testDim+ :: forall sh. (Shape sh, Slice sh, Show sh, P.Eq sh)+ => Gen (sh:.Int)+ -> TestTree+ testDim sh =+ testGroup ("DIM" P.++ show (rank @(sh:.Int)))+ [ testProperty "sum" $ test_scanl'Seg_sum runN sh (pure 0) e+ , testProperty "non-neutral sum" $ test_scanl'Seg_sum runN sh e e+ ]++test_scanrSeg :: RunN -> TestTree+test_scanrSeg runN =+ testGroup "scanrSeg"+ [ at @TestInt8 $ testElt i8+ , at @TestInt16 $ testElt i16+ , at @TestInt32 $ testElt i32+ , at @TestInt64 $ testElt i64+ , at @TestWord8 $ testElt w8+ , at @TestWord16 $ testElt w16+ , at @TestWord32 $ testElt w32+ , at @TestWord64 $ testElt w64+ , at @TestFloat $ testElt f32+ , at @TestDouble $ testElt f64+ ]+ where+ testElt :: forall a. (P.Num a, A.Num a, Similar a, Show a)+ => Gen a+ -> TestTree+ testElt e =+ testGroup (show (eltR @a))+ [ testDim dim1+ , testDim dim2+ , testDim dim3+ ]+ where+ testDim+ :: forall sh. (Shape sh, Slice sh, Show sh, P.Eq sh)+ => Gen (sh:.Int)+ -> TestTree+ testDim sh =+ testGroup ("DIM" P.++ show (rank @(sh:.Int)))+ [ testProperty "sum" $ test_scanrSeg_sum runN sh (pure 0) e+ , testProperty "non-neutral sum" $ test_scanrSeg_sum runN sh e e+ ]++test_scanr1Seg :: RunN -> TestTree+test_scanr1Seg runN =+ testGroup "scanr1Seg"+ [ at @TestInt8 $ testElt i8+ , at @TestInt16 $ testElt i16+ , at @TestInt32 $ testElt i32+ , at @TestInt64 $ testElt i64+ , at @TestWord8 $ testElt w8+ , at @TestWord16 $ testElt w16+ , at @TestWord32 $ testElt w32+ , at @TestWord64 $ testElt w64+ , at @TestFloat $ testElt f32+ , at @TestDouble $ testElt f64+ ]+ where+ testElt :: forall a. (P.Num a, A.Num a, Similar a, Show a)+ => Gen a+ -> TestTree+ testElt e =+ testGroup (show (eltR @a))+ [ testDim dim1+ , testDim dim2+ , testDim dim3+ ]+ where+ testDim+ :: forall sh. (Shape sh, Slice sh, Show sh, P.Eq sh)+ => Gen (sh:.Int)+ -> TestTree+ testDim sh =+ testGroup ("DIM" P.++ show (rank @(sh:.Int)))+ [ testProperty "sum" $ test_scanr1Seg_sum runN sh e+ ]++test_scanr'Seg :: RunN -> TestTree+test_scanr'Seg runN =+ testGroup "scanr'Seg"+ [ at @TestInt8 $ testElt i8+ , at @TestInt16 $ testElt i16+ , at @TestInt32 $ testElt i32+ , at @TestInt64 $ testElt i64+ , at @TestWord8 $ testElt w8+ , at @TestWord16 $ testElt w16+ , at @TestWord32 $ testElt w32+ , at @TestWord64 $ testElt w64+ , at @TestFloat $ testElt f32+ , at @TestDouble $ testElt f64+ ]+ where+ testElt :: forall a. (P.Num a, A.Num a, Similar a, Show a)+ => Gen a+ -> TestTree+ testElt e =+ testGroup (show (eltR @a))+ [ testDim dim1+ , testDim dim2+ , testDim dim3+ ]+ where+ testDim+ :: forall sh. (Shape sh, Slice sh, Show sh, P.Eq sh)+ => Gen (sh:.Int)+ -> TestTree+ testDim sh =+ testGroup ("DIM" P.++ show (rank @(sh:.Int)))+ [ testProperty "sum" $ test_scanr'Seg_sum runN sh (pure 0) e+ , testProperty "non-neutral sum" $ test_scanr'Seg_sum runN sh e e+ ]+++scalar :: Elt e => e -> Scalar e+scalar x = fromFunction Z (const x)++{-# NOINLINE test_scanl_sum #-}+test_scanl_sum+ :: (Shape sh, Show sh, Similar e, P.Eq sh, P.Num e, A.Num e, Show e)+ => RunN+ -> Gen (sh:.Int)+ -> Gen e+ -> Gen e+ -> Property+test_scanl_sum runN dim z e =+ property $ do+ x <- forAll z+ sh <- forAll dim+ arr <- forAll (array sh e)+ let !go = runN (\v -> A.scanl (+) (the v)) in go (scalar x) arr ~~~ scanlRef (+) x arr++{-# NOINLINE test_scanl1_sum #-}+test_scanl1_sum+ :: (Shape sh, Show sh, Similar e, P.Eq sh, P.Num e, A.Num e, Show e)+ => RunN+ -> Gen (sh:.Int)+ -> Gen e+ -> Property+test_scanl1_sum runN dim e =+ property $ do+ sh <- forAll dim+ arr <- forAll (array sh e)+ let !go = runN (A.scanl1 (+)) in go arr ~~~ scanl1Ref (+) arr++{-# NOINLINE test_scanl'_sum #-}+test_scanl'_sum+ :: (Shape sh, Show sh, Similar e, P.Eq sh, P.Num e, A.Num e, Show e)+ => RunN+ -> Gen (sh:.Int)+ -> Gen e+ -> Gen e+ -> Property+test_scanl'_sum runN dim z e =+ property $ do+ x <- forAll z+ sh <- forAll dim+ arr <- forAll (array sh e)+ let !go = runN (\v -> A.scanl' (+) (the v)) in go (scalar x) arr ~~~ scanl'Ref (+) x arr++{-# NOINLINE test_scanr_sum #-}+test_scanr_sum+ :: (Shape sh, Show sh, Similar e, P.Eq sh, P.Num e, A.Num e, Show e)+ => RunN+ -> Gen (sh:.Int)+ -> Gen e+ -> Gen e -> Property+test_scanr_sum runN dim z e =+ property $ do+ x <- forAll z+ sh <- forAll dim+ arr <- forAll (array sh e)+ let !go = runN (\v -> A.scanr (+) (the v)) in go (scalar x) arr ~~~ scanrRef (+) x arr++{-# NOINLINE test_scanr1_sum #-}+test_scanr1_sum+ :: (Shape sh, Show sh, Similar e, P.Eq sh, P.Num e, A.Num e, Show e)+ => RunN+ -> Gen (sh:.Int)+ -> Gen e+ -> Property+test_scanr1_sum runN dim e =+ property $ do+ sh <- forAll dim+ arr <- forAll (array sh e)+ let !go = runN (A.scanr1 (+)) in go arr ~~~ scanr1Ref (+) arr++{-# NOINLINE test_scanr'_sum #-}+test_scanr'_sum+ :: (Shape sh, Show sh, Similar e, P.Eq sh, P.Num e, A.Num e, Show e)+ => RunN+ -> Gen (sh:.Int)+ -> Gen e+ -> Gen e+ -> Property+test_scanr'_sum runN dim z e =+ property $ do+ x <- forAll z+ sh <- forAll dim+ arr <- forAll (array sh e)+ let !go = runN (\v -> A.scanr' (+) (the v)) in go (scalar x) arr ~~~ scanr'Ref (+) x arr++{-# NOINLINE test_scanl_interval #-}+test_scanl_interval+ :: (Shape sh, Show sh, Similar e, P.Eq sh, P.Eq e, P.Num e, A.Eq e, A.Num e, Show e)+ => RunN+ -> Gen (sh:.Int)+ -> Gen e+ -> Property+test_scanl_interval runN dim e =+ property $ do+ sh :. n <- forAll dim+ let arr = intervalArray sh n e+ let !go = runN (A.scanl iappend (constant one)) in go arr ~~~ scanlRef iappendRef one arr++{-# NOINLINE test_scanl1_interval #-}+test_scanl1_interval+ :: (Shape sh, Show sh, Similar e, P.Eq sh, P.Eq e, P.Num e, A.Eq e, A.Num e, Show e)+ => RunN+ -> Gen (sh:.Int)+ -> Gen e+ -> Property+test_scanl1_interval runN dim e =+ property $ do+ sh :. n <- forAll dim+ let arr = intervalArray sh n e+ let !go = runN (A.scanl1 iappend) in go arr ~~~ scanl1Ref iappendRef arr++{-# NOINLINE test_scanl'_interval #-}+test_scanl'_interval+ :: (Shape sh, Show sh, Similar e, P.Eq sh, P.Eq e, P.Num e, A.Eq e, A.Num e, Show e)+ => RunN+ -> Gen (sh:.Int)+ -> Gen e+ -> Property+test_scanl'_interval runN dim e =+ property $ do+ sh :. n <- forAll dim+ let arr = intervalArray sh n e+ let !go = runN (A.scanl' iappend (constant one)) in go arr ~~~ scanl'Ref iappendRef one arr++{-# NOINLINE test_scanr_interval #-}+test_scanr_interval+ :: (Shape sh, Show sh, Similar e, P.Eq sh, P.Eq e, P.Num e, A.Eq e, A.Num e, Show e)+ => RunN+ -> Gen (sh:.Int)+ -> Gen e+ -> Property+test_scanr_interval runN dim e =+ property $ do+ sh :. n <- forAll dim+ let arr = intervalArray sh n e+ let !go = runN (A.scanr iappend (constant one)) in go arr ~~~ scanrRef iappendRef one arr++{-# NOINLINE test_scanr1_interval #-}+test_scanr1_interval+ :: (Shape sh, Show sh, Similar e, P.Eq sh, P.Eq e, P.Num e, A.Eq e, A.Num e, Show e)+ => RunN+ -> Gen (sh:.Int)+ -> Gen e+ -> Property+test_scanr1_interval runN dim e =+ property $ do+ sh :. n <- forAll dim+ let arr = intervalArray sh n e+ let !go = runN (A.scanr1 iappend) in go arr ~~~ scanr1Ref iappendRef arr++{-# NOINLINE test_scanr'_interval #-}+test_scanr'_interval+ :: (Shape sh, Show sh, Similar e, P.Eq sh, P.Eq e, P.Num e, A.Eq e, A.Num e, Show e)+ => RunN+ -> Gen (sh:.Int)+ -> Gen e+ -> Property+test_scanr'_interval runN dim e =+ property $ do+ sh :. n <- forAll dim+ let arr = intervalArray sh n e+ let !go = runN (A.scanr' iappend (constant one)) in go arr ~~~ scanr'Ref iappendRef one arr++{-# NOINLINE test_scanlSeg_sum #-}+test_scanlSeg_sum+ :: forall sh e. (Shape sh, Slice sh, Show sh, Similar e, P.Eq sh, P.Num e, A.Num e, Show e)+ => RunN+ -> Gen (sh:.Int)+ -> Gen e+ -> Gen e+ -> Property+test_scanlSeg_sum runN dim z e =+ property $ do+ x <- forAll z+ sh:.n1 <- forAll dim+ n2 <- forAll (Gen.int (Range.linear 0 64))+ n <- pure (P.min n1 n2) -- don't generate too many segments+ seg <- forAll (array (Z:.n) (Gen.int (Range.linear 0 (128 `quot` 2 P.^ (rank @sh)))))+ arr <- forAll (array (sh:.P.sum (toList seg)) e)+ let !go = runN (\v -> A.scanlSeg (+) (the v)) in go (scalar x) arr seg ~~~ scanlSegRef (+) x arr seg++{-# NOINLINE test_scanl1Seg_sum #-}+test_scanl1Seg_sum+ :: forall sh e. (Shape sh, Slice sh, Show sh, Similar e, P.Eq sh, P.Num e, A.Num e, Show e)+ => RunN+ -> Gen (sh:.Int)+ -> Gen e+ -> Property+test_scanl1Seg_sum runN dim e =+ property $ do+ sh:.n1 <- forAll dim+ n2 <- forAll (Gen.int (Range.linear 1 64))+ n <- pure (P.min n1 n2) -- don't generate too many segments+ seg <- forAll (array (Z:.n) (Gen.int (Range.linear 1 (128 `quot` 2 P.^ (rank @sh)))))+ arr <- forAll (array (sh:.P.sum (toList seg)) e)+ let !go = runN (A.scanl1Seg (+)) in go arr seg ~~~ scanl1SegRef (+) arr seg++{-# NOINLINE test_scanl'Seg_sum #-}+test_scanl'Seg_sum+ :: forall sh e. (Shape sh, Slice sh, Show sh, Similar e, P.Eq sh, P.Num e, A.Num e, Show e)+ => RunN+ -> Gen (sh:.Int)+ -> Gen e+ -> Gen e+ -> Property+test_scanl'Seg_sum runN dim z e =+ property $ do+ x <- forAll z+ sh:.n1 <- forAll dim+ n2 <- forAll (Gen.int (Range.linear 0 64))+ n <- pure (P.min n1 n2) -- don't generate too many segments+ seg <- forAll (array (Z:.n) (Gen.int (Range.linear 0 (128 `quot` 2 P.^ (rank @sh)))))+ arr <- forAll (array (sh:.P.sum (toList seg)) e)+ let !go = runN (\v -> A.scanl'Seg (+) (the v)) in go (scalar x) arr seg ~~~ scanl'SegRef (+) x arr seg++{-# NOINLINE test_scanrSeg_sum #-}+test_scanrSeg_sum+ :: forall sh e. (Shape sh, Slice sh, Show sh, Similar e, P.Eq sh, P.Num e, A.Num e, Show e)+ => RunN+ -> Gen (sh:.Int)+ -> Gen e+ -> Gen e+ -> Property+test_scanrSeg_sum runN dim z e =+ property $ do+ x <- forAll z+ sh:.n1 <- forAll dim+ n2 <- forAll (Gen.int (Range.linear 0 64))+ n <- pure (P.min n1 n2) -- don't generate too many segments+ seg <- forAll (array (Z:.n) (Gen.int (Range.linear 0 (128 `quot` 2 P.^ (rank @sh)))))+ arr <- forAll (array (sh:.P.sum (toList seg)) e)+ let !go = runN (\v -> A.scanrSeg (+) (the v)) in go (scalar x) arr seg ~~~ scanrSegRef (+) x arr seg++{-# NOINLINE test_scanr1Seg_sum #-}+test_scanr1Seg_sum+ :: forall sh e. (Shape sh, Slice sh, Show sh, Similar e, P.Eq sh, P.Num e, A.Num e, Show e)+ => RunN+ -> Gen (sh:.Int)+ -> Gen e+ -> Property+test_scanr1Seg_sum runN dim e =+ property $ do+ sh:.n1 <- forAll dim+ n2 <- forAll (Gen.int (Range.linear 1 64))+ n <- pure (P.min n1 n2) -- don't generate too many segments+ seg <- forAll (array (Z:.n) (Gen.int (Range.linear 1 (128 `quot` 2 P.^ (rank @sh)))))+ arr <- forAll (array (sh:.P.sum (toList seg)) e)+ let !go = runN (A.scanr1Seg (+)) in go arr seg ~~~ scanr1SegRef (+) arr seg++{-# NOINLINE test_scanr'Seg_sum #-}+test_scanr'Seg_sum+ :: forall sh e. (Shape sh, Slice sh, Show sh, Similar e, P.Eq sh, P.Num e, A.Num e, Show e)+ => RunN+ -> Gen (sh:.Int)+ -> Gen e+ -> Gen e+ -> Property+test_scanr'Seg_sum runN dim z e =+ property $ do+ x <- forAll z+ sh:.n1 <- forAll dim+ n2 <- forAll (Gen.int (Range.linear 0 64))+ n <- pure (P.min n1 n2) -- don't generate too many segments+ seg <- forAll (array (Z:.n) (Gen.int (Range.linear 0 (128 `quot` 2 P.^ (rank @sh)))))+ arr <- forAll (array (sh:.P.sum (toList seg)) e)+ let !go = runN (\v -> A.scanr'Seg (+) (the v)) in go (scalar x) arr seg ~~~ scanr'SegRef (+) x arr seg+++-- Interval of summations monoid+--+one, top :: P.Num e => (e,e)+one = (-1,-1)+top = (-2,-2)++iappendRef :: (P.Num e, P.Eq e) => (e,e) -> (e,e) -> (e,e)+iappendRef x y+ | x P.== one = y+ | y P.== one = x+ | x P.== top P.|| y P.== top = top+iappendRef (x1,x2) (y1,y2)+ | x2 + 1 P.== y1 = (x1,y2)+ | otherwise = top++iappend :: forall e. (A.Eq e, A.Num e, P.Num e) => Exp (e,e) -> Exp (e,e) -> Exp (e,e)+iappend x y+ = x A.== constant one ? ( y+ , y A.== constant one ? ( x+ , x A.== constant top ? ( constant top -- A.|| y A.== constant top; see AccelerateHS/accelerate#364+ , let+ (x1,x2) = unlift x :: (Exp e, Exp e)+ (y1,y2) = unlift y :: (Exp e, Exp e)+ in+ x2 + 1 A.== y1 ? ( lift (x1,y2) , constant top )+ )))++intervalArray :: (Shape sh, Elt e, P.Num e) => sh -> Int -> Gen e -> Array (sh:.Int) (e,e)+intervalArray sh n _ = fromFunction (sh:.n) (\(_:.i) -> let x = P.fromIntegral i in (x,x))+++-- Reference implementation+-- ------------------------++scanlRef+ :: (Shape sh, Elt e)+ => (e -> e -> e)+ -> e+ -> Array (sh:.Int) e+ -> Array (sh:.Int) e+scanlRef f z arr =+ let sz :. n = arrayShape arr+ arr' = [ P.scanl f z sub | sub <- splitEvery n (toList arr) ]+ in+ A.fromList (sz :. n+1) (concat arr')++scanl'Ref+ :: (Shape sh, Elt e)+ => (e -> e -> e)+ -> e+ -> Array (sh:.Int) e+ -> (Array (sh:.Int) e, Array sh e)+scanl'Ref f z arr =+ let sz :. n = arrayShape arr+ (arr',sums) = P.unzip [ P.splitAt n (P.scanl f z sub) | sub <- splitEvery n (toList arr) ]+ in+ ( A.fromList (sz:.n) (concat arr'), A.fromList sz (concat sums) )++scanl1Ref+ :: (Shape sh, Elt e)+ => (e -> e -> e)+ -> Array (sh:.Int) e+ -> Array (sh:.Int) e+scanl1Ref f arr =+ let sz :. n = arrayShape arr+ arr' = [ P.scanl1 f sub | sub <- splitEvery n (toList arr) ]+ in+ A.fromList (sz:.n) (concat arr')++scanrRef+ :: (Shape sh, Elt e)+ => (e -> e -> e)+ -> e+ -> Array (sh:.Int) e+ -> Array (sh:.Int) e+scanrRef f z arr =+ let sz :. n = arrayShape arr+ arr' = [ P.scanr f z sub | sub <- splitEvery n (toList arr) ]+ in+ A.fromList (sz :. n+1) (concat arr')++scanr'Ref+ :: (Shape sh, Elt e)+ => (e -> e -> e)+ -> e+ -> Array (sh:.Int) e+ -> (Array (sh:.Int) e, Array sh e)+scanr'Ref f z arr =+ let sz :. n = arrayShape arr+ (sums,arr') = P.unzip [ P.splitAt 1 (P.scanr f z sub) | sub <- splitEvery n (toList arr) ]+ in+ ( A.fromList (sz:.n) (concat arr'), A.fromList sz (concat sums) )++scanr1Ref+ :: (Shape sh, Elt e)+ => (e -> e -> e)+ -> Array (sh:.Int) e+ -> Array (sh:.Int) e+scanr1Ref f arr =+ let sz :. n = arrayShape arr+ arr' = [ P.scanr1 f sub | sub <- splitEvery n (toList arr) ]+ in+ A.fromList (sz:.n) (concat arr')+++-- segmented operations+--+scanlSegRef+ :: (Shape sh, Elt e)+ => (e -> e -> e)+ -> e+ -> Array (sh:.Int) e+ -> Segments Int+ -> Array (sh:.Int) e+scanlSegRef f z arr seg =+ let+ sz :. n = arrayShape arr+ seg' = toList seg+ n' = P.sum $ P.map (+1) seg'+ arr' = [ P.scanl f z sec | sub <- splitEvery n (toList arr)+ , sec <- splitPlaces seg' sub ]+ in+ A.fromList (sz:.n') (concat arr')++scanl1SegRef+ :: (Shape sh, Elt e)+ => (e -> e -> e)+ -> Array (sh:.Int) e+ -> Segments Int+ -> Array (sh:.Int) e+scanl1SegRef f arr seg =+ let+ sz :. n = arrayShape arr+ seg' = toList seg+ n' = P.sum seg'+ arr' = [ P.scanl1 f sec | sub <- splitEvery n (toList arr)+ , sec <- splitPlaces seg' sub ]+ in+ A.fromList (sz:.n') (concat arr')++scanl'SegRef+ :: (Shape sh, Elt e)+ => (e -> e -> e)+ -> e+ -> Array (sh:.Int) e+ -> Segments Int+ -> (Array (sh:.Int) e, Array (sh:.Int) e)+scanl'SegRef f z arr seg =+ let+ sz :. n = arrayShape arr+ Z :. s = arrayShape seg+ scanl'_ v = P.splitAt (P.length v) (P.scanl f z v)+ (arr',sums) = P.unzip [ scanl'_ sec | sub <- splitEvery n (toList arr)+ , sec <- splitPlaces (toList seg) sub ]+ in+ ( A.fromList (sz:.n) (concat arr'), A.fromList (sz:.s) (concat sums) )++scanrSegRef+ :: (Shape sh, Elt e)+ => (e -> e -> e)+ -> e+ -> Array (sh:.Int) e+ -> Segments Int+ -> Array (sh:.Int) e+scanrSegRef f z arr seg =+ let+ sz :. n = arrayShape arr+ seg' = toList seg+ n' = P.sum $ P.map (+1) seg'+ arr' = [ P.scanr f z sec | sub <- splitEvery n (toList arr)+ , sec <- splitPlaces seg' sub ]+ in+ A.fromList (sz:.n') (concat arr')++scanr1SegRef+ :: (Shape sh, Elt e)+ => (e -> e -> e)+ -> Array (sh:.Int) e+ -> Segments Int+ -> Array (sh:.Int) e+scanr1SegRef f arr seg =+ let sz :. n = arrayShape arr+ seg' = toList seg+ n' = P.sum seg'+ arr' = [ P.scanr1 f sec | sub <- splitEvery n (toList arr)+ , sec <- splitPlaces seg' sub ]+ in+ A.fromList (sz:.n') (concat arr')++scanr'SegRef+ :: (Shape sh, Elt e)+ => (e -> e -> e)+ -> e+ -> Array (sh:.Int) e+ -> Segments Int+ -> (Array (sh:.Int) e, Array (sh:.Int) e)+scanr'SegRef f z arr seg =+ let+ sz :. n = arrayShape arr+ Z :. s = arrayShape seg+ (sums, arr') = P.unzip [ P.splitAt 1 (P.scanr f z sec) | sub <- splitEvery n (toList arr)+ , sec <- splitPlaces (toList seg) sub ]+ in+ ( A.fromList (sz:.n) (concat arr'), A.fromList (sz:.s) (concat sums) )+
+ src/Data/Array/Accelerate/Test/NoFib/Prelude/Stencil.hs view
@@ -0,0 +1,670 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeOperators #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Prelude.Stencil+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Test.NoFib.Prelude.Stencil (++ test_stencil++) where++import Data.Typeable+import Prelude as P++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Sugar.Elt as S+import Data.Array.Accelerate.Sugar.Array as S+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Analysis.Match+import Data.Array.Accelerate.Type+import Data.Array.Accelerate.Test.NoFib.Base+import Data.Array.Accelerate.Test.NoFib.Config+import Data.Array.Accelerate.Test.Similar++import Hedgehog+import qualified Hedgehog.Gen as Gen+import qualified Hedgehog.Range as Range++import Test.Tasty+import Test.Tasty.Hedgehog+++test_stencil :: RunN -> TestTree+test_stencil runN =+ testGroup "stencil"+ [ at @TestInt8 $ testElt i8+ , at @TestInt16 $ testElt i16+ , at @TestInt32 $ testElt i32+ , at @TestInt64 $ testElt i64+ , at @TestWord8 $ testElt w8+ , at @TestWord16 $ testElt w16+ , at @TestWord32 $ testElt w32+ , at @TestWord64 $ testElt w64+ , at @TestHalf $ testElt f16+ , at @TestFloat $ testElt f32+ , at @TestDouble $ testElt f64+ ]+ where+ testElt+ :: forall a. (P.Num a, A.Num a, Similar a, Show a)+ => Gen a+ -> TestTree+ testElt e =+ testGroup (show (eltR @a))+ [ testDim1+ , testDim2+ , testDim3+ ]+ where+ testDim1 :: TestTree+ testDim1 =+ testGroup "DIM1"+ [ testProperty "stencil3" $ test_stencil3 runN e+ , testProperty "stencil5" $ test_stencil5 runN e+ , testProperty "stencil7" $ test_stencil7 runN e+ , testProperty "stencil9" $ test_stencil9 runN e+ ]++ testDim2 :: TestTree+ testDim2 =+ testGroup "DIM2"+ [ testProperty "stencil3x3" $ test_stencil3x3 runN e+ , testProperty "stencil5x5" $ test_stencil5x5 runN e+ , testProperty "stencil7x7" $ test_stencil7x7 runN e+ , testProperty "stencil9x9" $ test_stencil9x9 runN e+ ]++ testDim3 :: TestTree+ testDim3 =+ testGroup "DIM3"+ [ testProperty "stencil3x3x3" $ test_stencil3x3x3 runN e+ ]+++{-# NOINLINE test_stencil3 #-}+test_stencil3+ :: (P.Num e, A.Num e, Similar e, Show e)+ => RunN+ -> Gen e+ -> Property+test_stencil3 runN e =+ property $ do+ sh <- forAll ((Z :.) P.<$> Gen.int (Range.linear 2 256))+ xs <- forAll (array sh e)+ b <- forAll (boundary e)+ P3 _ a r <- forAll pattern3+ let !go = case b of+ Clamp -> runN (A.stencil a A.clamp)+ Wrap -> runN (A.stencil a A.wrap)+ Mirror -> runN (A.stencil a A.mirror)+ Constant x -> runN (A.stencil a (A.function (\_ -> constant x)))+ --+ go xs ~~~ stencil3Ref r b xs++{-# NOINLINE test_stencil5 #-}+test_stencil5+ :: (P.Num e, A.Num e, Similar e, Show e)+ => RunN+ -> Gen e+ -> Property+test_stencil5 runN e =+ property $ do+ sh <- forAll ((Z :.) P.<$> Gen.int (Range.linear 3 256))+ xs <- forAll (array sh e)+ b <- forAll (boundary e)+ P5 _ a r <- forAll pattern5+ let !go = case b of+ Clamp -> runN (A.stencil a A.clamp)+ Wrap -> runN (A.stencil a A.wrap)+ Mirror -> runN (A.stencil a A.mirror)+ Constant x -> runN (A.stencil a (A.function (\_ -> constant x)))+ --+ go xs ~~~ stencil5Ref r b xs++{-# NOINLINE test_stencil7 #-}+test_stencil7+ :: (P.Num e, A.Num e, Similar e, Show e)+ => RunN+ -> Gen e+ -> Property+test_stencil7 runN e =+ property $ do+ sh <- forAll ((Z :.) P.<$> Gen.int (Range.linear 4 256))+ xs <- forAll (array sh e)+ b <- forAll (boundary e)+ P7 _ a r <- forAll pattern7+ let !go = case b of+ Clamp -> runN (A.stencil a A.clamp)+ Wrap -> runN (A.stencil a A.wrap)+ Mirror -> runN (A.stencil a A.mirror)+ Constant x -> runN (A.stencil a (A.function (\_ -> constant x)))+ --+ go xs ~~~ stencil7Ref r b xs++{-# NOINLINE test_stencil9 #-}+test_stencil9+ :: (P.Num e, A.Num e, Similar e, Show e)+ => RunN+ -> Gen e+ -> Property+test_stencil9 runN e =+ property $ do+ sh <- forAll ((Z :.) P.<$> Gen.int (Range.linear 5 256))+ xs <- forAll (array sh e)+ b <- forAll (boundary e)+ P9 _ a r <- forAll pattern9+ let !go = case b of+ Clamp -> runN (A.stencil a A.clamp)+ Wrap -> runN (A.stencil a A.wrap)+ Mirror -> runN (A.stencil a A.mirror)+ Constant x -> runN (A.stencil a (A.function (\_ -> constant x)))+ --+ go xs ~~~ stencil9Ref r b xs+++{-# NOINLINE test_stencil3x3 #-}+test_stencil3x3+ :: (P.Num e, A.Num e, Similar e, Show e)+ => RunN+ -> Gen e+ -> Property+test_stencil3x3 runN e =+ property $ do+ sy <- forAll (Gen.int (Range.linear 2 96))+ sx <- forAll (Gen.int (Range.linear 2 96))+ let sh = Z :. sy :. sx+ xs <- forAll (array sh e)+ b <- forAll (boundary e)+ P3x3 _ a r <- forAll pattern3x3+ let !go = case b of+ Clamp -> runN (A.stencil a A.clamp)+ Wrap -> runN (A.stencil a A.wrap)+ Mirror -> runN (A.stencil a A.mirror)+ Constant x -> runN (A.stencil a (A.function (\_ -> constant x)))+ --+ go xs ~~~ stencil3x3Ref r b xs++{-# NOINLINE test_stencil5x5 #-}+test_stencil5x5+ :: (P.Num e, A.Num e, Similar e, Show e)+ => RunN+ -> Gen e+ -> Property+test_stencil5x5 runN e =+ property $ do+ sy <- forAll (Gen.int (Range.linear 3 96))+ sx <- forAll (Gen.int (Range.linear 3 96))+ let sh = Z :. sy :. sx+ xs <- forAll (array sh e)+ b <- forAll (boundary e)+ P5x5 _ a r <- forAll pattern5x5+ let !go = case b of+ Clamp -> runN (A.stencil a A.clamp)+ Wrap -> runN (A.stencil a A.wrap)+ Mirror -> runN (A.stencil a A.mirror)+ Constant x -> runN (A.stencil a (A.function (\_ -> constant x)))+ --+ go xs ~~~ stencil5x5Ref r b xs++{-# NOINLINE test_stencil7x7 #-}+test_stencil7x7+ :: (P.Num e, A.Num e, Similar e, Show e)+ => RunN+ -> Gen e+ -> Property+test_stencil7x7 runN e =+ property $ do+ sy <- forAll (Gen.int (Range.linear 4 96))+ sx <- forAll (Gen.int (Range.linear 4 96))+ let sh = Z :. sy :. sx+ xs <- forAll (array sh e)+ b <- forAll (boundary e)+ P7x7 _ a r <- forAll pattern7x7+ let !go = case b of+ Clamp -> runN (A.stencil a A.clamp)+ Wrap -> runN (A.stencil a A.wrap)+ Mirror -> runN (A.stencil a A.mirror)+ Constant x -> runN (A.stencil a (A.function (\_ -> constant x)))+ --+ go xs ~~~ stencil7x7Ref r b xs++{-# NOINLINE test_stencil9x9 #-}+test_stencil9x9+ :: (P.Num e, A.Num e, Similar e, Show e)+ => RunN+ -> Gen e+ -> Property+test_stencil9x9 runN e =+ property $ do+ sy <- forAll (Gen.int (Range.linear 5 96))+ sx <- forAll (Gen.int (Range.linear 5 96))+ let sh = Z :. sy :. sx+ xs <- forAll (array sh e)+ b <- forAll (boundary e)+ P9x9 _ a r <- forAll pattern9x9+ let !go = case b of+ Clamp -> runN (A.stencil a A.clamp)+ Wrap -> runN (A.stencil a A.wrap)+ Mirror -> runN (A.stencil a A.mirror)+ Constant x -> runN (A.stencil a (A.function (\_ -> constant x)))+ --+ go xs ~~~ stencil9x9Ref r b xs++{-# NOINLINE test_stencil3x3x3 #-}+test_stencil3x3x3+ :: (P.Num e, A.Num e, Similar e, Show e)+ => RunN+ -> Gen e+ -> Property+test_stencil3x3x3 runN e =+ property $ do+ sz <- forAll (Gen.int (Range.linear 2 32))+ sy <- forAll (Gen.int (Range.linear 2 32))+ sx <- forAll (Gen.int (Range.linear 2 32))+ let sh = Z :. sz :. sy :. sx+ xs <- forAll (array sh e)+ b <- forAll (boundary e)+ P3x3x3 _ a r <- forAll pattern3x3x3+ let !go = case b of+ Clamp -> runN (A.stencil a A.clamp)+ Wrap -> runN (A.stencil a A.wrap)+ Mirror -> runN (A.stencil a A.mirror)+ Constant x -> runN (A.stencil a (A.function (\_ -> constant x)))+ --+ go xs ~~~ stencil3x3x3Ref r b xs+++type Stencil3Ref a = (a,a,a)+type Stencil5Ref a = (a,a,a,a,a)+type Stencil7Ref a = (a,a,a,a,a,a,a)+type Stencil9Ref a = (a,a,a,a,a,a,a,a,a)++type Stencil3x3Ref a = (Stencil3Ref a, Stencil3Ref a, Stencil3Ref a)+type Stencil5x5Ref a = (Stencil5Ref a, Stencil5Ref a, Stencil5Ref a, Stencil5Ref a, Stencil5Ref a)+type Stencil7x7Ref a = (Stencil7Ref a, Stencil7Ref a, Stencil7Ref a, Stencil7Ref a, Stencil7Ref a, Stencil7Ref a, Stencil7Ref a)+type Stencil9x9Ref a = (Stencil9Ref a, Stencil9Ref a, Stencil9Ref a, Stencil9Ref a, Stencil9Ref a, Stencil9Ref a, Stencil9Ref a, Stencil9Ref a, Stencil9Ref a)++type Stencil3x3x3Ref a = (Stencil3x3Ref a, Stencil3x3Ref a, Stencil3x3Ref a)++type Stencil7x7 a = (Stencil7 a, Stencil7 a, Stencil7 a, Stencil7 a, Stencil7 a, Stencil7 a, Stencil7 a)+type Stencil9x9 a = (Stencil9 a, Stencil9 a, Stencil9 a, Stencil9 a, Stencil9 a, Stencil9 a, Stencil9 a, Stencil9 a, Stencil9 a)+++data SimpleBoundary e+ = Wrap+ | Clamp+ | Mirror+ | Constant e+ deriving (P.Eq, Show)++boundary :: Gen e -> Gen (SimpleBoundary e)+boundary e =+ Gen.choice+ [ Constant P.<$> e+ , pure Clamp+ , pure Wrap+ , pure Mirror+ ]++data Pattern3 a = P3 [Int] (Stencil3 a -> Exp a) (Stencil3Ref a -> a)+data Pattern5 a = P5 [Int] (Stencil5 a -> Exp a) (Stencil5Ref a -> a)+data Pattern7 a = P7 [Int] (Stencil7 a -> Exp a) (Stencil7Ref a -> a)+data Pattern9 a = P9 [Int] (Stencil9 a -> Exp a) (Stencil9Ref a -> a)++data Pattern3x3 a = P3x3 [[Int]] (Stencil3x3 a -> Exp a) (Stencil3x3Ref a -> a)+data Pattern5x5 a = P5x5 [[Int]] (Stencil5x5 a -> Exp a) (Stencil5x5Ref a -> a)+data Pattern7x7 a = P7x7 [[Int]] (Stencil7x7 a -> Exp a) (Stencil7x7Ref a -> a)+data Pattern9x9 a = P9x9 [[Int]] (Stencil9x9 a -> Exp a) (Stencil9x9Ref a -> a)++data Pattern3x3x3 a = P3x3x3 [[[Int]]] (Stencil3x3x3 a -> Exp a) (Stencil3x3x3Ref a -> a)++instance Show (Pattern3 a) where show (P3 ix _ _) = show ix+instance Show (Pattern5 a) where show (P5 ix _ _) = show ix+instance Show (Pattern7 a) where show (P7 ix _ _) = show ix+instance Show (Pattern9 a) where show (P9 ix _ _) = show ix++instance Show (Pattern3x3 a) where show (P3x3 ix _ _) = show ix+instance Show (Pattern5x5 a) where show (P5x5 ix _ _) = show ix+instance Show (Pattern7x7 a) where show (P7x7 ix _ _) = show ix+instance Show (Pattern9x9 a) where show (P9x9 ix _ _) = show ix++instance Show (Pattern3x3x3 a) where show (P3x3x3 ix _ _) = show ix+++pattern3 :: (P.Num a, A.Num a) => Gen (Pattern3 a)+pattern3 = do+ i <- Gen.subsequence [0..2]+ pure $+ P3 i (\(x0,x1,x2) -> P.sum (P.map ([x0,x1,x2] P.!!) i))+ (\(x0,x1,x2) -> P.sum (P.map ([x0,x1,x2] P.!!) i))++pattern5 :: (P.Num a, A.Num a) => Gen (Pattern5 a)+pattern5 = do+ i <- Gen.subsequence [0..4]+ pure $+ P5 i (\(x0,x1,x2,x3,x4) -> P.sum (P.map ([x0,x1,x2,x3,x4] P.!!) i))+ (\(x0,x1,x2,x3,x4) -> P.sum (P.map ([x0,x1,x2,x3,x4] P.!!) i))++pattern7 :: (P.Num a, A.Num a) => Gen (Pattern7 a)+pattern7 = do+ i <- Gen.subsequence [0..6]+ pure $+ P7 i (\(x0,x1,x2,x3,x4,x5,x6) -> P.sum (P.map ([x0,x1,x2,x3,x4,x5,x6] P.!!) i))+ (\(x0,x1,x2,x3,x4,x5,x6) -> P.sum (P.map ([x0,x1,x2,x3,x4,x5,x6] P.!!) i))++pattern9 :: (P.Num a, A.Num a) => Gen (Pattern9 a)+pattern9 = do+ i <- Gen.subsequence [0..8]+ pure $+ P9 i (\(x0,x1,x2,x3,x4,x5,x6,x7,x8) -> P.sum (P.map ([x0,x1,x2,x3,x4,x5,x6,x7,x8] P.!!) i))+ (\(x0,x1,x2,x3,x4,x5,x6,x7,x8) -> P.sum (P.map ([x0,x1,x2,x3,x4,x5,x6,x7,x8] P.!!) i))++pattern3x3 :: (P.Num a, A.Num a) => Gen (Pattern3x3 a)+pattern3x3 = do+ P3 i0 a0 r0 <- pattern3+ P3 i1 a1 r1 <- pattern3+ P3 i2 a2 r2 <- pattern3+ pure $+ P3x3 [i0,i1,i2]+ (\(x0,x1,x2) -> P.sum [a0 x0, a1 x1, a2 x2])+ (\(x0,x1,x2) -> P.sum [r0 x0, r1 x1, r2 x2])++pattern5x5 :: (P.Num a, A.Num a) => Gen (Pattern5x5 a)+pattern5x5 = do+ P5 i0 a0 r0 <- pattern5+ P5 i1 a1 r1 <- pattern5+ P5 i2 a2 r2 <- pattern5+ P5 i3 a3 r3 <- pattern5+ P5 i4 a4 r4 <- pattern5+ pure $+ P5x5 [i0,i1,i2,i3,i4]+ (\(x0,x1,x2,x3,x4) -> P.sum [a0 x0, a1 x1, a2 x2, a3 x3, a4 x4])+ (\(x0,x1,x2,x3,x4) -> P.sum [r0 x0, r1 x1, r2 x2, r3 x3, r4 x4])++pattern7x7 :: (P.Num a, A.Num a) => Gen (Pattern7x7 a)+pattern7x7 = do+ P7 i0 a0 r0 <- pattern7+ P7 i1 a1 r1 <- pattern7+ P7 i2 a2 r2 <- pattern7+ P7 i3 a3 r3 <- pattern7+ P7 i4 a4 r4 <- pattern7+ P7 i5 a5 r5 <- pattern7+ P7 i6 a6 r6 <- pattern7+ pure $+ P7x7 [i0,i1,i2,i3,i4,i5,i6]+ (\(x0,x1,x2,x3,x4,x5,x6) -> P.sum [a0 x0, a1 x1, a2 x2, a3 x3, a4 x4, a5 x5, a6 x6])+ (\(x0,x1,x2,x3,x4,x5,x6) -> P.sum [r0 x0, r1 x1, r2 x2, r3 x3, r4 x4, r5 x5, r6 x6])++pattern9x9 :: (P.Num a, A.Num a) => Gen (Pattern9x9 a)+pattern9x9 = do+ P9 i0 a0 r0 <- pattern9+ P9 i1 a1 r1 <- pattern9+ P9 i2 a2 r2 <- pattern9+ P9 i3 a3 r3 <- pattern9+ P9 i4 a4 r4 <- pattern9+ P9 i5 a5 r5 <- pattern9+ P9 i6 a6 r6 <- pattern9+ P9 i7 a7 r7 <- pattern9+ P9 j8 a8 r8 <- pattern9+ pure $+ P9x9 [i0,i1,i2,i3,i4,i5,i6,i7,j8]+ (\(x0,x1,x2,x3,x4,x5,x6,x7,x8) -> P.sum [a0 x0, a1 x1, a2 x2, a3 x3, a4 x4, a5 x5, a6 x6, a7 x7, a8 x8])+ (\(x0,x1,x2,x3,x4,x5,x6,x7,x8) -> P.sum [r0 x0, r1 x1, r2 x2, r3 x3, r4 x4, r5 x5, r6 x6, r7 x7, r8 x8])++pattern3x3x3 :: (P.Num a, A.Num a) => Gen (Pattern3x3x3 a)+pattern3x3x3 = do+ P3x3 i0 a0 r0 <- pattern3x3+ P3x3 i1 a1 r1 <- pattern3x3+ P3x3 i2 a2 r2 <- pattern3x3+ pure $+ P3x3x3 [i0,i1,i2]+ (\(x0,x1,x2) -> P.sum [a0 x0, a1 x1, a2 x2])+ (\(x0,x1,x2) -> P.sum [r0 x0, r1 x1, r2 x2])++++stencil3Ref+ :: Elt a+ => (Stencil3Ref a -> a)+ -> SimpleBoundary a+ -> Vector a+ -> Vector a+stencil3Ref st bnd arr =+ let sh = S.shape arr+ in+ fromFunction sh+ (\ix@(Z:.n) -> let x0 = either id (arr S.!) (bound bnd sh (Z :. n-1))+ x1 = arr S.! ix+ x2 = either id (arr S.!) (bound bnd sh (Z :. n+1))+ in+ st (x0,x1,x2))++stencil5Ref+ :: Elt a+ => (Stencil5Ref a -> a)+ -> SimpleBoundary a+ -> Vector a+ -> Vector a+stencil5Ref st bnd arr =+ let sh = S.shape arr+ in+ fromFunction sh+ (\(Z:.i) ->+ let get it = either id (arr S.!) (bound bnd sh it)+ --+ x0 = get (Z:.i-2)+ x1 = get (Z:.i-1)+ x2 = get (Z:.i)+ x3 = get (Z:.i+1)+ x4 = get (Z:.i+2)+ in+ st (x0,x1,x2,x3,x4))++stencil7Ref+ :: Elt a+ => (Stencil7Ref a -> a)+ -> SimpleBoundary a+ -> Vector a+ -> Vector a+stencil7Ref st bnd arr =+ let sh = S.shape arr+ in+ fromFunction sh+ (\(Z:.i) ->+ let get it = either id (arr S.!) (bound bnd sh it)+ --+ x0 = get (Z:.i-3)+ x1 = get (Z:.i-2)+ x2 = get (Z:.i-1)+ x3 = get (Z:.i)+ x4 = get (Z:.i+1)+ x5 = get (Z:.i+2)+ x6 = get (Z:.i+3)+ in+ st (x0,x1,x2,x3,x4,x5,x6))++stencil9Ref+ :: Elt a+ => (Stencil9Ref a -> a)+ -> SimpleBoundary a+ -> Vector a+ -> Vector a+stencil9Ref st bnd arr =+ let sh = S.shape arr+ in+ fromFunction sh+ (\(Z:.i) ->+ let get it = either id (arr S.!) (bound bnd sh it)+ --+ x0 = get (Z:.i-4)+ x1 = get (Z:.i-3)+ x2 = get (Z:.i-2)+ x3 = get (Z:.i-1)+ x4 = get (Z:.i)+ x5 = get (Z:.i+1)+ x6 = get (Z:.i+2)+ x7 = get (Z:.i+3)+ x8 = get (Z:.i+4)+ in+ st (x0,x1,x2,x3,x4,x5,x6,x7,x8))++stencil3x3Ref+ :: Elt a+ => (Stencil3x3Ref a -> a)+ -> SimpleBoundary a+ -> Matrix a+ -> Matrix a+stencil3x3Ref st bnd arr =+ let sh = S.shape arr+ in+ fromFunction sh+ (\(Z:.j:.i) ->+ let get it = either id (arr S.!) (bound bnd sh it)+ --+ x0 = ( get (Z :. j-1 :. i-1), get (Z :. j-1 :. i), get (Z :. j-1 :. i+1) )+ x1 = ( get (Z :. j :. i-1), get (Z :. j :. i), get (Z :. j :. i+1) )+ x2 = ( get (Z :. j+1 :. i-1), get (Z :. j+1 :. i), get (Z :. j+1 :. i+1) )+ in+ st (x0,x1,x2))++stencil5x5Ref+ :: Elt a+ => (Stencil5x5Ref a -> a)+ -> SimpleBoundary a+ -> Matrix a+ -> Matrix a+stencil5x5Ref st bnd arr =+ let sh = S.shape arr+ in+ fromFunction sh+ (\(Z:.j:.i) ->+ let get it = either id (arr S.!) (bound bnd sh it)+ --+ x0 = ( get (Z :. j-2 :. i-2), get (Z :. j-2 :. i-1), get (Z :. j-2 :. i), get (Z :. j-2 :. i+1), get (Z :. j-2 :. i+2) )+ x1 = ( get (Z :. j-1 :. i-2), get (Z :. j-1 :. i-1), get (Z :. j-1 :. i), get (Z :. j-1 :. i+1), get (Z :. j-1 :. i+2) )+ x2 = ( get (Z :. j :. i-2), get (Z :. j :. i-1), get (Z :. j :. i), get (Z :. j :. i+1), get (Z :. j :. i+2) )+ x3 = ( get (Z :. j+1 :. i-2), get (Z :. j+1 :. i-1), get (Z :. j+1 :. i), get (Z :. j+1 :. i+1), get (Z :. j+1 :. i+2) )+ x4 = ( get (Z :. j+2 :. i-2), get (Z :. j+2 :. i-1), get (Z :. j+2 :. i), get (Z :. j+2 :. i+1), get (Z :. j+2 :. i+2) )+ in+ st (x0,x1,x2,x3,x4))++stencil7x7Ref+ :: Elt a+ => (Stencil7x7Ref a -> a)+ -> SimpleBoundary a+ -> Matrix a+ -> Matrix a+stencil7x7Ref st bnd arr =+ let sh = S.shape arr+ in+ fromFunction sh+ (\(Z:.j:.i) ->+ let get it = either id (arr S.!) (bound bnd sh it)+ --+ x0 = ( get (Z :. j-3 :. i-3), get (Z :. j-3 :. i-2), get (Z :. j-3 :. i-1), get (Z :. j-3 :. i), get (Z :. j-3 :. i+1), get (Z :. j-3 :. i+2), get (Z :. j-3 :. i+3) )+ x1 = ( get (Z :. j-2 :. i-3), get (Z :. j-2 :. i-2), get (Z :. j-2 :. i-1), get (Z :. j-2 :. i), get (Z :. j-2 :. i+1), get (Z :. j-2 :. i+2), get (Z :. j-2 :. i+3) )+ x2 = ( get (Z :. j-1 :. i-3), get (Z :. j-1 :. i-2), get (Z :. j-1 :. i-1), get (Z :. j-1 :. i), get (Z :. j-1 :. i+1), get (Z :. j-1 :. i+2), get (Z :. j-1 :. i+3) )+ x3 = ( get (Z :. j :. i-3), get (Z :. j :. i-2), get (Z :. j :. i-1), get (Z :. j :. i), get (Z :. j :. i+1), get (Z :. j :. i+2), get (Z :. j :. i+3) )+ x4 = ( get (Z :. j+1 :. i-3), get (Z :. j+1 :. i-2), get (Z :. j+1 :. i-1), get (Z :. j+1 :. i), get (Z :. j+1 :. i+1), get (Z :. j+1 :. i+2), get (Z :. j+1 :. i+3) )+ x5 = ( get (Z :. j+2 :. i-3), get (Z :. j+2 :. i-2), get (Z :. j+2 :. i-1), get (Z :. j+2 :. i), get (Z :. j+2 :. i+1), get (Z :. j+2 :. i+2), get (Z :. j+2 :. i+3) )+ x6 = ( get (Z :. j+3 :. i-3), get (Z :. j+3 :. i-2), get (Z :. j+3 :. i-1), get (Z :. j+3 :. i), get (Z :. j+3 :. i+1), get (Z :. j+3 :. i+2), get (Z :. j+3 :. i+3) )+ in+ st (x0,x1,x2,x3,x4,x5,x6))++stencil9x9Ref+ :: Elt a+ => (Stencil9x9Ref a -> a)+ -> SimpleBoundary a+ -> Matrix a+ -> Matrix a+stencil9x9Ref st bnd arr =+ let sh = S.shape arr+ in+ fromFunction sh+ (\(Z:.j:.i) ->+ let get it = either id (arr S.!) (bound bnd sh it)+ --+ x0 = ( get (Z :. j-4 :. i-4), get (Z :. j-4 :. i-3), get (Z :. j-4 :. i-2), get (Z :. j-4 :. i-1), get (Z :. j-4 :. i), get (Z :. j-4 :. i+1), get (Z :. j-4 :. i+2), get (Z :. j-4 :. i+3), get (Z :. j-4 :. i+4) )+ x1 = ( get (Z :. j-3 :. i-4), get (Z :. j-3 :. i-3), get (Z :. j-3 :. i-2), get (Z :. j-3 :. i-1), get (Z :. j-3 :. i), get (Z :. j-3 :. i+1), get (Z :. j-3 :. i+2), get (Z :. j-3 :. i+3), get (Z :. j-3 :. i+4) )+ x2 = ( get (Z :. j-2 :. i-4), get (Z :. j-2 :. i-3), get (Z :. j-2 :. i-2), get (Z :. j-2 :. i-1), get (Z :. j-2 :. i), get (Z :. j-2 :. i+1), get (Z :. j-2 :. i+2), get (Z :. j-2 :. i+3), get (Z :. j-2 :. i+4) )+ x3 = ( get (Z :. j-1 :. i-4), get (Z :. j-1 :. i-3), get (Z :. j-1 :. i-2), get (Z :. j-1 :. i-1), get (Z :. j-1 :. i), get (Z :. j-1 :. i+1), get (Z :. j-1 :. i+2), get (Z :. j-1 :. i+3), get (Z :. j-1 :. i+4) )+ x4 = ( get (Z :. j :. i-4), get (Z :. j :. i-3), get (Z :. j :. i-2), get (Z :. j :. i-1), get (Z :. j :. i), get (Z :. j :. i+1), get (Z :. j :. i+2), get (Z :. j :. i+3), get (Z :. j :. i+4) )+ x5 = ( get (Z :. j+1 :. i-4), get (Z :. j+1 :. i-3), get (Z :. j+1 :. i-2), get (Z :. j+1 :. i-1), get (Z :. j+1 :. i), get (Z :. j+1 :. i+1), get (Z :. j+1 :. i+2), get (Z :. j+1 :. i+3), get (Z :. j+1 :. i+4) )+ x6 = ( get (Z :. j+2 :. i-4), get (Z :. j+2 :. i-3), get (Z :. j+2 :. i-2), get (Z :. j+2 :. i-1), get (Z :. j+2 :. i), get (Z :. j+2 :. i+1), get (Z :. j+2 :. i+2), get (Z :. j+2 :. i+3), get (Z :. j+2 :. i+4) )+ x7 = ( get (Z :. j+3 :. i-4), get (Z :. j+3 :. i-3), get (Z :. j+3 :. i-2), get (Z :. j+3 :. i-1), get (Z :. j+3 :. i), get (Z :. j+3 :. i+1), get (Z :. j+3 :. i+2), get (Z :. j+3 :. i+3), get (Z :. j+3 :. i+4) )+ x8 = ( get (Z :. j+4 :. i-4), get (Z :. j+4 :. i-3), get (Z :. j+4 :. i-2), get (Z :. j+4 :. i-1), get (Z :. j+4 :. i), get (Z :. j+4 :. i+1), get (Z :. j+4 :. i+2), get (Z :. j+4 :. i+3), get (Z :. j+4 :. i+4) )+ in+ st (x0,x1,x2,x3,x4,x5,x6,x7,x8))++stencil3x3x3Ref+ :: forall a. Elt a+ => (Stencil3x3x3Ref a -> a)+ -> SimpleBoundary a+ -> Array DIM3 a+ -> Array DIM3 a+stencil3x3x3Ref st bnd arr =+ let sh = S.shape arr+ in+ fromFunction sh+ (\(Z:.k:.j:.i) ->+ let get it = either id (arr S.!) (bound bnd sh it)+ --+ x0 z = ( get (Z :. z :. j-1 :. i-1), get (Z :. z :. j-1 :. i), get (Z :. z :. j-1 :. i+1) )+ x1 z = ( get (Z :. z :. j :. i-1), get (Z :. z :. j :. i), get (Z :. z :. j :. i+1) )+ x2 z = ( get (Z :. z :. j+1 :. i-1), get (Z :. z :. j+1 :. i), get (Z :. z :. j+1 :. i+1) )+ in+ st ((x0 (k-1), x1 (k-1), x2 (k-1))+ ,(x0 k , x1 k, x2 k)+ ,(x0 (k+1), x1 (k+1), x2 (k+1))))+++bound :: forall sh e. Shape sh => SimpleBoundary e -> sh -> sh -> Either e sh+bound bnd sh0 ix0 =+ case go (eltR @sh) (fromElt sh0) (fromElt ix0) of+ Left e -> Left e+ Right ix' -> Right (toElt ix')+ where+ go :: TypeR t -> t -> t -> Either e t+ go TupRunit () () = Right ()+ go (TupRpair tsh tsz) (sh,sz) (ih,iz) = go tsh sh ih `addDim` go tsz sz iz+ go (TupRsingle t) sh i+ | Just Refl <- matchScalarType t (scalarType :: ScalarType Int)+ = if i P.< 0+ then case bnd of+ Clamp -> Right 0+ Mirror -> Right (-i)+ Wrap -> Right (sh+i)+ Constant e -> Left e++ else if i P.>= sh+ then case bnd of+ Clamp -> Right (sh-1)+ Mirror -> Right (sh-(i-sh+2))+ Wrap -> Right (i-sh)+ Constant e -> Left e+ else+ Right i+ --+ | otherwise+ = error "bound: expected shape with Int dimensions"++ Right ds `addDim` Right d = Right (ds, d)+ _ `addDim` Left e = Left e+ Left e `addDim` _ = Left e+
+ src/Data/Array/Accelerate/Test/NoFib/Prelude/ZipWith.hs view
@@ -0,0 +1,630 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE MonoLocalBinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeOperators #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Prelude.ZipWith+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Test.NoFib.Prelude.ZipWith (++ test_zipWith++) where++import Data.Bits as P+import Prelude as P++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Data.Bits as A+import Data.Array.Accelerate.Smart ( ($$) )+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Test.NoFib.Base+import Data.Array.Accelerate.Test.NoFib.Config+import Data.Array.Accelerate.Test.Similar+import qualified Data.Array.Accelerate.Sugar.Array as S+import qualified Data.Array.Accelerate.Sugar.Shape as S++import Hedgehog+import qualified Hedgehog.Gen as Gen+import qualified Hedgehog.Range as Range++import Test.Tasty+import Test.Tasty.Hedgehog+++test_zipWith :: RunN -> TestTree+test_zipWith runN =+ testGroup "zipWith"+ [ at @TestInt8 $ testIntegralElt i8+ , at @TestInt16 $ testIntegralElt i16+ , at @TestInt32 $ testIntegralElt i32+ , at @TestInt64 $ testIntegralElt i64+ , at @TestWord8 $ testIntegralElt w8+ , at @TestWord16 $ testIntegralElt w16+ , at @TestWord32 $ testIntegralElt w32+ , at @TestWord64 $ testIntegralElt w64+ , at @TestHalf $ testFloatingElt (Gen.realFloat :: Range Half -> Gen Half)+ , at @TestFloat $ testFloatingElt Gen.float+ , at @TestDouble $ testFloatingElt Gen.double+ ]+ where+ testIntegralElt+ :: forall a. ( P.Integral a, P.FiniteBits a+ , A.Integral a, A.FiniteBits a+ , Similar a, Show a )+ => Gen a+ -> TestTree+ testIntegralElt e =+ testGroup (show (eltR @a))+ [ testDim dim0+ , testDim dim1+ , testDim dim2+ ]+ where+ testDim+ :: forall sh. (Shape sh, Show sh, P.Eq sh, Show sh)+ => Gen sh+ -> TestTree+ testDim sh =+ testGroup ("DIM" P.++ show (S.rank @sh))+ [ -- operators on Num+ testProperty "(+)" $ test_plus runN sh e+ , testProperty "(-)" $ test_minus runN sh e+ , testProperty "(*)" $ test_mult runN sh e++ -- operators on Integral & Bits+ , testProperty "quot" $ test_quot runN sh e+ , testProperty "rem" $ test_rem runN sh e+ , testProperty "quotRem" $ test_quotRem runN sh e+ , testProperty "div" $ test_idiv runN sh e+ , testProperty "mod" $ test_mod runN sh e+ , testProperty "divMod" $ test_divMod runN sh e+ , testProperty "(.&.)" $ test_band runN sh e+ , testProperty "(.|.)" $ test_bor runN sh e+ , testProperty "xor" $ test_xor runN sh e+ , testProperty "shift" $ test_shift runN sh e+ , testProperty "shiftL" $ test_shiftL runN sh e+ , testProperty "shiftR" $ test_shiftR runN sh e+ , testProperty "rotate" $ test_rotate runN sh e+ , testProperty "rotateL" $ test_rotateL runN sh e+ , testProperty "rotateR" $ test_rotateR runN sh e++ -- relational and equality operators+ , testProperty "(<)" $ test_lt runN sh e+ , testProperty "(>)" $ test_gt runN sh e+ , testProperty "(<=)" $ test_lte runN sh e+ , testProperty "(>=)" $ test_gte runN sh e+ , testProperty "(==)" $ test_eq runN sh e+ , testProperty "(/=)" $ test_neq runN sh e+ , testProperty "min" $ test_min runN sh e+ , testProperty "max" $ test_max runN sh e+ ]++ testFloatingElt+ :: forall a. (P.RealFloat a, A.RealFloat a, Similar a, Show a)+ => (Range a -> Gen a)+ -> TestTree+ testFloatingElt e =+ testGroup (show (eltR @a))+ [ testDim dim0+ , testDim dim1+ , testDim dim2+ ]+ where+ testDim+ :: forall sh. (Shape sh, Show sh, P.Eq sh)+ => Gen sh+ -> TestTree+ testDim sh =+ testGroup ("DIM" P.++ show (S.rank @sh))+ [ -- operators on Num+ testProperty "(+)" $ test_plus runN sh (full e)+ , testProperty "(-)" $ test_minus runN sh (full e)+ , testProperty "(*)" $ test_mult runN sh (full e)++ -- operators on Fractional, Floating, RealFrac & RealFloat+ , testProperty "(/)" $ test_fdiv runN sh (full e)+ , testProperty "(**)" $ test_pow runN sh (full e)+ , testProperty "atan2" $ test_atan2 runN sh (full e)+ , testProperty "logBase" $ test_logBase runN sh (e (Range.linearFrac 0 flt_max) `except` zero)++ -- relational and equality operators+ , testProperty "(<)" $ test_lt runN sh (full e)+ , testProperty "(>)" $ test_gt runN sh (full e)+ , testProperty "(<=)" $ test_lte runN sh (full e)+ , testProperty "(>=)" $ test_gte runN sh (full e)+ , testProperty "(==)" $ test_eq runN sh (full e)+ , testProperty "(/=)" $ test_neq runN sh (full e)+ , testProperty "min" $ test_min runN sh (full e)+ , testProperty "max" $ test_max runN sh (full e)+ ]++ full :: P.RealFloat e => (Range e -> Gen e) -> Gen e+ full gen = gen (Range.linearFracFrom 0 (-flt_max) flt_max)+++zero :: (P.Num a, P.Eq a) => a -> Bool+zero x = x P.== 0++{-# NOINLINE test_plus #-}+test_plus+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Num e, A.Num e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_plus runN dim e =+ property $ do+ sh1 <- forAll dim+ sh2 <- forAll dim+ xs <- forAll (array sh1 e)+ ys <- forAll (array sh2 e)+ let !go = runN (A.zipWith (+)) in go xs ys ~~~ zipWithRef (+) xs ys++{-# NOINLINE test_minus #-}+test_minus+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Num e, A.Num e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_minus runN dim e =+ property $ do+ sh1 <- forAll dim+ sh2 <- forAll dim+ xs <- forAll (array sh1 e)+ ys <- forAll (array sh2 e)+ let !go = runN (A.zipWith (-)) in go xs ys ~~~ zipWithRef (-) xs ys++{-# NOINLINE test_mult #-}+test_mult+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Num e, A.Num e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_mult runN dim e =+ property $ do+ sh1 <- forAll dim+ sh2 <- forAll dim+ xs <- forAll (array sh1 e)+ ys <- forAll (array sh2 e)+ let !go = runN (A.zipWith (*)) in go xs ys ~~~ zipWithRef (*) xs ys++{-# NOINLINE test_quot #-}+test_quot+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Integral e, A.Integral e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_quot runN dim e =+ property $ do+ sh1 <- forAll dim+ sh2 <- forAll dim+ xs <- forAll (array sh1 e)+ ys <- forAll (array sh2 (e `except` zero))+ let !go = runN (A.zipWith quot) in go xs ys ~~~ zipWithRef quot xs ys++{-# NOINLINE test_rem #-}+test_rem+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Integral e, A.Integral e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_rem runN dim e =+ property $ do+ sh1 <- forAll dim+ sh2 <- forAll dim+ xs <- forAll (array sh1 e)+ ys <- forAll (array sh2 (e `except` zero))+ let !go = runN (A.zipWith rem) in go xs ys ~~~ zipWithRef rem xs ys++{-# NOINLINE test_quotRem #-}+test_quotRem+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Integral e, A.Integral e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_quotRem runN dim e =+ property $ do+ sh1 <- forAll dim+ sh2 <- forAll dim+ xs <- forAll (array sh1 e)+ ys <- forAll (array sh2 (e `except` zero))+ let !go = runN (A.zipWith (lift $$ quotRem)) in go xs ys ~~~ zipWithRef quotRem xs ys++{-# NOINLINE test_idiv #-}+test_idiv+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Integral e, A.Integral e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_idiv runN dim e =+ property $ do+ sh1 <- forAll dim+ sh2 <- forAll dim+ xs <- forAll (array sh1 e)+ ys <- forAll (array sh2 (e `except` zero))+ let !go = runN (A.zipWith div) in go xs ys ~~~ zipWithRef div xs ys++{-# NOINLINE test_fdiv #-}+test_fdiv+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Eq e, P.Fractional e, A.Fractional e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_fdiv runN dim e =+ property $ do+ sh1 <- forAll dim+ sh2 <- forAll dim+ xs <- forAll (array sh1 e)+ ys <- forAll (array sh2 (e `except` zero))+ let !go = runN (A.zipWith (/)) in go xs ys ~~~ zipWithRef (/) xs ys++{-# NOINLINE test_pow #-}+test_pow+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Floating e, A.Floating e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_pow runN dim e =+ property $ do+ sh1 <- forAll dim+ sh2 <- forAll dim+ xs <- forAll (array sh1 e)+ ys <- forAll (array sh2 e)+ let !go = runN (A.zipWith (**)) in go xs ys ~~~ zipWithRef (**) xs ys++{-# NOINLINE test_logBase #-}+test_logBase+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Floating e, A.Floating e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_logBase runN dim e =+ property $ do+ sh1 <- forAll dim+ sh2 <- forAll dim+ xs <- forAll (array sh1 e)+ ys <- forAll (array sh2 e)+ let !go = runN (A.zipWith logBase) in go xs ys ~~~ zipWithRef logBase xs ys++{-# NOINLINE test_atan2 #-}+test_atan2+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.RealFloat e, A.RealFloat e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_atan2 runN dim e =+ property $ do+ sh1 <- forAll dim+ sh2 <- forAll dim+ xs <- forAll (array sh1 e)+ ys <- forAll (array sh2 e)+ let !go = runN (A.zipWith A.atan2) in go xs ys ~~~ zipWithRef P.atan2 xs ys++{-# NOINLINE test_mod #-}+test_mod+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Integral e, A.Integral e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_mod runN dim e =+ property $ do+ sh1 <- forAll dim+ sh2 <- forAll dim+ xs <- forAll (array sh1 e)+ ys <- forAll (array sh2 (e `except` zero))+ let !go = runN (A.zipWith mod) in go xs ys ~~~ zipWithRef mod xs ys++{-# NOINLINE test_divMod #-}+test_divMod+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Integral e, A.Integral e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_divMod runN dim e =+ property $ do+ sh1 <- forAll dim+ sh2 <- forAll dim+ xs <- forAll (array sh1 e)+ ys <- forAll (array sh2 (e `except` zero))+ let !go = runN (A.zipWith (lift $$ divMod)) in go xs ys ~~~ zipWithRef divMod xs ys++{-# NOINLINE test_band #-}+test_band+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Bits e, A.Bits e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_band runN dim e =+ property $ do+ sh1 <- forAll dim+ sh2 <- forAll dim+ xs <- forAll (array sh1 e)+ ys <- forAll (array sh2 e)+ let !go = runN (A.zipWith (A..&.)) in go xs ys ~~~ zipWithRef (P..&.) xs ys++{-# NOINLINE test_bor #-}+test_bor+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Bits e, A.Bits e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_bor runN dim e =+ property $ do+ sh1 <- forAll dim+ sh2 <- forAll dim+ xs <- forAll (array sh1 e)+ ys <- forAll (array sh2 e)+ let !go = runN (A.zipWith (A..|.)) in go xs ys ~~~ zipWithRef (P..|.) xs ys++{-# NOINLINE test_xor #-}+test_xor+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Bits e, A.Bits e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_xor runN dim e =+ property $ do+ sh1 <- forAll dim+ sh2 <- forAll dim+ xs <- forAll (array sh1 e)+ ys <- forAll (array sh2 e)+ let !go = runN (A.zipWith A.xor) in go xs ys ~~~ zipWithRef P.xor xs ys++{-# NOINLINE test_shift #-}+test_shift+ :: forall sh e. (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.FiniteBits e, A.FiniteBits e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_shift runN dim e =+ property $ do+ let s = P.finiteBitSize (undefined::e)+ sh1 <- forAll dim+ sh2 <- forAll dim+ xs <- forAll (array sh1 e)+ ys <- forAll (array sh2 (Gen.int (Range.linearFrom 0 (-s) s)))+ let !go = runN (A.zipWith A.shift) in go xs ys ~~~ zipWithRef P.shift xs ys++{-# NOINLINE test_shiftL #-}+test_shiftL+ :: forall sh e. (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.FiniteBits e, A.FiniteBits e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_shiftL runN dim e =+ property $ do+ let s = P.finiteBitSize (undefined::e)+ sh1 <- forAll dim+ sh2 <- forAll dim+ xs <- forAll (array sh1 e)+ ys <- forAll (array sh2 (Gen.int (Range.linear 0 s)))+ let !go = runN (A.zipWith A.shiftL) in go xs ys ~~~ zipWithRef P.shiftL xs ys++{-# NOINLINE test_shiftR #-}+test_shiftR+ :: forall sh e. (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.FiniteBits e, A.FiniteBits e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_shiftR runN dim e =+ property $ do+ let s = P.finiteBitSize (undefined::e)+ sh1 <- forAll dim+ sh2 <- forAll dim+ xs <- forAll (array sh1 e)+ ys <- forAll (array sh2 (Gen.int (Range.linear 0 s)))+ let !go = runN (A.zipWith A.shiftR) in go xs ys ~~~ zipWithRef P.shiftR xs ys++{-# NOINLINE test_rotate #-}+test_rotate+ :: forall sh e. (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.FiniteBits e, A.FiniteBits e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_rotate runN dim e =+ property $ do+ let s = P.finiteBitSize (undefined::e)+ sh1 <- forAll dim+ sh2 <- forAll dim+ xs <- forAll (array sh1 e)+ ys <- forAll (array sh2 (Gen.int (Range.linearFrom 0 (-s) s)))+ let !go = runN (A.zipWith A.rotate) in go xs ys ~~~ zipWithRef P.rotate xs ys++{-# NOINLINE test_rotateL #-}+test_rotateL+ :: forall sh e. (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.FiniteBits e, A.FiniteBits e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_rotateL runN dim e =+ property $ do+ let s = P.finiteBitSize (undefined::e)+ sh1 <- forAll dim+ sh2 <- forAll dim+ xs <- forAll (array sh1 e)+ ys <- forAll (array sh2 (Gen.int (Range.linear 0 s)))+ let !go = runN (A.zipWith A.rotateL) in go xs ys ~~~ zipWithRef P.rotateL xs ys++{-# NOINLINE test_rotateR #-}+test_rotateR+ :: forall sh e. (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.FiniteBits e, A.FiniteBits e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_rotateR runN dim e =+ property $ do+ let s = P.finiteBitSize (undefined::e)+ sh1 <- forAll dim+ sh2 <- forAll dim+ xs <- forAll (array sh1 e)+ ys <- forAll (array sh2 (Gen.int (Range.linear 0 s)))+ let !go = runN (A.zipWith A.rotateR) in go xs ys ~~~ zipWithRef P.rotateR xs ys++{-# NOINLINE test_lt #-}+test_lt+ :: (Shape sh, Show sh, Show e, P.Eq sh, P.Ord e, A.Ord e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_lt runN dim e =+ property $ do+ sh1 <- forAll dim+ sh2 <- forAll dim+ xs <- forAll (array sh1 e)+ ys <- forAll (array sh2 e)+ let !go = runN (A.zipWith (A.<)) in go xs ys ~~~ zipWithRef (P.<) xs ys++{-# NOINLINE test_gt #-}+test_gt+ :: (Shape sh, Show sh, Show e, P.Eq sh, P.Ord e, A.Ord e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_gt runN dim e =+ property $ do+ sh1 <- forAll dim+ sh2 <- forAll dim+ xs <- forAll (array sh1 e)+ ys <- forAll (array sh2 e)+ let !go = runN (A.zipWith (A.>)) in go xs ys ~~~ zipWithRef (P.>) xs ys++{-# NOINLINE test_lte #-}+test_lte+ :: (Shape sh, Show sh, Show e, P.Eq sh, P.Ord e, A.Ord e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_lte runN dim e =+ property $ do+ sh1 <- forAll dim+ sh2 <- forAll dim+ xs <- forAll (array sh1 e)+ ys <- forAll (array sh2 e)+ let !go = runN (A.zipWith (A.<=)) in go xs ys ~~~ zipWithRef (P.<=) xs ys++{-# NOINLINE test_gte #-}+test_gte+ :: (Shape sh, Show sh, Show e, P.Eq sh, P.Ord e, A.Ord e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_gte runN dim e =+ property $ do+ sh1 <- forAll dim+ sh2 <- forAll dim+ xs <- forAll (array sh1 e)+ ys <- forAll (array sh2 e)+ let !go = runN (A.zipWith (A.>=)) in go xs ys ~~~ zipWithRef (P.>=) xs ys++{-# NOINLINE test_eq #-}+test_eq+ :: (Shape sh, Show sh, Show e, P.Eq sh, P.Ord e, A.Ord e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_eq runN dim e =+ property $ do+ sh1 <- forAll dim+ sh2 <- forAll dim+ xs <- forAll (array sh1 e)+ ys <- forAll (array sh2 e)+ let !go = runN (A.zipWith (A.==)) in go xs ys ~~~ zipWithRef (P.==) xs ys++{-# NOINLINE test_neq #-}+test_neq+ :: (Shape sh, Show sh, Show e, P.Eq sh, P.Ord e, A.Ord e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_neq runN dim e =+ property $ do+ sh1 <- forAll dim+ sh2 <- forAll dim+ xs <- forAll (array sh1 e)+ ys <- forAll (array sh2 e)+ let !go = runN (A.zipWith (A./=)) in go xs ys ~~~ zipWithRef (P./=) xs ys++{-# NOINLINE test_min #-}+test_min+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Ord e, A.Ord e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_min runN dim e =+ property $ do+ sh1 <- forAll dim+ sh2 <- forAll dim+ xs <- forAll (array sh1 e)+ ys <- forAll (array sh2 e)+ let !go = runN (A.zipWith (A.min)) in go xs ys ~~~ zipWithRef (P.min) xs ys++{-# NOINLINE test_max #-}+test_max+ :: (Shape sh, Show sh, Similar e, Show e, P.Eq sh, P.Ord e, A.Ord e)+ => RunN+ -> Gen sh+ -> Gen e+ -> Property+test_max runN dim e =+ property $ do+ sh1 <- forAll dim+ sh2 <- forAll dim+ xs <- forAll (array sh1 e)+ ys <- forAll (array sh2 e)+ let !go = runN (A.zipWith (A.max)) in go xs ys ~~~ zipWithRef (P.max) xs ys+++-- Reference Implementation+-- ------------------------++zipWithRef+ :: (Shape sh, Elt a, Elt b, Elt c)+ => (a -> b -> c)+ -> Array sh a+ -> Array sh b+ -> Array sh c+zipWithRef f xs ys =+ fromFunction+ (S.shape xs `S.intersect` S.shape ys)+ (\ix -> f (xs S.! ix) (ys S.! ix))+
+ src/Data/Array/Accelerate/Test/NoFib/Sharing.hs view
@@ -0,0 +1,334 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeOperators #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Sharing+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Test.NoFib.Sharing (++ test_sharing++) where++import Data.Array.Accelerate as A hiding ( exp )+import Data.Array.Accelerate.Trafo.Sharing+import Data.Array.Accelerate.Data.Bits as A++import Control.DeepSeq+import Control.Exception+import Test.Tasty+import Test.Tasty.ExpectedFailure+import Test.Tasty.HUnit+import Prelude as P hiding ( exp )+++test_sharing :: TestTree+test_sharing =+ testGroup "sharing"+ [ testCase "simple" $ sharingAcc test_simple+ , testCase "ordering" $ sharingAcc test_ordering+ , testCase "sort" $ sharingAcc test_sort+ , testCase "blowup" $ sharingAcc (test_blowup 20)+ , testCase "bfs" $ sharingAcc test_bfs+ , testGroup "same level"+ [ testCase "1" $ sharingAcc test_two_lets_same_level_1+ , testCase "2" $ sharingAcc test_two_lets_same_level_2+ ]+ , testGroup "empty top"+ [ testCase "1" $ sharingAcc test_no_let_at_top_1+ , testCase "2" $ sharingAcc test_no_let_at_top_2+ ]+ , testCase "pipe" $ sharingAcc test_pipe+ , testCase "bound variables" $ sharingAcc test_bound_variables+ , testCase "big tuple" $ sharingExp test_big_tuple+ , testGroup "iteration"+ [ testCase "simple" $ sharingAcc test_iteration_simple+ , testCase "outside" $ sharingAcc test_iteration_outside+ , testCase "body and condition" $ sharingAcc test_iteration_body_condition+ , testCase "awhile" $ sharingAcc test_awhile+ , testCase "iterate" $ sharingAcc test_iterate+ , testCase "nested" $ sharingExp test_nested_iteration+ , testCase "unused" $ sharingExp test_unused_iteration+ ]+ , testGroup "nested data-parallelism"+ [ expectFail $ testCase "mvm" $ sharingAcc test_nested_data_parallelism+ ]+ ]+ where+ sharingAcc :: Arrays a => Acc a -> Assertion+ sharingAcc acc =+ catch (rnf (convertAcc acc) `seq` pure ())+ (\(e :: SomeException) -> assertFailure (show e))++ sharingExp :: Elt e => Exp e -> Assertion+ sharingExp exp =+ catch (rnf (convertExp exp) `seq` pure ())+ (\(e :: SomeException) -> assertFailure (show e))+++--------------------------------------------------------------------------------+--+-- Some tests to make sure that sharing recovery is working.+--++mkArray :: Int -> Acc (Array DIM1 Int)+mkArray n = use $ fromList (Z:.1) [n]++test_blowup :: Int -> Acc (Array DIM1 Int)+test_blowup 0 = (mkArray 0)+test_blowup n = A.map (\_ -> newArr ! (lift (Z:.(0::Int))) ++ newArr ! (lift (Z:.(1::Int)))) (mkArray n)+ where+ newArr = test_blowup (n-1)++idx :: Int -> Exp DIM1+idx i = lift (Z:.i)++test_bfs :: Acc (Array DIM1 Int)+test_bfs = A.map (\x -> (map2 ! (idx 1)) + (map1 ! (idx 2)) + x) arr+ where+ map1 :: Acc (Array DIM1 Int)+ map1 = A.map (\y -> (map2 ! (idx 3)) + y) arr++ map2 :: Acc (Array DIM1 Int)+ map2 = A.map (\z -> z + 1) arr++ arr :: Acc (Array DIM1 Int)+ arr = mkArray 666++test_two_lets_same_level_1 :: Acc (Array DIM1 Int)+test_two_lets_same_level_1 =+ let arr1 = mkArray 1+ in let arr2 = mkArray 2+ in A.map (\_ -> arr1!(idx 1) + arr1!(idx 2) + arr2!(idx 3) + arr2!(idx 4)) (mkArray 3)++test_two_lets_same_level_2 :: Acc (Array DIM1 Int)+test_two_lets_same_level_2 =+ let arr2 = mkArray 2+ in let arr1 = mkArray 1+ in A.map (\_ -> arr1!(idx 1) + arr1!(idx 2) + arr2!(idx 3) + arr2!(idx 4)) (mkArray 3)+++-- These two programs test that lets can be introduced not just at the top of a AST+-- but in intermediate nodes.+--+test_no_let_at_top_1 :: Acc (Array DIM1 Int)+test_no_let_at_top_1 = A.map (\x -> x + 1) test_bfs++test_no_let_at_top_2 :: Acc (Array DIM1 Int)+test_no_let_at_top_2+ = A.map (\x -> x + 2)+ $ A.map (\x -> x + 1) test_bfs++--+--+--+test_simple :: Acc (Array DIM1 (Int,Int))+test_simple = A.map (\_ -> a ! (idx 1)) d+ where+ c = use $ A.fromList (Z :. 3) [1..]+ d = A.map (+1) c+ a = A.zip d c+++-- sortKey is a real program that Ben Lever wrote. It has some pretty interesting+-- sharing going on.+--+sortKey :: (Elt e)+ => (Exp e -> Exp Int) -- ^mapping function to produce key array from input array+ -> Acc (Vector e)+ -> Acc (Vector e)+sortKey keyFun arr = foldl sortOneBit arr (P.map lift ([0..31] :: [Int]))+ where+ sortOneBit inArr bitNum = outArr+ where+ keys = A.map keyFun inArr++ bits = A.map (\a -> (A.testBit a bitNum) ? (1, 0)) keys+ bitsInv = A.map (\b -> (b A.== 0) ? (1, 0)) bits++ (falses, numZeroes) = unlift (A.scanl' (+) 0 bitsInv)+ trues = A.map (\x -> (A.the numZeroes) + (A.fst x) - (A.snd x))+ $ A.zip ixs falses++ dstIxs = A.map (\x -> let (b, t, f) = unlift x in (b A.== (constant (0::Int))) ? (f, t))+ $ A.zip3 bits trues falses+ outArr = scatter dstIxs inArr inArr -- just use input as default array+ --(we're writing over everything anyway)+ --+ ixs = enumeratedArray (shape arr)++-- Create an array where each element is the value of its corresponding+-- row-major index.+--+enumeratedArray :: Exp DIM1 -> Acc (Array DIM1 Int)+enumeratedArray sh = A.generate sh unindex1++test_sort :: Acc (Vector Int)+test_sort = sortKey id $ use $ fromList (Z:.10) [9,8,7,6,5,4,3,2,1,0]++-- map1 has children map3 and map2.+-- map2 has child map3.+-- Back when we still used a list for the NodeCounts data structure this mean that+-- you would be merging [1,3,2] with [2,3] which violated precondition of (+++).+-- This tests that the new algorithm works just fine on this.+--+test_ordering :: Acc (Array DIM1 Int)+test_ordering = A.map (\_ -> map1 ! (idx 1) + map2 ! (idx 1)) arr+ where+ map1 = A.map (\_ -> map3 ! (idx 1) + map2 ! (idx 2)) arr+ map2 = A.map (\_ -> map3 ! (idx 3)) arr+ map3 = A.map (+1) arr+ arr = mkArray 42+++-- Tests array-valued lambdas in conjunction with sharing recovery.+--+test_pipe :: Acc (Vector Int)+test_pipe = (acc1 >-> acc2) xs+ where+ z :: Acc (Scalar Int)+ z = unit 0++ xs :: Acc (Vector Int)+ xs = use $ fromList (Z:.10) [0..]++ acc1 :: Acc (Vector Int) -> Acc (Vector Int)+ acc1 = A.map (\_ -> the z)++ acc2 :: Acc (Vector Int) -> Acc (Vector Int)+ acc2 arr = let arr2 = use $ fromList (Z:.10) [10..]+ in A.map (\_ -> arr2!constant (Z:.(0::Int))) (A.zip arr arr2)+++-- Test for bound variables+--+test_bound_variables :: Acc (Array DIM2 Int, Array DIM2 Float, Array DIM2 Float)+test_bound_variables = lift (first, both, second)+ where+ is :: Array DIM2 Int+ is = fromList (Z:.10:.10) [0..]++ fs :: Array DIM2 Float+ fs = fromList (Z:.10:.10) [0..]++ -- Ignoring the first parameter+ first = stencil2 centre clamp (use fs) clamp (use is)+ where+ centre :: Stencil3x3 Float -> Stencil3x3 Int -> Exp Int+ centre _ (_,(_,y,_),_) = y++ -- Using both+ both = stencil2 centre clamp (use fs) clamp (use is)+ where+ centre :: Stencil3x3 Float -> Stencil3x3 Int -> Exp Float+ centre (_,(_,x,_),_) (_,(_,y,_),_) = x + A.fromIntegral y++ -- Not using the second parameter+ second = stencil2 centre clamp (use fs) clamp (use is)+ where+ centre :: Stencil3x3 Float -> Stencil3x3 Int -> Exp Float+ centre (_,(_,x,_),_) _ = x++-- Test for 8 and 9 tuples+--+test_big_tuple :: Exp ((Int,Int,Int,Int,Int,Int,Int,Int), (Int,Int,Int,Int,Int,Int,Int,Int,Int))+test_big_tuple = lift (A.constant (0,0,0,0,0,0,0,0), A.constant (0,0,0,0,0,0,0,0,0))++{--+-- Tests for sharing recovery of iteration+--+iteration :: Test+iteration = testGroup "iteration"+ [+ iter "simple" test1+ , iter "outside" test2+ , iter "body and condition" test3+ , iter "awhile" awhile_test+ , iter "iterate" iterate_test+ , iter "nested" nested+ , iter "unused" unused+ ]+ where+ iter :: Show a => TestName -> a -> Test+ iter name acc = testCase name (P.length (show acc) `seq` return ())+--}++v1 :: Acc (Vector Float)+v1 = use $ fromList (Z:.10) [0..]++test_iteration_simple :: Acc (Vector Float)+test_iteration_simple+ = flip A.map v1+ $ \x -> A.while (A.< x) (+1) 0++test_iteration_outside :: Acc (Vector Float)+test_iteration_outside+ = flip A.map v1+ $ \x -> let y = 2*pi+ in y + A.while (A.< 10) (+y) x++test_iteration_body_condition :: Acc (Vector Float)+test_iteration_body_condition+ = flip A.map v1+ $ \x -> A.while (A.< x) (+x) 0++test_awhile :: Acc (Vector Float)+test_awhile = A.awhile (\a -> A.unit (the (A.sum a) A.< 200)) (A.map (+1)) v1++test_iterate :: Acc (Vector Float)+test_iterate+ = flip A.map v1+ $ \x -> let y = 2*x+ in y + A.iterate (constant 10) (\x' -> y + x' + 10) x++test_for :: Elt a => Exp Int -> (Exp Int -> Exp a -> Exp a) -> Exp a -> Exp a+test_for n f seed+ = A.snd+ $ A.iterate n (\v -> let (i, x) = unlift v+ in lift (i+1, f i x))+ (lift (constant 0, seed))++test_nested_iteration :: Exp Int+test_nested_iteration =+ test_for 64 (\i _ ->+ test_for 64 (\j acc' -> i + j + acc') 0) 0++test_unused_iteration :: Exp Int+test_unused_iteration =+ A.while (A.== 10) (const 10) 5++----------------------------------------------------------------------++-- This program contains nested data-parallelism and thus sharing recovery+-- will fail.+--+test_nested_data_parallelism :: Acc (Vector Float)+test_nested_data_parallelism =+ mvm (use $ fromList (Z:.10:.10) [0..]) (use $ fromList (Z:.10) [0..])+ where+ dotp :: A.Num e => Acc (Vector e) -> Acc (Vector e) -> Acc (Scalar e)+ dotp xs ys = A.fold (+) 0 $ A.zipWith (*) xs ys++ takeRow :: Elt e => Exp Int -> Acc (Array DIM2 e) -> Acc (Vector e)+ takeRow n mat =+ let Z :. _ :. cols = unlift (shape mat) :: Z:. Exp Int :. Exp Int+ in backpermute (index1 cols)+ (\ix -> index2 n (unindex1 ix))+ mat++ mvm :: A.Num e => Acc (Array DIM2 e) -> Acc (Vector e) -> Acc (Vector e)+ mvm mat vec =+ let Z :. rows :. _ = unlift (shape mat) :: Z :. Exp Int :. Exp Int+ in generate (index1 rows)+ (\ix -> the (vec `dotp` takeRow (unindex1 ix) mat))+
+ src/Data/Array/Accelerate/Test/NoFib/Spectral.hs view
@@ -0,0 +1,37 @@+{-# LANGUAGE RankNTypes #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Spectral+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Test.NoFib.Spectral (++ test_spectral,++ module Data.Array.Accelerate.Test.NoFib.Spectral.SMVM,+ module Data.Array.Accelerate.Test.NoFib.Spectral.RadixSort,+ module Data.Array.Accelerate.Test.NoFib.Spectral.BlackScholes,++) where++import Test.Tasty++import Data.Array.Accelerate.Test.NoFib.Base+import Data.Array.Accelerate.Test.NoFib.Spectral.SMVM+import Data.Array.Accelerate.Test.NoFib.Spectral.RadixSort+import Data.Array.Accelerate.Test.NoFib.Spectral.BlackScholes+++test_spectral :: RunN -> TestTree+test_spectral runN =+ testGroup "spectral"+ [ test_blackscholes runN+ , test_smvm runN+ , test_radixsort runN+ ]+
+ src/Data/Array/Accelerate/Test/NoFib/Spectral/BlackScholes.hs view
@@ -0,0 +1,131 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE ViewPatterns #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Spectral.BlackScholes+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Test.NoFib.Spectral.BlackScholes (++ test_blackscholes,++) where++import Prelude as P++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Sugar.Elt as S+import Data.Array.Accelerate.Sugar.Array as S+import Data.Array.Accelerate.Test.NoFib.Base+import Data.Array.Accelerate.Test.NoFib.Config+import Data.Array.Accelerate.Test.Similar++import Hedgehog+import qualified Hedgehog.Gen as Gen+import qualified Hedgehog.Range as Range++import Test.Tasty+import Test.Tasty.Hedgehog+++test_blackscholes :: RunN -> TestTree+test_blackscholes runN =+ testGroup "blackscholes"+ [ at @TestHalf $ testElt (Gen.realFloat :: Range Half -> Gen Half)+ , at @TestFloat $ testElt Gen.float+ , at @TestDouble $ testElt Gen.double+ ]+ where+ testElt+ :: forall a. (P.Floating a, P.Ord a, A.Floating a, A.Ord a , Similar a, Show a)+ => (Range a -> Gen a)+ -> TestTree+ testElt e =+ testProperty (show (eltR @a)) $ test_blackscholes' runN e+++test_blackscholes'+ :: (P.Floating a, P.Ord a, A.Floating a, A.Ord a, Similar a, Show a)+ => RunN+ -> (Range a -> Gen a)+ -> Property+test_blackscholes' runN e =+ property $ do+ sh <- forAll ((Z :.) P.<$> Gen.int (Range.linear 0 16384))+ psy <- forAll (array sh ((,,) P.<$> e (Range.linearFrac 5 30)+ P.<*> e (Range.linearFrac 1 100)+ P.<*> e (Range.linearFrac 0.25 10)))+ --+ let !go = runN blackscholes in go psy ~~~ blackscholesRef psy+++riskfree, volatility :: P.Floating a => a+riskfree = 0.02+volatility = 0.30++horner :: P.Num a => [a] -> a -> a+horner coeff x = x * foldr1 madd coeff+ where+ madd a b = a + x*b++cnd' :: P.Floating a => a -> a+cnd' d =+ let poly = horner coeff+ coeff = [0.31938153,-0.356563782,1.781477937,-1.821255978,1.330274429]+ rsqrt2pi = 0.39894228040143267793994605993438+ k = 1.0 / (1.0 + 0.2316419 * abs d)+ in+ rsqrt2pi * exp (-0.5*d*d) * poly k+++blackscholes :: (P.Floating a, A.Floating a, A.Ord a) => Acc (Vector (a, a, a)) -> Acc (Vector (a, a))+blackscholes = A.map go+ where+ go (A.unlift -> (price,strike,years)) =+ let+ r = A.constant riskfree+ v = A.constant volatility+ v_sqrtT = v * sqrt years+ d1 = (log (price / strike) + (r + 0.5 * v * v) * years) / v_sqrtT+ d2 = d1 - v_sqrtT+ cnd d = let c = cnd' d in d A.> 0 ? (1.0 - c, c)+ cndD1 = cnd d1+ cndD2 = cnd d2+ x_expRT = strike * exp (-r * years)+ in+ A.lift ( price * cndD1 - x_expRT * cndD2+ , x_expRT * (1.0 - cndD2) - price * (1.0 - cndD1))+++blackscholesRef :: (P.Floating a, P.Ord a, Elt a) => Vector (a, a, a) -> Vector (a, a)+blackscholesRef psy = fromFunction (S.shape psy) (go . indexArray psy)+ where+ go (price, strike, years) =+ let+ r = riskfree+ v = volatility+ v_sqrtT = v * sqrt years+ d1 = (log (price / strike) + (r + 0.5 * v * v) * years) / v_sqrtT+ d2 = d1 - v_sqrtT+ cnd d = let c = cnd' d in if d P.> 0+ then 1.0 - c+ else c+ cndD1 = cnd d1+ cndD2 = cnd d2+ x_expRT = strike * exp (-r * years)+ in+ ( price * cndD1 - x_expRT * cndD2+ , x_expRT * (1.0 - cndD2) - price * (1.0 - cndD1)+ )+
+ src/Data/Array/Accelerate/Test/NoFib/Spectral/RadixSort.hs view
@@ -0,0 +1,187 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE MonoLocalBinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeOperators #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Spectral.RadixSort+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Test.NoFib.Spectral.RadixSort (++ test_radixsort,++) where++import Data.Function+import Data.List ( sortBy )+import Prelude as P+import qualified Data.Bits as P++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Data.Bits as A+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Test.NoFib.Base+import Data.Array.Accelerate.Test.NoFib.Config+import Data.Array.Accelerate.Test.Similar++import Hedgehog+import qualified Hedgehog.Gen as Gen+import qualified Hedgehog.Range as Range++import Test.Tasty+import Test.Tasty.Hedgehog+++test_radixsort :: RunN -> TestTree+test_radixsort runN =+ testGroup "radixsort"+ [ at @TestInt8 $ testElt i8+ , at @TestInt16 $ testElt i16+ , at @TestInt32 $ testElt i32+ , at @TestInt64 $ testElt i64+ , at @TestWord8 $ testElt w8+ , at @TestWord16 $ testElt w16+ , at @TestWord32 $ testElt w32+ , at @TestWord64 $ testElt w64+ -- , at @TestFloat $ testElt f32+ -- , at @TestDouble $ testElt f64+ ]+ where+ testElt :: forall a. (Similar a, P.Ord a, Radix a, Show a)+ => Gen a+ -> TestTree+ testElt e =+ testGroup (show (eltR @a))+ [ testProperty "ascending" $ test_sort_ascending runN e+ , testProperty "descending" $ test_sort_descending runN e+ , testProperty "key-value" $ test_sort_keyval runN e f32+ ]++test_sort_ascending+ :: (P.Ord e, Radix e, Similar e, Show e)+ => RunN+ -> Gen e+ -> Property+test_sort_ascending runN e =+ property $ do+ sh <- forAll ((Z :.) P.<$> Gen.int (Range.linear 0 128)) -- just pick a small array; the algorithm is terrible+ xs <- forAll (array sh e)+ let !go = runN radixsort in go xs ~~~ sortRef P.compare xs++test_sort_descending+ :: (P.Ord e, Radix e, Similar e, Show e)+ => RunN+ -> Gen e+ -> Property+test_sort_descending runN e =+ property $ do+ sh <- forAll ((Z :.) P.<$> Gen.int (Range.linear 0 128))+ xs <- forAll (array sh e)+ let !go = runN (radixsortBy complement) in go xs ~~~ sortRef (flip P.compare) xs++test_sort_keyval+ :: (P.Ord k, Radix k, Similar k, Show k, Elt v, Similar v, Show v)+ => RunN+ -> Gen k+ -> Gen v+ -> Property+test_sort_keyval runN key val =+ property $ do+ sh <- forAll ((Z :.) P.<$> Gen.int (Range.linear 0 128))+ xs <- forAll (array sh ((,) P.<$> key P.<*> val))+ let !go = runN (radixsortBy A.fst) in go xs ~~~ sortRef (P.compare `on` P.fst) xs+++class A.Bits e => Radix e where+ passes :: e {- dummy -} -> Int+ radix :: Exp Int -> Exp e -> Exp Int++instance Radix Int8 where+ passes = P.finiteBitSize+ radix = radixOfSigned++instance Radix Int16 where+ passes = P.finiteBitSize+ radix = radixOfSigned++instance Radix Int32 where+ passes = P.finiteBitSize+ radix = radixOfSigned++instance Radix Int64 where+ passes = P.finiteBitSize+ radix = radixOfSigned++instance Radix Word8 where+ passes = P.finiteBitSize+ radix = radixOfUnsigned++instance Radix Word16 where+ passes = P.finiteBitSize+ radix = radixOfUnsigned++instance Radix Word32 where+ passes = P.finiteBitSize+ radix = radixOfUnsigned++instance Radix Word64 where+ passes = P.finiteBitSize+ radix = radixOfUnsigned++radixOfSigned+ :: forall e. (Radix e, A.Bounded e, A.Integral e, A.FromIntegral e Int)+ => Exp Int+ -> Exp e+ -> Exp Int+radixOfSigned i e = i A.== (passes' - 1) ? (radix' (e `xor` minBound), radix' e)+ where+ radix' x = A.fromIntegral $ (x `A.shiftR` i) .&. 1+ passes' = constant (passes (undefined :: e))++radixOfUnsigned+ :: (Radix e, A.Integral e, A.FromIntegral e Int)+ => Exp Int+ -> Exp e+ -> Exp Int+radixOfUnsigned i e = A.fromIntegral $ (e `A.shiftR` i) .&. 1+++-- A simple (parallel) radix sort implementation [1].+--+-- [1] G. E. Blelloch. "Prefix sums and their applications." Technical Report+-- CMU-CS-90-190. Carnegie Mellon University. 1990.+--+radixsort :: Radix a => Acc (Vector a) -> Acc (Vector a)+radixsort = radixsortBy id++radixsortBy :: forall a r. (Elt a, Radix r) => (Exp a -> Exp r) -> Acc (Vector a) -> Acc (Vector a)+radixsortBy rdx arr = foldr1 (>->) (P.map radixPass [0..p-1]) arr+ where+ p = passes (undefined :: r)+ --+ deal f x = let (a,b) = unlift x in (f A.== 0) ? (a,b)+ radixPass k v = let k' = unit (constant k)+ flags = A.map (radix (the k') . rdx) v+ idown = prescanl (+) 0 . A.map (xor 1) $ flags+ iup = A.map (size v - 1 -) . prescanr (+) 0 $ flags+ index = A.zipWith deal flags (A.zip idown iup)+ in+ permute const v (\ix -> Just_ (index1 (index!ix))) v+++-- This is rather slow. Speeding up the reference implementation by using, say,+-- vector-algorithms, does not significantly change the runtime.+--+sortRef :: Elt a => (a -> a -> Ordering) -> Vector a -> Vector a+sortRef cmp xs = fromList (arrayShape xs) (sortBy cmp (toList xs))+
+ src/Data/Array/Accelerate/Test/NoFib/Spectral/SMVM.hs view
@@ -0,0 +1,92 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeOperators #-}+-- |+-- Module : Data.Array.Accelerate.Test.NoFib.Spectral.SMVM+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Test.NoFib.Spectral.SMVM (++ test_smvm,++) where++import Prelude as P++import Data.Array.Accelerate as A+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Test.NoFib.Base+import Data.Array.Accelerate.Test.NoFib.Config+import Data.Array.Accelerate.Test.Similar++import Hedgehog+import qualified Hedgehog.Gen as Gen+import qualified Hedgehog.Range as Range++import Test.Tasty+import Test.Tasty.Hedgehog+++test_smvm :: RunN -> TestTree+test_smvm runN =+ testGroup "smvm"+ [ at @TestHalf $ testElt f16+ , at @TestFloat $ testElt f32+ , at @TestDouble $ testElt f64+ ]+ where+ testElt :: forall a. (P.Num a, A.Num a, Similar a, Show a)+ => Gen a+ -> TestTree+ testElt e =+ testProperty (show (eltR @a)) $ test_smvm' runN e+++test_smvm' :: (A.Num e, P.Num e, Similar e, Show e) => RunN -> Gen e -> Property+test_smvm' runN e =+ property $ do+ (smat, cols) <- forAll (sparseMatrix e)+ vec <- forAll (array (Z:.cols) e)+ --+ let !go = runN smvm in go smat vec ~~~ smvmRef smat vec+++sparseMatrix :: Elt e => Gen e -> Gen (SparseMatrix e, Int)+sparseMatrix e = do+ rows <- Gen.int (Range.linear 1 256)+ cols <- Gen.int (Range.linear 1 256)+ seg <- array (Z:.rows) (Gen.int (Range.linear 0 cols))+ let nnz = P.sum (toList seg)+ smat <- array (Z:.nnz) ((,) P.<$> Gen.int (Range.linear 0 (cols-1)) <*> e)+ P.return ((seg,smat), cols)+++type SparseVector e = Vector (Int, e)+type SparseMatrix e = (Segments Int, SparseVector e)++smvm :: A.Num a => Acc (SparseMatrix a) -> Acc (Vector a) -> Acc (Vector a)+smvm smat vec+ = let (segd, svec) = unlift smat+ (inds, vals) = A.unzip svec++ vecVals = A.gather inds vec+ products = A.zipWith (*) vecVals vals+ in+ foldSeg (+) 0 products segd++smvmRef :: (Elt a, P.Num a) => SparseMatrix a -> Vector a -> Vector a+smvmRef (segd, smat) vec =+ fromList (arrayShape segd)+ [ P.sum [ val * indexArray vec (Z :. i) | (i,val) <- row ]+ | row <- splitPlaces (toList segd) (toList smat) ]+
+ src/Data/Array/Accelerate/Test/Similar.hs view
@@ -0,0 +1,191 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeOperators #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Test.Similar+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Test.Similar+ where++import Data.Array.Accelerate.Data.Complex+import Data.Array.Accelerate.Sugar.Array+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Sugar.Shape+import Data.Array.Accelerate.Type++import Hedgehog+import Hedgehog.Internal.Source ( HasCallStack, withFrozenCallStack )++import Prelude hiding ( (!!) )+++-- | Fails the test if the two arguments are not equal, allowing for a small+-- amount of floating point inaccuracy.+--+infix 4 ~~~+(~~~) :: (MonadTest m, Similar a, Show a, HasCallStack) => a -> a -> m ()+a ~~~ b = withFrozenCallStack $ Sim a === Sim b++data Sim a = Sim a++instance Similar a => Eq (Sim a) where+ Sim a == Sim b = a ~= b++instance Show a => Show (Sim a) where+ show (Sim a) = show a+++-- | A class of things that support almost-equality, so that we can disregard+-- small amounts of floating-point round-off error.+--+class Similar a where+ {-# INLINE (~=) #-}+ (~=) :: a -> a -> Bool+ default (~=) :: Eq a => a -> a -> Bool+ (~=) = (==)++infix 4 ~=++instance Similar ()+instance Similar Z+instance Similar All+instance Similar Int+instance Similar Int8+instance Similar Int16+instance Similar Int32+instance Similar Int64+instance Similar Word8+instance Similar Word16+instance Similar Word32+instance Similar Word64+instance Similar Char+instance Similar Bool+instance Similar CShort+instance Similar CUShort+instance Similar CInt+instance Similar CUInt+instance Similar CLong+instance Similar CULong+instance Similar CLLong+instance Similar CULLong+instance Similar CChar+instance Similar CSChar+instance Similar CUChar++instance Similar (Any Z)+instance (Eq sh, Eq sz) => Similar (sh:.sz)+instance (Eq sh) => Similar (Any (sh:.Int))++instance Similar Half where (~=) = absRelTol 0.05 0.5+instance Similar Float where (~=) = absRelTol 0.00005 0.005+instance Similar Double where (~=) = absRelTol 0.00005 0.005+instance Similar CFloat where (~=) = absRelTol 0.00005 0.005+instance Similar CDouble where (~=) = absRelTol 0.00005 0.005++instance (Similar a, Similar b) => Similar (a, b) where+ (x1, x2) ~= (y1, y2) = x1 ~= y1 && x2 ~= y2++instance (Similar a, Similar b, Similar c) => Similar (a, b, c) where+ (x1, x2, x3) ~= (y1, y2, y3) = x1 ~= y1 && x2 ~= y2 && x3 ~= y3++instance (Similar a, Similar b, Similar c, Similar d) => Similar (a, b, c, d) where+ (x1, x2, x3, x4) ~= (y1, y2, y3, y4) = x1 ~= y1 && x2 ~= y2 && x3 ~= y3 && x4 ~= y4++instance (Similar a, Similar b, Similar c, Similar d, Similar e)+ => Similar (a, b, c, d, e) where+ (x1, x2, x3, x4, x5) ~= (y1, y2, y3, y4, y5) =+ x1 ~= y1 && x2 ~= y2 && x3 ~= y3 && x4 ~= y4 && x5 ~= y5++instance (Similar a, Similar b, Similar c, Similar d, Similar e, Similar f)+ => Similar (a, b, c, d, e, f) where+ (x1, x2, x3, x4, x5, x6) ~= (y1, y2, y3, y4, y5, y6) =+ x1 ~= y1 && x2 ~= y2 && x3 ~= y3 && x4 ~= y4 && x5 ~= y5 && x6 ~= y6++instance (Similar a, Similar b, Similar c, Similar d, Similar e, Similar f, Similar g)+ => Similar (a, b, c, d, e, f, g) where+ (x1, x2, x3, x4, x5, x6, x7) ~= (y1, y2, y3, y4, y5, y6, y7) =+ x1 ~= y1 && x2 ~= y2 && x3 ~= y3 && x4 ~= y4 && x5 ~= y5 && x6 ~= y6 && x7 ~= y7++instance (Similar a, Similar b, Similar c, Similar d, Similar e, Similar f, Similar g, Similar h)+ => Similar (a, b, c, d, e, f, g, h) where+ (x1, x2, x3, x4, x5, x6, x7, x8) ~= (y1, y2, y3, y4, y5, y6, y7, y8) =+ x1 ~= y1 && x2 ~= y2 && x3 ~= y3 && x4 ~= y4 && x5 ~= y5 && x6 ~= y6 && x7 ~= y7 && x8 ~= y8++instance (Similar a, Similar b, Similar c, Similar d, Similar e, Similar f, Similar g, Similar h, Similar i)+ => Similar (a, b, c, d, e, f, g, h, i) where+ (x1, x2, x3, x4, x5, x6, x7, x8, x9) ~= (y1, y2, y3, y4, y5, y6, y7, y8, y9) =+ x1 ~= y1 && x2 ~= y2 && x3 ~= y3 && x4 ~= y4 && x5 ~= y5 && x6 ~= y6 && x7 ~= y7 && x8 ~= y8 && x9 ~= y9++instance (Similar a, Similar b, Similar c, Similar d, Similar e, Similar f, Similar g, Similar h, Similar i, Similar j)+ => Similar (a, b, c, d, e, f, g, h, i, j) where+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10) ~= (y1, y2, y3, y4, y5, y6, y7, y8, y9, y10) =+ x1 ~= y1 && x2 ~= y2 && x3 ~= y3 && x4 ~= y4 && x5 ~= y5 && x6 ~= y6 && x7 ~= y7 && x8 ~= y8 && x9 ~= y9 && x10 ~= y10++instance (Similar a, Similar b, Similar c, Similar d, Similar e, Similar f, Similar g, Similar h, Similar i, Similar j, Similar k)+ => Similar (a, b, c, d, e, f, g, h, i, j, k) where+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11) ~= (y1, y2, y3, y4, y5, y6, y7, y8, y9, y10, y11) =+ x1 ~= y1 && x2 ~= y2 && x3 ~= y3 && x4 ~= y4 && x5 ~= y5 && x6 ~= y6 && x7 ~= y7 && x8 ~= y8 && x9 ~= y9 && x10 ~= y10 && x11 ~= y11++instance (Similar a, Similar b, Similar c, Similar d, Similar e, Similar f, Similar g, Similar h, Similar i, Similar j, Similar k, Similar l)+ => Similar (a, b, c, d, e, f, g, h, i, j, k, l) where+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12) ~= (y1, y2, y3, y4, y5, y6, y7, y8, y9, y10, y11, y12) =+ x1 ~= y1 && x2 ~= y2 && x3 ~= y3 && x4 ~= y4 && x5 ~= y5 && x6 ~= y6 && x7 ~= y7 && x8 ~= y8 && x9 ~= y9 && x10 ~= y10 && x11 ~= y11 && x12 ~= y12++instance (Similar a, Similar b, Similar c, Similar d, Similar e, Similar f, Similar g, Similar h, Similar i, Similar j, Similar k, Similar l, Similar m)+ => Similar (a, b, c, d, e, f, g, h, i, j, k, l, m) where+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13) ~= (y1, y2, y3, y4, y5, y6, y7, y8, y9, y10, y11, y12, y13) =+ x1 ~= y1 && x2 ~= y2 && x3 ~= y3 && x4 ~= y4 && x5 ~= y5 && x6 ~= y6 && x7 ~= y7 && x8 ~= y8 && x9 ~= y9 && x10 ~= y10 && x11 ~= y11 && x12 ~= y12 && x13 ~= y13++instance (Similar a, Similar b, Similar c, Similar d, Similar e, Similar f, Similar g, Similar h, Similar i, Similar j, Similar k, Similar l, Similar m, Similar n)+ => Similar (a, b, c, d, e, f, g, h, i, j, k, l, m, n) where+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14) ~= (y1, y2, y3, y4, y5, y6, y7, y8, y9, y10, y11, y12, y13, y14) =+ x1 ~= y1 && x2 ~= y2 && x3 ~= y3 && x4 ~= y4 && x5 ~= y5 && x6 ~= y6 && x7 ~= y7 && x8 ~= y8 && x9 ~= y9 && x10 ~= y10 && x11 ~= y11 && x12 ~= y12 && x13 ~= y13 && x14 ~= y14++instance (Similar a, Similar b, Similar c, Similar d, Similar e, Similar f, Similar g, Similar h, Similar i, Similar j, Similar k, Similar l, Similar m, Similar n, Similar o)+ => Similar (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) where+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15) ~= (y1, y2, y3, y4, y5, y6, y7, y8, y9, y10, y11, y12, y13, y14, y15) =+ x1 ~= y1 && x2 ~= y2 && x3 ~= y3 && x4 ~= y4 && x5 ~= y5 && x6 ~= y6 && x7 ~= y7 && x8 ~= y8 && x9 ~= y9 && x10 ~= y10 && x11 ~= y11 && x12 ~= y12 && x13 ~= y13 && x14 ~= y14 && x15 ~= y15++instance (Similar a, Similar b, Similar c, Similar d, Similar e, Similar f, Similar g, Similar h, Similar i, Similar j, Similar k, Similar l, Similar m, Similar n, Similar o, Similar p)+ => Similar (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) where+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16) ~= (y1, y2, y3, y4, y5, y6, y7, y8, y9, y10, y11, y12, y13, y14, y15, y16) =+ x1 ~= y1 && x2 ~= y2 && x3 ~= y3 && x4 ~= y4 && x5 ~= y5 && x6 ~= y6 && x7 ~= y7 && x8 ~= y8 && x9 ~= y9 && x10 ~= y10 && x11 ~= y11 && x12 ~= y12 && x13 ~= y13 && x14 ~= y14 && x15 ~= y15 && x16 ~= y16++instance Similar e => Similar (Complex e) where+ (r1 :+ i1) ~= (r2 :+ i2) = r1 ~= r2 && i1 ~= i2++instance Similar a => Similar [a] where+ [] ~= [] = True+ (x:xs) ~= (y:ys) = x ~= y && xs ~= ys+ _ ~= _ = False++instance (Similar e, Eq sh, Shape sh, Elt e) => Similar (Array sh e) where+ a1 ~= a2 = shape a1 == shape a2 && go 0+ where+ n = size (shape a1)+ go !i+ | i >= n = True+ | a1 !! i ~= a2 !! i = go (i+1)+ | otherwise = False++{-# INLINEABLE absRelTol #-}+absRelTol :: RealFloat a => a -> a -> a -> a -> Bool+absRelTol epsilonAbs epsilonRel u v+ | isInfinite u+ && isInfinite v = True+ | isNaN u+ && isNaN v = True+ | abs (u-v) < epsilonAbs = True+ | abs u > abs v = abs ((u-v) / u) < epsilonRel+ | otherwise = abs ((v-u) / v) < epsilonRel+
+ src/Data/Array/Accelerate/Trafo.hs view
@@ -0,0 +1,142 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Trafo+-- Copyright : [2012..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Trafo (++ -- * HOAS -> de Bruijn conversion+ -- ** Array computations+ convertAcc, convertAccWith,++ -- ** Array functions+ Afunction, ArraysFunctionR,+ convertAfun, convertAfunWith,++ -- ** Sequence computations+ -- convertSeq, convertSeqWith,++ -- ** Scalar expressions+ Function, EltFunctionR,+ convertExp, convertFun,++) where++import Data.Array.Accelerate.Sugar.Array ( ArraysR )+import Data.Array.Accelerate.Sugar.Elt ( EltR )+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Trafo.Config+import Data.Array.Accelerate.Trafo.Delayed+import Data.Array.Accelerate.Trafo.Sharing ( Afunction, ArraysFunctionR, Function, EltFunctionR )+import qualified Data.Array.Accelerate.AST as AST+import qualified Data.Array.Accelerate.Trafo.Fusion as Fusion+import qualified Data.Array.Accelerate.Trafo.LetSplit as LetSplit+import qualified Data.Array.Accelerate.Trafo.Simplify as Rewrite+import qualified Data.Array.Accelerate.Trafo.Sharing as Sharing+-- import qualified Data.Array.Accelerate.Trafo.Vectorise as Vectorise++import Control.DeepSeq+import Data.Text.Lazy.Builder++#ifdef ACCELERATE_DEBUG+import Formatting+import System.IO.Unsafe+import Data.Array.Accelerate.Debug.Internal.Flags hiding ( when )+import Data.Array.Accelerate.Debug.Internal.Timed+#endif+++-- HOAS -> de Bruijn conversion+-- ----------------------------++-- | Convert a closed array expression to de Bruijn form while also+-- incorporating sharing observation and array fusion.+--+convertAcc :: Acc arrs -> DelayedAcc (ArraysR arrs)+convertAcc = convertAccWith defaultOptions++convertAccWith :: Config -> Acc arrs -> DelayedAcc (ArraysR arrs)+convertAccWith config+ = phase "array-fusion" (Fusion.convertAccWith config)+ . phase "array-split-lets" LetSplit.convertAcc+ -- phase "vectorise-sequences" Vectorise.vectoriseSeqAcc `when` vectoriseSequences+ . phase "sharing-recovery" (Sharing.convertAccWith config)+++-- | Convert a unary function over array computations, incorporating sharing+-- observation and array fusion+--+convertAfun :: Afunction f => f -> DelayedAfun (ArraysFunctionR f)+convertAfun = convertAfunWith defaultOptions++convertAfunWith :: Afunction f => Config -> f -> DelayedAfun (ArraysFunctionR f)+convertAfunWith config+ = phase "array-fusion" (Fusion.convertAfunWith config)+ . phase "array-split-lets" LetSplit.convertAfun+ -- phase "vectorise-sequences" Vectorise.vectoriseSeqAfun `when` vectoriseSequences+ . phase "sharing-recovery" (Sharing.convertAfunWith config)+++-- | Convert a closed scalar expression, incorporating sharing observation and+-- optimisation.+--+convertExp :: Exp e -> AST.Exp () (EltR e)+convertExp+ = phase "exp-simplify" Rewrite.simplifyExp+ . phase "sharing-recovery" Sharing.convertExp+++-- | Convert closed scalar functions, incorporating sharing observation and+-- optimisation.+--+convertFun :: Function f => f -> AST.Fun () (EltFunctionR f)+convertFun+ = phase "exp-simplify" Rewrite.simplifyFun+ . phase "sharing-recovery" Sharing.convertFun++{--+-- | Convert a closed sequence computation, incorporating sharing observation and+-- optimisation.+--+convertSeq :: Typeable s => Seq s -> DelayedSeq s+convertSeq = convertSeqWith phases++convertSeqWith :: Typeable s => Phase -> Seq s -> DelayedSeq s+convertSeqWith Phase{..} s+ = phase "array-fusion" (Fusion.convertSeq enableAccFusion)+ -- $ phase "vectorise-sequences" Vectorise.vectoriseSeq `when` vectoriseSequences+ -- $ phase "rewrite-segment-offset" Rewrite.convertSegmentsSeq `when` convertOffsetOfSegment+ $ phase "sharing-recovery" (Sharing.convertSeq recoverAccSharing recoverExpSharing recoverSeqSharing floatOutAccFromExp)+ $ s+--}+++-- when :: (a -> a) -> Bool -> a -> a+-- when f True = f+-- when _ False = id++-- Debugging+-- ---------++-- Execute a phase of the compiler and (possibly) print some timing/gc+-- statistics.+--+phase :: NFData b => Builder -> (a -> b) -> a -> b+#ifdef ACCELERATE_DEBUG+phase n f x = unsafePerformIO $ do+ enabled <- getFlag dump_phases+ if enabled+ then timed dump_phases (now ("phase " <> n <> ": ") % elapsed) (return $!! f x)+ else return (f x)+#else+phase _ f = f+#endif+
+ src/Data/Array/Accelerate/Trafo/Algebra.hs view
@@ -0,0 +1,744 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE ViewPatterns #-}+-- |+-- Module : Data.Array.Accelerate.Trafo.Algebra+-- Copyright : [2012..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- Algebraic simplifications of scalar expressions, including constant folding+-- and using algebraic properties of particular operator-operand combinations.+--++module Data.Array.Accelerate.Trafo.Algebra (++ evalPrimApp,++) where++import Data.Array.Accelerate.AST+import Data.Array.Accelerate.AST.Var+import Data.Array.Accelerate.Analysis.Match+import Data.Array.Accelerate.Pretty.Print ( primOperator, isInfix, opName )+import Data.Array.Accelerate.Trafo.Environment+import Data.Array.Accelerate.Type++import qualified Data.Array.Accelerate.Debug.Internal.Stats as Stats++import Data.Bits+import Data.Monoid+import Data.Text ( Text )+import Prettyprinter+import Prettyprinter.Render.Text+import Prelude hiding ( exp )+import qualified Prelude as P++import GHC.Float ( float2Double, double2Float )+++-- Propagate constant expressions, which are either constant valued expressions+-- or constant let bindings. Be careful not to follow self-cycles.+--+propagate+ :: forall env aenv exp.+ Gamma env env aenv+ -> OpenExp env aenv exp+ -> Maybe exp+propagate env = cvtE+ where+ cvtE :: OpenExp env aenv e -> Maybe e+ cvtE exp = case exp of+ Const _ c -> Just c+ PrimConst c -> Just (evalPrimConst c)+ Evar (Var _ ix)+ | e <- prjExp ix env+ , Nothing <- matchOpenExp exp e -> cvtE e+ Nil -> Just ()+ Pair e1 e2 -> (,) <$> cvtE e1 <*> cvtE e2+ _ -> Nothing+++-- Attempt to evaluate primitive function applications+--+evalPrimApp+ :: forall env aenv a r.+ Gamma env env aenv+ -> PrimFun (a -> r)+ -> OpenExp env aenv a+ -> (Any, OpenExp env aenv r)+evalPrimApp env f x+ -- First attempt to move constant values towards the left+ | Just r <- commutes f x env = evalPrimApp env f r+-- | Just r <- associates f x = r++ -- Now attempt to evaluate any expressions+ | otherwise+ = maybe (Any False, PrimApp f x) (Any True,)+ $ case f of+ PrimAdd ty -> evalAdd ty x env+ PrimSub ty -> evalSub ty x env+ PrimMul ty -> evalMul ty x env+ PrimNeg ty -> evalNeg ty x env+ PrimAbs ty -> evalAbs ty x env+ PrimSig ty -> evalSig ty x env+ PrimQuot ty -> evalQuot ty x env+ PrimRem ty -> evalRem ty x env+ PrimQuotRem ty -> evalQuotRem ty x env+ PrimIDiv ty -> evalIDiv ty x env+ PrimMod ty -> evalMod ty x env+ PrimDivMod ty -> evalDivMod ty x env+ PrimBAnd ty -> evalBAnd ty x env+ PrimBOr ty -> evalBOr ty x env+ PrimBXor ty -> evalBXor ty x env+ PrimBNot ty -> evalBNot ty x env+ PrimBShiftL ty -> evalBShiftL ty x env+ PrimBShiftR ty -> evalBShiftR ty x env+ PrimBRotateL ty -> evalBRotateL ty x env+ PrimBRotateR ty -> evalBRotateR ty x env+ PrimPopCount ty -> evalPopCount ty x env+ PrimCountLeadingZeros ty -> evalCountLeadingZeros ty x env+ PrimCountTrailingZeros ty -> evalCountTrailingZeros ty x env+ PrimFDiv ty -> evalFDiv ty x env+ PrimRecip ty -> evalRecip ty x env+ PrimSin ty -> evalSin ty x env+ PrimCos ty -> evalCos ty x env+ PrimTan ty -> evalTan ty x env+ PrimAsin ty -> evalAsin ty x env+ PrimAcos ty -> evalAcos ty x env+ PrimAtan ty -> evalAtan ty x env+ PrimSinh ty -> evalSinh ty x env+ PrimCosh ty -> evalCosh ty x env+ PrimTanh ty -> evalTanh ty x env+ PrimAsinh ty -> evalAsinh ty x env+ PrimAcosh ty -> evalAcosh ty x env+ PrimAtanh ty -> evalAtanh ty x env+ PrimExpFloating ty -> evalExpFloating ty x env+ PrimSqrt ty -> evalSqrt ty x env+ PrimLog ty -> evalLog ty x env+ PrimFPow ty -> evalFPow ty x env+ PrimLogBase ty -> evalLogBase ty x env+ PrimAtan2 ty -> evalAtan2 ty x env+ PrimTruncate ta tb -> evalTruncate ta tb x env+ PrimRound ta tb -> evalRound ta tb x env+ PrimFloor ta tb -> evalFloor ta tb x env+ PrimCeiling ta tb -> evalCeiling ta tb x env+ PrimIsNaN ty -> evalIsNaN ty x env+ PrimIsInfinite ty -> evalIsInfinite ty x env+ PrimLt ty -> evalLt ty x env+ PrimGt ty -> evalGt ty x env+ PrimLtEq ty -> evalLtEq ty x env+ PrimGtEq ty -> evalGtEq ty x env+ PrimEq ty -> evalEq ty x env+ PrimNEq ty -> evalNEq ty x env+ PrimMax ty -> evalMax ty x env+ PrimMin ty -> evalMin ty x env+ PrimLAnd -> evalLAnd x env+ PrimLOr -> evalLOr x env+ PrimLNot -> evalLNot x env+ PrimFromIntegral ta tb -> evalFromIntegral ta tb x env+ PrimToFloating ta tb -> evalToFloating ta tb x env+++-- Discriminate binary functions that commute, and if so return the operands in+-- a stable ordering. If only one of the arguments is a constant, this is placed+-- to the left of the operator. Returning Nothing indicates no change is made.+--+commutes+ :: forall env aenv a r.+ PrimFun (a -> r)+ -> OpenExp env aenv a+ -> Gamma env env aenv+ -> Maybe (OpenExp env aenv a)+commutes f x env = case f of+ PrimAdd _ -> swizzle x+ PrimMul _ -> swizzle x+ PrimBAnd _ -> swizzle x+ PrimBOr _ -> swizzle x+ PrimBXor _ -> swizzle x+ PrimEq _ -> swizzle x+ PrimNEq _ -> swizzle x+ PrimMax _ -> swizzle x+ PrimMin _ -> swizzle x+ _ -> Nothing+ where+ swizzle :: OpenExp env aenv (b,b) -> Maybe (OpenExp env aenv (b,b))+ swizzle (Pair a b)+ | Nothing <- propagate env a+ , Just _ <- propagate env b+ = Stats.ruleFired (pprFun "commutes" f)+ $ Just $ Pair b a++-- TLM: changing the ordering here when neither term can be reduced can be+-- disadvantageous: for example in (x &&* y), the user might have put a+-- simpler condition first that is designed to fail fast.+--+-- | Nothing <- propagate env a+-- , Nothing <- propagate env b+-- , hashOpenExp a > hashOpenExp b+-- = Just $ Tuple (NilTup `SnocTup` b `SnocTup` a)++ swizzle _+ = Nothing+++{--+-- Determine if successive applications of a binary operator will associate, and+-- if so move them to the left. That is:+--+-- a + (b + c) --> (a + b) + c+--+-- Returning Nothing indicates no change is made.+--+-- TLM: we might get into trouble here, as we've lost track of where the user+-- has explicitly put parenthesis.+--+-- TLM: BROKEN!! does not correctly change the sign of expressions when flipping+-- (-x+y) or (-y+x).+--+associates+ :: (Elt a, Elt r)+ => PrimFun (a -> r)+ -> OpenExp env aenv a+ -> Maybe (OpenExp env aenv r)+associates fun exp = case fun of+ PrimAdd _ -> swizzle fun exp [PrimAdd ty, PrimSub ty]+ PrimSub _ -> swizzle fun exp [PrimAdd ty, PrimSub ty]+ PrimLAnd -> swizzle fun exp [fun]+ PrimLOr -> swizzle fun exp [fun]+ _ -> swizzle fun exp [fun]+ where+ -- TODO: check the list of ops is complete (and correct)+ ty = undefined+ ops = [ PrimMul ty, PrimFDiv ty, PrimAdd ty, PrimSub ty, PrimBAnd ty, PrimBOr ty, PrimBXor ty ]++ swizzle :: (Elt a, Elt r) => PrimFun (a -> r) -> OpenExp env aenv a -> [PrimFun (a -> r)] -> Maybe (OpenExp env aenv r)+ swizzle f x lvl+ | Just Refl <- matches f ops+ , Just (a,bc) <- untup2 x+ , PrimApp g y <- bc+ , Just Refl <- matches g lvl+ , Just (b,c) <- untup2 y+ = Stats.ruleFired (pprFun "associates" f)+ $ Just $ PrimApp g (tup2 (PrimApp f (tup2 (a,b)), c))++ swizzle _ _ _+ = Nothing++ matches :: (Elt s, Elt t) => PrimFun (s -> a) -> [PrimFun (t -> a)] -> Maybe (s :=: t)+ matches _ [] = Nothing+ matches f (x:xs)+ | Just Refl <- matchPrimFun' f x+ = Just Refl++ | otherwise+ = matches f xs+--}+++-- Helper functions+-- ----------------++type a :-> b = forall env aenv. OpenExp env aenv a -> Gamma env env aenv -> Maybe (OpenExp env aenv b)++eval1 :: SingleType b -> (a -> b) -> a :-> b+eval1 tp f x env+ | Just a <- propagate env x = Stats.substitution "constant fold" . Just $ Const (SingleScalarType tp) (f a)+ | otherwise = Nothing++eval2 :: SingleType c -> (a -> b -> c) -> (a,b) :-> c+eval2 tp f (untup2 -> Just (x,y)) env+ | Just a <- propagate env x+ , Just b <- propagate env y+ = Stats.substitution "constant fold"+ $ Just $ Const (SingleScalarType tp) (f a b)+eval2 _ _ _ _+ = Nothing++fromBool :: Bool -> PrimBool+fromBool False = 0+fromBool True = 1++toBool :: PrimBool -> Bool+toBool 0 = False+toBool _ = True++bool1 :: (a -> Bool) -> a :-> PrimBool+bool1 f x env+ | Just a <- propagate env x+ = Stats.substitution "constant fold"+ . Just $ Const scalarTypeWord8 (fromBool (f a))+bool1 _ _ _+ = Nothing++bool2 :: (a -> b -> Bool) -> (a,b) :-> PrimBool+bool2 f (untup2 -> Just (x,y)) env+ | Just a <- propagate env x+ , Just b <- propagate env y+ = Stats.substitution "constant fold"+ $ Just $ Const scalarTypeWord8 (fromBool (f a b))+bool2 _ _ _+ = Nothing++tup2 :: (OpenExp env aenv a, OpenExp env aenv b) -> OpenExp env aenv (a, b)+tup2 (a,b) = Pair a b++untup2 :: OpenExp env aenv (a, b) -> Maybe (OpenExp env aenv a, OpenExp env aenv b)+untup2 exp+ | Pair a b <- exp = Just (a, b)+ | otherwise = Nothing+++pprFun :: Text -> PrimFun f -> Text+pprFun rule f+ = renderStrict+ . layoutCompact+ $ pretty rule <+> f'+ where+ op = primOperator f+ f' = if isInfix op+ then parens (opName op)+ else opName op+++-- Methods of Num+-- --------------++evalAdd :: NumType a -> (a,a) :-> a+evalAdd ty@(IntegralNumType ty') | IntegralDict <- integralDict ty' = evalAdd' ty+evalAdd ty@(FloatingNumType ty') | FloatingDict <- floatingDict ty' = evalAdd' ty++evalAdd' :: (Eq a, Num a) => NumType a -> (a,a) :-> a+evalAdd' _ (untup2 -> Just (x,y)) env+ | Just a <- propagate env x+ , a == 0+ = Stats.ruleFired "x+0" $ Just y++evalAdd' ty arg env+ = eval2 (NumSingleType ty) (+) arg env+++evalSub :: NumType a -> (a,a) :-> a+evalSub ty@(IntegralNumType ty') | IntegralDict <- integralDict ty' = evalSub' ty+evalSub ty@(FloatingNumType ty') | FloatingDict <- floatingDict ty' = evalSub' ty++evalSub' :: forall a. (Eq a, Num a) => NumType a -> (a,a) :-> a+evalSub' ty (untup2 -> Just (x,y)) env+ | Just b <- propagate env y+ , b == 0+ = Stats.ruleFired "x-0" $ Just x++ | Nothing <- propagate env x+ , Just b <- propagate env y+ = Stats.ruleFired "-y+x"+ $ Just . snd $ evalPrimApp env (PrimAdd ty) (Const tp (-b) `Pair` x)+ -- (Tuple $ NilTup `SnocTup` Const (fromElt (-b)) `SnocTup` x)++ | Just Refl <- matchOpenExp x y+ = Stats.ruleFired "x-x"+ $ Just $ Const tp 0+ where+ tp = SingleScalarType $ NumSingleType ty++evalSub' ty arg env+ = eval2 (NumSingleType ty) (-) arg env+++evalMul :: NumType a -> (a,a) :-> a+evalMul ty@(IntegralNumType ty') | IntegralDict <- integralDict ty' = evalMul' ty+evalMul ty@(FloatingNumType ty') | FloatingDict <- floatingDict ty' = evalMul' ty++evalMul' :: (Eq a, Num a) => NumType a -> (a,a) :-> a+evalMul' _ (untup2 -> Just (x,y)) env+ | Just a <- propagate env x+ , Nothing <- propagate env y+ = case a of+ 0 -> Stats.ruleFired "x*0" $ Just x+ 1 -> Stats.ruleFired "x*1" $ Just y+ _ -> Nothing++evalMul' ty arg env+ = eval2 (NumSingleType ty) (*) arg env++evalNeg :: NumType a -> a :-> a+evalNeg _ x _ | PrimApp PrimNeg{} x' <- x = Stats.ruleFired "negate/negate" $ Just x'+evalNeg (IntegralNumType ty) x env | IntegralDict <- integralDict ty = eval1 (NumSingleType $ IntegralNumType ty) negate x env+evalNeg (FloatingNumType ty) x env | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) negate x env++evalAbs :: NumType a -> a :-> a+evalAbs (IntegralNumType ty) | IntegralDict <- integralDict ty = eval1 (NumSingleType $ IntegralNumType ty) abs+evalAbs (FloatingNumType ty) | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) abs++evalSig :: NumType a -> a :-> a+evalSig (IntegralNumType ty) | IntegralDict <- integralDict ty = eval1 (NumSingleType $ IntegralNumType ty) signum+evalSig (FloatingNumType ty) | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) signum+++-- Methods of Integral & Bits+-- --------------------------++evalQuot :: IntegralType a -> (a,a) :-> a+evalQuot ty exp env+ | Just qr <- evalQuotRem ty exp env+ , Just (q,_) <- untup2 qr+ = Just q+evalQuot _ _ _+ = Nothing++evalRem :: IntegralType a -> (a,a) :-> a+evalRem ty exp env+ | Just qr <- evalQuotRem ty exp env+ , Just (_,r) <- untup2 qr+ = Just r+evalRem _ _ _+ = Nothing++evalQuotRem :: forall a. IntegralType a -> (a,a) :-> (a,a)+evalQuotRem ty exp env+ | IntegralDict <- integralDict ty+ , Just (x, y) <- untup2 exp+ , Just b <- propagate env y+ = case b of+ 0 -> Nothing+ 1 -> Stats.ruleFired "quotRem x 1" $ Just (tup2 (x, Const tp 0))+ _ -> case propagate env x of+ Nothing -> Nothing+ Just a -> Stats.substitution "constant fold"+ $ Just $ let (u,v) = quotRem a b+ in tup2 (Const tp u, Const tp v)+ where+ tp = SingleScalarType $ NumSingleType $ IntegralNumType ty+evalQuotRem _ _ _+ = Nothing+++evalIDiv :: IntegralType a -> (a,a) :-> a+evalIDiv ty exp env+ | Just dm <- evalDivMod ty exp env+ , Just (d,_) <- untup2 dm+ = Just d+evalIDiv _ _ _+ = Nothing++evalMod :: IntegralType a -> (a,a) :-> a+evalMod ty exp env+ | Just dm <- evalDivMod ty exp env+ , Just (_,m) <- untup2 dm+ = Just m+evalMod _ _ _+ = Nothing++evalDivMod :: forall a. IntegralType a -> (a,a) :-> (a,a)+evalDivMod ty exp env+ | IntegralDict <- integralDict ty+ , Just (x, y) <- untup2 exp+ , Just b <- propagate env y+ = case b of+ 0 -> Nothing+ 1 -> Stats.ruleFired "divMod x 1" $ Just (tup2 (x, Const tp 0))+ _ -> case propagate env x of+ Nothing -> Nothing+ Just a -> Stats.substitution "constant fold"+ $ Just $ let (u,v) = divMod a b+ in tup2 (Const tp u, Const tp v)+ where+ tp = SingleScalarType $ NumSingleType $ IntegralNumType ty+evalDivMod _ _ _+ = Nothing++evalBAnd :: IntegralType a -> (a,a) :-> a+evalBAnd ty | IntegralDict <- integralDict ty = eval2 (NumSingleType $ IntegralNumType ty) (.&.)++evalBOr :: IntegralType a -> (a,a) :-> a+evalBOr ty | IntegralDict <- integralDict ty = evalBOr' ty++evalBOr' :: (Eq a, Num a, Bits a) => IntegralType a -> (a,a) :-> a+evalBOr' _ (untup2 -> Just (x,y)) env+ | Just 0 <- propagate env x+ = Stats.ruleFired "x .|. 0" $ Just y++evalBOr' ty arg env+ = eval2 (NumSingleType $ IntegralNumType ty) (.|.) arg env++evalBXor :: IntegralType a -> (a,a) :-> a+evalBXor ty | IntegralDict <- integralDict ty = eval2 (NumSingleType $ IntegralNumType ty) xor++evalBNot :: IntegralType a -> a :-> a+evalBNot ty | IntegralDict <- integralDict ty = eval1 (NumSingleType $ IntegralNumType ty) complement++evalBShiftL :: IntegralType a -> (a,Int) :-> a+evalBShiftL _ (untup2 -> Just (x,i)) env+ | Just 0 <- propagate env i+ = Stats.ruleFired "x `shiftL` 0" $ Just x++evalBShiftL ty arg env+ | IntegralDict <- integralDict ty = eval2 (NumSingleType $ IntegralNumType ty) shiftL arg env++evalBShiftR :: IntegralType a -> (a,Int) :-> a+evalBShiftR _ (untup2 -> Just (x,i)) env+ | Just 0 <- propagate env i+ = Stats.ruleFired "x `shiftR` 0" $ Just x++evalBShiftR ty arg env+ | IntegralDict <- integralDict ty = eval2 (NumSingleType $ IntegralNumType ty) shiftR arg env++evalBRotateL :: IntegralType a -> (a,Int) :-> a+evalBRotateL _ (untup2 -> Just (x,i)) env+ | Just 0 <- propagate env i+ = Stats.ruleFired "x `rotateL` 0" $ Just x+evalBRotateL ty arg env+ | IntegralDict <- integralDict ty = eval2 (NumSingleType $ IntegralNumType ty) rotateL arg env++evalBRotateR :: IntegralType a -> (a,Int) :-> a+evalBRotateR _ (untup2 -> Just (x,i)) env+ | Just 0 <- propagate env i+ = Stats.ruleFired "x `rotateR` 0" $ Just x+evalBRotateR ty arg env+ | IntegralDict <- integralDict ty = eval2 (NumSingleType $ IntegralNumType ty) rotateR arg env++evalPopCount :: IntegralType a -> a :-> Int+evalPopCount ty | IntegralDict <- integralDict ty = eval1 (NumSingleType $ IntegralNumType TypeInt) popCount++evalCountLeadingZeros :: IntegralType a -> a :-> Int+evalCountLeadingZeros ty | IntegralDict <- integralDict ty = eval1 (NumSingleType $ IntegralNumType TypeInt) countLeadingZeros++evalCountTrailingZeros :: IntegralType a -> a :-> Int+evalCountTrailingZeros ty | IntegralDict <- integralDict ty = eval1 (NumSingleType $ IntegralNumType TypeInt) countTrailingZeros+++-- Methods of Fractional & Floating+-- --------------------------------++evalFDiv :: FloatingType a -> (a,a) :-> a+evalFDiv ty | FloatingDict <- floatingDict ty = evalFDiv' ty++evalFDiv' :: (Fractional a, Eq a) => FloatingType a -> (a,a) :-> a+evalFDiv' _ (untup2 -> Just (x,y)) env+ | Just 1 <- propagate env y+ = Stats.ruleFired "x/1" $ Just x++evalFDiv' ty arg env+ = eval2 (NumSingleType $ FloatingNumType ty) (/) arg env+++evalRecip :: FloatingType a -> a :-> a+evalRecip ty | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) recip++evalSin :: FloatingType a -> a :-> a+evalSin ty | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) sin++evalCos :: FloatingType a -> a :-> a+evalCos ty | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) cos++evalTan :: FloatingType a -> a :-> a+evalTan ty | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) tan++evalAsin :: FloatingType a -> a :-> a+evalAsin ty | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) asin++evalAcos :: FloatingType a -> a :-> a+evalAcos ty | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) acos++evalAtan :: FloatingType a -> a :-> a+evalAtan ty | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) atan++evalSinh :: FloatingType a -> a :-> a+evalSinh ty | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) sinh++evalCosh :: FloatingType a -> a :-> a+evalCosh ty | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) cosh++evalTanh :: FloatingType a -> a :-> a+evalTanh ty | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) tanh++evalAsinh :: FloatingType a -> a :-> a+evalAsinh ty | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) asinh++evalAcosh :: FloatingType a -> a :-> a+evalAcosh ty | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) acosh++evalAtanh :: FloatingType a -> a :-> a+evalAtanh ty | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) atanh++evalExpFloating :: FloatingType a -> a :-> a+evalExpFloating ty | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) P.exp++evalSqrt :: FloatingType a -> a :-> a+evalSqrt ty | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) sqrt++evalLog :: FloatingType a -> a :-> a+evalLog ty | FloatingDict <- floatingDict ty = eval1 (NumSingleType $ FloatingNumType ty) log++evalFPow :: FloatingType a -> (a,a) :-> a+evalFPow ty | FloatingDict <- floatingDict ty = eval2 (NumSingleType $ FloatingNumType ty) (**)++evalLogBase :: FloatingType a -> (a,a) :-> a+evalLogBase ty | FloatingDict <- floatingDict ty = eval2 (NumSingleType $ FloatingNumType ty) logBase++evalAtan2 :: FloatingType a -> (a,a) :-> a+evalAtan2 ty | FloatingDict <- floatingDict ty = eval2 (NumSingleType $ FloatingNumType ty) atan2++evalTruncate :: FloatingType a -> IntegralType b -> a :-> b+evalTruncate ta tb+ | FloatingDict <- floatingDict ta+ , IntegralDict <- integralDict tb+ = eval1 (NumSingleType $ IntegralNumType tb) truncate++evalRound :: FloatingType a -> IntegralType b -> a :-> b+evalRound ta tb+ | FloatingDict <- floatingDict ta+ , IntegralDict <- integralDict tb+ = eval1 (NumSingleType $ IntegralNumType tb) round++evalFloor :: FloatingType a -> IntegralType b -> a :-> b+evalFloor ta tb+ | FloatingDict <- floatingDict ta+ , IntegralDict <- integralDict tb+ = eval1 (NumSingleType $ IntegralNumType tb) floor++evalCeiling :: FloatingType a -> IntegralType b -> a :-> b+evalCeiling ta tb+ | FloatingDict <- floatingDict ta+ , IntegralDict <- integralDict tb+ = eval1 (NumSingleType $ IntegralNumType tb) ceiling++evalIsNaN :: FloatingType a -> a :-> PrimBool+evalIsNaN ty | FloatingDict <- floatingDict ty = bool1 isNaN++evalIsInfinite :: FloatingType a -> a :-> PrimBool+evalIsInfinite ty | FloatingDict <- floatingDict ty = bool1 isInfinite+++-- Relational & Equality+-- ---------------------++evalLt :: SingleType a -> (a,a) :-> PrimBool+evalLt (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = bool2 (<)+evalLt (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = bool2 (<)++evalGt :: SingleType a -> (a,a) :-> PrimBool+evalGt (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = bool2 (>)+evalGt (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = bool2 (>)++evalLtEq :: SingleType a -> (a,a) :-> PrimBool+evalLtEq (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = bool2 (<=)+evalLtEq (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = bool2 (<=)++evalGtEq :: SingleType a -> (a,a) :-> PrimBool+evalGtEq (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = bool2 (>=)+evalGtEq (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = bool2 (>=)++evalEq :: SingleType a -> (a,a) :-> PrimBool+evalEq (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = bool2 (==)+evalEq (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = bool2 (==)++evalNEq :: SingleType a -> (a,a) :-> PrimBool+evalNEq (NumSingleType (IntegralNumType ty)) | IntegralDict <- integralDict ty = bool2 (/=)+evalNEq (NumSingleType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = bool2 (/=)++evalMax :: SingleType a -> (a,a) :-> a+evalMax ty@(NumSingleType (IntegralNumType ty')) | IntegralDict <- integralDict ty' = eval2 ty max+evalMax ty@(NumSingleType (FloatingNumType ty')) | FloatingDict <- floatingDict ty' = eval2 ty max++evalMin :: SingleType a -> (a,a) :-> a+evalMin ty@(NumSingleType (IntegralNumType ty')) | IntegralDict <- integralDict ty' = eval2 ty min+evalMin ty@(NumSingleType (FloatingNumType ty')) | FloatingDict <- floatingDict ty' = eval2 ty min++-- Logical operators+-- -----------------++evalLAnd :: (PrimBool,PrimBool) :-> PrimBool+evalLAnd (untup2 -> Just (x,y)) env+ | Just a <- propagate env x+ = Just+ $ if toBool a then Stats.ruleFired "True &&" y+ else Stats.ruleFired "False &&" $ Const scalarTypeWord8 0++ | Just b <- propagate env y+ = Just+ $ if toBool b then Stats.ruleFired "True &&" x+ else Stats.ruleFired "False &&" $ Const scalarTypeWord8 0++evalLAnd _ _+ = Nothing++evalLOr :: (PrimBool,PrimBool) :-> PrimBool+evalLOr (untup2 -> Just (x,y)) env+ | Just a <- propagate env x+ = Just+ $ if toBool a then Stats.ruleFired "True ||" $ Const scalarTypeWord8 1+ else Stats.ruleFired "False ||" y++ | Just b <- propagate env y+ = Just+ $ if toBool b then Stats.ruleFired "True ||" $ Const scalarTypeWord8 1+ else Stats.ruleFired "False ||" x++evalLOr _ _+ = Nothing++evalLNot :: PrimBool :-> PrimBool+evalLNot x _ | PrimApp PrimLNot x' <- x = Stats.ruleFired "not/not" $ Just x'+evalLNot x env = bool1 (not . toBool) x env++evalFromIntegral :: IntegralType a -> NumType b -> a :-> b+evalFromIntegral ta (IntegralNumType tb)+ | IntegralDict <- integralDict ta+ , IntegralDict <- integralDict tb = eval1 (NumSingleType $ IntegralNumType tb) fromIntegral++evalFromIntegral ta (FloatingNumType tb)+ | IntegralDict <- integralDict ta+ , FloatingDict <- floatingDict tb = eval1 (NumSingleType $ FloatingNumType tb) fromIntegral++evalToFloating :: NumType a -> FloatingType b -> a :-> b+evalToFloating (IntegralNumType ta) tb x env+ | IntegralDict <- integralDict ta+ , FloatingDict <- floatingDict tb = eval1 (NumSingleType $ FloatingNumType tb) realToFrac x env++evalToFloating (FloatingNumType ta) tb x env+ | TypeHalf <- ta+ , TypeHalf <- tb = Just x++ | TypeFloat <- ta+ , TypeFloat <- tb = Just x++ | TypeDouble <- ta+ , TypeDouble <- tb = Just x++ | TypeFloat <- ta+ , TypeDouble <- tb = eval1 (NumSingleType $ FloatingNumType tb) float2Double x env++ | TypeDouble <- ta+ , TypeFloat <- tb = eval1 (NumSingleType $ FloatingNumType tb) double2Float x env++ | FloatingDict <- floatingDict ta+ , FloatingDict <- floatingDict tb = eval1 (NumSingleType $ FloatingNumType tb) realToFrac x env+++-- Scalar primitives+-- -----------------++evalPrimConst :: PrimConst a -> a+evalPrimConst (PrimMinBound ty) = evalMinBound ty+evalPrimConst (PrimMaxBound ty) = evalMaxBound ty+evalPrimConst (PrimPi ty) = evalPi ty++evalMinBound :: BoundedType a -> a+evalMinBound (IntegralBoundedType ty) | IntegralDict <- integralDict ty = minBound++evalMaxBound :: BoundedType a -> a+evalMaxBound (IntegralBoundedType ty) | IntegralDict <- integralDict ty = maxBound++evalPi :: FloatingType a -> a+evalPi ty | FloatingDict <- floatingDict ty = pi+
+ src/Data/Array/Accelerate/Trafo/Config.hs view
@@ -0,0 +1,37 @@+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Trafo.Config+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Trafo.Config (++ Config(..),+ Flag(..),+ defaultOptions,++) where++import Data.BitSet+import Data.Array.Accelerate.Debug.Internal.Flags as F++import Data.Word+import System.IO.Unsafe+import Foreign.Storable+++data Config = Config+ { options :: {-# UNPACK #-} !(BitSet Word32 Flag)+ }+ deriving Show++{-# NOINLINE defaultOptions #-}+defaultOptions :: Config+defaultOptions = unsafePerformIO $!+ Config <$> BitSet <$> peek F.__cmd_line_flags+
+ src/Data/Array/Accelerate/Trafo/Delayed.hs view
@@ -0,0 +1,126 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Trafo.Delayed+-- Copyright : [2012..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- The type of delayed arrays. This representation is used to annotate the AST+-- in the recursive knot to distinguish standard AST terms from operand arrays+-- that should be embedded into their consumers.+--++module Data.Array.Accelerate.Trafo.Delayed+ where++import Data.Array.Accelerate.AST+import Data.Array.Accelerate.Analysis.Hash+import Data.Array.Accelerate.Analysis.Match+import Data.Array.Accelerate.Representation.Array+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Trafo.Substitution++import Data.Array.Accelerate.Debug.Internal.Stats as Stats++import Control.DeepSeq+import Data.ByteString.Builder+import Data.ByteString.Builder.Extra+++type DelayedAcc = DelayedOpenAcc ()+type DelayedAfun = PreOpenAfun DelayedOpenAcc ()+type DelayedOpenAfun = PreOpenAfun DelayedOpenAcc++-- type DelayedOpenSeq = PreOpenSeq DelayedOpenAcc+-- data DelayedSeq t where+-- DelayedSeq :: Extend DelayedOpenAcc () aenv+-- -> DelayedOpenSeq aenv () t+-- -> DelayedSeq t++data DelayedOpenAcc aenv a where+ Manifest :: PreOpenAcc DelayedOpenAcc aenv a+ -> DelayedOpenAcc aenv a++ Delayed ::+ { reprD :: ArrayR (Array sh e)+ , extentD :: Exp aenv sh+ , indexD :: Fun aenv (sh -> e)+ , linearIndexD :: Fun aenv (Int -> e)+ } -> DelayedOpenAcc aenv (Array sh e)++instance HasArraysR DelayedOpenAcc where+ arraysR (Manifest a) = arraysR a+ arraysR Delayed{..} = TupRsingle reprD++instance Rebuildable DelayedOpenAcc where+ type AccClo DelayedOpenAcc = DelayedOpenAcc+ rebuildPartial v = \case+ Manifest pacc -> Manifest <$> rebuildPartial v pacc+ Delayed{..} -> (\e i l -> Delayed reprD (unOpenAccExp e) (unOpenAccFun i) (unOpenAccFun l))+ <$> rebuildPartial v (OpenAccExp extentD)+ <*> rebuildPartial v (OpenAccFun indexD)+ <*> rebuildPartial v (OpenAccFun linearIndexD)++instance Sink DelayedOpenAcc where+ weaken k = Stats.substitution "weaken" . rebuildA (rebuildWeakenVar k)++instance NFData (DelayedOpenAfun aenv t) where+ rnf = rnfPreOpenAfun rnfDelayedOpenAcc++instance NFData (DelayedOpenAcc aenv t) where+ rnf = rnfDelayedOpenAcc++encodeDelayedOpenAcc :: EncodeAcc DelayedOpenAcc+encodeDelayedOpenAcc options acc =+ let+ travE :: Exp aenv sh -> Builder+ travE = encodeOpenExp++ travF :: Fun aenv f -> Builder+ travF = encodeOpenFun++ travA :: PreOpenAcc DelayedOpenAcc aenv a -> Builder+ travA = encodePreOpenAcc options encodeDelayedOpenAcc++ deepA :: PreOpenAcc DelayedOpenAcc aenv a -> Builder+ deepA | perfect options = travA+ | otherwise = encodeArraysType . arraysR+ in+ case acc of+ Manifest pacc -> intHost $(hashQ ("Manifest" :: String)) <> deepA pacc+ Delayed _ sh f g -> intHost $(hashQ ("Delayed" :: String)) <> travE sh <> travF f <> travF g++matchDelayedOpenAcc :: MatchAcc DelayedOpenAcc+matchDelayedOpenAcc (Manifest pacc1) (Manifest pacc2)+ = matchPreOpenAcc matchDelayedOpenAcc pacc1 pacc2+matchDelayedOpenAcc (Delayed _ sh1 ix1 lx1) (Delayed _ sh2 ix2 lx2)+ | Just Refl <- matchOpenExp sh1 sh2+ , Just Refl <- matchOpenFun ix1 ix2+ , Just Refl <- matchOpenFun lx1 lx2+ = Just Refl+matchDelayedOpenAcc _ _+ = Nothing++rnfDelayedOpenAcc :: NFDataAcc DelayedOpenAcc+rnfDelayedOpenAcc (Manifest pacc) =+ rnfPreOpenAcc rnfDelayedOpenAcc pacc+rnfDelayedOpenAcc (Delayed aR sh ix lx) =+ rnfArrayR aR `seq` rnfOpenExp sh `seq` rnfOpenFun ix `seq` rnfOpenFun lx++liftDelayedOpenAcc :: LiftAcc DelayedOpenAcc+liftDelayedOpenAcc (Manifest pacc) =+ [|| Manifest $$(liftPreOpenAcc liftDelayedOpenAcc pacc) ||]+liftDelayedOpenAcc (Delayed aR sh ix lx) =+ [|| Delayed $$(liftArrayR aR) $$(liftOpenExp sh) $$(liftOpenFun ix) $$(liftOpenFun lx) ||]+
+ src/Data/Array/Accelerate/Trafo/Environment.hs view
@@ -0,0 +1,163 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeOperators #-}+-- |+-- Module : Data.Array.Accelerate.Trafo.Environment+-- Copyright : [2012..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Trafo.Environment+ where++import Data.Array.Accelerate.AST+import Data.Array.Accelerate.AST.Environment+import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.AST.LeftHandSide+import Data.Array.Accelerate.Error+import Data.Array.Accelerate.Representation.Array+import Data.Array.Accelerate.Trafo.Substitution+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.Debug.Internal.Stats as Stats+++-- An environment that holds let-bound scalar expressions. The second+-- environment variable env' is used to project out the corresponding+-- index when looking up in the environment congruent expressions.+--+data Gamma env env' aenv where+ EmptyExp :: Gamma env env' aenv++ PushExp :: Gamma env env' aenv+ -> WeakOpenExp env aenv t+ -> Gamma env (env', t) aenv++data WeakOpenExp env aenv t where+ Subst :: env :> env'+ -> OpenExp env aenv t+ -> OpenExp env' aenv t {- LAZY -}+ -> WeakOpenExp env' aenv t++-- XXX: The simplifier calls this function every time it moves under a let+-- binding. This means we have a number of calls to 'weakenE' exponential in the+-- depth of nested let bindings, which quickly causes problems.+--+-- We can improve the situation slightly by observing that weakening by a single+-- variable does no less work than weaking by multiple variables at once; both+-- require a deep copy of the AST. By exploiting laziness (or, an IORef) we can+-- queue up multiple weakenings to happen in a single step.+--+-- <https://github.com/AccelerateHS/accelerate-llvm/issues/20>+--+incExp+ :: Gamma env env' aenv+ -> Gamma (env,s) env' aenv+incExp EmptyExp = EmptyExp+incExp (PushExp env w) = incExp env `PushExp` subs w+ where+ subs :: forall env aenv s t. WeakOpenExp env aenv t -> WeakOpenExp (env,s) aenv t+ subs (Subst k (e :: OpenExp env_ aenv t) _) = Subst (weakenSucc' k) e (weakenE (weakenSucc' k) e)++prjExp :: HasCallStack => Idx env' t -> Gamma env env' aenv -> OpenExp env aenv t+prjExp ZeroIdx (PushExp _ (Subst _ _ e)) = e+prjExp (SuccIdx ix) (PushExp env _) = prjExp ix env+prjExp _ _ = internalError "inconsistent valuation"++pushExp :: Gamma env env' aenv -> OpenExp env aenv t -> Gamma env (env',t) aenv+pushExp env e = env `PushExp` Subst weakenId e e++{--+lookupExp+ :: Gamma env env' aenv+ -> OpenExp env aenv t+ -> Maybe (Idx env' t)+lookupExp EmptyExp _ = Nothing+lookupExp (PushExp env e) x+ | Just Refl <- match e x = Just ZeroIdx+ | otherwise = SuccIdx `fmap` lookupExp env x++weakenGamma1+ :: Gamma env env' aenv+ -> Gamma env env' (aenv,t)+weakenGamma1 EmptyExp = EmptyExp+weakenGamma1 (PushExp env e) = PushExp (weakenGamma1 env) (weaken SuccIdx e)++sinkGamma+ :: Kit acc+ => Extend acc aenv aenv'+ -> Gamma env env' aenv+ -> Gamma env env' aenv'+sinkGamma _ EmptyExp = EmptyExp+sinkGamma ext (PushExp env e) = PushExp (sinkGamma ext env) (sinkA ext e)+--}++-- As part of various transformations we often need to lift out array valued+-- inputs to be let-bound at a higher point.+--+-- The Extend type is a heterogeneous snoc-list of array terms that witnesses+-- how the array environment is extended by binding these additional terms.+--+data Extend s f env env' where+ BaseEnv :: Extend s f env env++ PushEnv :: Extend s f env env'+ -> LeftHandSide s t env' env''+ -> f env' t+ -> Extend s f env env''++pushArrayEnv+ :: HasArraysR acc+ => Extend ArrayR acc aenv aenv'+ -> acc aenv' (Array sh e)+ -> Extend ArrayR acc aenv (aenv', Array sh e)+pushArrayEnv env a = PushEnv env (LeftHandSideSingle $ arrayR a) a+++-- Append two environment witnesses+--+append :: Extend s acc env env' -> Extend s acc env' env'' -> Extend s acc env env''+append x BaseEnv = x+append x (PushEnv e lhs a) = PushEnv (append x e) lhs a++-- Bring into scope all of the array terms in the Extend environment list. This+-- converts a term in the inner environment (aenv') into the outer (aenv).+--+bind :: (forall env t. PreOpenAcc acc env t -> acc env t)+ -> Extend ArrayR acc aenv aenv'+ -> PreOpenAcc acc aenv' a+ -> PreOpenAcc acc aenv a+bind _ BaseEnv = id+bind inject (PushEnv g lhs a) = bind inject g . Alet lhs a . inject++-- Sink a term from one array environment into another, where additional+-- bindings have come into scope according to the witness and no old things have+-- vanished.+--+sinkA :: Sink f => Extend s acc env env' -> f env t -> f env' t+sinkA env = weaken (sinkWeaken env) -- TODO: Fix Stats sinkA vs sink1++sink1 :: Sink f => Extend s acc env env' -> f (env,t') t -> f (env',t') t+sink1 env = weaken $ sink $ sinkWeaken env++sinkWeaken :: Extend s acc env env' -> env :> env'+sinkWeaken (PushEnv e (LeftHandSideWildcard _) _) = sinkWeaken e+sinkWeaken (PushEnv e (LeftHandSideSingle _) _) = weakenSucc' $ sinkWeaken e+sinkWeaken (PushEnv e (LeftHandSidePair l1 l2) _) = sinkWeaken (PushEnv (PushEnv e l1 undefined) l2 undefined)+sinkWeaken BaseEnv = Stats.substitution "sink" weakenId++-- Wrapper around OpenExp, with the order of type arguments env and aenv flipped+newtype OpenExp' aenv env e = OpenExp' (OpenExp env aenv e)++bindExps :: Extend ScalarType (OpenExp' aenv) env env'+ -> OpenExp env' aenv e+ -> OpenExp env aenv e+bindExps BaseEnv = id+bindExps (PushEnv g lhs (OpenExp' b)) = bindExps g . Let lhs b+
+ src/Data/Array/Accelerate/Trafo/Fusion.hs view
@@ -0,0 +1,1770 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE ViewPatterns #-}+{-# OPTIONS_GHC -fno-warn-name-shadowing #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Trafo.Fusion+-- Copyright : [2012..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- This module implements producer/producer and consumer/producer fusion as a+-- term rewriting of the Accelerate AST.+--+-- The function 'quench' perform the source-to-source fusion transformation,+-- while 'anneal' additionally makes the representation of embedded producers+-- explicit by representing the AST as a 'DelayedAcc' of manifest and delayed+-- nodes.+--++module Data.Array.Accelerate.Trafo.Fusion (++ convertAcc, convertAccWith,+ convertAfun, convertAfunWith,++) where++import Data.BitSet+import Data.Array.Accelerate.AST+import Data.Array.Accelerate.AST.LeftHandSide+import Data.Array.Accelerate.AST.Environment+import Data.Array.Accelerate.AST.Var+import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.Error+import Data.Array.Accelerate.Trafo.Config+import Data.Array.Accelerate.Trafo.Var+import Data.Array.Accelerate.Trafo.Delayed+import Data.Array.Accelerate.Trafo.Environment+import Data.Array.Accelerate.Trafo.Shrink+import Data.Array.Accelerate.Trafo.Simplify+import Data.Array.Accelerate.Trafo.Substitution+import Data.Array.Accelerate.Representation.Array ( Array, ArrayR(..), ArraysR )+import Data.Array.Accelerate.Representation.Shape ( ShapeR(..), shapeType )+import Data.Array.Accelerate.Representation.Slice+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Analysis.Match+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.Debug.Internal.Flags ( array_fusion )+import qualified Data.Array.Accelerate.Debug.Internal.Stats as Stats+#ifdef ACCELERATE_DEBUG+import System.IO.Unsafe -- for debugging+#endif++import Data.Function+import Lens.Micro ( over, mapped, _2 )+import Prelude hiding ( exp, until )+++-- Delayed Array Fusion+-- ====================++-- | Apply the fusion transformation to a closed de Bruijn AST+--+convertAcc :: HasCallStack => Acc arrs -> DelayedAcc arrs+convertAcc = convertAccWith defaultOptions++convertAccWith :: HasCallStack => Config -> Acc arrs -> DelayedAcc arrs+convertAccWith config = withSimplStats . convertOpenAcc config++-- | Apply the fusion transformation to a function of array arguments+--+convertAfun :: HasCallStack => Afun f -> DelayedAfun f+convertAfun = convertAfunWith defaultOptions++convertAfunWith :: HasCallStack => Config -> Afun f -> DelayedAfun f+convertAfunWith config = withSimplStats . convertOpenAfun config++-- -- | Apply the fusion transformation to the array computations embedded+-- -- in a sequence computation.+--+-- convertSeq :: Bool -> Seq a -> DelayedSeq a+-- convertSeq fuseAcc (embedSeq (embedOpenAcc fuseAcc) -> ExtendSeq aenv s)+-- = withSimplStats (DelayedSeq (cvtE aenv) (convertOpenSeq fuseAcc s))+-- where+-- cvtE :: Extend OpenAcc aenv aenv' -> Extend DelayedOpenAcc aenv aenv'+-- cvtE BaseEnv = BaseEnv+-- cvtE (PushEnv env a) | a' <- convertOpenAcc fuseAcc a = PushEnv (cvtE env) a'++withSimplStats :: a -> a+#ifdef ACCELERATE_DEBUG+withSimplStats x = unsafePerformIO Stats.resetSimplCount `seq` x+#else+withSimplStats x = x+#endif+++-- | Apply the fusion transformation to an AST. This consists of two phases:+--+-- 1. A bottom-up traversal that converts nodes into the internal delayed+-- representation, merging adjacent producer/producer pairs.+--+-- 2. A top-down traversal that makes the representation of fused+-- consumer/producer pairs explicit as a 'DelayedAcc' of manifest and+-- delayed nodes.+--+-- TLM: Note that there really is no ambiguity as to which state an array will+-- be in following this process: an array will be either delayed or+-- manifest, and the two helper functions are even named as such! We should+-- encode this property in the type somehow...+--+convertOpenAcc+ :: HasCallStack+ => Config+ -> OpenAcc aenv arrs+ -> DelayedOpenAcc aenv arrs+convertOpenAcc config = manifest config . computeAcc . embedOpenAcc config+++-- Convert array computations into an embeddable delayed representation.+-- Reapply the embedding function from the first pass and unpack the+-- representation. It is safe to match on BaseEnv because the first pass+-- will put producers adjacent to the term consuming it.+--+delayed+ :: HasCallStack+ => Config+ -> OpenAcc aenv (Array sh e)+ -> DelayedOpenAcc aenv (Array sh e)+delayed config (embedOpenAcc config -> Embed env cc)+ | BaseEnv <- env+ = simplify cc & \case+ Left (Done v) -> avarsIn Manifest v+ Right d -> d & \case+ Yield aR sh f -> Delayed aR sh f (f `compose` fromIndex (arrayRshape aR) sh)+ Step aR sh p f v+ | Just Refl <- matchOpenExp sh (arrayShape v)+ , Just Refl <- isIdentity p -> Delayed aR sh (f `compose` indexArray v) (f `compose` linearIndex v)+ | f' <- f `compose` indexArray v `compose` p -> Delayed aR sh f' (f' `compose` fromIndex (arrayRshape aR) sh)+ --+ | otherwise+ = manifest config (computeAcc (Embed env cc))+++-- Convert array programs as manifest terms.+--+manifest+ :: HasCallStack+ => Config+ -> OpenAcc aenv a+ -> DelayedOpenAcc aenv a+manifest config (OpenAcc pacc) =+ let fusionError = internalError "unexpected fusible materials"+ in+ Manifest $ case pacc of+ -- Non-fusible terms+ -- -----------------+ Avar ix -> Avar ix+ Use aR a -> Use aR a+ Unit t e -> Unit t e+ Alet lhs bnd body -> alet lhs (manifest config bnd) (manifest config body)+ Acond p t e -> Acond p (manifest config t) (manifest config e)+ Awhile p f a -> Awhile (cvtAF p) (cvtAF f) (manifest config a)+ Apair a1 a2 -> Apair (manifest config a1) (manifest config a2)+ Anil -> Anil+ Atrace msg a1 a2 -> Atrace msg (manifest config a1) (manifest config a2)+ Apply repr f a -> apply repr (cvtAF f) (manifest config a)+ Aforeign repr ff f a -> Aforeign repr ff (cvtAF f) (manifest config a)++ -- Producers+ -- ---------+ --+ -- Some producers might still exist as a manifest array. Typically this+ -- is because they are the last stage of the computation, or the result+ -- of a let-binding to be used multiple times. The input array here+ -- should be a evaluated array term, else something went wrong.+ --+ Map t f a -> Map t f (delayed config a)+ Generate repr sh f -> Generate repr sh f+ Transform repr sh p f a -> Transform repr sh p f (delayed config a)+ Backpermute shR sh p a -> Backpermute shR sh p (delayed config a)+ Reshape slr sl a -> Reshape slr sl (manifest config a)++ Replicate{} -> fusionError+ Slice{} -> fusionError+ ZipWith{} -> fusionError++ -- Consumers+ -- ---------+ --+ -- Embed producers directly into the representation. For delayed terms+ -- with local bindings, these will have been floated up above the+ -- consumer already+ --+ Fold f z a -> Fold f z (delayed config a)+ FoldSeg i f z a s -> FoldSeg i f z (delayed config a) (delayed config s)+ Scan d f z a -> Scan d f z (delayed config a)+ Scan' d f z a -> Scan' d f z (delayed config a)+ Permute f d p a -> Permute f (manifest config d) p (delayed config a)+ Stencil s t f x a -> Stencil s t f x (delayed config a)+ Stencil2 s1 s2 t f x a y b+ -> Stencil2 s1 s2 t f x (delayed config a) y (delayed config b)+ -- Collect s -> Collect (cvtS s)++ where+ -- Flatten needless let-binds, which can be introduced by the+ -- conversion to the internal embeddable representation.+ --+ alet :: HasCallStack+ => ALeftHandSide a aenv aenv'+ -> DelayedOpenAcc aenv a+ -> DelayedOpenAcc aenv' b+ -> PreOpenAcc DelayedOpenAcc aenv b+ alet lhs bnd body+ | Just bodyVars <- extractDelayedArrayVars body+ , Just Refl <- bindingIsTrivial lhs bodyVars+ , Manifest x <- bnd+ = x+ --+ | otherwise+ = Alet lhs bnd body++ -- Eliminate redundant application to an identity function. This+ -- arises in the use of pipe to avoid fusion and force its argument+ -- to be evaluated, i.e.:+ --+ -- > compute :: Acc a -> Acc a+ -- > compute = id >-> id+ --+ apply :: HasCallStack+ => ArraysR b+ -> PreOpenAfun DelayedOpenAcc aenv (a -> b)+ -> DelayedOpenAcc aenv a+ -> PreOpenAcc DelayedOpenAcc aenv b+ apply repr afun x+ | Alam lhs (Abody body) <- afun+ , Just bodyVars <- extractDelayedArrayVars body+ , Just Refl <- bindingIsTrivial lhs bodyVars+ , Manifest x' <- x+ = Stats.ruleFired "applyD/identity" x'+ --+ | otherwise+ = Apply repr afun x++ cvtAF :: HasCallStack => OpenAfun aenv f -> PreOpenAfun DelayedOpenAcc aenv f+ cvtAF (Alam lhs f) = Alam lhs (cvtAF f)+ cvtAF (Abody b) = Abody (manifest config b)++ -- cvtS :: PreOpenSeq OpenAcc aenv senv s -> PreOpenSeq DelayedOpenAcc aenv senv s+ -- cvtS = convertOpenSeq config++convertOpenAfun :: HasCallStack => Config -> OpenAfun aenv f -> DelayedOpenAfun aenv f+convertOpenAfun c (Alam lhs f) = Alam lhs (convertOpenAfun c f)+convertOpenAfun c (Abody b) = Abody (convertOpenAcc c b)++{--+convertOpenSeq :: Config -> PreOpenSeq OpenAcc aenv senv a -> PreOpenSeq DelayedOpenAcc aenv senv a+convertOpenSeq config s =+ case s of+ Consumer c -> Consumer (cvtC c)+ Reify ix -> Reify ix+ Producer p s' -> Producer p' (convertOpenSeq config s')+ where+ p' = case p of+ StreamIn arrs -> StreamIn arrs+ ToSeq slix sh a -> ToSeq slix sh (delayed config a)+ MapSeq f x -> MapSeq (cvtAF f) x+ ChunkedMapSeq f x -> ChunkedMapSeq (cvtAF f) x+ ZipWithSeq f x y -> ZipWithSeq (cvtAF f) x y+ ScanSeq f e x -> ScanSeq (cvtF f) (cvtE e) x+ where+ cvtC :: Consumer OpenAcc aenv senv a -> Consumer DelayedOpenAcc aenv senv a+ cvtC c =+ case c of+ FoldSeq f e x -> FoldSeq (cvtF f) (cvtE e) x+ FoldSeqFlatten f a x -> FoldSeqFlatten (cvtAF f) (manifest config a) x+ Stuple t -> Stuple (cvtCT t)++ cvtCT :: Atuple (Consumer OpenAcc aenv senv) t -> Atuple (Consumer DelayedOpenAcc aenv senv) t+ cvtCT NilAtup = NilAtup+ cvtCT (SnocAtup t c) = SnocAtup (cvtCT t) (cvtC c)++ cvtAF :: OpenAfun aenv f -> PreOpenAfun DelayedOpenAcc aenv f+ cvtAF (Alam f) = Alam (cvtAF f)+ cvtAF (Abody b) = Abody (manifest config b)++ cvtE :: OpenExp env aenv t -> DelayedOpenExp env aenv t+ cvtE = convertOpenExp config++ cvtF :: OpenFun env aenv f -> DelayedOpenFun env aenv f+ cvtF (Lam f) = Lam (cvtF f)+ cvtF (Body b) = Body (cvtE b)+--}+++type EmbedAcc acc = forall aenv arrs. acc aenv arrs -> Embed acc aenv arrs+type ElimAcc acc = forall aenv s t. acc aenv s -> acc (aenv,s) t -> Bool+++-- | Apply the fusion transformation to the AST to combine and simplify terms.+-- This converts terms into the internal delayed array representation and merges+-- adjacent producer/producer terms. Using the reduced internal form limits the+-- number of combinations that need to be considered.+--+embedOpenAcc :: HasCallStack => Config -> OpenAcc aenv arrs -> Embed OpenAcc aenv arrs+embedOpenAcc config (OpenAcc pacc) =+ embedPreOpenAcc config matchOpenAcc (embedOpenAcc config) elimOpenAcc pacc+ where+ -- When does the cost of re-computation outweigh that of memory access? For+ -- the moment only do the substitution on a single use of the bound array+ -- into the use site, but it is likely advantageous to be far more+ -- aggressive here.+ --+ -- SEE: [Sharing vs. Fusion]+ --+ elimOpenAcc :: ElimAcc OpenAcc+ elimOpenAcc _bnd body+ | count False ZeroIdx body <= lIMIT = True+ | otherwise = False+ where+ lIMIT = 1++ count :: UsesOfAcc OpenAcc+ count no ix (OpenAcc pacc) = usesOfPreAcc no count ix pacc++ matchOpenAcc :: MatchAcc OpenAcc+ matchOpenAcc (OpenAcc pacc1) (OpenAcc pacc2) =+ matchPreOpenAcc matchOpenAcc pacc1 pacc2+++embedPreOpenAcc+ :: HasCallStack+ => Config+ -> MatchAcc OpenAcc+ -> EmbedAcc OpenAcc+ -> ElimAcc OpenAcc+ -> PreOpenAcc OpenAcc aenv arrs+ -> Embed OpenAcc aenv arrs+embedPreOpenAcc config matchAcc embedAcc elimAcc pacc+ = unembed+ $ case pacc of++ -- Non-fusible terms+ -- -----------------+ --+ -- Solid and semi-solid terms that we generally do not wish to fuse, such+ -- as control flow (|?), array introduction (use, unit), array tupling and+ -- projection, and foreign function operations. Generally we also do not+ -- want to fuse past array let bindings, as this would imply work+ -- duplication. SEE: [Sharing vs. Fusion]+ --+ Alet lhs bnd body -> aletD embedAcc elimAcc lhs bnd body+ Anil -> done $ Anil+ Acond p at ae -> acondD matchAcc embedAcc (cvtE p) at ae+ Apply aR f a -> done $ Apply aR (cvtAF f) (cvtA a)+ Awhile p f a -> done $ Awhile (cvtAF p) (cvtAF f) (cvtA a)+ Apair a1 a2 -> done $ Apair (cvtA a1) (cvtA a2)+ Atrace msg a1 a2 -> done $ Atrace msg (cvtA a1) (cvtA a2)+ Aforeign aR ff f a -> done $ Aforeign aR ff (cvtAF f) (cvtA a)+ -- Collect s -> collectD s++ -- Array injection+ Avar v -> done $ Avar v+ Use aR a -> done $ Use aR a+ Unit t e -> done $ Unit t (cvtE e)++ -- Producers+ -- ---------+ --+ -- The class of operations that given a set of zero or more input arrays,+ -- produce a _single_ element for the output array by manipulating a+ -- _single_ element from each input array. These can be further classified+ -- as value (map, zipWith) or index space (backpermute, slice, replicate)+ -- transformations.+ --+ -- The critical feature is that each element of the output is produced+ -- independently of all others, and so we can aggressively fuse arbitrary+ -- sequences of these operations.+ --+ Generate aR sh f -> generateD aR (cvtE sh) (cvtF f)+ Map t f a -> mapD t (cvtF f) (embedAcc a)+ ZipWith t f a b -> fuse2 (into (zipWithD t) (cvtF f)) a b+ Transform aR sh p f a -> transformD aR (cvtE sh) (cvtF p) (cvtF f) (embedAcc a)+ Backpermute slr sl p a -> fuse (into2 (backpermuteD slr) (cvtE sl) (cvtF p)) a+ Slice slix a sl -> fuse (into (sliceD slix) (cvtE sl)) a+ Replicate slix sh a -> fuse (into (replicateD slix) (cvtE sh)) a+ Reshape slr sl a -> reshapeD slr (embedAcc a) (cvtE sl)++ -- Consumers+ -- ---------+ --+ -- Operations where each element of the output array depends on multiple+ -- elements of the input array. To implement these operations efficiently in+ -- parallel, we need to know how elements of the array depend on each other:+ -- a parallel scan is implemented very differently from a parallel fold, for+ -- example.+ --+ -- In order to avoid obfuscating this crucial information required for+ -- parallel implementation, fusion is separated into to phases:+ -- producer/producer, implemented above, and consumer/producer, which is+ -- implemented below. This will place producers adjacent to the consumer+ -- node, so that the producer can be directly embedded into the consumer+ -- during the code generation phase.+ --+ Fold f z a -> embed aR (into2M Fold (cvtF f) (cvtE <$> z)) a+ FoldSeg i f z a s -> embed2 aR (into2M (FoldSeg i) (cvtF f) (cvtE <$> z)) a s+ Scan d f z a -> embed aR (into2M (Scan d) (cvtF f) (cvtE <$> z)) a+ Scan' d f z a -> embed aR (into2 (Scan' d) (cvtF f) (cvtE z)) a+ Permute f d p a -> embed2 aR (into2 permute (cvtF f) (cvtF p)) d a+ Stencil s t f x a -> embed aR (into2 (stencil1 s t) (cvtF f) (cvtB x)) a+ Stencil2 s1 s2 t f x a y b -> embed2 aR (into3 (stencil2 s1 s2 t) (cvtF f) (cvtB x) (cvtB y)) a b++ where+ aR = arraysR pacc++ -- If fusion is not enabled, force terms to the manifest representation+ --+ unembed :: HasCallStack => Embed OpenAcc aenv arrs -> Embed OpenAcc aenv arrs+ unembed x+ | array_fusion `member` options config = x+ | Embed env cc <- x+ , pacc <- compute cc+ = case avarsOut extractOpenAcc pacc of+ Just vars -> Embed env $ Done vars+ _+ | DeclareVars lhs _ value <- declareVars (arraysR pacc)+ -> Embed (PushEnv env lhs $ OpenAcc pacc) $ Done $ value weakenId++ cvtA :: HasCallStack => OpenAcc aenv' a -> OpenAcc aenv' a+ cvtA = computeAcc . embedAcc++ cvtAF :: HasCallStack => PreOpenAfun OpenAcc aenv' f -> PreOpenAfun OpenAcc aenv' f+ cvtAF (Alam lhs f) = Alam lhs (cvtAF f)+ cvtAF (Abody a) = Abody (cvtA a)++ -- Helpers to shuffle the order of arguments to a constructor+ --+ permute f p d a = Permute f d p a++ -- NOTE: [Stencil fusion]+ --+ -- We allow stencils to delay their argument arrays with no special+ -- considerations. This means that the delayed function will be evaluated+ -- _at every element_ of the stencil pattern. We should do some analysis of+ -- when this duplication is beneficial (keeping in mind that the stencil+ -- implementations themselves may share neighbouring elements).+ --+ stencil1 s t f x a = Stencil s t f x a+ stencil2 s1 s2 t f x y a b = Stencil2 s1 s2 t f x a y b++ -- Conversions for closed scalar functions and expressions. This just+ -- applies scalar simplifications.+ --+ cvtF :: HasCallStack => Fun aenv' t -> Fun aenv' t+ cvtF = simplifyFun++ cvtE :: HasCallStack => Exp aenv' t -> Exp aenv' t+ cvtE = simplifyExp++ cvtB :: HasCallStack => Boundary aenv' t -> Boundary aenv' t+ cvtB Clamp = Clamp+ cvtB Mirror = Mirror+ cvtB Wrap = Wrap+ cvtB (Constant c) = Constant c+ cvtB (Function f) = Function (cvtF f)++ -- Helpers to embed and fuse delayed terms+ --+ into :: (HasCallStack, Sink f)+ => (f env' a -> b)+ -> f env a+ -> Extend ArrayR OpenAcc env env'+ -> b+ into op a env = op (sinkA env a)++ into2 :: (HasCallStack, Sink f1, Sink f2)+ => (f1 env' a -> f2 env' b -> c)+ -> f1 env a+ -> f2 env b+ -> Extend ArrayR OpenAcc env env'+ -> c+ into2 op a b env = op (sinkA env a) (sinkA env b)++ into2M :: (HasCallStack, Sink f1, Sink f2)+ => (f1 env' a -> Maybe (f2 env' b) -> c)+ -> f1 env a+ -> Maybe (f2 env b)+ -> Extend ArrayR acc env env'+ -> c+ into2M op a b env = op (sinkA env a) (sinkA env <$> b)++ into3 :: (HasCallStack, Sink f1, Sink f2, Sink f3)+ => (f1 env' a -> f2 env' b -> f3 env' c -> d)+ -> f1 env a+ -> f2 env b+ -> f3 env c+ -> Extend ArrayR OpenAcc env env'+ -> d+ into3 op a b c env = op (sinkA env a) (sinkA env b) (sinkA env c)++ -- Operations which can be fused into consumers. Move all of the local+ -- bindings out of the way so that the fusible function operates+ -- directly on the delayed representation. See also: [Representing+ -- delayed arrays]+ --+ fuse :: HasCallStack+ => (forall r aenv'. Extend ArrayR OpenAcc aenv aenv' -> Cunctation r aenv' as -> Cunctation D aenv' bs)+ -> OpenAcc aenv as+ -> Embed OpenAcc aenv bs+ fuse op (embedAcc -> Embed env cc) = Embed env (op env cc)++ fuse2 :: HasCallStack+ => (forall r s aenv'. Extend ArrayR OpenAcc aenv aenv' -> Cunctation r aenv' as -> Cunctation s aenv' bs -> Cunctation D aenv' cs)+ -> OpenAcc aenv as+ -> OpenAcc aenv bs+ -> Embed OpenAcc aenv cs+ fuse2 op a1 a0+ | Embed env1 cc1 <- embedAcc a1+ , Embed env0 cc0 <- embedAcc (sinkA env1 a0)+ , env <- env1 `append` env0+ = Embed env (op env (sinkA env0 cc1) cc0)++ -- Consumer operations which will be evaluated.+ --+ -- NOTE: [Fusion and the lowest common use site]+ --+ -- The AST given to us by sharing recovery will place let bindings at+ -- the lowest common use site for that shared term. For example:+ --+ -- fold f z (let a0 = ..+ -- a1 = ..+ -- in zipWith g a0 a1)+ --+ -- In order to enable producer/consumer fusion for the above example,+ -- it is necessary to float the let bindings above the `fold`+ -- operation; SEE: [Sharing vs. Fusion] for more information.+ --+ -- Furthermore, we used to maintain an invariant that all (manifest)+ -- arguments were supplied as array variables, for example:+ --+ -- fold1 f (let a0 = .. let a0 = ..+ -- in stencil g a0) ==> a1 = stencil g a0+ -- a2 = fold1 f a1+ --+ -- However, if the argument term will be evaluated (i.e. can not be+ -- fused into the producer) then it is better that we do _not_ float+ -- those terms, and instead leave them under the consumer. This helps+ -- to syntactically constrain the "liveness" of terms: if the argument+ -- to an operation is not an array variable, we can see directly that+ -- this will be the last use-site of that array. In particular, this is+ -- useful for the 'permute' operation to know when it can in-place+ -- update the array of default values.+ --+ embed :: HasCallStack+ => ArraysR bs+ -> (forall aenv'. Extend ArrayR OpenAcc aenv aenv' -> OpenAcc aenv' as -> PreOpenAcc OpenAcc aenv' bs)+ -> OpenAcc aenv as+ -> Embed OpenAcc aenv bs+ embed reprBs op (embedAcc -> Embed env cc)+ | Done{} <- cc+ , DeclareVars lhs _ value <- declareVars reprBs+ = Embed (PushEnv BaseEnv lhs $ OpenAcc (op BaseEnv (computeAcc (Embed env cc)))) $ Done $ value weakenId+ | otherwise+ -- Next line is duplicated for both branches, as the type variable for the environment is instantiated differently+ , DeclareVars lhs _ value <- declareVars reprBs+ = Embed (PushEnv env lhs $ OpenAcc (op env (OpenAcc (compute cc)))) $ Done $ value weakenId++ embed2 :: HasCallStack+ => ArraysR cs+ -> (forall aenv'. Extend ArrayR OpenAcc aenv aenv' -> OpenAcc aenv' as -> OpenAcc aenv' bs -> PreOpenAcc OpenAcc aenv' cs)+ -> OpenAcc aenv as+ -> OpenAcc aenv bs+ -> Embed OpenAcc aenv cs+ embed2 reprCs op (embedAcc -> Embed env1 cc1) a0+ | Done{} <- cc1+ , a1 <- computeAcc (Embed env1 cc1)+ = embed reprCs (\env0 -> op env0 (sinkA env0 a1)) a0+ --+ | Embed env0 cc0 <- embedAcc (sinkA env1 a0)+ , env <- env1 `append` env0+ = case cc0 of+ Done{}+ | DeclareVars lhs _ value <- declareVars reprCs+ -> Embed (PushEnv env1 lhs $ OpenAcc (op env1 (OpenAcc (compute cc1)) (computeAcc (Embed env0 cc0))))+ $ Done+ $ value weakenId+ _+ -- Next line is duplicated for both branches, as the type+ -- variable for the environment is instantiated differently+ | DeclareVars lhs _ value <- declareVars reprCs+ -> Embed (PushEnv env lhs $ OpenAcc (op env (OpenAcc (compute (sinkA env0 cc1))) (OpenAcc (compute cc0))))+ $ Done+ $ value weakenId++ -- trav1 :: (Arrays as, Arrays bs)+ -- => (forall aenv'. Embed acc aenv' as -> Embed acc aenv' as)+ -- -> (forall aenv'. Extend ArrayR acc aenv aenv' -> acc aenv' as -> PreOpenAcc acc aenv' bs)+ -- -> acc aenv as+ -- -> Embed acc aenv bs+ -- trav1 f op (f . embedAcc -> Embed env cc)+ -- = Embed (env `pushArrayEnv` inject (op env (inject (compute cc)))) doneZeroIdx++ -- trav2 :: (Arrays as, Arrays bs, Arrays cs)+ -- => (forall aenv'. Embed acc aenv' as -> Embed acc aenv' as)+ -- -> (forall aenv'. Embed acc aenv' bs -> Embed acc aenv' bs)+ -- -> (forall aenv'. Extend ArrayR acc aenv aenv' -> acc aenv' as -> acc aenv' bs -> PreOpenAcc acc aenv' cs)+ -- -> acc aenv as+ -- -> acc aenv bs+ -- -> Embed acc aenv cs+ -- trav2 f1 f0 op (f1 . embedAcc -> Embed env1 cc1) (f0 . embedAcc . sinkA env1 -> Embed env0 cc0)+ -- | env <- env1 `append` env0+ -- , acc1 <- inject . compute $ sinkA env0 cc1+ -- , acc0 <- inject . compute $ cc0+ -- = Embed (env `pushArrayEnv` inject (op env acc1 acc0)) doneZeroIdx++ -- force :: Arrays as => Embed acc aenv' as -> Embed acc aenv' as+ -- force (Embed env cc)+ -- | Done{} <- cc = Embed env cc+ -- | otherwise = Embed (env `pushArrayEnv` inject (compute cc)) doneZeroIdx++ -- -- Move additional bindings for producers outside of the sequence, so that+ -- -- producers may fuse with their arguments resulting in actual sequencing+ -- collectD :: PreOpenSeq acc aenv () arrs+ -- -> Embed acc aenv arrs+ -- collectD (embedSeq embedAcc -> ExtendSeq env s')+ -- = Embed (env `pushArrayEnv` inject (Collect s')) doneZeroIdx+++{--+-- Move additional bindings for producer outside of sequence, so+-- that producers may fuse with their arguments, resulting in+-- actual sequencing.+embedSeq :: forall acc aenv arrs. Kit acc+ => EmbedAcc acc+ -> PreOpenSeq acc aenv () arrs+ -> ExtendSeq acc aenv () arrs+embedSeq embedAcc s+ = travS s BaseEnv+ where+ travS :: forall senv aenv' arrs'.+ PreOpenSeq acc aenv senv arrs'+ -> Extend acc aenv aenv'+ -> ExtendSeq acc aenv senv arrs'+ travS s env =+ case s of+ Producer p s+ | ExtendSeq env' s' <- travS s env+ , ExtendProducer env'' p' <- travP p env'+ -> ExtendSeq (env' `append` env'') (Producer p' (sinkSeq env'' s'))+ Consumer c+ | c' <- travC c env+ -> ExtendSeq env (Consumer c')+ Reify ix+ -> ExtendSeq env (Reify ix)++ travP :: forall arrs' aenv' senv.+ Producer acc aenv senv arrs'+ -> Extend acc aenv aenv'+ -> ExtendProducer acc aenv' senv arrs'+ travP (ToSeq slix sh a) env+ | Embed env' cc <- embedAcc (sink env a)+ = ExtendProducer env' (ToSeq slix sh (inject (compute cc)))+ travP (StreamIn arrs) _ = ExtendProducer BaseEnv (StreamIn arrs)+ travP (MapSeq f x) env = ExtendProducer BaseEnv (MapSeq (cvtAF (sink env f)) x)+ travP (ChunkedMapSeq f x) env = ExtendProducer BaseEnv (ChunkedMapSeq (cvtAF (sink env f)) x)+ travP (ZipWithSeq f x y) env = ExtendProducer BaseEnv (ZipWithSeq (cvtAF (sink env f)) x y)+ travP (ScanSeq f e x) env = ExtendProducer BaseEnv (ScanSeq (cvtF (sink env f)) (cvtE (sink env e)) x)++ travC :: forall arrs' aenv' senv.+ Consumer acc aenv senv arrs'+ -> Extend acc aenv aenv'+ -> Consumer acc aenv' senv arrs'+ travC (FoldSeq f e x) env = FoldSeq (cvtF (sink env f)) (cvtE (sink env e)) x+ travC (FoldSeqFlatten f a x) env = FoldSeqFlatten (cvtAF (sink env f)) (cvtA (sink env a)) x+ travC (Stuple t) env = Stuple (cvtCT t)+ where+ cvtCT :: Atuple (Consumer acc aenv senv) t -> Atuple (Consumer acc aenv' senv) t+ cvtCT NilAtup = NilAtup+ cvtCT (SnocAtup t c) = SnocAtup (cvtCT t) (travC c env)++ cvtE :: Elt t => Exp aenv' t -> Exp aenv' t+ cvtE = simplifyExp++ cvtF :: Fun aenv' t -> Fun aenv' t+ cvtF = simplifyFun++ cvtA :: Arrays a => acc aenv' a -> acc aenv' a+ cvtA = computeAcc . embedAcc++ cvtAF :: PreOpenAfun acc aenv' f -> PreOpenAfun acc aenv' f+ cvtAF (Alam f) = Alam (cvtAF f)+ cvtAF (Abody a) = Abody (cvtA a)+++-- A sequence with additional bindings+data ExtendSeq acc aenv senv arrs where+ ExtendSeq :: forall acc aenv aenv' senv arrs.+ Extend acc aenv aenv'+ -> PreOpenSeq acc aenv' senv arrs+ -> ExtendSeq acc aenv senv arrs++-- A producer with additional bindings+data ExtendProducer acc aenv senv arrs where+ ExtendProducer :: forall acc aenv aenv' senv arrs.+ Extend acc aenv aenv'+ -> Producer acc aenv' senv arrs+ -> ExtendProducer acc aenv senv arrs+--}+++-- Internal representation+-- =======================++-- NOTE: [Representing delayed arrays]+--+-- During the fusion transformation we represent terms as a pair consisting of+-- a collection of supplementary environment bindings and a description of how+-- to construct the array.+--+-- It is critical to separate these two. To create a real AST node we need both+-- the environment and array term, but analysis of how to fuse terms requires+-- only the array description. If the additional bindings are bundled as part of+-- the representation, the existentially quantified extended environment type+-- will be untouchable. This is problematic because the terms of the two arrays+-- are defined with respect to this existentially quantified type, and there is+-- no way to directly combine these two environments:+--+-- append :: Extend env env1 -> Extend env env2 -> Extend env ???+--+-- And hence, no way to combine the terms of the delayed representation.+--+-- The only way to bring terms into the same scope is to operate via the+-- manifest terms. This entails a great deal of conversion between delayed and+-- AST terms, but is certainly possible.+--+-- However, because of the limited scope into which this existential type is+-- available, we ultimately perform this process many times. In fact, complexity+-- of the fusion algorithm for an AST of N terms becomes O(r^n), where r is the+-- number of different rules we have for combining terms.+--+data Embed acc aenv a where+ Embed :: Extend ArrayR acc aenv aenv'+ -> Cunctation r aenv' a+ -> Embed acc aenv a++instance HasArraysR acc => HasArraysR (Embed acc) where+ arraysR (Embed _ c) = arraysR c+++-- Delayed arrays are represented as functions+data D++-- Manifest arrays are real arrays backed by unboxed vectors+data M++-- Cunctation (n): the action or an instance of delaying; a tardy action.+--+-- This describes the ways in which the fusion transformation represents+-- intermediate arrays. The fusion process operates by recasting producer array+-- computations in terms of a set of scalar functions used to construct an+-- element at each index, and fusing successive producers by combining these+-- scalar functions.+--+data Cunctation r aenv a where++ -- The base case is just a real (manifest) array term. No fusion happens here.+ -- Note that the array is referenced by an index into the extended+ -- environment, ensuring that the array is manifest and making the term+ -- non-recursive in 'acc'.+ --+ Done :: ArrayVars aenv arrs+ -> Cunctation M aenv arrs++ -- We can represent an array by its shape and a function to compute an element+ -- at each index.+ --+ Yield :: ArrayR (Array sh e)+ -> Exp aenv sh+ -> Fun aenv (sh -> e)+ -> Cunctation D aenv (Array sh e)++ -- A more restrictive form than 'Yield' may afford greater opportunities for+ -- optimisation by a backend. This more structured form applies an index and+ -- value transform to an input array. Note that the transform is applied to an+ -- array stored as an environment index, so that the term is non-recursive and+ -- it is always possible to embed into a collective operation.+ --+ Step :: ArrayR (Array sh' b)+ -> Exp aenv sh'+ -> Fun aenv (sh' -> sh)+ -> Fun aenv (a -> b)+ -> ArrayVar aenv (Array sh a)+ -> Cunctation D aenv (Array sh' b)++instance HasArraysR (Cunctation r) where+ arraysR (Done v) = varsType v+ arraysR (Yield aR _ _) = TupRsingle aR+ arraysR (Step aR _ _ _ _) = TupRsingle aR++instance Sink (Cunctation r) where+ weaken k = \case+ Done v -> Done (weakenVars k v)+ Step aR sh p f v -> Step aR (weaken k sh) (weaken k p) (weaken k f) (weaken k v)+ Yield aR sh f -> Yield aR (weaken k sh) (weaken k f)++simplify+ :: HasCallStack+ => Cunctation r aenv a+ -> Either (Cunctation M aenv a) (Cunctation D aenv a)+simplify = \case+ Done v+ -> Left $ Done v+ Yield aR (simplifyExp -> sh) (simplifyFun -> f)+ -> Right $ Yield aR sh f+ Step aR (simplifyExp -> sh) (simplifyFun -> p) (simplifyFun -> f) v+ | Just Refl <- matchOpenExp sh (arrayShape v)+ , Just Refl <- isIdentity p+ , Just Refl <- isIdentity f+ -> Left $ (Done (TupRsingle v))+ | otherwise+ -> Right $ Step aR sh p f v+++-- Convert a real AST node into the internal representation+--+done :: HasCallStack => PreOpenAcc OpenAcc aenv a -> Embed OpenAcc aenv a+done pacc+ | Just vars <- avarsOut extractOpenAcc pacc+ = Embed BaseEnv (Done vars)+ | DeclareVars lhs _ value <- declareVars (arraysR pacc)+ = Embed (PushEnv BaseEnv lhs $ OpenAcc pacc) $ Done $ value weakenId++doneZeroIdx :: ArrayR (Array sh e) -> Cunctation M (aenv, Array sh e) (Array sh e)+doneZeroIdx aR = Done (TupRsingle (Var aR ZeroIdx))+++-- Recast a cunctation into a mapping from indices to elements+--+yield :: HasCallStack+ => Cunctation r aenv (Array sh e)+ -> Cunctation D aenv (Array sh e)+yield cc =+ case cc of+ Yield{} -> cc+ Step tR sh p f v -> Yield tR sh (f `compose` indexArray v `compose` p)+ Done (TupRsingle v@(Var tR _)) -> Yield tR (arrayShape v) (indexArray v)++-- Recast a cunctation into a delayed representation+--+delaying+ :: HasCallStack+ => Cunctation r aenv (Array sh e)+ -> Cunctation D aenv (Array sh e)+delaying cc =+ case cc of+ Yield{} -> cc+ Step{} -> cc+ Done u+ | TupRsingle v <- u+ , Var aR _ <- v+ , ArrayR shR tR <- aR+ -> Step aR (arrayShape v) (identity (shapeType shR)) (identity tR) v++-- Get the shape of a delayed array+--+shape :: HasCallStack => Cunctation r aenv (Array sh e) -> Exp aenv sh+shape cc =+ case delaying cc of+ Step _ sh _ _ _ -> sh+ Yield _ sh _ -> sh+++-- prjExtend :: Kit acc => Extend acc env env' -> Idx env' t -> PreOpenAcc acc env' t+-- prjExtend (PushEnv _ v) ZeroIdx = weakenA rebuildAcc SuccIdx v+-- prjExtend (PushEnv env _) (SuccIdx idx) = weakenA rebuildAcc SuccIdx $ prjExtend env idx+-- prjExtend _ _ = $internalError "prjExtend" "inconsistent valuation"++{--+-- Rearrange type arguments to fit with Sink type class.+newtype SinkSeq acc senv aenv a = SinkSeq { unSinkSeq :: PreOpenSeq acc aenv senv a }++-- sink for sequences.+sinkSeq :: Kit acc => Extend acc aenv aenv' -> PreOpenSeq acc aenv senv a -> PreOpenSeq acc aenv' senv a+sinkSeq env s = unSinkSeq $ sink env (SinkSeq s)++instance Kit acc => Sink (SinkSeq acc senv) where+ weaken :: forall aenv aenv' arrs. aenv :> aenv' -> SinkSeq acc senv aenv arrs -> SinkSeq acc senv aenv' arrs+ weaken k (SinkSeq s) = SinkSeq $+ case s of+ Producer p s' -> Producer (weakenP p) (weakenL s')+ Consumer c -> Consumer (weakenC c)+ Reify ix -> Reify ix++ where+ weakenL :: forall senv' arrs'. PreOpenSeq acc aenv senv' arrs' -> PreOpenSeq acc aenv' senv' arrs'+ weakenL s' = unSinkSeq (weaken k (SinkSeq s'))++ weakenP :: forall a. Producer acc aenv senv a -> Producer acc aenv' senv a+ weakenP p =+ case p of+ StreamIn arrs -> StreamIn arrs+ ToSeq slix sh a -> ToSeq slix sh (weaken k a)+ MapSeq f x -> MapSeq (weaken k f) x+ ChunkedMapSeq f x -> ChunkedMapSeq (weaken k f) x+ ZipWithSeq f x y -> ZipWithSeq (weaken k f) x y+ ScanSeq f a x -> ScanSeq (weaken k f) (weaken k a) x++ weakenC :: forall a. Consumer acc aenv senv a -> Consumer acc aenv' senv a+ weakenC c =+ case c of+ FoldSeq f a x -> FoldSeq (weaken k f) (weaken k a) x+ FoldSeqFlatten f a x -> FoldSeqFlatten (weaken k f) (weaken k a) x+ Stuple t ->+ let wk :: Atuple (Consumer acc aenv senv) t -> Atuple (Consumer acc aenv' senv) t+ wk NilAtup = NilAtup+ wk (SnocAtup t c) = wk t `SnocAtup` weakenC c+ in+ Stuple (wk t)+--}++-- Array fusion of a de Bruijn computation AST+-- ===========================================++-- Array computations+-- ------------------++-- Evaluate a delayed computation and tie the recursive knot+--+-- We do a bit of extra work to (try to) maintain that terms should be left+-- at their lowest common use site. SEE: [Fusion and the lowest common use site]+--+computeAcc+ :: HasCallStack+ => Embed OpenAcc aenv arrs+ -> OpenAcc aenv arrs+computeAcc (Embed BaseEnv cc) = OpenAcc (compute cc)+computeAcc (Embed env@(PushEnv bot lhs top) cc) =+ simplify cc & \case+ Left (Done v) -> bindA env (avarsIn OpenAcc v)+ Right d -> d & \case+ Yield repr sh f+ -> bindA env (OpenAcc (Generate repr sh f))++ Step repr sh p f v@(Var _ ix)+ | Just Refl <- matchOpenExp sh (arrayShape v)+ , Just Refl <- isIdentity p+ -> case ix of+ ZeroIdx+ | LeftHandSideSingle ArrayR{} <- lhs+ , Just (OpenAccFun g) <- strengthen noTop (OpenAccFun f)+ -> bindA bot (OpenAcc (Map (arrayRtype repr) g top))+ _ -> bindA env (OpenAcc (Map (arrayRtype repr) f (avarIn OpenAcc v)))++ | Just Refl <- isIdentity f+ -> case ix of+ ZeroIdx+ | LeftHandSideSingle ArrayR{} <- lhs+ , Just (OpenAccFun q) <- strengthen noTop (OpenAccFun p)+ , Just (OpenAccExp sz) <- strengthen noTop (OpenAccExp sh)+ -> bindA bot (OpenAcc (Backpermute (arrayRshape repr) sz q top))+ _ -> bindA env (OpenAcc (Backpermute (arrayRshape repr) sh p (avarIn OpenAcc v)))++ | otherwise+ -> case ix of+ ZeroIdx+ | LeftHandSideSingle ArrayR{} <- lhs+ , Just (OpenAccFun g) <- strengthen noTop (OpenAccFun f)+ , Just (OpenAccFun q) <- strengthen noTop (OpenAccFun p)+ , Just (OpenAccExp sz) <- strengthen noTop (OpenAccExp sh)+ -> bindA bot (OpenAcc (Transform repr sz q g top))+ _ -> bindA env (OpenAcc (Transform repr sh p f (avarIn OpenAcc v)))++ where+ bindA :: HasCallStack+ => Extend ArrayR OpenAcc aenv aenv'+ -> OpenAcc aenv' a+ -> OpenAcc aenv a+ bindA BaseEnv b = b+ bindA (PushEnv env lhs a) b+ -- If the freshly bound value is directly, returned, we don't have to bind it in a+ -- let. We can do this if the left hand side does not contain wildcards (other than+ -- wildcards for unit / nil) and if the value contains the same variables.+ | Just vars <- extractOpenArrayVars b+ , Just Refl <- bindingIsTrivial lhs vars = bindA env a+ | otherwise = bindA env (OpenAcc (Alet lhs a b))++ noTop :: (aenv, a) :?> aenv+ noTop ZeroIdx = Nothing+ noTop (SuccIdx ix) = Just ix++++-- Convert the internal representation of delayed arrays into a real AST+-- node. Use the most specific version of a combinator whenever possible.+--+compute+ :: HasCallStack+ => Cunctation r aenv arrs+ -> PreOpenAcc OpenAcc aenv arrs+compute cc = simplify cc & \case+ Left (Done v) -> v & \case+ TupRunit -> Anil+ TupRsingle v@(Var ArrayR{} _) -> Avar v+ TupRpair v1 v2 -> avarsIn OpenAcc v1 `Apair` avarsIn OpenAcc v2+ Right d -> d & \case+ Yield aR sh f -> Generate aR sh f+ Step (ArrayR shR tR) sh p f v+ | Just Refl <- matchOpenExp sh (arrayShape v)+ , Just Refl <- isIdentity p -> Map tR f (avarIn OpenAcc v)+ | Just Refl <- isIdentity f -> Backpermute shR sh p (avarIn OpenAcc v)+ | otherwise -> Transform (ArrayR shR tR) sh p f (avarIn OpenAcc v)+++-- Representation of a generator as a delayed array+--+generateD+ :: HasCallStack+ => ArrayR (Array sh e)+ -> Exp aenv sh+ -> Fun aenv (sh -> e)+ -> Embed OpenAcc aenv (Array sh e)+generateD repr sh f+ = Stats.ruleFired "generateD"+ $ Embed BaseEnv (Yield repr sh f)+++-- Fuse a unary function into a delayed array. Also looks for unzips which can+-- be executed in constant time; SEE [unzipD]+--+mapD :: HasCallStack+ => TypeR b+ -> Fun aenv (a -> b)+ -> Embed OpenAcc aenv (Array sh a)+ -> Embed OpenAcc aenv (Array sh b)+mapD tR f (unzipD tR f -> Just a) = a+mapD tR f (Embed env cc)+ = Stats.ruleFired "mapD"+ $ Embed env (go (delaying cc))+ where+ go (Step (ArrayR shR _) sh ix g v) = Step (ArrayR shR tR) sh ix (sinkA env f `compose` g) v+ go (Yield (ArrayR shR _) sh g) = Yield (ArrayR shR tR) sh (sinkA env f `compose` g)+++-- If we are unzipping a manifest array then force the term to be computed;+-- a backend will be able to execute this in constant time.+--+unzipD+ :: HasCallStack+ => TypeR b+ -> Fun aenv (a -> b)+ -> Embed OpenAcc aenv (Array sh a)+ -> Maybe (Embed OpenAcc aenv (Array sh b))+unzipD tR f (Embed env cc@(Done v))+ | Lam lhs (Body a) <- f+ , Just vars <- extractExpVars a+ , ArrayR shR _ <- arrayR cc+ , f' <- Lam lhs $ Body $ expVars vars+ = Just $ Embed (env `pushArrayEnv` OpenAcc (Map tR f' $ avarsIn OpenAcc v)) $ doneZeroIdx $ ArrayR shR tR+unzipD _ _ _+ = Nothing++-- Fuse an index space transformation function that specifies where elements in+-- the destination array read there data from in the source array.+--+backpermuteD+ :: HasCallStack+ => ShapeR sh'+ -> Exp aenv sh'+ -> Fun aenv (sh' -> sh)+ -> Cunctation r aenv (Array sh e)+ -> Cunctation D aenv (Array sh' e)+backpermuteD shR' sh' p = Stats.ruleFired "backpermuteD" . go . delaying+ where+ go (Step (ArrayR _ tR) _ q f v) = Step (ArrayR shR' tR) sh' (q `compose` p) f v+ go (Yield (ArrayR _ tR) _ g) = Yield (ArrayR shR' tR) sh' (g `compose` p)+++-- Transform as a combined map and backwards permutation+--+transformD+ :: HasCallStack+ => ArrayR (Array sh' b)+ -> Exp aenv sh'+ -> Fun aenv (sh' -> sh)+ -> Fun aenv (a -> b)+ -> Embed OpenAcc aenv (Array sh a)+ -> Embed OpenAcc aenv (Array sh' b)+transformD (ArrayR shR' tR) sh' p f+ = Stats.ruleFired "transformD"+ . fuse (into2 (backpermuteD shR') sh' p)+ . mapD tR f+ where+ fuse :: HasCallStack+ => (forall r aenv'. Extend ArrayR OpenAcc aenv aenv' -> Cunctation r aenv' as -> Cunctation D aenv' bs)+ -> Embed OpenAcc aenv as+ -> Embed OpenAcc aenv bs+ fuse op (Embed env cc) = Embed env (op env cc)++ into2 :: (HasCallStack, Sink f1, Sink f2)+ => (f1 env' a -> f2 env' b -> c)+ -> f1 env a+ -> f2 env b+ -> Extend ArrayR OpenAcc env env'+ -> c+ into2 op a b env = op (sinkA env a) (sinkA env b)+++-- Replicate as a backwards permutation+--+-- TODO: If we have a pattern such as `replicate sh (map f xs)` then in some+-- cases it might be beneficial to not fuse these terms, if `f` is+-- expensive and/or `sh` is large.+--+replicateD+ :: HasCallStack+ => SliceIndex slix sl co sh+ -> Exp aenv slix+ -> Cunctation r aenv (Array sl e)+ -> Cunctation D aenv (Array sh e)+replicateD sliceIndex slix cc+ = Stats.ruleFired "replicateD"+ $ backpermuteD (sliceDomainR sliceIndex) (IndexFull sliceIndex slix (shape cc)) (extend sliceIndex slix) cc+++-- Dimensional slice as a backwards permutation+--+sliceD+ :: HasCallStack+ => SliceIndex slix sl co sh+ -> Exp aenv slix+ -> Cunctation r aenv (Array sh e)+ -> Cunctation D aenv (Array sl e)+sliceD sliceIndex slix cc+ = Stats.ruleFired "sliceD"+ $ backpermuteD (sliceShapeR sliceIndex) (IndexSlice sliceIndex slix (shape cc)) (restrict sliceIndex slix) cc+++-- Reshape an array+--+-- For delayed arrays this is implemented as an index space transformation. For+-- manifest arrays this can be done with the standard Reshape operation in+-- constant time without executing any array operations. This does not affect+-- the fusion process since the term is already manifest.+--+-- TLM: there was a runtime check to ensure the old and new shapes contained the+-- same number of elements: this has been lost for the delayed cases!+--+reshapeD+ :: HasCallStack+ => ShapeR sl+ -> Embed OpenAcc aenv (Array sh e)+ -> Exp aenv sl+ -> Embed OpenAcc aenv (Array sl e)+reshapeD slr (Embed env cc) (sinkA env -> sl)+ | Done v <- cc+ = Embed (env `pushArrayEnv` OpenAcc (Reshape slr sl (avarsIn OpenAcc v))) $ doneZeroIdx repr++ | otherwise+ = Stats.ruleFired "reshapeD"+ $ Embed env (backpermuteD slr sl (reindex (arrayRshape $ arrayR cc) (shape cc) slr sl) cc)++ where+ ArrayR _ tR = arrayR cc+ repr = ArrayR slr tR+++-- Combine two arrays element-wise with a binary function to produce a delayed+-- array.+--+zipWithD+ :: HasCallStack+ => TypeR c+ -> Fun aenv (a -> b -> c)+ -> Cunctation r aenv (Array sh a)+ -> Cunctation s aenv (Array sh b)+ -> Cunctation D aenv (Array sh c)+zipWithD tR f cc1 cc0+ -- Two stepper functions identically accessing the same array can be kept in+ -- stepping form. This might yield a simpler final term.+ --+ | Step (ArrayR shR _) sh1 p1 f1 v1 <- delaying cc1+ , Step _ sh0 p0 f0 v0 <- delaying cc0+ , Just Refl <- matchVar v1 v0+ , Just Refl <- matchOpenFun p1 p0+ = Stats.ruleFired "zipWithD/step"+ $ Step (ArrayR shR tR) (intersect shR sh1 sh0) p0 (combine f f1 f0) v0++ -- Otherwise transform both delayed terms into (index -> value) mappings and+ -- combine the two indexing functions that way.+ --+ | Yield (ArrayR shR _) sh1 f1 <- yield cc1+ , Yield _ sh0 f0 <- yield cc0+ = Stats.ruleFired "zipWithD"+ $ Yield (ArrayR shR tR) (intersect shR sh1 sh0) (combine f f1 f0)++ | otherwise+ = error "work is stressing me out, I should take a break"+ where+ combine :: forall aenv a b c e. HasCallStack+ => Fun aenv (a -> b -> c)+ -> Fun aenv (e -> a)+ -> Fun aenv (e -> b)+ -> Fun aenv (e -> c)+ combine c ixa ixb+ | Lam lhs1 (Body ixa') <- ixa+ , Lam lhs2 (Body ixb') <- ixb+ -- The two LeftHandSides may differ in the use of wildcards. If they do not match, we must+ -- combine them as done in `combineLHS`. As this will probably not occur often and requires+ -- additional weakening, we do a quick check whether the left hand sides are equal.+ --+ = case matchELeftHandSide lhs1 lhs2 of+ Just Refl+ | Lam lhsA (Lam lhsB (Body c')) <- weakenE (weakenWithLHS lhs1) c+ -> Lam lhs1 $ Body $ Let lhsA ixa' $ Let lhsB (weakenE (weakenWithLHS lhsA) ixb') c'+ Nothing+ | CombinedLHS lhs k1 k2 <- combineLHS lhs1 lhs2+ , Lam lhsA (Lam lhsB (Body c')) <- weakenE (weakenWithLHS lhs) c+ , ixa'' <- weakenE k1 ixa'+ -> Lam lhs $ Body $ Let lhsA ixa'' $ Let lhsB (weakenE (weakenWithLHS lhsA .> k2) ixb') c'+ _+ -> error "how's your break?"+ --+ | otherwise+ = error "work is stressing me out, I should get back to it"+++data CombinedLHS s t env1' env2' env where+ CombinedLHS :: LeftHandSide s t env env'+ -> env1' :> env'+ -> env2' :> env'+ -> CombinedLHS s t env1' env2' env++combineLHS+ :: HasCallStack+ => LeftHandSide s t env env1'+ -> LeftHandSide s t env env2'+ -> CombinedLHS s t env1' env2' env+combineLHS = go weakenId weakenId+ where+ go :: env1 :> env -> env2 :> env -> LeftHandSide s t env1 env1' -> LeftHandSide s t env2 env2' -> CombinedLHS s t env1' env2' env+ go k1 k2 (LeftHandSideWildcard tR) (LeftHandSideWildcard _) = CombinedLHS (LeftHandSideWildcard tR) k1 k2+ go k1 k2 (LeftHandSideSingle tR) (LeftHandSideSingle _) = CombinedLHS (LeftHandSideSingle tR) (sink k1) (sink k2)+ go k1 k2 (LeftHandSidePair l1 h1) (LeftHandSidePair l2 h2)+ | CombinedLHS l k1' k2' <- go k1 k2 l1 l2+ , CombinedLHS h k1'' k2'' <- go k1' k2' h1 h2 = CombinedLHS (LeftHandSidePair l h) k1'' k2''+ go k1 k2 (LeftHandSideWildcard _) lhs+ | Exists lhs' <- rebuildLHS lhs = CombinedLHS lhs' (weakenWithLHS lhs' .> k1) (sinkWithLHS lhs lhs' k2)+ go k1 k2 lhs (LeftHandSideWildcard _)+ | Exists lhs' <- rebuildLHS lhs = CombinedLHS lhs' (sinkWithLHS lhs lhs' k1) (weakenWithLHS lhs' .> k2)+ go _ _ _ _+ = internalError "unexpected LHS combination"++++-- NOTE: [Sharing vs. Fusion]+--+-- The approach to array fusion is similar to that the first generation of Repa.+-- It was discovered that the most immediately pressing problem with delayed+-- arrays in Repa-1 was that it did not preserve sharing of collective+-- operations, leading to excessive recomputation and severe repercussions on+-- performance if the user did not explicitly intervene.+--+-- However, as we have explicit sharing information in the term tree, so it is+-- straightforward to respect sharing by not fusing let-bindings, as that+-- introduces work duplication. However, sometimes we can be cleverer.+--+-- let-floating:+-- -------------+--+-- If the binding is of manifest data, we can instead move the let-binding to a+-- different point in the program and then continue to fuse into the body. This+-- is done by adding the bound term to the Extend environment. In essence this+-- is covering a different occurrence of the same problem Extend was introduced+-- to handle: let bindings of manifest data unnecessarily get in the way of the+-- fusion process. For example:+--+-- map f (zipWith g xs (map h xs))+--+-- after sharing recovery results in:+--+-- map f (let a0 = xs in zipWith g a0 (map h a0))+--+-- Without allowing the binding for a0 to float outwards, `map f` will not be+-- fused into the rest of the program.+--+-- let-elimination:+-- ----------------+--+-- Array binding points appear in the program because the array data _or_ shape+-- was accessed multiple times in the source program. In general we want to fuse+-- arbitrary sequences of array _data_, irrespective of how the shape component+-- is used. For example, reverse is defined in the prelude as:+--+-- reverse xs = let len = unindex1 (shape xs)+-- pf i = len - i - 1+-- in+-- backpermute (shape xs) (ilift1 pf) xs+--+-- Sharing recovery introduces a let-binding for the input `xs` since it is used+-- thrice in the definition, which impedes subsequent fusion. However the actual+-- array data is only accessed once, with the remaining two uses querying the+-- array shape. Since the delayed terms contain the shape of the array they+-- represent as a scalar term, if the data component otherwise satisfies the+-- rules for fusing terms, as it does in this example, we can eliminate the+-- let-binding by pushing the scalar shape and value generation terms directly+-- into the body.+--+-- Let-elimination can also be used to _introduce_ work duplication, which may+-- be beneficial if we can estimate that the cost of re-computation is less than+-- the cost of completely evaluating the array and subsequently retrieving the+-- data from memory.+--+-- let-binding:+-- ------------+--+-- Ultimately, we might not want to eliminate the binding. If so, evaluate it+-- and add it to a _clean_ Extend environment for the body. If not, the Extend+-- list effectively _flattens_ all bindings, so any terms required for the bound+-- term get lifted out to the same scope as the body. This increases their+-- lifetime and hence raises the maximum memory used. If we don't do this, we+-- get terms such as:+--+-- let a0 = <terms for binding> in+-- let bnd = <bound term> in+-- <body term>+--+-- rather than the following, where the scope of a0 is clearly only availably+-- when evaluating the bound term, as it should be:+--+-- let bnd =+-- let a0 = <terms for binding>+-- in <bound term>+-- in <body term>+--+aletD :: HasCallStack+ => EmbedAcc OpenAcc+ -> ElimAcc OpenAcc+ -> ALeftHandSide arrs aenv aenv'+ -> OpenAcc aenv arrs+ -> OpenAcc aenv' brrs+ -> Embed OpenAcc aenv brrs+aletD embedAcc elimAcc lhs (embedAcc -> Embed env1 cc1) acc0++ -- let-floating+ -- ------------+ --+ -- Immediately inline the variable referring to the bound expression into the+ -- body, instead of adding to the environments and creating an indirection+ -- that must be later eliminated by shrinking.+ --+ | LeftHandSideSingle _ <- lhs+ , Done (TupRsingle v1@(Var ArrayR{} _)) <- cc1+ , Embed env0 cc0 <- embedAcc $ rebuildA (subAtop (Avar v1) . sink1 env1) acc0+ = Stats.ruleFired "aletD/float"+ $ Embed (env1 `append` env0) cc0++ -- Ensure we only call 'embedAcc' once on the body expression+ --+ | otherwise+ = aletD' embedAcc elimAcc lhs (Embed env1 cc1) (embedAcc acc0)+++aletD' :: forall aenv aenv' arrs brrs. HasCallStack+ => EmbedAcc OpenAcc+ -> ElimAcc OpenAcc+ -> ALeftHandSide arrs aenv aenv'+ -> Embed OpenAcc aenv arrs+ -> Embed OpenAcc aenv' brrs+ -> Embed OpenAcc aenv brrs+aletD' embedAcc elimAcc (LeftHandSideSingle ArrayR{}) (Embed env1 cc1) (Embed env0 cc0)++ -- let-binding+ -- -----------+ --+ -- Check whether we can eliminate the let-binding. Note that we must inspect+ -- the entire term, not just the Cunctation that would be produced by+ -- embedAcc. If we don't we can be left with dead terms that don't get+ -- eliminated. This problem occurred in the canny program.+ --+ | acc1 <- computeAcc (Embed env1 cc1)+ , False <- elimAcc acc1 acc0+ = Stats.ruleFired "aletD/bind"+ $ Embed (BaseEnv `pushArrayEnv` acc1 `append` env0) cc0++ -- let-elimination+ -- ---------------+ --+ -- Handle the remaining cases in a separate function. It turns out that this+ -- is important so we aren't excessively sinking/delaying terms.+ --+ | acc0' <- sink1 env1 acc0+ = Stats.ruleFired "aletD/eliminate"+ $ case delaying cc1 of+ Step{} -> eliminate env1 cc1 acc0'+ Yield{} -> eliminate env1 cc1 acc0'++ where+ acc0 :: OpenAcc aenv' brrs+ acc0 = computeAcc (Embed env0 cc0)++ kmap :: forall aenv a b. (PreOpenAcc OpenAcc aenv a -> PreOpenAcc OpenAcc aenv b)+ -> OpenAcc aenv a+ -> OpenAcc aenv b+ kmap f (OpenAcc pacc) = OpenAcc (f pacc)++ -- The second part of let-elimination. Splitting into two steps exposes the+ -- extra type variables, and ensures we don't do extra work manipulating the+ -- body when not necessary (which can lead to a complexity blowup).+ --+ eliminate+ :: forall r aenv aenv' sh e brrs. HasCallStack+ => Extend ArrayR OpenAcc aenv aenv'+ -> Cunctation r aenv' (Array sh e)+ -> OpenAcc (aenv', Array sh e) brrs+ -> Embed OpenAcc aenv brrs+ eliminate env1 cc1 body+ | Done v1 <- cc1+ , TupRsingle v1'@(Var r _) <- v1 = elim r (arrayShape v1') (indexArray v1')+ | Step r sh1 p1 f1 v1 <- cc1 = elim r sh1 (f1 `compose` indexArray v1 `compose` p1)+ | Yield r sh1 f1 <- cc1 = elim r sh1 f1+ where+ bnd :: PreOpenAcc OpenAcc aenv' (Array sh e)+ bnd = compute cc1++ elim :: HasCallStack+ => ArrayR (Array sh e)+ -> Exp aenv' sh+ -> Fun aenv' (sh -> e)+ -> Embed OpenAcc aenv brrs+ elim r sh1 f1+ | sh1' <- weaken (weakenSucc' weakenId) sh1+ , f1' <- weaken (weakenSucc' weakenId) f1+ , Embed env0' cc0' <- embedAcc $ rebuildA (subAtop bnd) $ kmap (replaceA sh1' f1' $ Var r ZeroIdx) body+ = Embed (env1 `append` env0') cc0'++ -- As part of let-elimination, we need to replace uses of array variables in+ -- scalar expressions with an equivalent expression that generates the+ -- result directly+ --+ -- TODO: when we inline bindings we ought to let bind at the first+ -- occurrence and use a variable at all subsequent locations. At the+ -- moment we are just hoping CSE in the simplifier phase does good+ -- things, but that is limited in what it looks for.+ --+ replaceE :: forall env aenv sh e t. HasCallStack+ => OpenExp env aenv sh+ -> OpenFun env aenv (sh -> e)+ -> ArrayVar aenv (Array sh e)+ -> OpenExp env aenv t+ -> OpenExp env aenv t+ replaceE sh' f' avar@(Var (ArrayR shR _) _) exp =+ case exp of+ Let lhs x y -> let k = weakenWithLHS lhs+ in Let lhs (cvtE x) (replaceE (weakenE k sh') (weakenE k f') avar y)+ Evar var -> Evar var+ Foreign tR ff f e -> Foreign tR ff f (cvtE e)+ Const tR c -> Const tR c+ Undef tR -> Undef tR+ Nil -> Nil+ Pair e1 e2 -> Pair (cvtE e1) (cvtE e2)+ VecPack vR e -> VecPack vR (cvtE e)+ VecUnpack vR e -> VecUnpack vR (cvtE e)+ IndexSlice x ix sh -> IndexSlice x (cvtE ix) (cvtE sh)+ IndexFull x ix sl -> IndexFull x (cvtE ix) (cvtE sl)+ ToIndex shR' sh ix -> ToIndex shR' (cvtE sh) (cvtE ix)+ FromIndex shR' sh i -> FromIndex shR' (cvtE sh) (cvtE i)+ Case e rhs def -> Case (cvtE e) (over (mapped . _2) cvtE rhs) (fmap cvtE def)+ Cond p t e -> Cond (cvtE p) (cvtE t) (cvtE e)+ PrimConst c -> PrimConst c+ PrimApp g x -> PrimApp g (cvtE x)+ ShapeSize shR' sh -> ShapeSize shR' (cvtE sh)+ While p f x -> While (replaceF sh' f' avar p) (replaceF sh' f' avar f) (cvtE x)+ Coerce t1 t2 e -> Coerce t1 t2 (cvtE e)++ Shape a+ | Just Refl <- matchVar a avar -> Stats.substitution "replaceE/shape" sh'+ | otherwise -> exp++ Index a sh+ | Just Refl <- matchVar a avar+ , Lam lhs (Body b) <- f' -> Stats.substitution "replaceE/!" . cvtE $ Let lhs sh b+ | otherwise -> Index a (cvtE sh)++ LinearIndex a i+ | Just Refl <- matchVar a avar+ , Lam lhs (Body b) <- f'+ -> Stats.substitution "replaceE/!!" . cvtE+ $ Let lhs+ (Let (LeftHandSideSingle scalarTypeInt) i+ $ FromIndex shR (weakenE (weakenSucc' weakenId) sh')+ $ Evar+ $ Var scalarTypeInt ZeroIdx)+ b+ | otherwise -> LinearIndex a (cvtE i)++ where+ cvtE :: OpenExp env aenv s -> OpenExp env aenv s+ cvtE = replaceE sh' f' avar++ replaceF :: forall env aenv sh e t. HasCallStack+ => OpenExp env aenv sh+ -> OpenFun env aenv (sh -> e)+ -> ArrayVar aenv (Array sh e)+ -> OpenFun env aenv t+ -> OpenFun env aenv t+ replaceF sh' f' avar fun =+ case fun of+ Body e -> Body (replaceE sh' f' avar e)+ Lam lhs f -> let k = weakenWithLHS lhs+ in Lam lhs (replaceF (weakenE k sh') (weakenE k f') avar f)++ replaceA :: forall aenv sh e a. HasCallStack+ => Exp aenv sh+ -> Fun aenv (sh -> e)+ -> ArrayVar aenv (Array sh e)+ -> PreOpenAcc OpenAcc aenv a+ -> PreOpenAcc OpenAcc aenv a+ replaceA sh' f' avar pacc =+ case pacc of+ Avar v+ | Just Refl <- matchVar v avar -> Avar avar+ | otherwise -> Avar v++ Alet lhs bnd (body :: OpenAcc aenv1 a) ->+ let w :: aenv :> aenv1+ w = weakenWithLHS lhs+ sh'' = weaken w sh'+ f'' = weaken w f'+ in+ Alet lhs (cvtA bnd) (kmap (replaceA sh'' f'' (weaken w avar)) body)++ Use repr arrs -> Use repr arrs+ Unit tR e -> Unit tR (cvtE e)+ Acond p at ae -> Acond (cvtE p) (cvtA at) (cvtA ae)+ Anil -> Anil+ Atrace msg a b -> Atrace msg (cvtA a) (cvtA b)+ Apair a1 a2 -> Apair (cvtA a1) (cvtA a2)+ Awhile p f a -> Awhile (cvtAF p) (cvtAF f) (cvtA a)+ Apply repr f a -> Apply repr (cvtAF f) (cvtA a)+ Aforeign repr ff f a -> Aforeign repr ff f (cvtA a) -- no sharing between f and a+ Generate repr sh f -> Generate repr (cvtE sh) (cvtF f)+ Map tR f a -> Map tR (cvtF f) (cvtA a)+ ZipWith tR f a b -> ZipWith tR (cvtF f) (cvtA a) (cvtA b)+ Backpermute shR sh p a -> Backpermute shR (cvtE sh) (cvtF p) (cvtA a)+ Transform repr sh p f a -> Transform repr (cvtE sh) (cvtF p) (cvtF f) (cvtA a)+ Slice slix a sl -> Slice slix (cvtA a) (cvtE sl)+ Replicate slix sh a -> Replicate slix (cvtE sh) (cvtA a)+ Reshape shR sl a -> Reshape shR (cvtE sl) (cvtA a)+ Fold f z a -> Fold (cvtF f) (cvtE <$> z) (cvtA a)+ FoldSeg i f z a s -> FoldSeg i (cvtF f) (cvtE <$> z) (cvtA a) (cvtA s)+ Scan d f z a -> Scan d (cvtF f) (cvtE <$> z) (cvtA a)+ Scan' d f z a -> Scan' d (cvtF f) (cvtE z) (cvtA a)+ Permute f d p a -> Permute (cvtF f) (cvtA d) (cvtF p) (cvtA a)+ Stencil s t f x a -> Stencil s t (cvtF f) (cvtB x) (cvtA a)+ Stencil2 s1 s2 t f x a y b+ -> Stencil2 s1 s2 t (cvtF f) (cvtB x) (cvtA a) (cvtB y) (cvtA b)+ -- Collect seq -> Collect (cvtSeq seq)++ where+ cvtA :: OpenAcc aenv s -> OpenAcc aenv s+ cvtA = kmap (replaceA sh' f' avar)++ cvtE :: Exp aenv s -> Exp aenv s+ cvtE = replaceE sh' f' avar++ cvtF :: Fun aenv s -> Fun aenv s+ cvtF = replaceF sh' f' avar++ cvtB :: Boundary aenv s -> Boundary aenv s+ cvtB Clamp = Clamp+ cvtB Mirror = Mirror+ cvtB Wrap = Wrap+ cvtB (Constant c) = Constant c+ cvtB (Function f) = Function (cvtF f)++ cvtAF :: HasCallStack => PreOpenAfun OpenAcc aenv s -> PreOpenAfun OpenAcc aenv s+ cvtAF = cvt sh' f' avar+ where+ cvt :: forall aenv a.+ Exp aenv sh -> Fun aenv (sh -> e) -> ArrayVar aenv (Array sh e)+ -> PreOpenAfun OpenAcc aenv a+ -> PreOpenAfun OpenAcc aenv a+ cvt sh'' f'' avar' (Abody a) = Abody $ kmap (replaceA sh'' f'' avar') a+ cvt sh'' f'' avar' (Alam lhs (af :: PreOpenAfun OpenAcc aenv1 b)) =+ Alam lhs $ cvt (weaken w sh'')+ (weaken w f'')+ (weaken w avar')+ af+ where+ w :: aenv :> aenv1+ w = weakenWithLHS lhs++-- Do not fuse bindings of multiple variables+aletD' _ _ lhs (Embed env1 cc1) (Embed env0 cc0)+ = Stats.ruleFired "aletD/bind"+ $ Embed (PushEnv BaseEnv lhs (computeAcc (Embed env1 cc1)) `append` env0) cc0++{--+ cvtSeq :: PreOpenSeq acc aenv senv s -> PreOpenSeq acc aenv senv s+ cvtSeq s =+ case s of+ Producer p s' ->+ Producer+ (case p of+ StreamIn arrs -> StreamIn arrs+ ToSeq slix sh a -> ToSeq slix sh (cvtA a)+ MapSeq f x -> MapSeq (cvtAF f) x+ ChunkedMapSeq f x -> ChunkedMapSeq (cvtAF f) x+ ZipWithSeq f x y -> ZipWithSeq (cvtAF f) x y+ ScanSeq f e x -> ScanSeq (cvtF f) (cvtE e) x)+ (cvtSeq s')+ Consumer c ->+ Consumer (cvtC c)+ Reify ix -> Reify ix++ cvtC :: Consumer acc aenv senv s -> Consumer acc aenv senv s+ cvtC c =+ case c of+ FoldSeq f e x -> FoldSeq (cvtF f) (cvtE e) x+ FoldSeqFlatten f a x -> FoldSeqFlatten (cvtAF f) (cvtA a) x+ Stuple t -> Stuple (cvtCT t)++ cvtCT :: Atuple (Consumer acc aenv senv) t -> Atuple (Consumer acc aenv senv) t+ cvtCT NilAtup = NilAtup+ cvtCT (SnocAtup t c) = cvtCT t `SnocAtup` cvtC c+--}+++-- Array conditionals, in particular eliminate branches when the predicate+-- reduces to a known constant.+--+-- Note that we take the raw unprocessed terms as input. If instead we had the+-- terms for each branch in the delayed representation, this would require that+-- each term has been sunk into a common environment, which implies the+-- conditional has been pushed underneath the intersection of bound terms for+-- both branches. This would result in redundant work processing the bindings+-- for the branch not taken.+--+acondD :: HasCallStack+ => MatchAcc OpenAcc+ -> EmbedAcc OpenAcc+ -> Exp aenv PrimBool+ -> OpenAcc aenv arrs+ -> OpenAcc aenv arrs+ -> Embed OpenAcc aenv arrs+acondD matchAcc embedAcc p t e+ | Const _ 1 <- p = Stats.knownBranch "True" $ embedAcc t+ | Const _ 0 <- p = Stats.knownBranch "False" $ embedAcc e+ | Just Refl <- matchAcc t e = Stats.knownBranch "redundant" $ embedAcc e+ | otherwise = done $ Acond p (computeAcc (embedAcc t))+ (computeAcc (embedAcc e))+++-- Scalar expressions+-- ------------------++identity :: TypeR a -> OpenFun env aenv (a -> a)+identity t+ | DeclareVars lhs _ value <- declareVars t+ = Lam lhs $ Body $ expVars $ value weakenId++toIndex :: ShapeR sh -> OpenExp env aenv sh -> OpenFun env aenv (sh -> Int)+toIndex shR sh+ | DeclareVars lhs k value <- declareVars $ shapeType shR+ = Lam lhs $ Body $ ToIndex shR (weakenE k sh) $ expVars $ value weakenId++fromIndex :: ShapeR sh -> OpenExp env aenv sh -> OpenFun env aenv (Int -> sh)+fromIndex shR sh+ = Lam (LeftHandSideSingle scalarTypeInt)+ $ Body+ $ FromIndex shR (weakenE (weakenSucc' weakenId) sh)+ $ Evar+ $ Var scalarTypeInt ZeroIdx++intersect :: ShapeR sh -> OpenExp env aenv sh -> OpenExp env aenv sh -> OpenExp env aenv sh+intersect = mkShapeBinary f+ where+ f a b = PrimApp (PrimMin singleType) $ Pair a b++-- union :: ShapeR sh -> OpenExp env aenv sh -> OpenExp env aenv sh -> OpenExp env aenv sh+-- union = mkShapeBinary f+-- where+-- f a b = PrimApp (PrimMax singleType) $ Pair a b++mkShapeBinary+ :: (forall env'. OpenExp env' aenv Int -> OpenExp env' aenv Int -> OpenExp env' aenv Int)+ -> ShapeR sh+ -> OpenExp env aenv sh+ -> OpenExp env aenv sh+ -> OpenExp env aenv sh+mkShapeBinary _ ShapeRz _ _ = Nil+mkShapeBinary f (ShapeRsnoc shR) (Pair as a) (Pair bs b) = mkShapeBinary f shR as bs `Pair` f a b+mkShapeBinary f shR (Let lhs bnd a) b = Let lhs bnd $ mkShapeBinary f shR a (weakenE (weakenWithLHS lhs) b)+mkShapeBinary f shR a (Let lhs bnd b) = Let lhs bnd $ mkShapeBinary f shR (weakenE (weakenWithLHS lhs) a) b+mkShapeBinary f shR a b@Pair{} -- `a` is not Pair+ | DeclareVars lhs k value <- declareVars $ shapeType shR+ = Let lhs a $ mkShapeBinary f shR (expVars $ value weakenId) (weakenE k b)+mkShapeBinary f shR a b -- `b` is not a Pair+ | DeclareVars lhs k value <- declareVars $ shapeType shR+ = Let lhs b $ mkShapeBinary f shR (weakenE k a) (expVars $ value weakenId)++reindex :: ShapeR sh'+ -> OpenExp env aenv sh'+ -> ShapeR sh+ -> OpenExp env aenv sh+ -> OpenFun env aenv (sh -> sh')+reindex shR' sh' shR sh+ | Just Refl <- matchOpenExp sh sh' = identity (shapeType shR')+ | otherwise = fromIndex shR' sh' `compose` toIndex shR sh++extend :: SliceIndex slix sl co sh+ -> Exp aenv slix+ -> Fun aenv (sh -> sl)+extend sliceIndex slix+ | DeclareVars lhs k value <- declareVars $ shapeType $ sliceDomainR sliceIndex+ = Lam lhs $ Body $ IndexSlice sliceIndex (weakenE k slix) $ expVars $ value weakenId++restrict :: SliceIndex slix sl co sh+ -> Exp aenv slix+ -> Fun aenv (sl -> sh)+restrict sliceIndex slix+ | DeclareVars lhs k value <- declareVars $ shapeType $ sliceShapeR sliceIndex+ = Lam lhs $ Body $ IndexFull sliceIndex (weakenE k slix) $ expVars $ value weakenId++arrayShape :: ArrayVar aenv (Array sh e) -> Exp aenv sh+arrayShape = simplifyExp . Shape++indexArray :: ArrayVar aenv (Array sh e) -> Fun aenv (sh -> e)+indexArray v@(Var (ArrayR shR _) _)+ | DeclareVars lhs _ value <- declareVars $ shapeType shR+ = Lam lhs $ Body $ Index v $ expVars $ value weakenId++linearIndex :: ArrayVar aenv (Array sh e) -> Fun aenv (Int -> e)+linearIndex v = Lam (LeftHandSideSingle scalarTypeInt) $ Body $ LinearIndex v $ Evar $ Var scalarTypeInt ZeroIdx+++extractOpenAcc :: ExtractAcc OpenAcc+extractOpenAcc (OpenAcc pacc) = Just pacc++extractDelayedOpenAcc :: ExtractAcc DelayedOpenAcc+extractDelayedOpenAcc (Manifest pacc) = Just pacc+extractDelayedOpenAcc _ = Nothing++extractOpenArrayVars+ :: OpenAcc aenv a+ -> Maybe (ArrayVars aenv a)+extractOpenArrayVars (OpenAcc pacc) =+ avarsOut extractOpenAcc pacc++extractDelayedArrayVars+ :: DelayedOpenAcc aenv a+ -> Maybe (ArrayVars aenv a)+extractDelayedArrayVars acc+ | Just pacc <- extractDelayedOpenAcc acc = avarsOut extractDelayedOpenAcc pacc+ | otherwise = Nothing+
+ src/Data/Array/Accelerate/Trafo/LetSplit.hs view
@@ -0,0 +1,77 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE GADTs #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Trafo.LetSplit+-- Copyright : [2012..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Trafo.LetSplit (++ convertAfun,+ convertAcc,++) where++import Prelude hiding ( exp )+import Data.Array.Accelerate.AST+import Data.Array.Accelerate.AST.LeftHandSide+import Data.Array.Accelerate.AST.Environment+import Data.Array.Accelerate.Trafo.Substitution+++convertAfun :: PreOpenAfun OpenAcc aenv f -> PreOpenAfun OpenAcc aenv f+convertAfun (Alam lhs f) = Alam lhs (convertAfun f)+convertAfun (Abody a) = Abody (convertAcc a)++convertAcc :: OpenAcc aenv a -> OpenAcc aenv a+convertAcc (OpenAcc pacc) = OpenAcc (convertPreOpenAcc pacc)++convertPreOpenAcc :: PreOpenAcc OpenAcc aenv a -> PreOpenAcc OpenAcc aenv a+convertPreOpenAcc = \case+ Alet lhs bnd body -> convertLHS lhs (convertAcc bnd) (convertAcc body)+ Avar var -> Avar var+ Apair a1 a2 -> Apair (convertAcc a1) (convertAcc a2)+ Anil -> Anil+ Atrace msg as bs -> Atrace msg (convertAcc as) (convertAcc bs)+ Apply repr f a -> Apply repr (convertAfun f) (convertAcc a)+ Aforeign repr asm f a -> Aforeign repr asm (convertAfun f) (convertAcc a)+ Acond e a1 a2 -> Acond e (convertAcc a1) (convertAcc a2)+ Awhile c f a -> Awhile (convertAfun c) (convertAfun f) (convertAcc a)+ Use repr arr -> Use repr arr+ Unit tp e -> Unit tp e+ Reshape shr e a -> Reshape shr e a+ Generate repr e f -> Generate repr e f+ Transform repr sh f g a -> Transform repr sh f g (convertAcc a)+ Replicate slix sl a -> Replicate slix sl (convertAcc a)+ Slice slix a sl -> Slice slix (convertAcc a) sl+ Map tp f a -> Map tp f (convertAcc a)+ ZipWith tp f a1 a2 -> ZipWith tp f (convertAcc a1) (convertAcc a2)+ Fold f e a -> Fold f e (convertAcc a)+ FoldSeg i f e a s -> FoldSeg i f e (convertAcc a) (convertAcc s)+ Scan d f e a -> Scan d f e (convertAcc a)+ Scan' d f e a -> Scan' d f e (convertAcc a)+ Permute f a1 g a2 -> Permute f (convertAcc a1) g (convertAcc a2)+ Backpermute shr sh f a -> Backpermute shr sh f (convertAcc a)+ Stencil s tp f b a -> Stencil s tp f b (convertAcc a)+ Stencil2 s1 s2 tp f b1 a1 b2 a2 -> Stencil2 s1 s2 tp f b1 (convertAcc a1) b2 (convertAcc a2)++convertLHS+ :: ALeftHandSide bnd aenv aenv'+ -> OpenAcc aenv bnd+ -> OpenAcc aenv' a+ -> PreOpenAcc OpenAcc aenv a+convertLHS lhs bnd@(OpenAcc pbnd) a@(OpenAcc pa) =+ case lhs of+ LeftHandSideWildcard{} -> pa+ LeftHandSideSingle{} -> Alet lhs bnd a+ LeftHandSidePair l1 l2 ->+ case pbnd of+ Apair b1 b2 -> convertLHS l1 b1 (OpenAcc (convertLHS l2 (weaken (weakenWithLHS l1) b2) a))+ _ -> Alet lhs bnd a+
+ src/Data/Array/Accelerate/Trafo/Sharing.hs view
@@ -0,0 +1,3161 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedLists #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# OPTIONS_GHC -fno-warn-name-shadowing #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Trafo.Sharing+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- This module implements HOAS to de Bruijn conversion of array expressions+-- while incorporating sharing information.+--++module Data.Array.Accelerate.Trafo.Sharing (++ -- * HOAS to de Bruijn conversion+ convertAcc, convertAccWith,++ Afunction, AfunctionR, ArraysFunctionR, AfunctionRepr(..), afunctionRepr,+ convertAfun, convertAfunWith,++ Function, FunctionR, EltFunctionR, FunctionRepr(..), functionRepr,+ convertExp, convertExpWith,+ convertFun, convertFunWith,++ -- convertSeq++) where++import Data.Array.Accelerate.AST hiding ( PreOpenAcc(..), OpenAcc(..), Acc, OpenExp(..), Exp, Boundary(..), HasArraysR(..), formatPreAccOp )+import Data.Array.Accelerate.AST.Environment+import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.AST.LeftHandSide+import Data.Array.Accelerate.AST.Var+import Data.Array.Accelerate.Analysis.Match+import Data.Array.Accelerate.Debug.Internal.Flags as Debug+import Data.Array.Accelerate.Debug.Internal.Trace as Debug+import Data.Array.Accelerate.Error+import Data.Array.Accelerate.Representation.Array ( Array, ArraysR, ArrayR(..), formatArraysR )+import Data.Array.Accelerate.Representation.Shape hiding ( zip )+import Data.Array.Accelerate.Representation.Stencil+import Data.Array.Accelerate.Representation.Tag+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Smart as Smart+import Data.Array.Accelerate.Sugar.Array hiding ( Array, ArraysR, (!!) )+import Data.Array.Accelerate.Sugar.Elt+import Data.Array.Accelerate.Trafo.Config+import Data.Array.Accelerate.Trafo.Substitution+import Data.Array.Accelerate.Trafo.Var+import Data.Array.Accelerate.Type+import Data.BitSet ( (\\), member )+import qualified Data.Array.Accelerate.AST as AST+import qualified Data.Array.Accelerate.Representation.Stencil as R+import qualified Data.Array.Accelerate.Sugar.Array as Sugar++import Control.Applicative hiding ( Const )+import Control.Monad.Fix+import Data.Function ( on )+import Data.Hashable+import Data.List ( elemIndex, findIndex, groupBy, partition )+import qualified Data.List.NonEmpty as NE+import Data.Maybe+import Data.Monoid ( Any(..) )+import Data.Text.Lazy.Builder+import Formatting+import Lens.Micro ( over, mapped, _1, _2 )+import System.IO.Unsafe ( unsafePerformIO )+import System.Mem.StableName+import qualified Data.HashMap.Strict as Map+import qualified Data.HashSet as Set+import qualified Data.HashTable.IO as Hash+import qualified Data.IntMap as IntMap+import qualified Formatting.Buildable as F+import Prelude hiding ( unlines )+++-- Layouts+-- -------++-- A layout of an environment has an entry for each entry of the environment.+-- Each entry in the layout holds the de Bruijn index that refers to the+-- corresponding entry in the environment.+--+data Layout s env env' where+ EmptyLayout :: Layout s env ()+ PushLayout :: Layout s env env1+ -> LeftHandSide s t env1 env2+ -> Vars s env t+ -> Layout s env env2++type ELayout = Layout ScalarType+type ArrayLayout = Layout ArrayR+++-- Project the nth index out of an environment layout.+--+-- The first argument provides context information for error messages in the+-- case of failure.+--+prjIdx :: forall s t env env1. HasCallStack+ => Builder+ -> (forall r t'. Format r (TupR s t' -> r))+ -> (forall u v. TupR s u -> TupR s v -> Maybe (u :~: v))+ -> TupR s t+ -> Int+ -> Layout s env env1+ -> Vars s env t+prjIdx context formatTp matchTp tp = go+ where+ go :: forall env'. HasCallStack => Int -> Layout s env env' -> Vars s env t+ go _ EmptyLayout = no "environment does not contain index"+ go 0 (PushLayout _ lhs vars)+ | Just Refl <- matchTp tp tp' = vars+ | otherwise = no $ bformat ("couldn't match expected type `" % formatTp % "' with actual type `" % formatTp % "'") tp tp'+ where+ tp' = lhsToTupR lhs+ go n (PushLayout l _ _) = go (n-1) l++ no :: HasCallStack => Builder -> a+ no reason = internalError (builder % "\nin the context: " % builder) reason context++-- Add an entry to a layout, incrementing all indices+--+incLayout :: env1 :> env2 -> Layout s env1 env' -> Layout s env2 env'+incLayout _ EmptyLayout = EmptyLayout+incLayout k (PushLayout lyt lhs v) = PushLayout (incLayout k lyt) lhs (weakenVars k v)++sizeLayout :: Layout s env env' -> Int+sizeLayout EmptyLayout = 0+sizeLayout (PushLayout lyt _ _) = 1 + sizeLayout lyt++-- Conversion from HOAS to de Bruijn computation AST+-- =================================================++-- Array computations+-- ------------------++-- | Convert a closed array expression to de Bruijn form while also incorporating sharing+-- information.+--+convertAcc :: HasCallStack => Acc arrs -> AST.Acc (Sugar.ArraysR arrs)+convertAcc = convertAccWith defaultOptions++convertAccWith :: HasCallStack => Config -> Acc arrs -> AST.Acc (Sugar.ArraysR arrs)+convertAccWith config (Acc acc) = convertOpenAcc config EmptyLayout acc+++-- | Convert a closed function over array computations, while incorporating+-- sharing information.+--+convertAfun :: HasCallStack => Afunction f => f -> AST.Afun (ArraysFunctionR f)+convertAfun = convertAfunWith defaultOptions++convertAfunWith :: HasCallStack => Afunction f => Config -> f -> AST.Afun (ArraysFunctionR f)+convertAfunWith config = convertOpenAfun config EmptyLayout++data AfunctionRepr f ar areprr where+ AfunctionReprBody+ :: Arrays b => AfunctionRepr (Acc b) b (Sugar.ArraysR b)++ AfunctionReprLam+ :: Arrays a+ => AfunctionRepr b br breprr+ -> AfunctionRepr (Acc a -> b) (a -> br) (Sugar.ArraysR a -> breprr)++-- Convert a HOAS fragment into de Bruijn form, binding variables into the typed+-- environment layout one binder at a time.+--+-- NOTE: Because we convert one binder at a time left-to-right, the bound+-- variables ('vars') will have de Bruijn index _zero_ as the outermost+-- binding, and thus go to the end of the list.+--+class Afunction f where+ type AfunctionR f+ type ArraysFunctionR f+ afunctionRepr :: HasCallStack => AfunctionRepr f (AfunctionR f) (ArraysFunctionR f)+ convertOpenAfun :: HasCallStack => Config -> ArrayLayout aenv aenv -> f -> AST.OpenAfun aenv (ArraysFunctionR f)++instance (Arrays a, Afunction r) => Afunction (Acc a -> r) where+ type AfunctionR (Acc a -> r) = a -> AfunctionR r+ type ArraysFunctionR (Acc a -> r) = Sugar.ArraysR a -> ArraysFunctionR r++ afunctionRepr = AfunctionReprLam $ afunctionRepr @r+ convertOpenAfun config alyt f+ | repr <- Sugar.arraysR @a+ , DeclareVars lhs k value <- declareVars repr+ = let a = Acc $ SmartAcc $ Atag repr $ sizeLayout alyt+ alyt' = PushLayout (incLayout k alyt) lhs (value weakenId)+ in+ Alam lhs $ convertOpenAfun config alyt' $ f a++instance Arrays b => Afunction (Acc b) where+ type AfunctionR (Acc b) = b+ type ArraysFunctionR (Acc b) = Sugar.ArraysR b+ afunctionRepr = AfunctionReprBody+ convertOpenAfun config alyt (Acc body) = Abody $ convertOpenAcc config alyt body++convertSmartAfun1+ :: HasCallStack+ => Config+ -> ArraysR a+ -> (SmartAcc a -> SmartAcc b)+ -> AST.Afun (a -> b)+convertSmartAfun1 config repr f+ | DeclareVars lhs _ value <- declareVars repr+ = let a = SmartAcc $ Atag repr 0+ alyt' = PushLayout EmptyLayout lhs (value weakenId)+ in+ Alam lhs $ Abody $ convertOpenAcc config alyt' $ f a++-- | Convert an open array expression to de Bruijn form while also incorporating sharing+-- information.+--+convertOpenAcc+ :: HasCallStack+ => Config+ -> ArrayLayout aenv aenv+ -> SmartAcc arrs+ -> AST.OpenAcc aenv arrs+convertOpenAcc config alyt acc =+ let lvl = sizeLayout alyt+ fvs = [lvl-1, lvl-2 .. 0]+ (sharingAcc, initialEnv) = recoverSharingAcc config lvl fvs acc+ in+ convertSharingAcc config alyt initialEnv sharingAcc+++-- | Convert an array expression with given array environment layout and sharing information into+-- de Bruijn form while recovering sharing at the same time (by introducing appropriate let+-- bindings). The latter implements the third phase of sharing recovery.+--+-- The sharing environment 'env' keeps track of all currently bound sharing variables, keeping them+-- in reverse chronological order (outermost variable is at the end of the list).+--+convertSharingAcc+ :: forall aenv arrs. HasCallStack+ => Config+ -> ArrayLayout aenv aenv+ -> [StableSharingAcc]+ -> ScopedAcc arrs+ -> AST.OpenAcc aenv arrs+convertSharingAcc _ alyt aenv (ScopedAcc lams (AvarSharing sa repr))+ | Just i <- findIndex (matchStableAcc sa) aenv'+ = avarsIn AST.OpenAcc+ $ prjIdx (bformat (builder % "; i = " % int) ctxt i) formatArraysR matchArraysR repr i alyt+ | null aenv'+ = error $ "Cyclic definition of a value of type 'Acc' (sa = " ++ show (hashStableNameHeight sa) ++ ")"+ | otherwise+ = internalError builder err+ where+ aenv' = lams ++ aenv+ ctxt = bformat ("shared 'Acc' tree with stable name " % formatStableNameHeight) sa+ err = bformat ("inconsistent valuation @ " % builder % ";\n aenv = " % list formatStableSharingAcc) ctxt aenv'++convertSharingAcc config alyt aenv (ScopedAcc lams (AletSharing sa@(StableSharingAcc (_ :: StableAccName as) boundAcc) bodyAcc))+ = case declareVars $ AST.arraysR bound of+ DeclareVars lhs k value ->+ let alyt' = PushLayout (incLayout k alyt) lhs (value weakenId)+ in AST.OpenAcc $ AST.Alet+ lhs+ bound+ (convertSharingAcc config alyt' (sa:aenv') bodyAcc)+ where+ aenv' = lams ++ aenv+ bound = convertSharingAcc config alyt aenv' (ScopedAcc [] boundAcc)++convertSharingAcc config alyt aenv (ScopedAcc lams (AccSharing _ preAcc))+ = AST.OpenAcc+ $ let aenv' = lams ++ aenv++ cvtA :: ScopedAcc a -> AST.OpenAcc aenv a+ cvtA = convertSharingAcc config alyt aenv'++ cvtE :: ScopedExp t -> AST.Exp aenv t+ cvtE = convertSharingExp config EmptyLayout alyt [] aenv'++ cvtF1 :: TypeR a -> (SmartExp a -> ScopedExp b) -> AST.Fun aenv (a -> b)+ cvtF1 = convertSharingFun1 config alyt aenv'++ cvtF2 :: TypeR a -> TypeR b -> (SmartExp a -> SmartExp b -> ScopedExp c) -> AST.Fun aenv (a -> b -> c)+ cvtF2 = convertSharingFun2 config alyt aenv'++ cvtAfun1 :: ArraysR a -> (SmartAcc a -> ScopedAcc b) -> AST.OpenAfun aenv (a -> b)+ cvtAfun1 = convertSharingAfun1 config alyt aenv'++ cvtAprj :: forall a b c. PairIdx (a, b) c -> ScopedAcc (a, b) -> AST.OpenAcc aenv c+ cvtAprj ix a = cvtAprj' ix $ cvtA a++ cvtAprj' :: forall a b c aenv1. PairIdx (a, b) c -> AST.OpenAcc aenv1 (a, b) -> AST.OpenAcc aenv1 c+ cvtAprj' PairIdxLeft (AST.OpenAcc (AST.Apair a _)) = a+ cvtAprj' PairIdxRight (AST.OpenAcc (AST.Apair _ b)) = b+ cvtAprj' ix a = case declareVars $ AST.arraysR a of+ DeclareVars lhs _ value ->+ AST.OpenAcc $ AST.Alet lhs a $ cvtAprj' ix $ avarsIn AST.OpenAcc $ value weakenId+ in+ case preAcc of++ Atag repr i+ -> let AST.OpenAcc a = avarsIn AST.OpenAcc $ prjIdx (bformat ("de Bruijn conversion tag " % int) i) formatArraysR matchArraysR repr i alyt+ in a++ Pipe reprA reprB reprC (afun1 :: SmartAcc as -> ScopedAcc bs) (afun2 :: SmartAcc bs -> ScopedAcc cs) acc+ | DeclareVars lhs k value <- declareVars reprB ->+ let+ noStableSharing = StableSharingAcc noStableAccName (undefined :: SharingAcc acc exp ())+ boundAcc = AST.Apply reprB (cvtAfun1 reprA afun1) (cvtA acc)+ alyt' = PushLayout (incLayout k alyt) lhs (value weakenId)+ bodyAcc = AST.Apply reprC+ (convertSharingAfun1 config alyt' (noStableSharing : aenv') reprB afun2)+ (avarsIn AST.OpenAcc $ value weakenId)+ in AST.Alet lhs (AST.OpenAcc boundAcc) (AST.OpenAcc bodyAcc)++ Aforeign repr ff afun acc+ -> AST.Aforeign repr ff (convertSmartAfun1 config (Smart.arraysR acc) afun) (cvtA acc)++ Acond b acc1 acc2 -> AST.Acond (cvtE b) (cvtA acc1) (cvtA acc2)+ Awhile reprA pred iter init -> AST.Awhile (cvtAfun1 reprA pred) (cvtAfun1 reprA iter) (cvtA init)+ Anil -> AST.Anil+ Apair acc1 acc2 -> AST.Apair (cvtA acc1) (cvtA acc2)+ Aprj ix a -> let AST.OpenAcc a' = cvtAprj ix a+ in a'+ Atrace msg acc1 acc2 -> AST.Atrace msg (cvtA acc1) (cvtA acc2)+ Use repr array -> AST.Use repr array+ Unit tp e -> AST.Unit tp (cvtE e)+ Generate repr@(ArrayR shr _) sh f+ -> AST.Generate repr (cvtE sh) (cvtF1 (shapeType shr) f)+ Reshape shr e acc -> AST.Reshape shr (cvtE e) (cvtA acc)+ Replicate si ix acc -> AST.Replicate si (cvtE ix) (cvtA acc)+ Slice si acc ix -> AST.Slice si (cvtA acc) (cvtE ix)+ Map t1 t2 f acc -> AST.Map t2 (cvtF1 t1 f) (cvtA acc)+ ZipWith t1 t2 t3 f acc1 acc2+ -> AST.ZipWith t3 (cvtF2 t1 t2 f) (cvtA acc1) (cvtA acc2)+ Fold tp f e acc -> AST.Fold (cvtF2 tp tp f) (cvtE <$> e) (cvtA acc)+ FoldSeg i tp f e acc1 acc2 -> AST.FoldSeg i (cvtF2 tp tp f) (cvtE <$> e) (cvtA acc1) (cvtA acc2)+ Scan d tp f e acc -> AST.Scan d (cvtF2 tp tp f) (cvtE <$> e) (cvtA acc)+ Scan' d tp f e acc -> AST.Scan' d (cvtF2 tp tp f) (cvtE e) (cvtA acc)+ Permute (ArrayR shr tp) f dftAcc perm acc+ -> AST.Permute (cvtF2 tp tp f) (cvtA dftAcc) (cvtF1 (shapeType shr) perm) (cvtA acc)+ Backpermute shr newDim perm acc+ -> AST.Backpermute shr (cvtE newDim) (cvtF1 (shapeType shr) perm) (cvtA acc)+ Stencil stencil tp f boundary acc+ -> AST.Stencil stencil+ tp+ (convertSharingStencilFun1 config alyt aenv' stencil f)+ (convertSharingBoundary config alyt aenv' (stencilShapeR stencil) boundary)+ (cvtA acc)+ Stencil2 stencil1 stencil2 tp f bndy1 acc1 bndy2 acc2+ | shr <- stencilShapeR stencil1+ -> AST.Stencil2 stencil1+ stencil2+ tp+ (convertSharingStencilFun2 config alyt aenv' stencil1 stencil2 f)+ (convertSharingBoundary config alyt aenv' shr bndy1)+ (cvtA acc1)+ (convertSharingBoundary config alyt aenv' shr bndy2)+ (cvtA acc2)+ -- Collect seq -> AST.Collect (convertSharingSeq config alyt EmptyLayout aenv' [] seq)++{--+-- Sequence expressions+-- --------------------++-- | Convert a closed sequence expression to de Bruijn form while incorporating+-- sharing information.+--+convertSeq+ :: Typeable s+ => Bool -- ^ recover sharing of array computations ?+ -> Bool -- ^ recover sharing of scalar expressions ?+ -> Bool -- ^ recover sharing of sequence computations ?+ -> Bool -- ^ always float array computations out of expressions?+ -> Seq s -- ^ computation to be converted+ -> AST.Seq s+convertSeq shareAcc shareExp shareSeq floatAcc seq+ = let config = Config shareAcc shareExp shareSeq floatAcc+ (sharingSeq, initialEnv) = recoverSharingSeq config seq+ in+ convertSharingSeq config EmptyLayout EmptyLayout [] initialEnv sharingSeq++convertSharingSeq+ :: forall aenv senv arrs.+ Config+ -> Layout aenv aenv+ -> Layout senv senv+ -> [StableSharingAcc]+ -> [StableSharingSeq]+ -> ScopedSeq arrs+ -> AST.PreOpenSeq AST.OpenAcc aenv senv arrs+convertSharingSeq _ _ slyt _ senv (ScopedSeq (SvarSharing sn))+ | Just i <- findIndex (matchStableSeq sn) senv+ = AST.Reify $ prjIdx (ctxt ++ "; i = " ++ show i) i slyt+ | null senv+ = error $ "Cyclic definition of a value of type 'Seq' (sa = " +++ show (hashStableNameHeight sn) ++ ")"+ | otherwise+ = $internalError "convertSharingSeq" err+ where+ ctxt = "shared 'Seq' tree with stable name " ++ show (hashStableNameHeight sn)+ err = "inconsistent valuation @ " ++ ctxt ++ ";\n senv = " ++ show senv+convertSharingSeq config alyt slyt aenv senv (ScopedSeq (SletSharing sa@(StableSharingSeq _ (SeqSharing _ boundSeq)) bodySeq))+ = convSeq boundSeq bodySeq+ where+ convSeq :: forall bnd body.+ PreSeq ScopedAcc ScopedSeq ScopedExp bnd+ -> ScopedSeq body+ -> AST.PreOpenSeq AST.OpenAcc aenv senv body+ convSeq bnd body =+ case bnd of+ StreamIn arrs -> producer $ AST.StreamIn arrs+ ToSeq slix acc -> producer $ mkToSeq slix (cvtA acc)+ MapSeq afun x -> producer $ AST.MapSeq (cvtAF1 afun) (asIdx x)+ ZipWithSeq afun x y -> producer $ AST.ZipWithSeq (cvtAF2 afun) (asIdx x) (asIdx y)+ ScanSeq fun e x -> producer $ AST.ScanSeq (cvtF2 fun) (cvtE e) (asIdx x)+ _ -> $internalError "convertSharingSeq:convSeq" "Consumer appears to have been let bound"+ where+ producer :: Arrays a+ => AST.Producer AST.OpenAcc aenv senv a+ -> AST.PreOpenSeq AST.OpenAcc aenv senv body+ producer p = AST.Producer p $ convertSharingSeq config alyt slyt' aenv (sa:senv) body+ where+ slyt' = incLayout slyt `PushLayout` ZeroIdx++ asIdx :: (HasCallStack, Arrays a)+ => ScopedSeq [a]+ -> Idx senv a+ asIdx (ScopedSeq (SvarSharing sn))+ | Just i <- findIndex (matchStableSeq sn) senv+ = prjIdx (ctxt ++ "; i = " ++ show i) i slyt+ | null senv+ = error $ "Cyclic definition of a value of type 'Seq' (sa = " +++ show (hashStableNameHeight sn) ++ ")"+ | otherwise+ = $internalError "convertSharingSeq" err+ where+ ctxt = "shared 'Seq' tree with stable name " ++ show (hashStableNameHeight sn)+ err = "inconsistent valuation @ " ++ ctxt ++ ";\n senv = " ++ show senv+ asIdx _+ = $internalError "convertSharingSeq:asIdx" "Sequence computation not in A-normal form"++ cvtA :: forall a. Arrays a => ScopedAcc a -> AST.OpenAcc aenv a+ cvtA acc = convertSharingAcc config alyt aenv acc++ cvtE :: forall t. Elt t => ScopedExp t -> AST.Exp aenv t+ cvtE = convertSharingExp config EmptyLayout alyt [] aenv++ cvtF2 :: (Elt a, Elt b, Elt c) => (Exp a -> Exp b -> ScopedExp c) -> AST.Fun aenv (a -> b -> c)+ cvtF2 = convertSharingFun2 config alyt aenv++ cvtAF1 :: forall a b. (Arrays a, Arrays b) => (Acc a -> ScopedAcc b) -> OpenAfun aenv (a -> b)+ cvtAF1 afun = convertSharingAfun1 config alyt aenv afun++ cvtAF2 :: forall a b c. (Arrays a, Arrays b, Arrays c) => (Acc a -> Acc b -> ScopedAcc c) -> OpenAfun aenv (a -> b -> c)+ cvtAF2 afun = convertSharingAfun2 config alyt aenv afun++convertSharingSeq _ _ _ _ _ (ScopedSeq (SletSharing _ _))+ = $internalError "convertSharingSeq" "Sequence computation not in A-normal form"++convertSharingSeq config alyt slyt aenv senv s+ = cvtC s+ where+ cvtC :: ScopedSeq a -> AST.PreOpenSeq AST.OpenAcc aenv senv a+ cvtC (ScopedSeq (SeqSharing _ s)) =+ case s of+ FoldSeq fun e x -> AST.Consumer $ AST.FoldSeq (cvtF2 fun) (cvtE e) (asIdx x)+ FoldSeqFlatten afun acc x -> AST.Consumer $ AST.FoldSeqFlatten (cvtAF3 afun) (cvtA acc) (asIdx x)+ Stuple t -> AST.Consumer $ AST.Stuple (cvtST t)+ _ -> $internalError "convertSharingSeq" "Producer has not been let bound"+ cvtC _ = $internalError "convertSharingSeq" "Unreachable"++ asIdx :: Arrays a+ => ScopedSeq [a]+ -> Idx senv a+ asIdx (ScopedSeq (SvarSharing sn))+ | Just i <- findIndex (matchStableSeq sn) senv+ = prjIdx (ctxt ++ "; i = " ++ show i) i slyt+ | null senv+ = error $ "Cyclic definition of a value of type 'Seq' (sa = " +++ show (hashStableNameHeight sn) ++ ")"+ | otherwise+ = $internalError "convertSharingSeq" err+ where+ ctxt = "shared 'Seq' tree with stable name " ++ show (hashStableNameHeight sn)+ err = "inconsistent valuation @ " ++ ctxt ++ ";\n senv = " ++ show senv+ asIdx _+ = $internalError "convertSharingSeq:asIdx" "Sequence computation not in A-normal form"++ cvtA :: forall a. Arrays a => ScopedAcc a -> AST.OpenAcc aenv a+ cvtA acc = convertSharingAcc config alyt aenv acc++ cvtE :: forall t. Elt t => ScopedExp t -> AST.Exp aenv t+ cvtE = convertSharingExp config EmptyLayout alyt [] aenv++ cvtF2 :: (Elt a, Elt b, Elt c) => (Exp a -> Exp b -> ScopedExp c) -> AST.Fun aenv (a -> b -> c)+ cvtF2 = convertSharingFun2 config alyt aenv++ cvtAF3 :: forall a b c d. (Arrays a, Arrays b, Arrays c, Arrays d) => (Acc a -> Acc b -> Acc c -> ScopedAcc d) -> OpenAfun aenv (a -> b -> c -> d)+ cvtAF3 afun = convertSharingAfun3 config alyt aenv afun++ cvtST :: Atuple ScopedSeq t -> Atuple (AST.Consumer AST.OpenAcc aenv senv) t+ cvtST NilAtup = NilAtup+ cvtST (SnocAtup t c) | AST.Consumer c' <- cvtC c+ = SnocAtup (cvtST t) c'+ | otherwise+ = $internalError "convertSharingSeq" "Unreachable"+--}++convertSharingAfun1+ :: forall aenv a b. HasCallStack+ => Config+ -> ArrayLayout aenv aenv+ -> [StableSharingAcc]+ -> ArraysR a+ -> (SmartAcc a -> ScopedAcc b)+ -> OpenAfun aenv (a -> b)+convertSharingAfun1 config alyt aenv reprA f+ | DeclareVars lhs k value <- declareVars reprA+ = let+ alyt' = PushLayout (incLayout k alyt) lhs (value weakenId)+ body = f undefined+ in+ Alam lhs (Abody (convertSharingAcc config alyt' aenv body))++-- | Convert a boundary condition+--+convertSharingBoundary+ :: forall aenv sh e. HasCallStack+ => Config+ -> ArrayLayout aenv aenv+ -> [StableSharingAcc]+ -> ShapeR sh+ -> PreBoundary ScopedAcc ScopedExp (Array sh e)+ -> AST.Boundary aenv (Array sh e)+convertSharingBoundary config alyt aenv shr = cvt+ where+ cvt :: PreBoundary ScopedAcc ScopedExp (Array sh e) -> AST.Boundary aenv (Array sh e)+ cvt bndy =+ case bndy of+ Clamp -> AST.Clamp+ Mirror -> AST.Mirror+ Wrap -> AST.Wrap+ Constant v -> AST.Constant v+ Function f -> AST.Function $ convertSharingFun1 config alyt aenv (shapeType shr) f+++-- mkToSeq :: forall slsix slix e aenv senv. (Division slsix, DivisionSlice slsix ~ slix, Elt e, Elt slix, Slice slix)+-- => slsix+-- -> AST.OpenAcc aenv (Array (FullShape slix) e)+-- -> AST.Producer AST.OpenAcc aenv senv (Array (SliceShape slix) e)+-- mkToSeq _ = AST.ToSeq (sliceIndex slix) (Proxy :: Proxy slix)+-- where+-- slix = undefined :: slix+++-- Scalar functions+-- ----------------++-- | Convert a closed scalar function to de Bruijn form while incorporating+-- sharing information.+--+-- The current design requires all free variables to be bound at the outermost+-- level --- we have no general apply term, and so lambdas are always outermost.+-- In higher-order abstract syntax, this represents an n-ary, polyvariadic+-- function.+--+convertFun :: (HasCallStack, Function f) => f -> AST.Fun () (EltFunctionR f)+convertFun+ = convertFunWith+ $ defaultOptions { options = options defaultOptions \\ [seq_sharing, acc_sharing] }++convertFunWith :: (HasCallStack, Function f) => Config -> f -> AST.Fun () (EltFunctionR f)+convertFunWith config = convertOpenFun config EmptyLayout++data FunctionRepr f r reprr where+ FunctionReprBody+ :: Elt b => FunctionRepr (Exp b) b (EltR b)++ FunctionReprLam+ :: Elt a+ => FunctionRepr b br breprr+ -> FunctionRepr (Exp a -> b) (a -> br) (EltR a -> breprr)++class Function f where+ type FunctionR f+ type EltFunctionR f++ functionRepr :: HasCallStack => FunctionRepr f (FunctionR f) (EltFunctionR f)+ convertOpenFun :: HasCallStack => Config -> ELayout env env -> f -> AST.OpenFun env () (EltFunctionR f)++instance (Elt a, Function r) => Function (Exp a -> r) where+ type FunctionR (Exp a -> r) = a -> FunctionR r+ type EltFunctionR (Exp a -> r) = EltR a -> EltFunctionR r++ functionRepr = FunctionReprLam $ functionRepr @r+ convertOpenFun config lyt f+ | tp <- eltR @a+ , DeclareVars lhs k value <- declareVars tp+ = let+ e = Exp $ SmartExp $ Tag tp $ sizeLayout lyt+ lyt' = PushLayout (incLayout k lyt) lhs (value weakenId)+ in+ Lam lhs $ convertOpenFun config lyt' $ f e++instance Elt b => Function (Exp b) where+ type FunctionR (Exp b) = b+ type EltFunctionR (Exp b) = EltR b++ functionRepr = FunctionReprBody+ convertOpenFun config lyt (Exp body) = Body $ convertOpenExp config lyt body++convertSmartFun+ :: HasCallStack+ => Config+ -> TypeR a+ -> (SmartExp a -> SmartExp b)+ -> AST.Fun () (a -> b)+convertSmartFun config tp f+ | DeclareVars lhs _ value <- declareVars tp+ = let+ e = SmartExp $ Tag tp 0+ lyt' = PushLayout EmptyLayout lhs (value weakenId)+ in+ Lam lhs $ Body $ convertOpenExp config lyt' $ f e++-- Scalar expressions+-- ------------------++-- | Convert a closed scalar expression to de Bruijn form while incorporating+-- sharing information.+--+convertExp+ :: HasCallStack+ => Exp e+ -> AST.Exp () (EltR e)+convertExp+ = convertExpWith+ $ defaultOptions { options = options defaultOptions \\ [seq_sharing, acc_sharing] }++convertExpWith+ :: HasCallStack+ => Config+ -> Exp e+ -> AST.Exp () (EltR e)+convertExpWith config (Exp e) = convertOpenExp config EmptyLayout e++convertOpenExp+ :: HasCallStack+ => Config+ -> ELayout env env+ -> SmartExp e+ -> AST.OpenExp env () e+convertOpenExp config lyt exp =+ let lvl = sizeLayout lyt+ fvs = [lvl-1, lvl-2 .. 0]+ (sharingExp, initialEnv) = recoverSharingExp config lvl fvs exp+ in+ convertSharingExp config lyt EmptyLayout initialEnv [] sharingExp+++-- | Convert an open expression with given environment layouts and sharing information into+-- de Bruijn form while recovering sharing at the same time (by introducing appropriate let+-- bindings). The latter implements the third phase of sharing recovery.+--+-- The sharing environments 'env' and 'aenv' keep track of all currently bound sharing variables,+-- keeping them in reverse chronological order (outermost variable is at the end of the list).+--+convertSharingExp+ :: forall t env aenv. HasCallStack+ => Config+ -> ELayout env env -- scalar environment+ -> ArrayLayout aenv aenv -- array environment+ -> [StableSharingExp] -- currently bound sharing variables of expressions+ -> [StableSharingAcc] -- currently bound sharing variables of array computations+ -> ScopedExp t -- expression to be converted+ -> AST.OpenExp env aenv t+convertSharingExp config lyt alyt env aenv exp@(ScopedExp lams _) = cvt exp+ where+ -- scalar environment with any lambda bound variables this expression is rooted in+ env' = lams ++ env++ cvt :: HasCallStack => ScopedExp t' -> AST.OpenExp env aenv t'+ cvt (ScopedExp _ (VarSharing se tp))+ | Just i <- findIndex (matchStableExp se) env' = expVars (prjIdx (ctx i) formatTypeR matchTypeR tp i lyt)+ | otherwise = internalError (unlined @[] builder) msg+ where+ ctx i = bformat ("shared 'Exp' tree with stable name " % formatStableNameHeight % "; i=" % int) se i+ msg =+ [ if null env'+ then bformat ("cyclic definition of a value of type 'Exp' (sa=" % formatStableNameHeight % ")") se+ else bformat ("inconsistent valuation at shared 'Exp' tree (sa=" % formatStableNameHeight % "; env=" % list formatStableSharingExp % ")") se env'+ , ""+ , "Note that this error usually arises due to the presence of nested data"+ , "parallelism; when a parallel computation attempts to initiate new parallel"+ , "work _which depends on_ a scalar variable given by the first computation."+ , ""+ , "For example, suppose we wish to sum the columns of a two-dimensional array."+ , "You might think to do this in the following (incorrect) way: by constructing"+ , "a vector using 'generate' where at each index we 'slice' out the"+ , "corresponding column of the matrix and 'sum' it:"+ , ""+ , "> sum_columns_ndp :: Num a => Acc (Matrix a) -> Acc (Vector a)"+ , "> sum_columns_ndp mat ="+ , "> let I2 rows cols = shape mat"+ , "> in generate (I1 cols)"+ , "> (\\(I1 col) -> the $ sum (slice mat (lift (Z :. All :. col))))"+ , ""+ , "However, since both 'generate' and 'slice' are data-parallel operators, and"+ , "moreover that 'slice' _depends on_ the argument 'col' given to it by the"+ , "'generate' function, this operation requires nested parallelism and is thus"+ , "not (at this time) permitted. The clue that this definition is invalid is"+ , "that in order to create a program which will be accepted by the type checker,"+ , "we had to use the function 'the' to retrieve the result of the parallel"+ , "'sum', effectively concealing that this is a collective operation in order to"+ , "match the type expected by 'generate'."+ , ""+ , "To solve this particular example, we can make use of the fact that (most)"+ , "collective operations in Accelerate are _rank polymorphic_. The 'sum'"+ , "operation reduces along the innermost dimension of an array of arbitrary"+ , "rank, reducing the dimensionality of the array by one. To reduce the array"+ , "column-wise then, we first need to simply 'transpose' the array:"+ , ""+ , "> sum_columns :: Num a => Acc (Matrix a) -> Acc (Vector a)"+ , "> sum_columns = sum . transpose"+ , ""+ , "If you feel like this is not the cause of your error, or you would like some"+ , "advice locating the problem and perhaps with a workaround, feel free to"+ , "submit an issue at the above URL."+ ]++ cvt (ScopedExp _ (LetSharing se@(StableSharingExp _ boundExp) bodyExp))+ | DeclareVars lhs k value <- declareVars $ typeR boundExp+ = let+ lyt' = PushLayout (incLayout k lyt) lhs (value weakenId)+ in+ AST.Let lhs (cvt (ScopedExp [] boundExp)) (convertSharingExp config lyt' alyt (se:env') aenv bodyExp)+ cvt (ScopedExp _ (ExpSharing _ pexp))+ = case pexp of+ Tag tp i -> expVars $ prjIdx ("de Bruijn conversion tag " <> F.build i) formatTypeR matchTypeR tp i lyt+ Match _ e -> cvt e -- XXX: this should probably be an error+ Const tp v -> AST.Const tp v+ Undef tp -> AST.Undef tp+ Prj idx e -> cvtPrj idx (cvt e)+ Nil -> AST.Nil+ Pair e1 e2 -> AST.Pair (cvt e1) (cvt e2)+ VecPack vec e -> AST.VecPack vec (cvt e)+ VecUnpack vec e -> AST.VecUnpack vec (cvt e)+ ToIndex shr sh ix -> AST.ToIndex shr (cvt sh) (cvt ix)+ FromIndex shr sh e -> AST.FromIndex shr (cvt sh) (cvt e)+ Case e rhs -> cvtCase (cvt e) (over (mapped . _2) cvt rhs)+ Cond e1 e2 e3 -> AST.Cond (cvt e1) (cvt e2) (cvt e3)+ While tp p it i -> AST.While (cvtFun1 tp p) (cvtFun1 tp it) (cvt i)+ PrimConst c -> AST.PrimConst c+ PrimApp f e -> cvtPrimFun f (cvt e)+ Index _ a e -> AST.Index (cvtAvar a) (cvt e)+ LinearIndex _ a i -> AST.LinearIndex (cvtAvar a) (cvt i)+ Shape _ a -> AST.Shape (cvtAvar a)+ ShapeSize shr e -> AST.ShapeSize shr (cvt e)+ Foreign repr ff f e -> AST.Foreign repr ff (convertSmartFun config (typeR e) f) (cvt e)+ Coerce t1 t2 e -> AST.Coerce t1 t2 (cvt e)++ cvtPrj :: forall a b c env1 aenv1. PairIdx (a, b) c -> AST.OpenExp env1 aenv1 (a, b) -> AST.OpenExp env1 aenv1 c+ cvtPrj PairIdxLeft (AST.Pair a _) = a+ cvtPrj PairIdxRight (AST.Pair _ b) = b+ cvtPrj ix a+ | DeclareVars lhs _ value <- declareVars $ AST.expType a+ = AST.Let lhs a (cvtPrj ix (expVars (value weakenId)))++ cvtA :: HasCallStack => ScopedAcc a -> AST.OpenAcc aenv a+ cvtA = convertSharingAcc config alyt aenv++ cvtAvar :: HasCallStack => ScopedAcc a -> AST.ArrayVar aenv a+ cvtAvar a = case cvtA a of+ AST.OpenAcc (AST.Avar var) -> var+ _ -> internalError "Expected array computation in expression to be floated out"++ cvtFun1 :: HasCallStack => TypeR a -> (SmartExp a -> ScopedExp b) -> AST.OpenFun env aenv (a -> b)+ cvtFun1 tp f+ | DeclareVars lhs k value <- declareVars tp+ = let+ lyt' = PushLayout (incLayout k lyt) lhs (value weakenId)+ body = f undefined+ in+ Lam lhs $ Body $ convertSharingExp config lyt' alyt env' aenv body++ -- Push primitive function applications down through let bindings so that+ -- they are adjacent to their arguments. It looks a bit nicer this way.+ --+ cvtPrimFun :: HasCallStack => AST.PrimFun (a -> r) -> AST.OpenExp env' aenv' a -> AST.OpenExp env' aenv' r+ cvtPrimFun f e = case e of+ AST.Let lhs bnd body -> AST.Let lhs bnd (cvtPrimFun f body)+ x -> AST.PrimApp f x++ -- Convert the flat list of equations into nested case statement+ -- directly on the tag variables.+ --+ cvtCase :: HasCallStack => AST.OpenExp env' aenv' a -> [(TagR a, AST.OpenExp env' aenv' b)] -> AST.OpenExp env' aenv' b+ cvtCase s es+ | AST.Pair{} <- s+ = nested s es+ | DeclareVars lhs _ value <- declareVars (AST.expType s)+ = AST.Let lhs s $ nested (expVars (value weakenId)) (over (mapped . _2) (weakenE (weakenWithLHS lhs)) es)+ where+ nested :: HasCallStack => AST.OpenExp env' aenv' a -> [(TagR a, AST.OpenExp env' aenv' b)] -> AST.OpenExp env' aenv' b+ nested _ [(_,r)] = r+ nested s rs =+ let groups = NE.groupBy (eqT `on` fst) rs+ tags = map (firstT . fst . NE.head) groups+ e = prjT (fst (head rs)) s+ rhs = map (nested s . map (over _1 ignore) . NE.toList) groups+ in+ AST.Case e (zip tags rhs) Nothing++ -- Extract the variable representing this particular tag from the+ -- scrutinee. This is safe because we let-bind the argument first.+ prjT :: TagR a -> AST.OpenExp env' aenv' a -> AST.OpenExp env' aenv' TAG+ prjT = fromJust $$ go+ where+ go :: TagR a -> AST.OpenExp env' aenv' a -> Maybe (AST.OpenExp env' aenv' TAG)+ go TagRtag{} (AST.Pair l _) = Just l+ go (TagRpair ta tb) (AST.Pair l r) =+ case go ta l of+ Just t -> Just t+ Nothing -> go tb r+ go _ _ = Nothing++ -- Equality up to the first constructor tag encountered+ eqT :: TagR a -> TagR a -> Bool+ eqT a b = snd $ go a b+ where+ go :: TagR a -> TagR a -> (Any, Bool)+ go TagRunit TagRunit = no True+ go TagRsingle{} TagRsingle{} = no True+ go TagRundef{} TagRundef{} = no True+ go (TagRtag v1 _) (TagRtag v2 _) = yes (v1 == v2)+ go (TagRpair a1 b1) (TagRpair a2 b2) =+ let (Any r, s) = go a1 a2+ in case r of+ True -> yes s+ False -> go b1 b2+ go _ _ = no False++ firstT :: TagR a -> TAG+ firstT = fromJust . go+ where+ go :: TagR a -> Maybe TAG+ go (TagRtag v _) = Just v+ go (TagRpair a b) =+ case go a of+ Just t -> Just t+ Nothing -> go b+ go _ = Nothing++ -- Replace the first constructor tag encountered with a regular+ -- scalar tag, so that that tag will be ignored in the recursive+ -- case.+ ignore = snd . go+ where+ go :: TagR a -> (Any, TagR a)+ go TagRunit = no $ TagRunit+ go (TagRsingle t) = no $ TagRsingle t+ go (TagRundef t) = no $ TagRundef t+ go (TagRtag _ a) = yes $ TagRpair (TagRundef scalarType) a+ go (TagRpair a1 a2) =+ let (Any r, a1') = go a1+ in case r of+ True -> yes $ TagRpair a1' a2+ False -> TagRpair a1' <$> go a2++ yes :: x -> (Any, x)+ yes e = (Any True, e)++ no :: x -> (Any, x)+ no = pure+++-- | Convert a unary functions+--+convertSharingFun1+ :: HasCallStack+ => Config+ -> ArrayLayout aenv aenv+ -> [StableSharingAcc] -- currently bound array sharing-variables+ -> TypeR a+ -> (SmartExp a -> ScopedExp b)+ -> AST.Fun aenv (a -> b)+convertSharingFun1 config alyt aenv tp f+ | DeclareVars lhs _ value <- declareVars tp+ = let+ a = SmartExp undefined -- the 'tag' was already embedded in Phase 1+ lyt = PushLayout EmptyLayout lhs (value weakenId)+ openF = convertSharingExp config lyt alyt [] aenv (f a)+ in+ Lam lhs (Body openF)++-- | Convert a binary functions+--+convertSharingFun2+ :: HasCallStack+ => Config+ -> ArrayLayout aenv aenv+ -> [StableSharingAcc] -- currently bound array sharing-variables+ -> TypeR a+ -> TypeR b+ -> (SmartExp a -> SmartExp b -> ScopedExp c)+ -> AST.Fun aenv (a -> b -> c)+convertSharingFun2 config alyt aenv ta tb f+ | DeclareVars lhs1 _ value1 <- declareVars ta+ , DeclareVars lhs2 k2 value2 <- declareVars tb+ = let+ a = SmartExp undefined+ b = SmartExp undefined+ lyt1 = PushLayout EmptyLayout lhs1 (value1 k2)+ lyt2 = PushLayout lyt1 lhs2 (value2 weakenId)+ openF = convertSharingExp config lyt2 alyt [] aenv (f a b)+ in+ Lam lhs1 $ Lam lhs2 $ Body openF++-- | Convert a unary stencil function+--+convertSharingStencilFun1+ :: HasCallStack+ => Config+ -> ArrayLayout aenv aenv+ -> [StableSharingAcc] -- currently bound array sharing-variables+ -> R.StencilR sh a stencil+ -> (SmartExp stencil -> ScopedExp b)+ -> AST.Fun aenv (stencil -> b)+convertSharingStencilFun1 config alyt aenv sR1 stencil =+ convertSharingFun1 config alyt aenv (R.stencilR sR1) stencil++-- | Convert a binary stencil function+--+convertSharingStencilFun2+ :: HasCallStack+ => Config+ -> ArrayLayout aenv aenv+ -> [StableSharingAcc] -- currently bound array sharing-variables+ -> R.StencilR sh a stencil1+ -> R.StencilR sh b stencil2+ -> (SmartExp stencil1 -> SmartExp stencil2 -> ScopedExp c)+ -> AST.Fun aenv (stencil1 -> stencil2 -> c)+convertSharingStencilFun2 config alyt aenv sR1 sR2 stencil =+ convertSharingFun2 config alyt aenv (R.stencilR sR1) (R.stencilR sR2) stencil+++-- Sharing recovery+-- ================++-- Sharing recovery proceeds in two phases:+--+-- /Phase One: build the occurrence map/+--+-- This is a top-down traversal of the AST that computes a map from AST nodes to the number of+-- occurrences of that AST node in the overall Accelerate program. An occurrences count of two or+-- more indicates sharing.+--+-- IMPORTANT: To avoid unfolding the sharing, we do not descent into subtrees that we have+-- previously encountered. Hence, the complexity is proportional to the number of nodes in the+-- tree /with/ sharing. Consequently, the occurrence count is that in the tree with sharing+-- as well.+--+-- During computation of the occurrences, the tree is annotated with stable names on every node+-- using 'AccSharing' constructors and all but the first occurrence of shared subtrees are pruned+-- using 'AvarSharing' constructors (see 'SharingAcc' below). This phase is impure as it is based+-- on stable names.+--+-- We use a hash table (instead of 'Data.Map') as computing stable names forces us to live in IO+-- anyway. Once, the computation of occurrence counts is complete, we freeze the hash table into+-- a 'Data.Map'.+--+-- (Implemented by 'makeOccMap*'.)+--+-- /Phase Two: determine scopes and inject sharing information/+--+-- This is a bottom-up traversal that determines the scope for every binding to be introduced+-- to share a subterm. It uses the occurrence map to determine, for every shared subtree, the+-- lowest AST node at which the binding for that shared subtree can be placed (using a+-- 'AletSharing' constructor)— it's the meet of all the shared subtree occurrences.+--+-- The second phase is also replacing the first occurrence of each shared subtree with a+-- 'AvarSharing' node and floats the shared subtree up to its binding point.+--+-- (Implemented by 'determineScopes*'.)+--+-- /Sharing recovery for expressions/+--+-- We recover sharing for each expression (including function bodies) independently of any other+-- expression — i.e., we cannot share scalar expressions across array computations. Hence, during+-- Phase One, we mark all scalar expression nodes with a stable name and compute one occurrence map+-- for every scalar expression (including functions) that occurs in an array computation. These+-- occurrence maps are added to the root of scalar expressions using 'RootExp'.+--+-- NB: We do not need to worry sharing recovery will try to float a shared subexpression past a+-- binder that occurs in that subexpression. Why? Otherwise, the binder would already occur+-- out of scope in the original source program.+--+-- /Lambda bound variables/+--+-- During sharing recovery, lambda bound variables appear in the form of 'Atag' and 'Tag' data+-- constructors. The tag values are determined during Phase One of sharing recovery by computing+-- the /level/ of each variable at its binding occurrence. The level at the root of the AST is 0+-- and increases by one with each lambda on each path through the AST.++-- Stable names+-- ------------++-- Opaque stable name for AST nodes — used to key the occurrence map.+--+data StableASTName c where+ StableASTName :: StableName (c t) -> StableASTName c++instance Show (StableASTName c) where+ show (StableASTName sn) = show (hashStableName sn)++instance Eq (StableASTName c) where+ StableASTName sn1 == StableASTName sn2 = eqStableName sn1 sn2++instance Hashable (StableASTName c) where+ hashWithSalt s (StableASTName sn) = hashWithSalt s sn++makeStableAST :: c t -> IO (StableName (c t))+makeStableAST e = e `seq` makeStableName e++formatStableName :: Format r (StableName a -> r)+formatStableName = later $ bformat int . hashStableName++-- Stable name for an AST node including the height of the AST representing the array computation.+--+data StableNameHeight t = StableNameHeight (StableName t) Int++instance Eq (StableNameHeight t) where+ (StableNameHeight sn1 _) == (StableNameHeight sn2 _) = eqStableName sn1 sn2++higherSNH :: StableNameHeight t1 -> StableNameHeight t2 -> Bool+StableNameHeight _ h1 `higherSNH` StableNameHeight _ h2 = h1 > h2++hashStableNameHeight :: StableNameHeight t -> Int+hashStableNameHeight (StableNameHeight sn _) = hashStableName sn++formatStableNameHeight :: Format r (StableNameHeight t -> r)+formatStableNameHeight = later $ \case+ StableNameHeight sn _ -> bformat formatStableName sn++-- Mutable occurrence map+-- ----------------------++-- Hash table keyed on the stable names of array computations.+--+type HashTable key val = Hash.BasicHashTable key val+type ASTHashTable c v = HashTable (StableASTName c) v++-- Mutable hashtable version of the occurrence map, which associates each AST node with an+-- occurrence count and the height of the AST.+--+type OccMapHash c = ASTHashTable c (Int, Int)++-- Create a new hash table keyed on AST nodes.+--+newASTHashTable :: IO (ASTHashTable c v)+newASTHashTable = Hash.new++-- Enter one AST node occurrence into an occurrence map. Returns 'Just h' if this is a repeated+-- occurrence and the height of the repeatedly occurring AST is 'h'.+--+-- If this is the first occurrence, the 'height' *argument* must provide the height of the AST;+-- otherwise, the height will be *extracted* from the occurrence map. In the latter case, this+-- function yields the AST height.+--+enterOcc :: OccMapHash c -> StableASTName c -> Int -> IO (Maybe Int)+enterOcc occMap sa height+ = Hash.mutate occMap sa+ $ \case+ Nothing -> (Just (1, height), Nothing)+ Just (n, heightS) -> (Just (n+1, heightS), Just heightS)+++-- Immutable occurrence map+-- ------------------------++-- Immutable version of the occurrence map (storing the occurrence count only, not the height). We+-- use the 'StableName' hash to index an 'IntMap' and disambiguate 'StableName's with identical+-- hashes explicitly, storing them in a list in the 'IntMap'.+--+type OccMap c = IntMap.IntMap [(StableASTName c, Int)]++-- Turn a mutable into an immutable occurrence map.+--+freezeOccMap :: OccMapHash c -> IO (OccMap c)+freezeOccMap oc+ = do+ ocl <- Hash.toList oc+ traceChunk "OccMap" (fromString (show ocl))++ return . IntMap.fromList+ . map (\kvs -> (key (NE.head kvs), NE.toList kvs))+ . NE.groupBy sameKey+ . map dropHeight+ $ ocl+ where+ key (StableASTName sn, _) = hashStableName sn+ sameKey kv1 kv2 = key kv1 == key kv2+ dropHeight (k, (cnt, _)) = (k, cnt)++-- Look up the occurrence map keyed by array computations using a stable name. If the key does+-- not exist in the map, return an occurrence count of '1'.+--+lookupWithASTName :: OccMap c -> StableASTName c -> Int+lookupWithASTName oc sa@(StableASTName sn)+ = fromMaybe 1 $ IntMap.lookup (hashStableName sn) oc >>= Prelude.lookup sa++-- Look up the occurrence map keyed by array computations using a sharing array computation. If an+-- the key does not exist in the map, return an occurrence count of '1'.+--+lookupWithSharingAcc :: OccMap SmartAcc -> StableSharingAcc -> Int+lookupWithSharingAcc oc (StableSharingAcc (StableNameHeight sn _) _)+ = lookupWithASTName oc (StableASTName sn)++-- Look up the occurrence map keyed by scalar expressions using a sharing expression. If an+-- the key does not exist in the map, return an occurrence count of '1'.+--+lookupWithSharingExp :: OccMap SmartExp -> StableSharingExp -> Int+lookupWithSharingExp oc (StableSharingExp (StableNameHeight sn _) _)+ = lookupWithASTName oc (StableASTName sn)+++-- Stable 'SmartAcc' nodes+-- ------------------++-- Stable name for 'SmartAcc' nodes including the height of the AST.+--+type StableAccName t = StableNameHeight (SmartAcc t)++-- Interleave sharing annotations into an array computation AST. Subtrees can be marked as being+-- represented by variable (binding a shared subtree) using 'AvarSharing' and as being prefixed by+-- a let binding (for a shared subtree) using 'AletSharing'.+--+data SharingAcc acc exp arrs where+ AvarSharing :: StableAccName arrs -> ArraysR arrs -> SharingAcc acc exp arrs+ AletSharing :: StableSharingAcc -> acc arrs -> SharingAcc acc exp arrs+ AccSharing :: StableAccName arrs -> PreSmartAcc acc exp arrs -> SharingAcc acc exp arrs++instance HasArraysR acc => HasArraysR (SharingAcc acc exp) where+ arraysR (AvarSharing _ repr) = repr+ arraysR (AletSharing _ acc) = Smart.arraysR acc+ arraysR (AccSharing _ acc) = Smart.arraysR acc+++-- Array expression with sharing but shared values have not been scoped; i.e. no let bindings. If+-- the expression is rooted in a function, the list contains the tags of the variables bound by the+-- immediate surrounding lambdas.+data UnscopedAcc t = UnscopedAcc [Int] (SharingAcc UnscopedAcc RootExp t)++instance HasArraysR UnscopedAcc where+ arraysR (UnscopedAcc _ acc) = Smart.arraysR acc+++-- Array expression with sharing. For expressions rooted in functions the list holds a sorted+-- environment corresponding to the variables bound in the immediate surounding lambdas.+data ScopedAcc t = ScopedAcc [StableSharingAcc] (SharingAcc ScopedAcc ScopedExp t)++instance HasArraysR ScopedAcc where+ arraysR (ScopedAcc _ acc) = Smart.arraysR acc+++-- Stable name for an array computation associated with its sharing-annotated version.+--+data StableSharingAcc where+ StableSharingAcc :: StableAccName arrs+ -> SharingAcc ScopedAcc ScopedExp arrs+ -> StableSharingAcc++instance Show StableSharingAcc where+ show (StableSharingAcc sn _) = show (hashStableNameHeight sn)++instance Eq StableSharingAcc where+ StableSharingAcc (StableNameHeight sn1 _) _ == StableSharingAcc (StableNameHeight sn2 _) _+ = eqStableName sn1 sn2++formatStableSharingAcc :: Format r (StableSharingAcc -> r)+formatStableSharingAcc = later $ \case+ StableSharingAcc sn _ -> bformat formatStableNameHeight sn++higherSSA :: StableSharingAcc -> StableSharingAcc -> Bool+StableSharingAcc sn1 _ `higherSSA` StableSharingAcc sn2 _ = sn1 `higherSNH` sn2++-- Test whether the given stable names matches an array computation with sharing.+--+matchStableAcc :: StableAccName arrs -> StableSharingAcc -> Bool+matchStableAcc (StableNameHeight sn1 _) (StableSharingAcc (StableNameHeight sn2 _) _)+ = eqStableName sn1 sn2++-- Dummy entry for environments to be used for unused variables.+--+{-# NOINLINE noStableAccName #-}+noStableAccName :: StableAccName arrs+noStableAccName = unsafePerformIO $ StableNameHeight <$> makeStableName undefined <*> pure 0++-- Stable 'Exp' nodes+-- ------------------++-- Stable name for 'Exp' nodes including the height of the AST.+--+type StableExpName t = StableNameHeight (SmartExp t)++-- Interleave sharing annotations into a scalar expressions AST in the same manner as 'SharingAcc'+-- do for array computations.+--+data SharingExp acc exp t where+ VarSharing :: StableExpName t -> TypeR t -> SharingExp acc exp t+ LetSharing :: StableSharingExp -> exp t -> SharingExp acc exp t+ ExpSharing :: StableExpName t -> PreSmartExp acc exp t -> SharingExp acc exp t++instance HasTypeR exp => HasTypeR (SharingExp acc exp) where+ typeR (VarSharing _ tp) = tp+ typeR (LetSharing _ exp) = Smart.typeR exp+ typeR (ExpSharing _ exp) = Smart.typeR exp++-- Specifies a scalar expression AST with sharing annotations but no scoping; i.e. no LetSharing+-- constructors. If the expression is rooted in a function, the list contains the tags of the+-- variables bound by the immediate surrounding lambdas.+data UnscopedExp t = UnscopedExp [Int] (SharingExp UnscopedAcc UnscopedExp t)++instance HasTypeR UnscopedExp where+ typeR (UnscopedExp _ exp) = Smart.typeR exp++-- Specifies a scalar expression AST with sharing. For expressions rooted in functions the list+-- holds a sorted environment corresponding to the variables bound in the immediate surounding+-- lambdas.+data ScopedExp t = ScopedExp [StableSharingExp] (SharingExp ScopedAcc ScopedExp t)++instance HasTypeR ScopedExp where+ typeR (ScopedExp _ exp) = Smart.typeR exp++-- Expressions rooted in 'SmartAcc' computations.+--+-- * When counting occurrences, the root of every expression embedded in an 'SmartAcc' is annotated by+-- an occurrence map for that one expression (excluding any subterms that are rooted in embedded+-- 'SmartAcc's.)+--+data RootExp t = RootExp (OccMap SmartExp) (UnscopedExp t)++-- Stable name for an expression associated with its sharing-annotated version.+--+data StableSharingExp where+ StableSharingExp :: StableExpName t -> SharingExp ScopedAcc ScopedExp t -> StableSharingExp++instance Show StableSharingExp where+ show (StableSharingExp sn _) = show (hashStableNameHeight sn)++instance Eq StableSharingExp where+ StableSharingExp (StableNameHeight sn1 _) _ == StableSharingExp (StableNameHeight sn2 _) _ =+ eqStableName sn1 sn2++formatStableSharingExp :: Format r (StableSharingExp -> r)+formatStableSharingExp = later $ \case+ StableSharingExp sn _ -> bformat formatStableNameHeight sn++higherSSE :: StableSharingExp -> StableSharingExp -> Bool+StableSharingExp sn1 _ `higherSSE` StableSharingExp sn2 _ = sn1 `higherSNH` sn2++-- Test whether the given stable names matches an expression with sharing.+--+matchStableExp :: StableExpName t -> StableSharingExp -> Bool+matchStableExp (StableNameHeight sn1 _) (StableSharingExp (StableNameHeight sn2 _) _) = eqStableName sn1 sn2++-- Dummy entry for environments to be used for unused variables.+--+{-# NOINLINE noStableExpName #-}+noStableExpName :: StableExpName t+noStableExpName = unsafePerformIO $ StableNameHeight <$> makeStableName undefined <*> pure 0+++{--+-- Stable 'Seq' nodes+-- ------------------++-- Stable name for 'Seq' nodes including the height of the AST.+--+type StableSeqName arrs = StableNameHeight (Seq arrs)++-- Interleave sharing annotations into an sequence computation AST in the same manner as SharingAcc+-- and SharingExp+--+data SharingSeq acc seq exp arrs where+ SvarSharing :: (Typeable arrs, Arrays arrs)+ => StableSeqName [arrs] -> SharingSeq acc seq exp [arrs]+ SletSharing :: StableSharingSeq -> seq t -> SharingSeq acc seq exp t+ SeqSharing :: Typeable arrs+ => StableSeqName arrs -> PreSeq acc seq exp arrs -> SharingSeq acc seq exp arrs++-- Array expression with sharing but shared values have not been scoped; i.e. no let bindings. If+-- the expression is rooted in a function, the list contains the tags of the variables bound by the+-- immediate surrounding lambdas.+data UnscopedSeq t = UnscopedSeq (SharingSeq UnscopedAcc UnscopedSeq RootExp t)++-- Array expression with sharing. For expressions rooted in functions the list holds a sorted+-- environment corresponding to the variables bound in the immediate surounding lambdas.+data ScopedSeq t = ScopedSeq (SharingSeq ScopedAcc ScopedSeq ScopedExp t)++-- Sequences rooted in 'Acc' computations.+--+-- * When counting occurrences, the root of every sequence embedded in an 'Acc' is annotated by+-- an occurrence map for that one expression (excluding any subterms that are rooted in embedded+-- 'Acc's.)+--+data RootSeq t = RootSeq (OccMap Seq) (UnscopedSeq t)++-- Stable name for an array computation associated with its sharing-annotated version.+--+data StableSharingSeq where+ StableSharingSeq :: Typeable arrs+ => StableSeqName arrs+ -> SharingSeq ScopedAcc ScopedSeq ScopedExp arrs+ -> StableSharingSeq++instance Show StableSharingSeq where+ show (StableSharingSeq sn _) = show $ hashStableNameHeight sn++instance Eq StableSharingSeq where+ StableSharingSeq sn1 _ == StableSharingSeq sn2 _+ | Just sn1' <- gcast sn1 = sn1' == sn2+ | otherwise = False++higherSSS :: StableSharingSeq -> StableSharingSeq -> Bool+StableSharingSeq sn1 _ `higherSSS` StableSharingSeq sn2 _ = sn1 `higherSNH` sn2++-- Test whether the given stable names matches an array computation with sharing.+--+matchStableSeq :: Typeable arrs => StableSeqName arrs -> StableSharingSeq -> Bool+matchStableSeq sn1 (StableSharingSeq sn2 _)+ | Just sn1' <- gcast sn1 = sn1' == sn2+ | otherwise = False+--}+++-- Occurrence counting+-- ===================++-- Compute the 'SmartAcc' occurrence map, marks all nodes (both 'Seq' and 'Exp' nodes) with stable names,+-- and drop repeated occurrences of shared 'SmartAcc' and 'Exp' subtrees (Phase One).+--+-- We compute a single 'SmartAcc' occurrence map for the whole AST, but one 'Exp' occurrence map for each+-- sub-expression rooted in an 'SmartAcc' operation. This is as we cannot float 'Exp' subtrees across+-- 'SmartAcc' operations, but we can float 'SmartAcc' subtrees out of 'Exp' expressions.+--+-- Note [Traversing functions and side effects]+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+-- We need to descent into function bodies to build the 'OccMap' with all occurrences in the+-- function bodies. Due to the side effects in the construction of the occurrence map and, more+-- importantly, the dependence of the second phase on /global/ occurrence information, we may not+-- delay the body traversals by putting them under a lambda. Hence, we apply each function, to+-- traverse its body and use a /dummy abstraction/ of the result.+--+-- For example, given a function 'f', we traverse 'f (Tag 0)', which yields a transformed body 'e'.+-- As the result of the traversal of the overall function, we use 'const e'. Hence, it is crucial+-- that the 'Tag' supplied during the initial traversal is already the one required by the HOAS to+-- de Bruijn conversion in 'convertSharingAcc' — any subsequent application of 'const e' will only+-- yield 'e' with the embedded 'Tag 0' of the original application. During sharing recovery, we+-- float /all/ free variables ('Atag' and 'Tag') out to construct the initial environment for+-- producing de Bruijn indices, which replaces them by 'AvarSharing' or 'VarSharing' nodes. Hence,+-- the tag values only serve the purpose of determining the ordering in that initial environment.+-- They are /not/ directly used to compute the de Brujin indices.+--+makeOccMapAcc+ :: HasCallStack+ => Config+ -> Level+ -> SmartAcc arrs+ -> IO (UnscopedAcc arrs, OccMap SmartAcc)+makeOccMapAcc config lvl acc = do+ traceLine "makeOccMapAcc" "Enter"+ accOccMap <- newASTHashTable+ (acc', _) <- makeOccMapSharingAcc config accOccMap lvl acc+ frozenAccOccMap <- freezeOccMap accOccMap+ traceLine "makeOccMapAcc" "Exit"+ return (acc', frozenAccOccMap)+++makeOccMapSharingAcc+ :: HasCallStack+ => Config+ -> OccMapHash SmartAcc+ -> Level+ -> SmartAcc arrs+ -> IO (UnscopedAcc arrs, Int)+makeOccMapSharingAcc config accOccMap = traverseAcc+ where+ traverseFun1+ :: HasCallStack+ => Level+ -> TypeR a+ -> (SmartExp a -> SmartExp b)+ -> IO (SmartExp a -> RootExp b, Int)+ traverseFun1 = makeOccMapFun1 config accOccMap++ traverseFun2+ :: HasCallStack+ => Level+ -> TypeR a+ -> TypeR b+ -> (SmartExp a -> SmartExp b -> SmartExp c)+ -> IO (SmartExp a -> SmartExp b -> RootExp c, Int)+ traverseFun2 = makeOccMapFun2 config accOccMap++ traverseAfun1+ :: HasCallStack+ => Level+ -> ArraysR a+ -> (SmartAcc a -> SmartAcc b)+ -> IO (SmartAcc a -> UnscopedAcc b, Int)+ traverseAfun1 = makeOccMapAfun1 config accOccMap++ traverseExp+ :: HasCallStack+ => Level+ -> SmartExp e+ -> IO (RootExp e, Int)+ traverseExp = makeOccMapExp config accOccMap++ traverseBoundary+ :: HasCallStack+ => Level+ -> ShapeR sh+ -> PreBoundary SmartAcc SmartExp (Array sh e)+ -> IO (PreBoundary UnscopedAcc RootExp (Array sh e), Int)+ traverseBoundary lvl shr bndy =+ case bndy of+ Clamp -> return (Clamp, 0)+ Mirror -> return (Mirror, 0)+ Wrap -> return (Wrap, 0)+ Constant v -> return (Constant v, 0)+ Function f -> do+ (f', h) <- traverseFun1 lvl (shapeType shr) f+ return (Function f', h)++ -- traverseSeq :: forall arrs. Typeable arrs+ -- => Level -> Seq arrs+ -- -> IO (RootSeq arrs, Int)+ -- traverseSeq = makeOccMapRootSeq config accOccMap++ traverseAcc+ :: forall arrs. HasCallStack+ => Level+ -> SmartAcc arrs+ -> IO (UnscopedAcc arrs, Int)+ traverseAcc lvl acc@(SmartAcc pacc)+ = mfix $ \ ~(_, height) -> do+ -- Compute stable name and enter it into the occurrence map+ --+ sn <- makeStableAST acc+ heightIfRepeatedOccurrence <- enterOcc accOccMap (StableASTName sn) height++ traceLine (bformat formatPreAccOp pacc) $ do+ let hash = hashStableName sn+ case heightIfRepeatedOccurrence of+ Just height -> bformat ("REPEATED occurrence (sn = " % int % "; height = " % int % ")") hash height+ Nothing -> bformat ("first occurrence (sn = " % int % ")") hash++ -- Reconstruct the computation in shared form.+ --+ -- In case of a repeated occurrence, the height comes from the occurrence map; otherwise+ -- it is computed by the traversal function passed in 'newAcc'. See also 'enterOcc'.+ --+ let reconstruct :: IO (PreSmartAcc UnscopedAcc RootExp arrs, Int)+ -> IO (UnscopedAcc arrs, Int)+ reconstruct newAcc+ = case heightIfRepeatedOccurrence of+ Just height | acc_sharing `member` options config+ -> return (UnscopedAcc [] (AvarSharing (StableNameHeight sn height) (Smart.arraysR pacc)), height)+ _ -> do (acc, height) <- newAcc+ return (UnscopedAcc [] (AccSharing (StableNameHeight sn height) acc), height)++ reconstruct $ case pacc of+ Atag repr i -> return (Atag repr i, 0) -- height is 0!+ Pipe repr1 repr2 repr3 afun1 afun2 acc+ -> do+ (afun1', h1) <- traverseAfun1 lvl repr1 afun1+ (afun2', h2) <- traverseAfun1 lvl repr2 afun2+ (acc', h3) <- traverseAcc lvl acc+ return (Pipe repr1 repr2 repr3 afun1' afun2' acc'+ , h1 `max` h2 `max` h3 + 1)+ Aforeign repr ff afun acc -> travA (Aforeign repr ff afun) acc+ Acond e acc1 acc2 -> do+ (e' , h1) <- traverseExp lvl e+ (acc1', h2) <- traverseAcc lvl acc1+ (acc2', h3) <- traverseAcc lvl acc2+ return (Acond e' acc1' acc2', h1 `max` h2 `max` h3 + 1)+ Awhile repr pred iter init -> do+ (pred', h1) <- traverseAfun1 lvl repr pred+ (iter', h2) <- traverseAfun1 lvl repr iter+ (init', h3) <- traverseAcc lvl init+ return (Awhile repr pred' iter' init'+ , h1 `max` h2 `max` h3 + 1)++ Anil -> return (Anil, 0)+ Apair acc1 acc2 -> do+ (a', h1) <- traverseAcc lvl acc1+ (b', h2) <- traverseAcc lvl acc2+ return (Apair a' b', h1 `max` h2 + 1)+ Aprj ix a -> travA (Aprj ix) a++ Atrace msg acc1 acc2 -> do+ (a', h1) <- traverseAcc lvl acc1+ (b', h2) <- traverseAcc lvl acc2+ return (Atrace msg a' b', h1 `max` h2 + 1)+ Use repr arr -> return (Use repr arr, 1)+ Unit tp e -> do+ (e', h) <- traverseExp lvl e+ return (Unit tp e', h + 1)+ Generate repr@(ArrayR shr _) e f+ -> do+ (e', h1) <- traverseExp lvl e+ (f', h2) <- traverseFun1 lvl (shapeType shr) f+ return (Generate repr e' f', h1 `max` h2 + 1)+ Reshape shr e acc -> travEA (Reshape shr) e acc+ Replicate si e acc -> travEA (Replicate si) e acc+ Slice si acc e -> travEA (flip $ Slice si) e acc+ Map t1 t2 f acc -> do+ (f' , h1) <- traverseFun1 lvl t1 f+ (acc', h2) <- traverseAcc lvl acc+ return (Map t1 t2 f' acc', h1 `max` h2 + 1)+ ZipWith t1 t2 t3 f acc1 acc2+ -> travF2A2 (ZipWith t1 t2 t3) t1 t2 f acc1 acc2+ Fold tp f e acc -> travF2MEA (Fold tp) tp tp f e acc+ FoldSeg i tp f e acc1 acc2 -> do+ (f' , h1) <- traverseFun2 lvl tp tp f+ (e' , h2) <- travME e+ (acc1', h3) <- traverseAcc lvl acc1+ (acc2', h4) <- traverseAcc lvl acc2+ return (FoldSeg i tp f' e' acc1' acc2',+ h1 `max` h2 `max` h3 `max` h4 + 1)+ Scan d tp f e acc -> travF2MEA (Scan d tp) tp tp f e acc+ Scan' d tp f e acc -> travF2EA (Scan' d tp) tp tp f e acc+ Permute repr@(ArrayR shr tp) c acc1 p acc2+ -> do+ (c' , h1) <- traverseFun2 lvl tp tp c+ (p' , h2) <- traverseFun1 lvl (shapeType shr) p+ (acc1', h3) <- traverseAcc lvl acc1+ (acc2', h4) <- traverseAcc lvl acc2+ return (Permute repr c' acc1' p' acc2',+ h1 `max` h2 `max` h3 `max` h4 + 1)+ Backpermute shr e p acc -> do+ (e' , h1) <- traverseExp lvl e+ (p' , h2) <- traverseFun1 lvl (shapeType shr) p+ (acc', h3) <- traverseAcc lvl acc+ return (Backpermute shr e' p' acc', h1 `max` h2 `max` h3 + 1)+ Stencil s tp f bnd acc -> do+ (f' , h1) <- makeOccMapStencil1 config accOccMap s lvl f+ (bnd', h2) <- traverseBoundary lvl (stencilShapeR s) bnd+ (acc', h3) <- traverseAcc lvl acc+ return (Stencil s tp f' bnd' acc', h1 `max` h2 `max` h3 + 1)+ Stencil2 s1 s2 tp f bnd1 acc1+ bnd2 acc2 -> do+ let shr = stencilShapeR s1+ (f' , h1) <- makeOccMapStencil2 config accOccMap s1 s2 lvl f+ (bnd1', h2) <- traverseBoundary lvl shr bnd1+ (acc1', h3) <- traverseAcc lvl acc1+ (bnd2', h4) <- traverseBoundary lvl shr bnd2+ (acc2', h5) <- traverseAcc lvl acc2+ return (Stencil2 s1 s2 tp f' bnd1' acc1' bnd2' acc2',+ h1 `max` h2 `max` h3 `max` h4 `max` h5 + 1)+ -- Collect s -> do+ -- (s', h) <- traverseSeq lvl s+ -- return (Collect s', h + 1)+++ where+ travA :: HasCallStack+ => (UnscopedAcc arrs' -> PreSmartAcc UnscopedAcc RootExp arrs)+ -> SmartAcc arrs'+ -> IO (PreSmartAcc UnscopedAcc RootExp arrs, Int)+ travA c acc+ = do+ (acc', h) <- traverseAcc lvl acc+ return (c acc', h + 1)++ travEA :: HasCallStack+ => (RootExp b -> UnscopedAcc arrs' -> PreSmartAcc UnscopedAcc RootExp arrs)+ -> SmartExp b+ -> SmartAcc arrs'+ -> IO (PreSmartAcc UnscopedAcc RootExp arrs, Int)+ travEA c exp acc+ = do+ (exp', h1) <- traverseExp lvl exp+ (acc', h2) <- traverseAcc lvl acc+ return (c exp' acc', h1 `max` h2 + 1)++ travF2EA+ :: HasCallStack+ => ((SmartExp b -> SmartExp c -> RootExp d) -> RootExp e -> UnscopedAcc arrs' -> PreSmartAcc UnscopedAcc RootExp arrs)+ -> TypeR b+ -> TypeR c+ -> (SmartExp b -> SmartExp c -> SmartExp d)+ -> SmartExp e+ -> SmartAcc arrs'+ -> IO (PreSmartAcc UnscopedAcc RootExp arrs, Int)+ travF2EA c t1 t2 fun exp acc+ = do+ (fun', h1) <- traverseFun2 lvl t1 t2 fun+ (exp', h2) <- traverseExp lvl exp+ (acc', h3) <- traverseAcc lvl acc+ return (c fun' exp' acc', h1 `max` h2 `max` h3 + 1)++ travF2MEA+ :: HasCallStack+ => ((SmartExp b -> SmartExp c -> RootExp d) -> Maybe (RootExp e) -> UnscopedAcc arrs' -> PreSmartAcc UnscopedAcc RootExp arrs)+ -> TypeR b+ -> TypeR c+ -> (SmartExp b -> SmartExp c -> SmartExp d)+ -> Maybe (SmartExp e)+ -> SmartAcc arrs'+ -> IO (PreSmartAcc UnscopedAcc RootExp arrs, Int)+ travF2MEA c t1 t2 fun exp acc+ = do+ (fun', h1) <- traverseFun2 lvl t1 t2 fun+ (exp', h2) <- travME exp+ (acc', h3) <- traverseAcc lvl acc+ return (c fun' exp' acc', h1 `max` h2 `max` h3 + 1)++ travME :: HasCallStack => Maybe (SmartExp t) -> IO (Maybe (RootExp t), Int)+ travME Nothing = return (Nothing, 0)+ travME (Just e) = do+ (e', c) <- traverseExp lvl e+ return (Just e', c)++ travF2A2+ :: HasCallStack+ => ((SmartExp b -> SmartExp c -> RootExp d) -> UnscopedAcc arrs1 -> UnscopedAcc arrs2 -> PreSmartAcc UnscopedAcc RootExp arrs)+ -> TypeR b+ -> TypeR c+ -> (SmartExp b -> SmartExp c -> SmartExp d)+ -> SmartAcc arrs1+ -> SmartAcc arrs2+ -> IO (PreSmartAcc UnscopedAcc RootExp arrs, Int)+ travF2A2 c t1 t2 fun acc1 acc2+ = do+ (fun' , h1) <- traverseFun2 lvl t1 t2 fun+ (acc1', h2) <- traverseAcc lvl acc1+ (acc2', h3) <- traverseAcc lvl acc2+ return (c fun' acc1' acc2', h1 `max` h2 `max` h3 + 1)++makeOccMapAfun1+ :: HasCallStack+ => Config+ -> OccMapHash SmartAcc+ -> Level+ -> ArraysR a+ -> (SmartAcc a -> SmartAcc b)+ -> IO (SmartAcc a -> UnscopedAcc b, Int)+makeOccMapAfun1 config accOccMap lvl repr f = do+ let x = SmartAcc (Atag repr lvl)+ --+ (UnscopedAcc [] body, height) <- makeOccMapSharingAcc config accOccMap (lvl+1) (f x)+ return (const (UnscopedAcc [lvl] body), height)++{--+makeOccMapAfun2 :: (Arrays a, Arrays b, Typeable c)+ => Config+ -> OccMapHash Acc+ -> Level+ -> (Acc a -> Acc b -> Acc c)+ -> IO (Acc a -> Acc b -> UnscopedAcc c, Int)+makeOccMapAfun2 config accOccMap lvl f = do+ let x = Acc (Atag (lvl + 1))+ y = Acc (Atag (lvl + 0))+ --+ (UnscopedAcc [] body, height) <- makeOccMapSharingAcc config accOccMap (lvl+2) (f x y)+ return (\ _ _ -> (UnscopedAcc [lvl, lvl+1] body), height)++makeOccMapAfun3 :: (Arrays a, Arrays b, Arrays c, Typeable d)+ => Config+ -> OccMapHash Acc+ -> Level+ -> (Acc a -> Acc b -> Acc c -> Acc d)+ -> IO (Acc a -> Acc b -> Acc c -> UnscopedAcc d, Int)+makeOccMapAfun3 config accOccMap lvl f = do+ let x = Acc (Atag (lvl + 2))+ y = Acc (Atag (lvl + 1))+ z = Acc (Atag (lvl + 0))+ --+ (UnscopedAcc [] body, height) <- makeOccMapSharingAcc config accOccMap (lvl+3) (f x y z)+ return (\ _ _ _ -> (UnscopedAcc [lvl, lvl+1, lvl+2] body), height)+--}++-- Generate occupancy information for scalar functions and expressions. Helper+-- functions wrapping around 'makeOccMapRootExp' with more specific types.+--+-- See Note [Traversing functions and side effects]+--+makeOccMapExp+ :: HasCallStack+ => Config+ -> OccMapHash SmartAcc+ -> Level+ -> SmartExp e+ -> IO (RootExp e, Int)+makeOccMapExp config accOccMap lvl = makeOccMapRootExp config accOccMap lvl []++makeOccMapFun1+ :: HasCallStack+ => Config+ -> OccMapHash SmartAcc+ -> Level+ -> TypeR a+ -> (SmartExp a -> SmartExp b)+ -> IO (SmartExp a -> RootExp b, Int)+makeOccMapFun1 config accOccMap lvl tp f = do+ let x = SmartExp (Tag tp lvl)+ --+ (body, height) <- makeOccMapRootExp config accOccMap (lvl+1) [lvl] (f x)+ return (const body, height)++makeOccMapFun2+ :: HasCallStack+ => Config+ -> OccMapHash SmartAcc+ -> Level+ -> TypeR a+ -> TypeR b+ -> (SmartExp a -> SmartExp b -> SmartExp c)+ -> IO (SmartExp a -> SmartExp b -> RootExp c, Int)+makeOccMapFun2 config accOccMap lvl t1 t2 f = do+ let x = SmartExp (Tag t1 (lvl+1))+ y = SmartExp (Tag t2 lvl)+ --+ (body, height) <- makeOccMapRootExp config accOccMap (lvl+2) [lvl, lvl+1] (f x y)+ return (\_ _ -> body, height)++makeOccMapStencil1+ :: forall sh a b stencil. HasCallStack+ => Config+ -> OccMapHash SmartAcc+ -> R.StencilR sh a stencil+ -> Level+ -> (SmartExp stencil -> SmartExp b)+ -> IO (SmartExp stencil -> RootExp b, Int)+makeOccMapStencil1 config accOccMap s lvl stencil = do+ let x = SmartExp (Tag (R.stencilR s) lvl)+ --+ (body, height) <- makeOccMapRootExp config accOccMap (lvl+1) [lvl] (stencil x)+ return (const body, height)++makeOccMapStencil2+ :: forall sh a b c stencil1 stencil2. HasCallStack+ => Config+ -> OccMapHash SmartAcc+ -> R.StencilR sh a stencil1+ -> R.StencilR sh b stencil2+ -> Level+ -> (SmartExp stencil1 -> SmartExp stencil2 -> SmartExp c)+ -> IO (SmartExp stencil1 -> SmartExp stencil2 -> RootExp c, Int)+makeOccMapStencil2 config accOccMap sR1 sR2 lvl stencil = do+ let x = SmartExp (Tag (R.stencilR sR1) (lvl+1))+ y = SmartExp (Tag (R.stencilR sR2) lvl)+ --+ (body, height) <- makeOccMapRootExp config accOccMap (lvl+2) [lvl, lvl+1] (stencil x y)+ return (\_ _ -> body, height)+++-- Generate sharing information for expressions embedded in Acc computations.+-- Expressions are annotated with:+--+-- 1) the tags of free scalar variables (for scalar functions)+-- 2) a local occurrence map for that expression.+--+makeOccMapRootExp+ :: HasCallStack+ => Config+ -> OccMapHash SmartAcc+ -> Level -- The level of currently bound scalar variables+ -> [Int] -- The tags of newly introduced free scalar variables in this expression+ -> SmartExp e+ -> IO (RootExp e, Int)+makeOccMapRootExp config accOccMap lvl fvs exp = do+ traceLine "makeOccMapRootExp" "Enter"+ expOccMap <- newASTHashTable+ (UnscopedExp [] exp', height) <- makeOccMapSharingExp config accOccMap expOccMap lvl exp+ frozenExpOccMap <- freezeOccMap expOccMap+ traceLine "makeOccMapRootExp" "Exit"+ return (RootExp frozenExpOccMap (UnscopedExp fvs exp'), height)+++-- Generate sharing information for an open scalar expression.+--+makeOccMapSharingExp+ :: HasCallStack+ => Config+ -> OccMapHash SmartAcc+ -> OccMapHash SmartExp+ -> Level -- The level of currently bound variables+ -> SmartExp e+ -> IO (UnscopedExp e, Int)+makeOccMapSharingExp config accOccMap expOccMap = travE+ where+ travE :: forall a. HasCallStack => Level -> SmartExp a -> IO (UnscopedExp a, Int)+ travE lvl exp@(SmartExp pexp)+ = mfix $ \ ~(_, height) -> do+ -- Compute stable name and enter it into the occurrence map+ --+ sn <- makeStableAST exp+ heightIfRepeatedOccurrence <- enterOcc expOccMap (StableASTName sn) height++ traceLine (bformat formatPreExpOp pexp) $ do+ let hash = hashStableName sn+ case heightIfRepeatedOccurrence of+ Just height -> bformat ("REPEATED occurrence (sn = " % int % "; height = " % int % ")") hash height+ Nothing -> bformat ("first occurrence (sn = " % int % ")") hash++ -- Reconstruct the computation in shared form.+ --+ -- In case of a repeated occurrence, the height comes from the occurrence map; otherwise+ -- it is computed by the traversal function passed in 'newExp'. See also 'enterOcc'.+ --+ let reconstruct :: IO (PreSmartExp UnscopedAcc UnscopedExp a, Int)+ -> IO (UnscopedExp a, Int)+ reconstruct newExp+ = case heightIfRepeatedOccurrence of+ Just height | exp_sharing `member` options config+ -> return (UnscopedExp [] (VarSharing (StableNameHeight sn height) (typeR pexp)), height)+ _ -> do (exp, height) <- newExp+ return (UnscopedExp [] (ExpSharing (StableNameHeight sn height) exp), height)++ reconstruct $ case pexp of+ Tag tp i -> return (Tag tp i, 0) -- height is 0!+ Const tp c -> return (Const tp c, 1)+ Undef tp -> return (Undef tp, 1)+ Nil -> return (Nil, 1)+ Pair e1 e2 -> travE2 Pair e1 e2+ Prj i e -> travE1 (Prj i) e+ VecPack vec e -> travE1 (VecPack vec) e+ VecUnpack vec e -> travE1 (VecUnpack vec) e+ ToIndex shr sh ix -> travE2 (ToIndex shr) sh ix+ FromIndex shr sh e -> travE2 (FromIndex shr) sh e+ Match t e -> travE1 (Match t) e+ Case e rhs -> do+ (e', h1) <- travE lvl e+ (rhs', h2) <- unzip <$> sequence [ travE1 (t,) c | (t,c) <- rhs ]+ return (Case e' rhs', h1 `max` maximum h2 + 1)+ Cond e1 e2 e3 -> travE3 Cond e1 e2 e3+ While t p iter init -> do+ (p' , h1) <- traverseFun1 lvl t p+ (iter', h2) <- traverseFun1 lvl t iter+ (init', h3) <- travE lvl init+ return (While t p' iter' init', h1 `max` h2 `max` h3 + 1)+ PrimConst c -> return (PrimConst c, 1)+ PrimApp p e -> travE1 (PrimApp p) e+ Index tp a e -> travAE (Index tp) a e+ LinearIndex tp a i -> travAE (LinearIndex tp) a i+ Shape shr a -> travA (Shape shr) a+ ShapeSize shr e -> travE1 (ShapeSize shr) e+ Foreign tp ff f e -> do+ (e', h) <- travE lvl e+ return (Foreign tp ff f e', h+1)+ Coerce t1 t2 e -> travE1 (Coerce t1 t2) e++ where+ traverseAcc :: HasCallStack => Level -> SmartAcc arrs -> IO (UnscopedAcc arrs, Int)+ traverseAcc = makeOccMapSharingAcc config accOccMap++ traverseFun1+ :: HasCallStack+ => Level+ -> TypeR a+ -> (SmartExp a -> SmartExp b)+ -> IO (SmartExp a -> UnscopedExp b, Int)+ traverseFun1 lvl tp f+ = do+ let x = SmartExp (Tag tp lvl)+ (UnscopedExp [] body, height) <- travE (lvl+1) (f x)+ return (const (UnscopedExp [lvl] body), height + 1)+++ travE1 :: HasCallStack => (UnscopedExp b -> r) -> SmartExp b -> IO (r, Int)+ travE1 c e+ = do+ (e', h) <- travE lvl e+ return (c e', h + 1)++ travE2 :: HasCallStack+ => (UnscopedExp b -> UnscopedExp c -> r)+ -> SmartExp b+ -> SmartExp c+ -> IO (r, Int)+ travE2 c e1 e2+ = do+ (e1', h1) <- travE lvl e1+ (e2', h2) <- travE lvl e2+ return (c e1' e2', h1 `max` h2 + 1)++ travE3 :: HasCallStack+ => (UnscopedExp b -> UnscopedExp c -> UnscopedExp d -> r)+ -> SmartExp b+ -> SmartExp c+ -> SmartExp d+ -> IO (r, Int)+ travE3 c e1 e2 e3+ = do+ (e1', h1) <- travE lvl e1+ (e2', h2) <- travE lvl e2+ (e3', h3) <- travE lvl e3+ return (c e1' e2' e3', h1 `max` h2 `max` h3 + 1)++ travA :: HasCallStack => (UnscopedAcc b -> r) -> SmartAcc b -> IO (r, Int)+ travA c acc+ = do+ (acc', h) <- traverseAcc lvl acc+ return (c acc', h + 1)++ travAE :: HasCallStack+ => (UnscopedAcc b -> UnscopedExp c -> r)+ -> SmartAcc b+ -> SmartExp c+ -> IO (r, Int)+ travAE c acc e+ = do+ (acc', h1) <- traverseAcc lvl acc+ (e' , h2) <- travE lvl e+ return (c acc' e', h1 `max` h2 + 1)++{--+makeOccMapRootSeq+ :: Typeable arrs+ => Config+ -> OccMapHash Acc+ -> Level+ -> Seq arrs+ -> IO (RootSeq arrs, Int)+makeOccMapRootSeq config accOccMap lvl seq = do+ traceLine "makeOccMapRootSeq" "Enter"+ seqOccMap <- newASTHashTable+ (seq', height) <- makeOccMapSharingSeq config accOccMap seqOccMap lvl seq+ frozenSeqOccMap <- freezeOccMap seqOccMap+ traceLine "makeOccMapRootSeq" "Exit"+ return (RootSeq frozenSeqOccMap seq', height)++-- Generate sharing information for an open sequence expression.+--+makeOccMapSharingSeq+ :: Typeable e+ => Config+ -> OccMapHash Acc+ -> OccMapHash Seq+ -> Level -- The level of currently bound variables+ -> Seq e+ -> IO (UnscopedSeq e, Int)+makeOccMapSharingSeq config accOccMap seqOccMap = traverseSeq+ where+ traverseAcc :: Typeable arrs => Level -> Acc arrs -> IO (UnscopedAcc arrs, Int)+ traverseAcc = makeOccMapSharingAcc config accOccMap++ traverseAfun1 :: (Arrays a, Typeable b) => Level -> (Acc a -> Acc b) -> IO (Acc a -> UnscopedAcc b, Int)+ traverseAfun1 = makeOccMapAfun1 config accOccMap++ traverseAfun2 :: (Arrays a, Arrays b, Typeable c) => Level -> (Acc a -> Acc b -> Acc c) -> IO (Acc a -> Acc b -> UnscopedAcc c, Int)+ traverseAfun2 = makeOccMapAfun2 config accOccMap++ traverseAfun3 :: (Arrays a, Arrays b, Arrays c, Typeable d) => Level -> (Acc a -> Acc b -> Acc c -> Acc d) -> IO (Acc a -> Acc b -> Acc c -> UnscopedAcc d, Int)+ traverseAfun3 = makeOccMapAfun3 config accOccMap++ traverseExp :: Typeable e => Level -> Exp e -> IO (RootExp e, Int)+ traverseExp = makeOccMapExp config accOccMap++ traverseFun2 :: (Elt a, Elt b, Typeable c)+ => Level+ -> (Exp a -> Exp b -> Exp c)+ -> IO (Exp a -> Exp b -> RootExp c, Int)+ traverseFun2 = makeOccMapFun2 config accOccMap++ traverseTup :: Level -> Atuple Seq tup -> IO (Atuple UnscopedSeq tup, Int)+ traverseTup _ NilAtup = return (NilAtup, 1)+ traverseTup lvl (SnocAtup tup s) = do+ (tup', h1) <- traverseTup lvl tup+ (s' , h2) <- traverseSeq lvl s+ return (SnocAtup tup' s', h1 `max` h2 + 1)++ traverseSeq :: forall arrs. Typeable arrs => Level -> Seq arrs -> IO (UnscopedSeq arrs, Int)+ traverseSeq lvl acc@(Seq seq)+ = mfix $ \ ~(_, height) -> do+ -- Compute stable name and enter it into the occurrence map+ --+ sn <- makeStableAST acc+ heightIfRepeatedOccurrence <- enterOcc seqOccMap (StableASTName sn) height++ traceLine (showPreSeqOp seq) $ do+ let hash = show (hashStableName sn)+ case heightIfRepeatedOccurrence of+ Just height -> "REPEATED occurrence (sn = " ++ hash ++ "; height = " ++ show height ++ ")"+ Nothing -> "first occurrence (sn = " ++ hash ++ ")"++ -- Reconstruct the computation in shared form.+ --+ -- In case of a repeated occurrence, the height comes from the occurrence map; otherwise+ -- it is computed by the traversal function passed in 'newAcc'. See also 'enterOcc'.+ --+ -- NB: This function can only be used in the case alternatives below; outside of the+ -- case we cannot discharge the 'Arrays arrs' constraint.+ --+ let producer :: (arrs ~ [a], Arrays a)+ => IO (PreSeq UnscopedAcc UnscopedSeq RootExp arrs, Int)+ -> IO (UnscopedSeq arrs, Int)+ producer newSeq+ = case heightIfRepeatedOccurrence of+ Just height | recoverSeqSharing config+ -> return (UnscopedSeq (SvarSharing (StableNameHeight sn height)), height)+ _ -> do (seq, height) <- newSeq+ return (UnscopedSeq (SeqSharing (StableNameHeight sn height) seq), height)++ let consumer :: IO (PreSeq UnscopedAcc UnscopedSeq RootExp arrs, Int)+ -> IO (UnscopedSeq arrs, Int)+ consumer newSeq+ = do (seq, height) <- newSeq+ return (UnscopedSeq (SeqSharing (StableNameHeight sn height) seq), height)++ case seq of+ StreamIn arrs -> producer $ return (StreamIn arrs, 1)+ ToSeq sl acc -> producer $ do+ (acc', h1) <- traverseAcc lvl acc+ return (ToSeq sl acc', h1 + 1)+ MapSeq afun s -> producer $ do+ (afun', h1) <- traverseAfun1 lvl afun+ (s' , h2) <- traverseSeq lvl s+ return (MapSeq afun' s', h1 `max` h2 + 1)+ ZipWithSeq afun s1 s2 -> producer $ do+ (afun', h1) <- traverseAfun2 lvl afun+ (s1' , h2) <- traverseSeq lvl s1+ (s2' , h3) <- traverseSeq lvl s2+ return (ZipWithSeq afun' s1' s2', h1 `max` h2 `max` h3 + 1)+ ScanSeq fun e s -> producer $ do+ (fun', h1) <- traverseFun2 lvl fun+ (e', h2) <- traverseExp lvl e+ (s' , h3) <- traverseSeq lvl s+ return (ScanSeq fun' e' s', h1 `max` h2 `max` h3 + 1)+ FoldSeq fun e s -> consumer $ do+ (fun', h1) <- traverseFun2 lvl fun+ (e' , h2) <- traverseExp lvl e+ (s' , h3) <- traverseSeq lvl s+ return (FoldSeq fun' e' s', h1 `max` h2 `max` h3 + 1)+ FoldSeqFlatten afun acc s -> consumer $ do+ (afun', h1) <- traverseAfun3 lvl afun+ (acc', h2) <- traverseAcc lvl acc+ (s' , h3) <- traverseSeq lvl s+ return (FoldSeqFlatten afun' acc' s', h1 `max` h2 `max` h3 + 1)+ Stuple t -> consumer $ do+ (t', h1) <- traverseTup lvl t+ return (Stuple t', h1 + 1)+--}+++-- Type used to maintain how often each shared subterm, so far, occurred during a bottom-up sweep,+-- as well as the relation between subterms. It is comprised of a list of terms and a graph giving+-- their relation.+--+-- Invariants of the list:+-- - If one shared term 's' is itself a subterm of another shared term 't', then 's' must occur+-- *after* 't' in the list.+-- - No shared term occurs twice.+-- - A term may have a final occurrence count of only 1 iff it is either a free variable ('Atag'+-- or 'Tag') or an array computation lifted out of an expression.+-- - All 'Exp' node counts precede all 'SmartAcc' node counts as we don't share 'Exp' nodes across 'SmartAcc'+-- nodes. Similarly, all 'Seq' nodes precede 'SmartAcc' nodes and 'Exp' nodes precede 'Seq' nodes.+--+-- We determine the subterm property by using the tree height in 'StableNameHeight'. Trees get+-- smaller towards the end of a 'NodeCounts' list. The height of free variables ('Atag' or 'Tag')+-- is 0, whereas other leaves have height 1. This guarantees that all free variables are at the end+-- of the 'NodeCounts' list.+--+-- The graph is represented as a map where a stable name 'a' is mapped to a set of stables names 'b'+-- such that if there exists a edge from 'a' to 'c' that 'c' is contained within 'b'.+--+-- Properties of the graph:+-- - There exists an edge from 'a' to 'b' if the term 'a' names is a subterm of the term named by+-- 'b'.+--+-- To ensure the list invariant and the graph properties are preserved over merging node counts from+-- sibling subterms, the function '(+++)' must be used.+--+type NodeCounts = ([NodeCount], Map.HashMap NodeName (Set.HashSet NodeName))++data NodeName where+ NodeName :: StableName a -> NodeName++instance Eq NodeName where+ (NodeName sn1) == (NodeName sn2) = eqStableName sn1 sn2++instance Hashable NodeName where+ hashWithSalt hash (NodeName sn1) = hash + hashStableName sn1++instance Show NodeName where+ show (NodeName sn) = show (hashStableName sn)++data NodeCount = AccNodeCount StableSharingAcc Int+ | ExpNodeCount StableSharingExp Int+ -- SeqNodeCount StableSharingSeq Int+ deriving Show++formatNodeCount :: Format r (NodeCount -> r)+formatNodeCount = later $ \case+ AccNodeCount n c -> bformat ("AccNodeCount " % formatStableSharingAcc % " " % int) n c+ ExpNodeCount n c -> bformat ("ExpNodeCount " % formatStableSharingExp % " " % int) n c++-- Empty node counts+--+noNodeCounts :: NodeCounts+noNodeCounts = ([], Map.empty)++-- Insert an Acc node into the node counts, assuming that it is a superterm of the all the existing+-- nodes.+--+-- TODO: Perform cycle detection here.+--+insertAccNode :: StableSharingAcc -> NodeCounts -> NodeCounts+insertAccNode ssa@(StableSharingAcc (StableNameHeight sn _) _) (subterms,g)+ = ([AccNodeCount ssa 1], g') +++ (subterms,g)+ where+ k = NodeName sn+ hs = map nodeName subterms+ g' = Map.fromList $ (k, Set.empty) : [(h, Set.singleton k) | h <- hs]++-- Insert an Exp node into the node counts, assuming that it is a superterm of the all the existing+-- nodes.+--+-- TODO: Perform cycle detection here.+--+insertExpNode :: StableSharingExp -> NodeCounts -> NodeCounts+insertExpNode ssa@(StableSharingExp (StableNameHeight sn _) _) (subterms,g)+ = ([ExpNodeCount ssa 1], g') +++ (subterms,g)+ where+ k = NodeName sn+ hs = map nodeName subterms+ g' = Map.fromList $ (k, Set.empty) : [(h, Set.singleton k) | h <- hs]++{--+-- Insert an Seq node into the node counts, assuming that it is a superterm of the all the existing+-- nodes.+--+-- TODO: Perform cycle detection here.+--+insertSeqNode :: StableSharingSeq -> NodeCounts -> NodeCounts+insertSeqNode ssa@(StableSharingSeq (StableNameHeight sn _) _) (subterms,g)+ = ([SeqNodeCount ssa 1], g') +++ (subterms,g)+ where+ k = NodeName sn+ hs = map nodeName subterms+ g' = Map.fromList $ (k, Set.empty) : [(h, Set.singleton k) | h <- hs]+--}++-- Remove nodes that aren't in the list from the graph.+--+-- RCE: This is no longer necessary when NDP is supported.+--+cleanCounts :: NodeCounts -> NodeCounts+cleanCounts (ns, g) = (ns, Map.fromList [(h, Set.filter (flip elem hs) (g Map.! h)) | h <- hs ])+ where+ hs = map nodeName ns++nodeName :: NodeCount -> NodeName+nodeName (AccNodeCount (StableSharingAcc (StableNameHeight sn _) _) _) = NodeName sn+nodeName (ExpNodeCount (StableSharingExp (StableNameHeight sn _) _) _) = NodeName sn+-- nodeName (SeqNodeCount (StableSharingSeq (StableNameHeight sn _) _) _) = NodeName sn+++-- Combine node counts that belong to the same node.+--+-- * We assume that the list invariant —subterms follow their parents— holds for both arguments and+-- guarantee that it still holds for the result.+--+-- * In the same manner, we assume that all 'Exp' node counts precede 'SmartAcc' node counts and+-- guarantee that this also hold for the result.+--+(+++) :: NodeCounts -> NodeCounts -> NodeCounts+(ns1, g1) +++ (ns2, g2) = (cleanup $ merge ns1 ns2, Map.unionWith Set.union g1 g2)+ where+ merge [] x = x+ merge x [] = x+ merge (x@(AccNodeCount sa1 count1):xs) (y@(AccNodeCount sa2 count2):ys)+ | sa1 == sa2 = AccNodeCount (sa1 `pickNoneAvar` sa2) (count1 + count2) : merge xs ys+ | sa1 `higherSSA` sa2 = x : merge xs (y:ys)+ | otherwise = y : merge (x:xs) ys+ merge (x@(ExpNodeCount se1 count1):xs) (y@(ExpNodeCount se2 count2):ys)+ | se1 == se2 = ExpNodeCount (se1 `pickNoneVar` se2) (count1 + count2) : merge xs ys+ | se1 `higherSSE` se2 = x : merge xs (y:ys)+ | otherwise = y : merge (x:xs) ys+ merge (x@(AccNodeCount _ _):xs) (y@(ExpNodeCount _ _):ys) = y : merge (x:xs) ys+ merge (x@(ExpNodeCount _ _):xs) (y@(AccNodeCount _ _):ys) = x : merge xs (y:ys)++ (StableSharingAcc _ (AvarSharing _ _)) `pickNoneAvar` sa2 = sa2+ sa1 `pickNoneAvar` _sa2 = sa1++ (StableSharingExp _ (VarSharing _ _)) `pickNoneVar` sa2 = sa2+ sa1 `pickNoneVar` _sa2 = sa1++ -- As the StableSharingAccs do not pose a strict ordering, this cleanup+ -- step is needed. In this step, all pairs of AccNodes and ExpNodes+ -- that are of the same height are compared against each other. Without+ -- this step, duplicates may arise.+ --+ -- Note that while (+++) is morally symmetric, replacing `merge [x] y'+ -- with `merge y [x]' inside of `cleanup' won't check all required+ -- possibilities.+ --+ cleanup = concatMap (foldr (\x y -> merge [x] y) []) . groupBy sameHeight+ sameHeight (AccNodeCount sa1 _) (AccNodeCount sa2 _) = not (sa1 `higherSSA` sa2) && not (sa2 `higherSSA` sa1)+ sameHeight (ExpNodeCount se1 _) (ExpNodeCount se2 _) = not (se1 `higherSSE` se2) && not (se2 `higherSSE` se1)+ sameHeight _ _ = False+++-- Build an initial environment for the tag values given in the first argument for traversing an+-- array expression. The 'StableSharingAcc's for all tags /actually used/ in the expressions are+-- in the second argument. (Tags are not used if a bound variable has no usage occurrence.)+--+-- Bail out if any tag occurs multiple times as this indicates that the sharing of an argument+-- variable was not preserved and we cannot build an appropriate initial environment (c.f., comments+-- at 'determineScopesAcc'.+--+buildInitialEnvAcc+ :: HasCallStack+ => [Level]+ -> [StableSharingAcc]+ -> [StableSharingAcc]+buildInitialEnvAcc tags sas = map (lookupSA sas) tags+ where+ lookupSA sas tag1+ = case filter hasTag sas of+ [] -> noStableSharing -- tag is not used in the analysed expression+ [sa] -> sa -- tag has a unique occurrence+ sas2 -> internalError ("Encountered duplicate 'ATag's\n " % commaSpaceSep (later showSA)) sas2+ where+ hasTag (StableSharingAcc _ (AccSharing _ (Atag _ tag2))) = tag1 == tag2+ hasTag sa+ = internalError ("Encountered a node that is not a plain 'Atag'\n " % builder) (showSA sa)++ noStableSharing :: StableSharingAcc+ noStableSharing = StableSharingAcc noStableAccName (undefined :: SharingAcc acc exp ())++ showSA (StableSharingAcc _ (AccSharing sn acc)) = bformat (formatStableNameHeight % ": " % formatPreAccOp) sn acc+ showSA (StableSharingAcc _ (AvarSharing sn _)) = bformat ("AvarSharing " % formatStableNameHeight) sn+ showSA (StableSharingAcc _ (AletSharing sa _)) = bformat ("AletSharing " % formatStableSharingAcc % "...") sa++-- Build an initial environment for the tag values given in the first argument for traversing a+-- scalar expression. The 'StableSharingExp's for all tags /actually used/ in the expressions are+-- in the second argument. (Tags are not used if a bound variable has no usage occurrence.)+--+-- Bail out if any tag occurs multiple times as this indicates that the sharing of an argument+-- variable was not preserved and we cannot build an appropriate initial environment (c.f., comments+-- at 'determineScopesAcc'.+--+buildInitialEnvExp+ :: HasCallStack+ => [Level]+ -> [StableSharingExp]+ -> [StableSharingExp]+buildInitialEnvExp tags ses = map (lookupSE ses) tags+ where+ lookupSE ses tag1+ = case filter hasTag ses of+ [] -> noStableSharing -- tag is not used in the analysed expression+ [se] -> se -- tag has a unique occurrence+ ses2 -> internalError ("Encountered a duplicate 'Tag'\n " % commaSpaceSep (later showSE)) ses2+ where+ hasTag (StableSharingExp _ (ExpSharing _ (Tag _ tag2))) = tag1 == tag2+ hasTag se+ = internalError ("Encountered a node that is not a plain 'Tag'\n " % builder) (showSE se)++ noStableSharing :: StableSharingExp+ noStableSharing = StableSharingExp noStableExpName (undefined :: SharingExp acc exp ())++ showSE (StableSharingExp _ (ExpSharing sn exp)) = bformat (formatStableNameHeight % ": " % formatPreExpOp) sn exp+ showSE (StableSharingExp _ (VarSharing sn _ )) = bformat ("VarSharing " % formatStableNameHeight) sn+ showSE (StableSharingExp _ (LetSharing se _ )) = bformat ("LetSharing " % formatStableSharingExp % "...") se++-- Determine whether a 'NodeCount' is for an 'Atag' or 'Tag', which represent free variables.+--+isFreeVar :: NodeCount -> Bool+isFreeVar (AccNodeCount (StableSharingAcc _ (AccSharing _ (Atag _ _))) _) = True+isFreeVar (ExpNodeCount (StableSharingExp _ (ExpSharing _ (Tag _ _))) _) = True+isFreeVar _ = False+++-- Determine scope of shared subterms+-- ==================================++-- Determine the scopes of all variables representing shared subterms (Phase Two) in a bottom-up+-- sweep. The first argument determines whether array computations are floated out of expressions+-- irrespective of whether they are shared or not — 'True' implies floating them out.+--+-- In addition to the AST with sharing information, yield the 'StableSharingAcc's for all free+-- variables of 'rootAcc', which are represented by 'Atag' leaves in the tree. They are in order of+-- the tag values — i.e., in the same order that they need to appear in an environment to use the+-- tag for indexing into that environment.+--+-- Precondition: there are only 'AvarSharing' and 'AccSharing' nodes in the argument.+--+determineScopesAcc+ :: HasCallStack+ => Config+ -> [Level]+ -> OccMap SmartAcc+ -> UnscopedAcc a+ -> (ScopedAcc a, [StableSharingAcc])+determineScopesAcc config fvs accOccMap rootAcc+ = let (sharingAcc, (counts, _)) = determineScopesSharingAcc config accOccMap rootAcc+ unboundTrees = filter (not . isFreeVar) counts+ in+ if all isFreeVar counts+ then (sharingAcc, buildInitialEnvAcc fvs [sa | AccNodeCount sa _ <- counts])+ else internalError ("unbound shared subtrees " % list formatNodeCount) unboundTrees+++determineScopesSharingAcc+ :: HasCallStack+ => Config+ -> OccMap SmartAcc+ -> UnscopedAcc a+ -> (ScopedAcc a, NodeCounts)+determineScopesSharingAcc config accOccMap = scopesAcc+ where+ scopesAcc :: forall arrs. HasCallStack => UnscopedAcc arrs -> (ScopedAcc arrs, NodeCounts)+ scopesAcc (UnscopedAcc _ (AletSharing _ _))+ = internalError "unexpected 'AletSharing'"++ scopesAcc (UnscopedAcc _ (AvarSharing sn tp))+ = (ScopedAcc [] (AvarSharing sn tp), StableSharingAcc sn (AvarSharing sn tp) `insertAccNode` noNodeCounts)++ scopesAcc (UnscopedAcc _ (AccSharing sn pacc))+ = case pacc of+ Atag tp i -> reconstruct (Atag tp i) noNodeCounts+ Pipe repr1 repr2 repr3 afun1 afun2 acc+ -> let+ (afun1', accCount1) = scopesAfun1 afun1+ (afun2', accCount2) = scopesAfun1 afun2+ (acc', accCount3) = scopesAcc acc+ in+ reconstruct (Pipe repr1 repr2 repr3 afun1' afun2' acc')+ (accCount1 +++ accCount2 +++ accCount3)++ Aforeign r ff afun acc -> let+ (acc', accCount) = scopesAcc acc+ in+ reconstruct (Aforeign r ff afun acc') accCount+ Acond e acc1 acc2 -> let+ (e' , accCount1) = scopesExp e+ (acc1', accCount2) = scopesAcc acc1+ (acc2', accCount3) = scopesAcc acc2+ in+ reconstruct (Acond e' acc1' acc2')+ (accCount1 +++ accCount2 +++ accCount3)++ Awhile repr pred iter init+ -> let+ (pred', accCount1) = scopesAfun1 pred+ (iter', accCount2) = scopesAfun1 iter+ (init', accCount3) = scopesAcc init+ in+ reconstruct (Awhile repr pred' iter' init')+ (accCount1 +++ accCount2 +++ accCount3)++ Anil -> reconstruct Anil noNodeCounts+ Apair a1 a2 -> let+ (a1', accCount1) = scopesAcc a1+ (a2', accCount2) = scopesAcc a2+ in+ reconstruct (Apair a1' a2') (accCount1 +++ accCount2)+ Aprj ix a -> travA (Aprj ix) a++ Atrace msg a1 a2 -> let+ (a1', accCount1) = scopesAcc a1+ (a2', accCount2) = scopesAcc a2+ in+ reconstruct (Atrace msg a1' a2') (accCount1 +++ accCount2)+ Use repr arr -> reconstruct (Use repr arr) noNodeCounts+ Unit tp e -> let+ (e', accCount) = scopesExp e+ in+ reconstruct (Unit tp e') accCount+ Generate repr sh f -> let+ (sh', accCount1) = scopesExp sh+ (f' , accCount2) = scopesFun1 f+ in+ reconstruct (Generate repr sh' f') (accCount1 +++ accCount2)+ Reshape shr sh acc -> travEA (Reshape shr) sh acc+ Replicate si n acc -> travEA (Replicate si) n acc+ Slice si acc i -> travEA (flip $ Slice si) i acc+ Map t1 t2 f acc -> let+ (f' , accCount1) = scopesFun1 f+ (acc', accCount2) = scopesAcc acc+ in+ reconstruct (Map t1 t2 f' acc') (accCount1 +++ accCount2)+ ZipWith t1 t2 t3 f acc1 acc2+ -> travF2A2 (ZipWith t1 t2 t3) f acc1 acc2+ Fold tp f z acc -> travF2MEA (Fold tp) f z acc+ FoldSeg i tp f z acc1 acc2 -> let+ (f' , accCount1) = scopesFun2 f+ (z' , accCount2) = travME z+ (acc1', accCount3) = scopesAcc acc1+ (acc2', accCount4) = scopesAcc acc2+ in+ reconstruct (FoldSeg i tp f' z' acc1' acc2')+ (accCount1 +++ accCount2 +++ accCount3 +++ accCount4)+ Scan d tp f z acc -> travF2MEA (Scan d tp) f z acc+ Scan' d tp f z acc -> travF2EA (Scan' d tp) f z acc+ Permute repr fc acc1 fp acc2+ -> let+ (fc' , accCount1) = scopesFun2 fc+ (acc1', accCount2) = scopesAcc acc1+ (fp' , accCount3) = scopesFun1 fp+ (acc2', accCount4) = scopesAcc acc2+ in+ reconstruct (Permute repr fc' acc1' fp' acc2')+ (accCount1 +++ accCount2 +++ accCount3 +++ accCount4)+ Backpermute shr sh fp acc+ -> let+ (sh' , accCount1) = scopesExp sh+ (fp' , accCount2) = scopesFun1 fp+ (acc', accCount3) = scopesAcc acc+ in+ reconstruct (Backpermute shr sh' fp' acc')+ (accCount1 +++ accCount2 +++ accCount3)+ Stencil sr tp st bnd acc -> let+ (st' , accCount1) = scopesStencil1 acc st+ (bnd', accCount2) = scopesBoundary bnd+ (acc', accCount3) = scopesAcc acc+ in+ reconstruct (Stencil sr tp st' bnd' acc') (accCount1 +++ accCount2 +++ accCount3)+ Stencil2 s1 s2 tp st bnd1 acc1 bnd2 acc2+ -> let+ (st' , accCount1) = scopesStencil2 acc1 acc2 st+ (bnd1', accCount2) = scopesBoundary bnd1+ (acc1', accCount3) = scopesAcc acc1+ (bnd2', accCount4) = scopesBoundary bnd2+ (acc2', accCount5) = scopesAcc acc2+ in+ reconstruct (Stencil2 s1 s2 tp st' bnd1' acc1' bnd2' acc2')+ (accCount1 +++ accCount2 +++ accCount3 +++ accCount4 +++ accCount5)+ -- Collect seq -> let+ -- (seq', accCount1) = scopesSeq seq+ -- in+ -- reconstruct (Collect seq') accCount1++ where+ travEA :: HasCallStack+ => (ScopedExp e -> ScopedAcc arrs' -> PreSmartAcc ScopedAcc ScopedExp arrs)+ -> RootExp e+ -> UnscopedAcc arrs'+ -> (ScopedAcc arrs, NodeCounts)+ travEA c e acc = reconstruct (c e' acc') (accCount1 +++ accCount2)+ where+ (e' , accCount1) = scopesExp e+ (acc', accCount2) = scopesAcc acc++ travF2EA+ :: HasCallStack+ => ((SmartExp a -> SmartExp b -> ScopedExp c) -> ScopedExp e -> ScopedAcc arrs' -> PreSmartAcc ScopedAcc ScopedExp arrs)+ -> (SmartExp a -> SmartExp b -> RootExp c)+ -> RootExp e+ -> UnscopedAcc arrs'+ -> (ScopedAcc arrs, NodeCounts)+ travF2EA c f e acc = reconstruct (c f' e' acc') (accCount1 +++ accCount2 +++ accCount3)+ where+ (f' , accCount1) = scopesFun2 f+ (e' , accCount2) = scopesExp e+ (acc', accCount3) = scopesAcc acc++ travF2MEA+ :: HasCallStack+ => ((SmartExp a -> SmartExp b -> ScopedExp c) -> Maybe (ScopedExp e) -> ScopedAcc arrs' -> PreSmartAcc ScopedAcc ScopedExp arrs)+ -> (SmartExp a -> SmartExp b -> RootExp c)+ -> Maybe (RootExp e)+ -> UnscopedAcc arrs'+ -> (ScopedAcc arrs, NodeCounts)+ travF2MEA c f e acc = reconstruct (c f' e' acc') (accCount1 +++ accCount2 +++ accCount3)+ where+ (f' , accCount1) = scopesFun2 f+ (e' , accCount2) = travME e+ (acc', accCount3) = scopesAcc acc++ travME :: HasCallStack => Maybe (RootExp e) -> (Maybe (ScopedExp e), NodeCounts)+ travME Nothing = (Nothing, noNodeCounts)+ travME (Just e) = (Just e', c)+ where (e', c) = scopesExp e++ travF2A2+ :: HasCallStack+ => ((SmartExp a -> SmartExp b -> ScopedExp c) -> ScopedAcc arrs1 -> ScopedAcc arrs2 -> PreSmartAcc ScopedAcc ScopedExp arrs)+ -> (SmartExp a -> SmartExp b -> RootExp c)+ -> UnscopedAcc arrs1+ -> UnscopedAcc arrs2+ -> (ScopedAcc arrs, NodeCounts)+ travF2A2 c f acc1 acc2 = reconstruct (c f' acc1' acc2')+ (accCount1 +++ accCount2 +++ accCount3)+ where+ (f' , accCount1) = scopesFun2 f+ (acc1', accCount2) = scopesAcc acc1+ (acc2', accCount3) = scopesAcc acc2++ travA :: HasCallStack+ => (ScopedAcc arrs' -> PreSmartAcc ScopedAcc ScopedExp arrs)+ -> UnscopedAcc arrs'+ -> (ScopedAcc arrs, NodeCounts)+ travA c acc = reconstruct (c acc') accCount+ where+ (acc', accCount) = scopesAcc acc++ -- Occurrence count of the currently processed node+ accOccCount = let StableNameHeight sn' _ = sn+ in+ lookupWithASTName accOccMap (StableASTName sn')++ -- Reconstruct the current tree node.+ --+ -- * If the current node is being shared ('accOccCount > 1'), replace it by a 'AvarSharing'+ -- node and float the shared subtree out wrapped in a 'NodeCounts' value.+ -- * If the current node is not shared, reconstruct it in place.+ -- * Special case for free variables ('Atag'): Replace the tree by a sharing variable and+ -- float the 'Atag' out in a 'NodeCounts' value. This is independent of the number of+ -- occurrences.+ --+ -- In either case, any completed 'NodeCounts' are injected as bindings using 'AletSharing'+ -- node.+ --+ reconstruct+ :: HasCallStack+ => PreSmartAcc ScopedAcc ScopedExp arrs+ -> NodeCounts+ -> (ScopedAcc arrs, NodeCounts)+ reconstruct newAcc@(Atag tp _) _subCount+ -- free variable => replace by a sharing variable regardless of the number of+ -- occurrences+ = let thisCount = StableSharingAcc sn (AccSharing sn newAcc) `insertAccNode` noNodeCounts+ in+ tracePure "FREE" (fromString (show thisCount))+ (ScopedAcc [] (AvarSharing sn tp), thisCount)+ reconstruct newAcc subCount+ -- shared subtree => replace by a sharing variable (if 'recoverAccSharing' enabled)+ | accOccCount > 1 && acc_sharing `member` options config+ = let allCount = (StableSharingAcc sn sharingAcc `insertAccNode` newCount)+ in+ tracePure ("SHARED" <> completed) (fromString (show allCount))+ (ScopedAcc [] (AvarSharing sn $ Smart.arraysR newAcc), allCount)+ -- neither shared nor free variable => leave it as it is+ | otherwise+ = tracePure ("Normal" <> completed) (fromString (show newCount))+ (ScopedAcc [] sharingAcc, newCount)+ where+ -- Determine the bindings that need to be attached to the current node...+ (newCount, bindHere) = filterCompleted subCount++ -- ...and wrap them in 'AletSharing' constructors+ lets = foldl (flip (.)) id . map (\x y -> AletSharing x (ScopedAcc [] y)) $ bindHere+ sharingAcc = lets $ AccSharing sn newAcc++ -- trace support+ completed | null bindHere = ""+ | otherwise = bformat (parenthesised (int % " lets")) (length bindHere)++ -- Extract *leading* nodes that have a complete node count (i.e., their node count is equal+ -- to the number of occurrences of that node in the overall expression).+ --+ -- Nodes with a completed node count should be let bound at the currently processed node.+ --+ -- NB: Only extract leading nodes (i.e., the longest run at the *front* of the list that is+ -- complete). Otherwise, we would let-bind subterms before their parents, which leads+ -- scope errors.+ --+ filterCompleted :: NodeCounts -> (NodeCounts, [StableSharingAcc])+ filterCompleted (ns, graph)+ = let bindable = map (isBindable bindable (map nodeName ns)) ns+ (bind, rest) = partition fst $ zip bindable ns+ in ((map snd rest, graph), [sa | AccNodeCount sa _ <- map snd bind])+ where+ -- a node is not yet complete while the node count 'n' is below the overall number+ -- of occurrences for that node in the whole program, with the exception that free+ -- variables are never complete+ isCompleted nc@(AccNodeCount sa n) | not . isFreeVar $ nc = lookupWithSharingAcc accOccMap sa == n+ isCompleted _ = False++ isBindable :: [Bool] -> [NodeName] -> NodeCount -> Bool+ isBindable bindable nodes nc@(AccNodeCount _ _) =+ let superTerms = Set.toList $ graph Map.! nodeName nc+ unbound = mapMaybe (`elemIndex` nodes) superTerms+ in isCompleted nc+ && all (bindable !!) unbound+ isBindable _ _ (ExpNodeCount _ _) = False+ -- isBindable _ _ (SeqNodeCount _ _) = False++ -- scopesSeq :: forall arrs. RootSeq arrs -> (ScopedSeq arrs, NodeCounts)+ -- scopesSeq = determineScopesSeq config accOccMap++ scopesExp+ :: HasCallStack+ => RootExp t+ -> (ScopedExp t, NodeCounts)+ scopesExp = determineScopesExp config accOccMap++ -- The lambda bound variable is at this point already irrelevant; for details, see+ -- Note [Traversing functions and side effects]+ --+ scopesAfun1+ :: HasCallStack+ => (SmartAcc a1 -> UnscopedAcc a2)+ -> (SmartAcc a1 -> ScopedAcc a2, NodeCounts)+ scopesAfun1 f = (const (ScopedAcc ssa body'), (counts', graph))+ where+ body@(UnscopedAcc fvs _) = f undefined+ (ScopedAcc [] body', (counts,graph)) = scopesAcc body+ (freeCounts, counts') = partition isBoundHere counts+ ssa = buildInitialEnvAcc fvs [sa | AccNodeCount sa _ <- freeCounts]++ isBoundHere (AccNodeCount (StableSharingAcc _ (AccSharing _ (Atag _ i))) _) = i `elem` fvs+ isBoundHere _ = False++ -- The lambda bound variable is at this point already irrelevant; for details, see+ -- Note [Traversing functions and side effects]+ --+ scopesFun1+ :: HasCallStack+ => (SmartExp e1 -> RootExp e2)+ -> (SmartExp e1 -> ScopedExp e2, NodeCounts)+ scopesFun1 f = (const body, counts)+ where+ (body, counts) = scopesExp (f undefined)++ -- The lambda bound variable is at this point already irrelevant; for details, see+ -- Note [Traversing functions and side effects]+ --+ scopesFun2+ :: HasCallStack+ => (SmartExp e1 -> SmartExp e2 -> RootExp e3)+ -> (SmartExp e1 -> SmartExp e2 -> ScopedExp e3, NodeCounts)+ scopesFun2 f = (\_ _ -> body, counts)+ where+ (body, counts) = scopesExp (f undefined undefined)++ -- The lambda bound variable is at this point already irrelevant; for details, see+ -- Note [Traversing functions and side effects]+ --+ scopesStencil1+ :: forall sh e1 e2 stencil. HasCallStack+ => UnscopedAcc (Array sh e1){-dummy-}+ -> (stencil -> RootExp e2)+ -> (stencil -> ScopedExp e2, NodeCounts)+ scopesStencil1 _ stencilFun = (const body, counts)+ where+ (body, counts) = scopesExp (stencilFun undefined)++ -- The lambda bound variable is at this point already irrelevant; for details, see+ -- Note [Traversing functions and side effects]+ --+ scopesStencil2+ :: forall sh e1 e2 e3 stencil1 stencil2. HasCallStack+ => UnscopedAcc (Array sh e1){-dummy-}+ -> UnscopedAcc (Array sh e2){-dummy-}+ -> (stencil1 -> stencil2 -> RootExp e3)+ -> (stencil1 -> stencil2 -> ScopedExp e3, NodeCounts)+ scopesStencil2 _ _ stencilFun = (\_ _ -> body, counts)+ where+ (body, counts) = scopesExp (stencilFun undefined undefined)++ scopesBoundary+ :: HasCallStack+ => PreBoundary UnscopedAcc RootExp t+ -> (PreBoundary ScopedAcc ScopedExp t, NodeCounts)+ scopesBoundary bndy =+ case bndy of+ Clamp -> (Clamp, noNodeCounts)+ Mirror -> (Mirror, noNodeCounts)+ Wrap -> (Wrap, noNodeCounts)+ Constant v -> (Constant v, noNodeCounts)+ Function f -> let (body, counts) = scopesFun1 f+ in (Function body, counts)+++determineScopesExp+ :: HasCallStack+ => Config+ -> OccMap SmartAcc+ -> RootExp t+ -> (ScopedExp t, NodeCounts) -- Root (closed) expression plus Acc node counts+determineScopesExp config accOccMap (RootExp expOccMap exp@(UnscopedExp fvs _))+ = let+ (ScopedExp [] expWithScopes, (nodeCounts,graph)) = determineScopesSharingExp config accOccMap expOccMap exp+ (expCounts, accCounts) = partition isExpNodeCount nodeCounts++ isExpNodeCount ExpNodeCount{} = True+ isExpNodeCount _ = False+ in+ (ScopedExp (buildInitialEnvExp fvs [se | ExpNodeCount se _ <- expCounts]) expWithScopes, cleanCounts (accCounts,graph))+++determineScopesSharingExp+ :: HasCallStack+ => Config+ -> OccMap SmartAcc+ -> OccMap SmartExp+ -> UnscopedExp t+ -> (ScopedExp t, NodeCounts)+determineScopesSharingExp config accOccMap expOccMap = scopesExp+ where+ scopesAcc+ :: HasCallStack+ => UnscopedAcc a+ -> (ScopedAcc a, NodeCounts)+ scopesAcc = determineScopesSharingAcc config accOccMap++ scopesFun1+ :: HasCallStack+ => (SmartExp a -> UnscopedExp b)+ -> (SmartExp a -> ScopedExp b, NodeCounts)+ scopesFun1 f = tracePure (bformat ("LAMBDA " % list formatStableSharingExp) ssa) (bformat (list formatNodeCount) counts) (const (ScopedExp ssa body'), (counts',graph))+ where+ body@(UnscopedExp fvs _) = f undefined+ (ScopedExp [] body', (counts, graph)) = scopesExp body+ (freeCounts, counts') = partition isBoundHere counts+ ssa = buildInitialEnvExp fvs [se | ExpNodeCount se _ <- freeCounts]++ isBoundHere (ExpNodeCount (StableSharingExp _ (ExpSharing _ (Tag _ i))) _) = i `elem` fvs+ isBoundHere _ = False++ scopesExp+ :: forall t. HasCallStack+ => UnscopedExp t+ -> (ScopedExp t, NodeCounts)+ scopesExp (UnscopedExp _ (LetSharing _ _))+ = internalError "unexpected 'LetSharing'"++ scopesExp (UnscopedExp _ (VarSharing sn tp))+ = (ScopedExp [] (VarSharing sn tp), StableSharingExp sn (VarSharing sn tp) `insertExpNode` noNodeCounts)++ scopesExp (UnscopedExp _ (ExpSharing sn pexp))+ = case pexp of+ Tag tp i -> reconstruct (Tag tp i) noNodeCounts+ Const tp c -> reconstruct (Const tp c) noNodeCounts+ Undef tp -> reconstruct (Undef tp) noNodeCounts+ Pair e1 e2 -> travE2 Pair e1 e2+ Nil -> reconstruct Nil noNodeCounts+ Prj i e -> travE1 (Prj i) e+ VecPack vec e -> travE1 (VecPack vec) e+ VecUnpack vec e -> travE1 (VecUnpack vec) e+ ToIndex shr sh ix -> travE2 (ToIndex shr) sh ix+ FromIndex shr sh e -> travE2 (FromIndex shr) sh e+ Match t e -> travE1 (Match t) e+ Case e rhs -> let (e', accCount1) = scopesExp e+ (rhs', accCount2) = unzip [ ((t,c'), counts)| (t,c) <- rhs, let (c', counts) = scopesExp c ]+ in reconstruct (Case e' rhs') (foldr (+++) accCount1 accCount2)+ Cond e1 e2 e3 -> travE3 Cond e1 e2 e3+ While tp p it i -> let (p' , accCount1) = scopesFun1 p+ (it', accCount2) = scopesFun1 it+ (i' , accCount3) = scopesExp i+ in reconstruct (While tp p' it' i') (accCount1 +++ accCount2 +++ accCount3)+ PrimConst c -> reconstruct (PrimConst c) noNodeCounts+ PrimApp p e -> travE1 (PrimApp p) e+ Index tp a e -> travAE (Index tp) a e+ LinearIndex tp a e -> travAE (LinearIndex tp) a e+ Shape shr a -> travA (Shape shr) a+ ShapeSize shr e -> travE1 (ShapeSize shr) e+ Foreign tp ff f e -> travE1 (Foreign tp ff f) e+ Coerce t1 t2 e -> travE1 (Coerce t1 t2) e+ where+ travE1 :: HasCallStack+ => (ScopedExp a -> PreSmartExp ScopedAcc ScopedExp t)+ -> UnscopedExp a+ -> (ScopedExp t, NodeCounts)+ travE1 c e = reconstruct (c e') accCount+ where+ (e', accCount) = scopesExp e++ travE2 :: HasCallStack+ => (ScopedExp a -> ScopedExp b -> PreSmartExp ScopedAcc ScopedExp t)+ -> UnscopedExp a+ -> UnscopedExp b+ -> (ScopedExp t, NodeCounts)+ travE2 c e1 e2 = reconstruct (c e1' e2') (accCount1 +++ accCount2)+ where+ (e1', accCount1) = scopesExp e1+ (e2', accCount2) = scopesExp e2++ travE3 :: HasCallStack+ => (ScopedExp a -> ScopedExp b -> ScopedExp c -> PreSmartExp ScopedAcc ScopedExp t)+ -> UnscopedExp a+ -> UnscopedExp b+ -> UnscopedExp c+ -> (ScopedExp t, NodeCounts)+ travE3 c e1 e2 e3 = reconstruct (c e1' e2' e3') (accCount1 +++ accCount2 +++ accCount3)+ where+ (e1', accCount1) = scopesExp e1+ (e2', accCount2) = scopesExp e2+ (e3', accCount3) = scopesExp e3++ travA :: HasCallStack+ => (ScopedAcc a -> PreSmartExp ScopedAcc ScopedExp t) -> UnscopedAcc a+ -> (ScopedExp t, NodeCounts)+ travA c acc = floatOutAcc c acc' accCount+ where+ (acc', accCount) = scopesAcc acc++ travAE :: HasCallStack+ => (ScopedAcc a -> ScopedExp b -> PreSmartExp ScopedAcc ScopedExp t)+ -> UnscopedAcc a+ -> UnscopedExp b+ -> (ScopedExp t, NodeCounts)+ travAE c acc e = floatOutAcc (`c` e') acc' (accCountA +++ accCountE)+ where+ (acc', accCountA) = scopesAcc acc+ (e' , accCountE) = scopesExp e++ floatOutAcc+ :: HasCallStack+ => (ScopedAcc a -> PreSmartExp ScopedAcc ScopedExp t)+ -> ScopedAcc a+ -> NodeCounts+ -> (ScopedExp t, NodeCounts)+ floatOutAcc c acc@(ScopedAcc _ (AvarSharing _ _)) accCount -- nothing to float out+ = reconstruct (c acc) accCount+ floatOutAcc c acc accCount+ = reconstruct (c var) ((stableAcc `insertAccNode` noNodeCounts) +++ accCount)+ where+ (var, stableAcc) = abstract acc (\(ScopedAcc _ s) -> s)++ abstract+ :: HasCallStack+ => ScopedAcc a+ -> (ScopedAcc a -> SharingAcc ScopedAcc ScopedExp a)+ -> (ScopedAcc a, StableSharingAcc)+ abstract (ScopedAcc _ (AvarSharing _ _)) _ = internalError "AvarSharing"+ abstract (ScopedAcc ssa (AletSharing sa acc)) lets = abstract acc (lets . ScopedAcc ssa . AletSharing sa)+ abstract acc@(ScopedAcc ssa (AccSharing sn a)) lets = (ScopedAcc ssa (AvarSharing sn $ Smart.arraysR a), StableSharingAcc sn (lets acc))++ -- Occurrence count of the currently processed node+ expOccCount = let StableNameHeight sn' _ = sn+ in lookupWithASTName expOccMap (StableASTName sn')++ -- Reconstruct the current tree node.+ --+ -- * If the current node is being shared ('expOccCount > 1'), replace it by a 'VarSharing'+ -- node and float the shared subtree out wrapped in a 'NodeCounts' value.+ -- * If the current node is not shared, reconstruct it in place.+ -- * Special case for free variables ('Tag'): Replace the tree by a sharing variable and+ -- float the 'Tag' out in a 'NodeCounts' value. This is independent of the number of+ -- occurrences.+ --+ -- In either case, any completed 'NodeCounts' are injected as bindings using 'LetSharing'+ -- node.+ --+ reconstruct+ :: HasCallStack+ => PreSmartExp ScopedAcc ScopedExp t+ -> NodeCounts+ -> (ScopedExp t, NodeCounts)+ reconstruct newExp@(Tag tp _) _subCount+ -- free variable => replace by a sharing variable regardless of the number of+ -- occurrences+ = let thisCount = StableSharingExp sn (ExpSharing sn newExp) `insertExpNode` noNodeCounts+ in+ tracePure "FREE" (fromString (show thisCount))+ (ScopedExp [] (VarSharing sn tp), thisCount)+ reconstruct newExp subCount+ -- shared subtree => replace by a sharing variable (if 'recoverExpSharing' enabled)+ | expOccCount > 1 && exp_sharing `member` options config+ = let allCount = StableSharingExp sn sharingExp `insertExpNode` newCount+ in+ tracePure ("SHARED" <> completed) (fromString (show allCount))+ (ScopedExp [] (VarSharing sn $ typeR newExp), allCount)+ -- neither shared nor free variable => leave it as it is+ | otherwise+ = tracePure ("Normal" <> completed) (fromString (show newCount))+ (ScopedExp [] sharingExp, newCount)+ where+ -- Determine the bindings that need to be attached to the current node...+ (newCount, bindHere) = filterCompleted subCount++ -- ...and wrap them in 'LetSharing' constructors+ lets = foldl (flip (.)) id . map (\x y -> LetSharing x (ScopedExp [] y)) $ bindHere+ sharingExp = lets $ ExpSharing sn newExp++ -- trace support+ completed | null bindHere = ""+ | otherwise = bformat (parenthesised (int % " lets")) (length bindHere)++ -- Extract *leading* nodes that have a complete node count (i.e., their node count is equal+ -- to the number of occurrences of that node in the overall expression).+ --+ -- Nodes with a completed node count should be let bound at the currently processed node.+ --+ -- NB: Only extract leading nodes (i.e., the longest run at the *front* of the list that is+ -- complete). Otherwise, we would let-bind subterms before their parents, which leads+ -- scope errors.+ --+ filterCompleted :: HasCallStack => NodeCounts -> (NodeCounts, [StableSharingExp])+ filterCompleted (ns,graph)+ = let bindable = map (isBindable bindable (map nodeName ns)) ns+ (bind, unbind) = partition fst $ zip bindable ns+ in ((map snd unbind, graph), [se | ExpNodeCount se _ <- map snd bind])+ where+ -- a node is not yet complete while the node count 'n' is below the overall number+ -- of occurrences for that node in the whole program, with the exception that free+ -- variables are never complete+ isCompleted nc@(ExpNodeCount sa n) | not . isFreeVar $ nc = lookupWithSharingExp expOccMap sa == n+ isCompleted _ = False++ isBindable :: [Bool] -> [NodeName] -> NodeCount -> Bool+ isBindable bindable nodes nc@(ExpNodeCount _ _) =+ let superTerms = Set.toList $ graph Map.! nodeName nc+ unbound = mapMaybe (`elemIndex` nodes) superTerms+ in isCompleted nc+ && all (bindable !!) unbound+ isBindable _ _ (AccNodeCount _ _) = False+ -- isBindable _ _ (SeqNodeCount _ _) = False++{--+determineScopesSeq+ :: Config+ -> OccMap Acc+ -> RootSeq t+ -> (ScopedSeq t, NodeCounts) -- Root (closed) expression plus Acc node counts+determineScopesSeq config accOccMap (RootSeq seqOccMap seq)+ = let+ (ScopedSeq seqWithScopes, (nodeCounts,graph)) = determineScopesSharingSeq config accOccMap seqOccMap seq+ binds = [s | SeqNodeCount s _ <- nodeCounts]+ lets = foldl (flip (.)) id . map (\x y -> SletSharing x (ScopedSeq y)) $ binds+ sharingSeq = lets seqWithScopes+ newCounts = filter (not . isSeqCount) nodeCounts+ isSeqCount SeqNodeCount{} = True+ isSeqCount _ = False+ in+ (ScopedSeq sharingSeq, cleanCounts (newCounts,graph))++determineScopesSharingSeq+ :: Config+ -> OccMap Acc+ -> OccMap Seq+ -> UnscopedSeq t+ -> (ScopedSeq t, NodeCounts)+determineScopesSharingSeq config accOccMap _seqOccMap = scopesSeq+ where+ scopesAcc :: UnscopedAcc a -> (ScopedAcc a, NodeCounts)+ scopesAcc = determineScopesSharingAcc config accOccMap++ scopesExp :: RootExp t -> (ScopedExp t, NodeCounts)+ scopesExp = determineScopesExp config accOccMap++ scopesFun2 :: (Elt e1, Elt e2)+ => (Exp e1 -> Exp e2 -> RootExp e3)+ -> (Exp e1 -> Exp e2 -> ScopedExp e3, NodeCounts)+ scopesFun2 f = (\_ _ -> body, counts)+ where+ (body, counts) = scopesExp (f undefined undefined)++ -- The lambda bound variable is at this point already irrelevant; for details, see+ -- Note [Traversing functions and side effects]+ --+ scopesAfun1 :: Arrays a1 => (Acc a1 -> UnscopedAcc a2) -> (Acc a1 -> ScopedAcc a2, NodeCounts)+ scopesAfun1 f = (const (ScopedAcc ssa body'), (counts',graph))+ where+ body@(UnscopedAcc fvs _) = f undefined+ ((ScopedAcc [] body'), (counts,graph)) = scopesAcc body+ ssa = buildInitialEnvAcc fvs [sa | AccNodeCount sa _ <- freeCounts]+ (freeCounts, counts') = partition isBoundHere counts++ isBoundHere (AccNodeCount (StableSharingAcc _ (AccSharing _ (Atag i))) _) = i `elem` fvs+ isBoundHere _ = False++ scopesAfun2 :: (Arrays a1, Arrays a2) => (Acc a1 -> Acc a2 -> UnscopedAcc a3) -> (Acc a1 -> Acc a2 -> ScopedAcc a3, NodeCounts)+ scopesAfun2 f = (\ _ _ -> (ScopedAcc ssa body'), (counts',graph))+ where+ body@(UnscopedAcc fvs _) = f undefined undefined+ ((ScopedAcc [] body'), (counts,graph)) = scopesAcc body+ ssa = buildInitialEnvAcc fvs [sa | AccNodeCount sa _ <- freeCounts]+ (freeCounts, counts') = partition isBoundHere counts++ isBoundHere (AccNodeCount (StableSharingAcc _ (AccSharing _ (Atag i))) _) = i `elem` fvs+ isBoundHere _ = False++ scopesAfun3 :: (Arrays a1, Arrays a2, Arrays a3) => (Acc a1 -> Acc a2 -> Acc a3 -> UnscopedAcc a4) -> (Acc a1 -> Acc a2 -> Acc a3 -> ScopedAcc a4, NodeCounts)+ scopesAfun3 f = (\ _ _ _ -> (ScopedAcc ssa body'), (counts',graph))+ where+ body@(UnscopedAcc fvs _) = f undefined undefined undefined+ ((ScopedAcc [] body'), (counts,graph)) = scopesAcc body+ ssa = buildInitialEnvAcc fvs [sa | AccNodeCount sa _ <- freeCounts]+ (freeCounts, counts') = partition isBoundHere counts++ isBoundHere (AccNodeCount (StableSharingAcc _ (AccSharing _ (Atag i))) _) = i `elem` fvs+ isBoundHere _ = False++ scopesTup :: Atuple UnscopedSeq tup -> (Atuple ScopedSeq tup, NodeCounts)+ scopesTup NilAtup = (NilAtup, noNodeCounts)+ scopesTup (SnocAtup tup s) = let+ (tup', accCountT) = scopesTup tup+ (s' , accCountS) = scopesSeq s+ in+ (SnocAtup tup' s', accCountT +++ accCountS)++ scopesSeq :: forall t. UnscopedSeq t -> (ScopedSeq t, NodeCounts)+ scopesSeq (UnscopedSeq (SletSharing _ _))+ = $internalError "determineScopesSharingSeq: scopesSeq" "unexpected 'LetSharing'"+ scopesSeq (UnscopedSeq (SvarSharing sn))+ = (ScopedSeq (SvarSharing sn), StableSharingSeq sn (SvarSharing sn) `insertSeqNode` noNodeCounts)++ scopesSeq (UnscopedSeq (SeqSharing sn s)) =+ case s of+ StreamIn arrs -> producer (StreamIn arrs) noNodeCounts+ ToSeq sl acc -> let+ (acc', accCount1) = scopesAcc acc+ in producer (ToSeq sl acc') accCount1+ MapSeq afun s' -> let+ (afun', accCount1) = scopesAfun1 afun+ (s'' , accCount2) = scopesSeq s'+ in producer (MapSeq afun' s'') (accCount1 +++ accCount2)+ ZipWithSeq afun s1 s2 -> let+ (afun', accCount1) = scopesAfun2 afun+ (s1' , accCount2) = scopesSeq s1+ (s2' , accCount3) = scopesSeq s2+ in producer (ZipWithSeq afun' s1' s2') (accCount1 +++ accCount2 +++ accCount3)+ ScanSeq fun e s' -> let+ (fun', accCount1) = scopesFun2 fun+ (e' , accCount2) = scopesExp e+ (s'' , accCount3) = scopesSeq s'+ in producer (ScanSeq fun' e' s'') (accCount1 +++ accCount2 +++ accCount3)+ FoldSeq fun e s' -> let+ (fun', accCount1) = scopesFun2 fun+ (e' , accCount2) = scopesExp e+ (s'' , accCount3) = scopesSeq s'+ in consumer (FoldSeq fun' e' s'') (accCount1 +++ accCount2 +++ accCount3)+ FoldSeqFlatten afun acc s' ->+ let+ (afun', accCount1) = scopesAfun3 afun+ (acc' , accCount2) = scopesAcc acc+ (s'' , accCount3) = scopesSeq s'+ in consumer (FoldSeqFlatten afun' acc' s'') (accCount1 +++ accCount2 +++ accCount3)+ Stuple tup -> let+ (tup', accCount1) = scopesTup tup+ in consumer (Stuple tup') accCount1+ where+ -- All producers must be replaced by sharing variables+ --+ producer :: (t ~ [a], Arrays a)+ => PreSeq ScopedAcc ScopedSeq ScopedExp t+ -> NodeCounts+ -> (ScopedSeq t, NodeCounts)+ producer newSeq subCount+ = let allCount = StableSharingSeq sn (SeqSharing sn newSeq) `insertSeqNode` subCount+ in+ tracePure "Producer" (fromString (show allCount))+ (ScopedSeq (SvarSharing sn), allCount)++ -- Consumers cannot be shared.+ --+ consumer :: PreSeq ScopedAcc ScopedSeq ScopedExp t+ -> NodeCounts+ -> (ScopedSeq t, NodeCounts)+ consumer newSeq subCount+ = tracePure "Consumer" (fromString (show subCount))+ (ScopedSeq (SeqSharing sn newSeq), subCount)+--}++-- |Recover sharing information and annotate the HOAS AST with variable and let binding+-- annotations. The first argument determines whether array computations are floated out of+-- expressions irrespective of whether they are shared or not — 'True' implies floating them out.+--+-- Also returns the 'StableSharingAcc's of all 'Atag' leaves in environment order — they represent+-- the free variables of the AST.+--+-- NB: Strictly speaking, this function is not deterministic, as it uses stable pointers to+-- determine the sharing of subterms. The stable pointer API does not guarantee its+-- completeness; i.e., it may miss some equalities, which implies that we may fail to discover+-- some sharing. However, sharing does not affect the denotational meaning of an array+-- computation; hence, we do not compromise denotational correctness.+--+-- There is one caveat: We currently rely on the 'Atag' and 'Tag' leaves representing free+-- variables to be shared if any of them is used more than once. If one is duplicated, the+-- environment for de Bruijn conversion will have a duplicate entry, and hence, be of the wrong+-- size, which is fatal. (The 'buildInitialEnv*' functions will already bail out.)+--+{-# NOINLINE recoverSharingAcc #-}+recoverSharingAcc+ :: HasCallStack+ => Config+ -> Level -- The level of currently bound array variables+ -> [Level] -- The tags of newly introduced free array variables+ -> SmartAcc a+ -> (ScopedAcc a, [StableSharingAcc])+recoverSharingAcc config alvl avars acc+ = let (acc', occMap)+ = unsafePerformIO -- to enable stable pointers; this is safe as explained above+ $ makeOccMapAcc config alvl acc+ in+ determineScopesAcc config avars occMap acc'+++{-# NOINLINE recoverSharingExp #-}+recoverSharingExp+ :: HasCallStack+ => Config+ -> Level -- The level of currently bound scalar variables+ -> [Level] -- The tags of newly introduced free scalar variables+ -> SmartExp e+ -> (ScopedExp e, [StableSharingExp])+recoverSharingExp config lvl fvar exp+ = let+ (rootExp, accOccMap) = unsafePerformIO $ do+ accOccMap <- newASTHashTable+ (exp', _) <- makeOccMapRootExp config accOccMap lvl fvar exp+ frozenAccOccMap <- freezeOccMap accOccMap++ return (exp', frozenAccOccMap)++ (ScopedExp sse sharingExp, _) =+ determineScopesExp config accOccMap rootExp+ in+ (ScopedExp [] sharingExp, sse)+++{--+{-# NOINLINE recoverSharingSeq #-}+recoverSharingSeq+ :: Config+ -> Seq e+ -> (ScopedSeq e, [StableSharingSeq])+recoverSharingSeq config seq+ = let+ (rootSeq, accOccMap) = unsafePerformIO $ do+ accOccMap <- newASTHashTable+ (seq', _) <- makeOccMapRootSeq config accOccMap 0 seq+ frozenAccOccMap <- freezeOccMap accOccMap++ return (seq', frozenAccOccMap)++ (ScopedSeq sharingSeq, (ns, _)) =+ determineScopesSeq config accOccMap rootSeq+ in+ (ScopedSeq sharingSeq, [a | SeqNodeCount a _ <- ns])+--}+++-- Debugging+-- ---------++traceLine :: Builder -> Builder -> IO ()+traceLine = Debug.traceM Debug.dump_sharing (builder % ": " % builder)++traceChunk :: Builder -> Builder -> IO ()+traceChunk = Debug.traceM Debug.dump_sharing (builder % ":\n" % indented 4 builder)++tracePure :: Builder -> Builder -> a -> a+tracePure header msg = Debug.trace Debug.dump_sharing (bformat (builder % ": " % builder) header msg)+
+ src/Data/Array/Accelerate/Trafo/Shrink.hs view
@@ -0,0 +1,651 @@+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE ViewPatterns #-}+-- |+-- Module : Data.Array.Accelerate.Trafo.Shrink+-- Copyright : [2012..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- The shrinking substitution arises as a restriction of beta-reduction to cases+-- where the bound variable is used zero (dead-code elimination) or one (linear+-- inlining) times. By simplifying terms, the shrinking reduction can expose+-- opportunities for further optimisation.+--+-- TODO: replace with a linear shrinking algorithm; e.g.+--+-- * Andrew Appel & Trevor Jim, "Shrinking lambda expressions in linear time".+--+-- * Nick Benton, Andrew Kennedy, Sam Lindley and Claudio Russo, "Shrinking+-- Reductions in SML.NET"+--++module Data.Array.Accelerate.Trafo.Shrink (++ -- Shrinking+ ShrinkAcc,+ shrinkExp,+ shrinkFun,++ -- Occurrence counting+ UsesOfAcc, usesOfPreAcc, usesOfExp,++) where++import Data.Array.Accelerate.AST+import Data.Array.Accelerate.AST.Environment+import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.AST.LeftHandSide+import Data.Array.Accelerate.AST.Var+import Data.Array.Accelerate.Analysis.Match+import Data.Array.Accelerate.Error+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Trafo.Substitution++import qualified Data.Array.Accelerate.Debug.Internal.Stats as Stats++import Control.Applicative hiding ( Const )+import Data.Maybe ( isJust )+import Data.Monoid+import Data.Semigroup+import Prelude hiding ( exp, seq )+++data VarsRange env =+ VarsRange !(Exists (Idx env)) -- rightmost variable+ {-# UNPACK #-} !Int -- count+ !(Maybe RangeTuple) -- tuple++data RangeTuple+ = RTNil+ | RTSingle+ | RTPair !RangeTuple !RangeTuple++lhsVarsRange :: LeftHandSide s v env env' -> Either (env :~: env') (VarsRange env')+lhsVarsRange lhs = case rightIx lhs of+ Left eq -> Left eq+ Right ix -> let (n, rt) = go lhs+ in Right $ VarsRange ix n rt+ where+ rightIx :: LeftHandSide s v env env' -> Either (env :~: env') (Exists (Idx env'))+ rightIx (LeftHandSideWildcard _) = Left Refl+ rightIx (LeftHandSideSingle _) = Right $ Exists ZeroIdx+ rightIx (LeftHandSidePair l1 l2) = case rightIx l2 of+ Right ix -> Right ix+ Left Refl -> rightIx l1++ go :: LeftHandSide s v env env' -> (Int, Maybe (RangeTuple))+ go (LeftHandSideWildcard TupRunit) = (0, Just RTNil)+ go (LeftHandSideWildcard _) = (0, Nothing)+ go (LeftHandSideSingle _) = (1, Just RTSingle)+ go (LeftHandSidePair l1 l2) = (n1 + n2, RTPair <$> t1 <*> t2)+ where+ (n1, t1) = go l1+ (n2, t2) = go l2++weakenVarsRange :: LeftHandSide s v env env' -> VarsRange env -> VarsRange env'+weakenVarsRange lhs (VarsRange ix n t) = VarsRange (go lhs ix) n t+ where+ go :: LeftHandSide s v env env' -> Exists (Idx env) -> Exists (Idx env')+ go (LeftHandSideWildcard _) ix' = ix'+ go (LeftHandSideSingle _) (Exists ix') = Exists (SuccIdx ix')+ go (LeftHandSidePair l1 l2) ix' = go l2 $ go l1 ix'++matchEVarsRange :: VarsRange env -> OpenExp env aenv t -> Bool+matchEVarsRange (VarsRange (Exists first) _ (Just rt)) expr = isJust $ go (idxToInt first) rt expr+ where+ go :: Int -> RangeTuple -> OpenExp env aenv t -> Maybe Int+ go i RTNil Nil = Just i+ go i RTSingle (Evar (Var _ ix))+ | checkIdx i ix = Just (i + 1)+ go i (RTPair t1 t2) (Pair e1 e2)+ | Just i' <- go i t2 e2 = go i' t1 e1+ go _ _ _ = Nothing++ checkIdx :: Int -> Idx env t -> Bool+ checkIdx 0 ZeroIdx = True+ checkIdx i (SuccIdx ix) = checkIdx (i - 1) ix+ checkIdx _ _ = False+matchEVarsRange _ _ = False++varInRange :: VarsRange env -> Var s env t -> Maybe Usages+varInRange (VarsRange (Exists rangeIx) n _) (Var _ varIx) = case go rangeIx varIx of+ Nothing -> Nothing+ Just j -> Just $ replicate j False ++ [True] ++ replicate (n - j - 1) False+ where+ -- `go ix ix'` checks whether ix <= ix' with recursion, and then checks+ -- whether ix' < ix + n in go'. Returns a Just if both checks+ -- are successful, containing an integer j such that ix + j = ix'.+ go :: Idx env u -> Idx env t -> Maybe Int+ go (SuccIdx ix) (SuccIdx ix') = go ix ix'+ go ZeroIdx ix' = go' ix' 0+ go _ ZeroIdx = Nothing++ go' :: Idx env t -> Int -> Maybe Int+ go' _ j | j >= n = Nothing+ go' ZeroIdx j = Just j+ go' (SuccIdx ix') j = go' ix' (j + 1)++-- Describes how often the variables defined in a LHS are used together.+data Count+ = Impossible !Usages+ -- Cannot inline this definition. This happens when the definition+ -- declares multiple variables (the right hand side returns a tuple)+ -- and the variables are used seperately.+ | Infinity+ -- The variable is used in a loop. Inlining should only proceed if+ -- the computation is cheap.+ | Finite {-# UNPACK #-} !Int++type Usages = [Bool] -- Per variable a Boolean denoting whether that variable is used.++instance Semigroup Count where+ Impossible u1 <> Impossible u2 = Impossible $ zipWith (||) u1 u2+ Impossible u <> Finite 0 = Impossible u+ Finite 0 <> Impossible u = Impossible u+ Impossible u <> _ = Impossible $ map (const True) u+ _ <> Impossible u = Impossible $ map (const True) u+ Infinity <> _ = Infinity+ _ <> Infinity = Infinity+ Finite a <> Finite b = Finite $ a + b++instance Monoid Count where+ mempty = Finite 0++loopCount :: Count -> Count+loopCount (Finite n) | n > 0 = Infinity+loopCount c = c++shrinkLhs+ :: HasCallStack+ => Count+ -> LeftHandSide s t env1 env2+ -> Maybe (Exists (LeftHandSide s t env1))+shrinkLhs _ (LeftHandSideWildcard _) = Nothing -- We cannot shrink this+shrinkLhs (Finite 0) lhs = Just $ Exists $ LeftHandSideWildcard $ lhsToTupR lhs -- LHS isn't used at all, replace with a wildcard+shrinkLhs (Impossible usages) lhs = case go usages lhs of+ (True , [], lhs') -> Just lhs'+ (False, [], _ ) -> Nothing -- No variables were dropped. Thus lhs == lhs'.+ _ -> internalError "Mismatch in length of usages array and LHS"+ where+ go :: HasCallStack => Usages -> LeftHandSide s t env1 env2 -> (Bool, Usages, Exists (LeftHandSide s t env1))+ go us (LeftHandSideWildcard tp) = (False, us, Exists $ LeftHandSideWildcard tp)+ go (True : us) (LeftHandSideSingle tp) = (False, us, Exists $ LeftHandSideSingle tp)+ go (False : us) (LeftHandSideSingle tp) = (True , us, Exists $ LeftHandSideWildcard $ TupRsingle tp)+ go us (LeftHandSidePair l1 l2)+ | (c2, us' , Exists l2') <- go us l2+ , (c1, us'', Exists l1') <- go us' l1+ , Exists l2'' <- rebuildLHS l2'+ = let+ lhs'+ | LeftHandSideWildcard t1 <- l1'+ , LeftHandSideWildcard t2 <- l2'' = LeftHandSideWildcard $ TupRpair t1 t2+ | otherwise = LeftHandSidePair l1' l2''+ in+ (c1 || c2, us'', Exists lhs')+ go _ _ = internalError "Empty array, mismatch in length of usages array and LHS"+shrinkLhs _ _ = Nothing++-- The first LHS should be 'larger' than the second, eg the second may have+-- a wildcard if the first LHS does bind variables there, but not the other+-- way around.+--+strengthenShrunkLHS+ :: HasCallStack+ => LeftHandSide s t env1 env2+ -> LeftHandSide s t env1' env2'+ -> env1 :?> env1'+ -> env2 :?> env2'+strengthenShrunkLHS (LeftHandSideWildcard _) (LeftHandSideWildcard _) k = k+strengthenShrunkLHS (LeftHandSideSingle _) (LeftHandSideSingle _) k = \ix -> case ix of+ ZeroIdx -> Just ZeroIdx+ SuccIdx ix' -> SuccIdx <$> k ix'+strengthenShrunkLHS (LeftHandSidePair lA hA) (LeftHandSidePair lB hB) k = strengthenShrunkLHS hA hB $ strengthenShrunkLHS lA lB k+strengthenShrunkLHS (LeftHandSideSingle _) (LeftHandSideWildcard _) k = \ix -> case ix of+ ZeroIdx -> Nothing+ SuccIdx ix' -> k ix'+strengthenShrunkLHS (LeftHandSidePair l h) (LeftHandSideWildcard t) k = strengthenShrunkLHS h (LeftHandSideWildcard t2) $ strengthenShrunkLHS l (LeftHandSideWildcard t1) k+ where+ (t1, t2) = case t of TupRpair t1' t2' -> (t1', t2')+ _ -> internalError "Pair type was not TupRpair"+strengthenShrunkLHS (LeftHandSideWildcard _) _ _ = internalError "Second LHS defines more variables"+strengthenShrunkLHS _ _ _ = internalError "Mismatch LHS single with LHS pair"+++-- Shrinking+-- =========++-- The shrinking substitution for scalar expressions. This is a restricted+-- instance of beta-reduction to cases where the bound variable is used zero+-- (dead-code elimination) or one (linear inlining) times.+--+shrinkExp :: HasCallStack => OpenExp env aenv t -> (Bool, OpenExp env aenv t)+shrinkExp = Stats.substitution "shrinkE" . first getAny . shrinkE+ where+ -- If the bound variable is used at most this many times, it will be inlined+ -- into the body. In cases where it is not used at all, this is equivalent+ -- to dead-code elimination.+ --+ lIMIT :: Int+ lIMIT = 1++ cheap :: OpenExp env aenv t -> Bool+ cheap (Evar _) = True+ cheap (Pair e1 e2) = cheap e1 && cheap e2+ cheap Nil = True+ cheap Const{} = True+ cheap PrimConst{} = True+ cheap Undef{} = True+ cheap (Coerce _ _ e) = cheap e+ cheap _ = False++ shrinkE :: HasCallStack => OpenExp env aenv t -> (Any, OpenExp env aenv t)+ shrinkE exp = case exp of+ Let (LeftHandSideSingle _) bnd@Evar{} body -> Stats.inline "Var" . yes $ shrinkE (inline body bnd)+ Let lhs bnd body+ | shouldInline -> case inlineVars lhs (snd body') (snd bnd') of+ Just inlined -> Stats.betaReduce msg . yes $ shrinkE inlined+ _ -> internalError "Unexpected failure while trying to inline some expression."+ | Just (Exists lhs') <- shrinkLhs count lhs -> case strengthenE (strengthenShrunkLHS lhs lhs' Just) (snd body') of+ Just body'' -> (Any True, Let lhs' (snd bnd') body'')+ Nothing -> internalError "Unexpected failure in strenthenE. Variable was analysed to be unused in usesOfExp, but appeared to be used in strenthenE."+ | otherwise -> Let lhs <$> bnd' <*> body'+ where+ shouldInline = case count of+ Finite 0 -> False -- Handled by shrinkLhs+ Finite n -> n <= lIMIT || cheap (snd bnd')+ Infinity -> cheap (snd bnd')+ Impossible _ -> False++ bnd' = shrinkE bnd+ body' = shrinkE body++ -- If the lhs includes non-trivial wildcards (the last field of range is Nothing),+ -- then we cannot inline the binding. We can only check which variables are not used,+ -- to detect unused variables.+ --+ -- If the lhs does not include non-trivial wildcards (the last field of range is a Just),+ -- we can both analyse whether we can inline the binding, and check which variables are+ -- not used, to detect unused variables.+ --+ count = case lhsVarsRange lhs of+ Left _ -> Finite 0+ Right range -> usesOfExp range (snd body')++ msg = case count of+ Finite 0 -> "dead exp"+ _ -> "inline exp" -- forced inlining when lIMIT > 1+ --+ Evar v -> pure (Evar v)+ Const t c -> pure (Const t c)+ Undef t -> pure (Undef t)+ Nil -> pure Nil+ Pair x y -> Pair <$> shrinkE x <*> shrinkE y+ VecPack vec e -> VecPack vec <$> shrinkE e+ VecUnpack vec e -> VecUnpack vec <$> shrinkE e+ IndexSlice x ix sh -> IndexSlice x <$> shrinkE ix <*> shrinkE sh+ IndexFull x ix sl -> IndexFull x <$> shrinkE ix <*> shrinkE sl+ ToIndex shr sh ix -> ToIndex shr <$> shrinkE sh <*> shrinkE ix+ FromIndex shr sh i -> FromIndex shr <$> shrinkE sh <*> shrinkE i+ Case e rhs def -> Case <$> shrinkE e <*> sequenceA [ (t,) <$> shrinkE c | (t,c) <- rhs ] <*> shrinkMaybeE def+ Cond p t e -> Cond <$> shrinkE p <*> shrinkE t <*> shrinkE e+ While p f x -> While <$> shrinkF p <*> shrinkF f <*> shrinkE x+ PrimConst c -> pure (PrimConst c)+ PrimApp f x -> PrimApp f <$> shrinkE x+ Index a sh -> Index a <$> shrinkE sh+ LinearIndex a i -> LinearIndex a <$> shrinkE i+ Shape a -> pure (Shape a)+ ShapeSize shr sh -> ShapeSize shr <$> shrinkE sh+ Foreign repr ff f e -> Foreign repr ff <$> shrinkF f <*> shrinkE e+ Coerce t1 t2 e -> Coerce t1 t2 <$> shrinkE e++ shrinkF :: HasCallStack => OpenFun env aenv t -> (Any, OpenFun env aenv t)+ shrinkF = first Any . shrinkFun++ shrinkMaybeE :: HasCallStack => Maybe (OpenExp env aenv t) -> (Any, Maybe (OpenExp env aenv t))+ shrinkMaybeE Nothing = pure Nothing+ shrinkMaybeE (Just e) = Just <$> shrinkE e++ first :: (a -> a') -> (a,b) -> (a',b)+ first f (x,y) = (f x, y)++ yes :: (Any, x) -> (Any, x)+ yes (_, x) = (Any True, x)++shrinkFun :: HasCallStack => OpenFun env aenv f -> (Bool, OpenFun env aenv f)+shrinkFun (Lam lhs f) = case lhsVarsRange lhs of+ Left Refl ->+ let b' = case lhs of+ LeftHandSideWildcard TupRunit -> b+ _ -> True+ in (b', Lam (LeftHandSideWildcard $ lhsToTupR lhs) f')+ Right range ->+ let+ count = usesOfFun range f+ in case shrinkLhs count lhs of+ Just (Exists lhs') -> case strengthenE (strengthenShrunkLHS lhs lhs' Just) f' of+ Just f'' -> (True, Lam lhs' f'')+ Nothing -> internalError "Unexpected failure in strenthenE. Variable was analysed to be unused in usesOfExp, but appeared to be used in strenthenE."+ Nothing -> (b, Lam lhs f')+ where+ (b, f') = shrinkFun f++shrinkFun (Body b) = Body <$> shrinkExp b++-- The shrinking substitution for array computations. This is further limited to+-- dead-code elimination only, primarily because linear inlining may inline+-- array computations into scalar expressions, which is generally not desirable.+--+type ShrinkAcc acc = forall aenv a. acc aenv a -> acc aenv a++{--+type ReduceAcc acc = forall aenv s t. acc aenv s -> acc (aenv,s) t -> Maybe (PreOpenAcc acc aenv t)++shrinkPreAcc+ :: forall acc aenv arrs. ShrinkAcc acc -> ReduceAcc acc+ -> PreOpenAcc acc aenv arrs+ -> PreOpenAcc acc aenv arrs+shrinkPreAcc shrinkAcc reduceAcc = Stats.substitution "shrinkA" shrinkA+ where+ shrinkA :: PreOpenAcc acc aenv' a -> PreOpenAcc acc aenv' a+ shrinkA pacc = case pacc of+ Alet lhs bnd body+ | Just reduct <- reduceAcc bnd' body' -> shrinkA reduct+ | otherwise -> Alet lhs bnd' body'+ where+ bnd' = shrinkAcc bnd+ body' = shrinkAcc body+ --+ Avar ix -> Avar ix+ Apair a1 a2 -> Apair (shrinkAcc a1) (shrinkAcc a2)+ Anil -> Anil+ Apply repr f a -> Apply repr (shrinkAF f) (shrinkAcc a)+ Aforeign ff af a -> Aforeign ff af (shrinkAcc a)+ Acond p t e -> Acond (shrinkE p) (shrinkAcc t) (shrinkAcc e)+ Awhile p f a -> Awhile (shrinkAF p) (shrinkAF f) (shrinkAcc a)+ Use repr a -> Use repr a+ Unit e -> Unit (shrinkE e)+ Reshape e a -> Reshape (shrinkE e) (shrinkAcc a)+ Generate e f -> Generate (shrinkE e) (shrinkF f)+ Transform sh ix f a -> Transform (shrinkE sh) (shrinkF ix) (shrinkF f) (shrinkAcc a)+ Replicate sl slix a -> Replicate sl (shrinkE slix) (shrinkAcc a)+ Slice sl a slix -> Slice sl (shrinkAcc a) (shrinkE slix)+ Map f a -> Map (shrinkF f) (shrinkAcc a)+ ZipWith f a1 a2 -> ZipWith (shrinkF f) (shrinkAcc a1) (shrinkAcc a2)+ Fold f z a -> Fold (shrinkF f) (shrinkE z) (shrinkAcc a)+ Fold1 f a -> Fold1 (shrinkF f) (shrinkAcc a)+ FoldSeg f z a b -> FoldSeg (shrinkF f) (shrinkE z) (shrinkAcc a) (shrinkAcc b)+ Fold1Seg f a b -> Fold1Seg (shrinkF f) (shrinkAcc a) (shrinkAcc b)+ Scanl f z a -> Scanl (shrinkF f) (shrinkE z) (shrinkAcc a)+ Scanl' f z a -> Scanl' (shrinkF f) (shrinkE z) (shrinkAcc a)+ Scanl1 f a -> Scanl1 (shrinkF f) (shrinkAcc a)+ Scanr f z a -> Scanr (shrinkF f) (shrinkE z) (shrinkAcc a)+ Scanr' f z a -> Scanr' (shrinkF f) (shrinkE z) (shrinkAcc a)+ Scanr1 f a -> Scanr1 (shrinkF f) (shrinkAcc a)+ Permute f1 a1 f2 a2 -> Permute (shrinkF f1) (shrinkAcc a1) (shrinkF f2) (shrinkAcc a2)+ Backpermute sh f a -> Backpermute (shrinkE sh) (shrinkF f) (shrinkAcc a)+ Stencil f b a -> Stencil (shrinkF f) b (shrinkAcc a)+ Stencil2 f b1 a1 b2 a2 -> Stencil2 (shrinkF f) b1 (shrinkAcc a1) b2 (shrinkAcc a2)+ -- Collect s -> Collect (shrinkS s)++{--+ shrinkS :: PreOpenSeq acc aenv' senv a -> PreOpenSeq acc aenv' senv a+ shrinkS seq =+ case seq of+ Producer p s -> Producer (shrinkP p) (shrinkS s)+ Consumer c -> Consumer (shrinkC c)+ Reify ix -> Reify ix++ shrinkP :: Producer acc aenv' senv a -> Producer acc aenv' senv a+ shrinkP p =+ case p of+ StreamIn arrs -> StreamIn arrs+ ToSeq sl slix a -> ToSeq sl slix (shrinkAcc a)+ MapSeq f x -> MapSeq (shrinkAF f) x+ ChunkedMapSeq f x -> ChunkedMapSeq (shrinkAF f) x+ ZipWithSeq f x y -> ZipWithSeq (shrinkAF f) x y+ ScanSeq f e x -> ScanSeq (shrinkF f) (shrinkE e) x++ shrinkC :: Consumer acc aenv' senv a -> Consumer acc aenv' senv a+ shrinkC c =+ case c of+ FoldSeq f e x -> FoldSeq (shrinkF f) (shrinkE e) x+ FoldSeqFlatten f a x -> FoldSeqFlatten (shrinkAF f) (shrinkAcc a) x+ Stuple t -> Stuple (shrinkCT t)++ shrinkCT :: Atuple (Consumer acc aenv' senv) t -> Atuple (Consumer acc aenv' senv) t+ shrinkCT NilAtup = NilAtup+ shrinkCT (SnocAtup t c) = SnocAtup (shrinkCT t) (shrinkC c)+--}++ shrinkE :: OpenExp env aenv' t -> OpenExp env aenv' t+ shrinkE exp = case exp of+ Let bnd body -> Let (shrinkE bnd) (shrinkE body)+ Var idx -> Var idx+ Const c -> Const c+ Undef -> Undef+ Tuple t -> Tuple (shrinkT t)+ Prj tup e -> Prj tup (shrinkE e)+ IndexNil -> IndexNil+ IndexCons sl sz -> IndexCons (shrinkE sl) (shrinkE sz)+ IndexHead sh -> IndexHead (shrinkE sh)+ IndexTail sh -> IndexTail (shrinkE sh)+ IndexSlice x ix sh -> IndexSlice x (shrinkE ix) (shrinkE sh)+ IndexFull x ix sl -> IndexFull x (shrinkE ix) (shrinkE sl)+ IndexAny -> IndexAny+ ToIndex sh ix -> ToIndex (shrinkE sh) (shrinkE ix)+ FromIndex sh i -> FromIndex (shrinkE sh) (shrinkE i)+ Cond p t e -> Cond (shrinkE p) (shrinkE t) (shrinkE e)+ While p f x -> While (shrinkF p) (shrinkF f) (shrinkE x)+ PrimConst c -> PrimConst c+ PrimApp f x -> PrimApp f (shrinkE x)+ Index a sh -> Index (shrinkAcc a) (shrinkE sh)+ LinearIndex a i -> LinearIndex (shrinkAcc a) (shrinkE i)+ Shape a -> Shape (shrinkAcc a)+ ShapeSize sh -> ShapeSize (shrinkE sh)+ Intersect sh sz -> Intersect (shrinkE sh) (shrinkE sz)+ Union sh sz -> Union (shrinkE sh) (shrinkE sz)+ Foreign ff f e -> Foreign ff (shrinkF f) (shrinkE e)+ Coerce e -> Coerce (shrinkE e)++ shrinkF :: OpenFun env aenv' f -> OpenFun env aenv' f+ shrinkF (Lam f) = Lam (shrinkF f)+ shrinkF (Body b) = Body (shrinkE b)++ shrinkT :: Tuple (OpenExp env aenv') t -> Tuple (OpenExp env aenv') t+ shrinkT NilTup = NilTup+ shrinkT (SnocTup t e) = shrinkT t `SnocTup` shrinkE e++ shrinkAF :: PreOpenAfun acc aenv' f -> PreOpenAfun acc aenv' f+ shrinkAF (Alam lhs f) = Alam lhs (shrinkAF f)+ shrinkAF (Abody a) = Abody (shrinkAcc a)+--}++-- Occurrence Counting+-- ===================++-- Count the number of occurrences an in-scope scalar expression bound at the+-- given variable index recursively in a term.+--+usesOfExp :: forall env aenv t. VarsRange env -> OpenExp env aenv t -> Count+usesOfExp range = countE+ where+ countE :: OpenExp env aenv e -> Count+ countE exp | matchEVarsRange range exp = Finite 1+ countE exp = case exp of+ Evar v -> case varInRange range v of+ Just cs -> Impossible cs+ Nothing -> Finite 0+ --+ Let lhs bnd body -> countE bnd <> usesOfExp (weakenVarsRange lhs range) body+ Const _ _ -> Finite 0+ Undef _ -> Finite 0+ Nil -> Finite 0+ Pair e1 e2 -> countE e1 <> countE e2+ VecPack _ e -> countE e+ VecUnpack _ e -> countE e+ IndexSlice _ ix sh -> countE ix <> countE sh+ IndexFull _ ix sl -> countE ix <> countE sl+ FromIndex _ sh i -> countE sh <> countE i+ ToIndex _ sh e -> countE sh <> countE e+ Case e rhs def -> countE e <> mconcat [ countE c | (_,c) <- rhs ] <> maybe (Finite 0) countE def+ Cond p t e -> countE p <> countE t <> countE e+ While p f x -> countE x <> loopCount (usesOfFun range p) <> loopCount (usesOfFun range f)+ PrimConst _ -> Finite 0+ PrimApp _ x -> countE x+ Index _ sh -> countE sh+ LinearIndex _ i -> countE i+ Shape _ -> Finite 0+ ShapeSize _ sh -> countE sh+ Foreign _ _ _ e -> countE e+ Coerce _ _ e -> countE e++usesOfFun :: VarsRange env -> OpenFun env aenv f -> Count+usesOfFun range (Lam lhs f) = usesOfFun (weakenVarsRange lhs range) f+usesOfFun range (Body b) = usesOfExp range b++-- Count the number of occurrences of the array term bound at the given+-- environment index. If the first argument is 'True' then it includes in the+-- total uses of the variable for 'Shape' information, otherwise not.+--+type UsesOfAcc acc = forall aenv s t. Bool -> Idx aenv s -> acc aenv t -> Int++-- XXX: Should this be converted to use the above 'Count' semigroup?+--+usesOfPreAcc+ :: forall acc aenv s t.+ Bool+ -> UsesOfAcc acc+ -> Idx aenv s+ -> PreOpenAcc acc aenv t+ -> Int+usesOfPreAcc withShape countAcc idx = count+ where+ countIdx :: Idx aenv a -> Int+ countIdx this+ | Just Refl <- matchIdx this idx = 1+ | otherwise = 0++ count :: PreOpenAcc acc aenv a -> Int+ count pacc = case pacc of+ Avar var -> countAvar var+ --+ Alet lhs bnd body -> countA bnd + countAcc withShape (weakenWithLHS lhs >:> idx) body+ Apair a1 a2 -> countA a1 + countA a2+ Anil -> 0+ Atrace _ a1 a2 -> countA a1 + countA a2+ Apply _ f a -> countAF f idx + countA a+ Aforeign _ _ _ a -> countA a+ Acond p t e -> countE p + countA t + countA e+ -- Body and condition of the while loop may be evaluated multiple times.+ -- We multiply the usage count, as a practical solution to this. As+ -- we will check whether the count is at most 1, we will thus never+ -- inline variables used in while loops.+ Awhile c f a -> 2 * countAF c idx + 2 * countAF f idx + countA a+ Use _ _ -> 0+ Unit _ e -> countE e+ Reshape _ e a -> countE e + countA a+ Generate _ e f -> countE e + countF f+ Transform _ sh ix f a -> countE sh + countF ix + countF f + countA a+ Replicate _ sh a -> countE sh + countA a+ Slice _ a sl -> countE sl + countA a+ Map _ f a -> countF f + countA a+ ZipWith _ f a1 a2 -> countF f + countA a1 + countA a2+ Fold f z a -> countF f + countME z + countA a+ FoldSeg _ f z a s -> countF f + countME z + countA a + countA s+ Scan _ f z a -> countF f + countME z + countA a+ Scan' _ f z a -> countF f + countE z + countA a+ Permute f1 a1 f2 a2 -> countF f1 + countA a1 + countF f2 + countA a2+ Backpermute _ sh f a -> countE sh + countF f + countA a+ Stencil _ _ f _ a -> countF f + countA a+ Stencil2 _ _ _ f _ a1 _ a2 -> countF f + countA a1 + countA a2+ -- Collect s -> countS s++ countE :: OpenExp env aenv e -> Int+ countE exp = case exp of+ Let _ bnd body -> countE bnd + countE body+ Evar _ -> 0+ Const _ _ -> 0+ Undef _ -> 0+ Nil -> 0+ Pair x y -> countE x + countE y+ VecPack _ e -> countE e+ VecUnpack _ e -> countE e+ IndexSlice _ ix sh -> countE ix + countE sh+ IndexFull _ ix sl -> countE ix + countE sl+ ToIndex _ sh ix -> countE sh + countE ix+ FromIndex _ sh i -> countE sh + countE i+ Case e rhs def -> countE e + sum [ countE c | (_,c) <- rhs ] + maybe 0 countE def+ Cond p t e -> countE p + countE t + countE e+ While p f x -> countF p + countF f + countE x+ PrimConst _ -> 0+ PrimApp _ x -> countE x+ Index a sh -> countAvar a + countE sh+ LinearIndex a i -> countAvar a + countE i+ ShapeSize _ sh -> countE sh+ Shape a+ | withShape -> countAvar a+ | otherwise -> 0+ Foreign _ _ _ e -> countE e+ Coerce _ _ e -> countE e++ countME :: Maybe (OpenExp env aenv e) -> Int+ countME = maybe 0 countE++ countA :: acc aenv a -> Int+ countA = countAcc withShape idx++ countAvar :: ArrayVar aenv a -> Int+ countAvar (Var _ this) = countIdx this++ countAF :: PreOpenAfun acc aenv' f+ -> Idx aenv' s+ -> Int+ countAF (Alam lhs f) v = countAF f (weakenWithLHS lhs >:> v)+ countAF (Abody a) v = countAcc withShape v a++ countF :: OpenFun env aenv f -> Int+ countF (Lam _ f) = countF f+ countF (Body b) = countE b++{--+ countS :: PreOpenSeq acc aenv senv arrs -> Int+ countS seq =+ case seq of+ Producer p s -> countP p + countS s+ Consumer c -> countC c+ Reify _ -> 0++ countP :: Producer acc aenv senv arrs -> Int+ countP p =+ case p of+ StreamIn _ -> 0+ ToSeq _ _ a -> countA a+ MapSeq f _ -> countAF f idx+ ChunkedMapSeq f _ -> countAF f idx+ ZipWithSeq f _ _ -> countAF f idx+ ScanSeq f e _ -> countF f + countE e++ countC :: Consumer acc aenv senv arrs -> Int+ countC c =+ case c of+ FoldSeq f e _ -> countF f + countE e+ FoldSeqFlatten f a _ -> countAF f idx + countA a+ Stuple t -> countCT t++ countCT :: Atuple (Consumer acc aenv senv) t' -> Int+ countCT NilAtup = 0+ countCT (SnocAtup t c) = countCT t + countC c+--}+
+ src/Data/Array/Accelerate/Trafo/Simplify.hs view
@@ -0,0 +1,686 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE ViewPatterns #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Trafo.Simplify+-- Copyright : [2012..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Trafo.Simplify (++ simplifyAfun,+ simplifyAcc,++ simplifyFun,+ simplifyExp++) where++import Data.Array.Accelerate.AST+import Data.Array.Accelerate.AST.Environment+import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.AST.LeftHandSide+import Data.Array.Accelerate.AST.Var+import Data.Array.Accelerate.Analysis.Hash+import Data.Array.Accelerate.Analysis.Match+import Data.Array.Accelerate.Error+import Data.Array.Accelerate.Representation.Array ( Array, ArrayR(..) )+import Data.Array.Accelerate.Representation.Shape ( ShapeR(..), shapeToList )+import Data.Array.Accelerate.Representation.Tag+import Data.Array.Accelerate.Trafo.Algebra+import Data.Array.Accelerate.Trafo.Environment+import Data.Array.Accelerate.Trafo.Shrink+import Data.Array.Accelerate.Trafo.Substitution+import Data.Array.Accelerate.Type++import qualified Data.Array.Accelerate.Debug.Internal.Stats as Stats+import qualified Data.Array.Accelerate.Debug.Internal.Flags as Debug+import qualified Data.Array.Accelerate.Debug.Internal.Trace as Debug++import Control.Applicative hiding ( Const )+import Data.List ( partition )+import Data.Maybe+import Data.Monoid+import Data.Text.Lazy.Builder+import Formatting+import Lens.Micro hiding ( ix )+import Prelude hiding ( exp, iterate )+import qualified Data.Map.Strict as Map+++-- Array simplification+-- ====================++simplifyAcc :: Acc a -> Acc a+simplifyAcc = simplifyOpenAcc++simplifyAfun :: Afun f -> Afun f+simplifyAfun = simplifyOpenAfun+++simplifyOpenAcc :: OpenAcc aenv a -> OpenAcc aenv a+simplifyOpenAcc (OpenAcc pacc) = OpenAcc (simplifyPreOpenAcc pacc)++simplifyOpenAfun :: PreOpenAfun OpenAcc aenv f -> PreOpenAfun OpenAcc aenv f+simplifyOpenAfun (Alam lhs f) = Alam lhs (simplifyOpenAfun f)+simplifyOpenAfun (Abody a) = Abody (simplifyOpenAcc a)++simplifyPreOpenAcc :: PreOpenAcc OpenAcc aenv a -> PreOpenAcc OpenAcc aenv a+simplifyPreOpenAcc = \case+ Alet lhs bnd body -> Alet lhs (simplifyOpenAcc bnd) (simplifyOpenAcc body)+ Avar var -> Avar var+ Apair a1 a2 -> Apair (simplifyOpenAcc a1) (simplifyOpenAcc a2)+ Anil -> Anil+ Atrace msg as bs -> Atrace msg (simplifyOpenAcc as) (simplifyOpenAcc bs)+ Apply repr f a -> Apply repr (simplifyOpenAfun f) (simplifyOpenAcc a)+ Aforeign repr asm f a -> Aforeign repr asm (simplifyOpenAfun f) (simplifyOpenAcc a)+ Acond e a1 a2 -> Acond (simplifyExp e) (simplifyOpenAcc a1) (simplifyOpenAcc a2)+ Awhile c f a -> Awhile (simplifyOpenAfun c) (simplifyOpenAfun f) (simplifyOpenAcc a)+ Use repr arr -> Use repr arr+ Unit eR e -> Unit eR (simplifyExp e)+ Reshape shr e a -> Reshape shr (simplifyExp e) (simplifyOpenAcc a)+ Generate repr e f -> Generate repr (simplifyExp e) (simplifyFun f)+ Transform repr sh f g a -> Transform repr (simplifyExp sh) (simplifyFun f) (simplifyFun g) (simplifyOpenAcc a)+ Replicate slix sl a -> Replicate slix (simplifyExp sl) (simplifyOpenAcc a)+ Slice slix a sl -> Slice slix (simplifyOpenAcc a) (simplifyExp sl)+ Map eR f a -> Map eR (simplifyFun f) (simplifyOpenAcc a)+ ZipWith eR f a1 a2 -> ZipWith eR (simplifyFun f) (simplifyOpenAcc a1) (simplifyOpenAcc a2)+ Fold f e a -> Fold (simplifyFun f) (fmap simplifyExp e) (simplifyOpenAcc a)+ FoldSeg iR f e a s -> FoldSeg iR (simplifyFun f) (fmap simplifyExp e) (simplifyOpenAcc a) (simplifyOpenAcc s)+ Scan d f e a -> Scan d (simplifyFun f) (fmap simplifyExp e) (simplifyOpenAcc a)+ Scan' d f e a -> Scan' d (simplifyFun f) (simplifyExp e) (simplifyOpenAcc a)+ Permute f a1 g a2 -> Permute (simplifyFun f) (simplifyOpenAcc a1) (simplifyFun g) (simplifyOpenAcc a2)+ Backpermute shr sh f a -> Backpermute shr (simplifyExp sh) (simplifyFun f) (simplifyOpenAcc a)+ Stencil s eR f b a -> Stencil s eR (simplifyFun f) b (simplifyOpenAcc a)+ Stencil2 s1 s2 eR f b1 a1 b2 a2 -> Stencil2 s1 s2 eR (simplifyFun f) b1 (simplifyOpenAcc a1) b2 (simplifyOpenAcc a2)+++-- Scalar optimisations+-- ====================++{--+-- Common subexpression elimination finds computations that are performed at+-- least twice on a given execution path and eliminates the second and later+-- occurrences, replacing them with uses of saved values. This implements a+-- simplified version of that idea, where we look for the expressions of the+-- form:+--+-- let x = e1 in e2+--+-- and replace all occurrences of e1 in e2 with x. This is not full redundancy+-- elimination, but good enough to catch some cases, and in particular those+-- likely to be introduced by scalar composition of terms in the fusion process.+--+-- While it may seem that common subexpression elimination is always worthwhile,+-- as it reduces the number of arithmetic operations performed, this is not+-- necessarily advantageous. The simplest case in which it may not be desirable+-- is if it causes a register to be occupied for a long time in order to hold+-- the shared expression's value, which hence reduces the number of registers+-- available for other uses. Even worse is if the value has to be spilled to+-- memory because there are insufficient registers available. We sidestep this+-- tricky and target-dependent issue by, for now, simply ignoring it.+--+localCSE :: (Kit acc, Elt a)+ => Gamma acc env env aenv+ -> OpenExp env aenv a+ -> OpenExp (env,a) aenv b+ -> Maybe (OpenExp env aenv b)+localCSE env bnd body+ | Just ix <- lookupExp env bnd = Stats.ruleFired "CSE" . Just $ inline body (Var ix)+ | otherwise = Nothing+--}+{--+-- Common subexpression elimination, which attempts to match the given+-- expression against something already bound in the environment. This can occur+-- due to simplification, in which case we replace the entire subterm with x.+--+-- > let x = e in .. e ..+--+globalCSE :: (Kit acc, Elt t)+ => Gamma acc env env aenv+ -> OpenExp env aenv t+ -> Maybe (OpenExp env aenv t)+globalCSE env exp+ | Just ix <- lookupExp env exp = Stats.ruleFired "CSE" . Just $ Var ix+ | otherwise = Nothing+--}++{--+-- Compared to regular Haskell, the scalar expression language of Accelerate is+-- rather limited in order to meet the restrictions of what can be efficiently+-- implemented on specialised hardware, such as GPUs. For example, to avoid+-- excessive SIMD divergence, we do not support any form of recursion or+-- iteration in scalar expressions. This harmonises well with the stratified+-- design of the Accelerate language: collective array operations comprise many+-- scalar computations that are executed in parallel, so for simplicity of+-- scheduling these operations we would like some assurance that each scalar+-- computation takes approximately the same time to execute as all others.+--+-- However, some computations are naturally expressed in terms of iteration. For+-- some problems, we can instead use generative techniques to implement the+-- program by defining a single step of a recurrence relation as an Accelerate+-- collective operation and using standard Haskell to unroll the loop a _fixed_+-- number of times.+--+-- However, this is outrageously slow because the intermediate values are+-- written to memory at the end of every iteration. Luckily the fusion process+-- will eliminate this intermediate memory traffic by combining the 'n'+-- collective operations into a single operation with 'n' instances of the loop+-- body. However, doing this we uncover an embarrassing secret: C compilers do+-- not compile C code, they compile _idiomatic_ C code.+--+-- This process recovers the iteration structure that was lost in the process of+-- fusing the collective operations. This allows a backend to generate explicit+-- loops in its target language.+--+recoverLoops+ :: (Kit acc, Elt b)+ => Gamma acc env env aenv+ -> OpenExp env aenv a+ -> OpenExp (env,a) aenv b+ -> Maybe (OpenExp env aenv b)+recoverLoops _ bnd e3+ -- To introduce scaler loops, we look for expressions of the form:+ --+ -- let x =+ -- let y = e1 in e2+ -- in e3+ --+ -- and if e2 and e3 are congruent, replace with:+ --+ -- iterate[2] (\y -> e2) e1+ --+ | Let e1 e2 <- bnd+ , Just Refl <- matchEnvTop e2 e3+ , Just Refl <- match e2 e3+ = Stats.ruleFired "loop recovery/intro" . Just+ $ Iterate (constant 2) e2 e1++ -- To merge expressions into a loop body, look for the pattern:+ --+ -- let x = iterate[n] f e1+ -- in e3+ --+ -- and if e3 matches the loop body, replace the let binding with the bare+ -- iteration with the trip count increased by one.+ --+ | Iterate n f e1 <- bnd+ , Just Refl <- match f e3+ = Stats.ruleFired "loop recovery/merge" . Just+ $ Iterate (constant 1 `plus` n) f e1++ | otherwise+ = Nothing++ where+ plus :: OpenExp env aenv Int -> OpenExp env aenv Int -> OpenExp env aenv Int+ plus x y = PrimApp (PrimAdd numType) $ Tuple $ NilTup `SnocTup` x `SnocTup` y++ constant :: Int -> OpenExp env aenv Int+ constant i = Const ((),i)++ matchEnvTop :: (Elt s, Elt t)+ => OpenExp (env,s) aenv f+ -> OpenExp (env,t) aenv g+ -> Maybe (s :=: t)+ matchEnvTop _ _ = gcast Refl+--}+++-- Walk a scalar expression applying simplifications to terms bottom-up.+--+-- TODO: Look for particular patterns of expressions that can be replaced by+-- something equivalent and simpler. In particular, indexing operations+-- introduced by the fusion transformation. This would benefit from a+-- rewrite rule schema.+--+-- TODO: We currently pass around an environment Gamma, but we do not use it.+-- It might be helpful to do some inlining if this enables other optimizations.+-- Eg, for `let x = -y in -x`, the inlining would allow us to shorten it to `y`.+-- If we do not want to do inlining, we should remove the environment here.+--+simplifyOpenExp+ :: forall env aenv e.+ Gamma env env aenv+ -> OpenExp env aenv e+ -> (Bool, OpenExp env aenv e)+simplifyOpenExp env = first getAny . cvtE+ where+ cvtE :: OpenExp env aenv t -> (Any, OpenExp env aenv t)+ cvtE exp = case exp of+ Let lhs bnd body -> (u <> v, exp')+ where+ (u, bnd') = cvtE bnd+ (v, exp') = cvtLet env lhs bnd' (\env' -> cvtE' env' body)+ Evar var -> pure $ Evar var+ Const tp c -> pure $ Const tp c+ Undef tp -> pure $ Undef tp+ Nil -> pure Nil+ Pair e1 e2 -> Pair <$> cvtE e1 <*> cvtE e2+ VecPack vec e -> VecPack vec <$> cvtE e+ VecUnpack vec e -> VecUnpack vec <$> cvtE e+ IndexSlice x ix sh -> IndexSlice x <$> cvtE ix <*> cvtE sh+ IndexFull x ix sl -> IndexFull x <$> cvtE ix <*> cvtE sl+ ToIndex shr sh ix -> toIndex shr (cvtE sh) (cvtE ix)+ FromIndex shr sh ix -> fromIndex shr (cvtE sh) (cvtE ix)+ Case e rhs def -> caseof (cvtE e) (sequenceA [ (t,) <$> cvtE c | (t,c) <- rhs ]) (cvtMaybeE def)+ Cond p t e -> cond (cvtE p) (cvtE t) (cvtE e)+ PrimConst c -> pure $ PrimConst c+ PrimApp f x -> (u<>v, fx)+ where+ (u, x') = cvtE x+ (v, fx) = evalPrimApp env f x'+ Index a sh -> Index a <$> cvtE sh+ LinearIndex a i -> LinearIndex a <$> cvtE i+ Shape a -> shape a+ ShapeSize shr sh -> shapeSize shr (cvtE sh)+ Foreign tp ff f e -> Foreign tp ff <$> first Any (simplifyOpenFun EmptyExp f) <*> cvtE e+ While p f x -> While <$> cvtF env p <*> cvtF env f <*> cvtE x+ Coerce t1 t2 e -> Coerce t1 t2 <$> cvtE e++ cvtE' :: Gamma env' env' aenv -> OpenExp env' aenv e' -> (Any, OpenExp env' aenv e')+ cvtE' env' = first Any . simplifyOpenExp env'++ cvtF :: Gamma env' env' aenv -> OpenFun env' aenv f -> (Any, OpenFun env' aenv f)+ cvtF env' = first Any . simplifyOpenFun env'++ cvtMaybeE :: Maybe (OpenExp env aenv e') -> (Any, Maybe (OpenExp env aenv e'))+ cvtMaybeE Nothing = pure Nothing+ cvtMaybeE (Just e) = Just <$> cvtE e++ cvtLet :: Gamma env' env' aenv+ -> ELeftHandSide bnd env' env''+ -> OpenExp env' aenv bnd+ -> (Gamma env'' env'' aenv -> (Any, OpenExp env'' aenv t))+ -> (Any, OpenExp env' aenv t)+ cvtLet env' lhs@(LeftHandSideSingle _) bnd body = Let lhs bnd <$> body (incExp $ env' `pushExp` bnd) -- Single variable on the LHS, add binding to the environment+ cvtLet env' (LeftHandSideWildcard _) _ body = body env' -- Binding not used, remove let binding+ cvtLet env' (LeftHandSidePair l1 l2) (Pair e1 e2) body -- Split binding to multiple bindings+ = first (const $ Any True)+ $ cvtLet env' l1 e1+ $ \env'' -> cvtLet env'' l2 (weakenE (weakenWithLHS l1) e2) body+ cvtLet env' lhs bnd body = Let lhs bnd <$> body (lhsExpr lhs env') -- Cannot split this binding.++ -- Simplify conditional expressions, in particular by eliminating branches+ -- when the predicate is a known constant.+ --+ cond :: (Any, OpenExp env aenv PrimBool)+ -> (Any, OpenExp env aenv t)+ -> (Any, OpenExp env aenv t)+ -> (Any, OpenExp env aenv t)+ cond p@(_,p') t@(_,t') e@(_,e')+ | Const _ 1 <- p' = Stats.knownBranch "True" (yes t')+ | Const _ 0 <- p' = Stats.knownBranch "False" (yes e')+ | Just Refl <- matchOpenExp t' e' = Stats.knownBranch "redundant" (yes e')+ | otherwise = Cond <$> p <*> t <*> e++ caseof :: (Any, OpenExp env aenv TAG)+ -> (Any, [(TAG, OpenExp env aenv b)])+ -> (Any, Maybe (OpenExp env aenv b))+ -> (Any, OpenExp env aenv b)+ caseof x@(_,x') xs@(_,xs') md@(_,md')+ | Const _ t <- x'+ = Stats.caseElim "known" (yes (fromJust $ lookup t xs'))+ | Just d <- md'+ , [] <- xs'+ = Stats.caseElim "redundant" (yes d)+ | Just d <- md'+ , [(_,(_,u))] <- us+ , Just Refl <- matchOpenExp d u+ = Stats.caseDefault "merge" $ yes (Case x' (map snd vs) (Just u))+ | Nothing <- md'+ , [] <- vs+ , [(_,(_,u))] <- us+ = Stats.caseElim "overlap" (yes u)+ | Nothing <- md'+ , [(_,(_,u))] <- us+ = Stats.caseDefault "introduction" $ yes (Case x' (map snd vs) (Just u))+ | otherwise+ = Case <$> x <*> xs <*> md+ where+ (us,vs) = partition (\(n,_) -> n > 1)+ $ Map.elems+ . Map.fromListWith merge+ $ [ (hashOpenExp e, (1,(t, e))) | (t,e) <- xs' ]++ merge :: (Int, (TAG, OpenExp env aenv b)) -> (Int, (TAG, OpenExp env aenv b)) -> (Int, (TAG, OpenExp env aenv b))+ merge (n,(_,a)) (m,(_,b))+ = internalCheck "hashOpenExp/collision" (maybe False (const True) (matchOpenExp a b))+ $ (n+m, (0xff, a))++ -- Shape manipulations+ --+ shape :: ArrayVar aenv (Array sh t) -> (Any, OpenExp env aenv sh)+ shape (Var (ArrayR ShapeRz _) _)+ = Stats.ruleFired "shape/Z" $ yes Nil+ shape a+ = pure $ Shape a++ shapeSize :: ShapeR sh -> (Any, OpenExp env aenv sh) -> (Any, OpenExp env aenv Int)+ shapeSize shr (_, sh)+ | Just c <- extractConstTuple sh+ = Stats.ruleFired "shapeSize/const" $ yes (Const scalarTypeInt (product (shapeToList shr c)))+ shapeSize shr sh+ = ShapeSize shr <$> sh++ toIndex :: ShapeR sh+ -> (Any, OpenExp env aenv sh)+ -> (Any, OpenExp env aenv sh)+ -> (Any, OpenExp env aenv Int)+ toIndex _ (_,sh) (_,FromIndex _ sh' ix)+ | Just Refl <- matchOpenExp sh sh' = Stats.ruleFired "toIndex/fromIndex" $ yes ix+ toIndex shr sh ix = ToIndex shr <$> sh <*> ix++ fromIndex :: ShapeR sh+ -> (Any, OpenExp env aenv sh)+ -> (Any, OpenExp env aenv Int)+ -> (Any, OpenExp env aenv sh)+ fromIndex _ (_,sh) (_,ToIndex _ sh' ix)+ | Just Refl <- matchOpenExp sh sh' = Stats.ruleFired "fromIndex/toIndex" $ yes ix+ fromIndex shr sh ix = FromIndex shr <$> sh <*> ix++ first :: (a -> a') -> (a,b) -> (a',b)+ first f (x,y) = (f x, y)++ yes :: x -> (Any, x)+ yes x = (Any True, x)++extractConstTuple :: OpenExp env aenv t -> Maybe t+extractConstTuple Nil = Just ()+extractConstTuple (Pair e1 e2) = (,) <$> extractConstTuple e1 <*> extractConstTuple e2+extractConstTuple (Const _ c) = Just c+extractConstTuple _ = Nothing++-- Simplification for open functions+--+simplifyOpenFun+ :: Gamma env env aenv+ -> OpenFun env aenv f+ -> (Bool, OpenFun env aenv f)+simplifyOpenFun env (Body e) = Body <$> simplifyOpenExp env e+simplifyOpenFun env (Lam lhs f) = Lam lhs <$> simplifyOpenFun env' f+ where+ env' = lhsExpr lhs env++lhsExpr :: ELeftHandSide t env env' -> Gamma env env aenv -> Gamma env' env' aenv+lhsExpr (LeftHandSideWildcard _) env = env+lhsExpr (LeftHandSideSingle tp) env = incExp env `pushExp` Evar (Var tp ZeroIdx)+lhsExpr (LeftHandSidePair l1 l2) env = lhsExpr l2 $ lhsExpr l1 env++-- Simplify closed expressions and functions. The process is applied+-- repeatedly until no more changes are made.+--+simplifyExp :: HasCallStack => Exp aenv t -> Exp aenv t+simplifyExp = iterate summariseOpenExp matchOpenExp shrinkExp (simplifyOpenExp EmptyExp)++simplifyFun :: HasCallStack => Fun aenv f -> Fun aenv f+simplifyFun = iterate summariseOpenFun matchOpenFun shrinkFun (simplifyOpenFun EmptyExp)+++-- NOTE: [Simplifier iterations]+--+-- Run the simplification pass _before_ the shrinking step. There are cases+-- where it is better to run shrinking first, and then simplification would+-- complete in a single step, but the converse is also true. However, as+-- shrinking can remove some structure of the let bindings, which might be+-- useful for the transformations (e.g. loop recovery) we want to maintain this+-- information for at least the first pass.+--+-- We always apply the simplification step once. Following this, we iterate+-- shrinking and simplification until the expression no longer changes. Both+-- shrink and simplify return a boolean indicating whether any work was done; we+-- stop as soon as either returns false.+--+-- With internal checks on, we also issue a warning if the iteration limit is+-- reached, but it was still possible to make changes to the expression.+--++iterate+ :: forall f a. HasCallStack+ => (f a -> Stats)+ -> (forall s t. f s -> f t -> Maybe (s :~: t)) -- match+ -> (f a -> (Bool, f a)) -- shrink+ -> (f a -> (Bool, f a)) -- simplify+ -> f a+ -> f a+iterate summarise match shrink simplify = fix 1 . setup+ where+ -- The maximum number of simplifier iterations. To be conservative and avoid+ -- excessive run times, we (should) set this value very low.+ --+ -- TODO: make this tunable via debug flags.+ --+ lIMIT = 25++ simplify' = Stats.simplifierDone . simplify+ setup x = Debug.trace Debug.dump_simpl_iterations (msg 0 "init" x)+ $ snd (trace 1 "simplify" (simplify' x))++ fix :: Int -> f a -> f a+ fix i x0+ | i > lIMIT = internalWarning "iteration limit reached" (not (x0 ==^ simplify x0)) x0+ | not shrunk = x1+ | not simplified = x2+ | otherwise = fix (i+1) x2+ where+ (shrunk, x1) = trace i "shrink" $ shrink x0+ (simplified, x2) = trace i "simplify" $ simplify' x1++ -- debugging support+ --+ u ==^ (_,v) = isJust (match u v)++ trace i s v@(changed,x)+ | changed = Debug.trace Debug.dump_simpl_iterations (msg i s x) v+ | otherwise = v++ msg :: Int -> Builder -> f a -> Builder+ msg i s x = bformat ("simpl-iters/" % rpadded 9 ' ' builder % squared int % ": " % builder) s i (ppr x)++ ppr :: f a -> Builder+ ppr = stats . summarise++ stats (Stats a b c d e) =+ bformat ("terms = " % int % ", types = " % int % ", lets = " % int % ", vars = " % int % ", primops = " % int) a b c d e+++-- Debugging support+-- -----------------++data Stats = Stats+ { _terms :: {-# UNPACK #-} !Int+ , _types :: {-# UNPACK #-} !Int+ , _binders :: {-# UNPACK #-} !Int+ , _vars :: {-# UNPACK #-} !Int+ , _ops :: {-# UNPACK #-} !Int+ }++instance Semigroup Stats where+ (<>) = (+++)++instance Monoid Stats where+ mempty = Stats 0 0 0 0 0++infixl 6 ++++(+++) :: Stats -> Stats -> Stats+Stats a1 b1 c1 d1 e1 +++ Stats a2 b2 c2 d2 e2 = Stats (a1+a2) (b1+b2) (c1+c2) (d1+d2) (e1+e2)+{-# INLINE (+++) #-}++terms, types, binders, vars, ops :: Lens' Stats Int+terms = lens _terms (\Stats{..} v -> Stats { _terms = v, ..})+types = lens _types (\Stats{..} v -> Stats { _types = v, ..})+binders = lens _binders (\Stats{..} v -> Stats { _binders = v, ..})+vars = lens _vars (\Stats{..} v -> Stats { _vars = v, ..})+ops = lens _ops (\Stats{..} v -> Stats { _ops = v, ..})+{-# INLINE terms #-}+{-# INLINE types #-}+{-# INLINE binders #-}+{-# INLINE vars #-}+{-# INLINE ops #-}++summariseOpenFun :: OpenFun env aenv f -> Stats+summariseOpenFun (Body e) = summariseOpenExp e & terms +~ 1+summariseOpenFun (Lam _ f) = summariseOpenFun f & terms +~ 1 & binders +~ 1++summariseOpenExp :: OpenExp env aenv t -> Stats+summariseOpenExp = (terms +~ 1) . goE+ where+ zero = Stats 0 0 0 0 0++ travE :: OpenExp env aenv t -> Stats+ travE = summariseOpenExp++ travF :: OpenFun env aenv t -> Stats+ travF = summariseOpenFun++ travA :: acc aenv a -> Stats+ travA _ = zero & vars +~ 1 -- assume an array index, else we should have failed elsewhere++ travC :: PrimConst c -> Stats+ travC (PrimMinBound t) = travBoundedType t & terms +~ 1+ travC (PrimMaxBound t) = travBoundedType t & terms +~ 1+ travC (PrimPi t) = travFloatingType t & terms +~ 1++ travIntegralType :: IntegralType t -> Stats+ travIntegralType _ = zero & types +~ 1++ travFloatingType :: FloatingType t -> Stats+ travFloatingType _ = zero & types +~ 1++ travNumType :: NumType t -> Stats+ travNumType (IntegralNumType t) = travIntegralType t & types +~ 1+ travNumType (FloatingNumType t) = travFloatingType t & types +~ 1++ travBoundedType :: BoundedType t -> Stats+ travBoundedType (IntegralBoundedType t) = travIntegralType t & types +~ 1++ -- travScalarType :: ScalarType t -> Stats+ -- travScalarType (SingleScalarType t) = travSingleType t & types +~ 1+ -- travScalarType (VectorScalarType t) = travVectorType t & types +~ 1++ travSingleType :: SingleType t -> Stats+ travSingleType (NumSingleType t) = travNumType t & types +~ 1++ -- travVectorType :: VectorType t -> Stats+ -- travVectorType (Vector2Type t) = travSingleType t & types +~ 1+ -- travVectorType (Vector3Type t) = travSingleType t & types +~ 1+ -- travVectorType (Vector4Type t) = travSingleType t & types +~ 1+ -- travVectorType (Vector8Type t) = travSingleType t & types +~ 1+ -- travVectorType (Vector16Type t) = travSingleType t & types +~ 1++ -- The scrutinee has already been counted+ goE :: OpenExp env aenv t -> Stats+ goE exp =+ case exp of+ Let _ bnd body -> travE bnd +++ travE body & binders +~ 1+ Evar{} -> zero & vars +~ 1+ Foreign _ _ _ x -> travE x & terms +~ 1 -- +1 for asm, ignore fallback impls.+ Const{} -> zero+ Undef _ -> zero+ Nil -> zero & terms +~ 1+ Pair e1 e2 -> travE e1 +++ travE e2 & terms +~ 1+ VecPack _ e -> travE e+ VecUnpack _ e -> travE e+ IndexSlice _ slix sh -> travE slix +++ travE sh & terms +~ 1 -- +1 for sliceIndex+ IndexFull _ slix sl -> travE slix +++ travE sl & terms +~ 1 -- +1 for sliceIndex+ ToIndex _ sh ix -> travE sh +++ travE ix+ FromIndex _ sh ix -> travE sh +++ travE ix+ Case e rhs def -> travE e +++ mconcat [ travE c | (_,c) <- rhs ] +++ maybe zero travE def+ Cond p t e -> travE p +++ travE t +++ travE e+ While p f x -> travF p +++ travF f +++ travE x+ PrimConst c -> travC c+ Index a ix -> travA a +++ travE ix+ LinearIndex a ix -> travA a +++ travE ix+ Shape a -> travA a+ ShapeSize _ sh -> travE sh+ PrimApp f x -> travPrimFun f +++ travE x+ Coerce _ _ e -> travE e++ travPrimFun :: PrimFun f -> Stats+ travPrimFun = (ops +~ 1) . goF+ where+ goF :: PrimFun f -> Stats+ goF fun =+ case fun of+ PrimAdd t -> travNumType t+ PrimSub t -> travNumType t+ PrimMul t -> travNumType t+ PrimNeg t -> travNumType t+ PrimAbs t -> travNumType t+ PrimSig t -> travNumType t+ PrimQuot t -> travIntegralType t+ PrimRem t -> travIntegralType t+ PrimQuotRem t -> travIntegralType t+ PrimIDiv t -> travIntegralType t+ PrimMod t -> travIntegralType t+ PrimDivMod t -> travIntegralType t+ PrimBAnd t -> travIntegralType t+ PrimBOr t -> travIntegralType t+ PrimBXor t -> travIntegralType t+ PrimBNot t -> travIntegralType t+ PrimBShiftL t -> travIntegralType t+ PrimBShiftR t -> travIntegralType t+ PrimBRotateL t -> travIntegralType t+ PrimBRotateR t -> travIntegralType t+ PrimPopCount t -> travIntegralType t+ PrimCountLeadingZeros t -> travIntegralType t+ PrimCountTrailingZeros t -> travIntegralType t+ PrimFDiv t -> travFloatingType t+ PrimRecip t -> travFloatingType t+ PrimSin t -> travFloatingType t+ PrimCos t -> travFloatingType t+ PrimTan t -> travFloatingType t+ PrimAsin t -> travFloatingType t+ PrimAcos t -> travFloatingType t+ PrimAtan t -> travFloatingType t+ PrimSinh t -> travFloatingType t+ PrimCosh t -> travFloatingType t+ PrimTanh t -> travFloatingType t+ PrimAsinh t -> travFloatingType t+ PrimAcosh t -> travFloatingType t+ PrimAtanh t -> travFloatingType t+ PrimExpFloating t -> travFloatingType t+ PrimSqrt t -> travFloatingType t+ PrimLog t -> travFloatingType t+ PrimFPow t -> travFloatingType t+ PrimLogBase t -> travFloatingType t+ PrimTruncate f i -> travFloatingType f +++ travIntegralType i+ PrimRound f i -> travFloatingType f +++ travIntegralType i+ PrimFloor f i -> travFloatingType f +++ travIntegralType i+ PrimCeiling f i -> travFloatingType f +++ travIntegralType i+ PrimIsNaN t -> travFloatingType t+ PrimIsInfinite t -> travFloatingType t+ PrimAtan2 t -> travFloatingType t+ PrimLt t -> travSingleType t+ PrimGt t -> travSingleType t+ PrimLtEq t -> travSingleType t+ PrimGtEq t -> travSingleType t+ PrimEq t -> travSingleType t+ PrimNEq t -> travSingleType t+ PrimMax t -> travSingleType t+ PrimMin t -> travSingleType t+ PrimLAnd -> zero+ PrimLOr -> zero+ PrimLNot -> zero+ PrimFromIntegral i n -> travIntegralType i +++ travNumType n+ PrimToFloating n f -> travNumType n +++ travFloatingType f+
+ src/Data/Array/Accelerate/Trafo/Substitution.hs view
@@ -0,0 +1,807 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE ViewPatterns #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Trafo.Substitution+-- Copyright : [2012..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Trafo.Substitution (++ -- ** Renaming & Substitution+ inline, inlineVars, compose,+ subTop, subAtop,++ -- ** Weakening+ (:>), Sink(..), SinkExp(..), weakenVars,++ -- ** Strengthening+ (:?>), strengthen, strengthenE,++ -- ** Rebuilding terms+ RebuildAcc, Rebuildable(..), RebuildableAcc,+ RebuildableExp(..), rebuildWeakenVar, rebuildLHS,+ OpenAccFun(..), OpenAccExp(..),++ -- ** Checks+ isIdentity, isIdentityIndexing, extractExpVars,+ bindingIsTrivial,++) where++import Data.Array.Accelerate.AST+import Data.Array.Accelerate.AST.LeftHandSide+import Data.Array.Accelerate.AST.Var+import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.AST.Environment+import Data.Array.Accelerate.Analysis.Match+import Data.Array.Accelerate.Error+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Representation.Array+import qualified Data.Array.Accelerate.Debug.Internal.Stats as Stats++import Data.Kind+import Control.Applicative hiding ( Const )+import Control.Monad+import Prelude hiding ( exp, seq )+++-- NOTE: [Renaming and Substitution]+--+-- To do things like renaming and substitution, we need some operation on+-- variables that we push structurally through terms, applying to each variable.+-- We have a type preserving but environment changing operation:+--+-- v :: forall t. Idx env t -> f env' aenv t+--+-- The crafty bit is that 'f' might represent variables (for renaming) or terms+-- (for substitutions). The demonic forall, --- which is to say that the+-- quantifier is in a position which gives us obligation, not opportunity ---+-- forces us to respect type: when pattern matching detects the variable we care+-- about, happily we discover that it has the type we must respect. The demon is+-- not so free to mess with us as one might fear at first.+--+-- We then lift this to an operation which traverses terms and rebuild them+-- after applying 'v' to the variables:+--+-- rebuildPartial v :: OpenExp env aenv t -> OpenExp env' aenv t+--+-- The Syntactic class tells us what we need to know about 'f' if we want to be+-- able to rebuildPartial terms. In essence, the crucial functionality is to propagate+-- a class of operations on variables that is closed under shifting.+--+infixr `compose`+-- infixr `substitute`++lhsFullVars :: forall s a env1 env2. LeftHandSide s a env1 env2 -> Maybe (Vars s env2 a)+lhsFullVars = fmap snd . go weakenId+ where+ go :: forall env env' b. (env' :> env2) -> LeftHandSide s b env env' -> Maybe (env :> env2, Vars s env2 b)+ go k (LeftHandSideWildcard TupRunit) = Just (k, TupRunit)+ go k (LeftHandSideSingle s) = Just $ (weakenSucc $ k, TupRsingle $ Var s $ k >:> ZeroIdx)+ go k (LeftHandSidePair l1 l2)+ | Just (k', v2) <- go k l2+ , Just (k'', v1) <- go k' l1 = Just (k'', TupRpair v1 v2)+ go _ _ = Nothing++bindingIsTrivial :: LeftHandSide s a env1 env2 -> Vars s env2 b -> Maybe (a :~: b)+bindingIsTrivial lhs vars+ | Just lhsVars <- lhsFullVars lhs+ , Just Refl <- matchVars vars lhsVars+ = Just Refl+bindingIsTrivial _ _ = Nothing++isIdentity :: OpenFun env aenv (a -> b) -> Maybe (a :~: b)+isIdentity (Lam lhs (Body (extractExpVars -> Just vars))) = bindingIsTrivial lhs vars+isIdentity _ = Nothing++-- Detects whether the function is of the form \ix -> a ! ix+isIdentityIndexing :: OpenFun env aenv (a -> b) -> Maybe (ArrayVar aenv (Array a b))+isIdentityIndexing (Lam lhs (Body body))+ | Index avar ix <- body+ , Just vars <- extractExpVars ix+ , Just Refl <- bindingIsTrivial lhs vars+ = Just avar+isIdentityIndexing _ = Nothing++-- | Replace the first variable with the given expression. The environment+-- shrinks.+--+inline :: OpenExp (env, s) aenv t+ -> OpenExp env aenv s+ -> OpenExp env aenv t+inline f g = Stats.substitution "inline" $ rebuildE (subTop g) f++inlineVars :: forall env env' aenv t1 t2.+ ELeftHandSide t1 env env'+ -> OpenExp env' aenv t2+ -> OpenExp env aenv t1+ -> Maybe (OpenExp env aenv t2)+inlineVars lhsBound expr bound+ | Just vars <- lhsFullVars lhsBound = substitute (strengthenWithLHS lhsBound) weakenId vars expr+ where+ substitute+ :: forall env1 env2 t.+ env1 :?> env2+ -> env :> env2+ -> ExpVars env1 t1+ -> OpenExp env1 aenv t+ -> Maybe (OpenExp env2 aenv t)+ substitute _ k2 vars (extractExpVars -> Just vars')+ | Just Refl <- matchVars vars vars' = Just $ weakenE k2 bound+ substitute k1 k2 vars topExp = case topExp of+ Let lhs e1 e2+ | Exists lhs' <- rebuildLHS lhs+ -> Let lhs' <$> travE e1 <*> substitute (strengthenAfter lhs lhs' k1) (weakenWithLHS lhs' .> k2) (weakenWithLHS lhs `weakenVars` vars) e2+ Evar (Var t ix) -> Evar . Var t <$> k1 ix+ Foreign tp asm f e1 -> Foreign tp asm f <$> travE e1+ Pair e1 e2 -> Pair <$> travE e1 <*> travE e2+ Nil -> Just Nil+ VecPack vec e1 -> VecPack vec <$> travE e1+ VecUnpack vec e1 -> VecUnpack vec <$> travE e1+ IndexSlice si e1 e2 -> IndexSlice si <$> travE e1 <*> travE e2+ IndexFull si e1 e2 -> IndexFull si <$> travE e1 <*> travE e2+ ToIndex shr e1 e2 -> ToIndex shr <$> travE e1 <*> travE e2+ FromIndex shr e1 e2 -> FromIndex shr <$> travE e1 <*> travE e2+ Case e1 rhs def -> Case <$> travE e1 <*> mapM (\(t,c) -> (t,) <$> travE c) rhs <*> travMaybeE def+ Cond e1 e2 e3 -> Cond <$> travE e1 <*> travE e2 <*> travE e3+ While f1 f2 e1 -> While <$> travF f1 <*> travF f2 <*> travE e1+ Const t c -> Just $ Const t c+ PrimConst c -> Just $ PrimConst c+ PrimApp p e1 -> PrimApp p <$> travE e1+ Index a e1 -> Index a <$> travE e1+ LinearIndex a e1 -> LinearIndex a <$> travE e1+ Shape a -> Just $ Shape a+ ShapeSize shr e1 -> ShapeSize shr <$> travE e1+ Undef t -> Just $ Undef t+ Coerce t1 t2 e1 -> Coerce t1 t2 <$> travE e1++ where+ travE :: OpenExp env1 aenv s -> Maybe (OpenExp env2 aenv s)+ travE = substitute k1 k2 vars++ travF :: OpenFun env1 aenv s -> Maybe (OpenFun env2 aenv s)+ travF = substituteF k1 k2 vars++ travMaybeE :: Maybe (OpenExp env1 aenv s) -> Maybe (Maybe (OpenExp env2 aenv s))+ travMaybeE Nothing = pure Nothing+ travMaybeE (Just x) = Just <$> travE x++ substituteF :: forall env1 env2 t.+ env1 :?> env2+ -> env :> env2+ -> ExpVars env1 t1+ -> OpenFun env1 aenv t+ -> Maybe (OpenFun env2 aenv t)+ substituteF k1 k2 vars (Body e) = Body <$> substitute k1 k2 vars e+ substituteF k1 k2 vars (Lam lhs f)+ | Exists lhs' <- rebuildLHS lhs = Lam lhs' <$> substituteF (strengthenAfter lhs lhs' k1) (weakenWithLHS lhs' .> k2) (weakenWithLHS lhs `weakenVars` vars) f++inlineVars _ _ _ = Nothing+++-- | Replace an expression that uses the top environment variable with another.+-- The result of the first is let bound into the second.+--+{- substitute' :: OpenExp (env, b) aenv c+ -> OpenExp (env, a) aenv b+ -> OpenExp (env, a) aenv c+substitute' f g+ | Stats.substitution "substitute" False = undefined+ | isIdentity f = g -- don't rebind an identity function+ | isIdentity g = f+ | otherwise = Let g $ rebuildE split f+ where+ split :: Idx (env,b) c -> OpenExp ((env,a),b) aenv c+ split ZeroIdx = Var ZeroIdx+ split (SuccIdx ix) = Var (SuccIdx (SuccIdx ix))++substitute :: LeftHandSide b env envb+ -> OpenExp envb c+ -> LeftHandSide a env enva+ -> OpenExp enva b+-}++-- | Composition of unary functions.+--+compose :: HasCallStack+ => OpenFun env aenv (b -> c)+ -> OpenFun env aenv (a -> b)+ -> OpenFun env aenv (a -> c)+compose f@(Lam lhsB (Body c)) g@(Lam lhsA (Body b))+ | Stats.substitution "compose" False = undefined+ | Just Refl <- isIdentity f = g -- don't rebind an identity function+ | Just Refl <- isIdentity g = f++ | Exists lhsB' <- rebuildLHS lhsB+ = Lam lhsA+ $ Body+ $ Let lhsB' b+ $ weakenE (sinkWithLHS lhsB lhsB' $ weakenWithLHS lhsA) c+ -- = Stats.substitution "compose" . Lam lhs2 . Body $ substitute' f g+compose _+ _ = error "compose: impossible evaluation"++subTop :: OpenExp env aenv s -> ExpVar (env, s) t -> OpenExp env aenv t+subTop s (Var _ ZeroIdx ) = s+subTop _ (Var tp (SuccIdx ix)) = Evar $ Var tp ix++subAtop :: PreOpenAcc acc aenv t -> ArrayVar (aenv, t) (Array sh2 e2) -> PreOpenAcc acc aenv (Array sh2 e2)+subAtop t (Var _ ZeroIdx ) = t+subAtop _ (Var repr (SuccIdx idx)) = Avar $ Var repr idx++data Identity a = Identity { runIdentity :: a }++instance Functor Identity where+ {-# INLINE fmap #-}+ fmap f (Identity a) = Identity (f a)++instance Applicative Identity where+ {-# INLINE (<*>) #-}+ {-# INLINE pure #-}+ Identity f <*> Identity a = Identity (f a)+ pure a = Identity a++-- A class for rebuilding terms.+--+class Rebuildable f where+ {-# MINIMAL rebuildPartial #-}+ type AccClo f :: Type -> Type -> Type++ rebuildPartial :: (Applicative f', SyntacticAcc fa)+ => (forall sh e. ArrayVar aenv (Array sh e) -> f' (fa (AccClo f) aenv' (Array sh e)))+ -> f aenv a+ -> f' (f aenv' a)++ {-# INLINEABLE rebuildA #-}+ rebuildA :: (SyntacticAcc fa)+ => (forall sh e. ArrayVar aenv (Array sh e) -> fa (AccClo f) aenv' (Array sh e))+ -> f aenv a+ -> f aenv' a+ rebuildA av = runIdentity . rebuildPartial (Identity . av)++-- A class for rebuilding scalar terms.+--+class RebuildableExp f where+ {-# MINIMAL rebuildPartialE #-}+ rebuildPartialE :: (Applicative f', SyntacticExp fe)+ => (forall e'. ExpVar env e' -> f' (fe env' aenv e'))+ -> f env aenv e+ -> f' (f env' aenv e)++ {-# INLINEABLE rebuildE #-}+ rebuildE :: SyntacticExp fe+ => (forall e'. ExpVar env e' -> fe env' aenv e')+ -> f env aenv e+ -> f env' aenv e+ rebuildE v = runIdentity . rebuildPartialE (Identity . v)++-- Terms that are rebuildable and also recursive closures+--+type RebuildableAcc acc = (Rebuildable acc, AccClo acc ~ acc)++-- Wrappers which add the 'acc' type argument+--+data OpenAccExp (acc :: Type -> Type -> Type) env aenv a where+ OpenAccExp :: { unOpenAccExp :: OpenExp env aenv a } -> OpenAccExp acc env aenv a++data OpenAccFun (acc :: Type -> Type -> Type) env aenv a where+ OpenAccFun :: { unOpenAccFun :: OpenFun env aenv a } -> OpenAccFun acc env aenv a++-- We can use the same plumbing to rebuildPartial all the things we want to rebuild.+--+instance Rebuildable (OpenAccExp acc env) where+ type AccClo (OpenAccExp acc env) = acc+ {-# INLINEABLE rebuildPartial #-}+ rebuildPartial v (OpenAccExp e) = OpenAccExp <$> Stats.substitution "rebuild" (rebuildOpenExp (pure . IE) (reindexAvar v) e)++instance Rebuildable (OpenAccFun acc env) where+ type AccClo (OpenAccFun acc env) = acc+ {-# INLINEABLE rebuildPartial #-}+ rebuildPartial v (OpenAccFun f) = OpenAccFun <$> Stats.substitution "rebuild" (rebuildFun (pure . IE) (reindexAvar v) f)++instance RebuildableAcc acc => Rebuildable (PreOpenAcc acc) where+ type AccClo (PreOpenAcc acc) = acc+ {-# INLINEABLE rebuildPartial #-}+ rebuildPartial x = Stats.substitution "rebuild" $ rebuildPreOpenAcc rebuildPartial x++instance RebuildableAcc acc => Rebuildable (PreOpenAfun acc) where+ type AccClo (PreOpenAfun acc) = acc+ {-# INLINEABLE rebuildPartial #-}+ rebuildPartial x = Stats.substitution "rebuild" $ rebuildAfun rebuildPartial x++instance Rebuildable OpenAcc where+ type AccClo OpenAcc = OpenAcc+ {-# INLINEABLE rebuildPartial #-}+ rebuildPartial x = Stats.substitution "rebuild" $ rebuildOpenAcc x++instance RebuildableExp OpenExp where+ {-# INLINEABLE rebuildPartialE #-}+ rebuildPartialE v x = Stats.substitution "rebuild" $ rebuildOpenExp v (ReindexAvar pure) x++instance RebuildableExp OpenFun where+ {-# INLINEABLE rebuildPartialE #-}+ rebuildPartialE v x = Stats.substitution "rebuild" $ rebuildFun v (ReindexAvar pure) x++-- NOTE: [Weakening]+--+-- Weakening is something we usually take for granted: every time you learn a+-- new word, old sentences still make sense. If a conclusion is justified by a+-- hypothesis, it is still justified if you add more hypotheses. Similarly, a+-- term remains in scope if you bind more (fresh) variables. Weakening is the+-- operation of shifting things from one scope to a larger scope in which new+-- things have become meaningful, but no old things have vanished.+--+-- When we use a named representation (or HOAS) we get weakening for free. But+-- in the de Bruijn representation weakening takes work: you have to shift all+-- variable references to make room for the new bindings.+--++class Sink f where+ weaken :: env :> env' -> forall t. f env t -> f env' t++ -- TLM: We can't use this default instance because it doesn't lead to+ -- specialised code. Perhaps the INLINEABLE pragma is ignored: GHC bug?+ --+ -- {-# INLINEABLE weaken #-}+ -- default weaken :: Rebuildable f => env :> env' -> f env t -> f env' t+ -- weaken k = Stats.substitution "weaken" . rebuildA rebuildWeakenVar++--instance Rebuildable f => Sink f where -- undecidable, incoherent+-- weaken k = Stats.substitution "weaken" . rebuildA rebuildWeakenVar++instance Sink Idx where+ {-# INLINEABLE weaken #-}+ weaken = (>:>)++instance Sink (Var s) where+ {-# INLINEABLE weaken #-}+ weaken k (Var s ix) = Var s (k >:> ix)++weakenVars :: env :> env' -> Vars s env t -> Vars s env' t+weakenVars _ TupRunit = TupRunit+weakenVars k (TupRsingle v) = TupRsingle $ weaken k v+weakenVars k (TupRpair v w) = TupRpair (weakenVars k v) (weakenVars k w)++rebuildWeakenVar :: env :> env' -> ArrayVar env (Array sh e) -> PreOpenAcc acc env' (Array sh e)+rebuildWeakenVar k (Var s idx) = Avar $ Var s $ k >:> idx++rebuildWeakenEvar :: env :> env' -> ExpVar env t -> OpenExp env' aenv t+rebuildWeakenEvar k (Var s idx) = Evar $ Var s $ k >:> idx++instance RebuildableAcc acc => Sink (PreOpenAcc acc) where+ {-# INLINEABLE weaken #-}+ weaken k = Stats.substitution "weaken" . rebuildA (rebuildWeakenVar k)++instance RebuildableAcc acc => Sink (PreOpenAfun acc) where+ {-# INLINEABLE weaken #-}+ weaken k = Stats.substitution "weaken" . rebuildA (rebuildWeakenVar k)++instance Sink (OpenExp env) where+ {-# INLINEABLE weaken #-}+ weaken k = Stats.substitution "weaken" . runIdentity . rebuildOpenExp (Identity . Evar) (ReindexAvar (Identity . weaken k))++instance Sink (OpenFun env) where+ {-# INLINEABLE weaken #-}+ weaken k = Stats.substitution "weaken" . runIdentity . rebuildFun (Identity . Evar) (ReindexAvar (Identity . weaken k))++instance Sink Boundary where+ {-# INLINEABLE weaken #-}+ weaken k bndy =+ case bndy of+ Clamp -> Clamp+ Mirror -> Mirror+ Wrap -> Wrap+ Constant c -> Constant c+ Function f -> Function (weaken k f)++instance Sink OpenAcc where+ {-# INLINEABLE weaken #-}+ weaken k = Stats.substitution "weaken" . rebuildA (rebuildWeakenVar k)++-- This rewrite rule is disabled because 'weaken' is now part of a type class.+-- As such, we cannot attach a NOINLINE pragma because it has many definitions.+-- {-# RULES+-- "weaken/weaken" forall a (v1 :: env' :> env'') (v2 :: env :> env').+-- weaken v1 (weaken v2 a) = weaken (v1 . v2) a+-- #-}++class SinkExp f where+ weakenE :: env :> env' -> f env aenv t -> f env' aenv t++ -- See comment in 'weaken'+ --+ -- {-# INLINEABLE weakenE #-}+ -- default weakenE :: RebuildableExp f => env :> env' -> f env aenv t -> f env' aenv t+ -- weakenE v = Stats.substitution "weakenE" . rebuildE (IE . v)++instance SinkExp OpenExp where+ {-# INLINEABLE weakenE #-}+ weakenE v = Stats.substitution "weakenE" . rebuildE (rebuildWeakenEvar v)++instance SinkExp OpenFun where+ {-# INLINEABLE weakenE #-}+ weakenE v = Stats.substitution "weakenE" . rebuildE (rebuildWeakenEvar v)++-- See above for why this is disabled.+-- {-# RULES+-- "weakenE/weakenE" forall a (v1 :: env' :> env'') (v2 :: env :> env').+-- weakenE v1 (weakenE v2 a) = weakenE (v1 . v2) a+-- #-}++-- NOTE: [Strengthening]+--+-- Strengthening is the dual of weakening. Shifting terms from one scope to a+-- smaller scope. Of course this is not always possible. If the term contains+-- any variables not in the new environment, then it cannot be strengthened.+-- This partial behaviour is captured with 'Maybe'.+--++-- The type of partially shifting terms from one context into another.+type env :?> env' = forall t'. Idx env t' -> Maybe (Idx env' t')++{-# INLINEABLE strengthen #-}+strengthen :: forall f env env' t. Rebuildable f => env :?> env' -> f env t -> Maybe (f env' t)+strengthen k x = Stats.substitution "strengthen" $ rebuildPartial @f @Maybe @IdxA (\(Var s ix) -> fmap (IA . Var s) $ k ix) x++{-# INLINEABLE strengthenE #-}+strengthenE :: forall f env env' aenv t. RebuildableExp f => env :?> env' -> f env aenv t -> Maybe (f env' aenv t)+strengthenE k x = Stats.substitution "strengthenE" $ rebuildPartialE @f @Maybe @IdxE (\(Var tp ix) -> fmap (IE . Var tp) $ k ix) x++strengthenWithLHS :: LeftHandSide s t env1 env2 -> env2 :?> env1+strengthenWithLHS (LeftHandSideWildcard _) = Just+strengthenWithLHS (LeftHandSideSingle _) = \ix -> case ix of+ ZeroIdx -> Nothing+ SuccIdx i -> Just i+strengthenWithLHS (LeftHandSidePair l1 l2) = strengthenWithLHS l2 >=> strengthenWithLHS l1++strengthenAfter :: LeftHandSide s t env1 env2 -> LeftHandSide s t env1' env2' -> env1 :?> env1' -> env2 :?> env2'+strengthenAfter (LeftHandSideWildcard _) (LeftHandSideWildcard _) k = k+strengthenAfter (LeftHandSideSingle _) (LeftHandSideSingle _) k = \ix -> case ix of+ ZeroIdx -> Just ZeroIdx+ SuccIdx i -> SuccIdx <$> k i+strengthenAfter (LeftHandSidePair l1 l2) (LeftHandSidePair l1' l2') k =+ strengthenAfter l2 l2' $ strengthenAfter l1 l1' k+strengthenAfter _ _ _ = error "Substitution.strengthenAfter: left hand sides do not match"++-- Simultaneous Substitution ===================================================+--++-- The scalar environment+-- ------------------++-- SEE: [Renaming and Substitution]+-- SEE: [Weakening]+--+class SyntacticExp f where+ varIn :: ExpVar env t -> f env aenv t+ expOut :: f env aenv t -> OpenExp env aenv t+ weakenExp :: f env aenv t -> f (env, s) aenv t++newtype IdxE env aenv t = IE { unIE :: ExpVar env t }++instance SyntacticExp IdxE where+ varIn = IE+ expOut = Evar . unIE+ weakenExp (IE (Var tp ix)) = IE $ Var tp $ SuccIdx ix++instance SyntacticExp OpenExp where+ varIn = Evar+ expOut = id+ weakenExp = runIdentity . rebuildOpenExp (Identity . weakenExp . IE) (ReindexAvar Identity)++{-# INLINEABLE shiftE #-}+shiftE+ :: (Applicative f, SyntacticExp fe)+ => RebuildEvar f fe env env' aenv+ -> RebuildEvar f fe (env, s) (env', s) aenv+shiftE _ (Var tp ZeroIdx) = pure $ varIn (Var tp ZeroIdx)+shiftE v (Var tp (SuccIdx ix)) = weakenExp <$> v (Var tp ix)++{-# INLINEABLE shiftE' #-}+shiftE'+ :: (Applicative f, SyntacticExp fa)+ => ELeftHandSide t env1 env1'+ -> ELeftHandSide t env2 env2'+ -> RebuildEvar f fa env1 env2 aenv+ -> RebuildEvar f fa env1' env2' aenv+shiftE' (LeftHandSideWildcard _) (LeftHandSideWildcard _) v = v+shiftE' (LeftHandSideSingle _) (LeftHandSideSingle _) v = shiftE v+shiftE' (LeftHandSidePair a1 b1) (LeftHandSidePair a2 b2) v = shiftE' b1 b2 $ shiftE' a1 a2 v+shiftE' _ _ _ = error "Substitution: left hand sides do not match"++{-# INLINEABLE rebuildMaybeExp #-}+rebuildMaybeExp+ :: (HasCallStack, Applicative f, SyntacticExp fe)+ => RebuildEvar f fe env env' aenv'+ -> ReindexAvar f aenv aenv'+ -> Maybe (OpenExp env aenv t)+ -> f (Maybe (OpenExp env' aenv' t))+rebuildMaybeExp _ _ Nothing = pure Nothing+rebuildMaybeExp v av (Just x) = Just <$> rebuildOpenExp v av x++{-# INLINEABLE rebuildOpenExp #-}+rebuildOpenExp+ :: (HasCallStack, Applicative f, SyntacticExp fe)+ => RebuildEvar f fe env env' aenv'+ -> ReindexAvar f aenv aenv'+ -> OpenExp env aenv t+ -> f (OpenExp env' aenv' t)+rebuildOpenExp v av@(ReindexAvar reindex) exp =+ case exp of+ Const t c -> pure $ Const t c+ PrimConst c -> pure $ PrimConst c+ Undef t -> pure $ Undef t+ Evar var -> expOut <$> v var+ Let lhs a b+ | Exists lhs' <- rebuildLHS lhs+ -> Let lhs' <$> rebuildOpenExp v av a <*> rebuildOpenExp (shiftE' lhs lhs' v) av b+ Pair e1 e2 -> Pair <$> rebuildOpenExp v av e1 <*> rebuildOpenExp v av e2+ Nil -> pure Nil+ VecPack vec e -> VecPack vec <$> rebuildOpenExp v av e+ VecUnpack vec e -> VecUnpack vec <$> rebuildOpenExp v av e+ IndexSlice x ix sh -> IndexSlice x <$> rebuildOpenExp v av ix <*> rebuildOpenExp v av sh+ IndexFull x ix sl -> IndexFull x <$> rebuildOpenExp v av ix <*> rebuildOpenExp v av sl+ ToIndex shr sh ix -> ToIndex shr <$> rebuildOpenExp v av sh <*> rebuildOpenExp v av ix+ FromIndex shr sh ix -> FromIndex shr <$> rebuildOpenExp v av sh <*> rebuildOpenExp v av ix+ Case e rhs def -> Case <$> rebuildOpenExp v av e <*> sequenceA [ (t,) <$> rebuildOpenExp v av c | (t,c) <- rhs ] <*> rebuildMaybeExp v av def+ Cond p t e -> Cond <$> rebuildOpenExp v av p <*> rebuildOpenExp v av t <*> rebuildOpenExp v av e+ While p f x -> While <$> rebuildFun v av p <*> rebuildFun v av f <*> rebuildOpenExp v av x+ PrimApp f x -> PrimApp f <$> rebuildOpenExp v av x+ Index a sh -> Index <$> reindex a <*> rebuildOpenExp v av sh+ LinearIndex a i -> LinearIndex <$> reindex a <*> rebuildOpenExp v av i+ Shape a -> Shape <$> reindex a+ ShapeSize shr sh -> ShapeSize shr <$> rebuildOpenExp v av sh+ Foreign tp ff f e -> Foreign tp ff f <$> rebuildOpenExp v av e+ Coerce t1 t2 e -> Coerce t1 t2 <$> rebuildOpenExp v av e++{-# INLINEABLE rebuildFun #-}+rebuildFun+ :: (HasCallStack, Applicative f, SyntacticExp fe)+ => RebuildEvar f fe env env' aenv'+ -> ReindexAvar f aenv aenv'+ -> OpenFun env aenv t+ -> f (OpenFun env' aenv' t)+rebuildFun v av fun =+ case fun of+ Body e -> Body <$> rebuildOpenExp v av e+ Lam lhs f+ | Exists lhs' <- rebuildLHS lhs+ -> Lam lhs' <$> rebuildFun (shiftE' lhs lhs' v) av f++-- The array environment+-- -----------------++type RebuildAcc acc =+ forall aenv aenv' f fa a. (HasCallStack, Applicative f, SyntacticAcc fa)+ => RebuildAvar f fa acc aenv aenv'+ -> acc aenv a+ -> f (acc aenv' a)++newtype IdxA (acc :: Type -> Type -> Type) aenv t = IA { unIA :: ArrayVar aenv t }++class SyntacticAcc f where+ avarIn :: ArrayVar aenv (Array sh e) -> f acc aenv (Array sh e)+ accOut :: f acc aenv (Array sh e) -> PreOpenAcc acc aenv (Array sh e)+ weakenAcc :: RebuildAcc acc -> f acc aenv (Array sh e) -> f acc (aenv, s) (Array sh e)++instance SyntacticAcc IdxA where+ avarIn = IA+ accOut = Avar . unIA+ weakenAcc _ (IA (Var s idx)) = IA $ Var s $ SuccIdx idx++instance SyntacticAcc PreOpenAcc where+ avarIn = Avar+ accOut = id+ weakenAcc k = runIdentity . rebuildPreOpenAcc k (Identity . weakenAcc k . IA)++type RebuildAvar f (fa :: (Type -> Type -> Type) -> Type -> Type -> Type) acc aenv aenv'+ = forall sh e. ArrayVar aenv (Array sh e) -> f (fa acc aenv' (Array sh e))++type RebuildEvar f fe env env' aenv' =+ forall t'. ExpVar env t' -> f (fe env' aenv' t')++newtype ReindexAvar f aenv aenv' =+ ReindexAvar (forall sh e. ArrayVar aenv (Array sh e) -> f (ArrayVar aenv' (Array sh e)))++reindexAvar+ :: forall f fa acc aenv aenv'.+ (HasCallStack, Applicative f, SyntacticAcc fa)+ => RebuildAvar f fa acc aenv aenv'+ -> ReindexAvar f aenv aenv'+reindexAvar v = ReindexAvar f where+ f :: forall sh e. ArrayVar aenv (Array sh e) -> f (ArrayVar aenv' (Array sh e))+ f var = g <$> v var++ g :: fa acc aenv' (Array sh e) -> ArrayVar aenv' (Array sh e)+ g fa = case accOut fa of+ Avar var' -> var'+ _ -> internalError "An Avar which was used in an Exp was mapped to an array term other than Avar. This mapping is invalid as an Exp can only contain array variables."+++{-# INLINEABLE shiftA #-}+shiftA+ :: (HasCallStack, Applicative f, SyntacticAcc fa)+ => RebuildAcc acc+ -> RebuildAvar f fa acc aenv aenv'+ -> ArrayVar (aenv, s) (Array sh e)+ -> f (fa acc (aenv', s) (Array sh e))+shiftA _ _ (Var s ZeroIdx) = pure $ avarIn $ Var s ZeroIdx+shiftA k v (Var s (SuccIdx ix)) = weakenAcc k <$> v (Var s ix)++shiftA'+ :: (HasCallStack, Applicative f, SyntacticAcc fa)+ => ALeftHandSide t aenv1 aenv1'+ -> ALeftHandSide t aenv2 aenv2'+ -> RebuildAcc acc+ -> RebuildAvar f fa acc aenv1 aenv2+ -> RebuildAvar f fa acc aenv1' aenv2'+shiftA' (LeftHandSideWildcard _) (LeftHandSideWildcard _) _ v = v+shiftA' (LeftHandSideSingle _) (LeftHandSideSingle _) k v = shiftA k v+shiftA' (LeftHandSidePair a1 b1) (LeftHandSidePair a2 b2) k v = shiftA' b1 b2 k $ shiftA' a1 a2 k v+shiftA' _ _ _ _ = internalError "left hand sides do not match"++{-# INLINEABLE rebuildOpenAcc #-}+rebuildOpenAcc+ :: (HasCallStack, Applicative f, SyntacticAcc fa)+ => (forall sh e. ArrayVar aenv (Array sh e) -> f (fa OpenAcc aenv' (Array sh e)))+ -> OpenAcc aenv t+ -> f (OpenAcc aenv' t)+rebuildOpenAcc av (OpenAcc acc) = OpenAcc <$> rebuildPreOpenAcc rebuildOpenAcc av acc++{-# INLINEABLE rebuildPreOpenAcc #-}+rebuildPreOpenAcc+ :: (HasCallStack, Applicative f, SyntacticAcc fa)+ => RebuildAcc acc+ -> RebuildAvar f fa acc aenv aenv'+ -> PreOpenAcc acc aenv t+ -> f (PreOpenAcc acc aenv' t)+rebuildPreOpenAcc k av acc =+ case acc of+ Use repr a -> pure $ Use repr a+ Alet lhs a b -> rebuildAlet k av lhs a b+ Avar ix -> accOut <$> av ix+ Apair as bs -> Apair <$> k av as <*> k av bs+ Anil -> pure Anil+ Atrace msg as bs -> Atrace msg <$> k av as <*> k av bs+ Apply repr f a -> Apply repr <$> rebuildAfun k av f <*> k av a+ Acond p t e -> Acond <$> rebuildOpenExp (pure . IE) av' p <*> k av t <*> k av e+ Awhile p f a -> Awhile <$> rebuildAfun k av p <*> rebuildAfun k av f <*> k av a+ Unit tp e -> Unit tp <$> rebuildOpenExp (pure . IE) av' e+ Reshape shr e a -> Reshape shr <$> rebuildOpenExp (pure . IE) av' e <*> k av a+ Generate repr e f -> Generate repr <$> rebuildOpenExp (pure . IE) av' e <*> rebuildFun (pure . IE) av' f+ Transform repr sh ix f a -> Transform repr <$> rebuildOpenExp (pure . IE) av' sh <*> rebuildFun (pure . IE) av' ix <*> rebuildFun (pure . IE) av' f <*> k av a+ Replicate sl slix a -> Replicate sl <$> rebuildOpenExp (pure . IE) av' slix <*> k av a+ Slice sl a slix -> Slice sl <$> k av a <*> rebuildOpenExp (pure . IE) av' slix+ Map tp f a -> Map tp <$> rebuildFun (pure . IE) av' f <*> k av a+ ZipWith tp f a1 a2 -> ZipWith tp <$> rebuildFun (pure . IE) av' f <*> k av a1 <*> k av a2+ Fold f z a -> Fold <$> rebuildFun (pure . IE) av' f <*> rebuildMaybeExp (pure . IE) av' z <*> k av a+ FoldSeg itp f z a s -> FoldSeg itp <$> rebuildFun (pure . IE) av' f <*> rebuildMaybeExp (pure . IE) av' z <*> k av a <*> k av s+ Scan d f z a -> Scan d <$> rebuildFun (pure . IE) av' f <*> rebuildMaybeExp (pure . IE) av' z <*> k av a+ Scan' d f z a -> Scan' d <$> rebuildFun (pure . IE) av' f <*> rebuildOpenExp (pure . IE) av' z <*> k av a+ Permute f1 a1 f2 a2 -> Permute <$> rebuildFun (pure . IE) av' f1 <*> k av a1 <*> rebuildFun (pure . IE) av' f2 <*> k av a2+ Backpermute shr sh f a -> Backpermute shr <$> rebuildOpenExp (pure . IE) av' sh <*> rebuildFun (pure . IE) av' f <*> k av a+ Stencil sr tp f b a -> Stencil sr tp <$> rebuildFun (pure . IE) av' f <*> rebuildBoundary av' b <*> k av a+ Stencil2 s1 s2 tp f b1 a1 b2 a2+ -> Stencil2 s1 s2 tp <$> rebuildFun (pure . IE) av' f <*> rebuildBoundary av' b1 <*> k av a1 <*> rebuildBoundary av' b2 <*> k av a2+ Aforeign repr ff afun as -> Aforeign repr ff afun <$> k av as+ -- Collect seq -> Collect <$> rebuildSeq k av seq+ where+ av' = reindexAvar av++{-# INLINEABLE rebuildAfun #-}+rebuildAfun+ :: (HasCallStack, Applicative f, SyntacticAcc fa)+ => RebuildAcc acc+ -> RebuildAvar f fa acc aenv aenv'+ -> PreOpenAfun acc aenv t+ -> f (PreOpenAfun acc aenv' t)+rebuildAfun k av (Abody b) = Abody <$> k av b+rebuildAfun k av (Alam lhs1 f)+ | Exists lhs2 <- rebuildLHS lhs1+ = Alam lhs2 <$> rebuildAfun k (shiftA' lhs1 lhs2 k av) f++rebuildAlet+ :: forall f fa acc aenv1 aenv1' aenv2 bndArrs arrs. (HasCallStack, Applicative f, SyntacticAcc fa)+ => RebuildAcc acc+ -> RebuildAvar f fa acc aenv1 aenv2+ -> ALeftHandSide bndArrs aenv1 aenv1'+ -> acc aenv1 bndArrs+ -> acc aenv1' arrs+ -> f (PreOpenAcc acc aenv2 arrs)+rebuildAlet k av lhs1 bind1 body1+ | Exists lhs2 <- rebuildLHS lhs1+ = Alet lhs2 <$> k av bind1 <*> k (shiftA' lhs1 lhs2 k av) body1++{-# INLINEABLE rebuildLHS #-}+rebuildLHS :: LeftHandSide s t aenv1 aenv1' -> Exists (LeftHandSide s t aenv2)+rebuildLHS (LeftHandSideWildcard r) = Exists $ LeftHandSideWildcard r+rebuildLHS (LeftHandSideSingle s) = Exists $ LeftHandSideSingle s+rebuildLHS (LeftHandSidePair as bs)+ | Exists as' <- rebuildLHS as+ , Exists bs' <- rebuildLHS bs+ = Exists $ LeftHandSidePair as' bs'++{-# INLINEABLE rebuildBoundary #-}+rebuildBoundary+ :: Applicative f+ => ReindexAvar f aenv aenv'+ -> Boundary aenv t+ -> f (Boundary aenv' t)+rebuildBoundary av bndy =+ case bndy of+ Clamp -> pure Clamp+ Mirror -> pure Mirror+ Wrap -> pure Wrap+ Constant v -> pure (Constant v)+ Function f -> Function <$> rebuildFun (pure . IE) av f++{--+{-# INLINEABLE rebuildSeq #-}+rebuildSeq+ :: (SyntacticAcc fa, Applicative f)+ => RebuildAcc acc+ -> RebuildAvar f fa acc aenv aenv'+ -> PreOpenSeq acc aenv senv t+ -> f (PreOpenSeq acc aenv' senv t)+rebuildSeq k v seq =+ case seq of+ Producer p s -> Producer <$> (rebuildP k v p) <*> (rebuildSeq k v s)+ Consumer c -> Consumer <$> (rebuildC k v c)+ Reify ix -> pure $ Reify ix++{-# INLINEABLE rebuildP #-}+rebuildP :: (SyntacticAcc fa, Applicative f)+ => RebuildAcc acc+ -> RebuildAvar f fa acc aenv aenv'+ -> Producer acc aenv senv a+ -> f (Producer acc aenv' senv a)+rebuildP k v p =+ case p of+ StreamIn arrs -> pure (StreamIn arrs)+ ToSeq sl slix acc -> ToSeq sl slix <$> k v acc+ MapSeq f x -> MapSeq <$> rebuildAfun k v f <*> pure x+ ChunkedMapSeq f x -> ChunkedMapSeq <$> rebuildAfun k v f <*> pure x+ ZipWithSeq f x y -> ZipWithSeq <$> rebuildAfun k v f <*> pure x <*> pure y+ ScanSeq f e x -> ScanSeq <$> rebuildFun (pure . IE) v f <*> rebuildOpenExp (pure . IE) v e <*> pure x++{-# INLINEABLE rebuildC #-}+rebuildC :: forall acc fa f aenv aenv' senv a. (SyntacticAcc fa, Applicative f)+ => RebuildAcc acc+ -> RebuildAvar f fa acc aenv aenv'+ -> Consumer acc aenv senv a+ -> f (Consumer acc aenv' senv a)+rebuildC k v c =+ case c of+ FoldSeq f e x -> FoldSeq <$> rebuildFun (pure . IE) v f <*> rebuildOpenExp (pure . IE) v e <*> pure x+ FoldSeqFlatten f acc x -> FoldSeqFlatten <$> rebuildAfun k v f <*> k v acc <*> pure x+ Stuple t -> Stuple <$> rebuildT t+ where+ rebuildT :: Atuple (Consumer acc aenv senv) t -> f (Atuple (Consumer acc aenv' senv) t)+ rebuildT NilAtup = pure NilAtup+ rebuildT (SnocAtup t s) = SnocAtup <$> (rebuildT t) <*> (rebuildC k v s)+--}++extractExpVars :: OpenExp env aenv a -> Maybe (ExpVars env a)+extractExpVars Nil = Just TupRunit+extractExpVars (Pair e1 e2) = TupRpair <$> extractExpVars e1 <*> extractExpVars e2+extractExpVars (Evar v) = Just $ TupRsingle v+extractExpVars _ = Nothing+
+ src/Data/Array/Accelerate/Trafo/Var.hs view
@@ -0,0 +1,79 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeOperators #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Trafo.Var+-- Copyright : [2012..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Trafo.Var+ where++import Data.Array.Accelerate.AST+import Data.Array.Accelerate.AST.Environment+import Data.Array.Accelerate.AST.Idx+import Data.Array.Accelerate.AST.LeftHandSide+import Data.Array.Accelerate.AST.Var+import Data.Array.Accelerate.Representation.Array+import Data.Array.Accelerate.Representation.Type+++data DeclareVars s t aenv where+ DeclareVars :: LeftHandSide s t env env'+ -> (env :> env')+ -> (forall env''. env' :> env'' -> Vars s env'' t)+ -> DeclareVars s t env++declareVars :: TupR s t -> DeclareVars s t env+declareVars TupRunit+ = DeclareVars LeftHandSideUnit weakenId $ const $ TupRunit+declareVars (TupRsingle s)+ = DeclareVars (LeftHandSideSingle s) (weakenSucc weakenId) $ \k -> TupRsingle $ Var s $ k >:> ZeroIdx+declareVars (TupRpair r1 r2)+ | DeclareVars lhs1 subst1 a1 <- declareVars r1+ , DeclareVars lhs2 subst2 a2 <- declareVars r2+ = DeclareVars (LeftHandSidePair lhs1 lhs2) (subst2 .> subst1) $ \k -> a1 (k .> subst2) `TupRpair` a2 k+++type InjectAcc acc = forall env t. PreOpenAcc acc env t -> acc env t+type ExtractAcc acc = forall env t. acc env t -> Maybe (PreOpenAcc acc env t)++avarIn :: InjectAcc acc+ -> ArrayVar aenv a+ -> acc aenv a+avarIn inject v@(Var ArrayR{} _) = inject (Avar v)++avarsIn :: forall acc aenv arrs.+ InjectAcc acc+ -> ArrayVars aenv arrs+ -> acc aenv arrs+avarsIn inject = go+ where+ go :: ArrayVars aenv t -> acc aenv t+ go TupRunit = inject Anil+ go (TupRsingle v) = avarIn inject v+ go (TupRpair a b) = inject (go a `Apair` go b)++avarsOut+ :: ExtractAcc acc+ -> PreOpenAcc acc aenv a+ -> Maybe (ArrayVars aenv a)+avarsOut extract = \case+ Anil -> Just $ TupRunit+ Avar v -> Just $ TupRsingle v+ Apair al ar+ | Just pl <- extract al+ , Just pr <- extract ar+ , Just as <- avarsOut extract pl+ , Just bs <- avarsOut extract pr+ -> Just (TupRpair as bs)+ _ -> Nothing+
+ src/Data/Array/Accelerate/Type.hs view
@@ -0,0 +1,520 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE RoleAnnotations #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE ViewPatterns #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Array.Accelerate.Type+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- Primitive scalar types supported by Accelerate+--+-- Integral types:+-- * Int+-- * Int8+-- * Int16+-- * Int32+-- * Int64+-- * Word+-- * Word8+-- * Word16+-- * Word32+-- * Word64+--+-- Floating types:+-- * Half+-- * Float+-- * Double+--+-- SIMD vector types of the above:+-- * Vec2+-- * Vec3+-- * Vec4+-- * Vec8+-- * Vec16+--+-- Note that 'Int' has the same bit width as in plain Haskell computations.+-- 'Float' and 'Double' represent IEEE single and double precision floating+-- point numbers, respectively.+--++module Data.Array.Accelerate.Type (++ Half(..), Float, Double,+ module Data.Int,+ module Data.Word,+ module Foreign.C.Types,+ module Data.Array.Accelerate.Type,++) where++import Data.Array.Accelerate.Orphans () -- Prim Half+import Data.Primitive.Vec++import Data.Bits+import Data.Int+import Data.Primitive.Types+import Data.Type.Equality+import Data.Word+import Foreign.C.Types+import Foreign.Storable ( Storable )+import Formatting+import Language.Haskell.TH.Extra+import Numeric.Half+import Text.Printf++import GHC.Prim+import GHC.TypeLits+++-- Scalar types+-- ------------++-- Reified dictionaries+--+data SingleDict a where+ SingleDict :: ( Eq a, Ord a, Show a, Storable a, Prim a )+ => SingleDict a++data IntegralDict a where+ IntegralDict :: ( Eq a, Ord a, Show a+ , Bounded a, Bits a, FiniteBits a, Integral a, Num a, Real a, Storable a )+ => IntegralDict a++data FloatingDict a where+ FloatingDict :: ( Eq a, Ord a, Show a+ , Floating a, Fractional a, Num a, Real a, RealFrac a, RealFloat a, Storable a )+ => FloatingDict a+++-- Scalar type representation+--++-- | Integral types supported in array computations.+--+data IntegralType a where+ TypeInt :: IntegralType Int+ TypeInt8 :: IntegralType Int8+ TypeInt16 :: IntegralType Int16+ TypeInt32 :: IntegralType Int32+ TypeInt64 :: IntegralType Int64+ TypeWord :: IntegralType Word+ TypeWord8 :: IntegralType Word8+ TypeWord16 :: IntegralType Word16+ TypeWord32 :: IntegralType Word32+ TypeWord64 :: IntegralType Word64++-- | Floating-point types supported in array computations.+--+data FloatingType a where+ TypeHalf :: FloatingType Half+ TypeFloat :: FloatingType Float+ TypeDouble :: FloatingType Double++-- | Numeric element types implement Num & Real+--+data NumType a where+ IntegralNumType :: IntegralType a -> NumType a+ FloatingNumType :: FloatingType a -> NumType a++-- | Bounded element types implement Bounded+--+data BoundedType a where+ IntegralBoundedType :: IntegralType a -> BoundedType a++-- | All scalar element types implement Eq & Ord+--+data ScalarType a where+ SingleScalarType :: SingleType a -> ScalarType a+ VectorScalarType :: VectorType (Vec n a) -> ScalarType (Vec n a)++data SingleType a where+ NumSingleType :: NumType a -> SingleType a++data VectorType a where+ VectorType :: KnownNat n => {-# UNPACK #-} !Int -> SingleType a -> VectorType (Vec n a)++instance Show (IntegralType a) where+ show TypeInt = "Int"+ show TypeInt8 = "Int8"+ show TypeInt16 = "Int16"+ show TypeInt32 = "Int32"+ show TypeInt64 = "Int64"+ show TypeWord = "Word"+ show TypeWord8 = "Word8"+ show TypeWord16 = "Word16"+ show TypeWord32 = "Word32"+ show TypeWord64 = "Word64"++instance Show (FloatingType a) where+ show TypeHalf = "Half"+ show TypeFloat = "Float"+ show TypeDouble = "Double"++instance Show (NumType a) where+ show (IntegralNumType ty) = show ty+ show (FloatingNumType ty) = show ty++instance Show (BoundedType a) where+ show (IntegralBoundedType ty) = show ty++instance Show (SingleType a) where+ show (NumSingleType ty) = show ty++instance Show (VectorType a) where+ show (VectorType n ty) = printf "<%d x %s>" n (show ty)++instance Show (ScalarType a) where+ show (SingleScalarType ty) = show ty+ show (VectorScalarType ty) = show ty++formatIntegralType :: Format r (IntegralType a -> r)+formatIntegralType = later $ \case+ TypeInt -> "Int"+ TypeInt8 -> "Int8"+ TypeInt16 -> "Int16"+ TypeInt32 -> "Int32"+ TypeInt64 -> "Int64"+ TypeWord -> "Word"+ TypeWord8 -> "Word8"+ TypeWord16 -> "Word16"+ TypeWord32 -> "Word32"+ TypeWord64 -> "Word64"++formatFloatingType :: Format r (FloatingType a -> r)+formatFloatingType = later $ \case+ TypeHalf -> "Half"+ TypeFloat -> "Float"+ TypeDouble -> "Double"++formatNumType :: Format r (NumType a -> r)+formatNumType = later $ \case+ IntegralNumType ty -> bformat formatIntegralType ty+ FloatingNumType ty -> bformat formatFloatingType ty++formatBoundedType :: Format r (BoundedType a -> r)+formatBoundedType = later $ \case+ IntegralBoundedType ty -> bformat formatIntegralType ty++formatSingleType :: Format r (SingleType a -> r)+formatSingleType = later $ \case+ NumSingleType ty -> bformat formatNumType ty++formatVectorType :: Format r (VectorType a -> r)+formatVectorType = later $ \case+ VectorType n ty -> bformat (angled (int % " x " % formatSingleType)) n ty++formatScalarType :: Format r (ScalarType a -> r)+formatScalarType = later $ \case+ SingleScalarType ty -> bformat formatSingleType ty+ VectorScalarType ty -> bformat formatVectorType ty+++-- | Querying Integral types+--+class (IsSingle a, IsNum a, IsBounded a) => IsIntegral a where+ integralType :: IntegralType a++-- | Querying Floating types+--+class (Floating a, IsSingle a, IsNum a) => IsFloating a where+ floatingType :: FloatingType a++-- | Querying Numeric types+--+class (Num a, IsSingle a) => IsNum a where+ numType :: NumType a++-- | Querying Bounded types+--+class IsBounded a where+ boundedType :: BoundedType a++-- | Querying single value types+--+class IsScalar a => IsSingle a where+ singleType :: SingleType a++-- | Querying all scalar types+--+class IsScalar a where+ scalarType :: ScalarType a+++integralDict :: IntegralType a -> IntegralDict a+integralDict TypeInt = IntegralDict+integralDict TypeInt8 = IntegralDict+integralDict TypeInt16 = IntegralDict+integralDict TypeInt32 = IntegralDict+integralDict TypeInt64 = IntegralDict+integralDict TypeWord = IntegralDict+integralDict TypeWord8 = IntegralDict+integralDict TypeWord16 = IntegralDict+integralDict TypeWord32 = IntegralDict+integralDict TypeWord64 = IntegralDict++floatingDict :: FloatingType a -> FloatingDict a+floatingDict TypeHalf = FloatingDict+floatingDict TypeFloat = FloatingDict+floatingDict TypeDouble = FloatingDict++singleDict :: SingleType a -> SingleDict a+singleDict = single+ where+ single :: SingleType a -> SingleDict a+ single (NumSingleType t) = num t++ num :: NumType a -> SingleDict a+ num (IntegralNumType t) = integral t+ num (FloatingNumType t) = floating t++ integral :: IntegralType a -> SingleDict a+ integral TypeInt = SingleDict+ integral TypeInt8 = SingleDict+ integral TypeInt16 = SingleDict+ integral TypeInt32 = SingleDict+ integral TypeInt64 = SingleDict+ integral TypeWord = SingleDict+ integral TypeWord8 = SingleDict+ integral TypeWord16 = SingleDict+ integral TypeWord32 = SingleDict+ integral TypeWord64 = SingleDict++ floating :: FloatingType a -> SingleDict a+ floating TypeHalf = SingleDict+ floating TypeFloat = SingleDict+ floating TypeDouble = SingleDict+++scalarTypeInt :: ScalarType Int+scalarTypeInt = SingleScalarType $ NumSingleType $ IntegralNumType TypeInt++scalarTypeWord :: ScalarType Word+scalarTypeWord = SingleScalarType $ NumSingleType $ IntegralNumType TypeWord++scalarTypeInt32 :: ScalarType Int32+scalarTypeInt32 = SingleScalarType $ NumSingleType $ IntegralNumType TypeInt32++scalarTypeWord8 :: ScalarType Word8+scalarTypeWord8 = SingleScalarType $ NumSingleType $ IntegralNumType TypeWord8++scalarTypeWord32 :: ScalarType Word32+scalarTypeWord32 = SingleScalarType $ NumSingleType $ IntegralNumType TypeWord32++rnfScalarType :: ScalarType t -> ()+rnfScalarType (SingleScalarType t) = rnfSingleType t+rnfScalarType (VectorScalarType t) = rnfVectorType t++rnfSingleType :: SingleType t -> ()+rnfSingleType (NumSingleType t) = rnfNumType t++rnfVectorType :: VectorType t -> ()+rnfVectorType (VectorType !_ t) = rnfSingleType t++rnfBoundedType :: BoundedType t -> ()+rnfBoundedType (IntegralBoundedType t) = rnfIntegralType t++rnfNumType :: NumType t -> ()+rnfNumType (IntegralNumType t) = rnfIntegralType t+rnfNumType (FloatingNumType t) = rnfFloatingType t++rnfIntegralType :: IntegralType t -> ()+rnfIntegralType TypeInt = ()+rnfIntegralType TypeInt8 = ()+rnfIntegralType TypeInt16 = ()+rnfIntegralType TypeInt32 = ()+rnfIntegralType TypeInt64 = ()+rnfIntegralType TypeWord = ()+rnfIntegralType TypeWord8 = ()+rnfIntegralType TypeWord16 = ()+rnfIntegralType TypeWord32 = ()+rnfIntegralType TypeWord64 = ()++rnfFloatingType :: FloatingType t -> ()+rnfFloatingType TypeHalf = ()+rnfFloatingType TypeFloat = ()+rnfFloatingType TypeDouble = ()+++liftScalar :: ScalarType t -> t -> CodeQ t+liftScalar (SingleScalarType t) = liftSingle t+liftScalar (VectorScalarType t) = liftVector t++liftSingle :: SingleType t -> t -> CodeQ t+liftSingle (NumSingleType t) = liftNum t++liftVector :: VectorType t -> t -> CodeQ t+liftVector VectorType{} = liftVec++liftNum :: NumType t -> t -> CodeQ t+liftNum (IntegralNumType t) = liftIntegral t+liftNum (FloatingNumType t) = liftFloating t++liftIntegral :: IntegralType t -> t -> CodeQ t+liftIntegral TypeInt x = [|| x ||]+liftIntegral TypeInt8 x = [|| x ||]+liftIntegral TypeInt16 x = [|| x ||]+liftIntegral TypeInt32 x = [|| x ||]+liftIntegral TypeInt64 x = [|| x ||]+liftIntegral TypeWord x = [|| x ||]+liftIntegral TypeWord8 x = [|| x ||]+liftIntegral TypeWord16 x = [|| x ||]+liftIntegral TypeWord32 x = [|| x ||]+liftIntegral TypeWord64 x = [|| x ||]++liftFloating :: FloatingType t -> t -> CodeQ t+liftFloating TypeHalf x = [|| x ||]+liftFloating TypeFloat x = [|| x ||]+liftFloating TypeDouble x = [|| x ||]+++liftScalarType :: ScalarType t -> CodeQ (ScalarType t)+liftScalarType (SingleScalarType t) = [|| SingleScalarType $$(liftSingleType t) ||]+liftScalarType (VectorScalarType t) = [|| VectorScalarType $$(liftVectorType t) ||]++liftSingleType :: SingleType t -> CodeQ (SingleType t)+liftSingleType (NumSingleType t) = [|| NumSingleType $$(liftNumType t) ||]++liftVectorType :: VectorType t -> CodeQ (VectorType t)+liftVectorType (VectorType n t) = [|| VectorType n $$(liftSingleType t) ||]++liftNumType :: NumType t -> CodeQ (NumType t)+liftNumType (IntegralNumType t) = [|| IntegralNumType $$(liftIntegralType t) ||]+liftNumType (FloatingNumType t) = [|| FloatingNumType $$(liftFloatingType t) ||]++liftBoundedType :: BoundedType t -> CodeQ (BoundedType t)+liftBoundedType (IntegralBoundedType t) = [|| IntegralBoundedType $$(liftIntegralType t) ||]++liftIntegralType :: IntegralType t -> CodeQ (IntegralType t)+liftIntegralType TypeInt = [|| TypeInt ||]+liftIntegralType TypeInt8 = [|| TypeInt8 ||]+liftIntegralType TypeInt16 = [|| TypeInt16 ||]+liftIntegralType TypeInt32 = [|| TypeInt32 ||]+liftIntegralType TypeInt64 = [|| TypeInt64 ||]+liftIntegralType TypeWord = [|| TypeWord ||]+liftIntegralType TypeWord8 = [|| TypeWord8 ||]+liftIntegralType TypeWord16 = [|| TypeWord16 ||]+liftIntegralType TypeWord32 = [|| TypeWord32 ||]+liftIntegralType TypeWord64 = [|| TypeWord64 ||]++liftFloatingType :: FloatingType t -> CodeQ (FloatingType t)+liftFloatingType TypeHalf = [|| TypeHalf ||]+liftFloatingType TypeFloat = [|| TypeFloat ||]+liftFloatingType TypeDouble = [|| TypeDouble ||]+++-- Type-level bit sizes+-- --------------------++-- | Constraint that values of these two types have the same bit width+--+type BitSizeEq a b = (BitSize a == BitSize b) ~ 'True+type family BitSize a :: Nat+++-- Instances+-- ---------+--+-- Generate instances for the IsX classes. It would be preferable to do this+-- automatically based on the members of the IntegralType (etc.) representations+-- (see for example FromIntegral.hs) but TH phase restrictions would require us+-- to split this into a separate module.+--++runQ $ do+ let+ bits :: FiniteBits b => b -> Integer+ bits = toInteger . finiteBitSize++ integralTypes :: [(Name, Integer)]+ integralTypes =+ [ (''Int, bits (undefined::Int))+ , (''Int8, 8)+ , (''Int16, 16)+ , (''Int32, 32)+ , (''Int64, 64)+ , (''Word, bits (undefined::Word))+ , (''Word8, 8)+ , (''Word16, 16)+ , (''Word32, 32)+ , (''Word64, 64)+ ]++ floatingTypes :: [(Name, Integer)]+ floatingTypes =+ [ (''Half, 16)+ , (''Float, 32)+ , (''Double, 64)+ ]++ vectorTypes :: [(Name, Integer)]+ vectorTypes = integralTypes ++ floatingTypes++ mkIntegral :: Name -> Integer -> Q [Dec]+ mkIntegral t n =+ [d| instance IsIntegral $(conT t) where+ integralType = $(conE (mkName ("Type" ++ nameBase t)))++ instance IsNum $(conT t) where+ numType = IntegralNumType integralType++ instance IsBounded $(conT t) where+ boundedType = IntegralBoundedType integralType++ instance IsSingle $(conT t) where+ singleType = NumSingleType numType++ instance IsScalar $(conT t) where+ scalarType = SingleScalarType singleType++ type instance BitSize $(conT t) = $(litT (numTyLit n))+ |]++ mkFloating :: Name -> Integer -> Q [Dec]+ mkFloating t n =+ [d| instance IsFloating $(conT t) where+ floatingType = $(conE (mkName ("Type" ++ nameBase t)))++ instance IsNum $(conT t) where+ numType = FloatingNumType floatingType++ instance IsSingle $(conT t) where+ singleType = NumSingleType numType++ instance IsScalar $(conT t) where+ scalarType = SingleScalarType singleType++ type instance BitSize $(conT t) = $(litT (numTyLit n))+ |]++ mkVector :: Name -> Integer -> Q [Dec]+ mkVector t n =+ [d| instance KnownNat n => IsScalar (Vec n $(conT t)) where+ scalarType = VectorScalarType (VectorType (fromIntegral (natVal' (proxy# :: Proxy# n))) singleType)++ type instance BitSize (Vec w $(conT t)) = w GHC.TypeLits.* $(litT (numTyLit n))+ |]+ --+ is <- mapM (uncurry mkIntegral) integralTypes+ fs <- mapM (uncurry mkFloating) floatingTypes+ vs <- mapM (uncurry mkVector) vectorTypes+ --+ return (concat is ++ concat fs ++ concat vs)+
+ src/Data/Array/Accelerate/Unsafe.hs view
@@ -0,0 +1,52 @@+{-# LANGUAGE MonoLocalBinds #-}+{-# LANGUAGE FlexibleContexts #-}+-- |+-- Module : Data.Array.Accelerate.Unsafe+-- Copyright : [2009..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- Operations which may be unsafe. Use with care.+--+-- @since 1.2.0.0+--++module Data.Array.Accelerate.Unsafe (++ -- ** Unsafe operations+ Coerce, coerce,+ undef,++) where++import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Sugar.Elt+++-- | The function 'coerce' allows you to convert a value between any two types+-- whose underlying representations have the same bit size at each component.+--+-- For example:+--+-- > coerce (x :: Exp Double) :: Exp Word64+-- > coerce (x :: Exp (Int64,Float)) :: Exp (Complex Float, Word32)+--+-- Furthermore, as we typically declare newtype wrappers similarly to:+--+-- > type instance EltR (Sum a) = ((), EltR a)+--+-- This can be used instead of the newtype constructor, to go from the newtype's+-- abstract type to the concrete type by dropping the extra @()@ from the+-- representation, and vice-versa.+--+-- The type class 'Coerce' assures that there is a coercion between the two+-- types.+--+-- @since 1.2.0.0+--+coerce :: Coerce (EltR a) (EltR b) => Exp a -> Exp b+coerce = mkCoerce+
+ src/Data/Atomic.hs view
@@ -0,0 +1,101 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE UnboxedTuples #-}+{-# OPTIONS_GHC -fobject-code #-}+-- |+-- Module : Data.Atomic+-- Copyright : [2016..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--+-- Atomic integer values. All operations are thread safe.+--++module Data.Atomic (++ Atomic(..),+ read, write, add, and, subtract,++) where++import Data.Int+import Language.Haskell.TH.Syntax++import GHC.Ptr+import GHC.Base+++-- | A mutable atomic integer+--+newtype Atomic = Atomic ( Ptr Int64 )++-- -- | Create a new atomic variable initialised to the given value+-- --+-- -- TLM: This is not correct because we need to keep the MutableByteArray#+-- -- around so that it does not get GC'ed. This would have been stored as+-- -- the ForeignPtrContents. Since we don't use this function at the+-- -- moment (all of the atomics we care about are defined in C code) we+-- -- just drop this function for now.+-- --+-- new :: Int64 -> IO Atomic+-- new v = do+-- a <- IO $ \s -> case newPinnedByteArray# 8# s of+-- (# s', mbarr# #) -> (# s', Atomic (Ptr (byteArrayContents# (unsafeCoerce# mbarr#))) #)+-- write a v+-- return a++-- SEE: [HLS and GHC IDE]+--+#ifndef __GHCIDE__++-- | Get the current value.+--+foreign import ccall unsafe "atomic_read_64" read :: Atomic -> IO Int64++-- | Set the atomic to the given value.+--+foreign import ccall unsafe "atomic_write_64" write :: Atomic -> Int64 -> IO ()++-- | Increase the atomic by the given amount. Returns the old value.+--+foreign import ccall unsafe "atomic_fetch_and_add_64" add :: Atomic -> Int64 -> IO Int64++-- | Bitwise AND the atomic with the given value. Return the old value.+--+foreign import ccall unsafe "atomic_fetch_and_and_64" and :: Atomic -> Int64 -> IO Int64++-- | Decrement the atomic value by the given amount. Return the old value.+--+foreign import ccall unsafe "atomic_fetch_and_sub_64" subtract :: Atomic -> Int64 -> IO Int64++#else++read :: Atomic -> IO Int64+read = undefined++write :: Atomic -> Int64 -> IO ()+write = undefined++add :: Atomic -> Int64 -> IO Int64+add = undefined++and :: Atomic -> Int64 -> IO Int64+and = undefined++subtract :: Atomic -> Int64 -> IO Int64+subtract = undefined++#endif++-- SEE: [linking to .c files]+--+runQ $ do+ addForeignFilePath LangC "cbits/atomic.c"+ return []+
+ src/Data/BitSet.hs view
@@ -0,0 +1,163 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.BitSet+-- Copyright : [2019..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.BitSet where++import Data.Bits+-- foldl' is exported by Prelude from GHC 9.10+import Prelude hiding ( foldl, foldr, foldl' )+import qualified Data.List as List++import GHC.Exts ( IsList, build )+import qualified GHC.Exts as Exts+++-- | A space-efficient implementation of a set data structure for+-- enumerated data types.+--+newtype BitSet c a = BitSet { getBits :: c }+ deriving Eq++instance (Enum a, Show a, Bits c, Num c) => Show (BitSet c a) where+ showsPrec p bs+ = showParen (p > 10)+ $ showString "fromList " . shows (toList bs)++instance (Enum a, Bits c) => Semigroup (BitSet c a) where+ (<>) = union++instance (Enum a, Bits c, Num c) => Monoid (BitSet c a) where+ mempty = empty++instance (Enum a, Bits c, Num c) => IsList (BitSet c a) where+ type Item (BitSet c a) = a+ fromList = fromList+ toList = toList+ {-# INLINE fromList #-}+ {-# INLINE toList #-}++-- | Is the bit set empty?+--+{-# INLINE null #-}+null :: (Eq c, Num c) => BitSet c a -> Bool+null (BitSet bits) = bits == 0++-- | The number of elements in the bit set.+--+{-# INLINE size #-}+size :: Bits c => BitSet c a -> Int+size (BitSet bits) = popCount bits++-- | Ask whether the item is in the bit set.+--+{-# INLINE member #-}+member :: (Enum a , Bits c) => a -> BitSet c a -> Bool+member x (BitSet bits) = bits `testBit` fromEnum x++-- | The empty bit set.+--+{-# INLINE empty #-}+empty :: (Enum a, Bits c, Num c) => BitSet c a+empty = BitSet 0++-- | Create a singleton set.+--+{-# INLINE singleton #-}+singleton :: (Enum a, Bits c, Num c) => a -> BitSet c a+singleton x = BitSet $! bit (fromEnum x)++-- | Insert an item into the bit set.+--+{-# INLINE insert #-}+insert :: (Enum a, Bits c) => a -> BitSet c a -> BitSet c a+insert x (BitSet bits) = BitSet $! bits `setBit` fromEnum x++-- | Delete an item from the bit set.+{-# INLINE delete #-}+delete :: (Enum a, Bits c) => a -> BitSet c a -> BitSet c a+delete x (BitSet bits ) = BitSet $! bits `clearBit` fromEnum x++-- | The union of two bit sets.+--+{-# INLINE union #-}+union :: Bits c => BitSet c a -> BitSet c a -> BitSet c a+union (BitSet bits1) (BitSet bits2) = BitSet $! bits1 .|. bits2++-- | Difference of two bit sets.+--+{-# INLINE difference #-}+difference :: Bits c => BitSet c a -> BitSet c a -> BitSet c a+difference (BitSet bits1) (BitSet bits2) = BitSet $! bits1 .&. complement bits2++-- | See 'difference'.+--+infix 5 \\ -- comment to fool cpp: https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/phases.html#cpp-and-string-gaps+{-# INLINE (\\) #-}+(\\) :: Bits c => BitSet c a -> BitSet c a -> BitSet c a+(\\) = difference++-- | The intersection of two bit sets.+--+{-# INLINE intersection #-}+intersection :: Bits c => BitSet c a -> BitSet c a -> BitSet c a+intersection (BitSet bits1) (BitSet bits2) = BitSet $! bits1 .&. bits2++-- | Transform this bit set by applying a function to every value.+-- Resulting bit set may be smaller then the original.+--+{-# INLINE map #-}+map :: (Enum a, Enum b, Bits c, Num c) => (a -> b) -> BitSet c a -> BitSet c b+map f = foldl' (\bs a -> f a `insert` bs) empty++-- | Reduce this bit set by applying a binary function to all elements,+-- using the given starting value. Each application of the operator is+-- evaluated before before using the result in the next application. This+-- function is strict in the starting value.+--+{-# INLINE foldl' #-}+foldl' :: (Enum a, Bits c) => (b -> a -> b) -> b -> BitSet c a -> b+foldl' f z (BitSet bits) = go z (popCount bits) 0+ where+ go !acc 0 !_ = acc+ go !acc !n !b = if bits `testBit` b+ then go (f acc $ toEnum b) (pred n) (succ b)+ else go acc n (succ b)++-- | Reduce this bit set by applying a binary function to all elements,+-- using the given starting value.+--+{-# INLINE foldr #-}+foldr :: (Enum a, Bits c) => (a -> b -> b) -> b -> BitSet c a -> b+foldr f z (BitSet bits) = go (popCount bits) 0+ where+ go 0 !_ = z+ go !n !b = if bits `testBit` b+ then toEnum b `f` go (pred n) (succ b)+ else go n (succ b)++-- | Convert this bit set set to a list of elements.+--+{-# INLINE [0] toList #-}+toList :: (Enum a, Bits c, Num c) => BitSet c a -> [a]+toList bs = build (\k z -> foldr k z bs)++-- | Make a bit set from a list of elements.+--+{-# INLINE [0] fromList #-}+fromList :: (Enum a, Bits c, Num c) => [a] -> BitSet c a+fromList xs = BitSet $! List.foldl' (\i x -> i `setBit` fromEnum x) 0 xs++{-# RULES+"fromList/toList" forall bs. fromList (toList bs) = bs+ #-}+
+ src/Data/Primitive/Vec.hs view
@@ -0,0 +1,289 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE RoleAnnotations #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE ViewPatterns #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module : Data.Primitive.Vec+-- Copyright : [2008..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Primitive.Vec (++ -- * SIMD vector types+ Vec(..),+ Vec2, pattern Vec2,+ Vec3, pattern Vec3,+ Vec4, pattern Vec4,+ Vec8, pattern Vec8,+ Vec16, pattern Vec16,++ listOfVec,+ liftVec,++) where++import Control.Monad.ST+import Data.Primitive.ByteArray+import Data.Primitive.Types+import Language.Haskell.TH.Extra+import Prettyprinter++import GHC.Base ( isTrue# )+import GHC.Int+import GHC.Prim+import GHC.TypeLits+import GHC.Word+++-- Note: [Representing SIMD vector types]+--+-- A simple polymorphic representation of SIMD types such as the following:+--+-- > data Vec2 a = Vec2 !a !a+--+-- is not able to unpack the values into the constructor, meaning that+-- 'Vec2' is storing pointers to (strict) values on the heap, which is+-- a very inefficient representation.+--+-- We might try defining a data family instead so that we can get efficient+-- unboxed representations, and even make use of the unlifted SIMD types GHC+-- knows about:+--+-- > data family Vec2 a :: *+-- > data instance Vec2 Float = Vec2_Float Float# Float# -- reasonable+-- > data instance Vec2 Double = Vec2_Double DoubleX2# -- built in!+--+-- However, this runs into the problem that GHC stores all values as word sized+-- entities:+--+-- > data instance Vec2 Int = Vec2_Int Int# Int#+-- > data instance Vec2 Int8 = Vec2_Int8 Int8# Int8# -- Int8# does not exist; requires a full Int#+--+-- which, again, is very memory inefficient.+--+-- So, as a last resort, we'll just use a ByteArray# to ensure an efficient+-- packed representation.+--+-- One inefficiency of this approach is that the byte array does track its size,+-- which redundant for our use case (derivable from type level information).+--+data Vec (n :: Nat) a = Vec ByteArray#++type role Vec nominal representational++instance (Show a, Prim a, KnownNat n) => Show (Vec n a) where+ show = vec . listOfVec+ where+ vec :: [a] -> String+ vec = show+ . group . encloseSep (flatAlt "< " "<") (flatAlt " >" ">") ", "+ . map viaShow++listOfVec :: forall a n. (Prim a, KnownNat n) => Vec n a -> [a]+listOfVec (Vec ba#) = go 0#+ where+ go :: Int# -> [a]+ go i# | isTrue# (i# <# n#) = indexByteArray# ba# i# : go (i# +# 1#)+ | otherwise = []++ !(I# n#) = fromIntegral (natVal' (proxy# :: Proxy# n))++instance Eq (Vec n a) where+ Vec ba1# == Vec ba2# = ByteArray ba1# == ByteArray ba2#++-- Type synonyms for common SIMD vector types+--+-- Note that non-power-of-two sized SIMD vectors are a bit dubious, and+-- special care must be taken in the code generator. For example, LLVM will+-- treat a Vec3 with alignment of _4_, meaning that reads and writes will+-- be (without further action) incorrect.+--+type Vec2 a = Vec 2 a+type Vec3 a = Vec 3 a+type Vec4 a = Vec 4 a+type Vec8 a = Vec 8 a+type Vec16 a = Vec 16 a++pattern Vec2 :: Prim a => a -> a -> Vec2 a+pattern Vec2 a b <- (unpackVec2 -> (a,b))+ where Vec2 = packVec2+{-# COMPLETE Vec2 #-}++pattern Vec3 :: Prim a => a -> a -> a -> Vec3 a+pattern Vec3 a b c <- (unpackVec3 -> (a,b,c))+ where Vec3 = packVec3+{-# COMPLETE Vec3 #-}++pattern Vec4 :: Prim a => a -> a -> a -> a -> Vec4 a+pattern Vec4 a b c d <- (unpackVec4 -> (a,b,c,d))+ where Vec4 = packVec4+{-# COMPLETE Vec4 #-}++pattern Vec8 :: Prim a => a -> a -> a -> a -> a -> a -> a -> a -> Vec8 a+pattern Vec8 a b c d e f g h <- (unpackVec8 -> (a,b,c,d,e,f,g,h))+ where Vec8 = packVec8+{-# COMPLETE Vec8 #-}++pattern Vec16 :: Prim a => a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> Vec16 a+pattern Vec16 a b c d e f g h i j k l m n o p <- (unpackVec16 -> (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p))+ where Vec16 = packVec16+{-# COMPLETE Vec16 #-}++unpackVec2 :: Prim a => Vec2 a -> (a,a)+unpackVec2 (Vec ba#) =+ ( indexByteArray# ba# 0#+ , indexByteArray# ba# 1#+ )++unpackVec3 :: Prim a => Vec3 a -> (a,a,a)+unpackVec3 (Vec ba#) =+ ( indexByteArray# ba# 0#+ , indexByteArray# ba# 1#+ , indexByteArray# ba# 2#+ )++unpackVec4 :: Prim a => Vec4 a -> (a,a,a,a)+unpackVec4 (Vec ba#) =+ ( indexByteArray# ba# 0#+ , indexByteArray# ba# 1#+ , indexByteArray# ba# 2#+ , indexByteArray# ba# 3#+ )++unpackVec8 :: Prim a => Vec8 a -> (a,a,a,a,a,a,a,a)+unpackVec8 (Vec ba#) =+ ( indexByteArray# ba# 0#+ , indexByteArray# ba# 1#+ , indexByteArray# ba# 2#+ , indexByteArray# ba# 3#+ , indexByteArray# ba# 4#+ , indexByteArray# ba# 5#+ , indexByteArray# ba# 6#+ , indexByteArray# ba# 7#+ )++unpackVec16 :: Prim a => Vec16 a -> (a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a)+unpackVec16 (Vec ba#) =+ ( indexByteArray# ba# 0#+ , indexByteArray# ba# 1#+ , indexByteArray# ba# 2#+ , indexByteArray# ba# 3#+ , indexByteArray# ba# 4#+ , indexByteArray# ba# 5#+ , indexByteArray# ba# 6#+ , indexByteArray# ba# 7#+ , indexByteArray# ba# 8#+ , indexByteArray# ba# 9#+ , indexByteArray# ba# 10#+ , indexByteArray# ba# 11#+ , indexByteArray# ba# 12#+ , indexByteArray# ba# 13#+ , indexByteArray# ba# 14#+ , indexByteArray# ba# 15#+ )++packVec2 :: Prim a => a -> a -> Vec2 a+packVec2 a b = runST $ do+ mba <- newByteArray (2 * sizeOf a)+ writeByteArray mba 0 a+ writeByteArray mba 1 b+ ByteArray ba# <- unsafeFreezeByteArray mba+ return $! Vec ba#++packVec3 :: Prim a => a -> a -> a -> Vec3 a+packVec3 a b c = runST $ do+ mba <- newByteArray (3 * sizeOf a)+ writeByteArray mba 0 a+ writeByteArray mba 1 b+ writeByteArray mba 2 c+ ByteArray ba# <- unsafeFreezeByteArray mba+ return $! Vec ba#++packVec4 :: Prim a => a -> a -> a -> a -> Vec4 a+packVec4 a b c d = runST $ do+ mba <- newByteArray (4 * sizeOf a)+ writeByteArray mba 0 a+ writeByteArray mba 1 b+ writeByteArray mba 2 c+ writeByteArray mba 3 d+ ByteArray ba# <- unsafeFreezeByteArray mba+ return $! Vec ba#++packVec8 :: Prim a => a -> a -> a -> a -> a -> a -> a -> a -> Vec8 a+packVec8 a b c d e f g h = runST $ do+ mba <- newByteArray (8 * sizeOf a)+ writeByteArray mba 0 a+ writeByteArray mba 1 b+ writeByteArray mba 2 c+ writeByteArray mba 3 d+ writeByteArray mba 4 e+ writeByteArray mba 5 f+ writeByteArray mba 6 g+ writeByteArray mba 7 h+ ByteArray ba# <- unsafeFreezeByteArray mba+ return $! Vec ba#++packVec16 :: Prim a => a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> Vec16 a+packVec16 a b c d e f g h i j k l m n o p = runST $ do+ mba <- newByteArray (16 * sizeOf a)+ writeByteArray mba 0 a+ writeByteArray mba 1 b+ writeByteArray mba 2 c+ writeByteArray mba 3 d+ writeByteArray mba 4 e+ writeByteArray mba 5 f+ writeByteArray mba 6 g+ writeByteArray mba 7 h+ writeByteArray mba 8 i+ writeByteArray mba 9 j+ writeByteArray mba 10 k+ writeByteArray mba 11 l+ writeByteArray mba 12 m+ writeByteArray mba 13 n+ writeByteArray mba 14 o+ writeByteArray mba 15 p+ ByteArray ba# <- unsafeFreezeByteArray mba+ return $! Vec ba#++-- O(n) at runtime to copy from the Addr# to the ByteArray#. We should be able+-- to do this without copying, but I don't think the definition of ByteArray# is+-- exported (or it is deeply magical).+--+liftVec :: Vec n a -> CodeQ (Vec n a)+liftVec (Vec ba#)+ = unsafeCodeCoerce+ [| runST $ \s ->+ case newByteArray# $(liftInt# n#) s of { (# s1, mba# #) ->+ case copyAddrToByteArray# $(litE (StringPrimL bytes)) mba# 0# $(liftInt# n#) s1 of { s2 ->+ case unsafeFreezeByteArray# mba# s2 of { (# s3, ba'# #) ->+ (# s3, Vec ba'# #)+ }}}+ |]+ where+ bytes :: [Word8]+ bytes = go 0#+ where+ go i# | isTrue# (i# <# n#) = W8# (indexWord8Array# ba# i#) : go (i# +# 1#)+ | otherwise = []++ n# = sizeofByteArray# ba#++ -- XXX: Typed TH does not support unlifted types+ --+ liftInt# :: Int# -> ExpQ+ liftInt# i# = litE (IntPrimL (toInteger (I# i#)))+
+ src/Language/Haskell/TH/Extra.hs view
@@ -0,0 +1,92 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+-- |+-- Module : Language.Haskell.TH.Extra+-- Copyright : [2019..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Language.Haskell.TH.Extra (++ module Language.Haskell.TH,+ module Language.Haskell.TH.Extra,++) where++#if MIN_VERSION_template_haskell(2,17,0)+import Language.Haskell.TH hiding ( plainInvisTV, tupP, tupE )+#else+import Language.Haskell.TH hiding ( TyVarBndr, tupP, tupE )+import Language.Haskell.TH.Syntax ( unTypeQ, unsafeTExpCoerce )+#if MIN_VERSION_template_haskell(2,16,0)+import GHC.Exts ( RuntimeRep, TYPE )+#endif+#endif+import qualified Language.Haskell.TH as TH+++tupT :: [TypeQ] -> TypeQ+tupT [t] = t+tupT tup =+ let n = length tup+ in foldl (\ts t -> [t| $ts $t |]) (tupleT n) tup++tupP :: [PatQ] -> PatQ+tupP [p] = p+tupP ps = TH.tupP ps++tupE :: [ExpQ] -> ExpQ+tupE [t] = t+tupE ts = TH.tupE ts+++#if MIN_VERSION_template_haskell(2,17,0)++tyVarBndrName :: TyVarBndr flag -> Name+tyVarBndrName (PlainTV n _) = n+tyVarBndrName (KindedTV n _ _) = n++plainInvisTV :: Name -> Specificity -> TyVarBndr Specificity+plainInvisTV = PlainTV++#else++type CodeQ a = Q (TExp a)++type TyVarBndr flag = TH.TyVarBndr++data Specificity = SpecifiedSpec | InferredSpec++specifiedSpec :: Specificity+specifiedSpec = SpecifiedSpec++tyVarBndrName :: TyVarBndr flag -> Name+tyVarBndrName (PlainTV n) = n+tyVarBndrName (KindedTV n _) = n++plainInvisTV :: Name -> Specificity -> TyVarBndr Specificity+plainInvisTV n _ = PlainTV n++#if MIN_VERSION_template_haskell(2,16,0)+unsafeCodeCoerce :: forall (r :: RuntimeRep) (a :: TYPE r). Q Exp -> Q (TExp a)+#else+unsafeCodeCoerce :: Q Exp -> Q (TExp a)+#endif+unsafeCodeCoerce = unsafeTExpCoerce++#if MIN_VERSION_template_haskell(2,16,0)+unTypeCode :: forall (r :: RuntimeRep) (a :: TYPE r). Q (TExp a) -> Q Exp+#else+unTypeCode :: Q (TExp a) -> Q Exp+#endif+unTypeCode = unTypeQ++#endif+
+ test/doctest/Main.hs view
@@ -0,0 +1,23 @@+-- |+-- Module : Main+-- Copyright : [2017..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Main where++import Build_doctests ( flags, pkgs, module_sources )+import Data.Foldable ( traverse_ )+import Test.DocTest++main :: IO ()+main = do+ traverse_ putStrLn args+ doctest args+ where+ args = flags ++ pkgs ++ module_sources+
+ test/nofib/Main.hs view
@@ -0,0 +1,24 @@+-- |+-- Module : nofib-interpreter+-- Copyright : [2017..2020] The Accelerate Team+-- License : BSD3+--+-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability : experimental+-- Portability : non-portable (GHC extensions)+--++module Main where++import Data.Array.Accelerate.Test.NoFib+import Data.Array.Accelerate.Interpreter++import System.Environment+import Test.Tasty++main :: IO ()+main = do+ setEnv "TASTY_INTERPRETER" "True"+ setEnv "TASTY_HEDGEHOG_TESTS" "50"+ nofib runN (testGroup "runQ" [])+